29 #include <CCfits/CCfits>
31 #include <boost/lexical_cast.hpp>
35 using Euclid::Table::operator<<;
40 using NdArray::NdArray;
50 size_t width = table.getColumnInfo()->getDescription(column_index).size;
51 for (
const auto& row : table) {
59 for (
const auto& row : table) {
66 auto column_info = table.getColumnInfo();
68 for (
size_t column_index = 0; column_index < column_info->size(); ++column_index) {
69 auto type = column_info->getDescription(column_index).type;
70 if (type ==
typeid(
bool)) {
72 }
else if (type ==
typeid(int32_t) || type ==
typeid(int64_t)) {
73 size_t width =
maxWidth(table, column_index);
74 format_list.emplace_back(
"I" + boost::lexical_cast<std::string>(
std::max(static_cast<size_t>(1), width)));
75 }
else if (type ==
typeid(
float) || type ==
typeid(
double)) {
77 format_list.emplace_back(
"E" + boost::lexical_cast<std::string>(
std::max(static_cast<size_t>(1), width)));
79 size_t width =
maxWidth(table, column_index);
80 format_list.emplace_back(
"A" + boost::lexical_cast<std::string>(
std::max(static_cast<size_t>(1), width)));
82 throw Elements::Exception() <<
"Unsupported column format for FITS ASCII table export: " << type.name();
90 if (table.size() == 0) {
93 size_t size = boost::get<std::vector<T>>(table[0][column_index]).size();
94 for (
const auto& row : table) {
95 if (boost::get<
std::vector<T>>(row[column_index]).size() != size) {
96 throw Elements::Exception() <<
"Binary FITS table variable length vector columns are not supported";
102 template <
typename T>
104 if (table.size() == 0) {
107 const auto& ndarray = boost::get<NdArray<T>>(table[0][column_index]);
108 size_t size = ndarray.size();
109 auto shape = ndarray.shape();
110 for (
const auto& row : table) {
111 if (boost::get<NdArray<T>>(row[column_index]).shape() != shape) {
112 throw Elements::Exception() <<
"Binary FITS table variable shape array columns are not supported";
121 template <
typename T>
126 throw Elements::Exception() <<
"Unsupported column format for FITS binary table export: " <<
typeid(T).name();
131 template <
typename T>
133 size_t size = vectorSize<T>(table, column_index);
134 return boost::lexical_cast<
std::string>(size) + GenericScalarFormat<T>(table, column_index);
137 template <
typename T>
139 size_t size = ndArraySize<T>(table, column_index);
140 return boost::lexical_cast<
std::string>(size) + GenericScalarFormat<T>(table, column_index);
145 {
typeid(bool), GenericScalarFormat<bool>},
146 {
typeid(int32_t), GenericScalarFormat<int32_t>},
147 {
typeid(int64_t), GenericScalarFormat<int64_t>},
148 {
typeid(float), GenericScalarFormat<float>},
149 {
typeid(double), GenericScalarFormat<double>},
158 [](
const Table& table,
size_t column) {
159 size_t width =
maxWidth(table, column);
164 {
typeid(NdArray<int32_t>), GenericNdFormat<int32_t>},
165 {
typeid(NdArray<int64_t>), GenericNdFormat<int64_t>},
166 {
typeid(NdArray<float>), GenericNdFormat<float>},
167 {
typeid(NdArray<double>), GenericNdFormat<double>},
171 auto column_info = table.getColumnInfo();
173 format_list.
reserve(column_info->size());
175 for (
size_t column_index = 0; column_index < column_info->size(); ++column_index) {
176 auto type = column_info->getDescription(column_index).type;
180 throw Elements::Exception() <<
"Unsupported column format for FITS binary table export: " << type.name();
183 format_list.
emplace_back(i->second(table, column_index));
188 template <
typename T>
192 [column_index](
const Row& row) {
return boost::get<T>(row[column_index]); });
196 template <
typename T>
199 for (
auto& row : table) {
200 const auto& vec = boost::get<std::vector<T>>(row[column_index]);
206 template <
typename T>
209 for (
auto& row : table) {
210 const auto& vec = boost::get<std::vector<T>>(row[column_index]);
216 template <
typename T>
219 for (
auto& row : table) {
220 const auto& ndarray = boost::get<NdArray<T>>(row[column_index]);
228 template <
typename T>
231 for (
auto& row : table) {
232 const auto& nd = boost::get<NdArray<T>>(row[column_index]);
241 template <
typename T>
243 const auto& vec = boost::get<std::vector<T>>(table[0][column_index]);
244 if (vec.size() > 1) {
245 table_hdu.column(column_index + 1).writeArrays(createVectorColumnData<T>(table, column_index), first_row);
247 table_hdu.column(column_index + 1).write(createSingleValueVectorColumnData<T>(table, column_index), first_row);
251 template <
typename T>
253 const auto& nd = boost::get<NdArray<T>>(table[0][column_index]);
255 table_hdu.column(column_index + 1).writeArrays(createNdArrayColumnData<T>(table, column_index), first_row);
257 table_hdu.column(column_index + 1).write(createSingleNdArrayVectorColumnData<T>(table, column_index), first_row);
262 if (table.size() == 0) {
266 auto& first_row = table[0];
267 auto& cell = first_row[column_index];
268 auto type = table.getColumnInfo()->getDescription(column_index).type;
271 if (type ==
typeid(NdArray<int32_t>)) {
272 shape = boost::get<NdArray<int32_t>>(cell).shape();
273 }
else if (type ==
typeid(NdArray<int64_t>)) {
274 shape = boost::get<NdArray<int64_t>>(cell).shape();
275 }
else if (type ==
typeid(NdArray<float>)) {
276 shape = boost::get<NdArray<float>>(cell).shape();
277 }
else if (type ==
typeid(NdArray<double>)) {
278 shape = boost::get<NdArray<double>>(cell).shape();
292 for (j = shape.
size() - 1; j > 0; --j) {
293 stream << shape[j] <<
",";
296 stream << shape[j] <<
')';
300 void populateColumn(
const Table& table,
int column_index,
const CCfits::ExtHDU& table_hdu,
long first_row) {
301 if (table.size() == 0) {
304 auto type = table.getColumnInfo()->getDescription(column_index).type;
306 if (type ==
typeid(
bool)) {
307 table_hdu.column(column_index + 1).write(createColumnData<bool>(table, column_index), first_row);
308 }
else if (type ==
typeid(int32_t)) {
309 table_hdu.column(column_index + 1).write(createColumnData<int32_t>(table, column_index), first_row);
310 }
else if (type ==
typeid(int64_t)) {
311 table_hdu.column(column_index + 1).write(createColumnData<int64_t>(table, column_index), first_row);
312 }
else if (type ==
typeid(
float)) {
313 table_hdu.column(column_index + 1).write(createColumnData<float>(table, column_index), first_row);
314 }
else if (type ==
typeid(
double)) {
315 table_hdu.column(column_index + 1).write(createColumnData<double>(table, column_index), first_row);
317 table_hdu.column(column_index + 1).write(createColumnData<std::string>(table, column_index), first_row);
319 populateVectorColumn<int32_t>(table, column_index, table_hdu, first_row);
321 populateVectorColumn<int64_t>(table, column_index, table_hdu, first_row);
323 populateVectorColumn<float>(table, column_index, table_hdu, first_row);
325 populateVectorColumn<double>(table, column_index, table_hdu, first_row);
326 }
else if (type ==
typeid(NdArray<int32_t>)) {
327 populateNdArrayColumn<int32_t>(table, column_index, table_hdu, first_row);
328 }
else if (type ==
typeid(NdArray<int64_t>)) {
329 populateNdArrayColumn<int64_t>(table, column_index, table_hdu, first_row);
330 }
else if (type ==
typeid(NdArray<float>)) {
331 populateNdArrayColumn<float>(table, column_index, table_hdu, first_row);
332 }
else if (type ==
typeid(NdArray<double>)) {
333 populateNdArrayColumn<double>(table, column_index, table_hdu, first_row);
335 throw Elements::Exception() <<
"Cannot populate FITS column with data of type " << type.name();
const std::vector< std::pair< char, std::type_index > > ScalarTypeMap
std::string getTDIM(const Table &table, int column_index)
std::vector< T > createSingleNdArrayVectorColumnData(const Euclid::Table::Table &table, size_t column_index)
std::string scientificFormat(const T &value)
std::vector< std::valarray< T > > createNdArrayColumnData(const Euclid::Table::Table &table, size_t column_index)
void populateVectorColumn(const Table &table, int column_index, const CCfits::ExtHDU &table_hdu, long first_row)
std::vector< T > createSingleValueVectorColumnData(const Euclid::Table::Table &table, size_t column_index)
size_t maxWidthScientific(const Table &table, size_t column_index)
static std::string GenericNdFormat(const Table &table, size_t column_index)
Represents one row of a Table.
std::vector< std::valarray< T > > createVectorColumnData(const Euclid::Table::Table &table, size_t column_index)
void populateNdArrayColumn(const Table &table, int column_index, const CCfits::ExtHDU &table_hdu, long first_row)
size_t ndArraySize(const Table &table, size_t column_index)
size_t vectorSize(const Table &table, size_t column_index)
std::vector< T > createColumnData(const Table &table, size_t column_index)
std::vector< std::string > getAsciiFormatList(const Table &table)
Returns a vector with strings representing the FITS ASCII table formats for the given table...
const std::map< std::type_index, std::function< std::string(const Table &, size_t)> > BinaryFormatter
static std::string GenericScalarFormat(const Table &, size_t)
void populateColumn(const Table &table, int column_index, const CCfits::ExtHDU &table_hdu, long first_row)
std::vector< std::string > getBinaryFormatList(const Table &table)
Returns a vector with strings representing the FITS binary table formats for the given table...
size_t maxWidth(const Table &table, size_t column_index)
static std::string GenericVectorFormat(const Table &table, size_t column_index)