Xmipp  v3.23.11-Nereus
rwHDF5.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Authors: Joaquin Oton (joton@cnb.csic.es)
3  *
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include "xmipp_image_base.h"
27 #include "xmipp_hdf5.h"
28 #include "multidim_array_base.h"
29 #include "metadata_static.h"
30 #include "xmipp_funcs.h"
31 
32 
34 {
35  H5T_sign_t h5sign = H5Tget_sign(h5datatype);
36 
37  // if (h5sign == H5T_SGN_ERROR)
38  // REPORT_ERROR(ERR_IO, "datatypeHDF5: Integer sign error in dataset.");
39  bool sign = (h5sign > H5T_SGN_NONE);
40  size_t size = H5Tget_size(h5datatype);
41 
42  DataType dt;
43  switch(H5Tget_class(h5datatype))
44  {
45  case H5T_FLOAT:
46  {
47  switch(size)
48  {
49  case 4:
50  dt = DT_Float;
51  break;
52  case 8:
53  dt = DT_Double;
54  break;
55  default:
56  REPORT_ERROR(ERR_IO_SIZE, "datatypeHDF5: bad datatype size");
57  }
58  }
59  break;
60  case H5T_INTEGER:
61  {
62  switch(size)
63  {
64  case 1:
65  dt = (sign)? DT_SChar : DT_UChar;
66  break;
67  case 2:
68  dt = (sign)? DT_Short : DT_UShort;
69  break;
70  case 4:
71  dt = (sign)? DT_Int : DT_UInt;
72  break;
73  case 8:
74  dt = (sign)? DT_Long : DT_ULong;
75  break;
76  default:
77  REPORT_ERROR(ERR_IO_SIZE, "datatypeHDF5: bad datatype size");
78  }
79  }
80  break;
81  case H5T_NO_CLASS:
82  default:
83  dt = DT_Unknown;
84  break;
85  }
86  return dt;
87 }
88 
90 {
91  switch (datatype)
92  {
93  case DT_Float:
94  return H5T_NATIVE_FLOAT;
95  case DT_ULong:
96  return H5T_NATIVE_ULONG;
97  case DT_Long:
98  return H5T_NATIVE_LONG;
99  case DT_UInt:
100  return H5T_NATIVE_UINT;
101  case DT_Int:
102  return H5T_NATIVE_INT;
103  case DT_UShort:
104  return H5T_NATIVE_USHORT;
105  case DT_Short:
106  return H5T_NATIVE_SHORT;
107  case DT_UChar:
108  return H5T_NATIVE_UCHAR;
109  case DT_SChar:
110  return H5T_NATIVE_CHAR;
111  case DT_Double:
112  return H5T_NATIVE_DOUBLE;
113  default:
114  REPORT_ERROR(ERR_NOT_IMPLEMENTED, formatString("rwHDF5: %s datatype not implemented for " \
115  " HDF5 datatype", datatype2Str(datatype).c_str()));
116  break;
117  }
118 
119 }
120 
122 public:
123  hid_t dataset; /* Dataset and datatype identifiers */
124  hid_t filespace;
125  hsize_t dims[4]; // We are not going to support more than 4 dimensions, at this moment.
126  hsize_t nobjEman;
127  hid_t cparms;
128  int rank;
130  H5Pclose(cparms);
131  H5Sclose(filespace);
132  H5Dclose(dataset);
133  }
134 };
135 
136 int ImageBase::readHDF5(size_t select_img)
137 {
138  H5infoProvider provider = getProvider(fhdf5); // Provider name
139 
140  String dsname = filename.getBlockName();
141  readHDF5Data d;
142 
143  // Setting default dataset name
144  if (dsname.empty())
145  {
146  dsname = provider.second;
147 
148  switch (provider.first)
149  {
150  case EMAN: // Images in stack are stored in separated groups
151  hid_t grpid;
152  grpid = H5Gopen(fhdf5,"/MDF/images/", H5P_DEFAULT);
153  /*herr_t err = */
154  H5Gget_num_objs(grpid, &d.nobjEman);
155  dsname = formatString(dsname.c_str(), IMG_INDEX(select_img));
156  H5Gclose(grpid);
157  break;
158  default:
159  break;
160  }
161  }
162  else
163  {
164  switch (provider.first)
165  {
166  case EMAN: // Images in stack are stored in separated groups
167  d.nobjEman=1;
168  break;
169  default:
170  break;
171  }
172  }
173 
174  d.dataset = H5Dopen2(fhdf5, dsname.c_str(), H5P_DEFAULT);
175 
176  if( d.dataset < 0)
177  REPORT_ERROR(ERR_IO_NOTEXIST, formatString("readHDF5: Dataset '%s' not found",dsname.c_str()));
178 
179  d.cparms = H5Dget_create_plist(d.dataset); /* Get properties handle first. */
180 
181  // Get dataset rank and dimension.
182  d.filespace = H5Dget_space(d.dataset); /* Get filespace handle first. */
183  // rank = H5Sget_simple_extent_ndims(filespace);
184  int rank = H5Sget_simple_extent_dims(d.filespace, d.dims, NULL);
185 
186  // Offset only set when it is possible to access to data directly
187  offset = (H5D_CONTIGUOUS == H5Pget_layout(d.cparms))? H5Dget_offset(d.dataset) : 0;
188 
189  hid_t h5datatype = H5Dget_type(d.dataset);
190 
191  // Reading byte order
192  switch(H5Tget_order(h5datatype))
193  {
194  case H5T_ORDER_ERROR:
195  REPORT_ERROR(ERR_IO, "readHDF5: error reading endianness.");
196  break;
197  case H5T_ORDER_LE:
198  swap = IsBigEndian();
199  break;
200  case H5T_ORDER_BE:
201  swap = IsLittleEndian();
202  break;
203  default:
204  REPORT_ERROR(ERR_IO, "readHDF5: unknown endianness type, maybe mixed types.");
205  break;
206  }
207 
208  DataType datatype = datatypeH5(h5datatype);
209  MDMainHeader.setValue(MDL_DATATYPE,(int) datatype);
210 
211  bool isStack = false;
212  // Setting isStack depending on provider
213  switch (provider.first)
214  {
215  case MISTRAL: // rank 3 arrays are stacks
216  isStack = true;
217  break;
218  // case EMAN: // Images in stack are stored in separated groups
219  default:
220  break;
221  }
222 
223  ArrayDim aDim;
224  size_t nDimFile;
225  aDim.xdim = d.dims[rank-1];
226  aDim.ydim = (rank>1)?d.dims[rank-2]:1;
227  aDim.zdim = (rank>3 || (rank==3 && !isStack))?d.dims[rank-3]:1;
228  if ( provider.first == EMAN )
229  nDimFile = d.nobjEman;
230  else
231  nDimFile = ( rank<3 || !isStack )?1:d.dims[0] ;
232 
233  if (select_img > nDimFile)
234  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS, formatString("readHDF5 (%s): Image number %lu exceeds stack size %lu", filename.c_str(), select_img, nDimFile));
235 
236  aDim.ndim = replaceNsize = (select_img == ALL_IMAGES)? nDimFile :1 ;
237  setDimensions(aDim);
238 
239  //Read header only
240  if(dataMode == HEADER || (dataMode == _HEADER_ALL && aDim.ndim > 1))
241  return 0;
242 
243 
244  // EMAN stores each image in a separate dataset
245  if ( provider.first == EMAN )
246  select_img = 1;
247 
248  size_t imgStart = IMG_INDEX(select_img);
249  size_t imgEnd = (select_img != ALL_IMAGES) ? imgStart + 1 : aDim.ndim;
250 
251  MD.clear();
252  for (size_t i = 0; i < imgEnd-imgStart; i++)
253  MD.push_back(std::unique_ptr<MDRowVec>(new MDRowVec(MDL::emptyHeaderVec())));
254 
255  if (dataMode < DATA) // Don't read data if not necessary but read the header
256  return 0;
257 
258  if ( H5Pget_layout(d.cparms) == H5D_CONTIGUOUS ) //We can read it directly
259  readData(fimg, select_img, datatype, 0);
260  else // We read it by hyperslabs
261  {
262  // Allocate memory for image data (Assume xdim, ydim, zdim and ndim are already set
263  //if memory already allocated use it (no resize allowed)
265 
266  hsize_t offset[4]; // Hyperslab offset in the file
267  hsize_t count[4]; // Size of the hyperslab in the file
268 
269  // Define the offset and count of the hyperslab to be read.
270 
271  switch (rank)
272  {
273  case 4:
274  count[0] = 1;
275  case 3:
276  // if (stack)
277  count[rank-3] = aDim.zdim;
278  offset[rank-2] = 0;
279  case 2:
280  count[rank-2] = aDim.ydim;
281  offset[rank-2] = 0;
282  break;
283  }
284  count[rank-1] = aDim.xdim;
285  offset[rank-1] = 0;
286 
287  aDim.xdim = d.dims[rank-1];
288  aDim.ydim = (rank>1)?d.dims[rank-2]:1;
289  aDim.zdim = (rank == 4)?d.dims[1]:1;
290 
291  // Define the memory space to read a hyperslab.
292  hid_t memspace = H5Screate_simple(rank,count,NULL);
293 
294  size_t data = (size_t) this->mdaBase->getArrayPointer();
295  size_t pad = aDim.zyxdim*gettypesize(myT());
296 
297 
298  for (size_t idx = imgStart, imN = 0; idx < imgEnd; ++idx, ++imN)
299  {
300 
301  // Set the offset of the hyperslab to be read
302  offset[0] = idx;
303 
304  if ( H5Sselect_hyperslab(d.filespace, H5S_SELECT_SET, offset, NULL,
305  count, NULL) < 0 )
306  REPORT_ERROR(ERR_IO_NOREAD, formatString("readHDF5: Error selecting hyperslab %d from filename %s",
307  imgStart, filename.c_str()));
308 
309  // Read
310  if ( H5Dread(d.dataset, H5Datatype(myT()), memspace, d.filespace,
311  H5P_DEFAULT, (void*)(data + pad*imN)) < 0 )
312  REPORT_ERROR(ERR_IO_NOREAD,formatString("readHDF5: Error reading hyperslab %d from filename %s",
313  imgStart, filename.c_str()));
314  }
315  H5Sclose(memspace);
316  }
317 
318  return 0;
319 }
320 
321 int ImageBase::writeHDF5(size_t select_img, bool isStack, int mode, String bitDepth, CastWriteMode castMode)
322 {
323  REPORT_ERROR(ERR_NOT_IMPLEMENTED, "writeHDF5: Not implemented yet.");
324 }
std::string datatype2Str(DataType datatype)
Index out of bounds.
Definition: xmipp_error.h:132
hsize_t dims[4]
Definition: rwHDF5.cpp:125
Case or algorithm not implemented yet.
Definition: xmipp_error.h:177
size_t xdim
DataMode dataMode
String getBlockName() const
bool IsLittleEndian(void)
bool IsBigEndian(void)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
double sign
DataType datatypeH5(hid_t dataset)
Definition: rwHDF5.cpp:33
virtual void readData(FILE *fimg, size_t select_img, DataType datatype, size_t pad)=0
hid_t H5Datatype(DataType datatype)
Definition: rwHDF5.cpp:89
virtual void coreAllocateReuse()=0
void setValue(const MDObject &object) override
int writeHDF5(size_t select_img, bool isStack=false, int mode=WRITE_OVERWRITE, String bitDepth="", CastWriteMode castMode=CW_CAST)
Definition: rwHDF5.cpp:321
std::vector< std::unique_ptr< MDRow > > MD
virtual void * getArrayPointer() const =0
if read from file original image datatype, this is an struct defined in image
Input/Output general error.
Definition: xmipp_error.h:134
hid_t filespace
Definition: rwHDF5.cpp:124
std::pair< H5FileProvider, String > H5infoProvider
Definition: xmipp_hdf5.h:51
#define i
doublereal * d
hsize_t nobjEman
Definition: rwHDF5.cpp:126
hid_t dataset
Definition: rwHDF5.cpp:123
if(fabs(c[*nmax+ *nmax *c_dim1])==0.e0)
size_t zdim
size_t zyxdim
virtual void setDimensions(int Xdim, int Ydim, int Zdim, size_t Ndim)=0
File or directory does not exist.
Definition: xmipp_error.h:136
Couldn&#39;t read from file.
Definition: xmipp_error.h:139
static MDRowVec emptyHeaderVec()
DataType
void mode
H5infoProvider getProvider(hid_t fhdf5)
Definition: xmipp_hdf5.cpp:202
int readHDF5(size_t select_img)
Definition: rwHDF5.cpp:136
MDRowVec MDMainHeader
size_t ndim
DataType datatype() const
std::string String
Definition: xmipp_strings.h:34
#define ALL_IMAGES
String formatString(const char *format,...)
#define IMG_INDEX(select_img)
size_t ydim
FileName filename
Incorrect file size.
Definition: xmipp_error.h:145
CastWriteMode
hid_t cparms
Definition: rwHDF5.cpp:127
virtual DataType myT() const =0
size_t replaceNsize
MultidimArrayBase * mdaBase
size_t gettypesize(DataType type)
Returns memory size of datatype.