Package madgraph :: Package madevent :: Module gen_crossxhtml
[hide private]
[frames] | no frames]

Source Code for Module madgraph.madevent.gen_crossxhtml

   1  ################################################################################ 
   2  # 
   3  # Copyright (c) 2011 The MadGraph5_aMC@NLO Development team and Contributors 
   4  # 
   5  # This file is a part of the MadGraph5_aMC@NLO project, an application which  
   6  # automatically generates Feynman diagrams and matrix elements for arbitrary 
   7  # high-energy processes in the Standard Model and beyond. 
   8  # 
   9  # It is subject to the MadGraph5_aMC@NLO license which should accompany this  
  10  # distribution. 
  11  # 
  12  # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch 
  13  # 
  14  ################################################################################ 
  15  """ Create gen_crossxhtml """ 
  16   
  17   
  18  import os 
  19  import math 
  20  import re 
  21  import pickle 
  22  import re 
  23  import glob 
  24  import logging 
  25   
  26  try: 
  27      import madgraph 
  28  except ImportError: 
  29      import internal.files as files 
  30      import internal.save_load_object as save_load_object 
  31      import internal.lhe_parser as lhe_parser 
  32      import internal.misc as misc 
  33  else: 
  34      import madgraph.iolibs.files as files 
  35      import madgraph.iolibs.save_load_object as save_load_object 
  36      import madgraph.various.lhe_parser as lhe_parser 
  37      import madgraph.various.misc as misc 
  38   
  39  pjoin = os.path.join 
  40  exists = os.path.exists 
  41  logger = logging.getLogger('madgraph.stdout') # -> stdout 
  42   
  43   
  44   
  45  crossxhtml_template = """ 
  46  <HTML>  
  47  <HEAD>  
  48      %(refresh)s  
  49      <META HTTP-EQUIV="EXPIRES" CONTENT="20" >  
  50      <TITLE>Online Event Generation</TITLE> 
  51      <link rel=stylesheet href="./HTML/mgstyle.css" type="text/css"> 
  52  </HEAD> 
  53  <BODY> 
  54  <script type="text/javascript"> 
  55  function UrlExists(url) { 
  56    var http = new XMLHttpRequest(); 
  57    http.open('HEAD', url, false); 
  58    try{ 
  59       http.send() 
  60       } 
  61    catch(err){ 
  62     return 1==2; 
  63    } 
  64    return http.status!=404; 
  65  } 
  66  function check_link(url,alt, id){ 
  67      var obj = document.getElementById(id); 
  68      if ( ! UrlExists(url)){ 
  69         if ( ! UrlExists(alt)){ 
  70           obj.href = url; 
  71           return 1==1; 
  72          } 
  73         obj.href = alt; 
  74         return 1 == 2; 
  75      } 
  76      obj.href = url; 
  77      return 1==1; 
  78  } 
  79  </script>     
  80      <H2 align=center> Results in the %(model)s for %(process)s </H2>  
  81      <HR> 
  82      %(status)s 
  83      <br> 
  84      <br> 
  85      <H2 align="center"> Available Results </H2> 
  86          <TABLE BORDER=2 align="center">   
  87              <TR align="center"> 
  88                  <TH>Run</TH>  
  89                  <TH>Collider</TH>  
  90                  <TH> Banner </TH> 
  91                  <TH> %(numerical_title)s </TH>  
  92                  <TH> Events  </TH> 
  93                  <TH> Data </TH>   
  94                  <TH>Output</TH> 
  95                  <TH>Action</TH>  
  96              </TR>       
  97              %(old_run)s 
  98          </TABLE> 
  99      <H3 align=center><A HREF="./index.html"> Main Page </A></H3> 
 100  </BODY>  
 101  </HTML>  
 102  """ 
 103   
 104  status_template = """ 
 105  <H2 ALIGN=CENTER> Currently Running %(run_mode_string)s</H2> 
 106  <TABLE BORDER=2 ALIGN=CENTER> 
 107      <TR ALIGN=CENTER> 
 108          <TH nowrap ROWSPAN=2 font color="#0000FF"> Run Name </TH> 
 109          <TH nowrap ROWSPAN=2 font color="#0000FF"> Tag Name </TH> 
 110          <TH nowrap ROWSPAN=2 font color="#0000FF"> Cards </TH>    
 111          <TH nowrap ROWSPAN=2 font color="#0000FF"> Results </TH>  
 112          <TH nowrap ROWSPAN=1 COLSPAN=3 font color="#0000FF"> Status/Jobs </TH> 
 113      </TR> 
 114          <TR>  
 115              <TH>   Queued </TH> 
 116              <TH>  Running </TH> 
 117              <TH> Done  </TH> 
 118          </TR> 
 119      <TR ALIGN=CENTER>  
 120          <TD nowrap ROWSPAN=2> %(run_name)s </TD> 
 121          <TD nowrap ROWSPAN=2> %(tag_name)s </TD> 
 122          <TD nowrap ROWSPAN=2> <a href="./Cards/param_card.dat">param_card</a><BR> 
 123                      <a href="./Cards/run_card.dat">run_card</a><BR> 
 124                      %(plot_card)s 
 125                      %(pythia_card)s 
 126                      %(pgs_card)s 
 127                      %(delphes_card)s 
 128                      %(shower_card)s 
 129                      %(fo_analyse_card)s 
 130          </TD> 
 131          <TD nowrap ROWSPAN=2> %(results)s </TD>  
 132          %(status)s 
 133   </TR> 
 134   <TR></TR> 
 135     %(stop_form)s 
 136   </TABLE> 
 137  """ 
 138   
