CMS 3D CMS Logo

Public Member Functions | Public Attributes

LumiList::LumiList Class Reference

List of all members.

Public Member Functions

def __add__
def __and__
def __contains__
def __init__
def __len__
def __or__
def __str__
def __sub__
def contains
def filterLumis
def getCMSSWString
def getCompactList
def getLumis
def getRuns
def removeRuns
def writeJSON

Public Attributes

 compactList
 filename

Detailed Description

Deal with lists of lumis in several different forms:
Compact list:
    {
    '1': [[1, 33], [35, 35], [37, 47], [49, 75], [77, 130], [133, 136]],
    '2':[[1,45],[50,80]]
    }
    where the first key is the run number, subsequent pairs are
    ranges of lumis within that run that are desired
Runs and lumis:
    {
    '1': [1,2,3,4,6,7,8,9,10],
    '2': [1,4,5,20]
    }
    where the first key is the run number and the list is a list of
    individual lumi sections
Run  lumi pairs:
    [[1,1], [1,2],[1,4], [2,1], [2,5], [1,10]]
    where each pair in the list is an individual run&lumi
CMSSW representation:
    '1:1-1:33,1:35,1:37-1:47,2:1-2:45,2:50-2:80'
    The string used by CMSSW in lumisToProcess or lumisToSkip
    is a subset of the compactList example above

Definition at line 18 of file LumiList.py.


Constructor & Destructor Documentation

def LumiList::LumiList::__init__ (   self,
  filename = None,
  lumis = None,
  runsAndLumis = None,
  runs = None,
  compactList = None 
)
Constructor takes filename (JSON), a list of run/lumi pairs,
or a dict with run #'s as the keys and a list of lumis as the values, or just a list of runs

Definition at line 45 of file LumiList.py.

00046                                                                                                            :
00047         """
00048         Constructor takes filename (JSON), a list of run/lumi pairs,
00049         or a dict with run #'s as the keys and a list of lumis as the values, or just a list of runs
00050         """
00051         self.compactList = {}
00052         if filename:
00053             self.filename = filename
00054             jsonFile = open(self.filename,'r')
00055             self.compactList = json.load(jsonFile)
00056         elif lumis:
00057             runsAndLumis = {}
00058             for (run, lumi) in lumis:
00059                 run = str(run)
00060                 if not runsAndLumis.has_key(run):
00061                     runsAndLumis[run] = []
00062                 runsAndLumis[run].append(lumi)
00063 
00064         if runsAndLumis:
00065             for run in runsAndLumis.keys():
00066                 runString = str(run)
00067                 lastLumi = -1000
00068                 lumiList = runsAndLumis[run]
00069                 if lumiList:
00070                     self.compactList[runString] = []
00071                     for lumi in sorted(lumiList):
00072                         if lumi == lastLumi:
00073                             pass # Skip duplicates
00074                         elif lumi != lastLumi + 1: # Break in lumi sequence
00075                             self.compactList[runString].append([lumi, lumi])
00076                         else:
00077                             nRange =  len(self.compactList[runString])
00078                             self.compactList[runString][nRange-1][1] = lumi
00079                         lastLumi = lumi
00080         if runs:
00081             for run in runs:
00082                 runString = str(run)
00083                 self.compactList[runString] = [[1, 0xFFFFFFF]]
00084 
00085         if compactList:
00086             for run in compactList.keys():
00087                 runString = str(run)
00088                 if compactList[run]:
00089                     self.compactList[runString] = compactList[run]
00090 


Member Function Documentation

def LumiList::LumiList::__add__ (   self,
  other 
)

Definition at line 167 of file LumiList.py.

00168                             :
00169         # + is the same as |
00170         return self|other

def LumiList::LumiList::__and__ (   self,
  other 
)

Definition at line 119 of file LumiList.py.

