4 Handle lists of lumi sections. Constuct in several different formats and filter 5 (mask) a secondary list of lumis. 6 This class can also handle ranges of events as the structure is identical 7 or could be subclassed renaming a function or two. 9 This code began life in COMP/CRAB/python/LumiList.py 13 from builtins
import range
21 Deal with lists of lumis in several different forms: 24 '1': [[1, 33], [35, 35], [37, 47], [49, 75], [77, 130], [133, 136]], 27 where the first key is the run number, subsequent pairs are 28 ranges of lumis within that run that are desired 31 '1': [1,2,3,4,6,7,8,9,10], 34 where the first key is the run number and the list is a list of 35 individual lumi sections. This form also takes a list of these objects 36 which can be much faster than LumiList += LumiList 38 [[1,1], [1,2],[1,4], [2,1], [2,5], [1,10]] 39 where each pair in the list is an individual run&lumi 41 '1:1-1:33,1:35,1:37-1:47,2:1-2:45,2:50-2:80' 42 The string used by CMSSW in lumisToProcess or lumisToSkip 43 is a subset of the compactList example above 47 def __init__(self, filename = None, lumis = None, runsAndLumis = None, runs = None, compactList = None, url = None):
49 Constructor takes filename (JSON), a list of run/lumi pairs, 50 or a dict with run #'s as the keys and a list of lumis as the values, or just a list of runs 60 jsonFile = urllib2.urlopen(url)
64 for (run, lumi)
in lumis:
66 if run
not in runsAndLumis:
67 runsAndLumis[run] = []
68 runsAndLumis[run].
append(lumi)
70 if isinstance(runsAndLumis, list):
72 for runLumiList
in runsAndLumis:
73 for run, lumis
in runLumiList.items():
74 queued.setdefault(run, []).extend(lumis)
78 for run
in runsAndLumis.keys():
81 lumiList = runsAndLumis[run]
85 for lumi
in sorted(lumiList):
88 elif lumi != lastLumi + 1:
100 for run
in compactList.keys():
107 for run
in self.compactList.keys():
111 if newLumis
and newLumis[-1][0] <= lumi[0] <= newLumis[-1][1] + 1:
112 newLumis[-1][1] =
max(newLumis[-1][1], lumi[1])
114 newLumis.append(lumi)
119 for run
in sorted(self.compactList.keys()):
121 blumis = sorted(other.compactList.get(run, []))
124 tmplist = [alumi[0], alumi[1]]
126 if blumi[0] <= tmplist[0]
and blumi[1] >= tmplist[1]:
129 if blumi[0] > tmplist[0]
and blumi[1] < tmplist[1]:
130 alist.append([tmplist[0], blumi[0]-1])
131 tmplist = [blumi[1]+1, tmplist[1]]
132 elif blumi[0] <= tmplist[0]
and blumi[1] < tmplist[1]
and blumi[1]>=tmplist[0]:
133 tmplist = [blumi[1]+1, tmplist[1]]
134 elif blumi[0] > tmplist[0]
and blumi[1] >= tmplist[1]
and blumi[0]<=tmplist[1]:
135 alist.append([tmplist[0], blumi[0]-1])
139 alist.append(tmplist)
142 return LumiList(compactList = result)
147 aruns = set(self.compactList.keys())
148 bruns = set(other.compactList.keys())
149 for run
in aruns & bruns:
153 for blumi
in other.compactList[run]:
154 if blumi[0] <= alumi[0]
and blumi[1] >= alumi[1]:
155 lumiList.append(alumi)
156 if blumi[0] > alumi[0]
and blumi[1] < alumi[1]:
157 lumiList.append(blumi)
158 elif blumi[0] <= alumi[0]
and blumi[1] < alumi[1]
and blumi[1] >= alumi[0]:
159 lumiList.append([alumi[0], blumi[1]])
160 elif blumi[0] > alumi[0]
and blumi[1] >= alumi[1]
and blumi[0] <= alumi[1]:
161 lumiList.append([blumi[0], alumi[1]])
165 unique = [lumiList[0]]
166 for pair
in lumiList[1:]:
167 if pair[0] == unique[-1][1]+1:
168 unique[-1][1] = copy.deepcopy(pair[1])
170 unique.append(copy.deepcopy(pair))
173 return LumiList(compactList = result)
178 aruns = self.compactList.keys()
179 bruns = other.compactList.keys()
180 runs = set(aruns + bruns)
182 overlap = sorted(self.compactList.get(run, []) + other.compactList.get(run, []))
183 unique = [overlap[0]]
184 for pair
in overlap[1:]:
185 if pair[0] >= unique[-1][0]
and pair[0] <= unique[-1][1]+1
and pair[1] > unique[-1][1]:
186 unique[-1][1] = copy.deepcopy(pair[1])
187 elif pair[0] > unique[-1][1]:
188 unique.append(copy.deepcopy(pair))
190 return LumiList(compactList = result)
198 '''Returns number of runs in list''' 203 Return a list of lumis that are in compactList. 204 lumilist is of the simple form 205 [(run1,lumi1),(run1,lumi2),(run2,lumi1)] 208 for (run, lumi)
in lumiList:
209 runsInLumi = self.compactList.get(
str(run), [[0, -1]])
210 for (first, last)
in runsInLumi:
211 if lumi >= first
and lumi <= last:
212 filteredList.append((run, lumi))
218 doubleBracketRE = re.compile (
r']],')
219 return doubleBracketRE.sub (
']],\n',
225 Return the compact list representation 232 Return the list of duplicates found during construction as a LumiList 239 Return the list of pairs representation 242 runs = self.compactList.keys()
246 for lumiPair
in sorted(lumis):
247 for lumi
in range(lumiPair[0], lumiPair[1]+1):
248 theList.append((
int(run), lumi))
255 return the sorted list of runs contained 257 return sorted (self.compactList.keys())
262 Turn compactList into a list of the format 263 [ 'R1:L1', 'R2:L2-R2:L3' ] which is used by getCMSSWString and getVLuminosityBlockRange 267 runs = self.compactList.keys()
271 for lumiPair
in sorted(lumis):
272 if lumiPair[0] == lumiPair[1]:
273 parts.append(
str(
"%s:%s" % (run, lumiPair[0])))
275 parts.append(
str(
"%s:%s-%s:%s" %
276 (run, lumiPair[0], run, lumiPair[1])))
282 Turn compactList into a list of the format 283 R1:L1,R2:L2-R2:L3 which is acceptable to CMSSW LumiBlockRange variable 287 output =
','.
join(parts)
293 Turn compactList into an (optionally tracked) VLuminosityBlockRange 296 import FWCore.ParameterSet.Config
as cms
299 return cms.VLuminosityBlockRange(parts)
301 return cms.untracked.VLuminosityBlockRange(parts)
306 Write out a JSON file representation of the object 308 jsonFile = open(fileName,
'w')
309 jsonFile.write(
"%s\n" % self)
315 removes runs from runList from collection 327 Selects only runs from runList in collection 330 for run
in self.compactList.keys():
331 if int(run)
not in runList
and run
not in runList:
332 runsToDelete.append(run)
334 for run
in runsToDelete:
341 returns true if the run, lumi section passed in is contained 342 in this lumiList. Input can be either: 343 - a single tuple of (run, lumi), 344 - separate run and lumi numbers 345 - a single run number (returns true if any lumi sections exist) 347 if lumiSection
is None:
349 if isinstance (run, int)
or isinstance (run, str):
356 raise RuntimeError(
"Improper format for run '%s'" % run)
357 lumiRangeList = self.compactList.get(
str(run) )
358 if not lumiRangeList:
361 for lumiRange
in lumiRangeList:
367 if lumiRange[0] <= lumiSection
and \
368 (0 == lumiRange[1]
or lumiSection <= lumiRange[1]):
382 import FWCore.ParameterSet.Config as cms 384 class LumiListTest(unittest.TestCase): 392 Test reading from JSON 394 exString = "1:1-1:33,1:35,1:37-1:47,2:49-2:75,2:77-2:130,2:133-2:136" 395 exDict = {'1': [[1, 33], [35, 35], [37, 47]], 396 '2': [[49, 75], [77, 130], [133, 136]]} 397 exVLBR = cms.VLuminosityBlockRange('1:1-1:33', '1:35', '1:37-1:47', '2:49-2:75', '2:77-2:130', '2:133-2:136') 399 jsonList = LumiList(filename = 'lumiTest.json') 400 lumiString = jsonList.getCMSSWString() 401 lumiList = jsonList.getCompactList() 402 lumiVLBR = jsonList.getVLuminosityBlockRange(True) 404 self.assertTrue(lumiString == exString) 405 self.assertTrue(lumiList == exDict) 406 self.assertTrue(lumiVLBR == exVLBR) 410 Test constucting from list of pairs 413 listLs1 = range(1, 34) + [35] + range(37, 48) 414 listLs2 = range(49, 76) + range(77, 131) + range(133, 137) 415 lumis = zip([1]*100, listLs1) + zip([2]*100, listLs2) 417 jsonLister = LumiList(filename = 'lumiTest.json') 418 jsonString = jsonLister.getCMSSWString() 419 jsonList = jsonLister.getCompactList() 421 pairLister = LumiList(lumis = lumis) 422 pairString = pairLister.getCMSSWString() 423 pairList = pairLister.getCompactList() 425 self.assertTrue(jsonString == pairString) 426 self.assertTrue(jsonList == pairList) 431 Test constucting from run and list of lumis 434 1: range(1, 34) + [35] + range(37, 48), 435 2: range(49, 76) + range(77, 131) + range(133, 137) 438 '1': range(1, 34) + [35] + range(37, 48), 439 '2': range(49, 76) + range(77, 131) + range(133, 137) 446 jsonLister = LumiList(filename = 'lumiTest.json') 447 jsonString = jsonLister.getCMSSWString() 448 jsonList = jsonLister.getCompactList() 450 runLister = LumiList(runsAndLumis = runsAndLumis) 451 runString = runLister.getCMSSWString() 452 runList = runLister.getCompactList() 454 runLister2 = LumiList(runsAndLumis = runsAndLumis2) 455 runList2 = runLister2.getCompactList() 457 runLister3 = LumiList(runsAndLumis = blank) 460 self.assertTrue(jsonString == runString) 461 self.assertTrue(jsonList == runList) 462 self.assertTrue(runList2 == runList) 463 self.assertTrue(len(runLister3) == 0) 465 def testFilter(self): 467 Test filtering of a list of lumis 470 1: range(1, 34) + [35] + range(37, 48), 471 2: range(49, 76) + range(77, 131) + range(133, 137) 474 completeList = zip([1]*150, range(1, 150)) + \ 475 zip([2]*150, range(1, 150)) + \ 476 zip([3]*150, range(1, 150)) 478 smallList = zip([1]*50, range(1, 10)) + zip([2]*50, range(50, 70)) 479 overlapList = zip([1]*150, range(30, 40)) + \ 480 zip([2]*150, range(60, 80)) 481 overlapRes = zip([1]*9, range(30, 34)) + [(1, 35)] + \ 482 zip([1]*9, range(37, 40)) + \ 483 zip([2]*30, range(60, 76)) + \ 484 zip([2]*9, range(77, 80)) 486 runLister = LumiList(runsAndLumis = runsAndLumis) 488 # Test a list to be filtered which is a superset of constructed list 489 filterComplete = runLister.filterLumis(completeList) 490 # Test a list to be filtered which is a subset of constructed list 491 filterSmall = runLister.filterLumis(smallList) 492 # Test a list to be filtered which is neither 493 filterOverlap = runLister.filterLumis(overlapList) 495 self.assertTrue(filterComplete == runLister.getLumis()) 496 self.assertTrue(filterSmall == smallList) 497 self.assertTrue(filterOverlap == overlapRes) 499 def testDuplicates(self): 501 Test a list with lots of duplicates 503 result = zip([1]*100, range(1, 34) + range(37, 48)) 504 lumis = zip([1]*100, range(1, 34) + range(37, 48) + range(5, 25)) 506 lister = LumiList(lumis = lumis) 507 self.assertTrue(lister.getLumis() == result) 514 runLister = LumiList(lumis = None) 516 self.assertTrue(runLister.getCMSSWString() == '') 517 self.assertTrue(runLister.getLumis() == []) 518 self.assertTrue(runLister.getCompactList() == {}) 520 def testSubtract(self): 522 a-b for lots of cases 525 alumis = {'1' : range(2,20) + range(31,39) + range(45,49), 526 '2' : range(6,20) + range (30,40), 527 '3' : range(10,20) + range (30,40) + range(50,60), 529 blumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(33,36), 531 '3' : range(10,15) + range(35,40) + range(45,51) + range(59,70), 533 clumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(33,36), 536 result = {'1' : range(6,12) + range(13,16) + range(31,33) + range(36,39), 537 '2' : range(6,10) + range(35,40), 538 '3' : range(15,20) + range(30,35) + range(51,59), 540 result2 = {'1' : range(6,12) + range(13,16) + range(31,33) + range(36,39), 541 '2' : range(6,10) + range(35,40), 542 '3' : range(10,20) + range (30,40) + range(50,60), 544 a = LumiList(runsAndLumis = alumis) 545 b = LumiList(runsAndLumis = blumis) 546 c = LumiList(runsAndLumis = clumis) 547 r = LumiList(runsAndLumis = result) 548 r2 = LumiList(runsAndLumis = result2) 550 self.assertTrue((a-b).getCMSSWString() == r.getCMSSWString()) 551 self.assertTrue((a-b).getCMSSWString() != (b-a).getCMSSWString()) 552 # Test where c is missing runs from a 553 self.assertTrue((a-c).getCMSSWString() == r2.getCMSSWString()) 554 self.assertTrue((a-c).getCMSSWString() != (c-a).getCMSSWString()) 556 self.assertTrue(str(a-a) == '{}') 557 self.assertTrue(len(a-a) == 0) 561 a|b for lots of cases 564 alumis = {'1' : range(2,20) + range(31,39) + range(45,49), 565 '2' : range(6,20) + range (30,40), 566 '3' : range(10,20) + range (30,40) + range(50,60), 568 blumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(39,80), 570 '3' : range(10,15) + range(35,40) + range(45,51) + range(59,70), 572 clumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(39,80), 575 result = {'1' : range(2,20) + range(31,39) + range(45,49) + range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(39,80), 576 '2' : range(6,20) + range (30,40) + range(10,35), 577 '3' : range(10,20) + range (30,40) + range(50,60) + range(10,15) + range(35,40) + range(45,51) + range(59,70), 579 a = LumiList(runsAndLumis = alumis) 580 b = LumiList(runsAndLumis = blumis) 581 c = LumiList(runsAndLumis = blumis) 582 r = LumiList(runsAndLumis = result) 583 self.assertTrue((a|b).getCMSSWString() == r.getCMSSWString()) 584 self.assertTrue((a|b).getCMSSWString() == (b|a).getCMSSWString()) 585 self.assertTrue((a|b).getCMSSWString() == (a+b).getCMSSWString()) 587 # Test list constuction (faster) 589 multiple = [alumis, blumis, clumis] 590 easy = LumiList(runsAndLumis = multiple) 593 self.assertTrue(hard.getCMSSWString() == easy.getCMSSWString()) 597 a&b for lots of cases 600 alumis = {'1' : range(2,20) + range(31,39) + range(45,49), 601 '2' : range(6,20) + range (30,40), 602 '3' : range(10,20) + range (30,40) + range(50,60), 605 blumis = {'1' : range(1,6) + range(12,13) + range(16,25) + range(25,40) + range(40,50) + range(33,36), 607 '3' : range(10,15) + range(35,40) + range(45,51) + range(59,70), 610 result = {'1' : range(2,6) + range(12,13) + range(16,20) + range(31,39) + range(45,49), 611 '2' : range(10,20) + range(30,35), 612 '3' : range(10,15) + range(35,40) + range(50,51)+ range(59,60), 614 a = LumiList(runsAndLumis = alumis) 615 b = LumiList(runsAndLumis = blumis) 616 r = LumiList(runsAndLumis = result) 617 self.assertTrue((a&b).getCMSSWString() == r.getCMSSWString()) 618 self.assertTrue((a&b).getCMSSWString() == (b&a).getCMSSWString()) 619 self.assertTrue((a|b).getCMSSWString() != r.getCMSSWString()) 621 def testRemoveSelect(self): 623 a-b for lots of cases 626 alumis = {'1' : range(2,20) + range(31,39) + range(45,49), 627 '2' : range(6,20) + range (30,40), 628 '3' : range(10,20) + range (30,40) + range(50,60), 629 '4' : range(10,20) + range (30,80), 632 result = {'2' : range(6,20) + range (30,40), 633 '4' : range(10,20) + range (30,80), 636 rem = LumiList(runsAndLumis = alumis) 637 sel = LumiList(runsAndLumis = alumis) 638 res = LumiList(runsAndLumis = result) 640 rem.removeRuns([1,3]) 641 sel.selectRuns([2,4]) 643 self.assertTrue(rem.getCMSSWString() == res.getCMSSWString()) 644 self.assertTrue(sel.getCMSSWString() == res.getCMSSWString()) 645 self.assertTrue(sel.getCMSSWString() == rem.getCMSSWString()) 648 URL = 'https://cms-service-dqm.web.cern.ch/cms-service-dqm/CAF/certification/Collisions12/8TeV/Reprocessing/Cert_190456-195530_8TeV_08Jun2012ReReco_Collisions12_JSON.txt' 649 ll = LumiList(url=URL) 650 self.assertTrue(len(ll) > 0) 654 alumis = {'1' : range(2,20) + range(31,39) + range(45,49), 655 '2' : range(6,20) + range (30,40), 656 '3' : range(10,20) + range (30,40) + range(50,60), 659 a = LumiList(runsAndLumis = alumis) 660 a.writeJSON('newFile.json') 663 if __name__ == '__main__': 664 jsonFile = open('lumiTest.json','w') 665 jsonFile.write('{"1": [[1, 33], [35, 35], [37, 47]], "2": [[49, 75], [77, 130], [133, 136]]}') 673 if __name__ ==
'__main__':
680 historyPath = os.path.expanduser(
"~/.pyhistory")
685 readline.write_history_file(historyPath)
686 if os.path.exists(historyPath):
687 readline.read_history_file(historyPath)
690 atexit.register(save_history)
691 readline.parse_and_bind(
"set show-all-if-ambiguous on")
692 readline.parse_and_bind(
"tab: complete")
693 if os.path.exists (historyPath) :
694 readline.read_history_file(historyPath)
695 readline.set_history_length(-1)
def getVLuminosityBlockRange(self, tracked=False)
def removeRuns(self, runList)
def contains(self, run, lumiSection=None)
def selectRuns(self, runList)
static std::string join(char **cmd)
def filterLumis(self, lumiList)
def save_history(historyPath=historyPath)
def __contains__(self, runTuple)
def __init__(self, filename=None, lumis=None, runsAndLumis=None, runs=None, compactList=None, url=None)
def writeJSON(self, fileName)