Skip to content

Improvement for TEC correction - #369

Open
seongsujeong wants to merge 18 commits into
isce-framework:developfrom
seongsujeong:tec_correction_config
Open

seongsujeong wants to merge 18 commits into
isce-framework:developfrom
seongsujeong:tec_correction_config

Conversation

@seongsujeong

@seongsujeong seongsujeong commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

This PR adds several options to ionospheric TEC correction

  • Add option into runconfig to use total TEC only
  • Add option to turn on / off the slant range / azimuth correction individually
  • Add logic to ignore topside TEC (i.e. use total TEC only) based on the data flag inside IMAGEN TEC
  • Apply polynomial fitting to TEC profile to get rid of spikes
  • Add the additional TEC profiles to GCOV and InSAR workflows

EDIT
09/10/2026: RANSAC-based outlier detection is implemented and being applied before polynomial fitting. Test is ongoing internally.

@hfattahi hfattahi added this to the R05.03.0 milestone Aug 25, 2026
Comment thread python/packages/nisar/workflows/geocode_corrections.py Outdated
Comment thread python/packages/nisar/workflows/geocode_corrections.py Outdated
Comment thread python/packages/nisar/workflows/geocode_corrections.py Outdated

@hfattahi hfattahi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some comments up to what we reviewed today.

Comment thread share/nisar/schemas/gslc.yaml Outdated
Comment thread share/nisar/schemas/gcov.yaml Outdated
Comment thread share/nisar/schemas/insar.yaml Outdated
Comment thread share/nisar/schemas/gcov.yaml
Comment thread share/nisar/defaults/gcov.yaml Outdated
Comment thread python/packages/nisar/workflows/geocode_corrections.py
Comment thread python/packages/nisar/workflows/geocode_corrections.py Outdated
Comment thread python/packages/nisar/workflows/geocode_corrections.py Outdated
Comment thread python/packages/nisar/workflows/geocode_corrections.py Outdated
Comment thread python/packages/isce3/atmosphere/tec_product.py Outdated

@bhawkins bhawkins left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Polynomial fitting might not be robust to outliers, so another approach like median filter or RANSAC algorithm might be better.

@gshiroma suggests checking that the related output layers (az and rg corrections, but not TEC, which get geocoded) in the GCOV product still make sense in all cases.

Comment thread python/packages/isce3/atmosphere/tec_product.py
Comment thread python/packages/isce3/atmosphere/tec_product.py
@seongsujeong

Copy link
Copy Markdown
Contributor Author

@gshiroma suggests checking that the related output layers (az and rg corrections, but not TEC, which get geocoded) in the GCOV product still make sense in all cases.

In GCOV, disabling either correction (i.e., the azimuth or slant-range correction) causes the corresponding correction LUT to be omitted from the output. @gshiroma Please confirm if this is expected behavior.

@rad-eng-59 rad-eng-59 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for the updates. Just some minor comments.

Comment thread python/packages/isce3/atmosphere/tec_product.py Outdated
Comment thread python/packages/isce3/atmosphere/tec_product.py Outdated
Comment thread python/packages/isce3/atmosphere/tec_product.py Outdated
Comment thread python/packages/isce3/atmosphere/tec_product.py Outdated
Comment thread python/packages/isce3/atmosphere/tec_product.py Outdated
Comment thread python/packages/isce3/atmosphere/tec_product.py Outdated

# Keep only inliers, but fall back to the plain fit if too few survive.
inliers = np.abs(resid) <= threshold
if np.count_nonzero(inliers) <= degree:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be "degrees + 1" instead? A polynomial with degree-n should require at least n + 1 samples.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<= will make trigger the log message below when the number of inliers are the same as the order. For example, if the order is 2 and we have 2 inliers, the if statement becomes True. If 3 or more, it satisfies the condition to perform 2nd order polynomial fitting.

Comment thread python/packages/isce3/atmosphere/tec_product.py Outdated
Comment thread python/packages/nisar/workflows/geocode_corrections.py Outdated
Comment thread python/packages/isce3/atmosphere/tec_product.py Outdated
# Degenerate noise scale (near-perfect fit); nothing to reject.
if not np.isfinite(threshold) or threshold <= 0:
info_channel.log('TEC MAD Threshold is not valid. Keeping all TEC samples for polynomial fitting.')
return np.polyval(coeffs, x)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return np.polyval(coeffs, x)
raise RuntimeError()

If we get here I'm not sure it's safe to evaluate the polynomial. So I'd suggest either return y or just throw an exception.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make sense to return the original values when any smoothing attempt fails. Not only this one but also the one in the below (not enough inliers)

inliers = np.abs(resid) <= threshold
if np.count_nonzero(inliers) <= degree:
info_channel.log('Not enough iners from TEC sample. Keeping all TEC samples for polynomial fitting.')
return np.polyval(coeffs, x)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return np.polyval(coeffs, x)
return y

This condition suggests the fit is bad, so maybe it's better not to apply polynomial smoothing and just return the data. Should mention the behavior in the docstring.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I'm having some doubts about what to do in this case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not having enough inliers mean the TEC profile is messed up (which is rare). In that case, it would be hard to tell which one performs better (i.e. fitted or not fitted). In that case I think it's safe to leave the TEC values as they are.

return delta_r


def _mad_polyfit(x: np.ndarray, y: np.ndarray, degree: int,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def _mad_polyfit(x: np.ndarray, y: np.ndarray, degree: int,
def _smooth_mad_polyfit(x: np.ndarray, y: np.ndarray, degree: int,

The function doesn't return fit coefficients like numpy.polyfit, so I think it's clearer if the name is more different. The function performs smoothing, so _smooth_mad_polyfit makes more sense to me, at least.

Comment thread share/nisar/defaults/gslc.yaml
Comment thread share/nisar/defaults/insar.yaml
Comment thread share/nisar/schemas/gcov.yaml
Comment thread share/nisar/schemas/gslc.yaml
Comment thread share/nisar/schemas/insar.yaml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants