Commit cf079ae01f3a526d6bc4b35fc1642b08b6729554

Authored by Jürgen Knödlseder
1 parent de558787

Add RING background method to ctskymap (#2207)

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)
... ...
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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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&amp; 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,, &quot;Background subtraction method&quot;
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
... ...