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

Source Code for Module madgraph.madweight.blob_solution

  1  #!/usr/bin/env python 
  2   
  3  from __future__ import absolute_import 
  4  from __future__ import print_function 
  5  import six 
  6  from six.moves import range 
  7  try: 
  8      import madgraph.madweight.particle_class as particle_class 
  9      import madgraph.various.misc as misc 
 10  except ImportError: 
 11      import internal.madweight.particle_class as particle_class 
 12      import internal.misc as misc 
 13  Particle = particle_class.Particle 
 14   
 15  import sys 
 16   
17 -class Level_generation:
18 """ define generic tool for maintained how to generate a sequential change of variable 19 this class in only defined in order to have common routine for ECS_sector and Blob-solution 20 """ 21
22 - def __init__(self,tag,def_step=0):
23 """init generic variable """ 24 self.num_fuse=0 25 self.sol_tag=tag 26 27 if def_step: 28 if type(def_step)==list: 29 self.step=def_step 30 else: 31 self.step=[def_step] 32 else: 33 self.step=[]
34 35 36 37
38 - def define_fuse_region(self,fuse_list,output_mode=1):
39 """ define a fuse part(Block '2' but with new particle) for the particle in the list 40 output_mode=1: return the particle 41 output_mode=2: return the particle and the unaligned propagator 42 """ 43 lowercase='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' 44 fuse_list_=list(fuse_list) 45 46 unaligned=[] 47 while 1: 48 if len(fuse_list_)==1: 49 break 50 if output_mode==1: return fuse_list_[0] 51 else: return fuse_list_[0],unaligned 52 else: 53 part1=fuse_list_.pop(0) 54 part2=fuse_list_.pop(0) 55 fuse_particle=Particle(lowercase[self.num_fuse],0,fuse=1) 56 fuse_particle.level=part1.level 57 if part1.level<part2.level: 58 fuse_particle.mother=part1.mother 59 unaligned.append(part2.mother) 60 else: 61 fuse_particle.mother=part2.mother 62 unaligned.append(part1.mother) 63 self.num_fuse+=1 64 fuse_list_.append(fuse_particle) 65 66 if(self.sol_tag=='blob'): 67 Block_B(self,'3',[part1,part2],fuse_particle) 68 else: 69 Block_sector(self,'3',[part1,part2],fuse_particle) 70 71 if output_mode==1: 72 return fuse_list_[0] #if we are out of the loop this means that the fuse is complete and fuse has only one element 73 else: 74 return fuse_list_[0],unaligned
75
76 - def order_block(self,main_sec):
77 """ (re)ordrer so that the new order follow the generation order """ 78 79 new_order=[] 80 #ready: particle who can enter in change of variable 81 ready=[] 82 ready+=main_sec.ext_content 83 control=0 #to avoid infinite loop 84 #print 'enter in ordering block routine' 85 while 1: 86 if len(self.step)==0:# or self.step==[blob_sec.main]: 87 #print 'reordering complete' 88 break 89 control+=1 90 if control>len(self.step)+1: #check if we have looked at all possibility without finding solution 91 sys.exit('ERROR: infinite loop detected in Level_generation.order_block()') 92 #print 'ready status:', 93 #for particle in ready: 94 # print particle.MG, 95 #print '\ncontinue: block still to order ',len(self.step),':', 96 #for block in self.step: 97 # print block 98 #print 99 block=self.step.pop(0) 100 for particle in block.in_part: 101 if particle not in ready: 102 self.step.append(block) 103 suceed=0 104 #print 'failed', particle.MG 105 break 106 else: 107 suceed=1 108 109 if not suceed: 110 continue 111 #print 'suceed' 112 control=0 113 #pass here only if the block can be generated at this step 114 new_order.append(block) 115 for particle in block.out_part: 116 ready.append(particle) 117 for particle in block.in_part: 118 ready.remove(particle) #to speed the search in ready 119 120 self.step=new_order
121 122 123 124
125 -class Blob_solution(Level_generation):
126 """ store the information of how to generate a blob """ 127
128 - def __init__(self,blob_sec,solution=''):
129 """ initialize how_gen: dict: Particle-> related block 130 step: list of all needed block in the correct order 131 update link with the related blob 132 """ 133 #standard-simple tool 134 Level_generation.__init__(self,'blob') 135 #link with the blob 136 self.blob_sec=blob_sec 137 blob_sec.solution.append(self) 138 #global option 139 self.opt=blob_sec.opt 140 141 self.unaligned=[] 142 143 #look if we have an original copy 144 if solution: 145 self.copy_solution(solution) 146 else: 147 self.how_gen={} 148 for part in blob_sec.content: 149 self.how_gen[part]='' #normaly block
150 151 152 153 154
155 - def copy_solution(self,solution):
156 """ duplicate solution (no alias use) in order to modify it later """ 157 158 159 self.num_fuse=solution.num_fuse 160 self.how_gen={} 161 self.ready_to_enter=list(solution.ready_to_enter) 162 163 self.num_fuse=solution.num_fuse 164 self.step=list(solution.step) 165 self.how_gen=dict(solution.how_gen) 166 self.unaligned=list(solution.unaligned) 167 168 a=self.step.pop(0) 169 if self.step==solution.step: 170 sys.exit('stop same object in step') 171 self.step.insert(0,a) 172 self.how_gen[1]=1 173 if self.how_gen==solution.how_gen: 174 sys.exit('stop same object in how_gen') 175 del self.how_gen[1]
176 177 178 179 180
181 - def find_all_solutions(self,blob_sec):
182 """ (blob)->None : complete blob_sec.sol 183 184 * find tree solutions: 185 1) this solutions maximize the number of propagator generated following BW 186 2) this solutions maximize the number of external particle generated following tf (i.e. all execpt neutrino) 187 3) this solutions try to be an intermediate solution between the two 188 * In practise, we start to construct a 'beta' solution, which one will identify globaly the structure of the solution 189 The beta try to made the more local change, and don't consider E case (but have E* tag for an D which can pass in E) 190 * Secondly we will apply modification to this beta, to pass in each solution case 191 The first solution will be the first one with improvment in 'A' case and will restore 'E'(and extend E) case 192 the second one will change all 'D','E' in '1', with little modification in 'A' case 193 The third solution will be essentially the beta without 'E' (only D for visible case)""" 194 195 #start with beta solution 196 self.find_beta_solution(blob_sec) 197 self.order_block(blob_sec) 198 #copy solution 199 if self.opt.use_sol_type_1: 200 sol1=Blob_solution(blob_sec,self) 201 if self.opt.use_sol_type_2: 202 sol2=Blob_solution(blob_sec,self) 203 if self.opt.use_sol_type_3: 204 sol3=self #no need to define new thing we can simply upgrate this solution 205 #be careful that a sol3=Blob_solution(blol_sec,self) (in place of sol3=self) is wrong 206 #it will add a new solution for the blob=> 4 solutions for the blob and not 3 207 # (in this case beta -self- stay a solution) 208 if self.opt.use_sol_type_1: 209 sol1.pass_in_solution(1) 210 if self.opt.use_sol_type_2: 211 sol2.pass_in_solution(2) 212 if self.opt.use_sol_type_3: 213 sol3.pass_in_solution(3) # update 'self' solution after the other solution, 214 else: # if we don't want to have this solution->remove from up level 215 blob_sec.solution.remove(self)# don't remove completely this solution it's the 'generic' one for the other 216 217 if not (self.opt.use_sol_type_1 or self.opt.use_sol_type_2 or self.opt.use_sol_type_3): 218 sys.exit('FATAL ERROR: At least one solution for Blob generation must be authorized')
219 220 ########################################################################################## 221 ## HOW FIND BETA SOLUTION ## 222 ########################################################################################## 223
224 - def find_beta_solution(self,blob_sec):
225 """ find a first solution to resolve the blob. 226 The idea is to take the more local possibility in all case 227 this is perhaps not the best solution but it's only the beginning of the resolution 228 Secondly we will not defined 'final' block but some more generic one (like E*: restriction at one level of E) 229 """ 230 231 self.ready_to_enter=list(blob_sec.ext_content) 232 self.ready_to_enter.reverse() 233 step=0 #security to supress infinite program 234 while 1: 235 step+=1 236 if step>40: 237 sys.exit('ERROR: infinite loop detected in Blob_solution.find_beta_solution()') 238 if len(self.ready_to_enter)<2: 239 break 240 #DEBUG 241 #print 'continue loop content:', 242 #for part in self.ready_to_enter: 243 # print part.MG, 244 #print 245 part1=self.ready_to_enter.pop(0) 246 #print 'test on :',part1.MG, '(value:',self.how_gen[part1],')', 247 part2=part1.twin 248 #print 'with :',part2.MG, 249 if part2 not in self.ready_to_enter: 250 #print 'failed' 251 self.ready_to_enter.append(part1) 252 continue 253 #print 'suceed', 254 solution=self.resolve_piece(blob_sec,[part1,part2]) 255 #print solution.chgt_var 256 257 #treat one particle case 258 if self.how_gen[blob_sec.main]=='': 259 #print 'main not defined-> pass in 0' 260 Block_B(self,'0',[blob_sec.main],[])
261 262
263 - def resolve_piece(self,blob_sec,in_part):
264 "find the 'first' solution for this piece" 265 266 #usefull particle: 267 mother1=in_part[0].mother 268 mother_twin=mother1.twin 269 270 #print 'resolve piece',in_part[0].MG,in_part[1].MG 271 #check case 2 272 if not( in_part[0].external or in_part[1].external): 273 #two propagator already generated =>sum them=>block '2' 274 result=Block_B(self,'2',in_part,mother1) #take care of all dependencies 275 return result 276 277 #print 'pass step 1' 278 self.sol_type='' 279 #check neutrino case (A,B,C) 280 for particle in in_part: 281 if particle.neutrino: 282 #print 'neutrino detect' 283 #first generate the other particle following tf function 284 twin=particle.twin 285 #now look how to generate this neutrino 286 motherX=particle 287 mother_list=[] 288 for X in range(1,4): #check the tree propa before the neutrino 289 #print 'motherXbut1',motherX.MG 290 motherX=motherX.mother 291 if motherX==0: 292 #print 'Not_exist' 293 stop='Not_exist' 294 break 295 #print 'motherX',motherX.MG 296 if blob_sec.contains_particle(motherX): 297 if self.how_gen[motherX]=='': 298 mother_list.append(motherX) 299 #print mother_list[-1].pid,mother_list[-1].mother 300 if mother_list[-1].twin!=0 and mother_list[-1].twin.neutrino: 301 #check for following neutrino configuration 302 stop='neut' 303 break 304 else: 305 #print self.how_gen[motherX] 306 #print 'already defined' 307 stop=self.how_gen[motherX] 308 break 309 else: 310 #print 'not exist' 311 stop='Not_exist' 312 break 313 #SO we have information to create the block 314 if len(mother_list)==0: 315 Block_B(self,'0',[particle],[]) 316 elif len(mother_list)==1: 317 block=Block_B(self,'C',[particle,twin],[mother_list[0]]) 318 block.give_stop_reason(stop) 319 self.treat_conflicting_block(block) #try to pass block in 'A' (but pass the 'A' block in 'B') 320 elif len(mother_list)==2: 321 block=Block_B(self,'B',[particle,twin,mother_list[0].twin],[mother_list[-1]]) 322 block.give_stop_reason(stop) 323 elif len(mother_list)==3: 324 block=Block_B(self,'A',[particle,twin,mother_list[0].twin,mother_list[1].twin],[mother_list[-1]]) 325 return block #end neutrino case 326 327 #print 'pass step 2' 328 #check for one visible particle and a propagator case (1,D) 329 if (not (in_part[0].external and in_part[1].external)): 330 if in_part[0].external: 331 particle=in_part[0] 332 propa=in_part[1] 333 else: 334 particle=in_part[1] 335 propa=in_part[0] 336 if particle.tf_level<2: 337 #must use TF function 338 result=Block_B(self,'1',in_part,[mother1]) 339 else: 340 #transfert are authorized 341 result=Block_B(self,'D',in_part,[mother1]) 342 return result#end visible+propa case 343 344 #check for double visible case (1,D,E) 345 #check if the width of the two visible particle autorize E/D 346 #print 'pass double visible case' 347 if in_part[0].tf_level<2 and in_part[1].tf_level<2: 348 #no transfer are authorized => 1 349 result=Block_B(self,'1',in_part,[mother1]) 350 elif in_part[0].tf_level<2 or in_part[1].tf_level<2: 351 #no transfer authorized for 0(1) but for 1(0) => D 352 #print 'no transfer authorized for 0(1) but for 1(0) => D' 353 result=Block_B(self,'D',in_part,[mother1]) 354 #Now transfer authorized for both =>check for E 355 elif not(in_part[0].mass and in_part[1].mass): 356 #mass condition for E fullfilled. store an E* information 357 #We don't create E block at this level, the extension of this block can cause inefficiency in some case 358 result=Block_B(self,'E*',in_part,[mother1])#special case of E 359 else: 360 #mass condition for E failed -> D 361 #print 'mass condition for E failed -> D' 362 result=Block_B(self,'D',in_part,[in_part[0].mother]) 363 return result #end of double visible case
364 365
366 - def treat_conflicting_block(self,block):
367 """ if a 'C' block is block by a 'A' block it's sometimes more powerful to degrade the 'A' in 'B' 368 if the 'C' can be upgrated to 'A'""" 369 370 #CHECK IF WE CAN DO SOMETHING 371 if block.stop!='A': 372 return 373 #block was stop by another change of variable ->try to improve that 374 375 #check if the third level if free 376 try: 377 mother1=block.out_part[0].mother 378 mother2=mother1.mother 379 if self.how_gen[mother2].chgt_var not in ['','0','1','2','D']: 380 return 381 except: 382 return 383 384 #PASS ALL CONDITION 385 #so pass block A->B 386 blockA=self.how_gen[mother1] 387 #change block data 388 new_in=blockA.in_part #be careful this is only a alias! 389 new_in.remove(block.out_part[0]) 390 blockA.redefine_block(self,'B',new_in,out_part[0].twin) 391 #pass this block -> A 392 new_in=block.in_part+[out_part[0].twin,mother1.twin] 393 block.redefine_block(self,'A',new_in,mother2)
394 395 ########################################################################################## 396 ## BETA UPGRATING FUNCTION ## 397 ########################################################################################## 398 399
400 - def pass_in_solution(self,tag):
401 """ tag -> upgrate solution in order to fullfill taged criteria 402 upgrate 'beta' solution following some criteria(tagged with tag)""" 403 404 #print 'input', self 405 if tag==1: 406 self.sol_type=1 407 self.extend_block('E*') 408 if self.opt.blob_fuse: 409 self.extend_block('D') 410 self.extend_block('A') 411 elif tag==2: 412 self.sol_type=2 413 self.convert_DE_in_1() 414 if self.opt.blob_fuse: 415 self.extend_block('A') 416 417 elif tag==3: 418 self.sol_type=3 419 self.convert_E_in_D() 420 #print 'ouput',self 421 #print 'pass in solution ',tag 422 #be sure that the order is still uptodate 423 self.order_block(self.blob_sec) 424 for block in self.step: 425 block.def_order_content()
426
427 - def convert_DE_in_1(self):
428 """ convert all 'E*' and all 'D' in '1' block """ 429 430 #find blok 'E*,D-> pass to '1' 431 all_block=list(self.step) 432 for block in all_block: 433 if self.blob_sec.content[0].width < self.opt.force_nwa: 434 continue 435 436 if block.chgt_var in ['E*','D']: 437 block.change_chgt_var(self,'1')
438 439
440 - def convert_E_in_D(self):
441 """ convert all 'E*' in 'D' """ 442 443 # find blok 'E*-> pass to 'D' 444 for block in self.step: 445 if block.chgt_var in ['E*']: 446 block.change_chgt_var(self,'D')
447 448
449 - def extend_block(self,chgt_var):
450 """ put the A/D/E propagator in place to minize problem with thin transfer function""" 451 452 num_propa={'A':3,'D':1,'E*':2} #maximum number of aligned propa 453 num_propa=num_propa[chgt_var] 454 new_chgt_var={'A':'A','D':'D','E*':'E'} 455 new_chgt_var=new_chgt_var[chgt_var] 456 457 #print '*** check how gen',self.sol_type,'for change',chgt_var,' *** number of block in step',len(self.step) 458 459 #step 1: find a blok 'chgt_var' 460 #step 2: find the area where we have freedom 461 # * define a list of delta-thin width associated to external particle 462 # * define which one to take (first condition thiner and second nearest of the neutrino) 463 #step 3: define the solution: 464 # * We will limit (for the moment) to move up to one propagator. 465 # * We move only propagator before a large tf (of course) and the one (if many) with largest width 466 # for the propagator 467 468 #step 1: find blok 469 step2=0 470 all_block=list(self.step) 471 for block in all_block: 472 step2+=1 473 if block.chgt_var!=chgt_var: 474 continue 475 if block not in self.step: 476 continue 477 #print 'find one' 478 #step 1 succeed 479 #step2:find the area where we have freedom 480 #initialisation of vector for width category 481 thin=[] #for the three particle associated to the thiner width 482 483 #look for area before 'A'/'D'/'E*-E': 484 try: 485 motherX=block.neut_content[0] #for 'A' like case 486 except: 487 motherX=block.in_part[0] #for 'E*' like case 488 while 1: 489 motherX=motherX.mother 490 if self.blob_sec.contains_particle(motherX)==0: 491 break 492 if not( self.how_gen[motherX].chgt_var in ['0','1','2','D'] or self.how_gen[motherX]==block): 493 break 494 495 #print 'create thin' 496 for i in range(0,len(thin)+1): 497 #print 'thin content: [', 498 #for particle in thin: 499 # print particle.MG,',', 500 #print '] step:',i, 'num_enter',num_propa 501 502 if i==len(thin) and i<num_propa: 503 thin.append(motherX) 504 elif(motherX.width<thin[i].width and motherX.channel=='S'): 505 thin.insert(i,motherX) 506 if len(thin)>num_propa: 507 thin=thin[:num_propa] 508 break 509 510 #print 'particle selected in step2', 511 #for particle in thin: 512 # print [particle.MG], 513 #print '|' 514 515 #change order of thin to be in the correct order (anti-level) for the generation 516 propa_in=[thin[0]] 517 for i in range(1,len(thin)):#lent(thin) can be lower than num_propa in some E* case 518 for j in range(0,len(propa_in)+1): 519 if j==len(propa_in): 520 propa_in.append(thin[i]) 521 elif(thin[i].level<propa_in[j].level): 522 propa_in.insert(j,thin[i]) 523 break 524 #end of step 2 525 #OPTION -> return to first propa if asked 526 if (block.chgt_var=='E*' and (not self.opt.blob_fuse) and len(propa_in)==2): 527 #CASE A/D with not blob_fuse cann't pass in the full routine if blob_fuse=0 528 propa_in=[block.in_part[0].mother,block.in_part[0].mother.mother] 529 530 #print 'propa selected in step2.2', 531 #for particle in propa_in: 532 # print particle.MG, 533 #print '|' 534 #step 3:define the solution 535 #'update' the generation 536 fuse_list=[] 537 step=0 538 try: 539 motherX=block.neut_content[0] #for 'A' like case 540 except: 541 motherX=block.in_part[0] #for 'E*' like case 542 543 part_in=[motherX] 544 while 1: 545 motherXbut1=motherX 546 motherX=motherX.mother 547 548 if step==len(propa_in): 549 break 550 if self.blob_sec.contains_particle(motherX)==0: 551 sys.exit('ERROR: unusual error in Blob_solution.expand_block: debug this routine (error type 1)') 552 if not( self.how_gen[motherX].chgt_var in ['0','1','2','D'] or self.how_gen[motherX]==block): 553 sys.exit('ERROR: unusual error in Blob_solution.expand_block: debug this routine (error type 2)') 554 555 if motherX in propa_in: 556 step+=1 557 if self.how_gen[motherX]!=block: 558 self.how_gen[motherX].del_from_sol(self) 559 if fuse_list: 560 fuse_part=self.define_fuse_region(fuse_list) 561 part_in.append(fuse_part) 562 fuse_list=[] 563 else: 564 part_in.append(motherXbut1.twin) 565 elif fuse_list: 566 self.how_gen[motherX].del_from_sol(self) 567 fuse_list.append(motherX.twin) 568 else: 569 self.how_gen[motherX].del_from_sol(self) 570 fuse_list=[motherXbut1.twin,motherX.twin] 571 572 #redifine this block 573 #print 'redefine_block', num_propa, len(part_in)-1 574 if num_propa==len(part_in)-1: 575 block.redefine_block(self,new_chgt_var,part_in,propa_in[0]) 576 elif chgt_var=='E*': 577 #failed to expand in E 578 block.change_chgt_var(self,'D') 579 else: 580 sys.exit('ERROR: unusual error in Blob_solution.expand_block: debug this routine (error type 3)')
581 582 583
584 - def del_ext1_in(self,particle_list):
585 """ delete blok '1' but only if the particle is an external one!""" 586 587 for particle in particle_list: 588 if particle.external and self.how_gen[particle].chgt_var=='1': 589 self.how_gen[particle].del_from_sol[self]
590 591 592 593 594 ########################################################################################## 595 ## OTHER FUNCTION ## 596 ########################################################################################## 597
598 - def debug(self):
599 """ function for debugging: print how_gen""" 600 print("how_gen") 601 list=list(self.how_gen.items()) 602 for i in range(0,len(list)): 603 try: 604 print('{'+str(list[i][0].MG),':'+str(list[i][1].chgt_var)+'}', end=' ') 605 except: 606 print('}', end=' ') 607 print()
608 609
610 - def __str__(self):
611 text='blob generation: ' 612 for block in self.step: 613 text+='['+block.chgt_var+'|' 614 for particle in block.in_part: 615 text+=str(particle.MG)+' ' 616 text+=':' 617 for particle in block.out_part: 618 text+=str(particle.MG)+' ' 619 text+='] ' 620 #if block.stop: 621 # print block.stop, 622 return text
623 624
625 -class Block_sector:
626 """define:store information on a Block. 627 This is a simple version of block dedicated for ECS 628 This is the basis for the blob dedicated 629 """ 630
631 - def __init__(self,sol_sec,chgt_var,input_propa,output_propa):
632 633 self.sol_sec=sol_sec 634 self.chgt_var=chgt_var 635 self.in_part=input_propa 636 if type(output_propa)==list: #output_propa must be a list, but sometimes it's forgotten 637 self.out_part=output_propa 638 else: 639 self.out_part=[output_propa] 640 self.opt=sol_sec.opt 641 self.unaligned=[] 642 643 #neutrino stuff 644 self.neut_content=[] 645 self.num_neut=0 646 for particle in input_propa: 647 if particle.neutrino: 648 self.neut_content.append(particle) 649 self.num_neut+=1 650 651 #stop reason 652 self.stop='' 653 654 #link to the solution_sector 655 sol_sec.step.append(self) 656 self.def_order_content()
657
658 - def give_stop_reason(self,message):
659 """ store the stop information (why not a more general change of variable) """ 660 self.stop=message
661 662
663 - def def_order_content(self):
664 """ define (in the corect order) the particle used in this ECS 665 only for fuse sector (routine overwirtted in other case) 666 """ 667 668 #normaly self.in_part are ordering in decreasing order (respected to level) 669 670 if self.chgt_var=='3': #define a fuse particle 671 self.order_content=self.in_part+self.out_part 672 self.chgt_var='2'
673 674 675
676 - def __str__(self):
677 """ print routine """ 678 679 text="["+str(self.chgt_var)+ ' |' 680 for particle in self.in_part: 681 text+=str(particle.MG)+',' 682 text=text[:-1]+' :' 683 for particle in self.out_part: 684 text+=str(particle.MG)+',' 685 686 return text[:-1]+']'
687 688
689 -class Block_ECS(Block_sector):
690 """ Define a Block dedicated to be an ECS central part""" 691
692 - def __init__(self,sol_sec,chgt_var,input_part):
693 """ create a block for the dedicated ECS """ 694 Block_sector.__init__(self,sol_sec,chgt_var,input_part,[]) 695 self.def_order_content() 696 self.def_unaligned()
697 698
699 - def def_order_content(self):
700 """ define (in the correct order) the particle used in this ECS 701 This routine is overwrited for block linked to blob 702 """ 703 #first treat zero neutrino case 704 if self.chgt_var=='a': 705 self.order_content=self.in_part 706 return 707 708 #consider other case 709 ext_content=[] 710 propa_content=[] 711 neut_content=[] 712 self.order_content=[] 713 714 for particle in self.in_part: 715 if particle.neutrino: 716 neut_content.append(particle) 717 continue 718 719 propa_content.append(particle.mother) 720 ext_content.append(particle) 721 722 self.order_content=neut_content+ext_content+propa_content 723 724 #special case: E class -> add the fisrt propa in S channel 725 if self.chgt_var=='e': 726 neut_in_ecs=neut_content[0] 727 self.order_content.append(neut_in_ecs.all_mother()[-1])
728 729 #print 'order_content',self.chgt_var 730 #for particle in self.order_content: 731 # print particle.MG, 732 #print 733
734 - def def_unaligned(self):
735 736 if self.chgt_var=='a': 737 unaligned=self.in_part[0].all_mother() 738 for part in self.in_part[1].all_mother(): 739 if part not in unaligned: 740 unaligned.append(part) 741 self.unaligned=unaligned+self.in_part 742 return 743 744 745 aligned=[part.mother for part in self.in_part if part.neutrino==0] 746 if self.chgt_var=='a': 747 aligned.append(self.order_content[-1]) # add the first propagator 748 749 unaligned=[] 750 for i in range(0,self.num_neut): 751 for part in self.order_content[i].all_mother(): 752 if part not in aligned+unaligned: 753 unaligned.append(part) 754 755 self.unaligned=unaligned
756
757 -class Block_B(Block_sector):
758 """ Define a Block dedicated to be in a blob""" 759
760 - def __init__(self,sol_sec,chgt_var,input_propa,output_propa,unaligned=[]):
761 762 Block_sector.__init__(self,sol_sec,chgt_var,input_propa,output_propa) 763 764 self.put_B_sol_uptodate(sol_sec) #maintain tool for beta solution and future update 765 self.def_unaligned()
766 767
768 - def put_B_sol_uptodate(self,sol_sec):
769 """ put the solution status uptodate with this block definition """ 770 771 for particle in self.in_part: 772 try: #we can generate some 'not ready' variable with block A,B,E 773 sol_sec.ready_to_enter.remove(particle) 774 except: 775 pass 776 if particle.external: 777 sol_sec.how_gen[particle]=self 778 if particle.mother and particle.mother not in self.out_part and self.chgt_var!='0': 779 if sol_sec.blob_sec.contains_particle(particle.mother): 780 sol_sec.how_gen[particle.mother]=self 781 for particle in self.out_part: 782 #check that the output particle isn't already consider like an input particle somewhere else 783 784 if sol_sec.blob_sec.contains_particle(particle.mother): #consider fuse case 785 if sol_sec.how_gen[particle.mother]=='': 786 sol_sec.ready_to_enter.append(particle) 787 sol_sec.how_gen[particle]=self
788 789
790 - def def_order_content(self):
791 """ define (in the corect order) the particle used in this blob """ 792 793 propa_content=[] 794 #normaly self.in_part are ordering in decreasing order (respected to level) 795 796 if self.chgt_var=='3': #define a fuse particle 797 self.order_content=self.in_part+self.out_part 798 self.chgt_var='2' 799 elif self.chgt_var=='0': #external particle 800 self.order_content=self.in_part 801 elif self.chgt_var=='E': 802 propa_content=[self.in_part[0].mother,self.in_part[2].mother] 803 if self.in_part[0].mass: 804 self.order_content=self.in_part+propa_content 805 else: 806 self.order_content=[self.in_part[1],self.in_part[0],self.in_part[2]]+propa_content 807 elif isinstance(self.in_part[0].MG, six.string_types): #check if first particle are fuse particle 808 self.order_content=self.in_part+[self.in_part[0].mother] 809 try: 810 self.order_content.append(self.in_part[2].mother) 811 except: 812 pass 813 elif isinstance(self.in_part[1].MG, six.string_types): #check if first particle are fuse particle 814 self.order_content=self.in_part+[self.in_part[1].mother] 815 try: 816 self.order_content.append(self.in_part[2].mother) 817 except: 818 pass 819 else: 820 for particle in self.in_part : 821 if particle.mother not in propa_content: 822 propa_content.append(particle.mother) 823 self.order_content=self.in_part+propa_content
824 825
826 - def change_chgt_var(self,sol_sec,new_chgt_var):
827 """ change the changement of variable associated """ 828 equivalent_class=[['E*','E','D','1','2'] #2 particle in entry one in output 829 #add a ,[] for a second type of equivalent class 830 ]#end of equivalent class 831 832 if self.sol_sec==sol_sec: 833 obj=self 834 else: 835 #supress old block from step 836 try: 837 sol_sec.step.remove(self) 838 except: 839 pass 840 obj=Block_B(sol_sec,self.chgt_var,self.in_part,self.out_part) 841 obj.def_unaligned() 842 843 for i in range(0,len(equivalent_class)): 844 if obj.chgt_var in equivalent_class[i]: 845 if new_chgt_var in equivalent_class[i]: 846 obj.chgt_var=new_chgt_var 847 obj.def_unaligned() 848 if obj.chgt_var!=new_chgt_var: 849 print('WARNING: unexpected modification:') 850 print(' pass from',[obj.chgt_var],'to',[new_chgt_var]) 851 print(' there are strictly non equivalent: but we go on anyway') 852 obj.chgt_var=new_chgt_var
853
854 - def def_unaligned(self):
855 """ associate in self.unaligned the particle with unaligned peaks """ 856 857 if self.chgt_var in ['1','2']: 858 self.unaligned=self.out_part[0] 859 elif self.chgt_var=='E': 860 self.unaligned=[self.in_part[0],self.in_part[1]] 861 elif self.chgt_var=='D': 862 tag1=self.in_part[0].MG 863 tag2=self.in_part[1].MG 864 if tag1<0: 865 self.unaligned=self.in_part[1] 866 elif tag2<0: 867 self.unaligned=self.in_part[0] 868 else: 869 if tag1>tag2: 870 tag1,tag2=tag2,tag1 871 self.unaligned='first_d_'+str(tag1)+'_'+str(tag2)
872
873 - def redefine_block(self,sol_sec,chgt_var,input_propa,output_propa):
874 """redifine block """ 875 if self.sol_sec==sol_sec: 876 sol_sec.step.remove(self) 877 stop=self.stop 878 self.__init__(sol_sec,chgt_var,input_propa,output_propa) 879 self.give_stop_reason(stop) 880 else: 881 stop=self.stop 882 #supress old block from step 883 try: 884 sol_sec.step.remove(self) 885 except: 886 pass 887 new_block=Block_B(sol_sec,chgt_var,input_propa,output_propa) 888 new_block.give_stop_reason(stop) 889 pass
890 891
892 - def del_from_sol(self,sol_sec):
893 """ supress corectly the block of the solutions """ 894 895 sol_sec.step.remove(self) 896 897 #update the solution-link 898 for particle in self.in_part: 899 if particle.external: 900 sol_sec.how_gen[particle]='' 901 sol_sec.ready_to_enter.append(particle) #normaly useless but if we are in a new type of generation in the future 902 903 for particle in self.out_part: 904 sol_sec.how_gen[particle]='' 905 try: 906 sol_sec.ready_to_enter.remove(particle) #idem,but normaly particle is not there. 907 except: 908 pass 909 910 if self.sol_sec==sol_sec: 911 #in this case supress the object: 912 del self
913