diff --git a/GUI/Model/Descriptor/DistributionItems.cpp b/GUI/Model/Descriptor/DistributionItems.cpp
index 686b879f7ee66cf44f9784048cc0f0bd7f520439..b300c361f35ab29f96cbbbf64180ce2c831257f2 100644
--- a/GUI/Model/Descriptor/DistributionItems.cpp
+++ b/GUI/Model/Descriptor/DistributionItems.cpp
@@ -128,17 +128,19 @@ void DistributionNoneItem::initDistribution(double value)
     setMean(value);
 }
 
-DoubleDescriptors DistributionNoneItem::distributionValues(bool withMean) const
+DoublePropertyRefs DistributionNoneItem::distributionValues(bool withMean)
 {
-    return withMean ? DoubleDescriptors{mean()} : DoubleDescriptors{};
+    return withMean ? DoublePropertyRefs{m_mean} : DoublePropertyRefs{};
 }
 
 // --------------------------------------------------------------------------------------------- //
 
 DistributionGateItem::DistributionGateItem()
 {
-    m_minimum.init("Min", "", 0.0, Unit::unitless, 3, RealLimits::limitless(), "min");
-    m_maximum.init("Max", "", 1.0, Unit::unitless, 3, RealLimits::limitless(), "max");
+    m_minimum.init("Min", "", 0.0, Unit::unitless, 3 /* decimals */, RealLimits::limitless(),
+                   "min");
+    m_maximum.init("Max", "", 1.0, Unit::unitless, 3 /* decimals */, RealLimits::limitless(),
+                   "max");
 }
 
 void DistributionGateItem::setUnit(const variant<QString, Unit>& unit)
@@ -149,7 +151,7 @@ void DistributionGateItem::setUnit(const variant<QString, Unit>& unit)
 
 std::unique_ptr<IDistribution1D> DistributionGateItem::createDistribution(double scale) const
 {
-    return std::make_unique<DistributionGate>(scale * m_minimum, scale * m_maximum);
+    return std::make_unique<DistributionGate>(scale * m_minimum.get(), scale * m_maximum.get());
 }
 
 void DistributionGateItem::initDistribution(double value)
@@ -174,9 +176,9 @@ void DistributionGateItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::Maximum, m_maximum);
 }
 
-DoubleDescriptors DistributionGateItem::distributionValues(bool /*withMean*/) const
+DoublePropertyRefs DistributionGateItem::distributionValues(bool /*withMean*/)
 {
-    return {minimum(), maximum()};
+    return {m_minimum, m_maximum};
 }
 
 // --------------------------------------------------------------------------------------------- //
@@ -197,13 +199,13 @@ void DistributionLorentzItem::setUnit(const variant<QString, Unit>& unit)
 
 std::unique_ptr<IDistribution1D> DistributionLorentzItem::createDistribution(double scale) const
 {
-    return std::make_unique<DistributionLorentz>(scale * m_mean, scale * m_hwhm);
+    return std::make_unique<DistributionLorentz>(scale * m_mean.get(), scale * m_hwhm.get());
 }
 
 std::unique_ptr<IRangedDistribution>
 DistributionLorentzItem::createIRangedDistribution(double scale) const
 {
-    return std::make_unique<RangedDistributionLorentz>(numberOfSamples(), sigmaFactor(),
+    return std::make_unique<RangedDistributionLorentz>(numberOfSamples(), m_sigmaFactor.get(),
                                                        m_limits.scaledLimits(scale));
 }
 
@@ -229,10 +231,10 @@ void DistributionLorentzItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::HWHM, m_hwhm);
 }
 
-DoubleDescriptors DistributionLorentzItem::distributionValues(bool withMean) const
+DoublePropertyRefs DistributionLorentzItem::distributionValues(bool withMean)
 {
-    return withMean ? DoubleDescriptors{mean(), hwhm(), sigmaFactor()}
-                    : DoubleDescriptors{hwhm(), sigmaFactor()};
+    return withMean ? DoublePropertyRefs{m_mean, m_hwhm, m_sigmaFactor}
+                    : DoublePropertyRefs{m_hwhm, m_sigmaFactor};
 }
 
 // --------------------------------------------------------------------------------------------- //
@@ -242,8 +244,8 @@ DistributionGaussianItem::DistributionGaussianItem()
 {
     initSigmaFactor();
 
-    m_standardDeviation.init("StdDev", "", 1.0, Unit::unitless, 3, RealLimits::lowerLimited(0.0),
-                             "stdDev");
+    m_standardDeviation.init("StdDev", "", 1.0, Unit::unitless, 3 /* decimals */,
+                             RealLimits::lowerLimited(0.0), "stdDev");
 }
 
 void DistributionGaussianItem::setUnit(const variant<QString, Unit>& unit)
@@ -254,19 +256,20 @@ void DistributionGaussianItem::setUnit(const variant<QString, Unit>& unit)
 
 std::unique_ptr<IDistribution1D> DistributionGaussianItem::createDistribution(double scale) const
 {
-    return std::make_unique<DistributionGaussian>(scale * m_mean, scale * m_standardDeviation);
+    return std::make_unique<DistributionGaussian>(scale * m_mean.get(),
+                                                  scale * m_standardDeviation.get());
 }
 
 std::unique_ptr<IRangedDistribution>
 DistributionGaussianItem::createIRangedDistribution(double scale) const
 {
-    return std::make_unique<RangedDistributionGaussian>(numberOfSamples(), sigmaFactor(),
+    return std::make_unique<RangedDistributionGaussian>(m_numberOfSamples, m_sigmaFactor.get(),
                                                         m_limits.scaledLimits(scale));
 }
 
 double DistributionGaussianItem::deviation(double scale) const
 {
-    return standardDeviation() * scale;
+    return m_standardDeviation.get() * scale;
 }
 
 void DistributionGaussianItem::initDistribution(double value)
@@ -285,10 +288,10 @@ void DistributionGaussianItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::StandardDeviation, m_standardDeviation);
 }
 
-DoubleDescriptors DistributionGaussianItem::distributionValues(bool withMean) const
+DoublePropertyRefs DistributionGaussianItem::distributionValues(bool withMean)
 {
-    return withMean ? DoubleDescriptors{mean(), standardDeviation(), sigmaFactor()}
-                    : DoubleDescriptors{standardDeviation(), sigmaFactor()};
+    return withMean ? DoublePropertyRefs{m_mean, m_standardDeviation, m_sigmaFactor}
+                    : DoublePropertyRefs{m_standardDeviation, m_sigmaFactor};
 }
 
 // --------------------------------------------------------------------------------------------- //
@@ -298,7 +301,7 @@ DistributionLogNormalItem::DistributionLogNormalItem()
     initSigmaFactor();
 
     m_median.init("Median", "", 1.0, Unit::unitless, "median");
-    m_scaleParameter.init("ScaleParameter", "", 1.0, Unit::unitless, 3,
+    m_scaleParameter.init("ScaleParameter", "", 1.0, Unit::unitless, 3 /* decimals */,
                           RealLimits::lowerLimited(0.0), "scalePar");
 }
 
@@ -309,7 +312,7 @@ void DistributionLogNormalItem::setUnit(const variant<QString, Unit>& unit)
 
 std::unique_ptr<IDistribution1D> DistributionLogNormalItem::createDistribution(double scale) const
 {
-    return std::make_unique<DistributionLogNormal>(scale * median(), scaleParameter());
+    return std::make_unique<DistributionLogNormal>(scale * m_median.get(), m_scaleParameter.get());
 }
 
 void DistributionLogNormalItem::initDistribution(double value)
@@ -329,9 +332,9 @@ void DistributionLogNormalItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::ScaleParameter, m_scaleParameter);
 }
 
-DoubleDescriptors DistributionLogNormalItem::distributionValues(bool /*withMean*/) const
+DoublePropertyRefs DistributionLogNormalItem::distributionValues(bool /*withMean*/)
 {
-    return {median(), scaleParameter(), sigmaFactor()};
+    return {m_median, m_scaleParameter, m_sigmaFactor};
 }
 
 // --------------------------------------------------------------------------------------------- //
@@ -340,7 +343,8 @@ DistributionCosineItem::DistributionCosineItem()
     : SymmetricResolutionItem(1.0)
 {
     initSigmaFactor();
-    m_sigma.init("Sigma", "", 1.0, Unit::unitless, 3, RealLimits::lowerLimited(0.0), "sigma");
+    m_sigma.init("Sigma", "", 1.0, Unit::unitless, 3 /* decimals */, RealLimits::lowerLimited(0.0),
+                 "sigma");
 }
 
 void DistributionCosineItem::setUnit(const variant<QString, Unit>& unit)
@@ -351,19 +355,19 @@ void DistributionCosineItem::setUnit(const variant<QString, Unit>& unit)
 
 std::unique_ptr<IDistribution1D> DistributionCosineItem::createDistribution(double scale) const
 {
-    return std::make_unique<DistributionCosine>(scale * m_mean, scale * sigma());
+    return std::make_unique<DistributionCosine>(scale * m_mean.get(), scale * m_sigma.get());
 }
 
 std::unique_ptr<IRangedDistribution>
 DistributionCosineItem::createIRangedDistribution(double scale) const
 {
-    return std::make_unique<RangedDistributionCosine>(numberOfSamples(), sigmaFactor(),
+    return std::make_unique<RangedDistributionCosine>(m_numberOfSamples, m_sigmaFactor.get(),
                                                       m_limits.scaledLimits(scale));
 }
 
 double DistributionCosineItem::deviation(double scale) const
 {
-    return sigma() * scale;
+    return m_sigma.get() * scale;
 }
 
 void DistributionCosineItem::initDistribution(double value)
@@ -382,17 +386,18 @@ void DistributionCosineItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::Sigma, m_sigma);
 }
 
-DoubleDescriptors DistributionCosineItem::distributionValues(bool withMean) const
+DoublePropertyRefs DistributionCosineItem::distributionValues(bool withMean)
 {
-    return withMean ? DoubleDescriptors{mean(), sigma(), sigmaFactor()}
-                    : DoubleDescriptors{sigma(), sigmaFactor()};
+    return withMean ? DoublePropertyRefs{m_mean, m_sigma, m_sigmaFactor}
+                    : DoublePropertyRefs{m_sigma, m_sigmaFactor};
 }
 
 // --------------------------------------------------------------------------------------------- //
 
 DistributionTrapezoidItem::DistributionTrapezoidItem()
 {
-    m_center.init("Center", "", 1.0, Unit::unitless, 3, RealLimits::limitless(), "center");
+    m_center.init("Center", "", 1.0, Unit::unitless, 3 /* decimals */, RealLimits::limitless(),
+                  "center");
     m_leftWidth.init("LeftWidth", "", 1.0, Unit::unitless, "left");
     m_middleWidth.init("MiddleWidth", "", 1.0, Unit::unitless, "middle");
     m_rightWidth.init("RightWidth", "", 1.0, Unit::unitless, "right");
@@ -408,8 +413,9 @@ void DistributionTrapezoidItem::setUnit(const variant<QString, Unit>& unit)
 
 std::unique_ptr<IDistribution1D> DistributionTrapezoidItem::createDistribution(double scale) const
 {
-    return std::make_unique<DistributionTrapezoid>(scale * center(), scale * leftWidth(),
-                                                   scale * middleWidth(), scale * rightWidth());
+    return std::make_unique<DistributionTrapezoid>(
+        scale * m_center.get(), scale * m_leftWidth.get(), scale * m_middleWidth.get(),
+        scale * m_rightWidth.get());
 }
 
 void DistributionTrapezoidItem::initDistribution(double value)
@@ -432,8 +438,8 @@ void DistributionTrapezoidItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::RightWidth, m_rightWidth);
 }
 
