CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
LumiList.py
Go to the documentation of this file.
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 This code began life in COMP/CRAB/python/LumiList.py
10 """
11 
12 
13 import copy
14 import json
15 import re
16 import urllib2
17 
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. This form also takes a list of these objects
35  which can be much faster than LumiList += LumiList
36  Run lumi pairs:
37  [[1,1], [1,2],[1,4], [2,1], [2,5], [1,10]]
38  where each pair in the list is an individual run&lumi
39  CMSSW representation:
40  '1:1-1:33,1:35,1:37-1:47,2:1-2:45,2:50-2:80'
41  The string used by CMSSW in lumisToProcess or lumisToSkip
42  is a subset of the compactList example above
43  """
44 
45 
46  def __init__(self, filename = None, lumis = None, runsAndLumis = None, runs = None, compactList = None, url = None):
47  """
48  Constructor takes filename (JSON), a list of run/lumi pairs,
49  or a dict with run #'s as the keys and a list of lumis as the values, or just a list of runs
50  """
51  self.compactList = {}
52  self.duplicates = {}
53  if filename:
54  self.filename = filename
55  jsonFile = open(self.filename,'r')
56  self.compactList = json.load(jsonFile)
57  elif url:
58  self.url = url
59  jsonFile = urllib2.urlopen(url)
60  self.compactList = json.load(jsonFile)
61  elif lumis:
62  runsAndLumis = {}
63  for (run, lumi) in lumis:
64  run = str(run)
65  if run not in runsAndLumis:
66  runsAndLumis[run] = []
67  runsAndLumis[run].append(lumi)
68 
69  if isinstance(runsAndLumis, list):
70  queued = {}
71  for runLumiList in runsAndLumis:
72  for run, lumis in runLumiList.items():
73  queued.setdefault(run, []).extend(lumis)
74  runsAndLumis = queued
75 
76  if runsAndLumis:
77  for run in runsAndLumis.keys():
78  runString = str(run)
79  lastLumi = -1000
80  lumiList = runsAndLumis[run]
81  if lumiList:
82  self.compactList[runString] = []
83  self.duplicates[runString] = []
84  for lumi in sorted(lumiList):
85  if lumi == lastLumi:
86  self.duplicates[runString].append(lumi)
87  elif lumi != lastLumi + 1: # Break in lumi sequence
88  self.compactList[runString].append([lumi, lumi])
89  else:
90  nRange = len(self.compactList[runString])
91  self.compactList[runString][nRange-1][1] = lumi
92  lastLumi = lumi
93  if runs:
94  for run in runs:
95  runString = str(run)
96  self.compactList[runString] = [[1, 0xFFFFFFF]]
97 
98  if compactList:
99  for run in compactList.keys():
100  runString = str(run)
101  if compactList[run]:
102  self.compactList[runString] = compactList[run]
103 
104  # Compact each run and make it unique
105 
106  for run in self.compactList.keys():
107  newLumis = []
108  for lumi in sorted(self.compactList[run]):
109  # If the next lumi starts inside or just after the last just change the endpoint of the first
110  if newLumis and newLumis[-1][0] <= lumi[0] <= newLumis[-1][1] + 1:
111  newLumis[-1][1] = max(newLumis[-1][1], lumi[1])
112  else:
113  newLumis.append(lumi)
114  self.compactList[run] = newLumis
115 
116  def __sub__(self, other): # Things from self not in other
117  result = {}
118  for run in sorted(self.compactList.keys()):
119  alumis = sorted(self.compactList[run])
120  blumis = sorted(other.compactList.get(run, []))
121  alist = [] # verified part
122  for alumi in alumis:
123  tmplist = [alumi[0], alumi[1]] # may be part
124  for blumi in blumis:
125  if blumi[0] <= tmplist[0] and blumi[1] >= tmplist[1]: # blumi has all of alumi
126  tmplist = []
127  break # blumi is has all of alumi
128  if blumi[0] > tmplist[0] and blumi[1] < tmplist[1]: # blumi is part of alumi
129  alist.append([tmplist[0], blumi[0]-1])
130  tmplist = [blumi[1]+1, tmplist[1]]
131  elif blumi[0] <= tmplist[0] and blumi[1] < tmplist[1] and blumi[1]>=tmplist[0]: # overlaps start
132  tmplist = [blumi[1]+1, tmplist[1]]
133  elif blumi[0] > tmplist[0] and blumi[1] >= tmplist[1] and blumi[0]<=tmplist[1]: # overlaps end
134  alist.append([tmplist[0], blumi[0]-1])
135  tmplist = []
136  break
137  if tmplist:
138  alist.append(tmplist)
139  result[run] = alist
140 
141  return LumiList(compactList = result)
142 
143 
144  def __and__(self, other): # Things in both
145  result = {}
146  aruns = set(self.compactList.keys())
147  bruns = set(other.compactList.keys())
148  for run in aruns & bruns:
149  lumiList = [] # List for this run
150  unique = [] # List for this run
151  for alumi in self.compactList[run]:
152  for blumi in other.compactList[run]:
153  if blumi[0] <= alumi[0] and blumi[1] >= alumi[1]: # blumi has all of alumi
154  lumiList.append(alumi)
155  if blumi[0] > alumi[0] and blumi[1] < alumi[1]: # blumi is part of alumi
156  lumiList.append(blumi)
157  elif blumi[0] <= alumi[0] and blumi[1] < alumi[1] and blumi[1] >= alumi[0]: # overlaps start
158  lumiList.append([alumi[0], blumi[1]])
159  elif blumi[0] > alumi[0] and blumi[1] >= alumi[1] and blumi[0] <= alumi[1]: # overlaps end
160  lumiList.append([blumi[0], alumi[1]])
161 
162 
163  if lumiList:
164  unique = [lumiList[0]]
165  for pair in lumiList[1:]:
166  if pair[0] == unique[-1][1]+1:
167  unique[-1][1] = copy.deepcopy(pair[1])
168  else:
169  unique.append(copy.deepcopy(pair))
170 
171  result[run] = unique
172  return LumiList(compactList = result)
173 
174 
175  def __or__(self, other):
176  result = {}
177  aruns = self.compactList.keys()
178  bruns = other.compactList.keys()
179  runs = set(aruns + bruns)
180  for run in runs:
181  overlap = sorted(self.compactList.get(run, []) + other.compactList.get(run, []))
182  unique = [overlap[0]]
183  for pair in overlap[1:]:
184  if pair[0] >= unique[-1][0] and pair[0] <= unique[-1][1]+1 and pair[1] > unique[-1][1]:
185  unique[-1][1] = copy.deepcopy(pair[1])
186  elif pair[0] > unique[-1][1]:
187  unique.append(copy.deepcopy(pair))
188  result[run] = unique
189  return LumiList(compactList = result)
190 
191 
192  def __add__(self, other):
193  # + is the same as |
194  return self.__or__(other)
195 
196  def __len__(self):
197  '''Returns number of runs in list'''
198  return len(self.compactList)
199 
200  def filterLumis(self, lumiList):
201  """
202  Return a list of lumis that are in compactList.
203  lumilist is of the simple form
204  [(run1,lumi1),(run1,lumi2),(run2,lumi1)]
205  """
206  filteredList = []
207  for (run, lumi) in lumiList:
208  runsInLumi = self.compactList.get(str(run), [[0, -1]])
209  for (first, last) in runsInLumi:
210  if lumi >= first and lumi <= last:
211  filteredList.append((run, lumi))
212  break
213  return filteredList
214 
215 
216  def __str__ (self):
217  doubleBracketRE = re.compile (r']],')
218  return doubleBracketRE.sub (']],\n',
219  json.dumps (self.compactList,
220  sort_keys=True))
221 
222  def getCompactList(self):
223  """
224  Return the compact list representation
225  """
226  return self.compactList
227 
228 
229  def getDuplicates(self):
230  """
231  Return the list of duplicates found during construction as a LumiList
232  """
233  return LumiList(runsAndLumis = self.duplicates)
234 
235 
236  def getLumis(self):
237  """
238  Return the list of pairs representation
239  """
240  theList = []
241  runs = self.compactList.keys()
242  runs.sort(key=int)
243  for run in runs:
244  lumis = self.compactList[run]
245  for lumiPair in sorted(lumis):
246  for lumi in range(lumiPair[0], lumiPair[1]+1):
247  theList.append((int(run), lumi))
248 
249  return theList
250 
251 
252  def getRuns(self):
253  '''
254  return the sorted list of runs contained
255  '''
256  return sorted (self.compactList.keys())
257 
258 
259  def _getLumiParts(self):
260  """
261  Turn compactList into a list of the format
262  [ 'R1:L1', 'R2:L2-R2:L3' ] which is used by getCMSSWString and getVLuminosityBlockRange
263  """
264 
265  parts = []
266  runs = self.compactList.keys()
267  runs.sort(key=int)
268  for run in runs:
269  lumis = self.compactList[run]
270  for lumiPair in sorted(lumis):
271  if lumiPair[0] == lumiPair[1]:
272  parts.append("%s:%s" % (run, lumiPair[0]))
273  else:
274  parts.append("%s:%s-%s:%s" %
275  (run, lumiPair[0], run, lumiPair[1]))
276  return parts
277 
278 
279  def getCMSSWString(self):
280  """
281  Turn compactList into a list of the format
282  R1:L1,R2:L2-R2:L3 which is acceptable to CMSSW LumiBlockRange variable
283  """
284 
285  parts = self._getLumiParts()
286  output = ','.join(parts)
287  return str(output)
288 
289 
290  def getVLuminosityBlockRange(self, tracked = False):
291  """
292  Turn compactList into an (optionally tracked) VLuminosityBlockRange
293  """
294 
295  import FWCore.ParameterSet.Config as cms
296  parts = self._getLumiParts()
297  if tracked:
298  return cms.VLuminosityBlockRange(parts)
299  else:
300  return cms.untracked.VLuminosityBlockRange(parts)
301 
302 
303  def writeJSON(self, fileName):
304  """
305  Write out a JSON file representation of the object
306  """
307  jsonFile = open(fileName,'w')
308  jsonFile.write("%s\n" % self)
309  jsonFile.close()
310 
311 
312  def removeRuns (self, runList):
313  '''
314  removes runs from runList from collection
315  '''
316  for run in runList:
317  run = str(run)
318  if run in self.compactList:
319  del self.compactList[run]
320 
321  return
322 
323 
324  def selectRuns (self, runList):
325  '''
326  Selects only runs from runList in collection
327  '''
328  runsToDelete = []
329  for run in self.compactList.keys():
330  if int(run) not in runList and run not in runList:
331  runsToDelete.append(run)
332 
333  for run in runsToDelete:
334  del self.compactList[run]
335 
336  return
337 
338  def contains (self, run, lumiSection = None):
339  '''
340  returns true if the run, lumi section passed in is contained
341  in this lumiList. Input can be either:
342  - a single tuple of (run, lumi),
343  - separate run and lumi numbers
344  - a single run number (returns true if any lumi sections exist)
345  '''
346  if lumiSection is None:
347  # if this is an integer or a string, see if the run exists
348  if isinstance (run, int) or isinstance (run, str):
349  return str(run) in self.compactList
350  # if we're here, then run better be a tuple or list
351  try:
352  lumiSection = run[1]
353  run = run[0]
354  except:
355  raise RuntimeError("Improper format for run '%s'" % run)
356  lumiRangeList = self.compactList.get( str(run) )
357  if not lumiRangeList:
358  # the run isn't there, so no need to look any further
359  return False
360  for lumiRange in lumiRangeList:
361  # we want to make this as found if either the lumiSection
362  # is inside the range OR if the lumi section is greater
363  # than or equal to the lower bound of the lumi range and
364  # the upper bound is 0 (which means extends to the end of
365  # the run)
366  if lumiRange[0] <= lumiSection and \
367  (0 == lumiRange[1] or lumiSection <= lumiRange[1]):
368  # got it
369  return True
370  return False
371 
372 
373  def __contains__ (self, runTuple):
374  return self.contains (runTuple)
375 
376 
377 
378 '''
379 # Unit test code
380 import unittest
381 import FWCore.ParameterSet.Config as cms
382 
383 class LumiListTest(unittest.TestCase):
384  """
385  _LumiListTest_
386 
387  """
388 
389  def testRead(self):
390  """
391  Test reading from JSON
392  """
393  exString = "1:1-1:33,1:35,1:37-1:47,2:49-2:75,2:77-2:130,2:133-2:136"
394  exDict = {'1': [[1, 33], [35, 35], [37, 47]],
395  '2': [[49, 75], [77, 130], [133, 136]]}
396  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')
397 
398  jsonList = LumiList(filename = 'lumiTest.json')
399  lumiString = jsonList.getCMSSWString()
400  lumiList = jsonList.getCompactList()
401  lumiVLBR = jsonList.getVLuminosityBlockRange(True)
402 
403  self.assertTrue(lumiString == exString)
404  self.assertTrue(lumiList == exDict)
405  self.assertTrue(lumiVLBR == exVLBR)
406 
407  def testList(self):
408  """
409  Test constucting from list of pairs
410  """
411 
412  listLs1 = range(1, 34) + [35] + range(37, 48)
413  listLs2 = range(49, 76) + range(77, 131) + range(133, 137)
414  lumis = zip([1]*100, listLs1) + zip([2]*100, listLs2)
415 
416  jsonLister = LumiList(filename = 'lumiTest.json')
417  jsonString = jsonLister.getCMSSWString()
418  jsonList = jsonLister.getCompactList()
419 
420  pairLister = LumiList(lumis = lumis)
421  pairString = pairLister.getCMSSWString()
422  pairList = pairLister.getCompactList()
423 
424  self.assertTrue(jsonString == pairString)
425  self.assertTrue(jsonList == pairList)
426 
427 
428  def testRuns(self):
429  """
430  Test constucting from run and list of lumis
431  """
432  runsAndLumis = {
433  1: range(1, 34) + [35] + range(37, 48),
434  2: range(49, 76) + range(77, 131) + range(133, 137)
435  }
436  runsAndLumis2 = {
437  '1': range(1, 34) + [35] + range(37, 48),
438  '2': range(49, 76) + range(77, 131) + range(133, 137)
439  }
440  blank = {
441  '1': [],
442  '2': []
443  }
444 
445  jsonLister = LumiList(filename = 'lumiTest.json')
446  jsonString = jsonLister.getCMSSWString()
447  jsonList = jsonLister.getCompactList()
448 
449  runLister = LumiList(runsAndLumis = runsAndLumis)
450  runString = runLister.getCMSSWString()
451  runList = runLister.getCompactList()
452 
453  runLister2 = LumiList(runsAndLumis = runsAndLumis2)
454  runList2 = runLister2.getCompactList()
455 
456  runLister3 = LumiList(runsAndLumis = blank)
457 
458 
459  self.assertTrue(jsonString == runString)
460  self.assertTrue(jsonList == runList)
461  self.assertTrue(runList2 == runList)
462  self.assertTrue(len(runLister3) == 0)
463 
464  def testFilter(self):
465  """
466  Test filtering of a list of lumis
467  """
468  runsAndLumis = {
469  1: range(1, 34) + [35] + range(37, 48),
470  2: range(49, 76) + range(77, 131) + range(133, 137)
471  }
472 
473  completeList = zip([1]*150, range(1, 150)) + \
474  zip([2]*150, range(1, 150)) + \
475  zip([3]*150, range(1, 150))
476 
477  smallList = zip([1]*50, range(1, 10)) + zip([2]*50, range(50, 70))
478  overlapList = zip([1]*150, range(30, 40)) + \
479  zip([2]*150, range(60, 80))
480  overlapRes = zip([1]*9, range(30, 34)) + [(1, 35)] + \
481  zip([1]*9, range(37, 40)) + \
482  zip([2]*30, range(60, 76)) + \
483  zip([2]*9, range(77, 80))
484 
485  runLister = LumiList(runsAndLumis = runsAndLumis)
486 
487  # Test a list to be filtered which is a superset of constructed list
488  filterComplete = runLister.filterLumis(completeList)
489  # Test a list to be filtered which is a subset of constructed list
490  filterSmall = runLister.filterLumis(smallList)
491  # Test a list to be filtered which is neither
492  filterOverlap = runLister.filterLumis(overlapList)
493 
494  self.assertTrue(filterComplete == runLister.getLumis())
495  self.assertTrue(filterSmall == smallList)
496  self.assertTrue(filterOverlap == overlapRes)
497 
498  def testDuplicates(self):
499  """
500  Test a list with lots of duplicates
501  """
502  result = zip([1]*100, range(1, 34) + range(37, 48))
503  lumis = zip([1]*100, range(1, 34) + range(37, 48) + range(5, 25))
504 
505  lister = LumiList(lumis = lumis)
506  self.assertTrue(lister.getLumis() == result)
507 
508  def testNull(self):
509  """
510  Test a null list
511  """
512 
513  runLister = LumiList(lumis = None)
514 
515  self.assertTrue(runLister.getCMSSWString() == '')
516  self.assertTrue(runLister.getLumis() == [])
517  self.assertTrue(runLister.getCompactList() == {})
518 
519  def testSubtract(self):
520  """
521  a-b for lots of cases
522  """
523 
524  alumis = {'1' : range(2,20) + range(31,39) + range(45,49),
525  '2' : range(6,20) + range (30,40),
526  '3' : range(10,20) + range (30,40) + range(50,60),
527  }
528  blumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(33,36),
529  '2' : range(10,35),
530  '3' : range(10,15) + range(35,40) + range(45,51) + range(59,70),
531  }
532  clumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(33,36),
533  '2' : range(10,35),
534  }
535  result = {'1' : range(6,12) + range(13,16) + range(31,33) + range(36,39),
536  '2' : range(6,10) + range(35,40),
537  '3' : range(15,20) + range(30,35) + range(51,59),
538  }
539  result2 = {'1' : range(6,12) + range(13,16) + range(31,33) + range(36,39),
540  '2' : range(6,10) + range(35,40),
541  '3' : range(10,20) + range (30,40) + range(50,60),
542  }
543  a = LumiList(runsAndLumis = alumis)
544  b = LumiList(runsAndLumis = blumis)
545  c = LumiList(runsAndLumis = clumis)
546  r = LumiList(runsAndLumis = result)
547  r2 = LumiList(runsAndLumis = result2)
548 
549  self.assertTrue((a-b).getCMSSWString() == r.getCMSSWString())
550  self.assertTrue((a-b).getCMSSWString() != (b-a).getCMSSWString())
551  # Test where c is missing runs from a
552  self.assertTrue((a-c).getCMSSWString() == r2.getCMSSWString())
553  self.assertTrue((a-c).getCMSSWString() != (c-a).getCMSSWString())
554  # Test empty lists
555  self.assertTrue(str(a-a) == '{}')
556  self.assertTrue(len(a-a) == 0)
557 
558  def testOr(self):
559  """
560  a|b for lots of cases
561  """
562 
563  alumis = {'1' : range(2,20) + range(31,39) + range(45,49),
564  '2' : range(6,20) + range (30,40),
565  '3' : range(10,20) + range (30,40) + range(50,60),
566  }
567  blumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(39,80),
568  '2' : range(10,35),
569  '3' : range(10,15) + range(35,40) + range(45,51) + range(59,70),
570  }
571  clumis = {'1' : range(1,6) + range(12,13) + range(16,30) + range(40,50) + range(39,80),
572  '2' : range(10,35),
573  }
574  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),
575  '2' : range(6,20) + range (30,40) + range(10,35),
576  '3' : range(10,20) + range (30,40) + range(50,60) + range(10,15) + range(35,40) + range(45,51) + range(59,70),
577  }
578  a = LumiList(runsAndLumis = alumis)
579  b = LumiList(runsAndLumis = blumis)
580  c = LumiList(runsAndLumis = blumis)
581  r = LumiList(runsAndLumis = result)
582  self.assertTrue((a|b).getCMSSWString() == r.getCMSSWString())
583  self.assertTrue((a|b).getCMSSWString() == (b|a).getCMSSWString())
584  self.assertTrue((a|b).getCMSSWString() == (a+b).getCMSSWString())
585 
586  # Test list constuction (faster)
587 
588  multiple = [alumis, blumis, clumis]
589  easy = LumiList(runsAndLumis = multiple)
590  hard = a + b
591  hard += c
592  self.assertTrue(hard.getCMSSWString() == easy.getCMSSWString())
593 
594  def testAnd(self):
595  """
596  a&b for lots of cases
597  """
598 
599  alumis = {'1' : range(2,20) + range(31,39) + range(45,49),
600  '2' : range(6,20) + range (30,40),
601  '3' : range(10,20) + range (30,40) + range(50,60),
602  '4' : range(1,100),
603  }
604  blumis = {'1' : range(1,6) + range(12,13) + range(16,25) + range(25,40) + range(40,50) + range(33,36),
605  '2' : range(10,35),
606  '3' : range(10,15) + range(35,40) + range(45,51) + range(59,70),
607  '5' : range(1,100),
608  }
609  result = {'1' : range(2,6) + range(12,13) + range(16,20) + range(31,39) + range(45,49),
610  '2' : range(10,20) + range(30,35),
611  '3' : range(10,15) + range(35,40) + range(50,51)+ range(59,60),
612  }
613  a = LumiList(runsAndLumis = alumis)
614  b = LumiList(runsAndLumis = blumis)
615  r = LumiList(runsAndLumis = result)
616  self.assertTrue((a&b).getCMSSWString() == r.getCMSSWString())
617  self.assertTrue((a&b).getCMSSWString() == (b&a).getCMSSWString())
618  self.assertTrue((a|b).getCMSSWString() != r.getCMSSWString())
619 
620  def testRemoveSelect(self):
621  """
622  a-b for lots of cases
623  """
624 
625  alumis = {'1' : range(2,20) + range(31,39) + range(45,49),
626  '2' : range(6,20) + range (30,40),
627  '3' : range(10,20) + range (30,40) + range(50,60),
628  '4' : range(10,20) + range (30,80),
629  }
630 
631  result = {'2' : range(6,20) + range (30,40),
632  '4' : range(10,20) + range (30,80),
633  }
634 
635  rem = LumiList(runsAndLumis = alumis)
636  sel = LumiList(runsAndLumis = alumis)
637  res = LumiList(runsAndLumis = result)
638 
639  rem.removeRuns([1,3])
640  sel.selectRuns([2,4])
641 
642  self.assertTrue(rem.getCMSSWString() == res.getCMSSWString())
643  self.assertTrue(sel.getCMSSWString() == res.getCMSSWString())
644  self.assertTrue(sel.getCMSSWString() == rem.getCMSSWString())
645 
646  def testURL(self):
647  URL = 'https://cms-service-dqm.web.cern.ch/cms-service-dqm/CAF/certification/Collisions12/8TeV/Reprocessing/Cert_190456-195530_8TeV_08Jun2012ReReco_Collisions12_JSON.txt'
648  ll = LumiList(url=URL)
649  self.assertTrue(len(ll) > 0)
650 
651 
652  def testWrite(self):
653  alumis = {'1' : range(2,20) + range(31,39) + range(45,49),
654  '2' : range(6,20) + range (30,40),
655  '3' : range(10,20) + range (30,40) + range(50,60),
656  '4' : range(1,100),
657  }
658  a = LumiList(runsAndLumis = alumis)
659  a.writeJSON('newFile.json')
660 
661 
662 if __name__ == '__main__':
663  jsonFile = open('lumiTest.json','w')
664  jsonFile.write('{"1": [[1, 33], [35, 35], [37, 47]], "2": [[49, 75], [77, 130], [133, 136]]}')
665  jsonFile.close()
666  unittest.main()
667 '''
668 # Test JSON file
669 
670 #{"1": [[1, 33], [35, 35], [37, 47]], "2": [[49, 75], [77, 130], [133, 136]]}
671 
672 if __name__ == '__main__':
673  #############################################
674  ## Load and save command line history when ##
675  ## running interactively. ##
676  #############################################
677  import os, readline
678  import atexit
679  historyPath = os.path.expanduser("~/.pyhistory")
680 
681 
682  def save_history(historyPath=historyPath):
683  import readline
684  readline.write_history_file(historyPath)
685  if os.path.exists(historyPath):
686  readline.read_history_file(historyPath)
687 
688 
689  atexit.register(save_history)
690  readline.parse_and_bind("set show-all-if-ambiguous on")
691  readline.parse_and_bind("tab: complete")
692  if os.path.exists (historyPath) :
693  readline.read_history_file(historyPath)
694  readline.set_history_length(-1)
695 
696 
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def getVLuminosityBlockRange
Definition: LumiList.py:290
list object
Definition: dbtoconf.py:77
def save_history
Definition: LumiList.py:682