From 21fa30afd993390f4ba53da7137dacd6fec7a804 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Fri, 7 Jul 2023 16:08:10 +0200
Subject: [PATCH] reuse helper

---
 Base/Util/VectorUtil.cpp               |  8 ++++++++
 Base/Util/VectorUtil.h                 |  4 ++++
 Resample/Slice/ProfileHelper.cpp       |  7 ++-----
 Resample/Slice/ProfileHelper.h         |  5 ++---
 Resample/Swig/MultiLayerFuncs.cpp      | 24 ++++++++++++++----------
 auto/Examples/varia/MaterialProfile.py | 14 +++++++-------
 6 files changed, 37 insertions(+), 25 deletions(-)

diff --git a/Base/Util/VectorUtil.cpp b/Base/Util/VectorUtil.cpp
index 10746261374..4c46982a9cd 100644
--- a/Base/Util/VectorUtil.cpp
+++ b/Base/Util/VectorUtil.cpp
@@ -49,3 +49,11 @@ std::vector<double> VectorUtil::make_grid(std::size_t n, double first, double la
         result.push_back(first + i * (last - first) / (n - 1));
     return result;
 }
+
+std::vector<double> VectorUtil::real(const std::vector<complex_t>& v)
+{
+    std::vector<double> result(v.size());
+    for (size_t i = 0; i < v.size(); i++)
+        result[i] = real(v[i]);
+    return result;
+}
diff --git a/Base/Util/VectorUtil.h b/Base/Util/VectorUtil.h
index 9fe88a676c0..4d40c4e6f01 100644
--- a/Base/Util/VectorUtil.h
+++ b/Base/Util/VectorUtil.h
@@ -15,6 +15,7 @@
 #ifndef BORNAGAIN_BASE_UTIL_VECTORUTIL_H
 #define BORNAGAIN_BASE_UTIL_VECTORUTIL_H
 
+#include <heinz/Complex.h>
 #include <vector>
 
 namespace VectorUtil {
@@ -24,6 +25,9 @@ bool is_equidistant(const std::vector<double>& vec, double tol);
 
 std::vector<double> make_grid(std::size_t n, double first, double last);
 
+//! Returns vector of real parts.
+std::vector<double> real(const std::vector<complex_t>& v);
+
 } // namespace VectorUtil
 
 #endif // BORNAGAIN_BASE_UTIL_VECTORUTIL_H
diff --git a/Resample/Slice/ProfileHelper.cpp b/Resample/Slice/ProfileHelper.cpp
index 19c76a53dc5..f5f3322ff49 100644
--- a/Resample/Slice/ProfileHelper.cpp
+++ b/Resample/Slice/ProfileHelper.cpp
@@ -14,6 +14,7 @@
 
 #include "Resample/Slice/ProfileHelper.h"
 #include "Base/Util/Assert.h"
+#include "Base/Util/VectorUtil.h"
 #include "Resample/Slice/SliceStack.h"
 #include "Sample/Interface/LayerRoughness.h"
 #include <numbers>
@@ -100,11 +101,7 @@ std::vector<double> ProfileHelper::calculateMagneticProfile(const std::vector<do
         throw std::runtime_error("Incorrect magnetization component \"" + component + "\".\nOnly \""
                                  + X + "\", \"" + Y + "\" or \"" + Z + "\" are allowed.");
 
-    std::vector<complex_t> v = profile(z_values, component);
-    std::vector<double> result(v.size());
-    for (size_t i = 0; i < v.size(); i++)
-        result[i] = real(v[i]);
-    return result;
+    return VectorUtil::real(profile(z_values, component));
 }
 
 std::pair<double, double> ProfileHelper::defaultLimits() const
diff --git a/Resample/Slice/ProfileHelper.h b/Resample/Slice/ProfileHelper.h
index dfa57ea7c42..31953c0b10e 100644
--- a/Resample/Slice/ProfileHelper.h
+++ b/Resample/Slice/ProfileHelper.h
@@ -18,13 +18,12 @@
 #ifndef BORNAGAIN_RESAMPLE_SLICE_PROFILEHELPER_H
 #define BORNAGAIN_RESAMPLE_SLICE_PROFILEHELPER_H
 
+#include "Resample/Slice/SliceStack.h"
 #include "Sample/Material/Material.h"
 #include <utility>
 #include <variant>
 #include <vector>
 
