GammaLib  1.7.0.dev
 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-2015 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::no_valid_time_ref
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 {
286  "Require either keyword \"MJDREF\" or keyword pair"
287  " \"MJDREFI\" and \"MJDREFF\".");
288  }
289 
290  // Return
291  return;
292 }
293 
294 
295 /***********************************************************************//**
296  * @brief Write time reference into FITS header
297  *
298  * @param[in] hdu FITS extension.
299  *
300  * Writes or updates the time reference information in a FITS header.
301  * Depending of whether the keyword "MJDREF" or the pair of keywords "MJDREFI"
302  * and "MJDREFF" exist already in the header, the method either writes the
303  * reference MJD as floating point value, or split into an integer and a
304  * fractional part. If nothing has been written yet, splitting into an
305  * integer and fractional part will be used as this preserves the highest
306  * possible accuracy.
307  *
308  * The following additional keywords are written:
309  * TIMEUNIT
310  * TIMESYS
311  * TIMEREF
312  *
313  ***************************************************************************/
315 {
316  // Case A: use floating point reference MJD
317  if (hdu.has_card("MJDREF")) {
318  hdu.card("MJDREF", mjdref(), "[days] Time reference MJD");
319  hdu.card("TIMEUNIT", timeunit(), "Time unit");
320  hdu.card("TIMESYS", timesys(), "Time system");
321  hdu.card("TIMEREF", timeref(), "Time reference");
322  }
323 
324  // Case B: use fractional reference MJD
325  else {
326  hdu.card("MJDREFI", mjdrefi(), "[days] Integer part of time reference MJD");
327  hdu.card("MJDREFF", mjdreff(), "[days] Fractional part of time reference MJD");
328  hdu.card("TIMEUNIT", timeunit(), "Time unit");
329  hdu.card("TIMESYS", timesys(), "Time system");
330  hdu.card("TIMEREF", timeref(), "Time reference");
331  }
332 
333  // Return
334  return;
335 }
336 
337 
338 /***********************************************************************//**
339  * @brief Read time reference from XML element
340  *
341  * @param[in] xml XML element.
342  *
343  * @exception GException::invalid_value
344  * Invalid XML format encountered.
345  *
346  * Reads the time reference from an XML element. The format of the time
347  * reference is
348  *
349  * <parameter name="TimeReference" mjdrefi="..." mjdreff="..."
350  * timeunit="..." timesys="..." timeref="..."/>
351  *
352  ***************************************************************************/
354 {
355  // Clear time reference
356  clear();
357 
358  // Get time reference parameter
359  const GXmlElement* par = gammalib::xml_get_par(G_READ_XML, xml, "TimeReference");
360 
361  // Initialise reference values
362  int mjdrefi;
363  double mjdreff;
364  std::string timeunit;
365  std::string timesys;
366  std::string timeref;
367 
368  // Extract attributes
369  if (par->has_attribute("mjdrefi")) {
370  mjdrefi = gammalib::toint(par->attribute("mjdrefi"));
371  }
372  else {
373  std::string msg = "Attribute \"mjdrefi\" not found in XML parameter"
374  " \"TimeReference\"."
375  " Please verify the XML format.";
377  }
378  if (par->has_attribute("mjdreff")) {
379  mjdreff = gammalib::todouble(par->attribute("mjdreff"));
380  }
381  else {
382  std::string msg = "Attribute \"mjdreff\" not found in XML parameter"
383  " \"TimeReference\"."
384  " Please verify the XML format.";
386  }
387  if (par->has_attribute("timeunit")) {
388  timeunit = par->attribute("timeunit");
389  }
390  else {
391  std::string msg = "Attribute \"timeunit\" not found in XML parameter"
392  " \"TimeReference\"."
393  " Please verify the XML format.";
395  }
396  if (par->has_attribute("timesys")) {
397  timesys = par->attribute("timesys");
398  }
399  else {
400  std::string msg = "Attribute \"timesys\" not found in XML parameter"
401  " \"TimeReference\"."
402  " Please verify the XML format.";
404  }
405  if (par->has_attribute("timeref")) {
406  timeref = par->attribute("timeref");
407  }
408  else {
409  std::string msg = "Attribute \"timeref\" not found in XML parameter"
410  " \"TimeReference\"."
411  " Please verify the XML format.";
413  }
414 
415  // Set time reference
416  set(mjdrefi, mjdreff, timeunit, timesys, timeref);
417 
418  // Return
419  return;
420 }
421 
422 
423 /***********************************************************************//**
424  * @brief Write time reference into XML element
425  *
426  * @param[in] xml XML element.
427  *
428  * Writes the time reference into an XML element. The format of the time
429  * reference is
430  *
431  * <parameter name="TimeReference" mjdrefi="..." mjdreff="..."
432  * timeunit="..." timesys="..." timeref="..."/>
433  *
434  ***************************************************************************/
436 {
437  // Get parameter
438  GXmlElement* par = gammalib::xml_need_par(G_WRITE_XML, xml, "TimeReference");
439 
440  // Write time reference
441  par->attribute("mjdrefi", gammalib::str(mjdrefi()));
442  par->attribute("mjdreff", gammalib::str(mjdreff()));
443  par->attribute("timeunit", timeunit());
444  par->attribute("timesys", timesys());
445  par->attribute("timeref", timeref());
446 
447  // Return
448  return;
449 }
450 
451 
452 /***********************************************************************//**
453  * @brief Set time reference
454  *
455  * @param[in] mjdref Reference MJD (days).
456  * @param[in] timeunit Time unit ("s", "d", "sec(s)", "day(s)").
457  * @param[in] timesys Time system.
458  * @param[in] timeref Time reference.
459  *
460  * @exception GException::time_invalid_unit
461  * Invalid time unit specified.
462  *
463  * Sets the time reference from a MJD reference day, a time unit, a time
464  * system and a time reference.
465  *
466  * @todo Implement checking of "timesys" and "timeref" parameters.
467  ***************************************************************************/
468 void GTimeReference::set(const double& mjdref,
469  const std::string& timeunit,
470  const std::string& timesys,
471  const std::string& timeref)
472 {
473  // Check timeunit string
474  std::string ltimeunit = gammalib::tolower(timeunit);
475  if (ltimeunit == "d" || ltimeunit == "day" || ltimeunit == "days") {
476  m_unit_sec = false;
477  }
478  else if (ltimeunit == "s" || ltimeunit == "sec" || ltimeunit == "secs") {
479  m_unit_sec = true;
480  }
481  else {
482  throw GException::time_invalid_unit(G_SET, timeunit,
483  "Valid timeunit values are: \"d\", \"day\", \"days\","
484  " \"s\", \"sec\" or \"secs\"");
485  }
486 
487  // Set members
488  m_mjdref = mjdref;
489  m_timeunit = ltimeunit;
490  m_timesys = gammalib::toupper(timesys);
491  m_timeref = gammalib::toupper(timeref);
492 
493  // Return
494  return;
495 }
496 
497 
498 /***********************************************************************//**
499  * @brief Set time reference
500  *
501  * @param[in] mjdrefi Integer part of reference MJD (days).
502  * @param[in] mjdreff Fractional part of reference MJD (days).
503  * @param[in] timeunit Time unit (sec, days).
504  * @param[in] timesys Time system (TT).
505  * @param[in] timeref Local time reference.
506  *
507  * Sets the time reference from a MJD reference day (specified by an integer
508  * and a fractional part), a time unit, a time system and a time reference.
509  ***************************************************************************/
510 void GTimeReference::set(const int& mjdrefi,
511  const double& mjdreff,
512  const std::string& timeunit,
513  const std::string& timesys,
514  const std::string& timeref)
515 {
516  // Compute reference MJD
517  double mjdref = double(mjdrefi) + mjdreff;
518 
519  // Set time
520  set(mjdref, timeunit, timesys, timeref);
521 
522  // Return
523  return;
524 }
525 
526 
527 /***********************************************************************//**
528  * @brief Return MJD reference (units: days)
529  *
530  * @return Modified Julian reference day (days).
531  *
532  * Returns the Modified Julian reference day.
533  ***************************************************************************/
534 const double& GTimeReference::mjdref(void) const
535 {
536  // Return MDJ reference
537  return m_mjdref;
538 }
539 
540 
541 /***********************************************************************//**
542  * @brief Returns integer part of MJD reference (units: days)
543  *
544  * @return Integer part of Modified Julian reference day (days).
545  *
546  * Returns the integer part of the Modified Julian reference day.
547  ***************************************************************************/
548 int GTimeReference::mjdrefi(void) const
549 {
550  // Return integer part of MJD reference
551  return int(m_mjdref);
552 }
553 
554 
555 /***********************************************************************//**
556  * @brief Returns fractional part of MJD reference (units: days)
557  *
558  * @return Fractional part of Modified Julian reference day (days).
559  *
560  * Returns the fractional part of the Modified Julian reference day.
561  ***************************************************************************/
562 double GTimeReference::mjdreff(void) const
563 {
564  // Return fractional part of MJD reference
565  return (m_mjdref-double(mjdrefi()));
566 }
567 
568 
569 /***********************************************************************//**
570  * @brief Return time unit
571  *
572  * @return Time unit.
573  *
574  * Returns the reference time unit.
575  ***************************************************************************/
576 const std::string& GTimeReference::timeunit(void) const
577 {
578  // Return time unit
579  return m_timeunit;
580 }
581 
582 
583 /***********************************************************************//**
584  * @brief Return time system
585  *
586  * @return Time system.
587  *
588  * Returns the reference time system.
589  ***************************************************************************/
590 const std::string& GTimeReference::timesys(void) const
591 {
592  // Return time system
593  return m_timesys;
594 }
595 
596 
597 /***********************************************************************//**
598  * @brief Return time reference
599  *
600  * @return Time reference.
601  *
602  * Returns the reference time reference.
603  ***************************************************************************/
604 const std::string& GTimeReference::timeref(void) const
605 {
606  // Return time reference
607  return m_timeref;
608 }
609 
610 
611 /***********************************************************************//**
612  * @brief Return the time unit in seconds
613  *
614  * @return Time unit in seconds.
615  *
616  * Returns 1 if the time using is in seconds and 86400 if the time unit is
617  * in days.
618  ***************************************************************************/
619 double GTimeReference::unitseconds(void) const
620 {
621  // Set time unit in seconds
622  double unit = (m_unit_sec) ? 1.0 : gammalib::sec_in_day;
623 
624  // Return time unit
625  return unit;
626 }
627 
628 
629 /***********************************************************************//**
630  * @brief Print time reference
631  *
632  * @param[in] chatter Chattiness (defaults to NORMAL).
633  * @return String containing the time reference.
634  ***************************************************************************/
635 std::string GTimeReference::print(const GChatter& chatter) const
636 {
637  // Initialise result string
638  std::string result;
639 
640  // Continue only if chatter is not silent
641  if (chatter != SILENT) {
642 
643  // Append header
644  result.append("=== GTimeReference ===");
645 
646  // Append information
647  result.append("\n"+gammalib::parformat("MJD reference time"));
648  result.append(gammalib::str(mjdref()));
649  result.append("\n"+gammalib::parformat("Time unit")+timeunit());
650  result.append("\n"+gammalib::parformat("Time system")+timesys());
651  result.append("\n"+gammalib::parformat("Time reference")+timeref());
652 
653  } // endif: chatter was not silent
654 
655  // Return
656  return result;
657 }
658 
659 
660 /*==========================================================================
661  = =
662  = Private methods =
663  = =
664  ==========================================================================*/
665 
666 /***********************************************************************//**
667  * @brief Initialise class members
668  ***************************************************************************/
670 {
671  // Initialise members
672  m_mjdref = 0.0;
673  m_timeunit = "secs";
674  m_timesys = "TT";
675  m_timeref = "LOCAL";
676  m_unit_sec = true;
677 
678  // Return
679  return;
680 }
681 
682 
683 /***********************************************************************//**
684  * @brief Copy class members
685  *
686  * @param[in] ref Time reference.
687  ***************************************************************************/
689 {
690  // Copy members
691  m_mjdref = ref.m_mjdref;
692  m_timeunit = ref.m_timeunit;
693  m_timesys = ref.m_timesys;
694  m_timeref = ref.m_timeref;
695  m_unit_sec = ref.m_unit_sec;
696 
697  // Return
698  return;
699 }
700 
701 
702 /***********************************************************************//**
703  * @brief Delete class members
704  ***************************************************************************/
706 {
707  // Return
708  return;
709 }
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:47
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:1513
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:820
Implements a time reference.
std::string tolower(const std::string &s)
Convert string to lower case.
Definition: GTools.cpp:834
int toint(const std::string &arg)
Convert string into integer value.
Definition: GTools.cpp:700
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1022
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:1562
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:805
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:413