BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
DistributionEditor.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/Instrument/DistributionEditor.cpp
6 //! @brief Implements classes DistributionSelector and DistributionEditor
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 "GUI/Support/XML/Backup.h"
26 #include <QComboBox>
27 #include <QFormLayout>
28 #include <QStackedLayout>
29 #include <utility>
30 
31 //==================================================================================================
32 // DistributionSelector
33 //==================================================================================================
34 
35 DistributionSelector::DistributionSelector(std::optional<MeanConfig> mean_config,
36  GUI::ID::Distributions distributions, QWidget* parent,
38  : QWidget(parent)
39  , m_item(item)
40  , m_meanConfig(std::move(mean_config))
41  , m_distributions(distributions)
42 {
43  ASSERT(item);
44  m_formLayout = new QFormLayout(this);
45  m_formLayout->setMargin(0);
46 
49  createDistributionWidgets();
50  emit distributionChanged();
51  });
52  m_formLayout->addRow("Distribution:", m_distributionCombo);
53 
55 }
56 
58 {
59  while (m_formLayout->rowCount() > 1)
60  m_formLayout->removeRow(1);
61 
62  if (auto* cosine = dynamic_cast<DistributionCosineItem*>(m_item->distribution())) {
63  createMeanSpinBox(cosine->mean());
64  createSpinBox(cosine->sigma());
65  createSpinBox(cosine->numberOfSamples());
66  createSpinBox(cosine->sigmaFactor());
67  } else if (auto* gate = dynamic_cast<DistributionGateItem*>(m_item->distribution())) {
68  auto* minSpinbox = createSpinBox(gate->minimum());
69  auto* maxSpinbox = createSpinBox(gate->maximum());
70  connect(minSpinbox, &DoubleSpinBox::baseValueChanged, [=](double d) {
71  if (d > gate->maximum()) {
72  gate->setMaximum(d);
73  maxSpinbox->updateValue();
74  }
75  });
76  connect(maxSpinbox, &DoubleSpinBox::baseValueChanged, [=](double d) {
77  if (d < gate->minimum()) {
78  gate->setMinimum(d);
79  minSpinbox->updateValue();
80  }
81  });
82  createSpinBox(gate->numberOfSamples());
83  } else if (auto* gauss = dynamic_cast<DistributionGaussianItem*>(m_item->distribution())) {
84  createMeanSpinBox(gauss->mean());
85  createSpinBox(gauss->standardDeviation());
86  createSpinBox(gauss->numberOfSamples());
87  createSpinBox(gauss->sigmaFactor());
88  } else if (auto* logNormal = dynamic_cast<DistributionLogNormalItem*>(m_item->distribution())) {
89  createSpinBox(logNormal->median());
90  createSpinBox(logNormal->scaleParameter());
91  createSpinBox(logNormal->numberOfSamples());
92  createSpinBox(logNormal->sigmaFactor());
93  } else if (auto* lorentz = dynamic_cast<DistributionLorentzItem*>(m_item->distribution())) {
94  createMeanSpinBox(lorentz->mean());
95  createSpinBox(lorentz->hwhm());
96  createSpinBox(lorentz->numberOfSamples());
97  createSpinBox(lorentz->sigmaFactor());
98  } else if (auto* none = dynamic_cast<DistributionNoneItem*>(m_item->distribution())) {
99  createMeanSpinBox(none->mean());
100  } else if (auto* trapezoid = dynamic_cast<DistributionTrapezoidItem*>(m_item->distribution())) {
101  createSpinBox(trapezoid->center());
102  createSpinBox(trapezoid->leftWidth());
103  createSpinBox(trapezoid->middleWidth());
104  createSpinBox(trapezoid->rightWidth());
105  createSpinBox(trapezoid->numberOfSamples());
106  }
107 }
108 
110 {
111  auto* sb = GUI::Util::createSpinBox(m_formLayout, d);
112  connect(sb, &DoubleSpinBox::baseValueChanged, [=](double v) {
113  d.set(v);
114  emit distributionChanged();
115  });
116  return sb;
117 }
118 
120 {
121  auto* sb = GUI::Util::createSpinBox(m_formLayout, d);
122  connect(sb, QOverload<int>::of(&QSpinBox::valueChanged), [=](int v) {
123  d.set(v);
124  emit distributionChanged();
125  });
126  return sb;
127 }
128 
130 {
131  if (m_meanConfig) {
132  if (m_meanConfig->scientific) {
134  connect(sb, &ScientificSpinBox::valueChanged, [=](double v) {
135  d.set(v);
136  emit distributionChanged();
137  });
138  } else
139  createSpinBox(d);
140  }
141 }
142 
144 {
145  return m_item;
146 }
147 
149 {
150  return m_distributions;
151 }
152 
154 {
155  QSignalBlocker b(m_distributionCombo);
156  m_distributionCombo->setCurrentIndex(m_item->distributionSelection().currentIndex());
158 }
159 
160 
161 //==================================================================================================
162 // DistributionEditor
163 //==================================================================================================
164 
166  const std::optional<MeanConfig>& mean_config,
167  GUI::ID::Distributions distributions, QWidget* parent,
168  BeamDistributionItem* item)
169  : QGroupBox(title, parent)
170 {
171  setProperty("subgroup", true); // for stylesheet addressing
172  auto* hLayout = new QHBoxLayout(this);
173  m_selector = new DistributionSelector(mean_config, distributions, this, item);
174  hLayout->addWidget(m_selector);
175  hLayout->setSpacing(50);
176 
177  m_plot = new DistributionPlot(this);
178  m_plot->setFixedSize(280, 170);
179  m_plot->setShowMouseCoords(false);
180  hLayout->addWidget(m_plot);
181  hLayout->addStretch(1);
182 
184 
189 
190  updatePlot();
191 }
192 
194 {
195  m_selector->refresh();
196 }
197 
199 {
200  auto* d = m_selector->item()->distribution();
201  m_plot->setVisible(!dynamic_cast<const DistributionNoneItem*>(d));
202  m_plot->setItem(d);
203  m_plot->plotItem();
204 }
Defines GUI::Util namespace.
Defines class BeamDistributionItem.
A widget for selecting a distribution and setting its parameters.
Defines class DistributionItemCatalog.
Defines class DistributionItem and several subclasses.
Defines class DistributionPlot.
Defines class DoubleSpinBox.
Defines class GroupBoxCollapser.
Defines class ScientificSpinBox.
Defines class Streamer.
Defines GUI::Util namespace.
The BeamDistributionItem handles wavelength, inclination and azimuthal parameter distribution for Bea...
SelectionDescriptor< DistributionItem * > distributionSelection() const
DistributionItem * distribution() const
DistributionPlot * m_plot
void updateData()
Update UI from data.
DistributionSelector * m_selector
void distributionChanged()
DistributionEditor(const QString &title, const std::optional< MeanConfig > &mean_config, GUI::ID::Distributions distributions, QWidget *parent, BeamDistributionItem *item)
The DistributionPlot class plots 1d functions corresponding to domain's Distribution1D.
void setShowMouseCoords(bool b)
void setItem(DistributionItem *item)
Widget for selecting a distribution (combo box) and input of the corresponding values with respect to...
BeamDistributionItem * m_item
DistributionSelector(std::optional< MeanConfig > mean_config, GUI::ID::Distributions distributions, QWidget *parent, BeamDistributionItem *item)
DoubleSpinBox * createSpinBox(const DoubleDescriptor &d)
GUI::ID::Distributions m_distributions
QComboBox * m_distributionCombo
GUI::ID::Distributions distributions() const
void createMeanSpinBox(const DoubleDescriptor &d)
BeamDistributionItem * item() const
QFormLayout * m_formLayout
std::optional< MeanConfig > m_meanConfig
Describes properties of a double value which are necessary to allow GUI representation,...
function< void(double)> set
function to set the value
SpinBox for DoubleDescriptors, supporting units.
Definition: DoubleSpinBox.h:22
void baseValueChanged(double newBaseValue)
Emitted whenever the value changes.
static GroupBoxCollapser * installIntoGroupBox(QGroupBox *groupBox, bool expanded=true)
void valueChanged(double value)
Describes properties of a uint value which are necessary to allow GUI representation,...
function< void(uint)> set
function to set the value
Distributions
Which distributions should be available in the selector.
Definition: ID.h:24
ScientificSpinBox * createScientificSpinBox(QFormLayout *parentLayout, const DoubleDescriptor &d, std::function< void(double)> slot=nullptr)
Create a label and a scientific spin box with the information found in a DoubleDescriptor and place t...
Definition: WidgetUtils.cpp:82
QComboBox * createSelectionCombo(QWidget *parent, const SelectionDescriptor< T > d, std::function< void(int)> slot=nullptr)
Create a combo box with the information found in a selection descriptor.
Definition: WidgetUtils.h:45
QSpinBox * createSpinBox(QWidget *parent, const UIntDescriptor &d, std::function< void(uint)> slot=nullptr)
Create a spin box with the information found in a UIntDescriptor.
Definition: WidgetUtils.cpp:24