Package madgraph :: Package iolibs :: Module drawing_eps
[hide private]
[frames] | no frames]

Source Code for Module madgraph.iolibs.drawing_eps

  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  """This files contains class for creating files or object representing a  
 17  diagram or a set of diagrams. 
 18   
 19  class structure: 
 20    
 21  DrawDiagram:  
 22      In principle ALL routines representing a diagram in Any format SHOULD derive 
 23      from this class. This is a (nearly empty) frameworks to draw a diagram  
 24      in any type format.   
 25   
 26      This frameworks defines in particular  
 27          - function to convert the input diagram in the correct object.  
 28              [convert_diagram] 
 29          - main loop to draw a diagram in a line-by-line method 
 30              [draw - draw_diagram] 
 31           
 32  DrawDiagramEPS: 
 33      This contains all the routines to represent one diagram in Encapsuled  
 34      PostScript (EPS) 
 35       
 36  DrawDiagramsEPS: 
 37      This contains all the routines to represent a set of diagrams in Encapsuled  
 38      PostScript (EPS).""" 
 39   
 40  from __future__ import division 
 41   
 42  from __future__ import absolute_import 
 43  import os 
 44  import math 
 45  import madgraph.core.drawing as draw 
 46  import madgraph.core.base_objects as base_objects 
 47  import madgraph.loop.loop_base_objects as loop_objects 
 48  import madgraph.various.misc as misc 
 49  import logging 
 50   
 51  logger = logging.getLogger('madgraph.drawing_eps') 
 52   
 53  _file_path = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0] + '/' 
 54   
 55  #=============================================================================== 
 56  # DrawDiagramEps 
 57  #=============================================================================== 
