From a1f88872c249424efa1dcadf3016accd4d03bee7 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Sun, 24 Apr 2022 14:04:17 +0200
Subject: [PATCH] ISimulation::result now allows to set title

---
 Device/Histo/SimulationResult.cpp             |  6 ++
 Device/Histo/SimulationResult.h               |  1 +
 .../specular/BasicPolarizedReflectometry.py   | 22 +++--
 Examples/specular/FootprintCorrection.py      |  4 +-
 Sim/Simulation/ISimulation.cpp                |  6 ++
 Sim/Simulation/ISimulation.h                  |  5 ++
 auto/Wrap/doxygenDevice.i                     |  3 +
 auto/Wrap/doxygenSim.i                        |  5 ++
 auto/Wrap/libBornAgainDevice.py               |  1 +
 auto/Wrap/libBornAgainDevice_wrap.cpp         | 55 +++++++++++-
 auto/Wrap/libBornAgainSim.py                  |  9 +-
 auto/Wrap/libBornAgainSim_wrap.cpp            | 89 +++++++++++++++++--
 12 files changed, 179 insertions(+), 27 deletions(-)

diff --git a/Device/Histo/SimulationResult.cpp b/Device/Histo/SimulationResult.cpp
index d2c5081fc1d..c8a750deea7 100644
--- a/Device/Histo/SimulationResult.cpp
+++ b/Device/Histo/SimulationResult.cpp
@@ -37,6 +37,12 @@ SimulationResult::SimulationResult(const SimulationResult& other)
     m_coordsys.reset(other.m_coordsys->clone());
 }
 
+SimulationResult::SimulationResult(const SimulationResult& other, const std::string& title)
+    : SimulationResult(other)
+{
+    m_title = title;
+}
+
 SimulationResult::SimulationResult(SimulationResult&& other)
     : m_data(std::move(other.m_data))
     , m_coordsys(std::move(other.m_coordsys))
diff --git a/Device/Histo/SimulationResult.h b/Device/Histo/SimulationResult.h
index c0a7ceead07..4b31195e79c 100644
--- a/Device/Histo/SimulationResult.h
+++ b/Device/Histo/SimulationResult.h
@@ -46,6 +46,7 @@ public:
     ~SimulationResult();
 
     SimulationResult(const SimulationResult& other);
+    SimulationResult(const SimulationResult& other, const std::string& title);
     SimulationResult(SimulationResult&& other);
 
     SimulationResult& operator=(const SimulationResult& other);
diff --git a/Examples/specular/BasicPolarizedReflectometry.py b/Examples/specular/BasicPolarizedReflectometry.py
index ef53bed7ec1..a9d42777b95 100755
--- a/Examples/specular/BasicPolarizedReflectometry.py
+++ b/Examples/specular/BasicPolarizedReflectometry.py
@@ -42,33 +42,31 @@ def get_simulation(sample, scan_size=500):
     """
 
 
-def simulate(polarizer_dir, analyzer_dir):
-    """
-    Runs simulation and returns its result.
-    """
+def simulate(polarizer_dir, analyzer_dir, title):
     n = bp.simargs['n']
     simulation = ba.SpecularSimulation()
     scan = ba.AlphaScan(1.54*angstrom, n, 0, 5*deg)
     simulation.setScan(scan)
     simulation.setSample(get_sample())
 
-    # adding polarization and analyzer operator
     simulation.instrument().setPolFilters(polarizer_dir, analyzer_dir, 1,
                                           0.5)
 
     simulation.simulate()
-    return simulation.result()
+
+    return simulation.result(title)
 
 
 def run_simulations():
-    ret = []
-    ret.append(
-        bp.NamedResult(simulate(ba.R3(0, +1, 0), ba.R3(0, +1, 0)), "$++$"))
-    ret.append(
-        bp.NamedResult(simulate(ba.R3(0, -1, 0), ba.R3(0, -1, 0)), "$--$"))
     return ret
 
 
 if __name__ == '__main__':
     bp.parse_args(sim_n=500)
-    bp.plot_multicurve_specular(run_simulations())
+
+    results = [
+        simulate(ba.R3(0, +1, 0), ba.R3(0, +1, 0), "$++$"),
+        simulate(ba.R3(0, -1, 0), ba.R3(0, -1, 0), "$--$"),
+    ]
+
+    bp.plot_multicurve_specular(results)
diff --git a/Examples/specular/FootprintCorrection.py b/Examples/specular/FootprintCorrection.py
index 01c7314ee2f..55648e63e4d 100755
--- a/Examples/specular/FootprintCorrection.py
+++ b/Examples/specular/FootprintCorrection.py
@@ -19,9 +19,7 @@ def simulate(footprint, title):
     simulation.setScan(scan)
     simulation.setSample(sample)
     simulation.simulate()
-    result = simulation.result()
-    result.setTitle(title)
-    return result
+    return simulation.result(title)
 
 
 if __name__ == '__main__':
diff --git a/Sim/Simulation/ISimulation.cpp b/Sim/Simulation/ISimulation.cpp
index 1de86613e40..78c0045a19e 100644
--- a/Sim/Simulation/ISimulation.cpp
+++ b/Sim/Simulation/ISimulation.cpp
@@ -277,6 +277,12 @@ SimulationResult ISimulation::result() const
     return *m_result;
 }
 
+SimulationResult ISimulation::result(const std::string& title) const
+{
+    ASSERT(m_result);
+    return SimulationResult(*m_result, title);
+}
+
 void ISimulation::addParameterDistribution(ParameterDistribution::WhichParameter whichParameter,
                                            const IDistribution1D& distribution, size_t nbr_samples,
                                            double sigma_factor, const RealLimits& limits)
diff --git a/Sim/Simulation/ISimulation.h b/Sim/Simulation/ISimulation.h
index d36ff433acd..fd142af7c35 100644
--- a/Sim/Simulation/ISimulation.h
+++ b/Sim/Simulation/ISimulation.h
@@ -63,6 +63,11 @@ public:
     //! that supports unit conversion and export to numpy arrays
     SimulationResult result() const;
 
+    //! Returns the results of the simulation in a format
+    //! that supports unit conversion and export to numpy arrays;
+    //! sets result title.
+    SimulationResult result(const std::string& title) const;
+
     void addParameterDistribution(ParameterDistribution::WhichParameter whichParameter,
                                   const IDistribution1D& distribution, size_t nbr_samples,
                                   double sigma_factor = 0.0,
diff --git a/auto/Wrap/doxygenDevice.i b/auto/Wrap/doxygenDevice.i
index f7a0ec78f87..859753a110e 100644
--- a/auto/Wrap/doxygenDevice.i
+++ b/auto/Wrap/doxygenDevice.i
@@ -2499,6 +2499,9 @@ C++ includes: SimulationResult.h
 %feature("docstring")  SimulationResult::SimulationResult "SimulationResult::SimulationResult(const SimulationResult &other)
 ";
 
+%feature("docstring")  SimulationResult::SimulationResult "SimulationResult::SimulationResult(const SimulationResult &other, const std::string &title)
+";
+
 %feature("docstring")  SimulationResult::SimulationResult "SimulationResult::SimulationResult(SimulationResult &&other)
 ";
 
diff --git a/auto/Wrap/doxygenSim.i b/auto/Wrap/doxygenSim.i
index 87433c717f7..3d02053d41f 100644
--- a/auto/Wrap/doxygenSim.i
+++ b/auto/Wrap/doxygenSim.i
@@ -901,6 +901,11 @@ The MultiLayer object will not be owned by the  ISimulation object.
 Returns the results of the simulation in a format that supports unit conversion and export to numpy arrays 
 ";
 
+%feature("docstring")  ISimulation::result "SimulationResult ISimulation::result(const std::string &title) const
+
+Returns the results of the simulation in a format that supports unit conversion and export to numpy arrays; sets result title. 
+";
+
 %feature("docstring")  ISimulation::addParameterDistribution "void ISimulation::addParameterDistribution(ParameterDistribution::WhichParameter whichParameter, const IDistribution1D &distribution, size_t nbr_samples, double sigma_factor=0.0, const RealLimits &limits=RealLimits())
 ";
 
diff --git a/auto/Wrap/libBornAgainDevice.py b/auto/Wrap/libBornAgainDevice.py
index 43450724097..ae6007538c3 100644
--- a/auto/Wrap/libBornAgainDevice.py
+++ b/auto/Wrap/libBornAgainDevice.py
@@ -5805,6 +5805,7 @@ class SimulationResult(object):
         __init__(SimulationResult self, IntensityData data, ICoordSystem const & coords) -> SimulationResult
         __init__(SimulationResult self, IntensityData data, ICoordSystem const *&& coords) -> SimulationResult
         __init__(SimulationResult self, SimulationResult other) -> SimulationResult
+        __init__(SimulationResult self, SimulationResult other, std::string const & title) -> SimulationResult
         __init__(SimulationResult self, SimulationResult other) -> SimulationResult
         SimulationResult::SimulationResult(SimulationResult &&other)
 
diff --git a/auto/Wrap/libBornAgainDevice_wrap.cpp b/auto/Wrap/libBornAgainDevice_wrap.cpp
index eaf0a52ec63..b60a8c7cb05 100644
--- a/auto/Wrap/libBornAgainDevice_wrap.cpp
+++ b/auto/Wrap/libBornAgainDevice_wrap.cpp
@@ -45754,6 +45754,45 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_SimulationResult__SWIG_4(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  SimulationResult *arg1 = 0 ;
+  std::string *arg2 = 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 = SWIG_OLDOBJ ;
+  SimulationResult *result = 0 ;
+  
+  if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_SimulationResult,  0  | 0);
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_SimulationResult" "', argument " "1"" of type '" "SimulationResult const &""'"); 
+  }
+  if (!argp1) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_SimulationResult" "', argument " "1"" of type '" "SimulationResult const &""'"); 
+  }
+  arg1 = reinterpret_cast< SimulationResult * >(argp1);
+  {
+    std::string *ptr = (std::string *)0;
+    res2 = SWIG_AsPtr_std_string(swig_obj[1], &ptr);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_SimulationResult" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    if (!ptr) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_SimulationResult" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    arg2 = ptr;
+  }
+  result = (SimulationResult *)new SimulationResult((SimulationResult const &)*arg1,(std::string const &)*arg2);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_SimulationResult, SWIG_POINTER_NEW |  0 );
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return resultobj;
+fail:
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_SimulationResult__SWIG_5(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   SimulationResult *arg1 = 0 ;
   void *argp1 = 0 ;
@@ -45802,7 +45841,7 @@ SWIGINTERN PyObject *_wrap_new_SimulationResult(PyObject *self, PyObject *args)
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_SimulationResult, SWIG_POINTER_NO_NULL);
     _v = SWIG_CheckState(res);
     if (_v) {
-      return _wrap_new_SimulationResult__SWIG_4(self, argc, argv);
+      return _wrap_new_SimulationResult__SWIG_5(self, argc, argv);
     }
   }
   if (argc == 2) {
@@ -45817,6 +45856,18 @@ SWIGINTERN PyObject *_wrap_new_SimulationResult(PyObject *self, PyObject *args)
       }
     }
   }
+  if (argc == 2) {
+    int _v;
+    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_SimulationResult, SWIG_POINTER_NO_NULL | 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsPtr_std_string(argv[1], (std::string**)(0));
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_new_SimulationResult__SWIG_4(self, argc, argv);
+      }
+    }
+  }
   if (argc == 2) {
     int _v;
     int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_OutputDataT_double_t, SWIG_POINTER_NO_NULL | 0);
@@ -45838,6 +45889,7 @@ fail:
     "    SimulationResult::SimulationResult(OutputData< double > const &,ICoordSystem const &)\n"
     "    SimulationResult::SimulationResult(OutputData< double > const &,ICoordSystem const *&&)\n"
     "    SimulationResult::SimulationResult(SimulationResult const &)\n"
+    "    SimulationResult::SimulationResult(SimulationResult const &,std::string const &)\n"
     "    SimulationResult::SimulationResult(SimulationResult &&)\n");
   return 0;
 }
@@ -49446,6 +49498,7 @@ static PyMethodDef SwigMethods[] = {
 		"SimulationResult(IntensityData data, ICoordSystem const & coords)\n"
 		"SimulationResult(IntensityData data, ICoordSystem const *&& coords)\n"
 		"SimulationResult(SimulationResult other)\n"
+		"SimulationResult(SimulationResult other, std::string const & title)\n"
 		"new_SimulationResult(SimulationResult other) -> SimulationResult\n"
 		"SimulationResult::SimulationResult(SimulationResult &&other)\n"
 		"\n"
diff --git a/auto/Wrap/libBornAgainSim.py b/auto/Wrap/libBornAgainSim.py
index 5e3e51d74e1..931ba8e686a 100644
--- a/auto/Wrap/libBornAgainSim.py
+++ b/auto/Wrap/libBornAgainSim.py
@@ -3781,15 +3781,16 @@ class ISimulation(libBornAgainParam.INode):
         """
         return _libBornAgainSim.ISimulation_setBackground(self, bg)
 
