experiment_prototype.scan_classes package

scan_class_base

This is the base module for all ScanClassBase types (iterable for an experiment given certain parameters). These types include the Scan class, the AveragingPeriod class, and the Sequence class.

copyright

2018 SuperDARN Canada

author

Marci Detwiller

class experiment_prototype.scan_classes.scan_class_base.ScanClassBase(object_keys, object_slice_dict, object_interface, transmit_metadata)[source]

Bases: object

The base class for the classes Scan, AveragingPeriod, and Sequence.

Scans are made up of AveragingPeriods, these are typically a 3sec time of the same pulse sequence pointing in one direction. AveragingPeriods are made up of Sequences, typically the same sequence run ave. 20-30 times after a clear frequency search. Sequences are made up of pulses, which is a list of dictionaries where each dictionary describes a pulse.

Parameters
  • object_keys – list of slice_ids that need to be included in this scan_class_base type.

  • object_slice_dict – the slice dictionary that explains the parameters of each slice that is included in this scan_class_base type. Keys are the slice_ids included and values are dictionaries including all necessary slice parameters as keys.

  • object_interface – the interfacing dictionary that describes how to interface the slices that are included in this scan_class_base type. Keys are tuples of format (slice_id_1, slice_id_2) and values are of interface_types set up in experiment_prototype.

  • transmit_metadata – a dictionary of the experiment-wide transmit metadata for building

pulse sequences. The keys of the transmit_metadata are:

‘output_rx_rate’ [Hz], ‘main_antenna_count’, ‘tr_window_time’ [s], ‘main_antenna_spacing’ [m], ‘pulse_ramp_time’ [s], ‘max_usrp_dac_amplitude’ [V peak], ‘rx_sample_rate’ [Hz], ‘minimum_pulse_separation’ [us], ‘txctrfreq’ [kHz], ‘txrate’ [Hz]

prep_for_nested_scan_class()[source]

Retrieve the params needed for the nested class (also with base ScanClassBase).

This class reduces duplicate code by breaking down the ScanClassBase class into the separate portions for the nested instances. For Scan class, the nested class is AveragingPeriod, and we will need to break down the parameters given to the Scan instance because there may be multiple AveragingPeriods within. For AveragingPeriod, the nested class is Sequence.

Returns

params for the nested class’s instantiation.

static slice_combos_sorter(list_of_combos, all_keys)[source]

Sort keys of a list of combinations so that keys only appear once in the list.

This function modifes the input list_of_combos so that all slices that are associated are associated in the same list. For example, if input is list_of_combos = [[0,1], [0,2], [0,4], [1,4], [2,4]] and all_keys = [0,1,2,4,5] then the output should be [[0,1,2,4], [5]]. This is used to get the slice dictionary for nested class instances. In the above example, we would then have two instances of the nested class to create: one with slices 0,1,2,4 and another with slice 5.

Parameters
  • list_of_combos – list of lists of length two associating two slices together.

  • all_keys – list of all keys included in this object (scan, ave_period, or sequence).

Returns

list of combos that is sorted so that each key only appears once and the lists within the list are of however long necessary

scans

This is the module containing the Scan class. The Scan class contains the ScanClassBase members, as well as a scanbound (to be implemented), a beamdir dictionary and scan_beams dictionary which specify beam direction angle and beam order in a scan, respectively, for individual slices that are to be combined in this scan. Beam direction information gets passed on to the AveragingPeriod.

copyright

2018 SuperDARN Canada

author

Marci Detwiller

class experiment_prototype.scan_classes.scans.Scan(scan_keys, scan_slice_dict, scan_interface, transmit_metadata)[source]

Bases: experiment_prototype.scan_classes.scan_class_base.ScanClassBase

Set up the scans.

A scan is made up of AveragingPeriods at defined beam directions, and some other metadata for the scan itself.

The unique members of the scan are (not a member of the scanclassbase):

scanbound

A list of seconds past the minute for scans to align to. Must be increasing, and it is possible to have values greater than 60s.

get_inttime_slice_ids()[source]

Return the slice_ids that are within the AveragingPeriods in this Scan instance.

