SourceXtractorPlusPlus 0.21
SourceXtractor++, the next generation SExtractor
Loading...
Searching...
No Matches
FitsImageSource.cpp
Go to the documentation of this file.
1
18/*
19 * FitsImageSource.cpp
20 *
21 * Created on: Mar 21, 2018
22 * Author: mschefer
23 */
24
27#include "SEUtils/VariantCast.h"
28#include <AlexandriaKernel/memory_tools.h>
29#include <ElementsKernel/Exception.h>
30#include <boost/algorithm/string/case_conv.hpp>
31#include <boost/algorithm/string/trim.hpp>
32#include <boost/filesystem/operations.hpp>
33#include <boost/filesystem/path.hpp>
34#include <boost/regex.hpp>
35#include <fstream>
36#include <iomanip>
37#include <numeric>
38#include <string>
39
40namespace SourceXtractor {
41
43
44namespace {
45
46ImageTile::ImageType convertImageType(int bitpix) {
47 ImageTile::ImageType image_type;
48
49 switch (bitpix) {
50 case FLOAT_IMG:
51 image_type = ImageTile::FloatImage;
52 break;
53 case DOUBLE_IMG:
54 image_type = ImageTile::DoubleImage;
55 break;
56 case LONG_IMG:
57 image_type = ImageTile::IntImage;
58 break;
59 case ULONG_IMG:
60 image_type = ImageTile::UIntImage;
61 break;
62 case LONGLONG_IMG:
63 image_type = ImageTile::LongLongImage;
64 break;
65 default:
66 throw Elements::Exception() << "Unsupported FITS image type: " << bitpix;
67 }
68
69 return image_type;
70}
71
72}
73
77 : m_filename(filename)
78 , m_file_manager(std::move(manager))
79 , m_handler(m_file_manager->getFileHandler(filename))
80 , m_hdu_number(hdu_number) {
81 int status = 0;
82 int bitpix, naxis;
83 long naxes[3] = {1, 1, 1};
84
85 auto acc = m_handler->getAccessor<FitsFile>();
86 auto fptr = acc->m_fd.getFitsFilePtr();
87
88 if (m_hdu_number <= 0) {
90 throw Elements::Exception() << "Can't get the active HDU from the FITS file: " << filename;
91 }
92 }
93 else {
95 }
96
98 if (status != 0 || (naxis != 2 && naxis != 3)) {
99 char error_message[32];
101 throw Elements::Exception()
102 << "Can't find 2D image or data cube in FITS file: " << filename << "[" << m_hdu_number << "]"
103 << " status: " << status << " = " << error_message;
104 }
105
106 m_width = naxes[0];
107 m_height = naxes[1];
108 m_depth = naxis >= 3 ? naxes[2] : 1;
109
110 if (image_type < 0) {
112 }
113 else {
115 }
116}
117
121 : m_filename(filename)
122 , m_file_manager(std::move(manager))
123 , m_handler(m_file_manager->getFileHandler(filename))
124 , m_width(width)
125 , m_height(height)
126 , m_image_type(image_type) {
127
128 int status = 0;
129 fitsfile* fptr = nullptr;
130
131 if (!append) {
132 // delete file if it exists already
133 boost::filesystem::remove(m_filename);
134 }
135
136 {
137 auto acc = m_handler->getAccessor<FitsFile>(FileHandler::kWrite);
138 fptr = acc->m_fd.getFitsFilePtr();
139
140 assert(fptr != nullptr);
141
142 if (empty_primary && acc->m_fd.getImageHdus().empty()) {
143 fits_create_img(fptr, FLOAT_IMG, 0, nullptr, &status);
144 if (status != 0) {
145 char error_message[32];
147 throw Elements::Exception() << "Can't create empty hdu: " << filename
148 << " status: " << status << " = " << error_message;
149 }
150 }
151
152 long naxes[2] = {width, height};
154
156 char error_message[32];
158 throw Elements::Exception() << "Can't get the active HDU from the FITS file: " << filename
159 << " status: " << status << " = " << error_message;
160 }
161
162 int hdutype = 0;
164
165 if (coord_system) {
166 auto headers = coord_system->getFitsHeaders();
167 for (const auto& h : headers) {
169 padded_key << std::setw(8) << std::left << h.first;
170
171 serializer << padded_key.str() << "= " << std::left << std::setw(70) << h.second;
172 auto str = serializer.str();
173
174 fits_update_card(fptr, padded_key.str().c_str(), str.c_str(), &status);
175 if (status != 0) {
176 char error_message[32];
178 throw Elements::Exception() << "Couldn't write the WCS headers: " << filename
179 << " status: " << status << " = " << error_message;
180 }
181 }
182 }
183
185 for (int i = 0; i < height; i++) {
186 long first_pixel[2] = {1, i + 1};
188 }
189
190 if (status != 0) {
191 char error_message[32];
193 throw Elements::Exception() << "Couldn't allocate space for new FITS file: " << filename
194 << " status: " << status << " = " << error_message;
195 }
196
197 acc->m_fd.refresh(); // make sure changes to the file structure are taken into account
198
199 }
200
201 // work around for canonical name bug:
202 // our file's canonical name might be wrong if it didn't exist, so we need to make sure we get the correct handler
203 // after we created the file
204
205 m_handler = nullptr;
206 m_handler = m_file_manager->getFileHandler(filename);
207}
208
209std::shared_ptr<ImageTile> FitsImageSource::getImageTile(int x, int y, int width, int height) const {
210 auto acc = m_handler->getAccessor<FitsFile>();
211 auto fptr = acc->m_fd.getFitsFilePtr();
213
214 auto tile = ImageTile::create(m_image_type, x, y, width, height,
216
217 long first_pixel[3] = {x + 1, y + 1, m_current_layer+1};
218 long last_pixel[3] = {x + width, y + height, m_current_layer+1};
219 long increment[3] = {1, 1, 1};
220 int status = 0;
221
223 nullptr, tile->getDataPtr(), nullptr, &status);
224 if (status != 0) {
225 char error_message[32];
227 throw Elements::Exception() << "Error reading image tile from FITS file."
228 << " status: " << status << " = " << error_message;
229 }
230
231 return tile;
232}
233
235 auto acc = m_handler->getAccessor<FitsFile>(FileHandler::kWrite);
236 auto fptr = acc->m_fd.getFitsFilePtr();
238
239 int x = tile.getPosX();
240 int y = tile.getPosY();
241 int width = tile.getWidth();
242 int height = tile.getHeight();
243
244 long first_pixel[2] = {x + 1, y + 1};
245 long last_pixel[2] = {x + width, y + height};
246 int status = 0;
247
249 if (status != 0) {
250 char error_message[32];
252 throw Elements::Exception() << "Error saving image tile to FITS file."
253 << " status: " << status << " = " << error_message;
254 }
256}
257
259 int status = 0;
260 int hdu_type = 0;
261
263
264 if (status != 0) {
265 char error_message[32];
267 throw Elements::Exception() << "Could not switch to HDU # " << hdu_number << " in file " << m_filename
268 << " status: " << status << " = " << error_message;
269 }
270 if (hdu_type != IMAGE_HDU) {
271 throw Elements::Exception() << "Trying to access non-image HDU in file " << m_filename;
272 }
273}
274
277 throw Elements::Exception() << "Trying to access an inexistent data cube layer (" << layer << ") in " << m_filename;
278 }
280}
281
285
286 auto& headers = getMetadata();
287 for (const auto& record : headers) {
288 const auto& key = record.first;
289
291 if (record_string.size() > 8) {
292 throw Elements::Exception() << "FITS keyword longer than 8 characters";
293 }
294 else if (record_string.size() < 8) {
295 record_string += std::string(8 - record_string.size(), ' ');
296 }
297
298 if (headers.at(key).m_value.type() == typeid(std::string)) {
299 record_string += "= '" + VariantCast<std::string>(headers.at(key).m_value) + "'";
300 }
301 else {
302 record_string += "= " + VariantCast<std::string>(headers.at(key).m_value);
303 }
304
305 if (record_string.size() > 80) {
306 throw Elements::Exception() << "FITS record longer than 80 characters";
307 }
308
309
310 if (record_string.size() < 80) {
311 record_string += std::string(80 - record_string.size(), ' ');
312 }
313
316 }
317
319 record_string += std::string(80 - record_string.size(), ' ');
321
322 auto buffer = make_unique<std::vector<char>>(records.begin(), records.end());
323 buffer->emplace_back(0);
324 return buffer;
325}
326
328 auto acc = m_handler->getAccessor<FitsFile>();
329 return acc->m_fd.getHDUHeaders(m_hdu_number);
330}
331
333 auto acc = m_handler->getAccessor<FitsFile>(FileHandler::kWrite);
334 auto fptr = acc->m_fd.getFitsFilePtr();
336
338 padded_key << std::setw(8) << std::left << key;
339
340 serializer << padded_key.str() << "= " << std::left << std::setw(70)
342 auto str = serializer.str();
343
344 int status = 0;
345 fits_update_card(fptr, padded_key.str().c_str(), str.c_str(), &status);
346
347 if (status != 0) {
348 char error_message[32];
350 throw Elements::Exception() << "Couldn't write the metadata: " << str
351 << " status: " << status << " = " << error_message;
352 }
353
354 // update the metadata
355 acc->m_fd.getHDUHeaders(m_hdu_number)[key] = value;
356}
357
359 switch (m_image_type) {
360 default:
362 return TFLOAT;
364 return TDOUBLE;
366 return TINT;
368 return TUINT;
370 return TLONGLONG;
371 }
372}
373
375 switch (m_image_type) {
376 default:
378 return FLOAT_IMG;
380 return DOUBLE_IMG;
382 return LONG_IMG;
384 return ULONG_IMG;
386 return LONGLONG_IMG;
387 }
388}
389
390//FIXME add missing types
391
392}
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > y
represents access to a whole FITS file and handles loading and caching FITS headers
Definition FitsFile.h:43
std::shared_ptr< FileManager > m_file_manager
const std::map< std::string, MetadataEntry > & getMetadata() const override
std::shared_ptr< ImageTile > getImageTile(int x, int y, int width, int height) const override
ImageTile::ImageType m_image_type
void saveTile(ImageTile &tile) override
FitsImageSource(const std::string &filename, int hdu_number=0, ImageTile::ImageType image_type=ImageTile::AutoType, std::shared_ptr< FileManager > manager=FileManager::getDefault())
std::unique_ptr< std::vector< char > > getFitsHeaders(int &number_of_records) const
void setMetadata(const std::string &key, const MetadataEntry &value) override
std::shared_ptr< FileHandler > m_handler
void switchHdu(fitsfile *fptr, int hdu_number) const
static size_t getTypeSize(ImageType image_type)
Definition ImageTile.h:117
static std::shared_ptr< ImageTile > create(ImageType image_type, int x, int y, int width, int height, std::shared_ptr< ImageSource > source=nullptr)
Definition ImageTile.cpp:24
T left(T... args)
T move(T... args)
std::unique_ptr< T > make_unique(Args &&... args)
STL namespace.
T setw(T... args)