00119                             : # Things in both
00120         result = {}
00121         aruns = set(self.compactList.keys())
00122         bruns = set(other.compactList.keys())
00123         for run in aruns & bruns:
00124             lumiList = []                    # List for this run
00125             unique = []                    # List for this run
00126             for alumi in self.compactList[run]:
00127                 for blumi in other.compactList[run]:
00128                     if blumi[0] <= alumi[0] and blumi[1] >= alumi[1]: # blumi has all of alumi
00129                         lumiList.append(alumi)
00130                     if blumi[0] > alumi[0] and blumi[1] < alumi[1]: # blumi is part of alumi
00131                         lumiList.append(blumi)
00132                     elif blumi[0] <= alumi[0] and blumi[1] < alumi[1] and blumi[1] >= alumi[0]: # overlaps start
00133                         lumiList.append([alumi[0], blumi[1]])
00134                     elif blumi[0] > alumi[0] and blumi[1] >= alumi[1] and blumi[0] <= alumi[1]: # overlaps end
00135                         lumiList.append([blumi[0], alumi[1]])
00136 
00137 
00138             if lumiList:
00139                 unique = [lumiList[0]]
00140             for pair in lumiList[1:]:
00141                 if pair[0] == unique[-1][1]+1:
00142                     unique[-1][1] = pair[1]
00143                 else:
00144                     unique.append(pair)
00145 
00146             result[run] = unique
00147         return LumiList(compactList = result)
00148 
00149 
def LumiList::LumiList::__contains__ (   self,
  runTuple 
)

Definition at line 302 of file LumiList.py.

