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