58 -class EpsDiagramDrawer(draw.DiagramDrawer):
59 """Class to write a EPS file containing the asked diagram 60 This class follows the DrawDiagram Frameworks. 61 62 The main routine to draw a diagram is 'draw' which call 63 1) initialize: setup things for the diagram (usually open a file) 64 2) convert_diagram : Update the diagram in the correct format if needed 65 3) draw_diagram : Perform diagram dependent operation 66 4) conclude : finish the operation. 67 """ 68 69 #some page information 70 width = 450 71 height = 450 72 npage = 1 73 74 # Define where to put the diagram in the page. This is the coordinate of 75 #the two opposites point of the drawing area 76 x_min = 150 77 y_min = 450 78 x_max = 450 79 y_max = 750 80 81 blob_size = 1.5 82 april_fool = False 83
84 - def initialize(self):
85 """Operation done before starting to create diagram specific EPS content 86 First open the file in write mode then write in it the header and the 87 library of particle type.""" 88 89 90 # Open file 91 super(EpsDiagramDrawer, self).initialize() 92 93 # File Header 94 text = "%!PS-Adobe-2.0\n" 95 text += "%%" + "BoundingBox: -20 -20 %s %s \n" % \ 96 (self.width, self.height) 97 text += "%%DocumentFonts: Helvetica\n" 98 text += "%%" + "Pages: %s \n" % self.npage 99 self.file.writelines(text) 100 101 # Import the definition of the different way to represent a line 102 self.file.writelines(open(os.path.join(_file_path, \ 103 'iolibs/template_files/drawing_eps_header.inc')).read())
104 105
106 - def conclude(self):
107 """Operation to perform when all code related to a specific diagram are 108 finish. Operation : 109 - Add the 'end of page' code 110 - write unwritten text and close the file. [DrawDiagram.conclude]""" 111 112 # Add an 'end of page statement' 113 self.text = 'showpage\n' 114 self.text += '%%trailer\n' 115 116 #write the diagram file 117 super(EpsDiagramDrawer, self).conclude()
118 119
120 - def rescale(self, x, y):
121 """All coordinates belongs to [0,1]. So that in order to have a visible 122 graph we need to re-scale the graph. This method distort the square in 123 a oblong. Deformation are linear.""" 124 125 # Use the information for the graph position. 'self.x_???,self.y_???? 126 #are the coordinate of the two opposites point of the drawing area. 127 x = self.x_min + (self.x_max - self.x_min) * x 128 y = self.y_min + (self.y_max - self.y_min) * y 129 130 return x, y
131 132
133 - def line_format(self, x1, y1, x2, y2, name):
134 """Specify the text format of a specific Particles. 135 EPS format for Particle is either [X Y X Y NAME] or [X Y X Y NUM NAME]. 136 In this routine we will consider only the first format. The second can 137 be matched by redefining name in [NUM NAME].""" 138 139 # Compute real position for starting/ending point 140 x1, y1 = self.rescale(x1, y1) 141 x2, y2 = self.rescale(x2, y2) 142 143 #return the line in correct format\ 144 if self.april_fool: 145 import random 146 c = random.random() 147 d = random.random() 148 e = random.random() 149 return "%s %s %s setrgbcolor\n %s %s %s %s %s \n" % (c,d,e,x1, y1, x2, y2, name) 150 else: 151 return "%s %s %s %s %s \n" % (x1, y1, x2, y2, name)
152 - def draw_vertex(self, vertex, bypass = ['QED','QCD'] ):
153 """Add blob in case on non QED-QCD information""" 154 155 interaction = self.model.get_interaction(vertex.id) 156 if interaction: 157 order = interaction.get('orders') 158 order = [key for key in order.keys() if order[key] and \ 159 key not in bypass] 160 161 if order: 162 x1, y1 = self.rescale(vertex.pos_x, vertex.pos_y) 163 self.text += " %s %s %s 1.0 Fblob \n" % (x1, y1, self.blob_size)
164 165 166
167 - def draw_straight(self, line):
168 """ADD the EPS code for this fermion line.""" 169 170 #add the code in the correct format 171 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 172 line.end.pos_x, line.end.pos_y, 'Ffermion')
173
174 - def draw_curved_dashed(self, line, cercle):
175 """ADD the EPS code for this fermion line.""" 176 177 if not cercle: 178 curvature = 0.4 179 else: 180 curvature = 1 181 182 if (line.begin.pos_x, line.begin.pos_y) == self.curved_part_start: 183 curvature *= -1 184 185 #add the code in the correct format 186 x1, y1 = self.rescale(line.begin.pos_x, line.begin.pos_y) 187 self.text += ' %s %s moveto \n' % (x1, y1) 188 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 189 line.end.pos_x, line.end.pos_y, '%s Fhiggsl' %\ 190 curvature)
191
192 - def draw_curved_straight(self, line, cercle):
193 """ADD the EPS code for this fermion line.""" 194 195 if not cercle: 196 curvature = 0.4 197 else: 198 curvature = 1 199 200 if (line.begin.pos_x, line.begin.pos_y) == self.curved_part_start: 201 curvature *= -1 202 203 #add the code in the correct format 204 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 205 line.end.pos_x, line.end.pos_y, '%s Ffermionl' %\ 206 curvature)
207
208 - def draw_circled_straight(self, line, cercle):
209 """ADD the EPS code for this fermion line.""" 210 211 if not cercle: 212 curvature = 4 213 else: 214 curvature = 5 215 216 is_tadpole = line.begin.pos_x==line.end.pos_x and \ 217 line.begin.pos_y==line.end.pos_y 218 219 if is_tadpole: 220 # Obtain the direction of the propagator supporting the tadpole 221 direction = None 222 for l in line.begin.lines: 223 new_direction = (l.end.pos_x-l.begin.pos_x, l.end.pos_y-l.begin.pos_y) 224 if new_direction==(0.0,0.0): 225 continue 226 norm = math.sqrt(new_direction[0]**2+new_direction[1]**2) 227 new_direction = (new_direction[0]/norm, new_direction[1]/norm) 228 229 if not direction: 230 direction = new_direction 231 else: 232 if direction not in \ 233 [new_direction, (-new_direction[0],-new_direction[1])]: 234 pass 235 # logger.debug('The case of a five-point vertex'+ 236 # 'yielding a tadpole is not supported') 237 continue 238 239 #add the code in the correct format 240 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 241 line.end.pos_x+0.01*direction[0], line.end.pos_y+0.01*direction[1], 242 '%s Ffermionl' % (curvature*7)) 243 else: 244 #add the code in the correct format 245 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 246 line.end.pos_x+0.01, line.end.pos_y+0.01, '%s Ffermionl' %\ 247 curvature)
248 - def draw_dashed(self, line):
249 """ADD the EPS code for this Higgs line.""" 250 251 #add the code in the correct format 252 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 253 line.end.pos_x, line.end.pos_y, 'Fhiggs')
254 255
256 - def draw_circled_dashed(self, line,cercle):
257 """ADD the EPS code for this Higgs line.""" 258 if not cercle: 259 curvature = 4 260 else: 261 curvature = 5 262 263 is_tadpole = line.begin.pos_x==line.end.pos_x and \ 264 line.begin.pos_y==line.end.pos_y 265 266 if is_tadpole: 267 # Obtain the direction of the propagator supporting the tadpole 268 direction = None 269 for l in line.begin.lines: 270 new_direction = (l.end.pos_x-l.begin.pos_x, l.end.pos_y-l.begin.pos_y) 271 if new_direction==(0.0,0.0): 272 continue 273 norm = math.sqrt(new_direction[0]**2+new_direction[1]**2) 274 new_direction = (new_direction[0]/norm, new_direction[1]/norm) 275 276 if not direction: 277 direction = new_direction 278 else: 279 if direction not in \ 280 [new_direction, (-new_direction[0],-new_direction[1])]: 281 # logger.error('The case of a five-point vertex'+ 282 # 'yielding a tadpole is not supported') 283 pass 284 285 #add the code in the correct format 286 x, y = self.rescale(line.begin.pos_x, line.begin.pos_y) 287 self.text += '%s %s moveto'%(x, y) 288 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 289 line.end.pos_x+0.01*direction[0], line.end.pos_y+0.01*direction[1], 290 '%s Fhiggsl' % (curvature*7)) 291 else: 292 #add the code in the correct format 293 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 294 line.end.pos_x+0.01, line.end.pos_y+0.01, '%s Fhiggsl'% curvature)
295
296 - def draw_dotted(self,line):
297 """ADD the EPS code for the ghost line.""" 298 299 #add the code in the correct format 300 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y,\ 301 line.end.pos_x, line.end.pos_y, 'Fghost')
302
303 - def draw_curved_dotted(self, line, cercle):
304 """ADD the EPS code for the ghost line.""" 305 if not cercle: 306 curvature = 0.4 307 else: 308 curvature = 1 309 310 if (line.begin.pos_x, line.begin.pos_y) == self.curved_part_start: 311 curvature *= -1 312 #add the code in the correct format 313 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y,\ 314 line.end.pos_x, line.end.pos_y, '%s Fghostl'% curvature)
315
316 - def draw_circled_dotted(self, line, cercle):
317 """ADD the EPS code for the ghost line.""" 318 if not cercle: 319 curvature = 4 320 else: 321 curvature = 5 322 323 is_tadpole = line.begin.pos_x==line.end.pos_x and \ 324 line.begin.pos_y==line.end.pos_y 325 326 if is_tadpole: 327 # Obtain the direction of the propagator supporting the tadpole 328 direction = None 329 for l in line.begin.lines: 330 new_direction = (l.end.pos_x-l.begin.pos_x, l.end.pos_y-l.begin.pos_y) 331 if new_direction==(0.0,0.0): 332 continue 333 norm = math.sqrt(new_direction[0]**2+new_direction[1]**2) 334 new_direction = (new_direction[0]/norm, new_direction[1]/norm) 335 336 if not direction: 337 direction = new_direction 338 else: 339 if direction not in \ 340 [new_direction, (-new_direction[0],-new_direction[1])]: 341 # logger.error('The case of a five-point vertex'+ 342 # 'yielding a tadpole is not supported') 343 pass 344 345 #add the code in the correct format 346 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 347 line.end.pos_x+0.01*direction[0], line.end.pos_y+0.01*direction[1], 348 '%s Fghostl' % (curvature*7)) 349 else: 350 #add the code in the correct format 351 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y,\ 352 line.end.pos_x+0.01, line.end.pos_y+0.01, '%s Fghostl'% curvature)
353
354 - def draw_wavy(self, line, opt=0, type=''):
355 """ADD the EPS code for this photon line.""" 356 357 #add the code in the correct format 358 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 359 line.end.pos_x, line.end.pos_y, '%d Fphoton%s' % (opt,type))
360
361 - def draw_curved_wavy(self, line, cercle, opt=0, type=''):
362 """ADD the EPS code for this photon line.""" 363 if not cercle: 364 curvature = 0.4 365 else: 366 curvature = 1 367 if (line.begin.pos_x, line.begin.pos_y) == self.curved_part_start: 368 curvature *= -1 369 #add the code in the correct format 370 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 371 line.end.pos_x, line.end.pos_y, '%d %s Fphotonl%s' % (opt,curvature,type))
372
373 - def draw_circled_wavy(self, line, cercle, opt=0, type=''):
374 """ADD the EPS code for this photon line.""" 375 376 if not cercle: 377 curvature = 4 378 else: 379 curvature = 5 380 381 is_tadpole = line.begin.pos_x==line.end.pos_x and \ 382 line.begin.pos_y==line.end.pos_y 383 384 if is_tadpole: 385 # Obtain the direction of the propagator supporting the tadpole 386 direction = None 387 for l in line.begin.lines: 388 new_direction = (l.end.pos_x-l.begin.pos_x, l.end.pos_y-l.begin.pos_y) 389 if new_direction==(0.0,0.0): 390 continue 391 norm = math.sqrt(new_direction[0]**2+new_direction[1]**2) 392 new_direction = (new_direction[0]/norm, new_direction[1]/norm) 393 394 if not direction: 395 direction = new_direction 396 else: 397 if direction not in \ 398 [new_direction, (-new_direction[0],-new_direction[1])]: 399 # logger.error('The case of a five-point vertex'+ 400 # 'yielding a tadpole is not supported') 401 pass 402 403 #add the code in the correct format 404 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 405 line.end.pos_x+0.01*direction[0], line.end.pos_y+0.01*direction[1], 406 '%d %s Fphotonl%s' % (opt,curvature*7,type)) 407 else: 408 #add the code in the correct format 409 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 410 line.end.pos_x+0.01, line.end.pos_y+0.01, 411 '%d %s Fphotonl%s' % (opt,curvature,type))
412
413 - def draw_curly(self, line, type=''):
414 """ADD the EPS code for this gluon line.""" 415 416 # Due to the asymmetry in the way to draw the gluon (everything is draw 417 #upper or below the line joining the points). We have to put conditions 418 #in order to have nice diagram. 419 if (line.begin.pos_x < line.end.pos_x) or \ 420 (line.begin.pos_x == line.end.pos_x and \ 421 line.begin.pos_y > line.end.pos_y): 422 self.text += self.line_format(line.begin.pos_x, 423 line.begin.pos_y, line.end.pos_x, 424 line.end.pos_y, '0 Fgluon%s' % type) 425 else: 426 self.text += self.line_format(line.end.pos_x, 427 line.end.pos_y, line.begin.pos_x, 428 line.begin.pos_y, '0 Fgluon%s' % type)
429
430 - def draw_curved_scurly(self, line, cercle, type=''):
431 432 self.draw_curved_curly(line, cercle, type) 433 self.draw_curved_straight(line, cercle)
434
435 - def draw_curved_curly(self, line, cercle, type=''):
436 """ADD the EPS code for this gluon line.""" 437 438 dist = math.sqrt((line.begin.pos_x-line.end.pos_x)**2 + \ 439 (line.begin.pos_y-line.end.pos_y)**2) 440 if not cercle or dist > 0.3: 441 curvature = 0.4 442 else: 443 curvature = 1 444 445 446 # Due to the asymmetry in the way to draw the gluon (everything is draw 447 #upper or below the line joining the points). We have to put conditions 448 #in order to have nice diagram. 449 450 if (line.begin.pos_x, line.begin.pos_y) == self.curved_part_start: 451 curvature *= -1 452 453 self.text += self.line_format(line.end.pos_x, 454 line.end.pos_y, line.begin.pos_x, 455 line.begin.pos_y, '0 %s Fgluonl%s' % (-1*curvature, type))
456 457 458
459 - def draw_scurly(self, line):
460 """ADD the EPS code for this gluino line.""" 461 self.draw_curly(line, type='r' 462 ) 463 self.draw_straight(line)
464
465 - def draw_swavy(self, line):
466 """ADD the EPS code for this neutralino line.""" 467 self.draw_wavy(line, type='r') 468 self.draw_straight(line)
469
470 - def draw_double(self, line, type='r'):
471 """ADD the EPS code for this neutralino line.""" 472 473 474 length = math.sqrt((line.end.pos_y - line.begin.pos_y)**2 + (line.end.pos_x - line.begin.pos_x) **2) 475 c1 = (line.end.pos_x - line.begin.pos_x)/length 476 c2 = (line.end.pos_y - line.begin.pos_y)/length 477 478 gap = 0.013 479 start2_x = line.begin.pos_x + gap * c1 480 start2_y = line.begin.pos_y + gap * c2 481 stop1_x = line.end.pos_x - gap * c1 482 stop1_y = line.end.pos_y - gap * c2 483 484 485 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 486 stop1_x, stop1_y, '0 Fphoton%s' % (type)) 487 #add the code in the correct format 488 self.text += self.line_format(start2_x, start2_y, 489 line.end.pos_x, line.end.pos_y, '0 Fphoton%s' % (type))
490 491
492 - def put_diagram_number(self, number=0):
493 """ADD the comment 'diagram [number]' just below the diagram.""" 494 495 # Position of the text in [0,1] square 496 x = 0.2 497 y = -0.17 498 # Compute the EPS coordinate 499 x, y = self.rescale(x, y) 500 #write the text 501 self.text += ' %s %s moveto \n' % (x, y) 502 503 if hasattr(self, 'diagram_type'): 504 self.text += '(%s diagram %s ) show\n' % (self.diagram_type, number + 1) # +1 python 505 #starts to count at 506 #zero. 507 else: 508 self.text += '(diagram %s ) show\n' % (number + 1) # +1 python 509 #starts to count at 510 #zero. 511 512 mystr = " (%s)" % ", ".join(["%s=%d" % (key, self.diagram.diagram['orders'][key]) \ 513 for key in sorted(self.diagram.diagram['orders'].keys()) \ 514 if key != 'WEIGHTED']) 515 516 x = 0.6 517 y = -0.17 518 x, y = self.rescale(x, y) 519 #write the text 520 self.text += ' %s %s moveto \n' % (x, y) 521 self.text += '%s show\n' % (mystr)
522 523 524
525 - def associate_number(self, line, number):
526 """Write in the EPS figure the MadGraph5_aMC@NLO number associate to the line. 527 Note that this routine is called only for external particle.""" 528 529 # find the external vertex associate to the line 530 if line.begin.is_external(): 531 vertex = line.begin 532 else: 533 vertex = line.end 534 535 # find the position of this vertex 536 x = vertex.pos_x 537 y = vertex.pos_y 538 539 # Move slightly the position to avoid overlapping 540 if x == 0: 541 x = -0.04 542 else: 543 x += 0.04 544 y = line._has_ordinate(x) 545 546 # Re-scale x,y in order to pass in EPS coordinate 547 x, y = self.rescale(x, y) 548 # Write the EPS text associate 549 self.text += ' %s %s moveto \n' % (x, y) 550 self.text += '(%s) show\n' % (number)
551
552 - def associate_name(self, line, name, loop=False, reverse=False):
553 """ADD the EPS code associate to the name of the particle. Place it near 554 to the center of the line. 555 """ 556 557 is_tadpole = line.begin.pos_x==line.end.pos_x and \ 558 line.begin.pos_y==line.end.pos_y 559 560 if is_tadpole: 561 # Obtain the direction of the propagator supporting the tadpole 562 direction = None 563 for l in line.begin.lines: 564 new_direction = (l.end.pos_x-l.begin.pos_x, l.end.pos_y-l.begin.pos_y) 565 if new_direction==(0.0,0.0): 566 continue 567 norm = math.sqrt(new_direction[0]**2+new_direction[1]**2) 568 new_direction = (new_direction[0]/norm, new_direction[1]/norm) 569 if not direction: 570 direction = new_direction 571 else: 572 if direction not in \ 573 [new_direction, (-new_direction[0],-new_direction[1])]: 574 # logger.error('The case of a five-point vertex'+ 575 # 'yielding a tadpole is not supported') 576 pass 577 # Compute the orthogonal the 578 orthogonal = (-direction[1],direction[0]) 579 580 # Put alias for vertex positions 581 x1, y1 = line.begin.pos_x, line.begin.pos_y 582 x2, y2 = line.end.pos_x, line.end.pos_y 583 584 d = line.get_length() 585 if is_tadpole: 586 scale = 0.08 587 dx, dy = scale*orthogonal[0], scale*orthogonal[1] 588 # compute gap from middle point 589 elif abs(x1 - x2) < 1e-3: 590 dx = 0.015 591 dy = -0.01 592 elif abs(y1 - y2) < 1e-3: 593 dx = -0.01 594 dy = 0.025 595 elif ((x1 < x2) == (y1 < y2)): 596 dx = -0.03 * len(name) 597 dy = 0.02 * len(name) #d * 0.12 598 else: 599 dx = 0.01 #0.05 600 dy = 0.02 #d * 0.12 601 if loop: 602 dx, dy = 1.5* dx, dy 603 if x1 == x2: 604 if y1 < y2: 605 dx, dy = -dx, -dy 606 elif y1 == y2: 607 if x1 >x2: 608 dx, dy = -dx, -dy 609 elif x1 < x2: 610 dx, dy = -dx, -dy 611 if reverse: 612 dx, dy = -dx, -dy 613 614 615 616 # Assign position 617 x_pos = (x1 + x2) / 2 + dx 618 y_pos = (y1 + y2) / 2 + dy 619 620 # Pass in EPS coordinate 621 x_pos, y_pos = self.rescale(x_pos, y_pos) 622 #write EPS code 623 self.text += ' %s %s moveto \n' % (x_pos, y_pos) 624 self.text += '(' + name + ') show\n'
625 626 627 #=============================================================================== 628 # DrawDiagramsEps 629 #===============================================================================
630 -class MultiEpsDiagramDrawer(EpsDiagramDrawer):
631 """Class to write a EPS file containing the asked set of diagram 632 This class follows the DrawDiagram Frameworks. 633 634 The main routine to draw a diagram is 'draw' which call 635 1) initialize: setup things for the diagram (usually open a file) 636 2) convert_diagram : Update the diagram in the correct format if needed 637 3) draw_diagram : Perform diagram dependent operation 638 4) conclude : finish the operation. 639 """ 640 641 # Define where to put the diagrams in the page. This is the coordinate of 642 #the lower left corner of the drawing area of the first graph. and the 643 #dimension associate to this drawing area. 644 645 x_min = 75 646 x_size = 200 647 y_min = 560 648 y_size = 150 649 # Define distances between two drawing area 650 x_gap = 75 651 y_gap = 70 652 653 #define font 654 font=9 655 656 #Defines the number of line-column in a EPS page 657 nb_line = 3 658 nb_col = 2 659 660 blob_size = 1.5 661 662 lower_scale = 5 663 second_scale ={'x_min': 40, 'x_size':150,'y_min':620,'y_size':100, 664 'x_gap':42,'y_gap':30,'font':6,'nb_line':5,'nb_col':3, 665 'blob_size':0.9} 666
667 - def __init__(self, diagramlist=None, filename='diagram.eps', \ 668 model=None, amplitude=None, legend='',diagram_type=''):
669 """Define basic variable and store some global information 670 all argument are optional 671 diagramlist : are the list of object to draw. item should inherit 672 from either base_objects.Diagram or drawing_lib.FeynmanDiagram 673 filename: filename of the file to write 674 model: model associate to the diagram. In principle use only if diagram 675 inherit from base_objects.Diagram 676 amplitude: amplitude associate to the diagram. NOT USE for the moment. 677 In future you could pass the amplitude associate to the object in 678 order to adjust fermion flow in case of Majorana fermion.""" 679 680 #use standard initialization but without any diagram 681 super(MultiEpsDiagramDrawer, self).__init__(None, filename , model, \ 682 amplitude) 683 self.legend = legend 684 #additional information 685 self.block_nb = 0 # keep track of the number of diagram already written 686 self.curr_page = 0 # keep track of the page position 687 self.block_in_page = 0 #ckeep track of the block in a page 688 #compute the number of pages 689 self.npage = 1 690 self.diagram_type = diagram_type 691 692 diagramlist = [d for d in diagramlist if not (isinstance(d, loop_objects.LoopUVCTDiagram) or \ 693 (isinstance(d, loop_objects.LoopDiagram) and d.get('type') < 0))] 694 diagramlist = base_objects.DiagramList(diagramlist) 695 696 limit = self.lower_scale * self.nb_col * self.nb_line 697 if len(diagramlist) < limit: 698 self.npage += (len(diagramlist)-1) // (self.nb_col * self.nb_line) 699 else: 700 add = (len(diagramlist) - limit -1) // \ 701 (self.second_scale['nb_col'] * self.second_scale['nb_line']) 702 self.npage += self.lower_scale + add 703 704 if diagramlist: 705 # diagramlist Argument should be a DiagramList object 706 assert(isinstance(diagramlist, base_objects.DiagramList)) 707 self.diagramlist = diagramlist 708 else: 709 self.diagramlist = None
710
711 - def rescale(self, x, y):
712 """All coordinates belongs to [0,1]. So that in order to have a visible 713 graph we need to re-scale the graph. This method distort the square in 714 a oblong. Deformation are linear.""" 715 716 # Compute the current line and column 717 block_pos = self.block_in_page 718 line_pos = block_pos // self.nb_col 719 col_pos = block_pos % self.nb_col 720 721 # Compute the coordinate of the drawing area associate to this line 722 #and column. 723 x_min = self.x_min + (self.x_size + self.x_gap) * col_pos 724 x_max = self.x_min + self.x_gap * (col_pos) + self.x_size * \ 725 (col_pos + 1) 726 y_min = self.y_min - (self.y_size + self.y_gap) * line_pos 727 y_max = self.y_min - self.y_gap * (line_pos) - self.y_size * \ 728 (line_pos - 1) 729 730 # Re-scale the coordinate in that box 731 x = x_min + (x_max - x_min) * x 732 y = y_min + (y_max - y_min) * y 733 734 return x, y
735
736 - def draw_diagram(self, diagram):
737 """Creates the representation in EPS format associate to a specific 738 diagram.""" 739 740 # Standard method 741 super(MultiEpsDiagramDrawer, self).draw_diagram(diagram, self.block_nb) 742 # But keep track how many diagrams are already drawn 743 744 self.block_nb += 1 745 self.block_in_page +=1
746 747
748 - def draw(self, diagramlist='', opt=None):
749 """Creates the representation in EPS format associate to a specific 750 diagram. 'opt' keeps track of possible option of drawing. Those option 751 are used if we need to convert diagram to Drawing Object. 752 opt is an DrawOption object containing all the possible option on how 753 draw a diagram.""" 754 755 if not opt and EpsDiagramDrawer.april_fool: 756 opt = draw.DrawOption({'external':True, 757 'horizontal':True, 758 'max_size':0.4, 759 'add_gap': 2.5}) 760 761 if diagramlist == '': 762 diagramlist = self.diagramlist 763 764 # Initialize some variable before starting to draw the diagram 765 # This creates the header-library of the output file 766 self.initialize() 767 self.text += '/Helvetica findfont %s scalefont setfont\n' % self.font 768 self.text += ' 50 770 moveto\n' 769 self.text += ' (%s) show\n' % self.legend 770 self.text += ' 525 770 moveto\n' 771 self.text += ' (page %s/%s) show\n' % (self.curr_page + 1, self.npage) 772 self.text += ' 260 50 moveto\n' 773 self.text += ' (Diagrams made by MadGraph5_aMC@NLO) show\n' 774 # Loop on all diagram 775 for i,diagram in enumerate(diagramlist): 776 # Check if they need to be convert in correct format 777 diagram = self.convert_diagram(diagram, self.model, self.amplitude, opt) 778 if diagram==None: 779 continue 780 # Write the code associate to this diagram 781 self.draw_diagram(diagram) 782 783 # Check if the current page is full or not 784 if self.block_in_page % (self.nb_col * self.nb_line) == 0: 785 #if full initialize a new page 786 self.pass_to_next_page() 787 788 #finish operation 789 self.conclude()
790
791 - def pass_to_next_page(self):
792 """Insert text in order to pass to next EPS page.""" 793 794 self.curr_page += 1 795 self.block_in_page = 0 796 if self.curr_page == self.lower_scale: 797 for key, value in self.second_scale.items(): 798 setattr(self, key, value) 799 800 801 self.text += 'showpage\n' 802 self.text += '%%' + 'Page: %s %s \n' % (self.curr_page+1, self.curr_page+1) 803 self.text += '%%PageBoundingBox:-20 -20 600 800\n' 804 self.text += '%%PageFonts: Helvetica\n' 805 self.text += '/Helvetica findfont %s scalefont setfont\n' % self.font 806 self.text += ' 50 770 moveto\n' 807 self.text += ' (%s) show\n' % self.legend 808 self.text += ' 525 770 moveto\n' 809 self.text += ' (page %s/%s) show\n' % (self.curr_page + 1, self.npage) 810 self.text += ' 260 40 moveto\n' 811 self.text += ' (Diagrams made by MadGraph5_aMC@NLO) show\n'
812