00303                                      :
00304         return self.contains (runTuple)
00305     
00306     
00307 
00308 '''
00309 # Unit test code
00310 import unittesti
00311 
00312 class LumiListTest(unittest.TestCase):
00313     """
00314     _LumiListTest_
00315 
00316     """
00317 
00318     def testRead(self):
00319         """
00320         Test reading from JSON
00321         """
00322         exString = "1:1-1:33,1:35,1:37-1:47,2:49-2:75,2:77-2:130,2:133-2:136"
00323         exDict   = {'1': [[1, 33], [35, 35], [37, 47]],
00324                     '2': [[49, 75], [77, 130], [133, 136]]}
00325 
00326         jsonList = LumiList(filename = 'lumiTest.json')
00327         lumiString = jsonList.getCMSSWString()
00328         lumiList = jsonList.getCompactList()
00329 
00330         self.assertTrue(lumiString == exString)
00331         self.assertTrue(lumiList   == exDict)
00332 
00333     def testList(self):
00334         """
00335         Test constucting from list of pairs
00336         """
00337 
00338         listLs1 = range(1, 34) + [35] + range(37, 48)
00339         listLs2 = range(49, 76) + range(77, 131) + range(133, 137)
00340         lumis = zip([1]*100, listLs1) + zip([2]*100, listLs2)
00341 
00342         jsonLister = LumiList(filename = 'lumiTest.json')
00343         jsonString = jsonLister.getCMSSWString()
00344         jsonList = jsonLister.getCompactList()
00345 
00346         pairLister = LumiList(lumis = lumis)
00347         pairString = pairLister.getCMSSWString()
00348         pairList = pairLister.getCompactList()
00349 
00350         self.assertTrue(jsonString == pairString)
00351         self.assertTrue(jsonList   == pairList)
00352 
00353 
00354     def testRuns(self):
00355         """
00356         Test constucting from run and list of lumis
00357         """
00358         runsAndLumis = {
00359             1: range(1, 34) + [35] + range(37, 48),
00360             2: range(49, 76) + range(77, 131) + range(133, 137)
00361         }
00362         runsAndLumis2 = {
00363             '1': range(1, 34) + [35] + range(37, 48),
00364             '2': range(49, 76) + range(77, 131) + range(133, 137)
00365         }
00366         blank = {
00367             '1': [],
00368             '2': []
00369         }
00370 
00371         jsonLister = LumiList(filename = 'lumiTest.json')
00372         jsonString = jsonLister.getCMSSWString()
00373         jsonList   = jsonLister.getCompactList()
00374 
00375         runLister = LumiList(runsAndLumis = runsAndLumis)
00376         runString = runLister.getCMSSWString()
00377         runList   = runLister.getCompactList()
00378 
00379         runLister2 = LumiList(runsAndLumis = runsAndLumis2)
00380         runList2 = runLister2.getCompactList()
00381 
00382         runLister3 = LumiList(runsAndLumis = blank)
00383 
00384 
00385         self.assertTrue(jsonString == runString)
00386         self.assertTrue(jsonList   == runList)
00387         self.assertTrue(runList2   == runList)
00388         self.assertTrue(len(runLister3) == 0)
00389 
00390     def testFilter(self):
00391         """
00392         Test filtering of a list of lumis
00393         """
00394         runsAndLumis = {
00395             1: range(1, 34) + [35] + range(37, 48),
00396             2: range(49, 76) + range(77, 131) + range(133, 137)
00397         }
00398 
00399         completeList = zip([1]*150, range(1, 150)) + \
00400                        zip([2]*150, range(1, 150)) + \
00401                        zip([3]*150, range(1, 150))
00402 
00403         smallList    = zip([1]*50,  range(1, 10)) + zip([2]*50, range(50, 70))
00404         overlapList  = zip([1]*150, range(30, 40)) + \
00405                        zip([2]*150, range(60, 80))
00406         overlapRes   = zip([1]*9,   range(30, 34)) + [(1, 35)] + \
00407                        zip([1]*9,   range(37, 40)) + \
00408                        zip([2]*30,  range(60, 76)) + \
00409                        zip([2]*9,   range(77, 80))
00410 
00411         runLister = LumiList(runsAndLumis = runsAndLumis)
00412 
00413         # Test a list to be filtered which is a superset of constructed list
00414         filterComplete = runLister.filterLumis(completeList)
00415         # Test a list to be filtered which is a subset of constructed list
00416         filterSmall    = runLister.filterLumis(smallList)
00417         # Test a list to be filtered which is neither
00418         filterOverlap  = runLister.filterLumis(overlapList)
00419 
00420         self.assertTrue(filterComplete == runLister.getLumis())
00421         self.assertTrue(filterSmall    == smallList)
00422         self.assertTrue(filterOverlap  == overlapRes)
00423 
00424     def testDuplicates(self):
00425         """
00426         Test a list with lots of duplicates
00427         """
00428         result = zip([1]*100, range(1, 34) + range(37, 48))
00429         lumis  = zip([1]*100, range(1, 34) + range(37, 48) + range(5, 25))
00430 
00431         lister = LumiList(lumis = lumis)
00432         self.assertTrue(lister.getLumis() == result)
00433 
00434     def testNull(self):
00435         """
00436         Test a null list
00437         """
00438 
00439         runLister = LumiList(lumis = None)
00440 
00441         self.assertTrue(runLister.getCMSSWString() == '')
00442         self.assertTrue(runLister.getLumis() == [])
00443         self.assertTrue(runLister.getCompactList() == {})
00444 
00445     def testSubtract(self):
00446         """
00447         a-b for lots of cases
00448         """
00449 
00450         alumis = {'1' : range(2,20) + range(31,39) + range(45,49),
00451                   '2' : range(6,20) + range (30,40),
00452                   '3' : range(10,20) + range (30,40) + range(50,60),
00453                  }
00454         blumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(33,36),
00455                   '2' : range(10,35),
00456                   '3' : range(10,15) + range(35,40) + range(45,51) + range(59,70),
00457                  }
00458         clumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(33,36),
00459                   '2' : range(10,35),
00460                  }
00461         result = {'1' : range(6,12) + range(13,16) + range(31,33) + range(36,39),
00462                   '2' : range(6,10) + range(35,40),
00463                   '3' : range(15,20) + range(30,35) + range(51,59),
00464                  }
00465         result2 = {'1' : range(6,12) + range(13,16) + range(31,33) + range(36,39),
00466                    '2' : range(6,10) + range(35,40),
00467                    '3' : range(10,20) + range (30,40) + range(50,60),
00468                  }
00469         a = LumiList(runsAndLumis = alumis)
00470         b = LumiList(runsAndLumis = blumis)
00471         c = LumiList(runsAndLumis = clumis)
00472         r = LumiList(runsAndLumis = result)
00473         r2 = LumiList(runsAndLumis = result2)
00474 
00475         self.assertTrue((a-b).getCMSSWString() == r.getCMSSWString())
00476         self.assertTrue((a-b).getCMSSWString() != (b-a).getCMSSWString())
00477         # Test where c is missing runs from a
00478         self.assertTrue((a-c).getCMSSWString() == r2.getCMSSWString())
00479         self.assertTrue((a-c).getCMSSWString() != (c-a).getCMSSWString())
00480         # Test empty lists
00481         self.assertTrue(str(a-a) == '{}')
00482         self.assertTrue(len(a-a) == 0)
00483 
00484     def testOr(self):
00485         """
00486         a|b for lots of cases
00487         """
00488 
00489         alumis = {'1' : range(2,20) + range(31,39) + range(45,49),
00490                   '2' : range(6,20) + range (30,40),
00491                   '3' : range(10,20) + range (30,40) + range(50,60),
00492                  }
00493         blumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(39,80),
00494                   '2' : range(10,35),
00495                   '3' : range(10,15) + range(35,40) + range(45,51) + range(59,70),
00496                  }
00497         clumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(39,80),
00498                   '2' : range(10,35),
00499                  }
00500         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),
00501                   '2' : range(6,20) + range (30,40) + range(10,35),
00502                   '3' : range(10,20) + range (30,40) + range(50,60) + range(10,15) + range(35,40) + range(45,51) + range(59,70),
00503                  }
00504         a = LumiList(runsAndLumis = alumis)
00505         b = LumiList(runsAndLumis = blumis)
00506         c = LumiList(runsAndLumis = blumis)
00507         r = LumiList(runsAndLumis = result)
00508         self.assertTrue((a|b).getCMSSWString() == r.getCMSSWString())
00509         self.assertTrue((a|b).getCMSSWString() == (b|a).getCMSSWString())
00510         self.assertTrue((a|b).getCMSSWString() == (a+b).getCMSSWString())
00511 
00512 
00513     def testAnd(self):
00514         """
00515         a&b for lots of cases
00516         """
00517 
00518         alumis = {'1' : range(2,20) + range(31,39) + range(45,49),
00519                   '2' : range(6,20) + range (30,40),
00520                   '3' : range(10,20) + range (30,40) + range(50,60),
00521                   '4' : range(1,100),
00522                  }
00523         blumis = {'1' : range(1,6) + range(12,13) + range(16,25) + range(25,40) + range(40,50) + range(33,36),
00524                   '2' : range(10,35),
00525                   '3' : range(10,15) + range(35,40) + range(45,51) + range(59,70),
00526                   '5' : range(1,100),
00527                  }
00528         result = {'1' : range(2,6) + range(12,13) + range(16,20) + range(31,39) + range(45,49),
00529                   '2' : range(10,20) + range(30,35),
00530                   '3' : range(10,15) + range(35,40) + range(50,51)+ range(59,60),
00531                  }
00532         a = LumiList(runsAndLumis = alumis)
00533         b = LumiList(runsAndLumis = blumis)
00534         r = LumiList(runsAndLumis = result)
00535         self.assertTrue((a&b).getCMSSWString() == r.getCMSSWString())
00536         self.assertTrue((a&b).getCMSSWString() == (b&a).getCMSSWString())
00537         self.assertTrue((a|b).getCMSSWString() != r.getCMSSWString())
00538 
00539     def testWrite(self):
00540         alumis = {'1' : range(2,20) + range(31,39) + range(45,49),
00541                   '2' : range(6,20) + range (30,40),
00542                   '3' : range(10,20) + range (30,40) + range(50,60),
00543                   '4' : range(1,100),
00544                  }
00545         a = LumiList(runsAndLumis = alumis)
00546         a.writeJSON('newFile.json')
00547 
00548 
00549 if __name__ == '__main__':
00550     jsonFile = open('lumiTest.json','w')
00551     jsonFile.write('{"1": [[1, 33], [35, 35], [37, 47]], "2": [[49, 75], [77, 130], [133, 136]]}')
00552     jsonFile.close()
00553     unittest.main()
00554 '''
00555 # Test JSON file
00556 
00557 #{"1": [[1, 33], [35, 35], [37, 47]], "2": [[49, 75], [77, 130], [133, 136]]}

