From 2b6955da55c10d328f92d7e17b06a7cac19c83c7 Mon Sep 17 00:00:00 2001
From: Marina Ganeva <m.ganeva@fz-juelich.de>
Date: Tue, 3 Dec 2013 14:44:35 +0100
Subject: [PATCH] IsGISAXS09 functional test is done.

---
 Core/StandardSamples/IsGISAXS08Builder.cpp    | 95 +++++++++++++++++++
 Core/StandardSamples/IsGISAXS08Builder.h      | 26 +++++
 Core/StandardSamples/SimulationRegistry.cpp   |  8 ++
 Core/StandardSamples/StandardSimulations.cpp  | 36 +++++++
 Core/StandardSamples/StandardSimulations.h    |  3 +-
 Tests/FunctionalTests/TestCore/CMakeLists.txt |  3 +-
 .../IsGISAXS082DDL/IsGISAXS082DDL.cpp         | 77 +++++++++++++++
 .../TestCore/IsGISAXS082DDL/IsGISAXS082DDL.h  | 27 ++++++
 .../IsGISAXS082DDL2/IsGISAXS082DDL2.cpp       | 77 +++++++++++++++
 .../IsGISAXS082DDL2/IsGISAXS082DDL2.h         | 27 ++++++
 .../TestCore/IsGISAXS09P/IsGISAXS09P.cpp      | 77 +++++++++++++++
 .../TestCore/IsGISAXS09P/IsGISAXS09P.h        | 28 ++++++
 .../TestCore/IsGISAXS09R/IsGISAXS09R.cpp      | 77 +++++++++++++++
 .../TestCore/IsGISAXS09R/IsGISAXS09R.h        | 28 ++++++
 14 files changed, 587 insertions(+), 2 deletions(-)
 create mode 100644 Core/StandardSamples/IsGISAXS08Builder.cpp
 create mode 100644 Core/StandardSamples/IsGISAXS08Builder.h
 create mode 100644 Tests/FunctionalTests/TestCore/IsGISAXS082DDL/IsGISAXS082DDL.cpp
 create mode 100644 Tests/FunctionalTests/TestCore/IsGISAXS082DDL/IsGISAXS082DDL.h
 create mode 100644 Tests/FunctionalTests/TestCore/IsGISAXS082DDL2/IsGISAXS082DDL2.cpp
 create mode 100644 Tests/FunctionalTests/TestCore/IsGISAXS082DDL2/IsGISAXS082DDL2.h
 create mode 100644 Tests/FunctionalTests/TestCore/IsGISAXS09P/IsGISAXS09P.cpp
 create mode 100644 Tests/FunctionalTests/TestCore/IsGISAXS09P/IsGISAXS09P.h
 create mode 100644 Tests/FunctionalTests/TestCore/IsGISAXS09R/IsGISAXS09R.cpp
 create mode 100644 Tests/FunctionalTests/TestCore/IsGISAXS09R/IsGISAXS09R.h

