From 86a5108a5da33a665f8763bc42009408a135eca5 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (l)" <j.wuttke@fz-juelich.de>
Date: Thu, 15 Oct 2020 17:32:31 +0200
Subject: [PATCH] delegate pyfmt2::printAxis to IAxis::pyString

---
 Base/Axis/FixedBinAxis.cpp          |  10 ++
 Base/Axis/FixedBinAxis.h            |   2 +
 Base/Axis/IAxis.h                   |   2 +
 Base/Axis/PointwiseAxis.cpp         |  16 +++
 Base/Axis/PointwiseAxis.h           |   2 +
 Base/Axis/VariableBinAxis.cpp       |   5 +
 Base/Axis/VariableBinAxis.h         |   2 +
 Device/Instrument/PyFmt2.cpp        |  23 +----
 auto/Wrap/doxygenBase.i             |  12 +++
 auto/Wrap/libBornAgainBase.py       |  24 +++++
 auto/Wrap/libBornAgainBase_wrap.cpp | 150 ++++++++++++++++++++++++++++
 11 files changed, 226 insertions(+), 22 deletions(-)

diff --git a/Base/Axis/FixedBinAxis.cpp b/Base/Axis/FixedBinAxis.cpp
index 5caf602a19d..5b5d4903706 100644
--- a/Base/Axis/FixedBinAxis.cpp
+++ b/Base/Axis/FixedBinAxis.cpp
@@ -15,6 +15,7 @@
 #include "Base/Axis/FixedBinAxis.h"
 #include "Base/Types/Exceptions.h"
 #include "Base/Utils/Algorithms.h"
+#include "Base/Utils/PyFmt.h"
 #include <iomanip>
 #include <limits>
 
@@ -121,3 +122,12 @@ bool FixedBinAxis::equals(const IAxis& other) const
     }
     return false;
 }
+
+std::string FixedBinAxis::pyString(const std::string& units, size_t) const
+{
+    std::ostringstream result;
+    result << "ba.FixedBinAxis(" << pyfmt::printString(getName()) << ", "
+           << size() << ", " << pyfmt::printValue(getMin(), units) << ", "
+           << pyfmt::printValue(getMax(), units) << ")";
+    return result.str();
+}
diff --git a/Base/Axis/FixedBinAxis.h b/Base/Axis/FixedBinAxis.h
index 72164ca8ec3..59a8b14b19d 100644
--- a/Base/Axis/FixedBinAxis.h
+++ b/Base/Axis/FixedBinAxis.h
@@ -52,6 +52,8 @@ public:
 
     FixedBinAxis* createClippedAxis(double left, double right) const;
 
+    std::string pyString(const std::string& units, size_t) const final;
+
 protected:
     void print(std::ostream& ostr) const;
     virtual bool equals(const IAxis& other) const;
diff --git a/Base/Axis/IAxis.h b/Base/Axis/IAxis.h
index 693cfbad5dd..de17be4028b 100644
--- a/Base/Axis/IAxis.h
+++ b/Base/Axis/IAxis.h
@@ -79,6 +79,8 @@ public:
     //! Returns true if axis contains given point
     virtual bool contains(double value) const;
 
+    virtual std::string pyString(const std::string& units, size_t offset) const = 0;
+
 protected:
     virtual void print(std::ostream& ostr) const = 0;
     virtual bool equals(const IAxis& other) const; // overloaded in child classes
diff --git a/Base/Axis/PointwiseAxis.cpp b/Base/Axis/PointwiseAxis.cpp
index 8bc775ccf09..1f12ab08416 100644
--- a/Base/Axis/PointwiseAxis.cpp
+++ b/Base/Axis/PointwiseAxis.cpp
@@ -13,6 +13,7 @@
 // ************************************************************************** //
 
 #include "Base/Axis/PointwiseAxis.h"
+#include "Base/Utils/PyFmt.h"
 #include <algorithm>
 #include <iomanip>
 #include <stdexcept>
