diff options
37 files changed, 725 insertions, 561 deletions
diff --git a/gnuradio-runtime/apps/evaluation_random_numbers.py b/gnuradio-runtime/apps/evaluation_random_numbers.py index 614a568d61..0d00554c3d 100644 --- a/gnuradio-runtime/apps/evaluation_random_numbers.py +++ b/gnuradio-runtime/apps/evaluation_random_numbers.py @@ -26,9 +26,9 @@ gauss_num_bins = 31 rayleigh_num_bins = 31 laplace_num_bins = 31 -rndm = gr.random() # instance of gnuradio random class (gr::random) +rndm = gr.random() # instance of gnuradio random class (gr::random) -print('All histograms contain',num_tests,'realisations.') +print('All histograms contain', num_tests, 'realisations.') #*** GENERATE DATA ***# @@ -45,83 +45,97 @@ for k in range(num_tests): #*** HISTOGRAM DATA AND CALCULATE EXPECTED COUNTS ***# -uniform_bins = np.linspace(0,1,uniform_num_bins) -gauss_bins = np.linspace(-8,8,gauss_num_bins) -laplace_bins = np.linspace(-8,8,laplace_num_bins) -rayleigh_bins = np.linspace(0,10,rayleigh_num_bins) +uniform_bins = np.linspace(0, 1, uniform_num_bins) +gauss_bins = np.linspace(-8, 8, gauss_num_bins) +laplace_bins = np.linspace(-8, 8, laplace_num_bins) +rayleigh_bins = np.linspace(0, 10, rayleigh_num_bins) -uniform_hist = np.histogram(uniform_values,uniform_bins) -gauss_hist = np.histogram(gauss_values,gauss_bins) -rayleigh_hist = np.histogram(rayleigh_values,rayleigh_bins) -laplace_hist = np.histogram(laplace_values,laplace_bins) +uniform_hist = np.histogram(uniform_values, uniform_bins) +gauss_hist = np.histogram(gauss_values, gauss_bins) +rayleigh_hist = np.histogram(rayleigh_values, rayleigh_bins) +laplace_hist = np.histogram(laplace_values, laplace_bins) -uniform_expected = np.zeros(uniform_num_bins-1) -gauss_expected = np.zeros(gauss_num_bins-1) -rayleigh_expected = np.zeros(rayleigh_num_bins-1) -laplace_expected = np.zeros(laplace_num_bins-1) +uniform_expected = np.zeros(uniform_num_bins - 1) +gauss_expected = np.zeros(gauss_num_bins - 1) +rayleigh_expected = np.zeros(rayleigh_num_bins - 1) +laplace_expected = np.zeros(laplace_num_bins - 1) for k in range(len(uniform_hist[0])): - uniform_expected[k] = num_tests / float(uniform_num_bins-1) + uniform_expected[k] = num_tests / float(uniform_num_bins - 1) for k in range(len(gauss_hist[0])): - gauss_expected[k] = float(norm.cdf(gauss_hist[1][k+1])-norm.cdf(gauss_hist[1][k]))*num_tests + gauss_expected[k] = float( + norm.cdf(gauss_hist[1][k + 1]) - norm.cdf(gauss_hist[1][k])) * num_tests for k in range(len(rayleigh_hist[0])): - rayleigh_expected[k] = float(rayleigh.cdf(rayleigh_hist[1][k+1])-rayleigh.cdf(rayleigh_hist[1][k]))*num_tests + rayleigh_expected[k] = float(rayleigh.cdf( + rayleigh_hist[1][k + 1]) - rayleigh.cdf(rayleigh_hist[1][k])) * num_tests for k in range(len(laplace_hist[0])): - laplace_expected[k] = float(laplace.cdf(laplace_hist[1][k+1])-laplace.cdf(laplace_hist[1][k]))*num_tests + laplace_expected[k] = float(laplace.cdf( + laplace_hist[1][k + 1]) - laplace.cdf(laplace_hist[1][k])) * num_tests #*** PLOT HISTOGRAMS AND EXPECTATIONS TAKEN FROM SCIPY ***# -uniform_bins_center = uniform_bins[0:-1]+(uniform_bins[1]-uniform_bins[0]) / 2.0 -gauss_bins_center = gauss_bins[0:-1]+(gauss_bins[1]-gauss_bins[0]) / 2.0 -rayleigh_bins_center = rayleigh_bins[0:-1]+(rayleigh_bins[1]-rayleigh_bins[0]) / 2.0 -laplace_bins_center = laplace_bins[0:-1]+(laplace_bins[1]-laplace_bins[0]) / 2.0 +uniform_bins_center = uniform_bins[0:-1] + \ + (uniform_bins[1] - uniform_bins[0]) / 2.0 +gauss_bins_center = gauss_bins[0:-1] + (gauss_bins[1] - gauss_bins[0]) / 2.0 +rayleigh_bins_center = rayleigh_bins[0:-1] + \ + (rayleigh_bins[1] - rayleigh_bins[0]) / 2.0 +laplace_bins_center = laplace_bins[0:-1] + \ + (laplace_bins[1] - laplace_bins[0]) / 2.0 plt.figure(1) -plt.subplot(2,1,1) -plt.plot(uniform_bins_center,uniform_hist[0],'s--',uniform_bins_center,uniform_expected,'o:') +plt.subplot(2, 1, 1) +plt.plot(uniform_bins_center, + uniform_hist[0], 's--', uniform_bins_center, uniform_expected, 'o:') plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Uniform: Distribution') -plt.legend(['histogram gr::random','calculation scipy'],loc=1) +plt.legend(['histogram gr::random', 'calculation scipy'], loc=1) -plt.subplot(2,1,2) -plt.plot(uniform_bins_center,uniform_hist[0] / uniform_expected,'rs--') -plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Uniform: Relative deviation to scipy') +plt.subplot(2, 1, 2) +plt.plot(uniform_bins_center, uniform_hist[0] / uniform_expected, 'rs--') +plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title( + 'Uniform: Relative deviation to scipy') plt.figure(2) -plt.subplot(2,1,1) -plt.plot(gauss_bins_center,gauss_hist[0],'s--',gauss_bins_center,gauss_expected,'o:') +plt.subplot(2, 1, 1) +plt.plot(gauss_bins_center, gauss_hist[0], 's--', + gauss_bins_center, gauss_expected, 'o:') plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Gauss: Distribution') -plt.legend(['histogram gr::random','calculation scipy'],loc=1) +plt.legend(['histogram gr::random', 'calculation scipy'], loc=1) -plt.subplot(2,1,2) -plt.plot(gauss_bins_center,gauss_hist[0] / gauss_expected,'rs--') -plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Gauss: Relative deviation to scipy') +plt.subplot(2, 1, 2) +plt.plot(gauss_bins_center, gauss_hist[0] / gauss_expected, 'rs--') +plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title( + 'Gauss: Relative deviation to scipy') plt.figure(3) -plt.subplot(2,1,1) -plt.plot(rayleigh_bins_center,rayleigh_hist[0],'s--',rayleigh_bins_center,rayleigh_expected,'o:') +plt.subplot(2, 1, 1) +plt.plot(rayleigh_bins_center, + rayleigh_hist[0], 's--', rayleigh_bins_center, rayleigh_expected, 'o:') plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Rayleigh: Distribution') -plt.legend(['histogram gr::random','calculation scipy'],loc=1) +plt.legend(['histogram gr::random', 'calculation scipy'], loc=1) -plt.subplot(2,1,2) -plt.plot(rayleigh_bins_center,rayleigh_hist[0] / rayleigh_expected,'rs--') -plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Rayleigh: Relative deviation to scipy') +plt.subplot(2, 1, 2) +plt.plot(rayleigh_bins_center, rayleigh_hist[0] / rayleigh_expected, 'rs--') +plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title( + 'Rayleigh: Relative deviation to scipy') plt.figure(4) -plt.subplot(2,1,1) -plt.plot(laplace_bins_center,laplace_hist[0],'s--',laplace_bins_center,laplace_expected,'o:') +plt.subplot(2, 1, 1) +plt.plot(laplace_bins_center, + laplace_hist[0], 's--', laplace_bins_center, laplace_expected, 'o:') plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Laplace: Distribution') -plt.legend(['histogram gr::random','calculation scipy'],loc=1) +plt.legend(['histogram gr::random', 'calculation scipy'], loc=1) -plt.subplot(2,1,2) -plt.plot(laplace_bins_center,laplace_hist[0] / laplace_expected,'rs--') -plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Laplace: Relative deviation to scipy') +plt.subplot(2, 1, 2) +plt.plot(laplace_bins_center, laplace_hist[0] / laplace_expected, 'rs--') +plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title( + 'Laplace: Relative deviation to scipy') plt.show() diff --git a/gnuradio-runtime/examples/mp-sched/affinity_set.py b/gnuradio-runtime/examples/mp-sched/affinity_set.py index 4516b96f54..530742ef22 100644 --- a/gnuradio-runtime/examples/mp-sched/affinity_set.py +++ b/gnuradio-runtime/examples/mp-sched/affinity_set.py @@ -13,6 +13,7 @@ from gnuradio.filter import firdes from argparse import ArgumentParser import sys + class affinity_set(gr.top_block): def __init__(self): @@ -27,19 +28,23 @@ class affinity_set(gr.top_block): # Blocks ################################################## vec_len = 1 - self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*vec_len, samp_rate) - self.blocks_null_source_0 = blocks.null_source(gr.sizeof_gr_complex*vec_len) - self.blocks_null_sink_0 = blocks.null_sink(gr.sizeof_gr_complex*vec_len) - self.filter_filt_0 = filter.fir_filter_ccc(1, 40000*[0.2+0.3j,]) - self.filter_filt_1 = filter.fir_filter_ccc(1, 40000*[0.2+0.3j,]) + self.blocks_throttle_0 = blocks.throttle( + gr.sizeof_gr_complex * vec_len, samp_rate) + self.blocks_null_source_0 = blocks.null_source( + gr.sizeof_gr_complex * vec_len) + self.blocks_null_sink_0 = blocks.null_sink( + gr.sizeof_gr_complex * vec_len) + self.filter_filt_0 = filter.fir_filter_ccc(1, 40000 * [0.2 + 0.3j, ]) + self.filter_filt_1 = filter.fir_filter_ccc(1, 40000 * [0.2 + 0.3j, ]) - self.filter_filt_0.set_processor_affinity([0,]) - self.filter_filt_1.set_processor_affinity([0,1]) + self.filter_filt_0.set_processor_affinity([0, ]) + self.filter_filt_1.set_processor_affinity([0, 1]) ################################################## # Connections ################################################## - self.connect((self.blocks_null_source_0, 0), (self.blocks_throttle_0, 0)) + self.connect((self.blocks_null_source_0, 0), + (self.blocks_throttle_0, 0)) self.connect((self.blocks_throttle_0, 0), (self.filter_filt_0, 0)) self.connect((self.filter_filt_0, 0), (self.filter_filt_1, 0)) self.connect((self.filter_filt_1, 0), (self.blocks_null_sink_0, 0)) @@ -50,6 +55,7 @@ class affinity_set(gr.top_block): def set_samp_rate(self, samp_rate): self.samp_rate = samp_rate + if __name__ == '__main__': parser = ArgumentParser() args = parser.parse_args() @@ -69,4 +75,4 @@ if __name__ == '__main__': except ValueError: print("Invalid number") else: - tb.filter_filt_0.set_processor_affinity([n,]) + tb.filter_filt_0.set_processor_affinity([n, ]) diff --git a/gnuradio-runtime/examples/mp-sched/plot_flops.py b/gnuradio-runtime/examples/mp-sched/plot_flops.py index 918197f9f4..5b58e1ddcf 100644 --- a/gnuradio-runtime/examples/mp-sched/plot_flops.py +++ b/gnuradio-runtime/examples/mp-sched/plot_flops.py @@ -47,9 +47,11 @@ def parse_file(input_filename, output): def handle_file(input_filename): - cmd_file = tempfile.NamedTemporaryFile(mode='w+', prefix='pf', suffix='.cmd') + cmd_file = tempfile.NamedTemporaryFile( + mode='w+', prefix='pf', suffix='.cmd') cmd_file_name = cmd_file.name - data_file = tempfile.NamedTemporaryFile(mode='w+', prefix='pf', suffix='.dat') + data_file = tempfile.NamedTemporaryFile( + mode='w+', prefix='pf', suffix='.dat') data_file_name = data_file.name desc = parse_file(input_filename, data_file) if len(desc) > 0: @@ -68,8 +70,8 @@ def handle_file(input_filename): os.system("gnuplot " + cmd_file_name + " -") - #sys.stdout.write(open(cmd_file_name,'r').read()) - #sys.stdout.write(open(data_file_name,'r').read()) + # sys.stdout.write(open(cmd_file_name,'r').read()) + # sys.stdout.write(open(data_file_name,'r').read()) def main(): diff --git a/gnuradio-runtime/examples/mp-sched/run_synthetic.py b/gnuradio-runtime/examples/mp-sched/run_synthetic.py index 35e7f1820d..db8378efe0 100644 --- a/gnuradio-runtime/examples/mp-sched/run_synthetic.py +++ b/gnuradio-runtime/examples/mp-sched/run_synthetic.py @@ -38,18 +38,20 @@ def write_shell_script(f, data_filename, description, ncores, gflops, max_pipes_ # We'd like each run of synthetic to take ~10 seconds desired_time_per_run = 10 est_gflops_avail = min(nstages * npipes, ncores) * gflops - nsamples = (est_gflops_avail * desired_time_per_run) / (512.0 * nstages * npipes) + nsamples = (est_gflops_avail * desired_time_per_run) / \ + (512.0 * nstages * npipes) nsamples = int(nsamples * 1e9) - cmd = "./synthetic.py -m -s %d -p %d -N %d\n" % (nstages, npipes, nsamples) + cmd = "./synthetic.py -m -s %d -p %d -N %d\n" % ( + nstages, npipes, nsamples) f.write(cmd) f.write('if test $? -ge 128; then exit 128; fi\n') - f.write(") 2>&1 | grep --line-buffered -v '^>>>' | tee %s\n" % (data_filename,)) + f.write(") 2>&1 | grep --line-buffered -v '^>>>' | tee %s\n" % + (data_filename,)) f.flush() - def main(): description = """%prog gathers multiprocessor scaling data using the ./synthetic.py benchmark. All combinations of npipes and nstages between 1 and --max-pipes-and-stages are tried. @@ -61,14 +63,15 @@ plot_flops.py will make pretty graphs from the output data generated by %prog. """ parser = ArgumentParser(description=description) parser.add_argument("-d", "--description", metavar="DESC", - help="machine description, e.g., \"Dual quad-core Xeon 3 GHz\"") + help="machine description, e.g., \"Dual quad-core Xeon 3 GHz\"") parser.add_argument("-n", "--ncores", type=int, default=1, - help="number of processor cores [default=%(default)s]") + help="number of processor cores [default=%(default)s]") parser.add_argument("-g", "--gflops", metavar="GFLOPS", type=float, default=3.0, - help="estimated GFLOPS per core [default=%(default)s]") + help="estimated GFLOPS per core [default=%(default)s]") parser.add_argument("-m", "--max-pipes-and-stages", metavar="MAX", type=int, default=16, - help="maximum number of pipes and stages to use [default=%(default)s]") - parser.add_argument("output_file_name", metavar="FILE", help="output file name") + help="maximum number of pipes and stages to use [default=%(default)s]") + parser.add_argument("output_file_name", metavar="FILE", + help="output file name") args = parser.parse_args() shell = os.popen("/bin/sh", "w") @@ -80,6 +83,6 @@ plot_flops.py will make pretty graphs from the output data generated by %prog. args.gflops, args.max_pipes_and_stages) + if __name__ == '__main__': main() - diff --git a/gnuradio-runtime/examples/mp-sched/synthetic.py b/gnuradio-runtime/examples/mp-sched/synthetic.py index 4d6f3b9a22..cff6fd970d 100644 --- a/gnuradio-runtime/examples/mp-sched/synthetic.py +++ b/gnuradio-runtime/examples/mp-sched/synthetic.py @@ -24,7 +24,7 @@ class pipeline(gr.hier_block2): gr.hier_block2.__init__(self, "pipeline", gr.io_signature(1, 1, gr.sizeof_float), gr.io_signature(0, 0, 0)) - taps = ntaps*[1.0 / ntaps] + taps = ntaps * [1.0 / ntaps] upstream = self for i in range(nstages): op = filter.fir_filter_fff(1, taps) @@ -41,14 +41,14 @@ class top(gr.top_block): default_nsamples = 10e6 parser = ArgumentParser() parser.add_argument("-p", "--npipelines", type=intx, default=1, - metavar="NPIPES", help="the number of pipelines to create (default=%(default)s)") + metavar="NPIPES", help="the number of pipelines to create (default=%(default)s)") parser.add_argument("-s", "--nstages", type=intx, default=1, metavar="NSTAGES", - help="the number of stages in each pipeline (default=%(default)s)") + help="the number of stages in each pipeline (default=%(default)s)") parser.add_argument("-N", "--nsamples", type=eng_float, default=default_nsamples, - help=("the number of samples to run through the graph (default=%s)" % - (eng_notation.num_to_str(default_nsamples)))) + help=("the number of samples to run through the graph (default=%s)" % + (eng_notation.num_to_str(default_nsamples)))) parser.add_argument("-m", "--machine-readable", action="store_true", default=False, - help="enable machine readable output") + help="enable machine readable output") args = parser.parse_args() @@ -74,23 +74,24 @@ def time_it(tb): start = os.times() tb.run() stop = os.times() - delta = list(map((lambda a, b: a-b), stop, start)) + delta = list(map((lambda a, b: a - b), stop, start)) user, sys, childrens_user, childrens_sys, real = delta total_user = user + childrens_user - total_sys = sys + childrens_sys + total_sys = sys + childrens_sys if tb.machine_readable: print("%3d %3d %.3e %7.3f %7.3f %7.3f %7.3f %.6e %.3e" % ( - tb.npipes, tb.nstages, tb.nsamples, real, total_user, total_sys, (total_user+total_sys) / real, tb.flop, tb.flop / real)) + tb.npipes, tb.nstages, tb.nsamples, real, total_user, total_sys, (total_user + total_sys) / real, tb.flop, tb.flop / real)) else: - print("npipes %7d" % (tb.npipes,)) - print("nstages %7d" % (tb.nstages,)) - print("nsamples %s" % (eng_notation.num_to_str(tb.nsamples),)) + print("npipes %7d" % (tb.npipes,)) + print("nstages %7d" % (tb.nstages,)) + print("nsamples %s" % (eng_notation.num_to_str(tb.nsamples),)) print("real %7.3f" % (real,)) print("user %7.3f" % (total_user,)) print("sys %7.3f" % (total_sys,)) print("(user+sys)/real %7.3f" % ((total_user + total_sys) / real,)) - print("pseudo_flop %s" % (eng_notation.num_to_str(tb.flop),)) - print("pseudo_flop/real %s" % (eng_notation.num_to_str(tb.flop / real),)) + print("pseudo_flop %s" % (eng_notation.num_to_str(tb.flop),)) + print("pseudo_flop/real %s" % + (eng_notation.num_to_str(tb.flop / real),)) if __name__ == "__main__": @@ -99,7 +100,3 @@ if __name__ == "__main__": time_it(tb) except KeyboardInterrupt: raise SystemExit(128) - - - - diff --git a/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py b/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py index f78404a66a..d2fa94b8ad 100644 --- a/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py +++ b/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py @@ -17,14 +17,15 @@ from argparse import ArgumentParser import sys import math + class wfm_rx_block (gr.top_block): def __init__(self): gr.top_block.__init__(self) parser = ArgumentParser(description="Decode WFM signal into WAV file.") parser.add_argument("-V", "--volume", type=eng_float, - help="Volume (dB) <%r, %r> (default is midpoint)" % \ - self.volume_range()[:2]) + help="Volume (dB) <%r, %r> (default is midpoint)" % + self.volume_range()[:2]) parser.add_argument("input_file", help="Input file (complex samples)") parser.add_argument("output_file", help="Output WAV file") @@ -34,7 +35,8 @@ class wfm_rx_block (gr.top_block): # build graph - self.src = blocks.file_source(gr.sizeof_gr_complex, args.input_file, False) + self.src = blocks.file_source( + gr.sizeof_gr_complex, args.input_file, False) adc_rate = 64e6 # 64 MS/s usrp_decim = 200 @@ -44,19 +46,17 @@ class wfm_rx_block (gr.top_block): audio_decimation = 10 audio_rate = demod_rate / audio_decimation # 32 kHz - - chan_filt_coeffs = filter.optfir.low_pass (1, # gain - usrp_rate, # sampling rate - 80e3, # passband cutoff - 115e3, # stopband cutoff - 0.1, # passband ripple - 60) # stopband attenuation - #print len(chan_filt_coeffs) - chan_filt = filter.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) - + chan_filt_coeffs = filter.optfir.low_pass(1, # gain + usrp_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + # print len(chan_filt_coeffs) + chan_filt = filter.fir_filter_ccf(chanfilt_decim, chan_filt_coeffs) #self.guts = analog.wfm_rcv (demod_rate, audio_decimation) - self.guts = analog.wfm_rcv_pll (demod_rate, audio_decimation) + self.guts = analog.wfm_rcv_pll(demod_rate, audio_decimation) # FIXME rework {add,multiply}_const_* to handle multiple streams self.volume_control_l = blocks.multiply_const_ff(self.vol) @@ -67,24 +67,24 @@ class wfm_rx_block (gr.top_block): sink = blocks.wavfile_sink(args.output_file, 2, int(audio_rate), blocks.FORMAT_WAV, blocks.FORMAT_PCM_16) else: - sink = audio.sink (int (audio_rate), - args.audio_output, - False) # ok_to_block + sink = audio.sink(int(audio_rate), + args.audio_output, + False) # ok_to_block # now wire it all together - self.connect (self.src, chan_filt, self.guts) - self.connect ((self.guts, 0), self.volume_control_l, (sink, 0)) - self.connect ((self.guts, 1), self.volume_control_r, (sink, 1)) + self.connect(self.src, chan_filt, self.guts) + self.connect((self.guts, 0), self.volume_control_l, (sink, 0)) + self.connect((self.guts, 1), self.volume_control_r, (sink, 1)) if args.volume is None: g = self.volume_range() - args.volume = float(g[0]+g[1]) / 2 + args.volume = float(g[0] + g[1]) / 2 # set initial values self.set_vol(args.volume) - def set_vol (self, vol): + def set_vol(self, vol): g = self.volume_range() self.vol = max(g[0], min(g[1], vol)) self.volume_control_l.set_k(10**(self.vol / 10)) diff --git a/gnuradio-runtime/examples/network/audio_sink.py b/gnuradio-runtime/examples/network/audio_sink.py index 68cc2ae95d..d38b30d34c 100644 --- a/gnuradio-runtime/examples/network/audio_sink.py +++ b/gnuradio-runtime/examples/network/audio_sink.py @@ -16,9 +16,11 @@ import sys try: from gnuradio import audio except ImportError: - sys.stderr.write("Failed to import gnuradio.audio. Make sure gr-audio component is installed.\n") + sys.stderr.write( + "Failed to import gnuradio.audio. Make sure gr-audio component is installed.\n") sys.exit(1) + class audio_sink(gr.top_block): def __init__(self, host, port, pkt_size, sample_rate, eof): gr.top_block.__init__(self, "audio_sink") @@ -26,18 +28,19 @@ class audio_sink(gr.top_block): dst = audio.sink(sample_rate) self.connect(src, dst) + if __name__ == '__main__': parser = ArgumentParser() parser.add_argument("--host", default="0.0.0.0", - help="local host name (domain name or IP address)") + help="local host name (domain name or IP address)") parser.add_argument("--port", type=int, default=65500, - help="port value to listen to for connection") + help="port value to listen to for connection") parser.add_argument("--packet-size", type=int, default=1472, - help="packet size.") + help="packet size.") parser.add_argument("-r", "--sample-rate", type=int, default=32000, - help="audio signal sample rate [default=%(default)r]") + help="audio signal sample rate [default=%(default)r]") parser.add_argument("--no-eof", action="store_true", default=False, - help="don't send EOF on disconnect") + help="don't send EOF on disconnect") args = parser.parse_args() # Create an instance of a hierarchical block top_block = audio_sink(args.host, args.port, @@ -50,4 +53,3 @@ if __name__ == '__main__': except KeyboardInterrupt: # Ctrl-C exits pass - diff --git a/gnuradio-runtime/examples/network/audio_source.py b/gnuradio-runtime/examples/network/audio_source.py index 70430025f2..6cffc3aedf 100644 --- a/gnuradio-runtime/examples/network/audio_source.py +++ b/gnuradio-runtime/examples/network/audio_source.py @@ -16,28 +16,32 @@ import sys try: from gnuradio import audio except ImportError: - sys.stderr.write("Failed to import gnuradio.audio. Make sure gr-audio component is installed.\n") + sys.stderr.write( + "Failed to import gnuradio.audio. Make sure gr-audio component is installed.\n") sys.exit(1) + class audio_source(gr.top_block): def __init__(self, host, port, pkt_size, sample_rate, eof): gr.top_block.__init__(self, "audio_source") self.audio = audio.source(sample_rate) - self.sink = blocks.udp_sink(gr.sizeof_float, host, port, pkt_size, eof=eof) + self.sink = blocks.udp_sink( + gr.sizeof_float, host, port, pkt_size, eof=eof) self.connect(self.audio, self.sink) + if __name__ == '__main__': parser = ArgumentParser() parser.add_argument("--host", default="127.0.0.1", - help="Remote host name (domain name or IP address") + help="Remote host name (domain name or IP address") parser.add_argument("--port", type=int, default=65500, - help="port number to connect to") + help="port number to connect to") parser.add_argument("--packet-size", type=int, default=1472, - help="packet size.") - parser.add_argument("-r", "--sample-rate", type=int, default=32000 , - help="audio signal sample rate [default=%(default)r]") + help="packet size.") + parser.add_argument("-r", "--sample-rate", type=int, default=32000, + help="audio signal sample rate [default=%(default)r]") parser.add_argument("--no-eof", action="store_true", default=False, - help="don't send EOF on disconnect") + help="don't send EOF on disconnect") args = parser.parse_args() # Create an instance of a hierarchical block top_block = audio_source(args.host, args.port, @@ -50,4 +54,3 @@ if __name__ == '__main__': except KeyboardInterrupt: # Ctrl-C exits pass - diff --git a/gnuradio-runtime/examples/network/dial_tone_sink.py b/gnuradio-runtime/examples/network/dial_tone_sink.py index 8fff674d23..d0702a5539 100644 --- a/gnuradio-runtime/examples/network/dial_tone_sink.py +++ b/gnuradio-runtime/examples/network/dial_tone_sink.py @@ -12,6 +12,7 @@ from gnuradio import gr, audio from gnuradio import blocks from argparse import ArgumentParser + class dial_tone_sink(gr.top_block): def __init__(self, host, port, pkt_size, sample_rate, eof): gr.top_block.__init__(self, "dial_tone_sink") @@ -19,18 +20,19 @@ class dial_tone_sink(gr.top_block): sink = audio.sink(sample_rate) self.connect(udp, sink) + if __name__ == '__main__': parser = ArgumentParser() parser.add_argument("--host", default="0.0.0.0", - help="local host name (domain name or IP address)") + help="local host name (domain name or IP address)") parser.add_argument("--port", type=int, default=65500, - help="port value to listen to for connection") + help="port value to listen to for connection") parser.add_argument("--packet-size", type=int, default=1472, - help="packet size.") + help="packet size.") parser.add_argument("-r", "--sample-rate", type=int, default=8000, - help="audio signal sample rate [default=%(default)r]") + help="audio signal sample rate [default=%(default)r]") parser.add_argument("--no-eof", action="store_true", default=False, - help="don't send EOF on disconnect") + help="don't send EOF on disconnect") args = parser.parse_args() # Create an instance of a hierarchical block top_block = dial_tone_sink(args.host, args.port, @@ -43,4 +45,3 @@ if __name__ == '__main__': except KeyboardInterrupt: # Ctrl-C exits pass - diff --git a/gnuradio-runtime/examples/network/dial_tone_source.py b/gnuradio-runtime/examples/network/dial_tone_source.py index 16e5fa34a8..abddf0f96e 100644 --- a/gnuradio-runtime/examples/network/dial_tone_source.py +++ b/gnuradio-runtime/examples/network/dial_tone_source.py @@ -22,13 +22,16 @@ try: except ImportError: sys.stderr.write("This example requires gr-blocks.\n") + class dial_tone_source(gr.top_block): def __init__(self, host, port, pkt_size, sample_rate, eof): gr.top_block.__init__(self, "dial_tone_source") amplitude = 0.3 - src0 = analog.sig_source_f(sample_rate, analog.GR_SIN_WAVE, 350, amplitude) - src1 = analog.sig_source_f(sample_rate, analog.GR_SIN_WAVE, 440, amplitude) + src0 = analog.sig_source_f( + sample_rate, analog.GR_SIN_WAVE, 350, amplitude) + src1 = analog.sig_source_f( + sample_rate, analog.GR_SIN_WAVE, 440, amplitude) add = blocks.add_ff() # Throttle needed here to account for the other side's audio card sampling rate @@ -38,18 +41,19 @@ class dial_tone_source(gr.top_block): self.connect(src1, (add, 1)) self.connect(add, thr, sink) + if __name__ == '__main__': parser = ArgumentParser() parser.add_argument("--host", default="127.0.0.1", - help="Remote host name (domain name or IP address") + help="Remote host name (domain name or IP address") parser.add_argument("--port", type=int, default=65500, - help="port number to connect to") + help="port number to connect to") parser.add_argument("--packet-size", type=int, default=1472, - help="packet size.") + help="packet size.") parser.add_argument("-r", "--sample-rate", type=int, default=8000, - help="audio signal sample rate [default=%(default)r]") + help="audio signal sample rate [default=%(default)r]") parser.add_argument("--no-eof", action="store_true", default=False, - help="don't send EOF on disconnect") + help="don't send EOF on disconnect") args = parser.parse_args() # Create an instance of a hierarchical block top_block = dial_tone_source(args.host, args.port, diff --git a/gnuradio-runtime/examples/network/vector_sink.py b/gnuradio-runtime/examples/network/vector_sink.py index 619303d7ec..06d0519b85 100644 --- a/gnuradio-runtime/examples/network/vector_sink.py +++ b/gnuradio-runtime/examples/network/vector_sink.py @@ -13,6 +13,7 @@ from gnuradio import blocks from gnuradio.eng_arg import eng_float, intx from argparse import ArgumentParser + class vector_sink(gr.top_block): def __init__(self, host, port, pkt_size, eof): gr.top_block.__init__(self, "vector_sink") @@ -21,16 +22,17 @@ class vector_sink(gr.top_block): sink = blocks.file_sink(gr.sizeof_float, "received.dat") self.connect(udp, sink) + if __name__ == "__main__": parser = ArgumentParser() parser.add_argument("-H", "--host", default="0.0.0.0", - help="local host name (domain name or IP address)") + help="local host name (domain name or IP address)") parser.add_argument("-p", "--port", type=int, default=65500, - help="port value to listen to for connection") + help="port value to listen to for connection") parser.add_argument("-s", "--packet-size", type=int, default=1471, - help="packet size.") + help="packet size.") parser.add_argument("--no-eof", action="store_true", default=False, - help="don't send EOF on disconnect") + help="don't send EOF on disconnect") args = parser.parse_args() # Create an instance of a hierarchical block top_block = vector_sink(args.host, args.port, @@ -43,4 +45,3 @@ if __name__ == "__main__": except KeyboardInterrupt: # Ctrl-C exits pass - diff --git a/gnuradio-runtime/examples/network/vector_source.py b/gnuradio-runtime/examples/network/vector_source.py index 0a43b4978b..7ab6a66df1 100644 --- a/gnuradio-runtime/examples/network/vector_source.py +++ b/gnuradio-runtime/examples/network/vector_source.py @@ -12,24 +12,26 @@ from gnuradio import gr from gnuradio import blocks from argparse import ArgumentParser + class vector_source(gr.top_block): def __init__(self, host, port, pkt_size, eof): gr.top_block.__init__(self, "vector_source") - data = [i*0.01 for i in range(1000)] + data = [i * 0.01 for i in range(1000)] vec = blocks.vector_source_f(data, True) udp = blocks.udp_sink(gr.sizeof_float, host, port, pkt_size, eof=eof) self.connect(vec, udp) + if __name__ == '__main__': parser = ArgumentParser() parser.add_argument("--host", default="127.0.0.1", - help="Remote host name (domain name or IP address") + help="Remote host name (domain name or IP address") parser.add_argument("--port", type=int, default=65500, - help="port number to connect to") + help="port number to connect to") parser.add_argument("--packet-size", type=int, default=1471, - help="packet size.") + help="packet size.") parser.add_argument("--no-eof", action="store_true", default=False, - help="don't send EOF on disconnect") + help="don't send EOF on disconnect") args = parser.parse_args() # Create an instance of a hierarchical block top_block = vector_source(args.host, args.port, args.packet_size, @@ -41,4 +43,3 @@ if __name__ == '__main__': except KeyboardInterrupt: # Ctrl-C exits pass - diff --git a/gnuradio-runtime/lib/math/gen_sine_table.py b/gnuradio-runtime/lib/math/gen_sine_table.py index ae31b6b81a..b45cb52e7e 100644 --- a/gnuradio-runtime/lib/math/gen_sine_table.py +++ b/gnuradio-runtime/lib/math/gen_sine_table.py @@ -11,33 +11,36 @@ import math import sys -def gen_approx_table (f, nentries, min_x, max_x): + +def gen_approx_table(f, nentries, min_x, max_x): """return a list of nentries containing tuples of the form: (m, c). min_x and max_x specify the domain of the table. """ r = [] - incx = float (max_x - min_x) / nentries - for i in range (nentries): + incx = float(max_x - min_x) / nentries + for i in range(nentries): a = (i * incx) + min_x b = ((i + 1) * incx) + min_x - m = (f(b)-f(a)) / (b-a) + m = (f(b) - f(a)) / (b - a) c = f(a) - r.append ((m, c)) + r.append((m, c)) return r -def scaled_sine (x): - return math.sin (x * math.pi / 2**31) -def gen_sine_table (): +def scaled_sine(x): + return math.sin(x * math.pi / 2**31) + + +def gen_sine_table(): nbits = 10 nentries = 2**nbits # min_x = -2**31 # max_x = 2**31-1 min_x = 0 - max_x = 2**32-1 - t = gen_approx_table (scaled_sine, nentries, min_x, max_x) + max_x = 2**32 - 1 + t = gen_approx_table(scaled_sine, nentries, min_x, max_x) # sys.stdout.write ('static const int WORDBITS = 32;\n') # sys.stdout.write ('static const int NBITS = %d;\n' % (nbits,)) @@ -45,9 +48,10 @@ def gen_sine_table (): # sys.stdout.write ('static const double sine_table[%d][2] = {\n'% (nentries,)) for e in t: - sys.stdout.write (' { %22.15e, %22.15e },\n' % (e[0], e[1])) + sys.stdout.write(' { %22.15e, %22.15e },\n' % (e[0], e[1])) # sys.stdout.write ('};\n') + if __name__ == '__main__': - gen_sine_table () + gen_sine_table() diff --git a/gnuradio-runtime/python/gnuradio/__init__.py b/gnuradio-runtime/python/gnuradio/__init__.py index 94e74574fb..cc330316bd 100644 --- a/gnuradio-runtime/python/gnuradio/__init__.py +++ b/gnuradio-runtime/python/gnuradio/__init__.py @@ -25,18 +25,20 @@ __path__ = extend_path(__path__, __name__) # https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew if os.name == 'nt' and hasattr(os, 'add_dll_directory'): root_dir = __file__ - for i in range(5): #limit search depth + for i in range(5): # limit search depth root_dir = os.path.dirname(root_dir) bin_dir = os.path.join(root_dir, 'bin') if os.path.exists(bin_dir): - try: os.add_dll_directory(bin_dir) + try: + os.add_dll_directory(bin_dir) except Exception as ex: - print('add_dll_directory(%s): %s'%(bin_dir, ex)) + print('add_dll_directory(%s): %s' % (bin_dir, ex)) break # Check if the gnuradio package is installed or whether we're attempting to import it from # the build directory. -path_ending = os.path.join('gnuradio-runtime', 'python', 'gnuradio', '__init__.py') +path_ending = os.path.join( + 'gnuradio-runtime', 'python', 'gnuradio', '__init__.py') path = os.path.abspath(__file__) if path.endswith('.pyc'): path = path[:-1] 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: diff --git a/gnuradio-runtime/python/gnuradio/eng_arg.py b/gnuradio-runtime/python/gnuradio/eng_arg.py index cefc16e222..a86ad94607 100644 --- a/gnuradio-runtime/python/gnuradio/eng_arg.py +++ b/gnuradio-runtime/python/gnuradio/eng_arg.py @@ -14,6 +14,7 @@ Add support for engineering notation to argparse.ArgumentParser import argparse from gnuradio import eng_notation + def intx(string): """ Generic integer type, will interpret string as string literal. @@ -26,6 +27,7 @@ def intx(string): "Invalid integer value: {}".format(string) ) + def eng_float(string): """ Takes a string, returns a float. Accepts engineering notation. @@ -38,4 +40,3 @@ def eng_float(string): raise argparse.ArgumentTypeError( "Invalid engineering notation value: {}".format(string) ) - diff --git a/gnuradio-runtime/python/gnuradio/eng_notation.py b/gnuradio-runtime/python/gnuradio/eng_notation.py index adf6e9572c..c4c95e3cc9 100644 --- a/gnuradio-runtime/python/gnuradio/eng_notation.py +++ b/gnuradio-runtime/python/gnuradio/eng_notation.py @@ -24,7 +24,8 @@ scale_factor['p'] = 1e-12 scale_factor['f'] = 1e-15 scale_factor['a'] = 1e-18 -def num_to_str (n, precision=6): + +def num_to_str(n, precision=6): '''Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n''' m = abs(n) format_spec = '%.' + repr(int(precision)) + 'g' @@ -50,7 +51,7 @@ def num_to_str (n, precision=6): return '%s' % float(format_spec % (n)) -def str_to_num (value): +def str_to_num(value): '''Convert a string in engineering notation to a number. E.g., '15m' -> 15e-3''' try: if not isinstance(value, str): @@ -58,8 +59,8 @@ def str_to_num (value): scale = 1.0 suffix = value[-1] if suffix in scale_factor: - return float (value[0:-1]) * scale_factor[suffix] - return float (value) + return float(value[0:-1]) * scale_factor[suffix] + return float(value) except (TypeError, KeyError, ValueError): - raise ValueError ( + raise ValueError( "Invalid engineering notation value: %r" % (value,)) diff --git a/gnuradio-runtime/python/gnuradio/eng_option.py b/gnuradio-runtime/python/gnuradio/eng_option.py index 5e7043ecd9..5e4cdf2544 100644 --- a/gnuradio-runtime/python/gnuradio/eng_option.py +++ b/gnuradio-runtime/python/gnuradio/eng_option.py @@ -13,23 +13,25 @@ from copy import copy from optparse import Option, OptionValueError from . import eng_notation -def check_eng_float (option, opt, value): + +def check_eng_float(option, opt, value): try: return eng_notation.str_to_num(value) except (ValueError, TypeError): - raise OptionValueError ( + raise OptionValueError( "option %s: invalid engineering notation value: %r" % (opt, value)) -def check_intx (option, opt, value): + +def check_intx(option, opt, value): try: - return int (value, 0) + return int(value, 0) except (ValueError, TypeError): - raise OptionValueError ( + raise OptionValueError( "option %s: invalid integer value: %r" % (opt, value)) + class eng_option (Option): TYPES = Option.TYPES + ("eng_float", "intx", "subdev") - TYPE_CHECKER = copy (Option.TYPE_CHECKER) + TYPE_CHECKER = copy(Option.TYPE_CHECKER) TYPE_CHECKER["eng_float"] = check_eng_float TYPE_CHECKER["intx"] = check_intx - diff --git a/gnuradio-runtime/python/gnuradio/gr/__init__.py b/gnuradio-runtime/python/gnuradio/gr/__init__.py index 0715a641ea..49142c65fc 100644 --- a/gnuradio-runtime/python/gnuradio/gr/__init__.py +++ b/gnuradio-runtime/python/gnuradio/gr/__init__.py @@ -20,7 +20,7 @@ Core contents. # If gnuradio is installed then the pybind output will be in this directory. # Otherwise it will reside in bindings/. -import os, sys +import os try: from .gr_python import * diff --git a/gnuradio-runtime/python/gnuradio/gr/exceptions.py b/gnuradio-runtime/python/gnuradio/gr/exceptions.py index 5dec4a6301..eda63b7954 100644 --- a/gnuradio-runtime/python/gnuradio/gr/exceptions.py +++ b/gnuradio-runtime/python/gnuradio/gr/exceptions.py @@ -10,6 +10,7 @@ class NotDAG (Exception): """Not a directed acyclic graph""" pass + class CantHappen (Exception): """Can't happen""" pass diff --git a/gnuradio-runtime/python/gnuradio/gr/gateway.py b/gnuradio-runtime/python/gnuradio/gr/gateway.py index 3be5e64eeb..7091a0586c 100644 --- a/gnuradio-runtime/python/gnuradio/gr/gateway.py +++ b/gnuradio-runtime/python/gnuradio/gr/gateway.py @@ -8,7 +8,6 @@ # - import numpy import ctypes @@ -80,7 +79,7 @@ class py_io_signature(object): return () if nports <= ntypes: return self.__types[:nports] - return self.__types + [self.__types[-1]]*(nports-ntypes) + return self.__types + [self.__types[-1]] * (nports - ntypes) def __iter__(self): """ @@ -106,7 +105,7 @@ class gateway_block(object): # Normalize the many Python ways of saying 'nothing' to '()' in_sig = in_sig or () out_sig = out_sig or () - + # Backward compatibility: array of type strings -> py_io_signature if type(in_sig) is py_io_signature: self.__in_sig = in_sig @@ -138,17 +137,17 @@ class gateway_block(object): Makes this block connectable by hier/top block python """ return self.gateway.to_basic_block() - + def fixed_rate_noutput_to_ninput(self, noutput_items): return int((noutput_items * self._decim / self._interp) + self.gateway.history() - 1) def handle_forecast(self, noutput_items, ninputs): """ - This is the handler function for forecast calls from + This is the handler function for forecast calls from block_gateway in c++ across pybind11 wrappers """ return self.forecast(noutput_items, ninputs) - + # return ninput_items_required def forecast(self, noutput_items, ninputs): @@ -156,50 +155,51 @@ class gateway_block(object): forecast is only called from a general block this is the default implementation """ - ninput_items_required = [0]*ninputs + ninput_items_required = [0] * ninputs for i in range(ninputs): - ninput_items_required[i] = noutput_items + self.gateway.history() - 1 + ninput_items_required[i] = noutput_items + \ + self.gateway.history() - 1 return ninput_items_required - def handle_general_work(self, noutput_items, - ninput_items, - input_items, - output_items): + def handle_general_work(self, noutput_items, + ninput_items, + input_items, + output_items): ninputs = len(input_items) noutputs = len(output_items) in_types = self.in_sig().port_types(ninputs) out_types = self.out_sig().port_types(noutputs) - ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p - ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p] + ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ + ctypes.py_object, ctypes.c_char_p] if self._block_type != gr.GW_BLOCK_GENERAL: - ii=[pointer_to_ndarray( - ctypes.pythonapi.PyCapsule_GetPointer(input_items[i],None), + ii = [pointer_to_ndarray( + ctypes.pythonapi.PyCapsule_GetPointer(input_items[i], None), in_types[i], self.fixed_rate_noutput_to_ninput(noutput_items) ) for i in range(ninputs)] else: - ii=[pointer_to_ndarray( - ctypes.pythonapi.PyCapsule_GetPointer(input_items[i],None), + ii = [pointer_to_ndarray( + ctypes.pythonapi.PyCapsule_GetPointer(input_items[i], None), in_types[i], ninput_items[i] ) for i in range(ninputs)] - oo=[pointer_to_ndarray( - ctypes.pythonapi.PyCapsule_GetPointer(output_items[i],None), + oo = [pointer_to_ndarray( + ctypes.pythonapi.PyCapsule_GetPointer(output_items[i], None), out_types[i], noutput_items - ) for i in range(noutputs)] + ) for i in range(noutputs)] if self._block_type != gr.GW_BLOCK_GENERAL: - r = self.work(ii,oo) + r = self.work(ii, oo) self.consume_items(r) else: - r = self.general_work(ii,oo) + r = self.general_work(ii, oo) return r @@ -224,7 +224,8 @@ class gateway_block(object): return self.__out_sig def set_msg_handler(self, which_port, handler_function): - self.gateway.set_msg_handler_pybind(which_port, handler_function.__name__) + self.gateway.set_msg_handler_pybind( + which_port, handler_function.__name__) # Save handler object in class so it's not garbage collected self.msg_handlers[which_port] = handler_function @@ -247,11 +248,10 @@ class gateway_block(object): # return self.gateway.produce(which_output, how_many_items) - ######################################################################## # Wrappers for the user to inherit from ######################################################################## -class basic_block(gateway_block): +class basic_block(gateway_block): """ Args: name (str): block name @@ -263,6 +263,7 @@ class basic_block(gateway_block): For backward compatibility, a sequence of numpy type names is also accepted as an io signature. """ + def __init__(self, name, in_sig, out_sig): gateway_block.__init__(self, name=name, @@ -271,10 +272,11 @@ class basic_block(gateway_block): block_type=gr.GW_BLOCK_GENERAL ) - def consume_items(self, nitems ): + def consume_items(self, nitems): pass -class sync_block(gateway_block): + +class sync_block(gateway_block): """ Args: name (str): block name @@ -286,6 +288,7 @@ class sync_block(gateway_block): For backward compatibility, a sequence of numpy type names is also accepted as an io signature. """ + def __init__(self, name, in_sig, out_sig): gateway_block.__init__(self, name=name, @@ -296,7 +299,7 @@ class sync_block(gateway_block): self._decim = 1 self._interp = 1 - def consume_items(self, nitems ): + def consume_items(self, nitems): if (nitems > 0): self.gateway.consume_each(nitems) @@ -313,6 +316,7 @@ class decim_block(gateway_block): For backward compatibility, a sequence of numpy type names is also accepted as an io signature. """ + def __init__(self, name, in_sig, out_sig, decim): gateway_block.__init__(self, name=name, @@ -325,7 +329,7 @@ class decim_block(gateway_block): self.gateway.set_relative_rate(self._interp, self._decim) self.gateway.set_output_multiple(self._interp) - def consume_items(self, nitems ): + def consume_items(self, nitems): if (nitems > 0): self.gateway.consume_each(int(nitems * self._decim)) @@ -333,7 +337,6 @@ class decim_block(gateway_block): return [self.fixed_rate_noutput_to_ninput(noutput_items) for ii in range(ninputs)] - class interp_block(gateway_block): """ Args: @@ -346,6 +349,7 @@ class interp_block(gateway_block): For backward compatibility, a sequence of numpy type names is also accepted as an io signature. """ + def __init__(self, name, in_sig, out_sig, interp): gateway_block.__init__(self, name=name, @@ -358,8 +362,7 @@ class interp_block(gateway_block): self.gateway.set_relative_rate(self._interp, self._decim) self.gateway.set_output_multiple(self._interp) - - def consume_items(self, nitems ): + def consume_items(self, nitems): if (nitems > 0): self.gateway.consume_each(int(nitems / self._interp)) diff --git a/gnuradio-runtime/python/gnuradio/gr/hier_block2.py b/gnuradio-runtime/python/gnuradio/gr/hier_block2.py index cbb6e77392..4d0f428174 100644 --- a/gnuradio-runtime/python/gnuradio/gr/hier_block2.py +++ b/gnuradio-runtime/python/gnuradio/gr/hier_block2.py @@ -19,12 +19,14 @@ def _multiple_endpoints(func): @functools.wraps(func) def wrapped(self, *points): if not points: - raise ValueError("At least one block required for " + func.__name__) + raise ValueError( + "At least one block required for " + func.__name__) elif len(points) == 1: try: block = points[0].to_basic_block() except AttributeError: - raise ValueError("At least two endpoints required for " + func.__name__) + raise ValueError( + "At least two endpoints required for " + func.__name__) func(self, block) else: try: @@ -75,7 +77,7 @@ class hier_block2(object): """ Pass-through member requests to the C++ object. """ - + try: object.__getattribute__(self, "_impl") except AttributeError as exception: @@ -84,7 +86,6 @@ class hier_block2(object): "a derived class?".format(object.__getattribute__(self.__class__, "__name__"))) from exception return getattr(self._impl, name) - # FIXME: these should really be implemented # in the original C++ class (gr_hier_block2), then they would all be inherited here diff --git a/gnuradio-runtime/python/gnuradio/gr/packet_utils.py b/gnuradio-runtime/python/gnuradio/gr/packet_utils.py index fd7d424480..53e053317d 100644 --- a/gnuradio-runtime/python/gnuradio/gr/packet_utils.py +++ b/gnuradio-runtime/python/gnuradio/gr/packet_utils.py @@ -11,6 +11,7 @@ from gnuradio import gr import pmt + def make_lengthtags(lengths, offsets, tagname='length', vlen=1): tags = [] assert(len(offsets) == len(lengths)) @@ -22,26 +23,31 @@ def make_lengthtags(lengths, offsets, tagname='length', vlen=1): tags.append(tag) return tags + def string_to_vector(string): v = [] for s in string: v.append(ord(s)) return v + def strings_to_vectors(strings, tsb_tag_key): vs = [string_to_vector(string) for string in strings] return packets_to_vectors(vs, tsb_tag_key) + def vector_to_string(v): s = [] for d in v: s.append(chr(d)) return ''.join(s) + def vectors_to_strings(data, tags, tsb_tag_key): packets = vectors_to_packets(data, tags, tsb_tag_key) return [vector_to_string(packet) for packet in packets] + def count_bursts(data, tags, tsb_tag_key, vlen=1): lengthtags = [t for t in tags if pmt.symbol_to_string(t.key) == tsb_tag_key] @@ -51,7 +57,7 @@ def count_bursts(data, tags, tsb_tag_key, vlen=1): raise ValueError( "More than one tags with key {0} with the same offset={1}." .format(tsb_tag_key, tag.offset)) - lengths[tag.offset] = pmt.to_long(tag.value)*vlen + lengths[tag.offset] = pmt.to_long(tag.value) * vlen in_burst = False in_packet = False packet_length = None @@ -60,7 +66,8 @@ def count_bursts(data, tags, tsb_tag_key, vlen=1): for pos in range(len(data)): if pos in lengths: if in_packet: - print("Got tag at pos {0} current packet_pos is {1}".format(pos, packet_pos)) + print("Got tag at pos {0} current packet_pos is {1}".format( + pos, packet_pos)) raise Exception("Received packet tag while in packet.") packet_pos = -1 packet_length = lengths[pos] @@ -72,11 +79,12 @@ def count_bursts(data, tags, tsb_tag_key, vlen=1): in_burst = False if in_packet: packet_pos += 1 - if packet_pos == packet_length-1: + if packet_pos == packet_length - 1: in_packet = False packet_pos = None return burst_count + def vectors_to_packets(data, tags, tsb_tag_key, vlen=1): lengthtags = [t for t in tags if pmt.symbol_to_string(t.key) == tsb_tag_key] @@ -86,7 +94,7 @@ def vectors_to_packets(data, tags, tsb_tag_key, vlen=1): raise ValueError( "More than one tags with key {0} with the same offset={1}." .format(tsb_tag_key, tag.offset)) - lengths[tag.offset] = pmt.to_long(tag.value)*vlen + lengths[tag.offset] = pmt.to_long(tag.value) * vlen if 0 not in lengths: raise ValueError("There is no tag with key {0} and an offset of 0" .format(tsb_tag_key)) @@ -100,12 +108,13 @@ def vectors_to_packets(data, tags, tsb_tag_key, vlen=1): length = lengths[pos] if length == 0: raise ValueError("Packets cannot have zero length.") - if pos+length > len(data): + if pos + length > len(data): raise ValueError("The final packet is incomplete.") - packets.append(data[pos: pos+length]) + packets.append(data[pos: pos + length]) pos += length return packets + def packets_to_vectors(packets, tsb_tag_key, vlen=1): """ Returns a single data vector and a set of tags. If used with blocks.vector_source_X, this set of data @@ -122,4 +131,3 @@ def packets_to_vectors(packets, tsb_tag_key, vlen=1): tags.append(tag) offset = offset + len(packet) return data, tags - diff --git a/gnuradio-runtime/python/gnuradio/gr/pubsub.py b/gnuradio-runtime/python/gnuradio/gr/pubsub.py index 11f53d5597..87e99785a6 100644 --- a/gnuradio-runtime/python/gnuradio/gr/pubsub.py +++ b/gnuradio-runtime/python/gnuradio/gr/pubsub.py @@ -17,9 +17,9 @@ This is a proof of concept implementation, will likely change significantly. class pubsub(dict): def __init__(self): - self._publishers = { } - self._subscribers = { } - self._proxies = { } + self._publishers = {} + self._subscribers = {} + self._proxies = {} def __missing__(self, key, value=None): dict.__setitem__(self, key, value) @@ -41,7 +41,8 @@ class pubsub(dict): sub(val) def __getitem__(self, key): - if key not in self: self.__missing__(key) + if key not in self: + self.__missing__(key) if self._proxies[key] is not None: (p, newkey) = self._proxies[key] return p[newkey] @@ -51,7 +52,8 @@ class pubsub(dict): return dict.__getitem__(self, key) def publish(self, key, publisher): - if key not in self: self.__missing__(key) + if key not in self: + self.__missing__(key) if self._proxies[key] is not None: (p, newkey) = self._proxies[key] p.publish(newkey, publisher) @@ -59,7 +61,8 @@ class pubsub(dict): self._publishers[key] = publisher def subscribe(self, key, subscriber): - if key not in self: self.__missing__(key) + if key not in self: + self.__missing__(key) if self._proxies[key] is not None: (p, newkey) = self._proxies[key] p.subscribe(newkey, subscriber) @@ -81,13 +84,16 @@ class pubsub(dict): self._subscribers[key].remove(subscriber) def proxy(self, key, p, newkey=None): - if key not in self: self.__missing__(key) - if newkey is None: newkey = key + if key not in self: + self.__missing__(key) + if newkey is None: + newkey = key self._proxies[key] = (p, newkey) def unproxy(self, key): self._proxies[key] = None + # Test code if __name__ == "__main__": import sys @@ -106,27 +112,28 @@ if __name__ == "__main__": class subber(object): def __init__(self, param): self._param = param + def printer(self, x): print(self._param, repr(x)) s = subber('param') o.subscribe('foo', s.printer) # The third is a lambda function - o.subscribe('foo', lambda x: sys.stdout.write('val='+repr(x)+'\n')) + o.subscribe('foo', lambda x: sys.stdout.write('val=' + repr(x) + '\n')) # Update key 'foo', will notify subscribers print("Updating 'foo' with three subscribers:") - o['foo'] = 'bar'; + o['foo'] = 'bar' # Remove first subscriber o.unsubscribe('foo', print_len) # Update now will only trigger second and third subscriber print("Updating 'foo' after removing a subscriber:") - o['foo'] = 'bar2'; + o['foo'] = 'bar2' # Publish a key as a function, in this case, a lambda function - o.publish('baz', lambda : 42) + o.publish('baz', lambda: 42) print("Published value of 'baz':", o['baz']) # Unpublish the key diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_flowgraph.py b/gnuradio-runtime/python/gnuradio/gr/qa_flowgraph.py index bbf979d0eb..78eb72222c 100644 --- a/gnuradio-runtime/python/gnuradio/gr/qa_flowgraph.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_flowgraph.py @@ -25,5 +25,6 @@ class test_flowgraph (gr_unittest.TestCase): self.tb.start() self.tb.stop() + if __name__ == '__main__': gr_unittest.run(test_flowgraph) diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py b/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py index 33a758902b..70075013fb 100644 --- a/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py @@ -106,7 +106,7 @@ class test_hier_block2(gr_unittest.TestCase): def test_010_end_with_head(self): import math exp = 1j * 440 / 44100 - src = blocks.vector_source_c([math.e**(exp*n) for n in range(10**6)]) + src = blocks.vector_source_c([math.e**(exp * n) for n in range(10**6)]) head = blocks.head(gr.sizeof_gr_complex, 1000) test = test_hblk([gr.sizeof_gr_complex], 0) tb = gr.top_block() @@ -116,7 +116,7 @@ class test_hier_block2(gr_unittest.TestCase): def test_011_test_message_connect(self): import math exp = 1j * 440 / 44100 - src = blocks.vector_source_c([math.e**(exp*n) for n in range(10**6)]) + src = blocks.vector_source_c([math.e**(exp * n) for n in range(10**6)]) strobe = blocks.message_strobe(pmt.PMT_NIL, 100) head = blocks.head(gr.sizeof_gr_complex, 1000) test = test_hblk([gr.sizeof_gr_complex], 1) @@ -131,7 +131,7 @@ class test_hier_block2(gr_unittest.TestCase): def test_012(self): import math exp = 1j * 440 / 44100 - src = blocks.vector_source_c([math.e**(exp*n) for n in range(10**6)]) + src = blocks.vector_source_c([math.e**(exp * n) for n in range(10**6)]) strobe = blocks.message_strobe(pmt.PMT_NIL, 100) head = blocks.head(gr.sizeof_gr_complex, 1000) test = test_hblk([gr.sizeof_gr_complex], 16) diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_random.py b/gnuradio-runtime/python/gnuradio/gr/qa_random.py index d7f4bb65a5..1f4b8aee15 100644 --- a/gnuradio-runtime/python/gnuradio/gr/qa_random.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_random.py @@ -95,10 +95,11 @@ class test_random(gr_unittest.TestCase): N = 10**6 self.assertEqual(gr.xoroshiro128p_prng.min(), 0) - self.assertEqual(gr.xoroshiro128p_prng.max(), 2**64-1) + self.assertEqual(gr.xoroshiro128p_prng.max(), 2**64 - 1) rng = gr.xoroshiro128p_prng(42) arr = all((0 <= rng() <= 2**64 - 1 for _ in range(N))) self.assertTrue(arr) + if __name__ == '__main__': gr_unittest.run(test_random) diff --git a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py index d48bf8eb78..7d415c28c9 100644 --- a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py +++ b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py @@ -2,13 +2,16 @@ import pmt from . import gr_python as gr + class PythonTag(object): " Python container for tags " + def __init__(self): self.offset = None - self.key = None - self.value = None - self.srcid = False + self.key = None + self.value = None + self.srcid = False + def tag_to_python(tag): """ Convert a stream tag to a Python-readable object """ @@ -19,6 +22,7 @@ def tag_to_python(tag): newtag.srcid = pmt.to_python(tag.srcid) return newtag + def python_to_tag(tag_struct): """ Convert a Python list/tuple/dictionary to a stream tag. diff --git a/gnuradio-runtime/python/gnuradio/gr/top_block.py b/gnuradio-runtime/python/gnuradio/gr/top_block.py index d44c6c46d4..b3cb06d41c 100644 --- a/gnuradio-runtime/python/gnuradio/gr/top_block.py +++ b/gnuradio-runtime/python/gnuradio/gr/top_block.py @@ -9,15 +9,16 @@ from .gr_python import (top_block_pb, - top_block_wait_unlocked, top_block_run_unlocked, - top_block_start_unlocked, top_block_stop_unlocked, - top_block_unlock_unlocked) #, dot_graph_tb) + top_block_wait_unlocked, top_block_run_unlocked, + top_block_start_unlocked, top_block_stop_unlocked, + top_block_unlock_unlocked) # , dot_graph_tb) from .hier_block2 import hier_block2 import threading from .hier_block2 import hier_block2 + class _top_block_waiter(threading.Thread): """ This kludge allows ^C to interrupt top_block.run and top_block.wait @@ -41,6 +42,7 @@ class _top_block_waiter(threading.Thread): See also top_block.wait (below), which uses this class to implement the interruptible wait. """ + def __init__(self, tb): threading.Thread.__init__(self) self.setDaemon(1) diff --git a/gnuradio-runtime/python/gnuradio/gr_unittest.py b/gnuradio-runtime/python/gnuradio/gr_unittest.py index ebd47019a5..8a98cd473d 100644 --- a/gnuradio-runtime/python/gnuradio/gr_unittest.py +++ b/gnuradio-runtime/python/gnuradio/gr_unittest.py @@ -17,6 +17,7 @@ import unittest # We allow snakeCase here for consistency with unittest # pylint: disable=invalid-name + class TestCase(unittest.TestCase): """A subclass of unittest.TestCase that adds additional assertions @@ -32,15 +33,14 @@ class TestCase(unittest.TestCase): Note that decimal places (from zero) is usually not the same as significant digits (measured from the most significant digit). """ - if round(second.real-first.real, places) != 0: + if round(second.real - first.real, places) != 0: raise self.failureException( msg or '%r != %r within %r places' % (first, second, places)) - if round(second.imag-first.imag, places) != 0: + if round(second.imag - first.imag, places) != 0: raise self.failureException( msg or '%r != %r within %r places' % (first, second, places) ) - def assertComplexAlmostEqual2(self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None): """ Fail if the two complex objects are unequal as determined by both @@ -50,20 +50,19 @@ class TestCase(unittest.TestCase): return if abs(ref) > abs_eps: - if abs(ref-x) / abs(ref) > rel_eps: + if abs(ref - x) / abs(ref) > rel_eps: raise self.failureException( msg or '%r != %r rel_error = %r rel_limit = %r' % ( - ref, x, abs(ref-x) / abs(ref), rel_eps + ref, x, abs(ref - x) / abs(ref), rel_eps ) ) else: raise self.failureException( msg or '%r != %r rel_error = %r rel_limit = %r' % ( - ref, x, abs(ref-x) / abs(ref), rel_eps + ref, x, abs(ref - x) / abs(ref), rel_eps ) ) - def assertComplexTuplesAlmostEqual(self, a, b, places=7, msg=None): """ Fail if the two complex tuples are not approximately equal. @@ -76,7 +75,6 @@ class TestCase(unittest.TestCase): for (x, y) in zip(a, b) ]) - def assertComplexTuplesAlmostEqual2(self, a, b, abs_eps=1e-12, rel_eps=1e-6, msg=None): """ @@ -89,7 +87,6 @@ class TestCase(unittest.TestCase): for (x, y) in zip(a, b) ]) - def assertFloatTuplesAlmostEqual(self, a, b, places=7, msg=None): """ Fail if the two real-valued tuples are not approximately equal. @@ -102,7 +99,6 @@ class TestCase(unittest.TestCase): for (x, y) in zip(a, b) ]) - def assertFloatTuplesAlmostEqual2(self, a, b, abs_eps=1e-12, rel_eps=1e-6, msg=None): self.assertEqual(len(a), len(b)) @@ -110,25 +106,25 @@ class TestCase(unittest.TestCase): self.assertComplexAlmostEqual2(x, y, abs_eps, rel_eps, msg) for (x, y) in zip(a, b) ]) - - + def assertSequenceEqualGR(self, data_in, data_out): - """ + """ Note this function exists because of this bug: https://bugs.python.org/issue19217 Calling self.assertEqual(seqA, seqB) can hang if seqA and seqB are not equal. """ if len(data_in) != len(data_out): - print('Lengths do not match: {:d} -- {:d}'.format(len(data_in), len(data_out))) + print( + 'Lengths do not match: {:d} -- {:d}'.format(len(data_in), len(data_out))) self.assertTrue(len(data_in) == len(data_out)) total_miscompares = 0 for idx, item in enumerate(zip(data_in, data_out)): if item[0] != item[1]: total_miscompares += 1 - print('Miscompare at: {:d} ({:d} -- {:d})'.format(idx, item[0], item[1])) + print( + 'Miscompare at: {:d} ({:d} -- {:d})'.format(idx, item[0], item[1])) if total_miscompares > 0: print('Total miscompares: {:d}'.format(total_miscompares)) self.assertTrue(total_miscompares == 0) - def waitFor( self, diff --git a/gnuradio-runtime/python/pmt/pmt_to_python.py b/gnuradio-runtime/python/pmt/pmt_to_python.py index b2777c7c4c..5c65564940 100644 --- a/gnuradio-runtime/python/pmt/pmt_to_python.py +++ b/gnuradio-runtime/python/pmt/pmt_to_python.py @@ -13,7 +13,9 @@ import numpy # getting the singleton locally. PMT_NIL = pmt.get_PMT_NIL() -#define missing +# define missing + + def pmt_to_tuple(p): elems = list() for i in range(pmt.length(p)): @@ -21,10 +23,12 @@ def pmt_to_tuple(p): elems.append(pmt_to_python(elem)) return tuple(elems) + def pmt_from_tuple(p): args = list(map(python_to_pmt, p)) return pmt.make_tuple(*args) + def pmt_to_vector(p): v = list() for i in range(pmt.length(p)): @@ -32,12 +36,14 @@ def pmt_to_vector(p): v.append(pmt_to_python(elem)) return v + def pmt_from_vector(p): v = pmt.make_vector(len(p), PMT_NIL) for i, elem in enumerate(p): pmt.vector_set(v, i, python_to_pmt(elem)) return v + def pmt_to_dict(p): d = dict() items = pmt.dict_items(p) @@ -48,13 +54,15 @@ def pmt_to_dict(p): d[pmt_to_python(k)] = pmt_to_python(v) return d + def pmt_from_dict(p): d = pmt.make_dict() for k, v in list(p.items()): - #dict is immutable -> therefore pmt_dict_add returns the new dict + # dict is immutable -> therefore pmt_dict_add returns the new dict d = pmt.dict_add(d, python_to_pmt(k), python_to_pmt(v)) return d + numpy_mappings = { numpy.dtype(numpy.float32): (pmt.init_f32vector, float, pmt.f32vector_elements, pmt.is_f32vector), numpy.dtype(numpy.float64): (pmt.init_f64vector, float, pmt.f64vector_elements, pmt.is_f64vector), @@ -63,15 +71,17 @@ numpy_mappings = { numpy.dtype(numpy.int8): (pmt.init_s8vector, int, pmt.s8vector_elements, pmt.is_s8vector), numpy.dtype(numpy.int16): (pmt.init_s16vector, int, pmt.s16vector_elements, pmt.is_s16vector), numpy.dtype(numpy.int32): (pmt.init_s32vector, int, pmt.s32vector_elements, pmt.is_s32vector), -# numpy.dtype(numpy.int64): (pmt.init_s64vector, int, pmt.s64vector_elements, pmt.is_s64vector), + # numpy.dtype(numpy.int64): (pmt.init_s64vector, int, pmt.s64vector_elements, pmt.is_s64vector), numpy.dtype(numpy.uint8): (pmt.init_u8vector, int, pmt.u8vector_elements, pmt.is_u8vector), numpy.dtype(numpy.uint16): (pmt.init_u16vector, int, pmt.u16vector_elements, pmt.is_u16vector), numpy.dtype(numpy.uint32): (pmt.init_u32vector, int, pmt.u32vector_elements, pmt.is_u32vector), -# numpy.dtype(numpy.uint64): (pmt.init_u64vector, int, pmt.u64vector_elements, pmt.is_u64vector), + # numpy.dtype(numpy.uint64): (pmt.init_u64vector, int, pmt.u64vector_elements, pmt.is_u64vector), numpy.dtype(numpy.byte): (pmt.init_u8vector, int, pmt.u8vector_elements, pmt.is_u8vector), } -uvector_mappings = dict([ (numpy_mappings[key][3], (numpy_mappings[key][2], key)) for key in numpy_mappings ]) +uvector_mappings = dict( + [(numpy_mappings[key][3], (numpy_mappings[key][2], key)) for key in numpy_mappings]) + def numpy_to_uvector(numpy_array): try: @@ -79,18 +89,22 @@ def numpy_to_uvector(numpy_array): pc = list(map(mapping[1], numpy.ravel(numpy_array))) return mapping[0](numpy_array.size, pc) except KeyError: - raise ValueError("unsupported numpy array dtype for conversion to pmt %s"%(numpy_array.dtype)) + raise ValueError( + "unsupported numpy array dtype for conversion to pmt %s" % (numpy_array.dtype)) + def uvector_to_numpy(uvector): - match = None - for test_func in list(uvector_mappings.keys()): - if test_func(uvector): - match = uvector_mappings[test_func] - return numpy.array(match[0](uvector), dtype = match[1]) - else: - raise ValueError("unsupported uvector data type for conversion to numpy array %s"%(uvector)) - -type_mappings = ( #python type, check pmt type, to python, from python + match = None + for test_func in list(uvector_mappings.keys()): + if test_func(uvector): + match = uvector_mappings[test_func] + return numpy.array(match[0](uvector), dtype=match[1]) + else: + raise ValueError( + "unsupported uvector data type for conversion to numpy array %s" % (uvector)) + + +type_mappings = ( # python type, check pmt type, to python, from python (None, pmt.is_null, lambda x: None, lambda x: PMT_NIL), (bool, pmt.is_bool, pmt.to_bool, pmt.from_bool), (str, pmt.is_symbol, pmt.symbol_to_string, pmt.string_to_symbol), @@ -102,23 +116,29 @@ type_mappings = ( #python type, check pmt type, to python, from python (tuple, pmt.is_tuple, pmt_to_tuple, pmt_from_tuple), (list, pmt.is_vector, pmt_to_vector, pmt_from_vector), (dict, pmt.is_dict, pmt_to_dict, pmt_from_dict), - (tuple, pmt.is_pair, lambda x: (pmt_to_python(pmt.car(x)), pmt_to_python(pmt.cdr(x))), lambda x: pmt.cons(python_to_pmt(x[0]), python_to_pmt(x[1]))), + (tuple, pmt.is_pair, lambda x: (pmt_to_python(pmt.car(x)), pmt_to_python( + pmt.cdr(x))), lambda x: pmt.cons(python_to_pmt(x[0]), python_to_pmt(x[1]))), (numpy.ndarray, pmt.is_uniform_vector, uvector_to_numpy, numpy_to_uvector), ) + def pmt_to_python(p): for python_type, pmt_check, to_python, from_python in type_mappings: if pmt_check(p): try: return to_python(p) - except (RuntimeError, TypeError, ValueError): # TODO: make pybind11 handle wrong_type, convert to type error + # TODO: make pybind11 handle wrong_type, convert to type error + except (RuntimeError, TypeError, ValueError): # This exception will be handled by the general failure case pass - raise ValueError("can't convert %s type to pmt (%s)"%(type(p),p)) + raise ValueError("can't convert %s type to pmt (%s)" % (type(p), p)) + def python_to_pmt(p): for python_type, pmt_check, to_python, from_python in type_mappings: if python_type is None: - if p is None: return from_python(p) - elif isinstance(p, python_type): return from_python(p) - raise ValueError("can't convert %s type to pmt (%s)"%(type(p),p)) + if p is None: + return from_python(p) + elif isinstance(p, python_type): + return from_python(p) + raise ValueError("can't convert %s type to pmt (%s)" % (type(p), p)) |