BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
ConvolutionDetectorResolution Class Reference

Description

Convolutes the intensity in 1 or 2 dimensions with a resolution function.

Limitation: this class assumes that the data points are evenly distributed on each axis

Definition at line 31 of file ConvolutionDetectorResolution.h.

Inheritance diagram for ConvolutionDetectorResolution:
[legend]
Collaboration diagram for ConvolutionDetectorResolution:
[legend]

Public Types

using cumulative_DF_1d = double(*)(double)
 

Public Member Functions

 ConvolutionDetectorResolution (const IResolutionFunction2D &p_res_function_2d)
 Constructor taking a 2 dimensional resolution function as argument. More...
 
 ConvolutionDetectorResolution (cumulative_DF_1d res_function_1d)
 Constructor taking a 1 dimensional resolution function as argument. More...
 
 ~ConvolutionDetectorResolution () override
 
void applyDetectorResolution (Datafield *p_intensity_map) const override
 Convolve given intensities with the encapsulated resolution. More...
 
void checkNodeArgs () const
 Raises exception if a parameter value is invalid. More...
 
std::string className () const final
 Returns the class name, to be hard-coded in each leaf class that inherits from INode. More...
 
ConvolutionDetectorResolutionclone () const override
 
const IResolutionFunction2DgetResolutionFunction2D () const
 
std::vector< const INode * > nodeChildren () const override
 Returns all children. More...
 
std::vector< const INode * > nodeOffspring () const
 Returns all descendants. More...
 
virtual std::vector< ParaMetaparDefs () const
 Returns the parameter definitions, to be hard-coded in each leaf class. More...
 
virtual void transferToCPP ()
 Used for Python overriding of clone (see swig/tweaks.py) More...
 

Protected Member Functions

 ConvolutionDetectorResolution (const ConvolutionDetectorResolution &other)
 

Protected Attributes

std::vector< double > m_P
 

Private Member Functions

void apply1dConvolution (Datafield *p_intensity_map) const
 
void apply2dConvolution (Datafield *p_intensity_map) const
 
double getIntegratedPDF1d (double x, double step) const
 
double getIntegratedPDF2d (double x, double step_x, double y, double step_y) const
 
void setResolutionFunction (const IResolutionFunction2D &resFunc)
 

Private Attributes

size_t m_rank
 
cumulative_DF_1d m_res_function_1d
 
std::unique_ptr< IResolutionFunction2Dm_res_function_2d
 

Member Typedef Documentation

◆ cumulative_DF_1d

Definition at line 33 of file ConvolutionDetectorResolution.h.

Constructor & Destructor Documentation

◆ ConvolutionDetectorResolution() [1/3]

ConvolutionDetectorResolution::ConvolutionDetectorResolution ( cumulative_DF_1d  res_function_1d)

Constructor taking a 1 dimensional resolution function as argument.

Definition at line 22 of file ConvolutionDetectorResolution.cpp.

23  : m_rank(1)
24  , m_res_function_1d(res_function_1d)
25 {
26 }

Referenced by clone().

◆ ConvolutionDetectorResolution() [2/3]

ConvolutionDetectorResolution::ConvolutionDetectorResolution ( const IResolutionFunction2D p_res_function_2d)

Constructor taking a 2 dimensional resolution function as argument.

Definition at line 28 of file ConvolutionDetectorResolution.cpp.

30  : m_rank(2)
31  , m_res_function_1d(nullptr)
32 {
33  setResolutionFunction(p_res_function_2d);
34 }
void setResolutionFunction(const IResolutionFunction2D &resFunc)

References setResolutionFunction().

Here is the call graph for this function:

◆ ~ConvolutionDetectorResolution()

ConvolutionDetectorResolution::~ConvolutionDetectorResolution ( )
overridedefault

◆ ConvolutionDetectorResolution() [3/3]

ConvolutionDetectorResolution::ConvolutionDetectorResolution ( const ConvolutionDetectorResolution other)
protected

Definition at line 38 of file ConvolutionDetectorResolution.cpp.

40 {
41  m_rank = other.m_rank;
43  if (other.m_res_function_2d)
45 }
std::unique_ptr< IResolutionFunction2D > m_res_function_2d

