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