BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
dataloader_utils.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file gui2/dataloader/dataloader_utils.cpp
6 //! @brief Implements class CLASS?
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2020
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
18 #include "mvvm/utils/stringutils.h"
19 #include <algorithm>
20 #include <fstream>
21 
22 namespace gui2 {
23 
24 namespace {
25 
26 //! Returns true if given pair of values can represent range
27 bool isRepresentRange(const std::optional<int>& v0, const std::optional<int>& v1)
28 {
29  if (v0.has_value() && v1.has_value())
30  return v0.value() > 0 && v1.value() > 0 && v0.value() <= v1.value();
31  return false;
32 }
33 
34 //! Finds in vector of ColumnInfo all columns of given type and returns it as a new vector.
35 std::vector<ColumnInfo> columnsForType(const std::vector<ColumnInfo>& input,
36  const std::string& columnType)
37 {
38  std::vector<ColumnInfo> result;
39  std::copy_if(input.begin(), input.end(), std::back_inserter(result),
40  [columnType](auto x) { return x.type_name == columnType; });
41  return result;
42 }
43 
44 } // namespace
45 
46 std::vector<std::string> Utils::LoadASCIIFile(const std::string& file_name)
47 {
48  std::vector<std::string> result;
49 
50  std::ifstream file(file_name);
51  if (!file.is_open())
52  throw std::ios_base::failure("Unable to open file '" + file_name + "'");
53  for (std::string line; getline(file, line);)
54  result.emplace_back(line);
55  return result;
56 }
57 
58 std::vector<std::pair<int, int>> Utils::ExpandLineNumberPattern(const std::string& pattern)
59 {
60  std::vector<std::pair<int, int>> result;
61 
62  // splitting "1, 2-3" first on comma-separated tokens
63  for (const auto& token : ModelView::Utils::SplitString(pattern, ",")) {
64  auto parts = ModelView::Utils::SplitString(token, "-");
65  // splitting on dash-separared tokens
66  if (!parts.empty()) {
67  // if no "-" is present, make from "1" a pair {1, 1}
68  // if "-" is present, make from "1-2" a pair {1,2}
69  auto conv0 = ModelView::Utils::StringToInteger(parts[0]);
70  auto conv1 = parts.size() > 1 ? ModelView::Utils::StringToInteger(parts[1]) : conv0;
71  if (isRepresentRange(conv0, conv1))
72  result.push_back({conv0.value(), conv1.value()});
73  }
74  }
75 
76  return result;
77 }
78 
80 {
81  std::vector<std::pair<int, int>> expanded_pattern = Utils::ExpandLineNumberPattern(pattern);
82  auto result = [expanded_pattern](int line_number) {
83  for (auto pair : expanded_pattern) {
84  if (line_number >= pair.first && line_number <= pair.second)
85  return true;
86  }
87  return false;
88  };
89  return result;
90 }
91 
92 accept_string_t Utils::CreateLinePrefixValidator(const std::string& prefix_to_exclude)
93 {
94  auto result = [prefix_to_exclude](const std::string& line) {
95  // line contains spaces only
96  if (line.empty() || line.find_first_not_of(' ') == std::string::npos)
97  return false;
98  // line starts from pattern
99  return line.find_first_of(prefix_to_exclude) == 0 ? false : true;
100  };
101  return result;
102 }
103 
105 {
106  if (separator.empty())
107  throw std::runtime_error("Error, empty separator.");
108 
109  bool is_space_only_separator = separator.find_first_not_of(' ') == std::string::npos;
110  auto result = [separator, is_space_only_separator](const std::string& line) {
111  std::vector<std::string> values;
112  std::string trimmed = ModelView::Utils::TrimWhitespace(line);
113  if (is_space_only_separator)
114  trimmed = ModelView::Utils::RemoveRepeatedSpaces(trimmed);
115  return ModelView::Utils::SplitString(trimmed, separator);
116  };
117  return result;
118 }
119 
120 std::string Utils::AddHtmlDivTag(const std::string& line)
121 {
122  const std::string open_div = "<div>";
123  const std::string close_div = "</div>";
124  std::string result;
125  return open_div + line + close_div;
126 }
127 
128 std::string Utils::AddHtmlColorTag(const std::string& line, const std::string& color)
129 {
130  const std::string open_tag = "<font color=\"" + color + "\">";
131  const std::string close_tag = "</font>";
132  std::string result;
133  return open_tag + line + close_tag;
134 }
135 
136 std::string Utils::AddHtmlBackgroundTag(const std::string& line, const std::string& color)
137 {
138  const std::string open_tag = "<span style=\"background-color:" + color + "\">";
139  const std::string close_tag = "</span>";
140  std::string result;
141  return open_tag + line + close_tag;
142 }
143 
144 std::string Utils::AddHtmlColorTagToParts(const std::string& line,
145  const std::vector<std::string>& parts,
146  const std::string& color_parts,
147  const std::string& color_rest)
148 {
149  std::string result;
150  std::string_view view(line);
151 
152  if (parts.empty())
153  return AddHtmlDivTag(AddHtmlColorTag(line, color_rest));
154 
155  for (auto part : parts) {
156  auto it = view.find_first_of(part);
157  if (it > 0)
158  result.append(AddHtmlBackgroundTag(std::string(view.substr(0, it)), color_rest));
159  result.append(AddHtmlColorTag(part, color_parts));
160  view.remove_prefix(it + part.size());
161  }
162  return AddHtmlDivTag(result);
163 }
164 
165 std::pair<std::vector<double>, std::vector<double>>
166 Utils::ExtractTwoColumns(const std::vector<std::vector<std::string>>& text_data, size_t col1,
167  size_t col2)
168 {
169  std::vector<double> vec1, vec2;
170  for (const auto& row : text_data) {
171  if (col1 < row.size() && col2 < row.size()) {
172  auto val1 = ModelView::Utils::StringToDouble(row[col1]);
173  auto val2 = ModelView::Utils::StringToDouble(row[col2]);
174  if (val1.has_value() && val2.has_value()) {
175  vec1.push_back(val1.value());
176  vec2.push_back(val2.value());
177  }
178  }
179  }
180 
181  return std::make_pair(std::move(vec1), std::move(vec2));
182 }
183 
184 std::vector<std::pair<ColumnInfo, ColumnInfo>>
185 Utils::CreateGraphInfoPairs(const std::vector<ColumnInfo>& column_info)
186 {
187  std::vector<std::pair<ColumnInfo, ColumnInfo>> result;
188 
189  auto axis_columns = columnsForType(column_info, Constants::AxisType);
190  auto intensity_columns = columnsForType(column_info, Constants::IntensityType);
191 
192  if (axis_columns.size() != 1)
193  throw std::runtime_error("There must be exactly one column with AxisType selected.");
194 
195  for (const auto& intensity_info : intensity_columns)
196  result.push_back(std::make_pair(axis_columns.back(), intensity_info));
197 
198  return result;
199 }
200 
201 GraphImportData Utils::CreateData(const std::vector<std::vector<std::string>>& text_data,
202  const ColumnInfo& axis, const ColumnInfo& intensity)
203 {
204  GraphImportData result;
205 
206  auto [axis_values, intensity_values] =
207  Utils::ExtractTwoColumns(text_data, axis.column, intensity.column);
208 
209  std::transform(intensity_values.begin(), intensity_values.end(), intensity_values.begin(),
210  [&intensity](auto x) { return x * intensity.multiplier; });
211 
212  result.bin_centers = axis_values;
213  result.axis_units = axis.units;
214 
215  result.bin_values = intensity_values;
216  result.signal_units = intensity.units;
217 
218  return result;
219 }
220 
221 } // namespace gui2
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
MVVM_MODEL_EXPORT std::string RemoveRepeatedSpaces(std::string str)
Removes repeating spaces for a string.
MVVM_MODEL_EXPORT std::string TrimWhitespace(const std::string &str)
Returns string after trimming whitespace surrounding, including tabs and carriage returns.
MVVM_MODEL_EXPORT std::vector< std::string > SplitString(const std::string &str, const std::string &delimeter)
Split string on substring using given delimeter. Reproduces Python's str.split() behavior.
MVVM_MODEL_EXPORT std::optional< int > StringToInteger(const std::string &str)
Converts string to integer.
MVVM_MODEL_EXPORT std::optional< double > StringToDouble(const std::string &str)
Converts string to double value using classc locale and returns it in the form of optional.
const std::string IntensityType
const std::string AxisType
DAREFLCORE_EXPORT std::vector< std::string > LoadASCIIFile(const std::string &file_name)
Loads ASCII file, returns it in the form of vector of strings.
DAREFLCORE_EXPORT accept_int_t CreateLineNumberPatternValidator(const std::string &pattern)
Creates a callback to define if given line number satisfies line number pattern.
DAREFLCORE_EXPORT std::pair< std::vector< double >, std::vector< double > > ExtractTwoColumns(const std::vector< std::vector< std::string >> &text_data, size_t col1, size_t col2)
Extracts double values from two columns of a string array.
DAREFLCORE_EXPORT line_splitter_t CreateSeparatorBasedSplitter(const std::string &separator)
Creates line splitter based on separator.
DAREFLCORE_EXPORT accept_string_t CreateLinePrefixValidator(const std::string &prefix_to_exclude)
Creates a callback to define if given line has a valid content for further parsing.
DAREFLCORE_EXPORT std::string AddHtmlColorTagToParts(const std::string &line, const std::vector< std::string > &parts, const std::string &color_parts, const std::string &color_rest)
Returns string representing original 'line', where 'parts' are surrounded with color tag.
DAREFLCORE_EXPORT std::string AddHtmlDivTag(const std::string &line)
Returns string representing original 'line' wrapped in 'div' tag.
DAREFLCORE_EXPORT std::vector< std::pair< ColumnInfo, ColumnInfo > > CreateGraphInfoPairs(const std::vector< ColumnInfo > &column_info)
Pack ColumnInfo into pairs representing {AxisType, IntensityType}.
DAREFLCORE_EXPORT std::vector< std::pair< int, int > > ExpandLineNumberPattern(const std::string &pattern)
Expands string representing line number pattern to inclusive pairs of line numbers.
DAREFLCORE_EXPORT GraphImportData CreateData(const std::vector< std::vector< std::string >> &text_data, const ColumnInfo &axis, const ColumnInfo &intensity)
Creates structure from text data.
DAREFLCORE_EXPORT std::string AddHtmlColorTag(const std::string &line, const std::string &color)
Returns string representing original 'line' wrapped in html color tag.
DAREFLCORE_EXPORT std::string AddHtmlBackgroundTag(const std::string &line, const std::string &color)
Returns string representing original 'line' wrapped in 'div' tag.
Based on Qt example "codeeditor" Copyright (C) 2016 The Qt Company Ltd.
Definition: app_constants.h:20
std::function< bool(const std::string &line)> accept_string_t
Function to define if given string should be accepted for further consideration.
std::function< bool(int)> accept_int_t
Function to define if given index satisfies criteria.
std::function< std::vector< std::string >(const std::string &line)> line_splitter_t
Function to define line splitter according to some criteria.
Defines class CLASS?
Info about the column as defined by the user via ImportTableWidget.
Raw data to construct GraphItem and Data1DItem's.
std::vector< double > bin_centers
std::vector< double > bin_values