EMAN2
xplorio.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#ifdef WIN32
33#include <time.h>
34#include <windows.h>
35#define MAXPATHLEN (MAX_PATH*4)
36#else
37#include <sys/param.h>
38#endif
39
40#include <cstring>
41#include "xplorio.h"
42#include "util.h"
43#include "emassert.h"
44#include "portable_fileio.h"
45#include "geometry.h"
46
47
48using namespace EMAN;
49
50const string XplorIO::SECTION_MODE = "ZYX";
51const int XplorIO::NFLOAT_PER_LINE = 6;
52const int XplorIO::INTEGER_SIZE = 8;
53const int XplorIO::FLOAT_SIZE = 12;
54const char * XplorIO::OUTFORMAT = "%12.5E";
55
56XplorIO::XplorIO(const string & fname, IOMode rw)
57: ImageIO(fname, rw)
58{
60 is_new_file = false;
62
63 nx = 0;
64 ny = 0;
65 nz = 0;
66
67 apix_x = 0;
68 apix_y = 0;
69 apix_z = 0;
70
71 cell_alpha = 0;
72 cell_beta = 0;
73 cell_gama = 0;
74}
75
77{
78 if (file) {
79 fclose(file);
80 file = 0;
81 }
82}
83
84void XplorIO::init()
85{
86 if (initialized) {
87 return;
88 }
89
91 initialized = true;
93
94 if (!is_new_file) {
95 char first_block[1024];
96 fread(&first_block, sizeof(char), sizeof(first_block), file);
97 if (!is_valid(&first_block)) {
98 throw ImageReadException(filename, "invalid XPLOR");
99 }
100 portable_fseek(file, 0, SEEK_SET);
101 char line[1024];
102 int i = 1;
103 int ntitle = 0;
104
105 int xmin = 0;
106 int xmax = 0;
107 int ymin = 0;
108 int ymax = 0;
109 int zmin = 0;
110 int zmax = 0;
111
112 float cellx = 0;
113 float celly = 0;
114 float cellz = 0;
115
116 while(fgets(line, sizeof(line), file)) {
117 line[strlen(line)-1] = '\0';
118 if (i == 2) {
119 ntitle = atoi(line);
120 }
121 else if (i == (ntitle+3)) {
122 if (sscanf(line, "%8d%8d%8d%8d%8d%8d%8d%8d%8d", &nx, &xmin, &xmax,
123 &ny, &ymin, &ymax, &nz, &zmin, &zmax) != 9) {
124 throw ImageReadException(filename, "invalid XPLOR");
125 }
126 }
127 else if (i == (ntitle+4)) {
128 if(sscanf(line, "%f %f %f %f %f %f",
129 &cellx, &celly, &cellz, &cell_alpha, &cell_beta, &cell_gama) != 6) {
130 throw ImageReadException(filename, "invalid XPLOR");
131 }
132 }
133 else if (i == (ntitle+5)) {
134 break;
135 }
136
137 i++;
138 }
140 apix_x = cellx / nx;
141 apix_y = celly / ny;
142 apix_z = cellz / nz;
143 }
144
145 EXITFUNC;
146}
147
148bool XplorIO::is_valid(const void *first_block)
149{
150 ENTERFUNC;
151 if (!first_block) {
152 return false;
153 }
154 char *buf = (char *)(first_block);
155 string line1 = Util::get_line_from_string(&buf);
156 bool result = true;
157
158 if (line1.size() != 0) {
159 result = false;
160 }
161 else {
162 string line2 = Util::get_line_from_string(&buf);
163 int ntitle = 0;
164
165 if ((int)line2.size() != INTEGER_SIZE) {
166 result = false;
167 }
168 else {
169 ntitle = atoi(line2.c_str());
170 if (ntitle < 0 || ntitle > 50) {
171 result = false;
172 }
173
174 else {
175 for (int i = 0; i < ntitle+2; i++) {
177 }
178
179 string modeline = Util::get_line_from_string(&buf);
180 if (modeline != SECTION_MODE) {
181 result = false;
182 }
183 }
184 }
185 }
186
187 EXITFUNC;
188 return result;
189}
190
191int XplorIO::read_header(Dict &dict, int image_index, const Region *area, bool)
192{
193 ENTERFUNC;
194
195 //single image format, index can only be zero
196 if(image_index == -1) {
197 image_index = 0;
198 }
199 if(image_index != 0) {
200 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().");
201 }
202
203 init();
205
206 int xlen = 0, ylen = 0, zlen = 0;
207 EMUtil::get_region_dims(area, nx, &xlen, ny, &ylen, nz, &zlen);
208
209 dict["nx"] = xlen;
210 dict["ny"] = ylen;
211 dict["nz"] = zlen;
212
213 dict["apix_x"] = apix_x;
214 dict["apix_y"] = apix_y;
215 dict["apix_z"] = apix_z;
216
217 dict["XPLOR.alpha"] = cell_alpha;
218 dict["XPLOR.beta"] = cell_beta;
219 dict["XPLOR.gama"] = cell_gama;
220
221 EXITFUNC;
222 return 0;
223}
224
225int XplorIO::write_header(const Dict & dict, int image_index, const Region* area,
226 EMUtil::EMDataType, bool)
227{
228 ENTERFUNC;
229 //single image format, index can only be zero
230 if(image_index == -1) {
231 image_index = 0;
232 }
233 if(image_index != 0) {
234 throw ImageWriteException(filename, "XPLOR file does not support stack.");
235 }
236 check_write_access(rw_mode, image_index);
237 if (area) {
239 EXITFUNC;
240 return 0;
241 }
242
243 nx = dict["nx"];
244 ny = dict["ny"];
245 nz = dict["nz"];
246 apix_x = dict["apix_x"];
247 apix_y = dict["apix_y"];
248 apix_z = dict["apix_z"];
249
251 time_t t0 = time(0);
252 struct tm *t = localtime(&t0);
253 rewind(file);
254
255 fprintf(file, "\n");
256 fprintf(file, "%8d\n", 1);
257 fprintf(file, "\"%s\" written by EMAN at %s", filename.c_str(), asctime(t));
258
259 int z0 = -nz / 2;
260 int z1 = (nz - 1) / 2;
261
262 if (2 * nz - 1 == nx && 2 * nz - 1 == ny) {
263 z0 = 0;
264 z1 = nz - 1;
265 }
266
267 fprintf(file, "%8d%8d%8d%8d%8d%8d%8d%8d%8d\n",
268 nx, -nx / 2, nx % 2 ? nx / 2 : nx / 2 - 1, ny, -ny / 2,
269 ny % 2 ? ny / 2 : ny / 2 - 1, nz, z0, z1);
270
271 char fformat[256];
272 sprintf(fformat, "%s%s%s%s%s%s\n",
274
275 fprintf(file, fformat,
276 nx * apix_x, ny * apix_y, nz * apix_z, 90.0, 90.0, 90.0);
277 fprintf(file, "ZYX\n");
279 flush();
280
281 EXITFUNC;
282 return 0;
283}
284
285int XplorIO::read_data(float *data, int image_index, const Region *area, bool)
286{
287 ENTERFUNC;
288
289 //single image format, index can only be zero
290 image_index = 0;
291 check_read_access(image_index);
292 FloatSize max_size = FloatSize(nx, ny, nz);
293 check_region(area, max_size, is_new_file);
294
295 // Had to put this here because this is the only function that calls
296 // EMUtil::process_ascii_region_io - this function does not allow regions that
297 // are outside the image dimensions. This is opposed to those functions which
298 // call EMUtil::process_region_io, which can handle it. David Woolford, April 23 2009
299
300 if (area != 0 && !area->is_region_in_box(max_size)) {
301 char desc[1024];
302 sprintf(desc, "Region box %s is outside image area (%d,%d,%d)",
303 area->get_string().c_str(), (int)max_size[0],
304 (int)max_size[1], (int)max_size[2]);
305 throw ImageReadException("", desc);
306 }
307
309 rewind(file);
311
313 FLOAT_SIZE, nx, ny, nz, area, true,
315
316 EXITFUNC;
317 return 0;
318}
319
320
321#if 0
322int XplorIO::read_data(float *data, int, const Region *, bool)
323{
324 ENTERFUNC;
325 int step = NFLOAT_PER_LINE;
326 char line[1024];
327 int nxy = nx * ny;
328 int nlines = nxy / step;
329 int nleft = nxy - nlines * step;
330
331 for (int k = 0; k < nz; k++) {
332 fgets(line, sizeof(line), file);
333 int kk = 0;
334 sscanf(line, "%d", &kk);
335 if (kk != (k+1)) {
336 LOGERR("section index = %d. It should be %d\n", kk, (k+1));
337 }
338
339 int k2 = k * nxy;
340
341 for (int i = 0; i < nlines; i++) {
342 fgets(line, sizeof(line), file);
343 int i2 = k2 + i * step;
344 sscanf(line, "%f %f %f %f %f %f",
345 &data[i2], &data[i2+1], &data[i2+2],
346 &data[i2+3], &data[i2+4], &data[i2+5]);
347 }
348
349 if (nleft > 0) {
350 int i2 = k2 + nlines * step;
351 fgets(line, sizeof(line), file);
352 char *pline = line;
353 for (int j = 0; j < nleft; j++) {
354 sscanf(pline, "%f", &data[i2+j]);
355 pline += FLOAT_SIZE;
356 }
357 }
358 }
359
360
361 EXITFUNC;
362 return 0;
363}
364#endif
365
366
367int XplorIO::write_data(float *data, int image_index, const Region* area,
368 EMUtil::EMDataType, bool)
369{
370
371 ENTERFUNC;
372 //single image format, index can only be zero
373 image_index = 0;
374 check_write_access(rw_mode, image_index, 1, data);
376
377 if (!is_new_file) {
378 rewind(file);
380 }
381
382 int nsecs = nx * ny;
383 int step = NFLOAT_PER_LINE;
384
385 if (!area) {
386 for (int k = 0; k < nz; ++k) {
387 fprintf(file, "%8d\n", (k+1));
388
389 for (int i = 0; i < nsecs - step; i += step) {
390 for (int j = 0; j < step; j++) {
391 fprintf(file, OUTFORMAT, data[k * nsecs + i + j]);
392 }
393 fprintf(file, "\n");
394 }
395
396 for (int l = (nsecs - 1) / step * step; l < nsecs; l++) {
397 fprintf(file, OUTFORMAT, data[k * nsecs + l]);
398 }
399
400 fprintf(file, "\n");
401 }
402
403 // not sure what this is doing. so comment out.
404 //fprintf(xplor_file, "%8d\n", -9999);
405 }
406 else {
408 image_index, FLOAT_SIZE, nx, ny, nz,
409 area, true, NFLOAT_PER_LINE, OUTFORMAT);
410
411 }
412
413 EXITFUNC;
414
415 return 0;
416}
417
418void XplorIO::flush()
419{
420 fflush(file);
421}
422
424{
425 return false;
426}
427
429{
430 init();
431 return is_big_endian;
432}
static bool is_host_big_endian()
Definition: byteorder.cpp:40
Dict is a dictionary to store <string, EMObject> pair.
Definition: emobject.h:385
EMDataType
Image pixel data type used in EMAN.
Definition: emutil.h:92
static void process_ascii_region_io(float *data, FILE *file, int rw_mode, int image_index, size_t mode_size, int nx, int ny, int nz, const Region *area, bool has_index_line, int nitems_per_line, const char *outformat)
Works for regions that are outside the image data dimension area.
Definition: emutil.cpp:1365
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.
Definition: emutil.cpp:860
static void jump_lines(FILE *file, int nlines)
Definition: emutil.cpp:1493
FloatSize is used to describe a 1D, 2D or 3D rectangular size in floating numbers.
Definition: geometry.h:105
ImageIO classes are designed for reading/writing various electron micrography image formats,...
Definition: imageio.h:127
IOMode rw_mode
Definition: imageio.h:353
string filename
Definition: imageio.h:352
void check_region(const Region *area, const FloatSize &max_size, bool is_new_file=false, bool inbounds_only=true)
Validate image I/O region.
Definition: imageio.cpp:58
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.
bool initialized
Definition: imageio.h:355
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.
Definition: imageio.cpp:135
void check_read_access(int image_index)
Validate 'image_index' in file reading.
Definition: imageio.cpp:95
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.
FILE * file
Definition: imageio.h:354
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.
Definition: imageio.cpp:113
virtual bool is_image_big_endian()=0
Is this image in big endian or not.
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
Definition: geometry.h:497
string get_string() const
Get the description of this region in a string.
Definition: geometry.cpp:138
bool is_region_in_box(const FloatSize &box) const
To check whether 'this' region is inside a given box assuming the box's origins are (0,...
Definition: geometry.cpp:123
static string get_line_from_string(char **str)
Extract a single line from a multi-line string.
Definition: util.cpp:322
static bool is_valid(const void *first_block)
Definition: xplorio.cpp:148
static const char * OUTFORMAT
Definition: xplorio.h:90
int nlines_in_header
Definition: xplorio.h:72
bool is_big_endian
Definition: xplorio.h:70
float cell_beta
Definition: xplorio.h:83
bool is_new_file
Definition: xplorio.h:71
float cell_alpha
Definition: xplorio.h:82
static const int FLOAT_SIZE
Definition: xplorio.h:89
float cell_gama
Definition: xplorio.h:84
float apix_y
Definition: xplorio.h:79
float apix_x
Definition: xplorio.h:78
static const string SECTION_MODE
Definition: xplorio.h:86
static const int NFLOAT_PER_LINE
Definition: xplorio.h:87
float apix_z
Definition: xplorio.h:80
static const int INTEGER_SIZE
Definition: xplorio.h:88
#define Assert(s)
Define Assert() function that is effective only when -DDEBUG is used.
Definition: emassert.h:42
#define ImageReadException(filename, desc)
Definition: exception.h:204
#define ImageWriteException(imagename, desc)
Definition: exception.h:223
#define LOGERR
Definition: log.h:51
#define ENTERFUNC
Definition: log.h:48
#define EXITFUNC
Definition: log.h:49
E2Exception class.
Definition: aligner.h:40
int portable_fseek(FILE *fp, off_t offset, int whence)