diff --git a/Core/StandardSamples/IsGISAXS08Builder.cpp b/Core/StandardSamples/IsGISAXS08Builder.cpp
new file mode 100644
index 00000000000..75e462ea8ec
--- /dev/null
+++ b/Core/StandardSamples/IsGISAXS08Builder.cpp
@@ -0,0 +1,95 @@
+#include "IsGISAXS08Builder.h"
+#include "MultiLayer.h"
+#include "ParticleDecoration.h"
+#include "MaterialManager.h"
+#include "InterferenceFunction2DParaCrystal.h"
+#include "FormFactorCylinder.h"
+#include "Units.h"
+#include "ParticleBuilder.h"
+
+IsGISAXS08Para1DBuilder::IsGISAXS08Para1DBuilder()
+{
+}
+
+ISample *IsGISAXS08Para1DBuilder::buildSample() const
+{
+    MultiLayer *multi_layer = new MultiLayer();
+
+	complex_t n_particle(1.0-6e-4, 2e-8);
+    const IMaterial *p_air_material =
+            MaterialManager::getHomogeneousMaterial("Air", 0.0, 0.0);
+    const IMaterial *p_substrate_material =
+            MaterialManager::getHomogeneousMaterial("Substrate", 6e-6, 2e-8);
+    const IMaterial *particle_material =
+            MaterialManager::getHomogeneousMaterial("Particle", n_particle);
+
+    Layer air_layer;
+    air_layer.setMaterial(p_air_material);
+    Layer substrate_layer;
+    substrate_layer.setMaterial(p_substrate_material);
+
+    InterferenceFunction2DParaCrystal *p_interference_function =
+            new InterferenceFunction2DParaCrystal(10.0*Units::nanometer,
+                    10.0*Units::nanometer, M_PI/2.0, 0.0, 0.0);
+    p_interference_function->setDomainSizes(20.0*Units::micrometer,
+            20.0*Units::micrometer);
+    FTDistribution2DCauchy pdf1(0.5*Units::nanometer, 2.0*Units::nanometer);
+    FTDistribution2DCauchy pdf2(0.5*Units::nanometer, 2.0*Units::nanometer);
+    p_interference_function->setProbabilityDistributions(pdf1, pdf2);
+    ParticleDecoration particle_decoration( new Particle(particle_material,
+            new FormFactorCylinder(5*Units::nanometer, 5*Units::nanometer)));
+    particle_decoration.addInterferenceFunction(p_interference_function);
+
+    air_layer.setDecoration(particle_decoration);
+
+    multi_layer->addLayer(air_layer);
+    multi_layer->addLayer(substrate_layer);
+
+    return multi_layer;
+}
+
+
+// -----------------------------------------------------------------------------
+//
+
+IsGISAXS08Para2DBuilder::IsGISAXS08Para2DBuilder()
+{
+}
+
+// IsGISAXS8 functional test: 2D paracrystal lattice with isotropic pdfs
+ISample *IsGISAXS08Para2DBuilder::buildSample() const
+{
+    MultiLayer *multi_layer = new MultiLayer();
+
+    complex_t n_particle(1.0-6e-4, 2e-8);
+    const IMaterial *p_air_material =
+            MaterialManager::getHomogeneousMaterial("Air", 0.0, 0.0);
+    const IMaterial *p_substrate_material =
+            MaterialManager::getHomogeneousMaterial("Substrate", 6e-6, 2e-8);
+    const IMaterial *particle_material =
+            MaterialManager::getHomogeneousMaterial("Particle", n_particle);
+
+    Layer air_layer;
+    air_layer.setMaterial(p_air_material);
+    Layer substrate_layer;
+    substrate_layer.setMaterial(p_substrate_material);
+
+    InterferenceFunction2DParaCrystal *p_interference_function =
+            new InterferenceFunction2DParaCrystal(10.0*Units::nanometer,
+                    10.0*Units::nanometer, M_PI/2.0, 0.0, 0.0);
+    p_interference_function->setDomainSizes(20.0*Units::micrometer,
+            20.0*Units::micrometer);
+    FTDistribution2DCauchy pdf1(0.5*Units::nanometer, 0.5*Units::nanometer);
+    FTDistribution2DCauchy pdf2(0.5*Units::nanometer, 0.5*Units::nanometer);
+    p_interference_function->setProbabilityDistributions(pdf1, pdf2);
+    ParticleDecoration particle_decoration( new Particle(particle_material,
+            new FormFactorCylinder(5*Units::nanometer, 5*Units::nanometer)));
+    particle_decoration.addInterferenceFunction(p_interference_function);
+
+    air_layer.setDecoration(particle_decoration);
+
+    multi_layer->addLayer(air_layer);
+    multi_layer->addLayer(substrate_layer);
+
+    return multi_layer;
+}
diff --git a/Core/StandardSamples/IsGISAXS08Builder.h b/Core/StandardSamples/IsGISAXS08Builder.h
new file mode 100644
index 00000000000..cf45c17cb2c
--- /dev/null
+++ b/Core/StandardSamples/IsGISAXS08Builder.h
@@ -0,0 +1,26 @@
+#ifndef ISGISAXS08BUILDER_H
+#define ISGISAXS08BUILDER_H
+
+#include "ISampleBuilder.h"
+
+//! The IsGISAXS08Builder class to build sample: 2D paracrystal lattice
+//! (IsGISAXS example #8)
+class IsGISAXS08Para1DBuilder : public ISampleBuilder
+{
+public:
+    IsGISAXS08Para1DBuilder();
+    ISample *buildSample() const;
+};
+
+
+//! The IsGISAXS08Builder class to build sample: 2D paracrystal lattice
+//! with isotropic pdfs (IsGISAXS example #8)
+class IsGISAXS08Para2DBuilder : public ISampleBuilder
+{
+public:
+    IsGISAXS08Para2DBuilder();
+    ISample *buildSample() const;
+};
+
+
+#endif // ISGISAXS08BUILDER_H
diff --git a/Core/StandardSamples/SimulationRegistry.cpp b/Core/StandardSamples/SimulationRegistry.cpp
index d86e49fa8d7..1bc820ca783 100644
--- a/Core/StandardSamples/SimulationRegistry.cpp
+++ b/Core/StandardSamples/SimulationRegistry.cpp
@@ -60,6 +60,14 @@ SimulationRegistry::SimulationRegistry()
         "isgisaxs08_2DDL2", StandardSimulations::IsGISAXS082DDL2,
         "IsGISAXS08 example, 2DDL lattice with isotropic pdfs");
 
