I am trying to add a pcolormesh to a simple line plot in wxmplot and cannot get its scale to match the plot data axis.
The pcolormesh grid wants to conform to its own limits, and match those to the plot data.
In the test program (adopted from wxmplot example stripchart.py), the generated data is a sin wave with small random numbers added that has a range of about /- 1.5. Adding the pcolormesh to that and we see only the bottom few rows (i.e. one or two integer rows) and nothing below zero.
If I multiple the Y data by 10, then I start to be able to see a more complete pcolormesh.
I have tried various variations of different values for the meshgrid, norm and transfer parameters. This is the most stable version, but I can't find the right parameters to change to get the pcolormesh to conform to the plotted data's Y axis, and to use its full range of colours for the available Y axis, including negative values.
Suggestions would be very welcome! Thanks.
Sample plot with normal range.
Sample plot with y*10.
#!/usr/bin/python
import time
import numpy as np
import sys
import wx
from wx.lib import masked
from floatcontrol import FloatCtrl
from wxmplot import PlotPanel
# Set the YMULTIPLER=1 to see the only the bottom two rows of the pcolormesh.
# Set the YMULTIPLER=10 to see the only the a more complete mesh.
# N.B. The pcolormesh does not get shown for any portion of the plot below zero.
#YMULTIPLIER=1
YMULTIPLIER=10
def next_data():
"simulated data"
t0 = time.time()
lt = time.localtime(t0)
tmin, tsec = lt[4],lt[5]
u = np.random.random()
v = np.random.random()
x = np.sin( (u tsec)/3.0) tmin/30. v/5.0
return t0, x
class StripChartFrame(wx.Frame):
def __init__(self, parent, ID, **kws):
kws["style"] = wx.DEFAULT_FRAME_STYLE|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL
wx.Frame.__init__(self, parent, ID, '',
wx.DefaultPosition, wx.Size(-1,-1), **kws)
self.SetTitle("wxmplot StripChart Demo")
self.tmin = 15.0
self.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.BOLD,False))
menu = wx.Menu()
menu_exit = menu.Append(-1, "E&xit", "Terminate the program")
menuBar = wx.MenuBar()
menuBar.Append(menu, "&File");
self.SetMenuBar(menuBar)
self.Bind(wx.EVT_MENU, self.OnExit, menu_exit)
self.Bind(wx.EVT_CLOSE, self.OnExit)
sbar = self.CreateStatusBar(2,wx.CAPTION)
sfont = sbar.GetFont()
sfont.SetWeight(wx.BOLD)
sfont.SetPointSize(11)
sbar.SetFont(sfont)
self.SetStatusWidths([-3,-1])
self.SetStatusText('',0)
mainsizer = wx.BoxSizer(wx.VERTICAL)
btnpanel = wx.Panel(self, -1)
btnsizer = wx.BoxSizer(wx.HORIZONTAL)
b_on = wx.Button(btnpanel, -1, 'Start', size=(-1,-1))
b_off = wx.Button(btnpanel, -1, 'Stop', size=(-1,-1))
b_on.Bind(wx.EVT_BUTTON, self.onStartTimer)
b_off.Bind(wx.EVT_BUTTON, self.onStopTimer)
tlabel = wx.StaticText(btnpanel, -1, ' Time range:')
self.time_range = FloatCtrl(btnpanel, size=(100, -1), value=abs(self.tmin), precision=1)
btnsizer.Add(b_on, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 0)
btnsizer.Add(b_off, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 0)
btnsizer.Add(tlabel, 1, wx.GROW|wx.ALL|wx.ALIGN_LEFT|wx.LEFT, 0)
btnsizer.Add(self.time_range, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER|wx.LEFT, 0)
btnpanel.SetSizer(btnsizer)
btnsizer.Fit(btnpanel)
self.plotpanel = PlotPanel(self, messenger=self.write_message)
self.plotpanel.BuildPanel()
self.plotpanel.set_xlabel('Time from Present (s)')
mainsizer.Add(btnpanel, 0, wx.GROW|wx.ALIGN_LEFT|wx.LEFT, 0)
mainsizer.Add(self.plotpanel, 1, wx.GROW|wx.ALL|wx.ALIGN_LEFT|wx.LEFT, 0)
self.SetSizer(mainsizer)
mainsizer.Fit(self)
self.Bind(wx.EVT_TIMER, self.onTimer)
self.timer = wx.Timer(self)
self.count = 0
self.Refresh()
self.SetSize(self.GetBestVirtualSize())
axes = self.plotpanel.axes
axis = axes.xaxis
wx.CallAfter(self.onStartTimer)
def write_message(self, msg, panel=0):
"""write a message to the Status Bar"""
self.SetStatusText(msg, panel)
def onStartTimer(self,event=None):
self.count = 0
t0,y0 = next_data()
y0 *= YMULTIPLIER
self.ylist = [y0]
self.tlist = [t0]
self.tmin_last = -10000
self.time0 = time.time()
self.timer.Start(50)
def onStopTimer(self,event=None):
self.timer.Stop()
def onTimer(self, event):
self.count = 1
etime = time.time() - self.time0
self.tmin = float(self.time_range.GetValue())
t1, y1 = next_data()
y1 *= YMULTIPLIER
self.tlist.append(t1)
self.ylist.append(y1)
if len(self.tlist) > 200:
del self.tlist[0]
del self.ylist[0]
tdat = np.array(self.tlist) - self.time0
mask = np.where(tdat > -abs(self.tmin))
ydat = np.array(self.ylist)
n = len(self.ylist)
if n <= 2:
self.plotpanel.plot(tdat, ydat)
else:
self.plotpanel.update_line(0, tdat, ydat, draw=False)
self.write_message("update %i points in %8.4f s" % (n,etime))
lims = self.plotpanel.get_viewlimits()
try:
ymin, ymax = ydat[mask].min(), ydat[mask].max()
except:
ymin, ymax = ydat.min(), ydat.max()
yrange = abs(ymax-ymin)
ymin -= yrange*0.05
ymax = yrange*0.05
if (ymin < lims[2] or ymax > lims[3] ):
self.plotpanel.set_xylims((-self.tmin, 0, ymin, ymax))
self.plotpanel.plot(tdat, ydat)
xmin, xmax = tdat.min(), tdat.max()
X, Y = np.meshgrid(np.linspace(xmin, xmax, num=len(tdat)), np.linspace(ymin, ymax, num=int(ymax-ymin)))
axes = self.plotpanel.axes
axes.pcolormesh(Y, cmap="RdYlGn", alpha=0.2, edgecolors='gray')
self.plotpanel.draw()
def OnAbout(self, event):
dlg = wx.MessageDialog(self, "wxmplot example: stripchart app",
"About WXMPlot test", wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def OnExit(self, event):
self.Destroy()
app = wx.App()
f = StripChartFrame(None,-1)
f.Show(True)
app.MainLoop()
CodePudding user response:
Additional screenshots for using pcolormesh with X,Y,Y
This changes the behaviour in two ways. First, it now does map to negative Y values. Second, the X bins are much smaller, i.e. less than one.
xmin, xmax = tdat.min(), tdat.max()
X, Y = np.meshgrid(np.linspace(xmin, xmax, num=len(tdat) 1), np.linspace(ymin, ymax, num=int(ymax-ymin) 1))
axes = self.plotpanel.axes
axes.pcolormesh(X, Y, Y, cmap="RdYlGn", alpha=0.2, edgecolors='gray')
self.plotpanel.draw()
CodePudding user response:
Thanks, that does help with the X sizing.
But Y scaling still off.
xmin, xmax = tdat.min(), tdat.max()
#X, Y = np.meshgrid(np.linspace(xmin, xmax, num=len(tdat) 1), np.linspace(ymin, ymax, num=int(ymax-ymin) 1))
X, Y = np.meshgrid(np.linspace(xmin, xmax, num=2), np.linspace(ymin, ymax, num=int(ymax-ymin) 1))
axes = self.plotpanel.axes
axes.pcolormesh(X, Y, Y, cmap="RdYlGn", alpha=0.2, edgecolors='gray')
self.plotpanel.draw()