Commit 145877c4512bd410fda163b8386f2e4a420203a1

Authored by Jürgen Knödlseder
1 parent 2af5a9b8

Implement King profile PSF, Prod1 and test IRF production.

Showing 1 changed file with 239 additions and 35 deletions
scripts/cta_root2caldb.py
... ... @@ -78,28 +78,29 @@ class caldb():
78 78 self.val_date = "2014-01-30"
79 79 self.val_time = "00:00:00"
80 80 self.ref_time = 51544.0
  81 + self.cal_name = "NAME("+obsid+")"
81 82 self.cal_version = "VERSION(Prod2)"
82 83 self.cal_cut = "CLASS(BEST)"
83 84 self.cal_analysis = "ANALYSIS(DESY)"
84 85 #
85 86 self.ea_name = "EFF_AREA"
86 87 self.ea_doc = "CAL/GEN/92-019"
87   - self.ea_bounds = [self.cal_obsid, self.cal_version, self.cal_cut, self.cal_analysis]
  88 + self.ea_bounds = [self.cal_name, self.cal_version, self.cal_cut, self.cal_analysis]
88 89 self.ea_desc = "CTA effective area"
89 90 #
90 91 self.psf_name = "RPSF"
91 92 self.psf_doc = "CAL/GEN/92-020"
92   - self.psf_bounds = [self.cal_obsid, self.cal_version, self.cal_cut, self.cal_analysis]
  93 + self.psf_bounds = [self.cal_name, self.cal_version, self.cal_cut, self.cal_analysis]
93 94 self.psf_desc = "CTA point spread function"
94 95 #
95 96 self.edisp_name = "EDISP"
96 97 self.edisp_doc = "???"
97   - self.edisp_bounds = [self.cal_obsid, self.cal_version, self.cal_cut, self.cal_analysis]
  98 + self.edisp_bounds = [self.cal_name, self.cal_version, self.cal_cut, self.cal_analysis]
98 99 self.edisp_desc = "CTA energy dispersion"
99 100 #
100 101 self.bgd_name = "BGD"
101 102 self.bgd_doc = "???"
102   - self.bgd_bounds = [self.cal_obsid, self.cal_version, self.cal_cut, self.cal_analysis]
  103 + self.bgd_bounds = [self.cal_name, self.cal_version, self.cal_cut, self.cal_analysis]
103 104 self.bgd_desc = "CTA background"
104 105  
105 106 # Create directory structure
... ... @@ -683,7 +684,7 @@ class caldb():
683 684 # Return boundary information
684 685 return bounds
685 686  
686   - def root2caldb(self, filename, rebin=False):
  687 + def root2caldb(self, filename, rebin=False, psftype="Gauss"):
687 688 """
688 689 Translate ROOT to CALDB information.
689 690  
... ... @@ -699,7 +700,7 @@ class caldb():
699 700 self.root2ea(file, rebin=rebin)
700 701  
701 702 # Create point spread function
702   - self.root2psf(file)
  703 + self.root2psf(file, psftype)
703 704  
704 705 # Create energy dispersion
705 706 self.root2edisp(file)
... ... @@ -760,7 +761,28 @@ class caldb():
760 761 # Return
761 762 return
762 763  
763   - def root2psf(self, file):
  764 + def root2psf(self, file, psftype):
  765 + """
  766 + Translate ROOT to CALDB point spread function extension.
  767 + Parameters:
  768 + file - ROOT file.
  769 + psftype - PSF type (Gauss, King)
  770 + Keywords:
  771 + None
  772 + """
  773 + # Continue only if point spread function HDU has been opened
  774 + if self.hdu_psf != None:
  775 +
  776 + # King profile PSF
  777 + if psftype == "King":
  778 + self.root2psf_king(file)
  779 + else:
  780 + self.root2psf_gauss(file)
  781 +
  782 + # Return
  783 + return
  784 +
  785 + def root2psf_gauss(self, file):
764 786 """
765 787 Translate ROOT to CALDB point spread function extension. The following
766 788 ROOT histograms are used:
... ... @@ -809,6 +831,7 @@ class caldb():
809 831 bounds = self.make_2D(r68, self.hdu_psf, None, "deg")
810 832 for b in bounds:
811 833 self.psf_bounds.append(b)
  834 + self.psf_bounds.append("PSF(GAUSS)")
