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