uxarray 2026.2.0__tar.gz → 2026.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {uxarray-2026.2.0 → uxarray-2026.4.0}/CONTRIBUTING.md +2 -2
- {uxarray-2026.2.0 → uxarray-2026.4.0}/INSTALLATION.md +2 -2
- {uxarray-2026.2.0 → uxarray-2026.4.0}/PKG-INFO +2 -2
- {uxarray-2026.2.0 → uxarray-2026.4.0}/pyproject.toml +1 -1
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/core/accessors.py +2 -2
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/core/dataarray.py +29 -4
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/core/dataset.py +21 -3
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/coordinates.py +0 -8
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/utils.py +84 -21
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/remap/bilinear.py +1 -1
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray.egg-info/PKG-INFO +2 -2
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray.egg-info/requires.txt +1 -1
- {uxarray-2026.2.0 → uxarray-2026.4.0}/.codecov.yml +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/.git_archival.txt +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/.gitattributes +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/CITATION.cff +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/CODE_OF_CONDUCT.md +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/LICENSE +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/MANIFEST.in +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/README.md +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/build.sh +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/setup.cfg +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/setup.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/__init__.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/constants.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/conventions/__init__.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/conventions/descriptors.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/conventions/ugrid.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/core/__init__.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/core/aggregation.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/core/api.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/core/gradient.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/core/utils.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/core/zonal.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/cross_sections/__init__.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/cross_sections/dataarray_accessor.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/cross_sections/grid_accessor.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/cross_sections/sample.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/formatting_html.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/__init__.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/arcs.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/area.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/bounds.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/connectivity.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/dual.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/geometry.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/grid.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/integrate.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/intersections.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/neighbors.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/point_in_face.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/slice.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/utils.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/grid/validation.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/__init__.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_delaunay.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_esmf.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_exodus.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_fesom2.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_geopandas.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_geos.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_healpix.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_icon.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_mpas.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_scrip.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_structured.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_topology.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_ugrid.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_vertices.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/io/_voronoi.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/plot/__init__.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/plot/accessor.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/plot/constants.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/plot/matplotlib.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/plot/utils.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/remap/__init__.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/remap/accessor.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/remap/inverse_distance_weighted.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/remap/nearest_neighbor.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/remap/spatial_coords_remap.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/remap/utils.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/subset/__init__.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/subset/dataarray_accessor.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/subset/grid_accessor.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/utils/__init__.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray/utils/computing.py +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray.egg-info/SOURCES.txt +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray.egg-info/dependency_links.txt +0 -0
- {uxarray-2026.2.0 → uxarray-2026.4.0}/uxarray.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Contributing to
|
|
1
|
+
# Contributing to UXarray
|
|
2
2
|
|
|
3
|
-
Anyone can contribute to and participate in the
|
|
3
|
+
Anyone can contribute to and participate in the UXarray project
|
|
4
4
|
at any levels of project development! We conduct all of our work
|
|
5
5
|
in the open, and all of our work is Open Source Licensed.
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
# How to install
|
|
1
|
+
# How to install UXarray
|
|
2
2
|
|
|
3
3
|
Please see our
|
|
4
|
-
[
|
|
4
|
+
[UXarray Installation](https://uxarray.readthedocs.io/en/latest/getting-started/installation.html)
|
|
5
5
|
instructions for detailed information!
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uxarray
|
|
3
|
-
Version: 2026.
|
|
3
|
+
Version: 2026.4.0
|
|
4
4
|
Summary: Xarray extension for unstructured climate and global weather data analysis and visualization.
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -230,7 +230,7 @@ Requires-Dist: matplotlib
|
|
|
230
230
|
Requires-Dist: matplotlib-inline
|
|
231
231
|
Requires-Dist: netcdf4
|
|
232
232
|
Requires-Dist: numba
|
|
233
|
-
Requires-Dist: numpy
|
|
233
|
+
Requires-Dist: numpy
|
|
234
234
|
Requires-Dist: pandas
|
|
235
235
|
Requires-Dist: pyarrow
|
|
236
236
|
Requires-Dist: requests
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Delegation-based accessor classes for
|
|
2
|
+
Delegation-based accessor classes for UXarray groupby operations.
|
|
3
3
|
|
|
4
4
|
These classes wrap xarray's groupby/resample/etc objects and ensure that
|
|
5
5
|
operations return UxDataArray/UxDataset objects with preserved uxgrid.
|
|
@@ -34,7 +34,7 @@ DATAARRAY_ACCESSOR_METHODS = {
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class BaseAccessor:
|
|
37
|
-
"""Base class for all
|
|
37
|
+
"""Base class for all UXarray accessor classes."""
|
|
38
38
|
|
|
39
39
|
# Default methods known to return DataArrays/Datasets - optimized for performance
|
|
40
40
|
_DEFAULT_PRESERVE_METHODS = {
|
|
@@ -573,7 +573,7 @@ class UxDataArray(xr.DataArray):
|
|
|
573
573
|
|
|
574
574
|
Examples
|
|
575
575
|
--------
|
|
576
|
-
Open a
|
|
576
|
+
Open a UXarray dataset and compute the integral
|
|
577
577
|
|
|
578
578
|
>>> import uxarray as ux
|
|
579
579
|
>>> uxds = ux.open_dataset("grid.ug", "centroid_pressure_data_ug")
|
|
@@ -691,10 +691,19 @@ class UxDataArray(xr.DataArray):
|
|
|
691
691
|
dims = list(self.dims)
|
|
692
692
|
dims[face_axis] = "latitudes"
|
|
693
693
|
|
|
694
|
+
# Assign coords from `self` to the result except one that corresponds to `dims[face_axis]`
|
|
695
|
+
new_coords = {
|
|
696
|
+
k: v
|
|
697
|
+
for k, v in self.coords.items()
|
|
698
|
+
if self.dims[face_axis] not in v.dims
|
|
699
|
+
}
|
|
700
|
+
# Add latitudes to the resulting coords
|
|
701
|
+
new_coords["latitudes"] = latitudes
|
|
702
|
+
|
|
694
703
|
return xr.DataArray(
|
|
695
704
|
res,
|
|
696
705
|
dims=dims,
|
|
697
|
-
coords=
|
|
706
|
+
coords=new_coords,
|
|
698
707
|
name=self.name + "_zonal_mean"
|
|
699
708
|
if self.name is not None
|
|
700
709
|
else "zonal_mean",
|
|
@@ -736,10 +745,19 @@ class UxDataArray(xr.DataArray):
|
|
|
736
745
|
dims = list(self.dims)
|
|
737
746
|
dims[face_axis] = "latitudes"
|
|
738
747
|
|
|
748
|
+
# Assign coords from `self` to the result except one that corresponds to `dims[face_axis]`
|
|
749
|
+
new_coords = {
|
|
750
|
+
k: v
|
|
751
|
+
for k, v in self.coords.items()
|
|
752
|
+
if self.dims[face_axis] not in v.dims
|
|
753
|
+
}
|
|
754
|
+
# Add latitudes to the resulting coords
|
|
755
|
+
new_coords["latitudes"] = centers
|
|
756
|
+
|
|
739
757
|
return xr.DataArray(
|
|
740
758
|
res,
|
|
741
759
|
dims=dims,
|
|
742
|
-
coords=
|
|
760
|
+
coords=new_coords,
|
|
743
761
|
name=self.name + "_zonal_mean"
|
|
744
762
|
if self.name is not None
|
|
745
763
|
else "zonal_mean",
|
|
@@ -853,10 +871,17 @@ class UxDataArray(xr.DataArray):
|
|
|
853
871
|
data=hit_count, dims="radius", coords={"radius": radii_deg}
|
|
854
872
|
)
|
|
855
873
|
|
|
874
|
+
# Assign coords from `self` to the result except one that corresponds to `dims[face_axis]`
|
|
875
|
+
new_coords = {
|
|
876
|
+
k: v for k, v in self.coords.items() if self.dims[face_axis] not in v.dims
|
|
877
|
+
}
|
|
878
|
+
# Add radii_deg to the resulting coords
|
|
879
|
+
new_coords["radius"] = radii_deg
|
|
880
|
+
|
|
856
881
|
uxda = xr.DataArray(
|
|
857
882
|
means,
|
|
858
883
|
dims=dims,
|
|
859
|
-
coords=
|
|
884
|
+
coords=new_coords,
|
|
860
885
|
name=self.name + "_azimuthal_mean"
|
|
861
886
|
if self.name is not None
|
|
862
887
|
else "azimuthal_mean",
|
|
@@ -90,6 +90,24 @@ class UxDataset(xr.Dataset):
|
|
|
90
90
|
else:
|
|
91
91
|
self._uxgrid = uxgrid
|
|
92
92
|
|
|
93
|
+
# As of xarray's 2026.4.0, `xr.Dataset(xr.Dataset)` is prohibited;
|
|
94
|
+
# hence this check, i.e. if we get `xr.Dataset` as input, use its `data_vars`
|
|
95
|
+
# as `dict` and handle `coords` and `attrs` properly as well
|
|
96
|
+
if args and isinstance(args[0], xr.Dataset):
|
|
97
|
+
ds = args[0]
|
|
98
|
+
# Replacee only args[0], `ds`, with `ds.data_vars` as `dict`
|
|
99
|
+
args = (dict(ds.data_vars),) + args[1:]
|
|
100
|
+
# coords not passed positionally
|
|
101
|
+
if len(args) < 2:
|
|
102
|
+
kwargs.setdefault(
|
|
103
|
+
"coords", dict(ds.coords)
|
|
104
|
+
) # Set it as kwarg only if not explicitly provided
|
|
105
|
+
# attrs not passed positionally
|
|
106
|
+
if len(args) < 3:
|
|
107
|
+
kwargs.setdefault(
|
|
108
|
+
"attrs", ds.attrs
|
|
109
|
+
) # Set it as kwarg only if not explicitly provided
|
|
110
|
+
|
|
93
111
|
super().__init__(*args, **kwargs)
|
|
94
112
|
|
|
95
113
|
# declare plotting accessor
|
|
@@ -567,7 +585,7 @@ class UxDataset(xr.Dataset):
|
|
|
567
585
|
|
|
568
586
|
Examples
|
|
569
587
|
--------
|
|
570
|
-
Open a
|
|
588
|
+
Open a UXarray dataset
|
|
571
589
|
|
|
572
590
|
>>> import uxarray as ux
|
|
573
591
|
>>> uxds = ux.open_dataset("grid.ug", "centroid_pressure_data_ug")
|
|
@@ -627,9 +645,9 @@ class UxDataset(xr.Dataset):
|
|
|
627
645
|
"""
|
|
628
646
|
if grid_format == "HEALPix":
|
|
629
647
|
ds = self.rename_dims({"n_face": "cell"})
|
|
630
|
-
return xr.Dataset(ds)
|
|
648
|
+
return xr.Dataset(ds.data_vars, coords=ds.coords, attrs=ds.attrs)
|
|
631
649
|
|
|
632
|
-
return xr.Dataset(self)
|
|
650
|
+
return xr.Dataset(self.data_vars, coords=self.coords, attrs=self.attrs)
|
|
633
651
|
|
|
634
652
|
def get_dual(self):
|
|
635
653
|
"""Compute the dual mesh for a dataset, returns a new dataset object.
|
|
@@ -68,10 +68,6 @@ def _xyz_to_lonlat_rad_no_norm(
|
|
|
68
68
|
def _xyz_to_lonlat_rad_scalar(x, y, z, normalize=True):
|
|
69
69
|
if normalize:
|
|
70
70
|
x, y, z = _normalize_xyz_scalar(x, y, z)
|
|
71
|
-
denom = abs(x * x + y * y + z * z)
|
|
72
|
-
x /= denom
|
|
73
|
-
y /= denom
|
|
74
|
-
z /= denom
|
|
75
71
|
|
|
76
72
|
lon = np.arctan2(y, x)
|
|
77
73
|
lat = np.asin(z)
|
|
@@ -121,10 +117,6 @@ def _xyz_to_lonlat_rad(
|
|
|
121
117
|
|
|
122
118
|
if normalize:
|
|
123
119
|
x, y, z = _normalize_xyz(x, y, z)
|
|
124
|
-
denom = np.abs(x * x + y * y + z * z)
|
|
125
|
-
x /= denom
|
|
126
|
-
y /= denom
|
|
127
|
-
z /= denom
|
|
128
120
|
|
|
129
121
|
lon = np.arctan2(y, x)
|
|
130
122
|
lat = np.arcsin(z)
|
|
@@ -7,51 +7,114 @@ from uxarray.io._mpas import _mpas_to_ugrid_dims
|
|
|
7
7
|
from uxarray.io._ugrid import _is_ugrid, _read_ugrid
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
def _is_exodus(dataset: xr.Dataset) -> bool:
|
|
11
|
+
"""Check whether a dataset looks like an Exodus mesh."""
|
|
12
|
+
has_packed_coords = "coord" in dataset
|
|
13
|
+
has_split_coords = {"coordx", "coordy"}.issubset(dataset.variables)
|
|
14
|
+
has_connectivity = any(
|
|
15
|
+
name.startswith("connect") for name in dataset.variables
|
|
16
|
+
) or any("num_nod_per_el" in dim for dim in dataset.dims)
|
|
17
|
+
|
|
18
|
+
return has_connectivity and (has_packed_coords or has_split_coords)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _is_scrip(dataset: xr.Dataset) -> bool:
|
|
22
|
+
"""Check whether a dataset looks like an unstructured SCRIP grid."""
|
|
23
|
+
required_vars = {
|
|
24
|
+
"grid_center_lon",
|
|
25
|
+
"grid_center_lat",
|
|
26
|
+
"grid_corner_lon",
|
|
27
|
+
"grid_corner_lat",
|
|
28
|
+
}
|
|
29
|
+
unstructured_markers = {"grid_imask", "grid_rank", "grid_area"}
|
|
30
|
+
|
|
31
|
+
return required_vars.issubset(dataset.variables) and any(
|
|
32
|
+
marker in dataset for marker in unstructured_markers
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _is_mpas(dataset: xr.Dataset) -> bool:
|
|
37
|
+
"""Check whether a dataset looks like an MPAS grid."""
|
|
38
|
+
if "verticesOnCell" not in dataset:
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
companion_groups = (
|
|
42
|
+
{"nEdgesOnCell"},
|
|
43
|
+
{"latCell", "lonCell"},
|
|
44
|
+
{"latVertex", "lonVertex"},
|
|
45
|
+
{"xCell", "yCell", "zCell"},
|
|
46
|
+
{"xVertex", "yVertex", "zVertex"},
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return any(group.issubset(dataset.variables) for group in companion_groups)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _is_esmf(dataset: xr.Dataset) -> bool:
|
|
53
|
+
"""Check whether a dataset looks like an ESMF mesh."""
|
|
54
|
+
return "maxNodePElement" in dataset.dims and "elementConn" in dataset
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _is_geos_cs(dataset: xr.Dataset) -> bool:
|
|
58
|
+
"""Check whether a dataset looks like a GEOS cube-sphere grid."""
|
|
59
|
+
required_dims = {"nf", "YCdim", "XCdim"}
|
|
60
|
+
required_vars = {"corner_lons", "corner_lats"}
|
|
61
|
+
|
|
62
|
+
return required_dims.issubset(dataset.sizes) and required_vars.issubset(
|
|
63
|
+
dataset.variables
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _is_icon(dataset: xr.Dataset) -> bool:
|
|
68
|
+
"""Check whether a dataset looks like an ICON grid."""
|
|
69
|
+
required_vars = {"vertex_of_cell", "clon", "clat", "vlon", "vlat"}
|
|
70
|
+
return required_vars.issubset(dataset.variables)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _is_fesom2(dataset: xr.Dataset) -> bool:
|
|
74
|
+
"""Check whether a dataset looks like a FESOM2 grid."""
|
|
75
|
+
return "triag_nodes" in dataset
|
|
76
|
+
|
|
77
|
+
|
|
10
78
|
def _parse_grid_type(dataset):
|
|
11
|
-
"""
|
|
12
|
-
UGrid, SCRIP, Exodus, ESMF, and shape file.
|
|
79
|
+
"""Determine the grid type represented by an input dataset.
|
|
13
80
|
|
|
14
81
|
Parameters
|
|
15
82
|
----------
|
|
16
83
|
dataset : Xarray dataset
|
|
17
|
-
|
|
84
|
+
Xarray dataset containing grid topology information.
|
|
18
85
|
|
|
19
86
|
Returns
|
|
20
87
|
-------
|
|
21
|
-
|
|
22
|
-
|
|
88
|
+
tuple[str, str | None, str | None]
|
|
89
|
+
A 3-tuple of ``(mesh_type, lon_name, lat_name)``. ``mesh_type`` is one
|
|
90
|
+
of ``"Exodus"``, ``"Scrip"``, ``"UGRID"``, ``"MPAS"``, ``"ESMF"``,
|
|
91
|
+
``"GEOS-CS"``, ``"ICON"``, ``"FESOM2"``, or ``"Structured"``. The
|
|
92
|
+
longitude and latitude coordinate names are only returned for structured
|
|
93
|
+
grids and are otherwise ``None``.
|
|
23
94
|
|
|
24
95
|
Raises
|
|
25
96
|
------
|
|
26
97
|
RuntimeError
|
|
27
|
-
|
|
28
|
-
ValueError
|
|
29
|
-
If file is not in UGRID format
|
|
98
|
+
If the dataset format cannot be recognized.
|
|
30
99
|
"""
|
|
31
100
|
|
|
32
101
|
_structured, lon_name, lat_name = _is_structured(dataset)
|
|
33
102
|
|
|
34
|
-
if
|
|
35
|
-
# exodus with coord or coordx
|
|
36
|
-
mesh_type = "Exodus"
|
|
37
|
-
elif "coordx" in dataset:
|
|
103
|
+
if _is_exodus(dataset):
|
|
38
104
|
mesh_type = "Exodus"
|
|
39
|
-
elif
|
|
40
|
-
# scrip with grid_center_lon
|
|
105
|
+
elif _is_scrip(dataset):
|
|
41
106
|
mesh_type = "Scrip"
|
|
42
107
|
elif _is_ugrid(dataset):
|
|
43
|
-
# ugrid topology is present
|
|
44
108
|
mesh_type = "UGRID"
|
|
45
|
-
elif
|
|
109
|
+
elif _is_mpas(dataset):
|
|
46
110
|
mesh_type = "MPAS"
|
|
47
|
-
elif
|
|
111
|
+
elif _is_esmf(dataset):
|
|
48
112
|
mesh_type = "ESMF"
|
|
49
|
-
elif
|
|
50
|
-
# expected dimensions for a GEOS cube sphere grid
|
|
113
|
+
elif _is_geos_cs(dataset):
|
|
51
114
|
mesh_type = "GEOS-CS"
|
|
52
|
-
elif
|
|
115
|
+
elif _is_icon(dataset):
|
|
53
116
|
mesh_type = "ICON"
|
|
54
|
-
elif
|
|
117
|
+
elif _is_fesom2(dataset):
|
|
55
118
|
mesh_type = "FESOM2"
|
|
56
119
|
elif _structured:
|
|
57
120
|
mesh_type = "Structured"
|
|
@@ -128,7 +128,7 @@ def _barycentric_weights(point_xyz, dual, data_size, source_grid):
|
|
|
128
128
|
# there were rare cases where counts > 0, hence the newer condition at the end
|
|
129
129
|
elif counts == 1:
|
|
130
130
|
all_weights[i, 0] = 1.0
|
|
131
|
-
all_indices[i, 0] = int(cur_inds[0])
|
|
131
|
+
all_indices[i, 0] = int(cur_inds[0].squeeze())
|
|
132
132
|
# 2/2/2026: For some `remap_to="nodes"` cases, `counts` happen to be bigger than 1. Not sure
|
|
133
133
|
# if the best way to add weights from multiple faces is to take only the first face's though
|
|
134
134
|
else:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uxarray
|
|
3
|
-
Version: 2026.
|
|
3
|
+
Version: 2026.4.0
|
|
4
4
|
Summary: Xarray extension for unstructured climate and global weather data analysis and visualization.
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -230,7 +230,7 @@ Requires-Dist: matplotlib
|
|
|
230
230
|
Requires-Dist: matplotlib-inline
|
|
231
231
|
Requires-Dist: netcdf4
|
|
232
232
|
Requires-Dist: numba
|
|
233
|
-
Requires-Dist: numpy
|
|
233
|
+
Requires-Dist: numpy
|
|
234
234
|
Requires-Dist: pandas
|
|
235
235
|
Requires-Dist: pyarrow
|
|
236
236
|
Requires-Dist: requests
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|