Skip to content
Snippets Groups Projects
Commit 06796aab authored by Yurov, Dmitry's avatar Yurov, Dmitry
Browse files

DepthProbeConverter

Redmine: #2006
parent af1bbdef
No related branches found
No related tags found
No related merge requests found
...@@ -31,7 +31,7 @@ class IAxis; ...@@ -31,7 +31,7 @@ class IAxis;
// workaround for SWIG (instead of just writing enum class AxesUnits...) // workaround for SWIG (instead of just writing enum class AxesUnits...)
struct BA_CORE_API_ AxesUnitsWrap { struct BA_CORE_API_ AxesUnitsWrap {
enum AxesUnits { DEFAULT, NBINS, RADIANS, DEGREES, MM, QSPACE }; enum AxesUnits { DEFAULT, NBINS, RADIANS, DEGREES, MM, NM, QSPACE };
}; };
typedef AxesUnitsWrap::AxesUnits AxesUnits; typedef AxesUnitsWrap::AxesUnits AxesUnits;
...@@ -51,7 +51,7 @@ public: ...@@ -51,7 +51,7 @@ public:
virtual double calculateMax(size_t i_axis, AxesUnits units_type) const=0; virtual double calculateMax(size_t i_axis, AxesUnits units_type) const=0;
virtual size_t axisSize(size_t i_axis) const=0; virtual size_t axisSize(size_t i_axis) const=0;
std::string axisName(size_t i_axis, AxesUnits units_type = AxesUnits::DEFAULT) const; virtual std::string axisName(size_t i_axis, AxesUnits units_type = AxesUnits::DEFAULT) const;
virtual AxesUnits defaultUnits() const=0; virtual AxesUnits defaultUnits() const=0;
#ifndef SWIG #ifndef SWIG
......
...@@ -350,3 +350,105 @@ void OffSpecularConverter::addDetectorYAxis(const IDetector2D& detector) ...@@ -350,3 +350,105 @@ void OffSpecularConverter::addDetectorYAxis(const IDetector2D& detector)
"wrong detector type"); "wrong detector type");
} }
} }
/* DepthProbeConverter **********************************************/
const std::string z_axis_name = "Position [nm]";
DepthProbeConverter::DepthProbeConverter(const Beam& beam, const IAxis& alpha_axis,
const IAxis& z_axis)
: UnitConverterSimple(beam)
{
auto alpha_axis_name = axisName(0);
addAxisData(alpha_axis_name, alpha_axis.getMin(), alpha_axis.getMax(), defaultUnits(),
alpha_axis.size());
addZAxis(z_axis);
}
DepthProbeConverter::~DepthProbeConverter() = default;
DepthProbeConverter* DepthProbeConverter::clone() const
{
return new DepthProbeConverter(*this);
}
double DepthProbeConverter::calculateMin(size_t i_axis, AxesUnits units_type) const
{
checkForDefaultUnits(units_type);
if (i_axis > 0) {
checkIndex(i_axis);
const AxisData& axis_data = m_axis_data_table[i_axis];
return axis_data.min;
}
return UnitConverterSimple::calculateMin(i_axis, units_type);
}
double DepthProbeConverter::calculateMax(size_t i_axis, AxesUnits units_type) const
{
checkForDefaultUnits(units_type);
if (i_axis > 0) {
checkIndex(i_axis);
const AxisData& axis_data = m_axis_data_table[i_axis];
return axis_data.max;
}
return UnitConverterSimple::calculateMax(i_axis, units_type);
}
std::string DepthProbeConverter::axisName(size_t i_axis, AxesUnits units_type) const
{
checkForDefaultUnits(units_type);
if (i_axis > 0) {
checkIndex(i_axis);
return z_axis_name;
}
return IUnitConverter::axisName(i_axis, units_type);
}
std::unique_ptr<IAxis> DepthProbeConverter::createConvertedAxis(size_t i_axis,
AxesUnits units) const
{
checkForDefaultUnits(units);
if (i_axis > 0) {
checkIndex(i_axis);
const AxisData& axis_data = m_axis_data_table[i_axis];
return std::make_unique<FixedBinAxis>(axis_data.name, axis_data.nbins, axis_data.min,
axis_data.max);
}
return UnitConverterSimple::createConvertedAxis(i_axis, units);
}
DepthProbeConverter::DepthProbeConverter(const DepthProbeConverter& other)
: UnitConverterSimple(other)
{}
void DepthProbeConverter::checkForDefaultUnits(AxesUnits units_type) const
{
if (units_type != AxesUnits::DEFAULT)
throw std::runtime_error(
"Error DepthProbeConverter::checkForDefaultUnits: only default units are allowed.");
}
double DepthProbeConverter::calculateValue(size_t, AxesUnits units_type, double value) const
{
switch(units_type) {
case AxesUnits::DEGREES:
return Units::rad2deg(value);
default:
throw std::runtime_error("Error in DepthProbeConverter::calculateValue: "
"target units not available: "
+ std::to_string(static_cast<int>(units_type)));
}
}
std::vector<std::map<AxesUnits, std::string>> DepthProbeConverter::createNameMaps() const
{
std::vector<std::map<AxesUnits, std::string>> result;
result.push_back(AxisNames::InitSpecAxis());
return result;
}
void DepthProbeConverter::addZAxis(const IAxis &z_axis)
{
addAxisData(z_axis_name, z_axis.getMin(), z_axis.getMax(), AxesUnits::NM, z_axis.size());
}
...@@ -134,4 +134,32 @@ private: ...@@ -134,4 +134,32 @@ private:
void addDetectorYAxis(const IDetector2D& detector); void addDetectorYAxis(const IDetector2D& detector);
}; };
//! DepthProbeConverter class handles the unit translations for depth probe simulations
//! Its default units are radians for x-axis and nm for y-axis
//! @ingroup simulation_internal
class BA_CORE_API_ DepthProbeConverter : public UnitConverterSimple
{
public:
DepthProbeConverter(const Beam& beam, const IAxis& alpha_axis, const IAxis& z_axis);
virtual ~DepthProbeConverter();
DepthProbeConverter* clone() const override;
double calculateMin(size_t i_axis, AxesUnits units_type) const override;
double calculateMax(size_t i_axis, AxesUnits units_type) const override;
// TODO: remove axisName after implementing functionality for two axis in different units
std::string axisName(size_t i_axis, AxesUnits units_type = AxesUnits::DEFAULT) const override;
AxesUnits defaultUnits() const override { return AxesUnits::DEGREES; }
std::unique_ptr<IAxis> createConvertedAxis(size_t i_axis, AxesUnits units) const override;
private:
DepthProbeConverter(const DepthProbeConverter& other);
void checkForDefaultUnits(AxesUnits units_type) const;
double calculateValue(size_t, AxesUnits units_type, double value) const override;
std::vector<std::map<AxesUnits, std::string>> createNameMaps() const override;
void addZAxis(const IAxis& z_axis);
};
#endif // SIMPLEUNITCONVERTERS_H #endif // SIMPLEUNITCONVERTERS_H
#include "google_test.h"
#include "Beam.h"
#include "FixedBinAxis.h"
#include "MathConstants.h"
#include "SimpleUnitConverters.h"
#include "Units.h"
class DepthProbeConverterTest : public ::testing::Test
{
public:
DepthProbeConverterTest();
~DepthProbeConverterTest();
protected:
void checkMainFunctionality(const DepthProbeConverter& test_object);
void checkAlphaAxis(AxesUnits units, const DepthProbeConverter& test_object);
void checkZAxis(AxesUnits units, const DepthProbeConverter& test_object);
const double m_alpha_start = 0.5; // first axis value in rads
const double m_alpha_end = 1.0; // last axis value in rads
const double m_z_start = -30.0;
const double m_z_end = 10.0;
const size_t m_nbins = 100;
Beam m_beam;
FixedBinAxis m_inclination_axis;
FixedBinAxis m_z_axis;
};
DepthProbeConverterTest::DepthProbeConverterTest()
: m_inclination_axis("Angles", m_nbins, m_alpha_start, m_alpha_end) // angles in radians
, m_z_axis("Positions", m_nbins, m_z_start, m_z_end) // z positions in nm
{
m_beam.setCentralK(1.0, 0.0, 0.0); // wavelength = 1.0 nm
}
DepthProbeConverterTest::~DepthProbeConverterTest() = default;
void DepthProbeConverterTest::checkMainFunctionality(const DepthProbeConverter& test_object)
{
EXPECT_EQ(test_object.dimension(), 2u);
EXPECT_NEAR(test_object.calculateMin(0, AxesUnits::DEFAULT), Units::rad2deg(m_alpha_start),
Units::rad2deg(m_alpha_start) * 1e-10);
EXPECT_NEAR(test_object.calculateMax(0, AxesUnits::DEFAULT), Units::rad2deg(m_alpha_end),
Units::rad2deg(m_alpha_end) * 1e-10);
checkAlphaAxis(AxesUnits::DEFAULT, test_object);
checkZAxis(AxesUnits::DEFAULT, test_object);
}
void DepthProbeConverterTest::checkAlphaAxis(AxesUnits units,
const DepthProbeConverter& test_object)
{
auto axis = test_object.createConvertedAxis(0, units);
EXPECT_TRUE(dynamic_cast<FixedBinAxis*>(axis.get()));
EXPECT_EQ(axis->size(), test_object.axisSize(0));
EXPECT_EQ(axis->size(), m_nbins);
EXPECT_EQ(axis->getName(), test_object.axisName(0, units));
EXPECT_EQ(axis->getMin(), test_object.calculateMin(0, units));
EXPECT_EQ(axis->getMax(), test_object.calculateMax(0, units));
}
void DepthProbeConverterTest::checkZAxis(AxesUnits units, const DepthProbeConverter& test_object)
{
auto axis = test_object.createConvertedAxis(1, units);
EXPECT_TRUE(dynamic_cast<FixedBinAxis*>(axis.get()));
EXPECT_EQ(axis->size(), test_object.axisSize(1));
EXPECT_EQ(axis->size(), m_nbins);
EXPECT_EQ(axis->getName(), test_object.axisName(1, units));
EXPECT_EQ(axis->getMin(), test_object.calculateMin(1, units));
EXPECT_NEAR(axis->getMin(), m_z_start, std::abs(m_z_start) * 1e-10);
EXPECT_EQ(axis->getMax(), test_object.calculateMax(1, units));
EXPECT_NEAR(axis->getMax(), m_z_end, std::abs(m_z_end) * 1e-10);
}
TEST_F(DepthProbeConverterTest, DepthProbeConverter)
{
DepthProbeConverter converter(m_beam, m_inclination_axis, m_z_axis);
checkMainFunctionality(converter);
}
TEST_F(DepthProbeConverterTest, DepthProbeConverterExceptions)
{
DepthProbeConverter converter(m_beam, m_inclination_axis, m_z_axis);
EXPECT_THROW(converter.axisName(0, AxesUnits::MM), std::runtime_error);
EXPECT_THROW(converter.axisName(0, AxesUnits::DEGREES), std::runtime_error);
EXPECT_THROW(converter.axisName(0, AxesUnits::RADIANS), std::runtime_error);
EXPECT_THROW(converter.axisName(0, AxesUnits::QSPACE), std::runtime_error);
EXPECT_THROW(converter.axisName(1, AxesUnits::MM), std::runtime_error);
EXPECT_THROW(converter.axisName(2, AxesUnits::DEFAULT), std::runtime_error);
EXPECT_THROW(converter.calculateMin(0, AxesUnits::MM), std::runtime_error);
EXPECT_THROW(converter.calculateMin(0, AxesUnits::DEGREES), std::runtime_error);
EXPECT_THROW(converter.calculateMin(0, AxesUnits::RADIANS), std::runtime_error);
EXPECT_THROW(converter.calculateMin(0, AxesUnits::QSPACE), std::runtime_error);
EXPECT_THROW(converter.calculateMin(1, AxesUnits::MM), std::runtime_error);
EXPECT_THROW(converter.calculateMin(2, AxesUnits::DEFAULT), std::runtime_error);
EXPECT_THROW(converter.calculateMax(0, AxesUnits::MM), std::runtime_error);
EXPECT_THROW(converter.calculateMax(0, AxesUnits::DEGREES), std::runtime_error);
EXPECT_THROW(converter.calculateMax(0, AxesUnits::RADIANS), std::runtime_error);
EXPECT_THROW(converter.calculateMax(0, AxesUnits::QSPACE), std::runtime_error);
EXPECT_THROW(converter.calculateMax(1, AxesUnits::MM), std::runtime_error);
EXPECT_THROW(converter.calculateMax(2, AxesUnits::RADIANS), std::runtime_error);
EXPECT_THROW(converter.createConvertedAxis(0, AxesUnits::MM), std::runtime_error);
EXPECT_THROW(converter.createConvertedAxis(0, AxesUnits::DEGREES), std::runtime_error);
EXPECT_THROW(converter.createConvertedAxis(0, AxesUnits::RADIANS), std::runtime_error);
EXPECT_THROW(converter.createConvertedAxis(0, AxesUnits::QSPACE), std::runtime_error);
EXPECT_THROW(converter.createConvertedAxis(1, AxesUnits::MM), std::runtime_error);
EXPECT_THROW(converter.createConvertedAxis(2, AxesUnits::DEFAULT), std::runtime_error);
}
TEST_F(DepthProbeConverterTest, DepthProbeConverterClone)
{
DepthProbeConverter converter(m_beam, m_inclination_axis, m_z_axis);
std::unique_ptr<DepthProbeConverter> converter_clone(converter.clone());
checkMainFunctionality(*converter_clone);
}
// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory> // To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
#include "CustomBinAxisTest.h" #include "CustomBinAxisTest.h"
#include "DepthProbeConverterTest.h"
#include "Histogram1DTest.h" #include "Histogram1DTest.h"
#include "VariableBinAxisTest.h" #include "VariableBinAxisTest.h"
#include "Histogram2DTest.h" #include "Histogram2DTest.h"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment