@@ -129,6 +129,23 @@ def get_axis_dim(self, axis: _XGRID_AXES) -> int:
129129
130130 return get_cell_count_along_dim (self .xgcm_grid .axes [axis ])
131131
132+ def localize (self , position : dict [_XGRID_AXES , tuple [int , float ]], dims : list [str ]) -> dict [str , tuple [int , float ]]:
133+ """
134+ Uses the grid context (i.e., the staggering of the grid) to convert a position relative
135+ to the F-points in the grid to a position relative to the dimensions of the array
136+ of interest.
137+ """
138+ axis_to_var = {get_axis_from_dim_name (self .xgcm_grid .axes , dim ): dim for dim in dims }
139+ var_positions = {
140+ axis : get_xgcm_position_from_dim_name (self .xgcm_grid .axes , dim ) for axis , dim in axis_to_var .items ()
141+ }
142+ return {
143+ axis_to_var [axis ]: _convert_center_pos_to_fpoint (
144+ index = index , bcoord = bcoord , position = var_positions [axis ], f_points_position = self ._fpoint_info [axis ]
145+ )
146+ for axis , (index , bcoord ) in position .items ()
147+ }
148+
132149 @property
133150 def _z4d (self ) -> Literal [0 , 1 ]:
134151 """
@@ -185,6 +202,19 @@ def search(self, z, y, x, ei=None):
185202
186203 raise NotImplementedError ("Searching in >2D lon/lat arrays is not implemented yet." )
187204
205+ @cached_property
206+ def _fpoint_info (self ):
207+ xgcm_axes = self .xgcm_grid .axes
208+ f_point_positions = ["left" , "right" , "inner" , "outer" ]
209+ axis_position_mapping = {}
210+ for axis in self .axes :
211+ coords = xgcm_axes [axis ].coords
212+ edge_positions = list (filter (lambda x : x in f_point_positions , coords .keys ()))
213+ assert len (edge_positions ) == 1 , f"Axis { axis } has multiple edge positions: { edge_positions } "
214+ axis_position_mapping [axis ] = edge_positions [0 ]
215+
216+ return axis_position_mapping
217+
188218
189219def get_axis_from_dim_name (axes : _XGCM_AXES , dim : str ) -> _XGCM_AXIS_DIRECTION | None :
190220 """For a given dimension name in a grid, returns the direction axis it is on."""
@@ -337,3 +367,22 @@ def _search_1d_array(
337367 i = np .argmin (arr <= x ) - 1
338368 bcoord = (x - arr [i ]) / (arr [i + 1 ] - arr [i ])
339369 return i , bcoord
370+
371+
372+ def _convert_center_pos_to_fpoint (
373+ * , index : int , bcoord : float , position : _XGCM_AXIS_POSITION , f_points_position : _XGCM_AXIS_POSITION
374+ ) -> tuple [int , float ]:
375+ """Converts a position relative to the center point along an axis to a reposition relative to the cell edges."""
376+ if position != "center" :
377+ return index , bcoord
378+
379+ bcoord = bcoord - 0.5
380+ if bcoord < 0 :
381+ bcoord += 1.0
382+ index -= 1
383+
384+ # Correct relative to the f-point position
385+ if f_points_position in ["inner" , "right" ]:
386+ index += 1
387+
388+ return index , bcoord
0 commit comments