2 from __future__
import print_function
3 from builtins
import range
7 from RecoLuminosity.LumiDB
import pileupParser
8 from RecoLuminosity.LumiDB
import selectionParser
10 from scipy.special
import loggamma
14 output ({run:[ls:[inlumi, meanint]]}) 16 selectf=open(inputfilename,
'r') 17 inputfilecontent=selectf.read() 21 runlsbyfile=p.runsandls()
34 cErf = 1.0 - (b1*T + b2*T*T + b3*T*T*T)*np.exp(-1.0*X*X)
47 return np.where(xInput < 0, -cErf, cErf)
51 return np.where(x == 0., np.exp(-par),
52 np.exp(x*np.log(par)-loggamma(x+1)-par))
59 self.
edges = np.linspace(xMin, xMax, num=num+1)
65 return np.floor((x-self.
xMin)*self.
num/(self.
xMax-self.
xMin)).astype(int)
71 lumiinfo:[intlumi per LS, mean interactions ] 73 intlumi is the deadtime corrected average integrated lumi per lumisection 76 LSintLumi = lumiInfo[0]
77 RMSInt = lumiInfo[1]*minbXsec
78 AveNumInt = lumiInfo[2]*minbXsec
82 areaAbove =
MyErf((AveNumInt-binning.edges)/Sqrt2/RMSInt)
84 ProbFromRMS = .5*(areaAbove[:-1]-areaAbove[1:])
86 ProbFromRMS = np.zeros(hContents.shape)
87 obs = binning.find(AveNumInt)
88 if ( obs < binning.num )
and ( AveNumInt >= 1.0E-5 ):
89 ProbFromRMS[obs] = 1.0
91 if calcOption ==
'true':
93 hContents += ProbFromRMS*LSintLumi
94 totalProb = np.sum(ProbFromRMS)
96 if 1.0-totalProb > 0.01:
97 print(
"Run %d, LS %d: Significant probability density outside of your histogram (mean %.2f," % (run, ls, AveNumInt))
98 print(
"rms %.2f, integrated probability %.3f). Consider using a higher value of --maxPileupBin." % (RMSInt, totalProb))
100 hContents[obs] += LSintLumi
102 if not hasattr(binning,
"poissConv"):
105 binning.edges[:-1,np.newaxis],
106 binning.centers[np.newaxis,:])
108 prob = np.sum(binning.poissConv * ProbFromRMS[np.newaxis,:], axis=1)
109 hContents += prob*LSintLumi
122 if __name__ ==
'__main__':
124 parser = argparse.ArgumentParser(description =
"Script to estimate pileup distribution using bunch instantaneous luminosity information and minimum bias cross section. Outputs a TH1D of the pileup distribution stored in a ROOT file.")
127 req_group = parser.add_argument_group(
'required arguments')
128 req_group.add_argument(
'outputfile', action=
'store', help=
'output ROOT file')
129 req_group.add_argument(
'-i',
'--input', dest=
'inputfile', action=
'store', required=
True,
130 help=
'input Run/LS file for your analysis in JSON format')
131 req_group.add_argument(
'-j',
'--inputLumiJSON', dest=
'inputLumiJSON', action=
'store', required=
True,
132 help=
'input pileup file in JSON format')
133 req_group.add_argument(
'-c',
'--calcMode' ,dest=
'calcMode', action=
'store',
134 help=
'calculate either "true" or "observed" distributions',
135 choices=[
'true',
'observed'], required=
True)
138 parser.add_argument(
'-x',
'--minBiasXsec', dest=
'minBiasXsec', action=
'store',
139 type=float, default=69200.0,
140 help=
'minimum bias cross section to use (in microbarn) (default: %(default).0f)')
141 parser.add_argument(
'-m',
'--maxPileupBin', dest=
'maxPileupBin', action=
'store',
142 type=int, default=100, help=
'maximum value of pileup histogram (default: %(default)d)')
143 parser.add_argument(
'-n',
'--numPileupBins', dest=
'numPileupBins', action=
'store',
144 type=int, default=1000, help=
'number of bins in pileup histogram (default: %(default)d)')
145 parser.add_argument(
'--pileupHistName', dest=
'pileupHistName', action=
'store',
146 default=
'pileup', help=
'name of pileup histogram (default: %(default)s)')
147 parser.add_argument(
'-v',
'--verbose', dest=
'verbose', action=
'store_true',
148 help=
'verbose mode for printing' )
150 options = parser.parse_args()
151 output = options.outputfile
154 print(
'General configuration')
155 print(
'\toutputfile:' ,options.outputfile)
156 print(
'\tAction:' ,options.calcMode,
'luminosity distribution will be calculated')
157 print(
'\tinput selection file:', options.inputfile)
158 print(
'\tinput lumi JSON:', options.inputLumiJSON)
159 print(
'\tMinBiasXsec:', options.minBiasXsec)
160 print(
'\tmaxPileupBin:', options.maxPileupBin)
161 print(
'\tnumPileupBins:', options.numPileupBins)
164 hContents = np.zeros(binning.centers.shape)
166 inpf = open(options.inputfile,
'r') 167 inputfilecontent = inpf.read() 177 for (run, lslist)
in sorted (inputRange.items()):
180 if run
in inputPileupRange.keys():
182 LSPUlist = inputPileupRange[run]
184 for LSnumber
in lslist:
185 if LSnumber
in LSPUlist.keys():
187 lumiInfo = LSPUlist[LSnumber]
191 options.minBiasXsec, run, LSnumber)
193 print(
"Run %d, LumiSection %d not found in Lumi/Pileup input file. Check your files!" \
197 print(
"Run %d not found in Lumi/Pileup input file. Check your files!" % (run))
204 pileupHist = ROOT.TH1D(options.pileupHistName, options.pileupHistName,
205 options.numPileupBins, 0., options.maxPileupBin)
206 for i,ct
in enumerate(hContents):
207 pileupHist.SetBinContent(i+1, ct)
209 histFile = ROOT.TFile.Open(output,
'recreate')
211 raise RuntimeError(
"Could not open '%s' as an output root file" % output)
214 print(
"Wrote output histogram to", output)
def fillPileupHistogram(lumiInfo, calcOption, binning, hContents, minbXsec, run, ls)
def parseInputFile(inputfilename)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
def __init__(self, num, xMin, xMax)