Skip to content

Bilinear Remapping #1016

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 231 commits into
base: main
Choose a base branch
from
Open

Bilinear Remapping #1016

wants to merge 231 commits into from

Conversation

aaronzedwick
Copy link
Member

@aaronzedwick aaronzedwick commented Oct 14, 2024

Closes #678

Overview

Adds bilinear remapping functionality to UXarray.

Expected Usage

import uxarray as ux

source = "/path"
destination = "/path"
source_uxds = ux.open_dataset(destination, destination)
destination = ux.open_dataset(destination, destination)

bilinear_remap = source_uxds.remap.bilinear(destination.uxgrid, remap_to='face centers')

PR Checklist

General

  • An issue is linked created and linked
  • Add appropriate labels
  • Filled out Overview and Expected Usage (if applicable) sections

Testing

  • Adequate tests are created if there is new functionality
  • Tests cover all possible logical paths in your function
  • Tests are not too basic (such as simply calling a function and nothing else)

Documentation

  • Docstrings have been added to all new functions
  • Docstrings have updated with any function changes
  • Internal functions have a preceding underscore (_) and have been added to docs/internal_api/index.rst
  • User functions have been added to docs/user_api/index.rst

@aaronzedwick
Copy link
Member Author

aaronzedwick commented Apr 17, 2025

@rajeeja @aaronzedwick
Have either of you had a chance to run a comparison to the results from TempestRemap?

@rajeeja created an example using ESMPy, which uses TempestRemap for its bilinear interpolation.

The example above seems to be on a basic unstructured grid. Have we done a comparison between unstructured grids?

That wasn't the comparison; that was showcasing our remapping on a grid that was slightly larger. However, I think he used the same file for the comparison. Rajeev mentioned that he was going to get actual grid data to load for the comparison, not sure if he ended up doing that @rajeeja. The issue is getting ESMPy and UXarray to both load the same files. I think Rajeev was having struggles with getting UXarray to load the files inside the ESMPy docs.

@rajeeja, if you did end up getting the comparison, can you post a photo here? If not, I can look into finding something that would work if you want me to. I would have to install ESMPy on my machine, however.

@rajeeja
Copy link
Contributor

rajeeja commented Apr 23, 2025

@rajeeja
Copy link
Contributor

rajeeja commented Apr 23, 2025

@aaronzedwick this one took 42 mins https://github.com/UXARRAY/uxarray/actions/runs/14623421875/job/41029024529?pr=1016

would it be good to shorten the test case in the notebook?

@aaronzedwick
Copy link
Member Author

@aaronzedwick this one took 42 mins https://github.com/UXARRAY/uxarray/actions/runs/14623421875/job/41029024529?pr=1016

would it be good to shorten the test case in the notebook?

We could, but it doesn't seem that much longer than what other PR's are taking for tests. It is only a few minutes longer. And when RTree is implemented, that should give a significant boost to performance, which should solve the extra few minutes it takes.

@rajeeja
Copy link
Contributor

rajeeja commented Apr 24, 2025

@rajeeja @aaronzedwick
Have either of you had a chance to run a comparison to the results from TempestRemap?

@rajeeja created an example using ESMPy, which uses TempestRemap for its bilinear interpolation.

The example above seems to be on a basic unstructured grid. Have we done a comparison between unstructured grids?

That wasn't the comparison; that was showcasing our remapping on a grid that was slightly larger. However, I think he used the same file for the comparison. Rajeev mentioned that he was going to get actual grid data to load for the comparison, not sure if he ended up doing that @rajeeja. The issue is getting ESMPy and UXarray to both load the same files. I think Rajeev was having struggles with getting UXarray to load the files inside the ESMPy docs.

@rajeeja, if you did end up getting the comparison, can you post a photo here? If not, I can look into finding something that would work if you want me to. I would have to install ESMPy on my machine, however.

