Commit a5a1a27acf595c74c8b607bfd953194055310a38

Authored by Jürgen Knödlseder
1 parent a11d1205

Use MigMatrixNoTheta2cut_offaxis and AngularPSF2DEtrue_offaxis histograms to com…

…pute PSF and energy dispersion IRFs (#2135)
ChangeLog
1 -2017-06-23 1 +2017-06-27
2 2
3 * Bug fix version 1.3.1 released 3 * Bug fix version 1.3.1 released
4 ================================ 4 ================================
5 5
  6 + Use MigMatrixNoTheta2cut_offaxis and AngularPSF2DEtrue_offaxis histograms to
  7 + compute PSF and energy dispersion IRFs (#2135)
6 Properly forward working log file pointer in ctobssim::set_mc_id_names() (#2123) 8 Properly forward working log file pointer in ctobssim::set_mc_id_names() (#2123)
7 Correct computation of standard deviations in cssrcdetect 9 Correct computation of standard deviations in cssrcdetect
8 csobsselect accepts an observation container upon construction 10 csobsselect accepts an observation container upon construction
1 New Features and Important Changes in ctools 1.3.1 1 New Features and Important Changes in ctools 1.3.1
2 2
3 -23 June 2017 3 +27 June 2017
4 4
5 5
6 Introduction 6 Introduction
@@ -122,6 +122,10 @@ The csobsselect script now accepts an observation container upon construction. @@ -122,6 +122,10 @@ The csobsselect script now accepts an observation container upon construction.
122 122
123 The standard deviation computation in cssrcdetect has been corrected. 123 The standard deviation computation in cssrcdetect has been corrected.
124 124
  125 +The csroot2caldb script now uses the MigMatrixNoTheta2cut_offaxis and
  126 +AngularPSF2DEtrue_offaxis ROOT histograms to compute the energy dispersion matrix
  127 +and the PSF shape (#2135).
  128 +
125 129
126 Examples 130 Examples
127 -------- 131 --------
cscripts/csroot2caldb.py
@@ -29,7 +29,7 @@ from cscripts import calutils @@ -29,7 +29,7 @@ from cscripts import calutils
29 29
30 # Optional ROOT import 30 # Optional ROOT import
31 try: 31 try:
32 - from ROOT import TFile 32 + from ROOT import TFile, TH2F, TH3F
33 _has_root = True 33 _has_root = True
34 except ImportError: 34 except ImportError:
35 _has_root = False 35 _has_root = False
@@ -651,6 +651,78 @@ class csroot2caldb(ctools.cscript): @@ -651,6 +651,78 @@ class csroot2caldb(ctools.cscript):
651 # Return 651 # Return
652 return 652 return
653 653
  654 + def _root2psf_get_r68_and_r80(self, tfile):
  655 + """
  656 + Generates 68% and 80% containment radii histograms from
  657 + AngularPSF2DEtrue_offaxis histogram
  658 +
  659 + Parameters
  660 + ----------
  661 + tfile : `~ROOT.TFile`
  662 + ROOT file
  663 +
  664 + Returns
  665 + -------
  666 + r68, r80 : Tuple of `~ROOT.THF2`
  667 + 68% and 80% containment radius ROOT histograms
  668 + """
  669 + # Get relevant ROOT histograms
  670 + psf = tfile.Get('AngularPSF2DEtrue_offaxis')
  671 +
  672 + # Extract axes
  673 + energies = psf.GetXaxis()
  674 + dists = psf.GetYaxis()
  675 + offsets = psf.GetZaxis()
  676 +
  677 + # Extract number of bins in histogram
  678 + neng = energies.GetNbins()
  679 + ndist = dists.GetNbins()
  680 + noffset = offsets.GetNbins()
  681 +
  682 + # Create r68 and r80 histograms
  683 + r68 = TH2F('AngRes68Etrue_offaxis',
  684 + 'Angular resolution (68% containment)',
  685 + neng, energies.GetBinLowEdge(1), energies.GetBinUpEdge(neng),
  686 + noffset, offsets.GetBinLowEdge(1), offsets.GetBinUpEdge(noffset))
  687 + r80 = TH2F('AngRes80Etrue_offaxis',
  688 + 'Angular resolution (80% containment)',
  689 + neng, energies.GetBinLowEdge(1), energies.GetBinUpEdge(neng),
  690 + noffset, offsets.GetBinLowEdge(1), offsets.GetBinUpEdge(noffset))
  691 +
  692 + # Loop over all energy and offset angle bins
  693 + for ieng in range(neng):
  694 + for ioff in range(noffset):
  695 +
  696 + # Compute PDF integral
  697 + pdf_integral = 0.0
  698 + for idist in range(ndist):
  699 + pdf_integral += psf.GetBinContent(ieng+1,idist+1,ioff+1)
  700 +
  701 + # Compute 68% containment radius
  702 + pdf_68 = 0.0
  703 + r68_angle = 0.0
  704 + for idist in range(ndist):
  705 + pdf_68 += psf.GetBinContent(ieng+1,idist+1,ioff+1)
  706 + if pdf_68 > 0.68*pdf_integral:
  707 + r68_angle = dists.GetBinLowEdge(idist+1)
  708 + break
  709 +
  710 + # Compute 80% containment radius
  711 + pdf_80 = 0.0
  712 + r80_angle = 0.0
  713 + for idist in range(ndist):
  714 + pdf_80 += psf.GetBinContent(ieng+1,idist+1,ioff+1)
  715 + if pdf_80 > 0.80*pdf_integral:
  716 + r80_angle = dists.GetBinLowEdge(idist+1)
  717 + break
  718 +
  719 + # Set histogram values
  720 + r68.SetBinContent(ieng+1,ioff+1,r68_angle)
  721 + r80.SetBinContent(ieng+1,ioff+1,r80_angle)
  722 +
  723 + # Return
  724 + return r68, r80
  725 +
654 def _root2psf_gauss(self, tfile, irf, ds): 726 def _root2psf_gauss(self, tfile, irf, ds):
655 """ 727 """
656 Translate ROOT to CALDB point spread function extension 728 Translate ROOT to CALDB point spread function extension
@@ -677,7 +749,8 @@ class csroot2caldb(ctools.cscript): @@ -677,7 +749,8 @@ class csroot2caldb(ctools.cscript):
677 'Generate Gaussian point spread function extension') 749 'Generate Gaussian point spread function extension')
678 750
679 # Get relevant ROOT histograms 751 # Get relevant ROOT histograms
680 - r68 = tfile.Get('AngRes_offaxis') 752 + #r68 = tfile.Get('AngRes_offaxis')
  753 + r68, _ = self._root2psf_get_r68_and_r80(tfile)
681 754
682 # Extract number of bins in histogram 755 # Extract number of bins in histogram
683 neng = r68.GetXaxis().GetNbins() 756 neng = r68.GetXaxis().GetNbins()
@@ -757,8 +830,9 @@ class csroot2caldb(ctools.cscript): @@ -757,8 +830,9 @@ class csroot2caldb(ctools.cscript):
757 'Generate King point spread function extension') 830 'Generate King point spread function extension')
758 831
759 # Get relevant ROOT histograms 832 # Get relevant ROOT histograms
760 - r68 = tfile.Get('AngRes_offaxis')  
761 - r80 = tfile.Get('AngRes80_offaxis') 833 + #r68 = tfile.Get('AngRes_offaxis')
  834 + #r80 = tfile.Get('AngRes80_offaxis')
  835 + r68, r80 = self._root2psf_get_r68_and_r80(tfile)
