28#include <CCfits/CCfits>
30#include <boost/lexical_cast.hpp>
48 size_t width = table.getColumnInfo()->getDescription(column_index).size;
49 for (
const auto& row : table) {
50 width =
std::max(width, boost::lexical_cast<std::string>(row[column_index]).size());
57 for (
const auto& row : table) {
64 auto column_info = table.getColumnInfo();
66 for (
size_t column_index = 0; column_index < column_info->size(); ++column_index) {
67 auto type = column_info->getDescription(column_index).type;
68 if (type ==
typeid(
bool)) {
70 }
else if (type ==
typeid(int32_t) || type ==
typeid(int64_t)) {
71 size_t width =
maxWidth(table, column_index);
72 format_list.push_back(
"I" + boost::lexical_cast<std::string>(
std::max(
static_cast<size_t>(1), width)));
73 }
else if (type ==
typeid(
float) || type ==
typeid(
double)) {
75 format_list.push_back(
"E" + boost::lexical_cast<std::string>(
std::max(
static_cast<size_t>(1), width)));
77 size_t width =
maxWidth(table, column_index);
78 format_list.push_back(
"A" + boost::lexical_cast<std::string>(
std::max(
static_cast<size_t>(1), width)));
80 throw Elements::Exception() <<
"Unsupported column format for FITS ASCII table export: " << type.name();
88 if (table.size() == 0) {
91 size_t size = boost::get<std::vector<T>>(table[0][column_index]).size();
92 for (
const auto& row : table) {
93 if (boost::get<
std::vector<T>>(row[column_index]).size() != size) {
94 throw Elements::Exception() <<
"Binary FITS table variable length vector columns are not supported";
102 if (table.size() == 0) {
105 const auto& ndarray = boost::get<NdArray<T>>(table[0][column_index]);
106 size_t size = ndarray.size();
107 auto shape = ndarray.shape();
108 for (
const auto& row : table) {
110 throw Elements::Exception() <<
"Binary FITS table variable shape array columns are not supported";
121 char type_format =
'\0';
123 if (p->second ==
typeid(T)) {
124 type_format = p->first;
129 throw Elements::Exception() <<
"Unsupported column format for FITS binary table export: " <<
typeid(T).name();
136 size_t size = vectorSize<T>(table, column_index);
137 return boost::lexical_cast<std::string>(size) + GenericScalarFormat<T>(table, column_index);
142 size_t size = ndArraySize<T>(table, column_index);
143 return boost::lexical_cast<std::string>(size) + GenericScalarFormat<T>(table, column_index);
148 {
typeid(bool), GenericScalarFormat<bool>},
149 {
typeid(int32_t), GenericScalarFormat<int32_t>},
150 {
typeid(int64_t), GenericScalarFormat<int64_t>},
151 {
typeid(float), GenericScalarFormat<float>},
152 {
typeid(double), GenericScalarFormat<double>},
161 [](
const Table& table,
size_t column) {
162 size_t width =
maxWidth(table, column);
164 return boost::lexical_cast<std::string>(
std::max(
static_cast<size_t>(1), width)) +
"A";
174 auto column_info = table.getColumnInfo();
176 format_list.
reserve(column_info->size());
178 for (
size_t column_index = 0; column_index < column_info->size(); ++column_index) {
179 auto type = column_info->getDescription(column_index).type;
183 throw Elements::Exception() <<
"Unsupported column format for FITS binary table export: " << type.name();
186 format_list.
emplace_back(i->second(table, column_index));
194 for (
const auto& row : table) {
195 data.
push_back(boost::get<T>(row[column_index]));
203 for (
auto& row : table) {
204 const auto& vec = boost::get<std::vector<T>>(row[column_index]);
213 for (
auto& row : table) {
214 const auto& vec = boost::get<std::vector<T>>(row[column_index]);
223 for (
auto& row : table) {
224 const auto& ndarray = boost::get<NdArray<T>>(row[column_index]);
235 for (
auto& row : table) {
236 const auto& nd = boost::get<NdArray<T>>(row[column_index]);
247 const auto& vec = boost::get<std::vector<T>>(table[0][column_index]);
248 if (vec.size() > 1) {
249 table_hdu.column(column_index + 1).writeArrays(createVectorColumnData<T>(table, column_index), first_row);
251 table_hdu.column(column_index + 1).write(createSingleValueVectorColumnData<T>(table, column_index), first_row);
257 const auto& nd = boost::get<NdArray<T>>(table[0][column_index]);
259 table_hdu.column(column_index + 1).writeArrays(createNdArrayColumnData<T>(table, column_index), first_row);
261 table_hdu.column(column_index + 1).write(createSingleNdArrayVectorColumnData<T>(table, column_index), first_row);
266 if (table.size() == 0) {
270 auto& first_row = table[0];
271 auto& cell = first_row[column_index];
272 auto type = table.getColumnInfo()->getDescription(column_index).type;
276 shape = boost::get<NdArray<int32_t>>(cell).shape();
278 shape = boost::get<NdArray<int64_t>>(cell).shape();
280 shape = boost::get<NdArray<float>>(cell).shape();
282 shape = boost::get<NdArray<double>>(cell).shape();
288 for (
auto& axis : shape) {
299 for (j = shape.
size() - 1; j > 0; --j) {
300 stream << shape[j] <<
",";
303 stream << shape[j] <<
')';
308 if (table.size() == 0) {
311 auto type = table.getColumnInfo()->getDescription(column_index).type;
313 if (type ==
typeid(
bool)) {
314 table_hdu.column(column_index + 1).write(createColumnData<bool>(table, column_index), first_row);
315 }
else if (type ==
typeid(int32_t)) {
316 table_hdu.column(column_index + 1).write(createColumnData<int32_t>(table, column_index), first_row);
317 }
else if (type ==
typeid(int64_t)) {
318 table_hdu.column(column_index + 1).write(createColumnData<int64_t>(table, column_index), first_row);
319 }
else if (type ==
typeid(
float)) {
320 table_hdu.column(column_index + 1).write(createColumnData<float>(table, column_index), first_row);
321 }
else if (type ==
typeid(
double)) {
322 table_hdu.column(column_index + 1).write(createColumnData<double>(table, column_index), first_row);
324 table_hdu.column(column_index + 1).write(createColumnData<std::string>(table, column_index), first_row);
326 populateVectorColumn<int32_t>(table, column_index, table_hdu, first_row);
328 populateVectorColumn<int64_t>(table, column_index, table_hdu, first_row);
330 populateVectorColumn<float>(table, column_index, table_hdu, first_row);
332 populateVectorColumn<double>(table, column_index, table_hdu, first_row);
334 populateNdArrayColumn<int32_t>(table, column_index, table_hdu, first_row);
336 populateNdArrayColumn<int64_t>(table, column_index, table_hdu, first_row);
338 populateNdArrayColumn<float>(table, column_index, table_hdu, first_row);
340 populateNdArrayColumn<double>(table, column_index, table_hdu, first_row);
342 throw Elements::Exception() <<
"Cannot populate FITS column with data of type " << type.name();
const std::vector< size_t > & shape() const
NdArray(std::vector< size_t > shape_)
T emplace_back(T... args)
const std::map< std::type_index, std::function< std::string(const Table &, size_t)> > BinaryFormatter
std::vector< std::string > getAsciiFormatList(const Table &table)
Returns a vector with strings representing the FITS ASCII table formats for the given table.
std::vector< T > createSingleNdArrayVectorColumnData(const Euclid::Table::Table &table, size_t column_index)
std::vector< std::valarray< T > > createVectorColumnData(const Euclid::Table::Table &table, size_t column_index)
static std::string GenericVectorFormat(const Table &table, size_t column_index)
std::vector< T > createSingleValueVectorColumnData(const Euclid::Table::Table &table, size_t column_index)
void populateColumn(const Table &table, size_t column_index, CCfits::ExtHDU &table_hdu, long first_row)
static std::string GenericNdFormat(const Table &table, size_t column_index)
std::string getTDIM(const Table &table, size_t column_index)
std::string scientificFormat(T value)
size_t maxWidthScientific(const Table &table, size_t column_index)
size_t maxWidth(const Table &table, size_t column_index)
const std::vector< std::pair< char, std::type_index > > ScalarTypeMap
size_t ndArraySize(const Table &table, size_t column_index)
std::vector< std::string > getBinaryFormatList(const Table &table)
Returns a vector with strings representing the FITS binary table formats for the given table.
void populateVectorColumn(const Table &table, size_t column_index, CCfits::ExtHDU &table_hdu, long first_row)
std::vector< T > createColumnData(const Euclid::Table::Table &table, size_t column_index)
std::vector< std::valarray< T > > createNdArrayColumnData(const Euclid::Table::Table &table, size_t column_index)
size_t vectorSize(const Table &table, size_t column_index)
static std::string GenericScalarFormat(const Table &, size_t)
void populateNdArrayColumn(const Table &table, size_t column_index, CCfits::ExtHDU &table_hdu, long first_row)