13#include <fmt/format.h>
14#include <fmt/ostream.h>
21std::vector<LiteralKeyword> ReadCurrentHduKeywords(fitsfile* ptr) {
26 if (fits_get_hdrspace(ptr, &count, &more_space, &status) != 0) {
27 throw CfitsioError(status,
"Failed to get number of keywords in HDU");
29 std::vector<LiteralKeyword> keywords;
30 keywords.reserve(count);
31 for (
int keynum = 1; keynum <= count; ++keynum) {
33 char record[FLEN_CARD];
34 if (fits_read_record(ptr, keynum, &record[0], &status) != 0) {
35 throw CfitsioError(status, fmt::format(
"Failed to read record number {}", keynum));
38 keywords.emplace_back(std::string_view(record));
42 fmt::format(
"Failed to read recordd number {} as literal keyword", keynum)));
48std::string FitsErrorMessage(
int status) {
49 char msg[FLEN_STATUS];
50 fits_get_errstatus(status, &msg[0]);
51 return std::string(msg);
78 : m_memory(std::make_unique<FitsMemory>(initial_buffer_size))
80 fitsfile* ptr =
nullptr;
82 fits_create_memfile(&ptr, &m_memory->buffer, &m_memory->size, 0u, realloc, &status);
87MemoryFitsFile::FitsMemory::FitsMemory(std::size_t initial_size) {
89 buffer = malloc(size);
90 memset(buffer, 0u, size);
93MemoryFitsFile::FitsMemory::~FitsMemory() noexcept {
95 fits_free_memory(buffer, &status);
99 : std::runtime_error(fmt::format(
"{}: {}", message, FitsErrorMessage(status)).c_str())
104 : std::runtime_error(fmt::format(
"{}: {}", message, FitsErrorMessage(status)).c_str())
112 (void)fits_movabs_hdu(ptr, hdu_num, &type, &status);
115 fmt::format(
"HDU with number {} could not be selected", hdu_num));
120 if (ptr ==
nullptr) {
124 fits_close_file(ptr, &status);
134 (void)fits_get_num_hdus(ptr, &num_hdus, &status);
136 throw CfitsioError(HEADER_NOT_EMPTY,
"Cannot safely initialize an non-empty FITS file");
138 (void)fits_create_hdu(ptr, &status);
157 (void)fits_get_num_hdus(ptr, &num_hdus, &status);
159 throw CfitsioError(HEADER_NOT_EMPTY,
"Cannot safely initialize an non-empty FITS file");
161 (void)fits_create_hdu(ptr, &status);
162 (void)fits_write_key(
163 ptr, TLOGICAL,
"SIMPLE", &simple,
"file does conform to FITS standard", &status);
164 (void)fits_write_key(ptr, TBYTE,
"BITPIX", &bitpix,
"number of bits per data pixel", &status);
165 (void)fits_write_key(
166 ptr, TBYTE,
"NAXIS", &naxis,
"file provides primary HDU keywords only", &status);
167 (void)fits_write_key(
168 ptr, TLOGICAL,
"EXTEND", &extend,
"FITS Extension may be present", &status);
171 fits_get_errstatus(status, &err_text[0]);
173 throw CfitsioError(status, fmt::format(
"failed to initialize primary HDU: {}", err_text));
178 fitsfile* ptr =
nullptr;
180 fits_create_diskfile(&ptr,
const_cast<char*
>(filename), &status);
181 if (status != 0 || ptr ==
nullptr) {
182 throw CfitsioError(status, fmt::format(
"failed to create FITS file '{}'", filename));
188 fitsfile* ptr =
nullptr;
190 fits_open_diskfile(&ptr,
191 const_cast<char*
>(filename),
194 if (status != 0 || ptr ==
nullptr) {
195 throw CfitsioError(status, fmt::format(
"failed to open FITS file '{}'", filename));
203 return ReadCurrentHduKeywords(ptr);
206std::vector<LiteralKeyword>
211 std::string null_terminated_name(name);
212 (void)fits_movnam_hdu(ptr,
213 static_cast<int>(type),
214 const_cast<char*
>(null_terminated_name.c_str()),
220 fmt::format(
"HDU with type {}, name '{}' and version {} could not be selected",
223 version.value_or(0)));
225 return ReadCurrentHduKeywords(ptr);
233 int num_current_keys = 0;
238 fits_get_hdrspace(ptr, &num_current_keys,
nullptr, &status);
239 for (
int keynum = num_current_keys; keynum > 0; --keynum) {
240 fits_delete_record(ptr, keynum, &status);
243 fmt::format(
"failed to delete keyword record index {}", keynum));
248void MakeHduSpace(fitsfile* ptr,
int hdu_num, std::size_t additional_keys) {
253 int num_current_keys = 0;
254 int more_keys = additional_keys;
260 fits_get_hdrspace(ptr, &num_current_keys, &more_keys, &status);
262 throw CfitsioError(status, fmt::format(
"Failed to update header space"));
268 std::vector<LiteralKeyword>
const& keywords,
269 std::optional<ssize_t>* remaining_size) {
272 std::string null_terminated_record;
273 null_terminated_record.reserve(FLEN_CARD);
275 int num_current_keys = 0;
276 int more_keys = keywords.size();
281 fits_get_hdrspace(ptr, &num_current_keys, &more_keys, &status);
283 throw CfitsioError(status, fmt::format(
"Failed to get header space"));
286 if (remaining_size !=
nullptr && more_keys != -1) {
287 *remaining_size = more_keys - keywords.size();
290 for (
auto const& kw : keywords) {
291 null_terminated_record.assign(kw.GetRecord());
293 fits_write_record(ptr, null_terminated_record.c_str(), &status);
297 fmt::format(
"Failed to write keyword record: \"{}\"", null_terminated_record));
306 fits_write_chksum(ptr, &status);
309 status, fmt::format(
"Failed to write checksum keywords to HDU number {}", hdu_num));
Contains functions and data structures related to cfitsio.
Represents errors from cfitsio.
int GetStatus() const noexcept
CfitsioError(int status, char const *message)
MemoryFitsFile() noexcept
Creates empty file.
void SelectHduNum(fitsfile *ptr, int hdu_num)
Select current HDU number.
UniqueFitsFile Open(char const *filename, OpenMode mode)
Open file.
std::unique_ptr< fitsfile, void(*)(fitsfile *) noexcept > UniqueFitsFile
Defines unique ownership type to cfitsio fitsfile.
void WriteKeywords(fitsfile *ptr, int hdu_num, std::vector< LiteralKeyword > const &keywords, std::optional< ssize_t > *remaining_size)
Write keywords to HDU identified by number hdu_num.
void MakeHduSpace(fitsfile *ptr, int hdu_num, std::size_t additional_keys)
void WriteChecksum(fitsfile *ptr, int hdu_num)
Write or update checksum keywords DATASUM and CHECKSUM to HDU specified by hdu_num.
void DefaultClose(fitsfile *ptr) noexcept
Default close function that is used by UniqueFitsFile as a deleter.
void DeleteAllKeywords(fitsfile *ptr, int hdu_num)
Delete all keywords from HDU.
void InitPrimaryHduNoImage(fitsfile *ptr)
Initializes an empty FITS file with a primary HDU.
std::ostream & operator<<(std::ostream &os, HduType hdu_type)
Format HduType hdu_type to os.
std::vector< LiteralKeyword > ReadKeywords(fitsfile *ptr, int hdu_num)
Read keywords from HDU identifed by absolute position hdu_num.
UniqueFitsFile CreateEmpty(char const *filename)
Creates empty FITS file using fits_create_file and returns a pointer with a deleter that will close t...
void InitPrimaryHduEmpty(fitsfile *ptr)
Initializes an empty FITS file with an empty primary HDU (no keywords)