Skip to content

Add IDW interpolation to rubbersheeting algorithm#239

Merged
xhuang-jpl merged 41 commits intoisce-framework:developfrom
xhuang-jpl:add_idw_rubbersheeting
Apr 16, 2026
Merged

Add IDW interpolation to rubbersheeting algorithm#239
xhuang-jpl merged 41 commits intoisce-framework:developfrom
xhuang-jpl:add_idw_rubbersheeting

Conversation

@xhuang-jpl
Copy link
Copy Markdown
Contributor

This PR is to add the IDW (inverse distance weighting) algorithm to the rubbersheeting algorithm. This is based on our comparison that the IDW performs slightly better than the linear interpolation.

Xiaodong Huang added 30 commits September 19, 2023 20:40
@hfattahi hfattahi added this to the R05.01.4 milestone Mar 31, 2026
Comment thread python/packages/nisar/workflows/rubbersheet.py Outdated
xhuang-jpl and others added 2 commits April 9, 2026 14:59
Co-authored-by: xhuang-jpl <118782850+xhuang-jpl@users.noreply.github.com>
Comment on lines +763 to +764
'''
Performs IDW interpolation on a 2D grid containing NaN values.
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.

Suggested change
'''
Performs IDW interpolation on a 2D grid containing NaN values.
'''
Performs Inverse Distance Weighting (IDW) interpolation on a 2D grid containing NaN values.

eps: float = 1e-12):
'''
Performs IDW interpolation on a 2D grid containing NaN values.
Missing pixels are filled using inverse distance weighting (IDW)
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.

Suggested change
Missing pixels are filled using inverse distance weighting (IDW)
Missing pixels are filled using IDW

Comment on lines +815 to +822
if radius is None:
dists, idxs = tree.query(qpoints, k=min(k, points.shape[0]))
# dists: (M, k)
# idxs : (M, k)
use_mask = np.isfinite(dists)
else:
dists, idxs = tree.query(qpoints, k=min(k, points.shape[0]), distance_upper_bound=radius)
# For neighbors not found within radius, idxs == points.shape[0], dists == inf
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.

need to combine together

Comment on lines +829 to +833
zero_hit = np.any((dists <= eps) & use_mask, axis=1)
if np.any(zero_hit):
row = np.where(zero_hit)[0]
col = np.argmax(((dists <= eps) & use_mask)[row], axis=1)
filled_vals[row] = values[idxs[row, col]]
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.

might not be neccessary here since the distance in 2D grid is usually > 1

Comment on lines +843 to +845
w = np.zeros_like(d, dtype=float)
w[m] = 1.0 / np.maximum(d[m], eps) ** power

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.

same here

Comment thread share/nisar/defaults/insar.yaml Outdated
Comment on lines +547 to +560
interpolation_method: idw

# Flag to enable the use of subswath mask for the outlier detection
subswath_mask_apply_enabled: True

# IDW interpolation method parameters
idw_interpolation:
# Power parameter controlling the distance weighting
power: 2
# Number of nearest neighbors used for interpolation
number: 100
# Maximum search radius in pixels
radius: 200

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.

keep the default to be linear

Comment thread share/nisar/schemas/insar.yaml Outdated
Comment on lines +607 to +610
# Number of nearest neighbors used for interpolation
number: int(min=0, required=False)
# Maximum search radius in pixels
radius: num(min=0, required=False)
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.

Suggested change
# Number of nearest neighbors used for interpolation
number: int(min=0, required=False)
# Maximum search radius in pixels
radius: num(min=0, required=False)
# Number of nearest neighbors used for interpolation
number: int(min=1, required=False)
# Maximum search radius in pixels, if not specified, it will use all of the valid pixels in the image
radius: num(min=1, required=False)

Comment thread share/nisar/schemas/insar.yaml
Copy link
Copy Markdown
Contributor

@hfattahi hfattahi left a comment

Choose a reason for hiding this comment

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

Thank you @xhuang-jpl for addressing the comments we discussed at PR review. This PR is extensively tested and the results are satisfactory. Looks great.

Copy link
Copy Markdown
Contributor

@seongsujeong seongsujeong left a comment

Choose a reason for hiding this comment

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

LGTM. I have a minor suggestion for readability.

Comment on lines +809 to +811
dists, idxs = tree.query(
qpoints, k=k, workers=-1,
**({'distance_upper_bound': radius} if radius is not None else {}))
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
dists, idxs = tree.query(
qpoints, k=k, workers=-1,
**({'distance_upper_bound': radius} if radius is not None else {}))
kwargs = {}
if radius is not None:
kwargs['distance_upper_bound'] = radius
dists, idxs = tree.query(
qpoints,
k=k,
workers=-1,
**kwargs
)

for readability

@xhuang-jpl xhuang-jpl merged commit 555bb03 into isce-framework:develop Apr 16, 2026
7 of 8 checks passed
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.

3 participants