SourceXtractorPlusPlus 0.21
SourceXtractor++, the next generation SExtractor
Loading...
Searching...
No Matches
LdacOutput.cpp
Go to the documentation of this file.
1
18#include <sstream>
19
20#include <AlexandriaKernel/memory_tools.h>
21
22#include "SOURCEXTRACTORPLUSPLUS_VERSION.h"
23
28
29#if BOOST_VERSION < 107300
30#include <boost/io/detail/quoted_manip.hpp>
31#else
32#include <boost/io/quoted.hpp>
33#endif
34
35namespace SourceXtractor {
36
39using namespace Euclid::Table;
40
41namespace {
42
43template<typename T>
44std::string generateHeader(const std::string& name, T value, const std::string& comment) {
46
47 str << std::setw(8) << std::left << name << "= "
48 << std::scientific << std::setw(20) << std::right << value
49 << " / ";
50
51 if (str.str().size() > 80) {
52 throw Elements::Exception() << "Header cannot exceed 80 characters: \"" << str.str() << "\"";
53 }
54
55 size_t remaining = 80 - str.str().size();
56 if (comment.size() < remaining) {
57 str << comment << std::string(remaining - comment.size(), ' ');
58 } else {
59 // truncate comment if too long
60 str << comment.substr(0, remaining);
61 }
62
63 return str.str();
64}
65
66template<>
67std::string generateHeader<std::string>(const std::string& name, std::string value, const std::string& comment) {
69
70 quoted_value << boost::io::quoted(value, '\'', '\'');
71
72 str << std::setw(8) << std::left << name << "= "
73 << std::setw(20) << std::left << quoted_value.str()
74 << " / ";
75
76 if (str.str().size() > 80) {
77 throw Elements::Exception() << "Header cannot exceed 80 characters: \"" << str.str() << "\"";
78 }
79
80 size_t remaining = 80 - str.str().size();
81 if (comment.size() < remaining) {
82 str << comment << std::string(remaining - comment.size(), ' ');
83 } else {
84 // truncate comment if too long
85 str << comment.substr(0, remaining);
86 }
87
88 return str.str();
89}
90
91static void generateHistory(std::vector<std::string>& headers) {
94
95 str << "Version " << SOURCEXTRACTORPLUSPLUS_VERSION_STRING;
96 entries.emplace_back(str.str());
97 str.str("");
98
99 auto t = std::time(nullptr);
100 auto now = *std::gmtime(&t);
101
102 char date_str[32];
103 strftime(date_str, sizeof(date_str), "%Y-%m-%dT%H:%M:%SZ", &now);
104 str << "Called at " << date_str;
105 entries.emplace_back(str.str());
106 str.str("");
107
108 for (auto& e : entries) {
109 std::stringstream padder;
110 padder << "HISTORY s++: " << std::setw(67) << std::left << e;
111 headers.emplace_back(padder.str());
112 }
113}
114
115}
116
117void LdacOutput::outputSource(const SourceInterface& source) {
118 if (m_fits_writer == nullptr) {
119 const auto& detection_frame_info = source.getProperty<DetectionFrameInfo>();
120 m_rms = detection_frame_info.getBackgroundMedianRms();
121 m_gain = detection_frame_info.getGain();
122
123 // Headers from the image
124 m_image_metadata = detection_frame_info.getMetadata();
125
126 writeHeaders();
127
128 m_fits_writer = std::make_shared<FitsWriter>(m_filename);
129
130
131 if (m_part_nb >= 1) {
133 hdu_name << "LDAC_OBJECTS_" << m_part_nb;
134 m_fits_writer->setHduName(hdu_name.str());
135 } else {
136 m_fits_writer->setHduName("LDAC_OBJECTS");
137 }
138 }
139 FlushableOutput::outputSource(source);
140}
141
142void LdacOutput::writeHeaders() {
143 auto imhead_writer = Euclid::make_unique<FitsWriter>(m_filename, m_part_nb == 0);
144 if (m_part_nb >= 1) {
146 hdu_name << "LDAC_IMHEAD_" << m_part_nb;
147 imhead_writer->setHduName(hdu_name.str());
148 } else {
149 imhead_writer->setHduName("LDAC_IMHEAD");
150 }
151
152 // Headers from the image
154 for (const auto &p : m_image_metadata) {
156 if (p.second.m_extra.count("comment")) {
157 comment = p.second.m_extra.at("comment");
158 }
159 if (p.second.m_value.type() == typeid(std::string)) {
160 ldac_imhead.emplace_back(generateHeader(p.first, boost::get<std::string>(p.second.m_value), comment));
161 } else {
162 ldac_imhead.emplace_back(generateHeader(p.first, p.second.m_value, comment));
163 }
164 }
165
166 // Headers from the configuration and detection
167 ldac_imhead.emplace_back(generateHeader("SPPGAIN", m_gain, "Gain used"));
168 ldac_imhead.emplace_back(generateHeader("SPPBKDEV", m_rms, "Median background RMS"));
169
170 // History, why not
172
173 // END
174 ldac_imhead.emplace_back("END" + std::string(77, ' '));
175
176 // Join everything as a single string
178
179 // Write the table
182 imhead_writer->addData(Table{std::move(rows)});
183}
184
185void LdacOutput::nextPart() {
186 m_part_nb++;
187 // closes current HDU and will trigger a new header HDU when the next source is written
188 m_fits_writer = nullptr;
189}
190
191} // end of namespace SourceXtractor
T accumulate(T... args)
The SourceInterface is an abstract "source" that has properties attached to it.
T scientific(T... args)
T function(T... args)
T gmtime(T... args)
T left(T... args)
T move(T... args)
constexpr double e
std::unique_ptr< T > make_unique(Args &&... args)
T setw(T... args)
T size(T... args)
T str(T... args)
T strftime(T... args)
T substr(T... args)
T time(T... args)