SourceXtractorPlusPlus  0.13
Please provide a description of the project.
FitsFile.cpp
Go to the documentation of this file.
1 
18 /*
19  * FitsFile.cpp
20  *
21  * Created on: Jun 9, 2020
22  * Author: mschefer
23  */
24 
25 #include <assert.h>
26 
27 #include <iostream>
28 #include <iomanip>
29 #include <fstream>
30 #include <string>
31 
32 #include <boost/filesystem/path.hpp>
33 #include <boost/filesystem/operations.hpp>
34 #include <boost/regex.hpp>
35 #include <boost/algorithm/string/case_conv.hpp>
36 #include <boost/algorithm/string/trim.hpp>
37 
40 
41 namespace SourceXtractor {
42 
50 static typename MetadataEntry::value_t valueAutoCast(const std::string& value) {
51  boost::regex float_regex("^[-+]?\\d*\\.?\\d+([eE][-+]?\\d+)?$");
52  boost::regex int_regex("^[-+]?\\d+$");
53 
54  try {
55  if (value.empty()) {
56  return value;
57  }
58  else if (boost::regex_match(value, int_regex)) {
59  return static_cast<int64_t>(std::stoll(value));
60  }
61  else if (boost::regex_match(value, float_regex)) {
62  return std::stod(value);
63  }
64  else if (value.size() == 1) {
65  return value.at(0);
66  }
67  } catch (...) {
68  }
69 
70  // Single quotes are used as escape code of another single quote, and
71  // the string starts and ends with single quotes.
72  // We used to use boost::io::quoted here, but it seems that starting with 1.73 it
73  // does not work well when the escape code and the delimiter are the same
74  std::string unquoted;
75  bool escape = false;
76  unquoted.reserve(value.size());
77  for (auto i = value.begin(); i != value.end(); ++i) {
78  if (*i == '\'' && !escape) {
79  escape = true;
80  // skip this char
81  }
82  else {
83  escape = false;
84  unquoted.push_back(*i);
85  }
86  }
87  return unquoted;
88 }
89 
91  m_filename(filename),
92  m_file_pointer(nullptr),
93  m_is_file_opened(false),
94  m_is_writeable(writeable),
95  m_was_opened_before(false),
96  m_manager(manager) {
97 }
98 
100  close();
101 }
102 
104  int status = 0;
105 
106  fits_open_image(&m_file_pointer, m_filename.c_str(), m_is_writeable ? READWRITE : READONLY, &status);
107  if (status != 0) {
108  throw Elements::Exception() << "Can't open FITS file: " << m_filename;
109  }
110 
111  m_image_hdus.clear() ;
112  int number_of_hdus = 0;
113  if (fits_get_num_hdus(m_file_pointer, &number_of_hdus, &status) < 0) {
114  throw Elements::Exception() << "Can't get the number of HDUs in FITS file: " << m_filename;
115  }
116 
117  m_headers.resize(number_of_hdus);
118 
119  // save current HDU (if the file is opened with advanced cfitsio syntax it might be set already
120  int original_hdu = 0;
121  fits_get_hdu_num(m_file_pointer, &original_hdu);
122 
123  // loop over HDUs to determine which ones are images
124  int hdu_type = 0;
125  for (int hdu_number=1; hdu_number <= number_of_hdus; hdu_number++) {
126  fits_movabs_hdu(m_file_pointer, hdu_number, &hdu_type, &status);
127  if (status != 0) {
128  throw Elements::Exception() << "Can't switch HDUs while opening: " << m_filename;
129  }
130 
131  if (hdu_type == IMAGE_HDU) {
132  int bitpix, naxis;
133  long naxes[2] = {1,1};
134 
135  fits_get_img_param(m_file_pointer, 2, &bitpix, &naxis, naxes, &status);
136  if (status == 0 && naxis == 2) {
137  m_image_hdus.emplace_back(hdu_number);
138  }
139  }
140  }
141 
142  // go back to saved HDU
143  fits_movabs_hdu(m_file_pointer, original_hdu, &hdu_type, &status);
144 
145  // load all FITS headers
146  reloadHeaders();
147 
148  // load optional .head file to override headers
149  loadHeadFile();
150 
151  m_is_file_opened = true;
152  m_was_opened_before = true;
153 }
154 
156  int status = 0;
157  fits_open_image(&m_file_pointer, m_filename.c_str(), m_is_writeable ? READWRITE : READONLY, &status);
158  if (status != 0) {
159  throw Elements::Exception() << "Can't open FITS file: " << m_filename;
160  }
161  m_is_file_opened = true;
162 }
163 
165  if (!m_is_file_opened) {
166  m_manager->reportOpenedFile(m_filename);
167  if (m_was_opened_before) {
168  reopen();
169  } else {
170  openFirstTime();
171  }
172  }
173  assert(m_file_pointer != nullptr);
174 }
175 
177  if (m_is_file_opened) {
178  m_manager->reportClosedFile(m_filename);
179  int status = 0;
180  fits_close_file(m_file_pointer, &status);
181  m_file_pointer = nullptr;
182  m_is_file_opened = false;
183  }
184 }
185 
187  if (!m_is_writeable) {
188  close();
189  m_is_writeable = true;
190  open();
191  }
192 }
193 
195  int status = 0;
196 
197  // save current HDU (if the file is opened with advanced cfitsio syntax it might be set already)
198  int original_hdu = 0;
199  fits_get_hdu_num(m_file_pointer, &original_hdu);
200 
201  int hdu_type = 0;
202  for (unsigned int i = 0; i < m_headers.size(); i++) {
203  fits_movabs_hdu(m_file_pointer, i+1, &hdu_type, &status); // +1 hdus start at 1
204 
206  }
207 
208  // go back to saved HDU
209  fits_movabs_hdu(m_file_pointer, original_hdu, &hdu_type, &status);
210 }
211 
214  char record[81];
215  int keynum = 1, status = 0;
216 
217  fits_read_record(fptr, keynum, record, &status);
218  while (status == 0 && strncmp(record, "END", 3) != 0) {
219  static boost::regex regex("([^=]{8})=([^\\/]*)(\\/(.*))?");
220  std::string record_str(record);
221 
222  boost::smatch sub_matches;
223  if (boost::regex_match(record_str, sub_matches, regex)) {
224  auto keyword = boost::to_upper_copy(sub_matches[1].str());
225  auto value = sub_matches[2].str();
226  auto comment = sub_matches[4].str();
227  boost::trim(keyword);
228  boost::trim(value);
229  boost::trim(comment);
230  headers.emplace(keyword, MetadataEntry{valueAutoCast(value), {{"comment", comment}}});
231  }
232  fits_read_record(fptr, ++keynum, record, &status);
233  }
234 
235  return headers;
236 }
237 
239  auto filename = boost::filesystem::path(m_filename);
240  auto base_name = filename.stem();
241  base_name.replace_extension(".head");
242  auto head_filename = filename.parent_path() / base_name;
243 
244  if (!boost::filesystem::exists(head_filename)) {
245  return;
246  }
247 
248  auto hdu_iter = m_image_hdus.begin();
249  std::ifstream file;
250 
251  // open the file and check
252  file.open(head_filename.native());
253  if (!file.good() || !file.is_open()) {
254  throw Elements::Exception() << "Cannot load ascii header file: " << head_filename;
255  }
256 
257  while (file.good() && hdu_iter != m_image_hdus.end()) {
258  int current_hdu = *hdu_iter;
259 
260  std::string line;
261  std::getline(file, line);
262 
263  static boost::regex regex_blank_line("\\s*$");
264  line = boost::regex_replace(line, regex_blank_line, std::string(""));
265  if (line.size() == 0) {
266  continue;
267  }
268 
269  if (boost::to_upper_copy(line) == "END") {
270  current_hdu = *(++hdu_iter);
271  }
272  else {
273  static boost::regex regex("([^=]{1,8})=([^\\/]*)(\\/ (.*))?");
274  boost::smatch sub_matches;
275  if (boost::regex_match(line, sub_matches, regex) && sub_matches.size() >= 3) {
276  auto keyword = boost::to_upper_copy(sub_matches[1].str());
277  auto value = sub_matches[2].str();
278  auto comment = sub_matches[4].str();
279  boost::trim(keyword);
280  boost::trim(value);
281  boost::trim(comment);
282  m_headers.at(current_hdu-1)[keyword] = MetadataEntry{valueAutoCast(value), {{"comment", comment}}};;
283  }
284  }
285  }
286 }
287 
288 
289 }
SourceXtractor::FitsFile::loadFitsHeader
std::map< std::string, MetadataEntry > loadFitsHeader(fitsfile *fptr)
Definition: FitsFile.cpp:212
std::string
STL class.
SourceXtractor::FitsFile::FitsFile
FitsFile(const std::string &filename, bool writeable, std::shared_ptr< FitsFileManager > manager)
Definition: FitsFile.cpp:90
std::shared_ptr
STL class.
SourceXtractor::FitsFile::reloadHeaders
void reloadHeaders()
Definition: FitsFile.cpp:194
conf.filename
string filename
Definition: conf.py:63
std::string::reserve
T reserve(T... args)
std::string::size
T size(T... args)
SourceXtractor::FitsFile::m_is_writeable
bool m_is_writeable
Definition: FitsFile.h:84
SourceXtractor::FitsFile::reopen
void reopen()
Definition: FitsFile.cpp:155
std::map::emplace
T emplace(T... args)
SourceXtractor::FitsFile::m_is_file_opened
bool m_is_file_opened
Definition: FitsFile.h:83
std::vector::clear
T clear(T... args)
SourceXtractor::valueAutoCast
static MetadataEntry::value_t valueAutoCast(const std::string &value)
Definition: FitsFile.cpp:50
std::string::push_back
T push_back(T... args)
SourceXtractor::FitsFile::m_headers
std::vector< std::map< std::string, MetadataEntry > > m_headers
Definition: FitsFile.h:89
std::stoll
T stoll(T... args)
SourceXtractor
Definition: Aperture.h:30
std::string::at
T at(T... args)
SourceXtractor::FitsFile::openFirstTime
void openFirstTime()
Definition: FitsFile.cpp:103
SourceXtractor::FitsFile::m_filename
std::string m_filename
Definition: FitsFile.h:81
Exception.h
std::string::c_str
T c_str(T... args)
Elements::Exception
std::ifstream::open
T open(T... args)
SourceXtractor::FitsFile::m_was_opened_before
bool m_was_opened_before
Definition: FitsFile.h:85
SourceXtractor::MetadataEntry
Definition: ImageSource.h:39
std::int64_t
std::map
STL class.
std::regex
std::ifstream::good
T good(T... args)
SourceXtractor::FitsFile::m_file_pointer
fitsfile * m_file_pointer
Definition: FitsFile.h:82
std::strncmp
T strncmp(T... args)
std::vector::emplace_back
T emplace_back(T... args)
std::stod
T stod(T... args)
SourceXtractor::FitsFile::~FitsFile
virtual ~FitsFile()
Definition: FitsFile.cpp:99
SourceXtractor::FitsFile::m_manager
std::shared_ptr< FitsFileManager > m_manager
Definition: FitsFile.h:91
std::string::begin
T begin(T... args)
std::getline
T getline(T... args)
SourceXtractor::FitsFile::setWriteMode
void setWriteMode()
Definition: FitsFile.cpp:186
std::string::empty
T empty(T... args)
SourceXtractor::FitsFile::open
void open()
Definition: FitsFile.cpp:164
SourceXtractor::FitsFile::m_image_hdus
std::vector< int > m_image_hdus
Definition: FitsFile.h:87
SourceXtractor::FitsFile::close
void close()
Definition: FitsFile.cpp:176
std::string::end
T end(T... args)
SourceXtractor::FitsFile::loadHeadFile
void loadHeadFile()
Definition: FitsFile.cpp:238
std::ifstream::is_open
T is_open(T... args)
FitsFile.h
SourceXtractor::MetadataEntry::value_t
boost::variant< bool, char, int64_t, double, std::string > value_t
Definition: ImageSource.h:40
std::ifstream
STL class.