Skip to content

Commit 7a9347b

Browse files
authored
feat: times and meta functions, and return named tuple of variables (#6)
* feat: add times and meta functions * feat: return named tuple of variables instead of vector of variables
1 parent 3a8ccca commit 7a9347b

5 files changed

Lines changed: 56 additions & 34 deletions

File tree

ext/DimensionalDataExt.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ function DimensionalData.DimArray(v::HAPIVariable; add_unit=true)
2727
DimArray(values, dims(v); name=Symbol(name(v)), metadata)
2828
end
2929

30-
DimStack(vs::AbstractArray{<:HAPIVariable}) = DimStack(DimArray.(vs)...)
30+
DimStack(vs::HAPIVariables) = DimStack(DimArray.(vs)...)
3131

3232
end

src/HAPIClient.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ using Unitful
99
using SpaceDataModel: AbstractDataVariable, parse_datetime
1010
import Unitful: unit
1111
using SpaceDataModel: name, units, meta
12+
import SpaceDataModel: times
1213

13-
export hapi, get_data
14+
export hapi, get_data, meta, times
1415
export HAPIVariable, HAPIVariables
1516

1617
include("server.jl")
@@ -24,6 +25,7 @@ hapi() = get_servers()
2425
hapi(server) = get_catalog(server)
2526
hapi(server, dataset) = get_parameters(server, dataset)
2627
hapi(server, dataset, parameters) = get_parameters(server, dataset, parameters)
28+
hapi(server, dataset, tmin, tmax; kwargs...) = get_data(server, dataset, "", tmin, tmax; kwargs...)
2729
hapi(server, dataset, parameters, tmin, tmax; kwargs...) = get_data(server, dataset, parameters, tmin, tmax; kwargs...)
2830

2931
function __init__()

src/data.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
21
"""
32
get_data(server, dataset, parameters, tmin, tmax; format="csv")
43
54
Get data and metadata from a HAPI `server` for a given `dataset` and `parameters` within a time range `[tmin, tmax]`.
65
76
Supported data formats: "csv", "binary", "json".
87
"""
9-
function get_data(server, dataset, parameters, tmin, tmax; format=format(server))
8+
function get_data(server, dataset, parameters, tmin, tmax; format = format(server))
109

1110
# Validate time format
1211
tmin = HAPIDateTime(tmin)
@@ -25,7 +24,7 @@ function get_data(server, dataset, parameters, tmin, tmax; format=format(server)
2524
response = HTTP.get(uri)
2625

2726
data = if format == "csv"
28-
CSV.File(response.body; header=false, dateformat=DEFAULT_DATE_FORMAT)
27+
CSV.File(response.body; header = false, dateformat = DEFAULT_DATE_FORMAT)
2928
elseif format == "json"
3029
JSON.parse(String(response.body))
3130
elseif format == "binary"
@@ -35,7 +34,15 @@ function get_data(server, dataset, parameters, tmin, tmax; format=format(server)
3534
end
3635
meta = get_parameters(server, dataset, parameters)
3736
meta["uri"] = uri
38-
return HAPIVariables(data, meta)
37+
params = meta["parameters"]
38+
n = length(params) - 1
39+
return n == 1 ? _merge_meta!(HAPIVariable(data, params, 1), meta) : HAPIVariables(data, params, meta)
40+
end
41+
42+
_merge_meta!(x, meta) = begin
43+
merge!(x.meta, meta)
44+
delete!(x.meta, "parameters")
45+
return x
3946
end
4047

4148
"""
@@ -55,4 +62,4 @@ function get_data(path, tmin, tmax; kwargs...)
5562
end
5663

5764
get_data(server, dataset, parameters, trange; kwargs...) = get_data(server, dataset, parameters, first(trange), last(trange); kwargs...)
58-
get_data(path, trange; kwargs...) = get_data(path, first(trange), last(trange); kwargs...)
65+
get_data(path, trange; kwargs...) = get_data(path, first(trange), last(trange); kwargs...)

src/types.jl

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,65 @@
1-
struct HAPIVariable{T,N,A<:AbstractArray{T,N},Tt<:AbstractVector} <: AbstractDataVariable{T,N}
1+
struct HAPIVariable{T, N, A <: AbstractArray{T, N}, Tt <: AbstractVector} <: AbstractDataVariable{T, N}
22
data::A
33
time::Tt
44
meta::Dict
55
end
66

7-
function HAPIVariables(data, meta)
8-
params = meta["parameters"]
7+
"""
8+
A thin wrapper over NamedTuple for HAPI variables that shares the same time axis.
9+
"""
10+
struct HAPIVariables{NT <: NamedTuple, D <: Dict}
11+
nt::NT
12+
meta::D
13+
end
14+
15+
@inline Base.parent(x::HAPIVariables) = getfield(x, :nt)
16+
times(x::HAPIVariables) = times(first(parent(x)))
17+
Base.propertynames(x::HAPIVariables) = propertynames(parent(x))
18+
Base.getproperty(x::HAPIVariables, s::Symbol) = getproperty(parent(x), s)
19+
Base.length(x::HAPIVariables) = length(parent(x))
20+
Base.iterate(x::HAPIVariables, args...) = iterate(parent(x), args...)
21+
Base.getindex(x::HAPIVariables, i) = getindex(parent(x), i)
22+
23+
function HAPIVariables(data, params, meta)
924
n = length(params) - 1
10-
vars = [HAPIVariable(data, meta, i) for i in 1:n]
11-
return n == 1 ? first(vars) : vars
25+
names = Tuple(Symbol(params[i + 1]["name"]) for i in 1:n)
26+
values = (HAPIVariable(data, params, i) for i in 1:n)
27+
return HAPIVariables(NamedTuple{names}(values), meta)
1228
end
1329

1430
colsize(param) = prod(get(param, "size", 1))
1531

1632
"""
17-
HAPIVariable(data, meta, i)
33+
HAPIVariable(data, params, i)
1834
19-
Construct a `HAPIVariable` object from CSV.File `data` and `meta` at index `i`.
35+
Construct a `HAPIVariable` object from CSV.File `data` and `params` at index `i`.
2036
"""
21-
function HAPIVariable(data::CSV.File, meta, i::Integer; merge_metadata=true, stackcolumns=true)
37+
function HAPIVariable(data::CSV.File, params, i::Integer)
2238
time = Tables.getcolumn(data, 1)
23-
params = meta["parameters"]
24-
param = params[i+1]
39+
param = params[i + 1]
2540
size = colsize(param)
2641
coloffset = mapreduce(colsize, +, @view(params[1:i])) + 1
2742

2843
values = if size == 1
2944
Tables.getcolumn(data, coloffset)
30-
elseif stackcolumns
31-
stack(coloffset:coloffset+size-1) do i
45+
else
46+
stack(coloffset:(coloffset + size - 1)) do i
3247
Tables.getcolumn(data, i)
3348
end
34-
else
35-
cols = coloffset:(coloffset+size-1)
36-
map(row -> getindex.(Ref(row), cols), data)
3749
end
38-
final_meta = merge_metadata ? delete!(merge(meta, param), "parameters") : param
39-
HAPIVariable(values, time, final_meta)
50+
return HAPIVariable(values, time, param)
4051
end
4152

4253
"""
43-
HAPIVariable(data, meta, i)
54+
HAPIVariable(data, params, i)
4455
45-
Construct a `HAPIVariable` object from a JSON-parsed `data` and `meta` at index `i`.
56+
Construct a `HAPIVariable` object from a JSON-parsed `data` and `params` at index `i`.
4657
"""
47-
function HAPIVariable(data, meta, i::Integer; merge_metadata=true)
58+
function HAPIVariable(data, params, i::Integer)
4859
time = @. DateTime(getindex(data, 1), DEFAULT_DATE_FORMAT)
49-
param = meta["parameters"][i+1]
60+
param = params[i + 1]
5061
values = getindex.(data, i + 1)
51-
final_meta = merge_metadata ? delete!(merge(meta, param), "parameters") : param
52-
HAPIVariable(values, time, final_meta)
62+
return HAPIVariable(values, time, param)
5363
end
5464

5565
"""
@@ -59,10 +69,10 @@ Construct a `HAPIVariable` object from a JSON-parsed Dict `d` (containing parame
5969
"""
6070
function HAPIVariable(d::Dict, i::Integer)
6171
data = d["data"]
62-
param = d["parameters"][i+1]
72+
param = d["parameters"][i + 1]
6373
time = @. DateTime(getindex(data, 1), DEFAULT_DATE_FORMAT)
6474
values = getindex.(data, i + 1)
65-
HAPIVariable(values, time, param)
75+
return HAPIVariable(values, time, param)
6676
end
6777

6878
HAPIVariable(d::Dict, meta, i::Integer) = HAPIVariable(d, i)
@@ -75,8 +85,8 @@ function hapi_uparse(u)
7585
isnothing(u) && return 1
7686
u == "UTC" && return 1
7787
u == "degrees" && return u"°"
78-
uparse(u)
88+
return uparse(u)
7989
end
8090
hapi_uparse(units::AbstractArray) = hapi_uparse.(units)
8191

82-
Unitful.unit(var::HAPIVariable) = hapi_uparse.(units(var))
92+
Unitful.unit(var::HAPIVariable) = hapi_uparse.(units(var))

test/data.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
@testitem "get_data" begin
44
for fmt in ["csv", "json"]
55
data = get_data("CDAWeb/AC_H0_MFI/Magnitude,BGSEc", ["2001-01-01T05", "2001-01-01T06"]; format = fmt)
6+
@test data.Magnitude == data[1]
67
@test length(data) == 2
8+
@test length(times(data)) == 225
9+
@test meta(data[1])["name"] == "Magnitude"
710
end
811
end
912
@testitem "TestData2.0" begin

0 commit comments

Comments
 (0)