BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
SimDataPair.cpp
Go to the documentation of this file.
1 // ************************************************************************** //
2 //
3 // BornAgain: simulate and fit scattering at grazing incidence
4 //
5 //! @file Core/Fitting/SimDataPair.cpp
6 //! @brief Defines class SimDataPair.
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 
19 #include "Fit/TestEngine/Numeric.h"
20 
21 namespace
22 {
23 [[noreturn]] void throwInitializationException(std::string method)
24 {
25  std::stringstream ss;
26  ss << "Error in SimDataPair::" << method << ": Trying access non-initialized data\n";
27  throw std::runtime_error(ss.str());
28 }
29 
30 std::unique_ptr<OutputData<double>> initUserWeights(const OutputData<double>& shape, double value)
31 {
32  auto result = std::make_unique<OutputData<double>>();
33  result->copyShapeFrom(shape);
34  result->setAllTo(value);
35  return result;
36 }
37 } // namespace
38 
40  std::unique_ptr<OutputData<double>> uncertainties, double user_weight)
41  : m_simulation_builder(builder), m_raw_data(data.clone()),
42  m_raw_uncertainties(std::move(uncertainties))
43 {
45  validate();
46 }
47 
49  std::unique_ptr<OutputData<double>> uncertainties,
50  std::unique_ptr<OutputData<double>> user_weights)
51  : m_simulation_builder(builder), m_raw_data(data.clone()),
52  m_raw_uncertainties(std::move(uncertainties)), m_raw_user_weights(std::move(user_weights))
53 {
54  if (!m_raw_user_weights)
56  validate();
57 }
58 
60  : m_simulation_builder(std::move(other.m_simulation_builder)),
61  m_simulation(std::move(other.m_simulation)), m_sim_data(std::move(other.m_sim_data)),
62  m_exp_data(std::move(other.m_exp_data)), m_uncertainties(std::move(other.m_uncertainties)),
63  m_user_weights(std::move(other.m_user_weights)), m_raw_data(std::move(other.m_raw_data)),
64  m_raw_uncertainties(std::move(other.m_raw_uncertainties)),
65  m_raw_user_weights(std::move(other.m_raw_user_weights))
66 {
67  validate();
68 }
69 
70 SimDataPair::~SimDataPair() = default;
71 
73 {
75  m_simulation->runSimulation();
76  m_sim_data = m_simulation->result();
77 
79 }
80 
82 {
83  return static_cast<bool>(m_raw_uncertainties);
84 }
85 
87 {
88  return m_simulation ? m_simulation->intensityMapSize() : 0;
89 }
90 
92 {
93  if (m_sim_data.empty())
94  throwInitializationException("simulationResult");
95  return m_sim_data;
96 }
97 
99 {
100  if (m_exp_data.empty())
101  throwInitializationException("experimentalData");
102  return m_exp_data;
103 }
104 
106 {
107  if (m_uncertainties.empty())
108  throwInitializationException("uncertainties");
109  return m_uncertainties;
110 }
111 
112 //! Returns the user uncertainties cut to the ROI area.
114 {
115  if (m_user_weights.empty())
116  throwInitializationException("userWeights");
117  return m_user_weights;
118 }
119 
120 //! Returns relative difference between simulation and experimental data.
121 
123 {
124  if (m_sim_data.size() == 0 || m_exp_data.size() == 0)
125  throwInitializationException("relativeDifference");
126 
127  SimulationResult result = m_sim_data;
128  for (size_t i = 0, size = result.size(); i < size; ++i)
129  result[i] = Numeric::GetRelativeDifference(result[i], m_exp_data[i]);
130 
131  return result;
132 }
133 
135 {
136  if (m_sim_data.size() == 0 || m_exp_data.size() == 0)
137  throwInitializationException("absoluteDifference");
138 
139  SimulationResult result = m_sim_data;
140  for (size_t i = 0, size = result.size(); i < size; ++i)
141  result[i] = Numeric::GetAbsoluteDifference(result[i], m_exp_data[i]);
142 
143  return result;
144 }
145 
146 std::vector<double> SimDataPair::experimental_array() const
147 {
148  if (m_exp_data.empty())
149  throwInitializationException("experimental_array");
150  return m_exp_data.data()->getRawDataVector();
151 }
152 
153 std::vector<double> SimDataPair::simulation_array() const
154 {
155  if (m_sim_data.empty())
156  throwInitializationException("simulation_array");
157  return m_sim_data.data()->getRawDataVector();
158 }
159 
160 std::vector<double> SimDataPair::uncertainties_array() const
161 {
162  if (m_uncertainties.empty())
163  throwInitializationException("uncertainties_array");
164  return m_uncertainties.data()->getRawDataVector();
165 }
166 
167 std::vector<double> SimDataPair::user_weights_array() const
168 {
169  if (m_user_weights.empty())
170  throwInitializationException("user_weights_array");
171  return m_user_weights.data()->getRawDataVector();
172 }
173 
175 {
176  if (m_exp_data.size() != 0 && m_uncertainties.size() != 0 && m_user_weights.size() != 0)
177  return;
178 
179  if (!m_simulation || m_sim_data.size() == 0)
180  throwInitializationException("initResultArrays");
181 
182  m_exp_data = m_simulation->convertData(*m_raw_data, true);
183 
184  if (containsUncertainties()) {
185  m_uncertainties = m_simulation->convertData(*m_raw_uncertainties, true);
186  } else {
187  const IUnitConverter& converter = m_sim_data.converter();
188  std::unique_ptr<OutputData<double>> dummy_array =
189  UnitConverterUtils::createOutputData(converter, converter.defaultUnits());
190  m_uncertainties = SimulationResult(*dummy_array, converter);
191  }
192 
193  m_user_weights = m_simulation->convertData(*m_raw_user_weights, true);
194 }
195 
197 {
199  throw std::runtime_error("Error in SimDataPair: simulation builder is empty");
200 
201  if (!m_raw_data)
202  throw std::runtime_error("Error in SimDataPair: passed experimental data array is empty");
203 
204  if (m_raw_uncertainties && !m_raw_uncertainties->hasSameShape(*m_raw_data))
205  throw std::runtime_error(
206  "Error in SimDataPair: experimental data and uncertainties have different shape.");
207 
208  if (!m_raw_user_weights || !m_raw_user_weights->hasSameShape(*m_raw_data))
209  throw std::runtime_error(
210  "Error in SimDataPair: user weights are not initialized or have invalid shape");
211 }
std::function< std::unique_ptr< Simulation >(const Fit::Parameters &)> simulation_builder_t
Definition: FitTypes.h:28
Defines class IntensityDataFunctions.
Defines constants and "almost equal" in namespace Numeric.
Defines class SimDataPair.
Defines class Simulation.
Declares utilities for unit converters.
A collection of fit parameters.
Definition: Parameters.h:28
Interface to provide axis translations to different units for simulation output.
virtual Axes::Units defaultUnits() const =0
Holds pair of simulation/experimental data to fit.
Definition: SimDataPair.h:26
SimulationResult userWeights() const
Returns the user uncertainties cut to the ROI area.
SimulationResult m_sim_data
Current simulation results. Masked areas are nullified.
Definition: SimDataPair.h:92
std::vector< double > experimental_array() const
Returns the flattened experimental data cut to the ROI area.
SimulationResult absoluteDifference() const
Returns the absolute difference between simulated and experimental data cut to the ROI area.
std::unique_ptr< OutputData< double > > m_raw_user_weights
User-defined weights.
Definition: SimDataPair.h:105
std::vector< double > user_weights_array() const
Returns a flat array of user weights cut to the ROI area.
std::vector< double > uncertainties_array() const
Returns the flattened experimental uncertainties cut to the ROI area.
std::vector< double > simulation_array() const
Returns the flattened simulated intensities cut to the ROI area.
SimDataPair(simulation_builder_t builder, const OutputData< double > &data, std::unique_ptr< OutputData< double >> uncertainties, double user_weight=1.0)
Definition: SimDataPair.cpp:39
SimulationResult uncertainties() const
Returns the data uncertainties cut to the ROI area If no uncertainties present, returns zero-filled S...
SimulationResult experimentalData() const
Returns the experimental data cut to the ROI area.
Definition: SimDataPair.cpp:98
bool containsUncertainties() const
Definition: SimDataPair.cpp:81
void validate() const
std::unique_ptr< OutputData< double > > m_raw_data
Raw experimental data as obtained from the user.
Definition: SimDataPair.h:101
void runSimulation(const Fit::Parameters &params)
Definition: SimDataPair.cpp:72
std::unique_ptr< Simulation > m_simulation
Current simulation for given set of parameters.
Definition: SimDataPair.h:89
size_t numberOfFitElements() const
Returns the number of elements in the fit area.
Definition: SimDataPair.cpp:86
SimulationResult relativeDifference() const
Returns the relative difference between simulated and experimental data cut to the ROI area.
SimulationResult simulationResult() const
Returns the result of last computed simulation.
Definition: SimDataPair.cpp:91
void initResultArrays()
SimulationResult m_uncertainties
Weights from experimental data uncertainties. Masked areas are nullified.
Definition: SimDataPair.h:96
SimulationResult m_exp_data
Experimental data cut to the ROI. Masked areas are nullified.
Definition: SimDataPair.h:94
SimulationResult m_user_weights
Manually defined (user) weights. Masked areas are nullified.
Definition: SimDataPair.h:98
std::unique_ptr< OutputData< double > > m_raw_uncertainties
Data uncertainties as provided by the user.
Definition: SimDataPair.h:103
simulation_builder_t m_simulation_builder
Simulation builder from the user to construct simulation for given set of parameters.
Definition: SimDataPair.h:86
Wrapper around OutputData<double> that also provides unit conversions.
bool empty() const
size_t size() const
const IUnitConverter & converter() const
Returns underlying unit converter.
std::unique_ptr< OutputData< double > > data(Axes::Units units=Axes::Units::DEFAULT) const
double GetRelativeDifference(double a, double b)
Returns the safe relative difference, which is 2(|a-b|)/(|a|+|b|) except in special cases.
Definition: Numeric.cpp:32
double GetAbsoluteDifference(double a, double b)
Returns the absolute value of the difference between a and b.
Definition: Numeric.cpp:26
std::unique_ptr< OutputData< double > > createOutputData(const IUnitConverter &converter, Axes::Units units)
Returns zero-valued output data array in specified units.
std::unique_ptr< OutputData< double > > initUserWeights(const OutputData< double > &shape, double value)
Definition: SimDataPair.cpp:30
void throwInitializationException(std::string method)
Definition: SimDataPair.cpp:23