45const char *ImagicIO::HED_EXT =
"hed";
46const char *ImagicIO::IMG_EXT =
"img";
47const char *ImagicIO::REAL_TYPE_MAGIC =
"REAL";
48const char *ImagicIO::CTF_MAGIC =
"!-";
50ImagicIO::ImagicIO(
const string & fname,
IOMode rw)
51:
ImageIO(fname, rw), hed_file(0), img_file(0)
95 LOGWARN(
"IMAGIC header file and data file should both exist or both not exist");
129 const int *data =
static_cast < const int *
>(first_block);
131 int headrec = data[3];
148 const int max_dim = 1 << 20;
152 count >= 0 && count < max_dim &&
153 nx > 0 && nx < max_dim &&
154 ny > 0 && ny < max_dim && month >= 0 && hour >= 0 && hour <= 24) {
174 LOGWARN(
"this is not a 3D IMAGIC. Read as a 2D");
179 if (image_index == 0) {
183 memset(&hed, 0,
sizeof(ImagicHeader));
185 fread(&hed,
sizeof(ImagicHeader), 1,
hed_file);
192 int xlen = 0, ylen = 0, zlen = 0;
201 dict[
"minimum"] = hed.min;
202 dict[
"maximum"] = hed.max;
203 dict[
"mean"] = hed.avdens;
204 dict[
"sigma"] = hed.sigma;
206 dict[
"IMAGIC.imgnum"] = hed.imgnum;
207 dict[
"IMAGIC.count"] = hed.count;
208 dict[
"IMAGIC.error"] = hed.error;
210 dict[
"IMAGIC.headrec"] = hed.headrec;
211 dict[
"IMAGIC.mday"] = hed.mday;
212 dict[
"IMAGIC.month"] = hed.month;
214 dict[
"IMAGIC.year"] = hed.year;
215 dict[
"IMAGIC.hour"] = hed.hour;
216 dict[
"IMAGIC.minute"] = hed.minute;
218 dict[
"IMAGIC.sec"] = hed.sec;
219 dict[
"IMAGIC.reals"] = hed.reals;
220 dict[
"IMAGIC.pixels"] = hed.pixels;
222 char tmp[5] = { hed.type[0],hed.type[1],hed.type[2],hed.type[3],0 };
223 dict[
"IMAGIC.type"] = tmp;
224 dict[
"IMAGIC.ixold"] = hed.ixold;
225 dict[
"IMAGIC.iyold"] = hed.iyold;
227 dict[
"IMAGIC.oldav"] = hed.oldav;
228 dict[
"IMAGIC.label"] = hed.label;
229 dict[
"ptcl_repr"] = hed.mrc2;
231 dict[
"orientation_convention"] =
"EMAN";
232 const float alt = hed.mrc1[1]*180.0f/M_PI;
233 const float az = hed.mrc1[2]*180.0f/M_PI;
234 const float phi = hed.mrc1[0]*180.0f/M_PI;
235 dict[
"euler_alt"] = alt;
236 dict[
"euler_az"] = az;
237 dict[
"euler_phi"] = phi;
239 trans->
set_rotation(
Dict(
"type",
"eman",
"alt", alt,
"az", az,
"phi", phi));
241 dict[
"xform.projection"] = trans;
244 dict[
"xform.projection"] = trans;
245 dict[
"xform.align3d"] = trans;
251 if(trans) {
delete trans; trans=0;}
252 if(ctf_) {
delete ctf_; ctf_=0;}
268 if (
nz > 1 && image_index != 0) {
289 sprintf(desc,
"new IMAGIC size %dx%d is not equal to existing size %dx%d",
302 ImagicHeader new_hed;
303 memset(&new_hed, 0,
sizeof(ImagicHeader));
305 time_t cur_time = time(0);
306 struct tm *tm = localtime(&cur_time);
311 new_hed.mday = tm->tm_mday;
312 new_hed.month = tm->tm_mon;
313 new_hed.year = tm->tm_year + 1900;
314 new_hed.hour = tm->tm_hour;
315 new_hed.minute = tm->tm_min;
316 new_hed.sec = tm->tm_sec;
318 new_hed.reals = nx * ny;
319 new_hed.pixels = nx * ny;
327 new_hed.min = (float)dict[
"minimum"];
328 new_hed.max = (float)dict[
"maximum"];
329 new_hed.avdens = (float)dict[
"mean"];
330 new_hed.sigma = (float)dict[
"sigma"];
332 if(
nz<=1 && dict.
has_key(
"xform.projection")) {
333 Transform * t = dict[
"xform.projection"];
335 new_hed.mrc1[1] = (float)d[
"alt"]*M_PI/180.0f;
336 new_hed.mrc1[2] = (float)d[
"az"]*M_PI/180.0f;
337 new_hed.mrc1[0] = (float)d[
"phi"]*M_PI/180.0f;
338 if(t) {
delete t; t=0;}
340 else if(
nz>1 && dict.
has_key(
"xform.align3d")) {
343 new_hed.mrc1[1] = (float)d[
"alt"]*M_PI/180.0f;
344 new_hed.mrc1[2] = (float)d[
"az"]*M_PI/180.0f;
345 new_hed.mrc1[0] = (float)d[
"phi"]*M_PI/180.0f;
346 if(t) {
delete t; t=0;}
349 if(dict.
has_key(
"euler_alt")) new_hed.mrc1[1] = (
float)dict[
"euler_alt"]*M_PI/180.0f;
350 if(dict.
has_key(
"euler_az")) new_hed.mrc1[2] = (
float)dict[
"euler_az"]*M_PI/180.0f;
351 if(dict.
has_key(
"euler_phi")) new_hed.mrc1[0] = (
float)dict[
"euler_phi"]*M_PI/180.0f;
354 if(dict.
has_key(
"ptcl_repr")) new_hed.mrc2 = (
int)dict[
"ptcl_repr"];
356 string new_label = dict.
has_key(
"IMAGIC.label") ? (string) dict[
"IMAGIC.label"] :
"";
357 sprintf(new_hed.label,
"%s", new_label.c_str() );
368 new_hed.nhalf = nx / 2;
369 new_hed.ibsd = nx * 2;
378 new_hed.linbuf = nx * 2;
379 new_hed.ntotbuf = -1;
381 new_hed.icend = nx / 2;
389 if (image_index>=0 && image_index<nimg) {
391 new_hed.imgnum=image_index+1;
394 fwrite(&new_hed,
sizeof(ImagicHeader),1,
hed_file);
399 if (
nz>1) required_len=
nz;
401 if (image_index<0) required_len=nimg+1;
402 else if (image_index+1>nimg) required_len=image_index+1;
403 else required_len=nimg;
408 while (nimg<required_len) {
413 fwrite(&new_hed,
sizeof(ImagicHeader),1,
hed_file);
421 fwrite(&nimg,
sizeof(
int), 1,
hed_file);
430 Ctf * ctf_ = dict[
"ctf"];
432 if(ctf_) {
delete ctf_; ctf_=0;}
451 LOGWARN(
"this is not a 3D IMAGIC. Read as a 2D");
459 unsigned short *sdata = (
unsigned short *) data;
460 unsigned char *cdata = (
unsigned char *) data;
469 for (
int k = 0; k < nimg; k++) {
470 for (
int i =
imagich.
ny - 1; i >= 0; i--) {
471 if (fread(&cdata[k * sec_size + i * row_size], row_size, 1,
img_file) != 1) {
472 LOGERR(
"incomplete data read: %d/%d blocks on file '%s'",
488 for (
int j = img_size - 1; j >= 0; j--) {
489 data[j] =
static_cast < float >(sdata[j]);
510 if (image_index == -1) {
520 if(!use_host_endian) {
530 if (image_index > old_num_imgs) {
531 n_pad_imgs = image_index - old_num_imgs;
544 size_t row_size =
imagich.
nx *
sizeof(float);
547 for (
int i = 0; i <
nz; i++) {
548 for (
int j =
imagich.
ny - 1; j >= 0; j--) {
576 string header_label(hed.
label);
579 if (header_label.size() > 2) {
580 string sctf =
"O" + header_label.substr(2);
596 string ctf_ = ctf->
to_string().substr(1);
632 if (strncmp(name,
"PACK",4) == 0) {
635 else if (strncmp(name,
"INTG",4) == 0) {
641 else if (strncmp(name,
"COMP",4) == 0) {
644 else if (strncmp(name,
"RECO",4) == 0) {
655 s =
sizeof(
unsigned char);
658 s =
sizeof(
unsigned short);
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.
static bool is_data_big_endian(const T *small_num_addr)
given a pointer to a reasonable small integer number, return whether the number is big endian or not.
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.
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 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.
void become_host_endian(T *data, size_t n=1)
Convert data of this image into host endian format.
virtual bool is_image_big_endian()=0
Is this image in big endian or not.
size_t get_datatype_size(DataType t)
static const char * REAL_TYPE_MAGIC
DataType get_datatype_from_name(const char *name)
@ IMAGIC_FFT_FLOAT_COMPLEX
int get_nimg()
Return the number of images in this image file.
static bool is_valid(const void *first_block)
static const char * HED_EXT
void make_header_host_endian(ImagicHeader &hed)
int to_em_datatype(DataType t)
static const char * IMG_EXT
Ctf * read_ctf(const ImagicHeader &hed) const
the Ctf object is a EMAN1Ctf object.
void swap_header(ImagicHeader &hed)
static const char * CTF_MAGIC
void write_ctf(const Ctf *const ctf, int image_index=0)
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
static string change_filename_ext(const string &old_filename, const string &new_ext)
Change a file's extension and return the new filename.
#define Assert(s)
Define Assert() function that is effective only when -DDEBUG is used.
#define ImageReadException(filename, desc)
#define ImageWriteException(imagename, desc)
int portable_fseek(FILE *fp, off_t offset, int whence)