GammaLib 2.1.0.dev
Loading...
Searching...
No Matches
GCOMDri.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * GCOMDri.cpp - COMPTEL Data Space class *
3 * ----------------------------------------------------------------------- *
4 * copyright (C) 2017-2023 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 GCOMDri.cpp
23 * @brief COMPTEL Data Space class implementation
24 * @author Juergen Knoedlseder
25 */
26
27/* __ Includes ___________________________________________________________ */
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include "GTools.hpp"
32#include "GMath.hpp"
33#include "GWcs.hpp"
34#include "GFits.hpp"
35#include "GFitsImage.hpp"
36#include "GNodeArray.hpp"
37#include "GModelSky.hpp"
38#include "GModelSpatial.hpp"
40#include "GEphemerides.hpp"
41#include "GCOMTools.hpp"
42#include "GCOMSupport.hpp"
43#include "GCOMDri.hpp"
44#include "GCOMOad.hpp"
45#include "GCOMOads.hpp"
46#include "GCOMTim.hpp"
47#include "GCOMStatus.hpp"
48#include "GCOMObservation.hpp"
49#include "GCOMEventList.hpp"
50#include "GCOMSelection.hpp"
51
52/* __ Method name definitions ____________________________________________ */
53#define G_COMPUTE_DRE "GCOMDri::compute_dre(GCOMObservation&, "\
54 "GCOMSelection&, double&)"
55#define G_COMPUTE_DRX "GCOMDri::compute_drx(GCOMObservation&, "\
56 "GCOMSelection&, double&)"
57#define G_COMPUTE_DRM "GCOMDri::compute_drm(GCOMObservation&, GModel&)"
58#define G_COMPUTE_TOF_CORRECTION "GCOMDri::compute_tof_correction()"
59
60/* __ Macros _____________________________________________________________ */
61
62/* __ Coding definitions _________________________________________________ */
63//#define G_CHECK_EHA_COMPUTATION
64
65/* __ Debug definitions __________________________________________________ */
66//#define G_DEBUG_COMPUTE_DRE
67//#define G_DEBUG_COMPUTE_DRG
68//#define G_DEBUG_COMPUTE_DRX
69
70/* __ Constants __________________________________________________________ */
71const double superpacket_duration = 16.384; // Duration of superpacket (s)
72const double r1 = 13.8; // D1 module radius (cm)
73
74/* __ Derived constants __________________________________________________ */
75const double r1sq = r1 * r1;
76const double d1_area = 7.0 * gammalib::pi * r1sq;
77
78
79/*==========================================================================
80 = =
81 = Constructors/destructors =
82 = =
83 ==========================================================================*/
84
85/***********************************************************************//**
86 * @brief Void constructor
87 ***************************************************************************/
89{
90 // Initialise class members
92
93 // Return
94 return;
95}
96
97
98/***********************************************************************//**
99 * @brief File name constructor
100 *
101 * @param[in] filename COMPTEL Data Space FITS file name.
102 ***************************************************************************/
104{
105 // Initialise class members
106 init_members();
107
108 // Load DRI FITS file
109 load(filename);
110
111 // Return
112 return;
113}
114
115
116/***********************************************************************//**
117 * @brief Sky map constructor
118 *
119 * @param[in] map Sky map defining the DRI cube.
120 * @param[in] phimin Minimum Phibar angle (deg).
121 * @param[in] phibin Bin size of Phibar angle (deg).
122 * @param[in] nphibin Number of Phibar bins.
123 *
124 * Constructs a DRI cube from a sky map and a Phibar binning definition.
125 ***************************************************************************/
127 const double& phimin,
128 const double& phibin,
129 const int& nphibin)
130{
131 // Initialise class members
132 init_members();
133
134 // Set sky map
135 m_dri = map;
136
137 // Make sure that sky map can hold the required number of maps
138 if (nphibin > 0) {
139 m_dri.nmaps(nphibin);
140 }
141
142 // Set all sky map pixels to zero
143 m_dri = 0;
144
145 // Store minimum Phibar and bin size
148
149 // Return
150 return;
151}
152
153
154/***********************************************************************//**
155 * @brief Copy constructor
156 *
157 * @param[in] dri COMPTEL Data Space.
158 ***************************************************************************/
160{
161 // Initialise class members
162 init_members();
163
164 // Copy members
165 copy_members(dri);
166
167 // Return
168 return;
169}
170
171
172/***********************************************************************//**
173 * @brief Destructor
174 ***************************************************************************/
176{
177 // Free members
178 free_members();
179
180 // Return
181 return;
182}
183
184
185/*==========================================================================
186 = =
187 = Operators =
188 = =
189 ==========================================================================*/
190
191/***********************************************************************//**
192 * @brief Assignment operator
193 *
194 * @param[in] dri COMPTEL Data Space.
195 * @return COMPTEL Data Space.
196 ***************************************************************************/
198{
199 // Execute only if object is not identical
200 if (this != &dri) {
201
202 // Free members
203 free_members();
204
205 // Initialise private members
206 init_members();
207
208 // Copy members
209 copy_members(dri);
210
211 } // endif: object was not identical
212
213 // Return this object
214 return *this;
215}
216
217
218/*==========================================================================
219 = =
220 = Public methods =
221 = =
222 ==========================================================================*/
223
224/***********************************************************************//**
225 * @brief Clear COMPTEL Data Space
226 ***************************************************************************/
228{
229 // Free members
230 free_members();
231
232 // Initialise private members
233 init_members();
234
235 // Return
236 return;
237}
238
239
240/***********************************************************************//**
241 * @brief Clone COMPTEL Data Space
242 *
243 * @return Pointer to deep copy of COMPTEL Data Space.
244 ***************************************************************************/
246{
247 return new GCOMDri(*this);
248}
249
250
251/***********************************************************************//**
252 * @brief Compute event cube
253 *
254 * @param[in] obs COMPTEL observation.
255 * @param[in] select Selection set.
256 * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg).
257 *
258 * @exception GException::invalid_argument
259 * DRE cube has a non-positive Phibar bin size.
260 * @exception GException::invalid_value
261 * No BVC data available for pulsar selection
262 *
263 * Compute DRE event cube for a COMPTEL observation.
264 ***************************************************************************/
266 const GCOMSelection& select,
267 const double& zetamin)
268{
269 // Debug
270 #if defined(G_DEBUG_COMPUTE_DRE)
271 std::cout << "GCOMDri::compute_dre" << std::endl;
272 std::cout << "====================" << std::endl;
273 #endif
274
275 // Check if observation contains a COMPTEL event list
276 const GCOMEventList* events = dynamic_cast<const GCOMEventList*>(obs.events());
277 if (events == NULL) {
278 std::string msg = "No event list found in COMPTEL observation. Please "
279 "specify an observation that contains an event list.";
281 }
282
283 // Check for positive Phibar bin size
284 if (m_phibin <= 0.0) {
285 std::string msg = "DRE cube has a non-positive Phibar bin size. Please "
286 "specify a DRE cube with a positive Phibar bin size.";
288 }
289
290 // Initialise event counter
291 int i_evt = 0;
292
293 // Initialise superpacket statistics
295
296 // Store selection set
297 m_selection = select;
298
299 // Initialise selection statistics
301
302 // Signal that event selection was used (this will enable writing into
303 // the FITS HDU) and store Earth horizon cut
304 m_has_selection = true;
305 m_zetamin = zetamin;
306
307 // Compute ToF correction
309
310 // Initialise statistics
311 int num_used_events = 0;
312 int num_event_outside_sp = 0;
313 int num_energy_too_low = 0;
314 int num_energy_too_high = 0;
315 int num_eha_too_small = 0;
316 int num_phibar_too_low = 0;
317 int num_phibar_too_high = 0;
318 int num_outside_dre = 0;
319 int num_event_before_dre = 0;
320 int num_event_after_dre = 0;
321 int num_processed = 0;
322
323 // Set all DRE bins to zero
324 init_cube();
325
326 // Signal that loop should be terminated
327 bool terminate = false;
328
329 // Initialise JPL DE200 ephemerides (use in case that no BVC data are
330 // available)
331 GEphemerides ephem;
332
333 // Get Good Time Intervals. If a pulsar selection is specified then
334 // reduce the Good Time Intervals to the validity intervals of the pulsar
335 // emphemerides.
336 GCOMTim tim = obs.tim();
337 if (m_selection.has_pulsar()) {
341 }
342
343 // Loop over Orbit Aspect Data
344 for (int i_oad = 0; i_oad < obs.oads().size(); ++i_oad) {
345
346 // Get reference to Orbit Aspect Data of superpacket
347 const GCOMOad &oad = obs.oads()[i_oad];
348
349 // Check superpacket usage
350 if (!use_superpacket(oad, tim, select)) {
351 continue;
352 }
353
354 // Prepare Earth horizon angle comparison
355 GSkyDir sky_geocentre;
356 double theta_geocentre = double(oad.gcel());
357 double phi_geocentre = double(oad.gcaz());
358 sky_geocentre.radec_deg(phi_geocentre, 90.0-theta_geocentre);
359
360 // Collect all events within superpacket. Break if the end
361 // of the event list was reached.
362 for (; i_evt < events->size(); ++i_evt) {
363
364 // Get pointer to event
365 const GCOMEventAtom* event = (*events)[i_evt];
366
367 // Break loop if the end of the superpacket was reached
368 if (event->time() > oad.tstop()) {
369 break;
370 }
371
372 // Increase number of processed events
373 num_processed++;
374
375 // Check GTIs if the DRE has GTIs
376 if (m_gti.size() > 0) {
377
378 // Skip event if it lies before the DRE start.
379 if (event->time() < m_gti.tstart()) {
380 num_event_before_dre++;
381 continue;
382 }
383
384 // Break if event lies after the DRE stop
385 else if (event->time() > m_gti.tstop()) {
386 num_event_after_dre++;
387 terminate = true;
388 break;
389 }
390
391 } // endif: DRE had GTIs
392
393 // Skip event if it lies before the superpacket start
394 if (event->time() < oad.tstart()) {
395 num_event_outside_sp++;
396 continue;
397 }
398
399 // Skip event if it lies outside energy range
400 if (event->energy() < m_ebounds.emin()) {
401 num_energy_too_low++;
402 continue;
403 }
404 else if (event->energy() > m_ebounds.emax()) {
405 num_energy_too_high++;
406 continue;
407 }
408
409 // Apply event selection
410 if (!m_selection.use_event(*event)) {
411 continue;
412 }
413
414 // Compute Compton scatter angle index. Skip if it's invalid.
415 int iphibar = int((event->phibar() - m_phimin) / m_phibin);
416 if (iphibar < 0) {
417 num_phibar_too_low++;
418 continue;
419 }
420 else if (iphibar >= nphibar()) {
421 num_phibar_too_high++;
422 continue;
423 }
424
425 // Option: Earth horizon angle comparison
426 #if defined(G_CHECK_EHA_COMPUTATION)
427 GSkyDir sky_event;
428 double theta_event = double(event->theta());
429 double phi_event = double(event->phi());
430 sky_event.radec_deg(-phi_event, 90.0-theta_event);
431 double eha = sky_geocentre.dist_deg(sky_event) - oad.georad();
432 if (std::abs(eha - event->eha()) > 1.5) {
433 std::string msg = "Earth horizon angle from EVP dataset ("+
434 gammalib::str(event->eha())+" deg) "
435 "differs from Earth horizon angle "
436 "computed from Orbit Aspect Data ("+
437 gammalib::str(eha)+" deg). Use the EVP "
438 "value.";
440 }
441 #endif
442
443 // Check for Earth horizon angle. There is a constant EHA limit
444 // over a Phibar layer to be compliant with the DRG.
445 double ehamin = double(iphibar) * m_phibin + zetamin;
446 if (event->eha() < ehamin) {
447 num_eha_too_small++;
448 continue;
449 }
450
451 // Optionally apply pulsar phase selection
452 if (m_selection.has_pulsar()) {
453
454 // Get pulsar ephemeris
455 const GPulsarEphemeris& ephemeris =
456 m_selection.pulsar().ephemeris(event->time());
457
458 // Convert event time to Solar System Barycentre time. If BVC
459 // information is available it will be used for the computation,
460 // otherwise the time correction will be computed on-the-fly
461 // from the JPL DE200 ephemerides.
462 //
463 // Note that the time correction includes an UTC_TO_TT conversion
464 // term, but this terms has already applied when setting the GTime
465 // object. Hence if time is read as time.mjd() the correction
466 // would be applied twice, yet reading the time as time.mjd('UTC')
467 // will remove the correation again.
468 double tdelta = 0.0;
469 if (obs.bvcs().is_empty()) {
470 tdelta = ephem.geo2ssb(ephemeris.dir(), event->time(), oad.pos()) +
471 event->time().utc2tt();
472 }
473 else {
474 tdelta = obs.bvcs().tdelta(ephemeris.dir(), event->time());
475 }
476 GTime time = event->time() + tdelta;
477
478 // Compute pulsar phase. See comment above why "UTC" needs
479 // to be specified.
480 double phase = ephemeris.phase(time, "UTC");
481
482 // If phase is not contained in phase interval then skip event
483 if (!m_selection.pulsar_phases().contains(phase)) {
484 continue;
485 }
486
487 } // endif: applied pulsar selection
488
489 // Now fill the event into the DRE. Put this in a try-catch
490 // block so that any invalid transformations are catched.
491 try {
492 GSkyPixel pixel = m_dri.dir2pix(event->dir().dir());
493 if (m_dri.contains(pixel)) {
494 int inx = m_dri.pix2inx(pixel) + iphibar * m_dri.npix();
495 (*this)[inx] += 1.0;
496 num_used_events++;
497 }
498 else {
499 num_outside_dre++;
500 }
501 }
503 num_outside_dre++;
504 }
505
506 } // endfor: collected events
507
508 // Break if termination was signalled or if there are no more events
509 if (terminate || i_evt >= events->size()) {
510 break;
511 }
512
513 } // endfor: looped over Orbit Aspect Data
514
515 // Set Good Time interval for DRE
516 if (m_num_used_superpackets > 0) {
518 }
519
520 // Debug
521 #if defined(G_DEBUG_COMPUTE_DRE)
522 std::cout << "Total number of superpackets .: " << m_num_superpackets << std::endl;
523 std::cout << "Used superpackets ............: " << m_num_used_superpackets << std::endl;
524 std::cout << "Skipped superpackets .........: " << m_num_skipped_superpackets << std::endl;
525 std::cout << "Total number of events .......: " << events.size() << std::endl;
526 std::cout << "Processed events .............: " << num_processed << std::endl;
527 std::cout << "Used events ..................: " << num_used_events << std::endl;
528 std::cout << "Events outside superpacket ...: " << num_event_outside_sp << std::endl;
529 std::cout << "Events before DRE GTI ........: " << num_event_before_dre << std::endl;
530 std::cout << "Events after DRE GTI .........: " << num_event_after_dre << std::endl;
531 std::cout << "Energy too low ...............: " << num_energy_too_low << std::endl;
532 std::cout << "Energy too high ..............: " << num_energy_too_high << std::endl;
533 std::cout << "Phibar too low ...............: " << num_phibar_too_low << std::endl;
534 std::cout << "Phibar too high ..............: " << num_phibar_too_high << std::endl;
535 std::cout << "Outside DRE cube .............: " << num_outside_dre << std::endl;
536 std::cout << "Earth horizon angle too small : " << num_eha_too_small << std::endl;
537 std::cout << m_selection << std::endl;
538 #endif
539
540 // Return
541 return;
542}
543
544
545/***********************************************************************//**
546 * @brief Compute geometry cube
547 *
548 * @param[in] obs COMPTEL observation.
549 * @param[in] select Selection set.
550 * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg).
551 *
552 * @exception GException::invalid_value
553 * No BVC data available for pulsar selection
554 *
555 * Compute DRG cube for a COMPTEL observation.
556 ***************************************************************************/
558 const GCOMSelection& select,
559 const double& zetamin)
560{
561 // Debug
562 #if defined(G_DEBUG_COMPUTE_DRG)
563 std::cout << "GCOMDri::compute_drg" << std::endl;
564 std::cout << "====================" << std::endl;
565 #endif
566
567 // Initialise D1 & D2 module status
568 GCOMStatus status;
569
570 // Initialise superpacket statistics
572
573 // Store selection set so that handling of failed PMT flag is correctly
574 // written into the FITS header
575 m_selection = select;
576
577 // Set all DRG bins to zero
578 init_cube();
579
580 // Get Good Time Intervals. If a pulsar selection is specified then
581 // reduce the Good Time Intervals to the validity intervals of the pulsar
582 // emphemerides.
583 GCOMTim tim = obs.tim();
584 if (m_selection.has_pulsar()) {
586 }
587
588 // Loop over Orbit Aspect Data
589 for (int i_oad = 0; i_oad < obs.oads().size(); ++i_oad) {
590
591 // Get reference to Orbit Aspect Data of superpacket
592 const GCOMOad &oad = obs.oads()[i_oad];
593
594 // Check superpacket usage
595 if (!use_superpacket(oad, tim, select)) {
596 continue;
597 }
598
599 // Prepare Earth horizon angle computation. The celestial system
600 // is reinterpreted as the COMPTEL coordinate system, where the
601 // 90 degrees - zenith angle becomes the declination and the azimuth
602 // angle becomes Right Ascension. This allows us later to use the
603 // GSkyDir::dist method to compute the distance between the geocentre
604 // and the telescope Z-axis.
605 double theta_geocentre = double(oad.gcel());
606 double phi_geocentre = double(oad.gcaz());
607 GSkyDir geocentre_comptel;
608 geocentre_comptel.radec_deg(phi_geocentre, 90.0-theta_geocentre);
609
610 // Compute geometrical factors for all (Chi, Psi)
611 for (int index = 0; index < m_dri.npix(); ++index) {
612
613 // Get sky direction for (Chi, Psi)
614 GSkyDir sky = m_dri.inx2dir(index);
615
616 // Convert sky direction to COMPTEL coordinates
617 double theta = oad.theta(sky);
618 double phi = oad.phi(sky);
619
620 // Compute geometric factor summed over all D1, D2
621 double geometry = compute_geometry(oad.tjd(), theta, phi, select, status);
622
623 // Compute Earth horizon angle as the distance between the Earth
624 // centre in COMPTEL coordinates and the (Chi, Psi) pixel in
625 // COMPTEL coordinates minus the radius of the Earth.
626 GSkyDir chipsi_comptel;
627 chipsi_comptel.radec_deg(phi, 90.0-theta);
628 double eha = geocentre_comptel.dist_deg(chipsi_comptel) - oad.georad();
629
630 // Loop over Phibar
631 for (int iphibar = 0; iphibar < nphibar(); ++iphibar) {
632
633 // Compute minimum Earth horizon angle for Phibar layer
634 double ehamin = double(iphibar) * m_phibin + zetamin;
635
636 // Add up geometry if the Earth horizon angle is equal or
637 // larger than the minimum
638 if (eha >= ehamin) {
639 int inx = index + iphibar * m_dri.npix();
640 (*this)[inx] += geometry;
641 }
642
643 } // endfor: looped over Phibar
644
645 } // endfor: looped over (Chi, Psi)
646
647 } // endfor: looped over Orbit Aspect Data
648
649 // Divide DRG by number of used superpackets
650 if (m_num_used_superpackets > 0) {
651 double norm = 1.0 / double(m_num_used_superpackets);
652 for (int i = 0; i < size(); ++i) {
653 (*this)[i] *= norm;
654 }
655 }
656
657 // Clear energy boundaries for DRG since DRG does not depend on energy)
659
660 // Set the Good Time interval for DRG
661 if (m_num_used_superpackets > 0) {
663 }
664
665 // Debug
666 #if defined(G_DEBUG_COMPUTE_DRG)
667 std::cout << "Total number of superpackets .: " << m_num_superpackets << std::endl;
668 std::cout << "Used superpackets ............: " << m_num_used_superpackets << std::endl;
669 std::cout << "Skipped superpackets .........: " << m_num_skipped_superpackets << std::endl;
670 #endif
671
672 // Return
673 return;
674}
675
676
677/***********************************************************************//**
678 * @brief Compute DRX exposure map
679 *
680 * @param[in] obs COMPTEL observation.
681 * @param[in] select Selection set.
682 *
683 * @exception GException::invalid_value
684 * No BVC data available for pulsar selection
685 *
686 * Compute DRX exposure map for a COMPTEL observation.
687 *
688 * For a given superpacket, the exposure is computed using
689 *
690 * \f[
691 * X_i(\theta_c) = 7 \pi r_1^2 \cos \theta_c
692 * \frac{1 - \exp \left( -\tau \ \cos \theta_c \right)}
693 * {1 - \exp \left( -\tau \right)}
694 * \f]
695 *
696 * where
697 * \f$\tau=0.2\f$ is the typical thickness of a D1 module in radiation
698 * lengths,
699 * \f$r_1=13.8\f$ cm is the radius of a D1 module, and
700 * \f$\theta_c\f$ is the zenith angle in COMPTEL coordinates.
701 ***************************************************************************/
703 const GCOMSelection& select)
704{
705 // Debug
706 #if defined(G_DEBUG_COMPUTE_DRX)
707 std::cout << "GCOMDri::compute_drx" << std::endl;
708 std::cout << "====================" << std::endl;
709 #endif
710
711 // Initialise constants
712 const double tau = 0.2; // Thickness in radiation lenghts
713
714 // Initialise superpacket statistics
716
717 // Set all DRX bins to zero
718 init_cube();
719
720 // Get Good Time Intervals. If a pulsar selection is specified then
721 // reduce the Good Time Intervals to the validity intervals of the pulsar
722 // emphemerides.
723 GCOMTim tim = obs.tim();
724 if (select.has_pulsar()) {
725 tim.reduce(select.pulsar().validity());
726 }
727
728 // Loop over Orbit Aspect Data
729 for (int i_oad = 0; i_oad < obs.oads().size(); ++i_oad) {
730
731 // Get reference to Orbit Aspect Data of superpacket
732 const GCOMOad &oad = obs.oads()[i_oad];
733
734 // Check superpacket usage
735 if (!use_superpacket(oad, tim, select)) {
736 continue;
737 }
738
739 // Loop over all DRX pixels
740 for (int index = 0; index < m_dri.npix(); ++index) {
741
742 // Get sky direction for DRX pixel
743 GSkyDir sky = m_dri.inx2dir(index);
744
745 // Compute zenith angle of pixel in COMPTEL coordinates
746 double theta = oad.theta(sky);
747
748 // Initialise exposure
749 double exposure = 0.0;
750
751 // Skip pixel if zenith angle is beyond 90 degrees
752 if (theta >= 90.0) {
753 continue;
754 }
755
756 // ... otherwise compute the exposure
757 else {
758 double costheta = std::cos(theta * gammalib::deg2rad);
759 if (theta < 89.0) {
760 exposure = d1_area * costheta *
761 (1.0 - std::exp(-tau / costheta)) /
762 (1.0 - std::exp(-tau));
763 }
764 else {
765 exposure = d1_area * costheta / (1.0 - std::exp(-tau));
766 }
767 }
768
769 // Accumulate exposure
770 (*this)[index] += exposure;
771
772 } // endfor: looped over all DRX pixels
773
774 } // endfor: looped over Orbit Aspect Data
775
776 // Multiply by time per superpacket to give the result in cm^2 s
777 for (int i = 0; i < size(); ++i) {
778 (*this)[i] *= superpacket_duration;
779 }
780
781 // Clear energy boundaries for DRX since DRX does not depend on energy)
783
784 // Set the Good Time interval for DRX
785 if (m_num_used_superpackets > 0) {
787 }
788
789 // Debug
790 #if defined(G_DEBUG_COMPUTE_DRX)
791 std::cout << "Total number of superpackets .: " << m_num_superpackets << std::endl;
792 std::cout << "Used superpackets ............: " << m_num_used_superpackets << std::endl;
793 std::cout << "Skipped superpackets .........: " << m_num_skipped_superpackets << std::endl;
794 #endif
795
796 // Return
797 return;
798}
799
800
801/***********************************************************************//**
802 * @brief Compute DRM model
803 *
804 * @param[in] obs COMPTEL observation.
805 * @param[in] model Model.
806 *
807 * Compute DRM model cube for a COMPTEL observation.
808 ***************************************************************************/
810 const GModel& model)
811{
812 // Evaluate model
813 GVector values = model.eval(obs);
814
815 // Get number of Chi/Psi pixels
816 int npix = nchi() * npsi();
817
818 // Fill DRM with model values
819 for (int iphibar = 0, i = 0; iphibar < nphibar(); ++iphibar) {
820 for (int ipix = 0; ipix < npix; ++ipix, ++i) {
821 m_dri(ipix, iphibar) = values[i];
822 }
823 }
824
825 // Return
826 return;
827}
828
829
830/***********************************************************************//**
831 * @brief Compute content in cone
832 *
833 * @param[in] dir Sky direction of cone apex.
834 * @param[in] armmin Minimum Angular Resolution Measure (deg).
835 * @param[in] armmax Maximum Angular Resolution Measure (deg).
836 * @return Content in cone.
837 *
838 * Compute the sum of the DRI bins within an event cone with apex at a given
839 * sky direction. All bins with an Angular Resolution Measure comprised
840 * between @p armmin (inclusive) and @p armmax (exclusive) will be
841 * considered. The bin centres will be used for the computation of the
842 * Angular Resolution Measure. The Angular Resolution Measure is defined as
843 * phibar - phigeo.
844 ***************************************************************************/
846 const double& armmin,
847 const double& armmax) const
848{
849 // Initialise content
850 double content = 0.0;
851
852 // Create Phigeo map in degrees
853 GSkyMap phigeo = m_dri.extract(0);
854 for (int i = 0; i < phigeo.npix(); ++i) {
855 phigeo(i) = dir.dist_deg(phigeo.inx2dir(i));
856 }
857
858 // Loop over phibar layers
859 for (int iphibar = 0; iphibar < this->nphibar(); ++iphibar) {
860
861 // Compute phibar
862 double phibar = this->phimin() + (iphibar+0.5) * this->phibin();
863
864 // Compute index offset
865 int offset = iphibar * phigeo.npix();
866
867 // Loop over bins in phibar layer
868 for (int i = 0; i < phigeo.npix(); ++i) {
869
870 // Compute ARM
871 double arm = phibar - phigeo(i);
872
873 // If ARM is within specified interval then add bin content
874 if (arm >= armmin && arm < armmax) {
875 content += (*this)[i + offset];
876 }
877
878 } // endfor: looped over bins in phibar layers
879
880 } // endfor: looped over phibar layers
881
882 // Return content
883 return content;
884}
885
886
887/***********************************************************************//**
888 * @brief Load COMPTEL Data Space from DRI FITS file
889 *
890 * @param[in] filename DRI FITS file name.
891 ***************************************************************************/
892void GCOMDri::load(const GFilename& filename)
893{
894 // Open FITS file
895 GFits fits(filename);
896
897 // Get HDU (pointer is always valid)
898 const GFitsImage& hdu = *fits.image(0);
899
900 // Read DRI file
901 read(hdu);
902
903 // If FITS file contains binary table then copy table into member
904 for (int i = 0; i < fits.size(); ++i) {
905 const GFitsBinTable* table = dynamic_cast<const GFitsBinTable*>(fits[i]);
906 if (table != NULL) {
907 m_drw_table = *table;
908 break;
909 }
910 }
911
912 // Close FITS file
913 fits.close();
914
915 // Return
916 return;
917}
918
919
920/***********************************************************************//**
921 * @brief Save COMPTEL Data Space into DRI FITS file
922 *
923 * @param[in] filename DRI FITS file name.
924 * @param[in] clobber Overwrite existing file?
925 ***************************************************************************/
926void GCOMDri::save(const GFilename& filename, const bool& clobber) const
927{
928 // Create FITS file
929 GFits fits;
930
931 // Write data space into FITS file
932 write(fits, filename.extname(gammalib::extname_dri));
933
934 // If DRI contains filled DRW binary table then append table to FITS file
935 if (m_drw_table.nrows() > 0) {
936 fits.append(m_drw_table);
937 }
938
939 // Save FITS file
940 fits.saveto(filename, clobber);
941
942 // Close FITS file
943 fits.close();
944
945 // Return
946 return;
947}
948
949
950/***********************************************************************//**
951 * @brief Read COMPTEL Data Space from DRI FITS image
952 *
953 * @param[in] image DRI FITS image.
954 ***************************************************************************/
955void GCOMDri::read(const GFitsImage& image)
956{
957 // Clear
958 clear();
959
960 // Read sky map
961 m_dri.read(image);
962
963 // Correct WCS projection (HEASARC data format kluge)
965
966 // Read attributes
967 read_attributes(&image);
968
969 // Return
970 return;
971}
972
973
974/***********************************************************************//**
975 * @brief Write COMPTEL Data Space into FITS image
976 *
977 * @param[in] fits FITS file.
978 * @param[in] extname Extension name.
979 ***************************************************************************/
980void GCOMDri::write(GFits& fits, const std::string& extname) const
981{
982 // Write sky map into FITS file
983 GFitsHDU *image = m_dri.write(fits, extname);
984
985 // Write DRI attributes
986 if (image != NULL) {
987 write_attributes(image);
988 }
989
990 // Return
991 return;
992}
993
994
995/***********************************************************************//**
996 * @brief Print COMPTEL Data Space
997 *
998 * @param[in] chatter Chattiness.
999 * @return String containing COMPTEL Data Space information.
1000 ***************************************************************************/
1001std::string GCOMDri::print(const GChatter& chatter) const
1002{
1003 // Initialise result string
1004 std::string result;
1005
1006 // Continue only if chatter is not silent
1007 if (chatter != SILENT) {
1008
1009 // Compute scatter angle dimensions
1010 double chimin = 0.0;
1011 double chimax = 0.0;
1012 double chibin = 0.0;
1013 double psimin = 0.0;
1014 double psimax = 0.0;
1015 double psibin = 0.0;
1016 const GWcs* wcs = dynamic_cast<const GWcs*>(m_dri.projection());
1017 if (wcs != NULL) {
1018 chibin = wcs->cdelt(0);
1019 chimin = wcs->crval(0) - (wcs->crpix(0)-0.5) * chibin;
1020 chimax = chimin + m_dri.nx() * chibin;
1021 psibin = wcs->cdelt(1);
1022 psimin = wcs->crval(1) - (wcs->crpix(1)-0.5) * psibin;
1023 psimax = psimin + m_dri.ny() * psibin;
1024 }
1025
1026 // Compute Phibar maximum
1027 double phimax = m_phimin + m_dri.nmaps() * m_phibin;
1028
1029 // Append header
1030 result.append("=== GCOMDri ===");
1031
1032 // Append Phibar information
1033 result.append("\n"+gammalib::parformat("Chi range"));
1034 result.append(gammalib::str(chimin)+" - ");
1035 result.append(gammalib::str(chimax)+" deg");
1036 result.append("\n"+gammalib::parformat("Chi bin size"));
1037 result.append(gammalib::str(chibin)+" deg");
1038 result.append("\n"+gammalib::parformat("Psi range"));
1039 result.append(gammalib::str(psimin)+" - ");
1040 result.append(gammalib::str(psimax)+" deg");
1041 result.append("\n"+gammalib::parformat("Psi bin size"));
1042 result.append(gammalib::str(psibin)+" deg");
1043 result.append("\n"+gammalib::parformat("Phibar range"));
1044 result.append(gammalib::str(m_phimin)+" - ");
1045 result.append(gammalib::str(phimax)+" deg");
1046 result.append("\n"+gammalib::parformat("Phibar bin size"));
1047 result.append(gammalib::str(m_phibin)+" deg");
1048 if (m_tofcor > 1.0) {
1049 result.append("\n"+gammalib::parformat("ToF correction"));
1050 result.append(gammalib::str(m_tofcor));
1051 }
1052
1053 // Append energy boundaries
1054 result.append("\n"+m_ebounds.print(gammalib::reduce(chatter)));
1055
1056 // Append GTI
1057 result.append("\n"+m_gti.print(gammalib::reduce(chatter)));
1058
1059 // EXPLICIT: Append sky map
1060 if (chatter >= EXPLICIT) {
1061 result.append("\n"+m_dri.print(gammalib::reduce(chatter)));
1062 }
1063
1064 // Append computation statistics
1065 result.append("\n"+gammalib::parformat("Input superpackets"));
1066 result.append(gammalib::str(m_num_superpackets));
1067 result.append("\n"+gammalib::parformat("Used superpackets"));
1068 result.append(gammalib::str(m_num_used_superpackets));
1069 result.append("\n"+gammalib::parformat("Skipped superpackets"));
1071
1072 // Append selection
1073 if (m_has_selection) {
1074 result.append("\n"+m_selection.print(gammalib::reduce(chatter)));
1075 }
1076
1077 } // endif: chatter was not silent
1078
1079 // Return result
1080 return result;
1081}
1082
1083
1084/*==========================================================================
1085 = =
1086 = Private methods =
1087 = =
1088 ==========================================================================*/
1089
1090/***********************************************************************//**
1091 * @brief Initialise class members
1092 ***************************************************************************/
1094{
1095 // Initialise members
1096 m_name.clear();
1097 m_dri.clear();
1098 m_ebounds.clear();
1099 m_gti.clear();
1100 m_phimin = 0.0;
1101 m_phibin = 0.0;
1102 m_tofcor = 1.0;
1103 m_phasecor = 1.0;
1104
1105 // Initialise statistics
1107
1108 // Initialise optional DRW members
1109 m_drw_method.clear();
1111 m_drw_status.clear();
1112 m_drw_fprompt = 0.0;
1113 m_drw_e_fprompt = 0.0;
1114 m_drw_iter = 0;
1115
1116 // Initialise selection parameters
1117 m_has_selection = false;
1119 m_zetamin = -90.0; // Signals no selection
1120
1121 // Return
1122 return;
1123}
1124
1125
1126/***********************************************************************//**
1127 * @brief Copy class members
1128 *
1129 * @param[in] dri COMPTEL Data Space.
1130 ***************************************************************************/
1132{
1133 // Copy members
1134 m_name = dri.m_name;
1135 m_dri = dri.m_dri;
1136 m_ebounds = dri.m_ebounds;
1137 m_gti = dri.m_gti;
1138 m_phimin = dri.m_phimin;
1139 m_phibin = dri.m_phibin;
1140 m_tofcor = dri.m_tofcor;
1141 m_phasecor = dri.m_phasecor;
1142
1143 // Copy statistics
1144 m_tstart = dri.m_tstart;
1145 m_tstop = dri.m_tstop;
1149
1150 // Copy optional DRW members
1156 m_drw_iter = dri.m_drw_iter;
1157
1158 // Copy selection parameters
1161 m_zetamin = dri.m_zetamin;
1162
1163 // Return
1164 return;
1165}
1166
1167
1168/***********************************************************************//**
1169 * @brief Delete class members
1170 ***************************************************************************/
1172{
1173 // Return
1174 return;
1175}
1176
1177
1178/***********************************************************************//**
1179 * @brief Initialise DRI cube
1180 *
1181 * Sets all DRI cube bins to zero.
1182 ***************************************************************************/
1184{
1185 // Set all cube bins to zero
1186 for (int i = 0; i < size(); ++i) {
1187 (*this)[i] = 0.0;
1188 }
1189
1190 // Return
1191 return;
1192}
1193
1194
1195/***********************************************************************//**
1196 * @brief Initialise computation statistics
1197 ***************************************************************************/
1199{
1200 // Initialise statistics
1201 m_tstart.clear();
1202 m_tstop.clear();
1206
1207 // Return
1208 return;
1209}
1210
1211
1212/***********************************************************************//**
1213 * @brief Check if superpacket should be used
1214 *
1215 * @param[in] oad Orbit Aspect Data record (i.e. superpacket).
1216 * @param[in] tim Good Time Intervals.
1217 * @param[in] select Selection set.
1218 * @return True if superpacket should be used, false otherwise.
1219 *
1220 * Checks if a superpacket should be used. A superpacket will be used if
1221 * it is fully enclosed within the COMPTEL Good Time Intervals and the
1222 * Good Time Intervals of the DRI dataset. In case that orbital phases are
1223 * present in the selection set, the superpacket will be used when the start
1224 * time is comprised in one of the orbital phases.
1225 *
1226 * The method updates the superpacket statistics and selected time interval.
1227 ***************************************************************************/
1229 const GCOMTim& tim,
1230 const GCOMSelection& select)
1231{
1232 // Initialise usage flag
1233 bool use = true;
1234
1235 // Increment superpacket counter
1237
1238 // Skip superpacket if it is not fully enclosed within the COMPTEL
1239 // Good Time Intervals
1240 if (!(tim.contains(oad.tstart()) && tim.contains(oad.tstop()))) {
1242 use = false;
1243 }
1244
1245 // Skip superpacket if it is not fully enclosed within the DRI Good
1246 // Time Intervals. Only check if there are Good Time Intervals in the
1247 // DRI.
1248 else if ((m_gti.size() > 0) &&
1249 !(m_gti.contains(oad.tstart()) && m_gti.contains(oad.tstop()))) {
1251 use = false;
1252 }
1253
1254 // If there are phase intervals then skip if superpacket is the phase
1255 // corresponding to the start time does not fall into any of the phase
1256 // intervals
1257 else if (!select.orbital_phases().is_empty()) {
1258 double phase = select.orbital_phase(oad.tstart());
1259 if (select.orbital_phases().contains(phase)) {
1261 }
1262 else {
1264 use = false;
1265 }
1266 }
1267
1268 // ... otherwise use superpacket
1269 else {
1271 }
1272
1273 // Update selection validity interval
1274 if (m_num_used_superpackets == 1) {
1275 m_tstart = oad.tstart();
1276 m_tstop = oad.tstop();
1277 }
1278 else {
1279 m_tstop = oad.tstop();
1280 }
1281
1282 // Return usage
1283 return use;
1284}
1285
1286
1287/***********************************************************************//**
1288 * @brief Read DRI attributes from FITS HDU
1289 *
1290 * @param[in] hdu FITS HDU pointer.
1291 *
1292 * Reads the time interval from the FITS header and sets the Phibar definiton
1293 * and energy boundaries from the header keywords if they are provided.
1294 ***************************************************************************/
1296{
1297 // Get time attributes
1298 GTime tstart = gammalib::com_time(hdu->integer("VISDAY"), hdu->integer("VISTIM"));
1299 GTime tstop = gammalib::com_time(hdu->integer("VIEDAY"), hdu->integer("VIETIM"));
1300
1301 // Set Good Time Intervals
1302 if (tstop > tstart) {
1303 m_gti = GGti(tstart, tstop);
1304 }
1305
1306 // Optionally read Phibar attributes
1307 if (hdu->has_card("CDELT3") &&
1308 hdu->has_card("CRVAL3") &&
1309 hdu->has_card("CRPIX3")) {
1310
1311 // Get phibar attributes
1312 m_phibin = hdu->real("CDELT3");
1313 m_phimin = hdu->real("CRVAL3") - (hdu->real("CRPIX3")-0.5) * m_phibin;
1314
1315 }
1316
1317 // ... otherwise set Phibar attributes to zero
1318 else {
1319 m_phimin = 0.0;
1320 m_phibin = 0.0;
1321 }
1322
1323 // Optionally read energy attributes
1324 if (hdu->has_card("E_MIN") && hdu->has_card("E_MAX")) {
1325
1326 // Get energy attributes
1327 GEnergy emin(hdu->real("E_MIN"), "MeV");
1328 GEnergy emax(hdu->real("E_MAX"), "MeV");
1329
1330 // Set energy boundaries
1331 m_ebounds = GEbounds(emin, emax);
1332
1333 }
1334
1335 // ... otherwise clear energy boundaries
1336 else {
1337 m_ebounds.clear();
1338 }
1339
1340 // Read selection set
1341 m_selection.read(*hdu);
1342
1343 // Signal if selected set keywords were present. For simplicity we just
1344 // search for the first keyword
1345 if (hdu->has_card("D1EMIN")) {
1346 m_has_selection = true;
1347 }
1348
1349 // Optionally read Earth horizon cut
1350 if (hdu->has_card("EHAMIN")) {
1351 m_zetamin = hdu->real("EHAMIN");
1352 }
1353
1354 // Optionally read ToF correction
1355 if (hdu->has_card("TOFCOR")) {
1356 m_tofcor = hdu->real("TOFCOR");
1357 }
1358
1359 // Optionally read pulsar phase correction
1360 if (hdu->has_card("PHASECOR")) {
1361 m_phasecor = hdu->real("PHASECOR");
1362 }
1363
1364 // Optionally read superpacket statistics
1365 if (hdu->has_card("NSPINP")) {
1366 m_num_superpackets = hdu->integer("NSPINP");
1367 }
1368 if (hdu->has_card("NSPUSE")) {
1369 m_num_used_superpackets = hdu->integer("NSPUSE");
1370 }
1371 if (hdu->has_card("NSPSKP")) {
1372 m_num_skipped_superpackets = hdu->integer("NSPSKP");
1373 }
1374
1375 // Return
1376 return;
1377}
1378
1379
1380/***********************************************************************//**
1381 * @brief Write DRI attributes into FITS HDU
1382 *
1383 * @param[in] hdu FITS HDU pointer.
1384 ***************************************************************************/
1386{
1387 // Write 3rd dimension keywords in case that a third dimension exists.
1388 // This avoids writing a Phibar layer for DRX.
1389 if (m_phibin > 0.0) {
1390
1391 // Set Phibar keywords
1392 double crval3 = m_phimin + 0.5 * m_phibin;
1393
1394 // Write Phibar keywords
1395 hdu->card("CTYPE3", "Phibar", "Compton scatter angle");
1396 hdu->card("CRPIX3", 1.0, "Pixel coordinate of reference point (starting from 1)");
1397 hdu->card("CRVAL3", crval3, "[deg] Coordinate value at reference point");
1398 hdu->card("CDELT3", m_phibin, "[deg] Coordinate increment at reference point");
1399
1400 } // endif: DRI was 3D
1401
1402 // Write OGIP time keywords
1403 m_gti.reference().write(*hdu);
1404 hdu->card("TSTART", m_gti.tstart().secs(), "[s] Start time");
1405 hdu->card("TSTOP", m_gti.tstop().secs(), "[s] Stop time");
1406 hdu->card("DATE-OBS", m_gti.tstart().utc(), "Start of observation in UTC");
1407 hdu->card("DATE-END", m_gti.tstop().utc(), "Stop of observation in UTC");
1408
1409 // Set time keywords
1410 int visday = gammalib::com_tjd(m_gti.tstart());
1411 int vistim = gammalib::com_tics(m_gti.tstart());
1412 int vieday = gammalib::com_tjd(m_gti.tstop());
1413 int vietim = gammalib::com_tics(m_gti.tstop());
1414
1415 // Write COMPTEL time keywords
1416 hdu->card("VISDAY", visday, "[TJD] Data validity interval start day");
1417 hdu->card("VISTIM", vistim, "[tics] Data validity interval start time");
1418 hdu->card("VIEDAY", vieday, "[TJD] Data validity interval end day");
1419 hdu->card("VIETIM", vietim, "[tics] Data validity interval end time");
1420
1421 // If there are energy boundaries then write them
1422 if (m_ebounds.size() > 0) {
1423 hdu->card("E_MIN", m_ebounds.emin().MeV(), "[MeV] Lower bound of energy range");
1424 hdu->card("E_MAX", m_ebounds.emax().MeV(), "[MeV] Upper bound of energy range");
1425 }
1426
1427 // If there was an event seletion then write selection set. Otherwise write
1428 // handling D1 and D2 module usage and handling mode of D2 PMT failures.
1429 if (m_has_selection) {
1430 m_selection.write(*hdu);
1431 }
1432 else {
1433
1434 // Write D2 PMT failure handling flag
1435 hdu->card("D2FPMT", m_selection.fpmtflag(), "D2 PMT failure handling");
1436
1437 // Write D1 module usage
1438 std::string d1use = "0000000";
1439 for (int i = 0; i < 7; ++i) {
1440 if (m_selection.use_d1(i)) {
1441 d1use[i] = '1';
1442 }
1443 }
1444 hdu->card("D1USE", d1use, "D1 module usage");
1445
1446 // Write D2 module usage
1447 std::string d2use = "00000000000000";
1448 for (int i = 0; i < 14; ++i) {
1449 if (m_selection.use_d2(i)) {
1450 d2use[i] = '1';
1451 }
1452 }
1453 hdu->card("D2USE", d2use, "D2 module usage");
1454
1455 }
1456
1457 // If there was a valid Earth horizon cut then write it
1458 if (m_zetamin != -90.0) {
1459 hdu->card("EHAMIN", m_zetamin, "[deg] Minimum Earth horizon - Phibar cut");
1460 }
1461
1462 // If there is a ToF correction then write it
1463 if (m_tofcor > 1.0) {
1464 hdu->card("TOFCOR", m_tofcor, "ToF correction");
1465 }
1466
1467 // If there is a pulsar phase correction then write it
1468 if (m_phasecor < 1.0) {
1469 hdu->card("PHASECOR", m_phasecor, "Pulsar phase correction");
1470 }
1471
1472 // Write superpacket statistics
1473 hdu->card("NSPINP", m_num_superpackets, "Number of input superpackets");
1474 hdu->card("NSPUSE", m_num_used_superpackets, "Number of used superpackets");
1475 hdu->card("NSPSKP", m_num_skipped_superpackets, "Number of skipped superpackets");
1476
1477 // Write optional DRW parameters
1478 if (!m_drw_method.empty()) {
1479 hdu->card("DRWMETHO", m_drw_method, "DRW computation method");
1480 if (m_drw_iter > 0) {
1481 hdu->card("DRWFITST", m_drw_status, "DRW f_prompt fit status");
1482 hdu->card("DRWFITIT", m_drw_iter, "DRW f_prompt fit iterations");
1483 hdu->card("DRWFP", m_drw_fprompt, "DRW f_prompt value");
1484 hdu->card("DRWEFP", m_drw_e_fprompt, "DRW f_prompt value error");
1485 }
1486 }
1487
1488 // Return
1489 return;
1490}
1491
1492
1493/***********************************************************************//**
1494 * @brief Compute DRG geometry factor
1495 *
1496 * @param[in] tjd TJD for module status
1497 * @param[in] theta Zenith angle in COMPTEL coordinates (deg).
1498 * @param[in] phi Azimuth angle in COMPTEL coordinates (deg).
1499 * @param[in] select Selection set.
1500 * @param[in] status D1 and D2 module status
1501 * @return Geometry factor.
1502 *
1503 * Computes the DRG geometry factor as function of zenith and azimuth angles
1504 * given in the COMPTEL coordinate system.
1505 ***************************************************************************/
1506double GCOMDri::compute_geometry(const int& tjd,
1507 const double& theta,
1508 const double& phi,
1509 const GCOMSelection& select,
1510 const GCOMStatus& status) const
1511{
1512 // Set D1 module positions (from COM-RP-MPE-M10-123, Issue 1, Page 3-3)
1513 const double xd1[] = {0.0,-42.3,-26.0,26.0, 42.3,26.0,-26.0};
1514 const double yd1[] = {0.0, 0.0, 39.1,39.1, 0.0,-39.1,-39.1};
1515
1516 // Set D2 module positions (from COM-RP-MPE-M10-123, Issue 1, Page 4-4)
1517 const double xd2[] = { 30.2, 0.0, -30.2, 45.3, 15.1, -15.1, -45.3,
1518 45.3, 15.1, -15.1, -45.3, 30.2, 0.0, -30.2};
1519 const double yd2[] = {-41.254,-41.254,-41.254,-15.1, -15.1, -15.1, -15.1,
1520 15.1, 15.1, 15.1 , 15.1, 41.254,41.254,41.254};
1521
1522 // Set distance between D1 and D2 levels in cm (from COM-SP-MPE-M10-123,
1523 // Issue 1, page 8-5
1524 const double delz = 158.0;
1525
1526 // Set D1 module radius in cm (from COM-TN-UNH-F70-051)
1527 //const double r1 = 13.8; // Defined globally
1528
1529 // Set D2 module radius in cm (from SIM-AL-005)
1530 const double r2 = 14.085;
1531
1532 // Derive some constants
1533 //const double r1sq = r1 * r1; // Defined globally
1534 const double r2sq = r2 * r2;
1535 const double drsq = r1sq - r2sq;
1536 const double norm_geo = 1.0 / (gammalib::pi * r1sq);
1537
1538 // Initialise geometry factor
1539 double geometry = 0.0;
1540
1541 // Precompute results
1542 double theta_rad = theta * gammalib::deg2rad;
1543 double phi_rad = phi * gammalib::deg2rad;
1544 double cosphi = std::cos(phi_rad);
1545 double sinphi = std::sin(phi_rad);
1546 double tantheta = std::tan(theta_rad);
1547
1548 // Loop over all D1 modules
1549 for (int id1 = 0; id1 < 7; ++id1) {
1550
1551 // Skip D1 module if it's off
1552 if (status.d1status(tjd, id1+1) != 1) {
1553 continue;
1554 }
1555
1556 // Compute coordinates of D1 projected on D2 plane
1557 double xd1_prj = xd1[id1] - delz * tantheta * cosphi;
1558 double yd1_prj = yd1[id1] - delz * tantheta * sinphi;
1559
1560 // Loop over all D2 modules
1561 for (int id2 = 0; id2 < 14; ++id2) {
1562
1563 // Skip if coresponding modules should not be used
1564 if (!select.use_d1(id1) || !select.use_d2(id2)) {
1565 continue;
1566 }
1567
1568 // Get D2 module status
1569 int d2status = status.d2status(tjd, id2+1);
1570
1571 // Skip D2 module if it's off or if module has failed PMT and
1572 // should be excluded
1573 if ((d2status < 1) || ((d2status > 1) && (select.fpmtflag() == 0))) {
1574 continue;
1575 }
1576
1577 // Compute distance between center of D2 and projected centre
1578 // of D1
1579 double dx = xd2[id2] - xd1_prj;
1580 double dy = yd2[id2] - yd1_prj;
1581 double dsq = dx * dx + dy * dy;
1582 double d = std::sqrt(dsq);
1583
1584 // If there is no overlap then skip the module
1585 if (d >= r1 + r2) {
1586 continue;
1587 }
1588
1589 // If D2 modules has failed PMT, the failed PMT zone should be
1590 // excluded and the module has an exclusion radius then compute
1591 // now the overlap of the failure zone; if the module has no
1592 // exclusion radius then exclude the entire module.
1593 double overlap = 0.0;
1594 if ((d2status > 1) && (select.fpmtflag() == 2)) {
1595 double r = gammalib::com_exd2r(id2+1);
1596 if (r >= 0.1) {
1597 overlap = compute_overlap(xd1_prj, yd1_prj, r1,
1598 xd2[id2], yd2[id2], r2,
1599 gammalib::com_exd2x(id2+1),
1600 gammalib::com_exd2y(id2+1),
1601 r);
1602 }
1603 else {
1604 continue;
1605 }
1606 } // endif: handled D2 modules with failed PMTs
1607
1608 // If there is total overlap (within 0.1 cm) then add 1-overlap
1609 // to the geometry factor
1610 if (d <= r2 - r1 + 0.1) {
1611 double gmt = (1.0 > overlap) ? 1.0 - overlap : 0.0;
1612 geometry += gmt;
1613 }
1614
1615 // ... otherwise if there is a partial overlap then compute the
1616 // semiangle subtended by overlap sector of D2 and projected
1617 // D1 module
1618 else {
1619
1620 // Cosine beta
1621 double d2 = 2.0 * d;
1622 double cbeta1 = (dsq + drsq) / (d2 * r1);
1623 double cbeta2 = (dsq - drsq) / (d2 * r2);
1624
1625 // Sin beta
1626 double sbeta1 = std::sqrt(1.0 - cbeta1 * cbeta1);
1627 double sbeta2 = std::sqrt(1.0 - cbeta2 * cbeta2);
1628
1629 // Beta
1630 double beta1 = std::acos(cbeta1);
1631 double beta2 = std::acos(cbeta2);
1632
1633 // Projection
1634 double gmt = (r1sq * (beta1 - sbeta1 * cbeta1) +
1635 r2sq * (beta2 - sbeta2 * cbeta2)) * norm_geo -
1636 overlap;
1637 if (gmt < 0.0) {
1638 gmt = 0.0;
1639 }
1640 geometry += gmt;
1641
1642 } // endelse: there was partial overlap
1643
1644 } // endfor: looped over D2 modules
1645
1646 } // endfor: looped over D1 modules
1647
1648 // Now divide by 7 since we want the probability of hitting a given
1649 // D1 module
1650 geometry /= 7.0;
1651
1652 // Return geometry factor
1653 return geometry;
1654}
1655
1656
1657/***********************************************************************//**
1658 * @brief Compute surface of overlap between two circles
1659 *
1660 * @param[in] x1 X position of D2 module (cm).
1661 * @param[in] y1 Y position of D2 module (cm).
1662 * @param[in] r1 Radius D2 module (cm).
1663 * @param[in] x2 X position of dead PMT (cm).
1664 * @param[in] y2 Y position of dead PMT (cm).
1665 * @param[in] r2 Radius of dead PMT (cm).
1666 * @return Surface of overlap (cm^2)
1667 *
1668 * Computes the surface of overlap in cm^2 between two circles, composed of
1669 * D2 module and failed PMT exclusion circle.
1670 *
1671 * The method is a reimplementation of the COMPASS SKYDRS17.COM2 function.
1672 ***************************************************************************/
1673double GCOMDri::compute_surface(const double& x1, const double& y1, const double& r1,
1674 const double& x2, const double& y2, const double& r2) const
1675{
1676 // Initialise surface
1677 double surface = 0.0;
1678
1679 // Compute distance between center of D2 and failed PMT exclusion circle
1680 double dx = x1 - x2;
1681 double dy = y1 - y2;
1682 double dsq = dx * dx + dy * dy;
1683 double d = std::sqrt(dsq);
1684
1685 // If failed PMT exclusion circle is fully comprised within D2 then use
1686 // failed PMT exclusion circle surface as overlap
1687 if (r1 > (d+r2)) {
1688 surface = gammalib::pi * r2 * r2;
1689 }
1690
1691 // ... otherwise, if D2 module is fully comprised in failed PMT exclusion
1692 // circle then use D2 module surface as overlap. This case is only relevant
1693 // if the failed PMTs exclusion circle is larger than the D2 modules.
1694 else if (r2 > (d+r1)) {
1695 surface = gammalib::pi * r1 * r1;
1696 }
1697
1698 // ... otherwise if D2 module and failed PMT exclusion circle overlap then
1699 // compute the area of overlap
1700 else if (d < (r1+r2)) {
1701
1702 // Cosine beta
1703 double d2 = 2.0 * d;
1704 double r1sq = r1 * r1;
1705 double r2sq = r2 * r2;
1706 double cbeta1 = (r1sq - r2sq + dsq) / (d2 * r1);
1707 double cbeta2 = (r2sq - r1sq + dsq) / (d2 * r2);
1708
1709 // Sin beta
1710 double sbeta1 = std::sqrt(1.0 - cbeta1 * cbeta1);
1711 double sbeta2 = std::sqrt(1.0 - cbeta2 * cbeta2);
1712
1713 // Beta
1714 double beta1 = std::acos(cbeta1);
1715 double beta2 = std::acos(cbeta2);
1716
1717 // Compute surface
1718 surface = r1sq * (beta1 - sbeta1 * cbeta1) +
1719 r2sq * (beta2 - sbeta2 * cbeta2);
1720
1721 }
1722
1723 // Return
1724 return surface;
1725}
1726
1727
1728/***********************************************************************//**
1729 * @brief Compute overlap between three circles
1730 *
1731 * @param[in] x1 X position of D1 projection (cm).
1732 * @param[in] y1 Y position of D1 projection (cm).
1733 * @param[in] r1 Radius D1 module (cm).
1734 * @param[in] x2 X position of D2 module (cm).
1735 * @param[in] y2 Y position of D2 module (cm).
1736 * @param[in] r2 Radius D2 module (cm).
1737 * @param[in] x3 X position of dead PMT (cm).
1738 * @param[in] y3 Y position of dead PMT (cm).
1739 * @param[in] r3 Radius of dead PMT (cm).
1740 * @return Fractional overlap [0.0,...,1.0]
1741 *
1742 * Compute fractional overlap between three circles, composed of projected
1743 * D1 module, D2 module and failed PMT exclusion circle.
1744 *
1745 * The method is a reimplementation of the COMPASS SKYDRS17.OVERLP function.
1746 ***************************************************************************/
1747double GCOMDri::compute_overlap(const double& x1, const double& y1, const double& r1,
1748 const double& x2, const double& y2, const double& r2,
1749 const double& x3, const double& y3, const double& r3) const
1750{
1751 // Initialise constants
1752 const int steps = 25;
1753 const int size = steps*steps;
1754 static double o23_x[size];
1755 static double o23_y[size];
1756 static double last_x2 = 1.0e25;
1757 static double last_y2 = 1.0e25;
1758 static double last_x3 = 1.0e25;
1759 static double last_y3 = 1.0e25;
1760 static int no23 = 0;
1761
1762 // Initialise overlap
1763 double overlap = 0.0;
1764
1765 // Create single-pass loop so that method has a single exit point
1766 do {
1767
1768 // If there is no overlap between D1 module projection and D2 module
1769 // then return zero overlap
1770 double dx12 = x1 - x2;
1771 double dy12 = y1 - y2;
1772 double d12 = std::sqrt(dx12*dx12 + dy12*dy12);
1773 if (d12 > (r1+r2)) {
1774 continue;
1775 }
1776
1777 // If there is no overlap between D1 module and failed PMT exclusion
1778 // circle then return zero overlap
1779 double dx13 = x1 - x3;
1780 double dy13 = y1 - y3;
1781 double d13 = std::sqrt(dx13*dx13 + dy13*dy13);
1782 if (d13 > (r1+r3)) {
1783 continue;
1784 }
1785
1786 // If PMT exclusion circle is contained within D1 module projection
1787 // then the overlap is the overlap between D2 module and PMT
1788 // exclusion circle
1789 if (d13+r3 < r1) {
1790 overlap = compute_surface(x2, y2, r2, x3, y3, r3);
1791 continue;
1792 }
1793
1794 // Start integration over the smallest circle which is the PMT
1795 // exclusion circle. Since the D2 module circle and the PMT
1796 // exclusion circle do not change position too often, their overlap
1797 // will be kept in a table. Then only the changing position of the
1798 // D1 projection needs to be taken care of in the seperate calls
1799 // to the routine.
1800 double step = 2.0 * r3 / double(steps-3);
1801 double stepsq = step * step;
1802 double r1sq = r1 * r1;
1803 if ((last_x2 != x2) || (last_y2 != y2) || (last_x3 != x3) || (last_y3 != y3)) {
1804
1805 // Store positions
1806 last_x2 = x2;
1807 last_y2 = y2;
1808 last_x3 = x3;
1809 last_y3 = y3;
1810
1811 // Compute arrays o23_x and o23_y which hold all (x,y) positions
1812 // that overlap with the D2 module and the PMT exclusion circle
1813 double r2sq = r2 * r2;
1814 double r3sq = r3 * r3;
1815 no23 = 0;
1816 double yy = y3 - r3 - step;
1817 for (int i = 0; i < steps; ++i, yy += step) {
1818 double xx = x3 - r3 - step;
1819 for (int j = 0; j < steps; ++j, xx += step) {
1820 double dx3 = xx - x3;
1821 double dy3 = yy - y3;
1822 if (dx3*dx3 + dy3*dy3 < r3sq) {
1823 double dx2 = xx - x2;
1824 double dy2 = yy - y2;
1825 if (dx2*dx2 + dy2*dy2 < r2sq) {
1826 o23_x[no23] = xx;
1827 o23_y[no23] = yy;
1828 no23++;
1829 }
1830 }
1831 }
1832 }
1833
1834 } // endif: update required
1835
1836 // Now compute overlap by checking all (x,y) positions that overlap
1837 // with the D2 module and the PMT exclusion circle
1838 for (int i = 0; i < no23; ++i) {
1839 double dx1 = o23_x[i] - x1;
1840 double dy1 = o23_y[i] - y1;
1841 if (dx1*dx1 + dy1*dy1 < r1sq) {
1842 overlap += stepsq;
1843 }
1844 }
1845
1846 } while(false);
1847
1848 // Finally divide by the D1 module area to get the fractional overlap
1849 if (overlap > 0.0) {
1850 overlap /= (gammalib::pi * r1sq);
1851 }
1852
1853 // Return
1854 return overlap;
1855}
1856
1857
1858/***********************************************************************//**
1859 * @brief Compute ToF correction
1860 *
1861 * Compute the ToF correction according to COM-RP-ROL-DRG-057.
1862 ***************************************************************************/
1864{
1865 // ToF correction factors according to Table 1 of COM-RP-ROL-DRG-057
1866 const double tofcoreng[] = {0.8660, 1.7321, 5.4772, 17.3205};
1867 const double tofcor110[] = {1.14, 1.07, 1.02, 1.01};
1868 const double tofcor111[] = {1.17, 1.09, 1.03, 1.01};
1869 const double tofcor112[] = {1.21, 1.11, 1.05, 1.02};
1870 const double tofcor113[] = {1.26, 1.15, 1.07, 1.04};
1871 const double tofcor114[] = {1.32, 1.20, 1.11, 1.06};
1872 const double tofcor115[] = {1.40, 1.27, 1.17, 1.11};
1873 const double tofcor116[] = {1.50, 1.36, 1.24, 1.17};
1874 const double tofcor117[] = {1.63, 1.47, 1.35, 1.28};
1875 const double tofcor118[] = {1.79, 1.63, 1.51, 1.43};
1876 const double tofcor119[] = {2.01, 1.85, 1.73, 1.67};
1877 const double* tofcor[] = {tofcor110, tofcor111, tofcor112,
1878 tofcor113, tofcor114, tofcor115,
1879 tofcor116, tofcor117, tofcor118,
1880 tofcor119};
1881
1882 // Determine ToF correction
1883 if (m_selection.tof_min() < 110) {
1884 std::string msg = "Minimum of ToF selection window "+
1886 " is smaller than 110. No ToF correction is "
1887 "available for this value.";
1889 }
1890 else if (m_selection.tof_min() > 119) {
1891 std::string msg = "Minimum of ToF selection window "+
1893 " is larger than 119. No ToF correction is "
1894 "available for this value.";
1896 }
1897 else if (m_selection.tof_max() != 130) {
1898 std::string msg = "Maximum of ToF selection window "+
1900 " is not 130. No ToF correction is available for "
1901 "this value.";
1903 }
1904 else {
1905
1906 // Compute mean energy of DRE
1907 double energy = std::sqrt(m_ebounds.emin().MeV() *
1908 m_ebounds.emax().MeV());
1909
1910 // Set node array
1911 GNodeArray nodes(4, tofcoreng);
1912
1913 // Set interpolation value
1914 nodes.set_value(energy);
1915
1916 // Get ToF correction index
1917 int i = m_selection.tof_min() - 110;
1918
1919 // Interpolate
1920 m_tofcor = tofcor[i][nodes.inx_left()] * nodes.wgt_left() +
1921 tofcor[i][nodes.inx_right()] * nodes.wgt_right();
1922
1923 }
1924
1925 // Return
1926 return;
1927}
#define G_COMPUTE_TOF_CORRECTION
Definition GCOMDri.cpp:58
const double r1sq
Definition GCOMDri.cpp:75
const double r1
Definition GCOMDri.cpp:72
const double d1_area
Definition GCOMDri.cpp:76
const double superpacket_duration
Definition GCOMDri.cpp:71
#define G_COMPUTE_DRE
Definition GCOMDri.cpp:53
COMPTEL Data Space class definition.
COMPTEL event list class definition.
COMPTEL Orbit Aspect Data class definition.
COMPTEL Orbit Aspect Data container class definition.
COMPTEL observation class interface definition.
COMPTEL selection set class definition.
COMPTEL instrument status class definition.
Implementation of support function used by COMPTEL classes.
COMPTEL Good Time Intervals class definition.
Definition of COMPTEL tools.
Ephemerides class definition.
Abstract FITS image base class definition.
FITS file class interface definition.
Mathematical function definitions.
Sky model class interface definition.
Point source spatial model class interface definition.
Abstract spatial model base class interface definition.
Node array class interface definition.
Gammalib tools definition.
GChatter
Definition GTypemaps.hpp:33
@ EXPLICIT
Definition GTypemaps.hpp:37
@ SILENT
Definition GTypemaps.hpp:34
double norm(const GVector &vector)
Computes vector norm.
Definition GVector.cpp:932
Abstract world coordinate system base class definition.
bool is_empty(void) const
Signals if there are no Solar System Barycentre Data in container.
Definition GCOMBvcs.hpp:163
double tdelta(const GSkyDir &dir, const GTime &time) const
Return time difference between photon arrival time at CGRO and the Solar System Barycentre (SSB)
Definition GCOMBvcs.cpp:564
COMPTEL Data Space class.
Definition GCOMDri.hpp:62
void init_statistics(void)
Initialise computation statistics.
Definition GCOMDri.cpp:1198
virtual void clear(void)
Clear COMPTEL Data Space.
Definition GCOMDri.cpp:227
GCOMDri & operator=(const GCOMDri &dri)
Assignment operator.
Definition GCOMDri.cpp:197
int m_num_skipped_superpackets
Number of skipped superpackets.
Definition GCOMDri.hpp:169
void save(const GFilename &filename, const bool &clobber=false) const
Save COMPTEL Data Space into DRI FITS file.
Definition GCOMDri.cpp:926
GFitsBinTable m_drw_table
DRW binary table to append to the FITS file.
Definition GCOMDri.hpp:173
double compute_overlap(const double &x1, const double &y1, const double &r1, const double &x2, const double &y2, const double &r2, const double &x3, const double &y3, const double &r3) const
Compute overlap between three circles.
Definition GCOMDri.cpp:1747
virtual GCOMDri * clone(void) const
Clone COMPTEL Data Space.
Definition GCOMDri.cpp:245
int nchi(void) const
Return number of Chi bins.
Definition GCOMDri.hpp:242
void compute_drm(const GCOMObservation &obs, const GModel &model)
Compute DRM model.
Definition GCOMDri.cpp:809
double m_drw_fprompt
DRW fitted fprompt parameter.
Definition GCOMDri.hpp:175
double m_phibin
Phibar binsize (deg)
Definition GCOMDri.hpp:160
double m_phasecor
Pulsar phase correction.
Definition GCOMDri.hpp:162
void write_attributes(GFitsHDU *hdu) const
Write DRI attributes into FITS HDU.
Definition GCOMDri.cpp:1385
GTime m_tstart
Selection start time.
Definition GCOMDri.hpp:165
virtual ~GCOMDri(void)
Destructor.
Definition GCOMDri.cpp:175
std::string m_drw_status
DRW fitting status.
Definition GCOMDri.hpp:174
double compute_surface(const double &x1, const double &y1, const double &r1, const double &x2, const double &y2, const double &r2) const
Compute surface of overlap between two circles.
Definition GCOMDri.cpp:1673
std::string m_drw_method
DRW method.
Definition GCOMDri.hpp:172
void free_members(void)
Delete class members.
Definition GCOMDri.cpp:1171
GGti m_gti
Good Time Intervals of data cube.
Definition GCOMDri.hpp:158
int m_num_used_superpackets
Number of used superpackets.
Definition GCOMDri.hpp:168
void compute_drx(const GCOMObservation &obs, const GCOMSelection &select=GCOMSelection())
Compute DRX exposure map.
Definition GCOMDri.cpp:702
void compute_drg(const GCOMObservation &obs, const GCOMSelection &select=GCOMSelection(), const double &zetamin=5.0)
Compute geometry cube.
Definition GCOMDri.cpp:557
double m_drw_e_fprompt
DRW fprompt parameter error.
Definition GCOMDri.hpp:176
void compute_tof_correction(void)
Compute ToF correction.
Definition GCOMDri.cpp:1863
double compute_geometry(const int &tjd, const double &theta, const double &phi, const GCOMSelection &select, const GCOMStatus &status) const
Compute DRG geometry factor.
Definition GCOMDri.cpp:1506
void init_members(void)
Initialise class members.
Definition GCOMDri.cpp:1093
const double & phibin(void) const
Return Compton scatter angle bin of DRI cube.
Definition GCOMDri.hpp:383
void init_cube(void)
Initialise DRI cube.
Definition GCOMDri.cpp:1183
void load(const GFilename &filename)
Load COMPTEL Data Space from DRI FITS file.
Definition GCOMDri.cpp:892
const GSkyMap & map(void) const
Return DRI sky map.
Definition GCOMDri.hpp:278
double m_zetamin
Minimum zeta angle.
Definition GCOMDri.hpp:182
const double & phimin(void) const
Return minimum Compton scatter angle of DRI cube.
Definition GCOMDri.hpp:371
GCOMDri(void)
Void constructor.
Definition GCOMDri.cpp:88
virtual std::string print(const GChatter &chatter=NORMAL) const
Print COMPTEL Data Space.
Definition GCOMDri.cpp:1001
GSkyMap m_dri
Data cube.
Definition GCOMDri.hpp:156
GCOMSelection m_selection
Selection parameters.
Definition GCOMDri.hpp:181
GEbounds m_ebounds
Energy boundaries of data cube.
Definition GCOMDri.hpp:157
int npsi(void) const
Return number of Psi bins.
Definition GCOMDri.hpp:254
double m_phimin
Phibar minimum (deg)
Definition GCOMDri.hpp:159
void compute_dre(const GCOMObservation &obs, const GCOMSelection &select=GCOMSelection(), const double &zetamin=5.0)
Compute event cube.
Definition GCOMDri.cpp:265
std::string m_name
Data cube name.
Definition GCOMDri.hpp:155
GTime m_tstop
Selection stop time.
Definition GCOMDri.hpp:166
int size(void) const
Return number of bins.
Definition GCOMDri.hpp:230
int m_drw_iter
DRW fitting iterations.
Definition GCOMDri.hpp:177
int m_num_superpackets
Number of superpackets.
Definition GCOMDri.hpp:167
bool use_superpacket(const GCOMOad &oad, const GCOMTim &tim, const GCOMSelection &select)
Check if superpacket should be used.
Definition GCOMDri.cpp:1228
bool m_has_selection
Signal that selection was applied.
Definition GCOMDri.hpp:180
void read_attributes(const GFitsHDU *hdu)
Read DRI attributes from FITS HDU.
Definition GCOMDri.cpp:1295
void write(GFits &fits, const std::string &extname="") const
Write COMPTEL Data Space into FITS image.
Definition GCOMDri.cpp:980
double m_tofcor
ToF correction.
Definition GCOMDri.hpp:161
int nphibar(void) const
Return number of Phibar bins.
Definition GCOMDri.hpp:266
void read(const GFitsImage &image)
Read COMPTEL Data Space from DRI FITS image.
Definition GCOMDri.cpp:955
void copy_members(const GCOMDri &dri)
Copy class members.
Definition GCOMDri.cpp:1131
double cone_content(const GSkyDir &dir, const double &armmin, const double &armmax) const
Compute content in cone.
Definition GCOMDri.cpp:845
COMPTEL event atom class.
COMPTEL event list class.
virtual int size(void) const
Return number of events in list.
COMPTEL Orbit Aspect Data class.
Definition GCOMOad.hpp:49
const int & tjd(void) const
Return Truncated Julian Days of Orbit Aspect Record.
Definition GCOMOad.hpp:196
double theta(const GSkyDir &sky) const
Return zenith angle of sky direction in COMPTEL coordinates.
Definition GCOMOad.hpp:460
const float & gcaz(void) const
Return Geocentre azimuth angle.
Definition GCOMOad.hpp:254
const GTime & tstart(void) const
Return start time of superpacket.
Definition GCOMOad.hpp:136
const float & gcel(void) const
Return Geocentre zenith angle.
Definition GCOMOad.hpp:283
const float & georad(void) const
Return apparent radius of Earth.
Definition GCOMOad.hpp:312
const GTime & tstop(void) const
Return stop time of superpacket.
Definition GCOMOad.hpp:167
const GVector & pos(void) const
Return telescope position vector (km)
Definition GCOMOad.hpp:430
double phi(const GSkyDir &sky) const
Return azimuth angle of sky direction in COMPTEL coordinates.
Definition GCOMOad.hpp:475
Interface class for COMPTEL observations.
const GCOMTim & tim(void) const
Return COMPTEL Good Time Intervals.
const GCOMOads & oads(void) const
Return Orbit Aspect Data.
const GCOMBvcs & bvcs(void) const
Return Solar System Barycentre Data.
COMPTEL selection set class.
virtual std::string print(const GChatter &chatter=NORMAL) const
Print COMPTEL selection set.
const int & tof_min(void) const
Return minimum of ToF selection window.
const int & fpmtflag(void) const
Return failed PMT flag for D2 modules.
void read(const GFitsHDU &hdu)
Read selection set from FITS HDU keywords.
void write(GFitsHDU &hdu) const
Write selection set keywords into FITS HDU.
bool has_pulsar(void) const
Signals that pulsar selection should be performed.
bool use_event(const GCOMEventAtom &event) const
Check if event should be used.
double orbital_phase(const GTime &time) const
Return orbital phase for a given time.
void init_statistics(void) const
Initialise selection statistics.
const int & tof_max(void) const
Return maximum of ToF selection window.
const GPhases & pulsar_phases(void) const
Return pulsar phases.
const bool & use_d1(const int &id1) const
Return D1 module usage flag.
const bool & use_d2(const int &id2) const
Return D2 module usage flag.
virtual void clear(void)
Clear COMPTEL selection set.
const GPhases & orbital_phases(void) const
Return orbital phases.
const GPulsar & pulsar(void) const
Return pulsar.
COMPTEL instrument status class.
int d2status(const int &tjd, const int &module) const
Return D2 module status.
int d1status(const int &tjd, const int &module) const
Return D1 module status.
COMPTEL Good Time Intervals class.
Definition GCOMTim.hpp:50
void reduce(const GGti &gti)
Reduces Good Time Intervals to intersection with intervals.
Definition GCOMTim.hpp:129
bool contains(const GTime &time) const
Check if time is comprised in the Good Time Intervals.
Definition GCOMTim.hpp:114
Energy boundaries container class.
Definition GEbounds.hpp:60
const GEnergy & emax(void) const
Return maximum energy of all intervals.
Definition GEbounds.hpp:199
std::string print(const GChatter &chatter=NORMAL) const
Print energy boundaries.
int size(void) const
Return number of energy boundaries.
Definition GEbounds.hpp:163
void clear(void)
Clear energy boundaries.
Definition GEbounds.cpp:268
const GEnergy & emin(void) const
Return minimum energy of all intervals.
Definition GEbounds.hpp:187
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
double MeV(void) const
Return energy in MeV.
Definition GEnergy.cpp:342
Ephemerides class.
double geo2ssb(const GSkyDir &srcdir, const GTime &time) const
Get time difference between geocentric and SSB (seconds)
Filename class.
Definition GFilename.hpp:62
std::string extname(const std::string &defaultname="") const
Return extension name.
FITS binary table class.
virtual void clear(void)
Clear binary table.
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
double real(const std::string &keyname) const
Return card value as double precision.
Definition GFitsHDU.hpp:423
GFitsHeaderCard & card(const int &cardno)
Return header card.
Definition GFitsHDU.hpp:259
int integer(const std::string &keyname) const
Return card value as integer.
Definition GFitsHDU.hpp:436
Abstract FITS image base class.
const int & nrows(void) const
Return number of rows in table.
FITS file class.
Definition GFits.hpp:63
void saveto(const GFilename &filename, const bool &clobber=false)
Saves to specified FITS file.
Definition GFits.cpp:1293
int size(void) const
Return number of HDUs in FITS file.
Definition GFits.hpp:237
GFitsHDU * append(const GFitsHDU &hdu)
Append HDU to FITS file.
Definition GFits.cpp:678
GFitsImage * image(const int &extno)
Get pointer to image HDU.
Definition GFits.cpp:368
void close(void)
Close FITS file.
Definition GFits.cpp:1342
Good Time Interval class.
Definition GGti.hpp:63
bool contains(const GTime &time) const
Checks whether Good Time Intervals contains time.
Definition GGti.cpp:1089
std::string print(const GChatter &chatter=NORMAL) const
Print Good Time Intervals.
Definition GGti.cpp:1125
void reference(const GTimeReference &ref)
Set time reference for Good Time Intervals.
Definition GGti.hpp:260
const GTime & tstop(void) const
Returns latest stop time in Good Time Intervals.
Definition GGti.hpp:210
int size(void) const
Return number of Good Time Intervals.
Definition GGti.hpp:157
void reduce(const GTime &tstart, const GTime &tstop)
Reduce Good Time Intervals to specified interval.
Definition GGti.cpp:420
const GTime & tstart(void) const
Returns earliest start time in Good Time Intervals.
Definition GGti.hpp:197
void clear(void)
Clear Good Time Intervals.
Definition GGti.cpp:238
Abstract model class.
Definition GModel.hpp:100
virtual double eval(const GEvent &event, const GObservation &obs, const bool &gradients=false) const =0
Node array class.
void set_value(const double &value) const
Set indices and weighting factors for interpolation.
const int & inx_right(void) const
Returns right node index.
const int & inx_left(void) const
Returns left node index.
const double & wgt_right(void) const
Returns right node weight.
const double & wgt_left(void) const
Returns left node weight.
virtual GEvents * events(void)
Return events.
double length(void) const
Returns total length of phase intervals.
Definition GPhases.cpp:365
bool contains(const double &phase) const
Check whether phase is contained in phases.
Definition GPhases.cpp:200
bool is_empty(void) const
Signal if there are no phase intervals.
Definition GPhases.hpp:114
Pulsar ephemeris class.
double phase(void) const
Returns pulse phase.
const GSkyDir & dir(void) const
Returns pulsar sky direction.
const GPulsarEphemeris & ephemeris(const GTime &time) const
Return pulsar ephemeris.
Definition GPulsar.cpp:253
GGti validity(void) const
Return validity intervals of pulsar ephemerides.
Definition GPulsar.cpp:286
Sky direction class.
Definition GSkyDir.hpp:62
void radec_deg(const double &ra, const double &dec)
Set equatorial sky direction (degrees)
Definition GSkyDir.cpp:245
double dist_deg(const GSkyDir &dir) const
Compute angular distance between sky directions in degrees.
Definition GSkyDir.hpp:288
Sky map class.
Definition GSkyMap.hpp:89
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
GSkyMap extract(const int &map, const int &nmaps=1) const
Extract maps into a new sky map object.
Definition GSkyMap.cpp:2139
const int & nx(void) const
Returns number of pixels in x coordinate.
Definition GSkyMap.hpp:399
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
const int & ny(void) const
Returns number of pixels in y coordinate.
Definition GSkyMap.hpp:415
const GSkyProjection * projection(void) const
Returns pointer to sky projection.
Definition GSkyMap.hpp:501
GFitsHDU * write(GFits &file, const std::string &extname="") const
Write sky map into FITS file.
Definition GSkyMap.cpp:2697
bool contains(const GSkyDir &dir) const
Checks if sky direction falls in map.
Definition GSkyMap.cpp:2023
int pix2inx(const GSkyPixel &pixel) const
Converts sky map pixel into pixel index.
Definition GSkyMap.cpp:1407
GSkyPixel dir2pix(const GSkyDir &dir) const
Returns sky map pixel for a given sky direction.
Definition GSkyMap.cpp:1472
std::string print(const GChatter &chatter=NORMAL) const
Print sky map.
Definition GSkyMap.cpp:2787
Sky map pixel class.
Definition GSkyPixel.hpp:74
Time class.
Definition GTime.hpp:55
void clear(void)
Clear time.
Definition GTime.cpp:252
std::string utc(const int &precision=0) const
Return time as string in UTC time system.
Definition GTime.cpp:465
const double & secs(void) const
Return time in seconds in native reference (TT)
Definition GTime.hpp:156
Vector class.
Definition GVector.hpp:46
Abstract world coordinate system base class.
Definition GWcs.hpp:51
double cdelt(const int &inx) const
Return pixel size.
Definition GWcs.cpp:935
double crpix(const int &inx) const
Return reference pixel.
Definition GWcs.cpp:911
double crval(const int &inx) const
Return value of reference pixel.
Definition GWcs.cpp:887
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1162
const double & com_exd2r(const int &id2)
Return D2 module exclusion region radius.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:508
const double pi
Definition GMath.hpp:35
const double & com_exd2x(const int &id2)
Return D2 module exclusion region X position.
const std::string extname_dri
Definition GCOMDri.hpp:53
const double deg2rad
Definition GMath.hpp:43
void com_wcs_mer2car(GSkyMap &map)
Changes Mercator's projection to cartesian projection.
const double & com_exd2y(const int &id2)
Return D2 module exclusion region Y position.
int com_tics(const GTime &time)
Convert GTime in COMPTEL tics.
GChatter reduce(const GChatter &chatter)
Reduce chattiness by one level.
Definition GTypemaps.hpp:65
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition GTools.cpp:1405
int com_tjd(const GTime &time)
Convert GTime in COMPTEL TJD.
Definition GCOMTools.cpp:91
GTime com_time(const int &tjd, const int &tics)
Convert TJD and COMPTEL tics in GTime object.
Definition GCOMTools.cpp:55