BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
CoordSystem2D.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Device/Coord/CoordSystem2D.cpp
6 //! @brief Implements ICoordSystem classes.
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 #include "Base/Axis/FixedBinAxis.h"
17 #include "Base/Const/Units.h"
18 #include "Base/Math/Constants.h"
20 #include "Base/Util/Assert.h"
21 #include "Base/Vector/Direction.h"
22 #include "Device/Coord/AxisNames.h"
23 #include <algorithm>
24 #include <cmath>
25 
26 namespace {
27 
28 double getQ(double wavelength, double angle)
29 {
30  return 4.0 * M_PI * std::sin(angle) / wavelength;
31 }
32 
33 double axisAngle(size_t i_axis, R3 k_f)
34 {
35  if (i_axis == 0)
36  return R3Util::phi(k_f);
37  if (i_axis == 1)
38  return M_PI_2 - R3Util::theta(k_f);
39  ASSERT(0);
40 }
41 
42 } // namespace
43 
44 // ************************************************************************************************
45 // class CoordSystem2D
46 // ************************************************************************************************
47 
48 CoordSystem2D::CoordSystem2D(const Direction& direction, double wavelength)
49  : CoordSystem2D({}, direction, wavelength)
50 {
51 }
52 
54  double wavelength)
55  : m_axes(axes)
56  , m_wavelength(wavelength)
57  , m_alpha_i(-direction.alpha())
58  , m_phi_i(direction.phi())
59 {
60 }
61 
63  : m_axes(other.m_axes)
64  , m_wavelength(other.m_wavelength)
65  , m_alpha_i(other.m_alpha_i)
66  , m_phi_i(other.m_phi_i)
67 {
68 }
69 
70 void CoordSystem2D::addAxisData(std::string name, double min, double max, size_t nbins)
71 {
72  m_axes.emplace_back(new FixedBinAxis(name, min, max, nbins));
73 }
74 
75 double CoordSystem2D::calculateMin(size_t i_axis, Coords units) const
76 {
77  ASSERT(i_axis < rank());
78  units = substituteDefaultUnits(units);
79  if (units == Coords::NBINS)
80  return 0.0;
81  return calculateValue(i_axis, units, m_axes[i_axis]->min());
82 }
83 
84 double CoordSystem2D::calculateMax(size_t i_axis, Coords units) const
85 {
86  ASSERT(i_axis < rank());
87  units = substituteDefaultUnits(units);
88  if (units == Coords::NBINS)
89  return m_axes[i_axis]->size();
90  return calculateValue(i_axis, units, m_axes[i_axis]->max());
91 }
92 
93 size_t CoordSystem2D::axisSize(size_t i_axis) const
94 {
95  ASSERT(i_axis < rank());
96  return m_axes[i_axis]->size();
97 }
98 
99 std::vector<Coords> CoordSystem2D::availableUnits() const
100 {
102 }
103 
104 IAxis* CoordSystem2D::createConvertedAxis(size_t i_axis, Coords units) const
105 {
106  const double min = calculateMin(i_axis, units);
107  const double max = calculateMax(i_axis, units);
108  const auto& axis_name = axisName(i_axis, units);
109  const auto axis_size = axisSize(i_axis);
110  return new FixedBinAxis(axis_name, axis_size, min, max);
111 }
112 
113 // ************************************************************************************************
114 // class SphericalCoords
115 // ************************************************************************************************
116 
118  double wavelength)
119  : CoordSystem2D(axes, direction, wavelength)
120 {
121  ASSERT(axes.size() == 2);
122 }
123 
125  : CoordSystem2D(other)
126 {
127 }
128 
130 
132 {
133  return new SphericalCoords(*this);
134 }
135 
136 std::vector<Coords> SphericalCoords::availableUnits() const
137 {
138  auto result = CoordSystem2D::availableUnits();
139  result.push_back(Coords::QSPACE);
140  return result;
141 }
142 
143 double SphericalCoords::calculateValue(size_t i_axis, Coords units, double value) const
144 {
145  switch (units) {
146  case Coords::RADIANS:
147  return value;
148  case Coords::DEGREES:
149  return Units::rad2deg(value);
150  case Coords::QSPACE: {
152  if (i_axis == 0) {
153  const R3 k_f = vecOfLambdaAlphaPhi(m_wavelength, 0.0, value);
154  return (k_i - k_f).y();
155  }
156  if (i_axis == 1) {
157  const R3 k_f = vecOfLambdaAlphaPhi(m_wavelength, value, 0.0);
158  return (k_f - k_i).z();
159  }
160  ASSERT(0);
161  }
162  case Coords::QXQY: {
164  if (i_axis == 0) {
165  const R3 k_f = vecOfLambdaAlphaPhi(m_wavelength, 0.0, value);
166  return (k_i - k_f).y();
167  }
168  if (i_axis == 1) {
169  const R3 k_f = vecOfLambdaAlphaPhi(m_wavelength, value, 0.0);
170  return (k_f - k_i).x();
171  }
172  ASSERT(0);
173  }
174  default:
175  ASSERT(0);
176  }
177 }
178 
179 std::vector<std::map<Coords, std::string>> SphericalCoords::createNameMaps() const
180 {
182 }
183 
184 // ************************************************************************************************
185 // class ImageCoords
186 // ************************************************************************************************
187 
189  const Direction& direction, double wavelength)
190  : CoordSystem2D(axes, direction, wavelength)
191  , m_detector_pixel(regionOfInterestPixel)
192 {
193  ASSERT(axes.size() == 2);
194 }
195 
197  : CoordSystem2D(other)
198  , m_detector_pixel(other.m_detector_pixel->clone())
199 {
200 }
201 
202 ImageCoords::~ImageCoords() = default;
203 
205 {
206  return new ImageCoords(*this);
207 }
208 
209 std::vector<Coords> ImageCoords::availableUnits() const
210 {
211  auto result = CoordSystem2D::availableUnits();
212  result.push_back(Coords::QSPACE);
213  result.push_back(Coords::MM);
214  return result;
215 }
216 
217 double ImageCoords::calculateValue(size_t i_axis, Coords units, double value) const
218 {
219  ASSERT(m_wavelength > 0);
220  if (units == Coords::MM)
221  return value;
222  const auto k00 = m_detector_pixel->getPosition(0.0, 0.0);
223  const auto k01 = m_detector_pixel->getPosition(0.0, 1.0);
224  const auto k10 = m_detector_pixel->getPosition(1.0, 0.0);
225  const auto& max_pos = i_axis == 0 ? k10 : k01; // position of max along given axis
226  const double shift = value - m_axes[i_axis]->min();
227  const R3 out_dir = k00 + shift * (max_pos - k00).unit();
228  const R3 k_f = out_dir.unit() * M_TWOPI / m_wavelength;
229 
230  switch (units) {
231  case Coords::RADIANS:
232  return axisAngle(i_axis, k_f);
233  case Coords::DEGREES:
234  return Units::rad2deg(axisAngle(i_axis, k_f));
235  case Coords::QSPACE: {
237  if (i_axis == 0)
238  return (k_i - k_f).y();
239  if (i_axis == 1)
240  return (k_f - k_i).z();
241  } break;
242  case Coords::QXQY: {
244  if (i_axis == 0)
245  return (k_i - k_f).y();
246  if (i_axis == 1)
247  return (k_f - k_i).x();
248  } break;
249  default:
250  break;
251  }
252  ASSERT(0);
253 }
254 
255 std::vector<std::map<Coords, std::string>> ImageCoords::createNameMaps() const
256 {
258 }
259 
260 // ************************************************************************************************
261 // class OffspecCoordinates
262 // ************************************************************************************************
263 
265  : CoordSystem2D(axes, direction)
266 {
267 }
268 
270  : CoordSystem2D(other)
271 {
272 }
273 
275 {
276  return new OffspecCoordinates(*this);
277 }
278 
279 double OffspecCoordinates::calculateValue(size_t, Coords units, double value) const
280 {
281  switch (units) {
282  case Coords::RADIANS:
283  return value;
284  case Coords::DEGREES:
285  return Units::rad2deg(value);
286  default:
287  ASSERT(0);
288  }
289 }
290 
291 std::vector<std::map<Coords, std::string>> OffspecCoordinates::createNameMaps() const
292 {
294 }
295 
296 // ************************************************************************************************
297 // class DepthProbeCoordinates
298 // ************************************************************************************************
299 
300 const std::string z_axis_name = "Position [nm]";
301 
303  const Direction& direction, double wavelength)
304  : CoordSystem2D(axes, direction, wavelength)
305 {
306 }
307 
309  : CoordSystem2D(other)
310 {
311 }
312 
314 
316 {
317  return new DepthProbeCoordinates(*this);
318 }
319 
320 std::vector<Coords> DepthProbeCoordinates::availableUnits() const
321 {
322  auto result = CoordSystem2D::availableUnits();
323  result.push_back(Coords::QSPACE);
324  return result;
325 }
326 
327 double DepthProbeCoordinates::calculateValue(size_t i_axis, Coords units, double value) const
328 {
329  const auto& available_units = availableUnits();
330  if (std::find(available_units.begin(), available_units.end(), units) == available_units.cend())
331  ASSERT(0);
332 
333  if (i_axis == 1)
334  return value; // unit conversions are not applied to sample position axis
335  switch (units) {
336  case Coords::DEGREES:
337  return Units::rad2deg(value);
338  case Coords::QSPACE:
339  return getQ(m_wavelength, value);
340  default:
341  return value;
342  }
343 }
344 
345 std::vector<std::map<Coords, std::string>> DepthProbeCoordinates::createNameMaps() const
346 {
348 }
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:45
Defines axisUnitLabel and maps in namespace AxisNames.
Defines M_PI and some more mathematical constants.
#define M_TWOPI
Definition: Constants.h:54
#define M_PI_2
Definition: Constants.h:45
#define M_PI
Definition: Constants.h:44
const std::string z_axis_name
Defines interface CoordSystem2D and its subclasses.
R3 vecOfLambdaAlphaPhi(double _lambda, double _alpha, double _phi)
Definition: Direction.cpp:19
Defines class Direction.
Defines class FixedBinAxis.
Defines class RectangularPixel.
Defines some unit conversion factors and other constants in namespace Units.
Interface for objects that provide axis translations to different units for IDetector objects.
Definition: CoordSystem2D.h:32
OwningVector< IAxis > m_axes
Definition: CoordSystem2D.h:56
size_t axisSize(size_t i_axis) const override
size_t rank() const override
Definition: CoordSystem2D.h:39
virtual double calculateValue(size_t i_axis, Coords units, double value) const =0
void addAxisData(std::string name, double min, double max, size_t nbins)
double m_wavelength
Definition: CoordSystem2D.h:57
std::vector< Coords > availableUnits() const override
Returns list of units that are available for all 2D detectors. Further units may be added by child cl...
CoordSystem2D(const Direction &direction, double wavelength=0)
double calculateMin(size_t i_axis, Coords units) const override
double calculateMax(size_t i_axis, Coords units) const override
double m_alpha_i
Definition: CoordSystem2D.h:58
IAxis * createConvertedAxis(size_t i_axis, Coords units) const override
DepthProbeCoordinates class handles the unit translations for depth probe simulations Its default uni...
DepthProbeCoordinates(const OwningVector< IAxis > &axes, const Direction &direction, double wavelength)
std::vector< Coords > availableUnits() const override
Returns list of units that are available for all 2D detectors. Further units may be added by child cl...
DepthProbeCoordinates * clone() const override
~DepthProbeCoordinates() override
double calculateValue(size_t, Coords units, double value) const override
std::vector< std::map< Coords, std::string > > createNameMaps() const override
A direction in three-dimensional space.
Definition: Direction.h:24
Axis with fixed bin size.
Definition: FixedBinAxis.h:23
Abstract base class for one-dimensional axes.
Definition: IAxis.h:27
Coords substituteDefaultUnits(Coords units) const
std::string axisName(size_t i_axis, Coords units=Coords::UNDEFINED) const
ICoordSystem class that handles the unit translations for rectangular detectors Its default units are...
Definition: CoordSystem2D.h:90
std::vector< Coords > availableUnits() const override
Returns list of units that are available for all 2D detectors. Further units may be added by child cl...
double calculateValue(size_t i_axis, Coords units, double value) const override
ImageCoords(const OwningVector< IAxis > &axes, RectangularPixel *regionOfInterestPixel, const Direction &direction, double wavelength)
std::unique_ptr< RectangularPixel > m_detector_pixel
std::vector< std::map< Coords, std::string > > createNameMaps() const override
~ImageCoords() override
ImageCoords * clone() const override
ICoordSystem class that handles the unit translations for off-specular simulations with a spherical d...
OffspecCoordinates * clone() const override
OffspecCoordinates(const OwningVector< IAxis > &axes, const Direction &direction)
double calculateValue(size_t i_axis, Coords units, double value) const override
std::vector< std::map< Coords, std::string > > createNameMaps() const override
void emplace_back(T *e)
Definition: OwningVector.h:62
size_t size() const
Definition: OwningVector.h:70
A pixel in a RectangularDetector.
ICoordSystem class that handles the unit translations for spherical detectors Its default units are r...
Definition: CoordSystem2D.h:69
std::vector< Coords > availableUnits() const override
Returns list of units that are available for all 2D detectors. Further units may be added by child cl...
std::vector< std::map< Coords, std::string > > createNameMaps() const override
SphericalCoords * clone() const override
SphericalCoords(const OwningVector< IAxis > &axes, const Direction &direction, double wavelength)
double calculateValue(size_t i_axis, Coords units, double value) const override
~SphericalCoords() override
Coords
Definition: Tags.h:20
BA_DEVICE_API_ const std::map< Coords, std::string > offspecAxis0
Definition: AxisNames.cpp:46
BA_DEVICE_API_ const std::map< Coords, std::string > specAxis
Definition: AxisNames.cpp:55
BA_DEVICE_API_ const std::map< Coords, std::string > sphericalAxis1
Definition: AxisNames.cpp:27
BA_DEVICE_API_ const std::map< Coords, std::string > rectangularAxis1
Definition: AxisNames.cpp:39
BA_DEVICE_API_ const std::map< Coords, std::string > sampleDepthAxis
Definition: AxisNames.cpp:71
BA_DEVICE_API_ const std::map< Coords, std::string > sphericalAxis0
Definition: AxisNames.cpp:21
BA_DEVICE_API_ const std::map< Coords, std::string > rectangularAxis0
Definition: AxisNames.cpp:35
BA_DEVICE_API_ const std::map< Coords, std::string > offspecAxis1
Definition: AxisNames.cpp:50
double rad2deg(double angle)
Definition: Units.h:54