From 04d5f7016967a0de1eb01e35fc6cd63f81d9033c Mon Sep 17 00:00:00 2001
From: Gennady Pospelov <g.pospelov@fz-juelich.de>
Date: Fri, 22 Sep 2017 12:17:41 +0200
Subject: [PATCH] Draft of multiple-sample support in MultiLayerBuilder

---
 Core/Multilayer/IMultiLayerBuilder.h          |  3 ++
 .../LayersWithAbsorptionBuilder.cpp           | 28 +++++++++++++++++++
 .../LayersWithAbsorptionBuilder.h             |  7 +++++
 Core/StandardSamples/ParaCrystalBuilder.cpp   | 27 ++++++++++++++++++
 Core/StandardSamples/ParaCrystalBuilder.h     |  6 ++++
 .../ParticleInTheAirBuilder.cpp               | 27 ++++++++++++++++++
 .../StandardSamples/ParticleInTheAirBuilder.h |  8 ++++++
 7 files changed, 106 insertions(+)

diff --git a/Core/Multilayer/IMultiLayerBuilder.h b/Core/Multilayer/IMultiLayerBuilder.h
index 00bf90dd3e3..6d1cc7e5882 100644
--- a/Core/Multilayer/IMultiLayerBuilder.h
+++ b/Core/Multilayer/IMultiLayerBuilder.h
@@ -44,6 +44,9 @@ public:
 
     // Without duplication below PythonBindings doesn't work for shared_ptr<IMultiLayerBuilder>
     virtual void onChange() {}
+
+    virtual MultiLayer* createSample(size_t index=0) { (void)index; return buildSample(); }
+    virtual size_t size() { return 1;}
 };
 
 #endif // IMULTILAYERBUILDER_H
diff --git a/Core/StandardSamples/LayersWithAbsorptionBuilder.cpp b/Core/StandardSamples/LayersWithAbsorptionBuilder.cpp
index 558d9a856bc..9c42ca71615 100644
--- a/Core/StandardSamples/LayersWithAbsorptionBuilder.cpp
+++ b/Core/StandardSamples/LayersWithAbsorptionBuilder.cpp
@@ -24,6 +24,7 @@
 #include "ParticleLayout.h"
 #include "RealParameter.h"
 #include "Units.h"
+#include "SubtestRegistry.h"
 
 MultiLayer* LayersWithAbsorptionBuilder::buildSample() const
 {
@@ -60,3 +61,30 @@ MultiLayer* LayersWithAbsorptionBuilder::buildSample() const
     multi_layer->addLayer(substrate);
     return multi_layer;
 }
+
+MultiLayer* LayersWithAbsorptionBuilder::createSample(size_t index)
+{
+    if(index >= size())
+        throw std::runtime_error("ParticleInTheAirBuilder::createSample() -> Error. "
+                                 "Sample index is out of range.");
+
+    auto ff_names = ff_registry().keys();
+    m_subtest_item = ff_registry().getItem(ff_names[index]);
+
+    setName(ff_names[index]);
+
+    return buildSample();
+}
+
+size_t LayersWithAbsorptionBuilder::size()
+{
+    static size_t result = ff_registry().keys().size();
+    return result;
+}
+
+SubtestRegistryFormFactor& LayersWithAbsorptionBuilder::ff_registry()
+{
+    static SubtestRegistryFormFactor result = SubtestRegistryFormFactor();
+    return result;
+}
+
diff --git a/Core/StandardSamples/LayersWithAbsorptionBuilder.h b/Core/StandardSamples/LayersWithAbsorptionBuilder.h
index 226d381f9e1..cdf83a89a84 100644
--- a/Core/StandardSamples/LayersWithAbsorptionBuilder.h
+++ b/Core/StandardSamples/LayersWithAbsorptionBuilder.h
@@ -17,6 +17,7 @@
 #define LAYERSWITHABSORPTIONBUILDER_H
 
 #include "IMultiLayerBuilder.h"
+class SubtestRegistryFormFactor;
 
 //! The LayersWithAbsorptionBuilder class generates a multilayer with 3 layers with
 //! absorption (refractive index has imaginary part).
@@ -31,6 +32,12 @@ public:
     LayersWithAbsorptionBuilder() {}
     virtual ~LayersWithAbsorptionBuilder() {}
     virtual MultiLayer* buildSample() const;
+
+    MultiLayer* createSample(size_t index=0);
+    size_t size();
+
+private:
+    SubtestRegistryFormFactor& ff_registry();
 };
 
 #endif // LAYERSWITHABSORPTIONBUILDER_H
diff --git a/Core/StandardSamples/ParaCrystalBuilder.cpp b/Core/StandardSamples/ParaCrystalBuilder.cpp
index 044e3471e24..a2f30b51637 100644
--- a/Core/StandardSamples/ParaCrystalBuilder.cpp
+++ b/Core/StandardSamples/ParaCrystalBuilder.cpp
@@ -24,6 +24,7 @@
 #include "ParticleLayout.h"
 #include "RealParameter.h"
 #include "Units.h"
