RFI Detection and Mitigation for Dithered PRF mode#235
RFI Detection and Mitigation for Dithered PRF mode#235hb6688 wants to merge 2 commits intoisce-framework:developfrom
Conversation
| else: | ||
| cov[i, i] = 0.0 |
There was a problem hiding this comment.
| else: | |
| cov[i, i] = 0.0 |
| Gap-excluded sample covariance matrix. | ||
| """ | ||
|
|
||
| num_pulses, num_rng_samples = data.shape |
There was a problem hiding this comment.
Add a check to see if x percent of total number of samples is above min required CPI length per theory and if not issue a warning.
FYI, for fixed PRF, make sure to check the number of valid samples (fixed over all CPI pulses) meets the min requirement and they are not all zeros.
|
|
||
| # compute number of CPIs | ||
| num_pulses, num_rng_samples = raw_data.shape | ||
| num_cpi = num_pulses // cpi_len |
There was a problem hiding this comment.
| num_cpi = num_pulses // cpi_len | |
| if cpi_len > num_pulses: | |
| raise ValueError(f'"cpi_len" {cpi_len} is larger than number of pulses {num_pulses}!') | |
| num_cpi = num_pulses // cpi_len |
| # Eigenvalues. Zero Eigenvalues are replaced by a small epsilon, 1e-30 to | ||
| # ensure log values of such are greater than zero. | ||
| eig_val_sort_db = 10*np.log10(np.maximum(np.abs(eig_val_sort), 1e-30)) | ||
| usable_rank = int(np.count_nonzero(eig_val_sort_db > 0)) |
There was a problem hiding this comment.
Adding some user-defined rank computation per max expected dynamic range of eigen values.
| usable_rank = int(np.count_nonzero(eig_val_sort_db > 0)) | |
| # do we need to peak normalize this? | |
| eig_val_norm = np.copy(eig_val_sort) | |
| if eig_val_sort[0] > eig_val_sort[-1]: | |
| eig_val_norm /= eig_val_sort[0] | |
| # set to max possible dynamic range (16 bits ~ 96 dB ~ 1e-9) or better to ENOB + floating-point precision ( < 8 bit ~ 50 dB ~ 1e-5) | |
| usable_rank = np.sum(~np.isclose(eig_val_norm, 0, atol=1e-9)) |
| eig_val_sort_db = 10*np.log10(np.maximum(np.abs(eig_val_sort), 1e-30)) | ||
| usable_rank = int(np.count_nonzero(eig_val_sort_db > 0)) | ||
|
|
||
| if usable_rank < noise_ev_idx + 1: |
There was a problem hiding this comment.
Replace noise_ev_idx with min_cpi_rank and then before for loop add error check min_cpi_rank <= cpi_len and issue a warning if not 1 < min_cpi_rank < cpi_len - 1 (recommended range in docstring).
| if usable_rank < noise_ev_idx + 1: | |
| if usable_rank < min_cpi_rank: |
| off_diag_overlap_ratio: float = 0.1, | ||
| diag_valid_ratio: float = 0.05, |
There was a problem hiding this comment.
At the runconfig, it is assumed that the num_range_sample_block >= 250, then here are the suggested default percentage.
| off_diag_overlap_ratio: float = 0.1, | |
| diag_valid_ratio: float = 0.05, | |
| off_diag_overlap_ratio: float = 0.25, | |
| diag_valid_ratio: float = 0.2, |
Tyler-g-hudson
left a comment
There was a problem hiding this comment.
I looked over your error strings and added some commentary on how to make them more descriptive. In one of them, I think there is also a small logic error which could lead to an edge case.
| raise ValueError( | ||
| "Minimum number of samples in a range block to estimate Sample Covariance" | ||
| f" Matrix is {rng_samples_min}! Current number of samples per range block" | ||
| f" is {num_rng_samples}!" | ||
| ) |
There was a problem hiding this comment.
This block assumes that a user with no knowledge of RFI mitigation is going to understand the significance of these numbers and how they are calculated. In general, it's most helpful to the user to be able to identify at a glance:
- What code is throwing this error (e.g. start the ValueError string with something like 'RFI detection:')
- How the errored values were acquired. In this case, it looks like these numbers are coming from the shape of the data and the CPI length; Some quick instruction regarding setting an appropriate CPI length for this data would be useful here e.g. CPI length must be no more than half of the number of range pixels.
| raise ValueError( | ||
| f"Coherent Processing Interval length exceeds total number of pulses {num_pulses}!" | ||
| ) |
There was a problem hiding this comment.
| raise ValueError( | |
| f"Coherent Processing Interval length exceeds total number of pulses {num_pulses}!" | |
| ) | |
| raise ValueError( | |
| f"Coherent Processing Interval length (cpi_len) exceeds total number of pulses {num_pulses}!" | |
| ) |
| mask_valid_cpi = np.ones(raw_data.shape, dtype=bool) | ||
|
|
||
| if mask_valid_cpi.shape != raw_data.shape: | ||
| raise ValueError(f"mask shape {mask_valid_cpi.shape} != data shape {raw_data.shape}") |
There was a problem hiding this comment.
| raise ValueError(f"mask shape {mask_valid_cpi.shape} != data shape {raw_data.shape}") | |
| raise ValueError(f"Valid CPI mask shape {mask_valid_cpi.shape} != data shape {raw_data.shape}") |
| mask_valid_cpi = np.ones(data.shape, dtype=bool) | ||
|
|
||
| if mask_valid_cpi.shape != data.shape: | ||
| raise ValueError(f"mask shape {mask_valid_cpi.shape} != data shape {data.shape}") |
There was a problem hiding this comment.
| raise ValueError(f"mask shape {mask_valid_cpi.shape} != data shape {data.shape}") | |
| raise ValueError(f"Valid CPI mask shape {mask_valid_cpi.shape} != data shape {data.shape}") |
| if detect_threshold <= 0: | ||
| raise ValueError("Detection threshold must be a positive value!") | ||
| if (not np.isfinite(detect_threshold)) or (detect_threshold <= 0): | ||
| #raise ValueError("Detection threshold must be a positive value!") |
There was a problem hiding this comment.
It looks like this ValueError is no longer needed
| #raise ValueError("Detection threshold must be a positive value!") |
| if noise_ev_idx >= cpi_len: | ||
| raise ValueError( | ||
| f"noise_ev_idx must be less than {cpi_len - 1}, got {noise_ev_idx}." | ||
| ) |
There was a problem hiding this comment.
The logic here and the error statement say two different things; the error output says it needs to be less than cpi_len - 1 but the logic only checks if it's less than cpi_len.
| if noise_ev_idx >= cpi_len: | |
| raise ValueError( | |
| f"noise_ev_idx must be less than {cpi_len - 1}, got {noise_ev_idx}." | |
| ) | |
| if noise_ev_idx >= (cpi_len - 1): | |
| raise ValueError( | |
| f"noise_ev_idx must be less than cpi_len - 1: {cpi_len - 1}, got {noise_ev_idx}." | |
| ) |
|
|
||
| # Verify Mask shape | ||
| if mask_valid.shape != raw_data.shape: | ||
| raise ValueError(f"mask shape {mask_valid.shape} != data shape {raw_data.shape}") |
There was a problem hiding this comment.
| raise ValueError(f"mask shape {mask_valid.shape} != data shape {raw_data.shape}") | |
| raise ValueError(f"Valid CPI mask shape {mask_valid.shape} != data shape {raw_data.shape}") |
This PR makes the following changes: