Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ Makie.save("surface_plot.png", fig)
- The number of dimensions of a `OutputVar` can be accessed with `ndims`.
- You can drop dimensions of size 1 with `dropdims`.
- `==` and `isequal` are now defined for `OutputVar`, `FlatVar`, and `Metadata`.
- When resampling with keyword arguments, `resampled_as` now accepts dates for
the time dimension, e.g. `resampled_as(var, time = [Dates.DateTime(2010)])`.

## Bug fixes

Expand Down
20 changes: 20 additions & 0 deletions docs/src/howdoi.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ the dimensions in `dest_var`.
```@setup resampled_as
import ClimaAnalysis
import OrderedCollections: OrderedDict
import Dates

src_lon = [0.0, 1.0, 2.0]
src_lat = [0.0, 1.0, 2.0, 3.0]
Expand All @@ -260,6 +261,11 @@ dest_dims = OrderedDict("long" => dest_long, "lat" => dest_lat)
dest_dim_attribs = OrderedDict("long" => Dict("units" => "degrees"), "lat" => Dict("units" => "degrees"))
dest_attribs = Dict("long_name" => "hi")
dest_var = ClimaAnalysis.OutputVar(dest_attribs, dest_dims, dest_dim_attribs, dest_var_data)

time_dims = OrderedDict("time" => [0.0, 86400.0, 172800.0])
time_dim_attribs = OrderedDict("time" => Dict("units" => "s"))
time_attribs = Dict("long_name" => "hi", "start_date" => "2010-01-01")
time_var = ClimaAnalysis.OutputVar(time_attribs, time_dims, time_dim_attribs, [1.0, 2.0, 3.0])
```

```@repl resampled_as
Expand Down Expand Up @@ -312,6 +318,20 @@ resampled_var.data
resampled_var.dims
```

If `start_date` is among the attributes of the `OutputVar`, then dates can be
passed to the time dimension. The dates are automatically converted to the
corresponding times using `start_date`.

```@repl resampled_as
ClimaAnalysis.dates(time_var)
resampled_var = ClimaAnalysis.resampled_as(
time_var,
time = [Dates.DateTime(2010, 1, 1), Dates.DateTime(2010, 1, 2)],
);
resampled_var.data
ClimaAnalysis.dates(resampled_var)
```

## How do I load multiple NetCDF files along the time dimension?

To load multiple NetCDF files along the time dimension, you can pass in
Expand Down
24 changes: 23 additions & 1 deletion src/Var.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1788,11 +1788,33 @@ If the dimensions in `dims` and `src_var.dims` match (ignoring order), the resul
dimensions of the resulting `OutputVar` will remain unchanged. If the dimensions of `dims`
is a strict subset of the dimensions in `src_var`, then partial resampling is done instead.

When resampling on the time dimension and `start_date` is among the attributes of
`src_var`, it is possible to directly pass a vector of `Dates.DateTime` and
`resampled_as` will automatically convert the dates into the corresponding times.

Note that there is no checking for units of the dimensions.

!!! compat "Support for dates"
Passing dates for the time dimension is introduced after ClimaAnalysis
v0.5.22.
"""
function resampled_as(src_var::OutputVar; kwargs...)
# If the values are dates, then compute the associated times before resampling
function _kwarg_to_dim_pair(dim_name, dim_array)
dim_name = String(dim_name)
vals_are_dates = eltype(dim_array) <: Dates.AbstractDateTime
dim_is_time = conventional_dim_name(dim_name) == "time"
(vals_are_dates && !dim_is_time) &&
error("Dates are only supported with time dimension")
vals_are_dates && (dim_array = date_to_time.(Ref(src_var), dim_array))
return dim_name => dim_array
end

# Construct tuple
dims = (String(dim_name) => dim_array for (dim_name, dim_array) in kwargs)
dims = (
_kwarg_to_dim_pair(dim_name, dim_array) for
(dim_name, dim_array) in kwargs
)

# Find corresponding dimension names in src_var
src_var_dim_names = collect(keys(src_var.dims))
Expand Down
65 changes: 65 additions & 0 deletions test/test_Var.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2030,6 +2030,71 @@ end
Dates.DateTime("2010-01-01")
end

@testset "Resampling with dates" begin
src_time = [0.0, 86400.0, 172800.0, 259200.0]
src_var =
TemplateVar() |>
add_dim("time", src_time, units = "s") |>
add_attribs(long_name = "hi", start_date = "2010-01-01") |>
one_to_n_data() |>
initialize

dest_dates =
[Dates.DateTime(2010, 1, 1, 12), Dates.DateTime(2010, 1, 2, 12)]
resampled_var = ClimaAnalysis.resampled_as(src_var, time = dest_dates)
@test ClimaAnalysis.times(resampled_var) == [43200.0, 129600.0]
@test ClimaAnalysis.dates(resampled_var) == dest_dates
@test resampled_var.data == [1.5, 2.5]

# Specify the time dimension by one of its conventional names
resampled_var = ClimaAnalysis.resampled_as(src_var, t = dest_dates)
@test ClimaAnalysis.times(resampled_var) == [43200.0, 129600.0]
@test resampled_var.data == [1.5, 2.5]

# Partial resampling on the time dimension with dates
src_long = 0.0:2.0 |> collect
src_var =
TemplateVar() |>
add_dim("time", src_time, units = "s") |>
add_dim("long", src_long, units = "degrees") |>
add_attribs(long_name = "hi", start_date = "2010-01-01") |>
one_to_n_data() |>
initialize
resampled_var = ClimaAnalysis.resampled_as(src_var, time = dest_dates)
@test ClimaAnalysis.times(resampled_var) == [43200.0, 129600.0]
@test resampled_var.dims["long"] == src_long
@test resampled_var.data == [[1.5, 2.5] [5.5, 6.5] [9.5, 10.5]]

# Resampling with a mix of dates and floats
resampled_var = ClimaAnalysis.resampled_as(
src_var,
time = dest_dates,
long = [0.0, 1.0],
)
@test ClimaAnalysis.times(resampled_var) == [43200.0, 129600.0]
@test resampled_var.dims["long"] == [0.0, 1.0]
@test resampled_var.data == [[1.5, 2.5] [5.5, 6.5]]

# Error handling
# Dates for a dimension that is not time
@test_throws ErrorException ClimaAnalysis.resampled_as(
src_var,
long = dest_dates,
)

# Dates when start_date is not among the attributes
no_start_date_var =
TemplateVar() |>
add_dim("time", src_time, units = "s") |>
add_attribs(long_name = "hi") |>
one_to_n_data() |>
initialize
@test_throws ErrorException ClimaAnalysis.resampled_as(
no_start_date_var,
time = dest_dates,
)
end

@testset "Units" begin
long = -180.0:180.0 |> collect
data = copy(long)
Expand Down
Loading