-DoubleDescriptors DistributionTrapezoidItem::distributionValues(bool withMean) const
+DoublePropertyRefs DistributionTrapezoidItem::distributionValues(bool withMean)
 {
-    return withMean ? DoubleDescriptors{center(), leftWidth(), middleWidth(), rightWidth()}
-                    : DoubleDescriptors{leftWidth(), middleWidth(), rightWidth()};
+    return withMean ? DoublePropertyRefs{m_center, m_leftWidth, m_middleWidth, m_rightWidth}
+                    : DoublePropertyRefs{m_leftWidth, m_middleWidth, m_rightWidth};
 }
diff --git a/GUI/Model/Descriptor/DistributionItems.h b/GUI/Model/Descriptor/DistributionItems.h
index fafafe4b06fd9edb50932daefaa21c7566833c1d..4f4d1e531343f118f30c5a8f8515cd74839226b9 100644
--- a/GUI/Model/Descriptor/DistributionItems.h
+++ b/GUI/Model/Descriptor/DistributionItems.h
@@ -56,14 +56,13 @@ public:
     //! to be set again by the owner of DistributionItem after reading it
     virtual void serialize(Streamer& s);
 
-    virtual DoubleDescriptors distributionValues(bool withMean = true) const = 0;
+    virtual DoublePropertyRefs distributionValues(bool withMean = true) = 0;
 
 protected:
     void initSigmaFactor();
 
     RealLimits m_limits;
 
-private:
     uint m_numberOfSamples = 5;
 };
 
@@ -90,7 +89,7 @@ public:
     double deviation(double scale) const override;
     void initDistribution(double value) override;
 
-    DoubleDescriptors distributionValues(bool withMean = true) const override;
+    DoublePropertyRefs distributionValues(bool withMean = true) override;
 };
 
 class DistributionGateItem : public DistributionItem {
@@ -107,7 +106,7 @@ public:
     void setRange(double min, double max);
 
     void serialize(Streamer& s) override;
-    DoubleDescriptors distributionValues(bool withMean = true) const override;
+    DoublePropertyRefs distributionValues(bool withMean = true) override;
 };
 
 class DistributionLorentzItem : public SymmetricResolutionItem {
@@ -124,7 +123,7 @@ public:
     void initDistribution(double value) override;
 
     void serialize(Streamer& s) override;
-    DoubleDescriptors distributionValues(bool withMean = true) const override;
+    DoublePropertyRefs distributionValues(bool withMean = true) override;
 };
 
 class DistributionGaussianItem : public SymmetricResolutionItem {
@@ -141,7 +140,7 @@ public:
     void initDistribution(double value) override;
     void serialize(Streamer& s) override;
 
-    DoubleDescriptors distributionValues(bool withMean = true) const override;
+    DoublePropertyRefs distributionValues(bool withMean = true) override;
 };
 
 class DistributionLogNormalItem : public DistributionItem {
@@ -156,7 +155,7 @@ public:
     DOUBLE_PROPERTY(scaleParameter, ScaleParameter);
 
     void serialize(Streamer& s) override;
-    DoubleDescriptors distributionValues(bool withMean = true) const override;
+    DoublePropertyRefs distributionValues(bool withMean = true) override;
 };
 
 class DistributionCosineItem : public SymmetricResolutionItem {
@@ -172,7 +171,7 @@ public:
     DOUBLE_PROPERTY(sigma, Sigma);
 
     void serialize(Streamer& s) override;
-    DoubleDescriptors distributionValues(bool withMean = true) const override;
+    DoublePropertyRefs distributionValues(bool withMean = true) override;
 };
 
 class DistributionTrapezoidItem : public DistributionItem {
@@ -189,7 +188,7 @@ public:
     DOUBLE_PROPERTY(rightWidth, RightWidth);
 
     void serialize(Streamer& s) override;
-    DoubleDescriptors distributionValues(bool withMean = true) const override;
+    DoublePropertyRefs distributionValues(bool withMean = true) override;
 };
 
 #endif // BORNAGAIN_GUI_MODEL_DESCRIPTOR_DISTRIBUTIONITEMS_H
diff --git a/GUI/Model/Descriptor/DoubleDescriptor.h b/GUI/Model/Descriptor/DoubleDescriptor.h
index 16d5b0c39637f26c8c5cc396984f674be3d6a1b5..eb24549e343ddd9ae83bdc91a9c7c90220123b8d 100644
--- a/GUI/Model/Descriptor/DoubleDescriptor.h
+++ b/GUI/Model/Descriptor/DoubleDescriptor.h
@@ -85,7 +85,4 @@ public:
         nullptr; //!< Path describing this value. Used e.g. for undo/redo
 };
 
-using DoubleDescriptors = QList<DoubleDescriptor>;
-
-
 #endif // BORNAGAIN_GUI_MODEL_DESCRIPTOR_DOUBLEDESCRIPTOR_H
diff --git a/GUI/Model/Descriptor/DoubleProperty.h b/GUI/Model/Descriptor/DoubleProperty.h
index 2168c053c3bc7445e24d703f0a681f129aa81514..fafcfe567b00ddc3fdad8e214f3cd86b5be0dd6d 100644
--- a/GUI/Model/Descriptor/DoubleProperty.h
+++ b/GUI/Model/Descriptor/DoubleProperty.h
@@ -30,17 +30,9 @@ class Streamer;
 //!   (e.g. Angstrom instead of nanometer)
 //! * decimals: how many decimals shall be shown in a spin box
 //! * limits: which limits shall be set in a spin box or other validator
-//! * persistent tag: a name to serialize this property. Do not change this tag if it was already
-//!   used for serialization, otherwise you may break backward compatibility of project reading.
 //! * uid: a unique id which represents this property. This is used for linking to this property,
-//!   also when serializing the link. Right now, this uid is a UUID. It could also be refactored and
-//!   changed to a simple (e.g. integer) id which is always unique throughout one project.
-//!
-//! This property class supports also the descriptor mechanism by directly returning a
-//! DoubleDescriptor. This descriptor contains all the relevant information taken from this class,
-//! and provides a getter and a setter to the contained value.
-//!
-//! \sa DoubleDescriptor
+//!   also when serializing the link. Right now, this uid is a UUID.
+
 class DoubleProperty {
 public:
     void init(const QString& label, const QString& tooltip, double value,
@@ -71,7 +63,7 @@ public:
 
     QString label() const { return m_label; }
 
-    uint decimals() { return m_decimals; }
+    uint decimals() const { return m_decimals; }
     void setDecimals(uint decimals) { m_decimals = decimals; }
 
     QString tooltip() const { return m_tooltip; }
@@ -80,7 +72,7 @@ public:
     std::variant<QString, Unit> unit() const { return m_unit; }
     void setUnit(const std::variant<QString, Unit>& unit);
 
-    RealLimits limits() { return m_limits; }
+    RealLimits limits() const { return m_limits; }
     void setLimits(const RealLimits& limits);
 
     //! True if one of the init methods has been called (checks for a valid uid).
@@ -120,4 +112,6 @@ public:                                                                 \
 
 // clang-format on
 
+using DoublePropertyRefs = QList<std::reference_wrapper<DoubleProperty>>;
+
 #endif // BORNAGAIN_GUI_MODEL_DESCRIPTOR_DOUBLEPROPERTY_H
diff --git a/GUI/Model/Descriptor/VectorProperty.h b/GUI/Model/Descriptor/VectorProperty.h
index c869bb9714b263a9fcb0ea836bd40e6b3e6ef591..7062c9e2591cf01758bd5d5e1b8b1deadc32e02c 100644
--- a/GUI/Model/Descriptor/VectorProperty.h
+++ b/GUI/Model/Descriptor/VectorProperty.h
@@ -57,9 +57,14 @@ public:
 
     void rwProperty(Streamer& s, const QString& tag);
 
-    DoubleDescriptor x() const { return m_x; }
-    DoubleDescriptor y() const { return m_y; }
-    DoubleDescriptor z() const { return m_z; }
+    DoubleProperty& x() { return m_x; }
+    const DoubleProperty& x() const { return m_x; }
+
+    DoubleProperty& y() { return m_y; }
+    const DoubleProperty& y() const { return m_y; }
+
+    DoubleProperty& z() { return m_z; }
+    const DoubleProperty& z() const { return m_z; }
 
 private:
     QString m_uid; //!< Unique id of this vector property.
diff --git a/GUI/Model/Device/BackgroundItems.cpp b/GUI/Model/Device/BackgroundItems.cpp
index 342e93687ccb68dd6509176cb3eddd839998ac62..49f33ae193bf5e895fa503e7d7c4ed81412059e8 100644
--- a/GUI/Model/Device/BackgroundItems.cpp
+++ b/GUI/Model/Device/BackgroundItems.cpp
@@ -28,8 +28,8 @@ const QString BackgroundValue("BackgroundValue");
 
 ConstantBackgroundItem::ConstantBackgroundItem()
 {
-    m_backgroundValue.init("Background value", "Constant background value", 0.0, "counts/pixel", 3,
-                           RealLimits::nonnegative(), "value");
+    m_backgroundValue.init("Background value", "Constant background value", 0.0, "counts/pixel",
+                           3 /* decimals */, RealLimits::nonnegative(), "value");
 }
 
 std::unique_ptr<IBackground> ConstantBackgroundItem::createBackground() const
diff --git a/GUI/Model/Device/BeamItems.cpp b/GUI/Model/Device/BeamItems.cpp
index 71c9993076de25f85a94133a7257e2daf5bb468b..58f4b0b3d415cb0ab4eccc5d8233566b809c6c40 100644
--- a/GUI/Model/Device/BeamItems.cpp
+++ b/GUI/Model/Device/BeamItems.cpp
@@ -49,7 +49,8 @@ RealLimits getLimits(double max_q)
 BeamItem::BeamItem()
 {
     m_intensity.init("Intensity", "Beam intensity in neutrons (or gammas) per sec.", 1e+08,
-                     Unit::unitless, 3, RealLimits::limited(0.0, 1e+32), "intensity");
+                     Unit::unitless, 3 /* decimals */, RealLimits::limited(0.0, 1e+32),
+                     "intensity");
 
     m_azimuthalAngleItem.reset(new BeamAzimuthalAngleItem());
 }
diff --git a/GUI/Model/Device/FootprintItems.cpp b/GUI/Model/Device/FootprintItems.cpp
index 323b599fdceff9e78178b4ac6c700102637bef42..454bba5b0c1ae15e57b419d92e500959fb679a71 100644
--- a/GUI/Model/Device/FootprintItems.cpp
+++ b/GUI/Model/Device/FootprintItems.cpp
@@ -34,7 +34,8 @@ std::unique_ptr<IFootprintFactor> FootprintNoneItem::createFootprint() const
 FootprintGaussianItem::FootprintGaussianItem(double value)
 {
     m_gaussianFootprintValue.init("Width ratio", "The ratio of beam and sample full widths", value,
-                                  Unit::unitless, 3, RealLimits::nonnegative(), "ratio");
+                                  Unit::unitless, 3 /* decimals */, RealLimits::nonnegative(),
+                                  "ratio");
 }
 
 void FootprintGaussianItem::serialize(Streamer& s)