812 835 self.set_cif_keywords(self.hdu_psf, self.psf_name, \
813 836 self.psf_bounds, self.psf_desc)
814 837  
... ... @@ -833,6 +856,133 @@ class caldb():
833 856 # Return
834 857 return
835 858  
  859 + def root2psf_king(self, file):
  860 + """
  861 + Translate ROOT to CALDB point spread function extension. The following
  862 + ROOT histograms are used:
  863 +
  864 + AngRes_offaxis
  865 + AngRes80_offaxis
  866 +
  867 + Parameters:
  868 + file - ROOT file.
  869 + Keywords:
  870 + None
  871 + """
  872 + # Continue only if point spread function HDU has been opened
  873 + if self.hdu_psf != None:
  874 +
  875 + # Allocate ROOT 2D arrays
  876 + r68 = TH2F()
  877 + r80 = TH2F()
  878 +
  879 + # Read 68% and 80% containment histograms
  880 + file.GetObject("AngRes_offaxis", r68)
  881 + file.GetObject("AngRes80_offaxis", r80)
  882 + neng = r68.GetXaxis().GetNbins()
  883 + noffset = r68.GetYaxis().GetNbins()
  884 +
  885 + # Initialise parameter maps by cloning the r68 2D map
  886 + gamma2D = r68.Clone()
  887 + sigma2D = r68.Clone()
  888 +
  889 + # Compute gamma and sigma values
  890 + for ioff in range(noffset):
  891 +
  892 + # Initialise last results
  893 + last_gamma = 0.0
  894 + last_sigma = 0.0
  895 +
  896 + for ieng in range(neng):
  897 +
  898 + # Extract radii
  899 + r_68 = r68.GetBinContent(ieng+1,ioff+1)
  900 + r_80 = r80.GetBinContent(ieng+1,ioff+1)
  901 +
  902 + # Initialise results
  903 + gamma = 0.0
  904 + sigma = 0.0
  905 +
  906 + # Continue only if both radii are positive
  907 + if r_68 > 0 and r_80 > 0:
  908 +
  909 + # Derive constants for equation to solve
  910 + a = 1.0 - 0.68
  911 + b = 1.0 - 0.80
  912 + c = r_68*r_68/(r_80*r_80)
  913 +
  914 + # Solve equation (a^x-1)/(b^x-1)=c for x using secant
  915 + # method. Stop when we are better than 1e-6.
  916 + x1 = -0.5
  917 + x2 = -1.0
  918 + f1 = (math.pow(a,x1) - 1.0)/(math.pow(b,x1) - 1.0) - c
  919 + f2 = (math.pow(a,x2) - 1.0)/(math.pow(b,x2) - 1.0) - c
  920 + iter = 0
  921 + while True:
  922 + x = x1 - f1 * (x1-x2)/(f1-f2)
  923 + f = (math.pow(a,x) - 1.0)/(math.pow(b,x) - 1.0) - c
  924 + iter += 1
  925 + if abs(f) < 1.0e-6:
  926 + break
  927 + else:
  928 + f2 = f1
  929 + x2 = x1
  930 + f1 = f
  931 + x1 = x
  932 +
  933 + # Compute gamma.
  934 + if x < 0.0:
  935 + gamma = 1.0 - 1.0/x
  936 + else:
  937 + gamma = 1.0
  938 +
  939 + # Compute sigma
  940 + denominator = 2.0 * gamma * (math.pow(a, x) - 1.0)
  941 + if denominator > 0.0:
  942 + sigma = r_68 * math.sqrt(1.0/denominator)
  943 + else:
  944 + denominator = 2.0 * gamma * (math.pow(b, x) - 1.0)
  945 + if denominator > 0.0:
  946 + sigma = r_80 * math.sqrt(1.0/denominator)
  947 + else:
  948 + gamma = 0.0
  949 + sigma = 0.0
  950 +
  951 + # Handle special case that no results were found.
  952 + # This takes care of pixels that are ill defined
  953 + # in the MC file.
  954 + if gamma == 0.0 and sigma == 0.0:
  955 + gamma = last_gamma
  956 + sigma = last_sigma
  957 +
  958 + # Store surrent result as last result
  959 + last_gamma = gamma
  960 + last_sigma = sigma
  961 +
  962 + # Show results on console
  963 + #print(ioff,ieng,gamma,sigma,x,f,iter)
  964 +
  965 + # Set bin contents
  966 + gamma2D.SetBinContent(ieng+1,ioff+1,gamma)
  967 + sigma2D.SetBinContent(ieng+1,ioff+1,sigma)
  968 +
  969 + # Set boundaries
  970 + bounds = self.make_2D(r68, self.hdu_psf, None, "deg")
  971 + for b in bounds:
  972 + self.psf_bounds.append(b)
  973 + self.psf_bounds.append("PSF(KING)")
  974 + self.set_cif_keywords(self.hdu_psf, self.psf_name, \
  975 + self.psf_bounds, self.psf_desc)
  976 +
  977 + # GAMMA
  978 + self.make_2D(gamma2D, self.hdu_psf, "GAMMA", "")
  979 +
  980 + # SIGMA
  981 + self.make_2D(sigma2D, self.hdu_psf, "SIGMA", "deg")
  982 +
  983 + # Return
  984 + return
  985 +
