Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

mrcio.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 #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                 //become_host_endian((int *) &mrch, NUM_4BYTES_PRE_MAP);
00094                 //become_host_endian((int *) &mrch.machinestamp, NUM_4BYTES_AFTER_MAP);
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];  //this field specify the extra bytes for symmetry information
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 //#ifndef SPIDERMRC // Spider MRC files don't satisfy the following test
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 //                      return false;
00170                         LOGWARN("image size check fails, still try to read it...");     //when size doesn't match, print error message instead of make it fail
00171                 }
00172                 else {
00173                         return true;
00174                 }
00175 //#endif // SPIDERMRC
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         //single image format, index can only be zero
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         //single image format, index can only be zero
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 //      if(dict.has_key("MRC.mx")) {
00429 //              mrch.mx = dict["MRC.mx"];
00430 //      }
00431 //      else {
00432                 mrch.mx = nx;
00433 //      }
00434 //      if(dict.has_key("MRC.my")) {
00435 //              mrch.my = dict["MRC.my"];
00436 //      }
00437 //      else {
00438                 mrch.my = ny;
00439 //      }
00440 //      if(dict.has_key("MRC.mz")) {
00441 //              mrch.mz = dict["MRC.mz"];
00442 //      }
00443 //      else {
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         //single image format, index can only be zero
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                         //rdata[i] = static_cast<float>(cdata[i]/100.0f - 1.28f);
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         //single image format, index can only be zero
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 //      int xlen = 0, ylen = 0, zlen = 0;
00604 //      EMUtil::get_region_dims(area, nx, &xlen, mrch.ny, &ylen, mrch.nz, &zlen);
00605 //      int size = xlen * ylen * zlen;
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         // New way to write data which includes region writing.
00665         // If it is tested to be OK, remove the old code in the
00666         // #if 0  ... #endif block.
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; //variable to hold pixel value
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         /*change mrch.amin/amax/amean.rms here*/
00817         mrch.amin = min;
00818         mrch.amax = max;
00819         mrch.amean = (float)mean;
00820         mrch.rms = sigma;
00821         
00822         MrcHeader mrch2 = mrch;
00823 
00824 //endian issue, can't get use_host_endian argument
00825 //      bool opposite_endian = false;
00826 
00827 //      if (!is_new_file) {
00828 //              if (is_big_endian != ByteOrder::is_host_big_endian()) {
00829 //                      opposite_endian = true;
00830 //              }
00831 //
00832 //              portable_fseek(mrcfile, 0, SEEK_SET);
00833 //      }
00834 //      
00835 //      if (opposite_endian || !use_host_endian) {
00836 //              swap_header(mrch2);
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 }

Generated on Thu Dec 9 13:45:47 2010 for EMAN2 by  doxygen 1.3.9.1