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