BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
IDetector.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Device/Detector/IDetector.cpp
6 //! @brief Implements common detector interface.
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 
21 
23 {
25 }
26 
28  : ICloneable()
29  , INode()
30  , m_axes(other.m_axes)
31  , m_detection_properties(other.m_detection_properties)
32 {
33  if (other.m_detector_resolution)
35  setName(other.getName());
37 }
38 
39 IDetector::~IDetector() = default;
40 
41 void IDetector::addAxis(const IAxis& axis)
42 {
44 }
45 
46 size_t IDetector::dimension() const
47 {
48  return m_axes.size();
49 }
50 
52 {
53  m_axes.clear();
54 }
55 
56 const IAxis& IDetector::axis(size_t index) const
57 {
58  if (index < dimension())
59  return *m_axes[index];
60  throw std::runtime_error("Error in IDetector::getAxis: not so many axes in this detector.");
61 }
62 
63 size_t IDetector::axisBinIndex(size_t index, size_t selected_axis) const
64 {
65  const size_t dim = dimension();
66  size_t remainder(index);
67  size_t i_axis = dim;
68  for (size_t i = 0; i < dim; ++i) {
69  --i_axis;
70  if (selected_axis == i_axis)
71  return remainder % m_axes[i_axis]->size();
72  remainder /= m_axes[i_axis]->size();
73  }
74  throw std::runtime_error("IDetector::getAxisBinIndex() -> "
75  "Error! No axis with given number");
76 }
77 
78 std::unique_ptr<IAxis> IDetector::createAxis(size_t index, size_t n_bins, double min,
79  double max) const
80 {
81  if (max <= min)
82  throw std::runtime_error("IDetector::createAxis() -> Error! max <= min");
83  if (n_bins == 0)
84  throw std::runtime_error("IDetector::createAxis() -> Error! Number n_bins can't be zero.");
85  return std::make_unique<FixedBinAxis>(axisName(index), n_bins, min, max);
86 }
87 
88 size_t IDetector::totalSize() const
89 {
90  const size_t dim = dimension();
91  if (dim == 0)
92  return 0;
93  size_t result = 1;
94  for (size_t i_axis = 0; i_axis < dim; ++i_axis)
95  result *= m_axes[i_axis]->size();
96  return result;
97 }
98 
99 void IDetector::setAnalyzerProperties(const kvector_t direction, double efficiency,
100  double total_transmission)
101 {
102  m_detection_properties.setAnalyzerProperties(direction, efficiency, total_transmission);
103 }
104 
105 void IDetector::setDetectorResolution(const IDetectorResolution& p_detector_resolution)
106 {
107  m_detector_resolution.reset(p_detector_resolution.clone());
109 }
110 
111 // TODO: pass dimension-independent argument to this function
113 {
114  ConvolutionDetectorResolution convFunc(resFunc);
115  setDetectorResolution(convFunc);
116 }
117 
119 {
120  if (!p_intensity_map)
121  throw std::runtime_error("IDetector::applyDetectorResolution() -> "
122  "Error! Null pointer to intensity map");
123  if (m_detector_resolution) {
124  m_detector_resolution->applyDetectorResolution(p_intensity_map);
125  if (detectorMask() && detectorMask()->hasMasks()) {
126  // sets amplitude in masked areas to zero
127  std::unique_ptr<OutputData<double>> buff(new OutputData<double>());
128  buff->copyShapeFrom(*p_intensity_map);
129 
130  iterate([&](const_iterator it) {
131  (*buff)[it.roiIndex()] = (*p_intensity_map)[it.roiIndex()];
132  });
133  p_intensity_map->setRawDataVector(buff->getRawDataVector());
134  }
135  }
136 }
137 
139 {
140  return m_detector_resolution.get();
141 }
142 
144 IDetector::createDetectorIntensity(const std::vector<SimulationElement>& elements) const
145 {
146  std::unique_ptr<OutputData<double>> detectorMap(createDetectorMap());
147  if (!detectorMap)
148  throw std::runtime_error("Instrument::createDetectorIntensity:"
149  "can't create detector map.");
150 
151  setDataToDetectorMap(*detectorMap, elements);
153  applyDetectorResolution(detectorMap.get());
154 
155  return detectorMap.release();
156 }
157 
158 std::unique_ptr<OutputData<double>> IDetector::createDetectorMap() const
159 {
160  const size_t dim = dimension();
161  if (dim == 0)
162  throw std::runtime_error(
163  "Error in IDetector::createDetectorMap: dimensions of the detector are undefined");
164 
165  std::unique_ptr<OutputData<double>> result(new OutputData<double>);
166  for (size_t i = 0; i < dim; ++i)
167  if (auto roi = regionOfInterest())
168  result->addAxis(*roi->clipAxisToRoi(i, axis(i)));
169  else
170  result->addAxis(axis(i));
171 
172  return result;
173 }
174 
176  const std::vector<SimulationElement>& elements) const
177 {
178  if (elements.empty())
179  return;
180  iterate([&](const_iterator it) {
181  detectorMap[it.roiIndex()] = elements[it.elementIndex()].intensity();
182  });
183 }
184 
186 {
187  size_t result(0);
188  iterate([&result](const_iterator) { ++result; });
189  return result;
190 }
191 
192 std::vector<const INode*> IDetector::getChildren() const
193 {
194  return std::vector<const INode*>() << &m_detection_properties << m_detector_resolution;
195 }
196 
197 void IDetector::iterate(std::function<void(IDetector::const_iterator)> func, bool visit_masks) const
198 {
199  if (this->dimension() == 0)
200  return;
201 
202  if (visit_masks) {
203  SimulationRoiArea area(this);
204  for (SimulationRoiArea::iterator it = area.begin(); it != area.end(); ++it)
205  func(it);
206  } else {
207  SimulationArea area(this);
208  for (SimulationArea::iterator it = area.begin(); it != area.end(); ++it)
209  func(it);
210  }
211 }
Defines class ConvolutionDetectorResolution.
Defines class DetectorMask.
Defines common detector interface.
Defines class RegionOfInterest.
Defines class SimulationArea.
Defines class SimulationElement.
void push_back(T *t)
Convolutes the intensity in 1 or 2 dimensions with a resolution function.
void setAnalyzerProperties(const kvector_t direction, double efficiency, double total_transmission)
Sets the polarization analyzer characteristics of the detector.
Interface for one-dimensional axes.
Definition: IAxis.h:25
virtual IAxis * clone() const =0
clone function
Interface for polymorphic classes that should not be copied, except by explicit cloning.
Definition: ICloneable.h:25
Interface for detector resolution algorithms.
virtual IDetectorResolution * clone() const =0
Abstract detector interface.
Definition: IDetector.h:36
void setDataToDetectorMap(OutputData< double > &detectorMap, const std::vector< SimulationElement > &elements) const
Definition: IDetector.cpp:175
void applyDetectorResolution(OutputData< double > *p_intensity_map) const
Applies the detector resolution to the given intensity maps.
Definition: IDetector.cpp:118
virtual std::string axisName(size_t index) const =0
Returns the name for the axis with given index.
virtual ~IDetector()
virtual const DetectorMask * detectorMask() const =0
Returns detector masks container.
void clear()
Definition: IDetector.cpp:51
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
virtual std::unique_ptr< IAxis > createAxis(size_t index, size_t n_bins, double min, double max) const
Generates an axis with correct name and default binning for given index.
Definition: IDetector.cpp:78
std::vector< const INode * > getChildren() const override
Returns a vector of children.
Definition: IDetector.cpp:192
size_t totalSize() const
Returns total number of pixels.
Definition: IDetector.cpp:88
size_t numberOfSimulationElements() const
Returns number of simulation elements.
Definition: IDetector.cpp:185
std::unique_ptr< IDetectorResolution > m_detector_resolution
Definition: IDetector.h:116
const IAxis & axis(size_t index) const
Definition: IDetector.cpp:56
void setResolutionFunction(const IResolutionFunction2D &resFunc)
Definition: IDetector.cpp:112
DetectionProperties m_detection_properties
Definition: IDetector.h:115
CloneableVector< IAxis > m_axes
Definition: IDetector.h:114
void setAnalyzerProperties(const kvector_t direction, double efficiency, double total_transmission)
Sets the polarization analyzer characteristics of the detector.
Definition: IDetector.cpp:99
void addAxis(const IAxis &axis)
Definition: IDetector.cpp:41
OutputData< double > * createDetectorIntensity(const std::vector< SimulationElement > &elements) const
Returns new intensity map with detector resolution applied.
Definition: IDetector.cpp:144
void setDetectorResolution(const IDetectorResolution &p_detector_resolution)
Sets the detector resolution.
Definition: IDetector.cpp:105
std::unique_ptr< OutputData< double > > createDetectorMap() const
Returns empty detector map in given axes units.
Definition: IDetector.cpp:158
void iterate(std::function< void(const_iterator)> func, bool visit_masks=false) const
Definition: IDetector.cpp:197
const IDetectorResolution * detectorResolution() const
Returns a pointer to detector resolution object.
Definition: IDetector.cpp:138
virtual const RegionOfInterest * regionOfInterest() const =0
Returns region of interest if exists.
Base class for tree-like structures containing parameterized objects.
Definition: INode.h:49
void registerChild(INode *node)
Definition: INode.cpp:57
const std::string & getName() const
void setName(const std::string &name)
Interface providing two-dimensional resolution function.
void setRawDataVector(const std::vector< T > &data_vector)
Sets new values to raw data vector.
Definition: OutputData.h:556
An iterator for SimulationArea.
Holds iteration logic over active detector channels in the presence of masked areas and RegionOfInter...
SimulationAreaIterator begin()
SimulationAreaIterator end()
Holds iteration logic over active detector channels in the presence of ROI.