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 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 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): 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 display_answer(self, question, answers, correct_answer, description, selected_index, correct): x, y = self.display_question(question, answers, selected_index, correct) #TODO pass what to check and if right or wrong y += 50 item = QGraphicsSimpleTextItem("Correct Answer: %s" % correct_answer) item.setBrush(self.TEXT_COLOR) font = QFont(self.BOLDISH) font.setUnderline(True) item.setFont(font) item.setX(x) item.setY(y) self.qtscene.addItem(item) self.references.append(item) y += 60 item = QGraphicsSimpleTextItem(make_pretty(description, 55)) item.setBrush(self.TEXT_COLOR) item.setFont(self.NORMALISH) item.setX(x) item.setY(y) self.qtscene.addItem(item) self.references.append(item) item = QPushButton('Next') item.clicked.connect(self.on_next) item.setFont(self.BOLDISH) item.move(x+700, y) self.qtscene.addWidget(item) self.references.append(item)
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 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 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 display_question(self, question, answers, selected_index = None, correct = None): self._init_scene() x = 50 y = 25 item = QGraphicsSimpleTextItem(question) item.setBrush(self.TEXT_COLOR) item.setFont(self.BOLDISH) item.setX(x) item.setY(y) self.qtscene.addItem(item) self.references.append(item) y += 75 for index, answer in enumerate(answers): index += 1 item = QGraphicsSimpleTextItem("%s) %s" % (index, answer)) item.setBrush(self.TEXT_COLOR) item.setFont(self.NORMALISH) item.setX(x) item.setY(y) item.setAcceptHoverEvents(True) self.qtscene.addItem(item) self.references.append(item) #TODO: do not register click but do show check or not if not selected_index: item.hoverEnterEvent = partial(self.on_hover_answer, item) item.hoverLeaveEvent = partial(self.on_unhover_answer, item) item.mousePressEvent = partial(self.on_click_answer, index) elif selected_index == index: if correct: item = QGraphicsSimpleTextItem(u"\u2713") item.setBrush(QBrush(QColor(0,150,0))) item.setX(0) else: item = QGraphicsSimpleTextItem("X") item.setBrush(QBrush(QColor(255,0,0))) item.setX(3) item.setFont(self.BOLDISH) item.setY(y) self.qtscene.addItem(item) self.references.append(item) y += 50 return x, y
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)
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)