I've created a class that allows a user to add several charts to a MATPLOTLIB
window. These can be either a line chart or a bar chart. It also has the
feature that when a chart has already been added to the window (as
identified from rowID) rather than draw a new plot it will replace the data
in the old plot. ie it allows for updates (animation)
This works grand for the line plot but I get corruption when plotting
several bar charts. The class looks like:
import math
class TFrmPlot():
def __init__(self, point_lists, deleteCallback, plotType, rowID):
import matplotlib
matplotlib.interactive( True )
matplotlib.use( 'WXAgg' )
import matplotlib.pyplot as plt
self.plt = plt
self.fig = plt.figure()
self.fig.canvas.mpl_connect('close_event', self.on_close)
import matplotlib.axes as ax
self.ax = ax
self.deleteCallback = deleteCallback
self.chartArray = []
self.addChart(point_lists, plotType, rowID)
def close(self):
self.plt.close('all')
#self.fig.close()
def replaceChartDataIfChartExists(self, point_lists, rowID):
if rowID==0:
pass
for chart in self.chartArray:
for plot in chart.plots:
if plot.rowID == rowID:
plot.points = point_lists
if plot.plotType=="Point":
plot.plotItem.set_data(point_lists[0],point_lists[1])
chart.subPlot.draw_artist(plot.plotItem)
self.fig.canvas.blit(chart.subPlot.bbox)
else:
for rect, h in zip(plot.plotItem,
point_lists[1]):
rect.set_height(h)
chart.subPlot.relim()
chart.subPlot.autoscale_view(True,True,True)
self.plt.draw()
return True
return False
def addChart(self, point_lists, plotType, rowID):
self.chartArray.append(TChart(rowID,plotType,point_lists))
self._drawAll()
def addPlot(self, point_lists, plotType, rowID):
chartNum = len(self.chartArray)
self.chartArray[chartNum-1].plots.append(TPlot(rowID,plotType,point_lists))
self._drawAll()
def on_close(self, event):
self.deleteCallback()
def _drawAll(self):
self.plt.clf()
numSubPlots = len(self.chartArray)
numCols = self._noCols(numSubPlots)
IndexConverter = TIndexConverter(numCols)
subPlot = None
for chartIndex in range(0,numSubPlots):
if numSubPlots==1:
subPlot = self.fig.add_subplot(1,1,1)
elif numSubPlots==2:
subPlot = self.fig.add_subplot(1,2,chartIndex+1)
else:
subPlot =
self.fig.add_subplot(2,numCols,IndexConverter._getSubPlotIndex(chartIndex))
subPlot.relim()
subPlot.autoscale_view(True,True,True)
self.chartArray[chartIndex].subPlot = subPlot
self._drawSubs(self.chartArray[chartIndex])
self.plt.show()
def _drawSubs(self, chart):
for plot in chart.plots:
if plot.plotType=="Point":
chart.subPlot.plot(plot.points[0],plot.points[1])
plot.plotItem =
chart.subPlot.lines[len(chart.subPlot.lines)-1]
else:
kwargs = {"alpha":0.5}
plot.plotItem =
chart.subPlot.bar(plot.points[0],plot.points[1],
width=self._calculateleastDiff(plot.points[0]), **kwargs)
def _noCols(self, numSubPlots):
return math.ceil(float(numSubPlots)/2.0)
def _calculateleastDiff(self, xValues):
xValues2 = sorted(xValues)
leastDiff = None
lastValue = None
for value in xValues2:
if lastValue is not None:
diff = value-lastValue
if leastDiff is None or diff < leastDiff:
leastDiff = diff
lastValue = value
return leastDiff
This is a bit long so to summarise:
addChart -- basically adds a new subplot
addPlot -- adds a new line or bar to an existing subplot
replaceChartDataIfChartExists -- refreshes the data if the ID already exists
The dummy data that I'm using just plots a positive gradient and a negative
gradient line in succession. My plots however can get into a state where
one/some or all of the bar plots become corrupted. It looks almost like the
x/y axis has been rotated, with the individual bars not starting from the
x-axis. The issue is intermittent; sometimes I will get several plots as
expected. Once a plot becomes corrupted all future updates remain corrupted.
Corrupted Chart:
<http://matplotlib.1069221.n5.nabble.com/file/n40023/corrupted.png>
···
--
View this message in context: http://matplotlib.1069221.n5.nabble.com/Bar-chart-corruption-when-plotting-multiple-subplots-in-MATPLOTLIB-tp40023.html
Sent from the matplotlib - users mailing list archive at Nabble.com.