From 96ab73c5890ba44faba9b1e563e7a24b2a980234 Mon Sep 17 00:00:00 2001
From: Walter Van Herck <w.van.herck@fz-juelich.de>
Date: Wed, 10 Jul 2019 10:26:23 +0200
Subject: [PATCH] Move MaterialProfile function to separate file and expose it
 to Python API

---
 Core/Computation/MultiLayerUtils.cpp | 26 --------------
 Core/Computation/MultiLayerUtils.h   |  5 ---
 Core/Multilayer/MultiLayerFuncs.cpp  | 49 +++++++++++++++++++++++++
 Core/Multilayer/MultiLayerFuncs.h    | 31 ++++++++++++++++
 Wrap/swig/libBornAgainCore.i         |  2 ++
 auto/Wrap/libBornAgainCore.py        |  4 +++
 auto/Wrap/libBornAgainCore_wrap.cpp  | 54 ++++++++++++++++++++++++++++
 7 files changed, 140 insertions(+), 31 deletions(-)
 create mode 100644 Core/Multilayer/MultiLayerFuncs.cpp
 create mode 100644 Core/Multilayer/MultiLayerFuncs.h

diff --git a/Core/Computation/MultiLayerUtils.cpp b/Core/Computation/MultiLayerUtils.cpp
index c6c09e6a676..5f3019b7a4f 100644
--- a/Core/Computation/MultiLayerUtils.cpp
+++ b/Core/Computation/MultiLayerUtils.cpp
@@ -19,14 +19,10 @@
 #include "LayerInterface.h"
 #include "MaterialUtils.h"
 #include "MultiLayer.h"
-#include "ProcessedSample.h"
-#include "ProfileHelper.h"
-#include "SimulationOptions.h"
 
 namespace
 {
 std::vector<double> BottomLayerCoordinates(const MultiLayer& multilayer);
-std::vector<double> GenerateZValues(int n_points, double z_min, double z_max);
 } // namespace
 
 double MultiLayerUtils::LayerThickness(const MultiLayer& multilayer, size_t i)
@@ -87,17 +83,6 @@ std::vector<ZLimits> MultiLayerUtils::ParticleRegions(const MultiLayer& multilay
     return layer_fill_limits.layerZLimits();
 }
 
-std::vector<complex_t> MultiLayerUtils::MaterialProfile(const MultiLayer& multilayer, int n_points,
-                                                        double z_min, double z_max)
-{
-    SimulationOptions options;
-    options.setUseAvgMaterials(true);
-    ProcessedSample sample(multilayer, options);
-    ProfileHelper helper(sample);
-    std::vector<double> z_values = GenerateZValues(n_points, z_min, z_max);
-    return helper.calculateProfile(z_values);
-}
-
 namespace
 {
 std::vector<double> BottomLayerCoordinates(const MultiLayer& multilayer)
@@ -112,15 +97,4 @@ std::vector<double> BottomLayerCoordinates(const MultiLayer& multilayer)
     }
     return result;
 }
-std::vector<double> GenerateZValues(int n_points, double z_min, double z_max)
-{
-    std::vector<double> result;
-    if (n_points < 1)
-        return result;
-    double step = n_points > 1 ? (z_max - z_min) / (n_points - 1) : 0.0;
-    for (int i = 0; i < n_points; ++i) {
-        result.push_back(z_min + i * step);
-    }
-    return result;
-}
 } // unnamed namespace
diff --git a/Core/Computation/MultiLayerUtils.h b/Core/Computation/MultiLayerUtils.h
index d59eb159ad3..d4d41490aaa 100644
--- a/Core/Computation/MultiLayerUtils.h
+++ b/Core/Computation/MultiLayerUtils.h
@@ -15,7 +15,6 @@
 #ifndef MULTILAYERUTILS_H
 #define MULTILAYERUTILS_H
 
-#include "Complex.h"
 #include "WinDllMacros.h"
 #include <cstddef>
 #include <vector>
@@ -48,10 +47,6 @@ BA_CORE_API_ bool ContainsCompatibleMaterials(const MultiLayer& multilayer);
 
 //! Calculate z-regions occupied by particles
 BA_CORE_API_ std::vector<ZLimits> ParticleRegions(const MultiLayer& multilayer, bool use_slicing);
-
-//! Calculate average material profile for given multilayer
-BA_CORE_API_ std::vector<complex_t> MaterialProfile(const MultiLayer& multilayer, int n_points,
-                                                    double z_min, double z_max);
 } // namespace MultiLayerUtils
 
 #endif // MULTILAYERUTILS_H
