GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GFitsHeaderCard.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GFitsHeaderCard.cpp - FITS header card class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2008-2018 by Juergen Knoedlseder *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 /**
22  * @file GFitsHeaderCard.cpp
23  * @brief FITS header card class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <cfloat>
32 #include <climits>
33 #include "GException.hpp"
34 #include "GTools.hpp"
35 #include "GFitsCfitsio.hpp"
36 #include "GFits.hpp"
37 #include "GFitsHeaderCard.hpp"
38 
39 /* __ Method name definitions ____________________________________________ */
40 #define G_COPY_DTYPE "GFitsHeaderCard::copy_dtype(GFitsHeaderCard&)"
41 #define G_FREE_DTYPE "GFitsHeaderCard::free_dtype()"
42 #define G_SET_DTYPE "GFitsHeaderCard::set_dtype(std::string&)"
43 #define G_READ_NUM "GFitsHeaderCard::read(void*, int&)"
44 #define G_READ_STR "GFitsHeaderCard::read(void*, std::string&)"
45 #define G_WRITE "GFitsHeaderCard::write(void*)"
46 
47 /* __ Definitions ________________________________________________________ */
48 
49 /* __ Macros _____________________________________________________________ */
50 
51 /* __ Coding definitions _________________________________________________ */
52 
53 /* __ Enumerations _______________________________________________________ */
54 
55 /* __ Debug definitions __________________________________________________ */
56 
57 
58 /*==========================================================================
59  = =
60  = Constructors/destructors =
61  = =
62  ==========================================================================*/
63 
64 /***********************************************************************//**
65  * @brief Void constructor
66  ***************************************************************************/
68 {
69  // Initialise class members
70  init_members();
71 
72  // Return
73  return;
74 }
75 
76 
77 /***********************************************************************//**
78  * @brief Card constructor
79  *
80  * @param[in] keyname Card name.
81  * @param[in] value Card value.
82  * @param[in] unit Card unit.
83  * @param[in] comment Card comment.
84  *
85  * Constructs a header card from @p keyname, @p value, @p unit and
86  * @p comment string. The card type is determined from the card value format.
87  ***************************************************************************/
88 GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname,
89  const std::string& value,
90  const std::string& unit,
91  const std::string& comment)
92 {
93  // Initialise class members
94  init_members();
95 
96  // Set members
97  set_members(keyname, value, unit, comment);
98 
99  // Return
100  return;
101 }
102 
103 
104 
105 
106 /***********************************************************************//**
107  * @brief Constructor for string cards
108  *
109  * @param[in] keyname Card name.
110  * @param[in] value Card string value.
111  * @param[in] comment Card comment.
112  *
113  * This constructor builds a header card from the keyname, value and comment.
114  ***************************************************************************/
115 GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname,
116  const std::string& value,
117  const std::string& comment)
118 {
119  // Initialise class members
120  init_members();
121 
122  // Set members
123  this->keyname(keyname);
124  this->value("'"+value+"'");
125  this->comment(comment);
126 
127  // Return
128  return;
129 }
130 
131 
132 /***********************************************************************//**
133  * @brief Constructor for floating point cards
134  *
135  * @param[in] keyname Card name.
136  * @param[in] value Card floating point value.
137  * @param[in] comment Card comment.
138  *
139  * This constructor builds a header card from the keyname, value and comment.
140  ***************************************************************************/
141 GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname,
142  const double& value,
143  const std::string& comment)
144 {
145  // Initialise class members
146  init_members();
147 
148  // Set members
149  this->keyname(keyname);
150  this->value(value);
151  this->comment(comment);
152 
153  // Return
154  return;
155 }
156 
157 
158 /***********************************************************************//**
159  * @brief Constructor for boolean cards
160  *
161  * @param[in] keyname Card name.
162  * @param[in] value Card integer value.
163  * @param[in] comment Card comment.
164  *
165  * This constructor builds a header card from the keyname, value and comment.
166  ***************************************************************************/
167 GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname,
168  const int& value,
169  const std::string& comment)
170 {
171  // Initialise class members
172  init_members();
173 
174  // Set members
175  this->keyname(keyname);
176  this->value(value);
177  this->comment(comment);
178 
179  // Return
180  return;
181 }
182 
183 
184 /***********************************************************************//**
185  * @brief Constructor for integer cards
186  *
187  * @param[in] keyname Card name.
188  * @param[in] value Card boolean value.
189  * @param[in] comment Card comment.
190  *
191  * This constructor builds a header card from the keyname, value and comment.
192  ***************************************************************************/
193 GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname,
194  const bool& value,
195  const std::string& comment)
196 {
197  // Initialise class members
198  init_members();
199 
200  // Set members
201  this->keyname(keyname);
202  this->value(value);
203  this->comment(comment);
204 
205  // Return
206  return;
207 }
208 
209 
210 /***********************************************************************//**
211  * @brief Constructor for character string cards
212  *
213  * @param[in] keyname Card name.
214  * @param[in] value Card character string value.
215  * @param[in] comment Card comment.
216  *
217  * This constructor builds a header card from the keyname, value and comment.
218  ***************************************************************************/
219 GFitsHeaderCard::GFitsHeaderCard(const std::string& keyname,
220  const char* value,
221  const std::string& comment)
222 {
223  // Initialise class members
224  init_members();
225 
226  // Set members
227  this->keyname(keyname);
228  this->value(std::string(value));
229  this->comment(comment);
230 
231  // Return
232  return;
233 }
234 
235 
236 /***********************************************************************//**
237  * @brief Copy constructor
238  *
239  * @param[in] card Header card.
240  ***************************************************************************/
242 {
243  // Initialise class members for clean destruction
244  init_members();
245 
246  // Copy members
247  copy_members(card);
248 
249  // Return
250  return;
251 }
252 
253 
254 /***********************************************************************//**
255  * @brief Destructor
256  ***************************************************************************/
258 {
259  // Free members
260  free_members();
261 
262  // Return
263  return;
264 }
265 
266 /*==========================================================================
267  = =
268  = Operators =
269  = =
270  ==========================================================================*/
271 
272 /***********************************************************************//**
273  * @brief Assignment operator
274  *
275  * @param[in] card Header card.
276  * @return Header card.
277  ***************************************************************************/
279 {
280  // Execute only if object is not identical
281  if (this != &card) {
282 
283  // Free members
284  free_members();
285 
286  // Initialise private members for clean destruction
287  init_members();
288 
289  // Copy members
290  copy_members(card);
291 
292  } // endif: object was not identical
293 
294  // Return this object
295  return *this;
296 }
297 
298 
299 /*==========================================================================
300  = =
301  = Public methods =
302  = =
303  ==========================================================================*/
304 
305 /***********************************************************************//**
306  * @brief Clear header card
307  ***************************************************************************/
309 {
310  // Free members
311  free_members();
312 
313  // Initialise members
314  init_members();
315 
316  // Return
317  return;
318 }
319 
320 
321 /***********************************************************************//**
322  * @brief Clone header card
323  *
324  * @return Pointer to deep copy of header card.
325  ***************************************************************************/
327 {
328  return new GFitsHeaderCard(*this);
329 }
330 
331 
332 /***********************************************************************//**
333  * @brief Set name of header card
334  *
335  * @param[in] keyname Card name.
336  ***************************************************************************/
337 void GFitsHeaderCard::keyname(const std::string& keyname)
338 {
339  // Set name of card
340  m_keyname = keyname;
341 
342  // Return
343  return;
344 }
345 
346 
347 /***********************************************************************//**
348  * @brief Set string value of header card
349  *
350  * @param[in] value Card string value.
351  *
352  * This method sets the value of a string header card. The internal string
353  * representation contains hyphens, yet for keyword writing the hyphens are
354  * stripped.
355  ***************************************************************************/
356 void GFitsHeaderCard::value(const std::string& value)
357 {
358  // Free data type
359  free_dtype();
360 
361  // Set value
362  m_value = value;
363 
364  // Attach hyphens to internal string representation if required
365  if (m_value[0] != '\x27') {
366  m_value = "'" + m_value;
367  }
368  if (m_value[m_value.length()-1] != '\x27') {
369  m_value = m_value + "'";
370  }
371 
372  // Strip hyphens and whitespace from datatype value that is used for
373  // keyword writing
374  std::string value_dtype =
375  gammalib::strip_whitespace(m_value.substr(1, m_value.length() - 2));
376 
377  // Set data type
378  m_dtype = __TSTRING;
379  m_value_dtype = new std::string(value_dtype);
380 
381  // Return
382  return;
383 }
384 
385 
386 /***********************************************************************//**
387  * @brief Set boolean value of header card
388  *
389  * @param[in] value Card boolean value.
390  ***************************************************************************/
391 void GFitsHeaderCard::value(const bool& value)
392 {
393  // Free data type
394  free_dtype();
395 
396  // Set value and data type
397  m_value = (value) ? "T" : "F";
399  m_value_dtype = new bool(value);
400 
401  // Return
402  return;
403 }
404 
405 
406 /***********************************************************************//**
407  * @brief Set single precision value of header card
408  *
409  * @param[in] value Card single precision value.
410  ***************************************************************************/
411 void GFitsHeaderCard::value(const float& value)
412 {
413  // Free data type
414  free_dtype();
415 
416  // Set value and data type
417  m_value = gammalib::str(value);
418  m_dtype = __TFLOAT;
419  m_value_dtype = new float(value);
420 
421  // Return
422  return;
423 }
424 
425 
426 /***********************************************************************//**
427  * @brief Set double precision value of header card
428  *
429  * @param[in] value Card double precision value.
430  ***************************************************************************/
431 void GFitsHeaderCard::value(const double& value)
432 {
433  // Free data type
434  free_dtype();
435 
436  // Set value and data type
437  m_value = gammalib::str(value);
438  m_dtype = __TDOUBLE;
439  m_value_dtype = new double(value);
440 
441  // Return
442  return;
443 }
444 
445 
446 /***********************************************************************//**
447  * @brief Set unsigned short integer value of header card
448  *
449  * @param[in] value Card unsigned short integer value.
450  ***************************************************************************/
451 void GFitsHeaderCard::value(const unsigned short& value)
452 {
453  // Free data type
454  free_dtype();
455 
456  // Set value and data type
457  m_value = gammalib::str(value);
458  m_dtype = __TUSHORT;
459  m_value_dtype = new unsigned short(value);
460 
461  // Return
462  return;
463 }
464 
465 
466 /***********************************************************************//**
467  * @brief Set short integer value of header card
468  *
469  * @param[in] value Card short integer value.
470  ***************************************************************************/
471 void GFitsHeaderCard::value(const short& value)
472 {
473  // Free data type
474  free_dtype();
475 
476  // Set value and data type
477  m_value = gammalib::str(value);
478  m_dtype = __TSHORT;
479  m_value_dtype = new short(value);
480 
481  // Return
482  return;
483 }
484 
485 
486 /***********************************************************************//**
487  * @brief Set unsigned integer value of header card
488  *
489  * @param[in] value Card unsigned integer value.
490  ***************************************************************************/
491 void GFitsHeaderCard::value(const unsigned int& value)
492 {
493  // Free data type
494  free_dtype();
495 
496  // Set value and data type
497  m_value = gammalib::str(value);
498  m_dtype = __TUINT;
499  m_value_dtype = new unsigned int(value);
500 
501  // Return
502  return;
503 }
504 
505 
506 /***********************************************************************//**
507  * @brief Set integer value of header card
508  *
509  * @param[in] value Card integer value.
510  ***************************************************************************/
511 void GFitsHeaderCard::value(const int& value)
512 {
513  // Free data type
514  free_dtype();
515 
516  // Set value and data type
517  m_value = gammalib::str(value);
518  m_dtype = __TINT;
519  m_value_dtype = new int(value);
520 
521  // Return
522  return;
523 }
524 
525 
526 /***********************************************************************//**
527  * @brief Set long integer value of header card
528  *
529  * @param[in] value Card long integer value.
530  ***************************************************************************/
531 void GFitsHeaderCard::value(const long& value)
532 {
533  // Free data type
534  free_dtype();
535 
536  // Set value and data type
537  m_value = gammalib::str(value);
538  m_dtype = __TLONG;
539  m_value_dtype = new long(value);
540 
541  // Return
542  return;
543 }
544 
545 
546 /***********************************************************************//**
547  * @brief Set unsigned integer long value of header card
548  *
549  * @param[in] value Card unsigned long integer value.
550  ***************************************************************************/
551 void GFitsHeaderCard::value(const unsigned long& value)
552 {
553  // Free data type
554  free_dtype();
555 
556  // Set value and data type
557  m_value = gammalib::str(value);
558  m_dtype = __TULONG;
559  m_value_dtype = new unsigned long(value);
560 
561  // Return
562  return;
563 }
564 
565 
566 /***********************************************************************//**
567  * @brief Set long long integer value of header card
568  *
569  * @param[in] value Card long long integer value.
570  ***************************************************************************/
571 void GFitsHeaderCard::value(const long long& value)
572 {
573  // Free data type
574  free_dtype();
575 
576  // Set value and data type
577  m_value = gammalib::str(value);
579  m_value_dtype = new long long(value);
580 
581  // Return
582  return;
583 }
584 
585 
586 /***********************************************************************//**
587  * @brief Return header card value as string
588  *
589  * @return Header card value as string
590  *
591  * Returns header card value as string. Any hyphens that may occur in the
592  * FITS card will be stripped.
593  ***************************************************************************/
594 std::string GFitsHeaderCard::string(void) const
595 {
596  // Initialize return value to actual value string
597  std::string result = m_value;
598 
599  // Type dependent conversion
600  if (m_value_dtype != NULL) {
601  switch (m_dtype) {
602  case __TSTRING:
603  {
604  int n = m_value.length();
605  if (n > 2) {
606  result = gammalib::strip_whitespace(m_value.substr(1, n-2));
607  }
608  else {
609  result = "";
610  }
611  }
612  break;
613  default:
614  break;
615  }
616  }
617 
618  // Return string
619  return result;
620 
621 }
622 
623 
624 /***********************************************************************//**
625  * @brief Return header card value as double precision
626  *
627  * Convert header card value into a double precision value. In case that the
628  * card did not contain a numerical value, 0 will be returned by the
629  * method.
630  ***************************************************************************/
631 double GFitsHeaderCard::real(void) const
632 {
633  // Initialize return value to 0.0
634  double result = 0.0;
635 
636  // Type dependent conversion
637  if (m_value_dtype != NULL) {
638  switch (m_dtype) {
639  case __TSTRING:
640  if (m_value.length() > 2) {
641  result = gammalib::todouble(m_value.substr(1, m_value.length() - 2));
642  }
643  break;
644  case __TLOGICAL:
645  result = (m_value == "T") ? 1.0 : 0.0;
646  break;
647  default:
648  result = gammalib::todouble(m_value);
649  break;
650  }
651  }
652 
653  // Return string
654  return result;
655 
656 }
657 
658 
659 /***********************************************************************//**
660  * @brief Return header card value as integer
661 *
662  * Convert header card value into a integer value. In case that the
663  * card did not contain a numerical value, 0 will be returned by the
664  * method.
665  ***************************************************************************/
667 {
668  // Initialize return value to 0
669  int result = 0;
670 
671  // Type dependent conversion
672  if (m_value_dtype != NULL) {
673  switch (m_dtype) {
674  case __TSTRING:
675  if (m_value.length() > 2) {
676  result = gammalib::toint(m_value.substr(1, m_value.length() - 2));
677  }
678  break;
679  case __TLOGICAL:
680  result = (m_value == "T") ? 1 : 0;
681  break;
682  default:
683  result = gammalib::toint(m_value);
684  break;
685  }
686  }
687 
688  // Return string
689  return result;
690 
691 }
692 
693 
694 /***********************************************************************//**
695  * @brief Print header card information
696  *
697  * @param[in] chatter Chattiness (defaults to NORMAL).
698  * @return String containing header card information.
699  ***************************************************************************/
700 std::string GFitsHeaderCard::print(const GChatter& chatter) const
701 {
702  // Initialise result string
703  std::string result;
704 
705  // Continue only if chatter is not silent
706  if (chatter != SILENT) {
707 
708  // Append keyname
709  result.append(gammalib::left(m_keyname,8));
710 
711  // Format values
712  if (m_keyname != "COMMENT" && m_keyname != "HISTORY" && m_keyname != "") {
713  if (m_unit.length() > 0) {
714  result.append(" ="+gammalib::right(m_value,21)+" / ["+m_unit+"] "+m_comment);
715  }
716  else {
717  result.append(" ="+gammalib::right(m_value,21)+" / "+m_comment);
718  }
719  }
720  else {
721  result.append(" "+m_comment);
722  }
723 
724  // Attach card type
725  if (m_value_dtype != NULL) {
726  switch (m_dtype) {
727  case __TNULL:
728  result.append(" <null>");
729  break;
730  case __TBIT:
731  result.append(" <bit>");
732  break;
733  case __TBYTE:
734  result.append(" <byte>");
735  break;
736  case __TSBYTE:
737  result.append(" <signed byte>");
738  break;
739  case __TLOGICAL:
740  result.append(" <bool>");
741  break;
742  case __TSTRING:
743  result.append(" <string>");
744  break;
745  case __TUSHORT:
746  result.append(" <unsigned short>");
747  break;
748  case __TSHORT:
749  result.append(" <short>");
750  break;
751  case __TUINT:
752  result.append(" <unsigned int>");
753  break;
754  case __TINT:
755  result.append(" <int>");
756  break;
757  case __TULONG:
758  result.append(" <unsigned long>");
759  break;
760  case __TLONG:
761  result.append(" <long>");
762  break;
763  case __TLONGLONG:
764  result.append(" <long long>");
765  break;
766  case __TFLOAT:
767  result.append(" <float>");
768  break;
769  case __TDOUBLE:
770  result.append(" <double>");
771  break;
772  case __TCOMPLEX:
773  result.append(" <complex>");
774  break;
775  case __TDBLCOMPLEX:
776  result.append(" <double complex>");
777  break;
778  default:
779  result.append(" <unsupported value "+gammalib::str(m_dtype)+">");
780  break;
781  }
782  }
783  /*
784  else {
785  switch (m_dtype) {
786  case __TNULL:
787  result.append(" <null>");
788  break;
789  default:
790  result.append(" <non native>");
791  break;
792  }
793  }
794  */
795 
796  } // endif: chatter was not silent
797 
798  // Return result
799  return result;
800 }
801 
802 
803 /*==========================================================================
804  = =
805  = Private methods =
806  = =
807  ==========================================================================*/
808 
809 /***********************************************************************//**
810  * @brief Initialise class members
811  ***************************************************************************/
813 {
814  // Initialise members
815  m_keyname.clear();
816  m_value.clear();
817  m_unit.clear();
818  m_comment.clear();
819  m_value_dtype = NULL;
820  m_dtype = __TNULL;
821  m_value_decimals = 10;
822  m_comment_write = true; // Was false before, not sure why ...
823 
824  // Return
825  return;
826 }
827 
828 
829 /***********************************************************************//**
830  * @brief Copy class members
831  *
832  * @param[in] card Header card to be copied
833  ***************************************************************************/
835 {
836  // Copy members
837  m_keyname = card.m_keyname;
838  m_value = card.m_value;
840  m_unit = card.m_unit;
841  m_comment = card.m_comment;
843 
844  // Copy native data types
845  copy_dtype(card);
846 
847  // Return
848  return;
849 }
850 
851 
852 /***********************************************************************//**
853  * @brief Delete class members
854  ***************************************************************************/
856 {
857  // Free members
858  free_dtype();
859 
860  // Return
861  return;
862 }
863 
864 
865 /***********************************************************************//**
866  * @brief Set card members
867  *
868  * @param[in] keyname Card name.
869  * @param[in] value Card value.
870  * @param[in] unit Card unit.
871  * @param[in] comment Card comment.
872  *
873  * Sets the card members from @p keyname, @p value, @p unit, and @p comment
874  * strings. The card type is determined from the format of the card value.
875  ***************************************************************************/
876 void GFitsHeaderCard::set_members(const std::string& keyname,
877  const std::string& value,
878  const std::string& unit,
879  const std::string& comment) {
880 
881  // Store attributes
882  m_keyname = keyname;
883  m_value = value;
884  m_comment = comment;
885 
886  // Determine card type
888 
889  // Return
890  return;
891 }
892 
893 
894 /***********************************************************************//**
895  * @brief Copy dtype
896  *
897  * @param[in] card Header card.
898  *
899  * Copies the data type of a header card.
900  ***************************************************************************/
902 {
903  // Copy data type
904  if (card.m_value_dtype != NULL) {
905  m_dtype = card.m_dtype;
906  switch (m_dtype) {
907  case __TLOGICAL:
908  m_value_dtype = new bool(*((bool*)card.m_value_dtype));
909  break;
910  case __TSTRING:
911  m_value_dtype = new std::string(*((std::string*)card.m_value_dtype));
912  break;
913  case __TUSHORT:
914  m_value_dtype = new unsigned short(*((unsigned short*)card.m_value_dtype));
915  break;
916  case __TSHORT:
917  m_value_dtype = new short(*((short*)card.m_value_dtype));
918  break;
919  case __TUINT:
920  m_value_dtype = new unsigned int(*((unsigned int*)card.m_value_dtype));
921  break;
922  case __TINT:
923  m_value_dtype = new int(*((int*)card.m_value_dtype));
924  break;
925  case __TULONG:
926  m_value_dtype = new unsigned long(*((unsigned long*)card.m_value_dtype));
927  break;
928  case __TLONG:
929  m_value_dtype = new long(*((long*)card.m_value_dtype));
930  break;
931  case __TLONGLONG:
932  m_value_dtype = new long long(*((long long*)card.m_value_dtype));
933  break;
934  case __TFLOAT:
935  m_value_dtype = new float(*((float*)card.m_value_dtype));
936  break;
937  case __TDOUBLE:
938  m_value_dtype = new double(*((double*)card.m_value_dtype));
939  break;
940  default:
941  std::string msg = "Invalid data type code "+
942  gammalib::str(m_dtype)+" encountered.";
944  break;
945  }
946  }
947 
948  // Return
949  return;
950 }
951 
952 
953 /***********************************************************************//**
954  * @brief Free dtype
955  ***************************************************************************/
957 {
958  // Free data type
959  if (m_value_dtype != NULL) {
960  switch (m_dtype) {
961  case __TLOGICAL:
962  delete (bool*)m_value_dtype;
963  break;
964  case __TSTRING:
965  delete (std::string*)m_value_dtype;
966  break;
967  case __TUSHORT:
968  delete (unsigned short*)m_value_dtype;
969  break;
970  case __TSHORT:
971  delete (short*)m_value_dtype;
972  break;
973  case __TUINT:
974  delete (unsigned int*)m_value_dtype;
975  break;
976  case __TINT:
977  delete (int*)m_value_dtype;
978  break;
979  case __TULONG:
980  delete (unsigned long*)m_value_dtype;
981  break;
982  case __TLONG:
983  delete (long*)m_value_dtype;
984  break;
985  case __TLONGLONG:
986  delete (long long*)m_value_dtype;
987  break;
988  case __TFLOAT:
989  delete (float*)m_value_dtype;
990  break;
991  case __TDOUBLE:
992  delete (double*)m_value_dtype;
993  break;
994  default:
995  std::string msg = "Invalid data type code "+
996  gammalib::str(m_dtype)+" encountered.";
998  break;
999  }
1000  }
1001 
1002  // Return
1003  return;
1004 }
1005 
1006 
1007 /***********************************************************************//**
1008  * @brief Set native data type from card string
1009  *
1010  * @param[in] value Card string.
1011  *
1012  * The native data type is determined from the card string. This method sets
1013  * the members m_dtype and m_value_type. The card type is determined by
1014  * analyzing the card value.
1015  *
1016  * @todo Implement syntax checking for integer or float values.
1017  ***************************************************************************/
1018 void GFitsHeaderCard::set_dtype(const std::string& value)
1019 {
1020  // Free data type
1021  free_dtype();
1022 
1023  // Main loop to allow fall through
1024  do {
1025 
1026  // Get index of last string element
1027  int last = m_value.length() - 1;
1028 
1029  // If value is empty and there is a COMMENT, HISTORY or BLANKFIELD
1030  // (empty) keyword then we have a commentary card. We can just
1031  // skip this card here. Otherwise we have an undefined value, also
1032  // called NULL value.
1033  if (last < 0) {
1034  if (m_keyname == "COMMENT" ||
1035  m_keyname == "HISTORY" ||
1036  m_keyname == "") {
1037  continue;
1038  }
1039  else {
1040  m_dtype = __TNULL;
1041  continue;
1042  }
1043  }
1044 
1045  // If value is enclosed in parentheses then we have a string
1046  if (m_value[0] == '\x27' && m_value[last] == '\x27') {
1047  this->value(value);
1048  continue;
1049  }
1050 
1051  // If value has only one digit and is either 'F' or 'T' we have a
1052  // Boolean
1053  if (last == 0 && (m_value[0] == 'F' || m_value[0] == 'T')) {
1054  this->value((m_value[0] == 'T'));
1055  continue;
1056  }
1057 
1058  // Conversion
1059  double value_dbl = gammalib::todouble(m_value);
1060  long long value_ll = gammalib::tolonglong(m_value);
1061  unsigned long long value_ull = gammalib::toulonglong(m_value);
1062 
1063  // Check if we have an integer
1064  if ((value_dbl >= 0 && value_dbl == value_ull) ||
1065  (value_dbl < 0 && value_dbl == value_ll)) {
1066 
1067  // Consider positive integers as unsigned
1068  if (value_dbl >= 0) {
1069  if (value_ull > ULONG_MAX) {
1070  m_dtype = __TLONGLONG;
1071  m_value_dtype = new long long(value_ll);
1072  }
1073  else if (value_ull > USHRT_MAX) {
1074  m_dtype = __TULONG;
1075  m_value_dtype = new unsigned long(value_ull);
1076  }
1077  else {
1078  m_dtype = __TUSHORT;
1079  m_value_dtype = new unsigned short(value_ull);
1080  }
1081  }
1082 
1083  // ... otherwise consider signed
1084  else {
1085  if (value_ll > LONG_MAX || value_ll < LONG_MIN) {
1086  m_dtype = __TLONGLONG;
1087  m_value_dtype = new long long(value_ll);
1088  }
1089  else if (value_ll > SHRT_MAX || value_ll < SHRT_MIN) {
1090  m_dtype = __TLONG;
1091  m_value_dtype = new long(value_ll);
1092  }
1093  else {
1094  m_dtype = __TSHORT;
1095  m_value_dtype = new short(value_ll);
1096  }
1097  }
1098  } // endif: handled integers
1099 
1100  // ... otherwise handle floats
1101  else {
1102  if (value_dbl > FLT_MAX || value_dbl < FLT_MIN) {
1103  m_dtype = __TDOUBLE;
1104  m_value_dtype = new double(value_dbl);
1105  }
1106  else {
1107  m_dtype = __TFLOAT;
1108  m_value_dtype = new float(value_dbl);
1109  }
1110  }
1111 
1112  } while(0);
1113 
1114  // Return
1115  return;
1116 }
1117 
1118 
1119 /***********************************************************************//**
1120  * @brief Read header card from FITS file
1121  *
1122  * @param[in] vptr FITS file void pointer.
1123  * @param[in] keynum Number of the header card.
1124  ***************************************************************************/
1125 void GFitsHeaderCard::read(void* vptr, const int& keynum)
1126 {
1127  // Initialise status
1128  int status = 0;
1129 
1130  // Move to HDU
1132 
1133  // Read keyword
1134  char keyname[80];
1135  char value[80];
1136  char comment[80];
1137  status = __ffgkyn(FPTR(vptr), keynum, keyname, value, comment, &status);
1138  if (status != 0) {
1139  throw GException::fits_error(G_READ_NUM, status);
1140  }
1141 
1142  // Store result
1143  m_keyname.assign(keyname);
1144  m_value.assign(value);
1145  m_comment.assign(comment);
1146 
1147  // Determine card type
1148  set_dtype(m_value);
1149 
1150  // Return
1151  return;
1152 }
1153 
1154 
1155 /***********************************************************************//**
1156  * @brief Read header card from FITS file
1157  *
1158  * @param[in] vptr FITS file void pointer.
1159  * @param[in] keyname Name of the header card.
1160  *
1161  * @exception GException::invalid_value
1162  * Specified @p keyname not found in FITS header.
1163  * @exception GException::fits_error
1164  * cfitsio error occured.
1165  ***************************************************************************/
1166 void GFitsHeaderCard::read(void* vptr, const std::string& keyname)
1167 {
1168  // Initialise FITS status
1169  int status = 0;
1170 
1171  // Move to HDU
1173 
1174  // Read keyword
1175  char value[80];
1176  char comment[80];
1177  status = __ffgkey(FPTR(vptr), (char*)keyname.c_str(), value, comment,
1178  &status);
1179 
1180  // Catch error
1181  if (status == 202) { // Keyword not found
1182  std::string msg = "Header card with keyword \""+keyname+"\" not"
1183  " found in FITS header (status=202).";
1185  }
1186  else if (status != 0) { // Any other error
1187  std::string msg = "Unable to read keyword \""+keyname+"\" from"
1188  " FITS extension "+
1189  gammalib::str((FPTR(vptr)->HDUposition))+
1190  " header.";
1191  throw GException::fits_error(G_READ_STR, status, msg);
1192  }
1193 
1194  // Store result
1195  m_keyname = keyname;
1196  m_value.assign(value);
1197  m_comment.assign(comment);
1198 
1199  // Determine card type
1200  set_dtype(m_value);
1201 
1202  // Return
1203  return;
1204 }
1205 
1206 
1207 /***********************************************************************//**
1208  * @brief Write header card
1209  *
1210  * @param[in] vptr FITS file void pointer.
1211  *
1212  * Writes any kind of header card to a FITS file.
1213  ***************************************************************************/
1214 void GFitsHeaderCard::write(void* vptr) const
1215 {
1216  // Initialise status
1217  int status = 0;
1218 
1219  // Move to HDU
1221 
1222  // If card is comment then write comment
1223  if (m_keyname == "COMMENT") {
1224  if (m_comment_write) {
1225  status = __ffpcom(FPTR(vptr), (char*)m_comment.c_str(), &status);
1226  }
1227  }
1228 
1229  // If card is history then write history
1230  else if (m_keyname == "HISTORY") {
1231  if (m_comment_write) {
1232  status = __ffphis(FPTR(vptr), (char*)m_comment.c_str(), &status);
1233  }
1234  }
1235 
1236  // If card is BLANKFIELD (empty keyword) then write empty line
1237  else if (m_keyname == "") {
1238  if (m_comment_write) {
1239  status = __ffprec(FPTR(vptr), "", &status);
1240  }
1241  }
1242 
1243  // If card holds a native data type then write it
1244  else if (m_value_dtype != NULL) {
1245  switch (m_dtype) {
1246  case __TLOGICAL:
1247  {
1248  int value = (*((bool*)m_value_dtype)) ? 1 : 0;
1249  status = __ffukyl(FPTR(vptr), (char*)m_keyname.c_str(), value,
1250  (char*)m_comment.c_str(), &status);
1251  }
1252  break;
1253  case __TSTRING:
1254  status = __ffukys(FPTR(vptr), (char*)m_keyname.c_str(),
1255  (char*)((std::string*)m_value_dtype)->c_str(),
1256  (char*)m_comment.c_str(), &status);
1257  break;
1258  case __TFLOAT:
1259  status = __ffukye(FPTR(vptr), (char*)m_keyname.c_str(),
1260  *((float*)m_value_dtype), decimals(),
1261  (char*)m_comment.c_str(), &status);
1262  break;
1263  case __TDOUBLE:
1264  status = __ffukyd(FPTR(vptr), (char*)m_keyname.c_str(),
1265  *((double*)m_value_dtype), decimals(),
1266  (char*)m_comment.c_str(), &status);
1267  break;
1268  default:
1269  status = __ffuky(FPTR(vptr), m_dtype, (char*)m_keyname.c_str(),
1270  m_value_dtype, (char*)m_comment.c_str(), &status);
1271  break;
1272  }
1273  } // endif: had native data type
1274 
1275  // ... otherwise if card holds a NULL value then write it
1276  else if (m_dtype == __TNULL) {
1277  status = __ffukyu(FPTR(vptr), (char*)m_keyname.c_str(),
1278  (char*)m_comment.c_str(), &status);
1279  }
1280 
1281  // ... capture all other stuff
1282  else {
1283  std::string msg = "The code should never arrive at this point!\n"
1284  "The keyname \""+m_keyname+"\" is neither"
1285  " \"COMMENT\" nor \"HISTRORY\" but it has a"
1286  " NULL data type value and a data type of"
1287  " "+gammalib::str(m_dtype)+".\n"
1288  "Maybe an invalid FITS header card has been"
1289  " encountered in reading a file?";
1290  gammalib::warning(G_WRITE, msg);
1291  }
1292 
1293  // Throw exception in case of a FITS error
1294  if (status != 0) {
1295  throw GException::fits_error(G_WRITE, status);
1296  }
1297 
1298  // Return
1299  return;
1300 }
#define __TINT
#define __TUSHORT
void * m_value_dtype
Value in native data type.
#define __TULONG
#define __TLOGICAL
std::string string(void) const
Return header card value as string.
#define FPTR(A)
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition: GTools.cpp:1386
#define __ffukyl(A, B, C, D, E)
int m_dtype
Native data type.
GFitsHeaderCard(void)
Void constructor.
const std::string & keyname(void) const
Return header card keyname.
void copy_dtype(const GFitsHeaderCard &card)
Copy dtype.
GFitsHeaderCard * clone(void) const
Clone header card.
void copy_members(const GFitsHeaderCard &card)
Copy class members.
void free_dtype(void)
Free dtype.
#define __TDOUBLE
std::string print(const GChatter &chatter=NORMAL) const
Print header card information.
Gammalib tools definition.
FITS file class interface definition.
bool m_comment_write
Signals that comment should be written.
#define __ffgkey(A, B, C, D, E)
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition: GTools.cpp:80
FITS header card class definition.
std::string m_value
Value of the card as read from file.
#define G_FREE_DTYPE
#define __TDBLCOMPLEX
const int & decimals(void) const
Return header card decimals.
GFitsHeaderCard & operator=(const GFitsHeaderCard &card)
Assignment operator.
#define __TBYTE
#define __ffuky(A, B, C, D, E, F)
Implements FITS header card interface.
std::string right(const std::string &s, const int &n, const char &c= ' ')
Right justify string to achieve a length of n characters.
Definition: GTools.cpp:1094
#define G_WRITE
std::string m_comment
Card comment.
#define __ffukye(A, B, C, D, E, F)
#define __TBIT
#define __TCOMPLEX
#define __ffukys(A, B, C, D, E)
#define __TSHORT
CFITSIO interface header.
std::string left(const std::string &s, const int &n, const char &c= ' ')
Left justify string to achieve a length of n characters.
Definition: GTools.cpp:1070
#define __ffphis(A, B, C)
const std::string & comment(void) const
Return header card comment.
void set_dtype(const std::string &value)
Set native data type from card string.
#define __TUINT
GChatter
Definition: GTypemaps.hpp:33
#define __TLONG
void read(void *vptr, const int &keynum)
Read header card from FITS file.
#define __ffukyd(A, B, C, D, E, F)
#define __TFLOAT
void write(void *fptr) const
Write header card.
unsigned long long toulonglong(const std::string &arg)
Convert string into unsigned long long value.
Definition: GTools.cpp:896
#define __ffukyu(A, B, C, D)
#define __ffpcom(A, B, C)
long long tolonglong(const std::string &arg)
Convert string into long long value.
Definition: GTools.cpp:881
double real(void) const
Return header card value as double precision.
#define __TLONGLONG
#define __ffprec(A, B, C)
void clear(void)
Clear header card.
void free_members(void)
Delete class members.
#define G_COPY_DTYPE
Exception handler interface definition.
#define __TSBYTE
const std::string & value(void) const
Return header card value.
int m_value_decimals
Decimals of value (for float)
#define __ffgkyn(A, B, C, D, E, F)
int toint(const std::string &arg)
Convert string into integer value.
Definition: GTools.cpp:821
std::string m_keyname
Name of the card.
int fits_move_to_hdu(const std::string &caller, void *vptr, const int &hdunum=0)
Move to FITS extension.
Definition: GFits.cpp:1774
#define G_READ_STR
int integer(void) const
Return header card value as integer.
#define G_READ_NUM
void set_members(const std::string &keyname, const std::string &value, const std::string &unit, const std::string &comment)
Set card members.
#define __TNULL
#define __TSTRING
std::string m_unit
Unit of the card value.
double todouble(const std::string &arg)
Convert string into double precision value.
Definition: GTools.cpp:926
virtual ~GFitsHeaderCard(void)
Destructor.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489
void init_members(void)
Initialise class members.