Package madgraph :: Package fks :: Module fks_common
[hide private]
[frames] | no frames]

Source Code for Module madgraph.fks.fks_common

  1  ################################################################################ 
  2  # 
  3  # Copyright (c) 2009 The MadGraph5_aMC@NLO Development team and Contributors 
  4  # 
  5  # This file is a part of the MadGraph5_aMC@NLO project, an application which  
  6  # automatically generates Feynman diagrams and matrix elements for arbitrary 
  7  # high-energy processes in the Standard Model and beyond. 
  8  # 
  9  # It is subject to the MadGraph5_aMC@NLO license which should accompany this  
 10  # distribution. 
 11  # 
 12  # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch 
 13  # 
 14  ################################################################################ 
 15   
 16  """Definitions of the objects needed both for MadFKS from real  
 17  and MadFKS from born""" 
 18   
 19  from __future__ import absolute_import 
 20  from __future__ import print_function 
 21  import madgraph.core.base_objects as MG 
 22  import madgraph.core.helas_objects as helas_objects 
 23  import madgraph.core.diagram_generation as diagram_generation 
 24  import madgraph.core.color_amp as color_amp 
 25  import madgraph.core.color_algebra as color_algebra 
 26  import madgraph.various.misc as misc 
 27  from operator import itemgetter 
 28  import copy 
 29  import logging 
 30  import array 
 31  import fractions 
 32  import six 
 33  from six.moves import range 
