diff options
Diffstat (limited to 'gnuradio-runtime/python/gnuradio/ctrlport')
7 files changed, 355 insertions, 279 deletions
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py b/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py index e1fbf97337..a57759b3d1 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py @@ -32,6 +32,7 @@ ControlPort client application for all transports. """ + class GNURadioControlPortClient(object): """ Constructor for creating a ControlPort connection to a specified host / port @@ -62,6 +63,7 @@ class GNURadioControlPortClient(object): such as QtGui.QApplication.exec_ """ + def __init__(self, host=None, port=None, rpcmethod='thrift', callback=None, blockingcallback=None): self.client = None diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py b/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py index f363393c36..ae3857d2f9 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py @@ -13,7 +13,9 @@ from gnuradio import gr from gnuradio import blocks from gnuradio import filter, fft from gnuradio.ctrlport.GNURadio import ControlPort -import sys, time, struct +import sys +import time +import struct try: from gnuradio import qtgui @@ -23,6 +25,7 @@ except ImportError: print("Error: Program requires PyQt5 and gr-qtgui.") sys.exit(1) + class GrDataPlotParent(gr.top_block, Qt.QWidget): # Setup signals plotupdated = QtCore.pyqtSignal(Qt.QWidget) @@ -34,7 +37,7 @@ class GrDataPlotParent(gr.top_block, Qt.QWidget): self._name = name self._npts = 500 self._rate = rate - self.knobnames = [name,] + self.knobnames = [name, ] self.layout = Qt.QVBoxLayout() self.setLayout(self.layout) @@ -52,10 +55,10 @@ class GrDataPlotParent(gr.top_block, Qt.QWidget): self.disconnect(self.thr, (self.snk, 0)) self.disconnect(self.src[0], self.thr) for n in range(1, self._ncons): - self.disconnect(self.src[n], (self.snk,n)) + self.disconnect(self.src[n], (self.snk, n)) self._ncons = nconnections - self._data_len = self._ncons*[0,] + self._data_len = self._ncons * [0, ] self.thr = blocks.throttle(self._datasize, self._rate) self.snk = self.get_qtsink() @@ -67,13 +70,13 @@ class GrDataPlotParent(gr.top_block, Qt.QWidget): for n in range(self._ncons): self.set_line_label(n, self.knobnames[n]) - self._last_data.append(int(self._npts)*[0,]) + 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.connect(self.src[n], (self.snk, n)) self.py_window = sip.wrapinstance(self.snk.qwidget(), Qt.QWidget) @@ -122,7 +125,7 @@ class GrDataPlotParent(gr.top_block, Qt.QWidget): 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)] + data = [complex(r, i) for r, i in zip(data_r, data_i)] return data def update(self, data): @@ -136,10 +139,11 @@ class GrDataPlotParent(gr.top_block, Qt.QWidget): 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._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[n] += (npts - self._npts)*[0,] + self._last_data[n] += (npts - self._npts) * [0, ] self._npts = npts self.snk.reset() @@ -152,12 +156,13 @@ class GrDataPlotParent(gr.top_block, Qt.QWidget): 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 = 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 + else: # single value update if(self._iscomplex): data[n] = complex(data[n][0], data[n][1]) if(self._data_len[n] < self._npts): @@ -170,12 +175,11 @@ class GrDataPlotParent(gr.top_block, Qt.QWidget): else: for n in range(self._ncons): if(type(data[n]) != list): - data[n] = [data[n],] + data[n] = [data[n], ] data[n] = self.data_to_complex(data[n]) self.src[n].set_data(data[n]) - class GrDataPlotterC(GrDataPlotParent): def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False): GrDataPlotParent.__init__(self, name, rate, pmin, pmax) @@ -203,8 +207,8 @@ class GrDataPlotterC(GrDataPlotParent): return self._npts 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] + "}") + self.snk.set_line_label(2 * n + 0, "Re{" + self.knobnames[n] + "}") + self.snk.set_line_label(2 * n + 1, "Im{" + self.knobnames[n] + "}") class GrDataPlotterF(GrDataPlotParent): @@ -366,6 +370,7 @@ class GrTimeRasterF(GrDataPlotParent): def set_line_label(self, n, name): self.snk.set_line_label(n, self.knobnames[n]) + class GrTimeRasterB(GrDataPlotParent): def __init__(self, name, rate, pmin=None, pmax=None): GrDataPlotParent.__init__(self, name, rate, pmin, pmax) @@ -404,7 +409,7 @@ class GrDataPlotterValueTable(object): self.uid = uid self.treeWidget = Qt.QTreeWidget(parent) self.treeWidget.setColumnCount(len(headers)) - self.treeWidget.setGeometry(x,y,xsize,ysize) + self.treeWidget.setGeometry(x, y, xsize, ysize) self.treeWidget.setHeaderLabels(headers) self.treeWidget.resizeColumnToContents(0) @@ -432,19 +437,19 @@ class GrDataPlotterValueTable(object): descr = str(knobprops[itemKey].description) if(type(v) == ControlPort.complex): - v = v.re + v.im*1j + v = v.re + v.im * 1j # If it's a byte stream, Python thinks it's a string. # Unpack and convert to floats for plotting. # Ignore the edge list knob if it's being exported elif(type(v) == str and itemKey.find('probe2_b') == 0): - v = struct.unpack(len(v)*'b', v) + v = struct.unpack(len(v) * 'b', v) # Convert the final value to a string for displaying v = str(v) if (item.text(1) != v or item.text(2) != units or - item.text(3) != descr): + item.text(3) != descr): item.setText(1, v) item.setText(2, units) @@ -458,20 +463,21 @@ class GrDataPlotterValueTable(object): if k not in foundKeys: v = knobs[k].value if(type(v) == ControlPort.complex): - v = v.re + v.im*1j + v = v.re + v.im * 1j # If it's a byte stream, Python thinks it's a string. # Unpack and convert to floats for plotting. # Ignore the edge list knob if it's being exported elif(type(v) == str and k.find('probe2_b') == 0): - v = struct.unpack(len(v)*'b', v) + v = struct.unpack(len(v) * 'b', v) item = Qt.QTreeWidgetItem([k, str(v), - knobprops[k].units, knobprops[k].description]) + knobprops[k].units, knobprops[k].description]) self.treeWidget.addTopLevelItem(item) # Remove items currently in tree that are not in the knob list. for itemKey in deleteKeys: - qtwiList = self.treeWidget.findItems(itemKey, Qt.Qt.MatchFixedString) + qtwiList = self.treeWidget.findItems( + itemKey, Qt.Qt.MatchFixedString) if (len(qtwiList) > 1): raise Exception('More than one item with key %s in tree' % itemKey) diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py index cfc8ce0734..fa15a1e7df 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py @@ -18,8 +18,8 @@ Args: RPCMethods = {'thrift': 'Apache Thrift', - #'ice': 'Zeroc ICE' - } + # 'ice': 'Zeroc ICE' + } """ @@ -62,14 +62,17 @@ Args: host: hostname of the connection """ + class RPCConnection(object): def __init__(self, method, port, host=None): (self.method, self.port) = (method, port) - if host is None: self.host = '127.0.0.1' - else: self.host = host + if host is None: + self.host = '127.0.0.1' + else: + self.host = host def __str__(self): - return "%s connection on %s:%s"%(self.getName(), self.getHost(), self.getPort()) + return "%s connection on %s:%s" % (self.getName(), self.getHost(), self.getPort()) def getName(self): return RPCMethods[self.method] @@ -89,13 +92,13 @@ class RPCConnection(object): def getKnobs(self, *args): raise NotImplementedError() - def getRe(self,*args): + def getRe(self, *args): raise NotImplementedError() - def postMessage(self,*args): + def postMessage(self, *args): raise NotImplementedError() - def setKnobs(self,*args): + def setKnobs(self, *args): raise NotImplementedError() def shutdown(self): diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py index dd9044a36c..7a87ea5739 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py @@ -18,6 +18,7 @@ from gnuradio import gr import pmt import sys + class ThriftRadioClient(object): def __init__(self, host, port): self.tsocket = TSocket.TSocket(host, port) @@ -39,6 +40,7 @@ class ThriftRadioClient(object): def getRadio(self): return self.radio + """ RPC Client interface for the Apache Thrift middle-ware RPC transport. @@ -47,6 +49,7 @@ Args: host: hostname of the connection """ + class RPCConnectionThrift(RPCConnection.RPCConnection): class Knob(object): def __init__(self, key, value=None, ktype=0): @@ -73,43 +76,44 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): else: port = int(port) - super(RPCConnectionThrift, self).__init__(method='thrift', port=port, host=host) + super(RPCConnectionThrift, self).__init__( + method='thrift', port=port, host=host) self.newConnection(host, port) self.unpack_dict = { - self.BaseTypes.BOOL: lambda k,b: self.Knob(k, b.value.a_bool, self.BaseTypes.BOOL), - self.BaseTypes.BYTE: lambda k,b: self.Knob(k, b.value.a_byte, self.BaseTypes.BYTE), - self.BaseTypes.SHORT: lambda k,b: self.Knob(k, b.value.a_short, self.BaseTypes.SHORT), - self.BaseTypes.INT: lambda k,b: self.Knob(k, b.value.a_int, self.BaseTypes.INT), - self.BaseTypes.LONG: lambda k,b: self.Knob(k, b.value.a_long, self.BaseTypes.LONG), - self.BaseTypes.DOUBLE: lambda k,b: self.Knob(k, b.value.a_double, self.BaseTypes.DOUBLE), - self.BaseTypes.STRING: lambda k,b: self.Knob(k, b.value.a_string, self.BaseTypes.STRING), - self.BaseTypes.COMPLEX: lambda k,b: self.Knob(k, b.value.a_complex, self.BaseTypes.COMPLEX), - self.BaseTypes.F32VECTOR: lambda k,b: self.Knob(k, b.value.a_f32vector, self.BaseTypes.F32VECTOR), - self.BaseTypes.F64VECTOR: lambda k,b: self.Knob(k, b.value.a_f64vector, self.BaseTypes.F64VECTOR), - self.BaseTypes.S64VECTOR: lambda k,b: self.Knob(k, b.value.a_s64vector, self.BaseTypes.S64VECTOR), - self.BaseTypes.S32VECTOR: lambda k,b: self.Knob(k, b.value.a_s32vector, self.BaseTypes.S32VECTOR), - self.BaseTypes.S16VECTOR: lambda k,b: self.Knob(k, b.value.a_s16vector, self.BaseTypes.S16VECTOR), - self.BaseTypes.S8VECTOR: lambda k,b: self.Knob(k, b.value.a_s8vector, self.BaseTypes.S8VECTOR), - self.BaseTypes.C32VECTOR: lambda k,b: self.Knob(k, b.value.a_c32vector, self.BaseTypes.C32VECTOR), + self.BaseTypes.BOOL: lambda k, b: self.Knob(k, b.value.a_bool, self.BaseTypes.BOOL), + self.BaseTypes.BYTE: lambda k, b: self.Knob(k, b.value.a_byte, self.BaseTypes.BYTE), + self.BaseTypes.SHORT: lambda k, b: self.Knob(k, b.value.a_short, self.BaseTypes.SHORT), + self.BaseTypes.INT: lambda k, b: self.Knob(k, b.value.a_int, self.BaseTypes.INT), + self.BaseTypes.LONG: lambda k, b: self.Knob(k, b.value.a_long, self.BaseTypes.LONG), + self.BaseTypes.DOUBLE: lambda k, b: self.Knob(k, b.value.a_double, self.BaseTypes.DOUBLE), + self.BaseTypes.STRING: lambda k, b: self.Knob(k, b.value.a_string, self.BaseTypes.STRING), + self.BaseTypes.COMPLEX: lambda k, b: self.Knob(k, b.value.a_complex, self.BaseTypes.COMPLEX), + self.BaseTypes.F32VECTOR: lambda k, b: self.Knob(k, b.value.a_f32vector, self.BaseTypes.F32VECTOR), + self.BaseTypes.F64VECTOR: lambda k, b: self.Knob(k, b.value.a_f64vector, self.BaseTypes.F64VECTOR), + self.BaseTypes.S64VECTOR: lambda k, b: self.Knob(k, b.value.a_s64vector, self.BaseTypes.S64VECTOR), + self.BaseTypes.S32VECTOR: lambda k, b: self.Knob(k, b.value.a_s32vector, self.BaseTypes.S32VECTOR), + self.BaseTypes.S16VECTOR: lambda k, b: self.Knob(k, b.value.a_s16vector, self.BaseTypes.S16VECTOR), + self.BaseTypes.S8VECTOR: lambda k, b: self.Knob(k, b.value.a_s8vector, self.BaseTypes.S8VECTOR), + self.BaseTypes.C32VECTOR: lambda k, b: self.Knob(k, b.value.a_c32vector, self.BaseTypes.C32VECTOR), } self.pack_dict = { - self.BaseTypes.BOOL: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_bool = k.value)), - self.BaseTypes.BYTE: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_byte = k.value)), - self.BaseTypes.SHORT: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_short = k.value)), - self.BaseTypes.INT: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_int = k.value)), - self.BaseTypes.LONG: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_long = k.value)), - self.BaseTypes.DOUBLE: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_double = k.value)), - self.BaseTypes.STRING: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_string = k.value)), - self.BaseTypes.COMPLEX: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_complex = k.value)), - self.BaseTypes.F32VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_f32vector = k.value)), - self.BaseTypes.F64VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_f64vector = k.value)), - self.BaseTypes.S64VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s64vector = k.value)), - self.BaseTypes.S32VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s32vector = k.value)), - self.BaseTypes.S16VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s16vector = k.value)), - self.BaseTypes.S8VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s8vector = k.value)), - self.BaseTypes.C32VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_c32vector = k.value)), + self.BaseTypes.BOOL: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_bool=k.value)), + self.BaseTypes.BYTE: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_byte=k.value)), + self.BaseTypes.SHORT: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_short=k.value)), + self.BaseTypes.INT: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_int=k.value)), + self.BaseTypes.LONG: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_long=k.value)), + self.BaseTypes.DOUBLE: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_double=k.value)), + self.BaseTypes.STRING: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_string=k.value)), + self.BaseTypes.COMPLEX: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_complex=k.value)), + self.BaseTypes.F32VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_f32vector=k.value)), + self.BaseTypes.F64VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_f64vector=k.value)), + self.BaseTypes.S64VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s64vector=k.value)), + self.BaseTypes.S32VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s32vector=k.value)), + self.BaseTypes.S16VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s16vector=k.value)), + self.BaseTypes.S8VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s8vector=k.value)), + self.BaseTypes.C32VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_c32vector=k.value)), } def __str__(self): @@ -122,7 +126,8 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): if(f): return f(key, knob) else: - sys.stderr.write("unpackKnobs: Incorrect Knob type: {0}\n".format(knob.type)) + sys.stderr.write( + "unpackKnobs: Incorrect Knob type: {0}\n".format(knob.type)) raise exceptions.ValueError def packKnob(self, knob): @@ -130,7 +135,8 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): if(f): return f(knob) else: - sys.stderr.write("packKnobs: Incorrect Knob type: {0}\n".format(knob.type)) + sys.stderr.write( + "packKnobs: Incorrect Knob type: {0}\n".format(knob.type)) raise exceptions.ValueError def newConnection(self, host=None, port=None): @@ -142,7 +148,8 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): #print("key:", key, "value:", knobprop, "type:", knobprop.type) knobprops[key].min = self.unpackKnob(key, knobprop.min) knobprops[key].max = self.unpackKnob(key, knobprop.max) - knobprops[key].defaultvalue = self.unpackKnob(key, knobprop.defaultvalue) + knobprops[key].defaultvalue = self.unpackKnob( + key, knobprop.defaultvalue) return knobprops def getKnobs(self, *args): @@ -166,7 +173,7 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): result[key] = knob return result - def getRe(self,*args): + def getRe(self, *args): result = {} for key, knob in list(self.thriftclient.radio.getRe(*args).items()): result[key] = self.unpackKnob(key, knob) @@ -186,7 +193,8 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): result[k.key] = self.packKnob(k) self.thriftclient.radio.setKnobs(result) else: - sys.stderr.write("setKnobs: Invalid type; must be dict, list, or tuple\n") + sys.stderr.write( + "setKnobs: Invalid type; must be dict, list, or tuple\n") def shutdown(self): self.thriftclient.radio.shutdown() @@ -204,8 +212,10 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): serialized. The msg is already a PMT and so just serialized. ''' self.thriftclient.radio.postMessage(pmt.serialize_str(pmt.intern(blk_alias)), - pmt.serialize_str(pmt.intern(port)), + pmt.serialize_str( + pmt.intern(port)), pmt.serialize_str(msg)) + def printProperties(self, props): info = "" info += "Item:\t\t{0}\n".format(props.description) diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor index 01b6a84d3f..c8c4771e45 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor +++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor @@ -11,12 +11,16 @@ from PyQt5 import QtCore, Qt from argparse import ArgumentParser -import os, sys, time, struct +import os +import sys +import time +import struct from gnuradio import gr, ctrlport from gnuradio.ctrlport.GrDataPlotter import * from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient + class RateDialog(Qt.QDialog): def __init__(self, delay, parent=None): super(RateDialog, self).__init__(parent) @@ -24,19 +28,23 @@ class RateDialog(Qt.QDialog): self.setWindowTitle("Update Delay (ms)") self.delay = Qt.QLineEdit(self) self.delay.setText(str(delay)) - self.buttonBox = Qt.QDialogButtonBox(Qt.QDialogButtonBox.Ok | Qt.QDialogButtonBox.Cancel) + self.buttonBox = Qt.QDialogButtonBox( + Qt.QDialogButtonBox.Ok | Qt.QDialogButtonBox.Cancel) self.gridLayout.addWidget(self.delay) self.gridLayout.addWidget(self.buttonBox) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) + def accept(self): self.done(1) + def reject(self): self.done(0) + class MAINWindow(Qt.QMainWindow): def minimumSizeHint(self): - return Qt.QSize(800,600) + return Qt.QSize(800, 600) def __init__(self, radioclient): @@ -65,7 +73,7 @@ class MAINWindow(Qt.QMainWindow): self.setUnifiedTitleAndToolBarOnMac(True) self.newCon(radioclient) - icon = Qt.QIcon(ctrlport.__path__[0] + "/icon.png" ) + icon = Qt.QIcon(ctrlport.__path__[0] + "/icon.png") self.setWindowIcon(icon) # Locally turn off ControlPort export from GR. This prevents @@ -74,14 +82,14 @@ class MAINWindow(Qt.QMainWindow): # been specified). os.environ['GR_CONF_CONTROLPORT_ON'] = 'False' - def setUpdateRate(self,nur): + def setUpdateRate(self, nur): self.updateRate = int(nur) for c in self.conns: c.updateRate = self.updateRate c.timer.setInterval(self.updateRate) def newCon(self, radioclient=None): - child = MForm(radioclient, len(self.conns), parent = self) + child = MForm(radioclient, len(self.conns), parent=self) if(child.radioclient is not None): child.setWindowTitle(str(child.radioclient)) self.mdiArea.addSubWindow(child) @@ -95,7 +103,7 @@ class MAINWindow(Qt.QMainWindow): props = radio.properties([key]) - pmin,pmax = get_minmax(props[key]) + pmin, pmax = get_minmax(props[key]) # Use display option mask of item to set up available plot # types and default options. @@ -166,8 +174,8 @@ class MAINWindow(Qt.QMainWindow): knobprop = self.knobprops[uid][tag] strr = str(tree.radioclient) - title = strr #title = "{0}:{1}".format(r[3], r[5]) - pmin,pmax = get_minmax(knobprop) + title = strr # title = "{0}:{1}".format(r[3], r[5]) + pmin, pmax = get_minmax(knobprop) disp = knobprop.display if(disp & gr.DISPTIME): @@ -217,7 +225,8 @@ class MAINWindow(Qt.QMainWindow): self.mdiArea.addSubWindow(plot) plot.setWindowTitle("{0}: {1}".format(title, plot.name())) - plot.qwidget().destroyed.connect(lambda obj=None, plot=plot: self.destroyPlot(plot=plot)), + plot.qwidget().destroyed.connect(lambda obj=None, + plot=plot: self.destroyPlot(plot=plot)), # when the plot is updated via drag-and-drop, we need to be # notified of the new qwidget that's created so we can @@ -232,8 +241,8 @@ class MAINWindow(Qt.QMainWindow): for i, plots in enumerate(self.plots): for p in plots: if(p == q): - #plots.remove(p) - #plots.append(q) + # plots.remove(p) + # plots.append(q) q.qwidget().destroyed.connect(lambda obj=None, plot=p: self.destroyPlot(plot=plot)) break @@ -290,7 +299,7 @@ class MAINWindow(Qt.QMainWindow): # If it's a byte stream, Python thinks it's a string. # Unpack and convert to floats for plotting. if(type(d) == str and n.find('probe2_b') == 0): - d = struct.unpack(len(d)*'b', d) + d = struct.unpack(len(d) * 'b', d) d = [float(di) for di in d] data.append(d) @@ -303,59 +312,58 @@ class MAINWindow(Qt.QMainWindow): if window: self.mdiArea.setActiveSubWindow(window) - def createActions(self): self.newConAct = Qt.QAction("&New Connection", - self, shortcut=Qt.QKeySequence.New, - statusTip="Create a new file", triggered=lambda x: self.newCon(None)) + self, shortcut=Qt.QKeySequence.New, + statusTip="Create a new file", triggered=lambda x: self.newCon(None)) self.exitAct = Qt.QAction("E&xit", self, shortcut="Ctrl+Q", - statusTip="Exit the application", - triggered=Qt.qApp.closeAllWindows) + statusTip="Exit the application", + triggered=Qt.qApp.closeAllWindows) self.closeAct = Qt.QAction("Cl&ose", self, shortcut="Ctrl+F4", - statusTip="Close the active window", - triggered=self.mdiArea.closeActiveSubWindow) + statusTip="Close the active window", + triggered=self.mdiArea.closeActiveSubWindow) self.closeAllAct = Qt.QAction("Close &All", self, - statusTip="Close all the windows", - triggered=self.mdiArea.closeAllSubWindows) + statusTip="Close all the windows", + triggered=self.mdiArea.closeAllSubWindows) self.urAct = Qt.QAction("Update Rate", self, shortcut="F5", - statusTip="Change Update Rate", - triggered=self.updateRateShow) + statusTip="Change Update Rate", + triggered=self.updateRateShow) qks = Qt.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T) self.tileAct = Qt.QAction("&Tile", self, - statusTip="Tile the windows", - triggered=self.mdiArea.tileSubWindows, - shortcut=qks) + statusTip="Tile the windows", + triggered=self.mdiArea.tileSubWindows, + shortcut=qks) qks = Qt.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C) self.cascadeAct = Qt.QAction("&Cascade", self, - statusTip="Cascade the windows", shortcut=qks, - triggered=self.mdiArea.cascadeSubWindows) + statusTip="Cascade the windows", shortcut=qks, + triggered=self.mdiArea.cascadeSubWindows) self.nextAct = Qt.QAction("Ne&xt", self, - shortcut=Qt.QKeySequence.NextChild, - statusTip="Move the focus to the next window", - triggered=self.mdiArea.activateNextSubWindow) + shortcut=Qt.QKeySequence.NextChild, + statusTip="Move the focus to the next window", + triggered=self.mdiArea.activateNextSubWindow) self.previousAct = Qt.QAction("Pre&vious", self, - shortcut=Qt.QKeySequence.PreviousChild, - statusTip="Move the focus to the previous window", - triggered=self.mdiArea.activatePreviousSubWindow) + shortcut=Qt.QKeySequence.PreviousChild, + statusTip="Move the focus to the previous window", + triggered=self.mdiArea.activatePreviousSubWindow) self.separatorAct = Qt.QAction(self) self.separatorAct.setSeparator(True) self.aboutAct = Qt.QAction("&About", self, - statusTip="Show the application's About box", - triggered=self.about) + statusTip="Show the application's About box", + triggered=self.about) self.aboutQtAct = Qt.QAction("About &Qt", self, - statusTip="Show the Qt library's About box", - triggered=Qt.qApp.aboutQt) + statusTip="Show the Qt library's About box", + triggered=Qt.qApp.aboutQt) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") @@ -395,7 +403,6 @@ class MAINWindow(Qt.QMainWindow): def createStatusBar(self): self.statusBar().showMessage("Ready") - def activeMdiChild(self): activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: @@ -426,7 +433,7 @@ class MAINWindow(Qt.QMainWindow): def about(self): about_info = \ -'''Copyright 2012 Free Software Foundation, Inc.\n + '''Copyright 2012 Free Software Foundation, Inc.\n This program is part of GNU Radio.\n 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.\n 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.\n @@ -441,13 +448,13 @@ class ConInfoDialog(Qt.QDialog): self.gridLayout = Qt.QGridLayout(self) - self.host = Qt.QLineEdit(self) self.port = Qt.QLineEdit(self) self.host.setText("localhost") self.port.setText("43243") - self.buttonBox = Qt.QDialogButtonBox(Qt.QDialogButtonBox.Ok | Qt.QDialogButtonBox.Cancel) + self.buttonBox = Qt.QDialogButtonBox( + Qt.QDialogButtonBox.Ok | Qt.QDialogButtonBox.Cancel) self.gridLayout.addWidget(self.host) self.gridLayout.addWidget(self.port) @@ -456,7 +463,6 @@ class ConInfoDialog(Qt.QDialog): self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) - def accept(self): self.done(1) @@ -471,7 +477,7 @@ class UpdaterWindow(Qt.QDialog): self.key = key self.radio = radio - self.resize(300,200) + self.resize(300, 200) self.layout = Qt.QVBoxLayout() self.props = radio.properties([key])[key] @@ -487,7 +493,6 @@ class UpdaterWindow(Qt.QDialog): except: has_set = False - if(has_set is False): self.cancelButton = Qt.QPushButton("Ok") self.cancelButton.clicked.connect(self.reject) @@ -496,7 +501,7 @@ class UpdaterWindow(Qt.QDialog): self.buttonlayout.addWidget(self.cancelButton) self.layout.addLayout(self.buttonlayout) - else: # we have a set function + else: # we have a set function self.textInput = Qt.QLineEdit() self.layout.addWidget(self.textInput) @@ -507,7 +512,7 @@ class UpdaterWindow(Qt.QDialog): rv = radio.getKnobs([key]) val = rv[key].value if(type(val) == ControlPort.complex): - val = val.re + val.im*1j + val = val.re + val.im * 1j self.textInput.setText(str(val)) self.sv = rv[key] @@ -516,15 +521,18 @@ class UpdaterWindow(Qt.QDialog): self.setButton.clicked.connect(self._set) self.cancelButton.clicked.connect(self.reject) - self.is_num = ((type(self.sv.value)==float) or (type(self.sv.value)==int)) + self.is_num = ((type(self.sv.value) == float) or + (type(self.sv.value) == int)) if(self.is_num): self.sliderlayout = Qt.QHBoxLayout() self.slider = Qt.QSlider(QtCore.Qt.Horizontal) - self.sliderlayout.addWidget(Qt.QLabel(str(self.props.min.value))) + self.sliderlayout.addWidget( + Qt.QLabel(str(self.props.min.value))) self.sliderlayout.addWidget(self.slider) - self.sliderlayout.addWidget(Qt.QLabel(str(self.props.max.value))) + self.sliderlayout.addWidget( + Qt.QLabel(str(self.props.max.value))) self.steps = 10000 self.valspan = self.props.max.value - self.props.min.value @@ -548,10 +556,12 @@ class UpdaterWindow(Qt.QDialog): self.setLayout(self.layout) def _set_slider_value(self, val): - self.slider.setValue(self.steps*(val-self.props.min.value)/self.valspan) + self.slider.setValue( + self.steps * (val - self.props.min.value) / self.valspan) def _slide(self): - val = self.props.min.value + (self.slider.value()/float(self.steps)*self.valspan) + val = self.props.min.value + \ + (self.slider.value() / float(self.steps) * self.valspan) self.textInput.setText(str(val)) def _apply(self): @@ -568,7 +578,8 @@ class UpdaterWindow(Qt.QDialog): val.re = t.real val.im = t.imag else: - sys.stderr.write("set type not supported! ({0})\n".format(type(self.sv.value))) + sys.stderr.write( + "set type not supported! ({0})\n".format(type(self.sv.value))) return self.sv.value = val @@ -589,11 +600,13 @@ class MForm(Qt.QWidget): st = time.time() knobs = self.radioclient.getKnobs([]) ft = time.time() - latency = ft-st - self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%(latency*1000)) + latency = ft - st + self.parent.statusBar().showMessage( + "Current GNU Radio Control Port Query Latency: %f ms" % (latency * 1000)) except Exception as e: - sys.stderr.write("ctrlport-monitor: lost connection ({0}).\n".format(e)) + sys.stderr.write( + "ctrlport-monitor: lost connection ({0}).\n".format(e)) if(type(self.parent) is MAINWindow): # Find window of connection remove = [] @@ -623,13 +636,12 @@ class MForm(Qt.QWidget): tableitems = knobs.keys() - #UPDATE TABLE: + # UPDATE TABLE: self.table.updateItems(knobs, self.knobprops) - #UPDATE PLOTS + # UPDATE PLOTS self.parent.update(knobs, self.uid) - def __init__(self, radioclient, uid=0, updateRate=2000, parent=None): super(MForm, self).__init__() @@ -642,7 +654,8 @@ class MForm(Qt.QWidget): port = str(askinfo.port.text()) try: - self.radioclient = GNURadioControlPortClient(host, port, 'thrift').client + self.radioclient = GNURadioControlPortClient( + host, port, 'thrift').client print("Connected to %s:%s" % (host, port)) except: print("Cannot connect to %s:%s" % (host, port)) @@ -659,17 +672,19 @@ class MForm(Qt.QWidget): self.knobprops = self.radioclient.properties([]) self.parent.knobprops.append(self.knobprops) - self.resize(775,500) + self.resize(775, 500) self.timer = QtCore.QTimer() self.constupdatediv = 0 self.tableupdatediv = 0 - plotsize=250 + plotsize = 250 # make table self.table = GrDataPlotterValueTable(uid, self, 0, 0, 400, 200) - sizePolicy = Qt.QSizePolicy(Qt.QSizePolicy.Preferred, Qt.QSizePolicy.Preferred) + sizePolicy = Qt.QSizePolicy( + Qt.QSizePolicy.Preferred, Qt.QSizePolicy.Preferred) self.table.treeWidget.setSizePolicy(sizePolicy) - self.table.treeWidget.setEditTriggers(Qt.QAbstractItemView.EditKeyPressed) + self.table.treeWidget.setEditTriggers( + Qt.QAbstractItemView.EditKeyPressed) self.table.treeWidget.setSortingEnabled(True) self.table.treeWidget.setDragEnabled(True) @@ -721,24 +736,27 @@ def get_minmax(p): if pmin == []: pmin = None else: - pmin = 1.1*float(pmin) + pmin = 1.1 * float(pmin) if pmax == []: pmax = None else: - pmax = 1.1*float(pmax) + pmax = 1.1 * float(pmax) return pmin, pmax + class MyApp(object): def __init__(self, args): parser = ArgumentParser(description="GNU Radio Control Port Monitor") - parser.add_argument("host", nargs="?", default="localhost", help="host name or IP") + parser.add_argument("host", nargs="?", + default="localhost", help="host name or IP") parser.add_argument("port", help="port") args = parser.parse_args() try: - GNURadioControlPortClient(args.host, args.port, 'thrift', self.run, Qt.QApplication(sys.argv).exec_) + GNURadioControlPortClient( + args.host, args.port, 'thrift', self.run, Qt.QApplication(sys.argv).exec_) except: print("ControlPort failed to connect. Check the config of your endpoint.") print("\t[ControlPort] on = True") @@ -749,4 +767,5 @@ class MyApp(object): def run(self, client): MAINWindow(client).show() + MyApp(sys.argv) diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx index 3c807755db..cd704888bb 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx +++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx @@ -10,8 +10,13 @@ from argparse import ArgumentParser -import sys, time, re, signal -import random,math,operator +import sys +import time +import re +import signal +import random +import math +import operator from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient @@ -29,11 +34,10 @@ try: print(sys.argv[0], "could not load QTAgg backend.") sys.exit(1) - from matplotlib.figure import Figure except ImportError: print(sys.argv[0], "requires networkx and matplotlib.", - "Please check that they are installed and try again.") + "Please check that they are installed and try again.") sys.exit(1) from PyQt5 import QtCore, Qt @@ -44,9 +48,10 @@ from gnuradio.ctrlport.GrDataPlotter import * from networkx.drawing.nx_agraph import graphviz_layout + class MAINWindow(Qt.QMainWindow): def minimumSizeHint(self): - return Qt.QSize(800,600) + return Qt.QSize(800, 600) def __init__(self, radioclient): @@ -74,7 +79,7 @@ class MAINWindow(Qt.QMainWindow): self.newCon(radioclient) - icon = Qt.QIcon(ctrlport.__path__[0] + "/icon.png" ) + icon = Qt.QIcon(ctrlport.__path__[0] + "/icon.png") self.setWindowIcon(icon) def newSubWindow(self, window, title): @@ -96,55 +101,54 @@ class MAINWindow(Qt.QMainWindow): if window: self.mdiArea.setActiveSubWindow(window) - def createActions(self): self.newConAct = Qt.QAction("&New Connection", - self, shortcut=Qt.QKeySequence.New, - statusTip="Create a new file", triggered=lambda x: self.newCon(None)) + self, shortcut=Qt.QKeySequence.New, + statusTip="Create a new file", triggered=lambda x: self.newCon(None)) self.exitAct = Qt.QAction("E&xit", self, shortcut="Ctrl+Q", - statusTip="Exit the application", - triggered=Qt.qApp.closeAllWindows) + statusTip="Exit the application", + triggered=Qt.qApp.closeAllWindows) self.closeAct = Qt.QAction("Cl&ose", self, shortcut="Ctrl+F4", - statusTip="Close the active window", - triggered=self.mdiArea.closeActiveSubWindow) + statusTip="Close the active window", + triggered=self.mdiArea.closeActiveSubWindow) self.closeAllAct = Qt.QAction("Close &All", self, - statusTip="Close all the windows", - triggered=self.mdiArea.closeAllSubWindows) + statusTip="Close all the windows", + triggered=self.mdiArea.closeAllSubWindows) qks = Qt.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T) self.tileAct = Qt.QAction("&Tile", self, - statusTip="Tile the windows", - triggered=self.mdiArea.tileSubWindows, - shortcut=qks) + statusTip="Tile the windows", + triggered=self.mdiArea.tileSubWindows, + shortcut=qks) qks = Qt.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C) self.cascadeAct = Qt.QAction("&Cascade", self, - statusTip="Cascade the windows", shortcut=qks, - triggered=self.mdiArea.cascadeSubWindows) + statusTip="Cascade the windows", shortcut=qks, + triggered=self.mdiArea.cascadeSubWindows) self.nextAct = Qt.QAction("Ne&xt", self, - shortcut=Qt.QKeySequence.NextChild, - statusTip="Move the focus to the next window", - triggered=self.mdiArea.activateNextSubWindow) + shortcut=Qt.QKeySequence.NextChild, + statusTip="Move the focus to the next window", + triggered=self.mdiArea.activateNextSubWindow) self.previousAct = Qt.QAction("Pre&vious", self, - shortcut=Qt.QKeySequence.PreviousChild, - statusTip="Move the focus to the previous window", - triggered=self.mdiArea.activatePreviousSubWindow) + shortcut=Qt.QKeySequence.PreviousChild, + statusTip="Move the focus to the previous window", + triggered=self.mdiArea.activatePreviousSubWindow) self.separatorAct = Qt.QAction(self) self.separatorAct.setSeparator(True) self.aboutAct = Qt.QAction("&About", self, - statusTip="Show the application's About box", - triggered=self.about) + statusTip="Show the application's About box", + triggered=self.about) self.aboutQtAct = Qt.QAction("About &Qt", self, - statusTip="Show the Qt library's About box", - triggered=Qt.qApp.aboutQt) + statusTip="Show the Qt library's About box", + triggered=Qt.qApp.aboutQt) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") @@ -173,7 +177,6 @@ class MAINWindow(Qt.QMainWindow): def createStatusBar(self): self.statusBar().showMessage("Ready") - def activeMdiChild(self): activeSubWindow = self.mdiArea.activeSubWindow() if activeSubWindow: @@ -204,7 +207,7 @@ class MAINWindow(Qt.QMainWindow): def about(self): about_info = \ -'''Copyright 2012 Free Software Foundation, Inc.\n + '''Copyright 2012 Free Software Foundation, Inc.\n This program is part of GNU Radio.\n 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.\n 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.\n @@ -219,14 +222,13 @@ class ConInfoDialog(Qt.QDialog): self.gridLayout = Qt.QGridLayout(self) - self.host = Qt.QLineEdit(self) self.port = Qt.QLineEdit(self) self.host.setText("localhost") self.port.setText("43243") self.buttonBox = Qt.QDialogButtonBox(Qt.QDialogButtonBox.Ok | - Qt.QDialogButtonBox.Cancel) + Qt.QDialogButtonBox.Cancel) self.gridLayout.addWidget(self.host) self.gridLayout.addWidget(self.port) @@ -235,7 +237,6 @@ class ConInfoDialog(Qt.QDialog): self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) - def accept(self): self.done(1) @@ -288,21 +289,22 @@ class DataTable(Qt.QWidget): self.perfTable = Qt.QTableWidget() self.perfTable.setColumnCount(2) self.perfTable.verticalHeader().hide() - self.perfTable.setHorizontalHeaderLabels( ["Block Name", "Percent Runtime"] ) + self.perfTable.setHorizontalHeaderLabels( + ["Block Name", "Percent Runtime"]) self.perfTable.horizontalHeader().setStretchLastSection(True) self.perfTable.setSortingEnabled(True) nodes = self.G.nodes(data=True) # set up plot - self.f = plt.figure(figsize=(10,8), dpi=90) + self.f = plt.figure(figsize=(10, 8), dpi=90) self.sp = self.f.add_subplot(111) - self.sp.autoscale_view(True,True,True) + self.sp.autoscale_view(True, True, True) self.sp.set_autoscale_on(True) # set up tabs self.tabber = Qt.QTabWidget() self.layout.addWidget(self.tabber) - self.tabber.addTab(self.perfTable,"Table View") + self.tabber.addTab(self.perfTable, "Table View") self.tabber.addTab(self.f.canvas, "Graph View") # set up timer @@ -312,19 +314,21 @@ class DataTable(Qt.QWidget): for i, node in enumerate(nodes): self.perfTable.setItem(i, 0, - Qt.QTableWidgetItem(node[0])) + Qt.QTableWidgetItem(node[0])) - def table_update(self,data): + def table_update(self, data): for k in data.keys(): weight = data[k] - existing = self.perfTable.findItems(str(k),QtCore.Qt.MatchFixedString) + existing = self.perfTable.findItems( + str(k), QtCore.Qt.MatchFixedString) if(len(existing) == 0): i = self.perfTable.rowCount() - self.perfTable.setRowCount( i+1) - self.perfTable.setItem( i,0, Qt.QTableWidgetItem(str(k))) - self.perfTable.setItem( i,1, Qt.QTableWidgetItem(str(weight))) + self.perfTable.setRowCount(i + 1) + self.perfTable.setItem(i, 0, Qt.QTableWidgetItem(str(k))) + self.perfTable.setItem(i, 1, Qt.QTableWidgetItem(str(weight))) else: - self.perfTable.setItem( self.perfTable.row(existing[0]),1, Qt.QTableWidgetItem(str(weight))) + self.perfTable.setItem(self.perfTable.row( + existing[0]), 1, Qt.QTableWidgetItem(str(weight))) def stat_changed(self, index): self._statistic = str(self.stattype.currentText()) @@ -332,22 +336,25 @@ class DataTable(Qt.QWidget): def checksort_changed(self, state): self._sort = state > 0 + class DataTableBuffers(DataTable): def __init__(self, radioclient, G): super(DataTableBuffers, self).__init__(radioclient, G) - self.perfTable.setHorizontalHeaderLabels( ["Block Name", "Percent Buffer Full"] ) + self.perfTable.setHorizontalHeaderLabels( + ["Block Name", "Percent Buffer Full"]) def update(self): nodes = self.G.nodes() # get buffer fullness for all blocks - kl = list(map(lambda x: "%s::%soutput %% full" % \ - (x, self._statistics_table[self._statistic]), - nodes)) + kl = list(map(lambda x: "%s::%soutput %% full" % + (x, self._statistics_table[self._statistic]), + nodes)) try: buf_knobs = self.radioclient.getKnobs(kl) except Exception as e: - sys.stderr.write("gr-perf-monitorx: lost connection ({0}).\n".format(e)) + sys.stderr.write( + "gr-perf-monitorx: lost connection ({0}).\n".format(e)) self.parentWidget().mdiArea().removeSubWindow(self.parentWidget()) self.close() return @@ -361,8 +368,8 @@ class DataTableBuffers(DataTable): for blk in buffer_fullness: bdata = buffer_fullness[blk] if bdata: - for port in range(0,len(bdata)): - blockport_fullness["%s:%d"%(blk,port)] = bdata[port] + for port in range(0, len(bdata)): + blockport_fullness["%s:%d" % (blk, port)] = bdata[port] if(self.perfTable.isVisible()): self.table_update(blockport_fullness) @@ -371,48 +378,54 @@ class DataTableBuffers(DataTable): if(self._sort): sorted_fullness = sorted(blockport_fullness.items(), key=operator.itemgetter(1)) - self._keymap = list(map(operator.itemgetter(0), sorted_fullness)) + self._keymap = list( + map(operator.itemgetter(0), sorted_fullness)) else: if self._keymap: - sorted_fullness = len(self._keymap)*['',] + sorted_fullness = len(self._keymap) * ['', ] for b in blockport_fullness: - sorted_fullness[self._keymap.index(b)] = (b, blockport_fullness[b]) + sorted_fullness[self._keymap.index(b)] = ( + b, blockport_fullness[b]) else: sorted_fullness = blockport_fullness.items() if(not self.disp): - self.disp = self.sp.bar(range(0,len(sorted_fullness)), - list(map(lambda x: x[1], sorted_fullness)), + self.disp = self.sp.bar(range(0, len(sorted_fullness)), + list( + map(lambda x: x[1], sorted_fullness)), alpha=0.5, align='edge') self.sp.set_ylabel("% Buffers Full") - self.sp.set_xticks(list(map(lambda x: x+0.5, range(0,len(sorted_fullness))))) + self.sp.set_xticks( + list(map(lambda x: x + 0.5, range(0, len(sorted_fullness))))) self.sp.set_xticklabels(list(map(lambda x: " " + x, map(lambda x: x[0], sorted_fullness))), rotation="vertical", verticalalignment="bottom") else: self.sp.set_xticklabels(list(map(lambda x: " " + x, map(lambda x: x[0], sorted_fullness))), rotation="vertical", verticalalignment="bottom") - for r,w in zip(self.disp, sorted_fullness): + for r, w in zip(self.disp, sorted_fullness): r.set_height(w[1]) self.f.canvas.draw() + class DataTableRuntimes(DataTable): def __init__(self, radioclient, G): - super(DataTableRuntimes, self).__init__( radioclient, G) + super(DataTableRuntimes, self).__init__(radioclient, G) def update(self): nodes = self.G.nodes() # get work time for all blocks - kl = list(map(lambda x: "%s::%swork time" % \ - (x, self._statistics_table[self._statistic]), - nodes)) + kl = list(map(lambda x: "%s::%swork time" % + (x, self._statistics_table[self._statistic]), + nodes)) try: wrk_knobs = self.radioclient.getKnobs(kl) except Exception as e: - sys.stderr.write("gr-perf-monitorx: lost connection ({0}).\n".format(e)) + sys.stderr.write( + "gr-perf-monitorx: lost connection ({0}).\n".format(e)) self.parentWidget().mdiArea().removeSubWindow(self.parentWidget()) self.close() return @@ -423,7 +436,7 @@ class DataTableRuntimes(DataTable): total_work = 1 work_times = dict(zip( map(lambda x: x.split("::")[0], wrk_knobs.keys()), - map(lambda x: 1e-10 + x.value/total_work, wrk_knobs.values()))) + map(lambda x: 1e-10 + x.value / total_work, wrk_knobs.values()))) # update table view if(self.perfTable.isVisible()): @@ -431,32 +444,35 @@ class DataTableRuntimes(DataTable): else: if(self._sort): - sorted_work = sorted(work_times.items(), key=operator.itemgetter(1)) + sorted_work = sorted(work_times.items(), + key=operator.itemgetter(1)) self._keymap = list(map(operator.itemgetter(0), sorted_work)) else: if self._keymap: - sorted_work = len(list(self._keymap))*['',] + sorted_work = len(list(self._keymap)) * ['', ] for b in work_times: sorted_work[self._keymap.index(b)] = (b, work_times[b]) else: sorted_work = work_times.items() if(not self.disp): - self.disp = self.sp.bar(range(0,len(sorted_work)), + self.disp = self.sp.bar(range(0, len(sorted_work)), list(map(lambda x: x[1], sorted_work)), alpha=0.5, align='edge') self.sp.set_ylabel("% Runtime") - self.sp.set_xticks(list(map(lambda x: x+0.5, range(0,len(sorted_work))))) + self.sp.set_xticks( + list(map(lambda x: x + 0.5, range(0, len(sorted_work))))) self.sp.set_xticklabels(list(map(lambda x: " " + x[0], sorted_work)), - rotation="vertical", verticalalignment="bottom" ) + rotation="vertical", verticalalignment="bottom") else: self.sp.set_xticklabels(list(map(lambda x: " " + x[0], sorted_work)), - rotation="vertical", verticalalignment="bottom" ) - for r,w in zip(self.disp, sorted_work): + rotation="vertical", verticalalignment="bottom") + for r, w in zip(self.disp, sorted_work): r.set_height(w[1]) self.f.canvas.draw() + class MForm(Qt.QWidget): def update(self): try: @@ -470,7 +486,8 @@ class MForm(Qt.QWidget): kl1 = self.radioclient.getKnobs([self.clockKey]) self.clockKey = list(kl1.keys())[0] self.currClock = kl1[self.clockKey].value - self.clockSelIdx = list(self.clocks.values()).index(self.currClock) + self.clockSelIdx = list( + self.clocks.values()).index(self.currClock) self.clockSel.setCurrentIndex(self.clockSelIdx) self.prevent_clock_change = False except Exception as e: @@ -481,9 +498,9 @@ class MForm(Qt.QWidget): nodes_msg = self.G_msg.nodes() # get current buffer depths of all output buffers - kl = list(map(lambda x: "%s::%soutput %% full" % \ - (x, self._statistics_table[self._statistic]), - nodes_stream)) + kl = list(map(lambda x: "%s::%soutput %% full" % + (x, self._statistics_table[self._statistic]), + nodes_stream)) st = time.time() buf_knobs = self.radioclient.getKnobs(kl) @@ -495,9 +512,9 @@ class MForm(Qt.QWidget): map(lambda x: x.value, buf_knobs.values()))) # get work time for all blocks - kl = list(map(lambda x: "%s::%swork time" % \ - (x, self._statistics_table[self._statistic]), - nodes_stream)) + kl = list(map(lambda x: "%s::%swork time" % + (x, self._statistics_table[self._statistic]), + nodes_stream)) st = time.time() wrk_knobs = self.radioclient.getKnobs(kl) td2 = time.time() - st @@ -507,18 +524,18 @@ class MForm(Qt.QWidget): if(total_work == 0): total_work = 1 work_times = dict(zip( - map(lambda x: x.split("::")[0], wrk_knobs.keys()), - map(lambda x: x.value/total_work, wrk_knobs.values()))) + map(lambda x: x.split("::")[0], wrk_knobs.keys()), + map(lambda x: x.value / total_work, wrk_knobs.values()))) work_times_padded = dict(zip( - self.G.nodes(), - [0.1]*len(self.G.nodes()))) + self.G.nodes(), + [0.1] * len(self.G.nodes()))) work_times_padded.update(work_times) for n in nodes_stream: # ne is the list of edges away from this node! - ne = self.G.edges([n],True) - #for e in ne: # iterate over edges from this block - for e in ne: # iterate over edges from this block + ne = self.G.edges([n], True) + # for e in ne: # iterate over edges from this block + for e in ne: # iterate over edges from this block # get the right output buffer/port weight for each edge sourceport = e[2]["sourceport"] if(e[2]["type"] == "stream"): @@ -526,8 +543,8 @@ class MForm(Qt.QWidget): e[2]["weight"] = newweight for n in nodes_msg: - ne = self.G.edges([n],True) - for e in ne: # iterate over edges from this block + ne = self.G.edges([n], True) + for e in ne: # iterate over edges from this block sourceport = e[2]["sourceport"] if(e[2]["type"] == "msg"): newweight = 0.01 @@ -535,8 +552,10 @@ class MForm(Qt.QWidget): # set updated weights #self.node_weights = map(lambda x: 20+2000*work_times[x], nodes_stream) - self.node_weights = list(map(lambda x: 20+2000*work_times_padded[x], self.G.nodes())) - self.edge_weights = list(map(lambda x: 100.0*x[2]["weight"], self.G.edges(data=True))) + self.node_weights = list( + map(lambda x: 20 + 2000 * work_times_padded[x], self.G.nodes())) + self.edge_weights = list( + map(lambda x: 100.0 * x[2]["weight"], self.G.edges(data=True))) # draw graph updates if(self.do_update): @@ -545,11 +564,12 @@ class MForm(Qt.QWidget): self.updateGraph() latency = td1 + td2 - self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%\ - (latency*1000)) + self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms" % + (latency * 1000)) except Exception as e: - sys.stderr.write("gr-perf-monitorx: lost connection ({0}).\n".format(e)) + sys.stderr.write( + "gr-perf-monitorx: lost connection ({0}).\n".format(e)) if(type(self.parent) is MAINWindow): # Find window of connection for p in self.parent.mdiArea.subWindowList(): @@ -562,15 +582,17 @@ class MForm(Qt.QWidget): return def rtt(self): - self.parent.newSubWindow(DataTableRuntimes(self.radioclient, self.G_stream), "Runtime Table") + self.parent.newSubWindow(DataTableRuntimes( + self.radioclient, self.G_stream), "Runtime Table") def bpt(self): - self.parent.newSubWindow(DataTableBuffers(self.radioclient, self.G_stream), "Buffers Table") + self.parent.newSubWindow(DataTableBuffers( + self.radioclient, self.G_stream), "Buffers Table") def resetPCs(self): knobs = [] for b in self.blocks_list: - knobs += [self.radioclient.Knob(b + "::reset_perf_counters"),] + knobs += [self.radioclient.Knob(b + "::reset_perf_counters"), ] k = self.radioclient.setKnobs(knobs) def toggleFlowgraph(self): @@ -614,13 +636,13 @@ class MForm(Qt.QWidget): host = str(askinfo.host.text()) port = str(askinfo.port.text()) try: - self.radioclient = GNURadioControlPortClient(host, port, 'thrift').client + self.radioclient = GNURadioControlPortClient( + host, port, 'thrift').client print("Connected to %s:%s" % (host, port)) except: print("Error connecting to %s:%s" % (host, port)) else: self.radioclient = radioclient - if self.radioclient is None: return @@ -635,27 +657,27 @@ class MForm(Qt.QWidget): self.layoutTop.addLayout(self.layout) self.rttAct = Qt.QAction("Runtime Table", - self, statusTip="Runtime Table", triggered=self.rtt) + self, statusTip="Runtime Table", triggered=self.rtt) self.rttBut = Qt.QToolButton() self.rttBut.setDefaultAction(self.rttAct) self.ctlBox.addWidget(self.rttBut) self.bptAct = Qt.QAction("Buffer Table", - self, statusTip="Buffer Table", triggered=self.bpt) + self, statusTip="Buffer Table", triggered=self.bpt) self.bptBut = Qt.QToolButton() self.bptBut.setDefaultAction(self.bptAct) self.ctlBox.addWidget(self.bptBut) self.resetPCsAct = Qt.QAction("Reset", self, - statusTip="Reset all Performance Counters", - triggered=self.resetPCs) + statusTip="Reset all Performance Counters", + triggered=self.resetPCs) self.resetPCsBut = Qt.QToolButton() self.resetPCsBut.setDefaultAction(self.resetPCsAct) self.ctlBox.addWidget(self.resetPCsBut) self.pauseFGAct = Qt.QAction("Pause", self, - statusTip="Pause the Flowgraph", - triggered=self.toggleFlowgraph) + statusTip="Pause the Flowgraph", + triggered=self.toggleFlowgraph) self.pauseFGAct.setCheckable(True) self.pauseFGBut = Qt.QToolButton() self.pauseFGBut.setDefaultAction(self.pauseFGAct) @@ -663,7 +685,7 @@ class MForm(Qt.QWidget): self.prevent_clock_change = True self.clockKey = None - self.clocks = {"MONOTONIC":1, "THREAD":3} + self.clocks = {"MONOTONIC": 1, "THREAD": 3} self.clockSel = Qt.QComboBox(self) list(map(lambda x: self.clockSel.addItem(x), self.clocks.keys())) self.ctlBox.addWidget(self.clockSel) @@ -691,15 +713,14 @@ class MForm(Qt.QWidget): self.timer = QtCore.QTimer() self.constupdatediv = 0 self.tableupdatediv = 0 - plotsize=250 - + plotsize = 250 # Set up the graph of blocks - input_name = lambda x: x+"::avg input % full" - output_name = lambda x: x+"::avg output % full" - wtime_name = lambda x: x+"::avg work time" - nout_name = lambda x: x+"::avg noutput_items" - nprod_name = lambda x: x+"::avg nproduced" + def input_name(x): return x + "::avg input % full" + def output_name(x): return x + "::avg output % full" + def wtime_name(x): return x + "::avg work time" + def nout_name(x): return x + "::avg noutput_items" + def nprod_name(x): return x + "::avg nproduced" tmplist = [] knobs = self.radio.getKnobs([]) @@ -719,11 +740,10 @@ class MForm(Qt.QWidget): if(input_name(blockname) in knobs): tmplist.append(blockname) - if not edgelist: - sys.stderr.write("Could not find list of edges from flowgraph. " + \ - "Make sure the option 'edges_list' is enabled " + \ - "in the ControlPort configuration.\n\n") + sys.stderr.write("Could not find list of edges from flowgraph. " + + "Make sure the option 'edges_list' is enabled " + + "in the ControlPort configuration.\n\n") sys.exit(1) self.blocks_list = tmplist @@ -736,12 +756,14 @@ class MForm(Qt.QWidget): # add stream connections for e in edges: _e = e.split("->") - edgepairs_stream.append( (_e[0].split(":")[0], _e[1].split(":")[0], {"type":"stream", "sourceport":int(_e[0].split(":")[1])}) ) + edgepairs_stream.append((_e[0].split(":")[0], _e[1].split( + ":")[0], {"type": "stream", "sourceport": int(_e[0].split(":")[1])})) # add msg connections for e in msgedges: _e = e.split("->") - edgepairs_msg.append( (_e[0].split(":")[0], _e[1].split(":")[0], {"type":"msg", "sourceport":_e[0].split(":")[1]}) ) + edgepairs_msg.append((_e[0].split(":")[0], _e[1].split(":")[0], { + "type": "msg", "sourceport": _e[0].split(":")[1]})) self.G = nx.MultiDiGraph() self.G_stream = nx.MultiDiGraph() @@ -755,14 +777,14 @@ class MForm(Qt.QWidget): n_edges = self.G.edges(data=True) for e in n_edges: - e[2]["weight"] = 5+random.random()*10 + e[2]["weight"] = 5 + random.random() * 10 self.G = nx.MultiDiGraph() self.G.add_edges_from(n_edges) - self.f = plt.figure(figsize=(10,8), dpi=90) + self.f = plt.figure(figsize=(10, 8), dpi=90) self.sp = self.f.add_subplot(111) - self.sp.autoscale_view(True,True,True) + self.sp.autoscale_view(True, True, True) self.sp.set_autoscale_on(True) self.layout.addWidget(self.f.canvas) @@ -799,26 +821,26 @@ class MForm(Qt.QWidget): thrsh = 100 if(x is not None and y is not None): - nearby = list(map(lambda z: math.sqrt( math.pow(x-z[0],2) + math.pow(y-z[1],2)), self.pos.values())) + nearby = list(map(lambda z: math.sqrt( + math.pow(x - z[0], 2) + math.pow(y - z[1], 2)), self.pos.values())) i = nearby.index(min(nearby)) if(abs(list(self.pos.values())[i][0] - x) < thrsh and - abs(list(self.pos.values())[i][1]-y) < thrsh): + abs(list(self.pos.values())[i][1] - y) < thrsh): self._current_block = list(self.pos.keys())[i] - #print "MOVING BLOCK: ", self._current_block - #print "CUR POS: ", self.pos.values()[i] + # print "MOVING BLOCK: ", self._current_block + # print "CUR POS: ", self.pos.values()[i] self._grabbed = True def mouse_move(self, event): if self._grabbed: x, y = event.xdata, event.ydata if(x is not None and y is not None): - self.pos[self._current_block] = (x,y) + self.pos[self._current_block] = (x, y) self.updateGraph() def button_release(self, event): self._grabbed = False - def openMenu(self, pos): index = self.table.treeWidget.selectedIndexes() item = self.table.treeWidget.itemFromIndex(index[0]) @@ -835,13 +857,14 @@ class MForm(Qt.QWidget): nx.draw(self.G, self.pos, edge_color=self.edge_weights, node_color='#A0CBE2', - width=list(map(lambda x: 3+math.log(x+1e-20), self.edge_weights)), + width=list( + map(lambda x: 3 + math.log(x + 1e-20), self.edge_weights)), node_shape="s", node_size=self.node_weights, edge_cmap=plt.cm.Reds, ax=self.sp, arrows=False - ) + ) nx.draw_networkx_labels(self.G, self.pos, font_size=12) @@ -859,7 +882,8 @@ class MForm(Qt.QWidget): nx.draw_networkx_edges(self.G, self.pos, edge_color=self.edge_weights, - width=list(map(lambda x: 3+math.log(x+1e-20), self.edge_weights)), + width=list( + map(lambda x: 3 + math.log(x + 1e-20), self.edge_weights)), edge_cmap=plt.cm.Reds, ax=self.sp, arrows=False) @@ -874,7 +898,8 @@ class MyApp(object): def __init__(self, args): parser = ArgumentParser(description="GNU Radio Performance Monitor") - parser.add_argument("host", nargs="?", default="localhost", help="host name or IP") + parser.add_argument("host", nargs="?", + default="localhost", help="host name or IP") parser.add_argument("port", help="port") args = parser.parse_args() @@ -882,7 +907,8 @@ class MyApp(object): signal.signal(signal.SIGTERM, signal.SIG_DFL) try: - GNURadioControlPortClient(args.host, args.port, 'thrift', self.run, Qt.QApplication(sys.argv).exec_) + GNURadioControlPortClient( + args.host, args.port, 'thrift', self.run, Qt.QApplication(sys.argv).exec_) except: print("ControlPort failed to connect. Check the config of your endpoint.") print("\t[ControlPort] on = True") @@ -894,4 +920,5 @@ class MyApp(object): def run(self, client): MAINWindow(client).show() + MyApp(sys.argv) diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py b/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py index 1310d9a28b..58af134004 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py @@ -9,29 +9,38 @@ # -import sys, subprocess, re, signal, time, atexit, os +import sys +import subprocess +import re +import signal +import time +import atexit +import os from gnuradio import gr + class monitor(object): - def __init__(self,tool="gr-ctrlport-monitor"): + def __init__(self, tool="gr-ctrlport-monitor"): print("ControlPort Monitor running.") self.started = False self.tool = tool atexit.register(self.shutdown) # setup export prefs - gr.prefs().singleton().set_bool("ControlPort","on",True) - gr.prefs().singleton().set_bool("PerfCounters","on",True) - gr.prefs().singleton().set_bool("PerfCounters","export",True) + gr.prefs().singleton().set_bool("ControlPort", "on", True) + gr.prefs().singleton().set_bool("PerfCounters", "on", True) + gr.prefs().singleton().set_bool("PerfCounters", "export", True) if(tool == "gr-perf-monitorx"): - gr.prefs().singleton().set_bool("ControlPort","edges_list",True) + gr.prefs().singleton().set_bool("ControlPort", "edges_list", True) def start(self): try: - print("monitor::endpoints() = %s" % (gr.rpcmanager_get().endpoints())) + print("monitor::endpoints() = %s" % + (gr.rpcmanager_get().endpoints())) ep = gr.rpcmanager_get().endpoints()[0] - cmd = [self.tool, re.search(r"-h (\S+|\d+\.\d+\.\d+\.\d+)", ep).group(1), re.search(r"-p (\d+)", ep).group(1)] - print("running: %s"%(str(cmd))) + cmd = [self.tool, re.search( + r"-h (\S+|\d+\.\d+\.\d+\.\d+)", ep).group(1), re.search(r"-p (\d+)", ep).group(1)] + print("running: %s" % (str(cmd))) self.proc = subprocess.Popen(cmd) self.started = True except: |