References m_rank, m_res_function_1d, m_res_function_2d, and setResolutionFunction().

Here is the call graph for this function:

Member Function Documentation

◆ apply1dConvolution()

void ConvolutionDetectorResolution::apply1dConvolution ( Datafield p_intensity_map) const
private

Definition at line 83 of file ConvolutionDetectorResolution.cpp.

84 {
85  ASSERT(m_res_function_1d == nullptr);
86  if (p_intensity_map->rank() != 1)
87  throw std::runtime_error(
88  "ConvolutionDetectorResolution::apply1dConvolution() -> Error! "
89  "Number of axes for intensity map does not correspond to the dimension of the map.");
90  const IAxis& axis = p_intensity_map->axis(0);
91  // Construct source vector from original intensity map
92  std::vector<double> source_vector = p_intensity_map->flatVector();
93  size_t data_size = source_vector.size();
94  if (data_size < 2)
95  return; // No convolution for sets of zero or one element
96  // Construct kernel vector from resolution function
97  if (axis.size() != data_size)
98  throw std::runtime_error(
99  "ConvolutionDetectorResolution::apply1dConvolution() -> Error! "
100  "Size of axis for intensity map does not correspond to size of data in the map.");
101  double step_size = std::abs(axis[0] - axis[axis.size() - 1]) / (data_size - 1);
102  double mid_value = axis[axis.size() / 2]; // because Convolve expects zero at midpoint
103  std::vector<double> kernel;
104  for (size_t index = 0; index < data_size; ++index)
105  kernel.push_back(getIntegratedPDF1d(axis[index] - mid_value, step_size));
106  // Calculate convolution
107  std::vector<double> result;
108  Convolve().fftconvolve(source_vector, kernel, result);
109  // Truncate negative values that can arise because of finite precision of Fourier Transform
110  for (double& e : result)
111  e = std::max(0.0, e);
112  // Populate intensity map with results
113  p_intensity_map->setVector(result);
114 }
#define ASSERT(condition)
Definition: Assert.h:45
double getIntegratedPDF1d(double x, double step) const
Convolution of two real vectors (in 1D or 2D) using Fast Fourier Transform.
Definition: Convolve.h:36
void fftconvolve(const double1d_t &source, const double1d_t &kernel, double1d_t &result)
convolution in 1D
Definition: Convolve.cpp:115
const IAxis & axis(size_t k) const
Definition: Datafield.cpp:91
void setVector(const std::vector< double > &data_vector)
Sets new values to raw data vector.
Definition: Datafield.cpp:69
std::vector< double > flatVector() const
Returns copy of raw data vector.
Definition: Datafield.cpp:119
size_t rank() const
Definition: Datafield.cpp:75
Abstract base class for one-dimensional axes.
Definition: IAxis.h:27
virtual size_t size() const =0
Returns the number of bins.

References ASSERT, Datafield::axis(), Convolve::fftconvolve(), Datafield::flatVector(), getIntegratedPDF1d(), m_res_function_1d, Datafield::rank(), Datafield::setVector(), and IAxis::size().

Referenced by applyDetectorResolution().

Here is the call graph for this function:

◆ apply2dConvolution()

void ConvolutionDetectorResolution::apply2dConvolution ( Datafield p_intensity_map) const
private

Definition at line 116 of file ConvolutionDetectorResolution.cpp.

