-
Couldn't load subscription status.
- Fork 42
Add CRS accessor for cartopy #577
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
base: main
Are you sure you want to change the base?
Changes from all commits
81d28d7
b8a797c
67a03ad
c2b8584
97e8fd6
019f035
3d7d9c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,6 +1,7 @@ | ||||||
| from __future__ import annotations | ||||||
|
|
||||||
| import functools | ||||||
| import importlib | ||||||
| import inspect | ||||||
| import itertools | ||||||
| import re | ||||||
|
|
@@ -48,6 +49,14 @@ | |||||
| ) | ||||||
|
|
||||||
|
|
||||||
| if importlib.util.find_spec("cartopy"): | ||||||
| # pyproj is a dep of cartopy | ||||||
| import cartopy.crs | ||||||
| import pyproj | ||||||
| else: | ||||||
| pyproj = None | ||||||
|
|
||||||
|
|
||||||
| from . import parametric, sgrid | ||||||
| from .criteria import ( | ||||||
| _DSG_ROLES, | ||||||
|
|
@@ -76,6 +85,7 @@ | |||||
| always_iterable, | ||||||
| emit_user_level_warning, | ||||||
| invert_mappings, | ||||||
| is_latitude_longitude, | ||||||
| parse_cell_methods_attr, | ||||||
| parse_cf_standard_name_table, | ||||||
| ) | ||||||
|
|
@@ -1092,6 +1102,10 @@ def _plot_wrapper(*args, **kwargs): | |||||
| func.__name__ == "wrapper" | ||||||
| and (kwargs.get("hue") or self._obj.ndim == 1) | ||||||
| ) | ||||||
| is_grid_plot = (func.__name__ in ["contour", "countourf", "pcolormsh"]) or ( | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| func.__name__ == "wrapper" | ||||||
| and (self._obj.ndim - sum(["col" in kwargs, "row" in kwargs])) == 2 | ||||||
| ) | ||||||
| if is_line_plot: | ||||||
| hue = kwargs.get("hue") | ||||||
| if "x" not in kwargs and "y" not in kwargs: | ||||||
|
|
@@ -1101,6 +1115,20 @@ def _plot_wrapper(*args, **kwargs): | |||||
| else: | ||||||
| kwargs = self._process_x_or_y(kwargs, "x", skip=kwargs.get("y")) | ||||||
| kwargs = self._process_x_or_y(kwargs, "y", skip=kwargs.get("x")) | ||||||
| if is_grid_plot and pyproj is not None: | ||||||
| from cartopy.mpl.geoaxes import GeoAxes | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's check if cartopy is present with |
||||||
|
|
||||||
| ax = kwargs.get("ax") | ||||||
| if ax is None or isinstance(ax, GeoAxes): | ||||||
| try: | ||||||
| kwargs["transform"] = self._obj.cf.cartopy_crs | ||||||
| except ValueError: | ||||||
| pass | ||||||
| else: | ||||||
| if ax is None: | ||||||
| kwargs.setdefault("subplot_kws", {}).setdefault( | ||||||
| "projection", kwargs["transform"] | ||||||
| ) | ||||||
|
|
||||||
| # Now set some nice properties | ||||||
| kwargs = self._set_axis_props(kwargs, "x") | ||||||
|
|
@@ -2745,6 +2773,24 @@ def grid_mapping_names(self) -> dict[str, list[str]]: | |||||
| results[v].append(k) | ||||||
| return results | ||||||
|
|
||||||
| @property | ||||||
| def cartopy_crs(self): | ||||||
| """Cartopy CRS of the dataset's grid mapping.""" | ||||||
| if pyproj is None: | ||||||
| raise ImportError( | ||||||
| "`crs` accessor requires optional packages `pyproj` and `cartopy`." | ||||||
| ) | ||||||
| gmaps = list(itertools.chain(*self.grid_mapping_names.values())) | ||||||
| if len(gmaps) > 1: | ||||||
| raise ValueError("Multiple grid mappings found.") | ||||||
| if len(gmaps) == 0: | ||||||
| if is_latitude_longitude(self._obj): | ||||||
| return cartopy.crs.PlateCarree() | ||||||
| raise ValueError( | ||||||
| "No grid mapping found and dataset guessed as not latitude_longitude." | ||||||
| ) | ||||||
| return cartopy.crs.Projection(pyproj.CRS.from_cf(self._obj[gmaps[0]].attrs)) | ||||||
|
|
||||||
| def decode_vertical_coords( | ||||||
| self, *, outnames: dict[str, str] | None = None, prefix: str | None = None | ||||||
| ) -> None: | ||||||
|
|
@@ -2899,6 +2945,21 @@ def formula_terms(self) -> dict[str, str]: # numpydoc ignore=SS06 | |||||
| terms[key] = value | ||||||
| return terms | ||||||
|
|
||||||
| def _get_grid_mapping(self, ignore_missing=False) -> DataArray | None: | ||||||
| da = self._obj | ||||||
|
|
||||||
| attrs_or_encoding = ChainMap(da.attrs, da.encoding) | ||||||
| grid_mapping = attrs_or_encoding.get("grid_mapping", None) | ||||||
| if not grid_mapping: | ||||||
| if ignore_missing: | ||||||
| return None | ||||||
| raise ValueError("No 'grid_mapping' attribute present.") | ||||||
|
|
||||||
| if grid_mapping not in da._coords: | ||||||
| raise ValueError(f"Grid Mapping variable {grid_mapping} not present.") | ||||||
|
|
||||||
| return da[grid_mapping] | ||||||
|
|
||||||
| @property | ||||||
| def grid_mapping_name(self) -> str: | ||||||
| """ | ||||||
|
|
@@ -2919,20 +2980,25 @@ def grid_mapping_name(self) -> str: | |||||
| >>> rotds.cf["temp"].cf.grid_mapping_name | ||||||
| 'rotated_latitude_longitude' | ||||||
| """ | ||||||
| grid_mapping_var = self._get_grid_mapping() | ||||||
| return grid_mapping_var.attrs["grid_mapping_name"] | ||||||
|
|
||||||
| da = self._obj | ||||||
|
|
||||||
| attrs_or_encoding = ChainMap(da.attrs, da.encoding) | ||||||
| grid_mapping = attrs_or_encoding.get("grid_mapping", None) | ||||||
| if not grid_mapping: | ||||||
| raise ValueError("No 'grid_mapping' attribute present.") | ||||||
|
|
||||||
| if grid_mapping not in da._coords: | ||||||
| raise ValueError(f"Grid Mapping variable {grid_mapping} not present.") | ||||||
|
|
||||||
| grid_mapping_var = da[grid_mapping] | ||||||
| @property | ||||||
| def cartopy_crs(self): | ||||||
| """Cartopy CRS of the dataset's grid mapping.""" | ||||||
| if pyproj is None: | ||||||
| raise ImportError( | ||||||
| "`crs` accessor requires optional packages `pyproj` and `cartopy`." | ||||||
| ) | ||||||
|
|
||||||
| return grid_mapping_var.attrs["grid_mapping_name"] | ||||||
| grid_mapping_var = self._get_grid_mapping(ignore_missing=True) | ||||||
| if grid_mapping_var is None: | ||||||
| if is_latitude_longitude(self._obj): | ||||||
| return cartopy.crs.PlateCarree() | ||||||
| raise ValueError( | ||||||
| "No grid mapping found and dataset guesses as not latitude_longitude." | ||||||
| ) | ||||||
| return cartopy.crs.Projection(pyproj.CRS.from_cf(grid_mapping_var.attrs)) | ||||||
|
|
||||||
| def __getitem__(self, key: Hashable | Iterable[Hashable]) -> DataArray: | ||||||
| """ | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.