GammaLib 2.2.0.dev
Loading...
Searching...
No Matches
GCOSSpaceCraft.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GCOSSpaceCraft.cpp - COSI space craft class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2026 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 GCOSSpaceCraft.cpp
23 * @brief COSI space craft class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <cstdio> // std::fopen, std::fgets, std::fclose, etc...
32#include "GTools.hpp"
33#include "GFilename.hpp"
34#include "GException.hpp"
35#include "GSkyDir.hpp"
36#include "GSkyMap.hpp"
37#include "GFits.hpp"
38#include "GFitsBinTable.hpp"
40#include "GFitsTable.hpp"
41#include "GFitsTableCol.hpp"
42#include "GCOSTools.hpp"
43#include "GCOSSpaceCraft.hpp"
44
45/* __ Method name definitions ____________________________________________ */
46#define G_OPERATOR "GCOSSpaceCraft::operator[](int&)"
47#define G_LOAD_ORI "GCOSSpaceCraft::load_ori(GFilename&)"
48
49/* __ Macros _____________________________________________________________ */
50
51/* __ Coding definitions _________________________________________________ */
52
53/* __ Debug definitions __________________________________________________ */
54
55
56
57/*==========================================================================
58 = =
59 = Constructors/destructors =
60 = =
61 ==========================================================================*/
62
63/***********************************************************************//**
64 * @brief Void constructor
65 ***************************************************************************/
67{
68 // Initialise class members
70
71 // Return
72 return;
73}
74
75
76/***********************************************************************//**
77 * @brief Filename constructor
78 *
79 * @param[in] filename Space craft file name.
80 ***************************************************************************/
82{
83 // Initialise class members
85
86 // Load space craft file
87 load(filename);
88
89 // Return
90 return;
91}
92
93
94/***********************************************************************//**
95 * @brief Copy constructor
96 *
97 * @param[in] spacecraft COSI space craft.
98 ***************************************************************************/
100{
101 // Initialise class members
102 init_members();
103
104 // Copy members
105 copy_members(spacecraft);
106
107 // Return
108 return;
109}
110
111
112/***********************************************************************//**
113 * @brief Destructor
114 ***************************************************************************/
116{
117 // Free members
118 free_members();
119
120 // Return
121 return;
122}
123
124
125/*==========================================================================
126 = =
127 = Operators =
128 = =
129 ==========================================================================*/
130
131/***********************************************************************//**
132 * @brief Assignment operator
133 *
134 * @param[in] spacecraft COSI space craft.
135 * @return COSI space craft.
136 ***************************************************************************/
138{
139 // Execute only if object is not identical
140 if (this != &spacecraft) {
141
142 // Free members
143 free_members();
144
145 // Initialise private members
146 init_members();
147
148 // Copy members
149 copy_members(spacecraft);
150
151 } // endif: object was not identical
152
153 // Return this object
154 return *this;
155}
156
157
158/***********************************************************************//**
159 * @brief Return reference to COSI pointing
160 *
161 * @param[in] index Pointing index [0,...,size()-1].
162 * @return Reference to COSI pointing.
163 *
164 * @exception GException::out_of_range
165 * Pointing index outside valid range.
166 *
167 * Returns reference to a COSI pointing.
168 ***************************************************************************/
170{
171 // Optionally check if the index is valid
172 #if defined(G_RANGE_CHECK)
173 if (index < 0 || index >= size()) {
174 throw GException::out_of_range(G_OPERATOR, "Pointing index", index, size());
175 }
176 #endif
177
178 // Return reference
179 return (m_pointings[index]);
180}
181
182
183/***********************************************************************//**
184 * @brief Return reference to COSI pointing (const version)
185 *
186 * @param[in] index Pointing index [0,...,size()-1].
187 * @return Reference to COSI pointing.
188 *
189 * @exception GException::out_of_range
190 * Pointing index outside valid range.
191 *
192 * Returns reference to a COSI pointing.
193 ***************************************************************************/
194const GCOSPointing& GCOSSpaceCraft::operator[](const int& index) const
195{
196 // Optionally check if the index is valid
197 #if defined(G_RANGE_CHECK)
198 if (index < 0 || index >= size()) {
199 throw GException::out_of_range(G_OPERATOR, "Pointing index", index, size());
200 }
201 #endif
202
203 // Return reference
204 return (m_pointings[index]);
205}
206
207
208/*==========================================================================
209 = =
210 = Public methods =
211 = =
212 ==========================================================================*/
213
214/***********************************************************************//**
215 * @brief Clear space craft
216 ***************************************************************************/
218{
219 // Free members
220 free_members();
221
222 // Initialise private members
223 init_members();
224
225 // Return
226 return;
227}
228
229
230/***********************************************************************//**
231 * @brief Clone space craft
232 *
233 * @return Pointer to deep copy of COSI space craft.
234 ***************************************************************************/
236{
237 return new GCOSSpaceCraft(*this);
238}
239
240
241/***********************************************************************//**
242 * @brief Compute livetime for a given sky direction
243 *
244 * @param[in] dir Sky direction.
245 *
246 * Computes the lifetime of a given sky direction taking into account only
247 * the time bins during which the source is not occulted by the Earth. The
248 * method assumes the Earth to be spherically symmetric with a radius of
249 * 6378 km.
250 ***************************************************************************/
251double GCOSSpaceCraft::livetime(const GSkyDir& dir) const
252{
253 // Initialise livetime
254 double livetime = 0.0;
255
256 // Loop over pointings
257 for (int i = 0; i < size(); ++i) {
258
259 // Get const reference to pointing
260 const GCOSPointing& pointing = m_pointings[i];
261
262 // Compute the apparent angular radius of the Earth by computing the
263 // arcsine of the angle towards the Earth centre and the Earth limb.
264 // This ignores the ellipticity of the Earth.
265 double earth_radius = std::asin(6378.0 / (6378.0 + pointing.altitude()));
266
267 // Compute the distance of the sky direction from the nadir direction
268 double distance = pointing.earth_nadir().dist(dir);
269
270 // If the distance is larger than the apparent angular radius of the
271 // Earth then add-up the livetime
272 if (distance > earth_radius) {
273 livetime += pointing.livetime();
274 }
275
276 } // endfor: looped over pointings
277
278 // Return livetime
279 return livetime;
280}
281
282
283/***********************************************************************//**
284 * @brief Compute livetime for a sky map
285 *
286 * @param[in] map Sky map.
287 *
288 * Computes the lifetime for the pixels of a sky map taking into account only
289 * the time bins during which the pixels are not occulted by the Earth. The
290 * method assumes the Earth to be spherically symmetric with a radius of
291 * 6378 km.
292 ***************************************************************************/
294{
295 // Initialise livetime sky map
296 GSkyMap livetime = map.extract(0); // Extract first map for pixel definition
297 livetime = 0.0; // Set all pixels to zero
298
299 // Get number of sky map pixels
300 int npix = livetime.npix();
301
302 // Build-up list of pixel directions for faster distance computation
303 std::vector<GSkyDir> dirs;
304 dirs.reserve(npix);
305 for (int k = 0; k < npix; ++k) {
306 dirs.push_back(livetime.inx2dir(k));
307 }
308
309 // Loop over pointings
310 for (int i = 0; i < size(); ++i) {
311
312 // Get const reference to pointing
313 const GCOSPointing& pointing = m_pointings[i];
314
315 // Compute the apparent angular radius of the Earth by computing the
316 // arcsine of the angle towards the Earth centre and the Earth limb.
317 // This ignores the ellipticity of the Earth.
318 double earth_radius = std::asin(6378.0 / (6378.0 + pointing.altitude()));
319
320 // Loop over all sky map pixels
321 for (int k = 0; k < npix; ++k) {
322
323 // Compute the distance of the sky direction from the nadir
324 // direction
325 double distance = pointing.earth_nadir().dist(dirs[k]);
326
327 // If the distance is larger than the apparent angular radius
328 // of the Earth then add-up the livetime
329 if (distance > earth_radius) {
330 livetime(k) += pointing.livetime();
331 }
332
333 } // endfor: looped over sky map pixels
334
335 } // endfor: looped over pointings
336
337 // Return livetime sky map
338 return livetime;
339}
340
341
342/***********************************************************************//**
343 * @brief Load COSI space craft file
344 *
345 * @param[in] filename Space craft file name.
346 ***************************************************************************/
347void GCOSSpaceCraft::load(const GFilename& filename)
348{
349 // If space craft file is a FITS file than load FITS file
350 if (filename.is_fits()) {
351 load_fits(filename);
352 }
353
354 // ... otherwise load ORI file
355 else {
356 load_ori(filename);
357 }
358
359 // Return
360 return;
361}
362
363
364/***********************************************************************//**
365 * @brief Save COSI space craft FITS file
366 *
367 * @param[in] filename Space craft FITS file name.
368 * @param[in] clobber Overwrite existing FITS file?
369 *
370 * Saves COSI space craft information into a FITS file.
371 ***************************************************************************/
372void GCOSSpaceCraft::save(const GFilename& filename, const bool& clobber) const
373{
374 // Open FITS file
375 GFits fits;
376
377 // Write space craft information
378 write(fits);
379
380 // Save file
381 fits.saveto(filename, clobber);
382
383 // Close FITS file
384 fits.close();
385
386 // Return
387 return;
388}
389
390
391/***********************************************************************//**
392 * @brief Read COSI space craft FITS file
393 *
394 * @param[in] fits FITS file.
395 *
396 * Read the COSI space craft information from a FITS file object.
397 ***************************************************************************/
399{
400 // Clear object
401 clear();
402
403 // Read pointings
404 read_pointings(fits);
405
406 // Read livetimes
407 read_livetimes(fits);
408
409 // Get GTI table
411
412 // Read Good Time Intervals
413 m_gti.read(gti);
414
415 // Return
416 return;
417}
418
419
420/***********************************************************************//**
421 * @brief Write COSI space craft into FITS file.
422 *
423 * @param[in] fits FITS file.
424 *
425 * Write the COSI space craft into FITS file.
426 ***************************************************************************/
428{
429 // Continue only if there are pointings
430 if (size() > 0) {
431
432 // Write pointings
433 write_pointings(fits);
434
435 // Write livetimes
436 write_livetimes(fits);
437
438 // Write Good Time Intervals
439 m_gti.write(fits);
440
441 } // endif: there were pointings
442
443 // Return
444 return;
445}
446
447
448/***********************************************************************//**
449 * @brief Print space craft information
450 *
451 * @param[in] chatter Chattiness.
452 * @return String containing space craft information.
453 ***************************************************************************/
454std::string GCOSSpaceCraft::print(const GChatter& chatter) const
455{
456 // Initialise result string
457 std::string result;
458
459 // Continue only if chatter is not silent
460 if (chatter != SILENT) {
461
462 // Append header
463 result.append("=== GCOSSpaceCraft ===");
464
465 // Append information
466 result.append("\n"+gammalib::parformat("Pointings"));
467 result.append(gammalib::str(size()));
468 result.append("\n"+gammalib::parformat("Ontime"));
469 result.append(gammalib::str(ontime())+" sec");
470 result.append("\n"+gammalib::parformat("Livetime"));
471 result.append(gammalib::str(livetime())+" sec");
472 result.append("\n"+gammalib::parformat("Deadtime correction"));
473 result.append(gammalib::str(m_deadc));
474 result.append("\n"+m_gti.print(gammalib::reduce(chatter)));
475
476 } // endif: chatter was not silent
477
478 // Return result
479 return result;
480}
481
482
483/*==========================================================================
484 = =
485 = Private methods =
486 = =
487 ==========================================================================*/
488
489/***********************************************************************//**
490 * @brief Initialise class members
491 ***************************************************************************/
493{
494 // Initialise members
495 m_gti.clear();
496 m_livetimes.clear();
497 m_pointings.clear();
498 m_ontime = 0.0;
499 m_livetime = 0.0;
500 m_deadc = 0.0;
501
502 // Return
503 return;
504}
505
506
507/***********************************************************************//**
508 * @brief Copy class members
509 *
510 * @param[in] spacecraft COSI space craft.
511 ***************************************************************************/
513{
514 // Copy members
515 m_gti = spacecraft.m_gti;
516 m_livetimes = spacecraft.m_livetimes;
517 m_pointings = spacecraft.m_pointings;
518 m_ontime = spacecraft.m_ontime;
519 m_livetime = spacecraft.m_livetime;
520 m_deadc = spacecraft.m_deadc;
521
522 // Return
523 return;
524}
525
526
527/***********************************************************************//**
528 * @brief Delete class members
529 ***************************************************************************/
531{
532 // Return
533 return;
534}
535
536
537/***********************************************************************//**
538 * @brief Load COSI space craft file from ORI file
539 *
540 * @param[in] filename Space craft ORI file name.
541 *
542 * Load space craft information from an ORI file. The ORI file is a
543 * whitespace separated list of 10 values, with a trailer and footer line.
544 * This method does not depend on the existence of the trailer and footer
545 * line but it scans all lines that have exactly 10 entries.
546 *
547 * The method computes the Good Time Intervals that are defined by the ORI
548 * file by collecting entries that have non-zero livetime in a single
549 * interval.
550 ***************************************************************************/
552{
553 // Clear instance
554 clear();
555
556 // Allocate line buffer
557 const int n = 10000;
558 char line[n];
559
560 // Expand environment variables
561 std::string fname = gammalib::expand_env(filename.url());
562
563 // Open CSV table (read-only)
564 FILE* fptr = std::fopen(fname.c_str(), "r");
565 if (fptr == NULL) {
566 std::string msg = "Unable to open file \""+fname+"\" for read access. "
567 "Please specify a readable file.";
569 }
570
571 // Initialise file parser
572 GTime tstart;
573 GTime time;
574 double altitude = 0.0;
575 double livetime = 0.0;
576 double gti_livetime = 0.0;
577
578 // Read lines
579 while (std::fgets(line, n, fptr) != NULL) {
580
581 // Get line with leading and trailing whitespace removed
582 std::string sline =
583 gammalib::strip_chars(gammalib::strip_whitespace(std::string(line)),"\n");
584
585 // Skip empty lines
586 if (sline.length() == 0) {
587 continue;
588 }
589
590 // Split line in elements
591 std::vector<std::string> elements = gammalib::split(sline, " ");
592 for (int i = 0; i < elements.size(); ++i) {
593 elements[i] = gammalib::strip_whitespace(elements[i]);
594 }
595
596 // Skip lines that have not 9 elements
597 if (elements.size() != 10) {
598 continue;
599 }
600
601 // Get information
602 time = gammalib::cos_time(gammalib::todouble(elements[1]));
603 GSkyDir sc_x;
604 sc_x.lb_deg(gammalib::todouble(elements[2]), gammalib::todouble(elements[3]));
605 GSkyDir sc_z;
606 sc_z.lb_deg(gammalib::todouble(elements[4]), gammalib::todouble(elements[5]));
607 altitude = gammalib::todouble(elements[6]);
608 GSkyDir earth_zenith;
609 earth_zenith.lb_deg(gammalib::todouble(elements[7]), gammalib::todouble(elements[8]));
610 livetime = gammalib::todouble(elements[9]);
611
612 // Derive Earth nadir direction
613 GSkyDir earth_nadir(earth_zenith);
614 earth_nadir.rotate(0.0, gammalib::pi);
615
616 // If current GTI lifetime is zero and current pointing has a positive
617 // lifetime then start a new GTI
618 if ((gti_livetime == 0.0) && (livetime > 0.0)) {
619 tstart = time;
620 gti_livetime += livetime;
621 }
622
623 // ... otherwise update the Good Time Interval
624 else {
625
626 // If GTI lifetime is positive and livetime is zero then append Good
627 // Time Interval and livetime
628 if ((gti_livetime > 0.0) && (livetime == 0.0)) {
629
630 // Append Good Time Interval and livetime
631 m_gti.append(tstart, time);
632 m_livetimes.push_back(gti_livetime);
633
634 // Update ontime and livetime
635 m_ontime += (time - tstart);
636 m_livetime += gti_livetime;
637
638 // Reset livetime for next GTI
639 gti_livetime = 0.0;
640
641 }
642
643 // ... otherwise update livetime
644 else {
645 gti_livetime += livetime;
646 }
647
648 } // endelse: updated Good Time Interval
649
650 // Build COSI pointing
651 GCOSPointing pointing;
652 pointing.time(time);
653 pointing.sc_x(sc_x);
654 pointing.sc_z(sc_z);
655 pointing.altitude(altitude);
656 pointing.earth_zenith(earth_zenith);
657 pointing.earth_nadir(earth_nadir);
658 pointing.livetime(livetime);
659
660 // Append COSI pointing
661 m_pointings.push_back(pointing);
662
663 } // endwhile: looped over lines
664
665 // Set livetime of last element to zero
666 if (size() > 0) {
667 m_pointings[size()-1].livetime(0.0);
668 }
669
670 // Correct lifetime since last value is to be ignored
671 gti_livetime -= livetime;
672
673 // If GTI lifetime is pending then append a final GTI
674 if ((gti_livetime > 0.0) && (time > tstart)) {
675
676 // Append Good Time Interval and livetime
677 m_gti.append(tstart, time);
678 m_livetimes.push_back(gti_livetime);
679
680 // Update ontime and livetime
681 m_ontime += (time - tstart);
682 m_livetime += gti_livetime;
683
684 } // endif: GTI lifetime was pending
685
686 // Close file
687 std::fclose(fptr);
688
689 // Compute deadtime correction
690 if (m_ontime > 0.0) {
692 }
693
694 // Return
695 return;
696}
697
698
699/***********************************************************************//**
700 * @brief Load COSI space craft file from FITS file
701 *
702 * @param[in] filename Space craft FITS file name.
703 ***************************************************************************/
705{
706 // Clear instance
707 clear();
708
709 // Open FITS file
710 GFits fits(filename);
711
712 // Read event list from FITS file
713 read(fits);
714
715 // Close FITS file
716 fits.close();
717
718 // Return
719 return;
720}
721
722
723/***********************************************************************//**
724 * @brief Read pointings from FITS file.
725 *
726 * @param[in] fits FITS file.
727 *
728 * Read pointings from FITS file.
729 ***************************************************************************/
731{
732 // Get reference to FITS table
733 const GFitsTable& table = *fits.table("POINTINGS");
734
735 // Extract number of pointings in FITS file
736 int num = table.nrows();
737
738 // If there are pointings then read them
739 if (num > 0) {
740
741 // Allocate pointings
742 m_pointings.resize(num);
743
744 // Get column pointers
745 const GFitsTableCol* col_time = table["TIME"];
746 const GFitsTableCol* col_sc_x_glon = table["SC_X_GLON"];
747 const GFitsTableCol* col_sc_x_glat = table["SC_X_GLAT"];
748 const GFitsTableCol* col_sc_z_glon = table["SC_Z_GLON"];
749 const GFitsTableCol* col_sc_z_glat = table["SC_Z_GLAT"];
750 const GFitsTableCol* col_altitude = table["ALTITUDE"];
751 const GFitsTableCol* col_earth_zenith_glon = table["EARTH_ZENITH_GLON"];
752 const GFitsTableCol* col_earth_zenith_glat = table["EARTH_ZENITH_GLAT"];
753 const GFitsTableCol* col_livetime = table["LIVETIME"];
754
755 // Extract pointing data from columns
756 for (int i = 0; i < num; ++i) {
757
758 // Set directions
759 GSkyDir sc_x;
760 GSkyDir sc_z;
761 GSkyDir earth_zenith;
762 sc_x.lb_deg(col_sc_x_glon->real(i), col_sc_x_glat->real(i));
763 sc_z.lb_deg(col_sc_z_glon->real(i), col_sc_z_glat->real(i));
764 earth_zenith.lb_deg(col_earth_zenith_glon->real(i), col_earth_zenith_glat->real(i));
765
766 // Derive Earth nadir direction
767 GSkyDir earth_nadir(earth_zenith);
768 earth_nadir.rotate(0.0, gammalib::pi);
769
770 // Set pointings
771 m_pointings[i].time(gammalib::cos_time(col_time->real(i)));
772 m_pointings[i].sc_x(sc_x);
773 m_pointings[i].sc_z(sc_z);
774 m_pointings[i].altitude(col_altitude->real(i));
775 m_pointings[i].earth_zenith(earth_zenith);
776 m_pointings[i].earth_nadir(earth_nadir);
777 m_pointings[i].livetime(col_livetime->real(i));
778
779 } // endfor: looped over pointings
780
781 // Read ontime, livetime and deadtime correction factor
782 m_ontime = table.real("ONTIME");
783 m_livetime = table.real("LIVETIME");
784 m_deadc = table.real("DEADC");
785
786 } // endif: there were pointings
787
788 // Return
789 return;
790}
791
792
793/***********************************************************************//**
794 * @brief Read livetimes from FITS file.
795 *
796 * @param[in] fits FITS file.
797 *
798 * Read livetimes from FITS file.
799 ***************************************************************************/
801{
802 // Get reference to FITS table
803 const GFitsTable& table = *fits.table("LIVETIMES");
804
805 // Extract number of livetimes in FITS file
806 int num = table.nrows();
807
808 // If there are livetimes then read them
809 if (num > 0) {
810
811 // Allocate livetimes
812 m_livetimes.resize(num);
813
814 // Get column pointer
815 const GFitsTableCol* col_livetime = table["LIVETIME"];
816
817 // Get data
818 for (int i = 0; i < num; ++i) {
819 m_livetimes[i] = col_livetime->real(i);
820 }
821
822 } // endif: there were livetimes
823
824 // Return
825 return;
826}
827
828
829/***********************************************************************//**
830 * @brief Write pointings into FITS file.
831 *
832 * @param[in] fits FITS file.
833 *
834 * Write pointings into FITS file.
835 ***************************************************************************/
837{
838 // Continue only if there are pointings
839 if (size() > 0) {
840
841 // Allocate FITS binary table
842 GFitsBinTable table;
843
844 // Allocate columns
845 GFitsTableDoubleCol col_time("TIME", size());
846 GFitsTableDoubleCol col_sc_x_glon("SC_X_GLON", size());
847 GFitsTableDoubleCol col_sc_x_glat("SC_X_GLAT", size());
848 GFitsTableDoubleCol col_sc_z_glon("SC_Z_GLON", size());
849 GFitsTableDoubleCol col_sc_z_glat("SC_Z_GLAT", size());
850 GFitsTableDoubleCol col_altitude("ALTITUDE", size());
851 GFitsTableDoubleCol col_earth_zenith_glon("EARTH_ZENITH_GLON", size());
852 GFitsTableDoubleCol col_earth_zenith_glat("EARTH_ZENITH_GLAT", size());
853 GFitsTableDoubleCol col_livetime("LIVETIME", size());
854
855 // Set units of columns
856 // (see http://fits.gsfc.nasa.gov/standard30/fits_standard30aa.pdf)
857 col_time.unit("s");
858 col_sc_x_glon.unit("deg");
859 col_sc_x_glat.unit("deg");
860 col_sc_z_glon.unit("deg");
861 col_sc_z_glat.unit("deg");
862 col_altitude.unit("km");
863 col_earth_zenith_glon.unit("deg");
864 col_earth_zenith_glat.unit("deg");
865 col_livetime.unit("s");
866
867 // Fill columns
868 for (int i = 0; i < size(); ++i) {
869 col_time(i) = gammalib::cos_seconds(m_pointings[i].time());
870 col_sc_x_glon(i) = m_pointings[i].sc_x().l_deg();
871 col_sc_x_glat(i) = m_pointings[i].sc_x().b_deg();
872 col_sc_z_glon(i) = m_pointings[i].sc_z().l_deg();
873 col_sc_z_glat(i) = m_pointings[i].sc_z().b_deg();
874 col_altitude(i) = m_pointings[i].altitude();
875 col_earth_zenith_glon(i) = m_pointings[i].earth_zenith().l_deg();
876 col_earth_zenith_glat(i) = m_pointings[i].earth_zenith().b_deg();
877 col_livetime(i) = m_pointings[i].livetime();
878 }
879
880 // Append columns to table
881 table.append(col_time);
882 table.append(col_sc_x_glon);
883 table.append(col_sc_x_glat);
884 table.append(col_sc_z_glon);
885 table.append(col_sc_z_glat);
886 table.append(col_altitude);
887 table.append(col_earth_zenith_glon);
888 table.append(col_earth_zenith_glat);
889 table.append(col_livetime);
890
891 // Set extension name
892 table.extname("POINTINGS");
893
894 // Write ontime, livetime and deadtime correction factor
895 table.card("ONTIME", m_ontime, "[s] Ontime");
896 table.card("LIVETIME", m_livetime, "[s] Deadtime");
897 table.card("DEADC", m_deadc, "Deadtime correction factor");
898
899 // Append table to FITS file
900 fits.append(table);
901
902 } // endif: there were pointings
903
904 // Return
905 return;
906}
907
908
909/***********************************************************************//**
910 * @brief Write livetimes into FITS file.
911 *
912 * @param[in] fits FITS file.
913 *
914 * Write livetimes into FITS file.
915 ***************************************************************************/
917{
918 // Determine number of livetimes
919 int num = m_livetimes.size();
920
921 // Continue only if there are lifetimes
922 if (num > 0) {
923
924 // Allocate FITS binary table
925 GFitsBinTable table;
926
927 // Allocate column for livetimes table
928 GFitsTableDoubleCol col_livetime("LIVETIME", num);
929
930 // Set units of column
931 // (see http://fits.gsfc.nasa.gov/standard30/fits_standard30aa.pdf)
932 col_livetime.unit("s");
933
934 // Fill column
935 for (int i = 0; i < num; ++i) {
936 col_livetime(i) = m_livetimes[i];
937 }
938
939 // Append column to table
940 table.append(col_livetime);
941
942 // Set extension name
943 table.extname("LIVETIMES");
944
945 // Write ontime, livetime and deadtime correction factor
946 table.card("ONTIME", m_ontime, "[s] Ontime");
947 table.card("LIVETIME", m_livetime, "[s] Deadtime");
948 table.card("DEADC", m_deadc, "Deadtime correction factor");
949
950 // Append table to FITS file
951 fits.append(table);
952
953 } // endif: there were lifetimes
954
955 // Return
956 return;
957}
958
959
#define G_LOAD_ORI
COSI space craft class definition.
Definition of COSI tools.
Exception handler interface definition.
Filename class interface definition.
FITS binary table class definition.
FITS table column abstract base class definition.
FITS table double column class interface definition.
FITS table abstract base class interface definition.
FITS file class interface definition.
Sky direction class interface definition.
Sky map class definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
#define G_OPERATOR
COSI pointing class.
const double & livetime(void) const
Return livetime.
const GSkyDir & sc_z(void) const
Return space craft Z-axis.
const GSkyDir & earth_nadir(void) const
Return direction of Earth's nadir at space craft location.
const double & altitude(void) const
Return space craft altitude in km.
const GSkyDir & sc_x(void) const
Return space craft X-axis.
const GTime & time(void) const
Return time stamp.
const GSkyDir & earth_zenith(void) const
Return direction of Earth's zenith at space craft location.
COSI space craft class.
const GGti & gti(void) const
Return Good Time Intervals.
std::vector< double > m_livetimes
Livetimes for each Good Time Interval (sec)
void load_fits(const GFilename &filename)
Load COSI space craft file from FITS file.
double m_livetime
Livetime (sec)
void load_ori(const GFilename &filename)
Load COSI space craft file from ORI file.
int size(void) const
Return number of pointing entries.
void read_livetimes(const GFits &fits)
Read livetimes from FITS file.
void write_livetimes(GFits &fits) const
Write livetimes into FITS file.
GCOSSpaceCraft(void)
Void constructor.
GCOSSpaceCraft & operator=(const GCOSSpaceCraft &spacecraft)
Assignment operator.
double m_deadc
Deadtime correction.
GGti m_gti
Good Time Intervals.
double m_ontime
Ontime (sec)
void clear(void)
Clear space craft.
void free_members(void)
Delete class members.
std::string print(const GChatter &chatter=NORMAL) const
Print space craft information.
void copy_members(const GCOSSpaceCraft &spacecraft)
Copy class members.
void read(const GFits &fits)
Read COSI space craft FITS file.
const double & ontime(void) const
Return ontime in seconds.
void load(const GFilename &filename)
Load COSI space craft file.
void write(GFits &fits) const
Write COSI space craft into FITS file.
std::vector< GCOSPointing > m_pointings
Pointings.
void read_pointings(const GFits &fits)
Read pointings from FITS file.
void write_pointings(GFits &fits) const
Write pointings into FITS file.
virtual ~GCOSSpaceCraft(void)
Destructor.
void save(const GFilename &filename, const bool &clobber=false) const
Save COSI space craft FITS file.
GCOSSpaceCraft * clone(void) const
Clone space craft.
void init_members(void)
Initialise class members.
GCOSPointing & operator[](const int &index)
Return reference to COSI pointing.
const double & livetime(void) const
Return livetime in seconds.
Filename class.
Definition GFilename.hpp:62
bool is_fits(void) const
Checks whether file is a FITS file.
std::string url(void) const
Return Uniform Resource Locator (URL)
FITS binary table class.
const std::string & extname(void) const
Return extension name.
Definition GFitsHDU.hpp:162
double real(const std::string &keyname) const
Return card value as double precision.
Definition GFitsHDU.hpp:423
GFitsHeaderCard & card(const int &cardno)
Return header card.
Definition GFitsHDU.hpp:259
Abstract interface for FITS table column.
virtual double real(const int &row, const int &inx=0) const =0
void unit(const std::string &unit)
Set column unit.
FITS table double column.
Abstract interface for FITS table.
GFitsTableCol * append(const GFitsTableCol &column)
Append column to the table.
const int & nrows(void) const
Return number of rows in table.
FITS file class.
Definition GFits.hpp:63
void saveto(const GFilename &filename, const bool &clobber=false)
Saves to specified FITS file.
Definition GFits.cpp:1293
GFitsHDU * append(const GFitsHDU &hdu)
Append HDU to FITS file.
Definition GFits.cpp:678
void close(void)
Close FITS file.
Definition GFits.cpp:1342
GFitsTable * table(const int &extno)
Get pointer to table HDU.
Definition GFits.cpp:482
std::string print(const GChatter &chatter=NORMAL) const
Print Good Time Intervals.
Definition GGti.cpp:1125
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:815
void read(const GFitsTable &table)
Read Good Time Intervals and time reference from FITS table.
Definition GGti.cpp:772
void append(const GTime &tstart, const GTime &tstop)
Append Good Time Interval.
Definition GGti.cpp:270
void clear(void)
Clear Good Time Intervals.
Definition GGti.cpp:238
Sky direction class.
Definition GSkyDir.hpp:62
void lb_deg(const double &l, const double &b)
Set galactic sky direction (degrees)
Definition GSkyDir.cpp:300
void rotate(const double &phi, const double &theta)
Rotate sky direction by zenith and azimuth angle.
Definition GSkyDir.cpp:527
double dist(const GSkyDir &dir) const
Compute angular distance between sky directions in radians.
Definition GSkyDir.hpp:273
Sky map class.
Definition GSkyMap.hpp:89
GSkyMap extract(const int &map, const int &nmaps=1) const
Extract maps into a new sky map object.
Definition GSkyMap.cpp:2139
Time class.
Definition GTime.hpp:55
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1136
double cos_seconds(const GTime &time)
Convert GammaLib time to COSI seconds.
Definition GCOSTools.cpp:71
GTime cos_time(const double &seconds)
Convert COSI seconds to GammaLib time.
Definition GCOSTools.cpp:49
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:508
const double pi
Definition GMath.hpp:35
double todouble(const std::string &arg)
Convert string into double precision value.
Definition GTools.cpp:919
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition GTools.cpp:99
std::string expand_env(const std::string &arg)
Expand environment variables in string.
Definition GTools.cpp:233
GChatter reduce(const GChatter &chatter)
Reduce chattiness by one level.
Definition GTypemaps.hpp:65
const std::string extname_gti
Definition GGti.hpp:45
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition GTools.cpp:976
std::string strip_chars(const std::string &arg, const std::string &chars)
Strip leading and trailing character from string.
Definition GTools.cpp:113