1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 from __future__ import division
17 import collections
18 import copy
19 import logging
20 import numbers
21 import os
22 import sys
23 import re
24 import math
25 import StringIO
26
27 pjoin = os.path.join
28
29 try:
30 import madgraph
31 except ImportError:
32 MADEVENT = True
33 from internal import MadGraph5Error, InvalidCmd
34 import internal.file_writers as file_writers
35 import internal.files as files
36 import internal.check_param_card as param_card_reader
37 import internal.misc as misc
38 MEDIR = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
39 MEDIR = os.path.split(MEDIR)[0]
40 else:
41 MADEVENT = False
42 import madgraph.various.misc as misc
43 import madgraph.iolibs.file_writers as file_writers
44 import madgraph.iolibs.files as files
45 import models.check_param_card as param_card_reader
46 from madgraph import MG5DIR, MadGraph5Error, InvalidCmd
47
48
49 logger = logging.getLogger('madevent.cards')
54
57 """ """
58
59 ordered_items = ['mgversion', 'mg5proccard', 'mgproccard', 'mgruncard',
60 'slha','initrwgt','mggenerationinfo', 'mgpythiacard', 'mgpgscard',
61 'mgdelphescard', 'mgdelphestrigger','mgshowercard',
62 'ma5card_parton','ma5card_hadron','run_settings']
63
64 capitalized_items = {
65 'mgversion': 'MGVersion',
66 'mg5proccard': 'MG5ProcCard',
67 'mgproccard': 'MGProcCard',
68 'mgruncard': 'MGRunCard',
69 'ma5card_parton' : 'MA5Card_parton',
70 'ma5card_hadron' : 'MA5Card_hadron',
71 'mggenerationinfo': 'MGGenerationInfo',
72 'mgpythiacard': 'MGPythiaCard',
73 'mgpgscard': 'MGPGSCard',
74 'mgdelphescard': 'MGDelphesCard',
75 'mgdelphestrigger': 'MGDelphesTrigger',
76 'mgshowercard': 'MGShowerCard' }
77
78 forbid_cdata = ['initrwgt']
79
81 """ """
82
83 if isinstance(banner_path, Banner):
84 dict.__init__(self, banner_path)
85 self.lhe_version = banner_path.lhe_version
86 return
87 else:
88 dict.__init__(self)
89
90
91 if MADEVENT:
92 self['mgversion'] = '#%s\n' % open(pjoin(MEDIR, 'MGMEVersion.txt')).read()
93 else:
94 info = misc.get_pkg_info()
95 self['mgversion'] = info['version']+'\n'
96
97 self.lhe_version = None
98
99
100 if banner_path:
101 self.read_banner(banner_path)
102
103
104
105
106 pat_begin=re.compile('<(?P<name>\w*)>')
107 pat_end=re.compile('</(?P<name>\w*)>')
108
109 tag_to_file={'slha':'param_card.dat',
110 'mgruncard':'run_card.dat',
111 'mgpythiacard':'pythia_card.dat',
112 'mgpgscard' : 'pgs_card.dat',
113 'mgdelphescard':'delphes_card.dat',
114 'mgdelphestrigger':'delphes_trigger.dat',
115 'mg5proccard':'proc_card_mg5.dat',
116 'mgproccard': 'proc_card.dat',
117 'init': '',
118 'mggenerationinfo':'',
119 'scalesfunctionalform':'',
120 'montecarlomasses':'',
121 'initrwgt':'',
122 'madspin':'madspin_card.dat',
123 'mgshowercard':'shower_card.dat',
124 'pythia8':'pythia8_card.dat',
125 'ma5card_parton':'madanalysis5_parton_card.dat',
126 'ma5card_hadron':'madanalysis5_hadron_card.dat',
127 'run_settings':''
128 }
129
131 """read a banner"""
132
133 if isinstance(input_path, str):
134 if input_path.find('\n') ==-1:
135 input_path = open(input_path)
136 else:
137 def split_iter(string):
138 return (x.groups(0)[0] for x in re.finditer(r"([^\n]*\n)", string, re.DOTALL))
139 input_path = split_iter(input_path)
140
141 text = ''
142 store = False
143 for line in input_path:
144 if self.pat_begin.search(line):
145 if self.pat_begin.search(line).group('name').lower() in self.tag_to_file:
146 tag = self.pat_begin.search(line).group('name').lower()
147 store = True
148 continue
149 if store and self.pat_end.search(line):
150 if tag == self.pat_end.search(line).group('name').lower():
151 self[tag] = text
152 text = ''
153 store = False
154 if store and not line.startswith(('<![CDATA[',']]>')):
155 if line.endswith('\n'):
156 text += line
157 else:
158 text += '%s%s' % (line, '\n')
159
160
161 if "</init>" in line:
162 break
163 elif "<event>" in line:
164 break
165
167 """allow auto-build for the run_card/param_card/... """
168 try:
169 return super(Banner, self).__getattribute__(attr)
170 except:
171 if attr not in ['run_card', 'param_card', 'slha', 'mgruncard', 'mg5proccard', 'mgshowercard', 'foanalyse']:
172 raise
173 return self.charge_card(attr)
174
175
176
178 """change the lhe version associate to the banner"""
179
180 version = float(version)
181 if version < 3:
182 version = 1
183 elif version > 3:
184 raise Exception, "Not Supported version"
185 self.lhe_version = version
186
188 """return the cross-section of the file"""
189
190 if "init" not in self:
191 raise Exception
192
193 text = self["init"].split('\n')
194 cross = 0
195 error = 0
196 for line in text:
197 s = line.split()
198 if len(s)==4:
199 cross += float(s[0])
200 if witherror:
201 error += float(s[1])**2
202 if not witherror:
203 return cross
204 else:
205 return cross, math.sqrt(error)
206
207
209 """modify the init information with the associate scale"""
210
211 assert "init" in self
212
213 all_lines = self["init"].split('\n')
214 new_data = []
215 new_data.append(all_lines[0])
216 for i in range(1, len(all_lines)):
217 line = all_lines[i]
218 split = line.split()
219 if len(split) == 4:
220 xsec, xerr, xmax, pid = split
221 else:
222 new_data += all_lines[i:]
223 break
224 pid = int(pid)
225
226 line = " %+13.7e %+13.7e %+13.7e %i" % \
227 (ratio*float(xsec), ratio* float(xerr), ratio*float(xmax), pid)
228 new_data.append(line)
229 self['init'] = '\n'.join(new_data)
230
232 """return the pdg of each beam"""
233
234 assert "init" in self
235
236 all_lines = self["init"].split('\n')
237 pdg1,pdg2,_ = all_lines[0].split(None, 2)
238 return int(pdg1), int(pdg2)
239
241 """ Load the proc_card /param_card and run_card """
242
243 self.add(pjoin(medir,'Cards', 'param_card.dat'))
244 self.add(pjoin(medir,'Cards', 'run_card.dat'))
245 if os.path.exists(pjoin(medir, 'SubProcesses', 'procdef_mg5.dat')):
246 self.add(pjoin(medir,'SubProcesses', 'procdef_mg5.dat'))
247 self.add(pjoin(medir,'Cards', 'proc_card_mg5.dat'))
248 else:
249 self.add(pjoin(medir,'Cards', 'proc_card.dat'))
250
252 """Change the seed value in the banner"""
253
254 p = re.compile(r'''^\s*\d+\s*=\s*iseed''', re.M)
255 new_seed_str = " %s = iseed" % seed
256 self['mgruncard'] = p.sub(new_seed_str, self['mgruncard'])
257
259 """add info on MGGeneration"""
260
261 text = """
262 # Number of Events : %s
263 # Integrated weight (pb) : %s
264 """ % (nb_event, cross)
265 self['MGGenerationInfo'] = text
266
267
268
269
270 - def split(self, me_dir, proc_card=True):
271 """write the banner in the Cards directory.
272 proc_card argument is present to avoid the overwrite of proc_card
273 information"""
274
275 for tag, text in self.items():
276 if tag == 'mgversion':
277 continue
278 if not proc_card and tag in ['mg5proccard','mgproccard']:
279 continue
280 if not self.tag_to_file[tag]:
281 continue
282 ff = open(pjoin(me_dir, 'Cards', self.tag_to_file[tag]), 'w')
283 ff.write(text)
284 ff.close()
285
286
287
288
289
291 """special routine removing width/mass of particles not present in the model
292 This is usefull in case of loop model card, when we want to use the non
293 loop model."""
294
295 if not hasattr(self, 'param_card'):
296 self.charge_card('slha')
297
298 for tag in ['mass', 'decay']:
299 block = self.param_card.get(tag)
300 for data in block:
301 pid = data.lhacode[0]
302 if pid not in pid2label.keys():
303 block.remove((pid,))
304
306 """get the lha_strategy: how the weight have to be handle by the shower"""
307
308 if not self["init"]:
309 raise Exception, "No init block define"
310
311 data = self["init"].split('\n')[0].split()
312 if len(data) != 10:
313 misc.sprint(len(data), self['init'])
314 raise Exception, "init block has a wrong format"
315 return int(float(data[-2]))
316
318 """set the lha_strategy: how the weight have to be handle by the shower"""
319
320 if not (-4 <= int(value) <= 4):
321 raise Exception, "wrong value for lha_strategy", value
322 if not self["init"]:
323 raise Exception, "No init block define"
324
325 all_lines = self["init"].split('\n')
326 data = all_lines[0].split()
327 if len(data) != 10:
328 misc.sprint(len(data), self['init'])
329 raise Exception, "init block has a wrong format"
330 data[-2] = '%s' % value
331 all_lines[0] = ' '.join(data)
332 self['init'] = '\n'.join(all_lines)
333
334
336 """modify the init information with the associate cross-section"""
337 assert isinstance(cross, dict)
338
339 assert "init" in self
340
341 cross = dict(cross)
342 for key in cross.keys():
343 if isinstance(key, str) and key.isdigit() and int(key) not in cross:
344 cross[int(key)] = cross[key]
345
346
347 all_lines = self["init"].split('\n')
348 new_data = []
349 new_data.append(all_lines[0])
350 for i in range(1, len(all_lines)):
351 line = all_lines[i]
352 split = line.split()
353 if len(split) == 4:
354 xsec, xerr, xmax, pid = split
355 else:
356 new_data += all_lines[i:]
357 break
358 if int(pid) not in cross:
359 raise Exception
360 pid = int(pid)
361 if float(xsec):
362 ratio = cross[pid]/float(xsec)
363 else:
364 ratio = 0
365 line = " %+13.7e %+13.7e %+13.7e %i" % \
366 (float(cross[pid]), ratio* float(xerr), ratio*float(xmax), pid)
367 new_data.append(line)
368 self['init'] = '\n'.join(new_data)
369
370
371
372
373 - def write(self, output_path, close_tag=True, exclude=[]):
374 """write the banner"""
375
376 if isinstance(output_path, str):
377 ff = open(output_path, 'w')
378 else:
379 ff = output_path
380
381 if MADEVENT:
382 header = open(pjoin(MEDIR, 'Source', 'banner_header.txt')).read()
383 else:
384 header = open(pjoin(MG5DIR,'Template', 'LO', 'Source', 'banner_header.txt')).read()
385
386 if not self.lhe_version:
387 self.lhe_version = self.get('run_card', 'lhe_version', default=1.0)
388 if float(self.lhe_version) < 3:
389 self.lhe_version = 1.0
390
391 ff.write(header % { 'version':float(self.lhe_version)})
392
393
394 for tag in [t for t in self.ordered_items if t in self.keys()]+ \
395 [t for t in self.keys() if t not in self.ordered_items]:
396 if tag in ['init'] or tag in exclude:
397 continue
398 capitalized_tag = self.capitalized_items[tag] if tag in self.capitalized_items else tag
399 start_data, stop_data = '', ''
400 if capitalized_tag not in self.forbid_cdata and \
401 ('<' in self[tag] or '@' in self[tag]):
402 start_data = '\n<![CDATA['
403 stop_data = ']]>\n'
404 ff.write('<%(tag)s>%(start_data)s\n%(text)s\n%(stop_data)s</%(tag)s>\n' % \
405 {'tag':capitalized_tag, 'text':self[tag].strip(),
406 'start_data': start_data, 'stop_data':stop_data})
407
408
409 if not '/header' in exclude:
410 ff.write('</header>\n')
411
412 if 'init' in self and not 'init' in exclude:
413 text = self['init']
414 ff.write('<%(tag)s>\n%(text)s\n</%(tag)s>\n' % \
415 {'tag':'init', 'text':text.strip()})
416 if close_tag:
417 ff.write('</LesHouchesEvents>\n')
418 return ff
419
420
421
422
423
424 - def add(self, path, tag=None):
425 """Add the content of the file to the banner"""
426
427 if not tag:
428 card_name = os.path.basename(path)
429 if 'param_card' in card_name:
430 tag = 'slha'
431 elif 'run_card' in card_name:
432 tag = 'MGRunCard'
433 elif 'pythia_card' in card_name:
434 tag = 'MGPythiaCard'
435 elif 'pythia8_card' in card_name or 'pythia8.cmd' in card_name:
436 tag = 'MGPythiaCard'
437 elif 'pgs_card' in card_name:
438 tag = 'MGPGSCard'
439 elif 'delphes_card' in card_name:
440 tag = 'MGDelphesCard'
441 elif 'delphes_trigger' in card_name:
442 tag = 'MGDelphesTrigger'
443 elif 'proc_card_mg5' in card_name:
444 tag = 'MG5ProcCard'
445 elif 'proc_card' in card_name:
446 tag = 'MGProcCard'
447 elif 'procdef_mg5' in card_name:
448 tag = 'MGProcCard'
449 elif 'shower_card' in card_name:
450 tag = 'MGShowerCard'
451 elif 'madspin_card' in card_name:
452 tag = 'madspin'
453 elif 'FO_analyse_card' in card_name:
454 tag = 'foanalyse'
455 elif 'reweight_card' in card_name:
456 tag='reweight_card'
457 elif 'madanalysis5_parton_card' in card_name:
458 tag='MA5Card_parton'
459 elif 'madanalysis5_hadron_card' in card_name:
460 tag='MA5Card_hadron'
461 else:
462 raise Exception, 'Impossible to know the type of the card'
463
464 self.add_text(tag.lower(), open(path).read())
465
466 - def add_text(self, tag, text):
467 """Add the content of the file to the banner"""
468
469 if tag == 'param_card':
470 tag = 'slha'
471 elif tag == 'run_card':
472 tag = 'mgruncard'
473 elif tag == 'proc_card':
474 tag = 'mg5proccard'
475 elif tag == 'shower_card':
476 tag = 'mgshowercard'
477 elif tag == 'FO_analyse_card':
478 tag = 'foanalyse'
479
480 self[tag.lower()] = text
481
482
532
533
535 """return a specific """
536
537 if tag in ['param_card', 'param']:
538 tag = 'slha'
539 attr_tag = 'param_card'
540 elif tag in ['run_card', 'run']:
541 tag = 'mgruncard'
542 attr_tag = 'run_card'
543 elif tag == 'proc_card':
544 tag = 'mg5proccard'
545 attr_tag = 'proc_card'
546 elif tag == 'model':
547 tag = 'mg5proccard'
548 attr_tag = 'proc_card'
549 arg = ('model',)
550 elif tag == 'generate':
551 tag = 'mg5proccard'
552 attr_tag = 'proc_card'
553 arg = ('generate',)
554 elif tag == 'shower_card':
555 tag = 'mgshowercard'
556 attr_tag = 'shower_card'
557 assert tag in ['slha', 'mgruncard', 'mg5proccard', 'shower_card'], '%s not recognized' % tag
558
559 if not hasattr(self, attr_tag):
560 self.charge_card(attr_tag)
561
562 card = getattr(self, attr_tag)
563 if len(arg) == 0:
564 return card
565 elif len(arg) == 1:
566 if tag == 'mg5proccard':
567 try:
568 return card.get(arg[0])
569 except KeyError, error:
570 if 'default' in opt:
571 return opt['default']
572 else:
573 raise
574 try:
575 return card[arg[0]]
576 except KeyError:
577 if 'default' in opt:
578 return opt['default']
579 else:
580 raise
581 elif len(arg) == 2 and tag == 'slha':
582 try:
583 return card[arg[0]].get(arg[1:])
584 except KeyError:
585 if 'default' in opt:
586 return opt['default']
587 else:
588 raise
589 elif len(arg) == 0:
590 return card
591 else:
592 raise Exception, "Unknow command"
593
594
595 get = get_detail
596
597 - def set(self, card, *args):
598 """modify one of the cards"""
599
600 if tag == 'param_card':
601 tag = 'slha'
602 attr_tag = 'param_card'
603 elif tag == 'run_card':
604 tag = 'mgruncard'
605 attr_tag = 'run_card'
606 elif tag == 'proc_card':
607 tag = 'mg5proccard'
608 attr_tag = 'proc_card'
609 elif tag == 'model':
610 tag = 'mg5proccard'
611 attr_tag = 'proc_card'
612 arg = ('model',)
613 elif tag == 'generate':
614 tag = 'mg5proccard'
615 attr_tag = 'proc_card'
616 arg = ('generate',)
617 elif tag == 'shower_card':
618 tag = 'mgshowercard'
619 attr_tag = 'shower_card'
620 assert tag in ['slha', 'mgruncard', 'mg5proccard', 'shower_card'], 'not recognized'
621
622 if not hasattr(self, attr_tag):
623 self.charge_card(attr_tag)
624
625 card = getattr(self, attr_tag)
626 if len(args) ==2:
627 if tag == 'mg5proccard':
628 card.info[args[0]] = args[-1]
629 else:
630 card[args[0]] = args[1]
631 else:
632 card[args[:-1]] = args[-1]
633
634
635 @misc.multiple_try()
637 """Add the banner to a file and change the associate seed in the banner"""
638
639 if seed is not None:
640 self.set("run_card", "iseed", seed)
641
642 if not out:
643 path_out = "%s.tmp" % path
644 else:
645 path_out = out
646
647 ff = self.write(path_out, close_tag=False,
648 exclude=['MGGenerationInfo', '/header', 'init'])
649 ff.write("## END BANNER##\n")
650 if self.lhe_version >= 3:
651
652 [ff.write(line) if not line.startswith("<generator name='MadGraph5_aMC@NLO'")
653 else ff.write("<generator name='MadGraph5_aMC@NLO' version='%s'>" % self['mgversion'][:-1])
654 for line in open(path)]
655 else:
656 [ff.write(line) for line in open(path)]
657 ff.write("</LesHouchesEvents>\n")
658 ff.close()
659 if out:
660 os.remove(path)
661 else:
662 files.mv(path_out, path)
663
664
665
666 -def split_banner(banner_path, me_dir, proc_card=True):
671
673 """as input we receive a gen_crossxhtml.AllResults object.
674 This define the current banner and load it
675 """
676
677 if not run:
678 try:
679 _run = results_object.current['run_name']
680 _tag = results_object.current['tag']
681 except Exception:
682 return Banner()
683 else:
684 _run = run
685 if not tag:
686 try:
687 _tag = results_object[run].tags[-1]
688 except Exception,error:
689 return Banner()
690 else:
691 _tag = tag
692
693 path = results_object.path
694 banner_path = pjoin(path,'Events',run,'%s_%s_banner.txt' % (run, tag))
695
696 if not os.path.exists(banner_path):
697 if level != "parton" and tag != _tag:
698 return recover_banner(results_object, level, _run, results_object[_run].tags[0])
699 elif level == 'parton':
700 paths = [pjoin(path,'Events',run, 'unweighted_events.lhe.gz'),
701 pjoin(path,'Events',run, 'unweighted_events.lhe'),
702 pjoin(path,'Events',run, 'events.lhe.gz'),
703 pjoin(path,'Events',run, 'events.lhe')]
704 for p in paths:
705 if os.path.exists(p):
706 if MADEVENT:
707 import internal.lhe_parser as lhe_parser
708 else:
709 import madgraph.various.lhe_parser as lhe_parser
710 lhe = lhe_parser.EventFile(p)
711 return Banner(lhe.banner)
712
713
714 return Banner()
715 banner = Banner(banner_path)
716
717
718
719 if level == 'pythia':
720 if 'mgpythiacard' in banner:
721 del banner['mgpythiacard']
722 if level in ['pythia','pgs','delphes']:
723 for tag in ['mgpgscard', 'mgdelphescard', 'mgdelphestrigger']:
724 if tag in banner:
725 del banner[tag]
726 return banner
727
730
732 """Basic Proccard object"""
733
734 history_header = \
735 '#************************************************************\n' + \
736 '#* MadGraph5_aMC@NLO *\n' + \
737 '#* *\n' + \
738 "#* * * *\n" + \
739 "#* * * * * *\n" + \
740 "#* * * * * 5 * * * * *\n" + \
741 "#* * * * * *\n" + \
742 "#* * * *\n" + \
743 "#* *\n" + \
744 "#* *\n" + \
745 "%(info_line)s" +\
746 "#* *\n" + \
747 "#* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \
748 "#* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \
749 '#* *\n' + \
750 '#************************************************************\n' + \
751 '#* *\n' + \
752 '#* Command File for MadGraph5_aMC@NLO *\n' + \
753 '#* *\n' + \
754 '#* run as ./bin/mg5_aMC filename *\n' + \
755 '#* *\n' + \
756 '#************************************************************\n'
757
758
759
760
762 """ initialize a basic proc_card"""
763 self.info = {'model': 'sm', 'generate':None,
764 'full_model_line':'import model sm'}
765 list.__init__(self)
766 if init:
767 self.read(init)
768
769
770 - def read(self, init):
771 """read the proc_card and save the information"""
772
773 if isinstance(init, str):
774 init = file(init, 'r')
775
776 store_line = ''
777 for line in init:
778 line = line.rstrip()
779 if line.endswith('\\'):
780 store_line += line[:-1]
781 else:
782 tmp = store_line + line
783 self.append(tmp.strip())
784 store_line = ""
785 if store_line:
786 raise Exception, "WRONG CARD FORMAT"
787
788
790 """move an element to the last history."""
791 for line in self[:]:
792 if line.startswith(cmd):
793 self.remove(line)
794 list.append(self, line)
795
797 """"add a line in the proc_card perform automatically cleaning"""
798
799 line = line.strip()
800 cmds = line.split()
801 if len(cmds) == 0:
802 return
803
804 list.append(self, line)
805
806
807 cmd = cmds[0]
808
809 if cmd == 'output':
810
811 self.clean(allow_for_removal = ['output'], keep_switch=True,
812 remove_bef_last='output')
813 elif cmd == 'generate':
814
815 self.clean(remove_bef_last='generate', keep_switch=True,
816 allow_for_removal= ['generate', 'add process', 'output'])
817 self.info['generate'] = ' '.join(cmds[1:])
818 elif cmd == 'add' and cmds[1] == 'process' and not self.info['generate']:
819 self.info['generate'] = ' '.join(cmds[2:])
820 elif cmd == 'import':
821 if len(cmds) < 2:
822 return
823 if cmds[1].startswith('model'):
824 self.info['full_model_line'] = line
825 self.clean(remove_bef_last='import', keep_switch=True,
826 allow_for_removal=['generate', 'add process', 'add model', 'output'])
827 if cmds[1] == 'model':
828 self.info['model'] = cmds[2]
829 else:
830 self.info['model'] = None
831 elif cmds[1] == 'proc_v4':
832
833 self[:] = []
834
835
836 - def clean(self, to_keep=['set','add','load'],
837 remove_bef_last=None,
838 to_remove=['open','display','launch', 'check','history'],
839 allow_for_removal=None,
840 keep_switch=False):
841 """Remove command in arguments from history.
842 All command before the last occurrence of 'remove_bef_last'
843 (including it) will be removed (but if another options tells the opposite).
844 'to_keep' is a set of line to always keep.
845 'to_remove' is a set of line to always remove (don't care about remove_bef_
846 status but keep_switch acts.).
847 if 'allow_for_removal' is define only the command in that list can be
848 remove of the history for older command that remove_bef_lb1. all parameter
849 present in to_remove are always remove even if they are not part of this
850 list.
851 keep_switch force to keep the statement remove_bef_??? which changes starts
852 the removal mode.
853 """
854
855
856 if __debug__ and allow_for_removal:
857 for arg in to_keep:
858 assert arg not in allow_for_removal
859
860
861 nline = -1
862 removal = False
863
864 while nline > -len(self):
865 switch = False
866
867
868 if not removal and remove_bef_last:
869 if self[nline].startswith(remove_bef_last):
870 removal = True
871 switch = True
872
873
874 if switch and keep_switch:
875 nline -= 1
876 continue
877
878
879 if any([self[nline].startswith(arg) for arg in to_remove]):
880 self.pop(nline)
881 continue
882
883
884 if removal:
885 if allow_for_removal:
886
887 if any([self[nline].startswith(arg)
888 for arg in allow_for_removal]):
889 self.pop(nline)
890 continue
891 elif not any([self[nline].startswith(arg) for arg in to_keep]):
892
893 self.pop(nline)
894 continue
895
896
897 nline -= 1
898
899 - def get(self, tag, default=None):
900 if isinstance(tag, int):
901 list.__getattr__(self, tag)
902 elif tag == 'info' or tag == "__setstate__":
903 return default
904 elif tag == "multiparticles":
905 out = []
906 for line in self:
907 if line.startswith('define'):
908 name, content = line[7:].split('=',1)
909 out.append((name, content))
910 return out
911 else:
912 return self.info[tag]
913
915 """write the proc_card to a given path"""
916
917 fsock = open(path, 'w')
918 fsock.write(self.history_header)
919 for line in self:
920 while len(line) > 70:
921 sub, line = line[:70]+"\\" , line[70:]
922 fsock.write(sub+"\n")
923 else:
924 fsock.write(line+"\n")
925
927
929 """ a class for storing/dealing with input file.
930 """
931
932 - def __init__(self, finput=None, **opt):
933 """initialize a new instance. input can be an instance of MadLoopParam,
934 a file, a path to a file, or simply Nothing"""
935
936 if isinstance(finput, self.__class__):
937 dict.__init__(self, finput)
938 assert finput.__dict__.keys()
939 for key in finput.__dict__:
940 setattr(self, key, copy.copy(getattr(finput, key)) )
941 return
942 else:
943 dict.__init__(self)
944
945
946 self.user_set = set()
947 self.auto_set = set()
948 self.system_only = set()
949 self.lower_to_case = {}
950 self.list_parameter = {}
951 self.dict_parameter = {}
952 self.comments = {}
953
954 self.allowed_value = {}
955
956 self.default_setup()
957
958
959
960 if isinstance(finput, (file, str, StringIO.StringIO)):
961 self.read(finput, **opt)
962
965
967 return self.__class__(self)
968
970 """define the sum"""
971 assert isinstance(other, dict)
972 base = self.__class__(self)
973
974 base.update((key.lower(),value) for key, value in other.items())
975 return base
976
978 """define the sum"""
979 new = copy.copy(other)
980 new.update((key, value) for key, value in self.items())
981 return new
982
985
989
992
995
996 @staticmethod
997 - def warn(text, level, raiseerror=False):
998 """convenient proxy to raiseerror/print warning"""
999
1000 if raiseerror is True:
1001 raise InvalidCardEdition(text)
1002 elif raiseerror:
1003 raise raiseerror(text)
1004
1005 if isinstance(level,str):
1006 log = getattr(logger, level.lower())
1007 elif isinstance(level, int):
1008 log = lambda t: logger.log(level, t)
1009 elif level:
1010 log = level
1011
1012 return log(text)
1013
1014 - def post_set(self, name, value, change_userdefine, raiseerror):
1015
1016 if value is None:
1017 value = self[name]
1018
1019 if hasattr(self, 'post_set_%s' % name):
1020 return getattr(self, 'post_set_%s' % name)(value, change_userdefine, raiseerror)
1021
1022 - def __setitem__(self, name, value, change_userdefine=False,raiseerror=False):
1023 """set the attribute and set correctly the type if the value is a string.
1024 change_userdefine on True if we have to add the parameter in user_set
1025 """
1026
1027 if not len(self):
1028
1029 self.__init__()
1030
1031 name = name.strip()
1032 lower_name = name.lower()
1033
1034
1035 if change_userdefine and lower_name in self.system_only:
1036 text='%s is a private entry which can not be modify by the user. Keep value at %s' % (name,self[name])
1037 self.warn(text, 'critical', raiseerror)
1038 return
1039
1040
1041 if lower_name in self:
1042 targettype = type(dict.__getitem__(self, lower_name))
1043 if targettype != str and isinstance(value, str) and value.lower() == 'auto':
1044 self.auto_set.add(lower_name)
1045 if lower_name in self.user_set:
1046 self.user_set.remove(lower_name)
1047
1048 self.post_set(lower_name, 'auto', change_userdefine, raiseerror)
1049 return
1050 elif lower_name in self.auto_set:
1051 self.auto_set.remove(lower_name)
1052
1053
1054 if lower_name in self.list_parameter:
1055 targettype = self.list_parameter[lower_name]
1056
1057
1058
1059 if isinstance(value, str):
1060
1061 value = value.strip()
1062 if value.startswith('[') and value.endswith(']'):
1063 value = value[1:-1]
1064
1065 data = re.split(r"((?<![\\])['\"])((?:.(?!(?<![\\])\1))*.?)\1", str(value))
1066 new_value = []
1067 i = 0
1068 while len(data) > i:
1069 current = filter(None, re.split(r'(?:(?<!\\)\s)|,', data[i]))
1070 i+=1
1071 if len(data) > i+1:
1072 if current:
1073 current[-1] += '{0}{1}{0}'.format(data[i], data[i+1])
1074 else:
1075 current = ['{0}{1}{0}'.format(data[i], data[i+1])]
1076 i+=2
1077 new_value += current
1078
1079 value = new_value
1080
1081 elif not hasattr(value, '__iter__'):
1082 value = [value]
1083 elif isinstance(value, dict):
1084 text = "not being able to handle dictionary in card entry"
1085 return self.warn(text, 'critical', raiseerror)
1086
1087
1088 values =[self.format_variable(v, targettype, name=name)
1089 for v in value]
1090
1091
1092 if lower_name in self.allowed_value and '*' not in self.allowed_value[lower_name]:
1093 new_values = []
1094 dropped = []
1095 for val in values:
1096 allowed = self.allowed_value[lower_name]
1097
1098 if val in allowed:
1099 new_values.append(val)
1100 continue
1101 elif isinstance(val, str):
1102 val = val.lower()
1103 allowed = allowed.lower()
1104 if value in allowed:
1105 i = allowed.index(value)
1106 new_values.append(self.allowed_value[i])
1107 continue
1108
1109 dropped.append(val)
1110
1111 if not new_values:
1112
1113 text= "value '%s' for entry '%s' is not valid. Preserving previous value: '%s'.\n" \
1114 % (value, name, self[lower_name])
1115 text += "allowed values are any list composed of the following entry: %s" % ', '.join([str(i) for i in self.allowed_value[lower_name]])
1116 return self.warn(text, 'warning', raiseerror)
1117 elif dropped:
1118 text = "some value for entry '%s' are not valid. Invalid item are: '%s'.\n" \
1119 % (value, name, dropped)
1120 text += "value will be set to %s" % new_values
1121 text += "allowed items in the list are: %s" % ', '.join([str(i) for i in self.allowed_value[lower_name]])
1122 self.warn(text, 'warning')
1123
1124 values = new_values
1125
1126
1127 dict.__setitem__(self, lower_name, values)
1128 if change_userdefine:
1129 self.user_set.add(lower_name)
1130
1131 return self.post_set(lower_name, None, change_userdefine, raiseerror)
1132 elif lower_name in self.dict_parameter:
1133 targettype = self.dict_parameter[lower_name]
1134 full_reset = True
1135
1136 if isinstance(value, str):
1137 value = value.strip()
1138
1139
1140
1141
1142
1143
1144
1145 if value.startswith('{') and value.endswith('}'):
1146 new_value = {}
1147 for pair in value[1:-1].split(','):
1148 if not pair.strip():
1149 break
1150 x, y = pair.split(':')
1151 x, y = x.strip(), y.strip()
1152 if x.startswith(('"',"'")) and x.endswith(x[0]):
1153 x = x[1:-1]
1154 new_value[x] = y
1155 value = new_value
1156 elif ',' in value:
1157 x,y = value.split(',')
1158 value = {x.strip():y.strip()}
1159 full_reset = False
1160
1161 elif ':' in value:
1162 x,y = value.split(':')
1163 value = {x.strip():y.strip()}
1164 full_reset = False
1165 else:
1166 x,y = value.split()
1167 value = {x:y}
1168 full_reset = False
1169
1170 if isinstance(value, dict):
1171 for key in value:
1172 value[key] = self.format_variable(value[key], targettype, name=name)
1173 if full_reset:
1174 dict.__setitem__(self, lower_name, value)
1175 else:
1176 dict.__getitem__(self, lower_name).update(value)
1177 else:
1178 raise Exception, '%s should be of dict type'% lower_name
1179 if change_userdefine:
1180 self.user_set.add(lower_name)
1181 return self.post_set(lower_name, None, change_userdefine, raiseerror)
1182 elif name in self:
1183 targettype = type(self[name])
1184 else:
1185 logger.debug('Trying to add argument %s in %s. ' % (name, self.__class__.__name__) +\
1186 'This argument is not defined by default. Please consider adding it.')
1187 suggestions = [k for k in self.keys() if k.startswith(name[0].lower())]
1188 if len(suggestions)>0:
1189 logger.debug("Did you mean one of the following: %s"%suggestions)
1190 self.add_param(lower_name, self.format_variable(UnknownType(value),
1191 UnknownType, name))
1192 self.lower_to_case[lower_name] = name
1193 if change_userdefine:
1194 self.user_set.add(lower_name)
1195 return self.post_set(lower_name, None, change_userdefine, raiseerror)
1196
1197 value = self.format_variable(value, targettype, name=name)
1198
1199 if lower_name in self.allowed_value and '*' not in self.allowed_value[lower_name]:
1200 valid = False
1201 allowed = self.allowed_value[lower_name]
1202
1203
1204 if value in allowed:
1205 valid=True
1206 elif isinstance(value, str):
1207 value = value.lower()
1208 allowed = [v.lower() for v in allowed]
1209 if value in allowed:
1210 i = allowed.index(value)
1211 value = self.allowed_value[lower_name][i]
1212 valid=True
1213
1214 if not valid:
1215
1216 text = "value '%s' for entry '%s' is not valid. Preserving previous value: '%s'.\n" \
1217 % (value, name, self[lower_name])
1218 text += "allowed values are %s\n" % ', '.join([str(i) for i in self.allowed_value[lower_name]])
1219 if lower_name in self.comments:
1220 text += 'type "help %s" for more information' % name
1221 return self.warn(text, 'warning', raiseerror)
1222
1223 dict.__setitem__(self, lower_name, value)
1224 if change_userdefine:
1225 self.user_set.add(lower_name)
1226 self.post_set(lower_name, None, change_userdefine, raiseerror)
1227
1228
1229 - def add_param(self, name, value, system=False, comment=False, typelist=None,
1230 allowed=[]):
1231 """add a default parameter to the class"""
1232
1233 lower_name = name.lower()
1234 if __debug__:
1235 if lower_name in self:
1236 raise Exception("Duplicate case for %s in %s" % (name,self.__class__))
1237
1238 dict.__setitem__(self, lower_name, value)
1239 self.lower_to_case[lower_name] = name
1240 if isinstance(value, list):
1241 if len(value):
1242 targettype = type(value[0])
1243 else:
1244 targettype=typelist
1245 assert typelist
1246 if any([targettype != type(v) for v in value]):
1247 raise Exception, "All entry should have the same type"
1248 self.list_parameter[lower_name] = targettype
1249 elif isinstance(value, dict):
1250 allvalues = value.values()
1251 if any([type(allvalues[0]) != type(v) for v in allvalues]):
1252 raise Exception, "All entry should have the same type"
1253 self.dict_parameter[lower_name] = type(allvalues[0])
1254 if '__type__' in value:
1255 del value['__type__']
1256 dict.__setitem__(self, lower_name, value)
1257
1258 if allowed and allowed != ['*']:
1259 self.allowed_value[lower_name] = allowed
1260 assert value in allowed or '*' in allowed
1261
1262
1263
1264 if system:
1265 self.system_only.add(lower_name)
1266 if comment:
1267 self.comments[lower_name] = comment
1268
1270 """return a minimal help for the parameter"""
1271
1272 out = "## Information on parameter %s from class %s\n" % (name, self.__class__.__name__)
1273 if name.lower() in self:
1274 out += "## current value: %s (parameter should be of type %s)\n" % (self[name], type(self[name]))
1275 if name.lower() in self.comments:
1276 out += '## %s\n' % self.comments[name.lower()].replace('\n', '\n## ')
1277 else:
1278 out += "## Unknown for this class\n"
1279 if name.lower() in self.user_set:
1280 out += "## This value is considered as been set by the user\n"
1281 else:
1282 out += "## This value is considered as been set by the system\n"
1283 if name.lower() in self.allowed_value:
1284 if '*' not in self.allowed_value[name.lower()]:
1285 out += "Allowed value are: %s\n" % ','.join([str(p) for p in self.allowed_value[name.lower()]])
1286 else:
1287 out += "Suggested value are : %s\n " % ','.join([str(p) for p in self.allowed_value[name.lower()] if p!='*'])
1288
1289 logger.info(out)
1290 return out
1291
1292 @staticmethod
1379
1380
1381
1383
1384 lower_name = name.lower()
1385 if __debug__:
1386 if lower_name not in self:
1387 if lower_name in [key.lower() for key in self] :
1388 raise Exception, "Some key are not lower case %s. Invalid use of the class!"\
1389 % [key for key in self if key.lower() != key]
1390
1391 if lower_name in self.auto_set:
1392 return 'auto'
1393
1394 return dict.__getitem__(self, name.lower())
1395
1396
1397 - def set(self, name, value, changeifuserset=True, user=False, raiseerror=False):
1398 """convenient way to change attribute.
1399 changeifuserset=False means that the value is NOT change is the value is not on default.
1400 user=True, means that the value will be marked as modified by the user
1401 (potentially preventing future change to the value)
1402 """
1403
1404
1405 if not changeifuserset:
1406 if name.lower() in self.user_set:
1407
1408 return
1409
1410 self.__setitem__(name, value, change_userdefine=user, raiseerror=raiseerror)
1411
1415 """A class to handle information which are passed from MadGraph to the madevent
1416 interface."""
1417
1419 """initialize the directory to the default value"""
1420
1421 self.add_param('loop_induced', False)
1422 self.add_param('has_isr', False)
1423 self.add_param('has_fsr', False)
1424 self.add_param('nb_channel', 0)
1425 self.add_param('nexternal', 0)
1426 self.add_param('ninitial', 0)
1427 self.add_param('grouped_matrix', True)
1428 self.add_param('has_loops', False)
1429 self.add_param('bias_module','None')
1430 self.add_param('max_n_matched_jets', 0)
1431 self.add_param('colored_pdgs', [1,2,3,4,5])
1432 self.add_param('complex_mass_scheme', False)
1433 self.add_param('pdg_initial1', [0])
1434 self.add_param('pdg_initial2', [0])
1435
1436 - def read(self, finput):
1437 """Read the input file, this can be a path to a file,
1438 a file object, a str with the content of the file."""
1439
1440 if isinstance(finput, str):
1441 if "\n" in finput:
1442 finput = finput.split('\n')
1443 elif os.path.isfile(finput):
1444 finput = open(finput)
1445 else:
1446 raise Exception, "No such file %s" % finput
1447
1448 for line in finput:
1449 if '#' in line:
1450 line = line.split('#',1)[0]
1451 if not line:
1452 continue
1453
1454 if '=' in line:
1455 key, value = line.split('=',1)
1456 self[key.strip()] = value
1457
1458 - def write(self, outputpath):
1459 """write the file"""
1460
1461 template ="# Information about the process #\n"
1462 template +="#########################################\n"
1463
1464 fsock = open(outputpath, 'w')
1465 fsock.write(template)
1466
1467 for key, value in self.items():
1468 fsock.write(" %s = %s \n" % (key, value))
1469
1470 fsock.close()
1471
1476 """an object for the GridpackCard"""
1477
1479 """default value for the GridpackCard"""
1480
1481 self.add_param("GridRun", True)
1482 self.add_param("gevents", 2500)
1483 self.add_param("gseed", 1)
1484 self.add_param("ngran", -1)
1485
1486 - def read(self, finput):
1487 """Read the input file, this can be a path to a file,
1488 a file object, a str with the content of the file."""
1489
1490 if isinstance(finput, str):
1491 if "\n" in finput:
1492 finput = finput.split('\n')
1493 elif os.path.isfile(finput):
1494 finput = open(finput)
1495 else:
1496 raise Exception, "No such file %s" % finput
1497
1498 for line in finput:
1499 line = line.split('#')[0]
1500 line = line.split('!')[0]
1501 line = line.split('=',1)
1502 if len(line) != 2:
1503 continue
1504 self[line[1].strip()] = line[0].replace('\'','').strip()
1505
1506 - def write(self, output_file, template=None):
1507 """Write the run_card in output_file according to template
1508 (a path to a valid run_card)"""
1509
1510 if not template:
1511 if not MADEVENT:
1512 template = pjoin(MG5DIR, 'Template', 'LO', 'Cards',
1513 'grid_card_default.dat')
1514 else:
1515 template = pjoin(MEDIR, 'Cards', 'grid_card_default.dat')
1516
1517
1518 text = ""
1519 for line in file(template,'r'):
1520 nline = line.split('#')[0]
1521 nline = nline.split('!')[0]
1522 comment = line[len(nline):]
1523 nline = nline.split('=')
1524 if len(nline) != 2:
1525 text += line
1526 elif nline[1].strip() in self:
1527 text += ' %s\t= %s %s' % (self[nline[1].strip()],nline[1], comment)
1528 else:
1529 logger.info('Adding missing parameter %s to current run_card (with default value)' % nline[1].strip())
1530 text += line
1531
1532 if isinstance(output_file, str):
1533 fsock = open(output_file,'w')
1534 else:
1535 fsock = output_file
1536
1537 fsock.write(text)
1538 fsock.close()
1539
1541 """ Implements the Pythia8 card."""
1542
1544 """ Placeholder function to allow overwriting in the PY8SubRun daughter.
1545 The initialization of the self.subruns attribute should of course not
1546 be performed in PY8SubRun."""
1547 if type == 'parameters':
1548 if "LHEFInputs:nSubruns" not in self:
1549 self.add_param("LHEFInputs:nSubruns", 1,
1550 hidden='ALWAYS_WRITTEN',
1551 comment="""
1552 ====================
1553 Subrun definitions
1554 ====================
1555 """)
1556 if type == 'attributes':
1557 if not(hasattr(self,'subruns')):
1558 first_subrun = PY8SubRun(subrun_id=0)
1559 self.subruns = dict([(first_subrun['Main:subrun'],first_subrun)])
1560
1562 """ Sets up the list of available PY8 parameters."""
1563
1564
1565
1566 self.add_param("Main:numberOfEvents", -1)
1567
1568
1569 self.add_param("JetMatching:qCut", -1.0, always_write_to_card=False)
1570 self.add_param("JetMatching:doShowerKt",False,always_write_to_card=False)
1571
1572 self.add_param("JetMatching:nJetMax", -1, always_write_to_card=False)
1573
1574 self.add_param("Merging:TMS", -1.0, always_write_to_card=False)
1575 self.add_param("Merging:Process", '<set_by_user>', always_write_to_card=False)
1576
1577 self.add_param("Merging:nJetMax", -1, always_write_to_card=False)
1578
1579
1580 self.add_param("SysCalc:fullCutVariation", False)
1581
1582
1583
1584 self.add_param("HEPMCoutput:file", 'auto')
1585
1586
1587
1588 self.add_param("Beams:frameType", 4,
1589 hidden=True,
1590 comment='Tell Pythia8 that an LHEF input is used.')
1591 self.add_param("HEPMCoutput:scaling", 1.0e9,
1592 hidden=True,
1593 comment='1.0 corresponds to HEPMC weight given in [mb]. We choose here the [pb] normalization.')
1594 self.add_param("Check:epTolErr", 1e-2,
1595 hidden=True,
1596 comment='Be more forgiving with momentum mismatches.')
1597
1598
1599 self.add_param("JetMatching:etaJetMax", 1000.0, hidden=True, always_write_to_card=True)
1600
1601
1602
1603 self.add_param("PDF:pSet", 'LHAPDF5:CT10.LHgrid', hidden=True, always_write_to_card=False,
1604 comment='Reminder: Parameter below is shower tune dependent.')
1605 self.add_param("SpaceShower:alphaSvalue", 0.118, hidden=True, always_write_to_card=False,
1606 comment='Reminder: Parameter below is shower tune dependent.')
1607 self.add_param("TimeShower:alphaSvalue", 0.118, hidden=True, always_write_to_card=False,
1608 comment='Reminder: Parameter below is shower tune dependent.')
1609 self.add_param("hadronlevel:all", True, hidden=True, always_write_to_card=False,
1610 comment='This allows to turn on/off hadronization alltogether.')
1611 self.add_param("partonlevel:mpi", True, hidden=True, always_write_to_card=False,
1612 comment='This allows to turn on/off MPI alltogether.')
1613 self.add_param("Beams:setProductionScalesFromLHEF", False, hidden=True,
1614 always_write_to_card=False,
1615 comment='This parameter is automatically set to True by MG5aMC when doing MLM merging with PY8.')
1616
1617
1618 self.add_param("JetMatching:merge", False, hidden=True, always_write_to_card=False,
1619 comment='Specifiy if we are merging sample of different multiplicity.')
1620 self.add_param("SysCalc:qCutList", [10.0,20.0], hidden=True, always_write_to_card=False)
1621 self['SysCalc:qCutList'] = 'auto'
1622 self.add_param("SysCalc:qWeed",-1.0,hidden=True, always_write_to_card=False,
1623 comment='Value of the merging scale below which one does not even write the HepMC event.')
1624 self.add_param("JetMatching:doVeto", False, hidden=True, always_write_to_card=False,
1625 comment='Do veto externally (e.g. in SysCalc).')
1626 self.add_param("JetMatching:scheme", 1, hidden=True, always_write_to_card=False)
1627 self.add_param("JetMatching:setMad", False, hidden=True, always_write_to_card=False,
1628 comment='Specify one must read inputs from the MadGraph banner.')
1629 self.add_param("JetMatching:coneRadius", 1.0, hidden=True, always_write_to_card=False)
1630 self.add_param("JetMatching:nQmatch",4,hidden=True, always_write_to_card=False)
1631
1632 self.add_param("TimeShower:pTmaxMatch", 2, hidden=True, always_write_to_card=False)
1633 self.add_param("SpaceShower:pTmaxMatch", 1, hidden=True, always_write_to_card=False)
1634 self.add_param("SysCalc:tmsList", [10.0,20.0], hidden=True, always_write_to_card=False)
1635 self['SysCalc:tmsList'] = 'auto'
1636 self.add_param("Merging:muFac", 91.188, hidden=True, always_write_to_card=False,
1637 comment='Set factorisation scales of the 2->2 process.')
1638 self.add_param("Merging:applyVeto", False, hidden=True, always_write_to_card=False,
1639 comment='Do veto externally (e.g. in SysCalc).')
1640 self.add_param("Merging:includeWeightInXsection", True, hidden=True, always_write_to_card=False,
1641 comment='If turned off, then the option belows forces PY8 to keep the original weight.')
1642 self.add_param("Merging:muRen", 91.188, hidden=True, always_write_to_card=False,
1643 comment='Set renormalization scales of the 2->2 process.')
1644 self.add_param("Merging:muFacInME", 91.188, hidden=True, always_write_to_card=False,
1645 comment='Set factorisation scales of the 2->2 Matrix Element.')
1646 self.add_param("Merging:muRenInME", 91.188, hidden=True, always_write_to_card=False,
1647 comment='Set renormalization scales of the 2->2 Matrix Element.')
1648 self.add_param("SpaceShower:rapidityOrder", False, hidden=True, always_write_to_card=False)
1649 self.add_param("Merging:nQuarksMerge",4,hidden=True, always_write_to_card=False)
1650
1651 self.add_param("Merging:mayRemoveDecayProducts", False, hidden=True, always_write_to_card=False)
1652 self.add_param("Merging:doKTMerging", False, hidden=True, always_write_to_card=False)
1653 self.add_param("Merging:Dparameter", 0.4, hidden=True, always_write_to_card=False)
1654 self.add_param("Merging:doPTLundMerging", False, hidden=True, always_write_to_card=False)
1655
1656
1657 self.add_param("BeamRemnants:primordialKT", True, hidden=True, always_write_to_card=False, comment="see http://home.thep.lu.se/~torbjorn/pythia82html/BeamRemnants.html")
1658 self.add_param("PartonLevel:Remnants", True, hidden=True, always_write_to_card=False, comment="Master switch for addition of beam remnants. Cannot be used to generate complete events")
1659 self.add_param("Check:event", True, hidden=True, always_write_to_card=False, comment="check physical sanity of the events")
1660 self.add_param("TimeShower:QEDshowerByQ", True, hidden=True, always_write_to_card=False, comment="Allow quarks to radiate photons for FSR, i.e. branchings q -> q gamma")
1661 self.add_param("TimeShower:QEDshowerByL", True, hidden=True, always_write_to_card=False, comment="Allow leptons to radiate photons for FSR, i.e. branchings l -> l gamma")
1662 self.add_param("SpaceShower:QEDshowerByQ", True, hidden=True, always_write_to_card=False, comment="Allow quarks to radiate photons for ISR, i.e. branchings q -> q gamma")
1663 self.add_param("SpaceShower:QEDshowerByL", True, hidden=True, always_write_to_card=False, comment="Allow leptons to radiate photonsfor ISR, i.e. branchings l -> l gamma")
1664 self.add_param("PartonLevel:FSRinResonances", True, hidden=True, always_write_to_card=False, comment="Do not allow shower to run from decay product of unstable particle")
1665 self.add_param("ProcessLevel:resonanceDecays", True, hidden=True, always_write_to_card=False, comment="Do not allow unstable particle to decay.")
1666
1667
1668
1669 self.add_default_subruns('parameters')
1670
1672
1673
1674
1675 self.hidden_param = []
1676 self.hidden_params_to_always_write = set()
1677 self.visible_params_to_always_write = set()
1678
1679 self.params_to_never_write = set()
1680
1681
1682
1683 self.system_set = set()
1684
1685
1686
1687 self.add_default_subruns('attributes')
1688
1689
1690 super(PY8Card, self).__init__(*args, **opts)
1691
1692 - def add_param(self, name, value, hidden=False, always_write_to_card=True,
1693 comment=None):
1694 """ add a parameter to the card. value is the default value and
1695 defines the type (int/float/bool/str) of the input.
1696 The option 'hidden' decides whether the parameter should be visible to the user.
1697 The option 'always_write_to_card' decides whether it should
1698 always be printed or only when it is system_set or user_set.
1699 The option 'comment' can be used to specify a comment to write above
1700 hidden parameters.
1701 """
1702 super(PY8Card, self).add_param(name, value, comment=comment)
1703 name = name.lower()
1704 if hidden:
1705 self.hidden_param.append(name)
1706 if always_write_to_card:
1707 self.hidden_params_to_always_write.add(name)
1708 else:
1709 if always_write_to_card:
1710 self.visible_params_to_always_write.add(name)
1711 if not comment is None:
1712 if not isinstance(comment, str):
1713 raise MadGraph5Error("Option 'comment' must be a string, not"+\
1714 " '%s'."%str(comment))
1715
1717 """Add a subrun to this PY8 Card."""
1718 assert(isinstance(py8_subrun,PY8SubRun))
1719 if py8_subrun['Main:subrun']==-1:
1720 raise MadGraph5Error, "Make sure to correctly set the subrun ID"+\
1721 " 'Main:subrun' *before* adding it to the PY8 Card."
1722 if py8_subrun['Main:subrun'] in self.subruns:
1723 raise MadGraph5Error, "A subrun with ID '%s'"%py8_subrun['Main:subrun']+\
1724 " is already present in this PY8 card. Remove it first, or "+\
1725 " access it directly."
1726 self.subruns[py8_subrun['Main:subrun']] = py8_subrun
1727 if not 'LHEFInputs:nSubruns' in self.user_set:
1728 self['LHEFInputs:nSubruns'] = max(self.subruns.keys())
1729
1730 - def userSet(self, name, value, **opts):
1731 """Set an attribute of this card, following a user_request"""
1732 self.__setitem__(name, value, change_userdefine=True, **opts)
1733 if name.lower() in self.system_set:
1734 self.system_set.remove(name.lower())
1735
1737 """ Forbid the writeout of a specific parameter of this card when the
1738 "write" function will be invoked."""
1739 self.params_to_never_write.add(name.lower())
1740
1742 """Set an attribute of this card, independently of a specific user
1743 request and only if not already user_set."""
1744 try:
1745 force = opts.pop('force')
1746 except KeyError:
1747 force = False
1748 if force or name.lower() not in self.user_set:
1749 self.__setitem__(name, value, change_userdefine=False, **opts)
1750 self.system_set.add(name.lower())
1751
1753 """ Sets a card attribute, but only if it is absent or not already
1754 user_set."""
1755 try:
1756 force = opts.pop('force')
1757 except KeyError:
1758 force = False
1759 if name.lower() not in self or (force or name.lower() not in self.user_set):
1760 self.__setitem__(name, value, change_userdefine=False, **opts)
1761 self.system_set.add(name.lower())
1762
1765
1766 @staticmethod
1817
1818
1819 - def write(self, output_file, template, read_subrun=False,
1820 print_only_visible=False, direct_pythia_input=False, add_missing=True):
1821 """ Write the card to output_file using a specific template.
1822 > 'print_only_visible' specifies whether or not the hidden parameters
1823 should be written out if they are in the hidden_params_to_always_write
1824 list and system_set.
1825 > If 'direct_pythia_input' is true, then visible parameters which are not
1826 in the self.visible_params_to_always_write list and are not user_set
1827 or system_set are commented.
1828 > If 'add_missing' is False then parameters that should be written_out but are absent
1829 from the template will not be written out."""
1830
1831
1832 visible_param = [p for p in self if p.lower() not in self.hidden_param
1833 or p.lower() in self.user_set]
1834
1835 visible_param = [p for p in visible_param if p.lower() not in self.params_to_never_write]
1836
1837
1838 if print_only_visible:
1839 hidden_output_param = []
1840 else:
1841 hidden_output_param = [p for p in self if p.lower() in self.hidden_param and
1842 not p.lower() in self.user_set and
1843 (p.lower() in self.hidden_params_to_always_write or
1844 p.lower() in self.system_set)]
1845
1846 hidden_output_param = [p for p in hidden_output_param if p not in self.params_to_never_write]
1847
1848 if print_only_visible:
1849 subruns = []
1850 else:
1851 if not read_subrun:
1852 subruns = sorted(self.subruns.keys())
1853
1854
1855
1856 subruns_to_write = {}
1857
1858
1859
1860 def group_params(params):
1861 if len(params)==0:
1862 return []
1863 groups = {}
1864 for p in params:
1865 try:
1866 groups[':'.join(p.split(':')[:-1])].append(p)
1867 except KeyError:
1868 groups[':'.join(p.split(':')[:-1])] = [p,]
1869 res = sum(groups.values(),[])
1870
1871 if 'Main:subrun' in res:
1872 res.insert(0,res.pop(res.index('Main:subrun')))
1873
1874 if 'LHEFInputs:nSubruns' in res:
1875 res.append(res.pop(res.index('LHEFInputs:nSubruns')))
1876 return res
1877
1878 visible_param = group_params(visible_param)
1879 hidden_output_param = group_params(hidden_output_param)
1880
1881
1882
1883 output = StringIO.StringIO()
1884
1885
1886 if isinstance(template, str):
1887 if os.path.isfile(template):
1888 tmpl = open(template, 'r')
1889 elif '\n' in template:
1890 tmpl = StringIO.StringIO(template)
1891 else:
1892 raise Exception, "File input '%s' not found." % file_input
1893 elif template is None:
1894
1895 tmpl = StringIO.StringIO()
1896 elif isinstance(template, (StringIO.StringIO, file)):
1897 tmpl = template
1898 else:
1899 raise MadGraph5Error("Incorrect type for argument 'template': %s"%
1900 template.__class__.__name__)
1901
1902
1903 last_pos = tmpl.tell()
1904 line = tmpl.readline()
1905 started_subrun_reading = False
1906 while line!='':
1907
1908 if line.strip().startswith('!') or \
1909 line.strip().startswith('\n') or\
1910 line.strip() == '':
1911 output.write(line)
1912
1913 last_pos = tmpl.tell()
1914 line = tmpl.readline()
1915 continue
1916
1917 try:
1918 param_entry, value_entry = line.split('=')
1919 param = param_entry.strip()
1920 value = value_entry.strip()
1921 except ValueError:
1922 line = line.replace('\n','')
1923 raise MadGraph5Error, "Could not read line '%s' of Pythia8 card."%\
1924 line
1925
1926 if param=='Main:subrun':
1927 if read_subrun:
1928 if not started_subrun_reading:
1929
1930 started_subrun_reading = True
1931 else:
1932
1933 tmpl.seek(last_pos)
1934 break
1935 else:
1936
1937 tmpl.seek(last_pos)
1938 subruns_to_write[int(value)] = StringIO.StringIO()
1939 if int(value) in subruns:
1940 self.subruns[int(value)].write(subruns_to_write[int(value)],
1941 tmpl,read_subrun=True)
1942
1943 subruns.pop(subruns.index(int(value)))
1944 else:
1945
1946 DummySubrun=PY8SubRun()
1947
1948 DummySubrun.clear()
1949 DummySubrun.write(subruns_to_write[int(value)],
1950 tmpl, read_subrun=True,
1951 print_only_visible=print_only_visible,
1952 direct_pythia_input=direct_pythia_input)
1953
1954 logger.info('Adding new unknown subrun with ID %d.'%
1955 int(value))
1956
1957 last_pos = tmpl.tell()
1958 line = tmpl.readline()
1959 continue
1960
1961
1962 if param in visible_param:
1963 new_value = PY8Card.pythia8_formatting(self[param])
1964 visible_param.pop(visible_param.index(param))
1965 elif param in hidden_output_param:
1966 new_value = PY8Card.pythia8_formatting(self[param])
1967 hidden_output_param.pop(hidden_output_param.index(param))
1968 else:
1969
1970 if param.lower() not in self.params_to_never_write:
1971 output.write(line)
1972 else:
1973 output.write('! The following parameter was forced to be commented out by MG5aMC.\n')
1974 output.write('! %s'%line)
1975
1976 last_pos = tmpl.tell()
1977 line = tmpl.readline()
1978 continue
1979
1980
1981
1982
1983
1984 if ((not direct_pythia_input) or
1985 (param.lower() in self.visible_params_to_always_write) or
1986 (param.lower() in self.user_set) or
1987 (param.lower() in self.system_set)):
1988 template = '%s=%s'
1989 else:
1990
1991
1992
1993 template = '!%s=%s'
1994
1995 output.write(template%(param_entry,
1996 value_entry.replace(value,new_value)))
1997
1998
1999 last_pos = tmpl.tell()
2000 line = tmpl.readline()
2001
2002
2003 if not add_missing:
2004 visible_param = []
2005 hidden_output_param = []
2006
2007
2008 if len(visible_param)>0 and not template is None:
2009 output.write(
2010 """!
2011 ! Additional general parameters%s.
2012 !
2013 """%(' for subrun %d'%self['Main:subrun'] if 'Main:subrun' in self else ''))
2014 for param in visible_param:
2015 value = PY8Card.pythia8_formatting(self[param])
2016 output.write('%s=%s\n'%(param,value))
2017 if template is None:
2018 if param=='Main:subrun':
2019 output.write(
2020 """!
2021 ! Definition of subrun %d
2022 !
2023 """%self['Main:subrun'])
2024 elif param.lower() not in self.hidden_param:
2025 logger.debug('Adding parameter %s (missing in the template) to current '+\
2026 'pythia8 card (with value %s)',param, value)
2027
2028 if len(hidden_output_param)>0 and not template is None:
2029 output.write(
2030 """!
2031 ! Additional technical parameters%s set by MG5_aMC.
2032 !
2033 """%(' for subrun %d'%self['Main:subrun'] if 'Main:subrun' in self else ''))
2034 for param in hidden_output_param:
2035 if param.lower() in self.comments:
2036 comment = '\n'.join('! %s'%c for c in
2037 self.comments[param.lower()].split('\n'))
2038 output.write(comment+'\n')
2039 output.write('%s=%s\n'%(param,PY8Card.pythia8_formatting(self[param])))
2040
2041
2042
2043 if read_subrun:
2044 output_file.write(output.getvalue())
2045 return
2046
2047
2048 for subrunID in subruns:
2049 new_subrun = StringIO.StringIO()
2050 self.subruns[subrunID].write(new_subrun,None,read_subrun=True)
2051 subruns_to_write[subrunID] = new_subrun
2052
2053
2054 for subrunID in sorted(subruns_to_write):
2055 output.write(subruns_to_write[subrunID].getvalue())
2056
2057
2058
2059 if 'LHEFInputs:nSubruns'.lower() not in self.user_set and \
2060 len(subruns_to_write)>0 and 'LHEFInputs:nSubruns' in self\
2061 and self['LHEFInputs:nSubruns']<max(subruns_to_write.keys()):
2062 logger.info("Updating PY8 parameter 'LHEFInputs:nSubruns' to "+
2063 "%d so as to cover all defined subruns."%max(subruns_to_write.keys()))
2064 self['LHEFInputs:nSubruns'] = max(subruns_to_write.keys())
2065 output = StringIO.StringIO()
2066 self.write(output,template,print_only_visible=print_only_visible)
2067
2068
2069 if isinstance(output_file, str):
2070 out = open(output_file,'w')
2071 out.write(output.getvalue())
2072 out.close()
2073 else:
2074 output_file.write(output.getvalue())
2075
2076 - def read(self, file_input, read_subrun=False, setter='default'):
2077 """Read the input file, this can be a path to a file,
2078 a file object, a str with the content of the file.
2079 The setter option choses the authority that sets potential
2080 modified/new parameters. It can be either:
2081 'default' or 'user' or 'system'"""
2082 if isinstance(file_input, str):
2083 if "\n" in file_input:
2084 finput = StringIO.StringIO(file_input)
2085 elif os.path.isfile(file_input):
2086 finput = open(file_input)
2087 else:
2088 raise Exception, "File input '%s' not found." % file_input
2089 elif isinstance(file_input, (StringIO.StringIO, file)):
2090 finput = file_input
2091 else:
2092 raise MadGraph5Error("Incorrect type for argument 'file_input': %s"%
2093 file_input.__class__.__name__)
2094
2095
2096 last_pos = finput.tell()
2097 line = finput.readline()
2098 started_subrun_reading = False
2099 while line!='':
2100
2101 if line.strip().startswith('!') or line.strip()=='':
2102
2103 last_pos = finput.tell()
2104 line = finput.readline()
2105 continue
2106
2107 try:
2108 param, value = line.split('=',1)
2109 param = param.strip()
2110 value = value.strip()
2111 except ValueError:
2112 line = line.replace('\n','')
2113 raise MadGraph5Error, "Could not read line '%s' of Pythia8 card."%\
2114 line
2115 if '!' in value:
2116 value,_ = value.split('!',1)
2117
2118
2119 if param=='Main:subrun':
2120 if read_subrun:
2121 if not started_subrun_reading:
2122
2123 started_subrun_reading = True
2124 else:
2125
2126 finput.seek(last_pos)
2127 return
2128 else:
2129
2130 finput.seek(last_pos)
2131 if int(value) in self.subruns:
2132 self.subruns[int(value)].read(finput,read_subrun=True,
2133 setter=setter)
2134 else:
2135
2136 NewSubrun=PY8SubRun()
2137 NewSubrun.read(finput,read_subrun=True, setter=setter)
2138 self.add_subrun(NewSubrun)
2139
2140
2141 last_pos = finput.tell()
2142 line = finput.readline()
2143 continue
2144
2145
2146
2147
2148
2149 if setter == 'user':
2150 self.userSet(param,value)
2151 elif setter == 'system':
2152 self.systemSet(param,value)
2153 else:
2154 self.defaultSet(param,value)
2155
2156
2157 last_pos = finput.tell()
2158 line = finput.readline()
2159
2161 """ Class to characterize a specific PY8 card subrun section. """
2162
2164 """ Overloading of the homonym function called in the __init__ of PY8Card.
2165 The initialization of the self.subruns attribute should of course not
2166 be performed in PY8SubRun."""
2167 pass
2168
2170 """ Initialize a subrun """
2171
2172
2173 subrunID = -1
2174 if 'subrun_id' in opts:
2175 subrunID = opts.pop('subrun_id')
2176
2177 super(PY8SubRun, self).__init__(*args, **opts)
2178 self['Main:subrun']=subrunID
2179
2181 """Sets up the list of available PY8SubRun parameters."""
2182
2183
2184 super(PY8SubRun, self).default_setup()
2185
2186 self.hidden_param = [k.lower() for k in self.keys()]
2187 self.hidden_params_to_always_write = set()
2188 self.visible_params_to_always_write = set()
2189
2190
2191 self.add_param("Main:subrun", -1)
2192 self.add_param("Beams:LHEF", "events.lhe.gz")
2193
2194
2195
2196 runblock = collections.namedtuple('block', ('name', 'fields', 'template_on', 'template_off'))
2198
2199 filename = 'run_card'
2200 blocks = []
2201
2202 - def __new__(cls, finput=None, **opt):
2203 if cls is RunCard:
2204 if not finput:
2205 target_class = RunCardLO
2206 elif isinstance(finput, cls):
2207 target_class = finput.__class__
2208 elif isinstance(finput, str):
2209 if '\n' not in finput:
2210 finput = open(finput).read()
2211 if 'req_acc_FO' in finput:
2212 target_class = RunCardNLO
2213 else:
2214 target_class = RunCardLO
2215 else:
2216 return None
2217 return super(RunCard, cls).__new__(target_class, finput, **opt)
2218 else:
2219 return super(RunCard, cls).__new__(cls, finput, **opt)
2220
2222
2223
2224
2225
2226 self.hidden_param = []
2227
2228 self.includepath = collections.defaultdict(list)
2229
2230 self.fortran_name = {}
2231
2232 self.legacy_parameter = {}
2233
2234 self.cuts_parameter = []
2235
2236 self.system_default = {}
2237
2238 self.display_block = []
2239 self.warned=False
2240
2241
2242 super(RunCard, self).__init__(*args, **opts)
2243
2244 - def add_param(self, name, value, fortran_name=None, include=True,
2245 hidden=False, legacy=False, cut=False, system=False, sys_default=None,
2246 **opts):
2247 """ add a parameter to the card. value is the default value and
2248 defines the type (int/float/bool/str) of the input.
2249 fortran_name defines what is the associate name in the f77 code
2250 include defines if we have to put the value in the include file
2251 hidden defines if the parameter is expected to be define by the user.
2252 legacy:Parameter which is not used anymore (raise a warning if not default)
2253 cut: defines the list of cut parameter to allow to set them all to off.
2254 sys_default: default used if the parameter is not in the card
2255
2256 options of **opts:
2257 - allowed: list of valid options. '*' means anything else should be allowed.
2258 empty list means anything possible as well.
2259 - comment: add comment for writing/help
2260 - typelist: type of the list if default is empty
2261 """
2262
2263 super(RunCard, self).add_param(name, value, system=system,**opts)
2264 name = name.lower()
2265 if fortran_name:
2266 self.fortran_name[name] = fortran_name
2267 if legacy:
2268 self.legacy_parameter[name] = value
2269 include = False
2270 self.includepath[include].append(name)
2271 if hidden or system:
2272 self.hidden_param.append(name)
2273 if cut:
2274 self.cuts_parameter.append(name)
2275 if sys_default is not None:
2276 self.system_default[name] = sys_default
2277
2278
2279
2280 - def read(self, finput, consistency=True):
2281 """Read the input file, this can be a path to a file,
2282 a file object, a str with the content of the file."""
2283
2284 if isinstance(finput, str):
2285 if "\n" in finput:
2286 finput = finput.split('\n')
2287 elif os.path.isfile(finput):
2288 finput = open(finput)
2289 else:
2290 raise Exception, "No such file %s" % finput
2291
2292 for line in finput:
2293 line = line.split('#')[0]
2294 line = line.split('!')[0]
2295 line = line.rsplit('=',1)
2296 if len(line) != 2:
2297 continue
2298 value, name = line
2299 name = name.lower().strip()
2300 if name not in self and ('min' in name or 'max' in name):
2301
2302 self.add_param(name, float(value), hidden=True, cut=True)
2303 else:
2304 self.set( name, value, user=True)
2305
2306 if consistency:
2307 try:
2308 self.check_validity()
2309 except InvalidRunCard, error:
2310 if consistency == 'warning':
2311 logger.warning(str(error))
2312 else:
2313 raise
2314
2315
2316 - def write(self, output_file, template=None, python_template=False,
2317 write_hidden=False):
2318 """Write the run_card in output_file according to template
2319 (a path to a valid run_card)"""
2320
2321 to_write = set(self.user_set)
2322 written = set()
2323 if not template:
2324 raise Exception
2325
2326
2327 write_block= []
2328 for b in self.blocks:
2329 name = b.name
2330
2331 if name not in self.display_block and \
2332 not any(f in self.user_set for f in b.fields):
2333 continue
2334 write_block.append(b.name)
2335
2336 if python_template and not to_write:
2337 import string
2338 text = file(template,'r').read()
2339 if self.blocks:
2340 text = string.Template(text)
2341 mapping = {}
2342 for b in self.blocks:
2343 if b.name in write_block:
2344 mapping[b.name] = b.template_on
2345 else:
2346 mapping[b.name] = b.template_off
2347 text = text.substitute(mapping)
2348
2349 if not self.list_parameter:
2350 text = text % self
2351 else:
2352 data = dict(self)
2353 for name in self.list_parameter:
2354 if self.list_parameter[name] != str:
2355 data[name] = ', '.join(str(v) for v in data[name])
2356 else:
2357 data[name] = "['%s']" % "', '".join(str(v) for v in data[name])
2358 text = text % data
2359 else:
2360 text = ""
2361 for line in file(template,'r'):
2362 nline = line.split('#')[0]
2363 nline = nline.split('!')[0]
2364 comment = line[len(nline):]
2365 nline = nline.split('=')
2366 if python_template and nline[0].startswith('$'):
2367 block_name = nline[0][1:]
2368 this_group = [b for b in self.blocks if b.name == block_name]
2369 if not this_group:
2370 logger.debug("block %s not defined", block_name)
2371 continue
2372 else:
2373 this_group = this_group[0]
2374 if block_name in write_block:
2375 text += this_group.on_template % self
2376 for name in this_group.fields:
2377 written.add(f)
2378 if name in to_write:
2379 to_write.remove(name)
2380 else:
2381 text += this_group.template_off % self
2382
2383 elif len(nline) != 2:
2384 text += line
2385 elif nline[1].strip() in self:
2386 name = nline[1].strip().lower()
2387 value = self[name]
2388 if name in self.list_parameter:
2389 if self.list_parameter[name] != str:
2390 value = ', '.join([str(v) for v in value])
2391 else:
2392 value = "['%s']" % "', '".join(str(v) for v in value)
2393 if python_template:
2394 text += line % {nline[1].strip():value, name:value}
2395 written.add(name)
2396 else:
2397 if not comment or comment[-1]!='\n':
2398 endline = '\n'
2399 else:
2400 endline = ''
2401 text += ' %s\t= %s %s%s' % (value, name, comment, endline)
2402 written.add(name)
2403
2404 if name in to_write:
2405 to_write.remove(name)
2406 else:
2407 logger.info('Adding missing parameter %s to current %s (with default value)',
2408 (name, self.filename))
2409 written.add(name)
2410 text += line
2411
2412 for b in self.blocks:
2413 if b.name not in write_block:
2414 continue
2415
2416 if all(f in written for f in b.fields):
2417 continue
2418
2419 to_add = []
2420 for line in b.template_on.split('\n'):
2421 nline = line.split('#')[0]
2422 nline = nline.split('!')[0]
2423 nline = nline.split('=')
2424 if len(nline) != 2:
2425 to_add.append(line)
2426 elif nline[1].strip() in self:
2427 name = nline[1].strip().lower()
2428 value = self[name]
2429 if name in self.list_parameter:
2430 value = ', '.join([str(v) for v in value])
2431 if name in written:
2432 continue
2433 else:
2434 to_add.append(line % {nline[1].strip():value, name:value})
2435 written.add(name)
2436
2437 if name in to_write:
2438 to_write.remove(name)
2439 else:
2440 raise Exception
2441
2442 if b.template_off in text:
2443 text = text.replace(b.template_off, '\n'.join(to_add))
2444 else:
2445 text += '\n'.join(to_add)
2446
2447 if to_write or write_hidden:
2448 text+="""#*********************************************************************
2449 # Additional hidden parameters
2450 #*********************************************************************
2451 """
2452 if write_hidden:
2453
2454
2455
2456 if python_template:
2457 written = written.union(set(re.findall('\%\((\w*)\)s', file(template,'r').read(), re.M)))
2458 to_write = to_write.union(set(self.hidden_param))
2459 to_write = to_write.difference(written)
2460
2461 for key in to_write:
2462 if key in self.system_only:
2463 continue
2464
2465 comment = self.comments.get(key,'hidden_parameter').replace('\n','\n#')
2466 text += ' %s\t= %s # %s\n' % (self[key], key, comment)
2467
2468 if isinstance(output_file, str):
2469 fsock = open(output_file,'w')
2470 fsock.write(text)
2471 fsock.close()
2472 else:
2473 output_file.write(text)
2474
2475
2476 - def get_default(self, name, default=None, log_level=None):
2477 """return self[name] if exist otherwise default. log control if we
2478 put a warning or not if we use the default value"""
2479
2480 lower_name = name.lower()
2481 if lower_name not in self.user_set:
2482 if log_level is None:
2483 if lower_name in self.system_only:
2484 log_level = 5
2485 elif lower_name in self.auto_set:
2486 log_level = 5
2487 elif lower_name in self.hidden_param:
2488 log_level = 10
2489 else:
2490 log_level = 20
2491 if not default:
2492 default = dict.__getitem__(self, name.lower())
2493
2494 logger.log(log_level, '%s missed argument %s. Takes default: %s'
2495 % (self.filename, name, default))
2496 self[name] = default
2497 return default
2498 else:
2499 return self[name]
2500
2501
2502 @staticmethod
2551
2552
2553
2555 """check that parameter missing in the card are set to the expected value"""
2556
2557 for name, value in self.system_default.items():
2558 self.set(name, value, changeifuserset=False)
2559
2560
2561 for name in self.includepath[False]:
2562 to_bypass = self.hidden_param + self.legacy_parameter.keys()
2563 if name not in to_bypass:
2564 self.get_default(name, log_level=log_level)
2565
2566 for name in self.legacy_parameter:
2567 if self[name] != self.legacy_parameter[name]:
2568 logger.warning("The parameter %s is not supported anymore this parameter will be ignored." % name)
2569
2570 default_include_file = 'run_card.inc'
2571
2573 """update hidden system only parameter for the correct writtin in the
2574 include"""
2575 return
2576
2578 """Write the various include file in output_dir.
2579 The entry True of self.includepath will be written in run_card.inc
2580 The entry False will not be written anywhere"""
2581
2582
2583 self.check_validity()
2584
2585
2586 self.update_system_parameter_for_include()
2587
2588 for incname in self.includepath:
2589 if incname is True:
2590 pathinc = self.default_include_file
2591 elif incname is False:
2592 continue
2593 else:
2594 pathinc = incname
2595
2596 fsock = file_writers.FortranWriter(pjoin(output_dir,pathinc))
2597 for key in self.includepath[incname]:
2598
2599 if key in self.fortran_name:
2600 fortran_name = self.fortran_name[key]
2601 else:
2602 fortran_name = key
2603
2604
2605 value = self.get_default(key)
2606
2607
2608 if isinstance(value, list):
2609
2610
2611
2612 targettype = self.list_parameter[key]
2613 if targettype is bool:
2614 pass
2615 elif targettype is int:
2616 line = '%s(%s) = %s \n' % (fortran_name, 0, self.f77_formatting(len(value)))
2617 fsock.writelines(line)
2618 elif targettype is float:
2619 line = '%s(%s) = %s \n' % (fortran_name, 0, self.f77_formatting(float(len(value))))
2620 fsock.writelines(line)
2621
2622 for i,v in enumerate(value):
2623 line = '%s(%s) = %s \n' % (fortran_name, i+1, self.f77_formatting(v))
2624 fsock.writelines(line)
2625 elif isinstance(value, dict):
2626 for fortran_name, onevalue in value.items():
2627 line = '%s = %s \n' % (fortran_name, self.f77_formatting(onevalue))
2628 fsock.writelines(line)
2629 else:
2630 line = '%s = %s \n' % (fortran_name, self.f77_formatting(value))
2631 fsock.writelines(line)
2632 fsock.close()
2633
2634 @staticmethod
2636 """return the particle colliding pdg code"""
2637 if lpp in (1,2, -1,-2):
2638 return math.copysign(2212, lpp)
2639 elif lpp in (3,-3):
2640 return math.copysign(11, lpp)
2641 elif lpp == 0:
2642
2643 return 0
2644 else:
2645 return lpp
2646
2661
2663 if pdf == "lhapdf":
2664 lhaid = self["lhaid"]
2665 if isinstance(lhaid, list):
2666 return lhaid[0]
2667 else:
2668 return lhaid
2669 else:
2670 return {'none': 0,
2671 'cteq6_m':10000,'cteq6_l':10041,'cteq6l1':10042,
2672 'nn23lo':246800,'nn23lo1':247000,'nn23nlo':244800
2673 }[pdf]
2674
2677
2679 """remove all the cut"""
2680
2681 for name in self.cuts_parameter:
2682 targettype = type(self[name])
2683 if targettype == bool:
2684 self[name] = False
2685 elif 'min' in name:
2686 self[name] = 0
2687 elif 'max' in name:
2688 self[name] = -1
2689 elif 'eta' in name:
2690 self[name] = -1
2691 else:
2692 self[name] = 0
2693
2695 """an object to handle in a nice way the run_card information"""
2696
2697 blocks = [
2698
2699 runblock(name='ion_pdf', fields=('nb_neutron1', 'nb_neutron2','nb_proton1','nb_proton2','mass_ion1', 'mass_ion2'),
2700 template_on=\
2701 """#*********************************************************************
2702 # Heavy ion PDF / rescaling of PDF *
2703 #*********************************************************************
2704 %(nb_proton1)s = nb_proton1 # number of proton for the first beam
2705 %(nb_neutron1)s = nb_neutron1 # number of neutron for the first beam
2706 %(mass_ion1)s = mass_ion1 # mass of the heavy ion (first beam)
2707 # Note that seting differently the two beams only work if you use
2708 # group_subprocess=False when generating your matrix-element
2709 %(nb_proton2)s = nb_proton2 # number of proton for the second beam
2710 %(nb_neutron2)s = nb_neutron2 # number of neutron for the second beam
2711 %(mass_ion2)s = mass_ion2 # mass of the heavy ion (second beam)
2712 """,
2713 template_off='# To see heavy ion options: type "update ion_pdf"'),
2714
2715
2716
2717 runblock(name='beam_pol', fields=('polbeam1','polbeam2'),
2718 template_on=\
2719 """#*********************************************************************
2720 # Beam polarization from -100 (left-handed) to 100 (right-handed) *
2721 #*********************************************************************
2722 %(polbeam1)s = polbeam1 ! beam polarization for beam 1
2723 %(polbeam2)s = polbeam2 ! beam polarization for beam 2
2724 """,
2725 template_off='# To see polarised beam options: type "update beam_pol"'),
2726
2727
2728 runblock(name='syscalc', fields=('sys_scalefact', 'sys_alpsfact','sys_matchscale','sys_pdf'),
2729 template_on=\
2730 """#**************************************
2731 # Parameter below of the systematics study
2732 # will be used by SysCalc (if installed)
2733 #**************************************
2734 #
2735 %(sys_scalefact)s = sys_scalefact # factorization/renormalization scale factor
2736 %(sys_alpsfact)s = sys_alpsfact # \alpha_s emission scale factors
2737 %(sys_matchscale)s = sys_matchscale # variation of merging scale
2738 # PDF sets and number of members (0 or none for all members).
2739 %(sys_pdf)s = sys_pdf # list of pdf sets. (errorset not valid for syscalc)
2740 # MSTW2008nlo68cl.LHgrid 1 = sys_pdf
2741 #
2742 """,
2743 template_off= '# Syscalc is deprecated but to see the associate options type\'update syscalc\''),
2744 ]
2745
2746
2747
2749 """default value for the run_card.dat"""
2750
2751 self.add_param("run_tag", "tag_1", include=False)
2752 self.add_param("gridpack", False)
2753 self.add_param("time_of_flight", -1.0, include=False)
2754 self.add_param("nevents", 10000)
2755 self.add_param("iseed", 0)
2756 self.add_param("python_seed", -1, include=False, hidden=True, comment="controlling python seed [handling in particular the final unweighting].\n -1 means use default from random module.\n -2 means set to same value as iseed")
2757 self.add_param("lpp1", 1, fortran_name="lpp(1)", allowed=[-1,1,0,2,3,9, -2,-3],
2758 comment='first beam energy distribution:\n 0: fixed energy\n 1: PDF from proton\n -1: PDF from anti-proton\n 2:photon from proton, 3:photon from electron, 9: PLUGIN MODE')
2759 self.add_param("lpp2", 1, fortran_name="lpp(2)", allowed=[-1,1,0,2,3,9],
2760 comment='first beam energy distribution:\n 0: fixed energy\n 1: PDF from proton\n -1: PDF from anti-proton\n 2:photon from proton, 3:photon from electron, 9: PLUGIN MODE')
2761 self.add_param("ebeam1", 6500.0, fortran_name="ebeam(1)")
2762 self.add_param("ebeam2", 6500.0, fortran_name="ebeam(2)")
2763 self.add_param("polbeam1", 0.0, fortran_name="pb1", hidden=True,
2764 comment="Beam polarization from -100 (left-handed) to 100 (right-handed) --use lpp=0 for this parameter--")
2765 self.add_param("polbeam2", 0.0, fortran_name="pb2", hidden=True,
2766 comment="Beam polarization from -100 (left-handed) to 100 (right-handed) --use lpp=0 for this parameter--")
2767 self.add_param('nb_proton1', 1, hidden=True, allowed=[1,0, 82 , '*'],fortran_name="nb_proton(1)",
2768 comment='For heavy ion physics nb of proton in the ion (for both beam but if group_subprocess was False)')
2769 self.add_param('nb_proton2', 1, hidden=True, allowed=[1,0, 82 , '*'],fortran_name="nb_proton(2)",
2770 comment='For heavy ion physics nb of proton in the ion (used for beam 2 if group_subprocess was False)')
2771 self.add_param('nb_neutron1', 0, hidden=True, allowed=[1,0, 126 , '*'],fortran_name="nb_neutron(1)",
2772 comment='For heavy ion physics nb of neutron in the ion (for both beam but if group_subprocess was False)')
2773 self.add_param('nb_neutron2', 0, hidden=True, allowed=[1,0, 126 , '*'],fortran_name="nb_neutron(2)",
2774 comment='For heavy ion physics nb of neutron in the ion (of beam 2 if group_subprocess was False )')
2775 self.add_param('mass_ion1', -1.0, hidden=True, fortran_name="mass_ion(1)",
2776 allowed=[-1,0, 0.938, 207.9766521*0.938, 0.000511, 0.105, '*'],
2777 comment='For heavy ion physics mass in GeV of the ion (of beam 1)')
2778 self.add_param('mass_ion2', -1.0, hidden=True, fortran_name="mass_ion(2)",
2779 allowed=[-1,0, 0.938, 207.9766521*0.938, 0.000511, 0.105, '*'],
2780 comment='For heavy ion physics mass in GeV of the ion (of beam 2)')
2781
2782 self.add_param("pdlabel", "nn23lo1", allowed=['lhapdf', 'cteq6_m','cteq6_l', 'cteq6l1','nn23lo', 'nn23lo1', 'nn23nlo']),
2783 self.add_param("lhaid", 230000, hidden=True)
2784 self.add_param("fixed_ren_scale", False)
2785 self.add_param("fixed_fac_scale", False)
2786 self.add_param("scale", 91.1880)
2787 self.add_param("dsqrt_q2fact1", 91.1880, fortran_name="sf1")
2788 self.add_param("dsqrt_q2fact2", 91.1880, fortran_name="sf2")
2789 self.add_param("dynamical_scale_choice", -1, comment="\'-1\' is based on CKKW back clustering (following feynman diagram).\n \'1\' is the sum of transverse energy.\n '2' is HT (sum of the transverse mass)\n '3' is HT/2\n '4' is the center of mass energy",
2790 allowed=[-1,0,1,2,3,4])
2791
2792
2793 self.add_param("bias_module", 'None', include=False)
2794 self.add_param('bias_parameters', {'__type__':1.0}, include='BIAS/bias.inc')
2795
2796
2797 self.add_param("scalefact", 1.0)
2798 self.add_param("ickkw", 0, allowed=[0,1], comment="\'0\' for standard fixed order computation.\n\'1\' for MLM merging activates alphas and pdf re-weighting according to a kt clustering of the QCD radiation.")
2799 self.add_param("highestmult", 1, fortran_name="nhmult", hidden=True)
2800 self.add_param("ktscheme", 1, hidden=True)
2801 self.add_param("alpsfact", 1.0)
2802 self.add_param("chcluster", False, hidden=True)
2803 self.add_param("pdfwgt", True, hidden=True)
2804 self.add_param("asrwgtflavor", 5, comment = 'highest quark flavor for a_s reweighting in MLM')
2805 self.add_param("clusinfo", True)
2806 self.add_param("lhe_version", 3.0)
2807 self.add_param("event_norm", "average", allowed=['sum','average', 'unity'],
2808 include=False, sys_default='sum')
2809
2810 self.add_param("auto_ptj_mjj", False)
2811 self.add_param("bwcutoff", 15.0)
2812 self.add_param("cut_decays", False)
2813 self.add_param("nhel", 0, include=False)
2814
2815 self.add_param("ptj", 20.0, cut=True)
2816 self.add_param("ptb", 0.0, cut=True)
2817 self.add_param("pta", 10.0, cut=True)
2818 self.add_param("ptl", 10.0, cut=True)
2819 self.add_param("misset", 0.0, cut=True)
2820 self.add_param("ptheavy", 0.0, cut=True, comment='this cut apply on particle heavier than 10 GeV')
2821 self.add_param("ptonium", 1.0, legacy=True)
2822 self.add_param("ptjmax", -1.0, cut=True)
2823 self.add_param("ptbmax", -1.0, cut=True)
2824 self.add_param("ptamax", -1.0, cut=True)
2825 self.add_param("ptlmax", -1.0, cut=True)
2826 self.add_param("missetmax", -1.0, cut=True)
2827
2828 self.add_param("ej", 0.0, cut=True)
2829 self.add_param("eb", 0.0, cut=True)
2830 self.add_param("ea", 0.0, cut=True)
2831 self.add_param("el", 0.0, cut=True)
2832 self.add_param("ejmax", -1.0, cut=True)
2833 self.add_param("ebmax", -1.0, cut=True)
2834 self.add_param("eamax", -1.0, cut=True)
2835 self.add_param("elmax", -1.0, cut=True)
2836
2837 self.add_param("etaj", 5.0, cut=True)
2838 self.add_param("etab", -1.0, cut=True)
2839 self.add_param("etaa", 2.5, cut=True)
2840 self.add_param("etal", 2.5, cut=True)
2841 self.add_param("etaonium", 0.6, legacy=True)
2842 self.add_param("etajmin", 0.0, cut=True)
2843 self.add_param("etabmin", 0.0, cut=True)
2844 self.add_param("etaamin", 0.0, cut=True)
2845 self.add_param("etalmin", 0.0, cut=True)
2846
2847 self.add_param("drjj", 0.4, cut=True)
2848 self.add_param("drbb", 0.0, cut=True)
2849 self.add_param("drll", 0.4, cut=True)
2850 self.add_param("draa", 0.4, cut=True)
2851 self.add_param("drbj", 0.0, cut=True)
2852 self.add_param("draj", 0.4, cut=True)
2853 self.add_param("drjl", 0.4, cut=True)
2854 self.add_param("drab", 0.0, cut=True)
2855 self.add_param("drbl", 0.0, cut=True)
2856 self.add_param("dral", 0.4, cut=True)
2857 self.add_param("drjjmax", -1.0, cut=True)
2858 self.add_param("drbbmax", -1.0, cut=True)
2859 self.add_param("drllmax", -1.0, cut=True)
2860 self.add_param("draamax", -1.0, cut=True)
2861 self.add_param("drbjmax", -1.0, cut=True)
2862 self.add_param("drajmax", -1.0, cut=True)
2863 self.add_param("drjlmax", -1.0, cut=True)
2864 self.add_param("drabmax", -1.0, cut=True)
2865 self.add_param("drblmax", -1.0, cut=True)
2866 self.add_param("dralmax", -1.0, cut=True)
2867
2868 self.add_param("mmjj", 0.0, cut=True)
2869 self.add_param("mmbb", 0.0, cut=True)
2870 self.add_param("mmaa", 0.0, cut=True)
2871 self.add_param("mmll", 0.0, cut=True)
2872 self.add_param("mmjjmax", -1.0, cut=True)
2873 self.add_param("mmbbmax", -1.0, cut=True)
2874 self.add_param("mmaamax", -1.0, cut=True)
2875 self.add_param("mmllmax", -1.0, cut=True)
2876 self.add_param("mmnl", 0.0, cut=True)
2877 self.add_param("mmnlmax", -1.0, cut=True)
2878
2879 self.add_param("ptllmin", 0.0, cut=True)
2880 self.add_param("ptllmax", -1.0, cut=True)
2881 self.add_param("xptj", 0.0, cut=True)
2882 self.add_param("xptb", 0.0, cut=True)
2883 self.add_param("xpta", 0.0, cut=True)
2884 self.add_param("xptl", 0.0, cut=True)
2885
2886 self.add_param("ptj1min", 0.0, cut=True)
2887 self.add_param("ptj1max", -1.0, cut=True)
2888 self.add_param("ptj2min", 0.0, cut=True)
2889 self.add_param("ptj2max", -1.0, cut=True)
2890 self.add_param("ptj3min", 0.0, cut=True)
2891 self.add_param("ptj3max", -1.0, cut=True)
2892 self.add_param("ptj4min", 0.0, cut=True)
2893 self.add_param("ptj4max", -1.0, cut=True)
2894 self.add_param("cutuse", 0, cut=True)
2895
2896 self.add_param("ptl1min", 0.0, cut=True)
2897 self.add_param("ptl1max", -1.0, cut=True)
2898 self.add_param("ptl2min", 0.0, cut=True)
2899 self.add_param("ptl2max", -1.0, cut=True)
2900 self.add_param("ptl3min", 0.0, cut=True)
2901 self.add_param("ptl3max", -1.0, cut=True)
2902 self.add_param("ptl4min", 0.0, cut=True)
2903 self.add_param("ptl4max", -1.0, cut=True)
2904
2905 self.add_param("htjmin", 0.0, cut=True)
2906 self.add_param("htjmax", -1.0, cut=True)
2907 self.add_param("ihtmin", 0.0, cut=True)
2908 self.add_param("ihtmax", -1.0, cut=True)
2909 self.add_param("ht2min", 0.0, cut=True)
2910 self.add_param("ht3min", 0.0, cut=True)
2911 self.add_param("ht4min", 0.0, cut=True)
2912 self.add_param("ht2max", -1.0, cut=True)
2913 self.add_param("ht3max", -1.0, cut=True)
2914 self.add_param("ht4max", -1.0, cut=True)
2915
2916 self.add_param("ptgmin", 0.0, cut=True)
2917 self.add_param("r0gamma", 0.4)
2918 self.add_param("xn", 1.0)
2919 self.add_param("epsgamma", 1.0)
2920 self.add_param("isoem", True)
2921 self.add_param("xetamin", 0.0, cut=True)
2922 self.add_param("deltaeta", 0.0, cut=True)
2923 self.add_param("ktdurham", -1.0, fortran_name="kt_durham", cut=True)
2924 self.add_param("dparameter", 0.4, fortran_name="d_parameter", cut=True)
2925 self.add_param("ptlund", -1.0, fortran_name="pt_lund", cut=True)
2926 self.add_param("pdgs_for_merging_cut", [21, 1, 2, 3, 4, 5, 6])
2927 self.add_param("maxjetflavor", 4)
2928 self.add_param("xqcut", 0.0, cut=True)
2929 self.add_param("use_syst", True)
2930 self.add_param('systematics_program', 'systematics', include=False, hidden=True, comment='Choose which program to use for systematics computation: none, systematics, syscalc')
2931 self.add_param('systematics_arguments', ['--mur=0.5,1,2', '--muf=0.5,1,2', '--pdf=errorset'], include=False, hidden=True, comment='Choose the argment to pass to the systematics command. like --mur=0.25,1,4. Look at the help of the systematics function for more details.')
2932
2933 self.add_param("sys_scalefact", "0.5 1 2", include=False, hidden=True)
2934 self.add_param("sys_alpsfact", "None", include=False, hidden=True)
2935 self.add_param("sys_matchscale", "auto", include=False, hidden=True)
2936 self.add_param("sys_pdf", "errorset", include=False, hidden=True)
2937 self.add_param("sys_scalecorrelation", -1, include=False, hidden=True)
2938
2939
2940 self.add_param('gridrun', False, hidden=True)
2941 self.add_param('fixed_couplings', True, hidden=True)
2942 self.add_param('mc_grouped_subproc', True, hidden=True)
2943 self.add_param('xmtcentral', 0.0, hidden=True, fortran_name="xmtc")
2944 self.add_param('d', 1.0, hidden=True)
2945 self.add_param('gseed', 0, hidden=True, include=False)
2946 self.add_param('issgridfile', '', hidden=True)
2947
2948 self.add_param('job_strategy', 0, hidden=True, include=False, allowed=[0,1,2], comment='see appendix of 1507.00020 (page 26)')
2949 self.add_param('survey_splitting', -1, hidden=True, include=False, comment="for loop-induced control how many core are used at survey for the computation of a single iteration.")
2950 self.add_param('survey_nchannel_per_job', 2, hidden=True, include=False, comment="control how many Channel are integrated inside a single job on cluster/multicore")
2951 self.add_param('refine_evt_by_job', -1, hidden=True, include=False, comment="control the maximal number of events for the first iteration of the refine (larger means less jobs)")
2952
2953
2954
2955 self.add_param('pt_min_pdg',{'__type__':0.}, include=False)
2956 self.add_param('pt_max_pdg',{'__type__':0.}, include=False)
2957 self.add_param('E_min_pdg',{'__type__':0.}, include=False)
2958 self.add_param('E_max_pdg',{'__type__':0.}, include=False)
2959 self.add_param('eta_min_pdg',{'__type__':0.}, include=False)
2960 self.add_param('eta_max_pdg',{'__type__':0.}, include=False)
2961 self.add_param('mxx_min_pdg',{'__type__':0.}, include=False)
2962 self.add_param('mxx_only_part_antipart', {'default':False}, include=False)
2963
2964 self.add_param('pdg_cut',[0], system=True)
2965 self.add_param('ptmin4pdg',[0.], system=True)
2966 self.add_param('ptmax4pdg',[-1.], system=True)
2967 self.add_param('Emin4pdg',[0.], system=True)
2968 self.add_param('Emax4pdg',[-1.], system=True)
2969 self.add_param('etamin4pdg',[0.], system=True)
2970 self.add_param('etamax4pdg',[-1.], system=True)
2971 self.add_param('mxxmin4pdg',[-1.], system=True)
2972 self.add_param('mxxpart_antipart', [False], system=True)
2973
2974
2976 """ """
2977
2978 super(RunCardLO, self).check_validity()
2979
2980
2981
2982
2983 if 'nhel' not in self.user_set:
2984 raise InvalidRunCard, "Parameter nhel is not defined in the run_card."
2985 if self['nhel'] not in [1,0]:
2986 raise InvalidRunCard, "Parameter nhel can only be '0' or '1', "+\
2987 "not %s." % self['nhel']
2988 if int(self['maxjetflavor']) > 6:
2989 raise InvalidRunCard, 'maxjetflavor should be lower than 5! (6 is partly supported)'
2990
2991 if len(self['pdgs_for_merging_cut']) > 1000:
2992 raise InvalidRunCard, "The number of elements in "+\
2993 "'pdgs_for_merging_cut' should not exceed 1000."
2994
2995
2996 if self['ptgmin'] > 0:
2997 if self['pta'] > 0:
2998 logger.warning('pta cut discarded since photon isolation is used')
2999 self['pta'] = 0.0
3000 if self['draj'] > 0:
3001 logger.warning('draj cut discarded since photon isolation is used')
3002 self['draj'] = 0.0
3003
3004
3005 if self['gridrun']:
3006 self['iseed'] = self['gseed']
3007
3008
3009 if self['use_syst']:
3010 if self['scalefact'] != 1.0:
3011 logger.warning('Since use_syst=T, We change the value of \'scalefact\' to 1')
3012 self['scalefact'] = 1.0
3013
3014
3015 if self['ickkw'] > 0:
3016 if self['ickkw'] != 1:
3017 logger.critical('ickkw >1 is pure alpha and only partly implemented.')
3018 import madgraph.interface.extended_cmd as basic_cmd
3019 answer = basic_cmd.smart_input('Do you really want to continue', allow_arg=['y','n'], default='n')
3020 if answer !='y':
3021 raise InvalidRunCard, 'ickkw>1 is still in alpha'
3022 if self['use_syst']:
3023
3024 if self['alpsfact'] != 1.0:
3025 logger.warning('Since use_syst=T, We change the value of \'alpsfact\' to 1')
3026 self['alpsfact'] =1.0
3027 if self['maxjetflavor'] == 6:
3028 raise InvalidRunCard, 'maxjetflavor at 6 is NOT supported for matching!'
3029 if self['ickkw'] == 2:
3030
3031 self.get_default('highestmult', log_level=20)
3032 self.get_default('issgridfile', 'issudgrid.dat', log_level=20)
3033 if self['xqcut'] > 0:
3034 if self['ickkw'] == 0:
3035 logger.error('xqcut>0 but ickkw=0. Potentially not fully consistent setup. Be carefull')
3036 import time
3037 time.sleep(5)
3038 if self['drjj'] != 0:
3039 logger.warning('Since icckw>0, We change the value of \'drjj\' to 0')
3040 self['drjj'] = 0
3041 if self['drjl'] != 0:
3042 logger.warning('Since icckw>0, We change the value of \'drjl\' to 0')
3043 self['drjl'] = 0
3044 if not self['auto_ptj_mjj']:
3045 if self['mmjj'] > self['xqcut']:
3046 logger.warning('mmjj > xqcut (and auto_ptj_mjj = F). MMJJ set to 0')
3047 self['mmjj'] = 0.0
3048
3049
3050
3051
3052 if self['pdlabel'] == 'lhapdf':
3053
3054 self.get_default('lhaid', log_level=20)
3055
3057
3058
3059 pdg_to_cut = set(self['pt_min_pdg'].keys() +self['pt_max_pdg'].keys() +
3060 self['e_min_pdg'].keys() +self['e_max_pdg'].keys() +
3061 self['eta_min_pdg'].keys() +self['eta_max_pdg'].keys()+
3062 self['mxx_min_pdg'].keys() + self['mxx_only_part_antipart'].keys())
3063 pdg_to_cut.discard('__type__')
3064 pdg_to_cut.discard('default')
3065 if len(pdg_to_cut)>25:
3066 raise Exception, "Maximum 25 different pdgs are allowed for pdg specific cut"
3067
3068 if any(int(pdg)<0 for pdg in pdg_to_cut):
3069 logger.warning('PDG specific cuts are always applied symmetrically on particle/anti-particle. Always use positve PDG codes')
3070 raise MadGraph5Error, 'Some PDG specific cuts are defined with negative pdg code'
3071
3072
3073 if any(pdg in pdg_to_cut for pdg in [1,2,3,4,5,21,22,11,13,15]):
3074 raise Exception, "Can not use PDG related cut for light quark/b quark/lepton/gluon/photon"
3075
3076 if pdg_to_cut:
3077 self['pdg_cut'] = list(pdg_to_cut)
3078 self['ptmin4pdg'] = []
3079 self['Emin4pdg'] = []
3080 self['etamin4pdg'] =[]
3081 self['ptmax4pdg'] = []
3082 self['Emax4pdg'] = []
3083 self['etamax4pdg'] =[]
3084 self['mxxmin4pdg'] =[]
3085 self['mxxpart_antipart'] = []
3086 for pdg in self['pdg_cut']:
3087 for var in ['pt','e','eta', 'Mxx']:
3088 for minmax in ['min', 'max']:
3089 if var in ['Mxx'] and minmax =='max':
3090 continue
3091 new_var = '%s%s4pdg' % (var, minmax)
3092 old_var = '%s_%s_pdg' % (var, minmax)
3093 default = 0. if minmax=='min' else -1.
3094 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3095
3096 old_var = 'mxx_only_part_antipart'
3097 new_var = 'mxxpart_antipart'
3098 if 'default' in self[old_var]:
3099 default = self[old_var]['default']
3100 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3101 else:
3102 if str(pdg) not in self[old_var]:
3103 raise Exception("no default value defined for %s and no value defined for pdg %s" % (old_var, pdg))
3104 self[new_var].append(self[old_var][str(pdg)])
3105 else:
3106 self['pdg_cut'] = [0]
3107 self['ptmin4pdg'] = [0.]
3108 self['Emin4pdg'] = [0.]
3109 self['etamin4pdg'] =[0.]
3110 self['ptmax4pdg'] = [-1.]
3111 self['Emax4pdg'] = [-1.]
3112 self['etamax4pdg'] =[-1.]
3113 self['mxxmin4pdg'] =[0.]
3114 self['mxxpart_antipart'] = [False]
3115
3116
3117
3119 """Rules
3120 process 1->N all cut set on off.
3121 loop_induced -> MC over helicity
3122 e+ e- beam -> lpp:0 ebeam:500
3123 p p beam -> set maxjetflavor automatically
3124 more than one multiplicity: ickkw=1 xqcut=30 use_syst=F
3125 """
3126
3127 if proc_characteristic['loop_induced']:
3128 self['nhel'] = 1
3129 self['pdgs_for_merging_cut'] = proc_characteristic['colored_pdgs']
3130
3131 if proc_characteristic['ninitial'] == 1:
3132
3133 self.remove_all_cut()
3134 self['use_syst'] = False
3135 else:
3136
3137 beam_id = set()
3138 for proc in proc_def:
3139 for oneproc in proc:
3140 for leg in oneproc['legs']:
3141 if not leg['state']:
3142 beam_id.add(leg['id'])
3143 if any(i in beam_id for i in [1,-1,2,-2,3,-3,4,-4,5,-5,21,22]):
3144 maxjetflavor = max([4]+[abs(i) for i in beam_id if -7< i < 7])
3145 self['maxjetflavor'] = maxjetflavor
3146 self['asrwgtflavor'] = maxjetflavor
3147 pass
3148 elif 11 in beam_id or -11 in beam_id:
3149 self['lpp1'] = 0
3150 self['lpp2'] = 0
3151 self['ebeam1'] = 500
3152 self['ebeam2'] = 500
3153 self['use_syst'] = False
3154 else:
3155 self['lpp1'] = 0
3156 self['lpp2'] = 0
3157 self['use_syst'] = False
3158
3159
3160 min_particle = 99
3161 max_particle = 0
3162 for proc in proc_def:
3163 min_particle = min(len(proc[0]['legs']), min_particle)
3164 max_particle = max(len(proc[0]['legs']), max_particle)
3165 if min_particle != max_particle:
3166
3167 for procmin in proc_def:
3168 if len(procmin[0]['legs']) != min_particle:
3169 continue
3170 else:
3171 idsmin = [l['id'] for l in procmin[0]['legs']]
3172 break
3173 matching = False
3174 for procmax in proc_def:
3175 if len(procmax[0]['legs']) != max_particle:
3176 continue
3177 idsmax = [l['id'] for l in procmax[0]['legs']]
3178 for i in idsmin:
3179 if i not in idsmax:
3180 continue
3181 else:
3182 idsmax.remove(i)
3183 for j in idsmax:
3184 if j not in [1,-1,2,-2,3,-3,4,-4,5,-5,21]:
3185 break
3186 else:
3187
3188 matching=True
3189 break
3190
3191 if matching:
3192 self['ickkw'] = 1
3193 self['xqcut'] = 30
3194
3195 self['drjj'] = 0
3196 self['drjl'] = 0
3197 self['sys_alpsfact'] = "0.5 1 2"
3198
3199
3200
3201 no_systematics = False
3202 for proc in proc_def:
3203 for oneproc in proc:
3204 if '^2' in oneproc.nice_string():
3205 no_systematics = True
3206 break
3207 else:
3208 continue
3209 break
3210 if no_systematics:
3211 self['use_syst'] = False
3212 self['systematics_program'] = 'none'
3213
3214 - def write(self, output_file, template=None, python_template=False,
3215 **opt):
3216 """Write the run_card in output_file according to template
3217 (a path to a valid run_card)"""
3218
3219 if not template:
3220 if not MADEVENT:
3221 template = pjoin(MG5DIR, 'Template', 'LO', 'Cards',
3222 'run_card.dat')
3223 python_template = True
3224 else:
3225 template = pjoin(MEDIR, 'Cards', 'run_card_default.dat')
3226 python_template = False
3227
3228 super(RunCardLO, self).write(output_file, template=template,
3229 python_template=python_template, **opt)
3230
3234
3236 """ A class to store a MadAnalysis5 card. Very basic since it is basically
3237 free format."""
3238
3239 _MG5aMC_escape_tag = '@MG5aMC'
3240
3241 _default_hadron_inputs = ['*.hepmc', '*.hep', '*.stdhep', '*.lhco','*.root']
3242 _default_parton_inputs = ['*.lhe']
3243 _skip_analysis = False
3244
3245 @classmethod
3247 """ Checks from the type of an event file whether it can be reconstructed or not."""
3248 return not (file_path.endswith('.lhco') or file_path.endswith('.lhco.gz') or \
3249 file_path.endswith('.root') or file_path.endswith('.root.gz'))
3250
3251 @classmethod
3253 """ A method returning the structure of an empty analysis """
3254 return {'commands':[],
3255 'reconstructions':[]}
3256
3257 @classmethod
3259 """ A method returning the structure of an empty reconstruction """
3260 return {'commands':[],
3261 'reco_output':'lhe'}
3262
3264 """define the default value"""
3265 self['mode'] = 'parton'
3266 self['inputs'] = []
3267
3268 self['stdout_lvl'] = None
3269
3270
3271
3272
3273
3274
3275
3276 self['analyses'] = {}
3277
3278
3279 self['recasting'] = {'commands':[],'card':[]}
3280
3281
3282 self['reconstruction'] = {'lhco_input':
3283 MadAnalysis5Card.empty_reconstruction(),
3284 'root_input':
3285 MadAnalysis5Card.empty_reconstruction()}
3286 self['reconstruction']['lhco_input']['reco_output']='lhco'
3287 self['reconstruction']['root_input']['reco_output']='root'
3288
3289
3290 self['order'] = []
3291
3292 - def __init__(self, finput=None,mode=None):
3293 if isinstance(finput, self.__class__):
3294 dict.__init__(self, finput)
3295 assert finput.__dict__.keys()
3296 for key in finput.__dict__:
3297 setattr(self, key, copy.copy(getattr(finput, key)) )
3298 return
3299 else:
3300 dict.__init__(self)
3301
3302
3303 self.default_setup()
3304 if not mode is None:
3305 self['mode']=mode
3306
3307
3308 if isinstance(finput, (file, str, StringIO.StringIO)):
3309 self.read(finput, mode=mode)
3310
3311 - def read(self, input, mode=None):
3312 """ Read an MA5 card"""
3313
3314 if mode not in [None,'parton','hadron']:
3315 raise MadGraph5Error('A MadAnalysis5Card can be read online the modes'+
3316 "'parton' or 'hadron'")
3317 card_mode = mode
3318
3319 if isinstance(input, (file, StringIO.StringIO)):
3320 input_stream = input
3321 elif isinstance(input, str):
3322 if not os.path.isfile(input):
3323 raise InvalidMadAnalysis5Card("Cannot read the MadAnalysis5 card."+\
3324 "File '%s' not found."%input)
3325 if mode is None and 'hadron' in input:
3326 card_mode = 'hadron'
3327 input_stream = open(input,'r')
3328 else:
3329 raise MadGraph5Error('Incorrect input for the read function of'+\
3330 ' the MadAnalysis5Card card. Received argument type is: %s'%str(type(input)))
3331
3332
3333 self.__init__()
3334 current_name = 'default'
3335 current_type = 'analyses'
3336 for line in input_stream:
3337
3338 if line.startswith('#'):
3339 continue
3340 if line.endswith('\n'):
3341 line = line[:-1]
3342 if line.strip()=='':
3343 continue
3344 if line.startswith(self._MG5aMC_escape_tag):
3345 try:
3346 option,value = line[len(self._MG5aMC_escape_tag):].split('=')
3347 value = value.strip()
3348 except ValueError:
3349 option = line[len(self._MG5aMC_escape_tag):]
3350 option = option.strip()
3351
3352 if option=='inputs':
3353 self['inputs'].extend([v.strip() for v in value.split(',')])
3354
3355 elif option == 'skip_analysis':
3356 self._skip_analysis = True
3357
3358 elif option=='stdout_lvl':
3359 try:
3360 self['stdout_lvl']=int(value)
3361 except ValueError:
3362 try:
3363 self['stdout_lvl']=eval(value)
3364 except:
3365 try:
3366 self['stdout_lvl']=eval('logging.%s'%value)
3367 except:
3368 raise InvalidMadAnalysis5Card(
3369 "MA5 output level specification '%s' is incorrect."%str(value))
3370
3371 elif option=='analysis_name':
3372 current_type = 'analyses'
3373 current_name = value
3374 if current_name in self[current_type]:
3375 raise InvalidMadAnalysis5Card(
3376 "Analysis '%s' already defined in MadAnalysis5 card"%current_name)
3377 else:
3378 self[current_type][current_name] = MadAnalysis5Card.empty_analysis()
3379
3380 elif option=='set_reconstructions':
3381 try:
3382 reconstructions = eval(value)
3383 if not isinstance(reconstructions, list):
3384 raise
3385 except:
3386 raise InvalidMadAnalysis5Card("List of reconstructions"+\
3387 " '%s' could not be parsed in MadAnalysis5 card."%value)
3388 if current_type!='analyses' and current_name not in self[current_type]:
3389 raise InvalidMadAnalysis5Card("A list of reconstructions"+\
3390 "can only be defined in the context of an "+\
3391 "analysis in a MadAnalysis5 card.")
3392 self[current_type][current_name]['reconstructions']=reconstructions
3393 continue
3394
3395 elif option=='reconstruction_name':
3396 current_type = 'reconstruction'
3397 current_name = value
3398 if current_name in self[current_type]:
3399 raise InvalidMadAnalysis5Card(
3400 "Reconstruction '%s' already defined in MadAnalysis5 hadron card"%current_name)
3401 else:
3402 self[current_type][current_name] = MadAnalysis5Card.empty_reconstruction()
3403
3404 elif option=='reco_output':
3405 if current_type!='reconstruction' or current_name not in \
3406 self['reconstruction']:
3407 raise InvalidMadAnalysis5Card(
3408 "Option '%s' is only available within the definition of a reconstruction"%option)
3409 if not value.lower() in ['lhe','root']:
3410 raise InvalidMadAnalysis5Card(
3411 "Option '%s' can only take the values 'lhe' or 'root'"%option)
3412 self['reconstruction'][current_name]['reco_output'] = value.lower()
3413
3414 elif option.startswith('recasting'):
3415 current_type = 'recasting'
3416 try:
3417 current_name = option.split('_')[1]
3418 except:
3419 raise InvalidMadAnalysis5Card('Malformed MA5 recasting option %s.'%option)
3420 if len(self['recasting'][current_name])>0:
3421 raise InvalidMadAnalysis5Card(
3422 "Only one recasting can be defined in MadAnalysis5 hadron card")
3423
3424 else:
3425 raise InvalidMadAnalysis5Card(
3426 "Unreckognized MG5aMC instruction in MadAnalysis5 card: '%s'"%option)
3427
3428 if option in ['analysis_name','reconstruction_name'] or \
3429 option.startswith('recasting'):
3430 self['order'].append((current_type,current_name))
3431 continue
3432
3433
3434
3435 if current_name == 'default' and current_type == 'analyses' and\
3436 'default' not in self['analyses']:
3437 self['analyses']['default'] = MadAnalysis5Card.empty_analysis()
3438 self['order'].append(('analyses','default'))
3439
3440 if current_type in ['recasting']:
3441 self[current_type][current_name].append(line)
3442 elif current_type in ['reconstruction']:
3443 self[current_type][current_name]['commands'].append(line)
3444 elif current_type in ['analyses']:
3445 self[current_type][current_name]['commands'].append(line)
3446
3447 if 'reconstruction' in self['analyses'] or len(self['recasting']['card'])>0:
3448 if mode=='parton':
3449 raise InvalidMadAnalysis5Card(
3450 "A parton MadAnalysis5 card cannot specify a recombination or recasting.")
3451 card_mode = 'hadron'
3452 elif mode is None:
3453 card_mode = 'parton'
3454
3455 self['mode'] = card_mode
3456 if self['inputs'] == []:
3457 if self['mode']=='hadron':
3458 self['inputs'] = self._default_hadron_inputs
3459 else:
3460 self['inputs'] = self._default_parton_inputs
3461
3462
3463
3464 if self['mode']=='hadron':
3465 for analysis_name, analysis in self['analyses'].items():
3466 if len(analysis['reconstructions'])==0:
3467 raise InvalidMadAnalysis5Card('Hadron-level analysis '+\
3468 "'%s' is not specified any reconstruction(s)."%analysis_name)
3469 if any(reco not in self['reconstruction'] for reco in \
3470 analysis['reconstructions']):
3471 raise InvalidMadAnalysis5Card('A reconstructions specified in'+\
3472 " analysis '%s' is not defined."%analysis_name)
3473
3474 - def write(self, output):
3475 """ Write an MA5 card."""
3476
3477 if isinstance(output, (file, StringIO.StringIO)):
3478 output_stream = output
3479 elif isinstance(output, str):
3480 output_stream = open(output,'w')
3481 else:
3482 raise MadGraph5Error('Incorrect input for the write function of'+\
3483 ' the MadAnalysis5Card card. Received argument type is: %s'%str(type(output)))
3484
3485 output_lines = []
3486 if self._skip_analysis:
3487 output_lines.append('%s skip_analysis'%self._MG5aMC_escape_tag)
3488 output_lines.append('%s inputs = %s'%(self._MG5aMC_escape_tag,','.join(self['inputs'])))
3489 if not self['stdout_lvl'] is None:
3490 output_lines.append('%s stdout_lvl=%s'%(self._MG5aMC_escape_tag,self['stdout_lvl']))
3491 for definition_type, name in self['order']:
3492
3493 if definition_type=='analyses':
3494 output_lines.append('%s analysis_name = %s'%(self._MG5aMC_escape_tag,name))
3495 output_lines.append('%s set_reconstructions = %s'%(self._MG5aMC_escape_tag,
3496 str(self['analyses'][name]['reconstructions'])))
3497 elif definition_type=='reconstruction':
3498 output_lines.append('%s reconstruction_name = %s'%(self._MG5aMC_escape_tag,name))
3499 elif definition_type=='recasting':
3500 output_lines.append('%s recasting_%s'%(self._MG5aMC_escape_tag,name))
3501
3502 if definition_type in ['recasting']:
3503 output_lines.extend(self[definition_type][name])
3504 elif definition_type in ['reconstruction']:
3505 output_lines.append('%s reco_output = %s'%(self._MG5aMC_escape_tag,
3506 self[definition_type][name]['reco_output']))
3507 output_lines.extend(self[definition_type][name]['commands'])
3508 elif definition_type in ['analyses']:
3509 output_lines.extend(self[definition_type][name]['commands'])
3510
3511 output_stream.write('\n'.join(output_lines))
3512
3513 return
3514
3515 - def get_MA5_cmds(self, inputs_arg, submit_folder, run_dir_path=None,
3516 UFO_model_path=None, run_tag=''):
3517 """ Returns a list of tuples ('AnalysisTag',['commands']) specifying
3518 the commands of the MadAnalysis runs required from this card.
3519 At parton-level, the number of such commands is the number of analysis
3520 asked for. In the future, the idea is that the entire card can be
3521 processed in one go from MA5 directly."""
3522
3523 if isinstance(inputs_arg, list):
3524 inputs = inputs_arg
3525 elif isinstance(inputs_arg, str):
3526 inputs = [inputs_arg]
3527 else:
3528 raise MadGraph5Error("The function 'get_MA5_cmds' can only take "+\
3529 " a string or a list for the argument 'inputs_arg'")
3530
3531 if len(inputs)==0:
3532 raise MadGraph5Error("The function 'get_MA5_cmds' must have "+\
3533 " at least one input specified'")
3534
3535 if run_dir_path is None:
3536 run_dir_path = os.path.dirname(inputs_arg)
3537
3538 cmds_list = []
3539
3540 UFO_load = []
3541
3542 if UFO_model_path:
3543 UFO_load.append('import %s'%UFO_model_path)
3544
3545 def get_import(input, type=None):
3546 """ Generates the MA5 import commands for that event file. """
3547 dataset_name = os.path.basename(input).split('.')[0]
3548 res = ['import %s as %s'%(input, dataset_name)]
3549 if not type is None:
3550 res.append('set %s.type = %s'%(dataset_name, type))
3551 return res
3552
3553 fifo_status = {'warned_fifo':False,'fifo_used_up':False}
3554 def warn_fifo(input):
3555 if not input.endswith('.fifo'):
3556 return False
3557 if not fifo_status['fifo_used_up']:
3558 fifo_status['fifo_used_up'] = True
3559 return False
3560 else:
3561 if not fifo_status['warned_fifo']:
3562 logger.warning('Only the first MA5 analysis/reconstructions can be run on a fifo. Subsequent runs will skip fifo inputs.')
3563 fifo_status['warned_fifo'] = True
3564 return True
3565
3566
3567 inputs_load = []
3568 for input in inputs:
3569 inputs_load.extend(get_import(input))
3570
3571 submit_command = 'submit %s'%submit_folder+'_%s'
3572
3573
3574
3575
3576 reconstruction_outputs = {
3577 'lhco_input':[f for f in inputs if
3578 f.endswith('.lhco') or f.endswith('.lhco.gz')],
3579 'root_input':[f for f in inputs if
3580 f.endswith('.root') or f.endswith('.root.gz')]}
3581
3582
3583 recasting_card_path = pjoin(run_dir_path,
3584 '_'.join([run_tag,os.path.basename(submit_folder),'recasting_card.dat']))
3585
3586
3587 for definition_type, name in self['order']:
3588 if definition_type == 'reconstruction':
3589 analysis_cmds = list(self['reconstruction'][name]['commands'])
3590 reco_outputs = []
3591 for i_input, input in enumerate(inputs):
3592
3593 if not MadAnalysis5Card.events_can_be_reconstructed(input):
3594 continue
3595
3596 if warn_fifo(input):
3597 continue
3598 analysis_cmds.append('import %s as reco_events'%input)
3599 if self['reconstruction'][name]['reco_output']=='lhe':
3600 reco_outputs.append('%s_%s.lhe.gz'%(os.path.basename(
3601 input).replace('_events','').split('.')[0],name))
3602 analysis_cmds.append('set main.outputfile=%s'%reco_outputs[-1])
3603 elif self['reconstruction'][name]['reco_output']=='root':
3604 reco_outputs.append('%s_%s.root'%(os.path.basename(
3605 input).replace('_events','').split('.')[0],name))
3606 analysis_cmds.append('set main.fastsim.rootfile=%s'%reco_outputs[-1])
3607 analysis_cmds.append(
3608 submit_command%('reco_%s_%d'%(name,i_input+1)))
3609 analysis_cmds.append('remove reco_events')
3610
3611 reconstruction_outputs[name]= [pjoin(run_dir_path,rec_out)
3612 for rec_out in reco_outputs]
3613 if len(reco_outputs)>0:
3614 cmds_list.append(('_reco_%s'%name,analysis_cmds))
3615
3616 elif definition_type == 'analyses':
3617 if self['mode']=='parton':
3618 cmds_list.append( (name, UFO_load+inputs_load+
3619 self['analyses'][name]['commands']+[submit_command%name]) )
3620 elif self['mode']=='hadron':
3621
3622 for reco in self['analyses'][name]['reconstructions']+\
3623 ['lhco_input','root_input']:
3624 if len(reconstruction_outputs[reco])==0:
3625 continue
3626 if self['reconstruction'][reco]['reco_output']=='lhe':
3627
3628 analysis_cmds = ['set main.mode = parton']
3629 else:
3630 analysis_cmds = []
3631 analysis_cmds.extend(sum([get_import(rec_out) for
3632 rec_out in reconstruction_outputs[reco]],[]))
3633 analysis_cmds.extend(self['analyses'][name]['commands'])
3634 analysis_cmds.append(submit_command%('%s_%s'%(name,reco)))
3635 cmds_list.append( ('%s_%s'%(name,reco),analysis_cmds) )
3636
3637 elif definition_type == 'recasting':
3638 if len(self['recasting']['card'])==0:
3639 continue
3640 if name == 'card':
3641
3642 open(recasting_card_path,'w').write('\n'.join(self['recasting']['card']))
3643 if name == 'commands':
3644 recasting_cmds = list(self['recasting']['commands'])
3645
3646 n_inputs = 0
3647 for input in inputs:
3648 if not MadAnalysis5Card.events_can_be_reconstructed(input):
3649 continue
3650
3651 if warn_fifo(input):
3652 continue
3653 recasting_cmds.extend(get_import(input,'signal'))
3654 n_inputs += 1
3655
3656 recasting_cmds.append('set main.recast.card_path=%s'%recasting_card_path)
3657 recasting_cmds.append(submit_command%'Recasting')
3658 if n_inputs>0:
3659 cmds_list.append( ('Recasting',recasting_cmds))
3660
3661 return cmds_list
3662
3664 """A class object for the run_card for a (aMC@)NLO pocess"""
3665
3667 """define the default value"""
3668
3669 self.add_param('run_tag', 'tag_1', include=False)
3670 self.add_param('nevents', 10000)
3671 self.add_param('req_acc', -1.0, include=False)
3672 self.add_param('nevt_job', -1, include=False)
3673 self.add_param('event_norm', 'average')
3674
3675 self.add_param('req_acc_fo', 0.01, include=False)
3676 self.add_param('npoints_fo_grid', 5000, include=False)
3677 self.add_param('niters_fo_grid', 4, include=False)
3678 self.add_param('npoints_fo', 10000, include=False)
3679 self.add_param('niters_fo', 6, include=False)
3680
3681 self.add_param('iseed', 0)
3682 self.add_param('lpp1', 1, fortran_name='lpp(1)')
3683 self.add_param('lpp2', 1, fortran_name='lpp(2)')
3684 self.add_param('ebeam1', 6500.0, fortran_name='ebeam(1)')
3685 self.add_param('ebeam2', 6500.0, fortran_name='ebeam(2)')
3686 self.add_param('pdlabel', 'nn23nlo', allowed=['lhapdf', 'cteq6_m','cteq6_d','cteq6_l','cteq6l1', 'nn23lo','nn23lo1','nn23nlo'])
3687 self.add_param('lhaid', [244600],fortran_name='lhaPDFid')
3688 self.add_param('lhapdfsetname', ['internal_use_only'], system=True)
3689
3690 self.add_param('parton_shower', 'HERWIG6', fortran_name='shower_mc')
3691 self.add_param('shower_scale_factor',1.0)
3692 self.add_param('fixed_ren_scale', False)
3693 self.add_param('fixed_fac_scale', False)
3694 self.add_param('mur_ref_fixed', 91.118)
3695 self.add_param('muf1_ref_fixed', -1.0, hidden=True)
3696 self.add_param('muf_ref_fixed', 91.118)
3697 self.add_param('muf2_ref_fixed', -1.0, hidden=True)
3698 self.add_param("dynamical_scale_choice", [-1],fortran_name='dyn_scale', comment="\'-1\' is based on CKKW back clustering (following feynman diagram).\n \'1\' is the sum of transverse energy.\n '2' is HT (sum of the transverse mass)\n '3' is HT/2")
3699 self.add_param('fixed_qes_scale', False, hidden=True)
3700 self.add_param('qes_ref_fixed', -1.0, hidden=True)
3701 self.add_param('mur_over_ref', 1.0)
3702 self.add_param('muf_over_ref', 1.0)
3703 self.add_param('muf1_over_ref', -1.0, hidden=True)
3704 self.add_param('muf2_over_ref', -1.0, hidden=True)
3705 self.add_param('qes_over_ref', -1.0, hidden=True)
3706 self.add_param('reweight_scale', [True], fortran_name='lscalevar')
3707 self.add_param('rw_rscale_down', -1.0, hidden=True)
3708 self.add_param('rw_rscale_up', -1.0, hidden=True)
3709 self.add_param('rw_fscale_down', -1.0, hidden=True)
3710 self.add_param('rw_fscale_up', -1.0, hidden=True)
3711 self.add_param('rw_rscale', [1.0,2.0,0.5], fortran_name='scalevarR')
3712 self.add_param('rw_fscale', [1.0,2.0,0.5], fortran_name='scalevarF')
3713 self.add_param('reweight_pdf', [False], fortran_name='lpdfvar')
3714 self.add_param('pdf_set_min', 244601, hidden=True)
3715 self.add_param('pdf_set_max', 244700, hidden=True)
3716 self.add_param('store_rwgt_info', False)
3717 self.add_param('systematics_program', 'none', include=False, hidden=True, comment='Choose which program to use for systematics computation: none, systematics')
3718 self.add_param('systematics_arguments', [''], include=False, hidden=True, comment='Choose the argment to pass to the systematics command. like --mur=0.25,1,4. Look at the help of the systematics function for more details.')
3719
3720
3721 self.add_param('ickkw', 0)
3722 self.add_param('bwcutoff', 15.0)
3723
3724 self.add_param('jetalgo', 1.0)
3725 self.add_param('jetradius', 0.7)
3726 self.add_param('ptj', 10.0 , cut=True)
3727 self.add_param('etaj', -1.0, cut=True)
3728 self.add_param('ptl', 0.0, cut=True)
3729 self.add_param('etal', -1.0, cut=True)
3730 self.add_param('drll', 0.0, cut=True)
3731 self.add_param('drll_sf', 0.0, cut=True)
3732 self.add_param('mll', 0.0, cut=True)
3733 self.add_param('mll_sf', 30.0, cut=True)
3734 self.add_param('ptgmin', 20.0, cut=True)
3735 self.add_param('etagamma', -1.0)
3736 self.add_param('r0gamma', 0.4)
3737 self.add_param('xn', 1.0)
3738 self.add_param('epsgamma', 1.0)
3739 self.add_param('isoem', True)
3740 self.add_param('maxjetflavor', 4, hidden=True)
3741 self.add_param('iappl', 0)
3742 self.add_param('lhe_version', 3, hidden=True, include=False)
3743
3744
3745 self.add_param('FO_LHE_weight_ratio',1e-3, hidden=True, system=True)
3746 self.add_param('FO_LHE_postprocessing',['grouping','random'],
3747 hidden=True, system=True, include=False)
3748
3749
3750 self.add_param('pt_min_pdg',{'__type__':0.}, include=False)
3751 self.add_param('pt_max_pdg',{'__type__':0.}, include=False)
3752 self.add_param('mxx_min_pdg',{'__type__':0.}, include=False)
3753 self.add_param('mxx_only_part_antipart', {'default':False}, include=False, hidden=True)
3754
3755
3756 self.add_param('pdg_cut',[0], hidden=True, system=True)
3757 self.add_param('ptmin4pdg',[0.], hidden=True, system=True)
3758 self.add_param('ptmax4pdg',[-1.], hidden=True, system=True)
3759 self.add_param('mxxmin4pdg',[0.], hidden=True, system=True)
3760 self.add_param('mxxpart_antipart', [False], hidden=True, system=True)
3761
3763 """check the validity of the various input"""
3764
3765 super(RunCardNLO, self).check_validity()
3766
3767
3768 if self['lpp1']==0 and self['lpp2']==0:
3769 if self['pdlabel']!='nn23nlo' or self['reweight_pdf']:
3770 self['pdlabel']='nn23nlo'
3771 self['reweight_pdf']=[False]
3772 logger.info('''Lepton-lepton collisions: ignoring PDF related parameters in the run_card.dat (pdlabel, lhaid, reweight_pdf, ...)''')
3773
3774
3775 if self['ickkw'] == 3:
3776
3777 scales=['fixed_ren_scale','fixed_fac_scale','fixed_QES_scale']
3778 for scale in scales:
3779 if self[scale]:
3780 logger.warning('''For consistency in the FxFx merging, \'%s\' has been set to false'''
3781 % scale,'$MG:BOLD')
3782 self[scale]= False
3783
3784 if len(self["dynamical_scale_choice"]) > 1 or self["dynamical_scale_choice"][0] != -1:
3785 self["dynamical_scale_choice"] = [-1]
3786 self["reweight_scale"]=[self["reweight_scale"][0]]
3787 logger.warning('''For consistency in the FxFx merging, dynamical_scale_choice has been set to -1 (default)'''
3788 ,'$MG:BOLD')
3789
3790
3791 jetparams=['jetradius','jetalgo']
3792 for jetparam in jetparams:
3793 if float(self[jetparam]) != 1.0:
3794 logger.info('''For consistency in the FxFx merging, \'%s\' has been set to 1.0'''
3795 % jetparam ,'$MG:BOLD')
3796 self[jetparam] = 1.0
3797 elif self['ickkw'] == -1 and (self["dynamical_scale_choice"][0] != -1 or
3798 len(self["dynamical_scale_choice"]) > 1):
3799 self["dynamical_scale_choice"] = [-1]
3800 self["reweight_scale"]=[self["reweight_scale"][0]]
3801 logger.warning('''For consistency with the jet veto, the scale which will be used is ptj. dynamical_scale_choice will be set at -1.'''
3802 ,'$MG:BOLD')
3803
3804
3805 if self['iappl'] != 0 and self['pdlabel'].lower() != 'lhapdf':
3806 raise InvalidRunCard('APPLgrid generation only possible with the use of LHAPDF')
3807 if self['iappl'] != 0 and not self['reweight_scale']:
3808 raise InvalidRunCard('APPLgrid generation only possible with including' +\
3809 ' the reweighting to get scale dependence')
3810
3811
3812 if self['qes_ref_fixed'] == -1.0:
3813 self['qes_ref_fixed']=self['mur_ref_fixed']
3814 if self['qes_over_ref'] == -1.0:
3815 self['qes_over_ref']=self['mur_over_ref']
3816 if self['muf1_over_ref'] != -1.0 and self['muf1_over_ref'] == self['muf2_over_ref']:
3817 self['muf_over_ref']=self['muf1_over_ref']
3818 if self['muf1_over_ref'] == -1.0:
3819 self['muf1_over_ref']=self['muf_over_ref']
3820 if self['muf2_over_ref'] == -1.0:
3821 self['muf2_over_ref']=self['muf_over_ref']
3822 if self['muf1_ref_fixed'] != -1.0 and self['muf1_ref_fixed'] == self['muf2_ref_fixed']:
3823 self['muf_ref_fixed']=self['muf1_ref_fixed']
3824 if self['muf1_ref_fixed'] == -1.0:
3825 self['muf1_ref_fixed']=self['muf_ref_fixed']
3826 if self['muf2_ref_fixed'] == -1.0:
3827 self['muf2_ref_fixed']=self['muf_ref_fixed']
3828
3829 if (self['rw_rscale_down'] != -1.0 and ['rw_rscale_down'] not in self['rw_rscale']) or\
3830 (self['rw_rscale_up'] != -1.0 and ['rw_rscale_up'] not in self['rw_rscale']):
3831 self['rw_rscale']=[1.0,self['rw_rscale_up'],self['rw_rscale_down']]
3832 if (self['rw_fscale_down'] != -1.0 and ['rw_fscale_down'] not in self['rw_fscale']) or\
3833 (self['rw_fscale_up'] != -1.0 and ['rw_fscale_up'] not in self['rw_fscale']):
3834 self['rw_fscale']=[1.0,self['rw_fscale_up'],self['rw_fscale_down']]
3835
3836
3837 if any(self['reweight_pdf']):
3838
3839 if self['pdlabel'] != "lhapdf":
3840 raise InvalidRunCard, 'Reweight PDF option requires to use pdf sets associated to lhapdf. Please either change the pdlabel to use LHAPDF or set reweight_pdf to False.'
3841
3842
3843 if self['pdlabel'] != "lhapdf":
3844 self['reweight_pdf']=[self['reweight_pdf'][0]]
3845 self['lhaid']=[self['lhaid'][0]]
3846
3847
3848 if self['fixed_ren_scale'] and self['fixed_fac_scale']:
3849 self['reweight_scale']=[self['reweight_scale'][0]]
3850 self['dynamical_scale_choice']=[0]
3851
3852
3853
3854
3855 if len(self['reweight_pdf']) == 1 and len(self['lhaid']) != 1:
3856 self['reweight_pdf']=self['reweight_pdf']*len(self['lhaid'])
3857 logger.warning("Setting 'reweight_pdf' for all 'lhaid' to %s" % self['reweight_pdf'][0])
3858 if len(self['reweight_scale']) == 1 and len(self['dynamical_scale_choice']) != 1:
3859 self['reweight_scale']=self['reweight_scale']*len(self['dynamical_scale_choice'])
3860 logger.warning("Setting 'reweight_scale' for all 'dynamical_scale_choice' to %s" % self['reweight_pdf'][0])
3861
3862
3863 if len(self['lhaid']) != len(set(self['lhaid'])):
3864 raise InvalidRunCard, "'lhaid' has two or more identical entries. They have to be all different for the code to work correctly."
3865 if len(self['dynamical_scale_choice']) != len(set(self['dynamical_scale_choice'])):
3866 raise InvalidRunCard, "'dynamical_scale_choice' has two or more identical entries. They have to be all different for the code to work correctly."
3867
3868
3869 if len(self['reweight_pdf']) != len(self['lhaid']):
3870 raise InvalidRunCard, "'reweight_pdf' and 'lhaid' lists should have the same length"
3871 if len(self['reweight_scale']) != len(self['dynamical_scale_choice']):
3872 raise InvalidRunCard, "'reweight_scale' and 'dynamical_scale_choice' lists should have the same length"
3873 if len(self['dynamical_scale_choice']) > 10 :
3874 raise InvalidRunCard, "Length of list for 'dynamical_scale_choice' too long: max is 10."
3875 if len(self['lhaid']) > 25 :
3876 raise InvalidRunCard, "Length of list for 'lhaid' too long: max is 25."
3877 if len(self['rw_rscale']) > 9 :
3878 raise InvalidRunCard, "Length of list for 'rw_rscale' too long: max is 9."
3879 if len(self['rw_fscale']) > 9 :
3880 raise InvalidRunCard, "Length of list for 'rw_fscale' too long: max is 9."
3881
3882 if 1.0 not in self['rw_rscale']:
3883 logger.warning("'1.0' has to be part of 'rw_rscale', adding it")
3884 self['rw_rscale'].insert(0,1.0)
3885 if 1.0 not in self['rw_fscale']:
3886 logger.warning("'1.0' has to be part of 'rw_fscale', adding it")
3887 self['rw_fscale'].insert(0,1.0)
3888 if self['rw_rscale'][0] != 1.0 and 1.0 in self['rw_rscale']:
3889 a=self['rw_rscale'].index(1.0)
3890 self['rw_rscale'][0],self['rw_rscale'][a]=self['rw_rscale'][a],self['rw_rscale'][0]
3891 if self['rw_fscale'][0] != 1.0 and 1.0 in self['rw_fscale']:
3892 a=self['rw_fscale'].index(1.0)
3893 self['rw_fscale'][0],self['rw_fscale'][a]=self['rw_fscale'][a],self['rw_fscale'][0]
3894
3895 if len(self['rw_rscale']) != len(set(self['rw_rscale'])):
3896 raise InvalidRunCard, "'rw_rscale' has two or more identical entries. They have to be all different for the code to work correctly."
3897 if len(self['rw_fscale']) != len(set(self['rw_fscale'])):
3898 raise InvalidRunCard, "'rw_fscale' has two or more identical entries. They have to be all different for the code to work correctly."
3899
3900
3902
3903
3904 pdg_to_cut = set(self['pt_min_pdg'].keys() +self['pt_max_pdg'].keys()+
3905 self['mxx_min_pdg'].keys()+ self['mxx_only_part_antipart'].keys())
3906 pdg_to_cut.discard('__type__')
3907 pdg_to_cut.discard('default')
3908 if len(pdg_to_cut)>25:
3909 raise Exception, "Maximum 25 different PDGs are allowed for PDG specific cut"
3910
3911 if any(int(pdg)<0 for pdg in pdg_to_cut):
3912 logger.warning('PDG specific cuts are always applied symmetrically on particle/anti-particle. Always use positve PDG codes')
3913 raise MadGraph5Error, 'Some PDG specific cuts are defined with negative PDG codes'
3914
3915
3916 if any(pdg in pdg_to_cut for pdg in [21,22,11,13,15]+ range(self['maxjetflavor']+1)):
3917
3918 raise Exception, "Can not use PDG related cuts for massless SM particles/leptons"
3919 if pdg_to_cut:
3920 self['pdg_cut'] = list(pdg_to_cut)
3921 self['ptmin4pdg'] = []
3922 self['ptmax4pdg'] = []
3923 self['mxxmin4pdg'] = []
3924 self['mxxpart_antipart'] = []
3925 for pdg in self['pdg_cut']:
3926 for var in ['pt','mxx']:
3927 for minmax in ['min', 'max']:
3928 if var == 'mxx' and minmax == 'max':
3929 continue
3930 new_var = '%s%s4pdg' % (var, minmax)
3931 old_var = '%s_%s_pdg' % (var, minmax)
3932 default = 0. if minmax=='min' else -1.
3933 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3934
3935 old_var = 'mxx_only_part_antipart'
3936 new_var = 'mxxpart_antipart'
3937 if 'default' in self[old_var]:
3938 default = self[old_var]['default']
3939 self[new_var].append(self[old_var][str(pdg)] if str(pdg) in self[old_var] else default)
3940 else:
3941 if str(pdg) not in self[old_var]:
3942 raise Exception("no default value defined for %s and no value defined for pdg %s" % (old_var, pdg))
3943 self[new_var].append(self[old_var][str(pdg)])
3944 else:
3945 self['pdg_cut'] = [0]
3946 self['ptmin4pdg'] = [0.]
3947 self['ptmax4pdg'] = [-1.]
3948 self['mxxmin4pdg'] = [0.]
3949 self['mxxpart_antipart'] = [False]
3950
3951 - def write(self, output_file, template=None, python_template=False, **opt):
3952 """Write the run_card in output_file according to template
3953 (a path to a valid run_card)"""
3954
3955 if not template:
3956 if not MADEVENT:
3957 template = pjoin(MG5DIR, 'Template', 'NLO', 'Cards',
3958 'run_card.dat')
3959 python_template = True
3960 else:
3961 template = pjoin(MEDIR, 'Cards', 'run_card_default.dat')
3962 python_template = False
3963
3964 super(RunCardNLO, self).write(output_file, template=template,
3965 python_template=python_template, **opt)
3966
3967
3969 """Rules
3970 e+ e- beam -> lpp:0 ebeam:500
3971 p p beam -> set maxjetflavor automatically
3972 """
3973
3974
3975 beam_id = set()
3976 for proc in proc_def:
3977 for leg in proc['legs']:
3978 if not leg['state']:
3979 beam_id.add(leg['id'])
3980 if any(i in beam_id for i in [1,-1,2,-2,3,-3,4,-4,5,-5,21,22]):
3981 maxjetflavor = max([4]+[abs(i) for i in beam_id if -7< i < 7])
3982 self['maxjetflavor'] = maxjetflavor
3983 pass
3984 elif 11 in beam_id or -11 in beam_id:
3985 self['lpp1'] = 0
3986 self['lpp2'] = 0
3987 self['ebeam1'] = 500
3988 self['ebeam2'] = 500
3989 else:
3990 self['lpp1'] = 0
3991 self['lpp2'] = 0
3992
3993 if proc_characteristic['ninitial'] == 1:
3994
3995 self.remove_all_cut()
3996
4000 """ a class for storing/dealing with the file MadLoopParam.dat
4001 contains a parser to read it, facilities to write a new file,...
4002 """
4003
4004 _ID_reduction_tool_map = {1:'CutTools',
4005 2:'PJFry++',
4006 3:'IREGI',
4007 4:'Golem95',
4008 5:'Samurai',
4009 6:'Ninja',
4010 7:'COLLIER'}
4011
4013 """initialize the directory to the default value"""
4014
4015 self.add_param("MLReductionLib", "6|7|1")
4016 self.add_param("IREGIMODE", 2)
4017 self.add_param("IREGIRECY", True)
4018 self.add_param("CTModeRun", -1)
4019 self.add_param("MLStabThres", 1e-3)
4020 self.add_param("NRotations_DP", 0)
4021 self.add_param("NRotations_QP", 0)
4022 self.add_param("ImprovePSPoint", 2)
4023 self.add_param("CTLoopLibrary", 2)
4024 self.add_param("CTStabThres", 1e-2)
4025 self.add_param("CTModeInit", 1)
4026 self.add_param("CheckCycle", 3)
4027 self.add_param("MaxAttempts", 10)
4028 self.add_param("ZeroThres", 1e-9)
4029 self.add_param("OSThres", 1.0e-8)
4030 self.add_param("DoubleCheckHelicityFilter", True)
4031 self.add_param("WriteOutFilters", True)
4032 self.add_param("UseLoopFilter", False)
4033 self.add_param("HelicityFilterLevel", 2)
4034 self.add_param("LoopInitStartOver", False)
4035 self.add_param("HelInitStartOver", False)
4036 self.add_param("UseQPIntegrandForNinja", True)
4037 self.add_param("UseQPIntegrandForCutTools", True)
4038 self.add_param("COLLIERMode", 1)
4039 self.add_param("COLLIERComputeUVpoles", True)
4040 self.add_param("COLLIERComputeIRpoles", True)
4041 self.add_param("COLLIERRequiredAccuracy", 1.0e-8)
4042 self.add_param("COLLIERCanOutput",False)
4043 self.add_param("COLLIERGlobalCache",-1)
4044 self.add_param("COLLIERUseCacheForPoles",False)
4045 self.add_param("COLLIERUseInternalStabilityTest",True)
4046
4047 - def read(self, finput):
4048 """Read the input file, this can be a path to a file,
4049 a file object, a str with the content of the file."""
4050
4051 if isinstance(finput, str):
4052 if "\n" in finput:
4053 finput = finput.split('\n')
4054 elif os.path.isfile(finput):
4055 finput = open(finput)
4056 else:
4057 raise Exception, "No such file %s" % input
4058
4059 previous_line= ''
4060 for line in finput:
4061 if previous_line.startswith('#'):
4062 name = previous_line[1:].split()[0]
4063 value = line.strip()
4064 if len(value) and value[0] not in ['#', '!']:
4065 self.__setitem__(name, value, change_userdefine=True)
4066 previous_line = line
4067
4068
4069 - def write(self, outputpath, template=None,commentdefault=False):
4070
4071 if not template:
4072 if not MADEVENT:
4073 template = pjoin(MG5DIR, 'Template', 'loop_material', 'StandAlone',
4074 'Cards', 'MadLoopParams.dat')
4075 else:
4076 template = pjoin(MEDIR, 'Cards', 'MadLoopParams_default.dat')
4077 fsock = open(template, 'r')
4078 template = fsock.readlines()
4079 fsock.close()
4080
4081 if isinstance(outputpath, str):
4082 output = open(outputpath, 'w')
4083 else:
4084 output = outputpath
4085
4086 def f77format(value):
4087 if isinstance(value, bool):
4088 if value:
4089 return '.true.'
4090 else:
4091 return '.false.'
4092 elif isinstance(value, int):
4093 return value
4094 elif isinstance(value, float):
4095 tmp ='%e' % value
4096 return tmp.replace('e','d')
4097 elif isinstance(value, str):
4098 return value
4099 else:
4100 raise Exception, "Can not format input %s" % type(value)
4101
4102 name = ''
4103 done = set()
4104 for line in template:
4105 if name:
4106 done.add(name)
4107 if commentdefault and name.lower() not in self.user_set :
4108 output.write('!%s\n' % f77format(self[name]))
4109 else:
4110 output.write('%s\n' % f77format(self[name]))
4111 name=''
4112 continue
4113 elif line.startswith('#'):
4114 name = line[1:].split()[0]
4115 output.write(line)
4116