mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
fitsHeaderCard.hpp
Go to the documentation of this file.
1 /** \file fitsHeaderCard.hpp
2  * \brief A class to work with a FITS header card
3  * \ingroup fits_processing_files
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  */
7 
8 //***********************************************************************//
9 // Copyright 2015-2022 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef ioutils_fits_fitsHeaderCard_hpp
28 #define ioutils_fits_fitsHeaderCard_hpp
29 
30 #include "../../mxException.hpp"
31 #include "fitsUtils.hpp"
32 
33 namespace mx
34 {
35  namespace fits
36  {
37 
38  /// Class to manage the three components of a FITS header card
39  /** Since FITS does not provide the type in keyword=value pairs in a FITS header, it is up to the user
40  * to determine the type. Futhermore, since we want to read values from files, type must
41  * be set at runtime. The result is that we must be able to accept a string, which is converted
42  * to a given type on demand at determined at runtime.
43  *
44  * Conversion from string to native type, or vice versa, only occurs when needed. So if you set the value to,
45  * say, a double, the value is not converted to string format unless specifically requested. If the write function is called
46  * when in this state, the cfitsio routine is called directly. This converson only on demand is most important for values read
47  * from a file, then written to another file. In this case, no conversion to its double (etc) representation.
48  * occurs.
49  *
50  * Note that because of the checks to determine the type and appropriate return values, accessing the value in a card
51  * is possibly slower than accessing a variable due to various if statements. This means that you should typically do
52  * so once and use a local variable for repeated use.
53  *
54  * \ingroup fits_processing
55  */
57  {
58 
59  protected:
60  /// The keyword
61  std::string m_keyword;
62 
63  /// The FITS type of the value, and indicates which member of m_values to access.
64  int m_type{fitsType<fitsUnknownType>()};
65 
66  /// The native type is held in a union.
67  union values
68  {
69  char Char; ///< the char value
70  unsigned char UChar; ///< the unsigned char value
71  short Short; ///< the short value
72  unsigned short UShort; ///< the unsigned short value
73  int Int; ///< the int value
74  unsigned int UInt; ///< the unsigned int value
75  long Long; ///< the long value
76  unsigned long ULong; ///< the unsigned long value
77  long long LongLong; ///< the long long value
78  unsigned long long ULongLong; ///< the unsigned long long value
79  float Float; ///< the float value
80  std::complex<float> complexFloat; ///< the std::complex<float> value
81  double Double; ///< the double value
82  std::complex<double> complexDouble; ///< the std::complex<double> value
83 
84  /// c'tor. have to specify due to inclusion of std::complex types.
86  {
87  return;
88  }
89 
90  } m_value;
91 
92  /// The value in string form
93  std::stringstream m_valueStr;
94 
95  bool m_valueGood{false}; ///< Flag indicating if the value is valid
96  bool m_valueStrGood{false}; ///< Flag indicating if the value string is valid
97 
98  /// The comment
99  std::string m_comment;
100 
101  public:
102  /// \name Constructors
103  /**
104  */
105  //@{
106 
107  /// Basic c'tor
109  {
110  }
111 
112  /// Construct from the three components for a value of string type
113  /**
114  */
115  fitsHeaderCard(const std::string &k, ///< [in] the keyword
116  const std::string &v, ///< [in] the value string
117  const std::string &c = "" ///< [in] the comment
118  );
119 
120  /// Construct from the three components, when already in a string format
121  /** Use this when the value is not a string
122  */
123  fitsHeaderCard(const std::string &k, ///< [in] the keyword
124  const std::string &v, ///< [in] the value string
125  const int &type, ///< [in] the type of the value
126  const std::string &c = "" ///< [in] the comment
127  );
128 
129  /// Construct from the three components, when it's really a comment card
130  /** This overload is provided to facilitate handling of comments when re-writing the file.
131  *
132  */
133  fitsHeaderCard(const std::string &k, ///< [in] the keyword
134  fitsCommentType v, ///< [in] an object of type fitsCommentType
135  const std::string &c ///< [in] the comment
136  );
137 
138  /// Construct from the three components, when it's really a history card
139  /** This overload is provided to facilitate handling of history when re-writing the file.
140  *
141  */
142  fitsHeaderCard(const std::string &k, ///< [in] the keyword
143  fitsHistoryType v, ///< [in] an object of type fitsHistoryType
144  const std::string &c ///< [in] the comment
145  );
146 
147  /// Construct from just keyword, when value's type is unknown
148  /**
149  */
150  explicit fitsHeaderCard(const std::string &k /**< [in] the keyword*/);
151 
152  /// Construct from just keyword, when value's type known
153  /**
154  */
155  fitsHeaderCard(const std::string &k, ///< [in] the keyword
156  const int type ///< [in] the type
157  );
158 
159  /// Construct from the three components for a char.
160  /**
161  */
162  template <typename typeT>
163  fitsHeaderCard(const std::string &k, ///< [in] they keyword
164  const typeT v, ///< [in] the value
165  const std::string &c = "" ///< [in] the comment
166  );
167 
168  /// Copy constructor
169  fitsHeaderCard(const fitsHeaderCard &card);
170 
171  //@}
172 
173  /// Assignment
175 
176  protected:
177  ///\name Converters
178  /** @{
179  */
180 
181  /// Convert from the type to a string.
182  /** This populates m_valueStr and sets m_valueStrGood so that this conversion
183  * only occurs once.
184  */
185  void convertToString();
186 
187  /// Convert from string to the type
188  /** This populates the appropriate union field and sets m_valueGood so that
189  * this conversion only occurs once.
190  */
191  template <typename typeT>
193 
194  /// Get the value from its type converted to a different type.
195  template <typename typeT>
196  typeT convertedValue();
197 
198  /// Convert the value from its type to a different type.
199  void convertValue(int newtype /**< [in] the new type */);
200 
201  ///@}
202 
203  public:
204  ///\name Accessors
205  /** @{
206  */
207 
208  /// Get the keyword
209  /** \returns a const reference to m_keyword
210  */
211  const std::string &keyword();
212 
213  /// Set the keyword
214  void keyword(const std::string &kw /**< [in] the new keyword */);
215 
216  /// Get the type
217  /** \returns the value of m_type
218  */
219  int type();
220 
221  /// Set the type
222  /** If this is a change in type and the native type is set in m_value (indicated by m_valueGood == true)
223  * then it is converted to the new type. Otherwise, no conversion occurs.
224  */
225  void type(const int &t /**< [in] the new type */);
226 
227  /// Get the value
228  /** Returns the value as typeT. Conversions occur
229  * automatically if necessary.
230  *
231  * \returns the value converted to typeT as necessary
232  *
233  * \throws if the value can't be converted to typeT
234  */
235  template <typename typeT>
236  typeT value();
237 
238  /// Get the value as a string
239  /** This calls value<string>().
240  *
241  * \returns the value converted to string as necessary
242  *
243  * \throws if the value can't be converted to a string
244  */
245  std::string String();
246 
247  /// Get the value as a char
248  /** This calls value<char>().
249  *
250  * \returns the value converted to char as necessary
251  *
252  * \throws if the value can't be converted to char
253  */
254  char Char();
255 
256  /// Get the value as an unsigned char
257  /** This calls value<unsigned char>().
258  *
259  * \returns the value converted to unsigned char as necessary
260  *
261  * \throws if the value can't be converted to unsigned char
262  */
263  unsigned char UChar();
264 
265  /// Get the value as a short
266  /** This calls value<short>().
267  *
268  * \returns the value converted to short as necessary
269  *
270  * \throws if the value can't be converted to short
271  */
272  short Short();
273 
274  /// Get the value as an unsigned short
275  /** This calls value<unsigned short>().
276  *
277  * \returns the value converted to unsigned short as necessary
278  *
279  * \throws if the value can't be converted to unsigned short
280  */
281  unsigned short UShort();
282 
283  /// Get the value as a int
284  /** This calls value<int>().
285  *
286  * \returns the value converted to int as necessary
287  *
288  * \throws if the value can't be converted to int
289  */
290  int Int();
291 
292  /// Get the value as an unsigned int
293  /** This calls value<unsigned int>().
294  *
295  * \returns the value converted to unsigned int as necessary
296  *
297  * \throws if the value can't be converted to unsigned int
298  */
299  unsigned int UInt();
300 
301  /// Get the value as a long
302  /** This calls value<long>().
303  *
304  * \returns the value converted to long as necessary
305  *
306  * \throws if the value can't be converted to long
307  */
308  long Long();
309 
310  /// Get the value as an unsigned long
311  /** This calls value<unsigned long>().
312  *
313  * \returns the value converted to unsigned long as necessary
314  *
315  * \throws if the value can't be converted to unsigned long
316  */
317  unsigned long ULong();
318 
319  /// Get the value as a long long
320  /** This calls value<long long>().
321  *
322  * \returns the value converted to long long as necessary
323  *
324  * \throws if the value can't be converted to long long
325  */
326  long long LongLong();
327 
328  /// Get the value as an unsigned long long
329  /** This calls value<unsigned long long>().
330  *
331  * \returns the value converted to unsigned long long as necessary
332  *
333  * \throws if the value can't be converted to unsigned long long
334  */
335  unsigned long long ULongLong();
336 
337  /// Get the value as a float
338  /** This calls value<float>().
339  *
340  * \returns the value converted to float as necessary
341  *
342  * \throws if the value can't be converted to float
343  */
344  float Float();
345 
346  /// Get the value as a std::complex<float>
347  /** This calls value<std::complex<float>>().
348  *
349  * \returns the value converted to std::complex<float> as necessary
350  *
351  * \throws if the value can't be converted to std::complex<float>
352  */
353  std::complex<float> complexFloat();
354 
355  /// Get the value as a double
356  /** This calls value<double>().
357  *
358  * \returns the value converted to double as necessary
359  *
360  * \throws if the value can't be converted to double
361  */
362  double Double();
363 
364  /// Get the value as a std::complex<double>
365  /** This calls value<std::complex<double>>().
366  *
367  * \returns the value converted to std::complex<double> as necessary
368  *
369  * \throws if the value can't be converted to std::complex<double>
370  */
371  std::complex<double> complexDouble();
372 
373  /// Set the value to a char * string
374  void value(const char *v /**< [in] a character string*/);
375 
376  /// Set the value to a std::string
377  /** \overload
378  */
379  void value(const std::string &v /**< [in] a std::string*/);
380 
381  /// Set the value to a char
382  /** \overload
383  */
384  void value(const char &v /**< [in] a char*/);
385 
386  /// Set the value to an unsigned char
387  /** \overload
388  */
389  void value(const unsigned char &v /**< [in] an unsigned char */);
390 
391  /// Set the value to a short int
392  /** \overload
393  */
394  void value(const short int &v /**< [in] a short int*/);
395 
396  /// Set the value to an unsigned short int
397  /** \overload
398  */
399  void value(const unsigned short int &v /**< [in] an unsigned short int*/);
400 
401  /// Set the value to an int
402  /** \overload
403  */
404  void value(const int &v /**< [in] an int*/);
405 
406  /// Set the value to an unsigned int
407  /** \overload
408  */
409  void value(const unsigned int &v /**< [in] an unsigned int*/);
410 
411  /// Set the value to a long int
412  /** \overload
413  */
414  void value(const long &v /**< [in] a long int*/);
415 
416  /// Set the value to an unsigned long int
417  /** \overload
418  */
419  void value(const unsigned long int &v /**< [in] an unsigned long int*/);
420 
421  /// Set the value to a long long int
422  /** \overload
423  */
424  void value(const long long &v /**< [in] a long long int*/);
425 
426  /// Set the value to an unsigned long long int
427  /** \overload
428  */
429  void value(const unsigned long long int &v /**< [in] an unsigned long long int*/);
430 
431  /// Set the value to a float
432  /** \overload
433  */
434  void value(const float &v /**< [in] a float*/);
435 
436  /// Set the value to a complex float
437  /** \overload
438  */
439  void value(const std::complex<float> &v /**< [in] a complex float*/);
440 
441  /// Set the value to a double
442  /** \overload
443  */
444  void value(const double &v /**< [in] a double*/);
445 
446  /// Set the value to a complex double
447  /** \overload
448  */
449  void value(const std::complex<double> &v /**< [in] a complex double*/);
450 
451  std::string valueStr();
452 
453  bool valueGood();
454 
455  bool valueStrGood();
456 
457  /// Get the comment
458  /** \returns the value of m_comment
459  */
460  const std::string &comment();
461 
462  /// Set the comment
463  void comment(const std::string &c /**< [in] the new comment */);
464 
465  //@}
466 
467  ///\name Output
468  /**
469  */
470  //@{
471 
472  /// Writes this card to a FITS file, using \ref mx::improc::fits_write_key<typename typeT>(fitsfile * fptr, char * keyword, void * value, char * comment).
473  /**
474  */
475  int write(fitsfile *fptr);
476 
477  //@}
478 
479  }; // fitsHeaderCard
480 
481  template <typename typeT>
482  fitsHeaderCard::fitsHeaderCard(const std::string &k,
483  const typeT v,
484  const std::string &c)
485  {
486  m_keyword = k;
487  value(v);
488  m_comment = c;
489  }
490 
491  } // namespace fits
492 } // namespace mx
493 
494 #endif // ioutils_fits_fitsHeaderCard_hpp
Class to manage the three components of a FITS header card.
std::complex< float > complexFloat()
Get the value as a std::complex<float>
fitsHeaderCard & operator=(const fitsHeaderCard &card)
Assignment.
const std::string & keyword()
Get the keyword.
int m_type
The FITS type of the value, and indicates which member of m_values to access.
std::stringstream m_valueStr
The value in string form.
int type()
Get the type.
char Char()
Get the value as a char.
std::string m_keyword
The keyword.
bool m_valueGood
Flag indicating if the value is valid.
const std::string & comment()
Get the comment.
typeT value()
Get the value.
double Double()
Get the value as a double.
long Long()
Get the value as a long.
int Int()
Get the value as a int.
unsigned char UChar()
Get the value as an unsigned char.
typeT convertedValue()
Get the value from its type converted to a different type.
unsigned short UShort()
Get the value as an unsigned short.
unsigned long ULong()
Get the value as an unsigned long.
unsigned int UInt()
Get the value as an unsigned int.
std::complex< double > complexDouble()
Get the value as a std::complex<double>
short Short()
Get the value as a short.
std::string m_comment
The comment.
bool m_valueStrGood
Flag indicating if the value string is valid.
long long LongLong()
Get the value as a long long.
void convertValue(int newtype)
Convert the value from its type to a different type.
unsigned long long ULongLong()
Get the value as an unsigned long long.
void convertToString()
Convert from the type to a string.
std::string String()
Get the value as a string.
void value(const unsigned short int &v)
Set the value to an unsigned short int.
int write(fitsfile *fptr)
Writes this card to a FITS file, using mx::improc::fits_write_key<typename typeT>(fitsfile * fptr,...
void convertFromString()
Convert from string to the type.
float Float()
Get the value as a float.
Declares and defines utilities to work with FITS files.
constexpr units::realT c()
The speed of light.
Definition: constants.hpp:60
constexpr units::realT k()
Boltzmann Constant.
Definition: constants.hpp:71
The mxlib c++ namespace.
Definition: mxError.hpp:107
The native type is held in a union.
unsigned int UInt
the unsigned int value
unsigned long long ULongLong
the unsigned long long value
values()
c'tor. have to specify due to inclusion of std::complex types.
std::complex< double > complexDouble
the std::complex<double> value
std::complex< float > complexFloat
the std::complex<float> value
unsigned short UShort
the unsigned short value
unsigned long ULong
the unsigned long value
double Double
the double value
unsigned char UChar
the unsigned char value
long long LongLong
the long long value