117 {
119  if (p_intensity_map->rank() != 2)
120  throw std::runtime_error(
121  "ConvolutionDetectorResolution::apply2dConvolution() -> Error! "
122  "Number of axes for intensity map does not correspond to the dimension of the map.");
123  const IAxis& axis_1 = p_intensity_map->axis(0);
124  const IAxis& axis_2 = p_intensity_map->axis(1);
125  size_t axis_size_1 = axis_1.size();
126  size_t axis_size_2 = axis_2.size();
127  if (axis_size_1 < 2 || axis_size_2 < 2)
128  return; // No 2d convolution for 1d data
129  // Construct source vector array from original intensity map
130  std::vector<double> raw_source_vector = p_intensity_map->flatVector();
131  std::vector<std::vector<double>> source;
132  size_t raw_data_size = raw_source_vector.size();
133  if (raw_data_size != axis_size_1 * axis_size_2)
134  throw std::runtime_error(
135  "ConvolutionDetectorResolution::apply2dConvolution() -> Error! "
136  "Intensity map data size does not match the product of its axes' sizes");
137  for (auto it = raw_source_vector.begin(); it != raw_source_vector.end(); it += axis_size_2) {
138  std::vector<double> row_vector(it, it + axis_size_2);
139  source.push_back(row_vector);
140  }
141  // Construct kernel vector from resolution function
142  std::vector<std::vector<double>> kernel;
143  kernel.resize(axis_size_1);
144  double mid_value_1 = axis_1[axis_size_1 / 2]; // because Convolve expects zero at midpoint
145  double mid_value_2 = axis_2[axis_size_2 / 2]; // because Convolve expects zero at midpoint
146  double step_size_1 = std::abs(axis_1[0] - axis_1[axis_size_1 - 1]) / (axis_size_1 - 1);
147  double step_size_2 = std::abs(axis_2[0] - axis_2[axis_size_2 - 1]) / (axis_size_2 - 1);
148  for (size_t index_1 = 0; index_1 < axis_size_1; ++index_1) {
149  double value_1 = axis_1[index_1] - mid_value_1;
150  std::vector<double> row_vector;
151  row_vector.resize(axis_size_2, 0.0);
152  for (size_t index_2 = 0; index_2 < axis_size_2; ++index_2) {
153  double value_2 = axis_2[index_2] - mid_value_2;
154  double z_value = getIntegratedPDF2d(value_1, step_size_1, value_2, step_size_2);
155  row_vector[index_2] = z_value;
156  }
157  kernel[index_1] = row_vector;
158  }
159  // Calculate convolution
160  std::vector<std::vector<double>> result;
161  Convolve().fftconvolve(source, kernel, result);
162  // Populate intensity map with results
163  std::vector<double> result_vector;
164  for (size_t index_1 = 0; index_1 < axis_size_1; ++index_1) {
165  for (size_t index_2 = 0; index_2 < axis_size_2; ++index_2) {
166  double value = result[index_1][index_2];
167  result_vector.push_back(value);
168  }
169  }
170  ASSERT(axis_size_1 * axis_size_2 == p_intensity_map->size());
171  for (size_t i = 0; i < p_intensity_map->size(); ++i) {
172  size_t i0 = p_intensity_map->frame().projectedIndex(i, 0);
173  size_t i1 = p_intensity_map->frame().projectedIndex(i, 1);
174  (*p_intensity_map)[i] = std::max(0.0, result[i0][i1]);
175  }
176 }
double getIntegratedPDF2d(double x, double step_x, double y, double step_y) const
size_t size() const
Returns total size of data buffer (product of bin number in every dimension).
Definition: Datafield.cpp:80
const Frame & frame() const
Definition: Datafield.cpp:86
size_t projectedIndex(size_t i_flat, size_t k_axis) const
Returns axis bin index for given global index.
Definition: Frame.cpp:56

References ASSERT, Datafield::axis(), Convolve::fftconvolve(), Datafield::flatVector(), Datafield::frame(), getIntegratedPDF2d(), m_res_function_2d, Frame::projectedIndex(), Datafield::rank(), Datafield::size(), and IAxis::size().

Referenced by applyDetectorResolution().

Here is the call graph for this function:

◆ applyDetectorResolution()

void ConvolutionDetectorResolution::applyDetectorResolution ( Datafield p_intensity_map) const
overridevirtual

Convolve given intensities with the encapsulated resolution.

Implements IDetectorResolution.

Definition at line 57 of file ConvolutionDetectorResolution.cpp.

58 {
59  if (p_intensity_map->rank() != m_rank) {
60  throw std::runtime_error(
61  "ConvolutionDetectorResolution::applyDetectorResolution() -> Error! "
62  "Intensity map must have same dimension as detector resolution function.");
63  }
64  switch (m_rank) {
65  case 1:
66  apply1dConvolution(p_intensity_map);
67  break;
68  case 2:
69  apply2dConvolution(p_intensity_map);
70  break;
71  default:
72  throw std::runtime_error(
73  "ConvolutionDetectorResolution::applyDetectorResolution() -> Error! "
74  "Class ConvolutionDetectorResolution must be initialized with dimension 1 or 2.");
75  }
76 }
void apply1dConvolution(Datafield *p_intensity_map) const
void apply2dConvolution(Datafield *p_intensity_map) const

