27 double getQ(
double wavelength,
double angle);
29 double getInvQ(
double wavelength,
double q);
31 std::unique_ptr<PointwiseAxis>
32 createTranslatedAxis(
const IAxis& axis, std::function<
double(
double)> translator, std::string name);
38 return std::make_unique<UnitConverterConvSpec>(*aScan);
40 if (
const auto* qScan =
dynamic_cast<const QSpecScan*
>(&scan))
41 return std::make_unique<UnitConverterQSpec>(*qScan);
43 throw std::runtime_error(
"Bug in UnitConverter1D::createUnitConverter: invalid case");
54 units_type = substituteDefaultUnits(units_type);
55 if (units_type == Axes::Units::NBINS)
58 return translator(coordinateAxis()->getBinCenter(0));
64 units_type = substituteDefaultUnits(units_type);
65 auto coordinate_axis = coordinateAxis();
66 if (units_type == Axes::Units::NBINS)
67 return static_cast<double>(coordinate_axis->size());
69 return translator(coordinate_axis->getBinCenter(coordinate_axis->size() - 1));
75 units = substituteDefaultUnits(units);
76 if (units == Axes::Units::NBINS)
77 return std::make_unique<FixedBinAxis>(axisName(0, units), coordinateAxis()->size(),
79 return createTranslatedAxis(*coordinateAxis(),
getTraslatorTo(units), axisName(0, units));
82 std::unique_ptr<OutputData<double>>
86 throw std::runtime_error(
"Error in UnitConverter1D::createConvertedData: unexpected "
87 "dimensions of the input data");
91 result->addAxis(*q_axis);
93 if (units != Axes::Units::RQ4) {
98 for (
size_t i = 0, size = result->getAllocatedSize(); i < size; ++i)
99 (*result)[i] = data[i] * std::pow((*q_axis)[i], 4);
104 Axes::Units axis_units)
105 : m_wavelength(beam.getWavelength())
109 throw std::runtime_error(
"Error in UnitConverter1D: input axis range is out of bounds");
113 : m_wavelength(handler.wavelength()), m_axis(handler.coordinateAxis()->clone())
117 UnitConverterConvSpec::~UnitConverterConvSpec() =
default;
132 return {Axes::Units::NBINS, Axes::Units::RADIANS, Axes::Units::DEGREES, Axes::Units::QSPACE,
138 return Axes::Units::DEGREES;
142 : m_wavelength(other.m_wavelength), m_axis(other.m_axis->clone())
148 std::vector<std::map<Axes::Units, std::string>> result;
149 result.push_back(AxisNames::InitSpecAxis());
155 switch (units_type) {
156 case Axes::Units::RADIANS:
157 return [](
double value) {
return value; };
158 case Axes::Units::DEGREES:
159 return [](
double value) {
return Units::deg2rad(value); };
160 case Axes::Units::QSPACE:
161 return [
this](
double value) {
return getInvQ(
m_wavelength, value); };
163 throwUnitsError(
"UnitConverterConvSpec::getTraslatorFrom",
164 {Axes::Units::RADIANS, Axes::Units::DEGREES, Axes::Units::QSPACE});
170 switch (units_type) {
171 case Axes::Units::RADIANS:
172 return [](
double value) {
return value; };
173 case Axes::Units::DEGREES:
174 return [](
double value) {
return Units::rad2deg(value); };
175 case Axes::Units::QSPACE:
176 return [wl =
m_wavelength](
double value) {
return getQ(wl, value); };
177 case Axes::Units::RQ4:
178 return [wl =
m_wavelength](
double value) {
return getQ(wl, value); };
180 throwUnitsError(
"UnitConverterConvSpec::getTraslatorTo",
availableUnits());
184 UnitConverterQSpec::UnitConverterQSpec(
const QSpecScan& handler)
185 : m_axis(handler.coordinateAxis()->clone())
189 UnitConverterQSpec::~UnitConverterQSpec() =
default;
206 return {Axes::Units::NBINS, Axes::Units::QSPACE, Axes::Units::RQ4};
212 return Axes::Units::QSPACE;
216 : m_axis(std::unique_ptr<
IAxis>(other.coordinateAxis()->clone()))
223 std::vector<std::map<Axes::Units, std::string>> result;
224 result.push_back(AxisNames::InitSpecAxisQ());
231 switch (units_type) {
232 case Axes::Units::QSPACE:
233 return [](
double value) {
return value; };
234 case Axes::Units::RQ4:
235 return [](
double value) {
return value; };
237 throwUnitsError(
"UnitConverterQSpec::getTraslatorTo",
availableUnits());
243 double getQ(
double wavelength,
double angle)
245 return 4.0 * M_PI * std::sin(angle) / wavelength;
248 double getInvQ(
double wavelength,
double q)
250 double sin_angle = q * wavelength / (4.0 * M_PI);
251 return std::asin(sin_angle);
254 std::unique_ptr<PointwiseAxis>
255 createTranslatedAxis(
const IAxis& axis, std::function<
double(
double)> translator, std::string name)
257 auto coordinates = axis.getBinCenters();
258 for (
size_t i = 0, size = coordinates.size(); i < size; ++i)
259 coordinates[i] = translator(coordinates[i]);
260 return std::make_unique<PointwiseAxis>(name, coordinates);
Declares AngularSpecScan class.
Defines namespace AxisNames.
Defines M_PI and some more mathematical constants.
Defines and implements template class OutputData.
Defines class PointwiseAxis.
Declares QSpecScan class.
Defines UnitConverter1D class and derived classes.
Defines some unit conversion factors and other constants in namespace Units.
Scan type with inclination angles as coordinate values and a unique wavelength.
Beam defined by wavelength, direction and intensity.
Interface for one-dimensional axes.
Pure virtual base class for all types of specular scans.
std::vector< T > getRawDataVector() const
Returns copy of raw data vector.
size_t getRank() const
Returns number of dimensions.
Scan type with z-components of scattering vector as coordinate values.
static std::unique_ptr< UnitConverter1D > createUnitConverter(const ISpecularScan &handler)
Factory function to create unit converter for particular type of specular data.
size_t dimension() const override
Returns dimensionality of converted canvas.
std::unique_ptr< OutputData< double > > createConvertedData(const OutputData< double > &data, Axes::Units units) const override
Creates OutputData array in converter units.
std::unique_ptr< IAxis > createConvertedAxis(size_t i_axis, Axes::Units units) const override
Creates axis in converted units.
double calculateMax(size_t i_axis, Axes::Units units_type) const override
Calculates maximum on-axis value in given units.
double calculateMin(size_t i_axis, Axes::Units units_type) const override
Calculates minimum on-axis value in given units.
virtual std::function< double(double)> getTraslatorTo(Axes::Units units_type) const =0
Returns translating functional (rads --> output units)
Conversion of axis units for the case of conventional (angle-based) reflectometry.
UnitConverterConvSpec(const Beam &beam, const IAxis &axis, Axes::Units axis_units=Axes::Units::RADIANS)
Constructs the object for unit conversion.
size_t axisSize(size_t i_axis) const override
Returns the size of underlying axis.
double m_wavelength
basic wavelength in nm (for translation to q-space).
std::vector< std::map< Axes::Units, std::string > > createNameMaps() const override
Creates name map for axis in various units.
std::function< double(double)> getTraslatorTo(Axes::Units units_type) const override
Returns translating functional (rads --> desired units)
std::function< double(double)> getTraslatorFrom(Axes::Units units_type) const
Returns translating functional (input units --> rads)
Axes::Units defaultUnits() const override
Returns default units to convert to.
std::unique_ptr< IAxis > m_axis
basic inclination angles (in rads).
std::vector< Axes::Units > availableUnits() const override
Returns the list of all available units.
Conversion of axis units for the case of q-defined reflectometry.
std::function< double(double)> getTraslatorTo(Axes::Units units_type) const override
Returns translating functional (inv. nm --> desired units)
std::unique_ptr< IAxis > m_axis
qz values (in inv. nm).
std::vector< std::map< Axes::Units, std::string > > createNameMaps() const override
Creates name map for axis in various units.
Axes::Units defaultUnits() const override
Returns default units to convert to.
size_t axisSize(size_t i_axis) const override
Returns the size of underlying axis.
std::vector< Axes::Units > availableUnits() const override
Returns the list of all available units.