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