Alexandria 2.25.0
SDC-CH common library for the Euclid project
FitsWriter.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012-2022 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
25#include "Table/FitsWriter.h"
27#include "FitsWriterHelper.h"
28#include <CCfits/CCfits>
29
30namespace Euclid {
31namespace Table {
32
33struct HeaderVisitor : public boost::static_visitor<void> {
34
35 HeaderVisitor(CCfits::HDU* hdu, const std::string& key, const std::string& comment)
36 : m_hdu(hdu), m_key(key), m_comment(comment) {}
37
38 template <typename T>
39 void operator()(T&& val) const {
40 m_hdu->addKey(m_key, val, m_comment);
41 }
42
43 CCfits::HDU* m_hdu;
45};
46
47FitsWriter::FitsWriter(const std::string& filename, bool override_flag)
48 : m_filename(filename), m_override_file(override_flag) {}
49
51
53 if (m_initialized) {
54 throw Elements::Exception() << "Changing the format after writing "
55 << "has started is not allowed";
56 }
57 m_format = format;
58 return *this;
59}
60
62 if (m_initialized) {
63 throw Elements::Exception() << "Changing the HDU name after writing "
64 << "has started is not allowed";
65 }
66 m_hdu_name = name;
67 return *this;
68}
69
70void FitsWriter::addComment(const std::string& message) {
71 if (m_initialized) {
72 throw Elements::Exception() << "Adding comments after writing "
73 << "has started is not allowed";
74 }
75 m_comments.push_back(message);
76}
77
78void FitsWriter::init(const Table& table) {
79
81 if (m_fits != nullptr) {
82 fits = m_fits;
83 } else {
84 // CCfits overrides the file if the name starts with !, otherwise it opens it
85 std::string filename = (m_override_file ? "!" : "") + m_filename;
86 fits = std::make_shared<CCfits::FITS>(filename, CCfits::RWmode::Write);
87 }
88
89 // Create the column info arrays to feed the CCfits based on the ColumnInfo object
90 auto& info = *table.getColumnInfo();
91 std::vector<std::string> column_name_list{};
92 std::vector<std::string> column_unit_list{};
93 for (size_t column_index = 0; column_index < info.size(); ++column_index) {
94 column_name_list.push_back(info.getDescription(column_index).name);
95 column_unit_list.push_back(info.getDescription(column_index).unit);
96 }
97 std::vector<std::string> column_format_list =
99
100 CCfits::HduType hdu_type = (m_format == Format::BINARY) ? CCfits::HduType::BinaryTbl : CCfits::HduType::AsciiTbl;
101
102 auto extension_map = fits->extension();
103 auto extension_i = extension_map.find(m_hdu_name);
104 bool new_hdu = (extension_i == extension_map.end() || extension_i->second->version() != 1);
105
106 CCfits::Table* table_hdu;
107 if (!new_hdu) {
108 table_hdu = dynamic_cast<CCfits::Table*>(extension_i->second);
109 assert(table_hdu != nullptr);
110 } else {
111 table_hdu = fits->addTable(m_hdu_name, 0, column_name_list, column_format_list, column_unit_list, hdu_type);
112
113 // Write the customized description header keywords, and also dimensions for multidimensional arrays
114 for (size_t column_index = 0; column_index < info.size(); ++column_index) {
115 auto& desc = info.getDescription(column_index).description;
116 table_hdu->addKey("TDESC" + std::to_string(column_index + 1), desc, "");
117
118 auto shape_str = getTDIM(table, column_index);
119 if (!shape_str.empty()) {
120 table_hdu->addKey(CCfits::Column::TDIM() + std::to_string(column_index + 1), shape_str, "");
121 }
122 }
123
124 for (auto& h : m_headers) {
125 HeaderVisitor visitor{table_hdu, h.m_key, h.m_comment};
126 boost::apply_visitor(visitor, h.m_value);
127 }
128
129 for (auto& c : m_comments) {
130 table_hdu->writeComment(c);
131 }
132 }
133
134 m_hdu_index = table_hdu->index();
135 m_current_line = table_hdu->rows() + 1;
136 m_initialized = true;
137}
138
139void FitsWriter::append(const Table& table) {
141 if (m_fits != nullptr) {
142 fits = m_fits;
143 } else {
144 fits = std::make_shared<CCfits::FITS>(m_filename, CCfits::RWmode::Write);
145 }
146 auto& table_hdu = fits->extension(m_hdu_index);
147
148 auto& info = *table.getColumnInfo();
149 for (size_t column_index = 0; column_index < info.size(); ++column_index) {
150 populateColumn(table, column_index, table_hdu, m_current_line);
151 }
152 m_current_line += table.size();
153}
154
155} // namespace Table
156} // namespace Euclid
TableWriter implementation for writing tables in FITS format.
Definition: FitsWriter.h:76
FitsWriter & setFormat(Format format)
Set the FITS table format.
Definition: FitsWriter.cpp:52
void addComment(const std::string &message) override
Adds a comment to the stream.
Definition: FitsWriter.cpp:70
Format
The format of the HDUs a FitsWriter creates.
Definition: FitsWriter.h:80
@ BINARY
FITS binary table HDU format.
std::vector< Header > m_headers
Definition: FitsWriter.h:220
void append(const Table &table) override
Definition: FitsWriter.cpp:139
FitsWriter(const std::string &filename, bool override_flag=false)
Creates a FitsWriter that writes to a specific file.
Definition: FitsWriter.cpp:47
std::vector< std::string > m_comments
Definition: FitsWriter.h:219
std::shared_ptr< CCfits::FITS > m_fits
Definition: FitsWriter.h:214
void init(const Table &table) override
Definition: FitsWriter.cpp:78
FitsWriter & setHduName(const std::string &name)
Set the HDU name where the table is written.
Definition: FitsWriter.cpp:61
Represents a table.
Definition: Table.h:49
std::vector< std::string > getAsciiFormatList(const Table &table)
Returns a vector with strings representing the FITS ASCII table formats for the given table.
void populateColumn(const Table &table, size_t column_index, CCfits::ExtHDU &table_hdu, long first_row)
std::string getTDIM(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.
T push_back(T... args)
const std::string & m_comment
Definition: FitsWriter.cpp:44
HeaderVisitor(CCfits::HDU *hdu, const std::string &key, const std::string &comment)
Definition: FitsWriter.cpp:35
void operator()(T &&val) const
Definition: FitsWriter.cpp:39
const std::string & m_key
Definition: FitsWriter.cpp:44
T to_string(T... args)