Skip to content

Commit 2851867

Browse files
Merge branch 'main' of github.com:JuliaGeo/AbstractDatasets.jl
2 parents b9cd38e + 70bd0af commit 2851867

File tree

10 files changed

+85
-19
lines changed

10 files changed

+85
-19
lines changed

docs/src/index.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11

22
## Abstract types
33

4-
Overview of methods
4+
In order to implement a new dataset based `CommonDataModel.jl`
5+
one has to create two types derived from:
6+
1 .`AbstractVariable`: a variable with named dimension and metadata
7+
2. `AbstractDataset`: a collection of variable with named dimension, metadata and sub-groups. The sub-groups are also `AbstractDataset`.
8+
9+
10+
Overview of methods:
511

612
| | get names | get value | write / set value |
713
|------------|---------------|------------|-------------------|

src/CommonDataModel.jl

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,23 @@ NetCDF or GRIB file)
1414
1515
A data set `ds` of a type derived from `AbstractDataset` should implemented at minimum:
1616
17-
* `Base.key(ds)`: return a list of variable names a strings
18-
* `Base.getindex(ds,varname::String)`: return an array-like data structure (derived from `AbstractVariable`) of the variables corresponding to `varname`. This array-like data structure should follow the CF semantics.
19-
* `attribnames(ds)`: should be an iterable with all attribute names
20-
* `attrib(ds,name)`: attribute value corresponding to name
17+
* `Base.key(ds)`: return a list of variable names as strings
18+
* `variable(ds,varname::String)`: return an array-like data structure (derived from `AbstractVariable`) of the variables corresponding to `varname`. This array-like data structure should follow the CF semantics.
2119
* `dimnames(ds)`: should be an iterable with all dimension names in the data set `ds`
2220
* `dim(ds,name)`: dimension value corresponding to name
2321
22+
Optionally a data set can have attributes and groups:
23+
24+
* `attribnames(ds)`: should be an iterable with all attribute names
25+
* `attrib(ds,name)`: attribute value corresponding to name
26+
* `groupnames(ds)`: should be an iterable with all group names
27+
* `group(ds,name)`: group corresponding to the name
28+
29+
For a writable-dataset, one should also implement:
30+
* `defDim`: define a dimension
31+
* `defAttrib`: define a attribute
32+
* `defVar`: define a variable
33+
* `defGroup`: define a group
2434
"""
2535
abstract type AbstractDataset
2636
end
@@ -29,9 +39,21 @@ end
2939
"""
3040
`AbstractVariable{T,N}` is a subclass of `AbstractArray{T, N}`. A variable `v` of a type derived from `AbstractVariable` should implement:
3141
32-
* `v.attrib`: should be a Dict-like data structure with all variable attribute names as keys and the corresponding value
33-
* `name(v)`: should be the name of variable within the dataset
42+
* `name(v)`: should be the name of variable within the data set
3443
* `dimnames(v)`: should be a iterable data structure with all dimension names of the variable `v`
44+
* `dataset(v)`: the parent dataset containing `v`
45+
* `Base.size(v)`: the size of the variable
46+
* `Base.getindex(v,indices...)`: get the data of `v` at the provided indices
47+
48+
Optionally a variable can have attributes:
49+
50+
* `attribnames(v)`: should be an iterable with all attribute names
51+
* `attrib(v,name)`: attribute value corresponding to name
52+
53+
For a writable-dataset, one should also implement:
54+
* `defAttrib`: define a attribute
55+
* `Base.setindex(v,data,indices...)`: set the data in `v` at the provided indices
56+
3557
"""
3658
abstract type AbstractVariable{T,N} <: AbstractArray{T, N}
3759
end
@@ -44,3 +66,7 @@ include("attribute.jl")
4466
include("dimension.jl")
4567

4668
end # module CommonDataModel
69+
70+
# LocalWords: AbstractDataset NetCDF GRIB ds AbstractVariable
71+
# LocalWords: varname dimnames iterable attribnames attrib dataset
72+
# LocalWords: groupnames AbstractArray

src/attribute.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ function attrib(ds::Union{AbstractDataset,AbstractVariable},attribname::Abstract
1515
error("no attributes $attribname in $(path(ds))")
1616
end
1717

18+
"""
19+
CommonDatamodel.defAttrib(ds::Union{AbstractDataset,AbstractVariable},name::AbstractString,data)
20+
21+
Create an attribute with the name `attrib` in the data set or variable `ds`.
22+
"""
1823
function defAttrib(ds::AbstractDataset,name::AbstractString,data)
1924
error("unimplemnted for abstract type")
2025
end

src/cfvariable.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Return a tuple of integers with the size of the variable `var`.
2222
Base.size(v::CFVariable) = size(v.var)
2323

2424
name(v::CFVariable) = name(v.var)
25+
dataset(v::CFVariable) = dataset(v.var)
26+
2527

2628
attribnames(v::CFVariable) = keys(v.attrib)
2729
attrib(v::CFVariable,name::AbstractString) = v.attrib[name]

src/dataset.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ function group(ds::AbstractDataset,groupname::AbstractString)
3535
error("no group $groupname in $(path(ds))")
3636
end
3737

38+
"""
39+
group = CommonDatamodel.defGroup(ds::AbstractDataset,name::AbstractString)
40+
41+
Create an empty sub-group with the name `name` in the data set `ds`.
42+
The `group` is a sub-type of `AbstractDataset`.
43+
"""
3844
function defGroup(ds::AbstractDataset,name::AbstractString)
3945
error("unimplemented for abstract type")
4046
end
@@ -110,6 +116,9 @@ function Base.show(io::IO,ds::AbstractDataset)
110116
end
111117

112118

119+
Base.getindex(ds::AbstractDataset,varname) = cfvariable(ds,varname)
120+
121+
113122
for (item_color,default) in (
114123
(:section_color, :red),
115124
(:attribute_color, :cyan),

src/dimension.jl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,22 @@ dimnames(ds::Union{AbstractDataset,AbstractVariable}) = ()
1313
Return the length of the dimension `dimname` in the data set `ds`.
1414
"""
1515
function dim(v::AbstractVariable,dimname::AbstractString)
16-
error("no dimension $dimname in $(name(v))")
16+
if !(dimname in dimnames(v))
17+
error("$dimname is not among the dimensions of $(name(v))")
18+
end
19+
return dim(dataset(v),dimname)
1720
end
1821

