sample_building package

sample_building.sample_building module

sample_building.sample_building.calculate_first_rx_sample_time(first_pulse_num_samples_with_tr, txrate)[source]

The first rx sample time is in the centre of the first pulse, so find the sample number of that time in the TX data so we can align the samples and offset appropriately in the RX decimated data. Assumes window time for TR is the same at front and end of actual non-zero samples. :param first_pulse_num_samples_with_tr: number of samples in the first pulse. :param txrate: The transmitting sample rate, in Hz. :return: first_rx_sample_time, time to centre of first pulse.

sample_building.sample_building.calculated_combined_pulse_samples_length(pulse_list, txrate)[source]

Get the total length of the array for the combined pulse.

Determine the length of the combined pulse in number of samples before combining the samples, using the length of the samples arrays and the starting sample number for each pulse to combine. (Not all pulse samples may start at sample zero due to differing intra_pulse_start_times.)

Parameters
  • pulse_list – list of pulse dictionaries that must be combined to one pulse.

  • txrate – sampling rate of transmission going to DAC.

Returns combined_pulse_length

the length of the pulse after combining slices if necessary.

sample_building.sample_building.create_debug_sequence_samples(txrate, txctrfreq, list_of_pulse_dicts, main_antenna_count, final_rx_sample_rate, ssdelay)[source]

Build the samples for the whole sequence, to be recorded in datawrite.

Parameters
  • txrate – The rate at which these samples will be transmitted at, Hz.

  • txctrfreq – The centre frequency that the N200 is tuned to (and will mix with these samples, kHz).

  • list_of_pulse_dicts – The list of all pulse dictionaries for pulses included

in this sequence. Pulse dictionaries have all metadata and the samples for the pulse. :param file_path: location to place the json file. :param main_antenna_count: The number of antennas available for transmitting on. :param final_rx_sample_rate: The final sample rate after decimating on the receive side (Hz). :param ssdelay: Receiver time of flight for last echo. This is the time to continue

receiving after the last pulse is transmitted.

Returns

sample_building.sample_building.create_uncombined_pulses(pulse_list, power_divider, exp_slices, beamdir, txrate, txctrfreq, main_antenna_count, main_antenna_spacing, pulse_ramp_time, max_usrp_dac_amplitude)[source]

Create the samples for a given pulse_list and append those samples to the pulse_list.

Creates a list of numpy arrays where each numpy array is the pulse samples for a given pulse and a given transmit antenna (index of array in list provides antenna number). Adds the list of samples to the pulse dictionary (in the pulse_list list) under the key ‘samples’.

If the antenna is listed in the config but is not used in the sequence, it is provided an array of zeroes to transmit.

Parameters
  • pulse_list – a list of dictionaries, each dict is a pulse. The list includes all pulses that will be combined together. All dictionaries in this list (all ‘pulses’) will be modified to include the ‘samples’ key which will be a list of arrays where every array is a set of samples for a specific antenna.

  • power_divider – an integer for number of pulses combined (max) in the whole sequence, so we can adjust the amplitude of each uncombined pulse accordingly.

  • exp_slices – slice dictionary containing all necessary slice_ids for this pulse.

  • beamdir – the slice to beamdir dictionary to retrieve the phasing information for each antenna in a certain slice’s pulses.

  • txrate – transmit sampling rate, in Hz.

  • txctrfreq – transmit mixing frequency, in kHz.

  • main_antenna_count – number of main antennas in the array to transmit.

  • main_antenna_spacing – spacing between main array antennas, assumed uniform.

  • pulse_ramp_time – time to ramp up the pulse at the start and end of the pulse. This

time counts as part of the total pulse length time (in seconds). :param max_usrp_dac_amplitude: max voltage out of the digital-analog converter on the USRP

sample_building.sample_building.get_phshift(beamdir, freq, antenna, pulse_shift, num_antennas, antenna_spacing, centre_offset=0.0)[source]

Find the phase shift for a given antenna and beam direction.

Form the beam given the beam direction (degrees off boresite), the tx frequency, the antenna number, a specified extra phase shift if there is any, the number of antennas in the array, and the spacing between antennas.

