2 # Copyright 2009 Free Software Foundation, Inc.
4 # This file is part of GNU Radio
6 # GNU Radio is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3, or (at your option)
11 # GNU Radio is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with GNU Radio; see the file COPYING. If not, write to
18 # the Free Software Foundation, Inc., 51 Franklin Street,
19 # Boston, MA 02110-1301, USA.
22 ##################################################
24 ##################################################
31 from constants import *
32 from gnuradio import gr #for gr.prefs
34 ##################################################
36 ##################################################
37 DEFAULT_WIN_SIZE = (600, 300)
39 ##################################################
40 # histo window control panel
41 ##################################################
42 class control_panel(wx.Panel):
44 A control panel with wx widgits to control the plotter and histo sink.
47 def __init__(self, parent):
49 Create a new control panel.
50 @param parent the wx parent window
53 wx.Panel.__init__(self, parent, style=wx.SUNKEN_BORDER)
54 control_box = wx.BoxSizer(wx.VERTICAL)
56 control_box.Add(common.LabelText(self, 'Options'), 0, wx.ALIGN_CENTER)
57 control_box.AddStretchSpacer()
59 def num_bins_cast(num):
63 num_bins_ctrl = common.TextBoxController(self, parent, NUM_BINS_KEY, cast=num_bins_cast)
64 control_box.Add(common.LabelBox(self, ' Num Bins ', num_bins_ctrl), 0, wx.EXPAND)
65 control_box.AddStretchSpacer()
67 frame_size_ctrl = common.TextBoxController(self, parent, FRAME_SIZE_KEY, cast=num_bins_cast)
68 control_box.Add(common.LabelBox(self, ' Frame Size ', frame_size_ctrl), 0, wx.EXPAND)
69 control_box.AddStretchSpacer()
71 self.run_button = common.ToggleButtonController(self, parent, RUNNING_KEY, 'Stop', 'Run')
72 control_box.Add(self.run_button, 0, wx.EXPAND)
74 self.SetSizerAndFit(control_box)
76 ##################################################
77 # histo window with plotter and control panel
78 ##################################################
79 class histo_window(wx.Panel, pubsub.pubsub):
92 pubsub.pubsub.__init__(self)
96 self.proxy(MAXIMUM_KEY, controller, maximum_key)
97 self.proxy(MINIMUM_KEY, controller, minimum_key)
98 self.proxy(NUM_BINS_KEY, controller, num_bins_key)
99 self.proxy(FRAME_SIZE_KEY, controller, frame_size_key)
100 self.proxy(MSG_KEY, controller, msg_key)
102 wx.Panel.__init__(self, parent, style=wx.SIMPLE_BORDER)
103 self.plotter = plotter.bar_plotter(self)
104 self.plotter.SetSize(wx.Size(*size))
105 self.plotter.set_title(title)
106 self.plotter.enable_point_label(True)
107 self.plotter.enable_grid_lines(False)
108 #setup the box with plot and controls
109 self.control_panel = control_panel(self)
110 main_box = wx.BoxSizer(wx.HORIZONTAL)
111 main_box.Add(self.plotter, 1, wx.EXPAND)
112 main_box.Add(self.control_panel, 0, wx.EXPAND)
113 self.SetSizerAndFit(main_box)
115 self[NUM_BINS_KEY] = self[NUM_BINS_KEY]
116 self[FRAME_SIZE_KEY] = self[FRAME_SIZE_KEY]
117 self[RUNNING_KEY] = True
121 self.subscribe(MSG_KEY, self.handle_msg)
122 self.subscribe(X_DIVS_KEY, self.update_grid)
123 self.subscribe(Y_DIVS_KEY, self.update_grid)
125 def handle_msg(self, msg):
127 Handle the message from the fft sink message queue.
128 @param msg the frame as a character array
130 if not self[RUNNING_KEY]: return
131 #convert to floating point numbers
132 self.samples = 100*numpy.fromstring(msg, numpy.float32)[:self[NUM_BINS_KEY]] #only take first frame
133 self.plotter.set_bars(
136 color_spec=(0, 0, 1),
140 def update_grid(self):
141 if not len(self.samples): return
142 #calculate the maximum y value
143 y_off = math.ceil(numpy.max(self.samples))
144 y_off = min(max(y_off, 1.0), 100.0) #between 1% and 100%
146 self.plotter.set_x_grid(
147 self[MINIMUM_KEY], self[MAXIMUM_KEY],
148 common.get_clean_num((self[MAXIMUM_KEY] - self[MINIMUM_KEY])/self[X_DIVS_KEY]),
150 self.plotter.set_x_label('Counts')
152 self.plotter.set_y_grid(0, y_off, y_off/self[Y_DIVS_KEY])
153 self.plotter.set_y_label('Frequency', '%')
154 self.plotter.update()