1 |
from HTMLParser import HTMLParser
|
2 |
from urllib2 import urlopen
|
3 |
import cPickle as pickle
|
4 |
import sys
|
5 |
|
6 |
class Page1Parser(HTMLParser):
|
7 |
|
8 |
def __init__(self):
|
9 |
HTMLParser.__init__(self)
|
10 |
self.InRow=0
|
11 |
self.InEntry=0
|
12 |
self.table = []
|
13 |
self.tmpRow = []
|
14 |
self.hyperlinks = []
|
15 |
self.RunNumber = 0
|
16 |
self.TriggerRates = []
|
17 |
self.Nevts = []
|
18 |
self.LiveLumiByLS = []
|
19 |
self.DeliveredLumiByLS = []
|
20 |
self.FirstLS = -1
|
21 |
self.LastLS = -1
|
22 |
self.AvLiveLumi = []
|
23 |
self.AvDeliveredLumi = []
|
24 |
self.AvDeadtime = []
|
25 |
self.DeadTime = []#grant
|
26 |
self.L1Prescales=[]
|
27 |
self.RunPage = ''
|
28 |
self.RatePage = ''
|
29 |
self.LumiPage = ''
|
30 |
self.L1Page=''
|
31 |
self.L1_LS_Page = ''#grant
|
32 |
self.PrescaleColumn=[]
|
33 |
self.PrescaleColumnString = ''
|
34 |
|
35 |
def _Parse(self,url):
|
36 |
self.table = []
|
37 |
self.hyperlinks = []
|
38 |
try:
|
39 |
req = urlopen(url)
|
40 |
self.feed(req.read())
|
41 |
except:
|
42 |
print "Error Getting page: "+url
|
43 |
print "Please retry. If problem persists, contact developer"
|
44 |
sys.exit(1)
|
45 |
|
46 |
def handle_starttag(self,tag,attrs):
|
47 |
if tag == 'a' and attrs:
|
48 |
self.hyperlinks.append(attrs[0][1])
|
49 |
if tag == 'tr':
|
50 |
self.InRow=1
|
51 |
if tag == 'td':
|
52 |
self.InEntry=1
|
53 |
|
54 |
def handle_endtag(self,tag):
|
55 |
if tag =='tr':
|
56 |
if self.InRow==1:
|
57 |
self.InRow=0
|
58 |
self.table.append(self.tmpRow)
|
59 |
self.tmpRow=[]
|
60 |
if tag == 'td':
|
61 |
self.InEntry=0
|
62 |
|
63 |
def handle_data(self,data):
|
64 |
if self.InEntry:
|
65 |
self.tmpRow.append(data)
|
66 |
|
67 |
def ParsePage1(self):
|
68 |
try:
|
69 |
# Find the first non-empty row on page one
|
70 |
MostRecent = self.table[0]
|
71 |
for line in self.table:
|
72 |
if line == []:
|
73 |
continue # skip empty rows, not exactly sure why they show up
|
74 |
MostRecent = line
|
75 |
break # find first non-empty line
|
76 |
TriggerMode = MostRecent[3]
|
77 |
isCollisions = not (TriggerMode.find('l1_hlt_collisions') == -1)
|
78 |
if not isCollisions:
|
79 |
return ''
|
80 |
self.RunNumber = MostRecent[0]
|
81 |
for link in self.hyperlinks:
|
82 |
if not link.find('RUN='+self.RunNumber)==-1:
|
83 |
self.RunPage = link
|
84 |
return link
|
85 |
except:
|
86 |
print "Cannot parse Page 1 to find the most recent run. Is WBM down? If not, and this message persists, post problem on elog!"
|
87 |
sys.exit(0)
|
88 |
|
89 |
def ParseRunPage(self):
|
90 |
try:
|
91 |
for entry in self.hyperlinks:
|
92 |
entry = entry.replace('../../','http://cmswbm/')
|
93 |
if not entry.find('HLTSummary') == -1:
|
94 |
self.RatePage = entry
|
95 |
if not entry.find('L1Summary') == -1:
|
96 |
self.L1Page = entry
|
97 |
if not entry.find('LumiSections') == -1:
|
98 |
self.LumiPage = "http://cmswbm/cmsdb/servlet/"+entry
|
99 |
return [self.RatePage,self.LumiPage,self.L1Page]
|
100 |
except:
|
101 |
print "Cannot parse Run Page. Is WBM down? If not, and this message persists, post problem on elog!"
|
102 |
sys.exit(0)
|
103 |
|
104 |
def ParseRunSummaryPage(self):
|
105 |
try:
|
106 |
for line in self.table:
|
107 |
if not len(line)>6: # All relevant lines in the table will be at least this long
|
108 |
continue
|
109 |
if line[1].startswith('HLT_'):
|
110 |
TriggerName = line[1][:line[1].find(' ')] # Format is HLT_... (####), this gets rid of the (####)
|
111 |
TriggerRate = float(line[6].replace(',','')) # Need to remove the ","s, since float() can't parse them
|
112 |
self.Nevts.append([TriggerName,int(line[3]),int(line[4]),int(line[5]),line[9]]) # 3-5 are the accept columns, 9 is the L1 seed name
|
113 |
PS=0
|
114 |
if int(line[4])>0:
|
115 |
PS = float(line[3])/float(line[4])
|
116 |
|
117 |
self.TriggerRates.append([TriggerName,TriggerRate,PS,line[9]])
|
118 |
except:
|
119 |
print "Cannot parse HLT Rate Page. Is WBM down? If not, and this message persists, post problem on elog!"
|
120 |
sys.exit(0)
|
121 |
|
122 |
def ParseLumiPage(self, StartLS=999999, EndEndLS=111111):
|
123 |
#previous_lumi = 0 ##Andrew - This and following lines with previous_lumi stop parsing when "Active" goes red
|
124 |
#already_continued = False
|
125 |
try:
|
126 |
for line in self.table:
|
127 |
if len(line)<2 or len(line)>12:
|
128 |
continue
|
129 |
if int(line[0]) > EndEndLS:
|
130 |
continue
|
131 |
|
132 |
#if float(line[6]) == previous_lumi and float(line[4]) != 0 and int(line[2]) == 0 and self.FirstLS != -1: #Stops when "Active" goes red
|
133 |
#already_continued = True
|
134 |
#continue
|
135 |
#if already_continued == True:
|
136 |
#continue
|
137 |
|
138 |
self.LiveLumiByLS.append(float(line[6])) # Live lumi is in position 6
|
139 |
self.DeliveredLumiByLS.append(float(line[5])) #Delivered lumi is in position 5
|
140 |
self.PrescaleColumn.append(int(line[2])) # Prescale column is in position 2
|
141 |
|
142 |
#if float(line[4]) != 0 and int(line[2]) == 0 and self.FirstLS != -1: #Initializes last_lumi when Prescale goes to 0
|
143 |
#previous_lumi = float(line[6])
|
144 |
|
145 |
if self.FirstLS == -1 and float(line[6]) > 0: # live lumi is in position 6, the first lumiblock with this > 0 should be recorded
|
146 |
self.FirstLS = int(line[0])
|
147 |
|
148 |
if not StartLS==999999:
|
149 |
|
150 |
if StartLS<0: # negative startLS means we want to do sliding window
|
151 |
StartLS = len(self.LiveLumiByLS)+StartLS-3 #start LS is -1*window, plus an offset of 3 LS to mitigate problems from parsing WBM live
|
152 |
|
153 |
if StartLS < self.FirstLS:
|
154 |
print "\n>>> Selected LS is before stable beam, defaulting to first LS of stable beam\n"
|
155 |
elif StartLS>len(self.LiveLumiByLS):
|
156 |
print "\n>>> Selected LS is out of range!"
|
157 |
sys.exit(0)
|
158 |
else:
|
159 |
self.FirstLS = StartLS
|
160 |
|
161 |
self.FirstLS-=2 ##The parsing starts from the second lumisection, so index = 0 corresponds to LS = 2, index = 5 -> LS = 7, etc.
|
162 |
if EndEndLS == 111111:
|
163 |
self.LastLS = self.FirstLS + (len(self.LiveLumiByLS[self.FirstLS:]) - 1) - 3 #len() is one off, plus WBM parsing offset
|
164 |
else:
|
165 |
self.LastLS = EndEndLS - 2 ##The parsing starts from the second lumisection, so index = 0 corresponds to LS = 2, index = 5 -> LS = 7, etc
|
166 |
|
167 |
self.AvLiveLumi = 1000 * ( max(self.LiveLumiByLS[self.FirstLS:self.LastLS]) - self.LiveLumiByLS[self.FirstLS] ) / ( ( len(self.LiveLumiByLS[self.FirstLS:self.LastLS]) - 1 ) * 23.3 )
|
168 |
self.AvDeliveredLumi = 1000 * ( max(self.DeliveredLumiByLS[self.FirstLS:self.LastLS]) - self.DeliveredLumiByLS[self.FirstLS] ) / ( ( len(self.DeliveredLumiByLS[self.FirstLS:self.LastLS]) - 1 ) * 23.3 )
|
169 |
|
170 |
self.AvDeadtime = 100 * (self.AvDeliveredLumi - self.AvLiveLumi) / (self.AvDeliveredLumi + 0.1)
|
171 |
|
172 |
if max(self.PrescaleColumn[self.FirstLS:]) == min(self.PrescaleColumn[self.FirstLS:]):
|
173 |
self.PrescaleColumnString = str(self.PrescaleColumn[self.FirstLS])
|
174 |
else:
|
175 |
self.PrescaleColumnString = str(max(self.PrescaleColumn[self.FirstLS:]))+" and "+str(min(self.PrescaleColumn[self.FirstLS:]))
|
176 |
self.FirstLS+=2 ##For purposes of printing output later on
|
177 |
self.LastLS+=2
|
178 |
|
179 |
except:
|
180 |
print "Cannot parse Lumi Page. Is WBM down? If not, and this message persists, post problem on elog!"
|
181 |
sys.exit(0)
|
182 |
|
183 |
def ParseL1Page(self):
|
184 |
try:
|
185 |
for line in self.table:
|
186 |
if len(line) < 9:
|
187 |
continue
|
188 |
if line[1].startswith('L1_'):
|
189 |
self.L1Prescales.append([line[1],float(line[8])])
|
190 |
except:
|
191 |
print "Cannot parse L1 Page. Is WBM down? If not, and this message persists, post problem on elog!"
|
192 |
sys.exit(0)
|
193 |
|
194 |
def Parse_LS_L1Page(self):
|
195 |
try:
|
196 |
self.DeadTime=[]
|
197 |
for line in self.table:
|
198 |
if line != [] and len(line)<5:
|
199 |
MostRecent = line[:]
|
200 |
if '%' in MostRecent:
|
201 |
print MostRecent
|
202 |
self.DeadTime.append(MostRecent[2])
|
203 |
except:
|
204 |
print"Unable to parse DeadTimes"
|
205 |
sys.exit(0)
|
206 |
|
207 |
def Save(self, fileName):
|
208 |
pickle.dump( self, open( fileName, 'w' ) )
|
209 |
|
210 |
def Load(self, fileName):
|
211 |
self = pickle.load( open( fileName ) )
|