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