From f8758dba39c7a4ccd60c02c1abe12ee78c58ff81 Mon Sep 17 00:00:00 2001 From: Luke Campagnola <> Date: Sat, 21 Apr 2012 15:57:47 -0400 Subject: [PATCH] PlotItem (finally) gets log scaling Also cleaned up some context menu items --- examples/Plotting.py | 11 +- examples/logAxis.py | 38 +++++++ graphicsItems/AxisItem.py | 26 +++++ graphicsItems/PlotItem/PlotItem.py | 100 ++++++++++++++++--- graphicsItems/PlotItem/plotConfigTemplate.py | 93 ++++++++++------- graphicsItems/PlotItem/plotConfigTemplate.ui | 82 +++++++++------ 6 files changed, 269 insertions(+), 81 deletions(-) create mode 100644 examples/logAxis.py diff --git a/examples/Plotting.py b/examples/Plotting.py index 79d0d4ac..cb512503 100644 --- a/examples/Plotting.py +++ b/examples/Plotting.py @@ -35,18 +35,20 @@ p3.plot(np.random.normal(size=100), pen=(200,200,200), symbolBrush=(255,0,0), sy win.nextRow() -p4 = win.addPlot(title="Parametric") +p4 = win.addPlot(title="Parametric, grid enabled") x = np.cos(np.linspace(0, 2*np.pi, 1000)) y = np.sin(np.linspace(0, 4*np.pi, 1000)) p4.plot(x, y) +p4.showGrid(x=True, y=True) -p5 = win.addPlot(title="Scatter plot with labels") +p5 = win.addPlot(title="Scatter plot, axis labels, log scale") x = np.random.normal(size=1000) * 1e-5 y = x*1000 + 0.005 * np.random.normal(size=1000) +y -= y.min()-1.0 p5.plot(x, y, pen=None, symbol='t', symbolPen=None, symbolSize=10, symbolBrush=(100, 100, 255, 50)) p5.setLabel('left', "Y Axis", units='A') p5.setLabel('bottom', "Y Axis", units='s') - +p5.setLogMode(x=True, y=False) p6 = win.addPlot(title="Updating plot") curve = p6.plot(pen='y') @@ -65,9 +67,10 @@ timer.start(50) win.nextRow() -p7 = win.addPlot(title="Filled plot") +p7 = win.addPlot(title="Filled plot, axis disabled") y = np.sin(np.linspace(0, 10, 1000)) + np.random.normal(size=1000, scale=0.1) p7.plot(y, fillLevel=-0.3, brush=(50,50,200,100)) +p7.showAxis('bottom', False) x2 = np.linspace(-100, 100, 1000) diff --git a/examples/logAxis.py b/examples/logAxis.py new file mode 100644 index 00000000..3e291fb2 --- /dev/null +++ b/examples/logAxis.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +import initExample ## Add path to library (just for examples; you do not need this) + +import numpy as np +from pyqtgraph.Qt import QtGui, QtCore +import pyqtgraph as pg + + +app = QtGui.QApplication([]) + +w = pg.GraphicsWindow() +p1 = w.addPlot(0,0, title="X Semilog") +p2 = w.addPlot(1,0, title="Y Semilog") +p3 = w.addPlot(2,0, title="XY Log") +p1.showGrid(True, True) +p2.showGrid(True, True) +p3.showGrid(True, True) +p1.setLogMode(True, False) +p2.setLogMode(False, True) +p3.setLogMode(True, True) +w.show() + +y = np.random.normal(size=1000) +x = np.linspace(0, 1, 1000) +p1.plot(x, y) +p2.plot(x, y) +p3.plot(x, y) + + + +#p.getAxis('bottom').setLogMode(True) + + +## Start Qt event loop unless running in interactive mode or using pyside. +import sys +if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): + app.exec_() diff --git a/graphicsItems/AxisItem.py b/graphicsItems/AxisItem.py index 563f3fb4..bd72561f 100644 --- a/graphicsItems/AxisItem.py +++ b/graphicsItems/AxisItem.py @@ -43,6 +43,7 @@ class AxisItem(GraphicsWidget): self.labelUnits = '' self.labelUnitPrefix='' self.labelStyle = {'color': '#CCC'} + self.logMode = False self.textHeight = 18 self.tickLength = maxTickLength @@ -76,6 +77,10 @@ class AxisItem(GraphicsWidget): self.prepareGeometryChange() self.update() + def setLogMode(self, log): + self.logMode = log + self.picture = None + self.update() def resizeEvent(self, ev=None): #s = self.size() @@ -316,6 +321,9 @@ class AxisItem(GraphicsWidget): By default, this method calls tickSpacing to determine the correct tick locations. This is a good method to override in subclasses. """ + if self.logMode: + return self.logTickValues(minVal, maxVal, size) + ticks = [] tickLevels = self.tickSpacing(minVal, maxVal, size) for i in range(len(tickLevels)): @@ -329,6 +337,16 @@ class AxisItem(GraphicsWidget): ticks.append((spacing, np.arange(num) * spacing + start)) return ticks + def logTickValues(self, minVal, maxVal, size): + v1 = int(np.floor(minVal)) + v2 = int(np.ceil(maxVal)) + major = range(v1+1, v2) + + minor = [] + for v in range(v1, v2): + minor.extend(v + np.log10(np.arange(1, 10))) + minor = filter(lambda x: x>minVal and x