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