References apply1dConvolution(), apply2dConvolution(), m_rank, and Datafield::rank().

Here is the call graph for this function:

◆ checkNodeArgs()

void INode::checkNodeArgs ( ) const
inherited

Raises exception if a parameter value is invalid.

Definition at line 27 of file INode.cpp.

28 {
29  size_t nP = m_P.size();
30  if (parDefs().size() != nP) {
31  std::cerr << "BUG in class " << className() << std::endl;
32  std::cerr << "#m_P = " << nP << std::endl;
33  std::cerr << "#PDf = " << parDefs().size() << std::endl;
34  for (const ParaMeta& pm : parDefs())
35  std::cerr << " PDf: " << pm.name << std::endl;
36  ASSERT(0);
37  }
38  ASSERT(parDefs().size() == nP);
39  for (size_t i = 0; i < nP; ++i) {
40  const ParaMeta pm = parDefs()[i];
41 
43  if (pm.vMin == -INF) {
44  ASSERT(pm.vMax == +INF);
45  // nothing to do
46  } else if (pm.vMax == +INF) {
47  ASSERT(pm.vMin == 0);
48  limits = RealLimits::nonnegative();
49  } else {
50  limits = RealLimits::limited(pm.vMin, pm.vMax);
51  }
52  limits.check(pm.name, m_P[i]);
53  }
54 }
const double INF
Definition: INode.h:26
virtual std::vector< ParaMeta > parDefs() const
Returns the parameter definitions, to be hard-coded in each leaf class.
Definition: INode.h:51
std::vector< double > m_P
Definition: INode.h:63
virtual std::string className() const =0
Returns the class name, to be hard-coded in each leaf class that inherits from INode.
Limits for a real fit parameter.
Definition: RealLimits.h:24
static RealLimits limitless()
Creates an object without bounds (default)
Definition: RealLimits.cpp:139
void check(const std::string &name, double value) const
Throws if value is outside limits. Parameter 'name' is for exception message.
Definition: RealLimits.cpp:170
static RealLimits nonnegative()
Creates an object which can have only positive values with 0. included.
Definition: RealLimits.cpp:124
static RealLimits limited(double left_bound_value, double right_bound_value)
Creates an object bounded from the left and right.
Definition: RealLimits.cpp:134
Metadata of one model parameter.
Definition: INode.h:29
double vMin
Definition: INode.h:33
double vMax
Definition: INode.h:34
std::string name
Definition: INode.h:30

References ASSERT, RealLimits::check(), INode::className(), INF, RealLimits::limited(), RealLimits::limitless(), INode::m_P, ParaMeta::name, RealLimits::nonnegative(), INode::parDefs(), ParaMeta::vMax, and ParaMeta::vMin.

