1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """A user friendly command line interface to access MadGraph5_aMC@NLO features.
16 Uses the cmd package for command interpretation and tab completion.
17 """
18 from __future__ import division
19
20
21
22 import ast
23 import logging
24 import math
25 import os
26 import re
27 import shutil
28 import signal
29 import stat
30 import subprocess
31 import sys
32 import time
33 import traceback
34 import urllib
35 import glob
36 import StringIO
37
38 try:
39 import readline
40 GNU_SPLITTING = ('GNU' in readline.__doc__)
41 except:
42 GNU_SPLITTING = True
43
44 root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
45 root_path = os.path.split(root_path)[0]
46 sys.path.insert(0, os.path.join(root_path,'bin'))
47
48
49 pjoin = os.path.join
50
51 logger = logging.getLogger('madgraph.stdout')
52 logger_stderr = logging.getLogger('madgraph.stderr')
53
54 try:
55 import madgraph
56 except ImportError:
57
58 import internal.extended_cmd as cmd
59 import internal.banner as banner_mod
60 import internal.shower_card as shower_card_mod
61 import internal.misc as misc
62 import internal.cluster as cluster
63 import internal.check_param_card as param_card_mod
64 import internal.files as files
65
66 import internal.save_load_object as save_load_object
67 import internal.gen_crossxhtml as gen_crossxhtml
68 import internal.lhe_parser as lhe_parser
69 import internal.FO_analyse_card as FO_analyse_card
70 import internal.sum_html as sum_html
71 from internal import InvalidCmd, MadGraph5Error
72
73 MADEVENT=True
74 else:
75
76 import madgraph.interface.extended_cmd as cmd
77 import madgraph.various.banner as banner_mod
78 import madgraph.various.shower_card as shower_card_mod
79 import madgraph.various.misc as misc
80 import madgraph.iolibs.files as files
81 import madgraph.various.cluster as cluster
82 import madgraph.various.lhe_parser as lhe_parser
83 import madgraph.various.FO_analyse_card as FO_analyse_card
84 import madgraph.iolibs.save_load_object as save_load_object
85 import madgraph.madevent.gen_crossxhtml as gen_crossxhtml
86 import models.check_param_card as param_card_mod
87 import madgraph.madevent.sum_html as sum_html
88
89
90 from madgraph import InvalidCmd, MadGraph5Error, MG5DIR
91 MADEVENT=False
97 """ The Series of help routins in common between amcatnlo_run and
98 madevent interface"""
99
101 logger.info("syntax: treatcards [param|run] [--output_dir=] [--param_card=] [--run_card=]")
102 logger.info("-- create the .inc files containing the cards information." )
103
105 logger.info("syntax: set %s argument" % "|".join(self._set_options))
106 logger.info("-- set options")
107 logger.info(" stdout_level DEBUG|INFO|WARNING|ERROR|CRITICAL")
108 logger.info(" change the default level for printed information")
109 logger.info(" timeout VALUE")
110 logger.info(" (default 20) Seconds allowed to answer questions.")
111 logger.info(" Note that pressing tab always stops the timer.")
112 logger.info(" cluster_temp_path PATH")
113 logger.info(" (default None) Allow to perform the run in PATH directory")
114 logger.info(" This allow to not run on the central disk. This is not used")
115 logger.info(" by condor cluster (since condor has it's own way to prevent it).")
116
118 logger.info("syntax: plot [RUN] [%s] [-f]" % '|'.join(self._plot_mode))
119 logger.info("-- create the plot for the RUN (current run by default)")
120 logger.info(" at the different stage of the event generation")
121 logger.info(" Note than more than one mode can be specified in the same command.")
122 logger.info(" This requires to have MadAnalysis and td installed.")
123 logger.info(" -f options: answer all question by default.")
124
126 logger.info("syntax: compute_widths Particle [Particles] [OPTIONS]")
127 logger.info("-- Compute the widths for the particles specified.")
128 logger.info(" By default, this takes the current param_card and overwrites it.")
129 logger.info(" Precision allows to define when to include three/four/... body decays (LO).")
130 logger.info(" If this number is an integer then all N-body decay will be included.")
131 logger.info(" Various options:\n")
132 logger.info(" --body_decay=X: Parameter to control the precision of the computation")
133 logger.info(" if X is an integer, we compute all channels up to X-body decay.")
134 logger.info(" if X <1, then we stop when the estimated error is lower than X.")
135 logger.info(" if X >1 BUT not an integer, then we X = N + M, with M <1 and N an integer")
136 logger.info(" We then either stop at the N-body decay or when the estimated error is lower than M.")
137 logger.info(" default: 4.0025")
138 logger.info(" --min_br=X: All channel which are estimated below this value will not be integrated numerically.")
139 logger.info(" default: precision (decimal part of the body_decay options) divided by four")
140 logger.info(" --precision_channel=X: requested numerical precision for each channel")
141 logger.info(" default: 0.01")
142 logger.info(" --path=X: path for param_card")
143 logger.info(" default: take value from the model")
144 logger.info(" --output=X: path where to write the resulting card. ")
145 logger.info(" default: overwrite input file. If no input file, write it in the model directory")
146 logger.info(" --nlo: Compute NLO width [if the model support it]")
147
149 logger.info("syntax: shower [shower_name] [shower_options]")
150 logger.info("-- This is equivalent to running '[shower_name] [shower_options]'")
151
153 logger.info("syntax: pgs [RUN] [--run_options]")
154 logger.info("-- run pgs on RUN (current one by default)")
155 self.run_options_help([('-f','answer all question by default'),
156 ('--tag=', 'define the tag for the pgs run'),
157 ('--no_default', 'not run if pgs_card not present')])
158
160 logger.info("syntax: delphes [RUN] [--run_options]")
161 logger.info("-- run delphes on RUN (current one by default)")
162 self.run_options_help([('-f','answer all question by default'),
163 ('--tag=', 'define the tag for the delphes run'),
164 ('--no_default', 'not run if delphes_card not present')])
165
167 if not skip_syntax:
168 logger.info("syntax: decay_events [RUN]")
169 logger.info("This functionality allows for the decay of resonances")
170 logger.info("in a .lhe file, keeping track of the spin correlation effets.")
171 logger.info("BE AWARE OF THE CURRENT LIMITATIONS:")
172 logger.info(" (1) Only a succession of 2 body decay are currently allowed")
173
177 """ The Series of check routines in common between amcatnlo_run and
178 madevent interface"""
179
181 """ check the validity of the line"""
182
183
184 if len(args) < 2:
185 if len(args)==1 and "=" in args[0]:
186 args[:] = args[0].split("=",1)
187 else:
188 self.help_set()
189 raise self.InvalidCmd('set needs an option and an argument')
190
191 if args[0] not in self._set_options + self.options.keys():
192 self.help_set()
193 raise self.InvalidCmd('Possible options for set are %s' % \
194 (self._set_options+self.options.keys()))
195
196 if args[0] in ['stdout_level']:
197 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL'] \
198 and not args[1].isdigit():
199 raise self.InvalidCmd('output_level needs ' + \
200 'a valid level')
201
202 if args[0] in ['timeout']:
203 if not args[1].isdigit():
204 raise self.InvalidCmd('timeout values should be a integer')
205
207 """check that the model is loadable and check that the format is of the
208 type: PART PATH --output=PATH -f --precision=N
209 return the model.
210 """
211
212
213 if MADEVENT and not self.options['mg5_path']:
214 raise self.InvalidCmd, '''The automatic computations of widths requires that MG5 is installed on the system.
215 You can install it and set his path in ./Cards/me5_configuration.txt'''
216 elif MADEVENT:
217 sys.path.append(self.options['mg5_path'])
218 try:
219 import models.model_reader as model_reader
220 import models.import_ufo as import_ufo
221 except ImportError:
222 raise self.ConfigurationError, '''Can\'t load MG5.
223 The variable mg5_path should not be correctly configure.'''
224
225
226 ufo_path = pjoin(self.me_dir,'bin','internal', 'ufomodel')
227
228 if not MADEVENT:
229 modelname = self.find_model_name()
230
231
232
233
234 force_CMS = self.mother and self.mother.options['complex_mass_scheme']
235 model = import_ufo.import_model(modelname, decay=True,
236 restrict=True, complex_mass_scheme=force_CMS)
237 else:
238 force_CMS = self.proc_characteristics['complex_mass_scheme']
239 model = import_ufo.import_model(pjoin(self.me_dir,'bin','internal',
240 'ufomodel'), decay=True, complex_mass_scheme=force_CMS)
241
242
243
244
245
246 if '-modelname' not in open(pjoin(self.me_dir,'Cards','proc_card_mg5.dat')).read():
247 model.pass_particles_name_in_mg_default()
248 model = model_reader.ModelReader(model)
249 particles_name = dict([(p.get('name'), p.get('pdg_code'))
250 for p in model.get('particles')])
251 particles_name.update(dict([(p.get('antiname'), p.get('pdg_code'))
252 for p in model.get('particles')]))
253
254 output = {'model': model, 'force': False, 'output': None,
255 'path':None, 'particles': set(), 'body_decay':4.0025,
256 'min_br':None, 'precision_channel':0.01}
257 for arg in args:
258 if arg.startswith('--output='):
259 output_path = arg.split('=',1)[1]
260 if not os.path.exists(output_path):
261 raise self.InvalidCmd, 'Invalid Path for the output. Please retry.'
262 if not os.path.isfile(output_path):
263 output_path = pjoin(output_path, 'param_card.dat')
264 output['output'] = output_path
265 elif arg == '-f':
266 output['force'] = True
267 elif os.path.isfile(arg):
268 ftype = self.detect_card_type(arg)
269 if ftype != 'param_card.dat':
270 raise self.InvalidCmd , '%s is not a valid param_card.' % arg
271 output['path'] = arg
272 elif arg.startswith('--path='):
273 arg = arg.split('=',1)[1]
274 ftype = self.detect_card_type(arg)
275 if ftype != 'param_card.dat':
276 raise self.InvalidCmd , '%s is not a valid param_card.' % arg
277 output['path'] = arg
278 elif arg.startswith('--'):
279 if "=" in arg:
280 name, value = arg.split('=',1)
281 try:
282 value = float(value)
283 except Exception:
284 raise self.InvalidCmd, '--%s requires integer or a float' % name
285 output[name[2:]] = float(value)
286 elif arg == "--nlo":
287 output["nlo"] = True
288 elif arg in particles_name:
289
290 output['particles'].add(particles_name[arg])
291 elif arg.isdigit() and int(arg) in particles_name.values():
292 output['particles'].add(ast.literal_eval(arg))
293 elif arg == 'all':
294 output['particles'] = set(['all'])
295 else:
296 self.help_compute_widths()
297 raise self.InvalidCmd, '%s is not a valid argument for compute_widths' % arg
298 if self.force:
299 output['force'] = True
300
301 if not output['particles']:
302 raise self.InvalidCmd, '''This routines requires at least one particle in order to compute
303 the related width'''
304
305 if output['output'] is None:
306 output['output'] = output['path']
307
308 return output
309
311 """Check the argument for pythia command
312 syntax: delphes [NAME]
313 Note that other option are already remove at this point
314 """
315
316
317 if not self.options['delphes_path']:
318 logger.info('Retry to read configuration file to find delphes path')
319 self.set_configuration()
320
321 if not self.options['delphes_path']:
322 error_msg = 'No valid Delphes path set.\n'
323 error_msg += 'Please use the set command to define the path and retry.\n'
324 error_msg += 'You can also define it in the configuration file.\n'
325 raise self.InvalidCmd(error_msg)
326
327 tag = [a for a in arg if a.startswith('--tag=')]
328 if tag:
329 arg.remove(tag[0])
330 tag = tag[0][6:]
331
332
333 if len(arg) == 0 and not self.run_name:
334 if self.results.lastrun:
335 arg.insert(0, self.results.lastrun)
336 else:
337 raise self.InvalidCmd('No run name currently define. Please add this information.')
338
339 if len(arg) == 1 and self.run_name == arg[0]:
340 arg.pop(0)
341
342 filepath = None
343 if not len(arg):
344 prev_tag = self.set_run_name(self.run_name, tag, 'delphes')
345 paths = [pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia_events.hep.gz'),
346 pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia8_events.hepmc.gz'),
347 pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia_events.hep'),
348 pjoin(self.me_dir,'Events',self.run_name, '%(tag)s_pythia8_events.hepmc'),
349 pjoin(self.me_dir,'Events','pythia_events.hep'),
350 pjoin(self.me_dir,'Events','pythia_events.hepmc'),
351 pjoin(self.me_dir,'Events','pythia8_events.hep.gz'),
352 pjoin(self.me_dir,'Events','pythia8_events.hepmc.gz')
353 ]
354 for p in paths:
355 if os.path.exists(p % {'tag': prev_tag}):
356 filepath = p % {'tag': prev_tag}
357 break
358 else:
359 a = raw_input("NO INPUT")
360 if nodefault:
361 return False
362 else:
363 self.help_pgs()
364 raise self.InvalidCmd('''No file file pythia_events.* currently available
365 Please specify a valid run_name''')
366
367 if len(arg) == 1:
368 prev_tag = self.set_run_name(arg[0], tag, 'delphes')
369 if os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)):
370 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)
371 elif os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc.gz' % prev_tag)):
372 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc.gz' % prev_tag)
373 elif os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep' % prev_tag)):
374 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)
375 elif os.path.exists(pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc' % prev_tag)):
376 filepath = pjoin(self.me_dir,'Events',self.run_name, '%s_pythia8_events.hepmc.gz' % prev_tag)
377 else:
378 raise self.InvalidCmd('No events file corresponding to %s run with tag %s.:%s '\
379 % (self.run_name, prev_tag,
380 pjoin(self.me_dir,'Events',self.run_name, '%s_pythia_events.hep.gz' % prev_tag)))
381 else:
382 if tag:
383 self.run_card['run_tag'] = tag
384 self.set_run_name(self.run_name, tag, 'delphes')
385
386 return filepath
387
388
389
390
391
392
393
395 """ check the validity of the line """
396
397 if len(args) != 1:
398 self.help_open()
399 raise self.InvalidCmd('OPEN command requires exactly one argument')
400
401 if args[0].startswith('./'):
402 if not os.path.isfile(args[0]):
403 raise self.InvalidCmd('%s: not such file' % args[0])
404 return True
405
406
407 if not self.me_dir:
408 if not os.path.isfile(args[0]):
409 self.help_open()
410 raise self.InvalidCmd('No MadEvent path defined. Unable to associate this name to a file')
411 else:
412 return True
413
414 path = self.me_dir
415 if os.path.isfile(os.path.join(path,args[0])):
416 args[0] = os.path.join(path,args[0])
417 elif os.path.isfile(os.path.join(path,'Cards',args[0])):
418 args[0] = os.path.join(path,'Cards',args[0])
419 elif os.path.isfile(os.path.join(path,'HTML',args[0])):
420 args[0] = os.path.join(path,'HTML',args[0])
421
422 elif '_card.dat' in args[0]:
423 name = args[0].replace('_card.dat','_card_default.dat')
424 if os.path.isfile(os.path.join(path,'Cards', name)):
425 files.cp(os.path.join(path,'Cards', name), os.path.join(path,'Cards', args[0]))
426 args[0] = os.path.join(path,'Cards', args[0])
427 else:
428 raise self.InvalidCmd('No default path for this file')
429 elif not os.path.isfile(args[0]):
430 raise self.InvalidCmd('No default path for this file')
431
433 """check that treatcards arguments are valid
434 [param|run|all] [--output_dir=] [--param_card=] [--run_card=]
435 """
436
437 opt = {'output_dir':pjoin(self.me_dir,'Source'),
438 'param_card':pjoin(self.me_dir,'Cards','param_card.dat'),
439 'run_card':pjoin(self.me_dir,'Cards','run_card.dat')}
440 mode = 'all'
441 for arg in args:
442 if arg.startswith('--') and '=' in arg:
443 key,value =arg[2:].split('=',1)
444 if not key in opt:
445 self.help_treatcards()
446 raise self.InvalidCmd('Invalid option for treatcards command:%s ' \
447 % key)
448 if key in ['param_card', 'run_card']:
449 if os.path.isfile(value):
450 card_name = self.detect_card_type(value)
451 if card_name != key:
452 raise self.InvalidCmd('Format for input file detected as %s while expecting %s'
453 % (card_name, key))
454 opt[key] = value
455 elif os.path.isfile(pjoin(self.me_dir,value)):
456 card_name = self.detect_card_type(pjoin(self.me_dir,value))
457 if card_name != key:
458 raise self.InvalidCmd('Format for input file detected as %s while expecting %s'
459 % (card_name, key))
460 opt[key] = value
461 else:
462 raise self.InvalidCmd('No such file: %s ' % value)
463 elif key in ['output_dir']:
464 if os.path.isdir(value):
465 opt[key] = value
466 elif os.path.isdir(pjoin(self.me_dir,value)):
467 opt[key] = pjoin(self.me_dir, value)
468 else:
469 raise self.InvalidCmd('No such directory: %s' % value)
470 elif arg in ['MadLoop','param','run','all']:
471 mode = arg
472 else:
473 self.help_treatcards()
474 raise self.InvalidCmd('Unvalid argument %s' % arg)
475
476 return mode, opt
477
479 """Check the argument for decay_events command
480 syntax is "decay_events [NAME]"
481 Note that other option are already remove at this point
482 """
483
484 opts = []
485 if '-from_cards' in args:
486 args.remove('-from_cards')
487 opts.append('-from_cards')
488
489 if any(t.startswith('--plugin=') for t in args):
490 plugin = [t for t in args if t.startswith('--plugin')][0]
491 args.remove(plugin)
492 opts.append(plugin)
493
494
495 if len(args) == 0:
496 if self.run_name:
497 args.insert(0, self.run_name)
498 elif self.results.lastrun:
499 args.insert(0, self.results.lastrun)
500 else:
501 raise self.InvalidCmd('No run name currently defined. Please add this information.')
502 return
503
504 if args[0] != self.run_name:
505 self.set_run_name(args[0])
506
507 args[0] = self.get_events_path(args[0])
508
509 args += opts
510
511
513 """Check the argument for decay_events command
514 syntax is "decay_events [NAME]"
515 Note that other option are already remove at this point
516 """
517
518 if len(args) == 0:
519 if self.run_name:
520 args.insert(0, self.run_name)
521 elif self.results.lastrun:
522 args.insert(0, self.results.lastrun)
523 else:
524 raise self.InvalidCmd('No run name currently defined. Please add this information.')
525 return
526
527 if args[0] and os.path.isfile(args[0]):
528 pass
529 else:
530 if args[0] != self.run_name:
531 self.set_run_name(args[0], allow_new_tag=False)
532
533 args[0] = self.get_events_path(args[0])
534
535
537 """return the path to the output events
538 """
539
540 if self.mode == 'madevent':
541 possible_path = [
542 pjoin(self.me_dir,'Events', run_name, 'unweighted_events.lhe.gz'),
543 pjoin(self.me_dir,'Events', run_name, 'unweighted_events.lhe')]
544 else:
545 possible_path = [
546 pjoin(self.me_dir,'Events', run_name, 'events.lhe.gz'),
547 pjoin(self.me_dir,'Events', run_name, 'events.lhe')]
548
549 for path in possible_path:
550 if os.path.exists(path):
551 correct_path = path
552 break
553 else:
554 if os.path.exists(run_name):
555 correct_path = run_name
556 else:
557 raise self.InvalidCmd('No events file corresponding to %s run. ' % run_name)
558 return correct_path
559
566
568
569
570
571
572 -class CommonRunCmd(HelpToCmd, CheckValidForCmd, cmd.Cmd):
573
574
575 debug_output = 'ME5_debug'
576 helporder = ['Main Commands', 'Documented commands', 'Require MG5 directory',
577 'Advanced commands']
578 sleep_for_error = True
579
580
581
582 options_configuration = {'pythia8_path': './pythia8',
583 'hwpp_path': './herwigPP',
584 'thepeg_path': './thepeg',
585 'hepmc_path': './hepmc',
586 'madanalysis_path': './MadAnalysis',
587 'madanalysis5_path': './HEPTools/madanalysis5',
588 'pythia-pgs_path':'./pythia-pgs',
589 'td_path':'./td',
590 'delphes_path':'./Delphes',
591 'exrootanalysis_path':'./ExRootAnalysis',
592 'syscalc_path': './SysCalc',
593 'lhapdf': 'lhapdf-config',
594 'timeout': 60,
595 'f2py_compiler':None,
596 'web_browser':None,
597 'eps_viewer':None,
598 'text_editor':None,
599 'fortran_compiler':None,
600 'cpp_compiler': None,
601 'auto_update':7,
602 'cluster_type': 'condor',
603 'cluster_status_update': (600, 30),
604 'cluster_nb_retry':1,
605 'cluster_local_path': None,
606 'cluster_retry_wait':300}
607
608 options_madgraph= {'stdout_level':None}
609
610 options_madevent = {'automatic_html_opening':True,
611 'notification_center':True,
612 'run_mode':2,
613 'cluster_queue':None,
614 'cluster_time':None,
615 'cluster_size':100,
616 'cluster_memory':None,
617 'nb_core': None,
618 'cluster_temp_path':None}
619
620
621 - def __init__(self, me_dir, options, *args, **opts):
622 """common"""
623
624 self.force_run = False
625 self.stop_for_runweb = False
626 if 'force_run' in opts and opts['force_run']:
627 self.force_run = True
628 del opts['force_run']
629
630 cmd.Cmd.__init__(self, *args, **opts)
631
632 if me_dir is None and MADEVENT:
633 me_dir = root_path
634
635 if os.path.isabs(me_dir):
636 self.me_dir = me_dir
637 else:
638 self.me_dir = pjoin(os.getcwd(),me_dir)
639
640 self.options = options
641
642 self.param_card_iterator = []
643
644
645 self.status = pjoin(self.me_dir, 'status')
646 self.error = pjoin(self.me_dir, 'error')
647 self.dirbin = pjoin(self.me_dir, 'bin', 'internal')
648
649
650 if not self.force_run:
651 if os.path.exists(pjoin(me_dir,'RunWeb')):
652 message = '''Another instance of the program is currently running.
653 (for this exact same directory) Please wait that this is instance is
654 closed. If no instance is running, you can delete the file
655 %s and try again.''' % pjoin(me_dir,'RunWeb')
656 self.stop_for_runweb = True
657 raise AlreadyRunning, message
658 else:
659 self.write_RunWeb(me_dir)
660
661 self.to_store = []
662 self.run_name = None
663 self.run_tag = None
664 self.banner = None
665
666 self.set_configuration()
667 self.configure_run_mode(self.options['run_mode'])
668
669
670 if MADEVENT and 'mg5_path' in self.options and self.options['mg5_path']:
671 mg5dir = self.options['mg5_path']
672 if mg5dir not in sys.path:
673 sys.path.append(mg5dir)
674 if pjoin(mg5dir, 'PLUGIN') not in self.plugin_path:
675 self.plugin_path.append(pjoin(mg5dir,'PLUGIN'))
676
677
678 self.get_characteristics()
679
680 if not self.proc_characteristics['ninitial']:
681
682 nexternal = open(pjoin(self.me_dir,'Source','nexternal.inc')).read()
683 found = re.search("PARAMETER\s*\(NINCOMING=(\d)\)", nexternal)
684 self.ninitial = int(found.group(1))
685 else:
686 self.ninitial = self.proc_characteristics['ninitial']
687
690
691
695
696 @staticmethod
698 pid = os.getpid()
699 fsock = open(pjoin(me_dir,'RunWeb'),'w')
700 fsock.write(`pid`)
701 fsock.close()
702
704
705 - def __init__(self, me_dir, crashifpresent=True, warnifpresent=True):
706 """raise error if RunWeb already exists
707 me_dir is the directory where the write RunWeb"""
708
709 self.remove_run_web = True
710 self.me_dir = me_dir
711
712 if crashifpresent or warnifpresent:
713 if os.path.exists(pjoin(me_dir, 'RunWeb')):
714 pid = open(pjoin(me_dir, 'RunWeb')).read()
715 try:
716 pid = int(pid)
717 except Exception:
718 pid = "unknown"
719
720 if pid == 'unknown' or misc.pid_exists(pid):
721
722 if crashifpresent:
723 if isinstance(crashifpresent, Exception):
724 raise crashifpresent
725 else:
726 message = '''Another instance of the program is currently running (pid = %s).
727 (for this exact same directory). Please wait that this is instance is
728 closed. If no instance is running, you can delete the file
729 %s and try again.''' % (pid, pjoin(me_dir, 'RunWeb'))
730 raise AlreadyRunning, message
731 elif warnifpresent:
732 if isinstance( warnifpresent, bool):
733 logger.warning("%s/RunWeb is present. Please check that only one run is running in that directory.")
734 else:
735 logger.log(warnifpresent, "%s/RunWeb is present. Please check that only one run is running in that directory.")
736 self.remove_run_web = False
737 else:
738 logger.debug('RunWeb exists but no associated process. Will Ignore it!')
739 return
740
741
742
743 CommonRunCmd.writeRunWeb(me_dir)
744
747
748 - def __exit__(self,exc_type, exc_value, traceback):
749
750 if self.remove_run_web:
751 try:
752 os.remove(pjoin(self.me_dir,'RunWeb'))
753 except Exception:
754 if os.path.exists(pjoin(self.me_dir,'RunWeb')):
755 logger.warning('fail to remove: %s' % pjoin(self.me_dir,'RunWeb'))
756 return
757
759 """allow to use this as decorator as well"""
760 def wrapper(*args, **kw):
761 with self:
762 return f(*args, **kw)
763 return wrapper
764
765
766
767
768
769
803
804
805 @misc.multiple_try(nb_try=5, sleep=2)
807 """load the current results status"""
808
809
810 if os.path.exists(pjoin(self.me_dir,'HTML','results.pkl')):
811 try:
812 self.results = save_load_object.load_from_file(pjoin(self.me_dir,'HTML','results.pkl'))
813 except Exception:
814
815 model = self.find_model_name()
816 process = self.process
817 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir)
818 self.results.resetall(self.me_dir)
819 else:
820 try:
821 self.results.resetall(self.me_dir)
822 except Exception, error:
823 logger.debug(error)
824
825 model = self.find_model_name()
826 process = self.process
827 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir)
828 self.results.resetall(self.me_dir)
829 self.last_mode = ''
830 try:
831 self.last_mode = self.results[self.results.lastrun][-1]['run_mode']
832 except:
833 self.results.resetall(self.me_dir)
834 self.last_mode = ''
835
836 else:
837 model = self.find_model_name()
838 process = self.process
839 self.results = gen_crossxhtml.AllResults(model, process, self.me_dir)
840 self.results.resetall(self.me_dir)
841 self.last_mode=''
842
843 return self.results
844
845
847 """Advanced commands: create .inc files from param_card.dat/run_card.dat"""
848
849
850
851 if hasattr(self, 'run_card'):
852 self.cluster.modify_interface(self)
853 else:
854 try:
855 self.cluster.modify_interface(self)
856 except Exception, error:
857 misc.sprint(str(error))
858
859 keepwidth = False
860 if '--keepwidth' in line:
861 keepwidth = True
862 line = line.replace('--keepwidth', '')
863 args = self.split_arg(line)
864 mode, opt = self.check_treatcards(args)
865
866 if mode in ['run', 'all']:
867 if not hasattr(self, 'run_card'):
868 run_card = banner_mod.RunCard(opt['run_card'])
869 else:
870 run_card = self.run_card
871
872
873 if amcatnlo and run_card['pdlabel']=='lhapdf':
874 pdfsetsdir=self.get_lhapdf_pdfsetsdir()
875 pdfsets=self.get_lhapdf_pdfsets_list(pdfsetsdir)
876 lhapdfsetname=[]
877 for lhaid in run_card['lhaid']:
878 if lhaid in pdfsets:
879 lhapdfsetname.append(pdfsets[lhaid]['filename'])
880 else:
881 raise MadGraph5Error("lhaid %s is not a valid PDF identification number. This can be due to the use of an outdated version of LHAPDF, or %s is not a LHAGlue number corresponding to a central PDF set (but rather one of the error sets)." % (lhaid,lhaid))
882 run_card['lhapdfsetname']=lhapdfsetname
883 run_card.write_include_file(opt['output_dir'])
884
885 if mode in ['MadLoop', 'all']:
886 if os.path.exists(pjoin(self.me_dir, 'Cards', 'MadLoopParams.dat')):
887 self.MadLoopparam = banner_mod.MadLoopParam(pjoin(self.me_dir,
888 'Cards', 'MadLoopParams.dat'))
889
890 self.MadLoopparam.write(pjoin(self.me_dir,"SubProcesses",
891 "MadLoopParams.dat"))
892
893 if mode in ['param', 'all']:
894 if os.path.exists(pjoin(self.me_dir, 'Source', 'MODEL', 'mp_coupl.inc')):
895 param_card = param_card_mod.ParamCardMP(opt['param_card'])
896 else:
897 param_card = param_card_mod.ParamCard(opt['param_card'])
898 outfile = pjoin(opt['output_dir'], 'param_card.inc')
899 ident_card = pjoin(self.me_dir,'Cards','ident_card.dat')
900 if os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')):
901 default = pjoin(self.me_dir,'bin','internal','ufomodel','restrict_default.dat')
902 elif os.path.isfile(pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')):
903 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
904 elif not os.path.exists(pjoin(self.me_dir,'bin','internal','ufomodel')):
905 fsock = open(pjoin(self.me_dir,'Source','param_card.inc'),'w')
906 fsock.write(' ')
907 fsock.close()
908 return
909 else:
910 subprocess.call(['python', 'write_param_card.py'],
911 cwd=pjoin(self.me_dir,'bin','internal','ufomodel'))
912 default = pjoin(self.me_dir,'bin','internal','ufomodel','param_card.dat')
913
914
915 if amcatnlo and not keepwidth:
916
917 pids = self.get_pid_final_initial_states()
918
919 if not MADEVENT and pjoin(self.me_dir,'bin','internal') not in sys.path:
920 sys.path.insert(0,pjoin(self.me_dir,'bin','internal'))
921
922
923
924 to_del = [name for name in sys.modules.keys()
925 if name.startswith('internal.ufomodel')
926 or name.startswith('ufomodel')]
927 for name in to_del:
928 del(sys.modules[name])
929
930 import ufomodel as ufomodel
931 zero = ufomodel.parameters.ZERO
932 no_width = [p for p in ufomodel.all_particles
933 if (str(p.pdg_code) in pids or str(-p.pdg_code) in pids)
934 and p.color != 1 and p.width != zero]
935 done = []
936 for part in no_width:
937 if abs(part.pdg_code) in done:
938 continue
939 done.append(abs(part.pdg_code))
940 param = param_card['decay'].get((part.pdg_code,))
941
942 if param.value != 0:
943 logger.info('''For gauge cancellation, the width of \'%s\' has been set to zero.'''\
944 % part.name,'$MG:BOLD')
945 param.value = 0
946
947 param_card.write_inc_file(outfile, ident_card, default)
948
950 """return the model related to this process"""
951
952 if self.options['mg5_path']:
953 sys.path.append(self.options['mg5_path'])
954 import models.import_ufo as import_ufo
955 complexmass = self.proc_characteristics['complex_mass_scheme']
956 with misc.MuteLogger(['madgraph.model'],[50]):
957 out= import_ufo.import_model(pjoin(self.me_dir,'bin','internal','ufomodel'),
958 complex_mass_scheme=complexmass)
959 return out
960
961
962
963 else:
964 return None
965
966 - def ask_edit_cards(self, cards, mode='fixed', plot=True, first_cmd=None, from_banner=None,
967 banner=None):
968 """ """
969 if not self.options['madanalysis_path']:
970 plot = False
971
972 self.ask_edit_card_static(cards, mode, plot, self.options['timeout'],
973 self.ask, first_cmd=first_cmd, from_banner=from_banner,
974 banner=banner)
975
976 for c in cards:
977 if not os.path.isabs(c):
978 c = pjoin(self.me_dir, c)
979 if not os.path.exists(c):
980 default = c.replace('dat', '_default.dat')
981 if os.path.exists(default):
982 files.cp(default, c)
983
984
985
986 @staticmethod
989 if not ask:
990 ask = CommonRunCmd.ask
991
992 def path2name(path):
993 if '_card' in path:
994 return path.split('_card')[0]
995 elif path == 'delphes_trigger.dat':
996 return 'trigger'
997 elif path == 'input.lhco':
998 return 'lhco'
999 elif path == 'MadLoopParams.dat':
1000 return 'MadLoopParams'
1001 else:
1002 raise Exception, 'Unknow cards name %s' % path
1003
1004
1005
1006 question = """Do you want to edit a card (press enter to bypass editing)?\n"""
1007 possible_answer = ['0', 'done']
1008 card = {0:'done'}
1009
1010 indent = max(len(path2name(card_name)) for card_name in cards)
1011 question += '/'+'-'*60+'\\\n'
1012 for i, card_name in enumerate(cards):
1013 imode = path2name(card_name)
1014 possible_answer.append(i+1)
1015 possible_answer.append(imode)
1016 question += '| %-77s|\n'%((' \x1b[31m%%s\x1b[0m. %%-%ds : \x1b[32m%%s\x1b[0m'%indent)%(i+1, imode, card_name))
1017 card[i+1] = imode
1018
1019 if plot and not 'plot_card.dat' in cards:
1020 question += '| %-77s|\n'%((' \x1b[31m9\x1b[0m. %%-%ds : \x1b[32mplot_card.dat\x1b[0m'%indent) % 'plot')
1021 possible_answer.append(9)
1022 possible_answer.append('plot')
1023 card[9] = 'plot'
1024
1025 question += '\\'+'-'*60+'/\n'
1026
1027 if 'param_card.dat' in cards:
1028
1029 question += ' you can also\n'
1030 question += ' - enter the path to a valid card or banner.\n'
1031 question += ' - use the \'set\' command to modify a parameter directly.\n'
1032 question += ' The set option works only for param_card and run_card.\n'
1033 question += ' Type \'help set\' for more information on this command.\n'
1034 question += ' - call an external program (ASperGE/MadWidth/...).\n'
1035 question += ' Type \'help\' for the list of available command\n'
1036 else:
1037 question += ' you can also\n'
1038 question += ' - enter the path to a valid card.\n'
1039 if 'transfer_card.dat' in cards:
1040 question += ' - use the \'change_tf\' command to set a transfer functions.\n'
1041
1042 out = 'to_run'
1043 while out not in ['0', 'done']:
1044 out = ask(question, '0', possible_answer, timeout=int(1.5*timeout),
1045 path_msg='enter path', ask_class = AskforEditCard,
1046 cards=cards, mode=mode, **opt)
1047
1048
1049 @staticmethod
1051 """detect the type of the card. Return value are
1052 banner
1053 param_card.dat
1054 run_card.dat
1055 pythia_card.dat
1056 pythia8_card.dat
1057 plot_card.dat
1058 pgs_card.dat
1059 delphes_card.dat
1060 delphes_trigger.dat
1061 shower_card.dat [aMCatNLO]
1062 FO_analyse_card.dat [aMCatNLO]
1063 madspin_card.dat [MS]
1064 transfer_card.dat [MW]
1065 madweight_card.dat [MW]
1066 madanalysis5_hadron_card.dat
1067 madanalysis5_parton_card.dat
1068
1069 Please update the unit-test: test_card_type_recognition when adding
1070 cards.
1071 """
1072
1073 fulltext = open(path).read(50000)
1074 if fulltext == '':
1075 logger.warning('File %s is empty' % path)
1076 return 'unknown'
1077
1078 to_search = ['<MGVersion>',
1079 '<mg5proccard>'
1080 'ParticlePropagator',
1081 'ExecutionPath',
1082 'Treewriter',
1083 'CEN_max_tracker',
1084 '#TRIGGER CARD',
1085 'parameter set name',
1086 'muon eta coverage',
1087 'req_acc_FO',
1088 'MSTP',
1089 'b_stable',
1090 'FO_ANALYSIS_FORMAT',
1091 'MSTU',
1092 'Begin Minpts',
1093 'gridpack',
1094 'ebeam1',
1095 'block\s+mw_run',
1096 'BLOCK',
1097 'DECAY',
1098 'launch',
1099 'madspin',
1100 'transfer_card\.dat',
1101 'set',
1102 'main:numberofevents',
1103 '@MG5aMC skip_analysis',
1104 '@MG5aMC\s*inputs\s*=\s*\*\.(?:hepmc|lhe)',
1105 '@MG5aMC\s*reconstruction_name',
1106 '@MG5aMC'
1107 ]
1108
1109
1110 text = re.findall('(%s)' % '|'.join(to_search), fulltext, re.I)
1111 text = [t.lower() for t in text]
1112 if '<mgversion>' in text or '<mg5proccard>' in text:
1113 return 'banner'
1114 elif 'particlepropagator' in text or 'executionpath' in text or 'treewriter' in text:
1115 return 'delphes_card.dat'
1116 elif 'cen_max_tracker' in text:
1117 return 'delphes_card.dat'
1118 elif '@mg5amc' in text:
1119 ma5_flag = [f[7:].strip() for f in text if f.startswith('@mg5amc')]
1120 if any(f.startswith('reconstruction_name') for f in ma5_flag):
1121 return 'madanalysis5_hadron_card.dat'
1122 ma5_flag = [f.split('*.')[1] for f in ma5_flag if '*.' in f]
1123 if any(f.startswith('lhe') for f in ma5_flag):
1124 return 'madanalysis5_parton_card.dat'
1125 if any(f.startswith(('hepmc','hep','stdhep','lhco')) for f in ma5_flag):
1126 return 'madanalysis5_hadron_card.dat'
1127 else:
1128 return 'unknown'
1129 elif '#trigger card' in text:
1130 return 'delphes_trigger.dat'
1131 elif 'parameter set name' in text:
1132 return 'pgs_card.dat'
1133 elif 'muon eta coverage' in text:
1134 return 'pgs_card.dat'
1135 elif 'mstp' in text and not 'b_stable' in text:
1136 return 'pythia_card.dat'
1137 elif 'begin minpts' in text:
1138 return 'plot_card.dat'
1139 elif ('gridpack' in text and 'ebeam1' in text) or \
1140 ('req_acc_fo' in text and 'ebeam1' in text):
1141 return 'run_card.dat'
1142 elif any(t.endswith('mw_run') for t in text):
1143 return 'madweight_card.dat'
1144 elif 'transfer_card.dat' in text:
1145 return 'transfer_card.dat'
1146 elif 'block' in text and 'decay' in text:
1147 return 'param_card.dat'
1148 elif 'b_stable' in text:
1149 return 'shower_card.dat'
1150 elif 'fo_analysis_format' in text:
1151 return 'FO_analyse_card.dat'
1152 elif 'main:numberofevents' in text:
1153 return 'pythia8_card.dat'
1154 elif 'launch' in text:
1155
1156
1157 if 'madspin' in text:
1158 return 'madspin_card.dat'
1159 if 'decay' in text:
1160
1161 if re.search("(^|;)\s*decay", fulltext):
1162 return 'madspin_card.dat'
1163 else:
1164 return 'reweight_card.dat'
1165 else:
1166 return 'reweight_card.dat'
1167 else:
1168 return 'unknown'
1169
1170
1171
1173 """create automatically a tag"""
1174
1175 used_tags = [r['tag'] for r in self.results[self.run_name]]
1176 i=0
1177 while 1:
1178 i+=1
1179 if 'tag_%s' %i not in used_tags:
1180 return 'tag_%s' % i
1181
1182
1183
1184 @misc.mute_logger(names=['madgraph.various.histograms',
1185 'internal.histograms'],levels=[20,20])
1189 """Generated the HwU plots from Pythia8 driver output for a specific
1190 observable."""
1191
1192 try:
1193 import madgraph
1194 except ImportError:
1195 import internal.histograms as histograms
1196 else:
1197 import madgraph.various.histograms as histograms
1198
1199
1200 if not os.path.isfile(data_path):
1201 return False
1202
1203
1204 histos = histograms.HwUList(data_path, consider_reweights='ALL',run_id=0)
1205 if len(histos)==0:
1206 return False
1207
1208
1209 merging_scales_available = [label[1] for label in \
1210 histos[0].bins.weight_labels if
1211 histograms.HwU.get_HwU_wgt_label_type(label)=='merging_scale']
1212 if len(merging_scales_available)>=2:
1213 min_merging_scale = min(merging_scales_available)
1214 max_merging_scale = max(merging_scales_available)
1215 else:
1216 min_merging_scale = None
1217 max_merging_scale = None
1218
1219
1220 histo_output_options = {
1221 'format':'gnuplot',
1222 'uncertainties':['scale','pdf','statistical',
1223 'merging_scale','alpsfact'],
1224 'ratio_correlations':True,
1225 'arg_string':'Automatic plotting from MG5aMC',
1226 'jet_samples_to_keep':None,
1227 'use_band':['merging_scale','alpsfact'],
1228 'auto_open':False
1229 }
1230
1231 if not (int(self.run_card['ickkw'])==1):
1232 histo_output_options['uncertainties'].pop(
1233 histo_output_options['uncertainties'].index('alpsfact'))
1234 histo_output_options['use_band'].pop(
1235 histo_output_options['use_band'].index('alpsfact'))
1236
1237 histos.output(pjoin(plot_root_path,
1238 'central_%s_%s_plots'%(merging_scale_name,observable_name)),
1239 **histo_output_options)
1240
1241 for scale in merging_scales_available:
1242 that_scale_histos = histograms.HwUList(
1243 data_path, run_id=0, merging_scale=scale)
1244 that_scale_histos.output(pjoin(plot_root_path,
1245 '%s_%.3g_%s_plots'%(merging_scale_name,scale,observable_name)),
1246 **histo_output_options)
1247
1248
1249
1250
1251 if not min_merging_scale is None:
1252 min_scale_histos = histograms.HwUList(data_path,
1253 consider_reweights=[], run_id=0,
1254 merging_scale=min_merging_scale)
1255 max_scale_histos = histograms.HwUList(data_path,
1256 consider_reweights=[], run_id=0,
1257 merging_scale=max_merging_scale)
1258
1259
1260 for histo in min_scale_histos:
1261 if histo.type is None:
1262 histo.type = '%s=%.4g'%(merging_scale_name, min_merging_scale)
1263 else:
1264 histo.type += '|%s=%.4g'%(merging_scale_name, min_merging_scale)
1265 for histo in max_scale_histos:
1266 if histo.type is None:
1267 histo.type = '%s=%.4g'%(merging_scale_name, max_merging_scale)
1268 else:
1269 histo.type += '|%s=%.4g'%(merging_scale_name, max_merging_scale)
1270
1271
1272 histograms.HwUList(min_scale_histos+max_scale_histos).output(
1273 pjoin(plot_root_path,'min_max_%s_%s_comparison'
1274 %(merging_scale_name,observable_name)),
1275 format='gnuplot',
1276 uncertainties=[],
1277 ratio_correlations=True,
1278 arg_string='Automatic plotting from MG5aMC',
1279 jet_samples_to_keep=None,
1280 use_band=[],
1281 auto_open=False)
1282 return True
1283
1285 """ """
1286 devnull = open(os.devnull, 'w')
1287 try:
1288 misc.call(['./bin/internal/gen_cardhtml-pl'], cwd=self.me_dir,
1289 stdout=devnull, stderr=devnull)
1290 except Exception:
1291 pass
1292 devnull.close()
1293
1294
1295 - def create_plot(self, mode='parton', event_path=None, output=None, tag=None):
1296 """create the plot"""
1297
1298 if not tag:
1299 tag = self.run_card['run_tag']
1300
1301 if mode != 'Pythia8':
1302 madir = self.options['madanalysis_path']
1303 td = self.options['td_path']
1304
1305 if not madir or not td or \
1306 not os.path.exists(pjoin(self.me_dir, 'Cards', 'plot_card.dat')):
1307 return False
1308 else:
1309 PY8_plots_root_path = pjoin(self.me_dir,'HTML',
1310 self.run_name,'%s_PY8_plots'%tag)
1311
1312 if 'ickkw' in self.run_card:
1313 if int(self.run_card['ickkw']) and mode == 'Pythia':
1314 self.update_status('Create matching plots for Pythia', level='pythia')
1315
1316 if not os.path.exists(pjoin(self.me_dir,'Events','events.tree')):
1317 misc.gunzip(pjoin(self.me_dir,'Events',
1318 self.run_name, '%s_pythia_events.tree.gz' % tag), keep=True,
1319 stdout=pjoin(self.me_dir,'Events','events.tree'))
1320 files.mv(pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_xsecs.tree'),
1321 pjoin(self.me_dir,'Events','xsecs.tree'))
1322
1323
1324 misc.call([self.dirbin+'/create_matching_plots.sh',
1325 self.run_name, tag, madir],
1326 stdout = os.open(os.devnull, os.O_RDWR),
1327 cwd=pjoin(self.me_dir,'Events'))
1328
1329
1330 misc.gzip(pjoin(self.me_dir,"Events","events.tree"),
1331 stdout=pjoin(self.me_dir,'Events',self.run_name, tag + '_pythia_events.tree.gz'))
1332 files.mv(pjoin(self.me_dir,'Events','xsecs.tree'),
1333 pjoin(self.me_dir,'Events',self.run_name, tag+'_pythia_xsecs.tree'))
1334
1335 elif mode == 'Pythia8' and (int(self.run_card['ickkw'])==1 or \
1336 self.run_card['ktdurham']>0.0 or self.run_card['ptlund']>0.0):
1337
1338 self.update_status('Create matching plots for Pythia8',
1339 level='pythia8')
1340
1341
1342 if not os.path.isdir(PY8_plots_root_path):
1343 os.makedirs(PY8_plots_root_path)
1344
1345 merging_scale_name = 'qCut' if int(self.run_card['ickkw'])==1 \
1346 else 'TMS'
1347
1348 djr_path = pjoin(self.me_dir,'Events',
1349 self.run_name, '%s_djrs.dat' % tag)
1350 pt_path = pjoin(self.me_dir,'Events',
1351 self.run_name, '%s_pts.dat' % tag)
1352 for observable_name, data_path in [('djr',djr_path),
1353 ('pt',pt_path)]:
1354 if not self.generate_Pythia8_HwU_plots(
1355 PY8_plots_root_path, merging_scale_name,
1356 observable_name,data_path):
1357 return False
1358
1359 if mode == 'Pythia8':
1360 plot_files = glob.glob(pjoin(PY8_plots_root_path,'*.gnuplot'))
1361 if not misc.which('gnuplot'):
1362 logger.warning("Install gnuplot to be able to view the plots"+\
1363 " generated at :\n "+\
1364 '\n '.join('%s.gnuplot'%p for p in plot_files))
1365 return True
1366 for plot in plot_files:
1367 command = ['gnuplot',plot]
1368 try:
1369 subprocess.call(command,cwd=PY8_plots_root_path,stderr=subprocess.PIPE)
1370 except Exception as e:
1371 logger.warning("Automatic processing of the Pythia8 "+\
1372 "merging plots with gnuplot failed. Try the"+\
1373 " following command by hand:\n %s"%(' '.join(command))+\
1374 "\nException was: %s"%str(e))
1375 return False
1376
1377 plot_files = glob.glob(pjoin(PY8_plots_root_path,'*.pdf'))
1378 if len(plot_files)>0:
1379
1380 html = "<html>\n<head>\n<TITLE>PLOT FOR PYTHIA8</TITLE>"
1381 html+= '<link rel=stylesheet href="../../mgstyle.css" type="text/css">\n</head>\n<body>\n'
1382 html += "<h2> Plot for Pythia8 </h2>\n"
1383 html += '<a href=../../../crossx.html>return to summary</a><br>'
1384 html += "<table>\n<tr> <td> <b>Obs.</b> </td> <td> <b>Type of plot</b> </td> <td><b> PDF</b> </td> <td><b> input file</b> </td> </tr>\n"
1385 def sorted_plots(elem):
1386 name = os.path.basename(elem[1])
1387 if 'central' in name:
1388 return -100
1389 if 'min_max' in name:
1390 return -10
1391 merging_re = re.match(r'^.*_(\d+)_.*$',name)
1392 if not merging_re is None:
1393 return int(merging_re.group(1))
1394 else:
1395 return 1e10
1396 djr_plot_files = sorted(
1397 (('DJR',p) for p in plot_files if '_djr_' in p),
1398 key = sorted_plots)
1399 pt_plot_files = sorted(
1400 (('Pt',p) for p in plot_files if '_pt_' in p),
1401 key = sorted_plots)
1402 last_obs = None
1403 for obs, one_plot in djr_plot_files+pt_plot_files:
1404 if obs!=last_obs:
1405
1406 html += "<tr><td></td></tr>"
1407 last_obs = obs
1408 name = os.path.basename(one_plot).replace('.pdf','')
1409 short_name = name
1410 for dummy in ['_plots','_djr','_pt']:
1411 short_name = short_name.replace(dummy,'')
1412 short_name = short_name.replace('_',' ')
1413 if 'min max' in short_name:
1414 short_name = "%s comparison with min/max merging scale"%obs
1415 if 'central' in short_name:
1416 short_name = "Merging uncertainty band around central scale"
1417 html += "<tr><td>%(obs)s</td><td>%(sn)s</td><td> <a href=./%(n)s.pdf>PDF</a> </td><td> <a href=./%(n)s.HwU>HwU</a> <a href=./%(n)s.gnuplot>GNUPLOT</a> </td></tr>\n" %\
1418 {'obs':obs, 'sn': short_name, 'n': name}
1419 html += '</table>\n'
1420 html += '<a href=../../../bin/internal/plot_djrs.py> Example of code to plot the above with matplotlib </a><br><br>'
1421 html+='</body>\n</html>'
1422 ff=open(pjoin(PY8_plots_root_path, 'index.html'),'w')
1423 ff.write(html)
1424 return True
1425
1426 if not event_path:
1427 if mode == 'parton':
1428 possibilities=[
1429 pjoin(self.me_dir, 'Events', 'unweighted_events.lhe'),
1430 pjoin(self.me_dir, 'Events', 'unweighted_events.lhe.gz'),
1431 pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe'),
1432 pjoin(self.me_dir, 'Events', self.run_name, 'unweighted_events.lhe.gz')]
1433 for event_path in possibilities:
1434 if os.path.exists(event_path):
1435 break
1436 output = pjoin(self.me_dir, 'HTML',self.run_name, 'plots_parton.html')
1437
1438 elif mode == 'Pythia':
1439 event_path = pjoin(self.me_dir, 'Events','pythia_events.lhe')
1440 output = pjoin(self.me_dir, 'HTML',self.run_name,
1441 'plots_pythia_%s.html' % tag)
1442 elif mode == 'PGS':
1443 event_path = pjoin(self.me_dir, 'Events', self.run_name,
1444 '%s_pgs_events.lhco' % tag)
1445 output = pjoin(self.me_dir, 'HTML',self.run_name,
1446 'plots_pgs_%s.html' % tag)
1447 elif mode == 'Delphes':
1448 event_path = pjoin(self.me_dir, 'Events', self.run_name,'%s_delphes_events.lhco' % tag)
1449 output = pjoin(self.me_dir, 'HTML',self.run_name,
1450 'plots_delphes_%s.html' % tag)
1451 elif mode == "shower":
1452 event_path = pjoin(self.me_dir, 'Events','pythia_events.lhe')
1453 output = pjoin(self.me_dir, 'HTML',self.run_name,
1454 'plots_shower_%s.html' % tag)
1455 if not self.options['pythia-pgs_path']:
1456 return
1457 else:
1458 raise self.InvalidCmd, 'Invalid mode %s' % mode
1459 elif mode == 'reweight' and not output:
1460 output = pjoin(self.me_dir, 'HTML',self.run_name,
1461 'plots_%s.html' % tag)
1462
1463 if not os.path.exists(event_path):
1464 if os.path.exists(event_path+'.gz'):
1465 misc.gunzip('%s.gz' % event_path)
1466 else:
1467 raise self.InvalidCmd, 'Events file %s does not exist' % event_path
1468 elif event_path.endswith(".gz"):
1469 misc.gunzip(event_path)
1470 event_path = event_path[:-3]
1471
1472
1473 self.update_status('Creating Plots for %s level' % mode, level = mode.lower())
1474
1475 mode = mode.lower()
1476 if mode not in ['parton', 'reweight']:
1477 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name,'plots_%s_%s' % (mode.lower(),tag))
1478 elif mode == 'parton':
1479 plot_dir = pjoin(self.me_dir, 'HTML', self.run_name,'plots_parton')
1480 else:
1481 plot_dir =pjoin(self.me_dir, 'HTML', self.run_name,'plots_%s' % (tag))
1482
1483 if not os.path.isdir(plot_dir):
1484 os.makedirs(plot_dir)
1485
1486 files.ln(pjoin(self.me_dir, 'Cards','plot_card.dat'), plot_dir, 'ma_card.dat')
1487
1488 try:
1489 proc = misc.Popen([os.path.join(madir, 'plot_events')],
1490 stdout = open(pjoin(plot_dir, 'plot.log'),'w'),
1491 stderr = subprocess.STDOUT,
1492 stdin=subprocess.PIPE,
1493 cwd=plot_dir)
1494 proc.communicate('%s\n' % event_path)
1495 del proc
1496
1497 misc.call(['%s/plot' % self.dirbin, madir, td],
1498 stdout = open(pjoin(plot_dir, 'plot.log'),'a'),
1499 stderr = subprocess.STDOUT,
1500 cwd=plot_dir)
1501
1502 misc.call(['%s/plot_page-pl' % self.dirbin,
1503 os.path.basename(plot_dir),
1504 mode],
1505 stdout = open(pjoin(plot_dir, 'plot.log'),'a'),
1506 stderr = subprocess.STDOUT,
1507 cwd=pjoin(self.me_dir, 'HTML', self.run_name))
1508
1509 shutil.move(pjoin(self.me_dir, 'HTML',self.run_name ,'plots.html'),
1510 output)
1511
1512 logger.info("Plots for %s level generated, see %s" % \
1513 (mode, output))
1514 except OSError, error:
1515 logger.error('fail to create plot: %s. Please check that MadAnalysis is correctly installed.' % error)
1516
1517 self.update_status('End Plots for %s level' % mode, level = mode.lower(),
1518 makehtml=False)
1519
1520 return True
1521
1523 """Run hep2lhe on the file Events/pythia_events.hep"""
1524
1525 if not self.options['pythia-pgs_path']:
1526 raise self.InvalidCmd, 'No pythia-pgs path defined'
1527
1528 pydir = pjoin(self.options['pythia-pgs_path'], 'src')
1529 eradir = self.options['exrootanalysis_path']
1530
1531
1532 if misc.is_executable(pjoin(pydir, 'hep2lhe')):
1533 self.update_status('Creating shower LHE File (for plot)', level='pythia')
1534
1535 out = open(pjoin(self.me_dir,'Events','pythia_events.lhe'), 'w')
1536
1537 out.writelines('<!--\n')
1538 out.writelines('# Warning! Never use this file for detector studies!\n')
1539 out.writelines('-->\n<!--\n')
1540 if banner_path:
1541 out.writelines(open(banner_path).read().replace('<LesHouchesEvents version="1.0">',''))
1542 out.writelines('\n-->\n')
1543 out.close()
1544
1545 self.cluster.launch_and_wait(self.dirbin+'/run_hep2lhe',
1546 argument= [pydir],
1547 cwd=pjoin(self.me_dir,'Events'),
1548 stdout=os.devnull)
1549
1550 logger.info('Warning! Never use this lhe file for detector studies!')
1551
1552 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHEFConverter')):
1553 self.update_status('Creating Pythia LHE Root File', level='pythia')
1554 try:
1555 misc.call([eradir+'/ExRootLHEFConverter',
1556 'pythia_events.lhe',
1557 pjoin(self.run_name, '%s_pythia_lhe_events.root' % self.run_tag)],
1558 cwd=pjoin(self.me_dir,'Events'))
1559 except Exception, error:
1560 misc.sprint('ExRootLHEFConverter fails', str(error),
1561 log=logger)
1562 pass
1563
1565 """Dummy routine, to be overwritten by daughter classes"""
1566
1567 pass
1568
1569
1571 """help for systematics command"""
1572 logger.info("syntax: systematics RUN_NAME [OUTPUT] [options]",'$MG:BOLD')
1573 logger.info("-- Run the systematics run on the RUN_NAME run.")
1574 logger.info(" RUN_NAME can be a path to a lhef file.")
1575 logger.info(" OUTPUT can be the path to the output lhe file, otherwise the input file will be overwritten")
1576 logger.info("")
1577 logger.info("options: (values written are the default)", '$MG:BOLD')
1578 logger.info("")
1579 logger.info(" --mur=0.5,1,2 # specify the values for renormalisation scale variation")
1580 logger.info(" --muf=0.5,1,2 # specify the values for factorisation scale variation")
1581 logger.info(" --alps=1 # specify the values for MLM emission scale variation (LO only)")
1582 logger.info(" --dyn=-1,1,2,3,4 # specify the dynamical schemes to use.")
1583 logger.info(" # -1 is the one used by the sample.")
1584 logger.info(" # > 0 correspond to options of dynamical_scale_choice of the run_card.")
1585 logger.info(" --pdf=errorset # specify the pdfs to use for pdf variation. (see below)")
1586 logger.info(" --together=mur,muf,dyn # lists the parameter that must be varied simultaneously so as to ")
1587 logger.info(" # compute the weights for all combinations of their variations.")
1588 logger.info(" --from_card # use the information from the run_card (LO only).")
1589 logger.info(" --remove_weights= # remove previously written weights matching the descriptions")
1590 logger.info(" --keep_weights= # force to keep the weight even if in the list of remove_weights")
1591 logger.info(" --start_id= # define the starting digit for the additial weight. If not specify it is determine automatically")
1592 logger.info(" --only_beam=0 # only apply the new pdf set to the beam selected.")
1593 logger.info(" --ion_scaling=True# if original sample was using rescaled PDF: apply the same rescaling for all PDF sets.")
1594 logger.info("")
1595 logger.info(" Allowed value for the pdf options:", '$MG:BOLD')
1596 logger.info(" central : Do not perform any pdf variation" )
1597 logger.info(" errorset : runs over the all the members of the PDF set used to generate the events")
1598 logger.info(" 244800 : runs over the associated set and all its members")
1599 logger.info(" 244800@0 : runs over the central member of the associated set")
1600
1601 logger.info(" CT10 : runs over the associated set and all its members")
1602 logger.info(" CT10@0 : runs over the central member of the associated set")
1603 logger.info(" CT10@X : runs over the Xth member of the associated PDF set")
1604 logger.info(" XX,YY,ZZ : runs over the sets for XX,YY,ZZ (those three follows above syntax)")
1605 logger.info("")
1606 logger.info(" Allowed value for the keep/remove_wgts options:", '$MG:BOLD')
1607 logger.info(" all : keep/remove all weights")
1608 logger.info(" name : keep/remove that particular weight")
1609 logger.info(" id1,id2 : keep/remove all the weights between those two values --included--")
1610 logger.info(" PATTERN : keep/remove all the weights matching the (python) regular expression.")
1611 logger.info(" note that multiple entry of those arguments are allowed")
1613 """auto completion for the systematics command"""
1614
1615 args = self.split_arg(line[0:begidx], error=False)
1616 options = ['--mur=', '--muf=', '--pdf=', '--dyn=','--alps=',
1617 '--together=','--from_card ','--remove_wgts=',
1618 '--keep_wgts=','--start_id=']
1619
1620 if len(args) == 1 and os.path.sep not in text:
1621
1622 data = misc.glob(pjoin('*','*events.lhe*'), pjoin(self.me_dir, 'Events'))
1623 data = [n.rsplit('/',2)[1] for n in data]
1624 return self.list_completion(text, data, line)
1625 elif len(args)==1:
1626
1627 return self.path_completion(text,
1628 os.path.join('.',*[a for a in args \
1629 if a.endswith(os.path.sep)]))
1630 elif len(args)==2 and os.path.sep in args[1]:
1631
1632 return self.path_completion(text, '.')
1633
1634 elif not line.endswith(tuple(options)):
1635 return self.list_completion(text, options)
1636
1637
1638
1640 """ syntax is 'systematics [INPUT [OUTPUT]] OPTIONS'
1641 --mur=0.5,1,2
1642 --muf=0.5,1,2
1643 --alps=1
1644 --dyn=-1
1645 --together=mur,muf #can be repeated
1646
1647 #special options
1648 --from_card=
1649 """
1650
1651 try:
1652 lhapdf_version = self.get_lhapdf_version()
1653 except Exception:
1654 logger.info('No version of lhapdf. Can not run systematics computation')
1655 return
1656 else:
1657 if lhapdf_version.startswith('5'):
1658 logger.info('can not run systematics with lhapdf 5')
1659 return
1660
1661 lhapdf = misc.import_python_lhapdf(self.options['lhapdf'])
1662 if not lhapdf:
1663 logger.info('can not run systematics since can not link python to lhapdf')
1664 return
1665
1666
1667
1668
1669 self.update_status('Running Systematics computation', level='parton')
1670 args = self.split_arg(line)
1671
1672 opts= []
1673 args = [a for a in args if not a.startswith('-') or opts.append(a)]
1674
1675
1676 if any(not o.startswith(('--mur=', '--muf=', '--alps=','--dyn=','--together=','--from_card','--pdf=',
1677 '--remove_wgts=', '--keep_wgts','--start_id='))
1678 for o in opts):
1679 raise self.InvalidCmd, "command systematics called with invalid option syntax. Please retry."
1680
1681
1682 if len(args) == 0:
1683 if self.run_name:
1684 args[0] = self.run_name
1685 else:
1686 raise self.InvalidCmd, 'no default run. Please specify the run_name'
1687
1688 if args[0] != self.run_name:
1689 self.set_run_name(args[0])
1690
1691
1692 result_file= sys.stdout
1693 if not os.path.isfile(args[0]) and not os.path.sep in args[0]:
1694 path = [pjoin(self.me_dir, 'Events', args[0], 'unweighted_events.lhe.gz'),
1695 pjoin(self.me_dir, 'Events', args[0], 'unweighted_events.lhe'),
1696 pjoin(self.me_dir, 'Events', args[0], 'events.lhe.gz'),
1697 pjoin(self.me_dir, 'Events', args[0], 'events.lhe')]
1698
1699 for p in path:
1700 if os.path.exists(p):
1701 nb_event = self.results[args[0]].get_current_info()['nb_event']
1702
1703
1704 if self.run_name != args[0]:
1705 tag = self.results[args[0]].tags[0]
1706 self.set_run_name(args[0], tag,'parton', False)
1707 result_file = open(pjoin(self.me_dir,'Events', self.run_name, 'parton_systematics.log'),'w')
1708 args[0] = p
1709 break
1710 else:
1711 raise self.InvalidCmd, 'Invalid run name. Please retry'
1712 elif self.options['nb_core'] != 1:
1713 lhe = lhe_parser.EventFile(args[0])
1714 nb_event = len(lhe)
1715 lhe.close()
1716
1717 input = args[0]
1718 if len(args)>1:
1719 output = pjoin(os.getcwd(),args[1])
1720 else:
1721 output = input
1722
1723 lhaid = [self.run_card.get_lhapdf_id()]
1724 if 'store_rwgt_info' in self.run_card and not self.run_card['store_rwgt_info']:
1725 raise self.InvalidCmd, "The events was not generated with store_rwgt_info=True. Can not evaluate systematics error on this event file."
1726 elif 'use_syst' in self.run_card:
1727 if not self.run_card['use_syst']:
1728 raise self.InvalidCmd, "The events was not generated with use_syst=True. Can not evaluate systematics error on this event file."
1729 elif self.proc_characteristics['ninitial'] ==1:
1730 if '--from_card' in opts:
1731 logger.warning('systematics not available for decay processes. Bypass it')
1732 return
1733 else:
1734 raise self.InvalidCmd, 'systematics not available for decay processes.'
1735
1736 try:
1737 pdfsets_dir = self.get_lhapdf_pdfsetsdir()
1738 except Exception, error:
1739 logger.debug(str(error))
1740 logger.warning('Systematic computation requires lhapdf to run. Bypass Systematics')
1741 return
1742
1743 if '--from_card' in opts:
1744 opts.remove('--from_card')
1745 opts.append('--from_card=internal')
1746
1747
1748 if 'sys_pdf' in self.run_card:
1749 if '&&' in self.run_card['sys_pdf']:
1750 if isinstance(self.run_card['sys_pdf'], list):
1751 line = ' '.join(self.run_card['sys_pdf'])
1752 else:
1753 line = self.run_card['sys_pdf']
1754 sys_pdf = line.split('&&')
1755 lhaid += [l.split()[0] for l in sys_pdf]
1756 else:
1757 lhaid += [l for l in self.run_card['sys_pdf'].split() if not l.isdigit() or int(l) > 500]
1758
1759 else:
1760
1761 pdf = [a[6:] for a in opts if a.startswith('--pdf=')]
1762 lhaid += [t.split('@')[0] for p in pdf for t in p.split(',')
1763 if t not in ['errorset', 'central']]
1764
1765
1766 try:
1767 [self.copy_lhapdf_set([onelha], pdfsets_dir) for onelha in lhaid]
1768 except Exception, error:
1769 logger.debug(str(error))
1770 logger.warning('impossible to download all the pdfsets. Bypass systematics')
1771 return
1772
1773 if self.options['run_mode'] ==2 and self.options['nb_core'] != 1:
1774 nb_submit = min(self.options['nb_core'], nb_event//2500)
1775 elif self.options['run_mode'] ==1:
1776 nb_submit = min(self.options['cluster_size'], nb_event//25000)
1777 else:
1778 nb_submit =1
1779
1780 if MADEVENT:
1781 import internal.systematics as systematics
1782 else:
1783 import madgraph.various.systematics as systematics
1784
1785
1786 if nb_submit in [0,1]:
1787 systematics.call_systematics([input, output] + opts,
1788 log=lambda x: logger.info(str(x)),
1789 result=result_file
1790 )
1791
1792 elif self.options['run_mode'] in [1,2]:
1793 event_per_job = nb_event // nb_submit
1794 nb_job_with_plus_one = nb_event % nb_submit
1795 start_event, stop_event = 0,0
1796 for i in range(nb_submit):
1797
1798 event_requested = event_per_job
1799 if i < nb_job_with_plus_one:
1800 event_requested += 1
1801 start_event = stop_event
1802 stop_event = start_event + event_requested
1803
1804 prog = sys.executable
1805 input_files = [os.path.basename(input)]
1806 output_files = ['./tmp_%s_%s' % (i, os.path.basename(output)),
1807 './log_sys_%s.txt' % (i)]
1808 argument = []
1809 if not __debug__:
1810 argument.append('-O')
1811 argument += [pjoin(self.me_dir, 'bin', 'internal', 'systematics.py'),
1812 input_files[0], output_files[0]] + opts +\
1813 ['--start_event=%i' % start_event,
1814 '--stop_event=%i' %stop_event,
1815 '--result=./log_sys_%s.txt' %i,
1816 '--lhapdf_config=%s' % self.options['lhapdf']]
1817 required_output = output_files
1818 self.cluster.cluster_submit(prog, argument,
1819 input_files=input_files,
1820 output_files=output_files,
1821 cwd=os.path.dirname(output),
1822 required_output=required_output,
1823 stdout='/dev/null'
1824 )
1825 starttime = time.time()
1826 update_status = lambda idle, run, finish: \
1827 self.update_status((idle, run, finish, 'running systematics'), level=None,
1828 force=False, starttime=starttime)
1829
1830 try:
1831 self.cluster.wait(os.path.dirname(output), update_status, update_first=update_status)
1832 except Exception:
1833 self.cluster.remove()
1834 old_run_mode = self.options['run_mode']
1835 self.options['run_mode'] =0
1836 try:
1837 out = self.do_systematics(line)
1838 finally:
1839 self.options['run_mode'] = old_run_mode
1840
1841 all_cross = []
1842 for i in range(nb_submit):
1843 pos=0
1844 for line in open(pjoin(os.path.dirname(output), 'log_sys_%s.txt'%i)):
1845 if line.startswith('#'):
1846 continue
1847 split = line.split()
1848 if len(split) in [0,1]:
1849 continue
1850 key = tuple(float(x) for x in split[:-1])
1851 cross= float(split[-1])
1852 if 'event_norm' in self.run_card and \
1853 self.run_card['event_norm'] in ['average', 'unity', 'bias']:
1854 cross *= (event_per_job+1 if i <nb_job_with_plus_one else event_per_job)
1855 if len(all_cross) > pos:
1856 all_cross[pos] += cross
1857 else:
1858 all_cross.append(cross)
1859 pos+=1
1860
1861 if 'event_norm' in self.run_card and \
1862 self.run_card['event_norm'] in ['unity']:
1863 all_cross= [cross/nb_event for cross in all_cross]
1864
1865 sys_obj = systematics.call_systematics([input, None] + opts,
1866 log=lambda x: logger.info(str(x)),
1867 result=result_file,
1868 running=False
1869 )
1870 sys_obj.print_cross_sections(all_cross, nb_event, result_file)
1871
1872
1873 subprocess.call(['cat']+\
1874 ['./tmp_%s_%s' % (i, os.path.basename(output)) for i in range(nb_submit)],
1875 stdout=open(output,'w'),
1876 cwd=os.path.dirname(output))
1877 for i in range(nb_submit):
1878 os.remove('%s/tmp_%s_%s' %(os.path.dirname(output),i,os.path.basename(output)))
1879
1880
1881
1882
1883
1884
1885 self.update_status('End of systematics computation', level='parton', makehtml=False)
1886
1887
1888
1890 """ syntax is "reweight RUN_NAME"
1891 Allow to reweight the events generated with a new choices of model
1892 parameter. Description of the methods are available here
1893 cp3.irmp.ucl.ac.be/projects/madgraph/wiki/Reweight
1894 """
1895
1896
1897
1898 def check_multicore(self):
1899 """ determine if the cards are save for multicore use"""
1900 card = pjoin(self.me_dir, 'Cards', 'reweight_card.dat')
1901
1902 multicore = True
1903 if self.options['run_mode'] in [0,1]:
1904 multicore = False
1905
1906 lines = [l.strip() for l in open(card) if not l.strip().startswith('#')]
1907 while lines and not lines[0].startswith('launch'):
1908 line = lines.pop(0)
1909
1910 if line.startswith('change') and line[6:].strip().startswith('output'):
1911 return False
1912 if line.startswith('change') and line[6:].strip().startswith('multicore'):
1913 split_line = line.split()
1914 if len(split_line) > 2:
1915 multicore = bool(split_line[2])
1916
1917
1918 lines = [line[6:].strip() for line in lines if line.startswith('change')]
1919 for line in lines:
1920 if line.startswith(('process','model','output', 'rwgt_dir')):
1921 return False
1922 elif line.startswith('multicore'):
1923 split_line = line.split()
1924 if len(split_line) > 1:
1925 multicore = bool(split_line[1])
1926
1927 return multicore
1928
1929
1930
1931 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'reweight_card.dat')):
1932 return
1933
1934 if '--multicore=create' in line:
1935 multicore='create'
1936 elif '--multicore=wait' in line:
1937 multicore='wait'
1938 else:
1939 multicore=False
1940
1941
1942 plugin = False
1943 if '--plugin=' in line:
1944 plugin = [l.split('=',1)[1] for l in line.split() if '--plugin=' in l][0]
1945 elif hasattr(self, 'switch') and self.switch['reweight'] not in ['ON','OFF']:
1946 plugin=self.switch['reweight']
1947
1948
1949
1950
1951 if MADEVENT and not self.options['mg5_path']:
1952 raise self.InvalidCmd, '''The module reweight requires that MG5 is installed on the system.
1953 You can install it and set its path in ./Cards/me5_configuration.txt'''
1954 elif MADEVENT:
1955 sys.path.append(self.options['mg5_path'])
1956 try:
1957 import madgraph.interface.reweight_interface as reweight_interface
1958 except ImportError:
1959 raise self.ConfigurationError, '''Can\'t load Reweight module.
1960 The variable mg5_path might not be correctly configured.'''
1961
1962
1963
1964 if not '-from_cards' in line:
1965 self.keep_cards(['reweight_card.dat'], ignore=['*'])
1966 self.ask_edit_cards(['reweight_card.dat'], 'fixed', plot=False)
1967
1968
1969 args = self.split_arg(line)
1970 if plugin and '--plugin=' not in line:
1971 args.append('--plugin=%s' % plugin)
1972
1973
1974 if not self.force_run:
1975
1976 if self.run_name and self.results.current and self.results.current['cross'] == 0:
1977 self.results.delete_run(self.run_name, self.run_tag)
1978 self.results.save()
1979
1980 if not hasattr(self, 'run_card'):
1981 self.run_card = banner_mod.RunCard(pjoin(self.me_dir, 'Cards', 'run_card.dat'))
1982
1983
1984 command = [sys.executable]
1985 if os.path.exists(pjoin(self.me_dir, 'bin', 'madevent')):
1986 command.append(pjoin(self.me_dir, 'bin', 'internal','madevent_interface.py'))
1987 else:
1988 command.append(pjoin(self.me_dir, 'bin', 'internal', 'amcatnlo_run_interface.py'))
1989 if not isinstance(self, cmd.CmdShell):
1990 command.append('--web')
1991 command.append('reweight')
1992
1993
1994 if self.options['nb_core']==1 or self.run_card['nevents'] < 101 or not check_multicore(self):
1995 if self.run_name:
1996 command.append(self.run_name)
1997 else:
1998 command += args
1999 if '-from_cards' not in command:
2000 command.append('-from_cards')
2001 p = misc.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, cwd=os.getcwd())
2002 while p.poll() is None:
2003 line = p.stdout.readline()
2004 if any(t in line for t in ['INFO:', 'WARNING:', 'CRITICAL:', 'ERROR:', 'root:','KEEP:']) and \
2005 not '***********' in line:
2006 print line[:-1].replace('INFO', 'REWEIGHT').replace('KEEP:','')
2007 elif __debug__ and line:
2008 logger.debug(line[:-1])
2009 if p.returncode !=0:
2010 logger.error("Reweighting failed")
2011 return
2012 self.results = self.load_results_db()
2013
2014 try:
2015 if self.results[self.run_name][-2]['cross']==0:
2016 self.results.delete_run(self.run_name,self.results[self.run_name][-2]['tag'])
2017 except:
2018 pass
2019 try:
2020 if self.results.current['cross'] == 0 and self.run_name:
2021 self.results.delete_run(self.run_name, self.run_tag)
2022 except:
2023 pass
2024
2025 try:
2026 self.results.def_current(self.run_name, self.run_tag)
2027 except Exception:
2028 pass
2029 return
2030
2031 else:
2032
2033 if not isinstance(self.cluster, cluster.MultiCore):
2034 mycluster = cluster.MultiCore(nb_core=self.options['nb_core'])
2035 else:
2036 mycluster = self.cluster
2037
2038 new_args=list(args)
2039 self.check_decay_events(new_args)
2040 try:
2041 os.remove(pjoin(self.me_dir,'rw_me','rwgt.pkl'))
2042 except Exception, error:
2043 pass
2044
2045 import madgraph.various.lhe_parser as lhe_parser
2046
2047 if 'nevt_job' in self.run_card and self.run_card['nevt_job'] !=-1:
2048 nevt_job = self.run_card['nevt_job']
2049 else:
2050 nevt_job = max(2500, self.run_card['nevents']/self.options['nb_core'])
2051 logger.info("split the event file in bunch of %s events" % nevt_job)
2052 nb_file = lhe_parser.EventFile(new_args[0]).split(nevt_job)
2053 starttime = time.time()
2054 update_status = lambda idle, run, finish: \
2055 self.update_status((idle, run, finish, 'reweight'), level=None,
2056 force=False, starttime=starttime)
2057
2058 all_lhe = []
2059
2060 to_zip=True
2061 if not os.path.exists(new_args[0]) and new_args[0].endswith('.gz') and\
2062 os.path.exists(new_args[0][:-3]):
2063 to_zip = False
2064 devnull= open(os.devnull)
2065
2066 for i in range(nb_file):
2067 new_command = list(command)
2068 if to_zip:
2069 new_command.append('%s_%s.lhe' % (new_args[0],i))
2070 all_lhe.append('%s_%s.lhe' % (new_args[0],i))
2071 else:
2072 new_command.append('%s_%s.lhe' % (new_args[0][:-3],i))
2073 all_lhe.append('%s_%s.lhe' % (new_args[0][:-3],i))
2074
2075 if '-from_cards' not in command:
2076 new_command.append('-from_cards')
2077 if plugin:
2078 new_command.append('--plugin=%s' % plugin)
2079 if i==0:
2080 if __debug__:
2081 stdout = None
2082 else:
2083 stdout = open(pjoin(self.me_dir,'Events', self.run_name, 'reweight.log'),'w')
2084 new_command.append('--multicore=create')
2085 else:
2086 stdout = devnull
2087
2088 new_command.append('--multicore=wait')
2089 mycluster.submit(prog=command[0], argument=new_command[1:], stdout=stdout, cwd=os.getcwd())
2090 mycluster.wait(self.me_dir,update_status)
2091 devnull.close()
2092 logger.info("Collect and combine the various output file.")
2093
2094 lhe = lhe_parser.MultiEventFile(all_lhe, parse=False)
2095 nb_event, cross_sections = lhe.write(new_args[0], get_info=True)
2096 if any(os.path.exists('%s_%s_debug.log' % (f, self.run_tag)) for f in all_lhe):
2097 for f in all_lhe:
2098 if os.path.exists('%s_%s_debug.log' % (f, self.run_tag)):
2099 raise Exception, "Some of the run failed: Please read %s_%s_debug.log" % (f, self.run_tag)
2100
2101
2102 if 'event_norm' in self.run_card and self.run_card['event_norm'] in ['average','bias']:
2103 for key, value in cross_sections.items():
2104 cross_sections[key] = value / (nb_event+1)
2105 lhe.remove()
2106 for key in cross_sections:
2107 if key == 'orig' or key.isdigit():
2108 continue
2109 logger.info('%s : %s pb' % (key, cross_sections[key]))
2110 return
2111
2112
2113
2114 self.to_store.append('event')
2115
2116 if not self.force_run and self.results.current['cross'] == 0 and self.run_name:
2117 self.results.delete_run(self.run_name, self.run_tag)
2118
2119 self.check_decay_events(args)
2120
2121 rwgt_interface = reweight_interface.ReweightInterface
2122 if plugin:
2123 rwgt_interface = misc.from_plugin_import(self.plugin_path, 'new_reweight',
2124 plugin, warning=False,
2125 info="Will use re-weighting from pluging %(plug)s")
2126
2127 reweight_cmd = rwgt_interface(args[0], mother=self)
2128
2129
2130 wgt_names = reweight_cmd.get_weight_names()
2131 if wgt_names == [''] and reweight_cmd.has_nlo:
2132 self.update_status('Running Reweighting (LO approximate)', level='madspin')
2133 else:
2134 self.update_status('Running Reweighting', level='madspin')
2135
2136 path = pjoin(self.me_dir, 'Cards', 'reweight_card.dat')
2137 reweight_cmd.raw_input=False
2138 reweight_cmd.me_dir = self.me_dir
2139 reweight_cmd.multicore = multicore
2140 reweight_cmd.import_command_file(path)
2141 reweight_cmd.do_quit('')
2142
2143 logger.info("quit rwgt")
2144
2145
2146
2147
2148 try:
2149 self.results.def_current(self.run_name, self.run_tag)
2150 except Exception:
2151 pass
2152
2153
2155 """launch pgs"""
2156
2157 args = self.split_arg(line)
2158
2159 if '--no_default' in args:
2160 no_default = True
2161 args.remove('--no_default')
2162 else:
2163 no_default = False
2164
2165 if no_default and not os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')):
2166 logger.info('No pgs_card detected, so not run pgs')
2167 return
2168
2169
2170
2171
2172
2173
2174 lock = self.check_pgs(args, no_default=no_default)
2175
2176
2177 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'pgs_card.dat')):
2178 files.cp(pjoin(self.me_dir, 'Cards', 'pgs_card_default.dat'),
2179 pjoin(self.me_dir, 'Cards', 'pgs_card.dat'))
2180 logger.info('No pgs card found. Take the default one.')
2181
2182 if not (no_default or self.force):
2183 self.ask_edit_cards(['pgs_card.dat'])
2184
2185 self.update_status('prepare PGS run', level=None)
2186
2187 pgsdir = pjoin(self.options['pythia-pgs_path'], 'src')
2188 eradir = self.options['exrootanalysis_path']
2189 madir = self.options['madanalysis_path']
2190 td = self.options['td_path']
2191
2192
2193 if not misc.is_executable(pjoin(pgsdir, 'pgs')):
2194 logger.info('No PGS executable -- running make')
2195 misc.compile(cwd=pgsdir)
2196
2197 self.update_status('Running PGS', level='pgs')
2198
2199 tag = self.run_tag
2200
2201 banner_path = pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, self.run_tag))
2202 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')):
2203 self.banner.add(pjoin(self.me_dir, 'Cards','pgs_card.dat'))
2204 self.banner.write(banner_path)
2205 else:
2206 open(banner_path, 'w').close()
2207
2208
2209
2210
2211 if lock:
2212 lock.wait()
2213
2214 ff = open(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'), 'w')
2215 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')):
2216 text = open(banner_path).read()
2217 text = '#%s' % text.replace('\n','\n#')
2218 dico = self.results[self.run_name].get_current_info()
2219 text +='\n## Integrated weight (pb) : %.4g' % dico['cross']
2220 text +='\n## Number of Event : %s\n' % dico['nb_event']
2221 ff.writelines(text)
2222 ff.close()
2223
2224 try:
2225 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done'))
2226 except Exception:
2227 pass
2228
2229 pgs_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_pgs.log" % tag)
2230 self.cluster.launch_and_wait('../bin/internal/run_pgs',
2231 argument=[pgsdir], cwd=pjoin(self.me_dir,'Events'),
2232 stdout=pgs_log, stderr=subprocess.STDOUT)
2233
2234 if not os.path.exists(pjoin(self.me_dir, 'Events', 'pgs.done')):
2235 logger.error('Fail to create LHCO events')
2236 return
2237 else:
2238 os.remove(pjoin(self.me_dir, 'Events', 'pgs.done'))
2239
2240 if os.path.getsize(banner_path) == os.path.getsize(pjoin(self.me_dir, 'Events','pgs_events.lhco')):
2241 misc.call(['cat pgs_uncleaned_events.lhco >> pgs_events.lhco'],
2242 cwd=pjoin(self.me_dir, 'Events'))
2243 os.remove(pjoin(self.me_dir, 'Events', 'pgs_uncleaned_events.lhco '))
2244
2245
2246 if eradir and misc.is_executable(pjoin(eradir, 'ExRootLHCOlympicsConverter')):
2247 self.update_status('Creating PGS Root File', level='pgs')
2248 try:
2249 misc.call([eradir+'/ExRootLHCOlympicsConverter',
2250 'pgs_events.lhco',pjoin('%s/%s_pgs_events.root' % (self.run_name, tag))],
2251 cwd=pjoin(self.me_dir, 'Events'))
2252 except Exception:
2253 logger.warning('fail to produce Root output [problem with ExRootAnalysis')
2254 if os.path.exists(pjoin(self.me_dir, 'Events', 'pgs_events.lhco')):
2255
2256 files.mv(pjoin(self.me_dir, 'Events', 'pgs_events.lhco'),
2257 pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag))
2258 self.create_plot('PGS')
2259 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_pgs_events.lhco' % tag))
2260
2261 self.update_status('finish', level='pgs', makehtml=False)
2262
2263
2265 """Require MG5 directory: Compute automatically the widths of a set
2266 of particles"""
2267
2268
2269
2270 args = self.split_arg(line)
2271 opts = self.check_compute_widths(args)
2272
2273 from madgraph.interface.master_interface import MasterCmd
2274 cmd = MasterCmd()
2275 self.define_child_cmd_interface(cmd, interface=False)
2276 cmd.options.update(self.options)
2277 cmd.exec_cmd('set automatic_html_opening False --no_save')
2278 if not opts['path']:
2279 opts['path'] = pjoin(self.me_dir, 'Cards', 'param_card.dat')
2280 if not opts['force'] :
2281 self.ask_edit_cards(['param_card.dat'],[], plot=False)
2282
2283
2284 line = 'compute_widths %s %s' % \
2285 (' '.join([str(i) for i in opts['particles']]),
2286 ' '.join('--%s=%s' % (key,value) for (key,value) in opts.items()
2287 if key not in ['model', 'force', 'particles'] and value))
2288 cmd.exec_cmd(line, model=opts['model'])
2289 self.child = None
2290 del cmd
2291
2292
2294 """Not in help:Print the cross-section/ number of events for a given run"""
2295
2296 args = self.split_arg(line)
2297 options={'path':None, 'mode':'w', 'format':'full'}
2298 for arg in list(args):
2299 if arg.startswith('--') and '=' in arg:
2300 name,value=arg.split('=',1)
2301 name = name [2:]
2302 options[name] = value
2303 args.remove(arg)
2304
2305
2306 if len(args) > 0:
2307 run_name = args[0]
2308 else:
2309 for i, run_name in enumerate(self.results.order):
2310 for j, one_result in enumerate(self.results[run_name]):
2311 if i or j:
2312 options['mode'] = "a"
2313 if options['path']:
2314 self.print_results_in_file(one_result, options['path'], options['mode'], options['format'])
2315 else:
2316 self.print_results_in_shell(one_result)
2317 return
2318
2319 if run_name not in self.results:
2320 raise self.InvalidCmd('%s is not a valid run_name or it doesn\'t have any information' \
2321 % run_name)
2322
2323
2324 if len(args) == 2:
2325 tag = args[1]
2326 if tag.isdigit():
2327 tag = int(tag) - 1
2328 if len(self.results[run_name]) < tag:
2329 raise self.InvalidCmd('Only %s different tag available' % \
2330 len(self.results[run_name]))
2331 data = self.results[run_name][tag]
2332 else:
2333 data = self.results[run_name].return_tag(tag)
2334 else:
2335 data = self.results[run_name].return_tag(None)
2336
2337 if options['path']:
2338 self.print_results_in_file(data, options['path'], options['mode'], options['format'])
2339 else:
2340 self.print_results_in_shell(data)
2341
2346
2347
2348
2349
2350
2351 @staticmethod
2352 - def runMA5(MA5_interpreter, MA5_cmds, MA5_runtag, logfile_path, advertise_log=True):
2353 """ Run MA5 in a controlled environnment."""
2354 successfull_MA5_run = True
2355
2356 try:
2357
2358 MA5_logger = None
2359 MA5_logger = logging.getLogger('MA5')
2360 BackUp_MA5_handlers = MA5_logger.handlers
2361 for handler in BackUp_MA5_handlers:
2362 MA5_logger.removeHandler(handler)
2363 file_handler = logging.FileHandler(logfile_path)
2364 MA5_logger.addHandler(file_handler)
2365 if advertise_log:
2366 logger.info("Follow Madanalysis5 run with the following command in a separate terminal:")
2367 logger.info(' tail -f %s'%logfile_path)
2368
2369 with misc.stdchannel_redirected(sys.stdout, os.devnull):
2370 with misc.stdchannel_redirected(sys.stderr, os.devnull):
2371 MA5_interpreter.print_banner()
2372 MA5_interpreter.load(MA5_cmds)
2373 except Exception as e:
2374 logger.warning("MadAnalysis5 failed to run the commands for task "+
2375 "'%s'. Madanalys5 analysis will be skipped."%MA5_runtag)
2376 error=StringIO.StringIO()
2377 traceback.print_exc(file=error)
2378 logger.debug('MadAnalysis5 error was:')
2379 logger.debug('-'*60)
2380 logger.debug(error.getvalue()[:-1])
2381 logger.debug('-'*60)
2382 successfull_MA5_run = False
2383 finally:
2384 if not MA5_logger is None:
2385 for handler in MA5_logger.handlers:
2386 MA5_logger.removeHandler(handler)
2387 for handler in BackUp_MA5_handlers:
2388 MA5_logger.addHandler(handler)
2389
2390 return successfull_MA5_run
2391
2392
2393
2394
2395 @staticmethod
2399 """ Makes sure to correctly setup paths and constructs and return an MA5 path"""
2400
2401 MA5path = os.path.normpath(pjoin(mg5_path,ma5_path))
2402
2403 if MA5path is None or not os.path.isfile(pjoin(MA5path,'bin','ma5')):
2404 return None
2405 if MA5path not in sys.path:
2406 sys.path.insert(0, MA5path)
2407
2408 try:
2409
2410
2411 import readline
2412 old_completer = readline.get_completer()
2413 old_delims = readline.get_completer_delims()
2414 old_history = [readline.get_history_item(i) for i in range(1,readline.get_current_history_length()+1)]
2415 except ImportError:
2416 old_completer, old_delims, old_history = None, None, None
2417 try:
2418 from madanalysis.interpreter.ma5_interpreter import MA5Interpreter
2419 with misc.stdchannel_redirected(sys.stdout, os.devnull):
2420 with misc.stdchannel_redirected(sys.stderr, os.devnull):
2421 MA5_interpreter = MA5Interpreter(MA5path, LoggerLevel=loglevel,
2422 LoggerStream=logstream,forced=forced,
2423 no_compilation=not compilation)
2424 except Exception as e:
2425 logger.warning('MadAnalysis5 failed to start so that MA5 analysis will be skipped.')
2426 error=StringIO.StringIO()
2427 traceback.print_exc(file=error)
2428 logger.debug('MadAnalysis5 error was:')
2429 logger.debug('-'*60)
2430 logger.debug(error.getvalue()[:-1])
2431 logger.debug('-'*60)
2432 MA5_interpreter = None
2433 finally:
2434
2435 if not old_history is None:
2436 readline.clear_history()
2437 for line in old_history:
2438 readline.add_history(line)
2439 if not old_completer is None:
2440 readline.set_completer(old_completer)
2441 if not old_delims is None:
2442 readline.set_completer_delims(old_delims)
2443
2444
2445 if not mg5_interface is None and any(not elem is None for elem in [old_completer, old_delims, old_history]):
2446 mg5_interface.set_readline_completion_display_matches_hook()
2447
2448 return MA5_interpreter
2449
2451 """Check the argument for the madanalysis5 command
2452 syntax: madanalysis5_parton [NAME]
2453 """
2454
2455 MA5_options = {'MA5_stdout_lvl':'default'}
2456
2457 stdout_level_tags = [a for a in args if a.startswith('--MA5_stdout_lvl=')]
2458 for slt in stdout_level_tags:
2459 lvl = slt.split('=')[1].strip()
2460 try:
2461
2462 MA5_options['MA5_stdout_lvl']=int(lvl)
2463 except ValueError:
2464 if lvl.startswith('logging.'):
2465 lvl = lvl[8:]
2466 try:
2467 MA5_options['MA5_stdout_lvl'] = getattr(logging, lvl)
2468 except:
2469 raise InvalidCmd("MA5 output level specification"+\
2470 " '%s' is incorrect." % str(lvl))
2471 args.remove(slt)
2472
2473 if mode=='parton':
2474
2475
2476 MA5_options['inputs'] = '*.lhe'
2477 elif mode=='hadron':
2478
2479
2480
2481 MA5_options['inputs'] = ['fromCard']
2482 else:
2483 raise MadGraph5Error('Mode %s not reckognized'%mode+
2484 ' in function check_madanalysis5.')
2485
2486 if not self.options['madanalysis5_path']:
2487 logger.info('Now trying to read the configuration file again'+
2488 ' to find MadAnalysis5 path')
2489 self.set_configuration()
2490
2491 if not self.options['madanalysis5_path'] or not \
2492 os.path.exists(pjoin(self.options['madanalysis5_path'],'bin','ma5')):
2493 error_msg = 'No valid MadAnalysis5 path set.\n'
2494 error_msg += 'Please use the set command to define the path and retry.\n'
2495 error_msg += 'You can also define it in the configuration file.\n'
2496 error_msg += 'Finally, it can be installed automatically using the'
2497 error_msg += ' install command.\n'
2498 raise self.InvalidCmd(error_msg)
2499
2500
2501 if not os.path.isfile(pjoin(self.me_dir,
2502 'Cards','madanalysis5_%s_card.dat'%mode)):
2503 raise self.InvalidCmd('Your installed version of MadAnalysis5 and/or'+\
2504 ' MadGraph5_aMCatNLO does not seem to support analysis at'+
2505 '%s level.'%mode)
2506
2507 tag = [a for a in args if a.startswith('--tag=')]
2508 if tag:
2509 args.remove(tag[0])
2510 tag = tag[0][6:]
2511
2512 if len(args) == 0 and not self.run_name:
2513 if self.results.lastrun:
2514 args.insert(0, self.results.lastrun)
2515 else:
2516 raise self.InvalidCmd('No run name currently defined. '+
2517 'Please add this information.')
2518
2519 if len(args) >= 1:
2520 if mode=='parton' and args[0] != self.run_name and \
2521 not os.path.exists(pjoin(self.me_dir,'Events',args[0],
2522 'unweighted_events.lhe.gz')) and not os.path.exists(
2523 pjoin(self.me_dir,'Events',args[0])):
2524 raise self.InvalidCmd('No events file in the %s run.'%args[0])
2525 self.set_run_name(args[0], tag, level='madanalysis5_%s'%mode)
2526 else:
2527 if tag:
2528 self.run_card['run_tag'] = args[0]
2529 self.set_run_name(self.run_name, tag, level='madanalysis5_%s'%mode)
2530
2531 if mode=='parton':
2532 if any(t for t in args if t.startswith('--input=')):
2533 raise InvalidCmd('The option --input=<input_file> is not'+
2534 ' available when running partonic MadAnalysis5 analysis. The'+
2535 ' .lhe output of the selected run is used automatically.')
2536 input_file = pjoin(self.me_dir,'Events',self.run_name, 'unweighted_events.lhe')
2537 MA5_options['inputs'] = '%s.gz'%input_file
2538 if not os.path.exists('%s.gz'%input_file):
2539 if os.path.exists(input_file):
2540 misc.gzip(input_file, stdout='%s.gz' % input_file)
2541 else:
2542 logger.warning("LHE event file not found in \n%s\ns"%input_file+
2543 "Parton-level MA5 analysis will be skipped.")
2544
2545 if mode=='hadron':
2546
2547
2548 self.store_result()
2549
2550 hadron_tag = [t for t in args if t.startswith('--input=')]
2551 if hadron_tag and hadron_tag[0][8:]:
2552 hadron_inputs = hadron_tag[0][8:].split(',')
2553
2554
2555 elif MA5_options['inputs'] == ['fromCard']:
2556 hadron_inputs = banner_mod.MadAnalysis5Card(pjoin(self.me_dir,
2557 'Cards','madanalysis5_hadron_card.dat'),mode='hadron')['inputs']
2558
2559
2560
2561 MA5_options['inputs'] = []
2562 special_source_tags = []
2563 for htag in hadron_inputs:
2564
2565 if htag in special_source_tags:
2566
2567 continue
2568
2569 if os.path.isfile(htag) or (os.path.exists(htag) and
2570 stat.S_ISFIFO(os.stat(htag).st_mode)):
2571 MA5_options['inputs'].append(htag)
2572 continue
2573
2574
2575
2576 file_candidates = misc.glob(htag, pjoin(self.me_dir,'Events',self.run_name))+\
2577 misc.glob('%s.gz'%htag, pjoin(self.me_dir,'Events',self.run_name))
2578 priority_files = [f for f in file_candidates if
2579 self.run_card['run_tag'] in os.path.basename(f)]
2580 priority_files = [f for f in priority_files if
2581 'EVENTS' in os.path.basename(f).upper()]
2582
2583 for f in file_candidates:
2584 if os.path.basename(f).startswith('unweighted_events.lhe'):
2585 priority_files.append(f)
2586 if priority_files:
2587 MA5_options['inputs'].append(priority_files[-1])
2588 continue
2589 if file_candidates:
2590 MA5_options['inputs'].append(file_candidates[-1])
2591 continue
2592
2593 return MA5_options
2594
2596 """Ask the question when launching madanalysis5.
2597 In the future we can ask here further question about the MA5 run, but
2598 for now we just edit the cards"""
2599
2600 cards = ['madanalysis5_%s_card.dat'%runtype]
2601 self.keep_cards(cards)
2602
2603 if self.force:
2604 return runtype
2605
2606
2607
2608 auto=False
2609 if mode=='auto':
2610 auto=True
2611 if auto:
2612 self.ask_edit_cards(cards, mode='auto', plot=False)
2613 else:
2614 self.ask_edit_cards(cards, plot=False)
2615
2616
2617
2618 mode = runtype
2619 return mode
2620
2622 "Complete the madanalysis5 command"
2623 args = self.split_arg(line[0:begidx], error=False)
2624 if len(args) == 1:
2625
2626 data = []
2627 for name in banner_mod.MadAnalysis5Card._default_hadron_inputs:
2628 data += misc.glob(pjoin('*','%s'%name), pjoin(self.me_dir, 'Events'))
2629 data += misc.glob(pjoin('*','%s.gz'%name), pjoin(self.me_dir, 'Events'))
2630 data = [n.rsplit('/',2)[1] for n in data]
2631 tmp1 = self.list_completion(text, data)
2632 if not self.run_name:
2633 return tmp1
2634 else:
2635 tmp2 = self.list_completion(text, ['-f',
2636 '--MA5_stdout_lvl=','--input=','--no_default', '--tag='], line)
2637 return tmp1 + tmp2
2638
2639 elif '--MA5_stdout_lvl=' in line and not any(arg.startswith(
2640 '--MA5_stdout_lvl=') for arg in args):
2641 return self.list_completion(text,
2642 ['--MA5_stdout_lvl=%s'%opt for opt in
2643 ['logging.INFO','logging.DEBUG','logging.WARNING',
2644 'logging.CRITICAL','90']], line)
2645 elif '--input=' in line and not any(arg.startswith(
2646 '--input=') for arg in args):
2647 return self.list_completion(text, ['--input=%s'%opt for opt in
2648 (banner_mod.MadAnalysis5Card._default_hadron_inputs +['path'])], line)
2649 else:
2650 return self.list_completion(text, ['-f',
2651 '--MA5_stdout_lvl=','--input=','--no_default', '--tag='], line)
2652
2654 """launch MadAnalysis5 at the hadron level."""
2655 return self.run_madanalysis5(line,mode='hadron')
2656
2658 """launch MadAnalysis5 at the parton level or at the hadron level with
2659 a specific command line."""
2660
2661
2662 args = self.split_arg(line)
2663
2664 if '--no_default' in args:
2665 no_default = True
2666 args.remove('--no_default')
2667 else:
2668 no_default = False
2669
2670 if no_default:
2671
2672 if mode=='parton' and not os.path.exists(pjoin(self.me_dir, 'Cards',
2673 'madanalysis5_parton_card.dat')):
2674 return
2675 if mode=='hadron' and not os.path.exists(pjoin(self.me_dir, 'Cards',
2676 'madanalysis5_hadron_card.dat')):
2677 return
2678 else:
2679
2680
2681 self.ask_madanalysis5_run_configuration(runtype=mode)
2682
2683 if not self.options['madanalysis5_path'] or \
2684 all(not os.path.exists(pjoin(self.me_dir, 'Cards',card)) for card in
2685 ['madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat']):
2686 if no_default:
2687 return
2688 else:
2689 raise InvalidCmd('You must have MadAnalysis5 available to run'+
2690 " this command. Consider installing it with the 'install' function.")
2691
2692 if not self.run_name:
2693 MA5_opts = self.check_madanalysis5(args, mode=mode)
2694 self.configure_directory(html_opening =False)
2695 else:
2696
2697 self.configure_directory(html_opening =False)
2698 MA5_opts = self.check_madanalysis5(args, mode=mode)
2699
2700
2701 if MA5_opts['inputs']==[]:
2702 if no_default:
2703 logger.warning('No hadron level input found to run MadAnalysis5 on.'+
2704 ' Skipping its hadron-level analysis.')
2705 return
2706 else:
2707 raise self.InvalidCmd('\nNo input files specified or availabled for'+
2708 ' this MadAnalysis5 hadron-level run.\nPlease double-check the options of this'+
2709 ' MA5 command (or card) and which output files\nare currently in the chosen'+
2710 " run directory '%s'."%self.run_name)
2711
2712 MA5_card = banner_mod.MadAnalysis5Card(pjoin(self.me_dir, 'Cards',
2713 'madanalysis5_%s_card.dat'%mode), mode=mode)
2714
2715 if MA5_card._skip_analysis:
2716 logger.info('Madanalysis5 %s-level analysis was skipped following user request.'%mode)
2717 logger.info("To run the analysis, remove or comment the tag '%s skip_analysis' "
2718 %banner_mod.MadAnalysis5Card._MG5aMC_escape_tag+
2719 "in\n '%s'."%pjoin(self.me_dir, 'Cards','madanalysis5_%s_card.dat'%mode))
2720 return
2721
2722 MA5_cmds_list = MA5_card.get_MA5_cmds(MA5_opts['inputs'],
2723 pjoin(self.me_dir,'MA5_%s_ANALYSIS'%mode.upper()),
2724 run_dir_path = pjoin(self.me_dir,'Events', self.run_name),
2725 UFO_model_path=pjoin(self.me_dir,'bin','internal','ufomodel'),
2726 run_tag = self.run_tag)
2727
2728
2729
2730
2731
2732
2733
2734
2735 self.update_status('\033[92mRunning MadAnalysis5 [arXiv:1206.1599]\033[0m',
2736 level='madanalysis5_%s'%mode)
2737 if mode=='hadron':
2738 logger.info('Hadron input files considered:')
2739 for input in MA5_opts['inputs']:
2740 logger.info(' --> %s'%input)
2741 elif mode=='parton':
2742 logger.info('Parton input file considered:')
2743 logger.info(' --> %s'%MA5_opts['inputs'])
2744
2745
2746
2747
2748 if MA5_opts['MA5_stdout_lvl']=='default':
2749 if MA5_card['stdout_lvl'] is None:
2750 MA5_lvl = self.options['stdout_level']
2751 else:
2752 MA5_lvl = MA5_card['stdout_lvl']
2753 else:
2754 MA5_lvl = MA5_opts['MA5_stdout_lvl']
2755
2756
2757 MA5_interpreter = CommonRunCmd.get_MadAnalysis5_interpreter(
2758 self.options['mg5_path'],
2759 self.options['madanalysis5_path'],
2760 logstream=sys.stdout,
2761 loglevel=100,
2762 forced=True,
2763 compilation=True)
2764
2765
2766
2767 if MA5_interpreter is None:
2768 return
2769
2770
2771 used_up_fifos = []
2772
2773 for MA5_run_number, (MA5_runtag, MA5_cmds) in enumerate(MA5_cmds_list):
2774
2775
2776
2777 MA5_run_number = 0
2778
2779 MA5_interpreter.setLogLevel(100)
2780
2781 if mode=='hadron':
2782 MA5_interpreter.init_reco()
2783 else:
2784 MA5_interpreter.init_parton()
2785 MA5_interpreter.setLogLevel(MA5_lvl)
2786
2787 if MA5_runtag!='default':
2788 if MA5_runtag.startswith('_reco_'):
2789 logger.info("MadAnalysis5 now running the reconstruction '%s'..."%
2790 MA5_runtag[6:],'$MG:color:GREEN')
2791 elif MA5_runtag=='Recasting':
2792 logger.info("MadAnalysis5 now running the recasting...",
2793 '$MG:color:GREEN')
2794 else:
2795 logger.info("MadAnalysis5 now running the '%s' analysis..."%
2796 MA5_runtag,'$MG:color:GREEN')
2797
2798
2799
2800 if not CommonRunCmd.runMA5(MA5_interpreter, MA5_cmds, MA5_runtag,
2801 pjoin(self.me_dir,'Events',self.run_name,'%s_MA5_%s.log'%(self.run_tag,MA5_runtag))):
2802
2803 return
2804
2805 if MA5_runtag.startswith('_reco_'):
2806
2807
2808
2809
2810 links_created=[]
2811 for i, input in enumerate(MA5_opts['inputs']):
2812
2813
2814 if not banner_mod.MadAnalysis5Card.events_can_be_reconstructed(input):
2815 continue
2816
2817 if input.endswith('.fifo'):
2818 if input in used_up_fifos:
2819
2820 continue
2821 else:
2822 used_up_fifos.append(input)
2823
2824 reco_output = pjoin(self.me_dir,
2825 'MA5_%s_ANALYSIS%s_%d'%(mode.upper(),MA5_runtag,i+1))
2826
2827 reco_event_file = misc.glob('*.lhe.gz',pjoin(reco_output,'Output','_reco_events','lheEvents0_%d'%MA5_run_number))+\
2828 misc.glob('*.root',pjoin(reco_output,'Output','_reco_events', 'RecoEvents0_%d'%MA5_run_number))
2829 if len(reco_event_file)==0:
2830 raise MadGraph5Error, "MadAnalysis5 failed to produce the "+\
2831 "reconstructed event file for reconstruction '%s'."%MA5_runtag[6:]
2832 reco_event_file = reco_event_file[0]
2833
2834 shutil.move(reco_output,pjoin(self.me_dir,'HTML',
2835 self.run_name,'%s_MA5_%s_ANALYSIS%s_%d'%
2836 (self.run_tag,mode.upper(),MA5_runtag,i+1)))
2837
2838
2839 links_created.append(os.path.basename(reco_event_file))
2840 parent_dir_name = os.path.basename(os.path.dirname(reco_event_file))
2841 files.ln(pjoin(self.me_dir,'HTML',self.run_name,
2842 '%s_MA5_%s_ANALYSIS%s_%d'%(self.run_tag,mode.upper(),
2843 MA5_runtag,i+1),'Output','_reco_events',parent_dir_name,links_created[-1]),
2844 pjoin(self.me_dir,'Events',self.run_name))
2845
2846 logger.info("MadAnalysis5 successfully completed the reconstruction "+
2847 "'%s'. Links to the reconstructed event files are:"%MA5_runtag[6:])
2848 for link in links_created:
2849 logger.info(' --> %s'%pjoin(self.me_dir,'Events',self.run_name,link))
2850 continue
2851
2852 if MA5_runtag.upper()=='RECASTING':
2853 target = pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s'\
2854 %(mode.upper(),MA5_runtag),'Output','CLs_output_summary.dat')
2855 else:
2856 target = pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s'\
2857 %(mode.upper(),MA5_runtag),'Output','PDF','MadAnalysis5job_%d'%MA5_run_number,'main.pdf')
2858 has_pdf = True
2859 if not os.path.isfile(target):
2860 has_pdf = False
2861
2862
2863 if MA5_runtag.upper()=='RECASTING':
2864 carboncopy_name = '%s_MA5_CLs.dat'%(self.run_tag)
2865 else:
2866 carboncopy_name = '%s_MA5_%s_analysis_%s.pdf'%(
2867 self.run_tag,mode,MA5_runtag)
2868 if has_pdf:
2869 shutil.copy(target, pjoin(self.me_dir,'Events',self.run_name,carboncopy_name))
2870 else:
2871 logger.error('MadAnalysis5 failed to create PDF output')
2872 if MA5_runtag!='default':
2873 logger.info("MadAnalysis5 successfully completed the "+
2874 "%s. Reported results are placed in:"%("analysis '%s'"%MA5_runtag
2875 if MA5_runtag.upper()!='RECASTING' else "recasting"))
2876 else:
2877 logger.info("MadAnalysis5 successfully completed the analysis."+
2878 " Reported results are placed in:")
2879 logger.info(' --> %s'%pjoin(self.me_dir,'Events',self.run_name,carboncopy_name))
2880
2881 anal_dir = pjoin(self.me_dir,'MA5_%s_ANALYSIS_%s' %(mode.upper(),MA5_runtag))
2882 if not os.path.exists(anal_dir):
2883 logger.error('MadAnalysis5 failed to completed succesfully')
2884 return
2885
2886 shutil.move(anal_dir, pjoin(self.me_dir,'HTML',self.run_name,
2887 '%s_MA5_%s_ANALYSIS_%s'%(self.run_tag,mode.upper(),MA5_runtag)))
2888
2889
2890
2891 new_details={}
2892 for detail in ['nb_event','cross','error']:
2893 new_details[detail] = \
2894 self.results[self.run_name].get_current_info()[detail]
2895 for detail in new_details:
2896 self.results.add_detail(detail,new_details[detail])
2897
2898 self.update_status('Finished MA5 analyses.', level='madanalysis5_%s'%mode,
2899 makehtml=False)
2900
2901
2902 self.banner.add(pjoin(self.me_dir, 'Cards',
2903 'madanalysis5_%s_card.dat'%mode))
2904 banner_path = pjoin(self.me_dir,'Events', self.run_name,
2905 '%s_%s_banner.txt'%(self.run_name, self.run_tag))
2906 self.banner.write(banner_path)
2907
2908 if not no_default:
2909 logger.info('Find more information about this run on the HTML local page')
2910 logger.info(' --> %s'%pjoin(self.me_dir,'index.html'))
2911
2912
2913
2914
2915
2917 """ run delphes and make associate root file/plot """
2918
2919 args = self.split_arg(line)
2920
2921 if '--no_default' in args:
2922 no_default = True
2923 args.remove('--no_default')
2924 else:
2925 no_default = False
2926
2927 if no_default and not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')):
2928 logger.info('No delphes_card detected, so not run Delphes')
2929 return
2930
2931
2932 filepath = self.check_delphes(args, nodefault=no_default)
2933 if no_default and not filepath:
2934 return
2935
2936 self.update_status('prepare delphes run', level=None)
2937
2938 if os.path.exists(pjoin(self.options['delphes_path'], 'data')):
2939 delphes3 = False
2940 prog = '../bin/internal/run_delphes'
2941 if filepath and '.hepmc' in filepath[:-10]:
2942 raise self.InvalidCmd, 'delphes2 do not support hepmc'
2943 else:
2944 delphes3 = True
2945 prog = '../bin/internal/run_delphes3'
2946
2947
2948
2949 if not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_card.dat')):
2950 if no_default:
2951 logger.info('No delphes_card detected, so not running Delphes')
2952 return
2953 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_card_default.dat'),
2954 pjoin(self.me_dir, 'Cards', 'delphes_card.dat'))
2955 logger.info('No delphes card found. Take the default one.')
2956 if not delphes3 and not os.path.exists(pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat')):
2957 files.cp(pjoin(self.me_dir, 'Cards', 'delphes_trigger_default.dat'),
2958 pjoin(self.me_dir, 'Cards', 'delphes_trigger.dat'))
2959 if not (no_default or self.force):
2960 if delphes3:
2961 self.ask_edit_cards(['delphes_card.dat'], args)
2962 else:
2963 self.ask_edit_cards(['delphes_card.dat', 'delphes_trigger.dat'], args)
2964
2965 self.update_status('Running Delphes', level=None)
2966
2967 delphes_dir = self.options['delphes_path']
2968 tag = self.run_tag
2969 if os.path.exists(pjoin(self.me_dir, 'Source', 'banner_header.txt')):
2970 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_card.dat'))
2971 if not delphes3:
2972 self.banner.add(pjoin(self.me_dir, 'Cards','delphes_trigger.dat'))
2973 self.banner.write(pjoin(self.me_dir, 'Events', self.run_name, '%s_%s_banner.txt' % (self.run_name, tag)))
2974
2975 cross = self.results[self.run_name].get_current_info()['cross']
2976
2977 delphes_log = pjoin(self.me_dir, 'Events', self.run_name, "%s_delphes.log" % tag)
2978 if not self.cluster:
2979 clus = cluster.onecore
2980 else:
2981 clus = self.cluster
2982 clus.launch_and_wait(prog,
2983 argument= [delphes_dir, self.run_name, tag, str(cross), filepath],
2984 stdout=delphes_log, stderr=subprocess.STDOUT,
2985 cwd=pjoin(self.me_dir,'Events'))
2986
2987 if not os.path.exists(pjoin(self.me_dir, 'Events',
2988 self.run_name, '%s_delphes_events.lhco.gz' % tag))\
2989 and not os.path.exists(pjoin(self.me_dir, 'Events',
2990 self.run_name, '%s_delphes_events.lhco' % tag)):
2991 logger.info('If you are interested in lhco output. please run root2lhco converter.')
2992 logger.info(' or edit bin/internal/run_delphes3 to run the converter automatically.')
2993
2994
2995
2996 madir = self.options['madanalysis_path']
2997 td = self.options['td_path']
2998
2999 if os.path.exists(pjoin(self.me_dir, 'Events',
3000 self.run_name, '%s_delphes_events.lhco' % tag)):
3001
3002 self.create_plot('Delphes')
3003
3004 if os.path.exists(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag)):
3005 misc.gzip(pjoin(self.me_dir, 'Events', self.run_name, '%s_delphes_events.lhco' % tag))
3006
3007 self.update_status('delphes done', level='delphes', makehtml=False)
3008
3009
3010
3012 """Find the pid of all particles in the final and initial states"""
3013 pids = set()
3014 subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
3015 'subproc.mg'))]
3016 nb_init = self.ninitial
3017 pat = re.compile(r'''DATA \(IDUP\(I,\d+\),I=1,\d+\)/([\+\-\d,\s]*)/''', re.I)
3018 for Pdir in subproc:
3019 text = open(pjoin(self.me_dir, 'SubProcesses', Pdir, 'born_leshouche.inc')).read()
3020 group = pat.findall(text)
3021 for particles in group:
3022 particles = particles.split(',')
3023 pids.update(set(particles))
3024
3025 return pids
3026
3027
3052
3053
3054 if hasattr(self, 'pdffile') and self.pdffile:
3055 return self.pdffile
3056 else:
3057 for line in open(pjoin(self.me_dir,'Source','PDF','pdf_list.txt')):
3058 data = line.split()
3059 if len(data) < 4:
3060 continue
3061 if data[1].lower() == self.run_card['pdlabel'].lower():
3062 self.pdffile = check_cluster(pjoin(self.me_dir, 'lib', 'Pdfdata', data[2]))
3063 return self.pdffile
3064 else:
3065
3066 path = pjoin(self.me_dir, 'lib', 'PDFsets')
3067 if os.path.exists(path):
3068 self.pdffile = path
3069 else:
3070 self.pdffile = " "
3071 return self.pdffile
3072
3073
3083
3084
3085 - def do_set(self, line, log=True):
3086 """Set an option, which will be default for coming generations/outputs
3087 """
3088
3089
3090
3091 args = self.split_arg(line)
3092
3093 self.check_set(args)
3094
3095 if args[0] in self.options_configuration and '--no_save' not in args:
3096 self.do_save('options --auto')
3097
3098 if args[0] == "stdout_level":
3099 if args[1].isdigit():
3100 logging.root.setLevel(int(args[1]))
3101 logging.getLogger('madgraph').setLevel(int(args[1]))
3102 else:
3103 logging.root.setLevel(eval('logging.' + args[1]))
3104 logging.getLogger('madgraph').setLevel(eval('logging.' + args[1]))
3105 if log: logger.info('set output information to level: %s' % args[1])
3106 elif args[0] == "fortran_compiler":
3107 if args[1] == 'None':
3108 args[1] = None
3109 self.options['fortran_compiler'] = args[1]
3110 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'fortran')
3111 if current != args[1] and args[1] != None:
3112 misc.mod_compilator(self.me_dir, args[1], current, 'gfortran')
3113 elif args[0] == "cpp_compiler":
3114 if args[1] == 'None':
3115 args[1] = None
3116 self.options['cpp_compiler'] = args[1]
3117 current = misc.detect_current_compiler(pjoin(self.me_dir,'Source','make_opts'), 'cpp')
3118 if current != args[1] and args[1] != None:
3119 misc.mod_compilator(self.me_dir, args[1], current, 'cpp')
3120 elif args[0] == "run_mode":
3121 if not args[1] in [0,1,2,'0','1','2']:
3122 raise self.InvalidCmd, 'run_mode should be 0, 1 or 2.'
3123 self.cluster_mode = int(args[1])
3124 self.options['run_mode'] = self.cluster_mode
3125 elif args[0] in ['cluster_type', 'cluster_queue', 'cluster_temp_path']:
3126 if args[1] == 'None':
3127 args[1] = None
3128 self.options[args[0]] = args[1]
3129
3130
3131 elif args[0] in ['cluster_nb_retry', 'cluster_retry_wait', 'cluster_size']:
3132 self.options[args[0]] = int(args[1])
3133
3134 elif args[0] == 'nb_core':
3135 if args[1] == 'None':
3136 import multiprocessing
3137 self.nb_core = multiprocessing.cpu_count()
3138 self.options['nb_core'] = self.nb_core
3139 return
3140 if not args[1].isdigit():
3141 raise self.InvalidCmd('nb_core should be a positive number')
3142 self.nb_core = int(args[1])
3143 self.options['nb_core'] = self.nb_core
3144 elif args[0] == 'timeout':
3145 self.options[args[0]] = int(args[1])
3146 elif args[0] == 'cluster_status_update':
3147 if '(' in args[1]:
3148 data = ' '.join([a for a in args[1:] if not a.startswith('-')])
3149 data = data.replace('(','').replace(')','').replace(',',' ').split()
3150 first, second = data[:2]
3151 else:
3152 first, second = args[1:3]
3153
3154 self.options[args[0]] = (int(first), int(second))
3155 elif args[0] == 'notification_center':
3156 if args[1] in ['None','True','False']:
3157 self.allow_notification_center = eval(args[1])
3158 self.options[args[0]] = eval(args[1])
3159 else:
3160 raise self.InvalidCmd('Not a valid value for notification_center')
3161
3162 elif args[0] in ['crash_on_error']:
3163 tmp = banner_mod.ConfigFile.format_variable(args[1], bool, 'crash_on_error')
3164 self.options[args[0]] = tmp
3165 elif args[0] in self.options:
3166 if args[1] in ['None','True','False']:
3167 self.options[args[0]] = ast.literal_eval(args[1])
3168 elif args[0].endswith('path'):
3169 if os.path.exists(args[1]):
3170 self.options[args[0]] = args[1]
3171 elif os.path.exists(pjoin(self.me_dir, args[1])):
3172 self.options[args[0]] = pjoin(self.me_dir, args[1])
3173 else:
3174 raise self.InvalidCmd('Not a valid path: keep previous value: \'%s\'' % self.options[args[0]])
3175 else:
3176 self.options[args[0]] = args[1]
3177
3178 - def post_set(self, stop, line):
3179 """Check if we need to save this in the option file"""
3180 try:
3181 args = self.split_arg(line)
3182 if 'cluster' in args[0] or args[0] == 'run_mode':
3183 self.configure_run_mode(self.options['run_mode'])
3184
3185
3186
3187 self.check_set(args)
3188
3189 if args[0] in self.options_configuration and '--no_save' not in args:
3190 self.exec_cmd('save options %s --auto' % args[0])
3191 elif args[0] in self.options_madevent:
3192 logger.info('This option will be the default in any output that you are going to create in this session.')
3193 logger.info('In order to keep this changes permanent please run \'save options\'')
3194 return stop
3195 except self.InvalidCmd:
3196 return stop
3197
3234
3236 """
3237 1) Check that no scan parameter are present
3238 2) Check that all the width are define in the param_card.
3239 - If a scan parameter is define. create the iterator and recall this fonction
3240 on the first element.
3241 - If some width are set on 'Auto', call the computation tools.
3242 - Check that no width are too small (raise a warning if this is the case)
3243 3) if dependent is on True check for dependent parameter (automatic for scan)"""
3244
3245 self.static_check_param_card(path, self, run=run, dependent=dependent)
3246
3247 card = param_card_mod.ParamCard(path)
3248 for param in card['decay']:
3249 width = param.value
3250 if width == 0:
3251 continue
3252 try:
3253 mass = card['mass'].get(param.lhacode).value
3254 except Exception:
3255 continue
3256
3257
3258
3259 @staticmethod
3262 pattern_scan = re.compile(r'''^(decay)?[\s\d]*scan''', re.I+re.M)
3263 pattern_width = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I)
3264 text = open(path).read()
3265
3266 if pattern_scan.search(text):
3267 if not isinstance(interface, cmd.CmdShell):
3268
3269 raise Exception, "Scan are not allowed in web mode"
3270
3271 main_card = iterator_class(text)
3272 interface.param_card_iterator = main_card
3273 first_card = main_card.next(autostart=True)
3274 first_card.write(path)
3275 return CommonRunCmd.static_check_param_card(path, interface, run, dependent=True)
3276
3277 pdg_info = pattern_width.findall(text)
3278 if pdg_info:
3279 if run:
3280 logger.info('Computing the width set on auto in the param_card.dat')
3281 has_nlo = any(nlo.lower()=="@nlo" for _,nlo in pdg_info)
3282 pdg = [pdg for pdg,nlo in pdg_info]
3283 if not has_nlo:
3284 line = '%s' % (' '.join(pdg))
3285 else:
3286 line = '%s --nlo' % (' '.join(pdg))
3287 CommonRunCmd.static_compute_widths(line, interface, path)
3288 else:
3289 logger.info('''Some width are on Auto in the card.
3290 Those will be computed as soon as you have finish the edition of the cards.
3291 If you want to force the computation right now and being able to re-edit
3292 the cards afterwards, you can type \"compute_wdiths\".''')
3293
3294 card = param_card_mod.ParamCard(path)
3295 if dependent:
3296 AskforEditCard.update_dependent(interface, interface.me_dir, card, path, timer=20)
3297
3298 for param in card['decay']:
3299 width = param.value
3300 if width == 0:
3301 continue
3302 try:
3303 mass = card['mass'].get(param.lhacode).value
3304 except Exception:
3305 logger.warning('Missing mass in the lhef file (%s) . Please fix this (use the "update missing" command if needed)', param.lhacode[0])
3306 continue
3307 if mass and abs(width/mass) < 1e-12:
3308 logger.error('The width of particle %s is too small for an s-channel resonance (%s). If you have this particle in an s-channel, this is likely to create numerical instabilities .', param.lhacode[0], width)
3309 if CommonRunCmd.sleep_for_error:
3310 time.sleep(5)
3311 CommonRunCmd.sleep_for_error = False
3312 elif not mass and width:
3313 logger.error('The width of particle %s is different of zero for a massless particle.', param.lhacode[0])
3314 if CommonRunCmd.sleep_for_error:
3315 time.sleep(5)
3316 CommonRunCmd.sleep_for_error = False
3317 return
3318
3319 @staticmethod
3321 """ factory to try to find a way to call the static method"""
3322
3323 handled = True
3324 if isinstance(interface, CommonRunCmd):
3325 if path:
3326 line = '%s %s' % (line, path)
3327 interface.do_compute_widths(line)
3328 else:
3329 handled = False
3330
3331 if handled:
3332 return
3333
3334 if hasattr(interface, 'do_compute_width'):
3335 interface.do_compute_widths('%s --path=%s' % (line, path))
3336 elif hasattr(interface, 'mother') and interface.mother and isinstance(interface, CommonRunCmd):
3337 return CommonRunCmd.static_compute_width(line, interface.mother, path)
3338 elif not MADEVENT:
3339 from madgraph.interface.master_interface import MasterCmd
3340 cmd = MasterCmd()
3341 interface.define_child_cmd_interface(cmd, interface=False)
3342 if hasattr(interface, 'options'):
3343 cmd.options.update(interface.options)
3344 try:
3345 cmd.exec_cmd('set automatic_html_opening False --no_save')
3346 except Exception:
3347 pass
3348
3349 model = interface.get_model()
3350
3351
3352 line = 'compute_widths %s --path=%s' % (line, path)
3353 cmd.exec_cmd(line, model=model)
3354 interface.child = None
3355 del cmd
3356 return
3357
3358
3359
3360 raise Exception, 'fail to find a way to handle Auto width'
3361
3362
3364 """return the information that need to be kept for the scan summary.
3365 Auto-width are automatically added."""
3366
3367 return {'cross': self.results.current['cross']}
3368
3369
3371 """If a ME run is currently running add a link in the html output"""
3372
3373
3374
3375 if hasattr(self, 'results') and hasattr(self.results, 'current') and\
3376 self.results.current and 'run_name' in self.results.current and \
3377 hasattr(self, 'me_dir'):
3378 name = self.results.current['run_name']
3379 tag = self.results.current['tag']
3380 self.debug_output = pjoin(self.me_dir, '%s_%s_debug.log' % (name,tag))
3381 if errortype:
3382 self.results.current.debug = errortype
3383 else:
3384 self.results.current.debug = self.debug_output
3385
3386 else:
3387
3388 self.debug_output = CommonRunCmd.debug_output
3389 if os.path.exists('ME5_debug') and not 'ME5_debug' in self.debug_output:
3390 try:
3391 os.remove('ME5_debug')
3392 except Exception:
3393 pass
3394 if not 'ME5_debug' in self.debug_output:
3395 os.system('ln -s %s ME5_debug &> /dev/null' % self.debug_output)
3396
3397
3399 """Not in help: exit """
3400
3401 if not self.force_run:
3402 try:
3403 os.remove(pjoin(self.me_dir,'RunWeb'))
3404 except Exception:
3405 pass
3406
3407 try:
3408 self.store_result()
3409 except Exception:
3410
3411 pass
3412
3413 try:
3414 self.update_status('', level=None)
3415 except Exception, error:
3416 pass
3417
3418 self.gen_card_html()
3419 return super(CommonRunCmd, self).do_quit(line)
3420
3421
3422 do_EOF = do_quit
3423 do_exit = do_quit
3424
3426 """try to remove RunWeb?"""
3427
3428 if not self.stop_for_runweb and not self.force_run:
3429 try:
3430 os.remove(pjoin(self.me_dir,'RunWeb'))
3431 except Exception:
3432 pass
3433
3434
3435 - def update_status(self, status, level, makehtml=True, force=True,
3436 error=False, starttime = None, update_results=True,
3437 print_log=True):
3438 """ update the index status """
3439
3440 if makehtml and not force:
3441 if hasattr(self, 'next_update') and time.time() < self.next_update:
3442 return
3443 else:
3444 self.next_update = time.time() + 3
3445
3446 if print_log:
3447 if isinstance(status, str):
3448 if '<br>' not in status:
3449 logger.info(status)
3450 elif starttime:
3451 running_time = misc.format_timer(time.time()-starttime)
3452 logger.info(' Idle: %s, Running: %s, Completed: %s [ %s ]' % \
3453 (status[0], status[1], status[2], running_time))
3454 else:
3455 logger.info(' Idle: %s, Running: %s, Completed: %s' % status[:3])
3456
3457 if isinstance(status, str) and status.startswith('\x1b['):
3458 status = status[status.index('m')+1:-7]
3459 if 'arXiv' in status:
3460 if '[' in status:
3461 status = status.split('[',1)[0]
3462 else:
3463 status = status.split('arXiv',1)[0]
3464
3465 if update_results:
3466 self.results.update(status, level, makehtml=makehtml, error=error)
3467
3468
3470 """Ask the question when launching generate_events/multi_run"""
3471
3472 check_card = ['pythia_card.dat', 'pgs_card.dat','delphes_card.dat',
3473 'delphes_trigger.dat', 'madspin_card.dat', 'shower_card.dat',
3474 'reweight_card.dat','pythia8_card.dat',
3475 'madanalysis5_parton_card.dat','madanalysis5_hadron_card.dat',
3476 'plot_card.dat']
3477
3478 cards_path = pjoin(self.me_dir,'Cards')
3479 for card in check_card:
3480 if card in ignore or (ignore == ['*'] and card not in need_card):
3481 continue
3482 if card not in need_card:
3483 if os.path.exists(pjoin(cards_path, card)):
3484 files.mv(pjoin(cards_path, card), pjoin(cards_path, '.%s' % card))
3485 else:
3486 if not os.path.exists(pjoin(cards_path, card)):
3487 if os.path.exists(pjoin(cards_path, '.%s' % card)):
3488 files.mv(pjoin(cards_path, '.%s' % card), pjoin(cards_path, card))
3489 else:
3490 default = card.replace('.dat', '_default.dat')
3491 files.cp(pjoin(cards_path, default),pjoin(cards_path, card))
3492
3493
3494 - def set_configuration(self, config_path=None, final=True, initdir=None, amcatnlo=False):
3495 """ assign all configuration variable from file
3496 ./Cards/mg5_configuration.txt. assign to default if not define """
3497
3498 if not hasattr(self, 'options') or not self.options:
3499 self.options = dict(self.options_configuration)
3500 self.options.update(self.options_madgraph)
3501 self.options.update(self.options_madevent)
3502
3503 if not config_path:
3504 if os.environ.has_key('MADGRAPH_BASE'):
3505 config_path = pjoin(os.environ['MADGRAPH_BASE'],'mg5_configuration.txt')
3506 self.set_configuration(config_path=config_path, final=False)
3507 if 'HOME' in os.environ:
3508 config_path = pjoin(os.environ['HOME'],'.mg5',
3509 'mg5_configuration.txt')
3510 if os.path.exists(config_path):
3511 self.set_configuration(config_path=config_path, final=False)
3512 if amcatnlo:
3513 me5_config = pjoin(self.me_dir, 'Cards', 'amcatnlo_configuration.txt')
3514 else:
3515 me5_config = pjoin(self.me_dir, 'Cards', 'me5_configuration.txt')
3516 self.set_configuration(config_path=me5_config, final=False, initdir=self.me_dir)
3517
3518 if self.options.has_key('mg5_path') and self.options['mg5_path']:
3519 MG5DIR = self.options['mg5_path']
3520 config_file = pjoin(MG5DIR, 'input', 'mg5_configuration.txt')
3521 self.set_configuration(config_path=config_file, final=False,initdir=MG5DIR)
3522 else:
3523 self.options['mg5_path'] = None
3524 return self.set_configuration(config_path=me5_config, final=final,initdir=self.me_dir)
3525
3526 config_file = open(config_path)
3527
3528
3529 logger.info('load configuration from %s ' % config_file.name)
3530 for line in config_file:
3531
3532 if '#' in line:
3533 line = line.split('#',1)[0]
3534 line = line.replace('\n','').replace('\r\n','')
3535 try:
3536 name, value = line.split('=')
3537 except ValueError:
3538 pass
3539 else:
3540 name = name.strip()
3541 value = value.strip()
3542 if name.endswith('_path') and not name.startswith('cluster'):
3543 path = value
3544 if os.path.isdir(path):
3545 self.options[name] = os.path.realpath(path)
3546 continue
3547 if not initdir:
3548 continue
3549 path = pjoin(initdir, value)
3550 if os.path.isdir(path):
3551 self.options[name] = os.path.realpath(path)
3552 continue
3553 else:
3554 self.options[name] = value
3555 if value.lower() == "none":
3556 self.options[name] = None
3557
3558 if not final:
3559 return self.options
3560
3561
3562
3563 for key in self.options:
3564
3565 if key.endswith('path') and not key.startswith("cluster"):
3566 path = self.options[key]
3567 if path is None:
3568 continue
3569 if os.path.isdir(path):
3570 self.options[key] = os.path.realpath(path)
3571 continue
3572 path = pjoin(self.me_dir, self.options[key])
3573 if os.path.isdir(path):
3574 self.options[key] = os.path.realpath(path)
3575 continue
3576 elif self.options.has_key('mg5_path') and self.options['mg5_path']:
3577 path = pjoin(self.options['mg5_path'], self.options[key])
3578 if os.path.isdir(path):
3579 self.options[key] = os.path.realpath(path)
3580 continue
3581 self.options[key] = None
3582 elif key.startswith('cluster') and key != 'cluster_status_update':
3583 if key in ('cluster_nb_retry','cluster_wait_retry'):
3584 self.options[key] = int(self.options[key])
3585 if hasattr(self,'cluster'):
3586 del self.cluster
3587 pass
3588 elif key == 'automatic_html_opening':
3589 if self.options[key] in ['False', 'True']:
3590 self.options[key] =ast.literal_eval(self.options[key])
3591 elif key == "notification_center":
3592 if self.options[key] in ['False', 'True']:
3593 self.allow_notification_center =ast.literal_eval(self.options[key])
3594 self.options[key] =ast.literal_eval(self.options[key])
3595 elif key not in ['text_editor','eps_viewer','web_browser','stdout_level',
3596 'complex_mass_scheme', 'gauge', 'group_subprocesses']:
3597
3598 try:
3599 self.do_set("%s %s --no_save" % (key, self.options[key]), log=False)
3600 except self.InvalidCmd:
3601 logger.warning("Option %s from config file not understood" \
3602 % key)
3603
3604
3605 misc.open_file.configure(self.options)
3606 self.configure_run_mode(self.options['run_mode'])
3607 return self.options
3608
3609 @staticmethod
3611 """ find a valid run_name for the current job """
3612
3613 name = 'run_%02d'
3614 data = [int(s[4:j]) for s in os.listdir(pjoin(me_dir,'Events')) for
3615 j in range(4,len(s)+1) if \
3616 s.startswith('run_') and s[4:j].isdigit()]
3617 return name % (max(data+[0])+1)
3618
3619
3620
3622 """Require MG5 directory: decay events with spin correlations
3623 """
3624
3625 if '-from_cards' in line and not os.path.exists(pjoin(self.me_dir, 'Cards', 'madspin_card.dat')):
3626 return
3627
3628
3629
3630 if MADEVENT and not self.options['mg5_path']:
3631 raise self.InvalidCmd, '''The module decay_events requires that MG5 is installed on the system.
3632 You can install it and set its path in ./Cards/me5_configuration.txt'''
3633 elif MADEVENT:
3634 sys.path.append(self.options['mg5_path'])
3635 try:
3636 import MadSpin.decay as decay
3637 import MadSpin.interface_madspin as interface_madspin
3638 except ImportError:
3639 if __debug__:
3640 raise
3641 else:
3642 raise self.ConfigurationError, '''Can\'t load MadSpin
3643 The variable mg5_path might not be correctly configured.'''
3644
3645 self.update_status('Running MadSpin', level='madspin')
3646 if not '-from_cards' in line and '-f' not in line:
3647 self.keep_cards(['madspin_card.dat'], ignore=['*'])
3648 self.ask_edit_cards(['madspin_card.dat'], 'fixed', plot=False)
3649 self.help_decay_events(skip_syntax=True)
3650
3651
3652 args = self.split_arg(line)
3653 self.check_decay_events(args)
3654
3655 madspin_cmd = interface_madspin.MadSpinInterface(args[0])
3656
3657 madspin_cmd.mg5cmd.options.update(self.options)
3658 for key, value in self.options.items():
3659 if isinstance(value, str):
3660 madspin_cmd.mg5cmd.exec_cmd( 'set %s %s' %(key,value), errorhandling=False, printcmd=False, precmd=False, postcmd=True)
3661 madspin_cmd.cluster = self.cluster
3662
3663 madspin_cmd.update_status = lambda *x,**opt: self.update_status(*x, level='madspin',**opt)
3664
3665 path = pjoin(self.me_dir, 'Cards', 'madspin_card.dat')
3666
3667 madspin_cmd.import_command_file(path)
3668
3669
3670 i = 1
3671 while os.path.exists(pjoin(self.me_dir,'Events', '%s_decayed_%i' % (self.run_name,i))):
3672 i+=1
3673 new_run = '%s_decayed_%i' % (self.run_name,i)
3674 evt_dir = pjoin(self.me_dir, 'Events')
3675
3676 os.mkdir(pjoin(evt_dir, new_run))
3677 current_file = args[0].replace('.lhe', '_decayed.lhe')
3678 new_file = pjoin(evt_dir, new_run, os.path.basename(args[0]))
3679 if not os.path.exists(current_file):
3680 if os.path.exists(current_file+'.gz'):
3681 current_file += '.gz'
3682 new_file += '.gz'
3683 elif current_file.endswith('.gz') and os.path.exists(current_file[:-3]):
3684 current_file = current_file[:-3]
3685 new_file = new_file[:-3]
3686 else:
3687 logger.error('MadSpin fails to create any decayed file.')
3688 return
3689
3690 files.mv(current_file, new_file)
3691 logger.info("The decayed event file has been moved to the following location: ")
3692 logger.info(new_file)
3693
3694 if hasattr(self, 'results'):
3695 current = self.results.current
3696 nb_event = self.results.current['nb_event']
3697 if not nb_event:
3698 current = self.results[self.run_name][0]
3699 nb_event = current['nb_event']
3700
3701 cross = current['cross']
3702 error = current['error']
3703 self.results.add_run( new_run, self.run_card)
3704 self.results.add_detail('nb_event', int(nb_event*madspin_cmd.efficiency))
3705 self.results.add_detail('cross', madspin_cmd.cross)
3706 self.results.add_detail('error', madspin_cmd.error+ cross * madspin_cmd.err_branching_ratio)
3707 self.results.add_detail('run_mode', current['run_mode'])
3708 self.to_store.append("event")
3709
3710 self.run_name = new_run
3711 self.banner = madspin_cmd.banner
3712 self.banner.add(path)
3713 self.banner.write(pjoin(self.me_dir,'Events',self.run_name, '%s_%s_banner.txt' %
3714 (self.run_name, self.run_tag)))
3715 self.update_status('MadSpin Done', level='parton', makehtml=False)
3716 if 'unweighted' in os.path.basename(args[0]):
3717 self.create_plot('parton')
3718
3725
3727 "Complete the print results command"
3728 args = self.split_arg(line[0:begidx], error=False)
3729 if len(args) == 1:
3730
3731 data = misc.glob(pjoin('*','unweighted_events.lhe.gz'),
3732 pjoin(self.me_dir, 'Events'))
3733
3734 data = [n.rsplit('/',2)[1] for n in data]
3735 tmp1 = self.list_completion(text, data)
3736 return tmp1
3737 else:
3738 data = misc.glob('*_pythia_events.hep.gz', pjoin(self.me_dir, 'Events', args[0]))
3739 data = [os.path.basename(p).rsplit('_',1)[0] for p in data]
3740 data += ["--mode=a", "--mode=w", "--path=", "--format=short"]
3741 tmp1 = self.list_completion(text, data)
3742 return tmp1
3743
3745 logger.info("syntax: print_result [RUN] [TAG] [options]")
3746 logger.info("-- show in text format the status of the run (cross-section/nb-event/...)")
3747 logger.info("--path= defines the path of the output file.")
3748 logger.info("--mode=a allow to add the information at the end of the file.")
3749 logger.info("--format=short (only if --path is define)")
3750 logger.info(" allows to have a multi-column output easy to parse")
3751
3752
3753
3755 """ return the model name """
3756 if hasattr(self, 'model_name'):
3757 return self.model_name
3758
3759 def join_line(old, to_add):
3760 if old.endswith('\\'):
3761 newline = old[:-1] + to_add
3762 else:
3763 newline = old + line
3764 return newline
3765
3766
3767
3768 model = 'sm'
3769 proc = []
3770 continuation_line = None
3771 for line in open(os.path.join(self.me_dir,'Cards','proc_card_mg5.dat')):
3772 line = line.split('#')[0]
3773 if continuation_line:
3774 line = line.strip()
3775 if continuation_line == 'model':
3776 model = join_line(model, line)
3777 elif continuation_line == 'proc':
3778 proc = join_line(proc, line)
3779 if not line.endswith('\\'):
3780 continuation_line = None
3781 continue
3782
3783 if line.startswith('import') and 'model' in line:
3784 model = line.split()[2]
3785 proc = []
3786 if model.endswith('\\'):
3787 continuation_line = 'model'
3788 elif line.startswith('generate'):
3789 proc.append(line.split(None,1)[1])
3790 if proc[-1].endswith('\\'):
3791 continuation_line = 'proc'
3792 elif line.startswith('add process'):
3793 proc.append(line.split(None,2)[2])
3794 if proc[-1].endswith('\\'):
3795 continuation_line = 'proc'
3796 self.model = model
3797 self.process = proc
3798 return model
3799
3800
3801
3827
3828
3841
3853
3854
3855
3857 "Complete the compute_widths command"
3858
3859 args = self.split_arg(line[0:begidx])
3860
3861 if args[-1] in ['--path=', '--output=']:
3862 completion = {'path': self.path_completion(text)}
3863 elif line[begidx-1] == os.path.sep:
3864 current_dir = pjoin(*[a for a in args if a.endswith(os.path.sep)])
3865 if current_dir.startswith('--path='):
3866 current_dir = current_dir[7:]
3867 if current_dir.startswith('--output='):
3868 current_dir = current_dir[9:]
3869 completion = {'path': self.path_completion(text, current_dir)}
3870 else:
3871 completion = {}
3872 completion['options'] = self.list_completion(text,
3873 ['--path=', '--output=', '--min_br=0.\$', '--nlo',
3874 '--precision_channel=0.\$', '--body_decay='])
3875
3876 return self.deal_multiple_categories(completion, formatting)
3877
3878
3880 """update the make_opts file writing the environmental variables
3881 stored in make_opts_var"""
3882 make_opts = os.path.join(self.me_dir, 'Source', 'make_opts')
3883
3884
3885 if not hasattr(self,'options') or not 'pythia8_path' in self.options or \
3886 not self.options['pythia8_path'] or \
3887 not os.path.isfile(pjoin(self.options['pythia8_path'],'bin','pythia8-config')):
3888 self.make_opts_var['PYTHIA8_PATH']='NotInstalled'
3889 else:
3890 self.make_opts_var['PYTHIA8_PATH']=self.options['pythia8_path']
3891
3892 self.make_opts_var['MG5AMC_VERSION'] = misc.get_pkg_info()['version']
3893
3894 return self.update_make_opts_full(make_opts, self.make_opts_var)
3895
3896 @staticmethod
3898 """update the make_opts file writing the environmental variables
3899 of def_variables.
3900 if a value of the dictionary is None then it is not written.
3901 """
3902 make_opts = path
3903 pattern = re.compile(r'^(\w+)\s*=\s*(.*)$',re.DOTALL)
3904 diff = False
3905
3906
3907 tag = '#end_of_make_opts_variables\n'
3908 make_opts_variable = True
3909 content = []
3910 variables = dict(def_variables)
3911 need_keys = variables.keys()
3912 for line in open(make_opts):
3913 line = line.strip()
3914 if make_opts_variable:
3915 if line.startswith('#') or not line:
3916 if line.startswith('#end_of_make_opts_variables'):
3917 make_opts_variable = False
3918 continue
3919 elif pattern.search(line):
3920 key, value = pattern.search(line).groups()
3921 if key not in variables:
3922 variables[key] = value
3923 elif value != variables[key]:
3924 diff=True
3925 else:
3926 need_keys.remove(key)
3927 else:
3928 make_opts_variable = False
3929 content.append(line)
3930 else:
3931 content.append(line)
3932
3933 if need_keys:
3934 diff=True
3935
3936 content_variables = '\n'.join('%s=%s' % (k,v) for k, v in variables.items() if v is not None)
3937 content_variables += '\n%s' % tag
3938
3939 if diff:
3940 with open(make_opts, 'w') as fsock:
3941 fsock.write(content_variables + '\n'.join(content))
3942 return
3943
3944
3945
3947 """links lhapdf into libdir"""
3948
3949 lhapdf_version = self.get_lhapdf_version()
3950 logger.info('Using LHAPDF v%s interface for PDFs' % lhapdf_version)
3951 lhalibdir = subprocess.Popen([self.options['lhapdf'], '--libdir'],
3952 stdout = subprocess.PIPE).stdout.read().strip()
3953
3954 if lhapdf_version.startswith('5.'):
3955 pdfsetsdir = subprocess.Popen([self.options['lhapdf'], '--pdfsets-path'],
3956 stdout = subprocess.PIPE).stdout.read().strip()
3957 else:
3958 pdfsetsdir = subprocess.Popen([self.options['lhapdf'], '--datadir'],
3959 stdout = subprocess.PIPE).stdout.read().strip()
3960
3961 self.lhapdf_pdfsets = self.get_lhapdf_pdfsets_list(pdfsetsdir)
3962
3963 lhalib = 'libLHAPDF.a'
3964
3965 if os.path.exists(pjoin(libdir, lhalib)):
3966 files.rm(pjoin(libdir, lhalib))
3967 files.ln(pjoin(lhalibdir, lhalib), libdir)
3968
3969 if not os.path.isdir(pjoin(libdir, 'PDFsets')):
3970 os.mkdir(pjoin(libdir, 'PDFsets'))
3971 self.make_opts_var['lhapdf'] = self.options['lhapdf']
3972 self.make_opts_var['lhapdfversion'] = lhapdf_version[0]
3973 self.make_opts_var['lhapdfsubversion'] = lhapdf_version.split('.',2)[1]
3974 self.make_opts_var['lhapdf_config'] = self.options['lhapdf']
3975
3976
3978 """reads the proc_characteristics file and initialises the correspondant
3979 dictionary"""
3980
3981 if not path:
3982 path = os.path.join(self.me_dir, 'SubProcesses', 'proc_characteristics')
3983
3984 self.proc_characteristics = banner_mod.ProcCharacteristic(path)
3985 return self.proc_characteristics
3986
3987
3989 """copy (if needed) the lhapdf set corresponding to the lhaid in lhaid_list
3990 into lib/PDFsets"""
3991
3992 if not hasattr(self, 'lhapdf_pdfsets'):
3993 self.lhapdf_pdfsets = self.get_lhapdf_pdfsets_list(pdfsets_dir)
3994
3995 pdfsetname=set()
3996 for lhaid in lhaid_list:
3997 if isinstance(lhaid, str) and lhaid.isdigit():
3998 lhaid = int(lhaid)
3999 if isinstance(lhaid, (int,float)):
4000 try:
4001 if lhaid in self.lhapdf_pdfsets:
4002 pdfsetname.add(self.lhapdf_pdfsets[lhaid]['filename'])
4003 else:
4004 raise MadGraph5Error('lhaid %s not valid input number for the current lhapdf' % lhaid )
4005 except KeyError:
4006 if self.lhapdf_version.startswith('5'):
4007 raise MadGraph5Error(\
4008 ('invalid lhaid set in th run_card: %d .\nPlease note that some sets' % lhaid) + \
4009 '(eg MSTW 90%CL error sets) \nare not available in aMC@NLO + LHAPDF 5.x.x')
4010 else:
4011 logger.debug('%d not found in pdfsets.index' % lhaid)
4012 else:
4013 pdfsetname.add(lhaid)
4014
4015
4016
4017
4018 if not os.path.isdir(pdfsets_dir):
4019 try:
4020 os.mkdir(pdfsets_dir)
4021 except OSError:
4022 pdfsets_dir = pjoin(self.me_dir, 'lib', 'PDFsets')
4023 elif os.path.exists(pjoin(self.me_dir, 'lib', 'PDFsets')):
4024
4025 for name in os.listdir(pjoin(self.me_dir, 'lib', 'PDFsets')):
4026 if name not in pdfsetname:
4027 try:
4028 if os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', name)):
4029 shutil.rmtree(pjoin(self.me_dir, 'lib', 'PDFsets', name))
4030 else:
4031 os.remove(pjoin(self.me_dir, 'lib', 'PDFsets', name))
4032 except Exception, error:
4033 logger.debug('%s', error)
4034
4035 if self.options["cluster_local_path"]:
4036 lhapdf_cluster_possibilities = [self.options["cluster_local_path"],
4037 pjoin(self.options["cluster_local_path"], "lhapdf"),
4038 pjoin(self.options["cluster_local_path"], "lhapdf", "pdfsets"),
4039 pjoin(self.options["cluster_local_path"], "..", "lhapdf"),
4040 pjoin(self.options["cluster_local_path"], "..", "lhapdf", "pdfsets"),
4041 pjoin(self.options["cluster_local_path"], "..", "lhapdf","pdfsets", "6.1")
4042 ]
4043 else:
4044 lhapdf_cluster_possibilities = []
4045
4046 for pdfset in pdfsetname:
4047
4048 if self.options["cluster_local_path"] and self.options["run_mode"] == 1 and \
4049 any((os.path.exists(pjoin(d, pdfset)) for d in lhapdf_cluster_possibilities)):
4050
4051 os.environ["LHAPATH"] = [d for d in lhapdf_cluster_possibilities if os.path.exists(pjoin(d, pdfset))][0]
4052 os.environ["CLUSTER_LHAPATH"] = os.environ["LHAPATH"]
4053
4054 if os.path.exists(pjoin(pdfsets_dir, pdfset)):
4055 try:
4056 if os.path.isdir(pjoin(pdfsets_dir, name)):
4057 shutil.rmtree(pjoin(pdfsets_dir, name))
4058 else:
4059 os.remove(pjoin(pdfsets_dir, name))
4060 except Exception, error:
4061 logger.debug('%s', error)
4062
4063
4064 elif not os.path.exists(pjoin(self.me_dir, 'lib', 'PDFsets', pdfset)) and \
4065 not os.path.isdir(pjoin(self.me_dir, 'lib', 'PDFsets', pdfset)):
4066
4067 if pdfset and not os.path.exists(pjoin(pdfsets_dir, pdfset)):
4068 self.install_lhapdf_pdfset(pdfsets_dir, pdfset)
4069
4070 if os.path.exists(pjoin(pdfsets_dir, pdfset)):
4071 files.cp(pjoin(pdfsets_dir, pdfset), pjoin(self.me_dir, 'lib', 'PDFsets'))
4072 elif os.path.exists(pjoin(os.path.dirname(pdfsets_dir), pdfset)):
4073 files.cp(pjoin(os.path.dirname(pdfsets_dir), pdfset), pjoin(self.me_dir, 'lib', 'PDFsets'))
4074
4076 """idownloads and install the pdfset filename in the pdfsets_dir"""
4077 lhapdf_version = self.get_lhapdf_version()
4078 local_path = pjoin(self.me_dir, 'lib', 'PDFsets')
4079 return self.install_lhapdf_pdfset_static(self.options['lhapdf'],
4080 pdfsets_dir, filename,
4081 lhapdf_version=lhapdf_version,
4082 alternate_path=local_path)
4083
4084
4085 @staticmethod
4088 """idownloads and install the pdfset filename in the pdfsets_dir.
4089 Version which can be used independently of the class.
4090 local path is used if the global installation fails.
4091 """
4092
4093 if not lhapdf_version:
4094 lhapdf_version = subprocess.Popen([lhapdf_config, '--version'],
4095 stdout = subprocess.PIPE).stdout.read().strip()
4096 if not pdfsets_dir:
4097 pdfsets_dir = subprocess.Popen([lhapdf_config, '--datadir'],
4098 stdout = subprocess.PIPE).stdout.read().strip()
4099
4100 if isinstance(filename, int):
4101 pdf_info = CommonRunCmd.get_lhapdf_pdfsets_list_static(pdfsets_dir, lhapdf_version)
4102 filename = pdf_info[filename]['filename']
4103
4104 if os.path.exists(pjoin(pdfsets_dir, filename)):
4105 logger.debug('%s is already present in %s', filename, pdfsets_dir)
4106 return
4107
4108 logger.info('Trying to download %s' % filename)
4109
4110 if lhapdf_version.startswith('5.'):
4111
4112
4113
4114 getdata = lhapdf_config.replace('lhapdf-config', ('lhapdf-getdata'))
4115 misc.call([getdata, filename], cwd = pdfsets_dir)
4116
4117 elif lhapdf_version.startswith('6.'):
4118
4119
4120 getdata = lhapdf_config.replace('lhapdf-config', ('lhapdf'))
4121
4122 if lhapdf_version.startswith('6.1'):
4123 misc.call([getdata, 'install', filename], cwd = pdfsets_dir)
4124 else:
4125
4126 lhapdf = misc.import_python_lhapdf(lhapdf_config)
4127 if lhapdf:
4128 if 'PYTHONPATH' in os.environ:
4129 os.environ['PYTHONPATH']+= ':' + os.path.dirname(lhapdf.__file__)
4130 else:
4131 os.environ['PYTHONPATH'] = ':'.join(sys.path) + ':' + os.path.dirname(lhapdf.__file__)
4132 else:
4133 logger.warning('lhapdf 6.2.1 requires python integration in order to download pdf set. Trying anyway')
4134 misc.call([getdata, 'install', filename], cwd = pdfsets_dir)
4135
4136 else:
4137 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version)
4138
4139
4140 if os.path.exists(pjoin(pdfsets_dir, filename)) or \
4141 os.path.isdir(pjoin(pdfsets_dir, filename)):
4142 logger.info('%s successfully downloaded and stored in %s' \
4143 % (filename, pdfsets_dir))
4144
4145 elif lhapdf_version.startswith('5.'):
4146 logger.warning('Could not download %s into %s. Trying to save it locally' \
4147 % (filename, pdfsets_dir))
4148 CommonRunCmd.install_lhapdf_pdfset_static(lhapdf_config, alternate_path, filename,
4149 lhapdf_version=lhapdf_version)
4150 elif lhapdf_version.startswith('6.') and '.LHgrid' in filename:
4151 logger.info('Could not download %s: Try %s', filename, filename.replace('.LHgrid',''))
4152 return CommonRunCmd.install_lhapdf_pdfset_static(lhapdf_config, pdfsets_dir,
4153 filename.replace('.LHgrid',''),
4154 lhapdf_version, alternate_path)
4155 elif lhapdf_version.startswith('6.'):
4156
4157 wwwpath = "http://www.hepforge.org/archive/lhapdf/pdfsets/%s/%s.tar.gz"
4158 wwwpath %= ('.'.join(lhapdf_version.split('.')[:2]), filename)
4159 misc.wget(wwwpath, pjoin(pdfsets_dir, '%s.tar.gz' %filename))
4160 misc.call(['tar', '-xzpvf', '%s.tar.gz' %filename],
4161 cwd=pdfsets_dir)
4162 if os.path.exists(pjoin(pdfsets_dir, filename)) or \
4163 os.path.isdir(pjoin(pdfsets_dir, filename)):
4164 logger.info('%s successfully downloaded and stored in %s' \
4165 % (filename, pdfsets_dir))
4166 else:
4167 raise MadGraph5Error, \
4168 'Could not download %s into %s. Please try to install it manually.' \
4169 % (filename, pdfsets_dir)
4170
4171 else:
4172 raise MadGraph5Error, \
4173 'Could not download %s into %s. Please try to install it manually.' \
4174 % (filename, pdfsets_dir)
4175
4176
4177
4179 """read the PDFsets.index file, which should be located in the same
4180 place as pdfsets_dir, and return a list of dictionaries with the information
4181 about each pdf set"""
4182 lhapdf_version = self.get_lhapdf_version()
4183 return self.get_lhapdf_pdfsets_list_static(pdfsets_dir, lhapdf_version)
4184
4185 @staticmethod
4187
4188 if lhapdf_version.startswith('5.'):
4189 if os.path.exists('%s.index' % pdfsets_dir):
4190 indexfile = '%s.index' % pdfsets_dir
4191 else:
4192 raise MadGraph5Error, 'index of lhapdf file not found'
4193 pdfsets_lines = \
4194 [l for l in open(indexfile).read().split('\n') if l.strip() and \
4195 not '90cl' in l]
4196 lhapdf_pdfsets = dict( (int(l.split()[0]), {'lhaid': int(l.split()[0]),
4197 'pdflib_ntype': int(l.split()[1]),
4198 'pdflib_ngroup': int(l.split()[2]),
4199 'pdflib_nset': int(l.split()[3]),
4200 'filename': l.split()[4],
4201 'lhapdf_nmem': int(l.split()[5]),
4202 'q2min': float(l.split()[6]),
4203 'q2max': float(l.split()[7]),
4204 'xmin': float(l.split()[8]),
4205 'xmax': float(l.split()[9]),
4206 'description': l.split()[10]}) \
4207 for l in pdfsets_lines)
4208
4209 elif lhapdf_version.startswith('6.'):
4210 pdfsets_lines = \
4211 [l for l in open(pjoin(pdfsets_dir, 'pdfsets.index')).read().split('\n') if l.strip()]
4212 lhapdf_pdfsets = dict( (int(l.split()[0]),
4213 {'lhaid': int(l.split()[0]),
4214 'filename': l.split()[1]}) \
4215 for l in pdfsets_lines)
4216
4217 else:
4218 raise MadGraph5Error('Not valid LHAPDF version: %s' % lhapdf_version)
4219
4220 return lhapdf_pdfsets
4221
4222
4224 """returns the lhapdf version number"""
4225 if not hasattr(self, 'lhapdfversion'):
4226 try:
4227 self.lhapdf_version = \
4228 subprocess.Popen([self.options['lhapdf'], '--version'],
4229 stdout = subprocess.PIPE).stdout.read().strip()
4230 except OSError, error:
4231 if error.errno == 2:
4232 raise Exception, 'lhapdf executable (%s) is not found on your system. Please install it and/or indicate the path to the correct executable in input/mg5_configuration.txt' % self.options['lhapdf']
4233 else:
4234 raise
4235
4236
4237 if self.lhapdf_version.startswith('6.0'):
4238 raise MadGraph5Error('LHAPDF 6.0.x not supported. Please use v6.1 or later')
4239 return self.lhapdf_version
4240
4241
4243 lhapdf_version = self.get_lhapdf_version()
4244
4245
4246 if 'LHAPDF_DATA_PATH' in os.environ.keys() and os.environ['LHAPDF_DATA_PATH']:
4247 datadir = os.environ['LHAPDF_DATA_PATH']
4248
4249 elif lhapdf_version.startswith('5.'):
4250 datadir = subprocess.Popen([self.options['lhapdf'], '--pdfsets-path'],
4251 stdout = subprocess.PIPE).stdout.read().strip()
4252
4253 elif lhapdf_version.startswith('6.'):
4254 datadir = subprocess.Popen([self.options['lhapdf'], '--datadir'],
4255 stdout = subprocess.PIPE).stdout.read().strip()
4256
4257 if ':' in datadir:
4258 for totry in datadir.split(':'):
4259 if os.path.exists(pjoin(totry, 'pdfsets.index')):
4260 return totry
4261 else:
4262 return None
4263
4264 return datadir
4265
4266
4268 """get the list of Pdirectory if not yet saved."""
4269
4270 if hasattr(self, "Pdirs"):
4271 if self.me_dir in self.Pdirs[0]:
4272 return self.Pdirs
4273 self.Pdirs = [pjoin(self.me_dir, 'SubProcesses', l.strip())
4274 for l in open(pjoin(self.me_dir,'SubProcesses', 'subproc.mg'))]
4275 return self.Pdirs
4276
4278 lhapdf_version = self.get_lhapdf_version()
4279
4280 if lhapdf_version.startswith('5.'):
4281 libdir = subprocess.Popen([self.options['lhapdf-config'], '--libdir'],
4282 stdout = subprocess.PIPE).stdout.read().strip()
4283
4284 elif lhapdf_version.startswith('6.'):
4285 libdir = subprocess.Popen([self.options['lhapdf'], '--libs'],
4286 stdout = subprocess.PIPE).stdout.read().strip()
4287
4288 return libdir
4289
4291 """A class for asking a question where in addition you can have the
4292 set command define and modifying the param_card/run_card correctly
4293
4294 special action can be trigger via trigger_XXXX when the user start a line
4295 with XXXX. the output of such function should be new line that can be handle.
4296 (return False to repeat the question)
4297 """
4298
4299 all_card_name = ['param_card', 'run_card', 'pythia_card', 'pythia8_card',
4300 'madweight_card', 'MadLoopParams', 'shower_card']
4301 to_init_card = ['param', 'run', 'madweight', 'madloop',
4302 'shower', 'pythia8','delphes','madspin']
4303 special_shortcut = {}
4304 special_shortcut_help = {}
4305
4306 integer_bias = 1
4307
4308 PY8Card_class = banner_mod.PY8Card
4309
4311 """ define all default variable. No load of card here.
4312 This allow to subclass this class and just change init and still have
4313 all variables defined."""
4314
4315 if not hasattr(self, 'me_dir'):
4316 self.me_dir = None
4317 self.param_card = None
4318 self.run_card = {}
4319 self.pname2block = {}
4320 self.conflict = []
4321 self.restricted_value = {}
4322 self.mode = ''
4323 self.cards = []
4324 self.run_set = []
4325 self.has_mw = False
4326 self.has_ml = False
4327 self.has_shower = False
4328 self.has_PY8 = False
4329 self.has_delphes = False
4330 self.paths = {}
4331 self.update_block = []
4332
4333
4335
4336 if 'pwd' in opt:
4337 self.me_dir = opt['pwd']
4338 elif 'mother_interface' in opt:
4339 self.mother_interface = opt['mother_interface']
4340 if not hasattr(self, 'me_dir') or not self.me_dir:
4341 self.me_dir = self.mother_interface.me_dir
4342
4343
4344 self.paths['param'] = pjoin(self.me_dir,'Cards','param_card.dat')
4345 self.paths['param_default'] = pjoin(self.me_dir,'Cards','param_card_default.dat')
4346 self.paths['run'] = pjoin(self.me_dir,'Cards','run_card.dat')
4347 self.paths['run_default'] = pjoin(self.me_dir,'Cards','run_card_default.dat')
4348 self.paths['transfer'] =pjoin(self.me_dir,'Cards','transfer_card.dat')
4349 self.paths['MadWeight'] =pjoin(self.me_dir,'Cards','MadWeight_card.dat')
4350 self.paths['MadWeight_default'] =pjoin(self.me_dir,'Cards','MadWeight_card_default.dat')
4351 self.paths['ML'] =pjoin(self.me_dir,'Cards','MadLoopParams.dat')
4352 self.paths['shower'] = pjoin(self.me_dir,'Cards','shower_card.dat')
4353 self.paths['shower_default'] = pjoin(self.me_dir,'Cards','shower_card_default.dat')
4354 self.paths['FO_analyse'] = pjoin(self.me_dir,'Cards','FO_analyse_card.dat')
4355 self.paths['FO_analyse_default'] = pjoin(self.me_dir,'Cards','FO_analyse_card_default.dat')
4356 self.paths['pythia'] =pjoin(self.me_dir, 'Cards','pythia_card.dat')
4357 self.paths['pythia8'] = pjoin(self.me_dir, 'Cards','pythia8_card.dat')
4358 self.paths['pythia8_default'] = pjoin(self.me_dir, 'Cards','pythia8_card_default.dat')
4359 self.paths['madspin_default'] = pjoin(self.me_dir,'Cards/madspin_card_default.dat')
4360 self.paths['madspin'] = pjoin(self.me_dir,'Cards/madspin_card.dat')
4361 self.paths['reweight'] = pjoin(self.me_dir,'Cards','reweight_card.dat')
4362 self.paths['delphes'] = pjoin(self.me_dir,'Cards','delphes_card.dat')
4363 self.paths['plot'] = pjoin(self.me_dir,'Cards','plot_card.dat')
4364 self.paths['plot_default'] = pjoin(self.me_dir,'Cards','plot_card_default.dat')
4365 self.paths['madanalysis5_parton'] = pjoin(self.me_dir,'Cards','madanalysis5_parton_card.dat')
4366 self.paths['madanalysis5_hadron'] = pjoin(self.me_dir,'Cards','madanalysis5_hadron_card.dat')
4367 self.paths['madanalysis5_parton_default'] = pjoin(self.me_dir,'Cards','madanalysis5_parton_card_default.dat')
4368 self.paths['madanalysis5_hadron_default'] = pjoin(self.me_dir,'Cards','madanalysis5_hadron_card_default.dat')
4369 self.paths['FO_analyse'] = pjoin(self.me_dir,'Cards', 'FO_analyse_card.dat')
4370
4371
4372
4373
4374 - def __init__(self, question, cards=[], from_banner=None, banner=None, mode='auto', *args, **opt):
4375
4376
4377 self.load_default()
4378 self.define_paths(**opt)
4379 self.last_editline_pos = 0
4380
4381 if 'allow_arg' not in opt or not opt['allow_arg']:
4382
4383 opt['allow_arg'] = range(self.integer_bias, self.integer_bias+len(cards))
4384
4385 self.param_consistency = True
4386 if 'param_consistency' in opt:
4387 self.param_consistency = opt['param_consistency']
4388
4389 cmd.OneLinePathCompletion.__init__(self, question, *args, **opt)
4390
4391 self.conflict = set()
4392 self.mode = mode
4393 self.cards = cards
4394 self.all_vars = set()
4395 self.modified_card = set()
4396
4397 self.init_from_banner(from_banner, banner)
4398
4399
4400 for card in cards:
4401 if os.path.exists(card) and os.path.sep in cards:
4402 card_name = CommonRunCmd.detect_card_type(card)
4403 card_name = card_name.split('_',1)[0]
4404 self.paths[card_name] = card
4405
4406
4407 for name in self.to_init_card:
4408 new_vars = set(getattr(self, 'init_%s' % name)(cards))
4409 new_conflict = self.all_vars.intersection(new_vars)
4410 self.conflict.union(new_conflict)
4411 self.all_vars.union(new_vars)
4412
4413
4415 """ defined card that need to be initialized from the banner file
4416 from_banner should be a list of card to load from the banner object
4417 """
4418
4419 if from_banner is None:
4420 self.from_banner = {}
4421 return
4422 misc.sprint(from_banner)
4423 self.from_banner = {}
4424 for card in from_banner:
4425 self.from_banner[card] = banner.charge_card(card)
4426 return self.from_banner
4427
4428
4430 """initialise the path if requested"""
4431
4432 defname = '%s_default' % name
4433
4434 if name in self.from_banner:
4435 return self.from_banner[name]
4436
4437 if isinstance(cards, list):
4438 if name in cards:
4439 return True
4440 elif '%s_card.dat' % name in cards:
4441 return True
4442 elif name in self.paths and self.paths[name] in cards:
4443 return True
4444 else:
4445 cardnames = [os.path.basename(p) for p in cards]
4446 if '%s_card.dat' % name in cardnames:
4447 return True
4448 else:
4449 return False
4450
4451 elif isinstance(cards, dict) and name in cards:
4452 self.paths[name]= cards[name]
4453 if defname in cards:
4454 self.paths[defname] = cards[defname]
4455 elif os.path.isfile(cards[name].replace('.dat', '_default.dat')):
4456 self.paths[defname] = cards[name].replace('.dat', '_default.dat')
4457 else:
4458 self.paths[defname] = self.paths[name]
4459
4460 return True
4461 else:
4462 return False
4463
4465 """check if we need to load the param_card"""
4466
4467 self.pname2block = {}
4468 self.restricted_value = {}
4469 self.param_card = {}
4470
4471 is_valid_path = self.get_path('param', cards)
4472 if not is_valid_path:
4473 self.param_consistency = False
4474 return []
4475 if isinstance(is_valid_path, param_card_mod.ParamCard):
4476 self.param_card = is_valid_path
4477 self.param_consistency = False
4478 return []
4479
4480 try:
4481 self.param_card = param_card_mod.ParamCard(self.paths['param'])
4482 except (param_card_mod.InvalidParamCard, ValueError) as e:
4483 logger.error('Current param_card is not valid. We are going to use the default one.')
4484 logger.error('problem detected: %s' % e)
4485 files.cp(self.paths['param_default'], self.paths['param'])
4486 self.param_card = param_card_mod.ParamCard(self.paths['param'])
4487
4488
4489
4490
4491 if os.path.exists(self.paths['param_default']):
4492 default_param = param_card_mod.ParamCard(self.paths['param_default'])
4493 else:
4494 default_param = param_card_mod.ParamCard(self.param_card)
4495 self.pname2block, self.restricted_value = default_param.analyze_param_card()
4496 self.param_card_default = default_param
4497 return self.pname2block.keys()
4498
4500
4501 self.run_set = []
4502 is_valid_path = self.get_path('run', cards)
4503 if not is_valid_path:
4504 return []
4505 if isinstance(is_valid_path, banner_mod.RunCard):
4506 self.run_card = is_valid_path
4507 return []
4508
4509
4510 try:
4511 self.run_card = banner_mod.RunCard(self.paths['run'], consistency='warning')
4512 except IOError:
4513 self.run_card = {}
4514 try:
4515 run_card_def = banner_mod.RunCard(self.paths['run_default'])
4516 except IOError:
4517 run_card_def = {}
4518
4519
4520 if run_card_def:
4521 if self.run_card:
4522 self.run_set = run_card_def.keys() + self.run_card.hidden_param
4523 else:
4524 self.run_set = run_card_def.keys() + run_card_def.hidden_param
4525 elif self.run_card:
4526 self.run_set = self.run_card.keys()
4527 else:
4528 self.run_set = []
4529
4530 if self.run_set:
4531 self.special_shortcut.update(
4532 {'ebeam':([float],['run_card ebeam1 %(0)s', 'run_card ebeam2 %(0)s']),
4533 'lpp': ([int],['run_card lpp1 %(0)s', 'run_card lpp2 %(0)s' ]),
4534 'lhc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']),
4535 'lep': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']),
4536 'ilc': ([int],['run_card lpp1 0', 'run_card lpp2 0', 'run_card ebeam1 %(0)s/2', 'run_card ebeam2 %(0)s/2']),
4537 'lcc': ([int],['run_card lpp1 1', 'run_card lpp2 1', 'run_card ebeam1 %(0)s*1000/2', 'run_card ebeam2 %(0)s*1000/2']),
4538 'fixed_scale': ([float],['run_card fixed_fac_scale T', 'run_card fixed_ren_scale T', 'run_card scale %(0)s', 'run_card dsqrt_q2fact1 %(0)s' ,'run_card dsqrt_q2fact2 %(0)s']),
4539 'no_parton_cut':([],['run_card nocut T']),
4540 'cm_velocity':([float], [lambda self :self.set_CM_velocity]),
4541 'pbp':([],['run_card lpp1 1', 'run_card lpp2 1','run_card nb_proton1 82', 'run_card nb_neutron1 126', 'run_card mass_ion1 195.0820996698','run_card nb_proton2 1', 'run_card nb_neutron2 0', 'run_card mass_ion1 -1']),
4542 'pbpb':([],['run_card lpp1 1', 'run_card lpp2 1','run_card nb_proton1 82', 'run_card nb_neutron1 126', 'run_card mass_ion1 195.0820996698', 'run_card nb_proton2 82', 'run_card nb_neutron2 126', 'run_card mass_ion2 195.0820996698' ]),
4543 'pp': ([],['run_card lpp1 1', 'run_card lpp2 1','run_card nb_proton1 1', 'run_card nb_neutron1 0', 'run_card mass_ion1 -1', 'run_card nb_proton2 1', 'run_card nb_neutron2 0', 'run_card mass_ion2 -1']),
4544 })
4545
4546 self.special_shortcut_help.update({
4547 'ebeam' : 'syntax: set ebeam VALUE:\n This parameter sets the energy to both beam to the value in GeV',
4548 'lpp' : 'syntax: set ebeam VALUE:\n'+\
4549 ' Set the type of beam to a given value for both beam\n'+\
4550 ' 0 : means no PDF\n'+\
4551 ' 1 : means proton PDF\n'+\
4552 ' -1 : means antiproton PDF\n'+\
4553 ' 2 : means PDF for elastic photon emited from a proton\n'+\
4554 ' 3 : means PDF for elastic photon emited from an electron',
4555 'lhc' : 'syntax: set lhc VALUE:\n Set for a proton-proton collision with that given center of mass energy (in TeV)',
4556 'lep' : 'syntax: set lep VALUE:\n Set for a electron-positron collision with that given center of mass energy (in GeV)',
4557 'fixed_scale' : 'syntax: set fixed_scale VALUE:\n Set all scales to the give value (in GeV)',
4558 'no_parton_cut': 'remove all cut (but BW_cutoff)',
4559 'cm_velocity': 'set sqrts to have the above velocity for the incoming particles',
4560 'pbpb': 'setup heavy ion configuration for lead-lead collision',
4561 'pbp': 'setup heavy ion configuration for lead-proton collision',
4562 'pp': 'remove setup of heavy ion configuration to set proton-proton collision',
4563 })
4564
4565 self.update_block += [b.name for b in self.run_card.blocks]
4566
4567 return self.run_set
4568
4570
4571 self.has_mw = False
4572 if not self.get_path('madweight', cards):
4573 return []
4574
4575
4576 self.do_change_tf = self.mother_interface.do_define_transfer_fct
4577 self.complete_change_tf = self.mother_interface.complete_define_transfer_fct
4578 self.help_change_tf = self.mother_interface.help_define_transfer_fct
4579 if not os.path.exists(self.paths['transfer']):
4580 logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
4581
4582 self.has_mw = True
4583 try:
4584 import madgraph.madweight.Cards as mwcards
4585 except:
4586 import internal.madweight.Cards as mwcards
4587 self.mw_card = mwcards.Card(self.paths['MadWeight'])
4588 self.mw_card = self.mw_card.info
4589 self.mw_vars = []
4590 for key in self.mw_card:
4591 if key == 'comment':
4592 continue
4593 for key2 in self.mw_card.info[key]:
4594 if isinstance(key2, str) and not key2.isdigit():
4595 self.mw_vars.append(key2)
4596 return self.mw_vars
4597
4599
4600 if isinstance(cards, dict):
4601 for key in ['ML', 'madloop','MadLoop']:
4602 if key in cards:
4603 self.paths['ML'] = cards[key]
4604
4605 self.has_ml = False
4606 if os.path.isfile(self.paths['ML']):
4607 self.has_ml = True
4608 self.MLcard = banner_mod.MadLoopParam(self.paths['ML'])
4609 self.MLcardDefault = banner_mod.MadLoopParam()
4610 self.ml_vars = [k.lower() for k in self.MLcard.keys()]
4611 return self.ml_vars
4612 return []
4613
4615
4616 self.has_shower = False
4617 if not self.get_path('shower', cards):
4618 return []
4619 self.has_shower = True
4620 self.shower_card = shower_card_mod.ShowerCard(self.paths['shower'])
4621 self.shower_vars = self.shower_card.keys()
4622 return self.shower_vars
4623
4625
4626 self.has_PY8 = False
4627 if not self.get_path('pythia8', cards):
4628 return []
4629
4630 self.has_PY8 = True
4631 self.PY8Card = self.PY8Card_class(self.paths['pythia8'])
4632 self.PY8CardDefault = self.PY8Card_class()
4633
4634 self.py8_vars = [k.lower() for k in self.PY8Card.keys()]
4635
4636 self.special_shortcut.update({
4637 'simplepy8':([],['pythia8_card hadronlevel:all False',
4638 'pythia8_card partonlevel:mpi False',
4639 'pythia8_card BeamRemnants:primordialKT False',
4640 'pythia8_card PartonLevel:Remnants False',
4641 'pythia8_card Check:event False',
4642 'pythia8_card TimeShower:QEDshowerByQ False',
4643 'pythia8_card TimeShower:QEDshowerByL False',
4644 'pythia8_card SpaceShower:QEDshowerByQ False',
4645 'pythia8_card SpaceShower:QEDshowerByL False',
4646 'pythia8_card PartonLevel:FSRinResonances False',
4647 'pythia8_card ProcessLevel:resonanceDecays False',
4648 ]),
4649 'mpi':([bool],['pythia8_card partonlevel:mpi %(0)s']),
4650 })
4651 self.special_shortcut_help.update({
4652 'simplepy8' : 'Turn off non-perturbative slow features of Pythia8.',
4653 'mpi' : 'syntax: set mpi value: allow to turn mpi in Pythia8 on/off',
4654 })
4655 return []
4656
4658
4659 if not self.get_path('madspin', cards):
4660 return []
4661
4662 self.special_shortcut.update({
4663 'spinmode':([str], ['add madspin_card --before_line="launch" set spinmode %(0)s'])
4664 })
4665 self.special_shortcut_help.update({
4666 'spinmode' : 'full|none|onshell. Choose the mode of madspin.\n - full: spin-correlation and off-shell effect\n - onshell: only spin-correlation,]\n - none: no spin-correlation and not offshell effects.'
4667 })
4668 return []
4669
4671
4672 self.has_delphes = False
4673 if not self.get_path('pythia8', cards):
4674 return []
4675 self.has_delphes = True
4676 return []
4677
4678
4680 """compute sqrts from the velocity in the center of mass frame"""
4681
4682 v = banner_mod.ConfigFile.format_variable(line, float, 'velocity')
4683
4684 self.mother_interface.get_characteristics()
4685 proc_info = self.mother_interface.proc_characteristics
4686 if 'pdg_initial1' not in proc_info:
4687 logger.warning('command not supported')
4688
4689 if len(proc_info['pdg_initial1']) == 1 == len(proc_info['pdg_initial2']) and\
4690 abs(proc_info['pdg_initial1'][0]) == abs(proc_info['pdg_initial2'][0]):
4691
4692 m = self.param_card.get_value('mass', abs(proc_info['pdg_initial1'][0]))
4693 sqrts = 2*m/ math.sqrt(1-v**2)
4694 self.do_set('run_card ebeam1 %s' % (sqrts/2.0))
4695 self.do_set('run_card ebeam2 %s' % (sqrts/2.0))
4696 self.do_set('run_card lpp 0')
4697 else:
4698 logger.warning('This is only possible for a single particle in the initial state')
4699
4700
4701
4702 - def do_help(self, line, conflict_raise=False, banner=True):
4703
4704
4705
4706 if banner:
4707 logger.info('*** HELP MESSAGE ***', '$MG:BOLD')
4708
4709 args = self.split_arg(line)
4710
4711 if len(args)==0 or (len(args) == 1 and hasattr(self, 'do_%s' % args[0])):
4712 out = cmd.BasicCmd.do_help(self, line)
4713 if len(args)==0:
4714 print 'Allowed Argument'
4715 print '================'
4716 print '\t'.join(self.allow_arg)
4717 print
4718 print 'Special shortcut: (type help <name>)'
4719 print '===================================='
4720 print ' syntax: set <name> <value>'
4721 print '\t'.join(self.special_shortcut)
4722 print
4723 if banner:
4724 logger.info('*** END HELP ***', '$MG:BOLD')
4725 return out
4726
4727
4728 if args[0] in self.special_shortcut:
4729 if args[0] in self.special_shortcut_help:
4730 print self.special_shortcut_help[args[0]]
4731 if banner:
4732 logger.info('*** END HELP ***', '$MG:BOLD')
4733 return
4734
4735 start = 0
4736 card = ''
4737 if args[0]+'_card' in self.all_card_name+ self.cards:
4738 args[0] += '_card'
4739 elif args[0]+'.dat' in self.all_card_name+ self.cards:
4740 args[0] += '.dat'
4741 elif args[0]+'_card.dat' in self.all_card_name+ self.cards:
4742 args[0] += '_card.dat'
4743 if args[0] in self.all_card_name + self.cards:
4744 start += 1
4745 card = args[0]
4746 if len(args) == 1:
4747 if args[0] == 'pythia8_card':
4748 args[0] = 'PY8Card'
4749 if args[0] == 'param_card':
4750 logger.info("Param_card information: ", '$MG:color:BLUE')
4751 print "File to define the various model parameter"
4752 logger.info("List of the Block defined:",'$MG:color:BLUE')
4753 print "\t".join(self.param_card.keys())
4754 elif args[0].startswith('madanalysis5'):
4755 print 'This card allow to make plot with the madanalysis5 package'
4756 print 'An example card is provided. For more information about the '
4757 print 'syntax please refer to: https://madanalysis.irmp.ucl.ac.be/'
4758 print 'or to the user manual [arXiv:1206.1599]'
4759 if args[0].startswith('madanalysis5_hadron'):
4760 print
4761 print 'This card also allow to make recasting analysis'
4762 print 'For more detail, see: arXiv:1407.3278'
4763 elif hasattr(self, args[0]):
4764 logger.info("%s information: " % args[0], '$MG:color:BLUE')
4765 print(eval('self.%s' % args[0]).__doc__)
4766 logger.info("List of parameter associated", '$MG:color:BLUE')
4767 print "\t".join(eval('self.%s' % args[0]).keys())
4768 if banner:
4769 logger.info('*** END HELP ***', '$MG:BOLD')
4770 return card
4771
4772
4773 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']:
4774 if args[start] not in self.run_set:
4775 args[start] = [l for l in self.run_set if l.lower() == args[start]][0]
4776
4777 if args[start] in self.conflict and not conflict_raise:
4778 conflict_raise = True
4779 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:BOLD')
4780 if card == '':
4781 logger.info('** If not explicitely speficy this parameter will modif the run_card file', '$MG:BOLD')
4782
4783 self.run_card.do_help(args[start])
4784
4785 elif (args[start] in self.param_card or args[start] == 'width') \
4786 and card in ['','param_card']:
4787 if args[start] in self.conflict and not conflict_raise:
4788 conflict_raise = True
4789 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:BOLD')
4790 if card == '':
4791 logger.info('** If not explicitely speficy this parameter will modif the param_card file', '$MG:BOLD')
4792
4793 if args[start] == 'width':
4794 args[start] = 'decay'
4795
4796 if len(args) == start+1:
4797 self.param_card.do_help(args[start], tuple())
4798 key = None
4799 elif args[start+1] in self.pname2block:
4800 all_var = self.pname2block[args[start+1]]
4801 key = None
4802 for bname, lhaid in all_var:
4803 if bname == args[start]:
4804 key = lhaid
4805 break
4806 else:
4807 logger.warning('%s is not part of block "%s" but "%s". please correct.' %
4808 (args[start+1], args[start], bname))
4809 else:
4810 try:
4811 key = tuple([int(i) for i in args[start+1:]])
4812 except ValueError:
4813 logger.warning('Failed to identify LHA information')
4814 return card
4815
4816 if key in self.param_card[args[start]].param_dict:
4817 self.param_card.do_help(args[start], key, default=self.param_card_default)
4818 elif key:
4819 logger.warning('invalid information: %s not defined in the param_card' % (key,))
4820
4821 elif args[start] in self.pname2block and card in ['','param_card']:
4822 if args[start] in self.conflict and not conflict_raise:
4823 conflict_raise = True
4824 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:BOLD')
4825 if card == '':
4826 logger.info('** If not explicitely speficy this parameter will modif the param_card file', '$MG:BOLD')
4827
4828 all_var = self.pname2block[args[start]]
4829 for bname, lhaid in all_var:
4830 new_line = 'param_card %s %s %s' % (bname,
4831 ' '.join([ str(i) for i in lhaid]), ' '.join(args[start+1:]))
4832 self.do_help(new_line, conflict_raise=True, banner=False)
4833
4834
4835 elif self.has_ml and args[start] in self.ml_vars \
4836 and card in ['', 'MadLoop_card']:
4837
4838 if args[start] in self.conflict and not conflict_raise:
4839 conflict_raise = True
4840 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:BOLD')
4841 if card == '':
4842 logger.info('** If not explicitely speficy this parameter will modif the madloop_card file', '$MG:BOLD')
4843
4844 self.MLcard.do_help(args[start])
4845
4846
4847 elif self.has_PY8 and args[start] in self.PY8Card:
4848 if args[start] in self.conflict and not conflict_raise:
4849 conflict_raise = True
4850 logger.info('** AMBIGUOUS NAME: %s **', args[start], '$MG:BOLD')
4851 if card == '':
4852 logger.info('** If not explicitely speficy this parameter will modif the pythia8_card file', '$MG:BOLD')
4853
4854 self.PY8Card.do_help(args[start])
4855 elif card.startswith('madanalysis5'):
4856 print 'MA5'
4857
4858
4859 elif banner:
4860 print "no help available"
4861
4862 if banner:
4863 logger.info('*** END HELP ***', '$MG:BOLD')
4864
4865 return card
4866
4867
4868
4869
4870
4871
4873 prev_timer = signal.alarm(0)
4874 if prev_timer:
4875 nb_back = len(line)
4876 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
4877 self.stdout.write(line)
4878 self.stdout.flush()
4879
4880 possibilities = self.complete_set(text, line, begidx, endidx,formatting=False)
4881 if line[:begidx].strip() == 'help':
4882 possibilities['Defined command'] = cmd.BasicCmd.completenames(self, text, line)
4883 possibilities.update(self.complete_add(text, line, begidx, endidx,formatting=False))
4884 return self.deal_multiple_categories(possibilities)
4885
4886
4887
4888
4889
4891 prev_timer = signal.alarm(0)
4892 if prev_timer:
4893 nb_back = len(line)
4894 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
4895 self.stdout.write(line)
4896 self.stdout.flush()
4897
4898 valid = ['dependent', 'missing', 'to_slha1', 'to_slha2', 'to_full']
4899 valid += self.update_block
4900
4901 arg = line[:begidx].split()
4902 if len(arg) <=1:
4903 return self.list_completion(text, valid, line)
4904 elif arg[0] == 'to_full':
4905 return self.list_completion(text, self.cards , line)
4906
4907 - def complete_set(self, text, line, begidx, endidx, formatting=True):
4908 """ Complete the set command"""
4909
4910 prev_timer = signal.alarm(0)
4911 if prev_timer:
4912 nb_back = len(line)
4913 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
4914 self.stdout.write(line)
4915 self.stdout.flush()
4916
4917 possibilities = {}
4918 allowed = {}
4919 args = self.split_arg(line[0:begidx])
4920 if args[-1] in ['Auto', 'default']:
4921 return
4922
4923 if len(args) == 1:
4924 allowed = {'category':'', 'run_card':'', 'block':'all', 'param_card':'','shortcut':''}
4925 if self.has_mw:
4926 allowed['madweight_card'] = ''
4927 allowed['mw_block'] = 'all'
4928 if self.has_shower:
4929 allowed['shower_card'] = ''
4930 if self.has_ml:
4931 allowed['madloop_card'] = ''
4932 if self.has_PY8:
4933 allowed['pythia8_card'] = ''
4934 if self.has_delphes:
4935 allowed['delphes_card'] = ''
4936
4937 elif len(args) == 2:
4938 if args[1] == 'run_card':
4939 allowed = {'run_card':'default'}
4940 elif args[1] == 'param_card':
4941 allowed = {'block':'all', 'param_card':'default'}
4942 elif self.param_card and args[1] in self.param_card.keys():
4943 allowed = {'block':args[1]}
4944 elif args[1] == 'width':
4945 allowed = {'block': 'decay'}
4946 elif args[1] == 'MadWeight_card':
4947 allowed = {'madweight_card':'default', 'mw_block': 'all'}
4948 elif args[1] == 'MadLoop_card':
4949 allowed = {'madloop_card':'default'}
4950 elif args[1] == 'pythia8_card':
4951 allowed = {'pythia8_card':'default'}
4952 elif self.has_mw and args[1] in self.mw_card.keys():
4953 allowed = {'mw_block':args[1]}
4954 elif args[1] == 'shower_card':
4955 allowed = {'shower_card':'default'}
4956 elif args[1] == 'delphes_card':
4957 allowed = {'delphes_card':'default'}
4958 else:
4959 allowed = {'value':''}
4960
4961 else:
4962 start = 1
4963 if args[1] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card',
4964 'MadLoop_card','pythia8_card','delphes_card','plot_card',
4965 'madanalysis5_parton_card','madanalysis5_hadron_card']:
4966 start = 2
4967
4968 if args[-1] in self.pname2block.keys():
4969 allowed['value'] = 'default'
4970 elif args[start] in self.param_card.keys() or args[start] == 'width':
4971 if args[start] == 'width':
4972 args[start] = 'decay'
4973
4974 if args[start+1:]:
4975 allowed = {'block':(args[start], args[start+1:])}
4976 else:
4977 allowed = {'block':args[start]}
4978 elif self.has_mw and args[start] in self.mw_card.keys():
4979 if args[start+1:]:
4980 allowed = {'mw_block':(args[start], args[start+1:])}
4981 else:
4982 allowed = {'mw_block':args[start]}
4983
4984
4985 else:
4986 allowed['value'] = ''
4987
4988 if 'category' in allowed.keys():
4989 categories = ['run_card', 'param_card']
4990 if self.has_mw:
4991 categories.append('MadWeight_card')
4992 if self.has_shower:
4993 categories.append('shower_card')
4994 if self.has_ml:
4995 categories.append('MadLoop_card')
4996 if self.has_PY8:
4997 categories.append('pythia8_card')
4998 if self.has_delphes:
4999 categories.append('delphes_card')
5000
5001 possibilities['category of parameter (optional)'] = \
5002 self.list_completion(text, categories)
5003
5004 if 'shortcut' in allowed.keys():
5005 possibilities['special values'] = self.list_completion(text, self.special_shortcut.keys()+['qcut', 'showerkt'])
5006
5007 if 'run_card' in allowed.keys():
5008 opts = self.run_set
5009 if allowed['run_card'] == 'default':
5010 opts.append('default')
5011
5012
5013 possibilities['Run Card'] = self.list_completion(text, opts)
5014
5015 if 'param_card' in allowed.keys():
5016 opts = self.pname2block.keys()
5017 if allowed['param_card'] == 'default':
5018 opts.append('default')
5019 possibilities['Param Card'] = self.list_completion(text, opts)
5020
5021 if 'madweight_card' in allowed.keys():
5022 opts = self.mw_vars + [k for k in self.mw_card.keys() if k !='comment']
5023 if allowed['madweight_card'] == 'default':
5024 opts.append('default')
5025 possibilities['MadWeight Card'] = self.list_completion(text, opts)
5026
5027 if 'madloop_card' in allowed.keys():
5028 opts = self.ml_vars
5029 if allowed['madloop_card'] == 'default':
5030 opts.append('default')
5031 possibilities['MadLoop Parameter'] = self.list_completion(text, opts)
5032
5033 if 'pythia8_card' in allowed.keys():
5034 opts = self.py8_vars
5035 if allowed['pythia8_card'] == 'default':
5036 opts.append('default')
5037 possibilities['Pythia8 Parameter'] = self.list_completion(text, opts)
5038
5039 if 'shower_card' in allowed.keys():
5040 opts = self.shower_vars + [k for k in self.shower_card.keys() if k !='comment']
5041 if allowed['shower_card'] == 'default':
5042 opts.append('default')
5043 possibilities['Shower Card'] = self.list_completion(text, opts)
5044
5045 if 'delphes_card' in allowed:
5046 if allowed['delphes_card'] == 'default':
5047 opts = ['default', 'atlas', 'cms']
5048 possibilities['Delphes Card'] = self.list_completion(text, opts)
5049
5050 if 'value' in allowed.keys():
5051 opts = ['default']
5052 if 'decay' in args:
5053 opts.append('Auto')
5054 opts.append('Auto@NLO')
5055 elif args[-1] in self.pname2block and self.pname2block[args[-1]][0][0] == 'decay':
5056 opts.append('Auto')
5057 opts.append('Auto@NLO')
5058 if args[-1] in self.run_set:
5059 allowed_for_run = []
5060 if args[-1].lower() in self.run_card.allowed_value:
5061 allowed_for_run = self.run_card.allowed_value[args[-1].lower()]
5062 if '*' in allowed_for_run:
5063 allowed_for_run.remove('*')
5064 elif isinstance(self.run_card[args[-1]], bool):
5065 allowed_for_run = ['True', 'False']
5066 opts += [str(i) for i in allowed_for_run]
5067
5068
5069 possibilities['Special Value'] = self.list_completion(text, opts)
5070
5071 if 'block' in allowed.keys() and self.param_card:
5072 if allowed['block'] == 'all' and self.param_card:
5073 allowed_block = [i for i in self.param_card.keys() if 'qnumbers' not in i]
5074 allowed_block.append('width')
5075 possibilities['Param Card Block' ] = \
5076 self.list_completion(text, allowed_block)
5077
5078 elif isinstance(allowed['block'], basestring):
5079 block = self.param_card[allowed['block']].param_dict
5080 ids = [str(i[0]) for i in block
5081 if (allowed['block'], i) not in self.restricted_value]
5082 possibilities['Param Card id' ] = self.list_completion(text, ids)
5083 varname = [name for name, all_var in self.pname2block.items()
5084 if any((bname == allowed['block']
5085 for bname,lhaid in all_var))]
5086 possibilities['Param card variable'] = self.list_completion(text,
5087 varname)
5088 else:
5089 block = self.param_card[allowed['block'][0]].param_dict
5090 nb = len(allowed['block'][1])
5091 ids = [str(i[nb]) for i in block if len(i) > nb and \
5092 [str(a) for a in i[:nb]] == allowed['block'][1]]
5093
5094 if not ids:
5095 if tuple([int(i) for i in allowed['block'][1]]) in block:
5096 opts = ['default']
5097 if allowed['block'][0] == 'decay':
5098 opts.append('Auto')
5099 opts.append('Auto@NLO')
5100 possibilities['Special value'] = self.list_completion(text, opts)
5101 possibilities['Param Card id' ] = self.list_completion(text, ids)
5102
5103 if 'mw_block' in allowed.keys():
5104 if allowed['mw_block'] == 'all':
5105 allowed_block = [i for i in self.mw_card.keys() if 'comment' not in i]
5106 possibilities['MadWeight Block' ] = \
5107 self.list_completion(text, allowed_block)
5108 elif isinstance(allowed['mw_block'], basestring):
5109 block = self.mw_card[allowed['mw_block']]
5110 ids = [str(i[0]) if isinstance(i, tuple) else str(i) for i in block]
5111 possibilities['MadWeight Card id' ] = self.list_completion(text, ids)
5112 else:
5113 block = self.mw_card[allowed['mw_block'][0]]
5114 nb = len(allowed['mw_block'][1])
5115 ids = [str(i[nb]) for i in block if isinstance(i, tuple) and\
5116 len(i) > nb and \
5117 [str(a) for a in i[:nb]] == allowed['mw_block'][1]]
5118
5119 if not ids:
5120 if tuple([i for i in allowed['mw_block'][1]]) in block or \
5121 allowed['mw_block'][1][0] in block.keys():
5122 opts = ['default']
5123 possibilities['Special value'] = self.list_completion(text, opts)
5124 possibilities['MadWeight Card id' ] = self.list_completion(text, ids)
5125
5126 return self.deal_multiple_categories(possibilities, formatting)
5127
5129 """ edit the value of one parameter in the card"""
5130
5131
5132 args = self.split_arg(line)
5133
5134
5135 if len(args) == 0:
5136 logger.warning("No argument. For help type 'help set'.")
5137
5138 if len(args)==1 and '=' in args[-1]:
5139 arg1, arg2 = args.pop(-1).split('=',1)
5140 args += [arg1, arg2]
5141 if '=' in args:
5142 args.remove('=')
5143
5144 args[:-1] = [ a.lower() for a in args[:-1]]
5145 if len(args) == 1:
5146 args = [args[0].lower()]
5147
5148 if args[0] in self.special_shortcut:
5149 targettypes , cmd = self.special_shortcut[args[0]]
5150 if len(args) != len(targettypes) +1:
5151 logger.warning('shortcut %s requires %s argument' % (args[0], len(targettypes)))
5152 if len(args) < len(targettypes) +1:
5153 return
5154 else:
5155 logger.warning('additional argument will be ignored')
5156 values ={}
5157 for i, argtype in enumerate(targettypes):
5158 try:
5159 values = {str(i): banner_mod.ConfigFile.format_variable(args[i+1], argtype, args[0])}
5160 except ValueError as e:
5161 logger.warning("Wrong argument: The entry #%s should be of type %s.", i+1, argtype)
5162 return
5163 except InvalidCmd as e:
5164 logger.warning(str(e))
5165 return
5166
5167
5168
5169 for arg in cmd:
5170 if isinstance(arg, str):
5171 try:
5172 text = arg % values
5173 except KeyError:
5174 logger.warning("This command requires one argument")
5175 return
5176 except Exception as e:
5177 logger.warning(str(e))
5178 return
5179 else:
5180 split = text.split()
5181 if hasattr(self, 'do_%s' % split[0]):
5182 getattr(self, 'do_%s' % split[0])(' '.join(split[1:]))
5183 else:
5184 self.do_set(text)
5185
5186 else:
5187 val = [values[str(i)] for i in range(len(values))]
5188 try:
5189 arg(self)(*val)
5190 except Exception, e:
5191 logger.warning(str(e))
5192 return
5193
5194 start = 0
5195 if len(args) < 2:
5196 logger.warning('Invalid set command %s (need two arguments)' % line)
5197 return
5198
5199
5200 if args[0].lower() == 'qcut':
5201 pythia_path = self.paths['pythia']
5202 if os.path.exists(pythia_path):
5203 logger.info('add line QCUT = %s in pythia_card.dat' % args[1])
5204 p_card = open(pythia_path,'r').read()
5205 p_card, n = re.subn('''^\s*QCUT\s*=\s*[\de\+\-\.]*\s*$''',
5206 ''' QCUT = %s ''' % args[1], \
5207 p_card, flags=(re.M+re.I))
5208 if n==0:
5209 p_card = '%s \n QCUT= %s' % (p_card, args[1])
5210 with open(pythia_path, 'w') as fsock:
5211 fsock.write(p_card)
5212 return
5213
5214 if args[0].lower() == 'showerkt':
5215 pythia_path = self.paths['pythia']
5216 if os.path.exists(pythia_path):
5217 logger.info('add line SHOWERKT = %s in pythia_card.dat' % args[1].upper())
5218 p_card = open(pythia_path,'r').read()
5219 p_card, n = re.subn('''^\s*SHOWERKT\s*=\s*[default\de\+\-\.]*\s*$''',
5220 ''' SHOWERKT = %s ''' % args[1].upper(), \
5221 p_card, flags=(re.M+re.I))
5222 if n==0:
5223 p_card = '%s \n SHOWERKT= %s' % (p_card, args[1].upper())
5224 with open(pythia_path, 'w') as fsock:
5225 fsock.write(p_card)
5226 return
5227
5228 card = ''
5229 if args[0] == 'madweight_card':
5230 if not self.mw_card:
5231 logger.warning('Invalid Command: No MadWeight card defined.')
5232 return
5233 args[0] = 'MadWeight_card'
5234
5235 if args[0] == 'shower_card':
5236 if not self.shower_card:
5237 logger.warning('Invalid Command: No Shower card defined.')
5238 return
5239 args[0] = 'shower_card'
5240
5241 if args[0] == "madloop_card":
5242 if not self.has_ml:
5243 logger.warning('Invalid Command: No MadLoopParam card defined.')
5244 return
5245 args[0] = 'MadLoop_card'
5246
5247 if args[0] == "pythia8_card":
5248 if not self.has_PY8:
5249 logger.warning('Invalid Command: No Pythia8 card defined.')
5250 return
5251 args[0] = 'pythia8_card'
5252
5253 if args[0] == 'delphes_card':
5254 if not self.has_delphes:
5255 logger.warning('Invalid Command: No Delphes card defined.')
5256 return
5257 if args[1] == 'atlas':
5258 logger.info("set default ATLAS configuration for Delphes", '$MG:BOLD')
5259 files.cp(pjoin(self.me_dir,'Cards', 'delphes_card_ATLAS.dat'),
5260 pjoin(self.me_dir,'Cards', 'delphes_card.dat'))
5261 return
5262 elif args[1] == 'cms':
5263 logger.info("set default CMS configuration for Delphes",'$MG:BOLD')
5264 files.cp(pjoin(self.me_dir,'Cards', 'delphes_card_CMS.dat'),
5265 pjoin(self.me_dir,'Cards', 'delphes_card.dat'))
5266 return
5267
5268 if args[0] in ['run_card', 'param_card', 'MadWeight_card', 'shower_card',
5269 'delphes_card','madanalysis5_hadron_card','madanalysis5_parton_card']:
5270
5271 if args[1] == 'default':
5272 logger.info('replace %s by the default card' % args[0],'$MG:BOLD')
5273 files.cp(self.paths['%s_default' %args[0][:-5]], self.paths[args[0][:-5]])
5274 if args[0] == 'param_card':
5275 self.param_card = param_card_mod.ParamCard(self.paths['param'])
5276 elif args[0] == 'run_card':
5277 self.run_card = banner_mod.RunCard(self.paths['run'])
5278 elif args[0] == 'shower_card':
5279 self.shower_card = shower_card_mod.ShowerCard(self.paths['shower'])
5280 return
5281 else:
5282 card = args[0]
5283 start=1
5284 if len(args) < 3:
5285 logger.warning('Invalid set command: %s (not enough arguments)' % line)
5286 return
5287
5288 elif args[0] in ['MadLoop_card']:
5289 if args[1] == 'default':
5290 logger.info('replace MadLoopParams.dat by the default card','$MG:BOLD')
5291 self.MLcard = banner_mod.MadLoopParam(self.MLcardDefault)
5292 self.MLcard.write(self.paths['ML'],
5293 commentdefault=True)
5294 return
5295 else:
5296 card = args[0]
5297 start=1
5298 if len(args) < 3:
5299 logger.warning('Invalid set command: %s (not enough arguments)' % line)
5300 return
5301 elif args[0] in ['pythia8_card']:
5302 if args[1] == 'default':
5303 logger.info('replace pythia8_card.dat by the default card','$MG:BOLD')
5304 self.PY8Card = self.PY8Card_class(self.PY8CardDefault)
5305 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'),
5306 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'),
5307 print_only_visible=True)
5308 return
5309 else:
5310 card = args[0]
5311 start=1
5312 if len(args) < 3:
5313 logger.warning('Invalid set command: %s (not enough arguments)' % line)
5314 return
5315 elif args[0] in ['madspin_card']:
5316 if args[1] == 'default':
5317 logger.info('replace madspin_card.dat by the default card','$MG:BOLD')
5318 files.cp(self.paths['MS_default'], self.paths['madspin'])
5319 return
5320 else:
5321 logger.warning("""Command set not allowed for modifying the madspin_card.
5322 Check the command \"decay\" instead.""")
5323 return
5324
5325
5326 if args[start] in [l.lower() for l in self.run_card.keys()] and card in ['', 'run_card']:
5327
5328 if args[start] not in self.run_set:
5329 if card in self.from_banner or 'run' in self.from_banner:
5330 raise Exception, "change not allowed for this card: event already generated!"
5331 args[start] = [l for l in self.run_set if l.lower() == args[start]][0]
5332
5333 if args[start] in self.conflict and card == '':
5334 text = 'Ambiguous name (present in more than one card). Will assume it to be referred to run_card.\n'
5335 text += 'If this is not intended, please reset it in the run_card and specify the relevant card to \n'
5336 text += 'edit, in the format < set card parameter value >'
5337 logger.warning(text)
5338
5339 if args[start+1] == 'default':
5340 default = banner_mod.RunCard(self.paths['run_default'])
5341 if args[start] in default.keys():
5342 self.setR(args[start],default[args[start]])
5343 else:
5344 logger.info('remove information %s from the run_card' % args[start],'$MG:BOLD')
5345 del self.run_card[args[start]]
5346 else:
5347 lower_name = args[0].lower()
5348 if lower_name.startswith('sys_') or \
5349 lower_name in self.run_card.list_parameter or \
5350 lower_name in self.run_card.dict_parameter:
5351 val = ' '.join(args[start+1:])
5352 val = val.split('#')[0]
5353 else:
5354 val = args[start+1]
5355 self.setR(args[start], val)
5356 self.modified_card.add('run')
5357
5358 elif card == 'run_card' and args[start] in ['nocut', 'no_cut']:
5359 logger.info("Going to remove all cuts from the run_card", '$MG:BOLD')
5360 self.run_card.remove_all_cut()
5361 self.modified_card.add('run')
5362
5363 elif self.param_card and (args[start] in self.param_card or args[start] == 'width') \
5364 and card in ['','param_card']:
5365
5366 if any(t.startswith('scan') for t in args):
5367 index = [i for i,t in enumerate(args) if t.startswith('scan')][0]
5368 args = args[:index] + [' '.join(args[index:])]
5369
5370 if args[start] in self.conflict and card == '':
5371 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
5372 text += ' in the format < set card parameter value>'
5373 logger.warning(text)
5374 return
5375
5376 if args[start] == 'width':
5377 args[start] = 'decay'
5378
5379 if args[start+1] in self.pname2block:
5380 all_var = self.pname2block[args[start+1]]
5381 key = None
5382 for bname, lhaid in all_var:
5383 if bname == args[start]:
5384 key = lhaid
5385 break
5386 else:
5387 logger.warning('%s is not part of block "%s" but "%s". please correct.' %
5388 (args[start+1], args[start], bname))
5389 return
5390 else:
5391 try:
5392 key = tuple([int(i) for i in args[start+1:-1]])
5393 except ValueError:
5394 if args[start] == 'decay' and args[start+1:-1] == ['all']:
5395 for key in self.param_card[args[start]].param_dict:
5396 if (args[start], key) in self.restricted_value:
5397 continue
5398 else:
5399 self.setP(args[start], key, args[-1])
5400 self.modified_card.add('param')
5401 return
5402 logger.warning('invalid set command %s (failed to identify LHA information)' % line)
5403 return
5404
5405 if key in self.param_card[args[start]].param_dict:
5406 if (args[start], key) in self.restricted_value:
5407 text = "Note that this parameter seems to be ignore by MG.\n"
5408 text += "MG will use instead the expression: %s\n" % \
5409 self.restricted_value[(args[start], key)]
5410 text += "You need to match this expression for external program (such pythia)."
5411 logger.warning(text)
5412
5413 if args[-1].lower() in ['default', 'auto', 'auto@nlo'] or args[-1].startswith('scan'):
5414 self.setP(args[start], key, args[-1])
5415 else:
5416 try:
5417 value = float(args[-1])
5418 except Exception:
5419 logger.warning('Invalid input: Expected number and not \'%s\'' \
5420 % args[-1])
5421 return
5422 self.setP(args[start], key, value)
5423 else:
5424 logger.warning('invalid set command %s' % line)
5425 return
5426 self.modified_card.add('param')
5427
5428
5429 elif args[start] in self.pname2block and card in ['','param_card']:
5430 if args[start] in self.conflict and card == '':
5431 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
5432 text += ' in the format < set card parameter value>'
5433 logger.warning(text)
5434 return
5435
5436 all_var = self.pname2block[args[start]]
5437 for bname, lhaid in all_var:
5438 new_line = 'param_card %s %s %s' % (bname,
5439 ' '.join([ str(i) for i in lhaid]), ' '.join(args[start+1:]))
5440 self.do_set(new_line)
5441 if len(all_var) > 1:
5442 logger.warning('This variable correspond to more than one parameter in the param_card.')
5443 for bname, lhaid in all_var:
5444 logger.warning(' %s %s' % (bname, ' '.join([str(i) for i in lhaid])))
5445 logger.warning('all listed variables have been modified')
5446
5447
5448 elif self.has_mw and (args[start] in self.mw_card and args[start] != 'comment') \
5449 and card in ['','MadWeight_card']:
5450
5451 if args[start] in self.conflict and card == '':
5452 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
5453 text += ' in the format < set card parameter value>'
5454 logger.warning(text)
5455 return
5456
5457 block = args[start]
5458 name = args[start+1]
5459 value = args[start+2:]
5460 self.setM(block, name, value)
5461 self.mw_card.write(self.paths['MadWeight'])
5462
5463
5464 elif self.has_mw and args[start] in self.mw_vars \
5465 and card in ['', 'MadWeight_card']:
5466
5467 if args[start] in self.conflict and card == '':
5468 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
5469 text += ' in the format < set card parameter value>'
5470 logger.warning(text)
5471 return
5472
5473 block = [b for b, data in self.mw_card.items() if args[start] in data]
5474 if len(block) > 1:
5475 logger.warning('%s is define in more than one block: %s.Please specify.'
5476 % (args[start], ','.join(block)))
5477 return
5478
5479 block = block[0]
5480 name = args[start]
5481 value = args[start+1:]
5482 self.setM(block, name, value)
5483 self.mw_card.write(self.paths['MadWeight'])
5484
5485
5486 elif self.has_mw and args[start].startswith('mw_') and len(args[start:]) == 3\
5487 and card == 'MadWeight_card':
5488 block = args[start]
5489 name = args[start+1]
5490 value = args[start+2]
5491 self.setM(block, name, value)
5492 self.mw_card.write(self.paths['MadWeight'])
5493
5494
5495 elif self.has_shower and args[start].lower() in [l.lower() for l in \
5496 self.shower_card.keys()] and card in ['', 'shower_card']:
5497 if args[start] not in self.shower_card:
5498 args[start] = [l for l in self.shower_card if l.lower() == args[start].lower()][0]
5499
5500 if args[start] in self.conflict and card == '':
5501 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
5502 text += ' in the format < set card parameter value>'
5503 logger.warning(text)
5504 return
5505
5506 if args[start+1].lower() == 'default':
5507 default = shower_card_mod.ShowerCard(self.paths['shower_default'])
5508 if args[start] in default.keys():
5509 self.shower_card.set_param(args[start],default[args[start]], self.paths['shower'])
5510 else:
5511 logger.info('remove information %s from the shower_card' % args[start],'$MG:BOLD')
5512 del self.shower_card[args[start]]
5513 elif args[start+1].lower() in ['t','.true.','true']:
5514 self.shower_card.set_param(args[start],'.true.',self.paths['shower'])
5515 elif args[start+1].lower() in ['f','.false.','false']:
5516 self.shower_card.set_param(args[start],'.false.',self.paths['shower'])
5517 elif args[start] in ['analyse', 'extralibs', 'extrapaths', 'includepaths'] or\
5518 args[start].startswith('dm_'):
5519
5520 args = line.split()
5521 args_str = ' '.join(str(a) for a in args[start+1:len(args)])
5522 self.shower_card.set_param(args[start],args_str,pjoin(self.me_dir,'Cards','shower_card.dat'))
5523 else:
5524 args_str = ' '.join(str(a) for a in args[start+1:len(args)])
5525 self.shower_card.set_param(args[start],args_str,self.paths['shower'])
5526
5527
5528 elif self.has_ml and args[start] in self.ml_vars \
5529 and card in ['', 'MadLoop_card']:
5530
5531 if args[start] in self.conflict and card == '':
5532 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
5533 logger.warning(text)
5534 return
5535
5536 if args[start+1] == 'default':
5537 value = self.MLcardDefault[args[start]]
5538 default = True
5539 else:
5540 value = args[start+1]
5541 default = False
5542 self.setML(args[start], value, default=default)
5543 self.MLcard.write(self.paths['ML'],
5544 commentdefault=True)
5545
5546
5547 elif self.has_PY8 and (card == 'pythia8_card' or (card == '' and \
5548 args[start] in self.PY8Card)):
5549
5550 if args[start] in self.conflict and card == '':
5551 text = 'ambiguous name (present in more than one card). Please specify which card to edit'
5552 logger.warning(text)
5553 return
5554
5555 if args[start+1] == 'default':
5556 value = self.PY8CardDefault[args[start]]
5557 default = True
5558 else:
5559 value = ' '.join(args[start+1:])
5560 default = False
5561 self.setPY8(args[start], value, default=default)
5562 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'),
5563 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'),
5564 print_only_visible=True)
5565
5566
5567 else:
5568 logger.warning('invalid set command %s ' % line)
5569 arg = args[start].lower()
5570 if self.has_PY8:
5571 close_opts = [name for name in self.PY8Card if name.lower().startswith(arg[:3]) or arg in name.lower()]
5572 if close_opts:
5573 logger.info('Did you mean one of the following PY8 options:\n%s' % '\t'.join(close_opts))
5574 if self.run_card:
5575 close_opts = [name for name in self.run_card if name.lower().startswith(arg[:3]) or arg in name.lower()]
5576 if close_opts:
5577 logger.info('Did you mean one of the following run_card options:\n%s' % '\t'.join(close_opts))
5578
5579 return
5580
5581 - def setM(self, block, name, value):
5582
5583 if isinstance(value, list) and len(value) == 1:
5584 value = value[0]
5585
5586 if block not in self.mw_card:
5587 logger.warning('block %s was not present in the current MadWeight card. We are adding it' % block)
5588 self.mw_card[block] = {}
5589 elif name not in self.mw_card[block]:
5590 logger.info('name %s was not present in the block %s for the current MadWeight card. We are adding it' % (name,block),'$MG:BOLD')
5591 if value == 'default':
5592 import madgraph.madweight.Cards as mwcards
5593 mw_default = mwcards.Card(self.paths['MadWeight_default'])
5594 try:
5595 value = mw_default[block][name]
5596 except KeyError:
5597 logger.info('removing id "%s" from Block "%s" '% (name, block),'$MG:BOLD')
5598 if name in self.mw_card[block]:
5599 del self.mw_card[block][name]
5600 return
5601 if value:
5602 logger.info('modify madweight_card information BLOCK "%s" with id "%s" set to %s',
5603 block, name, value, '$MG:BOLD')
5604 else:
5605 logger.warning("Invalid command: No value. To set default value. Use \"default\" as value")
5606 return
5607
5608 self.mw_card[block][name] = value
5609
5610 - def setR(self, name, value):
5611
5612 if self.mother_interface.inputfile:
5613 self.run_card.set(name, value, user=True, raiseerror=True)
5614 else:
5615 self.run_card.set(name, value, user=True)
5616 new_value = self.run_card.get(name)
5617 logger.info('modify parameter %s of the run_card.dat to %s' % (name, new_value),'$MG:BOLD')
5618
5619
5620 - def setML(self, name, value, default=False):
5621
5622 try:
5623 self.MLcard.set(name, value, user=True)
5624 except Exception, error:
5625 logger.warning("Fail to change parameter. Please Retry. Reason: %s." % error)
5626 return
5627 logger.info('modify parameter %s of the MadLoopParam.dat to %s' % (name, value),'$MG:BOLD')
5628 if default and name.lower() in self.MLcard.user_set:
5629 self.MLcard.user_set.remove(name.lower())
5630
5631 - def setPY8(self, name, value, default=False):
5640
5641 - def setP(self, block, lhaid, value):
5642 if isinstance(value, str):
5643 value = value.lower()
5644 if value == 'default':
5645 default = param_card_mod.ParamCard(self.paths['param_default'])
5646 value = default[block].param_dict[lhaid].value
5647
5648 elif value in ['auto', 'auto@nlo']:
5649 if 'nlo' in value:
5650 value = 'Auto@NLO'
5651 else:
5652 value = 'Auto'
5653 if block != 'decay':
5654 logger.warning('Invalid input: \'Auto\' value only valid for DECAY')
5655 return
5656 elif value.startswith('scan'):
5657 if ':' not in value:
5658 logger.warning('Invalid input: \'scan\' mode requires a \':\' before the definition.')
5659 return
5660 tag = value.split(':')[0]
5661 tag = tag[4:].strip()
5662 if tag and not tag.isdigit():
5663 logger.warning('Invalid input: scan tag need to be integer and not "%s"' % tag)
5664 return
5665
5666
5667 pass
5668 else:
5669 try:
5670 value = float(value)
5671 except ValueError:
5672 logger.warning('Invalid input: \'%s\' not valid intput.'% value)
5673
5674 logger.info('modify param_card information BLOCK %s with id %s set to %s' %\
5675 (block, lhaid, value), '$MG:BOLD')
5676 self.param_card[block].param_dict[lhaid].value = value
5677
5679 """This is run on quitting the class. Apply here all the self-consistency
5680 rule that you want. Do the modification via the set command."""
5681
5682
5683
5684
5685 if isinstance(self.run_card,banner_mod.RunCardLO):
5686
5687 proc_charac = self.mother_interface.proc_characteristics
5688 if proc_charac['grouped_matrix'] and \
5689 abs(self.run_card['lpp1']) == 1 == abs(self.run_card['lpp2']) and \
5690 (self.run_card['nb_proton1'] != self.run_card['nb_proton2'] or
5691 self.run_card['nb_neutron1'] != self.run_card['nb_neutron2'] or
5692 self.run_card['mass_ion1'] != self.run_card['mass_ion2']):
5693 raise Exception, "Heavy ion profile for both beam are different but the symmetry used forbids it. \n Please generate your process with \"set group_subprocesses False\"."
5694
5695
5696 for param in self.param_card['decay']:
5697 width = param.value
5698 if width == 0 or isinstance(width,str):
5699 continue
5700 try:
5701 mass = self.param_card['mass'].get(param.lhacode).value
5702 except Exception:
5703 continue
5704 if isinstance(mass,str):
5705 continue
5706
5707 if mass:
5708 if abs(width/mass) < self.run_card['small_width_treatment']:
5709 logger.warning("Particle %s will use a fake width ( %s instead of %s ).\n" +
5710 "Cross-section will be rescaled according to NWA if needed." +
5711 "To force exact treatment reduce the value of 'small_width_treatment' parameter of the run_card",
5712 param.lhacode[0], mass*self.run_card['small_width_treatment'], width)
5713 elif abs(width/mass) < 1e-12:
5714 logger.error('The width of particle %s is too small for an s-channel resonance (%s). If you have this particle in an s-channel, this is likely to create numerical instabilities .', param.lhacode[0], width)
5715 if CommonRunCmd.sleep_for_error:
5716 time.sleep(5)
5717 CommonRunCmd.sleep_for_error = False
5718
5719
5720
5721
5722
5723
5724 if isinstance(self.run_card,banner_mod.RunCardNLO):
5725 for pdg in set(self.run_card['pt_min_pdg'].keys()+self.run_card['pt_max_pdg'].keys()+
5726 self.run_card['mxx_min_pdg'].keys()):
5727
5728 if int(pdg)<0:
5729 raise Exception, "For PDG specific cuts, always use positive PDG codes: the cuts are applied to both particles and anti-particles"
5730 if self.param_card.get_value('mass', int(pdg), default=0) ==0:
5731 raise Exception, "For NLO runs, you can use PDG specific cuts only for massive particles: (failed for %s)" % pdg
5732
5733
5734 if 'reweight' in self.allow_arg and 'run' in self.allow_arg and \
5735 isinstance(self.run_card,banner_mod.RunCardNLO) and \
5736 not self.run_card['store_rwgt_info']:
5737
5738 re_pattern = re.compile(r'''^\s*change\s*mode\s* (LO\+NLO|LO|NLO|NLO_tree)\s*(?:#|$)''', re.M+re.I)
5739 text = open(self.paths['reweight']).read()
5740 options = re_pattern.findall(text)
5741 if any(o in ['NLO', 'LO+NLO'] for o in options):
5742 logger.info('NLO reweighting is on ON. Automatically set store_rwgt_info to True', '$MG:BOLD' )
5743 self.do_set('run_card store_rwgt_info True')
5744
5745
5746
5747 if 'run' in self.allow_arg and \
5748 self.run_card['systematics_program'] == 'systematics' and \
5749 isinstance(self.run_card,banner_mod.RunCardNLO) and \
5750 not self.run_card['store_rwgt_info']:
5751 logger.warning('To be able to run systematics program, we set store_rwgt_info to True')
5752 self.do_set('run_card store_rwgt_info True')
5753
5754
5755 if 'pythia_card.dat' in self.cards and 'run' in self.allow_arg:
5756 if self.run_card['event_norm'] != 'sum':
5757 logger.info('Pythia6 needs a specific normalisation of the events. We will change it accordingly.', '$MG:BOLD' )
5758 self.do_set('run_card event_norm sum')
5759
5760 elif 'pythia8_card.dat' in self.cards:
5761 if self.run_card['event_norm'] == 'sum':
5762 logger.info('Pythia8 needs a specific normalisation of the events. We will change it accordingly.', '$MG:BOLD' )
5763 self.do_set('run_card event_norm average')
5764
5765
5766 if self.has_shower and isinstance(self.run_card, banner_mod.RunCardNLO):
5767 modify_extralibs, modify_extrapaths = False,False
5768 extralibs = self.shower_card['extralibs'].split()
5769 extrapaths = self.shower_card['extrapaths'].split()
5770
5771 if self.run_card['parton_shower'] in ['PYTHIA8', 'HERWIGPP', 'HW7']:
5772 if 'stdhep' in self.shower_card['extralibs']:
5773 extralibs.remove('stdhep')
5774 modify_extralibs = True
5775 if 'Fmcfio' in self.shower_card['extralibs']:
5776 extralibs.remove('Fmcfio')
5777 modify_extralibs = True
5778 if self.run_card['parton_shower'] == 'PYTHIA8':
5779
5780 if not self.mother_interface.options['pythia8_path']:
5781 raise self.mother_interface.InvalidCmd, 'Pythia8 is not correctly specified to MadGraph5_aMC@NLO'
5782 executable = pjoin(self.mother_interface.options['pythia8_path'], 'bin', 'pythia8-config')
5783 if not os.path.exists(executable):
5784 raise self.mother.InvalidCmd, 'Pythia8 is not correctly specified to MadGraph5_aMC@NLO'
5785
5786
5787 libs , paths = [], []
5788 p = misc.subprocess.Popen([executable, '--libs'], stdout=subprocess.PIPE)
5789 stdout, _ = p. communicate()
5790 libs = [x[2:] for x in stdout.split() if x.startswith('-l') or paths.append(x[2:])]
5791
5792
5793 p = misc.subprocess.Popen([executable, '--config'], stdout=subprocess.PIPE)
5794 stdout, _ = p. communicate()
5795 for lib in ['-ldl','-lstdc++','-lc++']:
5796 if lib in stdout:
5797 libs.append(lib[2:])
5798
5799
5800
5801 supports_HEPMCHACK = '-DHEPMC2HACK' in stdout
5802
5803
5804 for l in libs:
5805 if l not in extralibs:
5806 modify_extralibs = True
5807 extralibs.append(l)
5808 for L in paths:
5809 if L not in extrapaths:
5810 modify_extrapaths = True
5811 extrapaths.append(L)
5812
5813
5814 if modify_extralibs:
5815 if extralibs:
5816 self.do_set('shower_card extralibs %s ' % ' '.join(extralibs))
5817 else:
5818 self.do_set('shower_card extralibs None ')
5819 if modify_extrapaths:
5820 if extrapaths:
5821 self.do_set('shower_card extrapaths %s ' % ' '.join(extrapaths))
5822 else:
5823 self.do_set('shower_card extrapaths None ')
5824
5825
5826 for key in list(self.modified_card):
5827 self.write_card(key)
5828
5829
5830 - def reask(self, *args, **opt):
5831
5832 cmd.OneLinePathCompletion.reask(self,*args, **opt)
5833 if self.has_mw and not os.path.exists(pjoin(self.me_dir,'Cards','transfer_card.dat')):
5834 logger.warning('No transfer function currently define. Please use the change_tf command to define one.')
5835
5836 fail_due_to_format = 0
5837 - def postcmd(self, stop, line):
5838
5839 if line not in [None, '0', 'done', '']:
5840 ending_question = cmd.OneLinePathCompletion.postcmd(self,stop,line)
5841 else:
5842 ending_question = True
5843
5844 if ending_question:
5845 self.check_card_consistency()
5846 if self.param_consistency:
5847 try:
5848 self.do_update('dependent', timer=20)
5849 except MadGraph5Error, error:
5850 if 'Missing block:' in str(error):
5851 self.fail_due_to_format +=1
5852 if self.fail_due_to_format == 10:
5853 missing, unknow = str(error).split('\n')[-2:]
5854 logger.warning("Invalid param_card:\n%s\n%s\n" % (missing, unknow))
5855 logger.info("Type \"update missing\" to use default value.\n ", '$MG:BOLD')
5856 self.value = False
5857 return self.reask(True)
5858 else:
5859 raise
5860
5861 return ending_question
5862
5863
5864
5865
5866
5868 """ syntax: update dependent: Change the mass/width of particles which are not free parameter for the model.
5869 update missing: add to the current param_card missing blocks/parameters.
5870 update to_slha1: pass SLHA2 card to SLHA1 convention. (beta)
5871 update to_slha2: pass SLHA1 card to SLHA2 convention. (beta)
5872 update to_full [run_card]
5873 update XXX [where XXX correspond to a hidden block of the run_card]
5874 """
5875 args = self.split_arg(line)
5876 if len(args)==0:
5877 logger.warning('miss an argument (dependent or missing). Please retry')
5878 return
5879
5880 if args[0] == 'dependent':
5881 if not self.mother_interface:
5882 logger.warning('Failed to update dependent parameter. This might create trouble for external program (like MadSpin/shower/...)')
5883
5884 pattern_width = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I)
5885 pattern_scan = re.compile(r'''^(decay)?[\s\d]*scan''', re.I+re.M)
5886 param_text= open(self.paths['param']).read()
5887
5888 if pattern_scan.search(param_text):
5889
5890
5891
5892 return
5893 elif pattern_width.search(param_text):
5894 self.do_compute_widths('')
5895 self.param_card = param_card_mod.ParamCard(self.paths['param'])
5896
5897
5898 self.update_dependent(self.mother_interface, self.me_dir, self.param_card,
5899 self.paths['param'], timer)
5900
5901 elif args[0] == 'missing':
5902 self.update_missing()
5903 return
5904
5905 elif args[0] == 'to_slha2':
5906 try:
5907 param_card_mod.convert_to_mg5card(self.paths['param'])
5908 logger.info('card updated')
5909 except Exception, error:
5910 logger.warning('failed to update to slha2 due to %s' % error)
5911 self.param_card = param_card_mod.ParamCard(self.paths['param'])
5912 elif args[0] == 'to_slha1':
5913 try:
5914 param_card_mod.convert_to_slha1(self.paths['param'])
5915 logger.info('card updated')
5916 except Exception, error:
5917 logger.warning('failed to update to slha1 due to %s' % error)
5918 self.param_card = param_card_mod.ParamCard(self.paths['param'])
5919 elif args[0] == 'to_full':
5920 return self.update_to_full(args[1:])
5921 elif args[0] in self.update_block:
5922 self.run_card.display_block.append(args[0].lower())
5923 self.modified_card.add('run')
5924 logger.info('add optional block %s to the run_card', args[0])
5925 else:
5926 self.help_update()
5927 logger.warning('unvalid options for update command. Please retry')
5928
5929
5931 """ trigger via update to_full LINE"""
5932
5933 logger.info("update the run_card by including all the hidden parameter")
5934 self.run_card.write(self.paths['run'], self.paths['run_default'], write_hidden=True)
5935 if 'run' in self.modified_card:
5936 self.modified_card.remove('run')
5937
5939 """proxy on how to write any card"""
5940
5941 if hasattr(self, 'write_card_%s' % name):
5942 getattr(self, 'write_card_%s' % name)()
5943 if name in self.modified_card:
5944 self.modified_card.remove(name)
5945 else:
5946 raise Exception, "Need to add the associate writter proxy"
5947
5949 """ write the run_card """
5950 self.run_card.write(self.paths['run'], self.paths['run_default'])
5951
5953 """ write the param_card """
5954 self.param_card.write(self.paths['param'])
5955
5956 @staticmethod
5958 """static method which can also be called from outside the class
5959 usefull in presence of scan.
5960 return if the param_card was updated or not
5961 """
5962
5963 if not param_card:
5964 return False
5965
5966 logger.info('Update the dependent parameter of the param_card.dat')
5967 modify = True
5968 class TimeOutError(Exception):
5969 pass
5970 def handle_alarm(signum, frame):
5971 raise TimeOutError
5972 signal.signal(signal.SIGALRM, handle_alarm)
5973 if timer:
5974 signal.alarm(timer)
5975 log_level=30
5976 else:
5977 log_level=20
5978
5979 try:
5980 model = mecmd.get_model()
5981 signal.alarm(0)
5982 except TimeOutError:
5983 logger.warning('The model takes too long to load so we bypass the updating of dependent parameter.\n'+\
5984 'This might create trouble for external program (like MadSpin/shower/...)\n'+\
5985 'The update can be forced without timer by typing \'update dependent\' at the time of the card edition')
5986 modify =False
5987 except Exception,error:
5988 logger.debug(str(error))
5989 logger.warning('Failed to update dependent parameter. This might create trouble for external program (like MadSpin/shower/...)')
5990 signal.alarm(0)
5991 else:
5992 restrict_card = pjoin(me_dir,'Source','MODEL','param_card_rule.dat')
5993 if not os.path.exists(restrict_card):
5994 restrict_card = None
5995
5996 if model:
5997 modify = param_card.update_dependent(model, restrict_card, log_level)
5998 if modify and path:
5999 param_card.write(path)
6000 else:
6001 logger.warning('missing MG5aMC code. Fail to update dependent parameter. This might create trouble for program like MadSpin/shower/...')
6002
6003 if log_level==20:
6004 logger.info('param_card up to date.')
6005
6006 return modify
6007
6008
6009
6011
6012 def check_block(self, blockname):
6013 add_entry = 0
6014 if blockname.lower() not in self.param_card_default:
6015 logger.info('unknow block %s: block will be ignored', blockname)
6016 return add_entry
6017 block = self.param_card_default[blockname]
6018 for key in block.keys():
6019 if key not in input_in_block:
6020 param = block.get(key)
6021 if blockname != 'decay':
6022 text.append('\t%s\t%s # %s\n' % (' \t'.join([`i` for i in param.lhacode]), param.value, param.comment))
6023 else:
6024 text.append('DECAY \t%s\t%s # %s\n' % (' \t'.join([`i` for i in param.lhacode]), param.value, param.comment))
6025 add_entry += 1
6026 if add_entry:
6027 text.append('\n')
6028 if add_entry:
6029 logger.info("Adding %s parameter(s) to block %s", add_entry, blockname)
6030 return add_entry
6031
6032
6033 current_block = ''
6034 input_in_block = set()
6035 defined_blocks = set()
6036 decay = set()
6037 text = []
6038 add_entry = 0
6039 for line in open(self.paths['param']):
6040
6041 new_block = re.findall(r'^\s*(block|decay)\s*(\w*)', line, re.I)
6042 if new_block:
6043 new_block = new_block[0]
6044 defined_blocks.add(new_block[1].lower())
6045 if current_block:
6046 add_entry += check_block(self, current_block)
6047
6048 current_block= new_block[1]
6049 input_in_block = set()
6050 if new_block[0].lower() == 'decay':
6051 decay.add((int(new_block[1]),))
6052 current_block = ''
6053 if new_block[1].lower() == 'qnumbers':
6054 current_block = ''
6055
6056 text.append(line)
6057 if not current_block:
6058 continue
6059
6060
6061
6062 line = line.split('#',1)[0]
6063 split = line.split()
6064 if not split:
6065 continue
6066 else:
6067 try:
6068 lhacode = [int(i) for i in split[:-1]]
6069 except:
6070 continue
6071 input_in_block.add(tuple(lhacode))
6072
6073 if current_block:
6074 add_entry += check_block(self, current_block)
6075
6076
6077 for block in self.param_card_default:
6078
6079 if block.startswith(('qnumbers', 'decay')):
6080 continue
6081
6082 if block not in defined_blocks:
6083 nb_entry = len(self.param_card_default[block])
6084 logger.info("Block %s was missing. Adding the %s associated parameter(s)", block,nb_entry)
6085 add_entry += nb_entry
6086 text.append(str(self.param_card_default[block]))
6087
6088
6089 input_in_block = decay
6090 add_entry += check_block(self, 'decay')
6091
6092 if add_entry:
6093 logger.info('write new param_card with %s new parameter(s).', add_entry, '$MG:BOLD')
6094 open(self.paths['param'],'w').write(''.join(text))
6095 self.reload_card(self.paths['param'])
6096 else:
6097 logger.info('No missing parameter detected.', '$MG:BOLD')
6098
6099
6104
6132
6134
6135 line = line.strip()
6136 args = line.split()
6137
6138 if not args:
6139 return line
6140 if not hasattr(self, 'trigger_%s' % args[0]):
6141 return line
6142
6143 triggerfct = getattr(self, 'trigger_%s' % args[0])
6144
6145
6146 outline = triggerfct(' '.join(args[1:]))
6147 if not outline:
6148 return 'repeat'
6149 return outline
6150
6152 """Default action if line is not recognized"""
6153
6154
6155 line = self.trigger(line)
6156
6157
6158 line = line.strip()
6159 args = line.split()
6160 if line == '' and self.default_value is not None:
6161 self.value = self.default_value
6162
6163 elif hasattr(self, 'do_%s' % args[0]):
6164 self.do_set(' '.join(args[1:]))
6165 elif line.strip() != '0' and line.strip() != 'done' and \
6166 str(line) != 'EOF' and line.strip() in self.allow_arg:
6167 self.open_file(line)
6168 self.value = 'repeat'
6169 elif os.path.isfile(line):
6170 self.copy_file(line)
6171 self.value = 'repeat'
6172 elif self.me_dir and os.path.exists(pjoin(self.me_dir, line)):
6173 self.copy_file(pjoin(self.me_dir,line))
6174 self.value = 'repeat'
6175 elif line.strip().startswith(('http:','www', 'https')):
6176 self.value = 'repeat'
6177 import tempfile
6178 fsock, path = tempfile.mkstemp()
6179 try:
6180 text = urllib.urlopen(line.strip())
6181 url = line.strip()
6182 except Exception:
6183 logger.error('fail to load the file')
6184 else:
6185 for line in text:
6186 os.write(fsock, line)
6187 os.close(fsock)
6188 self.copy_file(path, pathname=url)
6189 os.remove(path)
6190
6191
6192 else:
6193 self.value = line
6194
6195 return line
6196
6197
6199 """edit the madspin_card to define the decay of the associate particle"""
6200 signal.alarm(0)
6201 path = self.paths['madspin']
6202
6203 if 'madspin_card.dat' not in self.cards or not os.path.exists(path):
6204 logger.warning("Command decay not valid. Since MadSpin is not available.")
6205 return
6206
6207 if ">" not in line:
6208 logger.warning("invalid command for decay. Line ignored")
6209 return
6210
6211 if "-add" in line:
6212
6213 particle = line.split('>')[0].strip()
6214 text = open(path).read()
6215 line = line.replace('--add', '').replace('-add','')
6216 logger.info("change madspin_card to add one decay to %s: %s" %(particle, line.strip()), '$MG:BOLD')
6217 if 'launch' in text:
6218 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1)
6219 else:
6220 text += '\ndecay %s\n launch \n' % line
6221 else:
6222
6223
6224 particle = line.split('>')[0].strip()
6225 logger.info("change madspin_card to define the decay of %s: %s" %(particle, line.strip()), '$MG:BOLD')
6226 particle = particle.replace('+','\+').replace('-','\-')
6227 decay_pattern = re.compile(r"^\s*decay\s+%s\s*>[\s\w+-~]*?$" % particle, re.I+re.M)
6228 text= open(path).read()
6229 text = decay_pattern.sub('', text)
6230 if 'launch' in text:
6231 text = text.replace('launch', "\ndecay %s\nlaunch\n" % line,1)
6232 else:
6233 text += '\ndecay %s\n launch \n' % line
6234
6235 with open(path,'w') as fsock:
6236 fsock.write(text)
6237 self.reload_card(path)
6238
6239
6240
6242 signal.alarm(0)
6243
6244
6245 if 'param' in self.modified_card:
6246 self.write_card('param')
6247 self.modified_card.discard('param')
6248
6249 path = self.paths['param']
6250 pattern = re.compile(r'''decay\s+(\+?\-?\d+)\s+auto(@NLO|)''',re.I)
6251 text = open(path).read()
6252 pdg_info = pattern.findall(text)
6253 has_nlo = any("@nlo"==nlo.lower() for _, nlo in pdg_info)
6254 pdg = [p for p,_ in pdg_info]
6255
6256
6257 line = '%s %s' % (line, ' '.join(pdg))
6258 if not '--path' in line:
6259 line += ' --path=%s' % path
6260 if has_nlo:
6261 line += ' --nlo'
6262
6263 try:
6264 return self.mother_interface.do_compute_widths(line)
6265 except InvalidCmd, error:
6266 logger.error("Invalid command: %s " % error)
6267
6271
6273 """help for command decay which modifies MadSpin_card"""
6274
6275 signal.alarm(0)
6276 print '--syntax: decay PROC [--add]'
6277 print ' '
6278 print ' modify the madspin_card to modify the decay of the associate particle.'
6279 print ' and define it to PROC.'
6280 print ' if --add is present, just add a new decay for the associate particle.'
6281
6283 prev_timer = signal.alarm(0)
6284 if prev_timer:
6285 nb_back = len(line)
6286 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
6287 self.stdout.write(line)
6288 self.stdout.flush()
6289 return self.mother_interface.complete_compute_widths(text, line, begidx, endidx,**opts)
6290
6291
6293 """help for add command"""
6294
6295 logger.info('********************* HELP ADD ***************************')
6296 logger.info( '-- syntax: add pythia8_card NAME VALUE')
6297 logger.info( " add a definition of name in the pythia8_card with the given value")
6298 logger.info( " Do not work for the param_card" )
6299 logger.info('')
6300 return self.help_edit(prefix=False)
6301
6303 """help for edit command"""
6304
6305 if prefix: logger.info('********************* HELP ADD|EDIT ***************************')
6306 logger.info( '-- syntax: add filename [OPTION] LINE')
6307 logger.info( '-- syntax: edit filename [OPTION] LINE')
6308 logger.info( ' add the given LINE to the end of the associate file (all file supported).')
6309 logger.info( '')
6310 logger.info( ' OPTION parameter allows to change the position where to write in the file')
6311 logger.info( ' --after_line=banner : write the line at the end of the banner')
6312 logger.info( ' --line_position=X : insert the line before line X (starts at 0)')
6313 logger.info( ' --line_position=afterlast : insert the line after the latest inserted/modified line.')
6314 logger.info( ' --after_line="<regular-expression>" write the line after the first line matching the regular expression')
6315 logger.info( ' --before_line="<regular-expression>" write the line before the first line matching the regular expression')
6316 logger.info( ' --replace_line="<regular-expression>" replace the line matching the regular expression')
6317 logger.info( ' --clean remove all previously existing line in the file')
6318 logger.info('')
6319 logger.info(' Note: all regular-expression will be prefixed by ^\s*')
6320 logger.info('')
6321 logger.info( ' example: edit reweight --after_line="change mode\b" change model heft')
6322 logger.info( ' edit madspin --after_line="banner" change model XXXX')
6323 logger.info('********************* HELP ADD|EDIT ***************************')
6324
6325
6326 - def complete_add(self, text, line, begidx, endidx, formatting=True):
6327 """ auto-completion for add command"""
6328
6329 prev_timer = signal.alarm(0)
6330 if prev_timer:
6331 nb_back = len(line)
6332 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
6333 self.stdout.write(line)
6334 self.stdout.flush()
6335
6336 split = line[:begidx].split()
6337 if len(split)==1:
6338 possibilities = {}
6339 cards = [c.rsplit('.',1)[0] for c in self.cards]
6340 possibilities['category of parameter (optional)'] = \
6341 self.list_completion(text, cards)
6342 elif len(split) == 2:
6343 possibilities = {}
6344 options = ['--line_position=','--line_position=afterlast','--after_line=banner', '--after_line="','--before_line="']
6345 possibilities['category of parameter (optional)'] = \
6346 self.list_completion(text, options, line)
6347 else:
6348 return
6349 return self.deal_multiple_categories(possibilities, formatting)
6350
6352 """ syntax: add filename NAME VALUE
6353 syntax: add filename LINE"""
6354
6355 args = self.split_arg(line)
6356 if len(args) == 3 and args[0] in ['pythia8_card', 'pythia8_card.dat'] and self.has_PY8:
6357 name= args[1]
6358 value = args[2]
6359 self.PY8Card.userSet(name, value)
6360 self.PY8Card.write(pjoin(self.me_dir,'Cards','pythia8_card.dat'),
6361 pjoin(self.me_dir,'Cards','pythia8_card_default.dat'),
6362 print_only_visible=True)
6363 logger.info("add in the pythia8_card the parameter \"%s\" with value \"%s\"" % (name, value), '$MG:BOLD')
6364 elif len(args) > 0:
6365 if args[0] in self.cards:
6366 card = args[0]
6367 elif "%s.dat" % args[0] in self.cards:
6368 card = "%s.dat" % args[0]
6369 elif "%s_card.dat" % args[0] in self.cards:
6370 card = "%s_card.dat" % args[0]
6371 elif self.has_ml and args[0].lower() == "madloop":
6372 card = "MadLoopParams.dat"
6373 else:
6374 logger.error("unknow card %s. Please retry." % args[0])
6375 return
6376
6377 if card in self.modified_card:
6378 self.write_card(card)
6379 self.modified_card.discard(card)
6380
6381 if card in self.paths:
6382 path = self.paths[card]
6383 elif os.path.exists(card):
6384 path = card
6385 elif os.path.exists(pjoin(self.me_dir,'Cards',card)):
6386 path = pjoin(self.me_dir,'Cards',card)
6387 else:
6388 raise Exception, 'unknow path'
6389
6390
6391 if args[1] == '--clean':
6392 ff = open(path,'w')
6393 ff.write("# %s \n" % card)
6394 ff.write("%s \n" % line.split(None,2)[2])
6395 ff.close()
6396 logger.info("writing the line in %s (empty file) the line: \"%s\"" %(card, line.split(None,2)[2] ),'$MG:BOLD')
6397 elif args[1].startswith('--line_position=afterlast'):
6398
6399 text = open(path).read()
6400 split = text.split('\n')
6401 if self.last_editline_pos > 0:
6402 pos = self.last_editline_pos +1
6403 newline = line.split(None,2)[2]
6404 split.insert(pos, newline)
6405 ff = open(path,'w')
6406 ff.write('\n'.join(split))
6407 logger.info("writting at line %d of the file %s the line: \"%s\"" %(pos, card, line.split(None,2)[2] ),'$MG:BOLD')
6408 self.last_editline_pos = pos
6409 elif args[1].startswith('--line_position='):
6410
6411 text = open(path).read()
6412 split = text.split('\n')
6413 pos = int(args[1].split('=',1)[1])
6414 newline = line.split(None,2)[2]
6415 split.insert(pos, newline)
6416 ff = open(path,'w')
6417 ff.write('\n'.join(split))
6418 logger.info("writting at line %d of the file %s the line: \"%s\"" %(pos, card, line.split(None,2)[2] ),'$MG:BOLD')
6419 self.last_editline_pos = pos
6420
6421 elif args[1].startswith(('--after_line=banner','--after_line=\'banner\'','--after_line=\"banner\"')):
6422
6423 text = open(path).read()
6424 split = text.split('\n')
6425 for posline,l in enumerate(split):
6426 if not l.startswith('#'):
6427 break
6428 split.insert(posline, line.split(None,2)[2])
6429 ff = open(path,'w')
6430 ff.write('\n'.join(split))
6431 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,2)[2] ),'$MG:BOLD')
6432 self.last_editline_pos = posline
6433
6434 elif args[1].startswith('--replace_line='):
6435
6436
6437 text = open(path).read()
6438 split = text.split('\n')
6439 search_pattern=r'''replace_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1'''
6440 pattern = '^\s*' + re.search(search_pattern, line).group()[14:-1]
6441 for posline,l in enumerate(split):
6442 if re.search(pattern, l):
6443 break
6444 else:
6445 new_line = re.split(search_pattern,line)[-1].strip()
6446 if new_line.startswith(('--before_line=','--after_line')):
6447 return self.do_add('%s %s' % (args[0], new_line))
6448 raise Exception, 'invalid regular expression: not found in file'
6449
6450
6451 new_line = re.split(search_pattern,line)[-1].strip()
6452 if new_line.startswith(('--before_line=','--after_line')):
6453 search_pattern=r'''(?:before|after)_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1'''
6454 new_line = re.split(search_pattern,new_line)[-1]
6455
6456 old_line = split[posline]
6457 split[posline] = new_line
6458 ff = open(path,'w')
6459 ff.write('\n'.join(split))
6460 logger.info("Replacing the line \"%s\" [line %d of %s] by \"%s\"" %
6461 (old_line, posline, card, new_line ),'$MG:BOLD')
6462 self.last_editline_pos = posline
6463
6464
6465 elif args[1].startswith('--before_line='):
6466
6467 text = open(path).read()
6468 split = text.split('\n')
6469 search_pattern=r'''before_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1'''
6470 pattern = '^\s*' + re.search(search_pattern, line).group()[13:-1]
6471 for posline,l in enumerate(split):
6472 if re.search(pattern, l):
6473 break
6474 else:
6475 raise Exception, 'invalid regular expression: not found in file'
6476 split.insert(posline, re.split(search_pattern,line)[-1])
6477 ff = open(path,'w')
6478 ff.write('\n'.join(split))
6479 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,2)[2] ),'$MG:BOLD')
6480 self.last_editline_pos = posline
6481
6482 elif args[1].startswith('--after_line='):
6483
6484 text = open(path).read()
6485 split = text.split('\n')
6486 search_pattern = r'''after_line=(?P<quote>["'])(?:(?=(\\?))\2.)*?\1'''
6487 pattern = '^\s*' + re.search(search_pattern, line).group()[12:-1]
6488 for posline,l in enumerate(split):
6489 if re.search(pattern, l):
6490 break
6491 else:
6492 posline=len(split)
6493 split.insert(posline+1, re.split(search_pattern,line)[-1])
6494 ff = open(path,'w')
6495 ff.write('\n'.join(split))
6496
6497 logger.info("writting at line %d of the file %s the line: \"%s\"" %(posline, card, line.split(None,2)[2] ),'$MG:BOLD')
6498 self.last_editline_pos = posline
6499
6500 else:
6501 ff = open(path,'a')
6502 ff.write("%s \n" % line.split(None,1)[1])
6503 ff.close()
6504 logger.info("adding at the end of the file %s the line: \"%s\"" %(card, line.split(None,1)[1] ),'$MG:BOLD')
6505 self.last_editline_pos = -1
6506
6507 self.reload_card(path)
6508
6509 do_edit = do_add
6510 complete_edit = complete_add
6511
6513 """Help associated to the asperge command"""
6514 signal.alarm(0)
6515
6516 print '-- syntax: asperge [options]'
6517 print ' Call ASperGe to diagonalize all mass matrices in the model.'
6518 print ' This works only if the ASperGE module is part of the UFO model (a subdirectory).'
6519 print ' If you specify some names after the command (i.e. asperge m1 m2) then ASperGe will only'
6520 print ' diagonalize the associate mass matrices (here m1 and m2).'
6521
6523 prev_timer = signal.alarm(0)
6524 if prev_timer:
6525 nb_back = len(line)
6526 self.stdout.write('\b'*nb_back + '[timer stopped]\n')
6527 self.stdout.write(line)
6528 self.stdout.flush()
6529 blockname = self.pname2block.keys()
6530
6531 wrong = ['decay', 'mass', 'sminput']
6532 valid = [k for k in blockname if 'mix' in k]
6533 potential = [k for k in blockname if k not in valid+wrong]
6534 output = {'Mixing matrices': self.list_completion(text, valid, line),
6535 'Other potential valid input': self.list_completion(text, potential, line)}
6536
6537 return self.deal_multiple_categories(output, formatting)
6538
6539
6541 """Running ASperGe"""
6542 signal.alarm(0)
6543
6544
6545 if 'param' in self.modified_card:
6546 self.write_card('param')
6547 self.modified_card.discard('param')
6548
6549
6550 path = pjoin(self.me_dir,'bin','internal','ufomodel','ASperGE')
6551 if not os.path.exists(path):
6552 logger.error('ASperge has not been detected in the current model, therefore it will not be run.')
6553 return
6554 elif not os.path.exists(pjoin(path,'ASperGe')):
6555 logger.info('ASperGe has been detected but is not compiled. Running the compilation now.')
6556 try:
6557 misc.compile(cwd=path,shell=True)
6558 except MadGraph5Error, error:
6559 logger.error('''ASperGe failed to compile. Note that gsl is needed
6560 for this compilation to go trough. More information on how to install this package on
6561 http://www.gnu.org/software/gsl/
6562 Full compilation log is available at %s''' % pjoin(self.me_dir, 'ASperge_compilation.log'))
6563 open(pjoin(self.me_dir, 'ASperge_compilation.log'),'w').write(str(error))
6564 return
6565
6566 opts = line.split()
6567 card = self.paths['param']
6568 logger.info('running ASperGE')
6569 returncode = misc.call([pjoin(path,'ASperGe'), card, '%s.new' % card] + opts)
6570 if returncode:
6571 logger.error('ASperGE fails with status %s' % returncode)
6572 else:
6573 logger.info('AsPerGe creates the file succesfully')
6574 files.mv(card, '%s.beforeasperge' % card)
6575 files.mv('%s.new' % card, card)
6576
6577
6578
6580 """detect the type of the file and overwritte the current file"""
6581
6582 if not pathname:
6583 pathname = path
6584
6585 if path.endswith('.lhco'):
6586
6587
6588 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir))
6589 return
6590 elif path.endswith('.lhco.gz'):
6591
6592
6593 self.do_set('mw_run inputfile %s' % os.path.relpath(path, self.mother_interface.me_dir))
6594 return
6595 else:
6596 card_name = self.detect_card_type(path)
6597
6598 if card_name == 'unknown':
6599 logger.warning('Fail to determine the type of the file. Not copied')
6600 if card_name != 'banner':
6601 logger.info('copy %s as %s' % (pathname, card_name))
6602 files.cp(path, self.paths[card_name.rsplit('_',1)[0]])
6603 self.reload_card(self.paths[card_name.rsplit('_',1)[0]])
6604 elif card_name == 'banner':
6605 banner_mod.split_banner(path, self.mother_interface.me_dir, proc_card=False)
6606 logger.info('Splitting the banner in it\'s component')
6607 if not self.mode == 'auto':
6608 self.mother_interface.keep_cards(self.cards)
6609 for card_name in self.cards:
6610 self.reload_card(pjoin(self.me_dir, 'Cards', card_name))
6611
6616
6618 """open the file"""
6619
6620 try:
6621 me_dir = self.mother_interface.me_dir
6622 except:
6623 me_dir = None
6624
6625 if answer.isdigit():
6626 if answer == '9':
6627 answer = 'plot'
6628 else:
6629 answer = self.cards[int(answer)-self.integer_bias]
6630
6631 if 'madweight' in answer:
6632 answer = answer.replace('madweight', 'MadWeight')
6633 elif 'MadLoopParams' in answer:
6634 answer = self.paths['ML']
6635 elif 'pythia8_card' in answer:
6636 answer = self.paths['pythia8']
6637 if os.path.exists(answer):
6638 path = answer
6639 else:
6640 if not '.dat' in answer and not '.lhco' in answer:
6641 if answer != 'trigger':
6642 path = self.paths[answer]
6643 else:
6644 path = self.paths['delphes']
6645 elif not '.lhco' in answer:
6646 if '_' in answer:
6647 path = self.paths['_'.join(answer.split('_')[:-1])]
6648 else:
6649 path = pjoin(me_dir, 'Cards', answer)
6650 else:
6651 path = pjoin(me_dir, self.mw_card['mw_run']['inputfile'])
6652 if not os.path.exists(path):
6653 logger.info('Path in MW_card not existing')
6654 path = pjoin(me_dir, 'Events', answer)
6655
6656 path = path.replace('_card_card','_card')
6657
6658 if answer in self.modified_card:
6659 self.write_card(answer)
6660 elif os.path.basename(answer.replace('_card.dat','')) in self.modified_card:
6661 self.write_card(os.path.basename(answer.replace('_card.dat','')))
6662
6663 try:
6664 self.mother_interface.exec_cmd('open %s' % path)
6665 except InvalidCmd, error:
6666 if str(error) != 'No default path for this file':
6667 raise
6668 if answer == 'transfer_card.dat':
6669 logger.warning('You have to specify a transfer function first!')
6670 elif answer == 'input.lhco':
6671 path = pjoin(me_dir,'Events', 'input.lhco')
6672 ff = open(path,'w')
6673 ff.write('''No LHCO information imported at current time.
6674 To import a lhco file: Close this file and type the path of your file.
6675 You can also copy/paste, your event file here.''')
6676 ff.close()
6677 self.open_file(path)
6678 else:
6679 raise
6680 self.reload_card(path)
6681
6683 """reload object to have it in sync"""
6684
6685 if path == self.paths['param']:
6686 try:
6687 self.param_card = param_card_mod.ParamCard(path)
6688 except (param_card_mod.InvalidParamCard, ValueError) as e:
6689 logger.error('Current param_card is not valid. We are going to use the default one.')
6690 logger.error('problem detected: %s' % e)
6691 logger.error('Please re-open the file and fix the problem.')
6692 logger.warning('using the \'set\' command without opening the file will discard all your manual change')
6693 elif path == self.paths['run']:
6694 self.run_card = banner_mod.RunCard(path)
6695 elif path == self.paths['shower']:
6696 self.shower_card = shower_card_mod.ShowerCard(path)
6697 elif path == self.paths['ML']:
6698 self.MLcard = banner_mod.MadLoopParam(path)
6699 elif path == self.paths['pythia8']:
6700
6701
6702 if not self.PY8Card:
6703 self.PY8Card = self.PY8Card_class(self.paths['pythia8_default'])
6704
6705 self.PY8Card.read(self.paths['pythia8'], setter='user')
6706 self.py8_vars = [k.lower() for k in self.PY8Card.keys()]
6707 elif path == self.paths['MadWeight']:
6708 try:
6709 import madgraph.madweight.Cards as mwcards
6710 except:
6711 import internal.madweight.Cards as mwcards
6712 self.mw_card = mwcards.Card(path)
6713 else:
6714 logger.debug('not keep in sync: %s', path)
6715 return path
6716
6717
6718
6719 -def scanparamcardhandling(input_path=lambda obj: pjoin(obj.me_dir, 'Cards', 'param_card.dat'),
6720 store_for_scan=lambda obj: obj.store_scan_result,
6721 get_run_name=lambda obj: obj.run_name,
6722 set_run_name=lambda obj: obj.set_run_name,
6723 result_path=lambda obj: pjoin(obj.me_dir, 'Events', 'scan_%s.txt' ),
6724 ignoreerror=ZeroResult,
6725 iteratorclass=param_card_mod.ParamCardIterator,
6726 summaryorder=lambda obj: lambda:None,
6727 check_card=lambda obj: CommonRunCmd.static_check_param_card,
6728 ):
6729 """ This is a decorator for customizing/using scan over the param_card (or technically other)
6730 This should be use like this:
6731
6732 @scanparamcardhandling(arguments)
6733 def run_launch(self, *args, **opts)
6734
6735 possible arguments are listed above and should be function who takes a single
6736 argument the instance of intereset. those return
6737 input_path -> function that return the path of the card to read
6738 store_for_scan -> function that return a dict of entry to keep in memory
6739 get_run_name -> function that return the string with the current run_name
6740 set_run_name -> function that return the function that allow the set the next run_name
6741 result_path -> function that return the path of the summary result to write
6742 ignoreerror -> one class of error which are not for the error
6743 IteratorClass -> class to use for the iterator
6744 summaryorder -> function that return the function to call to get the order
6745
6746 advanced:
6747 check_card -> function that return the function to read the card and init stuff (compute auto-width/init self.iterator/...)
6748 This function should define the self.param_card_iterator if a scan exists
6749 and the one calling the auto-width functionalities/...
6750
6751 All the function are taking a single argument (an instance of the class on which the decorator is used)
6752 and they can either return themself a function or a string.
6753
6754 Note:
6755 1. the link to auto-width is not fully trivial due to the model handling
6756 a. If you inherit from CommonRunCmd (or if the self.mother is). Then
6757 everything should be automatic.
6758
6759 b. If you do not you can/should create the funtion self.get_model().
6760 Which returns the appropriate MG model (like the one from import_ufo.import_model)
6761
6762 c. You can also have full control by defining your own do_compute_widths(self, line)
6763 functions.
6764 """
6765 class restore_iterator(object):
6766 """ensure that the original card is always restore even for crash"""
6767 def __init__(self, iterator, path):
6768 self.iterator = iterator
6769 self.path = path
6770
6771 def __enter__(self):
6772 return self.iterator
6773
6774 def __exit__(self, ctype, value, traceback ):
6775 self.iterator.write(self.path)
6776
6777 def decorator(original_fct):
6778 def new_fct(obj, *args, **opts):
6779
6780 if isinstance(input_path, str):
6781 card_path = input_path
6782 else:
6783 card_path = input_path(obj)
6784
6785
6786
6787
6788
6789
6790
6791
6792 check_card(obj)(card_path, obj, iterator_class=iteratorclass)
6793
6794 param_card_iterator = None
6795 if obj.param_card_iterator:
6796 param_card_iterator = obj.param_card_iterator
6797 obj.param_card_iterator = []
6798
6799 if not param_card_iterator:
6800
6801 original_fct(obj, *args, **opts)
6802 return
6803
6804 with restore_iterator(param_card_iterator, card_path):
6805
6806
6807
6808 if not hasattr(obj, 'allow_notification_center'):
6809 obj.allow_notification_center = False
6810 with misc.TMP_variable(obj, 'allow_notification_center', False):
6811 orig_name = get_run_name(obj)
6812 next_name = orig_name
6813
6814 set_run_name(obj)(next_name)
6815
6816 original_fct(obj, *args, **opts)
6817 param_card_iterator.store_entry(next_name, store_for_scan(obj)(), param_card_path=card_path)
6818 for card in param_card_iterator:
6819 card.write(card_path)
6820
6821 check_card(obj)(card_path, obj, dependent=True)
6822 next_name = param_card_iterator.get_next_name(next_name)
6823 set_run_name(obj)(next_name)
6824 try:
6825 original_fct(obj, *args, **opts)
6826 except ignoreerror, error:
6827 param_card_iterator.store_entry(next_name, {'exception': error})
6828 else:
6829 param_card_iterator.store_entry(next_name, store_for_scan(obj)(), param_card_path=card_path)
6830
6831
6832 name = misc.get_scan_name(orig_name, next_name)
6833 path = result_path(obj) % name
6834 logger.info("write scan results in %s" % path ,'$MG:BOLD')
6835 order = summaryorder(obj)()
6836 param_card_iterator.write_summary(path, order=order)
6837 return new_fct
6838 return decorator
6839