BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
OutputDataReadWriteNumpyTXT.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Device/InputOutput/OutputDataReadWriteNumpyTXT.cpp
6 //! @brief Implements class OutputDataReadWriteNumpyTXT.
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/Utils/StringUtils.h"
17 #include "Device/Data/ArrayUtils.h"
19 #include <string>
20 #include <vector>
21 
22 namespace {
23 inline bool isDoubleStartChar(char c)
24 {
25  return isdigit(c) || c == '-' || c == '+';
26 }
27 } // namespace
28 
30 {
31  std::string line;
32  std::vector<std::vector<double>> data;
33 
34  // Read numbers from input stream:
35  while (std::getline(input_stream, line)) {
36  line = StringUtils::trim(line);
37  if (line.empty() || !isDoubleStartChar(line[0]))
38  continue;
39 
40  try {
41  std::vector<double> dataInRow = DataFormatUtils::parse_doubles(line);
42  data.push_back(dataInRow);
43  } catch (...) {
44  continue;
45  }
46  }
47 
48  // validating
49  size_t nrows = data.size();
50  size_t ncols(0);
51  if (nrows)
52  ncols = data[0].size();
53 
54  if (ncols == 0)
55  throw std::runtime_error("OutputDataReadNumpyTXTStrategy::readOutputData() -> Error. "
56  "Can't parse file");
57 
58  for (size_t row = 0; row < nrows; row++) {
59  if (data[row].size() != ncols)
60  throw std::runtime_error("OutputDataReadNumpyTXTStrategy::readOutputData() -> Error. "
61  "Number of elements is different from row to row.");
62  }
63 
64  if (nrows < 2)
65  return ArrayUtils::createData(std::move(data[0])).release();
66 
67  if (ncols < 2) {
68  const size_t size = data.size();
69  std::vector<double> vector1d(size);
70  for (size_t i = 0; i < size; ++i)
71  vector1d[i] = data[i][0];
72  return ArrayUtils::createData(std::move(vector1d)).release();
73  }
74 
75  return ArrayUtils::createData(data).release();
76 }
77 
79  std::ostream& output_stream)
80 {
81  output_stream << "# BornAgain Intensity Data" << std::endl;
82  output_stream << "# Simple array suitable for numpy, matlab etc." << std::endl;
83 
84  const size_t dim = data.rank();
85  switch (dim) {
86  case 1:
87  write1DRepresentation(data, output_stream);
88  break;
89  case 2:
90  write2DRepresentation(data, output_stream);
91  break;
92  default:
93  throw std::runtime_error("Error in OutputDataWriteNumpyTXTStrategy::writeOutputData: data "
94  "of unsupported dimensions");
95  }
96 }
97 
99  std::ostream& output_stream)
100 {
101  output_stream << "# coordinates intensities" << std::endl;
102  output_stream.imbue(std::locale::classic());
103  output_stream << std::scientific << std::setprecision(12);
104 
105  const std::vector<double> axis_values = data.axis(0).binCenters();
106 
107  // printing coordinate and associated intensity
108  for (size_t i = 0, nrows = axis_values.size(); i < nrows; ++i)
109  output_stream << axis_values[i] << " " << ignoreDenormalized(data[i]) << std::endl;
110 }
111 
113  std::ostream& output_stream)
114 {
115  const size_t nrows = data.axis(1).size();
116  const size_t ncols = data.axis(0).size();
117 
118  output_stream << "# [nrows=" << nrows << ", ncols=" << ncols << "]" << std::endl;
119 
120  std::vector<std::vector<double>> dataArray = ArrayUtils::createVector2D(data);
121  output_stream.imbue(std::locale::classic());
122  output_stream << std::scientific << std::setprecision(12);
123 
124  for (size_t i = 0; i < nrows; i++) {
125  for (size_t j = 0; j < ncols; j++) {
126  double z_value = dataArray[i][j];
127  output_stream << ignoreDenormalized(z_value) << " ";
128  }
129  output_stream << std::endl;
130  }
131 }
132 
134 {
135  return (std::fpclassify(value) == FP_SUBNORMAL) ? 0.0 : value;
136 }
Defines various functions to interact from numpy on Python side.
Defines a few helper functions.
Defines class OutputDataIOFactory.
Defines OutputDataReadWriteNumpyTXT.
virtual std::vector< double > binCenters() const
Definition: IAxis.cpp:22
virtual size_t size() const =0
retrieve the number of bins
static double ignoreDenormalized(double value)
static void write2DRepresentation(const OutputData< double > &data, std::ostream &output_stream)
void writeOutputData(const OutputData< double > &data, std::ostream &output_stream)
static void write1DRepresentation(const OutputData< double > &data, std::ostream &output_stream)
OutputData< double > * readOutputData(std::istream &input_stream)
size_t rank() const
Returns number of dimensions.
Definition: OutputData.h:56
const IAxis & axis(size_t serial_number) const
returns axis with given serial number
Definition: OutputData.h:318
decltype(auto) createVector2D(const T &data)
Creates 2D vector from OutputData.
CreateDataImpl::ReturnType< T > createData(const T &vec)
Creates OutputData array from input vector.
Definition: ArrayUtils.h:65
std::vector< double > parse_doubles(const std::string &str)
Parse double values from string to vector of double.
std::string trim(const std::string &str, const std::string &whitespace=" \t")
Cuts any of the chars given in whitespace from start and end of str.
Definition: StringUtils.cpp:98
std::string scientific(const T value, int n=10)
Returns scientific string representing given value of any numeric type.
Definition: StringUtils.h:61