Skip to content

Commit

Permalink
Bugfix/cfs mask (#492)
Browse files Browse the repository at this point in the history
* Sending cfs_masks to data_write as dictionary keyed by slice_id
* Attempting to fix CFS freq selection bug.
* All slices were choosing the same frequency offset relative to the center of the range
  • Loading branch information
RemingtonRohel committed Jun 27, 2024
1 parent a99d828 commit 3eef71b
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 89 deletions.
4 changes: 3 additions & 1 deletion src/data_write.py
Original file line number Diff line number Diff line change
Expand Up @@ -1424,7 +1424,9 @@ def write_tx_data():
parameters.cfs_freqs = np.array(aveperiod_meta.cfs_freqs)
parameters.cfs_noise = np.array(aveperiod_meta.cfs_noise)
parameters.cfs_range = np.array(aveperiod_meta.cfs_range)
parameters.cfs_masks = np.array(aveperiod_meta.cfs_masks)
parameters.cfs_masks = np.array(
aveperiod_meta.cfs_masks[np.uint32(rx_channel.slice_id)]
)
parameters.data_normalization_factor = (
aveperiod_meta.data_normalization_factor
)
Expand Down
202 changes: 117 additions & 85 deletions src/experiment_prototype/interface_classes/averaging_periods.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,103 +217,135 @@ def update_cfs_freqs(self, cfs_spectrum):
Accepts the analysis results of the clear frequency search and uses the passed frequencies and powers
to determine what frequencies to set each clear frequency search slice to.
* Loops through all sequences that have CFS slices:
* Records all non-CFS slice frequencies
* Loops through each CFS slice in the averaging period:
* Calculates the tx bandwidth for the slice pulses;
* Creates a mask of the CFS frequency band
* Masks restricted frequencies
* Masks already-used frequencies by other slices
* Masks around the N200 tuned center frequencies (rx and tx)
* Masks frequencies outside requested CFS range
* Sorts measured spectrum by power
* Sets slice frequency to least powerful frequency
* Updates already-used frequency list
* Stores the frequency mask
* Builds each CFS sequence
* Return the frequency masks
:param cfs_spectrum: Analyzed CFS sequence data
:type cfs_spectrum: dictionary
:type cfs_spectrum: ProcessedSequenceMessage
"""
cfs_freq_hz = np.array(cfs_spectrum.cfs_freq) # at baseband
cfs_data = [dset.cfs_data for dset in cfs_spectrum.output_datasets]
# Sort measured frequencies based on measured power at each freq
slice_masks = []
slice_masks = dict()
slice_used_freqs = dict()
# {cfs_slice_id: list of used frequencies that the slice must avoid}

cfs_slice_set = set(self.cfs_slice_ids)

for sqn_num, sequence in enumerate(self.cfs_sequences):
for sequence in self.cfs_sequences:
used_range = []
for slice_obj in sequence.slice_dict.values():
if not slice_obj.cfs_flag:
df = int(round(1e3 / (2 * slice_obj.pulse_len)))
# bandwidth of tx pulse / 2 in kHz
used_range.append([slice_obj.freq - df, slice_obj.freq + df])
# record pulse widths of all non-cfs slices in use

for slice_obj in sequence.slice_dict.values():
if slice_obj.cfs_flag:
df = int(round(1e3 / (2 * slice_obj.pulse_len)))
slice_range = slice_obj.cfs_range
center_freq_khz = int((slice_range[0] + slice_range[1]) / 2)
shifted_cfs_khz = cfs_freq_hz / 1000 + center_freq_khz

mask = np.full(len(shifted_cfs_khz), True)
for f_rng in options.restricted_ranges:
mask[
np.argwhere(
np.logical_and(
shifted_cfs_khz >= np.floor(f_rng[0]),
shifted_cfs_khz <= np.ceil(f_rng[1]),
)
)
] = False
# Rounding when setting the freq below could cause the freq to set to a restricted value
# so ceil and floor are used to ensure restricted ranges are avoided

for tx_range in used_range:
mask[
np.argwhere(
np.logical_and(
shifted_cfs_khz >= tx_range[0] - df,
shifted_cfs_khz <= tx_range[1] + df,
)
)
] = False
# Mask pulse width around all used frequencies

for ctr_freq in [self.txctrfreq, self.rxctrfreq]:
mask[
np.argwhere(
np.logical_and(
shifted_cfs_khz >= ctr_freq - 50,
shifted_cfs_khz <= ctr_freq + 50,
)
)
] = False
# Avoid frequencies within 50 kHz for the center freqs

f_rng = slice_obj.cfs_range
mask[
np.argwhere(
np.logical_or(
shifted_cfs_khz < f_rng[0], shifted_cfs_khz > f_rng[1]
)
sqn_slice_ids = set(sequence.slice_ids)
sqn_cfs_ids = sqn_slice_ids.intersection(cfs_slice_set)
for slice_id in sqn_slice_ids.difference(cfs_slice_set):
slice_obj = sequence.slice_dict[slice_id]
df = int(round(1e3 / (2 * slice_obj.pulse_len)))
# bandwidth of tx pulse / 2 in kHz
used_range.append([slice_obj.freq - df, slice_obj.freq + df])
# record pulse widths of all non-cfs slices in use
slice_used_freqs.update({k: used_range for k in sqn_cfs_ids})

for i, slice_id in enumerate(self.cfs_slice_ids):
slice_obj = self.slice_dict[slice_id]

df = int(round(1e3 / (2 * slice_obj.pulse_len)))
slice_range = slice_obj.cfs_range
center_freq_khz = int((slice_range[0] + slice_range[1]) / 2)
shifted_cfs_khz = cfs_freq_hz / 1000 + center_freq_khz

mask = np.full(len(shifted_cfs_khz), True)
for f_rng in options.restricted_ranges:
mask[
np.argwhere(
np.logical_and(
shifted_cfs_khz >= np.floor(f_rng[0]),
shifted_cfs_khz <= np.ceil(f_rng[1]),
)
] = False
shifted_cfs_khz = shifted_cfs_khz[mask]
# Mask all restricted frequencies, all frequencies within the tx pulse
# of used frequencies, frequencies outside cfs_range, and frequencies
# too close to the center frequencies in the cfs spectrum frequencies

if len(shifted_cfs_khz) < 1:
log.critical(
"All searched frequencies were too close to used frequencies or the tx or rx"
"center frequencies or were restricted. The radar will crash!!!",
current_slice_id=slice_obj.slice_id,
used_freq_tx_widths=used_range,
cfs_sorted_freqs=shifted_cfs_khz,
)
] = False
# Rounding when setting the freq below could cause the freq to set to a restricted value
# so ceil and floor are used to ensure restricted ranges are avoided

for tx_range in slice_used_freqs[slice_id]:
mask[
np.argwhere(
np.logical_and(
shifted_cfs_khz >= tx_range[0] - df,
shifted_cfs_khz <= tx_range[1] + df,
)

ind = np.argsort(cfs_data[sqn_num][mask])
sorted_freqs_khz = shifted_cfs_khz[ind]
selected_freq = np.round(sorted_freqs_khz[0])
slice_obj.freq = int(selected_freq)
used_range.append([selected_freq - df, selected_freq + df])
# Set cfs slice frequency and add frequency to used_freqs for this sequence
slice_masks.append(mask)

log.verbose(
"setting cfs slice freq",
slice_id=slice_obj.slice_id,
set_freq=slice_obj.freq,
)
] = False
# Mask pulse width around all used frequencies

for ctr_freq in [self.txctrfreq, self.rxctrfreq]:
mask[
np.argwhere(
np.logical_and(
shifted_cfs_khz >= ctr_freq - 50,
shifted_cfs_khz <= ctr_freq + 50,
)
)
] = False
# Avoid frequencies within 50 kHz for the center freqs

f_rng = slice_obj.cfs_range
mask[
np.argwhere(
np.logical_or(
shifted_cfs_khz < f_rng[0], shifted_cfs_khz > f_rng[1]
)
)
] = False
shifted_cfs_khz = shifted_cfs_khz[mask]
# Mask all restricted frequencies, all frequencies within the tx pulse
# of used frequencies, frequencies outside cfs_range, and frequencies
# too close to the center frequencies in the cfs spectrum frequencies

if len(shifted_cfs_khz) < 1:
log.critical(
"All searched frequencies were too close to used frequencies or the tx or rx"
"center frequencies or were restricted. The radar will crash!!!",
current_slice_id=slice_obj.slice_id,
used_freq_tx_widths=slice_used_freqs[slice_id],
cfs_sorted_freqs=shifted_cfs_khz,
)

slice_masks[slice_id] = mask
ind = np.argmin(cfs_data[i][mask])
selected_freq = int(np.round(shifted_cfs_khz[ind]))
slice_obj.freq = selected_freq

for sqn in self.cfs_sequences:
if slice_id in sqn.slice_ids:
other_ids = set(sqn.slice_ids).intersection(self.cfs_slice_ids)
other_ids.remove(slice_id)
for id in other_ids:
slice_used_freqs[id].append(
[selected_freq - df, selected_freq + df]
)
# Set cfs slice frequency and add frequency to used_freqs for all other concurrent slices

log.verbose(
"setting cfs slice freq",
slice_id=slice_obj.slice_id,
set_freq=slice_obj.freq,
)

for sequence in self.cfs_sequences:
sequence.build_sequence_pulses()
# Build sequence pulses once all cfs slices have been assigned a frequency

return slice_masks

def build_cfs_sequence(self):
Expand Down
4 changes: 2 additions & 2 deletions src/experiment_prototype/interface_classes/sequences.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ def build_sequence_pulses(self):
# tx_phases: [num_beams, num_antennas]
# basic_samples: [num_samples]
# phased_samps_for_beams: [num_beams, num_antennas, num_samples]
log.verbose(
log.debug(
"slice information",
slice_id=slice_id,
tx_main_phases=tx_phases,
Expand Down Expand Up @@ -481,7 +481,7 @@ def initialize_combined_pulse_dict(pulse_timing_info):
for i, cpm in enumerate(combined_pulses_metadata):
# message = f"Pulse {i}: start time(us) {cpm['start_time_us']} start sample {cpm['pulse_sample_start']}"
# message += f" pulse length(us) {cpm['total_pulse_len']} pulse num samples {cpm['total_num_samps']}"
log.verbose("pulse information", **cpm)
log.debug("pulse information", **cpm)

self.combined_pulses_metadata = combined_pulses_metadata

Expand Down
2 changes: 1 addition & 1 deletion src/radar_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class RadctrlParameters:
cfs_freq: list = field(default_factory=list)
cfs_mags: list = field(default_factory=list)
cfs_range: list = field(default_factory=list)
cfs_masks: list = field(default_factory=list)
cfs_masks: list = field(default_factory=dict)
scan_flag: bool = False
dsp_cfs_identity: str = ""
router_address: str = ""
Expand Down

0 comments on commit 3eef71b

Please sign in to comment.