ATLAS Offline Software
Loading...
Searching...
No Matches
LumiCalcHtml.py
Go to the documentation of this file.
1#!/usr/bin/env python
2
3# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4
5
6import cgi, os, sys
7import re
8import string
9import random
10import subprocess
11import cgitb
12import shutil
13
15
16 def __init__(self):
17
18 self.verbose = False
19 # Python file to make updates in working directory
20 self.updateScript = 'LumiCalcWorking.py'
21 self.recoverScript = 'LumiCalcRecover.py'
22
23 # Prod area
24 self.homeDir = '/var/www/lumicalc/'
25 self.dev = False
26
27 # Check if we are running as dev
28 if os.environ.get('SERVER_NAME', '') == 'atlas-lumicalc-dev.cern.ch':
29 self.homeDir = '/var/www/lumicalc_dev/'
30 self.dev = True
31
32 self.resultsDir = '/var/www/lumifiles/'
33
34 self.htmlDir = self.homeDir + 'athena/LumiBlock/LumiCalc/html/'
35 self.scriptDir = self.homeDir + 'athena/LumiBlock/LumiCalc/share/'
36 self.workdir = os.getcwd()
37
38 self.uselar = True
39 self.subdir = '.'
40
41 def createWorkdir(self):
42
43 # Create a new subdirectory for this
44 self.subdir = hex(random.randint(0,0xFFFFFF))[2:]
45 self.workdir = self.resultsDir + self.subdir
46 os.mkdir(self.workdir)
47
48 # Open the output file
49 self.f = open(self.workdir+'/working.html', 'w')
50
51 # Copy the working script
52 shutil.copyfile(self.updateScript, self.workdir+'/'+self.updateScript)
53
54 # Make sure it is executable
55 os.chmod(self.workdir+'/'+self.updateScript, 0o755)
56
57 # Also the recovery script
58 shutil.copyfile(self.recoverScript, self.workdir+'/'+self.recoverScript)
59 os.chmod(self.workdir+'/'+self.recoverScript, 0o755)
60
61 def cleanUp(self):
62
63 # Close the output file
64 self.f.close()
65
66 # OK, want to move working.html to result.html
67 # Update script should do the rest
68 shutil.move(self.workdir+'/working.html', self.workdir+'/result.html')
69
70 def printHead(self):
71
72 self.f.write( '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' )
73 self.f.write( '<head>\n' )
74 self.f.write( '<title>ATLAS Luminosity Calculator</title>\n' )
75 self.f.write( '<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"></meta>\n' )
76 self.f.write( '<meta name="ATLAS_Luminosity_Calculator" content="ATLAS Luminosity Calculator"></meta>\n' )
77 self.f.write( '<link rel="stylesheet" type="text/css" href="/css/atlas-datasummary.css" media="screen"></link>\n' )
78 self.f.write( '<link rel="stylesheet" type="text/css" href="/css/atlas-datasummary-print.css" media="print"></link>\n' )
79 self.f.write( '<link rel="shortcut icon" href="/images/favicon.ico"></link>\n' )
80 self.f.write( '</head>\n' )
81
82 def printTopTable(self):
83 self.f.write( '<body>\n' )
84 self.f.write( '<table class="toptable">\n' )
85
86 # Header file
87 fhead = open(self.htmlDir+"header.html", 'r')
88 for line in fhead.readlines():
89 self.f.write( line )
90 self.f.write( '</table>\n' )
91
93
94 # Footer file
95 ffoot = open(self.htmlDir+"footer.html", 'r')
96 for line in ffoot.readlines():
97 self.f.write( line )
98
99 def printFooter(self):
100 self.f.write( '<table class="bottomtable">\n')
101 self.f.write( '<tr style="height:45px; vertical-align: top;">\n')
102 self.f.write( '<td><a href="http://validator.w3.org/check?uri=referer">\n')
103 self.f.write( '<img src="/images/xhtml10.gif" alt="Valid XHTML 1.0 Transitional" /></a><br />\n')
104 self.f.write( '<a href="http://jigsaw.w3.org/css-validator/check/referer">\n')
105 self.f.write( '<img src="/images/css.gif" alt="Valid CSS!" /></a>\n')
106 self.f.write( '</td><td style="text-align:right"></td></tr></table>\n')
107
108 def parseForm(self):
109
110 form = cgi.FieldStorage()
111
112 # A nested FieldStorage instance holds the file
113 self.fileitem = form['file']
114 self.lumitag = form['lumitag'].value
115 self.livetrig = form['livetrig'].value
116 self.trigger = form['trigger'].value
117 self.clopts = form['clopts'].value
118 self.lartag = form['lartag'].value
119 for otheritem in form.getlist('other'):
120 self.clopts += (' ' + otheritem)
121
122 if self.lartag == 'None':
123 self.lartag = ''
124
125 def printForm(self):
126 self.f.write( '<div id="content">\n' )
127
128 # Go through and check for errors
129 error = False
130 self.f.write( '<h3>Checking inputs</h3>\n' )
131 self.f.write( '<ul>\n' )
132
133 self.f.write( '<li>Luminosity DB tag: '+self.lumitag+'</li>\n' )
134
135 if len(self.livetrig) == 0:
136 self.f.write( '<li><font color="red">Error: Live fraction trigger not specified!</font></li>\n' )
137 error = True
138
139 else:
140 self.f.write( '<li>Live fraction trigger: '+self.livetrig+'</li>\n' )
141
142 if string.find(self.livetrig, 'MBTS') > -1 and string.find(self.lumitag, 'HI') > -1:
143 self.f.write( '<li><font color="red">Error: Using MBTS to determine live fraction during Heavy Ion running is not recommended! Try using L1_LUCID_A_C instead.</font></li>\n')
144
145 if len(self.trigger) == 0:
146 self.f.write( '<li><font color="red">Warning: No physics trigger specified, uncorrected luminosity will be reported!</font></li>\n' )
147
148 else:
149 self.f.write( '<li>Physics trigger: '+self.trigger+'</li>\n' )
150
151 self.uselar = False
152 if len(self.lartag) == 0:
153 self.f.write( '<li><font color="red">Warning: No LAr EventVeto tag specified, uncorrected luminosity will be reported!</font></li>\n')
154
155 else:
156 self.f.write( '<li>LAr EventVeto Tag: ' + self.lartag+'</li>\n' )
157 self.uselar = True
158
159 # Test if the file was uploaded
160 if self.fileitem.filename:
161
162 # strip any leading C: from windows
163 if self.fileitem.filename[0:2] == 'C:':
164 self.fileitem.filename = self.fileitem.filename[2:]
165 # strip leading path from file name to avoid directory traversal attacks
166 self.grlfn = os.path.basename(self.fileitem.filename)
167
168 self.grlfilepath = self.workdir + '/' + self.grlfn
169 open(self.grlfilepath, 'w').write(self.fileitem.file.read())
170 self.f.write( '<li>GRL file: '+self.grlfn+' was uploaded successfully to '+self.workdir+'</li>\n' )
171
172 else:
173 self.f.write( '<li><font color="red">Error: No GRL file was uploaded</font></li>\n' )
174 error = True
175
176 if len(self.clopts) > 0:
177 self.f.write( '<li>Other options: '+self.clopts+'</li>\n' )
178
179 # Check if LAr EventVeto specified at the command line
180 if '--lar' in self.clopts:
181 self.uselar = True
182
183 self.f.write( '</ul>\n' )
184
185 if error:
186 self.f.write( '<p>Please fix errors before continuing!</p>\n' )
187
188 else:
189 self.f.write( '<p>Specification complete!</p>\n' )
190
191 return error
192
194
195 self.f.write( '<h3>Environment</h3>\n' )
196 f = open(self.htmlDir+'version.html', 'r')
197 for line in f.readlines():
198 self.f.write( line )
199
200 def printCommand(self):
201
202 self.f.write( '<h3>Command Details</h3>\n' )
203
204 self.command = ''
205 if self.lumitag == '--online':
206 self.command += ' --online'
207 elif self.lumitag == 'None':
208 pass
209 else:
210 self.command += (' --lumitag=' + self.lumitag)
211
212 self.command += (' --livetrigger=' + self.livetrig)
213 if len(self.trigger) > 0:
214 self.command += (' --trigger=' + self.trigger)
215
216 self.command += (' --xml=' + self.grlfilepath)
217
218 if len(self.lartag) > 0:
219 self.command += (' --lar --lartag=' + self.lartag)
220
221 if len(self.clopts) > 0:
222 self.command += (' '+self.clopts)
223
224 self.f.write( '<p>iLumiCalc '+self.command+'</p>\n' )
225
226 #self.cmdstr = os.getcwd()+'/runLumiCalc.sh '+self.command
227 if self.dev:
228 self.cmdstr = self.scriptDir+'runLumiCalcDev.sh '+self.command
229 else:
230 self.cmdstr = self.scriptDir+'runLumiCalc.sh '+self.command
231
232 def runCommand(self):
233 p = subprocess.Popen(self.cmdstr+' > output.txt 2>&1', executable='/bin/bash', cwd=self.workdir, shell=True)
234 p.wait()
235
236#
237# Now, parse iLumiCalc output file
238#
239 def parseOutput(self):
240
241 matchrun = re.compile(r'Run ([0-9]+) LB \[([0-9]+)-([0-9]+)\]')
242 matchlumidel = re.compile(r': IntL delivered \‍(ub\^-1\‍) : ([0-9\.e+]+)')
243 matchlumipre = re.compile(r': IntL after livefraction \‍(ub\^-1\‍): ([0-9\.\e\+\-]+)')
244 matchlumilar = re.compile(r': IntL after LAr fraction \‍(ub\^-1\‍): ([0-9\.\e\+\-]+)')
245 matchlumirec = re.compile(r': IntL recorded after prescale \‍(ub\^-1\‍) : ([0-9\.\e\+\-]+)')
246 matchgoodlb = re.compile(r': Good LBs : ([0-9]+)')
247 matchbadlb = re.compile(r': Bad LBs : ([0-9]+)')
248
249 matchtotlumidel = re.compile(r': Total IntL delivered \‍(ub\^-1\‍) : ([0-9\.\e\+\-]+)')
250 matchtotlumipre = re.compile(r': Total IntL after livefraction \‍(ub\^-1\‍): ([0-9\.\e\+\-]+)')
251 matchtotlumilar = re.compile(r': Total IntL after LAr fraction \‍(ub\^-1\‍): ([0-9\.\e\+\-]+)')
252 matchtotlumirec = re.compile(r': Total IntL recorded \‍(ub\^-1\‍) : ([0-9\.\e\+\-]+)')
253 matchtotgoodlb = re.compile(r': Total Good LBs : ([0-9]+)')
254 matchtotbadlb = re.compile(r': Total Bad LBs : ([0-9]+)')
255
256 matchrealtime = re.compile(r': Real time: ([0-9\.\e\+\-]+)')
257 matchcputime = re.compile(r': CPU time: ([0-9\.\e\+\-]+)')
258
259 self.runset = set()
260 self.lumidel = dict()
261 self.lumirec = dict()
262 self.lumipre = dict()
263 self.lumilar = dict()
264 self.goodlb = dict()
265 self.badlb = dict()
266
267 self.realtime = 0
268 self.cputime = 0
269
270 currentrun = '000000'
271
272 for line in open(self.workdir+'/output.txt').readlines():
273 m=matchrun.search(line)
274 if m:
275 if self.verbose:
276 print ('Found run/lbstart/lbend:', m.group(1), m.group(2), m.group(3))
277 currentrun = m.group(1)
278 self.runset.add(currentrun)
279
280 m=matchlumidel.search(line)
281 if m:
282 if self.verbose:
283 print ('Found lumiDel:', m.group(1), 'in run', currentrun)
284 self.lumidel[currentrun] = float(m.group(1)) + self.lumidel.get(currentrun, 0.)
285
286 m=matchlumirec.search(line)
287 if m:
288 if self.verbose:
289 print ('Found lumiRec:', m.group(1), 'in run', currentrun)
290 self.lumirec[currentrun] = float(m.group(1)) + self.lumirec.get(currentrun, 0.)
291
292 m=matchlumipre.search(line)
293 if m:
294 if self.verbose:
295 print ('Found lumiPre:', m.group(1), 'in run', currentrun)
296 self.lumipre[currentrun] = float(m.group(1)) + self.lumipre.get(currentrun, 0.)
297
298 m=matchlumilar.search(line)
299 if m:
300 if self.verbose:
301 print ('Found lumiLar:', m.group(1), 'in run', currentrun)
302 self.lumilar[currentrun] = float(m.group(1)) + self.lumilar.get(currentrun, 0.)
303
304 m = matchgoodlb.search(line)
305 if m:
306 if self.verbose:
307 print ('Found goodLB:', m.group(1), 'in run', currentrun)
308 self.goodlb[currentrun] = int(m.group(1)) + self.goodlb.get(currentrun, 0)
309
310 m = matchbadlb.search(line)
311 if m:
312 if self.verbose:
313 print ('Found badLB:', m.group(1), 'in run', currentrun)
314 self.badlb[currentrun] = int(m.group(1)) + self.badlb.get(currentrun, 0)
315
316 # Match end-of-job totals
317 m=matchtotlumidel.search(line)
318 if m:
319 if self.verbose:
320 print ('Found Total lumiDel:', m.group(1))
321 self.lumidel['Total'] = float(m.group(1)) + self.lumidel.get('Total', 0.)
322
323 m=matchtotlumirec.search(line)
324 if m:
325 if self.verbose:
326 print ('Found Total lumiRec:', m.group(1))
327 self.lumirec['Total'] = float(m.group(1)) + self.lumirec.get('Total', 0.)
328
329 m=matchtotlumipre.search(line)
330 if m:
331 if self.verbose:
332 print ('Found Total lumiPre:', m.group(1))
333 self.lumipre['Total'] = float(m.group(1)) + self.lumipre.get('Total', 0.)
334
335 m=matchtotlumilar.search(line)
336 if m:
337 if self.verbose:
338 print ('Found Total lumiLar:', m.group(1))
339 self.lumilar['Total'] = float(m.group(1)) + self.lumilar.get('Total', 0.)
340
341 m = matchtotgoodlb.search(line)
342 if m:
343 if self.verbose:
344 print ('Found Total goodLB:', m.group(1), 'in run', currentrun)
345 self.goodlb['Total'] = int(m.group(1)) + self.goodlb.get('Total', 0)
346
347 m = matchtotbadlb.search(line)
348 if m:
349 if self.verbose:
350 print ('Found Total badLB:', m.group(1), 'in run', currentrun)
351 self.badlb['Total'] = int(m.group(1)) + self.badlb.get('Total', 0)
352
353 m = matchrealtime.search(line)
354 if m:
355 self.realtime = float(m.group(1))
356
357 m = matchcputime.search(line)
358 if m:
359 self.cputime = float(m.group(1))
360
361 def printTable(self):
362
363 # Scale factor to apply to lumi values
364 # Base value is ub-1
365 totalLumi = self.lumirec.get('Total', 0.)
366 if totalLumi > 1E8:
367 scale = 1E-6
368 unit = 'pb<sup>-1</sup>'
369 elif totalLumi > 1E5:
370 scale = 1E-3
371 unit = 'nb<sup>-1</sup>'
372 elif totalLumi > 1E2:
373 scale = 1.
374 unit = 'ub<sup>-1</sup>'
375 else:
376 scale = 1000.
377 unit = 'mb<sup>-1</sup>'
378
379
380 # Open excel file
381 self.exf = open(self.workdir+'/lumitable.csv', 'w')
382
383 self.f.write( '<p>Command complete - CPU time: '+str(round(float(self.cputime), 1))+' s, Clock time: '+str(round(float(self.realtime), 1))+' s</p>\n' )
384 self.f.write( '<h3>Total Luminosity: '+str(scale*self.lumirec.get('Total', 0.))+' '+unit+'</h3>\n' )
385
386 self.f.write( '<table class="lumitable"><tbody>\n' )
387 self.f.write( '<tr><th>Run<br />Number</th><th>Number of<br />Good LBs</th><th>Number of<br />Bad LBs</th><th>Luminosity<br />Delivered ('+unit+')</th><th>Luminosity<br />Livefraction Corrected ('+unit+')</th>')
388 self.exf.write('Run, Good, Bad, LDelivered, LRecorded')
389 if self.uselar:
390 self.f.write('<th>Luminosity<br />LAr Veto Corrected ('+unit+')</th>')
391 self.exf.write(', LAr Corrected')
392
393 self.f.write('<th>Luminosity<br />Prescale Corrected ('+unit+')</th><th>Lumi-Weighted<br />Live Fraction (percent)</th>')
394 self.exf.write(', Prescale Corrected, Live Fraction')
395
396 if self.uselar:
397 self.f.write('<th>Lumi-Weighted<br />LAr Fraction (percent)</th>')
398 self.exf.write(', LAr Fraction')
399
400 self.f.write('<th>Lumi-Weighted<br />Prescale</th></tr>\n' )
401 self.exf.write(', Prescale Fraction\n')
402
403 # Sort this to get in order
404 runlist = []
405 for run in self.runset:
406 runlist.append(run)
407
408 runlist.sort()
409
410 # Tack this on the end so we print total also
411 runlist.append('Total')
412
413 for run in runlist:
414
415 if run == 'Total':
416 self.f.write( '<tr class="highlight">\n' )
417 self.f.write( '<td>Total</td>\n')
418 self.exf.write('Total, ')
419
420 else:
421 self.f.write( '<tr>\n' )
422 self.f.write( '<td>'+run+' (<a href="http://atlas-runquery.cern.ch/query.py?q=find+run+'+run+'+%2F+show+all+and+lhc">ARQ</a>, <a href="http://atlas-trigconf.cern.ch/psevo/'+run+'/">Prescales</a>)</td>\n')
423 self.exf.write((run+', '))
424
425 self.f.write( '<td>'+str(self.goodlb.get(run, 0))+'</td><td>'+str(self.badlb.get(run, 0))+'</td>\n' )
426
427 self.f.write( '<td>'+str(scale*self.lumidel.get(run, 0.))+'</td>\n' )
428 self.f.write( '<td>'+str(scale*self.lumipre.get(run, 0.))+'</td>\n' )
429 self.exf.write('%d, %d, %f, %f, ' % (self.goodlb.get(run, 0), self.badlb.get(run, 0), scale*self.lumidel.get(run, 0.), scale*self.lumipre.get(run, 0.)))
430
431 if self.uselar:
432 self.f.write( '<td>'+str(scale*self.lumilar.get(run, 0.))+'</td>\n' )
433 self.exf.write('%f, ' % (scale*self.lumilar.get(run, 0.)) )
434
435 self.f.write( '<td>'+str(scale*self.lumirec.get(run, 0.))+'</td>\n' )
436 self.exf.write('%f, ' % (scale*self.lumirec.get(run, 0.)) )
437
438 # Print live fraction
439 if self.lumidel.get(run, 0.) > 0.:
440 self.f.write( '<td>'+str(round(100*self.lumipre.get(run, 0.)/self.lumidel.get(run, 0.), 2))+'</td>\n' )
441 self.exf.write('%.2f, ' % (100*self.lumipre.get(run, 0.)/self.lumidel.get(run, 0.)) )
442 else:
443 self.f.write( '<td></td>\n' )
444 self.exf.write(' , ')
445
446 # Print LAr fraction
447 if self.uselar:
448 if self.lumipre.get(run, 0.) > 0.:
449 self.f.write( '<td>'+str(round(100*self.lumilar.get(run, 0.)/self.lumipre.get(run, 0.), 2))+'</td>\n' )
450 self.exf.write('%.2f, ' % (100*self.lumilar.get(run, 0.)/self.lumipre.get(run, 0.)) )
451
452 else:
453 self.f.write( '<td></td>\n' )
454 self.exf.write(' , ')
455
456 # Print prescale
457 if self.lumirec.get(run, 0.) > 0.:
458 self.f.write( '<td>'+str(round(self.lumilar.get(run, 0.)/self.lumirec.get(run, 0.), 3))+'</td>\n' )
459 self.exf.write('%.2f' % (100*self.lumilar.get(run, 0.)/self.lumirec.get(run, 0.)) )
460 else:
461 self.f.write( '<td></td>\n' )
462
463 else:
464 # Print prescale
465 if self.lumirec.get(run, 0.) > 0.:
466 self.f.write( '<td>'+str(round(self.lumipre.get(run, 0.)/self.lumirec.get(run, 0.), 3))+'</td>\n' )
467 self.exf.write('%.2f' % (100*self.lumipre.get(run, 0.)/self.lumirec.get(run, 0.)) )
468 else:
469 self.f.write( '<td></td>\n' )
470
471 self.f.write( '</tr>\n' )
472 self.exf.write('\n')
473
474
475 self.exf.close()
476
477 self.f.write( '</tbody></table>\n' )
478 self.f.write( '<p>[<a href="/results/'+self.subdir+'/lumitable.csv">Luminosity table as CSV file</a>]</p>\n' )
479
480 #
481 # Print warnings and errors from log file
482 #
483 def printWarnings(self):
484
485 matchwarn = re.compile('--- <.+>')
486 warnlist = []
487
488 for line in open(self.workdir+'/output.txt').readlines():
489 if matchwarn.search(line):
490 warnlist.append(line)
491
492 if len(warnlist) == 0:
493 return
494
495 self.f.write('<h3>Warnings/Errors</h3>\n')
496 self.f.write('<pre style="color: red">')
497 for warnline in warnlist:
498 self.f.write(warnline.replace('<', '&lsaquo;').replace('>', '&rsaquo;'))
499
500 self.f.write('</pre>\n')
501 self.f.write('<p>Check the <a href="/results/'+self.subdir+'/output.txt">Raw iLumiCalc output</a> for more information.</p>\n' )
502
503 #
504 # Now setup full dump (hidden by JS button)
505 #
506 def printScript(self):
507 self.f.write( '<script>' )
508 self.f.write( 'function makevisible() {' )
509 self.f.write( 'var visible' )
510 self.f.write( 'var hidden' )
511 self.f.write( 'visible = document.getElementById("visible").innerHTML;' )
512 self.f.write( 'hidden = document.getElementById("results").innerHTML;' )
513 self.f.write( 'document.getElementById("visible").innerHTML = hidden;' )
514 self.f.write( '}' )
515 self.f.write( '</script>' )
516
517 def printDetails(self):
518 self.f.write( '<div id="visible"><p><input type="button" value="Show detailed output" onclick="makevisible()"></p></div>\n' )
519
520 self.f.write( '<div id="results" style="visibility: hidden">\n' )
521 self.f.write( '<h3>Detailed Output</h3>\n' )
522 self.f.write( '<pre>\n' )
523 for line in open(self.workdir+'/output.txt').readlines():
524 self.f.write( line )
525
526 self.f.write( '</pre></div>\n' )
527
528 def printLinks(self):
529 self.f.write( '<h3>Links</h3>\n' )
530 self.f.write( '<p>The following links provide access to the iLumiCalc output files. These will likely remain for several weeks, but please copy any critical files to a more permanent location.</p>\n' )
531
532 self.f.write( '<p><a href="/results/'+self.subdir+'/">iLumiCalc working directory</a> - location for all output files</p>\n' )
533 self.f.write( '<p><a href="/results/'+self.subdir+'/result.html">Output HTML</a> - this page</p>\n' )
534 self.f.write( '<p><a href="/results/'+self.subdir+'/output.txt">Raw iLumiCalc output</a></p>\n' )
535 self.f.write( '<p><a href="/results/'+self.subdir+'/'+self.grlfn+'">Original GRL XML file</a></p>\n' )
536
537 # Call iLumiCalc to print out help
538 def printHelp(self):
539 self.f.write( '<h3>LumiCalc Usage</h3>\n' )
540 self.f.write( '<pre>\n' )
541 self.f.write( '> iLumiCalc --help\n\n' )
542 for line in open (self.scriptDir+'help.txt').readlines():
543 self.f.write( line )
544
545 self.f.write( '</pre>\n' )
546
547 # All done
548 def printFinish(self):
549 self.f.write( '</div>\n' )
550 # self.printBottomTable()
551 self.printFooter()
552 self.f.write( '</body></html>\n' )
553
554 def printRedirect(self, outfile='LumiCalcWorking.py'):
555 print ('Content-Type: text/html')
556 print ()# Blank line, end of headers
557 print ('<html><head>')
558 print ('<meta http-equiv="Refresh" content="0; url=/results/'+self.subdir+'/'+outfile+'">')
559 print ('</head></html>')
560
561 # For debugging, dump all os.environ variables
562 def dumpEnviron(self):
563
564 print ('Content-Type: text/html')
565 print () # Blank line, end of headers
566 print ('<html>')
567 for key in os.environ:
568 print('<p><b>',key,':</b>',os.environ[key],'<p>')
569 print ('</html>')
570
571# Run from command line
572if __name__ == "__main__":
573
574 # Enable debugging output for CGI
575 cgitb.enable()
576
577 # Experimental way here
578 lc = LumiCalc()
579 lc.createWorkdir()
580
581 # Make sure we have something in working.html
582 lc.parseForm()
583 lc.printHead()
584 lc.printTopTable()
585 if lc.printForm():
586 # Error, finish here
587 lc.printHelp()
588 lc.printFinish()
589 lc.cleanUp()
590 lc.printRedirect('result.html')
591 sys.exit(0) # Exit on error
592
593 # OK, we are going to run iLumiCalc
594 # Print the redirect and close stdout to get the browser to respond
595 lc.printEnvironment()
596 lc.printCommand()
597 lc.f.flush()
598 lc.printRedirect()
599 sys.stdout.flush()
600 sys.stdout.close() # Trigger browser to complete
601 os.close(1) # Really close it
602
603 # Here we run the command
604 lc.runCommand()
605
606 lc.parseOutput()
607 lc.printTable()
608 lc.printWarnings()
609 lc.printLinks()
610 lc.printFinish()
611 lc.cleanUp()
612
613 # Other possibility to fork
614 #sys.stdout.flush()
615 #if os.fork(): return
616 #fw = open('/dev/null','w')
617 #os.dup2(fw.fileno(),1)
618 #os.dup2(fw.fileno(),2)
619
void printHelp()
void print(char *figname, TCanvas *c1)
printRedirect(self, outfile='LumiCalcWorking.py')
STL class.
bool add(const std::string &hname, TKey *tobj)
Definition fastadd.cxx:55
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130