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