EMAN2
emdata_io.cpp
Go to the documentation of this file.
1/*
2 * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
3 * Copyright (c) 2000-2006 Baylor College of Medicine
4 *
5 * This software is issued under a joint BSD/GNU license. You may use the
6 * source code in this file under either license. However, note that the
7 * complete EMAN2 and SPARX software packages have some GPL dependencies,
8 * so you are responsible for compliance with the licenses of these packages
9 * if you opt to use BSD licensing. The warranty disclaimer below holds
10 * in either instance.
11 *
12 * This complete copyright notice must be included in any revised version of the
13 * source code. Additional authorship citations may be added, but existing
14 * author citations must be preserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * */
31
32#include <iomanip>
33
34#include "emdata.h"
35#include "io/all_imageio.h"
36#include "ctf.h"
37
38#include <iostream>
39using std::cout;
40using std::endl;
41
42#include <memory>
43#include <sys/stat.h>
44
45using std::shared_ptr;
46using namespace EMAN;
47
48void EMData::_read_image(ImageIO *imageio, int img_index, bool nodata,
49 const Region * region, bool is_3d)
50{
51 int err = imageio->read_header(attr_dict, img_index, region, is_3d);
52 if (err)
53 throw ImageReadException(imageio->get_filename(), "imageio read header failed");
54 else {
55 LstIO * myLstIO = dynamic_cast<LstIO *>(imageio);
56 if(!myLstIO)
57 attr_dict["source_path"] = imageio->get_filename(); //"source_path" is set to full path of reference image for LstIO, so skip this statement
58 attr_dict["source_n"] = img_index;
59 if (imageio->is_complex_mode()) {
60 set_complex(true);
61 set_fftpad(true);
62 }
63 if (attr_dict.has_key("is_fftodd") && (int)attr_dict["is_fftodd"] == 1)
64 set_fftodd(true);
65 if ((int) attr_dict["is_complex_ri"] == 1)
66 set_ri(true);
68
69 nx = attr_dict["nx"];
70 ny = attr_dict["ny"];
71 nz = attr_dict["nz"];
72 attr_dict.erase("nx");
73 attr_dict.erase("ny");
74 attr_dict.erase("nz");
75
76 if (!nodata) {
77 if (region) {
78 nx = (int)region->get_width();
79 if (nx <= 0) nx = 1;
80 ny = (int)region->get_height();
81 if (ny <= 0) ny = 1;
82 nz = (int)region->get_depth();
83 if (nz <= 0) nz = 1;
85 to_zero(); // This could be avoided in favor of setting only the regions that were not read to to zero... but tedious
86 } // else the dimensions of the file being read match those of this
87 else
88 set_size(nx, ny, nz);
89
90 // If GPU features are enabled there is danger that rdata will
91 // not be allocated, but set_size takes care of this, so this
92 // should be safe.
93 int err = imageio->read_data(get_data(), img_index, region, is_3d);
94 if (err)
95 throw ImageReadException(imageio->get_filename(), "imageio read data failed");
96 else
97 update();
98 }
99 else {
101 rdata=0;
102 }
103 }
104}
105
106void EMData::read_image(const string & filename, int img_index, bool nodata,
107 const Region * region, bool is_3d,
108 EMUtil::ImageType imgtype)
109{
110 ENTERFUNC;
111
112 ImageIO *imageio = EMUtil::get_imageio(filename, ImageIO::READ_ONLY, imgtype);
113
114 if (!imageio)
115 throw ImageFormatException("cannot create an image io");
116
117 _read_image(imageio, img_index, nodata, region, is_3d);
118
119 EMUtil::close_imageio(filename, imageio);
120 imageio = 0;
121 EXITFUNC;
122}
123
124void EMData::read_binedimage(const string & filename, int img_index, int binfactor, bool fast, bool is_3d)
125{
126 ENTERFUNC;
127
128 ImageIO *imageio = EMUtil::get_imageio(filename, ImageIO::READ_ONLY);
129
130 if (!imageio) {
131 throw ImageFormatException("cannot create an image io");
132 }
133 else {
134 int err = imageio->read_header(attr_dict, img_index, 0, is_3d);
135 if (err) {
136 throw ImageReadException(filename, "imageio read header failed");
137 }
138 else {
139 attr_dict["source_path"] = filename;
140 attr_dict["source_n"] = img_index;
141 if (imageio->is_complex_mode()) {
142 set_complex(true);
143 set_fftpad(true);
144 }
145 if (attr_dict.has_key("is_fftodd") && (int)attr_dict["is_fftodd"] == 1) {
146 set_fftodd(true);
147 }
148 if ((int) attr_dict["is_complex_ri"] == 1) {
149 set_ri(true);
150 }
151 save_byteorder_to_dict(imageio);
152
153 int ori_nx = nx = attr_dict["nx"];
154 int ori_ny = ny = attr_dict["ny"];
155 int ori_nz = nz = attr_dict["nz"];
156 if (!fast) ori_nz-=ori_nz%binfactor; // makes sure Z is a multiple of binfactor, hack to fix the poor logic in the original routine
157 attr_dict.erase("nx");
158 attr_dict.erase("ny");
159 attr_dict.erase("nz");
160
161 // At this point nx, ny and nz are all reduced by binfactor
162 set_size(nx/binfactor, ny/binfactor, nz/binfactor);
163
164 //here is where we read in the binned data
165 EMData* tempdata = new EMData();
166 size_t sizeofslice = nx*ny*sizeof(float);
167
168 //zbin factor use 1 to speed binning(but don't benfit by averaging in Z)
169 int zbin = binfactor;
170 if(fast) zbin = 1;
171 //verbose
172 float percent = 0.1f;
173 for(int k = 0; k < ori_nz; k+=binfactor){
174 if(k > ori_nz*percent){
175 printf("%1.0f %% Done\n",100.0*float(k)/float(ori_nz));
176 percent+=0.1f;
177 }
178 // read in a slice region
179// printf("%d %d %d %d\n",k,ori_nx,ori_ny,zbin);
180 const Region* binregion = new Region(0,0,k,ori_nx,ori_ny,zbin);
181 tempdata->read_image(filename, 0, false, binregion);
182 // shrink the slice
183 if (binfactor > 1) tempdata->process_inplace("math.meanshrink",Dict("n",binfactor));
184 size_t offset = nx*ny*k/binfactor;
185 //add slice to total
186 EMUtil::em_memcpy(get_data()+offset,tempdata->get_data(),sizeofslice);
187 delete binregion;
188 }
189
190 delete tempdata;
191 update();
192 }
193 }
194
195 EMUtil::close_imageio(filename, imageio);
196 imageio = 0;
197 EXITFUNC;
198}
199
200void EMData::_write_image(ImageIO *imageio, int img_index,
201 EMUtil::ImageType imgtype,
202 bool header_only, const Region * region,
203 EMUtil::EMDataType filestoragetype,
204 bool use_host_endian)
205{
206 if (!imageio)
207 throw ImageFormatException("cannot create an image io");
208 else {
209 update_stat();
210 /* Let each image format decide how to deal with negative image_index*/
211// if (img_index < 0) {
212// img_index = imageio->get_nimg();
213// }
214 LOGVAR("header write %d",img_index);
215
216 switch(filestoragetype) {
217 case EMUtil::EM_UINT:
218 attr_dict["datatype"] = (int)EMUtil::EM_UINT;
219 break;
221 attr_dict["datatype"] = (int)EMUtil::EM_USHORT;
222 break;
223 case EMUtil::EM_SHORT:
224 attr_dict["datatype"] = (int)EMUtil::EM_SHORT;
225 break;
226 case EMUtil::EM_CHAR:
227 attr_dict["datatype"] = (int)EMUtil::EM_CHAR;
228 break;
229 case EMUtil::EM_UCHAR:
230 attr_dict["datatype"] = (int)EMUtil::EM_UCHAR;
231 break;
232 default:
233 attr_dict["datatype"] = (int)EMUtil::EM_FLOAT;; //default float
234 }
235
236 int err = imageio->write_header(attr_dict, img_index, region, filestoragetype,
237 use_host_endian);
238 if (err)
239 throw ImageWriteException(imageio->get_filename(), "imageio write header failed");
240 else {
241 if (!header_only) {
242 if (imgtype == EMUtil::IMAGE_LST) {
243 const char *reffile = attr_dict["LST.reffile"];
244 if (strcmp(reffile, "") == 0)
245 reffile = path.c_str();
246 int refn = attr_dict["LST.refn"];
247 if (refn < 0)
248 refn = pathnum;
249
250 const char *comment = attr_dict["LST.comment"];
251 char *lstdata = new char[1024];
252 sprintf(lstdata, "%d\t%s", refn, reffile);
253 if(strcmp(comment, "") != 0)
254 sprintf(lstdata+strlen(lstdata), "\t%s\n", comment);
255 else
256 strcat(lstdata, "\n");
257 err = imageio->write_data((float*)lstdata, img_index,
258 region, filestoragetype, use_host_endian);
259 if( lstdata )
260 {
261 delete [] lstdata;
262 lstdata = 0;
263 }
264 }
265 if (imgtype == EMUtil::IMAGE_LSTFAST) {
266 const char *reffile = attr_dict["LST.reffile"];
267 if (strcmp(reffile, "") == 0)
268 reffile = path.c_str();
269 int refn = attr_dict["LST.refn"];
270 if (refn < 0)
271 refn = pathnum;
272
273 const char *comment = attr_dict["LST.comment"];
274 char *lstdata = new char[1024];
275 sprintf(lstdata, "%d\t%s", refn, reffile);
276 if(strcmp(comment, "") != 0)
277 sprintf(lstdata+strlen(lstdata), "\t%s\n", comment);
278 else
279 strcat(lstdata, "\n");
280 err = imageio->write_data((float*)lstdata, img_index,
281 region, filestoragetype, use_host_endian);
282 if( lstdata )
283 {
284 delete [] lstdata;
285 lstdata = 0;
286 }
287 }
288 else
289 err = imageio->write_data(get_data(), img_index, region, filestoragetype,
290 use_host_endian);
291 if (err) {
292 imageio->flush();
293 throw ImageWriteException(imageio->get_filename(), "imageio write data failed");
294 }
295 }
296 }
297 }
298 //PNG image already do cleaning in write_data function.
299 if (imgtype != EMUtil::IMAGE_PNG)
300 imageio->flush();
301}
302
303void EMData::write_image(const string & filename, int img_index,
304 EMUtil::ImageType imgtype,
305 bool header_only, const Region * region,
306 EMUtil::EMDataType filestoragetype,
307 bool use_host_endian)
308{
309 ENTERFUNC;
310
311 struct stat fileinfo;
312 if ( region && stat(filename.c_str(),&fileinfo) != 0 ) throw UnexpectedBehaviorException("To write an image using a region the file must already exist and be the correct dimensions");
313
314 if (is_complex() && is_shuffled())
315 fft_shuffle();
316
317 if (imgtype == EMUtil::IMAGE_UNKNOWN) {
318 auto pos = filename.rfind('.');
319 if (pos != string::npos)
320 imgtype = EMUtil::get_image_ext_type(filename.substr(pos+1));
321 }
323
324 //set "nx", "ny", "nz" and "changecount" in attr_dict, since they are taken out of attribute dictionary
325 attr_dict["nx"] = nx;
326 attr_dict["ny"] = ny;
327 attr_dict["nz"] = nz;
328 attr_dict["changecount"] = changecount;
329
330 // Check if this is a write only format.
331 if (Util::is_file_exist(filename) && (!header_only && region == 0)) {
332 ImageIO * tmp_imageio = EMUtil::get_imageio(filename, ImageIO::READ_ONLY, imgtype);
333 if (tmp_imageio->is_single_image_format())
334 rwmode = ImageIO::WRITE_ONLY;
335 EMUtil::close_imageio(filename, tmp_imageio);
336 tmp_imageio = 0;
337 }
338
339 LOGVAR("getimageio %d",rwmode);
340 ImageIO *imageio = EMUtil::get_imageio(filename, rwmode, imgtype);
341
342 _write_image(imageio, img_index, imgtype,
343 header_only, region, filestoragetype,
344 use_host_endian);
345
346 EMUtil::close_imageio(filename, imageio);
347 imageio = 0;
348 EXITFUNC;
349}
350
351
352void EMData::append_image(const string & filename,
353 EMUtil::ImageType imgtype, bool header_only)
354{
355 ENTERFUNC;
356 write_image(filename, -1, imgtype, header_only, 0);
357 EXITFUNC;
358}
359
360
361void EMData::write_lst(const string & filename, const string & reffile,
362 int refn, const string & comment)
363{
364 ENTERFUNC;
365 attr_dict["LST.reffile"] = reffile;
366 attr_dict["LST.refn"] = refn;
367 attr_dict["LST.comment"] = comment;
368 write_image(filename, -1, EMUtil::IMAGE_LST, false);
369 EXITFUNC;
370}
371
372vector<shared_ptr<EMData>> EMData::read_images(const string & filename, vector<int> img_indices,
373 EMUtil::ImageType imgtype,
374 bool header_only)
375{
376 ENTERFUNC;
377
378 int total_img = EMUtil::get_image_count(filename);
379 size_t num_img = img_indices.size();
380
381 for (size_t i = 0; i < num_img; i++)
382 if (img_indices[i] < 0 || img_indices[i] >= total_img)
383 throw OutofRangeException(0, total_img, img_indices[i], "image index");
384
385 size_t n = (num_img == 0 ? total_img : num_img);
386 ImageIO *imageio = EMUtil::get_imageio(filename, ImageIO::READ_ONLY, imgtype);
387
388 vector<shared_ptr<EMData>> v;
389 for (size_t j = 0; j < n; j++) {
390 shared_ptr<EMData> d(new EMData());
391 size_t k = (num_img == 0 ? j : img_indices[j]);
392 try {
393 d->_read_image(imageio, (int)k, header_only);
394 }
395 catch(E2Exception &e) {
396 throw(e);
397 }
398 if ( d != 0 )
399 v.push_back(d);
400 else
401 throw ImageReadException(filename, "imageio read data failed");
402 }
403
404 EMUtil::close_imageio(filename, imageio);
405 imageio = 0;
406
407
408 EXITFUNC;
409 return v;
410}
411
412bool EMData::write_images(const string & filename, vector<std::shared_ptr<EMData>> imgs,
413 EMUtil::ImageType imgtype,
414 bool header_only,
415 const Region * region,
416 EMUtil::EMDataType filestoragetype,
417 bool use_host_endian)
418{
419 ENTERFUNC;
420
421 ImageIO *imageio = EMUtil::get_imageio(filename, ImageIO::WRITE_ONLY);
422
423 auto num_imgs = imgs.size();
424 for (size_t i = 0; i < num_imgs; i++) {
425 auto d = imgs[i].get();
426 try {
427 d->_write_image(imageio, (int)i, imgtype, header_only, region, filestoragetype, use_host_endian);
428 }
429 catch(E2Exception &e) {
430 throw(e);
431 }
432 }
433
434 EMUtil::close_imageio(filename, imageio);
435 imageio = 0;
436
437
438 EXITFUNC;
439 return true;
440}
441
442ostream& operator<<(ostream& out, const EMData& obj) {
443 int nx = obj.get_xsize();
444 int ny = obj.get_ysize();
445 int nz = obj.get_zsize();
446 for (int iz = 0; iz < nz; iz++) {
447 out << "(z = " << iz << " slice)" << std::endl;
448 for (int ix = 0; ix < nx; ix++) {
449 for (int iy = 0; iy < ny; iy++) {
450 out << std::setiosflags(std::ios::fixed)
451 << std::setiosflags(std::ios_base::scientific)
452 << std::setw(12)
453 << std::setprecision(5) << obj(ix,iy,iz) << " ";
454 if (((iy+1) % 6) == 0) {
455 out << std::endl << " ";
456 }
457 }
458 out << std::endl;
459 }
460 }
461 return out;
462}
Dict is a dictionary to store <string, EMObject> pair.
Definition: emobject.h:385
void erase(const string &key)
Remove a particular key.
Definition: emobject.h:552
bool has_key(const string &key) const
Ask the Dictionary if it as a particular key.
Definition: emobject.h:511
E2Exception class is the parent class of all EMAN2 E2Exceptions.
Definition: exception.h:67
EMData stores an image's data and defines core image processing routines.
Definition: emdata.h:82
void update_stat() const
Definition: emdata.cpp:3091
int pathnum
Definition: emdata.h:858
void save_byteorder_to_dict(ImageIO *imageio)
Definition: emdata.cpp:4349
EMData()
For all image I/O.
Definition: emdata.cpp:70
int changecount
Definition: emdata.h:846
float * rdata
image real data
Definition: emdata.h:835
Dict attr_dict
to store all image header info
Definition: emdata.h:833
string path
Definition: emdata.h:857
int nx
image size
Definition: emdata.h:848
static void em_memcpy(void *dst, const void *const src, const size_t size)
Definition: emutil.h:384
static void close_imageio(const string &filename, const ImageIO *io)
Ian: Close ImageIO object.
Definition: emutil.cpp:720
static int get_image_count(const string &filename)
Get the number of images in an image file.
Definition: emutil.cpp:534
EMDataType
Image pixel data type used in EMAN.
Definition: emutil.h:92
@ EM_UCHAR
Definition: emutil.h:95
@ EM_USHORT
Definition: emutil.h:97
@ EM_SHORT
Definition: emutil.h:96
static ImageIO * get_imageio(const string &filename, int rw_mode, ImageType image_type=IMAGE_UNKNOWN)
Get an ImageIO object.
Definition: emutil.cpp:558
ImageType
Image format types.
Definition: emutil.h:112
@ IMAGE_LSTFAST
Definition: emutil.h:140
@ IMAGE_UNKNOWN
Definition: emutil.h:113
static ImageType get_image_ext_type(const string &file_ext)
Get an image's format type from its filename extension.
Definition: emutil.cpp:58
static void em_free(void *data)
Definition: emutil.h:380
ImageIO classes are designed for reading/writing various electron micrography image formats,...
Definition: imageio.h:127
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.
string get_filename() const
Definition: imageio.h:268
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.
virtual bool is_single_image_format() const
Is this image format only storing 1 image or not.
Definition: imageio.h:250
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.
A LST file is an ASCII file that contains a list of image file names.
Definition: lstio.h:46
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
Definition: geometry.h:497
float get_width() const
get the width
Definition: geometry.h:606
float get_depth() const
get the depth
Definition: geometry.h:610
float get_height() const
get the height
Definition: geometry.h:608
static bool is_file_exist(const string &filename)
check whether a file exists or not
Definition: util.cpp:253
void to_zero()
Set all the pixel value = 0.
void write_lst(const string &filename, const string &reffile="", int refn=-1, const string &comment="")
Append data to a LST image file.
Definition: emdata_io.cpp:361
void append_image(const string &filename, EMUtil::ImageType imgtype=EMUtil::IMAGE_UNKNOWN, bool header_only=false)
append to an image file; If the file doesn't exist, create one.
void read_binedimage(const string &filename, int img_index=0, int binfactor=0, bool fast=false, bool is_3d=false)
read in a binned image, bin while reading.
Definition: emdata_io.cpp:124
void _read_image(ImageIO *imageio, int img_index=0, bool header_only=false, const Region *region=0, bool is_3d=false)
This file is a part of "emdata.h", to use functions in this file, you should "#include "emdata....
void write_image(const string &filename, int img_index=0, EMUtil::ImageType imgtype=EMUtil::IMAGE_UNKNOWN, bool header_only=false, const Region *region=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)
write the header and data out to an image.
static vector< std::shared_ptr< EMData > > read_images(const string &filename, vector< int > img_indices=vector< int >(), EMUtil::ImageType imgtype=EMUtil::IMAGE_UNKNOWN, bool header_only=false)
Read a set of images from file specified by 'filename'.
void _write_image(ImageIO *imageio, int img_index=0, EMUtil::ImageType imgtype=EMUtil::IMAGE_UNKNOWN, bool header_only=false, const Region *region=0, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)
void read_image(const string &filename, int img_index=0, bool header_only=false, const Region *region=0, bool is_3d=false, EMUtil::ImageType imgtype=EMUtil::IMAGE_UNKNOWN)
read an image file and stores its information to this EMData object.
static bool write_images(const string &filename, vector< std::shared_ptr< EMData > > imgs, EMUtil::ImageType imgtype=EMUtil::IMAGE_UNKNOWN, bool header_only=false, const Region *region=nullptr, EMUtil::EMDataType filestoragetype=EMUtil::EM_FLOAT, bool use_host_endian=true)
Write a set of images to file specified by 'filename'.
void set_fftodd(bool is_fftodd)
Mark this image as having (real-space) odd nx.
void set_fftpad(bool is_fftpadded)
Mark this image as already extended along x for ffts.
void set_ri(bool is_ri)
Mark this image as a real/imaginary format complex image.
bool is_complex() const
Is this a complex image?
bool is_shuffled() const
Has this image been shuffled?
void set_size(int nx, int ny=1, int nz=1, bool noalloc=false)
Resize this EMData's main board memory pointer.
void update()
Mark EMData as changed, statistics, etc will be updated at need.
float * get_data() const
Get the image pixel density data in a 1D float array.
void set_complex(bool is_complex)
Mark this image as a complex image.
#define ImageReadException(filename, desc)
Definition: exception.h:204
#define ImageFormatException(desc)
Definition: exception.h:147
#define OutofRangeException(low, high, input, objname)
Definition: exception.h:334
#define UnexpectedBehaviorException(desc)
Definition: exception.h:400
#define ImageWriteException(imagename, desc)
Definition: exception.h:223
#define ENTERFUNC
Definition: log.h:48
#define LOGVAR
Definition: log.h:57
#define EXITFUNC
Definition: log.h:49
E2Exception class.
Definition: aligner.h:40
std::ostream & operator<<(std::ostream &os, const ScreenVector &v)
Definition: vecmath.h:133