BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
DistributionItems.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/Model/Descriptor/DistributionItems.cpp
6 //! @brief Implements class DistributionItem and several subclasses
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2022
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
19 #include "Param/Distrib/Distributions.h"
20 #include "Param/Distrib/RangedDistributions.h"
21 #include <cmath>
22 
24 {
25  m_numberOfSamples.init("Number of samples", "", 5, "", RealLimits::lowerLimited(1.0),
26  "nSamples");
27 }
28 
29 void DistributionItem::setLimits(const RealLimits& limits)
30 {
31  m_limits = limits;
32 }
33 
35 {
36  m_sigmaFactor.init("Sigma factor", "", 2.0, Unit::unitless, "sigmaFactor");
37  addToSerialization(&m_sigmaFactor);
38 }
39 
41 {
43 }
44 
46 {
47  return m_sigmaFactor.isInitialized();
48 }
49 
51 {
52  s.assertVersion(0);
53  Serialize::rwProperty(s, m_numberOfSamples);
54 
55  for (auto* p : m_serializationProperties)
56  Serialize::rwProperty(s, *p);
57 
58  // m_limits and a changed unit (with setUnit) will not be serialized here. They have to be set
59  // again by the owner of DistributionItem after reading it
60 }
61 
62 RealLimits DistributionItem::limits() const
63 {
64  return m_limits;
65 }
66 
67 // --------------------------------------------------------------------------------------------- //
68 
70  const QString& meanLabel)
71 {
72  m_mean.init(meanLabel, "", mean, Unit::unitless, decimals, RealLimits::limitless(), "mean");
73  addToSerialization(&m_mean);
74 }
75 
76 void SymmetricResolutionItem::setUnit(const variant<QString, Unit>& unit)
77 {
78  m_mean.setUnit(unit);
79 }
80 
81 void SymmetricResolutionItem::setLimits(const RealLimits& limits)
82 {
84  m_mean.setLimits(limits);
85 }
86 
88 {
89  m_mean.setDecimals(d);
90 }
91 
92 // --------------------------------------------------------------------------------------------- //
93 
95  : SymmetricResolutionItem(0.1, 3, "Value")
96 {
97 }
98 
99 std::unique_ptr<IDistribution1D> DistributionNoneItem::createDistribution(double) const
100 {
101  return nullptr;
102 }
103 
104 std::unique_ptr<IRangedDistribution> DistributionNoneItem::createIRangedDistribution(double) const
105 {
106  return nullptr;
107 }
108 
110 {
111  return 0.0;
112 }
113 
115 {
116  setMean(value);
117 }
118 
120 {
121  return withMean ? DoubleDescriptors{mean()} : DoubleDescriptors{};
122 }
123 
124 // --------------------------------------------------------------------------------------------- //
125 
127 {
128  m_minimum.init("Min", "", 0.0, Unit::unitless, 3, RealLimits::limitless(), "min");
129  m_maximum.init("Max", "", 1.0, Unit::unitless, 3, RealLimits::limitless(), "max");
130 
131  addToSerialization(&m_minimum);
132  addToSerialization(&m_maximum);
133 }
134 
135 void DistributionGateItem::setUnit(const variant<QString, Unit>& unit)
136 {
137  m_minimum.setUnit(unit);
138  m_maximum.setUnit(unit);
139 }
140 
141 std::unique_ptr<IDistribution1D> DistributionGateItem::createDistribution(double scale) const
142 {
143  return std::make_unique<DistributionGate>(scale * m_minimum, scale * m_maximum);
144 }
145 
147 {
148  double sigma(0.1 * std::abs(value));
149  if (sigma == 0.0)
150  sigma = 0.1;
151  m_minimum.set(value - sigma);
152  m_maximum.set(value + sigma);
153 }
154 
155 void DistributionGateItem::setRange(double min, double max)
156 {
157  m_minimum.set(min);
158  m_maximum.set(max);
159 }
160 
162 {
163  return {minimum(), maximum()};
164 }
165 
166 // --------------------------------------------------------------------------------------------- //
167 
170 {
171  initSigmaFactor();
172 
173  m_hwhm.init("HWHM", "", 1.0, Unit::unitless, "hwhm");
174  addToSerialization(&m_hwhm);
175 }
176 
177 void DistributionLorentzItem::setUnit(const variant<QString, Unit>& unit)
178 {
180  m_hwhm.setUnit(unit);
181 }
182 
183 std::unique_ptr<IDistribution1D> DistributionLorentzItem::createDistribution(double scale) const
184 {
185  return std::make_unique<DistributionLorentz>(scale * m_mean, scale * m_hwhm);
186 }
187 
188 std::unique_ptr<IRangedDistribution>
190 {
191  return std::make_unique<RangedDistributionLorentz>(numberOfSamples(), sigmaFactor(),
192  m_limits.scaledLimits(scale));
193 }
194 
195 double DistributionLorentzItem::deviation(double scale) const
196 {
197  return m_hwhm * scale;
198 }
199 
201 {
202  double hw(0.1 * std::abs(value));
203  if (hw == 0.0)
204  hw = 0.1;
205 
206  setMean(value);
207  setHwhm(hw);
208  m_hwhm.setLimits(RealLimits::lowerLimited(0.0));
209 }
210 
212 {
213  return withMean ? DoubleDescriptors{mean(), hwhm(), sigmaFactor()}
214  : DoubleDescriptors{hwhm(), sigmaFactor()};
215 }
216 
217 // --------------------------------------------------------------------------------------------- //
218 
221 {
222  initSigmaFactor();
223 
224  m_standardDeviation.init("StdDev", "", 1.0, Unit::unitless, 3, RealLimits::lowerLimited(0.0),
225  "stdDev");
226  addToSerialization(&m_standardDeviation);
227 }
228 
229 void DistributionGaussianItem::setUnit(const variant<QString, Unit>& unit)
230 {
232  m_standardDeviation.setUnit(unit);
233 }
234 
235 std::unique_ptr<IDistribution1D> DistributionGaussianItem::createDistribution(double scale) const
236 {
237  return std::make_unique<DistributionGaussian>(scale * m_mean, scale * m_standardDeviation);
238 }
239 
240 std::unique_ptr<IRangedDistribution>
242 {
243  return std::make_unique<RangedDistributionGaussian>(numberOfSamples(), sigmaFactor(),
244  m_limits.scaledLimits(scale));
245 }
246 
247 double DistributionGaussianItem::deviation(double scale) const
248 {
249  return standardDeviation() * scale;
250 }
251 
253 {
254  double stddev(0.1 * std::abs(value));
255  if (stddev == 0.0)
256  stddev = 0.1;
257 
258  setMean(value);
259  setStandardDeviation(stddev);
260 }
261 
263 {
264  return withMean ? DoubleDescriptors{mean(), standardDeviation(), sigmaFactor()}
265  : DoubleDescriptors{standardDeviation(), sigmaFactor()};
266 }
267 
268 // --------------------------------------------------------------------------------------------- //
269 
271 {
272  initSigmaFactor();
273 
274  m_median.init("Median", "", 1.0, Unit::unitless, "median");
275  m_scaleParameter.init("ScaleParameter", "", 1.0, Unit::unitless, 3,
276  RealLimits::lowerLimited(0.0), "scalePar");
277 
278  addToSerialization(&m_median);
279  addToSerialization(&m_scaleParameter);
280 }
281 
282 void DistributionLogNormalItem::setUnit(const variant<QString, Unit>& unit)
283 {
284  m_median.setUnit(unit);
285 }
286 
287 std::unique_ptr<IDistribution1D> DistributionLogNormalItem::createDistribution(double scale) const
288 {
289  return std::make_unique<DistributionLogNormal>(scale * median(), scaleParameter());
290 }
291 
293 {
294  double scale(0.1 * std::abs(value));
295  if (scale == 0.0)
296  scale = 0.1;
297 
298  setMedian(value);
299  setScaleParameter(scale);
300 }
301 
303 {
304  return {median(), scaleParameter(), sigmaFactor()};
305 }
306 
307 // --------------------------------------------------------------------------------------------- //
308 
311 {
312  initSigmaFactor();
313  m_sigma.init("Sigma", "", 1.0, Unit::unitless, 3, RealLimits::lowerLimited(0.0), "sigma");
314  addToSerialization(&m_sigma);
315 }
316 
317 void DistributionCosineItem::setUnit(const variant<QString, Unit>& unit)
318 {
320  m_sigma.setUnit(unit);
321 }
322 
323 std::unique_ptr<IDistribution1D> DistributionCosineItem::createDistribution(double scale) const
324 {
325  return std::make_unique<DistributionCosine>(scale * m_mean, scale * sigma());
326 }
327 
328 std::unique_ptr<IRangedDistribution>
330 {
331  return std::make_unique<RangedDistributionCosine>(numberOfSamples(), sigmaFactor(),
332  m_limits.scaledLimits(scale));
333 }
334 
335 double DistributionCosineItem::deviation(double scale) const
336 {
337  return sigma() * scale;
338 }
339 
341 {
342  double sigma(0.1 * std::abs(value));
343  if (sigma == 0.0)
344  sigma = 0.1;
345 
346  setMean(value);
347  setSigma(sigma);
348 }
349 
351 {
352  return withMean ? DoubleDescriptors{mean(), sigma(), sigmaFactor()}
353  : DoubleDescriptors{sigma(), sigmaFactor()};
354  ;
355 }
356 
357 // --------------------------------------------------------------------------------------------- //
358 
360 {
361  m_center.init("Center", "", 1.0, Unit::unitless, 3, RealLimits::limitless(), "center");
362  m_leftWidth.init("LeftWidth", "", 1.0, Unit::unitless, "left");
363  m_middleWidth.init("MiddleWidth", "", 1.0, Unit::unitless, "middle");
364  m_rightWidth.init("RightWidth", "", 1.0, Unit::unitless, "right");
365 
366  addToSerialization(&m_center);
367  addToSerialization(&m_leftWidth);
368  addToSerialization(&m_middleWidth);
369  addToSerialization(&m_rightWidth);
370 }
371 
372 void DistributionTrapezoidItem::setUnit(const variant<QString, Unit>& unit)
373 {
374  m_center.setUnit(unit);
375  m_leftWidth.setUnit(unit);
376  m_middleWidth.setUnit(unit);
377  m_rightWidth.setUnit(unit);
378 }
379 
380 std::unique_ptr<IDistribution1D> DistributionTrapezoidItem::createDistribution(double scale) const
381 {
382  return std::make_unique<DistributionTrapezoid>(scale * center(), scale * leftWidth(),
383  scale * middleWidth(), scale * rightWidth());
384 }
385 
387 {
388  double width(0.1 * std::abs(value));
389  if (width == 0.0)
390  width = 0.1;
391  setCenter(value);
392  setLeftWidth(width);
393  setMiddleWidth(width);
394  setRightWidth(width);
395 }
396 
398 {
399  return withMean ? DoubleDescriptors{center(), leftWidth(), middleWidth(), rightWidth()}
400  : DoubleDescriptors{leftWidth(), middleWidth(), rightWidth()};
401 }
Defines class DistributionItem and several subclasses.
Defines class DoubleDescriptor.
QList< DoubleDescriptor > DoubleDescriptors
Defines class GroupInfo.
Defines class Streamer.
@ unitless
void setUnit(const variant< QString, Unit > &unit) override
Set the unit of the distributed value.
double deviation(double scale) const override
std::unique_ptr< IRangedDistribution > createIRangedDistribution(double scale) const override
DoubleDescriptors distributionValues(bool withMean=true) const override
void initDistribution(double value) override
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
DoubleDescriptors distributionValues(bool withMean=true) const override
void setRange(double min, double max)
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
void setUnit(const variant< QString, Unit > &unit) override
Set the unit of the distributed value.
void initDistribution(double value) override
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
void initDistribution(double value) override
double deviation(double scale) const override
std::unique_ptr< IRangedDistribution > createIRangedDistribution(double scale) const override
void setUnit(const variant< QString, Unit > &unit) override
Set the unit of the distributed value.
DoubleDescriptors distributionValues(bool withMean=true) const override
void serialize(Streamer &s)
Serialization of contents.
RealLimits limits() const
void addToSerialization(DoubleProperty *d)
bool hasSigmaFactor() const
virtual void setLimits(const RealLimits &limits)
QVector< DoubleProperty * > m_serializationProperties
void initDistribution(double value) override
DoubleDescriptors distributionValues(bool withMean=true) const override
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
void setUnit(const variant< QString, Unit > &unit) override
Set the unit of the distributed value.
void initDistribution(double value) override
double deviation(double scale) const override
DoubleDescriptors distributionValues(bool withMean=true) const override
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
std::unique_ptr< IRangedDistribution > createIRangedDistribution(double scale) const override
void setUnit(const variant< QString, Unit > &unit) override
Set the unit of the distributed value.
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
DoubleDescriptors distributionValues(bool withMean=true) const override
double deviation(double scale) const override
void initDistribution(double value) override
std::unique_ptr< IRangedDistribution > createIRangedDistribution(double scale) const override
void setUnit(const variant< QString, Unit > &unit) override
Set the unit of the distributed value.
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
void initDistribution(double value) override
DoubleDescriptors distributionValues(bool withMean=true) const override
Class for representing a double value, its attributes and its accessors.
Supports serialization to or deserialization from QXmlStream.
Definition: Streamer.h:36
void assertVersion(unsigned expectedVersion) const
As reader, throws DeserializationException unless the expected version is read. As writer,...
Definition: Streamer.cpp:26
void setLimits(const RealLimits &limits) override
void setUnit(const variant< QString, Unit > &unit) override
Set the unit of the distributed value.
SymmetricResolutionItem(double mean, int decimals=3, const QString &meanLabel="Mean")
void rwProperty(Streamer &s, DoubleProperty &d)