Revision: 6786
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6786&view=rev
Author: jdh2358
Date: 2009-01-16 15:39:17 +0000 (Fri, 16 Jan 2009)
Log Message:
-----------
added Tom Krauss' wx fourier demo
Added Paths:
-----------
trunk/matplotlib/examples/user_interfaces/fourier_demo_wx.py
Added: trunk/matplotlib/examples/user_interfaces/fourier_demo_wx.py
===================================================================
--- trunk/matplotlib/examples/user_interfaces/fourier_demo_wx.py
(rev 0)
+++ trunk/matplotlib/examples/user_interfaces/fourier_demo_wx.py
2009-01-16 15:39:17 UTC (rev 6786)
@@ -0,0 +1,214 @@
+import numpy as np
+import wx
+
+import matplotlib
+matplotlib.interactive(False)
+matplotlib.use('WXAgg')
+from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
+from matplotlib.figure import Figure
+from matplotlib.pyplot import gcf, setp
+
+
+class Knob:
+ """
+ Knob - simple class with a "setKnob" method.
+ A Knob instance is attached to a Param instance, e.g. param.attach(knob)
+ Base class is for documentation purposes.
+ """
+ def setKnob(self, value):
+ pass
+
+
+class Param:
+ """
+ The idea of the "Param" class is that some parameter in the GUI may have
+ several knobs that both control it and reflect the parameter's state, e.g.
+ a slider, text, and dragging can all change the value of the frequency in
+ the waveform of this example.
+ The class allows a cleaner way to update/"feedback" to the other knobs
when
+ one is being changed. Also, this class handles min/max constraints for all
+ the knobs.
+ Idea - knob list - in "set" method, knob object is passed as well
+ - the other knobs in the knob list have a "set" method which gets
+ called for the others.
+ """
+ def __init__(self, initialValue=None, minimum=0., maximum=1.):
+ self.minimum = minimum
+ self.maximum = maximum
+ if initialValue != self.constrain(initialValue):
+ raise ValueError('illegal initial value')
+ self.value = initialValue
+ self.knobs = []
+
+ def attach(self, knob):
+ self.knobs += [knob]
+
+ def set(self, value, knob=None):
+ self.value = value
+ self.value = self.constrain(value)
+ for feedbackKnob in self.knobs:
+ if feedbackKnob != knob:
+ feedbackKnob.setKnob(self.value)
+ return self.value
+
+ def constrain(self, value):
+ if value <= self.minimum:
+ value = self.minimum
+ if value >= self.maximum:
+ value = self.maximum
+ return value
+
+
+class SliderGroup(Knob):
+ def __init__(self, parent, label, param):
+ self.sliderLabel = wx.StaticText(parent, label=label)
+ self.sliderText = wx.TextCtrl(parent, -1, style=wx.TE_PROCESS_ENTER)
+ self.slider = wx.Slider(parent, -1)
+ self.slider.SetMax(param.maximum*1000)
+ self.setKnob(param.value)
+
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(self.sliderLabel, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL,
border=2)
+ sizer.Add(self.sliderText, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL,
border=2)
+ sizer.Add(self.slider, 1, wx.EXPAND)
+ self.sizer = sizer
+
+ self.slider.Bind(wx.EVT_SLIDER, self.sliderHandler)
+ self.sliderText.Bind(wx.EVT_TEXT_ENTER, self.sliderTextHandler)
+
+ self.param = param
+ self.param.attach(self)
+
+ def sliderHandler(self, evt):
+ value = evt.GetInt() / 1000.
+ self.param.set(value)
+
+ def sliderTextHandler(self, evt):
+ value = float(self.sliderText.GetValue())
+ self.param.set(value)
+
+ def setKnob(self, value):
+ self.sliderText.SetValue('%g'%value)
+ self.slider.SetValue(value*1000)
+
+
+class FourierDemoFrame(wx.Frame):
+ def __init__(self, *args, **kwargs):
+ wx.Frame.__init__(self, *args, **kwargs)
+
+ self.fourierDemoWindow = FourierDemoWindow(self)
+ self.frequencySliderGroup = SliderGroup(self, label='Frequency f0:', \
+ param=self.fourierDemoWindow.f0)
+ self.amplitudeSliderGroup = SliderGroup(self, label=' Amplitude a:', \
+ param=self.fourierDemoWindow.A)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(self.fourierDemoWindow, 1, wx.EXPAND)
+ sizer.Add(self.frequencySliderGroup.sizer, 0, \
+ wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5)
+ sizer.Add(self.amplitudeSliderGroup.sizer, 0, \
+ wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5)
+ self.SetSizer(sizer)
+
+
+class FourierDemoWindow(wx.Window, Knob):
+ def __init__(self, *args, **kwargs):
+ wx.Window.__init__(self, *args, **kwargs)
+ self.lines = []
+ self.figure = Figure()
+ self.canvas = FigureCanvasWxAgg(self, -1, self.figure)
+ self.canvas.callbacks.connect('button_press_event', self.mouseDown)
+ self.canvas.callbacks.connect('motion_notify_event', self.mouseMotion)
+ self.canvas.callbacks.connect('button_release_event', self.mouseUp)
+ self.state = ''
+ self.mouseInfo = (None, None, None, None)
+ self.f0 = Param(2., minimum=0., maximum=6.)
+ self.A = Param(1., minimum=0.01, maximum=2.)
+ self.draw()
+
+ # Not sure I like having two params attached to the same Knob,
+ # but that is what we have here... it works but feels kludgy -
+ # although maybe it's not too bad since the knob changes both params
+ # at the same time (both f0 and A are affected during a drag)
+ self.f0.attach(self)
+ self.A.attach(self)
+ self.Bind(wx.EVT_SIZE, self.sizeHandler)
+
+ def sizeHandler(self, *args, **kwargs):
+ self.canvas.SetSize(self.GetSize())
+
+ def mouseDown(self, evt):
+ if self.lines[0] in self.figure.hitlist(evt):
+ self.state = 'frequency'
+ elif self.lines[1] in self.figure.hitlist(evt):
+ self.state = 'time'
+ else:
+ self.state = ''
+ self.mouseInfo = (evt.xdata, evt.ydata, max(self.f0.value, .1),
self.A.value)
+
+ def mouseMotion(self, evt):
+ if self.state == '':
+ return
+ x, y = evt.xdata, evt.ydata
+ if x is None: # outside the axes
+ return
+ x0, y0, f0Init, AInit = self.mouseInfo
+ self.A.set(AInit+(AInit*(y-y0)/y0), self)
+ if self.state == 'frequency':
+ self.f0.set(f0Init+(f0Init*(x-x0)/x0))
+ elif self.state == 'time':
+ if (x-x0)/x0 != -1.:
+ self.f0.set(1./(1./f0Init+(1./f0Init*(x-x0)/x0)))
+
+ def mouseUp(self, evt):
+ self.state = ''
+
+ def draw(self):
+ if not hasattr(self, 'subplot1'):
+ self.subplot1 = self.figure.add_subplot(211)
+ self.subplot2 = self.figure.add_subplot(212)
+ x1, y1, x2, y2 = self.compute(self.f0.value, self.A.value)
+ color = (1., 0., 0.)
+ self.lines += self.subplot1.plot(x1, y1, color=color, linewidth=2)
+ self.lines += self.subplot2.plot(x2, y2, color=color, linewidth=2)
+ #Set some plot attributes
+ self.subplot1.set_title("Click and drag waveforms to change frequency
and amplitude", fontsize=12)
+ self.subplot1.set_ylabel("Frequency Domain Waveform X(f)", fontsize =
8)
+ self.subplot1.set_xlabel("frequency f", fontsize = 8)
+ self.subplot2.set_ylabel("Time Domain Waveform x(t)", fontsize = 8)
+ self.subplot2.set_xlabel("time t", fontsize = 8)
+ self.subplot1.set_xlim([-6, 6])
+ self.subplot1.set_ylim([0, 1])
+ self.subplot2.set_xlim([-2, 2])
+ self.subplot2.set_ylim([-2, 2])
+ self.subplot1.text(0.05, .95, r'$X(f) = \mathcal{F}\{x(t)\}$', \
+ verticalalignment='top', transform = self.subplot1.transAxes)
+ self.subplot2.text(0.05, .95, r'$x(t) = a \cdot \cos(2\pi f_0 t)
e^{-\pi t^2}$', \
+ verticalalignment='top', transform = self.subplot2.transAxes)
+
+ def compute(self, f0, A):
+ f = np.arange(-6., 6., 0.02)
+ t = np.arange(-2., 2., 0.01)
+ x = A*np.cos(2*np.pi*f0*t)*np.exp(-np.pi*t**2)
+ X = A/2*(np.exp(-np.pi*(f-f0)**2) + np.exp(-np.pi*(f+f0)**2))
+ return f, X, t, x
+
+ def repaint(self):
+ self.canvas.draw()
+
+ def setKnob(self, value):
+ # Note, we ignore value arg here and just go by state of the params
+ x1, y1, x2, y2 = self.compute(self.f0.value, self.A.value)
+ setp(self.lines[0], xdata=x1, ydata=y1)
+ setp(self.lines[1], xdata=x2, ydata=y2)
+ self.repaint()
+
+
+class App(wx.App):
+ def OnInit(self):
+ self.frame1 = FourierDemoFrame(parent=None, title="Fourier Demo",
size=(640, 480))
+ self.frame1.Show()
+ return True
+
+app = App()
+app.MainLoop()
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins