BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
ScanResolution.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sim/Scan/ScanResolution.cpp
6 //! @brief Implements scan resolution class and derived ones.
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 
18 #include <utility>
19 
20 namespace {
21 
22 void checkIfEmpty(const std::vector<double>& input);
23 
24 const std::string relative_resolution = "ScanRelativeResolution";
25 const std::string absolute_resolution = "ScanAbsoluteResolution";
26 
27 class ScanSingleRelativeResolution : public ScanResolution {
28 public:
29  ScanSingleRelativeResolution(const IRangedDistribution& distr, double reldev)
30  : ScanResolution(distr)
31  , m_reldev(reldev)
32  {
33  }
34  ~ScanSingleRelativeResolution() override = default;
35 
36  ScanResolution* clone() const override
37  {
38  return new ScanSingleRelativeResolution(*distribution(), m_reldev);
39  }
40 
41  DistrOutput generateSamples(double mean, size_t n_times) const override;
42  DistrOutput generateSamples(const std::vector<double>& mean) const override;
43  std::vector<double> stdDevs(double mean, size_t n_times) const override;
44  std::vector<double> stdDevs(const std::vector<double>& mean) const override;
45 
46  double delta() const override { return m_reldev; }
47 
48 protected:
49  std::string name() const override { return relative_resolution; }
50 
51 private:
52  double m_reldev; //!< deltas for computing resolutions
53 };
54 
55 class ScanSingleAbsoluteResolution : public ScanResolution {
56 public:
57  ScanSingleAbsoluteResolution(const IRangedDistribution& distr, double stddev)
58  : ScanResolution(distr)
59  , m_stddev(stddev)
60  {
61  }
62  ~ScanSingleAbsoluteResolution() override = default;
63 
64  ScanResolution* clone() const override
65  {
66  return new ScanSingleAbsoluteResolution(*distribution(), m_stddev);
67  }
68 
69  DistrOutput generateSamples(double mean, size_t n_times) const override;
70  DistrOutput generateSamples(const std::vector<double>& mean) const override;
71  std::vector<double> stdDevs(double mean, size_t n_times) const override;
72  std::vector<double> stdDevs(const std::vector<double>& mean) const override;
73 
74  double delta() const override { return m_stddev; }
75 
76 protected:
77  std::string name() const override { return absolute_resolution; }
78 
79 private:
80  double m_stddev; //!< deltas for computing resolutions
81 };
82 
83 class ScanVectorRelativeResolution : public ScanResolution {
84 public:
85  ScanVectorRelativeResolution(const IRangedDistribution& distr, std::vector<double> reldev)
86  : ScanResolution(distr)
87  , m_reldev(std::move(reldev))
88  {
89  checkIfEmpty(m_reldev);
90  }
91  ~ScanVectorRelativeResolution() override = default;
92 
93  ScanResolution* clone() const override
94  {
95  return new ScanVectorRelativeResolution(*distribution(), m_reldev);
96  }
97 
98  DistrOutput generateSamples(double mean, size_t n_times) const override;
99  DistrOutput generateSamples(const std::vector<double>& mean) const override;
100  std::vector<double> stdDevs(double mean, size_t n_times) const override;
101  std::vector<double> stdDevs(const std::vector<double>& mean) const override;
102 
103  double delta() const override { return 0; } // TODO
104 
105 protected:
106  std::string name() const override { return relative_resolution; }
107 
108 private:
109  std::vector<double> m_reldev; //!< deltas for computing resolutions
110 };
111 
112 class ScanVectorAbsoluteResolution : public ScanResolution {
113 public:
114  ScanVectorAbsoluteResolution(const IRangedDistribution& distr, std::vector<double> stddev)
115  : ScanResolution(distr)
116  , m_stddev(std::move(stddev))
117  {
118  checkIfEmpty(m_stddev);
119  }
120  ~ScanVectorAbsoluteResolution() override = default;
121 
122  ScanResolution* clone() const override
123  {
124  return new ScanVectorAbsoluteResolution(*distribution(), m_stddev);
125  }
126 
127  DistrOutput generateSamples(double mean, size_t n_times) const override;
128  DistrOutput generateSamples(const std::vector<double>& mean) const override;
129  std::vector<double> stdDevs(double mean, size_t n_times) const override;
130  std::vector<double> stdDevs(const std::vector<double>& mean) const override;
131 
132  double delta() const override { return 0; } // TODO
133 
134 protected:
135  std::string name() const override { return absolute_resolution; }
136 
137 private:
138  std::vector<double> m_stddev; //!< deltas for computing resolutions
139 };
140 
141 class ScanEmptyResolution : public ScanResolution {
142 public:
143  ScanEmptyResolution() = default;
144 
145  ~ScanEmptyResolution() override = default;
146 
147  ScanResolution* clone() const override { return new ScanEmptyResolution(); }
148 
149  DistrOutput generateSamples(double mean, size_t n_times) const override;
150  DistrOutput generateSamples(const std::vector<double>& mean) const override;
151  std::vector<double> stdDevs(double mean, size_t n_times) const override;
152  std::vector<double> stdDevs(const std::vector<double>& mean) const override;
153 
154  double delta() const override { return 0; }
155 
156 protected:
157  std::string name() const override;
158 };
159 
160 } // namespace
161 
163 
165  double stddev)
166 {
167  return new ScanSingleRelativeResolution(distr, stddev);
168 }
169 
171  const std::vector<double>& stddevs)
172 {
173  return new ScanVectorRelativeResolution(distr, stddevs);
174 }
175 
177  double stddev)
178 {
179  return new ScanSingleAbsoluteResolution(distr, stddev);
180 }
181 
183  const std::vector<double>& stddevs)
184 {
185  return new ScanVectorAbsoluteResolution(distr, stddevs);
186 }
187 
189 {
190  return new ScanEmptyResolution();
191 }
192 
194 {
195  if (m_distr)
196  return m_distr->nSamples();
197  return 1;
198 }
199 
201 
203  : m_distr(distr.clone())
204 {
205 }
206 
207 namespace {
208 
209 ScanResolution::DistrOutput ScanSingleRelativeResolution::generateSamples(double mean,
210  size_t n_times) const
211 {
212  const double stddev = mean * m_reldev;
213  return DistrOutput(n_times, distribution()->generateSamples(mean, stddev));
214 }
215 
217 ScanSingleRelativeResolution::generateSamples(const std::vector<double>& mean) const
218 {
219  checkIfEmpty(mean);
220  DistrOutput result;
221  result.reserve(mean.size());
222  for (size_t i = 0, size = mean.size(); i < size; ++i)
223  result.push_back(distribution()->generateSamples(mean[i], mean[i] * m_reldev));
224  return result;
225 }
226 
227 std::vector<double> ScanSingleRelativeResolution::stdDevs(double mean, size_t n_times) const
228 {
229  return std::vector<double>(n_times, mean * m_reldev);
230 }
231 
232 std::vector<double> ScanSingleRelativeResolution::stdDevs(const std::vector<double>& mean) const
233 {
234  checkIfEmpty(mean);
235  std::vector<double> result;
236  result.reserve(mean.size());
237  for (size_t i = 0, size = mean.size(); i < size; ++i)
238  result.push_back(mean[i] * m_reldev);
239  return result;
240 }
241 
242 ScanResolution::DistrOutput ScanVectorRelativeResolution::generateSamples(double mean,
243  size_t n_times) const
244 {
245  return generateSamples(std::vector<double>(n_times, mean));
246 }
247 
249 ScanVectorRelativeResolution::generateSamples(const std::vector<double>& mean) const
250 {
251  const std::vector<double> stddevs = stdDevs(mean);
252  return distribution()->generateSamples(mean, stddevs);
253 }
254 
255 std::vector<double> ScanVectorRelativeResolution::stdDevs(double mean, size_t n_times) const
256 {
257  return stdDevs(std::vector<double>(n_times, mean));
258 }
259 
260 std::vector<double> ScanVectorRelativeResolution::stdDevs(const std::vector<double>& mean) const
261 {
262  const size_t result_size = mean.size();
263  if (result_size != m_reldev.size())
264  throw std::runtime_error(
265  "Error in ScanVectorRelativeResolution::stdDevs: passed mean values vector "
266  "size shall be of the same size with relative deviations vector");
267 
268  std::vector<double> stddevs(result_size);
269  for (size_t i = 0; i < result_size; ++i)
270  stddevs[i] = m_reldev[i] * mean[i];
271  return stddevs;
272 }
273 
274 ScanResolution::DistrOutput ScanSingleAbsoluteResolution::generateSamples(double mean,
275  size_t n_times) const
276 {
277  return DistrOutput(n_times, distribution()->generateSamples(mean, m_stddev));
278 }
279 
281 ScanSingleAbsoluteResolution::generateSamples(const std::vector<double>& mean) const
282 {
283  checkIfEmpty(mean);
284  DistrOutput result;
285  result.reserve(mean.size());
286  for (size_t i = 0, size = mean.size(); i < size; ++i)
287  result.push_back(distribution()->generateSamples(mean[i], m_stddev));
288  return result;
289 }
290 
291 std::vector<double> ScanSingleAbsoluteResolution::stdDevs(double, size_t n_times) const
292 {
293  return std::vector<double>(n_times, m_stddev);
294 }
295 
296 std::vector<double> ScanSingleAbsoluteResolution::stdDevs(const std::vector<double>& mean) const
297 {
298  checkIfEmpty(mean);
299  return std::vector<double>(mean.size(), m_stddev);
300 }
301 
302 ScanResolution::DistrOutput ScanVectorAbsoluteResolution::generateSamples(double mean,
303  size_t n_times) const
304 {
305  return generateSamples(std::vector<double>(n_times, mean));
306 }
307 
309 ScanVectorAbsoluteResolution::generateSamples(const std::vector<double>& mean) const
310 {
311  const size_t result_size = mean.size();
312  if (result_size != m_stddev.size())
313  throw std::runtime_error(
314  "Error in ScanVectorAbsoluteResolution::generateSamples: passed mean values vector "
315  "size shall be of the same size with standard deviations vector");
316  return distribution()->generateSamples(mean, m_stddev);
317 }
318 
319 std::vector<double> ScanVectorAbsoluteResolution::stdDevs(double mean, size_t n_times) const
320 {
321  return stdDevs(std::vector<double>(n_times, mean));
322 }
323 
324 std::vector<double> ScanVectorAbsoluteResolution::stdDevs(const std::vector<double>& mean) const
325 {
326  const size_t result_size = mean.size();
327  if (result_size != m_stddev.size())
328  throw std::runtime_error(
329  "Error in ScanVectorAbsoluteResolution::generateSamples: passed mean values vector "
330  "size shall be of the same size with standard deviations vector");
331  return m_stddev;
332 }
333 
334 ScanEmptyResolution::DistrOutput ScanEmptyResolution::generateSamples(double mean,
335  size_t n_times) const
336 {
337  return DistrOutput(n_times, std::vector<ParameterSample>{ParameterSample(mean, 1.)});
338 }
339 
340 ScanEmptyResolution::DistrOutput
341 ScanEmptyResolution::generateSamples(const std::vector<double>& mean) const
342 {
343  DistrOutput result;
344  result.reserve(mean.size());
345  for (size_t i = 0, size = mean.size(); i < size; ++i)
346  result.push_back({ParameterSample(mean[i], 1.0)});
347  return result;
348 }
349 
350 std::vector<double> ScanEmptyResolution::stdDevs(double, size_t n_times) const
351 {
352  return std::vector<double>(n_times, 0.0);
353 }
354 
355 std::vector<double> ScanEmptyResolution::stdDevs(const std::vector<double>& mean) const
356 {
357  return std::vector<double>(mean.size(), 0.0);
358 }
359 
360 std::string ScanEmptyResolution::name() const
361 {
362  throw std::runtime_error(
363  "Error in ScanEmptyResolution::name: attempt to get a name of an empty resolution object.");
364 }
365 
366 void checkIfEmpty(const std::vector<double>& input)
367 {
368  if (input.empty())
369  throw std::runtime_error("Error in ScanResolution: passed vector is empty");
370 }
371 
372 } // namespace
Defines classes representing ranged one-dimensional distributions.
Defines scan resolution class.
Interface for one-dimensional ranged distributions. All derived distributions allow for generating sa...
A parameter value with a weight, as obtained when sampling from a distribution.
Container for reflectivity resolution data.
static ScanResolution * scanAbsoluteResolution(const IRangedDistribution &distr, double stddev)
virtual double delta() const =0
std::vector< std::vector< ParameterSample > > DistrOutput
std::unique_ptr< IRangedDistribution > m_distr
basic distribution function
ScanResolution * clone() const override=0
size_t nSamples() const
~ScanResolution() override
static ScanResolution * scanEmptyResolution()
virtual std::string name() const =0
static ScanResolution * scanRelativeResolution(const IRangedDistribution &distr, double stddev)
const IRangedDistribution * distribution() const
virtual std::vector< double > stdDevs(double mean, size_t n_times) const =0
virtual DistrOutput generateSamples(double mean, size_t n_times) const =0