836 986 def root2edisp(self, file):
837 987 """
838 988 Translate ROOT to CALDB energy dispersion extension. The following ROOT
... ... @@ -907,7 +1057,7 @@ class caldb():
907 1057 # Return
908 1058 return
909 1059  
910   - def set_cif_keywords(self, hdu, name, bounds,desc):
  1060 + def set_cif_keywords(self, hdu, name, bounds, desc):
911 1061 """
912 1062 Set standard CIF keywords for extension.
913 1063 """
... ... @@ -935,86 +1085,137 @@ class caldb():
935 1085 return
936 1086  
937 1087  
  1088 +#===================#
  1089 +# Set test database #
  1090 +#===================#
  1091 +def set_test():
  1092 + """
  1093 + Set Prod1 IFAE database.
  1094 + """
  1095 + # Set database attributes
  1096 + path = "/project-data/cta/performance/prod1/IFAEOffaxisPerformanceBEI_May2012"
  1097 + rebin = True
  1098 +
  1099 + # Set database content
  1100 + db = [{'inst': "e", 'id': "IFAE20120510_50h",
  1101 + 'path': path, 'rebin': rebin, 'psftype': "Gauss",
  1102 + 'file': "SubarrayE_IFAE_50hours_20120510_offaxis.root"},
  1103 + {'inst': "e", 'id': "IFAE20120510_50h_King",
  1104 + 'path': path, 'rebin': rebin, 'psftype': "King",
  1105 + 'file': "SubarrayE_IFAE_50hours_20120510_offaxis.root"}]
  1106 +
  1107 + # Return database
  1108 + return db
  1109 +
  1110 +
  1111 +#=========================#
  1112 +# Set Prod1 IFAE database #
  1113 +#=========================#
  1114 +def set_prod1_ifae():
  1115 + """
  1116 + Set Prod1 IFAE database.
  1117 + """
  1118 + # Set database attributes
  1119 + path = "/project-data/cta/performance/prod1/IFAEOffaxisPerformanceBEI_May2012"
  1120 + rebin = True
  1121 + psftype = "Gauss"
  1122 +
  1123 + # Set database content
  1124 + db = [{'inst': "b", 'id': "IFAE20120510_50h",
  1125 + 'path': path, 'rebin': rebin, 'psftype': psftype,
  1126 + 'file': "SubarrayB_IFAE_50hours_20120510_offaxis.root"},
  1127 + {'inst': "e", 'id': "IFAE20120510_50h",
  1128 + 'path': path, 'rebin': rebin, 'psftype': psftype,
  1129 + 'file': "SubarrayE_IFAE_50hours_20120510_offaxis.root"},
  1130 + {'inst': "i", 'id': "IFAE20120510_50h",
  1131 + 'path': path, 'rebin': rebin, 'psftype': psftype,
  1132 + 'file': "SubarrayI_IFAE_50hours_20120510_offaxis.root"}]
  1133 +
  1134 + # Return database
  1135 + return db
  1136 +
  1137 +
938 1138 #=========================#
939 1139 # Set Prod2 DESY database #
940 1140 #=========================#
941 1141 def set_prod2_desy():
942 1142 """
943   - Set Prod2 database.
  1143 + Set Prod2 DESY database.
