48
48
)
49
49
50
50
51
+ try :
52
+ import pyproj
53
+ import cartopy .crs
54
+ except ImportError :
55
+ pyproj = None
56
+
57
+
51
58
from . import parametric , sgrid
52
59
from .criteria import (
53
60
_DSG_ROLES ,
@@ -2745,6 +2752,20 @@ def grid_mapping_names(self) -> dict[str, list[str]]:
2745
2752
results [v ].append (k )
2746
2753
return results
2747
2754
2755
+ @property
2756
+ def crs (self ):
2757
+ """Cartopy CRS of the dataset's grid mapping."""
2758
+ if pyproj is None :
2759
+ raise ImportError ('`crs` accessor requires optional packages `pyproj` and `cartopy`.' )
2760
+ gmaps = list (itertools .chain (* self .grid_mapping_names .values ()))
2761
+ if len (gmaps ) > 1 :
2762
+ raise ValueError ("Multiple grid mappings found." )
2763
+ if len (gmaps ) == 0 :
2764
+ if 'longitude' in self :
2765
+ return cartopy .crs .PlateCarree ()
2766
+ raise ValueError ('No grid mapping nor longitude found in dataset.' )
2767
+ return cartopy .crs .Projection (pyproj .CRS .from_cf (self ._obj [gmaps [0 ]].attrs ))
2768
+
2748
2769
def decode_vertical_coords (
2749
2770
self , * , outnames : dict [str , str ] | None = None , prefix : str | None = None
2750
2771
) -> None :
@@ -2899,6 +2920,21 @@ def formula_terms(self) -> dict[str, str]: # numpydoc ignore=SS06
2899
2920
terms [key ] = value
2900
2921
return terms
2901
2922
2923
+ def _get_grid_mapping (self , ignore_missing = False ) -> DataArray :
2924
+ da = self ._obj
2925
+
2926
+ attrs_or_encoding = ChainMap (da .attrs , da .encoding )
2927
+ grid_mapping = attrs_or_encoding .get ("grid_mapping" , None )
2928
+ if not grid_mapping :
2929
+ if ignore_missing :
2930
+ return None
2931
+ raise ValueError ("No 'grid_mapping' attribute present." )
2932
+
2933
+ if grid_mapping not in da ._coords :
2934
+ raise ValueError (f"Grid Mapping variable { grid_mapping } not present." )
2935
+
2936
+ return da [grid_mapping ]
2937
+
2902
2938
@property
2903
2939
def grid_mapping_name (self ) -> str :
2904
2940
"""
@@ -2919,21 +2955,22 @@ def grid_mapping_name(self) -> str:
2919
2955
>>> rotds.cf["temp"].cf.grid_mapping_name
2920
2956
'rotated_latitude_longitude'
2921
2957
"""
2922
-
2923
- da = self ._obj
2924
-
2925
- attrs_or_encoding = ChainMap (da .attrs , da .encoding )
2926
- grid_mapping = attrs_or_encoding .get ("grid_mapping" , None )
2927
- if not grid_mapping :
2928
- raise ValueError ("No 'grid_mapping' attribute present." )
2929
-
2930
- if grid_mapping not in da ._coords :
2931
- raise ValueError (f"Grid Mapping variable { grid_mapping } not present." )
2932
-
2933
- grid_mapping_var = da [grid_mapping ]
2934
-
2958
+ grid_mapping_var = self ._get_grid_mapping ()
2935
2959
return grid_mapping_var .attrs ["grid_mapping_name" ]
2936
2960
2961
+ @property
2962
+ def crs (self ):
2963
+ """Cartopy CRS of the dataset's grid mapping."""
2964
+ if pyproj is None :
2965
+ raise ImportError ('`crs` accessor requires optional packages `pyproj` and `cartopy`.' )
2966
+
2967
+ grid_mapping_var = self ._get_grid_mapping (ignore_missing = True )
2968
+ if grid_mapping_var is None :
2969
+ if 'longitude' in self :
2970
+ return cartopy .crs .PlateCarree ()
2971
+ raise ValueError ('No grid mapping nor longitude found.' )
2972
+ return cartopy .crs .Projection (pyproj .CRS .from_cf (grid_mapping_var .attrs ))
2973
+
2937
2974
def __getitem__ (self , key : Hashable | Iterable [Hashable ]) -> DataArray :
2938
2975
"""
2939
2976
Index into a DataArray making use of CF attributes.
0 commit comments