762 836
763 # Extract number of bins in histogram 837 # Extract number of bins in histogram
764 neng = r68.GetXaxis().GetNbins() 838 neng = r68.GetXaxis().GetNbins()
@@ -869,6 +943,80 @@ class csroot2caldb(ctools.cscript): @@ -869,6 +943,80 @@ class csroot2caldb(ctools.cscript):
869 # Return 943 # Return
870 return 944 return
871 945
  946 + def _root2edisp_get_migra(self, tfile):
  947 + """
  948 + Generates migration matrix histogram from AngularPSF2DEtrue_offaxis
  949 + histogram
  950 +
  951 + Parameters
  952 + ----------
  953 + tfile : `~ROOT.TFile`
  954 + ROOT file
  955 +
  956 + Returns
  957 + -------
  958 + migra : `~ROOT.TH3F`
  959 + Migration matrix
  960 + """
  961 + # Get relevant ROOT histograms
  962 + matrix = tfile.Get('MigMatrixNoTheta2cut_offaxis')
  963 +
  964 + # Extract axes
  965 + ereco = matrix.GetXaxis()
  966 + etrue = matrix.GetYaxis()
  967 + offsets = matrix.GetZaxis()
  968 +
  969 + # Extract number of bins in histogram
  970 + nereco = ereco.GetNbins()
  971 + netrue = etrue.GetNbins()
  972 + noffset = offsets.GetNbins()
  973 +
  974 + # Set number of migration bins
  975 + nmigra = 300
  976 +
  977 + # Create migra histograms
  978 + migra = TH3F('EestOverEtrue_offaxis',
  979 + 'Migration',
  980 + netrue, etrue.GetBinLowEdge(1), etrue.GetBinUpEdge(netrue),
  981 + nmigra, 0.0, 3.0,
  982 + noffset, offsets.GetBinLowEdge(1), offsets.GetBinUpEdge(noffset))
  983 +
  984 + # Loop over true energies
  985 + for ietrue in range(netrue):
  986 +
  987 + # Get true energy in TeV
  988 + e_true = math.pow(10.0, migra.GetXaxis().GetBinCenter(ietrue+1))
  989 +
  990 + # Loop over migration values
  991 + for imigra in range(nmigra):
  992 +
  993 + # Get migration value
  994 + migration = migra.GetYaxis().GetBinCenter(imigra+1)
  995 +
  996 + # Compute reconstructed energy in TeV
  997 + e_reco = e_true * migration
  998 +
  999 + # Continue only if reconstructed energy is positive
  1000 + if e_reco > 0.0:
  1001 +
  1002 + # Get reconstructed bin
  1003 + ireco = ereco.FindFixBin(math.log10(e_reco))
  1004 +
  1005 + # Continue only if bin is valid
  1006 + if ireco > 0 and ireco <= nereco:
  1007 +
  1008 + # Loop over offset angles
  1009 + for ioff in range(noffset):
  1010 +
  1011 + # Get bin value
  1012 + value = matrix.GetBinContent(ireco,ietrue+1,ioff+1)
  1013 +
  1014 + # Set bin value
  1015 + migra.SetBinContent(ietrue+1,imigra+1,ioff+1,value)
  1016 +
  1017 + # Return
  1018 + return migra
  1019 +
872 def _root2edisp(self, tfile, irf, ds): 1020 def _root2edisp(self, tfile, irf, ds):
873 """ 1021 """
874 Translate ROOT to CALDB energy dispersion extension 1022 Translate ROOT to CALDB energy dispersion extension
@@ -889,7 +1037,8 @@ class csroot2caldb(ctools.cscript): @@ -889,7 +1037,8 @@ class csroot2caldb(ctools.cscript):
889 self._log_header1(gammalib.TERSE, 'Generate energy dispersion extension') 1037 self._log_header1(gammalib.TERSE, 'Generate energy dispersion extension')
890 1038
891 # Get relevant ROOT histograms 1039 # Get relevant ROOT histograms
892 - matrix = tfile.Get('EestOverEtrue_offaxis') 1040 + matrix = self._root2edisp_get_migra(tfile)
  1041 + #matrix = tfile.Get('EestOverEtrue_offaxis')
893 1042
894 # Write boundary keywords 1043 # Write boundary keywords
895 self._set_cif_keywords(ds['HDU_EDISP'], irf['EDISP_NAME'], 1044 self._set_cif_keywords(ds['HDU_EDISP'], irf['EDISP_NAME'],