2 * Copyright (C) 2012-2021 Euclid Science Ground Segment
4 * This library is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License as published by the Free
6 * Software Foundation; either version 3.0 of the License, or (at your option)
9 * This library is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19#include <boost/algorithm/string.hpp>
24namespace GridContainer {
27 * Template class to help on the recursive traversal of the grid
29 * Handle the axis stored on the (I-1)th position on the GridContainer::AxesTuple
31template <size_t I, typename GridCellManager, typename... Axes>
32struct GridToFitsHelper {
35 * Generate recursively the column description for each *knot* on the grid. The order on the tuples
36 * is reversed, so the 0th tuple element is inserted on the last position.
38 * An instance of a grid
40 * A vector where to emplace the description
42 static void addColumnDescriptions(const GridContainer<GridCellManager, Axes...>& grid,
43 std::vector<Table::ColumnDescription>& description) {
44 auto& axis = grid.template getAxis<I - 1>();
45 using knot_t = typename std::remove_reference<decltype(axis)>::type::data_type;
46 auto name = axis.name();
47 boost::replace_all(name, " ", "_");
48 description.emplace_back(name, typeid(typename GridAxisToTable<knot_t>::table_cell_t));
50 GridToFitsHelper<I - 1, GridCellManager, Axes...>::addColumnDescriptions(grid, description);
54 * Iterate over the elements of the (I-1)th axis, and for each one call recursively unfold on the next axis.
56 * Used to keep track of the types of the knots of the previous axes
58 * An instance of a grid
60 * As populated by getColumnDescriptions
62 * Grid cells will be inserted on this vector
64 * Used to keep track of the values of the knots of the previous axis
66 template <typename... Args>
67 static void unfold(const GridContainer<GridCellManager, Axes...>& grid, const std::shared_ptr<Table::ColumnInfo>& column_info,
68 std::vector<Table::Row>& rows, std::pair<size_t, Args>... axes) {
69 auto& axis = grid.template getAxis<I - 1>();
70 for (size_t i = 0; i < axis.size(); ++i) {
71 GridToFitsHelper<I - 1, GridCellManager, Axes...>::unfold(grid, column_info, rows, std::make_pair(i, axis[i]), axes...);
76 * Same as before, but without the book-keeping data, since this is the entry point
78 static void unfold(const GridContainer<GridCellManager, Axes...>& grid, const std::shared_ptr<Table::ColumnInfo>& column_info,
79 std::vector<Table::Row>& rows) {
80 auto& axis = grid.template getAxis<I - 1>();
81 for (size_t i = 0; i < axis.size(); ++i) {
82 GridToFitsHelper<I - 1, GridCellManager, Axes...>::unfold(grid, column_info, rows, std::make_pair(i, axis[i]));
88 * Base class for the recursive traversal of the grid
90template <typename GridCellManager, typename... Axes>
91struct GridToFitsHelper<0, GridCellManager, Axes...> {
93 * There are no more axis, so do nothing for the columns
95 static void addColumnDescriptions(const GridContainer<GridCellManager, Axes...>&, std::vector<Table::ColumnDescription>&) {}
98 * Insert into the row vector the cell value plus the axes values that brought us here
100 template <typename... Args>
101 static void unfold(const GridContainer<GridCellManager, Axes...>& grid, const std::shared_ptr<Table::ColumnInfo>& column_info,
102 std::vector<Table::Row>& rows, std::pair<size_t, Args>... axes) {
103 using GridType = GridContainer<GridCellManager, Axes...>;
105 std::vector<Table::Row::cell_type> row_content{GridAxisToTable<Args>::serialize(axes.second)...};
106 std::reverse(row_content.begin(), row_content.end());
108 GridCellToTable<typename GridType::cell_type> cell_traits;
109 cell_traits.addCells(grid.at(axes.first...), row_content);
111 rows.emplace_back(row_content, column_info);
116 * Transform a GridContainer into a Table, with an entry for each
117 * cell. The content will be unfolded, so the knot values will be repeated.
119template <typename GridCellManager, typename... AxesTypes>
120Table::Table gridContainerToTable(const GridContainer<GridCellManager, AxesTypes...>& grid) {
121 using GridType = GridContainer<GridCellManager, AxesTypes...>;
122 using Helper = GridToFitsHelper<std::tuple_size<typename GridType::AxesTuple>::value, GridCellManager, AxesTypes...>;
124 std::vector<Table::ColumnDescription> columns;
125 Helper::addColumnDescriptions(grid, columns);
127 GridCellToTable<typename GridType::cell_type> cell_trais;
128 cell_trais.addColumnDescriptions(*grid.begin(), columns);
130 auto column_info = std::make_shared<Table::ColumnInfo>(std::move(columns));
132 std::vector<Table::Row> rows;
133 rows.reserve(grid.size());
135 Helper::unfold(grid, column_info, rows);
137 return Table::Table{std::move(rows)};
140} // end of namespace GridContainer
141} // end of namespace Euclid