Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 59 additions & 14 deletions python/packages/isce3/atmosphere/ionosphere_estimation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import journal
import numpy as np
from scipy.ndimage import median_filter, binary_opening
from isce3.signal.interpolate_by_range import decimate_freq_a_array
from isce3.signal.interpolate_by_range import (decimate_freq_a_array,
interpolate_freq_b_array)

class IonosphereEstimation:
'''
Expand All @@ -14,7 +15,8 @@ def __init__(self,
low_center_freq=None,
high_center_freq=None,
slant_main=None,
slant_side=None):
slant_side=None,
iono_radar_grid='side'):

"""Initialized IonosphereEstimation Base Class

Expand All @@ -31,6 +33,9 @@ def __init__(self,
method : {'split_main_band', 'main_side_band',
'main_diff_ms_band'}
ionosphere estimation method
iono_radar_grid : {"side", "main"}
If "side", main-grid arrays are decimated to the side grid.
If "main", side-grid arrays are interpolated to the main grid.
"""

error_channel = journal.error('ionosphere.IonosphereEstimation')
Expand All @@ -42,12 +47,20 @@ def __init__(self,
error_channel.log(err_str)
raise ValueError(err_str)

valid_modes = {"side", "main"}
if iono_radar_grid not in valid_modes:
raise ValueError(
f"iono_radar_grid must be one of {valid_modes}, "
f"but got {iono_radar_grid!r}."
)

self.f0 = main_center_freq
self.f1 = side_center_freq
self.freq_low = low_center_freq
self.freq_high = high_center_freq
self.slant_main = slant_main
self.slant_side = slant_side
self.iono_radar_grid = iono_radar_grid

def get_mask_median_filter(self,
disp,
Expand Down Expand Up @@ -139,23 +152,55 @@ def compute_unwrapp_error(
"""
# decimate coherences array of frequency A to
# frequency B grid
if side_runw is not None:
main_runw = decimate_freq_a_array(
slant_main,
slant_side,
main_runw)

if low_sub_runw is not None:
low_sub_runw = decimate_freq_a_array(

need_resampling = (
side_runw is not None
or diff_ms_runw is not None
)

if need_resampling:
if slant_main is None or slant_side is None:
raise ValueError(
"slant_main and slant_side are required when resampling "
"between main and side grids."
)

if self.iono_radar_grid == "side":

if side_runw is not None:
main_runw = decimate_freq_a_array(
slant_main,
slant_side,
main_runw)

if low_sub_runw is not None:
low_sub_runw = decimate_freq_a_array(
slant_main,
slant_side,
low_sub_runw)

if high_sub_runw is not None:
high_sub_runw = decimate_freq_a_array(
slant_main,
slant_side,
high_sub_runw)

elif self.iono_radar_grid == "main":
# side_runw and diff_ms_runw are originally on side grid.
# Convert them to main grid.
if side_runw is not None:
side_runw = interpolate_freq_b_array(
slant_main,
slant_side,
low_sub_runw)
side_runw,
)

if high_sub_runw is not None:
high_sub_runw = decimate_freq_a_array(
if diff_ms_runw is not None:
diff_ms_runw = interpolate_freq_b_array(
slant_main,
slant_side,
high_sub_runw)
diff_ms_runw,
)

com_unw_coeff, diff_unw_coeff = \
compute_unwrapp_error_func(
Expand Down
146 changes: 117 additions & 29 deletions python/packages/isce3/atmosphere/main_band_estimation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import numpy as np

from .ionosphere_estimation import IonosphereEstimation
from isce3.signal.interpolate_by_range import decimate_freq_a_array
from isce3.signal.interpolate_by_range import (decimate_freq_a_array,
interpolate_freq_b_array)
from isce3.unwrap.preprocess import interpret_subswath_mask


Expand All @@ -16,7 +17,8 @@ def __init__(self,
low_center_freq=None,
high_center_freq=None,
slant_main=None,
slant_side=None):
slant_side=None,
iono_radar_grid='main'):
"""Initialized IonosphereEstimation Class

Parameters
Expand All @@ -30,9 +32,15 @@ def __init__(self,
high_center_freq : float
center frequency of upper sub-band of the main band [Hz]
"""
super().__init__(main_center_freq, side_center_freq, low_center_freq,
high_center_freq)

super().__init__(
main_center_freq=main_center_freq,
side_center_freq=side_center_freq,
low_center_freq=low_center_freq,
high_center_freq=high_center_freq,
slant_main=slant_main,
slant_side=slant_side,
iono_radar_grid=iono_radar_grid,
)
self.estimate_iono = None
self.estimate_sigma = None
self.compute_unwrap_err = None
Expand Down Expand Up @@ -101,9 +109,38 @@ def compute_disp_nondisp(
error_channel.log(err_str)
raise ValueError(err_str)
# Match spatial sampling by decimating main-band to side-band spacing
phi_main = decimate_freq_a_array(slant_main,
slant_side,
phi_main)
if slant_main is None:
slant_main = self.slant_main

if slant_side is None:
slant_side = self.slant_side

if self.iono_radar_grid == "side":
# Final grid: side/frequency-B grid.
# main-band phase is moved to side-band grid.
phi_main = decimate_freq_a_array(
slant_main,
slant_side,
phi_main,
)

elif self.iono_radar_grid == "main":
# Final grid: main/frequency-A grid.
# side-band phase is moved to main-band grid.
if phi_side is not None:
phi_side = interpolate_freq_b_array(
slant_main,
slant_side,
phi_side,
)

if phi_diff_ms is not None:
phi_diff_ms = interpolate_freq_b_array(
slant_main,
slant_side,
phi_diff_ms,
)

if phi_diff_ms is not None:
no_data_array = (phi_main == no_data) |\
(phi_diff_ms == no_data)
Expand Down Expand Up @@ -288,10 +325,18 @@ def get_mask_array(
# decimate coherence or connected components
# when side array is also used.
if side_array is not None:
main_array = decimate_freq_a_array(
slant_main,
slant_side,
main_array)
if self.iono_radar_grid == "side":
main_array = decimate_freq_a_array(
slant_main,
slant_side,
main_array,
)
elif self.iono_radar_grid == "main":
side_array = interpolate_freq_b_array(
slant_main,
slant_side,
side_array,
)
if diff_ms_array is not None:
mask_array = (main_array > threshold) & \
(diff_ms_array > threshold)
Expand Down Expand Up @@ -350,10 +395,18 @@ def get_valid_area(
"""
# decimate image when side array is also used.
if side_array is not None:
main_array = decimate_freq_a_array(
slant_main,
slant_side,
main_array)
if self.iono_radar_grid == "side":
main_array = decimate_freq_a_array(
slant_main,
slant_side,
main_array,
)
elif self.iono_radar_grid == "main":
side_array = interpolate_freq_b_array(
slant_main,
slant_side,
side_array,
)
if diff_ms_array is not None:
mask_array = (main_array != invalid_value) & \
(diff_ms_array != invalid_value) & \
Expand Down Expand Up @@ -401,10 +454,18 @@ def get_subswath_mask_array(
# decimate subswath mask
# when side array is also used.
if side_array is not None:
main_array = decimate_freq_a_array(
slant_main,
slant_side,
main_array)
if self.iono_radar_grid == "side":
main_array = decimate_freq_a_array(
slant_main,
slant_side,
main_array,
)
elif self.iono_radar_grid == "main":
side_array = interpolate_freq_b_array(
slant_main,
slant_side,
side_array,
)
main_band_reference, main_band_secondary, _ = \
interpret_subswath_mask(main_array)
side_band_reference, side_band_secondary, _ = \
Expand Down Expand Up @@ -482,10 +543,18 @@ def estimate_iono_std(
if slant_side is None:
slant_side = self.slant_side

main_coh = decimate_freq_a_array(
slant_main,
slant_side,
main_coh)
if self.iono_radar_grid == "side":
main_coh = decimate_freq_a_array(
slant_main,
slant_side,
main_coh,
)
elif self.iono_radar_grid == "main":
side_used_coh = interpolate_freq_b_array(
slant_main,
slant_side,
side_used_coh,
)

sig_phi_main = np.divide(
np.sqrt(1 - main_coh**2),
Expand All @@ -507,7 +576,6 @@ def estimate_iono_std(

return sig_phi_iono, sig_nondisp


def estimate_sigma_main_side(
self,
sig_phi0,
Expand Down Expand Up @@ -600,6 +668,9 @@ def __init__(self,
side_center_freq=None,
low_center_freq=None,
high_center_freq=None,
slant_main=None,
slant_side=None,
iono_radar_grid='main',
method=None):
"""Initialized IonosphereEstimation Class

Expand All @@ -617,8 +688,15 @@ def __init__(self,
'main_diff_ms_band'}
ionosphere estimation method
"""
super().__init__(main_center_freq, side_center_freq, low_center_freq,
high_center_freq, method)
super().__init__(
main_center_freq=main_center_freq,
side_center_freq=side_center_freq,
low_center_freq=low_center_freq,
high_center_freq=high_center_freq,
slant_main=slant_main,
slant_side=slant_side,
iono_radar_grid=iono_radar_grid,
)

self.estimate_iono = estimate_iono_main_side
self.estimate_sigma = self.estimate_sigma_main_side
Expand All @@ -633,6 +711,9 @@ def __init__(self,
side_center_freq=None,
low_center_freq=None,
high_center_freq=None,
slant_main=None,
slant_side=None,
iono_radar_grid='main',
method=None):
"""Initialized IonosphereEstimation Class

Expand All @@ -650,8 +731,15 @@ def __init__(self,
'main_diff_ms_band'}
ionosphere estimation method
"""
super().__init__(main_center_freq, side_center_freq, low_center_freq,
high_center_freq, method)
super().__init__(
main_center_freq=main_center_freq,
side_center_freq=side_center_freq,
low_center_freq=low_center_freq,
high_center_freq=high_center_freq,
slant_main=slant_main,
slant_side=slant_side,
iono_radar_grid=iono_radar_grid,
)

self.estimate_iono = estimate_iono_main_diff
self.estimate_sigma = self.estimate_sigma_main_side
Expand Down
Loading
Loading