Take the interface keys inside this scan and return a list of lists where each inner list contains the slices that are in an averagingperiod that is inside this scan. ie. len(nested_slice_list) = # of averagingperiods in this scan, len(nested_slice_list[0]) = # of slices in the first averagingperiod, etc.

Returns

the nested_slice_list which is used when creating the AveragingPeriods for this scan.

prep_for_nested_scan_class()[source]

Override of base method to give more information about beamorder and beamdir.

Beam order and beamdir are required for instantiation of the nested class AveragingPeriod so we need to extract this information as well to fill self.aveperiods.

Returns

a list of lists of parameters that can be directly passed into the nested ScanClassBase type, AveragingPeriod. the params_list is of length = # of AveragingPeriods in this scan.

averaging_periods

This is the module containing the AveragingPeriod class. The AveragingPeriod class contains the ScanClassBase members, as well as clrfrqflag (to be implemented), intn (number of integrations to run), or intt(max time for integrations), and it contains sequences of class Sequence.

copyright

2018 SuperDARN Canada

author

Marci Detwiller

class experiment_prototype.scan_classes.averaging_periods.AveragingPeriod(ave_keys, ave_slice_dict, ave_interface, transmit_metadata, slice_to_beamorder_dict, slice_to_beamdir_dict)[source]

Bases: experiment_prototype.scan_classes.scan_class_base.ScanClassBase

Set up the AveragingPeriods.

An averagingperiod contains sequences and integrates one or multiple pulse sequences together in a given time frame or in a given number of averages, if that is the preferred limiter.

The unique members of the averagingperiod are (not a member of the scanclassbase):

slice_to_beamorder

passed in by the scan that this AveragingPeriod instance is contained in. A dictionary of slice: beam_order for all slices contained in this aveperiod.

slice_to_beamdir

passed in by the scan that this AveragingPeriod instance is contained in. A dictionary of slice: beamdir(s) for all slices contained in this aveperiod.

clrfrqflag

Boolean, True if clrfrqsearch should be performed.

clrfrqrange

The range of frequency to search if clrfrqflag is True. Otherwise empty.

intt

The priority limitation. The time limit (ms) at which time the aveperiod will end. If None, we will use intn to end the aveperiod (a number of sequences).

intn

