Commit cf079ae01f3a526d6bc4b35fc1642b08b6729554
1 parent
de558787
Add RING background method to ctskymap (#2207)
Showing
7 changed files
with
211 additions
and
161 deletions
ChangeLog
| 1 | -2017-10-11 | |
| 1 | +2017-10-16 | |
| 2 | 2 | |
| 3 | 3 | * Version 1.5.0 released |
| 4 | 4 | ======================== |
| 5 | 5 | |
| 6 | + Add RING background method to ctskymap (#2207) | |
| 6 | 7 | Add keywords to sky maps produced by ctskymap (#2194) |
| 7 | 8 | Enhance efficiency of computations in ctmodel (#2189) |
| 8 | 9 | Add csmodelsois script (#2180) | ... | ... |
NEWS
| 1 | 1 | New Features and Important Changes in ctools 1.5.0 |
| 2 | 2 | |
| 3 | -11 October 2017 | |
| 3 | +16 October 2017 | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | Introduction |
| ... | ... | @@ -57,6 +57,9 @@ Header keywords informing about the dates and times covered by the observations |
| 57 | 57 | used to generate the skymap, as well as the event energy range, are now appended |
| 58 | 58 | as header keywords to the FITS file (#2194). |
| 59 | 59 | |
| 60 | +Add the RING background method, which is a classical analysis methods for IACT | |
| 61 | +data analysis, for background subtraction (#2207). | |
| 62 | + | |
| 60 | 63 | |
| 61 | 64 | ctmodel - CTA counts cube modelling |
| 62 | 65 | ----------------------------------- | ... | ... |
doc/source/admin/release_history/1.5.rst
| ... | ... | @@ -22,6 +22,8 @@ Bug fixes |
| 22 | 22 | Improvements |
| 23 | 23 | ------------ |
| 24 | 24 | |
| 25 | +* [`2207 <https://cta-redmine.irap.omp.eu/issues/2207>`_] - | |
| 26 | + Add ``RING`` background method to :ref:`ctskymap` | |
| 25 | 27 | * [`2194 <https://cta-redmine.irap.omp.eu/issues/2194>`_] - |
| 26 | 28 | Add keywords to sky maps produced by :ref:`ctskymap` |
| 27 | 29 | * [`2189 <https://cta-redmine.irap.omp.eu/issues/2189>`_] - | ... | ... |
src/ctskymap/ctskymap.cpp
| ... | ... | @@ -33,10 +33,11 @@ |
| 33 | 33 | #include "GSkyRegions.hpp" |
| 34 | 34 | |
| 35 | 35 | /* __ Method name definitions ____________________________________________ */ |
| 36 | -#define G_INIT_MAP "ctskymap::init_map(GCTAObservation* obs)" | |
| 37 | -#define G_MAP_EVENTS "ctskymap::map_events(GCTAObservation*)" | |
| 38 | -#define G_MAP_BACKGROUND_IRF "ctskymap::map_background_irf(GCTAObservation*)" | |
| 39 | -#define G_MAP_BACKGROUND_RING "ctskymap::map_background_ring(GCTAObservation*)" | |
| 36 | +#define G_GET_PARAMETERS "ctskymap::get_parameter()" | |
| 37 | +#define G_MAP_EVENTS "ctskymap::map_events(GCTAObservation*)" | |
| 38 | +#define G_MAP_BACKGROUND_IRF "ctskymap::map_background_irf(GCTAObservation*)" | |
| 39 | +#define G_MAP_BACKGROUND_RING "ctskymap::map_background_ring("\ | |
| 40 | + "GCTAObservation*)" | |
| 40 | 41 | |
| 41 | 42 | /* __ Debug definitions __________________________________________________ */ |
| 42 | 43 | |
| ... | ... | @@ -242,10 +243,12 @@ void ctskymap::run(void) |
| 242 | 243 | |
| 243 | 244 | } // endfor: looped over observations |
| 244 | 245 | |
| 246 | + // If background subtraction is selected then compute significance map | |
| 245 | 247 | if (m_bkgsubtract != "NONE") { |
| 248 | + | |
| 246 | 249 | // Compute the significance map |
| 247 | 250 | map_significance(); |
| 248 | - | |
| 251 | + | |
| 249 | 252 | // Subtract background map from counts map |
| 250 | 253 | m_skymap -= m_bkgmap; |
| 251 | 254 | } |
| ... | ... | @@ -320,7 +323,7 @@ void ctskymap::save(void) |
| 320 | 323 | // Save FITS file to disk |
| 321 | 324 | fits.saveto(m_outmap, clobber()); |
| 322 | 325 | |
| 323 | - } | |
| 326 | + } // endif: filename and map were not empty | |
| 324 | 327 | |
| 325 | 328 | // Write into logger what has been done |
| 326 | 329 | std::string fname = (m_outmap.is_empty()) ? "NONE" : m_outmap.url(); |
| ... | ... | @@ -376,18 +379,21 @@ void ctskymap::init_members(void) |
| 376 | 379 | m_skymap.clear(); |
| 377 | 380 | m_bkgmap.clear(); |
| 378 | 381 | m_sigmap.clear(); |
| 382 | + m_exclmap.clear(); | |
| 383 | + m_alphamap.clear(); | |
| 384 | + m_onmap.clear(); | |
| 379 | 385 | m_emin = 0.0; |
| 380 | 386 | m_emax = 0.0; |
| 381 | 387 | m_bkgsubtract = "NONE"; |
| 388 | + m_roiradius = 0.0; | |
| 389 | + m_inradius = 0.0; | |
| 390 | + m_outradius = 0.0; | |
| 382 | 391 | m_publish = false; |
| 383 | 392 | m_chatter = static_cast<GChatter>(2); |
| 384 | - m_solidangle = std::vector<double>(0); | |
| 385 | 393 | |
| 386 | - // Variables for RING bkgd subtraction | |
| 387 | - m_exclmap.clear(); | |
| 388 | - m_roiradius = 0.0; | |
| 389 | - m_inradius = 0.0; | |
| 390 | - m_outradius = 0.0; | |
| 394 | + // Initialise cache | |
| 395 | + m_solidangle.clear(); | |
| 396 | + m_dirs.clear(); | |
| 391 | 397 | |
| 392 | 398 | // Return |
| 393 | 399 | return; |
| ... | ... | @@ -405,18 +411,21 @@ void ctskymap::copy_members(const ctskymap& app) |
| 405 | 411 | m_skymap = app.m_skymap; |
| 406 | 412 | m_bkgmap = app.m_bkgmap; |
| 407 | 413 | m_sigmap = app.m_sigmap; |
| 414 | + m_exclmap = app.m_exclmap; | |
| 415 | + m_alphamap = app.m_alphamap; | |
| 416 | + m_onmap = app.m_onmap; | |
| 408 | 417 | m_emin = app.m_emin; |
| 409 | 418 | m_emax = app.m_emax; |
| 410 | 419 | m_bkgsubtract = app.m_bkgsubtract; |
| 420 | + m_roiradius = app.m_roiradius; | |
| 421 | + m_inradius = app.m_inradius; | |
| 422 | + m_outradius = app.m_outradius; | |
| 411 | 423 | m_publish = app.m_publish; |
| 412 | 424 | m_chatter = app.m_chatter; |
| 413 | - m_solidangle = app.m_solidangle; | |
| 414 | 425 | |
| 415 | - // Variables for RING bkgd subtraction | |
| 416 | - m_exclmap = app.m_exclmap; | |
| 417 | - m_roiradius = app.m_roiradius; | |
| 418 | - m_inradius = app.m_inradius; | |
| 419 | - m_outradius = app.m_outradius; | |
| 426 | + // Copy cache | |
| 427 | + m_solidangle = app.m_solidangle; | |
| 428 | + m_dirs = app.m_dirs; | |
| 420 | 429 | |
| 421 | 430 | // Return |
| 422 | 431 | return; |
| ... | ... | @@ -456,6 +465,26 @@ void ctskymap::get_parameters(void) |
| 456 | 465 | m_emax = (*this)["emax"].real(); |
| 457 | 466 | m_bkgsubtract = (*this)["bkgsubtract"].string(); |
| 458 | 467 | |
| 468 | + // Get RING background parameters | |
| 469 | + if (m_bkgsubtract == "RING") { | |
| 470 | + | |
| 471 | + // Get parameters | |
| 472 | + m_roiradius = (*this)["roiradius"].real(); | |
| 473 | + m_inradius = (*this)["inradius"].real(); | |
| 474 | + m_outradius = (*this)["outradius"].real(); | |
| 475 | + | |
| 476 | + // Make sure that (roiradius < inradius < outradius) | |
| 477 | + if (m_roiradius > m_inradius) { | |
| 478 | + std::string msg("'roiradius' must be smaller than 'inradius'"); | |
| 479 | + throw GException::invalid_value(G_GET_PARAMETERS, msg); | |
| 480 | + } | |
| 481 | + else if (m_inradius > m_outradius) { | |
| 482 | + std::string msg("'inradius' must be smaller than 'outradius'"); | |
| 483 | + throw GException::invalid_value(G_GET_PARAMETERS, msg); | |
| 484 | + } | |
| 485 | + | |
| 486 | + } // endif: read RING background parameters | |
| 487 | + | |
| 459 | 488 | // If IRF background subtraction is requested then make sure that the |
| 460 | 489 | // CTA observations in the observation container have response information |
| 461 | 490 | if (m_bkgsubtract != "NONE") { |
| ... | ... | @@ -463,43 +492,29 @@ void ctskymap::get_parameters(void) |
| 463 | 492 | } |
| 464 | 493 | |
| 465 | 494 | // Get remaining parameters |
| 466 | - m_publish = (*this)["publish"].boolean(); | |
| 467 | - m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | |
| 495 | + m_publish = (*this)["publish"].boolean(); | |
| 496 | + m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); | |
| 468 | 497 | |
| 469 | 498 | // Read ahead parameters |
| 470 | 499 | if (read_ahead()) { |
| 471 | 500 | m_outmap = (*this)["outmap"].filename(); |
| 472 | - | |
| 473 | - if (m_bkgsubtract == "RING") { | |
| 474 | - // Get the integration region radii | |
| 475 | - m_roiradius = (*this)["roiradius"].real(); | |
| 476 | - m_inradius = (*this)["inradius"].real(); | |
| 477 | - m_outradius = (*this)["outradius"].real(); | |
| 478 | - | |
| 479 | - // Make sure that (roiradius < inradius < outradius) | |
| 480 | - if (m_roiradius > m_inradius) { | |
| 481 | - std::string err("'roiradius' must be smaller than inner ring radius"); | |
| 482 | - throw GException::invalid_value("ctskymap::get_parameter()",err); | |
| 483 | - } else if (m_inradius > m_outradius) { | |
| 484 | - std::string err("Inner ring radius must be smaller than outer ring radius"); | |
| 485 | - throw GException::invalid_value("ctskymap::get_parameter()",err); | |
| 486 | - } // endif: Ring radius checks | |
| 487 | - } | |
| 488 | 501 | } |
| 489 | 502 | |
| 490 | 503 | // Create background map and significance map if background subtraction |
| 491 | 504 | // is requested |
| 492 | 505 | if (m_bkgsubtract != "NONE") { |
| 506 | + | |
| 507 | + // Create backgrond and significance maps | |
| 493 | 508 | m_bkgmap = create_map(m_obs); |
| 494 | 509 | m_sigmap = create_map(m_obs); |
| 495 | 510 | |
| 496 | 511 | // Setup the exclusions map |
| 497 | - map_exclusions((*this)["regfile"].filename()); | |
| 512 | + map_exclusions((*this)["inexclusion"].filename()); | |
| 498 | 513 | |
| 499 | - // Cache the pixel areas | |
| 514 | + // Cache the pixel solid angles and sky directions | |
| 500 | 515 | m_solidangle.reserve(m_bkgmap.npix()); |
| 501 | 516 | m_dirs.reserve(m_bkgmap.npix()); |
| 502 | - for (int i=0; i<m_bkgmap.npix(); i++) { | |
| 517 | + for (int i = 0; i < m_bkgmap.npix(); ++i) { | |
| 503 | 518 | m_solidangle.push_back(m_bkgmap.solidangle(i)); |
| 504 | 519 | m_dirs.push_back(m_bkgmap.inx2dir(i)); |
| 505 | 520 | } |
| ... | ... | @@ -511,7 +526,7 @@ void ctskymap::get_parameters(void) |
| 511 | 526 | m_onmap = create_map(m_obs); |
| 512 | 527 | } |
| 513 | 528 | |
| 514 | - } | |
| 529 | + } // endif: background subtraction selected | |
| 515 | 530 | |
| 516 | 531 | // Write parameters into logger |
| 517 | 532 | log_parameters(TERSE); |
| ... | ... | @@ -623,13 +638,15 @@ void ctskymap::map_events(GCTAObservation* obs) |
| 623 | 638 | * |
| 624 | 639 | * NONE - No background estimation |
| 625 | 640 | * IRF - Background estimation based on IRF template |
| 641 | + * RING - Ring background estimation | |
| 626 | 642 | ***************************************************************************/ |
| 627 | 643 | void ctskymap::map_background(GCTAObservation* obs) |
| 628 | 644 | { |
| 629 | 645 | // Dispatch to appropriate background estimation method |
| 630 | 646 | if (m_bkgsubtract == "IRF") { |
| 631 | 647 | map_background_irf(obs); |
| 632 | - } else if (m_bkgsubtract == "RING") { | |
| 648 | + } | |
| 649 | + else if (m_bkgsubtract == "RING") { | |
| 633 | 650 | map_background_ring(obs); |
| 634 | 651 | } |
| 635 | 652 | |
| ... | ... | @@ -738,7 +755,8 @@ void ctskymap::map_background_irf(GCTAObservation* obs) |
| 738 | 755 | |
| 739 | 756 | |
| 740 | 757 | /***********************************************************************//** |
| 741 | - * @brief Estimates the background in sky map based on the ring background method | |
| 758 | + * @brief Estimates the background in sky map based on the ring background | |
| 759 | + * method | |
| 742 | 760 | * |
| 743 | 761 | * @param[in] obs CTA observation. |
| 744 | 762 | * |
| ... | ... | @@ -746,16 +764,16 @@ void ctskymap::map_background_irf(GCTAObservation* obs) |
| 746 | 764 | * No response information available for observation. |
| 747 | 765 | * No background template available in instrument response function. |
| 748 | 766 | * |
| 749 | - * Estimates the background in the sky map by summing the events within a ring | |
| 750 | - * centered at a given pixel's position. The pixels in the ring are weighted | |
| 751 | - * also by the background IRF value | |
| 767 | + * Estimates the background in the sky map by summing the events within a | |
| 768 | + * ring centered at a given pixel's position. The pixels in the ring are | |
| 769 | + * weighted also by the background IRF value. | |
| 752 | 770 | ***************************************************************************/ |
| 753 | 771 | void ctskymap::map_background_ring(GCTAObservation* obs) |
| 754 | 772 | { |
| 755 | 773 | // Get IRF response (to scale background counts) |
| 756 | 774 | const GCTAResponseIrf* rsp = dynamic_cast<const GCTAResponseIrf*>(obs->response()); |
| 757 | 775 | |
| 758 | - // Throw an exception if observation has no instrument response function | |
| 776 | + // Throw an exception if observation has no instrument response function | |
| 759 | 777 | if (rsp == NULL) { |
| 760 | 778 | std::string msg = "No response information available for "+ |
| 761 | 779 | get_obs_header(obs)+" to compute IRF background. " |
| ... | ... | @@ -784,9 +802,8 @@ void ctskymap::map_background_ring(GCTAObservation* obs) |
| 784 | 802 | GCTARoi roi = obs->roi(); |
| 785 | 803 | |
| 786 | 804 | // Initialise statistics |
| 787 | - int calls = 0; | |
| 788 | - double total = 0.0; | |
| 789 | - double exposure = obs->livetime() ; | |
| 805 | + int calls = 0; | |
| 806 | + double exposure = obs->livetime(); | |
| 790 | 807 | |
| 791 | 808 | // Loop over all map pixels |
| 792 | 809 | for (int i = 0; i < m_bkgmap.npix(); ++i) { |
| ... | ... | @@ -807,23 +824,26 @@ void ctskymap::map_background_ring(GCTAObservation* obs) |
| 807 | 824 | ctskymap::irf_kern integrand(bkg, &instdir); |
| 808 | 825 | GIntegral integral(&integrand); |
| 809 | 826 | |
| 810 | - // Set precision (has been carefully adjusted using a test simulation | |
| 811 | - // over the energy range 20 GeV - 120 TeV) | |
| 827 | + // Set precision | |
| 812 | 828 | integral.eps(1.0e-6); |
| 813 | 829 | |
| 814 | - // Do Romberg integration to get the sensitivity (note: this assumes the | |
| 815 | - // background IRF is a good approximation for the radial sensitivity) | |
| 830 | + // Do Romberg integration to get the sensitivity (note: this assumes | |
| 831 | + // the background IRF is a good approximation for the radial | |
| 832 | + // sensitivity) | |
| 816 | 833 | m_alphamap(i,0) += integral.romberg(lnEmin, lnEmax) * |
| 817 | - m_solidangle[i] * obs->livetime(); | |
| 834 | + m_solidangle[i] * exposure; | |
| 818 | 835 | |
| 819 | 836 | // Store the counts in this bin |
| 820 | 837 | m_onmap(i,0) += m_skymap(i,0); |
| 821 | - | |
| 838 | + | |
| 822 | 839 | // Update number of background function calls |
| 823 | 840 | calls += integral.calls(); |
| 824 | 841 | |
| 825 | 842 | } // endfor: Loop for caching bkg IRF sensitivity |
| 826 | 843 | |
| 844 | + // Log background subtraction results | |
| 845 | + log_value(NORMAL, "Alpha map evaluations", calls); | |
| 846 | + | |
| 827 | 847 | // Zero out the counts map to prepare it for the next observation |
| 828 | 848 | m_skymap = 0.0; |
| 829 | 849 | |
| ... | ... | @@ -858,12 +878,13 @@ void ctskymap::write_hdu_keywords(GFitsHDU* hdu) const |
| 858 | 878 | |
| 859 | 879 | |
| 860 | 880 | /***********************************************************************//** |
| 861 | - * @brief Computes the bin-by-bin significance if background subtraction requested | |
| 881 | + * @brief Computes the bin-by-bin significance if background subtraction | |
| 882 | + * requested | |
| 862 | 883 | * |
| 863 | 884 | * Method computes the bin-by bin significance if a background subtraction |
| 864 | - * method is specified. If method is "IRF", Poisson statistics (in the Gaussian | |
| 865 | - * limit) are assumed. If method is "RING" a Li & Ma significance is computed | |
| 866 | - * for each bin (as well as a map of the computed alpha values). | |
| 885 | + * method is specified. If method is "IRF", Poisson statistics (in the | |
| 886 | + * Gaussian limit) are assumed. If method is "RING" a Li & Ma significance | |
| 887 | + * is computed for each bin (as well as a map of the computed alpha values). | |
| 867 | 888 | ***************************************************************************/ |
| 868 | 889 | void ctskymap::map_significance(void) |
| 869 | 890 | { |
| ... | ... | @@ -875,16 +896,19 @@ void ctskymap::map_significance(void) |
| 875 | 896 | log_value(NORMAL, "Total pixels to process", m_onmap.npix()); |
| 876 | 897 | |
| 877 | 898 | // Store the number of bins with an inappropriate alpha parameter |
| 878 | - int num_bad_alpha(0); | |
| 899 | + int num_bad_alpha = 0; | |
| 900 | + | |
| 879 | 901 | // Loop through each bin in the on-counts map |
| 880 | 902 | for (int i = 0; i < m_onmap.npix(); ++i) { |
| 881 | 903 | |
| 882 | - // Reset the on/off counts and alpha for this bin | |
| 883 | - double n_on(0), n_off(0), alpha(0.0); | |
| 904 | + // Initialise the on/off counts and alpha for this bin | |
| 905 | + double n_on = 0.0; | |
| 906 | + double n_off = 0.0; | |
| 907 | + double alpha = 0.0; | |
| 884 | 908 | |
| 885 | 909 | // Since this can take a long time, keep the user updated on |
| 886 | 910 | // the progress when another 10% of pixels is processed |
| 887 | - if (i%(m_onmap.npix()/10)==0) { | |
| 911 | + if (i % (m_onmap.npix()/10) == 0) { | |
| 888 | 912 | log_value(NORMAL, "Pixels remaining", m_onmap.npix()-i); |
| 889 | 913 | } |
| 890 | 914 | |
| ... | ... | @@ -895,49 +919,51 @@ void ctskymap::map_significance(void) |
| 895 | 919 | compute_ring_values(m_onmap, m_alphamap, skydir, |
| 896 | 920 | n_on, n_off, alpha); |
| 897 | 921 | |
| 898 | - // If alpha is reasonable, then store the results | |
| 922 | + // If alpha is zero then increment the bad alpha counter | |
| 899 | 923 | if (alpha == 0.0) { |
| 900 | - // Increment the bad alpha counter | |
| 901 | 924 | num_bad_alpha++; |
| 902 | 925 | } |
| 903 | - | |
| 926 | + | |
| 927 | + // ... otherwise store the results | |
| 904 | 928 | else { |
| 905 | - // Save the on-counts and alpha-weighted off-counts | |
| 929 | + | |
| 930 | + // Store the on-counts and alpha-weighted off-counts | |
| 906 | 931 | m_skymap(i,0) = n_on; |
| 907 | 932 | m_bkgmap(i,0) = alpha * n_off; |
| 908 | 933 | |
| 909 | - // Compute significance | |
| 934 | + // Compute and store significance (Li & Ma eq. 17) | |
| 910 | 935 | if (n_on == 0.0) { |
| 911 | - | |
| 912 | - // The significance computation reduces to the following form | |
| 913 | 936 | m_sigmap(i,0) = -2.0 * n_off * std::log(1.0+alpha); |
| 914 | - | |
| 915 | - } else { | |
| 916 | - // Save the significance | |
| 917 | - m_sigmap(i,0) = (n_on < (alpha*n_off) ? -2.0:2.0 ) * | |
| 918 | - (n_on * std::log((1.0+alpha) * n_on / (alpha * (n_on+n_off))) + | |
| 919 | - n_off * std::log((1.0+alpha) * n_off / (n_on+n_off))); | |
| 920 | 937 | } |
| 921 | - } | |
| 922 | - } // endfor: Loop over all pixels | |
| 938 | + else { | |
| 939 | + m_sigmap(i,0) = (n_on < (alpha*n_off) ? -2.0 : 2.0) * | |
| 940 | + (n_on * std::log((1.0+alpha) * | |
| 941 | + n_on / (alpha * (n_on+n_off))) + | |
| 942 | + n_off * std::log((1.0+alpha) * | |
| 943 | + n_off / (n_on+n_off))); | |
| 944 | + } | |
| 945 | + | |
| 946 | + } // endelse: alpha was non-zero | |
| 947 | + | |
| 948 | + } // endfor: looped over all pixels | |
| 923 | 949 | |
| 924 | 950 | // Log the number of bad-alpha bins |
| 925 | - log_value(NORMAL, "Bins with bad alpha", num_bad_alpha); | |
| 951 | + log_value(NORMAL, "Bins with alpha=0", num_bad_alpha); | |
| 926 | 952 | |
| 927 | - // Now take the square root. Since some bins can be negative, first take | |
| 928 | - // the absolute value of the map, square root that, then multiply each | |
| 929 | - // bin by its sign to preserve the +/- significance. | |
| 930 | - m_sigmap = sign(m_sigmap) * sqrt( abs(m_sigmap) ); | |
| 931 | - } | |
| 953 | + // Now take the square root. Since some bins can be negative, first | |
| 954 | + // take the absolute value of the map, square root that, then multiply | |
| 955 | + // each bin by its sign to preserve the +/- significance. | |
| 956 | + m_sigmap = sign(m_sigmap) * sqrt(abs(m_sigmap)); | |
| 957 | + | |
| 958 | + } // endif: ring background selected | |
| 932 | 959 | |
| 933 | 960 | // Compute significance using Poisson statistics in the Gaussian limit |
| 934 | 961 | else { |
| 935 | - | |
| 936 | - // Compute significance map | |
| 937 | 962 | m_sigmap = (m_skymap - m_bkgmap) / sqrt(m_skymap); |
| 938 | - | |
| 939 | - } // endif: background subtraction was requested | |
| 940 | - | |
| 963 | + } | |
| 964 | + | |
| 965 | + // Return | |
| 966 | + return; | |
| 941 | 967 | } |
| 942 | 968 | |
| 943 | 969 | |
| ... | ... | @@ -957,13 +983,17 @@ void ctskymap::map_significance(void) |
| 957 | 983 | void ctskymap::compute_ring_values(const GSkyMap& counts, |
| 958 | 984 | const GSkyMap& sensitivity, |
| 959 | 985 | const GSkyDir& position, |
| 960 | - double& non, double& noff, double& alpha) | |
| 986 | + double& non, | |
| 987 | + double& noff, | |
| 988 | + double& alpha) | |
| 961 | 989 | { |
| 962 | - // Reset non and noff | |
| 963 | - non = 0.0; | |
| 990 | + // Reset Non and Noff | |
| 991 | + non = 0.0; | |
| 964 | 992 | noff = 0.0; |
| 965 | - double alpha_on(0.0); | |
| 966 | - double alpha_off(0.0); | |
| 993 | + | |
| 994 | + // Initialise On and Off alpha | |
| 995 | + double alpha_on = 0.0; | |
| 996 | + double alpha_off = 0.0; | |
| 967 | 997 | |
| 968 | 998 | // Define the regions necessary to do the pixel checks |
| 969 | 999 | GSkyRegionCircle roi_reg(position, m_roiradius); |
| ... | ... | @@ -976,9 +1006,8 @@ void ctskymap::compute_ring_values(const GSkyMap& counts, |
| 976 | 1006 | // Get the index and sky direction of this pixel |
| 977 | 1007 | GSkyDir& skydir = m_dirs[j]; |
| 978 | 1008 | |
| 979 | - // Check if it is in the background region | |
| 980 | - if ((m_exclmap(j,0) == 1.0) && | |
| 981 | - outer_reg.contains(skydir) && | |
| 1009 | + // Check if pixel is inside the background region | |
| 1010 | + if ((m_exclmap(j,0) == 0.0) && outer_reg.contains(skydir) && | |
| 982 | 1011 | !inner_reg.contains(skydir)) { |
| 983 | 1012 | |
| 984 | 1013 | // Update n_off |
| ... | ... | @@ -986,9 +1015,10 @@ void ctskymap::compute_ring_values(const GSkyMap& counts, |
| 986 | 1015 | |
| 987 | 1016 | // Update alpha_off |
| 988 | 1017 | alpha_off += sensitivity(j,0); |
| 1018 | + | |
| 989 | 1019 | } |
| 990 | 1020 | |
| 991 | - // Check if pixel is inside source region | |
| 1021 | + // ... otherwise check if pixel is inside source region | |
| 992 | 1022 | else if (roi_reg.contains(skydir)) { |
| 993 | 1023 | |
| 994 | 1024 | // Update n_on for significance computation |
| ... | ... | @@ -998,55 +1028,67 @@ void ctskymap::compute_ring_values(const GSkyMap& counts, |
| 998 | 1028 | alpha_on += sensitivity(j,0); |
| 999 | 1029 | |
| 1000 | 1030 | } // endif: source and background region check |
| 1001 | - | |
| 1002 | - } // endfor: sub-loop over pixels | |
| 1003 | 1031 | |
| 1004 | - // Compute alpha | |
| 1032 | + } // endfor: looped over pixels | |
| 1033 | + | |
| 1034 | + // Compute alpha. If the off region does not have any sensitivity then | |
| 1035 | + // set Non = Noff = 0 | |
| 1005 | 1036 | if (alpha_off == 0.0) { |
| 1006 | - // The off region does not have any sensitivity or there are no events | |
| 1007 | - // in either the on region or the off region | |
| 1008 | 1037 | alpha = 0.0; |
| 1009 | 1038 | non = 0.0; |
| 1010 | 1039 | noff = 0.0; |
| 1011 | - | |
| 1012 | - } else { | |
| 1040 | + } | |
| 1041 | + else { | |
| 1013 | 1042 | alpha = alpha_on / alpha_off; |
| 1014 | 1043 | } |
| 1044 | + | |
| 1045 | + // Return | |
| 1015 | 1046 | return; |
| 1016 | 1047 | } |
| 1017 | 1048 | |
| 1018 | 1049 | |
| 1019 | 1050 | /***********************************************************************//** |
| 1020 | - * @brief Generates a map of pixels to be excluded from background estimation | |
| 1051 | + * @brief Generates map of pixel exclusions | |
| 1021 | 1052 | * |
| 1022 | - * @param[in] filename Filename from which to take the exclusions from | |
| 1053 | + * @param[in] filename Exclusion file name. | |
| 1054 | + * | |
| 1055 | + * Generates a sky map of the pixels that are to be excluded from the | |
| 1056 | + * background estimation. Pixels with values different from 0 will be | |
| 1057 | + * excluded. | |
| 1023 | 1058 | ***************************************************************************/ |
| 1024 | 1059 | void ctskymap::map_exclusions(const GFilename& filename) |
| 1025 | 1060 | { |
| 1026 | - // Create the exlusion map and set all pixels to 1 | |
| 1061 | + // Create exlusion map | |
| 1027 | 1062 | m_exclmap = create_map(m_obs); |
| 1028 | - m_exclmap = 1.0; | |
| 1063 | + | |
| 1064 | + // Set all pixels to 0 (no pixel excluded) | |
| 1065 | + m_exclmap = 0.0; | |
| 1029 | 1066 | |
| 1030 | 1067 | // Make sure the exclusions filename is valid |
| 1031 | - if (!is_valid_filename(filename)) { | |
| 1032 | - return; | |
| 1033 | - } | |
| 1068 | + if (is_valid_filename(filename)) { | |
| 1034 | 1069 | |
| 1035 | - // Fill the exclusions based on the regions supplied | |
| 1036 | - if (filename.is_fits()) { | |
| 1037 | - map_exclusions_fits(filename); | |
| 1038 | - } else { | |
| 1039 | - map_exclusions_reg(filename); | |
| 1040 | - } // endif: generate exclusion map from filename | |
| 1070 | + // Fill the exclusions based on the regions supplied | |
| 1071 | + if (filename.is_fits()) { | |
| 1072 | + map_exclusions_fits(filename); | |
| 1073 | + } | |
| 1074 | + else { | |
| 1075 | + map_exclusions_reg(filename); | |
| 1076 | + } | |
| 1041 | 1077 | |
| 1078 | + } // endif: filename was valid | |
| 1079 | + | |
| 1080 | + // Return | |
| 1042 | 1081 | return; |
| 1043 | 1082 | } |
| 1044 | 1083 | |
| 1045 | 1084 | |
| 1046 | 1085 | /***********************************************************************//** |
| 1047 | - * @brief Fills exclusions map if file is a FITS image | |
| 1086 | + * @brief Fills exclusions map from FITS image | |
| 1048 | 1087 | * |
| 1049 | - * @param[in] filename Filename from which to take the exclusions from | |
| 1088 | + * @param[in] filename FITS image file name. | |
| 1089 | + * | |
| 1090 | + * Sets all exclusion map pixels to 1 that correspond to non-zero pixels in | |
| 1091 | + * the exclusion sky map FITS file. | |
| 1050 | 1092 | ***************************************************************************/ |
| 1051 | 1093 | void ctskymap::map_exclusions_fits(const GFilename& filename) |
| 1052 | 1094 | { |
| ... | ... | @@ -1054,26 +1096,33 @@ void ctskymap::map_exclusions_fits(const GFilename& filename) |
| 1054 | 1096 | GSkyMap inmap(filename); |
| 1055 | 1097 | |
| 1056 | 1098 | // Loop through the individual pixels in the exclusion map |
| 1057 | - GSkyDir dir; | |
| 1058 | - for (int i=0; i<m_exclmap.npix(); i++) { | |
| 1099 | + for (int i = 0; i < m_exclmap.npix(); ++i) { | |
| 1100 | + | |
| 1059 | 1101 | // Get the pixel direction |
| 1060 | - dir = m_exclmap.pix2dir(i); | |
| 1102 | + GSkyDir dir = m_exclmap.pix2dir(i); | |
| 1061 | 1103 | |
| 1062 | 1104 | // Check this sky position in the fits map |
| 1063 | - if (inmap.contains(dir) && (inmap(inmap.dir2inx(dir)) == 0.0)) { | |
| 1105 | + if (inmap.contains(dir) && (inmap(inmap.dir2inx(dir)) != 0.0)) { | |
| 1064 | 1106 | |
| 1065 | - // Set the pixel to 0 | |
| 1066 | - m_exclmap(i) = 0.0; | |
| 1107 | + // Set the pixel to 1 | |
| 1108 | + m_exclmap(i) = 1.0; | |
| 1067 | 1109 | |
| 1068 | 1110 | } // endif: pixel,region overlap check |
| 1069 | - } // endfor: Loop over exclusion map pixels | |
| 1111 | + | |
| 1112 | + } // endfor: looped over exclusion map pixels | |
| 1113 | + | |
| 1114 | + // Return | |
| 1115 | + return; | |
| 1070 | 1116 | } |
| 1071 | 1117 | |
| 1072 | 1118 | |
| 1073 | 1119 | /***********************************************************************//** |
| 1074 | - * @brief Fills exclusions map if file is a DS9 region file | |
| 1120 | + * @brief Fills exclusions map from DS9 region file | |
| 1121 | + * | |
| 1122 | + * @param[in] filename DS9 region file name. | |
| 1075 | 1123 | * |
| 1076 | - * @param[in] filename Filename from which to take the exclusions from | |
| 1124 | + * Sets all exclusion map pixels to 1 that are contained in any of the DS9 | |
| 1125 | + * regions. | |
| 1077 | 1126 | ***************************************************************************/ |
| 1078 | 1127 | void ctskymap::map_exclusions_reg(const GFilename& filename) |
| 1079 | 1128 | { |
| ... | ... | @@ -1081,18 +1130,20 @@ void ctskymap::map_exclusions_reg(const GFilename& filename) |
| 1081 | 1130 | GSkyRegions regions(filename); |
| 1082 | 1131 | |
| 1083 | 1132 | // Loop through the individual pixels in the exclusion map |
| 1084 | - for (int i=0; i<m_exclmap.npix(); i++) { | |
| 1133 | + for (int i = 0; i < m_exclmap.npix(); ++i) { | |
| 1085 | 1134 | |
| 1086 | 1135 | // Get the pixel position |
| 1087 | 1136 | GSkyDir dir = m_exclmap.pix2dir(i); |
| 1088 | 1137 | |
| 1089 | - // Check if GSkyDir overlaps with the regions | |
| 1138 | + // If pixel position overlaps with the regions | |
| 1090 | 1139 | if (regions.contains(dir)) { |
| 1091 | - // Set the pixel to 0 | |
| 1092 | - m_exclmap(i) = 0.0; | |
| 1140 | + m_exclmap(i) = 1.0; | |
| 1141 | + } | |
| 1093 | 1142 | |
| 1094 | - } // endif: pixel,region overlap check | |
| 1095 | - } // endfor: loop over exclusion map pixels | |
| 1143 | + } // endfor: looped over exclusion map pixels | |
| 1144 | + | |
| 1145 | + // Return | |
| 1146 | + return; | |
| 1096 | 1147 | } |
| 1097 | 1148 | |
| 1098 | 1149 | |
| ... | ... | @@ -1115,4 +1166,3 @@ double ctskymap::irf_kern::eval(const double& lnE) |
| 1115 | 1166 | // Return value |
| 1116 | 1167 | return value; |
| 1117 | 1168 | } |
| 1118 | - | ... | ... |
src/ctskymap/ctskymap.hpp
| ... | ... | @@ -100,21 +100,19 @@ protected: |
| 100 | 100 | double m_emin; //!< Minimum energy (TeV) |
| 101 | 101 | double m_emax; //!< Maximum energy (TeV) |
| 102 | 102 | std::string m_bkgsubtract; //!< Background subtraction method |
| 103 | + double m_roiradius; //!< Region of interest radius for RING bkg. | |
| 104 | + double m_inradius; //!< Inner ring radius for RING bkg. | |
| 105 | + double m_outradius; //!< Outer ring radius for RING bkg. | |
| 103 | 106 | bool m_publish; //!< Publish sky map? |
| 104 | 107 | GChatter m_chatter; //!< Chattiness |
| 105 | 108 | |
| 106 | - // Parameters for configuring the RING background subtraction | |
| 107 | - double m_roiradius; //!< Region of interest radius | |
| 108 | - double m_inradius; //!< Inner ring radius | |
| 109 | - double m_outradius; //!< Outer ring radius | |
| 110 | - | |
| 111 | 109 | // Protected members |
| 112 | - GSkyMap m_skymap; //!< Sky map | |
| 113 | - GSkyMap m_bkgmap; //!< Background map | |
| 114 | - GSkyMap m_sigmap; //!< Significance map | |
| 115 | - GSkyMap m_exclmap; //!< Exclusion map (if "RING" bkg subtraction) | |
| 116 | - GSkyMap m_alphamap; //!< Alpha map values (if "RING" subtraction) | |
| 117 | - GSkyMap m_onmap; //!< On counts map (if "RING" subtraction) | |
| 110 | + GSkyMap m_skymap; //!< Sky map | |
| 111 | + GSkyMap m_bkgmap; //!< Background map | |
| 112 | + GSkyMap m_sigmap; //!< Significance map | |
| 113 | + GSkyMap m_exclmap; //!< Exclusion map for RING background | |
| 114 | + GSkyMap m_alphamap; //!< Alpha map values for RING background | |
| 115 | + GSkyMap m_onmap; //!< On counts map for RING background | |
| 118 | 116 | |
| 119 | 117 | // Caching variables to prevent multiple computations of the same thing |
| 120 | 118 | std::vector<double> m_solidangle; //!< Cached pixel solid angles | ... | ... |
src/ctskymap/ctskymap.par
| ... | ... | @@ -46,7 +46,7 @@ bkgsubtract, s, a, NONE, NONE|IRF|RING,, "Background subtraction method" |
| 46 | 46 | roiradius, r, a, 0.0,,, "Source region radius for estimating on-counts (degrees)" |
| 47 | 47 | inradius, r, a, 0.6,,, "Inner ring radius (degrees)" |
| 48 | 48 | outradius, r, a, 0.8,,, "Outer ring radius (degrees)" |
| 49 | -regfile, f, h, NONE,,, "Exclusion regions definition file" | |
| 49 | +inexclusion, f, h, NONE,,, "Exclusion map or DS9 region file name" | |
| 50 | 50 | |
| 51 | 51 | # |
| 52 | 52 | # Standard parameters | ... | ... |
test/test_ctskymap.py
| ... | ... | @@ -237,31 +237,27 @@ class Test(test): |
| 237 | 237 | self._check_result_file('ctskymap_py4.fits[BACKGROUND]') |
| 238 | 238 | self._check_result_file('ctskymap_py4.fits[SIGNIFICANCE]') |
| 239 | 239 | |
| 240 | - # ================================ | |
| 241 | - # TEST RING BACKGROUND SUBTRACTION | |
| 242 | - # ================================ | |
| 243 | - | |
| 244 | - # Allocate ctskymap tool from observation container | |
| 240 | + # Test RING background subtraction | |
| 245 | 241 | skymap = ctools.ctskymap(obs) |
| 246 | 242 | skymap['emin'] = 0.1 |
| 247 | 243 | skymap['emax'] = 100 |
| 248 | - skymap['nxpix'] = 100 # Make region smaller since the 'RING' | |
| 249 | - skymap['nypix'] = 100 # method takes longer to run than 'IRF' | |
| 244 | + skymap['nxpix'] = 100 # Make region smaller since the 'RING' | |
| 245 | + skymap['nypix'] = 100 # method takes longer to run than 'IRF' | |
| 250 | 246 | skymap['binsz'] = 0.02 |
| 251 | 247 | skymap['coordsys'] = 'CEL' |
| 252 | 248 | skymap['proj'] = 'CAR' |
| 253 | 249 | skymap['xref'] = 83.63 |
| 254 | 250 | skymap['yref'] = 22.01 |
| 255 | 251 | skymap['bkgsubtract'] = 'RING' |
| 252 | + skymap['roiradius'] = 0.1 | |
| 253 | + skymap['inradius'] = 0.6 | |
| 254 | + skymap['outradius'] = 0.8 | |
| 255 | + skymap['inexclusion'] = 'NONE' | |
| 256 | 256 | skymap['caldb'] = self._caldb |
| 257 | 257 | skymap['irf'] = self._irf |
| 258 | 258 | skymap['outmap'] = 'ctskymap_py5.fits' |
| 259 | 259 | skymap['logfile'] = 'ctskymap_py5.log' |
| 260 | 260 | skymap['chatter'] = 4 |
| 261 | - skymap['roiradius'] = 0.1 | |
| 262 | - skymap['inradius'] = 0.6 | |
| 263 | - skymap['outradius'] = 0.8 | |
| 264 | - skymap['regfile'] = 'NONE' | |
| 265 | 261 | |
| 266 | 262 | # Execute tool |
| 267 | 263 | skymap.logFileOpen() # Needed to get a new log file | ... | ... |