EMAN2
dm4io.cpp
Go to the documentation of this file.
1/*
2 * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
3 * Copyright (c) 2000-2006 Baylor College of Medicine
4 *
5 * This software is issued under a joint BSD/GNU license. You may use the
6 * source code in this file under either license. However, note that the
7 * complete EMAN2 and SPARX software packages have some GPL dependencies,
8 * so you are responsible for compliance with the licenses of these packages
9 * if you opt to use BSD licensing. The warranty disclaimer below holds
10 * in either instance.
11 *
12 * This complete copyright notice must be included in any revised version of the
13 * source code. Additional authorship citations may be added, but existing
14 * author citations must be preserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * */
31
32#include "dm4io.h"
33#include "portable_fileio.h"
34#include "geometry.h"
35
36using namespace EMAN;
37using namespace EMAN::GatanDM4;
38
39const char *TagTable::IMAGE_WIDTH_TAG = "Dimensions #0";
40const char *TagTable::IMAGE_HEIGHT_TAG = "Dimensions #1";
41const char *TagTable::IMAGE_NIMG_TAG = "Dimensions #2";
42const char *TagTable::IMAGE_DATATYPE_TAG = "DataType";
43const char *TagTable::IMAGE_THUMB_INDEX_TAG = "ImageIndex";
44
45
46TagTable::TagTable()
47 : img_index(0), is_big_endian(true), img_counted(1), num_images_found(0)
48{
49}
50
52{
53 for (unsigned int i = 0; i < data_list.size(); i++) {
54 if (data_list[i]) {
55 delete[]data_list[i];
56 data_list[i] = 0;
57 }
58 }
59}
60
61void TagTable::add(const string & name, const string & value)
62{
63 const char *value_str = value.c_str();
64
65 if (name == IMAGE_WIDTH_TAG) {
66 x_list.push_back(atoi(value_str));
67 }
68 else if (name == IMAGE_HEIGHT_TAG) {
69 y_list.push_back(atoi(value_str));
70 }
71 else if (name == IMAGE_DATATYPE_TAG) {
72 datatype_list.push_back(atoi(value_str));
73 }
74 else if (name == IMAGE_THUMB_INDEX_TAG) {
75 set_thumb_index(atoi(value_str));
76 }
77 else if(name == IMAGE_NIMG_TAG){
78 img_counted=atoi(value_str);
79 }
80 else {
81 tags[name] = value;
82 }
83}
84
85void TagTable::add_data(char *data)
86{
87 if (!data) {
88 throw NullPointerException("DM4 data is NULL");
89 }
90 else {
91 data_list.push_back(data);
92 }
93}
94
95string TagTable::get_string(const string & name)
96{
97 return tags[name];
98}
99
100int TagTable::get_int(const string & name)
101{
102 return atoi(tags[name].c_str());
103}
104
105float TagTable::get_float(const string & name)
106{
107 return static_cast < float >(atof(tags[name].c_str()));
108}
109
110double TagTable::get_double(const string & name)
111{
112 return atof(tags[name].c_str());
113}
114
115void TagTable::dump() const
116{
117 map < string, string >::const_iterator p;
118
119 for (p = tags.begin(); p != tags.end(); p++) {
120// LOGDEBUG(" %s: %s", (*p).first.c_str(), (*p).second.c_str());
121 printf(" %s: %s\n", (*p).first.c_str(), (*p).second.c_str());
122 }
123}
124
126{
127 return x_list[img_index];
128}
129
131{
132 return img_counted;
133}
134
136{
137 return y_list[img_index];
138}
139
141{
142 return datatype_list[img_index];
143}
144
146{
147 return data_list[img_index];
148}
149
151{
152 if (i != 0 && i != 1) {
153 throw OutofRangeException(0, 1, i, "image index");
154 }
155 else {
156 if (i == 0) {
157 img_index = 1;
158 }
159 else {
160 img_index = 0;
161 }
162 }
163}
164
166{
167 return num_images_found;
168}
169
171{
172 num_images_found = num_found;
173}
174
176
177TagData::TagData(FILE * data_file, TagTable * table, const string & tagname)
178 : in(data_file), tagtable(table), name(tagname), tag_type(UNKNOWN)
179{
180}
181
183{
184}
185
186string TagData::read_native(bool is_value_stored)
187{
188 size_t sz = typesize();
189 size_t nr;
190 char val_str[32];
191
192 if (tag_type == SHORT) {
193 short val = 0;
194 nr = fread(&val, sz, 1, in); nr++;
196 sprintf(val_str, "%d", val);
197 }
198 else if (tag_type == USHORT) {
199 unsigned short val = 0;
200 nr = fread(&val, sz, 1, in); nr++;
202 sprintf(val_str, "%d", val);
203 }
204 else if (tag_type == INT) {
205 int val = 0;
206 nr = fread(&val, sz, 1, in); nr++;
208 sprintf(val_str, "%d", val);
209 }
210 else if (tag_type == CHAR || tag_type == OCTET) {
211 char val = 0;
212 nr = fread(&val, sz, 1, in); nr++;
213 sprintf(val_str, "%d", val);
214 }
215 else if (tag_type == BOOLEAN) {
216 bool val = false;
217 nr = fread(&val, sz, 1, in); nr++;
219 sprintf(val_str, "%d", val);
220 }
221 else if (tag_type == UINT) {
222 unsigned int val = 0;
223 nr = fread(&val, sz, 1, in); nr++;
225 sprintf(val_str, "%u", (int) val);
226 }
227 else if (tag_type == FLOAT) {
228 float val = 0;
229 nr = fread(&val, sz, 1, in); nr++;
231 sprintf(val_str, "%f", val);
232 }
233 else if (tag_type == DOUBLE) {
234 double val = 0;
235 nr = fread(&val, sz, 1, in); nr++;
237 sprintf(val_str, "%10e", val);
238 }
239 else if (tag_type == OCTEU) {
240 long long val = 0;
241 nr = fread(&val, sz, 1, in); nr++;
243 sprintf(val_str, "%lld", val);
244 }
245 else if (tag_type == OCTEV) {
246 unsigned long long val = 0;
247 nr = fread(&val, sz, 1, in); nr++;
249 sprintf(val_str, "%lld", val);
250 }
251 else {
252 LOGERR("invalid tag type: '%lld'", tag_type);
253 exit(1);
254 }
255
256 if (is_value_stored) {
257 tagtable->add(name, val_str);
258 }
259
260 LOGVAR("value = '%s'", val_str);
261
262 return string(val_str);
263}
264
266{
267 LOGVAR("TagData::read_array_types()");
268
269 long long array_type = 0;
270 size_t nr;
271 nr = fread(&array_type, sizeof(array_type), 1, in); nr++;
272
273 ByteOrder::become_big_endian(&array_type);
274
275 LOGVAR("array data type = '%s'", GatanDM4::to_str((Type) array_type));
276
277 vector < int >item_types;
278
279 if (array_type == STRUCT) {
280 item_types = read_struct_types();
281 }
282 else if (array_type == ARRAY) {
283 item_types = read_array_types();
284 LOGERR("DM4: don't know how to handle this array type");
285 }
286 else {
287 item_types.push_back(array_type);
288 }
289
290 return item_types;
291}
292
293// string tag data are stored in unicode
294string TagData::read_string(int size)
295{
296 if (size <= 0) {
297 return string("");
298 }
299
300 unsigned short *buf = new unsigned short[size];
301 char *str = new char[size + 1];
302
303 size_t nr;
304 nr = fread(buf, size * sizeof(unsigned short), 1, in); nr++;
305 tagtable->become_host_endian < unsigned short >(buf, size);
306
307 for (int i = 0; i < size; i++) {
308 str[i] = static_cast < char >(buf[i]);
309 }
310
311 str[size] = '\0';
312 string str1 = string(str);
313
314 if (str) {
315 delete [] str;
316 str = NULL;
317 }
318
319 if (buf) {
320 delete [] buf;
321 buf = NULL;
322 }
323
324 return str1;
325}
326
327int TagData::read_array_data(vector < int >item_types, bool nodata, int image_index, int num_images)
328{
329 ENTERFUNC;
330 if (item_types.size() == 0) {
331 LOGERR("DM4 item types cannot be empty");
332 return 1;
333 }
334
335 int err = 0;
336 long long array_size = 0;
337
338 size_t nr;
339 nr = fread(&array_size, sizeof(array_size), 1, in); nr++;
340 ByteOrder::become_big_endian(&array_size);
341
342 LOGVAR("array size = %lld\n", array_size);
343
344 size_t item_size = 0;
345 for (size_t i = 0; i < item_types.size(); i++) {
346 item_size += typesize(item_types[i]);
347 }
348
349 LOGVAR("%s array item size = %lld\n", name.c_str(), item_size);
350
351 size_t buf_size = item_size * array_size;
352
353 if (item_types.size() == 1 && item_types[0] == USHORT && nodata) {
354 string val = read_string(array_size);
355 tagtable->add(name, val);
356 LOGVAR("value: %s", val.c_str());
357 }
358 else if (!nodata && name == "Data") {
359 int num_found = tagtable->get_num_images_found();
360 num_found++;
361 tagtable->set_num_images_found(num_found);
362
363 char * data;
364
365 if (image_index < 0 || buf_size % num_images != 0 || num_found == 1) {
366 data = new char[buf_size];
367 nr = fread(data, item_size, array_size, in); nr++;
368 }
369 else {
370 size_t image_size = buf_size / num_images;
371
372 data = new char[image_size];
373 portable_fseek(in, image_index * image_size, SEEK_CUR);
374 nr = fread(data, image_size, 1, in); nr++;
375 portable_fseek(in, (num_images - image_index - 1) * image_size, SEEK_CUR);
376 array_size = array_size / num_images;
377 }
378
379 if (item_size == sizeof(short)) {
380 tagtable->become_host_endian((short *) data, array_size);
381 }
382 else if (item_size == sizeof(int)) {
383 tagtable->become_host_endian((int *) data, array_size);
384 }
385 else if (item_size == sizeof(double)) {
386 tagtable->become_host_endian((double *) data, array_size);
387 }
388 else {
389 LOGERR("cannot handle this type of DM4 image data");
390 return 1;
391 }
392
393 tagtable->add_data(data);
394 }
395 else {
396 portable_fseek(in, buf_size, SEEK_CUR);
397 }
398 EXITFUNC;
399 return err;
400}
401
403{
404 LOGVAR("TagData::read_struct_types()");
405
406 long long namelength = 0;
407 long long nfields = 0;
408
409 size_t nr;
410 nr = fread(&namelength, sizeof(namelength), 1, in); nr++;
411 ByteOrder::become_big_endian(&namelength);
412
413 nr = fread(&nfields, sizeof(nfields), 1, in); nr++;
415
416 LOGVAR("namelength = %lld\n", namelength);
417 LOGVAR("num fields = %lld\n", nfields);
418
419 vector < int >field_types;
420
421 for (unsigned int i = 0; i < nfields; i++) {
422 nr = fread(&namelength, sizeof(namelength), 1, in); nr++;
423 ByteOrder::become_big_endian(&namelength);
424
425 long long field_type = 0;
426 nr = fread(&field_type, sizeof(field_type), 1, in); nr++;
427 ByteOrder::become_big_endian(&field_type);
428
429 LOGVAR("%dth namelength = %lld, type = '%s'",
430 i, namelength, GatanDM4::to_str((Type) field_type));
431 field_types.push_back(field_type);
432 }
433
434 return field_types;
435}
436
437int TagData::read_any(bool nodata, int image_index, int num_images)
438{
439 int err = 0;
440
441 size_t nr;
442 nr = fread(&tag_type, sizeof(tag_type), 1, in); nr++;
443
445 LOGVAR("TagData::read_any tag type = '%s'\n", GatanDM4::to_str((Type) tag_type));
446
447
448 if (tag_type == ARRAY) {
449 vector < int >item_types = read_array_types();
450 err = read_array_data(item_types, nodata, image_index, num_images);
451 }
452 else if (tag_type == STRUCT) {
453 vector < int >field_types = read_struct_types();
454
455 for (unsigned int i = 0; i < field_types.size(); i++) {
456
457 tag_type = static_cast < Type > (field_types[i]);
458
459 string val = read_native(false);
460
461 char int_str[32];
462 sprintf(int_str, " #%d", i);
463 string fieldname = name + string(int_str);
464 tagtable->add(fieldname, val);
465 }
466 }
467 else if (tag_type == STRING) {
468
469 int str_sz = 0;
470 size_t nr;
471 nr = fread(&str_sz, sizeof(str_sz), 1, in); nr++;
473
474 char *val = new char[str_sz + 1];
475 nr = fread(val, str_sz, 1, in); nr++;
476 val[str_sz] = '\0';
477 string val_str = string(val);
478
479 if (val) {
480 delete [] val;
481 val = NULL;
482 }
483
484 tagtable->add(name, val_str);
485 }
486 else {
487 read_native(true);
488 }
489
490 return err;
491}
492
493int TagData::read_tag_data(bool nodata, int image_index, int num_images)
494{
495 LOGVAR("TagData::read_tag_data()");
496 int err = 0;
497
498 const char *DATA_TYPE_MARK = "%%%%";
499 const size_t mark_sz = strlen(DATA_TYPE_MARK);
500 char *mark = new char[mark_sz + 1];
501
502 long long interval;
503
504 size_t nr;
505 nr = fread(&interval, sizeof(interval), 1, in); nr++;
506
508
509 nr = fread(mark, mark_sz, 1, in); nr++;
510 mark[mark_sz] = '\0';
511
512 if (strcmp(mark, DATA_TYPE_MARK) != 0) {
513 LOGERR("data type label has been changed from '%s' to '%s'",
514 DATA_TYPE_MARK, mark);
515 return 1;
516 }
517
518 if (mark) {
519 delete [] mark;
520 mark = NULL;
521 }
522
523 long long encoded_types_size = 0;
524 nr = fread(&encoded_types_size, sizeof(long long), 1, in); nr++;
525 ByteOrder::become_big_endian(&encoded_types_size);
526
527 LOGVAR("encoded types size = %lld\n", encoded_types_size);
528
529 err = read_any(nodata, image_index, num_images);
530
531 return err;
532}
533
534size_t TagData::typesize() const
535{
536 return typesize((int) tag_type);
537}
538
539size_t TagData::typesize(int t) const
540{
541 size_t size = 0;
542 Type type = static_cast < Type > (t);
543
544
545 switch (type) {
546 case SHORT:
547 size = sizeof(short);
548 break;
549 case USHORT:
550 size = sizeof(unsigned short);
551 break;
552 case INT:
553 size = sizeof(int);
554 break;
555 case UINT:
556 size = sizeof(unsigned int);
557 break;
558 case FLOAT:
559 size = sizeof(float);
560 break;
561 case DOUBLE:
562 size = sizeof(double);
563 break;
564 case BOOLEAN:
565 size = sizeof(bool);
566 break;
567 case CHAR:
568 case OCTET:
569 size = sizeof(char);
570 break;
571 case OCTEU:
572 size = sizeof(double);
573 break;
574 case OCTEV:
575 size = sizeof(double);
576 break;
577 default:
578 LOGERR("no such type: '%d'\n", type);
579 break;
580 }
581
582 return size;
583}
584
586
587TagEntry::TagEntry(FILE * data_file, TagTable * table, TagGroup * parent)
588 : in(data_file), tagtable(table), parent_group(parent), name("")
589{
590}
591
593{
594}
595
596int TagEntry::read_tag_entry(bool nodata, int image_index, int num_images)
597{
598 LOGVAR("TagEntry::read_tag_entry()");
599 int err = 0;
600 long long pos = 0;
601 char tagtype = 0;
602 char *tmp_name = 0;
603
604 pos = ftell(in);
605 size_t nr;
606 nr = fread(&tagtype, sizeof(char), 1, in); nr++;
607
608 if (tagtype != GROUP_TAG && tagtype != DATA_TAG) {
609 portable_fseek(in, sizeof(char) * 7, SEEK_CUR);
610 nr = fread(&tagtype, sizeof(char), 1, in); nr++;
611 }
612
613 if (tagtype != GROUP_TAG && tagtype != DATA_TAG) {
614 tagtype = fgetc(in);
615 if (tagtype == EOF)
616 {
617 return 1;
618 }
619 else{
620 LOGERR("TagEntry::read_tag_entry() invalid tag type: %d @ position %lld", tagtype, pos);
621 return 1;
622 }
623 }
624
625 short name_len = 0;
626 nr = fread(&name_len, sizeof(short), 1, in); nr++;
627
629
630 if (name_len != 0) {
631 tmp_name = new char[name_len + 1];
632 nr = fread(tmp_name, name_len, 1, in); nr++;
633 tmp_name[name_len] = '\0';
634 }
635 else {
636 string parent_name = parent_group->get_name();
637 name_len = static_cast < short >(parent_name.size() + 4);
638 tmp_name = new char[name_len + 1];
639 sprintf(tmp_name, "%s #%d", parent_name.c_str(), parent_group->get_entry_id());
640 }
641
642 name = string(tmp_name);
643
644 if (tmp_name) {
645 delete [] tmp_name;
646 tmp_name = NULL;
647 }
648
649 LOGVAR("\ntag name: '%s', len: %d, type: '%s'",
650 name.c_str(), name_len, GatanDM4::to_str((EntryType) tagtype));
651
652 if (tagtype == DATA_TAG) {
653 TagData tag_data(in, tagtable, name);
654 err = tag_data.read_tag_data(nodata, image_index, num_images);
655 }
656 else if (tagtype == GROUP_TAG) {
657 long long tot_size = 0; //size of DataType record + size of data
658 nr = fread(&tot_size, sizeof(long long), 1, in); nr++;
660
661 TagGroup group(in, tagtable, name);
662 err = group.read_tag_group(nodata, image_index, num_images);
663 }
664
665/*
666 long long tot_size = 0; //size of DataType record + size of data
667 nr = fread(&tot_size, sizeof(long long), 1, in); nr++;
668*/
669 return err;
670}
671
673
674TagGroup::TagGroup(FILE * data_file, TagTable * table, const string & groupname)
675 : in(data_file), tagtable(table), name(groupname), entry_id(0)
676{
677}
678
680{
681}
682
683int TagGroup::read_tag_group(bool nodata, int image_index, int num_images)
684{
685 LOGVAR("TagGroup::read_tag_group()");
686 char is_sorted, is_open;
687
688 long long ntags = 0;
689
690// portable_fseek(in, sizeof(char) * 2, SEEK_CUR);
691 size_t nr;
692 nr = fread(&is_sorted, sizeof(is_sorted), 1, in); nr++;
693 nr = fread(&is_open, sizeof(is_open), 1, in); nr++;
694
695 nr = fread(&ntags, sizeof(ntags), 1, in); nr++;
696
698
699 LOGVAR("DM4: ntags = %d\n", ntags);
700
701 int err = 0;
702 // char flagend;
703 for (int i = 0; i < ntags; i++) {
704 /*
705 portable_fseek(in, sizeof(char) * 9, SEEK_CUR);
706 nr = fread(&flagend, sizeof(char), 1, in); nr++;
707
708 if (flagend ==EOF){
709 break;
710 }
711 else{
712 portable_fseek(in, -sizeof(char) * 10, SEEK_CUR);;
713 }
714
715 */
716
717 TagEntry tag_entry(in, tagtable, this);
718 err = tag_entry.read_tag_entry(nodata, image_index, num_images);
719
720 if (err) {
721 break;
722 }
723 }
724
725 return err;
726}
727
728string TagGroup::get_name() const
729{
730 return name;
731}
732
734{
735 int id = entry_id;
736 entry_id++;
737 return id;
738}
739
741
742DM4IO::DM4IO(const string & fname, IOMode rw)
743 : ImageIO(fname, rw)
744{
746 tagtable = new TagTable();
747}
748
750{
751 if (file) {
752 fclose(file);
753 file = 0;
754 }
755 if (tagtable) {
756 delete tagtable;
757 tagtable = 0;
758 }
759}
760
761void DM4IO::init()
762{
763 ENTERFUNC;
764 if (initialized) {
765 return;
766 }
767 initialized = true;
768
769 if (rw_mode != READ_ONLY) {
770 throw ImageReadException(filename, "only support DM4 read-only");
771 }
772
774
775 int stream_version = 0;
776 if (fread(&stream_version, sizeof(stream_version), 1, file) != 1) {
777 throw ImageReadException(filename, "read stream version of DM4 file");
778 }
779
780 long long recsize;
781 if (fread(&recsize, sizeof(recsize), 1, file) != 1) {
782 throw ImageReadException(filename, "read size of TagGroup recoed of DM4 file");
783 }
784
785 int endianness;
786 if (fread(&endianness, sizeof(endianness), 1, file) != 1) {
787 throw ImageReadException(filename, "read endianness indicator of DM4 file");
788 }
789
791 ByteOrder::swap_bytes(&stream_version);
792 ByteOrder::swap_bytes(&recsize);
793 ByteOrder::swap_bytes(&endianness);
794 }
795
796 if (endianness == 0) {
797 is_big_endian = true;
798 }
799 else {
800 is_big_endian = false;
801 }
802
804
805 LOGDEBUG("dm4 ver = %d, image size = %d, is_big_endian = %d",
806 stream_version, recsize, (int) is_big_endian);
807
808 EXITFUNC;
809}
810
811bool DM4IO::is_valid(const void *first_block)
812{
813 ENTERFUNC;
814
815 if (!first_block) {
816 return false;
817 }
818
819 const int *data = static_cast < const int *>(first_block);
820
821 int img_ver = data[0];
822 int byte_order = data[3];
824 ByteOrder::swap_bytes(&img_ver);
825 ByteOrder::swap_bytes(&byte_order);
826 }
827
828 if (img_ver != 4) {
829 return false;
830 }
831
832 if (byte_order != 0 && byte_order != 1) {
833 return false;
834 }
835
836 return true;
837}
838
840{
841 init();
842 return is_big_endian;
843}
844
845int DM4IO::read_header(Dict & dict, int image_index, const Region * area, bool)
846{
847 ENTERFUNC;
848 int err = 0;
849
850 //single image format, index can only be zero
851 if(image_index == -1) {
852 image_index = 0;
853 }
854 image_index = 0;
855 check_read_access(image_index);
856
857 portable_fseek(file, NUM_ID_INT * sizeof(int), SEEK_SET);
858 TagGroup root_group(file, tagtable, "");
859 root_group.read_tag_group(true, 0, 1);
860
861 int nx = tagtable->get_xsize();
862 int ny = tagtable->get_ysize();
863
864 check_region(area, IntSize(nx, ny));
865 int xlen = 0, ylen = 0;
866 EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen);
867
868 dict["nx"] = xlen;
869 dict["ny"] = ylen;
870 dict["nz"] = 1;
871
872 dict["nimg"] = tagtable->get_image_counted();
873 dict["DM4.acq_date"] = tagtable->get_string("Acquisition Date");
874 dict["DM4.acq_time"] = tagtable->get_string("Acquisition Time");
875 dict["DM4.source"] = tagtable->get_string("Source");
876 dict["DM4.exposure_number"] = tagtable->get_int("Exposure Number");
877 dict["DM4.exposure_time"] = tagtable->get_double("Exposure (s)");
878 dict["DM4.zoom"] = tagtable->get_double("Zoom");
879 dict["DM4.antiblooming"] = tagtable->get_int("Antiblooming");
880 dict["DM4.indicated_mag"] = tagtable->get_double("Indicated Magnification");
881 dict["DM4.actual_mag"] = tagtable->get_double("Actual Magnification");
882 dict["DM4.pixel_size"] = tagtable->get_double("Pixel Size (um) #0");
883 dict["DM4.name"] = tagtable->get_string("Name");
884
885 dict["DM4.voltage"] = tagtable->get_double("Voltage")/1000.0;
886 dict["microscope_voltage"]=(float)dict["DM4.voltage"];
887 dict["DM4.cs"] = tagtable->get_double("Cs(mm)");
888 dict["microscope_cs"]=(float)dict["DM4.cs"];
889
890 dict["DM4.frame_type"] = tagtable->get_string("Processing");
891 dict["DM4.camera_x"] = tagtable->get_int("Active Size (pixels) #0");
892 dict["DM4.camera_y"] = tagtable->get_int("Active Size (pixels) #1");
893 dict["DM4.binning_x"] = tagtable->get_int("Binning #0");
894 dict["DM4.binning_y"] = tagtable->get_int("Binning #1");
895 dict["datatype"] = to_em_datatype(tagtable->get_datatype());
896
897 if ((float)dict["DM4.actual_mag"] >0.0) {
898 float apix=10000.0*(float)dict["DM4.pixel_size"]/(float)dict["DM4.actual_mag"];
899 dict["apix_x"]=apix;
900 dict["apix_y"]=apix;
901 dict["apix_z"]=apix;
902 }
903
904 EXITFUNC;
905 return err;
906}
907
908int DM4IO::read_data(float *rdata, int image_index, const Region * area, bool)
909{
910 ENTERFUNC;
911
912 check_read_access(image_index, rdata);
913
914 portable_fseek(file, NUM_ID_INT * sizeof(int), SEEK_SET);
915 TagGroup root_group(file, tagtable, "");
916 root_group.read_tag_group(true, 0, 1);
917
918 int nx = tagtable->get_xsize();
919 int ny = tagtable->get_ysize();
920 int num_images = tagtable->get_image_counted();
921
922 portable_fseek(file, NUM_ID_INT * sizeof(int), SEEK_SET);
923 root_group.read_tag_group(false, image_index, num_images);
924
925 check_region(area, IntSize(nx, ny));
926
927 int xlen = 0, ylen = 0, x0 = 0, y0 = 0;
928 EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen);
929 EMUtil::get_region_origins(area, &x0, &y0);
930
931 char *data = tagtable->get_data();
932 int data_type = tagtable->get_datatype();
933
934 long long offset = 0;
935 long long k = 0;
936 long long off = 0;
937 int xlast = x0 + xlen;
938 int ylast = y0 + ylen;
939
940// bool flip_vertical = (getenv ("FLIP_VERTICAL") != NULL);
941 bool flip_vertical = true;
942
943 for (int iy = y0; iy < ylast; iy++) {
944 if (flip_vertical) {
945 off = offset + (y0 + ylast - 1 - iy) * nx;
946 }
947 else {
948 off = offset + iy * nx;
949 }
950
951 switch (data_type) {
953 for (int ix = x0; ix < xlast; ix++) {
954 rdata[k] = (float) ((char *) data)[off + ix];
955 k++;
956 }
957 break;
959 for (int ix = x0; ix < xlast; ix++) {
960 rdata[k] = (float) ((unsigned char *) data)[off + ix];
961 k++;
962 }
963 break;
965 for (int ix = x0; ix < xlast; ix++) {
966 rdata[k] = (float) ((short *) data)[off + ix];
967 k++;
968 }
969 break;
971 for (int ix = x0; ix < xlast; ix++) {
972 rdata[k] = (float) ((unsigned short *) data)[off + ix];
973 k++;
974 }
975 break;
977 for (int ix = x0; ix < xlast; ix++) {
978 rdata[k] = (float) ((int *) data)[off + ix];
979 k++;
980 }
981 break;
983 for (int ix = x0; ix < xlast; ix++) {
984 rdata[k] = (float) ((unsigned int *) data)[off + ix];
985 k++;
986 }
987 break;
989 for (int ix = x0; ix < xlast; ix++) {
990 rdata[k] = (float) ((float *) data)[off + ix];
991 k++;
992 }
993 break;
995 for (int ix = x0; ix < xlast; ix++) {
996 rdata[k] = (float) ((double *) data)[off + ix];
997 k++;
998 }
999 break;
1000 default:
1001 string desc = string("unsupported DM4 data type") +
1003 throw ImageReadException(filename, desc);
1004 k += xlen;
1005 }
1006 }
1007
1008// #include "debug_read_data.h"
1009
1010 EXITFUNC;
1011 return 0;
1012
1013 EXITFUNC;
1014}
1015
1017{
1018 return false;
1019}
1020
1021int DM4IO::write_header(const Dict &, int, const Region* , EMUtil::EMDataType, bool)
1022{
1023 ENTERFUNC;
1024 LOGWARN("DM4 write is not supported.");
1025 EXITFUNC;
1026 return 1;
1027}
1028
1029int DM4IO::write_data(float *, int, const Region* , EMUtil::EMDataType, bool)
1030{
1031 ENTERFUNC;
1032 LOGWARN("DM4 write is not supported.");
1033 EXITFUNC;
1034 return 1;
1035}
1036
1038{
1039 init();
1040
1041 TagGroup root_group(file, tagtable, "");
1042 root_group.read_tag_group(true, 0, 1);
1043
1044 return tagtable->get_image_counted();
1045}
1046
1047void DM4IO::flush()
1048{
1049}
1050
1051int GatanDM4::to_em_datatype(int gatan_datatype)
1052{
1053 DataType::GatanDataType type = static_cast < DataType::GatanDataType > (gatan_datatype);
1054 int t = 0;
1055
1056 switch (type) {
1058 t = EMUtil::EM_CHAR;
1059 break;
1061 t = EMUtil::EM_UCHAR;
1062 break;
1064 t = EMUtil::EM_SHORT;
1065 break;
1068 break;
1070 t = EMUtil::EM_INT;
1071 break;
1073 t = EMUtil::EM_UINT;
1074 break;
1075 default:
1077 }
1078
1079 return t;
1080}
1081
1082
1084{
1085 const char *str = "unknown";
1086
1087 switch (type) {
1088 case TagData::SHORT:
1089 str = "short";
1090 break;
1091 case TagData::INT:
1092 str = "int";
1093 break;
1094 case TagData::USHORT:
1095 str = "unsigned short";
1096 break;
1097 case TagData::UINT:
1098 str = "unsigned int";
1099 break;
1100 case TagData::FLOAT:
1101 str = "float";
1102 break;
1103 case TagData::DOUBLE:
1104 str = "double";
1105 break;
1106 case TagData::BOOLEAN:
1107 str = "boolean";
1108 break;
1109 case TagData::CHAR:
1110 str = "char";
1111 break;
1112 case TagData::OCTET:
1113 str = "octet";
1114 break;
1115 case TagData::STRUCT:
1116 str = "struct";
1117 break;
1118 case TagData::STRING:
1119 str = "string";
1120 break;
1121 case TagData::ARRAY:
1122 str = "array";
1123 break;
1124 default:
1125 str = "unknown";
1126 }
1127 return str;
1128}
1129
1131{
1132 const char *str = "unknown";
1133
1134 switch (type) {
1135 case TagEntry::GROUP_TAG:
1136 str = "Group";
1137 break;
1138 case TagEntry::DATA_TAG:
1139 str = "Data";
1140 break;
1141 default:
1142 str = "unknown";
1143 }
1144 return str;
1145}
1146
1147
1149{
1150 switch (type) {
1152 return "SIGNED_INT16_DATA";
1154 return "REAL4_DATA";
1156 return "COMPLEX8_DATA";
1158 return "OBSELETE_DATA";
1160 return "PACKED_DATA";
1162 return "UNSIGNED_INT8_DATA";
1164 return "SIGNED_INT32_DATA";
1166 return "RGB_DATA";
1168 return "SIGNED_INT8_DATA";
1170 return "UNSIGNED_INT16_DATA";
1172 return "UNSIGNED_INT32_DATA";
1174 return "REAL8_DATA";
1176 return "COMPLEX16_DATA";
1178 return "BINARY_DATA";
1180 return "RGB_UINT8_0_DATA";
1182 return "RGB_UINT8_1_DATA";
1184 return "RGB_UINT16_DATA";
1186 return "RGB_FLOAT32_DATA";
1188 return "RGB_FLOAT64_DATA";
1190 return "RGBA_UINT8_0_DATA";
1192 return "RGBA_UINT8_1_DATA";
1194 return "RGBA_UINT8_2_DATA";
1196 return "RGBA_UINT8_3_DATA";
1198 return "RGBA_UINT16_DATA";
1200 return "RGBA_FLOAT32_DATA";
1202 return "RGBA_FLOAT64_DATA";
1204 return "POINT2_SINT16_0_DATA";
1206 return "POINT2_SINT16_1_DATA";
1208 return "POINT2_SINT32_0_DATA";
1210 return "POINT2_FLOAT32_0_DATA";
1212 return "RECT_SINT16_1_DATA";
1214 return "RECT_SINT32_1_DATA";
1216 return "RECT_FLOAT32_1_DATA";
1218 return "RECT_FLOAT32_0_DATA";
1220 return "SIGNED_INT64_DATA";
1222 return "UNSIGNED_INT64_DATA";
1223 default:
1224 break;
1225 }
1226 return "Unknown Type";
1227}
#define rdata(i)
Definition: analyzer.cpp:592
static bool is_host_big_endian()
Definition: byteorder.cpp:40
static void swap_bytes(T *data, size_t n=1)
swap the byte order of data with 'n' T-type elements.
Definition: byteorder.h:131
static bool is_data_big_endian(const T *small_num_addr)
given a pointer to a reasonable small integer number, return whether the number is big endian or not.
Definition: byteorder.h:76
static void become_big_endian(T *data, size_t n=1)
convert data from host byte order to big endian order.
Definition: byteorder.h:112
int get_nimg()
Return the number of images in this image file.
Definition: dm4io.cpp:1037
GatanDM4::TagTable * tagtable
Definition: dm4io.h:263
@ NUM_ID_INT
Definition: dm4io.h:260
DM4IO(const string &fname, IOMode rw_mode=READ_ONLY)
Definition: dm4io.cpp:742
bool is_big_endian
Definition: dm4io.h:262
static bool is_valid(const void *first_block)
Definition: dm4io.cpp:811
Dict is a dictionary to store <string, EMObject> pair.
Definition: emobject.h:385
EMDataType
Image pixel data type used in EMAN.
Definition: emutil.h:92
@ EM_UCHAR
Definition: emutil.h:95
@ EM_UNKNOWN
Definition: emutil.h:93
@ EM_USHORT
Definition: emutil.h:97
@ EM_SHORT
Definition: emutil.h:96
static void get_region_origins(const Region *area, int *p_x0, int *p_y0, int *p_z0=0, int nz=1, int image_index=0)
Get a region's original locations.
Definition: emutil.cpp:891
static void get_region_dims(const Region *area, int nx, int *area_x, int ny, int *area_y, int nz=1, int *area_z=0)
Get a region's dimensions.
Definition: emutil.cpp:860
int read_tag_data(bool nodata=false, int image_index=0, int num_images=1)
Definition: dm4io.cpp:493
long long tag_type
Definition: dm4io.h:138
string read_string(int size)
Definition: dm4io.cpp:294
TagData(FILE *data_file, TagTable *tagtable, const string &tagname)
Definition: dm4io.cpp:177
vector< int > read_array_types()
Definition: dm4io.cpp:265
int read_any(bool nodata=false, int image_index=0, int num_images=1)
Definition: dm4io.cpp:437
size_t typesize() const
Definition: dm4io.cpp:534
TagTable * tagtable
Definition: dm4io.h:136
int read_array_data(vector< int >item_types, bool nodata=false, int image_index=0, int num_images=1)
Definition: dm4io.cpp:327
string read_native(bool is_value_stored)
Definition: dm4io.cpp:186
vector< int > read_struct_types()
Definition: dm4io.cpp:402
TagTable * tagtable
Definition: dm4io.h:174
TagEntry(FILE *data_file, TagTable *tagtable, TagGroup *parent_group)
Definition: dm4io.cpp:587
TagGroup * parent_group
Definition: dm4io.h:175
int read_tag_entry(bool nodata=false, int image_index=0, int num_images=1)
Definition: dm4io.cpp:596
int read_tag_group(bool nodata=false, int image_index=0, int num_images=1)
Definition: dm4io.cpp:683
TagGroup(FILE *data_file, TagTable *tagtable, const string &groupname)
Definition: dm4io.cpp:674
TagTable * tagtable
Definition: dm4io.h:153
string get_name() const
Definition: dm4io.cpp:728
char * get_data() const
Definition: dm4io.cpp:145
static const char * IMAGE_HEIGHT_TAG
Definition: dm4io.h:78
std::map< string, string > tags
Definition: dm4io.h:89
int get_num_images_found() const
Definition: dm4io.cpp:165
int get_datatype() const
Definition: dm4io.cpp:140
int get_int(const string &name)
Definition: dm4io.cpp:100
vector< int > datatype_list
Definition: dm4io.h:92
void become_host_endian(T *data, int n=1)
Definition: dm4io.h:65
vector< int > y_list
Definition: dm4io.h:91
void set_endian(bool big_endian)
Definition: dm4io.h:71
double get_double(const string &name)
Definition: dm4io.cpp:110
static const char * IMAGE_NIMG_TAG
Definition: dm4io.h:79
void set_num_images_found(int num_found)
Definition: dm4io.cpp:170
string get_string(const string &name)
Definition: dm4io.cpp:95
void add(const string &name, const string &value)
Definition: dm4io.cpp:61
static const char * IMAGE_THUMB_INDEX_TAG
Definition: dm4io.h:81
int get_image_counted() const
Definition: dm4io.cpp:130
static const char * IMAGE_WIDTH_TAG
Definition: dm4io.h:77
void set_thumb_index(int i)
Definition: dm4io.cpp:150
void dump() const
Definition: dm4io.cpp:115
void add_data(char *data)
Definition: dm4io.cpp:85
int get_xsize() const
Definition: dm4io.cpp:125
vector< char * > data_list
Definition: dm4io.h:93
int get_ysize() const
Definition: dm4io.cpp:135
float get_float(const string &name)
Definition: dm4io.cpp:105
vector< int > x_list
Definition: dm4io.h:90
static const char * IMAGE_DATATYPE_TAG
Definition: dm4io.h:80
ImageIO classes are designed for reading/writing various electron micrography image formats,...
Definition: imageio.h:127
IOMode rw_mode
Definition: imageio.h:353
string filename
Definition: imageio.h:352
void check_region(const Region *area, const FloatSize &max_size, bool is_new_file=false, bool inbounds_only=true)
Validate image I/O region.
Definition: imageio.cpp:58
virtual void flush()=0
Flush the IO buffer.
virtual int write_header(const Dict &dict, int image_index=0, const Region *area=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)=0
Write a header to an image.
bool initialized
Definition: imageio.h:355
virtual int write_data(float *data, int image_index=0, const Region *area=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)=0
Write data to an image.
virtual bool is_complex_mode()=0
Is this an complex image or not.
virtual int read_header(Dict &dict, int image_index=0, const Region *area=0, bool is_3d=false)=0
Read the header from an image.
FILE * sfopen(const string &filename, IOMode mode, bool *is_new=0, bool overwrite=false)
Run fopen safely.
Definition: imageio.cpp:135
void check_read_access(int image_index)
Validate 'image_index' in file reading.
Definition: imageio.cpp:95
virtual int read_data(float *data, int image_index=0, const Region *area=0, bool is_3d=false)=0
Read the data from an image.
FILE * file
Definition: imageio.h:354
virtual void init()=0
Do some initialization before doing the read/write.
virtual bool is_image_big_endian()=0
Is this image in big endian or not.
IntSize is used to describe a 1D, 2D or 3D rectangular size in integers.
Definition: geometry.h:49
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
Definition: geometry.h:497
#define ImageReadException(filename, desc)
Definition: exception.h:204
#define OutofRangeException(low, high, input, objname)
Definition: exception.h:334
#define NullPointerException(desc)
Definition: exception.h:241
#define LOGDEBUG
Definition: log.h:55
#define LOGWARN
Definition: log.h:53
#define LOGERR
Definition: log.h:51
#define ENTERFUNC
Definition: log.h:48
#define LOGVAR
Definition: log.h:57
#define EXITFUNC
Definition: log.h:49
int to_em_datatype(int gatan_datatype)
Definition: dm4io.cpp:1051
const char * to_str(GatanDM4::TagData::Type type)
Definition: dm4io.cpp:1083
int to_em_datatype(int gatan_datatype)
Definition: dm3io.cpp:894
E2Exception class.
Definition: aligner.h:40
int portable_fseek(FILE *fp, off_t offset, int whence)