Number of averages (# of times the sequence transmits) to end after for the averagingperiod.

sequences

The list of sequences included in this aveperiod. This does not indicate how many averages will be transmitted in the aveperiod. If there are multiple sequences in the list, they will be alternated between until the end of the aveperiod.

one_pulse_only

boolean, True if this averaging period only has one unique set of pulse samples in it. This is true if there is only one sequence in the averaging period, and all pulses after the first pulse in the sequence have the isarepeat key = True. This boolean can be used to speed up the process of sending data to the driver which means we can get more averages in less time.

build_sequences(slice_to_beamdir_dict)[source]

Build a list of sequences to iterate through when transmitting.

This includes building all pulses within the sequences, so it then contains all pulse samples data to iterate through when transmitting. If there is only one sequence type in the averaging period, this list will be of length 1. That would mean that that one sequence gets repeated throughout the averagingperiod (intn and intt still apply).

Returns

sequence_dict_list, list of lists of pulse dictionaries.

get_sequence_slice_ids()[source]

Return the slice_ids that are within the Sequences in this AveragingPeriod instance.

Take the interface keys inside this averagingperiod and return a list of lists where each inner list contains the slices that are in a sequence that is inside this averagingperiod. ie. len(nested_slice_list) = # of sequences in this averagingperiod, len(nested_slice_list[0]) = # of slices in the first sequence, etc.

Returns

the nested_slice_list which is used when creating the sequences in this averagingperiod.

set_beamdirdict(beamiter)[source]

Get a dictionary of ‘slice_id’ : ‘beamdir(s)’ for this averaging period.

At a given beam iteration, this averagingperiod instance will select the beam directions that it will shift to.

Parameters

beamiter – the index into the beam_order list, or the index of an averaging period into the scan

Returns

dictionary of slice to beamdir where beamdir is always a list (may be of length one though). Beamdir is azimuth angle.

sequences

This is the module containing the Sequence class. The Sequence class contains the ScanClassBase members, as well as a list of pulse dictionaries, the total_combined_pulses in the sequence, power_divider, last_pulse_len, ssdelay, seqtime, which together give sstime (scope synce time, or time for receiving, and numberofreceivesamples to sample during the receiving window (calculated using the receive sampling rate).

copyright

2018 SuperDARN Canada

author

Marci Detwiller

class experiment_prototype.scan_classes.sequences.Sequence(seqn_keys, sequence_slice_dict, sequence_interface, transmit_metadata)[source]

Bases: experiment_prototype.scan_classes.scan_class_base.ScanClassBase

Set up the sequence class.

The members of the sequence are:

pulses

a list of pre-combined, pre-sampled pulse dictionaries (one dictionary = one basic pulse of single frequency). The dictionary keys are: isarepeat, pulse_timing_us, slice_id, slice_pulse_index, pulse_len, intra_pulse_start_time, combined_pulse_index, pulse_shift, iscombined, combine_total, and combine_index.

total_combined_pulses

the total number of pulses to be sent by the driver. This may not be the sum of pulses in all slices in the sequence, as some pulses may need to be combined because they are overlapping in timing. This is the number of pulses in the combined sequence, or the number of times T/R signal goes high in the sequence.

power_divider

the power ratio per slice. If there are multiple slices in the same pulse then we must reduce the output amplitude to potentially accommodate multiple frequencies.

last_pulse_len

the length of the last pulse (us)

ssdelay

delay past the end of the sequence to receive for (us) - function of num_ranges and pulse_len. ss stands for scope sync.

seqtime

the amount of time for the whole sequence to transmit, until the logic signal switches low on the last pulse in the sequence (us).

sstime

ssdelay + seqtime (total time for receiving) (us).

numberofreceivesamples

the number of receive samples to take, given the rx rate, during the sstime.

first_rx_sample_time

The location of the first sample for the RX data, in time, from the start of the TX data. This will be calculated as the time at center sample of the first pulse. In seconds.

blanks

A list of sample indices that should not be used for acfs because they were samples taken when transmitting.

Pulses is a list of pulse dictionaries. The pulse dictionary keys are:

isarepeat

Boolean, True if the pulse is exactly the same as the last pulse in the sequence.

pulse_timing_us

The time past the start of sequence for this pulse to start at (us).

slice_id

The slice_id that corresponds to this pulse and gives the information about the experiment and pulse information (frequency, num_ranges, first_range, etc.).

slice_pulse_index

The index of the pulse in its own slice’s sequence.

pulse_len

The length of the pulse (us)

intra_pulse_start_time

If the pulse is combined with another pulse and they transmit in a single USRP burst, then we need to know if there is an offset from one pulse’s samples being sent and the other pulse’s samples being sent.

combined_pulse_index

The combined_pulse_index is the index corresponding with actual number of pulses that will be sent to driver, after combinations are completed. Multiple pulse dictionaries in self.pulses can have the same combined_pulse_index if they are combined together, ie are close enough in timing that T/R will not go low between them, and we will combine the samples of both pulses into one set to send to the driver.

pulse_shift

Phase shift for this pulse, for doing pulse coding.

iscombined

Boolean, true if there is another pulse with the same combined_pulse_index.

combine_total

Total number of pulse dictionaries that have the same combined_pulse_index as this one. (minimum number = 1, itself).

combine_index

Index of this pulse dictionary in regards to all the other pulse dictionaries that have the same combined_pulse_index.

build_pulse_transmit_data(slice_to_beamdir_dict)[source]

Build a list of ready-to-transmit pulse dictionaries (with samples) to send to driver.

Param

slice_to_beamdir_dict: dictionary of slice id to beam direction(s) for a single averaging period (i.e. if the list len > 1, we’re imaging).

Returns sequence_list

list of combined pulse dictionaries in correct order. The keys in the ready-to-transmit pulse dictionary are:

startofburst

Boolean, True if this is the first pulse in the sequence.

endofburst

Boolean, True if this is the last pulse in the sequence.

pulse_antennas

The antennas to transmit on

samples_array

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.

timing

The time to send the pulse at (past the start of sequence, us)

isarepeat

Boolean, True if this pulse is the same as the last pulse except for its timing.

find_blanks()[source]

Sets the blanks. Must be run after first_rx_sample_time is set inside the build_pulse_transmit_data function. Called from inside the build_pulse_transmit_data function.