From cd47b6b12c4b06413f713d7f91f090cf88f87f3b Mon Sep 17 00:00:00 2001
From: Matthias Puchner <github@mpuchner.de>
Date: Fri, 30 Apr 2021 16:01:36 +0200
Subject: [PATCH] refactor fitting tests to latest samplebuilder paradigm

A sample builder shall get the parameter values already at construction time, not afterwards.

This also eliminates the usage of registered parameters
---
 Sample/StandardSamples/CylindersBuilder.cpp   |  3 +-
 Sample/StandardSamples/CylindersBuilder.h     |  2 +-
 .../PlainMultiLayerBySLDBuilder.cpp           |  4 +-
 .../PlainMultiLayerBySLDBuilder.h             |  2 +-
 Sample/StandardSamples/ResonatorBuilder.cpp   |  3 +-
 Sample/StandardSamples/ResonatorBuilder.h     |  2 +-
 .../Core/Fitting/AdjustMinimizerPlan.cpp      | 11 ++-
 .../Core/Fitting/AdjustMinimizerPlan.h        |  4 +
 Tests/Functional/Core/Fitting/Plan.cpp        | 18 -----
 Tests/Functional/Core/Fitting/Plan.h          |  7 +-
 Tests/Functional/Core/Fitting/PlanCases.cpp   | 76 +++++++++++++++++--
 Tests/Functional/Core/Fitting/PlanCases.h     | 29 +++++++
 12 files changed, 124 insertions(+), 37 deletions(-)

diff --git a/Sample/StandardSamples/CylindersBuilder.cpp b/Sample/StandardSamples/CylindersBuilder.cpp
index bef842f6d59..17758944682 100644
--- a/Sample/StandardSamples/CylindersBuilder.cpp
+++ b/Sample/StandardSamples/CylindersBuilder.cpp
@@ -50,7 +50,8 @@ MultiLayer* CylindersInDWBABuilder::buildSample() const
 // -----------------------------------------------------------------------------
 // Cylinders in BA
 // -----------------------------------------------------------------------------
