BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
OutputDataReadStrategy.cpp
Go to the documentation of this file.
1 // ************************************************************************** //
2 //
3 // BornAgain: simulate and fit scattering at grazing incidence
4 //
5 //! @file Device/InputOutput/OutputDataReadStrategy.cpp
6 //! @brief Implements class OutputDataReadStrategy.
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 
20 #include <map>
21 #include <stdexcept> // need overlooked by g++ 5.4
22 
23 namespace
24 {
25 inline std::string trim(const std::string& str, const std::string& whitespace = " \t")
26 {
27  const auto strBegin = str.find_first_not_of(whitespace);
28 
29  if (strBegin == std::string::npos)
30  return "";
31 
32  const auto strEnd = str.find_last_not_of(whitespace);
33  const auto strRange = strEnd - strBegin + 1;
34 
35  return str.substr(strBegin, strRange);
36 }
37 inline bool isDoubleStartChar(char c)
38 {
39  return isdigit(c) || c == '-' || c == '+';
40 }
41 } // namespace
42 
44 {
46  std::string line;
47 
48  while (std::getline(input_stream, line)) {
49  line = trim(line);
50  if (line.find("axis") != std::string::npos) {
51  std::unique_ptr<IAxis> axis = DataFormatUtils::createAxis(input_stream);
52  result->addAxis(*axis);
53  }
54 
55  if (line.find("data") != std::string::npos) {
56  DataFormatUtils::fillOutputData(result, input_stream);
57  }
58  }
59  return result;
60 }
61 
63 {
65  std::string line;
66  std::vector<std::vector<double>> vecVec;
67  std::map<double, double> QvsR;
68  std::map<double, double> QvsDR;
69  std::map<double, double> QvsDQ;
70 
71  // Read numbers from file:
72  while (std::getline(fin, line)) {
73  line = trim(line);
74  try {
75  std::vector<double> rowVec = DataFormatUtils::parse_doubles(line);
76  vecVec.push_back(rowVec);
77  } catch (...) {
78  continue;
79  }
80  }
81 
82  // validate - There is at least one row and at least two columns
83  size_t nrows = vecVec.size();
84  if (nrows < 1)
85  throw std::runtime_error("Import1dTextData: no numerical values found");
86  size_t ncols = vecVec[0].size();
87  if (ncols < 2)
88  throw std::runtime_error("Import1dTextData: Minimum 2 columns required");
89 
90  // Assign Q vs R, dR, dQ:
91  for (size_t row = 0; row < nrows; row++) {
92  if (vecVec[row].size() != ncols)
93  throw std::runtime_error("The number of columns varies among the rows");
94  double Q = vecVec[row][0];
95  switch (ncols) {
96  case 1:
97  break;
98  case 2:
99  QvsR[Q] = vecVec[row][1];
100  QvsDR[Q] = 0;
101  QvsDQ[Q] = 0;
102  break;
103  case 3:
104  QvsR[Q] = vecVec[row][1];
105  QvsDR[Q] = vecVec[row][2];
106  QvsDQ[Q] = 0;
107  break;
108  default:
109  QvsR[Q] = vecVec[row][1];
110  QvsDR[Q] = vecVec[row][2];
111  QvsDQ[Q] = vecVec[row][3];
112  break;
113  }
114  }
115 
116  std::vector<double> qVec;
117  std::vector<double> rVec;
118  for (auto it = QvsR.begin(); it != QvsR.end(); ++it) {
119  if (it->second <= 0)
120  continue;
121  qVec.push_back(it->first);
122  rVec.push_back(it->second);
123  }
124 
125  oData->addAxis(PointwiseAxis("qVector", qVec));
126  oData->setRawDataVector(rVec);
127  return oData;
128 }
129 
131 {
132  std::string line;
133  std::vector<std::vector<double>> data;
134 
135  // Read numbers from input stream:
136  while (std::getline(input_stream, line)) {
137  line = trim(line);
138  if (line.empty() || !isDoubleStartChar(line[0]))
139  continue;
140 
141  try {
142  std::vector<double> dataInRow = DataFormatUtils::parse_doubles(line);
143  data.push_back(dataInRow);
144  } catch (...) {
145  continue;
146  }
147  }
148 
149  // validating
150  size_t nrows = data.size();
151  size_t ncols(0);
152  if (nrows)
153  ncols = data[0].size();
154 
155  if (ncols == 0)
156  throw std::runtime_error("OutputDataReadNumpyTXTStrategy::readOutputData() -> Error. "
157  "Can't parse file");
158 
159  for (size_t row = 0; row < nrows; row++) {
160  if (data[row].size() != ncols)
161  throw std::runtime_error("OutputDataReadNumpyTXTStrategy::readOutputData() -> Error. "
162  "Number of elements is different from row to row.");
163  }
164 
165  if (nrows < 2) {
166  return ArrayUtils::createData(std::move(data[0])).release();
167  } else if (ncols < 2) {
168  const size_t size = data.size();
169  std::vector<double> vector1d(size);
170  for (size_t i = 0; i < size; ++i) {
171  vector1d[i] = data[i][0];
172  }
173  return ArrayUtils::createData(std::move(vector1d)).release();
174  } else {
175  return ArrayUtils::createData(data).release();
176  }
177 }
178 
179 #ifdef BORNAGAIN_TIFF_SUPPORT
180 
181 OutputDataReadTiffStrategy::OutputDataReadTiffStrategy() : m_d(new TiffHandler) {}
182 
183 OutputDataReadTiffStrategy::~OutputDataReadTiffStrategy()
184 {
185  delete m_d;
186 }
187 
188 OutputData<double>* OutputDataReadTiffStrategy::readOutputData(std::istream& input_stream)
189 {
190  m_d->read(input_stream);
191  return m_d->getOutputData()->clone();
192 }
193 
194 #endif // BORNAGAIN_TIFF_SUPPORT
Defines various functions to interact from numpy on Python side.
Defines class OutputDataIOFactory.
Defines IOutputDataReadStrategy and related classes.
Defines class PointwiseAxis.
Defines class TiffHandler.
OutputData< double > * readOutputData(std::istream &input_stream)
OutputData< double > * readOutputData(std::istream &input_stream)
OutputData< double > * readOutputData(std::istream &input_stream)
void addAxis(const IAxis &new_axis)
Definition: OutputData.h:289
void setRawDataVector(const std::vector< T > &data_vector)
Sets new values to raw data vector.
Definition: OutputData.h:559
OutputData * clone() const
Definition: OutputData.h:253
Axis containing arbitrary (non-equidistant) coordinate values.
Definition: PointwiseAxis.h:33
CreateDataImpl::ReturnType< T > createData(const T &vec)
Creates OutputData array from input vector.
Definition: ArrayUtils.h:61
std::unique_ptr< IAxis > createAxis(std::istream &input_stream)
Creates axis of certain type from input stream.
std::vector< double > parse_doubles(const std::string &str)
Parse double values from string to vector of double.
void fillOutputData(OutputData< double > *data, std::istream &input_stream)
Fills output data raw buffer from input stream.
std::string trim(const std::string &str, const std::string &whitespace=" \t")