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