def LumiList::LumiList::__len__ (   self)
Returns number of runs in list

Definition at line 171 of file LumiList.py.

00172                      :
00173         '''Returns number of runs in list'''
00174         return len(self.compactList)

def LumiList::LumiList::__or__ (   self,
  other 
)

Definition at line 150 of file LumiList.py.

00151                            :
00152         result = {}
00153         aruns = self.compactList.keys()
00154         bruns = other.compactList.keys()
00155         runs = set(aruns + bruns)
00156         for run in runs:
00157             overlap = sorted(self.compactList.get(run, []) + other.compactList.get(run, []))
00158             unique = [overlap[0]]
00159             for pair in overlap[1:]:
00160                 if pair[0] >= unique[-1][0] and pair[0] <= unique[-1][1]+1 and pair[1] > unique[-1][1]:
00161                     unique[-1][1] = pair[1]
00162                 elif pair[0] > unique[-1][1]:
00163                     unique.append(pair)
00164             result[run] = unique
00165         return LumiList(compactList = result)
00166 

def LumiList::LumiList::__str__ (   self)

Definition at line 191 of file LumiList.py.

00192                       :
00193         doubleBracketRE = re.compile (r']],')
00194         return doubleBracketRE.sub (']],\n',
00195                                     json.dumps (self.compactList,
00196                                                 sort_keys=True))

