1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Definitions of the objects needed both for MadFKS from real
17 and MadFKS from born"""
18
19 import madgraph.core.base_objects as MG
20 import madgraph.core.helas_objects as helas_objects
21 import madgraph.core.diagram_generation as diagram_generation
22 import madgraph.core.color_amp as color_amp
23 import madgraph.core.color_algebra as color_algebra
24 from operator import itemgetter
25 import copy
26 import logging
27 import array
28 import fractions
33 """Exception for MadFKS"""
34 pass
35
38 """Modified diagram tags to be used to link born and real configurations.
39 """
40
41 @staticmethod
43 """Returns the default end link for a leg: ((id, number), number).
44 Note that the number is not taken into account if tag comparison,
45 but is used only to extract leg permutations.
46 """
47 return [((leg.get('id'), leg.get('number')), leg.get('number'))]
48
51 """finds the real configurations that match the born ones, i.e. for
52 each born configuration, the real configuration that has the ij ->
53 i j splitting. i, j and ij are integers, and refer to the leg
54 position in the real process (i, j) and in the born process (ij).
55 """
56
57 id_ij = born_amp['process']['legs'][ij - 1]['id']
58 nlegs_b = len(born_amp['process']['legs'])
59 nlegs_r = len(real_amp['process']['legs'])
60 if nlegs_r - nlegs_b != 1:
61 raise FKSProcessError('Inconsistent number of born and real legs: %d %d' % (nlegs_b, nlegs_r))
62
63
64 shift_dict = {}
65 for ir in range(1, nlegs_r + 1):
66 shift = 0
67 if ir > j:
68 shift += 1
69 if ir > i:
70 shift += 1
71 if ir > ij and ij <= max(i,j):
72 shift -= 1
73 shift_dict[ir] = ir - shift
74
75
76 minvert = min([max([len(vert.get('legs')) \
77 for vert in diag.get('vertices')]) \
78 for diag in born_amp.get('diagrams')])
79
80 born_confs = []
81 real_confs = []
82
83 k=0
84 for diag in born_amp.get('diagrams'):
85 if any([len(vert.get('legs')) > minvert for vert in
86 diag.get('vertices')]):
87 continue
88 else:
89 born_confs.append({'number' : k, 'diagram' : diag})
90 k=k+1
91
92 k=0
93 for diag in real_amp.get('diagrams'):
94 if any([len(vert.get('legs')) > minvert \
95 for vert in diag.get('vertices')]):
96 continue
97 else:
98 real_confs.append({'number': k, 'diagram': diag})
99 k=k+1
100
101 good_diags = []
102
103
104
105
106 real_confs_new = copy.deepcopy(real_confs)
107 for diag in real_confs_new:
108 for vert in diag['diagram'].get('vertices'):
109 vert_legs = [l.get('number') for l in vert.get('legs')]
110 vert_ids = [l.get('id') for l in vert.get('legs')]
111 if (i in vert_legs and not j in vert_legs) or \
112 (j in vert_legs and not i in vert_legs):
113 break
114
115 if i in vert_legs and j in vert_legs:
116 vert_ids.remove(vert_ids[vert_legs.index(i)])
117 vert_legs.remove(i)
118 vert_ids.remove(vert_ids[vert_legs.index(j)])
119 vert_legs.remove(j)
120 last_leg = vert_legs[0]
121
122
123 if abs(vert_ids[0]) == abs(id_ij):
124 diag['diagram']['vertices'].remove(vert)
125 good_diags.append({'diagram': diag['diagram'],
126 'leg_ij': last_leg,
127 'number': diag['number']})
128 break
129
130
131
132
133
134
135
136
137
138
139
140 for ir in range(1, nlegs_r + 1):
141 for good_diag in good_diags:
142 for vert in good_diag['diagram'].get('vertices'):
143 for l in vert.get('legs'):
144 if l.get('number') == ir:
145 l.set('number', shift_dict[l.get('number')])
146
147
148 if len(good_diags) == 1 and len(born_confs) == 1:
149 return [{'real_conf': good_diags[0]['number'],
150 'born_conf': born_confs[0]['number']}]
151
152
153
154 if nlegs_b ==3:
155 for diag in good_diags:
156 counts = []
157 for il in range(nlegs_b):
158 counts.append([l['number'] for v in diag['diagram']['vertices'] for l in v['legs']].count(il+1))
159
160
161 even_list = [c / 2 * 2 == c for c in counts]
162 if any(even_list):
163 if not even_list.count(True) == 2:
164 raise FKSProcessError('Linking: Don\'t know what to do in this case')
165
166 ilmax = counts.index(max([c for c in counts if even_list[counts.index(c)]]))
167 ilmin = counts.index(min([c for c in counts if even_list[counts.index(c)]]))
168
169
170 replaced = False
171 for vert in diag['diagram']['vertices']:
172 for leg in vert['legs']:
173 if leg['number'] == ilmax + 1 and not replaced:
174 leg['number'] = ilmin + 1
175 replaced = True
176
177
178 born_tags = [FKSDiagramTag(d['diagram'],
179 born_amp.get('process').get('model')) \
180 for d in born_confs]
181
182
183 real_tags = [FKSDiagramTag(d['diagram'],
184 real_amp.get('process').get('model')) \
185 for d in good_diags ]
186 real_tags = []
187 for d in good_diags:
188 tag = FKSDiagramTag(d['diagram'], real_amp.get('process').get('model'))
189 if not tag in real_tags:
190 real_tags.append(tag)
191
192
193 if len(born_tags) != len(real_tags):
194 print '\n'.join([str(r) for r in real_tags]) + '\n'
195 raise FKSProcessError('Cannot map born/real configurations between \
196 %s and %s (i,j=%d,%d): not same number of configurations: %d %d' % \
197 (born_amp.get('process').nice_string().replace('Process:',''),
198 real_amp.get('process').nice_string().replace('Process:',''),
199 i,j,
200 len(born_tags),
201 len(real_tags)))
202
203 links = []
204 for ib, btag in enumerate(born_tags):
205 try:
206 ir = real_tags.index(btag)
207 links.append({'real_conf': good_diags[ir]['number'],
208 'born_conf': born_confs[ib]['number']})
209 real_tags.remove(btag)
210 good_diags.pop(ir)
211 except ValueError:
212 print real_tags, i, j, ij
213 print '\n'.join( d['diagram'].nice_string() for d in good_diags)
214 raise FKSProcessError('Linking %s to %s: could not link born diagram %s' % \
215 (born_amp.get('process').nice_string().replace('Process:',''),
216 real_amp.get('process').nice_string().replace('Process:',''),
217 born_confs[ib]['diagram'].nice_string()) )
218
219 return links
220
224 """Takes an amplitude as input, and returns a dictionary with the
225 orders of the couplings.
226 """
227 assert isinstance(amp, diagram_generation.Amplitude)
228 orders = {}
229 for diag in amp.get('diagrams'):
230 for order, value in diag.get('orders').items():
231 if value != 0 or order in amp['process']['orders'].keys():
232 try:
233 orders[order] = max(orders[order], value)
234 except KeyError:
235 orders[order] = value
236 return orders
237
240 """Finds the possible splittings corresponding to leg
241 """
242 if dict == {}:
243 dict = find_pert_particles_interactions(model, pert)
244 splittings = []
245
246
247 if leg.get('id') in dict['pert_particles']:
248 part = model.get('particle_dict')[leg.get('id')]
249 antipart = model.get('particle_dict')[part.get_anti_pdg_code()]
250 for ii in dict['interactions']:
251
252 parts = copy.deepcopy(ii['particles'])
253 nsoft = 0
254 if part in parts:
255
256 parts.pop(parts.index(antipart))
257 for p in parts:
258 if p.get_pdg_code() in dict['soft_particles']:
259 nsoft += 1
260 if nsoft >= 1:
261 splittings.extend(split_leg(leg, parts, model))
262 return splittings
263
266 """Splits the leg into parts, and returns the two new legs.
267 """
268
269 split = []
270
271 if leg['state'] :
272 split.append([])
273 for part in parts:
274 split[-1].append(to_fks_leg({'state': True, \
275 'id': part.get_pdg_code()},model))
276 ij_final(split[-1])
277
278
279 else:
280 if parts[0] != parts[1]:
281 for part in parts:
282 cparts = copy.deepcopy(parts)
283 split.append([\
284 to_fks_leg({'state': False,
285 'id': cparts.pop(cparts.index(part)).get_pdg_code(),
286 'fks': 'j'}, model),
287 to_fks_leg({'state': True,
288 'id': cparts[0].get_anti_pdg_code(),
289 'fks': 'i'}, model)\
290 ])
291 else:
292 split.append([\
293 to_fks_leg({'state': False,
294 'id': parts[0].get_pdg_code(),
295 'fks': 'j'}, model),
296 to_fks_leg({'state': True,
297 'id': parts[1].get_anti_pdg_code(),
298 'fks': 'i'}, model)])
299 return split
300
303 """given a pair of legs in the final state, assigns the i/j fks id
304 NOTE: the j partons is always put before the i one
305 """
306
307
308
309 if len(pair) == 2:
310 for i in range(len(pair)):
311 set = 0
312 if (pair[i]['massless'] and pair[i]['self_antipart']) or \
313 (not pair[i]['is_part'] and pair[1-i]['is_part'] and\
314 (pair[i]['spin']+pair[1-i]['spin'])%2==0) and not set:
315 pair[i]['fks'] = 'i'
316 pair[1-i]['fks'] = 'j'
317
318 if i < 1 - i:
319 pair.reverse()
320 set = 1
321
323 """Returns a new leglist with leg splitted into split.
324 The convention is to remove leg ij, replace it with leg j, and put
325 i at the end of the group of legs with the same color(charge) representation
326 """
327 if pert =='QCD':
328 color = 'color'
329 elif pert == 'QED':
330 color = 'charge'
331 else:
332 raise FKSProcessError, "Only QCD or QED is allowed not %s" % pert
333
334 leglist = FKSLegList(copy.deepcopy(leglist_orig))
335
336 for i in range(len(leglist)):
337 if leglist[-i - 1].get('state'):
338 firstfinal = len(leglist) - i - 1
339
340 leglist[leglist.index(leg)] = split[0]
341
342 col_maxindex = {}
343 mass_col_maxindex = {}
344 for col in set([l[color] for l in leglist[firstfinal:] if l['massless']]):
345 col_maxindex[col] = max([0] + [leglist.index(l) for l in leglist[firstfinal:]\
346 if l[color] == col and l['massless']])
347 for col in set([abs(l[color]) for l in leglist[firstfinal:] if not l['massless']]):
348 mass_col_maxindex[col] = max([0] + [leglist.index(l) for l in leglist[firstfinal:]\
349 if abs(l[color]) == col and not l['massless']])
350
351 if pert == 'QCD':
352 for col in copy.copy(col_maxindex.keys()):
353 if abs(col) > abs(split[1][color]):
354 del col_maxindex[col]
355
356
357
358
359 if split[1]['is_part'] and not split[1]['self_antipart']:
360
361
362
363
364 try:
365 del col_maxindex[-split[1][color]]
366 except KeyError:
367 pass
368
369 leglist.insert(max(col_maxindex.values() + mass_col_maxindex.values() + [firstfinal - 1] ) + 1, split[1])
370
371
372
373
374
375
376
377
378
379
380
381 for i, leg in enumerate(leglist):
382 leg['number'] = i + 1
383 return leglist
384
385
386 -def combine_ij( i, j, model, dict, pert='QCD'):
387 """checks whether FKSlegs i and j can be combined together in the given model
388 and with given perturbation order and if so combines them into ij.
389 If dict is empty it is initialized with find_pert_particles_interactions
390 """
391 if dict == {}:
392 dict = find_pert_particles_interactions(model, pert)
393 ij = []
394 num = copy.copy(min(i.get('number'), j.get('number')))
395
396
397 not_double_counting = (j.get('spin') == 3 and j.get('massless') and
398 i.get('spin') == 3 and i.get('massless')) or \
399 j.get('spin') != 3 or not j.get('massless') or \
400 not j.get('state')
401
402
403
404 if j.get('state') and j.get('id') == - i.get('id'):
405 not_double_counting = not_double_counting and j.get('id') >0
406
407 if i.get('id') in dict['soft_particles'] and \
408 j.get('id') in dict['pert_particles'] and \
409 i.get('state') and not_double_counting:
410 for int in dict['interactions']:
411 parts= copy.copy(int['particles'])
412
413 try:
414 parts.remove(model.get('particle_dict')[i.get('id')])
415 except ValueError:
416 continue
417
418
419 if j.get('state'):
420 j_id = j.get('id')
421 else:
422 j_id = model.get('particle_dict')[j.get('id')].get_anti_pdg_code()
423 try:
424 parts.remove(model.get('particle_dict')[j_id])
425 except ValueError:
426 continue
427
428
429 if j.get('state'):
430 ij.append(MG.Leg({
431 'id': parts[0].get_anti_pdg_code(),
432 'state': True,
433 'number': num}))
434 else:
435 ij.append(MG.Leg({
436 'id': parts[0].get_pdg_code(),
437 'state': False,
438 'number': num}))
439 return to_fks_legs(ij, model)
440
441
442 -def find_pert_particles_interactions(model, pert_order = 'QCD'):
443 """given a model and pert_order, returns a dictionary with as entries:
444 --interactions : the interactions of order pert_order
445 --pert_particles : pdgs of particles taking part to interactions
446 --soft_particles : pdgs of massless particles in pert_particles
447 """
448
449 ghost_list = []
450 ghost_list += [ p.get_pdg_code() for p in model.get('particles') if p.get('ghost')]
451 qcd_inter = MG.InteractionList()
452 pert_parts = []
453 soft_parts = []
454 for i, ii in model.get('interaction_dict').items():
455
456
457
458 if ii.get('type') != 'base': continue
459
460 if ii.get('orders') == {pert_order:1} and len(ii['particles']) == 3 :
461 masslist = [p.get('mass').lower() for p in ii['particles']]
462
463
464 found_soft_even_spin_particle = False
465 for p in ii['particles']:
466 if p.get('mass').lower()=='zero':
467 if p.get('spin')%2==1:
468 found_soft_even_spin_particle = True
469 break
470 if not found_soft_even_spin_particle:
471 continue
472
473
474
475
476
477 try:
478 masslist.remove('zero')
479 except ValueError:
480 continue
481 if len(set(masslist)) == 1 and not \
482 any( [ p.get_pdg_code() in ghost_list for p in ii['particles']]) :
483 qcd_inter.append(ii)
484 for pp in ii['particles']:
485 pert_parts.append(pp.get_pdg_code())
486 if pp['mass'].lower() == 'zero':
487 soft_parts.append(pp.get_pdg_code())
488
489 return {'interactions': sorted(qcd_inter),
490 'pert_particles': sorted(set(pert_parts)),
491 'soft_particles': sorted(set(soft_parts))}
492
495 """insert the color links in col_obj: returns a list of dictionaries
496 (one for each link) with the following entries:
497 --link: the numbers of the linked legs
498 --link_basis: the linked color basis
499 --link_matrix: the color matrix created from the original basis and the linked one
500 """
501 assert isinstance(col_basis, color_amp.ColorBasis)
502 assert isinstance(col_obj, list)
503 result =[]
504 for link in links:
505 this = {}
506
507 l =[]
508 for leg in link['legs']:
509 l.append(leg.get('number'))
510 this['link'] = l
511
512
513
514
515
516 this_col_obj = []
517 for old_dict in col_obj:
518 new_dict = dict(old_dict)
519 for k, string in new_dict.items():
520 new_dict[k] = string.create_copy()
521 for col in new_dict[k]:
522 for ind in col:
523 for pair in link['replacements']:
524 if ind == pair[0]:
525 col[col.index(ind)] = pair[1]
526 new_dict[k].product(link['string'])
527 this_col_obj.append(new_dict)
528 basis_link = color_amp.ColorBasis()
529 for ind, new_dict in enumerate(this_col_obj):
530 basis_link.update_color_basis(new_dict, ind)
531
532 this['link_basis'] = basis_link
533 this['link_matrix'] = color_amp.ColorMatrix(col_basis,basis_link)
534 result.append(this)
535 basis_orig = color_amp.ColorBasis()
536 for ind, new_dict in enumerate(col_obj):
537 basis_orig.update_color_basis(new_dict, ind)
538
539 for link in result:
540 link['orig_basis'] = basis_orig
541 return result
542
546 """Finds all the possible color(charge) links between any
547 two legs of the born.
548 If symm is true, only half of the color links are generated, those
549 for which leg1['number'] <= leg2['number']
550 """
551 if pert == 'QCD':
552 color = 'color'
553 zero = 1
554 elif pert == 'QED':
555 color = 'charge'
556 zero = 0.
557 else:
558 raise FKSProcessError,"Only QCD or QED is allowed not %s" % pert
559 color_links = []
560 for leg1 in leglist:
561 for leg2 in leglist:
562
563 if (leg1.get(color) != zero and leg2.get(color) != zero) \
564 and (leg1 != leg2 or not leg1.get('massless')):
565 if not symm or leg1['number'] <= leg2['number']:
566 col_dict = legs_to_color_link_string(leg1,leg2,pert = pert)
567 color_links.append({
568 'legs': [leg1, leg2],
569 'string': col_dict['string'],
570 'replacements': col_dict['replacements']})
571
572 return color_links
573
576 """given two FKSlegs, returns a dictionary containing:
577 --string: the color link between the two particles, to be appended to
578 the old color string
579 extra minus or 1/2 factor are included as it was done in MadDipole
580 --replacements: a pair of lists containing the replacements of the color
581 indices in the old string to match the link
582 """
583
584
585
586 legs = FKSLegList([leg1, leg2])
587 dict = {}
588 min_index = -3000
589 iglu = min_index*2
590 string = color_algebra.ColorString()
591 replacements = []
592 if pert == 'QCD':
593 if leg1 != leg2:
594 for leg in legs:
595 min_index -= 1
596 num = leg.get('number')
597 replacements.append([num, min_index])
598 icol = 1
599 if not leg.get('state'):
600 icol = - 1
601 if leg.get('color') * icol == 3:
602 string.product(color_algebra.ColorString([
603 color_algebra.T(iglu, num, min_index)]))
604 string.coeff = string.coeff * (-1)
605 elif leg.get('color') * icol == - 3:
606 string.product(color_algebra.ColorString([
607 color_algebra.T(iglu, min_index, num)]))
608 elif leg.get('color') == 8:
609 string.product(color_algebra.ColorString(init_list = [
610 color_algebra.f(min_index,iglu,num)],
611 is_imaginary =True))
612
613 else:
614 icol = 1
615 if not leg1.get('state'):
616 icol = - 1
617 num = leg1.get('number')
618 replacements.append([num, min_index -1])
619 if leg1.get('color') * icol == 3:
620 string = color_algebra.ColorString(
621 [color_algebra.T(iglu, iglu, num, min_index -1)])
622 elif leg1.get('color') * icol == - 3:
623 string = color_algebra.ColorString(
624 [color_algebra.T(iglu, iglu, min_index-1, num)])
625 elif leg1.get('color') == 8:
626 string = color_algebra.ColorString(init_list = [
627 color_algebra.f(min_index-1,iglu,min_index)],
628 is_imaginary =True)
629 string.product(color_algebra.ColorString(init_list = [
630 color_algebra.f(min_index,iglu,num)],
631 is_imaginary =True))
632 string.coeff = string.coeff * fractions.Fraction(1, 2)
633
634 elif pert == 'QED':
635 for leg in legs:
636
637 string.coeff = string.coeff * fractions.Fraction(leg['charge']*3.)*\
638 fractions.Fraction(1,3)
639 else:
640 raise FKSProcessError,"Only QCD or QED is allowed not %s"% pert
641
642 dict['replacements'] = replacements
643 dict['string'] = string
644 return dict
645
648 """Given a process, this function returns the same process
649 but with sorted FKSLegs.
650 """
651 leglist = to_fks_legs(process.get('legs'), process.get('model'))
652 leglist.sort(pert = pert)
653 for n, leg in enumerate(leglist):
654 leg['number'] = n + 1
655 process['legs'] = leglist
656
657 process['legs_with_decays']=MG.LegList()
658
659 return process
660
663 """Given a FKSLeg, returns the original Leg.
664 """
665 leg = MG.Leg( \
666 {'id': fksleg.get('id'),
667 'number': fksleg.get('number'),
668 'state': fksleg.get('state'),
669 'from_group': fksleg.get('from_group'),
670 'polarization': fksleg.get('polarization')
671 })
672 return leg
673
676 """Given a FKSLegList, returns the corresponding LegList.
677 """
678 leglist = MG.LegList()
679 for leg in fkslegs:
680 leglist.append(to_leg(leg))
681 return leglist
682
685 """Given a leg or a dict with Leg entries,
686 adds color, spin and massless entries, according to model"""
687 fksleg = FKSLeg(leg)
688 part = model.get('particle_dict')[leg['id']]
689 fksleg['color'] = part.get_color()
690 fksleg['charge'] = part.get_charge()
691 fksleg['massless'] = part['mass'].lower() == 'zero'
692 fksleg['spin'] = part.get('spin')
693 fksleg['is_part'] = part.get('is_part')
694 fksleg['self_antipart'] = part.get('self_antipart')
695 return fksleg
696
699 """given leglist, sets color and massless entries according to the model
700 variable.
701 return a FKSLeglist"""
702 fkslegs = FKSLegList()
703 for leg in leglist:
704 fkslegs.append(to_fks_leg(leg, model))
705 return fkslegs
706
709 """list of FKSLegs"""
710
712 """Test if object obj is a valid FKSLeg for the list."""
713 return isinstance(obj, FKSLeg)
714
715 - def sort(self,pert='QCD'):
716 """Sorting routine, sorting chosen to be optimal for madfks"""
717 sorted_leglist = FKSLegList()
718
719 initial_legs = FKSLegList([l for l in copy.copy(self) if not l['state']])
720
721 final_legs = FKSLegList([l for l in copy.copy(self) if l['state']])
722 if len(initial_legs) == 1:
723 sorted_leglist.extend(initial_legs)
724 elif len(initial_legs) == 2:
725 if initial_legs[0]['number'] > initial_legs[1]['number']:
726 initial_legs.reverse()
727 sorted_leglist.extend(initial_legs)
728 else:
729 raise FKSProcessError('Too many initial legs')
730
731 if pert == 'QCD':
732 color = 'color'
733 zero = 1
734 elif pert == 'QED':
735 color = 'charge'
736 zero = 0.
737 else:
738 raise FKSProcessError,"Only QCD and QED is allowed not %s"% pert
739 colors = sorted(set([abs(l[color]) for l in final_legs]))
740
741 if zero in colors:
742 sorted_leglist.extend(sorted(\
743 [l for l in final_legs if l[color] == zero], key = itemgetter('number')))
744 colors.remove(zero)
745
746
747 massless_dict = {}
748 massive_dict = {}
749 for col in colors:
750 col_legs = FKSLegList([l for l in final_legs if abs(l[color]) == col])
751
752 massive_dict[col] = [l for l in col_legs if not l['massless']]
753 massless_dict[col] = [l for l in col_legs if l['massless']]
754
755 for i_m, dict in enumerate([massive_dict, massless_dict]):
756 for col in colors:
757
758
759 if col == zero:
760 keys = [itemgetter('number'), itemgetter('number')]
761 reversing = False
762 else:
763 keys = [itemgetter('id'), itemgetter('id')]
764 reversing = True
765
766 init_pdg_legs = []
767 list = dict[col]
768 if len(initial_legs) == 2:
769
770 for i in range(len(set([ abs(l['id']) for l in initial_legs]))):
771 pdg = abs(initial_legs[i]['id'])
772 init_pdg_legs = [l for l in list if abs(l['id']) == pdg]
773 if init_pdg_legs:
774
775
776 init_pdg_legs.sort(key = keys[i_m], reverse=reversing)
777 sorted_leglist.extend(FKSLegList(init_pdg_legs))
778
779 init_pdgs = [ abs(l['id']) for l in initial_legs]
780 other_legs = [l for l in list if not abs(l['id']) in init_pdgs]
781 other_legs.sort(key = keys[i_m], reverse=reversing)
782 sorted_leglist.extend(FKSLegList(other_legs))
783 else:
784 list.sort(key = keys[i_m], reverse=reversing)
785 sorted_leglist.extend(FKSLegList(list))
786
787 for i, l in enumerate(sorted_leglist):
788 self[i] = l
789
793 """a class for FKS legs: it inherits from the ususal leg class, with two
794 extra keys in the dictionary:
795 -'fks', whose value can be 'i', 'j' or 'n' (for "normal" particles)
796 -'color', which gives the color of the leg
797 -'charge', which gives the charge of the leg
798 -'massless', boolean, true if leg is massless
799 -'spin' which gives the spin of leg
800 -'is_part', boolean, true if leg is an particle
801 -'self_antipart', boolean, true if leg is an self-conjugated particle
802 """
803
805 """Default values for all properties"""
806 super(FKSLeg, self).default_setup()
807
808 self['fks'] = 'n'
809 self['color'] = 0
810 self['charge'] = 0.
811 self['massless'] = True
812 self['spin'] = 0
813 self['is_part'] = True
814 self['self_antipart'] = False
815
817 """Return particle property names as a nicely sorted list."""
818 keys = super(FKSLeg, self).get_sorted_keys()
819 keys += ['fks', 'color','charge', 'massless', 'spin','is_part','self_antipart']
820 return keys
821
822
823 - def filter(self, name, value):
824 """Filter for valid leg property values."""
825
826 if name == 'fks':
827 if not isinstance(value, str):
828 raise self.PhysicsObjectError, \
829 "%s is not a valid string for leg fks flag" \
830 % str(value)
831 if name in ['color', 'spin']:
832 if not isinstance(value, int):
833 raise self.PhysicsObjectError, \
834 "%s is not a valid leg %s flag" % \
835 str(value),name
836
837 if name in ['massless','self_antipart','is_part']:
838 if not isinstance(value, bool):
839 raise self.PhysicsObjectError, \
840 "%s is not a valid boolean for leg flag %s" % \
841 str(value),name
842 if name is 'charge':
843 if not isinstance(value, float):
844 raise self.PhysicsObjectError, \
845 "%s is not a valid float for leg flag charge" \
846 % str(value)
847 return super(FKSLeg,self).filter(name, value)
848