Package ete2 :: Package treeview :: Module faces
[hide private]
[frames] | no frames]

Source Code for Module ete2.treeview.faces

  1  __VERSION__="ete2-2.0rev89"  
  2  # #START_LICENSE########################################################### 
  3  # 
  4  # Copyright (C) 2009 by Jaime Huerta Cepas. All rights reserved.   
  5  # email: jhcepas@gmail.com 
  6  # 
  7  # This file is part of the Environment for Tree Exploration program (ETE).  
  8  # http://ete.cgenomics.org 
  9  #   
 10  # ETE is free software: you can redistribute it and/or modify it 
 11  # under the terms of the GNU General Public License as published by 
 12  # the Free Software Foundation, either version 3 of the License, or 
 13  # (at your option) any later version. 
 14  #   
 15  # ETE is distributed in the hope that it will be useful, 
 16  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 17  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 18  # GNU General Public License for more details. 
 19  #   
 20  # You should have received a copy of the GNU General Public License 
 21  # along with ETE.  If not, see <http://www.gnu.org/licenses/>. 
 22  # 
 23  # #END_LICENSE############################################################# 
 24   
 25  try: 
 26      from PyQt4 import QtCore, QtGui 
 27  except: 
 28      import QtCore, QtGui 
 29   
 30  import numpy 
 31   
 32  aafgcolors = { 
 33  'A':"#000000" , 
 34  'R':"#000000" , 
 35  'N':"#000000" , 
 36  'D':"#000000" , 
 37  'C':"#000000" , 
 38  'Q':"#000000" , 
 39  'E':"#000000" , 
 40  'G':"#000000" , 
 41  'H':"#000000" , 
 42  'I':"#000000" , 
 43  'L':"#000000" , 
 44  'K':"#000000" , 
 45  'M':"#000000" , 
 46  'F':"#000000" , 
 47  'P':"#000000" , 
 48  'S':"#000000" , 
 49  'T':"#000000" , 
 50  'W':"#000000" , 
 51  'Y':"#000000" , 
 52  'V':"#000000" , 
 53  'B':"#000000" , 
 54  'Z':"#000000" , 
 55  'X':"#000000", 
 56  '.':"#000000", 
 57  '-':"#000000", 
 58  } 
 59   
 60  aabgcolors = { 
 61  'A':"#C8C8C8" , 
 62  'R':"#145AFF" , 
 63  'N':"#00DCDC" , 
 64  'D':"#E60A0A" , 
 65  'C':"#E6E600" , 
 66  'Q':"#00DCDC" , 
 67  'E':"#E60A0A" , 
 68  'G':"#EBEBEB" , 
 69  'H':"#8282D2" , 
 70  'I':"#0F820F" , 
 71  'L':"#0F820F" , 
 72  'K':"#145AFF" , 
 73  'M':"#E6E600" , 
 74  'F':"#3232AA" , 
 75  'P':"#DC9682" , 
 76  'S':"#FA9600" , 
 77  'T':"#FA9600" , 
 78  'W':"#B45AB4" , 
 79  'Y':"#3232AA" , 
 80  'V':"#0F820F" , 
 81  'B':"#FF69B4" , 
 82  'Z':"#FF69B4" , 
 83  'X':"#BEA06E", 
 84  '.':"#FFFFFF", 
 85  '-':"#FFFFFF", 
 86  } 
 87   
 88  ntfgcolors = { 
 89  'A':'#000000', 
 90  'G':'#000000', 
 91  'I':'#000000', 
 92  'C':'#000000', 
 93  'T':'#000000', 
 94  'U':'#000000', 
 95  '.':"#000000", 
 96  '-':"#000000", 
 97  ' ':"#000000" 
 98   
 99  } 
100   
101  ntbgcolors = { 
102  'A':'#A0A0FF', 
103  'G':'#FF7070', 
104  'I':'#80FFFF', 
105  'C':'#FF8C4B', 
106  'T':'#A0FFA0', 
107  'U':'#FF8080', 
108  '.':"#FFFFFF", 
109  '-':"#FFFFFF", 
110  ' ':"#FFFFFF" 
111   
112  } 
113   
114  __all__ = ["add_face_to_node", "Face", "TextFace", "AttrFace", "ImgFace", "ProfileFace", "ValidationFace", "SequenceFace"] 
115   
116  try: 
117      import psyco 
118      pysco.full() 
119  except: 
120      pass 
121   
122 -def add_face_to_node(face, node, column, aligned=False):
123 """ Links a node with a given face instance. """ 124 125 if column >= len(node.img_style["faces"]): 126 for i in xrange(len(node.img_style["faces"]), column+1): 127 node.img_style["faces"].append([]) 128 # None value will be the pointer to a pixmap 129 node.img_style["faces"][column].append([face, aligned, None])
130
131 -class Face(object):
132 """ Standard definition of a face node object. 133 134 This class is not functional and it should only be used to create 135 other faces objects. By inheriting this class, you set all the 136 essential attributes, however the update_pixmap() function is 137 required to be reimplemented for convenience. 138 139 """ 140
141 - def __init__(self):
142 self.node = None 143 self.type = "pixmap" 144 self.name = "unknown" 145 self.xmargin = 0 146 self.ymargin = 0 147 self.pixmap = None
148 # self.aligned = False 149
150 - def _size(self):
151 if self.pixmap: 152 return self._width(),self._height() 153 else: 154 return 0, 0
155
156 - def _width(self):
157 if self.pixmap: 158 return self.pixmap.width() #+ self.xmargin*2 159 else: 160 return 0
161
162 - def _height(self):
163 if self.pixmap: 164 return self.pixmap.height() #+ self.ymargin*2 165 else: 166 return 0
167
168 - def load_pixmap_from_file(self, filename):
169 self.pixmap = QtGui.QPixmap(filename)
170
171 - def update_pixmap(self):
172 pass
173
174 -class TextFace(Face):
175 """ Creates a new text face object. 176 177 Arguments description 178 --------------------- 179 text: Text to be drawn 180 ftype: Font type, e.g. Arial, Verdana, Courier, (default="Verdana") 181 fsize: Font size, e.g. 10,12,6, (default=10) 182 fgcolor: Foreground font color in RGB name format, e.g. #FF00DD,#000000 (default="#000000") 183 bgcolor: Backgroung font color in RGB name format, e.g. #FFFFFF,#DDDDDD, (default=None) 184 penwidth: Penwdith used to draw the text. (default is 0) 185 """ 186
187 - def __init__(self, text, ftype="Verdana", fsize=10, fgcolor="#000000", bgcolor=None, penwidth=0):
188 Face.__init__(self) 189 190 if bgcolor is None: 191 bgcolor = QtCore.Qt.transparent 192 self.pixmap = None 193 self.type = "text" 194 self.text = str(text) 195 self.pen = QtGui.QPen(QtGui.QColor(fgcolor)) 196 self.pen.setWidth(penwidth) 197 if not bgcolor: 198 self.bgcolor = QtGui.QColor(None) 199 else: 200 self.bgcolor = QtGui.QColor(bgcolor) 201 self.fgcolor = QtGui.QColor(fgcolor) 202 self.font = QtGui.QFont(ftype,fsize)
203
204 - def _height(self):
205 fm = QtGui.QFontMetrics(self.font) 206 h = fm.boundingRect(QtCore.QRect(), \ 207 QtCore.Qt.AlignLeft, \ 208 self.get_text()).height() 209 return h
210 # Other buggy alternatives 211 # fm = QtGui.QFontMetrics(self.font) 212 # h = 0 213 # for l in lines: 214 # if l == lines[0]: 215 # h+=fm.tightBoundingRect(l).height() 216 # else: 217 # h+=fm.height() 218 # return h #+ ((len(lines)-1)*fm.leading()) 219 # 220 # lines = len(self.get_text().split("\n")) 221 # return lines*fm.height() + (lines-1 * fm.leading()) 222 # 223 # h = fm.boundingRect(QtCore.QRect(), \ 224 # QtCore.Qt.AlignLeft, \ 225 # self.get_text()).height() 226 # return h 227 228 229
230 - def _width(self):
231 fm = QtGui.QFontMetrics(self.font) 232 return fm.size(QtCore.Qt.AlignTop, self.text).width()
233
234 - def get_text(self):
235 return self.text
236
237 -class AttrFace(TextFace):
238 """ Creates a new text attribute face object. 239 240 Arguments description 241 --------------------- 242 name: Face's name 243 attr: Node's attribute that will be drawn as text 244 ftype: Font type, e.g. Arial, Verdana, Courier, (default="Verdana") 245 fsize: Font size, e.g. 10,12,6, (default=10) 246 fgcolor: Foreground font color in RGB name format, e.g. #FF00DD,#000000 (default="#000000") 247 bgcolor: Backgroung font color in RGB name format, e.g. #FFFFFF,#DDDDDD, (default=None) 248 penwidth: Penwdith used to draw the text. (default is 0) 249 """ 250
251 - def __init__(self, attr, ftype="Verdana", fsize=10, fgcolor="#000000", bgcolor=None, penwidth=0):
252 Face.__init__(self) 253 TextFace.__init__(self, "", ftype, fsize, fgcolor, bgcolor, penwidth) 254 self.attr = attr 255 self.type = "text"
256
257 - def _width(self):
258 text = str(getattr(self.node, self.attr)) 259 fm = QtGui.QFontMetrics(self.font) 260 return fm.size(QtCore.Qt.AlignTop,text).width()
261
262 - def get_text(self):
263 return str(getattr(self.node, self.attr))
264 265 266
267 -class ImgFace(Face):
268 """ Creates a new image face object. 269 270 Arguments description 271 --------------------- 272 273 img_file: Image file in png,jpg,bmp format 274 """
275 - def __init__(self,img_file):
276 Face.__init__(self) 277 self.img_file = img_file 278 self.name = "ImageFile"
279
280 - def update_pixmap(self):
281 self.load_pixmap_from_file(self.img_file)
282 283
284 -class ProfileFace(Face):
285 """ Creates a new vector profile face object. 286 287 Arguments description 288 --------------------- 289 290 max_v: maximum value used to build the build the plot scale. 291 max_v: manimum value used to build the build the plot scale. 292 center_v: Center value used to scale plot and heat map. 293 width: Plot width in pixels. (defaulf=200) 294 height: Plot width in pixels. (defaulf=40) 295 style: Plot style: "lines", "bars", "cbars" or "heatmap". (default="lines") 296 """
297 - def __init__(self,max_v,min_v,center_v,width=200,height=40,style="lines",colorscheme=2):
298 Face.__init__(self) 299 300 self.width = width 301 self.height = height 302 self.max_value = max_v 303 self.min_value = min_v 304 self.center_v = center_v 305 self.xmargin = 1 306 self.ymargin = 1 307 self.style = style 308 self.colorscheme = colorscheme
309
310 - def update_pixmap(self):
311 if self.style=="lines": 312 self.draw_line_profile() 313 elif self.style=="heatmap": 314 self.draw_heatmap_profile() 315 elif self.style=="bars": 316 self.draw_bar_profile() 317 elif self.style=="cbars": 318 self.draw_centered_bar_profile()
319
320 - def get_color_gradient(self):
321 colors = [] 322 if self.colorscheme == 0: 323 # Blue and Green 324 for a in xrange(100,0,-1): 325 color=QtGui.QColor() 326 color.setRgb( 200-2*a,255,200-2*a ) 327 colors.append(color) 328 for a in xrange(0,100): 329 color=QtGui.QColor() 330 color.setRgb( 200-2*a,200-2*a,255 ) 331 colors.append(color) 332 # color=QtGui.QColor() 333 # color.setRgb( 0,255,255 ) 334 # colors.append(color) 335 336 elif self.colorscheme == 1: 337 for a in xrange(100,0,-1): 338 color=QtGui.QColor() 339 color.setRgb( 200-2*a,255,200-2*a ) 340 colors.append(color) 341 342 for a in xrange(0,100): 343 color=QtGui.QColor() 344 color.setRgb( 255,200-2*a,200-2*a ) 345 colors.append(color) 346 # color=QtGui.QColor() 347 # color.setRgb(255,255,0 ) 348 # colors.append(color) 349 350 else: 351 # Blue and Red 352 for a in xrange(100,0,-1): 353 color=QtGui.QColor() 354 color.setRgb( 200-2*a,200-2*a,255 ) 355 colors.append(color) 356 for a in xrange(0,100): 357 color=QtGui.QColor() 358 color.setRgb( 255,200-2*a,200-2*a ) 359 colors.append(color) 360 # color=QtGui.QColor() 361 # color.setRgb( 255,0,255 ) 362 # colors.append(color) 363 colors.append(QtGui.QColor("white")) 364 365 return colors
366
367 - def draw_bar_profile(self):
368 # Calculate vector 369 mean_vector = self.node.profile 370 deviation_vector = self.node.deviation 371 # If no vector, skip 372 if mean_vector is None: 373 return 374 375 colors = self.get_color_gradient() 376 377 vlength = len(mean_vector) 378 # pixels per array position 379 profile_width = self.width - self.xmargin*2 - 40 380 profile_height= self.height - self.ymargin*2 381 382 x_alpha = float( profile_width / (len(mean_vector)) ) 383 y_alpha = float ( profile_height / (self.max_value-self.min_value) ) 384 385 # Creates a pixmap 386 self.pixmap = QtGui.QPixmap(self.width,self.height) 387 self.pixmap.fill(QtGui.QColor("white")) 388 p = QtGui.QPainter(self.pixmap) 389 390 x2 = self.xmargin 391 y = self.ymargin 392 393 # Mean and quartiles y positions 394 mean_line_y = y + profile_height/2 395 line2_y = mean_line_y + profile_height/4 396 line3_y = mean_line_y - profile_height/4 397 398 # Draw axis and scale 399 p.setPen(QtGui.QColor("black")) 400 p.drawRect(x2,y,profile_width, profile_height-1) 401 p.setFont(QtGui.QFont("Verdana",8)) 402 p.drawText(self.xmargin+profile_width,y+10,"%0.3f" %self.max_value) 403 p.drawText(self.xmargin+profile_width,y+profile_height,"%0.3f" %self.min_value) 404 405 dashedPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor("#ddd")), 0) 406 dashedPen.setStyle(QtCore.Qt.DashLine) 407 408 # Draw hz grid 409 p.setPen(dashedPen) 410 p.drawLine(x2+1, mean_line_y, profile_width-2, mean_line_y ) 411 p.drawLine(x2+1, line2_y, profile_width-2, line2_y ) 412 p.drawLine(x2+1, line3_y, profile_width-2, line3_y ) 413 414 415 # Draw bars 416 for pos in xrange(vlength): 417 # first and second X pixel positions 418 x1 = x2 419 x2 = x1 + x_alpha 420 421 dev1 = self.fit_to_scale( deviation_vector[pos] ) 422 mean1 = self.fit_to_scale( mean_vector[pos] ) 423 424 # If nan value, skip 425 if not numpy.isfinite(mean1): 426 continue 427 428 # Set heatmap color 429 if mean1>self.center_v: 430 color_index = int(abs(((self.center_v-mean1)*100)/(self.max_value-self.center_v))) 431 customColor = colors[100+color_index] 432 elif mean1<self.center_v: 433 color_index = int(abs(((self.center_v-mean1)*100)/(self.min_value-self.center_v))) 434 customColor = colors[100-color_index] 435 else: 436 customColor = colors[0] 437 438 # mean bar high 439 mean_y1 = int ( (mean1 - self.min_value) * y_alpha) 440 441 # Draw bar border 442 p.setPen(QtGui.QColor("black")) 443 #p.drawRect(x1+2,mean_y1, x_alpha-3, profile_height-mean_y1+1) 444 # Fill bar with custom color 445 p.fillRect(x1+3,profile_height-mean_y1, x_alpha-4, mean_y1-1, QtGui.QBrush(customColor)) 446 447 # Draw error bars 448 if dev1 != 0: 449 dev_up_y1 = int((mean1+dev1 - self.min_value) * y_alpha) 450 dev_down_y1 = int((mean1-dev1 - self.min_value) * y_alpha) 451 p.drawLine(x1+x_alpha/2, profile_height-dev_up_y1 ,x1+x_alpha/2, profile_height-dev_down_y1 ) 452 p.drawLine(x1-1+x_alpha/2, profile_height-dev_up_y1, x1+1+x_alpha/2, profile_height-dev_up_y1 ) 453 p.drawLine(x1-1+x_alpha/2, profile_height-dev_down_y1, x1+1+x_alpha/2, profile_height-dev_down_y1 )
454
456 # Calculate vector 457 mean_vector = self.node.profile 458 deviation_vector = self.node.deviation 459 # If no vector, skip 460 if mean_vector is None: 461 return 462 463 colors = self.get_color_gradient() 464 465 vlength = len(mean_vector) 466 # pixels per array position 467 profile_width = self.width - self.xmargin*2 - 40 468 profile_height= self.height - self.ymargin*2 469 470 x_alpha = float( profile_width / (len(mean_vector)) ) 471 y_alpha_up = float ( (profile_height/2) / (self.max_value-self.center_v) ) 472 y_alpha_down = float ( (profile_height/2) / (self.min_value-self.center_v) ) 473 474 # Creates a pixmap 475 self.pixmap = QtGui.QPixmap(self.width,self.height) 476 self.pixmap.fill(QtGui.QColor("white")) 477 p = QtGui.QPainter(self.pixmap) 478 479 x2 = self.xmargin 480 y = self.ymargin 481 482 # Mean and quartiles y positions 483 mean_line_y = y + profile_height/2 484 line2_y = mean_line_y + profile_height/4 485 line3_y = mean_line_y - profile_height/4 486 487 # Draw axis and scale 488 p.setPen(QtGui.QColor("black")) 489 p.drawRect(x2,y,profile_width, profile_height-1) 490 p.setFont(QtGui.QFont("Verdana",8)) 491 p.drawText(self.xmargin+profile_width,y+10,"%0.3f" %self.max_value) 492 p.drawText(self.xmargin+profile_width,y+profile_height,"%0.3f" %self.min_value) 493 p.drawText(self.xmargin+profile_width,mean_line_y,"%0.3f" %self.center_v) 494 495 dashedPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor("#ddd")), 0) 496 dashedPen.setStyle(QtCore.Qt.DashLine) 497 498 # Draw hz grid 499 p.setPen(dashedPen) 500 p.drawLine(x2+1, mean_line_y, profile_width-2, mean_line_y ) 501 p.drawLine(x2+1, line2_y, profile_width-2, line2_y ) 502 p.drawLine(x2+1, line3_y, profile_width-2, line3_y ) 503 504 505 # Draw bars 506 for pos in xrange(vlength): 507 # first and second X pixel positions 508 x1 = x2 509 x2 = x1 + x_alpha 510 511 dev1 = self.fit_to_scale( deviation_vector[pos] ) 512 mean1 = self.fit_to_scale( mean_vector[pos] ) 513 514 # If nan value, skip 515 if not numpy.isfinite(mean1): 516 continue 517 518 # Set heatmap color 519 if mean1>self.center_v: 520 color_index = int(abs(((self.center_v-mean1)*100)/(self.max_value-self.center_v))) 521 customColor = colors[100+color_index] 522 elif mean1<self.center_v: 523 color_index = int(abs(((self.center_v-mean1)*100)/(self.min_value-self.center_v))) 524 customColor = colors[100-color_index] 525 else: 526 customColor = colors[0] 527 528 # mean bar high 529 if mean1<self.center_v: 530 mean_y1 = int(abs((mean1 - self.center_v) * y_alpha_down)) 531 else: 532 mean_y1 = int(abs((mean1 - self.center_v) * y_alpha_up)) 533 534 # Draw bar border 535 p.setPen(QtGui.QColor("black")) 536 #p.drawRect(x1+2,mean_y1, x_alpha-3, profile_height-mean_y1+1) 537 # Fill bar with custom color 538 if mean1<self.center_v: 539 p.fillRect(x1+3, mean_line_y, x_alpha-4, mean_y1, QtGui.QBrush(customColor)) 540 else: 541 p.fillRect(x1+3, mean_line_y-mean_y1, x_alpha-4, mean_y1+1, QtGui.QBrush(customColor)) 542 543 # Draw error bars 544 if dev1 != 0: 545 if mean1<self.center_v: 546 dev_up_y1 = int((mean1+dev1 - self.center_v) * y_alpha_down) 547 dev_down_y1 = int((mean1-dev1 - self.center_v) * y_alpha_down) 548 p.drawLine(x1+x_alpha/2, mean_line_y+dev_up_y1 ,x1+x_alpha/2, mean_line_y+dev_down_y1 ) 549 p.drawLine(x1-1+x_alpha/2, mean_line_y+dev_up_y1 ,x1+1+x_alpha/2, mean_line_y+dev_up_y1 ) 550 p.drawLine(x1-1+x_alpha/2, mean_line_y+dev_down_y1 ,x1+1+x_alpha/2, mean_line_y+dev_down_y1 ) 551 else: 552 dev_up_y1 = int((mean1+dev1 - self.center_v) * y_alpha_up) 553 dev_down_y1 = int((mean1-dev1 - self.center_v) * y_alpha_up) 554 p.drawLine(x1+x_alpha/2, mean_line_y-dev_up_y1 ,x1+x_alpha/2, mean_line_y-dev_down_y1 ) 555 p.drawLine(x1-1+x_alpha/2, mean_line_y-dev_up_y1 ,x1+1+x_alpha/2, mean_line_y-dev_up_y1 ) 556 p.drawLine(x1-1+x_alpha/2, mean_line_y-dev_down_y1 ,x1+1+x_alpha/2, mean_line_y-dev_down_y1 )
557
558 - def draw_line_profile(self):
559 # Calculate vector 560 mean_vector = self.node.profile 561 deviation_vector = self.node.deviation 562 if mean_vector is None: 563 return 564 565 vlength = len(mean_vector) 566 # pixels per array position 567 profile_width = self.width - self.xmargin*2 - 40 568 profile_height= self.height - self.ymargin*2 569 570 571 x_alpha = float( profile_width / (len(mean_vector)-1) ) 572 y_alpha = float ( profile_height / (self.max_value-self.min_value) ) 573 574 # Creates a pixmap 575 self.pixmap = QtGui.QPixmap(self.width,self.height) 576 self.pixmap.fill(QtGui.QColor("white")) 577 p = QtGui.QPainter(self.pixmap) 578 579 x2 = self.xmargin 580 y = self.ymargin 581 582 # Mean and quartiles y positions 583 mean_line_y = (self.center_v - self.min_value) * y_alpha 584 line2_y = ((self.center_v+abs(self.min_value/2)) - self.min_value) * y_alpha 585 line3_y = ((self.center_v-abs(self.max_value/2)) - self.min_value) * y_alpha 586 587 # Draw axis and scale 588 p.setPen(QtGui.QColor("black")) 589 p.drawRect(x2,y,profile_width, profile_height-1) 590 p.setFont(QtGui.QFont("Verdana",8)) 591 p.drawText(self.xmargin+profile_width,y+10,"%0.3f" %self.max_value) 592 p.drawText(self.xmargin+profile_width,y+profile_height,"%0.3f" %self.min_value) 593 p.drawText(self.xmargin+profile_width,mean_line_y+5,"%0.3f" %self.center_v) 594 595 dashedPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor("#ddd")), 0) 596 dashedPen.setStyle(QtCore.Qt.DashLine) 597 598 # Draw hz grid 599 p.setPen(dashedPen) 600 p.drawLine(x2+1, mean_line_y, profile_width-2, mean_line_y ) 601 p.drawLine(x2+1, line2_y, profile_width-2, line2_y ) 602 p.drawLine(x2+1, line3_y, profile_width-2, line3_y ) 603 604 # Draw lines 605 for pos in xrange(0,vlength-1): 606 dev1 = self.fit_to_scale( deviation_vector[pos] ) 607 dev2 = self.fit_to_scale( deviation_vector[pos+1] ) 608 mean1 = self.fit_to_scale( mean_vector[pos] ) 609 mean2 = self.fit_to_scale( mean_vector[pos+1] ) 610 # first and second X pixel positions 611 x1 = x2 612 x2 = x1 + x_alpha 613 614 # Draw vt grid 615 if x2 < profile_width: 616 p.setPen(dashedPen) 617 p.drawLine(x2, y+1, x2, profile_height-2) 618 619 # If nan values, continue 620 if not numpy.isfinite(mean1) or not numpy.isfinite(mean2): 621 continue 622 623 # First Y postions for mean 624 mean_y1 = (mean1 - self.min_value) * y_alpha 625 # Second Y postions for mean 626 mean_y2 = (mean2 - self.min_value) * y_alpha 627 # Draw blue mean line 628 p.setPen(QtGui.QColor("blue")) 629 p.drawLine(x1,mean_y1, x2, mean_y2) 630 631 if dev1!= 0 and dev2!=0: 632 # First Y postions for deviations 633 dev_up_y1 = (mean1+dev1 - self.min_value) * y_alpha 634 dev_down_y1 = (mean1-dev1 - self.min_value) * y_alpha 635 # Second Y postions for deviations 636 dev_up_y2 = (mean2+dev2 - self.min_value) * y_alpha 637 dev_down_y2 = (mean2-dev2 - self.min_value) * y_alpha 638 # Draw red deviation lines 639 p.setPen(QtGui.QColor("red")) 640 p.drawLine(x1,dev_up_y1, x2, dev_up_y2) 641 p.setPen(QtGui.QColor("red")) 642 p.drawLine(x1,dev_down_y1, x2, dev_down_y2)
643 644
645 - def draw_heatmap_profile(self):
646 # Calculate vector 647 vector = self.node.profile 648 deviation = self.node.deviation 649 # If no vector, skip 650 if vector is None: 651 return 652 653 colors = self.get_color_gradient() 654 655 leaves = self.node.get_leaves() 656 657 vlength = len(vector) 658 # pixels per array position 659 img_height = self.height * len(leaves) 660 profile_width = self.width - self.xmargin*2 661 profile_height= img_height - self.ymargin*2 662 663 x_alpha = float( profile_width / (len(vector)) ) 664 665 # Creates a pixmap 666 self.pixmap = QtGui.QPixmap(self.width,img_height) 667 self.pixmap.fill(QtGui.QColor("white")) 668 p = QtGui.QPainter(self.pixmap) 669 670 x2 = self.xmargin 671 y = self.ymargin 672 y_step = self.height 673 for leaf in leaves: 674 mean_vector = leaf.profile 675 deviation_vector = leaf.deviation 676 # Draw heatmap 677 for pos in xrange(vlength): 678 # first and second X pixel positions 679 x1 = x2 680 x2 = x1 + x_alpha 681 dev1 = self.fit_to_scale( deviation_vector[pos] ) 682 mean1 = self.fit_to_scale( mean_vector[pos] ) 683 # Set heatmap color 684 if not numpy.isfinite(mean1): 685 customColor = QtGui.QColor("#000000") 686 elif mean1>self.center_v: 687 color_index = int(abs(((self.center_v-mean1)*100)/(self.max_value-self.center_v))) 688 customColor = colors[100+color_index] 689 elif mean1<self.center_v: 690 color_index = int(abs(((self.center_v-mean1)*100)/(self.min_value-self.center_v))) 691 customColor = colors[100-color_index] 692 else: 693 customColor = colors[-1] 694 695 # Fill bar with custom color 696 p.fillRect(x1, y, x_alpha, y_step, QtGui.QBrush(customColor)) 697 y+= y_step 698 x2 = self.xmargin
699
700 - def fit_to_scale(self,v):
701 if v<self.min_value: 702 return float(self.min_value) 703 elif v>self.max_value: 704 return float(self.max_value) 705 else: 706 return float(v)
707
708 -class ValidationFace(Face):
709 """ Creates a new clustering validation face """ 710
711 - def __init__(self,fsize=10):
712 Face.__init__(self) 713 self.seq = seq 714 self.name = "validation" 715 self.fsize= fsize 716 self.font = QtGui.QFont("Courier",self.fsize) 717 self.style = seqtype
718
719 - def update_pixmap(self):
720 pass
721
722 -class SequenceFace(Face):
723 """ Creates a new molecular sequence face object. 724 725 Arguments description 726 --------------------- 727 seq: Sequence string to be drawn 728 seqtype: Type of sequence: "nt" or "aa" 729 fsize: Font size, (default=10) 730 """ 731
732 - def __init__(self, seq, seqtype, fsize=10, aafg=aafgcolors, aabg=aabgcolors, ntfg=ntfgcolors, ntbg=ntbgcolors):
733 Face.__init__(self) 734 self.seq = seq 735 self.name = "sequence" 736 self.fsize= fsize 737 self.font = QtGui.QFont("Courier", self.fsize) 738 self.style = seqtype 739 self.aafg = aafg 740 self.aabg = aabg 741 self.ntfg = ntfg 742 self.ntbg = ntbg
743
744 - def update_pixmap(self):
745 746 747 fm = QtGui.QFontMetrics(self.font) 748 height = fm.leading() + fm.overlinePos() + fm.underlinePos() 749 width = fm.size(QtCore.Qt.AlignTop, self.seq).width() 750 751 self.pixmap = QtGui.QPixmap(width,height) 752 self.pixmap.fill() 753 p = QtGui.QPainter(self.pixmap) 754 x = 0 755 y = height - fm.underlinePos()*2 756 757 p.setFont(self.font) 758 759 for letter in self.seq: 760 letter = letter.upper() 761 if self.style=="nt": 762 letter_brush = QtGui.QBrush(QtGui.QColor(self.ntbg.get(letter,"#ffffff" ))) 763 letter_pen = QtGui.QPen(QtGui.QColor(self.ntfg.get(letter, "#000000"))) 764 else: 765 letter_brush = QtGui.QBrush(QtGui.QColor(self.aabg.get(letter,"#ffffff" ))) 766 letter_pen = QtGui.QPen(QtGui.QColor(self.aafg.get(letter,"#000000" ))) 767 768 p.setPen(letter_pen) 769 p.fillRect(x,0,width, height,letter_brush) 770 p.drawText(x, y, letter) 771 x += float(width)/len(self.seq) 772 p.end()
773