Source code for optimeed.visualize.gui.widgets.graphsVisualWidget.traceVisual

from . import pyqtgraph as pg
from PyQt5 import QtCore, QtGui


[docs]class TraceVisual(QtCore.QObject): """Defines a trace in a graph."""
[docs] signal_must_update = QtCore.pyqtSignal()
[docs] class _ModifiedPaintElem: """Hidden class to manage brushes or pens""" def __init__(self): self.indices = list() self.newPaintElems = list()
[docs] def add_modified_paintElem(self, index, newPaintElem): try: indexInList = self.indices.index(index) self.indices[indexInList] = index self.newPaintElems[indexInList] = newPaintElem except ValueError: self.indices.append(index) self.newPaintElems.append(newPaintElem)
[docs] def modify_paintElems(self, paintElemsIn_List): """ Apply transformation to paintElemsIn_List :param paintElemsIn_List: list of brushes or pens to modify :return: False if nothing has been modified, True is something has been modified """ if not len(self.indices): return False for i in range(len(self.indices)): try: paintElemsIn_List[self.indices[i]] = self.newPaintElems[i] except IndexError: print("WidgetGraphsVisual: Could not apply paintElem ... point deleted ?") return True
[docs] def reset_paintElem(self, index): """ Remove transformation of point index""" try: indexInList = self.indices.index(index) del self.indices[indexInList] del self.newPaintElems[indexInList] except ValueError: pass
[docs] def reset(self): self.__init__()
def __init__(self, theData, theWGPlot, highlight_last): """ :param theColor: Color of the trace. If color is specified in data, this is overriden. :param theData: from class Data. Contains all the informations to plot (x, y, z, transforms, etc.) :param theWGPlot: holder of the trace. This is a plotWidget :param highlight_last: Boolean. If set to true, the last point in the data will be highlighted. """ super().__init__() # set brush self.theBrushesModifier = self._ModifiedPaintElem() # set symbolPen self.theSymbolPensModifier = self._ModifiedPaintElem() # set symbols self.theSymbolModifier = self._ModifiedPaintElem() # set data self.theData = theData # set trace item (plotItem) if theData.get_legend(): self.thePlotItem = theWGPlot.plot([float('inf')], name=theData.get_legend()) else: self.thePlotItem = theWGPlot.plot([float('inf')]) # set highlight last self.highlight_last = highlight_last self.drawPoints = True # signals self.signal_must_update.connect(self.updateTrace)
[docs] def hide_points(self): """Hide all the points""" self.drawPoints = False self.signal_must_update.emit()
[docs] def get_color(self): """Get colour of the trace, return tuple (r,g,b)""" return self.get_data().get_color()
[docs] def set_color(self, color): """Set colour of the trace, argument as tuple (r,g,b)""" self.get_data().set_color(color) self.thePlotItem.scatter.opts['brush'] = color
[docs] def get_base_symbol_brush(self): """Get symbol brush configured for this trace, return :class:`pg.QBrush`""" return pg.mkBrush(self.get_color())
[docs] def get_base_pen(self): """Get pen configured for this trace, return :class:`pg.QPen`""" return pg.mkPen(self.get_color(), width=self.get_data().get_width())
[docs] def get_base_symbol_pen(self): """Get symbol pen configured for this trace, return :class:`pg.QPen`""" if self.get_data().symbol_isfilled(): return pg.mkPen(QtGui.QColor(*self.get_color()).darker(int(self.get_data().get_symbolOutline()*100)), isCosmetic=True) # 120 or 250 ? :) else: return pg.mkPen(self.get_color(), isCosmetic=False, width=self.get_data().get_width())
[docs] def get_base_symbol(self): """Get base symbol configured for this trace, return str of the symbol (e.g. 'o')""" return self.get_data().get_symbol()
[docs] def get_symbol(self, size): """Get actual symbols for the trace. If the symbols have been modified: return a list which maps each points to a symbol. Otherwise: return :meth:TraceVisual.get_base_symbol()""" symbol = self.get_base_symbol() theSymbolList = [symbol] * size hasBeenModified = self.theSymbolModifier.modify_paintElems(theSymbolList) return symbol if not hasBeenModified else theSymbolList
[docs] def updateTrace(self): """Forces the trace to refresh.""" try: theData = self.get_data() x, y = theData.get_plot_data() if x: if self.drawPoints: theBrushes = self.get_brushes(len(x)) theSymbolPens = self.get_symbolPens(len(x)) else: theBrushes = None theSymbolPens = None theBasePen = self.get_base_pen() if theData.is_scattered(): theBasePen.setStyle(QtCore.Qt.NoPen) else: self.set_pen_linestyle(theBasePen, theData.get_linestyle()) self.thePlotItem.setData(x, y, symbolBrush=theBrushes, symbol=self.get_symbol(len(x)), symbolPen=theSymbolPens, symbolSize=self.get_data().get_symbolsize(), pen=theBasePen) # symbolPen = None for no outline else: self.thePlotItem.setData([], [], symbolBrush=None) except ValueError: pass
[docs] def get_length(self): """Return number of data to plot""" x = self.get_data().get_plot_data() return len(x)
[docs] def hide(self): """Hides the trace""" self.thePlotItem.clear()
[docs] def show(self): """Shows the trace""" self.signal_must_update.emit()
[docs] def toggle(self, boolean): """Toggle the trace (hide/show)""" if boolean: self.show() else: self.hide()
[docs] def get_data(self): """Get data to plot :class:`~optimeed.visualize.graphs.Graphs.Data`""" return self.theData
[docs] def get_brushes(self, size): """Get actual brushes for the trace (=symbol filling). return a list which maps each points to a symbol brush""" symbolBrush = self.get_base_symbol_brush() if self.get_data().symbol_isfilled() else None theBrushList = [symbolBrush] * size if self.highlight_last: theBrushList[-1] = pg.mkBrush('y') hasBeenModified = self.theBrushesModifier.modify_paintElems(theBrushList) if not hasBeenModified and not self.highlight_last: return symbolBrush return theBrushList
[docs] def set_brush(self, indexPoint, newbrush, update=True): """Set the symbol brush for a specific point: :param indexPoint: Index of the point (in the graph) to modify :param newbrush: either QBrush or tuple (r, g, b) of the new brush :param update: if True, update the trace afterwards. This is slow operation.""" if isinstance(newbrush, tuple): newbrush = pg.mkBrush(newbrush) self.theBrushesModifier.add_modified_paintElem(indexPoint, newbrush) if update: self.signal_must_update.emit()
[docs] def set_symbol(self, indexPoint, newSymbol, update=True): """Set the symbol shape for a specific point: :param indexPoint: Index of the point (in the graph) to modify :param newSymbol: string of the new symbol (e.g.: 'o') :param update: if True, update the trace afterwards. This is slow operation.""" self.theSymbolModifier.add_modified_paintElem(indexPoint, newSymbol) if update: self.signal_must_update.emit()
[docs] def set_brushes(self, list_indexPoint, list_newbrush): """Same as :meth:`~TraceVisual.set_brush` but by taking a list as input""" if not isinstance(list_newbrush, list): list_newbrush = [list_newbrush] * len(list_indexPoint) for i in range(len(list_indexPoint)): self.set_brush(list_indexPoint[i], list_newbrush[i], update=False) self.signal_must_update.emit()
[docs] def reset_brush(self, indexPoint, update=True): """Reset the brush of the point indexpoint""" self.theBrushesModifier.reset_paintElem(indexPoint) if update: self.signal_must_update.emit()
[docs] def reset_all_brushes(self): """Reset all the brushes""" self.theBrushesModifier.reset() self.signal_must_update.emit()
[docs] def reset_symbol(self, indexPoint, update=True): """Reset the symbol shape of the point indexpoint""" self.theSymbolModifier.reset_paintElem(indexPoint) if update: self.signal_must_update.emit()
[docs] def get_symbolPens(self, size): """Get actual symbol pens for the trace (=symbol outline). return a list which maps each points to a symbol pen""" thePenList = [self.get_base_symbol_pen()] * size hasBeenModified = self.theSymbolPensModifier.modify_paintElems(thePenList) if not hasBeenModified: return self.get_base_symbol_pen() return thePenList
[docs] def set_symbolPen(self, indexPoint, newPen, update=True): """Set the symbol shape for a specific point: :param indexPoint: Index of the point (in the graph) to modify :param newPen: QPen item or tuple of the color (r,g,b) :param update: if True, update the trace afterwards. This is slow operation.""" if isinstance(newPen, tuple): newPen = pg.mkPen(newPen) self.theSymbolPensModifier.add_modified_paintElem(indexPoint, newPen) if update: self.signal_must_update.emit()
[docs] def set_symbolPens(self, list_indexPoint, list_newpens): """Same as :meth:`~TraceVisual.set_symbolPen` but by taking a list as input""" for i in range(len(list_indexPoint)): self.set_symbolPen(list_indexPoint[i], list_newpens[i], update=False) self.signal_must_update.emit()
[docs] def reset_symbolPen(self, indexPoint): """Reset the symbol pen of the point indexpoint""" self.theSymbolPensModifier.reset_paintElem(indexPoint) self.signal_must_update.emit()
[docs] def reset_all_symbolPens(self): """Reset all the symbol pens""" self.theSymbolPensModifier.reset() self.signal_must_update.emit()
@staticmethod
[docs] def set_pen_linestyle(thePen, linestyle): """Transform a pen for dashed lines: :param thePen: QPen item :param linestyle: str (e.g.: '.', '.-', '--', ...) """ if linestyle in ['.', ':', '..']: thePen.setDashPattern([0.1, 2]) thePen.setCapStyle(QtCore.Qt.RoundCap) thePen.setWidthF(thePen.width()*1.75) elif linestyle in ['.-', '-.']: thePen.setCapStyle(QtCore.Qt.RoundCap) thePen.setDashPattern([3, 2, 0.1, 2]) thePen.setWidthF(thePen.width()*1.25) elif linestyle in ['-..', '.-.', '..-']: thePen.setDashPattern([0.1, 2, 3, 2, 0.1, 2]) thePen.setWidthF(thePen.width()*1.25) elif linestyle in ['--']: thePen.setDashPattern([2.5, 2]) thePen.setWidthF(thePen.width()*1.1) else: thePen.setStyle(QtCore.Qt.SolidLine)
[docs] def get_point(self, indexPoint): """Return object pyqtgraph.SpotItem""" return self.thePlotItem.scatter.points()[indexPoint]