BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
QSpecScan.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Core/Scan/QSpecScan.cpp
6 //! @brief Implements QSpecScan 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 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
15 #include "Core/Scan/QSpecScan.h"
16 #include "Base/Axis/FixedBinAxis.h"
21 
22 QSpecScan::QSpecScan(std::vector<double> qs_nm)
23  : m_qs(std::make_unique<PointwiseAxis>("qs", std::move(qs_nm)))
24  , m_resolution(ScanResolution::scanEmptyResolution())
25 {
27 }
28 
30  : m_qs(qs_nm.clone()), m_resolution(ScanResolution::scanEmptyResolution())
31 {
33 }
34 
35 QSpecScan::QSpecScan(int nbins, double qz_min, double qz_max)
36  : m_qs(std::make_unique<FixedBinAxis>("qs", nbins, qz_min, qz_max))
37  , m_resolution(ScanResolution::scanEmptyResolution())
38 {
40 }
41 
42 QSpecScan::~QSpecScan() = default;
43 
45 {
46  auto* result = new QSpecScan(*m_qs);
47  result->setQResolution(*m_resolution);
48  result->setOffset(m_offset);
49  return result;
50 }
51 
52 //! Generates simulation elements for specular simulations
53 std::vector<SpecularSimulationElement>
55 {
56  const std::vector<double> qz = generateQzVector();
57 
58  std::vector<SpecularSimulationElement> result;
59  result.reserve(qz.size());
60  for (size_t i = 0, size = qz.size(); i < size; ++i)
61  result.emplace_back(
62  SpecularSimulationElement(-(qz[i] + m_offset) / 2.0, instrument, qz[i] >= 0));
63 
64  return result;
65 }
66 
67 std::vector<double> QSpecScan::footprint(size_t i, size_t n_elements) const
68 {
69  if (i + n_elements > numberOfSimulationElements())
70  throw std::runtime_error("Error in QSpecScan::footprint: given index exceeds the "
71  "number of simulation elements");
72  return std::vector<double>(n_elements, 1.0);
73 }
74 
75 //! Returns the number of simulation elements
77 {
78  return m_qs->size() * m_resolution->nSamples();
79 }
80 
81 std::vector<double>
82 QSpecScan::createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const
83 {
84  const size_t axis_size = m_qs->size();
85  std::vector<double> result(axis_size, 0.0);
86 
87  const auto samples = applyQResolution();
88 
89  size_t elem_pos = 0;
90  for (size_t i = 0; i < axis_size; ++i) {
91  double& current = result[i];
92  for (size_t j = 0, size = samples[i].size(); j < size; ++j) {
93  current += sim_elements[elem_pos].intensity() * samples[i][j].weight;
94  ++elem_pos;
95  }
96  }
97  return result;
98 }
99 
101 {
102  m_resolution.reset(resolution.clone());
103  m_q_res_cache.clear();
104  m_q_res_cache.shrink_to_fit();
105 }
106 
107 void QSpecScan::setRelativeQResolution(const IRangedDistribution& distr, double rel_dev)
108 {
109  std::unique_ptr<ScanResolution> resolution(
112 }
113 
115  const std::vector<double>& rel_dev)
116 {
117  std::unique_ptr<ScanResolution> resolution(
120 }
121 
122 void QSpecScan::setAbsoluteQResolution(const IRangedDistribution& distr, double std_dev)
123 {
124  std::unique_ptr<ScanResolution> resolution(
127 }
128 
130  const std::vector<double>& std_dev)
131 {
132  std::unique_ptr<ScanResolution> resolution(
135 }
136 
138 {
139  std::vector<double> axis_values = m_qs->binCenters();
140  if (!std::is_sorted(axis_values.begin(), axis_values.end()))
141  throw std::runtime_error("Error in QSpecScan::checkInitialization: q-vector values shall "
142  "be sorted in ascending order.");
143 
144  if (axis_values.front() < 0)
145  throw std::runtime_error("Error in QSpecScan::checkInitialization: q-vector values are out "
146  "of acceptable range.");
147 }
148 
149 std::vector<double> QSpecScan::generateQzVector() const
150 {
151  const auto samples = applyQResolution();
152 
153  std::vector<double> result;
154  result.reserve(numberOfSimulationElements());
155  for (size_t i = 0, size_out = samples.size(); i < size_out; ++i)
156  for (size_t j = 0, size_in = samples[i].size(); j < size_in; ++j)
157  result.push_back(samples[i][j].value);
158  return result;
159 }
160 
161 std::vector<std::vector<ParameterSample>> QSpecScan::applyQResolution() const
162 {
163  if (m_q_res_cache.empty())
164  m_q_res_cache = m_resolution->generateSamples(m_qs->binCenters());
165  return m_q_res_cache;
166 }
Defines class FixedBinAxis.
Defines class PointwiseAxis.
Declares QSpecScan class.
Defines classes representing ranged one-dimensional distributions.
Defines scan resolution class.
Declares the class SpecularSimulationElement.
Axis with fixed bin size.
Definition: FixedBinAxis.h:23
Interface for one-dimensional axes.
Definition: IAxis.h:25
Interface for one-dimensional ranged distributions.
Assembles beam, detector and their relative positions with respect to the sample.
Definition: Instrument.h:32
Axis containing arbitrary (non-equidistant) coordinate values.
Definition: PointwiseAxis.h:37
Scan type with z-components of scattering vector as coordinate values.
Definition: QSpecScan.h:28
std::vector< SpecularSimulationElement > generateSimulationElements(const Instrument &instrument) const override
Generates simulation elements for specular simulations.
Definition: QSpecScan.cpp:54
double m_offset
Definition: QSpecScan.h:98
void setAbsoluteQResolution(const IRangedDistribution &distr, double std_dev)
Definition: QSpecScan.cpp:122
size_t numberOfSimulationElements() const override
Returns the number of simulation elements.
Definition: QSpecScan.cpp:76
QSpecScan * clone() const override
Definition: QSpecScan.cpp:44
std::vector< double > footprint(size_t i, size_t n_elements) const override
Returns footprint correction factor for a range of simulation elements of size n_elements and startin...
Definition: QSpecScan.cpp:67
std::vector< std::vector< ParameterSample > > m_q_res_cache
Definition: QSpecScan.h:96
void setRelativeQResolution(const IRangedDistribution &distr, double rel_dev)
Definition: QSpecScan.cpp:107
std::vector< double > createIntensities(const std::vector< SpecularSimulationElement > &sim_elements) const override
Returns intensity vector corresponding to convolution of given simulation elements.
Definition: QSpecScan.cpp:82
QSpecScan(std::vector< double > qs_nm)
Accepts qz-value vector (in inverse nm)
Definition: QSpecScan.cpp:22
std::unique_ptr< ScanResolution > m_resolution
Definition: QSpecScan.h:95
void setQResolution(const ScanResolution &resolution)
Sets q resolution values via ScanResolution object.
Definition: QSpecScan.cpp:100
void checkInitialization()
Definition: QSpecScan.cpp:137
std::vector< double > generateQzVector() const
Definition: QSpecScan.cpp:149
const ScanResolution * resolution() const
Definition: QSpecScan.h:42
~QSpecScan() override
const std::unique_ptr< IAxis > m_qs
Definition: QSpecScan.h:94
std::vector< std::vector< ParameterSample > > applyQResolution() const
Definition: QSpecScan.cpp:161
Container for reflectivity resolution data.
static ScanResolution * scanAbsoluteResolution(const IRangedDistribution &distr, double stddev)
ScanResolution * clone() const override=0
static ScanResolution * scanRelativeResolution(const IRangedDistribution &distr, double stddev)
Data stucture containing both input and output of a single image pixel for specular simulation.
Definition: filesystem.h:81