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 moveTo(self, pos): #data coordinates oldX, oldY = self.pos.x(), self.pos.y() x, y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen( QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x - self.brushSize // 2 - 1))) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1))) self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1))) self.bb.setBottom( max(self.bb.bottom(), min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1))) #update/move position self.pos = pos
class GPendulum(Graphics.Items.ItemGroupBase): def _setup(self): self.rod = QGraphicsLineItem(QLineF(0, 0, 0, 100)) p = QPen(QColor(100, 100, 100)) p.setWidth(5) self.rod.setPen(p) self.rod.setToolTip('This is the rod of the pendulum') self.ball = QGraphicsEllipseItem(QRectF(-20, 80, 40, 40)) b = QBrush(Qt.SolidPattern) b.setColor(QColor(0, 255, 0)) self.ball.setBrush(b) self.ball.setToolTip('This is the ball of the pendulum where the mass is concentrated') self.addToGroup(self.rod) self.addToGroup(self.ball) self.setFlags(QGraphicsItem.ItemIsSelectable) def setProperties(self, q): self.properties = q def contextMenuEvent(self, e): e.accept() m = QMenu() p = m.addAction("Properties") a = m.exec_(e.screenPos()) if a == p: dlg = SimTools.RichTypes.Qt4Widgets.SimpleRichTypesDialog(mainWin, 'Pendulum properties', text='Change physical properties', scrolling=False) dlg.addRichTypes(self.properties) dlg.exec_()
def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: downPos = event.buttonDownPos(Qt.LeftButton) if not self.__tmpLine and self.__dragStartItem and \ (downPos - event.pos()).manhattanLength() > \ QApplication.instance().startDragDistance(): # Start a line drag line = QGraphicsLineItem(self) start = self.__dragStartItem.boundingRect().center() start = self.mapFromItem(self.__dragStartItem, start) line.setLine(start.x(), start.y(), event.pos().x(), event.pos().y()) pen = QPen(Qt.black, 4) pen.setCapStyle(Qt.RoundCap) line.setPen(pen) line.show() self.__tmpLine = line if self.__tmpLine: # Update the temp line line = self.__tmpLine.line() line.setP2(event.pos()) self.__tmpLine.setLine(line) QGraphicsWidget.mouseMoveEvent(self, event)
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 draw_errors(self, x, i): lower = self.values[i]+self._dw_err[i] upper = self.values[i]+self._up_err[i] lineItem = QGraphicsLineItem(0, self.coordY(lower), 0, self.coordY(upper), parent=self.item) lineItem.setX(x) lineItem.setPen(QPen(QColor('black'),1))
def draw_hlines(self, line, col): lineItem = QGraphicsLineItem(0, self.coordY(line), self.width, self.coordY(line), parent=self.item) lineItem.setPen(QPen(QColor(col), 1, Qt.DashLine)) lineItem.setZValue(10)
def draw_stick(self, x, y, i): lineItem = QGraphicsLineItem(0, self.coordY(self.ylim[0]), 0, self.coordY(y), parent=self.item) lineItem.setX(x) lineItem.setPen(QPen(QColor(self.colors[i]), 2))
def draw_errors(self, x, i): lower = self.values[i] + self._dw_err[i] upper = self.values[i] + self._up_err[i] lineItem = QGraphicsLineItem(0, self.coordY(lower), 0, self.coordY(upper), parent=self.item) lineItem.setX(x) lineItem.setPen(QPen(QColor('black'), 1))
class CrossX(ItemGroupBase): """a cross (x) made of two lines""" def _setup(self, x=0, y=0, size=10, pen=QPen(QColor(0,0, 255))): a = 0.5*size self.p1 = QGraphicsLineItem(QLineF(x-a, y-a, x+a, y+a)) self.p2 = QGraphicsLineItem(QLineF(x-a, y+a, x+a, y-a)) self.p1.setPen(pen) self.p2.setPen(pen) self.addToGroup(self.p1) self.addToGroup(self.p2)
class Axes(ItemGroupBase): """two rectangular lines as axes""" def _setup(self, x=[0, -100, 100], y=[0, -100, 100], pen=QPen(QColor(255,0,0))): if x: self.xAxis = QGraphicsLineItem(QLineF(x[1], x[0], x[2], x[0])) self.xAxis.setPen(pen) self.addToGroup(self.xAxis) if y: self.yAxis = QGraphicsLineItem(QLineF(y[0], y[1], y[0], y[2])) self.yAxis.setPen(pen) self.addToGroup(self.yAxis)
def onEdgeAdd(start,end): ''' Whenever a new edge is added to model, this method is to be notified. ''' p1 = nodeToScene[start].rect().center() p2 = nodeToScene[end] .rect().center() line = QGraphicsLineItem( QLineF(p1,p2) ) line.setPen( QPen( QColor(32,32,32), 1 ) ) groupEdges.addToGroup(line) nodeToLineP1[start].add(line) nodeToLineP2 [end].add(line)
def draw_curve(self, x, y, i): # top line lineItem = QGraphicsLineItem(0, self.coordY(y), 4, self.coordY(y), parent=self.item) lineItem.setX(x-2) lineItem.setPen(QPen(QColor(self.colors[i]),2)) if i > 0: prev = self.values[i-1] if i>0 else self.values[i] lineItem = QGraphicsLineItem(0, self.coordY(prev), self.col_w-4, self.coordY(y), parent=self.item) lineItem.setX(x - self.col_w+2) lineItem.setPen(QPen(QColor(self.colors[i]),2))
def onMouseMove_draw( self, imageview, event ): self._navIntr.onMouseMove_default( imageview, event ) o = imageview.scene().data2scene.map(QPointF(imageview.oldX,imageview.oldY)) n = imageview.scene().data2scene.map(QPointF(imageview.x,imageview.y)) # Draw temporary line for the brush stroke so the user gets feedback before the data is really updated. pen = QPen( QBrush(self._brushingCtrl._brushingModel.drawColor), self._brushingCtrl._brushingModel.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) line = QGraphicsLineItem(o.x(), o.y(), n.x(), n.y()) line.setPen(pen) imageview.scene().addItem(line) line.setParentItem(imageview.scene().dataRectItem) self._lineItems.append(line) self._brushingCtrl._brushingModel.moveTo(imageview.mousePos)
def onMouseMove_draw( self, imageview, event ): self._navIntr.onMouseMove_default( imageview, event ) o = imageview.scene().data2scene.map(QPointF(imageview.oldX,imageview.oldY)) n = imageview.scene().data2scene.map(QPointF(imageview.x,imageview.y)) # Draw temporary line for the brush stroke so the user gets feedback before the data is really updated. pen = QPen( QBrush(self._brushingCtrl._brushingModel.drawColor), self._brushingCtrl._brushingModel.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) line = QGraphicsLineItem(o.x(), o.y(), n.x(), n.y()) line.setPen(pen) imageview.scene().addItem(line) line.setParentItem(imageview.scene().dataRect) self._lineItems.append(line) self._brushingCtrl._brushingModel.moveTo(imageview.mousePos)
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 draw_curve(self, x, y, i): # top line lineItem = QGraphicsLineItem(0, self.coordY(y), 4, self.coordY(y), parent=self.item) lineItem.setX(x - 2) lineItem.setPen(QPen(QColor(self.colors[i]), 2)) if i > 0: prev = self.values[i - 1] if i > 0 else self.values[i] lineItem = QGraphicsLineItem(0, self.coordY(prev), self.col_w - 4, self.coordY(y), parent=self.item) lineItem.setX(x - self.col_w + 2) lineItem.setPen(QPen(QColor(self.colors[i]), 2))
def addLines(self, x, y, w, h, diff, pen): if w == 0 or h == 0: return dist = 20 * diff # original distance between two lines in pixels temp = dist canvas = self.canvas while temp < w: r = QGraphicsLineItem(temp + x, y, temp + x, y + h, None) canvas.addItem(r) r.setPen(pen) temp += dist temp = dist while temp < h: r = QGraphicsLineItem(x, y + temp, x + w, y + temp, None) canvas.addItem(r) r.setPen(pen) temp += dist
def moveTo(self, pos): oldX, oldY = self.pos.x(), self.pos.y() x,y = pos.x(), pos.y() #print "BrushingModel.moveTo(pos=%r)" % (pos) line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(x,y), QSize(1,1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x-self.brushSize/2-1) ) ) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0]-1, x+self.brushSize/2+1) ) ) self.bb.setTop( min(self.bb.top(), max(0, y-self.brushSize/2-1) ) ) self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize/2+1) ) ) #update/move position self.pos = pos
def moveTo(self, pos): lineVis = QGraphicsLineItem(self.pos.x(), self.pos.y(), pos.x(), pos.y()) lineVis.setPen(self.penVis) line = QGraphicsLineItem(self.pos.x(), self.pos.y(), pos.x(), pos.y()) line.setPen(self.penDraw) self.scene.addItem(line) self.pos = pos x = pos.x() y = pos.y() #update bounding Box : if x > self.bb.right(): self.bb.setRight(x) if x < self.bb.left(): self.bb.setLeft(x) if y > self.bb.bottom(): self.bb.setBottom(y) if y < self.bb.top(): self.bb.setTop(y) return lineVis
def addLink(self, output, input): """ Add a link between `output` (:class:`OutputSignal`) and `input` (:class:`InputSignal`). """ if not compatible_channels(output, input): return if output not in self.source.output_channels(): raise ValueError("%r is not an output channel of %r" % \ (output, self.source)) if input not in self.sink.input_channels(): raise ValueError("%r is not an input channel of %r" % \ (input, self.sink)) if input.single: # Remove existing link if it exists. for s1, s2, _ in self.__links: if s2 == input: self.removeLink(s1, s2) line = QGraphicsLineItem(self) source_anchor = self.sourceNodeWidget.anchor(output) sink_anchor = self.sinkNodeWidget.anchor(input) source_pos = source_anchor.boundingRect().center() source_pos = self.mapFromItem(source_anchor, source_pos) sink_pos = sink_anchor.boundingRect().center() sink_pos = self.mapFromItem(sink_anchor, sink_pos) line.setLine(source_pos.x(), source_pos.y(), sink_pos.x(), sink_pos.y()) pen = QPen(Qt.black, 4) pen.setCapStyle(Qt.RoundCap) line.setPen(pen) self.__links.append(_Link(output, input, line))
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)
class Visualizer: def __init__(self, scene): self.scene = scene # Pool of items to grab from when needed. self.taskItemPool = list() # The items that are active and to be updated. self.activeItems = list() # Dictionary of PIDs and an associated item to represent the process. self.taskItemPids = dict() # Scales the visualization dimension for cpu%. self.cpuScale = 2.0 # Setup memory axis visualization. self.memAxisLen = 1000 self.memXOffset = -10 self._memTickInterval = 0.1 # As a percentage of the memScale. self.memAxis = None self.setup_mem_axis() # Set the color codes for each task type. self.userTaskColor = Qt.red self.rootTaskColor = Qt.darkGray self.otherTaskColor = Qt.cyan # Spacing between each task graphical item self.taskItemSpacing = 20 self.showRootTasks = False # Set up the timers to update the visualization. self.updateProcessDataTimer = QTimer() self.updateProcessDataTimer.timeout.connect(self.update_processes_data) self.updateItemsTimer = QTimer() self.updateItemsTimer.timeout.connect(self.update_items) # Fill the pool of task items. for i in range(0, 200): self.add_new_task_graphics_item(False) self.updateProcessDataTimer.start(1000.0) self.updateItemsTimer.start(50.0) def update_processes_data(self): # Reset USED flag in order to determine which task items are unused. This # will happen when an item's process does not exist anymore. for item in self.activeItems: item.used = False processes = StateManager.get_processes_data() # Update the graphical representations x = 0 for p in processes: if p[USER_INDEX] == ROOT_NAME and not self.showRootTasks: continue pid = p[PID_INDEX] # Pid still exists. if pid in self.taskItemPids: item = self.taskItemPids[pid] # Check if PID returned after it ended. This means that the mapped # item MAY be associated with another process. if item.pid != pid: item = self.fetch_task_item() self.taskItemPids[pid] = item item.pid = pid # Remove from pool and add to active. elif item in self.taskItemPool: self.taskItemPool.remove(item) self.activeItems.append(item) # ELSE: reuse item, the process returned continuously. item.setVisible(True) item.used = True # Pid not in dictionary, Add task item. else: item = self.fetch_task_item() self.taskItemPids[pid] = item item.pid = pid item.used = True # CPU % new_diameter = p[CPU_INDEX] * self.cpuScale + 2 # MEM % y = p[MEM_INDEX] / 100.0 * self.memAxisLen # Center around on y-component. y -= new_diameter / 2.0 pos = item.rect().topLeft() diameter = item.rect().width() # Set position bounds. item.startPos = pos item.endPos = QPointF(x, y) # Setup diameter bounds. item.startDiameter = diameter item.endDiameter = new_diameter x += new_diameter + self.taskItemSpacing # Setup the name of the task. item.set_name(p[NAME_INDEX]) if p[USER_INDEX] == USER_NAME: item.setBrush(QBrush(self.userTaskColor)) item.textItem.setDefaultTextColor(Qt.white) elif p[USER_INDEX] == ROOT_NAME: item.setBrush(QBrush(self.rootTaskColor)) item.textItem.setDefaultTextColor(self.rootTaskColor) else: item.setBrush(QBrush(self.otherTaskColor)) item.textItem.setDefaultTextColor(Qt.white) self.recycle_unused_items() # Update the scene so it can repaint properly self.scene.update() def update_items(self): time_step = self.updateItemsTimer.interval() / float(self.updateProcessDataTimer.interval()) for item in self.activeItems: item.update(time_step) def fetch_task_item(self): # Add more graphic items if there isn't enough in the pool. if len(self.taskItemPool) == 0: self.add_new_task_graphics_item() item = self.taskItemPool.pop() item.setVisible(True) self.activeItems.append(item) return item def recycle_task_item(self, item): item.setVisible(False) self.taskItemPool.append(item) # Items without an active process are recycled def recycle_unused_items(self): # Recycle unused. for item in self.activeItems: if not item.used: self.recycle_task_item(item) # Only keep the used items. self.activeItems = [item for item in self.activeItems if item.used] def add_new_task_graphics_item(self, visible=True): item = TaskGraphicsItem(QRectF(0, 0, 1, 1)) item.setVisible(visible) self.taskItemPool.append(item) self.scene.addItem(item) def setup_mem_axis(self): self.memAxis = QGraphicsLineItem(self.memXOffset, 0, self.memXOffset, self.memAxisLen, None, self.scene) self.memAxis.setPen(QPen(Qt.white)) step = int(self._memTickInterval * self.memAxisLen) pen = QPen(Qt.CustomDashLine) pen.setDashPattern([2, 20]) pen.setColor(Qt.lightGray) for y in range(step, self.memAxisLen + step, step): self.scene.addLine(self.memXOffset, y, 2500.0, y, pen) def update_mem_axis(self): # Set Length of line to the x value of the last active task item. pass
def setAxisIntersect(self, intersect): self._axisIntersect = intersect #print "SkeletonsLayer(axis=%d) is updating intersect=%d" % (self._axis, self._axisIntersect) nodes, eIntersected, ePlane = self._3d._skeletons.intersect( self._axis, self._axisIntersect) #update existing items toRemove = [] for node, item in self._node2view.iteritems(): if node.pos[self._axis] != self._axisIntersect: self._scene.removeItem(item) toRemove.append(node) elif node.pointF(self._axis) != item.pos(): item.setPos(self._scene.data2scene.map(node.pointF( self._axis))) if node.isSelected() != item.isSelected(): item.setSelected(node.isSelected()) assert item.isSelected() == node.isSelected() i = 0 newSize = [0, 0] for j in range(3): if j == self._axis: continue newSize[i] = node.shape[j] i += 1 newRectF = QRectF(0, 0, *newSize) newRectF = self._scene.data2scene.mapRect(newRectF) item.setRect( QRectF(-newRectF.width() / 2.0, -newRectF.height() / 2.0, newRectF.width(), newRectF.height())) for r in toRemove: del self._node2view[r] #add new views for nodes for n in nodes: if n in self._node2view: continue pos2D = list(n.pos) del pos2D[self._axis] shape2D = n.shape2D(self._axis) itm = QGraphicsSkeletonNode(shape2D, skeletons=self._3d._skeletons, node=n) itm.setPos(self._scene.data2scene.map(QPointF(*pos2D))) itm.setSelected(n.isSelected()) self._scene.addItem(itm) self._node2view[n] = itm for itm in self._edge2view.values(): self._scene.removeItem(itm) self._edge2view = dict() for e in ePlane: l = QLineF(e[0].pointF(), e[1].pointF()) c1 = e[0].color() c2 = e[1].color() mixColor = QColor((c1.red() + c2.red()) / 2, (c1.green() + c2.green()) / 2, (c1.blue() + c2.blue()) / 2) line = QGraphicsLineItem(self._scene.data2scene.map(l)) line.setPen(QPen(mixColor)) self._scene.addItem(line) self._edge2view[e] = line for theEdge, e in eIntersected: c1 = theEdge[0].color() c2 = theEdge[1].color() mixColor = QColor((c1.red() + c2.red()) / 2, (c1.green() + c2.green()) / 2, (c1.blue() + c2.blue()) / 2) nodeSize = 6 p = QGraphicsRectItem(-nodeSize / 2, -nodeSize / 2, nodeSize, nodeSize) pos2D = list(e) del pos2D[self._axis] p.setPos(self._scene.data2scene.map(QPointF(*pos2D))) p.setPen(QPen(mixColor)) self._scene.addItem(p) self._edge2view[e] = p
def setColor(self, color): pen = QPen(color) QGraphicsLineItem.setPen(self, pen)
def resetColor(self): pen = QPen(QColor.fromRgb(0,0,0)) QGraphicsLineItem.setPen(self, pen)
def _offseted_line(ax, ay): r = QGraphicsLineItem(x + ax, y + ay, x + (ax or w), y + (ay or h)) self.canvas.addItem(r) r.setPen(pen)
def line(x1, y1, x2, y2): r = QGraphicsLineItem(x1, y1, x2, y2, None) self.canvas.addItem(r) r.setPen(QPen(Qt.white, 2)) r.setZValue(30)
def setAxisIntersect(self, intersect): self._axisIntersect = intersect #print "SkeletonsLayer(axis=%d) is updating intersect=%d" % (self._axis, self._axisIntersect) nodes, eIntersected, ePlane = self._3d._skeletons.intersect(self._axis, self._axisIntersect) #update existing items toRemove = [] for node, item in self._node2view.iteritems(): if node.pos[self._axis] != self._axisIntersect: self._scene.removeItem(item) toRemove.append(node) elif node.pointF(self._axis) != item.pos(): item.setPos( self._scene.data2scene.map( node.pointF(self._axis) ) ) if node.isSelected() != item.isSelected(): item.setSelected(node.isSelected()) assert item.isSelected() == node.isSelected() i = 0 newSize = [0,0] for j in range(3): if j == self._axis: continue newSize[i] = node.shape[j] i += 1 newRectF = QRectF(0,0,*newSize) newRectF = self._scene.data2scene.mapRect(newRectF) item.setRect(QRectF(-newRectF.width()/2.0, -newRectF.height()/2.0, newRectF.width(), newRectF.height())) for r in toRemove: del self._node2view[r] #add new views for nodes for n in nodes: if n in self._node2view: continue pos2D = list(n.pos) del pos2D[self._axis] shape2D = n.shape2D(self._axis) itm = QGraphicsSkeletonNode(shape2D, skeletons=self._3d._skeletons, node = n) itm.setPos(self._scene.data2scene.map(QPointF(*pos2D))) itm.setSelected(n.isSelected()) self._scene.addItem(itm) self._node2view[n] = itm for itm in self._edge2view.values(): self._scene.removeItem(itm) self._edge2view = dict() for e in ePlane: l = QLineF(e[0].pointF(), e[1].pointF()) c1 = e[0].color() c2 = e[1].color() mixColor = QColor( (c1.red()+c2.red())/2, (c1.green()+c2.green())/2, (c1.blue()+c2.blue())/2 ) line = QGraphicsLineItem(self._scene.data2scene.map(l)) line.setPen(QPen(mixColor)) self._scene.addItem(line) self._edge2view[e] = line for theEdge, e in eIntersected: c1 = theEdge[0].color() c2 = theEdge[1].color() mixColor = QColor( (c1.red()+c2.red())/2, (c1.green()+c2.green())/2, (c1.blue()+c2.blue())/2 ) nodeSize = 6 p = QGraphicsRectItem(-nodeSize/2, -nodeSize/2, nodeSize, nodeSize) pos2D = list(e) del pos2D[self._axis] p.setPos(self._scene.data2scene.map(QPointF(*pos2D))) p.setPen(QPen(mixColor)) self._scene.addItem(p) self._edge2view[e] = p
def draw_stick(self, x, y, i): lineItem = QGraphicsLineItem(0, self.coordY(self.ylim[0]), 0, self.coordY(y), parent=self.item) lineItem.setX(x) lineItem.setPen(QPen(QColor(self.colors[i]),2))
def draw_hlines (self, line, col): lineItem = QGraphicsLineItem(0, self.coordY(line), self.width, self.coordY(line), parent=self.item) lineItem.setPen(QPen(QColor(col), 1, Qt.DashLine)) lineItem.setZValue(10)
def draw_bar(self, x, y, i): h = self.coordY(self.ylim[0]) #self.height coordY = self.coordY item = self.item # if value stands out of bound if y < self.ylim[0]: return if y < self.ylim[1]: # left line lineItem = QGraphicsLineItem(0, h, 0, coordY(y), parent=item) lineItem.setX(x - 3) lineItem.setPen(QPen(QColor(self.colors[i]), 2)) # right line lineItem = QGraphicsLineItem(0, h, 0, coordY(y), parent=item) lineItem.setX(x + 3) lineItem.setPen(QPen(QColor(self.colors[i]), 2)) # top line lineItem = QGraphicsLineItem(0, coordY(y), 6, coordY(y), parent=item) lineItem.setX(x - 3) lineItem.setPen(QPen(QColor(self.colors[i]), 2)) else: # lower left line lineItem = QGraphicsLineItem(0, h, 0, coordY(y), parent=item) lineItem.setX(x - 3) lineItem.setPen(QPen(QColor(self.colors[i]), 2)) # lower right line lineItem = QGraphicsLineItem(0, h, 0, coordY(y), parent=item) lineItem.setX(x + 3) lineItem.setPen(QPen(QColor(self.colors[i]), 2)) # upper left line lineItem = QGraphicsLineItem(0, coordY(y) - 4, 0, coordY(y) - 7, parent=item) lineItem.setX(x - 3) lineItem.setPen(QPen(QColor(self.colors[i]), 2)) # upper right line lineItem = QGraphicsLineItem(0, coordY(y) - 4, 0, coordY(y) - 7, parent=item) lineItem.setX(x + 3) lineItem.setPen(QPen(QColor(self.colors[i]), 2)) # top line lineItem = QGraphicsLineItem(0, coordY(y) - 7, 6, coordY(y) - 7, parent=item) lineItem.setX(x - 3) lineItem.setPen(QPen(QColor(self.colors[i]), 2))
class OWAxis(QGraphicsItem): Role = OWPalette.Axis def __init__(self, id, title = '', title_above = False, title_location = AxisMiddle, line = None, arrows = 0, plot = None): QGraphicsItem.__init__(self) self.setFlag(QGraphicsItem.ItemHasNoContents) self.setZValue(AxisZValue) self.id = id self.title = title self.title_location = title_location self.data_line = line self.plot = plot self.graph_line = None self.size = None self.scale = None self.tick_length = (10, 5, 0) self.arrows = arrows self.title_above = title_above self.line_item = QGraphicsLineItem(self) self.title_item = QGraphicsTextItem(self) self.end_arrow_item = None self.start_arrow_item = None self.show_title = False self.scale = None path = QPainterPath() path.setFillRule(Qt.WindingFill) path.moveTo(0, 3.09) path.lineTo(0, -3.09) path.lineTo(9.51, 0) path.closeSubpath() self.arrow_path = path self.label_items = [] self.label_bg_items = [] self.tick_items = [] self._ticks = [] self.zoom_transform = QTransform() self.labels = None self.auto_range = None self.auto_scale = True self.zoomable = False self.update_callback = None self.max_text_width = 50 self.text_margin = 5 self.always_horizontal_text = False @staticmethod def compute_scale(min, max): magnitude = int(3*log10(abs(max-min)) + 1) if magnitude % 3 == 0: first_place = 1 elif magnitude % 3 == 1: first_place = 2 else: first_place = 5 magnitude = magnitude // 3 - 1 step = first_place * pow(10, magnitude) first_val = ceil(min/step) * step return first_val, step def update_ticks(self): self._ticks = [] major, medium, minor = self.tick_length if self.labels is not None and not self.auto_scale: for i, text in enumerate(self.labels): self._ticks.append( ( i, text, medium, 1 ) ) else: if self.scale and not self.auto_scale: min, max, step = self.scale elif self.auto_range: min, max = self.auto_range if min is not None and max is not None: step = (max - min)/10 else: return else: return if max == min: return val, step = self.compute_scale(min, max) while val <= max: self._ticks.append( ( val, "%.4g" % val, medium, step ) ) val += step def update_graph(self): if self.update_callback: self.update_callback() def update(self, zoom_only = False): self.update_ticks() line_color = self.plot.color(OWPalette.Axis) text_color = self.plot.color(OWPalette.Text) if not self.graph_line or not self.scene(): return self.line_item.setLine(self.graph_line) self.line_item.setPen(line_color) if self.title: self.title_item.setHtml('<b>' + self.title + '</b>') self.title_item.setDefaultTextColor(text_color) if self.title_location == AxisMiddle: title_p = 0.5 elif self.title_location == AxisEnd: title_p = 0.95 else: title_p = 0.05 title_pos = self.graph_line.pointAt(title_p) v = self.graph_line.normalVector().unitVector() dense_text = False if hasattr(self, 'title_margin'): offset = self.title_margin elif self._ticks: if self.should_be_expanded(): offset = 55 dense_text = True else: offset = 35 else: offset = 10 if self.title_above: title_pos = title_pos + (v.p2() - v.p1())*(offset + QFontMetrics(self.title_item.font()).height()) else: title_pos = title_pos - (v.p2() - v.p1())*offset ## TODO: Move it according to self.label_pos self.title_item.setVisible(self.show_title) self.title_item.setRotation(-self.graph_line.angle()) c = self.title_item.mapToParent(self.title_item.boundingRect().center()) tl = self.title_item.mapToParent(self.title_item.boundingRect().topLeft()) self.title_item.setPos(title_pos - c + tl) ## Arrows if not zoom_only: if self.start_arrow_item: self.scene().removeItem(self.start_arrow_item) self.start_arrow_item = None if self.end_arrow_item: self.scene().removeItem(self.end_arrow_item) self.end_arrow_item = None if self.arrows & AxisStart: if not zoom_only or not self.start_arrow_item: self.start_arrow_item = QGraphicsPathItem(self.arrow_path, self) self.start_arrow_item.setPos(self.graph_line.p1()) self.start_arrow_item.setRotation(-self.graph_line.angle() + 180) self.start_arrow_item.setBrush(line_color) self.start_arrow_item.setPen(line_color) if self.arrows & AxisEnd: if not zoom_only or not self.end_arrow_item: self.end_arrow_item = QGraphicsPathItem(self.arrow_path, self) self.end_arrow_item.setPos(self.graph_line.p2()) self.end_arrow_item.setRotation(-self.graph_line.angle()) self.end_arrow_item.setBrush(line_color) self.end_arrow_item.setPen(line_color) ## Labels n = len(self._ticks) resize_plot_item_list(self.label_items, n, QGraphicsTextItem, self) resize_plot_item_list(self.label_bg_items, n, QGraphicsRectItem, self) resize_plot_item_list(self.tick_items, n, QGraphicsLineItem, self) test_rect = QRectF(self.graph_line.p1(), self.graph_line.p2()).normalized() test_rect.adjust(-1, -1, 1, 1) n_v = self.graph_line.normalVector().unitVector() if self.title_above: n_p = n_v.p2() - n_v.p1() else: n_p = n_v.p1() - n_v.p2() l_v = self.graph_line.unitVector() l_p = l_v.p2() - l_v.p1() for i in range(n): pos, text, size, step = self._ticks[i] hs = 0.5 * step tick_pos = self.map_to_graph( pos ) if not test_rect.contains(tick_pos): self.tick_items[i].setVisible(False) self.label_items[i].setVisible(False) continue item = self.label_items[i] item.setVisible(True) if not zoom_only: if self.id in XAxes or getattr(self, 'is_horizontal', False): item.setHtml( '<center>' + Qt.escape(text.strip()) + '</center>') else: item.setHtml(Qt.escape(text.strip())) item.setTextWidth(-1) text_angle = 0 if dense_text: w = min(item.boundingRect().width(), self.max_text_width) item.setTextWidth(w) if self.title_above: label_pos = tick_pos + n_p * (w + self.text_margin) + l_p * item.boundingRect().height()/2 else: label_pos = tick_pos + n_p * self.text_margin + l_p * item.boundingRect().height()/2 text_angle = -90 if self.title_above else 90 else: w = min(item.boundingRect().width(), QLineF(self.map_to_graph(pos - hs), self.map_to_graph(pos + hs) ).length()) label_pos = tick_pos + n_p * self.text_margin - l_p * w/2 item.setTextWidth(w) if not self.always_horizontal_text: if self.title_above: item.setRotation(-self.graph_line.angle() - text_angle) else: item.setRotation(self.graph_line.angle() - text_angle) item.setPos(label_pos) item.setDefaultTextColor(text_color) self.label_bg_items[i].setRect(item.boundingRect()) self.label_bg_items[i].setPen(QPen(Qt.NoPen)) self.label_bg_items[i].setBrush(self.plot.color(OWPalette.Canvas)) item = self.tick_items[i] item.setVisible(True) tick_line = QLineF(v) tick_line.translate(-tick_line.p1()) tick_line.setLength(size) if self.title_above: tick_line.setAngle(tick_line.angle() + 180) item.setLine( tick_line ) item.setPen(line_color) item.setPos(self.map_to_graph(pos)) @staticmethod def make_title(label, unit = None): lab = '<i>' + label + '</i>' if unit: lab = lab + ' [' + unit + ']' return lab def set_line(self, line): self.graph_line = line self.update() def set_title(self, title): self.title = title self.update() def set_show_title(self, b): self.show_title = b self.update() def set_labels(self, labels): self.labels = labels self.graph_line = None self.auto_scale = False self.update_ticks() self.update_graph() def set_scale(self, min, max, step_size): self.scale = (min, max, step_size) self.graph_line = None self.auto_scale = False self.update_ticks() self.update_graph() def set_tick_length(self, minor, medium, major): self.tick_length = (minor, medium, major) self.update() def map_to_graph(self, x): min, max = self.plot.bounds_for_axis(self.id) if min == max: return QPointF() line_point = self.graph_line.pointAt( (x-min)/(max-min) ) end_point = line_point * self.zoom_transform return self.projection(end_point, self.graph_line) @staticmethod def projection(point, line): norm = line.normalVector() norm.translate(point - norm.p1()) p = QPointF() type = line.intersect(norm, p) return p def continuous_labels(self): min, max, step = self.scale magnitude = log10(abs(max-min)) def paint(self, painter, option, widget): pass def boundingRect(self): return QRectF() def ticks(self): if not self._ticks: self.update_ticks() return self._ticks def bounds(self): if self.labels: return -0.2, len(self.labels) -0.8 elif self.scale: min, max, _step = self.scale return min, max elif self.auto_range: return self.auto_range else: return 0, 1 def should_be_expanded(self): self.update_ticks() return self.id in YAxes or self.always_horizontal_text or sum(len(t[1]) for t in self._ticks) * 12 > self.plot.width()
def line(scene, x1, y1, x2, y2, color="blue", width=5): item = QGraphicsLineItem(x1, y1, x2, y2) pen = QPen(QColor(color)) pen.setWidth(width) item.setPen(pen) scene.addItem(item)
class OWAxis(QGraphicsItem): Role = OWPalette.Axis def __init__(self, id, title='', title_above=False, title_location=AxisMiddle, line=None, arrows=AxisEnd, plot=None): QGraphicsItem.__init__(self) self.setFlag(QGraphicsItem.ItemHasNoContents) self.setZValue(AxisZValue) self.id = id self.title = title self.title_location = title_location self.data_line = line self.plot = plot self.graph_line = None self.size = None self.scale = None self.tick_length = (10, 5, 0) self.arrows = arrows self.title_above = title_above self.line_item = QGraphicsLineItem(self) self.title_item = QGraphicsTextItem(self) self.end_arrow_item = None self.start_arrow_item = None self.show_title = False self.scale = None path = QPainterPath() path.setFillRule(Qt.WindingFill) path.moveTo(0, 3.09) path.lineTo(0, -3.09) path.lineTo(9.51, 0) path.closeSubpath() self.arrow_path = path self.label_items = [] self.label_bg_items = [] self.tick_items = [] self._ticks = [] self.zoom_transform = QTransform() self.labels = None self.auto_range = None self.auto_scale = True self.zoomable = False self.update_callback = None self.max_text_width = 50 self.text_margin = 5 self.always_horizontal_text = False def update_ticks(self): self._ticks = [] major, medium, minor = self.tick_length if self.labels is not None and not self.auto_scale: for i, text in enumerate(self.labels): self._ticks.append((i, text, medium, 1)) else: if self.scale and not self.auto_scale: min, max, step = self.scale elif self.auto_range: min, max = self.auto_range if min is not None and max is not None: step = (max - min) / 10 else: return else: return if max == min: return magnitude = int(3 * log10(abs(max - min)) + 1) if magnitude % 3 == 0: first_place = 1 elif magnitude % 3 == 1: first_place = 2 else: first_place = 5 magnitude = magnitude / 3 - 1 step = first_place * pow(10, magnitude) val = ceil(min / step) * step while val <= max: self._ticks.append((val, "%.4g" % val, medium, step)) val = val + step def update_graph(self): if self.update_callback: self.update_callback() def update(self, zoom_only=False): self.update_ticks() line_color = self.plot.color(OWPalette.Axis) text_color = self.plot.color(OWPalette.Text) if not self.graph_line or not self.scene(): return self.line_item.setLine(self.graph_line) self.line_item.setPen(line_color) if self.title: self.title_item.setHtml('<b>' + self.title + '</b>') self.title_item.setDefaultTextColor(text_color) if self.title_location == AxisMiddle: title_p = 0.5 elif self.title_location == AxisEnd: title_p = 0.95 else: title_p = 0.05 title_pos = self.graph_line.pointAt(title_p) v = self.graph_line.normalVector().unitVector() dense_text = False if hasattr(self, 'title_margin'): offset = self.title_margin elif self._ticks: if self.should_be_expanded(): offset = 55 dense_text = True else: offset = 35 else: offset = 10 if self.title_above: title_pos = title_pos + (v.p2() - v.p1()) * ( offset + QFontMetrics(self.title_item.font()).height()) else: title_pos = title_pos - (v.p2() - v.p1()) * offset ## TODO: Move it according to self.label_pos self.title_item.setVisible(self.show_title) self.title_item.setRotation(-self.graph_line.angle()) c = self.title_item.mapToParent( self.title_item.boundingRect().center()) tl = self.title_item.mapToParent( self.title_item.boundingRect().topLeft()) self.title_item.setPos(title_pos - c + tl) ## Arrows if not zoom_only: if self.start_arrow_item: self.scene().removeItem(self.start_arrow_item) self.start_arrow_item = None if self.end_arrow_item: self.scene().removeItem(self.end_arrow_item) self.end_arrow_item = None if self.arrows & AxisStart: if not zoom_only or not self.start_arrow_item: self.start_arrow_item = QGraphicsPathItem( self.arrow_path, self) self.start_arrow_item.setPos(self.graph_line.p1()) self.start_arrow_item.setRotation(-self.graph_line.angle() + 180) self.start_arrow_item.setBrush(line_color) self.start_arrow_item.setPen(line_color) if self.arrows & AxisEnd: if not zoom_only or not self.end_arrow_item: self.end_arrow_item = QGraphicsPathItem(self.arrow_path, self) self.end_arrow_item.setPos(self.graph_line.p2()) self.end_arrow_item.setRotation(-self.graph_line.angle()) self.end_arrow_item.setBrush(line_color) self.end_arrow_item.setPen(line_color) ## Labels n = len(self._ticks) resize_plot_item_list(self.label_items, n, QGraphicsTextItem, self) resize_plot_item_list(self.label_bg_items, n, QGraphicsRectItem, self) resize_plot_item_list(self.tick_items, n, QGraphicsLineItem, self) test_rect = QRectF(self.graph_line.p1(), self.graph_line.p2()).normalized() test_rect.adjust(-1, -1, 1, 1) n_v = self.graph_line.normalVector().unitVector() if self.title_above: n_p = n_v.p2() - n_v.p1() else: n_p = n_v.p1() - n_v.p2() l_v = self.graph_line.unitVector() l_p = l_v.p2() - l_v.p1() for i in range(n): pos, text, size, step = self._ticks[i] hs = 0.5 * step tick_pos = self.map_to_graph(pos) if not test_rect.contains(tick_pos): self.tick_items[i].setVisible(False) self.label_items[i].setVisible(False) continue item = self.label_items[i] item.setVisible(True) if not zoom_only: if self.id in XAxes or getattr(self, 'is_horizontal', False): item.setHtml('<center>' + Qt.escape(text.strip()) + '</center>') else: item.setHtml(Qt.escape(text.strip())) item.setTextWidth(-1) text_angle = 0 if dense_text: w = min(item.boundingRect().width(), self.max_text_width) item.setTextWidth(w) if self.title_above: label_pos = tick_pos + n_p * ( w + self.text_margin ) + l_p * item.boundingRect().height() / 2 else: label_pos = tick_pos + n_p * self.text_margin + l_p * item.boundingRect( ).height() / 2 text_angle = -90 if self.title_above else 90 else: w = min( item.boundingRect().width(), QLineF(self.map_to_graph(pos - hs), self.map_to_graph(pos + hs)).length()) label_pos = tick_pos + n_p * self.text_margin - l_p * w / 2 item.setTextWidth(w) if not self.always_horizontal_text: if self.title_above: item.setRotation(-self.graph_line.angle() - text_angle) else: item.setRotation(self.graph_line.angle() - text_angle) item.setPos(label_pos) item.setDefaultTextColor(text_color) self.label_bg_items[i].setRect(item.boundingRect()) self.label_bg_items[i].setPen(QPen(Qt.NoPen)) self.label_bg_items[i].setBrush(self.plot.color(OWPalette.Canvas)) item = self.tick_items[i] item.setVisible(True) tick_line = QLineF(v) tick_line.translate(-tick_line.p1()) tick_line.setLength(size) if self.title_above: tick_line.setAngle(tick_line.angle() + 180) item.setLine(tick_line) item.setPen(line_color) item.setPos(self.map_to_graph(pos)) @staticmethod def make_title(label, unit=None): lab = '<i>' + label + '</i>' if unit: lab = lab + ' [' + unit + ']' return lab def set_line(self, line): self.graph_line = line self.update() def set_title(self, title): self.title = title self.update() def set_show_title(self, b): self.show_title = b self.update() def set_labels(self, labels): self.labels = labels self.graph_line = None self.auto_scale = False self.update_ticks() self.update_graph() def set_scale(self, min, max, step_size): self.scale = (min, max, step_size) self.graph_line = None self.auto_scale = False self.update_ticks() self.update_graph() def set_tick_length(self, minor, medium, major): self.tick_length = (minor, medium, major) self.update() def map_to_graph(self, x): min, max = self.plot.bounds_for_axis(self.id) if min == max: return QPointF() line_point = self.graph_line.pointAt((x - min) / (max - min)) end_point = line_point * self.zoom_transform return self.projection(end_point, self.graph_line) @staticmethod def projection(point, line): norm = line.normalVector() norm.translate(point - norm.p1()) p = QPointF() type = line.intersect(norm, p) return p def continuous_labels(self): min, max, step = self.scale magnitude = log10(abs(max - min)) def paint(self, painter, option, widget): pass def boundingRect(self): return QRectF() def ticks(self): if not self._ticks: self.update_ticks() return self._ticks def bounds(self): if self.labels: return -0.2, len(self.labels) - 0.8 elif self.scale: min, max, _step = self.scale return min, max elif self.auto_range: return self.auto_range else: return 0, 1 def should_be_expanded(self): self.update_ticks() return self.id in YAxes or self.always_horizontal_text or sum( len(t[1]) for t in self._ticks) * 12 > self.plot.width()
def drawHistogram(self): if self.result is None: return # Label the histogram #self.minValueLabel.setText(str(self.minValue)) #self.maxValueLabel.setText(str(self.maxValue)) minvaltext = QGraphicsTextItem(str(self.minValue)) minvaltextheight = minvaltext.boundingRect().height() maxvaltext = QGraphicsTextItem(str(self.maxValue)) maxvaltextwidth = maxvaltext.boundingRect().width() #self.showInfo(str(self.result)) # Check which element should be used for the histogram element = 1 maxvalue = 0.0 for i in range(len(self.result)): if self.result[i][element] > maxvalue: maxvalue = self.result[i][element] # Find the maximum value for scaling cutoffvalue = maxvalue if (self.frequencyRangeSpinBox.value() > 0): cutoffvalue = self.frequencyRangeSpinBox.value() #self.maxNumberLabel.setText(str(maxvalue)) #self.maxNumberLabel.setText(str(cutoffvalue)) self.scene.clear() if maxvalue == 0: return viewprect = QRectF(self.histogramGraphicsView.viewport().rect()) self.histogramGraphicsView.setSceneRect(viewprect) bottom = self.histogramGraphicsView.sceneRect().bottom() top = self.histogramGraphicsView.sceneRect().top() left = self.histogramGraphicsView.sceneRect().left() right = self.histogramGraphicsView.sceneRect().right() height = bottom - top - 1 width = right - left - 1 padding = 3 toppadding = 3 bottompadding = minvaltextheight # Determine the width of the left margin (depends on the y range) clog = log(cutoffvalue,10) clogint = int(clog) #clogrem = clog % clogint yincr = pow(10,clogint) dummytext = QGraphicsTextItem(str(yincr)) # The left padding must accomodate the y labels leftpadding = dummytext.boundingRect().width() #leftpadding = 30 # Find the width of the maximium frequency label maxfreqtext = QGraphicsTextItem(str(cutoffvalue)) maxfreqtextwidth = maxvaltext.boundingRect().width() rightpadding = maxfreqtextwidth width = width - (leftpadding + rightpadding) height = height - (toppadding + bottompadding) barwidth = width / self.bins #center = QPoint(left + width / 2.0, top + height / 2.0) #start = QPointF(self.histogramGraphicsView.mapToScene(center)) # Create the histogram for i in range(self.bins): #barheight = height * self.result[i][element] / maxvalue barheight = height * self.result[i][element] / cutoffvalue barrect = QGraphicsRectItem(QRectF(leftpadding + barwidth * i, height-barheight+toppadding, barwidth, barheight)) barbrush = QBrush(QColor(255,153,102)) barrect.setBrush(barbrush) self.scene.addItem(barrect) # Determine the increments for the horizontal lines if (cutoffvalue // yincr <= 5 and yincr > 1 ): yincr = yincr / 2 if (cutoffvalue // yincr < 5 and yincr > 10 ): yincr = yincr / 2 # Draw horizontal lines with labels yval = 0 while (yval <= cutoffvalue): scval = height + toppadding - yval * height / cutoffvalue hline = QGraphicsLineItem(QLineF(leftpadding-2, scval,width+(leftpadding),scval)) hlinepen = QPen(QColor(153,153,153)) hline.setPen(hlinepen) self.scene.addItem(hline) ylabtext = QGraphicsTextItem(str(int(yval))) ylabtextheight = ylabtext.boundingRect().height() ylabtextwidth = ylabtext.boundingRect().width() ylabtext.setPos(leftpadding - ylabtextwidth, scval - ylabtextheight/2) if (scval - ylabtextheight/2 > 0): self.scene.addItem(ylabtext) yval = yval + yincr #yincr = (cutoffvalue / 10) minvaltextwidth = minvaltext.boundingRect().width() minvaltext.setPos(leftpadding - minvaltextwidth/2, height + toppadding + bottompadding - minvaltextheight) self.scene.addItem(minvaltext) maxvaltext.setPos(leftpadding + width - maxvaltextwidth/2, height + toppadding + bottompadding - minvaltextheight) self.scene.addItem(maxvaltext) maxfreqtext.setPos(leftpadding + width, 0) self.scene.addItem(maxfreqtext)
class AxisItem(pg.GraphicsObject): def __init__(self, parent=None, line=None, label=None, **kwargs): super().__init__(parent, **kwargs) self.setFlag(pg.GraphicsObject.ItemHasNoContents) if line is None: line = QLineF(0, 0, 1, 0) self._spine = QGraphicsLineItem(line, self) angle = QLineF(0, 0, 1, 0).angleTo(line) angle = (180 - angle) % 360 dx = line.x2() - line.x1() dy = line.y2() - line.y1() rad = numpy.arctan2(dy, dx) angle = (rad * 180 / numpy.pi) % 360 self._arrow = pg.ArrowItem(parent=self, angle=180 - angle) self._arrow.setPos(self._spine.line().p2()) self._label = pg.TextItem(text=label, color=(10, 10, 10)) self._label.setParentItem(self) self._label.setPos(self._spine.line().p2()) def setLabel(self, label): if label != self._label: self._label = label self._label.setText(label) def setPen(self, pen): self._spine.setPen(pen) def paint(self, painter, option, widget): pass def boundingRect(self): return QRectF() def viewTransformChanged(self): self.__updateLabelPos() def __updateLabelPos(self): T = self.viewTransform() if T is not None: Tinv, ok = T.inverted() else: Tinv, ok = None, False if not ok: T = Tinv = QtGui.QTransform() # map the axis spine to viewbox coord. system viewbox_line = Tinv.map(self._spine.line()) angle = viewbox_line.angle() # note in Qt the y axis is inverted (90 degree angle 'points' down) left_quad = 270 <= angle <= 360 or -0.0 <= angle < 90 # position the text label along the viewbox_line label_pos = viewbox_line.pointAt(0.90) if left_quad: anchor = (0.5, -0.1) else: anchor = (0.5, 1.1) pos = T.map(label_pos) self._label.setPos(pos) self._label.anchor = pg.Point(*anchor) self._label.updateText() self._label.setRotation(angle if left_quad else angle - 180)
def draw_bar(self, x, y, i): h = self.coordY(self.ylim[0])#self.height coordY = self.coordY item = self.item # if value stands out of bound if y < self.ylim[0]: return if y < self.ylim[1]: # left line lineItem = QGraphicsLineItem(0, h, 0, coordY(y), parent=item) lineItem.setX(x-3) lineItem.setPen(QPen(QColor(self.colors[i]),2)) # right line lineItem = QGraphicsLineItem(0, h, 0, coordY(y), parent=item) lineItem.setX(x+3) lineItem.setPen(QPen(QColor(self.colors[i]),2)) # top line lineItem = QGraphicsLineItem(0, coordY(y), 6, coordY(y), parent=item) lineItem.setX(x-3) lineItem.setPen(QPen(QColor(self.colors[i]),2)) else: # lower left line lineItem = QGraphicsLineItem(0, h, 0, coordY(y), parent=item) lineItem.setX(x-3) lineItem.setPen(QPen(QColor(self.colors[i]),2)) # lower right line lineItem = QGraphicsLineItem(0, h, 0, coordY(y), parent=item) lineItem.setX(x+3) lineItem.setPen(QPen(QColor(self.colors[i]),2)) # upper left line lineItem = QGraphicsLineItem(0, coordY(y)-4, 0, coordY(y)-7, parent=item) lineItem.setX(x-3) lineItem.setPen(QPen(QColor(self.colors[i]),2)) # upper right line lineItem = QGraphicsLineItem(0, coordY(y)-4, 0, coordY(y)-7, parent=item) lineItem.setX(x+3) lineItem.setPen(QPen(QColor(self.colors[i]),2)) # top line lineItem = QGraphicsLineItem(0, coordY(y)-7, 6, coordY(y)-7, parent=item) lineItem.setX(x-3) lineItem.setPen(QPen(QColor(self.colors[i]),2))