8 #include <fmt/format.h>
9 #include <log4cplus/loggingmacros.h>
17 return source.GetKeywordRuleProcessor().Process(
21 auto msg = fmt::format(
"Processing keyword rules failed for JSON keywords source '{}'",
23 LOG4CPLUS_ERROR(ops.
logger, msg);
24 std::throw_with_nested(std::runtime_error(msg));
29 auto logger = log4cplus::Logger::getInstance(
"daq.dpmmerge");
32 result.reserve(literal_kws.size());
33 std::copy(std::make_move_iterator(literal_kws.begin()),
34 std::make_move_iterator(literal_kws.end()),
35 std::back_inserter(result));
38 return source.GetKeywordRuleProcessor().Process(
41 auto msg = fmt::format(
"Processing keyword rules failed for FITS file keywords source '{}'",
42 source.GetFilePath().string());
43 LOG4CPLUS_ERROR(logger, msg);
44 std::throw_with_nested(std::runtime_error(msg));
53 std::vector<SourceTypes>
const& sources) {
54 auto logger = log4cplus::Logger::getInstance(
"daq.dpmmerge");
55 constexpr
const int primary_hdu_num = 1;
58 LOG4CPLUS_DEBUG(logger,
"Read keywords from " << target.GetFilePath());
59 std::for_each(std::begin(literal_kws), std::end(literal_kws), [&](
auto const& kw) {
60 LOG4CPLUS_DEBUG(logger, kw);
62 result.reserve(literal_kws.size());
63 std::copy(std::begin(literal_kws), std::end(literal_kws), std::back_inserter(result));
67 result = target.GetKeywordRuleProcessor().Process(
69 LOG4CPLUS_DEBUG(logger,
"Result after keyword processing: " << target.GetFilePath());
70 std::for_each(std::begin(result), std::end(result), [&](
auto const& kw) {
71 LOG4CPLUS_DEBUG(logger, kw);
74 auto msg = fmt::format(
"Processing keyword rules failed for target FITS file '{}'",
75 target.GetFilePath().string());
76 LOG4CPLUS_ERROR(logger, msg);
77 std::throw_with_nested(std::runtime_error(msg));
80 for (
auto const& source : sources) {
81 std::string path_or_name;
82 auto kws = std::visit(
84 using T = std::decay_t<decltype(source)>;
85 if constexpr (std::is_same_v<T, FitsKeywordsSource>) {
86 path_or_name = fmt::format(
"{}: (keyword list)", source.GetName());
88 }
else if constexpr (std::is_same_v<T, FitsFileSource>) {
90 fmt::format(
"{}: {}", source.GetName(), source.GetFilePath().native());
95 LOG4CPLUS_DEBUG(logger,
"Updating with keywords from : " << path_or_name);
97 std::begin(kws), std::end(kws), [&](
auto const& kw) { LOG4CPLUS_DEBUG(logger, kw); });
105 std::vector<fits::LiteralKeyword>
FormatKeywords(fits::KeywordVector::const_iterator begin,
106 fits::KeywordVector::const_iterator end,
108 auto const& logger = log4cplus::Logger::getInstance(
"daq.dpmmerge");
109 std::vector<fits::LiteralKeyword> result;
110 LOG4CPLUS_DEBUG(logger,
"Formatting keywords ...");
113 LOG4CPLUS_DEBUG(logger,
"Formatting keyword input: \"" << kw <<
"\"");
115 LOG4CPLUS_DEBUG(logger,
"Formatting keyword result: \"" << formatted <<
"\"");
118 LOG4CPLUS_DEBUG(logger,
"Formatting keywords done.");
122 template <
class Container>
123 void LogKeywords(log4cplus::Logger
const& logger, Container
const& keywords) {
124 std::for_each(std::begin(keywords), std::end(keywords), [&](
auto const& kw) {
125 LOG4CPLUS_DEBUG(logger, kw);
132 std::vector<SourceTypes>
const& sources,
134 auto const& logger = ops.
logger;
135 LOG4CPLUS_INFO(logger,
"Merge primary HDU keywords");
136 LOG4CPLUS_INFO(logger,
"Compile primary keywords");
137 constexpr
const int primary_hdu_num = 1;
142 mandatory.emplace_back(std::in_place_type<fits::ValueKeyword>,
"ORIGFILE", params.
origfile);
143 mandatory.emplace_back(std::in_place_type<fits::ValueKeyword>,
"ARCFILE", params.
arcfile);
145 primary_hdu_keywords, primary_hdu_keywords.end(), mandatory.begin(), mandatory.end());
147 LOG4CPLUS_INFO(logger,
"Format keywords");
149 std::begin(primary_hdu_keywords), std::end(primary_hdu_keywords), ops.
keyword_formatter);
151 LOG4CPLUS_INFO(logger,
"Sort keywords");
153 LOG4CPLUS_DEBUG(logger,
"Sorted keywords");
160 LOG4CPLUS_INFO(logger,
"Clear keywords to make room for writing back sorted keywords.");
162 LOG4CPLUS_INFO(logger,
"Writing keywords");
163 std::optional<ssize_t> remaining_size;
165 if (remaining_size) {
166 if (*remaining_size < 0) {
167 auto needed = -*remaining_size;
169 auto msg = fmt::format(
170 "Writing keywords required resizing of primary HDU: Add space for at least {} "
171 "keywords to avoid resize",
175 auto msg = fmt::format(
"Primary HDU keyword space remaining: {} ", *remaining_size);
176 LOG4CPLUS_INFO(logger, msg);
180 LOG4CPLUS_INFO(logger,
"Writing keywords SKIPPED (dry-run)");
191 auto const& logger = ops.
logger;
194 "Merging HDU extensions from " << source.GetName() <<
"(" << source.GetFilePath() <<
")");
197 fitsfile* source_fits = source.GetFitsFile();
198 fitsfile* target_fits = target.GetFitsFile();
200 fits_get_num_hdus(source_fits, &num_hdus, &status);
203 fmt::format(
"Failed to get number of HDUs from '{}'", target.GetFilePath().c_str());
204 LOG4CPLUS_ERROR(logger, msg);
211 LOG4CPLUS_INFO(ops.
logger,
212 "Note: No HDU extensions to merge from " << source.GetFilePath());
220 int previous =
false;
222 int following =
true;
223 fits_copy_file(source_fits, target_fits, previous, current, following, &status);
225 auto const msg =
"FITS function fits_copy_file failed";
226 LOG4CPLUS_ERROR(logger, msg);
230 LOG4CPLUS_INFO(logger,
231 "Merging HDU extensions from " << source.GetName() <<
"("
232 << source.GetFilePath()
233 <<
") SKIPPED (dry-run)");
239 std::vector<SourceTypes>
const& sources,
241 auto const& logger = ops.
logger;
242 LOG4CPLUS_INFO(logger,
"Merging HDU extensions");
244 for (
auto const& source_var : sources) {
245 if (!std::holds_alternative<FitsFileSource>(source_var)) {
248 FitsFileSource const& source = std::get<FitsFileSource>(source_var);
252 std::throw_with_nested(
253 std::runtime_error(fmt::format(
"Failed to copy HDU extensions from '{}' to '{}'",
254 source.GetFilePath().c_str(),
255 target.GetFilePath().c_str())));
258 LOG4CPLUS_INFO(logger,
"Merging HDU extensions completed successfully");
262 auto const& logger = ops.
logger;
263 LOG4CPLUS_INFO(logger,
"Updating checksums for all HDUs");
265 fitsfile* target_fits = target.GetFitsFile();
267 fits_get_num_hdus(target_fits, &num_hdus, &status);
270 fmt::format(
"Failed to get number of HDUs from '{}'", target.GetFilePath().c_str());
271 LOG4CPLUS_ERROR(logger, msg);
276 for (
int hdu_num = 1; hdu_num <= num_hdus; ++hdu_num) {
277 LOG4CPLUS_DEBUG(logger,
"Updating checksum for HDU " << hdu_num);
281 LOG4CPLUS_INFO(logger,
"Updating checkum keywords SKIPPED (dry-run)");
283 LOG4CPLUS_INFO(logger,
"Updating checkum keywords completed for all HDUs successfully");
289 std::vector<SourceTypes>
const& sources,
291 auto const& logger = ops.
logger;
308 LOG4CPLUS_INFO(logger,
"Starting merge operation");
312 std::throw_with_nested(std::runtime_error(
"Failed to merge primary HDU keywords"));
318 std::throw_with_nested(std::runtime_error(
"Failed to merge primary HDU keywords"));
323 std::throw_with_nested(std::runtime_error(
"Failed to update checksums"));
326 LOG4CPLUS_INFO(logger,
"Completed successfully");
Contains functions and data structures related to cfitsio.
@ User
Default is to keep only user-keywords.
@ All
Default rule is to keep all keywords (useful for in-place merge)
fits::KeywordVector const & GetKeywords() const &noexcept
virtual void SortKeywords(std::vector< fits::LiteralKeyword > &keywords)=0
Sort keywords.
virtual void PostAlert(std::string const &id, std::string const &message)=0
Post event.
Represents errors from cfitsio.
Represents the literal 80-character FITS keyword record.
fits::KeywordVector CompilePrimaryHduKeywords(Operations ops, TargetSource &target, std::vector< SourceTypes > const &sources)
Compiles unique keywords and formats primary HDU keywords.
std::vector< fits::LiteralKeyword > FormatKeywords(fits::KeywordVector::const_iterator begin, fits::KeywordVector::const_iterator end, KeywordFormatter &fmt)
KeywordFormatter & keyword_formatter
fits::KeywordVector CompileKeywords(Operations ops, FitsKeywordsSource const &source)
log4cplus::Logger const & logger
void UpdateChecksums(Operations ops, TargetSource &target, bool dry_run)
KeywordSorter & keyword_sorter
void CopyExtensions(Operations ops, TargetSource &target, FitsFileSource const &source, bool dry_run)
Copy all extensions from source to target.
void Merge(Operations ops, Params const ¶ms, TargetSource &target, std::vector< SourceTypes > const &sources, bool dry_run)
Merge sources into the target target.
void LogKeywords(log4cplus::Logger const &logger, Container const &keywords)
void MergeHduExtensions(Operations ops, TargetSource &target, std::vector< SourceTypes > const &sources, bool dry_run)
StatusReporter & status_reporter
void MergePrimaryHduKeywords(Operations ops, Params const ¶ms, TargetSource &target, std::vector< SourceTypes > const &sources, bool dry_run)
void SelectHduNum(fitsfile *ptr, int hdu_num)
Select current HDU number.
void InsertKeywords(KeywordVector &keywords, KeywordVector::iterator position, KeywordVector::const_iterator from_first, KeywordVector::const_iterator from_last)
Insert keywords.
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 WriteChecksum(fitsfile *ptr, int hdu_num)
Write or update checksum keywords DATASUM and CHECKSUM to HDU specified by hdu_num.
void DeleteAllKeywords(fitsfile *ptr, int hdu_num)
Delete all keywords from HDU.
std::vector< KeywordVariant > KeywordVector
Vector of keywords.
void UpdateKeywords(KeywordVector &to, KeywordVector const &from, ConflictPolicy policy=ConflictPolicy::Replace)
Updates to with keywords from from.
std::vector< LiteralKeyword > ReadKeywords(fitsfile *ptr, int hdu_num)
Read keywords from HDU identifed by absolute position hdu_num.
@ Skip
Skip keyword that conflicts.