-CylindersInBABuilder::CylindersInBABuilder() : m_height(5 * Units::nm), m_radius(5 * Units::nm)
+CylindersInBABuilder::CylindersInBABuilder(double height, double radius)
+    : m_height(height * Units::nm), m_radius(radius * Units::nm)
 {
     registerParameter("height", &m_height);
     registerParameter("radius", &m_radius);
diff --git a/Sample/StandardSamples/CylindersBuilder.h b/Sample/StandardSamples/CylindersBuilder.h
index 280fa725be6..6f85f664567 100644
--- a/Sample/StandardSamples/CylindersBuilder.h
+++ b/Sample/StandardSamples/CylindersBuilder.h
@@ -40,7 +40,7 @@ private:
 
 class CylindersInBABuilder : public ISampleBuilder {
 public:
-    CylindersInBABuilder();
+    CylindersInBABuilder(double height = 5, double radius = 5);
     MultiLayer* buildSample() const;
 
 private:
diff --git a/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.cpp b/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.cpp
index 477ecd52cf6..b3d0edf3761 100644
--- a/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.cpp
+++ b/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.cpp
@@ -18,12 +18,12 @@
 #include "Sample/Multilayer/Layer.h"
 #include "Sample/Multilayer/MultiLayer.h"
 
-PlainMultiLayerBySLDBuilder::PlainMultiLayerBySLDBuilder(int n_layers)
+PlainMultiLayerBySLDBuilder::PlainMultiLayerBySLDBuilder(int n_layers, double thick_ti)
     : m_number_of_layers(n_layers)
     , m_si{2.0704e-06, 2.3726e-11}
     , m_ti{-1.9493e-06, 9.6013e-10}
     , m_ni{9.4245e-06, 1.1423e-09}
-    , m_thick_ti(3.0)
+    , m_thick_ti(thick_ti)
     , m_thick_ni(7.0)
 {
     registerParameter("ti_thickness", &m_thick_ti);
diff --git a/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.h b/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.h
index 22e136d2f8b..640208ac5e3 100644
--- a/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.h
+++ b/Sample/StandardSamples/PlainMultiLayerBySLDBuilder.h
@@ -28,7 +28,7 @@
 
 class PlainMultiLayerBySLDBuilder : public ISampleBuilder {
 public:
-    PlainMultiLayerBySLDBuilder(int n_layers = 10);
+    PlainMultiLayerBySLDBuilder(int n_layers = 10, double thick_ti = 3.0);
     MultiLayer* buildSample() const override; // passes ownership
 
 protected:
diff --git a/Sample/StandardSamples/ResonatorBuilder.cpp b/Sample/StandardSamples/ResonatorBuilder.cpp
index 073083a76bc..d0bb6fa3ee0 100644
--- a/Sample/StandardSamples/ResonatorBuilder.cpp
+++ b/Sample/StandardSamples/ResonatorBuilder.cpp
@@ -20,7 +20,8 @@
 #include "Sample/Slice/LayerRoughness.h"
 #include <memory>
 
-ResonatorBuilder::ResonatorBuilder() : ISampleBuilder(), m_l_ti(13.0 * Units::nm)
+ResonatorBuilder::ResonatorBuilder(double ti_thickness)
+    : ISampleBuilder(), m_l_ti(ti_thickness * Units::nm)
 {
     registerParameter("ti_thickness", &m_l_ti);
 }
diff --git a/Sample/StandardSamples/ResonatorBuilder.h b/Sample/StandardSamples/ResonatorBuilder.h
index a5b936ff744..387b2dd4536 100644
--- a/Sample/StandardSamples/ResonatorBuilder.h
+++ b/Sample/StandardSamples/ResonatorBuilder.h
@@ -27,7 +27,7 @@
 
 class ResonatorBuilder : public ISampleBuilder {
 public:
-    ResonatorBuilder();
+    ResonatorBuilder(double ti_thickness = 13.0);
     MultiLayer* buildSample() const;
 
 private:
diff --git a/Tests/Functional/Core/Fitting/AdjustMinimizerPlan.cpp b/Tests/Functional/Core/Fitting/AdjustMinimizerPlan.cpp
index 6f0483bbba9..06d97529a08 100644
--- a/Tests/Functional/Core/Fitting/AdjustMinimizerPlan.cpp
+++ b/Tests/Functional/Core/Fitting/AdjustMinimizerPlan.cpp
@@ -16,6 +16,8 @@
 #include "Base/Const/Units.h"
 #include "Core/Fitting/FitObjective.h"
 #include "Fit/Kernel/Minimizer.h"
+#include "Sample/Multilayer/MultiLayer.h"
+#include "Sample/StandardSamples/CylindersBuilder.h"
 #include <iostream>
 
 namespace {
@@ -26,7 +28,6 @@ using namespace mumufit;
 
 AdjustMinimizerPlan::AdjustMinimizerPlan() : Plan("AdjustMinimizerPlan")
 {
-    setBuilderName("CylindersInBABuilder");
     setSimulationName("MiniGISASFit");
     addParameter(Parameter("height", 2.0 * nm, AttLimits::limited(0.01, 30.0), 0.05), 5.0 * nm);
     addParameter(Parameter("radius", 10.0 * nm, AttLimits::limited(0.01, 30.0), 0.05), 5.0 * nm);
@@ -59,3 +60,11 @@ bool AdjustMinimizerPlan::checkMinimizer(mumufit::Minimizer& minimizer)
 
     return success;
 }
+
+std::unique_ptr<MultiLayer>
+AdjustMinimizerPlan::createMultiLayer(const mumufit::Parameters& params) const
+{
+    CylindersInBABuilder sampleBuilder(params["height"].value(), params["radius"].value());
+
+    return std::unique_ptr<MultiLayer>(sampleBuilder.buildSample());
+}
diff --git a/Tests/Functional/Core/Fitting/AdjustMinimizerPlan.h b/Tests/Functional/Core/Fitting/AdjustMinimizerPlan.h
index 9ab90761286..0639b60ea9a 100644
--- a/Tests/Functional/Core/Fitting/AdjustMinimizerPlan.h
+++ b/Tests/Functional/Core/Fitting/AdjustMinimizerPlan.h
@@ -25,6 +25,10 @@ public:
     AdjustMinimizerPlan();
 
     bool checkMinimizer(mumufit::Minimizer& minimizer);
+
+protected:
+    virtual std::unique_ptr<MultiLayer>
+    createMultiLayer(const mumufit::Parameters& params) const override;
 };
 
 #endif // BORNAGAIN_TESTS_FUNCTIONAL_CORE_FITTING_ADJUSTMINIMIZERPLAN_H
diff --git a/Tests/Functional/Core/Fitting/Plan.cpp b/Tests/Functional/Core/Fitting/Plan.cpp
index ae888bebfe8..822cb482b7a 100644
--- a/Tests/Functional/Core/Fitting/Plan.cpp
+++ b/Tests/Functional/Core/Fitting/Plan.cpp
@@ -55,11 +55,6 @@ bool Plan::checkMinimizer(mumufit::Minimizer& minimizer)
     return success;
 }
 
-void Plan::setBuilderName(const std::string& name)
-{
-    m_sample_builder_name = name;
-}
-
 void Plan::setSimulationName(const std::string& name)
 {
     m_simulation_name = name;
@@ -96,19 +91,6 @@ std::unique_ptr<ISimulation> Plan::createSimulation(const mumufit::Parameters&)
     return SimulationFactory().createItemPtr(m_simulation_name);
 }
 
-//! Creates sample for given set of fit parameters.
-
-std::unique_ptr<MultiLayer> Plan::createMultiLayer(const mumufit::Parameters& params) const
-{
-    auto sample_builder = SampleBuilderFactory().createItemPtr(m_sample_builder_name);
-
-    // propagating current values of fit parameters to sample builder before building the sample
-    for (const auto& par : params)
-        sample_builder->registeredParameter(par.name())->setValue(par.value());
-
-    return std::unique_ptr<MultiLayer>(sample_builder->buildSample());
-}
-
 //! Creates "experimental" data for fitting.
 
 std::unique_ptr<OutputData<double>> Plan::createOutputData() const
diff --git a/Tests/Functional/Core/Fitting/Plan.h b/Tests/Functional/Core/Fitting/Plan.h
index a39e2a37aec..621a1c85dca 100644
--- a/Tests/Functional/Core/Fitting/Plan.h
+++ b/Tests/Functional/Core/Fitting/Plan.h
@@ -36,18 +36,19 @@ public:
 
     virtual bool checkMinimizer(mumufit::Minimizer& minimizer);
 
-    void setBuilderName(const std::string& name);
     void setSimulationName(const std::string& name);
 
 protected:
     virtual std::unique_ptr<FitObjective> createFitObjective() const;
     virtual std::unique_ptr<ISimulation> buildSimulation(const mumufit::Parameters& params) const;
     virtual std::unique_ptr<ISimulation> createSimulation(const mumufit::Parameters& params) const;
-    virtual std::unique_ptr<MultiLayer> createMultiLayer(const mumufit::Parameters& params) const;
+
+    //! Creates sample for given set of fit parameters.
+    virtual std::unique_ptr<MultiLayer>
+    createMultiLayer(const mumufit::Parameters& params) const = 0;
     virtual std::unique_ptr<OutputData<double>> createOutputData() const;
 
     std::string m_simulation_name;
-    std::string m_sample_builder_name;
     bool m_residual_based;
 };
 
diff --git a/Tests/Functional/Core/Fitting/PlanCases.cpp b/Tests/Functional/Core/Fitting/PlanCases.cpp
index cac0eb79f7d..46b1e63df26 100644
--- a/Tests/Functional/Core/Fitting/PlanCases.cpp
+++ b/Tests/Functional/Core/Fitting/PlanCases.cpp
@@ -25,6 +25,9 @@
 #include "Sample/Multilayer/Layer.h"
 #include "Sample/Multilayer/MultiLayer.h"
 #include "Sample/Particle/Particle.h"
+#include "Sample/StandardSamples/CylindersBuilder.h"
+#include "Sample/StandardSamples/PlainMultiLayerBySLDBuilder.h"
+#include "Sample/StandardSamples/ResonatorBuilder.h"
 
 using namespace mumufit;
 
@@ -34,15 +37,23 @@ const double nm = Units::nm;
 
 CylindersInBAPlan::CylindersInBAPlan() : Plan("CylindersInBAPlan")
 {
-    setBuilderName("CylindersInBABuilder");
     setSimulationName("MiniGISAS");
     addParameter(Parameter("height", 4.5 * nm, AttLimits::lowerLimited(0.01), 0.01), 5.0 * nm);
     addParameter(Parameter("radius", 5.5 * nm, AttLimits::lowerLimited(0.01), 0.01), 5.0 * nm);
 }
 
+std::unique_ptr<MultiLayer>
+CylindersInBAPlan::createMultiLayer(const mumufit::Parameters& params) const
+{
+    CylindersInBABuilder sampleBuilder(params["height"].value(), params["radius"].value());
+
+    return std::unique_ptr<MultiLayer>(sampleBuilder.buildSample());
+}
+
+// ----------------------------------------------------------------------------
+
 CylindersInBAEasyPlan::CylindersInBAEasyPlan() : Plan("CylindersInBAEasyPlan")
 {
-    setBuilderName("CylindersInBABuilder");
     setSimulationName("MiniGISASFit");
     const double tolerance = 0.1;
     addParameter(Parameter("height", 4.5 * nm, AttLimits::limited(4.0, 6.0), 0.1), 5.0 * nm,
@@ -51,20 +62,36 @@ CylindersInBAEasyPlan::CylindersInBAEasyPlan() : Plan("CylindersInBAEasyPlan")
                  tolerance);
 }
 
+std::unique_ptr<MultiLayer>
+CylindersInBAEasyPlan::createMultiLayer(const mumufit::Parameters& params) const
+{
+    CylindersInBABuilder sampleBuilder(params["height"].value(), params["radius"].value());
+
+    return std::unique_ptr<MultiLayer>(sampleBuilder.buildSample());
+}
+
+// ----------------------------------------------------------------------------
+
 CylindersInBAResidualPlan::CylindersInBAResidualPlan()
     : Plan("CylindersInBAResidualPlan", /*residual_based*/ true)
 {
-    setBuilderName("CylindersInBABuilder");
     setSimulationName("MiniGISAS");
     addParameter(Parameter("height", 4.5 * nm, AttLimits::limitless(), 0.01), 5.0 * nm);
     addParameter(Parameter("radius", 5.5 * nm, AttLimits::limitless(), 0.01), 5.0 * nm);
 }
 
+std::unique_ptr<MultiLayer>
+CylindersInBAResidualPlan::createMultiLayer(const mumufit::Parameters& params) const
+{
+    CylindersInBABuilder sampleBuilder(params["height"].value(), params["radius"].value());
+
+    return std::unique_ptr<MultiLayer>(sampleBuilder.buildSample());
+}
+
 // ----------------------------------------------------------------------------
 
 RectDetPlan::RectDetPlan() : Plan("RectDetPlan")
 {
-    setBuilderName("CylindersInBABuilder");
     addParameter(Parameter("height", 4.5 * nm, AttLimits::limited(4.0, 6.0), 0.01), 5.0 * nm);
     addParameter(Parameter("radius", 5.5 * nm, AttLimits::limited(4.0, 6.0), 0.01), 5.0 * nm);
 }
@@ -87,32 +114,50 @@ std::unique_ptr<ISimulation> RectDetPlan::createSimulation(const Parameters&) co
     return std::unique_ptr<ISimulation>(result.release());
 }
 
+std::unique_ptr<MultiLayer> RectDetPlan::createMultiLayer(const mumufit::Parameters& params) const
+{
+    CylindersInBABuilder sampleBuilder(params["height"].value(), params["radius"].value());
+
+    return std::unique_ptr<MultiLayer>(sampleBuilder.buildSample());
+}
+
 // ----------------------------------------------------------------------------
 
 SpecularPlan::SpecularPlan() : Plan("SpecularPlan")
 {
     setSimulationName("BasicSpecular");
-    setBuilderName("PlainMultiLayerBySLDBuilder");
     addParameter(Parameter("ti_thickness", 5.0 * nm, AttLimits::limited(1.0 * nm, 7.0 * nm), 0.1),
                  3.0 * nm);
 }
 
+std::unique_ptr<MultiLayer> SpecularPlan::createMultiLayer(const mumufit::Parameters& params) const
+{
+    PlainMultiLayerBySLDBuilder sampleBuilder(10, params["ti_thickness"].value());
+
+    return std::unique_ptr<MultiLayer>(sampleBuilder.buildSample());
+}
+
 // ----------------------------------------------------------------------------
 
 SpecularPlanQ::SpecularPlanQ() : Plan("SpecularPlanQ")
 {
     setSimulationName("BasicSpecularQ");
-    setBuilderName("PlainMultiLayerBySLDBuilder");
     addParameter(Parameter("ti_thickness", 5.0 * nm, AttLimits::limited(1.0 * nm, 7.0 * nm), 0.1),
                  3.0 * nm);
 }
 
+std::unique_ptr<MultiLayer> SpecularPlanQ::createMultiLayer(const mumufit::Parameters& params) const
+{
+    PlainMultiLayerBySLDBuilder sampleBuilder(10, params["ti_thickness"].value());
+
+    return std::unique_ptr<MultiLayer>(sampleBuilder.buildSample());
+}
+
 // ----------------------------------------------------------------------------
 
 MultipleSpecPlan::MultipleSpecPlan() : Plan("MultipleSpecPlan")
 {
     setSimulationName("BasicSpecular");
-    setBuilderName("PlainMultiLayerBySLDBuilder");
     addParameter(Parameter("ti_thickness", 5.0 * nm, AttLimits::limited(1.0 * nm, 7.0 * nm), 0.1),
                  3.0 * nm);
 }
@@ -134,13 +179,28 @@ std::unique_ptr<FitObjective> MultipleSpecPlan::createFitObjective() const
     return result;
 }
 
+std::unique_ptr<MultiLayer>
+MultipleSpecPlan::createMultiLayer(const mumufit::Parameters& params) const
+{
+    PlainMultiLayerBySLDBuilder sampleBuilder(10, params["ti_thickness"].value());
+
+    return std::unique_ptr<MultiLayer>(sampleBuilder.buildSample());
+}
+
 // ----------------------------------------------------------------------------
 
 OffSpecularPlan::OffSpecularPlan() : Plan("OffSpecularPlan")
 {
-    setBuilderName("ResonatorBuilder");
     setSimulationName("OffSpecularMini");
     addParameter(
         Parameter("ti_thickness", 12.0 * nm, AttLimits::limited(11.5 * nm, 14.0 * nm), 0.1 * nm),
         13.0 * nm);
 }
+
+std::unique_ptr<MultiLayer>
+OffSpecularPlan::createMultiLayer(const mumufit::Parameters& params) const
+{
+    ResonatorBuilder sampleBuilder(params["ti_thickness"].value());
+
+    return std::unique_ptr<MultiLayer>(sampleBuilder.buildSample());
+}
diff --git a/Tests/Functional/Core/Fitting/PlanCases.h b/Tests/Functional/Core/Fitting/PlanCases.h
index 6d44ae542b4..c05ab6ba737 100644
--- a/Tests/Functional/Core/Fitting/PlanCases.h
+++ b/Tests/Functional/Core/Fitting/PlanCases.h
@@ -22,6 +22,10 @@
 class CylindersInBAPlan : public Plan {
 public:
     CylindersInBAPlan();
+
+protected:
+    virtual std::unique_ptr<MultiLayer>
+    createMultiLayer(const mumufit::Parameters& params) const override;
 };
 
 //! Two parameter fit: cylinders in BA with mini GISAS simulation.
@@ -30,6 +34,10 @@ public:
 class CylindersInBAEasyPlan : public Plan {
 public:
     CylindersInBAEasyPlan();
+
+protected:
+    virtual std::unique_ptr<MultiLayer>
+    createMultiLayer(const mumufit::Parameters& params) const override;
 };
 
 //! Two parameter fit: cylinders in BA with mini GISAS simulation.
@@ -38,6 +46,10 @@ public:
 class CylindersInBAResidualPlan : public Plan {
 public:
     CylindersInBAResidualPlan();
+
+protected:
+    virtual std::unique_ptr<MultiLayer>
+    createMultiLayer(const mumufit::Parameters& params) const override;
 };
 
 //! Two parameter fit: cylinders in BA with mini GISAS simulation.
@@ -50,6 +62,8 @@ public:
 
 protected:
     std::unique_ptr<ISimulation> createSimulation(const mumufit::Parameters&) const;
+    virtual std::unique_ptr<MultiLayer>
+    createMultiLayer(const mumufit::Parameters& params) const override;
 };
 
 //! Plan for fitting reflectometry curve on Ti/Ni multilayer