Referenced by BarGauss::BarGauss(), BarLorentz::BarLorentz(), Bipyramid4::Bipyramid4(), Box::Box(), CantellatedCube::CantellatedCube(), Cone::Cone(), ConstantBackground::ConstantBackground(), CosineRippleBox::CosineRippleBox(), CosineRippleGauss::CosineRippleGauss(), CosineRippleLorentz::CosineRippleLorentz(), Cylinder::Cylinder(), DistributionCosine::DistributionCosine(), DistributionGate::DistributionGate(), DistributionGaussian::DistributionGaussian(), DistributionLogNormal::DistributionLogNormal(), DistributionLorentz::DistributionLorentz(), DistributionTrapezoid::DistributionTrapezoid(), Dodecahedron::Dodecahedron(), EllipsoidalCylinder::EllipsoidalCylinder(), FootprintGauss::FootprintGauss(), FootprintSquare::FootprintSquare(), FuzzySphere::FuzzySphere(), GaussSphere::GaussSphere(), HemiEllipsoid::HemiEllipsoid(), HollowSphere::HollowSphere(), HorizontalCylinder::HorizontalCylinder(), Icosahedron::Icosahedron(), LongBoxGauss::LongBoxGauss(), LongBoxLorentz::LongBoxLorentz(), PlatonicOctahedron::PlatonicOctahedron(), PlatonicTetrahedron::PlatonicTetrahedron(), Prism3::Prism3(), Prism6::Prism6(), Profile1DCauchy::Profile1DCauchy(), Profile1DCosine::Profile1DCosine(), Profile1DGate::Profile1DGate(), Profile1DGauss::Profile1DGauss(), Profile1DTriangle::Profile1DTriangle(), Profile1DVoigt::Profile1DVoigt(), Profile2DCauchy::Profile2DCauchy(), Profile2DCone::Profile2DCone(), Profile2DGate::Profile2DGate(), Profile2DGauss::Profile2DGauss(), Profile2DVoigt::Profile2DVoigt(), Pyramid2::Pyramid2(), Pyramid3::Pyramid3(), Pyramid4::Pyramid4(), Pyramid6::Pyramid6(), RotationEuler::RotationEuler(), RotationX::RotationX(), RotationY::RotationY(), RotationZ::RotationZ(), SawtoothRippleBox::SawtoothRippleBox(), SawtoothRippleGauss::SawtoothRippleGauss(), SawtoothRippleLorentz::SawtoothRippleLorentz(), Sphere::Sphere(), Spheroid::Spheroid(), TruncatedCube::TruncatedCube(), TruncatedSphere::TruncatedSphere(), and TruncatedSpheroid::TruncatedSpheroid().

Here is the call graph for this function:

◆ className()

std::string ConvolutionDetectorResolution::className ( ) const
inlinefinalvirtual

Returns the class name, to be hard-coded in each leaf class that inherits from INode.

Implements INode.

Definition at line 44 of file ConvolutionDetectorResolution.h.

44 { return "ConvolutionDetectorResolution"; }

◆ clone()

ConvolutionDetectorResolution * ConvolutionDetectorResolution::clone ( ) const
overridevirtual

Implements IDetectorResolution.

Definition at line 47 of file ConvolutionDetectorResolution.cpp.

48 {
49  return new ConvolutionDetectorResolution(*this);
50 }
ConvolutionDetectorResolution(cumulative_DF_1d res_function_1d)
Constructor taking a 1 dimensional resolution function as argument.

References ConvolutionDetectorResolution().

Here is the call graph for this function:

◆ getIntegratedPDF1d()

double ConvolutionDetectorResolution::getIntegratedPDF1d ( double  x,
double  step 
) const
private

Definition at line 178 of file ConvolutionDetectorResolution.cpp.

179 {
180  double halfstep = step / 2.0;
181  double xmin = x - halfstep;
182  double xmax = x + halfstep;
183  ASSERT(m_res_function_1d != nullptr);
184  return m_res_function_1d(xmax) - m_res_function_1d(xmin);
185 }

References ASSERT, and m_res_function_1d.

Referenced by apply1dConvolution().

◆ getIntegratedPDF2d()

double ConvolutionDetectorResolution::getIntegratedPDF2d ( double  x,
double  step_x,
double  y,
double  step_y 
) const
private

Definition at line 187 of file ConvolutionDetectorResolution.cpp.

189 {
190  double halfstepx = step_x / 2.0;
191  double halfstepy = step_y / 2.0;
192  double xmin = x - halfstepx;
193  double xmax = x + halfstepx;
194  double ymin = y - halfstepy;
195  double ymax = y + halfstepy;
196  double result =
197  m_res_function_2d->evaluateCDF(xmax, ymax) - m_res_function_2d->evaluateCDF(xmax, ymin)
198  - m_res_function_2d->evaluateCDF(xmin, ymax) + m_res_function_2d->evaluateCDF(xmin, ymin);
199  return result;
200 }

References m_res_function_2d.

Referenced by apply2dConvolution().

◆ getResolutionFunction2D()

const IResolutionFunction2D * ConvolutionDetectorResolution::getResolutionFunction2D ( ) const
inline

Definition at line 68 of file ConvolutionDetectorResolution.h.

69 {
70  return m_res_function_2d.get();
71 }

References m_res_function_2d.

◆ nodeChildren()