@@ -51,7 +52,8 @@ std::unique_ptr<IFootprintFactor> FootprintGaussianItem::createFootprint() const
 FootprintSquareItem::FootprintSquareItem(double value)
 {
     m_squareFootprintValue.init("Width ratio", "The ratio of beam and sample full widths", value,
-                                Unit::unitless, 3, RealLimits::nonnegative(), "ratio");
+                                Unit::unitless, 3 /* decimals */, RealLimits::nonnegative(),
+                                "ratio");
 }
 
 void FootprintSquareItem::serialize(Streamer& s)
diff --git a/GUI/Model/Device/InstrumentItems.cpp b/GUI/Model/Device/InstrumentItems.cpp
index 6dea79c3835bbffa8ed465b7f91a21946c1147e4..b8a3e168530f22692dc8e7a5b9b4272d8c892db4 100644
--- a/GUI/Model/Device/InstrumentItems.cpp
+++ b/GUI/Model/Device/InstrumentItems.cpp
@@ -75,10 +75,11 @@ InstrumentItem::InstrumentItem()
 {
     m_id = QUuid::createUuid().toString();
     m_analyzerEfficiency.init("Analyzer efficiency", "Efficiency of the polarization analysis", 0.0,
-                              Unit::unitless, 4, RealLimits::limitless(), "efficiency");
-    m_analyzerTotalTransmission.init("Analyzer transmission",
-                                     "Total transmission of the polarization analysis", 1.0,
-                                     Unit::unitless, 4, RealLimits::nonnegative(), "transmission");
+                              Unit::unitless, 4 /* decimals */, RealLimits::limitless(),
+                              "efficiency");
+    m_analyzerTotalTransmission.init(
+        "Analyzer transmission", "Total transmission of the polarization analysis", 1.0,
+        Unit::unitless, 4 /* decimals */, RealLimits::nonnegative(), "transmission");
     m_polarization.init("Polarization (Bloch vector)",
                         "Polarization of the beam, given as the Bloch vector", Unit::unitless,
                         "polarization");
diff --git a/GUI/Model/Device/RectangularDetectorItem.cpp b/GUI/Model/Device/RectangularDetectorItem.cpp
index c316c42212ddd1f35d52b3fb5d8e4c7597ef6949..7b423ed024b2de7e47e9f0a1e3f4b3b7d2bf3f52 100644
--- a/GUI/Model/Device/RectangularDetectorItem.cpp
+++ b/GUI/Model/Device/RectangularDetectorItem.cpp
@@ -86,10 +86,10 @@ RectangularDetectorItem::RectangularDetectorItem()
 
     m_xSize = 100;
     m_ySize = 100;
-    m_width.init("Width (x-axis)", "Width of the detector", default_detector_width, "mm", 3,
-                 RealLimits::positive(), "width");
-    m_height.init("Height (y-axis)", "Height of the detector", default_detector_height, "mm", 3,
-                  RealLimits::positive(), "height");
+    m_width.init("Width (x-axis)", "Width of the detector", default_detector_width, "mm",
+                 3 /* decimals */, RealLimits::positive(), "width");
+    m_height.init("Height (y-axis)", "Height of the detector", default_detector_height, "mm",
+                  3 /* decimals */, RealLimits::positive(), "height");
 
     m_normalVector.init(
         "Normal vector",
@@ -101,8 +101,9 @@ RectangularDetectorItem::RectangularDetectorItem()
                            Unit::unitless, "directionVector");
     m_directionVector.setY(-1.0);
 
-    m_u0.init("u0", "", default_detector_width / 2., "mm", 3, RealLimits::limitless(), "u0");
-    m_v0.init("v0", "", 0.0, "mm", 3, RealLimits::limitless(), "v0");
+    m_u0.init("u0", "", default_detector_width / 2., "mm", 3 /* decimals */,
+              RealLimits::limitless(), "u0");
+    m_v0.init("v0", "", 0.0, "mm", 3 /* decimals */, RealLimits::limitless(), "v0");
     m_distance.init("Distance", "Distance from the sample origin to the detector plane",
                     default_detector_distance, "mm", "distance");
 
diff --git a/GUI/Model/Device/ResolutionFunctionItems.cpp b/GUI/Model/Device/ResolutionFunctionItems.cpp
index 3741fd4326da2258f3bbafb69deffdbc23e68d2e..bd7d141610496ad9ff9d222b0a973c2e3c2747f3 100644
--- a/GUI/Model/Device/ResolutionFunctionItems.cpp
+++ b/GUI/Model/Device/ResolutionFunctionItems.cpp
@@ -33,9 +33,9 @@ ResolutionFunctionNoneItem::createResolutionFunction(double) const
 
 ResolutionFunction2DGaussianItem::ResolutionFunction2DGaussianItem()
 {
-    m_sigmaX.init("Sigma X", "Resolution along horizontal axis", 0.02, Unit::degree, 3,
-                  RealLimits::lowerLimited(0.0), "sigmaX");
-    m_sigmaY.init("Sigma Y", "Resolution along vertical axis", 0.02, Unit::degree, 3,
+    m_sigmaX.init("Sigma X", "Resolution along horizontal axis", 0.02, Unit::degree,
+                  3 /* decimals */, RealLimits::lowerLimited(0.0), "sigmaX");
+    m_sigmaY.init("Sigma Y", "Resolution along vertical axis", 0.02, Unit::degree, 3 /* decimals */,
                   RealLimits::lowerLimited(0.0), "sigmaY");
 }
 
diff --git a/GUI/Model/Model/ParameterTreeUtils.cpp b/GUI/Model/Model/ParameterTreeUtils.cpp
index 3522450bdb5f4044196cbb223fb7e9caebdd1eb4..45a3689bcd1d01d2d240fbcb56efb1c6e08747d5 100644
--- a/GUI/Model/Model/ParameterTreeUtils.cpp
+++ b/GUI/Model/Model/ParameterTreeUtils.cpp
@@ -140,17 +140,17 @@ void ParameterTreeBuilder::addSample()
     }
 }
 
