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