remove wx GUI

parent eac364a0
import wx
from wx.lib.pubsub import Publisher as pub
from Model import Model
from View import View
class Controller:
""" a 'middleman' between the View (visual aspects) and the Model (information) of the application.
It ensures decoupling between both.
"""
def __init__(self, app):
# initialize the model and view
# * The model handles all the data, and signal-related operations
# * The view handles all the data visualization
self.model = Model()
self.view = View()
# subscribe to messages sent by the view
pub.subscribe(self.parse_file, "FILE PATH CHANGED")
pub.subscribe(self.reprocess_fft, "FFT CONTROLS CHANGED")
# subscribe to messages sent by the model
pub.subscribe(self.signal_changed, "SIGNAL CHANGED")
pub.subscribe(self.signal_changed, "FFT CHANGED")
self.view.Show()
def parse_file(self, message):
"""
Handles "FILE PATH CHANGED" messages, send by the View. It tells the model to parse a new file.
message.data should contain the path of the new file
"""
#try:
self.model.parse_file(message.data)
#except Exception as exception:
# self.view.show_exception('Error reading file', 'The following error happened while reading the file:\n%s' % str(exception))
# raise exception
def reprocess_fft(self, message):
"""
Handler "FFT CONTROLS CHANGED" messages from the View. It tells the model to re-process the fft.
message.data should contain the array [window, slices, max_peaks]
"""
self.model.reprocess_fft(* message.data)
def signal_changed(self, message):
"""
Handles "SIGNAL CHANGED" messages sent by the model. Tells the view to update itself.
message is ignored
"""
self.view.signal_changed(self.model)
def fft_changed(self, message):
"""
Handles "FFT CHANGED" messages sent by the model. Tells the view to update itself.
message is ignored
"""
self.view.fft_changed(self.model)
#! /usr/bin/python
# To change this template, choose Tools | Templates
# and open the template in the editor.
__author__="federico"
__date__ ="$Jul 15, 2011 2:20:38 PM$"
import wx, os
from wx.lib.pubsub import Publisher as pub
class FileChooser(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
# buttons / controls
path_label = wx.StaticText(self, -1, "Choose a signal file:")
self.path_ctrl = wx.TextCtrl(self)
self.open_button = wx.Button(self, -1, "...", wx.DefaultPosition, wx.Size(30,30))
self.parse_button = wx.Button(self, -1, "Parse file", wx.DefaultPosition, wx.Size(120,30))
# Bind actions to the two buttons
self.open_button.Bind(wx.EVT_BUTTON, self.open_dialog)
self.parse_button.Bind(wx.EVT_BUTTON, self.send_path_changed_message)
# sizer for the textbox and buttons
ctrls_sizer = wx.BoxSizer(wx.HORIZONTAL)
ctrls_sizer.Add(self.path_ctrl, 1, wx.EXPAND)
ctrls_sizer.Add(self.open_button, 0, wx.EXPAND)
ctrls_sizer.Add(self.parse_button, 0, wx.EXPAND)
vsizer = wx.BoxSizer(wx.VERTICAL)
vsizer.Add(path_label, 0.5, wx.EXPAND)
vsizer.Add(ctrls_sizer, 0.5, wx.EXPAND)
self.SetSizer(vsizer)
# jdgc: pa abreviar
# fasara: using os.path facilities
defaultPath = os.path.join(os.getcwd(), 'samples', 'data.txt')
self.path_ctrl.SetValue(defaultPath)
self.send_path_changed_message()
def send_path_changed_message(self, evt=None):
""" Sends a message to the Controller saying that the file path has been changed and it's ready to be reloaded.
Called right after using the '...' button and choosing a file, and also when pressing the 'Parse file' button.
"""
pub.sendMessage("FILE PATH CHANGED", self.path_ctrl.GetValue())
def open_dialog(self, evt=None):
""" Shows and controls the File Opening dialog """
prevPath = self.path_ctrl.GetValue()
if len(prevPath) > 0:
defaultDir = os.path.dirname(prevPath)
else:
defaultDir = os.getcwd()
dlg = wx.FileDialog(
self, message="Choose a file",
defaultDir=defaultDir,
defaultFile="",
wildcard="All files (*.*)|*.*",
style=wx.OPEN
)
# Show the dialog and retrieve the user response. If it is the OK response,
# Parse the data.
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
self.path_ctrl.SetValue(path)
self.send_path_changed_message()
dlg.Destroy()
import ConfigParser
import string
from wx.lib.pubsub import Publisher as pub
from SignalsProcessing.Signal import Signal
class Model:
""" Holds all the pertinent information regarding the signals.
It also caches the information so it isn't re-calculated unnecesarily (for example when re-dimensioning windows)
It communicates with the Controller by emiting messages.
"""
FFT_METHODS = ['process_gain', 'noise_floor', 'SFDR', 'SINAD', 'THD', 'SNR', 'ENOB']
def __init__(self):
self.signal = None
def parse_file(self, path, max_peaks=0, dB = None, time_domain = None):
""" Invoked when a new file needs to be parsed. Will raise an exception if the file contains syntax errors
Emits the message 'SIGNAL CHANGED' if the file was cached succesfully
"""
self.signal = None
print "parse file"
#try:
if True:
config = ConfigParser.RawConfigParser()
config.read(path)
nbits = config.getint('SIGNAL', 'nbits')
rate = config.getint('SIGNAL', 'rate')
dataString = config.get('SIGNAL', 'data').split('\n')
data = map(string.atoi, dataString)
print "setting up signal"
self.signal = Signal(nbits, rate, data)
print "signal done"
if True:
#finally:
self.cache_signal()
pub.sendMessage("SIGNAL CHANGED")
def reprocess_fft(self, window, slices, max_peaks):
""" Invoked when the FFT controls on tab 3 have been changed. re-calculates fft
Emits the message 'FFT CHANGED' when done calculating
"""
#if self.signal is None:
# self.fft_signal = None
#else:
# print 'window = ', window
# self.fft_signal = self.signal.FFT(slices, window)
self.cache_fft_signal(max_peaks)
pub.sendMessage("FFT CHANGED")
def cache_signal(self):
""" Invokes all methods in Signal and caches their result for later use (mainly window resizing)
Resets values to safe values (0, []) if there was an error while processing the signal definition file
"""
print "do nothing"
return
if self.signal is None:
self.data = []
self.INL, self.max_INL = [], 0
self.DNL, self.max_DNL = [], 0
self.histogram, self.ideal_histogram = [], []
else:
self.data = self.signal.data
self.INL, self.max_INL = self.signal.INL()
self.DNL, self.max_DNL = self.signal.DNL()
self.histogram, self.ideal_histogram = self.signal.histogram(), self.signal.ideal_histogram()
def cache_fft_signal(self, max_peaks = 0):
""" Invokes all methods in FFTSignal and caches their result for later use (mainly window resizing)
Resets values to safe values (0, []) if there was an error while processing the signal definition file
"""
print "do nothing"
return
if self.fft_signal is None:
self.fft = []
self.harmonic_peaks = []
for name in Model.FFT_METHODS:
setattr(self, name, 0)
else:
self.fft = self.fft_signal.fft
self.harmonic_peaks = self.fft_signal.harmonic_peaks(max_peaks)
for name in Model.FFT_METHODS:
setattr( self, name, getattr(self.fft_signal, name)() )
import wx
from wx.lib.pubsub import Publisher as pub
import matplotlib
matplotlib.use('WXagg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2Wx as Toolbar
from matplotlib.figure import Figure
#FIXME remove when unused
from numpy import arange, sin, pi, cos, hstack
__doc__ = """
This module contains the definitions of all the graphs used in the app.
It is the only one interfacing with matplotlib.
"""
class Signal(FigureCanvas):
""" Represents the raw data from a Signal, right after being loaded from a file (Tab 1)
"""
def __init__(self, parent):
self.figure = Figure((5,3)) # 5,3 is the initial figure
FigureCanvas.__init__(self, parent, -1, self.figure)
self.axes = self.figure.add_subplot(111)
self.scrollEventCID = self.mpl_connect('scroll_event', self.zoom)
def zoom(self, event):
print "Zoom"
""" Specifies what has to be done if the signal is changed (the data has to be re-plotted)
"""
def update(self, data):
self.axes.clear()
self.axes.plot(arange(0,len(data),1) ,data, '-')
self.draw()
class DNL(Signal):
""" Represents the DNL plot
"""
def __init__(self, parent):
Signal.__init__(self, parent)
class INL(Signal):
""" Represents the INL plot
"""
def __init__(self, parent):
Signal.__init__(self, parent)
class Histogram(Signal):
""" Represents the histogram plot
"""
def __init__(self, parent):
Signal.__init__(self, parent)
""" Specifies what has to be done if the signal is changed (the data has to be re-plotted)
"""
def update(self, histogram, ideal_histogram):
self.axes.clear()
self.axes.plot(arange(0,len(histogram),1), histogram, '.')
self.axes.plot(arange(0,len(ideal_histogram),1), ideal_histogram, '.')
self.draw()
class FFT(Signal):
""" Represents the FFT plot
"""
def __init__(self, parent):
Signal.__init__(self, parent)
def update(self, fft, harmonic_peaks, maxPeak, sfdrPeak, noiseFloor):
self.axes.clear()
self.axes.grid(color='black', linestyle='-', linewidth=1, alpha=0.5)
self.axes.vlines(arange(0,len(fft),1), 0, fft)
if len(harmonic_peaks) != 0:
thindex = hstack(map(lambda x: x[0], harmonic_peaks))
thvalues = hstack(map(lambda x: x[2], harmonic_peaks))
self.axes.plot(thindex , thvalues, '.')
# plot SFDR
self.axes.axhline(maxPeak)
self.axes.axhline(sfdrPeak)
self.axes.axhspan(sfdrPeak, maxPeak, facecolor='blue', alpha=0.15)
# noise floor
self.axes.axhline(noiseFloor)
self.axes.axhspan(0, noiseFloor, facecolor='gray', alpha=0.15)
self.draw()
# To change this template, choose Tools | Templates
# and open the template in the editor.
__author__="federico"
__date__ ="$Jul 8, 2011 3:48:20 PM$"
import wx
from wx.lib.pubsub import Publisher as pub
class SliceChooser(wx.Panel):
def __init__(self, windows):
wx.Panel.__init__(self, windows)
self.slices_label = wx.StaticText(self, -1, "Slices:")
self.slices_ctrl = wx.SpinCtrl(self, -1, "1", wx.DefaultPosition, (100,30))
self.slices_ctrl.SetRange(1,10)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.vsizer.Add(self.slices_label, 0.5, wx.EXPAND)
self.vsizer.Add(self.slices_ctrl, 0.5, wx.EXPAND)
def get(self):
return self.slices_ctrl.Get_Value()
\ No newline at end of file
This diff is collapsed.
# To change this template, choose Tools | Templates
# and open the template in the editor.
__author__="federico"
__date__ ="$Jul 8, 2011 3:48:20 PM$"
import wx
from wx.lib.pubsub import Publisher as pub
from WindowParameter import WindowParameter
class WindowPicker(wx.Panel):
def __init__(self, windows):
wx.Panel.__init__(self, windows)
# create a DropBox
self.windowLabel = wx.StaticText( self, -1, "Window:")
self.windows = windows
self.allWindows = windows.keys()
self.currentWindow = self.allWindows[0]
self.windowBox = wx.ComboBox(self, 500, self.currentWindow, wx.DefaultPosition, (120,30),
allWindows, wx.CB_DROPDOWN | wx.CB_READONLY | wx.CB_SORT )
self.slices_label = wx.StaticText(self, -1, "Slices:")
self.slices_ctrl = wx.SpinCtrl(self, -1, "1", wx.DefaultPosition, (100,30))
self.slices_ctrl.SetRange(1,10)
self.spinboxes = []
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.vsizer.Add(self.windowLabel, 0.5, wx.EXPAND)
self.vsizer.Add(self.windowBox, 0.5, wx.EXPAND)
self.vsizer.Add(self.windowBox, 0.5, wx.EXPAND)
self.updateView()
def updateView(self):
if self.windowBox.GetValue() == self.currentWindow:
return
self.currentWindow = self.windowBox.GetValue()
window = self.windows[self.currentWindow]
# hide and show spinners accordingly
for i in self.spinboxes:
self.vsizer.Remove(i)
self.spinboxes = [WindowParameter(self, i, window) for i in window.parameters]
for i in self.spinboxes:
self.vsizer.Add(i, 0.5, wx.EXPAND)
def get(self):
window = self.windows[self.currentWindow]
parameters = [i.get() for i in self.spinboxes]
return window, parameters
\ No newline at end of file
# To change this template, choose Tools | Templates
# and open the template in the editor.
__author__="federico"
__date__ ="$Jul 8, 2011 4:42:35 PM$"
import wx
from wx.lib.pubsub import Publisher as pub
class WindowParameter(wx.Panel):
def __init__(self, parent, name, window):
wx.Panel.__init__(self, parent)
self.label = wx.StaticText(self, -1, "%s:" % name)
self.spin = wx.SpinCtrl(self, -1, "1", wx.DefaultPosition, (100,30))
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.vsizer.Add(self.label, 0.5, wx.EXPAND)
self.vsizer.Add(self.spin, 0.5, wx.EXPAND)
self.SetSizer(vsizer)
def get(self):
return self.spin.GetValue()
__author__="federico"
__date__ ="$Jul 11, 2011 5:22:02 PM$"
import wxversion
# We need at least version 2.8
wxversion.ensureMinimal('2.8')
def start():
import wx
import Controller
# Create an application
app = wx.App(False)
# Create our controller and bind it to the app
controller = Controller.Controller(app)
# Start the main loop
app.MainLoop()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment