From c5f2ccd16ae665bd92d0fbef5a73c5a4854132fd Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Mon, 4 Nov 2024 15:48:54 +0100
Subject: [PATCH 1/4] init m_wavelength_item in SourceItem

---
 GUI/Model/Beam/SourceItems.cpp | 17 +++++------------
 GUI/Model/Beam/SourceItems.h   |  2 +-
 2 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/GUI/Model/Beam/SourceItems.cpp b/GUI/Model/Beam/SourceItems.cpp
index d673a006f0c..8df7144106e 100644
--- a/GUI/Model/Beam/SourceItems.cpp
+++ b/GUI/Model/Beam/SourceItems.cpp
@@ -66,11 +66,12 @@ void setAxisPresentationDefaults(BasicAxisItem* axisItem)
 //  ************************************************************************************************
 
 SourceItem::SourceItem()
+    : m_wavelength_item(std::make_unique<BeamDistributionItem>(1.))
+    , m_azimuthal_angle_item(std::make_unique<BeamDistributionItem>(Units::deg))
 {
     m_intensity.init("Intensity", "Beam intensity in neutrons/photons per sec.", 1e8, 3,
                      RealLimits::limited(0.0, 1e32), "intensity");
 
-    m_azimuthal_angle_item = std::make_unique<BeamDistributionItem>(Units::deg);
     m_footprint.simpleInit(
         "Footprint type",
         "Model for surface area where scattering takes place (\"beam footprint\")",
@@ -79,7 +80,6 @@ SourceItem::SourceItem()
 
 void SourceItem::writeTo(QXmlStreamWriter* w) const
 {
-    ASSERT(m_wavelength_item);
     m_intensity.writeTo2(w, Tag::Intensity);
     XML::writeTaggedElement(w, Tag::Wavelength, *m_wavelength_item);
     XML::writeTaggedElement(w, Tag::AzimuthalAngle, *m_azimuthal_angle_item);
@@ -90,7 +90,6 @@ void SourceItem::writeTo(QXmlStreamWriter* w) const
 
 void SourceItem::readFrom(QXmlStreamReader* r)
 {
-    ASSERT(m_wavelength_item);
     while (r->readNextStartElement()) {
         QString tag = r->name().toString();
         if (tag == Tag::Intensity)
@@ -160,22 +159,18 @@ void SourceItem::setFootprintItem(const IFootprint* footprint)
 //  ************************************************************************************************
 
 BeamItem::BeamItem()
+    : m_inclination_angle_item(std::make_unique<BeamDistributionItem>(Units::deg))
 {
-    m_wavelength_item = std::make_unique<BeamDistributionItem>(1.);
-    m_inclination_angle_item = std::make_unique<BeamDistributionItem>(Units::deg);
 }
 
 void BeamItem::writeTo(QXmlStreamWriter* w) const
 {
-    ASSERT(m_inclination_angle_item);
     XML::writeBaseElement<SourceItem>(w, XML::Tag::BaseData, this);
     XML::writeTaggedElement(w, Tag::InclinationAngle, *m_inclination_angle_item);
 }
 
 void BeamItem::readFrom(QXmlStreamReader* r)
 {
-    ASSERT(m_inclination_angle_item);
-
     while (r->readNextStartElement()) {
         QString tag = r->name().toString();
         if (tag == Tag::BaseData)
@@ -217,11 +212,9 @@ std::unique_ptr<Beam> BeamItem::createBeam() const
 
 ScanItem::ScanItem()
     : m_current_axis_is_uniform_axis(true)
+    , m_uniform_alpha_axis(std::make_unique<BasicAxisItem>())
+    , m_grazing_scan_item(std::make_unique<BeamDistributionItem>(Units::deg))
 {
-    m_grazing_scan_item = std::make_unique<BeamDistributionItem>(Units::deg);
-    m_wavelength_item = std::make_unique<BeamDistributionItem>(1.);
-
-    m_uniform_alpha_axis = std::make_unique<BasicAxisItem>();
     setAxisPresentationDefaults(m_uniform_alpha_axis.get());
 }
 
diff --git a/GUI/Model/Beam/SourceItems.h b/GUI/Model/Beam/SourceItems.h
index b72d2b79635..2b68745c942 100644
--- a/GUI/Model/Beam/SourceItems.h
+++ b/GUI/Model/Beam/SourceItems.h
@@ -120,9 +120,9 @@ public:
     void updateAxIndicators(const Frame& frame);
 
 private:
+    bool m_current_axis_is_uniform_axis;
     std::unique_ptr<BasicAxisItem> m_uniform_alpha_axis;
     std::unique_ptr<PointwiseAxisItem> m_pointwise_alpha_axis;
-    bool m_current_axis_is_uniform_axis;
     std::unique_ptr<BeamDistributionItem> m_grazing_scan_item;
 };
 
-- 
GitLab


From a81e347d9d0152917078cefecf8201a1954ee36f Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Mon, 4 Nov 2024 16:26:29 +0100
Subject: [PATCH 2/4] init lambda and angle with default values

---
 GUI/Model/Beam/SourceItems.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/GUI/Model/Beam/SourceItems.cpp b/GUI/Model/Beam/SourceItems.cpp
index 8df7144106e..9ef101a002b 100644
--- a/GUI/Model/Beam/SourceItems.cpp
+++ b/GUI/Model/Beam/SourceItems.cpp
@@ -76,6 +76,8 @@ SourceItem::SourceItem()
         "Footprint type",
         "Model for surface area where scattering takes place (\"beam footprint\")",
         FootprintCatalog::Type::Gaussian);
+
+    m_wavelength_item->resetToValue(0.1);
 }
 
 void SourceItem::writeTo(QXmlStreamWriter* w) const
@@ -161,6 +163,7 @@ void SourceItem::setFootprintItem(const IFootprint* footprint)
 BeamItem::BeamItem()
     : m_inclination_angle_item(std::make_unique<BeamDistributionItem>(Units::deg))
 {
+    m_inclination_angle_item->resetToValue(0.2);
 }
 
 void BeamItem::writeTo(QXmlStreamWriter* w) const
-- 
GitLab


From 12a6e85261ebcb785c58b1342f88f71e502722f0 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Mon, 4 Nov 2024 18:08:56 +0100
Subject: [PATCH 3/4] preserve central value of distribution

---
 GUI/Model/Beam/DistributionItems.h       |  4 +++
 GUI/View/Device/DistributionSelector.cpp | 10 +++++---
 GUI/View/Numeric/ComboUtil.h             | 32 ++++++++++++++++--------
 3 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/GUI/Model/Beam/DistributionItems.h b/GUI/Model/Beam/DistributionItems.h
index cc0cdc97979..c11a33aac7f 100644
--- a/GUI/Model/Beam/DistributionItems.h
+++ b/GUI/Model/Beam/DistributionItems.h
@@ -38,6 +38,7 @@ public:
 
     virtual DoubleProperty& center() = 0;
     virtual const DoubleProperty& center() const = 0;
+    virtual void setCenter(double v) = 0;
 
     //! Serialization of contents.
     //!
@@ -63,6 +64,7 @@ public:
 
     DoubleProperty& center() override { return mean(); }
     const DoubleProperty& center() const override { return mean(); }
+    void setCenter(double v) override { m_mean.setDVal(v); }
 
     void writeTo(QXmlStreamWriter* w) const override;
     void readFrom(QXmlStreamReader* r) override;
@@ -88,6 +90,7 @@ public:
 
     DoubleProperty& center() override { return m_center; }
     const DoubleProperty& center() const override { return m_center; }
+    void setCenter(double v) override { m_center.setDVal(v); }
 
     DoubleProperty& halfwidth() { return m_halfwidth; }
     const DoubleProperty& halfwidth() const { return m_halfwidth; }
@@ -149,6 +152,7 @@ public:
 
     DoubleProperty& center() override { return median(); }
     const DoubleProperty& center() const override { return median(); }
+    void setCenter(double v) override { m_median.setDVal(v); }
 
     DoubleProperty& scaleParameter() { return m_scale_parameter; }
     const DoubleProperty& scaleParameter() const { return m_scale_parameter; }
diff --git a/GUI/View/Device/DistributionSelector.cpp b/GUI/View/Device/DistributionSelector.cpp
index 9b27266ca3f..fec6c9e744c 100644
--- a/GUI/View/Device/DistributionSelector.cpp
+++ b/GUI/View/Device/DistributionSelector.cpp
@@ -33,13 +33,17 @@ DistributionSelector::DistributionSelector(std::optional<MeanConfig> mean_config
     m_form_layout = new QFormLayout(this);
     m_form_layout->setContentsMargins(0, 0, 0, 0);
 
-    m_distribution_combo = GUI::Util::createComboBoxFromPolyPtr(
-        item->distributionSelection(),
-        [this](int) {
+    m_distribution_combo = GUI::Util::createGeneralComboBoxFromPolyPtr(
+        m_item->distributionSelection(),
+        [this](int index) {
+            double old_center = m_item->distributionItem()->center().dVal();
+            m_item->distributionSelection().setCertainIndex(index);
+            m_item->distributionItem()->setCenter(old_center);
             createDistributionWidgets();
             emit distributionChanged();
         },
         true);
+
     m_distribution_combo->setEnabled(allow_distr);
     m_form_layout->addRow("Distribution:", m_distribution_combo);
 
diff --git a/GUI/View/Numeric/ComboUtil.h b/GUI/View/Numeric/ComboUtil.h
index 0a5fbeaf311..c57e7ab79da 100644
--- a/GUI/View/Numeric/ComboUtil.h
+++ b/GUI/View/Numeric/ComboUtil.h
@@ -43,12 +43,9 @@ QComboBox* createComboBox(std::function<ComboProperty()> comboFunction,
 //! Furthermore, the combo box can prohibit accidental changes by the mouse wheel. Otherwise it
 //! would be dangerous if the combo is on a scrollable form - unintended and unnoticed changes would
 //! take place when just scrolling through the form.
-//!
-//! Changes in the combobox will be notified to the PolyItem already. The additional (and
-//! optional) slot can be used to be notified about an already executed change.
 template <typename B, typename C>
-QComboBox* createComboBoxFromPolyPtr(PolyPtr<B, C>& d, std::function<void(int)> slot,
-                                     bool inScrollArea)
+QComboBox* createGeneralComboBoxFromPolyPtr(PolyPtr<B, C>& d, std::function<void(int)> full_slot,
+                                            bool inScrollArea)
 {
     auto* combo = new QComboBox;
     combo->addItems(d.menuEntries());
@@ -59,15 +56,30 @@ QComboBox* createComboBoxFromPolyPtr(PolyPtr<B, C>& d, std::function<void(int)>
     if (inScrollArea)
         WheelEventEater::install(combo);
 
-    QObject::connect(combo, &QComboBox::currentIndexChanged, [&d, slot](int index) {
-        d.setCertainIndex(index);
-        if (slot)
-            slot(index);
+    QObject::connect(combo, &QComboBox::currentIndexChanged, [full_slot](int index) {
+        if (full_slot)
+            full_slot(index);
     });
 
     return combo;
 }
-
+//! Create a combo box with the information found in a selection property.
+//!
+//! Changes in the combobox will be notified to the PolyItem already. The additional (and
+//! optional) slot can be used to be notified about an already executed change.
+template <typename B, typename C>
+QComboBox* createComboBoxFromPolyPtr(PolyPtr<B, C>& d, std::function<void(int)> optional_slot,
+                                     bool inScrollArea)
+{
+    return createGeneralComboBoxFromPolyPtr(
+        d,
+        [&d, optional_slot](int index) {
+            d.setCertainIndex(index);
+            if (optional_slot)
+                optional_slot(index);
+        },
+        inScrollArea);
+}
 } // namespace GUI::Util
 
 #endif // BORNAGAIN_GUI_VIEW_NUMERIC_COMBOUTIL_H
-- 
GitLab


From 675665cceb25f9abf46a5d337d800cadf1609749 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Mon, 4 Nov 2024 18:41:16 +0100
Subject: [PATCH 4/4] hide and do not preserve mean in scans

---
 GUI/Model/Beam/DistributionItems.cpp     |  8 ++++----
 GUI/View/Device/DistributionSelector.cpp | 14 +++++++++-----
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/GUI/Model/Beam/DistributionItems.cpp b/GUI/Model/Beam/DistributionItems.cpp
index 5ba714a35c1..5c2af146eba 100644
--- a/GUI/Model/Beam/DistributionItems.cpp
+++ b/GUI/Model/Beam/DistributionItems.cpp
@@ -157,7 +157,7 @@ DoubleProperties DistributionGateItem::distributionValues(bool /*withMean*/)
 // --------------------------------------------------------------------------------------------- //
 
 DistributionLorentzItem::DistributionLorentzItem()
-    : SymmetricDistributionItem(1.0)
+    : SymmetricDistributionItem(0)
 {
     m_hwhm.init("HWHM", "", 1.0, "hwhm");
 }
@@ -198,7 +198,7 @@ DoubleProperties DistributionLorentzItem::distributionValues(bool withMean)
 // --------------------------------------------------------------------------------------------- //
 
 DistributionGaussianItem::DistributionGaussianItem()
-    : SymmetricDistributionItem(1.0)
+    : SymmetricDistributionItem(0)
 {
     m_standard_deviation.init("StdDev", "", 1.0, 3, RealLimits::lowerLimited(0.0), "stdDev");
 }
@@ -242,7 +242,7 @@ DoubleProperties DistributionGaussianItem::distributionValues(bool withMean)
 DistributionLogNormalItem::DistributionLogNormalItem()
 {
     m_median.init("Median", "", 1.0, "median");
-    m_scale_parameter.init("ScaleParameter", "", 1.0, 3, RealLimits::lowerLimited(0.0), "scalePar");
+    m_scale_parameter.init("ScaleParameter", "", 0.5, 3, RealLimits::positive(), "scalePar");
 }
 
 std::unique_ptr<IDistribution1D> DistributionLogNormalItem::createDistribution(double scale) const
@@ -286,7 +286,7 @@ DoubleProperties DistributionLogNormalItem::distributionValues(bool /*withMean*/
 // --------------------------------------------------------------------------------------------- //
 
 DistributionCosineItem::DistributionCosineItem()
-    : SymmetricDistributionItem(1.0)
+    : SymmetricDistributionItem(0)
 {
     m_hwhm.init("HWHM", "", 1.0, 3, RealLimits::lowerLimited(0.0), "hwhm");
 }
diff --git a/GUI/View/Device/DistributionSelector.cpp b/GUI/View/Device/DistributionSelector.cpp
index fec6c9e744c..a3bb9812ee1 100644
--- a/GUI/View/Device/DistributionSelector.cpp
+++ b/GUI/View/Device/DistributionSelector.cpp
@@ -36,9 +36,13 @@ DistributionSelector::DistributionSelector(std::optional<MeanConfig> mean_config
     m_distribution_combo = GUI::Util::createGeneralComboBoxFromPolyPtr(
         m_item->distributionSelection(),
         [this](int index) {
-            double old_center = m_item->distributionItem()->center().dVal();
-            m_item->distributionSelection().setCertainIndex(index);
-            m_item->distributionItem()->setCenter(old_center);
+            if (m_mean_config) {
+                double old_center = m_item->distributionItem()->center().dVal();
+                m_item->distributionSelection().setCertainIndex(index);
+                m_item->distributionItem()->setCenter(old_center);
+            } else
+                m_item->distributionSelection().setCertainIndex(index);
+
             createDistributionWidgets();
             emit distributionChanged();
         },
@@ -60,7 +64,7 @@ void DistributionSelector::createDistributionWidgets()
         createSpinBox(it->hwhm());
         createNumSamplesSpinBox(it);
     } else if (auto* it = dynamic_cast<DistributionGateItem*>(m_item->distributionItem())) {
-        createSpinBox(it->center());
+        createMeanSpinBox(it->center());
         createSpinBox(it->halfwidth());
         createNumSamplesSpinBox(it);
     } else if (auto* it = dynamic_cast<DistributionGaussianItem*>(m_item->distributionItem())) {
@@ -69,7 +73,7 @@ void DistributionSelector::createDistributionWidgets()
         createNumSamplesSpinBox(it);
         createSpinBox(it->relSamplingWidth());
     } else if (auto* it = dynamic_cast<DistributionLogNormalItem*>(m_item->distributionItem())) {
-        createSpinBox(it->median());
+        createMeanSpinBox(it->median());
         createSpinBox(it->scaleParameter());
         createNumSamplesSpinBox(it);
         createSpinBox(it->relSamplingWidth());
-- 
GitLab