GammaLib  2.1.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GCOMSelection.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GCOMSelection.cpp - COMPTEL selection set class *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2017-2022 by Juergen Knoedlseder *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 /**
22  * @file GCOMSelection.cpp
23  * @brief COMPTEL selection set class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include "GFitsHDU.hpp"
32 #include "GCOMTools.hpp"
33 #include "GCOMSupport.hpp"
34 #include "GCOMStatus.hpp"
35 #include "GCOMSelection.hpp"
36 #include "GCOMEventAtom.hpp"
37 
38 /* __ Method name definitions ____________________________________________ */
39 #define G_FPMTFLAG "GCOMSelection::fpmtflag(int&)"
40 #define G_USE_D1_GET "GCOMSelection::use_d1(int&)"
41 #define G_USE_D1_SET "GCOMSelection::use_d1(int&, bool&)"
42 #define G_USE_D2_GET "GCOMSelection::use_d2(int&)"
43 #define G_USE_D2_SET "GCOMSelection::use_d2(int&, bool&)"
44 
45 /* __ Macros _____________________________________________________________ */
46 
47 /* __ Coding definitions _________________________________________________ */
48 
49 /* __ Debug definitions __________________________________________________ */
50 
51 
52 
53 /*==========================================================================
54  = =
55  = Constructors/destructors =
56  = =
57  ==========================================================================*/
58 
59 /***********************************************************************//**
60  * @brief Void constructor
61  ***************************************************************************/
63 {
64  // Initialise class members
65  init_members();
66 
67  // Return
68  return;
69 }
70 
71 
72 /***********************************************************************//**
73  * @brief Copy constructor
74  *
75  * @param[in] select COMPTEL selection set.
76  ***************************************************************************/
78 {
79  // Initialise class members
80  init_members();
81 
82  // Copy members
83  copy_members(select);
84 
85  // Return
86  return;
87 }
88 
89 
90 /***********************************************************************//**
91  * @brief Destructor
92  ***************************************************************************/
94 {
95  // Free members
96  free_members();
97 
98  // Return
99  return;
100 }
101 
102 
103 /*==========================================================================
104  = =
105  = Operators =
106  = =
107  ==========================================================================*/
108 
109 /***********************************************************************//**
110  * @brief Assignment operator
111  *
112  * @param[in] select COMPTEL selection set.
113  * @return COMPTEL selection set.
114  ***************************************************************************/
116 {
117  // Execute only if object is not identical
118  if (this != &select) {
119 
120  // Free members
121  free_members();
122 
123  // Initialise private members
124  init_members();
125 
126  // Copy members
127  copy_members(select);
128 
129  } // endif: object was not identical
130 
131  // Return this object
132  return *this;
133 }
134 
135 
136 /*==========================================================================
137  = =
138  = Public methods =
139  = =
140  ==========================================================================*/
141 
142 /***********************************************************************//**
143  * @brief Clear COMPTEL selection set
144  ***************************************************************************/
146 {
147  // Free members
148  free_members();
149 
150  // Initialise private members
151  init_members();
152 
153  // Return
154  return;
155 }
156 
157 
158 /***********************************************************************//**
159  * @brief Clone COMPTEL selection set
160  *
161  * @return Pointer to deep copy of COMPTEL selection set.
162  ***************************************************************************/
164 {
165  return new GCOMSelection(*this);
166 }
167 
168 
169 /***********************************************************************//**
170  * @brief Initialise selection statistics
171  ***************************************************************************/
173 {
174  // Initialise statistics members
176  m_num_events_used = 0;
178  m_num_e1_min = 0;
179  m_num_e1_max = 0;
180  m_num_e2_min = 0;
181  m_num_e2_max = 0;
182  m_num_tof_min = 0;
183  m_num_tof_max = 0;
184  m_num_psd_min = 0;
185  m_num_psd_max = 0;
186  m_num_reflag_min = 0;
187  m_num_reflag_max = 0;
188  m_num_vetoflag_min = 0;
189  m_num_vetoflag_max = 0;
190  m_num_no_scatter = 0;
192  m_num_d1module_off = 0;
193  m_num_d2module_off = 0;
194  m_num_fpmt = 0;
195  for (int i = 0; i < 7; ++i) {
196  m_num_d1[i] = 0;
197  }
198  for (int i = 0; i < 14; ++i) {
199  m_num_d2[i] = 0;
200  }
201 
202  // Return
203  return;
204 }
205 
206 
207 /***********************************************************************//**
208  * @brief Check if event should be used
209  *
210  * @param[in] event Event.
211  * @return True if event should be used, false otherwise.
212  *
213  * Checks if an event should be used for DRE binning.
214  ***************************************************************************/
215 bool GCOMSelection::use_event(const GCOMEventAtom& event) const
216 {
217  // Initialise D1 & D2 module status
218  static const GCOMStatus status;
219 
220  // Initialise usage flag
221  bool use = true;
222 
223  // Increment number of checked events
225 
226  // Check for bad minitelescopes
227  if (event.modcom() < 1 || event.modcom() > 98) {
229  use = false;
230  }
231 
232  // Check whether the event has a scatter angle determined. This is
233  // signaled by a scatter angle -10e20 in radians.
234  else if (event.theta() < -1.0e3) {
236  use = false;
237  }
238 
239  // Apply event selection
240  else if (event.e1() < m_e1_min) {
241  m_num_e1_min++;
242  use = false;
243  }
244  else if (event.e1() > m_e1_max) {
245  m_num_e1_max++;
246  use = false;
247  }
248  else if (event.e2() < m_e2_min) {
249  m_num_e2_min++;
250  use = false;
251  }
252  else if (event.e2() > m_e2_max) {
253  m_num_e2_max++;
254  use = false;
255  }
256  else if (event.tof() < m_tof_min) {
257  m_num_tof_min++;
258  use = false;
259  }
260  else if (event.tof() > m_tof_max) {
261  m_num_tof_max++;
262  use = false;
263  }
264  else if (event.psd() < m_psd_min) {
265  m_num_psd_min++;
266  use = false;
267  }
268  else if (event.psd() > m_psd_max) {
269  m_num_psd_max++;
270  use = false;
271  }
272  else if (event.reflag() < m_reflag_min) {
274  use = false;
275  }
276  else if (event.reflag() > m_reflag_max) {
278  use = false;
279  }
280  else if (event.veto() < m_vetoflag_min) {
282  use = false;
283  }
284  else if (event.veto() > m_vetoflag_max) {
286  use = false;
287  }
288 
289  // If event should be used then handle now the module status and
290  // decide whether it should be rejected
291  if (use) {
292 
293  // Extract module IDs from MODCOM
294  int id2 = (event.modcom()-1)/7 + 1; // [1-14]
295  int id1 = event.modcom() - (id2-1) * 7; // [1-7]
296 
297  // Get event TJD
298  int tjd = gammalib::com_tjd(event.time());
299 
300  // Set D1 and D2 status
301  int d1status = status.d1status(tjd, id1);
302  int d2status = status.d2status(tjd, id2);
303 
304  // Exclude event if the coresponding modules should not be used
305  if (!m_use_d1[id1-1]) {
307  use = false;
308  }
309  else if (!m_use_d2[id2-1]) {
311  use = false;
312  }
313 
314  // Exclude event if the corresponding modules are signalled
315  // as off
316  else if (d1status != 1) {
318  use = false;
319  }
320  else if (d2status < 1) {
322  use = false;
323  }
324 
325  // Handle D2 modules with failed PMTs based on value of
326  // failure flag
327  else if (d2status > 1) {
328 
329  // If failure flag = 0 then reject event and signal that the
330  // module was off
331  if (m_fpmtflag == 0) {
333  use = false;
334  }
335 
336  // ... otherwise if failure flag = 2 and the module has a
337  // valid exclusion circle then reject event if it is
338  // within the exclusion circle; if the module has no
339  // exclusion region then reject the entire module and
340  // signal that it was off.
341  else if (m_fpmtflag == 2) {
342  double r = gammalib::com_exd2r(id2);
343  if (r >= 0.1) {
344  double dx = gammalib::com_exd2x(id2) - 0.1 * event.x_d2();
345  double dy = gammalib::com_exd2y(id2) - 0.1 * event.y_d2();
346  double dsq = dx*dx + dy*dy;
347  double rsq = r*r;
348  if (dsq <= rsq) {
349  m_num_fpmt++;
350  use = false;
351  }
352  }
353  else {
355  use = false;
356  }
357  }
358 
359  } // endif: handled D2 modules with failed PMTs
360 
361  } // endif: handled module status
362 
363  // Update acceptance and rejection statistics
364  if (use) {
365 
366  // Extract module IDs from MODCOM
367  int id2 = (event.modcom()-1)/7 + 1; // [1-14]
368  int id1 = event.modcom() - (id2-1) * 7; // [1-7]
369 
370  // Update statistics
372  m_num_d1[id1-1]++;
373  m_num_d2[id2-1]++;
374 
375  }
376  else {
378  }
379 
380  // Return usage flag
381  return use;
382 }
383 
384 
385 /***********************************************************************//**
386  * @brief Set failed PMT flag for D2 modules
387  *
388  * @param[in] fpmtflag Failed PMT flag for D2 modules.
389  *
390  * Set the failed PMT flag for D2 modules. The following values can be
391  * set:
392  * - 0: excluded D2 modules with failed PMTs
393  * - 1: include D2 modules with failed PMTs
394  * - 2: include D2 modules with failed PMTs by excluding zone around failed
395  * PMTs
396  ***************************************************************************/
397 void GCOMSelection::fpmtflag(const int& fpmtflag)
398 {
399  // Check validify of values
400  if (fpmtflag < 0 || fpmtflag > 2) {
401  std::string msg = "Invalid value "+gammalib::str(fpmtflag)+
402  " specified for failed PMT flag for D2 modules. "
403  "Please specify 0, 1 or 2.";
405  }
406 
407  // Set flag
409 
410  // Return
411  return;
412 }
413 
414 
415 /***********************************************************************//**
416  * @brief Return D1 module usage flag
417  *
418  * @param[in] id1 D1 module identifier [0,...,6].
419  * @return True if D1 module @p id1 should be used.
420  ***************************************************************************/
421 const bool& GCOMSelection::use_d1(const int& id1) const
422 {
423  // Check module validity range
424  if (id1 < 0 || id1 > 6) {
425  std::string msg = "Invalid D1 module identifier "+gammalib::str(id1)+
426  " specified. The D1 module identifier needs to be "
427  "comprised within 0 and 6.";
429  }
430 
431  // Return usage flag
432  return (m_use_d1[id1]);
433 }
434 
435 
436 /***********************************************************************//**
437  * @brief Set D1 module usage flag
438  *
439  * @param[in] id1 D1 module identifier [0,...,6].
440  * @param[in] use D1 module usage.
441  ***************************************************************************/
442 void GCOMSelection::use_d1(const int& id1, const bool& use)
443 {
444  // Check module validity range
445  if (id1 < 0 || id1 > 6) {
446  std::string msg = "Invalid D1 module identifier "+gammalib::str(id1)+
447  " specified. The D1 module identifier needs to be "
448  "comprised within 0 and 6.";
450  }
451 
452  // Set usage flag
453  m_use_d1[id1] = use;
454 
455  // Return
456  return;
457 }
458 
459 
460 /***********************************************************************//**
461  * @brief Return D2 module usage flag
462  *
463  * @param[in] id2 D2 module identifier [0,...,13].
464  * @return True if D2 module @p id2 should be used.
465  ***************************************************************************/
466 const bool& GCOMSelection::use_d2(const int& id2) const
467 {
468  // Check module validity range
469  if (id2 < 0 || id2 > 13) {
470  std::string msg = "Invalid D2 module identifier "+gammalib::str(id2)+
471  " specified. The D2 module identifier needs to be "
472  "comprised within 0 and 13.";
474  }
475 
476  // Return usage flag
477  return (m_use_d2[id2]);
478 }
479 
480 
481 /***********************************************************************//**
482  * @brief Set D2 module usage flag
483  *
484  * @param[in] id2 D2 module identifier [0,...,13].
485  * @param[in] use D2 module usage.
486  ***************************************************************************/
487 void GCOMSelection::use_d2(const int& id2, const bool& use)
488 {
489  // Check module validity range
490  if (id2 < 0 || id2 > 13) {
491  std::string msg = "Invalid D2 module identifier "+gammalib::str(id2)+
492  " specified. The D2 module identifier needs to be "
493  "comprised within 0 and 13.";
495  }
496 
497  // Set usage flag
498  m_use_d2[id2] = use;
499 
500  // Return
501  return;
502 }
503 
504 
505 /***********************************************************************//**
506  * @brief Read selection set from FITS HDU keywords
507  *
508  * @param[in] hdu FITS HDU.
509  ***************************************************************************/
511 {
512  // Read D1 energy selection
513  if (hdu.has_card("D1EMIN") && hdu.has_card("D1EMAX")) {
514  m_e1_min = hdu.real("D1EMIN");
515  m_e1_max = hdu.real("D1EMAX");
516  }
517 
518  // Read D2 energy selection
519  if (hdu.has_card("D2EMIN") && hdu.has_card("D2EMAX")) {
520  m_e2_min = hdu.real("D2EMIN");
521  m_e2_max = hdu.real("D2EMAX");
522  }
523 
524  // Read ToF selection
525  if (hdu.has_card("TOFMIN") && hdu.has_card("TOFMAX")) {
526  m_tof_min = hdu.integer("TOFMIN");
527  m_tof_max = hdu.integer("TOFMAX");
528  }
529 
530  // Read PSD selection
531  if (hdu.has_card("PSDMIN") && hdu.has_card("PSDMAX")) {
532  m_psd_min = hdu.integer("PSDMIN");
533  m_psd_max = hdu.integer("PSDMAX");
534  }
535 
536  // Read rejection flag selection
537  if (hdu.has_card("RFLMIN") && hdu.has_card("RFLMAX")) {
538  m_reflag_min = hdu.integer("RFLMIN");
539  m_reflag_max = hdu.integer("RFLMAX");
540  }
541 
542  // Read veto flag selection
543  if (hdu.has_card("VFLMIN") && hdu.has_card("VFLMAX")) {
544  m_vetoflag_min = hdu.integer("VFLMIN");
545  m_vetoflag_max = hdu.integer("VFLMAX");
546  }
547 
548  // Read D2 PMT failure handling flag
549  if (hdu.has_card("D2FPMT")) {
550  m_fpmtflag = hdu.integer("D2FPMT");
551  }
552 
553  // Read D1 module usage flag
554  if (hdu.has_card("D1USE")) {
555  std::string use = gammalib::strip_whitespace(hdu.string("D1USE"));
556  if (use.length() == 7) {
557  for (int i = 0; i < 7; ++i) {
558  m_use_d1[i] = (use[i] == '1');
559  }
560  }
561  }
562 
563  // Read D2 module usage flag
564  if (hdu.has_card("D2USE")) {
565  std::string use = gammalib::strip_whitespace(hdu.string("D2USE"));
566  if (use.length() == 14) {
567  for (int i = 0; i < 14; ++i) {
568  m_use_d2[i] = (use[i] == '1');
569  }
570  }
571  }
572 
573  // Read selection statistics
574  if (hdu.has_card("NEVCHK")) {
575  m_num_events_checked = hdu.integer("NEVCHK");
576  }
577  if (hdu.has_card("NEVUSE")) {
578  m_num_events_used = hdu.integer("NEVUSE");
579  }
580  if (hdu.has_card("NEVREJ")) {
581  m_num_events_rejected = hdu.integer("NEVREJ");
582  }
583  if (hdu.has_card("ND1ELO") && hdu.has_card("ND1EHI")) {
584  m_num_e1_min = hdu.integer("ND1ELO");
585  m_num_e1_max = hdu.integer("ND1EHI");
586  }
587  if (hdu.has_card("ND2ELO") && hdu.has_card("ND2EHI")) {
588  m_num_e2_min = hdu.integer("ND2ELO");
589  m_num_e2_max = hdu.integer("ND2EHI");
590  }
591  if (hdu.has_card("NTOFLO") && hdu.has_card("NTOFHI")) {
592  m_num_tof_min = hdu.integer("NTOFLO");
593  m_num_tof_max = hdu.integer("NTOFHI");
594  }
595  if (hdu.has_card("NPSDLO") && hdu.has_card("NPSDHI")) {
596  m_num_psd_min = hdu.integer("NPSDLO");
597  m_num_psd_max = hdu.integer("NPSDHI");
598  }
599  if (hdu.has_card("NRFLLO") && hdu.has_card("NRFLHI")) {
600  m_num_reflag_min = hdu.integer("NRFLLO");
601  m_num_reflag_max = hdu.integer("NRFLHI");
602  }
603  if (hdu.has_card("NVFLLO") && hdu.has_card("NVFLHI")) {
604  m_num_vetoflag_min = hdu.integer("NVFLLO");
605  m_num_vetoflag_max = hdu.integer("NVFLHI");
606  }
607  if (hdu.has_card("NNOSCT")) {
608  m_num_no_scatter = hdu.integer("NNOSCT");
609  }
610  for (int i = 0; i < 7; ++i) {
611  std::string key = "ND1-"+gammalib::str(i+1,"%2.2d");
612  if (hdu.has_card(key)) {
613  m_num_d1[i] = hdu.integer(key);
614  }
615  }
616  for (int i = 0; i < 14; ++i) {
617  std::string key = "ND2-"+gammalib::str(i+1,"%2.2d");
618  if (hdu.has_card(key)) {
619  m_num_d2[i] = hdu.integer(key);
620  }
621  }
622  if (hdu.has_card("ND1OFF")) {
623  m_num_d1module_off = hdu.integer("ND1OFF");
624  }
625  if (hdu.has_card("ND2OFF")) {
626  m_num_d2module_off = hdu.integer("ND2OFF");
627  }
628  if (hdu.has_card("ND2FPM")) {
629  m_num_fpmt = hdu.integer("ND2FPM");
630  }
631 
632  // Return
633  return;
634 }
635 
636 
637 /***********************************************************************//**
638  * @brief Write selection set keywords into FITS HDU
639  *
640  * @param[in] hdu FITS HDU.
641  ***************************************************************************/
643 {
644  // Write D1 energy selection
645  hdu.card("D1EMIN", m_e1_min, "[MeV] Minimum D1 energy deposit");
646  hdu.card("D1EMAX", m_e1_max, "[MeV] Maximum D1 energy deposit");
647 
648  // Write D2 energy selection
649  hdu.card("D2EMIN", m_e2_min, "[MeV] Minimum D2 energy deposit");
650  hdu.card("D2EMAX", m_e2_max, "[MeV] Maximum D2 energy deposit");
651 
652  // Write ToF selection
653  hdu.card("TOFMIN", m_tof_min, "ToF selection minimum");
654  hdu.card("TOFMAX", m_tof_max, "ToF selection maximum");
655 
656  // Write PSD selection
657  hdu.card("PSDMIN", m_psd_min, "PSD selection minimum");
658  hdu.card("PSDMAX", m_psd_max, "PSD selection maximum");
659 
660  // Write rejection flag selection
661  hdu.card("RFLMIN", m_reflag_min, "Rejection flag minimum");
662  hdu.card("RFLMAX", m_reflag_max, "Rejection flag maximum");
663 
664  // Write veto flag selection
665  hdu.card("VFLMIN", m_vetoflag_min, "Veto flag minimum");
666  hdu.card("VFLMAX", m_vetoflag_max, "Veto flag maximum");
667 
668  // Write D2 PMT failure handling flag
669  hdu.card("D2FPMT", m_fpmtflag, "D2 PMT failure handling");
670 
671  // Write D1 module usage
672  std::string d1use = "0000000";
673  for (int i = 0; i < 7; ++i) {
674  if (m_use_d1[i]) {
675  d1use[i] = '1';
676  }
677  }
678  hdu.card("D1USE", d1use, "D1 module usage");
679 
680  // Write D2 module usage
681  std::string d2use = "00000000000000";
682  for (int i = 0; i < 14; ++i) {
683  if (m_use_d2[i]) {
684  d2use[i] = '1';
685  }
686  }
687  hdu.card("D2USE", d2use, "D2 module usage");
688 
689  // Write selection statistics
690  hdu.card("NEVCHK", m_num_events_checked, "Number of checked events");
691  hdu.card("NEVUSE", m_num_events_used, "Number of used events");
692  hdu.card("NEVREJ", m_num_events_rejected, "Number of rejected events");
693  hdu.card("ND1ELO", m_num_e1_min, "Number of events < D1EMIN");
694  hdu.card("ND1EHI", m_num_e1_max, "Number of events > D1EMAX");
695  hdu.card("ND2ELO", m_num_e2_min, "Number of events < D2EMIN");
696  hdu.card("ND2EHI", m_num_e2_max, "Number of events > D2EMAX");
697  hdu.card("NTOFLO", m_num_tof_min, "Number of events < TOFMIN");
698  hdu.card("NTOFHI", m_num_tof_max, "Number of events > TOFMIN");
699  hdu.card("NPSDLO", m_num_psd_min, "Number of events < PSDMIN");
700  hdu.card("NPSDHI", m_num_psd_max, "Number of events > PSDMAX");
701  hdu.card("NRFLLO", m_num_reflag_min, "Number of events < RFLMIN");
702  hdu.card("NRFLHI", m_num_reflag_max, "Number of events > RFLMAX");
703  hdu.card("NVFLLO", m_num_vetoflag_min, "Number of events < VFLMIN");
704  hdu.card("NVFLHI", m_num_vetoflag_max, "Number of events > VFLMAX");
705  hdu.card("NNOSCT", m_num_no_scatter, "Number of events w/o scatter angle");
706  hdu.card("NINVMT", m_num_invalid_modcom, "Number of events with invalid minitelescope");
707  for (int i = 0; i < 7; ++i) {
708  std::string key = "ND1-"+gammalib::str(i+1,"%2.2d");
709  std::string com = "Number of events in D1 module "+gammalib::str(i+1);
710  hdu.card(key, m_num_d1[i], com);
711  }
712  for (int i = 0; i < 14; ++i) {
713  std::string key = "ND2-"+gammalib::str(i+1,"%2.2d");
714  std::string com = "Number of events in D2 module "+gammalib::str(i+1);
715  hdu.card(key, m_num_d2[i], com);
716  }
717  hdu.card("ND1OFF", m_num_d1module_off, "Number of events with D1 module off");
718  hdu.card("ND2OFF", m_num_d2module_off, "Number of events with D2 module off");
719  hdu.card("ND2FPM", m_num_fpmt, "Number of events excluded due to failed PMTs");
720 
721  // Return
722  return;
723 }
724 
725 
726 /***********************************************************************//**
727  * @brief Set orbital period
728  *
729  * @param[in] period Orbital period (days).
730  * @param[in] time Time of phase zero.
731  *
732  * Set the orbital phase for orbital phase selection.
733  ***************************************************************************/
734 void GCOMSelection::orbital_period(const double& period, const GTime& time)
735 {
736  // Clear temporal phase curve
738 
739  // Get frequency of orbit in units of Hz
740  double f0 = 1.0 / (period * gammalib::sec_in_day);
741 
742  // Set phase curve elements
743  m_orbital_phase_curve.mjd(time); // Reference time
744  m_orbital_phase_curve.phase(0.0); // Phase at reference time
745  m_orbital_phase_curve.f0(f0); // Frequency at reference time
746  m_orbital_phase_curve.f1(0.0); // No frequency derivative
747  m_orbital_phase_curve.f2(0.0); // No 2nd frequency derivative
748 
749  // Return
750  return;
751 }
752 
753 
754 /***********************************************************************//**
755  * @brief Print COMPTEL selection set
756  *
757  * @param[in] chatter Chattiness.
758  * @return String containing COMPTEL selection set information.
759  ***************************************************************************/
760 std::string GCOMSelection::print(const GChatter& chatter) const
761 {
762  // Initialise result string
763  std::string result;
764 
765  // Continue only if chatter is not silent
766  if (chatter != SILENT) {
767 
768  // Append header
769  result.append("=== GCOMSelection ===");
770 
771  // Append number of checked events
772  result.append("\n"+gammalib::parformat("Checked events"));
773  result.append(gammalib::str(m_num_events_checked));
774  result.append("\n"+gammalib::parformat("Accepted events"));
775  result.append(gammalib::str(m_num_events_used));
776  result.append("\n"+gammalib::parformat("Rejected events"));
777  result.append(gammalib::str(m_num_events_rejected));
778 
779  // Append E1 selection statistics
780  result.append("\n"+gammalib::parformat("E1 selection"));
781  result.append(gammalib::str(m_num_e1_min)+" < [");
782  result.append(gammalib::str(m_e1_min)+" - ");
783  result.append(gammalib::str(m_e1_max)+" MeV] < ");
784  result.append(gammalib::str(m_num_e1_max));
785 
786  // Append E2 selection statistics
787  result.append("\n"+gammalib::parformat("E2 selection"));
788  result.append(gammalib::str(m_num_e2_min)+" < [");
789  result.append(gammalib::str(m_e2_min)+" - ");
790  result.append(gammalib::str(m_e2_max)+" MeV] < ");
791  result.append(gammalib::str(m_num_e2_max));
792 
793  // Append TOF selection statistics
794  result.append("\n"+gammalib::parformat("TOF selection"));
795  result.append(gammalib::str(m_num_tof_min)+" < [");
796  result.append(gammalib::str(m_tof_min)+" - ");
797  result.append(gammalib::str(m_tof_max)+"] < ");
798  result.append(gammalib::str(m_num_tof_max));
799 
800  // Append PSD selection statistics
801  result.append("\n"+gammalib::parformat("PSD selection"));
802  result.append(gammalib::str(m_num_psd_min)+" < [");
803  result.append(gammalib::str(m_psd_min)+" - ");
804  result.append(gammalib::str(m_psd_max)+"] < ");
805  result.append(gammalib::str(m_num_psd_max));
806 
807  // Append rejection flag selection statistics
808  result.append("\n"+gammalib::parformat("Rejection flag selection"));
809  result.append(gammalib::str(m_num_reflag_min)+" < [");
810  result.append(gammalib::str(m_reflag_min)+" - ");
811  result.append(gammalib::str(m_reflag_max)+"] < ");
812  result.append(gammalib::str(m_num_reflag_max));
813 
814  // Append veto flag selection statistics
815  result.append("\n"+gammalib::parformat("Veto flag selection"));
816  result.append(gammalib::str(m_num_vetoflag_min)+" < [");
817  result.append(gammalib::str(m_vetoflag_min)+" - ");
818  result.append(gammalib::str(m_vetoflag_max)+"] < ");
819  result.append(gammalib::str(m_num_vetoflag_max));
820 
821  // Append D1 module usage
822  for (int i = 0; i < 7; ++i) {
823  result.append("\n"+gammalib::parformat("D1 module "+gammalib::str(i+1)));
824  result.append(gammalib::str(m_num_d1[i]));
825  if (m_use_d1[i]) {
826  result.append(" [use]");
827  }
828  else {
829  result.append(" [don't use]");
830  }
831  }
832 
833  // Append D2 module usage
834  for (int i = 0; i < 14; ++i) {
835  result.append("\n"+gammalib::parformat("D2 module "+gammalib::str(i+1)));
836  result.append(gammalib::str(m_num_d2[i]));
837  if (m_use_d2[i]) {
838  result.append(" [use]");
839  }
840  else {
841  result.append(" [don't use]");
842  }
843  }
844 
845  // Append D1 module off
846  result.append("\n"+gammalib::parformat("D1 modules off"));
847  result.append(gammalib::str(m_num_d1module_off));
848 
849  // Append D2 module off
850  result.append("\n"+gammalib::parformat("D2 modules off"));
851  result.append(gammalib::str(m_num_d2module_off));
852 
853  // Append D2 PMT failure handling statistics
854  result.append("\n"+gammalib::parformat("D2 PMT failure"));
855  result.append(gammalib::str(m_num_fpmt)+" [");
856  result.append(gammalib::str(m_fpmtflag)+"]");
857 
858  // Append other statistics
859  result.append("\n"+gammalib::parformat("No scatter angle"));
860  result.append(gammalib::str(m_num_no_scatter));
861  result.append("\n"+gammalib::parformat("Invalid minitelescope"));
862  result.append(gammalib::str(m_num_invalid_modcom));
863 
864  // Append orbital phase selection if it exists
865  if (!m_orbital_phases.is_empty()) {
866  result.append("\n"+m_orbital_phases.print());
867  result.append("\n"+m_orbital_phase_curve.print());
868  }
869 
870  // Append pulsar if it exists
871  if (!m_pulsar.is_empty()) {
872  result.append("\n"+m_pulsar.print());
873  }
874 
875  // Append pulsar phase selection if it exists
876  if (!m_pulsar_phases.is_empty()) {
877  result.append("\n"+m_pulsar_phases.print());
878  }
879 
880  } // endif: chatter was not silent
881 
882  // Return result
883  return result;
884 }
885 
886 
887 /*==========================================================================
888  = =
889  = Private methods =
890  = =
891  ==========================================================================*/
892 
893 /***********************************************************************//**
894  * @brief Initialise class members
895  ***************************************************************************/
897 {
898  // Initialise members
899  m_e1_min = 0.070; //!< Minimum D1 energy deposit (MeV)
900  m_e1_max = 20.0; //!< Maximum D1 energy deposit (MeV)
901  m_e2_min = 0.650; //!< Minimum D2 energy deposit (MeV)
902  m_e2_max = 30.0; //!< Maximum D2 energy deposit (MeV)
903  m_tof_min = 115; //!< Minimum TOF window
904  m_tof_max = 130; //!< Maximum TOF window
905  m_psd_min = 0; //!< Minimum PSD window
906  m_psd_max = 110; //!< Maximum PSD window
907  m_reflag_min = 1; //!< Minimum rejection flag
908  m_reflag_max = 1000; //!< Maximum rejection flag
909  m_vetoflag_min = 0; //!< Minimum veto flag
910  m_vetoflag_max = 0; //!< Maximum veto flag
911  m_fpmtflag = 0; //!< D2 PMT failure flag
915  m_pulsar.clear();
916  for (int i = 0; i < 7; ++i) {
917  m_use_d1[i] = true;
918  }
919  for (int i = 0; i < 14; ++i) {
920  m_use_d2[i] = true;
921  }
922 
923  // Initialise statistics
924  init_statistics();
925 
926  // Return
927  return;
928 }
929 
930 
931 /***********************************************************************//**
932  * @brief Copy class members
933  *
934  * @param[in] select COMPTEL selection set.
935  ***************************************************************************/
937 {
938  // Copy members
939  m_e1_min = select.m_e1_min;
940  m_e1_max = select.m_e1_max;
941  m_e2_min = select.m_e2_min;
942  m_e2_max = select.m_e2_max;
943  m_tof_min = select.m_tof_min;
944  m_tof_max = select.m_tof_max;
945  m_psd_min = select.m_psd_min;
946  m_psd_max = select.m_psd_max;
947  m_reflag_min = select.m_reflag_min;
948  m_reflag_max = select.m_reflag_max;
951  m_fpmtflag = select.m_fpmtflag;
955  m_pulsar = select.m_pulsar;
956  for (int i = 0; i < 7; ++i) {
957  m_use_d1[i] = select.m_use_d1[i];
958  }
959  for (int i = 0; i < 14; ++i) {
960  m_use_d2[i] = select.m_use_d2[i];
961  }
962 
963  // Copy statistics
967  m_num_e1_min = select.m_num_e1_min;
968  m_num_e1_max = select.m_num_e1_max;
969  m_num_e2_min = select.m_num_e2_min;
970  m_num_e2_max = select.m_num_e2_max;
971  m_num_tof_min = select.m_num_tof_min;
972  m_num_tof_max = select.m_num_tof_max;
973  m_num_psd_min = select.m_num_psd_min;
974  m_num_psd_max = select.m_num_psd_max;
983  m_num_fpmt = select.m_num_fpmt;
984 
985  // Copy module usage
986  for (int i = 0; i < 7; ++i) {
987  m_num_d1[i] = select.m_num_d1[i];
988  }
989  for (int i = 0; i < 14; ++i) {
990  m_num_d2[i] = select.m_num_d2[i];
991  }
992 
993  // Return
994  return;
995 }
996 
997 
998 /***********************************************************************//**
999  * @brief Delete class members
1000  ***************************************************************************/
1002 {
1003  // Return
1004  return;
1005 }
void clear(void)
Clear phase intervals.
Definition: GPhases.cpp:166
COMPTEL instrument status class.
Definition: GCOMStatus.hpp:49
COMPTEL instrument status class definition.
const bool & use_d2(const int &id2) const
Return D2 module usage flag.
void modcom(const int &modcom)
Set mini telescope.
void copy_members(const GCOMSelection &select)
Copy class members.
int m_num_d2[14]
Number of events per D2 module.
bool has_card(const int &cardno) const
Check existence of header card.
Definition: GFitsHDU.hpp:233
int m_vetoflag_max
Maximum veto flag.
int m_num_d1module_off
Number of events excluded since D1 module off.
int m_num_tof_max
Number of events above TOF threshold.
int m_reflag_min
Minimum rejection flag.
Definition of COMPTEL tools.
bool m_use_d1[7]
D1 module usage.
Abstract FITS extension base class.
Definition: GFitsHDU.hpp:51
GTime mjd(void) const
Return reference Modified Julian Day.
COMPTEL event atom class definition.
void reflag(const int &reflag)
Set rejection flag.
void theta(const float &theta)
Set scatter zenith angle.
int m_tof_max
Maximum TOF window.
void tof(const float &tof)
Set TOF value.
double m_e2_max
Maximum D2 energy deposit (MeV)
Time class.
Definition: GTime.hpp:55
double m_e2_min
Minimum D2 energy deposit (MeV)
void e2(const float &e2)
Set D2 module energy deposit.
bool is_empty(void) const
Signals if there are no ephemerides for pulsar.
Definition: GPulsar.hpp:164
double f2(void) const
Return second frequency derivative at reference Modified Julian Day.
COMPTEL selection set class.
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition: GTools.cpp:80
int m_reflag_max
Maximum rejection flag.
const double & com_exd2r(const int &id2)
Return D2 module exclusion region radius.
int m_vetoflag_min
Minimum veto flag.
bool is_empty(void) const
Signal if there are no phase intervals.
Definition: GPhases.hpp:114
Implementation of support function used by COMPTEL classes.
const int & fpmtflag(void) const
Return failed PMT flag for D2 modules.
Abstract FITS extension base class definition.
GModelTemporalPhaseCurve m_orbital_phase_curve
Orbital phase curve.
COMPTEL selection set class definition.
const double sec_in_day
Definition: GTools.hpp:49
double real(const std::string &keyname) const
Return card value as double precision.
Definition: GFitsHDU.hpp:423
void free_members(void)
Delete class members.
void write(GFitsHDU &hdu) const
Write selection set keywords into FITS HDU.
int m_psd_max
Maximum PSD window.
const double & com_exd2y(const int &id2)
Return D2 module exclusion region Y position.
void veto(const int &veto)
Set veto flag.
#define G_USE_D1_SET
virtual std::string print(const GChatter &chatter=NORMAL) const
Print Pulsar.
Definition: GPulsar.cpp:381
int m_num_reflag_max
Number of events above rejection flag threshold.
void orbital_period(const double &period, const GTime &time)
Set orbital period.
GCOMSelection(void)
Void constructor.
int com_tjd(const GTime &time)
Convert GTime in COMPTEL TJD.
Definition: GCOMTools.cpp:91
int m_num_e1_min
Number of events below E1 threshold.
void init_members(void)
Initialise class members.
#define G_USE_D2_SET
int m_psd_min
Minimum PSD window.
double f0(void) const
Return frequency at reference Modified Julian Day.
void init_statistics(void) const
Initialise selection statistics.
const double & com_exd2x(const int &id2)
Return D2 module exclusion region X position.
int m_num_d2module_off
Number of events excluded since D2 module off.
GCOMSelection & operator=(const GCOMSelection &select)
Assignment operator.
virtual ~GCOMSelection(void)
Destructor.
GChatter
Definition: GTypemaps.hpp:33
virtual std::string print(const GChatter &chatter=NORMAL) const
Print COMPTEL selection set.
#define G_USE_D2_GET
int integer(const std::string &keyname) const
Return card value as integer.
Definition: GFitsHDU.hpp:436
void psd(const float &psd)
Set PSD value.
double m_e1_max
Maximum D1 energy deposit (MeV)
int m_num_e2_max
Number of events above E2 threshold.
GPulsar m_pulsar
Pulsar information.
int d1status(const int &tjd, const int &module) const
Return D1 module status.
Definition: GCOMStatus.cpp:188
#define G_FPMTFLAG
const bool & use_d1(const int &id1) const
Return D1 module usage flag.
int m_num_events_rejected
Number of rejected events.
bool m_use_d2[14]
D2 module usage.
virtual GCOMSelection * clone(void) const
Clone COMPTEL selection set.
int m_num_vetoflag_min
Number of events below veto flag threshold.
double phase(void) const
Return phase at reference Modified Julian Day.
int m_num_reflag_min
Number of events below rejection flag threshold.
const GTime & time(void) const
Return event time.
bool use_event(const GCOMEventAtom &event) const
Check if event should be used.
int d2status(const int &tjd, const int &module) const
Return D2 module status.
Definition: GCOMStatus.cpp:217
void e1(const float &e1)
Set D1 module energy deposit.
int m_num_invalid_modcom
Number of events with invalid minitelescopes.
#define G_USE_D1_GET
virtual std::string print(const GChatter &chatter=NORMAL) const
Print phase curve information.
int m_num_events_checked
Number of checked events.
GPhases m_pulsar_phases
Phases for pulse phase selection.
int m_num_fpmt
Number of events excluded due to failed PMT.
int m_num_tof_min
Number of events below TOF threshold.
virtual void clear(void)
Clear COMPTEL selection set.
int m_num_psd_max
Number of events above PSD threshold.
std::string string(const std::string &keyname) const
Return card value as string.
Definition: GFitsHDU.hpp:410
int m_num_no_scatter
Number of events without scatter angle.
double f1(void) const
Return first frequency derivative at reference Modified Julian Day.
int m_num_psd_min
Number of events below PSD threshold.
virtual void clear(void)
Clear Pulsar.
Definition: GPulsar.cpp:171
double m_e1_min
Minimum D1 energy deposit (MeV)
void read(const GFitsHDU &hdu)
Read selection set from FITS HDU keywords.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
int m_num_e2_min
Number of events below E2 threshold.
GPhases m_orbital_phases
Phases for orbital phase selection.
GFitsHeaderCard & card(const int &cardno)
Return header card.
Definition: GFitsHDU.hpp:259
std::string print(const GChatter &chatter=NORMAL) const
Print phase intervals.
Definition: GPhases.cpp:386
int m_num_events_used
Number of used events.
int m_num_vetoflag_max
Number of events above veto flag threshold.
int m_tof_min
Minimum TOF window.
int m_num_e1_max
Number of events above E1 threshold.
int m_num_d1[7]
Number of events per D1 module.
virtual void clear(void)
Clear phase curve.
COMPTEL event atom class.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489