std::vector< const INode * > ConvolutionDetectorResolution::nodeChildren ( ) const
overridevirtual

Returns all children.

Reimplemented from INode.

Definition at line 52 of file ConvolutionDetectorResolution.cpp.

53 {
54  return std::vector<const INode*>() << m_res_function_2d;
55 }

References m_res_function_2d.

◆ nodeOffspring()

std::vector< const INode * > INode::nodeOffspring ( ) const
inherited

Returns all descendants.

Definition at line 61 of file INode.cpp.

62 {
63  std::vector<const INode*> result;
64  result.push_back(this);
65  for (const auto* child : nodeChildren()) {
66  for (const auto* p : child->nodeOffspring())
67  result.push_back(p);
68  }
69  return result;
70 }
virtual std::vector< const INode * > nodeChildren() const
Returns all children.
Definition: INode.cpp:56

References INode::nodeChildren().

Here is the call graph for this function:

◆ parDefs()

virtual std::vector<ParaMeta> INode::parDefs ( ) const
inlinevirtualinherited

Returns the parameter definitions, to be hard-coded in each leaf class.

Reimplemented in ConstantBackground, GaussSphere, FuzzySphere, RotationEuler, RotationZ, RotationY, RotationX, Crystal, Layer, HexagonalLattice2D, SquareLattice2D, BasicLattice2D, LayerRoughness, TruncatedSpheroid, TruncatedSphere, TruncatedCube, Spheroid, Sphere, SawtoothRippleLorentz, SawtoothRippleGauss, SawtoothRippleBox, Pyramid6, Pyramid4, Pyramid3, Pyramid2, Prism6, Prism3, PlatonicTetrahedron, PlatonicOctahedron, LongBoxLorentz, LongBoxGauss, Icosahedron, HorizontalCylinder, HollowSphere, HemiEllipsoid, EllipsoidalCylinder, Dodecahedron, Cylinder, CosineRippleLorentz, CosineRippleGauss, CosineRippleBox, Cone, CantellatedCube, Box, Bipyramid4, BarLorentz, BarGauss, Profile2DVoigt, Profile2DCone, Profile2DGate, Profile2DGauss, Profile2DCauchy, Profile1DVoigt, Profile1DCosine, Profile1DTriangle, Profile1DGate, Profile1DGauss, Profile1DCauchy, MisesGaussPeakShape, MisesFisherGaussPeakShape, LorentzFisherPeakShape, GaussFisherPeakShape, IsotropicLorentzPeakShape, IsotropicGaussPeakShape, ParticleLayout, InterferenceTwin, InterferenceRadialParaCrystal, InterferenceHardDisk, Interference2DSuperLattice, Interference2DParaCrystal, Interference1DLattice, DistributionTrapezoid, DistributionCosine, DistributionLogNormal, DistributionGaussian, DistributionLorentz, DistributionGate, ResolutionFunction2DGaussian, PolFilter, FootprintSquare, and FootprintGauss.

Definition at line 51 of file INode.h.

51 { return {}; }

Referenced by INode::checkNodeArgs(), and IFormFactor::pythonConstructor().

◆ setResolutionFunction()

void ConvolutionDetectorResolution::setResolutionFunction ( const IResolutionFunction2D resFunc)
private

Definition at line 78 of file ConvolutionDetectorResolution.cpp.

79 {
80  m_res_function_2d.reset(resFunc.clone());
81 }
IResolutionFunction2D * clone() const override=0

References IResolutionFunction2D::clone(), and m_res_function_2d.

Referenced by ConvolutionDetectorResolution().

Here is the call graph for this function:

◆ transferToCPP()

virtual void ICloneable::transferToCPP ( )
inlinevirtualinherited

Used for Python overriding of clone (see swig/tweaks.py)

Definition at line 32 of file ICloneable.h.

Member Data Documentation

◆ m_P

◆ m_rank

size_t ConvolutionDetectorResolution::m_rank
private

◆ m_res_function_1d

cumulative_DF_1d ConvolutionDetectorResolution::m_res_function_1d
private

◆ m_res_function_2d

std::unique_ptr<IResolutionFunction2D> ConvolutionDetectorResolution::m_res_function_2d
private

The documentation for this class was generated from the following files: