Commit 9261f32030e3b886359ac0df9e55a051f86d4ccf
1 parent
b0b38ecb
Implement phibar-dependent rate weighting for DRW
Showing
3 changed files
with
638 additions
and
239 deletions
inst/com/include/GCOMDris.hpp
... | ... | @@ -34,6 +34,9 @@ |
34 | 34 | #include "GContainer.hpp" |
35 | 35 | |
36 | 36 | /* __ Forward declarations _______________________________________________ */ |
37 | +class GCOMObservation; | |
38 | +class GCOMEventList; | |
39 | +class GCOMSelection; | |
37 | 40 | |
38 | 41 | /* __ Constants __________________________________________________________ */ |
39 | 42 | |
... | ... | @@ -75,7 +78,9 @@ public: |
75 | 78 | void extend(const GCOMDris& dris); |
76 | 79 | void compute_drws(const GCOMObservation& obs, |
77 | 80 | const GCOMSelection& select = GCOMSelection(), |
78 | - const double& zetamin = 5.0); | |
81 | + const double& zetamin = 5.0, | |
82 | + const double& timebin = 300.0, | |
83 | + const std::string& method = "phibar"); | |
79 | 84 | std::string print(const GChatter& chatter = NORMAL) const; |
80 | 85 | |
81 | 86 | protected: |
... | ... | @@ -83,6 +88,16 @@ protected: |
83 | 88 | void init_members(void); |
84 | 89 | void copy_members(const GCOMDris& dris); |
85 | 90 | void free_members(void); |
91 | + void compute_drws_energy(const GCOMObservation& obs, | |
92 | + const GCOMEventList* events, | |
93 | + const GCOMSelection& select = GCOMSelection(), | |
94 | + const double& zetamin = 5.0, | |
95 | + const double& timebin = 300.0); | |
96 | + void compute_drws_phibar(const GCOMObservation& obs, | |
97 | + const GCOMEventList* events, | |
98 | + const GCOMSelection& select = GCOMSelection(), | |
99 | + const double& zetamin = 5.0, | |
100 | + const double& timebin = 300.0); | |
86 | 101 | |
87 | 102 | // Protected data members |
88 | 103 | std::vector<GCOMDri> m_dris; //!< Data space instances | ... | ... |
inst/com/pyext/GCOMDris.i
... | ... | @@ -55,7 +55,9 @@ public: |
55 | 55 | void extend(const GCOMDris& dris); |
56 | 56 | void compute_drws(const GCOMObservation& obs, |
57 | 57 | const GCOMSelection& select = GCOMSelection(), |
58 | - const double& zetamin = 5.0); | |
58 | + const double& zetamin = 5.0, | |
59 | + const double& timebin = 300.0, | |
60 | + const std::string& method = "phibar"); | |
59 | 61 | }; |
60 | 62 | |
61 | 63 | ... | ... |
inst/com/src/GCOMDris.cpp
... | ... | @@ -39,14 +39,16 @@ |
39 | 39 | #include "GCOMTim.hpp" |
40 | 40 | #include "GCOMStatus.hpp" |
41 | 41 | #include "GCOMObservation.hpp" |
42 | +#include "GCOMEventList.hpp" | |
43 | +#include "GCOMEventAtom.hpp" | |
42 | 44 | #include "GCOMSelection.hpp" |
43 | 45 | |
44 | 46 | /* __ Method name definitions ____________________________________________ */ |
45 | 47 | #define G_AT "GCOMDris::at(int&)" |
46 | 48 | #define G_INSERT "GCOMDris::insert(int&, GCOMDri&)" |
47 | 49 | #define G_REMOVE "GCOMDris::remove(int&)" |
48 | -#define G_COMPUTE_DRWS "GCOMDris::compute_drws(GCOMObservation&, "\ | |
49 | - "GCOMSelection&, double&)" | |
50 | +#define G_COMPUTE_DRWS "GCOMDris::compute_drws(GCOMObservation&,"\ | |
51 | + " GCOMSelection&, double&, double&, std::string&)" | |
50 | 52 | |
51 | 53 | /* __ Macros _____________________________________________________________ */ |
52 | 54 | |
... | ... | @@ -55,6 +57,9 @@ |
55 | 57 | /* __ Debug definitions __________________________________________________ */ |
56 | 58 | #define G_DEBUG_COMPUTE_DRWS |
57 | 59 | |
60 | +/* __ Constants __________________________________________________________ */ | |
61 | +const double superpacket_duration = 16.384; // Duration of superpacket (s) | |
62 | + | |
58 | 63 | |
59 | 64 | /*========================================================================== |
60 | 65 | = = |
... | ... | @@ -338,11 +343,13 @@ void GCOMDris::extend(const GCOMDris& dris) |
338 | 343 | |
339 | 344 | |
340 | 345 | /***********************************************************************//** |
341 | - * @brief Compute backgroud weighting cubes | |
346 | + * @brief Compute background weighting cubes | |
342 | 347 | * |
343 | 348 | * @param[in] obs COMPTEL observation. |
344 | 349 | * @param[in] select Selection set. |
345 | 350 | * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg). |
351 | + * @param[in] timebin Time binning for rate determination (sec). | |
352 | + * @param[in] method Method to compute DRWs ("energy" or "phibar"). | |
346 | 353 | * |
347 | 354 | * @exception GException::invalid_value |
348 | 355 | * DRW with mismatching definition encountered in container. |
... | ... | @@ -350,34 +357,18 @@ void GCOMDris::extend(const GCOMDris& dris) |
350 | 357 | * No event list found in COMPTEL observation. |
351 | 358 | * |
352 | 359 | * Compute DRW cubes for a COMPTEL observation. DRW cubes are event-rate |
353 | - * weighted geometry cubes, where event rate are time and energy-dependent. | |
354 | - * | |
355 | - * Three hard-wired energy ranges are defined for which the event rate is | |
356 | - * determined on a 5 minutes basis: | |
357 | - * | |
358 | - * E < 1.8 MeV | |
359 | - * 1.8 < E < 4.3 MeV | |
360 | - * E > 4.3 MeV | |
361 | - * | |
362 | - * For each superpacket, these event rates are linearly interpolated to the | |
363 | - * relevant superpacket time. | |
360 | + * weighted geometry cubes which were multiplied by the solid angle of | |
361 | + * the (Chi,Psi) pixels. | |
364 | 362 | * |
365 | 363 | * The DRW cubes are normalised so that the sum of each Phibar layer equals |
366 | 364 | * to unity. |
367 | 365 | ***************************************************************************/ |
368 | 366 | void GCOMDris::compute_drws(const GCOMObservation& obs, |
369 | 367 | const GCOMSelection& select, |
370 | - const double& zetamin) | |
368 | + const double& zetamin, | |
369 | + const double& timebin, | |
370 | + const std::string& method) | |
371 | 371 | { |
372 | - // Debug | |
373 | - #if defined(G_DEBUG_COMPUTE_DRWS) | |
374 | - std::cout << "GCOMDris::compute_drws" << std::endl; | |
375 | - std::cout << "======================" << std::endl; | |
376 | - #endif | |
377 | - | |
378 | - // Set constants | |
379 | - const double dtime = 5.0 * 60.0; // Event rate integration time in seconds | |
380 | - | |
381 | 372 | // Continue only if there are DRWs in container |
382 | 373 | if (!is_empty()) { |
383 | 374 | |
... | ... | @@ -387,9 +378,6 @@ void GCOMDris::compute_drws(const GCOMObservation& obs, |
387 | 378 | std::cout << "--------------" << std::endl; |
388 | 379 | #endif |
389 | 380 | |
390 | - // Initialise D1 & D2 module status | |
391 | - GCOMStatus status; | |
392 | - | |
393 | 381 | // Get pointer to first DRW in container (for convenient access to |
394 | 382 | // members of GCOMDri; we won't use it for modifications, hence we |
395 | 383 | // can declare it as constant) |
... | ... | @@ -433,219 +421,16 @@ void GCOMDris::compute_drws(const GCOMObservation& obs, |
433 | 421 | throw GException::invalid_argument(G_COMPUTE_DRWS, msg); |
434 | 422 | } |
435 | 423 | |
436 | - // Debug | |
437 | - #if defined(G_DEBUG_COMPUTE_DRWS) | |
438 | - std::cout << "Determine energy-dependent event rates" << std::endl; | |
439 | - std::cout << "--------------------------------------" << std::endl; | |
440 | - #endif | |
441 | - | |
442 | - // Initialise current time and vectors for computation of node function | |
443 | - // and vectors for energy-dependent rate interpolation | |
444 | - double time; | |
445 | - double rate0 = 0.0; | |
446 | - double rate1 = 0.0; | |
447 | - double rate2 = 0.0; | |
448 | - GNodeArray times; | |
449 | - std::vector<double> rates0; | |
450 | - std::vector<double> rates1; | |
451 | - std::vector<double> rates2; | |
452 | - | |
453 | - // Set time of first event | |
454 | - if (events->size() > 0) { | |
455 | - time = (*events)[0]->time().secs(); | |
424 | + // Method A: energy-dependent weighting | |
425 | + if (method == "energy") { | |
426 | + compute_drws_energy(obs, events, select, zetamin, timebin); | |
456 | 427 | } |
457 | 428 | |
458 | - // Determine energy-dependent event rates. The standard event selection | |
459 | - // criteria and earth horizon cut is applied so that the event rate | |
460 | - // corresponds to the current selection, yet we do not consider any | |
461 | - // Good Time Intervals or OAD time information as we later only access | |
462 | - // relevant times (YET THERE COULD BE AN ISSUE WITH A GLITCH). Rates | |
463 | - // are computed for three hard-coded energy intervals. | |
464 | - for (int i_evt = 0; i_evt < events->size(); ++i_evt) { | |
465 | - | |
466 | - // Get pointer to event | |
467 | - const GCOMEventAtom* event = (*events)[i_evt]; | |
468 | - | |
469 | - // Apply event selection | |
470 | - if (!select.use_event(*event)) { | |
471 | - continue; | |
472 | - } | |
473 | - | |
474 | - // Apply Earth horizon cut | |
475 | - if ((event->eha() - event->phibar()) < zetamin) { | |
476 | - continue; | |
477 | - } | |
478 | - | |
479 | - // If time exceeds time bin then add rates | |
480 | - while (event->time().secs() > (time + dtime)) { | |
481 | - | |
482 | - // If rates are not all zero then append rates to vectors | |
483 | - if ((rate0 != 0.0) || (rate1 != 0.0) || (rate2 != 0.0)) { | |
484 | - | |
485 | - // Append time at mid-point of interval | |
486 | - times.append(time + 0.5 * dtime); | |
487 | - | |
488 | - // Append rates | |
489 | - rates0.push_back(rate0); | |
490 | - rates1.push_back(rate1); | |
491 | - rates2.push_back(rate2); | |
492 | - | |
493 | - // Debug | |
494 | - #if defined(G_DEBUG_COMPUTE_DRWS) | |
495 | - std::cout << "t=" << time + 0.5 * dtime; | |
496 | - std::cout << " r0=" << rate0; | |
497 | - std::cout << " r1=" << rate1; | |
498 | - std::cout << " r2=" << rate2; | |
499 | - std::cout << std::endl; | |
500 | - #endif | |
501 | - | |
502 | - // Initialise rates for new accumulation | |
503 | - rate0 = 0.0; | |
504 | - rate1 = 0.0; | |
505 | - rate2 = 0.0; | |
506 | - | |
507 | - } // endif: there were rates to append | |
508 | - | |
509 | - // Increment time | |
510 | - time += dtime; | |
511 | - | |
512 | - } // endwhile: event time was after the current integration time stop | |
513 | - | |
514 | - // Accumulate rates | |
515 | - double energy = event->energy().MeV(); | |
516 | - if (energy < 1.8) { | |
517 | - rate0 += 1.0; | |
518 | - } | |
519 | - else if (energy < 4.3) { | |
520 | - rate1 += 1.0; | |
521 | - } | |
522 | - else { | |
523 | - rate2 += 1.0; | |
524 | - } | |
525 | - | |
526 | - } // endfor: looped over events | |
527 | - | |
528 | - // Debug | |
529 | - #if defined(G_DEBUG_COMPUTE_DRWS) | |
530 | - std::cout << "Compute DRWs" << std::endl; | |
531 | - std::cout << "------------" << std::endl; | |
532 | - #endif | |
533 | - | |
534 | - // Get Good Time Intervals. If a pulsar selection is specified then | |
535 | - // reduce the Good Time Intervals to the validity intervals of the | |
536 | - // pulsar emphemerides. | |
537 | - GCOMTim tim = obs.tim(); | |
538 | - if (select.has_pulsar()) { | |
539 | - tim.reduce(select.pulsar().validity()); | |
429 | + // Method B: Phibar-dependent weighting | |
430 | + else if (method == "phibar") { | |
431 | + compute_drws_phibar(obs, events, select, zetamin, timebin); | |
540 | 432 | } |
541 | 433 | |
542 | - // Loop over Orbit Aspect Data | |
543 | - for (int i_oad = 0; i_oad < obs.oads().size(); ++i_oad) { | |
544 | - | |
545 | - // Get reference to Orbit Aspect Data of superpacket | |
546 | - const GCOMOad &oad = obs.oads()[i_oad]; | |
547 | - | |
548 | - // Check superpacket usage for all DRWs so that their statistics | |
549 | - // get correctly updated | |
550 | - bool skip = false; | |
551 | - for (int i = 0; i < size(); ++i) { | |
552 | - if (!m_dris[i].use_superpacket(oad, tim, select)) { | |
553 | - skip = true; | |
554 | - } | |
555 | - } | |
556 | - if (skip) { | |
557 | - continue; | |
558 | - } | |
559 | - | |
560 | - // Get Orbit Aspect Data mid-time in seconds | |
561 | - double time = oad.tstart().secs() + 0.5 * (oad.tstop() - oad.tstart()); | |
562 | - | |
563 | - // Compute energy-dependent rates | |
564 | - std::vector<double> rates; | |
565 | - for (int i = 0; i < size(); ++i) { | |
566 | - if (m_dris[i].m_ebounds.emin().MeV() > 4.3) { | |
567 | - rates.push_back(times.interpolate(time, rates2)); | |
568 | - } | |
569 | - else if (m_dris[i].m_ebounds.emin().MeV() > 1.8) { | |
570 | - rates.push_back(times.interpolate(time, rates1)); | |
571 | - } | |
572 | - else { | |
573 | - rates.push_back(times.interpolate(time, rates0)); | |
574 | - } | |
575 | - } | |
576 | - | |
577 | - // Debug | |
578 | - #if defined(G_DEBUG_COMPUTE_DRWS) | |
579 | - std::cout << "time=" << time; | |
580 | - for (int i = 0; i < size(); ++i) { | |
581 | - std::cout << " r[" << i << "]=" << rates[i]; | |
582 | - } | |
583 | - std::cout << std::endl; | |
584 | - #endif | |
585 | - | |
586 | - // Prepare Earth horizon angle computation. The celestial system | |
587 | - // is reinterpreted as the COMPTEL coordinate system, where the | |
588 | - // 90 degrees - zenith angle becomes the declination and the azimuth | |
589 | - // angle becomes Right Ascension. This allows us later to use the | |
590 | - // GSkyDir::dist method to compute the distance between the geocentre | |
591 | - // and the telescope Z-axis. | |
592 | - double theta_geocentre = double(oad.gcel()); | |
593 | - double phi_geocentre = double(oad.gcaz()); | |
594 | - GSkyDir geocentre_comptel; | |
595 | - geocentre_comptel.radec_deg(phi_geocentre, 90.0-theta_geocentre); | |
596 | - | |
597 | - // Compute geometrical factors for all (Chi, Psi). We assume here | |
598 | - // that their size and definition is identical, which was checked | |
599 | - // before | |
600 | - for (int index = 0; index < dri->m_dri.npix(); ++index) { | |
601 | - | |
602 | - // Get sky direction and solid angle for (Chi, Psi) | |
603 | - GSkyDir sky = dri->m_dri.inx2dir(index); | |
604 | - double omega = dri->m_dri.solidangle(index); | |
605 | - | |
606 | - // Convert sky direction to COMPTEL coordinates | |
607 | - double theta = oad.theta(sky); | |
608 | - double phi = oad.phi(sky); | |
609 | - | |
610 | - // Compute geometric factor summed over all D1, D2 times | |
611 | - // the solid angle of the weighting cube pixel | |
612 | - double geometry = dri->compute_geometry(oad.tjd(), theta, phi, select, status) * | |
613 | - omega; | |
614 | - | |
615 | - // Compute Earth horizon angle as the distance between the Earth | |
616 | - // centre in COMPTEL coordinates and the (Chi, Psi) pixel in | |
617 | - // COMPTEL coordinates minus the radius of the Earth. | |
618 | - GSkyDir chipsi_comptel; | |
619 | - chipsi_comptel.radec_deg(phi, 90.0-theta); | |
620 | - double eha = geocentre_comptel.dist_deg(chipsi_comptel) - oad.georad(); | |
621 | - | |
622 | - // Loop over Phibar | |
623 | - for (int iphibar = 0; iphibar < dri->nphibar(); ++iphibar) { | |
624 | - | |
625 | - // Compute minimum Earth horizon angle for Phibar layer | |
626 | - double ehamin = double(iphibar) * dri->m_phibin + zetamin; | |
627 | - | |
628 | - // Add up weighted geometry if the Earth horizon angle is | |
629 | - // equal or larger than the minimum | |
630 | - if (eha >= ehamin) { | |
631 | - | |
632 | - // Get data space index | |
633 | - int inx = index + iphibar * dri->m_dri.npix(); | |
634 | - | |
635 | - // Loop over DRWs and multiply geometry with appopriate | |
636 | - // rates | |
637 | - for (int i = 0; i < size(); ++i) { | |
638 | - m_dris[i][inx] += geometry * rates[i]; | |
639 | - } | |
640 | - | |
641 | - } // endif: Earth horizon cut passed | |
642 | - | |
643 | - } // endfor: looped over Phibar | |
644 | - | |
645 | - } // endfor: looped over (Chi, Psi) | |
646 | - | |
647 | - } // endfor: looped over Orbit Aspect Data | |
648 | - | |
649 | 434 | // Normalise Phibar layers of all DRWs to unity |
650 | 435 | for (int i = 0; i < size(); ++i) { |
651 | 436 | |
... | ... | @@ -676,7 +461,7 @@ void GCOMDris::compute_drws(const GCOMObservation& obs, |
676 | 461 | |
677 | 462 | } // endfor: looped over DRWs |
678 | 463 | |
679 | - } // endif: container was not empty | |
464 | + } // endif: there were DRWs in container | |
680 | 465 | |
681 | 466 | // Return |
682 | 467 | return; |
... | ... | @@ -753,3 +538,600 @@ void GCOMDris::free_members(void) |
753 | 538 | // Return |
754 | 539 | return; |
755 | 540 | } |
541 | + | |
542 | + | |
543 | +/***********************************************************************//** | |
544 | + * @brief Compute background weighting cubes using energy dependent rates | |
545 | + * | |
546 | + * @param[in] obs COMPTEL observation. | |
547 | + * @param[in] event COMPTEL event list. | |
548 | + * @param[in] select Selection set. | |
549 | + * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg). | |
550 | + * @param[in] timebin Time binning for rate determination (sec). | |
551 | + * | |
552 | + * Compute DRW cubes for a COMPTEL observation. DRW cubes are event-rate | |
553 | + * weighted geometry cubes which were multiplied by the solid angle of | |
554 | + * the (Chi,Psi) pixels. | |
555 | + * | |
556 | + * For this method the event rates depend on time and energy. Three | |
557 | + * hard-wired energy ranges are defined for which the event rate is | |
558 | + * determined: | |
559 | + * | |
560 | + * E < 1.8 MeV | |
561 | + * 1.8 < E < 4.3 MeV | |
562 | + * E > 4.3 MeV | |
563 | + * | |
564 | + * For each superpacket, the event rates are linearly interpolated to the | |
565 | + * relevant superpacket time. | |
566 | + * | |
567 | + * The DRW cubes are normalised so that the sum of each Phibar layer equals | |
568 | + * to unity. | |
569 | + ***************************************************************************/ | |
570 | +void GCOMDris::compute_drws_energy(const GCOMObservation& obs, | |
571 | + const GCOMEventList* events, | |
572 | + const GCOMSelection& select, | |
573 | + const double& zetamin, | |
574 | + const double& timebin) | |
575 | +{ | |
576 | + // Debug | |
577 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
578 | + std::cout << "GCOMDris::compute_drws_energy" << std::endl; | |
579 | + std::cout << "=============================" << std::endl; | |
580 | + #endif | |
581 | + | |
582 | + // Initialise D1 & D2 module status | |
583 | + GCOMStatus status; | |
584 | + | |
585 | + // Get pointer to first DRW in container (for convenient access to members | |
586 | + // of GCOMDri; we won't use it for modifications, hence we can declare it | |
587 | + // as constant) | |
588 | + const GCOMDri* dri = &(m_dris[0]); | |
589 | + | |
590 | + // Debug | |
591 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
592 | + std::cout << "Determine energy-dependent event rates" << std::endl; | |
593 | + std::cout << "--------------------------------------" << std::endl; | |
594 | + #endif | |
595 | + | |
596 | + // Initialise current time and vectors for computation of node function | |
597 | + // and vectors for energy-dependent rate interpolation | |
598 | + double time; | |
599 | + double rate0 = 0.0; | |
600 | + double rate1 = 0.0; | |
601 | + double rate2 = 0.0; | |
602 | + GNodeArray times; | |
603 | + std::vector<double> rates0; | |
604 | + std::vector<double> rates1; | |
605 | + std::vector<double> rates2; | |
606 | + bool set = false; | |
607 | + | |
608 | + // Set time of first event | |
609 | + if (events->size() > 0) { | |
610 | + time = (*events)[0]->time().secs(); | |
611 | + } | |
612 | + | |
613 | + // Determine energy-dependent event rates. The standard event selection | |
614 | + // criteria and earth horizon cut is applied so that the event rate | |
615 | + // corresponds to the current selection, yet we do not consider any | |
616 | + // Good Time Intervals or OAD time information as we later only access | |
617 | + // relevant times (YET THERE COULD BE AN ISSUE WITH A GLITCH). Rates | |
618 | + // are computed for three hard-coded energy intervals. | |
619 | + for (int i_evt = 0; i_evt < events->size(); ++i_evt) { | |
620 | + | |
621 | + // Get pointer to event | |
622 | + const GCOMEventAtom* event = (*events)[i_evt]; | |
623 | + | |
624 | + // Apply event selection | |
625 | + if (!select.use_event(*event)) { | |
626 | + continue; | |
627 | + } | |
628 | + | |
629 | + // Apply Earth horizon cut. Note that we need to correct later | |
630 | + // for this cut to remove the additional time variation coming | |
631 | + // from the cut. | |
632 | + if ((event->eha() - event->phibar()) < zetamin) { | |
633 | + continue; | |
634 | + } | |
635 | + | |
636 | + // If time exceeds time bin then add rates | |
637 | + while (event->time().secs() > (time + timebin)) { | |
638 | + | |
639 | + // If rates are not all zero then append rates to vectors | |
640 | + if (set) { | |
641 | + | |
642 | + // Append time at mid-point of interval | |
643 | + times.append(time + 0.5 * timebin); | |
644 | + | |
645 | + // Append rates | |
646 | + rates0.push_back(rate0); | |
647 | + rates1.push_back(rate1); | |
648 | + rates2.push_back(rate2); | |
649 | + | |
650 | + // Debug | |
651 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
652 | + std::cout << "t=" << time + 0.5 * timebin; | |
653 | + std::cout << " r0=" << rate0; | |
654 | + std::cout << " r1=" << rate1; | |
655 | + std::cout << " r2=" << rate2; | |
656 | + std::cout << std::endl; | |
657 | + #endif | |
658 | + | |
659 | + // Initialise rates for new accumulation | |
660 | + rate0 = 0.0; | |
661 | + rate1 = 0.0; | |
662 | + rate2 = 0.0; | |
663 | + set = false; | |
664 | + | |
665 | + } // endif: there were rates to append | |
666 | + | |
667 | + // Increment time | |
668 | + time += timebin; | |
669 | + | |
670 | + } // endwhile: event time was after the current integration time stop | |
671 | + | |
672 | + // Accumulate rates | |
673 | + double energy = event->energy().MeV(); | |
674 | + if (energy < 1.8) { | |
675 | + rate0 += 1.0; | |
676 | + set = true; | |
677 | + } | |
678 | + else if (energy < 4.3) { | |
679 | + rate1 += 1.0; | |
680 | + set = true; | |
681 | + } | |
682 | + else { | |
683 | + rate2 += 1.0; | |
684 | + set = true; | |
685 | + } | |
686 | + | |
687 | + } // endfor: looped over events | |
688 | + | |
689 | + // Append remaining rates | |
690 | + if (set) { | |
691 | + | |
692 | + // Append time at mid-point of interval | |
693 | + times.append(time + 0.5 * timebin); | |
694 | + | |
695 | + // Append rates | |
696 | + rates0.push_back(rate0); | |
697 | + rates1.push_back(rate1); | |
698 | + rates2.push_back(rate2); | |
699 | + | |
700 | + } // endif: appended remaining rates | |
701 | + | |
702 | + // Debug | |
703 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
704 | + std::cout << "Compute DRWs" << std::endl; | |
705 | + std::cout << "------------" << std::endl; | |
706 | + #endif | |
707 | + | |
708 | + // Allocate geometry factor and Earth horizon angle working arrays | |
709 | + std::vector<double> geometry(dri->m_dri.npix()); | |
710 | + std::vector<double> eha(dri->m_dri.npix()); | |
711 | + | |
712 | + // Get Good Time Intervals. If a pulsar selection is specified then | |
713 | + // reduce the Good Time Intervals to the validity intervals of the | |
714 | + // pulsar emphemerides. | |
715 | + GCOMTim tim = obs.tim(); | |
716 | + if (select.has_pulsar()) { | |
717 | + tim.reduce(select.pulsar().validity()); | |
718 | + } | |
719 | + | |
720 | + // Loop over Orbit Aspect Data | |
721 | + for (int i_oad = 0; i_oad < obs.oads().size(); ++i_oad) { | |
722 | + | |
723 | + // Get reference to Orbit Aspect Data of superpacket | |
724 | + const GCOMOad &oad = obs.oads()[i_oad]; | |
725 | + | |
726 | + // Check superpacket usage for all DRWs so that their statistics | |
727 | + // get correctly updated | |
728 | + bool skip = false; | |
729 | + for (int i = 0; i < size(); ++i) { | |
730 | + if (!m_dris[i].use_superpacket(oad, tim, select)) { | |
731 | + skip = true; | |
732 | + } | |
733 | + } | |
734 | + if (skip) { | |
735 | + continue; | |
736 | + } | |
737 | + | |
738 | + // Get Orbit Aspect Data mid-time in seconds | |
739 | + double time = oad.tstart().secs() + 0.5 * (oad.tstop() - oad.tstart()); | |
740 | + | |
741 | + // Compute energy-dependent rates | |
742 | + std::vector<double> rates; | |
743 | + for (int i = 0; i < size(); ++i) { | |
744 | + if (m_dris[i].m_ebounds.emin().MeV() > 4.3) { | |
745 | + rates.push_back(times.interpolate(time, rates2)); | |
746 | + } | |
747 | + else if (m_dris[i].m_ebounds.emin().MeV() > 1.8) { | |
748 | + rates.push_back(times.interpolate(time, rates1)); | |
749 | + } | |
750 | + else { | |
751 | + rates.push_back(times.interpolate(time, rates0)); | |
752 | + } | |
753 | + } | |
754 | + | |
755 | + // Debug | |
756 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
757 | + std::cout << "time=" << time; | |
758 | + for (int i = 0; i < size(); ++i) { | |
759 | + std::cout << " r[" << i << "]=" << rates[i]; | |
760 | + } | |
761 | + std::cout << std::endl; | |
762 | + #endif | |
763 | + | |
764 | + // Prepare Earth horizon angle computation. The celestial system | |
765 | + // is reinterpreted as the COMPTEL coordinate system, where the | |
766 | + // 90 degrees - zenith angle becomes the declination and the azimuth | |
767 | + // angle becomes Right Ascension. This allows us later to use the | |
768 | + // GSkyDir::dist method to compute the distance between the geocentre | |
769 | + // and the telescope Z-axis. | |
770 | + double theta_geocentre = double(oad.gcel()); | |
771 | + double phi_geocentre = double(oad.gcaz()); | |
772 | + GSkyDir geocentre_comptel; | |
773 | + geocentre_comptel.radec_deg(phi_geocentre, 90.0-theta_geocentre); | |
774 | + | |
775 | + // Compute solid-angle-corrected geometry factors and Earth horizon | |
776 | + // angles for all (Chi,Psi) pixels | |
777 | + for (int index = 0; index < dri->m_dri.npix(); ++index) { | |
778 | + | |
779 | + // Get sky direction and solid angle for (Chi, Psi) | |
780 | + GSkyDir sky = dri->m_dri.inx2dir(index); | |
781 | + double omega = dri->m_dri.solidangle(index); | |
782 | + | |
783 | + // Convert sky direction to COMPTEL coordinates | |
784 | + double theta = oad.theta(sky); | |
785 | + double phi = oad.phi(sky); | |
786 | + | |
787 | + // Compute geometric factor summed over all D1, D2 times | |
788 | + // the solid angle of the weighting cube pixel | |
789 | + geometry[index] = dri->compute_geometry(oad.tjd(), theta, phi, | |
790 | + select, status) * omega; | |
791 | + | |
792 | + // Compute Earth horizon angle as the distance between the Earth | |
793 | + // centre in COMPTEL coordinates and the (Chi, Psi) pixel in | |
794 | + // COMPTEL coordinates minus the radius of the Earth. | |
795 | + GSkyDir chipsi_comptel; | |
796 | + chipsi_comptel.radec_deg(phi, 90.0-theta); | |
797 | + eha[index] = geocentre_comptel.dist_deg(chipsi_comptel) - oad.georad(); | |
798 | + | |
799 | + } // endfor: computed solid-angle-corrected geometry factors | |
800 | + | |
801 | + // Loop over all DRWs | |
802 | + for (int i = 0; i < size(); ++i) { | |
803 | + | |
804 | + // Compute Earth horizon cut correction factor | |
805 | + double rates_sum_all = 0.0; | |
806 | + double rates_sum_cut = 0.0; | |
807 | + double ehacorr = 1.0; | |
808 | + for (int iphibar = 0; iphibar < dri->nphibar(); ++iphibar) { | |
809 | + | |
810 | + // Sum product of geometry and rates for all pixels | |
811 | + for (int index = 0; index < dri->m_dri.npix(); ++index) { | |
812 | + rates_sum_all += geometry[index] * rates[i]; | |
813 | + } | |
814 | + | |
815 | + // Sum product of geometry and rates for pixels passing | |
816 | + // the Earth horizon cut | |
817 | + double ehamin = double(iphibar) * dri->m_phibin + zetamin; | |
818 | + for (int index = 0; index < dri->m_dri.npix(); ++index) { | |
819 | + if (eha[index] >= ehamin) { | |
820 | + rates_sum_cut += geometry[index] * rates[i]; | |
821 | + } | |
822 | + } | |
823 | + | |
824 | + } // endfor: looped over Phibar | |
825 | + | |
826 | + // If something passes the Earth horizon cut then compute the | |
827 | + // correction factor now | |
828 | + if (rates_sum_cut != 0.0) { | |
829 | + ehacorr = rates_sum_all / rates_sum_cut; | |
830 | + } | |
831 | + | |
832 | + // Loop over all Phibar layers | |
833 | + for (int iphibar = 0; iphibar < dri->nphibar(); ++iphibar) { | |
834 | + | |
835 | + // Compute minimum Earth horizon angle for Phibar layer | |
836 | + double ehamin = double(iphibar) * dri->m_phibin + zetamin; | |
837 | + | |
838 | + // Loop over all (Chi,Psi) pixels | |
839 | + for (int index = 0; index < dri->m_dri.npix(); ++index) { | |
840 | + | |
841 | + // If Earth horizon angle is equal or larger than the minimum | |
842 | + // requirement then add up the rate weighted geometry factor | |
843 | + if (eha[index] >= ehamin) { | |
844 | + | |
845 | + // Get data space index | |
846 | + int inx = index + iphibar * dri->m_dri.npix(); | |
847 | + | |
848 | + // Store product as DRW value | |
849 | + m_dris[i][inx] += geometry[index] * rates[i] * ehacorr; | |
850 | + | |
851 | + } // endif: Earth horizon cut passed | |
852 | + | |
853 | + } // endfor: looped over (Chi, Psi) | |
854 | + | |
855 | + } // endfor: looped over Phibar | |
856 | + | |
857 | + } // endfor: looped over all DRWs | |
858 | + | |
859 | + } // endfor: looped over Orbit Aspect Data | |
860 | + | |
861 | + // Return | |
862 | + return; | |
863 | +} | |
864 | + | |
865 | + | |
866 | +/***********************************************************************//** | |
867 | + * @brief Compute background weighting cubes using Phibar dependent rates | |
868 | + * | |
869 | + * @param[in] obs COMPTEL observation. | |
870 | + * @param[in] event COMPTEL event list. | |
871 | + * @param[in] select Selection set. | |
872 | + * @param[in] zetamin Minimum Earth horizon - Phibar cut (deg). | |
873 | + * @param[in] timebin Time binning for rate determination (sec). | |
874 | + * | |
875 | + * Compute DRW cubes for a COMPTEL observation. DRW cubes are event-rate | |
876 | + * weighted geometry cubes which were multiplied by the solid angle of | |
877 | + * the (Chi,Psi) pixels. | |
878 | + * | |
879 | + * For this method the event rates depend on time and Phibar angle. For | |
880 | + * each superpacket, the event rates are linearly interpolated to the | |
881 | + * relevant superpacket time. | |
882 | + * | |
883 | + * The DRW cubes are normalised so that the sum of each Phibar layer equals | |
884 | + * to unity. | |
885 | + ***************************************************************************/ | |
886 | +void GCOMDris::compute_drws_phibar(const GCOMObservation& obs, | |
887 | + const GCOMEventList* events, | |
888 | + const GCOMSelection& select, | |
889 | + const double& zetamin, | |
890 | + const double& timebin) | |
891 | +{ | |
892 | + // Debug | |
893 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
894 | + std::cout << "GCOMDris::compute_drws_phibar" << std::endl; | |
895 | + std::cout << "=============================" << std::endl; | |
896 | + #endif | |
897 | + | |
898 | + // Initialise D1 & D2 module status | |
899 | + GCOMStatus status; | |
900 | + | |
901 | + // Get pointer to first DRW in container (for convenient access to members | |
902 | + // of GCOMDri; we won't use it for modifications, hence we can declare it | |
903 | + // as constant) | |
904 | + const GCOMDri* dri = &(m_dris[0]); | |
905 | + | |
906 | + // Debug | |
907 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
908 | + std::cout << "Determine Phibar-dependent event rates" << std::endl; | |
909 | + std::cout << "--------------------------------------" << std::endl; | |
910 | + #endif | |
911 | + | |
912 | + // Initialise current time and vectors for computation of node function | |
913 | + // and vectors for energy-dependent rate interpolation | |
914 | + double time; | |
915 | + std::vector<double> rate(dri->nphibar()); | |
916 | + GNodeArray times; | |
917 | + std::vector<std::vector<double> > rates(dri->nphibar()); | |
918 | + bool set = false; | |
919 | + | |
920 | + // Set time of first event | |
921 | + if (events->size() > 0) { | |
922 | + time = (*events)[0]->time().secs(); | |
923 | + } | |
924 | + | |
925 | + // Determine energy-dependent event rates. The standard event selection | |
926 | + // criteria and earth horizon cut is applied so that the event rate | |
927 | + // corresponds to the current selection, yet we do not consider any | |
928 | + // Good Time Intervals or OAD time information as we later only access | |
929 | + // relevant times. | |
930 | + for (int i_evt = 0; i_evt < events->size(); ++i_evt) { | |
931 | + | |
932 | + // Get pointer to event | |
933 | + const GCOMEventAtom* event = (*events)[i_evt]; | |
934 | + | |
935 | + // Apply event selection | |
936 | + if (!select.use_event(*event)) { | |
937 | + continue; | |
938 | + } | |
939 | + | |
940 | + // Apply Earth horizon cut. Note that we need to correct later | |
941 | + // for this cut to remove the additional time variation coming | |
942 | + // from the cut. | |
943 | + if ((event->eha() - event->phibar()) < zetamin) { | |
944 | + continue; | |
945 | + } | |
946 | + | |
947 | + // If time exceeds time bin then add rates | |
948 | + while (event->time().secs() > (time + timebin)) { | |
949 | + | |
950 | + // If rates are set then append rates to vectors | |
951 | + if (set) { | |
952 | + | |
953 | + // Append time at mid-point of interval | |
954 | + times.append(time + 0.5 * timebin); | |
955 | + | |
956 | + // Append rates and initialise for new accumulation | |
957 | + for (int iphibar = 0; iphibar < dri->nphibar(); ++iphibar) { | |
958 | + rates[iphibar].push_back(rate[iphibar]); | |
959 | + rate[iphibar] = 0.0; | |
960 | + } | |
961 | + | |
962 | + // Signal that rates were not yet set | |
963 | + set = false; | |
964 | + | |
965 | + } // endif: there were rates to append | |
966 | + | |
967 | + // Increment time | |
968 | + time += timebin; | |
969 | + | |
970 | + } // endwhile: event time was after the current integration time stop | |
971 | + | |
972 | + // Accumulate rates | |
973 | + int iphibar = int((event->phibar() - dri->phimin()) / dri->phibin()); | |
974 | + if (iphibar >= 0 and iphibar < dri->nphibar()) { | |
975 | + rate[iphibar] += 1.0; | |
976 | + set = true; | |
977 | + } | |
978 | + | |
979 | + } // endfor: looped over events | |
980 | + | |
981 | + // Append remaining rates | |
982 | + if (set) { | |
983 | + | |
984 | + // Append time at mid-point of interval | |
985 | + times.append(time + 0.5 * timebin); | |
986 | + | |
987 | + // Append rates | |
988 | + for (int iphibar = 0; iphibar < dri->nphibar(); ++iphibar) { | |
989 | + rates[iphibar].push_back(rate[iphibar]); | |
990 | + } | |
991 | + | |
992 | + } // endif: appended remaining rates | |
993 | + | |
994 | + // Debug | |
995 | + #if defined(G_DEBUG_COMPUTE_DRWS) | |
996 | + std::cout << "Compute DRWs" << std::endl; | |
997 | + std::cout << "------------" << std::endl; | |
998 | + #endif | |
999 | + | |
1000 | + // Allocate geometry factor and Earth horizon angle working arrays | |
1001 | + std::vector<double> geometry(dri->m_dri.npix()); | |
1002 | + std::vector<double> eha(dri->m_dri.npix()); | |
1003 | + | |
1004 | + // Get Good Time Intervals. If a pulsar selection is specified then | |
1005 | + // reduce the Good Time Intervals to the validity intervals of the | |
1006 | + // pulsar emphemerides. | |
1007 | + GCOMTim tim = obs.tim(); | |
1008 | + if (select.has_pulsar()) { | |
1009 | + tim.reduce(select.pulsar().validity()); | |
1010 | + } | |
1011 | + | |
1012 | + // Loop over Orbit Aspect Data | |
1013 | + for (int i_oad = 0; i_oad < obs.oads().size(); ++i_oad) { | |
1014 | + | |
1015 | + // Get reference to Orbit Aspect Data of superpacket | |
1016 | + const GCOMOad &oad = obs.oads()[i_oad]; | |
1017 | + | |
1018 | + // Check superpacket usage for all DRWs so that their statistics | |
1019 | + // get correctly updated | |
1020 | + bool skip = false; | |
1021 | + for (int i = 0; i < size(); ++i) { | |
1022 | + if (!m_dris[i].use_superpacket(oad, tim, select)) { | |
1023 | + skip = true; | |
1024 | + } | |
1025 | + } | |
1026 | + if (skip) { | |
1027 | + continue; | |
1028 | + } | |
1029 | + | |
1030 | + // Get Orbit Aspect Data mid-time in seconds | |
1031 | + double time = oad.tstart().secs() + 0.5 * (oad.tstop() - oad.tstart()); | |
1032 | + | |
1033 | + // Compute Phibar-dependent rates by interpolation of precomputed | |
1034 | + // rate vectors | |
1035 | + std::vector<double> rate_oad(dri->nphibar()); | |
1036 | + for (int iphibar = 0; iphibar < dri->nphibar(); ++iphibar) { | |
1037 | + rate_oad[iphibar] = times.interpolate(time, rates[iphibar]); | |
1038 | + } | |
1039 | + | |
1040 | + // Prepare Earth horizon angle computation. The celestial system | |
1041 | + // is reinterpreted as the COMPTEL coordinate system, where the | |
1042 | + // 90 degrees - zenith angle becomes the declination and the azimuth | |
1043 | + // angle becomes Right Ascension. This allows us later to use the | |
1044 | + // GSkyDir::dist method to compute the distance between the geocentre | |
1045 | + // and the telescope Z-axis. | |
1046 | + double theta_geocentre = double(oad.gcel()); | |
1047 | + double phi_geocentre = double(oad.gcaz()); | |
1048 | + GSkyDir geocentre_comptel; | |
1049 | + geocentre_comptel.radec_deg(phi_geocentre, 90.0-theta_geocentre); | |
1050 | + | |
1051 | + // Compute solid-angle-corrected geometry factors and Earth horizon | |
1052 | + // angles for all (Chi,Psi) pixels | |
1053 | + for (int index = 0; index < dri->m_dri.npix(); ++index) { | |
1054 | + | |
1055 | + // Get sky direction and solid angle for (Chi, Psi) | |
1056 | + GSkyDir sky = dri->m_dri.inx2dir(index); | |
1057 | + double omega = dri->m_dri.solidangle(index); | |
1058 | + | |
1059 | + // Convert sky direction to COMPTEL coordinates | |
1060 | + double theta = oad.theta(sky); | |
1061 | + double phi = oad.phi(sky); | |
1062 | + | |
1063 | + // Compute geometric factor summed over all D1, D2 times | |
1064 | + // the solid angle of the weighting cube pixel | |
1065 | + geometry[index] = dri->compute_geometry(oad.tjd(), theta, phi, | |
1066 | + select, status) * omega; | |
1067 | + | |
1068 | + // Compute Earth horizon angle as the distance between the Earth | |
1069 | + // centre in COMPTEL coordinates and the (Chi, Psi) pixel in | |
1070 | + // COMPTEL coordinates minus the radius of the Earth. | |
1071 | + GSkyDir chipsi_comptel; | |
1072 | + chipsi_comptel.radec_deg(phi, 90.0-theta); | |
1073 | + eha[index] = geocentre_comptel.dist_deg(chipsi_comptel) - oad.georad(); | |
1074 | + | |
1075 | + } // endfor: computed solid-angle-corrected geometry factors | |
1076 | + | |
1077 | + // Correct rates for Earth horizon cut | |
1078 | + for (int iphibar = 0; iphibar < dri->nphibar(); ++iphibar) { | |
1079 | + | |
1080 | + // Compute minimum Earth Horizon angle for Phibar layer | |
1081 | + double ehamin = double(iphibar) * dri->m_phibin + zetamin; | |
1082 | + | |
1083 | + // Initialise sums | |
1084 | + double rates_sum_all = 0.0; | |
1085 | + double rates_sum_cut = 0.0; | |
1086 | + | |
1087 | + // Sum geometry for all pixels and pixels passing the Earth horizon cut | |
1088 | + for (int index = 0; index < dri->m_dri.npix(); ++index) { | |
1089 | + rates_sum_all += geometry[index]; | |
1090 | + if (eha[index] >= ehamin) { | |
1091 | + rates_sum_cut += geometry[index]; | |
1092 | + } | |
1093 | + } | |
1094 | + | |
1095 | + // If something passes the Earth horizon cut then correct | |
1096 | + // the rate | |
1097 | + if (rates_sum_cut != 0.0) { | |
1098 | + rate_oad[iphibar] *= rates_sum_all / rates_sum_cut; | |
1099 | + } | |
1100 | + | |
1101 | + } // endfor: looped over Phibar | |
1102 | + | |
1103 | + // Loop over all DRWs | |
1104 | + for (int i = 0; i < size(); ++i) { | |
1105 | + | |
1106 | + // Loop over all Phibar layers | |
1107 | + for (int iphibar = 0; iphibar < dri->nphibar(); ++iphibar) { | |
1108 | + | |
1109 | + // Compute minimum Earth horizon angle for Phibar layer | |
1110 | + double ehamin = double(iphibar) * dri->m_phibin + zetamin; | |
1111 | + | |
1112 | + // Loop over all (Chi,Psi) pixels | |
1113 | + for (int index = 0; index < dri->m_dri.npix(); ++index) { | |
1114 | + | |
1115 | + // If Earth horizon angle is equal or larger than the minimum | |
1116 | + // requirement then add up the rate weighted geometry factor | |
1117 | + if (eha[index] >= ehamin) { | |
1118 | + | |
1119 | + // Get data space index | |
1120 | + int inx = index + iphibar * dri->m_dri.npix(); | |
1121 | + | |
1122 | + // Store product as DRW value | |
1123 | + m_dris[i][inx] += geometry[index] * rate_oad[iphibar]; | |
1124 | + | |
1125 | + } // endif: Earth horizon cut passed | |
1126 | + | |
1127 | + } // endfor: looped over (Chi, Psi) | |
1128 | + | |
1129 | + } // endfor: looped over Phibar | |
1130 | + | |
1131 | + } // endfor: looped over all DRWs | |
1132 | + | |
1133 | + } // endfor: looped over Orbit Aspect Data | |
1134 | + | |
1135 | + // Return | |
1136 | + return; | |
1137 | +} | ... | ... |