GammaLib 2.0.0
Loading...
Searching...
No Matches
GSPIEventCube.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GSPIEventCube.cpp - INTEGRAL/SPI event bin container class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2020-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 GSPIEventCube.hpp
23 * @brief INTEGRAL/SPI event bin container class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GSPIEventCube.hpp"
32#include "GSPITools.hpp"
33#include "GSPIInstDir.hpp"
34#include "GSkyDir.hpp"
35#include "GEnergy.hpp"
36#include "GTime.hpp"
37
38/* __ Method name definitions ____________________________________________ */
39#define G_NAXIS "GSPIEventCube::naxis(int)"
40#define G_MODEL_COUNTS "GSPIEventCube::model_counts(int&)"
41#define G_SET_ENERGIES "GSPIEventCube::set_energies()"
42#define G_SET_TIMES "GSPIEventCube::set_times()"
43#define G_SET_BIN "GSPIEventCube::set_bin(int&)"
44#define G_READ_FITS "GSPIEventCube::read(GFits&)"
45#define G_READ_EBDS "GSPIEventCube::read_ebds(GFitsTable*)"
46#define G_READ_PNT "GSPIEventCube::read_pnt(GFitsTable*, GFitsTable*)"
47#define G_READ_MODELS "GSPIEventCube::read_models(GFits&)"
48#define G_PTID "GSPIEventCube::ptid(int&)"
49#define G_DIR "GSPIEventCube::dir(int&, int&)"
50#define G_SPI_X "GSPIEventCube::spi_x(int&)"
51#define G_SPI_Z "GSPIEventCube::spi_z(int&)"
52
53/* __ Macros _____________________________________________________________ */
54
55/* __ Coding definitions _________________________________________________ */
56
57/* __ Debug definitions __________________________________________________ */
58
59
60
61/*==========================================================================
62 = =
63 = Constructors/destructors =
64 = =
65 ==========================================================================*/
66
67/***********************************************************************//**
68 * @brief Void constructor
69 *
70 * Constructs an empty INTEGRAL/SPI event cube.
71 ***************************************************************************/
73{
74 // Initialise members
76
77 // Return
78 return;
79}
80
81
82/***********************************************************************//**
83 * @brief Observation Group constructor
84 *
85 * @param[in] filename Observation Group FITS file name.
86 *
87 * Construct an INTEGRAL/SPI event cube from an Observation Group.
88 ***************************************************************************/
90{
91 // Initialise members
93
94 // Load event cube
95 load(filename);
96
97 // Return
98 return;
99}
100
101
102/***********************************************************************//**
103 * @brief Copy constructor
104 *
105 * @param[in] cube INTEGRAL/SPI event cube.
106 ***************************************************************************/
108{
109 // Initialise members
110 init_members();
111
112 // Copy members
113 copy_members(cube);
114
115 // Return
116 return;
117}
118
119
120/***********************************************************************//**
121 * @brief Destructor
122 ***************************************************************************/
124{
125 // Free members
126 free_members();
127
128 // Return
129 return;
130}
131
132
133/*==========================================================================
134 = =
135 = Operators =
136 = =
137 ==========================================================================*/
138
139/***********************************************************************//**
140 * @brief Assignment operator
141 *
142 * @param[in] cube INTEGRAL/SPI event cube.
143 * @return INTEGRAL/SPI event cube.
144 ***************************************************************************/
146{
147 // Execute only if object is not identical
148 if (this != &cube) {
149
150 // Copy base class members
151 this->GEventCube::operator=(cube);
152
153 // Free members
154 free_members();
155
156 // Initialise members
157 init_members();
158
159 // Copy members
160 copy_members(cube);
161
162 } // endif: object was not identical
163
164 // Return this object
165 return *this;
166}
167
168
169/***********************************************************************//**
170 * @brief Event bin access operator
171 *
172 * @param[in] index Event index [0,...,size()-1].
173 * @return Pointer to event bin.
174 *
175 * Returns pointer to an event bin. Note that the returned pointer is in
176 * fact always the same, but the method sets the pointers within the
177 * event bin so that they point to the appropriate information.
178 ***************************************************************************/
180{
181 // Set event bin
182 set_bin(index);
183
184 // Return pointer
185 return (&m_bin);
186}
187
188
189/***********************************************************************//**
190 * @brief Event bin access operator (const version)
191 *
192 * @param[in] index Event index [0,...,size()-1].
193 * @return Const pointer to event bin.
194 *
195 * Returns pointer to an event bin. Note that the returned pointer is in
196 * fact always the same, but the method sets the pointers within the
197 * event bin so that they point to the appropriate information.
198 ***************************************************************************/
199const GSPIEventBin* GSPIEventCube::operator[](const int& index) const
200{
201 // Set event bin (circumvent const correctness)
202 const_cast<GSPIEventCube*>(this)->set_bin(index);
203
204 // Return pointer
205 return (&m_bin);
206}
207
208
209/*==========================================================================
210 = =
211 = Public methods =
212 = =
213 ==========================================================================*/
214
215/***********************************************************************//**
216 * @brief Clear INTEGRAL/SPI event cube
217 *
218 * Clears INTEGRAL/SPI event cube by resetting all class members to an
219 * initial state. Any information that was present before will be lost.
220 ***************************************************************************/
222{
223 // Free class members (base and derived classes, derived class first)
224 free_members();
226 this->GEvents::free_members();
227
228 // Initialise members
229 this->GEvents::init_members();
231 init_members();
232
233 // Return
234 return;
235}
236
237
238/***********************************************************************//**
239 * @brief Clone event cube
240 *
241 * @return Pointer to deep copy of INTEGRAL/SPI event cube.
242 ***************************************************************************/
244{
245 return new GSPIEventCube(*this);
246}
247
248
249/***********************************************************************//**
250 * @brief Return number of bins in axis
251 *
252 * @param[in] axis Axis [0,...,dim()-1].
253 * @return Number of bins in axis.
254 *
255 * @exception GException::out_of_range
256 * Axis is out of range.
257 *
258 * Returns the number of bins along a given event cube @p axis.
259 ***************************************************************************/
260int GSPIEventCube::naxis(const int& axis) const
261{
262 // Optionally check if the axis is valid
263 #if defined(G_RANGE_CHECK)
264 if (axis < 0 || axis >= dim()) {
265 throw GException::out_of_range(G_NAXIS, "INTEGRAL/SPI event cube axis",
266 axis, dim());
267 }
268 #endif
269
270 // Setup const pointer array that points to relevant axis size
271 const int* ptr[3] = {&m_num_pt, &m_num_det, &m_num_ebin};
272
273 // Set number of bins dependent on axis
274 int naxis = *ptr[axis];
275
276 // Return result
277 return naxis;
278}
279
280
281/***********************************************************************//**
282 * @brief Load INTEGRAL/SPI event cube from Observation Group
283 *
284 * @param[in] filename Observation Group FITS file name.
285 *
286 * Loads data from an Observation Group FITS file into an INTEGRAL/SPI
287 * event cube.
288 ***************************************************************************/
289void GSPIEventCube::load(const GFilename& filename)
290{
291 #pragma omp critical(GSPIEventCube_load)
292 {
293 // Clear object
294 clear();
295
296 // Open FITS file
297 GFits fits(filename);
298
299 // Read event cube from FITS file
300 read(fits);
301
302 // Close FITS file
303 fits.close();
304 }
305
306 // Return
307 return;
308}
309
310
311/***********************************************************************//**
312 * @brief Save INTEGRAL/SPI event cube into FITS file
313 *
314 * @param[in] filename FITS file name.
315 * @param[in] clobber Overwrite existing FITS file?
316 *
317 * Saves the INTEGRAL/SPI event cube into a FITS file.
318 ***************************************************************************/
319void GSPIEventCube::save(const GFilename& filename, const bool& clobber) const
320{
321 // Create empty FITS file
322 GFits fits;
323
324 // Write event cube into FITS file
325 write(fits);
326
327 // Save FITS file
328 fits.saveto(filename, clobber);
329
330 // Close FITS file
331 fits.close();
332
333 // Return
334 return;
335}
336
337
338/***********************************************************************//**
339 * @brief Read INTEGRAL/SPI event cube from Observation Group FITS file
340 *
341 * @param[in] fits Observation Group FITS file.
342 *
343 * @exception GException::invalid_value
344 * Observation Group FITS file invalid.
345 *
346 * Reads an INTEGRAL/SPI event cube from an Observation Group FITS file.
347 * The following extension are mandatory
348 *
349 * "SPI.-EBDS-SET"
350 * "SPI.-OBS.-PNT"
351 * "SPI.-OBS.-GTI"
352 * "SPI.-OBS.-DSP"
353 * "SPI.-OBS.-DTI"
354 *
355 * Optional extensions are
356 *
357 * "SPI.-SDET-SPE"
358 * "SPI.-BMOD-DSP"
359 *
360 ***************************************************************************/
361void GSPIEventCube::read(const GFits& fits)
362{
363 // Clear object
364 clear();
365
366 // Get table pointers
367 const GFitsTable* ebds = gammalib::spi_hdu(fits, "SPI.-EBDS-SET");
368 const GFitsTable* pnt = gammalib::spi_hdu(fits, "SPI.-OBS.-PNT");
369 const GFitsTable* gti = gammalib::spi_hdu(fits, "SPI.-OBS.-GTI");
370 const GFitsTable* dsp = gammalib::spi_hdu(fits, "SPI.-OBS.-DSP");
371 const GFitsTable* dti = gammalib::spi_hdu(fits, "SPI.-OBS.-DTI");
372
373 // Throw an exception if one of the mandatory HDUs is missing
374 if (ebds == NULL) {
375 std::string msg = "Extension \"SPI.-EBDS-SET\" not found in "
376 "Observation Group FITS file \""+
377 fits.filename().url()+"\". Please specify a "
378 "valid Observation Group.";
380 }
381 if (pnt == NULL) {
382 std::string msg = "Extension \"SPI.-OBS.-PNT\" not found in "
383 "Observation Group FITS file \""+
384 fits.filename().url()+"\". Please specify a "
385 "valid Observation Group.";
387 }
388 if (gti == NULL) {
389 std::string msg = "Extension \"SPI.-OBS.-GTI\" not found in "
390 "Observation Group FITS file \""+
391 fits.filename().url()+"\". Please specify a "
392 "valid Observation Group.";
394 }
395 if (dsp == NULL) {
396 std::string msg = "Extension \"SPI.-OBS.-DSP\" not found in "
397 "Observation Group FITS file \""+
398 fits.filename().url()+"\". Please specify a "
399 "valid Observation Group.";
401 }
402 if (dti == NULL) {
403 std::string msg = "Extension \"SPI.-OBS.-DTI\" not found in "
404 "Observation Group FITS file \""+
405 fits.filename().url()+"\". Please specify a "
406 "valid Observation Group.";
408 }
409
410 // Determine dataspace dimensions from FITS tables
411 m_num_pt = dsp->integer("PT_NUM");
412 m_num_det = dsp->integer("DET_NUM");
413 m_num_ebin = dsp->integer("EBIN_NUM");
414
415 // Get number of sky and background models
416 m_num_sky = gammalib::spi_num_hdus(fits, "SPI.-SDET-SPE");
417 m_num_bgm = gammalib::spi_num_hdus(fits, "SPI.-BMOD-DSP");
418
419 // Allocate data
420 alloc_data();
421
422 // Read energy boundaries
423 read_ebds(ebds);
424
425 // Read pointing information
426 read_pnt(pnt, gti);
427
428 // Read Good Time Intervals
429 read_gti(gti);
430
431 // Read dead time information
432 read_dti(dti);
433
434 // Read detector spectra
435 read_dsp(dsp);
436
437 // Read models
438 read_models(fits);
439
440 // Free HDU pointers
441 if (ebds != NULL) delete ebds;
442 if (pnt != NULL) delete pnt;
443 if (gti != NULL) delete gti;
444 if (dsp != NULL) delete dsp;
445 if (dti != NULL) delete dti;
446
447 // Prepare event bin
448 init_bin();
449
450 // Return
451 return;
452}
453
454
455/***********************************************************************//**
456 * @brief Write INTEGRAL/SPI event cube into FITS file.
457 *
458 * @param[in] file FITS file.
459 *
460 * Writes the INTEGRAL/SPI event cube into a FITS file.
461 ***************************************************************************/
463{
464 // TODO: Here you have to implement the interface between the class and
465 // the event cube FITS file.
466
467 // Return
468 return;
469}
470
471
472/***********************************************************************//**
473 * @brief Return number of events in cube
474 *
475 * @return Number of events in event cube.
476 *
477 * This method returns the number of events in the event cube rounded to the
478 * nearest integer.
479 ***************************************************************************/
481{
482 // Initialise result
483 double number = 0.0;
484
485 // Compute sum of all events
486 if (m_dsp_size > 0) {
487 for (int i = 0; i < m_dsp_size; ++i) {
488 number += m_counts[i];
489 }
490 }
491
492 // Return
493 return int(number+0.5);
494}
495
496
497/***********************************************************************//**
498 * @brief Return total ontime
499 *
500 * @return Total ontime.
501 *
502 * Returns the total ontime in the event cube. The total ontime is the sum
503 * of the ontime of all pointings and detectors, divided by the number of
504 * detectors that were active (determine by positive ontime values).
505 ***************************************************************************/
506double GSPIEventCube::ontime(void) const
507{
508 // Initialise result
509 double ontime = 0.0;
510
511 // Loop over all pointings
512 for (int ipt = 0; ipt < m_num_pt; ++ipt) {
513
514 // Initialise mean ontime and number of active detectors for this
515 // pointing
516 double mean_ontime = 0.0;
517 double num_active_det = 0.0;
518
519 // Loop over all detectors
520 for (int idet = 0; idet < m_num_det; ++idet) {
521
522 // Get row index in table
523 int irow = ipt * m_num_det + idet;
524
525 // If detector has positive ontime then count it for the mean
526 // ontime
527 if (m_ontime[irow] > 0.0) {
528 mean_ontime += m_ontime[irow];
529 num_active_det += 1.0;
530 }
531
532 } // endfor: looped over all detectors
533
534 // Compute mean ontime for this pointing
535 if (num_active_det > 0.0) {
536 mean_ontime /= num_active_det;
537 }
538 else {
539 mean_ontime = 0.0;
540 }
541
542 // Add mean ontime to total sum
543 ontime += mean_ontime;
544
545 } // endfor: looped over all pointings
546
547 // Return ontime
548 return ontime;
549}
550
551
552/***********************************************************************//**
553 * @brief Return total livetime
554 *
555 * @return Total livetime.
556 *
557 * Returns the total livetime in the event cube. The total livetime is the
558 * sum of the livetime of all pointings and detectors, divided by the number
559 * of detectors that were active (determine by positive livetime values).
560 ***************************************************************************/
561double GSPIEventCube::livetime(void) const
562{
563 // Initialise result
564 double livetime = 0.0;
565
566 // Loop over all pointings
567 for (int ipt = 0; ipt < m_num_pt; ++ipt) {
568
569 // Initialise mean livetime and number of active detectors for this
570 // pointing
571 double mean_livetime = 0.0;
572 double num_active_det = 0.0;
573
574 // Loop over all detectors
575 for (int idet = 0; idet < m_num_det; ++idet) {
576
577 // Get row index in table
578 int irow = ipt * m_num_det + idet;
579
580 // If detector has positive livetime then count it for the mean
581 // livetime
582 if (m_livetime[irow] > 0.0) {
583 mean_livetime += m_livetime[irow];
584 num_active_det += 1.0;
585 }
586
587 } // endfor: looped over all detectors
588
589 // Compute mean livetime for this pointing
590 if (num_active_det > 0.0) {
591 mean_livetime /= num_active_det;
592 }
593 else {
594 mean_livetime = 0.0;
595 }
596
597 // Add mean livetime to total sum
598 livetime += mean_livetime;
599
600 } // endfor: looped over all pointings
601
602 // Return livetime
603 return livetime;
604}
605
606
607/***********************************************************************//**
608 * @brief Return number of events in model
609 *
610 * @param[in] index Model index.
611 * @return Number of events in event cube.
612 *
613 * @exception GException::out_of_range
614 * Invalid model index
615 *
616 * Returns the total number of counts in model.
617 ***************************************************************************/
618double GSPIEventCube::model_counts(const int& index) const
619{
620 // Initialise result
621 double counts = 0.0;
622
623 // Compute total number of models
624 int num_models = m_num_sky + m_num_bgm;
625
626 // Optionally check if the model index is valid
627 #if defined(G_RANGE_CHECK)
628 if (index < 0 || index >= num_models) {
629 throw GException::out_of_range(G_MODEL_COUNTS, "Invalid model index",
630 index, num_models);
631 }
632 #endif
633
634 // Compute sum of all events in model
635 if (m_dsp_size > 0) {
636 for (int i = 0; i < m_dsp_size; ++i) {
637 counts += m_models[i*num_models + index];
638 }
639 }
640
641 // Return
642 return counts;
643}
644
645
646/***********************************************************************//**
647 * @brief Return pointing identifier
648 *
649 * @param[in] ipt Pointing index.
650 * @return Pointing identifier.
651 *
652 * @exception GException::out_of_range
653 * Invalid pointing index
654 *
655 * Returns the pointing identifier for the specified index.
656 ***************************************************************************/
657const std::string& GSPIEventCube::ptid(const int& ipt) const
658{
659 // Optionally check if the pointing index is valid
660 #if defined(G_RANGE_CHECK)
661 if (ipt < 0 || ipt >= m_num_pt) {
662 throw GException::out_of_range(G_PTID, "Invalid pointing index",
663 ipt, m_num_pt);
664 }
665 #endif
666
667 // Return
668 return (m_ptid[ipt]);
669}
670
671
672/***********************************************************************//**
673 * @brief Return instrument direction
674 *
675 * @param[in] ipt Pointing index.
676 * @param[in] idet Detector index.
677 * @return Instrument direction.
678 *
679 * @exception GException::out_of_range
680 * Invalid pointing or detector index
681 *
682 * Returns the instrument direction for the specified pointing and detector
683 * index.
684 ***************************************************************************/
685const GSPIInstDir& GSPIEventCube::dir(const int& ipt, const int& idet) const
686{
687 // Optionally check if the pointing index is valid
688 #if defined(G_RANGE_CHECK)
689 if (ipt < 0 || ipt >= m_num_pt) {
690 throw GException::out_of_range(G_DIR, "Invalid pointing index",
691 ipt, m_num_pt);
692 }
693 if (idet < 0 || idet >= m_num_det) {
694 throw GException::out_of_range(G_DIR, "Invalid detector index",
695 idet, m_num_det);
696 }
697 #endif
698
699 // Return
700 return (m_dir[ipt*m_num_det+idet]);
701}
702
703
704/***********************************************************************//**
705 * @brief Return SPI X direction (pointing direction)
706 *
707 * @param[in] ipt Pointing index.
708 * @return SPI X direction.
709 *
710 * @exception GException::out_of_range
711 * Invalid pointing index
712 *
713 * Returns the SPI X direction for the specified index. The SPI X direction
714 * is the SPI pointing direction.
715 ***************************************************************************/
716const GSkyDir& GSPIEventCube::spi_x(const int& ipt) const
717{
718 // Optionally check if the pointing index is valid
719 #if defined(G_RANGE_CHECK)
720 if (ipt < 0 || ipt >= m_num_pt) {
721 throw GException::out_of_range(G_SPI_X, "Invalid pointing index",
722 ipt, m_num_pt);
723 }
724 #endif
725
726 // Return
727 return (m_spix[ipt]);
728}
729
730
731/***********************************************************************//**
732 * @brief Return SPI Z direction
733 *
734 * @param[in] ipt Pointing index.
735 * @return SPI Z direction.
736 *
737 * @exception GException::out_of_range
738 * Invalid pointing index
739 *
740 * Returns the SPI Z direction for the specified index.
741 ***************************************************************************/
742const GSkyDir& GSPIEventCube::spi_z(const int& ipt) const
743{
744 // Optionally check if the pointing index is valid
745 #if defined(G_RANGE_CHECK)
746 if (ipt < 0 || ipt >= m_num_pt) {
747 throw GException::out_of_range(G_SPI_Z, "Invalid pointing index",
748 ipt, m_num_pt);
749 }
750 #endif
751
752 // Return
753 return (m_spiz[ipt]);
754}
755
756
757/***********************************************************************//**
758 * @brief Print INTEGRAL/SPI event cube information
759 *
760 * @param[in] chatter Chattiness.
761 * @return String containing INTEGRAL/SPI event cube information.
762 ***************************************************************************/
763std::string GSPIEventCube::print(const GChatter& chatter) const
764{
765 // Initialise result string
766 std::string result;
767
768 // Continue only if chatter is not silent
769 if (chatter != SILENT) {
770
771 // Append header
772 result.append("=== GSPIEventCube ===");
773
774 // Append information
775 result.append("\n"+gammalib::parformat("Number of events"));
776 result.append(gammalib::str(number()));
777 result.append("\n"+gammalib::parformat("Number of elements"));
778 result.append(gammalib::str(size()));
779 result.append("\n"+gammalib::parformat("Pointings"));
780 result.append(gammalib::str(m_num_pt));
781 result.append("\n"+gammalib::parformat("Detectors"));
782 result.append(gammalib::str(m_num_det));
783 result.append("\n"+gammalib::parformat("Energy bins"));
784 result.append(gammalib::str(m_num_ebin));
785 result.append("\n"+gammalib::parformat("Sky models"));
786 result.append(gammalib::str(m_num_sky));
787 for (int i = 0; i < m_num_sky; ++i) {
788 result.append("\n"+gammalib::parformat(" Model name "+gammalib::str(i+1)));
789 result.append(m_modnames[i]);
790 result.append("\n"+gammalib::parformat(" Number of events"));
791 result.append(gammalib::str(model_counts(i)));
792 }
793 result.append("\n"+gammalib::parformat("Background models"));
794 result.append(gammalib::str(m_num_bgm));
795 for (int i = 0; i < m_num_bgm; ++i) {
796 result.append("\n"+gammalib::parformat(" Model name "+gammalib::str(i+1)));
797 result.append(m_modnames[i+m_num_sky]);
798 result.append("\n"+gammalib::parformat(" Number of events"));
799 result.append(gammalib::str(model_counts(i+m_num_sky)));
800 }
801 result.append("\n"+gammalib::parformat("Energy range"));
802 result.append(gammalib::str(emin().MeV())+" - ");
803 result.append(gammalib::str(emax().MeV())+" MeV");
804 result.append("\n"+gammalib::parformat("Ontime"));
805 result.append(gammalib::str(ontime())+" s");
806 result.append("\n"+gammalib::parformat("Livetime"));
807 result.append(gammalib::str(livetime())+" s");
808 result.append("\n"+gammalib::parformat("Time interval"));
809 result.append(tstart().utc()+" - ");
810 result.append(tstop().utc());
811
812 } // endif: chatter was not silent
813
814 // Return result
815 return result;
816}
817
818
819/*==========================================================================
820 = =
821 = Private methods =
822 = =
823 ==========================================================================*/
824
825/***********************************************************************//**
826 * @brief Initialise class members
827 ***************************************************************************/
829{
830 // Initialise members
831 m_bin.clear();
832 m_num_pt = 0;
833 m_num_det = 0;
834 m_num_ebin = 0;
835 m_num_sky = 0;
836 m_num_bgm = 0;
837 m_gti_size = 0;
838 m_dsp_size = 0;
839 m_model_size = 0;
840 m_ontime = NULL;
841 m_livetime = NULL;
842 m_counts = NULL;
843 m_stat_err = NULL;
844 m_models = NULL;
845 m_size = NULL;
846 m_dir = NULL;
847 m_time = NULL;
848 m_energy = NULL;
849 m_ewidth = NULL;
850 m_spix = NULL;
851 m_spiz = NULL;
852 m_ptid = NULL;
853
854 // Prepare event bin
855 init_bin();
856
857 // Return
858 return;
859}
860
861
862/***********************************************************************//**
863 * @brief Copy class members
864 *
865 * @param[in] cube INTEGRAL/SPI event cube.
866 *
867 * This method copies the class members from another event cube in the actual
868 * object. It also prepares the event bin member that will be returned in
869 * case of an operator access to the class.
870 ***************************************************************************/
872{
873 // Copy members. Note that the event bin is not copied as it will
874 // be initialised later. The event bin serves just as a container of
875 // pointers, hence we do not want to copy over the pointers from the
876 // original class.
877 m_num_pt = cube.m_num_pt;
878 m_num_det = cube.m_num_det;
879 m_num_ebin = cube.m_num_ebin;
880 m_num_sky = cube.m_num_sky;
881 m_num_bgm = cube.m_num_bgm;
882 m_gti_size = cube.m_gti_size;
883 m_dsp_size = cube.m_dsp_size;
885 m_modnames = cube.m_modnames;
886
887 // Copy data
888 if (m_num_ebin > 0) {
891 for (int i = 0; i < m_num_ebin; ++i) {
892 m_energy[i] = cube.m_energy[i];
893 m_ewidth[i] = cube.m_ewidth[i];
894 }
895 }
896 if (m_num_pt > 0) {
897 m_ptid = new std::string[m_num_pt];
898 m_spix = new GSkyDir[m_num_pt];
899 m_spiz = new GSkyDir[m_num_pt];
900 for (int i = 0; i < m_num_pt; ++i) {
901 m_ptid[i] = cube.m_ptid[i];
902 m_spix[i] = cube.m_spix[i];
903 m_spiz[i] = cube.m_spiz[i];
904 }
905 }
906 if (m_gti_size > 0) {
907 m_ontime = new double[m_gti_size];
908 m_livetime = new double[m_gti_size];
909 m_time = new GTime[m_gti_size];
911 for (int i = 0; i < m_gti_size; ++i) {
912 m_ontime[i] = cube.m_ontime[i];
913 m_livetime[i] = cube.m_livetime[i];
914 m_time[i] = cube.m_time[i];
915 m_dir[i] = cube.m_dir[i];
916 }
917 }
918 if (m_dsp_size > 0) {
919 m_counts = new double[m_dsp_size];
920 m_stat_err = new double[m_dsp_size];
921 m_size = new double[m_dsp_size];
922 for (int i = 0; i < m_dsp_size; ++i) {
923 m_counts[i] = cube.m_counts[i];
924 m_stat_err[i] = cube.m_stat_err[i];
925 m_size[i] = cube.m_size[i];
926 }
927 }
928 if (m_model_size > 0) {
929 m_models = new double[m_model_size];
930 for (int i = 0; i < m_model_size; ++i) {
931 m_models[i] = cube.m_models[i];
932 }
933 }
934
935 // Prepare event bin
936 init_bin();
937
938 // Return
939 return;
940}
941
942
943/***********************************************************************//**
944 * @brief Delete class members
945 ***************************************************************************/
947{
948 // Delete memory
949 if (m_ontime != NULL) delete [] m_ontime;
950 if (m_livetime != NULL) delete [] m_livetime;
951 if (m_counts != NULL) delete [] m_counts;
952 if (m_stat_err != NULL) delete [] m_stat_err;
953 if (m_models != NULL) delete [] m_models;
954 if (m_size != NULL) delete [] m_size;
955 if (m_dir != NULL) delete [] m_dir;
956 if (m_time != NULL) delete [] m_time;
957 if (m_energy != NULL) delete [] m_energy;
958 if (m_ewidth != NULL) delete [] m_ewidth;
959 if (m_spix != NULL) delete [] m_spix;
960 if (m_spiz != NULL) delete [] m_spiz;
961 if (m_ptid != NULL) delete [] m_ptid;
962
963 // Set pointers to free
964 m_ontime = NULL;
965 m_livetime = NULL;
966 m_counts = NULL;
967 m_stat_err = NULL;
968 m_models = NULL;
969 m_size = NULL;
970 m_dir = NULL;
971 m_time = NULL;
972 m_energy = NULL;
973 m_ewidth = NULL;
974 m_spix = NULL;
975 m_spiz = NULL;
976 m_ptid = NULL;
977
978 // Return
979 return;
980}
981
982
983/***********************************************************************//**
984 * @brief Allocate data
985 ***************************************************************************/
987{
988 // Make sure that data is free
989 free_members();
990
991 // Compute array sizes
995
996 // Allocate and initialise EBDS data
997 if (m_num_ebin > 0) {
1000 for (int i = 0; i < m_num_ebin; ++i) {
1001 m_energy[i].clear();
1002 m_ewidth[i].clear();
1003 }
1004 }
1005
1006 // Allocate and initialise pointing data
1007 if (m_num_pt > 0) {
1008 m_ptid = new std::string[m_num_pt];
1009 m_spix = new GSkyDir[m_num_pt];
1010 m_spiz = new GSkyDir[m_num_pt];
1011 for (int i = 0; i < m_num_pt; ++i) {
1012 m_ptid[i].clear();
1013 m_spix[i].clear();
1014 m_spiz[i].clear();
1015 }
1016 }
1017
1018 // Allocate and initialise GTI data
1019 if (m_gti_size > 0) {
1020 m_ontime = new double[m_gti_size];
1021 m_livetime = new double[m_gti_size];
1022 m_time = new GTime[m_gti_size];
1024 for (int i = 0; i < m_gti_size; ++i) {
1025 m_ontime[i] = 0.0;
1026 m_livetime[i] = 0.0;
1027 m_time[i].clear();
1028 m_dir[i].clear();
1029 }
1030 }
1031
1032 // Allocate and initialise DSP data
1033 if (m_dsp_size > 0) {
1034 m_counts = new double[m_dsp_size];
1035 m_stat_err = new double[m_dsp_size];
1036 m_size = new double[m_dsp_size];
1037 for (int i = 0; i < m_dsp_size; ++i) {
1038 m_counts[i] = 0.0;
1039 m_stat_err[i] = 0.0;
1040 m_size[i] = 0.0;
1041 }
1042 }
1043
1044 // Allocate and initialise model data
1045 if (m_model_size > 0) {
1046 m_models = new double[m_model_size];
1047 for (int i = 0; i < m_model_size; ++i) {
1048 m_models[i] = 0.0;
1049 }
1050 }
1051
1052 // Return
1053 return;
1054}
1055
1056
1057/***********************************************************************//**
1058 * @brief Read data from INTEGRAL/SPI "SPI.-EBDS-SET" extension
1059 *
1060 * @param[in] ebds Pointer to energy boundaries FITS table.
1061 *
1062 * @exception GException::invalid_value
1063 * Incompatible number of energy bins encountered
1064 *
1065 * Reads data from an INTEGRAL/SPI "SPI.-EBDS-SET" extension. The method
1066 * sets up the m_energy array and the m_ebounds member.
1067 ***************************************************************************/
1069{
1070 // Continue only if energy boundary FITS table pointer is valid
1071 if (ebds != NULL) {
1072
1073 // Read energy boundaries
1074 m_ebounds.read(*ebds);
1075
1076 // Throw an exception if the number of energy boundaries is not
1077 // consistent with DSP keyword
1078 if (m_ebounds.size() != m_num_ebin) {
1079 std::string msg = "Number of energy bins "+
1080 gammalib::str(m_ebounds.size())+" found in "
1081 "\"SPI.-EBDS-SET\" extension differes from value "+
1082 gammalib::str(m_num_det)+" of \"DET_NUM\" keyword "
1083 "in \"SPI.-OBS.-DSP\" extension. Please specify a "
1084 "valid Observation Group.";
1086 }
1087
1088 // Loop over all energy bins
1089 for (int iebin = 0; iebin < m_num_ebin; ++iebin) {
1090
1091 // Store linear mean energy and bin width
1092 m_energy[iebin] = m_ebounds.emean(iebin);
1093 m_ewidth[iebin] = m_ebounds.ewidth(iebin);
1094
1095 } // endfor: looped over all energy bins
1096
1097 } // endif: energy boundary FITS table pointer was valid
1098
1099 // Return
1100 return;
1101}
1102
1103
1104/***********************************************************************//**
1105 * @brief Read pointing information
1106 *
1107 * @param[in] pnt Pointer to pointing FITS table.
1108 * @param[in] gti Pointer to GTI FITS table.
1109 *
1110 * @exception GException::invalid_value
1111 * Incompatible PTID_SPI pointing identifiers encountered
1112 *
1113 * Reads pointing information from "SPI.-OBS.-PNT" and "SPI.-OBS.-GTI"
1114 * extensions. The method sets up the m_dir array.
1115 ***************************************************************************/
1117{
1118 // Continue only if FITS table pointers are valid
1119 if (pnt != NULL && gti != NULL) {
1120
1121 // Get relevant columns
1122 const GFitsTableCol* pnt_ptid = (*pnt)["PTID_SPI"];
1123 const GFitsTableCol* ra_spix = (*pnt)["RA_SPIX"];
1124 const GFitsTableCol* dec_spix = (*pnt)["DEC_SPIX"];
1125 const GFitsTableCol* ra_spiz = (*pnt)["RA_SPIZ"];
1126 const GFitsTableCol* dec_spiz = (*pnt)["DEC_SPIZ"];
1127 const GFitsTableCol* gti_ptid = (*gti)["PTID_SPI"];
1128 const GFitsTableCol* det_id = (*gti)["DET_ID"];
1129
1130 // Loop over all pointings
1131 for (int ipt = 0; ipt < m_num_pt; ++ipt) {
1132
1133 // Store pointing identifier
1134 m_ptid[ipt] = pnt_ptid->string(ipt);
1135
1136 // Store SPI X and Z directions
1137 m_spix[ipt].radec_deg(ra_spix->real(ipt), dec_spix->real(ipt));
1138 m_spiz[ipt].radec_deg(ra_spiz->real(ipt), dec_spiz->real(ipt));
1139
1140 // Set pointing direction
1141 GSkyDir pnt_dir;
1142 pnt_dir.radec_deg(ra_spix->real(ipt), dec_spix->real(ipt));
1143
1144 // Loop over all detectors
1145 for (int idet = 0; idet < m_num_det; ++idet) {
1146
1147 // Get row index in table
1148 int irow = ipt * m_num_det + idet;
1149
1150 // Throw an exception if the pointing identifier in the pointing
1151 // and the GTI extension is not the same
1152 if (pnt_ptid->string(ipt) != gti_ptid->string(irow)) {
1153 std::string msg = "PITD_SPI \""+pnt_ptid->string(ipt)+"\" in "
1154 "\"SPI.-OBS.-PNT\" differs from \""+
1155 gti_ptid->string(irow)+"\" in "
1156 "\"SPI.-OBS.-GTI\" extension for detector "+
1157 gammalib::str(det_id->integer(irow))+". Please "
1158 "specify a valid Observation Group.";
1160 }
1161
1162 // Store pointing direction and detector identifier
1163 m_dir[irow].dir(pnt_dir);
1164 m_dir[irow].detid(det_id->integer(irow));
1165
1166 } // endfor: looped over all detectors
1167
1168 } // endfor: looped over all pointings
1169
1170 } // endif: FITS table pointers were valid
1171
1172 // Return
1173 return;
1174}
1175
1176
1177/***********************************************************************//**
1178 * @brief Read data from INTEGRAL/SPI "SPI.-OBS.-GTI" extension
1179 *
1180 * @param[in] gti Pointer to GTI FITS table.
1181 *
1182 * Reads data from an INTEGRAL/SPI "SPI.-OBS.-GTI" extension. The method
1183 * sets up the m_ontime array and the m_gti member.
1184 ***************************************************************************/
1186{
1187 // Continue only if FITS table pointer is valid
1188 if (gti != NULL) {
1189
1190 // Get relevant columns
1191 const GFitsTableCol* ontime = (*gti)["ONTIME"];
1192 const GFitsTableCol* tstart = (*gti)["TSTART"];
1193 const GFitsTableCol* tstop = (*gti)["TSTOP"];
1194
1195 // Loop over all pointings
1196 for (int ipt = 0; ipt < m_num_pt; ++ipt) {
1197
1198 // Initialise minimum TSTART and maximum TSTOP for GTI (they should
1199 // all be identical and are anyways not used, but we want to have a
1200 // reasonable GTI object
1201 double t_start = 0.0;
1202 double t_stop = 0.0;
1203
1204 // Loop over all detectors
1205 for (int idet = 0; idet < m_num_det; ++idet) {
1206
1207 // Get row index in table
1208 int irow = ipt * m_num_det + idet;
1209
1210 // Store ontime
1211 m_ontime[irow] = ontime->real(irow);
1212
1213 // Compute and store mean time
1214 double ijd = 0.5 * (tstart->real(irow) + tstop->real(irow));
1215 m_time[irow] = gammalib::spi_ijd2time(ijd);
1216
1217 // Update TSTART and TSTOP (only if ontime is > 0.0 since TSTART
1218 // and TSTOP may be zero for zero ontime)
1219 if (ontime->real(irow) > 0.0) {
1220 if (t_start == 0.0 || (tstart->real(irow) < t_start)) {
1221 t_start = tstart->real(irow);
1222 }
1223 if (t_stop == 0.0 || (tstop->real(irow) > t_stop)) {
1224 t_stop = tstop->real(irow);
1225 }
1226 }
1227
1228 } // endfor: looped over all detectors
1229
1230 // Append GTI (only if TSTART and TSTOP are not zero)
1231 if (t_start != 0.0 && t_stop != 0.0) {
1233 gammalib::spi_ijd2time(t_stop));
1234 }
1235
1236 } // endfor: looped over all pointings
1237
1238 } // endif: FITS table pointer was valid
1239
1240 // Return
1241 return;
1242}
1243
1244
1245/***********************************************************************//**
1246 * @brief Read data from INTEGRAL/SPI "SPI.-OBS.-DTI" extension
1247 *
1248 * @param[in] dti Pointer to Dead time information FITS table.
1249 *
1250 * Reads data from an INTEGRAL/SPI "SPI.-OBS.-DTI" extension. The method
1251 * sets up the m_ontime array and the m_gti member.
1252 ***************************************************************************/
1254{
1255 // Continue only if FITS table pointer is valid
1256 if (dti != NULL) {
1257
1258 // Get relevant columns
1259 const GFitsTableCol* livetime = (*dti)["LIVETIME"];
1260
1261 // Loop over all pointings
1262 for (int ipt = 0; ipt < m_num_pt; ++ipt) {
1263
1264 // Loop over all detectors
1265 for (int idet = 0; idet < m_num_det; ++idet) {
1266
1267 // Get row index in table
1268 int irow = ipt * m_num_det + idet;
1269
1270 // Store livetime
1271 m_livetime[irow] = livetime->real(irow);
1272
1273 } // endfor: looped over all detectors
1274
1275 } // endfor: looped over all pointings
1276
1277 } // endif: FITS table pointer was valid
1278
1279 // Return
1280 return;
1281}
1282
1283
1284/***********************************************************************//**
1285 * @brief Read data from INTEGRAL/SPI "SPI.-OBS.-DSP" extension
1286 *
1287 * @param[in] dsp DSP FITS table.
1288 *
1289 * Reads data from an INTEGRAL/SPI "SPI.-OBS.-DSP" extension. The method
1290 * sets up the m_counts, m_stat_err and m_size arrays.
1291 *
1292 * Note that the computation of the m_size arrays needs ontime and energy
1293 * width information that has been previously setup in the read_ebds() and
1294 * read_gti() methods.
1295 ***************************************************************************/
1297{
1298 // Continue only if FITS table pointer is valid
1299 if (dsp != NULL) {
1300
1301 // Get relevant columns
1302 const GFitsTableCol* counts = (*dsp)["COUNTS"];
1303 const GFitsTableCol* stat_err = (*dsp)["STAT_ERR"];
1304
1305 // Loop over all pointings
1306 for (int ipt = 0; ipt < m_num_pt; ++ipt) {
1307
1308 // Loop over all detectors
1309 for (int idet = 0; idet < m_num_det; ++idet) {
1310
1311 // Get row index in table
1312 int irow = ipt * m_num_det + idet;
1313
1314 // Set start index in destination arrays
1315 int index = irow * m_num_ebin;
1316
1317 // Copy energy bins
1318 for (int iebin = 0; iebin < m_num_ebin; ++iebin, ++index) {
1319 m_counts[index] = counts->real(irow, iebin);
1320 m_stat_err[index] = stat_err->real(irow, iebin);
1321 m_size[index] = m_livetime[irow] * m_ewidth[iebin].MeV();
1322 }
1323
1324 } // endfor: looped over all detectors
1325
1326 } // endfor: looped over all pointings
1327
1328 } // endif: FITS table pointer was valid
1329
1330 // Return
1331 return;
1332}
1333
1334
1335/***********************************************************************//**
1336 * @brief Read models from INTEGRAL/SPI Observation Group
1337 *
1338 * @param[in] fits Observation Group FITS file.
1339 ***************************************************************************/
1341{
1342 // Clear model names
1343 m_modnames.clear();
1344
1345 // Initialise model index
1346 int imodel = 0;
1347
1348 // Compute total number of models
1349 int num_models = m_num_sky + m_num_bgm;
1350
1351 // Loop over all sky models
1352 for (int i = 0; i < m_num_sky; ++i, ++imodel) {
1353
1354 // Get FITS table
1355 const GFitsTable* model = gammalib::spi_hdu(fits, "SPI.-SDET-SPE", i+1);
1356
1357 // Throw an exception if the FITS table is missing
1358 if (model == NULL) {
1359 std::string msg = "Extension \"SPI.-SDET-SPE\" version "+
1360 gammalib::str(i+1)+" not found in Observation "
1361 "Group FITS file \""+fits.filename().url()+
1362 "\". Please specify a valid Observation Group.";
1364 }
1365
1366 // Get model name
1367 std::string name = "MODEL" + gammalib::str(imodel+1);
1368 if (model->has_card("SOURCEID")) {
1369 name = model->string("SOURCEID");
1370 }
1371 m_modnames.push_back(name);
1372
1373 // Get relevant columns
1374 const GFitsTableCol* counts = (*model)["COUNTS"];
1375
1376 // Loop over all pointings
1377 for (int ipt = 0; ipt < m_num_pt; ++ipt) {
1378
1379 // Loop over all detectors
1380 for (int idet = 0; idet < m_num_det; ++idet) {
1381
1382 // Get row index in model table
1383 int irow = ipt * m_num_det + idet;
1384
1385 // Set start index in destination array
1386 int index = irow * m_num_ebin;
1387
1388 // Copy energy bins
1389 for (int iebin = 0; iebin < m_num_ebin; ++iebin, ++index) {
1390 m_models[index*num_models + imodel] = counts->real(irow, iebin);
1391 }
1392
1393 } // endfor: looped over all detectors
1394
1395 } // endfor: looped over all pointings
1396
1397 } // endfor: looped over all sky models
1398
1399 // Loop over all background models
1400 for (int i = 0; i < m_num_bgm; ++i, ++imodel) {
1401
1402 // Get FITS table
1403 const GFitsTable* model = gammalib::spi_hdu(fits, "SPI.-BMOD-DSP", i+1);
1404
1405 // Throw an exception if the FITS table is missing
1406 if (model == NULL) {
1407 std::string msg = "Extension \"SPI.-BMOD-DSP\" version "+
1408 gammalib::str(i+1)+" not found in Observation "
1409 "Group FITS file \""+fits.filename().url()+
1410 "\". Please specify a valid Observation Group.";
1412 }
1413
1414 // Get model name
1415 std::string name = "MODEL" + gammalib::str(imodel+1);
1416 if (model->has_card("BKGNAME")) {
1417 name = model->string("BKGNAME");
1418 }
1419 m_modnames.push_back(name);
1420
1421 // Get relevant columns
1422 const GFitsTableCol* counts = (*model)["COUNTS"];
1423
1424 // Loop over all pointings
1425 for (int ipt = 0; ipt < m_num_pt; ++ipt) {
1426
1427 // Loop over all detectors
1428 for (int idet = 0; idet < m_num_det; ++idet) {
1429
1430 // Get row index in model table
1431 int irow = ipt * m_num_det + idet;
1432
1433 // Set start index in destination array
1434 int index = irow * m_num_ebin;
1435
1436 // Copy energy bins
1437 for (int iebin = 0; iebin < m_num_ebin; ++iebin, ++index) {
1438 m_models[index*num_models + imodel] = counts->real(irow, iebin);
1439 }
1440
1441 } // endfor: looped over all detectors
1442
1443 } // endfor: looped over all pointings
1444
1445 } // endfor: looped over all background models
1446
1447 // Return
1448 return;
1449}
1450
1451
1452/***********************************************************************//**
1453 * @brief Initialise event bin
1454 *
1455 * Initialises the event bin. All fixed content is set here, the content
1456 * that depends on the bin index is set by the set_bin() method which is
1457 * called before any event bin access.
1458 ***************************************************************************/
1460{
1461 // Prepare event bin
1463 m_bin.m_index = 0; //!< Set by set_bin method
1464 m_bin.m_ipt = 0; //!< Set by set_bin method
1465 m_bin.m_idir = 0; //!< Set by set_bin method
1466 m_bin.m_iebin = 0; //!< Set by set_bin method
1468 m_bin.m_dir = NULL; //!< Set by set_bin method
1469 m_bin.m_time = NULL; //!< Set by set_bin method
1470 m_bin.m_energy = NULL; //!< Set by set_bin method
1471 m_bin.m_counts = NULL; //!< Set by set_bin method
1472 m_bin.m_ontime = NULL; //!< Set by set_bin method
1473 m_bin.m_livetime = NULL; //!< Set by set_bin method
1474 m_bin.m_size = NULL; //!< Set by set_bin method
1475 m_bin.m_models = NULL; //!< Set by set_bin method
1476
1477 // Return
1478 return;
1479}
1480
1481
1482/***********************************************************************//**
1483 * @brief Set event bin
1484 *
1485 * @param[in] index Event index [0,...,size()[.
1486 *
1487 * @exception GException::out_of_range
1488 * Event index is outside valid range.
1489 *
1490 * Sets the pointers of the event bin to the event cube cell that corresponds
1491 * to the specified @p index.
1492 *
1493 * The event bin is in fact physically stored in the event cube, and only a
1494 * single event bin is indeed allocated. This method sets up the pointers in
1495 * the event bin so that a client can easily access the information of
1496 * individual bins as if they were stored in an array.
1497 ***************************************************************************/
1498void GSPIEventCube::set_bin(const int& index)
1499{
1500 // Optionally check if the index is valid
1501 #if defined(G_RANGE_CHECK)
1502 if (index < 0 || index >= size()) {
1503 throw GException::out_of_range(G_SET_BIN, "Event index", index, size());
1504 }
1505 #endif
1506
1507 // Set indices
1508 m_bin.m_index = index;
1509 m_bin.m_idir = index / m_num_ebin;
1511 m_bin.m_iebin = index % m_num_ebin;
1512
1513 // Set GSPIEventBin pointers
1522
1523 // Return
1524 return;
1525}
#define G_SET_BIN
#define G_NAXIS
#define G_DIR
Energy value class definition.
#define G_READ_FITS
#define G_READ_MODELS
#define G_MODEL_COUNTS
#define G_READ_EBDS
#define G_SPI_Z
#define G_PTID
#define G_SPI_X
#define G_READ_PNT
INTEGRAL/SPI event bin container class definition.
INTEGRAL/SPI instrument direction class definition.
Definition of INTEGRAL/SPI tools.
Sky direction class interface definition.
Time class interface definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
GEnergy ewidth(const int &index) const
Returns energy interval width.
void read(const GFitsTable &table)
Read energy boundaries from FITS table.
Definition GEbounds.cpp:761
GEnergy emean(const int &index) const
Returns mean energy for a given energy interval.
int size(void) const
Return number of energy boundaries.
Definition GEbounds.hpp:163
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
double MeV(void) const
Return energy in MeV.
Definition GEnergy.cpp:321
void clear(void)
Clear instance.
Definition GEnergy.cpp:261
Abstract event bin container class.
void free_members(void)
Delete class members.
void init_members(void)
Initialise class members.
virtual GEventCube & operator=(const GEventCube &cube)
Assignment operator.
void free_members(void)
Delete class members.
Definition GEvents.cpp:206
GGti m_gti
Good time intervals covered by events.
Definition GEvents.hpp:112
const GTime & tstart(void) const
Return start time.
Definition GEvents.hpp:146
GEbounds m_ebounds
Energy boundaries covered by events.
Definition GEvents.hpp:111
const GGti & gti(void) const
Return Good Time Intervals.
Definition GEvents.hpp:134
void init_members(void)
Initialise class members.
Definition GEvents.cpp:176
const GTime & tstop(void) const
Return stop time.
Definition GEvents.hpp:158
const GEnergy & emax(void) const
Return maximum energy.
Definition GEvents.hpp:182
const GEnergy & emin(void) const
Return minimum energy.
Definition GEvents.hpp:170
Filename class.
Definition GFilename.hpp:62
std::string url(void) const
Return Uniform Resource Locator (URL)
bool has_card(const int &cardno) const
Check existence of header card.
Definition GFitsHDU.hpp:233
std::string string(const std::string &keyname) const
Return card value as string.
Definition GFitsHDU.hpp:410
int integer(const std::string &keyname) const
Return card value as integer.
Definition GFitsHDU.hpp:436
Abstract interface for FITS table column.
virtual int integer(const int &row, const int &inx=0) const =0
virtual double real(const int &row, const int &inx=0) const =0
virtual std::string string(const int &row, const int &inx=0) const =0
Abstract interface for FITS 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
void close(void)
Close FITS file.
Definition GFits.cpp:1342
const GFilename & filename(void) const
Return FITS filename.
Definition GFits.hpp:313
void append(const GTime &tstart, const GTime &tstop)
Append Good Time Interval.
Definition GGti.cpp:269
INTEGRAL/SPI event bin class.
virtual void clear(void)
Clear INTEGRAL/SPI event bin.
int m_index
Dataspace index.
GSPIInstDir * m_dir
Pointer to direction of bin.
GTime * m_time
Pointer to time of bin.
GEnergy * m_energy
Pointer to energy of bin.
double * m_counts
Pointer to number of counts.
int m_num_models
Number of models in bin.
int m_iebin
Energy bin index.
void free_members(void)
Delete class members.
double * m_ontime
Pointer to ontime of bin.
int m_idir
Direction index.
double * m_livetime
Pointer to livetime of bin.
double * m_size
Pointer to size of bin.
int m_ipt
Pointing index.
double * m_models
Pointer to models of bin.
INTEGRAL/SPI event bin container class.
void copy_members(const GSPIEventCube &cube)
Copy class members.
virtual void clear(void)
Clear INTEGRAL/SPI event cube.
void init_members(void)
Initialise class members.
void read_pnt(const GFitsTable *pnt, const GFitsTable *gti)
Read pointing information.
GSkyDir * m_spiz
SPI Z axis array.
GSkyDir * m_spix
SPI X axis array.
int m_model_size
Size of model arrays.
const GSPIInstDir & dir(const int &ipt, const int &idet) const
Return instrument direction.
const GSkyDir & spi_z(const int &ipt) const
Return SPI Z direction.
double * m_livetime
Livetime array.
GSPIEventBin m_bin
Actual event bin.
void read_models(const GFits &file)
Read models from INTEGRAL/SPI Observation Group.
GTime * m_time
Time array.
virtual ~GSPIEventCube(void)
Destructor.
void read_dti(const GFitsTable *dti)
Read data from INTEGRAL/SPI "SPI.-OBS.-DTI" extension.
virtual int dim(void) const
Return event cube dimension.
void read_dsp(const GFitsTable *dsp)
Read data from INTEGRAL/SPI "SPI.-OBS.-DSP" extension.
virtual void save(const GFilename &filename, const bool &clobber=false) const
Save INTEGRAL/SPI event cube into FITS file.
virtual int naxis(const int &axis) const
Return number of bins in axis.
void free_members(void)
Delete class members.
double livetime(void) const
Return total livetime.
virtual int size(void) const
Return event cube size.
void init_bin(void)
Initialise event bin.
GEnergy * m_energy
Energy array.
int m_num_pt
Number of pointings.
std::vector< std::string > m_modnames
Model names.
const std::string & ptid(const int &ipt) const
Return pointing identifier.
void set_bin(const int &index)
Set event bin.
virtual GSPIEventCube & operator=(const GSPIEventCube &cube)
Assignment operator.
double ontime(void) const
Return total ontime.
virtual void load(const GFilename &filename)
Load INTEGRAL/SPI event cube from Observation Group.
virtual void write(GFits &file) const
Write INTEGRAL/SPI event cube into FITS file.
double * m_size
Event bin size array.
GSPIInstDir * m_dir
Event direction array.
void read_gti(const GFitsTable *gti)
Read data from INTEGRAL/SPI "SPI.-OBS.-GTI" extension.
void alloc_data(void)
Allocate data.
int m_gti_size
Size of GTI arrays.
int m_num_sky
Number of sky models.
int m_num_ebin
Number of energy bins.
virtual GSPIEventBin * operator[](const int &index)
Event bin access operator.
virtual std::string print(const GChatter &chatter=NORMAL) const
Print INTEGRAL/SPI event cube information.
int m_num_det
Number of detectors.
int m_num_bgm
Number of background models.
double * m_counts
Counts array.
double * m_stat_err
Statistical error array.
double * m_ontime
Ontime array.
std::string * m_ptid
Pointing identifiers.
GSPIEventCube(void)
Void constructor.
virtual GSPIEventCube * clone(void) const
Clone event cube.
int m_dsp_size
Size of DSP arrays.
virtual void read(const GFits &file)
Read INTEGRAL/SPI event cube from Observation Group FITS file.
GEnergy * m_ewidth
Energy bin width array.
double * m_models
Models array.
double model_counts(const int &index) const
Return number of events in model.
const GSkyDir & spi_x(const int &ipt) const
Return SPI X direction (pointing direction)
void read_ebds(const GFitsTable *ebds)
Read data from INTEGRAL/SPI "SPI.-EBDS-SET" extension.
virtual int number(void) const
Return number of events in cube.
INTEGRAL/SPI instrument direction class.
virtual void clear(void)
Clear INTEGRAL/SPI instrument direction.
void dir(const GSkyDir &dir)
Set pointing direction.
void detid(const int &detid)
Set detector identifier.
Sky direction class.
Definition GSkyDir.hpp:62
void radec_deg(const double &ra, const double &dec)
Set equatorial sky direction (degrees)
Definition GSkyDir.cpp:224
void clear(void)
Clear sky direction.
Definition GSkyDir.cpp:164
Time class.
Definition GTime.hpp:55
void clear(void)
Clear time.
Definition GTime.cpp:252
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
int spi_num_hdus(const GFits &fits, const std::string &extname)
Return number of HDU versions.
GTime spi_ijd2time(const double &ijd)
Convert IJD to GTime.
const GFitsTable * spi_hdu(const GFits &fits, const std::string &extname, const int &extver=1)
Return FITS table.
Definition GSPITools.cpp:57