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
82 - def initialize(self):
83 """Operation done before starting to create diagram specific EPS content 84 First open the file in write mode then write in it the header and the 85 library of particle type.""" 86 87 # Open file 88 super(EpsDiagramDrawer, self).initialize() 89 90 # File Header 91 text = "%!PS-Adobe-2.0\n" 92 text += "%%" + "BoundingBox: -20 -20 %s %s \n" % \ 93 (self.width, self.height) 94 text += "%%DocumentFonts: Helvetica\n" 95 text += "%%" + "Pages: %s \n" % self.npage 96 self.file.writelines(text) 97 98 # Import the definition of the different way to represent a line 99 self.file.writelines(open(os.path.join(_file_path, \ 100 'iolibs/template_files/drawing_eps_header.inc')).read())
101 102
103 - def conclude(self):
104 """Operation to perform when all code related to a specific diagram are 105 finish. Operation : 106 - Add the 'end of page' code 107 - write unwritten text and close the file. [DrawDiagram.conclude]""" 108 109 # Add an 'end of page statement' 110 self.text = 'showpage\n' 111 self.text += '%%trailer\n' 112 113 #write the diagram file 114 super(EpsDiagramDrawer, self).conclude()
115 116
117 - def rescale(self, x, y):
118 """All coordinates belongs to [0,1]. So that in order to have a visible 119 graph we need to re-scale the graph. This method distort the square in 120 a oblong. Deformation are linear.""" 121 122 # Use the information for the graph position. 'self.x_???,self.y_???? 123 #are the coordinate of the two opposites point of the drawing area. 124 x = self.x_min + (self.x_max - self.x_min) * x 125 y = self.y_min + (self.y_max - self.y_min) * y 126 127 return x, y
128 129
130 - def line_format(self, x1, y1, x2, y2, name):
131 """Specify the text format of a specific Particles. 132 EPS format for Particle is either [X Y X Y NAME] or [X Y X Y NUM NAME]. 133 In this routine we will consider only the first format. The second can 134 be matched by redefining name in [NUM NAME].""" 135 136 # Compute real position for starting/ending point 137 x1, y1 = self.rescale(x1, y1) 138 x2, y2 = self.rescale(x2, y2) 139 140 #return the line in correct format 141 return " %s %s %s %s %s \n" % (x1, y1, x2, y2, name)
142
143 - def draw_vertex(self, vertex, bypass = ['QED','QCD'] ):
144 """Add blob in case on non QED-QCD information""" 145 146 interaction = self.model.get_interaction(vertex.id) 147 if interaction: 148 order = interaction.get('orders') 149 order = [key for key in order.keys() if order[key] and \ 150 key not in bypass] 151 152 if order: 153 x1, y1 = self.rescale(vertex.pos_x, vertex.pos_y) 154 self.text += " %s %s %s 1.0 Fblob \n" % (x1, y1, self.blob_size)
155 156 157
158 - def draw_straight(self, line):
159 """ADD the EPS code for this fermion line.""" 160 161 #add the code in the correct format 162 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 163 line.end.pos_x, line.end.pos_y, 'Ffermion')
164
165 - def draw_curved_dashed(self, line, cercle):
166 """ADD the EPS code for this fermion line.""" 167 168 if not cercle: 169 curvature = 0.4 170 else: 171 curvature = 1 172 173 if (line.begin.pos_x, line.begin.pos_y) == self.curved_part_start: 174 curvature *= -1 175 176 #add the code in the correct format 177 x1, y1 = self.rescale(line.begin.pos_x, line.begin.pos_y) 178 self.text += ' %s %s moveto \n' % (x1, y1) 179 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 180 line.end.pos_x, line.end.pos_y, '%s Fhiggsl' %\ 181 curvature)
182
183 - def draw_curved_straight(self, line, cercle):
184 """ADD the EPS code for this fermion line.""" 185 186 if not cercle: 187 curvature = 0.4 188 else: 189 curvature = 1 190 191 if (line.begin.pos_x, line.begin.pos_y) == self.curved_part_start: 192 curvature *= -1 193 194 #add the code in the correct format 195 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 196 line.end.pos_x, line.end.pos_y, '%s Ffermionl' %\ 197 curvature)
198
199 - def draw_circled_straight(self, line, cercle):
200 """ADD the EPS code for this fermion line.""" 201 202 if not cercle: 203 curvature = 4 204 else: 205 curvature = 5 206 207 is_tadpole = line.begin.pos_x==line.end.pos_x and \ 208 line.begin.pos_y==line.end.pos_y 209 210 if is_tadpole: 211 # Obtain the direction of the propagator supporting the tadpole 212 direction = None 213 for l in line.begin.lines: 214 new_direction = (l.end.pos_x-l.begin.pos_x, l.end.pos_y-l.begin.pos_y) 215 if new_direction==(0.0,0.0): 216 continue 217 norm = math.sqrt(new_direction[0]**2+new_direction[1]**2) 218 new_direction = (new_direction[0]/norm, new_direction[1]/norm) 219 220 if not direction: 221 direction = new_direction 222 else: 223 if direction not in \ 224 [new_direction, (-new_direction[0],-new_direction[1])]: 225 pass 226 # logger.debug('The case of a five-point vertex'+ 227 # 'yielding a tadpole is not supported') 228 continue 229 230 #add the code in the correct format 231 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 232 line.end.pos_x+0.01*direction[0], line.end.pos_y+0.01*direction[1], 233 '%s Ffermionl' % (curvature*7)) 234 else: 235 #add the code in the correct format 236 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 237 line.end.pos_x+0.01, line.end.pos_y+0.01, '%s Ffermionl' %\ 238 curvature)
239 - def draw_dashed(self, line):
240 """ADD the EPS code for this Higgs line.""" 241 242 #add the code in the correct format 243 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 244 line.end.pos_x, line.end.pos_y, 'Fhiggs')
245 246
247 - def draw_circled_dashed(self, line,cercle):
248 """ADD the EPS code for this Higgs line.""" 249 if not cercle: 250 curvature = 4 251 else: 252 curvature = 5 253 254 is_tadpole = line.begin.pos_x==line.end.pos_x and \ 255 line.begin.pos_y==line.end.pos_y 256 257 if is_tadpole: 258 # Obtain the direction of the propagator supporting the tadpole 259 direction = None 260 for l in line.begin.lines: 261 new_direction = (l.end.pos_x-l.begin.pos_x, l.end.pos_y-l.begin.pos_y) 262 if new_direction==(0.0,0.0): 263 continue 264 norm = math.sqrt(new_direction[0]**2+new_direction[1]**2) 265 new_direction = (new_direction[0]/norm, new_direction[1]/norm) 266 267 if not direction: 268 direction = new_direction 269 else: 270 if direction not in \ 271 [new_direction, (-new_direction[0],-new_direction[1])]: 272 # logger.error('The case of a five-point vertex'+ 273 # 'yielding a tadpole is not supported') 274 pass 275 276 #add the code in the correct format 277 x, y = self.rescale(line.begin.pos_x, line.begin.pos_y) 278 self.text += '%s %s moveto'%(x, y) 279 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 280 line.end.pos_x+0.01*direction[0], line.end.pos_y+0.01*direction[1], 281 '%s Fhiggsl' % (curvature*7)) 282 else: 283 #add the code in the correct format 284 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 285 line.end.pos_x+0.01, line.end.pos_y+0.01, '%s Fhiggsl'% curvature)
286
287 - def draw_dotted(self,line):
288 """ADD the EPS code for the ghost line.""" 289 290 #add the code in the correct format 291 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y,\ 292 line.end.pos_x, line.end.pos_y, 'Fghost')
293
294 - def draw_curved_dotted(self, line, cercle):
295 """ADD the EPS code for the ghost line.""" 296 if not cercle: 297 curvature = 0.4 298 else: 299 curvature = 1 300 301 if (line.begin.pos_x, line.begin.pos_y) == self.curved_part_start: 302 curvature *= -1 303 #add the code in the correct format 304 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y,\ 305 line.end.pos_x, line.end.pos_y, '%s Fghostl'% curvature)
306
307 - def draw_circled_dotted(self, line, cercle):
308 """ADD the EPS code for the ghost line.""" 309 if not cercle: 310 curvature = 4 311 else: 312 curvature = 5 313 314 is_tadpole = line.begin.pos_x==line.end.pos_x and \ 315 line.begin.pos_y==line.end.pos_y 316 317 if is_tadpole: 318 # Obtain the direction of the propagator supporting the tadpole 319 direction = None 320 for l in line.begin.lines: 321 new_direction = (l.end.pos_x-l.begin.pos_x, l.end.pos_y-l.begin.pos_y) 322 if new_direction==(0.0,0.0): 323 continue 324 norm = math.sqrt(new_direction[0]**2+new_direction[1]**2) 325 new_direction = (new_direction[0]/norm, new_direction[1]/norm) 326 327 if not direction: 328 direction = new_direction 329 else: 330 if direction not in \ 331 [new_direction, (-new_direction[0],-new_direction[1])]: 332 # logger.error('The case of a five-point vertex'+ 333 # 'yielding a tadpole is not supported') 334 pass 335 336 #add the code in the correct format 337 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 338 line.end.pos_x+0.01*direction[0], line.end.pos_y+0.01*direction[1], 339 '%s Fghostl' % (curvature*7)) 340 else: 341 #add the code in the correct format 342 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y,\ 343 line.end.pos_x+0.01, line.end.pos_y+0.01, '%s Fghostl'% curvature)
344
345 - def draw_wavy(self, line, opt=0, type=''):
346 """ADD the EPS code for this photon line.""" 347 348 #add the code in the correct format 349 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 350 line.end.pos_x, line.end.pos_y, '%d Fphoton%s' % (opt,type))
351
352 - def draw_curved_wavy(self, line, cercle, opt=0, type=''):
353 """ADD the EPS code for this photon line.""" 354 if not cercle: 355 curvature = 0.4 356 else: 357 curvature = 1 358 if (line.begin.pos_x, line.begin.pos_y) == self.curved_part_start: 359 curvature *= -1 360 #add the code in the correct format 361 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 362 line.end.pos_x, line.end.pos_y, '%d %s Fphotonl%s' % (opt,curvature,type))
363
364 - def draw_circled_wavy(self, line, cercle, opt=0, type=''):
365 """ADD the EPS code for this photon line.""" 366 367 if not cercle: 368 curvature = 4 369 else: 370 curvature = 5 371 372 is_tadpole = line.begin.pos_x==line.end.pos_x and \ 373 line.begin.pos_y==line.end.pos_y 374 375 if is_tadpole: 376 # Obtain the direction of the propagator supporting the tadpole 377 direction = None 378 for l in line.begin.lines: 379 new_direction = (l.end.pos_x-l.begin.pos_x, l.end.pos_y-l.begin.pos_y) 380 if new_direction==(0.0,0.0): 381 continue 382 norm = math.sqrt(new_direction[0]**2+new_direction[1]**2) 383 new_direction = (new_direction[0]/norm, new_direction[1]/norm) 384 385 if not direction: 386 direction = new_direction 387 else: 388 if direction not in \ 389 [new_direction, (-new_direction[0],-new_direction[1])]: 390 # logger.error('The case of a five-point vertex'+ 391 # 'yielding a tadpole is not supported') 392 pass 393 394 #add the code in the correct format 395 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 396 line.end.pos_x+0.01*direction[0], line.end.pos_y+0.01*direction[1], 397 '%d %s Fphotonl%s' % (opt,curvature*7,type)) 398 else: 399 #add the code in the correct format 400 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 401 line.end.pos_x+0.01, line.end.pos_y+0.01, 402 '%d %s Fphotonl%s' % (opt,curvature,type))
403
404 - def draw_curly(self, line, type=''):
405 """ADD the EPS code for this gluon line.""" 406 407 # Due to the asymmetry in the way to draw the gluon (everything is draw 408 #upper or below the line joining the points). We have to put conditions 409 #in order to have nice diagram. 410 if (line.begin.pos_x < line.end.pos_x) or \ 411 (line.begin.pos_x == line.end.pos_x and \ 412 line.begin.pos_y > line.end.pos_y): 413 self.text += self.line_format(line.begin.pos_x, 414 line.begin.pos_y, line.end.pos_x, 415 line.end.pos_y, '0 Fgluon%s' % type) 416 else: 417 self.text += self.line_format(line.end.pos_x, 418 line.end.pos_y, line.begin.pos_x, 419 line.begin.pos_y, '0 Fgluon%s' % type)
420
421 - def draw_curved_curly(self, line, cercle, type=''):
422 """ADD the EPS code for this gluon line.""" 423 424 dist = math.sqrt((line.begin.pos_x-line.end.pos_x)**2 + \ 425 (line.begin.pos_y-line.end.pos_y)**2) 426 if not cercle or dist > 0.3: 427 curvature = 0.4 428 else: 429 curvature = 1 430 431 432 # Due to the asymmetry in the way to draw the gluon (everything is draw 433 #upper or below the line joining the points). We have to put conditions 434 #in order to have nice diagram. 435 436 if (line.begin.pos_x, line.begin.pos_y) == self.curved_part_start: 437 curvature *= -1 438 439 self.text += self.line_format(line.end.pos_x, 440 line.end.pos_y, line.begin.pos_x, 441 line.begin.pos_y, '0 %s Fgluonl%s' % (-1*curvature, type))
442 443 444
445 - def draw_scurly(self, line):
446 """ADD the EPS code for this gluino line.""" 447 self.draw_curly(line, type='r' 448 ) 449 self.draw_straight(line)
450
451 - def draw_swavy(self, line):
452 """ADD the EPS code for this neutralino line.""" 453 self.draw_wavy(line, type='r') 454 self.draw_straight(line)
455
456 - def draw_double(self, line, type='r'):
457 """ADD the EPS code for this neutralino line.""" 458 459 460 length = math.sqrt((line.end.pos_y - line.begin.pos_y)**2 + (line.end.pos_x - line.begin.pos_x) **2) 461 c1 = (line.end.pos_x - line.begin.pos_x)/length 462 c2 = (line.end.pos_y - line.begin.pos_y)/length 463 464 gap = 0.013 465 start2_x = line.begin.pos_x + gap * c1 466 start2_y = line.begin.pos_y + gap * c2 467 stop1_x = line.end.pos_x - gap * c1 468 stop1_y = line.end.pos_y - gap * c2 469 470 471 self.text += self.line_format(line.begin.pos_x, line.begin.pos_y, 472 stop1_x, stop1_y, '0 Fphoton%s' % (type)) 473 #add the code in the correct format 474 self.text += self.line_format(start2_x, start2_y, 475 line.end.pos_x, line.end.pos_y, '0 Fphoton%s' % (type))
476 477
478 - def put_diagram_number(self, number=0):
479 """ADD the comment 'diagram [number]' just below the diagram.""" 480 481 # Position of the text in [0,1] square 482 x = 0.2 483 y = -0.17 484 # Compute the EPS coordinate 485 x, y = self.rescale(x, y) 486 #write the text 487 self.text += ' %s %s moveto \n' % (x, y) 488 489 if hasattr(self, 'diagram_type'): 490 self.text += '(%s diagram %s ) show\n' % (self.diagram_type, number + 1) # +1 python 491 #starts to count at 492 #zero. 493 else: 494 self.text += '(diagram %s ) show\n' % (number + 1) # +1 python 495 #starts to count at 496 #zero. 497 498 mystr = " (%s)" % ", ".join(["%s=%d" % (key, self.diagram.diagram['orders'][key]) \ 499 for key in sorted(self.diagram.diagram['orders'].keys()) \ 500 if key != 'WEIGHTED']) 501 502 x = 0.6 503 y = -0.17 504 x, y = self.rescale(x, y) 505 #write the text 506 self.text += ' %s %s moveto \n' % (x, y) 507 self.text += '%s show\n' % (mystr)
508 509 510
511 - def associate_number(self, line, number):
512 """Write in the EPS figure the MadGraph5_aMC@NLO number associate to the line. 513 Note that this routine is called only for external particle.""" 514 515 # find the external vertex associate to the line 516 if line.begin.is_external(): 517 vertex = line.begin 518 else: 519 vertex = line.end 520 521 # find the position of this vertex 522 x = vertex.pos_x 523 y = vertex.pos_y 524 525 # Move slightly the position to avoid overlapping 526 if x == 0: 527 x = -0.04 528 else: 529 x += 0.04 530 y = line._has_ordinate(x) 531 532 # Re-scale x,y in order to pass in EPS coordinate 533 x, y = self.rescale(x, y) 534 # Write the EPS text associate 535 self.text += ' %s %s moveto \n' % (x, y) 536 self.text += '(%s) show\n' % (number)
537
538 - def associate_name(self, line, name, loop=False, reverse=False):
539 """ADD the EPS code associate to the name of the particle. Place it near 540 to the center of the line. 541 """ 542 543 is_tadpole = line.begin.pos_x==line.end.pos_x and \ 544 line.begin.pos_y==line.end.pos_y 545 546 if is_tadpole: 547 # Obtain the direction of the propagator supporting the tadpole 548 direction = None 549 for l in line.begin.lines: 550 new_direction = (l.end.pos_x-l.begin.pos_x, l.end.pos_y-l.begin.pos_y) 551 if new_direction==(0.0,0.0): 552 continue 553 norm = math.sqrt(new_direction[0]**2+new_direction[1]**2) 554 new_direction = (new_direction[0]/norm, new_direction[1]/norm) 555 if not direction: 556 direction = new_direction 557 else: 558 if direction not in \ 559 [new_direction, (-new_direction[0],-new_direction[1])]: 560 # logger.error('The case of a five-point vertex'+ 561 # 'yielding a tadpole is not supported') 562 pass 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