From 4b191f356a107785e3182a1f60533f7c85db62c2 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Tue, 11 Jul 2023 16:03:39 +0200
Subject: [PATCH] correct Py export

---
 Base/Axis/MakeScale.h               |  4 +-
 Base/Axis/Scale.cpp                 | 17 +++++++
 Base/Axis/Scale.h                   |  1 +
 Sim/Export/PyFmt2.cpp               |  4 ++
 auto/Wrap/libBornAgainBase.py       |  8 +++
 auto/Wrap/libBornAgainBase_wrap.cpp | 78 +++++++++++++++++++++++++++++
 6 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/Base/Axis/MakeScale.h b/Base/Axis/MakeScale.h
index 5b8bb864c24..104a1b5f69c 100644
--- a/Base/Axis/MakeScale.h
+++ b/Base/Axis/MakeScale.h
@@ -40,9 +40,9 @@ std::unique_ptr<Scale> uniqueEquiDivision(const std::string& name, size_t N, dou
                                           double end);
 #endif // SWIG
 
-#ifndef SWIG
-//! Returns a EquiDivision determined by first and last point in scan.
+//! Returns axis with equidistant points (zero bin width).
 Scale EquiScan(const std::string& name, size_t N, double start, double end);
+#ifndef SWIG
 Scale* newEquiScan(const std::string& name, size_t N, double start, double end);
 std::shared_ptr<Scale> sharedEquiScan(const std::string& name, size_t N, double start, double end);
 std::unique_ptr<Scale> uniqueEquiScan(const std::string& name, size_t N, double start, double end);
diff --git a/Base/Axis/Scale.cpp b/Base/Axis/Scale.cpp
index 9e927f3c154..3c6a8beef94 100644
--- a/Base/Axis/Scale.cpp
+++ b/Base/Axis/Scale.cpp
@@ -107,6 +107,23 @@ bool Scale::isEquiDivision() const
     return true;
 }
 
