def process_capture(self, fstart, fstop, data): # store usable bins before next call to capture_time_domain usable_bins = list(self._capture_device.usable_bins) # only read data if WSA digitizer is used if 'DIGITIZER' in self._state.device_settings['iq_output_path']: if self._state.sweeping(): self.read_sweep() return self.read_block() if 'reflevel' in data['context_pkt']: self._ref_level = data['context_pkt']['reflevel'] pow_data = compute_fft( self._dut, data['data_pkt'], data['context_pkt'], ref=self._ref_level, **self._dsp_options) if not self._options.get('show_attenuated_edges'): pow_data, usable_bins, fstart, fstop = ( trim_to_usable_fstart_fstop( pow_data, usable_bins, fstart, fstop)) self.capture_receive.emit( self._state, fstart, fstop, data['data_pkt'], pow_data, usable_bins, None)
def update(): # update the plot to show new data global p3, z, colors # read data data, context = read_data_and_context(dut, powerSize) # ignore the reference level so plot doesn't change positions context['reflevel'] = STATIC_REFLEVEL # compute the fft of the complex data powData = compute_fft(dut, data, context) # compress the FFT into a 128 array zData = represent_fft_to_plot(powData) # move the data stream as well as colours back to show new data for i in range (ySize): if i == 0: continue else: colors[:,ySize - i,:] = colors[:, ySize - i - 1,:] z[:,ySize - i] = z[:, ySize - i - 1] z[:,0] = zData[:,0] # grab new color colors[:,0,:] = create_color_heatmap(powData) colors[:,1,:] = create_color_heatmap(powData) # update the plot p3.setData(z = z, colors = colors.reshape(xSize*ySize,4))
def process_capture(self, fstart, fstop, data): # store usable bins before next call to capture_time_domain usable_bins = list(self._capture_device.usable_bins) # only read data if WSA digitizer is used if 'DIGITIZER' in self._state.device_settings['iq_output_path']: if self._state.sweeping(): self.read_sweep() return self.read_block() if 'reflevel' in data['context_pkt']: self._ref_level = data['context_pkt']['reflevel'] pow_data = compute_fft(self._dut, data['data_pkt'], data['context_pkt'], ref=self._ref_level, **self._dsp_options) if not self._options.get('show_attenuated_edges'): pow_data, usable_bins, fstart, fstop = ( trim_to_usable_fstart_fstop(pow_data, usable_bins, fstart, fstop)) #FIXME: Find out why there is a case where pow_data may be empty if pow_data.any(): if self._plot_options.get('reference_offset_value'): pow_data += self._plot_options['reference_offset_value'] if self._export_csv: self._export_csv_file(self._state.rfe_mode(), fstart, fstop, pow_data) self.capture_receive.emit(self._state, fstart, fstop, data['data_pkt'], pow_data, usable_bins, None)
def capture_sweep_spectrum(dut, mode, points, dec=1, fshift=0, packets=1): usable_bins = compute_usable_bins(dut.properties, mode, points, dec, fshift) total_pow = [] samples = int(points / packets) # read data for p in range(packets): if p == 0: data, context = collect_data_and_context(dut) else: d, c = collect_data_and_context(dut, samples) data.data.np_array = np.concatenate([data.data.np_array, d.data.np_array]) # adjust fstart and fstop based on the spectral inversion usable_bins, fstart, fstop = adjust_usable_fstart_fstop( dut.properties, mode, points, dec, context["rffreq"], data.spec_inv, usable_bins ) # compute fft pow_data = compute_fft(dut, data, context) if not len(total_pow): total_pow = pow_data else: total_pow = np.add(total_pow, pow_data) pow_data = total_pow # trim FFT pow_data, usable_bins, fstart, fstop = trim_to_usable_fstart_fstop(pow_data, usable_bins, fstart, fstop) return (fstart, fstop, pow_data, context)
def acquire_single_power_spectrum(self): STAIRS_MODE = False self._capture_count += 1 if STAIRS_MODE: STAIR_WIDTH = 50 stair_start = self._capture_count % self._numpts stair_start = np.floor(stair_start / STAIR_WIDTH) * STAIR_WIDTH stair_stop = stair_start + STAIR_WIDTH ps_dBm = np.zeros(self._numpts) - 80 ps_dBm[stair_start:stair_stop] = -20 timestamp_s = self._capture_count else: drv = self._driver vrt_data, context = read_data_and_context(drv, self._numpts) assert isinstance(vrt_data, pyrf.vrt.DataPacket) ps_dBm = compute_fft(drv, vrt_data, context, convert_to_dbm=True) #Accumulate history... timestamp_s = calc_vrt_sample_time_s(vrt_data) self.capture_history.add_row(ps_dBm, timestamp_s=timestamp_s) self._last_power_spectrum_dBm = ps_dBm return ps_dBm
def _playback_step(self): if not self._playback_file: self._playback_started = False return QtCore.QTimer.singleShot(PLAYBACK_STEP_MSEC, self._playback_step) while True: pkt = self._playback_vrt() if pkt.is_context_packet(): if 'speca' in pkt.fields: self._playback_sweep_data = None state_json = pkt.fields['speca'] self._apply_complete_settings(state_json, playback=True) else: self._playback_context.update(pkt.fields) continue if self._state.sweeping(): if not self._playback_sweep_step(pkt): continue return break usable_bins = compute_usable_bins( self._dut.properties, self._state.rfe_mode(), len(pkt.data), self._state.decimation, self._state.fshift) usable_bins, fstart, fstop = adjust_usable_fstart_fstop( self._dut.properties, self._state.rfe_mode(), len(pkt.data), self._state.decimation, self._state.center, pkt.spec_inv, usable_bins) pow_data = compute_fft( self._dut, pkt, self._playback_context, **self._dsp_options) if not self._options.get('show_attenuated_edges'): pow_data, usable_bins, fstart, fstop = ( trim_to_usable_fstart_fstop( pow_data, usable_bins, fstart, fstop)) self.capture_receive.emit( self._state, fstart, fstop, pkt, pow_data, usable_bins, None)
def acquire_single_power_spectrum(self): STAIRS_MODE = False self._capture_count += 1 if STAIRS_MODE: STAIR_WIDTH = 50 stair_start = self._capture_count % self._numpts stair_start = np.floor(stair_start / STAIR_WIDTH) * STAIR_WIDTH stair_stop = stair_start + STAIR_WIDTH ps_dBm = np.zeros(self._numpts) - 80 ps_dBm[stair_start:stair_stop] = -20 timestamp_s = self._capture_count else: drv = self._driver vrt_data, context = read_data_and_context(drv, self._numpts) assert isinstance(vrt_data, pyrf.vrt.DataPacket) ps_dBm = compute_fft(drv, vrt_data, context, convert_to_dbm=True) #Accumulate history... timestamp_s = calc_vrt_sample_time_s(vrt_data) self.capture_history.add_row(ps_dBm, timestamp_s = timestamp_s) self._last_power_spectrum_dBm = ps_dBm return ps_dBm
def _playback_sweep_step(self, pkt): """ process one data packet from a recorded sweep and plot collected data after receiving complete sweep. returns True if data was plotted on this step. """ if self._playback_sweep_data is None: self._playback_sweep_start() last_center = None else: last_center = self._playback_sweep_last_center sweep_start = float(self._state.center - self._state.span / 2) sweep_stop = float(self._state.center + self._state.span / 2) step_center = self._playback_context['rffreq'] updated_plot = False if last_center is not None and last_center >= step_center: # starting a new sweep, plot the data we have self.capture_receive.emit(self._state, sweep_start, sweep_stop, None, self._playback_sweep_data, None, None) updated_plot = True self._playback_sweep_start() self._playback_sweep_last_center = step_center usable_bins = compute_usable_bins(self._dut.properties, self._state.rfe_mode(), len(pkt.data), self._state.decimation, self._state.fshift) usable_bins, fstart, fstop = adjust_usable_fstart_fstop( self._dut.properties, self._state.rfe_mode(), len(pkt.data), self._state.decimation, step_center, pkt.spec_inv, usable_bins) pow_data = compute_fft(self._dut, pkt, self._playback_context, **self._dsp_options) pow_data, usable_bins, fstart, fstop = (trim_to_usable_fstart_fstop( pow_data, usable_bins, fstart, fstop)) clip_left = max(sweep_start, fstart) clip_right = min(sweep_stop, fstop) sweep_points = len(self._playback_sweep_data) point_left = int((clip_left - sweep_start) * sweep_points / (sweep_stop - sweep_start)) point_right = int((clip_right - sweep_start) * sweep_points / (sweep_stop - sweep_start)) xvalues = np.linspace(clip_left, clip_right, point_right - point_left) if point_left >= point_right: logger.info('received sweep step outside sweep: %r, %r' % ((fstart, fstop), (sweep_start, sweep_stop))) else: self._playback_sweep_data[point_left:point_right] = np.interp( xvalues, np.linspace(fstart, fstop, len(pow_data)), pow_data) return updated_plot
def update_screen(self): data, context = read_data_and_context( self.dut, self.points) self.screen.update_data( compute_fft(self.dut, data, context), self.center_freq, self.decimation_factor)
def initDUT(self): self.center_freq = self.dut.freq() self.decimation_factor = self.dut.decimation() data, reflevel = read_data_and_reflevel(self.dut) self.screen.update_data( compute_fft(self.dut, data, reflevel), self.center_freq, self.decimation_factor)
def update_screen(self): data, reflevel = read_data_and_reflevel( self.dut, self.points) self.screen.update_data( compute_fft(self.dut, data, reflevel), self.center_freq, self.decimation_factor)
def read_data(self, spp): """ Check if we have permission to read data. :param spp: the number of samples in a packet :returns: data class, context dictionary, and fft array """ data, context = read_data_and_context(self, spp) pow_data = compute_fft(self, data, context) return data, context, pow_data
def update(): global dut, curve, fft_plot, freq_range, max_location # read data data, context = read_data_and_context(dut, SAMPLE_SIZE) center_freq = context['rffreq'] bandwidth = context['bandwidth'] # compute the fft and plot the data pow_data = compute_fft(dut, data, context) if self.marker_freq == None: self.marker_freq = self.center_freq # update axes limits plot_xmin = (center_freq) - (bandwidth / 2) plot_xmax = (center_freq) + (bandwidth / 2) # update the frequency range (Hz) freq_range = np.linspace(plot_xmin , plot_xmax, SAMPLE_SIZE) # initialize the x-axis of the plot fft_plot.setXRange(plot_xmin,plot_xmax) fft_plot.setLabel('bottom', text= 'Frequency', units = 'Hz', unitPrefix=None) # grab new cursor region cursor_region = region_selection_lines.getRegion() index_region = np.zeros(2) # index_region[0] = int((cursor_region[0] - plot_xmin) * SAMPLE_SIZE/bandwidth) if index_region[0] < 0: index_region[0] = 0 index_region[1] = int((cursor_region[1] - plot_xmin) * SAMPLE_SIZE/bandwidth) if index_region[1] > SAMPLE_SIZE: index_region[1] = SAMPLE_SIZE max_index = find_max_index(pow_data[np.amin(index_region):np.amax(index_region)]) if max_index < np.amin(index_region): max_index = max_index + np.amin(index_region) max_freq = freq_range[max_index] max_pow = pow_data[max_index] label.setText("<span style='color: green'>Max Frequency Location=%0.1f MHz, Power=%0.1f dBm</span>" % (max_freq/1e6, max_pow)) # TODO: use better method than bellow # hold maximum positions pos = np.random.normal(size=(2,1), scale=1e-9) max_location.setData(x =pos[0] + max_freq , y = pos[0] + max_pow, size = 20, symbol = 't') curve.setData(freq_range,pow_data, pen = 'g')
def receive_vrt(packet): # read until I get 1 data packet global context, dut if not packet.is_data_packet(): context.update(packet.fields) return else: pow_data = compute_fft(dut, packet, context) print pow_data update(dut, pow_data)
def receive_vrt(packet): # read until get 1 data packet global dut, context if not packet.is_data_packet(): context.update(packet.fields) return else: pow_data = compute_fft(dut, packet, context) update(dut, pow_data) # now disable the range to prevent fluctuation fft_plot.enableAutoRange('xy', False)
def __init__(self, dut): super(MainPanel, self).__init__() self.dut = dut self.get_freq_mhz() self.get_decimation() self.decimation_points = None data, reflevel = read_data_and_reflevel(dut) self.screen = SpectrumView( compute_fft(dut, data, reflevel), self.center_freq, self.decimation_factor) self.initUI()
def initDUT(self): self.center_freq = yield self.dut.freq() self.decimation_factor = yield self.dut.decimation() yield self.dut.request_read_perm() while True: data, reflevel = yield twisted_util.read_data_and_reflevel( self.dut, self.points) self.screen.update_data( compute_fft(self.dut, data, reflevel), self.center_freq, self.decimation_factor)
def receive_capture(self, fstart, fstop, data): # store usable bins before next call to capture_time_domain self.usable_bins = list(self.cap_dut.usable_bins) self.sweep_segments = None self.read_block() if 'reflevel' in data['context_pkt']: self.ref_level = data['context_pkt']['reflevel'] self.pow_data = compute_fft(self.dut, data['data_pkt'], data['context_pkt'], ref = self.ref_level) self.raw_data = data['data_pkt'] self.update_plot()
def read_data(self, spp): """ Read and return a data packet, as well as computed power spectral density data, of *spp* (samples per packet) size, the associated context info and the computed power spetral data. If a block of data is requested (such as *ppb* is more than 1), loop through this function to retreive all data. See also data other capture functions: :meth:`pyrf.util.capture_spectrum`, :meth:`pyrf.capture_device.capture_time_domain` :param int spp: the number of samples in a VRT packet (256 to 65504) in a multiple of 32 :returns: data, context dictionary, and power spectral data array """ data, context = read_data_and_context(self, spp) pow_data = compute_fft(self, data, context) return data, context, pow_data
def _playback_step(self, single=False): if not (self._plot_options['cont_cap_mode'] or self._single_capture): return if not self._playback_file: self._playback_started = False return QtCore.QTimer.singleShot(PLAYBACK_STEP_MSEC, self._playback_step) while True: pkt = self._playback_vrt() if pkt.is_context_packet(): if 'speca' in pkt.fields: self._playback_sweep_data = None state_json = pkt.fields['speca'] self._apply_complete_settings(state_json, playback=True) else: self._playback_context.update(pkt.fields) continue if self._state.sweeping(): if not self._playback_sweep_step(pkt): continue self._single_capture = False return break usable_bins = compute_usable_bins(self._dut.properties, self._state.rfe_mode(), len(pkt.data), self._state.decimation, self._state.fshift) usable_bins, fstart, fstop = adjust_usable_fstart_fstop( self._dut.properties, self._state.rfe_mode(), len(pkt.data), self._state.decimation, self._state.center, pkt.spec_inv, usable_bins) pow_data = compute_fft(self._dut, pkt, self._playback_context, **self._dsp_options) if not self._options.get('show_attenuated_edges'): pow_data, usable_bins, fstart, fstop = ( trim_to_usable_fstart_fstop(pow_data, usable_bins, fstart, fstop)) if self._export_csv: self._export_csv_file(self._state.rfe_mode(), fstart, fstop, pow_data) self.capture_receive.emit(self._state, fstart, fstop, pkt, pow_data, usable_bins, None)
def receive_vrt(self, packet): if packet.is_data_packet(): if any(x not in self._vrt_context for x in ( 'reflevel', 'rffreq')): return # queue up the next capture while we update self.dut.capture(self.points, 1) self.screen.update_data( compute_fft(self.dut, packet, self._vrt_context), self.center_freq, self.decimation_factor) else: self._vrt_context.update(packet.fields)
def update(): global dut, fft_curve, max_curve, freq_range # read data data, context = read_data_and_context(dut, SAMPLE_SIZE) # compute the fft and plot the data pow_data = compute_fft(dut, data, context) for i in range(len(pow_data)): if pow_data[i] > max_hold[i]: max_hold[i] = pow_data[i] fft_curve.setData(freq_range,pow_data,pen = 'g') max_curve.setData(freq_range,max_hold,pen = 'y')
def receive_capture(self, fstart, fstop, data): # store usable bins before next call to capture_time_domain self.usable_bins = list(self.cap_dut.usable_bins) self.sweep_segments = None self.read_block() if 'reflevel' in data['context_pkt']: self.ref_level = data['context_pkt']['reflevel'] self.pow_data = compute_fft(self.dut, data['data_pkt'], data['context_pkt'], ref=self.ref_level) self.raw_data = data['data_pkt'] self.freq_range = (fstart, fstop) self.update_trace()
def update(): global dut, curve, fft_plot, plot_xmin, plot_xmax # read data data, context = read_data_and_context(dut, SAMPLE_SIZE) # compute the fft and plot the data pow_data = compute_fft(dut, data, context) # update the frequency range (Hz) freq_range = np.linspace(plot_xmin , plot_xmax, len(pow_data)) # initialize the x-axis of the plot fft_plot.setXRange(plot_xmin,plot_xmax) fft_plot.setLabel('bottom', text= 'Frequency', units = 'Hz', unitPrefix=None) curve.setData(freq_range,pow_data, pen = 'g')
def update(): global dut, curve, fft_plot, freq_range, center_freq, bandwidth, cont_pow_data, fade_curve # read data data, context = read_data_and_context(dut, SAMPLE_SIZE) center_freq = context['rffreq'] bandwidth = context['bandwidth'] # update axes limits plot_xmin = (center_freq) - (bandwidth / 2) plot_xmax = (center_freq) + (bandwidth / 2) # update the frequency range (Hz) freq_range = np.linspace(plot_xmin , plot_xmax, SAMPLE_SIZE) # initialize the x-axis of the plot fft_plot.setXRange(plot_xmin,plot_xmax) fft_plot.setLabel('bottom', text= 'Frequency', units = 'Hz', unitPrefix=None) # compute the fft and plot the data powData = compute_fft(dut, data, context) for i in range(number_of_fade_curves): #fade_curve[i].setData(freq_range,cont_pow_data[i,:],pen = (255,0,255,i * (255 / number_of_fade_curves)) ) if i == number_of_fade_curves - 1: cont_pow_data[i,:] = powData else: cont_pow_data[i,:] = cont_pow_data[i + 1,:] variance = np.zeros(number_of_curves) for i in range(number_of_curves): variance[i] = np.std(cont_pow_data[:,i]) if variance[i] < 10: color = 'r' else: color = 'b' x = np.array(freq_range[i * 8:(i * 8) + 7]) y = np.array(powData[i * 8:(i * 8) + 7]) if i == 57: color = 'g' curve[i].setData(x,y,pen = color)
def update(): global dut, curve, fft_plot, freq_range, max_location # read data data, context = read_data_and_context(dut, SAMPLE_SIZE) # retrieve freq and bandwidth to update axis center_freq = context['rffreq'] bandwidth = context['bandwidth'] # update axes limits plot_xmin = (center_freq) - (bandwidth / 2) plot_xmax = (center_freq) + (bandwidth / 2) # update the frequency range (Hz) freq_range = np.linspace(plot_xmin , plot_xmax, SAMPLE_SIZE) # update the x-axis of the plot fft_plot.setXRange(plot_xmin,plot_xmax) fft_plot.setLabel('bottom', text= 'Frequency', units = 'Hz', unitPrefix=None) # compute the fft and plot the data pow_data = compute_fft(dut, data, context) # determine the index of the maximum point max_index = np.argmax(pow_data) # retrieve maximum power and freq of max power max_freq = freq_range[max_index] max_pow = pow_data[max_index] # update label label.setText("<span style='color: green'>Max Frequency Location=%0.1f MHz, Power=%0.1f dBm</span>" % (max_freq/1e6, max_pow)) # TODO: Find a better way then using an array with small random values # create array of small numbers pos = np.random.normal(size=(2,1), scale=1e-9) # update scatter plot max_location.setData(x =pos[0] + max_freq , y = pos[0] + max_pow, size = 20, symbol = 't') # update fft curve curve.setData(freq_range,pow_data, pen = 'g')
def receive_capture(self, fstart, fstop, data): # store usable bins before next call to capture_time_domain self.usable_bins = list(self.cap_dut.usable_bins) self.sweep_segments = None # only read data if WSA digitizer is used if self.plot_state.dev_set['iq_output_path'] == 'DIGITIZER': if not self.plot_state.block_mode: self.read_sweep() return self.read_block() if 'reflevel' in data['context_pkt']: self.ref_level = data['context_pkt']['reflevel'] self.pow_data = compute_fft(self.dut, data['data_pkt'], data['context_pkt'], ref = self.ref_level) self.raw_data = data['data_pkt'] self.update_plot()
def update(): global dut, curve, fft_plot, freq_range, center_freq, bandwidth # read data data, context = read_data_and_context(dut, SAMPLE_SIZE) center_freq = context['rffreq'] bandwidth = context['bandwidth'] # update axes limits plot_xmin = (center_freq) - (bandwidth / 2) plot_xmax = (center_freq) + (bandwidth / 2) # update the frequency range (Hz) freq_range = np.linspace(plot_xmin , plot_xmax, SAMPLE_SIZE) # initialize the x-axis of the plot fft_plot.setXRange(plot_xmin,plot_xmax) fft_plot.setLabel('bottom', text= 'Frequency', units = 'Hz', unitPrefix=None) # compute the fft and plot the data powData = compute_fft(dut, data, context) curve.setData(freq_range,powData, pen = 'g')
def process_capture(self, fstart, fstop, data): # store usable bins before next call to capture_time_domain usable_bins = list(self._capture_device.usable_bins) # only read data if WSA digitizer is used if 'DIGITIZER' in self._state.device_settings['iq_output_path']: if self._state.sweeping(): self.read_sweep() return self.read_block() if 'reflevel' in data['context_pkt']: self._ref_level = data['context_pkt']['reflevel'] pow_data = compute_fft( self._dut, data['data_pkt'], data['context_pkt'], ref=self._ref_level, **self._dsp_options) if not self._options.get('show_attenuated_edges'): pow_data, usable_bins, fstart, fstop = ( trim_to_usable_fstart_fstop( pow_data, usable_bins, fstart, fstop)) #FIXME: Find out why there is a case where pow_data may be empty if pow_data.any(): if self._plot_options.get('reference_offset_value'): pow_data += self._plot_options['reference_offset_value'] if self._export_csv: self._export_csv_file(self._state.rfe_mode(), fstart, fstop, pow_data) self.capture_receive.emit( self._state, fstart, fstop, data['data_pkt'], pow_data, usable_bins, None)
def _playback_sweep_step(self, pkt): """ process one data packet from a recorded sweep and plot collected data after receiving complete sweep. returns True if data was plotted on this step. """ if self._playback_sweep_data is None: self._playback_sweep_start() last_center = None else: last_center = self._playback_sweep_last_center sweep_start = float(self._state.center - self._state.span / 2) sweep_stop = float(self._state.center + self._state.span / 2) step_center = self._playback_context['rffreq'] updated_plot = False if last_center is not None and last_center >= step_center: # starting a new sweep, plot the data we have self.capture_receive.emit( self._state, sweep_start, sweep_stop, None, self._playback_sweep_data, None, None) updated_plot = True self._playback_sweep_start() self._playback_sweep_last_center = step_center usable_bins = compute_usable_bins( self._dut.properties, self._state.rfe_mode(), len(pkt.data), self._state.decimation, self._state.fshift) usable_bins, fstart, fstop = adjust_usable_fstart_fstop( self._dut.properties, self._state.rfe_mode(), len(pkt.data), self._state.decimation, step_center, pkt.spec_inv, usable_bins) pow_data = compute_fft( self._dut, pkt, self._playback_context, **self._dsp_options) pow_data, usable_bins, fstart, fstop = ( trim_to_usable_fstart_fstop( pow_data, usable_bins, fstart, fstop)) clip_left = max(sweep_start, fstart) clip_right = min(sweep_stop, fstop) sweep_points = len(self._playback_sweep_data) point_left = int((clip_left - sweep_start) * sweep_points / ( sweep_stop - sweep_start)) point_right = int((clip_right - sweep_start) * sweep_points / ( sweep_stop - sweep_start)) xvalues = np.linspace(clip_left, clip_right, point_right - point_left) if point_left >= point_right: logger.info('received sweep step outside sweep: %r, %r' % ((fstart, fstop), (sweep_start, sweep_stop))) else: self._playback_sweep_data[point_left:point_right] = np.interp( xvalues, np.linspace(fstart, fstop, len(pow_data)), pow_data) return updated_plot
def _vrt_receive(self, packet): packet_bytes = packet.size * 4 if packet.is_context_packet(): self._vrt_context.update(packet.fields) self.context_bytes_received += packet_bytes return self.data_bytes_received += packet_bytes sweep_id = self._vrt_context.get('sweepid') if sweep_id != self._sweep_id: if sweep_id == self._prev_sweep_id: self.past_end_bytes_discarded += packet_bytes else: self.martian_bytes_discarded += packet_bytes return # not our data # WORKAROUND for 5K not always sending reflevel if 'reflevel' not in self._vrt_context: self._vrt_context['reflevel'] = 0 assert 'reflevel' in self._vrt_context, ( "missing required context, sweep failed") freq = self._vrt_context['rffreq'] if self._ss_index is None: self.past_end_bytes_discarded += packet_bytes return # more data than we asked for fft_start_time = time.time() pow_data = compute_fft(self.real_device, packet, self._vrt_context) # collect and compute bins collect_start_time = time.time() ss = self.plan[self._ss_index] pass_now = 0 if self._ss_received else ss.bins_pass take = min(ss.bins_run - pass_now, ss.bins_keep - self._ss_received) start = ss.bins_skip + pass_now # adjust for not-centered pass band pbc = self.real_device.properties.PASS_BAND_CENTER[self.rfe_mode] if pbc != 0.5: offset = int(len(pow_data) * (pbc - 0.5)) if packet.spec_inv: offset = -offset start += offset self.bin_arrays.append(pow_data[start:start + take]) self._ss_received += take collect_stop_time = time.time() self.fft_calculation_seconds += collect_start_time - fft_start_time self.bin_collection_seconds += collect_stop_time - collect_start_time self.data_bytes_processed += take * 4 if self._ss_received < ss.bins_keep: return self._ss_received = 0 self._ss_index += 1 if self._ss_index < len(self.plan): return # done the complete sweep # XXX: in case sweep_iterations() does not work if not self.continuous: self._ss_index = None self.real_device.abort() self.real_device.flush() self.bins = np.concatenate(self.bin_arrays) if self.async_callback: self.real_device.vrt_callback = None self.async_callback(self.fstart, self.fstop, self.bins) if self.continuous: self._ss_index = 0 self._ss_received = 0 self.bins = [] return return (self.fstart, self.fstop, self.bins)
def capture_spectrum(dut, rbw=None, average=1, dec=1, fshift=0): """ Returns the spectral data, and the start frequency, stop frequency corresponding to the WSA's current configuration :param rbw: rbw of spectral capture (Hz) (will round to nearest native RBW) :param average: number of capture iterations :param dec: decimation factor applied :param fshift: the fshift applied :returns: (fstart, fstop, pow_data) where pow_data is a list """ # grab mode/decimation mode = dut.rfe_mode() bandwidth = dut.properties.FULL_BW[mode] # calculate points if RBW is given if rbw is not None: # calculate nearest rbw available req_points = bandwidth / rbw try: points = dut.properties.SAMPLE_SIZES[ np.argmin(np.abs(np.subtract(dut.properties.SAMPLE_SIZES, int(req_points)))) + 1 ] except IndexError: points = dut.properties.SAMPLE_SIZES[-1] # determine if multiple packets per block are required if points > dut.properties.MAX_SPP: samples = dut.properties.MAX_SPP packets = points / dut.properties.MAX_SPP else: samples = points packets = 1 dut.spp(samples) dut.ppb(packets) # if no rbw requested, use current point else: samples = dut.spp() packets = dut.ppb() points = samples * packets rbw = bandwidth / points # calculate the usable bins freq = dut.freq() fstart = freq - bandwidth / 2 fstop = freq + bandwidth / 2 usable_bins = compute_usable_bins(dut.properties, mode, points, dec, fshift) total_pow = [] for v in range(average): dut.capture(samples, packets) # read data for p in range(packets): if p == 0: data, context = collect_data_and_context(dut) else: d, c = collect_data_and_context(dut) data.data.np_array = np.concatenate([data.data.np_array, d.data.np_array]) # adjust fstart and fstop based on the spectral inversion usable_bins, fstart, fstop = adjust_usable_fstart_fstop( dut.properties, mode, points, dec, freq, data.spec_inv, usable_bins ) # compute fft pow_data = compute_fft(dut, data, context) if not len(total_pow): total_pow = pow_data else: total_pow = np.add(total_pow, pow_data) pow_data = total_pow / average # trim FFT pow_data, usable_bins, fstart, fstop = trim_to_usable_fstart_fstop(pow_data, usable_bins, fstart, fstop) return (fstart, fstop, pow_data)
def _vrt_receive(self, packet): # context packet just update our context dictionary if packet.is_context_packet(): # look for any geolocation info geo = { } for field in [ 'latitude', 'longitude', 'altitude', 'speedoverground', 'heading', 'track', 'magneticvariation' ]: if field in packet.fields: geo[field] = packet.fields[field] if geo and self._geo_callback_func: # execute callback func = self._geo_callback_func func(self._geo_callback_data, geo) self._vrt_context.update(packet.fields) self.log(packet) return # check to see if we recieved our sweep ID if not ('sweepid' in self._vrt_context): return # make sure we are receiving packets for the right sweep if not (self._vrt_context['sweepid'] == self._next_sweep_id): raise SweepDeviceError("data packets received before start of sweep received! cur = %d, next = %d" % (self._vrt_context['sweepid'], self._next_sweep_id)) # increment the packet count self.packet_count += 1 self.log("#%d of %d - %s" % (self.packet_count, self._sweep_settings.step_count, packet)) # retrieve the frequency and usable BW of the packet packet_freq = self._vrt_context['rffreq'] usable_bw = self.dev_properties.USABLE_BW[self._sweep_settings.rfe_mode] # compute the fft pow_data = compute_fft(self.real_device, packet, self._vrt_context) # calc rbw for this packet rbw = float(self.dev_properties.FULL_BW[self._sweep_settings.rfe_mode]) / len(pow_data) self.log("rbw = %f, %f" % (rbw, self._sweep_settings.rbw)) if self._flattening_enabled: # Check if we are above 50 MHz and in SH mode if packet_freq >= 50e6 and self._sweep_settings.rfe_mode == "SH": number_of_points = len(pow_data) # check if we have correction vectors (Noise) if self.nf_corr_obj is not None: # if so grab them nf_cal = \ self.nf_corr_obj.get_correction_vector(packet_freq, number_of_points) else: # if no set it to 0 nf_cal = np.zeros(number_of_points) # check if we have corrrection vectors (Spectrum) if self.sp_corr_obj is not None: # if so grab them sp_cal = \ self.sp_corr_obj.get_correction_vector(packet_freq, number_of_points) else: # if not set it to 0 sp_cal = np.zeros(number_of_points) # if the data is spectraly inverted, invert the vectors if packet.spec_inv: nf_cal = np.flipud(nf_cal) sp_cal = np.flipud(sp_cal) # calculate the correction threshold correction_thresh = (-135.0 + ((10.0 * packet_freq / 1e6) / 27000.0) + 10.0 * np.log10(rbw) + self._sweep_settings.attenuation) # creat the spectrum. per bin, if the ampltitude is above # correction threshold do pow_data - sp_cal else do pow_data - # nf_cal pow_data = np.where(pow_data < correction_thresh, pow_data - nf_cal, pow_data - sp_cal) # check if DD mode was used in this sweep if self.packet_count == 1 and self._sweep_settings.dd_mode: # copy the data into the result array self._copy_data(0, self.dev_properties.FULL_BW['DD'], pow_data, self._sweep_settings.bandstart, self._sweep_settings.bandstop, self.spectral_data); if self._sweep_settings.beyond_dd: return else: return self._emit_data() # determine the usable bins in this config self.log("===> compute_usable_bins()", self._sweep_settings.rfe_mode, self._sweep_settings.spp, 1, 0) usable_bins = compute_usable_bins(self.dev_properties, self._sweep_settings.rfe_mode, self._sweep_settings.spp, 1, 0) self.log("<--- usable_bins", usable_bins) # adjust the usable range based on spectral inversion self.log("===> adjust_usable_fstart_fstop()", "self.dev_properties", self._sweep_settings.rfe_mode, len(pow_data) * 2, 1, packet_freq, packet.spec_inv, usable_bins) usable_bins, packet_start, packet_stop = adjust_usable_fstart_fstop(self.dev_properties, self._sweep_settings.rfe_mode, len(pow_data) * 2, 1, packet_freq, packet.spec_inv, usable_bins) self.log("<--- adjust_usable_fstart_fstop", packet_start, packet_stop, usable_bins) # # WARNING: the start and stop returned from this function are HIGHLY sketchy # # calculate packet frequency range #packet_start = packet_freq - (self.dev_properties.FULL_BW[self._sweep_settings.rfe_mode] / 2) #packet_stop = packet_freq + (self.dev_properties.FULL_BW[self._sweep_settings.rfe_mode] / 2) #print "packet start/stop", packet_start, packet_stop #trim the FFT data, note decimation is 1, fshift is 0 self.log("===> trim_to_usable_fstart_fstop()", "pow_data", usable_bins, packet_start, packet_stop) trimmed_spectrum, edge_data, usable_start, usable_stop = trim_to_usable_fstart_fstop(pow_data, usable_bins, packet_start, packet_stop) self.log("<--- trim_to_usable_fstart_fstop", usable_start, usable_stop, "trimmed_spectrum", edge_data) # copy the data self._copy_data(usable_start, usable_stop, trimmed_spectrum, self._sweep_settings.bandstart, self._sweep_settings.bandstop, self.spectral_data); # if there's no more packets, emit result if self.packet_count == self._sweep_settings.step_count: return self._emit_data() # all done return
dut.request_read_perm() dut.ifgain(0) dut.freq(2450e6) dut.gain('high') dut.fshift(0) dut.decimation(0) trigger = TriggerSettings(trigtype="LEVEL", fstart=2400e6, fstop=2480e6, amplitude=-70) dut.trigger(trigger) # capture 1 packet data, reflevel = read_data_and_reflevel(dut, 1024) # compute the fft of the complex data powdata = compute_fft(dut, data, reflevel) # setup my graph fig = figure(1) axis([0, 1024, -120, 20]) xlabel("Sample Index") ylabel("Amplitude") # plot something plot(powdata, color='blue') # show graph show()
def _vrt_receive(self, packet): # context packet just update our context dictionary if packet.is_context_packet(): self._vrt_context.update(packet.fields) self.log(packet) return # check to see if we recieved our sweep ID if not ('sweepid' in self._vrt_context): return # make sure we are receiving packets for the right sweep if not (self._vrt_context['sweepid'] == self._next_sweep_id): raise SweepDeviceError( "data packets received before start of sweep received! cur = %d, next = %d" % (self._vrt_context['sweepid'], self._next_sweep_id)) # increment the packet count self.packet_count += 1 self.log("#%d of %d - %s" % (self.packet_count, self._sweep_settings.step_count, packet)) # compute the fft pow_data = compute_fft(self.real_device, packet, self._vrt_context) # check if DD mode was used in this sweep if self.packet_count == 1 and self._sweep_settings.dd_mode: # copy the data into the result array self._copy_data(0, self.dev_properties.FULL_BW['DD'], pow_data, self._sweep_settings.bandstart, self._sweep_settings.bandstop, self.spectral_data) if self._sweep_settings.beyond_dd: return else: return self._emit_data() # retrieve the frequency and usable BW of the packet packet_freq = self._vrt_context['rffreq'] usable_bw = self.dev_properties.USABLE_BW[ self._sweep_settings.rfe_mode] # calc rbw for this packet rbw = float(self.dev_properties.FULL_BW[ self._sweep_settings.rfe_mode]) / len(pow_data) self.log("rbw = %f, %f" % (rbw, self._sweep_settings.rbw)) # determine the usable bins in this config self.log("===> compute_usable_bins()", self._sweep_settings.rfe_mode, self._sweep_settings.spp, 1, 0) usable_bins = compute_usable_bins(self.dev_properties, self._sweep_settings.rfe_mode, self._sweep_settings.spp, 1, 0) self.log("<--- usable_bins", usable_bins) # adjust the usable range based on spectral inversion self.log("===> adjust_usable_fstart_fstop()", "self.dev_properties", self._sweep_settings.rfe_mode, len(pow_data) * 2, 1, packet_freq, packet.spec_inv, usable_bins) usable_bins, packet_start, packet_stop = adjust_usable_fstart_fstop( self.dev_properties, self._sweep_settings.rfe_mode, len(pow_data) * 2, 1, packet_freq, packet.spec_inv, usable_bins) self.log("<--- adjust_usable_fstart_fstop", packet_start, packet_stop, usable_bins) # # WARNING: the start and stop returned from this function are HIGHLY sketchy # # calculate packet frequency range #packet_start = packet_freq - (self.dev_properties.FULL_BW[self._sweep_settings.rfe_mode] / 2) #packet_stop = packet_freq + (self.dev_properties.FULL_BW[self._sweep_settings.rfe_mode] / 2) #print "packet start/stop", packet_start, packet_stop #trim the FFT data, note decimation is 1, fshift is 0 self.log("===> trim_to_usable_fstart_fstop()", "pow_data", usable_bins, packet_start, packet_stop) trimmed_spectrum, edge_data, usable_start, usable_stop = trim_to_usable_fstart_fstop( pow_data, usable_bins, packet_start, packet_stop) self.log("<--- trim_to_usable_fstart_fstop", usable_start, usable_stop, "trimmed_spectrum", edge_data) # copy the data self._copy_data(usable_start, usable_stop, trimmed_spectrum, self._sweep_settings.bandstart, self._sweep_settings.bandstop, self.spectral_data) # if there's no more packets, emit result if self.packet_count == self._sweep_settings.step_count: return self._emit_data() # all done return
dut.ifgain(0) dut.freq(2450e6) dut.gain('high') dut.fshift(0) dut.decimation(0) trigger = TriggerSettings( trigtype="LEVEL", fstart=2400e6, fstop=2480e6, amplitude=-70) dut.trigger(trigger) # capture 1 packet data, context = read_data_and_context(dut, 1024) # compute the fft of the complex data powdata = compute_fft(dut, data, context) # setup my graph fig = figure(1) axis([0, 1024, -120, 20]) xlabel("Sample Index") ylabel("Amplitude") # plot something plot(powdata, color='blue') # show graph show()
dut.ifgain(0) dut.freq(2450e6) dut.gain('high') dut.fshift(0) dut.decimation(0) trigger = TriggerSettings( trigtype="LEVEL", fstart=2400e6, fstop=2480e6, amplitude=-70) dut.trigger(trigger) # capture 1 packet data, reflevel = read_data_and_reflevel(dut, 1024) # compute the fft of the complex data powdata = compute_fft(dut, data, reflevel) # setup my graph fig = figure(1) axis([0, 1024, -120, 20]) xlabel("Sample Index") ylabel("Amplitude") # plot something plot(powdata, color='blue') # show graph show()