-class SliceStack;
-
 //! Object that can generate the material profile of a sample as a function of depth.
 //!
 //! The generated profile contains the complex SLD for SLD materials and the parameters
@@ -45,7 +44,7 @@ private:
     std::vector<complex_t> profile(const std::vector<double>& z_values,
                                    std::string component) const;
 
-    const SliceStack& m_stack; // from Fresnel map
+    const SliceStack m_stack; // copy
 };
 
 #endif // BORNAGAIN_RESAMPLE_SLICE_PROFILEHELPER_H
diff --git a/Resample/Swig/MultiLayerFuncs.cpp b/Resample/Swig/MultiLayerFuncs.cpp
index 68b880fd6dd..d5ada075604 100644
--- a/Resample/Swig/MultiLayerFuncs.cpp
+++ b/Resample/Swig/MultiLayerFuncs.cpp
@@ -17,6 +17,18 @@
 #include "Resample/Processed/ReSample.h"
 #include "Resample/Slice/ProfileHelper.h"
 
+namespace {
+
+ProfileHelper helper(const MultiLayer& sample)
+{
+    SimulationOptions options;
+    options.setUseAvgMaterials(true);
+    const ReSample resample = ReSample::make(sample, options);
+    return ProfileHelper(resample.averageSlices());
+}
+
+} // namespace
+
 std::vector<double> swigAPI::generateZValues(int n_points, double z_min, double z_max)
 {
     std::vector<double> result;
@@ -31,23 +43,15 @@ std::vector<double> swigAPI::generateZValues(int n_points, double z_min, double
 std::vector<complex_t> swigAPI::materialProfileSLD(const MultiLayer& sample, int n_points,
                                                    double z_min, double z_max)
 {
-    SimulationOptions options;
-    options.setUseAvgMaterials(true);
-    const ReSample resample = ReSample::make(sample, options);
-    ProfileHelper helper(resample.averageSlices());
     std::vector<double> z_values = generateZValues(n_points, z_min, z_max);
-    return helper.calculateProfile(z_values);
+    return ::helper(sample).calculateProfile(z_values);
 }
 
 std::vector<double> swigAPI::magnetizationProfile(const MultiLayer& sample, std::string component,
                                                   int n_points, double z_min, double z_max)
 {
-    SimulationOptions options;
-    options.setUseAvgMaterials(true);
-    const ReSample resample = ReSample::make(sample, options);
-    ProfileHelper helper(resample.averageSlices());
     std::vector<double> z_values = generateZValues(n_points, z_min, z_max);
-    return helper.calculateMagneticProfile(z_values, component);
+    return ::helper(sample).calculateMagneticProfile(z_values, component);
 }
 
 std::pair<double, double> swigAPI::defaultMaterialProfileLimits(const MultiLayer& sample)
diff --git a/auto/Examples/varia/MaterialProfile.py b/auto/Examples/varia/MaterialProfile.py
index 80650e2ec17..bb2084f605b 100755
--- a/auto/Examples/varia/MaterialProfile.py
+++ b/auto/Examples/varia/MaterialProfile.py
@@ -38,17 +38,17 @@ def magnetizationProfile(sample, n_points=400, z_min=None, z_max=None):
     z_min = def_z_min if z_min is None else z_min
     z_max = def_z_max if z_max is None else z_max
     z_points = ba.generateZValues(n_points, z_min, z_max)
-    magnetization_values = ba.magnetizationProfile(sample, "w", n_points, z_min, z_max)
+    magnetization_values = ba.magnetizationProfile(sample, "X", n_points, z_min, z_max)
     return (z_points, magnetization_values)
 
 if __name__ == '__main__':
     sample = get_sample()
-    # zpoints, slds = sample_tools.materialProfile(sample, 400)
-    # plt.figure()
-    # plt.plot(zpoints, np.real(slds))
-
-    zpoints, mag = magnetizationProfile(sample, 400)
+    zpoints, slds = sample_tools.materialProfile(sample, 400)
     plt.figure()
-    plt.plot(zpoints, mag)
+    plt.plot(zpoints, np.real(slds))
+
+    # zpoints, mag = magnetizationProfile(sample, 400)
+    # plt.figure()
+    # plt.plot(zpoints, mag)
 
     bp.show_or_export()
-- 
GitLab