1922
function dim(ds::AbstractDataset,dimname::AbstractString)
2023
error("no dimension $dimname in $(path(ds))")
2124
end
2225

26+
"""
27+
CommonDatamodel.defDim(ds::AbstractDataset,name::AbstractString,len)
28+
29+
Create dimension with the name `name` in the data set `ds` with the length `len`.
30+
`len` can be `Inf` for unlimited dimensions.
31+
"""
2332
function defDim(ds::AbstractDataset,name::AbstractString,len)
2433
error("unimplemnted for abstract type")
2534
end

src/variable.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
"""
2-
CommonDatamodel.name(v::AbstractVariable)
2+
CommonDataModel.name(v::AbstractVariable)
33
44
Return the name of the variable `v` as a string.
55
"""
66
name(v::AbstractVariable) = ""
77

88

99
"""
10-
CommonDatamodel.dimnames(v::AbstractVariable)
10+
CommonDataModel.dimnames(v::AbstractVariable)
1111
1212
Return an iterable of the dimension names of the variable `v`.
1313
"""
1414
dimnames(av::AbstractVariable) = ()
1515

1616

1717
"""
18-
CommonDatamodel.varnames(ds::AbstractDataset)
18+
CommonDataModel.varnames(ds::AbstractDataset)
1919
2020
Return an iterable of all the variable name.
2121
"""
2222
varnames(ds::AbstractDataset) = ()
2323

