BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
DataFormatUtils.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Device/InputOutput/DataFormatUtils.cpp
6 //! @brief Implements class DataFormatUtils.
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 "Base/Utils/StringUtils.h"
21 #include "Device/Data/OutputData.h"
22 #include <iostream>
23 #include <iterator>
24 
25 namespace {
26 std::istringstream getAxisStringRepresentation(std::istream& input_stream);
27 
28 template <class Axis> std::unique_ptr<IAxis> createFixedBinLikeAxis(std::istringstream iss);
29 std::unique_ptr<IAxis> createVariableBinAxis(std::istringstream iss);
30 std::unique_ptr<IAxis> createPointwiseAxis(std::istringstream iss);
31 
32 using createAxisFun = std::function<std::unique_ptr<IAxis>(std::istringstream iss)>;
33 const std::vector<std::pair<std::string, createAxisFun>> type_map = {
34  {"ConstKBinAxis", createFixedBinLikeAxis<ConstKBinAxis>},
35  {"CustomBinAxis", createFixedBinLikeAxis<CustomBinAxis>},
36  {"FixedBinAxis", createFixedBinLikeAxis<FixedBinAxis>},
37  {"PointwiseAxis", createPointwiseAxis},
38  {"VariableBinAxis", createVariableBinAxis}};
39 
40 const std::string GzipExtension = ".gz";
41 const std::string BzipExtension = ".bz2";
42 const std::string IntExtension = ".int";
43 const std::string TiffExtension = ".tif";
44 const std::string TiffExtension2 = ".tiff";
45 } // namespace
46 
47 bool DataFormatUtils::isCompressed(const std::string& name)
48 {
49  return isGZipped(name) || isBZipped(name);
50 }
51 
52 //! Does name contain *.gz extension?
53 
54 bool DataFormatUtils::isGZipped(const std::string& name)
55 {
56  return FileSystemUtils::extension(name) == GzipExtension;
57 }
58 
59 bool DataFormatUtils::isBZipped(const std::string& name)
60 {
61  return FileSystemUtils::extension(name) == BzipExtension;
62 }
63 
64 //! Returns file main extension (without .gz).
65 
66 std::string DataFormatUtils::GetFileMainExtension(const std::string& name)
67 {
68  std::string stripped_name(name);
69  if (isGZipped(name)) {
70  stripped_name = name.substr(0, name.size() - GzipExtension.size());
71  } else if (isBZipped(name)) {
72  stripped_name = name.substr(0, name.size() - BzipExtension.size());
73  }
74  return FileSystemUtils::extension(stripped_name);
75 }
76 
77 bool DataFormatUtils::isIntFile(const std::string& file_name)
78 {
79  return GetFileMainExtension(file_name) == IntExtension;
80 }
81 
82 bool DataFormatUtils::isTiffFile(const std::string& file_name)
83 {
84  return (GetFileMainExtension(file_name) == TiffExtension
85  || GetFileMainExtension(file_name) == TiffExtension2);
86 }
87 
88 //! Creates axis of certain type from input stream
89 std::unique_ptr<IAxis> DataFormatUtils::createAxis(std::istream& input_stream)
90 {
91  auto iss = getAxisStringRepresentation(input_stream);
92  std::string type;
93  if (!(iss >> type))
94  throw std::runtime_error(
95  "Error in DataFormatUtils::createAxis:: couldn't read axis type from input");
96 
97  for (auto iter = type_map.cbegin(); iter != type_map.end(); ++iter)
98  if (iter->first == type)
99  return iter->second(std::move(iss));
100  throw std::runtime_error("Error in DataFormatUtils::createAxis:"
101  "Unknown axis type '"
102  + type + "'");
103 }
104 
105 //! Fills output data raw buffer from input stream
106 void DataFormatUtils::fillOutputData(OutputData<double>* data, std::istream& input_stream)
107 {
108  std::string line;
109  data->setAllTo(0.0);
110  OutputData<double>::iterator it = data->begin();
111  while (std::getline(input_stream, line)) {
112  if (line.empty() || line[0] == '#')
113  break;
114 
115  std::istringstream iss(line);
116  std::vector<double> buffer;
117  readLineOfDoubles(buffer, iss);
118  for (auto value : buffer) {
119  *it = value;
120  ++it;
121  }
122  }
123  if (it != data->end())
124  throw std::runtime_error("DataFormatUtils::fillOutputData() -> Error while parsing data.");
125 }
126 
127 //! Parse double values from string to vector of double
128 
129 // #migration +++ this works only if separator is space or tab; it does not work e.g. with comma or
130 // semicolon
131 std::vector<double> DataFormatUtils::parse_doubles(const std::string& str)
132 {
133  std::vector<double> result;
134  std::istringstream iss(str);
136  if (result.empty()) {
137  std::string out = str;
138  const size_t max_string_length(10);
139  if (out.size() > max_string_length)
140  out.resize(max_string_length, ' ');
141  out += " ...";
142  throw std::runtime_error("DataFormatUtils::parse_doubles -> Error! Can't parse double "
143  "values from a string '"
144  + out + "'");
145  }
146  return result;
147 }
148 
149 // #migration +++ this works only if separator is space or tab; it does not work e.g. with comma or
150 // semicolon
151 void DataFormatUtils::readLineOfDoubles(std::vector<double>& buffer, std::istringstream& iss)
152 {
153  iss.imbue(std::locale::classic());
154  std::copy(std::istream_iterator<double>(iss), std::istream_iterator<double>(),
155  back_inserter(buffer));
156 }
157 
158 namespace {
159 std::istringstream getAxisStringRepresentation(std::istream& input_stream)
160 {
161  std::string line;
162  std::getline(input_stream, line);
163  const std::vector<std::string> to_replace = {",", "\"", "(", ")", "[", "]"};
164  StringUtils::replaceItemsFromString(line, to_replace, " ");
165  return std::istringstream(line);
166 }
167 
168 //! Creates one of FixedBinAxis from string representation
169 //! FixedBinAxis("axis0", 10, -1, 1)
170 //! ConstKBinAxis("axis0", 10, -1, 1)
171 //! CustomBinAxis("axis0", 10, -1, 1)
172 template <class Axis> std::unique_ptr<IAxis> createFixedBinLikeAxis(std::istringstream iss)
173 {
174  std::string name;
175  size_t nbins(0);
176  if (!(iss >> name >> nbins))
177  throw std::runtime_error("createFixedBinLikeAxis() -> Error. Can't parse the string.");
178 
179  std::vector<double> boundaries;
180  DataFormatUtils::readLineOfDoubles(boundaries, iss);
181  if (boundaries.size() != 2)
182  throw std::runtime_error("Error in createFixedBinLikeAxis: Can't parse the string while "
183  "reading boundaries.");
184 
185  return std::make_unique<Axis>(name, nbins, boundaries[0], boundaries[1]);
186 }
187 
188 //! Creates VariableBinAxis from string representation
189 //! VariableBinAxis("axis0", 4, [-1, -0.5, 0.5, 1, 2])
190 std::unique_ptr<IAxis> createVariableBinAxis(std::istringstream iss)
191 {
192  std::string name;
193  size_t nbins(0);
194  if (!(iss >> name >> nbins))
195  throw std::runtime_error("Error in createVariableBinAxis: Can't parse the string.");
196 
197  std::vector<double> boundaries;
198  DataFormatUtils::readLineOfDoubles(boundaries, iss);
199  if (boundaries.size() != nbins + 1)
200  throw std::runtime_error(
201  "Error in createVariableBinAxis: wrong number of boundaries read.");
202 
203  return std::make_unique<VariableBinAxis>(name, nbins, boundaries);
204 }
205 
206 //! Creates createPointwiseAxis from string representation
207 //! PointwiseAxis("axis0", [-0.5, 0.5, 1, 2])
208 std::unique_ptr<IAxis> createPointwiseAxis(std::istringstream iss)
209 {
210  std::string name;
211  if (!(iss >> name))
212  throw std::runtime_error("Error in createPointwiseAxis:Can't parse the string.");
213 
214  std::vector<double> coordinates;
215  DataFormatUtils::readLineOfDoubles(coordinates, iss);
216 
217  return std::make_unique<PointwiseAxis>(name, coordinates);
218 }
219 } // namespace
Defines a few helper functions.
Defines class ConstKBinAxis.
Defines class CustomBinAxis.
Defines class OutputDataIOFactory.
Defines namespace FileSystemUtils.
Defines and implements templated class OutputData.
Defines class PointwiseAxis.
iterator end()
Returns read/write iterator that points to the one past last element.
Definition: OutputData.h:93
void setAllTo(const T &value)
Sets content of output data to specific value.
Definition: OutputData.h:476
iterator begin()
Returns read/write iterator that points to the first element.
Definition: OutputData.h:343
bool isBZipped(const std::string &name)
Returns true if name contains *.bz2 extension.
void readLineOfDoubles(std::vector< double > &buffer, std::istringstream &iss)
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)
std::string GetFileMainExtension(const std::string &name)
Returns file extension after stripping '.gz' if any.
bool isTiffFile(const std::string &file_name)
returns true if file name corresponds to tiff file (can be also compressed)
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.
bool isGZipped(const std::string &name)
Returns true if name contains *.gz extension.
void fillOutputData(OutputData< double > *data, std::istream &input_stream)
Fills output data raw buffer from input stream.
std::string extension(const std::string &path)
Returns extension of given filename.
QString const & name(EShape k)
Definition: particles.cpp:21
void replaceItemsFromString(std::string &text, const std::vector< std::string > &items, const std::string &replacement="")
Replaces all occurrences of items from string text with delimiter.
Definition: StringUtils.cpp:64