+    registerItem(
+        "isgisaxs09", StandardSimulations::IsGISAXS09,
+        "IsGISAXS09 example, Pyramids on top of substrate");
+
+    registerItem(
+        "isgisaxs09_rotated", StandardSimulations::IsGISAXS09R,
+        "IsGISAXS09 example, Rotated pyramids on top of substrate");
+
     registerItem(
         "mesocrystal01", StandardSimulations::MesoCrystal01,
         "mesocrystals of cylindrical shape composed by spherical nanoparticles");
diff --git a/Core/StandardSamples/StandardSimulations.cpp b/Core/StandardSamples/StandardSimulations.cpp
index 01252beddc2..f28993398cc 100644
--- a/Core/StandardSamples/StandardSimulations.cpp
+++ b/Core/StandardSamples/StandardSimulations.cpp
@@ -270,6 +270,42 @@ Simulation *StandardSimulations::IsGISAXS082DDL2()
     return result;
 }
 
+Simulation *StandardSimulations::IsGISAXS09()
+{
+    SampleBuilderFactory factory;
+    ISampleBuilder *builder = factory.createBuilder("isgisaxs09");
+
+    Simulation *result = new Simulation();
+
+    result->setDetectorParameters(
+        100, 0.0*Units::degree, 2.0*Units::degree,
+        100, 0.0*Units::degree, 2.0*Units::degree, true);
+    result->setBeamParameters(
+        1.0*Units::angstrom, 0.2*Units::degree, 0.0*Units::degree);
+
+    result->setSampleBuilder( builder );
+
+    return result;
+}
+
+Simulation *StandardSimulations::IsGISAXS09R()
+{
+    SampleBuilderFactory factory;
+    ISampleBuilder *builder = factory.createBuilder("isgisaxs09_rotated");
+
+    Simulation *result = new Simulation();
+
+    result->setDetectorParameters(
+        100, 0.0*Units::degree, 2.0*Units::degree,
+        100, 0.0*Units::degree, 2.0*Units::degree, true);
+    result->setBeamParameters(
+        1.0*Units::angstrom, 0.2*Units::degree, 0.0*Units::degree);
+
+    result->setSampleBuilder( builder );
+
+    return result;
+}
+
 Simulation *StandardSimulations::MesoCrystal01()
 {
     SampleBuilderFactory factory;
diff --git a/Core/StandardSamples/StandardSimulations.h b/Core/StandardSamples/StandardSimulations.h
index 20a1b95358b..41694e3bb97 100644
--- a/Core/StandardSamples/StandardSimulations.h
+++ b/Core/StandardSamples/StandardSimulations.h
@@ -22,7 +22,8 @@ Simulation *IsGISAXS06L4();
 Simulation *IsGISAXS07();
 Simulation *IsGISAXS082DDL();
 Simulation *IsGISAXS082DDL2();
-//Simulation *IsGISAXS09();
+Simulation *IsGISAXS09();
+Simulation *IsGISAXS09R();
 //Simulation *IsGISAXS10();
 //Simulation *IsGISAXS11();
 //Simulation *IsGISAXS15();
diff --git a/Tests/FunctionalTests/TestCore/CMakeLists.txt b/Tests/FunctionalTests/TestCore/CMakeLists.txt
index 27ec39bdf0d..dcedbe9f7b3 100644
--- a/Tests/FunctionalTests/TestCore/CMakeLists.txt
+++ b/Tests/FunctionalTests/TestCore/CMakeLists.txt
@@ -19,7 +19,8 @@ set(list_of_tests
     "IsGISAXS07"
     "IsGISAXS082DDL"
     "IsGISAXS082DDL2"
-    "IsGISAXS09"
+    "IsGISAXS09P"
+    "IsGISAXS09R"
     "IsGISAXS10"
     "IsGISAXS11"
     "IsGISAXS15"
diff --git a/Tests/FunctionalTests/TestCore/IsGISAXS082DDL/IsGISAXS082DDL.cpp b/Tests/FunctionalTests/TestCore/IsGISAXS082DDL/IsGISAXS082DDL.cpp
new file mode 100644
index 00000000000..ddccf21bf50
--- /dev/null
+++ b/Tests/FunctionalTests/TestCore/IsGISAXS082DDL/IsGISAXS082DDL.cpp
@@ -0,0 +1,77 @@
+#include "IsGISAXS082DDL.h"
+#include "OutputDataIOFactory.h"
+#include "SampleBuilderFactory.h"
+#include "Simulation.h"
+#include "Units.h"
+#include "Utils.h"
+#include "MathFunctions.h"
+#include "SimulationRegistry.h"
+#include <iostream>
+#include <cmath>
+
+FunctionalTests::IsGISAXS082DDL::IsGISAXS082DDL()
+    : m_name("IsGISAXS082DDL")
+    , m_description("2D Paracrystal lattice")
+    , m_result(0)
+	, m_reference(0)
+{ }
+
+
+void FunctionalTests::IsGISAXS082DDL::run(const std::string &path_to_data)
+{
+
+    SimulationRegistry sim_registry;
+    Simulation *simulation = sim_registry.createSimulation("isgisaxs08_2DDL");
+
+    // loading reference data
+    std::string filename = path_to_data + "isgisaxs08_reference_2DDL_lattice.ima.gz";
+    m_reference = OutputDataIOFactory::readIntensityData(filename);
+
+    simulation->runSimulation();
+
+    m_result = simulation->getIntensityData();
+    delete simulation;
+}
+
+
+int FunctionalTests::IsGISAXS082DDL::analyseResults()
+{
+    const double threshold(2e-10);
+
+    // Calculating average relative difference.
+    *m_result -= *m_reference;
+    *m_result /= *m_reference;
+
+    double diff(0);
+    for(OutputData<double>::const_iterator it =
+            m_result->begin(); it!=m_result->end(); ++it) {
+        diff+= std::fabs(*it);
+    }
+    diff /= m_result->getAllocatedSize();
+
+    // Assess result.
+	bool status_ok(true);
+    if( diff > threshold || std::isnan(diff)) status_ok=false;
+
+    std::cout << " diff " << diff << std::endl;
+    std::cout << m_name << " " << m_description << " " <<
+            (status_ok ? "[OK]" : "[FAILED]") << std::endl;
+    return (status_ok ? 0 : 1);
+}
+
+
+#ifdef STANDALONE
+std::string GetPathToData(int argc, char **argv)
+{
+    if(argc == 2) return argv[1];
+    return Utils::FileSystem::GetPathToData("../../../ReferenceData/BornAgain/", argv[0]);
+}
+
+int main(int argc, char **argv)
+{
+    FunctionalTests::IsGISAXS082DDL test;
+    test.run(GetPathToData(argc, argv));
+    return test.analyseResults();
+}
+#endif
+
diff --git a/Tests/FunctionalTests/TestCore/IsGISAXS082DDL/IsGISAXS082DDL.h b/Tests/FunctionalTests/TestCore/IsGISAXS082DDL/IsGISAXS082DDL.h
new file mode 100644
index 00000000000..08bf175357f
--- /dev/null
+++ b/Tests/FunctionalTests/TestCore/IsGISAXS082DDL/IsGISAXS082DDL.h
@@ -0,0 +1,27 @@
+#ifndef FUNCTIONALTESTS_ISGISAXS082DDL_H
+#define FUNCTIONALTESTS_ISGISAXS082DDL_H
+
+#include "ISampleBuilder.h"
+#include <string>
+#include "OutputData.h"
+
+namespace FunctionalTests {
+
+class IsGISAXS082DDL
+{
+ public:
+    IsGISAXS082DDL();
+    ~IsGISAXS082DDL() { delete m_result; delete m_reference; }
+    void run(const std::string &path_to_data = std::string());
+    int analyseResults();
+//    const OutputData<double> *getOutputData() { return m_result;}
+ private:
+    std::string m_name;
+    std::string m_description;
+    OutputData<double> *m_result;
+    OutputData<double> *m_reference;
+};
+
+}
+
+#endif
diff --git a/Tests/FunctionalTests/TestCore/IsGISAXS082DDL2/IsGISAXS082DDL2.cpp b/Tests/FunctionalTests/TestCore/IsGISAXS082DDL2/IsGISAXS082DDL2.cpp
new file mode 100644
index 00000000000..52c1f778f7d
--- /dev/null
+++ b/Tests/FunctionalTests/TestCore/IsGISAXS082DDL2/IsGISAXS082DDL2.cpp
@@ -0,0 +1,77 @@
+#include "IsGISAXS082DDL2.h"
+#include "OutputDataIOFactory.h"
+#include "SampleBuilderFactory.h"
+#include "Simulation.h"
+#include "Units.h"
+#include "Utils.h"
+#include "MathFunctions.h"
+#include "SimulationRegistry.h"
+#include <iostream>
+#include <cmath>
+
+FunctionalTests::IsGISAXS082DDL2::IsGISAXS082DDL2()
+    : m_name("IsGISAXS042DDL")
+    , m_description("2D Paracrystal lattice with isotropic pdfs")
+    , m_result(0)
+	, m_reference(0)
+{ }
+
+
+void FunctionalTests::IsGISAXS082DDL2::run(const std::string &path_to_data)
+{
+
+    SimulationRegistry sim_registry;
+    Simulation *simulation = sim_registry.createSimulation("isgisaxs08_2DDL2");
+
+    // loading reference data
+    std::string filename = path_to_data + "isgisaxs08_reference_2DDL_lattice2.ima.gz";
+    m_reference = OutputDataIOFactory::readIntensityData(filename);
+
+    simulation->runSimulation();
+
+    m_result = simulation->getIntensityData();
+    delete simulation;
+}
+
+
+int FunctionalTests::IsGISAXS082DDL2::analyseResults()
+{
+    const double threshold(2e-10);
+
+    // Calculating average relative difference.
+    *m_result -= *m_reference;
+    *m_result /= *m_reference;
+
+    double diff(0);
+    for(OutputData<double>::const_iterator it =
+            m_result->begin(); it!=m_result->end(); ++it) {
+        diff+= std::fabs(*it);
+    }
+    diff /= m_result->getAllocatedSize();
+
+    // Assess result.
+	bool status_ok(true);
+    if( diff > threshold || std::isnan(diff)) status_ok=false;
+
+    std::cout << " diff " << diff << std::endl;
+    std::cout << m_name << " " << m_description << " " <<
+            (status_ok ? "[OK]" : "[FAILED]") << std::endl;
+    return (status_ok ? 0 : 1);
+}
+
+
+#ifdef STANDALONE
+std::string GetPathToData(int argc, char **argv)
+{
+    if(argc == 2) return argv[1];
+    return Utils::FileSystem::GetPathToData("../../../ReferenceData/BornAgain/", argv[0]);
+}
+
+int main(int argc, char **argv)
+{
+    FunctionalTests::IsGISAXS082DDL2 test;
+    test.run(GetPathToData(argc, argv));
+    return test.analyseResults();
+}
+#endif
+
diff --git a/Tests/FunctionalTests/TestCore/IsGISAXS082DDL2/IsGISAXS082DDL2.h b/Tests/FunctionalTests/TestCore/IsGISAXS082DDL2/IsGISAXS082DDL2.h
new file mode 100644
index 00000000000..60f5aa73607
--- /dev/null
+++ b/Tests/FunctionalTests/TestCore/IsGISAXS082DDL2/IsGISAXS082DDL2.h
@@ -0,0 +1,27 @@
+#ifndef FUNCTIONALTESTS_ISGISAXS082DDL2_H
+#define FUNCTIONALTESTS_ISGISAXS082DDL2_H
+
+#include "ISampleBuilder.h"
+#include <string>
+#include "OutputData.h"
+
+namespace FunctionalTests {
+
+class IsGISAXS082DDL2
+{
+ public:
+    IsGISAXS082DDL2();
+    ~IsGISAXS082DDL2() { delete m_result; delete m_reference; }
+    void run(const std::string &path_to_data = std::string());
+    int analyseResults();
+//    const OutputData<double> *getOutputData() { return m_result;}
+ private:
+    std::string m_name;
+    std::string m_description;
+    OutputData<double> *m_result;
+    OutputData<double> *m_reference;
+};
+
+}
+
+#endif
diff --git a/Tests/FunctionalTests/TestCore/IsGISAXS09P/IsGISAXS09P.cpp b/Tests/FunctionalTests/TestCore/IsGISAXS09P/IsGISAXS09P.cpp
new file mode 100644
index 00000000000..c8ed78222fb
--- /dev/null
+++ b/Tests/FunctionalTests/TestCore/IsGISAXS09P/IsGISAXS09P.cpp
@@ -0,0 +1,77 @@
+#include "IsGISAXS09P.h"
+#include "OutputDataIOFactory.h"
+#include "SampleBuilderFactory.h"
+#include "Simulation.h"
+#include "Utils.h"
+#include "Units.h"
+#include "MathFunctions.h"
+#include "SimulationRegistry.h"
+#include <iostream>
+#include <cmath>
+
+
+FunctionalTests::IsGISAXS09::IsGISAXS09()
+    : m_name("IsGISAXS09")
+    , m_description("Pyramids on top of substrate")
+    , m_result(0)
+	, m_reference(0)
+{ }
+
+
+void FunctionalTests::IsGISAXS09::run(const std::string &path_to_data)
+{
+
+    SimulationRegistry sim_registry;
+    Simulation *simulation = sim_registry.createSimulation("isgisaxs09");
+
+    // loading reference data
+    std::string filename = path_to_data + "isgisaxs09_reference_pyramid_Z0.ima.gz";
+    m_reference = OutputDataIOFactory::readIntensityData(filename);
+
+    simulation->runSimulation();
+
+    m_result = simulation->getIntensityData();
+    delete simulation;
+}
+
+
+int FunctionalTests::IsGISAXS09::analyseResults()
+{
+    const double threshold(2e-10);
+
+    // Calculating average relative difference.
+    *m_result -= *m_reference;
+    *m_result /= *m_reference;
+
+    double diff(0);
+    for(OutputData<double>::const_iterator it =
+            m_result->begin(); it!=m_result->end(); ++it) {
+        diff+= std::fabs(*it);
+    }
+    diff /= m_result->getAllocatedSize();
+
+    // Assess result.
+	bool status_ok(true);
+    if( diff > threshold || std::isnan(diff)) status_ok=false;
+
+    std::cout << " diff " << diff << std::endl;
+    std::cout << m_name << " " << m_description << " " <<
+            (status_ok ? "[OK]" : "[FAILED]") << std::endl;
+    return (status_ok ? 0 : 1);
+}
+
+
+#ifdef STANDALONE
+std::string GetPathToData(int argc, char **argv)
+{
+    if(argc == 2) return argv[1];
+    return Utils::FileSystem::GetPathToData("../../../ReferenceData/BornAgain/", argv[0]);
+}
+
+int main(int argc, char **argv)
+{
+    FunctionalTests::IsGISAXS09 test;
+    test.run(GetPathToData(argc, argv));
+    return test.analyseResults();
+}
+#endif
diff --git a/Tests/FunctionalTests/TestCore/IsGISAXS09P/IsGISAXS09P.h b/Tests/FunctionalTests/TestCore/IsGISAXS09P/IsGISAXS09P.h
new file mode 100644
index 00000000000..20f525f44f4
--- /dev/null
+++ b/Tests/FunctionalTests/TestCore/IsGISAXS09P/IsGISAXS09P.h
@@ -0,0 +1,28 @@
+#ifndef FUNCTIONALTESTS_ISGISAXS09P_H
+#define FUNCTIONALTESTS_ISGISAXS09P_H
+
+#include "ISampleBuilder.h"
+#include <string>
+#include "OutputData.h"
+
+
+namespace FunctionalTests {
+
+class IsGISAXS09
+{
+ public:
+    IsGISAXS09();
+    ~IsGISAXS09() { delete m_result; delete m_reference; }
+    void run(const std::string &path_to_data = std::string());
+    int analyseResults();
+//    const OutputData<double> *getOutputData() { return m_result;}
+ private:
+    std::string m_name;
+    std::string m_description;
+    OutputData<double> *m_result;
+    OutputData<double> *m_reference;
+};
+
+}
+
+#endif
diff --git a/Tests/FunctionalTests/TestCore/IsGISAXS09R/IsGISAXS09R.cpp b/Tests/FunctionalTests/TestCore/IsGISAXS09R/IsGISAXS09R.cpp
new file mode 100644
index 00000000000..fd65882d1d9
--- /dev/null
+++ b/Tests/FunctionalTests/TestCore/IsGISAXS09R/IsGISAXS09R.cpp
@@ -0,0 +1,77 @@
+#include "IsGISAXS09R.h"
+#include "OutputDataIOFactory.h"
+#include "SampleBuilderFactory.h"
+#include "Simulation.h"
+#include "Utils.h"
+#include "Units.h"
+#include "MathFunctions.h"
+#include "SimulationRegistry.h"
+#include <iostream>
+#include <cmath>
+
+
+FunctionalTests::IsGISAXS09R::IsGISAXS09R()
+    : m_name("IsGISAXS09R")
+    , m_description("Rotated pyramids on top of substrate")
+    , m_result(0)
+	, m_reference(0)
+{ }
+
+
+void FunctionalTests::IsGISAXS09R::run(const std::string &path_to_data)
+{
+
+    SimulationRegistry sim_registry;
+    Simulation *simulation = sim_registry.createSimulation("isgisaxs09_rotated");
+
+    // loading reference data
+    std::string filename = path_to_data + "isgisaxs09_reference_pyramid_Z45.ima.gz";
+    m_reference = OutputDataIOFactory::readIntensityData(filename);
+
+    simulation->runSimulation();
+
+    m_result = simulation->getIntensityData();
+    delete simulation;
+}
+
+
+int FunctionalTests::IsGISAXS09R::analyseResults()
+{
+    const double threshold(2e-10);
+
+    // Calculating average relative difference.
+    *m_result -= *m_reference;
+    *m_result /= *m_reference;
+
+    double diff(0);
+    for(OutputData<double>::const_iterator it =
+            m_result->begin(); it!=m_result->end(); ++it) {
+        diff+= std::fabs(*it);
+    }
+    diff /= m_result->getAllocatedSize();
+
+    // Assess result.
+	bool status_ok(true);
+    if( diff > threshold || std::isnan(diff)) status_ok=false;
+
+    std::cout << " diff " << diff << std::endl;
+    std::cout << m_name << " " << m_description << " " <<
+            (status_ok ? "[OK]" : "[FAILED]") << std::endl;
+    return (status_ok ? 0 : 1);
+}
+
+
+#ifdef STANDALONE
+std::string GetPathToData(int argc, char **argv)
+{
+    if(argc == 2) return argv[1];
+    return Utils::FileSystem::GetPathToData("../../../ReferenceData/BornAgain/", argv[0]);
+}
+
+int main(int argc, char **argv)
+{
+    FunctionalTests::IsGISAXS09R test;
+    test.run(GetPathToData(argc, argv));
+    return test.analyseResults();
+}
+#endif
diff --git a/Tests/FunctionalTests/TestCore/IsGISAXS09R/IsGISAXS09R.h b/Tests/FunctionalTests/TestCore/IsGISAXS09R/IsGISAXS09R.h
new file mode 100644
index 00000000000..16ae3f6d647
--- /dev/null
+++ b/Tests/FunctionalTests/TestCore/IsGISAXS09R/IsGISAXS09R.h
@@ -0,0 +1,28 @@
+#ifndef FUNCTIONALTESTS_ISGISAXS09R_H
+#define FUNCTIONALTESTS_ISGISAXS09R_H
+
+#include "ISampleBuilder.h"
+#include <string>
+#include "OutputData.h"
+
+
+namespace FunctionalTests {
+
+class IsGISAXS09R
+{
+ public:
+    IsGISAXS09R();
+    ~IsGISAXS09R() { delete m_result; delete m_reference; }
+    void run(const std::string &path_to_data = std::string());
+    int analyseResults();
+//    const OutputData<double> *getOutputData() { return m_result;}
+ private:
+    std::string m_name;
+    std::string m_description;
+    OutputData<double> *m_result;
+    OutputData<double> *m_reference;
+};
+
+}
+
+#endif
-- 
GitLab