def LumiList::LumiList::__sub__ (   self,
  other 
)

Definition at line 91 of file LumiList.py.

00091                             : # Things from self not in other
00092         result = {}
00093         for run in sorted(self.compactList.keys()):
00094             alumis = sorted(self.compactList[run])
00095             blumis = sorted(other.compactList.get(run, []))
00096             alist = []                    # verified part
00097             for alumi in alumis:
00098                 tmplist = [alumi[0], alumi[1]] # may be part
00099                 for blumi in blumis:
00100                     if blumi[0] <= tmplist[0] and blumi[1] >= tmplist[1]: # blumi has all of alumi
00101                         tmplist = []
00102                         break # blumi is has all of alumi
00103                     if blumi[0] > tmplist[0] and blumi[1] < tmplist[1]: # blumi is part of alumi
00104                         alist.append([tmplist[0], blumi[0]-1])
00105                         tmplist = [blumi[1]+1, tmplist[1]]
00106                     elif blumi[0] <= tmplist[0] and blumi[1] < tmplist[1] and blumi[1]>=tmplist[0]: # overlaps start
00107                         tmplist = [blumi[1]+1, tmplist[1]]
00108                     elif blumi[0] > tmplist[0] and blumi[1] >= tmplist[1] and blumi[0]<=tmplist[1]: # overlaps end
00109                         alist.append([tmplist[0], blumi[0]-1])
00110                         tmplist = []
00111                         break
00112                 if tmplist:
00113                     alist.append(tmplist)
00114             result[run] = alist
00115 
00116         return LumiList(compactList = result)
00117 
00118 
def LumiList::LumiList::contains (   self,
  run,
  lumiSection = None 
)
returns true if the run, lumi section passed in is contained
in this lumiList.  Input can be either:
- a single tuple of (run, lumi),
- separate run and lumi numbers
- a single run number (returns true if any lumi sections exist)

Definition at line 267 of file LumiList.py.

00268                                                 :
00269         '''
00270         returns true if the run, lumi section passed in is contained
00271         in this lumiList.  Input can be either:
00272         - a single tuple of (run, lumi),
00273         - separate run and lumi numbers
00274         - a single run number (returns true if any lumi sections exist)
00275         '''
00276         if lumiSection is None:
00277             # if this is an integer or a string, see if the run exists
00278             if isinstance (run, int) or isinstance (run, str):
00279                 return self.compactList.has_key( str(run) )
00280             # if we're here, then run better be a tuple or list
00281             try:
00282                 lumiSection = run[1]
00283                 run         = run[0]
00284             except:
00285                 raise RuntimeError, "Improper format for run '%s'" % run
00286         lumiRangeList = self.compactList.get( str(run) )
00287         if not lumiRangeList:
00288             # the run isn't there, so no need to look any further
00289             return False
00290         for lumiRange in lumiRangeList:
00291             # we want to make this as found if either the lumiSection
00292             # is inside the range OR if the lumi section is greater
00293             # than or equal to the lower bound of the lumi range and
00294             # the upper bound is 0 (which means extends to the end of
00295             # the run)
00296             if lumiRange[0] <= lumiSection and \
00297                (0 == lumiRange[1] or lumiSection <= lumiRange[1]):
00298                 # got it
00299                 return True
00300         return False
00301 

