BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
ImportDataUtils.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Views/ImportDataWidgets/ImportDataUtils.cpp
6 //! @brief Implements ImportDataUtils namespace
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
16 #include "Base/Axis/IAxis.h"
30 #include <QApplication>
31 #include <QFileDialog>
32 #include <QFileInfo>
33 #include <QMessageBox>
34 
35 namespace {
36 const QString filter_string_ba = "Intensity File (*.int *.gz *.tif *.tiff *.txt *.csv);;"
37  "Other (*.*)";
38 const QString filter_string_ascii = "Intensity File (*.int *.int.gz *.txt *.csv *.dat *.ascii);;"
39  "Ascii column-wise data (*.*)";
40 
41 int rank(const RealDataItem& item)
42 {
43  return static_cast<int>(item.shape().size());
44 }
45 
46 int rank(const InstrumentItem& item)
47 {
48  return static_cast<int>(item.shape().size());
49 }
50 
51 } // namespace
52 
53 std::unique_ptr<OutputData<double>> ImportDataUtils::ImportKnownData(const QString& fileName)
54 {
55  // Try to use the canonical tools for importing data
56  std::unique_ptr<OutputData<double>> result;
57  try {
58  std::unique_ptr<OutputData<double>> data(
59  IntensityDataIOFactory::readOutputData(fileName.toStdString()));
60  result = CreateSimplifiedOutputData(*data);
61  } catch (std::exception& ex) {
62  QString message = QString("Error while trying to read file\n\n'%1'\n\n%2")
63  .arg(fileName)
64  .arg(QString::fromStdString(std::string(ex.what())));
65  QMessageBox::warning(nullptr, "IO Problem", message);
66  }
67  return result;
68 }
69 
70 std::unique_ptr<OutputData<double>>
72 {
73  std::unique_ptr<OutputData<double>> result;
74  try {
75  std::unique_ptr<OutputData<double>> data(
76  IntensityDataIOFactory::readReflectometryData(fileName.toStdString()));
77  result.swap(data);
78  } catch (std::exception& ex) {
79  QString message = QString("Error while trying to read file\n\n'%1'\n\n%2")
80  .arg(fileName)
81  .arg(QString::fromStdString(std::string(ex.what())));
82  QMessageBox::warning(nullptr, "IO Problem", message);
83  }
84  return result;
85 }
86 
87 std::unique_ptr<OutputData<double>> ImportDataUtils::Import2dData(const QString& fileName)
88 {
89  return ImportKnownData(fileName);
90 }
91 
93  const AbstractDataLoader* selectedLoader)
94 {
95  const QString fileName = realDataItem->nativeFileName();
96  const std::string fileNameStdString = fileName.toStdString();
97 
98  if (selectedLoader == nullptr) {
99  if (DataFormatUtils::isCompressed(fileNameStdString)
100  || DataFormatUtils::isIntFile(fileNameStdString)
101  || DataFormatUtils::isTiffFile(fileNameStdString)) {
102  try {
103  ImportDataInfo data(ImportKnownData(fileName), Axes::Units::QSPACE);
104  if (data) {
105  realDataItem->setImportData(std::move(data));
106  return QString();
107  }
108  } catch (std::exception& ex) {
109  // If it is not tiff but e.g. dat.gz, it could be tried with CSV import
110  const bool tryWithLoaders =
111  (DataFormatUtils::isIntFile(fileNameStdString)
113  fileNameStdString)); // #baimport support compressed
114 
115  if (!tryWithLoaders)
116  // import is not possible
117  return QString::fromLatin1(ex.what());
118  }
119  }
120  }
121 
122  // -- try with selected CSV loader. If none selected, try with QRE loader
123 
124  QFile file(fileName);
125  const bool fileCouldBeOpened = file.open(QFile::ReadOnly | QIODevice::Text);
126 
127  if (!fileCouldBeOpened)
128  return "File could not be opened.";
129 
130  QByteArray fileContent = file.readAll();
131  file.close();
132 
133  if (fileContent.isEmpty())
134  return "The imported file is empty.";
135 
136  if (DataFormatUtils::isCompressed(fileNameStdString)) {
137  // #baimport implement decompress
138  }
139 
140  AbstractDataLoader* loader = nullptr;
141  if (selectedLoader == nullptr)
142  loader = new QREDataLoader();
143  else
144  loader = selectedLoader->clone();
146  loader->setRealDataItem(realDataItem);
147  realDataItem->setDataLoader(loader);
148  QApplication::setOverrideCursor(Qt::WaitCursor);
149  loader->setFileContents(fileContent);
150  loader->guessSettings();
151  loader->processContents();
152  QApplication::restoreOverrideCursor();
153 
154  return QString();
155 }
156 
157 bool ImportDataUtils::Compatible(const InstrumentItem& instrumentItem,
158  const RealDataItem& realDataItem)
159 {
160  return rank(instrumentItem) == rank(realDataItem);
161 }
162 
163 std::unique_ptr<OutputData<double>>
165 {
166  const size_t data_rank = data.rank();
167  if (data_rank > 2 || data_rank < 1)
168  throw std::runtime_error("Error in ImportDataUtils::CreateSimplifiedOutputData: passed "
169  "array is neither 1D nor 2D");
170 
171  std::unique_ptr<OutputData<double>> result(new OutputData<double>);
172  for (size_t i = 0; i < data_rank; ++i) {
173  const IAxis& axis = data.axis(i);
174  const size_t axis_size = axis.size();
175  const double min = 0.0;
176  const double max = axis_size;
177  result->addAxis(FixedBinAxis(axis.getName(), axis_size, min, max));
178  }
179  result->setRawDataVector(data.getRawDataVector());
180 
181  return result;
182 }
183 
184 QString ImportDataUtils::printShapeMessage(const std::vector<int>& instrument_shape,
185  const std::vector<int>& data_shape)
186 {
187  auto to_str = [](const std::vector<int>& shape) {
188  std::string result;
189  for (size_t i = 0, size = shape.size(); i < size; ++i) {
190  result += std::to_string(shape[i]);
191  if (i + 1 != size)
192  result += ", ";
193  }
194  return result;
195  };
196 
197  std::string message_string = "instrument [";
198  message_string += to_str(instrument_shape);
199  message_string += "], data [";
200  message_string += to_str(data_shape);
201  message_string += "]";
202  return QString::fromStdString(std::move(message_string));
203 }
Defines class AbstractDataLoader1D.
Defines class AppSvc.
Defines various axis items.
Defines class OutputDataIOFactory.
Defines class DataLoaders1D.
Defines class GUIHelpers functions.
Defines class ProjectManager.
Defines interface IAxis.
Defines ImportDataUtils namespace.
Defines InstrumentItems classes.
Defines class IntensityDataIOFactory.
Defines class IntensityDataItem.
Defines class PointwiseAxis.
Defines class QREDataLoader.
Defines class RealDataItem.
Base class for all data loaders (classes which can import real data)
virtual void guessSettings()
Guess appropriate settings (for example the separator in a CSV file).
virtual void setFileContents(const QByteArray &fileContent)=0
Sets the file contents to be imported.
virtual void processContents()=0
Process the file contents.
virtual void initWithDefaultImportSettings()
Set import settings to defaults.
virtual AbstractDataLoader * clone() const =0
Create a complete clone, including all internal states.
void setRealDataItem(RealDataItem *item)
Define the real data item on which the import shall work.
Axis with fixed bin size.
Definition: FixedBinAxis.h:23
Interface for one-dimensional axes.
Definition: IAxis.h:25
virtual size_t size() const =0
retrieve the number of bins
std::string getName() const
retrieve the label of the axis
Definition: IAxis.h:40
Carries information about loaded data.
virtual std::vector< int > shape() const =0
static OutputData< double > * readOutputData(const std::string &file_name)
Reads file and returns newly created OutputData object.
static OutputData< double > * readReflectometryData(const std::string &file_name)
size_t rank() const
Returns number of dimensions.
Definition: OutputData.h:56
std::vector< T > getRawDataVector() const
Returns copy of raw data vector.
Definition: OutputData.h:334
const IAxis & axis(size_t serial_number) const
returns axis with given serial number
Definition: OutputData.h:318
Real data loader for Q/R/E reflectometry CSV files.
Definition: QREDataLoader.h:27
The RealDataItem class represents intensity data imported from file and intended for fitting.
Definition: RealDataItem.h:35
void setImportData(ImportDataInfo data)
Sets imported data to underlying item.
std::vector< int > shape() const
Returns the shape of underlying data item.
QString nativeFileName() const
void setDataLoader(AbstractDataLoader *loader)
Takes ownership of loader.
bool isCompressed(const std::string &name)
Returns true if name contains *.gz extension.
bool isIntFile(const std::string &file_name)
returns true if file name corresponds to BornAgain native format (compressed or not)
bool isTiffFile(const std::string &file_name)
returns true if file name corresponds to tiff file (can be also compressed)
void warning(QWidget *parent, const QString &title, const QString &text, const QString &detailedText)
Definition: GUIHelpers.cpp:74
std::unique_ptr< OutputData< double > > CreateSimplifiedOutputData(const OutputData< double > &data)
Creates OutputData with bin-valued axes.
std::unique_ptr< OutputData< double > > ImportReflectometryData(const QString &baseNameOfLoadedFile)
QString Import1dData(RealDataItem *realDataItem, const AbstractDataLoader *selectedLoader)
Import 1D data into the given item.
QString printShapeMessage(const std::vector< int > &instrument_shape, const std::vector< int > &data_shape)
Composes a message with the shapes of InstrumentItem and RealDataItem.
std::unique_ptr< OutputData< double > > ImportKnownData(const QString &baseNameOfLoadedFile)
bool Compatible(const InstrumentItem &instrumentItem, const RealDataItem &realDataItem)
Check whether data item is compatible with instrument (same rank)
std::unique_ptr< OutputData< double > > Import2dData(const QString &baseNameOfLoadedFile)