2424
"""
25-
CommonDatamodel.variable(ds::AbstractDataset,variablename::AbstractString)
25+
CommonDataModel.variable(ds::AbstractDataset,variablename::AbstractString)
2626
2727
Return the variable with the name `variablename` from the data set `ds`.
2828
"""
@@ -31,10 +31,17 @@ function variable(ds::AbstractDataset,variablename::AbstractString)
3131
end
3232

3333
function defVar(ds::AbstractDataset,name::AbstractString,type,dimnames)
34-
error("unimplemnted for abstract type")
34+
error("unimplemented for abstract type")
3535
end
3636

37+
"""
38+
ds = CommonDataModel.dataset(v::AbstractVariable)
3739
40+
Return the data set `ds` to which a the variable `v` belongs to.
41+
"""
42+
function dataset(v::AbstractVariable)
43+
error("unimplemented for abstract type")
44+
end
3845

3946

4047
function Base.show(io::IO,v::AbstractVariable)

test/memory_dataset.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,13 @@ end
2020

2121
Base.getindex(v::MemoryVariable,ij...) = v.data[ij...]
2222
Base.setindex!(v::MemoryVariable,data,ij...) = v.data[ij...] = data
23+
Base.size(v::MemoryVariable) = size(v.data)
2324
CDM.name(v::MemoryVariable) = v.name
2425
CDM.dimnames(v::MemoryVariable) = v.dimnames
25-
Base.size(v::MemoryVariable) = size(v.data)
26-
CDM.dim(v::MemoryVariable,name::AbstractString) = v.parent_dataset.dim[name]
26+
CDM.dataset(v::MemoryVariable) = v.parent_dataset
2727

2828
Base.keys(md::MemoryDataset) = keys(md.variables)
2929
CDM.variable(md::MemoryDataset,varname::AbstractString) = md.variables[varname]
30-
Base.getindex(md::MemoryDataset,varname::AbstractString) = CDM.cfvariable(md,varname)
3130
CDM.dimnames(md::MemoryDataset) = keys(md.dim)
3231
CDM.dim(md::MemoryDataset,name::AbstractString) = md.dim[name]
3332
CDM.attribnames(md::Union{MemoryDataset,MemoryVariable}) = keys(md.attrib)

test/test_conversion.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import NCDatasets
22
import GRIBDatasets
33
import CommonDataModel as CDM
44
using Test
5+
using DataStructures
56

67
datadir = joinpath(dirname(pathof(GRIBDatasets)),"..","test","sample-data")
78
filename = joinpath(datadir,"era5-levels-members.grib")
@@ -28,9 +29,9 @@ NCDatasets.write(tmp_filename,ds)
2829
dsnc = NCDatasets.Dataset(tmp_filename)
2930
@test ds["number"][:] == dsnc["number"][:]
3031

31-
@test CDM.dims(ds) == CDM.dims(dsnc)
32-
@test CDM.attribs(ds) == CDM.attribs(dsnc)
33-
@test CDM.groups(ds) == CDM.groups(dsnc)
32+
@test OrderedDict(CDM.dims(ds)) == OrderedDict(CDM.dims(dsnc))
33+
@test OrderedDict(CDM.attribs(ds)) == OrderedDict(CDM.attribs(dsnc))
34+
@test OrderedDict(CDM.groups(ds)) == OrderedDict(CDM.groups(dsnc))
3435

3536

3637
close(dsnc)

test/test_scaling.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,6 @@ time_origin = DateTime(2000,1,1)
122122
md["data"][1,2] = DateTime(2000,2,1)
123123
@test md["data"].var[1,2] == Dates.value(md["data"][1,2] - time_origin) ÷ (24*60*60*1000)
124124

125+
126+
@test CDM.dataset(md["data"]) == md
125127
close(md)

0 commit comments

Comments
 (0)