-    def result(self):
+    def result(self, *args):
         r"""
         result(ISimulation self) -> SimulationResult
-        SimulationResult ISimulation::result() const
+        result(ISimulation self, std::string const & title) -> SimulationResult
+        SimulationResult ISimulation::result(const std::string &title) const
 
-        Returns the results of the simulation in a format that supports unit conversion and export to numpy arrays 
+        Returns the results of the simulation in a format that supports unit conversion and export to numpy arrays; sets result title. 
 
         """
-        return _libBornAgainSim.ISimulation_result(self)
+        return _libBornAgainSim.ISimulation_result(self, *args)
 
     def addParameterDistribution(self, *args):
         r"""
diff --git a/auto/Wrap/libBornAgainSim_wrap.cpp b/auto/Wrap/libBornAgainSim_wrap.cpp
index 8daa3b004ff..0777546d732 100644
--- a/auto/Wrap/libBornAgainSim_wrap.cpp
+++ b/auto/Wrap/libBornAgainSim_wrap.cpp
@@ -41653,16 +41653,14 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_ISimulation_result(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_ISimulation_result__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   ISimulation *arg1 = (ISimulation *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  PyObject *swig_obj[1] ;
   SimulationResult result;
   
-  if (!args) SWIG_fail;
-  swig_obj[0] = args;
+  if ((nobjs < 1) || (nobjs > 1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ISimulation, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ISimulation_result" "', argument " "1"" of type '" "ISimulation const *""'"); 
@@ -41676,6 +41674,82 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_ISimulation_result__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  ISimulation *arg1 = (ISimulation *) 0 ;
+  std::string *arg2 = 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 = SWIG_OLDOBJ ;
+  SimulationResult result;
+  
+  if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ISimulation, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ISimulation_result" "', argument " "1"" of type '" "ISimulation const *""'"); 
+  }
+  arg1 = reinterpret_cast< ISimulation * >(argp1);
+  {
+    std::string *ptr = (std::string *)0;
+    res2 = SWIG_AsPtr_std_string(swig_obj[1], &ptr);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ISimulation_result" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    if (!ptr) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "ISimulation_result" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    arg2 = ptr;
+  }
+  result = ((ISimulation const *)arg1)->result((std::string const &)*arg2);
+  resultobj = SWIG_NewPointerObj((new SimulationResult(static_cast< const SimulationResult& >(result))), SWIGTYPE_p_SimulationResult, SWIG_POINTER_OWN |  0 );
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return resultobj;
+fail:
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ISimulation_result(PyObject *self, PyObject *args) {
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  
+  if (!(argc = SWIG_Python_UnpackTuple(args, "ISimulation_result", 0, 2, argv))) SWIG_fail;
+  --argc;
+  if (argc == 1) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_ISimulation, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      return _wrap_ISimulation_result__SWIG_0(self, argc, argv);
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_ISimulation, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsPtr_std_string(argv[1], (std::string**)(0));
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_ISimulation_result__SWIG_1(self, argc, argv);
+      }
+    }
+  }
+  
+fail:
+  SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'ISimulation_result'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    ISimulation::result() const\n"
+    "    ISimulation::result(std::string const &) const\n");
+  return 0;
+}
+
+
 SWIGINTERN PyObject *_wrap_ISimulation_addParameterDistribution__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   ISimulation *arg1 = (ISimulation *) 0 ;
@@ -46515,11 +46589,12 @@ static PyMethodDef SwigMethods[] = {
 		"void ISimulation::setBackground(const IBackground &bg)\n"
 		"\n"
 		""},
-	 { "ISimulation_result", _wrap_ISimulation_result, METH_O, "\n"
+	 { "ISimulation_result", _wrap_ISimulation_result, METH_VARARGS, "\n"
 		"ISimulation_result(ISimulation self) -> SimulationResult\n"
-		"SimulationResult ISimulation::result() const\n"
+		"ISimulation_result(ISimulation self, std::string const & title) -> SimulationResult\n"
+		"SimulationResult ISimulation::result(const std::string &title) const\n"
 		"\n"
-		"Returns the results of the simulation in a format that supports unit conversion and export to numpy arrays \n"
+		"Returns the results of the simulation in a format that supports unit conversion and export to numpy arrays; sets result title. \n"
 		"\n"
 		""},
 	 { "ISimulation_addParameterDistribution", _wrap_ISimulation_addParameterDistribution, METH_VARARGS, "\n"
-- 
GitLab