00001
00002
00003
00004
00005
00006
00007
00008
00009 import os,os.path,sys,math,array,datetime,time,calendar,re
00010 import coral
00011
00012 from RecoLuminosity.LumiDB import argparse,sessionManager,lumiTime,CommonUtil,lumiCalcAPI,lumiCorrections,lumiParameters
00013 MINFILL=1800
00014 MAXFILL=9999
00015 allfillname='allfills.txt'
00016
00017 def getFillFromDB(schema,fillnum):
00018 '''
00019 output: {run:starttime}
00020 '''
00021 runtimesInFill={}
00022 fillrundict=lumiCalcAPI.fillrunMap(schema,fillnum)
00023 if len(fillrundict)>0:
00024 runs=fillrundict.values()[0]
00025 runlsdict=dict(zip(runs,[None]*len(runs)))
00026 runresult=lumiCalcAPI.runsummary(schema,runlsdict)
00027 for perrundata in runresult:
00028 runtimesInFill[perrundata[0]]=perrundata[7]
00029 return runtimesInFill
00030
00031 def listfilldir(indir):
00032 '''
00033 list all fills contained in the given dir
00034 input: indir
00035 output: [fill]
00036 '''
00037 fillnamepat=r'^[0-9]{4}$'
00038 p=re.compile(fillnamepat)
00039 processedfills=[]
00040 dirList=os.listdir(indir)
00041 for fname in dirList:
00042 if p.match(fname) and os.path.isdir(os.path.join(indir,fname)):
00043 allfs=os.listdir(os.path.join(indir,fname))
00044 for myfile in allfs:
00045 sumfilenamepat=r'^[0-9]{4}_bxsum_CMS.txt$'
00046 s=re.compile(sumfilenamepat)
00047 if s.match(myfile):
00048
00049 processedfills.append(int(fname))
00050 return processedfills
00051
00052 def lastcompleteFill(infile):
00053 '''
00054 parse infile to find LASTCOMPLETEFILL
00055 input: input file name
00056 output: last completed fill number
00057 '''
00058 lastfill=None
00059 hlinepat=r'(LASTCOMPLETEFILL )([0-9]{4})'
00060 h=re.compile(hlinepat)
00061 dqmfile=open(infile,'r')
00062 for line in dqmfile:
00063 result=h.match(line)
00064 if result:
00065 lastfill=result.group(2)
00066 break
00067 return int(lastfill)
00068
00069 def calculateSpecificLumi(lumi,lumierr,beam1intensity,beam1intensityerr,beam2intensity,beam2intensityerr):
00070 '''
00071 calculate specific lumi
00072 input: instlumi, instlumierror,beam1intensity,beam1intensityerror,beam2intensity,beam2intensityerror
00073 output (specific lumi value,specific lumi error)
00074 '''
00075 specificlumi=0.0
00076 specificlumierr=0.0
00077 if beam1intensity<0: beam1intensity=0
00078 if beam2intensity<0: beam2intensity=0
00079 if beam1intensity!=0.0 and beam2intensity!=0.0:
00080 specificlumi=float(lumi)/(float(beam1intensity)*float(beam2intensity))
00081 specificlumierr=specificlumi*math.sqrt(lumierr**2/lumi**2+beam1intensityerr**2/beam1intensity**2+beam2intensityerr**2/beam2intensity**2)
00082 return (specificlumi,specificlumierr)
00083
00084 def getFillFromFile(fillnum,inputdir):
00085 '''
00086 parse fill_xxx.txt files in the input directory for runs, starttime in the fill
00087 input: fillnumber, input dir
00088 output: {run:tarttime}
00089 '''
00090 runtimesInFill={}
00091
00092 for filename in os.listdir(inputdir):
00093 mpat=r'^fill_[0-9]{4}.txt$'
00094 m=re.compile(mpat)
00095 if m.match(filename) is None:
00096 continue
00097 filename=filename.strip()
00098 if filename.find('.')==-1: continue
00099 basename,extension=filename.split('.')
00100 if not extension or extension!='txt':
00101 continue
00102 if basename.find('_')==-1: continue
00103 prefix,number=basename.split('_')
00104 if not number : continue
00105 if fillnum!=int(number):continue
00106 f=open(os.path.join(inputdir,'fill_'+number+'.txt'),'r')
00107 for line in f:
00108 l=line.strip()
00109 fields=l.split(',')
00110 if len(fields)<2 : continue
00111 runtimesInFill[int(fields[0])]=fields[1]
00112 f.close()
00113 return runtimesInFill
00114
00115
00116 def filltofiles(allfills,runsperfill,runtimes,dirname):
00117 '''
00118 write runnumber:starttime map per fill to files
00119 '''
00120 f=open(os.path.join(dirname,allfillname),'w')
00121 for fill in allfills:
00122 print >>f,'%d'%(fill)
00123 f.close()
00124 for fill,runs in runsperfill.items():
00125 filename='fill_'+str(fill)+'.txt'
00126 if len(runs)!=0:
00127 f=open(os.path.join(dirname,filename),'w')
00128 for run in runs:
00129 print >>f,'%d,%s'%(run,runtimes[run])
00130 f.close()
00131
00132 def specificlumiTofile(fillnum,filldata,outdir):
00133
00134
00135
00136
00137
00138
00139 if not filldata:
00140 print 'empty input data, do nothing for fill ',fillnum
00141 return
00142 timedict={}
00143 filloutdir=os.path.join(outdir,str(fillnum))
00144 if not os.path.exists(filloutdir):
00145 os.mkdir(filloutdir)
00146 for cmsbxidx,perbxdata in filldata.items():
00147 lhcbucket=0
00148 if cmsbxidx!=0:
00149 lhcbucket=(cmsbxidx-1)*10+1
00150 a=sorted(perbxdata,key=lambda x:x[0])
00151 filename=str(fillnum)+'_lumi_'+str(lhcbucket)+'_CMS.txt'
00152 linedata=[]
00153 for perlsdata in a:
00154 ts=int(perlsdata[0])
00155 beamstatusfrac=perlsdata[1]
00156 lumi=perlsdata[2]
00157 lumierror=perlsdata[3]
00158
00159
00160 speclumi=perlsdata[4]
00161 speclumierror= perlsdata[5]
00162 if lumi>0:
00163 linedata.append([ts,beamstatusfrac,lumi,lumierror,speclumi,speclumierror])
00164 if not timedict.has_key(ts):
00165 timedict[ts]=[]
00166 timedict[ts].append([beamstatusfrac,lumi,lumierror,speclumi,speclumierror])
00167 if len(linedata)>10:
00168 f=open(os.path.join(filloutdir,filename),'w')
00169 for line in linedata:
00170 print >>f, '%d\t%e\t%e\t%e\t%e\t%e'%(line[0],line[1],line[2],line[3],line[4],line[5])
00171 f.close()
00172
00173 summaryfilename=str(fillnum)+'_lumi_CMS.txt'
00174 f=None
00175 lstimes=timedict.keys()
00176 lstimes.sort()
00177 fillseg=[]
00178 lscounter=0
00179 for lstime in lstimes:
00180 allvalues=timedict[lstime]
00181 transposedvalues=CommonUtil.transposed(allvalues,0.0)
00182 bstatfrac=transposedvalues[0][0]
00183 lumivals=transposedvalues[1]
00184 lumitot=sum(lumivals)
00185 if bstatfrac==1.0 :
00186 fillseg.append([lstime,lumitot])
00187 lumierrs=transposedvalues[2]
00188 lumierrortot=math.sqrt(sum(map(lambda x:x**2,lumierrs)))
00189 specificvals=transposedvalues[3]
00190 specificavg=sum(specificvals)/float(len(specificvals))
00191 specificerrs=transposedvalues[4]
00192 specifictoterr=math.sqrt(sum(map(lambda x:x**2,specificerrs)))
00193 specificerravg=specifictoterr/float(len(specificvals))
00194 if lscounter==0:
00195 f=open(os.path.join(filloutdir,summaryfilename),'w')
00196 lscounter+=1
00197 print >>f,'%d\t%e\t%e\t%e\t%e\t%e'%(lstime,bstatfrac,lumitot,lumierrortot,specificavg,specificerravg)
00198 if f is not None:
00199 f.close()
00200
00201 fillsummaryfilename=str(fillnum)+'_bxsum_CMS.txt'
00202 f=open(os.path.join(filloutdir,fillsummaryfilename),'w')
00203 if len(fillseg)==0:
00204 print >>f,'%s'%('#no stable beams')
00205 f.close()
00206 return
00207 previoustime=fillseg[0][0]
00208 boundarytime=fillseg[0][0]
00209
00210 summaryls={}
00211 summaryls[boundarytime]=[]
00212 for [lstime,lumitot] in fillseg:
00213 if lstime-previoustime>50.0:
00214 boundarytime=lstime
00215
00216 summaryls[boundarytime]=[]
00217
00218 summaryls[boundarytime].append([lstime,lumitot])
00219 previoustime=lstime
00220
00221
00222 summarylstimes=summaryls.keys()
00223 summarylstimes.sort()
00224 lumip=lumiParameters.ParametersObject()
00225 for bts in summarylstimes:
00226 startts=bts
00227 tsdatainseg=summaryls[bts]
00228
00229 stopts=tsdatainseg[-1][0]
00230 plu=max(CommonUtil.transposed(tsdatainseg,0.0)[1])
00231 lui=sum(CommonUtil.transposed(tsdatainseg,0.0)[1])*lumip.lslengthsec()
00232 print >>f,'%d\t%d\t%e\t%e'%(startts,stopts,plu,lui)
00233 f.close()
00234
00235 def getSpecificLumi(schema,fillnum,inputdir,xingMinLum=0.0,norm='pp7TeV',withcorrection=True,amodetag='PROTPHYS',bxAlgo='OCC1'):
00236 '''
00237 specific lumi in 1e-30 (ub-1s-1) unit
00238 lumidetail occlumi in 1e-27
00239 1309_lumi_401_CMS.txt
00240 time(in seconds since January 1,2011,00:00:00 UTC) stab(fraction of time spent in stable beams for this time bin) l(lumi in Hz/ub) dl(point-to-point error on lumi in Hz/ub) sl(specific lumi in Hz/ub) dsl(error on specific lumi)
00241 20800119.0 1 -0.889948 0.00475996848729 0.249009 0.005583287562 -0.68359 6.24140208607 0.0 0.0 0.0 0.0 0.0 0.0 0.0383576 0.00430892097862 0.0479095 0.00430892097862 66.6447 4.41269758764 0.0 0.0 0.0
00242 result [(time,beamstatusfrac,lumi,lumierror,speclumi,speclumierror)]
00243 '''
00244 t=lumiTime.lumiTime()
00245 fillbypos={}
00246 runtimesInFill=getFillFromDB(schema,fillnum)
00247 runlist=runtimesInFill.keys()
00248 if not runlist: return fillbypos
00249 irunlsdict=dict(zip(runlist,[None]*len(runlist)))
00250
00251 finecorrections=None
00252 driftcorrections=None
00253 if withcorrection :
00254 cterms=lumiCorrections.nonlinearV2()
00255 finecorrections=lumiCorrections.correctionsForRangeV2(schema,runlist,cterms)
00256 driftcorrections=lumiCorrections.driftcorrectionsForRange(schema,runlist,cterms)
00257 lumidetails=lumiCalcAPI.instCalibratedLumiForRange(schema,irunlsdict,beamstatus=None,amodetag=amodetag,withBXInfo=True,withBeamIntensity=True,bxAlgo=bxAlgo,xingMinLum=xingMinLum,norm=norm,finecorrections=finecorrections,driftcorrections=driftcorrections,usecorrectionv2=True)
00258 session.transaction().commit()
00259
00260
00261
00262 totalstablebeamls=0
00263 orderedrunlist=sorted(lumidetails)
00264 for run in orderedrunlist:
00265 perrundata=lumidetails[run]
00266 for perlsdata in perrundata:
00267 beamstatus=perlsdata[3]
00268 if beamstatus=='STABLE BEAMS':
00269 totalstablebeamls+=1
00270
00271 if totalstablebeamls<10:
00272 print 'fill ',fillnum,' , having less than 10 stable beam lS, is not good, skip'
00273 return fillbypos
00274 for run in orderedrunlist:
00275 perrundata=lumidetails[run]
00276 for perlsdata in perrundata:
00277 beamstatusfrac=0.0
00278 tsdatetime=perlsdata[2]
00279 ts=calendar.timegm(tsdatetime.utctimetuple())
00280 beamstatus=perlsdata[3]
00281 if beamstatus=='STABLE BEAMS':
00282 beamstatusfrac=1.0
00283 (bxidxlist,bxvaluelist,bxerrolist)=perlsdata[9]
00284 maxlumi=0.0
00285 if len(bxvaluelist)!=0:
00286 maxlumi=max(bxvaluelist)
00287 avginstlumi=0.0
00288 if len(bxvaluelist)!=0:
00289 avginstlumi=sum(bxvaluelist)
00290 (intbxidxlist,b1intensities,b2intensities)=perlsdata[10]
00291 for bxidx in bxidxlist:
00292 idx=bxidxlist.index(bxidx)
00293 bxvalue=bxvaluelist[idx]
00294 bxerror=bxerrolist[idx]
00295 if bxvalue<max(xingMinLum,maxlumi*0.2):
00296 continue
00297 bintensityPos=-1
00298 try:
00299 bintensityPos=intbxidxlist.index(bxidx)
00300 except ValueError:
00301 pass
00302 if bintensityPos<=0:
00303 fillbypos.setdefault(bxidx,[]).append([ts,beamstatusfrac,bxvalue,bxerror,0.0,0.0])
00304 continue
00305 b1intensity=b1intensities[bintensityPos]
00306 b2intensity=b2intensities[bintensityPos]
00307 speclumi=calculateSpecificLumi(bxvalue,bxerror,b1intensity,0.0,b2intensity,0.0)
00308 fillbypos.setdefault(bxidx,[]).append([ts,beamstatusfrac,bxvalue,bxerror,speclumi[0],speclumi[1]])
00309 return fillbypos
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 if __name__ == '__main__':
00321 parser = argparse.ArgumentParser(prog=os.path.basename(sys.argv[0]),description = "specific lumi",formatter_class=argparse.ArgumentDefaultsHelpFormatter)
00322 amodetagChoices = [ "PROTPHYS","IONPHYS",'PAPHYS' ]
00323 xingAlgoChoices =[ "OCC1","OCC2","ET"]
00324
00325 parser.add_argument('-c',dest='connect',
00326 action='store',
00327 required=False,
00328 help='connect string to lumiDB,optional',
00329 default='frontier://LumiCalc/CMS_LUMI_PROD')
00330 parser.add_argument('-P',dest='authpath',
00331 action='store',
00332 help='path to authentication file,optional')
00333 parser.add_argument('-i',dest='inputdir',
00334 action='store',
00335 required=False,
00336 help='output dir',
00337 default='.')
00338 parser.add_argument('-o',dest='outputdir',
00339 action='store',
00340 required=False,
00341 help='output dir',
00342 default='.')
00343 parser.add_argument('-f','--fill',dest='fillnum',
00344 action='store',
00345 required=False,
00346 help='specific fill',
00347 default=None)
00348 parser.add_argument('--minfill',dest='minfill',
00349 type=int,
00350 action='store',
00351 required=False,
00352 default=MINFILL,
00353 help='min fill')
00354 parser.add_argument('--maxfill',dest='maxfill',
00355 type=int,
00356 action='store',
00357 required=False,
00358 default=MAXFILL,
00359 help='maximum fillnumber '
00360 )
00361 parser.add_argument('--amodetag',dest='amodetag',
00362 action='store',
00363 choices=amodetagChoices,
00364 required=False,
00365 help='specific accelerator mode choices [PROTOPHYS,IONPHYS,PAPHYS] (optional)')
00366 parser.add_argument('--xingMinLum', dest = 'xingMinLum',
00367 type=float,
00368 default=1e-03,
00369 required=False,
00370 help='Minimum luminosity considered for lumibylsXing action')
00371 parser.add_argument('--xingAlgo', dest = 'bxAlgo',
00372 default='OCC1',
00373 required=False,
00374 help='algorithm name for per-bunch lumi ')
00375 parser.add_argument('--norm',dest='normfactor',action='store',
00376 required=False,
00377 help='norm',
00378 default=None)
00379
00380
00381
00382 parser.add_argument('--siteconfpath',dest='siteconfpath',action='store',
00383 help='specific path to site-local-config.xml file, optional. If path undefined, fallback to cern proxy&server')
00384
00385
00386
00387 parser.add_argument('--without-correction',dest='withoutFineCorrection',action='store_true',
00388 help='without fine correction on calibration' )
00389 parser.add_argument('--debug',dest='debug',action='store_true',
00390 help='debug')
00391 options=parser.parse_args()
00392 if options.authpath:
00393 os.environ['CORAL_AUTH_PATH'] = options.authpath
00394
00395
00396
00397
00398
00399
00400 normfactor=options.normfactor
00401 svc=sessionManager.sessionManager(options.connect,authpath=options.authpath,debugON=options.debug)
00402 session=svc.openSession(isReadOnly=True,cpp2sqltype=[('unsigned int','NUMBER(10)'),('unsigned long long','NUMBER(20)')])
00403
00404 fillstoprocess=[]
00405 maxfillnum=options.maxfill
00406 minfillnum=options.minfill
00407 if options.fillnum is not None:
00408 fillstoprocess.append(int(options.fillnum))
00409 else:
00410 session.transaction().start(True)
00411 schema=session.nominalSchema()
00412 allfillsFromDB=lumiCalcAPI.fillInRange(schema,fillmin=minfillnum,fillmax=maxfillnum,amodetag=options.amodetag)
00413 processedfills=listfilldir(options.outputdir)
00414 lastcompletedFill=lastcompleteFill(os.path.join(options.inputdir,'runtofill_dqm.txt'))
00415 for pf in processedfills:
00416 if pf>lastcompletedFill:
00417 print '\tremove unfinished fill from processed list ',pf
00418 processedfills.remove(pf)
00419 for fill in allfillsFromDB:
00420 if fill not in processedfills :
00421 if int(fill)<=lastcompletedFill:
00422 if int(fill)>minfillnum and int(fill)<maxfillnum:
00423 fillstoprocess.append(fill)
00424 else:
00425 print 'ongoing fill...',fill
00426 session.transaction().commit()
00427 print 'fills to process : ',fillstoprocess
00428 if len(fillstoprocess)==0:
00429 print 'no fill to process, exit '
00430 exit(0)
00431 finecorrections=None
00432 driftcorrections=None
00433 print '===== Start Processing Fills',fillstoprocess
00434 print '====='
00435 withcorrection=not options.withoutFineCorrection
00436 filldata={}
00437 session.transaction().start(True)
00438 for fillnum in fillstoprocess:
00439 filldata=getSpecificLumi(session.nominalSchema(),fillnum,options.inputdir,xingMinLum=options.xingMinLum,norm=options.normfactor,withcorrection=withcorrection,amodetag=options.amodetag,bxAlgo=options.bxAlgo)
00440 specificlumiTofile(fillnum,filldata,options.outputdir)
00441 session.transaction().commit()
00442
00443