diff --git a/Core/Multilayer/MultiLayerFuncs.cpp b/Core/Multilayer/MultiLayerFuncs.cpp
new file mode 100644
index 00000000000..0a202d62631
--- /dev/null
+++ b/Core/Multilayer/MultiLayerFuncs.cpp
@@ -0,0 +1,49 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Core/Material/MultiLayerFuncs.cpp
+//! @brief     Global functions related to MultiLayers.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2018
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+// ************************************************************************** //
+
+#include "MultiLayerFuncs.h"
+#include "ProcessedSample.h"
+#include "ProfileHelper.h"
+#include "SimulationOptions.h"
+
+namespace
+{
+std::vector<double> GenerateZValues(int n_points, double z_min, double z_max);
+} // namespace
+
+std::vector<complex_t> MaterialProfile(const MultiLayer& multilayer, int n_points, double z_min,
+                                       double z_max)
+{
+    SimulationOptions options;
+    options.setUseAvgMaterials(true);
+    ProcessedSample sample(multilayer, options);
+    ProfileHelper helper(sample);
+    std::vector<double> z_values = GenerateZValues(n_points, z_min, z_max);
+    return helper.calculateProfile(z_values);
+}
+
+namespace
+{
+std::vector<double> GenerateZValues(int n_points, double z_min, double z_max)
+{
+    std::vector<double> result;
+    if (n_points < 1)
+        return result;
+    double step = n_points > 1 ? (z_max - z_min) / (n_points - 1) : 0.0;
+    for (int i = 0; i < n_points; ++i) {
+        result.push_back(z_min + i * step);
+    }
+    return result;
+}
+} // unnamed namespace
diff --git a/Core/Multilayer/MultiLayerFuncs.h b/Core/Multilayer/MultiLayerFuncs.h
new file mode 100644
index 00000000000..79ba2bb4ab1
--- /dev/null
+++ b/Core/Multilayer/MultiLayerFuncs.h
@@ -0,0 +1,31 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Core/Material/MultiLayerFuncs.h
+//! @brief     Global functions related to MultiLayers.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2018
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+// ************************************************************************** //
+
+#ifndef MULTILAYERFUNCS_H_
+#define MULTILAYERFUNCS_H_
+
+#include "Complex.h"
+#include "WinDllMacros.h"
+#include <vector>
+
+class MultiLayer;
+
+//! @ingroup materials
+
+//! Calculate average material profile for given multilayer
+BA_CORE_API_ std::vector<complex_t> MaterialProfile(const MultiLayer& multilayer, int n_points,
+                                                    double z_min, double z_max);
+
+
+#endif // MULTILAYERFUNCS_H_
diff --git a/Wrap/swig/libBornAgainCore.i b/Wrap/swig/libBornAgainCore.i
index 974d4b0520c..e2e53b55fad 100644
--- a/Wrap/swig/libBornAgainCore.i
+++ b/Wrap/swig/libBornAgainCore.i
@@ -194,6 +194,7 @@
 #include "MathFunctions.h"
 #include "MesoCrystal.h"
 #include "MultiLayer.h"
+#include "MultiLayerFuncs.h"
 #include "OffSpecSimulation.h"
 #include "OutputData.h"
 #include "ParameterDistribution.h"
@@ -447,6 +448,7 @@
 %include "MaterialFactoryFuncs.h"
 %include "MesoCrystal.h"
 %include "MultiLayer.h"
+%include "MultiLayerFuncs.h"
 %include "OffSpecSimulation.h"
 %include "IIntensityFunction.h"
 %include "OutputData.h"
diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index beba795e4de..5d09ae2ca47 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -25365,6 +25365,10 @@ class MultiLayer(ISample):
 MultiLayer_swigregister = _libBornAgainCore.MultiLayer_swigregister
 MultiLayer_swigregister(MultiLayer)
 
+
+def MaterialProfile(multilayer, n_points, z_min, z_max):
+    """MaterialProfile(MultiLayer multilayer, int n_points, double z_min, double z_max) -> vector_complex_t"""
+    return _libBornAgainCore.MaterialProfile(multilayer, n_points, z_min, z_max)
 class OffSpecSimulation(Simulation2D):
     """
 
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index 8547cf4218d..53f02443a2b 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -7328,6 +7328,7 @@ SWIGINTERN void std_vector_Sl_std_pair_Sl_double_Sc_double_Sg__Sg__insert__SWIG_
 #include "MathFunctions.h"
 #include "MesoCrystal.h"
 #include "MultiLayer.h"
+#include "MultiLayerFuncs.h"
 #include "OffSpecSimulation.h"
 #include "OutputData.h"
 #include "ParameterDistribution.h"
@@ -107113,6 +107114,58 @@ SWIGINTERN PyObject *MultiLayer_swigregister(PyObject *SWIGUNUSEDPARM(self), PyO
   return SWIG_Py_Void();
 }
 
+SWIGINTERN PyObject *_wrap_MaterialProfile(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MultiLayer *arg1 = 0 ;
+  int arg2 ;
+  double arg3 ;
+  double arg4 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  std::vector< complex_t,std::allocator< complex_t > > result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:MaterialProfile",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1, SWIGTYPE_p_MultiLayer,  0  | 0);
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MaterialProfile" "', argument " "1"" of type '" "MultiLayer const &""'"); 
+  }
+  if (!argp1) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "MaterialProfile" "', argument " "1"" of type '" "MultiLayer const &""'"); 
+  }
+  arg1 = reinterpret_cast< MultiLayer * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "MaterialProfile" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_double(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "MaterialProfile" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "MaterialProfile" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  result = MaterialProfile((MultiLayer const &)*arg1,arg2,arg3,arg4);
+  resultobj = swig::from(static_cast< std::vector< std::complex< double >,std::allocator< std::complex< double > > > >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_new_OffSpecSimulation__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   OffSpecSimulation *result = 0 ;
@@ -137009,6 +137062,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		""},
 	 { (char *)"MultiLayer_swigregister", MultiLayer_swigregister, METH_VARARGS, NULL},
+	 { (char *)"MaterialProfile", _wrap_MaterialProfile, METH_VARARGS, (char *)"MaterialProfile(MultiLayer multilayer, int n_points, double z_min, double z_max) -> vector_complex_t"},
 	 { (char *)"new_OffSpecSimulation", _wrap_new_OffSpecSimulation, METH_VARARGS, (char *)"\n"
 		"OffSpecSimulation()\n"
 		"OffSpecSimulation(MultiLayer p_sample)\n"
-- 
GitLab