26 std::vector<std::vector<double>>
 
   27 extractValues(std::vector<std::vector<ParameterSample>> samples,
 
   30     std::vector<std::vector<double>> result;
 
   31     result.resize(samples.size());
 
   32     for (
size_t i = 0, size = result.size(); i < size; ++i) {
 
   33         const auto& sample_row = samples[i];
 
   34         auto& result_row = result[i];
 
   35         result_row.reserve(sample_row.size());
 
   36         std::for_each(sample_row.begin(), sample_row.end(),
 
   38                           result_row.push_back(extractor(sample));
 
   46 AngularSpecScan::AngularSpecScan(
double wl, std::vector<double> inc_angle)
 
   48       m_inc_angle(std::make_unique<
PointwiseAxis>(
"inc_angles", std::move(inc_angle))),
 
   52     checkInitialization();
 
   55 AngularSpecScan::AngularSpecScan(
double wl, 
const IAxis& inc_angle)
 
   56     : m_wl(wl), m_inc_angle(inc_angle.clone()),
 
   60     checkInitialization();
 
   63 AngularSpecScan::AngularSpecScan(
double wl, 
int nbins, 
double alpha_i_min, 
double alpha_i_max)
 
   65       m_inc_angle(std::make_unique<
FixedBinAxis>(
"inc_angles", nbins, alpha_i_min, alpha_i_max)),
 
   69     checkInitialization();
 
   75     result->setFootprintFactor(m_footprint.get());
 
   76     result->setWavelengthResolution(*m_wl_resolution);
 
   77     result->setAngleResolution(*m_inc_resolution);
 
   81 AngularSpecScan::~AngularSpecScan() = 
default;
 
   85     const auto wls = extractValues(applyWlResolution(),
 
   87     const auto incs = extractValues(applyIncResolution(),
 
   90     std::vector<SpecularSimulationElement> result;
 
   92     for (
size_t i = 0; i < m_inc_angle->size(); ++i) {
 
   93         for (
size_t k = 0, size_incs = incs[i].size(); k < size_incs; ++k) {
 
   94             const double inc = incs[i][k];
 
   95             for (
size_t j = 0, size_wls = wls[i].size(); j < size_wls; ++j) {
 
   96                 const double wl = wls[i][j];
 
  107     m_footprint.reset(f_factor ? f_factor->clone() : 
nullptr);
 
  112     m_wl_resolution.reset(resolution.clone());
 
  113     m_wl_res_cache.clear();
 
  114     m_wl_res_cache.shrink_to_fit();
 
  117 void AngularSpecScan::setRelativeWavelengthResolution(
const RangedDistribution& distr,
 
  120     std::unique_ptr<ScanResolution> resolution(
 
  121         ScanResolution::scanRelativeResolution(distr, rel_dev));
 
  126                                                       const std::vector<double>& rel_dev)
 
  128     std::unique_ptr<ScanResolution> resolution(
 
  129         ScanResolution::scanRelativeResolution(distr, rel_dev));
 
  133 void AngularSpecScan::setAbsoluteWavelengthResolution(
const RangedDistribution& distr,
 
  136     std::unique_ptr<ScanResolution> resolution(
 
  137         ScanResolution::scanAbsoluteResolution(distr, std_dev));
 
  142                                                       const std::vector<double>& std_dev)
 
  144     std::unique_ptr<ScanResolution> resolution(
 
  145         ScanResolution::scanAbsoluteResolution(distr, std_dev));
 
  151     m_inc_resolution.reset(resolution.clone());
 
  152     m_inc_res_cache.clear();
 
  153     m_inc_res_cache.shrink_to_fit();
 
  156 void AngularSpecScan::setRelativeAngularResolution(
const RangedDistribution& distr, 
double rel_dev)
 
  158     std::unique_ptr<ScanResolution> resolution(
 
  159         ScanResolution::scanRelativeResolution(distr, rel_dev));
 
  164                                                    const std::vector<double>& rel_dev)
 
  166     std::unique_ptr<ScanResolution> resolution(
 
  167         ScanResolution::scanRelativeResolution(distr, rel_dev));
 
  171 void AngularSpecScan::setAbsoluteAngularResolution(
const RangedDistribution& distr, 
double std_dev)
 
  173     std::unique_ptr<ScanResolution> resolution(
 
  174         ScanResolution::scanAbsoluteResolution(distr, std_dev));
 
  179                                                    const std::vector<double>& std_dev)
 
  181     std::unique_ptr<ScanResolution> resolution(
 
  182         ScanResolution::scanAbsoluteResolution(distr, std_dev));
 
  189         throw std::runtime_error(
"Error in AngularSpecScan::footprint: given index exceeds the " 
  190                                  "number of simulation elements");
 
  192     std::vector<double> result(n_elements, 1.0);
 
  196     const size_t n_wl_samples = m_wl_resolution->nSamples();
 
  197     const size_t n_inc_samples = m_inc_resolution->nSamples();
 
  199     const auto sample_values = extractValues(
 
  200         applyIncResolution(), [](
const ParameterSample& sample) { 
return sample.value; });
 
  202     const size_t pos_out = start / (n_wl_samples * n_inc_samples);
 
  203     size_t pos_inc = (start - pos_out * n_wl_samples * n_inc_samples) / n_wl_samples;
 
  204     size_t pos_wl = (start - pos_inc * n_wl_samples);
 
  205     int left = 
static_cast<int>(n_elements);
 
  207     for (
size_t i = pos_out; left > 0; ++i)
 
  208         for (
size_t k = pos_inc; k < n_inc_samples && left > 0; ++k) {
 
  210             const double angle = sample_values[i][k];
 
  212                 (angle >= 0 && angle <= M_PI_2) ? m_footprint->calculate(angle) : 1.0;
 
  213             for (
size_t j = pos_wl; j < n_wl_samples && left > 0; ++j) {
 
  225     return m_inc_angle->size() * m_wl_resolution->nSamples() * m_inc_resolution->nSamples();
 
  231     const size_t axis_size = m_inc_angle->size();
 
  232     std::vector<double> result(axis_size, 0.0);
 
  234     const auto wl_weights = extractValues(
 
  235         applyWlResolution(), [](
const ParameterSample& sample) { 
return sample.weight; });
 
  236     const auto inc_weights = extractValues(
 
  237         applyIncResolution(), [](
const ParameterSample& sample) { 
return sample.weight; });
 
  240     for (
size_t i = 0; i < axis_size; ++i) {
 
  241         double& current = result[i];
 
  242         for (
size_t k = 0, size_incs = inc_weights[i].size(); k < size_incs; ++k) {
 
  243             const double inc_weight = inc_weights[i][k];
 
  244             for (
size_t j = 0, size_wls = wl_weights[i].size(); j < size_wls; ++j) {
 
  245                 current += sim_elements[elem_pos].getIntensity() * inc_weight * wl_weights[i][j];
 
  255     std::stringstream result;
 
  256     result << 
"\n" << 
pyfmt::indent() << 
"# Defining specular scan:\n";
 
  258     result << axis_def << 
coordinateAxis()->pyString(
"rad", axis_def.size()) << 
"\n";
 
  261     result << 
"ba.AngularSpecScan(" << pyfmt::printDouble(m_wl) << 
", axis)\n";
 
  264         result << *m_footprint << 
"\n";
 
  265         result << 
pyfmt::indent() << 
"scan.setFootprintFactor(footprint)\n";
 
  267     if (!m_inc_resolution->empty()) {
 
  268         result << 
"\n" << 
pyfmt::indent() << 
"# Defining angular resolution\n";
 
  269         result << *m_inc_resolution << 
"\n";
 
  270         result << 
pyfmt::indent() << 
"scan.setAngleResolution(resolution)\n";
 
  272     if (!m_wl_resolution->empty()) {
 
  273         result << 
"\n" << 
pyfmt::indent() << 
"# Defining wavelength resolution\n";
 
  274         result << *m_wl_resolution << 
"\n";
 
  275         result << 
pyfmt::indent() << 
"scan.setWavelengthResolution(resolution)\n";
 
  280 void AngularSpecScan::checkInitialization()
 
  283         throw std::runtime_error(
 
  284             "Error in AngularSpecScan::checkInitialization: wavelength shell be positive");
 
  286     const std::vector<double> axis_values = m_inc_angle->getBinCenters();
 
  287     if (!std::is_sorted(axis_values.begin(), axis_values.end()))
 
  288         throw std::runtime_error(
"Error in AngularSpecScan::checkInitialization: q-vector values " 
  289                                  "shall be sorted in ascending order.");
 
  294 AngularSpecScan::DistrOutput AngularSpecScan::applyWlResolution()
 const 
  296     if (m_wl_res_cache.empty())
 
  297         m_wl_res_cache = m_wl_resolution->generateSamples(m_wl, m_inc_angle->size());
 
  298     return m_wl_res_cache;
 
  301 AngularSpecScan::DistrOutput AngularSpecScan::applyIncResolution()
 const 
  303     if (m_inc_res_cache.empty())
 
  304         m_inc_res_cache = m_inc_resolution->generateSamples(m_inc_angle->getBinCenters());
 
  305     return m_inc_res_cache;
 
Declares AngularSpecScan class.
 
Defines class FixedBinAxis.
 
Defines class PointwiseAxis.
 
Defines functions in namespace pyfmt.
 
Defines classes representing ranged one-dimensional distributions.
 
Defines scan resolution class.
 
Declares the class SpecularSimulationElement.
 
Scan type with inclination angles as coordinate values and a unique wavelength.
 
void setAngleResolution(const ScanResolution &resolution)
Sets angle resolution values via ScanResolution object.
 
std::vector< double > footprint(size_t i, size_t n_elements) const override
Returns footprint correction factor for a range of simulation elements of size n_elements and startin...
 
size_t numberOfSimulationElements() const override
Returns the number of simulation elements.
 
virtual const IAxis * coordinateAxis() const override
Returns coordinate axis assigned to the data holder.
 
std::vector< double > createIntensities(const std::vector< SpecularSimulationElement > &sim_elements) const override
Returns intensity vector corresponding to convolution of given simulation elements.
 
void setFootprintFactor(const IFootprintFactor *f_factor)
Sets footprint correction factor.
 
void setWavelengthResolution(const ScanResolution &resolution)
Sets wavelength resolution values via ScanResolution object.
 
std::string print() const override
Print scan definition in python format.
 
std::vector< SpecularSimulationElement > generateSimulationElements() const override
Generates simulation elements for specular simulations.
 
Axis with fixed bin size.
 
Interface for one-dimensional axes.
 
A parameter value with a weight, as obtained when sampling from a distribution.
 
Axis containing arbitrary (non-equidistant) coordinate values.
 
Interface for one-dimensional ranged distributions.
 
Container for reflectivity resolution data.
 
Data stucture containing both input and output of a single image pixel for specular simulation.
 
std::string indent(size_t width)
Returns a string of blanks with given width.