GammaLib 2.2.0.dev
Loading...
Searching...
No Matches
GCOSEventCube.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GCOSEventCube.cpp - COSI event bin container 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 GCOSEventCube.hpp
23 * @brief COSI 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 "GBounds.hpp"
32#include "GEbounds.hpp"
33#include "GSkyMap.hpp"
34#include "GCOSEventCube.hpp"
35#include "GCOSEventList.hpp"
36
37/* __ Method name definitions ____________________________________________ */
38#define G_NAXIS "GCOSEventCube::naxis(int)"
39#define G_SET "GCOSEventCube::set(std::string&, int&, std::string&, "\
40 "GBounds&, GEbounds&)"
41#define G_FILL "GCOSEventCube::fill(GCOSEventList&)"
42#define G_SET_SCATTER_DIRECTIONS "GCOSEventCube::set_scatter_directions()"
43#define G_SET_SCATTER_ANGLES "GCOSEventCube::set_scatter_angles()"
44#define G_SET_ENERGIES "GCOSEventCube::set_energies()"
45#define G_SET_TIMES "GCOSEventCube::set_times()"
46#define G_SET_BIN "GCOSEventCube::set_bin(int&)"
47
48/* __ Macros _____________________________________________________________ */
49
50/* __ Coding definitions _________________________________________________ */
51
52/* __ Debug definitions __________________________________________________ */
53
54
55
56/*==========================================================================
57 = =
58 = Constructors/destructors =
59 = =
60 ==========================================================================*/
61
62/***********************************************************************//**
63 * @brief Void constructor
64 *
65 * Constructs an empty COSI event cube.
66 ***************************************************************************/
68{
69 // Initialise members
71
72 // Return
73 return;
74}
75
76
77/***********************************************************************//**
78 * @brief Cube constructor
79 *
80 * @param[in] coords Event cube coordinate system (CEL or GAL).
81 * @param[in] nside Event cube Nside parameter.
82 * @param[in] order Event cube pixel ordering (RING or NEST).
83 * @param[in] phibounds Phi layer boundaries.
84 * @param[in] ebounds Event cube energy boundaries.
85 * @param[in] gti Good Time intervals.
86 *
87 * Constructs a HealPix event cube by specifying the coordinate system, the
88 * HealPix Nside parameter and pixel ordering scheme, the event cube Phi
89 * layer boundaries, the event cube energy boundaries and the event cube
90 * Good Time Invervals.
91 ***************************************************************************/
92GCOSEventCube::GCOSEventCube(const std::string& coords,
93 const int& nside,
94 const std::string& order,
95 const GBounds& phibounds,
96 const GEbounds& ebounds,
97 const GGti& gti) : GEventCube()
98{
99 // Initialise members
100 init_members();
101
102 // Set event cube
103 this->set(coords, nside, order, phibounds, ebounds, gti);
104
105 // Return
106 return;
107}
108
109
110/***********************************************************************//**
111 * @brief Load constructor
112 *
113 * @param[in] filename COSI event cube FITS filename.
114 *
115 * Construct a COSI event cube by loading it from a FITS file.
116 ***************************************************************************/
118{
119 // Initialise members
120 init_members();
121
122 // Load event cube
123 load(filename);
124
125 // Return
126 return;
127}
128
129
130/***********************************************************************//**
131 * @brief Copy constructor
132 *
133 * @param[in] cube COSI event cube.
134 ***************************************************************************/
136{
137 // Initialise members
138 init_members();
139
140 // Copy members
142
143 // Return
144 return;
145}
146
147
148/***********************************************************************//**
149 * @brief Destructor
150 ***************************************************************************/
152{
153 // Free members
154 free_members();
155
156 // Return
157 return;
158}
159
160
161/*==========================================================================
162 = =
163 = Operators =
164 = =
165 ==========================================================================*/
166
167/***********************************************************************//**
168 * @brief Assignment operator
169 *
170 * @param[in] cube COSI event cube.
171 * @return COSI event cube.
172 ***************************************************************************/
174{
175 // Execute only if object is not identical
176 if (this != &cube) {
177
178 // Copy base class members
179 this->GEventCube::operator=(cube);
180
181 // Free members
182 free_members();
183
184 // Initialise members
185 init_members();
186
187 // Copy members
189
190 } // endif: object was not identical
191
192 // Return this object
193 return *this;
194}
195
196
197/***********************************************************************//**
198 * @brief Event bin access operator
199 *
200 * @param[in] index Event index [0,...,size()-1].
201 * @return Pointer to event bin.
202 *
203 * Returns pointer to an event bin. Note that the returned pointer is in
204 * fact always the same, but the method sets the pointers within the
205 * event bin so that they point to the appropriate information.
206 ***************************************************************************/
208{
209 // Set event bin
210 set_bin(index);
211
212 // Return pointer
213 return (&m_bin);
214}
215
216
217/***********************************************************************//**
218 * @brief Event bin access operator (const version)
219 *
220 * @param[in] index Event index [0,...,size()-1].
221 * @return Const pointer to event bin.
222 *
223 * Returns pointer to an event bin. Note that the returned pointer is in
224 * fact always the same, but the method sets the pointers within the
225 * event bin so that they point to the appropriate information.
226 ***************************************************************************/
227const GCOSEventBin* GCOSEventCube::operator[](const int& index) const
228{
229 // Set event bin (circumvent const correctness)
230 const_cast<GCOSEventCube*>(this)->set_bin(index);
231
232 // Return pointer
233 return (&m_bin);
234}
235
236
237/*==========================================================================
238 = =
239 = Public methods =
240 = =
241 ==========================================================================*/
242
243/***********************************************************************//**
244 * @brief Clear COSI event cube
245 *
246 * Clears COSI event cube by resetting all class members to an
247 * initial state. Any information that was present before will be lost.
248 ***************************************************************************/
250{
251 // Free class members (base and derived classes, derived class first)
252 free_members();
254 this->GEvents::free_members();
255
256 // Initialise members
257 this->GEvents::init_members();
259 init_members();
260
261 // Return
262 return;
263}
264
265
266/***********************************************************************//**
267 * @brief Clone event cube
268 *
269 * @return Pointer to deep copy of COSI event cube.
270 ***************************************************************************/
272{
273 return new GCOSEventCube(*this);
274}
275
276
277/***********************************************************************//**
278 * @brief Return number of bins in event cube
279 *
280 * @return Number of bins in event cube.
281 ***************************************************************************/
282int GCOSEventCube::size(void) const
283{
284 // Compute number of bins
285 int nbins = m_cube.npix() * m_cube.nmaps();
286
287 // Return number of bins
288 return nbins;
289}
290
291
292/***********************************************************************//**
293 * @brief Return dimension of event cube
294 *
295 * @return Number of dimensions in event cube.
296 *
297 * The number of dimensions of the event cube counts one for the sky map
298 * pixels, one for the phibar axis and one for the energy axis. So typically
299 * an event cube has 3 dimensions.
300 ***************************************************************************/
301int GCOSEventCube::dim(void) const
302{
303 // Compute dimension
304 int dim = (m_cube.is_empty()) ? 0 : m_cube.ndim() + 1;
305
306 // Return dimension
307 return dim;
308}
309
310
311/***********************************************************************//**
312 * @brief Return number of bins in axis
313 *
314 * @param[in] axis Axis [0,...,dim()-1].
315 * @return Number of bins in axis.
316 *
317 * @exception GException::out_of_range
318 * Axis is out of range.
319 *
320 * Returns the number of bins along a given event cube @p axis.
321 * If @p axis=0 the number if HealPix pixels is returned.
322 * If @p axis=1 the number of Phi laters is returned.
323 * If @p axis=2 the number of energy bins is returned.
324 ***************************************************************************/
325int GCOSEventCube::naxis(const int& axis) const
326{
327 // Optionally check if the axis is valid
328 #if defined(G_RANGE_CHECK)
329 if (axis < 0 || axis >= dim()) {
330 throw GException::out_of_range(G_NAXIS, "COSI event cube axis",
331 axis, dim());
332 }
333 #endif
334
335 // Set result
336 int naxis = (axis == 0) ? m_cube.npix() : m_cube.shape()[axis-1];
337
338 // Return result
339 return naxis;
340}
341
342
343/***********************************************************************//**
344 * @brief Load COSI event cube from FITS file
345 *
346 * @param[in] filename FITS file name.
347 *
348 * The method clears the object before loading, thus any events residing in
349 * the object before loading will be lost.
350 ***************************************************************************/
351void GCOSEventCube::load(const GFilename& filename)
352{
353 // Open FITS file
354 GFits fits(filename);
355
356 // Read event cube from FITS file
357 read(fits);
358
359 // Close FITS file
360 fits.close();
361
362 // Return
363 return;
364}
365
366
367/***********************************************************************//**
368 * @brief Save COSI event cube into FITS file
369 *
370 * @param[in] filename FITS file name.
371 * @param[in] clobber Overwrite existing FITS file?
372 *
373 * Saves the COSI event cube into a FITS file.
374 ***************************************************************************/
375void GCOSEventCube::save(const GFilename& filename, const bool& clobber) const
376{
377 // Create empty FITS file
378 GFits fits;
379
380 // Write event cube into FITS file
381 write(fits);
382
383 // Save FITS file
384 fits.saveto(filename, clobber);
385
386 // Close FITS file
387 fits.close();
388
389 // Return
390 return;
391}
392
393
394/***********************************************************************//**
395 * @brief Read COSI event cube from FITS file
396 *
397 * @param[in] fits FITS file.
398 *
399 * Reads a COSI event cube from a FITS file.
400 ***************************************************************************/
401void GCOSEventCube::read(const GFits& fits)
402{
403 // Clear object
404 clear();
405
406 // Get event cube HDU and Phi boundaries table
407 const GFitsHDU& hdu = *fits["EVENT CUBE"];
408 const GFitsTable& phibounds = *fits.table("PHI BOUNDARIES");
411
412 // Read event cube
413 m_cube.read(hdu);
414
415 // Read Phi boundaries
417
418 // Read energy boundaries
420
421 // Read Good Time Intervals
422 m_gti.read(gti);
423
424 // Read event selection statistics
425 if (hdu.has_card("NEVCHK")) {
426 m_num_events_checked = hdu.integer("NEVCHK");
427 }
428 if (hdu.has_card("NEVUSE")) {
429 m_num_events_used = hdu.integer("NEVUSE");
430 }
431 if (hdu.has_card("NEVGTI")) {
432 m_num_outside_gti = hdu.integer("NEVGTI");
433 }
434 if (hdu.has_card("NEVEBD")) {
435 m_num_outside_ebounds = hdu.integer("NEVEBD");
436 }
437 if (hdu.has_card("NEVPBD")) {
438 m_num_outside_phibounds = hdu.integer("NEVPBD");
439 }
440
441 // Set event cube shape
443
444 // Set scatter directions
446
447 // Set scatter angles
449
450 // Set energies
451 set_energies();
452
453 // Set times
454 set_times();
455
456 // Return
457 return;
458}
459
460
461/***********************************************************************//**
462 * @brief Write COSI event cube into FITS file.
463 *
464 * @param[in] fits FITS file.
465 *
466 * Writes the COSI event cube into a FITS file. The method does nothing if
467 * size() is not positive.
468 ***************************************************************************/
470{
471 // Continue only if size is positive
472 if (size() > 0) {
473
474 // Write event cube
475 m_cube.write(fits, "EVENT CUBE");
476
477 // Write Phi boundaries
478 m_phibounds.write(fits, "PHI BOUNDARIES");
479
480 // Write energy boundaries
481 m_ebounds.write(fits);
482
483 // Write Good Time Intervals
484 m_gti.write(fits);
485
486 // Optionally write event selection statistics into event cube
487 if (m_num_events_checked > 0) {
488
489 // Get event cube HDU
490 GFitsHDU* hdu = fits["EVENT CUBE"];
491
492 // Derive number of rejected events
493 int num_events_rejected = m_num_events_checked - m_num_events_used;
494
495 // Write event selection statistics
496 hdu->card("NEVCHK", m_num_events_checked, "Number of checked events");
497 hdu->card("NEVUSE", m_num_events_used, "Number of used events");
498 hdu->card("NEVREJ", num_events_rejected, "Number of rejected events");
499 hdu->card("NEVGTI", m_num_outside_gti, "Number of events outside GTI");
500 hdu->card("NEVEBD", m_num_outside_ebounds, "Number of events outside energy boundaries");
501 hdu->card("NEVPBD", m_num_outside_phibounds, "Number of events outside Phi boundaries");
502
503 }
504
505 } // endif: size was positive
506
507 // Return
508 return;
509}
510
511
512/***********************************************************************//**
513 * @brief Return number of events in cube
514 *
515 * @return Number of events in event cube.
516 *
517 * This method returns the number of events in the event cube.
518 ***************************************************************************/
519double GCOSEventCube::number(void) const
520{
521 // Initialise number of events
522 double number = 0.0;
523
524 // Get pointer to event cube bins
525 const double *ptr = m_cube.pixels();
526
527 // Loop over event cube and sum events
528 for (int i = 0; i < size(); ++i, ++ptr) {
529 number += *ptr;
530 }
531
532 // Return
533 return number;
534}
535
536
537/***********************************************************************//**
538 * @brief Set event cube
539 *
540 * @param[in] coords Event cube coordinate system (CEL or GAL).
541 * @param[in] nside Event cube Nside parameter.
542 * @param[in] order Event cube pixel ordering (RING or NEST).
543 * @param[in] phibounds Phi layer boundaries.
544 * @param[in] ebounds Event cube energy boundaries.
545 * @param[in] gti Good Time intervals.
546 *
547 * @exception GException::invalid_argument
548 * Invalid units specified for Phi layer boundaries.
549 *
550 * Sets a HealPix event cube by specifying the coordinate system, the
551 * HealPix Nside parameter and pixel ordering scheme, the event cube Phi
552 * layer boundaries, the event cube energy boundaries and the event cube
553 * Good Time Intervals.
554 ***************************************************************************/
555void GCOSEventCube::set(const std::string& coords,
556 const int& nside,
557 const std::string& order,
558 const GBounds& phibounds,
559 const GEbounds& ebounds,
560 const GGti& gti)
561{
562 // Clear event cube
563 clear();
564
565 // Compute number of maps in event cube
566 int nmaps = phibounds.size() * ebounds.size();
567
568 // Allocate event cube
569 m_cube = GSkyMap(coords, nside, order, nmaps);
570
571 // Set event cube shape
573
574 // Make sure that Phi boundaries are in degrees
575 std::string unit = gammalib::tolower(phibounds.unit());
576 if ((unit != "") && ((unit != "deg") || (unit != "degrees"))) {
577 std::string msg = "Invalid unit \""+phibounds.unit()+"\"specified for "
578 "Phi boundaries. Please specify Phi boundaries in "
579 "units of \"deg\".";
581 }
582
583 // Store Phi boundaries and set units to deg
585 m_phibounds.unit("deg");
586
587 // Store energy boundaries
589
590 // Store Good Time intervals
591 m_gti = gti;
592
593 // Set scatter directions
595
596 // Set scatter angles
598
599 // Set energies
600 set_energies();
601
602 // Set times
603 set_times();
604
605 // Return
606 return;
607}
608
609
610/***********************************************************************//**
611 * @brief Fill event cube with events from event list
612 *
613 * @param[in] list COSI event list.
614 *
615 * @exception GException::invalid_value
616 * No Good Time Intervals defined.
617 * No energy boundaries defined.
618 * No scatter angle boundaries defined.
619 *
620 * Fills events from an event list into the event cube. Events that existed
621 * in the event cube will be preserved so that events from multiple event
622 * lists can be filled into the event cube.
623 *
624 * The method requires that Good Time Intervals, energy boundaries and
625 * scatter angle boundaries are defined. If boundaries are not defined an
626 * exception will be thrown.
627 *
628 * Only events that fall within the Good Time Intervals, energy boundaries
629 * and scatter angle boundaries will be filled into the cube, other events
630 * will be ignored.
631 *
632 * The method assumes that the event list and the Good Time Intervals are
633 * sorted by increasing time. This allows for a fast check of event times
634 * against Good Time Intervals.
635 *
636 * The method updates the event filling statistics.
637 ***************************************************************************/
639{
640 // Check that boundaries are defined
641 if (gti().is_empty()) {
642 std::string msg = "No Good Time Intervals were defined for the event "
643 "cube. Please set the Good Time Intervals before "
644 "calling the method.";
646 }
647 if (ebounds().is_empty()) {
648 std::string msg = "No energy boundaries were defined for the event "
649 "cube. Please set the energy boundaries before "
650 "calling the method.";
652 }
653 if (phibounds().is_empty()) {
654 std::string msg = "No scatter angle boundaries were defined for the "
655 "event cube. Please set the scatter angle "
656 "boundaries before calling the method.";
658 }
659
660 // Initialise Good Time Interval index
661 int igti = 0;
662
663 // Loop over events
664 for (int i = 0; i < list.size(); ++i) {
665
666 // Get event and attributes
667 const GCOSEventAtom* event = list[i];
668 const GTime& time = event->time();
669
670 // Update selection statistics
672
673 // If event is before current Good Time Interval then skip event
674 if (time < gti().tstart(igti)) {
676 continue;
677 }
678
679 // If event time is after current Good Time Interval then search
680 // for the next Good Time Interval that has a stop time after the
681 // event time. If such an interval is found but the event time is
682 // not in the interval the drop the event. If no such interval was
683 // found then exit the loop.
684 if (time >= gti().tstop(igti)) {
685 bool found = false; // Signal that no GTI was found
686 igti++; // Move to next GTI
687 while (igti < gti().size()) { // Search GTIs until exhaustion
688 if (time < gti().tstop(igti)) { // If event is before stop...
689 if (time >= gti().tstart(igti)) { // then check if after start...
690 found = true; // and if so we found a new GTI
691 }
692 break; // Break since event is before GTI stop
693 }
694 igti++; // Move to next GTI
695 }
696 if (!found) { // No GTI found
697 if (igti < gti().size()) { // If GTIs are not exhausted
698 m_num_outside_gti++; // the event is dropped
699 }
700 else { // otherwise we exit the event loop
701 m_num_events_checked += list.size() - i - 1;
702 break;
703 }
704 }
705 }
706
707 // Get energy boundary index
708 int ieng = m_ebounds.index(event->energy());
709
710 // Skip event if it does not fall into energy boundaries
711 if (ieng == -1) {
713 continue;
714 }
715
716 // Get Phi boundary index
717 int iphi = m_phibounds.index(event->dir().phi());
718
719 // Skip event if it does not fall into Phi boundaries
720 if (iphi == -1) {
722 continue;
723 }
724
725 // If we survived until now the event will be used
727
728 // Compute map index
729 int imap = iphi + ieng * m_phibounds.size();
730
731 // Get skymap pixel index
732 int ipix = m_cube.dir2inx(event->dir().dir());
733
734 // Increment event cube
735 m_cube(ipix, imap) += 1.0;
736
737 } // endfor: looped over events
738
739 // Return
740 return;
741}
742
743
744/***********************************************************************//**
745 * @brief Print COSI event cube information
746 *
747 * @param[in] chatter Chattiness.
748 * @return String containing COSI event cube information.
749 ***************************************************************************/
750std::string GCOSEventCube::print(const GChatter& chatter) const
751{
752 // Initialise result string
753 std::string result;
754
755 // Continue only if chatter is not silent
756 if (chatter != SILENT) {
757
758 // Append header
759 result.append("=== GCOSEventCube ===");
760
761 // Append information
762 result.append("\n"+gammalib::parformat("Number of events"));
763 result.append(gammalib::str(number()));
764 result.append("\n"+gammalib::parformat("Number of elements"));
765 result.append(gammalib::str(size()));
766 result.append("\n"+gammalib::parformat("Number of pixels"));
767 result.append(gammalib::str(m_npix));
768 result.append("\n"+gammalib::parformat("Number of Phi layers"));
769 result.append(gammalib::str(m_phibounds.size()));
770 result.append("\n"+gammalib::parformat("Number of energy bins"));
771 result.append(gammalib::str(m_ebounds.size()));
772 result.append("\n"+gammalib::parformat("Phi boundaries"));
773 result.append(gammalib::str(m_phibounds.min())+" - ");
774 result.append(gammalib::str(m_phibounds.max())+" ");
775 result.append(m_phibounds.unit());
776 result.append("\n"+gammalib::parformat("Energy boundaries"));
777 result.append(gammalib::str(emin().keV())+" - ");
778 result.append(gammalib::str(emax().keV())+" keV");
779 result.append("\n"+gammalib::parformat("Ontime"));
780 result.append(gammalib::str(m_ontime)+" s");
781 result.append("\n"+gammalib::parformat("Mean time"));
782 result.append(m_time.print(gammalib::reduce(chatter)));
783
784 // Append GTI interval
785 result.append("\n"+gammalib::parformat("Good time intervals"));
786 result.append(gammalib::str(gti().size()));
787 result.append("\n"+gammalib::parformat("Time interval"));
788 if (gti().size() > 0) {
789 result.append(gammalib::str(tstart().mjd()));
790 result.append(" - ");
791 result.append(gammalib::str(tstop().mjd())+" Modified Julian days");
792 }
793 else {
794 result.append("not defined");
795 }
796 result.append("\n"+gammalib::parformat("Date interval"));
797 if (gti().size() > 0) {
798 result.append(tstart().utc());
799 result.append(" - ");
800 result.append(tstop().utc());
801 }
802 else {
803 result.append("not defined");
804 }
805
806 } // endif: chatter was not silent
807
808 // Return result
809 return result;
810}
811
812
813/*==========================================================================
814 = =
815 = Private methods =
816 = =
817 ==========================================================================*/
818
819/***********************************************************************//**
820 * @brief Initialise class members
821 ***************************************************************************/
823{
824 // Initialise members
825 m_cube.clear();
827 m_bin.clear();
828 m_dir.clear();
829 m_time.clear();
830 m_ontime = 0.0;
831 m_solidangle = 0.0;
832 m_npix = 0;
833 m_nphi = 0;
834 m_dirs.clear();
835 m_phis.clear();
836 m_phiwidths.clear();
837 m_energies.clear();
838 m_ewidths.clear();
839
840 // Initialise filling selection statistics
846
847 // Prepare event bin
848 init_bin();
849
850 // Return
851 return;
852}
853
854
855/***********************************************************************//**
856 * @brief Copy class members
857 *
858 * @param[in] cube COSI event cube.
859 *
860 * This method copies the class members from another event cube in the actual
861 * object. It also prepares the event bin member that will be returned in
862 * case of an operator access to the class.
863 ***************************************************************************/
865{
866 // Copy members. Note that the event bin is copied as it will be
867 // initialised by the init_bin() method. The event bin serves just as a
868 // container of pointers, hence we do not want to copy over the pointers
869 // from the original class.
870 m_cube = cube.m_cube;
871 m_phibounds = cube.m_phibounds;
872 m_dir = cube.m_dir;
873 m_time = cube.m_time;
874 m_ontime = cube.m_ontime;
875 m_solidangle = cube.m_solidangle;
876 m_npix = cube.m_npix;
877 m_nphi = cube.m_nphi;
878 m_dirs = cube.m_dirs;
879 m_phis = cube.m_phis;
880 m_phiwidths = cube.m_phiwidths;
881 m_energies = cube.m_energies;
882 m_ewidths = cube.m_ewidths;
883
884 // Copy filling selection statistics
885 m_num_events_checked = cube.m_num_events_checked;
886 m_num_events_used = cube.m_num_events_used;
887 m_num_outside_gti = cube.m_num_outside_gti;
888 m_num_outside_ebounds = cube.m_num_outside_ebounds;
889 m_num_outside_phibounds = cube.m_num_outside_phibounds;
890
891 // Prepare event bin
892 init_bin();
893
894 // Return
895 return;
896}
897
898
899/***********************************************************************//**
900 * @brief Delete class members
901 ***************************************************************************/
903{
904 // Return
905 return;
906}
907
908
909/***********************************************************************//**
910 * @brief Set scatter directions of all events cube pixels
911 *
912 * @exception GException::invalid_value
913 * No sky pixels have been defined.
914 *
915 * Computes the scatter directions of all events cube pixels. This method
916 * sets the m_dirs, m_npix and m_solidangle members of the class.
917 ***************************************************************************/
919{
920 // Clear scatter directions
921 m_dirs.clear();
922
923 // Store number of pixels
924 m_npix = m_cube.npix();
925
926 // Throw an exception if we have no sky pixels
927 if (m_npix < 1) {
928 std::string msg = "No sky pixels were defined for event cube. "
929 "Please define the sky pixels of the event "
930 "cube.";
932 }
933
934 // Reserve pixel scatter direction
935 m_dirs.reserve(m_npix);
936
937 // Set pixel scatter direction
938 for (int i = 0; i < m_npix; ++i) {
939 m_dirs[i] = m_cube.inx2dir(i);
940 }
941
942 // Store solid angle of pixels (HealPix map solid angles are constant)
944
945 // Return
946 return;
947}
948
949
950/***********************************************************************//**
951 * @brief Set Compton scatter angles of event cube
952 *
953 * @exception GException::invalid_value
954 * No scatter angles have been defined.
955 *
956 * Computes the Compton scatter angles for all Phibar layers. This method
957 * sets the m_phis, m_phiwidths and m_nphi members of the class.
958 ***************************************************************************/
960{
961 // Clear scatter angles and widths
962 m_phis.clear();
963 m_phiwidths.clear();
964
965 // Store number of Phi boundaries
967
968 // Throw an exception if we have no scatter angles
969 if (m_nphi < 1) {
970 std::string msg = "No scatter angles were defined for event cube. "
971 "Please define the scatter angles of the event "
972 "cube.";
974 }
975
976 // Reserve space for scatter angles and widths
977 m_phis.reserve(m_nphi);
978 m_phiwidths.reserve(m_nphi);
979
980 // Set mean scatter angles and scatter angle bin widths
981 for (int i = 0; i < m_nphi; ++i) {
982 m_phis[i] = m_phibounds.mean(i);
984 }
985
986 // Return
987 return;
988}
989
990
991/***********************************************************************//**
992 * @brief Set log mean energies and energy widths of energy bins
993 *
994 * @exception GException::invalid_value
995 * No energy boundaries defined.
996 *
997 * Computes the long mean energy and energy bin width of the event cube.
998 ***************************************************************************/
1000{
1001 // Clear energies and energy widths
1002 m_energies.clear();
1003 m_ewidths.clear();
1004
1005 // Throw an exception if energy boundaries are empty
1006 if (m_ebounds.size() < 1) {
1007 std::string msg = "No energy boundaries were defined for event cube. "
1008 "Please define the energy boundaries of the event "
1009 "cube.";
1011 }
1012
1013 // Reserve energies and energy widths
1014 m_energies.reserve(m_ebounds.size());
1015 m_ewidths.reserve(m_ebounds.size());
1016
1017 // Loop over energy bins
1018 for (int i = 0; i < m_ebounds.size(); ++i) {
1020 m_ewidths[i] = m_ebounds.emax(i) - m_ebounds.emin(i);
1021 }
1022
1023 // Return
1024 return;
1025}
1026
1027
1028/***********************************************************************//**
1029 * @brief Set mean event time and ontime of event cube
1030 *
1031 * @exception GException::invalid_value
1032 * No Good Time Intervals found.
1033 *
1034 * Computes the mean time of the event cube by taking the mean between start
1035 * and stop time. Computes also the ontime by summing up of all good time
1036 * intervals.
1037 ***************************************************************************/
1039{
1040 // Throw an exception if GTI is empty
1041 if (m_gti.size() < 1) {
1042 std::string msg = "No Good Time Intervals were defined for event "
1043 "cube. Please define the Good Time Intervals of "
1044 "the event cube.";
1046 }
1047
1048 // Compute mean time
1049 m_time = m_gti.tstart() + 0.5 * (m_gti.tstop() - m_gti.tstart());
1050
1051 // Set ontime
1052 m_ontime = m_gti.ontime();
1053
1054 // Return
1055 return;
1056}
1057
1058
1059/***********************************************************************//**
1060 * @brief Initialise event bin
1061 *
1062 * Initialises the event bin. The event bin is cleared and all fixed pointers
1063 * are set. Only the m_counts, m_phiwidth, m_energy and m_ewidth members of
1064 * the event bin will be set to NULL as those will change for individual bins
1065 * and set by the set_bin() method. The set_bin() method is called before any
1066 * event bin access.
1067 ***************************************************************************/
1069{
1070 // Prepare event bin
1072 m_bin.m_counts = NULL; //!< Will be set by set_bin method
1073 m_bin.m_dir = &m_dir; //!< Content will be set by set_bin method
1074 m_bin.m_solidangle = &m_solidangle; //!< Fixed content
1075 m_bin.m_time = &m_time; //!< Fixed content
1076 m_bin.m_ontime = &m_ontime; //!< Fixed content
1077 m_bin.m_phiwidth = NULL; //!< Will be set by set_bin method
1078 m_bin.m_energy = NULL; //!< Will be set by set_bin method
1079 m_bin.m_ewidth = NULL; //!< Will be set by set_bin method
1080
1081 // Return
1082 return;
1083}
1084
1085
1086/***********************************************************************//**
1087 * @brief Set event bin
1088 *
1089 * @param[in] index Event index [0,...,size()[.
1090 *
1091 * @exception GException::out_of_range
1092 * Event index is outside valid range.
1093 *
1094 * Sets the pointers of the event bin to the event cube cell that corresponds
1095 * to the specified @p index. The event bin is in fact physically stored in
1096 * the event cube, and only a single event bin is indeed allocated. This
1097 * method sets up the pointers in the event bin so that a client can easily
1098 * access the information of individual bins as if they were stored in an
1099 * array.
1100 *
1101 * The method updates the following members of the event bin: m_index,
1102 * m_counts, m_phiwidth, m_energy and m_ewidth.
1103 *
1104 * The method also updates the event bin direction m_dir.
1105 ***************************************************************************/
1106void GCOSEventCube::set_bin(const int& index)
1107{
1108 // Optionally check if the index is valid
1109 #if defined(G_RANGE_CHECK)
1110 if (index < 0 || index >= size()) {
1111 throw GException::out_of_range(G_SET_BIN, "Event index", index, size());
1112 }
1113 #endif
1114
1115 // Get pixel, phi layer and energy bin indices.
1116 int ipix = index % m_npix;
1117 int imap = index / m_npix;
1118 int iphi = imap % m_nphi;
1119 int ieng = imap / m_nphi;
1120
1121 // Set event bin member
1122 m_bin.m_index = index;
1123 m_bin.m_counts = &((const_cast<double*>(m_cube.pixels()))[index]);
1124 m_bin.m_phiwidth = &(m_phiwidths[iphi]);
1125 m_bin.m_energy = &(m_energies[ieng]);
1126 m_bin.m_ewidth = &(m_ewidths[ieng]);
1127
1128 // Set instrument direction member
1129 m_dir.dir(m_dirs[ipix]);
1130 m_dir.phi(m_phis[iphi]);
1131
1132 // Return
1133 return;
1134}
Boundaries class interface definition.
#define G_SET_TIMES
#define G_SET_ENERGIES
#define G_SET_SCATTER_DIRECTIONS
#define G_SET_BIN
#define G_NAXIS
#define G_SET_SCATTER_ANGLES
#define G_FILL
COSI event bin container class definition.
COSI event list class definition.
Energy boundaries class interface definition.
#define G_SET
Definition GEnergies.cpp:46
Sky map class definition.
GChatter
Definition GTypemaps.hpp:33
@ SILENT
Definition GTypemaps.hpp:34
Boundaries container class.
Definition GBounds.hpp:59
void read(const GFitsTable &table)
Read boundaries from FITS table.
Definition GBounds.cpp:662
void clear(void)
Clear boundaries.
Definition GBounds.cpp:262
const std::string & unit(void) const
Return boundary units.
Definition GBounds.hpp:178
double max(void) const
Return maximum value of all intervals.
Definition GBounds.cpp:806
double mean(const int &index) const
Returns mean value for a given interval.
Definition GBounds.cpp:943
double min(void) const
Return minimum value of all intervals.
Definition GBounds.cpp:781
void write(GFits &file, const std::string &extname=gammalib::extname_bounds) const
Write boundaries into FITS object.
Definition GBounds.cpp:703
int size(void) const
Return number of boundaries.
Definition GBounds.hpp:154
int index(const double &value) const
Returns bin index for a value.
Definition GBounds.cpp:758
COSI event atom class.
COSI event bin class.
double * m_ontime
Pointer to ontime of bin (seconds)
double * m_phiwidth
Pointer to Phi width.
virtual void clear(void)
Clear COSI event bin.
GEnergy * m_energy
Pointer to bin energy.
GTime * m_time
Pointer to bin time.
GEnergy * m_ewidth
Pointer to energy width of bin.
int m_index
Dataspace index.
GCOSInstDir * m_dir
Pointer to bin direction.
double * m_solidangle
Pointer to solid angle of pixel (sr)
double * m_counts
Pointer to number of counts.
void free_members(void)
Delete class members.
COSI event bin container class.
void init_members(void)
Initialise class members.
std::vector< GEnergy > m_ewidths
Cube energy bin widths.
virtual int naxis(const int &axis) const
Return number of bins in axis.
virtual void clear(void)
Clear COSI event cube.
void free_members(void)
Delete class members.
virtual GCOSEventCube & operator=(const GCOSEventCube &cube)
Assignment operator.
GCOSEventBin m_bin
Current event bin.
virtual int size(void) const
Return number of bins in event cube.
void set(const std::string &coords, const int &nside, const std::string &order, const GBounds &phibounds, const GEbounds &ebounds, const GGti &gti)
Set event cube.
virtual GCOSEventBin * operator[](const int &index)
Event bin access operator.
int m_num_outside_ebounds
Number of events outside energy boundaries.
std::vector< double > m_phiwidths
Array of scatter angles bin widths.
void init_bin(void)
Initialise event bin.
int m_num_outside_phibounds
Number of events outside scatter angle bounds.
virtual void read(const GFits &fits)
Read COSI event cube from FITS file.
void copy_members(const GCOSEventCube &cube)
Copy class members.
virtual ~GCOSEventCube(void)
Destructor.
virtual void set_energies(void)
Set log mean energies and energy widths of energy bins.
const GSkyMap & cube(void) const
Return event cube.
GBounds m_phibounds
Phi layer boundaries.
void set_scatter_angles(void)
Set Compton scatter angles of event cube.
int m_num_outside_gti
Number of events outside GTI.
GCOSEventCube(void)
Void constructor.
double m_ontime
Event cube ontime (sec)
virtual GCOSEventCube * clone(void) const
Clone event cube.
const GBounds & phibounds(void) const
Return Phi boundaries.
void set_scatter_directions(void)
Set scatter directions of all events cube pixels.
int m_num_events_checked
Number of checked events.
virtual double number(void) const
Return number of events in cube.
int m_npix
Number of HealPix pixels.
GCOSInstDir m_dir
Current event direction.
void fill(const GCOSEventList &list)
Fill event cube with events from event list.
GTime m_time
Event cube mean time.
virtual void load(const GFilename &filename)
Load COSI event cube from FITS file.
GSkyMap m_cube
Event cube.
double m_solidangle
Event bin solid angle (sr)
const GTime & time(void) const
Return event cube time.
virtual int dim(void) const
Return dimension of event cube.
virtual void write(GFits &fits) const
Write COSI event cube into FITS file.
int m_num_events_used
Number of used events.
virtual std::string print(const GChatter &chatter=NORMAL) const
Print COSI event cube information.
virtual void save(const GFilename &filename, const bool &clobber=false) const
Save COSI event cube into FITS file.
std::vector< GEnergy > m_energies
Cube energy bin mean energies.
virtual void set_times(void)
Set mean event time and ontime of event cube.
std::vector< GSkyDir > m_dirs
Cube pixel scatter directions.
std::vector< double > m_phis
Array of scatter angles.
void set_bin(const int &index)
Set event bin.
int m_nphi
Number of Phi layers.
COSI event list class.
virtual int size(void) const
Return number of events in list.
void phi(const double &phi)
Set event Compton scatter angle.
virtual void clear(void)
Clear COSI instrument direction.
void dir(const GSkyDir &dir)
Set event scatter direction in celestial coordinates.
Energy boundaries container class.
Definition GEbounds.hpp:60
int index(const GEnergy &eng) const
Returns energy bin index for a given energy.
Definition GEbounds.cpp:948
const GEnergy & emax(void) const
Return maximum energy of all intervals.
Definition GEbounds.hpp:199
void read(const GFitsTable &table)
Read energy boundaries from FITS table.
Definition GEbounds.cpp:761
int size(void) const
Return number of energy boundaries.
Definition GEbounds.hpp:163
GEnergy elogmean(const int &index) const
Returns logarithmic mean energy for a given energy interval.
const GEnergy & emin(void) const
Return minimum energy of all intervals.
Definition GEbounds.hpp:187
void write(GFits &file, const std::string &extname=gammalib::extname_ebounds, const std::string &unit="keV") const
Write energy boundaries into FITS object.
Definition GEbounds.cpp:816
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 GEbounds & ebounds(void) const
Return energy boundaries.
Definition GEvents.hpp:122
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
Abstract FITS extension base class.
Definition GFitsHDU.hpp:51
bool has_card(const int &cardno) const
Check existence of header card.
Definition GFitsHDU.hpp:233
GFitsHeaderCard & card(const int &cardno)
Return header card.
Definition GFitsHDU.hpp:259
int integer(const std::string &keyname) const
Return card value as integer.
Definition GFitsHDU.hpp:436
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
GFitsTable * table(const int &extno)
Get pointer to table HDU.
Definition GFits.cpp:482
Good Time Interval class.
Definition GGti.hpp:63
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
const GTime & tstop(void) const
Returns latest stop time in Good Time Intervals.
Definition GGti.hpp:210
void read(const GFitsTable &table)
Read Good Time Intervals and time reference from FITS table.
Definition GGti.cpp:772
int size(void) const
Return number of Good Time Intervals.
Definition GGti.hpp:157
const double & ontime(void) const
Returns ontime.
Definition GGti.hpp:243
const GTime & tstart(void) const
Returns earliest start time in Good Time Intervals.
Definition GGti.hpp:197
Sky map class.
Definition GSkyMap.hpp:89
double solidangle(const int &index) const
Returns solid angle of pixel.
Definition GSkyMap.cpp:1858
int ndim(void) const
Returns dimension of maps.
Definition GSkyMap.hpp:451
const int & nmaps(void) const
Returns number of maps.
Definition GSkyMap.hpp:427
void clear(void)
Clear instance.
Definition GSkyMap.cpp:1100
GSkyDir inx2dir(const int &index) const
Returns sky direction of pixel.
Definition GSkyMap.cpp:1331
bool is_empty(void) const
Signals if sky map is empty.
Definition GSkyMap.hpp:369
int dir2inx(const GSkyDir &dir) const
Returns pixel index for a given sky direction.
Definition GSkyMap.cpp:1445
void read(const GFitsHDU &hdu)
Read skymap from FITS HDU.
Definition GSkyMap.cpp:2664
const int & npix(void) const
Returns number of pixels.
Definition GSkyMap.hpp:383
GFitsHDU * write(GFits &file, const std::string &extname="") const
Write sky map into FITS file.
Definition GSkyMap.cpp:2697
const std::vector< int > & shape(void) const
Returns shape of maps.
Definition GSkyMap.hpp:439
const double * pixels(void) const
Returns pointer to pixel data.
Definition GSkyMap.hpp:513
Time class.
Definition GTime.hpp:55
void clear(void)
Clear time.
Definition GTime.cpp:252
std::string print(const GChatter &chatter=NORMAL) const
Print time.
Definition GTime.cpp:1212
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1136
const std::string extname_ebounds
Definition GEbounds.hpp:44
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:508
std::string tolower(const std::string &s)
Convert string to lower case.
Definition GTools.cpp:948
GChatter reduce(const GChatter &chatter)
Reduce chattiness by one level.
Definition GTypemaps.hpp:65
const std::string extname_gti
Definition GGti.hpp:45