BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
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/Axis/Bin.h"
17 #include "Base/Axis/IAxis.h"
18 #include "Base/Const/Units.h"
19 #include "Base/Math/Constants.h"
21 #include "Base/Util/Assert.h"
22 #include "Device/Beam/Beam.h"
26 
27 RectangularDetector::RectangularDetector(size_t nxbins, double width, size_t nybins, double height)
28  : m_u0(0.0)
29  , m_v0(0.0)
30  , m_direction(R3(0.0, -1.0, 0.0))
31  , m_distance(0.0)
32  , m_dbeam_u0(0.0)
33  , m_dbeam_v0(0.0)
34  , m_detector_arrangement(GENERIC)
35 {
36  setDetectorParameters(nxbins, 0.0, width, nybins, 0.0, height);
37 }
38 
40 
41  = default;
42 
44 
46 {
47  return new RectangularDetector(*this);
48 }
49 
51 {
52  initNormalVector(direction.vector());
53  initUandV(-direction.alpha());
54 }
55 
56 void RectangularDetector::setDetectorPosition(const R3 normal_to_detector, double u0, double v0,
57  const R3 direction)
58 {
60  m_normal_to_detector = normal_to_detector;
62  m_u0 = u0;
63  m_v0 = v0;
64  m_direction = direction;
65 }
66 
67 void RectangularDetector::setPerpendicularToSampleX(double distance, double u0, double v0)
68 {
70  setDistanceAndOffset(distance, u0, v0);
71 }
72 
73 void RectangularDetector::setPerpendicularToDirectBeam(double distance, double u0, double v0)
74 {
76  setDistanceAndOffset(distance, u0, v0);
77 }
78 
79 void RectangularDetector::setPerpendicularToReflectedBeam(double distance, double u0, double v0)
80 {
82  setDistanceAndOffset(distance, u0, v0);
83 }
84 
86 {
88  m_dbeam_u0 = u0;
89  m_dbeam_v0 = v0;
90 }
91 
93 {
94  return axis(0).span();
95 }
96 
98 {
99  return axis(1).span();
100 }
101 
103 {
104  return axis(0).size();
105 }
106 
108 {
109  return axis(1).size();
110 }
111 
113 {
114  return m_normal_to_detector;
115 }
116 
118 {
119  return m_u0;
120 }
121 
123 {
124  return m_v0;
125 }
126 
128 {
129  return m_direction;
130 }
131 
133 {
134  return m_distance;
135 }
136 
138 {
139  return m_dbeam_u0;
140 }
141 
143 {
144  return m_dbeam_v0;
145 }
146 
148 {
149  return m_detector_arrangement;
150 }
151 
153 {
154  const auto uAxisBoundsROI = regionOfInterestBounds(0);
155  const auto vAxisBoundsROI = regionOfInterestBounds(1);
156 
157  const double u_min = uAxisBoundsROI.first;
158  const double v_min = vAxisBoundsROI.first;
159  const double width = uAxisBoundsROI.second - uAxisBoundsROI.first;
160  const double height = vAxisBoundsROI.second - vAxisBoundsROI.first;
161 
162  const R3 corner_position(m_normal_to_detector + (u_min - m_u0) * m_u_unit
163  + (v_min - m_v0) * m_v_unit);
164  const R3 uaxis_vector = width * m_u_unit;
165  const R3 vaxis_vector = height * m_v_unit;
166  return new RectangularPixel(corner_position, uaxis_vector, vaxis_vector);
167 }
168 
170 {
171  const IAxis& u_axis = axis(0);
172  const IAxis& v_axis = axis(1);
173  const size_t u_index = axisBinIndex(index, 0);
174  const size_t v_index = axisBinIndex(index, 1);
175 
176  const Bin1D u_bin = u_axis.bin(u_index);
177  const Bin1D v_bin = v_axis.bin(v_index);
178  const R3 corner_position(m_normal_to_detector + (u_bin.m_lower - m_u0) * m_u_unit
179  + (v_bin.m_lower - m_v0) * m_v_unit);
180  const R3 width = u_bin.binSize() * m_u_unit;
181  const R3 height = v_bin.binSize() * m_v_unit;
182  return new RectangularPixel(corner_position, width, height);
183 }
184 
185 std::string RectangularDetector::axisName(size_t index) const
186 {
187  switch (index) {
188  case 0:
189  return "u";
190  case 1:
191  return "v";
192  default:
193  throw std::runtime_error(
194  "RectangularDetector::getAxisName(size_t index) -> Error! index > 1");
195  }
196 }
197 
199 {
200  if (rank() != 2)
201  return totalSize();
202  const double alpha = beam.direction().alpha();
203  const double phi = beam.direction().phi();
204  const R3 k_spec = vecOfLambdaAlphaPhi(beam.wavelength(), alpha, phi);
205  const R3 normal_unit = m_normal_to_detector.unit();
206  const double kd = k_spec.dot(normal_unit);
207  if (kd <= 0.0)
208  return totalSize();
209  ASSERT(m_distance != 0);
210  const R3 rpix = k_spec * (m_distance / kd);
211  const double u = rpix.dot(m_u_unit) + m_u0;
212  const double v = rpix.dot(m_v_unit) + m_v0;
213  const IAxis& u_axis = axis(0); // the x axis, GISAS only
214  const IAxis& v_axis = axis(1); // the y axis, in reflectometer plane
215  if (!u_axis.contains(u) || !v_axis.contains(v))
216  return totalSize();
217  return getGlobalIndex(u_axis.findClosestIndex(u), v_axis.findClosestIndex(v));
218 }
219 
220 void RectangularDetector::setDistanceAndOffset(double distance, double u0, double v0)
221 {
222  if (distance <= 0.0) {
223  std::ostringstream message;
224  message << "RectangularDetector::setPerpendicularToSample() -> Error. "
225  << "Distance to sample can't be negative or zero";
226  throw std::runtime_error(message.str());
227  }
228  m_distance = distance;
229  m_u0 = u0;
230  m_v0 = v0;
231 }
232 
234 {
235  R3 central_k_unit = central_k.unit();
236 
238  // do nothing
239  }
240 
242  m_normal_to_detector = R3(m_distance, 0.0, 0.0);
243 
244 
246  m_normal_to_detector = m_distance * central_k_unit;
247 
248 
251  m_normal_to_detector = m_distance * central_k_unit;
253  }
254 
255  else
256  throw std::runtime_error("RectangularDetector::init() -> Unknown detector arrangement");
257 }
258 
259 void RectangularDetector::initUandV(double alpha_i)
260 {
262  R3 u_direction =
264  m_u_unit = u_direction.unit();
265  m_v_unit = m_u_unit.cross(m_normal_to_detector).unit();
266 
268  R3 z(0.0, 0.0, 1.0);
269  R3 normal_unit = m_normal_to_detector.unit();
270  R3 zp = z - z.dot(normal_unit) * normal_unit;
271  double uz = zp.dot(m_u_unit) / zp.mag();
272  double vz = zp.dot(m_v_unit) / zp.mag();
273  m_u0 = m_dbeam_u0 + m_distance * std::tan(2 * alpha_i) * uz;
274  m_v0 = m_dbeam_v0 + m_distance * std::tan(2 * alpha_i) * vz;
275  }
276 }
277 
279  const Direction& beamDirection) const
280 {
281  const auto axes = axesClippedToRegionOfInterest();
282  ASSERT(axes.size() == 2);
283  const IAxis& yAxis = *axes[1];
284 
285  std::unique_ptr<RectangularPixel> det_pixel(regionOfInterestPixel());
286  IAxis* alpha_f_axis = det_pixel->createAxis(yAxis.size());
287 
288  OwningVector<IAxis> axes2({beamAxis, alpha_f_axis});
289  return new OffspecCoordinates(axes2, beamDirection);
290 }
291 
293 {
295  beam.direction(), beam.wavelength());
296 }
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:45
Defines class Beam.
Defines structs Bin1D, Bin1DCVector.
Defines M_PI and some more mathematical constants.
Defines interface CoordSystem2D and its subclasses.
Defines class DiffuseElement.
R3 vecOfLambdaAlphaPhi(double _lambda, double _alpha, double _phi)
Definition: Direction.cpp:19
Defines interface IAxis.
Defines interface IDetectorResolution.
Defines class RectangularDetector.
Defines class RectangularPixel.
Defines some unit conversion factors and other constants in namespace Units.
An incident neutron or x-ray beam.
Definition: Beam.h:28
Direction direction() const
Definition: Beam.h:46
double wavelength() const
Definition: Beam.h:44
Definition: Bin.h:20
double binSize() const
Definition: Bin.h:31
double m_lower
lower bound of the bin
Definition: Bin.h:28
Interface for objects that provide axis translations to different units for IDetector objects.
Definition: CoordSystem2D.h:32
A direction in three-dimensional space.
Definition: Direction.h:24
double phi() const
Definition: Direction.h:37
double alpha() const
Definition: Direction.h:36
R3 vector() const
Returns Cartesian 3D vector.
Definition: Direction.cpp:24
Abstract base class for one-dimensional axes.
Definition: IAxis.h:27
double span() const
Returns distance from first to last point.
Definition: IAxis.cpp:55
virtual bool contains(double value) const
Returns true if axis contains given point.
Definition: IAxis.cpp:45
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
Returns the number of bins.
Interface to provide axis translations to different units for simulation output.
Definition: ICoordSystem.h:40
std::pair< double, double > regionOfInterestBounds(size_t iAxis) const
The lower and upper bound of the region of interest. If no region of interest is explicitly defined,...
Definition: IDetector.cpp:227
size_t axisBinIndex(size_t index, size_t selected_axis) const
Calculate axis index for given global index.
Definition: IDetector.cpp:80
size_t totalSize() const
Returns total number of pixels. Any region of interest is not taken into account.
Definition: IDetector.cpp:114
void setDetectorParameters(size_t n_x, double x_min, double x_max, size_t n_y, double y_min, double y_max)
Sets equidistant axes.
Definition: IDetector.cpp:329
const IAxis & axis(size_t index) const
One axis of the complete detector. Any region of interest is not taken into account.
Definition: IDetector.cpp:74
OwningVector< IAxis > axesClippedToRegionOfInterest() const
Returns the axes clipped to the region of interest. If no region of interest is explicitly defined,...
Definition: IDetector.cpp:136
size_t getGlobalIndex(size_t x, size_t y) const
Calculate global index from two axis indices.
Definition: IDetector.cpp:377
size_t rank() const
Returns number of defined axes.
Definition: IDetector.cpp:64
Interface for a function that maps [0,1]x[0,1] to the kvectors in a pixel. Abstract base class for Sp...
Definition: IPixel.h:29
ICoordSystem class that handles the unit translations for rectangular detectors Its default units are...
Definition: CoordSystem2D.h:90
ICoordSystem class that handles the unit translations for off-specular simulations with a spherical d...
A flat rectangular detector with axes and resolution function.
void initNormalVector(R3 central_k)
CoordSystem2D * scatteringCoords(const Beam &beam) const override
R3 m_direction
direction vector of detector coordinate system
void setDirectBeamPosition(double u0, double v0)
double m_dbeam_v0
position of direct beam in detector coordinates
void initUandV(double alpha_i)
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)
void setPerpendicularToReflectedBeam(double distance, double u0=0.0, double v0=0.0)
~RectangularDetector() override
EDetectorArrangement getDetectorArrangment() const
RectangularDetector * clone() const override
size_t indexOfSpecular(const Beam &beam) const override
Returns index of pixel that contains the specular wavevector. If no pixel contains this specular wave...
void setDetectorPosition(R3 normal_to_detector, double u0, double v0, R3 direction=R3(0.0, -1.0, 0.0))
IPixel * createPixel(size_t index) const override
Creates an IPixel for the given Datafield object and index.
double getDirectBeamV0() 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
void setDetectorNormal(const Direction &direction) override
Inits detector with the beam settings.
RectangularDetector(size_t nxbins, double width, size_t nybins, double height)
Rectangular detector constructor.
ICoordSystem * offspecCoords(IAxis *beamAxis, const Direction &beamDirection) const override
void setDistanceAndOffset(double distance, double u0, double v0)
RectangularPixel * regionOfInterestPixel() const
A pixel in a RectangularDetector.