Changeset 7654

Show
Ignore:
Timestamp:
02/13/08 11:38:11
Author:
jcorgan
Message:

Merged relevant portions of changeset r7324 from trunk into release branch.
Adds plotting utilties, gr.peak_detector2, and branchless clipping.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gnuradio/branches/releases/3.1/AUTHORS

    r5957 r7654  
    1212Johnathan Corgan <jcorgan@corganenterprises.com>  Build system, ongoing stuff, release manager 
    1313Bdale Garbee <bdale@gag.com>           Debian release packages 
     14Tom Rondeau <trondeau@vt.edu>          Mostly digital waveforms and a little bit of trouble 
  • gnuradio/branches/releases/3.1/gnuradio-core/src/lib/general/Makefile.am

    r6626 r7654  
    9999        gr_pa_2x2_phase_combiner.cc     \ 
    100100        gr_packet_sink.cc               \ 
     101        gr_peak_detector2_fb.cc         \ 
    101102        gr_phase_modulator_fc.cc        \ 
    102103        gr_pll_carriertracking_cc.cc    \ 
     
    231232        gr_pa_2x2_phase_combiner.h      \ 
    232233        gr_packet_sink.h                \ 
     234        gr_peak_detector2_fb.h          \ 
    233235        gr_phase_modulator_fc.h         \ 
    234236        gr_pll_carriertracking_cc.h     \ 
     
    364366        gr_pa_2x2_phase_combiner.i      \ 
    365367        gr_packet_sink.i                \ 
     368        gr_peak_detector2_fb.i          \ 
    366369        gr_phase_modulator_fc.i         \ 
    367370        gr_pll_carriertracking_cc.i     \ 
  • gnuradio/branches/releases/3.1/gnuradio-core/src/lib/general/general.i

    r6626 r7654  
    119119#include <gr_glfsr_source_b.h> 
    120120#include <gr_glfsr_source_f.h> 
     121#include <gr_peak_detector2_fb.h> 
    121122%} 
    122123 
     
    217218%include "gr_glfsr_source_b.i" 
    218219%include "gr_glfsr_source_f.i" 
     220%include "gr_peak_detector2_fb.i" 
  • gnuradio/branches/releases/3.1/gnuradio-core/src/lib/general/gr_math.h

    r7517 r7654  
    6666} 
    6767 
     68 
     69/* This bounds x by +/- clip without a branch */ 
     70 
     71static inline float gr_branchless_clip(float x, float clip) 
     72{ 
     73  float x1 = fabsf(x+clip); 
     74  float x2 = fabsf(x-clip); 
     75  x1 -= x2; 
     76  return 0.5*x1; 
     77} 
     78 
     79 
     80 
    6881#endif /* _GR_MATH_H_ */ 
  • gnuradio/branches/releases/3.1/gnuradio-core/src/utils/gr_plot_const.py

    r6044 r7654  
    2121#  
    2222 
    23 import pylab, math 
     23import scipy 
    2424from pylab import * 
    25 import struct, sy
     25from matplotlib.font_manager import fontManager, FontPropertie
    2626from optparse import OptionParser 
    2727 
    28 import gr_read_binary 
     28matplotlib.interactive(True) 
     29matplotlib.use('TkAgg') 
    2930 
    30 class zoom: 
    31     def __init__(self, xdata, reals, imags, sp_iq, sp_const, plot_const, manager): 
    32         self.sp_iq = sp_iq 
    33         self.sp_const = sp_const 
    34         self.xaxis = xdata 
    35         self.reals = reals 
    36         self.imags = imags 
    37         self.plot_const = plot_const 
    38         self.manager = manager 
     31class draw_constellation: 
     32    def __init__(self, filename, options): 
     33        self.hfile = open(filename, "r") 
     34        self.block_length = options.block 
     35        self.start = options.start 
     36        self.sample_rate = options.sample_rate 
     37 
     38        self.axis_font_size = 16 
     39        self.label_font_size = 18 
     40        self.title_font_size = 20 
     41 
     42        # Setup PLOT 
     43        self.fig = figure(1, figsize=(16, 9), facecolor='w') 
     44        rcParams['xtick.labelsize'] = self.axis_font_size 
     45        rcParams['ytick.labelsize'] = self.axis_font_size 
     46         
     47        self.text_file     = figtext(0.10, 0.95, ("File: %s" % filename), weight="heavy", size=16) 
     48        self.text_file_pos = figtext(0.10, 0.90, "File Position: ", weight="heavy", size=16) 
     49        self.text_block    = figtext(0.40, 0.90, ("Block Size: %d" % self.block_length), 
     50                                     weight="heavy", size=16)         
     51        self.text_sr       = figtext(0.60, 0.90, ("Sample Rate: %.2f" % self.sample_rate), 
     52                                     weight="heavy", size=16) 
     53        self.make_plots() 
     54 
     55        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], frameon=True) 
     56        self.button_left = Button(self.button_left_axes, "<") 
     57        self.button_left_callback = self.button_left.on_clicked(self.button_left_click) 
     58 
     59        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], frameon=True) 
     60        self.button_right = Button(self.button_right_axes, ">") 
     61        self.button_right_callback = self.button_right.on_clicked(self.button_right_click) 
    3962 
    4063        self.xlim = self.sp_iq.get_xlim() 
    41             
    42     def __call__(self, event): 
     64 
     65        self.manager = get_current_fig_manager() 
     66        connect('draw_event', self.zoom) 
     67        connect('key_press_event', self.click) 
     68        show() 
     69 
     70    def get_data(self): 
     71        self.text_file_pos.set_text("File Position: %d" % (self.hfile.tell()//8)) 
     72        iq = scipy.fromfile(self.hfile, dtype=scipy.complex64, count=self.block_length) 
     73        #print "Read in %d items" % len(iq) 
     74        if(len(iq) == 0): 
     75            print "End of File" 
     76        else: 
     77            self.reals = [r.real for r in iq] 
     78            self.imags = [i.imag for i in iq] 
     79 
     80            self.time = [i*(1/self.sample_rate) for i in range(len(self.reals))] 
     81             
     82    def make_plots(self): 
     83        # if specified on the command-line, set file pointer 
     84        self.hfile.seek(16*self.start, 1) 
     85 
     86        self.get_data() 
     87         
     88        # Subplot for real and imaginary parts of signal 
     89        self.sp_iq = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.4, 0.6]) 
     90        self.sp_iq.set_title(("I&Q"), fontsize=self.title_font_size, fontweight="bold") 
     91        self.sp_iq.set_xlabel("Time (s)", fontsize=self.label_font_size, fontweight="bold") 
     92        self.sp_iq.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, fontweight="bold") 
     93        self.plot_iq = plot(self.time, self.reals, 'bo-', self.time, self.imags, 'ro-') 
     94        self.sp_iq.axis([min(self.time), max(self.time), 
     95                         1.5*min([min(self.reals), min(self.imags)]), 
     96                         1.5*max([max(self.reals), max(self.imags)])]) 
     97 
     98        # Subplot for constellation plot 
     99        self.sp_const = self.fig.add_subplot(2,2,1, position=[0.575, 0.2, 0.4, 0.6]) 
     100        self.sp_const.set_title(("Constellation"), fontsize=self.title_font_size, fontweight="bold") 
     101        self.sp_const.set_xlabel("Inphase", fontsize=self.label_font_size, fontweight="bold") 
     102        self.sp_const.set_ylabel("Qaudrature", fontsize=self.label_font_size, fontweight="bold") 
     103        self.plot_const = plot(self.reals, self.imags, 'bo') 
     104        self.sp_const.axis([-2, 2, -2, 2]) 
     105 
     106        draw() 
     107 
     108    def update_plots(self): 
     109        self.plot_iq[0].set_data([self.time, self.reals]) 
     110        self.plot_iq[1].set_data([self.time, self.imags]) 
     111        self.sp_iq.axis([min(self.time), max(self.time), 
     112                         1.5*min([min(self.reals), min(self.imags)]), 
     113                         1.5*max([max(self.reals), max(self.imags)])]) 
     114 
     115        self.plot_const[0].set_data([self.reals, self.imags]) 
     116        self.sp_const.axis([-2, 2, -2, 2]) 
     117        draw() 
     118         
     119    def zoom(self, event): 
    43120        newxlim = self.sp_iq.get_xlim() 
    44  
    45121        if(newxlim != self.xlim): 
    46122            self.xlim = newxlim 
    47             r = self.reals[int(self.xlim[0]) : int(self.xlim[1])] 
    48             i = self.imags[int(self.xlim[0]) : int(self.xlim[1])] 
     123            r = self.reals[int(ceil(self.xlim[0])) : int(ceil(self.xlim[1]))] 
     124            i = self.imags[int(ceil(self.xlim[0])) : int(ceil(self.xlim[1]))] 
    49125 
    50126            self.plot_const[0].set_data(r, i) 
    51127            self.sp_const.axis([-2, 2, -2, 2]) 
    52128            self.manager.canvas.draw() 
     129            draw() 
     130 
     131    def click(self, event): 
     132        forward_valid_keys = [" ", "down", "right"] 
     133        backward_valid_keys = ["up", "left"] 
     134 
     135        if(find(event.key, forward_valid_keys)): 
     136            self.step_forward() 
    53137             
     138        elif(find(event.key, backward_valid_keys)): 
     139            self.step_backward() 
     140 
     141    def button_left_click(self, event): 
     142        self.step_backward() 
     143 
     144    def button_right_click(self, event): 
     145        self.step_forward() 
     146 
     147    def step_forward(self): 
     148        self.get_data() 
     149        self.update_plots() 
     150 
     151    def step_backward(self): 
     152        # Step back in file position 
     153        if(self.hfile.tell() >= 16*self.block_length ): 
     154            self.hfile.seek(-16*self.block_length, 1) 
     155        else: 
     156            self.hfile.seek(-self.hfile.tell(),1) 
     157        self.get_data() 
     158        self.update_plots() 
     159         
     160             
     161 
     162#FIXME: there must be a way to do this with a Python builtin 
     163def find(item_in, list_search): 
     164    for l in list_search: 
     165        if item_in == l: 
     166            return True 
     167    return False 
     168 
    54169def main(): 
    55     usage="%prog: [options] output_filename" 
    56     parser = OptionParser(conflict_handler="resolve", usage=usage) 
    57     parser.add_option("-s", "--size", type="int", default=None, 
    58                       help="Specify the number of points to plot [default=%default]") 
    59     parser.add_option("", "--skip", type="int", default=None, 
    60                       help="Specify the number of points to skip [default=%default]") 
     170    usage="%prog: [options] input_filename" 
     171    description = "Takes a GNU Radio complex binary file and displays the I&Q data versus time and the constellation plot (I vs. Q). You can set the block size to specify how many points to read in at a time and the start position in the file. By default, the system assumes a sample rate of 1, so in time, each sample is plotted versus the sample number. To set a true time axis, set the sample rate (-R or --sample-rate) to the sample rate used when capturing the samples." 
    61172 
     173    parser = OptionParser(conflict_handler="resolve", usage=usage, description=description) 
     174    parser.add_option("-B", "--block", type="int", default=1000, 
     175                      help="Specify the block size [default=%default]") 
     176    parser.add_option("-s", "--start", type="int", default=0, 
     177                      help="Specify where to start in the file [default=%default]") 
     178    parser.add_option("-R", "--sample-rate", type="float", default=1.0, 
     179                      help="Set the sampler rate of the data [default=%default]") 
     180     
    62181    (options, args) = parser.parse_args () 
    63182    if len(args) != 1: 
     
    66185    filename = args[0] 
    67186 
    68     iq = gr_read_binary.read_complex_binary(filename) 
    69  
    70     if(options.skip is None): 
    71         options.skip = 0 
    72      
    73     if((options.size is None) or ((options.skip+options.size) > len(iq[0]))): 
    74         options.size = len(iq[0]) - options.skip 
    75  
    76     reals = iq[0][options.skip : options.skip + options.size] 
    77     imags = iq[1][options.skip : options.skip + options.size] 
    78     x = range(options.skip, options.skip + options.size) 
    79      
    80     # PLOT 
    81     f = figure(1, figsize=(16, 12), facecolor='w') 
    82     rcParams['xtick.labelsize'] = 16 
    83     rcParams['ytick.labelsize'] = 16 
    84  
    85     # Subplot for real and imaginary parts of signal 
    86     sp1 = f.add_subplot(2,1,1) 
    87     sp1.set_title(("I&Q"), fontsize=26, fontweight="bold") 
    88     sp1.set_xlabel("Time (s)", fontsize=20, fontweight="bold") 
    89     sp1.set_ylabel("Amplitude (V)", fontsize=20, fontweight="bold") 
    90     plot(x, reals, 'bo-', x, imags, 'ro-') 
    91  
    92     # Subplot for constellation plot 
    93     sp2 = f.add_subplot(2,1,2) 
    94     sp2.set_title(("Constellation"), fontsize=26, fontweight="bold") 
    95     sp2.set_xlabel("Inphase", fontsize=20, fontweight="bold") 
    96     sp2.set_ylabel("Qaudrature", fontsize=20, fontweight="bold") 
    97     p2 = plot(reals, imags, 'bo') 
    98     sp2.axis([-2, 2, -2, 2]) 
    99      
    100     manager = get_current_fig_manager() 
    101     zm = zoom(x, reals, imags, sp1, sp2, p2, manager) 
    102     connect('draw_event', zm) 
    103      
    104     show() 
     187    dc = draw_constellation(filename, options) 
    105188 
    106189if __name__ == "__main__": 
  • gnuradio/branches/releases/3.1/gnuradio-core/src/utils/gr_plot_float.py

    r6044 r7654  
    2121#  
    2222 
    23 import pylab, math 
     23import scipy 
    2424from pylab import * 
    25 import struct, sys 
    2625from optparse import OptionParser 
    2726 
    28 import gr_read_binary 
     27matplotlib.interactive(True) 
     28matplotlib.use('TkAgg') 
     29 
     30class draw_fft_c: 
     31    def __init__(self, filename, options): 
     32        self.hfile = open(filename, "r") 
     33        self.block_length = options.block 
     34        self.start = options.start 
     35        self.sample_rate = options.sample_rate 
     36 
     37        self.axis_font_size = 16 
     38        self.label_font_size = 18 
     39        self.title_font_size = 20 
     40        self.text_size = 22 
     41 
     42        # Setup PLOT 
     43        self.fig = figure(1, figsize=(16, 9), facecolor='w') 
     44        rcParams['xtick.labelsize'] = self.axis_font_size 
     45        rcParams['ytick.labelsize'] = self.axis_font_size 
     46         
     47        self.text_file     = figtext(0.10, 0.94, ("File: %s" % filename), weight="heavy", size=self.text_size) 
     48        self.text_file_pos = figtext(0.10, 0.88, "File Position: ", weight="heavy", size=self.text_size) 
     49        self.text_block    = figtext(0.40, 0.88, ("Block Size: %d" % self.block_length), 
     50                                     weight="heavy", size=self.text_size) 
     51        self.text_sr       = figtext(0.60, 0.88, ("Sample Rate: %.2f" % self.sample_rate), 
     52                                     weight="heavy", size=self.text_size) 
     53        self.make_plots() 
     54 
     55        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], frameon=True) 
     56        self.button_left = Button(self.button_left_axes, "<") 
     57        self.button_left_callback = self.button_left.on_clicked(self.button_left_click) 
     58 
     59        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], frameon=True) 
     60        self.button_right = Button(self.button_right_axes, ">") 
     61        self.button_right_callback = self.button_right.on_clicked(self.button_right_click) 
     62 
     63        self.xlim = self.sp_f.get_xlim() 
     64 
     65        self.manager = get_current_fig_manager() 
     66        connect('key_press_event', self.click) 
     67        show() 
     68         
     69    def get_data(self): 
     70        self.text_file_pos.set_text("File Position: %d" % (self.hfile.tell()//4)) 
     71        f = scipy.fromfile(self.hfile, dtype=scipy.float32, count=self.block_length) 
     72        #print "Read in %d items" % len(self.f) 
     73        if(len(f) == 0): 
     74            print "End of File" 
     75        else: 
     76            self.f = f 
     77            self.time = [i*(1/self.sample_rate) for i in range(len(self.f))] 
     78         
     79    def make_plots(self): 
     80        # if specified on the command-line, set file pointer 
     81        self.hfile.seek(8*self.start, 1) 
     82 
     83        self.get_data() 
     84         
     85        # Subplot for real and imaginary parts of signal 
     86        self.sp_f = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.875, 0.6]) 
     87        self.sp_f.set_title(("Amplitude"), fontsize=self.title_font_size, fontweight="bold") 
     88        self.sp_f.set_xlabel("Time (s)", fontsize=self.label_font_size, fontweight="bold") 
     89        self.sp_f.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, fontweight="bold") 
     90        self.plot_f = plot(self.time, self.f, 'bo-') 
     91        self.sp_f.set_ylim([1.5*min(self.f), 
     92                            1.5*max(self.f)]) 
     93 
     94        draw() 
     95 
     96    def update_plots(self): 
     97        self.plot_f[0].set_data([self.time, self.f]) 
     98        self.sp_f.set_ylim([1.5*min(self.f), 
     99                            1.5*max(self.f)]) 
     100        draw() 
     101         
     102    def click(self, event): 
     103        forward_valid_keys = [" ", "down", "right"] 
     104        backward_valid_keys = ["up", "left"] 
     105 
     106        if(find(event.key, forward_valid_keys)): 
     107            self.step_forward() 
     108             
     109        elif(find(event.key, backward_valid_keys)): 
     110            self.step_backward() 
     111 
     112    def button_left_click(self, event): 
     113        self.step_backward() 
     114 
     115    def button_right_click(self, event): 
     116        self.step_forward() 
     117 
     118    def step_forward(self): 
     119        self.get_data() 
     120        self.update_plots() 
     121 
     122    def step_backward(self): 
     123        # Step back in file position 
     124        if(self.hfile.tell() >= 8*self.block_length ): 
     125            self.hfile.seek(-8*self.block_length, 1) 
     126        else: 
     127            self.hfile.seek(-self.hfile.tell(),1) 
     128        self.get_data() 
     129        self.update_plots() 
     130         
     131             
     132 
     133#FIXME: there must be a way to do this with a Python builtin 
     134def find(item_in, list_search): 
     135    for l in list_search: 
     136        if item_in == l: 
     137            return True 
     138    return False 
    29139 
    30140def main(): 
    31     usage="%prog: [options] output_filename" 
    32     parser = OptionParser(conflict_handler="resolve", usage=usage) 
    33     parser.add_option("-s", "--size", type="int", default=None, 
    34                       help="Specify the number of points to plot [default=%default]") 
    35     parser.add_option("", "--skip", type="int", default=None, 
    36                       help="Specify the number of points to skip [default=%default]") 
     141    usage="%prog: [options] input_filename" 
     142    description = "Takes a GNU Radio floating point binary file and displays the samples versus time. You can set the block size to specify how many points to read in at a time and the start position in the file. By default, the system assumes a sample rate of 1, so in time, each sample is plotted versus the sample number. To set a true time axis, set the sample rate (-R or --sample-rate) to the sample rate used when capturing the samples." 
    37143 
     144    parser = OptionParser(conflict_handler="resolve", usage=usage, description=description) 
     145    parser.add_option("-B", "--block", type="int", default=1000, 
     146                      help="Specify the block size [default=%default]") 
     147    parser.add_option("-s", "--start", type="int", default=0, 
     148                      help="Specify where to start in the file [default=%default]") 
     149    parser.add_option("-R", "--sample-rate", type="float", default=1.0, 
     150                      help="Set the sampler rate of the data [default=%default]") 
     151     
    38152    (options, args) = parser.parse_args () 
    39153    if len(args) != 1: 
     
    42156    filename = args[0] 
    43157 
    44     fl = gr_read_binary.read_float_binary(filename) 
    45  
    46     if(options.skip is None): 
    47         options.skip = 0 
    48      
    49     if((options.size is None) or ((options.skip+options.size) > len(iq[0]))): 
    50         options.size = len(fl) - options.skip 
    51  
    52     x = range(options.skip, options.skip + options.size) 
    53      
    54     # PLOT REAL AND IMAGINARY PARTS 
    55      
    56     f = figure(1, figsize=(16, 12), facecolor='w') 
    57     rcParams['xtick.labelsize'] = 16 
    58     rcParams['ytick.labelsize'] = 16 
    59  
    60     sp1 = f.add_subplot(1,1,1) 
    61     sp1.set_title(("GNU Radio Float"), fontsize=26, fontweight="bold") 
    62     sp1.set_xlabel("Time (s)", fontsize=20, fontweight="bold") 
    63     sp1.set_ylabel("Amplitude (V)", fontsize=20, fontweight="bold") 
    64     plot(x, fl, 'bo-') 
    65  
    66     show() 
     158    dc = draw_fft_c(filename, options) 
    67159 
    68160if __name__ == "__main__": 
     
    72164        pass 
    73165     
    74  
    75  
  • gnuradio/branches/releases/3.1/gnuradio-core/src/utils/gr_plot_iq.py

    r6044 r7654  
    2121#  
    2222 
    23 import pylab, math 
     23import scipy 
    2424from pylab import * 
    25 import struct, sys 
    2625from optparse import OptionParser 
    2726 
    28 import gr_read_binary 
     27matplotlib.interactive(True) 
     28matplotlib.use('TkAgg') 
     29 
     30class draw_fft: 
     31    def __init__(self, filename, options): 
     32        self.hfile = open(filename, "r") 
     33        self.block_length = options.block 
     34        self.start = options.start 
     35        self.sample_rate = options.sample_rate 
     36 
     37        self.axis_font_size = 16 
     38        self.label_font_size = 18 
     39        self.title_font_size = 20 
     40        self.text_size = 22 
     41 
     42        # Setup PLOT 
     43        self.fig = figure(1, figsize=(16, 9), facecolor='w') 
     44        rcParams['xtick.labelsize'] = self.axis_font_size 
     45        rcParams['ytick.labelsize'] = self.axis_font_size 
     46         
     47        self.text_file     = figtext(0.10, 0.94, ("File: %s" % filename), weight="heavy", size=self.text_size) 
     48        self.text_file_pos = figtext(0.10, 0.88, "File Position: ", weight="heavy", size=self.text_size) 
     49        self.text_block    = figtext(0.40, 0.88, ("Block Size: %d" % self.block_length), 
     50                                     weight="heavy", size=self.text_size) 
     51        self.text_sr       = figtext(0.60, 0.88, ("Sample Rate: %.2f" % self.sample_rate), 
     52                                     weight="heavy", size=self.text_size) 
     53        self.make_plots() 
     54 
     55        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], frameon=True) 
     56        self.button_left = Button(self.button_left_axes, "<") 
     57        self.button_left_callback = self.button_left.on_clicked(self.button_left_click) 
     58 
     59        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], frameon=True) 
     60        self.button_right = Button(self.button_right_axes, ">") 
     61        self.button_right_callback = self.button_right.on_clicked(self.button_right_click) 
     62 
     63        self.xlim = self.sp_iq.get_xlim() 
     64 
     65        self.manager = get_current_fig_manager() 
     66        connect('key_press_event', self.click) 
     67        show() 
     68 
     69    def get_data(self): 
     70        self.text_file_pos.set_text("File Position: %d" % (self.hfile.tell()//8)) 
     71        self.iq = scipy.fromfile(self.hfile, dtype=scipy.complex64, count=self.block_length) 
     72        #print "Read in %d items" % len(self.iq) 
     73        if(len(self.iq) == 0): 
     74            print "End of File" 
     75        else: 
     76            self.reals = [r.real for r in self.iq] 
     77            self.imags = [i.imag for i in self.iq] 
     78            self.time = [i*(1/self.sample_rate) for i in range(len(self.reals))] 
     79             
     80    def make_plots(self): 
     81        # if specified on the command-line, set file pointer 
     82        self.hfile.seek(16*self.start, 1) 
     83 
     84        self.get_data() 
     85         
     86        # Subplot for real and imaginary parts of signal 
     87        self.sp_iq = self.fig.add_subplot(2,1,1, position=[0.075, 0.14, 0.85, 0.67]) 
     88        self.sp_iq.set_title(("I&Q"), fontsize=self.title_font_size, fontweight="bold") 
     89        self.sp_iq.set_xlabel("Time (s)", fontsize=self.label_font_size, fontweight="bold") 
     90        self.sp_iq.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, fontweight="bold") 
     91        self.plot_iq = plot(self.time, self.reals, 'bo-', self.time, self.imags, 'ro-') 
     92        self.sp_iq.set_ylim([1.5*min([min(self.reals), min(self.imags)]), 
     93                             1.5*max([max(self.reals), max(self.imags)])]) 
     94         
     95        draw() 
     96 
     97    def update_plots(self): 
     98        self.plot_iq[0].set_data([self.time, self.reals]) 
     99        self.plot_iq[1].set_data([self.time, self.imags]) 
     100        self.sp_iq.set_ylim([1.5*min([min(self.reals), min(self.imags)]), 
     101                             1.5*max([max(self.reals), max(self.imags)])]) 
     102        draw() 
     103         
     104    def click(self, event): 
     105        forward_valid_keys = [" ", "down", "right"] 
     106        backward_valid_keys = ["up", "left"] 
     107 
     108        if(find(event.key, forward_valid_keys)): 
     109            self.step_forward() 
     110             
     111        elif(find(event.key, backward_valid_keys)): 
     112            self.step_backward() 
     113 
     114    def button_left_click(self, event): 
     115        self.step_backward() 
     116 
     117    def button_right_click(self, event): 
     118        self.step_forward() 
     119 
     120    def step_forward(self): 
     121        self.get_data() 
     122        self.update_plots() 
     123 
     124    def step_backward(self): 
     125        # Step back in file position 
     126        if(self.hfile.tell() >= 16*self.block_length ): 
     127            self.hfile.seek(-16*self.block_length, 1) 
     128        else: 
     129            self.hfile.seek(-self.hfile.tell(),1) 
     130        self.get_data() 
     131        self.update_plots() 
     132         
     133             
     134 
     135#FIXME: there must be a way to do this with a Python builtin 
     136def find(item_in, list_search): 
     137    for l in list_search: 
     138        if item_in == l: 
     139            return True 
     140    return False 
    29141 
    30142def main(): 
    31     usage="%prog: [options] output_filename" 
    32     parser = OptionParser(conflict_handler="resolve", usage=usage) 
    33     parser.add_option("-s", "--size", type="int", default=None, 
    34                       help="Specify the number of points to plot [default=%default]") 
    35     parser.add_option("", "--skip", type="int", default=None, 
    36                       help="Specify the number of points to skip [default=%default]") 
     143    usage="%prog: [options] input_filename" 
     144    description = "Takes a GNU Radio complex binary file and displays the I&Q data versus time. You can set the block size to specify how many points to read in at a time and the start position in the file. By default, the system assumes a sample rate of 1, so in time, each sample is plotted versus the sample number. To set a true time axis, set the sample rate (-R or --sample-rate) to the sample rate used when capturing the samples." 
    37145 
     146    parser = OptionParser(conflict_handler="resolve", usage=usage, description=description) 
     147    parser.add_option("-B", "--block", type="int", default=1000, 
     148                      help="Specify the block size [default=%default]") 
     149    parser.add_option("-s", "--start", type="int", default=0, 
     150                      help="Specify where to start in the file [default=%default]") 
     151    parser.add_option("-R", "--sample-rate", type="float", default=1.0, 
     152                      help="Set the sampler rate of the data [default=%default]") 
     153     
    38154    (options, args) = parser.parse_args () 
    39155    if len(args) != 1: 
     
    42158    filename = args[0] 
    43159 
    44     iq = gr_read_binary.read_complex_binary(filename) 
    45  
    46     if(options.skip is None): 
    47         options.skip = 0 
    48      
    49     if((options.size is None) or ((options.skip+options.size) > len(iq[0]))): 
    50         options.size = len(iq[0]) - options.skip 
    51  
    52     reals = iq[0][options.skip : options.skip + options.size] 
    53     imags = iq[1][options.skip : options.skip + options.size] 
    54     x = range(options.skip, options.skip + options.size) 
    55      
    56     # PLOT REAL AND IMAGINARY PARTS 
    57      
    58     f = figure(1, figsize=(16, 12), facecolor='w') 
    59     rcParams['xtick.labelsize'] = 16 
    60     rcParams['ytick.labelsize'] = 16 
    61  
    62     sp1 = f.add_subplot(1,1,1) 
    63     sp1.set_title(("I&Q"), fontsize=26, fontweight="bold") 
    64     sp1.set_xlabel("Time (s)", fontsize=20, fontweight="bold") 
    65     sp1.set_ylabel("Amplitude (V)", fontsize=20, fontweight="bold") 
    66     plot(x, reals, 'bo-', x, imags, 'ro-') 
    67  
    68     show() 
     160    dc = draw_fft(filename, options) 
    69161 
    70162if __name__ == "__main__":