diff --git a/Project.toml b/Project.toml index c03821b9..169a855a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "InferenceObjects" uuid = "b5cf5a8d-e756-4ee3-b014-01d49d192c00" authors = ["Seth Axen and contributors"] -version = "0.4.15" +version = "0.4.16" [deps] ANSIColoredPrinters = "a4c015fc-c6ff-483c-b24f-f7ea428134e9" @@ -25,7 +25,7 @@ InferenceObjectsPosteriorStatsExt = ["PosteriorStats", "StatsBase"] ANSIColoredPrinters = "0.0.1" ArviZExampleData = "0.3" Dates = "1" -DimensionalData = "0.27, 0.28, 0.29" +DimensionalData = "0.27, 0.28, 0.29, 0.30" EvoTrees = "0.16" MCMCDiagnosticTools = "0.3.4" MLJBase = "1" diff --git a/ext/InferenceObjectsMCMCDiagnosticToolsExt/InferenceObjectsMCMCDiagnosticToolsExt.jl b/ext/InferenceObjectsMCMCDiagnosticToolsExt/InferenceObjectsMCMCDiagnosticToolsExt.jl index d8ed3b55..68164e4c 100644 --- a/ext/InferenceObjectsMCMCDiagnosticToolsExt/InferenceObjectsMCMCDiagnosticToolsExt.jl +++ b/ext/InferenceObjectsMCMCDiagnosticToolsExt/InferenceObjectsMCMCDiagnosticToolsExt.jl @@ -1,7 +1,7 @@ module InferenceObjectsMCMCDiagnosticToolsExt using Base: @doc -using DimensionalData: DimensionalData, Dimensions, LookupArrays +using DimensionalData: DimensionalData, Dimensions using InferenceObjects: InferenceObjects, Random using MCMCDiagnosticTools: MCMCDiagnosticTools diff --git a/ext/InferenceObjectsNCDatasetsExt/InferenceObjectsNCDatasetsExt.jl b/ext/InferenceObjectsNCDatasetsExt/InferenceObjectsNCDatasetsExt.jl index 4edbeb68..13e17283 100644 --- a/ext/InferenceObjectsNCDatasetsExt/InferenceObjectsNCDatasetsExt.jl +++ b/ext/InferenceObjectsNCDatasetsExt/InferenceObjectsNCDatasetsExt.jl @@ -1,6 +1,6 @@ module InferenceObjectsNCDatasetsExt -using DimensionalData: DimensionalData, Dimensions, LookupArrays +using DimensionalData: DimensionalData, Dimensions, Lookups using NCDatasets: NCDatasets using InferenceObjects @@ -20,7 +20,7 @@ function _from_netcdf(ds, load_mode) index = collect(group[dim_name]) if index == eachindex(index) # discard the index if it is just the default - index = LookupArrays.NoLookup() + index = Lookups.NoLookup() end return Symbol(dim_name) => Dimensions.Dim{Symbol(dim_name)}(index) end... @@ -36,7 +36,7 @@ function _from_netcdf(ds, load_mode) else var.attrib end - metadata = isempty(attrib) ? LookupArrays.NoMetadata() : attrib + metadata = isempty(attrib) ? Lookups.NoMetadata() : attrib da = DimensionalData.DimArray(vals, dims; name, metadata) return name => da end... @@ -89,7 +89,7 @@ function InferenceObjects.to_netcdf( for dim in Dimensions.dims(group_data) dim_name = String(Dimensions.name(dim)) NCDatasets.defDim(group_ds, dim_name, length(dim)) - index = LookupArrays.index(group_data, dim) + index = parent(Dimensions.lookup(group_data, dim)) var = NCDatasets.defVar(group_ds, dim_name, eltype(index), (dim_name,)) copyto!(var, index) end diff --git a/ext/InferenceObjectsPosteriorStatsExt/InferenceObjectsPosteriorStatsExt.jl b/ext/InferenceObjectsPosteriorStatsExt/InferenceObjectsPosteriorStatsExt.jl index 320dcaa0..ceef99f1 100644 --- a/ext/InferenceObjectsPosteriorStatsExt/InferenceObjectsPosteriorStatsExt.jl +++ b/ext/InferenceObjectsPosteriorStatsExt/InferenceObjectsPosteriorStatsExt.jl @@ -1,7 +1,7 @@ module InferenceObjectsPosteriorStatsExt using Base: @doc -using DimensionalData: DimensionalData, Dimensions, LookupArrays +using DimensionalData: DimensionalData, Dimensions using InferenceObjects: InferenceObjects using PosteriorStats: PosteriorStats using StatsBase: StatsBase diff --git a/src/InferenceObjects.jl b/src/InferenceObjects.jl index 6a10d4f0..58aaacde 100644 --- a/src/InferenceObjects.jl +++ b/src/InferenceObjects.jl @@ -2,7 +2,7 @@ module InferenceObjects using ANSIColoredPrinters: ANSIColoredPrinters using Dates: Dates -using DimensionalData: DimensionalData, Dimensions, LookupArrays +using DimensionalData: DimensionalData, Dimensions, Lookups using Random: Random using Tables: Tables diff --git a/src/dataset.jl b/src/dataset.jl index d27f284d..a786f4d9 100644 --- a/src/dataset.jl +++ b/src/dataset.jl @@ -20,18 +20,26 @@ that implements the same interface as `DimensionalData.DimStack` and has identic In most cases, use [`convert_to_dataset`](@ref) to create a `Dataset` instead of directly using a constructor. """ -struct Dataset{K,T,N,L,D<:DimensionalData.AbstractDimStack{K,T,N,L}} <: - DimensionalData.AbstractDimStack{K,T,N,L} - data::D -end +Dataset +@static if pkgversion(DimensionalData) ≥ v"0.30.0" + struct Dataset{K,T,N,L,D,Data<:DimensionalData.AbstractDimStack{K,T,N,L,D}} <: + DimensionalData.AbstractDimStack{K,T,N,L,D} + data::Data + end +else # DimensionalData < 0.30 + struct Dataset{K,T,N,L,Data<:DimensionalData.AbstractDimStack{K,T,N,L}} <: + DimensionalData.AbstractDimStack{K,T,N,L} + data::Data + end -function Dataset{K,T,N}( - data::L, dims, refdims, layerdims, metadata, layermetadata -) where {K,T,N,L} - data = DimensionalData.DimStack{K,T,N}( - data, dims, refdims, layerdims, metadata, layermetadata - ) - return Dataset{K,T,N,L,typeof(data)}(data) + function Dataset{K,T,N}( + data::L, dims, refdims, layerdims, metadata, layermetadata + ) where {K,T,N,L} + data = DimensionalData.DimStack{K,T,N}( + data, dims, refdims, layerdims, metadata, layermetadata + ) + return Dataset{K,T,N,L,typeof(data)}(data) + end end Dataset(args...; kwargs...) = Dataset(DimensionalData.DimStack(args...; kwargs...)) Dataset(data::Dataset) = data @@ -123,9 +131,6 @@ end DimensionalData.modify(f, s::Dataset) = Dataset(DimensionalData.modify(f, parent(s))) -# Warning: this is not an API function and probably should be implemented abstractly upstream -DimensionalData.show_after(io, mime, ::Dataset) = nothing - attributes(data::DimensionalData.AbstractDimStack) = DimensionalData.metadata(data) Base.convert(T::Type{<:DimensionalData.DimStack}, data::Dataset) = convert(T, parent(data)) diff --git a/src/dimensions.jl b/src/dimensions.jl index e99a6338..b306dd3d 100644 --- a/src/dimensions.jl +++ b/src/dimensions.jl @@ -2,13 +2,13 @@ has_all_sample_dims(dims) = all(Dimensions.hasdim(dims, DEFAULT_SAMPLE_DIMS)) # Like Dimensions.name2dim but doesn't allow users to inject their own dimensions using # Dimensions.@dim. See https://github.com/arviz-devs/InferenceObjects.jl/issues/37 -_name2dim(d::Symbol) = Dimensions.Dim{d}(LookupArrays.NoLookup()) +_name2dim(d::Symbol) = Dimensions.Dim{d}(Lookups.NoLookup()) _name2dim(d::Tuple) = map(_name2dim, d) _name2dim(d) = d # make sure dim has a lookup value accessible with `val` _valdim(d) = d -_valdim(d::Type{<:Dimensions.Dimension}) = d(LookupArrays.NoLookup()) +_valdim(d::Type{<:Dimensions.Dimension}) = d(Lookups.NoLookup()) """ as_dimension(dim, coords, axis) -> DimensionsionalData.Dimension @@ -31,8 +31,8 @@ Convert `dim`, `coords`, and `axis` to a `Dimension` object. """ function as_dimension(dim, coords, axis) cdim = _valdim(_name2dim(dim)) - val = LookupArrays.val(cdim) - inds = val isa Union{Colon,LookupArrays.NoLookup} ? axis : val + val = Lookups.val(cdim) + inds = val isa Union{Colon,Lookups.NoLookup} ? axis : val coords_inds = get(coords, Dimensions.name(cdim), inds) return Dimensions.rebuild(cdim, coords_inds) end @@ -79,7 +79,7 @@ function generate_dims(array, name; dims=(), coords=(;), default_dims=()) end dims_all = (default_dims..., dims_named...) # default to the axes if no coords are provided - axes_all = map(_ -> LookupArrays.NoLookup(), dims_all) + axes_all = map(_ -> Lookups.NoLookup(), dims_all) T = NTuple{ndims(array),Dimensions.Dimension} dims_with_coords = as_dimension.(dims_all, Ref(coords), axes_all)::T return Dimensions.format(dims_with_coords, array)::T @@ -107,7 +107,7 @@ function array_to_dimarray(array::DimensionalData.AbstractDimArray, name; kwargs end """ - AsSlice{T<:LookupArrays.Selector} <: LookupArrays.Selector{T} + AsSlice{T<:Lookups.Selector} <: Lookups.Selector{T} AsSlice(selector) @@ -115,12 +115,12 @@ Selector that ensures selected indices are arrays so that slicing occurs. This is useful to ensure that selecting a single index still returns an array. """ -struct AsSlice{T<:LookupArrays.Selector} <: LookupArrays.Selector{T} +struct AsSlice{T<:Lookups.Selector} <: Lookups.Selector{T} val::T end -function LookupArrays.selectindices(l::LookupArrays.LookupArray, sel::AsSlice; kw...) - i = LookupArrays.selectindices(l, LookupArrays.val(sel); kw...) +function Lookups.selectindices(l::Lookups.LookupArray, sel::AsSlice; kw...) + i = Lookups.selectindices(l, Lookups.val(sel); kw...) inds = i isa AbstractVector ? i : [i] return inds end @@ -132,4 +132,4 @@ Convert `index` to a collection of indices or a selector representing such a col """ index_to_indices(i) = i index_to_indices(i::Int) = [i] -index_to_indices(sel::LookupArrays.Selector) = AsSlice(sel) +index_to_indices(sel::Lookups.Selector) = AsSlice(sel) diff --git a/src/inference_data.jl b/src/inference_data.jl index 32f44dbc..839c63cd 100644 --- a/src/inference_data.jl +++ b/src/inference_data.jl @@ -320,6 +320,7 @@ julia> idata_cat1.posterior ├────────────────────────────────────────────────── metadata ┤ Dict{String, Any} with 1 entry: "created_at" => "2025-07-25T10:11:18.92" +└────────────────────────────────────────────────────────────┘ ``` Alternatively, we can concatenate along a new `run` dimension, which will be created. @@ -342,6 +343,7 @@ julia> idata_cat2.posterior ├───────────────────────────────────────────────────────── metadata ┤ Dict{String, Any} with 1 entry: "created_at" => "2025-07-25T10:11:18.92" +└───────────────────────────────────────────────────────────────────┘ ``` We can also concatenate only a subset of groups and merge the rest, which is useful when @@ -374,6 +376,7 @@ julia> idata_cat3.posterior ├───────────────────────────────────────────────────────── metadata ┤ Dict{String, Any} with 1 entry: "created_at" => "2025-07-25T10:11:18.92" +└───────────────────────────────────────────────────────────────────┘ julia> idata_cat3.observed_data ┌ 10-element Dataset ┐ @@ -384,6 +387,7 @@ julia> idata_cat3.observed_data ├────────────────────────────────────────────┴ metadata ┐ Dict{String, Any} with 1 entry: "created_at" => "2025-07-25T10:11:18.951" +└───────────────────────────────────────────────────────┘ ``` """ function Base.cat(data::InferenceData, others::InferenceData...; groups=keys(data), dims) diff --git a/test/dataset.jl b/test/dataset.jl index f468d296..1d155335 100644 --- a/test/dataset.jl +++ b/test/dataset.jl @@ -1,4 +1,5 @@ using InferenceObjects, DimensionalData, Test +using DimensionalData: Lookups @testset "dataset" begin @testset "Dataset" begin @@ -118,9 +119,9 @@ using InferenceObjects, DimensionalData, Test end @testset "DimensionalData.set" begin - ds2 = DimensionalData.set(ds; ydim1=LookupArrays.Sampled([-2, 2])) + ds2 = DimensionalData.set(ds, :ydim1 => Lookups.Sampled([-2, 2])) @test ds2 isa Dataset - @test DimensionalData.lookup(ds2, :ydim1) == [-2, 2] + @test parent(DimensionalData.lookup(ds2, :ydim1)) == [-2, 2] @test DimensionalData.data(ds2) == DimensionalData.data(ds) end end diff --git a/test/dimensions.jl b/test/dimensions.jl index 602441f5..d148a08b 100644 --- a/test/dimensions.jl +++ b/test/dimensions.jl @@ -1,5 +1,5 @@ using InferenceObjects, DimensionalData, OffsetArrays, Test -using DimensionalData.LookupArrays +using DimensionalData.Lookups Dimensions.@dim foo "foo" @@ -69,24 +69,27 @@ Dimensions.@dim foo "foo" ) @test gdims isa NTuple{4,Dim} @test Dimensions.name(gdims) === (:x_dim_1, :x_dim_2, :x_dim_3, :x_dim_4) - @test Dimensions.index(gdims) == (11:20, 0:3, -1:0, 2:4) - @test Dimensions.val.(Dimensions.dims(gdims)) isa NTuple{4,LookupArrays.NoLookup} + glooks = Dimensions.lookup(gdims) + @test glooks isa NTuple{4,NoLookup} + @test parent.(glooks) == (11:20, 0:3, -1:0, 2:4) gdims = @inferred NTuple{4,Dimensions.Dimension} InferenceObjects.generate_dims( x, :y; dims=(:a, :b) ) @test gdims isa NTuple{4,Dim} @test Dimensions.name(gdims) === (:a, :b, :y_dim_3, :y_dim_4) - @test Dimensions.index(gdims) == (11:20, 0:3, -1:0, 2:4) - @test Dimensions.val.(Dimensions.dims(gdims)) isa NTuple{4,LookupArrays.NoLookup} + glooks = Dimensions.lookup(gdims) + @test glooks isa NTuple{4,NoLookup} + @test parent.(glooks) == (11:20, 0:3, -1:0, 2:4) gdims = @inferred NTuple{4,Dimensions.Dimension} InferenceObjects.generate_dims( x, :z; dims=(:c, :d), default_dims=(:draw, :chain) ) @test gdims isa NTuple{4,Dim} @test Dimensions.name(gdims) === (:draw, :chain, :c, :d) - @test Dimensions.index(gdims) == (11:20, 0:3, -1:0, 2:4) - @test Dimensions.val.(Dimensions.dims(gdims)) isa NTuple{4,LookupArrays.NoLookup} + glooks = Dimensions.lookup(gdims) + @test glooks isa NTuple{4,NoLookup} + @test parent.(glooks) == (11:20, 0:3, -1:0, 2:4) x = randn(2, 3) InferenceObjects.generate_dims(x, :x; dims=(:a, :b)) @@ -109,7 +112,7 @@ Dimensions.@dim foo "foo" gdims = Dimensions.dims(da) @test gdims isa NTuple{4,Dim} @test Dimensions.name(gdims) === (:x_dim_1, :x_dim_2, :x_dim_3, :x_dim_4) - @test Dimensions.index(gdims) == (11:20, 0:3, -1:0, 2:4) + @test parent.(Dimensions.lookup(gdims)) == (11:20, 0:3, -1:0, 2:4) da = @inferred DimArray InferenceObjects.array_to_dimarray(x, :y; dims=(:a, :b)) @test da == x @@ -117,7 +120,7 @@ Dimensions.@dim foo "foo" gdims = Dimensions.dims(da) @test gdims isa NTuple{4,Dim} @test Dimensions.name(gdims) === (:a, :b, :y_dim_3, :y_dim_4) - @test Dimensions.index(gdims) == (11:20, 0:3, -1:0, 2:4) + @test parent.(Dimensions.lookup(gdims)) == (11:20, 0:3, -1:0, 2:4) da = @inferred DimArray InferenceObjects.array_to_dimarray( x, :z; dims=(:c, :d), default_dims=(:draw, :chain) @@ -127,7 +130,7 @@ Dimensions.@dim foo "foo" gdims = Dimensions.dims(da) @test gdims isa NTuple{4,Dim} @test Dimensions.name(gdims) === (:draw, :chain, :c, :d) - @test Dimensions.index(gdims) == (11:20, 0:3, -1:0, 2:4) + @test parent.(Dimensions.lookup(gdims)) == (11:20, 0:3, -1:0, 2:4) v = randn(1_000) da = @inferred DimArray InferenceObjects.array_to_dimarray( @@ -138,7 +141,7 @@ Dimensions.@dim foo "foo" gdims = Dimensions.dims(da) @test gdims isa NTuple{2,Dim} @test Dimensions.name(gdims) === (:draw, :chain) - @test Dimensions.index(gdims) == (1:1000, 1:1) + @test parent.(Dimensions.lookup(gdims)) == (1:1000, 1:1) s = fill(1) # 0-dimensional array da = @inferred DimArray InferenceObjects.array_to_dimarray( @@ -149,18 +152,18 @@ Dimensions.@dim foo "foo" gdims = Dimensions.dims(da) @test gdims isa NTuple{2,Dim} @test Dimensions.name(gdims) === (:draw, :chain) - @test Dimensions.index(gdims) == (1:1, 1:1) + @test parent.(Dimensions.lookup(gdims)) == (1:1, 1:1) end @testset "AsSlice" begin da = DimArray(randn(2), Dim{:a}(["foo", "bar"])) - @test da[a=At("foo")] == da[1] - da_sel = @inferred da[a=InferenceObjects.AsSlice(At("foo"))] + @test da[a = At("foo")] == da[1] + da_sel = @inferred da[a = InferenceObjects.AsSlice(At("foo"))] @test da_sel isa DimArray @test Dimensions.dims(da_sel) == (Dim{:a}(["foo"]),) - @test da_sel == da[a=At(["foo"])] + @test da_sel == da[a = At(["foo"])] - da_sel = @inferred da[a=At(["foo", "bar"])] + da_sel = @inferred da[a = At(["foo", "bar"])] @test da_sel isa DimArray @test Dimensions.dims(da_sel) == Dimensions.dims(da) @test da_sel == da diff --git a/test/inference_data.jl b/test/inference_data.jl index 080ed2c5..122ac47b 100644 --- a/test/inference_data.jl +++ b/test/inference_data.jl @@ -57,26 +57,29 @@ using InferenceObjects, DimensionalData, Test @test idata[1] === posterior @test idata[2] === prior - idata_sel = idata[dima=At(2:3), dimb=At(6)] + idata_sel = idata[dima = At(2:3), dimb = At(6)] @test idata_sel isa InferenceData @test InferenceObjects.groupnames(idata_sel) === InferenceObjects.groupnames(idata) - @test Dimensions.index(idata_sel.posterior, :dima) == 2:3 - @test Dimensions.index(idata_sel.prior, :dima) == 2:3 - @test Dimensions.index(idata_sel.posterior, :dimb) == [6] - @test Dimensions.index(idata_sel.prior, :dimb) == [6] + @test parent(Dimensions.lookup(idata_sel.posterior, :dima)) == 2:3 + @test parent(Dimensions.lookup(idata_sel.prior, :dima)) == 2:3 + @test parent(Dimensions.lookup(idata_sel.posterior, :dimb)) == [6] + @test parent(Dimensions.lookup(idata_sel.prior, :dimb)) == [6] if VERSION ≥ v"1.7" - idata_sel = idata[(:posterior, :observed_data), dimy=1, dimb=1, shared=At("s1")] + idata_sel = idata[ + (:posterior, :observed_data), dimy = 1, dimb = 1, shared = At("s1") + ] @test idata_sel isa InferenceData @test InferenceObjects.groupnames(idata_sel) === (:posterior, :observed_data) - @test Dimensions.index(idata_sel.posterior, :dima) == coords.dima - @test Dimensions.index(idata_sel.posterior, :dimb) == coords.dimb[[1]] - @test Dimensions.index(idata_sel.posterior, :shared) == ["s1"] - @test Dimensions.index(idata_sel.observed_data, :dimy) == coords.dimy[[1]] - @test Dimensions.index(idata_sel.observed_data, :shared) == ["s1"] + @test parent(Dimensions.lookup(idata_sel.posterior, :dima)) == coords.dima + @test parent(Dimensions.lookup(idata_sel.posterior, :dimb)) == coords.dimb[[1]] + @test parent(Dimensions.lookup(idata_sel.posterior, :shared)) == ["s1"] + @test parent(Dimensions.lookup(idata_sel.observed_data, :dimy)) == + coords.dimy[[1]] + @test parent(Dimensions.lookup(idata_sel.observed_data, :shared)) == ["s1"] end - ds_sel = idata[:posterior, chain=1] + ds_sel = idata[:posterior, chain = 1] @test ds_sel isa Dataset @test !hasdim(ds_sel, :chain) diff --git a/test/test_helpers.jl b/test/test_helpers.jl index 8c0bb6c9..859d2e64 100644 --- a/test/test_helpers.jl +++ b/test/test_helpers.jl @@ -81,7 +81,7 @@ function test_idata_approx_equal( dims1 = DimensionalData.dims(da1) dims2 = DimensionalData.dims(da2) @test DimensionalData.name(dims1) == DimensionalData.name(dims2) - @test DimensionalData.index(dims1) == DimensionalData.index(dims2) + @test parent.(Dimensions.lookup(dims1)) == parent.(Dimensions.lookup(dims2)) end if check_metadata metadata1 = DimensionalData.metadata(ds1) @@ -119,7 +119,7 @@ function test_idata_group_correct( for dim in _dims dim_name = DimensionalData.name(dim) if dim_name ∈ keys(coords) - @test coords[dim_name] == DimensionalData.index(dim) + @test coords[dim_name] == parent(dim) end end end