BornAgain  1.18.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 scattering at grazing incidence
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 
17 #include "Base/Const/Units.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), m_v0(0.0), m_direction(kvector_t(0.0, -1.0, 0.0)), m_distance(0.0),
26  m_dbeam_u0(0.0), m_dbeam_v0(0.0), m_detector_arrangement(GENERIC)
27 {
28  setDetectorParameters(nxbins, 0.0, width, nybins, 0.0, height);
29  setName("RectangularDetector");
30 }
31 
33  : IDetector2D(other), m_normal_to_detector(other.m_normal_to_detector), m_u0(other.m_u0),
34  m_v0(other.m_v0), m_direction(other.m_direction), m_distance(other.m_distance),
35  m_dbeam_u0(other.m_dbeam_u0), m_dbeam_v0(other.m_dbeam_v0),
36  m_detector_arrangement(other.m_detector_arrangement), m_u_unit(other.m_u_unit),
37  m_v_unit(other.m_v_unit)
38 {
39  setName("RectangularDetector");
40 }
41 
43 
45 {
46  return new RectangularDetector(*this);
47 }
48 
50 {
51  double alpha_i = beam.getAlpha();
52  kvector_t central_k = beam.getCentralK();
53  initNormalVector(central_k);
54  initUandV(alpha_i);
55 }
56 
57 void RectangularDetector::setPosition(const kvector_t normal_to_detector, double u0, double v0,
58  const kvector_t direction)
59 {
61  m_normal_to_detector = normal_to_detector;
63  m_u0 = u0;
64  m_v0 = v0;
65  m_direction = direction;
66 }
67 
68 void RectangularDetector::setPerpendicularToSampleX(double distance, double u0, double v0)
69 {
71  setDistanceAndOffset(distance, u0, v0);
72 }
73 
74 void RectangularDetector::setPerpendicularToDirectBeam(double distance, double u0, double v0)
75 {
77  setDistanceAndOffset(distance, u0, v0);
78 }
79 
80 void RectangularDetector::setPerpendicularToReflectedBeam(double distance, double u0, double v0)
81 {
83  setDistanceAndOffset(distance, u0, v0);
84 }
85 
87 {
89  m_dbeam_u0 = u0;
90  m_dbeam_v0 = v0;
91 }
92 
94 {
95  const IAxis& axis = getAxis(0);
96  return axis.getMax() - axis.getMin();
97 }
98 
100 {
101  const IAxis& axis = getAxis(1);
102  return axis.getMax() - axis.getMin();
103 }
104 
106 {
107  return getAxis(0).size();
108 }
109 
111 {
112  return getAxis(1).size();
113 }
114 
116 {
117  return m_normal_to_detector;
118 }
119 
121 {
122  return m_u0;
123 }
124 
126 {
127  return m_v0;
128 }
129 
131 {
132  return m_direction;
133 }
134 
136 {
137  return m_distance;
138 }
139 
141 {
142  return m_dbeam_u0;
143 }
144 
146 {
147  return m_dbeam_v0;
148 }
149 
151 {
152  return m_detector_arrangement;
153 }
154 
156 {
157  return Axes::Units::MM;
158 }
159 
161 {
162  const IAxis& u_axis = getAxis(0);
163  const IAxis& v_axis = getAxis(1);
164  double u_min, v_min, width, height;
165  auto p_roi = regionOfInterest();
166  if (p_roi) {
167  u_min = p_roi->getXlow();
168  v_min = p_roi->getYlow();
169  width = p_roi->getXup() - p_roi->getXlow();
170  height = p_roi->getYup() - p_roi->getYlow();
171  } else {
172  u_min = u_axis.getMin();
173  v_min = v_axis.getMin();
174  width = getWidth();
175  height = getHeight();
176  }
177  const kvector_t corner_position(m_normal_to_detector + (u_min - m_u0) * m_u_unit
178  + (v_min - m_v0) * m_v_unit);
179  const kvector_t uaxis_vector = width * m_u_unit;
180  const kvector_t vaxis_vector = height * m_v_unit;
181  return new RectangularPixel(corner_position, uaxis_vector, vaxis_vector);
182 }
183 
185 {
186  const IAxis& u_axis = getAxis(0);
187  const IAxis& v_axis = getAxis(1);
188  const size_t u_index = axisBinIndex(index, 0);
189  const size_t v_index = axisBinIndex(index, 1);
190 
191  const Bin1D u_bin = u_axis.getBin(u_index);
192  const Bin1D v_bin = v_axis.getBin(v_index);
193  const kvector_t corner_position(m_normal_to_detector + (u_bin.m_lower - m_u0) * m_u_unit
194  + (v_bin.m_lower - m_v0) * m_v_unit);
195  const kvector_t width = u_bin.getBinSize() * m_u_unit;
196  const kvector_t height = v_bin.getBinSize() * m_v_unit;
197  return new RectangularPixel(corner_position, width, height);
198 }
199 
200 std::string RectangularDetector::axisName(size_t index) const
201 {
202  switch (index) {
203  case 0:
204  return "u";
205  case 1:
206  return "v";
207  default:
209  "RectangularDetector::getAxisName(size_t index) -> Error! index > 1");
210  }
211 }
212 
214 {
215  if (dimension() != 2)
216  return totalSize();
217  const double alpha = beam.getAlpha();
218  const double phi = beam.getPhi();
219  const kvector_t k_spec = vecOfLambdaAlphaPhi(beam.getWavelength(), alpha, phi);
220  const kvector_t normal_unit = m_normal_to_detector.unit();
221  const double kd = k_spec.dot(normal_unit);
222  if (kd <= 0.0)
223  return totalSize();
224  ASSERT(m_distance != 0);
225  const kvector_t rpix = k_spec * (m_distance / kd);
226  const double u = rpix.dot(m_u_unit) + m_u0;
227  const double v = rpix.dot(m_v_unit) + m_v0;
228  const IAxis& u_axis = getAxis(0); // the x axis, GISAS only
229  const IAxis& v_axis = getAxis(1); // the y axis, in reflectometer plane
230  if (!u_axis.contains(u) || !v_axis.contains(v))
231  return totalSize();
232  return getGlobalIndex(u_axis.findClosestIndex(u), v_axis.findClosestIndex(v));
233 }
234 
235 void RectangularDetector::setDistanceAndOffset(double distance, double u0, double v0)
236 {
237  if (distance <= 0.0) {
238  std::ostringstream message;
239  message << "RectangularDetector::setPerpendicularToSample() -> Error. "
240  << "Distance to sample can't be negative or zero";
241  throw Exceptions::LogicErrorException(message.str());
242  }
243  m_distance = distance;
244  m_u0 = u0;
245  m_v0 = v0;
246 }
247 
249 {
250  kvector_t central_k_unit = central_k.unit();
251 
253  // do nothing
254  }
255 
258  }
259 
261  m_normal_to_detector = m_distance * central_k_unit;
262  }
263 
266  m_normal_to_detector = m_distance * central_k_unit;
268  }
269 
270  else {
272  "RectangularDetector::init() -> Unknown detector arrangement");
273  }
274 }
275 
276 void RectangularDetector::initUandV(double alpha_i)
277 {
279  kvector_t u_direction =
281  m_u_unit = u_direction.unit();
283 
285  kvector_t z(0.0, 0.0, 1.0);
286  kvector_t normal_unit = m_normal_to_detector.unit();
287  kvector_t zp = z - z.dot(normal_unit) * normal_unit;
288  double uz = zp.dot(m_u_unit) / zp.mag();
289  double vz = zp.dot(m_v_unit) / zp.mag();
290  m_u0 = m_dbeam_u0 + m_distance * std::tan(2 * alpha_i) * uz;
291  m_v0 = m_dbeam_v0 + m_distance * std::tan(2 * alpha_i) * vz;
292  }
293 }
#define ASSERT(condition)
Definition: Assert.h:26
BasicVector3D< double > vecOfLambdaAlphaPhi(double _lambda, double _alpha, double _phi)
Creates a vector<double> as a wavevector with given wavelength and angles.
Defines class Beam.
Defines class IDetectorResolution.
Defines M_PI and some more mathematical constants.
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:68
void setZ(const T &a)
Sets z-component in cartesian coordinate system.
Definition: BasicVector3D.h:75
auto cross(const BasicVector3D< U > &v) const
Returns cross product of vectors (linear in both arguments).
Beam defined by wavelength, direction and intensity.
Definition: Beam.h:27
double getWavelength() const
Definition: Beam.h:69
double getAlpha() const
Definition: Beam.h:70
kvector_t getCentralK() const
Returns the wavevector.
Definition: Beam.cpp:71
double getPhi() const
Definition: Beam.h:71
Interface for one-dimensional axes.
Definition: IAxis.h:25
virtual bool contains(double value) const
Returns true if axis contains given point.
Definition: IAxis.cpp:40
virtual size_t findClosestIndex(double value) const =0
find bin index which is best match for given value
virtual Bin1D getBin(size_t index) const =0
retrieve a 1d bin for the given index
virtual double getMin() const =0
Returns value of first point of axis.
virtual size_t size() const =0
retrieve the number of bins
virtual double getMax() const =0
Returns value of last 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:98
size_t dimension() const
Returns actual dimensionality of the detector (number of defined axes)
Definition: IDetector.cpp:44
size_t axisBinIndex(size_t index, size_t selected_axis) const
Calculate axis index for given global index.
Definition: IDetector.cpp:61
size_t totalSize() const
Returns total number of pixels.
Definition: IDetector.cpp:87
const IAxis & getAxis(size_t index) const
Definition: IDetector.cpp:54
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:24
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 getBinSize() const
Definition: Bin.h:26
double m_lower
lower bound of the bin
Definition: Bin.h:23