// ************************************************************************************************ // // BornAgain: simulate and fit reflection and scattering // //! @file Base/Axis/Frame.cpp //! @brief Implements class Frame. //! //! @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 "Base/Axis/Frame.h" #include "Base/Axis/Bin.h" #include "Base/Axis/IAxis.h" #include "Base/Util/Assert.h" Frame::Frame(const std::vector<IAxis*>& axes) : m_axes(axes) { } const IAxis& Frame::axis(size_t serial_number) const { return *m_axes[serial_number]; } double Frame::projectedCoord(size_t i_flat, size_t k_axis) const { auto axis_index = projectedIndex(i_flat, k_axis); return (*m_axes[k_axis])[axis_index]; } Bin1D Frame::projectedBin(size_t i_flat, size_t k_axis) const { auto axis_index = projectedIndex(i_flat, k_axis); return m_axes[k_axis]->bin(axis_index); } std::vector<int> Frame::allIndices(size_t i_flat) const { size_t remainder = i_flat; std::vector<int> result; result.resize(rank()); for (size_t k = 0; k < rank(); ++k) { size_t kk = rank() - 1 - k; result[kk] = (int)(remainder % m_axes[kk]->size()); remainder /= m_axes[kk]->size(); } return result; } size_t Frame::projectedIndex(size_t i_flat, size_t k_axis) const { size_t remainder(i_flat); for (size_t k = 0; k < rank(); ++k) { size_t kk = rank() - 1 - k; size_t result = remainder % m_axes[kk]->size(); if (k_axis == kk) return result; remainder /= m_axes[kk]->size(); } ASSERT(0); } size_t Frame::toGlobalIndex(const std::vector<unsigned>& axes_indices) const { ASSERT(axes_indices.size() == rank()); size_t result = 0; size_t step_size = 1; for (size_t k = rank(); k > 0; --k) { ASSERT(axes_indices[k - 1] < m_axes[k - 1]->size()); result += axes_indices[k - 1] * step_size; step_size *= m_axes[k - 1]->size(); } return result; } size_t Frame::findGlobalIndex(const std::vector<double>& coordinates) const { ASSERT(coordinates.size() == rank()); std::vector<unsigned> axes_indexes; axes_indexes.resize(rank()); for (size_t k = 0; k < rank(); ++k) axes_indexes[k] = static_cast<unsigned>(m_axes[k]->findClosestIndex(coordinates[k])); return toGlobalIndex(axes_indexes); }