GammaLib 2.0.0
Loading...
Searching...
No Matches
GGti.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GGti.cpp - Good time interval class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2008-2022 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 GGti.cpp
23 * @brief Good time interval class implementation.
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GException.hpp"
32#include "GTools.hpp"
33#include "GFilename.hpp"
34#include "GGti.hpp"
35#include "GFits.hpp"
36#include "GFitsTable.hpp"
37#include "GFitsBinTable.hpp"
39#include "GXmlElement.hpp"
40
41/* __ Method name definitions ____________________________________________ */
42#define G_REDUCE "GGti::reduce(GTime&, GTime&)"
43#define G_REMOVE "GGti::remove(int&)"
44#define G_READ_XML "GGti::read(GXmlElement&)"
45#define G_WRITE_XML "GGti::write(GXmlElement&)"
46#define G_TSTART "GGti::tstart(int&)"
47#define G_TSTOP "GGti::tstop(int&)"
48#define G_INSERT_GTI "GGti::insert_gti(int&, GTime&, GTime&)"
49
50/* __ Macros _____________________________________________________________ */
51
52/* __ Coding definitions _________________________________________________ */
53
54/* __ Debug definitions __________________________________________________ */
55
56
57/*==========================================================================
58 = =
59 = Constructors/destructors =
60 = =
61 ==========================================================================*/
62
63/***********************************************************************//**
64 * @brief Void constructor
65 *
66 * Constructs empty Good Time Intervals.
67 ***************************************************************************/
69{
70 // Initialise class members
72
73 // Return
74 return;
75}
76
77
78/***********************************************************************//**
79 * @brief FITS file constructor
80 *
81 * @param[in] filename FITS file name.
82 *
83 * Constructs Good Time Intervals from a FITS file.
84 ***************************************************************************/
85GGti::GGti(const GFilename& filename)
86{
87 // Initialise members
89
90 // Load FITS file
91 load(filename);
92
93 // Return
94 return;
95}
96
97
98/***********************************************************************//**
99 * @brief Copy constructor
100 *
101 * @param[in] gti Good Time Intervals.
102 *
103 * Constructs Good Time Intervals by copying other Good Time Intervals.
104 ***************************************************************************/
105GGti::GGti(const GGti& gti)
106{
107 // Initialise class members
108 init_members();
109
110 // Copy members
111 copy_members(gti);
112
113 // Return
114 return;
115}
116
117
118/***********************************************************************//**
119 * @brief XML element constructor
120 *
121 * @param[in] xml XML element.
122 *
123 * Constructs Good Time Intervals from an XML element.
124 ***************************************************************************/
126{
127 // Initialise members
128 init_members();
129
130 // Read Good Time Intervals from XML element
131 read(xml);
132
133 // Return
134 return;
135}
136
137
138/***********************************************************************//**
139 * @brief Single time interval constructor
140 *
141 * @param[in] tstart Start time of interval.
142 * @param[in] tstop Stop time of interval.
143 *
144 * Constructs Good Time Intervals from a single time interval, given by
145 * [p@ tstart, @p tstop].
146 ***************************************************************************/
147GGti::GGti(const GTime& tstart, const GTime& tstop)
148{
149 // Initialise members
150 init_members();
151
152 // Append time interval
154
155 // Return
156 return;
157}
158
159
160/***********************************************************************//**
161 * @brief Time reference constructor
162 *
163 * @param[in] ref Time reference.
164 *
165 * Constructs Good Time Intervals using a specific time reference. The time
166 * reference will be used when writing the Good Time Intervals into a FITS
167 * file.
168 ***************************************************************************/
170{
171 // Initialise class members
172 init_members();
173
174 // Set time reference
175 this->reference(ref);
176
177 // Return
178 return;
179}
180
181
182/***********************************************************************//**
183 * @brief Destructor
184 ***************************************************************************/
186{
187 // Free members
188 free_members();
189
190 // Return
191 return;
192}
193
194
195/*==========================================================================
196 = =
197 = Operators =
198 = =
199 ==========================================================================*/
200
201/***********************************************************************//**
202 * @brief Assignment operator
203 *
204 * @param[in] gti Good Time Intervals.
205 * @return Good Time Intervals.
206 ***************************************************************************/
208{
209 // Execute only if object is not identical
210 if (this != &gti) {
211
212 // Free members
213 free_members();
214
215 // Initialise private members
216 init_members();
217
218 // Copy members
219 copy_members(gti);
220
221 } // endif: object was not identical
222
223 // Return this object
224 return *this;
225}
226
227
228/*==========================================================================
229 = =
230 = Public methods =
231 = =
232 ==========================================================================*/
233
234/***********************************************************************//**
235 * @brief Clear Good Time Intervals
236 ***************************************************************************/
237void GGti::clear(void)
238{
239 // Free members
240 free_members();
241
242 // Initialise private members
243 init_members();
244
245 // Return
246 return;
247}
248
249
250/***********************************************************************//**
251 * @brief Clone Good Time Intervals
252 *
253 * @return Pointer to deep copy of Good Time Intervals.
254 ***************************************************************************/
255GGti* GGti::clone(void) const
256{
257 return new GGti(*this);
258}
259
260
261/***********************************************************************//**
262 * @brief Append Good Time Interval
263 *
264 * @param[in] tstart Start time of interval.
265 * @param[in] tstop Stop time of interval.
266 *
267 * Appends a Good Time Interval at the end of the container.
268 ***************************************************************************/
269void GGti::append(const GTime& tstart, const GTime& tstop)
270{
271 // Insert GTI at end of list
273
274 // Return
275 return;
276}
277
278
279/***********************************************************************//**
280 * @brief Insert Good Time Interval
281 *
282 * @param[in] tstart Start time of interval.
283 * @param[in] tstop Stop time of interval.
284 *
285 * Inserts a Good Time Interval into the container after the first interval
286 * that has a start time smaller than @p tstart. The method implicitely
287 * assumes that the Good Time Intervals are ordered by increasing start time.
288 ***************************************************************************/
289void GGti::insert(const GTime& tstart, const GTime& tstop)
290{
291 // Determine index at which GTI should be inserted
292 int inx = 0;
293 for (; inx < m_num; ++inx) {
294 if (tstart < m_start[inx]) {
295 break;
296 }
297 }
298
299 // Insert interval
300 insert_gti(inx, tstart, tstop);
301
302 // Return
303 return;
304}
305
306
307/***********************************************************************//**
308 * @brief Merge all overlapping Good Time Intervals
309 *
310 * Merges all overlapping or connecting successive Good Time Intervals. The
311 * method implicitely assumes that the intervals are ordered by increasing
312 * start time.
313 *
314 * Note that the method does not actually reduce the memory size but just
315 * updates the information on the number of elements in the array.
316 ***************************************************************************/
317void GGti::merge(void)
318{
319 // Find overlaps
320 int i = 0;
321 int num = m_num;
322 while (i < num-1) {
323
324 // If GTI overlaps with following one then merge both GTIs, move
325 // all remaining GTIs one position up, and reduce number of elements
326 if (m_start[i+1] <= m_stop[i]) {
327 m_start[i] = (m_start[i] < m_start[i+1]) ? m_start[i] : m_start[i+1];
328 m_stop[i] = (m_stop[i] > m_stop[i+1]) ? m_stop[i] : m_stop[i+1];
329 for (int k = i+2; k < num; ++k) {
330 m_start[k-1] = m_start[k];
331 m_stop[k-1] = m_stop[k];
332 }
333 num--;
334 }
335
336 // Otherwise increment GTI index
337 else {
338 i++;
339 }
340
341 } // endwhile: there were still GTIs to check
342
343 // Update number of elements in GTI
344 m_num = num;
345
346 // Update attributes
348
349 // Return
350 return;
351}
352
353
354/***********************************************************************//**
355 * @brief Merge Good Time Interval into container
356 *
357 * @param[in] tstart Start time of interval.
358 * @param[in] tstop Stop time of interval.
359 *
360 * Inserts a Good Time Interval into the container after the first interval
361 * that has a start time smaller than @p tstart and then merges any
362 * overlapping or connecting Good Time Intervals. The method implicitely
363 * assumes that the intervals are ordered by increasing start time.
364 ***************************************************************************/
365void GGti::merge(const GTime& tstart, const GTime& tstop)
366{
367 // Determine index at which GTI should be inserted
368 int inx = 0;
369 for (int i = 0; i < m_num; ++i) {
370 if (tstart < m_start[i]) {
371 break;
372 }
373 }
374
375 // Insert GTI
376 insert_gti(inx, tstart, tstop);
377
378 // Merge any overlapping GTIs
379 merge();
380
381 // Return
382 return;
383}
384
385
386/***********************************************************************//**
387 * @brief Reduce Good Time Intervals to specified interval
388 *
389 * @param[in] tstart Start time of interval.
390 * @param[in] tstop Stop time of interval.
391 *
392 * @exception GException::invalid_argument
393 * Start time is later than stop time
394 *
395 * Reduces the Good Time Intervals to the specified interval. Reducing means
396 * that all Good Time Intervals are dropped that fall outside the specified
397 * interval [@p tstart, @p tstop], and Good Time Intervals will be limited
398 * to >@p tstart and <=@p tstop in case that their boundaries are outside
399 * [@p tstart, @p tstop].
400 ***************************************************************************/
401void GGti::reduce(const GTime& tstart, const GTime& tstop)
402{
403 // Throw an exception if time interval is invalid
404 if (tstart > tstop) {
405 std::string msg = "Invalid time interval specified. Start time "+
406 tstart.print(NORMAL)+" can not be later than "
407 "stop time "+tstop.print(NORMAL)+".";
409 }
410
411 // Adjust existing GTIs. This will limit all GTIs to [tstart,tstop].
412 // All GTIs outside [tstart,tstop] will have start > stop. The number
413 // of valid GTIs will also be determined.
414 int num = 0;
415 for (int i = 0; i < m_num; ++i) {
416 if (m_start[i] < tstart) {
417 m_start[i] = tstart;
418 }
419 if (m_stop[i] > tstop) {
420 m_stop[i] = tstop;
421 }
422 if (m_start[i] <= m_stop[i]) {
423 num++;
424 }
425 }
426
427 // If we still have valid GTIs then allocate memory for them, copy
428 // over the start and stop times, and update the attributes
429 if (num > 0) {
430
431 // Allocate new intervals
432 GTime* start = new GTime[num];
433 GTime* stop = new GTime[num];
434
435 // Copy valid intervals
436 for (int i = 0; i < m_num; ++i) {
437 if (m_start[i] <= m_stop[i]) {
438 start[i] = m_start[i];
439 stop[i] = m_stop[i];
440 }
441 }
442
443 // Free old memory
444 if (m_start != NULL) delete [] m_start;
445 if (m_stop != NULL) delete [] m_stop;
446
447 // Set new memory
448 m_start = start;
449 m_stop = stop;
450
451 // Set attributes
452 m_num = num;
454
455 } // endif: there were still valid GTIs
456
457 // ... otherwise we remove all GTIs
458 else {
459 clear();
460 }
461
462 // Return
463 return;
464}
465
466
467/***********************************************************************//**
468 * @brief Reduce Good Time Intervals to specified intervals
469 *
470 * @param[in] gti Good Time Intervals.
471 *
472 * Reduces the Good Time Intervals to the specified intervals. Reducing means
473 * that the resulting Good Time Intervals are the intersection between the
474 * initial Good Time Intervals and the specified Good Time Intervals.
475 *
476 * Specifically, all Good Time Intervals are dropped that do not overlap
477 * with one of the specified intervals, and overlapping intervals will be
478 * reduced to the overlapping time intervals, eventually splitting a Good
479 * Time Interval into several overlapping intervals.
480 ***************************************************************************/
481void GGti::reduce(const GGti& gti)
482{
483 // Determine maximum size of reduced Good Time Intervals. Continue only
484 // if the size if positive
485 int size = m_num + gti.m_num;
486 if (size > 0) {
487
488 // Initialise tstart and tstop vectors for resulting Good Time
489 // Intervals
490 std::vector<GTime> tstart_reduced;
491 std::vector<GTime> tstop_reduced;
492 tstart_reduced.reserve(size);
493 tstop_reduced.reserve(size);
494
495 // Loop over all GTIs and reduce them to the specified intervals
496 for (int i = 0; i < m_num; ++i) {
497
498 // Loop over all intervals to which the Good Time Intervals
499 // should be reduced
500 for (int k = 0; k < gti.size(); ++k) {
501
502 // If GTI starts after interval then skip
503 if (m_start[i] >= gti.m_stop[k]) {
504 continue;
505 }
506
507 // ... otherwise if GTI stops before interval then skip
508 else if (m_stop[i] <= gti.m_start[k]) {
509 continue;
510 }
511
512 // ... otherwise there is an overlap and we reduce the
513 // interval to the overlapping interval. If this results
514 // in a positive interval we append the interval to the
515 // vector of reduced start and stop times
516 else {
517 GTime tstart = m_start[i];
518 GTime tstop = m_stop[i];
519 if (tstart < gti.m_start[k]) {
520 tstart = gti.m_start[k];
521 }
522 if (tstop > gti.m_stop[k]) {
523 tstop = gti.m_stop[k];
524 }
525 if (tstop > tstart) {
526 tstart_reduced.push_back(tstart);
527 tstop_reduced.push_back(tstop);
528 }
529 }
530
531 } // endfor: looped over intervals
532
533 } // endfor: looped over GTIs
534
535 // If there are reduced GTIs then allocate memory for them, set
536 // the start and stop times, and update the attributes
537 int num = tstart_reduced.size();
538 if (num > 0) {
539
540 // Allocate new intervals
541 GTime* start = new GTime[num];
542 GTime* stop = new GTime[num];
543
544 // Set intervals
545 for (int i = 0; i < num; ++i) {
546 start[i] = tstart_reduced[i];
547 stop[i] = tstop_reduced[i];
548 }
549
550 // Free old memory
551 if (m_start != NULL) delete [] m_start;
552 if (m_stop != NULL) delete [] m_stop;
553
554 // Set new memory
555 m_start = start;
556 m_stop = stop;
557
558 // Set attributes
559 m_num = num;
561
562 } // endif: there were still valid GTIs
563
564 // ... otherwise we remove all GTIs
565 else {
566 clear();
567 }
568
569 } // endif: there were elements to be reduced
570
571 // Return
572 return;
573}
574
575
576/***********************************************************************//**
577 * @brief Remove Good Time Interval
578 *
579 * @param[in] index Good Time Interval index [0,...,size()[.
580 *
581 * Removes Good Time Interval at @p index from the container. All intervals
582 * after the specified @p index are moved forward by one position.
583 *
584 * Note that the method does not actually reduce the memory size but just
585 * updates the information on the number of elements in the array.
586 ***************************************************************************/
587void GGti::remove(const int& index)
588{
589 #if defined(G_RANGE_CHECK)
590 // If index is outside boundary then throw an error
591 if (index < 0 || index >= m_num) {
592 throw GException::out_of_range(G_REMOVE, "Good Time Interval index",
593 index, m_num);
594 }
595 #endif
596
597 // Move all elements located after index forward
598 for (int i = index+1; i < m_num; ++i) {
599 m_start[i-1] = m_start[i];
600 m_stop[i-1] = m_stop[i];
601 }
602
603 // Reduce number of elements by one
604 m_num--;
605
606 // Update attributes
608
609 // Return
610 return;
611}
612
613
614/***********************************************************************//**
615 * @brief Append Good Time Intervals
616 *
617 * @param[in] gti Good Time Intervals.
618 *
619 * Append Good Time Intervals to the container. The method performs automatic
620 * time reference conversion in case that the specified Good Time Intervals
621 * @p gti have a time reference that differs from that of the current
622 * instance.
623 ***************************************************************************/
624void GGti::extend(const GGti& gti)
625{
626 // Do nothing if Good Time Intervals are empty
627 if (!gti.is_empty()) {
628
629 // Allocate new intervals
630 int num = m_num+gti.size();
631 GTime* start = new GTime[num];
632 GTime* stop = new GTime[num];
633
634 // Initialise index
635 int inx = 0;
636
637 // Copy existing intervals
638 for (; inx < m_num; ++inx) {
639 start[inx] = m_start[inx];
640 stop[inx] = m_stop[inx];
641 }
642
643 // Append intervals. Convert to GTI reference on the fly.
644 for (int i = 0; i < gti.size(); ++i, ++inx) {
645 double tstart = gti.m_start[i].convert(m_reference);
646 double tstop = gti.m_stop[i].convert(m_reference);
647 start[inx].set(tstart, m_reference);
648 stop[inx].set(tstop, m_reference);
649 }
650
651 // Free memory
652 if (m_start != NULL) delete [] m_start;
653 if (m_stop != NULL) delete [] m_stop;
654
655 // Set new memory
656 m_start = start;
657 m_stop = stop;
658
659 // Set number of elements
660 m_num = num;
661
662 // Set attributes
664
665 } // endif: Good Time Intervals were not empty
666
667 // Return
668 return;
669}
670
671
672
673/***********************************************************************//**
674 * @brief Load Good Time Intervals from FITS file
675 *
676 * @param[in] filename FITS filename.
677 *
678 * Loads the Good Time Intervals from FITS file.
679 *
680 * If no extension name is provided in the @p filename, the Good Time
681 * Intervals are loaded from the `GTI` extension.
682 ***************************************************************************/
683void GGti::load(const GFilename& filename)
684{
685 // Open FITS file
686 GFits fits(filename);
687
688 // Get GTI table
689 const GFitsTable& table =
690 *fits.table(filename.extname(gammalib::extname_gti));
691
692 // Read GTI from table
693 read(table);
694
695 // Close FITS file
696 fits.close();
697
698 // Return
699 return;
700}
701
702
703/***********************************************************************//**
704 * @brief Save Good Time Intervals into FITS file
705 *
706 * @param[in] filename FITS filename.
707 * @param[in] clobber Overwrite an existing Good Time Interval extension?
708 *
709 * Saves Good Time Intervals into a FITS file. If a file with the given
710 * @p filename does not yet exist it will be created, otherwise the method
711 * opens the existing file. Good Time Intervals can only be appended to an
712 * existing file if the @p clobber flag is set to `true` (otherwise an
713 * exception is thrown).
714 *
715 * The method will append a binary FITS table containing the Good Time
716 * Intervals to the FITS file. The extension name can be specified as part
717 * of the @p filename. For example the @p filename
718 *
719 * myfile.fits[GOOD TIME INTERVALS]
720 *
721 * will save the Good Time Intervals in the `GOOD TIME INTERVALS` extension
722 * of the `myfile.fits` file. If the extension exists already in the file it
723 * will be replaced, otherwise a new extension will be created. If no
724 * extension name is provided, the method will use `GTI` as the default
725 * extension name for Good Time Intervals.
726 ***************************************************************************/
727void GGti::save(const GFilename& filename, const bool& clobber) const
728{
729 // Open or create FITS file (without extension name since the requested
730 // extension may not yet exist in the file)
731 GFits fits(filename.url(), true);
732
733 // Write GTI to FITS object
734 write(fits, filename.extname(gammalib::extname_gti));
735
736 // Save to file
737 fits.save(clobber);
738
739 // Return
740 return;
741}
742
743
744/***********************************************************************//**
745 * @brief Read Good Time Intervals and time reference from FITS table
746 *
747 * @param[in] table FITS table.
748 *
749 * Reads the Good Time Intervals and time reference from a FITS table. The
750 * start and stop times of the Good Time Intervals are read from the "START"
751 * and "STOP" columns.
752 ***************************************************************************/
753void GGti::read(const GFitsTable& table)
754{
755 // Clear object
756 clear();
757
758 // Read time reference
759 m_reference.read(table);
760
761 // Extract GTI information from FITS table
762 m_num = table.integer("NAXIS2");
763 if (m_num > 0) {
764
765 // Set GTIs
766 m_start = new GTime[m_num];
767 m_stop = new GTime[m_num];
768 for (int i = 0; i < m_num; ++i) {
769 m_start[i].set(table["START"]->real(i), m_reference);
770 m_stop[i].set(table["STOP"]->real(i), m_reference);
771 }
772
773 // Set attributes
775
776 }
777
778 // Return
779 return;
780}
781
782
783/***********************************************************************//**
784 * @brief Write Good Time Intervals and time reference into FITS object
785 *
786 * @param[in] fits FITS file.
787 * @param[in] extname GTI extension name.
788 *
789 * Writes Good Time Intervals and time reference into a FITS object. If an
790 * extension with the same name does already exist in the FITS object, the
791 * values in that extension will be replaced.
792 *
793 * The start and stop tims of the Good Time Intervals will be written into
794 * double precision columns named `START` and `STOP`.
795 ***************************************************************************/
796void GGti::write(GFits& fits, const std::string& extname) const
797{
798 // Create GTI columns
799 GFitsTableDoubleCol cstart("START", m_num);
800 GFitsTableDoubleCol cstop("STOP", m_num);
801
802 // Fill GTI columns in specified time reference
803 for (int i = 0; i < m_num; ++i) {
804 cstart(i) = m_start[i].convert(m_reference);
805 cstop(i) = m_stop[i].convert(m_reference);
806 }
807
808 // Create GTI table
809 GFitsBinTable table(m_num);
810 table.append(cstart);
811 table.append(cstop);
812 table.extname(extname);
813
814 // Write time reference into table
815 m_reference.write(table);
816
817 // If the FITS object contains already an extension with the same
818 // name then remove now this extension
819 if (fits.contains(extname)) {
820 fits.remove(extname);
821 }
822
823 // Append GTI table to FITS file
824 fits.append(table);
825
826 // Return
827 return;
828}
829
830
831/***********************************************************************//**
832 * @brief Read Good Time Intervals from XML element
833 *
834 * @param[in] xml XML element.
835 *
836 * @exception GException::invalid_value
837 * Invalid XML format encountered.
838 *
839 * Read Good Time Intervals from an XML element. The format of the Good Time
840 * Intervals is either
841 *
842 * <parameter name="GoodTimeIntervals" file="..."/>
843 *
844 * in case that the information is stored in a FITS file, or
845 *
846 * <parameter name="GoodTimeIntervals" tmin="..." tmax="..."/>
847 *
848 * if the Good Time Intervals should be constructed from a start and stop
849 * time (the units of the @a tmin and @a tmax parameters are seconds). In the
850 * latter case, the method also expects that the time reference is provided
851 * as parameter in the @p xml element.
852 ***************************************************************************/
853void GGti::read(const GXmlElement& xml)
854{
855 // Clear energy boundaries
856 clear();
857
858 // Get GTI parameter
859 const GXmlElement* par = gammalib::xml_get_par(G_READ_XML, xml, "GoodTimeIntervals");
860
861 // If we have a "file" attribute then load GTIs from file ...
862 if (par->has_attribute("file")) {
863
864 // Get filename
865 std::string filename = par->attribute("file");
866
867 // Load GTIs from file
868 load(filename);
869
870 // Store filename (we need to do this after loading as the
871 // load method calls the read method that clears the object
872 m_xml_filename = filename;
873
874 }
875
876 // ... otherwise if "tmin" and "tmax" attributes are found then set
877 // the GTIs from these attributes and also read the time reference
878 // from the XML file
879 else if (par->has_attribute("tmin") && par->has_attribute("tmax")) {
880
881 // Read time reference first (needed before reading times!)
882 m_reference.read(xml);
883
884 // Create GTI from "tmin" and "tmax" attributes
885 double tmin = gammalib::todouble(par->attribute("tmin"));
886 double tmax = gammalib::todouble(par->attribute("tmax"));
887 append(GTime(tmin, m_reference), GTime(tmax, m_reference));
888
889 }
890
891 // ... otherwise throw an exception
892 else {
893 std::string msg = "Attributes \"file\" or \"tmin\" and \"tmax\" not "
894 "found in XML parameter \"GoodTimeIntervals\". "
895 "Please verify the observation definition XML "
896 "file.";
898 }
899
900 // Return
901 return;
902}
903
904
905/***********************************************************************//**
906 * @brief Write Good Time Intervals into XML element
907 *
908 * @param[in] xml XML element.
909 *
910 * Writes Good Time Intervals into an XML element. The format of the Good
911 * Time Intervals is
912 *
913 * <parameter name="GoodTimeIntervals" file="..."/>
914 *
915 * if a file name has been specified previously upon reading from an XML
916 * file. In that case, the method will also write the Good Time Intervals to
917 * the specified file. If no file name is available, the method will write
918 * the first start and the last stop time of the Good Time Intervals in the
919 * format
920 *
921 * <parameter name="GoodTimeIntervals" tmin="..." tmax="..."/>
922 *
923 * The units of the @a tmin and @a tmax parameters are seconds. In that case,
924 * the time reference is also written into the XML element.
925 *
926 * This method does nothing if the Good Time Intervals are empty.
927 ***************************************************************************/
928void GGti::write(GXmlElement& xml) const
929{
930 // Continue only if there are GTIs
931 if (!is_empty()) {
932
933 // Get parameter
934 GXmlElement* par =
935 gammalib::xml_need_par(G_WRITE_XML, xml, "GoodTimeIntervals");
936
937 // If we have a file name then write the "file" attribute ...
938 if (!m_xml_filename.is_empty()) {
939
940 // Write "file" attribute
941 par->attribute("file", m_xml_filename);
942
943 // Write GTI file
944 save(m_xml_filename, true);
945
946 }
947
948 // ... otherwise write "tmin" and "tmax" attributes and write the
949 // time reference
950 else {
951
952 // Write time interval
953 par->attribute("tmin", gammalib::str(tstart().convert(m_reference)));
954 par->attribute("tmax", gammalib::str(tstop().convert(m_reference)));
955
956 // Write time reference
957 m_reference.write(xml);
958
959 }
960
961 } // endif: GTIs were not empty
962
963 // Return
964 return;
965}
966
967
968/***********************************************************************//**
969 * @brief Returns start time for a given Good Time Interval
970 *
971 * @param[in] index Good Time Interval index [0,...,size()[.
972 * @return Start time.
973 *
974 * @exception GException::out_of_range
975 * Specified index is out of range.
976 ***************************************************************************/
977const GTime& GGti::tstart(const int& index) const
978{
979 #if defined(G_RANGE_CHECK)
980 // If index is outside boundary then throw an error
981 if (index < 0 || index >= m_num) {
982 throw GException::out_of_range(G_TSTART, "Good Time Interval index",
983 index, m_num);
984 }
985 #endif
986
987 // Return
988 return (m_start[index]);
989}
990
991
992/***********************************************************************//**
993 * @brief Returns stop time for a given Good Time Interval
994 *
995 * @param[in] index Good Time Interval index [0,...,size()[.
996 * @return Stop time.
997 *
998 * @exception GException::out_of_range
999 * Specified index is out of range.
1000 ***************************************************************************/
1001const GTime& GGti::tstop(const int& index) const
1002{
1003 #if defined(G_RANGE_CHECK)
1004 // If index is outside boundary then throw an error
1005 if (index < 0 || index >= m_num) {
1006 throw GException::out_of_range(G_TSTOP, "Good Time Interval index",
1007 index, m_num);
1008 }
1009 #endif
1010
1011 // Return
1012 return (m_stop[index]);
1013}
1014
1015
1016/***********************************************************************//**
1017 * @brief Computes overlap of time interval with GTIs
1018 *
1019 * @param[in] tstart Start time of interval.
1020 * @param[in] tstop Stop time of interval.
1021 * @return Overlap (seconds).
1022 *
1023 * Returns the overlap of time interval with GTIs in seconds.
1024 ***************************************************************************/
1025double GGti::overlap(const GTime& tstart, const GTime& tstop) const
1026{
1027 // Initialise overlap
1028 double overlap = 0.0;
1029
1030 // Compute the overlap
1031 for (int i = 0; i < m_num; ++i) {
1032 if (m_start[i] < tstart) {
1033 if (m_stop[i] > tstart) {
1034 if (m_stop[i] > tstop) {
1035 overlap += tstop - tstart;
1036 }
1037 else {
1038 overlap += m_stop[i] - tstart;
1039 }
1040 }
1041 }
1042 else if (m_stop[i] > tstop) {
1043 if (m_start[i] < tstop) {
1044 overlap += tstop - m_start[i];
1045 }
1046 }
1047 else {
1048 overlap += m_stop[i] - m_start[i];
1049 }
1050 }
1051
1052 // Return
1053 return overlap;
1054}
1055
1056
1057/***********************************************************************//**
1058 * @brief Checks whether Good Time Intervals contains time
1059 *
1060 * @param[in] time Time to be checked.
1061 *
1062 * Checks if a given @p time falls in at least one of the Good Time
1063 * Intervals. The method exits when the first matching interval has been
1064 * found.
1065 *
1066 * Since this method may be called repeadetly while scanning an ordered list
1067 * of time it is most efficient to start the search always at the index where
1068 * the last search was successful.
1069 ***************************************************************************/
1070bool GGti::contains(const GTime& time) const
1071{
1072 // Initialise test
1073 bool found = false;
1074
1075 // Start GTIs search from the last successful index
1076 for (int i = m_last_index; i < m_num; ++i) {
1077 if (time >= m_start[i] && time <= m_stop[i]) {
1078 found = true;
1079 m_last_index = i;
1080 break;
1081 }
1082 }
1083
1084 // If no GTI has been found then search now from the start of the list
1085 if (!found) {
1086 for (int i = 0; i < m_last_index; ++i) {
1087 if (time >= m_start[i] && time <= m_stop[i]) {
1088 found = true;
1089 m_last_index = i;
1090 break;
1091 }
1092 }
1093 }
1094
1095 // Return result
1096 return found;
1097}
1098
1099
1100/***********************************************************************//**
1101 * @brief Print Good Time Intervals
1102 *
1103 * @param[in] chatter Chattiness.
1104 * @return String containing Good Time Interval information.
1105 ***************************************************************************/
1106std::string GGti::print(const GChatter& chatter) const
1107{
1108 // Initialise result string
1109 std::string result;
1110
1111 // Continue only if chatter is not silent
1112 if (chatter != SILENT) {
1113
1114 // Append header
1115 result.append("=== GGti ===");
1116
1117 // Append GTI information
1118 result.append("\n"+gammalib::parformat("Number of intervals"));
1119 result.append(gammalib::str(size()));
1120 result.append("\n"+gammalib::parformat("Ontime"));
1121 result.append(gammalib::str(ontime())+" sec");
1122 result.append("\n"+gammalib::parformat("Elapsed time"));
1123 result.append(gammalib::str(telapse())+" sec");
1124 result.append("\n"+gammalib::parformat("MJD range"));
1125 result.append(gammalib::str(tstart().mjd()));
1126 result.append(" - ");
1127 result.append(gammalib::str(tstop().mjd()));
1128 result.append(" "+reference().timeunit());
1129 result.append(" ("+reference().timesys()+")");
1130 result.append("\n"+gammalib::parformat("UTC range"));
1131 result.append(tstart().utc());
1132 result.append(" - ");
1133 result.append(tstop().utc());
1134 result.append(" "+reference().timeunit());
1135 result.append(" ("+reference().timesys()+")");
1136
1137 // Append reference MJD
1138 result.append("\n"+gammalib::parformat("Reference MJD"));
1139 result.append(gammalib::str(reference().mjdref()));
1140
1141 // EXPLICIT: Append time reference information
1142 if (chatter >= EXPLICIT) {
1143 result.append("\n"+reference().print(chatter));
1144 }
1145
1146 // Optionally append XML filename
1147 if (!m_xml_filename.is_empty()) {
1148 result.append("\n"+gammalib::parformat("File name"));
1149 result.append(m_xml_filename);
1150 }
1151
1152 } // endif: chatter was not silent
1153
1154 // Return result
1155 return result;
1156}
1157
1158
1159/*==========================================================================
1160 = =
1161 = Private methods =
1162 = =
1163 ==========================================================================*/
1164
1165/***********************************************************************//**
1166 * @brief Initialise class members
1167 ***************************************************************************/
1169{
1170 // Initialise members
1171 m_num = 0;
1172 m_tstart.clear();
1173 m_tstop.clear();
1175 m_ontime = 0.0;
1176 m_telapse = 0.0;
1177 m_start = NULL;
1178 m_stop = NULL;
1179
1180 // Initialise computation cache
1181 m_last_index = 0;
1182
1183 // Initialise time reference with native reference
1184 GTime time;
1185 m_reference = time.reference();
1186
1187 // Return
1188 return;
1189}
1190
1191
1192/***********************************************************************//**
1193 * @brief Copy class members
1194 *
1195 * @param[in] gti Good Time Intervals.
1196 ***************************************************************************/
1197void GGti::copy_members(const GGti& gti)
1198{
1199 // Copy attributes
1200 m_num = gti.m_num;
1201 m_tstart = gti.m_tstart;
1202 m_tstop = gti.m_tstop;
1203 m_ontime = gti.m_ontime;
1204 m_telapse = gti.m_telapse;
1207
1208 // Copy start/stop times
1209 if (m_num > 0) {
1210 m_start = new GTime[m_num];
1211 m_stop = new GTime[m_num];
1212 for (int i = 0; i < m_num; ++i) {
1213 m_start[i] = gti.m_start[i];
1214 m_stop[i] = gti.m_stop[i];
1215 }
1216 }
1217
1218 // Copy computation cache
1220
1221 // Return
1222 return;
1223}
1224
1225
1226/***********************************************************************//**
1227 * @brief Delete class members
1228 ***************************************************************************/
1230{
1231 // Free memory
1232 if (m_start != NULL) delete [] m_start;
1233 if (m_stop != NULL) delete [] m_stop;
1234
1235 // Signal free pointers
1236 m_start = NULL;
1237 m_stop = NULL;
1238
1239 // Return
1240 return;
1241}
1242
1243
1244/***********************************************************************//**
1245 * @brief Set class attributes
1246 *
1247 * Compute the following class attributes:
1248 *
1249 * m_tstart - Earliest start time of GTIs
1250 * m_stop - Latest stop time of GTIs
1251 * m_telapse - Latest stop time minus earliest start time of GTIs [sec]
1252 * m_ontime - Sum of all intervals [sec]
1253 ***************************************************************************/
1255{
1256 // If there are intervals then determine the start and stop time
1257 // from these intervals ...
1258 if (m_num > 0) {
1259 m_tstart = m_start[0];
1260 m_tstop = m_stop[0];
1261 for (int i = 1; i < m_num; ++i) {
1262 if (m_start[i] < m_tstart) m_tstart = m_start[i];
1263 if (m_stop[i] > m_tstop) m_tstop = m_stop[i];
1264 }
1265 }
1266
1267 // ... otherwise clear the start and stop time
1268 else {
1269 m_tstart.clear();
1270 m_tstop.clear();
1271 }
1272
1273 // Set attributes
1275 m_ontime = 0.0;
1276 for (int i = 0; i < m_num; ++i) {
1277 m_ontime += (m_stop[i].secs() - m_start[i].secs());
1278 }
1279
1280 // Return
1281 return;
1282}
1283
1284
1285/***********************************************************************//**
1286 * @brief Insert Good Time Interval
1287 *
1288 * @param[in] index Index at which interval is inserted.
1289 * @param[in] tstart Start time of interval.
1290 * @param[in] tstop Stop time of interval.
1291 *
1292 * @exception GException::invalid_argument
1293 * Start time later than stop time
1294 *
1295 * Inserts a Good Time Interval at the specified @p index in the Good
1296 * Time Intervals. The method does not reorder the intervals by time,
1297 * instead the client needs to determine the approriate @p index.
1298 *
1299 * Invalid parameters do not produce any exception, but are handled
1300 * transparently. If the interval is invalid (i.e. @p tstart > @p tstop)
1301 * an exception is thrown. If the @p index is out of the valid range, the
1302 * index will be adjusted to either the first or the last element.
1303 ***************************************************************************/
1304void GGti::insert_gti(const int& index, const GTime& tstart, const GTime& tstop)
1305{
1306 // Throw an exception if time interval is invalid
1307 if (tstart > tstop) {
1308 std::string msg = "Invalid time interval specified. Start time "+
1309 tstart.print(NORMAL)+" can not be later than "
1310 "stop time "+tstop.print(NORMAL)+".";
1312 }
1313
1314 // Set index
1315 int inx = index;
1316
1317 // If inx is out of range then adjust it
1318 if (inx < 0) inx = 0;
1319 if (inx > m_num) inx = m_num;
1320
1321 // Allocate new intervals
1322 int num = m_num+1;
1323 GTime* start = new GTime[num];
1324 GTime* stop = new GTime[num];
1325
1326 // Copy intervals before GTI to be inserted
1327 for (int i = 0; i < inx; ++i) {
1328 start[i] = m_start[i];
1329 stop[i] = m_stop[i];
1330 }
1331
1332 // Insert GTI
1333 start[inx] = tstart;
1334 stop[inx] = tstop;
1335
1336 // Copy intervals after GTI to be inserted
1337 for (int i = inx+1; i < num; ++i) {
1338 start[i] = m_start[i-1];
1339 stop[i] = m_stop[i-1];
1340 }
1341
1342 // Free memory
1343 if (m_start != NULL) delete [] m_start;
1344 if (m_stop != NULL) delete [] m_stop;
1345
1346 // Set new memory
1347 m_start = start;
1348 m_stop = stop;
1349
1350 // Set number of elements
1351 m_num = num;
1352
1353 // Set attributes
1355
1356 // Return
1357 return;
1358}
#define G_WRITE_XML
Definition GEbounds.cpp:45
#define G_READ_XML
Definition GEbounds.cpp:44
Exception handler interface definition.
Filename class interface definition.
FITS binary table class definition.
#define G_REMOVE
FITS table double column class interface definition.
FITS table abstract base class interface definition.
FITS file class interface definition.
#define G_REDUCE
Definition GGti.cpp:42
#define G_TSTOP
Definition GGti.cpp:47
#define G_TSTART
Definition GGti.cpp:46
#define G_INSERT_GTI
Definition GGti.cpp:48
Good time interval class interface definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ NORMAL
Definition GTypemaps.hpp:36
@ EXPLICIT
Definition GTypemaps.hpp:37
@ SILENT
Definition GTypemaps.hpp:34
XML element node class interface definition.
Filename class.
Definition GFilename.hpp:62
std::string url(void) const
Return Uniform Resource Locator (URL)
std::string extname(const std::string &defaultname="") const
Return extension name.
bool is_empty(void) const
Signal if filename is empty.
void clear(void)
Clear file name.
FITS binary table class.
const std::string & extname(void) const
Return extension name.
Definition GFitsHDU.hpp:162
int integer(const std::string &keyname) const
Return card value as integer.
Definition GFitsHDU.hpp:436
FITS table double column.
Abstract interface for FITS table.
GFitsTableCol * append(const GFitsTableCol &column)
Append column to the table.
FITS file class.
Definition GFits.hpp:63
bool contains(const int &extno) const
Check if HDU exists in FITS file.
Definition GFits.hpp:282
GFitsHDU * append(const GFitsHDU &hdu)
Append HDU to FITS file.
Definition GFits.cpp:678
void close(void)
Close FITS file.
Definition GFits.cpp:1342
void remove(const int &extno)
Remove HDU from FITS file.
Definition GFits.cpp:862
void save(const bool &clobber=false)
Saves FITS file.
Definition GFits.cpp:1178
GFitsTable * table(const int &extno)
Get pointer to table HDU.
Definition GFits.cpp:482
Good Time Interval class.
Definition GGti.hpp:62
int m_last_index
Last index for containment test.
Definition GGti.hpp:132
GGti * clone(void) const
Clone Good Time Intervals.
Definition GGti.cpp:255
void set_attributes(void)
Set class attributes.
Definition GGti.cpp:1254
bool contains(const GTime &time) const
Checks whether Good Time Intervals contains time.
Definition GGti.cpp:1070
const GTimeReference & reference(void) const
Return time reference for Good Time Intervals.
Definition GGti.hpp:275
void insert(const GTime &tstart, const GTime &tstop)
Insert Good Time Interval.
Definition GGti.cpp:289
std::string print(const GChatter &chatter=NORMAL) const
Print Good Time Intervals.
Definition GGti.cpp:1106
const double & telapse(void) const
Returns elapsed time.
Definition GGti.hpp:224
void remove(const int &index)
Remove Good Time Interval.
Definition GGti.cpp:587
void load(const GFilename &filename)
Load Good Time Intervals from FITS file.
Definition GGti.cpp:683
GGti & operator=(const GGti &gti)
Assignment operator.
Definition GGti.cpp:207
void copy_members(const GGti &gti)
Copy class members.
Definition GGti.cpp:1197
GTime m_tstart
Start time of Good Time Intervals.
Definition GGti.hpp:122
GTime * m_stop
Array of stop times.
Definition GGti.hpp:127
void write(GFits &fits, const std::string &extname=gammalib::extname_gti) const
Write Good Time Intervals and time reference into FITS object.
Definition GGti.cpp:796
GTime m_tstop
Stop time of Good Time Intervals.
Definition GGti.hpp:123
GTime * m_start
Array of start times.
Definition GGti.hpp:126
void init_members(void)
Initialise class members.
Definition GGti.cpp:1168
void insert_gti(const int &index, const GTime &tstart, const GTime &tstop)
Insert Good Time Interval.
Definition GGti.cpp:1304
const GTime & tstop(void) const
Returns latest stop time in Good Time Intervals.
Definition GGti.hpp:207
GTimeReference m_reference
Time reference.
Definition GGti.hpp:128
void save(const GFilename &filename, const bool &clobber=false) const
Save Good Time Intervals into FITS file.
Definition GGti.cpp:727
void extend(const GGti &gti)
Append Good Time Intervals.
Definition GGti.cpp:624
double m_telapse
Time between start of first GTI and stop of last GTI (in seconds)
Definition GGti.hpp:125
void read(const GFitsTable &table)
Read Good Time Intervals and time reference from FITS table.
Definition GGti.cpp:753
bool is_empty(void) const
Signal if there are no Good Time Intervals.
Definition GGti.hpp:166
int size(void) const
Return number of Good Time Intervals.
Definition GGti.hpp:154
GFilename m_xml_filename
XML filename.
Definition GGti.hpp:129
int m_num
Number of Good Time Intervals.
Definition GGti.hpp:121
virtual ~GGti(void)
Destructor.
Definition GGti.cpp:185
void free_members(void)
Delete class members.
Definition GGti.cpp:1229
void reduce(const GTime &tstart, const GTime &tstop)
Reduce Good Time Intervals to specified interval.
Definition GGti.cpp:401
const double & ontime(void) const
Returns ontime.
Definition GGti.hpp:240
GGti(void)
Void constructor.
Definition GGti.cpp:68
void merge(void)
Merge all overlapping Good Time Intervals.
Definition GGti.cpp:317
void append(const GTime &tstart, const GTime &tstop)
Append Good Time Interval.
Definition GGti.cpp:269
const GTime & tstart(void) const
Returns earliest start time in Good Time Intervals.
Definition GGti.hpp:194
void clear(void)
Clear Good Time Intervals.
Definition GGti.cpp:237
double m_ontime
Sum of GTIs durations (in seconds)
Definition GGti.hpp:124
double overlap(const GTime &tstart, const GTime &tstop) const
Computes overlap of time interval with GTIs.
Definition GGti.cpp:1025
Implements a time reference.
void write(GFitsHDU &hdu) const
Write time reference into FITS header.
void read(const GFitsHDU &hdu)
Read time reference from FITS header.
Time class.
Definition GTime.hpp:55
void clear(void)
Clear time.
Definition GTime.cpp:252
GTimeReference reference(void) const
Returns native time reference.
Definition GTime.cpp:1170
std::string print(const GChatter &chatter=NORMAL) const
Print time.
Definition GTime.cpp:1188
double convert(const GTimeReference &ref) const
Return time in specified reference.
Definition GTime.cpp:698
void set(const double &time, const GTimeReference &ref)
Set time given in specified reference.
Definition GTime.cpp:1005
const double & secs(void) const
Return time in seconds in native reference (TT)
Definition GTime.hpp:156
XML element node class.
const GXmlAttribute * attribute(const int &index) const
Return attribute.
bool has_attribute(const std::string &name) const
Check if element has a given attribute.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1143
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
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
double todouble(const std::string &arg)
Convert string into double precision value.
Definition GTools.cpp:926
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 extname_gti
Definition GGti.hpp:44