34 35 36 37 -class FKSProcessError(Exception):
38 """Exception for MadFKS""" 39 pass
40
41 42 -class FKSDiagramTag(diagram_generation.DiagramTag): #test written
43 """Modified diagram tags to be used to link born and real configurations. 44 """ 45 46 @staticmethod 53
54 55 -def get_qed_qcd_orders_from_weighted(nexternal, hierarchy, weighted):
56 """computes the QED/QCD orders from the knowledge of the n of ext particles 57 and of the weighted orders""" 58 qed_w = hierarchy['QED'] 59 qcd_w = hierarchy['QCD'] 60 # n vertices = nexternal - 2 =QED + QCD 61 # weighted = qed_w*QED + qcd_w*QCD 62 63 QED = (weighted - qcd_w * (nexternal - 2) ) / (qed_w - qcd_w) 64 QCD = (weighted - qed_w * QED) / qcd_w 65 return int(QED), int(QCD)
66 238
239 240 241 -def find_orders(amp): #test_written
242 """Takes an amplitude as input, and returns a dictionary with the 243 orders of the couplings. 244 """ 245 assert isinstance(amp, diagram_generation.Amplitude) 246 orders = {} 247 for diag in amp.get('diagrams'): 248 for order, value in diag.get('orders').items(): 249 if value != 0 or order in list(amp['process']['orders'].keys()): 250 try: 251 orders[order] = max(orders[order], value) 252 except KeyError: 253 orders[order] = value 254 return orders 255
256 257 -def find_splittings(leg, model, dict, pert='QCD', include_init_leptons=True): #test written
258 """Finds the possible splittings corresponding to leg 259 """ 260 261 leptons = model.get_lepton_pdgs() 262 263 if dict == {}: 264 dict = find_pert_particles_interactions(model, pert) 265 splittings = [] 266 #check that the leg is a qcd leg 267 268 if leg.get('id') in dict['pert_particles']: 269 part = model.get('particle_dict')[leg.get('id')] 270 antipart = model.get('particle_dict')[part.get_anti_pdg_code()] 271 for ii in dict['interactions']: 272 #check which interactions contain leg and at least one soft particles: 273 parts = copy.deepcopy(ii['particles']) 274 nsoft = 0 275 if part in parts: 276 #try to pop the ANTI-particle of part from the interaction 277 #if not there, pop part 278 try: 279 parts.pop(parts.index(antipart)) 280 except ValueError: 281 parts.pop(parts.index(part)) 282 for p in parts: 283 if p.get_pdg_code() in dict['soft_particles']: 284 nsoft += 1 285 if nsoft >= 1: 286 for split in split_leg(leg, parts, model): 287 # add the splitting, but check if there is 288 # an initial-state lepton if the flag 289 # include_init_leptons is False 290 if include_init_leptons or \ 291 not (any([l['id'] in leptons for l in split if not l['state']])): 292 splittings.append(split) 293 return splittings 294
295 296 -def find_mothers(leg1, leg2, model, dict={}, pert='', mom_mass=''):
297 """Find the possible mothers of leg1, leg2. 298 If mom_mass is passed, only the mothers with mom_mass are returned 299 """ 300 if pert: 301 if dict == {}: 302 dict = find_pert_particles_interactions(model, pert) 303 interactions = dict['interactions'] 304 mothers = [] 305 306 for inte in interactions: 307 # loop over interactions which contain leg1 and leg2 308 # and add the third particle to mothers 309 pdgs = [p.get_pdg_code() for p in inte['particles']] 310 try: 311 for l in [leg1, leg2]: 312 if not l['state']: 313 pdgs.remove(l['id']) 314 else: 315 pdgs.remove(model.get('particle_dict')[l['id']].get_anti_pdg_code()) 316 except ValueError: 317 continue 318 if mom_mass and \ 319 mom_mass.lower() == model.get('particle_dict')[pdgs[0]]['mass'].lower(): 320 mothers.append(pdgs[0]) 321 322 return mothers
323
324 325 -def split_leg(leg, parts, model): #test written
326 """Splits the leg into parts, and returns the two new legs. 327 """ 328 #for an outgoing leg take the antiparticles 329 split = [] 330 #for a final state particle one can have only a splitting 331 if leg['state'] : 332 split.append([]) 333 for part in parts: 334 split[-1].append(to_fks_leg({'state': True, \ 335 'id': part.get_pdg_code()},model)) 336 ij_final(split[-1]) 337 #while for an initial state particle one can have two splittings 338 # if the two partons are different 339 else: 340 if parts[0] != parts[1]: 341 for part in parts: 342 cparts = copy.deepcopy(parts) 343 split.append([\ 344 to_fks_leg({'state': False, 345 'id': cparts.pop(cparts.index(part)).get_pdg_code(), 346 'fks': 'j'}, model), 347 to_fks_leg({'state': True, 348 'id': cparts[0].get_anti_pdg_code(), 349 'fks': 'i'}, model)\ 350 ]) 351 else: 352 split.append([\ 353 to_fks_leg({'state': False, 354 'id': parts[0].get_pdg_code(), 355 'fks': 'j'}, model), 356 to_fks_leg({'state': True, 357 'id': parts[1].get_anti_pdg_code(), 358 'fks': 'i'}, model)]) 359 return split 360
361 362 -def ij_final(pair):
363 """given a pair of legs in the final state, assigns the i/j fks id 364 NOTE: the j partons is always put before the i one 365 """ 366 #if a massless bosonic particle is in the pair, it is i 367 #else by convention the anti-particle is labeled i 368 #the order of the splitting is [ j, i] 369 if len(pair) == 2: 370 for i in range(len(pair)): 371 set = 0 372 if (pair[i]['massless'] and pair[i]['self_antipart']) or \ 373 (not pair[i]['is_part'] and pair[1-i]['is_part'] and\ 374 (pair[i]['spin']+pair[1-i]['spin'])%2==0) and not set: 375 pair[i]['fks'] = 'i' 376 pair[1-i]['fks'] = 'j' 377 #check that first j then i 378 if i < 1 - i: 379 pair.reverse() 380 set = 1
381
382 -def insert_legs(leglist_orig, leg, split,pert='QCD'):
383 """Returns a new leglist with leg splitted into split. 384 The convention is to remove leg ij, replace it with leg j, and put 385 i at the end of the group of legs with the same color(charge) representation 386 """ 387 if pert =='QCD': 388 color = 'color' 389 elif pert == 'QED': 390 color = 'charge' 391 else: 392 raise FKSProcessError("Only QCD or QED is allowed not %s" % pert) 393 # the deepcopy statement is crucial 394 leglist = FKSLegList(copy.deepcopy(leglist_orig)) 395 #find the position of the first final state leg 396 for i in range(len(leglist)): 397 if leglist[-i - 1].get('state'): 398 firstfinal = len(leglist) - i - 1 399 # replace leg with leg_j (split[0]) 400 leglist[leglist.index(leg)] = split[0] 401 # and find where to insert i (split[1]) 402 col_maxindex = {} 403 mass_col_maxindex = {} 404 for col in set([l[color] for l in leglist[firstfinal:] if l['massless']]): 405 col_maxindex[col] = max([0] + [leglist.index(l) for l in leglist[firstfinal:]\ 406 if l[color] == col and l['massless']]) 407 for col in set([abs(l[color]) for l in leglist[firstfinal:] if not l['massless']]): 408 mass_col_maxindex[col] = max([0] + [leglist.index(l) for l in leglist[firstfinal:]\ 409 if abs(l[color]) == col and not l['massless']]) 410 #no need to keep info on particles with color > i 411 if pert == 'QCD': 412 for col in copy.copy(list(col_maxindex.keys())): 413 if abs(col) > abs(split[1][color]): 414 del col_maxindex[col] 415 ### for col in copy.copy(mass_col_maxindex.keys()): 416 ### if abs(col) > abs(split[1][color]): 417 ### del mass_col_maxindex[col] 418 #also remove antiquarks if i is a quark or a fermion 419 if split[1]['is_part'] and not split[1]['self_antipart']: 420 # In old MADFKS5, the line below was used instead. It is however equivalent in principle. 421 # We can remove this comment and the line below altogether after validation and complete 422 # merge of the EW branch in aMC@NLO trunk. 423 #if split[1][color] > 0: 424 try: 425 del col_maxindex[-split[1][color]] 426 except KeyError: 427 pass 428 #so now the maximum of the max_col entries should be the position to insert leg i 429 leglist.insert(max(list(col_maxindex.values()) + list(mass_col_maxindex.values()) + [firstfinal - 1] ) + 1, split[1]) 430 ### leglist.insert(max(col_maxindex.values() + [firstfinal - 1] ) + 1, split[1]) 431 # for sleg in split: 432 # leglist.insert(i, sleg) 433 # #keep track of the number for initial state legs 434 # #if not sleg.get('state') and not leg.get('state'): 435 # leglist[i]['number'] = leg['number'] 436 # i += 1 437 # if i < firstfinal: 438 # i = firstfinal 439 # 440 # leglist.sort() 441 for i, leg in enumerate(leglist): 442 leg['number'] = i + 1 443 return leglist
444
445 446 -def combine_ij( i, j, model, dict, pert='QCD'): #test written
447 """checks whether FKSlegs i and j can be combined together in the given model 448 and with given perturbation order and if so combines them into ij. 449 If dict is empty it is initialized with find_pert_particles_interactions 450 """ 451 if dict == {}: 452 dict = find_pert_particles_interactions(model, pert) 453 ij = [] 454 num = copy.copy(min(i.get('number'), j.get('number'))) 455 456 # we do not want j being a massless vector unless also i is or j is initial 457 not_double_counting = (j.get('spin') == 3 and j.get('massless') and 458 i.get('spin') == 3 and i.get('massless')) or \ 459 j.get('spin') != 3 or not j.get('massless') or \ 460 not j.get('state') 461 462 #if i and j are a final state particle and antiparticle pair, 463 # then we want i to be antipart and j to be 464 if j.get('state') and j.get('id') == - i.get('id'): 465 not_double_counting = not_double_counting and j.get('id') >0 466 467 if i.get('id') in dict['soft_particles'] and \ 468 j.get('id') in dict['pert_particles'] and \ 469 i.get('state') and not_double_counting: 470 for int in dict['interactions']: 471 parts= copy.copy(int['particles']) 472 #remove i 473 try: 474 parts.remove(model.get('particle_dict')[i.get('id')]) 475 except ValueError: 476 continue 477 478 #remove j if final state, anti j if initial state 479 if j.get('state'): 480 j_id = j.get('id') 481 else: 482 j_id = model.get('particle_dict')[j.get('id')].get_anti_pdg_code() 483 try: 484 parts.remove(model.get('particle_dict')[j_id]) 485 except ValueError: 486 continue 487 488 #ij is what remains if j is initial, the anti of if j is final 489 if j.get('state'): 490 ij.append(MG.Leg({ 491 'id': parts[0].get_anti_pdg_code(), 492 'state': True, 493 'number': num})) 494 else: 495 ij.append(MG.Leg({ 496 'id': parts[0].get_pdg_code(), 497 'state': False, 498 'number': num})) 499 return to_fks_legs(ij, model) 500
501 502 -def find_pert_particles_interactions(model, pert_order = 'QCD'): #test written
503 """given a model and pert_order, returns a dictionary with as entries: 504 --interactions : the interactions of order pert_order 505 --pert_particles : pdgs of particles taking part to interactions 506 --soft_particles : pdgs of massless particles in pert_particles 507 """ 508 #ghost_list = [82, -82] # make sure ghost_list is non-empty 509 ghost_list = [] 510 ghost_list += [ p.get_pdg_code() for p in model.get('particles') 511 if p.get('ghost') or p.get('goldstone')] 512 513 qcd_inter = MG.InteractionList() 514 pert_parts = [] 515 soft_parts = [] 516 for i, ii in model.get('interaction_dict').items(): 517 # i want interections of pert_order: 1 (from LO to NLO), 518 # without any other orders 519 # and of "base" type 520 if ii.get('type') != 'base': continue 521 522 if ii.get('orders') == {pert_order:1} and len(ii['particles']) == 3 : 523 masslist = [p.get('mass').lower() for p in ii['particles']] 524 525 # require that at least one particle be soft and of even spin for the interaction to be IR singular 526 found_soft_even_spin_particle = False 527 for p in ii['particles']: 528 if p.get('mass').lower()=='zero': 529 if p.get('spin')%2==1: 530 found_soft_even_spin_particle = True 531 break 532 if not found_soft_even_spin_particle: 533 continue 534 535 # check that there is at least a massless particle, and that the 536 # remaining ones have the same mass 537 # (otherwise the real emission final state will not be degenerate 538 # with the born one 539 try: 540 masslist.remove('zero') 541 except ValueError: 542 continue 543 if len(set(masslist)) == 1 and not \ 544 any( [ p.get_pdg_code() in ghost_list or \ 545 p.get_anti_pdg_code() in ghost_list for p in ii['particles']]) : 546 qcd_inter.append(ii) 547 for pp in ii['particles']: 548 pert_parts.append(pp.get_pdg_code()) 549 if pp['mass'].lower() == 'zero': 550 soft_parts.append(pp.get_pdg_code()) 551 552 return {'interactions': sorted(qcd_inter, key=misc.cmp_to_key(misc.dict_cmp)), 553 'pert_particles': sorted(set(pert_parts)), 554 'soft_particles': sorted(set(soft_parts))} 555 558 """insert the color links in col_obj: returns a list of dictionaries 559 (one for each link) with the following entries: 560 --link: the numbers of the linked legs 561 --link_basis: the linked color basis 562 --link_matrix: the color matrix created from the original basis and the linked one 563 """ 564 assert isinstance(col_basis, color_amp.ColorBasis) 565 assert isinstance(col_obj, list) 566 result =[] 567 for link in links: 568 this = {} 569 #define the link 570 l =[] 571 for leg in link['legs']: 572 l.append(leg.get('number')) 573 this['link'] = l 574 575 #replace the indices in col_obj of the linked legs according to 576 # link['replacements'] 577 # and extend-> product the color strings 578 579 this_col_obj = [] 580 for old_dict in col_obj: 581 new_dict = dict(old_dict) 582 for k, string in new_dict.items(): 583 new_dict[k] = string.create_copy() 584 for col in new_dict[k]: 585 for ind in col: 586 for pair in link['replacements']: 587 if ind == pair[0]: 588 col[col.index(ind)] = pair[1] 589 new_dict[k].product(link['string']) 590 this_col_obj.append(new_dict) 591 basis_link = color_amp.ColorBasis() 592 for ind, new_dict in enumerate(this_col_obj): 593 basis_link.update_color_basis(new_dict, ind) 594 595 this['link_basis'] = basis_link 596 this['link_matrix'] = color_amp.ColorMatrix(col_basis,basis_link) 597 result.append(this) 598 basis_orig = color_amp.ColorBasis() 599 for ind, new_dict in enumerate(col_obj): 600 basis_orig.update_color_basis(new_dict, ind) 601 602 for link in result: 603 link['orig_basis'] = basis_orig 604 return result 605 609 """Finds all the possible color(charge) links between any 610 two legs of the born. 611 If symm is true, only half of the color links are generated, those 612 for which leg1['number'] <= leg2['number'] 613 """ 614 if pert == 'QCD': 615 color = 'color' 616 zero = 1 617 elif pert == 'QED': 618 color = 'charge' 619 zero = 0. 620 else: 621 raise FKSProcessError("Only QCD or QED is allowed not %s" % pert) 622 color_links = [] 623 for leg1 in leglist: 624 for leg2 in leglist: 625 #legs must be colored(charged) and different, unless massive 626 if (leg1.get(color) != zero and leg2.get(color) != zero) \ 627 and (leg1 != leg2 or not leg1.get('massless')): 628 if not symm or leg1['number'] <= leg2['number']: 629 col_dict = legs_to_color_link_string(leg1,leg2,pert = pert) 630 color_links.append({ 631 'legs': [leg1, leg2], 632 'string': col_dict['string'], 633 'replacements': col_dict['replacements']}) 634 635 return color_links 636 639 """given two FKSlegs, returns a dictionary containing: 640 --string: the color link between the two particles, to be appended to 641 the old color string 642 extra minus or 1/2 factor are included as it was done in MadDipole 643 --replacements: a pair of lists containing the replacements of the color 644 indices in the old string to match the link 645 """ 646 #the second-to-last index of the t is the triplet, 647 # the last is the anti-triplet 648 649 legs = FKSLegList([leg1, leg2]) 650 dict = {} 651 min_index = -3000 652 iglu = min_index*2 653 string = color_algebra.ColorString() 654 replacements = [] 655 if pert == 'QCD': 656 if leg1 != leg2: 657 for leg in legs: 658 min_index -= 1 659 num = leg.get('number') 660 replacements.append([num, min_index]) 661 icol = 1 662 if not leg.get('state'): 663 icol = - 1 664 if leg.get('color') * icol == 3: 665 string.product(color_algebra.ColorString([ 666 color_algebra.T(iglu, num, min_index)])) 667 string.coeff = string.coeff * (-1) 668 elif leg.get('color') * icol == - 3: 669 string.product(color_algebra.ColorString([ 670 color_algebra.T(iglu, min_index, num)])) 671 elif leg.get('color') == 8: 672 string.product(color_algebra.ColorString(init_list = [ 673 color_algebra.f(min_index,iglu,num)], 674 is_imaginary =True)) 675 676 else: 677 icol = 1 678 if not leg1.get('state'): 679 icol = - 1 680 num = leg1.get('number') 681 replacements.append([num, min_index -1]) 682 if leg1.get('color') * icol == 3: 683 string = color_algebra.ColorString( 684 [color_algebra.T(iglu, iglu, num, min_index -1)]) 685 elif leg1.get('color') * icol == - 3: 686 string = color_algebra.ColorString( 687 [color_algebra.T(iglu, iglu, min_index-1, num)]) 688 elif leg1.get('color') == 8: 689 string = color_algebra.ColorString(init_list = [ 690 color_algebra.f(min_index-1,iglu,min_index)], 691 is_imaginary =True) 692 string.product(color_algebra.ColorString(init_list = [ 693 color_algebra.f(min_index,iglu,num)], 694 is_imaginary =True)) 695 string.coeff = string.coeff * fractions.Fraction(1, 2) 696 697 elif pert == 'QED': 698 for leg in legs: 699 # make it a fraction 700 string.coeff = string.coeff * fractions.Fraction(leg['charge']*3.)*\ 701 fractions.Fraction(1,3) 702 else: 703 raise FKSProcessError("Only QCD or QED is allowed not %s"% pert) 704 705 dict['replacements'] = replacements 706 dict['string'] = string 707 return dict 708
709 710 -def sort_proc(process,pert = 'QCD'):
711 """Given a process, this function returns the same process 712 but with sorted FKSLegs. 713 """ 714 leglist = to_fks_legs(process.get('legs'), process.get('model')) 715 leglist.sort(pert = pert) 716 for n, leg in enumerate(leglist): 717 leg['number'] = n + 1 718 process['legs'] = leglist 719 # add this line to pass ./test_managers.py -p A test_check_ppzjj 720 process['legs_with_decays']=MG.LegList() 721 722 return process
723
724 725 -def to_leg(fksleg):
726 """Given a FKSLeg, returns the original Leg. 727 """ 728 leg = MG.Leg( \ 729 {'id': fksleg.get('id'), 730 'number': fksleg.get('number'), 731 'state': fksleg.get('state'), 732 'from_group': fksleg.get('from_group'), 733 'polarization': fksleg.get('polarization') 734 }) 735 return leg
736
737 738 -def to_legs(fkslegs):
739 """Given a FKSLegList, returns the corresponding LegList. 740 """ 741 leglist = MG.LegList() 742 for leg in fkslegs: 743 leglist.append(to_leg(leg)) 744 return leglist
745
746 747 -def to_fks_leg(leg, model): #test written
748 """Given a leg or a dict with Leg entries, 749 adds color, spin and massless entries, according to model""" 750 fksleg = FKSLeg(leg) 751 part = model.get('particle_dict')[leg['id']] 752 fksleg['color'] = part.get_color() 753 fksleg['charge'] = part.get_charge() 754 fksleg['massless'] = part['mass'].lower() == 'zero' 755 fksleg['spin'] = part.get('spin') 756 fksleg['is_part'] = part.get('is_part') 757 fksleg['self_antipart'] = part.get('self_antipart') 758 return fksleg 759
760 761 -def to_fks_legs(leglist, model): #test written
762 """given leglist, sets color and massless entries according to the model 763 variable. 764 return a FKSLeglist""" 765 fkslegs = FKSLegList() 766 for leg in leglist: 767 fkslegs.append(to_fks_leg(leg, model)) 768 return fkslegs 769
770 771 -class FKSLegList(MG.LegList):
772 """list of FKSLegs""" 773
774 - def is_valid_element(self, obj):
775 """Test if object obj is a valid FKSLeg for the list.""" 776 return isinstance(obj, FKSLeg)
777 778
779 - def sort(self,pert='QCD'):
780 """Sorting routine, sorting chosen to be optimal for madfks""" 781 sorted_leglist = FKSLegList() 782 #find initial state legs 783 initial_legs = FKSLegList([l for l in copy.copy(self) if not l['state']]) 784 #find final state legs 785 final_legs = FKSLegList([l for l in copy.copy(self) if l['state']]) 786 if len(initial_legs) == 1: 787 sorted_leglist.extend(initial_legs) 788 elif len(initial_legs) == 2: 789 if initial_legs[0]['number'] > initial_legs[1]['number']: 790 initial_legs.reverse() 791 sorted_leglist.extend(initial_legs) 792 else: 793 raise FKSProcessError('Too many initial legs') 794 #find color representations 795 # order according to spin and mass 796 #find massive and massless legs 797 massive_legs = [l for l in final_legs if not l['massless']] 798 massless_legs = [l for l in final_legs if l['massless']] 799 800 for leglist in [massive_legs, massless_legs]: 801 spins = sorted(set([abs(l['spin']) for l in leglist])) 802 for spin in spins: 803 spin_legs = FKSLegList([l for l in leglist if abs(l['spin']) == spin]) 804 init_pdg_legs = [] 805 if len(initial_legs) == 2: 806 #put first legs which have the same abs(pdg) of the initial ones 807 for j in range(len(set([ abs(l['id']) for l in initial_legs]))): 808 pdg = abs(initial_legs[j]['id']) 809 init_pdg_legs = [l for l in spin_legs if abs(l['id']) == pdg] 810 if init_pdg_legs: 811 # sort in order to put first quarks then antiparticles, 812 # and to put fks partons as n j i 813 init_pdg_legs.sort(key = itemgetter('id'), reverse=True) 814 sorted_leglist.extend(FKSLegList(init_pdg_legs)) 815 816 init_pdgs = [ abs(l['id']) for l in initial_legs] 817 other_legs = [l for l in spin_legs if not abs(l['id']) in init_pdgs] 818 other_legs.sort(key = itemgetter('id'), reverse=True) 819 sorted_leglist.extend(FKSLegList(other_legs)) 820 else: 821 #llist.sort(key = itemgetter('id'), reverse=True) 822 sorted_leglist.extend(FKSLegList(spin_legs)) 823 824 for i, l in enumerate(sorted_leglist): 825 self[i] = l
826
827 828 -class FKSLeg(MG.Leg):
829 """a class for FKS legs: it inherits from the ususal leg class, with two 830 extra keys in the dictionary: 831 -'fks', whose value can be 'i', 'j' or 'n' (for "normal" particles) 832 -'color', which gives the color of the leg 833 -'charge', which gives the charge of the leg 834 -'massless', boolean, true if leg is massless 835 -'spin' which gives the spin of leg 836 -'is_part', boolean, true if leg is an particle 837 -'self_antipart', boolean, true if leg is an self-conjugated particle 838 """ 839
840 - def default_setup(self):
841 """Default values for all properties""" 842 super(FKSLeg, self).default_setup() 843 844 self['fks'] = 'n' 845 self['color'] = 0 846 self['charge'] = 0. 847 self['massless'] = True 848 self['spin'] = 0 849 self['is_part'] = True 850 self['self_antipart'] = False
851
852 - def get_sorted_keys(self):
853 """Return particle property names as a nicely sorted list.""" 854 keys = super(FKSLeg, self).get_sorted_keys() 855 keys += ['fks', 'color','charge', 'massless', 'spin','is_part','self_antipart'] 856 return keys
857 858
859 - def filter(self, name, value):
860 """Filter for valid leg property values.""" 861 862 if name == 'fks': 863 if not isinstance(value, str): 864 raise self.PhysicsObjectError("%s is not a valid string for leg fks flag" \ 865 % str(value)) 866 if name in ['color', 'spin']: 867 if not isinstance(value, int): 868 six.reraise(self.PhysicsObjectError, "%s is not a valid leg %s flag" % \ 869 str(value), name) 870 871 if name in ['massless','self_antipart','is_part']: 872 if not isinstance(value, bool): 873 six.reraise(self.PhysicsObjectError, "%s is not a valid boolean for leg flag %s" % \ 874 str(value), name) 875 if name == 'charge': 876 if not isinstance(value, float): 877 raise self.PhysicsObjectError("%s is not a valid float for leg flag charge" \ 878 % str(value)) 879 return super(FKSLeg,self).filter(name, value)
880