GammaLib  2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GTimeReference.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GTimeReference.cpp - Time reference class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2012-2021 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 GTimeReference.cpp
23  * @brief Time reference class interface implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include "GTimeReference.hpp"
32 #include "GTools.hpp"
33 #include "GException.hpp"
34 #include "GFitsHDU.hpp"
35 #include "GXmlElement.hpp"
36 
37 /* __ Constants __________________________________________________________ */
38 
39 /* __ Method name definitions ____________________________________________ */
40 #define G_READ "GTimeReference::read(GFitsHDU&)"
41 #define G_READ_XML "GTimeReference::read(GXmlElement&)"
42 #define G_WRITE_XML "GTimeReference::write(GXmlElement&)"
43 #define G_SET "GTimeReference::set(double&, std::string&, std::string&, "\
44  "std::string&)"
45 
46 /* __ Macros _____________________________________________________________ */
47 
48 /* __ Coding definitions _________________________________________________ */
49 
50 /* __ Debug definitions __________________________________________________ */
51 
52 
53 /*==========================================================================
54  = =
55  = Constructors/destructors =
56  = =
57  ==========================================================================*/
58 
59 /***********************************************************************//**
60  * @brief Void constructor
61  ***************************************************************************/
63 {
64  // Initialise private members
65  init_members();
66 
67  // Return
68  return;
69 }
70 
71 
72 /***********************************************************************//**
73  * @brief Copy constructor
74  *
75  * @param[in] ref Time reference.
76  ***************************************************************************/
78 {
79  // Initialise private members
80  init_members();
81 
82  // Copy members
83  copy_members(ref);
84 
85  // Return
86  return;
87 }
88 
89 
90 /***********************************************************************//**
91  * @brief Time reference constructor
92  *
93  * @param[in] mjdref Reference MJD (days).
94  * @param[in] timeunit Time unit ("sec(s)", "day(s)").
95  * @param[in] timesys Time system (ignored so far).
96  * @param[in] timeref Time reference (ignored so far).
97  *
98  * Sets the time reference from a MJD reference day, a time unit, a time
99  * system and a time reference.
100  ***************************************************************************/
101 GTimeReference::GTimeReference(const double& mjdref,
102  const std::string& timeunit,
103  const std::string& timesys,
104  const std::string& timeref)
105 {
106  // Initialise private members
107  init_members();
108 
109  // Set time reference
110  set(mjdref, timeunit, timesys, timeref);
111 
112  // Return
113  return;
114 }
115 
116 
117 /***********************************************************************//**
118  * @brief Time reference constructor
119  *
120  * @param[in] mjdrefi Integer part of reference MJD (days).
121  * @param[in] mjdreff Fractional part of reference MJD (days).
122  * @param[in] timeunit Time unit (sec, days).
123  * @param[in] timesys Time system (TT).
124  * @param[in] timeref Local time reference.
125  *
126  * Sets the time reference from a MJD reference day (specified by an integer
127  * and a fractional part), a time unit, a time system and a time reference.
128  ***************************************************************************/
130  const double& mjdreff,
131  const std::string& timeunit,
132  const std::string& timesys,
133  const std::string& timeref)
134 {
135  // Initialise private members
136  init_members();
137 
138  // Set time reference
139  set(mjdrefi, mjdreff, timeunit, timesys, timeref);
140 
141  // Return
142  return;
143 }
144 
145 
146 /***********************************************************************//**
147  * @brief FITS header constructor
148  *
149  * @param[in] hdu FITS extension.
150  *
151  * Constructs time reference from the information found in the FITS header.
152  * See GTimeReference::read for more information on the expected format.
153  ***************************************************************************/
155 {
156  // Initialise private members
157  init_members();
158 
159  // Read reference from FITS header
160  read(hdu);
161 
162  // Return
163  return;
164 }
165 
166 
167 /***********************************************************************//**
168  * @brief Destructor
169  ***************************************************************************/
171 {
172  // Free members
173  free_members();
174 
175  // Return
176  return;
177 }
178 
179 
180 /*==========================================================================
181  = =
182  = Operators =
183  = =
184  ==========================================================================*/
185 
186 /***********************************************************************//**
187  * @brief Assignment operator
188  *
189  * @param[in] ref Time reference.
190  ***************************************************************************/
192 {
193  // Execute only if object is not identical
194  if (this != &ref) {
195 
196  // Free members
197  free_members();
198 
199  // Initialise private members
200  init_members();
201 
202  // Copy members
203  copy_members(ref);
204 
205  } // endif: object was not identical
206 
207  // Return
208  return *this;
209 }
210 
211 
212 /*==========================================================================
213  = =
214  = Public methods =
215  = =
216  ==========================================================================*/
217 
218 /***********************************************************************//**
219  * @brief Clear time reference
220  ***************************************************************************/
222 {
223  // Free members
224  free_members();
225 
226  // Initialise members
227  init_members();
228 
229  // Return
230  return;
231 }
232 
233 
234 /***********************************************************************//**
235  * @brief Clone object
236  *
237  * @return Pointer to deep copy of time reference.
238  ***************************************************************************/
240 {
241  // Clone this image
242  return new GTimeReference(*this);
243 }
244 
245 
246 /***********************************************************************//**
247  * @brief Read time reference from FITS header
248  *
249  * @param[in] hdu FITS extension.
250  *
251  * GException::invalid_value
252  * No valid reference MJD found in header.
253  *
254  * Reads the time reference information from a FITS header. The method
255  * requires either the keyword "MJDREF" or the pair of keywords "MJDREFI"
256  * and "MJDREFF" to be set. The following keywords are optional (the
257  * assumed default values in absent of the keywords is given in parentheses):
258  *
259  * TIMEUNIT ("s")
260  * TIMESYS ("TT")
261  * TIMEREF ("LOCAL")
262  *
263  ***************************************************************************/
265 {
266  // Get reference MJD
267  double mjdref = (hdu.has_card("MJDREF")) ? hdu.real("MJDREF") : 0.0;
268  int mjdrefi = (hdu.has_card("MJDREFI")) ? hdu.integer("MJDREFI") : 0;
269  double mjdreff = (hdu.has_card("MJDREFF")) ? hdu.real("MJDREFF") : 0.0;
270 
271  // Get remaining keywords. To accept a large variety of FITS headers,
272  // all keywords are optionally.
273  std::string timeunit = (hdu.has_card("TIMEUNIT")) ? hdu.string("TIMEUNIT") : "s";
274  std::string timesys = (hdu.has_card("TIMESYS")) ? hdu.string("TIMESYS") : "TT";
275  std::string timeref = (hdu.has_card("TIMEREF")) ? hdu.string("TIMEREF") : "LOCAL";
276 
277  // Set time reference
278  if (hdu.has_card("MJDREF")) {
279  set(mjdref, timeunit, timesys, timeref);
280  }
281  else if (hdu.has_card("MJDREFI") && hdu.has_card("MJDREFF")) {
282  set(mjdrefi, mjdreff, timeunit, timesys, timeref);
283  }
284  else {
285  std::string msg = "No valid time reference keywords found in FITS "
286  "header. The FITS header must contain either the "
287  "keyword \"MJDREF\" or the keyword pair"
288  " \"MJDREFI\" and \"MJDREFF\".";
289  throw GException::invalid_value(G_READ, msg);
290  }
291 
292  // Return
293  return;
294 }
295 
296 
297 /***********************************************************************//**
298  * @brief Write time reference into FITS header
299  *
300  * @param[in] hdu FITS extension.
301  *
302  * Writes or updates the time reference information in a FITS header.
303  * Depending of whether the keyword "MJDREF" or the pair of keywords "MJDREFI"
304  * and "MJDREFF" exist already in the header, the method either writes the
305  * reference MJD as floating point value, or split into an integer and a
306  * fractional part. If nothing has been written yet, splitting into an
307  * integer and fractional part will be used as this preserves the highest
308  * possible accuracy.
309  *
310  * The following additional keywords are written:
311  * TIMEUNIT
312  * TIMESYS
313  * TIMEREF
314  *
315  ***************************************************************************/
317 {
318  // Case A: use floating point reference MJD
319  if (hdu.has_card("MJDREF")) {
320  hdu.card("MJDREF", mjdref(), "[days] Time reference MJD");
321  hdu.card("TIMEUNIT", timeunit(), "Time unit");
322  hdu.card("TIMESYS", timesys(), "Time system");
323  hdu.card("TIMEREF", timeref(), "Time reference");
324  }
325 
326  // Case B: use fractional reference MJD
327  else {
328  hdu.card("MJDREFI", mjdrefi(), "[days] Integer part of time reference MJD");
329  hdu.card("MJDREFF", mjdreff(), "[days] Fractional part of time reference MJD");
330  hdu.card("TIMEUNIT", timeunit(), "Time unit");
331  hdu.card("TIMESYS", timesys(), "Time system");
332  hdu.card("TIMEREF", timeref(), "Time reference");
333  }
334 
335  // Return
336  return;
337 }
338 
339 
340 /***********************************************************************//**
341  * @brief Read time reference from XML element
342  *
343  * @param[in] xml XML element.
344  *
345  * @exception GException::invalid_value
346  * Invalid XML format encountered.
347  *
348  * Reads the time reference from an XML element. The format of the time
349  * reference is
350  *
351  * <parameter name="TimeReference" mjdrefi="..." mjdreff="..."
352  * timeunit="..." timesys="..." timeref="..."/>
353  *
354  ***************************************************************************/
356 {
357  // Clear time reference
358  clear();
359 
360  // Get time reference parameter
361  const GXmlElement* par = gammalib::xml_get_par(G_READ_XML, xml, "TimeReference");
362 
363  // Initialise reference values
364  int mjdrefi;
365  double mjdreff;
366  std::string timeunit;
367  std::string timesys;
368  std::string timeref;
369 
370  // Extract attributes
371  if (par->has_attribute("mjdrefi")) {
372  mjdrefi = gammalib::toint(par->attribute("mjdrefi"));
373  }
374  else {
375  std::string msg = "Attribute \"mjdrefi\" not found in XML parameter"
376  " \"TimeReference\"."
377  " Please verify the XML format.";
379  }
380  if (par->has_attribute("mjdreff")) {
381  mjdreff = gammalib::todouble(par->attribute("mjdreff"));
382  }
383  else {
384  std::string msg = "Attribute \"mjdreff\" not found in XML parameter"
385  " \"TimeReference\"."
386  " Please verify the XML format.";
388  }
389  if (par->has_attribute("timeunit")) {
390  timeunit = par->attribute("timeunit");
391  }
392  else {
393  std::string msg = "Attribute \"timeunit\" not found in XML parameter"
394  " \"TimeReference\"."
395  " Please verify the XML format.";
397  }
398  if (par->has_attribute("timesys")) {
399  timesys = par->attribute("timesys");
400  }
401  else {
402  std::string msg = "Attribute \"timesys\" not found in XML parameter"
403  " \"TimeReference\"."
404  " Please verify the XML format.";
406  }
407  if (par->has_attribute("timeref")) {
408  timeref = par->attribute("timeref");
409  }
410  else {
411  std::string msg = "Attribute \"timeref\" not found in XML parameter"
412  " \"TimeReference\"."
413  " Please verify the XML format.";
415  }
416 
417  // Set time reference
418  set(mjdrefi, mjdreff, timeunit, timesys, timeref);
419 
420  // Return
421  return;
422 }
423 
424 
425 /***********************************************************************//**
426  * @brief Write time reference into XML element
427  *
428  * @param[in] xml XML element.
429  *
430  * Writes the time reference into an XML element. The format of the time
431  * reference is
432  *
433  * <parameter name="TimeReference" mjdrefi="..." mjdreff="..."
434  * timeunit="..." timesys="..." timeref="..."/>
435  *
436  ***************************************************************************/
438 {
439  // Get parameter
440  GXmlElement* par = gammalib::xml_need_par(G_WRITE_XML, xml, "TimeReference");
441 
442  // Write time reference
443  par->attribute("mjdrefi", gammalib::str(mjdrefi()));
444  par->attribute("mjdreff", gammalib::str(mjdreff()));
445  par->attribute("timeunit", timeunit());
446  par->attribute("timesys", timesys());
447  par->attribute("timeref", timeref());
448 
449  // Return
450  return;
451 }
452 
453 
454 /***********************************************************************//**
455  * @brief Set time reference
456  *
457  * @param[in] mjdref Reference MJD (days).
458  * @param[in] timeunit Time unit ("s", "d", "sec(s)", "day(s)").
459  * @param[in] timesys Time system.
460  * @param[in] timeref Time reference.
461  *
462  * @exception GException::invalid_argument
463  * Invalid time unit specified.
464  *
465  * Sets the time reference from a MJD reference day, a time unit, a time
466  * system and a time reference.
467  *
468  * @todo Implement checking of "timesys" and "timeref" parameters.
469  ***************************************************************************/
470 void GTimeReference::set(const double& mjdref,
471  const std::string& timeunit,
472  const std::string& timesys,
473  const std::string& timeref)
474 {
475  // Check timeunit string
476  std::string ltimeunit = gammalib::tolower(timeunit);
477  if (ltimeunit == "d" || ltimeunit == "day" || ltimeunit == "days") {
478  m_unit_sec = false;
479  }
480  else if (ltimeunit == "s" || ltimeunit == "sec" || ltimeunit == "secs") {
481  m_unit_sec = true;
482  }
483  else {
484  std::string msg = "Invalid time unit \""+timeunit+"\" specified. "
485  "Please specify one of \"d\", \"day\", \"days\", "
486  "\"s\", \"sec\" or \"secs\"";
488  }
489 
490  // Set members
491  m_mjdref = mjdref;
492  m_timeunit = ltimeunit;
493  m_timesys = gammalib::toupper(timesys);
494  m_timeref = gammalib::toupper(timeref);
495 
496  // Return
497  return;
498 }
499 
500 
501 /***********************************************************************//**
502  * @brief Set time reference
503  *
504  * @param[in] mjdrefi Integer part of reference MJD (days).
505  * @param[in] mjdreff Fractional part of reference MJD (days).
506  * @param[in] timeunit Time unit (sec, days).
507  * @param[in] timesys Time system (TT).
508  * @param[in] timeref Local time reference.
509  *
510  * Sets the time reference from a MJD reference day (specified by an integer
511  * and a fractional part), a time unit, a time system and a time reference.
512  ***************************************************************************/
513 void GTimeReference::set(const int& mjdrefi,
514  const double& mjdreff,
515  const std::string& timeunit,
516  const std::string& timesys,
517  const std::string& timeref)
518 {
519  // Compute reference MJD
520  double mjdref = double(mjdrefi) + mjdreff;
521 
522  // Set time
523  set(mjdref, timeunit, timesys, timeref);
524 
525  // Return
526  return;
527 }
528 
529 
530 /***********************************************************************//**
531  * @brief Return MJD reference (units: days)
532  *
533  * @return Modified Julian reference day (days).
534  *
535  * Returns the Modified Julian reference day.
536  ***************************************************************************/
537 const double& GTimeReference::mjdref(void) const
538 {
539  // Return MDJ reference
540  return m_mjdref;
541 }
542 
543 
544 /***********************************************************************//**
545  * @brief Returns integer part of MJD reference (units: days)
546  *
547  * @return Integer part of Modified Julian reference day (days).
548  *
549  * Returns the integer part of the Modified Julian reference day.
550  ***************************************************************************/
551 int GTimeReference::mjdrefi(void) const
552 {
553  // Return integer part of MJD reference
554  return int(m_mjdref);
555 }
556 
557 
558 /***********************************************************************//**
559  * @brief Returns fractional part of MJD reference (units: days)
560  *
561  * @return Fractional part of Modified Julian reference day (days).
562  *
563  * Returns the fractional part of the Modified Julian reference day.
564  ***************************************************************************/
565 double GTimeReference::mjdreff(void) const
566 {
567  // Return fractional part of MJD reference
568  return (m_mjdref-double(mjdrefi()));
569 }
570 
571 
572 /***********************************************************************//**
573  * @brief Return time unit
574  *
575  * @return Time unit.
576  *
577  * Returns the reference time unit.
578  ***************************************************************************/
579 const std::string& GTimeReference::timeunit(void) const
580 {
581  // Return time unit
582  return m_timeunit;
583 }
584 
585 
586 /***********************************************************************//**
587  * @brief Return time system
588  *
589  * @return Time system.
590  *
591  * Returns the reference time system.
592  ***************************************************************************/
593 const std::string& GTimeReference::timesys(void) const
594 {
595  // Return time system
596  return m_timesys;
597 }
598 
599 
600 /***********************************************************************//**
601  * @brief Return time reference
602  *
603  * @return Time reference.
604  *
605  * Returns the reference time reference.
606  ***************************************************************************/
607 const std::string& GTimeReference::timeref(void) const
608 {
609  // Return time reference
610  return m_timeref;
611 }
612 
613 
614 /***********************************************************************//**
615  * @brief Return the time unit in seconds
616  *
617  * @return Time unit in seconds.
618  *
619  * Returns 1 if the time using is in seconds and 86400 if the time unit is
620  * in days.
621  ***************************************************************************/
622 double GTimeReference::unitseconds(void) const
623 {
624  // Set time unit in seconds
625  double unit = (m_unit_sec) ? 1.0 : gammalib::sec_in_day;
626 
627  // Return time unit
628  return unit;
629 }
630 
631 
632 /***********************************************************************//**
633  * @brief Print time reference
634  *
635  * @param[in] chatter Chattiness (defaults to NORMAL).
636  * @return String containing the time reference.
637  ***************************************************************************/
638 std::string GTimeReference::print(const GChatter& chatter) const
639 {
640  // Initialise result string
641  std::string result;
642 
643  // Continue only if chatter is not silent
644  if (chatter != SILENT) {
645 
646  // Append header
647  result.append("=== GTimeReference ===");
648 
649  // Append information
650  result.append("\n"+gammalib::parformat("MJD reference time"));
651  result.append(gammalib::str(mjdref()));
652  result.append("\n"+gammalib::parformat("Time unit")+timeunit());
653  result.append("\n"+gammalib::parformat("Time system")+timesys());
654  result.append("\n"+gammalib::parformat("Time reference")+timeref());
655 
656  } // endif: chatter was not silent
657 
658  // Return
659  return result;
660 }
661 
662 
663 /*==========================================================================
664  = =
665  = Private methods =
666  = =
667  ==========================================================================*/
668 
669 /***********************************************************************//**
670  * @brief Initialise class members
671  ***************************************************************************/
673 {
674  // Initialise members
675  m_mjdref = 0.0;
676  m_timeunit = "secs";
677  m_timesys = "TT";
678  m_timeref = "LOCAL";
679  m_unit_sec = true;
680 
681  // Return
682  return;
683 }
684 
685 
686 /***********************************************************************//**
687  * @brief Copy class members
688  *
689  * @param[in] ref Time reference.
690  ***************************************************************************/
692 {
693  // Copy members
694  m_mjdref = ref.m_mjdref;
695  m_timeunit = ref.m_timeunit;
696  m_timesys = ref.m_timesys;
697  m_timeref = ref.m_timeref;
698  m_unit_sec = ref.m_unit_sec;
699 
700  // Return
701  return;
702 }
703 
704 
705 /***********************************************************************//**
706  * @brief Delete class members
707  ***************************************************************************/
709 {
710  // Return
711  return;
712 }
void clear(void)
Clear time reference.
std::string m_timeunit
Time unit.
GTimeReference(void)
Void constructor.
double mjdreff(void) const
Returns fractional part of MJD reference (units: days)
bool has_card(const int &cardno) const
Check existence of header card.
Definition: GFitsHDU.hpp:233
const std::string & timeunit(void) const
Return time unit.
XML element node class interface definition.
void write(GFitsHDU &hdu) const
Write time reference into FITS header.
int mjdrefi(void) const
Returns integer part of MJD reference (units: days)
Abstract FITS extension base class.
Definition: GFitsHDU.hpp:51
double m_mjdref
Time MJD reference (days)
void read(const GFitsHDU &hdu)
Read time reference from FITS header.
void free_members(void)
Delete class members.
XML element node class.
Definition: GXmlElement.hpp:48
double unitseconds(void) const
Return the time unit in seconds.
Gammalib tools definition.
GTimeReference & operator=(const GTimeReference &ref)
Assignment operator.
Abstract FITS extension base class definition.
const double sec_in_day
Definition: GTools.hpp:49
double real(const std::string &keyname) const
Return card value as double precision.
Definition: GFitsHDU.hpp:423
const double & mjdref(void) const
Return MJD reference (units: days)
const GXmlAttribute * attribute(const int &index) const
Return attribute.
#define G_READ
bool has_attribute(const std::string &name) const
Check if element has a given attribute.
Time reference class interface definition.
GXmlElement * xml_need_par(const std::string &origin, GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition: GTools.cpp:1637
const std::string & timesys(void) const
Return time system.
void copy_members(const GTimeReference &ref)
Copy class members.
GChatter
Definition: GTypemaps.hpp:33
virtual ~GTimeReference(void)
Destructor.
int integer(const std::string &keyname) const
Return card value as integer.
Definition: GFitsHDU.hpp:436
const std::string & timeref(void) const
Return time reference.
#define G_READ_XML
#define G_SET
std::string print(const GChatter &chatter=NORMAL) const
Print time reference.
void set(const double &mrdref, const std::string &timeunit, const std::string &timesys="TT", const std::string &timeref="LOCAL")
Set time reference.
std::string string(const std::string &keyname) const
Return card value as string.
Definition: GFitsHDU.hpp:410
Exception handler interface definition.
GTimeReference * clone(void) const
Clone object.
std::string toupper(const std::string &s)
Convert string to upper case.
Definition: GTools.cpp:941
Implements a time reference.
std::string tolower(const std::string &s)
Convert string to lower case.
Definition: GTools.cpp:955
int toint(const std::string &arg)
Convert string into integer value.
Definition: GTools.cpp:821
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
std::string m_timeref
Time reference.
GFitsHeaderCard & card(const int &cardno)
Return header card.
Definition: GFitsHDU.hpp:259
const GXmlElement * xml_get_par(const std::string &origin, const GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition: GTools.cpp:1689
std::string m_timesys
Time system.
#define G_WRITE_XML
void init_members(void)
Initialise class members.
double todouble(const std::string &arg)
Convert string into double precision value.
Definition: GTools.cpp:926
bool m_unit_sec
True: unit is seconds, False: unit is days.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489