-void ParameterTreeBuilder::addParameterItem(ParameterLabelItem* parent, const DoubleDescriptor& d,
+void ParameterTreeBuilder::addParameterItem(ParameterLabelItem* parent, DoubleProperty& d,
                                             const QString& label)
 {
     auto* parameterItem = new ParameterItem(parent);
-    parameterItem->setTitle(labelWithUnit(label.isEmpty() ? d.label : label, d.unit));
+    parameterItem->setTitle(labelWithUnit(label.isEmpty() ? d.label() : label, d.unit()));
     parameterItem->linkToDescriptor(d);
     if (m_recreateBackupValues)
         m_jobItem->parameterContainerItem()->setBackupValue(parameterItem->link(), d.get());
 }
 
-void ParameterTreeBuilder::addParameterItem(ParameterLabelItem* parent, const VectorProperty& d)
+void ParameterTreeBuilder::addParameterItem(ParameterLabelItem* parent, VectorProperty& d)
 {
     auto* label = new ParameterLabelItem(d.label(), parent);
     addParameterItem(label, d.x());
@@ -172,7 +172,7 @@ bool ParameterTreeBuilder::allowMagneticFields() const
 void ParameterTreeBuilder::addInterference(ParameterLabelItem* layoutLabel,
                                            const ParticleLayoutItem* layout)
 {
-    const auto* interference = layout->interference().currentItem();
+    auto* interference = layout->interference().currentItem();
     if (!interference)
         return;
 
@@ -181,26 +181,26 @@ void ParameterTreeBuilder::addInterference(ParameterLabelItem* layoutLabel,
 
     auto* label = new ParameterLabelItem("Interference (" + title + ")", layoutLabel);
 
-    if (const auto* itf = dynamic_cast<const InterferenceRadialParacrystalItem*>(interference)) {
+    if (auto* itf = dynamic_cast<InterferenceRadialParacrystalItem*>(interference)) {
         addParameterItem(label, itf->positionVariance());
         addParameterItem(label, itf->peakDistance());
         addParameterItem(label, itf->dampingLength());
         addParameterItem(label, itf->domainSize());
         addParameterItem(label, itf->kappa());
 
-        const auto* pdf = itf->probabilityDistribution().currentItem();
+        auto* pdf = itf->probabilityDistribution().currentItem();
         auto* pdfLabel = addLabel<Profile1DItemCatalog>(label, "PDF", pdf);
-        for (const auto& d : pdf->valueDescriptors())
+        for (auto& d : pdf->valueDescriptors())
             addParameterItem(pdfLabel, d);
-    } else if (const auto* itf = dynamic_cast<const Interference2DParacrystalItem*>(interference)) {
+    } else if (auto* itf = dynamic_cast<Interference2DParacrystalItem*>(interference)) {
         addParameterItem(label, itf->positionVariance());
         addParameterItem(label, itf->dampingLength());
         addParameterItem(label, itf->domainSize1());
         addParameterItem(label, itf->domainSize2());
         addLattice(label, itf);
 
-        const auto* pdf1 = itf->probabilityDistribution1().currentItem();
-        const auto* pdf2 = itf->probabilityDistribution2().currentItem();
+        auto* pdf1 = itf->probabilityDistribution1().currentItem();
+        auto* pdf2 = itf->probabilityDistribution2().currentItem();
         const bool samePdfTypes =
             Profile2DItemCatalog::type(pdf1) == Profile2DItemCatalog::type(pdf2);
         auto* pdf1Label =
@@ -211,32 +211,31 @@ void ParameterTreeBuilder::addInterference(ParameterLabelItem* layoutLabel,
             addLabel<Profile2DItemCatalog>(label, samePdfTypes ? "PDF2" : "PDF", pdf2);
         for (const auto& d : pdf2->valueDescriptors())
             addParameterItem(pdf2Label, d);
-    } else if (const auto* itf = dynamic_cast<const Interference1DLatticeItem*>(interference)) {
+    } else if (auto* itf = dynamic_cast<Interference1DLatticeItem*>(interference)) {
         addParameterItem(label, itf->positionVariance());
         addParameterItem(label, itf->length());
         addParameterItem(label, itf->rotationAngle());
 
-        const auto* df = itf->decayFunction().currentItem();
+        auto* df = itf->decayFunction().currentItem();
         auto* dfLabel = addLabel<Profile1DItemCatalog>(label, "Decay function", df);
         for (const auto& d : df->valueDescriptors())
             addParameterItem(dfLabel, d);
-    } else if (const auto* itf = dynamic_cast<const Interference2DLatticeItem*>(interference)) {
+    } else if (auto* itf = dynamic_cast<Interference2DLatticeItem*>(interference)) {
         addParameterItem(label, itf->positionVariance());
         addLattice(label, itf);
 
-        const auto* df = itf->decayFunction().currentItem();
+        auto* df = itf->decayFunction().currentItem();
         auto* dfLabel = addLabel<Profile2DItemCatalog>(label, "Decay function", df);
         for (const auto& d : df->valueDescriptors())
             addParameterItem(dfLabel, d);
-    } else if (const auto* itf =
-                   dynamic_cast<const InterferenceFinite2DLatticeItem*>(interference)) {
+    } else if (auto* itf = dynamic_cast<InterferenceFinite2DLatticeItem*>(interference)) {
         // domainSize1 and domainSize2 are of type UInt (not matching the double approach for tuning
         // and fitting). In BornAgain 1.18 these values have not been added to the tuning tree, and
         // also not to the fitting parameters. Maybe this should be necessary, but for now this
         // stays the same and the two sizes are not added
         addParameterItem(label, itf->positionVariance());
         addLattice(label, itf);
-    } else if (const auto* itf = dynamic_cast<const InterferenceHardDiskItem*>(interference)) {
+    } else if (auto* itf = dynamic_cast<InterferenceHardDiskItem*>(interference)) {
         addParameterItem(label, itf->positionVariance());
         addParameterItem(label, itf->radius());
         addParameterItem(label, itf->density());
@@ -256,7 +255,7 @@ ParameterLabelItem* ParameterTreeBuilder::addParticle(ParameterLabelItem* parent
     addRotation(label, p);
 
     if (const auto* particle = dynamic_cast<const ParticleItem*>(p)) {
-        const auto* formFactor = particle->formfactor();
+        auto* formFactor = particle->formfactor();
         auto* ffLabel = addLabel<FormFactorItemCatalog>(label, "Formfactor", formFactor);
         for (const auto& d : formFactor->geometryValues())
             addParameterItem(ffLabel, d);
@@ -268,12 +267,12 @@ ParameterLabelItem* ParameterTreeBuilder::addParticle(ParameterLabelItem* parent
         l->setTitle(l->title() + " (Core)");
         l = addParticle(label, coreShell->shell(), false, false);
         l->setTitle(l->title() + " (Shell)");
-    } else if (const auto* meso = dynamic_cast<const MesocrystalItem*>(p)) {
+    } else if (auto* meso = dynamic_cast<MesocrystalItem*>(p)) {
         addParameterItem(label, meso->vectorA());
         addParameterItem(label, meso->vectorB());
         addParameterItem(label, meso->vectorC());
 
-        const auto* outerShape = meso->outerShape().currentItem();
+        auto* outerShape = meso->outerShape().currentItem();
         auto* ffLabel = addLabel<FormFactorItemCatalog>(label, "Outer shape", outerShape);
         for (const auto& d : outerShape->geometryValues())
             addParameterItem(ffLabel, d);
@@ -288,7 +287,7 @@ ParameterLabelItem* ParameterTreeBuilder::addParticle(ParameterLabelItem* parent
 void ParameterTreeBuilder::addLattice(ParameterLabelItem* parentLabel,
                                       const Interference2DAbstractLatticeItem* itf)
 {
-    const auto* lattice = itf->latticeType().currentItem();
+    auto* lattice = itf->latticeType().currentItem();
     auto* label = addLabel<Lattice2DItemCatalog>(parentLabel, "Lattice", lattice);
     for (const auto& d : lattice->geometryValues(!itf->xiIntegration()))
         addParameterItem(label, d);
@@ -296,18 +295,18 @@ void ParameterTreeBuilder::addLattice(ParameterLabelItem* parentLabel,
 
 void ParameterTreeBuilder::addRotation(ParameterLabelItem* parentLabel, ItemWithParticles* p)
 {
-    const auto* r = p->rotation().currentItem();
+    auto* r = p->rotation().currentItem();
     if (!r)
         return;
 
     auto* label = addLabel<RotationItemCatalog>(parentLabel, "Rotation", r);
-    for (const auto& d : r->rotationValues())
+    for (auto& d : r->rotationValues())
         addParameterItem(label, d);
 }
 
 void ParameterTreeBuilder::addInstrument()
 {
-    const auto* instrument = m_jobItem->instrumentItem();
+    auto* instrument = m_jobItem->instrumentItem();
     auto* label = new ParameterLabelItem(instrument->instrumentType() + " instrument",
                                          parameterContainer()->parameterTreeRoot());
 
@@ -415,7 +414,7 @@ void ParameterTreeBuilder::addBackground(ParameterLabelItem* instrumentLabel,
 }
 
 void ParameterTreeBuilder::addPolarization(ParameterLabelItem* instrumentLabel,
-                                           const InstrumentItem* instrument)
+                                           InstrumentItem* instrument)
 {
     if (!instrument->withPolarizerAnalyzer())
         return;
diff --git a/GUI/Model/Model/ParameterTreeUtils.h b/GUI/Model/Model/ParameterTreeUtils.h
index 114decb0b03d70df637be4260b55bb34811e2b33..3ee62be724d001987cfade017a5cbce017395d3e 100644
--- a/GUI/Model/Model/ParameterTreeUtils.h
+++ b/GUI/Model/Model/ParameterTreeUtils.h
@@ -20,20 +20,20 @@
 #include <functional>
 #include <variant>
 
+class BackgroundItem;
+class BeamDistributionItem;
+class BeamItem;
+class DetectorItem;
+class DoubleProperty;
+class InstrumentItem;
+class Interference2DAbstractLatticeItem;
+class ItemWithParticles;
 class JobItem;
+class ParameterContainerItem;
 class ParameterItem;
 class ParameterLabelItem;
-class ParameterContainerItem;
-class DoubleDescriptor;
-class VectorProperty;
 class ParticleLayoutItem;
-class ItemWithParticles;
-class Interference2DAbstractLatticeItem;
-class BeamItem;
-class BeamDistributionItem;
-class DetectorItem;
-class BackgroundItem;
-class InstrumentItem;
+class VectorProperty;
 
 //! The ParameterTreeBuilder contains helper functions to create container
 //! with ParameterItems. The ParameterItem appears in RealTimeView and provides real
@@ -52,9 +52,9 @@ private:
     //! add the job's sample
     void addSample();
     void addInstrument();
-    void addParameterItem(ParameterLabelItem* parent, const DoubleDescriptor& d,
+    void addParameterItem(ParameterLabelItem* parent, DoubleProperty& d,
                           const QString& label = QString());
-    void addParameterItem(ParameterLabelItem* parent, const VectorProperty& d);
+    void addParameterItem(ParameterLabelItem* parent, VectorProperty& d);
     ParameterContainerItem* parameterContainer();
     bool allowMagneticFields() const;
 
@@ -72,7 +72,7 @@ private:
 
     void addDetector(ParameterLabelItem* parentLabel, DetectorItem* detector);
     void addBackground(ParameterLabelItem* instrumentLabel, BackgroundItem* backgroundItem);
-    void addPolarization(ParameterLabelItem* instrumentLabel, const InstrumentItem* instrument);
+    void addPolarization(ParameterLabelItem* instrumentLabel, InstrumentItem* instrument);
 
 private:
     JobItem* m_jobItem;
diff --git a/GUI/Model/Sample/FormFactorItems.h b/GUI/Model/Sample/FormFactorItems.h
index efec54fd2557702f12cfb4a7c36dbafd226bd480..eb86d1ff1bb71170957e4e5337a7865881034f73 100644
--- a/GUI/Model/Sample/FormFactorItems.h
+++ b/GUI/Model/Sample/FormFactorItems.h
@@ -38,7 +38,7 @@ public:
 
 public:
     virtual std::unique_ptr<IFormFactor> createFormFactor() const = 0;
-    virtual DoubleDescriptors geometryValues() const = 0;
+    virtual DoublePropertyRefs geometryValues() = 0;
     virtual void serialize(Streamer& s) = 0;
 };
 
@@ -52,10 +52,7 @@ public:
     FF_PROPERTY(height, Height)
     FF_PROPERTY(alpha, Alpha)
 
-    DoubleDescriptors geometryValues() const override
-    {
-        return {m_length, m_width, m_height, m_alpha};
-    }
+    DoublePropertyRefs geometryValues() override { return {m_length, m_width, m_height, m_alpha}; }
     void serialize(Streamer& s) override;
 };
 
@@ -68,7 +65,7 @@ public:
     FF_PROPERTY(width, Width)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_length, m_width, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_length, m_width, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -81,7 +78,7 @@ public:
     FF_PROPERTY(width, Width)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_length, m_width, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_length, m_width, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -94,7 +91,7 @@ public:
     FF_PROPERTY(width, Width)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_length, m_width, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_length, m_width, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -107,7 +104,7 @@ public:
     FF_PROPERTY(height, Height)
     FF_PROPERTY(alpha, Alpha)
 
-    DoubleDescriptors geometryValues() const override { return {m_radius, m_height, m_alpha}; }
+    DoublePropertyRefs geometryValues() override { return {m_radius, m_height, m_alpha}; }
     void serialize(Streamer& s) override;
 };
 
@@ -120,7 +117,7 @@ public:
     FF_PROPERTY(height, Height)
     FF_PROPERTY(alpha, Alpha)
 
-    DoubleDescriptors geometryValues() const override { return {m_baseEdge, m_height, m_alpha}; }
+    DoublePropertyRefs geometryValues() override { return {m_baseEdge, m_height, m_alpha}; }
     void serialize(Streamer& s) override;
 };
 
@@ -134,7 +131,7 @@ public:
     FF_PROPERTY(heightRatio, HeightRatio)
     FF_PROPERTY(alpha, Alpha)
 
-    DoubleDescriptors geometryValues() const override
+    DoublePropertyRefs geometryValues() override
     {
         return {m_length, m_height, m_heightRatio, m_alpha};
     }
@@ -149,7 +146,7 @@ public:
     FF_PROPERTY(radius, Radius)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_radius, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_radius, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -162,7 +159,7 @@ public:
     FF_PROPERTY(radiusY, RadiusY)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_radiusX, m_radiusY, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_radiusX, m_radiusY, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -173,7 +170,7 @@ public:
 
     FF_PROPERTY(radius, Radius)
 
-    DoubleDescriptors geometryValues() const override { return {m_radius}; }
+    DoublePropertyRefs geometryValues() override { return {m_radius}; }
     void serialize(Streamer& s) override;
 };
 
@@ -185,7 +182,7 @@ public:
     FF_PROPERTY(radius, Radius)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_radius, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_radius, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -198,7 +195,7 @@ public:
     FF_PROPERTY(radiusY, RadiusY)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_radiusX, m_radiusY, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_radiusX, m_radiusY, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -210,7 +207,7 @@ public:
     FF_PROPERTY(baseEdge, BaseEdge)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_baseEdge, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_baseEdge, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -222,7 +219,7 @@ public:
     FF_PROPERTY(baseEdge, BaseEdge)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_baseEdge, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_baseEdge, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -235,7 +232,7 @@ public:
     FF_PROPERTY(height, Height)
     FF_PROPERTY(alpha, Alpha)
 
-    DoubleDescriptors geometryValues() const override { return {m_baseEdge, m_height, m_alpha}; }
+    DoublePropertyRefs geometryValues() override { return {m_baseEdge, m_height, m_alpha}; }
     void serialize(Streamer& s) override;
 };
 
@@ -248,7 +245,7 @@ public:
     FF_PROPERTY(width, Width)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_length, m_width, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_length, m_width, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -261,7 +258,7 @@ public:
     FF_PROPERTY(width, Width)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_length, m_width, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_length, m_width, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -274,7 +271,7 @@ public:
     FF_PROPERTY(width, Width)
     FF_PROPERTY(height, Height)
 
-    DoubleDescriptors geometryValues() const override { return {m_length, m_width, m_height}; }
+    DoublePropertyRefs geometryValues() override { return {m_length, m_width, m_height}; }
     void serialize(Streamer& s) override;
 };
 
@@ -288,7 +285,7 @@ public:
     FF_PROPERTY(height, Height)
     FF_PROPERTY(asymmetry, Asymmetry)
 
-    DoubleDescriptors geometryValues() const override
+    DoublePropertyRefs geometryValues() override
     {
         return {m_length, m_width, m_height, m_asymmetry};
     }
@@ -305,7 +302,7 @@ public:
     FF_PROPERTY(height, Height)
     FF_PROPERTY(asymmetry, Asymmetry)
 
-    DoubleDescriptors geometryValues() const override
+    DoublePropertyRefs geometryValues() override
     {
         return {m_length, m_width, m_height, m_asymmetry};
     }
@@ -322,7 +319,7 @@ public:
     FF_PROPERTY(height, Height)
     FF_PROPERTY(asymmetry, Asymmetry)
 
-    DoubleDescriptors geometryValues() const override
+    DoublePropertyRefs geometryValues() override
     {
         return {m_length, m_width, m_height, m_asymmetry};
     }
@@ -338,7 +335,7 @@ public:
     FF_PROPERTY(height, Height)
     FF_PROPERTY(alpha, Alpha)
 
-    DoubleDescriptors geometryValues() const override { return {m_baseEdge, m_height, m_alpha}; }
+    DoublePropertyRefs geometryValues() override { return {m_baseEdge, m_height, m_alpha}; }
     void serialize(Streamer& s) override;
 };
 
@@ -350,7 +347,7 @@ public:
     FF_PROPERTY(length, Length)
     FF_PROPERTY(removedLength, RemovedLength)
 
-    DoubleDescriptors geometryValues() const override { return {m_length, m_removedLength}; }
+    DoublePropertyRefs geometryValues() override { return {m_length, m_removedLength}; }
     void serialize(Streamer& s) override;
 };
 
@@ -363,7 +360,7 @@ public:
     FF_PROPERTY(height, Height)
     FF_PROPERTY(removedTop, RemovedTop)
 
-    DoubleDescriptors geometryValues() const override { return {m_radius, m_height, m_removedTop}; }
+    DoublePropertyRefs geometryValues() override { return {m_radius, m_height, m_removedTop}; }
     void serialize(Streamer& s) override;
 };
 
@@ -377,7 +374,7 @@ public:
     FF_PROPERTY(heightFlattening, HeightFlattening)
     FF_PROPERTY(removedTop, RemovedTop)
 
-    DoubleDescriptors geometryValues() const override
+    DoublePropertyRefs geometryValues() override
     {
         return {m_radius, m_height, m_heightFlattening, m_removedTop};
     }
@@ -392,7 +389,7 @@ public:
     FF_PROPERTY(length, Length)
     FF_PROPERTY(removedLength, RemovedLength)
 
-    DoubleDescriptors geometryValues() const override { return {m_length, m_removedLength}; }
+    DoublePropertyRefs geometryValues() override { return {m_length, m_removedLength}; }
     void serialize(Streamer& s) override;
 };
 
@@ -406,7 +403,7 @@ public:
     FF_PROPERTY(sliceBottom, SliceBottom)
     FF_PROPERTY(sliceTop, SliceTop)
 
-    DoubleDescriptors geometryValues() const override
+    DoublePropertyRefs geometryValues() override
     {
         return {m_radius, m_length, m_sliceBottom, m_sliceTop};
     }
@@ -419,7 +416,7 @@ class PlatonicItem : public FormFactorItem {
 public:
     FF_PROPERTY(edge, Edge)
 
-    DoubleDescriptors geometryValues() const override { return {m_edge}; }
+    DoublePropertyRefs geometryValues() override { return {m_edge}; }
     void serialize(Streamer& s) override;
 };
 
diff --git a/GUI/Model/Sample/Lattice2DItems.cpp b/GUI/Model/Sample/Lattice2DItems.cpp
index 74884987989db40b28764b379908da734e912b76..96152bdd755632ee8509e039ceb42c1c14417dd7 100644
--- a/GUI/Model/Sample/Lattice2DItems.cpp
+++ b/GUI/Model/Sample/Lattice2DItems.cpp
@@ -42,16 +42,6 @@ double Lattice2DItem::unitCellArea() const
     return createLattice()->unitCellArea();
 }
 
-DoubleDescriptor Lattice2DItem::latticeRotationAngle() const
-{
-    return m_latticeRotationAngle;
-}
-
-void Lattice2DItem::setLatticeRotationAngle(const double angle)
-{
-    m_latticeRotationAngle.set(angle);
-}
-
 // --------------------------------------------------------------------------------------------- //
 
 BasicLattice2DItem::BasicLattice2DItem()
@@ -65,8 +55,9 @@ BasicLattice2DItem::BasicLattice2DItem()
 
 std::unique_ptr<Lattice2D> BasicLattice2DItem::createLattice() const
 {
-    return std::make_unique<BasicLattice2D>(m_length1, m_length2, Units::deg2rad(m_angle),
-                                            Units::deg2rad(latticeRotationAngle()));
+    return std::make_unique<BasicLattice2D>(m_length1.get(), m_length2.get(),
+                                            Units::deg2rad(m_angle.get()),
+                                            Units::deg2rad(m_latticeRotationAngle.get()));
 }
 
 void BasicLattice2DItem::serialize(Streamer& s)
@@ -78,36 +69,6 @@ void BasicLattice2DItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::Angle, m_angle);
 }
 
-DoubleDescriptor BasicLattice2DItem::latticeLength1() const
-{
-    return m_length1;
-}
-
-void BasicLattice2DItem::setLatticeLength1(const double length1)
-{
-    m_length1.set(length1);
-}
-
-DoubleDescriptor BasicLattice2DItem::latticeLength2() const
-{
-    return m_length2;
-}
-
-void BasicLattice2DItem::setLatticeLength2(const double length2)
-{
-    m_length2.set(length2);
-}
-
-DoubleDescriptor BasicLattice2DItem::latticeAngle() const
-{
-    return m_angle;
-}
-
-void BasicLattice2DItem::setLatticeAngle(const double angle)
-{
-    m_angle.set(angle);
-}
-
 // --------------------------------------------------------------------------------------------- //
 
 SquareLattice2DItem::SquareLattice2DItem()
@@ -118,7 +79,8 @@ SquareLattice2DItem::SquareLattice2DItem()
 
 std::unique_ptr<Lattice2D> SquareLattice2DItem::createLattice() const
 {
-    return std::make_unique<SquareLattice2D>(m_length, Units::deg2rad(latticeRotationAngle()));
+    return std::make_unique<SquareLattice2D>(m_length,
+                                             Units::deg2rad(m_latticeRotationAngle.get()));
 }
 
 void SquareLattice2DItem::serialize(Streamer& s)
@@ -128,16 +90,6 @@ void SquareLattice2DItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::Length, m_length);
 }
 
