Alexandria 2.31.0
SDC-CH common library for the Euclid project
Loading...
Searching...
No Matches
FitsReader.cpp
Go to the documentation of this file.
1
25#include <set>
26
30#include "Table/FitsReader.h"
31
33#include "FitsReaderHelper.h"
34#include "ReaderHelper.h"
35
36namespace Euclid {
37namespace Table {
38
39static CCfits::HDU& _readKeys(CCfits::HDU& hdu) {
40 hdu.readAllKeys();
41 return hdu;
42}
43
44FitsReader::FitsReader(const CCfits::HDU& hdu) : m_hdu(hdu) {}
45
46FitsReader::FitsReader(const std::string& filename, int hduIndex)
47 : m_fits(Euclid::make_unique<CCfits::FITS>(filename)), m_hdu(_readKeys(m_fits->extension(hduIndex))) {}
48
49FitsReader::FitsReader(const std::string& filename, const std::string& hduName)
50 : m_fits(Euclid::make_unique<CCfits::FITS>(filename)), m_hdu(_readKeys(m_fits->extension(hduName))) {}
51
54 throw Elements::Exception() << "Fixing the column names after reading "
55 << "has started is not allowed";
56 }
57
58 m_column_names = std::move(column_names);
59
61 regex::regex whitespace{".*\\s.*"}; // Checks if input contains any whitespace characters
62 for (const auto& name : m_column_names) {
63 if (name.empty()) {
64 throw Elements::Exception() << "Empty string column names are not allowed";
65 }
66 if (regex_match(name, whitespace)) {
67 throw Elements::Exception() << "Column name '" << name << "' contains "
68 << "whitespace characters";
69 }
70 if (!set.insert(name).second) { // Check for duplicate names
71 throw Elements::Exception() << "Duplicate column name " << name;
72 }
73 }
74
75 return *this;
76}
77
79 if (m_column_info != nullptr) {
80 return;
81 }
82 m_reading_started = true;
83
84 try {
85 ELEMENTS_UNUSED auto& temp = dynamic_cast<const CCfits::Table&>(m_hdu.get());
86 } catch (std::bad_cast&) {
87 throw Elements::Exception() << "Given HDU is not a table";
88 }
89 const CCfits::Table& table_hdu = dynamic_cast<const CCfits::Table&>(m_hdu.get());
90
91 m_total_rows = table_hdu.rows();
92
94 if (m_column_names.empty()) {
95 names = autoDetectColumnNames(table_hdu);
96 } else if (m_column_names.size() != static_cast<size_t>(table_hdu.numCols())) {
97 throw Elements::Exception() << "Columns number in HDU (" << table_hdu.numCols()
98 << ") does not match the column names number (" << m_column_names.size() << ")";
99 } else {
100 names = m_column_names;
101 }
104}
105
108 return *m_column_info;
109}
110
112 const CCfits::Table& table_hdu = dynamic_cast<const CCfits::Table&>(m_hdu.get());
113 return table_hdu.comment();
114}
115
118
119 // Compute how many rows we are going to read
121 return Table(m_column_info);
122 }
123 if (rows == -1) {
124 rows = m_total_rows - m_current_row + 1;
125 }
126 rows = std::min(rows, m_total_rows - m_current_row + 1);
127
128 const CCfits::Table& table_hdu = dynamic_cast<const CCfits::Table&>(m_hdu.get());
129
130 // CCfits reads per column, so we first read all the columns and then we
131 // create all the rows
133 data.reserve(table_hdu.numCols());
134 for (int i = 1; i <= table_hdu.numCols(); ++i) {
135 // The i-1 is because CCfits starts from 1 and ColumnInfo from 0
136 // We use a clone of the column because CCfits will cache in memory the read data, so multiple calls
137 // to readImpl will steadily increase the memory consumption, which will only be released when
138 // the FitsReader is destroyed (~FitsReader() => ~Table() => ~Column())
139 // For scalars this is not a big deal, but when the column has an array (i.e. a bunch of PDZs), the
140 // pile up can be significant after a while.
141 std::unique_ptr<CCfits::Column> column(table_hdu.column(i).clone());
142 data.emplace_back(
143 translateColumn(*column, m_column_info->getDescription(i - 1).type, m_current_row, m_current_row + rows - 1));
144 }
145
146 m_current_row += rows;
147
148 std::vector<Row> row_list;
149 row_list.reserve(rows);
150 for (int i = 0; i < rows; ++i) {
152 cells.reserve(data.size());
153 for (auto& column_data : data) {
154 cells.emplace_back(std::move(column_data[i]));
155 }
156 row_list.emplace_back(cells, m_column_info);
157 }
158
159 return Table(std::move(row_list));
160}
161
162void FitsReader::skip(long rows) {
164 m_current_row += rows;
165}
166
171
176
177} // namespace Table
178} // namespace Euclid
Provides information about the columns of a Table.
Definition ColumnInfo.h:52
TableReader implementation for reading FITS tables.
Definition FitsReader.h:75
void skip(long rows) override
Implements the TableReader::skip() contract.
std::vector< std::string > m_column_names
Definition FitsReader.h:166
FitsReader(const CCfits::HDU &hdu)
Creates a FitsReader that reads from the given HDU.
bool hasMoreRows() override
Implements the TableReader::hasMoreRows() contract.
const ColumnInfo & getInfo() override
Returns the column information of the table.
Table readImpl(long rows) override
Implements the TableReader::readImpl() contract.
std::reference_wrapper< const CCfits::HDU > m_hdu
Definition FitsReader.h:162
std::shared_ptr< ColumnInfo > m_column_info
Definition FitsReader.h:167
std::size_t rowsLeft() override
Implements the TableReader::rowsLeft() contract.
std::string getComment() override
FitsReader & fixColumnNames(std::vector< std::string > column_names)
Overrides the column names of the table.
Represents a table.
Definition Table.h:49
T emplace_back(T... args)
T empty(T... args)
#define ELEMENTS_UNUSED
T min(T... args)
T move(T... args)
std::map< std::string, ColumnDescription > autoDetectColumnDescriptions(std::istream &in, const std::string &comment)
Reads the column descriptions of the given stream.
static CCfits::HDU & _readKeys(CCfits::HDU &hdu)
std::vector< std::string > autoDetectColumnUnits(const CCfits::Table &table_hdu)
Reads the column units based on the TUNITn keyword.
std::vector< std::string > autoDetectColumnNames(std::istream &in, const std::string &comment, size_t columns_number)
Reads the column names of the given stream.
std::vector< Row::cell_type > translateColumn(CCfits::Column &column, std::type_index type)
Returns a vector representing the given FITS table column data, converted to the requested type.
std::vector< std::pair< std::type_index, std::size_t > > autoDetectColumnTypes(const CCfits::Table &table_hdu)
Reads the column types of the given table HDU.
std::shared_ptr< ColumnInfo > createColumnInfo(const std::vector< std::string > &names, const std::vector< std::pair< std::type_index, std::size_t > > &types, const std::vector< std::string > &units, const std::vector< std::string > &descriptions)
Creates a ColumnInfo object from the given names and types.
std::unique_ptr< T > make_unique(Args &&... args)
Constructs an object of type T and wraps it in a std::unique_ptr using args as the parameter list for...
T reserve(T... args)
T size(T... args)