Skip to content

Commit cf8adad

Browse files
implement defVar to copy variable from other dataset
1 parent 6544e9d commit cf8adad

File tree

3 files changed

+124
-3
lines changed

3 files changed

+124
-3
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ authors = ["Alexander Barth <[email protected]>"]
44
keywords = ["netcdf", "GRIB", "climate and forecast conventions", "oceanography", "meteorology", "climatology", "opendap"]
55
license = "MIT"
66
desc = "CommonDataModel is a module that defines types common to NetCDF and GRIB data"
7-
version = "0.2.3"
7+
version = "0.2.4"
88

99
[deps]
1010
CFTime = "179af706-886a-5703-950a-314cd64e0468"

src/variable.jl

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,118 @@ function variable(ds::AbstractDataset,variablename::SymbolOrString)
3030
error("no variable $variablename in $(path(ds)) (abstract method)")
3131
end
3232

33-
function defVar(ds::AbstractDataset,name::SymbolOrString,type,dimnames)
33+
function defVar(ds::AbstractDataset,name::SymbolOrString,type::DataType,
34+
dimnames)
3435
error("unimplemented for abstract type")
3536
end
3637

38+
39+
40+
41+
# data has the type e.g. Array{Union{Missing,Float64},3}
42+
function defVar(ds::AbstractDataset,
43+
name::SymbolOrString,
44+
data::AbstractArray{Union{Missing,T},N},
45+
dimnames;
46+
kwargs...) where T <: Union{Int8,UInt8,Int16,Int32,Int64,Float32,Float64} where N
47+
_defVar(ds::AbstractDataset,name,data,T,dimnames; kwargs...)
48+
end
49+
50+
# data has the type e.g. Vector{DateTime}, Array{Union{Missing,DateTime},3} or
51+
# Vector{DateTime360Day}
52+
# Data is always stored as Float64 in the NetCDF file
53+
function defVar(ds::AbstractDataset,
54+
name::SymbolOrString,
55+
data::AbstractArray{<:Union{Missing,T},N},
56+
dimnames;
57+
kwargs...) where T <: Union{DateTime,AbstractCFDateTime} where N
58+
_defVar(ds::AbstractDataset,name,data,Float64,dimnames; kwargs...)
59+
end
60+
61+
function defVar(ds::AbstractDataset,name::SymbolOrString,data,dimnames; kwargs...)
62+
# eltype of a String would be Char
63+
if data isa String
64+
nctype = String
65+
else
66+
nctype = eltype(data)
67+
end
68+
_defVar(ds::AbstractDataset,name,data,nctype,dimnames; kwargs...)
69+
end
70+
71+
function _defVar(ds::AbstractDataset,name::SymbolOrString,data,nctype,vardimnames; attrib = [], kwargs...)
72+
# define the dimensions if necessary
73+
for (i,dimname) in enumerate(vardimnames)
74+
if !(dimname in dimnames(ds))
75+
defDim(ds,dimname,size(data,i))
76+
elseif !(dimname in unlimited(ds.dim))
77+
dimlen = dim(ds,dimname)
78+
79+
if (dimlen != size(data,i))
80+
error("dimension $(dimname) is already defined with the " *
81+
"length $dimlen. It cannot be redefined with a length of $(size(data,i)).")
82+
end
83+
end
84+
end
85+
86+
T = eltype(data)
87+
attrib = collect(attrib)
88+
89+
if T <: Union{TimeType,Missing}
90+
dattrib = Dict(attrib)
91+
if !haskey(dattrib,"units")
92+
push!(attrib,"units" => CFTime.DEFAULT_TIME_UNITS)
93+
end
94+
if !haskey(dattrib,"calendar")
95+
# these dates cannot be converted to the standard calendar
96+
if T <: Union{DateTime360Day,Missing}
97+
push!(attrib,"calendar" => "360_day")
98+
elseif T <: Union{DateTimeNoLeap,Missing}
99+
push!(attrib,"calendar" => "365_day")
100+
elseif T <: Union{DateTimeAllLeap,Missing}
101+
push!(attrib,"calendar" => "366_day")
102+
end
103+
end
104+
end
105+
106+
v =
107+
if Missing <: T
108+
# make sure a fill value is set (it might be overwritten by kwargs...)
109+
defVar(ds,name,nctype,vardimnames;
110+
fillvalue = fillvalue(nctype),
111+
attrib = attrib,
112+
kwargs...)
113+
else
114+
defVar(ds,name,nctype,vardimnames;
115+
attrib = attrib,
116+
kwargs...)
117+
end
118+
119+
v[:] = data
120+
return v
121+
end
122+
123+
124+
function defVar(ds::AbstractDataset,name,data::T; kwargs...) where T <: Union{Number,String,Char}
125+
v = defVar(ds,name,T,(); kwargs...)
126+
v[:] = data
127+
return v
128+
end
129+
130+
"""
131+
v = CommonDataModel.defVar(ds::AbstractDataset,src::AbstractVariable)
132+
133+
Defines and return the variable in the data set `ds`
134+
copied from the variable `src`. The variable name, dimension name, attributes
135+
and data are copied from `src`.
136+
"""
137+
function defVar(ds::AbstractDataset,src::AbstractVariable)
138+
v = defVar(ds,name(src),
139+
Array(src),
140+
dimnames(src),
141+
attrib=attribs(src))
142+
return v
143+
end
144+
37145
"""
38146
ds = CommonDataModel.dataset(v::AbstractVariable)
39147

test/test_conversion.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,17 @@ dsnc = NCDatasets.Dataset(tmp_filename)
3535

3636

3737
close(dsnc)
38-
# close(ds)
38+
39+
40+
# copy individual variables
41+
tmp_filename = tempname()
42+
dsnc = NCDatasets.Dataset(tmp_filename,"c")
43+
gribv = ds["lon"]
44+
ncv = CDM.defVar(dsnc,gribv)
45+
@test CDM.name(ncv) == CDM.name(gribv)
46+
@test ncv[:] == gribv[:]
47+
@test CDM.attrib(ncv,"units") == CDM.attrib(gribv,"units")
48+
@test collect(CDM.dimnames(ncv)) == collect(CDM.dimnames(gribv))
49+
close(dsnc)
50+
51+
close(ds)

0 commit comments

Comments
 (0)