From 7c0299e2528fe540bb8468f16aefe159161007aa Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Tue, 26 Sep 2023 09:57:58 +0200
Subject: [PATCH 1/6] Pt example now loading through ba. Todo: restrict q range

---
 Device/IO/ReadReflectometry.cpp               |  2 +-
 auto/Examples/fit/specular/Pt_layer_fit.py    | 49 ++++---------------
 .../MiniExamples/fit/specular/Pt_layer_fit.py | 49 ++++---------------
 rawEx/fit/specular/Pt_layer_fit.py            | 49 ++++---------------
 4 files changed, 31 insertions(+), 118 deletions(-)

diff --git a/Device/IO/ReadReflectometry.cpp b/Device/IO/ReadReflectometry.cpp
index 71343ca3377..4cf79206910 100644
--- a/Device/IO/ReadReflectometry.cpp
+++ b/Device/IO/ReadReflectometry.cpp
@@ -69,7 +69,7 @@ Datafield* Util::RW::readReflectometryTable(std::istream& s, const ImportSetting
     double fac = 1.;
     Coordinate outCoord = p.xCoord;
     if (outCoord.unit() == "1/angstrom") {
-        fac = 0.1;
+        fac = 10;
         outCoord = {outCoord.name(), "1/nm"};
     } else if (outCoord.unit() == "deg") {
         fac = pi / 180.;
diff --git a/auto/Examples/fit/specular/Pt_layer_fit.py b/auto/Examples/fit/specular/Pt_layer_fit.py
index a9b82577a8b..370ac7da945 100755
--- a/auto/Examples/fit/specular/Pt_layer_fit.py
+++ b/auto/Examples/fit/specular/Pt_layer_fit.py
@@ -56,44 +56,18 @@ def get_simulation(q_axis, P):
 
     return simulation
 
-####################################################################
-#  Experimental data
-####################################################################
-
-def load_data(filename, qmin, qmax):
-    filepath = os.path.join(datadir, filename)
-    data = np.genfromtxt(filepath, unpack=True)
-
-    r0 = np.where(data[0] - np.roll(data[0], 1) == 0)
-    data = np.delete(data, r0, 1)
-
-    data[0] = data[0]/angstrom
-    data[3] = data[3]/angstrom
-
-    data[1] = data[1]
-    data[2] = data[2]
-
-    so = np.argsort(data[0])
-
-    data = data[:, so]
-
-    minIndex = np.argmin(np.abs(data[0] - qmin))
-    maxIndex = np.argmin(np.abs(data[0] - qmax))
-
-    return data[:, minIndex:maxIndex + 1]
-
 ####################################################################
 #  Plotting
 ####################################################################
 
-def plot(q, r, exp, P):
+def plot(q, r, data, P):
     fig = plt.figure()
     ax = fig.add_subplot(111)
 
-    ax.errorbar(exp[0],
-                exp[1],
-                xerr=exp[3],
-                yerr=exp[2],
+    ax.errorbar(data.npXcenters(),
+                data.npArray(),
+                # xerr=data.xxx, TODO restore
+                yerr=data.npErrors(),
                 label="R",
                 fmt='.',
                 markersize=1.,
@@ -143,25 +117,22 @@ if __name__ == '__main__':
 
     qmin = 0.18
     qmax = 2.4
-
-    data = load_data("specular/RvsQ_36563_36662.dat.gz", qmin, qmax)
-
     qzs = np.linspace(qmin, qmax, 1500)
 
-    # Plot data with initial model:
+    fpath = os.path.join(datadir, "specular/RvsQ_36563_36662.dat.gz")
+    flags = ba.ImportSettings1D("q (1/angstrom)", "#", "", 1, 2, 3, 4)
+    data = ba.readData1D(fpath, ba.csv1D, flags)
 
     r = get_simulation(qzs, initialP | fixedP).simulate().npArray()
     plot(qzs, r, data, initialP)
 
     # Fit:
 
-    Q, R, dR = (data[0], data[1], data[2])
-
     fit_objective = ba.FitObjective()
     fit_objective.setObjectiveMetric("chi2")
     fit_objective.initPrint(10)
-    fit_objective.addSimulationAndData(
-        lambda P: get_simulation(Q, P | fixedP), R, dR, 1)
+    fit_objective.addFitPair(
+        lambda P: get_simulation(data.npXcenters(), P | fixedP), data, 1)
 
     P = ba.Parameters()
     for name, p in startPnB.items():
diff --git a/auto/MiniExamples/fit/specular/Pt_layer_fit.py b/auto/MiniExamples/fit/specular/Pt_layer_fit.py
index b64d78e7e08..256101529dc 100755
--- a/auto/MiniExamples/fit/specular/Pt_layer_fit.py
+++ b/auto/MiniExamples/fit/specular/Pt_layer_fit.py
@@ -56,44 +56,18 @@ def get_simulation(q_axis, P):
 
     return simulation
 
-####################################################################
-#  Experimental data
-####################################################################
-
-def load_data(filename, qmin, qmax):
-    filepath = os.path.join(datadir, filename)
-    data = np.genfromtxt(filepath, unpack=True)
-
-    r0 = np.where(data[0] - np.roll(data[0], 1) == 0)
-    data = np.delete(data, r0, 1)
-
-    data[0] = data[0]/angstrom
-    data[3] = data[3]/angstrom
-
-    data[1] = data[1]
-    data[2] = data[2]
-
-    so = np.argsort(data[0])
-
-    data = data[:, so]
-
-    minIndex = np.argmin(np.abs(data[0] - qmin))
-    maxIndex = np.argmin(np.abs(data[0] - qmax))
-
-    return data[:, minIndex:maxIndex + 1]
-
 ####################################################################
 #  Plotting
 ####################################################################
 
-def plot(q, r, exp, P):
+def plot(q, r, data, P):
     fig = plt.figure()
     ax = fig.add_subplot(111)
 
-    ax.errorbar(exp[0],
-                exp[1],
-                xerr=exp[3],
-                yerr=exp[2],
+    ax.errorbar(data.npXcenters(),
+                data.npArray(),
+                # xerr=data.xxx, TODO restore
+                yerr=data.npErrors(),
                 label="R",
                 fmt='.',
                 markersize=1.,
@@ -143,25 +117,22 @@ if __name__ == '__main__':
 
     qmin = 0.18
     qmax = 2.4
-
-    data = load_data("specular/RvsQ_36563_36662.dat.gz", qmin, qmax)
-
     qzs = np.linspace(qmin, qmax, 1500)
 
-    # Plot data with initial model:
+    fpath = os.path.join(datadir, "specular/RvsQ_36563_36662.dat.gz")
+    flags = ba.ImportSettings1D("q (1/angstrom)", "#", "", 1, 2, 3, 4)
+    data = ba.readData1D(fpath, ba.csv1D, flags)
 
     r = get_simulation(qzs, initialP | fixedP).simulate().npArray()
     plot(qzs, r, data, initialP)
 
     # Fit:
 
-    Q, R, dR = (data[0], data[1], data[2])
-
     fit_objective = ba.FitObjective()
     fit_objective.setObjectiveMetric("chi2")
     fit_objective.initPrint(10)
-    fit_objective.addSimulationAndData(
-        lambda P: get_simulation(Q, P | fixedP), R, dR, 1)
+    fit_objective.addFitPair(
+        lambda P: get_simulation(data.npXcenters(), P | fixedP), data, 1)
 
     P = ba.Parameters()
     for name, p in startPnB.items():
diff --git a/rawEx/fit/specular/Pt_layer_fit.py b/rawEx/fit/specular/Pt_layer_fit.py
index 0d0b68d4383..6636ac21c0d 100755
--- a/rawEx/fit/specular/Pt_layer_fit.py
+++ b/rawEx/fit/specular/Pt_layer_fit.py
@@ -56,44 +56,18 @@ def get_simulation(q_axis, P):
 
     return simulation
 
-####################################################################
-#  Experimental data
-####################################################################
-
-def load_data(filename, qmin, qmax):
-    filepath = os.path.join(datadir, filename)
-    data = np.genfromtxt(filepath, unpack=True)
-
-    r0 = np.where(data[0] - np.roll(data[0], 1) == 0)
-    data = np.delete(data, r0, 1)
-
-    data[0] = data[0]/angstrom
-    data[3] = data[3]/angstrom
-
-    data[1] = data[1]
-    data[2] = data[2]
-
-    so = np.argsort(data[0])
-
-    data = data[:, so]
-
-    minIndex = np.argmin(np.abs(data[0] - qmin))
-    maxIndex = np.argmin(np.abs(data[0] - qmax))
-
-    return data[:, minIndex:maxIndex + 1]
-
 ####################################################################
 #  Plotting
 ####################################################################
 
-def plot(q, r, exp, P):
+def plot(q, r, data, P):
     fig = plt.figure()
     ax = fig.add_subplot(111)
 
-    ax.errorbar(exp[0],
-                exp[1],
-                xerr=exp[3],
-                yerr=exp[2],
+    ax.errorbar(data.npXcenters(),
+                data.npArray(),
+                # xerr=data.xxx, TODO restore
+                yerr=data.npErrors(),
                 label="R",
                 fmt='.',
                 markersize=1.,
@@ -143,25 +117,22 @@ if __name__ == '__main__':
 
     qmin = 0.18
     qmax = 2.4
-
-    data = load_data("specular/RvsQ_36563_36662.dat.gz", qmin, qmax)
-
     qzs = np.linspace(qmin, qmax, 1500)
 
-    # Plot data with initial model:
+    fpath = os.path.join(datadir, "specular/RvsQ_36563_36662.dat.gz")
+    flags = ba.ImportSettings1D("q (1/angstrom)", "#", "", 1, 2, 3, 4)
+    data = ba.readData1D(fpath, ba.csv1D, flags)
 
     r = get_simulation(qzs, initialP | fixedP).simulate().npArray()
     plot(qzs, r, data, initialP)
 
     # Fit:
 
-    Q, R, dR = (data[0], data[1], data[2])
-
     fit_objective = ba.FitObjective()
     fit_objective.setObjectiveMetric("chi2")
     fit_objective.initPrint(10)
-    fit_objective.addSimulationAndData(
-        lambda P: get_simulation(Q, P | fixedP), R, dR, 1)
+    fit_objective.addFitPair(
+        lambda P: get_simulation(data.npXcenters(), P | fixedP), data, 1)
 
     P = ba.Parameters()
     for name, p in startPnB.items():
-- 
GitLab


From 1ecbef262bc287b71a735c0c44fe4def637a600b Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Tue, 26 Sep 2023 10:02:32 +0200
Subject: [PATCH 2/6] + parameter intensity

---
 auto/Examples/fit/specular/Pt_layer_fit.py     | 2 ++
 auto/MiniExamples/fit/specular/Pt_layer_fit.py | 2 ++
 rawEx/fit/specular/Pt_layer_fit.py             | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/auto/Examples/fit/specular/Pt_layer_fit.py b/auto/Examples/fit/specular/Pt_layer_fit.py
index 370ac7da945..81b1a746674 100755
--- a/auto/Examples/fit/specular/Pt_layer_fit.py
+++ b/auto/Examples/fit/specular/Pt_layer_fit.py
@@ -47,6 +47,7 @@ def get_simulation(q_axis, P):
     sample = get_sample(P)
 
     scan = ba.QzScan(q_axis)
+    scan.setIntensity(P["intensity"])
     scan.setOffset(P["q_offset"])
 
     distr = ba.DistributionGaussian(0., 1., 25, 4.)
@@ -103,6 +104,7 @@ if __name__ == '__main__':
     }
 
     startPnB = {
+        "intensity": (1., 0.7, 1.3),
         "q_offset": (0.01, -0.02, 0.02),
         "q_res/q": (0.01, 0, 0.02),
         "t_pt/nm": (50, 45, 55),
diff --git a/auto/MiniExamples/fit/specular/Pt_layer_fit.py b/auto/MiniExamples/fit/specular/Pt_layer_fit.py
index 256101529dc..4f3bba2f104 100755
--- a/auto/MiniExamples/fit/specular/Pt_layer_fit.py
+++ b/auto/MiniExamples/fit/specular/Pt_layer_fit.py
@@ -47,6 +47,7 @@ def get_simulation(q_axis, P):
     sample = get_sample(P)
 
     scan = ba.QzScan(q_axis)
+    scan.setIntensity(P["intensity"])
     scan.setOffset(P["q_offset"])
 
     distr = ba.DistributionGaussian(0., 1., 25, 4.)
@@ -103,6 +104,7 @@ if __name__ == '__main__':
     }
 
     startPnB = {
+        "intensity": (1., 0.7, 1.3),
         "q_offset": (0.01, -0.02, 0.02),
         "q_res/q": (0.01, 0, 0.02),
         "t_pt/nm": (50, 45, 55),
diff --git a/rawEx/fit/specular/Pt_layer_fit.py b/rawEx/fit/specular/Pt_layer_fit.py
index 6636ac21c0d..70a25952906 100755
--- a/rawEx/fit/specular/Pt_layer_fit.py
+++ b/rawEx/fit/specular/Pt_layer_fit.py
@@ -47,6 +47,7 @@ def get_simulation(q_axis, P):
     sample = get_sample(P)
 
     scan = ba.QzScan(q_axis)
+    scan.setIntensity(P["intensity"])
     scan.setOffset(P["q_offset"])
 
     distr = ba.DistributionGaussian(0., 1., 25, 4.)
@@ -103,6 +104,7 @@ if __name__ == '__main__':
     }
 
     startPnB = {
+        "intensity": (1., 0.8, 1.2),
         "q_offset": (0.01, -0.02, 0.02),
         "q_res/q": (0.01, 0, 0.02),
         "t_pt/nm": (50, 45, 55),
-- 
GitLab


From 31381d375bb432d0b2e882af22e59ac214e8f34a Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Tue, 26 Sep 2023 10:14:37 +0200
Subject: [PATCH 3/6] Datafield::crop[2] no longer delete error bars

---
 Device/Data/Datafield.cpp                      | 16 +++++++++++-----
 auto/Examples/fit/specular/Pt_layer_fit.py     |  8 +++++++-
 auto/MiniExamples/fit/specular/Pt_layer_fit.py |  8 +++++++-
 rawEx/fit/specular/Pt_layer_fit.py             |  6 ++++++
 4 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/Device/Data/Datafield.cpp b/Device/Data/Datafield.cpp
index 08038dc68f1..6ab5ce4a88b 100644
--- a/Device/Data/Datafield.cpp
+++ b/Device/Data/Datafield.cpp
@@ -273,14 +273,20 @@ Datafield* Datafield::crop(double xmin, double xmax) const
 {
     const auto xclipped = std::make_unique<Scale>(xAxis().clipped(xmin, xmax));
 
-    std::vector<double> out(size());
+    const size_t N = size();
+    std::vector<double> out(N);
+    std::vector<double> errout(hasErrorSigmas() ? N : 0);
     size_t iout = 0;
-    for (size_t i = 0; i < size(); ++i) {
+    for (size_t i = 0; i < N; ++i) {
         const double x = frame().projectedCoord(i, 0);
-        if (xclipped->rangeComprises(x))
-            out[iout++] = m_values[i];
+        if (xclipped->rangeComprises(x)) {
+            out[iout] = m_values[i];
+            if (hasErrorSigmas())
+                errout[iout] = m_errSigmas[i];
+            ++iout;
+        }
     }
-    return new Datafield(frame().clone(), out);
+    return new Datafield(frame().clone(), out, errout);
 }
 
 #ifdef BORNAGAIN_PYTHON
diff --git a/auto/Examples/fit/specular/Pt_layer_fit.py b/auto/Examples/fit/specular/Pt_layer_fit.py
index 81b1a746674..bd4f17520fe 100755
--- a/auto/Examples/fit/specular/Pt_layer_fit.py
+++ b/auto/Examples/fit/specular/Pt_layer_fit.py
@@ -104,7 +104,7 @@ if __name__ == '__main__':
     }
 
     startPnB = {
-        "intensity": (1., 0.7, 1.3),
+        "intensity": (1., 0.8, 1.2),
         "q_offset": (0.01, -0.02, 0.02),
         "q_res/q": (0.01, 0, 0.02),
         "t_pt/nm": (50, 45, 55),
@@ -125,9 +125,15 @@ if __name__ == '__main__':
     flags = ba.ImportSettings1D("q (1/angstrom)", "#", "", 1, 2, 3, 4)
     data = ba.readData1D(fpath, ba.csv1D, flags)
 
+    # Initial plot
+
     r = get_simulation(qzs, initialP | fixedP).simulate().npArray()
     plot(qzs, r, data, initialP)
 
+    # Restrict data to given q range
+
+    data = data.crop(qmin, qmax)
+
     # Fit:
 
     fit_objective = ba.FitObjective()
diff --git a/auto/MiniExamples/fit/specular/Pt_layer_fit.py b/auto/MiniExamples/fit/specular/Pt_layer_fit.py
index 4f3bba2f104..3a32ac836a5 100755
--- a/auto/MiniExamples/fit/specular/Pt_layer_fit.py
+++ b/auto/MiniExamples/fit/specular/Pt_layer_fit.py
@@ -104,7 +104,7 @@ if __name__ == '__main__':
     }
 
     startPnB = {
-        "intensity": (1., 0.7, 1.3),
+        "intensity": (1., 0.8, 1.2),
         "q_offset": (0.01, -0.02, 0.02),
         "q_res/q": (0.01, 0, 0.02),
         "t_pt/nm": (50, 45, 55),
@@ -125,9 +125,15 @@ if __name__ == '__main__':
     flags = ba.ImportSettings1D("q (1/angstrom)", "#", "", 1, 2, 3, 4)
     data = ba.readData1D(fpath, ba.csv1D, flags)
 
+    # Initial plot
+
     r = get_simulation(qzs, initialP | fixedP).simulate().npArray()
     plot(qzs, r, data, initialP)
 
+    # Restrict data to given q range
+
+    data = data.crop(qmin, qmax)
+
     # Fit:
 
     fit_objective = ba.FitObjective()
diff --git a/rawEx/fit/specular/Pt_layer_fit.py b/rawEx/fit/specular/Pt_layer_fit.py
index 70a25952906..bae2abf7f92 100755
--- a/rawEx/fit/specular/Pt_layer_fit.py
+++ b/rawEx/fit/specular/Pt_layer_fit.py
@@ -125,9 +125,15 @@ if __name__ == '__main__':
     flags = ba.ImportSettings1D("q (1/angstrom)", "#", "", 1, 2, 3, 4)
     data = ba.readData1D(fpath, ba.csv1D, flags)
 
+    # Initial plot
+
     r = get_simulation(qzs, initialP | fixedP).simulate().npArray()
     plot(qzs, r, data, initialP)
 
+    # Restrict data to given q range
+
+    data = data.crop(qmin, qmax)
+
     # Fit:
 
     fit_objective = ba.FitObjective()
-- 
GitLab


From 963da40c19bd6d3cf99341e1cdb4d5fb854ddea5 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Tue, 26 Sep 2023 11:42:24 +0200
Subject: [PATCH 4/6] correct Datafield::crop[2]

---
 Base/Axis/Frame.cpp       |  6 ++++++
 Base/Axis/Frame.h         |  1 +
 Base/Types/OwningVector.h | 13 ++++++++++---
 Device/Data/Datafield.cpp | 27 ++++++++++++++++++---------
 4 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/Base/Axis/Frame.cpp b/Base/Axis/Frame.cpp
index 38847e0d0f0..ddc66982a76 100644
--- a/Base/Axis/Frame.cpp
+++ b/Base/Axis/Frame.cpp
@@ -165,3 +165,9 @@ Frame* Frame::flat() const
             outaxes.emplace_back(s->clone());
     return new Frame(std::move(outaxes));
 }
+
+void Frame::setScale(size_t k_axis, Scale* scale)
+{
+    m_axes.replace_at(k_axis, scale);
+    m_size = FrameUtil::product_size(m_axes.reference());
+}
diff --git a/Base/Axis/Frame.h b/Base/Axis/Frame.h
index 58215319a14..5cbc1e9d9ed 100644
--- a/Base/Axis/Frame.h
+++ b/Base/Axis/Frame.h
@@ -83,6 +83,7 @@ public:
     Frame* flat() const;
 
 #ifndef SWIG
+    void setScale(size_t k_axis, Scale* scale);
     std::vector<const Scale*> clonedAxes() const;
 
 private:
diff --git a/Base/Types/OwningVector.h b/Base/Types/OwningVector.h
index bac97140c22..ca8e04b40c2 100644
--- a/Base/Types/OwningVector.h
+++ b/Base/Types/OwningVector.h
@@ -18,6 +18,7 @@
 #ifndef BORNAGAIN_BASE_TYPES_OWNINGVECTOR_H
 #define BORNAGAIN_BASE_TYPES_OWNINGVECTOR_H
 
+#include "Base/Util/Assert.h"
 #include <cstddef>
 #include <utility>
 #include <vector>
@@ -45,9 +46,6 @@ public:
     OwningVector& operator=(OwningVector&& other) = default;
 
     void reserve(size_t n) { m_v.reserve(n); }
-    void emplace_back(T* e) { m_v.emplace_back(e); }
-    void insert_at(size_t index, T* e) { m_v.insert(m_v.begin() + index, e); }
-
     void clear()
     {
         for (T* e : *this)
@@ -82,6 +80,15 @@ public:
         m_v.erase(m_v.begin() + i);
         return result;
     }
+    void emplace_back(T* e) { m_v.emplace_back(e); }
+    void insert_at(size_t i, T* e) { m_v.insert(m_v.begin() + i, e); }
+    void replace_at(size_t i, T* e)
+    {
+        ASSERT(i < m_v.size());
+        delete m_v[i];
+        m_v[i] = e;
+    }
+
 
     T* release_back()
     {
diff --git a/Device/Data/Datafield.cpp b/Device/Data/Datafield.cpp
index 6ab5ce4a88b..e1429ba1347 100644
--- a/Device/Data/Datafield.cpp
+++ b/Device/Data/Datafield.cpp
@@ -255,6 +255,7 @@ double Datafield::minVal() const
 
 Datafield* Datafield::crop(double xmin, double ymin, double xmax, double ymax) const
 {
+    ASSERT(false); // needs renovation, similar to Datafield::crop(double xmin, double xmax)
     const auto xclipped = std::make_unique<Scale>(xAxis().clipped(xmin, xmax));
     const auto yclipped = std::make_unique<Scale>(yAxis().clipped(ymin, ymax));
 
@@ -271,22 +272,30 @@ Datafield* Datafield::crop(double xmin, double ymin, double xmax, double ymax) c
 
 Datafield* Datafield::crop(double xmin, double xmax) const
 {
-    const auto xclipped = std::make_unique<Scale>(xAxis().clipped(xmin, xmax));
+    std::vector<Bin1D> outbins;
+    for (size_t i = 0; i < xAxis().size(); ++i) {
+        const double x = xAxis().binCenter(i);
+        if (xmin <= x && x <= xmax)
+            outbins.push_back(xAxis().bin(i));
+    }
+
+    auto* xclipped = new Scale(xAxis().axisLabel(), outbins);
 
     const size_t N = size();
-    std::vector<double> out(N);
-    std::vector<double> errout(hasErrorSigmas() ? N : 0);
-    size_t iout = 0;
+    std::vector<double> out;
+    std::vector<double> errout;
     for (size_t i = 0; i < N; ++i) {
         const double x = frame().projectedCoord(i, 0);
-        if (xclipped->rangeComprises(x)) {
-            out[iout] = m_values[i];
+        if (xmin <= x && x <= xmax) {
+            out.push_back(m_values[i]);
             if (hasErrorSigmas())
-                errout[iout] = m_errSigmas[i];
-            ++iout;
+                errout.push_back(m_errSigmas[i]);
         }
     }
-    return new Datafield(frame().clone(), out, errout);
+    Frame* outframe = frame().clone();
+    outframe->setScale(0, xclipped);
+    ASSERT(outframe->xAxis().size() == out.size());
+    return new Datafield(outframe, out, errout);
 }
 
 #ifdef BORNAGAIN_PYTHON
-- 
GitLab


From 2092565ba54802371c8011f4080c5a5b1932d792 Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Tue, 26 Sep 2023 12:08:22 +0200
Subject: [PATCH 5/6] accelerate Honeycomb example to allow fast testing

---
 auto/Examples/fit/specular/Honeycomb_fit.py   | 33 ++++++++++---------
 .../fit/specular/Honeycomb_fit.py             | 29 ++++++++--------
 rawEx/fit/specular/Honeycomb_fit.py           | 33 ++++++++++---------
 3 files changed, 49 insertions(+), 46 deletions(-)

diff --git a/auto/Examples/fit/specular/Honeycomb_fit.py b/auto/Examples/fit/specular/Honeycomb_fit.py
index 13020d2e508..ce43c300624 100755
--- a/auto/Examples/fit/specular/Honeycomb_fit.py
+++ b/auto/Examples/fit/specular/Honeycomb_fit.py
@@ -143,7 +143,7 @@ def plot(q, rs, exps, shifts, labels):
     plt.ylabel("R")
 
     plt.tight_layout()
-    plt.close()
+    #plt.close()
 
 
 def plot_sld_profile(P):
@@ -164,7 +164,7 @@ def plot_sld_profile(P):
 
     plt.legend()
     plt.tight_layout()
-    plt.close()
+    #plt.close()
 
 ####################################################################
 #  Main
@@ -181,18 +181,6 @@ if __name__ == '__main__':
         "t_Py2": (56, 46, 66),
         "t_Py1": (56, 46, 66),
         "t_SiO2": (22, 15, 29),
-        "sld_PyOx_real": (1.995, 1.92, 2.07),
-        "sld_Py2_real": (5, 4.7, 5.3),
-        "sld_Py1_real": (4.62, 4.32, 4.92),
-        "rPyOx": (27, 15, 35),
-        "rPy2": (12, 2, 20),
-        "rPy1": (12, 2, 20),
-        "rSiO2": (15, 5, 25),
-        "rSi": (15, 5, 25),
-        "msld_PyOx": (0.25, 0, 1),
-        "msld_Py2": (0.63, 0, 1),
-        "msld_Py1": (0.64, 0, 1),
-        "ms150": (1.05, 1.0, 1.1),
     }
 
     # For fixed parameters, bounds are ignored. We leave them here just
@@ -206,6 +194,19 @@ if __name__ == '__main__':
         "sld_SiO2_real": (3.47, 3, 4),
         "sld_Si_real": (2.0704, 2, 3),
         "dq": (0.018, 0, 0.1),
+    # Start by moving the following back to startPnB:
+        "sld_PyOx_real": (1.995, 1.92, 2.07),
+        "sld_Py2_real": (5, 4.7, 5.3),
+        "sld_Py1_real": (4.62, 4.32, 4.92),
+        "rPyOx": (27, 15, 35),
+        "rPy2": (12, 2, 20),
+        "rPy1": (12, 2, 20),
+        "rSiO2": (15, 5, 25),
+        "rSi": (15, 5, 25),
+        "msld_PyOx": (0.25, 0, 1),
+        "msld_Py2": (0.63, 0, 1),
+        "msld_Py1": (0.64, 0, 1),
+        "ms150": (1.05, 1.0, 1.1),
     }
 
     fixedP = {d: v[0] for d, v in fixedPnB.items()}
@@ -261,8 +262,8 @@ if __name__ == '__main__':
     result = scipy.optimize.differential_evolution(
         objective_function,
         bounds,
-        maxiter=500,
-        popsize=10,
+        maxiter=5,
+        popsize=3,
         tol=1e-2,
         mutation=(0.5, 1.5),
         seed=0,
diff --git a/auto/MiniExamples/fit/specular/Honeycomb_fit.py b/auto/MiniExamples/fit/specular/Honeycomb_fit.py
index c6cbc5a32c6..fa2a12e826b 100755
--- a/auto/MiniExamples/fit/specular/Honeycomb_fit.py
+++ b/auto/MiniExamples/fit/specular/Honeycomb_fit.py
@@ -143,7 +143,7 @@ def plot(q, rs, exps, shifts, labels):
     plt.ylabel("R")
 
     #plt.tight_layout()
-    #plt.close()
+    ##plt.close()
 
 
 def plot_sld_profile(P):
@@ -164,7 +164,7 @@ def plot_sld_profile(P):
 
     plt.legend()
     #plt.tight_layout()
-    #plt.close()
+    ##plt.close()
 
 ####################################################################
 #  Main
@@ -181,18 +181,6 @@ if __name__ == '__main__':
         "t_Py2": (56, 46, 66),
         "t_Py1": (56, 46, 66),
         "t_SiO2": (22, 15, 29),
-        "sld_PyOx_real": (1.995, 1.92, 2.07),
-        "sld_Py2_real": (5, 4.7, 5.3),
-        "sld_Py1_real": (4.62, 4.32, 4.92),
-        "rPyOx": (27, 15, 35),
-        "rPy2": (12, 2, 20),
-        "rPy1": (12, 2, 20),
-        "rSiO2": (15, 5, 25),
-        "rSi": (15, 5, 25),
-        "msld_PyOx": (0.25, 0, 1),
-        "msld_Py2": (0.63, 0, 1),
-        "msld_Py1": (0.64, 0, 1),
-        "ms150": (1.05, 1.0, 1.1),
     }
 
     # For fixed parameters, bounds are ignored. We leave them here just
@@ -206,6 +194,19 @@ if __name__ == '__main__':
         "sld_SiO2_real": (3.47, 3, 4),
         "sld_Si_real": (2.0704, 2, 3),
         "dq": (0.018, 0, 0.1),
+    # Start by moving the following back to startPnB:
+        "sld_PyOx_real": (1.995, 1.92, 2.07),
+        "sld_Py2_real": (5, 4.7, 5.3),
+        "sld_Py1_real": (4.62, 4.32, 4.92),
+        "rPyOx": (27, 15, 35),
+        "rPy2": (12, 2, 20),
+        "rPy1": (12, 2, 20),
+        "rSiO2": (15, 5, 25),
+        "rSi": (15, 5, 25),
+        "msld_PyOx": (0.25, 0, 1),
+        "msld_Py2": (0.63, 0, 1),
+        "msld_Py1": (0.64, 0, 1),
+        "ms150": (1.05, 1.0, 1.1),
     }
 
     fixedP = {d: v[0] for d, v in fixedPnB.items()}
diff --git a/rawEx/fit/specular/Honeycomb_fit.py b/rawEx/fit/specular/Honeycomb_fit.py
index 7135c1efc2f..95b5c3ab50f 100755
--- a/rawEx/fit/specular/Honeycomb_fit.py
+++ b/rawEx/fit/specular/Honeycomb_fit.py
@@ -143,7 +143,7 @@ def plot(q, rs, exps, shifts, labels):
     plt.ylabel("R")
 
     <%= sm ? "#" : "" %>plt.tight_layout()
-    <%= sm ? "#" : "" %>plt.close()
+    #<%= sm ? "#" : "" %>plt.close()
 
 
 def plot_sld_profile(P):
@@ -164,7 +164,7 @@ def plot_sld_profile(P):
 
     plt.legend()
     <%= sm ? "#" : "" %>plt.tight_layout()
-    <%= sm ? "#" : "" %>plt.close()
+    #<%= sm ? "#" : "" %>plt.close()
 
 ####################################################################
 #  Main
@@ -181,18 +181,6 @@ if __name__ == '__main__':
         "t_Py2": (56, 46, 66),
         "t_Py1": (56, 46, 66),
         "t_SiO2": (22, 15, 29),
-        "sld_PyOx_real": (1.995, 1.92, 2.07),
-        "sld_Py2_real": (5, 4.7, 5.3),
-        "sld_Py1_real": (4.62, 4.32, 4.92),
-        "rPyOx": (27, 15, 35),
-        "rPy2": (12, 2, 20),
-        "rPy1": (12, 2, 20),
-        "rSiO2": (15, 5, 25),
-        "rSi": (15, 5, 25),
-        "msld_PyOx": (0.25, 0, 1),
-        "msld_Py2": (0.63, 0, 1),
-        "msld_Py1": (0.64, 0, 1),
-        "ms150": (1.05, 1.0, 1.1),
     }
 
     # For fixed parameters, bounds are ignored. We leave them here just
@@ -206,6 +194,19 @@ if __name__ == '__main__':
         "sld_SiO2_real": (3.47, 3, 4),
         "sld_Si_real": (2.0704, 2, 3),
         "dq": (0.018, 0, 0.1),
+    # Start by moving the following back to startPnB:
+        "sld_PyOx_real": (1.995, 1.92, 2.07),
+        "sld_Py2_real": (5, 4.7, 5.3),
+        "sld_Py1_real": (4.62, 4.32, 4.92),
+        "rPyOx": (27, 15, 35),
+        "rPy2": (12, 2, 20),
+        "rPy1": (12, 2, 20),
+        "rSiO2": (15, 5, 25),
+        "rSi": (15, 5, 25),
+        "msld_PyOx": (0.25, 0, 1),
+        "msld_Py2": (0.63, 0, 1),
+        "msld_Py1": (0.64, 0, 1),
+        "ms150": (1.05, 1.0, 1.1),
     }
 
     fixedP = {d: v[0] for d, v in fixedPnB.items()}
@@ -261,8 +262,8 @@ if __name__ == '__main__':
     result = scipy.optimize.differential_evolution(
         objective_function,
         bounds,
-        maxiter=<%= sm ? 2 : 500 %>,
-        popsize=<%= sm ? 2 : 10 %>,
+        maxiter=<%= sm ? 2 : 5 %>, # for a serious DE fit, choose 500
+        popsize=<%= sm ? 2 : 3 %>, # for a serious DE fit, choose 10
         tol=1e-2,
         mutation=(0.5, 1.5),
         seed=0,
-- 
GitLab


From f571503d2d6b5cc6ee70b15030593b3b39d660ab Mon Sep 17 00:00:00 2001
From: Joachim Wuttke <j.wuttke@fz-juelich.de>
Date: Tue, 26 Sep 2023 12:24:30 +0200
Subject: [PATCH 6/6] units always in round parentheses

---
 GUI/Model/Model/ParameterTreeUtil.cpp                    | 2 +-
 GUI/View/MaterialEditor/MaterialEditorModel.cpp          | 2 +-
 GUI/View/Numeric/NumWidgetUtil.cpp                       | 2 +-
 GUI/View/SampleDesigner/LayerEditorUtil.cpp              | 2 +-
 auto/Examples/fit/specular/Honeycomb_fit.py              | 8 ++++----
 auto/Examples/fit/specular/PolarizedSpinAsymmetry.py     | 4 ++--
 auto/Examples/fit/specular/Pt_layer_fit.py               | 2 +-
 auto/Examples/specular/PolarizedSpinAsymmetry.py         | 4 ++--
 auto/MiniExamples/fit/specular/Honeycomb_fit.py          | 8 ++++----
 auto/MiniExamples/fit/specular/PolarizedSpinAsymmetry.py | 4 ++--
 auto/MiniExamples/fit/specular/Pt_layer_fit.py           | 2 +-
 auto/MiniExamples/specular/PolarizedSpinAsymmetry.py     | 4 ++--
 rawEx/fit/specular/Honeycomb_fit.py                      | 4 ++--
 rawEx/fit/specular/Pt_layer_fit.py                       | 2 +-
 rawEx/specular/PolarizedSpinAsymmetry.py                 | 4 ++--
 15 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/GUI/Model/Model/ParameterTreeUtil.cpp b/GUI/Model/Model/ParameterTreeUtil.cpp
index 9c3e106882c..54671288089 100644
--- a/GUI/Model/Model/ParameterTreeUtil.cpp
+++ b/GUI/Model/Model/ParameterTreeUtil.cpp
@@ -43,7 +43,7 @@ QString labelWithUnit(const QString& label, variant<QString, Unit> unit)
                                                             : unitAsString(std::get<Unit>(unit));
 
     if (!s.isEmpty())
-        return label + " [" + s + "]";
+        return label + " (" + s + ")";
 
     return label;
 }
diff --git a/GUI/View/MaterialEditor/MaterialEditorModel.cpp b/GUI/View/MaterialEditor/MaterialEditorModel.cpp
index 34138a5ca9f..3714fa455d6 100644
--- a/GUI/View/MaterialEditor/MaterialEditorModel.cpp
+++ b/GUI/View/MaterialEditor/MaterialEditorModel.cpp
@@ -48,7 +48,7 @@ QVariant MaterialEditorModel::headerData(int section, Qt::Orientation /*orientat
     case PARAMETERS:
         return "Material parameters";
     case MAGNETIZATION:
-        return "Magnetization [A/m]";
+        return "Magnetization (A/m)";
     default:
         return {};
     }
diff --git a/GUI/View/Numeric/NumWidgetUtil.cpp b/GUI/View/Numeric/NumWidgetUtil.cpp
index 68110dd28ba..0be3617e5fe 100644
--- a/GUI/View/Numeric/NumWidgetUtil.cpp
+++ b/GUI/View/Numeric/NumWidgetUtil.cpp
@@ -44,7 +44,7 @@ QString GUI::Util::labelWithUnit(const QString& label, variant<QString, Unit> un
     const QString s = std::holds_alternative<QString>(unit) ? std::get<QString>(unit)
                                                             : unitAsString(std::get<Unit>(unit));
     if (!s.isEmpty())
-        return label + " [" + s + "]";
+        return label + " (" + s + ")";
 
     return label;
 }
diff --git a/GUI/View/SampleDesigner/LayerEditorUtil.cpp b/GUI/View/SampleDesigner/LayerEditorUtil.cpp
index 2667f1380b8..dfb442e5874 100644
--- a/GUI/View/SampleDesigner/LayerEditorUtil.cpp
+++ b/GUI/View/SampleDesigner/LayerEditorUtil.cpp
@@ -46,7 +46,7 @@ void updateLabelUnit(QLabel* label, const QString& unit)
         text.chop(1);
 
     if (!unit.isEmpty())
-        text += " [" + unit + "]";
+        text += " (" + unit + ")";
     if (hasColon)
         text += ":";
     label->setText(text);
diff --git a/auto/Examples/fit/specular/Honeycomb_fit.py b/auto/Examples/fit/specular/Honeycomb_fit.py
index ce43c300624..9a9a01df3d4 100755
--- a/auto/Examples/fit/specular/Honeycomb_fit.py
+++ b/auto/Examples/fit/specular/Honeycomb_fit.py
@@ -139,7 +139,7 @@ def plot(q, rs, exps, shifts, labels):
     ax.set_yscale('log')
     plt.legend()
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("q (1/nm)")
     plt.ylabel("R")
 
     plt.tight_layout()
@@ -159,7 +159,7 @@ def plot_sld_profile(P):
     plt.plot(z_150p, np.real(sld_150p)*1e6, label=r"150K $+$")
     plt.plot(z_150m, np.real(sld_150m)*1e6, label=r"150K $-$")
 
-    plt.xlabel(r"$z$ [A]")
+    plt.xlabel(r"$z (\AA)$")
     plt.ylabel(r"$\delta(z) \cdot 10^6$")
 
     plt.legend()
@@ -262,8 +262,8 @@ if __name__ == '__main__':
     result = scipy.optimize.differential_evolution(
         objective_function,
         bounds,
-        maxiter=5,
-        popsize=3,
+        maxiter=5, # for a serious DE fit, choose 500
+        popsize=3, # for a serious DE fit, choose 10
         tol=1e-2,
         mutation=(0.5, 1.5),
         seed=0,
diff --git a/auto/Examples/fit/specular/PolarizedSpinAsymmetry.py b/auto/Examples/fit/specular/PolarizedSpinAsymmetry.py
index 91f3571438b..d859c5ea1d5 100755
--- a/auto/Examples/fit/specular/PolarizedSpinAsymmetry.py
+++ b/auto/Examples/fit/specular/PolarizedSpinAsymmetry.py
@@ -131,7 +131,7 @@ def plotData(qs, rs, exps, labels, colors):
     ax.set_yscale('log')
     plt.legend()
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("q (1/nm)")
     plt.ylabel("R")
 
     plt.tight_layout()
@@ -164,7 +164,7 @@ def plotSpinAsymmetry(data_pp, data_mm, q, r_pp, r_mm):
 
     plt.gca().set_ylim((-0.3, 0.5))
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("Q (1/nm)")
     plt.ylabel("Spin asymmetry")
 
     plt.tight_layout()
diff --git a/auto/Examples/fit/specular/Pt_layer_fit.py b/auto/Examples/fit/specular/Pt_layer_fit.py
index bd4f17520fe..1af4988e765 100755
--- a/auto/Examples/fit/specular/Pt_layer_fit.py
+++ b/auto/Examples/fit/specular/Pt_layer_fit.py
@@ -79,7 +79,7 @@ def plot(q, r, data, P):
 
     ax.set_yscale('log')
 
-    ax.set_xlabel("Q [nm$^{^-1}$]")
+    ax.set_xlabel("q (1/nm)")
     ax.set_ylabel("R")
 
     y = 0.5
diff --git a/auto/Examples/specular/PolarizedSpinAsymmetry.py b/auto/Examples/specular/PolarizedSpinAsymmetry.py
index 91f3571438b..d859c5ea1d5 100755
--- a/auto/Examples/specular/PolarizedSpinAsymmetry.py
+++ b/auto/Examples/specular/PolarizedSpinAsymmetry.py
@@ -131,7 +131,7 @@ def plotData(qs, rs, exps, labels, colors):
     ax.set_yscale('log')
     plt.legend()
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("q (1/nm)")
     plt.ylabel("R")
 
     plt.tight_layout()
@@ -164,7 +164,7 @@ def plotSpinAsymmetry(data_pp, data_mm, q, r_pp, r_mm):
 
     plt.gca().set_ylim((-0.3, 0.5))
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("Q (1/nm)")
     plt.ylabel("Spin asymmetry")
 
     plt.tight_layout()
diff --git a/auto/MiniExamples/fit/specular/Honeycomb_fit.py b/auto/MiniExamples/fit/specular/Honeycomb_fit.py
index fa2a12e826b..b07ea2c3d00 100755
--- a/auto/MiniExamples/fit/specular/Honeycomb_fit.py
+++ b/auto/MiniExamples/fit/specular/Honeycomb_fit.py
@@ -139,7 +139,7 @@ def plot(q, rs, exps, shifts, labels):
     ax.set_yscale('log')
     plt.legend()
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("q (1/nm)")
     plt.ylabel("R")
 
     #plt.tight_layout()
@@ -159,7 +159,7 @@ def plot_sld_profile(P):
     plt.plot(z_150p, np.real(sld_150p)*1e6, label=r"150K $+$")
     plt.plot(z_150m, np.real(sld_150m)*1e6, label=r"150K $-$")
 
-    plt.xlabel(r"$z$ [A]")
+    plt.xlabel(r"$z (\AA)$")
     plt.ylabel(r"$\delta(z) \cdot 10^6$")
 
     plt.legend()
@@ -262,8 +262,8 @@ if __name__ == '__main__':
     result = scipy.optimize.differential_evolution(
         objective_function,
         bounds,
-        maxiter=2,
-        popsize=2,
+        maxiter=2, # for a serious DE fit, choose 500
+        popsize=2, # for a serious DE fit, choose 10
         tol=1e-2,
         mutation=(0.5, 1.5),
         seed=0,
diff --git a/auto/MiniExamples/fit/specular/PolarizedSpinAsymmetry.py b/auto/MiniExamples/fit/specular/PolarizedSpinAsymmetry.py
index 0123529d57f..3185a2719f2 100755
--- a/auto/MiniExamples/fit/specular/PolarizedSpinAsymmetry.py
+++ b/auto/MiniExamples/fit/specular/PolarizedSpinAsymmetry.py
@@ -131,7 +131,7 @@ def plotData(qs, rs, exps, labels, colors):
     ax.set_yscale('log')
     plt.legend()
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("q (1/nm)")
     plt.ylabel("R")
 
     plt.tight_layout()
@@ -164,7 +164,7 @@ def plotSpinAsymmetry(data_pp, data_mm, q, r_pp, r_mm):
 
     plt.gca().set_ylim((-0.3, 0.5))
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("Q (1/nm)")
     plt.ylabel("Spin asymmetry")
 
     plt.tight_layout()
diff --git a/auto/MiniExamples/fit/specular/Pt_layer_fit.py b/auto/MiniExamples/fit/specular/Pt_layer_fit.py
index 3a32ac836a5..6370c896f52 100755
--- a/auto/MiniExamples/fit/specular/Pt_layer_fit.py
+++ b/auto/MiniExamples/fit/specular/Pt_layer_fit.py
@@ -79,7 +79,7 @@ def plot(q, r, data, P):
 
     ax.set_yscale('log')
 
-    ax.set_xlabel("Q [nm$^{^-1}$]")
+    ax.set_xlabel("q (1/nm)")
     ax.set_ylabel("R")
 
     y = 0.5
diff --git a/auto/MiniExamples/specular/PolarizedSpinAsymmetry.py b/auto/MiniExamples/specular/PolarizedSpinAsymmetry.py
index 0123529d57f..3185a2719f2 100755
--- a/auto/MiniExamples/specular/PolarizedSpinAsymmetry.py
+++ b/auto/MiniExamples/specular/PolarizedSpinAsymmetry.py
@@ -131,7 +131,7 @@ def plotData(qs, rs, exps, labels, colors):
     ax.set_yscale('log')
     plt.legend()
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("q (1/nm)")
     plt.ylabel("R")
 
     plt.tight_layout()
@@ -164,7 +164,7 @@ def plotSpinAsymmetry(data_pp, data_mm, q, r_pp, r_mm):
 
     plt.gca().set_ylim((-0.3, 0.5))
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("Q (1/nm)")
     plt.ylabel("Spin asymmetry")
 
     plt.tight_layout()
diff --git a/rawEx/fit/specular/Honeycomb_fit.py b/rawEx/fit/specular/Honeycomb_fit.py
index 95b5c3ab50f..dcb28876ff2 100755
--- a/rawEx/fit/specular/Honeycomb_fit.py
+++ b/rawEx/fit/specular/Honeycomb_fit.py
@@ -139,7 +139,7 @@ def plot(q, rs, exps, shifts, labels):
     ax.set_yscale('log')
     plt.legend()
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("q (1/nm)")
     plt.ylabel("R")
 
     <%= sm ? "#" : "" %>plt.tight_layout()
@@ -159,7 +159,7 @@ def plot_sld_profile(P):
     plt.plot(z_150p, np.real(sld_150p)*1e6, label=r"150K $+$")
     plt.plot(z_150m, np.real(sld_150m)*1e6, label=r"150K $-$")
 
-    plt.xlabel(r"$z$ [A]")
+    plt.xlabel(r"$z (\AA)$")
     plt.ylabel(r"$\delta(z) \cdot 10^6$")
 
     plt.legend()
diff --git a/rawEx/fit/specular/Pt_layer_fit.py b/rawEx/fit/specular/Pt_layer_fit.py
index bae2abf7f92..cc9200f3154 100755
--- a/rawEx/fit/specular/Pt_layer_fit.py
+++ b/rawEx/fit/specular/Pt_layer_fit.py
@@ -79,7 +79,7 @@ def plot(q, r, data, P):
 
     ax.set_yscale('log')
 
-    ax.set_xlabel("Q [nm$^{^-1}$]")
+    ax.set_xlabel("q (1/nm)")
     ax.set_ylabel("R")
 
     y = 0.5
diff --git a/rawEx/specular/PolarizedSpinAsymmetry.py b/rawEx/specular/PolarizedSpinAsymmetry.py
index 9378c689fd1..cba1b8ac600 100755
--- a/rawEx/specular/PolarizedSpinAsymmetry.py
+++ b/rawEx/specular/PolarizedSpinAsymmetry.py
@@ -131,7 +131,7 @@ def plotData(qs, rs, exps, labels, colors):
     ax.set_yscale('log')
     plt.legend()
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("q (1/nm)")
     plt.ylabel("R")
 
     plt.tight_layout()
@@ -164,7 +164,7 @@ def plotSpinAsymmetry(data_pp, data_mm, q, r_pp, r_mm):
 
     plt.gca().set_ylim((-0.3, 0.5))
 
-    plt.xlabel("Q [nm${}^{-1}$]")
+    plt.xlabel("Q (1/nm)")
     plt.ylabel("Spin asymmetry")
 
     plt.tight_layout()
-- 
GitLab