Commit cbe8c7475ba27dcda1a44fec99f72ecfb9735a11

Authored by Jürgen Knödlseder
1 parent cbe733dd

Write migration matrix instead of ERES and EBIAS into FITS file

Showing 1 changed file with 143 additions and 4 deletions
scripts/cta_root2caldb.py
... ... @@ -3,7 +3,7 @@
3 3 # This script generates IRFs in the CALDB format of HEASARC using ROOT 2D
4 4 # performance files.
5 5 # -------------------------------------------------------------------------
6   -# Copyright (C) 2011-2014 Juergen Knoedlseder
  6 +# Copyright (C) 2011-2015 Juergen Knoedlseder
7 7 # -------------------------------------------------------------------------
8 8 #
9 9 # This program is free software: you can redistribute it and/or modify
... ... @@ -24,7 +24,7 @@
24 24 # - gammalib
25 25 # - pyroot
26 26 # ==========================================================================
27   -from ROOT import TFile, TH1F, TH2F
  27 +from ROOT import TFile, TH1F, TH2F, TH3F
28 28 from gammalib import *
29 29 from datetime import datetime
30 30 import math
... ... @@ -818,6 +818,113 @@ class caldb():
818 818  
819 819 # Return boundary information
820 820 return bounds
  821 +
  822 + def make_3D_migra(self, array, hdu, name, unit, scale=1.0):
  823 + """
  824 + Make 3D cube as function of ETRUE, MIGRA and THETA form ROOT 3D
  825 + histogram. If the HDU has already the columns, this method will
  826 + simply add another data column.
  827 + If name==None, the method will not append any data column.
  828 +
  829 + Parameters:
  830 + array - ROOT 3D histogram.
  831 + hdu - FITS HDU.
  832 + name - Data column name.
  833 + unit - Data unit.
  834 + Keywords:
  835 + scale - Scaling factor for histogram values.
  836 + """
  837 + # Extract Etrue, Eobs/Etrue and offset angle vectors
  838 + etrue = array.GetXaxis()
  839 + netrue = etrue.GetNbins()
  840 + migra = array.GetYaxis()
  841 + nmigra = migra.GetNbins()
  842 + offsets = array.GetZaxis()
  843 + noffset = offsets.GetNbins()
  844 + ewidth = [] # in MeV
  845 + for ieng in range(netrue):
  846 + ewidth.append(pow(10.0, etrue.GetBinUpEdge(ieng+1) +6.0) - \
  847 + pow(10.0, etrue.GetBinLowEdge(ieng+1)+6.0))
  848 +
  849 + # Attach columns to HDU. We do this only if they do not yet
  850 + # exist. This allows adding columns to the same HDU in successive
  851 + # calls of this method
  852 + #
  853 + # ETRUE_LO
  854 + if not hdu.contains("ETRUE_LO"):
  855 + hdu.append(GFitsTableFloatCol("ETRUE_LO", 1, netrue))
  856 + hdu["ETRUE_LO"].unit("TeV")
  857 + for ieng in range(netrue):
  858 + e_lo = pow(10.0, etrue.GetBinLowEdge(ieng+1))
  859 + hdu["ETRUE_LO"][0,ieng] = e_lo
  860 + #
  861 + # ETRUE_HI
  862 + if not hdu.contains("ETRUE_HI"):
  863 + hdu.append(GFitsTableFloatCol("ETRUE_HI", 1, netrue))
  864 + hdu["ETRUE_HI"].unit("TeV")
  865 + for ieng in range(netrue):
  866 + e_hi = pow(10.0, etrue.GetBinUpEdge(ieng+1))
  867 + hdu["ETRUE_HI"][0,ieng] = e_hi
  868 + #
  869 + # MIGRA_LO
  870 + if not hdu.contains("MIGRA_LO"):
  871 + hdu.append(GFitsTableFloatCol("MIGRA_LO", 1, nmigra))
  872 + hdu["MIGRA_LO"].unit("")
  873 + for ieng in range(nmigra):
  874 + e_lo = pow(10.0, migra.GetBinLowEdge(ieng+1))
  875 + hdu["MIGRA_LO"][0,ieng] = e_lo
  876 + #
  877 + # MIGRA_HI
  878 + if not hdu.contains("MIGRA_HI"):
  879 + hdu.append(GFitsTableFloatCol("MIGRA_HI", 1, nmigra))
  880 + hdu["MIGRA_HI"].unit("")
  881 + for ieng in range(nmigra):
  882 + e_hi = pow(10.0, migra.GetBinUpEdge(ieng+1))
  883 + hdu["MIGRA_HI"][0,ieng] = e_hi
  884 + #
  885 + # THETA_LO
  886 + if not hdu.contains("THETA_LO"):
  887 + hdu.append(GFitsTableFloatCol("THETA_LO", 1, noffset))
  888 + hdu["THETA_LO"].unit("deg")
  889 + for ioff in range(noffset):
  890 + o_lo = offsets.GetBinLowEdge(ioff+1)
  891 + hdu["THETA_LO"][0,ioff] = o_lo
  892 + #
  893 + # THETA_LO
  894 + if not hdu.contains("THETA_HI"):
  895 + hdu.append(GFitsTableFloatCol("THETA_HI", 1, noffset))
  896 + hdu["THETA_HI"].unit("deg")
  897 + for ioff in range(noffset):
  898 + o_hi = offsets.GetBinUpEdge(ioff+1)
  899 + hdu["THETA_HI"][0,ioff] = o_hi
  900 + #
  901 + # "NAME"
  902 + if name != None and not hdu.contains(name):
  903 + hdu.append(GFitsTableFloatCol(name, 1, netrue*nmigra*noffset))
  904 + hdu[name].unit(unit)
  905 + hdu[name].dim([netrue, nmigra, noffset])
  906 + for ioff in range(noffset):
  907 + for imigra in range(nmigra):
  908 + for ieng in range(netrue):
  909 + index = ieng + (imigra + ioff * nmigra) * netrue
  910 + value = array.GetBinContent(ieng+1,imigra+1,ioff+1)
  911 + hdu[name][0,index] = value * scale
  912 +
  913 + # Collect boundary information
  914 + bd_eng = "ETRUE(%.4f-%.2f)TeV" % \
  915 + (pow(10.0, etrue.GetBinLowEdge(1)), \
  916 + pow(10.0, etrue.GetBinUpEdge(netrue)))
  917 + bd_migra = "MIGRA(%.4f-%.2f)TeV" % \
  918 + (pow(10.0, migra.GetBinLowEdge(1)), \
  919 + pow(10.0, migra.GetBinUpEdge(nmigra)))
  920 + bd_off = "THETA(%.2f-%.2f)deg" % \
  921 + (offsets.GetBinLowEdge(1), \
  922 + offsets.GetBinUpEdge(noffset))
  923 + bd_phi = "PHI(0-360)deg"
  924 + bounds = [bd_eng, bd_migra, bd_off, bd_phi]
  925 +
  926 + # Return boundary information
  927 + return bounds
821 928  
822 929 def root2caldb(self, filename, rebin=False, psftype="Gauss", scale=1.0):
823 930 """
... ... @@ -838,7 +945,7 @@ class caldb():
838 945 self.root2psf(file, psftype)
839 946  
840 947 # Create energy dispersion
841   - self.root2edisp(file)
  948 + self.root2edisp_migra(file)
842 949  
843 950 # Create background
844 951 #self.root2bgd(file)
... ... @@ -1126,7 +1233,7 @@ class caldb():
1126 1233 # Return
1127 1234 return
1128 1235  
1129   - def root2edisp(self, file):
  1236 + def root2edisp_2D(self, file):
1130 1237 """
1131 1238 Translate ROOT to CALDB energy dispersion extension. The following ROOT
1132 1239 histograms are used:
... ... @@ -1164,6 +1271,38 @@ class caldb():
1164 1271 # Return
1165 1272 return
1166 1273  
  1274 + def root2edisp_migra(self, file):
  1275 + """
  1276 + Translate ROOT to CALDB energy dispersion extension. The following ROOT
  1277 + histograms are used:
  1278 +
  1279 + EestOverEtrue_offaxis -> MATRIX
  1280 +
  1281 + Parameters:
  1282 + file - ROOT file.
  1283 + Keywords:
  1284 + None
  1285 + """
  1286 + # Continue only if energy dispersion HDU has been opened
  1287 + if self.hdu_edisp != None:
  1288 +
  1289 + # Allocate ROOT 3D array
  1290 + matrix = TH3F()
  1291 + file.GetObject("EestOverEtrue_offaxis", matrix)
  1292 +
  1293 + # Set boundaries
  1294 + bounds = self.make_3D_migra(matrix, self.hdu_edisp, None, "")
  1295 + for b in bounds:
  1296 + self.edisp_bounds.append(b)
  1297 + self.set_cif_keywords(self.hdu_edisp, self.edisp_name, \
  1298 + self.edisp_bounds, self.edisp_desc)
  1299 +
  1300 + # MATRIX
  1301 + self.make_3D_migra(matrix, self.hdu_edisp, "MATRIX", "")
  1302 +
  1303 + # Return
  1304 + return
  1305 +
1167 1306 def root2bgd(self, file):
1168 1307 """
1169 1308 Translate ROOT to CALDB background extension. The following ROOT
... ...