Package madgraph :: Package madweight :: Module substructure_class
[hide private]
[frames] | no frames]

Source Code for Module madgraph.madweight.substructure_class

  1  #!/usr/bin/env python 
  2   
  3   
  4  try: 
  5      import madgraph.madweight.blob_solution as blob_solution 
  6  except ImportError: 
  7      import internal.madweight.blob_solution as blob_solution 
  8       
  9  Level_generation = blob_solution.Level_generation 
 10  Blob_solution = blob_solution.Blob_solution   
 11  Block_ECS =blob_solution.Block_ECS 
 12  Block_sector =blob_solution.Block_sector 
 13  Block_B =blob_solution.Block_B 
 14   
 15  import sys 
 16   
17 -class diagram:
18
19 - def __init__(self):
20 21 self.content={} 22 self.prop_content=[] 23 self.ext_content=[] 24 self.neut_content=[] 25 self.num_propa=0 26 self.ext_part=0 27 self.num_neut=0 28 self.config=0
29 30 31
32 - def add_content(self,MG_id,object):
33 "add a element in the diagram" 34 self.content[int(MG_id)]=object 35 36 if object.external and int(MG_id) > 2: 37 self.ext_content.append(object) 38 self.ext_part+=1 39 elif not object.external: 40 self.prop_content.append(object) 41 self.num_propa+=1
42 43
44 - def define_neut_content(self):
45 "define neutrino content" 46 self.neut_content=[] 47 for ExtPart in self.ext_content : 48 if(ExtPart.neutrino): 49 self.neut_content.append(ExtPart) 50 self.num_neut=len(self.neut_content)
51 52
53 - def define_level(self):
54 """ complete self.content[i].level:number a propa before a external particle, and the number of propa before 55 (with himself for a propa)""" 56 57 #level of a propagator 58 for i in range(1,self.num_propa+1): 59 propa=self.prop_content[-i] 60 61 if(propa.mother in self.prop_content and propa.channel=='S'): 62 propa.level=propa.mother.level+1 63 elif(propa.channel=='T'): 64 propa.level=0 65 else: 66 propa.level=1 67 #print propa.MG, propa.level 68 #level of initial particle 69 self.content[1].level=0 70 self.content[2].level=0 71 #level of an external particle 72 for ExtPart in self.ext_content: 73 if ExtPart.mother: 74 ExtPart.level=ExtPart.mother.level 75 else: 76 ExtPart.level=0
77 78
79 - def order_in_level(self):
80 "return list with external particle ordering following level" 81 82 #organise in level in a dictionary 83 dict_level_to_part={} 84 for particle in self.ext_content: 85 if particle.level in dict_level_to_part.keys(): 86 dict_level_to_part[particle.level].append(particle) 87 else: 88 dict_level_to_part[particle.level]=[particle] 89 90 #re-organise like a list 91 self.ext_content=[] 92 level=-1 93 while 1: 94 if len(dict_level_to_part)==0: 95 break 96 level+=1 97 self.ext_content+=dict_level_to_part.pop(level,[])
98
99 - def contains_particle(self,particle):
100 """ check if tha particle is in the diagram """ 101 #note that content is a dict or list depending of the object 102 if type(self.content)== dict: 103 if self.content.has_key(particle.MG): 104 return 1 105 else: 106 return 0 107 elif type(self.content)== list: 108 if particle in self.content: 109 return 1 110 else: 111 return 0
112 113 114
115 -class ECS_sector_no_multi_channel(diagram,Level_generation):
116 """ The ECS sector. 117 The parenty to Blob_solution is slightly dangerous, lot of variables are different, but some part are equivalent 118 lot of time ECS play the two role: Blob and Blob solution 119 """ 120
121 - def __init__(self,diag,chgt_var,neut_in_ecs,unaligned):
122 """ create the ECS SECTOR 123 neut_in_ecs are the fondamental particle of the class (and so not always neutrino) 124 """ 125 neut_in_class={'a':0,'b':1,'c':1,'d':2,'e':2,'f':2,'g':2} 126 intrinsec_in_class={'a':2,'b':1,'c':1,'d':2,'e':2,'f':2,'g':2}#number of particles used to restore E-p conservation 127 128 #initialization 129 diagram.__init__(self) 130 Level_generation.__init__(self,'ecs') 131 self.fuse=0 132 #store initial input 133 self.MG_sec=diag 134 self.chgt_var=chgt_var 135 if type(neut_in_ecs)==list: 136 self.main_content=neut_in_ecs 137 else: 138 self.main_content=[neut_in_ecs] 139 self.unaligned=unaligned 140 #construct more elaborate things 141 self.num_neut=neut_in_class[chgt_var] 142 self.intrinsec=intrinsec_in_class[chgt_var] #number of particles used to restore E-p conservation 143 self.opt=diag.opt
144
145 - def define_blob(self,diag,propa_in_ecs=""):
146 """ define the blob associated to this Enlarged constraint sector """ 147 148 if not propa_in_ecs: 149 propa_in_ecs=self.main_content 150 151 self.blob_content=[] 152 153 #define blob from the black box 154 155 156 #define all the mother of the one/two central particle of the ecs 157 for i in range(0,self.intrinsec): 158 159 #define a list of combine all mother 160 if i==0: 161 combine_all_mother=[] 162 combine_all_mother+=propa_in_ecs[i].all_mother() #not in one line (we doesn't want to have a pointer) 163 continue 164 #i>0 165 for mother in propa_in_ecs[i].all_mother(): 166 if mother not in combine_all_mother: 167 combine_all_mother.append(mother) 168 169 #define blob 170 for particle in combine_all_mother: 171 #print 'mother',particle.MG, len(combine_all_mother) 172 for desint in particle.des: 173 if desint not in combine_all_mother and desint not in propa_in_ecs: 174 blob_sector(desint,diag,ECS_sec=self) 175 176 #This technique is not complete for 'T' channel. In this case some branch are simply forget. 177 #add those branch 178 for i in range(-1*diag.num_propa,0): 179 propa=diag.content[i] 180 #first look at T Channel 181 if propa.channel=='T': 182 for desint in propa.des: 183 if desint.external: 184 if desint not in propa_in_ecs: 185 blob_sector(desint,diag,ECS_sec=self) 186 #at this point particle is propagator 187 elif(desint not in combine_all_mother): 188 blob_sector(desint,diag,ECS_sec=self) 189 #This technique fails for the 'free' branch => look at particle without mother 190 for particle in diag.prop_content+diag.ext_content: 191 if particle.mother==0: 192 if particle not in combine_all_mother and particle not in propa_in_ecs: 193 blob_sector(particle,diag,ECS_sec=self)
194 195 196
197 - def equivalent_ECS(self):
198 """ 1) define completely the change of variable for the enlarged ECS 199 -find which propagator aligned,... 200 2) define equivalent solution if any (B->C) 201 """ 202 203 if self.num_neut==0: 204 #option: authorize a! 205 if self.opt.use_ecs_a: 206 solution=Block_ECS(self,'a',self.main_content) 207 return [self] 208 else: 209 return [] 210 elif self.num_neut==1: 211 #option: authorize b or c! 212 if self.opt.use_ecs_b or self.opt.use_ecs_c: 213 output=self.equivalent_ECS_1neut() 214 return output 215 else: 216 return [] 217 else: 218 #two neutrino case 219 #option: authorize d or e or f! 220 if self.opt.use_ecs_d or self.opt.use_ecs_e or self.opt.use_ecs_f : 221 output=self.equivalent_ECS_2neut() 222 return output 223 else: 224 return []
225 226 227
228 - def equivalent_ECS_1neut(self,use_noresonant=0):
229 """ 1) define completly the change of variable for the enlarged ECS 230 -find which propagator aligned,... 231 2) define equivalent solution if any (B->C) 232 """ 233 # 1.1) ->search for the two thiner propagator+ check if we can pass in C change of variable 234 thiner=self.main_content[0].mother.width 235 part_thin=self.main_content[0].mother 236 thiner_bef_m0=500 #thiner propagator in ascendance of mass nul (for Case C) 237 thiner_m0=500 #thiner mother of a mass null particle (for Case C) 238 madeC=0 239 motherX=self.main_content[0] 240 241 while 1: 242 motherX=motherX.mother 243 if motherX==0: 244 break 245 246 if motherX.width<thiner and motherX.channel=='S': 247 thiner=motherX.width 248 part_thin=motherX 249 250 #check for C splitting: 251 try: 252 if motherX.twin.external and motherX.twin.mass==0: 253 if motherX.twin.tf_level>1 and motherX.channel=='S': 254 madeC=1 255 if motherX.mother.width<thiner_m0: 256 thiner_m0=motherX.mother.width 257 if thiner<thiner_bef_m0: 258 thiner_bef_m0=thiner 259 except: 260 pass 261 262 #1.2) ->create block and new ECS first for C change of variable secondly for B 263 if madeC: 264 New_sol=ECS_sector(self.MG_sec,'c',self.main_content,self.unaligned) 265 fuse_list=[] 266 motherX=self.main_content[0] 267 while motherX.width!=thiner_bef_m0: 268 fuse_list.append(motherX.twin) 269 motherX=motherX.mother 270 fuse_particle1=New_sol.define_fuse_region(fuse_list) 271 fuse_list=[] 272 while motherX.width!=thiner_m0: 273 fuse_list.append(motherX.twin) 274 motherX=motherX.mother 275 fuse_particle2=New_sol.define_fuse_region(fuse_list) 276 Block_ECS(New_sol,'c',self.main_content+[fuse_particle1,fuse_particle2]) 277 New_sol.order_block(New_sol) 278 279 280 # define B change of variable 281 fuse_list=[] 282 motherX=self.main_content[0] 283 while part_thin!=motherX: 284 fuse_list.append(motherX.twin) 285 motherX=motherX.mother 286 fuse_particle=self.define_fuse_region(fuse_list) 287 Block_ECS(self,'b',self.main_content+[fuse_particle]) 288 self.order_block(self) 289 290 #2) Check definition from option 291 sol=[] 292 if self.opt.use_ecs_b: 293 sol.append(self) 294 if madeC and self.opt.use_ecs_c: 295 sol.append(New_sol) 296 297 return sol
298 299 300
301 - def equivalent_ECS_2neut(self):
302 """ 1) define completly the change of variable for the enlarged ECS 303 -find which propagator aligned,... 304 Each change of variable are factorized!!! 305 """ 306 total_propa,lim1,lim2=self.main_content[0].unaligned_propa(self.main_content[1],0) 307 lim=[lim1,lim2] 308 fuse_particle=[] 309 # 310 # Enlarged constraint Sector D 311 # 312 if self.chgt_var=='d': 313 #check validity from option 314 if not self.opt.use_ecs_d: 315 return [] 316 #find the two thiner propagator for each neutrino 317 for i in [0,1]: 318 thiner=500 319 thiner2=600 320 #search thiner propa if option authorized 321 if self.opt.ecs_fuse: 322 motherX=self.main_content[i] 323 for j in range(0,lim[i]): 324 motherX=motherX.mother 325 if motherX.width<thiner and motherX.channel=='S': 326 thiner2=thiner 327 thiner=motherX.width 328 elif motherX.width<thiner2 and motherX.channel=='S': 329 thiner2=motherX.width 330 #check number of find solution and reassign 331 if thiner==500: #no propagator in S channel or don't use fuse 332 thiner=self.main_content[i].mother.width #order between thiner 333 thiner2=self.main_content[i].mother.mother.width #is irrelevant at this stage 334 if thiner2==500: #only one propagator in S channel 335 if thiner!=self.main_content[i].mother.width: 336 thiner2=self.main_content[i].mother.mother.width 337 elif self.main_content[i].mother.channel=='S_flat': 338 thiner2=self.main_content[i].mother.mother.width 339 else: 340 thiner2=self.main_content[i].mother.mother.width 341 342 #define fuse particle 343 motherX=self.main_content[i] 344 fuse_list=[] 345 fuse_with_this_neut=0 346 while fuse_with_this_neut<2: 347 fuse_list.append(motherX.twin) 348 motherX=motherX.mother 349 if motherX==0: 350 break 351 if motherX.width in [thiner,thiner2]: 352 fuse=self.define_fuse_region(fuse_list) 353 fuse_particle.append(fuse) 354 fuse_list=[] 355 fuse_with_this_neut+=1 356 Block_ECS(self,'d',self.main_content+fuse_particle) 357 self.order_block(self) 358 return [self] 359 # 360 # Enlarged constraint Sector E 361 # 362 elif self.chgt_var=='e': 363 #check validity from option 364 if not self.opt.use_ecs_e: 365 return [] 366 #find the two thiner propagator 367 for i in [0,1]: 368 #search thiner propagator if option authorized 369 if self.opt.ecs_fuse: 370 motherX=self.main_content[i].mother 371 thiner=motherX.width 372 for j in range(0,lim[i]-1): 373 motherX=motherX.mother 374 if motherX.width<thiner and motherX.channel=='S': 375 thiner=motherX.width 376 else: 377 thiner=self.main_content[i].mother.width 378 #define fuse particle 379 motherX=self.main_content[i] 380 fuse_list=[] 381 while 1: 382 fuse_list.append(motherX.twin) 383 motherX=motherX.mother 384 if motherX.width==thiner: 385 fuse=self.define_fuse_region(fuse_list) 386 fuse_particle.append(fuse) 387 break 388 a=Block_ECS(self,'e',self.main_content+fuse_particle) 389 self.order_block(self) 390 #print 'ECS E content: ', 391 #for particle in self.main_content+fuse_particle:#a.order_content: 392 # print particle.MG, 393 #print 394 return [self] 395 # 396 # Enlarged constraint Sector F 397 # 398 elif self.chgt_var=='f' or self.chgt_var=='g': 399 #check validity from option 400 if not self.opt.use_ecs_f: 401 return [] 402 #F change of variable can't have freedom to move those propagator 403 twin_part=[] 404 twin_part.append(self.main_content[0].twin) 405 twin_part.append(self.main_content[1].twin) 406 Block_ECS(self,self.chgt_var,self.main_content+twin_part) 407 self.order_block(self) 408 return [self]
409 410
412 """ take care of the position of the other neutrino in order to have a more 413 serious definition of the number of un-aligned variable 414 415 this routine is designed for update the 1 neutrino case 416 """ 417 418 control=0 #control of flux 419 for neutrino in self.main_content: 420 motherX=neutrino 421 #treat first zero neutrino case: ->particle following 422 if motherX.neutrino==0: 423 try: 424 neutrino2,step=motherX.twin.detect_neut_in_decay() 425 if step<3 and neutrino2: 426 self.unaligned+=3-step 427 except: 428 pass 429 #treat all case ->particle before main 430 while 1: 431 motherX=motherX.mother 432 if motherX==0: 433 break 434 435 try: 436 neutrino2,step=motherX.twin.detect_neut_in_decay() 437 except: 438 continue 439 if neutrino2==0: 440 continue 441 if neutrino2 in self.main_content: 442 control+=1 443 if control==2: 444 break 445 else: 446 continue 447 if step<3: 448 self.unaligned+=3-step
449 450
451 - def order_block(self,main_sec=''):
452 453 new_order=[] 454 step=1 455 while 1: 456 step+=1 457 if len(self.step)==1: 458 break 459 if step>20: 460 sys.exit('''ERROR: infinite loop detected in ECS_sector.order_block ''') 461 462 block=self.step.pop(0) 463 #print block 464 if block.chgt_var not in ['2','3']: 465 self.step.append(block) 466 else: 467 new_order.append(block) 468 new_order.append(self.step[0]) 469 self.step=new_order
470 471 472 473 474
475 - def info(self):
476 """ return some information about the ECS and the associated blob """ 477 num_in_part={'a':2,'b':2,'c':3,'d':6,'e':4,'f':4,'g':4} 478 479 text='\t** Enlarged Contraint Sector global information **\n\n' 480 text+= 'Class: '+self.chgt_var.upper()+'\n' 481 text+='particle in ECS : ' 482 for i in range(0,num_in_part[self.chgt_var]): 483 part=self.step[-1].order_content[i] 484 if i%3==0 and i!=0: 485 text+='\n\t\t\t\t ' 486 if part.external: 487 if part.neutrino: 488 text+=str(part.MG)+'(missing)\t' 489 else: 490 text+=str(part.MG)+'(visible)\t' 491 elif type(part.MG)==str: 492 text+=str(part.MG)+'(fuse)\t' 493 else: 494 text+=str(part.MG)+'(propagator)\t' 495 496 text+='\nblob linked are generated by :' 497 for blob in self.blob_content: 498 if blob.main.MG<0: 499 text+=str(blob.main.MG)+'\t' 500 text+='\n' 501 return text
502
503 - def __str__(self):
504 text= 'ECS info:' 505 text+= 'Class: '+str(self.chgt_var)+' particles in ECS : ' 506 for part in self.ext_content: 507 text+=str(part.MG)+'\t' 508 text+='|| linked blob(\'s): ' 509 try: 510 for blob in self.blob_content: 511 text+=str(blob.main.MG)+'\t' 512 except: 513 text+='not yet defined' 514 return text
515 516 517 518 519 520 521 522
523 -class blob_sector(diagram):
524 """ blob structure """ 525
526 - def __init__(self,particle,diag,ECS_sec=''):
527 """create completly a blob if he is not defined already """ 528 529 #Check if already defined + validity of the definition of a blob 530 if diag.blob_content.has_key(particle.MG): # check if the blob is already defined 531 self=diag.blob_content[particle.MG] 532 self.put_in_ecs(ECS_sec) 533 return #stop creation 534 elif particle.MG in range(0,diag.num_init):#remove initial particle from creating blob 535 return None 536 elif not particle.external: 537 if not particle.channel.startswith('S'): #remove T channel from creating a blob 538 return None 539 540 #creation of a new blob 541 diagram.__init__(self) 542 #put the main_diag up-to-date 543 diag.blob_content[particle.MG]=self 544 #put the ECS up-to-date 545 self.put_in_ecs(ECS_sec) 546 #put information in the blob 547 self.main=particle 548 self.generate_content() 549 self.solution=[] 550 #option 551 self.opt=diag.opt
552 553
554 - def put_in_ecs(self,ECS_sec):
555 """ put this blob in the blob content of ECS """ 556 #option put in ECS-blob content ->remark the blob is independant of the ECS 557 if ECS_sec: 558 if self not in ECS_sec.blob_content: 559 ECS_sec.blob_content.append(self)
560
561 - def generate_content(self):
562 """ import all the information for the blog """ 563 self.content=[self.main] 564 for particle in self.content: 565 if particle.external: 566 self.ext_content.append(particle) 567 self.ext_part+=1 568 if particle.neutrino: 569 self.neut_content.append(particle) 570 self.num_neut+=1 571 else: 572 self.prop_content.append(particle) 573 self.num_propa+=1 574 self.content+=particle.des 575 self.order_in_level()
576 #order in propa is not good ->change it? 577
578 - def find_solutions(self):
579 """ find a first solution to resolve the blob. 580 The idea is to take the more local possibility in all case 581 this is perhaps not the best solution but it's only the beginning of the resolution""" 582 sol1=Blob_solution(self) 583 sol1.find_all_solutions(self) 584 self.supress_identical_solution()
585 586
588 """ supress identical solution """ 589 590 del_sol=[] 591 for i in range(0,len(self.solution)): 592 for j in range(i+1,len(self.solution)): 593 if str(self.solution[i])==str(self.solution[j]): 594 del_sol.append(i) 595 break 596 for i in range(0,len(del_sol)): 597 del self.solution[del_sol[i]-i]
598 599
600 - def __str__(self):
601 text= 'Blob details: main '+str(self.main.MG)+'\n' 602 for solution in self.solution: 603 text+=str(solution)+'\n' 604 return text
605 606
607 -class ECS_sector(ECS_sector_no_multi_channel):
608 """ modify version of ECS sector, returning the different 609 possibility of unalignment in the black box 610 (usefull for multichannel mode) 611 """ 612
613 - def equivalent_ECS_1neut(self,use_noresonant=0):
614 """ 615 define completely the change of variable for the enlarged ECS 616 - return all the possible ECS changing the particles entering in the B case 617 - define equivalent soltution if any (B->C) 618 """ 619 620 sol=[] 621 fuse_list=[self.main_content[0].twin] #define the blob fuse 622 for propagator in self.main_content[0].all_mother(): 623 if propagator.channel.startswith('T'): 624 break 625 # define a B change of variable 626 if self.opt.use_ecs_b: 627 New_sol=ECS_sector(self.MG_sec,'b',self.main_content,self.unaligned) 628 fuse_particle=New_sol.define_fuse_region(fuse_list) 629 Block_ECS(New_sol,'b',self.main_content+[fuse_particle]) 630 New_sol.order_block(New_sol) 631 sol.append(New_sol) 632 633 #look for class C 634 if self.opt.use_ecs_c: 635 sol+=self.equivalent_ECS_passinC(propagator,fuse_list) 636 637 #update fuse for next level 638 fuse_list.append(propagator.twin) 639 640 641 return sol
642 643
644 - def equivalent_ECS_passinC(self,propa1,fuse1):
645 """ check if those information can create a C block and define it 646 propa1: first propagator than should enter in the C block 647 fuse1: list of particles following this propa and should be fuse 648 """ 649 650 particle2=propa1.twin 651 if not particle2 or particle2.mass: 652 return [] #the mass should be 0 653 if particle2.MG<3: 654 return [] 655 propa2=propa1.mother 656 if propa2 == 0 or propa2.channel.startswith('T'): 657 return [] #not enough propa remaining 658 659 New_sol=ECS_sector(self.MG_sec,'c',self.main_content,self.unaligned) 660 fuse=self.define_fuse_region(fuse1) 661 Block_ECS(New_sol,'c',self.main_content+[fuse,particle2]) 662 New_sol.order_block(New_sol) 663 664 return [New_sol]
665
666 - def equivalent_ECS_2neut(self):
667 """ 1) define completely the change of variable for the enlarged ECS 668 -find which propagator aligned,... 669 Each change of variable are factorized!!! 670 """ 671 672 if self.chgt_var!='d': 673 return ECS_sector_no_multi_channel.equivalent_ECS_2neut(self) 674 675 if not self.opt.use_ecs_d: 676 return [] 677 678 sol=[] 679 680 681 682 possible_propa_1=[propa for propa in self.main_content[0].all_mother() \ 683 if propa not in self.main_content[1].all_mother() ] 684 possible_propa_2=[propa for propa in self.main_content[1].all_mother() \ 685 if propa not in self.main_content[0].all_mother() ] 686 687 fuse_list1_1=[self.main_content[0].twin] #define the blob fuse 688 for propagator1_1 in possible_propa_1: 689 fuse_list1_2=[propagator1_1.twin] 690 for propagator1_2 in propagator1_1.all_mother(): 691 if propagator1_2 not in possible_propa_1 or propagator1_2.channel.startswith('T'): 692 break 693 fuse_list2_1= [self.main_content[1].twin] #define the blob fuse 694 for propagator2_1 in possible_propa_2: 695 fuse_list2_2=[propagator2_1.twin] 696 for propagator2_2 in propagator2_1.all_mother(): 697 if propagator2_2 not in possible_propa_2 or propagator2_2.channel.startswith('T'): 698 break 699 propagator=[propagator1_1,propagator1_2,propagator2_1,propagator2_2] 700 fuse=[fuse_list1_1,fuse_list1_2,fuse_list2_1,fuse_list2_2] 701 sol+=self.define_new_ecs_d(propagator,fuse) 702 703 fuse_list2_2.append(propagator2_2.twin) 704 fuse_list2_1.append(propagator2_1.twin) 705 fuse_list1_2.append(propagator1_2.twin) 706 fuse_list1_1.append(propagator1_1.twin) 707 708 return sol
709
710 - def define_new_ecs_d(self,propagator,fuse):
711 """ return a valid object for this change of variable """ 712 713 for propa in propagator: 714 if propa.channel.startswith('T'): 715 return [] 716 717 fuse_particle=[] 718 for data in fuse: 719 fuse_particle.append(self.define_fuse_region(data)) 720 for particule in fuse_particle: 721 if particule.MG in [1,2]: 722 return [] 723 724 725 New_sol=ECS_sector(self.MG_sec,'d',self.main_content,self.unaligned) 726 Block_ECS(New_sol,'d',self.main_content+fuse_particle) 727 New_sol.order_block(New_sol) 728 return [New_sol]
729