On Fri, Dec 14, 2012 at 8:55 AM, p.bingham <p.bing...@kelvatek.com> wrote:
> 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>
>
>
Your code is needlessly complex, and it is more likely that the bug lies in
there rather than with matplotlib. First, you really shouldn't ever do
imports within a class, and it makes no sense to assign those imports as
members of the class. Second, you shouldn't need to do complex subplot
management to do what you need, matplotlib has done it for you already.
For example, the fig.add_subplot() command will simply return the axes to
you if it has already been created. Alternatively, you might be interested
in using the mpl_toolkit.axes_grid1 module:
http://matplotlib.org/mpl_toolkits/axes_grid/users/overview.html
but it might be overkill in your case.
If you can simplify your code significantly, and still encounter the
corruption issue, please come back and post the code so we can help you out.
Cheers!
Ben Root
------------------------------------------------------------------------------
LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
Remotely access PCs and mobile devices and provide instant support
Improve your efficiency, and focus on delivering more value-add services
Discover what IT Professionals Know. Rescue delivers
http://p.sf.net/sfu/logmein_12329d2d
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users