https://github.com/rajeeja/uxarray_squadgen/blob/main/tempestremap_uxarray/remap_comparison_report.md#histogram-and-scatter-plot-of-remapping-differences

Copy link
Contributor

@rajeeja rajeeja left a comment

Choose a reason for hiding this comment

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

tempestremap comparison looks good. code for comparison here: https://github.com/rajeeja/uxarray_squadgen/tree/main/tempestremap_uxarray

@aaronzedwick aaronzedwick requested a review from philipc2 April 24, 2025 17:08
@aaronzedwick
Copy link
Member Author

tempestremap comparison looks good. code for comparison here: https://github.com/rajeeja/uxarray_squadgen/tree/main/tempestremap_uxarray

This looks great, thanks for doing this!

@philipc2
Copy link
Member

@rajeeja

Thank you for putting this report together!

Do we know where the differences are coming from? A max difference of 1e-2 is quite a bit larger than what I would expect.

Looking at the UXarray and TempestRemap plots, the UXarray one has a noticeable jitter

image

For example

image

Compared to

image

Can you generate a plot of the following

  • Absolute Difference between TempestRemap and UXarray at each cell

@aaronzedwick
Copy link
Member Author

The differences could be that tempest remap splits bigger polygons into triangles and finds the sub triangle that holds the point. It then does the barycentric calculation with that triangle. I tried to emulate the current barycentric implementation that spatial hashing uses, by just getting the weights of the entire polygon without finding the sub triangle the point is in, thus eliminating the extra check to point in polygon. In my mind the performance at the time was worth it. However now that I have done some benchmarks, point in polygon is actually very lightweight. I don’t think it would have a massive impact if we changed to check the sub triangles. However, it would cause more calls to point in polygon. For example, a mesh with any given polygon would have (n_edges-2) * n_face calls to point in polygon. Like I said though, I believe the function takes a very small amount of time even with the current calls (n_face best case). Let me know what you think @philipc2

@aaronzedwick aaronzedwick added run-benchmark Run ASV benchmark workflow and removed run-benchmark Run ASV benchmark workflow labels May 1, 2025
@rajeeja
Copy link
Contributor

rajeeja commented May 2, 2025

With new changes:

UXARRAY mean: 1.9997, std: 0.4955
TEMPEST mean: 2.0000, std: 0.4963
Mean abs diff: 0.002161
Max abs diff: 0.363508

a
b

@rajeeja
Copy link
Contributor

rajeeja commented May 8, 2025

@aaronzedwick can you push the latest changes that make it same as tempestremap?

@aaronzedwick
Copy link
Member Author

@aaronzedwick can you push the latest changes that make it same as tempestremap?

I already have.

@philipc2 philipc2 requested a review from Copilot May 8, 2025 18:45
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds bilinear remapping functionality to UXarray by introducing new bilinear methods on both the UxDataset and UxDataArray remap accessors along with a dedicated bilinear remapping module. Key changes include the implementation of the bilinear interpolation algorithm in uxarray/remap/bilinear.py, updates to the accessor methods in dataset_accessor.py and dataarray_accessor.py to support bilinear remapping (including destination grid checks), and corresponding updates to tests, benchmarks, and documentation.

Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
uxarray/remap/dataset_accessor.py Added bilinear remap method with None-check for destination grid
uxarray/remap/dataarray_accessor.py Introduced bilinear remap method for data arrays
uxarray/remap/bilinear.py New module implementing bilinear remapping logic
uxarray/grid/neighbors.py Minor cleanup by removing extra newline
uxarray/grid/grid.py Added explicit conversion of point coordinates to np.asarray
test/test_remap.py Added tests to verify bilinear remapping behavior
docs/user-guide/remapping.ipynb Updated user guide to document the bilinear remapping option
docs/api.rst Updated API docs to include the new bilinear remapping methods
benchmarks/mpas_ocean.py Added performance benchmarks for bilinear remapping

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.

Bilinear Remapping
4 participants