Alexandria 2.32.0
SDC-CH common library for the Euclid project
Loading...
Searching...
No Matches
FitsSerialize.icpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012-2021 Euclid Science Ground Segment
3 *
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)
7 * any later version.
8 *
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
12 * details.
13 *
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
17 */
18
19/*
20 * @file FitsSerialize.icpp
21 * @author nikoapos
22 */
23
26#include "Table/FitsWriter.h"
27#include "Table/Table.h"
29#include <CCfits/CCfits>
30#include <boost/filesystem.hpp>
31#include <cstdint>
32#include <type_traits>
33#include <valarray>
34#include <cstdint>
35
36namespace Euclid {
37namespace GridContainer {
38
39template <typename T>
41 static_assert(!std::is_same<T, T>::value, "FITS arrays of type T are not supported");
42};
43
44template <>
45struct FitsBpixTraits<std::int8_t> {
46 static constexpr int BPIX = BYTE_IMG;
47};
48
49template <>
50struct FitsBpixTraits<std::int16_t> {
51 static constexpr int BPIX = SHORT_IMG;
52};
53
54template <>
55struct FitsBpixTraits<std::int32_t> {
56 static constexpr int BPIX = LONG_IMG;
57};
58
59template <>
61 static constexpr int BPIX = LONGLONG_IMG;
62};
63
64template <>
65struct FitsBpixTraits<float> {
66 static constexpr int BPIX = FLOAT_IMG;
67};
68
69template <>
70struct FitsBpixTraits<double> {
71 static constexpr int BPIX = DOUBLE_IMG;
72};
73
74template <typename T>
76 using FitsType = T;
77 static FitsType axisToFits(const T& value) {
78 return value;
79 }
80 static T FitsToAxis(const FitsType& value) {
81 return value;
82 }
83};
84
85template <>
86struct GridAxisValueFitsHelper<XYDataset::QualifiedName> {
89 return value.qualifiedName();
90 }
92 return value;
93 }
94};
95
96template <typename... AxesTypes>
98
99 template <int I>
100 static void addGridAxesToFitsFile(const boost::filesystem::path& filename, const std::string& array_hdu_name,
101 const std::tuple<GridAxis<AxesTypes>...>& axes_tuple,
102 const TemplateLoopCounter<I>&) {
103 addGridAxesToFitsFile(filename, array_hdu_name, axes_tuple, TemplateLoopCounter<I - 1>{});
104
105 auto& axis = std::get<I - 1>(axes_tuple);
106 using AxisType = typename std::remove_reference<decltype(axis)>::type::data_type;
107 using FitsType = typename GridAxisValueFitsHelper<AxisType>::FitsType;
108
110 Table::ColumnInfo::info_type{"Value", typeid(FitsType)}};
112
113 std::vector<Table::Row> row_list{};
114 for (size_t i = 0; i < axis.size(); ++i) {
115 auto fits_value = GridAxisValueFitsHelper<AxisType>::axisToFits(axis[i]);
116 row_list.push_back(Table::Row{{(int)i, fits_value}, column_info});
117 }
118 Table::Table table{row_list};
119
120 Table::FitsWriter{filename.string(), false}
122 .setHduName(axis.name() + "_" + array_hdu_name)
123 .addData(table);
124 }
125
126 static void addGridAxesToFitsFile(const boost::filesystem::path&, const std::string&,
128};
129
130template <typename GridCellManager, typename... AxesTypes>
131void gridFitsExport(const boost::filesystem::path& filename, const std::string& hdu_name,
133 auto& axes = grid.getAxesTuple();
134
135 // Create the first HDU with the array. We do that in a scope so the file is
136 // created and the data are flushed into it before we continue.
137 {
138 CCfits::FITS fits(filename.string(), CCfits::Write);
139
140 auto ext_ax_size_t =
142 std::vector<long> ext_ax{ext_ax_size_t.begin(), ext_ax_size_t.end()};
143
144 using cell_type = typename GridCellManagerTraits<GridCellManager>::data_type;
146 fits.addImage(hdu_name, bpix, ext_ax);
147 std::valarray<cell_type> data(grid.size());
148 int i = 0;
149 for (auto value : grid) {
150 data[i] = value;
151 ++i;
152 }
153 fits.currentExtension().write(1, grid.size(), data);
154 }
155
157 TemplateLoopCounter<sizeof...(AxesTypes)>{});
158}
159
160template <typename GridType>
162
163 template <int I>
164 using AxisType = typename std::remove_reference<decltype(std::declval<GridType>().template getAxis<I>())>::type;
165
166 template <int I, typename = void>
171
172 template <int I>
173 struct AxesTupleType<I, typename std::enable_if<I == -1>::type> {
175 };
176
177 template <int I>
178 using GridAxisType = typename std::remove_reference<decltype(std::declval<GridType>().template getAxis<I>())>::type;
179
180 template <int I>
181 static GridAxisType<I> readAxis(const std::string& grid_name, CCfits::ExtHDU& hdu) {
182 using KnotType = typename GridAxisType<I>::data_type;
183 using FitsType = typename GridAxisValueFitsHelper<KnotType>::FitsType;
184
185 auto axis_name = hdu.name().substr(0, hdu.name().size() - grid_name.size() - 1);
187 try {
188 auto& column = hdu.column("Value");
189 column.read(data, 1, column.rows());
190 } catch (CCfits::FitsException e) {
191 throw Elements::Exception() << e.message();
192 }
193 std::vector<KnotType> knots{};
194 for (std::size_t i = 0; i < data.size(); ++i) {
196 }
197 return {std::move(axis_name), std::move(knots)};
198 }
199
200 template <int I>
201 static typename AxesTupleType<I>::type readAxesTuple(CCfits::FITS& fits, const std::string& grid_name, int hdu_index,
202 const TemplateLoopCounter<I>&) {
203 auto axis = readAxis<I>(grid_name, fits.extension(hdu_index));
204 auto previous = readAxesTuple(fits, grid_name, hdu_index - 1, TemplateLoopCounter<I - 1>{});
205 return std::tuple_cat(std::move(previous), std::tuple<decltype(axis)>{std::move(axis)});
206 }
207
208 static std::tuple<> readAxesTuple(CCfits::FITS&, const std::string&, int, const TemplateLoopCounter<-1>&) {
209 return {};
210 }
211
212public:
213 static typename AxesTupleType<GridType::axisNumber() - 1>::type readAllAxes(CCfits::FITS& fits, int hdu_index) {
214 auto name = fits.extension(hdu_index).name();
215 return readAxesTuple(fits, name, hdu_index + GridType::axisNumber(),
216 TemplateLoopCounter<GridType::axisNumber() - 1>{});
217 }
218};
219
220template <typename GridType>
221GridType gridFitsImport(const boost::filesystem::path& filename, int hdu_index) {
222 CCfits::FITS fits(filename.string(), CCfits::Read);
223
224 auto axes = GridAxisFitsReader<GridType>::readAllAxes(fits, hdu_index);
225
226 GridType grid{std::move(axes)};
227
229 fits.extension(hdu_index).read(data);
230
231 int i = 0;
232 for (auto iter = grid.begin(); iter != grid.end(); ++iter, ++i) {
233 *iter = data[i];
234 }
235
236 return grid;
237}
238
239} // end of namespace GridContainer
240} // end of namespace Euclid
static AxesTupleType< I >::type readAxesTuple(CCfits::FITS &fits, const std::string &grid_name, int hdu_index, const TemplateLoopCounter< I > &)
static std::tuple readAxesTuple(CCfits::FITS &, const std::string &, int, const TemplateLoopCounter<-1 > &)
typename std::remove_reference< decltype(std::declval< GridType >().template getAxis< I >())>::type AxisType
static GridAxisType< I > readAxis(const std::string &grid_name, CCfits::ExtHDU &hdu)
typename std::remove_reference< decltype(std::declval< GridType >().template getAxis< I >())>::type GridAxisType
static AxesTupleType< GridType::axisNumber() -1 >::type readAllAxes(CCfits::FITS &fits, int hdu_index)
Provides information related with an axis of a GridContainer.
Definition GridAxis.h:49
static std::vector< size_t > createAxesSizesVector(const std::tuple< GridAxis< Axes >... > &axes, const TemplateLoopCounter< I > &)
Creates a vector which contains the sizes of the given axes.
Representation of a multi-dimensional grid which contains axis information.
Provides information about the columns of a Table.
Definition ColumnInfo.h:52
ColumnDescription info_type
Definition ColumnInfo.h:55
TableWriter implementation for writing tables in FITS format.
Definition FitsWriter.h:76
FitsWriter & setFormat(Format format)
Set the FITS table format.
@ BINARY
FITS binary table HDU format.
Definition FitsWriter.h:84
FitsWriter & setHduName(const std::string &name)
Set the HDU name where the table is written.
Represents one row of a Table.
Definition Row.h:57
void addData(const Table &table)
Appends the contents of the given table to the output.
Represents a table.
Definition Table.h:49
Represents a name qualified with a set of groups.
const std::string & qualifiedName() const
Returns the qualified name as a string.
T declval(T... args)
T emplace_back(T... args)
T move(T... args)
GridType gridFitsImport(const boost::filesystem::path &filename, int hdu_index)
Imports a Grid from a FITS file.
void gridFitsExport(const boost::filesystem::path &filename, const std::string &hdu_name, const GridContainer< GridCellManager, AxesTypes... > &grid)
Exports a Grid as a FITS file.
STL namespace.
T push_back(T... args)
T size(T... args)
static void addGridAxesToFitsFile(const boost::filesystem::path &filename, const std::string &array_hdu_name, const std::tuple< GridAxis< AxesTypes >... > &axes_tuple, const TemplateLoopCounter< I > &)
static void addGridAxesToFitsFile(const boost::filesystem::path &, const std::string &, const std::tuple< GridAxis< AxesTypes >... > &, const TemplateLoopCounter< 0 > &)
decltype(std::tuple_cat(std::declval< previous >(), std::declval< std::tuple< AxisType< I > > >())) type
static XYDataset::QualifiedName FitsToAxis(const FitsType &value)
static FitsType axisToFits(const XYDataset::QualifiedName &value)
static T FitsToAxis(const FitsType &value)
static FitsType axisToFits(const T &value)
GridCellManager::data_type data_type
The type of the data kept by the GridCellManager.
T tuple_cat(T... args)