@@ -338,27 +338,21 @@ def _get_measure_variable(
338338
339339def _get_measure (obj : Union [DataArray , Dataset ], key : str ) -> List [str ]:
340340 """
341- Translate from cell measures ("area" or "volume") to appropriate variable name.
341+ Translate from cell measures to appropriate variable name.
342342 This function interprets the ``cell_measures`` attribute on DataArrays.
343343
344344 Parameters
345345 ----------
346346 obj: DataArray, Dataset
347347 DataArray belonging to the coordinate to be checked
348- key: str, ["area", "volume"]
348+ key: str
349349 key to check for.
350350
351351 Returns
352352 -------
353353 List[str], Variable name(s) in parent xarray object that matches axis or coordinate `key`
354354 """
355355
356- valid_keys = _CELL_MEASURES
357- if key not in valid_keys :
358- raise KeyError (
359- f"cf_xarray did not understand key { key !r} . Expected one of { valid_keys !r} "
360- )
361-
362356 if isinstance (obj , DataArray ):
363357 obj = obj ._to_temp_dataset ()
364358
@@ -438,7 +432,7 @@ def _build_docstring(func):
438432 mapper_docstrings = {
439433 _get_axis_coord : f"One or more of { (_AXIS_NAMES + _COORD_NAMES )!r} " ,
440434 _get_axis_coord_single : f"One of { (_AXIS_NAMES + _COORD_NAMES )!r} " ,
441- _get_measure_variable : f"One of { _CELL_MEASURES !r} " ,
435+ # _get_measure_variable: f"One of {_CELL_MEASURES!r}",
442436 }
443437
444438 sig = inspect .signature (func )
@@ -653,6 +647,9 @@ class CFAccessor:
653647
654648 def __init__ (self , da ):
655649 self ._obj = da
650+ self ._defined_cell_measures = tuple (
651+ set (_CELL_MEASURES + tuple (self .cell_measures ))
652+ )
656653
657654 def _process_signature (
658655 self ,
@@ -833,7 +830,7 @@ def describe(self):
833830
834831 text += "\n Cell Measures:\n "
835832 measures = self .cell_measures
836- for key in _CELL_MEASURES :
833+ for key in sorted ( self . _defined_cell_measures ) :
837834 text += f"\t { key } : { measures [key ] if key in measures else []} \n "
838835
839836 text += "\n Standard Names:\n "
@@ -930,15 +927,33 @@ def cell_measures(self) -> Dict[str, List[str]]:
930927 Returns
931928 -------
932929 Dictionary of valid cell measure names that can be used with __getitem__ or .cf[key].
933- Will be ("area", "volume") or a subset thereof.
934930 """
935931
936- measures = {
937- key : apply_mapper (_get_measure , self ._obj , key , error = False )
938- for key in _CELL_MEASURES
939- }
932+ obj = self ._obj
933+ all_attrs = [
934+ da .attrs .get ("cell_measures" )
935+ for da in obj .coords .values ()
936+ if da .attrs .get ("cell_measures" )
937+ ]
938+ if isinstance (obj , DataArray ):
939+ all_attrs += (
940+ [obj .attrs .get ("cell_measures" )]
941+ if obj .attrs .get ("cell_measures" )
942+ else []
943+ )
944+ elif isinstance (obj , Dataset ):
945+ all_attrs += [
946+ da .attrs .get ("cell_measures" )
947+ for da in obj .data_vars .values ()
948+ if da .attrs .get ("cell_measures" )
949+ ]
950+
951+ measures : Dict [str , List [str ]] = dict ()
952+ for attr in all_attrs :
953+ for key , value in parse_cell_methods_attr (attr ).items ():
954+ measures [key ] = measures .setdefault (key , []) + [value ]
940955
941- return {k : sorted (v ) for k , v in measures .items () if v }
956+ return {k : sorted (set ( v ) ) for k , v in measures .items () if v }
942957
943958 def get_standard_names (self ) -> List [str ]:
944959
@@ -1069,7 +1084,7 @@ def check_results(names, k):
10691084 check_results (names , k )
10701085 successful [k ] = bool (names )
10711086 coords .extend (names )
1072- elif k in _CELL_MEASURES :
1087+ elif k in self . _defined_cell_measures :
10731088 measure = _get_measure (self ._obj , k )
10741089 check_results (measure , k )
10751090 successful [k ] = bool (measure )
0 commit comments