1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file Device/Detector/SphericalDetector.cpp
//! @brief Implements class SphericalDetector.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#include "Device/Detector/SphericalDetector.h"
#include "Base/Axis/Frame.h"
#include "Base/Axis/MakeScale.h"
#include "Base/Axis/Pixel.h"
#include "Base/Axis/Scale.h"
#include "Base/Util/Assert.h"
#include "Device/Beam/Beam.h"
#include "Device/Resolution/IDetectorResolution.h"
#include <numbers>
using std::numbers::pi;
namespace {
Frame* detEquiFrame(size_t n_phi, double phi_min, double phi_max, size_t n_alpha, double alpha_min,
double alpha_max)
{
if (phi_min >= phi_max)
throw std::runtime_error("Detector phi: min >= max");
if (alpha_min >= alpha_max)
throw std::runtime_error("Detector alpha: min >= max");
return new Frame(newEquiDivision("phi_f (rad)", n_phi, phi_min, phi_max),
newEquiDivision("alpha_f (rad)", n_alpha, alpha_min, alpha_max));
}
} // namespace
SphericalDetector::SphericalDetector(size_t n_phi, double phi_min, double phi_max, size_t n_alpha,
double alpha_min, double alpha_max)
: IDetector(detEquiFrame(n_phi, phi_min, phi_max, n_alpha, alpha_min, alpha_max))
{
ASSERT(-pi / 2 < axis(0).min() && axis(0).max() < +pi / 2);
ASSERT(-pi / 2 < axis(1).min() && axis(1).max() < +pi / 2);
}
SphericalDetector* SphericalDetector::clone() const
{
return new SphericalDetector(*this);
}
Pixel* SphericalDetector::createPixel(size_t index) const
{
const size_t ix = axisBinIndex(index, 0);
const size_t iy = axisBinIndex(index, 1);
const Bin1D& phi_in = axis(0).bin(ix);
const Bin1D phi_out = Bin1D::FromTo(atan(phi_in.min()), atan(phi_in.max()));
const double ru = hypot(1., pow(phi_in.center(), 2));
const Bin1D& alpha_in = axis(1).bin(iy);
const Bin1D alpha_out = Bin1D::FromTo(atan(alpha_in.min() / ru), atan(alpha_in.max() / ru));
return new Pixel(phi_out, alpha_out);
}
size_t SphericalDetector::indexOfSpecular(const Beam& beam) const
{
const double alpha = beam.alpha_i();
const double phi = beam.phi_i();
const double u = tan(phi);
const double v = hypot(1., u * u) * tan(alpha);
if (axis(0).rangeComprises(u) && axis(1).rangeComprises(v))
return getGlobalIndex(axis(0).closestIndex(u), axis(1).closestIndex(v));
return totalSize();
}
|