-DoubleDescriptor SquareLattice2DItem::latticeLength() const
-{
-    return m_length;
-}
-
-void SquareLattice2DItem::setLatticeLength(const double length)
-{
-    m_length.set(length);
-}
-
 // --------------------------------------------------------------------------------------------- //
 
 HexagonalLattice2DItem::HexagonalLattice2DItem()
@@ -148,7 +100,8 @@ HexagonalLattice2DItem::HexagonalLattice2DItem()
 
 std::unique_ptr<Lattice2D> HexagonalLattice2DItem::createLattice() const
 {
-    return std::make_unique<HexagonalLattice2D>(m_length, Units::deg2rad(latticeRotationAngle()));
+    return std::make_unique<HexagonalLattice2D>(m_length.get(),
+                                                Units::deg2rad(m_latticeRotationAngle.get()));
 }
 
 void HexagonalLattice2DItem::serialize(Streamer& s)
@@ -157,13 +110,3 @@ void HexagonalLattice2DItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::LatticeRotationAngle, m_latticeRotationAngle);
     Serialize::rwProperty(s, Tag::Length, m_length);
 }
-
-DoubleDescriptor HexagonalLattice2DItem::latticeLength() const
-{
-    return m_length;
-}
-
-void HexagonalLattice2DItem::setLatticeLength(const double length)
-{
-    m_length.set(length);
-}
diff --git a/GUI/Model/Sample/Lattice2DItems.h b/GUI/Model/Sample/Lattice2DItems.h
index 3e6d87b97e0c499e4515af8d6c7c5bdfbe162b4c..a6b36bb9261b69c52192c5c92cd3704ed14d1173 100644
--- a/GUI/Model/Sample/Lattice2DItems.h
+++ b/GUI/Model/Sample/Lattice2DItems.h
@@ -30,12 +30,12 @@ protected:
 public:
     virtual ~Lattice2DItem() = default;
     virtual std::unique_ptr<Lattice2D> createLattice() const = 0;
-    virtual DoubleDescriptors geometryValues(bool withRotationAngle) const = 0;
+    virtual DoublePropertyRefs geometryValues(bool withRotationAngle) = 0;
     virtual void serialize(Streamer& s) = 0;
     double unitCellArea() const;
 
-    DoubleDescriptor latticeRotationAngle() const;
-    void setLatticeRotationAngle(double angle);
+    DoubleProperty& latticeRotationAngle() { return m_latticeRotationAngle; }
+    void setLatticeRotationAngle(double v) { m_latticeRotationAngle.set(v); }
 
 protected:
     DoubleProperty m_latticeRotationAngle;
@@ -48,21 +48,16 @@ public:
     BasicLattice2DItem();
     std::unique_ptr<Lattice2D> createLattice() const override;
     void serialize(Streamer& s) override;
-    DoubleDescriptors geometryValues(bool withRotationAngle) const override
+    DoublePropertyRefs geometryValues(bool withRotationAngle) override
     {
         if (withRotationAngle)
             return {m_length1, m_length2, m_angle, m_latticeRotationAngle};
         return {m_length1, m_length2, m_angle};
     }
 
-    DoubleDescriptor latticeLength1() const;
-    void setLatticeLength1(double length1);
-
-    DoubleDescriptor latticeLength2() const;
-    void setLatticeLength2(double length2);
-
-    DoubleDescriptor latticeAngle() const;
-    void setLatticeAngle(double angle);
+    void setLatticeLength1(double v) { m_length1.set(v); }
+    void setLatticeLength2(double v) { m_length2.set(v); }
+    void setLatticeAngle(double v) { m_angle.set(v); }
 
 private:
     DoubleProperty m_length1;
@@ -77,15 +72,14 @@ public:
     SquareLattice2DItem();
     std::unique_ptr<Lattice2D> createLattice() const override;
     void serialize(Streamer& s) override;
-    DoubleDescriptors geometryValues(bool withRotationAngle) const override
+    DoublePropertyRefs geometryValues(bool withRotationAngle) override
     {
         if (withRotationAngle)
             return {m_length, m_latticeRotationAngle};
         return {m_length};
     }
 
-    DoubleDescriptor latticeLength() const;
-    void setLatticeLength(double length);
+    void setLatticeLength(double v) { m_length.set(v); }
 
 private:
     DoubleProperty m_length;
@@ -98,15 +92,14 @@ public:
     HexagonalLattice2DItem();
     std::unique_ptr<Lattice2D> createLattice() const override;
     void serialize(Streamer& s) override;
-    DoubleDescriptors geometryValues(bool withRotationAngle) const override
+    DoublePropertyRefs geometryValues(bool withRotationAngle) override
     {
         if (withRotationAngle)
             return {m_length, m_latticeRotationAngle};
         return {m_length};
     }
 
-    DoubleDescriptor latticeLength() const;
-    void setLatticeLength(double length);
+    void setLatticeLength(double v) { m_length.set(v); }
 
 private:
     DoubleProperty m_length;
diff --git a/GUI/Model/Sample/ProfileItems.cpp b/GUI/Model/Sample/ProfileItems.cpp
index 7c87cf415d7b3d235971054de798cd2f8f7e76dc..b279f320ec161a925b4a62a11ce4f041228a5158 100644
--- a/GUI/Model/Sample/ProfileItems.cpp
+++ b/GUI/Model/Sample/ProfileItems.cpp
@@ -39,7 +39,7 @@ void Profile1DItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::Omega, m_omega);
 }
 
-DoubleDescriptors Profile1DItem::valueDescriptors() const
+DoublePropertyRefs Profile1DItem::valueDescriptors()
 {
     return {m_omega};
 }
@@ -99,9 +99,9 @@ void Profile1DVoigtItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::Eta, m_eta);
 }
 
-DoubleDescriptors Profile1DVoigtItem::valueDescriptors() const
+DoublePropertyRefs Profile1DVoigtItem::valueDescriptors()
 {
-    return Profile1DItem::valueDescriptors() + DoubleDescriptors{m_eta};
+    return Profile1DItem::valueDescriptors() + DoublePropertyRefs{m_eta};
 }
 
 // --------------------------------------------------------------------------------------------- //
@@ -126,7 +126,7 @@ void Profile2DItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::Gamma, m_gamma);
 }
 
-DoubleDescriptors Profile2DItem::valueDescriptors() const
+DoublePropertyRefs Profile2DItem::valueDescriptors()
 {
     return {m_omegaX, m_omegaY, m_gamma};
 }
@@ -186,7 +186,7 @@ void Profile2DVoigtItem::serialize(Streamer& s)
     Serialize::rwProperty(s, Tag::Eta, m_eta);
 }
 
-DoubleDescriptors Profile2DVoigtItem::valueDescriptors() const
+DoublePropertyRefs Profile2DVoigtItem::valueDescriptors()
 {
     return {m_omegaX, m_omegaY, m_eta, m_gamma};
 }
diff --git a/GUI/Model/Sample/ProfileItems.h b/GUI/Model/Sample/ProfileItems.h
index 648317a1326fac82d62a920513110cf0972d56a6..c90bb1ed0451259d18f77cb3e088e56e7ab7422d 100644
--- a/GUI/Model/Sample/ProfileItems.h
+++ b/GUI/Model/Sample/ProfileItems.h
@@ -33,7 +33,7 @@ public:
     double omega() const { return m_omega.get(); }
     void setOmega(double v) { m_omega.set(v); }
 
-    virtual DoubleDescriptors valueDescriptors() const;
+    virtual DoublePropertyRefs valueDescriptors();
 
 protected:
     Profile1DItem();
@@ -74,7 +74,7 @@ public:
 
     void setEta(double v) { m_eta.set(v); }
 
-    DoubleDescriptors valueDescriptors() const override;
+    DoublePropertyRefs valueDescriptors() override;
 
 private:
     DoubleProperty m_eta;
@@ -92,7 +92,7 @@ public:
     void setOmegaY(double v) { m_omegaY.set(v); }
     void setGamma(double v) { m_gamma.set(v); }
 
-    virtual DoubleDescriptors valueDescriptors() const;
+    virtual DoublePropertyRefs valueDescriptors();
 
 protected:
     Profile2DItem();
@@ -130,7 +130,7 @@ public:
 
     void setEta(double v) { m_eta.set(v); }
 
-    DoubleDescriptors valueDescriptors() const override;
+    DoublePropertyRefs valueDescriptors() override;
 
 private:
     DoubleProperty m_eta;
diff --git a/GUI/Model/Sample/RotationItems.h b/GUI/Model/Sample/RotationItems.h
index 96dc05fd3bac00f582dc508ae87799e8fd77b438..ec3318b441a3b3c7d06d0cea1bc005a5ca3a2083 100644
--- a/GUI/Model/Sample/RotationItems.h
+++ b/GUI/Model/Sample/RotationItems.h
@@ -29,7 +29,7 @@ public:
     RotMatrix rotation() const;
 
     virtual void serialize(Streamer& s) = 0;
-    virtual DoubleDescriptors rotationValues() const = 0;
+    virtual DoublePropertyRefs rotationValues() = 0;
 
 protected:
     RotationItem();
@@ -39,7 +39,7 @@ protected:
 class XYZRotationItem : public RotationItem {
 public:
     void serialize(Streamer& s) override;
-    DoubleDescriptors rotationValues() const override { return {m_angle}; };
+    DoublePropertyRefs rotationValues() override { return {m_angle}; };
 
     void setAngle(double v) { m_angle.set(v); }
 
@@ -75,7 +75,7 @@ class EulerRotationItem : public RotationItem {
 public:
     EulerRotationItem();
     void serialize(Streamer& s) override;
-    DoubleDescriptors rotationValues() const override { return {m_alpha, m_beta, m_gamma}; };
+    DoublePropertyRefs rotationValues() override { return {m_alpha, m_beta, m_gamma}; };
 
     void setAlpha(double v) { m_alpha.set(v); }
     void setBeta(double v) { m_beta.set(v); }
diff --git a/GUI/View/MaterialEditor/MaterialEditorDialog.cpp b/GUI/View/MaterialEditor/MaterialEditorDialog.cpp
index 129270fe5b30f85a2888cb8eb8970ed2b6cccb90..bc99c21b464276903f38479e96a628093cf73ec5 100644
--- a/GUI/View/MaterialEditor/MaterialEditorDialog.cpp
+++ b/GUI/View/MaterialEditor/MaterialEditorDialog.cpp
@@ -255,9 +255,9 @@ void MaterialEditorDialog::fill()
         m_ui->imaginaryEdit->setText(QString::number(materialItem->sldIm().get(), 'g'));
     }
 
-    m_ui->xSpinBox->setValue(materialItem->magnetization().x());
-    m_ui->ySpinBox->setValue(materialItem->magnetization().y());
-    m_ui->zSpinBox->setValue(materialItem->magnetization().z());
+    m_ui->xSpinBox->setValue(materialItem->magnetization().r3().x());
+    m_ui->ySpinBox->setValue(materialItem->magnetization().r3().y());
+    m_ui->zSpinBox->setValue(materialItem->magnetization().r3().z());
 }
 
 void MaterialEditorDialog::setCurrentMaterial(const MaterialItem* m)
diff --git a/GUI/View/MaterialEditor/MaterialEditorModel.cpp b/GUI/View/MaterialEditor/MaterialEditorModel.cpp
index 907a59115f0c8bfdaa455ab4eab4a026c3b90323..f5436c4ca8e7ff6865874e3904585c32445cb8ea 100644
--- a/GUI/View/MaterialEditor/MaterialEditorModel.cpp
+++ b/GUI/View/MaterialEditor/MaterialEditorModel.cpp
@@ -60,7 +60,7 @@ QVariant MaterialEditorModel::data(const QModelIndex& index, int role /*= Qt::Di
     if (!index.isValid())
         return {};
 
-    MaterialItem* material = m_model->materialItems()[index.row()];
+    const MaterialItem* material = m_model->materialItems()[index.row()];
 
     if (role == Qt::DisplayRole) {
         switch (index.column()) {
@@ -78,9 +78,9 @@ QVariant MaterialEditorModel::data(const QModelIndex& index, int role /*= Qt::Di
 
         case MAGNETIZATION:
             return QString("%1/%2/%3")
-                .arg(material->magnetization().x())
-                .arg(material->magnetization().y())
-                .arg(material->magnetization().z());
+                .arg(material->magnetization().r3().x())
+                .arg(material->magnetization().r3().y())
+                .arg(material->magnetization().r3().z());
         }
     } else if (role == Qt::DecorationRole) {
         switch (index.column()) {
diff --git a/GUI/View/SampleDesigner/FormLayouter.cpp b/GUI/View/SampleDesigner/FormLayouter.cpp
index 5b1c5e34d023ebd0b81a22587eb19a0b4afdfa9b..790a3ddbd27ae79686fef5e40ee0609d41f95e47 100644
--- a/GUI/View/SampleDesigner/FormLayouter.cpp
+++ b/GUI/View/SampleDesigner/FormLayouter.cpp
@@ -73,7 +73,7 @@ void FormLayouter::insertRow(int row, QString label, QWidget* w)
     m_formLayout->insertRow(row, LayerEditorUtils::createBoldLabel(label), w);
 }
 
-int FormLayouter::addGroupOfValues(const QString& labelText, const DoubleDescriptors& values)
+int FormLayouter::addGroupOfValues(const QString& labelText, const DoublePropertyRefs& values)
 {
     auto* w = new QWidget(m_formLayout->parentWidget());
     w->setObjectName("PropertyBaseWidget");
@@ -89,7 +89,7 @@ int FormLayouter::addGroupOfValues(const QString& labelText, const DoubleDescrip
     return addRow(labelText, w);
 }
 
-int FormLayouter::addVector(const VectorProperty& d, bool vertically /*= true*/)
+int FormLayouter::addVector(VectorProperty& d, bool vertically /*= true*/)
 {
     auto* w = new QWidget(m_formLayout->parentWidget());
     w->setObjectName("PropertyBaseWidget");
@@ -129,28 +129,27 @@ void FormLayouter::addStructureEditingRow(QPushButton* button)
     addRow(w);
 }
 