@@ -57,6 +71,10 @@ protected:
 class SpecularPlan : public Plan {
 public:
     SpecularPlan();
+
+protected:
+    virtual std::unique_ptr<MultiLayer>
+    createMultiLayer(const mumufit::Parameters& params) const override;
 };
 
 //! Plan for fitting reflectometry curve on Ti/Ni multilayer (q-defined beam)
@@ -64,6 +82,10 @@ public:
 class SpecularPlanQ : public Plan {
 public:
     SpecularPlanQ();
+
+protected:
+    virtual std::unique_ptr<MultiLayer>
+    createMultiLayer(const mumufit::Parameters& params) const override;
 };
 
 //! The same as SpecularPlan, but with two (identical) datasets
@@ -75,6 +97,9 @@ public:
 
 protected:
     std::unique_ptr<FitObjective> createFitObjective() const override;
+
+    virtual std::unique_ptr<MultiLayer>
+    createMultiLayer(const mumufit::Parameters& params) const override;
 };
 
 //! Fit for off-specular experiment
@@ -83,6 +108,10 @@ class OffSpecularPlan : public Plan {
 public:
     OffSpecularPlan();
     ~OffSpecularPlan() override = default;
+
+protected:
+    virtual std::unique_ptr<MultiLayer>
+    createMultiLayer(const mumufit::Parameters& params) const override;
 };
 
 #endif // BORNAGAIN_TESTS_FUNCTIONAL_CORE_FITTING_PLANCASES_H
-- 
GitLab