@@ -83,6 +84,21 @@ PointwiseAxis* PointwiseAxis::createClippedAxis(double left, double right) const
     return new PointwiseAxis(getName(), std::vector<double>(begin, end));
 }
 
+std::string PointwiseAxis::pyString(const std::string& units, size_t offset) const
+{
+    std::ostringstream result;
+    const std::string py_def_call = "numpy.asarray([";
+    const size_t total_offset = offset + py_def_call.size();
+    result << py_def_call;
+    std::vector<double> points = getBinCenters();
+    for (auto iter = points.begin(); iter != points.end() - 1; ++iter) {
+        result << pyfmt::printValue(*iter, units) << ",\n";
+        result << pyfmt::indent(total_offset);
+    }
+    result << pyfmt::printValue(points.back(), units) << "])";
+    return result.str();
+}
+
 void PointwiseAxis::print(std::ostream& ostr) const
 {
     auto precision = std::setprecision(std::numeric_limits<double>::digits10 + 2);
diff --git a/Base/Axis/PointwiseAxis.h b/Base/Axis/PointwiseAxis.h
index 405ecd26c59..795204cb7c4 100644
--- a/Base/Axis/PointwiseAxis.h
+++ b/Base/Axis/PointwiseAxis.h
@@ -73,6 +73,8 @@ public:
     //! Creates a new clipped axis
     PointwiseAxis* createClippedAxis(double left, double right) const override;
 
+    std::string pyString(const std::string& units, size_t offset) const final;
+
 private:
     void print(std::ostream& ostr) const override;
     bool equals(const IAxis& other) const override;
diff --git a/Base/Axis/VariableBinAxis.cpp b/Base/Axis/VariableBinAxis.cpp
index 8ab8a65d66d..f46a16c3d2d 100644
--- a/Base/Axis/VariableBinAxis.cpp
+++ b/Base/Axis/VariableBinAxis.cpp
@@ -124,6 +124,11 @@ VariableBinAxis* VariableBinAxis::createClippedAxis(double left, double right) c
     return new VariableBinAxis(getName(), new_nbins, new_boundaries);
 }
 
