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 <climits>
00038
00039 #include "mrcio.h"
00040 #include "portable_fileio.h"
00041 #include "geometry.h"
00042 #include "util.h"
00043 #include "ctf.h"
00044 #include "transform.h"
00045
00046 using namespace EMAN;
00047
00048 const char *MrcIO::CTF_MAGIC = "!-";
00049 const char *MrcIO::SHORT_CTF_MAGIC = "!$";
00050
00051 MrcIO::MrcIO(const string & mrc_filename, IOMode rw)
00052 : filename(mrc_filename), rw_mode(rw), mrcfile(0), mode_size(0)
00053 {
00054 memset(&mrch, 0, sizeof(MrcHeader));
00055 is_ri = 0;
00056 is_big_endian = ByteOrder::is_host_big_endian();
00057 is_new_file = false;
00058 initialized = false;
00059 }
00060
00061 MrcIO::~MrcIO()
00062 {
00063 if (mrcfile) {
00064 fclose(mrcfile);
00065 mrcfile = 0;
00066 }
00067 }
00068
00069 void MrcIO::init()
00070 {
00071 ENTERFUNC;
00072
00073 if (initialized) {
00074 return;
00075 }
00076
00077 initialized = true;
00078 mrcfile = sfopen(filename, rw_mode, &is_new_file);
00079
00080 if (!is_new_file) {
00081 if (fread(&mrch, sizeof(MrcHeader), 1, mrcfile) != 1) {
00082 throw ImageReadException(filename, "MRC header");
00083 }
00084
00085 if (!is_valid(&mrch)) {
00086 throw ImageReadException(filename, "invalid MRC");
00087 }
00088
00089 is_big_endian = ByteOrder::is_data_big_endian(&mrch.nz);
00090 if (is_big_endian != ByteOrder::is_host_big_endian()) {
00091 swap_header(mrch);
00092 }
00093
00094
00095 mode_size = get_mode_size(mrch.mode);
00096 if(is_complex_mode()) {
00097 is_ri = 1;
00098 }
00099
00100 if (mrch.nxstart != 0 || mrch.nystart != 0 || mrch.nzstart != 0) {
00101 LOGWARN("nx/ny/nz start not zero");
00102 }
00103
00104 if (is_complex_mode()) {
00105 mrch.nx *= 2;
00106 }
00107
00108 if (mrch.xlen == 0) {
00109 mrch.xlen = 1.0;
00110 }
00111
00112 if (mrch.ylen == 0) {
00113 mrch.ylen = 1.0;
00114 }
00115
00116 if (mrch.zlen == 0) {
00117 mrch.zlen = 1.0;
00118 }
00119 }
00120 EXITFUNC;
00121 }
00122
00123
00124 bool MrcIO::is_image_big_endian()
00125 {
00126 init();
00127 return is_big_endian;
00128 }
00129
00130 bool MrcIO::is_valid(const void *first_block, off_t file_size)
00131 {
00132 ENTERFUNC;
00133
00134 if (!first_block) {
00135 return false;
00136 }
00137
00138 const int *data = static_cast < const int *>(first_block);
00139 int nx = data[0];
00140 int ny = data[1];
00141 int nz = data[2];
00142 int mrcmode = data[3];
00143 int nsymbt = data[23];
00144
00145 bool data_big_endian = ByteOrder::is_data_big_endian(&nz);
00146
00147 if (data_big_endian != ByteOrder::is_host_big_endian()) {
00148 ByteOrder::swap_bytes(&nx);
00149 ByteOrder::swap_bytes(&ny);
00150 ByteOrder::swap_bytes(&nz);
00151 ByteOrder::swap_bytes(&mrcmode);
00152 ByteOrder::swap_bytes(&nsymbt);
00153 }
00154
00155 if (mrcmode == MRC_SHORT_COMPLEX || mrcmode == MRC_FLOAT_COMPLEX) {
00156 nx *= 2;
00157 }
00158
00159 const int max_dim = 1 << 20;
00160
00161 if ((mrcmode >= MRC_UCHAR && mrcmode < MRC_UNKNOWN) &&
00162 (nx > 1 && nx < max_dim) && (ny > 0 && ny < max_dim) && (nz > 0 && nz < max_dim)) {
00163
00164 if (file_size > 0) {
00165 off_t file_size1 = (off_t)nx * (off_t)ny * (off_t)nz * (off_t)get_mode_size(mrcmode) + (off_t)sizeof(MrcHeader) + nsymbt;
00166 if (file_size == file_size1) {
00167 return true;
00168 }
00169
00170 LOGWARN("image size check fails, still try to read it...");
00171 }
00172 else {
00173 return true;
00174 }
00175
00176 return true;
00177 }
00178 EXITFUNC;
00179 return false;
00180 }
00181
00182 int MrcIO::read_header(Dict & dict, int image_index, const Region * area, bool )
00183 {
00184 ENTERFUNC;
00185
00186
00187 if(image_index == -1) {
00188 image_index = 0;
00189 }
00190 if(image_index != 0) {
00191 throw ImageReadException(filename, "no stack allowed for MRC image. For take 2D slice out of 3D image, read the 3D image first, then use get_clip().");
00192 }
00193
00194 init();
00195
00196 check_region(area, FloatSize(mrch.nx, mrch.ny, mrch.nz), is_new_file,false);
00197
00198 dict["apix_x"] = mrch.xlen / mrch.mx;
00199 dict["apix_y"] = mrch.ylen / mrch.my;
00200 dict["apix_z"] = mrch.zlen / mrch.mz;
00201
00202 dict["MRC.minimum"] = mrch.amin;
00203 dict["MRC.maximum"] = mrch.amax;
00204 dict["MRC.mean"] = mrch.amean;
00205 dict["mean"] = mrch.amean;
00206 dict["datatype"] = to_em_datatype(mrch.mode);
00207
00208 if (is_complex_mode()) {
00209 dict["is_complex"] = 1;
00210 dict["is_complex_ri"] = 1;
00211 }
00212
00213 int xlen = 0, ylen = 0, zlen = 0;
00214 EMUtil::get_region_dims(area, mrch.nx, &xlen, mrch.ny, &ylen, mrch.nz, &zlen);
00215
00216 dict["nx"] = xlen;
00217 dict["ny"] = ylen;
00218 dict["nz"] = zlen;
00219
00220 if (area) {
00221 dict["origin_x"] = mrch.xorigin + mrch.xlen * area->origin[0];
00222 dict["origin_y"] = mrch.yorigin + mrch.xlen * area->origin[1];
00223
00224 if (area->get_ndim() == 3 && mrch.nz > 1) {
00225 dict["origin_z"] = mrch.zorigin + mrch.xlen * area->origin[2];
00226 }
00227 else {
00228 dict["origin_z"] = mrch.zorigin;
00229 }
00230 }
00231 else {
00232 dict["origin_x"] = mrch.xorigin;
00233 dict["origin_y"] = mrch.yorigin;
00234 dict["origin_z"] = mrch.zorigin;
00235 }
00236
00237 dict["MRC.nxstart"] = mrch.nxstart;
00238 dict["MRC.nystart"] = mrch.nystart;
00239 dict["MRC.nzstart"] = mrch.nzstart;
00240
00241 dict["MRC.mx"] = mrch.mx;
00242 dict["MRC.my"] = mrch.my;
00243 dict["MRC.mz"] = mrch.mz;
00244
00245 dict["MRC.nx"] = mrch.nx;
00246 dict["MRC.ny"] = mrch.ny;
00247 dict["MRC.nz"] = mrch.nz;
00248
00249 dict["MRC.xlen"] = mrch.xlen;
00250 dict["MRC.ylen"] = mrch.ylen;
00251 dict["MRC.zlen"] = mrch.zlen;
00252
00253 dict["MRC.alpha"] = mrch.alpha;
00254 dict["MRC.beta"] = mrch.beta;
00255 dict["MRC.gamma"] = mrch.gamma;
00256
00257 dict["MRC.mapc"] = mrch.mapc;
00258 dict["MRC.mapr"] = mrch.mapr;
00259 dict["MRC.maps"] = mrch.maps;
00260
00261 dict["MRC.ispg"] = mrch.ispg;
00262 dict["MRC.nsymbt"] = mrch.nsymbt;
00263 dict["MRC.machinestamp"] = mrch.machinestamp;
00264
00265 dict["MRC.rms"] = mrch.rms;
00266 dict["sigma"] = mrch.rms;
00267 dict["MRC.nlabels"] = mrch.nlabels;
00268 for (int i = 0; i < mrch.nlabels; i++) {
00269 char label[32];
00270 sprintf(label, "MRC.label%d", i);
00271 dict[string(label)] = mrch.labels[i];
00272 }
00273
00274 EMAN1Ctf ctf_;
00275 if(read_ctf(ctf_) == 0) {
00276 vector<float> vctf = ctf_.to_vector();
00277 dict["ctf"] = vctf;
00278 }
00279
00280 Dict dic;
00281 dic.put("type", "imagic");
00282 dic.put("alpha", mrch.alpha);
00283 dic.put("beta", mrch.beta);
00284 dic.put("gamma", mrch.gamma);
00285 dic.put("tx", mrch.xorigin);
00286 dic.put("ty", mrch.yorigin);
00287 dic.put("tz", mrch.zorigin);
00288 Transform * trans = new Transform(dic);
00289 if(zlen<=1) {
00290 dict["xform.projection"] = trans;
00291 }
00292 else {
00293 dict["xform.align3d"] = trans;
00294 }
00295
00296 if(trans) {delete trans; trans=0;}
00297 EXITFUNC;
00298 return 0;
00299 }
00300
00301 int MrcIO::write_header(const Dict & dict, int image_index, const Region* area,
00302 EMUtil::EMDataType filestoragetype, bool use_host_endian)
00303 {
00304 ENTERFUNC;
00305
00306
00307 if(image_index == -1) {
00308 image_index = 0;
00309 }
00310 if(image_index != 0) {
00311 throw ImageWriteException(filename, "MRC file does not support stack.");
00312 }
00313 check_write_access(rw_mode, image_index, 1);
00314 if (area) {
00315 check_region(area, FloatSize(mrch.nx, mrch.ny, mrch.nz), is_new_file);
00316 EXITFUNC;
00317 return 0;
00318 }
00319
00320 int new_mode = to_mrcmode(filestoragetype, (int) dict["is_complex"]);
00321 int nx = dict["nx"];
00322 int ny = dict["ny"];
00323 int nz = dict["nz"];
00324 is_ri = dict["is_complex_ri"];
00325
00326 bool opposite_endian = false;
00327
00328 if (!is_new_file) {
00329 if (is_big_endian != ByteOrder::is_host_big_endian()) {
00330 opposite_endian = true;
00331 }
00332 #if 0
00333 if (new_mode != mrch.mode) {
00334 LOGERR("cannot write to different mode file %s", filename.c_str());
00335 return 1;
00336 }
00337 #endif
00338 portable_fseek(mrcfile, 0, SEEK_SET);
00339 }
00340 else {
00341 mrch.alpha = mrch.beta = mrch.gamma = 90.0f;
00342 mrch.mapc = 1;
00343 mrch.mapr = 2;
00344 mrch.maps = 3;
00345 mrch.nxstart = mrch.nystart = mrch.nzstart = 0;
00346 }
00347
00348 if(nz<=1 && dict.has_key("xform.projection") && !dict.has_key("UCSF.chimera")) {
00349 Transform * t = dict["xform.projection"];
00350 Dict d = t->get_params("imagic");
00351 mrch.alpha = d["alpha"];
00352 mrch.beta = d["beta"];
00353 mrch.gamma = d["gamma"];
00354 mrch.xorigin = d["tx"];
00355 mrch.yorigin = d["ty"];
00356 mrch.zorigin = d["tz"];
00357 if(t) {delete t; t=0;}
00358 }
00359 else if(nz>1 && dict.has_key("xform.align3d") && !dict.has_key("UCSF.chimera")) {
00360 Transform * t = dict["xform.align3d"];
00361 Dict d = t->get_params("imagic");
00362 mrch.alpha = d["alpha"];
00363 mrch.beta = d["beta"];
00364 mrch.gamma = d["gamma"];
00365 mrch.xorigin = d["tx"];
00366 mrch.yorigin = d["ty"];
00367 mrch.zorigin = d["tz"];
00368 if(t) {delete t; t=0;}
00369 }
00370
00371 if(dict.has_key("origin_x") && dict.has_key("origin_y") && dict.has_key("origin_z")){
00372 mrch.xorigin = (float)dict["origin_x"];
00373 mrch.yorigin = (float)dict["origin_y"];
00374
00375 if (is_new_file) {
00376 mrch.zorigin = (float)dict["origin_z"];
00377 }
00378 else {
00379 mrch.zorigin = (float) dict["origin_z"] - (float) dict["apix_z"] * image_index;
00380 }
00381 }
00382
00383 if (dict.has_key("MRC.nlabels")) {
00384 mrch.nlabels = dict["MRC.nlabels"];
00385 }
00386
00387 for (int i = 0; i < MRC_NUM_LABELS; i++) {
00388 char label[32];
00389 sprintf(label, "MRC.label%d", i);
00390 if (dict.has_key(label)) {
00391 sprintf(&mrch.labels[i][0], "%s", (const char *) dict[label]);
00392 mrch.nlabels = i + 1;
00393 }
00394 }
00395
00396 if (mrch.nlabels < (MRC_NUM_LABELS - 1)) {
00397 sprintf(&mrch.labels[mrch.nlabels][0], "EMAN %s", Util::get_time_label().c_str());
00398 mrch.nlabels++;
00399 }
00400
00401 mrch.labels[mrch.nlabels][0] = '\0';
00402 mrch.mode = new_mode;
00403
00404 if (is_complex_mode()) {
00405 mrch.nx = nx / 2;
00406 }
00407 else {
00408 mrch.nx = nx;
00409 }
00410 mrch.ny = ny;
00411
00412 if (is_new_file) {
00413 mrch.nz = nz;
00414 }
00415 else if (image_index >= mrch.nz) {
00416 mrch.nz = image_index + 1;
00417 }
00418
00419 mrch.ispg = 0;
00420 mrch.nsymbt = 0;
00421 mrch.amin = dict["minimum"];
00422 mrch.amax = dict["maximum"];
00423 mrch.amean = dict["mean"];
00424 mrch.rms = dict["sigma"];
00425
00428
00429
00430
00431
00432 mrch.mx = nx;
00433
00434
00435
00436
00437
00438 mrch.my = ny;
00439
00440
00441
00442
00443
00444 mrch.mz = nz;
00445
00446
00447 mrch.xlen = mrch.mx * (float) dict["apix_x"];
00448 mrch.ylen = mrch.my * (float) dict["apix_y"];
00449 mrch.zlen = mrch.mz * (float) dict["apix_z"];
00450
00451 if(dict.has_key("MRC.nxstart")) {
00452 mrch.nxstart = dict["MRC.nxstart"];
00453 }
00454 else {
00455 mrch.nxstart = -nx / 2;
00456 }
00457 if(dict.has_key("MRC.nystart")) {
00458 mrch.nystart = dict["MRC.nystart"];
00459 }
00460 else {
00461 mrch.nystart = -ny / 2;
00462 }
00463 if(dict.has_key("MRC.nzstart")) {
00464 mrch.nzstart = dict["MRC.nzstart"];
00465 }
00466 else {
00467 mrch.nzstart = -nz / 2;
00468 }
00469
00470 sprintf(mrch.map, "MAP ");
00471 mrch.machinestamp = generate_machine_stamp();
00472
00473 MrcHeader mrch2 = mrch;
00474
00475 if (opposite_endian || !use_host_endian) {
00476 swap_header(mrch2);
00477 }
00478
00479 if (fwrite(&mrch2, sizeof(MrcHeader), 1, mrcfile) != 1) {
00480 throw ImageWriteException(filename, "MRC header");
00481 }
00482
00483 mode_size = get_mode_size(mrch.mode);
00484 is_new_file = false;
00485
00486 if( dict.has_key("ctf") ) {
00487 vector<float> vctf = dict["ctf"];
00488 EMAN1Ctf ctf_;
00489 ctf_.from_vector(vctf);
00490 write_ctf(ctf_);
00491 }
00492
00493 EXITFUNC;
00494 return 0;
00495 }
00496
00497 int MrcIO::read_data(float *rdata, int image_index, const Region * area, bool )
00498 {
00499 ENTERFUNC;
00500
00501
00502 image_index = 0;
00503 check_read_access(image_index, rdata);
00504
00505 if (area && is_complex_mode()) {
00506 LOGERR("Error: cannot read a region of a complex image.");
00507 return 1;
00508 }
00509
00510 check_region(area, FloatSize(mrch.nx, mrch.ny, mrch.nz), is_new_file, false);
00511
00512 unsigned char *cdata = (unsigned char *) rdata;
00513 short *sdata = (short *) rdata;
00514 unsigned short *usdata = (unsigned short *) rdata;
00515
00516 portable_fseek(mrcfile, sizeof(MrcHeader)+mrch.nsymbt, SEEK_SET);
00517
00518 EMUtil::process_region_io(cdata, mrcfile, READ_ONLY,
00519 image_index, mode_size,
00520 mrch.nx, mrch.ny, mrch.nz, area);
00521
00522 int xlen = 0, ylen = 0, zlen = 0;
00523 EMUtil::get_region_dims(area, mrch.nx, &xlen, mrch.ny, &ylen, mrch.nz, &zlen);
00524
00525 size_t size = xlen * ylen * zlen;
00526
00527 if (mrch.mode != MRC_UCHAR) {
00528 if (mode_size == sizeof(short)) {
00529 become_host_endian < short >(sdata, size);
00530 }
00531 else if (mode_size == sizeof(float)) {
00532 become_host_endian < float >(rdata, size);
00533 }
00534 }
00535
00536 if (mrch.mode == MRC_UCHAR) {
00537 for (size_t i = 0; i < size; ++i) {
00538 size_t j = size - 1 - i;
00539
00540 rdata[j] = static_cast < float >(cdata[j]);
00541 }
00542 }
00543 else if (mrch.mode == MRC_SHORT ) {
00544 for (size_t i = 0; i < size; ++i) {
00545 size_t j = size - 1 - i;
00546 rdata[j] = static_cast < float >(sdata[j]);
00547 }
00548 }
00549 else if (mrch.mode == MRC_USHORT) {
00550 for (size_t i = 0; i < size; ++i) {
00551 size_t j = size - 1 - i;
00552 rdata[j] = static_cast < float >(usdata[j]);
00553 }
00554 }
00555
00556 if (is_complex_mode()) {
00557 if(!is_ri) Util::ap2ri(rdata, size);
00558 Util::flip_complex_phase(rdata, size);
00559 Util::rotate_phase_origin(rdata, xlen, ylen, zlen);
00560 }
00561 EXITFUNC;
00562 return 0;
00563 }
00564
00565 int MrcIO::write_data(float *data, int image_index, const Region* area,
00566 EMUtil::EMDataType, bool use_host_endian)
00567 {
00568 ENTERFUNC;
00569
00570 image_index = 0;
00571 check_write_access(rw_mode, image_index, 1, data);
00572 check_region(area, FloatSize(mrch.nx, mrch.ny, mrch.nz), is_new_file);
00573
00574 int nx = mrch.nx;
00575 int ny = mrch.ny;
00576 int nz = mrch.nz;
00577 size_t size = nx * ny * nz;
00578
00579 if (is_complex_mode()) {
00580 nx *= 2;
00581 if (!is_ri) {
00582 Util::ap2ri(data, size);
00583 is_ri = 1;
00584 }
00585 Util::flip_complex_phase(data, size);
00586 Util::rotate_phase_origin(data, nx, ny, nz);
00587 }
00588
00589 portable_fseek(mrcfile, sizeof(MrcHeader), SEEK_SET);
00590
00591 if ( (is_big_endian != ByteOrder::is_host_big_endian()) || !use_host_endian) {
00592 if (mrch.mode != MRC_UCHAR) {
00593 if (mode_size == sizeof(short)) {
00594 ByteOrder::swap_bytes((short*) data, size);
00595 }
00596 else if (mode_size == sizeof(float)) {
00597 ByteOrder::swap_bytes((float*) data, size);
00598 }
00599 }
00600 }
00601 mode_size = get_mode_size(mrch.mode);
00602
00603
00604
00605
00606 void * ptr_data = data;
00607
00608 float rendermin = 0.0f;
00609 float rendermax = 0.0f;
00610 EMUtil::getRenderMinMax(data, nx, ny, rendermin, rendermax, nz);
00611
00612 unsigned char *cdata = 0;
00613 short *sdata = 0;
00614 unsigned short *usdata = 0;
00615 if (mrch.mode == MRC_UCHAR) {
00616 cdata = new unsigned char[size];
00617 for (size_t i = 0; i < size; ++i) {
00618 if(data[i] <= rendermin) {
00619 cdata[i] = 0;
00620 }
00621 else if(data[i] >= rendermax){
00622 cdata[i] = UCHAR_MAX;
00623 }
00624 else {
00625 cdata[i]=(unsigned char)((data[i]-rendermin)/(rendermax-rendermin)*UCHAR_MAX);
00626 }
00627 }
00628 ptr_data = cdata;
00629 update_stat((void *)cdata);
00630 }
00631 else if (mrch.mode == MRC_SHORT || mrch.mode == MRC_SHORT_COMPLEX) {
00632 sdata = new short[size];
00633 for (size_t i = 0; i < size; ++i) {
00634 if(data[i] <= rendermin) {
00635 sdata[i] = SHRT_MIN;
00636 }
00637 else if(data[i] >= rendermax) {
00638 sdata[i] = SHRT_MAX;
00639 }
00640 else {
00641 sdata[i]=(short)(((data[i]-rendermin)/(rendermax-rendermin))*(SHRT_MAX-SHRT_MIN) - SHRT_MAX);
00642 }
00643 }
00644 ptr_data = sdata;
00645 update_stat((void *)sdata);
00646 }
00647 else if (mrch.mode == MRC_USHORT) {
00648 usdata = new unsigned short[size];
00649 for (size_t i = 0; i < size; ++i) {
00650 if(data[i] <= rendermin) {
00651 usdata[i] = 0;
00652 }
00653 else if(data[i] >= rendermax) {
00654 usdata[i] = USHRT_MAX;
00655 }
00656 else {
00657 usdata[i]=(unsigned short)((data[i]-rendermin)/(rendermax-rendermin)*USHRT_MAX);
00658 }
00659 }
00660 ptr_data = usdata;
00661 update_stat((void *)usdata);
00662 }
00663
00664
00665
00666
00667 EMUtil::process_region_io(ptr_data, mrcfile, WRITE_ONLY, image_index,
00668 mode_size, nx, mrch.ny, mrch.nz, area);
00669
00670 if(cdata) {delete [] cdata; cdata=0;}
00671 if(sdata) {delete [] sdata; sdata=0;}
00672 if(usdata) {delete [] usdata; usdata=0;}
00673
00674 #if 0
00675 int row_size = nx * get_mode_size(mrch.mode);
00676 int sec_size = nx * ny;
00677
00678 unsigned char *cbuf = new unsigned char[row_size];
00679 unsigned short *sbuf = (unsigned short *) cbuf;
00680
00681 for (int i = 0; i < nz; i++) {
00682 int i2 = i * sec_size;
00683 for (int j = 0; j < ny; j++) {
00684 int k = i2 + j * nx;
00685 void *pbuf = 0;
00686
00687 switch (mrch.mode) {
00688 case MRC_UCHAR:
00689 for (int l = 0; l < nx; l++) {
00690 cbuf[l] = static_cast < unsigned char >(data[k + l]);
00691 }
00692 pbuf = cbuf;
00693 fwrite(cbuf, row_size, 1, mrcfile);
00694 break;
00695
00696 case MRC_SHORT:
00697 case MRC_SHORT_COMPLEX:
00698 for (int l = 0; l < nx; l++) {
00699 sbuf[l] = static_cast < short >(data[k + l]);
00700 }
00701 pbuf = sbuf;
00702 fwrite(sbuf, row_size, 1, mrcfile);
00703 break;
00704
00705 case MRC_USHORT:
00706 for (int l = 0; l < nx; l++) {
00707 sbuf[l] = static_cast < unsigned short >(data[k + l]);
00708 }
00709 pbuf = sbuf;
00710 fwrite(sbuf, row_size, 1, mrcfile);
00711 break;
00712
00713 case MRC_FLOAT:
00714 case MRC_FLOAT_COMPLEX:
00715 pbuf = &data[k];
00716 break;
00717 }
00718 if (pbuf) {
00719 fwrite(pbuf, row_size, 1, mrcfile);
00720 }
00721 }
00722 }
00723
00724 if(cbuf)
00725 {
00726 delete[]cbuf;
00727 cbuf = 0;
00728 }
00729 #endif
00730
00731 EXITFUNC;
00732 return 0;
00733 }
00734
00735 void MrcIO::update_stat(void* data)
00736 {
00737 size_t size = mrch.nx * mrch.ny * mrch.nz;
00738 float v = 0.0f;
00739 double sum = 0.0;
00740 double square_sum = 0.0;
00741 double mean = 0.0;
00742 float min, max;
00743
00744 unsigned char * cdata = 0;
00745 short * sdata = 0;
00746 unsigned short * usdata = 0;
00747
00748 if (mrch.mode == MRC_UCHAR) {
00749 max = 0.0f;
00750 min = UCHAR_MAX;
00751 cdata = (unsigned char *)data;
00752
00753 for (size_t i = 0; i < size; ++i) {
00754 v = (float)(cdata[i]);
00755 #ifdef _WIN32
00756 max = _cpp_max(max,v);
00757 min = _cpp_min(min,v);
00758 #else
00759 max=std::max<float>(max,v);
00760 min=std::min<float>(min,v);
00761 #endif //_WIN32
00762
00763 sum += v;
00764 square_sum += v * v;
00765 }
00766 }
00767 else if (mrch.mode == MRC_SHORT || mrch.mode == MRC_SHORT_COMPLEX) {
00768 max = (float)SHRT_MIN;
00769 min = (float)SHRT_MAX;
00770 sdata = (short *)data;
00771
00772 for (size_t i = 0; i < size; ++i) {
00773 v = (float)(sdata[i]);
00774 #ifdef _WIN32
00775 max = _cpp_max(max,v);
00776 min = _cpp_min(min,v);
00777 #else
00778 max=std::max<float>(max,v);
00779 min=std::min<float>(min,v);
00780 #endif //_WIN32
00781
00782 sum += v;
00783 square_sum += v * v;
00784 }
00785 }
00786 else if (mrch.mode == MRC_USHORT) {
00787 max = 0.0f;
00788 min = (float)USHRT_MAX;
00789 usdata = (unsigned short*)data;
00790
00791 for (size_t i = 0; i < size; ++i) {
00792 v = (float)(usdata[i]);
00793 #ifdef _WIN32
00794 max = _cpp_max(max,v);
00795 min = _cpp_min(min,v);
00796 #else
00797 max=std::max<float>(max,v);
00798 min=std::min<float>(min,v);
00799 #endif //_WIN32
00800
00801 sum += v;
00802 square_sum += v * v;
00803 }
00804 }
00805 else {
00806 throw InvalidCallException("This function is used to write 8bit/16bit mrc file only.");
00807 }
00808
00809 mean = sum/size;
00810 #ifdef _WIN32
00811 float sigma = (float)std::sqrt( _cpp_max(0.0,(square_sum - sum*sum / size)/(size-1)));
00812 #else
00813 float sigma = (float)std::sqrt(std::max<float>(0.0,(square_sum - sum*sum / size)/(size-1)));
00814 #endif //_WIN32
00815
00816
00817 mrch.amin = min;
00818 mrch.amax = max;
00819 mrch.amean = (float)mean;
00820 mrch.rms = sigma;
00821
00822 MrcHeader mrch2 = mrch;
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839 portable_fseek(mrcfile, 0, SEEK_SET);
00840
00841 if (fwrite(&mrch2, sizeof(MrcHeader), 1, mrcfile) != 1) {
00842 throw ImageWriteException(filename, "MRC header");
00843 }
00844
00845 portable_fseek(mrcfile, sizeof(MrcHeader), SEEK_SET);
00846 }
00847
00848 bool MrcIO::is_complex_mode()
00849 {
00850 init();
00851 if (mrch.mode == MRC_SHORT_COMPLEX || mrch.mode == MRC_FLOAT_COMPLEX) {
00852 return true;
00853 }
00854 return false;
00855 }
00856
00857
00858 int MrcIO::read_ctf(Ctf & ctf, int)
00859 {
00860 ENTERFUNC;
00861 init();
00862 size_t n = strlen(CTF_MAGIC);
00863
00864 int err = 1;
00865 if (strncmp(&mrch.labels[0][0], CTF_MAGIC, n) == 0) {
00866 err = ctf.from_string(string(&mrch.labels[0][n]));
00867 }
00868 EXITFUNC;
00869 return err;
00870 }
00871
00872 void MrcIO::write_ctf(const Ctf & ctf, int)
00873 {
00874 ENTERFUNC;
00875 init();
00876
00877 string ctf_str = ctf.to_string();
00878 sprintf(&mrch.labels[0][0], "%s%s", CTF_MAGIC, ctf_str.c_str());
00879 rewind(mrcfile);
00880
00881 if (fwrite(&mrch, sizeof(MrcHeader), 1, mrcfile) != 1) {
00882 throw ImageWriteException(filename, "write CTF info to header failed");
00883 }
00884 EXITFUNC;
00885 }
00886
00887 void MrcIO::flush()
00888 {
00889 fflush(mrcfile);
00890 }
00891
00892
00893 int MrcIO::get_mode_size(int mm)
00894 {
00895 MrcIO::MrcMode m = static_cast < MrcMode > (mm);
00896
00897 int msize = 0;
00898 switch (m) {
00899 case MRC_UCHAR:
00900 msize = sizeof(char);
00901 break;
00902 case MRC_SHORT:
00903 case MRC_USHORT:
00904 case MRC_SHORT_COMPLEX:
00905 msize = sizeof(short);
00906 break;
00907 case MRC_FLOAT:
00908 case MRC_FLOAT_COMPLEX:
00909 msize = sizeof(float);
00910 break;
00911 default:
00912 msize = 0;
00913 }
00914
00915 return msize;
00916 }
00917
00918 int MrcIO::to_em_datatype(int m)
00919 {
00920 EMUtil::EMDataType e = EMUtil::EM_UNKNOWN;
00921
00922 switch (m) {
00923 case MRC_UCHAR:
00924 e = EMUtil::EM_UCHAR;
00925 break;
00926 case MRC_SHORT:
00927 e = EMUtil::EM_SHORT;
00928 break;
00929 case MRC_USHORT:
00930 e = EMUtil::EM_USHORT;
00931 break;
00932 case MRC_SHORT_COMPLEX:
00933 e = EMUtil::EM_SHORT_COMPLEX;
00934 break;
00935 case MRC_FLOAT:
00936 e = EMUtil::EM_FLOAT;
00937 break;
00938 case MRC_FLOAT_COMPLEX:
00939 e = EMUtil::EM_FLOAT_COMPLEX;
00940 break;
00941 default:
00942 e = EMUtil::EM_UNKNOWN;
00943 }
00944 return e;
00945 }
00946
00947
00948 int MrcIO::to_mrcmode(int e, int is_complex)
00949 {
00950 MrcMode m = MRC_UNKNOWN;
00951 EMUtil::EMDataType em_type = static_cast < EMUtil::EMDataType > (e);
00952
00953 switch (em_type) {
00954 case EMUtil::EM_UCHAR:
00955 m = MRC_UCHAR;
00956 break;
00957 case EMUtil::EM_USHORT:
00958 if (is_complex) {
00959 m = MRC_SHORT_COMPLEX;
00960 }
00961 else {
00962 m = MRC_USHORT;
00963 }
00964 break;
00965 case EMUtil::EM_SHORT:
00966 if (is_complex) {
00967 m = MRC_SHORT_COMPLEX;
00968 }
00969 else {
00970 m = MRC_SHORT;
00971 }
00972 break;
00973 case EMUtil::EM_SHORT_COMPLEX:
00974 case EMUtil::EM_USHORT_COMPLEX:
00975 m = MRC_SHORT_COMPLEX;
00976 break;
00977 case EMUtil::EM_CHAR:
00978 case EMUtil::EM_INT:
00979 case EMUtil::EM_UINT:
00980 case EMUtil::EM_FLOAT:
00981 if (is_complex) {
00982 m = MRC_FLOAT_COMPLEX;
00983 }
00984 else {
00985 m = MRC_FLOAT;
00986 }
00987 break;
00988 case EMUtil::EM_FLOAT_COMPLEX:
00989 m = MRC_FLOAT_COMPLEX;
00990 break;
00991 default:
00992 m = MRC_FLOAT;
00993 }
00994
00995 return m;
00996 }
00997
00998
00999
01000 int MrcIO::generate_machine_stamp()
01001 {
01002 int stamp = 0;
01003 char *p = (char *) (&stamp);
01004
01005 if (ByteOrder::is_host_big_endian()) {
01006 p[0] = 0x11;
01007 p[1] = 0x11;
01008 p[2] = 0;
01009 p[3] = 0;
01010 }
01011 else {
01012 p[0] = 0x44;
01013 p[1] = 0x41;
01014 p[2] = 0;
01015 p[3] = 0;
01016 }
01017 return stamp;
01018 }
01019
01020 void MrcIO::swap_header(MrcHeader& mrch)
01021 {
01022 ByteOrder::swap_bytes((int *) &mrch, NUM_4BYTES_PRE_MAP);
01023 ByteOrder::swap_bytes((int *) &mrch.machinestamp, NUM_4BYTES_AFTER_MAP);
01024 }