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                 isFEI(false), is_ri(0), is_new_file(false), initialized(false),
00054                 is_transpose(false)
00055 {
00056         memset(&mrch, 0, sizeof(MrcHeader));
00057         is_big_endian = ByteOrder::is_host_big_endian();
00058 }
00059 
00060 MrcIO::~MrcIO()
00061 {
00062         if (mrcfile) {
00063                 fclose(mrcfile);
00064                 mrcfile = 0;
00065         }
00066 }
00067 
00068 void MrcIO::init()
00069 {
00070         ENTERFUNC;
00071 
00072         if (initialized) {
00073                 return;
00074         }
00075 
00076         initialized = true;
00077         mrcfile = sfopen(filename, rw_mode, &is_new_file);
00078 
00079         if (!is_new_file) {
00080                 if (fread(&mrch, sizeof(MrcHeader), 1, mrcfile) != 1) {
00081                         throw ImageReadException(filename, "MRC header");
00082                 }
00083 
00084                 if (!is_valid(&mrch)) {
00085                         throw ImageReadException(filename, "invalid MRC");
00086                 }
00087 
00088                 is_big_endian = ByteOrder::is_data_big_endian(&mrch.nz);
00089                 if (is_big_endian != ByteOrder::is_host_big_endian()) {
00090                         swap_header(mrch);
00091                 }
00092                 //become_host_endian((int *) &mrch, NUM_4BYTES_PRE_MAP);
00093                 //become_host_endian((int *) &mrch.machinestamp, NUM_4BYTES_AFTER_MAP);
00094                 mode_size = get_mode_size(mrch.mode);
00095                 if(is_complex_mode()) {
00096                         is_ri = 1;
00097                 }
00098 
00099                 if (mrch.nxstart != 0 || mrch.nystart != 0 || mrch.nzstart != 0) {
00100                         LOGWARN("nx/ny/nz start not zero");
00101                 }
00102 
00103                 if (is_complex_mode()) {
00104                         mrch.nx *= 2;
00105                 }
00106 
00107                 if (mrch.xlen == 0) {
00108                         mrch.xlen = 1.0;
00109                 }
00110 
00111                 if (mrch.ylen == 0) {
00112                         mrch.ylen = 1.0;
00113                 }
00114 
00115                 if (mrch.zlen == 0) {
00116                         mrch.zlen = 1.0;
00117                 }
00118 
00119                 if(mrch.nlabels>0) {
00120                         if( string(mrch.labels[0],3) == "Fei") {
00121                                 isFEI = true;
00122                         }
00123                 }
00124 
00125                 if(mrch.mapc==2 && mrch.mapr==1) {
00126                         is_transpose = true;
00127                 }
00128         }
00129         EXITFUNC;
00130 }
00131 
00132 
00133 bool MrcIO::is_image_big_endian()
00134 {
00135         init();
00136         return is_big_endian;
00137 }
00138 
00139 bool MrcIO::is_valid(const void *first_block, off_t file_size)
00140 {
00141         ENTERFUNC;
00142 
00143         if (!first_block) {
00144                 return false;
00145         }
00146 
00147         const int *data = static_cast < const int *>(first_block);
00148         int nx = data[0];
00149         int ny = data[1];
00150         int nz = data[2];
00151         int mrcmode = data[3];
00152         int nsymbt = data[23];  //this field specify the extra bytes for symmetry information
00153 
00154         bool data_big_endian = ByteOrder::is_data_big_endian(&nz);
00155 
00156         if (data_big_endian != ByteOrder::is_host_big_endian()) {
00157                 ByteOrder::swap_bytes(&nx);
00158                 ByteOrder::swap_bytes(&ny);
00159                 ByteOrder::swap_bytes(&nz);
00160                 ByteOrder::swap_bytes(&mrcmode);
00161                 ByteOrder::swap_bytes(&nsymbt);
00162         }
00163 
00164         if (mrcmode == MRC_SHORT_COMPLEX || mrcmode == MRC_FLOAT_COMPLEX) {
00165                 nx *= 2;
00166         }
00167 
00168         const int max_dim = 1 << 20;
00169 
00170         if ((mrcmode >= MRC_UCHAR && mrcmode < MRC_UNKNOWN) &&
00171                 (nx > 1 && nx < max_dim) && (ny > 0 && ny < max_dim) && (nz > 0 && nz < max_dim)) {
00172 //#ifndef SPIDERMRC // Spider MRC files don't satisfy the following test
00173                 if (file_size > 0) {
00174                         off_t file_size1 = (off_t)nx * (off_t)ny * (off_t)nz * (off_t)get_mode_size(mrcmode) + (off_t)sizeof(MrcHeader) + nsymbt;
00175                         if (file_size == file_size1) {
00176                                 return true;
00177                         }
00178 //                      return false;
00179                         LOGWARN("image size check fails, still try to read it...");     //when size doesn't match, print error message instead of make it fail
00180                 }
00181                 else {
00182                         return true;
00183                 }
00184 //#endif // SPIDERMRC
00185                 return true;
00186         }
00187         EXITFUNC;
00188         return false;
00189 }
00190 
00191 int MrcIO::read_header(Dict & dict, int image_index, const Region * area, bool is_3d)
00192 {
00193         init();
00194 
00195         if(isFEI) {
00196                 return read_fei_header(dict, image_index, area, is_3d);
00197         }
00198         else {
00199                 return read_mrc_header(dict, image_index, area, is_3d);
00200         }
00201 }
00202 
00203 int MrcIO::read_mrc_header(Dict & dict, int image_index, const Region * area, bool)
00204 {
00205         ENTERFUNC;
00206 
00207         //single image format, index can only be zero
00208         if(image_index < 0) {
00209                 image_index = 0;
00210         }
00211         if(image_index != 0) {
00212                 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().");
00213         }
00214 
00215         check_region(area, FloatSize(mrch.nx, mrch.ny, mrch.nz), is_new_file, false);
00216 
00217         int xlen = 0, ylen = 0, zlen = 0;
00218         EMUtil::get_region_dims(area, mrch.nx, &xlen, mrch.ny, &ylen, mrch.nz, &zlen);
00219 
00220         dict["nx"] = xlen;
00221         dict["ny"] = ylen;
00222         dict["nz"] = zlen;
00223         dict["MRC.nx"] = mrch.nx;
00224         dict["MRC.ny"] = mrch.ny;
00225         dict["MRC.nz"] = mrch.nz;
00226 
00227         dict["datatype"] = to_em_datatype(mrch.mode);
00228 
00229         dict["MRC.nxstart"] = mrch.nxstart;
00230         dict["MRC.nystart"] = mrch.nystart;
00231         dict["MRC.nzstart"] = mrch.nzstart;
00232 
00233         dict["MRC.mx"] = mrch.mx;
00234         dict["MRC.my"] = mrch.my;
00235         dict["MRC.mz"] = mrch.mz;
00236 
00237         dict["MRC.xlen"] = mrch.xlen;
00238         dict["MRC.ylen"] = mrch.ylen;
00239         dict["MRC.zlen"] = mrch.zlen;
00240 
00241         dict["MRC.alpha"] = mrch.alpha;
00242         dict["MRC.beta"] = mrch.beta;
00243         dict["MRC.gamma"] = mrch.gamma;
00244 
00245         dict["MRC.mapc"] = mrch.mapc;
00246         dict["MRC.mapr"] = mrch.mapr;
00247         dict["MRC.maps"] = mrch.maps;
00248 
00249         dict["MRC.minimum"] = mrch.amin;
00250         dict["MRC.maximum"] = mrch.amax;
00251         dict["MRC.mean"] = mrch.amean;
00252         dict["mean"] = mrch.amean;
00253 
00254         dict["MRC.ispg"] = mrch.ispg;
00255         dict["MRC.nsymbt"] = mrch.nsymbt;
00256 
00257         float apx = mrch.xlen / mrch.mx;
00258         float apy = mrch.ylen / mrch.my;
00259         float apz = mrch.zlen / mrch.mz;
00260         if(apx>1000 || apx<0.01) {
00261                 dict["apix_x"] = 1.0f;
00262         }
00263         else {
00264                 dict["apix_x"] = apx;
00265         }
00266         if(apy>1000 || apy<0.01) {
00267                 dict["apix_y"] = 1.0f;
00268         }
00269         else {
00270                 dict["apix_y"] = apy;
00271         }
00272         if(apz>1000 || apz<0.01) {
00273                 dict["apix_z"] = 1.0f;
00274         }
00275         else {
00276                 dict["apix_z"] = apz;
00277         }
00278 
00279         if (area) {
00280                 dict["origin_x"] = mrch.xorigin + mrch.xlen * area->origin[0];
00281                 dict["origin_y"] = mrch.yorigin + mrch.xlen * area->origin[1];
00282 
00283                 if (area->get_ndim() == 3 && mrch.nz > 1) {
00284                         dict["origin_z"] = mrch.zorigin + mrch.xlen * area->origin[2];
00285                 }
00286                 else {
00287                         dict["origin_z"] = mrch.zorigin;
00288                 }
00289         }
00290         else {
00291                 dict["origin_x"] = mrch.xorigin;
00292                 dict["origin_y"] = mrch.yorigin;
00293                 dict["origin_z"] = mrch.zorigin;
00294         }
00295 
00296         if (is_complex_mode()) {
00297                 dict["is_complex"] = 1;
00298                 dict["is_complex_ri"] = 1;
00299         }
00300 
00301         dict["MRC.machinestamp"] = mrch.machinestamp;
00302 
00303         dict["MRC.rms"] = mrch.rms;
00304         dict["sigma"] = mrch.rms;
00305         dict["MRC.nlabels"] = mrch.nlabels;
00306         for (int i = 0; i < mrch.nlabels; i++) {
00307                 char label[32];
00308                 sprintf(label, "MRC.label%d", i);
00309                 dict[string(label)] = string(mrch.labels[i],80);
00310         }
00311 
00312         EMAN1Ctf ctf_;
00313         if(read_ctf(ctf_) == 0) {
00314                 vector<float> vctf = ctf_.to_vector();
00315                 dict["ctf"] = vctf;
00316         }
00317 
00318         if(is_transpose) {
00319                 dict["nx"] = ylen;
00320                 dict["ny"] = xlen;
00321                 dict["MRC.nx"] = mrch.ny;
00322                 dict["MRC.ny"] = mrch.nx;
00323                 dict["MRC.mx"] = mrch.my;
00324                 dict["MRC.my"] = mrch.mx;
00325                 dict["apix_x"] = mrch.ylen / mrch.my;
00326                 dict["apix_y"] = mrch.xlen / mrch.mx;
00327                 dict["origin_x"] = mrch.yorigin;
00328                 dict["origin_y"] = mrch.xorigin;
00329                 dict["MRC.nxstart"] = mrch.nystart;
00330                 dict["MRC.nystart"] = mrch.nxstart;
00331         }
00332 
00333         Transform * trans = new Transform();
00334         if(is_transpose) {
00335                 trans->set_trans(mrch.nystart, mrch.nxstart, mrch.nzstart);
00336         }
00337         else {
00338                 trans->set_trans(mrch.nxstart, mrch.nystart, mrch.nzstart);
00339         }
00340         
00341         if(zlen<=1) {
00342                 dict["xform.projection"] = trans;
00343         }
00344         else {
00345                 dict["xform.align3d"] = trans;
00346         }
00347 
00348         if(trans) {delete trans; trans=0;}
00349 
00350         EXITFUNC;
00351         return 0;
00352 }
00353 
00354 int MrcIO::read_fei_header(Dict & dict, int image_index, const Region * area, bool)
00355 {
00356         ENTERFUNC;
00357 
00358         if(image_index < 0) {
00359                 image_index = 0;
00360         }
00361 
00362         init();
00363 
00364         check_region(area, FloatSize(feimrch.nx, feimrch.ny, feimrch.nz), is_new_file, false);
00365 
00366         int xlen = 0, ylen = 0, zlen = 0;
00367         EMUtil::get_region_dims(area, feimrch.nx, &xlen, feimrch.ny, &ylen, feimrch.nz, &zlen);
00368 
00369         dict["nx"] = xlen;
00370         dict["ny"] = ylen;
00371         dict["nz"] = zlen;
00372         dict["FEIMRC.nx"] = feimrch.nx;
00373         dict["FEIMRC.ny"] = feimrch.ny;
00374         dict["FEIMRC.nz"] = feimrch.nz;
00375 
00376         dict["datatype"] = to_em_datatype(feimrch.mode);        //=1, FEI-MRC file always use short for data type
00377 
00378         dict["FEIMRC.nxstart"] = feimrch.nxstart;
00379         dict["FEIMRC.nystart"] = feimrch.nystart;
00380         dict["FEIMRC.nzstart"] = feimrch.nzstart;
00381 
00382         dict["FEIMRC.mx"] = feimrch.mx;
00383         dict["FEIMRC.my"] = feimrch.my;
00384         dict["FEIMRC.mz"] = feimrch.mz;
00385 
00386         dict["FEIMRC.xlen"] = feimrch.xlen;
00387         dict["FEIMRC.ylen"] = feimrch.ylen;
00388         dict["FEIMRC.zlen"] = feimrch.zlen;
00389 
00390         dict["FEIMRC.alpha"] = feimrch.alpha;
00391         dict["FEIMRC.beta"] = feimrch.beta;
00392         dict["FEIMRC.gamma"] = feimrch.gamma;
00393 
00394         dict["FEIMRC.mapc"] = feimrch.mapc;
00395         dict["FEIMRC.mapr"] = feimrch.mapr;
00396         dict["FEIMRC.maps"] = feimrch.maps;
00397 
00398         dict["FEIMRC.minimum"] = feimrch.amin;
00399         dict["FEIMRC.maximum"] = feimrch.amax;
00400         dict["FEIMRC.mean"] = feimrch.amean;
00401         dict["mean"] = feimrch.amean;
00402 
00403         dict["FEIMRC.ispg"] = feimrch.ispg;
00404         dict["FEIMRC.nsymbt"] = feimrch.nsymbt;
00405 
00406         dict["apix_x"] = feimrch.xlen / feimrch.mx;
00407         dict["apix_y"] = feimrch.ylen / feimrch.my;
00408         dict["apix_z"] = feimrch.zlen / feimrch.mz;
00409 
00410         dict["FEIMRC.next"] = feimrch.next;     //offset from end of header to the first dataset
00411         dict["FEIMRC.dvid"] = feimrch.dvid;
00412         dict["FEIMRC.numintegers"] = feimrch.numintegers;
00413         dict["FEIMRC.numfloats"] = feimrch.numfloats;
00414         dict["FEIMRC.sub"] = feimrch.sub;
00415         dict["FEIMRC.zfac"] = feimrch.zfac;
00416 
00417         dict["FEIMRC.min2"] = feimrch.min2;
00418         dict["FEIMRC.max2"] = feimrch.max2;
00419         dict["FEIMRC.min3"] = feimrch.min3;
00420         dict["FEIMRC.max3"] = feimrch.max3;
00421         dict["FEIMRC.min4"] = feimrch.min4;
00422         dict["FEIMRC.max4"] = feimrch.max4;
00423 
00424         dict["FEIMRC.idtype"] = feimrch.idtype;
00425         dict["FEIMRC.lens"] = feimrch.lens;
00426         dict["FEIMRC.nd1"] = feimrch.nd1;
00427         dict["FEIMRC.nd2"] = feimrch.nd2;
00428         dict["FEIMRC.vd1"] = feimrch.vd1;
00429         dict["FEIMRC.vd2"] = feimrch.vd2;
00430 
00431         for(int i=0; i<9; i++) {        //9 tilt angles
00432                 char label[32];
00433                 sprintf(label, "MRC.tiltangles%d", i);
00434                 dict[string(label)] = feimrch.tiltangles[i];
00435         }
00436 
00437         dict["FEIMRC.zorg"] = feimrch.zorg;
00438         dict["FEIMRC.xorg"] = feimrch.xorg;
00439         dict["FEIMRC.yorg"] = feimrch.yorg;
00440 
00441         dict["FEIMRC.nlabl"] = feimrch.nlabl;
00442         for (int i = 0; i < feimrch.nlabl; i++) {
00443                 char label[32];
00444                 sprintf(label, "MRC.label%d", i);
00445                 dict[string(label)] = string(feimrch.labl[i], 80);
00446         }
00447 
00448         /* Read extended image header by specified image index*/
00449         FeiMrcExtHeader feiexth;
00450         portable_fseek(mrcfile, sizeof(FeiMrcHeader)+sizeof(FeiMrcExtHeader)*image_index, SEEK_SET);
00451         if (fread(&feiexth, sizeof(FeiMrcExtHeader), 1, mrcfile) != 1) {
00452                 throw ImageReadException(filename, "FEI MRC extended header");
00453         }
00454 
00455         dict["FEIMRC.a_tilt"] = feiexth.a_tilt;
00456         dict["FEIMRC.b_tilt"] = feiexth.b_tilt;
00457 
00458         dict["FEIMRC.x_stage"] = feiexth.x_stage;
00459         dict["FEIMRC.y_stage"] = feiexth.y_stage;
00460         dict["FEIMRC.z_stage"] = feiexth.z_stage;
00461 
00462         dict["FEIMRC.x_shift"] = feiexth.x_shift;
00463         dict["FEIMRC.y_shift"] = feiexth.y_shift;
00464 
00465         dict["FEIMRC.defocus"] = feiexth.defocus;
00466         dict["FEIMRC.exp_time"] = feiexth.exp_time;
00467         dict["FEIMRC.mean_int"] = feiexth.mean_int;
00468         dict["FEIMRC.tilt_axis"] = feiexth.tilt_axis;
00469 
00470         dict["FEIMRC.pixel_size"] = feiexth.pixel_size;
00471         dict["FEIMRC.magnification"] = feiexth.magnification;
00472         dict["FEIMRC.ht"] = feiexth.ht;
00473         dict["FEIMRC.binning"] = feiexth.binning;
00474         dict["FEIMRC.appliedDefocus"] = feiexth.appliedDefocus;
00475 
00476         //remainder 16 4-byte floats not used
00477 
00478         EXITFUNC;
00479         return 0;
00480 }
00481 
00482 int MrcIO::write_header(const Dict & dict, int image_index, const Region* area,
00483                                                 EMUtil::EMDataType filestoragetype, bool use_host_endian)
00484 {
00485         ENTERFUNC;
00486 
00487         //single image format, index can only be zero
00488         if(image_index == -1) {
00489                 image_index = 0;
00490         }
00491         if(image_index != 0) {
00492                 throw ImageWriteException(filename, "MRC file does not support stack.");
00493         }
00494         check_write_access(rw_mode, image_index, 1);
00495         if (area) {
00496                 check_region(area, FloatSize(mrch.nx, mrch.ny, mrch.nz), is_new_file);
00497                 EXITFUNC;
00498                 return 0;
00499         }
00500 
00501         int new_mode = to_mrcmode(filestoragetype, (int) dict["is_complex"]);
00502         int nx = dict["nx"];
00503         int ny = dict["ny"];
00504         int nz = dict["nz"];
00505         is_ri =  dict["is_complex_ri"];
00506 
00507         bool opposite_endian = false;
00508 
00509         if (!is_new_file) {
00510                 if (is_big_endian != ByteOrder::is_host_big_endian()) {
00511                         opposite_endian = true;
00512                 }
00513 #if 0
00514                 if (new_mode != mrch.mode) {
00515                         LOGERR("cannot write to different mode file %s", filename.c_str());
00516                         return 1;
00517                 }
00518 #endif
00519                 portable_fseek(mrcfile, 0, SEEK_SET);
00520         }
00521         else {
00522                 mrch.alpha = mrch.beta = mrch.gamma = 90.0f;
00523                 mrch.mapc = 1;
00524                 mrch.mapr = 2;
00525                 mrch.maps = 3;
00526                 mrch.nxstart = mrch.nystart = mrch.nzstart = 0;
00527         }
00528 
00529         if(nz<=1 && dict.has_key("xform.projection") && !dict.has_key("UCSF.chimera")) {
00530                 Transform * t = dict["xform.projection"];
00531                 Dict d = t->get_params("imagic");
00532                 mrch.alpha = d["alpha"];
00533                 mrch.beta = d["beta"];
00534                 mrch.gamma = d["gamma"];
00535                 mrch.xorigin = d["tx"];
00536                 mrch.yorigin = d["ty"];
00537                 mrch.zorigin = d["tz"];
00538                 if(t) {delete t; t=0;}
00539         }
00540         else if(nz>1 && dict.has_key("xform.align3d") && !dict.has_key("UCSF.chimera")) {
00541                 Transform * t = dict["xform.align3d"];
00542                 Dict d = t->get_params("imagic");
00543                 mrch.alpha = d["alpha"];
00544                 mrch.beta = d["beta"];
00545                 mrch.gamma = d["gamma"];
00546                 mrch.xorigin = d["tx"];
00547                 mrch.yorigin = d["ty"];
00548                 mrch.zorigin = d["tz"];
00549                 if(t) {delete t; t=0;}
00550         }
00551 
00552         if(dict.has_key("origin_x") && dict.has_key("origin_y") && dict.has_key("origin_z")){
00553                 mrch.xorigin = (float)dict["origin_x"];
00554                 mrch.yorigin = (float)dict["origin_y"];
00555 
00556                 if (is_new_file) {
00557                         mrch.zorigin = (float)dict["origin_z"];
00558                 }
00559                 else {
00560                         mrch.zorigin = (float) dict["origin_z"] - (float) dict["apix_z"] * image_index;
00561                 }
00562         }
00563 
00564         if (dict.has_key("MRC.nlabels")) {
00565                 mrch.nlabels = dict["MRC.nlabels"];
00566         }
00567 
00568         for (int i = 0; i < MRC_NUM_LABELS; i++) {
00569                 char label[32];
00570 #ifdef _WIN32
00571                 _snprintf(label,31, "MRC.label%d", i);
00572 #else
00573                 snprintf(label,31, "MRC.label%d", i);
00574 #endif  //_WIN32
00575                 if (dict.has_key(label)) {
00576 #ifdef _WIN32
00577                         _snprintf(&mrch.labels[i][0],80, "%s", (const char *) dict[label]);
00578 #else
00579                         snprintf(&mrch.labels[i][0],80, "%s", (const char *) dict[label]);
00580 #endif  //_WIN32
00581                         mrch.nlabels = i + 1;
00582                 }
00583         }
00584 
00585         if (mrch.nlabels < (MRC_NUM_LABELS - 1)) {
00586 #ifdef _WIN32
00587                 _snprintf(&mrch.labels[mrch.nlabels][0],79, "EMAN %s", Util::get_time_label().c_str());
00588 #else
00589                 snprintf(&mrch.labels[mrch.nlabels][0],79, "EMAN %s", Util::get_time_label().c_str());
00590 #endif  //_WIN32
00591                 mrch.nlabels++;
00592         }
00593 
00594         mrch.labels[mrch.nlabels][0] = '\0';
00595         mrch.mode = new_mode;
00596 
00597         if (is_complex_mode()) {
00598                 mrch.nx = nx / 2;
00599         }
00600         else {
00601                 mrch.nx = nx;
00602         }
00603         mrch.ny = ny;
00604 
00605         if (is_new_file) {
00606                 mrch.nz = nz;
00607         }
00608         else if (image_index >= mrch.nz) {
00609                 mrch.nz = image_index + 1;
00610         }
00611 
00612         mrch.ispg = dict.has_key("MRC.ispg") ? (int)dict["MRC.ispg"] : 0;
00613         mrch.nsymbt = 0;
00614         mrch.amin = dict["minimum"];
00615         mrch.amax = dict["maximum"];
00616         mrch.amean = dict["mean"];
00617         mrch.rms = dict["sigma"];
00618 
00621 //      if(dict.has_key("MRC.mx")) {
00622 //              mrch.mx = dict["MRC.mx"];
00623 //      }
00624 //      else {
00625                 mrch.mx = nx;
00626 //      }
00627 //      if(dict.has_key("MRC.my")) {
00628 //              mrch.my = dict["MRC.my"];
00629 //      }
00630 //      else {
00631                 mrch.my = ny;
00632 //      }
00633 //      if(dict.has_key("MRC.mz")) {
00634 //              mrch.mz = dict["MRC.mz"];
00635 //      }
00636 //      else {
00637                 mrch.mz = nz;
00638 //      }
00639 
00640         mrch.xlen = mrch.mx * (float) dict["apix_x"];
00641         mrch.ylen = mrch.my * (float) dict["apix_y"];
00642         mrch.zlen = mrch.mz * (float) dict["apix_z"];
00643 
00644         if(dict.has_key("MRC.nxstart")) {
00645                 mrch.nxstart = dict["MRC.nxstart"];
00646         }
00647         else {
00648                 mrch.nxstart = -nx / 2;
00649         }
00650         if(dict.has_key("MRC.nystart")) {
00651                 mrch.nystart = dict["MRC.nystart"];
00652         }
00653         else {
00654                 mrch.nystart = -ny / 2;
00655         }
00656         if(dict.has_key("MRC.nzstart")) {
00657                 mrch.nzstart = dict["MRC.nzstart"];
00658         }
00659         else {
00660                 mrch.nzstart = -nz / 2;
00661         }
00662 
00663         strncpy(mrch.map,"MAP ",4);
00664         mrch.machinestamp = generate_machine_stamp();
00665 
00666         MrcHeader mrch2 = mrch;
00667 
00668         if (opposite_endian || !use_host_endian) {
00669                 swap_header(mrch2);
00670         }
00671 
00672         if (fwrite(&mrch2, sizeof(MrcHeader), 1, mrcfile) != 1) {
00673                 throw ImageWriteException(filename, "MRC header");
00674         }
00675 
00676         mode_size = get_mode_size(mrch.mode);
00677         is_new_file = false;
00678 
00679         if( dict.has_key("ctf") ) {
00680                 vector<float> vctf = dict["ctf"];
00681                 EMAN1Ctf ctf_;
00682                 ctf_.from_vector(vctf);
00683                 write_ctf(ctf_);
00684         }
00685 
00686         EXITFUNC;
00687         return 0;
00688 }
00689 
00690 int MrcIO::read_data(float *rdata, int image_index, const Region * area, bool )
00691 {
00692         ENTERFUNC;
00693 
00694         if(!isFEI) {
00695                 //single image format, index can only be zero
00696                 image_index = 0;
00697         }
00698 
00699         if(is_transpose && area!=0) {
00700                 printf("Warning: This image dimension is in (y,x,z), region I/O not supported, return the whole image instead.");
00701         }
00702 
00703         check_read_access(image_index, rdata);
00704 
00705         if (area && is_complex_mode()) {
00706                 LOGERR("Error: cannot read a region of a complex image.");
00707                 return 1;
00708         }
00709 
00710         unsigned char *cdata = (unsigned char *) rdata;
00711         short *sdata = (short *) rdata;
00712         unsigned short *usdata = (unsigned short *) rdata;
00713 
00714         size_t size = 0;
00715         int xlen = 0, ylen = 0, zlen = 0;
00716         if(isFEI) {     //FEI extended MRC
00717                 check_region(area, FloatSize(feimrch.nx, feimrch.ny, feimrch.nz), is_new_file, false);
00718                 portable_fseek(mrcfile, sizeof(MrcHeader)+feimrch.next, SEEK_SET);
00719 
00720                 EMUtil::process_region_io(cdata, mrcfile, READ_ONLY,
00721                                                                   image_index, mode_size,
00722                                                                   feimrch.nx, feimrch.ny, feimrch.nz, area);
00723 
00724                 EMUtil::get_region_dims(area, feimrch.nx, &xlen, feimrch.ny, &ylen, feimrch.nz, &zlen);
00725 
00726                 size = (size_t)xlen * ylen * zlen;
00727         }
00728         else {  //regular MRC
00729                 check_region(area, FloatSize(mrch.nx, mrch.ny, mrch.nz), is_new_file, false);
00730                 portable_fseek(mrcfile, sizeof(MrcHeader)+mrch.nsymbt, SEEK_SET);
00731 
00732                 EMUtil::process_region_io(cdata, mrcfile, READ_ONLY,
00733                                                                   image_index, mode_size,
00734                                                                   mrch.nx, mrch.ny, mrch.nz, area);
00735 
00736                 EMUtil::get_region_dims(area, mrch.nx, &xlen, mrch.ny, &ylen, mrch.nz, &zlen);
00737 
00738                 size = xlen * ylen * zlen;
00739         }
00740 
00741         if (mrch.mode != MRC_UCHAR) {
00742                 if (mode_size == sizeof(short)) {
00743                         become_host_endian < short >(sdata, size);
00744                 }
00745                 else if (mode_size == sizeof(float)) {
00746                         become_host_endian < float >(rdata, size);
00747                 }
00748         }
00749 
00750         if (mrch.mode == MRC_UCHAR) {
00751                 for (size_t i = 0; i < size; ++i) {
00752                         size_t j = size - 1 - i;
00753                         //rdata[i] = static_cast<float>(cdata[i]/100.0f - 1.28f);
00754                         rdata[j] = static_cast < float >(cdata[j]);
00755                 }
00756         }
00757         else if (mrch.mode == MRC_SHORT ) {
00758                 for (size_t i = 0; i < size; ++i) {
00759                         size_t j = size - 1 - i;
00760                         rdata[j] = static_cast < float >(sdata[j]);
00761                 }
00762         }
00763         else if (mrch.mode == MRC_USHORT) {
00764                 for (size_t i = 0; i < size; ++i) {
00765                         size_t j = size - 1 - i;
00766                         rdata[j] = static_cast < float >(usdata[j]);
00767                 }
00768         }
00769 
00770         if(is_transpose) {
00771                 transpose(rdata, xlen, ylen, zlen);
00772         }
00773 
00774         if (is_complex_mode()) {
00775                 if(!is_ri) Util::ap2ri(rdata, size);
00776                 Util::flip_complex_phase(rdata, size);
00777                 Util::rotate_phase_origin(rdata, xlen, ylen, zlen);
00778         }
00779         EXITFUNC;
00780         return 0;
00781 }
00782 
00783 int MrcIO::write_data(float *data, int image_index, const Region* area,
00784                                           EMUtil::EMDataType, bool use_host_endian)
00785 {
00786         ENTERFUNC;
00787         //single image format, index can only be zero
00788         image_index = 0;
00789         check_write_access(rw_mode, image_index, 1, data);
00790         check_region(area, FloatSize(mrch.nx, mrch.ny, mrch.nz), is_new_file);
00791 
00792         int nx, ny, nz;
00793         if(!area) {
00794                 nx = mrch.nx;
00795                 ny = mrch.ny;
00796                 nz = mrch.nz;
00797         }
00798         else {
00799                 nx = area->get_width();
00800                 ny = area->get_height();
00801                 nz = area->get_depth();
00802         }
00803         size_t size = (size_t)nx * ny * nz;
00804 
00805         if (is_complex_mode()) {
00806                 nx *= 2;
00807                 if (!is_ri) {
00808                         Util::ap2ri(data, size);
00809                         is_ri = 1;
00810                 }
00811                 Util::flip_complex_phase(data, size);
00812                 Util::rotate_phase_origin(data, nx, ny, nz);
00813         }
00814 
00815         portable_fseek(mrcfile, sizeof(MrcHeader), SEEK_SET);
00816 
00817         if ( (is_big_endian != ByteOrder::is_host_big_endian()) || !use_host_endian) {
00818                 if (mrch.mode != MRC_UCHAR) {
00819                         if (mode_size == sizeof(short)) {
00820                                 ByteOrder::swap_bytes((short*) data, size);
00821                         }
00822                         else if (mode_size == sizeof(float)) {
00823                                 ByteOrder::swap_bytes((float*) data, size);
00824                         }
00825                 }
00826         }
00827         mode_size = get_mode_size(mrch.mode);
00828 
00829 //      int xlen = 0, ylen = 0, zlen = 0;
00830 //      EMUtil::get_region_dims(area, nx, &xlen, mrch.ny, &ylen, mrch.nz, &zlen);
00831 //      int size = xlen * ylen * zlen;
00832         void * ptr_data = data;
00833 
00834         float rendermin = 0.0f;
00835         float rendermax = 0.0f;
00836         EMUtil::getRenderMinMax(data, nx, ny, rendermin, rendermax, nz);
00837 
00838         unsigned char *cdata = 0;
00839         short *sdata = 0;
00840         unsigned short *usdata = 0;
00841         if (mrch.mode == MRC_UCHAR) {
00842                 cdata = new unsigned char[size];
00843                 for (size_t i = 0; i < size; ++i) {
00844                         if(data[i] <= rendermin) {
00845                                 cdata[i] = 0;
00846                         }
00847                         else if(data[i] >= rendermax){
00848                                 cdata[i] = UCHAR_MAX;
00849                         }
00850                         else {
00851                                 cdata[i]=(unsigned char)((data[i]-rendermin)/(rendermax-rendermin)*UCHAR_MAX);
00852                         }
00853                 }
00854                 ptr_data = cdata;
00855                 update_stat((void *)cdata);
00856         }
00857         else if (mrch.mode == MRC_SHORT || mrch.mode == MRC_SHORT_COMPLEX) {
00858                 sdata = new short[size];
00859                 for (size_t i = 0; i < size; ++i) {
00860                         if(data[i] <= rendermin) {
00861                                 sdata[i] = SHRT_MIN;
00862                         }
00863                         else if(data[i] >= rendermax) {
00864                                 sdata[i] = SHRT_MAX;
00865                         }
00866                         else {
00867                                 sdata[i]=(short)(((data[i]-rendermin)/(rendermax-rendermin))*(SHRT_MAX-SHRT_MIN) - SHRT_MAX);
00868                         }
00869                 }
00870                 ptr_data = sdata;
00871                 update_stat((void *)sdata);
00872         }
00873         else if (mrch.mode == MRC_USHORT) {
00874                 usdata = new unsigned short[size];
00875                 for (size_t i = 0; i < size; ++i) {
00876                         if(data[i] <= rendermin) {
00877                                 usdata[i] = 0;
00878                         }
00879                         else if(data[i] >= rendermax) {
00880                                 usdata[i] = USHRT_MAX;
00881                         }
00882                         else {
00883                                 usdata[i]=(unsigned short)((data[i]-rendermin)/(rendermax-rendermin)*USHRT_MAX);
00884                         }
00885                 }
00886                 ptr_data = usdata;
00887                 update_stat((void *)usdata);
00888         }
00889 
00890         // New way to write data which includes region writing.
00891         // If it is tested to be OK, remove the old code in the
00892         // #if 0  ... #endif block.
00893         EMUtil::process_region_io(ptr_data, mrcfile, WRITE_ONLY, image_index,
00894                                                           mode_size, nx, mrch.ny, mrch.nz, area);
00895 
00896         if(cdata) {delete [] cdata; cdata=0;}
00897         if(sdata) {delete [] sdata; sdata=0;}
00898         if(usdata) {delete [] usdata; usdata=0;}
00899 
00900 #if 0
00901         int row_size = nx * get_mode_size(mrch.mode);
00902         int sec_size = nx * ny;
00903 
00904         unsigned char *cbuf = new unsigned char[row_size];
00905         unsigned short *sbuf = (unsigned short *) cbuf;
00906 
00907         for (int i = 0; i < nz; i++) {
00908                 int i2 = i * sec_size;
00909                 for (int j = 0; j < ny; j++) {
00910                         int k = i2 + j * nx;
00911                         void *pbuf = 0;
00912 
00913                         switch (mrch.mode) {
00914                         case MRC_UCHAR:
00915                                 for (int l = 0; l < nx; l++) {
00916                                         cbuf[l] = static_cast < unsigned char >(data[k + l]);
00917                                 }
00918                                 pbuf = cbuf;
00919                                 fwrite(cbuf, row_size, 1, mrcfile);
00920                                 break;
00921 
00922                         case MRC_SHORT:
00923                         case MRC_SHORT_COMPLEX:
00924                                 for (int l = 0; l < nx; l++) {
00925                                         sbuf[l] = static_cast < short >(data[k + l]);
00926                                 }
00927                                 pbuf = sbuf;
00928                                 fwrite(sbuf, row_size, 1, mrcfile);
00929                                 break;
00930 
00931                         case MRC_USHORT:
00932                                 for (int l = 0; l < nx; l++) {
00933                                         sbuf[l] = static_cast < unsigned short >(data[k + l]);
00934                                 }
00935                                 pbuf = sbuf;
00936                                 fwrite(sbuf, row_size, 1, mrcfile);
00937                                 break;
00938 
00939                         case MRC_FLOAT:
00940                         case MRC_FLOAT_COMPLEX:
00941                                 pbuf = &data[k];
00942                                 break;
00943                         }
00944                         if (pbuf) {
00945                                 fwrite(pbuf, row_size, 1, mrcfile);
00946                         }
00947                 }
00948         }
00949 
00950         if(cbuf)
00951         {
00952                 delete[]cbuf;
00953                 cbuf = 0;
00954         }
00955 #endif
00956 
00957         EXITFUNC;
00958         return 0;
00959 }
00960 
00961 void MrcIO::update_stat(void* data)
00962 {
00963         size_t size =  mrch.nx * mrch.ny * mrch.nz;
00964         float v = 0.0f; //variable to hold pixel value
00965         double sum = 0.0;
00966         double square_sum = 0.0;
00967         double mean = 0.0;
00968         float min, max;
00969         
00970         unsigned char * cdata = 0;
00971         short * sdata = 0;
00972         unsigned short * usdata = 0;
00973         
00974         if (mrch.mode == MRC_UCHAR) {
00975                 max = 0.0f;
00976                 min = UCHAR_MAX;
00977                 cdata = (unsigned char *)data;
00978                 
00979                 for (size_t i = 0; i < size; ++i) {
00980                         v = (float)(cdata[i]);
00981 #ifdef _WIN32
00982                         max = _cpp_max(max,v);
00983                         min = _cpp_min(min,v);
00984 #else
00985                         max=std::max<float>(max,v);
00986                         min=std::min<float>(min,v);
00987 #endif  //_WIN32
00988                         
00989                         sum += v;
00990                         square_sum += v * v;
00991                 }
00992         }
00993         else if (mrch.mode == MRC_SHORT || mrch.mode == MRC_SHORT_COMPLEX) {
00994                 max = (float)SHRT_MIN;
00995                 min = (float)SHRT_MAX;
00996                 sdata = (short *)data;
00997                 
00998                 for (size_t i = 0; i < size; ++i) {
00999                         v = (float)(sdata[i]);
01000 #ifdef _WIN32
01001                         max = _cpp_max(max,v);
01002                         min = _cpp_min(min,v);
01003 #else
01004                         max=std::max<float>(max,v);
01005                         min=std::min<float>(min,v);
01006 #endif  //_WIN32
01007                         
01008                         sum += v;
01009                         square_sum += v * v;
01010                 }
01011         }
01012         else if (mrch.mode == MRC_USHORT) {
01013                 max = 0.0f;
01014                 min = (float)USHRT_MAX;
01015                 usdata = (unsigned short*)data;
01016                 
01017                 for (size_t i = 0; i < size; ++i) {
01018                         v = (float)(usdata[i]);
01019 #ifdef _WIN32
01020                         max = _cpp_max(max,v);
01021                         min = _cpp_min(min,v);
01022 #else
01023                         max=std::max<float>(max,v);
01024                         min=std::min<float>(min,v);
01025 #endif  //_WIN32
01026                         
01027                         sum += v;
01028                         square_sum += v * v;
01029                 }
01030         }
01031         else {
01032                 throw InvalidCallException("This function is used to write 8bit/16bit mrc file only.");
01033         }
01034         
01035         mean = sum/size;
01036 #ifdef _WIN32
01037         float sigma = (float)std::sqrt( _cpp_max(0.0,(square_sum - sum*sum / size)/(size-1)));
01038 #else
01039         float sigma = (float)std::sqrt(std::max<float>(0.0,(square_sum - sum*sum / size)/(size-1)));
01040 #endif  //_WIN32
01041 
01042         /*change mrch.amin/amax/amean.rms here*/
01043         mrch.amin = min;
01044         mrch.amax = max;
01045         mrch.amean = (float)mean;
01046         mrch.rms = sigma;
01047         
01048         MrcHeader mrch2 = mrch;
01049 
01050 //endian issue, can't get use_host_endian argument
01051 //      bool opposite_endian = false;
01052 
01053 //      if (!is_new_file) {
01054 //              if (is_big_endian != ByteOrder::is_host_big_endian()) {
01055 //                      opposite_endian = true;
01056 //              }
01057 //
01058 //              portable_fseek(mrcfile, 0, SEEK_SET);
01059 //      }
01060 //      
01061 //      if (opposite_endian || !use_host_endian) {
01062 //              swap_header(mrch2);
01063 //      }
01064 
01065         portable_fseek(mrcfile, 0, SEEK_SET);
01066         
01067         if (fwrite(&mrch2, sizeof(MrcHeader), 1, mrcfile) != 1) {
01068                 throw ImageWriteException(filename, "MRC header");
01069         }
01070         
01071         portable_fseek(mrcfile, sizeof(MrcHeader), SEEK_SET);
01072 }
01073 
01074 bool MrcIO::is_complex_mode()
01075 {
01076         init();
01077         if (mrch.mode == MRC_SHORT_COMPLEX || mrch.mode == MRC_FLOAT_COMPLEX) {
01078                 return true;
01079         }
01080         return false;
01081 }
01082 
01083 
01084 int MrcIO::read_ctf(Ctf & ctf, int)
01085 {
01086         ENTERFUNC;
01087         init();
01088         size_t n = strlen(CTF_MAGIC);
01089 
01090         int err = 1;
01091         if (strncmp(&mrch.labels[0][0], CTF_MAGIC, n) == 0) {
01092                 err = ctf.from_string(string(&mrch.labels[0][n]));
01093         }
01094         EXITFUNC;
01095         return err;
01096 }
01097 
01098 void MrcIO::write_ctf(const Ctf & ctf, int)
01099 {
01100         ENTERFUNC;
01101         init();
01102 
01103         string ctf_str = ctf.to_string();
01104 #ifdef _WIN32
01105         _snprintf(&mrch.labels[0][0],80, "%s%s", CTF_MAGIC, ctf_str.c_str());
01106 #else
01107         snprintf(&mrch.labels[0][0],80, "%s%s", CTF_MAGIC, ctf_str.c_str());
01108 #endif  //_WIN32
01109         rewind(mrcfile);
01110 
01111         if (fwrite(&mrch, sizeof(MrcHeader), 1, mrcfile) != 1) {
01112                 throw ImageWriteException(filename, "write CTF info to header failed");
01113         }
01114         EXITFUNC;
01115 }
01116 
01117 void MrcIO::flush()
01118 {
01119         fflush(mrcfile);
01120 }
01121 
01122 
01123 int MrcIO::get_mode_size(int mm)
01124 {
01125         MrcIO::MrcMode m = static_cast < MrcMode > (mm);
01126 
01127         int msize = 0;
01128         switch (m) {
01129         case MRC_UCHAR:
01130                 msize = sizeof(char);
01131                 break;
01132         case MRC_SHORT:
01133         case MRC_USHORT:
01134         case MRC_SHORT_COMPLEX:
01135                 msize = sizeof(short);
01136                 break;
01137         case MRC_FLOAT:
01138         case MRC_FLOAT_COMPLEX:
01139                 msize = sizeof(float);
01140                 break;
01141         default:
01142                 msize = 0;
01143         }
01144 
01145         return msize;
01146 }
01147 
01148 int MrcIO::to_em_datatype(int m)
01149 {
01150         EMUtil::EMDataType e = EMUtil::EM_UNKNOWN;
01151 
01152         switch (m) {
01153         case MRC_UCHAR:
01154                 e = EMUtil::EM_UCHAR;
01155                 break;
01156         case MRC_SHORT:
01157                 e = EMUtil::EM_SHORT;
01158                 break;
01159         case MRC_USHORT:
01160                 e = EMUtil::EM_USHORT;
01161                 break;
01162         case MRC_SHORT_COMPLEX:
01163                 e = EMUtil::EM_SHORT_COMPLEX;
01164                 break;
01165         case MRC_FLOAT:
01166                 e = EMUtil::EM_FLOAT;
01167                 break;
01168         case MRC_FLOAT_COMPLEX:
01169                 e = EMUtil::EM_FLOAT_COMPLEX;
01170                 break;
01171         default:
01172                 e = EMUtil::EM_UNKNOWN;
01173         }
01174         return e;
01175 }
01176 
01177 
01178 int MrcIO::to_mrcmode(int e, int is_complex)
01179 {
01180         MrcMode m = MRC_UNKNOWN;
01181         EMUtil::EMDataType em_type = static_cast < EMUtil::EMDataType > (e);
01182 
01183         switch (em_type) {
01184         case EMUtil::EM_UCHAR:
01185                 m = MRC_UCHAR;
01186                 break;
01187         case EMUtil::EM_USHORT:
01188                 if (is_complex) {
01189                         m = MRC_SHORT_COMPLEX;
01190                 }
01191                 else {
01192                         m = MRC_USHORT;
01193                 }
01194                 break;
01195         case EMUtil::EM_SHORT:
01196                 if (is_complex) {
01197                         m = MRC_SHORT_COMPLEX;
01198                 }
01199                 else {
01200                         m = MRC_SHORT;
01201                 }
01202                 break;
01203         case EMUtil::EM_SHORT_COMPLEX:
01204         case EMUtil::EM_USHORT_COMPLEX:
01205                 m = MRC_SHORT_COMPLEX;
01206                 break;
01207         case EMUtil::EM_CHAR:
01208         case EMUtil::EM_INT:
01209         case EMUtil::EM_UINT:
01210         case EMUtil::EM_FLOAT:
01211                 if (is_complex) {
01212                         m = MRC_FLOAT_COMPLEX;
01213                 }
01214                 else {
01215                         m = MRC_FLOAT;
01216                 }
01217                 break;
01218         case EMUtil::EM_FLOAT_COMPLEX:
01219                 m = MRC_FLOAT_COMPLEX;
01220                 break;
01221         default:
01222                 m = MRC_FLOAT;
01223         }
01224 
01225         return m;
01226 }
01227 
01228 
01229 
01230 int MrcIO::generate_machine_stamp()
01231 {
01232         int stamp = 0;
01233         char *p = (char *) (&stamp);
01234 
01235         if (ByteOrder::is_host_big_endian()) {
01236                 p[0] = 0x11;
01237                 p[1] = 0x11;
01238                 p[2] = 0;
01239                 p[3] = 0;
01240         }
01241         else {
01242                 p[0] = 0x44;
01243                 p[1] = 0x41;
01244                 p[2] = 0;
01245                 p[3] = 0;
01246         }
01247         return stamp;
01248 }
01249 
01250 void MrcIO::swap_header(MrcHeader& mrch)
01251 {
01252         ByteOrder::swap_bytes((int *) &mrch, NUM_4BYTES_PRE_MAP);
01253         ByteOrder::swap_bytes((int *) &mrch.machinestamp, NUM_4BYTES_AFTER_MAP);
01254 }
01255 
01256 int MrcIO::get_nimg()
01257 {
01258         init();
01259 
01260         return 1;
01261 }
01262 
01263 int MrcIO::transpose(float *data, int xlen, int ylen, int zlen) const
01264 {
01265         float * tmp = new float[xlen*ylen];
01266 
01267         for(size_t z=0; z<(size_t)zlen; ++z) {
01268                 for(size_t y=0; y<(size_t)ylen; ++y) {
01269                         for(size_t x=0; x<(size_t)xlen; ++x) {
01270                                 tmp[x*ylen+y] = data[z*xlen*ylen+y*xlen+x];
01271                         }
01272                 }
01273                 std::copy(tmp, tmp+xlen*ylen, data+z*xlen*ylen);
01274         }
01275 
01276         delete [] tmp;
01277 
01278         return 0;
01279 }

Generated on Thu Nov 17 12:42:59 2011 for EMAN2 by  doxygen 1.4.7