00001
00002 VERSION='1.00'
00003 import os,sys,time
00004 import optparse
00005 from RecoLuminosity.LumiDB import pileupParser
00006 from RecoLuminosity.LumiDB import selectionParser
00007 from math import exp
00008 from math import sqrt
00009
00010 def parseInputFile(inputfilename):
00011 '''
00012 output ({run:[ls:[inlumi, meanint]]})
00013 '''
00014 selectf=open(inputfilename,'r')
00015 inputfilecontent=selectf.read()
00016 p=pileupParser.pileupParser(inputfilecontent)
00017
00018
00019 runlsbyfile=p.runsandls()
00020 return runlsbyfile
00021
00022 def fillPileupHistogram (lumiInfo, calcOption, hist, minbXsec, Nbins):
00023 '''
00024 lumiinfo:[intlumi per LS, mean interactions ]
00025
00026 intlumi is the deadtime corrected average integraged lumi per lumisection
00027 '''
00028
00029 LSintLumi = lumiInfo[0]
00030 RMSInt = lumiInfo[1]*minbXsec
00031 AveNumInt = lumiInfo[2]*minbXsec
00032
00033 coeff = 0
00034 if RMSInt > 0:
00035 coeff = 1.0/RMSInt/sqrt(6.283185)
00036 expon = 2.0*RMSInt*RMSInt
00037
00038
00039
00040 ProbFromRMS = []
00041
00042
00043 if RMSInt > 0:
00044 for obs in range (Nbins):
00045 val = hist.GetBinCenter(obs+1)
00046 prob = coeff*exp(-1.0*(val-AveNumInt)*(val-AveNumInt)/expon)
00047 ProbFromRMS.append(prob)
00048 else:
00049 obs = hist.FindBin(AveNumInt)
00050 for bin in range (Nbins):
00051 ProbFromRMS.append(0.0)
00052 ProbFromRMS[obs] = 1.0
00053 if AveNumInt < 1.0E-5:
00054 ProbFromRMS[obs] = 0.
00055
00056 if calcOption == 'true':
00057 if RMSInt > 0:
00058 totalProb = 0
00059 for obs in range (Nbins):
00060 prob = ProbFromRMS[obs]
00061 val = hist.GetBinCenter(obs+1)
00062
00063 totalProb += prob
00064 hist.Fill (val, prob * LSintLumi)
00065 if totalProb < 1:
00066 hist.Fill (val, (1 - totalProb) * LSintLumi)
00067 else:
00068 hist.Fill(AveNumInt,LSintLumi)
00069 else:
00070 totalProb = 0
00071 Peak = 0
00072 BinWidth = hist.GetBinWidth(1)
00073 for obs in range (Nbins):
00074 Peak = hist.GetBinCenter(obs+1)
00075 RMSWeight = ProbFromRMS[obs]
00076 for bin in range (Nbins):
00077 val = hist.GetBinCenter(bin+1)-0.5*BinWidth
00078 prob = ROOT.TMath.Poisson (val, Peak)
00079 totalProb += prob
00080 hist.Fill (val, prob * LSintLumi * RMSWeight)
00081 if totalProb < 1:
00082 hist.Fill (Peak, (1 - totalProb) * LSintLumi)
00083
00084 return hist
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 if __name__ == '__main__':
00097
00098 parser = optparse.OptionParser ("Usage: %prog [--options] output.root",
00099 description = "Script to estimate pileup distribution using xing instantaneous luminosity information and minimum bias cross section. Output is TH1D stored in root file")
00100
00101
00102 CalculationModeChoices = ['truth', 'observed']
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 parser.add_option('-o',dest='outputfile',action='store',
00113 default='PileupCalc.root',
00114 help='output root file')
00115 parser.add_option('-i',dest='inputfile',action='store',
00116 help='Input Run/LS file for your analysis in JSON format (required)')
00117 parser.add_option('--inputLumiJSON',dest='inputLumiJSON',action='store',
00118 help='Input Lumi/Pileup file in JSON format (required)')
00119 parser.add_option('--calcMode',dest='calcMode',action='store',
00120 help='Calculate either True ="true" or Observed="observed" distributions')
00121 parser.add_option('--minBiasXsec',dest='minBiasXsec',action='store',
00122 type=float,
00123 default=73500,
00124 help='Minimum bias cross section assumed (in microbbarn), default %default microbarn')
00125 parser.add_option('--maxPileupBin',dest='maxPileupBin',action='store',
00126 type=int,
00127 default=25,
00128 help='Maximum value of pileup histogram, default %default')
00129 parser.add_option('--numPileupBins',dest='numPileupBins',action='store',
00130 type=int,
00131 default=1000,
00132 help='number of bins in pileup histogram, default %default')
00133 parser.add_option('--pileupHistName',dest='pileupHistName',action='store',
00134 default='pileup',
00135 help='name of pileup histogram, default %default')
00136 parser.add_option('--verbose',dest='verbose',action='store_true',help='verbose mode for printing' )
00137
00138
00139 try:
00140 (options, args) = parser.parse_args()
00141 except Exception , e:
00142 print e
00143 if not args:
00144 parser.print_usage()
00145 sys.exit()
00146 if len (args) != 1:
00147 parser.print_usage()
00148 raise RuntimeError, "Exactly one output file must be given"
00149 output = args[0]
00150
00151
00152
00153 if options.verbose:
00154 print 'General configuration'
00155 print '\toutputfile: ',options.outputfile
00156 print '\tAction: ',options.calcMode, 'luminosity distribution will be calculated'
00157 print '\tinput selection file: ',options.inputfile
00158 print '\tMinBiasXsec: ',options.minBiasXsec
00159 print '\tmaxPileupBin: ',options.maxPileupBin
00160 print '\tnumPileupBins: ',options.numPileupBins
00161
00162 import ROOT
00163 pileupHist = ROOT.TH1D (options.pileupHistName,options.pileupHistName,
00164 options.numPileupBins,
00165 0., options.maxPileupBin)
00166
00167 nbins = options.numPileupBins
00168 upper = options.maxPileupBin
00169
00170 inpf = open (options.inputfile, 'r')
00171 inputfilecontent = inpf.read()
00172 inputRange = selectionParser.selectionParser (inputfilecontent).runsandls()
00173
00174
00175
00176 if options.calcMode in ['true','observed']:
00177 inputPileupRange=parseInputFile(options.inputLumiJSON)
00178
00179
00180
00181
00182 for (run, lslist) in sorted (inputRange.iteritems() ):
00183
00184
00185 if run in inputPileupRange.keys():
00186
00187 LSPUlist = inputPileupRange[run]
00188
00189 for LSnumber in lslist:
00190 if LSnumber in LSPUlist.keys():
00191
00192 lumiInfo = LSPUlist[LSnumber]
00193
00194 fillPileupHistogram (lumiInfo, options.calcMode,
00195 pileupHist, options.minBiasXsec, nbins)
00196 else:
00197 print "Run %d, LumiSection %d not found in Lumi/Pileup input file. Check your files!" \
00198 % (run,LSnumber)
00199
00200 else:
00201 print "Run %d not found in Lumi/Pileup input file. Check your files!" % (run)
00202
00203
00204
00205
00206
00207
00208 histFile = ROOT.TFile.Open (output, 'recreate')
00209 if not histFile:
00210 raise RuntimeError, \
00211 "Could not open '%s' as an output root file" % output
00212 pileupHist.Write()
00213
00214
00215 histFile.Close()
00216 sys.exit()
00217
00218 else:
00219 print "must specify a pileup calculation mode via --calcMode true or --calcMode observed"
00220 sys.exit()