Skip to content

Commit dbe41fe

Browse files
committed
Add time and date bounds
1 parent 522dffc commit dbe41fe

File tree

4 files changed

+84
-0
lines changed

4 files changed

+84
-0
lines changed

NEWS.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
# NEWS
2+
v0.2.13
3+
-------
4+
5+
## Features
6+
7+
### Add time and date bounds for netCDF files
8+
In a netCDF file produced by ClimaDiagnostics, there are now the dimensions
9+
`time_bnds` and `date_bnds`. Each time or date value is a representative of the
10+
corresponding time or date bound. For example, if the time is `10.0` and
11+
corresponding time bound is `[0.0, 10.0]`, then the time of `10.0` represents
12+
the interval `[0.0, 10.0]`. If one knows that the data represents a time
13+
average, then the time of `10.0` is the time average over the interval
14+
`[0.0, 10.0]`.
15+
216
v0.2.12
317
-------
418

src/netcdf_writer.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ function write_field!(writer::NetCDFWriter, field, diagnostic, u, p, t)
355355
axis = "T",
356356
standard_name = "time",
357357
long_name = "Time",
358+
bounds = "time_bnds",
358359
)
359360

360361
dim_names = add_space_coordinates_maybe!(
@@ -373,12 +374,25 @@ function write_field!(writer::NetCDFWriter, field, diagnostic, u, p, t)
373374
else
374375
start_date = writer.start_date
375376
end
377+
378+
add_time_bounds_maybe!(
379+
nc,
380+
TT;
381+
comments = "time bounds for each time value",
382+
units = "s",
383+
)
384+
376385
if !isnothing(start_date)
377386
add_date_maybe!(
378387
nc;
379388
units = "seconds since $start_date",
380389
bounds = "date_bnds",
381390
)
391+
add_date_bounds_maybe!(
392+
nc;
393+
comments = "date bounds for each date value",
394+
units = "seconds since $start_date",
395+
)
382396
end
383397

384398
if haskey(nc, "$(var.short_name)")
@@ -411,6 +425,9 @@ function write_field!(writer::NetCDFWriter, field, diagnostic, u, p, t)
411425

412426
# TODO: Use ITime here
413427
nc["time"][time_index] = float(t)
428+
nc["time_bnds"][:, time_index] =
429+
time_index == 1 ? [zero(float(t)); float(t)] :
430+
[nc["time"][time_index - 1]; float(t)]
414431

415432
# FIXME: We are hardcoding p.start_date !
416433
# FIXME: We are rounding t
@@ -419,6 +436,9 @@ function write_field!(writer::NetCDFWriter, field, diagnostic, u, p, t)
419436
curr_date = start_date + Dates.Millisecond(round(1000 * float(t)))
420437
date_type = typeof(curr_date) # not necessarily a Dates.DateTime
421438
nc["date"][time_index] = curr_date
439+
nc["date_bnds"][:, time_index] =
440+
time_index == 1 ? [start_date; curr_date] :
441+
[date_type(nc["date"][time_index - 1]); curr_date]
422442
end
423443

424444
# TODO: It would be nice to find a cleaner way to do this

src/netcdf_writer_coordinates.jl

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,49 @@ function add_date_maybe!(nc::NCDatasets.NCDataset; kwargs...)
132132
dim.attrib[String(k)] = v
133133
end
134134
end
135+
136+
"""
137+
add_time_bounds_maybe!(nc::NCDatasets.NCDataset,
138+
float_type::Type{FT};
139+
kwargs...)
140+
141+
Add the `time_bnds` dimension (with infinite size) to the given NetCDF file if
142+
not already there. Optionally, add all the keyword arguments as attributes.
143+
144+
This function is meant to be called after `add_time_maybe!`.
145+
"""
146+
function add_time_bounds_maybe!(
147+
nc::NCDatasets.NCDataset,
148+
float_type::Type{FT};
149+
kwargs...,
150+
) where {FT}
151+
haskey(nc, "time_bnds") && return nothing
152+
!haskey(nc, "time") && error(
153+
"Time dimension does not exist. Call add_time_maybe! before calling this function",
154+
)
155+
!("nv" in NCDatasets.dimnames(nc)) && NCDatasets.defDim(nc, "nv", 2) # number of vertices
156+
dim = NCDatasets.defVar(nc, "time_bnds", FT, ("nv", "time"))
157+
for (k, v) in kwargs
158+
dim.attrib[String(k)] = v
159+
end
160+
return nothing
161+
end
162+
163+
"""
164+
add_date_bounds_maybe!(nc::NCDatasets.NCDataset; kwargs...)
165+
166+
Add the `date_bnds` dimension (with infinite size) to the given NetCDF file if
167+
not already there. Optionally, add all the keyword arguments as attributes.
168+
169+
This function is meant to be called after `add_time_maybe!`.
170+
"""
171+
function add_date_bounds_maybe!(nc::NCDatasets.NCDataset; kwargs...)
172+
haskey(nc, "date_bnds") && return nothing
173+
!haskey(nc, "date") && error(
174+
"Time dimension does not exist. Call add_time_maybe! before calling this function",
175+
)
176+
!("nv" in NCDatasets.dimnames(nc)) && NCDatasets.defDim(nc, "nv", 2) # number of vertices
177+
dim = NCDatasets.defVar(nc, "date_bnds", Float64, ("nv", "time"))
135178
for (k, v) in kwargs
136179
dim.attrib[String(k)] = v
137180
end

test/writers.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ end
107107
@test nc["lat"].attrib["standard_name"] == "latitude"
108108
@test nc["lat"].attrib["long_name"] == "Latitude"
109109
@test nc["lat"].attrib["axis"] == "Y"
110+
111+
# Test bounds
112+
@test nc["time_bnds"][:, 1] == [0.0; 10.0]
113+
@test nc["date_bnds"][:, 1] == [
114+
Dates.DateTime(1453, 5, 29)
115+
Dates.DateTime(1453, 5, 29) + Dates.Second(10.0)
116+
]
110117
end
111118

112119
# Disable vertical interpolation

0 commit comments

Comments
 (0)