Commit 169cd9220db83b8260e6d32e36d75fdc5f8d8242

Authored by Jürgen Knödlseder
1 parent 32febe17

Implement normalization of 2D histograms on 1D histograms

cscripts/csroot2caldb.par
@@ -24,6 +24,7 @@ id, s, a, South_50h,,, "Instrument Response Function identifier" @@ -24,6 +24,7 @@ id, s, a, South_50h,,, "Instrument Response Function identifier"
24 version, s, a, prod3,,, "Instrument Response Function version" 24 version, s, a, prod3,,, "Instrument Response Function version"
25 analysis, s, a, DESY,,, "Instrument Response Function analysis" 25 analysis, s, a, DESY,,, "Instrument Response Function analysis"
26 psftype, s, h, Gauss,Gauss|King,, "Point spread function type" 26 psftype, s, h, Gauss,Gauss|King,, "Point spread function type"
  27 +norm1d, b, h, no,,, "Normalize on 1D histograms"
27 rebin, b, h, no,,, "Rebin" 28 rebin, b, h, no,,, "Rebin"
28 eascale, r, h, 1.0,,, "Scaling factor for effective areas" 29 eascale, r, h, 1.0,,, "Scaling factor for effective areas"
29 bgdscale, r, h, 1.0,,, "Scaling factor for background rates" 30 bgdscale, r, h, 1.0,,, "Scaling factor for background rates"
cscripts/csroot2caldb.py
@@ -27,7 +27,7 @@ from datetime import datetime @@ -27,7 +27,7 @@ from datetime import datetime
27 27
28 # Optional ROOT import 28 # Optional ROOT import
29 try: 29 try:
30 - from ROOT import TFile, TH2F, TH3F 30 + from ROOT import TFile, TH1F, TH2F, TH3F
31 _has_root = True 31 _has_root = True
32 except: 32 except:
33 _has_root = False 33 _has_root = False
@@ -80,6 +80,7 @@ class csroot2caldb(ctools.cscript): @@ -80,6 +80,7 @@ class csroot2caldb(ctools.cscript):
80 self['analysis'].string() 80 self['analysis'].string()
81 self['version'].string() 81 self['version'].string()
82 self['psftype'].string() 82 self['psftype'].string()
  83 + self['norm1d'].boolean()
83 self['rebin'].boolean() 84 self['rebin'].boolean()
84 self['eascale'].real() 85 self['eascale'].real()
85 self['bgdscale'].real() 86 self['bgdscale'].real()
@@ -570,11 +571,23 @@ class csroot2caldb(ctools.cscript): @@ -570,11 +571,23 @@ class csroot2caldb(ctools.cscript):
570 # Continue only if effective area HDU has been opened 571 # Continue only if effective area HDU has been opened
571 if self._hdu_ea != None: 572 if self._hdu_ea != None:
572 573
  574 + # Get User parameters
  575 + norm1d = self['norm1d'].boolean()
  576 +
573 # Allocate ROOT 2D arrays 577 # Allocate ROOT 2D arrays
574 etrue = TH2F() 578 etrue = TH2F()
575 ereco = TH2F() 579 ereco = TH2F()
576 - file.GetObject("EffectiveAreaEtrue_offaxis", etrue)  
577 - file.GetObject("EffectiveArea_offaxis", ereco) 580 + file.GetObject('EffectiveAreaEtrue_offaxis', etrue)
  581 + file.GetObject('EffectiveArea_offaxis', ereco)
  582 +
  583 + # Normalize 2D histogram on on-axis 1D histogram
  584 + if norm1d:
  585 + etrue_1D = TH1F()
  586 + ereco_1D = TH1F()
  587 + file.GetObject('EffectiveAreaEtrue', etrue_1D)
  588 + file.GetObject('EffectiveArea', ereco_1D)
  589 + self._renorm_onaxis(etrue, etrue_1D)
  590 + self._renorm_onaxis(ereco, ereco_1D)
578 591
579 # Rebin etrue histogram 592 # Rebin etrue histogram
580 if rebin: 593 if rebin:
@@ -929,10 +942,19 @@ class csroot2caldb(ctools.cscript): @@ -929,10 +942,19 @@ class csroot2caldb(ctools.cscript):
929 # Continue only if background HDU has been opened 942 # Continue only if background HDU has been opened
930 if self._hdu_bgd != None: 943 if self._hdu_bgd != None:
931 944
  945 + # Get User parameters
  946 + norm1d = self['norm1d'].boolean()
  947 +
932 # Allocate ROOT 2D array 948 # Allocate ROOT 2D array
933 array = TH2F() 949 array = TH2F()
934 file.GetObject('BGRatePerSqDeg_offaxis', array) 950 file.GetObject('BGRatePerSqDeg_offaxis', array)
935 951
  952 + # Normalize 2D histogram on on-axis 1D histogram
  953 + if norm1d:
  954 + array_1D = TH1F()
  955 + file.GetObject('BGRatePerSqDeg', array_1D)
  956 + self._renorm_onaxis(array, array_1D)
  957 +