-int FormLayouter::addValue(const DoubleDescriptor& d)
+int FormLayouter::addValue(DoubleProperty& d)
 {
     insertValue(m_formLayout->rowCount(), d);
     return m_formLayout->rowCount() - 1;
 }
 
-int FormLayouter::addValue(const DoubleDescriptor& d, function<void(double)> onValueChange)
+int FormLayouter::addValue(DoubleProperty& d, function<void(double)> onValueChange)
 {
     insertValue(m_formLayout->rowCount(), d, onValueChange);
     return m_formLayout->rowCount() - 1;
 }
 
-void FormLayouter::insertValue(int row, const DoubleDescriptor& d)
+void FormLayouter::insertValue(int row, DoubleProperty& d)
 {
     auto* ec = m_ec; // to allow copy-capture in the following lambda
     insertValue(row, d, [ec, d](double newValue) { ec->setDouble(newValue, d); });
 }
 
-void FormLayouter::insertValue(int row, const DoubleDescriptor& d,
-                               function<void(double)> onValueChange)
+void FormLayouter::insertValue(int row, DoubleProperty& d, function<void(double)> onValueChange)
 {
-    auto labelText = d.label;
+    auto labelText = d.label();
     if (!labelText.endsWith(":"))
         labelText += ":";
 
diff --git a/GUI/View/SampleDesigner/FormLayouter.h b/GUI/View/SampleDesigner/FormLayouter.h
index 0ea7d56d75bdc82ac8d9e0ec41efc5ae83f4d64b..2d19425d1222915bd54a63dd63bba6eac82cb305 100644
--- a/GUI/View/SampleDesigner/FormLayouter.h
+++ b/GUI/View/SampleDesigner/FormLayouter.h
@@ -19,7 +19,6 @@
 #include "GUI/View/SampleDesigner/SelectionContainerForm.h"
 #include <QFormLayout>
 
-class DoubleDescriptor;
 class QPushButton;
 class QString;
 class QWidget;
@@ -29,9 +28,9 @@ class VectorProperty;
 
 //! Utility class to populate a QFormLayout.
 //!
-//! Helps to add edit controls which operate on descriptors (DoubleDescriptor, UIntDescriptor and so
-//! on). Also takes care of bold printed labels, the connection of labels and edit controls
-//! (buddies), which is necessary to realize the "label shows unit of value" feature.
+//! Helps to add edit controls which operate on Properties (DoubleProperty, VectorProperty,
+//! SelectionProperty). Also takes care of bold printed labels, the connection of labels and edit
+//! controls (buddies), which is necessary to realize the "label shows unit of value" feature.
 //! Connections to a given SampleEditorController are established as well.
 class FormLayouter {
 public:
@@ -79,7 +78,7 @@ public:
     //!
     //! The whole selection is realized by adding a SelectionContainerForm. This
     //! SelectionContainerForm is limited to contain the selection combo box and a list of double
-    //! values represented by DoubleDescriptors. To add more complex selections (e.g. with
+    //! values represented by DoubleProperties. To add more complex selections (e.g. with
     //! sub-selections or different value types), this method and the SelectionContainerForm is not
     //! sufficient. It has to be done "manually".
     //! For more details, see SelectionContainerForm.
@@ -89,7 +88,7 @@ public:
 
     //! Adds a row with a bold printed label and a DoubleSpinBox.
     //!
-    //! The DoubleSpinBox is initialized with the contents found in the descriptor (e.g. limits,
+    //! The DoubleSpinBox is initialized with the contents found in the DoubleProperty (e.g. limits,
     //! decimals, unit). The DoubleSpinBox is set as the "buddy" of the label. This is necessary to
     //! realize the "label shows unit of value" feature. Changes of the DoubleSpinBox are signaled
     //! to the SampleEditorController which has been overhanded in the constructor of this
@@ -97,43 +96,43 @@ public:
     //! should be called (e.g. for a special undo functionality), this method is not sufficient. It
     //! would have to be done "manually" or with the overload which takes a slot (see below).
     //! Returns the newly added row.
-    int addValue(const DoubleDescriptor& d);
+    int addValue(DoubleProperty& d);
 
     //! Adds a row with a bold printed label and a DoubleSpinBox.
     //!
     //! Same as above, but the called slot in case of a value change has to be overhanded.
     //! Use this only if the standard (calling SampleEditorController::setDouble()) is not
     //! sufficient.
-    int addValue(const DoubleDescriptor& d, std::function<void(double)> onValueChange);
+    int addValue(DoubleProperty& d, std::function<void(double)> onValueChange);
 
     //! Inserts a row with a bold printed label and a DoubleSpinBox.
     //!
     //! Same functionality as addValue(), please read there.
-    void insertValue(int row, const DoubleDescriptor& d);
+    void insertValue(int row, DoubleProperty& d);
 
     //! Inserts a row with a bold printed label and a DoubleSpinBox.
     //!
     //! Same functionality as addValue(), please read there.
-    void insertValue(int row, const DoubleDescriptor& d, std::function<void(double)> onValueChange);
+    void insertValue(int row, DoubleProperty& d, std::function<void(double)> onValueChange);
 
     //! Adds a row with a bold printed label and a set of DoubleDescriptors.
     //!
-    //! The label describes the set of the Descriptors and is located in the first column of the
-    //! layout. The DoubleSpinBoxes for each DoubleDescriptor are created as children of a newly
+    //! The label describes the set of the DoubleProperties and is located in the first column of
+    //! the layout. The DoubleSpinBoxes for each DoubleProperty are created as children of a newly
     //! created widget, which is positioned in the second column of the layout. If the number of
     //! values is greater than 1, the related labels are shown above them, to limit the necessary
-    //! space to the right. For the creation, signaling, unit handling etc. of one DoubleDescriptor
-    //! the same applies as when adding a single DoubleDesciptor with the method addValue(),
+    //! space to the right. For the creation, signaling, unit handling etc. of one DoubleProperty
+    //! the same applies as when adding a single DoubleProperty with the method addValue(),
     //! therefore please read there for more details. Returns the newly added row.
-    int addGroupOfValues(const QString& labelText, const DoubleDescriptors& values);
+    int addGroupOfValues(const QString& labelText, const DoublePropertyRefs& values);
 
     //! Adds a row with a bold printed label and the 3 values of a 3D vector.
     //!
-    //! Works the same as addGroupOfValues. The label is taken from the VectorDescriptor.
+    //! Works the same as addGroupOfValues. The label is taken from the VectorProperty.
     //! In addition, the caller can define whether the labels are above the values
     //! (vertically=true), or whether labels and values are all placed in one row
     //! (vertically=false).
-    int addVector(const VectorProperty& d, bool vertically = true);
+    int addVector(VectorProperty& d, bool vertically = true);
 
     //! Shows or hides the widgets in a row.
     void setRowVisible(int row, bool visible);
diff --git a/GUI/View/SampleDesigner/InterferenceForm.cpp b/GUI/View/SampleDesigner/InterferenceForm.cpp
index c1457759dd5b7a7e1c7e70db4639b0b9cbce722e..94e1890ae06657efd8a8daa1aef42aff89fc987c 100644
--- a/GUI/View/SampleDesigner/InterferenceForm.cpp
+++ b/GUI/View/SampleDesigner/InterferenceForm.cpp
@@ -76,7 +76,7 @@ void InterferenceForm::createInterferenceWidgets()
     // provide all the updating (data & UI), the method
     // SampleEditorController::setDensityRelatedValueValue has to be called (instead of
     // SampleEditorController::setDouble). For this we have the following lambda to add a value:
-    const auto addDensityRelatedValue = [&](DoubleDescriptor d) {
+    const auto addDensityRelatedValue = [this, &layouter, interference](DoubleProperty& d) {
         layouter.addValue(
             d, [=](double newValue) { m_ec->setDensityRelatedValue(interference, newValue, d); });
     };
diff --git a/GUI/View/SampleDesigner/LayerEditorUtils.cpp b/GUI/View/SampleDesigner/LayerEditorUtils.cpp
index 14cc40f90abfa04cd2ae8d38d55de747f99a6130..a09dbc19dc9a144121bde4d4b7559b5e6dbb1aea 100644
--- a/GUI/View/SampleDesigner/LayerEditorUtils.cpp
+++ b/GUI/View/SampleDesigner/LayerEditorUtils.cpp
@@ -65,7 +65,7 @@ void LayerEditorUtils::updateLabelUnit(QLabel* label)
 }
 
 void LayerEditorUtils::addMultiPropertyToGrid(QGridLayout* m_gridLayout, int firstCol,
-                                              const DoubleDescriptors& valueDescriptors,
+                                              const DoublePropertyRefs& valueDescriptors,
                                               SampleEditorController* ec, bool vertically,
                                               bool addSpacer)
 {
@@ -78,14 +78,14 @@ void LayerEditorUtils::addMultiPropertyToGrid(QGridLayout* m_gridLayout, int fir
 }
 
 void LayerEditorUtils::addMultiPropertyToGrid(QGridLayout* m_gridLayout, int firstCol,
-                                              const DoubleDescriptors& valueDescriptors,
+                                              const DoublePropertyRefs& valueDescriptors,
                                               function<void(double, DoubleDescriptor)> setNewValue,
                                               bool vertically, bool addSpacer)
 {
     int col = firstCol;
-    for (const auto& valueDescriptor : valueDescriptors) {
+    for (const DoubleProperty& valueDescriptor : valueDescriptors) {
         DoubleSpinBox* editor;
-        if (valueDescriptor.label == "Angle")
+        if (valueDescriptor.label() == "Angle")
             editor = new DoubleSpinBox(valueDescriptor, false, 1, 1.0);
         else
             editor = new DoubleSpinBox(valueDescriptor);
@@ -93,7 +93,7 @@ void LayerEditorUtils::addMultiPropertyToGrid(QGridLayout* m_gridLayout, int fir
         QObject::connect(editor, &DoubleSpinBox::baseValueChanged,
                          [=](double newValue) { setNewValue(newValue, valueDescriptor); });
 
-        QString labeltext = valueDescriptor.label;
+        QString labeltext = valueDescriptor.label();
         if (!vertically && !labeltext.endsWith(":"))
             labeltext += ":";
         auto* label = new QLabel(labeltext, m_gridLayout->parentWidget());
@@ -114,24 +114,22 @@ void LayerEditorUtils::addMultiPropertyToGrid(QGridLayout* m_gridLayout, int fir
 }
 
 void LayerEditorUtils::addMultiPropertyToGrid(QGridLayout* m_gridLayout, int firstCol,
-                                              const DoubleDescriptors& valueDescriptors,
+                                              const DoublePropertyRefs& valueDescriptors,
                                               SampleEditorController* ec, bool addSpacer)
 {
     addMultiPropertyToGrid(m_gridLayout, firstCol, valueDescriptors, ec,
                            valueDescriptors.size() > 1, addSpacer);
 }
 
-void LayerEditorUtils::addVectorToGrid(QGridLayout* m_gridLayout, int firstCol,
-                                       const VectorProperty& v, SampleEditorController* ec,
-                                       bool vertically, bool addSpacer)
+void LayerEditorUtils::addVectorToGrid(QGridLayout* m_gridLayout, int firstCol, VectorProperty& v,
+                                       SampleEditorController* ec, bool vertically, bool addSpacer)
 {
     addMultiPropertyToGrid(m_gridLayout, firstCol, {v.x(), v.y(), v.z()}, ec, vertically,
                            addSpacer);
 }
 
 
-void LayerEditorUtils::addVectorToGrid(QGridLayout* m_gridLayout, int firstCol,
-                                       const VectorProperty& v,
+void LayerEditorUtils::addVectorToGrid(QGridLayout* m_gridLayout, int firstCol, VectorProperty& v,
                                        function<void(double, DoubleDescriptor)> setNewValue,
                                        bool vertically, bool addSpacer)
 {
@@ -148,7 +146,7 @@ QLabel* LayerEditorUtils::createBoldLabel(const QString& text)
     return l;
 }
 
-DoubleDescriptors LayerEditorUtils::doubleDescriptorsOfItem(RotationItem* item)
+DoublePropertyRefs LayerEditorUtils::doubleDescriptorsOfItem(RotationItem* item)
 {
     if (!item)
         return {};
@@ -156,22 +154,22 @@ DoubleDescriptors LayerEditorUtils::doubleDescriptorsOfItem(RotationItem* item)
     return item->rotationValues();
 }
 
-DoubleDescriptors LayerEditorUtils::doubleDescriptorsOfItem(Profile2DItem* item)
+DoublePropertyRefs LayerEditorUtils::doubleDescriptorsOfItem(Profile2DItem* item)
 {
     return item->valueDescriptors();
 }
 
-DoubleDescriptors LayerEditorUtils::doubleDescriptorsOfItem(Profile1DItem* item)
+DoublePropertyRefs LayerEditorUtils::doubleDescriptorsOfItem(Profile1DItem* item)
 {
     return item->valueDescriptors();
 }
 
-DoubleDescriptors LayerEditorUtils::doubleDescriptorsOfItem(FormFactorItem* item)
+DoublePropertyRefs LayerEditorUtils::doubleDescriptorsOfItem(FormFactorItem* item)
 {
     return item->geometryValues();
 }
 
-DoubleDescriptors LayerEditorUtils::doubleDescriptorsOfItem(LayerBasicRoughnessItem* r)
+DoublePropertyRefs LayerEditorUtils::doubleDescriptorsOfItem(LayerBasicRoughnessItem* r)
 {
     if (r)
         return {r->sigma(), r->hurst(), r->lateralCorrelationLength()};
diff --git a/GUI/View/SampleDesigner/LayerEditorUtils.h b/GUI/View/SampleDesigner/LayerEditorUtils.h
index 25854f96b220d64bf08a33078add122565baba02..383a9b24754fd1d6d93a1dbb30aac68a11d00352 100644
--- a/GUI/View/SampleDesigner/LayerEditorUtils.h
+++ b/GUI/View/SampleDesigner/LayerEditorUtils.h
@@ -15,19 +15,19 @@
 #ifndef BORNAGAIN_GUI_VIEW_SAMPLEDESIGNER_LAYEREDITORUTILS_H
 #define BORNAGAIN_GUI_VIEW_SAMPLEDESIGNER_LAYEREDITORUTILS_H
 
-#include "GUI/Model/Descriptor/DoubleDescriptor.h"
-
 #include "GUI/Model/CatSample/FormFactorItemCatalog.h"
 #include "GUI/Model/CatSample/ItemWithParticlesCatalog.h"
+#include "GUI/Model/Descriptor/DoubleProperty.h"
 #include <QColor>
 #include <QList>
 #include <functional>
 
 class DoubleSpinBox;
-class Profile1DItem;
 class FormFactorItem;
 class ItemWithParticles;
 class LayerBasicRoughnessItem;
+class Profile1DItem;
+class Profile2DItem;
 class QGridLayout;
 class QLabel;
 class QPushButton;
@@ -36,7 +36,6 @@ class QWidget;
 class RotationItem;
 class SampleEditorController;
 class VectorProperty;
-class Profile2DItem;
 
 //! Utility functions to support layer oriented sample editor
 namespace LayerEditorUtils {
@@ -47,37 +46,37 @@ void updateLabelUnit(QLabel* label, DoubleSpinBox* editor);
 //! Create DoubleSpinBoxes for the DoubeDescriptors and connect them to
 //! SampleEditorController::setDouble()
 void addMultiPropertyToGrid(QGridLayout* m_gridLayout, int firstCol,
-                            const DoubleDescriptors& valueDescriptors, SampleEditorController* ec,
+                            const DoublePropertyRefs& valueDescriptors, SampleEditorController* ec,
                             bool vertically, bool addSpacer);
 
 //! Create DoubleSpinBoxes for the DoubeDescriptors and connect them to the given setNewValue()
 void addMultiPropertyToGrid(QGridLayout* m_gridLayout, int firstCol,
-                            const DoubleDescriptors& valueDescriptors,
+                            const DoublePropertyRefs& valueDescriptors,
                             std::function<void(double, DoubleDescriptor)> setNewValue,
                             bool vertically, bool addSpacer);
 
 void addMultiPropertyToGrid(QGridLayout* m_gridLayout, int firstCol,
-                            const DoubleDescriptors& valueDescriptors, SampleEditorController* ec,
+                            const DoublePropertyRefs& valueDescriptors, SampleEditorController* ec,
                             bool addSpacer);
 
 //! Create DoubleSpinBoxes for the DoubeDescriptors and connect them to
 //! SampleEditorController::setDouble()
-void addVectorToGrid(QGridLayout* m_gridLayout, int firstCol, const VectorProperty& v,
+void addVectorToGrid(QGridLayout* m_gridLayout, int firstCol, VectorProperty& v,
                      SampleEditorController* ec, bool vertically, bool addSpacer);
 
 //! Create DoubleSpinBoxes for the DoubeDescriptors and connect them to the given setNewValue()
-void addVectorToGrid(QGridLayout* m_gridLayout, int firstCol, const VectorProperty& v,
+void addVectorToGrid(QGridLayout* m_gridLayout, int firstCol, VectorProperty& v,
                      std::function<void(double, DoubleDescriptor)> setNewValue, bool vertically,
                      bool addSpacer);
 
 
 QLabel* createBoldLabel(const QString& text);
 
-DoubleDescriptors doubleDescriptorsOfItem(LayerBasicRoughnessItem* item);
-DoubleDescriptors doubleDescriptorsOfItem(FormFactorItem* item);
-DoubleDescriptors doubleDescriptorsOfItem(Profile1DItem* item);
-DoubleDescriptors doubleDescriptorsOfItem(Profile2DItem* item);
-DoubleDescriptors doubleDescriptorsOfItem(RotationItem* item);
+DoublePropertyRefs doubleDescriptorsOfItem(LayerBasicRoughnessItem* item);
+DoublePropertyRefs doubleDescriptorsOfItem(FormFactorItem* item);
+DoublePropertyRefs doubleDescriptorsOfItem(Profile1DItem* item);
+DoublePropertyRefs doubleDescriptorsOfItem(Profile2DItem* item);
+DoublePropertyRefs doubleDescriptorsOfItem(RotationItem* item);
 
 QWidget* createWidgetForItemWithParticles(QWidget* parentWidget,
                                           ItemWithParticles* itemWithParticles, bool allowAbundance,
diff --git a/GUI/View/SampleDesigner/MaterialInplaceForm.cpp b/GUI/View/SampleDesigner/MaterialInplaceForm.cpp
index 17dd9b0361bbc3800b8037eedea500312f3066ac..442f957f0efa3cc7d2cd76b0736ba0201a3307a4 100644
--- a/GUI/View/SampleDesigner/MaterialInplaceForm.cpp
+++ b/GUI/View/SampleDesigner/MaterialInplaceForm.cpp
@@ -92,16 +92,16 @@ void MaterialInplaceForm::createWidgets()
     ASSERT(material);
 
     // -- Create UI for delta/beta resp. sldRe/sldIm
-    DoubleDescriptors values;
+    DoublePropertyRefs values;
     if (material->hasRefractiveIndex())
         values << material->delta() << material->beta();
     else
         values << material->sldRe() << material->sldIm();
 
     int col = 0;
-    for (const auto& d : values) {
+    for (const DoubleProperty& d : values) {
         auto* editor = new DoubleLineEdit(this, d);
-        auto* label = new QLabel(d.label, this);
+        auto* label = new QLabel(d.label(), this);
         label->setBuddy(editor);
 
         QObject::connect(editor, &DoubleLineEdit::baseValueChanged,
diff --git a/GUI/View/SampleDesigner/SelectionContainerForm.h b/GUI/View/SampleDesigner/SelectionContainerForm.h
index 482c36dd271f63bfbe9b6dd5b4dc634d11948a15..4b4880af9d3cafd3fbcc93d082a2094dae87a68a 100644
--- a/GUI/View/SampleDesigner/SelectionContainerForm.h
+++ b/GUI/View/SampleDesigner/SelectionContainerForm.h
@@ -109,7 +109,7 @@ public:
                 return LayerEditorUtils::doubleDescriptorsOfItem(d.currentItem());
             };
         else
-            currentValues = [] { return DoubleDescriptors(); };
+            currentValues = [] { return DoublePropertyRefs(); };
 
         initUI(d);
     }
@@ -121,7 +121,7 @@ public:
     }
 
 private:
-    std::function<DoubleDescriptors()> currentValues = nullptr;
+    std::function<DoublePropertyRefs()> currentValues = nullptr;
 };
 
 #endif // BORNAGAIN_GUI_VIEW_SAMPLEDESIGNER_SELECTIONCONTAINERFORM_H