1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Definitions of the Helas objects needed for the implementation of MadFKS
17 from born"""
18
19
20 import madgraph.core.base_objects as MG
21 import madgraph.core.helas_objects as helas_objects
22 import madgraph.core.diagram_generation as diagram_generation
23 import madgraph.core.color_amp as color_amp
24 import madgraph.core.color_algebra as color_algebra
25 import madgraph.fks.fks_base as fks_base
26 import madgraph.fks.fks_common as fks_common
27 import madgraph.loop.loop_helas_objects as loop_helas_objects
28 import madgraph.loop.loop_diagram_generation as loop_diagram_generation
29 from madgraph import InvalidCmd
30 import copy
31 import logging
32 import array
33 import multiprocessing
34 import signal
35 import tempfile
36 import cPickle
37 import itertools
38 import os
39
40 logger = logging.getLogger('madgraph.fks_helas_objects')
41
42
43
45 i = args[0]
46 real_amp = args[1]
47
48
49 amplitude = real_amp.generate_real_amplitude()
50
51
52 if not amplitude['diagrams']:
53 msg = "Discarding amplitude with no diagrams%s" % \
54 (amplitude['process'].nice_string(print_weighted=False).replace('Process ', ''))
55 logger.debug(msg)
56 return []
57
58 helasreal = helas_objects.HelasMatrixElement(amplitude)
59 logger.info('Generating real %s' % \
60 real_amp.process.nice_string(print_weighted=False).replace('Process', 'process'))
61
62
63
64 list_colorize = []
65 list_color_basis = []
66 list_color_matrices = []
67
68
69
70
71 dict_loopborn_matrices = {}
72
73
74 color_information = { 'list_colorize' : list_colorize,
75 'list_color_basis' : list_color_basis,
76 'list_color_matrices' : list_color_matrices,
77 'dict_loopborn_matrices' : dict_loopborn_matrices}
78
79 helas_objects.HelasMultiProcess.process_color(helasreal,color_information)
80
81 outdata = [amplitude,helasreal]
82
83 output = tempfile.NamedTemporaryFile(delete = False)
84 cPickle.dump(outdata,output,protocol=2)
85 output.close()
86
87 return [output.name,helasreal.get_num_configs(),helasreal.get_nexternal_ninitial()[0]]
88
89
91 i = args[0]
92 born = args[1]
93 born_pdg_list = args[2]
94 loop_orders = args[3]
95 pdg_list = args[4]
96 loop_optimized = args[5]
97 OLP = args[6]
98 realmapout = args[7]
99
100 logger.info('Generating born %s' % \
101 born.born_amp['process'].nice_string(print_weighted=False).replace('Process', 'process'))
102
103
104 helasreal_list = []
105 amp_to_remove = []
106 for amp in born.real_amps:
107
108
109 try:
110 idx = pdg_list.index(amp.pdgs)
111 infilename = realmapout[idx]
112 infile = open(infilename,'rb')
113 realdata = cPickle.load(infile)
114 infile.close()
115 amp.amplitude = realdata[0]
116 helasreal_list.append(realdata[1])
117
118 except ValueError:
119 logger.debug('Removing amplitude: %s' % amp.process.nice_string())
120 amp_to_remove.append(amp)
121
122 for amp in amp_to_remove:
123 born.real_amps.remove(amp)
124
125 born.link_born_reals()
126
127 for amp in born.real_amps:
128 amp.find_fks_j_from_i(born_pdg_list)
129
130
131 has_loops = False
132 if born.born_amp['process'].get('NLO_mode') == 'all' and OLP == 'MadLoop':
133 myproc = copy.copy(born.born_amp['process'])
134
135
136 myproc['perturbation_couplings'] = myproc['model']['coupling_orders']
137 myproc['legs'] = fks_common.to_legs(copy.copy(myproc['legs']))
138
139 try:
140 myamp = loop_diagram_generation.LoopAmplitude(myproc)
141 has_loops = True
142 born.virt_amp = myamp
143 except InvalidCmd:
144 has_loops = False
145
146 helasfull = FKSHelasProcess(born, helasreal_list,
147 loop_optimized = loop_optimized,
148 decay_ids=[],
149 gen_color=False)
150
151 processes = helasfull.born_me.get('processes')
152
153 max_configs = helasfull.born_me.get_num_configs()
154
155 metag = helas_objects.IdentifyMETag.create_tag(helasfull.born_me.get('base_amplitude'))
156
157 outdata = helasfull
158
159 output = tempfile.NamedTemporaryFile(delete = False)
160 cPickle.dump(outdata,output,protocol=2)
161 output.close()
162
163 return [output.name,metag,has_loops,processes,helasfull.born_me.get_num_configs(),helasfull.get_nexternal_ninitial()[0]]
164
165
167
168 i = args[0]
169 mefile = args[1]
170 duplist = args[2]
171
172 infile = open(mefile,'rb')
173 me = cPickle.load(infile)
174 infile.close()
175
176
177 me.get('processes')[0].set('uid', i)
178
179
180
181
182 col_basis = color_amp.ColorBasis()
183 new_amp = me.born_me.get_base_amplitude()
184 me.born_me.set('base_amplitude', new_amp)
185 colorize_obj = col_basis.create_color_dict_list(new_amp)
186
187 col_basis.build()
188 col_matrix = color_amp.ColorMatrix(col_basis)
189
190 me.born_me.set('color_basis',col_basis)
191 me.born_me.set('color_matrix',col_matrix)
192
193 cannot_combine = []
194
195 for iother,othermefile in enumerate(duplist):
196 infileother = open(othermefile,'rb')
197 otherme = cPickle.load(infileother)
198 infileother.close()
199
200
201
202 if otherme == me:
203 me.add_process(otherme)
204 else:
205 cannot_combine.append(othermefile)
206
207 me.set_color_links()
208
209 initial_states=[]
210 for fksreal in me.real_processes:
211
212 initial_states.append(sorted(list(set((p.get_initial_pdg(1),p.get_initial_pdg(2)) for \
213 p in fksreal.matrix_element.get('processes')))))
214
215 if me.virt_matrix_element:
216 has_virtual = True
217 else:
218 has_virtual = False
219
220
221 outdata = me
222
223 output = tempfile.NamedTemporaryFile(delete = False)
224 cPickle.dump(outdata,output,protocol=2)
225 output.close()
226
227
228 return [output.name,initial_states,me.get_used_lorentz(),me.get_used_couplings(),has_virtual,cannot_combine]
229
230
232 """class to generate the helas calls for a FKSMultiProcess"""
233
235 """Return particle property names as a nicely sorted list."""
236 keys = super(FKSHelasMultiProcess, self).get_sorted_keys()
237 keys += ['real_matrix_elements', ['has_isr'], ['has_fsr'],
238 'used_lorentz', 'used_couplings', 'max_configs', 'max_particles', 'processes']
239 return keys
240
241 - def filter(self, name, value):
248
249 - def __init__(self, fksmulti, loop_optimized = False, gen_color =True, decay_ids =[]):
250 """Initialization from a FKSMultiProcess"""
251
252
253 loggers_off = [logging.getLogger('madgraph.diagram_generation'),
254 logging.getLogger('madgraph.helas_objects')]
255 old_levels = [logg.level for logg in loggers_off]
256 for logg in loggers_off:
257 logg.setLevel(logging.WARNING)
258
259 self.loop_optimized = loop_optimized
260
261 self['used_lorentz'] = []
262 self['used_couplings'] = []
263 self['processes'] = []
264
265 self['max_particles'] = -1
266 self['max_configs'] = -1
267
268 if not fksmulti['ncores_for_proc_gen']:
269
270
271 if fksmulti['real_amplitudes']:
272 logger.info('Generating real emission matrix-elements...')
273 self['real_matrix_elements'] = self.generate_matrix_elements(
274 copy.copy(fksmulti['real_amplitudes']), combine_matrix_elements = False)
275 else:
276 self['real_matrix_elements'] = helas_objects.HelasMatrixElementList()
277
278 self['matrix_elements'] = self.generate_matrix_elements_fks(
279 fksmulti,
280 gen_color, decay_ids)
281 self['initial_states']=[]
282 self['has_loops'] = len(self.get_virt_matrix_elements()) > 0
283
284 else:
285 self['has_loops'] = False
286
287 born_procs = fksmulti.get('born_processes')
288 born_pdg_list = [[l['id'] for l in born.born_amp['process']['legs']] \
289 for born in born_procs ]
290 loop_orders = {}
291 for born in born_procs:
292 for coup, val in fks_common.find_orders(born.born_amp).items():
293 try:
294 loop_orders[coup] = max([loop_orders[coup], val])
295 except KeyError:
296 loop_orders[coup] = val
297 pdg_list = []
298 real_amp_list = []
299 for born in born_procs:
300 for amp in born.real_amps:
301 if not pdg_list.count(amp.pdgs):
302 pdg_list.append(amp.pdgs)
303 real_amp_list.append(amp)
304
305
306 real_out_list = []
307 realmapin = []
308 for i,real_amp in enumerate(real_amp_list):
309 realmapin.append([i,real_amp])
310
311
312 original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
313 if fksmulti['ncores_for_proc_gen'] < 0:
314 pool = multiprocessing.Pool(maxtasksperchild=1)
315 else:
316 pool = multiprocessing.Pool(processes=fksmulti['ncores_for_proc_gen'],maxtasksperchild=1)
317 signal.signal(signal.SIGINT, original_sigint_handler)
318
319 logger.info('Generating real matrix elements...')
320 try:
321
322
323 realmapout = pool.map_async(async_generate_real,realmapin).get(9999999)
324 except KeyboardInterrupt:
325 pool.terminate()
326 raise KeyboardInterrupt
327
328
329
330 for rout, ramp, rpdg in zip(realmapout, real_amp_list, pdg_list):
331 if not rout:
332 realmapout.remove(rout)
333 real_amp_list.remove(ramp)
334 pdg_list.remove(rpdg)
335
336
337
338 realmapfiles = []
339 for realout in realmapout:
340 realmapfiles.append(realout[0])
341
342 logger.info('Generating born and virtual matrix elements...')
343
344 bornmapin = []
345 OLP=fksmulti['OLP']
346 for i,born in enumerate(born_procs):
347 bornmapin.append([i,born,born_pdg_list,loop_orders,pdg_list,loop_optimized,OLP,realmapfiles])
348
349 try:
350 bornmapout = pool.map_async(async_generate_born,bornmapin).get(9999999)
351 except KeyboardInterrupt:
352 pool.terminate()
353 raise KeyboardInterrupt
354
355 configs_list = [bout[4] for bout in bornmapout]
356 nparticles_list = [bout[5] for bout in bornmapout]
357
358
359 for realtmp in realmapout:
360 os.remove(realtmp[0])
361
362 memapout = []
363 while bornmapout:
364 logger.info('Collecting infos and finalizing matrix elements, %d left...' \
365 % (len(bornmapout)))
366 unique_me_list = []
367 duplicate_me_lists = []
368 for bornout in bornmapout:
369 mefile = bornout[0]
370 metag = bornout[1]
371 has_loops = bornout[2]
372 self['has_loops'] = self['has_loops'] or has_loops
373 processes = bornout[3]
374 self['processes'].extend(processes)
375 unique = True
376 for ime2,bornout2 in enumerate(unique_me_list):
377 mefile2 = bornout2[0]
378 metag2 = bornout2[1]
379 if metag==metag2:
380 duplicate_me_lists[ime2].append(mefile)
381 unique = False
382 break;
383 if unique:
384 unique_me_list.append(bornout)
385 duplicate_me_lists.append([])
386
387 memapin = []
388 not_combined = []
389 for i,bornout in enumerate(unique_me_list):
390 mefile = bornout[0]
391 memapin.append([i,mefile, duplicate_me_lists[i]])
392
393 try:
394 memapout.append(pool.map_async(async_finalize_matrix_elements,memapin).get(9999999))
395 except KeyboardInterrupt:
396 pool.terminate()
397 raise KeyboardInterrupt
398
399
400
401 for meout in memapout[-1]:
402 not_combined += meout[5]
403
404
405 for bornout in bornmapout[:]:
406 mefile = bornout[0]
407 if not mefile in not_combined:
408 os.remove(mefile)
409 bornmapout.remove(bornout)
410
411 pool.close()
412 pool.join()
413
414
415 memapout = sum(memapout, [])
416
417
418 matrix_elements = []
419 for meout in memapout:
420 matrix_elements.append(meout[0])
421
422 self['matrix_elements']=matrix_elements
423
424
425
426 initial_states = []
427 for meout in memapout:
428 me_initial_states = meout[1]
429 for state in me_initial_states:
430 initial_states.append(state)
431
432
433 checked = []
434 for e in initial_states:
435 if e not in checked:
436 checked.append(e)
437 initial_states=checked
438
439 self['initial_states']=initial_states
440
441 helas_list = []
442 for meout in memapout:
443 helas_list.extend(meout[2])
444 self['used_lorentz']=list(set(helas_list))
445
446 coupling_list = []
447 for meout in memapout:
448 coupling_list.extend([c for l in meout[3] for c in l])
449 self['used_couplings'] = list(set(coupling_list))
450
451 has_virtuals = False
452 for meout in memapout:
453 if meout[4]:
454 has_virtuals = True
455 break
456 self['has_virtuals'] = has_virtuals
457
458
459
460
461 for meout in realmapout:
462 configs_list.append(meout[1])
463 self['max_configs'] = max(configs_list)
464
465 for meout in realmapout:
466 nparticles_list.append(meout[2])
467 self['max_particles'] = max(nparticles_list)
468
469 self['has_isr'] = fksmulti['has_isr']
470 self['has_fsr'] = fksmulti['has_fsr']
471
472 logger.info('... Done')
473
474 for i, logg in enumerate(loggers_off):
475 logg.setLevel(old_levels[i])
476
478 """Return a list of (lorentz_name, conjugate, outgoing) with
479 all lorentz structures used by this HelasMultiProcess."""
480
481 if not self['used_lorentz']:
482 helas_list = []
483 for me in self.get('matrix_elements'):
484 helas_list.extend(me.get_used_lorentz())
485 self['used_lorentz'] = list(set(helas_list))
486
487 return self['used_lorentz']
488
489
491 """Return a list with all couplings used by this
492 HelasMatrixElement."""
493
494 if not self['used_couplings']:
495 coupling_list = []
496 for me in self.get('matrix_elements'):
497 coupling_list.extend([c for l in me.get_used_couplings() for c in l])
498 self['used_couplings'] = list(set(coupling_list))
499
500 return self['used_couplings']
501
502
504 """Return a list with all couplings used by this
505 HelasMatrixElement."""
506
507 if not self['processes']:
508 process_list = []
509 for me in self.get('matrix_elements'):
510 process_list.extend(me.born_me.get('processes'))
511 self['processes'] = process_list
512
513 return self['processes']
514
515
517 """Return max_configs"""
518
519 if self['max_configs'] < 0:
520 try:
521 self['max_configs'] = max([me.get_num_configs() \
522 for me in self['real_matrix_elements']])
523 except (ValueError, MG.PhysicsObject.PhysicsObjectError):
524 pass
525 self['max_configs'] = max(self['max_configs'],\
526 max([me.born_me.get_num_configs() \
527 for me in self['matrix_elements']]))
528 return self['max_configs']
529
530
532 """Return max_paricles"""
533
534 if self['max_particles'] < 0:
535 self['max_particles'] = max([me.get_nexternal_ninitial()[0] \
536 for me in self['matrix_elements']])
537
538 return self['max_particles']
539
540
542 """Extract the list of matrix elements"""
543 return self.get('matrix_elements')
544
545
547 """Extract the list of virtuals matrix elements"""
548 return [me.virt_matrix_element for me in self.get('matrix_elements') \
549 if me.virt_matrix_element]
550
551
554 """Generate the HelasMatrixElements for the amplitudes,
555 identifying processes with identical matrix elements, as
556 defined by HelasMatrixElement.__eq__. Returns a
557 HelasMatrixElementList and an amplitude map (used by the
558 SubprocessGroup functionality). decay_ids is a list of decayed
559 particle ids, since those should not be combined even if
560 matrix element is identical."""
561
562 fksprocs = fksmulti['born_processes']
563 assert isinstance(fksprocs, fks_base.FKSProcessList), \
564 "%s is not valid FKSProcessList" % \
565 repr(fksprocs)
566
567
568
569 list_colorize = []
570 list_color_links = []
571 list_color_basis = []
572 list_color_matrices = []
573 real_me_list = []
574 me_id_list = []
575
576 matrix_elements = FKSHelasProcessList()
577
578 for i, proc in enumerate(fksprocs):
579 logger.info("Generating Helas calls for FKS %s (%d / %d)" % \
580 (proc.get_born_nice_string().\
581 replace('Process', 'process'),
582 i + 1, len(fksprocs)))
583 matrix_element_list = [\
584 FKSHelasProcess(proc, self['real_matrix_elements'],
585 [amp for amp in fksmulti['real_amplitudes'] if amp['diagrams']],
586 loop_optimized = self.loop_optimized,
587 decay_ids=decay_ids,
588 gen_color=False)]
589
590 for matrix_element in matrix_element_list:
591 assert isinstance(matrix_element, FKSHelasProcess), \
592 "Not a FKSHelasProcess: %s" % matrix_element
593
594 try:
595
596
597
598 other = \
599 matrix_elements[matrix_elements.index(matrix_element)]
600 except ValueError:
601
602
603 if matrix_element.born_me.get('processes') and \
604 matrix_element.born_me.get('diagrams'):
605 matrix_elements.append(matrix_element)
606
607 if not gen_color:
608 continue
609
610
611
612
613 col_basis = color_amp.ColorBasis()
614 new_amp = matrix_element.born_me.get_base_amplitude()
615 matrix_element.born_me.set('base_amplitude', new_amp)
616 colorize_obj = col_basis.create_color_dict_list(new_amp)
617
618 try:
619
620
621
622 col_index = list_colorize.index(colorize_obj)
623 logger.info(\
624 "Reusing existing color information for %s" % \
625 matrix_element.born_me.get('processes')\
626 [0].nice_string(print_weighted=False).\
627 replace('Process', 'process'))
628 except ValueError:
629
630
631 list_colorize.append(colorize_obj)
632 col_basis.build()
633 list_color_basis.append(col_basis)
634 col_matrix = color_amp.ColorMatrix(col_basis)
635 list_color_matrices.append(col_matrix)
636 col_index = -1
637
638 logger.info(\
639 "Processing color information for %s" % \
640 matrix_element.born_me.get('processes')[0].\
641 nice_string(print_weighted=False).\
642 replace('Process', 'process'))
643 matrix_element.born_me.set('color_basis', list_color_basis[col_index])
644 matrix_element.born_me.set('color_matrix', list_color_matrices[col_index])
645 else:
646
647
648 other.add_process(matrix_element)
649
650 for me in matrix_elements:
651 me.set_color_links()
652 return matrix_elements
653
654
656 """class to handle lists of FKSHelasProcesses"""
657
659 """Test if object obj is a valid FKSProcess for the list."""
660 return isinstance(obj, FKSHelasProcess)
661
662
664 """class to generate the Helas calls for a FKSProcess. Contains:
665 -- born ME
666 -- list of FKSHelasRealProcesses
667 -- color links
668 -- charges
669 -- extra MEs used as counterterms
670 """
671
672 - def __init__(self, fksproc=None, real_me_list =[], real_amp_list=[],
673 loop_optimized = False, **opts):
674 """ constructor, starts from a FKSProcess,
675 sets reals and color links. Real_me_list and real_amp_list are the lists of pre-genrated
676 matrix elements in 1-1 correspondence with the amplitudes"""
677
678 if fksproc != None:
679 self.born_me = helas_objects.HelasMatrixElement(fksproc.born_amp, **opts)
680
681 self.real_processes = []
682 self.extra_cnt_me_list = []
683 self.perturbation = fksproc.perturbation
684 self.charges_born = fksproc.get_charges()
685 real_amps_new = []
686
687 for extra_cnt in fksproc.extra_cnt_amp_list:
688 self.extra_cnt_me_list.append(helas_objects.HelasMatrixElement(extra_cnt,gen_color=True))
689
690
691 if fksproc.ncores_for_proc_gen:
692
693 for real_me, proc in itertools.izip(real_me_list,fksproc.real_amps):
694 fksreal_me = FKSHelasRealProcess(proc, real_me, **opts)
695 try:
696 other = self.real_processes[self.real_processes.index(fksreal_me)]
697 other.matrix_element.get('processes').extend(\
698 fksreal_me.matrix_element.get('processes') )
699 except ValueError:
700 if fksreal_me.matrix_element.get('processes') and \
701 fksreal_me.matrix_element.get('diagrams'):
702 self.real_processes.append(fksreal_me)
703 real_amps_new.append(proc)
704 else:
705
706 for proc in fksproc.real_amps:
707 if proc.amplitude['diagrams']:
708 fksreal_me = FKSHelasRealProcess(proc, real_me_list, real_amp_list, **opts)
709 try:
710 other = self.real_processes[self.real_processes.index(fksreal_me)]
711 other.matrix_element.get('processes').extend(\
712 fksreal_me.matrix_element.get('processes') )
713 except ValueError:
714 if fksreal_me.matrix_element.get('processes') and \
715 fksreal_me.matrix_element.get('diagrams'):
716 self.real_processes.append(fksreal_me)
717 real_amps_new.append(proc)
718
719 fksproc.real_amps = real_amps_new
720 if fksproc.virt_amp:
721 self.virt_matrix_element = \
722 loop_helas_objects.LoopHelasMatrixElement(fksproc.virt_amp,
723 optimized_output = loop_optimized)
724 else:
725 self.virt_matrix_element = None
726 self.color_links = []
727
728
730 """this function computes and returns the color links, it should be called
731 after the initialization and the setting of the color basis"""
732 if not self.color_links:
733 legs = self.born_me.get('base_amplitude').get('process').get('legs')
734 model = self.born_me.get('base_amplitude').get('process').get('model')
735 color_links_info = fks_common.find_color_links(fks_common.to_fks_legs(legs, model),
736 symm = True, pert = self.perturbation)
737 col_basis = self.born_me.get('color_basis')
738 self.color_links = fks_common.insert_color_links(col_basis,
739 col_basis.create_color_dict_list(
740 self.born_me.get('base_amplitude')),
741 color_links_info)
742
744 """Returns the list of the fks infos for all processes in the format
745 {n_me, pdgs, fks_info}, where n_me is the number of real_matrix_element the configuration
746 belongs to"""
747 info_list = []
748 for n, real in enumerate(self.real_processes):
749 pdgs = [l['id'] for l in real.matrix_element.get_base_amplitude()['process']['legs']]
750 for info in real.fks_infos:
751 info_list.append({'n_me' : n + 1,'pdgs' : pdgs, 'fks_info' : info})
752 return info_list
753
754
756 """Returns the pdgs of the legs in the form "i1 i2 -> f1 f2 ...", which may
757 be useful (eg. to be written in a B-LH order file)"""
758
759 initial = ''
760 final = ''
761 for leg in self.born_me.get('processes')[0].get('legs'):
762 if leg.get('state'):
763 final += '%d ' % leg.get('id')
764 else:
765 initial += '%d ' % leg.get('id')
766 return initial + '-> ' + final
767
768
769 - def get(self, key):
770 """the get function references to the born
771 matrix element
772 """
773 return self.born_me.get(key)
774
775
777 """the get_used_lorentz function references to born, reals
778 and virtual matrix elements"""
779 lorentz_list = self.born_me.get_used_lorentz()
780 for real in self.real_processes:
781 lorentz_list.extend(real.matrix_element.get_used_lorentz())
782 if self.virt_matrix_element:
783 lorentz_list.extend(self.virt_matrix_element.get_used_lorentz())
784
785 return list(set(lorentz_list))
786
787
789 """the get_used_couplings function references to born, reals
790 and virtual matrix elements"""
791 coupl_list = self.born_me.get_used_couplings()
792 for real in self.real_processes:
793 coupl_list.extend([c for c in\
794 real.matrix_element.get_used_couplings()])
795 if self.virt_matrix_element:
796 coupl_list.extend(self.virt_matrix_element.get_used_couplings())
797 return coupl_list
798
800 """the nexternal_ninitial function references to the real emissions if they have been
801 generated, otherwise to the born"""
802 if self.real_processes:
803 (nexternal, ninitial) = self.real_processes[0].matrix_element.get_nexternal_ninitial()
804 else:
805 (nexternal, ninitial) = self.born_me.get_nexternal_ninitial()
806 nexternal += 1
807 return (nexternal, ninitial)
808
810 """the equality between two FKSHelasProcesses is defined up to the
811 color links"""
812
813 selftag = helas_objects.IdentifyMETag.\
814 create_tag(self.born_me.get('base_amplitude'))
815 othertag = helas_objects.IdentifyMETag.\
816 create_tag(other.born_me.get('base_amplitude'))
817
818 if selftag != othertag:
819 return False
820
821
822 if self.virt_matrix_element != other.virt_matrix_element:
823 return False
824
825
826 reals2 = copy.copy(other.real_processes)
827
828 for real in self.real_processes:
829 try:
830 reals2.remove(real)
831 except ValueError:
832 return False
833
834 if not reals2:
835 return True
836 else:
837 return False
838
839
841 """Inequality operator
842 """
843 return not self.__eq__(other)
844
845
847 """adds processes from born and reals of other to itself. Note that
848 corresponding real processes may not be in the same order. This is
849 taken care of by constructing the list of self_reals.
850 """
851
852
853 this_pdgs = [[leg['id'] for leg in proc['legs']] \
854 for proc in self.born_me['processes']]
855 for oth_proc in other.born_me['processes']:
856 oth_pdgs = [leg['id'] for leg in oth_proc['legs']]
857 if oth_pdgs not in this_pdgs:
858 self.born_me['processes'].append(oth_proc)
859 this_pdgs.append(oth_pdgs)
860
861
862 if self.virt_matrix_element and other.virt_matrix_element:
863 self.virt_matrix_element.get('processes').extend(
864 other.virt_matrix_element.get('processes'))
865
866
867 self_reals = [real.matrix_element for real in self.real_processes]
868 for oth_real in other.real_processes:
869
870 try:
871
872
873 this_real = self.real_processes[self.real_processes.index(oth_real)]
874 except ValueError:
875 raise fks_common.FKSProcessError('add_process: error in combination of real MEs')
876
877 this_pdgs = [[leg['id'] for leg in proc['legs']] \
878 for proc in this_real.matrix_element['processes']]
879 for oth_proc in oth_real.matrix_element['processes']:
880 oth_pdgs = [leg['id'] for leg in oth_proc['legs']]
881 if oth_pdgs not in this_pdgs:
882 this_real.matrix_element['processes'].append(oth_proc)
883 this_pdgs.append(oth_pdgs)
884
885
886
888 """class to generate the Helas calls for a FKSRealProcess
889 contains:
890 -- colors
891 -- charges
892 -- i/j/ij fks, ij refers to the born leglist
893 -- ijglu
894 -- need_color_links
895 -- fks_j_from_i
896 -- matrix element
897 -- is_to_integrate
898 -- leg permutation<<REMOVED"""
899
900 - def __init__(self, fksrealproc=None, real_me_list = [], real_amp_list =[], **opts):
901 """constructor, starts from a fksrealproc and then calls the
902 initialization for HelasMatrixElement.
903 Sets i/j fks and the permutation.
904 real_me_list and real_amp_list are the lists of pre-generated matrix elements in 1-1
905 correspondance with the amplitudes"""
906
907 if fksrealproc != None:
908 self.isfinite = False
909 self.colors = fksrealproc.colors
910 self.charges = fksrealproc.charges
911 self.fks_infos = fksrealproc.fks_infos
912 self.is_to_integrate = fksrealproc.is_to_integrate
913
914
915
916 if type(real_me_list) == list and len(real_me_list) != len(real_amp_list):
917 raise fks_common.FKSProcessError(
918 'not same number of amplitudes and matrix elements: %d, %d' % \
919 (len(real_amp_list), len(real_me_list)))
920 if type(real_me_list) == list and real_me_list and real_amp_list:
921 self.matrix_element = copy.deepcopy(real_me_list[real_amp_list.index(fksrealproc.amplitude)])
922 self.matrix_element['processes'] = copy.deepcopy(self.matrix_element['processes'])
923
924 elif type(real_me_list) == helas_objects.HelasMatrixElement:
925
926 assert fksrealproc.process in real_me_list['processes'], \
927 "Inconsistent input in FKSHelasRealProcess\nfksrealproc: %s\nME: %s" % \
928 (fksrealproc.process.nice_string(),
929 ' - '.join([p.nice_string() for p in real_me_list['processes']]))
930 self.matrix_element = real_me_list
931
932 else:
933
934 if real_me_list and real_amp_list:
935 self.matrix_element = copy.deepcopy(real_me_list[real_amp_list.index(fksrealproc.amplitude)])
936 self.matrix_element['processes'] = copy.deepcopy(self.matrix_element['processes'])
937 else:
938 logger.info('generating matrix element...')
939 self.matrix_element = helas_objects.HelasMatrixElement(
940 fksrealproc.amplitude, **opts)
941
942 self.matrix_element.get('color_basis').build(
943 self.matrix_element.get('base_amplitude'))
944 self.matrix_element.set('color_matrix',
945 color_amp.ColorMatrix(
946 self.matrix_element.get('color_basis')))
947
948 self.fks_j_from_i = fksrealproc.fks_j_from_i
949
953
955 """Equality operator:
956 compare two FKSHelasRealProcesses by comparing their dictionaries"""
957
958 for key in [k for k in self.__dict__.keys() if k not in ['fks_infos', 'charges']]:
959 if self.__dict__[key] != other.__dict__[key]:
960 return False
961
962
963 if (len(self.fks_infos) != len(other.fks_infos)):
964 return False
965
966 tocheck_info = [k for k in self.fks_infos[0].keys() if k not in ['ij_id', 'underlying_born']]
967 for selfinfo, otherinfo in zip(self.fks_infos, other.fks_infos):
968 if len(selfinfo['underlying_born']) != len(otherinfo['underlying_born']):
969 return False
970 for key in tocheck_info:
971 if selfinfo[key] != otherinfo [key]:
972 return False
973
974 return True
975
976
978 """Inequality operator:
979 compare two FKSHelasRealProcesses by comparing their dictionaries"""
980 return not self.__eq__(other)
981