@@ -170,3 +170,44 @@ Weighted average of `a` and `b` with weight `γ`.
170170``(1 - γ) * a + γ * b``
171171"""
172172smooth (a, b, γ) = a + γ * (b - a)
173+
174+ """
175+ prange(xout, xin)
176+
177+ Compute the percentile range for the non-missing time steps of xin, and save it to xout.
178+ `lowerpercentile` and `upperpercentile` specify the boundary of the percentile range.
179+ These have to be between 0 and 1.
180+ """
181+ function prange (xout, xin, lowpercentile= 0.02 , upperpercentile= 0.98 )
182+ xinfiltered = filter (! ismissing, xin)
183+ filter! (! isnan, xinfiltered)
184+ lowerlim, upperlim = quantile (xinfiltered, [lowpercentile, upperpercentile])
185+ xout .= upperlim - lowerlim
186+ end
187+
188+ function prange (cube; lowerpercentile= 0.02 , upperpercentile= 0.98 , outpath= tempname () * " .zarr" , overwrite= false , kwargs... )
189+ mapCube (prange, cube, lowerpercentile, upperpercentile; indims= InDims (" Time" ), outdims= OutDims (; outtype= Float32, path= outpath, fill_value= NaN , overwrite, kwargs... ))
190+ end
191+
192+ @testitem " prange cube" begin
193+ using YAXArrays
194+ using Dates
195+ using DimensionalData: Ti, X, Y
196+ using Statistics
197+ import Random
198+ Random. seed! (1234 )
199+
200+ mock_axes = (
201+ Ti (Date (" 2022-01-01" ): Day (1 ): Date (" 2022-01-01" )+ Day (100 )),
202+ X (range (1 , 10 , length= 10 )),
203+ Y (range (1 , 5 , length= 15 )),
204+ )
205+ s = size (mock_axes)
206+ mock_data = reshape (1 : prod (s), s)
207+ mock_props = Dict ()
208+ mock_cube = YAXArray (mock_axes, mock_data, mock_props)
209+
210+ mock_trend = prange (mock_cube)
211+ @test mock_trend. axes == (mock_cube. X, mock_cube. Y)
212+ @test mock_trend[1 ,1 ] == 96
213+ end
0 commit comments