EMAN2
gatan2io.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 "gatan2io.h"
33#include "geometry.h"
34#include "portable_fileio.h"
35#include <cstring>
36
37using namespace EMAN;
38
39Gatan2IO::Gatan2IO(const string & fname, IOMode rw)
40: ImageIO(fname, rw)
41{
43 memset(&gatanh, 0, sizeof(Gatan2Header));
44}
45
47{
48 if (file) {
49 fclose(file);
50 file = 0;
51 }
52}
53
54void Gatan2IO::init()
55{
57
58 if (initialized) {
59 return;
60 }
61
62 initialized = true;
63
64 bool is_new_file = false;
65 file = sfopen(filename, rw_mode, &is_new_file);
66
67 if (!is_new_file) {
68 if (fread(&gatanh, sizeof(Gatan2Header), 1, file) != 1) {
69 throw ImageReadException(filename, "Gatan2 Header");
70 }
71
72 if (!is_valid(&gatanh)) {
73 throw ImageReadException(filename, "invalid Gatan2 file");
74 }
75
77 become_host_endian((short *) &gatanh, sizeof(Gatan2Header) / sizeof(short));
78 }
80}
81
82bool Gatan2IO::is_valid(const void *first_block)
83{
85 bool result = false;
86
87 if (!first_block) {
88 result = false;
89 }
90 else {
91 const short *data = static_cast < const short *>(first_block);
92 short len = data[5];
93 short type = data[6];
94
95 bool data_big_endian = ByteOrder::is_data_big_endian(&len);
96
97 if (data_big_endian != ByteOrder::is_host_big_endian()) {
100 }
101
102 int double_size = sizeof(double);
103 if (len > 0 && len <= double_size && type > 0 && type <= GATAN2_INVALID) {
104 result = true;
105 }
106 }
107 EXITFUNC;
108 return result;
109}
110
111int Gatan2IO::read_header(Dict & dict, int image_index, const Region * area, bool)
112{
113 ENTERFUNC;
114 //single image format, index can only be zero
115 if(image_index == -1) {
116 image_index = 0;
117 }
118
119 if(image_index != 0) {
120 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().");
121 }
122
123 init();
124
125 if (is_complex_mode()) {
126 throw ImageReadException(filename, "Cannot read complex Gatan2 files");
127 }
128 else {
130
131 int xlen = 0, ylen = 0;
132 EMUtil::get_region_dims(area, gatanh.nx, &xlen, gatanh.ny, &ylen);
133
134 dict["nx"] = xlen;
135 dict["ny"] = ylen;
136 dict["nz"] = 1;
137 dict["datatype"] = to_em_datatype(gatanh.type);
138 }
139
140 EXITFUNC;
141 return 0;
142}
143
144int Gatan2IO::write_header(const Dict &, int, const Region* , EMUtil::EMDataType, bool)
145{
146 ENTERFUNC;
147 LOGWARN("Gatan2 write is not supported.");
148 EXITFUNC;
149 return 1;
150}
151
152int Gatan2IO::read_data(float *data, int image_index, const Region * area, bool )
153{
154 ENTERFUNC;
155 //single image format, index can only be zero
156 image_index = 0;
157 check_read_access(image_index, data);
158
159 if (is_complex_mode()) {
160 throw ImageReadException(filename, "Cannot read complex Gatan2 files");
161 }
162
164
165 portable_fseek(file, sizeof(Gatan2Header), SEEK_SET);
166
167#if 0
168 if (fread(data, gatanh.nx * gatanh.len, gatanh.ny, file) != (unsigned int) gatanh.ny) {
169 LOGDEBUG("Data read incomplete in Gatan file '%s'", filename.c_str());
170 return 1;
171 }
172#endif
173
174 int size = gatanh.nx * gatanh.ny;
175 short *sdata = (short *) data;
176 unsigned char *cdata = (unsigned char *) data;
177 int *ldata = (int *) data;
178
179 EMUtil::process_region_io(cdata, file, READ_ONLY, image_index, gatanh.len,
180 gatanh.nx, gatanh.ny, 1, area);
181
182 switch (gatanh.type) {
183 case GATAN2_SHORT:
184 become_host_endian((short *) data, size);
185 for (int i = size - 1; i >= 0; i--) {
186 data[i] = static_cast < float >(sdata[i]);
187 }
188 break;
189 case GATAN2_FLOAT:
190 become_host_endian(data, size);
191 break;
192 case GATAN2_CHAR:
193 for (int i = size - 1; i >= 0; i--) {
194 data[i] = static_cast < float >(cdata[i]);
195 }
196 break;
197 case GATAN2_INT:
198 become_host_endian((int *) data, size);
199 for (int i = size - 1; i >= 0; i--) {
200 data[i] = static_cast < float >(ldata[i]);
201 }
202 break;
203 default:
204 throw ImageReadException(filename, "unsupported Gatan2 data type");
205 }
206 EXITFUNC;
207 return 0;
208}
209
210int Gatan2IO::write_data(float *, int, const Region*, EMUtil::EMDataType, bool)
211{
212 ENTERFUNC;
213 LOGWARN("Gatan2 write is not supported.");
214 EXITFUNC;
215 return 1;
216}
217
218void Gatan2IO::flush()
219{
220}
221
223{
224 init();
226 return true;
227 }
228 return false;
229}
230
232{
233 init();
234 return is_big_endian;
235}
236
237
238
239int Gatan2IO::to_em_datatype(int gatan_type)
240{
241 switch (gatan_type) {
242 case GATAN2_SHORT:
243 return EMUtil::EM_SHORT;
244
245 case GATAN2_FLOAT:
246 return EMUtil::EM_FLOAT;
247
248 case GATAN2_CHAR:
249 return EMUtil::EM_CHAR;
250
251 case GATAN2_INT:
252 return EMUtil::EM_INT;
253 }
254
255 return EMUtil::EM_UNKNOWN;
256}
static bool is_host_big_endian()
Definition: byteorder.cpp:40
static void swap_bytes(T *data, size_t n=1)
swap the byte order of data with 'n' T-type elements.
Definition: byteorder.h:131
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.
Definition: byteorder.h:76
Dict is a dictionary to store <string, EMObject> pair.
Definition: emobject.h:385
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.
Definition: emutil.cpp:931
EMDataType
Image pixel data type used in EMAN.
Definition: emutil.h:92
@ EM_UNKNOWN
Definition: emutil.h:93
@ EM_SHORT
Definition: emutil.h:96
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
Gatan2Header gatanh
Definition: gatan2io.h:79
@ GATAN2_PACKED_COMPLEX
Definition: gatan2io.h:59
static bool is_valid(const void *first_block)
Definition: gatan2io.cpp:82
bool is_big_endian
Definition: gatan2io.h:81
int to_em_datatype(int gatan_type)
Definition: gatan2io.cpp:239
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 become_host_endian(T *data, size_t n=1)
Convert data of this image into host endian format.
Definition: imageio.h:261
virtual bool is_image_big_endian()=0
Is this image in big endian or not.
IntSize is used to describe a 1D, 2D or 3D rectangular size in integers.
Definition: geometry.h:49
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
Definition: geometry.h:497
#define ImageReadException(filename, desc)
Definition: exception.h:204
#define LOGDEBUG
Definition: log.h:55
#define LOGWARN
Definition: log.h:53
#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)