// ************************************************************************************************ // // 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/FrameUtil.h" #include "Base/Axis/Scale.h" #include "Base/Util/Assert.h" #include "Base/Util/StringUtil.h" Frame::Frame(const CloneableVector<const Scale>& axes) : m_axes(axes) , m_size(FrameUtil::product_size(m_axes.shared())) { } Frame::Frame(const Scale* ax0) : Frame(std::vector<const Scale*>{ax0}) { } Frame::Frame(const Scale* ax0, const Scale* ax1) : Frame(std::vector<const Scale*>{ax0, ax1}) { } Frame::Frame(const Frame&) = default; Frame::~Frame() = default; Frame* Frame::clone() const { return new Frame(*this); } void Frame::setAxes(CloneableVector<const Scale> axes) { std::swap(m_axes, axes); m_size = FrameUtil::product_size(m_axes.shared()); } size_t Frame::rank() const { return m_axes.size(); } const Scale& Frame::axis(size_t k_axis) const { ASSERT(k_axis < rank()); return *m_axes.at(k_axis); } const Scale& Frame::xAxis() const { return *m_axes.at(0); } const Scale& Frame::yAxis() const { ASSERT(1 < rank()); return *m_axes.at(1); } size_t Frame::projectedSize(size_t k_axis) const { ASSERT(k_axis < rank()); return m_axes[k_axis]->size(); } 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]->binCenter(axis_index); } std::vector<int> Frame::allIndices(size_t i_flat) const { std::vector<int> result(rank()); for (size_t k = 0; k < rank(); ++k) result[k] = projectedIndex(i_flat, k); return result; } size_t Frame::projectedIndex(size_t i, size_t k_axis) const { ASSERT(k_axis < rank()); if (rank() == 1) return i; if (rank() == 2) { if (k_axis == 0) return i % m_axes[0]->size(); if (k_axis == 1) return (i / m_axes[0]->size()) % m_axes[1]->size(); } ASSERT_NEVER; } bool Frame::operator==(const Frame& o) const { if (rank() != o.rank()) return false; for (size_t k = 0; k < rank(); ++k) if (axis(k) != o.axis(k)) return false; return true; } std::vector<const Scale*> Frame::clonedAxes() const { return m_axes.cloned_vector(); } bool Frame::hasSameSizes(const Frame& o) const { if (rank() != o.rank()) return false; for (size_t k = 0; k < rank(); ++k) if (axis(k).size() != o.axis(k).size()) return false; return true; } Frame* Frame::plottableFrame() const { std::vector<const Scale*> outaxes; for (size_t k = 0; k < rank(); ++k) { auto* s = new Scale(axis(k).plottableScale()); outaxes.emplace_back(s); } return new Frame(std::move(outaxes)); } Frame* Frame::flat() const { std::vector<const Scale*> outaxes; for (const Scale* s : m_axes) if (s->size() > 1) outaxes.emplace_back(s->clone()); return new Frame(std::move(outaxes)); } void Frame::setScale(size_t k_axis, Scale* scale) { m_axes.replace_at(k_axis, scale); m_size = FrameUtil::product_size(m_axes.shared()); }