1 |
#!/usr/bin/env python
|
2 |
|
3 |
# LM: version date: 01/02/2010 --> fixed dataset search and added json output file (optional)
|
4 |
# LM: updated 03/04/2010 --> adapted to new runreg api (and dcs status info)
|
5 |
|
6 |
# include XML-RPC client library
|
7 |
# RR API uses XML-RPC webservices interface for data access
|
8 |
import xmlrpclib,sys,ConfigParser,os,string,commands,time,re
|
9 |
# for json support
|
10 |
try: # FUTURE: Python 2.6, prior to 2.6 requires simplejson
|
11 |
import json
|
12 |
except:
|
13 |
try:
|
14 |
import simplejson as json
|
15 |
except:
|
16 |
print "Please set a crab environment in order to get the proper JSON lib"
|
17 |
sys.exit(1)
|
18 |
|
19 |
global QF_Req,ls_temp_data,QF_ALL_SYS,EXCEPTION,EXRUN
|
20 |
EXCEPTION=False
|
21 |
EXRUN=-1
|
22 |
|
23 |
def invert_intervals(intervals,min_val=1,max_val=9999):
|
24 |
# first order and merge in case
|
25 |
if not intervals:
|
26 |
return []
|
27 |
intervals=merge_intervals(intervals)
|
28 |
intervals = sorted(intervals, key = lambda x: x[0])
|
29 |
result = []
|
30 |
if min_val==-1:
|
31 |
# defin min and max
|
32 |
(a,b)=intervals[0]
|
33 |
min_val=a
|
34 |
if max_val==-1:
|
35 |
(a,b)=intervals[len(intervals)-1]
|
36 |
max_val=b
|
37 |
|
38 |
curr_min=min_val
|
39 |
for (x,y) in intervals:
|
40 |
if x>curr_min:
|
41 |
result.append((curr_min,x-1))
|
42 |
curr_min=y+1
|
43 |
if curr_min<max_val:
|
44 |
result.append((curr_min,max_val))
|
45 |
|
46 |
# print min_val,max_val
|
47 |
return result
|
48 |
|
49 |
def merge_intervals(intervals):
|
50 |
if not intervals:
|
51 |
return []
|
52 |
intervals = sorted(intervals, key = lambda x: x[0])
|
53 |
result = []
|
54 |
(a, b) = intervals[0]
|
55 |
for (x, y) in intervals[1:]:
|
56 |
if x <= b:
|
57 |
b = max(b, y)
|
58 |
else:
|
59 |
result.append((a, b))
|
60 |
(a, b) = (x, y)
|
61 |
result.append((a, b))
|
62 |
return result
|
63 |
|
64 |
def remove_html_tags(data):
|
65 |
p = re.compile(r'<.*?>')
|
66 |
newdata=p.sub('', data)
|
67 |
newdata=newdata.replace(" ","")
|
68 |
return newdata
|
69 |
|
70 |
def remove_extra_spaces(data):
|
71 |
result= re.sub(r'\s', '', data)
|
72 |
return result
|
73 |
|
74 |
def searchrun(runno):
|
75 |
global QF_Req,ls_temp_data,QF_ALL_SYS,EXCEPTION,EXRUN
|
76 |
intervallist=[]
|
77 |
selectls=""
|
78 |
|
79 |
for line in ls_temp_data.split("\n"):
|
80 |
if runno in line:
|
81 |
# print line
|
82 |
try:
|
83 |
if "%%%BAD LS INFO BEGIN%%%" in line:
|
84 |
selectls=line.split("%%%BAD LS INFO BEGIN%%%")[1]
|
85 |
selectls=selectls.split("%%%BAD LS INFO END%%%")[0]
|
86 |
selectls=remove_html_tags(selectls)
|
87 |
selectls=remove_extra_spaces(selectls)
|
88 |
# print selectls
|
89 |
for tag in QF_ALL_SYS:
|
90 |
selectls=selectls.replace(tag+":","\n"+tag+":")
|
91 |
# print selectls
|
92 |
|
93 |
for line in selectls.split("\n"):
|
94 |
try:
|
95 |
tag=line.split(":")[0]
|
96 |
intervals=line.split(":")[1]
|
97 |
except:
|
98 |
continue
|
99 |
if tag in QF_Req.keys():
|
100 |
if QF_Req[tag]=="GOOD":
|
101 |
for interval in intervals.split(","):
|
102 |
if "ALL" in interval:
|
103 |
lmin=1
|
104 |
lmax=9999
|
105 |
else:
|
106 |
strmin=interval.split('-')[0]
|
107 |
strmax=interval.split('-')[1]
|
108 |
lmin=int(strmin)
|
109 |
if "END" in strmax:
|
110 |
lmax=9999
|
111 |
else:
|
112 |
lmax=int(strmax)
|
113 |
intervallist.append((lmin,lmax))
|
114 |
except:
|
115 |
EXCEPTION=True
|
116 |
EXRUN=int(runno)
|
117 |
intervallist=merge_intervals(intervallist)
|
118 |
# print runno, intervallist
|
119 |
return intervallist
|
120 |
|
121 |
|
122 |
|
123 |
#main starts here#
|
124 |
|
125 |
QF_Req={}
|
126 |
GOODRUN={}
|
127 |
compactList = {}
|
128 |
|
129 |
QF_ALL_SYS=["Hcal","Track","Strip","Egam","Es","Dt","Csc","Pix","Muon","Rpc","Castor","Jmet","Ecal","L1t","Hlt","NONE"]
|
130 |
QF_ALL_STAT=["GOOD","BAD","EXCL","NONE"]
|
131 |
DCS_ALL=['Bpix','Fpix','Tibtid','TecM','TecP','Tob','Ebminus','Ebplus','EeMinus','EePlus','EsMinus','EsPlus','HbheA','HbheB','HbheC','H0','Hf','Dtminus','Dtplus','Dt0','CscMinus','CscPlus','Rpc','Castor',"NONE"]
|
132 |
|
133 |
# reading config file
|
134 |
CONFIGFILE='runreg.cfg'
|
135 |
CONFIG = ConfigParser.ConfigParser()
|
136 |
print 'Reading configuration file from ',CONFIGFILE
|
137 |
CONFIG.read(CONFIGFILE)
|
138 |
|
139 |
DATASET=CONFIG.get('Common','Dataset')
|
140 |
GROUP=CONFIG.get('Common','Group')
|
141 |
ADDRESS=CONFIG.get('Common','RunReg')
|
142 |
RUNMIN=CONFIG.get('Common','Runmin')
|
143 |
RUNMAX=CONFIG.get('Common','Runmax')
|
144 |
QFLAGS=CONFIG.get('Common','QFLAGS')
|
145 |
LSPARSE=CONFIG.get('Common','LSCOMMENT')
|
146 |
DCSSTAT=CONFIG.get('Common','DCS')
|
147 |
DCSLIST=string.split(DCSSTAT,',')
|
148 |
|
149 |
LSCOMMENT=True
|
150 |
if "TRUE" in LSPARSE.upper() or "1" in LSPARSE.upper() or "YES" in LSPARSE.upper():
|
151 |
LSCOMMENT=True
|
152 |
elif "FALSE" in LSPARSE.upper() or "0" in LSPARSE.upper() or "NO" in LSPARSE.upper():
|
153 |
LSCOMMENT=False
|
154 |
else:
|
155 |
print "Error in parsing LSCOMMENT cfg parameter: LSPARSE"
|
156 |
sys.exit(1)
|
157 |
|
158 |
QFlist=string.split(QFLAGS,',')
|
159 |
for QF in QFlist:
|
160 |
syst=string.split(QF,":")[0]
|
161 |
value=string.split(QF,":")[1]
|
162 |
if syst not in QF_ALL_SYS or value not in QF_ALL_STAT:
|
163 |
print "QFLAG not valid:",syst,value
|
164 |
sys.exit(1)
|
165 |
QF_Req[syst]=value
|
166 |
|
167 |
for dcs in DCSLIST:
|
168 |
if dcs not in DCS_ALL:
|
169 |
print "DCS not valid:",dcs
|
170 |
sys.exit(1)
|
171 |
|
172 |
|
173 |
CFGLIST=CONFIG.items('Common')
|
174 |
JSONFILE=CONFIG.get('Common','JSONFILE')
|
175 |
|
176 |
# report the request
|
177 |
|
178 |
print "You asked for the runreg info in the run range:"+RUNMIN+"-"+RUNMAX
|
179 |
print "for dataset: "+DATASET
|
180 |
print "with the following quality flags:"
|
181 |
for SS in QF_Req.keys():
|
182 |
print SS, QF_Req[SS]
|
183 |
print "and with the following DCS status:"
|
184 |
for dcs in DCSLIST:
|
185 |
print dcs
|
186 |
print "Manual bad LS in comment column:",LSCOMMENT
|
187 |
#sys.exit(1)
|
188 |
|
189 |
# get handler to RR XML-RPC server
|
190 |
FULLADDRESS=ADDRESS+"/xmlrpc"
|
191 |
print "RunRegistry from: ",FULLADDRESS
|
192 |
server = xmlrpclib.ServerProxy(FULLADDRESS)
|
193 |
|
194 |
# build up selection in RUN table
|
195 |
sel_runtable="{groupName} ='"+GROUP+"' and {runNumber} >= "+RUNMIN+" and {runNumber} <= "+RUNMAX+" and {datasetName} LIKE '"+DATASET+"'"
|
196 |
|
197 |
# the lumisection selection is on the Express dataset:
|
198 |
sel_dstable="{groupName} ='"+GROUP+"' and {runNumber} >= "+RUNMIN+" and {runNumber} <= "+RUNMAX+" and {datasetName} LIKE '%Express%'"
|
199 |
|
200 |
for key in QF_Req.keys():
|
201 |
if key != "NONE" and QF_Req[key]!="NONE":
|
202 |
sel_runtable+=" and {cmp"+key+"} = '"+QF_Req[key]+"'"
|
203 |
sel_dstable+=" and {cmp"+key+"} = '"+QF_Req[key]+"'"
|
204 |
#print sel_runtable
|
205 |
|
206 |
# build up selection in RUNLUMISECTION table
|
207 |
sel_dcstable="{groupName} ='"+GROUP+"' and {runNumber} >= "+RUNMIN+" and {runNumber} <= "+RUNMAX
|
208 |
for dcs in DCSLIST:
|
209 |
if dcs !="NONE":
|
210 |
sel_dcstable+=" and {parDcs"+dcs+"} = 1"
|
211 |
# = 'True'"
|
212 |
# print sel_dcstable
|
213 |
|
214 |
Tries=0
|
215 |
print " "
|
216 |
while Tries<10:
|
217 |
try:
|
218 |
print "Accessing run registry...."
|
219 |
dcs_data = server.DataExporter.export('RUNLUMISECTION', 'GLOBAL', 'json', sel_dcstable)
|
220 |
run_data = server.DataExporter.export('RUN', 'GLOBAL', 'csv_runs', sel_runtable)
|
221 |
ls_temp_data = server.DataExporter.export('RUN', 'GLOBAL', 'csv_datasets', sel_dstable)
|
222 |
break
|
223 |
except:
|
224 |
print "Something wrong in accessing runregistry, retrying in 3s...."
|
225 |
Tries=Tries+1
|
226 |
time.sleep(3)
|
227 |
if Tries==10:
|
228 |
print "Run registry unaccessible.....exiting now"
|
229 |
sys.exit(1)
|
230 |
|
231 |
#print dcs_data
|
232 |
#print run_data
|
233 |
#print ls_temp_data
|
234 |
# find LS info in comment
|
235 |
|
236 |
|
237 |
|
238 |
LISTOFRUN=[]
|
239 |
for line in run_data.split("\n"):
|
240 |
run=line.split(',')[0]
|
241 |
if run.isdigit():
|
242 |
LISTOFRUN.append(run)
|
243 |
|
244 |
|
245 |
selected_dcs={}
|
246 |
jsonlist=json.loads(dcs_data)
|
247 |
|
248 |
|
249 |
for element in jsonlist:
|
250 |
if element in LISTOFRUN:
|
251 |
# first search manual ls certification
|
252 |
if LSCOMMENT:
|
253 |
# using LS intervals in comment
|
254 |
manualbad_int=searchrun(element)
|
255 |
# make a badlumi list
|
256 |
dcsbad_int=invert_intervals(jsonlist[element])
|
257 |
combined=[]
|
258 |
for interval in manualbad_int:
|
259 |
combined.append(interval)
|
260 |
for interval in dcsbad_int:
|
261 |
combined.append(interval)
|
262 |
combined=merge_intervals(combined)
|
263 |
combined=invert_intervals(combined)
|
264 |
selected_dcs[element]=combined
|
265 |
else:
|
266 |
# using only DCS info
|
267 |
selected_dcs[element]=jsonlist[element]
|
268 |
# combined include bith manual LS and DCS LS
|
269 |
|
270 |
#JSONOUT=json.dumps(selected_dcs)
|
271 |
# WARNING: Don't use selected_dcs before dumping into file, it gets screwed up (don't know why!!)
|
272 |
if JSONFILE != "NONE":
|
273 |
lumiSummary = open(JSONFILE, 'w')
|
274 |
json.dump(selected_dcs, lumiSummary)
|
275 |
lumiSummary.close()
|
276 |
print " "
|
277 |
print "-------------------------------------------"
|
278 |
print "Json file: ",JSONFILE," written."
|
279 |
|
280 |
|
281 |
# buildup cms snippet
|
282 |
selectlumi="process.source.lumisToProcess = cms.untracked.VLuminosityBlockRange(\n"
|
283 |
ranges = []
|
284 |
runs_to_print = selected_dcs.keys()
|
285 |
runs_to_print.sort()
|
286 |
for run in runs_to_print:
|
287 |
blocks = selected_dcs[run]
|
288 |
blocks.sort()
|
289 |
prevblock = [-2,-2]
|
290 |
for lsrange in blocks:
|
291 |
if lsrange[0] == prevblock[1]+1:
|
292 |
print "Run: ",run,"- This lumi starts at ", lsrange[0], " previous ended at ", prevblock[1]+1, " so I should merge"
|
293 |
prevblock[1] = lsrange[1]
|
294 |
ranges[-1] = "\t'%s:%d-%s:%d',\n" % (run, prevblock[0],
|
295 |
run, prevblock[1])
|
296 |
else:
|
297 |
ranges.append("\t'%s:%d-%s:%d',\n" % (run, lsrange[0],
|
298 |
run, lsrange[1]))
|
299 |
prevblock = lsrange
|
300 |
selectlumi += "".join(ranges)
|
301 |
selectlumi += ")"
|
302 |
|
303 |
|
304 |
print "-------------------------------------------"
|
305 |
print " "
|
306 |
print "CFG snippet to select:"
|
307 |
print selectlumi
|
308 |
|
309 |
if EXCEPTION:
|
310 |
print "WARNING: Something wrong in manual lumisection selection tag for run: "+str(EXRUN)
|