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