139 -class AllResults(dict):
140 """Store the results for all the run of a given directory""" 141 142 web = False 143
144 - def __init__(self, model, process, path, recreateold=True):
145 146 dict.__init__(self) 147 self.order = [] 148 self.lastrun = None 149 self.process = ', '.join(process) 150 if len(self.process) > 60: 151 pos = self.process[50:].find(',') 152 if pos != -1: 153 self.process = self.process[:50+pos] + ', ...' 154 self.path = path 155 self.model = model 156 self.status = '' 157 self.unit = 'pb' 158 self.current = None 159 160 # Check if some directory already exists and if so add them 161 runs = [d for d in os.listdir(pjoin(path, 'Events')) if 162 os.path.isdir(pjoin(path, 'Events', d))] 163 if runs: 164 if recreateold: 165 for run in runs: 166 self.readd_old_run(run) 167 if self.order: 168 self.current = self[self.order[-1]] 169 else: 170 logger.warning("Previous runs exists but they will not be present in the html output.")
171
172 - def readd_old_run(self, run_name):
173 """ re-create the data-base from scratch if the db was remove """ 174 175 event_path = pjoin(self.path, "Events", run_name, "unweighted_events.lhe") 176 177 try: 178 import madgraph 179 except ImportError: 180 import internal.banner as bannerlib 181 else: 182 import madgraph.various.banner as bannerlib 183 184 if os.path.exists("%s.gz" % event_path): 185 misc.gunzip(event_path, keep=True) 186 if not os.path.exists(event_path): 187 return 188 banner = bannerlib.Banner(event_path) 189 190 # load the information to add a new Run: 191 run_card = banner.charge_card("run_card") 192 process = banner.get_detail("proc_card", "generate") 193 #create the new object 194 run = RunResults(run_name, run_card, process, self.path) 195 run.recreate(banner) 196 self[run_name] = run 197 self.order.append(run_name)
198 199
200 - def def_current(self, run, tag=None):
201 """define the name of the current run 202 The first argument can be a OneTagResults 203 """ 204 205 if isinstance(run, OneTagResults): 206 self.current = run 207 self.lastrun = run['run_name'] 208 return 209 210 assert run in self or run == None 211 self.lastrun = run 212 if run: 213 if not tag: 214 self.current = self[run][-1] 215 else: 216 assert tag in self[run].tags 217 index = self[run].tags.index(tag) 218 self.current = self[run][index] 219 220 else: 221 self.current = None
222
223 - def delete_run(self, run_name, tag=None):
224 """delete a run from the database""" 225 226 assert run_name in self 227 228 if not tag : 229 if self.current and self.current['run_name'] == run_name: 230 self.def_current(None) 231 del self[run_name] 232 self.order.remove(run_name) 233 if self.lastrun == run_name: 234 self.lastrun = None 235 else: 236 assert tag in [a['tag'] for a in self[run_name]] 237 RUN = self[run_name] 238 if len(RUN) == 1: 239 self.delete_run(run_name) 240 return 241 RUN.remove(tag) 242 243 #update the html 244 self.output()
245
246 - def def_web_mode(self, web):
247 """define if we are in web mode or not """ 248 if web is True: 249 try: 250 web = os.environ['SERVER_NAME'] 251 except Exception: 252 web = 'my_computer' 253 self['web'] = web 254 self.web = web
255
256 - def add_run(self, name, run_card, current=True):
257 """ Adding a run to this directory""" 258 259 tag = run_card['run_tag'] 260 if name in self.order: 261 #self.order.remove(name) # Reorder the run to put this one at the end 262 if tag in self[name].tags: 263 if self[name].return_tag(tag).parton and len(self[name]) > 1: 264 #move the parton information before the removr 265 self[name].return_tag(self[name][1]['tag']).parton = \ 266 self[name].return_tag(tag).parton 267 if len(self[name]) > 1: 268 self[name].remove(tag) # Remove previous tag if define 269 self[name].add(OneTagResults(name, run_card, self.path)) 270 else: 271 #add the new tag run 272 self[name].add(OneTagResults(name, run_card, self.path)) 273 new = self[name] 274 else: 275 new = RunResults(name, run_card, self.process, self.path) 276 self[name] = new 277 self.order.append(name) 278 279 if current: 280 self.def_current(name) 281 if new.info['unit'] == 'GeV': 282 self.unit = 'GeV'
283
284 - def update(self, status, level, makehtml=True, error=False):
285 """update the current run status""" 286 if self.current: 287 self.current.update_status(level) 288 self.status = status 289 if self.current and self.current.debug and self.status and not error: 290 self.current.debug = None 291 292 if makehtml: 293 self.output()
294
295 - def resetall(self, main_path=None):
296 """check the output status of all run 297 main_path redefines the path associated to the run (allowing to move 298 the directory) 299 """ 300 301 self.path = main_path 302 303 for key,run in self.items(): 304 if key == 'web': 305 continue 306 for i,subrun in enumerate(run): 307 self.def_current(subrun) 308 self.clean() 309 self.current.event_path = pjoin(main_path,'Events') 310 self.current.me_dir = main_path 311 if i==0: 312 self.current.update_status() 313 else: 314 self.current.update_status(nolevel='parton') 315 self.output()
316
317 - def clean(self, levels = ['all'], run=None, tag=None):
318 """clean the run for the levels""" 319 320 if not run and not self.current: 321 return 322 to_clean = self.current 323 if run and not tag: 324 for tagrun in self[run]: 325 self.clean(levels, run, tagrun['tag']) 326 return 327 328 if run: 329 to_clean = self[run].return_tag(tag) 330 else: 331 run = to_clean['run_name'] 332 333 if 'all' in levels: 334 levels = ['parton', 'pythia', 'pgs', 'delphes', 'channel'] 335 336 if 'parton' in levels: 337 to_clean.parton = [] 338 if 'pythia' in levels: 339 to_clean.pythia = [] 340 if 'pgs' in levels: 341 to_clean.pgs = [] 342 if 'delphes' in levels: 343 to_clean.delphes = []
344 345
346 - def save(self):
347 """Save the results of this directory in a pickle file""" 348 filename = pjoin(self.path, 'HTML', 'results.pkl') 349 save_load_object.save_to_file(filename, self)
350
351 - def add_detail(self, name, value, run=None, tag=None):
352 """ add information to current run (cross/error/event)""" 353 assert name in ['cross', 'error', 'nb_event', 'cross_pythia', 354 'nb_event_pythia','error_pythia', 'run_mode', 355 'run_statistics'] 356 357 if not run and not self.current: 358 return 359 360 if not run: 361 run = self.current 362 else: 363 run = self[run].return_tag(tag) 364 365 if name == 'cross_pythia': 366 run['cross_pythia'] = float(value) 367 elif name == 'nb_event': 368 run[name] = int(value) 369 elif name == 'nb_event_pythia': 370 run[name] = int(value) 371 elif name in ['run_mode','run_statistics']: 372 run[name] = value 373 else: 374 run[name] = float(value)
375
376 - def get_detail(self, name, run=None, tag=None):
377 """ add information to current run (cross/error/event)""" 378 assert name in ['cross', 'error', 'nb_event', 'cross_pythia', 379 'nb_event_pythia','error_pythia', 'run_mode', 380 'run_statistics'] 381 382 if not run and not self.current: 383 return None 384 385 if not run: 386 run = self.current 387 else: 388 run = self[run].return_tag(tag) 389 390 return run[name]
391
392 - def output(self):
393 """ write the output file """ 394 395 # 1) Create the text for the status directory 396 if self.status and self.current: 397 if isinstance(self.status, str): 398 status = '<td ROWSPAN=2 colspan=4>%s</td>' % self.status 399 else: 400 s = list(self.status) 401 if s[0] == '$events': 402 if self.current['nb_event']: 403 nevent = self.current['nb_event'] 404 else: 405 nevent = self[self.current['run_name']][0]['nb_event'] 406 if nevent: 407 s[0] = nevent - int(s[1]) -int(s[2]) 408 else: 409 s[0] = '' 410 status ='''<td> %s </td> <td> %s </td> <td> %s </td> 411 </tr><tr><td colspan=3><center> %s </center></td>''' % (s[0],s[1], s[2], s[3]) 412 413 414 status_dict = {'status': status, 415 'cross': self.current['cross'], 416 'error': self.current['error'], 417 'run_name': self.current['run_name'], 418 'tag_name': self.current['tag'], 419 'unit': self[self.current['run_name']].info['unit']} 420 # add the run_mode_string for amcatnlo_run 421 if 'run_mode' in self.current.keys(): 422 run_mode_string = {'aMC@NLO': '(aMC@NLO)', 423 'aMC@LO': '(aMC@LO)', 424 'noshower': '(aMC@NLO)', 425 'noshowerLO': '(aMC@LO)', 426 'NLO': '(NLO f.o.)', 427 'LO': '(LO f.o.)', 428 'madevent':''} 429 status_dict['run_mode_string'] = run_mode_string[self.current['run_mode']] 430 else: 431 status_dict['run_mode_string'] = '' 432 433 434 if exists(pjoin(self.path, 'HTML',self.current['run_name'], 435 'results.html')): 436 status_dict['results'] = """<A HREF="./HTML/%(run_name)s/results.html">%(cross).4g <font face=symbol>&#177;</font> %(error).4g (%(unit)s)</A>""" % status_dict 437 else: 438 status_dict['results'] = "No results yet" 439 if exists(pjoin(self.path, 'Cards', 'plot_card.dat')): 440 status_dict['plot_card'] = """ <a href="./Cards/plot_card.dat">plot_card</a><BR>""" 441 else: 442 status_dict['plot_card'] = "" 443 if exists(pjoin(self.path, 'Cards', 'pythia_card.dat')): 444 status_dict['pythia_card'] = """ <a href="./Cards/pythia_card.dat">pythia_card</a><BR>""" 445 else: 446 status_dict['pythia_card'] = "" 447 if exists(pjoin(self.path, 'Cards', 'pgs_card.dat')): 448 status_dict['pgs_card'] = """ <a href="./Cards/pgs_card.dat">pgs_card</a><BR>""" 449 else: 450 status_dict['pgs_card'] = "" 451 if exists(pjoin(self.path, 'Cards', 'delphes_card.dat')): 452 status_dict['delphes_card'] = """ <a href="./Cards/delphes_card.dat">delphes_card</a><BR>""" 453 else: 454 status_dict['delphes_card'] = "" 455 if exists(pjoin(self.path, 'Cards', 'shower_card.dat')): 456 status_dict['shower_card'] = """ <a href="./Cards/shower_card.dat">shower_card</a><BR>""" 457 else: 458 status_dict['shower_card'] = "" 459 if exists(pjoin(self.path, 'Cards', 'FO_analyse_card.dat')): 460 status_dict['fo_analyse_card'] = """ <a href="./Cards/FO_analyse_card.dat">FO_analyse_card</a><BR>""" 461 else: 462 status_dict['fo_analyse_card'] = "" 463 464 if self.web: 465 status_dict['stop_form'] = """ 466 <TR ALIGN=CENTER><TD COLSPAN=7 text-align=center> 467 <FORM ACTION="http://%(web)s/cgi-bin/RunProcess/handle_runs-pl" ENCTYPE="multipart/form-data" METHOD="POST"> 468 <INPUT TYPE=HIDDEN NAME=directory VALUE="%(me_dir)s"> 469 <INPUT TYPE=HIDDEN NAME=whattodo VALUE="stop_job"> 470 <INPUT TYPE=SUBMIT VALUE="Stop Current Job"> 471 </FORM></TD></TR>""" % {'me_dir': self.path, 'web': self.web} 472 else: 473 status_dict['stop_form'] = "" 474 475 476 status = status_template % status_dict 477 refresh = "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"10\">" 478 else: 479 status ='' 480 refresh = '' 481 482 483 # See if we need to incorporate the button for submission 484 if os.path.exists(pjoin(self.path, 'RunWeb')): 485 running = True 486 else: 487 running = False 488 489 # 2) Create the text for the old run: 490 old_run = '' 491 for key in self.order: 492 old_run += self[key].get_html(self.path, web=self.web, running=running) 493 494 text_dict = {'process': self.process, 495 'model': self.model, 496 'status': status, 497 'old_run': old_run, 498 'refresh': refresh, 499 'numerical_title': self.unit == 'pb' and 'Cross section (pb)'\ 500 or 'Width (GeV)'} 501 502 text = crossxhtml_template % text_dict 503 open(pjoin(self.path,'crossx.html'),'w').write(text)
504 505
506 -class AllResultsNLO(AllResults):
507 """Store the results for a NLO run of a given directory""" 508
509 - def __init__(self,model, process, path, recreateold=False):
510 return AllResults.__init__(self, model, process, path, recreateold=recreateold)
511 512
513 -class RunResults(list):
514 """The list of all OneTagResults""" 515
516 - def __init__(self, run_name, run_card, process, path):
517 """initialize the object""" 518 519 self.info = {'run_name': run_name,'me_dir':path} 520 self.tags = [run_card['run_tag']] 521 522 # Set the collider information 523 data = process.split('>',1)[0].split() 524 if len(data) == 2: 525 name1,name2 = data 526 if run_card['lpp1'] == -1: 527 name1 = ' p~' 528 elif run_card['lpp1'] == 1: 529 name1 = ' p' 530 elif run_card['lpp1'] in [2,3]: 531 name1 = ' a' 532 if run_card['lpp2'] == -1: 533 name2 = 'p~' 534 elif run_card['lpp2'] == 1: 535 name2 = ' p' 536 elif run_card['lpp2'] == [2,3]: 537 name2 = ' a' 538 self.info['collider'] = '''%s %s <br> %s x %s GeV''' % \ 539 (name1, name2, run_card['ebeam1'], run_card['ebeam2']) 540 self.info['unit'] = 'pb' 541 else: 542 self.info['collider'] = 'decay' 543 self.info['unit'] = 'GeV' 544 545 self.append(OneTagResults(run_name, run_card, path))
546 547
548 - def get_html(self, output_path, **opt):
549 """WRITE HTML OUTPUT""" 550 try: 551 self.web = opt['web'] 552 self.info['web'] = self.web 553 except Exception: 554 self.web = False 555 556 # check if more than one parton output 557 parton = [r for r in self if r.parton] 558 # clean wrong previous run link 559 if len(parton)>1: 560 for p in parton[:-1]: 561 p.parton = [] 562 563 dico = self.info 564 dico['run_span'] = sum([tag.get_nb_line() for tag in self], 1) -1 565 dico['tag_data'] = '\n'.join([tag.get_html(self) for tag in self]) 566 text = """ 567 <tr> 568 <td rowspan=%(run_span)s>%(run_name)s</td> 569 <td rowspan=%(run_span)s><center> %(collider)s </center></td> 570 %(tag_data)s 571 </tr> 572 """ % dico 573 574 if self.web: 575 576 text = text % self.info 577 578 return text
579 580
581 - def return_tag(self, name):
582 583 for data in self: 584 if data['tag'] == name: 585 return data 586 587 if name is None: 588 # return last entry 589 return self[-1] 590 591 raise Exception, '%s is not a valid tag' % name
592
593 - def recreate(self, banner):
594 """Fully recreate the information due to a hard removal of the db 595 Work for LO ONLY!""" 596 597 run_name = self.info["run_name"] 598 run_card = banner.get("run_card") 599 path = self.info["me_dir"] 600 # Recover the main information (cross-section/number of event) 601 informations = banner['mggenerationinfo'] 602 #number of events 603 nb_event = re.search(r"Number\s*of\s*Events\s*:\s*(\d*)", informations) 604 if nb_event: 605 nb_event = int(nb_event.group(1)) 606 else: 607 nb_event = 0 608 609 # cross-section 610 cross = re.search(r"Integrated\s*weight\s*\(\s*pb\s*\)\s*:\s*([\+\-\d.e]+)", informations, 611 re.I) 612 if cross: 613 cross = float(cross.group(1)) 614 else: 615 cross = 0 616 617 # search pythia file for tag: tag_1_pythia.log 618 path = pjoin(self.info['me_dir'],'Events', self.info['run_name']) 619 files = [pjoin(path, f) for f in os.listdir(path) if 620 os.path.isfile(pjoin(path,f)) and f.endswith('pythia.log')] 621 #order them by creation date. 622 files.sort(key=lambda x: os.path.getmtime(x)) 623 tags = [os.path.basename(name[:-11]) for name in files] 624 625 626 # No pythia only a single run: 627 if not tags: 628 self[0]['nb_event'] = nb_event 629 self[0]['cross'] = cross 630 631 #Loop over pythia run 632 for tag in tags: 633 if tag not in self.tags: 634 tagresult = OneTagResults(run_name, run_card, path) 635 tagresult['tag'] = tag 636 self.add(tagresult) 637 else: 638 tagresult = self.return_tag(tag) 639 tagresult['nb_event'] = nb_event 640 tagresult['cross'] = cross 641 if run_card['ickkw'] != 0: 642 #parse the file to have back the information 643 pythia_log = misc.BackRead(pjoin(path, '%s_pythia.log' % tag)) 644 pythiare = re.compile("\s*I\s+0 All included subprocesses\s+I\s+(?P<generated>\d+)\s+(?P<tried>\d+)\s+I\s+(?P<xsec>[\d\.D\-+]+)\s+I") 645 for line in pythia_log: 646 info = pythiare.search(line) 647 if not info: 648 continue 649 try: 650 # Pythia cross section in mb, we want pb 651 sigma_m = float(info.group('xsec').replace('D','E')) *1e9 652 Nacc = int(info.group('generated')) 653 except ValueError: 654 # xsec is not float - this should not happen 655 tagresult['cross_pythia'] = 0 656 tagresult['nb_event_pythia'] = 0 657 tagresult['error_pythia'] = 0 658 else: 659 tagresult['cross_pythia'] = sigma_m 660 tagresult['nb_event_pythia'] = Nacc 661 tagresult['error_pythia'] = 0 662 break 663 pythia_log.close()
664 665
666 - def is_empty(self):
667 """Check if this run contains smtg else than html information""" 668 669 if not self: 670 return True 671 if len(self) > 1: 672 return False 673 674 data = self[0] 675 if data.parton or data.pythia or data.pgs or data.delphes: 676 return False 677 else: 678 return True
679
680 - def add(self, obj):
681 """ """ 682 683 assert isinstance(obj, OneTagResults) 684 tag = obj['tag'] 685 assert tag not in self.tags 686 self.tags.append(tag) 687 self.append(obj)
688
689 - def get_last_pythia(self):
690 for i in range(1, len(self)+1): 691 if self[-i].pythia: 692 return self[-i]['tag']
693
694 - def get_current_info(self):
695 696 output = {} 697 current = self[-1] 698 # Check that cross/nb_event/error are define 699 if current.pythia and not current['nb_event'] and len(self) > 1: 700 output['nb_event'] = self[-2]['nb_event'] 701 output['cross'] = self[-2]['cross'] 702 output['error'] = self[-2]['error'] 703 elif (current.pgs or current.delphes) and not current['nb_event'] and len(self) > 1: 704 if self[-2]['cross_pythia'] and self[-2]['nb_event_pythia']: 705 output['cross'] = self[-2]['cross_pythia'] 706 output['nb_event'] = self[-2]['nb_event_pythia'] 707 output['error'] = self[-2]['error_pythia'] 708 else: 709 output['nb_event'] = self[-2]['nb_event'] 710 output['cross'] = self[-2]['cross'] 711 output['error'] = self[-2]['error'] 712 elif current['cross']: 713 return current 714 elif len(self) > 1: 715 output['nb_event'] = self[-2]['nb_event'] 716 output['cross'] = self[-2]['cross'] 717 output['error'] = self[-2]['error'] 718 else: 719 output['nb_event'] = 0 720 output['cross'] = 0 721 output['error'] = 1e-99 722 return output
723 724
725 - def remove(self, tag):
726 727 assert tag in self.tags 728 729 obj = [o for o in self if o['tag']==tag][0] 730 self.tags.remove(tag) 731 list.remove(self, obj)
732 733 734
735 -class OneTagResults(dict):
736 """ Store the results of a specific run """ 737
738 - def __init__(self, run_name, run_card, path):
739 """initialize the object""" 740 741 # define at run_result 742 self['run_name'] = run_name 743 self['tag'] = run_card['run_tag'] 744 self.event_path = pjoin(path,'Events') 745 self.me_dir = path 746 self.debug = None 747 748 # Default value 749 self['nb_event'] = 0 750 self['cross'] = 0 751 self['cross_pythia'] = '' 752 self['nb_event_pythia'] = 0 753 self['error'] = 0 754 self['run_mode'] = 'madevent' 755 self.parton = [] 756 self.reweight = [] 757 self.pythia = [] 758 self.pgs = [] 759 self.delphes = [] 760 self.shower = [] 761 # data 762 self.status = '' 763 764 # Dictionary with (Pdir,G) as keys and sum_html.RunStatistics instances 765 # as values 766 self['run_statistics'] = {}
767 768
769 - def update_status(self, level='all', nolevel=[]):
770 """update the status of the current run """ 771 772 exists = os.path.exists 773 run = self['run_name'] 774 tag =self['tag'] 775 776 path = pjoin(self.event_path, run) 777 html_path = pjoin(self.event_path, os.pardir, 'HTML', run) 778 779 # Check if the output of the last status exists 780 if level in ['gridpack','all']: 781 if 'gridpack' not in self.parton and \ 782 exists(pjoin(path,os.pardir ,os.pardir,"%s_gridpack.tar.gz" % run)): 783 self.parton.append('gridpack') 784 # Check if the output of the last status exists 785 if level in ['reweight','all']: 786 if 'plot' not in self.reweight and \ 787 exists(pjoin(html_path,"plots_%s.html" % tag)): 788 self.reweight.append('plot') 789 790 if level in ['parton','all'] and 'parton' not in nolevel: 791 792 if 'lhe' not in self.parton and \ 793 (exists(pjoin(path,"unweighted_events.lhe.gz")) or 794 exists(pjoin(path,"unweighted_events.lhe")) or 795 exists(pjoin(path,"events.lhe.gz")) or 796 exists(pjoin(path,"events.lhe"))): 797 self.parton.append('lhe') 798 799 if 'root' not in self.parton and \ 800 exists(pjoin(path,"unweighted_events.root")): 801 self.parton.append('root') 802 803 if 'plot' not in self.parton and \ 804 exists(pjoin(html_path,"plots_parton.html")): 805 self.parton.append('plot') 806 807 if 'param_card' not in self.parton and \ 808 exists(pjoin(path, "param_card.dat")): 809 self.parton.append('param_card') 810 811 if 'syst' not in self.parton and \ 812 exists(pjoin(path, "%s_parton_syscalc.log" %self['tag'])): 813 self.parton.append('syst') 814 815 for kind in ['top','HwU','pdf','ps']: 816 if glob.glob(pjoin(path,"*.%s" % kind)): 817 if self['run_mode'] in ['LO', 'NLO']: 818 self.parton.append('%s' % kind) 819 820 if level in ['shower','all'] and 'shower' not in nolevel \ 821 and self['run_mode'] != 'madevent': 822 # this is for hep/top/HwU files from amcatnlo 823 if glob.glob(pjoin(path,"*.hep")) + \ 824 glob.glob(pjoin(path,"*.hep.gz")): 825 self.shower.append('hep') 826 827 if 'plot' not in self.shower and \ 828 exists(pjoin(html_path,"plots_shower_%s.html" % tag)): 829 self.shower.append('plot') 830 831 if glob.glob(pjoin(path,"*.hepmc")) + \ 832 glob.glob(pjoin(path,"*.hepmc.gz")): 833 self.shower.append('hepmc') 834 835 for kind in ['top','HwU','pdf','ps']: 836 if glob.glob(pjoin(path,'*.' + kind)): 837 if self['run_mode'] in ['LO', 'NLO']: 838 self.parton.append('%s' % kind) 839 else: 840 self.shower.append('%s' % kind) 841 842 843 if level in ['pythia', 'all']: 844 845 if 'plot' not in self.pythia and \ 846 exists(pjoin(html_path,"plots_pythia_%s.html" % tag)): 847 self.pythia.append('plot') 848 849 if 'lhe' not in self.pythia and \ 850 (exists(pjoin(path,"%s_pythia_events.lhe.gz" % tag)) or 851 exists(pjoin(path,"%s_pythia_events.lhe" % tag))): 852 self.pythia.append('lhe') 853 854 855 if 'hep' not in self.pythia and \ 856 (exists(pjoin(path,"%s_pythia_events.hep.gz" % tag)) or 857 exists(pjoin(path,"%s_pythia_events.hep" % tag))): 858 self.pythia.append('hep') 859 860 if 'rwt' not in self.pythia and \ 861 (exists(pjoin(path,"%s_syscalc.dat.gz" % tag)) or 862 exists(pjoin(path,"%s_syscalc.dat" % tag))): 863 self.pythia.append('rwt') 864 865 if 'root' not in self.pythia and \ 866 exists(pjoin(path,"%s_pythia_events.root" % tag)): 867 self.pythia.append('root') 868 869 if 'lheroot' not in self.pythia and \ 870 exists(pjoin(path,"%s_pythia_lhe_events.root" % tag)): 871 self.pythia.append('lheroot') 872 873 if 'log' not in self.pythia and \ 874 exists(pjoin(path,"%s_pythia.log" % tag)): 875 self.pythia.append('log') 876 877 if level in ['pgs', 'all']: 878 879 if 'plot' not in self.pgs and \ 880 exists(pjoin(html_path,"plots_pgs_%s.html" % tag)): 881 self.pgs.append('plot') 882 883 if 'lhco' not in self.pgs and \ 884 (exists(pjoin(path,"%s_pgs_events.lhco.gz" % tag)) or 885 exists(pjoin(path,"%s_pgs_events.lhco." % tag))): 886 self.pgs.append('lhco') 887 888 if 'root' not in self.pgs and \ 889 exists(pjoin(path,"%s_pgs_events.root" % tag)): 890 self.pgs.append('root') 891 892 if 'log' not in self.pgs and \ 893 exists(pjoin(path,"%s_pgs.log" % tag)): 894 self.pgs.append('log') 895 896 if level in ['delphes', 'all']: 897 898 if 'plot' not in self.delphes and \ 899 exists(pjoin(html_path,"plots_delphes_%s.html" % tag)): 900 self.delphes.append('plot') 901 902 if 'lhco' not in self.delphes and \ 903 (exists(pjoin(path,"%s_delphes_events.lhco.gz" % tag)) or 904 exists(pjoin(path,"%s_delphes_events.lhco" % tag))): 905 self.delphes.append('lhco') 906 907 if 'root' not in self.delphes and \ 908 exists(pjoin(path,"%s_delphes_events.root" % tag)): 909 self.delphes.append('root') 910 911 if 'log' not in self.delphes and \ 912 exists(pjoin(path,"%s_delphes.log" % tag)): 913 self.delphes.append('log')
914 921 926 1048 1049
1050 - def get_nb_line(self):
1051 1052 nb_line = 0 1053 for i in [self.parton, self.reweight, self.pythia, self.pgs, self.delphes, self.shower]: 1054 if len(i): 1055 nb_line += 1 1056 return max([nb_line,1])
1057 1058
1059 - def get_html(self, runresults):
1060 """create the html output linked to the this tag 1061 RunResults is given in case of cross-section need to be taken 1062 from a previous run 1063 """ 1064 1065 1066 tag_template = """ 1067 <td rowspan=%(tag_span)s> <a href="./Events/%(run)s/%(run)s_%(tag)s_banner.txt">%(tag)s</a>%(debug)s</td> 1068 %(subruns)s""" 1069 1070 # Compute the text for eachsubpart 1071 1072 sub_part_template_parton = """ 1073 <td rowspan=%(cross_span)s><center><a href="./HTML/%(run)s/results.html"> %(cross).4g <font face=symbol>&#177;</font> %(err).2g</a> %(syst)s </center></td> 1074 <td rowspan=%(cross_span)s><center> %(nb_event)s<center></td><td> %(type)s </td> 1075 <td> %(links)s</td> 1076 <td> %(action)s</td> 1077 </tr>""" 1078 1079 sub_part_template_reweight = """ 1080 <td rowspan=%(cross_span)s><center> %(cross).4g </center></td> 1081 <td rowspan=%(cross_span)s><center> %(nb_event)s<center></td><td> %(type)s </td> 1082 <td> %(links)s</td> 1083 <td> %(action)s</td> 1084 </tr>""" 1085 1086 sub_part_template_pgs = """ 1087 <td> %(type)s </td> 1088 <td> %(links)s</td> 1089 <td> %(action)s</td> 1090 </tr>""" 1091 1092 sub_part_template_shower = """ 1093 <td> %(type)s %(run_mode)s </td> 1094 <td> %(links)s</td> 1095 <td> %(action)s</td> 1096 </tr>""" 1097 1098 # Compute the HTMl output for subpart 1099 nb_line = self.get_nb_line() 1100 # Check that cross/nb_event/error are define 1101 if self.pythia and not self['nb_event']: 1102 try: 1103 self['nb_event'] = runresults[-2]['nb_event'] 1104 self['cross'] = runresults[-2]['cross'] 1105 self['error'] = runresults[-2]['error'] 1106 except Exception: 1107 pass 1108 1109 elif (self.pgs or self.delphes) and not self['nb_event'] and \ 1110 len(runresults) > 1: 1111 if runresults[-2]['cross_pythia'] and runresults[-2]['cross']: 1112 self['cross'] = runresults[-2]['cross_pythia'] 1113 self['error'] = runresults[-2]['error_pythia'] 1114 self['nb_event'] = runresults[-2]['nb_event_pythia'] 1115 else: 1116 self['nb_event'] = runresults[-2]['nb_event'] 1117 self['cross'] = runresults[-2]['cross'] 1118 self['error'] = runresults[-2]['error'] 1119 1120 1121 first = None 1122 subresults_html = '' 1123 for ttype in ['parton', 'pythia', 'pgs', 'delphes','reweight','shower']: 1124 data = getattr(self, ttype) 1125 if not data: 1126 continue 1127 1128 local_dico = {'type': ttype, 'run': self['run_name'], 'syst': ''} 1129 if 'run_mode' in self.keys(): 1130 local_dico['run_mode'] = self['run_mode'] 1131 else: 1132 local_dico['run_mode'] = "" 1133 if not first: 1134 if ttype == 'reweight': 1135 template = sub_part_template_reweight 1136 else: 1137 template = sub_part_template_parton 1138 first = ttype 1139 if ttype=='parton' and self['cross_pythia']: 1140 local_dico['cross_span'] = 1 1141 local_dico['cross'] = self['cross'] 1142 local_dico['err'] = self['error'] 1143 local_dico['nb_event'] = self['nb_event'] 1144 if 'syst' in self.parton: 1145 local_dico['syst'] = '<font face=symbol>&#177;</font> <a href="./Events/%(run_name)s/%(tag)s_parton_syscalc.log">systematics</a>' \ 1146 % {'run_name':self['run_name'], 'tag': self['tag']} 1147 elif self['cross_pythia']: 1148 if self.parton: 1149 local_dico['cross_span'] = nb_line -1 1150 else: 1151 local_dico['cross_span'] = nb_line 1152 if self['nb_event_pythia']: 1153 local_dico['nb_event'] = self['nb_event_pythia'] 1154 else: 1155 local_dico['nb_event'] = 0 1156 local_dico['cross'] = self['cross_pythia'] 1157 local_dico['err'] = self['error_pythia'] 1158 if 'rwt' in self.pythia: 1159 local_dico['syst'] = '<font face=symbol>&#177;</font> <a href="./Events/%(run_name)s/%(tag)s_Pythia_syscalc.log">systematics</a>' \ 1160 % {'run_name':self['run_name'], 'tag': self['tag']} 1161 else: 1162 local_dico['type'] += ' %s' % self['run_mode'] 1163 local_dico['cross_span'] = nb_line 1164 local_dico['cross'] = self['cross'] 1165 local_dico['err'] = self['error'] 1166 local_dico['nb_event'] = self['nb_event'] 1167 if 'syst' in self.parton: 1168 local_dico['syst'] = '<font face=symbol>&#177;</font> <a href="./Events/%(run_name)s/%(tag)s_parton_syscalc.log">systematics</a>' \ 1169 % {'run_name':self['run_name'], 'tag': self['tag']} 1170 1171 elif ttype == 'pythia' and self['cross_pythia']: 1172 template = sub_part_template_parton 1173 if self.parton: 1174 local_dico['cross_span'] = nb_line - 1 1175 if self['nb_event_pythia']: 1176 local_dico['nb_event'] = self['nb_event_pythia'] 1177 else: 1178 local_dico['nb_event'] = 0 1179 else: 1180 local_dico['cross_span'] = nb_line 1181 local_dico['nb_event'] = self['nb_event'] 1182 if 'rwt' in self.pythia: 1183 local_dico['syst'] = '<font face=symbol>&#177;</font> <a href="./Events/%(run_name)s/%(tag)s_Pythia_syscalc.log">systematics</a>' \ 1184 % {'run_name':self['run_name'], 'tag': self['tag']} 1185 local_dico['cross'] = self['cross_pythia'] 1186 local_dico['err'] = self['error_pythia'] 1187 1188 elif ttype == 'shower': 1189 template = sub_part_template_shower 1190 if self.parton: 1191 local_dico['cross_span'] = nb_line - 1 1192 else: 1193 local_dico['cross_span'] = nb_line 1194 else: 1195 template = sub_part_template_pgs 1196 1197 # Fill the links 1198 local_dico['links'] = self.get_links(ttype) 1199 1200 # Fill the actions 1201 if ttype == 'parton': 1202 if runresults.web: 1203 local_dico['action'] = """ 1204 <FORM ACTION="http://%(web)s/cgi-bin/RunProcess/handle_runs-pl" ENCTYPE="multipart/form-data" METHOD="POST"> 1205 <INPUT TYPE=HIDDEN NAME=directory VALUE="%(me_dir)s"> 1206 <INPUT TYPE=HIDDEN NAME=whattodo VALUE="remove_level"> 1207 <INPUT TYPE=HIDDEN NAME=level VALUE="all"> 1208 <INPUT TYPE=HIDDEN NAME=tag VALUE=\"""" + self['tag'] + """\"> 1209 <INPUT TYPE=HIDDEN NAME=run VALUE="%(run_name)s"> 1210 <INPUT TYPE=SUBMIT VALUE="Remove run"> 1211 </FORM> 1212 1213 <FORM ACTION="http://%(web)s/cgi-bin/RunProcess/handle_runs-pl" ENCTYPE="multipart/form-data" METHOD="POST"> 1214 <INPUT TYPE=HIDDEN NAME=directory VALUE="%(me_dir)s"> 1215 <INPUT TYPE=HIDDEN NAME=whattodo VALUE="pythia"> 1216 <INPUT TYPE=HIDDEN NAME=run VALUE="%(run_name)s"> 1217 <INPUT TYPE=SUBMIT VALUE="Run Pythia"> 1218 </FORM>""" 1219 else: 1220 local_dico['action'] = self.command_suggestion_html('remove %s parton --tag=%s' \ 1221 % (self['run_name'], self['tag'])) 1222 # this the detector simulation and pythia should be available only for madevent 1223 if self['run_mode'] == 'madevent': 1224 local_dico['action'] += self.command_suggestion_html('pythia %s ' % self['run_name']) 1225 else: 1226 pass 1227 1228 elif ttype == 'shower': 1229 if runresults.web: 1230 local_dico['action'] = """ 1231 <FORM ACTION="http://%(web)s/cgi-bin/RunProcess/handle_runs-pl" ENCTYPE="multipart/form-data" METHOD="POST"> 1232 <INPUT TYPE=HIDDEN NAME=directory VALUE="%(me_dir)s"> 1233 <INPUT TYPE=HIDDEN NAME=whattodo VALUE="remove_level"> 1234 <INPUT TYPE=HIDDEN NAME=level VALUE="all"> 1235 <INPUT TYPE=HIDDEN NAME=tag VALUE=\"""" + self['tag'] + """\"> 1236 <INPUT TYPE=HIDDEN NAME=run VALUE="%(run_name)s"> 1237 <INPUT TYPE=SUBMIT VALUE="Remove run"> 1238 </FORM> 1239 1240 <FORM ACTION="http://%(web)s/cgi-bin/RunProcess/handle_runs-pl" ENCTYPE="multipart/form-data" METHOD="POST"> 1241 <INPUT TYPE=HIDDEN NAME=directory VALUE="%(me_dir)s"> 1242 <INPUT TYPE=HIDDEN NAME=whattodo VALUE="pythia"> 1243 <INPUT TYPE=HIDDEN NAME=run VALUE="%(run_name)s"> 1244 <INPUT TYPE=SUBMIT VALUE="Run Pythia"> 1245 </FORM>""" 1246 else: 1247 local_dico['action'] = self.command_suggestion_html('remove %s parton --tag=%s' \ 1248 % (self['run_name'], self['tag'])) 1249 # this the detector simulation and pythia should be available only for madevent 1250 if self['run_mode'] == 'madevent': 1251 local_dico['action'] += self.command_suggestion_html('pythia %s ' % self['run_name']) 1252 else: 1253 pass 1254 1255 elif ttype == 'pythia': 1256 if self['tag'] == runresults.get_last_pythia(): 1257 if runresults.web: 1258 local_dico['action'] = """ 1259 <FORM ACTION="http://%(web)s/cgi-bin/RunProcess/handle_runs-pl" ENCTYPE="multipart/form-data" METHOD="POST"> 1260 <INPUT TYPE=HIDDEN NAME=directory VALUE="%(me_dir)s"> 1261 <INPUT TYPE=HIDDEN NAME=whattodo VALUE="remove_level"> 1262 <INPUT TYPE=HIDDEN NAME=level VALUE="pythia"> 1263 <INPUT TYPE=HIDDEN NAME=run VALUE="%(run_name)s"> 1264 <INPUT TYPE=HIDDEN NAME=tag VALUE=\"""" + self['tag'] + """\"> 1265 <INPUT TYPE=SUBMIT VALUE="Remove pythia"> 1266 </FORM> 1267 1268 <FORM ACTION="http://%(web)s/cgi-bin/RunProcess/handle_runs-pl" ENCTYPE="multipart/form-data" METHOD="POST"> 1269 <INPUT TYPE=HIDDEN NAME=directory VALUE="%(me_dir)s"> 1270 <INPUT TYPE=HIDDEN NAME=whattodo VALUE="pgs"> 1271 <INPUT TYPE=HIDDEN NAME=run VALUE="%(run_name)s"> 1272 <INPUT TYPE=SUBMIT VALUE="Run Detector"> 1273 </FORM>""" 1274 else: 1275 local_dico['action'] = self.command_suggestion_html( 1276 'remove %s pythia --tag=%s' % \ 1277 (self['run_name'], self['tag'])) 1278 local_dico['action'] += self.command_suggestion_html( 1279 'pgs %(1)s or delphes %(1)s' % {'1': self['run_name']}) 1280 else: 1281 if runresults.web: 1282 local_dico['action'] = '' 1283 else: 1284 local_dico['action'] = self.command_suggestion_html('remove %s pythia --tag=%s'\ 1285 % (self['run_name'], self['tag'])) 1286 else: 1287 if runresults.web: 1288 local_dico['action'] = """ 1289 <FORM ACTION="http://%(web)s/cgi-bin/RunProcess/handle_runs-pl" ENCTYPE="multipart/form-data" METHOD="POST"> 1290 <INPUT TYPE=HIDDEN NAME=directory VALUE="%(me_dir)s"> 1291 <INPUT TYPE=HIDDEN NAME=whattodo VALUE="remove_level"> 1292 <INPUT TYPE=HIDDEN NAME=level VALUE=\"""" + str(type) + """\"> 1293 <INPUT TYPE=HIDDEN NAME=tag VALUE=\"""" + self['tag'] + """\"> 1294 <INPUT TYPE=HIDDEN NAME=run VALUE="%(run_name)s"> 1295 <INPUT TYPE=SUBMIT VALUE="Remove """ + str(ttype) + """\"> 1296 </FORM>""" 1297 else: 1298 local_dico['action'] = self.command_suggestion_html('remove %s %s --tag=%s' %\ 1299 (self['run_name'], ttype, self['tag'])) 1300 1301 # create the text 1302 subresults_html += template % local_dico 1303 1304 1305 if subresults_html == '': 1306 if runresults.web: 1307 action = """ 1308 <FORM ACTION="http://%(web)s/cgi-bin/RunProcess/handle_runs-pl" ENCTYPE="multipart/form-data" METHOD="POST"> 1309 <INPUT TYPE=HIDDEN NAME=directory VALUE="%(me_dir)s"> 1310 <INPUT TYPE=HIDDEN NAME=whattodo VALUE="remove_level"> 1311 <INPUT TYPE=HIDDEN NAME=level VALUE="banner"> 1312 <INPUT TYPE=HIDDEN NAME=tag VALUE=\"""" + self['tag'] + """\"> 1313 <INPUT TYPE=HIDDEN NAME=run VALUE="%(run_name)s"> 1314 <INPUT TYPE=SUBMIT VALUE="Remove Banner"> 1315 </FORM> 1316 1317 <FORM ACTION="http://%(web)s/cgi-bin/RunProcess/handle_runs-pl" ENCTYPE="multipart/form-data" METHOD="POST"> 1318 <INPUT TYPE=HIDDEN NAME=directory VALUE="%(me_dir)s"> 1319 <INPUT TYPE=HIDDEN NAME=whattodo VALUE="banner"> 1320 <INPUT TYPE=HIDDEN NAME=run VALUE="%(run_name)s"> 1321 <INPUT TYPE=SUBMIT VALUE="Run the banner"> 1322 </FORM>""" 1323 else: 1324 action = self.command_suggestion_html('remove %s banner --tag=%s' \ 1325 % (self['run_name'], self['tag'])) 1326 action += self.command_suggestion_html('banner_run %s ' % self['run_name']) 1327 1328 1329 1330 subresults_html = sub_part_template_parton % \ 1331 {'type': '', 1332 'run': self['run_name'], 1333 'cross_span': 1, 1334 'cross': self['cross'], 1335 'err': self['error'], 1336 'nb_event': self['nb_event'] and self['nb_event'] or 'No events yet', 1337 'links': 'banner only', 1338 'action': action, 1339 'run_mode': '', 1340 'syst':'' 1341 } 1342 1343 if self.debug is KeyboardInterrupt: 1344 debug = '<br><font color=red>Interrupted</font>' 1345 elif isinstance(self.debug, basestring): 1346 if not os.path.isabs(self.debug) and not self.debug.startswith('./'): 1347 self.debug = './' + self.debug 1348 elif os.path.isabs(self.debug): 1349 self.debug = os.path.relpath(self.debug, self.me_dir) 1350 debug = '<br> <a href=\'%s\'> <font color=red>ERROR</font></a>' \ 1351 % (self.debug) 1352 elif self.debug: 1353 text = str(self.debug).replace('. ','.<br>') 1354 if 'http' in text: 1355 pat = re.compile('(http[\S]*)') 1356 text = pat.sub(r'<a href=\1> here </a>', text) 1357 debug = '<br><font color=red>%s<BR>%s</font>' % \ 1358 (self.debug.__class__.__name__, text) 1359 else: 1360 debug = '' 1361 text = tag_template % {'tag_span': nb_line, 1362 'run': self['run_name'], 'tag': self['tag'], 1363 'subruns' : subresults_html, 1364 'debug':debug} 1365 1366 return text
1367 1368
1369 - def command_suggestion_html(self, command):
1370 """return html button with code suggestion""" 1371 1372 if command.startswith('pythia'): 1373 button = 'launch pythia' 1374 if command.startswith('shower'): 1375 button = 'shower events' 1376 elif command.startswith('remove banner'): 1377 button = 'remove banner' 1378 elif command.startswith('remove'): 1379 button = 'remove run' 1380 elif command.startswith('banner_run'): 1381 button = 're-run from the banner' 1382 else: 1383 button = 'launch detector simulation' 1384 if self['run_mode'] == 'madevent': 1385 header = 'Launch ./bin/madevent in a shell, and run the following command: ' 1386 else: 1387 header = 'Launch ./bin/aMCatNLO in a shell, and run the following command: ' 1388 1389 return "<INPUT TYPE=SUBMIT VALUE='%s' onClick=\"alert('%s')\">" % (button, header + command) 1390 1391 1392 return + '<br>'
1393