BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
RectangularDetector.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Device/Detector/RectangularDetector.cpp
6 //! @brief Implements class RectangularDetector.
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/Const/Units.h"
17 #include "Base/Math/Constants.h"
19 #include "Device/Beam/Beam.h"
23 
24 RectangularDetector::RectangularDetector(size_t nxbins, double width, size_t nybins, double height)
25  : m_u0(0.0)
26  , m_v0(0.0)
27  , m_direction(kvector_t(0.0, -1.0, 0.0))
28  , m_distance(0.0)
29  , m_dbeam_u0(0.0)
30  , m_dbeam_v0(0.0)
31  , m_detector_arrangement(GENERIC)
32 {
33  setDetectorParameters(nxbins, 0.0, width, nybins, 0.0, height);
34  setName("RectangularDetector");
35 }
36 
38  : IDetector2D(other)
39  , m_normal_to_detector(other.m_normal_to_detector)
40  , m_u0(other.m_u0)
41  , m_v0(other.m_v0)
42  , m_direction(other.m_direction)
43  , m_distance(other.m_distance)
44  , m_dbeam_u0(other.m_dbeam_u0)
45  , m_dbeam_v0(other.m_dbeam_v0)
46  , m_detector_arrangement(other.m_detector_arrangement)
47  , m_u_unit(other.m_u_unit)
48  , m_v_unit(other.m_v_unit)
49 {
50  setName("RectangularDetector");
51 }
52 
54 
56 {
57  return new RectangularDetector(*this);
58 }
59 
61 {
62  double alpha_i = beam.direction().alpha();
63  kvector_t central_k = beam.getCentralK();
64  initNormalVector(central_k);
65  initUandV(alpha_i);
66 }
67 
68 void RectangularDetector::setPosition(const kvector_t normal_to_detector, double u0, double v0,
69  const kvector_t direction)
70 {
72  m_normal_to_detector = normal_to_detector;
74  m_u0 = u0;
75  m_v0 = v0;
76  m_direction = direction;
77 }
78 
79 void RectangularDetector::setPerpendicularToSampleX(double distance, double u0, double v0)
80 {
82  setDistanceAndOffset(distance, u0, v0);
83 }
84 
85 void RectangularDetector::setPerpendicularToDirectBeam(double distance, double u0, double v0)
86 {
88  setDistanceAndOffset(distance, u0, v0);
89 }
90 
91 void RectangularDetector::setPerpendicularToReflectedBeam(double distance, double u0, double v0)
92 {
94  setDistanceAndOffset(distance, u0, v0);
95 }
96 
98 {
100  m_dbeam_u0 = u0;
101  m_dbeam_v0 = v0;
102 }
103 
105 {
106  return axis(0).span();
107 }
108 
110 {
111  return axis(1).span();
112 }
113 
115 {
116  return axis(0).size();
117 }
118 
120 {
121  return axis(1).size();
122 }
123 
125 {
126  return m_normal_to_detector;
127 }
128 
130 {
131  return m_u0;
132 }
133 
135 {
136  return m_v0;
137 }
138 
140 {
141  return m_direction;
142 }
143 
145 {
146  return m_distance;
147 }
148 
150 {
151  return m_dbeam_u0;
152 }
153 
155 {
156  return m_dbeam_v0;
157 }
158 
160 {
161  return m_detector_arrangement;
162 }
163 
165 {
166  return Axes::Units::MM;
167 }
168 
170 {
171  const IAxis& u_axis = axis(0);
172  const IAxis& v_axis = axis(1);
173  double u_min, v_min, width, height;
174  auto p_roi = regionOfInterest();
175  if (p_roi) {
176  u_min = p_roi->getXlow();
177  v_min = p_roi->getYlow();
178  width = p_roi->getXup() - p_roi->getXlow();
179  height = p_roi->getYup() - p_roi->getYlow();
180  } else {
181  u_min = u_axis.lowerBound();
182  v_min = v_axis.lowerBound();
183  width = getWidth();
184  height = getHeight();
185  }
186  const kvector_t corner_position(m_normal_to_detector + (u_min - m_u0) * m_u_unit
187  + (v_min - m_v0) * m_v_unit);
188  const kvector_t uaxis_vector = width * m_u_unit;
189  const kvector_t vaxis_vector = height * m_v_unit;
190  return new RectangularPixel(corner_position, uaxis_vector, vaxis_vector);
191 }
192 
194 {
195  const IAxis& u_axis = axis(0);
196  const IAxis& v_axis = axis(1);
197  const size_t u_index = axisBinIndex(index, 0);
198  const size_t v_index = axisBinIndex(index, 1);
199 
200  const Bin1D u_bin = u_axis.bin(u_index);
201  const Bin1D v_bin = v_axis.bin(v_index);
202  const kvector_t corner_position(m_normal_to_detector + (u_bin.m_lower - m_u0) * m_u_unit
203  + (v_bin.m_lower - m_v0) * m_v_unit);
204  const kvector_t width = u_bin.binSize() * m_u_unit;
205  const kvector_t height = v_bin.binSize() * m_v_unit;
206  return new RectangularPixel(corner_position, width, height);
207 }
208 
209 std::string RectangularDetector::axisName(size_t index) const
210 {
211  switch (index) {
212  case 0:
213  return "u";
214  case 1:
215  return "v";
216  default:
217  throw std::runtime_error(
218  "RectangularDetector::getAxisName(size_t index) -> Error! index > 1");
219  }
220 }
221 
223 {
224  if (dimension() != 2)
225  return totalSize();
226  const double alpha = beam.direction().alpha();
227  const double phi = beam.direction().phi();
228  const kvector_t k_spec = vecOfLambdaAlphaPhi(beam.wavelength(), alpha, phi);
229  const kvector_t normal_unit = m_normal_to_detector.unit();
230  const double kd = k_spec.dot(normal_unit);
231  if (kd <= 0.0)
232  return totalSize();
233  ASSERT(m_distance != 0);
234  const kvector_t rpix = k_spec * (m_distance / kd);
235  const double u = rpix.dot(m_u_unit) + m_u0;
236  const double v = rpix.dot(m_v_unit) + m_v0;
237  const IAxis& u_axis = axis(0); // the x axis, GISAS only
238  const IAxis& v_axis = axis(1); // the y axis, in reflectometer plane
239  if (!u_axis.contains(u) || !v_axis.contains(v))
240  return totalSize();
241  return getGlobalIndex(u_axis.findClosestIndex(u), v_axis.findClosestIndex(v));
242 }
243 
244 void RectangularDetector::setDistanceAndOffset(double distance, double u0, double v0)
245 {
246  if (distance <= 0.0) {
247  std::ostringstream message;
248  message << "RectangularDetector::setPerpendicularToSample() -> Error. "
249  << "Distance to sample can't be negative or zero";
250  throw std::runtime_error(message.str());
251  }
252  m_distance = distance;
253  m_u0 = u0;
254  m_v0 = v0;
255 }
256 
258 {
259  kvector_t central_k_unit = central_k.unit();
260 
262  // do nothing
263  }
264 
267  }
268 
270  m_normal_to_detector = m_distance * central_k_unit;
271  }
272 
275  m_normal_to_detector = m_distance * central_k_unit;
277  }
278 
279  else {
280  throw std::runtime_error("RectangularDetector::init() -> Unknown detector arrangement");
281  }
282 }
283 
284 void RectangularDetector::initUandV(double alpha_i)
285 {
287  kvector_t u_direction =
289  m_u_unit = u_direction.unit();
291 
293  kvector_t z(0.0, 0.0, 1.0);
294  kvector_t normal_unit = m_normal_to_detector.unit();
295  kvector_t zp = z - z.dot(normal_unit) * normal_unit;
296  double uz = zp.dot(m_u_unit) / zp.mag();
297  double vz = zp.dot(m_v_unit) / zp.mag();
298  m_u0 = m_dbeam_u0 + m_distance * std::tan(2 * alpha_i) * uz;
299  m_v0 = m_dbeam_v0 + m_distance * std::tan(2 * alpha_i) * vz;
300  }
301 }
#define ASSERT(condition)
Definition: Assert.h:31
Defines class Beam.
Defines M_PI and some more mathematical constants.
kvector_t vecOfLambdaAlphaPhi(double _lambda, double _alpha, double _phi)
Definition: Direction.cpp:19
Defines interface IDetectorResolution.
Defines class RectangularDetector.
Defines class RectangularPixel.
Defines class RegionOfInterest.
Defines class SimulationElement.
Defines some unit conversion factors and other constants in namespace Units.
BasicVector3D< double > kvector_t
Definition: Vectors3D.h:21
auto dot(const BasicVector3D< U > &v) const
Returns dot product of vectors (antilinear in the first [=self] argument).
BasicVector3D< T > unit() const
Returns unit vector in direction of this. Throws for null vector.
double mag() const
Returns magnitude of the vector.
T z() const
Returns z-component in cartesian coordinate system.
Definition: BasicVector3D.h:67
void setZ(const T &a)
Sets z-component in cartesian coordinate system.
Definition: BasicVector3D.h:74
auto cross(const BasicVector3D< U > &v) const
Returns cross product of vectors (linear in both arguments).
An incident neutron or x-ray beam.
Definition: Beam.h:27
Direction direction() const
Definition: Beam.h:45
double wavelength() const
Definition: Beam.h:43
kvector_t getCentralK() const
Returns the wavevector.
Definition: Beam.cpp:73
double phi() const
Definition: Direction.h:30
double alpha() const
Definition: Direction.h:29
Interface for one-dimensional axes.
Definition: IAxis.h:25
double span() const
Returns distance from first to last point.
Definition: IAxis.cpp:42
virtual bool contains(double value) const
Returns true if axis contains given point.
Definition: IAxis.cpp:37
virtual size_t findClosestIndex(double value) const =0
find bin index which is best match for given value
virtual Bin1D bin(size_t index) const =0
retrieve a 1d bin for the given index
virtual size_t size() const =0
retrieve the number of bins
virtual double lowerBound() const =0
Returns value of first point of axis.
Abstract 2D detector interface.
Definition: IDetector2D.h:31
const RegionOfInterest * regionOfInterest() const override
Returns region of interest if exists.
Definition: IDetector2D.cpp:43
void setDetectorParameters(size_t n_x, double x_min, double x_max, size_t n_y, double y_min, double y_max)
Sets detector parameters using angle ranges.
Definition: IDetector2D.cpp:35
size_t getGlobalIndex(size_t x, size_t y) const
Calculate global index from two axis indices.
Definition: IDetector2D.cpp:92
size_t dimension() const
Returns actual dimensionality of the detector (number of defined axes)
Definition: IDetector.cpp:46
size_t axisBinIndex(size_t index, size_t selected_axis) const
Calculate axis index for given global index.
Definition: IDetector.cpp:63
size_t totalSize() const
Returns total number of pixels.
Definition: IDetector.cpp:88
const IAxis & axis(size_t index) const
Definition: IDetector.cpp:56
void setName(const std::string &name)
Interface for a function that maps [0,1]x[0,1] to the kvectors in a pixel.
Definition: IPixel.h:25
A flat rectangular detector with axes and resolution function.
void setDirectBeamPosition(double u0, double v0)
double m_dbeam_v0
position of direct beam in detector coordinates
void initUandV(double alpha_i)
void init(const Beam &beam) override
Inits detector with the beam settings.
double m_v0
position of normal vector hitting point in detector coordinates
void setPerpendicularToSampleX(double distance, double u0, double v0)
void setPerpendicularToDirectBeam(double distance, double u0, double v0)
kvector_t m_direction
direction vector of detector coordinate system
void initNormalVector(const kvector_t central_k)
void setPerpendicularToReflectedBeam(double distance, double u0=0.0, double v0=0.0)
Axes::Units defaultAxesUnits() const override
return default axes units
EDetectorArrangement getDetectorArrangment() const
RectangularDetector * clone() const override
size_t indexOfSpecular(const Beam &beam) const override
Returns index of pixel that contains the specular wavevector.
void setPosition(const kvector_t normal_to_detector, double u0, double v0, const kvector_t direction=kvector_t(0.0, -1.0, 0.0))
IPixel * createPixel(size_t index) const override
Creates an IPixel for the given OutputData object and index.
double getDirectBeamV0() const
kvector_t getDirectionVector() const
double m_distance
distance from sample origin to the detector plane
std::string axisName(size_t index) const override
Returns the name for the axis with given index.
EDetectorArrangement m_detector_arrangement
double getDirectBeamU0() const
RectangularDetector(size_t nxbins, double width, size_t nybins, double height)
Rectangular detector constructor.
kvector_t getNormalVector() const
void setDistanceAndOffset(double distance, double u0, double v0)
RectangularPixel * regionOfInterestPixel() const
A pixel in a RectangularDetector.
Definition: Bin.h:20
double binSize() const
Definition: Bin.h:26
double m_lower
lower bound of the bin
Definition: Bin.h:23