From b938a855e3a7f9cf5da805f61d0db06aaf5dbcaf Mon Sep 17 00:00:00 2001
From: Antonin Portelli <antonin.portelli@me.com>
Date: Fri, 19 Jan 2024 22:39:52 -0300
Subject: [PATCH] DataFilter cleanup and Laplacian filter with CDR optimisation

---
 lib/Physics/DataFilter.cpp | 24 ++++------
 lib/Physics/DataFilter.hpp | 93 +++++++++++++++++++++++++++++++++++---
 2 files changed, 97 insertions(+), 20 deletions(-)

diff --git a/lib/Physics/DataFilter.cpp b/lib/Physics/DataFilter.cpp
index c4fbfda..acded7a 100644
--- a/lib/Physics/DataFilter.cpp
+++ b/lib/Physics/DataFilter.cpp
@@ -24,10 +24,15 @@
 using namespace std;
 using namespace Latan;
 
+/******************************************************************************
+ *                        DataFilter implementation                           *
+ ******************************************************************************/
+// constructor ////////////////////////////////////////////////////////////////
 DataFilter::DataFilter(const vector<double> &filter, const bool downsample)
 : filter_(filter), downsample_(downsample)
 {}
 
+// filtering //////////////////////////////////////////////////////////////////
 template <typename MatType>
 void filter(MatType &out, const MatType &in, const vector<double> &filter, 
             const bool downsample, MatType &buf)
@@ -56,18 +61,15 @@ void DataFilter::operator()(DMat &out, const DMat &in)
     filter(out, in, filter_, downsample_, mBuf_);
 }
 
-void DataFilter::operator()(DMatSample &out, const DMatSample &in)
-{
-    FOR_STAT_ARRAY(in, s)
-    {
-        (*this)(out[s], in[s]);
-    }
-}
-
+/******************************************************************************
+ *                     LaplaceDataFilter implementation                       *
+ ******************************************************************************/
+// constructor ////////////////////////////////////////////////////////////////
 LaplaceDataFilter::LaplaceDataFilter(const bool downsample)
 : DataFilter({1., -2. , 1.}, downsample)
 {}
 
+// filtering //////////////////////////////////////////////////////////////////
 void LaplaceDataFilter::operator()(DVec &out, const DVec &in, const double lambda)
 {
     filter_[1] = -2. - lambda;
@@ -79,9 +81,3 @@ void LaplaceDataFilter::operator()(DMat &out, const DMat &in, const double lambd
     filter_[1] = -2. - lambda;
     DataFilter::operator()(out, in);
 }
-
-void LaplaceDataFilter::operator()(DMatSample &out, const DMatSample &in, const double lambda)
-{
-    filter_[1] = -2. - lambda;
-    DataFilter::operator()(out, in);
-}
diff --git a/lib/Physics/DataFilter.hpp b/lib/Physics/DataFilter.hpp
index 25fc4a6..9bc45df 100644
--- a/lib/Physics/DataFilter.hpp
+++ b/lib/Physics/DataFilter.hpp
@@ -21,19 +21,26 @@
 #define Latan_DataFilter_hpp_
 
 #include <LatAnalyze/Global.hpp>
+#include <LatAnalyze/Core/Math.hpp>
+#include <LatAnalyze/Statistics/StatArray.hpp>
 #include <LatAnalyze/Statistics/MatSample.hpp>
+#include <LatAnalyze/Numerical/Minimizer.hpp>
 
 BEGIN_LATAN_NAMESPACE
 
+/******************************************************************************
+ *                    Generic convolution filter class                        *
+ ******************************************************************************/
 class DataFilter
 {
 public:
     // constructor
     DataFilter(const std::vector<double> &filter, const bool downsample = false);
     // filtering
-    virtual void operator()(DVec &out, const DVec &in);
-    virtual void operator()(DMat &out, const DMat &in);
-    virtual void operator()(DMatSample &out, const DMatSample &in);
+    void operator()(DVec &out, const DVec &in);
+    void operator()(DMat &out, const DMat &in);
+    template <typename MatType, Index o>
+    void operator()(StatArray<MatType, o> &out, const StatArray<MatType, o> &in);
 protected:
     std::vector<double> filter_;
 private:
@@ -42,17 +49,91 @@ class DataFilter
     DMat                mBuf_;
 };
 
+/******************************************************************************
+ *                         Laplacian filter class                             *
+ ******************************************************************************/
 class LaplaceDataFilter: public DataFilter
 {
 public:
     // constructor
     LaplaceDataFilter(const bool downsample = false);
     // filtering
-    virtual void operator()(DVec &out, const DVec &in, const double lambda = 0.);
-    virtual void operator()(DMat &out, const DMat &in, const double lambda = 0.);
-    virtual void operator()(DMatSample &out, const DMatSample &in, const double lambda = 0.);
+    void operator()(DVec &out, const DVec &in, const double lambda = 0.);
+    void operator()(DMat &out, const DMat &in, const double lambda = 0.);
+    template <typename MatType, Index o>
+    void operator()(StatArray<MatType, o> &out, const StatArray<MatType, o> &in, 
+                    const double lambda = 0.);
+    // correlation optimisation
+    template <typename MatType, Index o>
+    double optimiseCdr(const StatArray<MatType, o> &data, Minimizer &min,
+                       const unsigned int nPass = 3);
 };
 
+/******************************************************************************
+ *                 DataFilter class template implementation                   *
+ ******************************************************************************/
+// filtering //////////////////////////////////////////////////////////////////
+template <typename MatType, Index o>
+void DataFilter::operator()(StatArray<MatType, o> &out, const StatArray<MatType, o> &in)
+{
+    FOR_STAT_ARRAY(in, s)
+    {
+        (*this)(out[s], in[s]);
+    }
+}
+
+/******************************************************************************
+ *            LaplaceDataFilter class template implementation                 *
+ ******************************************************************************/
+// filtering //////////////////////////////////////////////////////////////////
+template <typename MatType, Index o>
+void LaplaceDataFilter::operator()(StatArray<MatType, o> &out, 
+                                   const StatArray<MatType, o> &in, const double lambda)
+{
+    FOR_STAT_ARRAY(in, s)
+    {
+        (*this)(out[s], in[s], lambda);
+    }
+}
+
+// correlation optimisation ///////////////////////////////////////////////////
+template <typename MatType, Index o>
+double LaplaceDataFilter::optimiseCdr(const StatArray<MatType, o> &data, 
+                                      Minimizer &min, const unsigned int nPass)
+{
+    StatArray<MatType, o> fdata(data.size());
+    DVec init(1);
+    double reg, prec;
+    DoubleFunction cdr([&data, &fdata, this](const double *x)
+    {
+        double res;
+        (*this)(fdata, data, x[0]);
+        res = Math::cdr(fdata.correlationMatrix());
+        
+        return res;
+    }, 1);
+
+    min.setLowLimit(0., -0.1);
+    min.setHighLimit(0., 100000.);
+    init(0) = 0.1;
+    min.setInit(init);
+    prec = 0.1;
+    min.setPrecision(prec);
+    reg = min(cdr)(0);
+    for (unsigned int pass = 0; pass < nPass; pass++)
+    {
+        min.setLowLimit(0., (1.-10.*prec)*reg);
+        min.setHighLimit(0., (1.+10.*prec)*reg);
+        init(0) = reg;
+        min.setInit(init);
+        prec *= 0.1;
+        min.setPrecision(prec);
+        reg = min(cdr)(0);
+    }
+
+    return reg;
+}
+
 END_LATAN_NAMESPACE
 
 #endif // Latan_DataFilter_hpp_