Commit 1fbf6770fd946562fb0d6cb6fc56a0b9ffb6595c

Authored by Jürgen Knödlseder
1 parent 22933023

Add D1 and D2 module statistics

ChangeLog
1 -2021-12-01 1 +2021-12-02
2 2
3 * Version 2.0.0 released 3 * Version 2.0.0 released
4 ======================== 4 ========================
5 5
6 - Add GCOMSelection::fpmtflag() method (#3917) 6 + Add GCOMSelection::fpmtflag(), GCOMSelection::use_d1() and
  7 + GCOMSelection::use_d2() methods (#3917)
7 Add GCOMModelDRBPhibarBins class (#3913) 8 Add GCOMModelDRBPhibarBins class (#3913)
8 Compute spectral model gradients for negative factor values 9 Compute spectral model gradients for negative factor values
9 Add likelihood fit event selection hook (#3912) 10 Add likelihood fit event selection hook (#3912)
@@ -114,6 +114,8 @@ The following methods have been added: @@ -114,6 +114,8 @@ The following methods have been added:
114 - GCOMSelection::phase_curve() 114 - GCOMSelection::phase_curve()
115 - GCOMSelection::phases() 115 - GCOMSelection::phases()
116 - GCOMSelection::fpmtflag() 116 - GCOMSelection::fpmtflag()
  117 +- GCOMSelection::use_d1()
  118 +- GCOMSelection::use_d2()
117 - gammalib::tmpnam() 119 - gammalib::tmpnam()
118 - gammalib::compare() 120 - gammalib::compare()
119 - gammalib::xml_check_parnum() 121 - gammalib::xml_check_parnum()
@@ -389,6 +391,11 @@ spatial model gradients (#3203). @@ -389,6 +391,11 @@ spatial model gradients (#3203).
389 391
390 22. COMPTEL interface 392 22. COMPTEL interface
391 --------------------- 393 ---------------------
  394 +Added GCOMSelection::use_d1() and GCOMSelection::use_d2() methods to control the usage
  395 +of D1 and D2 modules. The control logic was implemented in GCOMDri and header keywords
  396 +with per module information are now written into the DRE FITS files. A D1 and D2
  397 +module usage string is also written into DRE and DRG files (#3917).
  398 +
392 Added GCOMSelection::fpmtflag() methods to select the method how D2 modules with 399 Added GCOMSelection::fpmtflag() methods to select the method how D2 modules with
393 failed PMTs will be handled. If the flag is set to 0, D2 modules with failed PMTs 400 failed PMTs will be handled. If the flag is set to 0, D2 modules with failed PMTs
394 will be discarded, if set to 1 modules with failed PMT will be included, and if set 401 will be discarded, if set to 1 modules with failed PMT will be included, and if set
README.md
1 GammaLib information 1 GammaLib information
2 ==================== 2 ====================
3 -* Version: 2.0.0.dev (1 December 2021) 3 +* Version: 2.0.0.dev (2 December 2021)
4 4
5 [![Build Status](https://cta-jenkins.irap.omp.eu/buildStatus/icon?job=gammalib-integrate-os)](https://cta-jenkins.irap.omp.eu/job/gammalib-integrate-os/) 5 [![Build Status](https://cta-jenkins.irap.omp.eu/buildStatus/icon?job=gammalib-integrate-os)](https://cta-jenkins.irap.omp.eu/job/gammalib-integrate-os/)
6 6
doc/source/admin/release_history/2.0.rst
1 .. _2.0: 1 .. _2.0:
2 2
3 -GammaLib 2.0 release (30 November 2021)  
4 -======================================= 3 +GammaLib 2.0 release (2 December 2021)
  4 +======================================
5 5
6 Overview 6 Overview
7 -------- 7 --------
@@ -37,6 +37,8 @@ Bug fixes @@ -37,6 +37,8 @@ Bug fixes
37 Improvements 37 Improvements
38 ------------ 38 ------------
39 39
  40 +* [`3917 <https://cta-redmine.irap.omp.eu/issues/3913>`_] -
  41 + Add ``GCOMSelection::fpmtflag()``, ``GCOMSelection::use_d1()`` and ``GCOMSelection::use_d2()`` methods
40 * [`3913 <https://cta-redmine.irap.omp.eu/issues/3913>`_] - 42 * [`3913 <https://cta-redmine.irap.omp.eu/issues/3913>`_] -
41 Add ``GCOMModelDRBPhibarBins`` class 43 Add ``GCOMModelDRBPhibarBins`` class
42 * [`3912 <https://cta-redmine.irap.omp.eu/issues/3912>`_] - 44 * [`3912 <https://cta-redmine.irap.omp.eu/issues/3912>`_] -
inst/com/include/GCOMSelection.hpp
@@ -97,6 +97,10 @@ public: @@ -97,6 +97,10 @@ public:
97 void vetoflag_max(const int& vetoflag_max); 97 void vetoflag_max(const int& vetoflag_max);
98 const int& fpmtflag(void) const; 98 const int& fpmtflag(void) const;
99 void fpmtflag(const int& fpmtflag); 99 void fpmtflag(const int& fpmtflag);
  100 + const bool& use_d1(const int& id1) const;
  101 + void use_d1(const int& id1, const bool& use);
  102 + const bool& use_d2(const int& id2) const;
  103 + void use_d2(const int& id2, const bool& use);
100 const GModelTemporalPhaseCurve& phase_curve(void) const; 104 const GModelTemporalPhaseCurve& phase_curve(void) const;
101 void phase_curve(const GModelTemporalPhaseCurve& phase_curve); 105 void phase_curve(const GModelTemporalPhaseCurve& phase_curve);
102 const GPhases& phases(void) const; 106 const GPhases& phases(void) const;
@@ -128,6 +132,8 @@ protected: @@ -128,6 +132,8 @@ protected:
128 int m_fpmtflag; //!< D2 PMT failures 132 int m_fpmtflag; //!< D2 PMT failures
129 //!< (0: exclude modules, 1: include modules, 133 //!< (0: exclude modules, 1: include modules,
130 //!< 2: use FPM information) 134 //!< 2: use FPM information)
  135 + bool m_use_d1[7]; //!< D1 module usage
  136 + bool m_use_d2[14]; //!< D2 module usage
131 GModelTemporalPhaseCurve m_phase_curve; //!< Phase curve for phase selection 137 GModelTemporalPhaseCurve m_phase_curve; //!< Phase curve for phase selection
132 GPhases m_phases; //!< Phases for phase selection 138 GPhases m_phases; //!< Phases for phase selection
133 139
@@ -154,6 +160,8 @@ protected: @@ -154,6 +160,8 @@ protected:
154 mutable int m_num_d1module_off; //!< Number of events excluded since D1 module off 160 mutable int m_num_d1module_off; //!< Number of events excluded since D1 module off
155 mutable int m_num_d2module_off; //!< Number of events excluded since D2 module off 161 mutable int m_num_d2module_off; //!< Number of events excluded since D2 module off
156 mutable int m_num_fpmt; //!< Number of events excluded due to failed PMT 162 mutable int m_num_fpmt; //!< Number of events excluded due to failed PMT
  163 + mutable int m_num_d1[7]; //!< Number of events per D1 module
  164 + mutable int m_num_d2[14]; //!< Number of events per D2 module
157 }; 165 };
158 166
159 167
inst/com/pyext/GCOMSelection.i
@@ -80,6 +80,10 @@ public: @@ -80,6 +80,10 @@ public:
80 void vetoflag_max(const int& vetoflag_max); 80 void vetoflag_max(const int& vetoflag_max);
81 const int& fpmtflag(void) const; 81 const int& fpmtflag(void) const;
82 void fpmtflag(const int& fpmtflag); 82 void fpmtflag(const int& fpmtflag);
  83 + const bool& use_d1(const int& id1) const;
  84 + void use_d1(const int& id1, const bool& use);
  85 + const bool& use_d2(const int& id2) const;
  86 + void use_d2(const int& id2, const bool& use);
83 const GModelTemporalPhaseCurve& phase_curve(void) const; 87 const GModelTemporalPhaseCurve& phase_curve(void) const;
84 void phase_curve(const GModelTemporalPhaseCurve& phase_curve); 88 void phase_curve(const GModelTemporalPhaseCurve& phase_curve);
85 const GPhases& phases(void) const; 89 const GPhases& phases(void) const;
inst/com/src/GCOMDri.cpp
@@ -1309,12 +1309,33 @@ void GCOMDri::write_attributes(GFitsHDU* hdu) const @@ -1309,12 +1309,33 @@ void GCOMDri::write_attributes(GFitsHDU* hdu) const
1309 } 1309 }
1310 1310
1311 // If there was an event seletion then write selection set. Otherwise write 1311 // If there was an event seletion then write selection set. Otherwise write
1312 - // handling of D2 PMT failures. 1312 + // handling D1 and D2 module usage and handling mode of D2 PMT failures.
1313 if (m_has_selection) { 1313 if (m_has_selection) {
1314 m_selection.write(*hdu); 1314 m_selection.write(*hdu);
1315 } 1315 }
1316 else { 1316 else {
  1317 +
  1318 + // Write D2 PMT failure handling flag
1317 hdu->card("D2FPMT", m_selection.fpmtflag(), "D2 PMT failure handling"); 1319 hdu->card("D2FPMT", m_selection.fpmtflag(), "D2 PMT failure handling");
  1320 +
  1321 + // Write D1 module usage
  1322 + std::string d1use = "0000000";
  1323 + for (int i = 0; i < 7; ++i) {
  1324 + if (m_selection.use_d1(i)) {
  1325 + d1use[i] = '1';
  1326 + }
  1327 + }
  1328 + hdu->card("D1USE", d1use, "D1 module usage");
  1329 +
  1330 + // Write D2 module usage
  1331 + std::string d2use = "00000000000000";
  1332 + for (int i = 0; i < 14; ++i) {
  1333 + if (m_selection.use_d2(i)) {
  1334 + d2use[i] = '1';
  1335 + }
  1336 + }
  1337 + hdu->card("D2USE", d2use, "D2 module usage");
  1338 +
1318 } 1339 }
1319 1340
1320 // If there was a valid Earth horizon cut then write it 1341 // If there was a valid Earth horizon cut then write it
@@ -1407,6 +1428,11 @@ double GCOMDri::compute_geometry(const int&amp; tjd, @@ -1407,6 +1428,11 @@ double GCOMDri::compute_geometry(const int&amp; tjd,
1407 // Loop over all D2 modules 1428 // Loop over all D2 modules
1408 for (int id2 = 0; id2 < 14; ++id2) { 1429 for (int id2 = 0; id2 < 14; ++id2) {
1409 1430
  1431 + // Skip if coresponding modules should not be used
  1432 + if (!select.use_d1(id1) || !select.use_d2(id2)) {
  1433 + continue;
  1434 + }
  1435 +
1410 // Get D2 module status 1436 // Get D2 module status
1411 int d2status = status.d2status(tjd, id2+1); 1437 int d2status = status.d2status(tjd, id2+1);
1412 1438
inst/com/src/GCOMSelection.cpp
@@ -37,6 +37,10 @@ @@ -37,6 +37,10 @@
37 37
38 /* __ Method name definitions ____________________________________________ */ 38 /* __ Method name definitions ____________________________________________ */
39 #define G_FPMTFLAG "GCOMSelection::fpmtflag(int&)" 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&)"
40 44
41 /* __ Macros _____________________________________________________________ */ 45 /* __ Macros _____________________________________________________________ */
42 46
@@ -190,6 +194,12 @@ void GCOMSelection::init_statistics(void) const @@ -190,6 +194,12 @@ void GCOMSelection::init_statistics(void) const
190 m_num_d1module_off = 0; 194 m_num_d1module_off = 0;
191 m_num_d2module_off = 0; 195 m_num_d2module_off = 0;
192 m_num_fpmt = 0; 196 m_num_fpmt = 0;
  197 + for (int i = 0; i < 7; ++i) {
  198 + m_num_d1[i] = 0;
  199 + }
  200 + for (int i = 0; i < 14; ++i) {
  201 + m_num_d2[i] = 0;
  202 + }
193 203
194 // Return 204 // Return
195 return; 205 return;
@@ -304,9 +314,19 @@ bool GCOMSelection::use_event(const GCOMEventAtom&amp; event) const @@ -304,9 +314,19 @@ bool GCOMSelection::use_event(const GCOMEventAtom&amp; event) const
304 int d1status = status.d1status(tjd, id1); 314 int d1status = status.d1status(tjd, id1);
305 int d2status = status.d2status(tjd, id2); 315 int d2status = status.d2status(tjd, id2);
306 316
  317 + // Exclude event if the coresponding modules should not be used
  318 + if (!m_use_d1[id1-1]) {
  319 + m_num_d1module_off++;
  320 + use = false;
  321 + }
  322 + else if (!m_use_d2[id2-1]) {
  323 + m_num_d2module_off++;
  324 + use = false;
  325 + }
  326 +
307 // Exclude event if the corresponding modules are signalled 327 // Exclude event if the corresponding modules are signalled
308 // as off 328 // as off
309 - if (d1status != 1) { 329 + else if (d1status != 1) {
310 m_num_d1module_off++; 330 m_num_d1module_off++;
311 use = false; 331 use = false;
312 } 332 }
@@ -319,16 +339,18 @@ bool GCOMSelection::use_event(const GCOMEventAtom&amp; event) const @@ -319,16 +339,18 @@ bool GCOMSelection::use_event(const GCOMEventAtom&amp; event) const
319 // failure flag 339 // failure flag
320 else if (d2status > 1) { 340 else if (d2status > 1) {
321 341
322 - // If failure flag = 0 then reject event 342 + // If failure flag = 0 then reject event and signal that the
  343 + // module was off
323 if (m_fpmtflag == 0) { 344 if (m_fpmtflag == 0) {
324 - m_num_fpmt++; 345 + m_num_d2module_off++;
325 use = false; 346 use = false;
326 } 347 }
327 348
328 // ... otherwise if failure flag = 2 and the module has a 349 // ... otherwise if failure flag = 2 and the module has a
329 // valid exclusion circle then reject event if it is 350 // valid exclusion circle then reject event if it is
330 // within the exclusion circle; if the module has no 351 // within the exclusion circle; if the module has no
331 - // exclusion region then reject the entire module. 352 + // exclusion region then reject the entire module and
  353 + // signal that it was off.
332 else if (m_fpmtflag == 2) { 354 else if (m_fpmtflag == 2) {
333 double r = gammalib::com_exd2r(id2); 355 double r = gammalib::com_exd2r(id2);
334 if (r >= 0.1) { 356 if (r >= 0.1) {
@@ -342,7 +364,7 @@ bool GCOMSelection::use_event(const GCOMEventAtom&amp; event) const @@ -342,7 +364,7 @@ bool GCOMSelection::use_event(const GCOMEventAtom&amp; event) const
342 } 364 }
343 } 365 }
344 else { 366 else {
345 - m_num_fpmt++; 367 + m_num_d2module_off++;
346 use = false; 368 use = false;
347 } 369 }
348 } 370 }
@@ -353,7 +375,16 @@ bool GCOMSelection::use_event(const GCOMEventAtom&amp; event) const @@ -353,7 +375,16 @@ bool GCOMSelection::use_event(const GCOMEventAtom&amp; event) const
353 375
354 // Update acceptance and rejection statistics 376 // Update acceptance and rejection statistics
355 if (use) { 377 if (use) {
  378 +
  379 + // Extract module IDs from MODCOM
  380 + int id2 = (event.modcom()-1)/7 + 1; // [1-14]
  381 + int id1 = event.modcom() - (id2-1) * 7; // [1-7]
  382 +
  383 + // Update statistics
356 m_num_events_used++; 384 m_num_events_used++;
  385 + m_num_d1[id1-1]++;
  386 + m_num_d2[id2-1]++;
  387 +
357 } 388 }
358 else { 389 else {
359 m_num_events_rejected++; 390 m_num_events_rejected++;
@@ -395,6 +426,96 @@ void GCOMSelection::fpmtflag(const int&amp; fpmtflag) @@ -395,6 +426,96 @@ void GCOMSelection::fpmtflag(const int&amp; fpmtflag)
395 426
396 427
397 /***********************************************************************//** 428 /***********************************************************************//**
  429 + * @brief Return D1 module usage flag
  430 + *
  431 + * @param[in] id1 D1 module identifier [0,...,6].
  432 + * @return True if D1 module @p id1 should be used.
  433 + ***************************************************************************/
  434 +const bool& GCOMSelection::use_d1(const int& id1) const
  435 +{
  436 + // Check module validity range
  437 + if (id1 < 0 or id1 > 6) {
  438 + std::string msg = "Invalid D1 module identifier "+gammalib::str(id1)+
  439 + " specified. The D1 module identifier needs to be "
  440 + "comprised within 0 and 6.";
  441 + throw GException::invalid_argument(G_USE_D1_GET, msg);
  442 + }
  443 +
  444 + // Return usage flag
  445 + return (m_use_d1[id1]);
  446 +}
  447 +
  448 +
  449 +/***********************************************************************//**
  450 + * @brief Set D1 module usage flag
  451 + *
  452 + * @param[in] id1 D1 module identifier [0,...,6].
  453 + * @param[in] use D1 module usage.
  454 + ***************************************************************************/
  455 +void GCOMSelection::use_d1(const int& id1, const bool& use)
  456 +{
  457 + // Check module validity range
  458 + if (id1 < 0 or id1 > 6) {
  459 + std::string msg = "Invalid D1 module identifier "+gammalib::str(id1)+
  460 + " specified. The D1 module identifier needs to be "
  461 + "comprised within 0 and 6.";
  462 + throw GException::invalid_argument(G_USE_D1_SET, msg);
  463 + }
  464 +
  465 + // Set usage flag
  466 + m_use_d1[id1] = use;
  467 +
  468 + // Return
  469 + return;
  470 +}
  471 +
  472 +
  473 +/***********************************************************************//**
  474 + * @brief Return D2 module usage flag
  475 + *
  476 + * @param[in] id2 D2 module identifier [0,...,13].
  477 + * @return True if D2 module @p id2 should be used.
  478 + ***************************************************************************/
  479 +const bool& GCOMSelection::use_d2(const int& id2) const
  480 +{
  481 + // Check module validity range
  482 + if (id2 < 0 or id2 > 13) {
  483 + std::string msg = "Invalid D2 module identifier "+gammalib::str(id2)+
  484 + " specified. The D2 module identifier needs to be "
  485 + "comprised within 0 and 13.";
  486 + throw GException::invalid_argument(G_USE_D2_GET, msg);
  487 + }
  488 +
  489 + // Return usage flag
  490 + return (m_use_d2[id2]);
  491 +}
  492 +
  493 +
  494 +/***********************************************************************//**
  495 + * @brief Set D2 module usage flag
  496 + *
  497 + * @param[in] id2 D2 module identifier [0,...,13].
  498 + * @param[in] use D2 module usage.
  499 + ***************************************************************************/
  500 +void GCOMSelection::use_d2(const int& id2, const bool& use)
  501 +{
  502 + // Check module validity range
  503 + if (id2 < 0 or id2 > 13) {
  504 + std::string msg = "Invalid D2 module identifier "+gammalib::str(id2)+
  505 + " specified. The D2 module identifier needs to be "
  506 + "comprised within 0 and 13.";
  507 + throw GException::invalid_argument(G_USE_D2_SET, msg);
  508 + }
  509 +
  510 + // Set usage flag
  511 + m_use_d2[id2] = use;
  512 +
  513 + // Return
  514 + return;
  515 +}
  516 +
  517 +
  518 +/***********************************************************************//**
398 * @brief Read selection set from FITS HDU keywords 519 * @brief Read selection set from FITS HDU keywords
399 * 520 *
400 * @param[in] hdu FITS HDU. 521 * @param[in] hdu FITS HDU.
@@ -425,7 +546,6 @@ void GCOMSelection::read(const GFitsHDU&amp; hdu) @@ -425,7 +546,6 @@ void GCOMSelection::read(const GFitsHDU&amp; hdu)
425 m_psd_max = hdu.real("PSDMAX"); 546 m_psd_max = hdu.real("PSDMAX");
426 } 547 }
427 548
428 -  
429 // Read Earth horizon angle - Phibar selection 549 // Read Earth horizon angle - Phibar selection
430 if (hdu.has_card("ZETMIN") && hdu.has_card("ZETMAX")) { 550 if (hdu.has_card("ZETMIN") && hdu.has_card("ZETMAX")) {
431 m_zeta_min = hdu.real("ZETMIN"); 551 m_zeta_min = hdu.real("ZETMIN");
@@ -449,6 +569,26 @@ void GCOMSelection::read(const GFitsHDU&amp; hdu) @@ -449,6 +569,26 @@ void GCOMSelection::read(const GFitsHDU&amp; hdu)
449 m_fpmtflag = hdu.integer("D2FPMT"); 569 m_fpmtflag = hdu.integer("D2FPMT");
450 } 570 }
451 571
  572 + // Read D1 module usage flag
  573 + if (hdu.has_card("D1USE")) {
  574 + std::string use = gammalib::strip_whitespace(hdu.string("D1USE"));
  575 + if (use.length() == 7) {
  576 + for (int i = 0; i < 7; ++i) {
  577 + m_use_d1[i] = (use[i] == '1');
  578 + }
  579 + }
  580 + }
  581 +
  582 + // Read D2 module usage flag
  583 + if (hdu.has_card("D2USE")) {
  584 + std::string use = gammalib::strip_whitespace(hdu.string("D2USE"));
  585 + if (use.length() == 14) {
  586 + for (int i = 0; i < 14; ++i) {
  587 + m_use_d2[i] = (use[i] == '1');
  588 + }
  589 + }
  590 + }
  591 +
452 // Read selection statistics 592 // Read selection statistics
453 if (hdu.has_card("NEVCHK")) { 593 if (hdu.has_card("NEVCHK")) {
454 m_num_events_checked = hdu.integer("NEVCHK"); 594 m_num_events_checked = hdu.integer("NEVCHK");
@@ -490,6 +630,18 @@ void GCOMSelection::read(const GFitsHDU&amp; hdu) @@ -490,6 +630,18 @@ void GCOMSelection::read(const GFitsHDU&amp; hdu)
490 if (hdu.has_card("NNOSCT")) { 630 if (hdu.has_card("NNOSCT")) {
491 m_num_no_scatter = hdu.integer("NNOSCT"); 631 m_num_no_scatter = hdu.integer("NNOSCT");
492 } 632 }
  633 + for (int i = 0; i < 7; ++i) {
  634 + std::string key = "ND1-"+gammalib::str(i+1,"%2.2d");
  635 + if (hdu.has_card(key)) {
  636 + m_num_d1[i] = hdu.integer(key);
  637 + }
  638 + }
  639 + for (int i = 0; i < 14; ++i) {
  640 + std::string key = "ND2-"+gammalib::str(i+1,"%2.2d");
  641 + if (hdu.has_card(key)) {
  642 + m_num_d2[i] = hdu.integer(key);
  643 + }
  644 + }
493 if (hdu.has_card("ND1OFF")) { 645 if (hdu.has_card("ND1OFF")) {
494 m_num_d1module_off = hdu.integer("ND1OFF"); 646 m_num_d1module_off = hdu.integer("ND1OFF");
495 } 647 }
@@ -543,6 +695,24 @@ void GCOMSelection::write(GFitsHDU&amp; hdu) const @@ -543,6 +695,24 @@ void GCOMSelection::write(GFitsHDU&amp; hdu) const
543 // Write D2 PMT failure handling flag 695 // Write D2 PMT failure handling flag
544 hdu.card("D2FPMT", m_fpmtflag, "D2 PMT failure handling"); 696 hdu.card("D2FPMT", m_fpmtflag, "D2 PMT failure handling");
545 697
  698 + // Write D1 module usage
  699 + std::string d1use = "0000000";
  700 + for (int i = 0; i < 7; ++i) {
  701 + if (m_use_d1[i]) {
  702 + d1use[i] = '1';
  703 + }
  704 + }
  705 + hdu.card("D1USE", d1use, "D1 module usage");
  706 +
  707 + // Write D2 module usage
  708 + std::string d2use = "00000000000000";
  709 + for (int i = 0; i < 14; ++i) {
  710 + if (m_use_d2[i]) {
  711 + d2use[i] = '1';
  712 + }
  713 + }
  714 + hdu.card("D2USE", d2use, "D2 module usage");
  715 +
546 // Write selection statistics 716 // Write selection statistics
547 hdu.card("NEVCHK", m_num_events_checked, "Number of checked events"); 717 hdu.card("NEVCHK", m_num_events_checked, "Number of checked events");
548 hdu.card("NEVUSE", m_num_events_used, "Number of used events"); 718 hdu.card("NEVUSE", m_num_events_used, "Number of used events");
@@ -563,6 +733,16 @@ void GCOMSelection::write(GFitsHDU&amp; hdu) const @@ -563,6 +733,16 @@ void GCOMSelection::write(GFitsHDU&amp; hdu) const
563 hdu.card("NVFLHI", m_num_vetoflag_max, "Number of events > VFLMAX"); 733 hdu.card("NVFLHI", m_num_vetoflag_max, "Number of events > VFLMAX");
564 hdu.card("NNOSCT", m_num_no_scatter, "Number of events w/o scatter angle"); 734 hdu.card("NNOSCT", m_num_no_scatter, "Number of events w/o scatter angle");
565 hdu.card("NINVMT", m_num_invalid_modcom, "Number of events with invalid minitelescope"); 735 hdu.card("NINVMT", m_num_invalid_modcom, "Number of events with invalid minitelescope");
  736 + for (int i = 0; i < 7; ++i) {
  737 + std::string key = "ND1-"+gammalib::str(i+1,"%2.2d");
  738 + std::string com = "Number of events in D1 module "+gammalib::str(i+1);
  739 + hdu.card(key, m_num_d1[i], com);
  740 + }
  741 + for (int i = 0; i < 14; ++i) {
  742 + std::string key = "ND2-"+gammalib::str(i+1,"%2.2d");
  743 + std::string com = "Number of events in D2 module "+gammalib::str(i+1);
  744 + hdu.card(key, m_num_d2[i], com);
  745 + }
566 hdu.card("ND1OFF", m_num_d1module_off, "Number of events with D1 module off"); 746 hdu.card("ND1OFF", m_num_d1module_off, "Number of events with D1 module off");
567 hdu.card("ND2OFF", m_num_d2module_off, "Number of events with D2 module off"); 747 hdu.card("ND2OFF", m_num_d2module_off, "Number of events with D2 module off");
568 hdu.card("ND2FPM", m_num_fpmt, "Number of events excluded due to failed PMTs"); 748 hdu.card("ND2FPM", m_num_fpmt, "Number of events excluded due to failed PMTs");
@@ -646,6 +826,30 @@ std::string GCOMSelection::print(const GChatter&amp; chatter) const @@ -646,6 +826,30 @@ std::string GCOMSelection::print(const GChatter&amp; chatter) const
646 result.append(gammalib::str(m_vetoflag_max)+"] < "); 826 result.append(gammalib::str(m_vetoflag_max)+"] < ");
647 result.append(gammalib::str(m_num_vetoflag_max)); 827 result.append(gammalib::str(m_num_vetoflag_max));
648 828
  829 + // Append D1 module usage
  830 + for (int i = 0; i < 7; ++i) {
  831 + result.append("\n"+gammalib::parformat("D1 module "+gammalib::str(i+1)));
  832 + result.append(gammalib::str(m_num_d1[i]));
  833 + if (m_use_d1[i]) {
  834 + result.append(" [use]");
  835 + }
  836 + else {
  837 + result.append(" [don't use]");
  838 + }
  839 + }
  840 +
  841 + // Append D2 module usage
  842 + for (int i = 0; i < 14; ++i) {
  843 + result.append("\n"+gammalib::parformat("D2 module "+gammalib::str(i+1)));
  844 + result.append(gammalib::str(m_num_d2[i]));
  845 + if (m_use_d2[i]) {
  846 + result.append(" [use]");
  847 + }
  848 + else {
  849 + result.append(" [don't use]");
  850 + }
  851 + }
  852 +
649 // Append D1 module off 853 // Append D1 module off
650 result.append("\n"+gammalib::parformat("D1 modules off")); 854 result.append("\n"+gammalib::parformat("D1 modules off"));
651 result.append(gammalib::str(m_num_d1module_off)); 855 result.append(gammalib::str(m_num_d1module_off));
@@ -707,6 +911,12 @@ void GCOMSelection::init_members(void) @@ -707,6 +911,12 @@ void GCOMSelection::init_members(void)
707 m_fpmtflag = 0; //!< D2 PMT failure flag 911 m_fpmtflag = 0; //!< D2 PMT failure flag
708 m_phase_curve.clear(); 912 m_phase_curve.clear();
709 m_phases.clear(); 913 m_phases.clear();
  914 + for (int i = 0; i < 7; ++i) {
  915 + m_use_d1[i] = true;
  916 + }
  917 + for (int i = 0; i < 14; ++i) {
  918 + m_use_d2[i] = true;
  919 + }
710 920
711 // Initialise statistics 921 // Initialise statistics
712 init_statistics(); 922 init_statistics();
@@ -741,6 +951,12 @@ void GCOMSelection::copy_members(const GCOMSelection&amp; select) @@ -741,6 +951,12 @@ void GCOMSelection::copy_members(const GCOMSelection&amp; select)
741 m_fpmtflag = select.m_fpmtflag; 951 m_fpmtflag = select.m_fpmtflag;
742 m_phase_curve = select.m_phase_curve; 952 m_phase_curve = select.m_phase_curve;
743 m_phases = select.m_phases; 953 m_phases = select.m_phases;
  954 + for (int i = 0; i < 7; ++i) {
  955 + m_use_d1[i] = select.m_use_d1[i];
  956 + }
  957 + for (int i = 0; i < 14; ++i) {
  958 + m_use_d2[i] = select.m_use_d2[i];
  959 + }
744 960
745 // Copy statistics 961 // Copy statistics
746 m_num_events_checked = select.m_num_events_checked; 962 m_num_events_checked = select.m_num_events_checked;
@@ -766,6 +982,14 @@ void GCOMSelection::copy_members(const GCOMSelection&amp; select) @@ -766,6 +982,14 @@ void GCOMSelection::copy_members(const GCOMSelection&amp; select)
766 m_num_d2module_off = select.m_num_d2module_off; 982 m_num_d2module_off = select.m_num_d2module_off;
767 m_num_fpmt = select.m_num_fpmt; 983 m_num_fpmt = select.m_num_fpmt;
768 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 +
769 // Return 993 // Return
770 return; 994 return;
771 } 995 }