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