ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/COMP/CRAB/python/LumiList.py
Revision: 1.1.2.1
Committed: Wed Apr 7 15:57:10 2010 UTC (15 years ago) by spiga
Content type: text/x-python
Branch: CRAB_2_7_1_branch
CVS Tags: CRAB_2_7_2_p1, CRAB_2_7_1_branch_firstMERGE, CRAB_2_7_2, CRAB_2_7_2_pre4, CRAB_2_7_2_pre3, CRAB_2_7_2_pre2, CRAB_2_7_2_pre1
Changes since 1.1: +9 -5 lines
Log Message:
add LumiMask support

File Contents

# User Rev Content
1 ewv 1.1 #!/usr/bin/env python
2    
3     """
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.
8     """
9    
10 spiga 1.1.2.1 __revision__ = "$Id: LumiList.py,v 1.2 2010/02/22 14:43:56 ewv Exp $"
11     __version__ = "$Revision: 1.2 $"
12 ewv 1.1
13     try: # FUTURE: Python 2.6, prior to 2.6 requires simplejson
14     import json
15     except ImportError:
16     import simplejson as json
17    
18     class LumiList(object):
19     """
20     Deal with lists of lumis in several different forms:
21     Compact list:
22     {
23     '1': [[1, 33], [35, 35], [37, 47], [49, 75], [77, 130], [133, 136]],
24     '2':[[1,45],[50,80]]
25     }
26     where the first key is the run number, subsequent pairs are
27     ranges of lumis within that run that are desired
28     Runs and lumis:
29     {
30     '1': [1,2,3,4,6,7,8,9,10],
31     '2': [1,4,5,20]
32     }
33     where the first key is the run number and the list is a list of
34     individual lumi sections
35     Run lumi pairs:
36     [[1,1], [1,2],[1,4], [2,1], [2,5], [1,10]]
37     where each pair in the list is an individual run&lumi
38     CMSSW representation:
39     '1:1-1:33,1:35,1:37-1:47,2:1-2:45,2:50-2:80'
40     The string used by CMSSW in lumisToProcess or lumisToSkip
41     is a subset of the compactList example above
42     """
43    
44    
45     def __init__(self, filename = None, lumis = None, runsAndLumis = None):
46     """
47     Constructor takes filename (JSON), a list of run/lumi pairs,
48     or a dict with run #'s as the keys and a list of lumis as the values
49     """
50     self.compactList = {}
51     if filename:
52     self.filename = filename
53     jsonFile = open(self.filename,'r')
54     self.compactList = json.load(jsonFile)
55     elif lumis:
56     runsAndLumis = {}
57     for (run, lumi) in lumis:
58     run = str(run)
59     if not runsAndLumis.has_key(run):
60     runsAndLumis[run] = []
61     runsAndLumis[run].append(lumi)
62    
63     if runsAndLumis:
64     for run in runsAndLumis.keys():
65     runString = str(run)
66     lastLumi = -1000
67     self.compactList[runString] = []
68     lumiList = runsAndLumis[run]
69     for lumi in sorted(lumiList):
70     if lumi == lastLumi:
71     pass # Skip duplicates
72     elif lumi != lastLumi + 1: # Break in lumi sequence
73     self.compactList[runString].append([lumi, lumi])
74     else:
75     nRange = len(self.compactList[runString])
76     self.compactList[runString][nRange-1][1] = lumi
77     lastLumi = lumi
78    
79    
80     def filterLumis(self, lumiList):
81     """
82     Return a list of lumis that are in compactList.
83     lumilist is of the simple form
84     [(run1,lumi1),(run1,lumi2),(run2,lumi1)]
85     """
86     filteredList = []
87     for (run, lumi) in lumiList:
88 spiga 1.1.2.1 runsInLumi = self.compactList.get(str(run), [[0,-1]])
89 ewv 1.1 for (first, last) in runsInLumi:
90     if lumi >= first and lumi <= last:
91     filteredList.append((run, lumi))
92     break
93     return filteredList
94    
95    
96     def getCompactList(self):
97     """
98     Return the compact list representation
99     """
100     return self.compactList
101    
102    
103     def getLumis(self):
104     """
105     Return the list of pairs representation
106     """
107     theList = []
108     runs = self.compactList.keys()
109     runs.sort(key=int)
110     for run in runs:
111     lumis = self.compactList[run]
112     for lumiPair in sorted(lumis):
113     for lumi in range(lumiPair[0], lumiPair[1]+1):
114     theList.append((int(run), lumi))
115    
116     return theList
117    
118    
119     def getCMSSWString(self):
120     """
121     Turn compactList into a list of the format
122     R1:L1,R2:L2-R2:L3 which is acceptable to CMSSW LumiBlockRange variable
123     """
124    
125     parts = []
126     runs = self.compactList.keys()
127     runs.sort(key=int)
128     for run in runs:
129     lumis = self.compactList[run]
130     for lumiPair in sorted(lumis):
131     if lumiPair[0] == lumiPair[1]:
132     parts.append("%s:%s" % (run, lumiPair[0]))
133     else:
134     parts.append("%s:%s-%s:%s" %
135     (run, lumiPair[0], run, lumiPair[1]))
136    
137     output = ','.join(parts)
138     return output
139    
140 spiga 1.1.2.1
141    
142 ewv 1.1 # Unit test code
143     '''
144     import unittest
145     from WMCore.DataStructs.LumiList import LumiList
146    
147    
148     class LumiListTest(unittest.TestCase):
149     """
150     _LumiListTest_
151    
152     """
153    
154     def testRead(self):
155     """
156     Test reading from JSON
157     """
158     exString = "1:1-1:33,1:35,1:37-1:47,2:49-2:75,2:77-2:130,2:133-2:136"
159     exDict = {'1': [[1, 33], [35, 35], [37, 47]],
160     '2': [[49, 75], [77, 130], [133, 136]]}
161    
162     jsonList = LumiList(filename = 'lumiTest.json')
163     lumiString = jsonList.getCMSSWString()
164     lumiList = jsonList.getCompactList()
165    
166     self.assertTrue(lumiString == exString)
167     self.assertTrue(lumiList == exDict)
168    
169     def testList(self):
170     """
171     Test constucting from list of pairs
172     """
173    
174     listLs1 = range(1, 34) + [35] + range(37, 48)
175     listLs2 = range(49, 76) + range(77, 131) + range(133, 137)
176     lumis = zip([1]*100, listLs1) + zip([2]*100, listLs2)
177    
178     jsonLister = LumiList(filename = 'lumiTest.json')
179     jsonString = jsonLister.getCMSSWString()
180     jsonList = jsonLister.getCompactList()
181    
182     pairLister = LumiList(lumis = lumis)
183     pairString = pairLister.getCMSSWString()
184     pairList = pairLister.getCompactList()
185    
186     self.assertTrue(jsonString == pairString)
187     self.assertTrue(jsonList == pairList)
188    
189    
190     def testRuns(self):
191     """
192     Test constucting from run and list of lumis
193     """
194     runsAndLumis = {
195     1: range(1, 34) + [35] + range(37, 48),
196     2: range(49, 76) + range(77, 131) + range(133, 137)
197     }
198     runsAndLumis2 = {
199     '1': range(1, 34) + [35] + range(37, 48),
200     '2': range(49, 76) + range(77, 131) + range(133, 137)
201     }
202    
203     jsonLister = LumiList(filename = 'lumiTest.json')
204     jsonString = jsonLister.getCMSSWString()
205     jsonList = jsonLister.getCompactList()
206    
207     runLister = LumiList(runsAndLumis = runsAndLumis)
208     runString = runLister.getCMSSWString()
209     runList = runLister.getCompactList()
210    
211     runLister2 = LumiList(runsAndLumis = runsAndLumis2)
212     runList2 = runLister2.getCompactList()
213    
214     self.assertTrue(jsonString == runString)
215     self.assertTrue(jsonList == runList)
216     self.assertTrue(runList2 == runList)
217    
218    
219     def testFilter(self):
220     """
221     Test filtering of a list of lumis
222     """
223     runsAndLumis = {
224     1: range(1, 34) + [35] + range(37, 48),
225     2: range(49, 76) + range(77, 131) + range(133, 137)
226     }
227    
228     completeList = zip([1]*150, range(1, 150)) + \
229 spiga 1.1.2.1 zip([2]*150, range(1, 150)) + \
230     zip([3]*150, range(1, 150))
231    
232 ewv 1.1 smallList = zip([1]*50, range(1, 10)) + zip([2]*50, range(50, 70))
233     overlapList = zip([1]*150, range(30, 40)) + \
234     zip([2]*150, range(60, 80))
235     overlapRes = zip([1]*9, range(30, 34)) + [(1, 35)] + \
236     zip([1]*9, range(37, 40)) + \
237     zip([2]*30, range(60, 76)) + \
238     zip([2]*9, range(77, 80))
239    
240     runLister = LumiList(runsAndLumis = runsAndLumis)
241    
242     # Test a list to be filtered which is a superset of constructed list
243     filterComplete = runLister.filterLumis(completeList)
244     # Test a list to be filtered which is a subset of constructed list
245     filterSmall = runLister.filterLumis(smallList)
246     # Test a list to be filtered which is neither
247     filterOverlap = runLister.filterLumis(overlapList)
248    
249     self.assertTrue(filterComplete == runLister.getLumis())
250     self.assertTrue(filterSmall == smallList)
251     self.assertTrue(filterOverlap == overlapRes)
252    
253     def testDuplicates(self):
254     """
255     Test a list with lots of duplicates
256     """
257     result = zip([1]*100, range(1, 34) + range(37, 48))
258     lumis = zip([1]*100, range(1, 34) + range(37, 48) + range(5, 25))
259    
260     lister = LumiList(lumis = lumis)
261     self.assertTrue(lister.getLumis() == result)
262    
263     def testNull(self):
264     """
265     Test a null list
266     """
267    
268     runLister = LumiList(lumis = None)
269    
270     self.assertTrue(runLister.getCMSSWString() == '')
271     self.assertTrue(runLister.getLumis() == [])
272     self.assertTrue(runLister.getCompactList() == {})
273    
274    
275    
276     if __name__ == '__main__':
277     unittest.main()
278     '''
279    
280     # Test JSON file
281    
282 spiga 1.1.2.1 #{"1": [[1, 33], [35, 35], [37, 47]], "2": [[49, 75], [77, 130], [133, 136]]}