+bool Scale::isEquiScan() const
+{
+    const size_t N = size();
+    ASSERT(N);
+    if (N == 1)
+        return !bin(0).binSize();
+    for (size_t i = 0; i < N; ++i) {
+        const Bin1D& b = bin(i);
+        if (b.binSize())
+            return false;
+        // exactly replicate the computation of bin bounds in the EquiDivision factory function
+        if (b.lowerBound() != (N - 1 - i) * (min() / (N - 1)) + i * (max() / (N - 1)))
+            return false;
+    }
+    return true;
+}
+
 bool Scale::isScan() const
 {
     for (const Bin1D& b : bins())
diff --git a/Base/Axis/Scale.h b/Base/Axis/Scale.h
index ccd0feba876..824bb2d47fa 100644
--- a/Base/Axis/Scale.h
+++ b/Base/Axis/Scale.h
@@ -67,6 +67,7 @@ public:
     size_t closestIndex(double value) const;
 
     bool isEquiDivision() const;
+    bool isEquiScan() const;
     bool isScan() const;
 
     Scale clipped(double lower, double upper) const;
diff --git a/Sim/Export/PyFmt2.cpp b/Sim/Export/PyFmt2.cpp
index 0ead39448d4..c9a6c956624 100644
--- a/Sim/Export/PyFmt2.cpp
+++ b/Sim/Export/PyFmt2.cpp
@@ -96,6 +96,10 @@ std::string Py::Fmt2::printAxis(const Scale* a, const std::string& unit)
         result << "ba.EquiDivision(" << Py::Fmt::printString(a->axisName()) << ", " << a->size()
                << ", " << Py::Fmt::printValue(a->min(), unit) << ", "
                << Py::Fmt::printValue(a->max(), unit) << ")";
+    else if (a->isEquiScan())
+        result << "ba.EquiScan(" << Py::Fmt::printString(a->axisName()) << ", " << a->size() << ", "
+               << Py::Fmt::printValue(a->min(), unit) << ", " << Py::Fmt::printValue(a->max(), unit)
+               << ")";
     else if (a->isScan()) {
         result << "numpy.asarray([";
         const std::vector<double>& points = a->binCenters();
diff --git a/auto/Wrap/libBornAgainBase.py b/auto/Wrap/libBornAgainBase.py
index b5addf32034..1becc07e63c 100644
--- a/auto/Wrap/libBornAgainBase.py
+++ b/auto/Wrap/libBornAgainBase.py
@@ -1918,6 +1918,10 @@ class Scale(object):
         r"""isEquiDivision(Scale self) -> bool"""
         return _libBornAgainBase.Scale_isEquiDivision(self)
 
+    def isEquiScan(self):
+        r"""isEquiScan(Scale self) -> bool"""
+        return _libBornAgainBase.Scale_isEquiScan(self)
+
     def isScan(self):
         r"""isScan(Scale self) -> bool"""
         return _libBornAgainBase.Scale_isScan(self)
@@ -1952,6 +1956,10 @@ def ListScan(name, points):
 def EquiDivision(name, N, start, end):
     r"""EquiDivision(std::string const & name, size_t N, double start, double end) -> Scale"""
     return _libBornAgainBase.EquiDivision(name, N, start, end)
+
+def EquiScan(name, N, start, end):
+    r"""EquiScan(std::string const & name, size_t N, double start, double end) -> Scale"""
+    return _libBornAgainBase.EquiScan(name, N, start, end)
 class Frame(ICloneable):
     r"""Proxy of C++ Frame class."""
 
diff --git a/auto/Wrap/libBornAgainBase_wrap.cpp b/auto/Wrap/libBornAgainBase_wrap.cpp
index 10406009406..502c690395f 100644
--- a/auto/Wrap/libBornAgainBase_wrap.cpp
+++ b/auto/Wrap/libBornAgainBase_wrap.cpp
@@ -25732,6 +25732,29 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Scale_isEquiScan(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  Scale *arg1 = (Scale *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  bool result;
+  
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Scale, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Scale_isEquiScan" "', argument " "1"" of type '" "Scale const *""'"); 
+  }
+  arg1 = reinterpret_cast< Scale * >(argp1);
+  result = (bool)((Scale const *)arg1)->isEquiScan();
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Scale_isScan(PyObject *self, PyObject *args) {
   PyObject *resultobj = 0;
   Scale *arg1 = (Scale *) 0 ;
@@ -26086,6 +26109,59 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_EquiScan(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  std::string *arg1 = 0 ;
+  size_t arg2 ;
+  double arg3 ;
+  double arg4 ;
+  int res1 = SWIG_OLDOBJ ;
+  size_t val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  PyObject *swig_obj[4] ;
+  SwigValueWrapper< Scale > result;
+  
+  if (!SWIG_Python_UnpackTuple(args, "EquiScan", 4, 4, swig_obj)) SWIG_fail;
+  {
+    std::string *ptr = (std::string *)0;
+    res1 = SWIG_AsPtr_std_string(swig_obj[0], &ptr);
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "EquiScan" "', argument " "1"" of type '" "std::string const &""'"); 
+    }
+    if (!ptr) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "EquiScan" "', argument " "1"" of type '" "std::string const &""'"); 
+    }
+    arg1 = ptr;
+  }
+  ecode2 = SWIG_AsVal_size_t(swig_obj[1], &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "EquiScan" "', argument " "2"" of type '" "size_t""'");
+  } 
+  arg2 = static_cast< size_t >(val2);
+  ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "EquiScan" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(swig_obj[3], &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "EquiScan" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  result = EquiScan((std::string const &)*arg1,SWIG_STD_MOVE(arg2),arg3,arg4);
+  resultobj = SWIG_NewPointerObj((new Scale(result)), SWIGTYPE_p_Scale, SWIG_POINTER_OWN |  0 );
+  if (SWIG_IsNewObj(res1)) delete arg1;
+  return resultobj;
+fail:
+  if (SWIG_IsNewObj(res1)) delete arg1;
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_new_Frame__SWIG_0(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   std::vector< Scale const *,std::allocator< Scale const * > > *arg1 = 0 ;
@@ -28705,6 +28781,7 @@ static PyMethodDef SwigMethods[] = {
 	 { "Scale_binCenters", _wrap_Scale_binCenters, METH_O, "Scale_binCenters(Scale self) -> vdouble1d_t"},
 	 { "Scale_closestIndex", _wrap_Scale_closestIndex, METH_VARARGS, "Scale_closestIndex(Scale self, double value) -> size_t"},
 	 { "Scale_isEquiDivision", _wrap_Scale_isEquiDivision, METH_O, "Scale_isEquiDivision(Scale self) -> bool"},
+	 { "Scale_isEquiScan", _wrap_Scale_isEquiScan, METH_O, "Scale_isEquiScan(Scale self) -> bool"},
 	 { "Scale_isScan", _wrap_Scale_isScan, METH_O, "Scale_isScan(Scale self) -> bool"},
 	 { "Scale_clipped", _wrap_Scale_clipped, METH_VARARGS, "\n"
 		"Scale_clipped(Scale self, double lower, double upper) -> Scale\n"
@@ -28718,6 +28795,7 @@ static PyMethodDef SwigMethods[] = {
 	 { "Scale_swiginit", Scale_swiginit, METH_VARARGS, NULL},
 	 { "ListScan", _wrap_ListScan, METH_VARARGS, "ListScan(std::string const & name, vdouble1d_t points) -> Scale"},
 	 { "EquiDivision", _wrap_EquiDivision, METH_VARARGS, "EquiDivision(std::string const & name, size_t N, double start, double end) -> Scale"},
+	 { "EquiScan", _wrap_EquiScan, METH_VARARGS, "EquiScan(std::string const & name, size_t N, double start, double end) -> Scale"},
 	 { "new_Frame", _wrap_new_Frame, METH_VARARGS, "\n"
 		"Frame(std::vector< Scale const *,std::allocator< Scale const * > > && axes)\n"
 		"Frame(Scale const *&& ax0)\n"
-- 
GitLab