ATLAS Offline Software
Loading...
Searching...
No Matches
AtlRunQuerySelectorDQ.py
Go to the documentation of this file.
1# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2
3
4from CoolRunQuery.selector.AtlRunQuerySelectorBase import Selector, RunLBBasedCondition, OOO
5from CoolRunQuery.utils.AtlRunQueryIOV import IOVRange
6from CoolRunQuery.utils.AtlRunQueryUtils import coolDbConn
7from CoolRunQuery.utils.AtlRunQueryLookup import DQChannel
8
9from collections import defaultdict, namedtuple
10
11DQDefectPayload = namedtuple("DQDefectPayload", "defect comment user ignore primary tolerable recoverable")
12DQDefectPayload.pickled = DQDefectPayload._asdict
13
14DD = namedtuple("DD","description comment since until")
15
16def vfgen(vfobjs):
17 for obj in vfobjs:
18 yield OOO(obj.channel, (str(obj.Code),obj.Comment), IOVRange(starttime=obj.since, endtime=obj.until), True)
19
20class DQSelector(Selector):
21 def __init__(self, name='dataquality'):
22 super(DQSelector,self).__init__(name)
23 self.selectors = {}
24
25 from CoolRunQuery.AtlRunQuerySelectorWorker import SelectorWorker
26 SelectorWorker.getRetrieveSelector('readyforphysics','ReadyForPhysicsSelector')
27
28
29 def __getChannelAndFolder(self, chanAndfolder):
30 cf = chanAndfolder.split()
31 if len(cf)==1:
32 channel=''
33 folder=cf[0]
34 else:
35 channel, folder = cf
36 return (channel,folder)
37
38 def __getCondition(self, folder):
39 if folder in self.selectors:
40 return self.selectors[folder]
41 if folder.startswith('DEFECTS'):
42 self.selectors[folder] = DQDefectCondition(self.name+"DEFECTS", folder)
43 else:
44 self.selectors[folder] = DQCondition(self.name+folder, folder, [])
45 return self.selectors[folder]
46
47 def addSelectionChannel(self, dq=[]):
48 """
49 dq can be e.g. ['EMBA yellow SHIFTOFL', 'FCALA green+ DQMFOFL', 'EMBA,EMBC,EMECA,EMECC yellow+ SHIFTOFL']
50 this example should be translated into two selectors, one for each of the folders 'SHIFTOFL' and 'DQMFOFL'
51 """
52 folderCriteria = defaultdict(list)
53 for x in dq:
54 s = x.split()
55 folderCriteria[s[-1]].append(s[:-1])
56 for f in folderCriteria.keys():
57 if f.startswith('DEFECTS'):
58 self.selectors[f] = DQDefectCondition(self.name+"DEFECTS", f )
59 self.selectors[f].addSelectionChannels(folderCriteria[f])
60 else:
61 self.selectors[f] = DQCondition(self.name+f, f, folderCriteria[f])
62
63
64 def addShowChannel(self, chanAndfolder):
65 (channel,folder) = self.__getChannelAndFolder(chanAndfolder)
66 condition = self.__getCondition(folder)
67 condition.addShowChannel(folder, channel, 'HEAD')
68
69 def setShowOutput(self):
70 for sel in self.selectors.values():
71 sel.setShowOutput()
72
73
74 def __str__(self):
75 s = ""
76 for sel in self.selectors.values():
77 s += "\n%s" % sel
78 return s
79
80
81 def select(self, runlist):
82 # garbage collector
83 # import gc
84 # gcod = gc.get_objects()
85 # print ("GC objects",len(gcod))
86 # print ("GC object count",gc.get_count())
87
88 for sel in self.selectors.values():
89 runlist = sel.select(runlist)
90 return runlist
91
92 def runAfterQuery(self,runlist):
93 for sel in self.selectors.values():
94 sel.runAfterQuery(runlist)
95
96
97
98class DQCondition(RunLBBasedCondition):
99
100 code = {'unknown': 0, 'red': 1, 'yellow': 2, 'green': 3, 'black': -1}
101 color = {'n.a.': 'n.a.', '0': 'U', '1': 'R', '2': 'Y', '3': 'G', '-1': 'B'}
102 invert = {'n.a.': -2, 'B': -1, 'U': 0, 'R': 1, 'Y': 2, 'G': 3 }
103
104 def __init__(self, name, foldername, dq):
105
106 self.foldername = foldername
107 self.channelNames = []
109 self.channels = []
110 self.channelsflat = []
111 self.flags = []
112 self.useVirtualFlags = False
113
114 dbname = 'COOLOFL_GLOBAL'
115 if 'ONL' in self.foldername:
116 dbname = 'COOLONL_GLOBAL'
117
118 # set up virtual flag logic folder and expand wild cards for VF in dq
119 self.GetVirtualFlagsExpanded(dq, Selector.compDB(), dbname)
120
121 for x in dq:
122 ch = x[0].split(',')
123 self.channelNames += [["%s:%s" % (self.foldername,chn) for chn in ch]]
124 self.channels += [[self.DQChannel(chn) for chn in ch]]
125 self.flags += [(x+[''])[1]]
126
127 for chN in self.channelNames:
128 self.channelNamesFlat += chN
129 for ch in self.channels:
130 self.channelsflat += ch
131
132 self.channelCommentsFlat = [n+"_m" for n in self.channelNamesFlat]
133
134 # choose DB based on foldername
135
136 # out of 'SHIFTOFL', 'DQCALCOFL', 'DQMFOFL', 'DQMFOFLH', 'DCSOFL', 'TISUMM', 'LBSUMM', 'MUONCALIB', 'DQMFONL', 'SHIFTONL'
137 # these ones have a comment field
138
139 self.folderHasComment = ( (self.foldername == "SHIFTOFL") or (self.foldername.startswith("SHIFTOFL#")) or
140 (self.foldername == "LBSUMM") or (self.foldername.startswith("LBSUMM#")) or
141 (self.foldername == "DQCALCOFL") or (self.foldername.startswith("DQCALCOFL#")) or
142 (self.foldername.startswith("MUONCALIB#")) )
143
144 # channel keys:
145 # [Code (Int32) : 1], [deadFrac (Float) : 0], [Thrust (Float) : 0], [Comment (String255) : "warm start"]
146 if self.folderHasComment:
147 channelKeys = zip(self.channelsflat, self.channelNamesFlat, len(self.channelsflat)*[('Code','Comment')])
148 else:
149 channelKeys = zip(self.channelsflat, self.channelNamesFlat, len(self.channelsflat)*['Code'])
150
151 super(DQCondition,self).__init__(name=name,
152 dbfolderkey='%s::/GLOBAL/DETSTATUS/%s' % (dbname, self.foldername),
153 channelKeys = channelKeys)
154
156 for flag in self.flags:
157 self.flagInterpreter[flag] = {}
158 d = self.flagInterpreter[flag]
159 d['refVal'] = None
160 d['passFnc'] = None
161 d['passFncName'] = ''
162
163 if flag=='n.a.':
164 d['passFnc'] = lambda x: x==-2
165 d['passFncName'] = "x=='n.a.'"
166 elif flag[-1] in '+-':
167 cd = self.code[flag[:-1].lower()]
168 d['refVal'] = cd
169 if flag[-1]=='+':
170 if cd == -1:
171 d['passFnc'] = lambda x: int(x)>=-1
172 elif cd == 0:
173 d['passFnc'] = lambda x: int(x)>=0
174 elif cd == 1:
175 d['passFnc'] = lambda x: int(x)>=1
176 elif cd == 2:
177 d['passFnc'] = lambda x: int(x)>=2
178 elif cd == 3:
179 d['passFnc'] = lambda x: int(x)>=3
180 d['passFncName'] = "x>='%i'" % d['refVal']
181 else:
182 if cd == -1:
183 d['passFnc'] = lambda x: int(x)<=-1
184 elif cd == 0:
185 d['passFnc'] = lambda x: int(x)<=0
186 elif cd == 1:
187 d['passFnc'] = lambda x: int(x)<=1
188 elif cd == 2:
189 d['passFnc'] = lambda x: int(x)<=2
190 elif cd == 3:
191 d['passFnc'] = lambda x: int(x)<=3
192 d['passFncName'] = "x<='%i'" % d['refVal']
193 else:
194 cd = self.code[flag.lower()]
195 d['refVal'] = cd
196 if cd == -1:
197 d['passFnc'] = lambda x: int(x)==-1
198 elif cd == 0:
199 d['passFnc'] = lambda x: int(x)==0
200 elif cd == 1:
201 d['passFnc'] = lambda x: int(x)==1
202 elif cd == 2:
203 d['passFnc'] = lambda x: int(x)==2
204 elif cd == 3:
205 d['passFnc'] = lambda x: int(x)==3
206 d['passFncName'] = "x=='%i'" % d['refVal']
207
208 self.passSpecs = {}
209 for chgrp, flag in zip(self.channelNames,self.flags):
210 for ch in chgrp:
211 self.passSpecs[ch] = self.flagInterpreter[flag]
212
213 def _getFolder(self):
214 from CoolRunQuery.AtlRunQueryRun import RunData
215 RunData.DQLogic = self.channelNames
216 RunData.DQKeys = self.channelNamesFlat
217
218 f = coolDbConn.GetDBConn(schema = self.schema,db=Selector.condDB()).getFolder(self.folder)
219 if self.useVirtualFlags:
220 f = self.VirtualFlagFolder(f)
221 else:
222 if f.versioningMode()==0:
223 self.tagname=""
224 if self.tagname not in ["HEAD", ""]:
225 self.tagname = f.resolveTag(self.tagname)
226 return f
227
228 def _retrieve(self, iovmin, iovmax, f, sortedRanges):
229 if self.useVirtualFlags:
230 channels = [x.lower().split(':')[-1] for x in self.channelNamesFlat]
231 objs = vfgen(f.browseObjects( iovmin, iovmax, channels, self.tagname ))
232 else:
233 objs = super(DQCondition,self)._retrieve(iovmin, iovmax, f, sortedRanges)
234 return objs
235
236 def DQChannel(self,dqfullname):
237 dqname = dqfullname.split(':')[-1].split('#')[0]
238 if self.useVirtualFlags and dqname in self.vfl.get_logic_list().keys():
239 try:
240 return self.vfl.get_logic_list()[dqname].record.channel
241 except AttributeError:
242 return self.vfl.get_logic_list()[dqname].channel
243 return DQChannel(dqname)
244
245 def GetVirtualFlagsExpanded(self, dqlist, db, schema):
246 for i in range(len(dqlist)):
247 dqs = dqlist[i][0].split(',')
248 newdqs = []
249 for c in dqs:
250 if '_' in c:
251 newdqs += self.ExpandVFlag(c,db,schema)
252 else:
253 newdqs.append(c)
254 dqlist[i][0] = ','.join(newdqs)
255
256 def ExpandVFlag(self, cpflag, db, schema):
257 vfl = self.GetVirtualFlagLogic(db, schema)
258 vflags = vfl.get_logic_list().keys()
259 useprimaries = cpflag[-1]=='+'
260 cpflag=cpflag.rstrip('+')
261 expflags = []
262
263 if cpflag in vflags:
264 self.AddVFHeaderData(cpflag)
265 expflags += [cpflag]
266 if useprimaries:
267 expflags += self.getVFDef(cpflag)
268 else:
269 for vf in vflags:
270 if vf.startswith(cpflag):
271 self.AddVFHeaderData(vf)
272 expflags += [vf]
273 if useprimaries:
274 expflags += self.getVFDef(vf)
275
276 if len(expflags)==0:
277 raise RuntimeError("Virtual Flag pattern %s does not match any virtual flag: %r" % (cpflag, vfl.get_logic_list().keys()))
278
279 return expflags
280
281
282 def GetVirtualFlagLogic(self, db, schema):
283 if self.useVirtualFlags:
284 return self.vfl
285 try: # import
286 from VirtualFlags import VirtualFlagLogicFolder, VirtualFlagFolder
287 except ImportError:
288 print ("Can't import virtual flags")
289 import traceback
290 traceback.print_exc()
291
292 self.VirtualFlagFolder = VirtualFlagFolder
293 self.vfl = VirtualFlagLogicFolder(coolDbConn.GetDBConn(schema=schema, db=db))
294 self.logics = self.vfl.get_logic_list()
295 self.useVirtualFlags = True
296 return self.vfl
297
298 def AddVFHeaderData(self,cpflag):
299 from CoolRunQuery.AtlRunQueryRun import Run
300 if cpflag in Run.Fieldinfo:
301 return
302 Run.Fieldinfo[cpflag] = '<strong><b>%s</b></strong><br><table width="300"><tr><td>%s</td></tr></div>' % \
303 (self.vfl.get_logic_list()[cpflag].comment,
304 ", ".join(self.getVFDef(cpflag)) )
305
306 def getVFDef(self,cpflag):
307 return self.vfl.resolve_primary_flags(self.vfl.resolve_dependancies([cpflag]))
308
309
310
311 def ApplySelection(self,key):
312 if key in self.passSpecs:
313 return True
314 return False
315
316 def addShowChannel(self, folder, channelname, tag):
317 tmplist = [[channelname,'']]
318 self.GetVirtualFlagsExpanded(tmplist, Selector.compDB(), self.schema)
319
320 for shch in tmplist[0][0].split(','):
321 self.addSingleShowChannel(folder+':'+shch)
322
323 def addSingleShowChannel(self, channelname):
324 ch = self.DQChannel(channelname)
325 ssr = self.DoSelectShowRetrieve()
326 if ch in self.channelsflat: # channel exists already, just need to set showoutput to true
327 idx = self.channelsflat.index(ch) # location of the channel in the flat list
328 self.channelNamesFlat[idx] = channelname
329 ssr[idx] += 2
330 else:
331 self.channelNamesFlat += [channelname]
332 self.channelsflat += [self.DQChannel(channelname)]
333 ssr += [2]
334 # re-assign
335 self.channels = self.channelsflat
336
337 if self.folderHasComment:
338 channelKeys = zip(self.channelsflat, self.channelNamesFlat, len(self.channelsflat)*[('Code','Comment')])
339 else:
340 channelKeys = zip(self.channelsflat, self.channelNamesFlat, len(self.channelsflat)*['Code'])
341
342 self.setChannelKeys(channelKeys,ssr)
343
344 def __str__(self):
346 s = "SELOUT Checking in the DQ folder %s" % self.foldername
347 flagCh = defaultdict(list)
348 for flag,ch in zip(self.flags,self.channelNames):
349 flagCh[flag].append('(' + ' or '.join(ch) + ')')
350 for flag in flagCh:
351 chlist = ' and '.join(flagCh[flag])
352 s += "\nSELOUT %s is %r" % (chlist, flag)
353 return s
354 else:
355 return "Retrieving DQ for channels %r from folder %s" % (self.channelNamesFlat, self.foldername)
356
357 def passes(self,values, key):
358 passfnc = self.passSpecs[key]['passFnc']
359 if isinstance(values,tuple):
360 v = values[0]
361 else:
362 v = values
363 if v=='n.a.':
364 v=-2
365 try:
366 if passfnc(v): # passed this DQ flag in the OR group?
367 return True
368 except ValueError:
369 # happens when comparing 'n.a.' with 0,1,2,3 (for 'U','R','Y','G') ... and the black flag? (AH)
370 # should never set pass=True
371 pass
372
373 return False
374
375 def rejectRun(self,run):
376 for k in self.ResultKey():
377 passfnc = self.passSpecs[k]['passFnc']
378 for entry in run.data[k]:
379 v = entry.value
380 dqres = v[0] if type(v)==tuple else v
381 dqcode = self.invert[dqres]
382 entry.rejected = not passfnc( dqcode )
383 return super(DQCondition,self).rejectRun(run)
384
385
386
387 def prettyValue(self, value, key):
388 if type(value)==tuple:
389 return (self.color[value[0]], value[1])
390 else:
391 return self.color[value]
392
393 def runAfterQuery(self,runlist):
394 dqs = ['G','Y','R','B','U','n.a.']
395 for run in runlist:
396 for k in self.ResultKey():
397 n={}
398 run.stats[k] = {}
399 for dq in dqs:
400 n[dq] = 0
401 blocks = []
402 for entry in run.data[k]:
403 if self.folderHasComment:
404 if entry.value == 'n.a.':
405 dq, dqcomment = ('n.a.','')
406 else:
407 dq, dqcomment = entry.value
408 else:
409 dq, dqcomment = (entry.value,None)
410
411 n[dq] += len(entry)
412 if entry.startlb == 0:
413 n[dq] -= 1 # CAUTION: problem with LB-1 = 0 ==> needs to be corrected
414 if len(blocks) > 0 and blocks[-1][0]==(dq,dqcomment) and blocks[-1][2]==entry.startlb:
415 blocks[-1][2] = entry.endlb
416 else:
417 blocks += [ [(dq, dqcomment), entry.startlb, entry.endlb] ]
418
419 maxn = max(n.values())
420 # find maximum DQ flag
421 dqmax = dqs[0]
422 for dq in dqs:
423 if n[dq]==maxn:
424 dqmax=dq
425 run.result[k]=dqmax
426 run.stats[k] = { "counts" : n, "max": dqmax, "blocks": blocks }
427
428
429class DQDefectCondition(RunLBBasedCondition):
430
431 def __init__(self, name, folder):
432 self.foldername = folder # DEFECTS#<TAG>
433 self.primaries = {} # self.primaries[runnr] is the list of primary defects that are set in each run
434 self.channelNames = []
436 self.global_ignore = set() # set of all primary defects that should be ignored in all defects
437 super(DQDefectCondition,self).__init__(name=name,
438 dbfolderkey = 'COOLOFL_GLOBAL::%s' % self.foldername, # folder name handled internally by DQDefects
439 channelKeys = [('DQDEFECT', 'DQ',('Code','Comment'))])
440
441 self.data_keys[0]._second_internal_key = self.tagname
442
443 def _getFolder(self):
444 from CoolRunQuery.AtlRunQueryRun import RunData
445 RunData.DefectSelector = self._pass
446 self.__db = coolDbConn.GetDBConn('DEFECTS',self.tagname)
447 return self.__db # return the DB, not the folder
448
449 def _pass(self,data):
450 these_defects = []
451 if data is not None:
452 for x in data:
453 if x.value.ignore is None: # no ignore
454 these_defects += [x.value.defect]
455 else:
456 these_defects += [x.value.defect+'\\'+x.value.ignore]
457 for orGroup in self.selectionChannelNames:
458 any_passes = False
459 for k in orGroup:
460 if k[0]=='\\':
461 continue # "\Defect" are modifiers not requirements so we ignore it in the check
462 if k[0]=='!': # !DEFECT
463 kk = k[1:]
464 passes = kk not in these_defects
465 else:
466 passes = k in these_defects
467 if passes:
468 any_passes = True
469 break
470 if not any_passes: # none pass in the OR-group
471 return False
472 return True
473
474 def _fix_channel_names(self, db):
475 newl = []
476 for litem in self.selectionChannelNames:
477 newlitem = []
478 for k in litem:
479 if k[0]=='\\':
480 newlitem.append(k)
481 elif k[0] == '!':
482 newlitem.append('!' + db.normalize_defect_names(k[1:]))
483 else:
484 newlitem.append(db.normalize_defect_names(k))
485 newl.append(newlitem)
486 self.selectionChannelNames = newl
487 self.global_ignore = set(db.normalize_defect_names(self.global_ignore))
488
489
490 def __getChannels(self, db, channel_name_patterns):
491 """ based on the patterns in the list channel_name_patterns create a
492 list of pairs of patterns and matching defects ( pattern, set(matching defects) )
493 and attach it to the global Run.FieldInfo dictionary under 'DQ'
494 """
495 from re import compile
496 from CoolRunQuery.AtlRunQueryRun import Run
497 if 'DQ' not in Run.Fieldinfo:
498 Run.Fieldinfo['DQ'] = {}
499 if 'DefMatch' not in Run.Fieldinfo['DQ']:
500 Run.Fieldinfo['DQ']['DefMatch'] = []
501 Run.Fieldinfo['DQ']['IntolerableDefects'] = db.get_intolerable_defects(old_primary_only=False)
502 matches = set()
503 for pattern in channel_name_patterns:
504 if pattern.upper() != 'DET':
505 cpattern = compile(pattern)
506 channelnames = set(filter(cpattern.match,db.defect_names))
507 channelnames.update(filter(cpattern.match,db.virtual_defect_names))
508 else:
509 channelnames = set([d for d in db.defect_names if '_' not in d])
510 channelnames.update([d for d in db.virtual_defect_names if '_' not in d])
511 matches.update(channelnames)
512 Run.Fieldinfo['DQ']['DefMatch'] += [(pattern,channelnames)]
513 return matches
514
515
516 def _retrieve(self, iovmin, iovmax, db, sortedRanges):
517 runmin = iovmin>>32
518 runmax = iovmax>>32
519 since = (runmin,iovmin&0xFFFFFFFF)
520 until = (runmax,iovmax&0xFFFFFFFF)
521
522 # add the channels for showing (those can be wildcarded, so call __getChannels to get exact matches)
523 channels = self.__getChannels(db,self.channelNames)
524
525 # Rewrite defect names to get cases to be correct
526 self._fix_channel_names(db)
527
528 # add the channels for selection (those have to match exactly, they are simply added)
529 channels_with_ignore = {} # unique
530 for selChans in self.selectionChannelNames:
531 channels.update([x.lstrip('!') for x in selChans if '\\' not in x])
532 for x in selChans: # for the defects with ignore condition
533 if '\\' not in x:
534 continue
535 channel, ignore_str = self.sort_uniq_ignores(x).split('\\',1)
536 if ignore_str not in channels_with_ignore:
537 channels_with_ignore[ignore_str] = []
538 channels_with_ignore[ignore_str] += [channel.lstrip('!')]
539
540 #print ("CHANNELS",channels)
541 if len(channels) + len(channels_with_ignore)==0:
542 return []
543
544 # we need to remove the special case ANY from the set
545 if 'ANY' in channels:
546 channels.remove('ANY')
547
548 res = [] if len(channels)==0 else [ (db.retrieve(since=since, until=until, channels=channels, ignore=self.global_ignore, with_primary_dependencies=True).trim_iovs, None) ]
549
550 # and also treat the defects with 'ignore' condition
551 for _ignore_str, _channels in channels_with_ignore.items():
552 ignore = set(_ignore_str.split('\\'))
553 ignore.update(self.global_ignore)
554
555 res += [ (db.retrieve(since=since, until=until, channels=_channels, ignore=ignore, with_primary_dependencies=True).trim_iovs, _ignore_str) ]
556
557 return self.defgen(db, res, channels, channels_with_ignore)
558
559
560
561 def defgen(self, db, defects_with_ignore, channels, channels_with_ignore):
562 """
563 defects: list of defects returned by query
564 channels: explicit list of channels that matched the pattern
565 """
566 intolerableDefects = db.get_intolerable_defects(old_primary_only=False)
567 for defects, ignore in defects_with_ignore:
568 chanlist = channels if ignore is None else channels_with_ignore[ignore]
569 for d in defects:
570 if not d.present:
571 continue
572 isVirtual = (d.user == 'sys:virtual') # db.defect_is_virtual(d.channel)
573 if not isVirtual:
574 run = d.since.run
575 # fill list of primaries defects for this run (this is needed for the comments, but not for the selection)
576 if run not in self.primaries:
577 self.primaries[run] = []
578 self.primaries[run] += [d]
579 if d.channel not in chanlist:
580 continue
581
582 defPayload = DQDefectPayload(defect = d.channel, comment = d.comment,
583 user = d.user, primary = not isVirtual,
584 ignore = ignore,
585 tolerable = (d.channel not in intolerableDefects),
586 recoverable = d.recoverable)
587 # note that the comment is either the user's comment,
588 # a comment that the defect is auto-generated, or the
589 # list of source defects in case of virtual defects
590
591 #o = O("DQDEFECT", (d.channel, d.comment, ignore), IOVRange(starttime=d.since.real, endtime=d.until.real), True)
592 o = OOO("DQDEFECT", defPayload, IOVRange(starttime=d.since.real, endtime=d.until.real), True)
593 yield o
594
595
596
597 def ApplySelection(self,key):
598 return key=='DQ' and len(self.selectionChannelNames)!=0
599
600
601 def sort_uniq_ignores(self,requirement):
602 if '\\' not in requirement:
603 return requirement
604 x = requirement.split('\\')
605 new_req = x[0] + '\\' + '\\'.join(sorted(list(set(x[1:]))))
606 return new_req
607
608
609 def addSelectionChannels(self, dq):
610 for channels,flag in dq:
611 a = []
612 prefix = '!' if flag == 'green' else ''
613 for x in channels.split(','):
614 if x[0]=='\\':
615 self.global_ignore.update( x.lstrip('\\').split('\\') ) # "\Defect" are modifiers not a selection requirement
616 else:
617 a += [ prefix+self.sort_uniq_ignores(x) ]
618 if len(a)>0:
619 self.selectionChannelNames += [ a ]
620
621
622 def addShowChannel(self, folder, channelname, tag):
623 self.channelNames += [channelname]
624 from CoolRunQuery.AtlRunQueryRun import Run
625 if 'DQ' not in Run.Fieldinfo:
626 Run.Fieldinfo['DQ'] = {}
627 if 'DefChannels' not in Run.Fieldinfo['DQ']:
628 Run.Fieldinfo['DQ']['DefChannels'] = []
629 Run.Fieldinfo['DQ']['DefChannels'] += [channelname]
630
631
632 def __str__(self):
634 return "SELOUT Checking the DQ defects %s" % ', '.join([', '.join(cn) for cn in self.selectionChannelNames])
635 else:
636 return "Retrieving DQ defects %s" % ', '.join([', '.join(cn) for cn in self.selectionChannelNames])
637
638 def passes(self,values, key):
639 return True
640
641 def rejectRun(self,run):
642 return super(DQDefectCondition,self).rejectRun(run)
643
644 def mergeRanges(self,it):
645 """ two adjacent defect entries are merged into one"""
646 doMerge = False
647 if doMerge:
648 mergedByDefect = []
649 x = it.next()
650 (openedat,openuntil) = (x.startlb,x.endlb)
651 for x in it:
652 if x.startlb == openuntil:
653 openuntil = x.endlb
654 else:
655 mergedByDefect += [(openedat, openuntil)]
656 openedat,openuntil = x.startlb,x.endlb
657 mergedByDefect += [(openedat, openuntil)]
658 return mergedByDefect
659 else:
660 return [(x.startlb,x.endlb) for x in it]
661
662
663
664 def runAfterQuery(self,runlist):
665 """
666 collects, sorts, and groups defects with LBs and comments
667 """
668 from itertools import groupby
669 from operator import attrgetter
670
671 for run in runlist:
672
673 for k in self.ResultKey():
674 # format of run.data[k] is
675 # [ <DataEntry with value = (defect_name, defect_comment or defect_composition)>, ...]
676
677 #for x in run.data[k]:
678 # print (" %r" % (x,))
679 if k not in run.data.keys():
680 run.result[k] = {}
681 run.stats[k] = {}
682
683 all_defects = sorted(list(set([x.value[0] for x in run.data[k]])))
684
685 grouped_defects = groupby(sorted(run.data[k],key=lambda x: x.value[0]),key = lambda x: x.value[0]) # first sort by defect name, then group by defect name
686
687 desired_defects = [ (defect_name, self.mergeRanges(lblist)) for defect_name, lblist in grouped_defects ]
688
689 run.stats[k] = { "defects": desired_defects,
690 "primaries": {} }
691
692 primaries = {} # defect : list of primaries with lb-range
693 if run.runNr in self.primaries:
694 primgroups = groupby(sorted([p for p in self.primaries[run.runNr]],key=attrgetter('channel')),key=attrgetter('channel'))
695 primaries = dict([(p,list(l)) for p,l in primgroups])
696
697 for defect in all_defects:
698 if self.__db.defect_is_virtual(defect):
699 reps = []
700 self.find_primaries(DD, self.__db.virtual_defect_logics[defect], primaries, defect, reps)
701 run.stats[k]["primaries"][defect] = reps
702 elif defect in primaries:
703 run.stats[k]["primaries"][defect] = [ DD("->%s" % def_obj.channel, def_obj.comment, def_obj.since.lumi, def_obj.until.lumi) for def_obj in primaries[defect] ]
704
705
706 #import pickle
707 #f = open("dev.pickle","w")
708 #pickle.dump(run.stats[k]["primaries"],f)
709 #f.close()
710
711 #for x,l in run.stats[k]["primaries"].items():
712 # print (x)
713 # for y in sorted(l):
714 # print (" ",y)
715
716
717 def find_primaries(self, DD, defect_logic, primaries, curpath, reps):
718 for pdef in defect_logic.primary_defects:
719 if pdef not in primaries:
720 continue
721 pdefects = primaries[pdef]
722 for pdeflb in pdefects:
723 reps += [ DD("%s->%s" % (curpath, pdeflb.channel), pdeflb.comment, pdeflb.since.lumi, pdeflb.until.lumi) ]
724 for dep in defect_logic.dependencies:
725 self.find_primaries(DD, dep, primaries, curpath+"->"+dep.name, reps)
726
#define max(a, b)
Definition cfImp.cxx:41
Validity Range object.
Definition IOVRange.h:30
_retrieve(self, iovmin, iovmax, f, sortedRanges)
find_primaries(self, DD, defect_logic, primaries, curpath, reps)
defgen(self, db, defects_with_ignore, channels, channels_with_ignore)
STL class.
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
Definition index.py:1