def __init__(self, x, y, text=None, bbox=None): PlotInfo.__init__(self, "label") self.x = x """ The label's x coordinate """ self.y = y """ The label's y coordinate """ self.text = text """ The text that should be displayed with the label """ self.textX = x self.textY = y self.arrow = None self._marker = Marker() self._labelProperties = LabelProperties() if bbox: self.bbox = dict(bbox) else: self.bbox = None
def setMapStyle(self): layers = self.iface.legendInterface().layers() self.scrc = SymbolCategoryRenderClass( self.makeokdict(self.getTabs(csv=True))) self.labProp = LabelProperties(self.okdict) for layer in layers: layerType = layer.type() if layerType == QgsMapLayer.VectorLayer: node = len(layers) if layer.name() == u'LAYER3-polygon': self.reorderLayers(layer, node) if layer.name() == u'LAYER7-polygon': self.reorderLayers(layer, node - 1) if layer.name() == u'LAYER12-polygon': self.reorderLayers(layer, node - 2) if layer.name() == u'LAYER19-polygon': self.reorderLayers(layer, node - 3) if layer.name() == u'LAYER17-label': self.labProp.makeLabels(layer) self.scrc.CategoryRender(self.style, layer) layer.triggerRepaint()
def __init__(self): self.plots = [] self.title = None """ The plot's title (will be centered above the axes themselves) """ self.xFormatter = None self.yFormatter = None self.yLabel = None """ The label for the plot's y-axis """ self.xLabel = None """ The label for the plot's x-axis """ self._xLabelProperties = LabelProperties() self._yLabelProperties = LabelProperties() self.legend = None self._xLimits = None self._yLimits = None self.twinxLabel = None self.twinxIndex = -1 self.twinxLimits = None self.lineStyles = None self.lineColors = None self.markers = None self.width = None self.height = None self.dpi = 100 self.plotParams = None self.logx = False """ If true, this plot's x-axis will be drawn in log scale. """ self.logy = False """ If true, this plot's y-axis will be drawn in log scale. """ self.loglog = False """ If true, both this plot's axes will be drawn in log scale. """ self.logbase = 10 """ The base of the logarithm used to draw log scale axes. """ self.logbasex = None """ The base of the logarithm used to draw the x-axis. Overrides `logbase`, and only takes effect if logx or loglog are True. """ self.logbasey = None """ The base of the logarithm used to draw the y-axis. Overrides `logbase`, and only takes effect if logy or loglog are True. """ self._grid = Grid() self._grid.visible = False self.insets = [] self.hideTicks = False """ If True, this plot's tick labels are hidden. """ self.titleSize = None """ The size of the text used for plot title. """ self.latex = False self.axesLabelSize = None """ The size of the text used for labeling the x and y axes. """ self.xTickLabelSize = None """ The size of the text used for x-axis tick labels """ self.yTickLabelSize = None """ The size of the text used for y-axis tick labels """ self.titleProperties = LabelProperties() self.tight = False """ If True, this plot is auto-scaled so that axis labels don't get cut off. """ self.allows_tight = True self.projection = None """
class Plot(object): """ Represents a single plot, usually consisting of a single X and Y axis. """ def __init__(self): self.plots = [] self.title = None """ The plot's title (will be centered above the axes themselves) """ self.xFormatter = None self.yFormatter = None self.yLabel = None """ The label for the plot's y-axis """ self.xLabel = None """ The label for the plot's x-axis """ self._xLabelProperties = LabelProperties() self._yLabelProperties = LabelProperties() self.legend = None self._xLimits = None self._yLimits = None self.twinxLabel = None self.twinxIndex = -1 self.twinxLimits = None self.lineStyles = None self.lineColors = None self.markers = None self.width = None self.height = None self.dpi = 100 self.plotParams = None self.logx = False """ If true, this plot's x-axis will be drawn in log scale. """ self.logy = False """ If true, this plot's y-axis will be drawn in log scale. """ self.loglog = False """ If true, both this plot's axes will be drawn in log scale. """ self.logbase = 10 """ The base of the logarithm used to draw log scale axes. """ self.logbasex = None """ The base of the logarithm used to draw the x-axis. Overrides `logbase`, and only takes effect if logx or loglog are True. """ self.logbasey = None """ The base of the logarithm used to draw the y-axis. Overrides `logbase`, and only takes effect if logy or loglog are True. """ self._grid = Grid() self._grid.visible = False self.insets = [] self.hideTicks = False """ If True, this plot's tick labels are hidden. """ self.titleSize = None """ The size of the text used for plot title. """ self.latex = False self.axesLabelSize = None """ The size of the text used for labeling the x and y axes. """ self.xTickLabelSize = None """ The size of the text used for x-axis tick labels """ self.yTickLabelSize = None """ The size of the text used for y-axis tick labels """ self.titleProperties = LabelProperties() self.tight = False """ If True, this plot is auto-scaled so that axis labels don't get cut off. """ self.allows_tight = True self.projection = None """ Defines the projection used when drawing this plot. The only currently supported value other than the standard (no projection) is 'polar'. """ @property def xLabelProperties(self): """ A dictionary of properties that control the appearance of the X axis' axis label. See :ref:`styling-labels` for more information on which properties can be set. """ return self._xLabelProperties @xLabelProperties.setter def xLabelProperties(self, propsobj): self._xLabelProperties.update(propsobj) @property def yLabelProperties(self): """ A dictionary of properties that control the appearance of the Y axis' axis label. See :ref:`styling-labels` for more information on which properties can be set. """ return self._yLabelProperties @yLabelProperties.setter def yLabelProperties(self, propsobj): self._yLabelProperties.update(propsobj) @property def xLimits(self): """ A pair giving the minimum and maximum values visible on the x-axis. """ return self._xLimits @xLimits.setter def xLimits(self, value): if type(value) not in [tuple, list] or len(value) != 2: raise AttributeError("xLimits must be set to a (min, max) tuple") self._xLimits = tuple(value) @property def yLimits(self): """ A pair giving the minimum and maximum values visible on the x-axis. """ return self._yLimits @yLimits.setter def yLimits(self, value): if type(value) not in [tuple, list] or len(value) != 2: raise AttributeError("yLimits must be set to a (min, max) tuple") self._yLimits = value @property def legendLabelSize(self): """ The size of the text in this plot's legend. """ return self.legend.labelSize @legendLabelSize.setter def legendLabelSize(self, size): self.setLegendLabelSize(size) @property def grid(self): """ A boomslang.Grid.Grid that defines the properties of this plot's grid lines. See :ref:`plots-grid-lines` for configuration options. """ return self._grid @grid.setter def grid(self, value): if isinstance(value, bool) and value == True: self._grid.visible = True else: raise AttributeError("Plot.grid cannot be re-assigned") def setTitleProperties(self, **propList): """ Set the properties of the title. See :ref:`styling-labels` for more information about valid properties. """ self.__setProperties(self.titleProperties, propList) def __setProperties(self, propsDict, propList): for (key, val) in propList.items(): propsDict[key] = val def __str__(self): return str(self.__dict__) def setTitleSize(self, size): self.titleSize = size def setAxesLabelSize(self, size): self.axesLabelSize = size def setXTickLabelSize(self, size): self.xTickLabelSize = size def setYTickLabelSize(self, size): self.yTickLabelSize = size def setLegendLabelSize(self, size): if self.legend is None: self.legend = Legend() self.legend.labelSize = size def split(self, pieces): """ Split this plot into `pieces` separate plots, each showing a different portion of the x-axis """ splitPlots = [copy.deepcopy(self) for i in xrange(pieces)] for plot in splitPlots: plot.plots = [] for plot in self.plots: elements = plot.split(pieces) for i in xrange(pieces): splitPlots[i].add(elements[i]) splitPlots[i].setXLimits(min(elements[i].xValues), max(elements[i].xValues)) return splitPlots def getDimensions(self): """ Get the dimensions of this plot. """ if self.width is None: (self.width, self.height) = getGoldenRatioDimensions(8.0) elif self.height is None: (goldWidth, goldHeight) = getGoldenRatioDimensions(self.width) self.height = goldHeight return (self.width, self.height) def hideTickLabels(self): self.hideTicks = True def setDimensions(self, width=None, height=None, dpi=100): """ Set the dimensions for this plot to `width` x `height` """ self.width = width self.height = height self.dpi = dpi def add(self, plottableObject): """ Add a plottable object (a Line, Bar, etc.) to this plot, causing it to be drawn when the plot is drawn. """ if not issubclass(plottableObject.__class__, PlotInfo): raise BoomslangPlotConfigurationException("All objects added to a Plot must be a subclass of PlotInfo") self.plots.append(plottableObject) def addInset(self, plot, **kwargs): """ Add `plot` (a Plot object) as an inset to this plot object. Valid arguments are as follows: ============ ==================================================================================================================== Argument Description ============ ==================================================================================================================== ``width`` The width of the inset as a fraction of the size of the parent plot ``height`` The height of the inset as a fraction of the size of the parent plot ``location`` The location of the inset. See :ref:`plots-locations` for valid locations. ``padding`` The amount of padding between the edge of the parent plot and the inset as a fraction of the size of the parent plot ============ ==================================================================================================================== """ inset = Inset(plot, **kwargs) self.insets.append(inset) def addLineStyle(self, style): """ Add a line style to the list of line styles through which the plot will cycle when drawing lines. If no line styles are specified, the plot will default to the line style specified in the Line objects themselves. Note that, when drawing lines, all line styles for a given color are cycled through before another color is used. """ if self.lineStyles is None: self.lineStyles = [] currStyle = LineStyle() currStyle.style = style self.lineStyles.append(currStyle) def addLineColor(self, color): """ Add a line color to the list of line colors through which the plot will cycle when drawing lines. If no line colors are specified, the line colors specified by the Line objects themselves will be used. Note that, when drawing lines, all line styles for a given color are cycled through before another color is used. """ if self.lineColors is None: self.lineColors = [] self.lineColors.append(color) def addMarker(self, marker): """ Add a marker style to the list of marker styles through which the plot will cycle when drawing lines. If no markers are specified, the markers specified by the Line objects themselves will be used. Note that, when drawing lines, all line style/color combinations are cycled through with a given marker before a new marker is chosen. """ if self.markers is None: self.markers = [] currMarker = Marker() currMarker.marker = marker self.markers.append(currMarker) def getNumPlots(self): # Get the number of plottable objects currently registered for this # plot. return len(self.plots) def setTwinX(self, label, index, yMin=None, yMax=None): """ Make the plot use a secondary y-axis with the provided label. All registered plottable objects at or after the given index will use this second axis. """ self.twinxLabel = label self.twinxIndex = index if yMin is not None and yMax is not None: self.twinxLimits = (yMin, yMax) def setYFormatter(self, formatter): """ Set the y-axis formatter used by this plot to the given function. """ self.yFormatter = pylab.FuncFormatter(formatter) def setXFormatter(self, formatter): """ Set the x-axis formatter used by this plot to the given function. """ self.xFormatter = pylab.FuncFormatter(formatter) def setXLabel(self, xLabel): self.xLabel = xLabel def setYLabel(self, yLabel): self.yLabel = yLabel def setXLimits(self, minX, maxX): self.xLimits = (minX, maxX) def setYLimits(self, minY, maxY): self.yLimits = (minY, maxY) def hasFigLegend( self, columns=1, location="best", scatterPoints=3, draw_frame=True, bbox_to_anchor=None, labelSize=None, title=None, labelOrdering=None, leftToRight=False, ): """ Declare that the figure has a legend with a given number of columns and location. """ self.legend = Legend( columns=columns, scatterPoints=scatterPoints, drawFrame=draw_frame, location=location, figLegend=True, labelSize=labelSize, bboxToAnchor=bbox_to_anchor, title=title, labelOrdering=labelOrdering, leftToRight=leftToRight, ) def hasLegend( self, columns=1, location="best", scatterPoints=3, draw_frame=True, bbox_to_anchor=None, labelSize=None, title=None, labelOrdering=None, leftToRight=False, ): """ Declare that the plot has a legend with a given number of columns and location. """ self.legend = Legend( columns=columns, scatterPoints=scatterPoints, drawFrame=draw_frame, location=location, figLegend=False, labelSize=labelSize, bboxToAnchor=bbox_to_anchor, title=title, labelOrdering=labelOrdering, leftToRight=leftToRight, ) def setTitle(self, title): self.title = title def __cmp__(self, other): if not isinstance(other, Plot): raise ValueError("Can't compare a Plot with a non-Plot") return cmp(self.title, other.title) def __setupLayout(self): layout = PlotLayout() (width, height) = self.getDimensions() layout.setPlotDimensions(width, height, dpi=self.dpi) if self.plotParams is not None: layout.setPlotParameters(**self.plotParams) if self.titleSize is not None: layout.setTitleSize(self.titleSize) if self.latex == True: layout.useLatexLabels() if self.axesLabelSize is not None: layout.setAxesLabelSize(self.axesLabelSize) if self.xTickLabelSize is not None: layout.setXTickLabelSize(self.xTickLabelSize) if self.yTickLabelSize is not None: layout.setYTickLabelSize(self.yTickLabelSize) layout.addPlot(self) return layout def useLatexLabels(self): self.latex = True def plot(self): """ Draw this plot to a matplotlib canvas. """ layout = self.__setupLayout() layout.plot() def plot_fig(self): layout = self.__setupLayout() return layout._doPlot() def setPlotParameters(self, **kwdict): """ Set the margins of this plot. See `matplotlib's SubplotParams documentation <http://matplotlib.sourceforge.net/api/figure_api.html#matplotlib.figure.SubplotParams>`_ for more details. It is recommended that you set :py:attr:`boomslang.Plot.Plot.tight` to True instead of setting these parameters. """ self.plotParams = dict(kwdict) if "left" not in self.plotParams: self.plotParams["left"] = 0.12 if "bottom" not in self.plotParams: self.plotParams["bottom"] = 0.10 if "right" not in self.plotParams: self.plotParams["right"] = 0.90 if "top" not in self.plotParams: self.plotParams["top"] = 0.90 if "wspace" not in self.plotParams: self.plotParams["wspace"] = 0.20 if "hspace" not in self.plotParams: self.plotParams["hspace"] = 0.20 def save(self, filename, **kwargs): """ Save this plot to a file. """ layout = self.__setupLayout() layout.save(filename, **kwargs) def subplot(self, fig, row, column, position, projection): kwdict = {} if projection is not None: kwdict["projection"] = projection ax = fig.add_subplot(row, column, position, **kwdict) return self.drawPlot(fig, ax) def drawPlot(self, fig, ax): """ Used by PlotLayout to plot the graph at a given location in the layout. """ ax2 = None if self.tight and self.allows_tight: ax.autoscale_view(tight=True) for inset in self.insets: inset.draw(fig, ax) if self.hideTicks == True: for xtl in ax.get_xticklabels(): xtl.set_visible(False) for xtick in ax.get_xticklines(): xtick.set_visible(False) for ytl in ax.get_yticklabels(): ytl.set_visible(False) for ytick in ax.get_yticklines(): ytick.set_visible(False) if self.grid.visible == True: self.grid.draw(fig, ax) if self.loglog or self.logx: myBase = None if self.logbasex is not None: myBase = self.logbasex else: myBase = self.logbase ax.set_xscale("log", basex=myBase) if self.loglog or self.logy: myBase = None if self.logbasey is not None: myBase = self.logbasey else: myBase = self.logbase ax.set_yscale("log", basey=myBase) if self.twinxIndex > 0: ax2 = ax.twinx() ax2.set_ylabel(self.twinxLabel) if self.twinxLimits is not None: ax2.set_ylim(ymin=self.twinxLimits[0], ymax=self.twinxLimits[1]) plotHandles = [] plotLabels = [] if self.xFormatter is not None: ax.xaxis.set_major_formatter(self.xFormatter) if self.yFormatter is not None: ax.yaxis.set_major_formatter(self.yFormatter) if self.title is not None: ax.set_title(self.title, **self.titleProperties) i = 0 myAxis = ax hasLineStyles = self.lineStyles is not None hasColors = self.lineColors is not None hasMarkers = self.markers is not None numLineStyles = 1 numColors = 1 numMarkers = 1 if hasLineStyles: numLineStyles = len(self.lineStyles) if hasColors: numColors = len(self.lineColors) if hasMarkers: numMarkers = len(self.markers) plotIndex = 0 for plotInfo in self.plots: if self.twinxIndex >= 0 and i == self.twinxIndex: myAxis = ax2 myLineStyle = None myColor = None myMarker = None # cycle through styles first, then markers, then colors colorIndex = (plotIndex / (numMarkers * numLineStyles)) % numColors markerIndex = int(plotIndex / numLineStyles) % numMarkers lineStyleIndex = plotIndex % numLineStyles if hasLineStyles: myLineStyle = self.lineStyles[lineStyleIndex].style if hasColors: myColor = self.lineColors[colorIndex] if hasMarkers: myMarker = self.markers[markerIndex].marker plotIndex += 1 if myLineStyle is not None: plotInfo.lineStyle = myLineStyle if myMarker is not None: plotInfo.marker = myMarker if myColor is not None: plotInfo.color = myColor plotInfo._preDraw() (currPlotHandles, currPlotLabels) = plotInfo.draw(fig, myAxis) labelIndices = [x for x in range(len(currPlotLabels)) if currPlotLabels[x] is not None] if len(labelIndices) > 0: plotHandles.extend([currPlotHandles[x] for x in labelIndices]) plotLabels.extend([currPlotLabels[x] for x in labelIndices]) if plotInfo.xLimits is not None: if self.xLimits is None: self.xLimits = plotInfo.xLimits else: (myXMin, myXMax) = plotInfo.xLimits self.xLimits = (min(self.xLimits[0], myXMin), max(self.xLimits[1], myXMax)) i += 1 if self.xLimits is not None: ax.set_xlim(xmin=self.xLimits[0], xmax=self.xLimits[1]) if self.yLimits is not None: ax.set_ylim(ymin=self.yLimits[0], ymax=self.yLimits[1]) if self.xLabel is not None: ax.set_xlabel(self.xLabel, **self.xLabelProperties) if self.yLabel is not None: ax.set_ylabel(self.yLabel, **self.yLabelProperties) if self.legend is not None: if len(plotHandles) == 0: print >>sys.stderr, "ERROR: Plot wanted to draw a legend, " "but none of its elements have labels" sys.exit(1) if self.twinxIndex > 0: legendAxis = ax2 else: legendAxis = ax self.legend.draw(fig, legendAxis, plotHandles, plotLabels) return (plotHandles, plotLabels)
class ViewShpForRscCode: def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface # initialize plugin directory dir = os.path.dirname(__file__) self.plugin_dir = dir.decode('cp1251') self.labProp = None self.fed = None self.scrc = None self.codename = None self.model = None self.okdict = {} self.root = QgsProject.instance().layerTreeRoot() self.style = QgsStyleV2().defaultStyle() self.dlg = ViewShpForRscCodeDialog() self.editRend = EditRenderDialog() self.editRend.listWgt.doubleClicked.connect(self.editSymbol) self.editRend.closeButton.clicked.connect(self.closeEditRend) self.editRend.csvExpButton.clicked.connect(self.expCSV) self.editRend.xmlExpButton.clicked.connect(self.expXML) self.editRend.saveButton.clicked.connect( functools.partial(self.expCSV, True)) self.editRend.delButton.clicked.connect(self.removeCodeItem) self.editRend.addButton.clicked.connect(self.addCodeItem) self.dlg.runButton.clicked.connect(self.setMapStyle) self.dlg.closeButton.clicked.connect(self.closeDial) self.dlg.importXmlButton.clicked.connect(self.importXML) self.dlg.editRenderButton.clicked.connect(self.editRender) self.dlg.delTabButton.clicked.connect(self.removeTab) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join(self.plugin_dir, 'i18n', 'MapStyling_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&ViewShpForRscCodePlugin') self.toolbar = self.iface.addToolBar(u'MapStyling') self.toolbar.setObjectName(u'MapStyling') def tr(self, message): return QCoreApplication.translate('MapStyling', message) def add_action(self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ # Create the dialog (after translation) and keep reference icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.toolbar.addAction(action) if add_to_menu: self.iface.addPluginToMenu(self.menu, action) self.actions.append(action) return action def GetModelForCombobox(self, list): model = QtGui.QStandardItemModel(1, 1) n = 0 for l in list: item_str = l.rpartition('\\')[2] item = QtGui.QStandardItem(item_str) model.setItem(n, 0, item) n = n + 1 return model def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/ViewShpForRscCode/icon.png' self.add_action(icon_path, text=self.tr('ViewShpForRscCode'), callback=self.run, parent=self.iface.mainWindow()) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu(self.tr(u'&MViewShpForRscCodePlugin'), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar QgsExpression.unregisterFunction("fontProperty") def run(self): """Run method that performs all the real work""" # show the dialog #self.dlg.show() # Run the dialog event loop self.fillCombos() result = self.dlg.exec_() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. pass def fillCombos(self): xml = glob.glob(self.plugin_dir + '/svg/*.xml') tab = glob.glob(self.plugin_dir + '/tab/*.csv') self.dlg.scaleComboBox.setModel(self.GetModelForCombobox(xml)) self.dlg.tabComboBox.setModel(self.GetModelForCombobox(tab)) def reorderLayers(self, layer, node): lyr = self.root.findLayer(layer.id()) lyrClone = lyr.clone() parent = lyr.parent() parent.insertChildNode(node, lyrClone) parent.removeChildNode(lyr) def setMapStyle(self): layers = self.iface.legendInterface().layers() self.scrc = SymbolCategoryRenderClass( self.makeokdict(self.getTabs(csv=True))) self.labProp = LabelProperties(self.okdict) for layer in layers: layerType = layer.type() if layerType == QgsMapLayer.VectorLayer: node = len(layers) if layer.name() == u'LAYER3-polygon': self.reorderLayers(layer, node) if layer.name() == u'LAYER7-polygon': self.reorderLayers(layer, node - 1) if layer.name() == u'LAYER12-polygon': self.reorderLayers(layer, node - 2) if layer.name() == u'LAYER19-polygon': self.reorderLayers(layer, node - 3) if layer.name() == u'LAYER17-label': self.labProp.makeLabels(layer) self.scrc.CategoryRender(self.style, layer) layer.triggerRepaint() def getTabs(self, csv=None, lbl=None): if csv: tabName = self.dlg.tabComboBox.currentText() csv_path = os.path.join(self.plugin_dir, 'tab/' + tabName) return csv_path def makeokdict(self, csv_path): with open(csv_path) as f: reader = csv.reader(f, delimiter=';') for row in reader: if 'T' in row[0]: self.okdict[row[0]] = [ row[1].decode('utf-8'), row[2].decode('utf-8').split(',') ] else: self.okdict[row[0]] = [ row[1].decode('utf-8'), row[2].decode('utf-8') ] return self.okdict def importXML(self): srcStyle = QgsStyleV2() dstStyle = self.style symLib = self.dlg.scaleComboBox.currentText() svg_dst = QgsApplication.svgPaths()[0] spath = self.plugin_dir + '/svg/' copylist = [] if not os.path.isfile(spath): for path, dirs, filenames in os.walk(spath): for directory in dirs: dir_path = os.path.join(svg_dst, directory) if not os.path.exists(dir_path): os.makedirs(os.path.join(dir_path)) for sfile in filenames: s_file = os.path.join(path, sfile) d_file = os.path.join(path.replace(spath, svg_dst), sfile) copylist.append([s_file, d_file]) for c in copylist: shutil.copy(c[0], c[1]) xml_path = spath + symLib srcStyle.importXML(xml_path) groupName = symLib.replace(".xml", "") if groupName not in dstStyle.groupNames(): dstStyle.addGroup(groupName) groupid = dstStyle.groupId(groupName) for sym in srcStyle.symbolNames(): symbol = srcStyle.symbol(sym) dstStyle.addSymbol(sym, symbol) dstStyle.saveSymbol(sym, symbol, groupid, []) QtGui.QMessageBox.information(QWidget(), u'Информация', u'Импорт завершен', QtGui.QMessageBox.Ok) return def editRender(self): tab = self.dlg.tabComboBox.currentText() self.editRend.listWgt.setIconSize(QSize(32, 32)) self.editRend.listWgt.setEditTriggers( QtGui.QAbstractItemView.SelectedClicked) self.model = QStandardItemModel() self.model.setColumnCount(3) self.model.setHorizontalHeaderItem(0, QStandardItem(u'Код')) self.model.setHorizontalHeaderItem(1, QStandardItem(u'Название')) self.model.setHorizontalHeaderItem(2, QStandardItem(u'Знак')) self.editRend.listWgt.setModel(self.model) self.editRend.listWgt.setSelectionBehavior(QTableView.SelectRows) self.codename = {} with open(self.plugin_dir + '/tab/' + tab) as f: reader = csv.reader(f, delimiter=';') for row in reader: itemCode = QStandardItem(row[0]) itemName = QStandardItem(row[1].decode('utf-8')) symName = row[2].decode('utf-8') if symName == 'None': if 'L' in itemCode.text(): symName = 'NoneStyleLine' if 'P' in itemCode.text(): symName = 'NoneStyleMark' if 'S' in itemCode.text(): symName = 'NoneStylePoly' if 'V' in itemCode.text(): symName = 'NoneStyleLine' itemSymb = QStandardItem(symName) symbol = self.style.symbol(symName) if symbol: itemSymb = QStandardItem(symName) icon = QgsSymbolLayerV2Utils.symbolPreviewIcon( symbol, self.editRend.listWgt.iconSize()) itemSymb.setIcon(icon) self.model.appendRow([itemCode, itemName, itemSymb]) self.codename[itemCode.text()] = symName self.editRend.listWgt.resizeRowsToContents() self.editRend.listWgt.setColumnWidth(2, 125) self.editRend.listWgt.setColumnWidth(1, 250) self.editRend.exec_() def editSymbol(self): row = self.editRend.listWgt.selectionModel().currentIndex().row() code = self.model.item(row, 0).text() name = self.model.item(row, 2).text() if name == 'None': t = QInputDialog.getItem( QWidget(), u'Создание условного знака', u'Укажите тип объекта', [u'Точка', u'Линия', u'Полигон', u'Текст'], editable=False) if t[1]: if t[0] == u'Точка': name = 'NoneStyleMark' if t[0] == u'Линия': name = 'NoneStyleLine' if t[0] == u'Полигон': name = 'NoneStylePoly' if t[0] == u'Текст': name = None else: return if 'T' in code: fontProps = self.fontDialog(name) if fontProps: item = QStandardItem(','.join(fontProps)) self.model.setItem(row, 2, item) return symbol = self.style.symbol(name) if not symbol: return d = QgsSymbolV2SelectorDialog(symbol, self.style, None) if d.exec_() == 0: return if 'None' in name: name = '' newName = QInputDialog.getText(QWidget(), u"Имя условного знака", u"Введите имя условного знака:", text=name) if newName[1]: name = newName[0] if not newName[1]: return self.style.addSymbol(name, symbol, True) itemSymb = QStandardItem(name) icon = QgsSymbolLayerV2Utils.symbolPreviewIcon( symbol, self.editRend.listWgt.iconSize()) itemSymb.setIcon(icon) self.model.setItem(row, 2, itemSymb) def fontDialog(self, name=False): fsc = None if name: fsc = name.split(',') self.fed = fontEditDialog(fsc) return self.fed.showDial() def removeTab(self): tab = self.dlg.tabComboBox.currentText() if tab == 'codeNameTab_100k.csv': QtGui.QMessageBox.information(QWidget(), u'Информация', u'Невозможно удалить этот файл', QtGui.QMessageBox.Ok) return tpath = self.plugin_dir + '/tab/' + tab os.remove(tpath) self.fillCombos() def closeDial(self): self.dlg.close() def closeEditRend(self): self.editRend.close() self.fillCombos() def expXML(self): QgsStyleV2ManagerDialog(self.style).exportItems() def expCSV(self, save=False): if not save: nameInput = QInputDialog.getText(QWidget(), u"Название таблицы", u"Введите название таблицы") if nameInput[1]: name = nameInput[0] else: return if save: name = self.dlg.tabComboBox.currentText().replace('.csv', '') with open(self.plugin_dir + '/tab/' + name + '.csv', 'wb') as fout: writer = UnicodeWriter(fout, delimiter=';') for r in range(self.model.rowCount()): itemCode = self.model.item(r, 0).text() itemName = self.model.item(r, 1).text() itemSymb = self.model.item(r, 2).text() writer.writerow([itemCode, itemName, itemSymb]) def removeCodeItem(self): indexList = [] for r in self.editRend.listWgt.selectionModel().selectedRows(): row = r.row() indexList.append(row) for i in indexList[::-1]: self.model.removeRows(i, 1) def addCodeItem(self): itemCode = QStandardItem('None') itemName = QStandardItem('None') itemSymb = QStandardItem('None') itemList = [itemCode, itemName, itemSymb] selection = self.editRend.listWgt.selectionModel().selectedRows() if selection: self.model.insertRow(selection[-1::][0].row() + 1, itemList) else: self.model.appendRow(itemList)
def __init__(self, plotType, xValues = None, yValues = None, xTickLabels = None, yTickLabels = None, xTickLabelPoints = None, yTickLabelPoints = None, xTickLabelProperties = None, yTickLabelProperties = None, label = None, yMins = None, yMaxes = None, yErrors = None, autosort = True, xLimits = None, errorBarColor = None, errorBarLineWidth = None, errorBarCapsize = None, picker=None): if xValues is None: xValues = [] if yValues is None: yValues = [] if xTickLabels is None: xTickLabels = [] if yTickLabels is None: yTickLabels = [] if xTickLabelPoints is None: xTickLabelPoints = [] if yTickLabelPoints is None: yTickLabelPoints = [] if yMins is None: yMins = [] if yMaxes is None: yMaxes = [] if yErrors is None: yErrors = [] self.plotType = plotType """ Names the type of plot element """ self.xValues = xValues """ An array of x-axis values for the plot element """ self.yValues = yValues """ An array of y-axis values for the plot elements """ self.xTickLabels = xTickLabels """ A list of labels that should be drawn on the x-axis """ self.yTickLabels = yTickLabels """ A list of labels that should be drawn on the y-axis """ self.xTickLabelPoints = xTickLabelPoints """ The locations on the x-axis where the labels in :attr:`xTickLabels` should be drawn """ self.yTickLabelPoints = yTickLabelPoints """ The locations on the x-axis where the labels in :attr:`xTickLabels` should be drawn """ self._xTickLabelProperties = LabelProperties() self._yTickLabelProperties = LabelProperties() if xTickLabelProperties is not None: self.xTickLabelProperties = xTickLabelProperties if yTickLabelProperties is not None: self.yTickLabelProperties = yTickLabelProperties self.label = label """ A string used to label this plot element in a legend """ self.yMins = yMins """ For asymmetric error bars, a list of locations for the bottoms of this plot element's error bars """ self.yMaxes = yMaxes """ For asymmetric error bars, a list of locations for the tops of this plot element's error bars """ self.yErrors = yErrors """ For symmetric error bars, a list of error bar widths for this plot element's error bars """ self.autosort = autosort """ If true, x/y pairs in :py:attr:`xValues` and :py:attr:`yValues` are sorted by x value before the plot is rendered """ self.xLimits = xLimits self.errorBarColor = errorBarColor self.errorBarLineWidth = errorBarLineWidth self.errorBarCapsize = errorBarCapsize self.picker = picker
class PlotInfo(object): def __init__(self, plotType, xValues = None, yValues = None, xTickLabels = None, yTickLabels = None, xTickLabelPoints = None, yTickLabelPoints = None, xTickLabelProperties = None, yTickLabelProperties = None, label = None, yMins = None, yMaxes = None, yErrors = None, autosort = True, xLimits = None, errorBarColor = None, errorBarLineWidth = None, errorBarCapsize = None, picker=None): if xValues is None: xValues = [] if yValues is None: yValues = [] if xTickLabels is None: xTickLabels = [] if yTickLabels is None: yTickLabels = [] if xTickLabelPoints is None: xTickLabelPoints = [] if yTickLabelPoints is None: yTickLabelPoints = [] if yMins is None: yMins = [] if yMaxes is None: yMaxes = [] if yErrors is None: yErrors = [] self.plotType = plotType """ Names the type of plot element """ self.xValues = xValues """ An array of x-axis values for the plot element """ self.yValues = yValues """ An array of y-axis values for the plot elements """ self.xTickLabels = xTickLabels """ A list of labels that should be drawn on the x-axis """ self.yTickLabels = yTickLabels """ A list of labels that should be drawn on the y-axis """ self.xTickLabelPoints = xTickLabelPoints """ The locations on the x-axis where the labels in :attr:`xTickLabels` should be drawn """ self.yTickLabelPoints = yTickLabelPoints """ The locations on the x-axis where the labels in :attr:`xTickLabels` should be drawn """ self._xTickLabelProperties = LabelProperties() self._yTickLabelProperties = LabelProperties() if xTickLabelProperties is not None: self.xTickLabelProperties = xTickLabelProperties if yTickLabelProperties is not None: self.yTickLabelProperties = yTickLabelProperties self.label = label """ A string used to label this plot element in a legend """ self.yMins = yMins """ For asymmetric error bars, a list of locations for the bottoms of this plot element's error bars """ self.yMaxes = yMaxes """ For asymmetric error bars, a list of locations for the tops of this plot element's error bars """ self.yErrors = yErrors """ For symmetric error bars, a list of error bar widths for this plot element's error bars """ self.autosort = autosort """ If true, x/y pairs in :py:attr:`xValues` and :py:attr:`yValues` are sorted by x value before the plot is rendered """ self.xLimits = xLimits self.errorBarColor = errorBarColor self.errorBarLineWidth = errorBarLineWidth self.errorBarCapsize = errorBarCapsize self.picker = picker @property def xTickLabelProperties(self): """ A dictionary of properties that control the appearance of the X axis' tick labels. See :ref:`styling-labels` for more information on which properties can be set. """ return self._xTickLabelProperties @xTickLabelProperties.setter def xTickLabelProperties(self, **props): self._xTickLabelProperties.update(props) @xTickLabelProperties.setter def xTickLabelProperties(self, propsobj): self._xTickLabelProperties.update(propsobj) @property def yTickLabelProperties(self): """ A dictionary of properties that control the appearance of the Y axis' tick labels. See :ref:`styling-labels` for more information on which properties can be set. """ return self._yTickLabelProperties @yTickLabelProperties.setter def yTickLabelProperties(self, props): self._yTickLabelProperties.update(props) def __str__(self): return str(self.__dict__) def _preDraw(self): """ The _preDraw function is called on all plot elements before drawing occurs. This allows various fields to be set in a structured way prior to actual drawing. """ pass def setXTickLabelProperties(self, **propList): # Deprecated: use xTickLabelProperties field instead self._xTickLabelProperties.update(propList) def setYTickLabelProperties(self, **propList): # Deprecated: use yTickLabelProperties field instead self._yTickLabelProperties.update(propList) def split(self, pieces): """ Split this plot element into `pieces` separate plot elements, each of which is responsible for a disjoint range of the original plot element's x-axis. This is useful for situations where a plot element cannot fit comfortably in a single plot. """ elements = [] numXVals = len(self.xValues) valChunkSize = numXVals / pieces valChunkRemainder = numXVals % pieces for i in xrange(pieces): element = copy.deepcopy(self) if i < pieces - 1 or valChunkRemainder == 0: element.xValues = self.xValues[i * valChunkSize:(i+1) * valChunkSize] element.yValues = self.yValues[i * valChunkSize:(i+1) * valChunkSize] else: element.xValues = self.xValues[i * valChunkSize:] element.yValues = self.yValues[i * valChunkSize:] elements.append(element) return elements def getAttributes(self): """ Get the attributes dictionary used to style the plot element. Extending this method allows plot elements to inherit attributes. """ kwdict = {} if self.picker is not None: kwdict['picker'] = self.picker return kwdict def draw(self, fig, axis, transform=None): """ The base method for drawing a plot element on the axis `axis` within the figure `fig`. Other plot elements should override this method, but should also be sure to call this method before doing any element-specific processing. """ if len(self.xValues) > 0 and self.autosort: # This is a total kludge --AR sortAsymmetricErrorBars = len(self.yMins) > 0 or \ len(self.yMaxes) > 0 sortSymmetricErrorBars = len(self.yErrors) > 0 if sortAsymmetricErrorBars: if len(self.yMins) != len(self.yValues): warnings.warn("You don't have an error bar for every " "point, some points will be truncated") zipped = zip(self.xValues, self.yValues, self.yMins, self.yMaxes) zipped.sort() self.xValues, self.yValues, self.yMins, self.yMaxes \ = zip(*zipped) elif sortSymmetricErrorBars: if len(self.yErrors) != len(self.yValues): warnings.warn("You don't have an error bar for every " "point, some points will be truncated") zipped = zip(self.xValues, self.yValues, self.yErrors) zipped.sort() self.xValues, self.yValues, self.yErrors = zip(*zipped) else: zipped = zip(self.xValues, self.yValues) zipped.sort() self.xValues, self.yValues = zip(*zipped) if len(self.xTickLabels) > 0: if len(self.xTickLabelPoints) == 0: axis.set_xticks(self.xValues[0:len(self.xTickLabels)]) else: axis.set_xticks(self.xTickLabelPoints) axis.set_xticklabels(self.xTickLabels, **self.xTickLabelProperties) if len(self.yTickLabels) > 0: if len(self.yTickLabelPoints) == 0: axis.set_yticks(self.yValues[0:len(self.yTickLabels)]) else: axis.set_yticks(self.yTickLabelPoints) axis.set_yticklabels(self.yTickLabels, **self.yTickLabelProperties) self.drawErrorBars(axis) def drawErrorBars(self, axis, transform=None): """ Draw error bars for the plot element using the plot element's `yMins`/`yMaxes` or `yErrors`. If `yMins` or `yMaxes` have non-zero length, they are used to draw error bars that can be asymmetric. Otherwise, `yErrors` are used to draw symmetric error bars. If some transform should be applied to the error bars, it is provided by the caller with the `transform` parameter. """ errorBarKeywords = {} if self.errorBarColor is not None: errorBarKeywords["ecolor"] = self.errorBarColor elif hasattr(self, "color"): errorBarKeywords["ecolor"] = self.color if self.errorBarCapsize is not None: errorBarKeywords["capsize"] = self.errorBarCapsize if self.errorBarLineWidth is not None: errorBarKeywords["linewidth"] = self.errorBarLineWidth if hasattr(self, "lineStyle"): errorBarKeywords["linestyle"] = self.lineStyle if transform: errorBarKeywords['transform'] = transform + axis.transData errorBarKeywords["fmt"] = None if len(self.yMins) > 0 and len(self.yMaxes) > 0: numYVals = len(self.yValues) yMin = [self.yValues[i] - self.yMins[i] for i in xrange(numYVals)] yMax = [self.yMaxes[i] - self.yValues[i] for i in xrange(numYVals)] errorBarKeywords["yerr"] = [yMin, yMax] axis.errorbar(self.xValues, self.yValues, **errorBarKeywords) elif len(self.yErrors) > 0: errorBarKeywords["yerr"] = self.yErrors axis.errorbar(self.xValues, self.yValues, **errorBarKeywords)
def __init__(self, plotType, xValues = None, yValues = None, xTickLabels = None, yTickLabels = None, xTickLabelPoints = None, yTickLabelPoints = None, xTickLabelProperties = None, yTickLabelProperties = None, label = None, yMins = None, yMaxes = None, yErrors = None, autosort = True, xLimits = None, errorBarColor = None, errorBarLineWidth = None, errorBarCapsize = None, picker=None): if xValues is None: xValues = [] if yValues is None: yValues = [] if xTickLabels is None: xTickLabels = [] if yTickLabels is None: yTickLabels = [] if xTickLabelPoints is None: xTickLabelPoints = [] if yTickLabelPoints is None: yTickLabelPoints = [] # if xTickLabelProperties is None: # xTickLabelProperties = LabelProperties() # if yTickLabelProperties is None: # yTickLabelProperties = LabelProperties() if yMins is None: yMins = [] if yMaxes is None: yMaxes = [] if yErrors is None: yErrors = [] self.plotType = plotType self.xValues = xValues self.yValues = yValues self.xTickLabels = xTickLabels self.yTickLabels = yTickLabels self.xTickLabelPoints = xTickLabelPoints self.yTickLabelPoints = yTickLabelPoints self._xTickLabelProperties = LabelProperties() self._yTickLabelProperties = LabelProperties() if xTickLabelProperties is not None: self.xTickLabelProperties = xTickLabelProperties if yTickLabelProperties is not None: self.yTickLabelProperties = yTickLabelProperties self.label = label self.yMins = yMins self.yMaxes = yMaxes self.yErrors = yErrors self.autosort = autosort self.xLimits = xLimits self.errorBarColor = errorBarColor self.errorBarLineWidth = errorBarLineWidth self.errorBarCapsize = errorBarCapsize self.picker = picker
class PlotInfo(object): def __init__(self, plotType, xValues = None, yValues = None, xTickLabels = None, yTickLabels = None, xTickLabelPoints = None, yTickLabelPoints = None, xTickLabelProperties = None, yTickLabelProperties = None, label = None, yMins = None, yMaxes = None, yErrors = None, autosort = True, xLimits = None, errorBarColor = None, errorBarLineWidth = None, errorBarCapsize = None, picker=None): if xValues is None: xValues = [] if yValues is None: yValues = [] if xTickLabels is None: xTickLabels = [] if yTickLabels is None: yTickLabels = [] if xTickLabelPoints is None: xTickLabelPoints = [] if yTickLabelPoints is None: yTickLabelPoints = [] # if xTickLabelProperties is None: # xTickLabelProperties = LabelProperties() # if yTickLabelProperties is None: # yTickLabelProperties = LabelProperties() if yMins is None: yMins = [] if yMaxes is None: yMaxes = [] if yErrors is None: yErrors = [] self.plotType = plotType self.xValues = xValues self.yValues = yValues self.xTickLabels = xTickLabels self.yTickLabels = yTickLabels self.xTickLabelPoints = xTickLabelPoints self.yTickLabelPoints = yTickLabelPoints self._xTickLabelProperties = LabelProperties() self._yTickLabelProperties = LabelProperties() if xTickLabelProperties is not None: self.xTickLabelProperties = xTickLabelProperties if yTickLabelProperties is not None: self.yTickLabelProperties = yTickLabelProperties self.label = label self.yMins = yMins self.yMaxes = yMaxes self.yErrors = yErrors self.autosort = autosort self.xLimits = xLimits self.errorBarColor = errorBarColor self.errorBarLineWidth = errorBarLineWidth self.errorBarCapsize = errorBarCapsize self.picker = picker @property def xTickLabelProperties(self): """ A dictionary of properties that control the appearance of the X axis' tick labels """ return self._xTickLabelProperties @xTickLabelProperties.setter def xTickLabelProperties(self, **props): self._xTickLabelProperties.update(props) @xTickLabelProperties.setter def xTickLabelProperties(self, propsobj): self._xTickLabelProperties.update(propsobj) @property def yTickLabelProperties(self): """ A dictionary of properties that control the appearance of the X axis' tick labels """ return self._yTickLabelProperties @yTickLabelProperties.setter def yTickLabelProperties(self, props): self._yTickLabelProperties.update(props) def __str__(self): return str(self.__dict__) def _preDraw(self): """ The _preDraw function is called on all plot elements before drawing occurs. This allows various fields to be set in a structured way prior to actual drawing. """ pass def setXTickLabelProperties(self, **propList): self._xTickLabelProperties.update(propList) def setYTickLabelProperties(self, **propList): self._yTickLabelProperties.update(propList) def split(self, pieces): elements = [] numXVals = len(self.xValues) valChunkSize = numXVals / pieces valChunkRemainder = numXVals % pieces for i in xrange(pieces): element = copy.deepcopy(self) if i < pieces - 1 or valChunkRemainder == 0: element.xValues = self.xValues[i * valChunkSize:(i+1) * valChunkSize] element.yValues = self.yValues[i * valChunkSize:(i+1) * valChunkSize] else: element.xValues = self.xValues[i * valChunkSize:] element.yValues = self.yValues[i * valChunkSize:] elements.append(element) return elements def getAttributes(self): kwdict = {} if self.picker is not None: kwdict['picker'] = self.picker return kwdict def draw(self, fig, axis): if len(self.xValues) > 0 and self.autosort: # This is a total kludge --AR sortAsymmetricErrorBars = len(self.yMins) > 0 or \ len(self.yMaxes) > 0 sortSymmetricErrorBars = len(self.yErrors) > 0 if sortAsymmetricErrorBars: if len(self.yMins) != len(self.yValues): warnings.warn("You don't have an error bar for every " "point, some points will be truncated") zipped = zip(self.xValues, self.yValues, self.yMins, self.yMaxes) zipped.sort() self.xValues, self.yValues, self.yMins, self.yMaxes \ = zip(*zipped) elif sortSymmetricErrorBars: if len(self.yErrors) != len(self.yValues): warnings.warn("You don't have an error bar for every " "point, some points will be truncated") zipped = zip(self.xValues, self.yValues, self.yErrors) zipped.sort() self.xValues, self.yValues, self.yErrors = zip(*zipped) else: zipped = zip(self.xValues, self.yValues) zipped.sort() self.xValues, self.yValues = zip(*zipped) if len(self.xTickLabels) > 0: if len(self.xTickLabelPoints) == 0: axis.set_xticks(self.xValues[0:len(self.xTickLabels)]) else: axis.set_xticks(self.xTickLabelPoints) axis.set_xticklabels(self.xTickLabels, **self.xTickLabelProperties) if len(self.yTickLabels) > 0: if len(self.yTickLabelPoints) == 0: axis.set_yticks(self.yValues[0:len(self.yTickLabels)]) else: axis.set_yticks(self.yTickLabelPoints) axis.set_yticklabels(self.yTickLabels, **self.yTickLabelProperties) self.drawErrorBars(axis) def drawErrorBars(self, axis, transform=None): errorBarKeywords = {} if self.errorBarColor is not None: errorBarKeywords["ecolor"] = self.errorBarColor elif hasattr(self, "color"): errorBarKeywords["ecolor"] = self.color if self.errorBarCapsize is not None: errorBarKeywords["capsize"] = self.errorBarCapsize if self.errorBarLineWidth is not None: errorBarKeywords["linewidth"] = self.errorBarLineWidth if hasattr(self, "lineStyle"): errorBarKeywords["linestyle"] = self.lineStyle if transform: errorBarKeywords['transform'] = transform + axis.transData errorBarKeywords["fmt"] = None if len(self.yMins) > 0 and len(self.yMaxes) > 0: numYVals = len(self.yValues) yMin = [self.yValues[i] - self.yMins[i] for i in xrange(numYVals)] yMax = [self.yMaxes[i] - self.yValues[i] for i in xrange(numYVals)] errorBarKeywords["yerr"] = [yMin, yMax] axis.errorbar(self.xValues, self.yValues, **errorBarKeywords) elif len(self.yErrors) > 0: errorBarKeywords["yerr"] = self.yErrors axis.errorbar(self.xValues, self.yValues, **errorBarKeywords)
def __init__(self): self._formatter = None self.labels = None self.labelPoints = None self._properties = LabelProperties() self.size = None
class Plot(object): """ Represents a single plot, usually consisting of a single X and Y axis. """ def __init__(self): self.plots = [] self.title = None """ The plot's title (will be centered above the axes themselves) """ self.xFormatter = None self.yFormatter = None self.yLabel = None """ The label for the plot's y-axis """ self.xLabel = None """ The label for the plot's x-axis """ self._xLabelProperties = LabelProperties() self._yLabelProperties = LabelProperties() self.legend = None self._xLimits = None self._yLimits = None self.twinxLabel = None self.twinxIndex = -1 self.twinxLimits = None self.lineStyles = None self.lineColors = None self.markers = None self.width = None self.height = None self.dpi = 100 self.plotParams = None self.logx = False """ If true, this plot's x-axis will be drawn in log scale. """ self.logy = False """ If true, this plot's y-axis will be drawn in log scale. """ self.loglog = False """ If true, both this plot's axes will be drawn in log scale. """ self.logbase = 10 """ The base of the logarithm used to draw log scale axes. """ self.logbasex = None """ The base of the logarithm used to draw the x-axis. Overrides `logbase`, and only takes effect if logx or loglog are True. """ self.logbasey = None """ The base of the logarithm used to draw the y-axis. Overrides `logbase`, and only takes effect if logy or loglog are True. """ self._grid = Grid() self._grid.visible = False self.insets = [] self.hideTicks = False """ If True, this plot's tick labels are hidden. """ self.titleSize = None """ The size of the text used for plot title. """ self.latex = False self.axesLabelSize = None """ The size of the text used for labeling the x and y axes. """ self.xTickLabelSize = None """ The size of the text used for x-axis tick labels """ self.yTickLabelSize = None """ The size of the text used for y-axis tick labels """ self.titleProperties = LabelProperties() self.tight = False """ If True, this plot is auto-scaled so that axis labels don't get cut off. """ self.allows_tight = True self.projection = None """ Defines the projection used when drawing this plot. The only currently supported value other than the standard (no projection) is 'polar'. """ @property def xLabelProperties(self): """ A dictionary of properties that control the appearance of the X axis' axis label. See :ref:`styling-labels` for more information on which properties can be set. """ return self._xLabelProperties @xLabelProperties.setter def xLabelProperties(self, propsobj): self._xLabelProperties.update(propsobj) @property def yLabelProperties(self): """ A dictionary of properties that control the appearance of the Y axis' axis label. See :ref:`styling-labels` for more information on which properties can be set. """ return self._yLabelProperties @yLabelProperties.setter def yLabelProperties(self, propsobj): self._yLabelProperties.update(propsobj) @property def xLimits(self): """ A pair giving the minimum and maximum values visible on the x-axis. """ return self._xLimits @xLimits.setter def xLimits(self, value): if type(value) not in [tuple, list] or len(value) != 2: raise AttributeError("xLimits must be set to a (min, max) tuple") self._xLimits = tuple(value) @property def yLimits(self): """ A pair giving the minimum and maximum values visible on the x-axis. """ return self._yLimits @yLimits.setter def yLimits(self, value): if type(value) not in [tuple, list] or len(value) != 2: raise AttributeError("yLimits must be set to a (min, max) tuple") self._yLimits = value @property def legendLabelSize(self): """ The size of the text in this plot's legend. """ return self.legend.labelSize @legendLabelSize.setter def legendLabelSize(self, size): self.setLegendLabelSize(size) @property def grid(self): """ A boomslang.Grid.Grid that defines the properties of this plot's grid lines. See :ref:`plots-grid-lines` for configuration options. """ return self._grid @grid.setter def grid(self, value): if isinstance(value, bool) and value == True: self._grid.visible = True else: raise AttributeError("Plot.grid cannot be re-assigned") def setTitleProperties(self, **propList): """ Set the properties of the title. See :ref:`styling-labels` for more information about valid properties. """ self.__setProperties(self.titleProperties, propList) def __setProperties(self, propsDict, propList): for (key, val) in propList.items(): propsDict[key] = val def __str__(self): return str(self.__dict__) def setTitleSize(self, size): self.titleSize = size def setAxesLabelSize(self, size): self.axesLabelSize = size def setXTickLabelSize(self, size): self.xTickLabelSize = size def setYTickLabelSize(self, size): self.yTickLabelSize = size def setLegendLabelSize(self, size): if self.legend is None: self.legend = Legend() self.legend.labelSize = size def split(self, pieces): """ Split this plot into `pieces` separate plots, each showing a different portion of the x-axis """ splitPlots = [copy.deepcopy(self) for i in xrange(pieces)] for plot in splitPlots: plot.plots = [] for plot in self.plots: elements = plot.split(pieces) for i in xrange(pieces): splitPlots[i].add(elements[i]) splitPlots[i].setXLimits( min(elements[i].xValues), max(elements[i].xValues)) return splitPlots def getDimensions(self): """ Get the dimensions of this plot. """ if self.width is None: (self.width, self.height) = getGoldenRatioDimensions(8.0) elif self.height is None: (goldWidth, goldHeight) = getGoldenRatioDimensions(self.width) self.height = goldHeight return (self.width, self.height) def hideTickLabels(self): self.hideTicks = True def setDimensions(self, width=None, height=None, dpi=100): """ Set the dimensions for this plot to `width` x `height` """ self.width = width self.height = height self.dpi = dpi def add(self, plottableObject): """ Add a plottable object (a Line, Bar, etc.) to this plot, causing it to be drawn when the plot is drawn. """ if not issubclass(plottableObject.__class__, PlotInfo): raise BoomslangPlotConfigurationException( "All objects added to a Plot must be a subclass of PlotInfo") self.plots.append(plottableObject) def addInset(self, plot, **kwargs): """ Add `plot` (a Plot object) as an inset to this plot object. Valid arguments are as follows: ============ ==================================================================================================================== Argument Description ============ ==================================================================================================================== ``width`` The width of the inset as a fraction of the size of the parent plot ``height`` The height of the inset as a fraction of the size of the parent plot ``location`` The location of the inset. See :ref:`plots-locations` for valid locations. ``padding`` The amount of padding between the edge of the parent plot and the inset as a fraction of the size of the parent plot ============ ==================================================================================================================== """ inset = Inset(plot, **kwargs) self.insets.append(inset) def addLineStyle(self, style): """ Add a line style to the list of line styles through which the plot will cycle when drawing lines. If no line styles are specified, the plot will default to the line style specified in the Line objects themselves. Note that, when drawing lines, all line styles for a given color are cycled through before another color is used. """ if self.lineStyles is None: self.lineStyles = [] currStyle = LineStyle() currStyle.style = style self.lineStyles.append(currStyle) def addLineColor(self, color): """ Add a line color to the list of line colors through which the plot will cycle when drawing lines. If no line colors are specified, the line colors specified by the Line objects themselves will be used. Note that, when drawing lines, all line styles for a given color are cycled through before another color is used. """ if self.lineColors is None: self.lineColors = [] self.lineColors.append(color) def addMarker(self, marker): """ Add a marker style to the list of marker styles through which the plot will cycle when drawing lines. If no markers are specified, the markers specified by the Line objects themselves will be used. Note that, when drawing lines, all line style/color combinations are cycled through with a given marker before a new marker is chosen. """ if self.markers is None: self.markers = [] currMarker = Marker() currMarker.marker = marker self.markers.append(currMarker) def getNumPlots(self): # Get the number of plottable objects currently registered for this # plot. return len(self.plots) def setTwinX(self, label, index, yMin=None, yMax=None): """ Make the plot use a secondary y-axis with the provided label. All registered plottable objects at or after the given index will use this second axis. """ self.twinxLabel = label self.twinxIndex = index if yMin is not None and yMax is not None: self.twinxLimits = (yMin, yMax) def setYFormatter(self, formatter): """ Set the y-axis formatter used by this plot to the given function. """ self.yFormatter = pylab.FuncFormatter(formatter) def setXFormatter(self, formatter): """ Set the x-axis formatter used by this plot to the given function. """ self.xFormatter = pylab.FuncFormatter(formatter) def setXLabel(self, xLabel): self.xLabel = xLabel def setYLabel(self, yLabel): self.yLabel = yLabel def setXLimits(self, minX, maxX): self.xLimits = (minX, maxX) def setYLimits(self, minY, maxY): self.yLimits = (minY, maxY) def hasFigLegend(self, columns=1, location="best", scatterPoints=3, draw_frame=True, bbox_to_anchor=None, labelSize=None, title=None, labelOrdering=None, leftToRight=False): """ Declare that the figure has a legend with a given number of columns and location. """ self.legend = Legend(columns = columns, scatterPoints = scatterPoints, drawFrame = draw_frame, location = location, figLegend = True, labelSize = labelSize, bboxToAnchor = bbox_to_anchor, title = title, labelOrdering = labelOrdering, leftToRight = leftToRight) def hasLegend(self, columns=1, location="best", scatterPoints=3, draw_frame=True, bbox_to_anchor=None, labelSize = None, title=None, labelOrdering=None, leftToRight=False): """ Declare that the plot has a legend with a given number of columns and location. """ self.legend = Legend(columns = columns, scatterPoints = scatterPoints, drawFrame = draw_frame, location = location, figLegend = False, labelSize = labelSize, bboxToAnchor = bbox_to_anchor, title = title, labelOrdering = labelOrdering, leftToRight = leftToRight) def setTitle(self, title): self.title = title def __cmp__(self, other): if not isinstance(other, Plot): raise ValueError("Can't compare a Plot with a non-Plot") return cmp(self.title, other.title) def __setupLayout(self): layout = PlotLayout() (width, height) = self.getDimensions() layout.setPlotDimensions(width, height, dpi=self.dpi) if self.plotParams is not None: layout.setPlotParameters(**self.plotParams) if self.titleSize is not None: layout.setTitleSize(self.titleSize) if self.latex == True: layout.useLatexLabels() if self.axesLabelSize is not None: layout.setAxesLabelSize(self.axesLabelSize) if self.xTickLabelSize is not None: layout.setXTickLabelSize(self.xTickLabelSize) if self.yTickLabelSize is not None: layout.setYTickLabelSize(self.yTickLabelSize) layout.addPlot(self) return layout def useLatexLabels(self): self.latex = True def plot(self): """ Draw this plot to a matplotlib canvas. """ layout = self.__setupLayout() layout.plot() def plot_fig(self): layout = self.__setupLayout() return layout._doPlot() def setPlotParameters(self, **kwdict): """ Set the margins of this plot. See `matplotlib's SubplotParams documentation <http://matplotlib.sourceforge.net/api/figure_api.html#matplotlib.figure.SubplotParams>`_ for more details. It is recommended that you set :py:attr:`boomslang.Plot.Plot.tight` to True instead of setting these parameters. """ self.plotParams = dict(kwdict) if "left" not in self.plotParams: self.plotParams["left"] = 0.12 if "bottom" not in self.plotParams: self.plotParams["bottom"] = 0.10 if "right" not in self.plotParams: self.plotParams["right"] = 0.90 if "top" not in self.plotParams: self.plotParams["top"] = 0.90 if "wspace" not in self.plotParams: self.plotParams["wspace"] = 0.20 if "hspace" not in self.plotParams: self.plotParams["hspace"] = 0.20 def save(self, filename, **kwargs): """ Save this plot to a file. """ layout = self.__setupLayout() layout.save(filename,**kwargs) def subplot(self, fig, row, column, position, projection): kwdict = {} if projection is not None: kwdict["projection"] = projection ax = fig.add_subplot(row, column, position, **kwdict) return self.drawPlot(fig, ax) def drawPlot(self, fig, ax): """ Used by PlotLayout to plot the graph at a given location in the layout. """ ax2 = None if self.tight and self.allows_tight: ax.autoscale_view(tight=True) for inset in self.insets: inset.draw(fig, ax) if self.hideTicks == True: for xtl in ax.get_xticklabels(): xtl.set_visible(False) for xtick in ax.get_xticklines(): xtick.set_visible(False) for ytl in ax.get_yticklabels(): ytl.set_visible(False) for ytick in ax.get_yticklines(): ytick.set_visible(False) if self.grid.visible == True: self.grid.draw(fig, ax) if self.loglog or self.logx: myBase = None if self.logbasex is not None: myBase = self.logbasex else: myBase = self.logbase ax.set_xscale('log', basex=myBase) if self.loglog or self.logy: myBase = None if self.logbasey is not None: myBase = self.logbasey else: myBase = self.logbase ax.set_yscale('log', basey=myBase) if self.twinxIndex > 0: ax2 = ax.twinx() ax2.set_ylabel(self.twinxLabel) if self.twinxLimits is not None: ax2.set_ylim(ymin=self.twinxLimits[0], ymax=self.twinxLimits[1]) plotHandles = [] plotLabels = [] if self.xFormatter is not None: ax.xaxis.set_major_formatter(self.xFormatter) if self.yFormatter is not None: ax.yaxis.set_major_formatter(self.yFormatter) if self.title is not None: ax.set_title(self.title, **self.titleProperties) i = 0 myAxis = ax hasLineStyles = self.lineStyles is not None hasColors = self.lineColors is not None hasMarkers = self.markers is not None numLineStyles = 1 numColors = 1 numMarkers = 1 if hasLineStyles: numLineStyles = len(self.lineStyles) if hasColors: numColors = len(self.lineColors) if hasMarkers: numMarkers = len(self.markers) plotIndex = 0 for plotInfo in self.plots: if self.twinxIndex >= 0 and i == self.twinxIndex: myAxis = ax2 myLineStyle = None myColor = None myMarker = None # cycle through styles first, then markers, then colors colorIndex = (plotIndex / (numMarkers * numLineStyles)) % numColors markerIndex = int(plotIndex / numLineStyles) % numMarkers lineStyleIndex = plotIndex % numLineStyles if hasLineStyles: myLineStyle = self.lineStyles[lineStyleIndex].style if hasColors: myColor = self.lineColors[colorIndex] if hasMarkers: myMarker = self.markers[markerIndex].marker plotIndex += 1 if myLineStyle is not None: plotInfo.lineStyle = myLineStyle if myMarker is not None: plotInfo.marker = myMarker if myColor is not None: plotInfo.color = myColor plotInfo._preDraw() (currPlotHandles, currPlotLabels) = plotInfo.draw(fig, myAxis) labelIndices = [x for x in range(len(currPlotLabels)) \ if currPlotLabels[x] is not None] if len(labelIndices) > 0: plotHandles.extend([currPlotHandles[x] for x in labelIndices]) plotLabels.extend([currPlotLabels[x] for x in labelIndices]) if plotInfo.xLimits is not None: if self.xLimits is None: self.xLimits = plotInfo.xLimits else: (myXMin, myXMax) = plotInfo.xLimits self.xLimits = (min(self.xLimits[0], myXMin), max(self.xLimits[1], myXMax)) i += 1 if self.xLimits is not None: ax.set_xlim(xmin=self.xLimits[0], xmax=self.xLimits[1]) if self.yLimits is not None: ax.set_ylim(ymin=self.yLimits[0], ymax=self.yLimits[1]) if self.xLabel is not None: ax.set_xlabel(self.xLabel, **self.xLabelProperties) if self.yLabel is not None: ax.set_ylabel(self.yLabel, **self.yLabelProperties) if self.legend is not None: if len(plotHandles) == 0: print >>sys.stderr, "ERROR: Plot wanted to draw a legend, " \ "but none of its elements have labels" sys.exit(1) if self.twinxIndex > 0: legendAxis = ax2 else: legendAxis = ax self.legend.draw(fig, legendAxis, plotHandles, plotLabels) return (plotHandles, plotLabels)