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 24 version, s, a, prod3,,, "Instrument Response Function version"
25 25 analysis, s, a, DESY,,, "Instrument Response Function analysis"
26 26 psftype, s, h, Gauss,Gauss|King,, "Point spread function type"
  27 +norm1d, b, h, no,,, "Normalize on 1D histograms"
27 28 rebin, b, h, no,,, "Rebin"
28 29 eascale, r, h, 1.0,,, "Scaling factor for effective areas"
29 30 bgdscale, r, h, 1.0,,, "Scaling factor for background rates"
... ...
cscripts/csroot2caldb.py
... ... @@ -27,7 +27,7 @@ from datetime import datetime
27 27  
28 28 # Optional ROOT import
29 29 try:
30   - from ROOT import TFile, TH2F, TH3F
  30 + from ROOT import TFile, TH1F, TH2F, TH3F
31 31 _has_root = True
32 32 except:
33 33 _has_root = False
... ... @@ -80,6 +80,7 @@ class csroot2caldb(ctools.cscript):
80 80 self['analysis'].string()
81 81 self['version'].string()
82 82 self['psftype'].string()
  83 + self['norm1d'].boolean()
83 84 self['rebin'].boolean()
84 85 self['eascale'].real()
85 86 self['bgdscale'].real()
... ... @@ -570,11 +571,23 @@ class csroot2caldb(ctools.cscript):
570 571 # Continue only if effective area HDU has been opened
571 572 if self._hdu_ea != None:
572 573  
  574 + # Get User parameters
  575 + norm1d = self['norm1d'].boolean()
  576 +
573 577 # Allocate ROOT 2D arrays
574 578 etrue = TH2F()
575 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 592 # Rebin etrue histogram
580 593 if rebin:
... ... @@ -929,10 +942,19 @@ class csroot2caldb(ctools.cscript):
929 942 # Continue only if background HDU has been opened
930 943 if self._hdu_bgd != None:
931 944  
  945 + # Get User parameters
  946 + norm1d = self['norm1d'].boolean()
  947 +
932 948 # Allocate ROOT 2D array
933 949 array = TH2F()
934 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 958 # Set boundaries
937 959 bounds = self._make_3D(array, self._hdu_bgd, None, 'deg')
938 960 for b in bounds:
... ... @@ -970,7 +992,7 @@ class csroot2caldb(ctools.cscript):
970 992 hdu[name].unit(unit)
971 993  
972 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 996 low = True
975 997 else:
976 998 low = False
... ... @@ -988,6 +1010,83 @@ class csroot2caldb(ctools.cscript):
988 1010 # Return
989 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 1090 def _make_2D(self, array, hdu, name, unit, scale=1.0):
992 1091 """
993 1092 Make 2D matrix as function of energy and offset angle from a
... ...