summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/python
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2013-02-28 14:38:40 -0500
committerTom Rondeau <trondeau@vt.edu>2013-02-28 14:38:40 -0500
commit9f29e51f2945f355b43f3012da43e37dcd95f6b4 (patch)
treebcc71c8975379c107bb6e94da944292a5ee9a03a /gnuradio-core/src/python
parent7afefc484137bf0bed7ab9a7ed86017c117d6a35 (diff)
parent2f55d7dfc33e8d990e44c5bbb7c6d2fbdaddd563 (diff)
Merge branch 'next' into perf_monitor
Diffstat (limited to 'gnuradio-core/src/python')
-rw-r--r--gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py683
-rwxr-xr-xgnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor66
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_pack_k_bits.py67
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_regenerate.py90
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py57
5 files changed, 325 insertions, 638 deletions
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py b/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
index 27858b575b..f797271970 100644
--- a/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012 Free Software Foundation, Inc.
+# Copyright 2012,2013 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -21,6 +21,7 @@
#
from gnuradio import gr
+from gnuradio import blocks
import sys, time
try:
@@ -31,34 +32,68 @@ except ImportError:
print "Error: Program requires PyQt4 and gr-qtgui."
sys.exit(1)
-class GrDataPlotterC(gr.top_block):
- def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
+class GrDataPlotParent(gr.top_block, QtGui.QWidget):
+ # Setup signals
+ plotupdated = QtCore.pyqtSignal(QtGui.QWidget)
+
+ def __init__(self, name, rate, pmin=None, pmax=None):
gr.top_block.__init__(self)
+ QtGui.QWidget.__init__(self, None)
- self._stripchart = stripchart
self._name = name
self._npts = 500
- samp_rate = 1.0
+ self._rate = rate
+ self.knobnames = [name,]
+
+ self.layout = QtGui.QVBoxLayout()
+ self.setLayout(self.layout)
+
+ self.setAcceptDrops(True)
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ def _setup(self, nconnections):
+ self.stop()
+ self.wait()
- self.src = gr.vector_source_c([])
- self.thr = gr.throttle(gr.sizeof_gr_complex, rate)
- self.snk = qtgui.time_sink_c(self._npts, samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ if(self.layout.count() > 0):
+ # Remove and disconnect. Making sure no references to snk
+ # remain so that the plot gets deleted.
+ self.layout.removeWidget(self.py_window)
+ self.disconnect(self.thr, (self.snk, 0))
+ self.disconnect(self.src[0], self.thr)
+ for n in xrange(1, self._ncons):
+ self.disconnect(self.src[n], (self.snk,n))
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._ncons = nconnections
+ self._data_len = self._ncons*[0,]
- self.snk.set_line_label(0, "Real")
- self.snk.set_line_label(1, "Imag")
+ self.thr = blocks.throttle(self._datasize, self._rate)
+ self.snk = self.get_qtsink()
+
+ self.connect(self.thr, (self.snk, 0))
+
+ self._last_data = []
+ self.src = []
+ for n in xrange(self._ncons):
+ self.set_line_label(n, self.knobnames[n])
+
+ self._last_data.append(int(self._npts)*[0,])
+ self.src.append(self.get_vecsource())
+
+ if(n == 0):
+ self.connect(self.src[n], self.thr)
+ else:
+ self.connect(self.src[n], (self.snk,n))
self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ self.layout.addWidget(self.py_window)
+
def __del__(self):
pass
+ def close(self):
+ self.snk.close()
+
def qwidget(self):
return self.py_window
@@ -68,162 +103,172 @@ class GrDataPlotterC(gr.top_block):
def semilogy(self, en=True):
self.snk.enable_semilogy(en)
- def stem(self, en=True):
- self.snk.enable_stem_plot(en)
+ def dragEnterEvent(self, e):
+ e.acceptProposedAction()
+
+ def dropEvent(self, e):
+ if(e.mimeData().hasFormat("text/plain")):
+ data = str(e.mimeData().text())
+
+ #"PlotData:{0}:{1}".format(tag, iscomplex)
+ datalst = data.split(":::")
+ tag = datalst[0]
+ name = datalst[1]
+ cpx = datalst[2] != "0"
+
+ if(tag == "PlotData" and cpx == self._iscomplex):
+ self.knobnames.append(name)
+
+ # create a new qwidget plot with the new data stream.
+ self._setup(len(self.knobnames))
+
+ # emit that this plot has been updated with a new qwidget.
+ self.plotupdated.emit(self)
+
+ e.acceptProposedAction()
+
+ def data_to_complex(self, data):
+ if(self._iscomplex):
+ data_r = data[0::2]
+ data_i = data[1::2]
+ data = [complex(r,i) for r,i in zip(data_r, data_i)]
+ return data
def update(self, data):
# Ask GUI if there has been a change in nsamps
- npts = self.snk.nsamps()
+ npts = self.get_npts()
if(self._npts != npts):
# Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
+ for n in xrange(self._ncons):
+ if(npts < self._npts):
+ if(self._data_len[n] < npts):
+ self._last_data[n] = self._last_data[n][0:npts]
+ else:
+ self._last_data[n] = self._last_data[n][self._data_len[n]-npts:self._data_len[n]]
+ self._data_len[n] = npts
else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
+ self._last_data[n] += (npts - self._npts)*[0,]
self._npts = npts
self.snk.reset()
-
+
if(self._stripchart):
# Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ for n in xrange(self._ncons):
+ if(type(data[n]) == list):
+ data[n] = self.data_to_complex(data[n])
+ if(len(data[n]) > self._npts):
+ self.src[n].set_data(data[n])
+ self._last_data[n] = data[n][-self._npts:]
+ else:
+ newdata = self._last_data[n][-(self._npts-len(data)):]
+ newdata += data[n]
+ self.src[n].set_data(newdata)
+ self._last_data[n] = newdata
+
+ else: # single value update
+ if(self._iscomplex):
+ data[n] = complex(data[n][0], data[n][1])
+ if(self._data_len[n] < self._npts):
+ self._last_data[n][self._data_len[n]] = data[n]
+ self._data_len[n] += 1
+ else:
+ self._last_data[n] = self._last_data[n][1:]
+ self._last_data[n].append(data[n])
+ self.src[n].set_data(self._last_data[n])
else:
- if(type(data) != list):
- data = [data,]
- self.src.set_data(data)
+ for n in xrange(self._ncons):
+ if(type(data[n]) != list):
+ data[n] = [data[n],]
+ data[n] = self.data_to_complex(data[n])
+ self.src[n].set_data(data[n])
+
+
-class GrDataPlotterF(gr.top_block):
+class GrDataPlotterC(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
- gr.top_block.__init__(self)
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
self._stripchart = stripchart
- self._name = name
- self._npts = 500
- samp_rate = 1.0
+ self._datasize = gr.sizeof_gr_complex
+ self._iscomplex = True
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ self._setup(1)
- self.src = gr.vector_source_f([])
- self.thr = gr.throttle(gr.sizeof_float, rate)
- self.snk = qtgui.time_sink_f(self._npts, samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ def stem(self, en=True):
+ self.snk.enable_stem_plot(en)
- self.connect(self.src, self.thr, (self.snk, 0))
+ def get_qtsink(self):
+ snk = qtgui.time_sink_c(self._npts, 1.0,
+ self._name, self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ def get_vecsource(self):
+ return gr.vector_source_c([])
- def __del__(self):
- pass
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
- def qwidget(self):
- return self.py_window
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(2*n+0, "Re{" + self.knobnames[n] + "}")
+ self.snk.set_line_label(2*n+1, "Im{" + self.knobnames[n] + "}")
- def name(self):
- return self._name
- def semilogy(self, en=True):
- self.snk.enable_semilogy(en)
+class GrDataPlotterF(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- def stem(self, en=True):
- self.snk.enable_stem_plot(en)
+ self._stripchart = stripchart
+ self._datasize = gr.sizeof_float
+ self._iscomplex = False
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = self.snk.nsamps()
- if(self._npts != npts):
+ self._setup(1)
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
+ def stem(self, en=True):
+ self.snk.enable_stem_plot(en)
- if(self._stripchart):
- # Update the plot data depending on type
- if(type(data) == list):
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
- else:
- if(type(data) != list):
- data = [data,]
- self.src.set_data(data)
+ def get_qtsink(self):
+ snk = qtgui.time_sink_f(self._npts, 1.0,
+ self._name, self._ncons)
+ snk.enable_autoscale(True)
+ return snk
+
+ def get_vecsource(self):
+ return gr.vector_source_f([])
+
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
+
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
-class GrDataPlotterConst(gr.top_block):
- def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
-
- self._name = name
- self._npts = 500
- samp_rate = 1.0
- self._last_data = self._npts*[0,]
- self._data_len = 0
-
- self.src = gr.vector_source_c([])
- self.thr = gr.throttle(gr.sizeof_gr_complex, rate)
- self.snk = qtgui.const_sink_c(self._npts,
- self._name, 1)
- self.snk.enable_autoscale(True)
+class GrDataPlotterConst(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._datasize = gr.sizeof_gr_complex
+ self._stripchart = False
+ self._iscomplex = True
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ self._setup(1)
- def __del__(self):
- pass
+ def get_qtsink(self):
+ snk = qtgui.const_sink_c(self._npts,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- def qwidget(self):
- return self.py_window
+ def get_vecsource(self):
+ return gr.vector_source_c([])
- def name(self):
- return self._name
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
def scatter(self, en=True):
if(en):
@@ -231,327 +276,133 @@ class GrDataPlotterConst(gr.top_block):
else:
self.snk.set_line_style(0, 1)
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = self.snk.nsamps()
- if(self._npts != npts):
-
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
-class GrDataPlotterPsdC(gr.top_block):
+class GrDataPlotterPsdC(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self._name = name
- self._samp_rate = 1.0
- self._fftsize = 2048
+ self._datasize = gr.sizeof_gr_complex
+ self._stripchart = True
+ self._iscomplex = True
+
+ self._npts = 2048
self._wintype = gr.firdes.WIN_BLACKMAN_hARRIS
self._fc = 0
-
- self._last_data = self._fftsize*[0,]
- self._data_len = 0
- self.src = gr.vector_source_c([])
- self.thr = gr.throttle(gr.sizeof_gr_complex, rate)
- self.snk = qtgui.freq_sink_c(self._fftsize, self._wintype,
- self._fc, self._samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ self._setup(1)
- self.connect(self.src, self.thr, (self.snk, 0))
+ def get_qtsink(self):
+ snk = qtgui.freq_sink_c(self._npts, self._wintype,
+ self._fc, 1.0,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
-
- def __del__(self):
- pass
+ def get_vecsource(self):
+ return gr.vector_source_c([])
- def qwidget(self):
- return self.py_window
+ def get_npts(self):
+ self._npts = self.snk.fft_size()
+ return self._npts
- def name(self):
- return self._name
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- fftsize = self.snk.fft_size()
- if(self._fftsize != fftsize):
-
- # Adjust buffers to accomodate new settings
- if(fftsize < self._fftsize):
- if(self._data_len < fftsize):
- self._last_data = self._last_data[0:fftsize]
- else:
- self._last_data = self._last_data[self._data_len-fftsize:self._data_len]
- self._data_len = fftsize
- else:
- self._last_data += (fftsize - self._fftsize)*[0,]
- self._fftsize = fftsize
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._fftsize):
- self.src.set_data(data)
- self._last_data = data[-self._fftsize:]
- else:
- newdata = self._last_data[-(self._fftsize-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._fftsize):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
-class GrDataPlotterPsdF(gr.top_block):
+class GrDataPlotterPsdF(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self._name = name
- self._samp_rate = 1.0
- self._fftsize = 2048
+ self._datasize = gr.sizeof_float
+ self._stripchart = True
+ self._iscomplex = False
+
+ self._npts = 2048
self._wintype = gr.firdes.WIN_BLACKMAN_hARRIS
self._fc = 0
-
- self._last_data = self._fftsize*[0,]
- self._data_len = 0
- self.src = gr.vector_source_f([])
- self.thr = gr.throttle(gr.sizeof_float, rate)
- self.snk = qtgui.freq_sink_f(self._fftsize, self._wintype,
- self._fc, self._samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ self._setup(1)
- self.connect(self.src, self.thr, (self.snk, 0))
+ def get_qtsink(self):
+ snk = qtgui.freq_sink_f(self._npts, self._wintype,
+ self._fc, 1.0,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
-
- def __del__(self):
- pass
+ def get_vecsource(self):
+ return gr.vector_source_f([])
- def qwidget(self):
- return self.py_window
+ def get_npts(self):
+ self._npts = self.snk.fft_size()
+ return self._npts
- def name(self):
- return self._name
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- fftsize = self.snk.fft_size()
- if(self._fftsize != fftsize):
-
- # Adjust buffers to accomodate new settings
- if(fftsize < self._fftsize):
- if(self._data_len < fftsize):
- self._last_data = self._last_data[0:fftsize]
- else:
- self._last_data = self._last_data[self._data_len-fftsize:self._data_len]
- self._data_len = fftsize
- else:
- self._last_data += (fftsize - self._fftsize)*[0,]
- self._fftsize = fftsize
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._fftsize):
- self.src.set_data(data)
- self._last_data = data[-self._fftsize:]
- else:
- newdata = self._last_data[-(self._fftsize-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._fftsize):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
-
-class GrTimeRasterF(gr.top_block):
+class GrTimeRasterF(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
-
- self._name = name
- self._npts = 100
- self._rows = 100
- samp_rate = 1.0
-
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self.src = gr.vector_source_f([])
- self.thr = gr.throttle(gr.sizeof_float, rate)
- self.snk = qtgui.time_raster_sink_f(samp_rate, self._npts, self._rows,
- [], [], self._name, 1)
+ self._npts = 10
+ self._rows = 40
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._datasize = gr.sizeof_float
+ self._stripchart = False
+ self._iscomplex = False
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ self._setup(1)
- def __del__(self):
- pass
+ def get_qtsink(self):
+ snk = qtgui.time_raster_sink_f(1.0, self._npts, self._rows,
+ [], [], self._name,
+ self._ncons)
+ return snk
- def qwidget(self):
- return self.py_window
+ def get_vecsource(self):
+ return gr.vector_source_f([])
- def name(self):
- return self._name
+ def get_npts(self):
+ self._npts = self.snk.num_cols()
+ return self._npts
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = int(self.snk.num_cols())
- if(self._npts != npts):
-
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
-class GrTimeRasterB(gr.top_block):
+class GrTimeRasterB(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
-
- self._name = name
- self._npts = 100
- self._rows = 100
- samp_rate = 1.0
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ self._npts = 10
+ self._rows = 40
- self.src = gr.vector_source_b([])
- self.thr = gr.throttle(gr.sizeof_char, rate)
- self.snk = qtgui.time_raster_sink_b(samp_rate, self._npts, self._rows,
- [], [], self._name, 1)
+ self._datasize = gr.sizeof_char
+ self._stripchart = False
+ self._iscomplex = False
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._setup(1)
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ def get_qtsink(self):
+ snk = qtgui.time_raster_sink_b(1.0, self._npts, self._rows,
+ [], [], self._name,
+ self._ncons)
+ return snk
- def __del__(self):
- pass
-
- def qwidget(self):
- return self.py_window
-
- def name(self):
- return self._name
+ def get_vecsource(self):
+ return gr.vector_source_b([])
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = self.snk.num_cols()
- if(self._npts != npts):
+ def get_npts(self):
+ self._npts = self.snk.num_cols()
+ return self._npts
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
class GrDataPlotterValueTable:
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor b/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
index 60a810b04e..e71cd92ab7 100755
--- a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012 Free Software Foundation, Inc.
+# Copyright 2012,2013 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -24,7 +24,7 @@ from gnuradio import gr, ctrlport
from PyQt4 import QtCore,Qt
import PyQt4.QtGui as QtGui
-import sys, time
+import os, sys, time
import Ice
from gnuradio.ctrlport.IceRadioClient import *
@@ -55,7 +55,7 @@ class MAINWindow(QtGui.QMainWindow):
def __init__(self, radio, port, interface):
super(MAINWindow, self).__init__()
- self.updateRate = 2000;
+ self.updateRate = 1000;
self.conns = []
self.plots = []
self.knobprops = []
@@ -83,6 +83,11 @@ class MAINWindow(QtGui.QMainWindow):
icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" )
self.setWindowIcon(icon)
+ # Locally turn off ControlPort export from GR. This prevents
+ # our GR-based plotters from launching their own ControlPort
+ # instance (and possibly causing a port collision if one has
+ # been specified).
+ os.environ['GR_CONF_CONTROLPORT_ON'] = 'False'
def setUpdateRate(self,nur):
self.updateRate = int(nur);
@@ -217,17 +222,55 @@ class MAINWindow(QtGui.QMainWindow):
else:
self.newPlotPsdC(tag, uid, title)
+ def startDrag(self, e):
+ drag = QtGui.QDrag(self)
+ mime_data = QtCore.QMimeData()
+
+ tag = str(e.text(0))
+ tree = e.treeWidget().parent()
+ knobprop = self.knobprops[tree.uid][tag]
+ disp = knobprop.display
+ iscomplex = (disp & gr.DISPOPTCPLX) or (disp & gr.DISPXY)
+
+ if(disp != gr.DISPNULL):
+ data = "PlotData:::{0}:::{1}".format(tag, iscomplex)
+ else:
+ data = "OtherData:::{0}:::{1}".format(tag, iscomplex)
+
+ mime_data.setText(data)
+ drag.setMimeData(mime_data)
+
+ drop = drag.start()
+
def createPlot(self, plot, uid, title):
plot.start()
self.plots[uid].append(plot)
- self.mdiArea.addSubWindow(plot.qwidget())
- plot.qwidget().setWindowTitle("{0}: {1}".format(title, plot.name()))
+ self.mdiArea.addSubWindow(plot)
+ plot.setWindowTitle("{0}: {1}".format(title, plot.name()))
self.connect(plot.qwidget(),
QtCore.SIGNAL('destroyed(QObject*)'),
self.destroyPlot)
- plot.qwidget().show()
+ # when the plot is updated via drag-and-drop, we need to be
+ # notified of the new qwidget that's created so we can
+ # properly destroy it.
+ plot.plotupdated.connect(self.plotUpdated)
+
+ plot.show()
+
+ def plotUpdated(self, q):
+ # the plot has been updated with a new qwidget; make sure this
+ # gets dies to the destroyPlot function.
+ for i, plots in enumerate(self.plots):
+ for p in plots:
+ if(p == q):
+ #plots.remove(p)
+ #plots.append(q)
+ self.connect(q.qwidget(),
+ QtCore.SIGNAL('destroyed(QObject*)'),
+ self.destroyPlot)
+ break
def destroyPlot(self, obj):
for plots in self.plots:
@@ -275,7 +318,9 @@ class MAINWindow(QtGui.QMainWindow):
def update(self, knobs, uid):
#sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys()))
for plot in self.plots[uid]:
- data = knobs[plot.name()].value
+ data = []
+ for n in plot.knobnames:
+ data.append(knobs[n].value)
plot.update(data)
plot.stop()
plot.wait()
@@ -639,7 +684,7 @@ class MForm(QtGui.QWidget):
self.table.treeWidget.setEditTriggers(QtGui.QAbstractItemView.EditKeyPressed)
self.table.treeWidget.setSortingEnabled(True)
self.table.treeWidget.setDragEnabled(True)
-
+
# add things to layouts
self.horizontalLayout.addWidget(self.table.treeWidget)
@@ -657,6 +702,11 @@ class MForm(QtGui.QWidget):
QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'),
self.parent.newSub);
+ # Allow drag/drop event from table item to plotter
+ self.connect(self.table.treeWidget,
+ QtCore.SIGNAL('itemPressed(QTreeWidgetItem*, int)'),
+ self.parent.startDrag)
+
def openMenu(self, pos):
index = self.table.treeWidget.selectedIndexes()
item = self.table.treeWidget.itemFromIndex(index[0])
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pack_k_bits.py b/gnuradio-core/src/python/gnuradio/gr/qa_pack_k_bits.py
deleted file mode 100755
index 25fc5e9fcc..0000000000
--- a/gnuradio-core/src/python/gnuradio/gr/qa_pack_k_bits.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2006,2010 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-#
-
-from gnuradio import gr, gr_unittest
-import random
-
-class test_pack(gr_unittest.TestCase):
-
- def setUp(self):
- self.tb = gr.top_block ()
-
- def tearDown(self):
- self.tb = None
-
- def test_001(self):
- src_data = (1,0,1,1,0,1,1,0)
- expected_results = (1,0,1,1,0,1,1,0)
- src = gr.vector_source_b(src_data,False)
- op = gr.pack_k_bits_bb(1)
- dst = gr.vector_sink_b()
- self.tb.connect(src, op, dst)
- self.tb.run()
- self.assertEqual(expected_results, dst.data())
-
- def test_002(self):
- src_data = (1,0,1,1,0,0,0,1)
- expected_results = ( 2, 3, 0, 1)
- src = gr.vector_source_b(src_data,False)
- op = gr.pack_k_bits_bb(2)
- dst = gr.vector_sink_b()
- self.tb.connect(src, op, dst)
- self.tb.run()
- #self.assertEqual(expected_results, dst.data())
- self.assertEqual(expected_results, dst.data())
-
- def test_003(self):
- src_data = expected_results = map(lambda x: random.randint(0,3), range(10));
- src = gr.vector_source_b( src_data );
- pack = gr.pack_k_bits_bb(2);
- unpack = gr.unpack_k_bits_bb(2);
- snk = gr.vector_sink_b();
- self.tb.connect(src,unpack,pack,snk);
- self.tb.run()
- self.assertEqual(list(expected_results), list(snk.data()));
-
-if __name__ == '__main__':
- gr_unittest.run(test_pack, "test_pack.xml")
-
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_regenerate.py b/gnuradio-core/src/python/gnuradio/gr/qa_regenerate.py
deleted file mode 100755
index 5aca03b777..0000000000
--- a/gnuradio-core/src/python/gnuradio/gr/qa_regenerate.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2007,2010 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-#
-
-from gnuradio import gr, gr_unittest
-import math
-
-class test_regenerate (gr_unittest.TestCase):
-
- def setUp (self):
- self.tb = gr.top_block ()
-
- def tearDown (self):
- self.tb = None
-
- def test_regen1 (self):
- tb = self.tb
-
- data = [0, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-
- expected_result = (0, 0, 0,
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
-
-
- src = gr.vector_source_b(data, False)
- regen = gr.regenerate_bb(5, 2)
- dst = gr.vector_sink_b()
-
- tb.connect (src, regen)
- tb.connect (regen, dst)
- tb.run ()
-
- dst_data = dst.data ()
-
- self.assertEqual (expected_result, dst_data)
-
- def test_regen2 (self):
- tb = self.tb
-
- data = 200*[0,]
- data[9] = 1
- data[99] = 1
-
- expected_result = 200*[0,]
- expected_result[9] = 1
- expected_result[19] = 1
- expected_result[29] = 1
- expected_result[39] = 1
-
- expected_result[99] = 1
- expected_result[109] = 1
- expected_result[119] = 1
- expected_result[129] = 1
-
- src = gr.vector_source_b(data, False)
- regen = gr.regenerate_bb(10, 3)
- dst = gr.vector_sink_b()
-
- tb.connect (src, regen)
- tb.connect (regen, dst)
- tb.run ()
-
- dst_data = dst.data ()
-
- self.assertEqual (tuple(expected_result), dst_data)
-
-
-if __name__ == '__main__':
- gr_unittest.run(test_regenerate, "test_regenerate.xml")
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py b/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py
deleted file mode 100755
index bb4e7733d4..0000000000
--- a/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2006,2010 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-#
-
-from gnuradio import gr, gr_unittest
-import random
-
-class test_unpack(gr_unittest.TestCase):
-
- def setUp(self):
- self.tb = gr.top_block ()
-
- def tearDown(self):
- self.tb = None
-
- def test_001(self):
- src_data = (1,0,1,1,0,1,1,0)
- expected_results = (1,0,1,1,0,1,1,0)
- src = gr.vector_source_b(src_data,False)
- op = gr.unpack_k_bits_bb(1)
- dst = gr.vector_sink_b()
- self.tb.connect(src, op, dst)
- self.tb.run()
- self.assertEqual(expected_results, dst.data())
-
- def test_002(self):
- src_data = ( 2, 3, 0, 1)
- expected_results = (1,0,1,1,0,0,0,1)
- src = gr.vector_source_b(src_data,False)
- op = gr.unpack_k_bits_bb(2)
- dst = gr.vector_sink_b()
- self.tb.connect(src, op, dst)
- self.tb.run()
- self.assertEqual(expected_results, dst.data())
-
-
-if __name__ == '__main__':
- gr_unittest.run(test_unpack, "test_unpack.xml")
-