def iLabel(node, *args, **kargs): #code for making specialized faces for intermediates mostly cribbed from the ete2 website example (though not interactive): # http://pythonhosted.org/ete2/tutorial/tutorial_drawing.html#creating-your-custom-interactive-item-faces my_label = node.name ellipse = QGraphicsEllipseItem( 0, 0, fontSize * 2, fontSize * 2 ) #I think the first two are coords of center; second pair is major/minor axis ellipse.setPen(QPen(QColor('black'))) ellipse.setBrush(QBrush(QColor('white'))) text = QGraphicsSimpleTextItem(my_label) text.setParentItem(ellipse) text.setBrush(QBrush(QColor("black"))) font = QFont("Arial", fontSize * .9, weight=80) font.setLetterSpacing(1, 2) #add 2 pixels between letters for legibility text.setFont(font) #Center text according to masterItem size tw = text.boundingRect().width() th = text.boundingRect().height() center = ellipse.boundingRect().center() text.setPos( center.x() + 1 - tw / 2, center.y() - th / 2 ) #since the last letter has an extra 2 pixels after it from the spacing command, adjust center to compensate return ellipse
def update_items(self): #self.item = QGraphicsRectItem(0,0,self._total_w, self.row_h) seq_width = 0 nopen = QPen(QtCore.Qt.NoPen) font = QFont("Courier", self.fsize) rect_cls = self.InteractiveLetterItem if self.interact else QGraphicsRectItem for i, letter in enumerate(self.seq): width = self.col_w for m in self.special_col: if m[0] < i <= m[1]: width = self.alt_col_w break #load interactive item if called correspondingly rectItem = rect_cls(0, 0, width, self.row_h, parent=self.item) rectItem.setX(seq_width) # to give correct X to children item rectItem.setBrush(self.bg_col[letter]) rectItem.setPen(nopen) if self.interact: if self.codon: rectItem.codon = '%s, %d: %s' % ( self.seq[i], i, self.codon[i * 3:i * 3 + 3]) else: rectItem.codon = '%s, %d' % (self.seq[i], i) # write letter if enough space if width >= self.fsize: text = QGraphicsSimpleTextItem(letter, parent=rectItem) text.setFont(font) text.setBrush(self.fg_col[letter]) # Center text according to rectItem size tw = text.boundingRect().width() th = text.boundingRect().height() text.setPos((width - tw) / 2, (self.row_h - th) / 2) seq_width += width self.width = seq_width
def draw_y_axis(self): lineItem = QGraphicsLineItem(0, self.coordY(self.ylim[0]), 0, self.coordY(self.ylim[1]), parent=self.item) lineItem.setPen(QPen(QColor('black'))) lineItem.setZValue(10) max_w = 0 for y in set(self.hlines + list(self.ylim)): lineItem = QGraphicsLineItem(0, self.coordY(y), -5, self.coordY(y), parent=self.item) lineItem.setPen(QPen(QColor('black'))) lineItem.setZValue(10) text = QGraphicsSimpleTextItem(str(y)) text.setFont(QFont("Arial", self.fsize-2)) text.setParentItem(self.item) tw = text.boundingRect().width() max_w = tw if tw > max_w else max_w th = text.boundingRect().height() # Center text according to masterItem size text.setPos(-tw - 5, self.coordY(y)-th/2) if self.ylabel: text = QGraphicsSimpleTextItem(self.ylabel) text.setFont(QFont("Arial", self.fsize-1)) text.setParentItem(self.item) text.rotate(-90) tw = text.boundingRect().width() th = text.boundingRect().height() # Center text according to masterItem size text.setPos(-th -5-max_w, tw/2+self.coordY(sum(self.ylim)/2))
def iLabel(node, *args, **kargs): #code for making specialized faces for intermediates mostly cribbed from the ete2 website example (though not interactive): # http://pythonhosted.org/ete2/tutorial/tutorial_drawing.html#creating-your-custom-interactive-item-faces my_label = node.name ellipse = QGraphicsEllipseItem(0,0,fontSize*2,fontSize*2) #I think the first two are coords of center; second pair is major/minor axis ellipse.setPen(QPen(QColor( 'black' ))) ellipse.setBrush(QBrush(QColor( 'white' ))) text = QGraphicsSimpleTextItem(my_label) text.setParentItem(ellipse) text.setBrush(QBrush(QColor("black"))) font = QFont("Arial",fontSize*.9,weight=80) font.setLetterSpacing(1, 2) #add 2 pixels between letters for legibility text.setFont(font) #Center text according to masterItem size tw = text.boundingRect().width() th = text.boundingRect().height() center = ellipse.boundingRect().center() text.setPos(center.x()+1-tw/2, center.y()-th/2) #since the last letter has an extra 2 pixels after it from the spacing command, adjust center to compensate return ellipse
def update_items(self): #self.item = QGraphicsRectItem(0,0,self._total_w, self.row_h) seq_width = 0 nopen = QPen(QtCore.Qt.NoPen) font = QFont("Courier", self.fsize) rect_cls = self.InteractiveLetterItem if self.interact else QGraphicsRectItem for i, letter in enumerate(self.seq): width = self.col_w for m in self.special_col: if m[0] < i <= m[1]: width = self.alt_col_w break #load interactive item if called correspondingly rectItem = rect_cls(0, 0, width, self.row_h, parent=self.item) rectItem.setX(seq_width) # to give correct X to children item rectItem.setBrush(self.bg_col[letter]) rectItem.setPen(nopen) if self.interact: if self.codon: rectItem.codon = '%s, %d: %s' % (self.seq[i], i, self.codon[i*3:i*3+3]) else: rectItem.codon = '%s, %d' % (self.seq[i], i) # write letter if enough space if width >= self.fsize: text = QGraphicsSimpleTextItem(letter, parent=rectItem) text.setFont(font) text.setBrush(self.fg_col[letter]) # Center text according to rectItem size tw = text.boundingRect().width() th = text.boundingRect().height() text.setPos((width - tw)/2, (self.row_h - th)/2) seq_width += width self.width = seq_width
def draw_y_axis(self): lineItem = QGraphicsLineItem(0, self.coordY(self.ylim[0]), 0, self.coordY(self.ylim[1]), parent=self.item) lineItem.setPen(QPen(QColor('black'))) lineItem.setZValue(10) max_w = 0 for y in set(self.hlines + list(self.ylim)): lineItem = QGraphicsLineItem(0, self.coordY(y), -5, self.coordY(y), parent=self.item) lineItem.setPen(QPen(QColor('black'))) lineItem.setZValue(10) text = QGraphicsSimpleTextItem(str(y)) text.setFont(QFont("Arial", self.fsize - 2)) text.setParentItem(self.item) tw = text.boundingRect().width() max_w = tw if tw > max_w else max_w th = text.boundingRect().height() # Center text according to masterItem size text.setPos(-tw - 5, self.coordY(y) - th / 2) if self.ylabel: text = QGraphicsSimpleTextItem(self.ylabel) text.setFont(QFont("Arial", self.fsize - 1)) text.setParentItem(self.item) text.rotate(-90) tw = text.boundingRect().width() th = text.boundingRect().height() # Center text according to masterItem size text.setPos(-th - 5 - max_w, tw / 2 + self.coordY(sum(self.ylim) / 2))
def update_items(self): rect_cls = QGraphicsRectItem self.item = rect_cls(0, 0, self.width, self.row_h) seq_width = 0 nopen = QPen(Qt.NoPen) font = QFont("Courier", self.fsize) for i, letter in enumerate(self.seq): width = self.col_w for reg in self.special_col: if reg[0] < i <= reg[1]: width = self.alt_col_w break rectitem = rect_cls(0, 0, width, self.row_h, parent=self.item) rectitem.setX(seq_width) # to give correct X to children item rectitem.setBrush(self.bg_col[letter]) rectitem.setPen(nopen) # write letter if enough space if width >= self.fsize: text = QGraphicsSimpleTextItem(letter, parent=rectitem) text.setFont(font) text.setBrush(self.fg_col[letter]) # Center text according to rectitem size txtw = text.boundingRect().width() txth = text.boundingRect().height() text.setPos((width - txtw) / 2, (self.row_h - txth) / 2) seq_width += width self.width = seq_width
def update_items(self): try: max_codons = math.ceil( max([len(x) for x in self.readict.values()]) / 2.0) * 2 except: max_codons = 1 if self.maxcodon: max_codons = max(max_codons, self.maxcodon) max_h = max_codons * (self.h + self.spacer) rect_cls = QGraphicsRectItem self.item = rect_cls() nopen = QPen(QColor('#EEEEEE')) nobrush = QBrush(Qt.NoBrush) width = self.mgl font = QFont(self.ffamily, self.fsize) for aa in self.aa_list: codons = self.readict.get(aa, []) tot_codons = len(codons) hpos = (self.h + self.spacer) * (max_codons - tot_codons) / 2.0 for cod in codons: rectitem = rect_cls(0, 0, self.w, self.h, parent=self.item) rectitem.setX(width) rectitem.setY(hpos) rectitem.setBrush(self.bgcolor[aa]) rectitem.setPen(nopen) hpos += (self.h + self.spacer) # write letter if enough space if self.w >= self.fsize: text = QGraphicsSimpleTextItem(cod, parent=rectitem) text.setFont(font) text.setBrush(self.fgcolor[aa]) # Center text according to rectitem size txtw = text.boundingRect().width() txth = text.boundingRect().height() text.setPos((self.w - txtw) / 2, (self.h - txth) / 2) # this only happen if codon reassignment not found for aa # we do not need a spacer if it's an internal node (I hope) if hpos == 0 and self.is_leaf: rectitem = rect_cls(0, 0, self.w, self.h, parent=self.item) rectitem.setX(width) rectitem.setY(hpos) rectitem.setBrush(nobrush) rectitem.setPen(nopen) width += self.w + self.spacer self.width = width self.item.setPen(nopen) self.item.setRect(0, 0, self.width, max_h)
def add_text(self): if (self.labels): center = self.item.boundingRect().center() text = QGraphicsSimpleTextItem(str(self.labels)) text.setFont(QFont("Arial", self.label_size)) text.setParentItem(self.item) text.setBrush(QBrush(QColor('#ddd'))) tw = text.boundingRect().width() / 2. th = text.boundingRect().height() / 2. x = -tw + center.x() y = -th + center.y() # Center text according to masterItem size text.setPos(x, y)
def update_items(self): rect_cls = QGraphicsRectItem nobrush = QBrush(Qt.NoBrush) nopen = QPen(QColor('#FFFFFF')) grad = Qt.NoBrush self.item = rect_cls() for codon in self.codons.keys(): rectitem = rect_cls(self.width, self.margin, self.w, self.h, parent=self.item) total_rea = len(self.aa_list[codon]) if total_rea > 0: grad = QLinearGradient(QPointF(0, 0.5), QPointF(1, 0.5)) grad.setCoordinateMode(QLinearGradient.ObjectBoundingMode) pointpos = 1.0 / total_rea starting = -0.001 for reqcol, aa in enumerate(self.aa_list[codon]): curcol = self.bgcolor[aa] # use the same color twice to mark start and end grad.setColorAt(starting + 0.001, curcol) starting += pointpos grad.setColorAt(starting, curcol) # grad.setColorAt(starting, QColor(curcol)) # put small rec in big rec # Comment award of the year ! brush = QBrush(QColor('#CCCCCC')) pen = QPen(QColor('#BBBBBB')) if self.codons[codon]: brush = QBrush(grad) pen = QPen(QColor('#000000')) rectitem.setBrush(brush) rectitem.setPen(pen) # Center text according to rectitem size text = QGraphicsSimpleTextItem(self.codons[codon], parent=rectitem) text.setFont(self.font) text.setBrush(self.fgcolor) center = rectitem.boundingRect().center() txtw = text.boundingRect().width() txth = text.boundingRect().height() text.setPos(center.x() - txtw / 2, center.y() - txth / 2) self.width += self.w + self.margin # now plot the big rect (with margin) self.item.setPen(nopen) self.item.setBrush(nobrush) self.item.setRect(0, 0, self.width, self.h + (2 * self.margin))
def __init__(self, table, vector, mass=1.0): """Documentation here""" self.name = table.name self._mediator = Mediator() # layout widget x, y = vector.x, vector.y text = QGraphicsSimpleTextItem('{0} as {1}'.format(self.name, self.alias)) width = text.boundingRect().width() QGraphicsRectItem.__init__(self, x, y, width + 10, 22) self.table = table.alias(self.alias) self.setBrush(Qt.cyan) self.setPen(Qt.darkCyan) self.width = width + 10 self.height = 22 self.setFlag(self.ItemIsSelectable, True) text.setParentItem(self) text.setX(x + 5) text.setY(y + 5) self.point = vector self.mass = mass self.velocity = Vector(0, 0) self.force = Vector(0, 0) self.instances.append(self)
def showMoveHelper(self, visible=True): """show help text In empty HandBoards""" if visible: if not self.__moveHelper: splitter = QGraphicsRectItem(self) hbCenter = self.rect().center() splitter.setRect(hbCenter.x() * 0.5, hbCenter.y(), hbCenter.x() * 1, 1) helpItems = [splitter] for name, yFactor in [(m18n('Move Exposed Tiles Here'), 0.5), (m18n('Move Concealed Tiles Here'), 1.5)]: helper = QGraphicsSimpleTextItem(name, self) helper.setScale(3) nameRect = QRectF() nameRect.setSize(helper.mapToParent(helper.boundingRect()).boundingRect().size()) center = QPointF(hbCenter) center.setY(center.y() * yFactor) helper.setPos(center - nameRect.center()) if self.sceneRotation() == 180: rotateCenter(helper, 180) helpItems.append(helper) self.__moveHelper = self.scene().createItemGroup(helpItems) self.__moveHelper.setVisible(True) else: if self.__moveHelper: self.__moveHelper.setVisible(False)
def draw_x_axis(self): #lineItem = QGraphicsLineItem(self.col_w/2, # self.coordY(self.ylim[0])+2, # self.width-self.col_w/2, # self.coordY(self.ylim[0])+2, # parent=self.item) #lineItem.setPen(QPen(QColor('black'))) #lineItem.setZValue(10) #all_vals = list(range(0, len(self.values), 5)) #if (len(self.values)-1)%5: # all_vals += [len(self.values)-1] for x, lab in enumerate(self.values): # lineItem = QGraphicsLineItem(0, self.coordY(self.ylim[0])+2, # 0, self.coordY(self.ylim[0])+6, # parent=self.item) # lineItem.setX(x*self.col_w + self.col_w/2) # lineItem.setPen(QPen(QColor('black'))) # lineItem.setZValue(10) text = QGraphicsSimpleTextItem(str(lab)) text.rotate(-90) text.setFont(QFont("Arial", self.fsize-2)) text.setParentItem(self.item) tw = text.boundingRect().height() # Center text according to masterItem size text.setPos(x*self.col_w-tw/2 + self.col_w/2, self.coordY(self.ylim[0]))
def update_items(self): self.item = QGraphicsRectItem( 0, 0, self.width, self.row_h * self.coeff_h) seq_width = 0 nopen = QPen(Qt.NoPen) self.item.setPen(nopen) font = QFont(self.ftype, self.fsize) if self.fstyle == "italic": font.setStyle(QFont.StyleItalic) elif self.fstyle == "oblique": font.setStyle(QFont.StyleOblique) rect_cls = QGraphicsRectItem for i, val in enumerate(self.liste): width = self.col_w height = self.row_h * len(str(val)) + 1 rectitem = rect_cls(0, 0, width, height, parent=self.item) rectitem.setX(seq_width) # to give correct X to children item rectitem.setBrush(QBrush(QColor(self.bgcolor))) rectitem.setPen(nopen) # write letter if enough space in height if height >= self.fsize: text = QGraphicsSimpleTextItem(str(val), parent=rectitem) text.setFont(font) text.setBrush(QBrush(QColor(self.fgcolor))) # Center text according to rectitem size # txtw = text.boundingRect().width() txth = text.boundingRect().height() text.setRotation(self.rot) text.setX(txth) seq_width += width self.width = seq_width
def draw_x_axis(self): #lineItem = QGraphicsLineItem(self.col_w/2, # self.coordY(self.ylim[0])+2, # self.width-self.col_w/2, # self.coordY(self.ylim[0])+2, # parent=self.item) #lineItem.setPen(QPen(QColor('black'))) #lineItem.setZValue(10) #all_vals = list(range(0, len(self.values), 5)) #if (len(self.values)-1)%5: # all_vals += [len(self.values)-1] for x, lab in enumerate(self.values): # lineItem = QGraphicsLineItem(0, self.coordY(self.ylim[0])+2, # 0, self.coordY(self.ylim[0])+6, # parent=self.item) # lineItem.setX(x*self.col_w + self.col_w/2) # lineItem.setPen(QPen(QColor('black'))) # lineItem.setZValue(10) text = QGraphicsSimpleTextItem(str(lab)) text.rotate(-90) text.setFont(QFont("Arial", self.fsize - 2)) text.setParentItem(self.item) tw = text.boundingRect().height() # Center text according to masterItem size text.setPos(x * self.col_w - tw / 2 + self.col_w / 2, self.coordY(self.ylim[0]))
def draw_x_axis(self): lineItem = QGraphicsLineItem(self.col_w / 2, self.coordY(self.ylim[0]) + 2, self.width - self.col_w / 2, self.coordY(self.ylim[0]) + 2, parent=self.item) lineItem.setPen(QPen(QColor('black'))) lineItem.setZValue(10) all_vals = list(range(0, len(self.values), self.x_inter_values)) if (len(self.values) - 1) % self.x_inter_values: all_vals += [len(self.values) - 1] hp_x = [] if self.hp: for x in list(range(0, len(self.values))): if self.x_values[x] in self.hp: hp_x.append(x) if not x in all_vals: all_vals += [x] all_vals.sort() for x in all_vals: lineItem = QGraphicsLineItem(0, self.coordY(self.ylim[0]) + 2, 0, self.coordY(self.ylim[0]) + 6, parent=self.item) lineItem.setX(x * self.col_w + self.col_w / 2) lineItem.setPen(QPen(QColor('black'))) lineItem.setZValue(10) if x in hp_x: text = QGraphicsSimpleTextItem("*" + str(self.x_values[x])) qfont = QFont("Arial", self.fsize - 1) #qfont.setBold(True) text.setFont(qfont) else: text = QGraphicsSimpleTextItem(" " + str(self.x_values[x])) text.setFont(QFont("Arial", self.fsize - 1)) text.rotate(-90) text.setParentItem(self.item) text.setZValue(10) tw = text.boundingRect().width() th = text.boundingRect().height() # Center text according to masterItem size text.setPos(x * self.col_w - th / 2 + self.col_w / 2, tw + self.coordY(self.ylim[0]) + 7)
def update_items(self): rect_h = self.height if self.x_axis: rect_h += 30 self.item = QGraphicsRectItem(0, 0, self.width + 40, rect_h) self.item.setPen(QPen(QColor('white'))) #X axis if self.x_axis: self.draw_x_axis() # Legend self.draw_legend() # Y axes and colo rect yi = -1 for model in ["PCOC", "PC", "OC", "Topological", "Identical"]: if self.dict_values_pcoc.has_key(model): yi += 1 y = yi * self.col_w # Y axes ## Stick yaxis = (yi + 0.5) * self.col_w lineItem = QGraphicsLineItem(self.width, yaxis, self.width + 5, yaxis, parent=self.item) lineItem.setPen(QPen(QColor('black'))) ## Text text = QGraphicsSimpleTextItem(model) text.setFont(QFont("Arial", self.fsize - 2)) text.setParentItem(self.item) tw = text.boundingRect().width() th = text.boundingRect().height() ## Center text according to masterItem size text.setPos(self.width + 5, yaxis - th / 2) # Color rect for each model values = self.dict_values_pcoc[model] for i, val in enumerate(values): self.draw_fun(i * self.col_w, y, val, col_width=self.col_w)
def ugly_name_face(node, *args, **kargs): """ This is my item generator. It must receive a node object, and returns a Qt4 graphics item that can be used as a node face. """ # receive an arbitrary number of arguments, in this case width and # height of the faces width = args[0][0] height = args[0][1] ## Creates a main master Item that will contain all other elements ## Items can be standard QGraphicsItem # masterItem = QGraphicsRectItem(0, 0, width, height) # Or your custom Items, in which you can re-implement interactive # functions, etc. Check QGraphicsItem doc for details. masterItem = InteractiveItem(0, 0, width, height) # Keep a link within the item to access node info masterItem.node = node # I dont want a border around the masterItem masterItem.setPen(QPen(QtCore.Qt.NoPen)) # Add ellipse around text ellipse = QGraphicsEllipseItem(masterItem.rect()) ellipse.setParentItem(masterItem) # Change ellipse color ellipse.setBrush(QBrush(QColor(random_color()))) # Add node name within the ellipse text = QGraphicsSimpleTextItem(node.name) text.setParentItem(ellipse) text.setPen(QPen(QPen(QColor("white")))) # Center text according to masterItem size tw = text.boundingRect().width() th = text.boundingRect().height() center = masterItem.boundingRect().center() text.setPos(center.x() - tw / 2, center.y() - th / 2) return masterItem
def ugly_name_face(node, *args, **kargs): """ This is my item generator. It must receive a node object, and returns a Qt4 graphics item that can be used as a node face. """ # receive an arbitrary number of arguments, in this case width and # height of the faces width = args[0][0] height = args[0][1] ## Creates a main master Item that will contain all other elements ## Items can be standard QGraphicsItem # masterItem = QGraphicsRectItem(0, 0, width, height) # Or your custom Items, in which you can re-implement interactive # functions, etc. Check QGraphicsItem doc for details. masterItem = InteractiveItem(0, 0, width, height) # Keep a link within the item to access node info masterItem.node = node # I dont want a border around the masterItem masterItem.setPen(QPen(QtCore.Qt.NoPen)) # Add ellipse around text ellipse = QGraphicsEllipseItem(masterItem.rect()) ellipse.setParentItem(masterItem) # Change ellipse color ellipse.setBrush(QBrush(QColor( random_color()))) # Add node name within the ellipse text = QGraphicsSimpleTextItem(node.name) text.setParentItem(ellipse) text.setPen(QPen(QPen(QColor("white")))) # Center text according to masterItem size tw = text.boundingRect().width() th = text.boundingRect().height() center = masterItem.boundingRect().center() text.setPos(center.x()-tw/2, center.y()-th/2) return masterItem
def iLabel(node, *args, **kargs): #code for making specialized faces for intermediates mostly cribbed from the ete2 website example (though not interactive): # http://pythonhosted.org/ete2/tutorial/tutorial_drawing.html#creating-your-custom-interactive-item-faces my_label = args[0][0] #or maybe just node.name? ellipse = QGraphicsEllipseItem(0,0,fontSize*2,fontSize*2) #I think the first two are coords of center; second pair is major/minor axis ellipse.setBrush(QBrush(QColor( 'black' ))) text = QGraphicsSimpleTextItem(my_label) text.setParentItem(ellipse) text.setBrush(QBrush(QColor("white"))) text.setFont(QFont("Arial",fontSize*.75)) #Center text according to masterItem size tw = text.boundingRect().width() th = text.boundingRect().height() center = ellipse.boundingRect().center() text.setPos(center.x()-tw/2, center.y()-th/2) return ellipse
def draw_legend(self): legend_h = self.height * ((self.nb_models - 1) / float(self.nb_models)) if legend_h < 35: legend_h = 35 legend_rect = QGraphicsRectItem(-20, 0, 10, legend_h, parent=self.item) x0 = -20 n_cat = 6. for y, str_y in [(1, 1), (1 / n_cat * 5, 0.99), (1 / n_cat * 4, 0.9), (1 / n_cat * 3, 0.8), (1 / n_cat * 2, 0.7), (1 / n_cat * 1, 0.5), (1 / n_cat * 0, 0)]: y_stick = legend_h - y * legend_h lineItem = QGraphicsLineItem(x0 - 5, y_stick, x0, y_stick, parent=self.item) lineItem.setPen(QPen(QColor('black'))) text = QGraphicsSimpleTextItem(str(str_y)) text.setFont(QFont("Arial", self.fsize - 4)) text.setParentItem(self.item) tw = text.boundingRect().width() th = text.boundingRect().height() # Center text according to masterItem size text.setPos(x0 - tw - 7, y_stick - th / 2) for (y1, y2, c) in [(1, 1 / n_cat * 5, 0.99), (1 / n_cat * 5, 1 / n_cat * 4, 0.9), (1 / n_cat * 4, 1 / n_cat * 3, 0.8), (1 / n_cat * 3, 1 / n_cat * 2, 0.7), (1 / n_cat * 2, 1 / n_cat * 1, 0.5), (1 / n_cat * 1, 1 / n_cat * 0, 0)]: y1_stick = legend_h - y1 * legend_h y2_stick = legend_h - y2 * legend_h self.draw_fun(x0, y1_stick, c, col_width=10, col_height=y2_stick - y1_stick)
def iLabel(node, *args, **kargs): #code for making specialized faces for intermediates mostly cribbed from the ete2 website example (though not interactive): # http://pythonhosted.org/ete2/tutorial/tutorial_drawing.html#creating-your-custom-interactive-item-faces my_label = args[0][0] #or maybe just node.name? ellipse = QGraphicsEllipseItem( 0, 0, fontSize * 2, fontSize * 2 ) #I think the first two are coords of center; second pair is major/minor axis ellipse.setBrush(QBrush(QColor('black'))) text = QGraphicsSimpleTextItem(my_label) text.setParentItem(ellipse) text.setBrush(QBrush(QColor("white"))) text.setFont(QFont("Arial", fontSize * .75)) #Center text according to masterItem size tw = text.boundingRect().width() th = text.boundingRect().height() center = ellipse.boundingRect().center() text.setPos(center.x() - tw / 2, center.y() - th / 2) return ellipse
class PreCrossoverHandle(QGraphicsItem): scafpen = QPen(styles.pch_scaf_stroke, styles.PATH_STRAND_STROKE_WIDTH) scafpen.setCapStyle(Qt.FlatCap) # or Qt.RoundCap scafpen.setJoinStyle(Qt.RoundJoin) stappen = QPen(styles.pch_stap_stroke, styles.PATH_STRAND_STROKE_WIDTH) stappen.setCapStyle(Qt.FlatCap) # or Qt.RoundCap stappen.setJoinStyle(Qt.RoundJoin) disabpen = QPen(styles.pch_disab_stroke, styles.PATH_STRAND_STROKE_WIDTH) disabpen.setCapStyle(Qt.FlatCap) disabpen.setJoinStyle(Qt.RoundJoin) disabbrush = QBrush(styles.pch_disab_stroke) # For the helix number label enabbrush = QBrush(Qt.SolidPattern) # Also for the helix number label baseWidth = styles.PATH_BASE_WIDTH rect = QRectF(0, 0, styles.PATH_BASE_WIDTH, styles.PATH_BASE_WIDTH) toHelixNumFont = QFont("Times", 10, QFont.Bold) def __init__(self, parentPH, fromStrand, fromIdx, toVH, toIdx, orientedLeft): super(PreCrossoverHandle, self).__init__(parentPH) self.fromVH = parentPH.vhelix() self.fromStrand = fromStrand self.fromIdx = fromIdx self.toVH = toVH self.toIdx = toIdx self.orientedLeft = orientedLeft self.fromVH.basesModified.connect(self.updateVisibilityAndEnabledness) self.toVH.basesModified.connect(self.updateVisibilityAndEnabledness) self.label = QGraphicsSimpleTextItem(str(toVH.number()), parent=self) self.label.setFont(self.toHelixNumFont) x = self.baseWidth * self.fromIdx y = (-1.25 if self.onTopStrand() else 2.25) * self.baseWidth self.setPos(x, y) halfLabelW = self.label.boundingRect().width() / 2 labelX = self.baseWidth/2 - halfLabelW labelY = (-.10 if self.onTopStrand() else .48) * self.baseWidth self.label.setPos(labelX, labelY) self.updateVisibilityAndEnabledness() def onTopStrand(self): return self.fromVH.evenParity() and self.fromStrand==StrandType.Scaffold or\ not self.fromVH.evenParity() and self.fromStrand==StrandType.Staple def couldFormNewCrossover(self): return self.fromVH.possibleNewCrossoverAt(self.fromStrand, self.fromIdx, self.toVH, self.toIdx) def crossoverExists(self): return self.fromVH.hasCrossoverAt(self.fromStrand, self.fromIdx) def is3pEndOfCrossover(self): return self.orientedLeft and self.onTopStrand() or\ not self.orientedLeft and not self.onTopStrand def updateVisibilityAndEnabledness(self): shouldBeVisible = not self.crossoverExists() self.setVisible(shouldBeVisible) self.label.setVisible(shouldBeVisible) if self.couldFormNewCrossover(): self.label.setBrush(self.enabbrush) else: self.label.setBrush(self.disabbrush) self.update() def paint(self, painter, option, widget=None): #Look Up Table pathLUT = (_ppathRD, _ppathRU, _ppathLD, _ppathLU) path = pathLUT[2*int(self.orientedLeft) + int(self.onTopStrand())] pen = self.disabpen if self.couldFormNewCrossover(): if self.fromStrand == StrandType.Scaffold: pen = self.scafpen else: pen = self.stappen painter.setPen(pen) painter.drawPath(path) def boundingRect(self): return self.rect def mousePressEvent(self, event): if event.button() != Qt.LeftButton: return QGraphicsItem.mousePressEvent(self, event) if not self.couldFormNewCrossover(): return # Determine upstream base fromHelix, toHelix = self.fromVH, self.toVH fromIdx, toIdx = self.fromIdx, self.toIdx if not self.is3pEndOfCrossover(): fromHelix, toHelix = toHelix, fromHelix fromIdx, toIdx = toIdx, fromIdx # Create XoverHandlePair and store references # fromHelix.installXoverFrom3To5(StrandType.Scaffold, \ # fromIndex, toHelix, toIndex) fromHelix.installXoverFrom3To5(self.fromStrand, \ fromIdx, toHelix, toIdx)
def polygon_name_face(node, *args, **kwargs): """create a wedge shaped face in the style of ARB Args: width (int): size in pixels for the width of the wedge height (int): size in pixels for the height of the wedge width_percent (float): change the angle of the point of the wedge. This must be a number between 0 and 1 Returns: QGraphicsRectItem: The Qt graphics item of the polygon """ n_leaves = len(node.get_leaves()) closest_leaf_dist = node.get_closest_leaf()[1] farthest_leaf_dist = node.get_farthest_leaf()[1] base_height = 30 width = 60 height = math.log(n_leaves, 2) + base_height width_percent = closest_leaf_dist / farthest_leaf_dist #print(width, height, width_percent) points = [ (0.0, 0.0), # top left point (width, 0.0), # top right point (width * width_percent, height), # bottom right point (0.0, height), # bottom left point (0.0, 0.0) # back to the beginning ] shape = QPolygonF() for i in points: shape << QtCore.QPointF(*i) ## Creates a main master Item that will contain all other elements ## Items can be standard QGraphicsItem masterItem = QGraphicsRectItem(0, 0, width, height) # Keep a link within the item to access node info masterItem.node = node # I dont want a border around the masterItem masterItem.setPen(QPen(QtCore.Qt.NoPen)) polygon = QGraphicsPolygonItem(shape, masterItem) # Make the wedge grey in color polygon.setBrush(QBrush(QColor( '#D3D3D3'))) # Print the name of the node # Center text according to masterItem size center = masterItem.boundingRect().center() text = QGraphicsSimpleTextItem(node.name) text.setParentItem(polygon) tw = text.boundingRect().width() th = text.boundingRect().height() text.setPos(center.x() + tw/2, center.y() - th/2) # this is a hack to prevent the name being printed twice # we set the node name to blank after we write it with the QGraphicsSimpleTextItem # it must be set to a blank string for it not to be printed later node.name = '' # print the number of collapsed leaves in the polygon leaves_count_text = QGraphicsSimpleTextItem('('+str(n_leaves)+')') leaves_count_text.setParentItem(polygon) leaves_count_text.setFont(QFont('Veranda', 6)) leaves_count_text.setPos(masterItem.boundingRect().x() + 5, center.y() - leaves_count_text.boundingRect().height()/2) polygon.setPos(0, masterItem.boundingRect().y()/1.5) return masterItem
class ActiveSliceHandle(QGraphicsItem): """docstring for ActiveSliceHandle""" _baseWidth = styles.PATH_BASE_WIDTH _brush = QBrush(styles.orangefill) _labelbrush = QBrush(styles.orangestroke) _pen = QPen(styles.orangestroke, styles.SLICE_HANDLE_STROKE_WIDTH) _myfont = QFont("Times", 12, QFont.Bold) def __init__(self, pathHelixGroup): super(ActiveSliceHandle, self).__init__(pathHelixGroup) self._pathHelixGroup = None self._activeSlice = 0 self._dragMode = False self._label = QGraphicsSimpleTextItem("", parent=self) self._label.setPos(0, -18) self._label.setFont(self._myfont) self._label.setBrush(self._labelbrush) self._label.hide() self.setPathHelixGroup(pathHelixGroup) self.setFlag(QGraphicsItem.ItemIsMovable) self.setAcceptHoverEvents(True) self.setZValue(styles.ZACTIVESLICEHANDLE) def controller(self): return self._pathHelixGroup.controller() def part(self): return self._pathHelixGroup.part() def pathHelixGroup(self): return self._pathHelixGroup def setPathHelixGroup(self, newPHG): if self._pathHelixGroup: self._pathHelixGroup.geometryChanged.disconnect(\ self.prepareGeometryChange) self._pathHelixGroup.displayedVHsChanged.disconnect(self._hideIfEmptySelection) if self._pathHelixGroup and self._pathHelixGroup.part(): self._pathHelixGroup.part().activeSliceWillChange.disconnect(\ self._updateActiveSlice) self._pathHelixGroup = newPHG newPHG.geometryChanged.connect(self.prepareGeometryChange) newPHG.part().activeSliceWillChange.connect(self._updateActiveSlice) newPHG.displayedVHsChanged.connect(self._hideIfEmptySelection) self._hideIfEmptySelection() self._updateActiveSlice(newPHG.part().activeSlice()) def activeSlice(self): return self.part().activeSlice() def setActiveSlice(self, baseIndex): self.part().setActiveSlice(baseIndex) def _hideIfEmptySelection(self): self.setVisible(len(self.pathHelixGroup().displayedVHs())>0) def _updateActiveSlice(self, baseIndex): """The slot that receives active slice changed notifications from the part and changes the receiver to reflect the part""" bi = int(baseIndex) if bi < 0 or bi >= self.part().dimensions()[2]: raise IndexError self.setPos(bi * self._baseWidth, -styles.PATH_HELIX_PADDING) self._activeSlice = bi if self._label: self._label.setText("%d" % bi) self._label.setX((self._baseWidth -\ self._label.boundingRect().width()) / 2) def boundingRect(self): return QRectF(0, 0, self._baseWidth,\ self.pathHelixGroup().boundingRect().height()) def paint(self, painter, option, widget=None): if self.boundingRect().height() > 0: painter.setBrush(self._brush) painter.setPen(self._pen) painter.drawRect(self.boundingRect()) self._label.show() else: self._label.hide() def resetBounds(self, maxBase): """Call after resizing virtualhelix canvas.""" self.maxBase = maxBase self.maxX = (maxBase - 1) * self._baseWidth def hoverEnterEvent(self, event): if self.controller().isSelectToolActive(): self.setCursor(Qt.OpenHandCursor) QGraphicsItem.hoverEnterEvent(self, event) # end def # def hoverMoveEvent(self, event): # if not self.controller().isSelectToolActive(): # # pass None, but if needed pass self for having a special # # behavior for the slice helix # self.controller().toolHoverMove(None, event, flag=True) # QGraphicsItem.hoverMoveEvent(self, event) # end def def hoverLeaveEvent(self, event): self.setCursor(Qt.ArrowCursor) QGraphicsItem.hoverLeaveEvent(self, event) # end def def mouseMoveEvent(self, event): """Snaps handle into place when dragging.""" if not self.controller().isSelectToolActive() or not self._dragMode: return x = event.scenePos().x() dx = int((x - self.pressX)/self._baseWidth) self.setActiveSlice(self.pressBaseIdx+dx) def mousePressEvent(self, event): if event.button() != Qt.LeftButton: event.ignore() QGraphicsItem.mousePressEvent(self, event) return if not self.controller().isSelectToolActive(): return self.scene().views()[0].addToPressList(self) self._dragMode = True self.pressX = event.scenePos().x() self.pressBaseIdx = self.activeSlice() def customMouseRelease(self, eventPosition): """Snaps to grid after mouse released. Updates vhelix data according to what movement took place.""" self._dragMode = False def moveToLastSlice(self): """Moves to the last slice position.""" self.setActiveSlice(self.part().numBases() - 1) def moveToFirstSlice(self): """Moves to the last slice position.""" self.setActiveSlice(0)