CFEL - ASG Software Suite  2.5.0
CASS
file_handler.cpp
Go to the documentation of this file.
1 // Copyright (C) 2013 Lutz Foucar
2 
3 /**
4  * @file file_handler.cpp contains a file handler
5  *
6  * @author Lutz Foucar
7  */
8 
9 #include <stdexcept>
10 #include <vector>
11 
12 #include <QtCore/QString>
13 #include <QtCore/QFileInfo>
14 #include <QtCore/QObject>
15 #include <QtCore/QDebug>
16 
17 #if QT_VERSION >= 0x050000
18 #include <QtWidgets/QMessageBox>
19 #include <QtWidgets/QInputDialog>
20 #else
21 #include <QtGui/QMessageBox>
22 #include <QtGui/QInputDialog>
23 #endif
24 #include <QtGui/QImage>
25 #include <QtGui/QImageReader>
26 
27 #include "file_handler.h"
28 
29 #ifdef HDF5
30 #include "hdf5_handle.hpp"
31 #endif
32 #include "result.hpp"
33 #include "cbf_handle.hpp"
34 
35 
36 using namespace jocassview;
37 using namespace cass;
38 using namespace std;
39 
41  : _filename(filename)
42 {
43 
44 }
45 
47 {
48  QFileInfo fileInfo(filename);
49  if (! fileInfo.exists())
50  return QString();
51 
52  return fileInfo.baseName();
53 }
54 
56 {
57  QFileInfo fileInfo(filename);
58 
59  bool retval(false);
60  if (fileInfo.suffix().toUpper() == QString("h5").toUpper() ||
61  fileInfo.suffix().toUpper() == QString("hdf5").toUpper() )
62  retval = true;
63 
64  return retval;
65 }
66 
68 {
69  QFileInfo fileInfo(filename);
70  if (fileInfo.exists())
71  return;
72 
73  FileHandler instance;
74 
75  if (fileInfo.suffix().toUpper() == QString("hst").toUpper())
76  {
77  instance.saveDataToHist(filename,data);
78  }
79  else if (fileInfo.suffix().toUpper() == QString("csv").toUpper())
80  {
81  instance.saveDataToCSV(filename,data);
82  }
83  else if (fileInfo.suffix().toUpper() == QString("h5").toUpper() ||
84  fileInfo.suffix().toUpper() == QString("hdf5").toUpper() )
85  {
86  instance.saveDataToH5(filename,data,"w");
87  }
88  else if (fileInfo.suffix().toUpper() == QString("cbf").toUpper())
89  {
90  instance.saveDataToCBF(filename,data);
91  }
92  return;
93 }
94 
96 {
97  QFileInfo fileInfo(filename);
98  if (fileInfo.exists())
99  {
100 #ifdef HDF5
101  hdf5::Handler(filename.toStdString(),"w");
102 #endif
103  }
104 }
105 
107 {
108  QFileInfo fileInfo(_filename);
109  if (! fileInfo.exists())
110  return result_t::shared_pointer();
111 
112  if (fileInfo.suffix().toUpper() == QString("png").toUpper() ||
113  fileInfo.suffix().toUpper() == QString("tiff").toUpper() ||
114  fileInfo.suffix().toUpper() == QString("jpg").toUpper() ||
115  fileInfo.suffix().toUpper() == QString("jpeg").toUpper() ||
116  fileInfo.suffix().toUpper() == QString("giv").toUpper() ||
117  fileInfo.suffix().toUpper() == QString("bmp").toUpper() )
118  {
119  QMessageBox::critical(0,QObject::tr("Error"),QObject::tr("Can't convert image to Data."));
120  }
121  if (fileInfo.suffix().toUpper() == QString("hst").toUpper())
122  {
123  return loadDataFromHist();
124  }
125  if (fileInfo.suffix().toUpper() == QString("csv").toUpper())
126  {
127  return loadDataFromCSV();
128  }
129  if (fileInfo.suffix().toUpper() == QString("h5").toUpper() ||
130  fileInfo.suffix().toUpper() == QString("hdf5").toUpper() )
131  {
132  return loadDataFromH5(key);
133  }
134  if (fileInfo.suffix().toUpper() == QString("cbf").toUpper())
135  {
136  return loadDataFromCBF();
137  }
138  return result_t::shared_pointer();
139 }
140 
142 {
143  QStringList items;
145  {
146 #ifdef HDF5
147  try
148  {
149  hdf5::Handler h5handle(_filename.toStdString(),"r");
150 
151  list<string> dataset(h5handle.datasets());
152  for (list<string>::const_iterator it=dataset.begin(); it != dataset.end(); ++it)
153  items.append(QString::fromStdString(*it));
154  }
155  catch(...)
156  {
157  QMessageBox::critical(0,QObject::tr("Error"),QObject::tr("FileHandler::getKeyList(): some error occured"));
158  }
159 #endif
160  }
161  else
162  {
163  items.append(getBaseName(_filename));
164  }
165  return items;
166 }
167 
169 {
170  return QString("File");
171 }
172 
173 void FileHandler::setFilename(const QString &filename)
174 {
175  _filename = filename;
176 }
177 
179 {
180  QImageReader imageReader(filename);
181  if (imageReader.canRead())
182  return QImage(filename);
183  return QImage();
184 }
185 
186 void FileHandler::saveImage(const QString &filename, const QImage &image)
187 {
188  if(! image.save(filename, "PNG"))
189  QMessageBox::critical(0, QObject::tr("Error"), QObject::tr("Image'") + filename +
190  QObject::tr("' could not be saved!"));
191 }
192 
194 {
195  /** use a file serializer to deserialize the data in the file to a hist object
196  * and get the dimension from the object.
197  */
198  cass::SerializerReadFile serializer( _filename.toStdString().c_str() );
200  serializer >> (*result);
201  serializer.close();
202 
203  return result;
204 }
205 
207 {
208  cass::SerializerWriteFile serializer( filename.toStdString().c_str() );
209  serializer << (*data);
210  serializer.close();
211 }
212 
214 {
215  QMessageBox::information(0,QObject::tr("Info"),QObject::tr("CSV loading not yet implemented"));
216  return result_t::shared_pointer();
217 }
218 
220 {
221  QFile file(filename);
222  if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
223  return;
224  QTextStream out(&file);
225  switch (data->dim())
226  {
227  case 0:
228  {
229  for (size_t i(0); i < data->size(); ++i)
230  out << (*data)[i] << endl;
231  break;
232  }
233  case 1:
234  {
235  const result_t::axe_t &xaxis(data->axis(result_t::xAxis));
236  out<<"x-axis value, y-axis value"<<endl;
237  for (size_t i(0); i < xaxis.nBins; ++i)
238  out <<xaxis.pos(i)<<";"<< (*data)[i] << endl;
239  break;
240  }
241  case 2:
242  {
243  const result_t::axe_t &xaxis(data->axis(result_t::xAxis));
244  const result_t::axe_t &yaxis(data->axis(result_t::yAxis));
245  out<<"x-axis value, y-axis value, z-axis value"<<endl;
246  for (size_t yy(0); yy < yaxis.nBins; ++yy)
247  for (size_t xx(0); xx < xaxis.nBins; ++xx)
248  out << xaxis.pos(xx) << ";" << yaxis.pos(yy) <<";"<<(*data)[yy*xaxis.nBins + xx] << endl;
249  break;
250  }
251  }
252 }
253 
254 #ifdef HDF5
256 {
257  try
258  {
259  hdf5::Handler h5handle(_filename.toStdString(),"r");
260 
261  /** get the list of all items in the h5 file */
262  list<string> dataset(h5handle.datasets());
263  QStringList items;
264  for (list<string>::const_iterator it=dataset.begin(); it != dataset.end(); ++it)
265  items.append(QString::fromStdString(*it));
266 
267  /** if no key is given or the given key is not on the list,
268  * request one from the user
269  */
270  QString key(keyname);
271  //qDebug()<<"loadDatafromH5"<<key<<key.isEmpty()<<(key =="")<< !items.contains(key);
272  if (key == "" || key.isEmpty() || !items.contains(key))
273  {
274  bool ok(false);
275  QString item(QInputDialog::getItem(0, QObject::tr("Select Key"),
276  QObject::tr("Key:"), items, 0, false, &ok));
277  if (ok && !item.isEmpty())
278  key = item;
279  else
280  return result_t::shared_pointer();
281  }
282 
283  switch (h5handle.dimension(key.toStdString()))
284  {
285  case (0):
286  {
287  float value(h5handle.readScalar<float>(key.toStdString()));
289  result->setValue(value);
290  result->name(key.toStdString());
291  return result;
292  break;
293  }
294  case (1):
295  {
296  vector<float> array;
297  size_t length(2);
298  float xlow,xup;
299  h5handle.readArray(array,length,key.toStdString());
300  if (length > 1)
301  {
302  try { xlow = h5handle.readScalarAttribute<float>("xLow",key.toStdString()); }
303  catch(const invalid_argument & what) { xlow = 0; }
304  try { xup = h5handle.readScalarAttribute<float>("xUp",key.toStdString()); }
305  catch(const invalid_argument & what) { xup = length; }
307  copy(array.begin(),array.end(),result->begin());
308  result->name(key.toStdString());
309  return result;
310  }
311  else
312  {
314  result->setValue(array[0]);
315  result->name(key.toStdString());
316  return result;
317  }
318  break;
319  }
320  case (2):
321  {
322  vector<float> matrix;
323  pair<size_t,size_t> shape;
324  h5handle.readMatrix(matrix,shape,key.toStdString());
325  float xlow,xup,ylow,yup;
326  try { xlow = h5handle.readScalarAttribute<float>("xLow",key.toStdString()); }
327  catch(const invalid_argument & what) { xlow = 0; }
328  try { xup = h5handle.readScalarAttribute<float>("xUp",key.toStdString()); }
329  catch(const invalid_argument & what) { xup = shape.first; }
330  try { ylow = h5handle.readScalarAttribute<float>("yLow",key.toStdString()); }
331  catch(const invalid_argument & what) { ylow = 0; }
332  try { yup = h5handle.readScalarAttribute<float>("yUp",key.toStdString()); }
333  catch(const invalid_argument & what) { yup = shape.second; }
335  (result_t::axe_t(shape.first,xlow,xup),
336  result_t::axe_t(shape.second,ylow,yup)));
337  copy(matrix.begin(),matrix.end(),result->begin());
338  result->name(key.toStdString());
339  return result;
340  break;
341  }
342  case (3):
343  {
344  QString text(QString::fromStdString(h5handle.readString(key.toStdString())));
345  //qDebug()<<text;
346  QMessageBox::information(0,key,text);
347  break;
348  }
349  default:
350  QMessageBox::critical(0,QObject::tr("Error"),QString("FileHandler::loadDataFromH5(): Unknown dimension of dataset '" +
351  key + "' in file '" + _filename + "'"));
352  return result_t::shared_pointer();
353  }
354  }
355  catch(const invalid_argument & err)
356  {
358  }
359  catch(const logic_error& err)
360  {
362  }
363  catch(const runtime_error & err)
364  {
366  }
367  catch(...)
368  {
369  QMessageBox::critical(0,QObject::tr("Error"),QString("FileHandler::loadDataFromH5(): can't open '" +
370  _filename + "'. Unknown error occured"));
371  }
372  return result_t::shared_pointer();
373 }
374 
375 void FileHandler::saveDataToH5(const QString &filename, result_t::shared_pointer data, const QString &mode)
376 {
377  try
378  {
379  hdf5::Handler h5handle(filename.toStdString(),mode.toStdString());
380  switch (data->dim())
381  {
382  case 0:
383  {
384  h5handle.writeScalar(data->front(),data->name());
385  break;
386  }
387  case 1:
388  {
389  const result_t::axe_t &xaxis(data->axis(result_t::xAxis));
390  h5handle.writeArray(data->storage(),data->shape().first, data->name());
391  h5handle.writeScalarAttribute(xaxis.low, "xLow", data->name());
392  h5handle.writeScalarAttribute(xaxis.up, "xUp", data->name());
393  break;
394  }
395  case 2:
396  {
397  const result_t::axe_t &xaxis(data->axis(result_t::xAxis));
398  const result_t::axe_t &yaxis(data->axis(result_t::yAxis));
399  h5handle.writeMatrix(data->storage(),data->shape(),data->name(),9);
400  h5handle.writeScalarAttribute(xaxis.low, "xLow", data->name());
401  h5handle.writeScalarAttribute(xaxis.up, "xUp", data->name());
402  h5handle.writeScalarAttribute(yaxis.low, "yLow", data->name());
403  h5handle.writeScalarAttribute(yaxis.up, "yUp", data->name());
404  break;
405  }
406  }
407  }
408  catch(const invalid_argument & err)
409  {
411  }
412  catch(const logic_error& err)
413  {
415  }
416  catch(const runtime_error & err)
417  {
419  }
420  catch(...)
421  {
422  QMessageBox::critical(0,QObject::tr("Error"),QString("FileHandler::loadDataFromH5(): can't open '" +
423  filename + "'. Unknown error occured"));
424  }
425 }
426 #else
427 cass::HistogramBackend* FileHandler::loadDataFromH5(const QString &)
428 {
429  return 0;
430 }
431 
433 {
434 
435 }
436 
437 #endif
438 
440 {
441  vector<float> matrix;
442  pair<int,int> shape(0,0);
443  string header;
444  CBF::read(_filename.toStdString(), header, matrix, shape);
445 
446 // qDebug()<<QString::fromStdString(header)<<shape.first<<"x"<<shape.second;
447 
448  /** try to retrieve the center from the header */
449  pair<double,double> center(0,0);
450  QString head(QString::fromStdString(header));
451  QTextStream headstream(&head);
452  QString line;
453  do
454  {
455  line = headstream.readLine();
456  if (line.contains("# Beam_xy"))
457  {
458  QStringList tokens(line.split(' '));
459  QString ccol = tokens[2];
460  ccol.remove('(');
461  ccol.remove(')');
462  ccol.remove(',');
463  QString crow = tokens[3];
464  crow.remove('(');
465  crow.remove(')');
466  crow.remove(',');
467  center.first = ccol.toDouble();
468  center.second = crow.toDouble();
469  }
470  } while(!line.isNull());
471  //qDebug() << center.first<<center.second;
472 
473  double xmin = -center.first;
474  double xmax = shape.first - center.first;
475  double ymin = -center.second;
476  double ymax = shape.second - center.second;
478  (new result_t
479  (result_t::axe_t(shape.first, xmin, xmax, "cols"),
480  result_t::axe_t(shape.second, ymin, ymax, "rows")));
481  copy(matrix.begin(), matrix.end(), result->begin());
482  result->name(_filename.toStdString());
483 
484  return result;
485 }
486 
488 {
489  cass::CBF::write(filename.toStdString(), data->begin(), data->shape());
490 }
handle cbf files
getItem(QWidget *parent, const QString &title, const QString &label, const QStringList &items, int current=0, bool editable=true, bool *ok=0, Qt::WindowFlags flags=0)
FileHandler(const QString &filename=QString())
constructor
readLine(qint64 maxlen=0)
result_t::shared_pointer loadDataFromCBF()
read the data from a cbf file
save(const QString &fileName, const char *format=0, int quality=-1)
A file output serializer.
Definition: serializer.hpp:481
split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive)
std::tr1::shared_ptr< self_type > shared_pointer
a shared pointer of this class
Definition: result.hpp:323
A handler for h5 files.
static void saveData(const QString &filename, result_t::shared_pointer data)
save data to a given file
read and write data to files
Definition: file_handler.h:30
STL namespace.
an axis of a more than 0 dimensional container
Definition: result.hpp:29
result_t::shared_pointer loadDataFromHist()
read the data from a hist file
remove(int position, int n)
toDouble(bool *ok=0)
result classes
tr(const char *sourceText, const char *disambiguation=0, int n=-1)
information(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons=Ok, StandardButton defaultButton=NoButton)
QImage loadImage(const QString &filename)
read the data from an image file
Axis< double > axe_t
the axis descriptions of this container
Definition: result.hpp:353
result_t::shared_pointer result(const QString &key, quint64 id=0)
retrieve an result from the file
void close()
close file
Definition: serializer.hpp:505
void saveDataToCBF(const QString &filename, result_t::shared_pointer data)
save the data to a cbf file
void saveDataToH5(const QString &filename, result_t::shared_pointer data, const QString &mode="w")
write the data to a hdf5 file
fromStdString(const std::string &str)
static bool isContainerFile(const QString &filename)
return whether the file is a container file
QStringList resultNames()
retrieve the list of names that an be displayed from the file
contains a file handler
A file input deserializer.
Definition: serializer.hpp:527
void read(const std::string &filename, std::string &headerstring, std::vector< float > &matrix, std::pair< int, int > &shape)
read the cbf data into a linearized 2d array
Definition: cbf_handle.hpp:191
void saveDataToCSV(const QString &filename, result_t::shared_pointer data)
save the data from a CSV file
result_t::shared_pointer loadDataFromH5(const QString &key="")
read the data from a hdf5 file
open(OpenMode mode)
void saveDataToHist(const QString &filename, result_t::shared_pointer data)
save the data from a hist file
contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive)
auxiliary data[Processor]
void setFilename(const QString &filename)
set the filename
cass::Result< float > result_t
define the result type
Definition: data_source.h:30
QString type() const
retrieve the type of source
QString _filename
the filename of the file to work on
Definition: file_handler.h:167
result_t::shared_pointer loadDataFromCSV()
read the data from a CSV file
critical(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons=Ok, StandardButton defaultButton=NoButton)
void saveImage(const QString &filename, const QImage &image)
save image data
void writeScalar(const type value, const std::string &valname)
write an scalar value with a given name as part of a given group
check if there is some light in the chamber based upon the GMD value
easier api for hdf5 file writing
static void createContainer(const QString &filename)
create the container file
static QString getBaseName(const QString &filename)
return the basename of the filename
void write(const std::string &filename, std::vector< float >::const_iterator data, const std::pair< int, int > &shape)
write cbf file
Definition: cbf_handle.hpp:35