00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <cstring>
00037 #include "imagicio.h"
00038 #include "portable_fileio.h"
00039 #include "util.h"
00040 #include "geometry.h"
00041 #include "ctf.h"
00042 #include "emassert.h"
00043 #include "transform.h"
00044
00045 #ifdef _WIN32
00046 #include <ctime>
00047 #endif //_WIN32
00048
00049 using namespace EMAN;
00050
00051 const char *ImagicIO::HED_EXT = "hed";
00052 const char *ImagicIO::IMG_EXT = "img";
00053 const char *ImagicIO::REAL_TYPE_MAGIC = "REAL";
00054 const char *ImagicIO::CTF_MAGIC = "!-";
00055
00056 ImagicIO2::ImagicIO2(string file, IOMode rw)
00057 : filename(file), rw_mode(rw), hed_file(0), img_file(0), initialized(false)
00058 {
00059 hed_filename = Util::change_filename_ext(filename, HED_EXT);
00060 img_filename = Util::change_filename_ext(filename, IMG_EXT);
00061
00062 is_big_endian = ByteOrder::is_host_big_endian();
00063 is_new_hed = false;
00064 is_new_img = false;
00065 memset(&imagich, 0, sizeof(Imagic4D));
00066 imagich.count = -1;
00067 datatype = IMAGIC_UNKNOWN_TYPE;
00068 nz = 0;
00069 }
00070
00071 ImagicIO2::~ImagicIO2()
00072 {
00073 if (hed_file) {
00074 fclose(hed_file);
00075 hed_file = 0;
00076 }
00077
00078 if (img_file) {
00079 fclose(img_file);
00080 img_file = 0;
00081 }
00082 }
00083
00084 void ImagicIO2::init()
00085 {
00086 ENTERFUNC;
00087
00088 if (initialized) {
00089 return;
00090 }
00091
00092 initialized = true;
00093
00094 is_new_hed = false;
00095 is_new_img = false;
00096
00097 hed_file = sfopen(hed_filename, rw_mode, &is_new_hed);
00098 img_file = sfopen(img_filename, rw_mode, &is_new_img);
00099
00100 if (is_new_hed != is_new_img) {
00101 LOGWARN("IMAGIC header file and data file should both exist or both not exist");
00102 }
00103
00104 if (!is_new_hed) {
00105 if (fread(&imagich, sizeof(ImagicHeader), 1, hed_file) != 1) {
00106 throw ImageReadException(hed_filename, "IMAGIC header");
00107 }
00108
00109 if (!is_valid(&imagich)) {
00110 throw ImageReadException(hed_filename, "invalid IMAGIC file");
00111 }
00112
00113 datatype = get_datatype_from_name(imagich.type);
00114
00115 if (datatype != IMAGIC_USHORT && datatype != IMAGIC_FLOAT) {
00116 LOGERR("unsupported imagic data type: %s", imagich.type);
00117 throw ImageReadException(hed_filename, "unsupported imagic data type");
00118 }
00119
00120 is_big_endian = ByteOrder::is_data_big_endian(&imagich.ny);
00121 make_header_host_endian(imagich);
00122 rewind(hed_file);
00123 }
00124 EXITFUNC;
00125 }
00126
00127 bool ImagicIO2::is_valid(const void *first_block)
00128 {
00129 ENTERFUNC;
00130
00131 if (!first_block) {
00132 return false;
00133 }
00134
00135 const int *data = static_cast < const int *>(first_block);
00136 int count = data[1];
00137 int headrec = data[3];
00138 int month = data[4];
00139 int hour = data[7];
00140 int nx = data[13];
00141 int ny = data[12];
00142 int realtype = data[68];
00143
00144 bool data_big_endian = ByteOrder::is_data_big_endian(&headrec);
00145
00146 if (data_big_endian != ByteOrder::is_host_big_endian()) {
00147 ByteOrder::swap_bytes(&count);
00148 ByteOrder::swap_bytes(&headrec);
00149 ByteOrder::swap_bytes(&month);
00150 ByteOrder::swap_bytes(&hour);
00151 ByteOrder::swap_bytes(&nx);
00152 ByteOrder::swap_bytes(&ny);
00153 ByteOrder::swap_bytes(&realtype);
00154 }
00155
00156 const int max_dim = 1 << 20;
00157 bool result = false;
00158
00159
00160 if(realtype != VAX_VMS && realtype != LINUX_WINDOWS && realtype != SGI_IBM) {
00161 EXITFUNC;
00162 return result;
00163 }
00164
00165 if (headrec == 1 &&
00166 count >= 0 && count < max_dim &&
00167 nx > 0 && nx < max_dim &&
00168 ny > 0 && ny < max_dim &&
00169 month >= 0 && month <=12 &&
00170 hour >= 0 && hour <= 24) {
00171 result = true;
00172 }
00173
00174 EXITFUNC;
00175 return result;
00176 }
00177
00178 int ImagicIO2::read_header(Dict & dict, int image_index, const Region * area, bool)
00179 {
00180 ENTERFUNC;
00181
00182 check_read_access(image_index);
00183
00184 int nimg = 1;
00185
00186 Imagic4D hed;
00187 if (image_index == 0) {
00188 hed = imagich;
00189 }
00190 else {
00191 memset(&hed, 0, sizeof(Imagic4D));
00192 portable_fseek(hed_file, sizeof(Imagic5H) * image_index, SEEK_SET);
00193 fread(&hed, sizeof(Imagic4D), 1, hed_file);
00194 make_header_host_endian(hed);
00195 }
00196 check_region(area, FloatSize(hed.nx, hed.ny, nimg), is_new_hed, false);
00197
00198 datatype = get_datatype_from_name(imagich.type);
00199
00200 int xlen = 0, ylen = 0, zlen = 0;
00201 EMUtil::get_region_dims(area, hed.nx, &xlen, hed.ny, &ylen, hed.izlp, &zlen);
00202
00203 dict["nx"] = xlen;
00204 dict["ny"] = ylen;
00205 dict["nz"] = zlen;
00206
00207 dict["IMAGIC.imgnum"] = hed.imgnum;
00208 dict["IMAGIC.count"] = hed.count;
00209 dict["IMAGIC.error"] = hed.error;
00210
00211 dict["IMAGIC.month"] = hed.month;
00212 dict["IMAGIC.day"] = hed.mday;
00213 dict["IMAGIC.year"] = hed.year;
00214 dict["IMAGIC.hour"] = hed.hour;
00215 dict["IMAGIC.minute"] = hed.minute;
00216 dict["IMAGIC.sec"] = hed.sec;
00217
00218 dict["IMAGIC.reals"] = hed.reals;
00219 dict["IMAGIC.izold"] = hed.izold;
00220
00221 dict["datatype"] = to_em_datatype(hed.type);
00222
00223 dict["IMAGIC.ixold"] = hed.ixold;
00224 dict["IMAGIC.iyold"] = hed.iyold;
00225
00226 dict["mean"] = hed.avdens;
00227 dict["sigma"] = hed.sigma;
00228 dict["variance"] = hed.varia;
00229 dict["IMAGIC.oldav"] = hed.oldav;
00230 dict["maximum"] = hed.max;
00231 dict["minimum"] = hed.min;
00232
00233 dict["IMAGIC.cellx"] = hed.cellx;
00234 dict["IMAGIC.celly"] = hed.celly;
00235 dict["IMAGIC.cellz"] = hed.cellz;
00236 dict["IMAGIC.cell_alpha"] = hed.clpha;
00237 dict["IMAGIC.cell_beta"] = hed.cbeta;
00238 dict["IMAGIC.cell_gamma"] = hed.cgamma;
00239
00240 dict["IMAGIC.label"] = hed.label;
00241 dict["IMAGIC.mapc"] = hed.mapc;
00242 dict["IMAGIC.mapr"] = hed.mapr;
00243 dict["IMAGIC.maps"] = hed.maps;
00244
00245 dict["IMAGIC.ispg"] = hed.ispg;
00246 dict["IMAGIC.nxstart"] = hed.nxstart;
00247 dict["IMAGIC.nystart"] = hed.nystart;
00248 dict["IMAGIC.nzstart"] = hed.nzstart;
00249
00250 dict["IMAGIC.nxintv"] = hed.nxintv;
00251 dict["IMAGIC.nyintv"] = hed.nyintv;
00252 dict["IMAGIC.nzintv"] = hed.nzintv;
00253
00254 dict["IMAGIC.i4lp"] = hed.i4lp;
00255
00256
00257 char tmp[5] = { hed.type[0],hed.type[1],hed.type[2],hed.type[3],0 };
00258 dict["IMAGIC.type"] = tmp;
00259
00260
00261 dict["IMAGIC.oldav"] = hed.oldav;
00262
00263 dict["ptcl_repr"] = hed.mrc2;
00264
00265 dict["orientation_convention"] = "EMAN";
00266 const float alt = hed.mrc1[1]*180.0f/M_PI;
00267 const float az = hed.mrc1[2]*180.0f/M_PI;
00268 const float phi = hed.mrc1[0]*180.0f/M_PI;
00269 dict["euler_alt"] = alt;
00270 dict["euler_az"] = az;
00271 dict["euler_phi"] = phi;
00272 Transform *trans = new Transform();
00273 trans->set_rotation(Dict("type", "eman", "alt", alt, "az", az, "phi", phi));
00274 if( hed.count==0 ) {
00275 dict["xform.projection"] = trans;
00276 }
00277 else {
00278 dict["xform.projection"] = trans;
00279 dict["xform.align3d"] = trans;
00280 }
00281 Ctf * ctf_ = read_ctf(hed);
00282 if( ctf_ != 0) {
00283 dict["ctf"] = ctf_;
00284 }
00285 if(trans) {delete trans; trans=0;}
00286 if(ctf_) {delete ctf_; ctf_=0;}
00287 EXITFUNC;
00288 return 0;
00289 }
00290
00291 ImagicIO2::DataType ImagicIO2::get_datatype_from_name(const char *name)
00292 {
00293 DataType t = IMAGIC_UNKNOWN_TYPE;
00294
00295 if (strncmp(name, "PACK",4) == 0) {
00296 t = IMAGIC_CHAR;
00297 }
00298 else if (strncmp(name, "INTG",4) == 0) {
00299 t = IMAGIC_SHORT;
00300 }
00301 else if (strncmp(name, REAL_TYPE_MAGIC,4) == 0) {
00302 t = IMAGIC_FLOAT;
00303 }
00304 else if (strncmp(name, "COMP",4) == 0) {
00305 t = IMAGIC_FLOAT_COMPLEX;
00306 }
00307 else if (strncmp(name, "RECO",4) == 0) {
00308 t = IMAGIC_FFT_FLOAT_COMPLEX;
00309 }
00310 return t;
00311 }
00312
00313 int ImagicIO2::to_em_datatype(DataType t)
00314 {
00315 switch (t) {
00316 case IMAGIC_CHAR:
00317 return EMUtil::EM_CHAR;
00318 case IMAGIC_SHORT:
00319 return EMUtil::EM_SHORT;
00320 case IMAGIC_FLOAT:
00321 return EMUtil::EM_FLOAT;
00322 case IMAGIC_FLOAT_COMPLEX:
00323 case IMAGIC_FFT_FLOAT_COMPLEX:
00324 return EMUtil::EM_FLOAT_COMPLEX;
00325 default:
00326 break;
00327 }
00328
00329 return EMUtil::EM_UNKNOWN;
00330 }
00331
00332 Ctf * ImagicIO2::read_ctf(const Imagic5H& hed) const
00333 {
00334 ENTERFUNC;
00335
00336 Ctf * ctf_ = 0;
00337 size_t n = strlen(CTF_MAGIC);
00338
00339 if (strncmp(imagich.label, CTF_MAGIC, n) == 0) {
00340 ctf_ = new EMAN1Ctf();
00341 string header_label(hed.label);
00342
00343
00344 if (header_label.size() > 2) {
00345 string sctf = "O" + header_label.substr(2);
00346 ctf_->from_string(sctf);
00347 }
00348 }
00349
00350 EXITFUNC;
00351 return ctf_;
00352 }
00353
00354 void ImagicIO2::write_ctf(const Ctf * const ctf, int image_index)
00355 {
00356 ENTERFUNC;
00357 init();
00358
00359 size_t n = strlen(CTF_MAGIC);
00360 strcpy(imagich.label, CTF_MAGIC);
00361 string ctf_ = ctf->to_string().substr(1);
00362 strncpy(&imagich.label[n], ctf_.c_str(), sizeof(imagich.label) - n);
00363
00364 rewind(hed_file);
00365 if (fwrite(&imagich, sizeof(ImagicHeader), 1, hed_file) != 1) {
00366 throw ImageWriteException(hed_filename, "Imagic Header");
00367 }
00368
00369 EXITFUNC;
00370 }