944 1144 """
945 1145 # Set database attributes
946   - path = "/project-data/cta/performance/prod2/Performance_DESY_20140128"
947   - rebin = False
  1146 + path = "/project-data/cta/performance/prod2/Performance_DESY_20140128"
  1147 + rebin = False
  1148 + psftype = "Gauss"
948 1149  
949 1150 # Set database content
950 1151 db = [{'inst': "aar", 'id': "DESY20140105_50h",
951   - 'path': path, 'rebin': rebin,
  1152 + 'path': path, 'rebin': rebin, 'psftype': psftype,
952 1153 'file': "DESY.d20140105.Erec1.V2.ID0NIM2.prod2-Aar-NS.S.2a.180000s.root"},
953 1154 {'inst': "aar", 'id': "DESY20140105_50h_0deg",
954   - 'path': path, 'rebin': rebin,
  1155 + 'path': path, 'rebin': rebin, 'psftype': psftype,
955 1156 'file': "DESY.d20140105.Erec1.V2.ID0_0degNIM2.prod2-Aar-NS.S.2a.180000s.root"},
956 1157 {'inst': "aar", 'id': "DESY20140105_50h_180deg",
957   - 'path': path, 'rebin': rebin,
  1158 + 'path': path, 'rebin': rebin, 'psftype': psftype,
958 1159 'file': "DESY.d20140105.Erec1.V2.ID0_180degNIM2.prod2-Aar-NS.S.2a.180000s.root"},
959 1160  
960 1161 {'inst': "aar500", 'id': "DESY20140105_50h",
961   - 'path': path, 'rebin': rebin,
  1162 + 'path': path, 'rebin': rebin, 'psftype': psftype,
962 1163 'file': "DESY.d20140105.Erec1.V2.ID0NIM2.prod2-Aar-500m-NS.S.2a.180000s.root"},
963 1164 {'inst': "aar500", 'id': "DESY20140105_50h_0deg",
964   - 'path': path, 'rebin': rebin,
  1165 + 'path': path, 'rebin': rebin, 'psftype': psftype,
965 1166 'file': "DESY.d20140105.Erec1.V2.ID0_0degNIM2.prod2-Aar-500m-NS.S.2a.180000s.root"},
966 1167 {'inst': "aar500", 'id': "DESY20140105_50h_180deg",
967   - 'path': path, 'rebin': rebin,
  1168 + 'path': path, 'rebin': rebin, 'psftype': psftype,
968 1169 'file': "DESY.d20140105.Erec1.V2.ID0_180degNIM2.prod2-Aar-500m-NS.S.2a.180000s.root"},
969 1170  
970 1171 {'inst': "leoncito", 'id': "DESY20140105_50h",
971   - 'path': path, 'rebin': rebin,
  1172 + 'path': path, 'rebin': rebin, 'psftype': psftype,
972 1173 'file': "DESY.d20140105.Erec1.V2.ID0NIM2.prod2-LeoncitoPP-NS.S.2a.180000s.root"},
973 1174 {'inst': "leoncito", 'id': "DESY20140105_50h_0deg",
974   - 'path': path, 'rebin': rebin,
  1175 + 'path': path, 'rebin': rebin, 'psftype': psftype,
975 1176 'file': "DESY.d20140105.Erec1.V2.ID0_0degNIM2.prod2-LeoncitoPP-NS.S.2a.180000s.root"},
976 1177 {'inst': "leoncito", 'id': "DESY20140105_50h_180deg",
977   - 'path': path, 'rebin': rebin,
  1178 + 'path': path, 'rebin': rebin, 'psftype': psftype,
978 1179 'file': "DESY.d20140105.Erec1.V2.ID0_180degNIM2.prod2-LeoncitoPP-NS.S.2a.180000s.root"},
979 1180  
980 1181 {'inst': "sac", 'id': "DESY20140105_50h",
981   - 'path': path, 'rebin': rebin,
  1182 + 'path': path, 'rebin': rebin, 'psftype': psftype,
982 1183 'file': "DESY.d20140105.Erec1.V2.ID0NIM2.prod2-SAC100-NS.S.2a.180000s.root"},
983 1184 {'inst': "sac", 'id': "DESY20140105_50h_0deg",
984   - 'path': path, 'rebin': rebin,
  1185 + 'path': path, 'rebin': rebin, 'psftype': psftype,
985 1186 'file': "DESY.d20140105.Erec1.V2.ID0_0degNIM2.prod2-SAC100-NS.S.2a.180000s.root"},
986 1187 {'inst': "sac", 'id': "DESY20140105_50h_180deg",
987   - 'path': path, 'rebin': rebin,
  1188 + 'path': path, 'rebin': rebin, 'psftype': psftype,
988 1189 'file': "DESY.d20140105.Erec1.V2.ID0_180degNIM2.prod2-SAC100-NS.S.2a.180000s.root"},
989 1190  
990 1191 {'inst': "spm", 'id': "DESY20140105_50h",
991   - 'path': path, 'rebin': rebin,
  1192 + 'path': path, 'rebin': rebin, 'psftype': psftype,
992 1193 'file': "DESY.d20140105.Erec1.V2.ID0NIM2.prod2-SPM-NS.N.2NN.180000s.root"},
993 1194 {'inst': "spm", 'id': "DESY20140105_50h_0deg",
994   - 'path': path, 'rebin': rebin,
  1195 + 'path': path, 'rebin': rebin, 'psftype': psftype,
995 1196 'file': "DESY.d20140105.Erec1.V2.ID0_0degNIM2.prod2-SPM-NS.N.2NN.180000s.root"},
996 1197 {'inst': "spm", 'id': "DESY20140105_50h_180deg",
997   - 'path': path, 'rebin': rebin,
  1198 + 'path': path, 'rebin': rebin, 'psftype': psftype,
998 1199 'file': "DESY.d20140105.Erec1.V2.ID0_180degNIM2.prod2-SPM-NS.N.2NN.180000s.root"},
999 1200  
1000 1201 {'inst': "tenerife", 'id': "DESY20140105_50h",
1001   - 'path': path, 'rebin': rebin,
  1202 + 'path': path, 'rebin': rebin, 'psftype': psftype,
1002 1203 'file': "DESY.d20140105.Erec1.V2.ID0NIM2.prod2-Tenerife-NS.N.2NN.180000s.root"},
1003 1204 {'inst': "tenerife", 'id': "DESY20140105_50h_0deg",
1004   - 'path': path, 'rebin': rebin,
  1205 + 'path': path, 'rebin': rebin, 'psftype': psftype,
1005 1206 'file': "DESY.d20140105.Erec1.V2.ID0_0degNIM2.prod2-Tenerife-NS.N.2NN.180000s.root"},
1006 1207 {'inst': "tenerife", 'id': "DESY20140105_50h_180deg",
1007   - 'path': path, 'rebin': rebin,
  1208 + 'path': path, 'rebin': rebin, 'psftype': psftype,
1008 1209 'file': "DESY.d20140105.Erec1.V2.ID0_180degNIM2.prod2-Tenerife-NS.N.2NN.180000s.root"},
1009 1210  
1010 1211 {'inst': "us", 'id': "DESY20140105_50h",
1011   - 'path': path, 'rebin': rebin,
  1212 + 'path': path, 'rebin': rebin, 'psftype': psftype,
1012 1213 'file': "DESY.d20140105.Erec1.V2.ID0NIM2.prod2-US-NS.N.2NN.180000s.root"},
1013 1214 {'inst': "us", 'id': "DESY20140105_50h_0deg",
1014   - 'path': path, 'rebin': rebin,
  1215 + 'path': path, 'rebin': rebin, 'psftype': psftype,
1015 1216 'file': "DESY.d20140105.Erec1.V2.ID0_0degNIM2.prod2-US-NS.N.2NN.180000s.root"},
1016 1217 {'inst': "us", 'id': "DESY20140105_50h_180deg",
1017   - 'path': path, 'rebin': rebin,
  1218 + 'path': path, 'rebin': rebin, 'psftype': psftype,
1018 1219 'file': "DESY.d20140105.Erec1.V2.ID0_180degNIM2.prod2-US-NS.N.2NN.180000s.root"}]
1019 1220  
1020 1221 # Return database
... ... @@ -1045,7 +1246,9 @@ if __name__ == &#39;__main__&#39;:
1045 1246 - Ebias_offaxis (2D) - Energy bias
1046 1247 """
1047 1248 # Get database
1048   - entries = set_prod2_desy()
  1249 + entries = set_test()
  1250 + #entries = set_prod1_ifae()
  1251 + #entries = set_prod2_desy()
1049 1252  
1050 1253 # Loop over entries
1051 1254 for entry in entries:
... ... @@ -1053,8 +1256,9 @@ if __name__ == &#39;__main__&#39;:
1053 1256 # Get attributes
1054 1257 inst = entry['inst']
1055 1258 path = entry['path']
1056   - rebin = entry['rebin']
1057 1259 id = entry['id']
  1260 + rebin = entry['rebin']
  1261 + psftype = entry['psftype']
1058 1262 filename = path+"/"+entry['file']
1059 1263  
1060 1264 # Allocate caldb entry
... ... @@ -1064,4 +1268,4 @@ if __name__ == &#39;__main__&#39;:
1064 1268 irf.open("file")
1065 1269  
1066 1270 # Translate ROOT to CALDB information
1067   - irf.root2caldb(filename, rebin=rebin)
  1271 + irf.root2caldb(filename, rebin=rebin, psftype=psftype)
... ...