From 262572ed6467d7d3306e3317b4310f783115f344 Mon Sep 17 00:00:00 2001
From: Gennady Pospelov <g.pospelov@fz-juelich.de>
Date: Fri, 17 Apr 2015 16:27:20 +0200
Subject: [PATCH] ParticleDistribution is added to python script generation

---
 Core/Samples/inc/ParticleDistribution.h       |  6 ++
 Core/Tools/inc/PyGenTools.h                   |  4 ++
 Core/Tools/inc/PyGenVisitor.h                 |  3 +
 Core/Tools/inc/SampleLabelHandler.h           |  6 ++
 Core/Tools/src/PyGenTools.cpp                 | 40 +++++++++++++
 Core/Tools/src/PyGenVisitor.cpp               | 56 +++++++++++++++++++
 Core/Tools/src/SampleLabelHandler.cpp         | 21 +++++++
 .../CylindersWithSizeDistribution.py          |  1 +
 8 files changed, 137 insertions(+)

diff --git a/Core/Samples/inc/ParticleDistribution.h b/Core/Samples/inc/ParticleDistribution.h
index 8e630601253..e88503ff56d 100644
--- a/Core/Samples/inc/ParticleDistribution.h
+++ b/Core/Samples/inc/ParticleDistribution.h
@@ -80,6 +80,12 @@ public:
         return m_particle.createParameterTree();
     }
 
+    //! Returns particle.
+    const IParticle *getParticle() const
+    {
+        return m_particle.getParticle();
+    }
+
 protected:
     ParticleInfo m_particle;
     ParameterDistribution m_par_distribution;
diff --git a/Core/Tools/inc/PyGenTools.h b/Core/Tools/inc/PyGenTools.h
index b55ca3c13b2..5c4a9fe6290 100644
--- a/Core/Tools/inc/PyGenTools.h
+++ b/Core/Tools/inc/PyGenTools.h
@@ -18,6 +18,7 @@
 #include "Simulation.h"
 #include "PyGenVisitor.h"
 
