1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """ Command interface for MadSpin """
16 from __future__ import division
17 import difflib
18 import logging
19 import math
20 import os
21 import re
22 import shutil
23 import sys
24 import tempfile
25 import time
26 import subprocess
27 from subprocess import Popen, PIPE, STDOUT
28
29
30 pjoin = os.path.join
31
32 import madgraph.interface.extended_cmd as extended_cmd
33 import madgraph.interface.madgraph_interface as mg_interface
34 import madgraph.interface.master_interface as master_interface
35 import madgraph.interface.common_run_interface as common_run_interface
36 import madgraph.iolibs.files as files
37 import MadSpin.interface_madspin as madspin_interface
38 import madgraph.various.misc as misc
39 import madgraph.various.banner as banner
40 import madgraph.various.lhe_parser as lhe_parser
41 import madgraph.various.combine_plots as combine_plots
42 import madgraph.various.cluster as cluster
43 import madgraph.fks.fks_common as fks_common
44
45 import models.import_ufo as import_ufo
46 import models.check_param_card as check_param_card
47 import MadSpin.decay as madspin
48
49
50 logger = logging.getLogger('decay.stdout')
51 logger_stderr = logging.getLogger('decay.stderr')
52 cmd_logger = logging.getLogger('cmdprint2')
53
54
55 dir_to_f2py_free_mod = {}
56 nb_f2py_module = 0
63 """Basic interface for reweighting operation"""
64
65 prompt = 'Reweight>'
66 debug_output = 'Reweight_debug'
67
68 @misc.mute_logger()
69 - def __init__(self, event_path=None, allow_madspin=False, *completekey, **stdin):
70 """initialize the interface with potentially an event_path"""
71
72 if not event_path:
73 cmd_logger.info('************************************************************')
74 cmd_logger.info('* *')
75 cmd_logger.info('* Welcome to Reweight Module *')
76 cmd_logger.info('* *')
77 cmd_logger.info('************************************************************')
78 extended_cmd.Cmd.__init__(self, *completekey, **stdin)
79
80 self.model = None
81 self.has_standalone_dir = False
82
83 self.options = {'curr_dir': os.path.realpath(os.getcwd())}
84
85 self.events_file = None
86 self.processes = {}
87 self.second_model = None
88 self.second_process = None
89 self.mg5cmd = master_interface.MasterCmd()
90 self.seed = None
91 self.output_type = "default"
92 self.helicity_reweighting = True
93 self.rwgt_dir = None
94
95 if event_path:
96 logger.info("Extracting the banner ...")
97 self.do_import(event_path, allow_madspin=allow_madspin)
98
99
100 self.calculator = {}
101 self.calculator_nbcall = {}
102
103
104 self.all_cross_section = {}
105
106 - def do_import(self, inputfile, allow_madspin=False):
107 """import the event file"""
108
109 args = self.split_arg(inputfile)
110 if not args:
111 return self.InvalidCmd, 'import requires arguments'
112
113
114 self.options['curr_dir'] = os.path.realpath(os.path.dirname(inputfile))
115 if os.path.basename(os.path.dirname(os.path.dirname(inputfile))) == 'Events':
116 self.options['curr_dir'] = pjoin(self.options['curr_dir'],
117 os.path.pardir, os.pardir)
118
119
120 if not os.path.exists(inputfile):
121 if inputfile.endswith('.gz'):
122 if not os.path.exists(inputfile[:-3]):
123 raise self.InvalidCmd('No such file or directory : %s' % inputfile)
124 else:
125 inputfile = inputfile[:-3]
126 elif os.path.exists(inputfile + '.gz'):
127 inputfile = inputfile + '.gz'
128 else:
129 raise self.InvalidCmd('No such file or directory : %s' % inputfile)
130
131 if inputfile.endswith('.gz'):
132 misc.gunzip(inputfile)
133 inputfile = inputfile[:-3]
134
135
136 self.lhe_input = lhe_parser.EventFile(os.path.realpath(inputfile))
137 if not self.lhe_input.banner:
138 value = self.ask("What is the path to banner", 0, [0], "please enter a path", timeout=0)
139 self.lhe_input.banner = open(value).read()
140 self.banner = self.lhe_input.get_banner()
141
142
143 if 'init' not in self.banner:
144 self.orig_cross = (0,0)
145
146 else:
147 for line in self.banner['init'].split('\n'):
148 split = line.split()
149 if len(split) == 4:
150 cross, error = float(split[0]), float(split[1])
151 self.orig_cross = (cross, error)
152
153
154
155
156 if 'slha' not in self.banner:
157 misc.sprint(self.banner)
158 self.events_file = None
159 raise self.InvalidCmd('Event file does not contain model information')
160 elif 'mg5proccard' not in self.banner:
161 self.events_file = None
162 raise self.InvalidCmd('Event file does not contain generation information')
163
164 if 'madspin' in self.banner and not allow_madspin:
165 raise self.InvalidCmd('Reweight should be done before running MadSpin')
166
167
168
169 process = self.banner.get_detail('proc_card', 'generate')
170 if '[' in process:
171 logger.warning("Remember that the reweighting is performed at Leading Order. NLO precision is not guarantee.")
172
173 if not process:
174 msg = 'Invalid proc_card information in the file (no generate line):\n %s' % self.banner['mg5proccard']
175 raise Exception, msg
176 process, option = mg_interface.MadGraphCmd.split_process_line(process)
177 self.proc_option = option
178
179 logger.info("process: %s" % process)
180 logger.info("options: %s" % option)
181
182
184 """return the LO definitions of the process corresponding to the born/real"""
185
186
187 process, order, final = re.split('\[\s*(.*)\s*\]', proc)
188
189 commandline="add process %s %s --no_warning=duplicate;" % (process, final)
190 if not order:
191
192 return proc
193 elif not order.startswith(('virt=','loonly=','noborn=')):
194
195 if '=' in order:
196
197 order = order.split('=',1)[1]
198
199
200 pert = fks_common.find_pert_particles_interactions(self.model,
201 pert_order = order)['soft_particles']
202 commandline += "define pert_%s = %s;" % (order.replace(' ',''), ' '.join(map(str,pert)) )
203
204
205 if '%s=' % order in process:
206 result=re.split(' ',process)
207 process=''
208 for r in result:
209 if '%s=' % order in r:
210 ior=re.split('=',r)
211 r='QCD=%i' % (int(ior[1])+1)
212 process=process+r+' '
213
214 result = re.split('([/$@]|\w+=\w+)', process, 1)
215 if len(result) ==3:
216 process, split, rest = result
217 commandline+="add process %s pert_%s %s%s %s --no_warning=duplicate;" % (process, order.replace(' ','') ,split, rest, final)
218 else:
219 commandline +='add process %s pert_%s %s --no_warning=duplicate;' % (process,order.replace(' ',''), final)
220 elif order.startswith(('noborn=')):
221
222 return "add process %s " % proc.replace('noborn=', 'sqrvirt=')
223
224 else:
225
226 return "add process %s " % proc
227 return commandline
228
229
231 """Check some basic property of the events file"""
232
233 sum_of_weight = 0
234 sum_of_abs_weight = 0
235 negative_event = 0
236 positive_event = 0
237
238 start = time.time()
239 for event_nb,event in enumerate(self.lhe_input):
240
241 if (event_nb % max(int(10**int(math.log10(float(event_nb)+1))),10)==0):
242 running_time = misc.format_timer(time.time()-start)
243 logger.info('Event nb %s %s' % (event_nb, running_time))
244 if (event_nb==10001): logger.info('reducing number of print status. Next status update in 10000 events')
245
246 try:
247 event.check()
248 except Exception, error:
249 print event
250 raise error
251 sum_of_weight += event.wgt
252 sum_of_abs_weight += abs(event.wgt)
253 if event.wgt < 0 :
254 negative_event +=1
255 else:
256 positive_event +=1
257
258 logger.info("total cross-section: %s" % sum_of_weight)
259 logger.info("total abs cross-section: %s" % sum_of_abs_weight)
260 logger.info("fraction of negative event %s", negative_event/(negative_event+positive_event))
261 logger.info("total number of events %s", (negative_event+positive_event))
262 logger.info("negative event %s", negative_event)
263
264
265
266
267 @extended_cmd.debug()
269 "Complete the import command"
270
271 args=self.split_arg(line[0:begidx])
272
273 if len(args) == 1:
274 base_dir = '.'
275 else:
276 base_dir = args[1]
277
278 return self.path_completion(text, base_dir)
279
280
281 if os.path.sep in args[-1] + text:
282 return self.path_completion(text,
283 pjoin(*[a for a in args if \
284 a.endswith(os.path.sep)]))
285
287 """help for change command"""
288
289 print "change model X :use model X for the reweighting"
290 print "change process p p > e+ e-: use a new process for the reweighting"
291 print "change process p p > mu+ mu- --add : add one new process to existing ones"
292
294 """allow to define a second model/processes"""
295
296 global nb_f2py_module
297
298 args = self.split_arg(line)
299 if len(args)<2:
300 logger.critical("not enough argument (need at least two). Discard line")
301 if args[0] == "model":
302 nb_f2py_module += 1
303 self.second_model = " ".join(args[1:])
304 if self.has_standalone_dir:
305 self.terminate_fortran_executables()
306 self.has_standalone_dir = False
307 elif args[0] == "process":
308 nb_f2py_module += 1
309 if self.has_standalone_dir:
310 self.terminate_fortran_executables()
311 self.has_standalone_dir = False
312 if args[-1] == "--add":
313 self.second_process.append(" ".join(args[1:-1]))
314 else:
315 self.second_process = [" ".join(args[1:])]
316 elif args[0] == "output":
317 if args[1] in ['default', '2.0', 'unweight']:
318 self.output_type = args[1]
319 elif args[0] == "helicity":
320 self.helicity_reweighting = banner.ConfigFile.format_variable(args[1], bool, "helicity")
321 elif args[0] == "rwgt_dir":
322 self.rwgt_dir = args[1]
323 if not os.path.exists(self.rwgt_dir):
324 os.mkdir(self.rwgt_dir)
325 else:
326 logger.critical("unknown option! %s. Discard line." % args[0])
327
328
330 """check the validity of the launch command"""
331
332 if not self.lhe_input:
333 if isinstance(self.lhe_input, lhe_parser.EventFile):
334 self.lhe_input = lhe_parser.EventFile(self.lhe_input.name)
335 else:
336 raise self.InvalidCmd("No events files defined.")
337
339 """help for the launch command"""
340
341 logger.info('''Add to the loaded events a weight associated to a
342 new param_card (to be define). The weight returned is the ratio of the
343 square matrix element by the squared matrix element of production.
344 All scale are kept fix for this re-weighting.''')
345
346
347
349 """end of the configuration launched the code"""
350
351 args = self.split_arg(line)
352 self.check_launch(args)
353
354 model_line = self.banner.get('proc_card', 'full_model_line')
355
356 if not self.has_standalone_dir:
357 if self.rwgt_dir and os.path.exists(pjoin(self.rwgt_dir,'rw_me','rwgt.pkl')):
358 self.load_from_pickle()
359 self.me_dir = self.rwgt_dir
360 else:
361 self.create_standalone_directory()
362
363 if self.rwgt_dir:
364 path_me =self.rwgt_dir
365 else:
366 path_me = self.me_dir
367
368 if self.second_model or self.second_process:
369 rw_dir = pjoin(path_me, 'rw_me_second')
370 else:
371 rw_dir = pjoin(path_me, 'rw_me')
372
373 if not '--keep_card' in args:
374 ff = open(pjoin(rw_dir,'Cards', 'param_card.dat'), 'w')
375 ff.write(self.banner['slha'])
376 ff.close()
377 ff = open(pjoin(path_me, 'rw_me','Cards', 'param_card_orig.dat'), 'w')
378 ff.write(self.banner['slha'])
379 ff.close()
380 cmd = common_run_interface.CommonRunCmd.ask_edit_card_static(cards=['param_card.dat'],
381 ask=self.ask, pwd=rw_dir, first_cmd=self.stored_line)
382 self.stored_line = None
383
384
385 new_card = open(pjoin(rw_dir, 'Cards', 'param_card.dat')).read()
386 pattern_scan = re.compile(r'''^[\s\d]*scan''', re.I+re.M)
387 param_card_iterator = []
388 if pattern_scan.search(new_card):
389 if not isinstance(self.mother, cmd.CmdShell):
390 raise Exception, "scan are not allowed on the Web"
391
392 main_card = check_param_card.ParamCardIterator(new_card)
393
394 param_card_iterator = main_card
395 first_card = param_card_iterator.next(autostart=True)
396 new_card = first_card.write()
397 first_card.write(pjoin(rw_dir, 'Cards', 'param_card.dat'))
398
399 if "auto" in new_card.lower():
400 self.mother.check_param_card(pjoin(rw_dir, 'Cards', 'param_card.dat'))
401 new_card = open(pjoin(rw_dir, 'Cards', 'param_card.dat')).read()
402
403
404 if 'initrwgt' in self.banner:
405 if 'type=\'mg_reweighting\'' in self.banner['initrwgt']:
406 blockpat = re.compile(r'''<weightgroup type=\'mg_reweighting\'\s*>(?P<text>.*?)</weightgroup>''', re.I+re.M+re.S)
407 before, content, after = blockpat.split(self.banner['initrwgt'])
408 header_rwgt_other = before + after
409 pattern = re.compile('<weight id=\'mg_reweight_(?P<id>\d+)\'>(?P<info>[^<]*)</weight>', re.S+re.I+re.M)
410 mg_rwgt_info = pattern.findall(content)
411 maxid = 0
412 for i, diff in mg_rwgt_info:
413 if int(i) > maxid:
414 maxid = int(i)
415 maxid += 1
416 rewgtid = maxid
417 else:
418 header_rwgt_other = self.banner['initrwgt']
419 mg_rwgt_info = []
420 rewgtid = 1
421 else:
422 self.banner['initrwgt'] = ''
423 header_rwgt_other = ''
424 mg_rwgt_info = []
425 rewgtid = 1
426
427
428
429 s_orig = self.banner['slha']
430 s_new = new_card
431 if not self.second_model:
432 old_param = check_param_card.ParamCard(s_orig.splitlines())
433 new_param = check_param_card.ParamCard(s_new.splitlines())
434 card_diff = old_param.create_diff(new_param)
435 if card_diff == '' and not self.second_process:
436 logger.warning(' REWEIGHTING: original card and new card are identical. Bypass this run')
437 return
438
439 try:
440 if old_param['sminputs'].get(3)- new_param['sminputs'].get(3) > 1e-3 * new_param['sminputs'].get(3):
441 logger.warning("We found different value of alpha_s. Note that the value of alpha_s used is the one associate with the event and not the one from the cards.")
442 except Exception, error:
443 logger.debug("error in check of alphas: %s" % str(error))
444 pass
445 if not self.second_process:
446 mg_rwgt_info.append((str(rewgtid), card_diff))
447 else:
448 str_proc = "\n change process ".join([""]+self.second_process)
449 mg_rwgt_info.append((str(rewgtid), str_proc + '\n'+ card_diff))
450 else:
451 str_info = "change model %s" % self.second_model
452 if self.second_process:
453 str_info += "\n change process ".join([""]+self.second_process)
454 card_diff = str_info
455 str_info += '\n' + s_new
456 mg_rwgt_info.append((str(rewgtid), str_info))
457
458
459 self.banner['initrwgt'] = header_rwgt_other
460 self.banner['initrwgt'] += '\n<weightgroup type=\'mg_reweighting\'>\n'
461 for tag, diff in mg_rwgt_info:
462 self.banner['initrwgt'] += '<weight id=\'mg_reweight_%s\'>%s</weight>\n' % \
463 (tag, diff)
464 self.banner['initrwgt'] += '\n</weightgroup>\n'
465 self.banner['initrwgt'] = self.banner['initrwgt'].replace('\n\n', '\n')
466
467 output = open( self.lhe_input.name +'rw', 'w')
468
469
470 logger.info('starts to compute weight for events with the following modification to the param_card:')
471 logger.info(card_diff)
472
473
474 self.banner.write(output, close_tag=False)
475
476 if self.mother:
477 out_path = pjoin(self.mother.me_dir, 'Events', 'reweight.lhe')
478 output2 = open(out_path, 'w')
479 lha_strategy = self.banner.get_lha_strategy()
480 self.banner.set_lha_strategy(4*lha_strategy/abs(lha_strategy))
481 self.banner.write(output2, close_tag=False)
482 self.banner.set_lha_strategy(lha_strategy)
483 new_banner = banner.Banner(self.banner)
484 if not hasattr(self, 'run_card'):
485 self.run_card = new_banner.charge_card('run_card')
486 self.run_card['run_tag'] = 'reweight_%s' % rewgtid
487 new_banner['slha'] = s_new
488 del new_banner['initrwgt']
489 assert 'initrwgt' in self.banner
490 ff = open(pjoin(self.mother.me_dir,'Events',self.mother.run_name, '%s_%s_banner.txt' % \
491 (self.mother.run_name, self.run_card['run_tag'])),'w')
492 new_banner.write(ff)
493 ff.close()
494
495
496 tag_name = 'mg_reweight_%s' % rewgtid
497 start = time.time()
498 cross = 0
499 ratio, ratio_square = 0, 0
500
501 os.environ['GFORTRAN_UNBUFFERED_ALL'] = 'y'
502 if self.lhe_input.closed:
503 misc.sprint("using", self.lhe_input.name)
504 self.lhe_input = lhe_parser.EventFile(self.lhe_input.name)
505
506
507 nb_core = 1
508
509
510
511 self.lhe_input.seek(0)
512 for event_nb,event in enumerate(self.lhe_input):
513
514 if (event_nb % max(int(10**int(math.log10(float(event_nb)+1))),10)==0):
515 running_time = misc.format_timer(time.time()-start)
516 logger.info('Event nb %s %s' % (event_nb, running_time))
517 if (event_nb==10001): logger.info('reducing number of print status. Next status update in 10000 events')
518
519 if nb_core > 1:
520
521 while 1:
522 if multicore.queue.qsize() < 100 * nb_core:
523 multicore.submit(self.write_reweighted_event, argument=[event, tag_name])
524 break
525
526
527 continue
528 else:
529 weight = self.calculate_weight(event)
530 cross += weight
531 ratio += weight/event.wgt
532 ratio_square += (weight/event.wgt)**2
533 if self.output_type == "default":
534 event.reweight_data[tag_name] = weight
535
536 output.write(str(event))
537 if self.mother:
538 event.wgt = weight
539 event.reweight_data = {}
540 output2.write(str(event))
541
542 else:
543 event.wgt = weight
544 event.reweight_data = {}
545 if self.mother:
546 output2.write(str(event))
547 else:
548 output.write(str(event))
549
550
551 if 'event_norm' in self.run_card:
552 if self.run_card['event_norm'] == 'average':
553 cross /= event_nb+1
554
555
556 running_time = misc.format_timer(time.time()-start)
557 logger.info('All event done (nb_event: %s) %s' % (event_nb+1, running_time))
558
559 output.write('</LesHouchesEvents>\n')
560 output.close()
561 os.environ['GFORTRAN_UNBUFFERED_ALL'] = 'n'
562 if self.mother:
563 output2.write('</LesHouchesEvents>\n')
564 output2.close()
565
566 if hasattr(self.mother, 'results'):
567 run_name = self.mother.run_name
568 results = self.mother.results
569 results.add_run(run_name, self.run_card, current=True)
570 results.add_detail('nb_event', event_nb+1)
571 results.add_detail('cross', cross)
572 event_nb +=1
573 variance = ratio_square/event_nb - (ratio/event_nb)**2
574 orig_cross, orig_error = self.orig_cross
575 error = variance/math.sqrt(event_nb) * orig_cross + ratio/event_nb * orig_error
576
577 results.add_detail('error', error)
578 self.mother.create_plot(mode='reweight', event_path=output2.name,
579 tag=self.run_card['run_tag'])
580
581 if 'plot' in results.current.reweight:
582 html_dir = pjoin(self.mother.me_dir, 'HTML', run_name)
583 td = pjoin(self.mother.options['td_path'], 'td')
584 MA = pjoin(self.mother.options['madanalysis_path'])
585 path1 = pjoin(html_dir, 'plots_parton')
586 path2 = pjoin(html_dir, 'plots_%s' % self.run_card['run_tag'])
587 outputplot = path2
588 combine_plots.merge_all_plots(path2, path1, outputplot, td, MA)
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603 self.lhe_input.close()
604 if not self.mother or self.output_type != "default" :
605 target = pjoin(self.mother.me_dir, 'Events', run_name, 'events.lhe')
606 else:
607 target = self.lhe_input.name
608
609 if self.output_type == "default":
610 files.mv(output.name, target)
611 elif self.output_type == "unweight":
612 output2.close()
613 lhe = lhe_parser.EventFile(output2.name)
614 nb_event = lhe.unweight(target)
615 if self.mother and hasattr(self.mother, 'results'):
616 results = self.mother.results
617 results.add_detail('nb_event', nb_event)
618 results.current.parton.append('lhe')
619
620 else:
621 files.mv(output2.name, self.lhe_input.name)
622 if self.mother and hasattr(self.mother, 'results'):
623 results = self.mother.results
624 results.current.parton.append('lhe')
625
626 logger.info('Event %s have now the additional weight' % self.lhe_input.name)
627 logger.info('new cross-section is : %g pb (indicative error: %g pb)' % (cross,error))
628 self.terminate_fortran_executables(new_card_only=True)
629
630 self.all_cross_section[rewgtid] = (cross, error)
631
632
633 if param_card_iterator:
634 for card in param_card_iterator:
635 card.write(pjoin(rw_dir, 'Cards', 'param_card.dat'))
636 self.exec_cmd("launch --keep_card", printcmd=False, precmd=True)
637
638
640 "Not in help"
641
642 logger.warning("Invalid Syntax. The command 'set' should be placed after the 'launch' one. Continuing by adding automatically 'launch'")
643 self.stored_line = "set %s" % line
644 return self.exec_cmd("launch")
645
646 - def default(self, line, log=True):
647 """Default action if line is not recognized"""
648
649 if os.path.isfile(line):
650 if log:
651 logger.warning("Invalid Syntax. The path to a param_card' should be placed after the 'launch' command. Continuing by adding automatically 'launch'")
652 self.stored_line = line
653 return self.exec_cmd("launch")
654 else:
655 return super(ReweightInterface,self).default(line, log=log)
656
658 """a function for running in multicore"""
659
660 if not hasattr(opt['thread_space'], "calculator"):
661 opt['thread_space'].calculator = {}
662 opt['thread_space'].calculator_nbcall = {}
663 opt['thread_space'].cross = 0
664 opt['thread_space'].output = open( self.lhe_input.name +'rw.%s' % opt['thread_id'], 'w')
665 if self.mother:
666 out_path = pjoin(self.mother.me_dir, 'Events', 'reweight.lhe.%s' % opt['thread_id'])
667 opt['thread_space'].output2 = open(out_path, 'w')
668
669 weight = self.calculate_weight(event, space=opt['thread_space'])
670 opt['thread_space'].cross += weight
671 if self.output_type == "default":
672 event.reweight_data[tag_name] = weight
673
674 opt['thread_space'].output.write(str(event))
675 if self.mother:
676 event.wgt = weight
677 event.reweight_data = {}
678 opt['thread_space'].output2.write(str(event))
679 else:
680 event.wgt = weight
681 event.reweight_data = {}
682 if self.mother:
683 opt['thread_space'].output2.write(str(event))
684 else:
685 opt['thread_space'].output.write(str(event))
686
687 return 0
688
690 """space defines where to find the calculator (in multicore)"""
691
692 if not space:
693 space = self
694
695 event.parse_reweight()
696
697 w_orig = self.calculate_matrix_element(event, 0, space)
698 w_new = self.calculate_matrix_element(event, 1, space)
699 if w_orig == 0:
700 tag, order = event.get_tag_and_order()
701 orig_order, Pdir, hel_dict = self.id_to_path[tag]
702 misc.sprint(w_orig, w_new)
703 misc.sprint(event)
704 raise Exception, "Invalid matrix element for original computation (weight=0)"
705 return w_new/w_orig*event.wgt
706
707 @staticmethod
709 """ fortran/C-python do not order table in the same order"""
710 new_p = []
711 for i in range(len(p[0])): new_p.append([0]*len(p))
712 for i, onep in enumerate(p):
713 for j, x in enumerate(onep):
714 new_p[j][i] = x
715 return new_p
716
717 @staticmethod
719 if tag == 2:
720 return
721 if os.path.exists(pjoin(Pdir, 'matrix%spy.so' % tag)):
722 return
723 else:
724 open(pjoin(Pdir, 'matrix%spy.so' % tag),'w').write(open(pjoin(Pdir, 'matrix2py.so')
725 ).read().replace('matrix2py', 'matrix%spy' % tag))
726
728 """routine to return the matrix element"""
729
730 tag, order = event.get_tag_and_order()
731
732 if (not self.second_model and not self.second_process) or hypp_id==0:
733 orig_order, Pdir, hel_dict = self.id_to_path[tag]
734 else:
735 orig_order, Pdir, hel_dict = self.id_to_path_second[tag]
736
737 run_id = (tag, hypp_id)
738
739
740 assert space == self
741 start = False
742 if run_id in space.calculator:
743 external = space.calculator[run_id]
744 elif (not self.second_model and not self.second_process) or hypp_id==0:
745
746 subdir = pjoin(self.me_dir,'rw_me ', 'SubProcesses')
747 if self.me_dir not in sys.path:
748 sys.path.insert(0,self.me_dir)
749 if self.rwgt_dir and self.rwgt_dir not in sys.path:
750 sys.path.insert(0,self.rwgt_dir)
751 Pname = os.path.basename(Pdir)
752 if hypp_id == 0:
753 if (Pdir, 0) not in dir_to_f2py_free_mod:
754 metag = 1
755 dir_to_f2py_free_mod[(Pdir,0)] = (metag, nb_f2py_module)
756 else:
757 metag, old_module = dir_to_f2py_free_mod[(Pdir,0)]
758 if old_module != nb_f2py_module:
759 metag += 1
760 dir_to_f2py_free_mod[(Pdir,0)] = (metag, nb_f2py_module)
761
762 os.environ['MENUM'] = '2'
763 if not self.rwgt_dir or not os.path.exists(pjoin(Pdir, 'matrix2py.so')):
764 misc.compile(['matrix2py.so'], cwd=Pdir)
765 self.rename_f2py_lib(Pdir, 2*metag)
766
767 mymod = __import__('rw_me.SubProcesses.%s.matrix%spy' % (Pname, 2*metag), globals(), locals(), [],-1)
768 S = mymod.SubProcesses
769 P = getattr(S, Pname)
770 mymod = getattr(P, 'matrix%spy' % (2*metag))
771 with misc.chdir(Pdir):
772 mymod.initialise('param_card_orig.dat')
773
774 if hypp_id == 1:
775
776 metag = dir_to_f2py_free_mod[(Pdir,0)][0]
777 newtag = 2*metag+1
778 self.rename_f2py_lib(Pdir, newtag)
779 try:
780 mymod = __import__('rw_me.SubProcesses.%s.matrix%spy' % (Pname, newtag), globals(), locals(), [],-1)
781 except Exception, error:
782 os.remove(pjoin(Pdir, 'matrix%spy.so' % newtag))
783 newtag = "L%s" % newtag
784 os.environ['MENUM'] = newtag
785 misc.compile(['matrix%spy.so' % newtag], cwd=Pdir)
786 mymod = __import__('rw_me.SubProcesses.%s.matrix%spy' % (Pname, newtag), globals(), locals(), [],-1)
787
788 S = mymod.SubProcesses
789 P = getattr(S, Pname)
790 mymod = getattr(P, 'matrix%spy' % newtag)
791 with misc.chdir(Pdir):
792 mymod.initialise('param_card.dat')
793 space.calculator[run_id] = mymod.get_me
794 external = space.calculator[run_id]
795 else:
796 subdir = pjoin(self.me_dir,'rw_me_second', 'SubProcesses')
797 if self.me_dir not in sys.path:
798 sys.path.append(self.me_dir)
799
800 assert hypp_id == 1
801 Pname = os.path.basename(Pdir)
802 os.environ['MENUM'] = '2'
803 if not self.rwgt_dir or not os.path.exists(pjoin(Pdir, 'matrix2py.so')):
804 misc.compile(['matrix2py.so'], cwd=pjoin(subdir, Pdir))
805 if (Pdir, 1) not in dir_to_f2py_free_mod:
806 metag = 1
807 dir_to_f2py_free_mod[(Pdir,1)] = (metag, nb_f2py_module)
808 else:
809 metag, old_module = dir_to_f2py_free_mod[(Pdir,1)]
810 if old_module != nb_f2py_module:
811 metag += 1
812 dir_to_f2py_free_mod[(Pdir,1)] = (metag, nb_f2py_module)
813 self.rename_f2py_lib(Pdir, metag)
814
815 try:
816 mymod = __import__("rw_me_second.SubProcesses.%s.matrix%spy" % (Pname, metag))
817 except ImportError:
818 os.remove(pjoin(Pdir, 'matrix%spy.so' % metag ))
819 metag = "L%s" % metag
820 os.environ['MENUM'] = str(metag)
821 misc.compile(['matrix%spy.so' % metag], cwd=pjoin(subdir, Pdir))
822 mymod = __import__("rw_me_second.SubProcesses.%s.matrix%spy" % (Pname, metag))
823 reload(mymod)
824 S = mymod.SubProcesses
825 P = getattr(S, Pname)
826 mymod = getattr(P, 'matrix%spy' % metag)
827 with misc.chdir(Pdir):
828 mymod.initialise('param_card.dat')
829 space.calculator[run_id] = mymod.get_me
830 external = space.calculator[run_id]
831
832
833 p = self.invert_momenta(event.get_momenta(orig_order))
834
835
836 hel_order = event.get_helicity(orig_order)
837 if self.helicity_reweighting and 9 not in hel_order:
838 nhel = hel_dict[tuple(hel_order)]
839 else:
840 nhel = 0
841
842 with misc.chdir(Pdir):
843 with misc.stdchannel_redirected(sys.stdout, os.devnull):
844 me_value = external(p,event.aqcd, nhel)
845
846 if isinstance(me_value, tuple):
847 me_value, code = me_value
848
849 hundred_value = (code % 1000) //100
850 if hundred_value in [4]:
851 me_value = 0.
852
853 return me_value
854
856 """routine to terminate all fortran executables"""
857
858 for (mode, production) in dict(self.calculator):
859
860 if new_card_only and production == 0:
861 continue
862 del self.calculator[(mode, production)]
863
885
888
889
891 """Adding one element to the list based on the matrix element"""
892
893
894
895
896
897
898 @misc.mute_logger()
900 """generate the various directory for the weight evaluation"""
901
902
903 if not self.rwgt_dir:
904 path_me = self.me_dir
905 else:
906 path_me = self.rwgt_dir
907 try:
908 shutil.rmtree(pjoin(path_me,'rw_me'))
909 except Exception:
910 pass
911
912
913 complex_mass = False
914 has_cms = re.compile(r'''set\s+complex_mass_scheme\s*(True|T|1|true|$|;)''')
915 for line in self.banner.proc_card:
916 if line.startswith('set'):
917 self.mg5cmd.exec_cmd(line, printcmd=False, precmd=False, postcmd=False)
918 if has_cms.search(line):
919 complex_mass = True
920 elif line.startswith('define'):
921 try:
922 self.mg5cmd.exec_cmd(line, printcmd=False, precmd=False, postcmd=False)
923 except Exception:
924 pass
925
926 info = self.banner.get('proc_card', 'full_model_line')
927 if '-modelname' in info:
928 mg_names = False
929 else:
930 mg_names = True
931 model_name = self.banner.get('proc_card', 'model')
932 if model_name:
933 self.load_model(model_name, mg_names, complex_mass)
934 else:
935 raise self.InvalidCmd('Only UFO model can be loaded in this module.')
936
937 mgcmd = self.mg5cmd
938 modelpath = self.model.get('modelpath')
939 if os.path.basename(modelpath) != mgcmd._curr_model['name']:
940 name, restrict = mgcmd._curr_model['name'].rsplit('-',1)
941 if os.path.exists(pjoin(os.path.dirname(modelpath),name, 'restrict_%s.dat' % restrict)):
942 modelpath = pjoin(os.path.dirname(modelpath), mgcmd._curr_model['name'])
943
944 commandline="import model %s " % modelpath
945 mgcmd.exec_cmd(commandline)
946
947
948 for name, content in self.banner.get('proc_card', 'multiparticles'):
949 mgcmd.exec_cmd("define %s = %s" % (name, content))
950
951
952 processes = [line[9:].strip() for line in self.banner.proc_card
953 if line.startswith('generate')]
954 processes += [' '.join(line.split()[2:]) for line in self.banner.proc_card
955 if re.search('^\s*add\s+process', line)]
956 mgcmd.exec_cmd("set group_subprocesses False")
957
958 logger.info('generating the square matrix element for reweighting')
959 start = time.time()
960 commandline=''
961 for proc in processes:
962 if '[' not in proc:
963 commandline += "add process %s ;" % proc
964 else:
965 commandline += self.get_LO_definition_from_NLO(proc)
966
967 commandline = commandline.replace('add process', 'generate',1)
968 logger.info(commandline)
969 mgcmd.exec_cmd(commandline, precmd=True)
970 commandline = 'output standalone_rw %s' % pjoin(path_me,'rw_me')
971 mgcmd.exec_cmd(commandline, precmd=True)
972 logger.info('Done %.4g' % (time.time()-start))
973 self.has_standalone_dir = True
974
975
976
977 matrix_elements = mgcmd._curr_matrix_elements.get_matrix_elements()
978
979 self.id_to_path = {}
980 for me in matrix_elements:
981 for proc in me.get('processes'):
982 initial = []
983 final = [l.get('id') for l in proc.get('legs')\
984 if l.get('state') or initial.append(l.get('id'))]
985 order = (initial, final)
986 tag = proc.get_initial_final_ids()
987 decay_finals = proc.get_final_ids_after_decay()
988
989 if tag[1] != decay_finals:
990 order = (initial, list(decay_finals))
991 decay_finals.sort()
992 tag = (tag[0], tuple(decay_finals))
993 Pdir = pjoin(path_me, 'rw_me', 'SubProcesses',
994 'P%s' % me.get('processes')[0].shell_string())
995 assert os.path.exists(Pdir), "Pdir %s do not exists" % Pdir
996 if tag in self.id_to_path:
997 if not Pdir == self.id_to_path[tag][1]:
998 misc.sprint(tag, Pdir, self.id_to_path[tag][1])
999 raise self.InvalidCmd, '2 different process have the same final states. This module can not handle such situation'
1000 else:
1001 continue
1002
1003 hel_nb = 0
1004 hel_dict = {9:0}
1005 for helicities in me.get_helicity_matrix():
1006 hel_nb +=1
1007 hel_dict[tuple(helicities)] = hel_nb
1008
1009 self.id_to_path[tag] = [order, Pdir, hel_dict]
1010
1011
1012 if self.second_model or self.second_process:
1013 self.create_second_standalone_directory()
1014
1015 @misc.mute_logger()
1017 """generate the various directory for the weight evaluation"""
1018
1019
1020 path_me = self.me_dir
1021 try:
1022 shutil.rmtree(pjoin(path_me,'rw_me_second'))
1023 except Exception:
1024 pass
1025
1026 mgcmd = self.mg5cmd
1027
1028 if self.second_model:
1029 use_mgdefault= True
1030 complex_mass = False
1031 if ' ' in self.second_model:
1032 args = self.second_model.split()
1033 if '--modelname' in args:
1034 use_mgdefault = False
1035 model_name = args[0]
1036 else:
1037 model_name = self.second_model
1038 self.load_model(model_name, use_mgdefault, complex_mass)
1039
1040 modelpath = self.model.get('modelpath')
1041 if os.path.basename(modelpath) != mgcmd._curr_model['name']:
1042 name, restrict = mgcmd._curr_model['name'].rsplit('-',1)
1043 if os.path.exists(pjoin(os.path.dirname(modelpath),name, 'restrict_%s.dat' % restrict)):
1044 modelpath = pjoin(os.path.dirname(modelpath), mgcmd._curr_model['name'])
1045
1046 commandline="import model %s " % modelpath
1047 if not use_mgdefault:
1048 commandline += ' -modelname '
1049 mgcmd.exec_cmd(commandline)
1050
1051
1052 if self.second_process:
1053 processes = self.second_process
1054 else:
1055 processes = [line[9:].strip() for line in self.banner.proc_card
1056 if line.startswith('generate')]
1057 processes += [' '.join(line.split()[2:]) for line in self.banner.proc_card
1058 if re.search('^\s*add\s+process', line)]
1059 mgcmd.exec_cmd("set group_subprocesses False")
1060
1061 logger.info('generating the square matrix element for reweighting')
1062 start = time.time()
1063 commandline=''
1064 for proc in processes:
1065 if '[' not in proc:
1066 commandline+="add process %s ;" % proc
1067 elif 'sqrvirt' in proc:
1068 commandline+="add process %s ;" % proc
1069 else:
1070 raise self.InvalidCmd('NLO processes can\'t be reweight (for Loop induced reweighting use [sqrvirt =])')
1071
1072 commandline = commandline.replace('add process', 'generate',1)
1073 logger.info(commandline)
1074 mgcmd.exec_cmd(commandline, precmd=True)
1075
1076 matrix_elements = mgcmd._curr_matrix_elements.get_matrix_elements()
1077
1078 commandline = 'output standalone_rw %s' % pjoin(path_me,'rw_me_second')
1079 mgcmd.exec_cmd(commandline, precmd=True)
1080 logger.info('Done %.4g' % (time.time()-start))
1081
1082
1083 matrix_elements = mgcmd._curr_matrix_elements.get_matrix_elements()
1084
1085 self.id_to_path_second = {}
1086 to_check = []
1087 for me in matrix_elements:
1088 for proc in me.get('processes'):
1089 initial = []
1090 final = [l.get('id') for l in proc.get('legs')\
1091 if l.get('state') or initial.append(l.get('id'))]
1092 order = (initial, final)
1093 tag = proc.get_initial_final_ids()
1094 decay_finals = proc.get_final_ids_after_decay()
1095
1096 if tag[1] != decay_finals:
1097 order = (initial, list(decay_finals))
1098 decay_finals.sort()
1099 tag = (tag[0], tuple(decay_finals))
1100 Pdir = pjoin(path_me, 'rw_me_second', 'SubProcesses',
1101 'P%s' % me.get('processes')[0].shell_string())
1102 if not os.path.exists(Pdir):
1103 to_check.append(tag)
1104 continue
1105 if tag in self.id_to_path_second:
1106 if not Pdir == self.id_to_path_second[tag][1]:
1107 misc.sprint(tag, Pdir, self.id_to_path_second[tag][1])
1108 raise self.InvalidCmd, '2 different process have the same final states. This module can not handle such situation'
1109 else:
1110 continue
1111
1112
1113 hel_nb = 0
1114 hel_dict = {9:0}
1115 for helicities in me.get_helicity_matrix():
1116 hel_nb +=1
1117 hel_dict[tuple(helicities)] = hel_nb
1118 self.id_to_path_second[tag] = [order, Pdir, hel_dict]
1119
1120 for tag in to_check:
1121 if tag not in self.id_to_path:
1122 logger.warning("no valid path for %s" % (tag,))
1123
1124
1125
1126 if os.path.exists(pjoin(path_me, 'rw_me_second', 'Cards', 'MadLoopParams.dat')):
1127 MLCard = banner.MadLoopParam(pjoin(path_me, 'rw_me_second', 'Cards', 'MadLoopParams.dat'))
1128 MLCard.set('WriteOutFilters', False)
1129 MLCard.set('UseLoopFilter', False)
1130 MLCard.set("DoubleCheckHelicityFilter", False)
1131 MLCard.set("HelicityFilterLevel", 0)
1132 MLCard.write(pjoin(path_me, 'rw_me_second', 'SubProcesses', 'MadLoopParams.dat'),
1133 pjoin(path_me, 'rw_me_second', 'Cards', 'MadLoopParams.dat'),
1134 commentdefault=False)
1135
1136
1137
1138
1139
1140
1141 - def load_model(self, name, use_mg_default, complex_mass=False):
1159
1160
1162 import madgraph.iolibs.save_load_object as save_load_object
1163
1164 to_save = {}
1165 to_save['id_to_path'] = self.id_to_path
1166 if hasattr(self, 'id_to_path_second'):
1167 to_save['id_to_path_second'] = self.id_to_path_second
1168 else:
1169 to_save['id_to_path_second'] = {}
1170 to_save['all_cross_section'] = self.all_cross_section
1171 to_save['processes'] = self.processes
1172 to_save['second_process'] = self.second_process
1173 if self.second_model:
1174 to_save['second_model'] =True
1175 else:
1176 to_save['second_model'] = None
1177 to_save['rwgt_dir'] = self.rwgt_dir
1178
1179 name = pjoin(self.rwgt_dir, 'rw_me', 'rwgt.pkl')
1180 save_load_object.save_to_file(name, to_save)
1181
1183 import madgraph.iolibs.save_load_object as save_load_object
1184
1185 obj = save_load_object.load_from_file( pjoin(self.rwgt_dir, 'rw_me', 'rwgt.pkl'))
1186
1187 self.has_standalone_dir = True
1188 self.options = {'curr_dir': os.path.realpath(os.getcwd())}
1189
1190 old_rwgt = obj['rwgt_dir']
1191
1192
1193 self.id_to_path = {}
1194 for key , (order, Pdir, hel_dict) in obj['id_to_path'].items():
1195 new_P = Pdir.replace(old_rwgt, self.rwgt_dir)
1196 self.id_to_path[key] = [order, new_P, hel_dict]
1197
1198
1199 self.id_to_path_second = {}
1200 for key , (order, Pdir, hel_dict) in obj['id_to_path_second'].items():
1201 new_P = Pdir.replace(old_rwgt, self.rwgt_dir)
1202 self.id_to_path_second[key] = [order, new_P, hel_dict]
1203
1204 self.all_cross_section = obj['all_cross_section']
1205 self.processes = obj['processes']
1206 self.second_process = obj['second_process']
1207 self.second_model = obj['second_model']
1208