46const char *MrcIO::CTF_MAGIC =
"!-";
47const char *MrcIO::SHORT_CTF_MAGIC =
"!$";
49MrcIO::MrcIO(
const string & fname,
IOMode rw)
50:
ImageIO(fname, rw), mode_size(0),
51 isFEI(false),
is_ri(0), is_new_file(false),
52 is_transpose(false), is_stack(false), stack_size(1),
53 is_8_bit_packed(false), use_given_dimensions(true),
54 rendermin(0.0), rendermax(0.0), renderbits(16)
76 setbuf (stdout, NULL);
90 error_type = stat(
filename.c_str(), & status);
101 if (ext ==
"raw" || ext ==
"RAW") {
105 if (ext ==
"mrcs" || ext ==
"MRCS") {
111 if (fread(&
mrch,
sizeof(MrcHeader), 1,
file) != 1) {
115 bool do_swap, have_err;
135 for (
int ilabel = 0; ilabel < max_labels; ilabel++) {
148 LOGWARN(
"nx/ny/nz start not zero");
184 float ny_to_nx_ratio;
190 ny_to_nx_ratio = 1.0;
194 strstr(
mrch.
labels[0],
"4 bits packed") != NULL);
195 bool have_packed_filename =
196 (strstr(
filename.c_str(),
"4_bits_packed") != NULL);
198 bool ny_twice_nx = (fabs(ny_to_nx_ratio - 2.0f) <= 0.1f);
200 (have_packed_label || have_packed_filename));
206 if (getenv(
"DISALLOW_PACKED_FORMAT")) {
231 bool & do_swap,
bool & have_err)
236 int mrcmode = data[3];
240 int nsymbt = data[23];
243 int nxw, nyw, nzw, modew, mapcw, maprw, mapsw, nsymw, machw;
265 const int max_dim = 1 << 20;
269 bool debug = (getenv(
"DEBUG_MRC_SANITY"));
275 if (mach == actual_stamp) {
278 else if (machw == actual_stamp) {
283 if (1 <= mapr && mapr <= 3 &&
284 1 <= mapc && mapc <= 3 &&
285 1 <= maps && maps <= 3) {
288 else if (1 <= maprw && maprw <= 3 &&
289 1 <= mapcw && mapcw <= 3 &&
290 1 <= mapsw && mapsw <= 3) {
294 double ave_xyz = ((double) nx + (
double) ny + (double) nz) / 3.0;
295 double ave_xyzw = ((double) nxw + (
double) nyw + (double) nzw) / 3.0;
297 if (nx > 0 && ny > 0 && nz > 0 && ave_xyz <= max_dim) {
300 else if (nxw > 0 && nyw > 0 && nzw > 0 && ave_xyzw <= max_dim) {
306 errmsg =
"MRC image dimensions nonpositive or too large.";
311 if (mrcmode > 0 && mrcmode < 128) {
314 else if (modew > 0 && modew < 128) {
320 errmsg =
"MRC mode is not from 0 to 127.";
325 if (debug || (have_err && show_errors)) {
327 printf (
"file name = '%s'.\n", filnam);
330 printf (
"stamp: mach, file, swapd = %8.0x %8.0x %8.0x\n",
331 actual_stamp, mach, machw);
332 printf (
"stamp: mach, file, swapd = %d %d %d\n",
333 actual_stamp, mach, machw);
334 printf (
"nx, ny, nz, mode = %d %d %d %d\n", nx, ny, nz, mrcmode);
335 printf (
"nx, ny, nz, mode swapped = %d %d %d %d\n", nxw, nyw, nzw, modew);
336 printf (
"mapc, mapr, maps = %d %d %d\n", mapc, mapr, maps);
337 printf (
"mapc, mapr, maps swapped = %d %d %d\n", mapcw, maprw, mapsw);
338 printf (
"%s\n", errmsg.c_str());
350 const int * data = (
const int *) first_block;
355 int mrcmode = data[3];
356 int nsymbt = data[23];
358 const int max_dim = 1 << 20;
360 bool do_swap, have_err;
362 check_swap(data, NULL,
false, do_swap, have_err);
382 (nx > 1 && nx < max_dim) && (ny > 0 && ny < max_dim)
383 && (nz > 0 && nz < max_dim)) {
388 off_t file_size1 = (off_t)nx * (off_t)ny * (off_t)nz *
392 if (file_size == file_size1) {
400 LOGWARN(
"image size check fails, still try to read it...");
432 if (image_index < 0) {
436 if (image_index != 0 && !
is_stack) {
438 "no stack allowed for MRC image. For take 2D slice out of 3D image, "
439 "read the 3D image first, then use get_clip().");
444 int xlen = 0, ylen = 0, zlen = 0;
491 if (apx > 1000 || apx < 0.01) {
492 dict[
"apix_x"] = 1.0f;
495 dict[
"apix_x"] = apx;
498 if (apy > 1000 || apy < 0.01) {
499 dict[
"apix_y"] = 1.0f;
502 dict[
"apix_y"] = apy;
505 if (apz > 1000 || apz < 0.01) {
506 dict[
"apix_z"] = 1.0f;
509 dict[
"apix_z"] = apz;
530 dict[
"is_complex"] = 1;
531 dict[
"is_complex_ri"] = 1;
543 sprintf(label,
"MRC.label%d", i);
578 if(image_index < 0) {
586 int xlen = 0, ylen = 0, zlen = 0;
654 for(
int i=0; i<9; i++) {
655 sprintf(label,
"MRC.tiltangles%d", i);
666 sprintf(label,
"MRC.label%d", i);
679 dict[
"FEIMRC.a_tilt"] = feiexth.
a_tilt;
680 dict[
"FEIMRC.b_tilt"] = feiexth.
b_tilt;
682 dict[
"FEIMRC.x_stage"] = feiexth.
x_stage;
683 dict[
"FEIMRC.y_stage"] = feiexth.
y_stage;
684 dict[
"FEIMRC.z_stage"] = feiexth.
z_stage;
686 dict[
"FEIMRC.x_shift"] = feiexth.
x_shift;
687 dict[
"FEIMRC.y_shift"] = feiexth.
y_shift;
689 dict[
"FEIMRC.defocus"] = feiexth.
defocus;
690 dict[
"FEIMRC.exp_time"] = feiexth.
exp_time;
691 dict[
"FEIMRC.mean_int"] = feiexth.
mean_int;
692 dict[
"FEIMRC.tilt_axis"] = feiexth.
tilt_axis;
694 dict[
"FEIMRC.pixel_size"] = feiexth.
pixel_size;
699 dict[
"FEIMRC.ht"] = feiexth.
ht;
700 dict[
"FEIMRC.binning"] = feiexth.
binning;
716 is_stack = (ext ==
"mrcs" || ext ==
"MRCS");
718 bool append = (image_index == -1);
720 if (image_index == -1) {
724 if (image_index != 0 && !
is_stack) {
744 int new_mode =
to_mrcmode(filestoragetype, (
int) dict[
"is_complex"]);
749 bool got_one_image = (nz > 1);
751 is_ri = dict[
"is_complex_ri"];
753 bool opposite_endian =
false;
757 opposite_endian =
true;
770 if (nz <= 1 && dict.
has_key(
"xform.projection") &&
771 ! dict.
has_key(
"UCSF.chimera")) {
772 Transform * t = dict[
"xform.projection"];
781 if (t) {
delete t; t = NULL;}
783 else if (nz > 1 && dict.
has_key(
"xform.align3d") &&
784 ! dict.
has_key(
"UCSF.chimera")) {
794 if (t) {
delete t; t = NULL;}
805 mrch.
zorigin = (float) dict[
"origin_z"] - (
float) dict[
"apix_z"] * image_index;
809 if (dict.
has_key(
"MRC.nlabels")) {
816 sprintf(label,
"MRC.label%d", i);
873 else if (image_index >= nz) {
874 nz = image_index + 1;
917 if (dict.
has_key(
"MRC.nxstart")) {
924 if (dict.
has_key(
"MRC.nystart")) {
931 if (dict.
has_key(
"MRC.nzstart")) {
941 MrcHeader mrch2 =
mrch;
943 if (opposite_endian || !use_host_endian) {
947 if (fwrite(&mrch2,
sizeof(MrcHeader), 1,
file) != 1) {
984 printf(
"Warning: This image dimension is in (y,x,z), "
985 "region I/O not supported, return the whole image instead.");
991 LOGERR(
"Error: cannot read a region of a complex image.");
996 signed char * scdata = (
signed char *)
rdata;
997 unsigned char * cdata = (
unsigned char *)
rdata;
998 short * sdata = (
short *)
rdata;
999 unsigned short * usdata = (
unsigned short *)
rdata;
1002 int xlen = 0, ylen = 0, zlen = 0;
1014 size = (size_t)xlen * ylen * zlen;
1025 modesize = 11111111;
1032 image_index, modesize,
1037 size = (size_t)xlen * ylen * zlen;
1044 become_host_endian < short >(sdata, size);
1047 become_host_endian < float >(
rdata, size);
1052 size_t num_pairs = size / 2;
1053 size_t num_pts = num_pairs * 2;
1055 size_t ipt = num_pts;
1057 for (
size_t ipair = num_pairs; ipair >= 1; ipair--) {
1058 unsigned int v = (
unsigned int) cdata[ipair-1];
1060 rdata[ipt] = (float)(v >> 4);
1062 rdata[ipt] = (float)(v & 15);
1066 for (
size_t i = 0; i < size; ++i) {
1067 size_t j = size - 1 - i;
1069 rdata[j] =
static_cast < float >(cdata[j]);
1073 for (
size_t i = 0; i < size; ++i) {
1074 size_t j = size - 1 - i;
1076 rdata[j] =
static_cast < float >(scdata[j]);
1080 for (
size_t i = 0; i < size; ++i) {
1081 size_t j = size - 1 - i;
1082 rdata[j] =
static_cast < float >(sdata[j]);
1086 for (
size_t i = 0; i < size; ++i) {
1087 size_t j = size - 1 - i;
1088 rdata[j] =
static_cast < float >(usdata[j]);
1115 bool append = (image_index == -1);
1144 bool got_one_image = (nz > 1);
1150 size_t size = (size_t)nx * ny * nz;
1182 void * ptr_data = data;
1205 signed char * scdata = NULL;
1206 unsigned char * cdata = NULL;
1207 short * sdata = NULL;
1208 unsigned short * usdata = NULL;
1217 cdata =
new unsigned char[size];
1219 dont_rescale = (rmin == 0.0 && rmax == UCHAR_MAX);
1221 for (
size_t i = 0; i < size; ++i) {
1222 if (data[i] <= rmin) {
1225 else if (data[i] >= rmax){
1226 cdata[i] = UCHAR_MAX;
1228 else if (dont_rescale) {
1229 cdata[i] = (
unsigned char) data[i];
1232 cdata[i] = (
unsigned char)((data[i] - rmin) /
1243 scdata =
new signed char[size];
1245 dont_rescale = (rmin == SCHAR_MIN && rmax == SCHAR_MAX);
1247 for (
size_t i = 0; i < size; ++i) {
1248 if (data[i] <= rmin) {
1249 scdata[i] = SCHAR_MIN;
1251 else if (data[i] >= rmax){
1252 scdata[i] = SCHAR_MAX;
1254 else if (dont_rescale) {
1255 scdata[i] = (
signed char) data[i];
1258 scdata[i] = (
signed char)((data[i] - rmin) /
1260 (SCHAR_MAX - SCHAR_MIN) + SCHAR_MIN);
1269 sdata =
new short[size];
1271 dont_rescale = (rmin == SHRT_MIN && rmax == SHRT_MAX);
1273 for (
size_t i = 0; i < size; ++i) {
1274 if (data[i] <= rmin) {
1275 sdata[i] = SHRT_MIN;
1277 else if (data[i] >= rmax) {
1278 sdata[i] = SHRT_MAX;
1280 else if (dont_rescale) {
1281 sdata[i] = (short) data[i];
1284 sdata[i] = (short)(((data[i] - rmin) /
1286 (SHRT_MAX - SHRT_MIN) + SHRT_MIN);
1295 usdata =
new unsigned short[size];
1297 dont_rescale = (rmin == 0.0 && rmax == USHRT_MAX);
1299 for (
size_t i = 0; i < size; ++i) {
1300 if (data[i] <= rmin) {
1303 else if (data[i] >= rmax) {
1304 usdata[i] = USHRT_MAX;
1306 else if (dont_rescale) {
1307 usdata[i] = (
unsigned short) data[i];
1310 usdata[i] = (
unsigned short)((data[i] - rmin) /
1331 if (cdata) {
delete [] cdata; cdata = NULL;}
1332 if (scdata) {
delete [] scdata; scdata = NULL;}
1333 if (sdata) {
delete [] sdata; sdata = NULL;}
1334 if (usdata) {
delete [] usdata; usdata = NULL;}
1338 int sec_size = nx * ny;
1340 unsigned char * cbuf =
new unsigned char[row_size];
1341 unsigned short * sbuf = (
unsigned short *) cbuf;
1343 for (
int i = 0; i < nz; i++) {
1344 int i2 = i * sec_size;
1346 for (
int j = 0; j < ny; j++) {
1347 int k = i2 + j * nx;
1352 for (
int l = 0; l < nx; l++) {
1353 cbuf[l] =
static_cast < unsigned char >(data[k + l]);
1357 fwrite(cbuf, row_size, 1,
file);
1363 for (
int l = 0; l < nx; l++) {
1364 sbuf[l] =
static_cast < short >(data[k + l]);
1368 fwrite(sbuf, row_size, 1,
file);
1373 for (
int l = 0; l < nx; l++) {
1374 sbuf[l] =
static_cast < unsigned short >(data[k + l]);
1378 fwrite(sbuf, row_size, 1,
file);
1390 fwrite(pbuf, row_size, 1,
file);
1416 signed char * scdata = NULL;
1417 unsigned char * cdata = NULL;
1418 short * sdata = NULL;
1419 unsigned short * usdata = NULL;
1429 cdata = (
unsigned char *) data;
1431 else if (use_schar) {
1434 scdata = (
signed char *) data;
1436 else if (use_short) {
1437 max = (float) SHRT_MIN;
1438 min = (float) SHRT_MAX;
1439 sdata = (
short *) data;
1441 else if (use_ushort) {
1443 min = (float) USHRT_MAX;
1444 usdata = (
unsigned short *) data;
1452 for (
size_t i = 0; i < size; i++) {
1454 v = (float) (cdata[i]);
1456 else if (use_schar) {
1457 v = (float) (scdata[i]);
1459 else if (use_short) {
1460 v = (float) (sdata[i]);
1463 v = (float) (usdata[i]);
1466 if (v < min) min = v;
1467 if (v > max) max = v;
1473 mean = sum / (double) size;
1481 for (
size_t i = 0; i < size; i++) {
1483 v = (float) (cdata[i]);
1485 else if (use_schar) {
1486 v = (float) (scdata[i]);
1488 else if (use_short) {
1489 v = (float) (sdata[i]);
1492 v = (float) (usdata[i]);
1497 square_sum = square_sum + vv * vv;
1501 sigma =
std::sqrt(square_sum / (
double) (size-1));
1603 msize =
sizeof(char);
1608 msize =
sizeof(short);
1612 msize =
sizeof(float);
1716 char *p = (
char *) (&stamp);
1749 float * tmp =
new float[xlen*ylen];
1751 for(
size_t z=0; z<(size_t)zlen; ++z) {
1752 for(
size_t y=0;
y<(size_t)ylen; ++
y) {
1753 for(
size_t x=0;
x<(size_t)xlen; ++
x) {
1754 tmp[
x*ylen+
y] = data[z*xlen*ylen+
y*xlen+
x];
1758 std::copy(tmp, tmp+xlen*ylen, data+z*xlen*ylen);
static bool is_host_big_endian()
static void swap_bytes(T *data, size_t n=1)
swap the byte order of data with 'n' T-type elements.
Ctf is the base class for all CTF model.
virtual int from_string(const string &ctf)=0
virtual string to_string() const =0
Dict is a dictionary to store <string, EMObject> pair.
bool has_key(const string &key) const
Ask the Dictionary if it as a particular key.
EMAN1Ctf is the CTF model used in EMAN1.
vector< float > to_vector() const
static void process_region_io(void *cdata, FILE *file, int rw_mode, int image_index, size_t mode_size, int nx, int ny, int nz=1, const Region *area=0, bool need_flip=false, ImageType imgtype=IMAGE_UNKNOWN, int pre_row=0, int post_row=0)
Process image region IO.
EMDataType
Image pixel data type used in EMAN.
static void getRenderMinMax(float *data, const int nx, const int ny, float &rendermin, float &rendermax, int &renderbits, const int nz=1)
Calculate the min and max pixel value accepted for image nomalization, if we did not get them from im...
static void getRenderLimits(const Dict &dict, float &rendermin, float &rendermax, int &renderbits)
Get the min and max pixel value accepted for image nomalization from image attribute dictionary,...
static void get_region_dims(const Region *area, int nx, int *area_x, int ny, int *area_y, int nz=1, int *area_z=0)
Get a region's dimensions.
FloatSize is used to describe a 1D, 2D or 3D rectangular size in floating numbers.
ImageIO classes are designed for reading/writing various electron micrography image formats,...
void check_region(const Region *area, const FloatSize &max_size, bool is_new_file=false, bool inbounds_only=true)
Validate image I/O region.
virtual void flush()=0
Flush the IO buffer.
virtual int write_header(const Dict &dict, int image_index=0, const Region *area=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)=0
Write a header to an image.
virtual int write_data(float *data, int image_index=0, const Region *area=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)=0
Write data to an image.
virtual bool is_complex_mode()=0
Is this an complex image or not.
virtual int read_header(Dict &dict, int image_index=0, const Region *area=0, bool is_3d=false)=0
Read the header from an image.
FILE * sfopen(const string &filename, IOMode mode, bool *is_new=0, bool overwrite=false)
Run fopen safely.
void check_read_access(int image_index)
Validate 'image_index' in file reading.
virtual int read_data(float *data, int image_index=0, const Region *area=0, bool is_3d=false)=0
Read the data from an image.
virtual void init()=0
Do some initialization before doing the read/write.
void check_write_access(IOMode rw_mode, int image_index, int max_nimg=0)
Validate rw_mode and image_index in file writing.
virtual bool is_image_big_endian()=0
Is this image in big endian or not.
static const char * CTF_MAGIC
int get_nimg()
Return the number of images in this image file.
static void check_swap(const int *data, const char *filnam, bool show_errors, bool &do_swap, bool &have_err)
This is a utility routine to tell whether to byte swap MRC header.
int read_fei_header(Dict &dict, int image_index=0, const Region *area=0, bool is_3d=false)
int transpose(float *data, int nx, int ny, int nz) const
static bool is_valid(const void *first_block, off_t file_size=0)
static int generate_machine_stamp()
generate the machine stamp used in MRC image format.
bool use_given_dimensions
void write_ctf(const Ctf &ctf, int image_index=0)
Write CTF data to this image.
int read_mrc_header(Dict &dict, int image_index=0, const Region *area=0, bool is_3d=false)
static int to_em_datatype(int mrcmode)
void swap_header(MrcHeader &mrch)
static int get_mode_size(int mm)
void update_stats(void *data, size_t size)
This is a utility function used to calculate new min/max/mean/sigma when write MRC file as 16 bit or ...
static int to_mrcmode(int em_datatype, int is_complex)
int read_ctf(Ctf &ctf, int image_index=0)
Read CTF data from this image.
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
float get_width() const
get the width
int get_ndim() const
Get the region's dimension.
float get_depth() const
get the depth
float get_height() const
get the height
static void flip_complex_phase(float *data, size_t n)
flip the phase of a complex data array.
static string get_time_label()
Get the current time in a string with format "mm/dd/yyyy hh:mm".
static string get_filename_ext(const string &filename)
Get a filename's extension.
static void replace_non_ascii(char *str, int max_size, char repl_char='?')
Replace any non-ASCII characters in a C string with a given character.
static void rotate_phase_origin(float *data, size_t nx, size_t ny, size_t nz)
rotate data vertically by ny/2, to make the mrc phase origin compliance with EMAN1 and TNF reader
static void ap2ri(float *data, size_t n)
convert complex data array from Amplitude/Phase format into Real/Imaginary format.
static int get_min(int f1, int f2)
Get the minimum of 2 numbers.
EMData * copy() const
This file is a part of "emdata.h", to use functions in this file, you should "#include "emdata....
EMData * sqrt() const
return square root of current image
#define ImageReadException(filename, desc)
#define ImageWriteException(imagename, desc)
#define InvalidCallException(desc)
int portable_fseek(FILE *fp, off_t offset, int whence)