BornAgain  1.19.0
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/coregui/Models/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 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
19 #include <cmath>
20 
21 namespace {
22 template <class DistrType>
23 std::unique_ptr<IRangedDistribution>
24 createIRangedDistribution(const SymmetricDistributionItem& distr_item, double scale);
25 }
26 
27 const QString DistributionItem::P_NUMBER_OF_SAMPLES = "Number of samples";
28 const QString DistributionItem::P_SIGMA_FACTOR = "Sigma factor";
29 const QString DistributionItem::P_IS_INITIALIZED = "is initialized";
30 const QString DistributionItem::P_LIMITS = "Limits";
31 
33 {
34  addProperty(P_IS_INITIALIZED, false)->setVisible(false);
35 }
36 
37 //! Provides initialization of the distribution with some reasonable parameters around given value.
38 //! Used by beamDistributionItem to propagate value from DistributionNone to the distribution
39 //! currently selected by GroupItem.
40 
41 void DistributionItem::init_parameters(double value, const RealLimits& limits)
42 {
43  if (getItemValue(P_IS_INITIALIZED).toBool())
44  return;
45 
49 }
50 
51 void DistributionItem::init_limits_group(const RealLimits& limits, double factor)
52 {
53  if (!isTag(P_LIMITS))
54  return;
55  if (limits.isLimitless()) {
56  setGroupProperty(P_LIMITS, "RealLimitsLimitless");
57  } else if (limits.isPositive()) {
58  setGroupProperty(P_LIMITS, "RealLimitsPositive");
59  } else if (limits.isNonnegative()) {
60  setGroupProperty(P_LIMITS, "RealLimitsNonnegative");
61  } else if (limits.isLowerLimited()) {
62  SessionItem* lim = setGroupProperty(P_LIMITS, "RealLimitsLowerLimited");
64  } else if (limits.isUpperLimited()) {
65  SessionItem* lim = setGroupProperty(P_LIMITS, "RealLimitsUpperLimited");
67  } else if (limits.isLimited()) {
68  SessionItem* lim = setGroupProperty(P_LIMITS, "RealLimitsLimited");
71  }
72 }
73 
75 {
77 }
78 
80 {
82 }
83 
85 {
86  addGroupProperty(P_LIMITS, "RealLimits group");
87  setGroupProperty(P_LIMITS, "RealLimitsLimitless");
88 }
89 
90 // --------------------------------------------------------------------------------------------- //
91 
92 const QString SymmetricDistributionItem::P_MEAN = QString::fromStdString("Mean");
93 
95 {
96 }
97 
99 {
100  getItem(P_MEAN)->setVisible(flag);
101 }
102 
103 // --------------------------------------------------------------------------------------------- //
104 
106 {
109 }
110 
111 std::unique_ptr<IDistribution1D> DistributionNoneItem::createDistribution(double scale) const
112 {
113  Q_UNUSED(scale);
114  return nullptr;
115 }
116 
117 std::unique_ptr<IRangedDistribution> DistributionNoneItem::createIRangedDistribution(double) const
118 {
119  return nullptr;
120 }
121 
123 {
124  return 0.0;
125 }
126 
128 {
130 }
131 
132 // --------------------------------------------------------------------------------------------- //
133 
134 const QString DistributionGateItem::P_MIN = QString::fromStdString("Min");
135 const QString DistributionGateItem::P_MAX = QString::fromStdString("Max");
136 
138 {
142  register_limits();
143  getItem(P_LIMITS)->setVisible(false);
144 }
145 
146 std::unique_ptr<IDistribution1D> DistributionGateItem::createDistribution(double scale) const
147 {
148  double min = getItemValue(P_MIN).toDouble();
149  double max = getItemValue(P_MAX).toDouble();
150  return std::make_unique<DistributionGate>(scale * min, scale * max);
151 }
152 
154 {
155  double sigma(0.1 * std::abs(value));
156  if (sigma == 0.0)
157  sigma = 0.1;
158  setItemValue(P_MIN, value - sigma);
159  setItemValue(P_MAX, value + sigma);
160 }
161 
162 // --------------------------------------------------------------------------------------------- //
163 
164 const QString DistributionLorentzItem::P_HWHM = QString::fromStdString("HWHM");
165 
167  : SymmetricDistributionItem("DistributionLorentz")
168 {
170  addProperty(P_HWHM, 1.0);
173  register_limits();
174 }
175 
176 std::unique_ptr<IDistribution1D> DistributionLorentzItem::createDistribution(double scale) const
177 {
178  double mean = getItemValue(P_MEAN).toDouble();
179  double hwhm = getItemValue(P_HWHM).toDouble();
180  return std::make_unique<DistributionLorentz>(scale * mean, scale * hwhm);
181 }
182 
183 std::unique_ptr<IRangedDistribution>
185 {
186  return ::createIRangedDistribution<RangedDistributionLorentz>(*this, scale);
187 }
188 
189 double DistributionLorentzItem::deviation(double scale) const
190 {
191  return getItemValue(P_HWHM).toDouble() * scale;
192 }
193 
195 {
196  double sigma(0.1 * std::abs(value));
197  if (sigma == 0.0)
198  sigma = 0.1;
199 
201  setItemValue(P_HWHM, sigma);
203 }
204 
205 // --------------------------------------------------------------------------------------------- //
206 
207 const QString DistributionGaussianItem::P_STD_DEV = QString::fromStdString("StdDev");
208 
210  : SymmetricDistributionItem("DistributionGaussian")
211 {
213  addProperty(P_STD_DEV, 1.0);
216  register_limits();
217 }
218 
219 std::unique_ptr<IDistribution1D> DistributionGaussianItem::createDistribution(double scale) const
220 {
221  double mean = getItemValue(P_MEAN).toDouble();
222  double std_dev = getItemValue(P_STD_DEV).toDouble();
223  return std::make_unique<DistributionGaussian>(scale * mean, scale * std_dev);
224 }
225 
226 std::unique_ptr<IRangedDistribution>
228 {
229  return ::createIRangedDistribution<RangedDistributionGaussian>(*this, scale);
230 }
231 
232 double DistributionGaussianItem::deviation(double scale) const
233 {
234  return getItemValue(P_STD_DEV).toDouble() * scale;
235 }
236 
238 {
239  double sigma(0.1 * std::abs(value));
240  if (sigma == 0.0)
241  sigma = 0.1;
242 
244  setItemValue(P_STD_DEV, sigma);
246 }
247 
248 // --------------------------------------------------------------------------------------------- //
249 
250 const QString DistributionLogNormalItem::P_MEDIAN = QString::fromStdString("Median");
251 const QString DistributionLogNormalItem::P_SCALE_PAR = QString::fromStdString("ScaleParameter");
252 
254 {
255  addProperty(P_MEDIAN, 1.0);
256  addProperty(P_SCALE_PAR, 1.0);
259  register_limits();
260 }
261 
262 std::unique_ptr<IDistribution1D> DistributionLogNormalItem::createDistribution(double scale) const
263 {
264  double median = getItemValue(P_MEDIAN).toDouble();
265  double scale_par = getItemValue(P_SCALE_PAR).toDouble();
266  return std::make_unique<DistributionLogNormal>(scale * median, scale_par);
267 }
268 
270 {
271  double sigma(0.1 * std::abs(value));
272  if (sigma == 0.0)
273  sigma = 0.1;
274 
276  setItemValue(P_SCALE_PAR, sigma);
278 }
279 
281 {
282  getItem(P_MEDIAN)->setVisible(flag);
283 }
284 
285 // --------------------------------------------------------------------------------------------- //
286 
287 const QString DistributionCosineItem::P_SIGMA = QString::fromStdString("Sigma");
288 
290 {
292  addProperty(P_SIGMA, 1.0);
295  register_limits();
296 }
297 
298 std::unique_ptr<IDistribution1D> DistributionCosineItem::createDistribution(double scale) const
299 {
300  double mean = getItemValue(P_MEAN).toDouble();
301  double sigma = getItemValue(P_SIGMA).toDouble();
302  return std::make_unique<DistributionCosine>(scale * mean, scale * sigma);
303 }
304 
305 std::unique_ptr<IRangedDistribution>
307 {
308  return ::createIRangedDistribution<RangedDistributionCosine>(*this, scale);
309 }
310 
311 double DistributionCosineItem::deviation(double scale) const
312 {
313  return getItemValue(P_SIGMA).toDouble() * scale;
314 }
315 
317 {
318  double sigma(0.1 * std::abs(value));
319  if (sigma == 0.0)
320  sigma = 0.1;
321 
323  setItemValue(P_SIGMA, sigma);
325 }
326 
327 // --------------------------------------------------------------------------------------------- //
328 
329 const QString DistributionTrapezoidItem::P_CENTER = QString::fromStdString("Center");
330 const QString DistributionTrapezoidItem::P_LEFTWIDTH = QString::fromStdString("LeftWidth");
331 const QString DistributionTrapezoidItem::P_MIDDLEWIDTH = QString::fromStdString("MiddleWidth");
332 const QString DistributionTrapezoidItem::P_RIGHTWIDTH = QString::fromStdString("RightWidth");
333 
335 {
337  addProperty(P_LEFTWIDTH, 1.0);
341  register_limits();
342 }
343 
344 std::unique_ptr<IDistribution1D> DistributionTrapezoidItem::createDistribution(double scale) const
345 {
346  double center = getItemValue(P_CENTER).toDouble();
347  double left = getItemValue(P_LEFTWIDTH).toDouble();
348  double middle = getItemValue(P_MIDDLEWIDTH).toDouble();
349  double right = getItemValue(P_RIGHTWIDTH).toDouble();
350  return std::make_unique<DistributionTrapezoid>(scale * center, scale * left, scale * middle,
351  scale * right);
352 }
353 
355 {
356  double width(0.1 * std::abs(value));
357  if (width == 0.0)
358  width = 0.1;
360  setItemValue(P_LEFTWIDTH, width);
361  setItemValue(P_MIDDLEWIDTH, width);
362  setItemValue(P_RIGHTWIDTH, width);
363 }
364 
366 {
367  getItem(P_CENTER)->setVisible(flag);
368 }
369 
370 namespace {
371 template <class DistrType>
372 std::unique_ptr<IRangedDistribution>
373 createIRangedDistribution(const SymmetricDistributionItem& distr_item, double scale)
374 {
375  int n_samples = distr_item.getItemValue(SymmetricDistributionItem::P_NUMBER_OF_SAMPLES).toInt();
376  double n_sig = distr_item.getItemValue(SymmetricDistributionItem::P_SIGMA_FACTOR).toDouble();
377 
378  auto limits_item = distr_item.getGroupItem(SymmetricDistributionItem::P_LIMITS);
379  const RealLimits limits =
380  limits_item ? dynamic_cast<RealLimitsItem*>(limits_item)->createRealLimits(scale)
381  : RealLimits::limitless();
382 
383  return std::make_unique<DistrType>(n_samples, n_sig, limits);
384 }
385 } // namespace
Defines class DistributionItem and several subclasses.
Defines classes representing one-dimensional distributions.
Defines classes representing ranged one-dimensional distributions.
Defines RealLimitsItems's classes.
double deviation(double scale) const override
std::unique_ptr< IRangedDistribution > createIRangedDistribution(double scale) const override
void init_distribution(double value) override
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
static const QString P_SIGMA
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
static const QString P_MAX
void init_distribution(double value) override
static const QString P_MIN
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
static const QString P_STD_DEV
double deviation(double scale) const override
void init_distribution(double value) override
std::unique_ptr< IRangedDistribution > createIRangedDistribution(double scale) const override
void init_parameters(double value, const RealLimits &limits=RealLimits::limitless())
Provides initialization of the distribution with some reasonable parameters around given value.
virtual void init_distribution(double)
void init_limits_group(const RealLimits &limits, double factor=1.0)
static const QString P_LIMITS
DistributionItem(const QString &name)
static const QString P_IS_INITIALIZED
static const QString P_NUMBER_OF_SAMPLES
static const QString P_SIGMA_FACTOR
void showMean(bool flag) override
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
static const QString P_MEDIAN
static const QString P_SCALE_PAR
void init_distribution(double value) override
void init_distribution(double value) override
static const QString P_HWHM
double deviation(double scale) const override
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
std::unique_ptr< IRangedDistribution > createIRangedDistribution(double scale) const override
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
double deviation(double scale) const override
std::unique_ptr< IRangedDistribution > createIRangedDistribution(double scale) const override
void init_distribution(double value) override
static const QString P_LEFTWIDTH
std::unique_ptr< IDistribution1D > createDistribution(double scale=1.0) const override
void showMean(bool flag) override
static const QString P_RIGHTWIDTH
static const QString P_MIDDLEWIDTH
static const QString P_CENTER
void init_distribution(double value) override
static const QString P_XMAX
static const QString P_XMIN
Limits for a real fit parameter.
Definition: RealLimits.h:24
bool isLimited() const
Definition: RealLimits.cpp:199
static RealLimits limitless()
Creates an object withoud bounds (default)
Definition: RealLimits.cpp:130
bool isLowerLimited() const
Definition: RealLimits.cpp:189
bool isPositive() const
Definition: RealLimits.cpp:178
static RealLimits lowerLimited(double bound_value)
Creates an object bounded from the left.
Definition: RealLimits.cpp:105
double upperLimit() const
Returns upper limit.
Definition: RealLimits.cpp:62
double lowerLimit() const
Returns lower limit.
Definition: RealLimits.cpp:40
bool isNonnegative() const
Definition: RealLimits.cpp:184
bool isLimitless() const
Definition: RealLimits.cpp:173
bool isUpperLimited() const
Definition: RealLimits.cpp:194
bool isTag(const QString &name) const
Returns true if tag is available.
SessionItem * addProperty(const QString &name, const QVariant &variant)
Add new property item and register new tag.
SessionItem & setDecimals(int n)
SessionItem * getGroupItem(const QString &groupName) const
Access subitem of group item.
QVariant value() const
Get value.
void setVisible(bool enabled)
Flags accessors.
QVariant getItemValue(const QString &tag) const
Directly access value of item under given tag.
void setDisplayName(const QString &display_name)
Set display name.
SessionItem * addGroupProperty(const QString &groupTag, const QString &groupType)
Creates new group item and register new tag, returns GroupItem.
void setItemValue(const QString &tag, const QVariant &variant)
Directly set value of item under given tag.
SessionItem * setGroupProperty(const QString &groupTag, const QString &modelType) const
Set the current type of group item.
RealLimits limits() const
SessionItem * getItem(const QString &tag="", int row=0) const
Returns item in given row of given tag.
SessionItem & setLimits(const RealLimits &value)
void showMean(bool flag) override
SymmetricDistributionItem(const QString &name)
static const QString P_MEAN
QString const & name(EShape k)
Definition: particles.cpp:21