936 # Set boundaries 958 # Set boundaries
937 bounds = self._make_3D(array, self._hdu_bgd, None, 'deg') 959 bounds = self._make_3D(array, self._hdu_bgd, None, 'deg')
938 for b in bounds: 960 for b in bounds:
@@ -970,7 +992,7 @@ class csroot2caldb(ctools.cscript): @@ -970,7 +992,7 @@ class csroot2caldb(ctools.cscript):
970 hdu[name].unit(unit) 992 hdu[name].unit(unit)
971 993
972 # Do we have a LO axis? If not we have a HI axis 994 # Do we have a LO axis? If not we have a HI axis
973 - if name[-2:] == "LO": 995 + if name[-2:] == 'LO':
974 low = True 996 low = True
975 else: 997 else:
976 low = False 998 low = False
@@ -988,6 +1010,83 @@ class csroot2caldb(ctools.cscript): @@ -988,6 +1010,83 @@ class csroot2caldb(ctools.cscript):
988 # Return 1010 # Return
989 return 1011 return
990 1012
  1013 + def _renorm_onaxis(self, hist2D, hist1D):
  1014 + """
  1015 + Renormalise 2D histogram (energy,offset) on 1D histogram (energy)
  1016 +
  1017 + This method makes sure that a 2D histogram has the same onaxis values
  1018 + as the corresponding 1D histogram.
  1019 +
  1020 + Parameters
  1021 + ----------
  1022 + hist2D : `~ROOT.TH2F`
  1023 + ROOT 2D histogram.
  1024 + hist1D : `~ROOT.TH1F`
  1025 + ROOT 1D histogram.
  1026 + """
  1027 + # Get 2D dimensions
  1028 + neng = hist2D.GetXaxis().GetNbins()
  1029 + noffset = hist2D.GetYaxis().GetNbins()
  1030 +
  1031 + # Continue only if the 1D and 2D histograms have the same number
  1032 + # of energy bins
  1033 + if neng != hist1D.GetXaxis().GetNbins():
  1034 + # Write header
  1035 + if self._logTerse():
  1036 + self._log('Difference in energy binning between 2D histogram'
  1037 + ' "%s" and 1D histogram "%s".\n' %
  1038 + (hist2D.GetName(), hist1D.GetName()))
  1039 + else:
  1040 + # Write header
  1041 + if self._logTerse():
  1042 + self._log('Renormalize 2D histogram "%s" on 1D histogram "%s".\n' %
  1043 + (hist2D.GetName(), hist1D.GetName()))
  1044 +
  1045 + # Get a copy of 2D histogram
  1046 + hist2D_copy = hist2D.Clone()
  1047 +
  1048 + # Divide 2D histogram by onaxis values to remove the energy
  1049 + # dependence
  1050 + for ieng in range(neng):
  1051 + onaxis = hist1D.GetBinContent(ieng+1)
  1052 + if onaxis > 0.0:
  1053 + for ioff in range(noffset):
  1054 + value = hist2D.GetBinContent(ieng+1,ioff+1) / onaxis
  1055 + hist2D.SetBinContent(ieng+1,ioff+1,value)
  1056 +
  1057 + # Smooth in energy direction to reduce statistical fluctuations
  1058 + for ieng in range(neng):
  1059 + for ioff in range(noffset):
  1060 + if ieng == 0:
  1061 + value = (2.0 * hist2D.GetBinContent(ieng+1,ioff+1) +
  1062 + 1.0 * hist2D.GetBinContent(ieng+2,ioff+1)) / 3.0
  1063 + elif ieng == neng-1:
  1064 + value = (2.0 * hist2D.GetBinContent(ieng+1,ioff+1) +
  1065 + 1.0 * hist2D.GetBinContent(ieng+0,ioff+1)) / 3.0
  1066 + else:
  1067 + value = (2.0 * hist2D.GetBinContent(ieng+1,ioff+1) +
  1068 + 1.0 * hist2D.GetBinContent(ieng+0,ioff+1) +
  1069 + 1.0 * hist2D.GetBinContent(ieng+2,ioff+1)) / 4.0
  1070 + hist2D_copy.SetBinContent(ieng+1,ioff+1,value)
  1071 +
  1072 + # Normalize now for an onaxis value of 1
  1073 + for ieng in range(neng):
  1074 + onaxis = hist2D_copy.GetBinContent(ieng+1,1)
  1075 + if onaxis > 0.0:
  1076 + for ioff in range(noffset):
  1077 + value = hist2D_copy.GetBinContent(ieng+1,ioff+1) / onaxis
  1078 + hist2D_copy.SetBinContent(ieng+1,ioff+1,value)
  1079 +
  1080 + # Put back the energy dependence
  1081 + for ieng in range(neng):
  1082 + onaxis = hist1D.GetBinContent(ieng+1)
  1083 + for ioff in range(noffset):
  1084 + value = hist2D_copy.GetBinContent(ieng+1,ioff+1) * onaxis
  1085 + hist2D.SetBinContent(ieng+1,ioff+1,value)
  1086 +
  1087 + # Return
  1088 + return
  1089 +
991 def _make_2D(self, array, hdu, name, unit, scale=1.0): 1090 def _make_2D(self, array, hdu, name, unit, scale=1.0):
992 """ 1091 """
993 Make 2D matrix as function of energy and offset angle from a 1092 Make 2D matrix as function of energy and offset angle from a