Parameters
  • beamdir – the azimuthal direction of the beam off boresight, in degrees, positive beamdir being to the right of the boresight (looking along boresight from ground). This is for this antenna.

  • freq – transmit frequency in kHz

  • antenna – antenna number, INDEXED FROM ZERO, zero being the leftmost antenna if looking down the boresight and positive beamdir right of boresight

  • pulse_shift – in degrees, for phase encoding

  • num_antennas – number of antennas in this array

  • antenna_spacing – distance between antennas in this array, in meters

  • centre_offset – the phase reference for the midpoint of the array. Default = 0.0, in metres. Important if there is a shift in centre point between arrays in the direction along the array. Positive is shifted to the right when looking along boresight (from the ground).

Returns phshift

a phase shift for the samples for this antenna number, in radians.

sample_building.sample_building.get_samples(rate, wave_freq, pulse_len, ramp_time, max_amplitude, iwave_table=None, qwave_table=None)[source]

Get basic (not phase-shifted) samples for a given pulse.

Find the normalized sample array given the rate (Hz), frequency (Hz), pulse length (s), and wavetables (list containing single cycle of waveform). Will shift for beam later. No need to use wavetable if just a sine wave.

Parameters
  • rate – tx sampling rate, in Hz.

  • wave_freq – frequency offset from the centre frequency on the USRP, given in Hz. To be mixed with the centre frequency before transmitting. (ex. centre = 12 MHz, wave_freq = + 1.2 MHz, output = 13.2 MHz.

  • pulse_len – length of the pulse (in seconds)

  • ramp_time – ramp up and ramp down time for the pulse, in seconds. Typical 0.00001 s from config.

  • max_amplitude – USRP’s max DAC amplitude. N200 = 0.707 max

  • iwave_table – i samples (in-phase) wavetable if a wavetable is required (ie. not a sine wave to be sampled)

  • qwave_table – q samples (quadrature) wavetable if a wavetable is required (ie. not a sine wave to be sampled)

Returns samples

a numpy array of complex samples, representing all samples needed for a pulse of length pulse_len sampled at a rate of rate.

Returns actual_wave_freq

the frequency possible given the wavetable. If wavetype != ‘SINE’ (i.e. calculated wavetables were used), then actual_wave_freq may not be equal to the requested wave_freq param.

sample_building.sample_building.get_wavetables(wavetype)[source]

Find the wavetable to sample from for a given wavetype.

If there are ever any other types of wavetypes besides ‘SINE’, set them up here.

NOTE: The wavetables should sample a single cycle of the waveform. Note that we will have to block frequencies that could interfere with our license, which will affect the waveform. This blocking of frequencies is not currently set up, so beware. Would have to get the spectrum of the wavetable waveform and then block frequencies that when mixed with the centre frequency, result in the restricted frequencies.

Also NOTE: wavetables create a fixed frequency resolution based on their length. This code is from get_samples:

f_norm = wave_freq / rate

sample_skip = int(f_norm * wave_table_len) # THIS MUST BE AN INT, WHICH DEFINES THE FREQUENCY RESOLUTION.

actual_wave_freq = (float(sample_skip) / float(wave_table_len)) * rate

Parameters

wavetype – A string descriptor of the wavetype.

Returns iwavetable

an in-phase wavetable, or None if given ‘SINE’ wavetype.

Returns qwavetable

a quadrature wavetable, or None if given ‘SINE’ wavetype.

sample_building.sample_building.make_pulse_samples(pulse_list, power_divider, exp_slices, slice_to_beamdir_dict, txrate, txctrfreq, main_antenna_count, main_antenna_spacing, pulse_ramp_time, max_usrp_dac_amplitude, tr_window_time)[source]

Make all necessary samples for all antennas for this pulse.

Given a pulse_list (list of dictionaries of pulses that must be combined), make and phase shift samples for all antennas, and combine pulse dictionaries into one pulse if there are multiple waveforms to combine (e.g., multiple frequencies).

Parameters
  • pulse_list – a list of dictionaries, each dict is a pulse. The list only contains pulses that will be sent as a single pulse (ie. have the same combined_pulse_index).

  • power_divider – an integer for number of pulses combined (max) in the whole sequence, so we can adjust the amplitude of each uncombined pulse accordingly.

  • exp_slices – this is the slice dictionary containing the slices necessary for the sequence.

  • slice_to_beamdir_dict – a dictionary describing the beam directions for the slice_ids.

  • txrate – transmit sampling rate, in Hz.

  • txctrfreq – transmit mixing frequency, in kHz.

  • main_antenna_count – number of main antennas in the array to transmit.

  • main_antenna_spacing – spacing between main array antennas, assumed uniform.

  • pulse_ramp_time – time to ramp up the pulse at the start and end of the pulse. This

time counts as part of the total pulse length time (in seconds). :param max_usrp_dac_amplitude: max voltage out of the digital-analog converter on the USRP :param tr_window_time: time in seconds to add zero-samples to the transmit waveform in order to count for the transmit/receive switching time. Windows the pulse on both sides. :returns combined_samples: a list of arrays - each array corresponds to an antenna

(the samples are phased). All arrays are the same length for a single pulse on that antenna. The length of the list is equal to main_antenna_count (all samples are calculated). If we are not using an antenna, that index is a numpy array of zeroes.

Returns pulse_channels

The antennas to actually send the corresponding array. If not all transmit antennas, then we will know that we are transmitting zeroes on any antennas not listed in this list but available as identified in the config file.

sample_building.sample_building.resolve_imaging_directions(beamdirs_list, num_antennas, antenna_spacing)[source]

Resolve imaging directions to direction per antenna.

This function will take in a list of directions and resolve that to a direction for each antenna. It will return a list of length num_antenna where each element is a direction off orthogonal for that antenna.

Parameters
  • beamdirs_list – The list of beam directions for this pulse sequence.

  • num_antennas – The number of antennas to calculate direcitonrs for.

  • antenna_spacing – The spacing between the antennas.

Returns beamdirs

A list of beam directions for each antenna.

Returns amplitudes

A list of amplitudes for each antenna

sample_building.sample_building.rx_azimuth_to_antenna_offset(beamdir, main_antenna_count, interferometer_antenna_count, main_antenna_spacing, interferometer_antenna_spacing, intf_offset, freq)[source]

Get all the necessary phase shifts for all antennas for all the beams for a pulse sequence.

Take all beam directions and resolve into a list of phase offsets for all antennas given the spacing, frequency, and number of antennas to resolve for (provided in config).

If the experiment does not use all channels in config, that will be accounted for in the send_dsp_metadata function, where the phase rotation will instead = 0.0 so all samples from that receive channel will be multiplied by zero and therefore not included (in beamforming).

Parameters
  • beamdir – list of length 1 or more.

  • main_antenna_count – the number of main antennas to calculate the phase offset for.

  • interferometer_antenna_count – the number of interferometer antennas to calculate the phase offset for.

  • main_antenna_spacing – the spacing between the main array antennas (m).

  • interferometer_antenna_spacing – the spacing between the interferometer antennas (m).

  • intf_offset – The interferometer offset from the main array (from centre to centre), in Cartesian coordinates. [x, y, z] where x is along line of antennas, y is along array normal and z is altitude difference, in m.

  • freq – the frequency we are transmitting/receiving at.

Returns beams_antenna_phases

a list of length = beam directions, where each element is a list of length = number of antennas (main array followed by interferometer array). The inner list contains the phase shift for the corresponding antenna for the corresponding beam.

sample_building.sample_building.shift_samples(basic_samples, phshift, amplitude)[source]

Shift samples for a pulse by a given phase shift.

Take the samples and shift by given phase shift in rads and adjust amplitude as required for imaging.

Parameters
  • basic_samples – samples for this pulse, numpy array

  • phshift – phase for this antenna to offset by in rads, float

  • amplitude – amplitude for this antenna (= 1 if not imaging), float

Returns samples

basic_samples that have been shaped for the antenna for the desired beam.