8 #include <fmt/format.h>
9 #include <log4cplus/loggingmacros.h>
18 return source.GetKeywordRuleProcessor().Process(source.
GetKeywords(),
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(
"dpm.merge");
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(result,
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(
"dpm.merge");
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(result,
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(
"dpm.merge");
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");