+#include "SubtestRegistry.h"
 
 RadialParaCrystalBuilder::RadialParaCrystalBuilder()
     : m_corr_peak_distance(20.0*Units::nanometer)
@@ -129,6 +130,32 @@ MultiLayer* Basic2DParaCrystalBuilder::buildSample() const
     return multi_layer;
 }
 
+MultiLayer* Basic2DParaCrystalBuilder::createSample(size_t index)
+{
+    if(index >= size())
+        throw std::runtime_error("Basic2DParaCrystalBuilder::createSample() -> Error. "
+                                 "Sample index is out of range.");
+
+    auto names = pdf_registry().keys();
+    m_subtest_item = pdf_registry().getItem(names[index]);
+
+    setName(names[index]);
+
+    return buildSample();
+}
+
+size_t Basic2DParaCrystalBuilder::size()
+{
+    static size_t result = pdf_registry().keys().size();
+    return result;
+}
+
+SubtestRegistryFTDistribution2D& Basic2DParaCrystalBuilder::pdf_registry()
+{
+    static SubtestRegistryFTDistribution2D result = SubtestRegistryFTDistribution2D();
+    return result;
+}
+
 
 
 // -----------------------------------------------------------------------------
diff --git a/Core/StandardSamples/ParaCrystalBuilder.h b/Core/StandardSamples/ParaCrystalBuilder.h
index 1c40c87c4e1..fa3a2e07bdd 100644
--- a/Core/StandardSamples/ParaCrystalBuilder.h
+++ b/Core/StandardSamples/ParaCrystalBuilder.h
@@ -21,6 +21,7 @@
 
 class IFTDistribution2D;
 class ISample;
+class SubtestRegistryFTDistribution2D;
 
 //! @ingroup standard_samples
 //! Builds sample: cylinders with 1DDL structure factor (IsGISAXS example #4).
@@ -52,7 +53,12 @@ public:
     Basic2DParaCrystalBuilder();
     virtual ~Basic2DParaCrystalBuilder();
     virtual MultiLayer* buildSample() const;
+
+    MultiLayer* createSample(size_t index=0);
+    size_t size();
+
 private:
+    SubtestRegistryFTDistribution2D& pdf_registry();
     std::unique_ptr<IFTDistribution2D> m_pdf1;
     std::unique_ptr<IFTDistribution2D> m_pdf2;
 };
diff --git a/Core/StandardSamples/ParticleInTheAirBuilder.cpp b/Core/StandardSamples/ParticleInTheAirBuilder.cpp
index e0f65197e45..89adc8b79ac 100644
--- a/Core/StandardSamples/ParticleInTheAirBuilder.cpp
+++ b/Core/StandardSamples/ParticleInTheAirBuilder.cpp
@@ -21,6 +21,7 @@
 #include "Particle.h"
 #include "ParticleLayout.h"
 #include "RealParameter.h"
+#include "SubtestRegistry.h"
 
 MultiLayer* ParticleInTheAirBuilder::buildSample() const
 {
@@ -43,3 +44,29 @@ MultiLayer* ParticleInTheAirBuilder::buildSample() const
 
     return result;
 }
+
+MultiLayer* ParticleInTheAirBuilder::createSample(size_t index)
+{
+    if(index >= size())
+        throw std::runtime_error("ParticleInTheAirBuilder::createSample() -> Error. "
+                                 "Sample index is out of range.");
+
+    auto ff_names = ff_registry().keys();
+    m_subtest_item = ff_registry().getItem(ff_names[index]);
+
+    setName(ff_names[index]);
+
+    return buildSample();
+}
+
+size_t ParticleInTheAirBuilder::size()
+{
+    static size_t result = ff_registry().keys().size();
+    return result;
+}
+
+SubtestRegistryFormFactor& ParticleInTheAirBuilder::ff_registry()
+{
+    static SubtestRegistryFormFactor result = SubtestRegistryFormFactor();
+    return result;
+}
diff --git a/Core/StandardSamples/ParticleInTheAirBuilder.h b/Core/StandardSamples/ParticleInTheAirBuilder.h
index 49d1b13273e..6b790a88e26 100644
--- a/Core/StandardSamples/ParticleInTheAirBuilder.h
+++ b/Core/StandardSamples/ParticleInTheAirBuilder.h
@@ -18,6 +18,8 @@
 
 #include "IMultiLayerBuilder.h"
 
+class SubtestRegistryFormFactor;
+
 //! The ParticleInTheAirBuilder class generates a multilayer with single air layer
 //! populated with particles of certain types.
 //! Requires IComponentService which generates form factors, used for bulk form factors testing.
@@ -29,6 +31,12 @@ public:
     ParticleInTheAirBuilder() {}
     virtual ~ParticleInTheAirBuilder() {}
     virtual MultiLayer* buildSample() const;
+
+    MultiLayer* createSample(size_t index=0);
+    size_t size();
+
+private:
+    SubtestRegistryFormFactor& ff_registry();
 };
 
 #endif // PARTICLEINTHEAIRBUILDER_H
-- 
GitLab