EMAN2
dm3io.cpp
Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00007  * Copyright (c) 2000-2006 Baylor College of Medicine
00008  *
00009  * This software is issued under a joint BSD/GNU license. You may use the
00010  * source code in this file under either license. However, note that the
00011  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00012  * so you are responsible for compliance with the licenses of these packages
00013  * if you opt to use BSD licensing. The warranty disclaimer below holds
00014  * in either instance.
00015  *
00016  * This complete copyright notice must be included in any revised version of the
00017  * source code. Additional authorship citations may be added, but existing
00018  * author citations must be preserved.
00019  *
00020  * This program is free software; you can redistribute it and/or modify
00021  * it under the terms of the GNU General Public License as published by
00022  * the Free Software Foundation; either version 2 of the License, or
00023  * (at your option) any later version.
00024  *
00025  * This program is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028  * GNU General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU General Public License
00031  * along with this program; if not, write to the Free Software
00032  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00033  *
00034  * */
00035 
00036 #include <cstring>
00037 
00038 #include "dm3io.h"
00039 #include "portable_fileio.h"
00040 #include "geometry.h"
00041 
00042 using namespace EMAN;
00043 using namespace EMAN::Gatan;
00044 
00045 const char *TagTable::IMAGE_WIDTH_TAG = "Dimensions #0";
00046 const char *TagTable::IMAGE_HEIGHT_TAG = "Dimensions #1";
00047 const char *TagTable::IMAGE_DATATYPE_TAG = "DataType";
00048 const char *TagTable::IMAGE_THUMB_INDEX_TAG = "ImageIndex";
00049 
00050 TagTable::TagTable()
00051         :       img_index(0), is_big_endian(true)
00052 {
00053 }
00054 
00055 TagTable::~TagTable()
00056 {
00057         for (unsigned int i = 0; i < data_list.size(); i++) {
00058                 if (data_list[i]) {
00059                         delete [] data_list[i];
00060                         data_list[i] = 0;
00061                 }
00062         }
00063 }
00064 
00065 void TagTable::add(const string & name, const string & value)
00066 {
00067         const char *value_str = value.c_str();
00068 
00069         if (name == IMAGE_WIDTH_TAG) {
00070                 x_list.push_back(atoi(value_str));
00071         }
00072         else if (name == IMAGE_HEIGHT_TAG) {
00073                 y_list.push_back(atoi(value_str));
00074         }
00075         else if (name == IMAGE_DATATYPE_TAG) {
00076                 datatype_list.push_back(atoi(value_str));
00077         }
00078         else if (name == IMAGE_THUMB_INDEX_TAG) {
00079                 set_thumb_index(atoi(value_str));
00080         }
00081         else {
00082                 tags[name] = value;
00083         }
00084 }
00085 
00086 void TagTable::add_data(char *data)
00087 {
00088         if (!data) {
00089                 throw NullPointerException("DM3 data is NULL");
00090         }
00091         else {
00092                 data_list.push_back(data);
00093         }
00094 }
00095 
00096 string TagTable::get_string(const string & name)
00097 {
00098         return tags[name];
00099 }
00100 
00101 int TagTable::get_int(const string & name)
00102 {
00103         return atoi(tags[name].c_str());
00104 }
00105 
00106 float TagTable::get_float(const string & name)
00107 {
00108         return static_cast < float >(atof(tags[name].c_str()));
00109 }
00110 
00111 double TagTable::get_double(const string & name)
00112 {
00113         return atof(tags[name].c_str());
00114 }
00115 
00116 void TagTable::dump() const
00117 {
00118         map < string, string >::const_iterator p;
00119 
00120         for (p = tags.begin(); p != tags.end(); p++) {
00121 //              LOGDEBUG("  %s: %s", (*p).first.c_str(), (*p).second.c_str());
00122                 printf("  %s: %s\n", (*p).first.c_str(), (*p).second.c_str());
00123         }
00124 }
00125 
00126 int TagTable::get_xsize() const
00127 {
00128         return x_list[img_index];
00129 }
00130 
00131 int TagTable::get_ysize() const
00132 {
00133         return y_list[img_index];
00134 }
00135 
00136 int TagTable::get_datatype() const
00137 {
00138         return datatype_list[img_index];
00139 }
00140 
00141 char *TagTable::get_data() const
00142 {
00143         return data_list[img_index];
00144 }
00145 
00146 void TagTable::set_thumb_index(int i)
00147 {
00148         if (i != 0 && i != 1) {
00149                 throw OutofRangeException(0, 1, i, "image index");
00150         }
00151         else {
00152                 if (i == 0) {
00153                         img_index = 1;
00154                 }
00155                 else {
00156                         img_index = 0;
00157                 }
00158         }
00159 }
00160 
00161 TagData::TagData(FILE * data_file, TagTable * table, const string & tagname)
00162         :       in(data_file), tagtable(table), name(tagname), tag_type(UNKNOWN)
00163 {
00164 }
00165 
00166 TagData::~TagData()
00167 {
00168 }
00169 
00170 string TagData::read_native(bool is_value_stored)
00171 {
00172         size_t sz = typesize();
00173         size_t nr;
00174         char val_str[32];
00175 
00176         if (tag_type == SHORT) {
00177                 short val = 0;
00178                 nr = fread(&val, sz, 1, in);
00179                 tagtable->become_host_endian(&val);
00180                 sprintf(val_str, "%d", val);
00181         }
00182         else if (tag_type == USHORT) {
00183                 unsigned short val = 0;
00184                 nr = fread(&val, sz, 1, in);
00185                 tagtable->become_host_endian(&val);
00186                 sprintf(val_str, "%d", val);
00187         }
00188         else if (tag_type == INT) {
00189                 int val = 0;
00190                 nr = fread(&val, sz, 1, in);
00191                 tagtable->become_host_endian(&val);
00192                 sprintf(val_str, "%d", val);
00193         }
00194         else if (tag_type == CHAR || tag_type == OCTET) {
00195                 char val = 0;
00196                 nr = fread(&val, sz, 1, in);
00197                 sprintf(val_str, "%d", val);
00198         }
00199         else if (tag_type == BOOLEAN) {
00200                 bool val = false;
00201                 nr = fread(&val, sz, 1, in);
00202                 tagtable->become_host_endian(&val);
00203                 sprintf(val_str, "%d", val);
00204         }
00205         else if (tag_type == UINT) {
00206                 unsigned int val = 0;
00207                 nr = fread(&val, sz, 1, in);
00208                 tagtable->become_host_endian(&val);
00209                 sprintf(val_str, "%d", (int) val);
00210         }
00211         else if (tag_type == FLOAT) {
00212                 float val = 0;
00213                 nr = fread(&val, sz, 1, in);
00214                 tagtable->become_host_endian(&val);
00215                 sprintf(val_str, "%f", val);
00216         }
00217         else if (tag_type == DOUBLE) {
00218                 double val = 0;
00219                 nr = fread(&val, sz, 1, in);
00220                 tagtable->become_host_endian(&val);
00221                 sprintf(val_str, "%10e", val);
00222         }
00223         else {
00224                 LOGERR("invalid tag type: '%d'", tag_type);
00225                 exit(1);
00226         }
00227 
00228         if (is_value_stored) {
00229                 tagtable->add(name, val_str);
00230         }
00231 
00232         LOGVAR("value = '%s'", val_str);
00233 
00234         return string(val_str);
00235 }
00236 
00237 vector < int >TagData::read_array_types()
00238 {
00239         LOGVAR("TagData::read_array_types()");
00240 
00241         int array_type = 0;
00242         size_t nr;
00243         nr = fread(&array_type, sizeof(array_type), 1, in);
00244 
00245         ByteOrder::become_big_endian(&array_type);
00246 
00247         LOGVAR("array data type = '%s'", Gatan::to_str((Type) array_type));
00248 
00249         vector < int >item_types;
00250 
00251         if (array_type == STRUCT) {
00252                 item_types = read_struct_types();
00253         }
00254         else if (array_type == ARRAY) {
00255                 item_types = read_array_types();
00256                 LOGERR("DM3: don't know how to handle this array type");
00257         }
00258         else {
00259                 item_types.push_back(array_type);
00260         }
00261 
00262         return item_types;
00263 }
00264 
00265 // string tag data are stored in unicode
00266 
00267 string TagData::read_string(int size)
00268 {
00269         if (size <= 0) {
00270                 return string("");
00271         }
00272 
00273         unsigned short *buf = new unsigned short[size];
00274         char *str = new char[size + 1];
00275 
00276         size_t nr;
00277         nr = fread(buf, size * sizeof(unsigned short), 1, in);
00278         tagtable->become_host_endian < unsigned short >(buf, size);
00279 
00280         for (int i = 0; i < size; i++) {
00281                 str[i] = static_cast < char >(buf[i]);
00282         }
00283 
00284         str[size] = '\0';
00285         string str1 = string(str);
00286 
00287         if (str) {
00288                 delete [] str;
00289                 str = NULL;
00290         }
00291 
00292         if (buf) {
00293                 delete [] buf;
00294                 buf = NULL;
00295         }
00296 
00297         return str1;
00298 }
00299 
00300 int TagData::read_array_data(vector < int >item_types, bool nodata)
00301 {
00302         ENTERFUNC;
00303         if (item_types.size() == 0) {
00304                 LOGERR("DM3 item types cannot be empty");
00305                 return 1;
00306         }
00307 
00308         int err = 0;
00309         int array_size = 0;
00310 
00311         size_t nr;
00312         nr = fread(&array_size, sizeof(array_size), 1, in);
00313         ByteOrder::become_big_endian(&array_size);
00314 
00315         LOGVAR("array size = %d\n", array_size);
00316 
00317         size_t item_size = 0;
00318         for (size_t i = 0; i < item_types.size(); i++) {
00319                 item_size += typesize(item_types[i]);
00320         }
00321 
00322         LOGVAR("%s array item size = %d\n", name.c_str(), item_size);
00323 
00324         size_t buf_size = item_size * array_size;
00325 
00326         if (item_types.size() == 1 && item_types[0] == USHORT && nodata) {
00327                 string val = read_string(array_size);
00328                 tagtable->add(name, val);
00329                 LOGVAR("value: %s", val.c_str());
00330         }
00331         else if (!nodata && name == "Data") {
00332                 char *data = new char[buf_size];
00333                 nr = fread(data, buf_size, 1, in);
00334 
00335                 if (item_size == sizeof(short)) {
00336                         tagtable->become_host_endian((short *) data, array_size);
00337                 }
00338                 else if (item_size == sizeof(int)) {
00339                         tagtable->become_host_endian((int *) data, array_size);
00340                 }
00341                 else if (item_size == sizeof(double)) {
00342                         tagtable->become_host_endian((double *) data, array_size);
00343                 }
00344                 else {
00345                         LOGERR("cannot handle this type of DM3 image data");
00346                         return 1;
00347                 }
00348 
00349                 tagtable->add_data(data);
00350         }
00351         else {
00352                 portable_fseek(in, buf_size, SEEK_CUR);
00353         }
00354         EXITFUNC;
00355         return err;
00356 }
00357 
00358 vector < int >TagData::read_struct_types()
00359 {
00360         LOGVAR("TagData::read_struct_types()");
00361 
00362         unsigned int namelength = 0;
00363         unsigned int nfields = 0;
00364 
00365         size_t nr;
00366         nr = fread(&namelength, sizeof(namelength), 1, in);
00367         ByteOrder::become_big_endian(&namelength);
00368 
00369         nr = fread(&nfields, sizeof(nfields), 1, in);
00370         ByteOrder::become_big_endian(&nfields);
00371 
00372         LOGVAR("namelength = %d\n", namelength);
00373         LOGVAR("num fields = %d\n", nfields);
00374 
00375         vector < int >field_types;
00376 
00377         for (unsigned int i = 0; i < nfields; i++) {
00378                 nr = fread(&namelength, sizeof(namelength), 1, in);
00379                 ByteOrder::become_big_endian(&namelength);
00380 
00381                 int field_type = 0;
00382                 nr = fread(&field_type, sizeof(field_type), 1, in);
00383                 ByteOrder::become_big_endian(&field_type);
00384 
00385                 LOGVAR("%dth namelength = %d, type = '%s'",
00386                            i, namelength, Gatan::to_str((Type) field_type));
00387                 field_types.push_back(field_type);
00388         }
00389 
00390         return field_types;
00391 }
00392 
00393 int TagData::read_any(bool nodata)
00394 {
00395         int err = 0;
00396 
00397         size_t nr;
00398         nr = fread(&tag_type, sizeof(tag_type), 1, in);
00399         ByteOrder::become_big_endian(&tag_type);
00400         LOGVAR("tag type = '%s'\n", Gatan::to_str((Type) tag_type));
00401 
00402         if (tag_type == ARRAY) {
00403                 vector < int >item_types = read_array_types();
00404                 err = read_array_data(item_types, nodata);
00405         }
00406         else if (tag_type == STRUCT) {
00407                 vector < int >field_types = read_struct_types();
00408 
00409                 for (unsigned int i = 0; i < field_types.size(); i++) {
00410                         tag_type = static_cast < Type > (field_types[i]);
00411                         string val = read_native(false);
00412                         char int_str[32];
00413                         sprintf(int_str, " #%d", i);
00414                         string fieldname = name + string(int_str);
00415                         tagtable->add(fieldname, val);
00416                 }
00417         }
00418         else if (tag_type == STRING) {
00419                 int str_sz = 0;
00420                 nr = fread(&str_sz, sizeof(str_sz), 1, in);
00421                 ByteOrder::become_big_endian(&str_sz);
00422 
00423                 char *val = new char[str_sz + 1];
00424                 nr = fread(val, str_sz, 1, in);
00425                 val[str_sz] = '\0';
00426                 string val_str = string(val);
00427                 if( val )
00428                 {
00429                         delete[]val;
00430                         val = 0;
00431                 }
00432 
00433                 tagtable->add(name, val_str);
00434         }
00435         else {
00436                 read_native(true);
00437         }
00438 
00439         return err;
00440 }
00441 
00442 int TagData::read(bool nodata)
00443 {
00444         LOGVAR("TagData::read()");
00445         int err = 0;
00446 
00447         const char *DATA_TYPE_MARK = "%%%%";
00448         const size_t mark_sz = strlen(DATA_TYPE_MARK);
00449         char *mark = new char[mark_sz + 1];
00450 
00451         size_t nr;
00452         nr = fread(mark, mark_sz, 1, in);
00453         mark[mark_sz] = '\0';
00454 
00455         if (strcmp(mark, DATA_TYPE_MARK) != 0) {
00456                 LOGERR("data type label has been changed from '%s' to '%s'",
00457                            DATA_TYPE_MARK, mark);
00458                 return 1;
00459         }
00460 
00461         if (mark) {
00462                 delete [] mark;
00463                 mark = 0;
00464         }
00465 
00466         int encoded_types_size = 0;
00467         nr = fread(&encoded_types_size, sizeof(int), 1, in);
00468         ByteOrder::become_big_endian(&encoded_types_size);
00469 
00470         LOGVAR("encoded types size = %d\n", encoded_types_size);
00471 
00472         err = read_any(nodata);
00473 
00474         return err;
00475 }
00476 
00477 size_t TagData::typesize() const
00478 {
00479         return typesize((int) tag_type);
00480 }
00481 
00482 size_t TagData::typesize(int t) const
00483 {
00484         size_t size = 0;
00485         Type type = static_cast < Type > (t);
00486 
00487         switch (type) {
00488         case SHORT:
00489                 size = sizeof(short);
00490                 break;
00491         case USHORT:
00492                 size = sizeof(unsigned short);
00493                 break;
00494         case INT:
00495                 size = sizeof(int);
00496                 break;
00497         case UINT:
00498                 size = sizeof(unsigned int);
00499                 break;
00500         case FLOAT:
00501                 size = sizeof(float);
00502                 break;
00503         case DOUBLE:
00504                 size = sizeof(double);
00505                 break;
00506         case BOOLEAN:
00507                 size = sizeof(bool);
00508                 break;
00509         case CHAR:
00510         case OCTET:
00511                 size = sizeof(char);
00512                 break;
00513         default:
00514                 LOGERR("no such type: '%d'\n", type);
00515                 break;
00516         }
00517 
00518         return size;
00519 }
00520 
00522 
00523 TagGroup::TagGroup(FILE * data_file, TagTable * table, const string & groupname)
00524         :       in(data_file), tagtable(table), name(groupname), entry_id(0)
00525 {
00526 }
00527 
00528 TagGroup::~TagGroup()
00529 {
00530 }
00531 
00532 int TagGroup::read(bool nodata)
00533 {
00534         LOGVAR("TagGroup::read()");
00535 
00536         int ntags = 0;
00537         portable_fseek(in, sizeof(char) * 2, SEEK_CUR);
00538         
00539         size_t nr;
00540         nr = fread(&ntags, sizeof(ntags), 1, in);
00541         
00542         ByteOrder::become_big_endian(&ntags);
00543         
00544         LOGVAR("DM3: ntags = %d\n", ntags);
00545 
00546         int err = 0;
00547 
00548         for (int i = 0; i < ntags; i++) {
00549                 TagEntry tag_entry(in, tagtable, this);
00550                 err = tag_entry.read(nodata);
00551 
00552                 if (err) {
00553                         break;
00554                 }
00555         }
00556 
00557         return err;
00558 }
00559 
00560 string TagGroup::get_name() const
00561 {
00562         return name;
00563 }
00564 
00565 int TagGroup::get_entry_id()
00566 {
00567         int id = entry_id;
00568         entry_id++;
00569         return id;
00570 }
00571 
00573 
00574 TagEntry::TagEntry(FILE * data_file, TagTable * table, TagGroup * parent)
00575         :       in(data_file), tagtable(table), parent_group(parent), name("")
00576 {
00577 }
00578 
00579 TagEntry::~TagEntry()
00580 {
00581 }
00582 
00583 int TagEntry::read(bool nodata)
00584 {
00585         LOGVAR("TagEntry::read()");
00586         int err = 0;
00587         char tag_type = 0;
00588         char *tmp_name = 0;
00589 
00590         size_t nr;
00591         nr = fread(&tag_type, sizeof(char), 1, in);
00592 
00593         if (tag_type != GROUP_TAG && tag_type != DATA_TAG) {
00594                 LOGERR("TagEntry::read() invalid tag type: %d", tag_type);
00595                 return 1;
00596         }
00597 
00598         short name_len = 0;
00599         nr = fread(&name_len, sizeof(short), 1, in);
00600         ByteOrder::become_big_endian(&name_len);
00601 
00602         if (name_len != 0) {
00603                 tmp_name = new char[name_len + 1];
00604                 nr = fread(tmp_name, name_len, 1, in);
00605                 tmp_name[name_len] = '\0';
00606         }
00607         else {
00608                 string parent_name = parent_group->get_name();
00609                 name_len = static_cast < short >(parent_name.size() + 4);
00610                 tmp_name = new char[name_len + 1];
00611                 sprintf(tmp_name, "%s #%d", parent_name.c_str(), parent_group->get_entry_id());
00612         }
00613 
00614         name = string(tmp_name);
00615 
00616         if (tmp_name) {
00617                 delete [] tmp_name;
00618                 tmp_name = 0;
00619         }
00620 
00621         LOGVAR("\ntag name: '%s', len: %d, type: '%s'",
00622                    name.c_str(), name_len, Gatan::to_str((EntryType) tag_type));
00623 
00624         if (tag_type == DATA_TAG) {
00625                 TagData tag_data(in, tagtable, name);
00626                 err = tag_data.read(nodata);
00627         }
00628         else if (tag_type == GROUP_TAG) {
00629                 TagGroup group(in, tagtable, name);
00630                 err = group.read(nodata);
00631         }
00632 
00633         return err;
00634 }
00635 
00637 
00638 DM3IO::DM3IO(const string & dm3_filename, IOMode rw)
00639         :       filename(dm3_filename), rw_mode(rw), dm3file(0), initialized(false)
00640 {
00641         is_big_endian = ByteOrder::is_host_big_endian();
00642         tagtable = new TagTable();
00643 }
00644 
00645 DM3IO::~DM3IO()
00646 {
00647         if (dm3file) {
00648                 fclose(dm3file);
00649                 dm3file = 0;
00650         }
00651         if (tagtable) {
00652                 delete tagtable;
00653                 tagtable = 0;
00654         }
00655 }
00656 
00657 void DM3IO::init()
00658 {
00659         ENTERFUNC;
00660         if (initialized) {
00661                 return;
00662         }
00663         initialized = true;
00664 
00665         if (rw_mode != READ_ONLY) {
00666                 throw ImageReadException(filename, "only support DM3 read-only");
00667         }
00668 
00669         dm3file = sfopen(filename, READ_ONLY);
00670 
00671         int buf[NUM_ID_INT];
00672         if (fread(buf, sizeof(buf), 1, dm3file) != 1) {
00673                 throw ImageReadException(filename, "read first block of DM3 file");
00674         }
00675 
00676         if (!is_valid(&buf)) {
00677                 throw ImageReadException(filename, "invalid DM3 file");
00678         }
00679 
00680         int byte_order = buf[2];
00681 
00682         if (byte_order == 0) {
00683                 is_big_endian = true;
00684         }
00685         else {
00686                 is_big_endian = false;
00687         }
00688 
00689         tagtable->set_endian(is_big_endian);
00690         ByteOrder::become_big_endian(buf, 3);
00691 
00692         LOGDEBUG("dm3 ver = %d, image size = %d, is_big_endian = %d",
00693                          buf[0], buf[1], (int) is_big_endian);
00694 
00695         EXITFUNC;
00696 }
00697 
00698 bool DM3IO::is_valid(const void *first_block)
00699 {
00700         ENTERFUNC;
00701 
00702         if (!first_block) {
00703                 return false;
00704         }
00705 
00706         const int *data = static_cast < const int *>(first_block);
00707 
00708         int img_ver = data[0];
00709         int img_size = data[1];
00710         int byte_order = data[2];
00711 
00712         ByteOrder::become_big_endian(&img_ver);
00713 
00714         if (img_ver != 3) {
00715                 return false;
00716         }
00717 
00718         ByteOrder::become_big_endian(&img_size);
00719         ByteOrder::become_big_endian(&byte_order);
00720 
00721         if (byte_order != 0 && byte_order != 1) {
00722                 return false;
00723         }
00724 
00725         return true;
00726 }
00727 
00728 bool DM3IO::is_image_big_endian()
00729 {
00730         init();
00731         return is_big_endian;
00732 }
00733 
00734 int DM3IO::read_header(Dict & dict, int image_index, const Region * area, bool)
00735 {
00736         ENTERFUNC;
00737         int err = 0;
00738 
00739         //single image format, index can only be zero
00740         if(image_index == -1) {
00741                 image_index = 0;
00742         }
00743         image_index = 0;
00744         check_read_access(image_index);
00745 
00746         portable_fseek(dm3file, NUM_ID_INT * sizeof(int), SEEK_SET);
00747         TagGroup root_group(dm3file, tagtable, "");
00748         root_group.read(true);
00749 
00750         int nx = tagtable->get_xsize();
00751         int ny = tagtable->get_ysize();
00752 
00753         check_region(area, IntSize(nx, ny));
00754         int xlen = 0, ylen = 0;
00755         EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen);
00756 
00757         dict["nx"] = xlen;
00758         dict["ny"] = ylen;
00759         dict["nz"] = 1;
00760 
00761         dict["DM3.acq_date"] = tagtable->get_string("Acquisition Date");
00762         dict["DM3.acq_time"] = tagtable->get_string("Acquisition Time");
00763         dict["DM3.source"] = tagtable->get_string("Source");
00764         dict["DM3.exposure_number"] = tagtable->get_int("Exposure Number");
00765         dict["DM3.exposure_time"] = tagtable->get_double("Exposure (s)");
00766         dict["DM3.zoom"] = tagtable->get_double("Zoom");
00767         dict["DM3.antiblooming"] = tagtable->get_int("Antiblooming");
00768         dict["DM3.indicated_mag"] = tagtable->get_double("Indicated Magnification");
00769         dict["DM3.actual_mag"] = tagtable->get_double("Actual Magnification");
00770         dict["DM3.pixel_size"] = tagtable->get_double("Pixel Size (um) #0");
00771         dict["DM3.name"] = tagtable->get_string("Name");
00772 
00773         dict["DM3.voltage"] = tagtable->get_double("Voltage")/1000.0;
00774         dict["microscope_voltage"]=(float)dict["DM3.voltage"];
00775         dict["DM3.cs"] = tagtable->get_double("Cs(mm)");
00776         dict["microscope_cs"]=(float)dict["DM3.cs"];
00777 
00778         dict["DM3.frame_type"] = tagtable->get_string("Processing");
00779         dict["DM3.camera_x"] = tagtable->get_int("Active Size (pixels) #0");
00780         dict["DM3.camera_y"] = tagtable->get_int("Active Size (pixels) #1");
00781         dict["DM3.binning_x"] = tagtable->get_int("Binning #0");
00782         dict["DM3.binning_y"] = tagtable->get_int("Binning #1");
00783         dict["datatype"] = to_em_datatype(tagtable->get_datatype());
00784 
00785         if ((float)dict["DM3.actual_mag"] >0.0) {
00786                 float apix=10000.0*(float)dict["DM3.pixel_size"]/(float)dict["DM3.actual_mag"];
00787                 dict["apix_x"]=apix;
00788                 dict["apix_y"]=apix;
00789                 dict["apix_z"]=apix;
00790         }
00791 
00792 //      tagtable->dump();
00793 
00794         EXITFUNC;
00795         return err;
00796 }
00797 
00798 int DM3IO::read_data(float *rdata, int image_index, const Region * area, bool)
00799 {
00800         ENTERFUNC;
00801         //single image format, index can only be zero
00802         image_index = 0;
00803         check_read_access(image_index, rdata);
00804 
00805         portable_fseek(dm3file, NUM_ID_INT * sizeof(int), SEEK_SET);
00806 
00807         TagGroup root_group(dm3file, tagtable, "");
00808         root_group.read(false);
00809         
00810         int nx = tagtable->get_xsize();
00811         int ny = tagtable->get_ysize();
00812 
00813         check_region(area, IntSize(nx, ny));
00814 
00815         int xlen = 0, ylen = 0, x0 = 0, y0 = 0;
00816         EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen);
00817         EMUtil::get_region_origins(area, &x0, &y0);
00818 
00819         char *data = tagtable->get_data();
00820         int data_type = tagtable->get_datatype();
00821 
00822         int k = 0;
00823         int off = 0;
00824         int xlast = x0 + xlen;
00825         int ylast = y0 + ylen;
00826 
00827 //      bool flip_vertical = (getenv ("FLIP_VERTICAL") != NULL);
00828         bool flip_vertical = true;
00829         
00830         for (int iy = y0; iy < ylast; iy++) {
00831                 if (flip_vertical) {
00832                         off = (y0 + ylast - 1 - iy) * nx;
00833                 }
00834                 else {
00835                         off = iy * nx;
00836                 }
00837 
00838                 for (int ix = x0; ix < xlast; ix++) {
00839                         switch (data_type) {
00840                         case Gatan::DataType::SIGNED_INT8_DATA:
00841                                 rdata[k] = (float) ((char *) data)[off + ix];
00842                                 break;
00843                         case Gatan::DataType::UNSIGNED_INT8_DATA:
00844                                 rdata[k] = (float) ((unsigned char *) data)[off + ix];
00845                                 break;
00846                         case Gatan::DataType::SIGNED_INT16_DATA:
00847                                 rdata[k] = (float) ((short *) data)[off + ix];
00848                                 break;
00849                         case Gatan::DataType::UNSIGNED_INT16_DATA:
00850                                 rdata[k] = (float) ((unsigned short *) data)[off + ix];
00851                                 break;
00852                         case Gatan::DataType::SIGNED_INT32_DATA:
00853                                 rdata[k] = (float) ((int *) data)[off + ix];
00854                                 break;
00855                         case Gatan::DataType::UNSIGNED_INT32_DATA:
00856                                 rdata[k] = (float) ((unsigned int *) data)[off + ix];
00857                                 break;
00858                         case Gatan::DataType::REAL4_DATA:
00859                                 rdata[k] = (float) ((float *) data)[off + ix];
00860                                 break;
00861                         default:
00862                                 string desc = string("unsupported DM3 data type") +
00863                                         string(Gatan::to_str((Gatan::DataType::GatanDataType) data_type));
00864                                 throw ImageReadException(filename, desc);
00865                         }
00866                         k++;
00867                 }
00868         }
00869         EXITFUNC;
00870         return 0;
00871 }
00872 
00873 bool DM3IO::is_complex_mode()
00874 {
00875         return false;
00876 }
00877 
00878 int DM3IO::write_header(const Dict &, int, const Region* , EMUtil::EMDataType, bool)
00879 {
00880         ENTERFUNC;
00881         LOGWARN("DM3 write is not supported.");
00882         EXITFUNC;
00883         return 1;
00884 }
00885 
00886 int DM3IO::write_data(float *, int, const Region* , EMUtil::EMDataType, bool)
00887 {
00888         ENTERFUNC;
00889         LOGWARN("DM3 write is not supported.");
00890         EXITFUNC;
00891         return 1;
00892 }
00893 
00894 void DM3IO::flush()
00895 {
00896 }
00897 
00898 int Gatan::to_em_datatype(int gatan_datatype)
00899 {
00900         DataType::GatanDataType type = static_cast < DataType::GatanDataType > (gatan_datatype);
00901         int t = 0;
00902 
00903         switch (type) {
00904         case Gatan::DataType::SIGNED_INT8_DATA:
00905                 t = EMUtil::EM_CHAR;
00906                 break;
00907         case Gatan::DataType::UNSIGNED_INT8_DATA:
00908                 t = EMUtil::EM_UCHAR;
00909                 break;
00910         case Gatan::DataType::SIGNED_INT16_DATA:
00911                 t = EMUtil::EM_SHORT;
00912                 break;
00913         case Gatan::DataType::UNSIGNED_INT16_DATA:
00914                 t = EMUtil::EM_USHORT;
00915                 break;
00916         case Gatan::DataType::SIGNED_INT32_DATA:
00917                 t = EMUtil::EM_INT;
00918                 break;
00919         case Gatan::DataType::UNSIGNED_INT32_DATA:
00920                 t = EMUtil::EM_UINT;
00921                 break;
00922         default:
00923                 t = EMUtil::EM_UNKNOWN;
00924         }
00925 
00926         return t;
00927 }
00928 
00929 const char *Gatan::to_str(TagData::Type type)
00930 {
00931         const char *str = "unknown";
00932 
00933         switch (type) {
00934         case TagData::SHORT:
00935                 str = "short";
00936                 break;
00937         case TagData::INT:
00938                 str = "int";
00939                 break;
00940         case TagData::USHORT:
00941                 str = "unsigned short";
00942                 break;
00943         case TagData::UINT:
00944                 str = "unsigned int";
00945                 break;
00946         case TagData::FLOAT:
00947                 str = "float";
00948                 break;
00949         case TagData::DOUBLE:
00950                 str = "double";
00951                 break;
00952         case TagData::BOOLEAN:
00953                 str = "boolean";
00954                 break;
00955         case TagData::CHAR:
00956                 str = "char";
00957                 break;
00958         case TagData::OCTET:
00959                 str = "octet";
00960                 break;
00961         case TagData::STRUCT:
00962                 str = "struct";
00963                 break;
00964         case TagData::STRING:
00965                 str = "string";
00966                 break;
00967         case TagData::ARRAY:
00968                 str = "array";
00969                 break;
00970         default:
00971                 str = "unknown";
00972         }
00973         return str;
00974 }
00975 
00976 const char *Gatan::to_str(TagEntry::EntryType type)
00977 {
00978         const char *str = "unknown";
00979 
00980         switch (type) {
00981         case TagEntry::GROUP_TAG:
00982                 str = "Group";
00983                 break;
00984         case TagEntry::DATA_TAG:
00985                 str = "Data";
00986                 break;
00987         default:
00988                 str = "unknown";
00989         }
00990         return str;
00991 }
00992 
00993 const char *Gatan::to_str(Gatan::DataType::GatanDataType type)
00994 {
00995         switch (type) {
00996         case Gatan::DataType::SIGNED_INT16_DATA:
00997                 return "SIGNED_INT16_DATA";
00998         case Gatan::DataType::REAL4_DATA:
00999                 return "REAL4_DATA";
01000         case Gatan::DataType::COMPLEX8_DATA:
01001                 return "COMPLEX8_DATA";
01002         case Gatan::DataType::OBSELETE_DATA:
01003                 return "OBSELETE_DATA";
01004         case Gatan::DataType::PACKED_DATA:
01005                 return "PACKED_DATA";
01006         case Gatan::DataType::UNSIGNED_INT8_DATA:
01007                 return "UNSIGNED_INT8_DATA";
01008         case Gatan::DataType::SIGNED_INT32_DATA:
01009                 return "SIGNED_INT32_DATA";
01010         case Gatan::DataType::RGB_DATA:
01011                 return "RGB_DATA";
01012         case Gatan::DataType::SIGNED_INT8_DATA:
01013                 return "SIGNED_INT8_DATA";
01014         case Gatan::DataType::UNSIGNED_INT16_DATA:
01015                 return "UNSIGNED_INT16_DATA";
01016         case Gatan::DataType::UNSIGNED_INT32_DATA:
01017                 return "UNSIGNED_INT32_DATA";
01018         case Gatan::DataType::REAL8_DATA:
01019                 return "REAL8_DATA";
01020         case Gatan::DataType::COMPLEX16_DATA:
01021                 return "COMPLEX16_DATA";
01022         case Gatan::DataType::BINARY_DATA:
01023                 return "BINARY_DATA";
01024         case Gatan::DataType::RGB_UINT8_0_DATA:
01025                 return "RGB_UINT8_0_DATA";
01026         case Gatan::DataType::RGB_UINT8_1_DATA:
01027                 return "RGB_UINT8_1_DATA";
01028         case Gatan::DataType::RGB_UINT16_DATA:
01029                 return "RGB_UINT16_DATA";
01030         case Gatan::DataType::RGB_FLOAT32_DATA:
01031                 return "RGB_FLOAT32_DATA";
01032         case Gatan::DataType::RGB_FLOAT64_DATA:
01033                 return "RGB_FLOAT64_DATA";
01034         case Gatan::DataType::RGBA_UINT8_0_DATA:
01035                 return "RGBA_UINT8_0_DATA";
01036         case Gatan::DataType::RGBA_UINT8_1_DATA:
01037                 return "RGBA_UINT8_1_DATA";
01038         case Gatan::DataType::RGBA_UINT8_2_DATA:
01039                 return "RGBA_UINT8_2_DATA";
01040         case Gatan::DataType::RGBA_UINT8_3_DATA:
01041                 return "RGBA_UINT8_3_DATA";
01042         case Gatan::DataType::RGBA_UINT16_DATA:
01043                 return "RGBA_UINT16_DATA";
01044         case Gatan::DataType::RGBA_FLOAT32_DATA:
01045                 return "RGBA_FLOAT32_DATA";
01046         case Gatan::DataType::RGBA_FLOAT64_DATA:
01047                 return "RGBA_FLOAT64_DATA";
01048         case Gatan::DataType::POINT2_SINT16_0_DATA:
01049                 return "POINT2_SINT16_0_DATA";
01050         case Gatan::DataType::POINT2_SINT16_1_DATA:
01051                 return "POINT2_SINT16_1_DATA";
01052         case Gatan::DataType::POINT2_SINT32_0_DATA:
01053                 return "POINT2_SINT32_0_DATA";
01054         case Gatan::DataType::POINT2_FLOAT32_0_DATA:
01055                 return "POINT2_FLOAT32_0_DATA";
01056         case Gatan::DataType::RECT_SINT16_1_DATA:
01057                 return "RECT_SINT16_1_DATA";
01058         case Gatan::DataType::RECT_SINT32_1_DATA:
01059                 return "RECT_SINT32_1_DATA";
01060         case Gatan::DataType::RECT_FLOAT32_1_DATA:
01061                 return "RECT_FLOAT32_1_DATA";
01062         case Gatan::DataType::RECT_FLOAT32_0_DATA:
01063                 return "RECT_FLOAT32_0_DATA";
01064         case Gatan::DataType::SIGNED_INT64_DATA:
01065                 return "SIGNED_INT64_DATA";
01066         case Gatan::DataType::UNSIGNED_INT64_DATA:
01067                 return "UNSIGNED_INT64_DATA";
01068         default:
01069                 break;
01070         }
01071         return "Unknown Type";
01072 }