def LumiList::LumiList::filterLumis (   self,
  lumiList 
)
Return a list of lumis that are in compactList.
lumilist is of the simple form
[(run1,lumi1),(run1,lumi2),(run2,lumi1)]

Definition at line 175 of file LumiList.py.

00176                                    :
00177         """
00178         Return a list of lumis that are in compactList.
00179         lumilist is of the simple form
00180         [(run1,lumi1),(run1,lumi2),(run2,lumi1)]
00181         """
00182         filteredList = []
00183         for (run, lumi) in lumiList:
00184             runsInLumi = self.compactList.get(str(run), [[0, -1]])
00185             for (first, last) in runsInLumi:
00186                 if lumi >= first and lumi <= last:
00187                     filteredList.append((run, lumi))
00188                     break
00189         return filteredList
00190 

def LumiList::LumiList::getCMSSWString (   self)
Turn compactList into a list of the format
R1:L1,R2:L2-R2:L3 which is acceptable to CMSSW LumiBlockRange variable

Definition at line 227 of file LumiList.py.

00228                             :
00229         """
00230         Turn compactList into a list of the format
00231         R1:L1,R2:L2-R2:L3 which is acceptable to CMSSW LumiBlockRange variable
00232         """
00233 
00234         parts = []
00235         runs = self.compactList.keys()
00236         runs.sort(key=int)
00237         for run in runs:
00238             lumis = self.compactList[run]
00239             for lumiPair in sorted(lumis):
00240                 if lumiPair[0] == lumiPair[1]:
00241                     parts.append("%s:%s" % (run, lumiPair[0]))
00242                 else:
00243                     parts.append("%s:%s-%s:%s" %
00244                                  (run, lumiPair[0], run, lumiPair[1]))
00245 
00246         output = ','.join(parts)
00247         return output

def LumiList::LumiList::getCompactList (   self)
Return the compact list representation

Definition at line 197 of file LumiList.py.

00198                             :
00199         """
00200         Return the compact list representation
00201         """
00202         return self.compactList
00203 

def LumiList::LumiList::getLumis (   self)
Return the list of pairs representation

Definition at line 204 of file LumiList.py.

00205                       :
00206         """
00207         Return the list of pairs representation
00208         """
00209         theList = []
00210         runs = self.compactList.keys()
00211         runs.sort(key=int)
00212         for run in runs:
00213             lumis = self.compactList[run]
00214             for lumiPair in sorted(lumis):
00215                 for lumi in range(lumiPair[0], lumiPair[1]+1):
00216                     theList.append((int(run), lumi))
00217 
00218         return theList
00219 

def LumiList::LumiList::getRuns (   self)
return the sorted list of runs contained

Definition at line 220 of file LumiList.py.

00221                      :
00222         '''
00223         return the sorted list of runs contained
00224         '''
00225         return sorted (self.compactList.keys())
00226 

def LumiList::LumiList::removeRuns (   self,
  runList 
)
removes runs from runList from collection

Definition at line 257 of file LumiList.py.

00258                                   :
00259         '''
00260         removes runs from runList from collection
00261         '''
00262         for run in runList:
00263             run = str(run)
00264             if self.compactList.has_key (run):
00265                 del self.compactList[run]
00266 

def LumiList::LumiList::writeJSON (   self,
  fileName 
)
Write out a JSON file representation of the object

Definition at line 248 of file LumiList.py.

00249                                  :
00250         """
00251         Write out a JSON file representation of the object
00252         """
00253         jsonFile = open(fileName,'w')
00254         jsonFile.write("%s\n" % self)
00255         jsonFile.close()
00256 


Member Data Documentation

Definition at line 48 of file LumiList.py.

Definition at line 48 of file LumiList.py.