Revision 4af111d3 gr-qtgui/apps/gr_constellation_plot
| b/gr-qtgui/apps/gr_constellation_plot | ||
|---|---|---|
| 33 | 33 |
print "Error: Program requires PyQt4 and gr-qtgui." |
| 34 | 34 |
sys.exit(1) |
| 35 | 35 |
|
| 36 |
try: |
|
| 37 |
import scipy |
|
| 38 |
except ImportError: |
|
| 39 |
print "Error: Scipy required (www.scipy.org)." |
|
| 40 |
sys.exit(1) |
|
| 41 |
|
|
| 42 |
from plot_form import * |
|
| 43 |
|
|
| 44 |
def read_samples(filename, start, in_size): |
|
| 45 |
# Read in_size number of samples from file |
|
| 46 |
fhandle = open(filename, 'r') |
|
| 47 |
fhandle.seek(start*gr.sizeof_gr_complex, 0) |
|
| 48 |
data = scipy.fromfile(fhandle, dtype=scipy.complex64, count=in_size) |
|
| 49 |
data = data.tolist() |
|
| 50 |
fhandle.close() |
|
| 51 |
|
|
| 52 |
if(len(data) < in_size): |
|
| 53 |
print "Warning: read in {0} samples but asked for {1} samples.".format(
|
|
| 54 |
len(data), in_size) |
|
| 55 |
|
|
| 56 |
return data |
|
| 57 |
|
|
| 36 | 58 |
class my_top_block(gr.top_block): |
| 37 |
def __init__(self, filelist, fc, samp_rate, psdsize, start, nsamples):
|
|
| 59 |
def __init__(self, filelist, start, nsamples, max_nsamples):
|
|
| 38 | 60 |
gr.top_block.__init__(self) |
| 39 | 61 |
|
| 40 | 62 |
self._filelist = filelist |
| 41 |
self._center_freq = fc |
|
| 42 |
self._samp_rate = samp_rate |
|
| 43 |
self._psd_size = psdsize |
|
| 44 | 63 |
self._start = start |
| 45 |
self._nsamps = nsamples
|
|
| 64 |
self._max_nsamps = max_nsamples
|
|
| 46 | 65 |
self._nsigs = len(self._filelist) |
| 47 | 66 |
|
| 67 |
if(nsamples is None): |
|
| 68 |
self._nsamps = max_nsamples |
|
| 69 |
else: |
|
| 70 |
self._nsamps = nsamples |
|
| 71 |
|
|
| 48 | 72 |
self.qapp = QtGui.QApplication(sys.argv) |
| 49 | 73 |
|
| 50 | 74 |
self.skip = gr.skiphead(gr.sizeof_gr_complex, self._start) |
| 51 |
self.head = gr.head(gr.sizeof_gr_complex, self._nsamps) |
|
| 52 |
self.gui_snk = qtgui.const_sink_c(self._psd_size, |
|
| 75 |
self.gui_snk = qtgui.const_sink_c(self._nsamps, |
|
| 53 | 76 |
"GNU Radio Constellation Plot", |
| 54 | 77 |
self._nsigs) |
| 55 | 78 |
n = 0 |
| 56 | 79 |
self.srcs = list() |
| 57 | 80 |
for f in filelist: |
| 58 |
self.srcs.append(gr.file_source(gr.sizeof_gr_complex, f)) |
|
| 81 |
data = read_samples(f, self._start, self._nsamps) |
|
| 82 |
self.srcs.append(gr.vector_source_c(data)) |
|
| 59 | 83 |
|
| 60 | 84 |
# Set default labels based on file names |
| 61 | 85 |
self.gui_snk.set_title(n, "{0}".format(f))
|
| 62 | 86 |
n += 1 |
| 63 | 87 |
|
| 64 | 88 |
self.connect(self.srcs[0], self.skip) |
| 65 |
self.connect(self.skip, self.head) |
|
| 66 |
self.connect(self.head, (self.gui_snk, 0)) |
|
| 89 |
self.connect(self.skip, (self.gui_snk, 0)) |
|
| 67 | 90 |
|
| 68 | 91 |
for i,s in enumerate(self.srcs[1:]): |
| 69 | 92 |
self.connect(s, (self.gui_snk, i+1)) |
| 70 | 93 |
|
| 71 | 94 |
# Get Python Qt references |
| 72 | 95 |
pyQt = self.gui_snk.pyqwidget() |
| 73 |
pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) |
|
| 74 |
pyWin.show() |
|
| 96 |
self.pyWin = sip.wrapinstance(pyQt, QtGui.QWidget) |
|
| 97 |
|
|
| 98 |
def get_gui(self): |
|
| 99 |
return self.pyWin |
|
| 100 |
|
|
| 101 |
def reset(self, newstart, newnsamps): |
|
| 102 |
self.stop() |
|
| 103 |
self.wait() |
|
| 104 |
|
|
| 105 |
self._start = newstart |
|
| 106 |
|
|
| 107 |
for s,f in zip(self.srcs, self._filelist): |
|
| 108 |
data = read_samples(f, self._start, newnsamps) |
|
| 109 |
s.set_data(data) |
|
| 110 |
if(len(data) < newnsamps): |
|
| 111 |
newnsamps = len(data) |
|
| 112 |
|
|
| 113 |
self._nsamps = newnsamps |
|
| 114 |
self.gui_snk.set_nsamps(self._nsamps) |
|
| 115 |
|
|
| 116 |
self.start() |
|
| 75 | 117 |
|
| 76 | 118 |
def main(): |
| 77 | 119 |
description = "Plots the constellations of a list of files." |
| ... | ... | |
| 81 | 123 |
help="Set the number of samples to display [default=prints entire file]") |
| 82 | 124 |
parser.add_option("-S", "--start", type="int", default=0,
|
| 83 | 125 |
help="Starting sample number [default=%default]") |
| 84 |
parser.add_option("-L", "--psd-size", type="int", default=2048,
|
|
| 85 |
help="Set the FFT size of the PSD [default=%default]") |
|
| 86 |
parser.add_option("-f", "--center-frequency", type="eng_float", default=0.0,
|
|
| 87 |
help="Set the center frequency of the signal [default=%default]") |
|
| 88 |
parser.add_option("-r", "--sample-rate", type="eng_float", default=1.0,
|
|
| 89 |
help="Set the sample rate of the signal [default=%default]") |
|
| 90 | 126 |
(options, args) = parser.parse_args() |
| 91 | 127 |
|
| 92 | 128 |
if(len(args) < 1): |
| ... | ... | |
| 95 | 131 |
|
| 96 | 132 |
filelist = list(args) |
| 97 | 133 |
|
| 98 |
# Use the user-specified number of samples for all files if given; |
|
| 99 |
# otherwise, find the number of samples in all files and use the |
|
| 100 |
# largest value for everyone. |
|
| 101 | 134 |
nsamples = options.nsamples |
| 102 |
if(nsamples is None): |
|
| 103 |
filesizes = [] |
|
| 104 |
for f in filelist: |
|
| 105 |
if(os.path.exists(f)): |
|
| 106 |
filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex) |
|
| 107 |
nsamples = max(filesizes) |
|
| 135 |
|
|
| 136 |
# Find the smallest number of samples in all files and use that as |
|
| 137 |
# a maximum value possible. |
|
| 138 |
filesizes = [] |
|
| 139 |
for f in filelist: |
|
| 140 |
if(os.path.exists(f)): |
|
| 141 |
filesizes.append(os.path.getsize(f) / gr.sizeof_gr_complex) |
|
| 142 |
max_nsamples = min(filesizes) |
|
| 108 | 143 |
|
| 109 | 144 |
tb = my_top_block(filelist, |
| 110 |
options.center_frequency, options.sample_rate, |
|
| 111 |
options.psd_size, |
|
| 112 |
options.start, nsamples); |
|
| 113 |
tb.start() |
|
| 145 |
options.start, nsamples, max_nsamples); |
|
| 146 |
|
|
| 147 |
main_box = dialog_box(tb, 'GNU Radio Constellation Plot') |
|
| 148 |
main_box.show() |
|
| 149 |
|
|
| 150 |
tb.run() |
|
| 114 | 151 |
tb.qapp.exec_() |
| 115 |
tb.stop() |
|
| 116 | 152 |
|
| 117 | 153 |
if __name__ == "__main__": |
| 118 | 154 |
try: |
Also available in: Unified diff