+class IDistribution1D;
 
 namespace PyGenTools {
     BA_CORE_API_ std::string genPyScript(Simulation *simulation);
@@ -25,6 +26,9 @@ namespace PyGenTools {
     BA_CORE_API_ bool isSquare(double length1, double length2, double angle);
     BA_CORE_API_ bool isHexagonal(double length1, double length2, double angle);
     BA_CORE_API_ bool testPyScript(Simulation *simulation);
+    BA_CORE_API_ std::string getRepresentation(const IDistribution1D *distribution);
+
+
 }
 
 #endif // PYSCRIPTTOOLS_H
diff --git a/Core/Tools/inc/PyGenVisitor.h b/Core/Tools/inc/PyGenVisitor.h
index f758059e370..b30ae13ed24 100644
--- a/Core/Tools/inc/PyGenVisitor.h
+++ b/Core/Tools/inc/PyGenVisitor.h
@@ -28,6 +28,7 @@ class BA_CORE_API_ PyGenVisitor : public ISampleVisitor
 {
 public:
     PyGenVisitor();
+    ~PyGenVisitor();
 
     using ISampleVisitor::visit;
 
@@ -68,6 +69,7 @@ public:
     void visit(const ParticleComposition *sample);
     void visit(const MesoCrystal *sample);
     void visit(const Particle *sample);
+    void visit(const ParticleDistribution *sample);
     void visit(const ParticleCoreShell *sample);
     void visit(const ParticleInfo *sample){ (void)sample; }
     void visit(const ParticleLayout *sample);
@@ -87,6 +89,7 @@ private:
     std::string defineFormFactors() const;
     std::string defineParticles() const;
     std::string defineCoreShellParticles() const;
+    std::string defineParticleDistributions() const;
     std::string defineParticleCompositions() const;
     std::string defineInterferenceFunctions() const;
     std::string defineParticleLayouts() const;
diff --git a/Core/Tools/inc/SampleLabelHandler.h b/Core/Tools/inc/SampleLabelHandler.h
index ac3735c1d70..da92e653a0d 100644
--- a/Core/Tools/inc/SampleLabelHandler.h
+++ b/Core/Tools/inc/SampleLabelHandler.h
@@ -29,6 +29,7 @@ class IMaterial;
 class Particle;
 class IParticle;
 class ParticleCoreShell;
+class ParticleDistribution;
 class ILayout;
 class ParticleComposition;
 class IRotation;
@@ -48,6 +49,7 @@ public:
     typedef Utils::OrderedMap<const MultiLayer*, std::string> multilayers_t;
     typedef Utils::OrderedMap<const Particle*, std::string> particles_t;
     typedef Utils::OrderedMap<const ParticleCoreShell*, std::string> particlescoreshell_t;
+    typedef Utils::OrderedMap<const ParticleDistribution*, std::string> particledistributions_t;
     typedef Utils::OrderedMap<const ILayout*, std::string> layouts_t;
     typedef Utils::OrderedMap<const ParticleComposition*, std::string> particlecompositions_t;
     typedef Utils::OrderedMap<const IRotation*, std::string> rotations_t;
@@ -61,6 +63,7 @@ public:
     multilayers_t* getMultiLayerMap();
     particles_t* getParticleMap();
     particlescoreshell_t* getParticleCoreShellMap();
+    particledistributions_t* getParticleDistributionsMap();
     layouts_t* getParticleLayoutMap();
     particlecompositions_t* getParticleCompositionMap();
     rotations_t* getRotationsMap();
@@ -73,6 +76,7 @@ public:
     std::string getLabel(const MultiLayer *sample);
     std::string getLabel(const IParticle *sample);
     std::string getLabel(const ParticleCoreShell *sample);
+    std::string getLabel(const ParticleDistribution *sample);
     std::string getLabel(const ILayout *sample);
     std::string getLabel(const ParticleComposition *sample);
     std::string getLabel(const IRotation *sample);
@@ -86,6 +90,7 @@ public:
     void setLabel(const MultiLayer *sample);
     void setLabel(const Particle *sample);
     void setLabel(const ParticleCoreShell *sample);
+    void setLabel(const ParticleDistribution *sample);
     void setLabel(const ParticleComposition *sample);
     void setLabel(const IRotation *sample);
 
@@ -100,6 +105,7 @@ private:
     multilayers_t m_MultiLayerLabel;
     particles_t m_ParticleLabel;
     particlescoreshell_t m_ParticleCoreShellLabel;
+    particledistributions_t m_ParticleDistributionLabel;
     layouts_t m_ILayoutLabel;
     particlecompositions_t m_ParticleCompositionLabel;
     rotations_t m_RotationsLabel;
diff --git a/Core/Tools/src/PyGenTools.cpp b/Core/Tools/src/PyGenTools.cpp
index 87244a7e8bd..1a1b09ae201 100644
--- a/Core/Tools/src/PyGenTools.cpp
+++ b/Core/Tools/src/PyGenTools.cpp
@@ -27,6 +27,7 @@
 #include "MultiLayer.h"
 #include "PyGenTools.h"
 #include "Simulation.h"
+#include "Distributions.h"
 #include "BAPython.h"
 
 std::string PyGenTools::genPyScript(Simulation *simulation)
@@ -111,3 +112,42 @@ bool PyGenTools::testPyScript(Simulation *simulation)
                      " reference sample: = " << diff << std::endl;
         return false;
 }
+
+
+std::string PyGenTools::getRepresentation(const IDistribution1D *distribution)
+{
+     std::ostringstream result;
+     result << std::setprecision(12);
+
+     if(const DistributionGate *d = dynamic_cast<const DistributionGate *>(distribution)) {
+        result << "DistributionGate("
+               << PyGenTools::printDouble(d->getMin()) << ", "
+               << PyGenTools::printDouble(d->getMax()) << ")";
+     }
+     else if(const DistributionLorentz *d = dynamic_cast<const DistributionLorentz *>(distribution)) {
+         result << "DistributionLorentz("
+                << PyGenTools::printDouble(d->getMean()) << ", "
+                << PyGenTools::printDouble(d->getHWHM()) << ")";
+     }
+     else if(const DistributionGaussian *d = dynamic_cast<const DistributionGaussian *>(distribution)) {
+         result << "DistributionGaussian("
+                << PyGenTools::printDouble(d->getMean()) << ", "
+                << PyGenTools::printDouble(d->getStdDev()) << ")";
+     }
+     else if(const DistributionLogNormal *d = dynamic_cast<const DistributionLogNormal *>(distribution)) {
+         result << "DistributionLogNormal("
+                << PyGenTools::printDouble(d->getMedian()) << ", "
+                << PyGenTools::printDouble(d->getScalePar()) << ")";
+     }
+     else if(const DistributionCosine *d = dynamic_cast<const DistributionCosine *>(distribution)) {
+         result << "DistributionCosine("
+                << PyGenTools::printDouble(d->getMean()) << ", "
+                << PyGenTools::printDouble(d->getSigma()) << ")";
+     }
+     else {
+         throw RuntimeErrorException(
+            "PyGenTools::getRepresentation(const IDistribution1D *distribution) "
+            "-> Error. Unknown distribution type");
+     }
+     return result.str();
+}
diff --git a/Core/Tools/src/PyGenVisitor.cpp b/Core/Tools/src/PyGenVisitor.cpp
index 2f093461590..e5d6d95ad72 100644
--- a/Core/Tools/src/PyGenVisitor.cpp
+++ b/Core/Tools/src/PyGenVisitor.cpp
@@ -30,10 +30,12 @@
 #include "MultiLayer.h"
 #include "Particle.h"
 #include "ParticleCoreShell.h"
+#include "ParticleDistribution.h"
 #include "ParticleInfo.h"
 #include "ParticleLayout.h"
 #include "PyGenVisitor.h"
 #include "PyGenTools.h"
+#include "ParameterDistribution.h"
 #include "Rotations.h"
 
 PyGenVisitor::PyGenVisitor()
@@ -41,6 +43,11 @@ PyGenVisitor::PyGenVisitor()
 {
 }
 
+PyGenVisitor::~PyGenVisitor()
+{
+    delete m_label;
+}
+
 std::string PyGenVisitor::writePyScript(const Simulation *simulation)
 {
     std::ostringstream result;
@@ -235,6 +242,11 @@ void PyGenVisitor::visit(const Particle *sample)
     m_label->setLabel(sample);
 }
 
+void PyGenVisitor::visit(const ParticleDistribution *sample)
+{
+    m_label->setLabel(sample);
+}
+
 void PyGenVisitor::visit(const ParticleCoreShell *sample)
 {
     m_label->setLabel(sample);
@@ -292,6 +304,7 @@ std::string PyGenVisitor::defineGetSample() const
     result << defineFormFactors();
     result << defineParticles();
     result << defineCoreShellParticles();
+    result << defineParticleDistributions();
     result << defineParticleCompositions();
     result << defineInterferenceFunctions();
     result << defineParticleLayouts();
@@ -720,6 +733,49 @@ std::string PyGenVisitor::defineCoreShellParticles() const
     return result.str();
 }
 
+std::string PyGenVisitor::defineParticleDistributions() const
+{
+    if (m_label->getParticleDistributionsMap()->size() == 0) return "";
+
+    std::ostringstream result;
+    result << std::setprecision(12);
+    result << "\n"<<indent()<<"# Defining collection of particle with size distribution\n";
+    SampleLabelHandler::particledistributions_t::iterator it =
+            m_label->getParticleDistributionsMap()->begin();
+
+    int index(1);
+    while (it != m_label->getParticleDistributionsMap()->end())
+    {
+        ParameterDistribution par_distr = it->first->getParameterDistribution();
+
+        // building distribution functions
+        std::stringstream s_distr;
+        s_distr << "distr_" << index;
+
+        result << indent() << s_distr.str() << " = "
+               << PyGenTools::getRepresentation(par_distr.getDistribution()) << "\n";
+
+        // building parameter distribution
+        std::stringstream s_par_distr;
+        s_par_distr << "par_distr_" << index;
+
+        result << indent() << s_par_distr.str()
+               << " = ParameterDistribution("
+               << "\"" << par_distr.getMainParameterName() << "\"" << ", "
+               << s_distr.str() << ", "
+               << par_distr.getNbrSamples() << ", "
+               << par_distr.getSigmaFactor()
+               << ")\n";
+        result << indent() << it->second << " = ParticleDistribution("
+               << m_label->getLabel(it->first->getParticle())
+               << ", " << s_par_distr.str()
+               << ")\n";
+        it++;
+        index++;
+    }
+    return result.str();
+}
+
 std::string PyGenVisitor::defineParticleCompositions() const
 {
     if (m_label->getParticleCompositionMap()->size() == 0) return "";
diff --git a/Core/Tools/src/SampleLabelHandler.cpp b/Core/Tools/src/SampleLabelHandler.cpp
index 09550114bea..62494a47556 100644
--- a/Core/Tools/src/SampleLabelHandler.cpp
+++ b/Core/Tools/src/SampleLabelHandler.cpp
@@ -20,6 +20,7 @@
 #include "ParticleLayout.h"
 #include "ParticleCoreShell.h"
 #include "ParticleComposition.h"
+#include "ParticleDistribution.h"
 #include <iostream>
 
 SampleLabelHandler::SampleLabelHandler()
@@ -63,6 +64,9 @@ std::string SampleLabelHandler::getLabel(const IParticle *sample)
         return m_ParticleCoreShellLabel[core_shell_particle];
     if (const Particle *particle = dynamic_cast<const Particle*>(sample))
         return m_ParticleLabel[particle];
+    if (const ParticleDistribution *particle = dynamic_cast<const ParticleDistribution*>(sample))
+        return m_ParticleDistributionLabel[particle];
+
     if (const ParticleComposition *lattice_basis = dynamic_cast<const ParticleComposition*>(sample))
         return m_ParticleCompositionLabel[lattice_basis];
     throw Exceptions::NotImplementedException("SampleLabelHandler::getLabel: called"
@@ -74,6 +78,11 @@ std::string SampleLabelHandler::getLabel(const ParticleCoreShell *sample)
     return m_ParticleCoreShellLabel[sample];
 }
 
+std::string SampleLabelHandler::getLabel(const ParticleDistribution *sample)
+{
+    return m_ParticleDistributionLabel[sample];
+}
+
 std::string SampleLabelHandler::getLabel(const ILayout *sample)
 {
     return m_ILayoutLabel[sample];
@@ -129,6 +138,11 @@ SampleLabelHandler::particlescoreshell_t *SampleLabelHandler::getParticleCoreShe
     return &m_ParticleCoreShellLabel;
 }
 
+SampleLabelHandler::particledistributions_t *SampleLabelHandler::getParticleDistributionsMap()
+{
+    return &m_ParticleDistributionLabel;
+}
+
 SampleLabelHandler::layouts_t *SampleLabelHandler::getParticleLayoutMap()
 {
     return &m_ILayoutLabel;
@@ -234,6 +248,13 @@ void SampleLabelHandler::setLabel(const ParticleCoreShell *sample)
     m_ParticleCoreShellLabel.insert(sample, inter.str());
 }
 
+void SampleLabelHandler::setLabel(const ParticleDistribution *sample)
+{
+    std::ostringstream inter;
+    inter << "particleDistribution_" << m_ParticleDistributionLabel.size()+1;
+    m_ParticleDistributionLabel.insert(sample, inter.str());
+}
+
 void SampleLabelHandler::setLabel(const ParticleComposition *sample)
 {
     std::ostringstream inter;
diff --git a/Examples/python/simulation/ex01_BasicParticles/CylindersWithSizeDistribution.py b/Examples/python/simulation/ex01_BasicParticles/CylindersWithSizeDistribution.py
index 7a40de94ad3..85c379a4464 100644
--- a/Examples/python/simulation/ex01_BasicParticles/CylindersWithSizeDistribution.py
+++ b/Examples/python/simulation/ex01_BasicParticles/CylindersWithSizeDistribution.py
@@ -61,6 +61,7 @@ def run_simulation():
     Run simulation and plot results
     """
     sample = get_sample()
+    sample.printSampleTree()
     simulation = get_simulation()
     simulation.setSample(sample)
     simulation.runSimulation()
-- 
GitLab