@@ -305,6 +305,28 @@ def _select_range_slice(da, da_bin, da_mask):
305305 return da_slice .where (~ da_mask )
306306
307307
308+ def _slice_range_at_bin (xr_obj , da_bin ):
309+ da_bin , da_mask = get_bin_dataarray (xr_obj , bins = da_bin )
310+
311+ # Slice along the 'range' dimension
312+ is_dataset_input = isinstance (xr_obj , xr .Dataset )
313+ if is_dataset_input :
314+ vertical_variables = xr_obj .gpm .vertical_variables
315+ non_vertical_variables = set (xr_obj .data_vars ) - set (vertical_variables )
316+ # Copy non vertical variables
317+ xr_out = xr_obj [non_vertical_variables ].copy ()
318+ # Slice vertical variables
319+ for var in vertical_variables :
320+ xr_out [var ] = _select_range_slice (da = xr_obj [var ], da_bin = da_bin , da_mask = da_mask )
321+ else :
322+ xr_out = _select_range_slice (
323+ da = xr_obj ,
324+ da_bin = da_bin ,
325+ da_mask = da_mask ,
326+ )
327+ return xr_out
328+
329+
308330def slice_range_at_bin (xr_obj , bins ):
309331 """Extract values at the range bins specified by ``bin_variable``.
310332
@@ -332,25 +354,95 @@ def slice_range_at_bin(xr_obj, bins):
332354 check_has_vertical_dim (xr_obj )
333355
334356 # Get the bin DataArray
335- da_bin , da_mask = get_bin_dataarray (xr_obj , bins = bins )
357+ da_bin = _get_bin_dataarray (xr_obj , bins = bins )
336358
337- # Slice along the 'range' dimension
338- is_dataset_input = isinstance (xr_obj , xr .Dataset )
339- if is_dataset_input :
340- vertical_variables = xr_obj .gpm .vertical_variables
341- non_vertical_variables = set (xr_obj .data_vars ) - set (vertical_variables )
342- # Copy non vertical variables
343- xr_out = xr_obj [non_vertical_variables ].copy ()
344- # Slice vertical variables
345- for var in vertical_variables :
346- xr_out [var ] = _select_range_slice (da = xr_obj [var ], da_bin = da_bin , da_mask = da_mask )
347- else :
348- xr_out = _select_range_slice (
349- da = xr_obj ,
350- da_bin = da_bin ,
351- da_mask = da_mask ,
359+ # Bin without frequency
360+ if "radar_frequency" not in da_bin .dims :
361+ da_bin = da_bin .drop_vars ("radar_frequency" , errors = "ignore" )
362+ return _slice_range_at_bin (xr_obj , da_bin )
363+
364+ # If this is a DataArray, the simple case is enough
365+ if isinstance (xr_obj , xr .DataArray ):
366+ list_da = []
367+
368+ for radar_frequency in da_bin ["radar_frequency" ].to_numpy ():
369+ da_f = xr_obj .sel (radar_frequency = radar_frequency )
370+ da_bin_f = da_bin .sel (radar_frequency = radar_frequency )
371+
372+ da_f = _slice_range_at_bin (da_f , da_bin_f )
373+ da_f = da_f .expand_dims (radar_frequency = [radar_frequency ])
374+
375+ list_da .append (da_f )
376+
377+ return xr .concat (list_da , dim = "radar_frequency" )
378+
379+ # Dataset case
380+ frequency_variables = xr_obj .gpm .frequency_variables
381+ non_frequency_variables = set (xr_obj .data_vars ) - set (frequency_variables )
382+
383+ # Slice variables having radar_frequency frequency-by-frequency
384+ ds_freq = xr_obj [frequency_variables ]
385+ list_ds = []
386+ for radar_frequency in da_bin ["radar_frequency" ].to_numpy ():
387+ ds_f = ds_freq .sel (radar_frequency = radar_frequency )
388+ da_bin_f = da_bin .sel (radar_frequency = radar_frequency )
389+
390+ ds_f = _slice_range_at_bin (ds_f , da_bin_f )
391+ ds_f = ds_f .expand_dims (radar_frequency = [radar_frequency ])
392+ list_ds .append (ds_f )
393+
394+ ds_freq_sliced = xr .concat (list_ds , dim = "radar_frequency" , coords = "different" , compat = "equals" )
395+
396+ # Slice variables without radar_frequency only once.
397+ # --> Selecting the first frequency bin.
398+ first_frequency = da_bin ["radar_frequency" ].to_numpy ()[0 ]
399+ da_bin_ref = da_bin .sel (radar_frequency = first_frequency )
400+ ds_non_freq = xr .Dataset ()
401+ if len (non_frequency_variables ) > 0 :
402+ ds_non_freq = _slice_range_at_bin (
403+ xr_obj [non_frequency_variables ],
404+ da_bin_ref ,
352405 )
353- return xr_out
406+
407+ return xr .merge ([ds_freq_sliced , ds_non_freq ], compat = "override" )
408+
409+ # # Get the bin DataArray
410+ # da_bin, da_mask = get_bin_dataarray(xr_obj, bins=bins)
411+
412+ # # Slice along the 'range' dimension
413+ # is_dataset_input = isinstance(xr_obj, xr.Dataset)
414+ # if is_dataset_input:
415+ # vertical_variables = xr_obj.gpm.vertical_variables
416+ # non_vertical_variables = set(xr_obj.data_vars) - set(vertical_variables)
417+ # # Copy non vertical variables
418+ # xr_out = xr_obj[non_vertical_variables].copy()
419+ # # Slice vertical variables
420+ # for var in vertical_variables:
421+ # xr_out[var] = _select_range_slice(da=xr_obj[var], da_bin=da_bin, da_mask=da_mask)
422+ # else:
423+ # xr_out = _select_range_slice(
424+ # da=xr_obj,
425+ # da_bin=da_bin,
426+ # da_mask=da_mask,
427+ # )
428+ # return xr_out
429+
430+
431+ def slice_range_at_cfb (xr_obj , tolerance = 0 ):
432+ """Slice the 3D arrays at the surface given by binRealSurface.
433+
434+ If tolerance is positive, slice tolerance n_gates below CFB (within the blind zone).
435+ If tolerance is negative, slice tolerance n_gates above CFB.
436+ """
437+ da_bins_cfb = get_xarray_variable (xr_obj , variable = "binClutterFreeBottom" )
438+ da_bins_cfb = da_bins_cfb + tolerance
439+ return slice_range_at_bin (xr_obj , bins = da_bins_cfb )
440+
441+
442+ def slice_range_at_surface (xr_obj ):
443+ """Slice the 3D arrays at the surface given by binRealSurface."""
444+ da_bins_surface = get_xarray_variable (xr_obj , variable = "binRealSurface" ) - 1
445+ return slice_range_at_bin (xr_obj , bins = da_bins_surface )
354446
355447
356448####------------------------------------------------------------------------------------------------------------------.
0 commit comments