14 import os,os.path,sys,math,array,datetime,time,calendar,re
17 from RecoLuminosity.LumiDB
import argparse,sessionManager,lumiTime,CommonUtil,lumiCalcAPI,lumiParameters,revisionDML,normDML
20 allfillname=
'allfills.txt'
24 output: {run:starttime}
28 if len(fillrundict)>0:
29 runs=fillrundict.values()[0]
30 runlsdict=
dict(zip(runs,[
None]*len(runs)))
32 for perrundata
in runresult:
33 runtimesInFill[perrundata[0]]=perrundata[7]
38 list all fills contained in the given dir
42 fillnamepat=
r'^[0-9]{4}$'
43 p=re.compile(fillnamepat)
45 dirList=os.listdir(indir)
47 if p.match(fname)
and os.path.isdir(os.path.join(indir,fname)):
48 allfs=os.listdir(os.path.join(indir,fname))
50 sumfilenamepat=
r'^[0-9]{4}_bxsum_CMS.txt$'
51 s=re.compile(sumfilenamepat)
54 processedfills.append(int(fname))
59 parse infile to find LASTCOMPLETEFILL
60 input: input file name
61 output: last completed fill number
64 hlinepat=
r'(LASTCOMPLETEFILL )([0-9]{4})'
65 h=re.compile(hlinepat)
66 dqmfile=open(infile,
'r')
70 lastfill=result.group(2)
76 calculate specific lumi
77 input: instlumi, instlumierror,beam1intensity,beam1intensityerror,beam2intensity,beam2intensityerror
78 output (specific lumi value,specific lumi error)
82 if beam1intensity<0: beam1intensity=0
83 if beam2intensity<0: beam2intensity=0
84 if beam1intensity>0.0
and beam2intensity>0.0:
85 specificlumi=float(lumi)/(float(beam1intensity)*float(beam2intensity))
86 specificlumierr=specificlumi*math.sqrt(lumierr**2/lumi**2+beam1intensityerr**2/beam1intensity**2+beam2intensityerr**2/beam2intensity**2)
87 return (specificlumi,specificlumierr)
91 parse fill_xxx.txt files in the input directory for runs, starttime in the fill
92 input: fillnumber, input dir
93 output: {run:tarttime}
97 for filename
in os.listdir(inputdir):
98 mpat=
r'^fill_[0-9]{4}.txt$'
100 if m.match(filename)
is None:
102 filename=filename.strip()
103 if filename.find(
'.')==-1:
continue
104 basename,extension=filename.split(
'.')
105 if not extension
or extension!=
'txt':
107 if basename.find(
'_')==-1:
continue
108 prefix,number=basename.split(
'_')
109 if not number :
continue
110 if fillnum!=int(number):
continue
111 f=open(os.path.join(inputdir,
'fill_'+number+
'.txt'),
'r')
115 if len(fields)<2 :
continue
116 runtimesInFill[int(fields[0])]=fields[1]
118 return runtimesInFill
123 write runnumber:starttime map per fill to files
125 f=open(os.path.join(dirname,allfillname),
'w')
126 for fill
in allfills:
127 print >>f,
'%d'%(fill)
129 for fill,runs
in runsperfill.items():
130 filename=
'fill_'+str(fill)+
'.txt'
132 f=open(os.path.join(dirname,filename),
'w')
134 print >>f,
'%d,%s'%(run,runtimes[run])
145 print 'empty input data, do nothing for fill ',fillnum
148 filloutdir=os.path.join(outdir,str(fillnum))
149 if not os.path.exists(filloutdir):
151 for cmsbxidx,perbxdata
in filldata.items():
154 lhcbucket=(cmsbxidx-1)*10+1
155 a=sorted(perbxdata,key=
lambda x:x[0])
156 filename=str(fillnum)+
'_lumi_'+str(lhcbucket)+
'_CMS.txt'
160 beamstatusfrac=perlsdata[1]
162 lumierror=perlsdata[3]
165 speclumi=perlsdata[4]
166 speclumierror= perlsdata[5]
168 linedata.append([ts,beamstatusfrac,lumi,lumierror,speclumi,speclumierror])
169 if not timedict.has_key(ts):
171 timedict[ts].
append([beamstatusfrac,lumi,lumierror,speclumi,speclumierror])
173 f=open(os.path.join(filloutdir,filename),
'w')
174 for line
in linedata:
175 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])
178 summaryfilename=str(fillnum)+
'_lumi_CMS.txt'
180 lstimes=timedict.keys()
184 for lstime
in lstimes:
185 allvalues=timedict[lstime]
187 bstatfrac=transposedvalues[0][0]
188 lumivals=transposedvalues[1]
189 lumitot=sum(lumivals)
191 fillseg.append([lstime,lumitot])
192 lumierrs=transposedvalues[2]
193 lumierrortot=math.sqrt(sum(
map(
lambda x:x**2,lumierrs)))
194 specificvals=transposedvalues[3]
195 specificavg=sum(specificvals)/float(len(specificvals))
196 specificerrs=transposedvalues[4]
197 specifictoterr=math.sqrt(sum(
map(
lambda x:x**2,specificerrs)))
198 specificerravg=specifictoterr/float(len(specificvals))
200 f=open(os.path.join(filloutdir,summaryfilename),
'w')
202 print >>f,
'%d\t%e\t%e\t%e\t%e\t%e'%(lstime,bstatfrac,lumitot,lumierrortot,specificavg,specificerravg)
206 fillsummaryfilename=str(fillnum)+
'_bxsum_CMS.txt'
207 f=open(os.path.join(filloutdir,fillsummaryfilename),
'w')
209 print >>f,
'%s'%(
'#no stable beams')
212 previoustime=fillseg[0][0]
213 boundarytime=fillseg[0][0]
216 summaryls[boundarytime]=[]
217 for [lstime,lumitot]
in fillseg:
218 if lstime-previoustime>50.0:
221 summaryls[boundarytime]=[]
223 summaryls[boundarytime].
append([lstime,lumitot])
227 summarylstimes=summaryls.keys()
228 summarylstimes.sort()
230 for bts
in summarylstimes:
232 tsdatainseg=summaryls[bts]
234 stopts=tsdatainseg[-1][0]
237 print >>f,
'%d\t%d\t%e\t%e'%(startts,stopts,plu,lui)
240 def getSpecificLumi(schema,fillnum,inputdir,dataidmap,normmap,xingMinLum=0.0,amodetag='PROTPHYS',bxAlgo='OCC1'):
242 specific lumi in 1e-30 (ub-1s-1) unit
243 lumidetail occlumi in 1e-27
244 1309_lumi_401_CMS.txt
245 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)
246 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
247 result [(time,beamstatusfrac,lumi,lumierror,speclumi,speclumierror)]
252 runlist=runtimesInFill.keys()
253 if not runlist:
return fillbypos
254 irunlsdict=
dict(zip(runlist,[
None]*len(runlist)))
257 lumidetails=
lumiCalcAPI.deliveredLumiForIds(schema,irunlsdict,dataidmap,GrunsummaryData,beamstatusfilter=
None,normmap=normmap,withBXInfo=
True,bxAlgo=bxAlgo,xingMinLum=xingMinLum,withBeamIntensity=
True,lumitype=
'HF')
262 orderedrunlist=sorted(lumidetails)
263 for run
in orderedrunlist:
264 perrundata=lumidetails[run]
265 for perlsdata
in perrundata:
266 beamstatus=perlsdata[3]
267 if beamstatus==
'STABLE BEAMS':
270 if totalstablebeamls<10:
271 print 'fill ',fillnum,
' , having less than 10 stable beam lS, is not good, skip'
274 for run
in orderedrunlist:
275 perrundata=lumidetails[run]
276 for perlsdata
in perrundata:
278 tsdatetime=perlsdata[2]
279 ts=calendar.timegm(tsdatetime.utctimetuple())
280 beamstatus=perlsdata[3]
281 if beamstatus==
'STABLE BEAMS':
283 (bxidxlist,bxvaluelist,bxerrolist)=perlsdata[7]
285 instbxvaluelist=[x
for x
in bxvaluelist
if x]
287 if len(instbxvaluelist)!=0:
288 maxlumi=
max(instbxvaluelist)
290 if len(instbxvaluelist)!=0:
291 avginstlumi=sum(instbxvaluelist)
292 (intbxidxlist,b1intensities,b2intensities)=perlsdata[8]
293 for bxidx
in bxidxlist:
294 idx=bxidxlist.index(bxidx)
295 instbxvalue=bxvaluelist[idx]
296 bxerror=bxerrolist[idx]
297 if instbxvalue<
max(xingMinLum,maxlumi*0.2):
301 bintensityPos=intbxidxlist.index(bxidx)
305 fillbypos.setdefault(bxidx,[]).
append([ts,beamstatusfrac,instbxvalue,bxerror,0.0,0.0])
307 b1intensity=b1intensities[bintensityPos]
308 b2intensity=b2intensities[bintensityPos]
310 fillbypos.setdefault(bxidx,[]).
append([ts,beamstatusfrac,instbxvalue,bxerror,speclumi[0],speclumi[1]])
322 if __name__ ==
'__main__':
324 amodetagChoices = [
"PROTPHYS",
"IONPHYS",
'PAPHYS' ]
325 xingAlgoChoices =[
"OCC1",
"OCC2",
"ET"]
327 parser.add_argument(
'-c',dest=
'connect',
330 help=
'connect string to lumiDB,optional',
331 default=
'frontier://LumiCalc/CMS_LUMI_PROD')
332 parser.add_argument(
'-P',dest=
'authpath',
334 help=
'path to authentication file,optional')
335 parser.add_argument(
'-i',dest=
'inputdir',
340 parser.add_argument(
'-o',dest=
'outputdir',
345 parser.add_argument(
'-f',
'--fill',dest=
'fillnum',
348 help=
'specific fill',
350 parser.add_argument(
'--minfill',dest=
'minfill',
356 parser.add_argument(
'--maxfill',dest=
'maxfill',
361 help=
'maximum fillnumber '
363 parser.add_argument(
'--amodetag',dest=
'amodetag',
365 choices=amodetagChoices,
367 help=
'specific accelerator mode choices [PROTOPHYS,IONPHYS,PAPHYS] (optional)')
368 parser.add_argument(
'--xingMinLum', dest =
'xingMinLum',
372 help=
'Minimum luminosity considered for lumibylsXing action')
373 parser.add_argument(
'--xingAlgo', dest =
'bxAlgo',
376 help=
'algorithm name for per-bunch lumi ')
377 parser.add_argument(
'--normtag',dest=
'normtag',action=
'store',
381 parser.add_argument(
'--datatag',dest=
'datatag',action=
'store',
388 parser.add_argument(
'--siteconfpath',dest=
'siteconfpath',action=
'store',
389 help=
'specific path to site-local-config.xml file, optional. If path undefined, fallback to cern proxy&server')
393 parser.add_argument(
'--without-correction',dest=
'withoutNorm',action=
'store_true',
394 help=
'without any correction/calibration' )
395 parser.add_argument(
'--debug',dest=
'debug',action=
'store_true',
397 options=parser.parse_args()
399 os.environ[
'CORAL_AUTH_PATH'] = options.authpath
407 session=svc.openSession(isReadOnly=
True,cpp2sqltype=[(
'unsigned int',
'NUMBER(10)'),(
'unsigned long long',
'NUMBER(20)')])
410 maxfillnum=options.maxfill
411 minfillnum=options.minfill
412 if options.fillnum
is not None:
413 fillstoprocess.append(int(options.fillnum))
415 session.transaction().
start(
True)
416 schema=session.nominalSchema()
420 for pf
in processedfills:
421 if pf>lastcompletedFill:
422 print '\tremove unfinished fill from processed list ',pf
423 processedfills.remove(pf)
424 for fill
in allfillsFromDB:
425 if fill
not in processedfills :
426 if int(fill)<=lastcompletedFill:
427 if int(fill)>minfillnum
and int(fill)<maxfillnum:
428 fillstoprocess.append(fill)
430 print 'ongoing fill...',fill
431 session.transaction().commit()
432 print 'fills to process : ',fillstoprocess
433 if len(fillstoprocess)==0:
434 print 'no fill to process, exit '
438 print '===== Start Processing Fills',fillstoprocess
444 reqfillmin=
min(fillstoprocess)
445 reqfillmax=
max(fillstoprocess)
446 session.transaction().
start(
True)
447 runlist=
lumiCalcAPI.runList(session.nominalSchema(),options.fillnum,runmin=
None,runmax=
None,fillmin=reqfillmin,fillmax=reqfillmax,startT=
None,stopT=
None,l1keyPattern=
None,hltkeyPattern=
None,amodetag=options.amodetag,nominalEnergy=
None,energyFlut=
None,requiretrg=
False,requirehlt=
False)
449 datatagname=options.datatag
463 if not options.withoutNorm:
464 normname=options.normtag
468 normname=normmap.keys()[0]
469 normid=normmap[normname]
473 raise RuntimeError(
'[ERROR] cannot resolve norm/correction')
476 session.transaction().commit()
477 for fillnum
in fillstoprocess:
478 session.transaction().
start(
True)
479 filldata=
getSpecificLumi(session.nominalSchema(),fillnum,options.inputdir,dataidmap,normvalueDict,xingMinLum=options.xingMinLum,amodetag=options.amodetag,bxAlgo=options.bxAlgo)
481 session.transaction().commit()
def calculateSpecificLumi
const T & max(const T &a, const T &b)
def runsummary
Lumi data management and calculation API # # Author: Zhen Xie #.
def filltofiles
output methods####