+std::string VariableBinAxis::pyString(const std::string&, size_t) const
+{
+    throw std::runtime_error("VariableBinAxis::pyString not yet implemented"); // TODO
+}
+
 void VariableBinAxis::print(std::ostream& ostr) const
 {
     ostr << "VariableBinAxis(\"" << getName() << "\", " << size() << ", [";
diff --git a/Base/Axis/VariableBinAxis.h b/Base/Axis/VariableBinAxis.h
index 8782f37e6fc..f9e7ac67635 100644
--- a/Base/Axis/VariableBinAxis.h
+++ b/Base/Axis/VariableBinAxis.h
@@ -52,6 +52,8 @@ public:
 
     virtual VariableBinAxis* createClippedAxis(double left, double right) const;
 
+    std::string pyString(const std::string& units, size_t offset) const final;
+
 protected:
     VariableBinAxis(const std::string& name, size_t nbins = 0);
     void setBinBoundaries(const std::vector<double>& bin_boundaries);
diff --git a/Device/Instrument/PyFmt2.cpp b/Device/Instrument/PyFmt2.cpp
index ebaa5c8f4a2..d6048132dca 100644
--- a/Device/Instrument/PyFmt2.cpp
+++ b/Device/Instrument/PyFmt2.cpp
@@ -142,28 +142,7 @@ std::string printParameterDistribution(const ParameterDistribution& par_distr,
 
 std::string printAxis(const IAxis& axis, const std::string& units, size_t offset)
 {
-    std::ostringstream result;
-
-    if (auto fixedAxis = dynamic_cast<const FixedBinAxis*>(&axis)) {
-        result << "ba.FixedBinAxis(" << pyfmt::printString(fixedAxis->getName()) << ", "
-               << fixedAxis->size() << ", " << pyfmt::printValue(fixedAxis->getMin(), units) << ", "
-               << pyfmt::printValue(fixedAxis->getMax(), units) << ")";
-    } else if (auto pointwise_axis = dynamic_cast<const PointwiseAxis*>(&axis)) {
-        const std::string py_def_call = "numpy.asarray([";
-        const size_t total_offset = offset + py_def_call.size();
-        result << py_def_call;
-
-        std::vector<double> points = pointwise_axis->getBinCenters();
-        for (auto iter = points.begin(); iter != points.end() - 1; ++iter) {
-            result << pyfmt::printValue(*iter, units) << ",\n";
-            result << pyfmt::indent(total_offset);
-        }
-        result << pyfmt::printValue(points.back(), units) << "])";
-    } else {
-        throw std::runtime_error("pyfmt2::printAxis() -> Error. Unsupported axis");
-    }
-
-    return result.str();
+    return axis.pyString(units, offset);
 }
 
 } // namespace pyfmt2
diff --git a/auto/Wrap/doxygenBase.i b/auto/Wrap/doxygenBase.i
index 7e805b453a8..91ea6cd9735 100644
--- a/auto/Wrap/doxygenBase.i
+++ b/auto/Wrap/doxygenBase.i
@@ -486,6 +486,9 @@ find bin index which is best match for given value
 Creates a new clipped axis. 
 ";
 
+%feature("docstring")  FixedBinAxis::pyString "std::string FixedBinAxis::pyString(const std::string &units, size_t) const final
+";
+
 
 // File: classExceptions_1_1FormatErrorException.xml
 %feature("docstring") Exceptions::FormatErrorException "";
@@ -571,6 +574,9 @@ Creates a new clipped axis.
 Returns true if axis contains given point. 
 ";
 
+%feature("docstring")  IAxis::pyString "virtual std::string IAxis::pyString(const std::string &units, size_t offset) const =0
+";
+
 
 // File: classICloneable.xml
 %feature("docstring") ICloneable "
@@ -745,6 +751,9 @@ find index of the coordinate closest to the given value
 Creates a new clipped axis. 
 ";
 
+%feature("docstring")  PointwiseAxis::pyString "std::string PointwiseAxis::pyString(const std::string &units, size_t offset) const final
+";
+
 
 // File: classPolarizationHandler.xml
 %feature("docstring") PolarizationHandler "
@@ -1152,6 +1161,9 @@ find bin index which is best match for given value
 Creates a new clipped axis. 
 ";
 
+%feature("docstring")  VariableBinAxis::pyString "std::string VariableBinAxis::pyString(const std::string &units, size_t offset) const final
+";
+
 
 // File: namespacealgo.xml
 %feature("docstring")  algo::almostEqual "bool algo::almostEqual(double a, double b)
diff --git a/auto/Wrap/libBornAgainBase.py b/auto/Wrap/libBornAgainBase.py
index 33224bb5a9a..ffc84d1344d 100644
--- a/auto/Wrap/libBornAgainBase.py
+++ b/auto/Wrap/libBornAgainBase.py
@@ -2287,6 +2287,14 @@ class IAxis(object):
         """
         return _libBornAgainBase.IAxis_contains(self, value)
 
+    def pyString(self, units, offset):
+        r"""
+        pyString(IAxis self, std::string const & units, size_t offset) -> std::string
+        virtual std::string IAxis::pyString(const std::string &units, size_t offset) const =0
+
+        """
+        return _libBornAgainBase.IAxis_pyString(self, units, offset)
+
 # Register IAxis in _libBornAgainBase:
 _libBornAgainBase.IAxis_swigregister(IAxis)
 
@@ -2430,6 +2438,14 @@ class VariableBinAxis(IAxis):
         """
         return _libBornAgainBase.VariableBinAxis_createClippedAxis(self, left, right)
 
+    def pyString(self, units, offset):
+        r"""
+        pyString(VariableBinAxis self, std::string const & units, size_t offset) -> std::string
+        std::string VariableBinAxis::pyString(const std::string &units, size_t offset) const final
+
+        """
+        return _libBornAgainBase.VariableBinAxis_pyString(self, units, offset)
+
     def __getitem__(self, i):
         r"""__getitem__(VariableBinAxis self, unsigned int i) -> double"""
         return _libBornAgainBase.VariableBinAxis___getitem__(self, i)
@@ -2712,6 +2728,14 @@ class FixedBinAxis(IAxis):
         """
         return _libBornAgainBase.FixedBinAxis_createClippedAxis(self, left, right)
 
+    def pyString(self, units, arg3):
+        r"""
+        pyString(FixedBinAxis self, std::string const & units, size_t arg3) -> std::string
+        std::string FixedBinAxis::pyString(const std::string &units, size_t) const final
+
+        """
+        return _libBornAgainBase.FixedBinAxis_pyString(self, units, arg3)
+
     def __getitem__(self, i):
         r"""__getitem__(FixedBinAxis self, unsigned int i) -> double"""
         return _libBornAgainBase.FixedBinAxis___getitem__(self, i)
diff --git a/auto/Wrap/libBornAgainBase_wrap.cpp b/auto/Wrap/libBornAgainBase_wrap.cpp
index 50f3b25ccbc..559625f8d08 100644
--- a/auto/Wrap/libBornAgainBase_wrap.cpp
+++ b/auto/Wrap/libBornAgainBase_wrap.cpp
@@ -26789,6 +26789,51 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IAxis_pyString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IAxis *arg1 = (IAxis *) 0 ;
+  std::string *arg2 = 0 ;
+  size_t arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 = SWIG_OLDOBJ ;
+  size_t val3 ;
+  int ecode3 = 0 ;
+  PyObject *swig_obj[3] ;
+  std::string result;
+  
+  if (!SWIG_Python_UnpackTuple(args, "IAxis_pyString", 3, 3, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_IAxis, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IAxis_pyString" "', argument " "1"" of type '" "IAxis const *""'"); 
+  }
+  arg1 = reinterpret_cast< IAxis * >(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 '" "IAxis_pyString" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    if (!ptr) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IAxis_pyString" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    arg2 = ptr;
+  }
+  ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "IAxis_pyString" "', argument " "3"" of type '" "size_t""'");
+  } 
+  arg3 = static_cast< size_t >(val3);
+  result = ((IAxis const *)arg1)->pyString((std::string const &)*arg2,arg3);
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return resultobj;
+fail:
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *IAxis_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
@@ -27172,6 +27217,51 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_VariableBinAxis_pyString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  VariableBinAxis *arg1 = (VariableBinAxis *) 0 ;
+  std::string *arg2 = 0 ;
+  size_t arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 = SWIG_OLDOBJ ;
+  size_t val3 ;
+  int ecode3 = 0 ;
+  PyObject *swig_obj[3] ;
+  std::string result;
+  
+  if (!SWIG_Python_UnpackTuple(args, "VariableBinAxis_pyString", 3, 3, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_VariableBinAxis, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VariableBinAxis_pyString" "', argument " "1"" of type '" "VariableBinAxis const *""'"); 
+  }
+  arg1 = reinterpret_cast< VariableBinAxis * >(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 '" "VariableBinAxis_pyString" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    if (!ptr) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "VariableBinAxis_pyString" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    arg2 = ptr;
+  }
+  ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VariableBinAxis_pyString" "', argument " "3"" of type '" "size_t""'");
+  } 
+  arg3 = static_cast< size_t >(val3);
+  result = ((VariableBinAxis const *)arg1)->pyString((std::string const &)*arg2,arg3);
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return resultobj;
+fail:
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_VariableBinAxis___getitem__(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   VariableBinAxis *arg1 = (VariableBinAxis *) 0 ;
@@ -27901,6 +27991,51 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_FixedBinAxis_pyString(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  FixedBinAxis *arg1 = (FixedBinAxis *) 0 ;
+  std::string *arg2 = 0 ;
+  size_t arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 = SWIG_OLDOBJ ;
+  size_t val3 ;
+  int ecode3 = 0 ;
+  PyObject *swig_obj[3] ;
+  std::string result;
+  
+  if (!SWIG_Python_UnpackTuple(args, "FixedBinAxis_pyString", 3, 3, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_FixedBinAxis, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FixedBinAxis_pyString" "', argument " "1"" of type '" "FixedBinAxis const *""'"); 
+  }
+  arg1 = reinterpret_cast< FixedBinAxis * >(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 '" "FixedBinAxis_pyString" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    if (!ptr) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "FixedBinAxis_pyString" "', argument " "2"" of type '" "std::string const &""'"); 
+    }
+    arg2 = ptr;
+  }
+  ecode3 = SWIG_AsVal_size_t(swig_obj[2], &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "FixedBinAxis_pyString" "', argument " "3"" of type '" "size_t""'");
+  } 
+  arg3 = static_cast< size_t >(val3);
+  result = ((FixedBinAxis const *)arg1)->pyString((std::string const &)*arg2,arg3);
+  resultobj = SWIG_From_std_string(static_cast< std::string >(result));
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return resultobj;
+fail:
+  if (SWIG_IsNewObj(res2)) delete arg2;
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_FixedBinAxis___getitem__(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   FixedBinAxis *arg1 = (FixedBinAxis *) 0 ;
@@ -33965,6 +34100,11 @@ static PyMethodDef SwigMethods[] = {
 		"Returns true if axis contains given point. \n"
 		"\n"
 		""},
+	 { "IAxis_pyString", _wrap_IAxis_pyString, METH_VARARGS, "\n"
+		"IAxis_pyString(IAxis self, std::string const & units, size_t offset) -> std::string\n"
+		"virtual std::string IAxis::pyString(const std::string &units, size_t offset) const =0\n"
+		"\n"
+		""},
 	 { "IAxis_swigregister", IAxis_swigregister, METH_O, NULL},
 	 { "HaveSameNameAndShape", _wrap_HaveSameNameAndShape, METH_VARARGS, "\n"
 		"HaveSameNameAndShape(IAxis left, IAxis right) -> bool\n"
@@ -34061,6 +34201,11 @@ static PyMethodDef SwigMethods[] = {
 		"Creates a new clipped axis. \n"
 		"\n"
 		""},
+	 { "VariableBinAxis_pyString", _wrap_VariableBinAxis_pyString, METH_VARARGS, "\n"
+		"VariableBinAxis_pyString(VariableBinAxis self, std::string const & units, size_t offset) -> std::string\n"
+		"std::string VariableBinAxis::pyString(const std::string &units, size_t offset) const final\n"
+		"\n"
+		""},
 	 { "VariableBinAxis___getitem__", _wrap_VariableBinAxis___getitem__, METH_VARARGS, "VariableBinAxis___getitem__(VariableBinAxis self, unsigned int i) -> double"},
 	 { "VariableBinAxis_swigregister", VariableBinAxis_swigregister, METH_O, NULL},
 	 { "VariableBinAxis_swiginit", VariableBinAxis_swiginit, METH_VARARGS, NULL},
@@ -34253,6 +34398,11 @@ static PyMethodDef SwigMethods[] = {
 		"Creates a new clipped axis. \n"
 		"\n"
 		""},
+	 { "FixedBinAxis_pyString", _wrap_FixedBinAxis_pyString, METH_VARARGS, "\n"
+		"FixedBinAxis_pyString(FixedBinAxis self, std::string const & units, size_t arg3) -> std::string\n"
+		"std::string FixedBinAxis::pyString(const std::string &units, size_t) const final\n"
+		"\n"
+		""},
 	 { "FixedBinAxis___getitem__", _wrap_FixedBinAxis___getitem__, METH_VARARGS, "FixedBinAxis___getitem__(FixedBinAxis self, unsigned int i) -> double"},
 	 { "FixedBinAxis_swigregister", FixedBinAxis_swigregister, METH_O, NULL},
 	 { "FixedBinAxis_swiginit", FixedBinAxis_swiginit, METH_VARARGS, NULL},
-- 
GitLab