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