From 50950ea27d65c65e72b0bad646f78c57c099b340 Mon Sep 17 00:00:00 2001 From: Seth Axen Date: Thu, 18 Aug 2022 00:25:44 +0200 Subject: [PATCH] Depend on and export InferenceObjects (#220) * Add InferenceObjects as dependency * Remove InferenceObjects module * Load OrderedCollections * Increment version number * Add module to docs build * Separate out InferenceObjects exports --- Project.toml | 4 +- docs/make.jl | 2 +- src/ArviZ.jl | 26 +- src/InferenceObjects/InferenceObjects.jl | 40 --- src/InferenceObjects/convert_dataset.jl | 19 -- .../convert_inference_data.jl | 90 ------- src/InferenceObjects/dataset.jl | 128 --------- src/InferenceObjects/dimensions.jl | 119 --------- src/InferenceObjects/from_namedtuple.jl | 203 -------------- src/InferenceObjects/inference_data.jl | 252 ------------------ src/InferenceObjects/utils.jl | 79 ------ test/InferenceObjects/convert_dataset.jl | 58 ---- .../convert_inference_data.jl | 84 ------ test/InferenceObjects/dataset.jl | 156 ----------- test/InferenceObjects/dimensions.jl | 115 -------- test/InferenceObjects/from_namedtuple.jl | 70 ----- test/InferenceObjects/inference_data.jl | 127 --------- test/InferenceObjects/runtests.jl | 12 - test/InferenceObjects/test_helpers.jl | 123 --------- test/InferenceObjects/utils.jl | 44 --- test/runtests.jl | 2 - test/test_mcmcchains.jl | 2 +- 22 files changed, 18 insertions(+), 1737 deletions(-) delete mode 100644 src/InferenceObjects/InferenceObjects.jl delete mode 100644 src/InferenceObjects/convert_dataset.jl delete mode 100644 src/InferenceObjects/convert_inference_data.jl delete mode 100644 src/InferenceObjects/dataset.jl delete mode 100644 src/InferenceObjects/dimensions.jl delete mode 100644 src/InferenceObjects/from_namedtuple.jl delete mode 100644 src/InferenceObjects/inference_data.jl delete mode 100644 src/InferenceObjects/utils.jl delete mode 100644 test/InferenceObjects/convert_dataset.jl delete mode 100644 test/InferenceObjects/convert_inference_data.jl delete mode 100644 test/InferenceObjects/dataset.jl delete mode 100644 test/InferenceObjects/dimensions.jl delete mode 100644 test/InferenceObjects/from_namedtuple.jl delete mode 100644 test/InferenceObjects/inference_data.jl delete mode 100644 test/InferenceObjects/runtests.jl delete mode 100644 test/InferenceObjects/test_helpers.jl delete mode 100644 test/InferenceObjects/utils.jl diff --git a/Project.toml b/Project.toml index c30820d5..06740c7a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,13 +1,14 @@ name = "ArviZ" uuid = "131c737c-5715-5e2e-ad31-c244f01c1dc7" authors = ["Seth Axen "] -version = "0.6.2" +version = "0.6.3" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DimensionalData = "0703355e-b756-11e9-17c0-8b28908087d0" +InferenceObjects = "b5cf5a8d-e756-4ee3-b014-01d49d192c00" LogExpFunctions = "2ab3a3ac-af41-5b50-aa03-7779005ae688" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" @@ -22,6 +23,7 @@ StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" Conda = "1.0" DataFrames = "0.20, 0.21, 0.22, 1.0" DimensionalData = "0.20, 0.21" +InferenceObjects = "0.1" LogExpFunctions = "0.2.0, 0.3" OrderedCollections = "1" PSIS = "0.2, 0.3, 0.4, 0.5" diff --git a/docs/make.jl b/docs/make.jl index 553c12cf..2faa040c 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -31,7 +31,7 @@ download_asset("ArviZ_white.png", "logo-dark.png") download_asset("favicon.ico") makedocs(; - modules=[ArviZ, PSIS], + modules=[ArviZ, InferenceObjects, PSIS], sitename="ArviZ.jl", pages=[ "Home" => "index.md", diff --git a/src/ArviZ.jl b/src/ArviZ.jl index 4db4a0d1..c701ad4c 100644 --- a/src/ArviZ.jl +++ b/src/ArviZ.jl @@ -34,14 +34,12 @@ import StatsBase: summarystats import Markdown: @doc_str import PyCall: PyObject -include("InferenceObjects/InferenceObjects.jl") - -using .InferenceObjects -import .InferenceObjects: convert_to_inference_data, namedtuple_of_arrays +using InferenceObjects +import InferenceObjects: convert_to_inference_data, namedtuple_of_arrays # internal functions temporarily used/extended here -using .InferenceObjects: +using InferenceObjects: attributes, flatten, groupnames, groups, hasgroup, rekey, setattribute! -import .InferenceObjects: namedtuple_of_arrays +import InferenceObjects: namedtuple_of_arrays # Exports @@ -79,20 +77,22 @@ export bfmi, ess, rhat, mcse ## Stats utils export autocov, autocorr, make_ufunc, wrap_xarray_ufunc -## Dataset -export Dataset, convert_to_dataset, namedtuple_to_dataset -## InferenceData -export InferenceData +## InferenceObjects +export InferenceObjects, + Dataset, + InferenceData, + convert_to_dataset, + convert_to_inference_data, + from_namedtuple, + namedtuple_to_dataset ## Data -export convert_to_inference_data, - extract_dataset, +export extract_dataset, load_arviz_data, to_netcdf, from_json, from_netcdf, - from_namedtuple, from_dict, from_cmdstan, from_mcmcchains, diff --git a/src/InferenceObjects/InferenceObjects.jl b/src/InferenceObjects/InferenceObjects.jl deleted file mode 100644 index 07eec7ab..00000000 --- a/src/InferenceObjects/InferenceObjects.jl +++ /dev/null @@ -1,40 +0,0 @@ -module InferenceObjects - -using Dates: Dates -using DimensionalData: DimensionalData, Dimensions, LookupArrays -using OrderedCollections: OrderedDict - -# groups that are officially listed in the schema -const SCHEMA_GROUPS = ( - :posterior, - :posterior_predictive, - :predictions, - :log_likelihood, - :sample_stats, - :prior, - :prior_predictive, - :sample_stats_prior, - :observed_data, - :constant_data, - :predictions_constant_data, - :warmup_posterior, - :warmup_posterior_predictive, - :warmup_predictions, - :warmup_sample_stats, - :warmup_log_likelihood, -) -const SCHEMA_GROUPS_DICT = Dict(n => i for (i, n) in enumerate(SCHEMA_GROUPS)) -const DEFAULT_SAMPLE_DIMS = Dimensions.key2dim((:chain, :draw)) - -export Dataset, InferenceData -export convert_to_dataset, convert_to_inference_data, from_namedtuple, namedtuple_to_dataset - -include("utils.jl") -include("dimensions.jl") -include("dataset.jl") -include("inference_data.jl") -include("convert_dataset.jl") -include("convert_inference_data.jl") -include("from_namedtuple.jl") - -end # module diff --git a/src/InferenceObjects/convert_dataset.jl b/src/InferenceObjects/convert_dataset.jl deleted file mode 100644 index 8706055d..00000000 --- a/src/InferenceObjects/convert_dataset.jl +++ /dev/null @@ -1,19 +0,0 @@ -Base.convert(::Type{Dataset}, obj) = convert_to_dataset(obj) -Base.convert(::Type{Dataset}, obj::Dataset) = obj - -""" - convert_to_dataset(obj; group = :posterior, kwargs...) -> Dataset - -Convert a supported object to a `Dataset`. - -In most cases, this function calls [`convert_to_inference_data`](@ref) and returns the -corresponding `group`. -""" -function convert_to_dataset end - -function convert_to_dataset(obj; group::Symbol=:posterior, kwargs...) - idata = convert_to_inference_data(obj; group, kwargs...) - dataset = getproperty(idata, group) - return dataset -end -convert_to_dataset(data::Dataset; kwargs...) = data diff --git a/src/InferenceObjects/convert_inference_data.jl b/src/InferenceObjects/convert_inference_data.jl deleted file mode 100644 index fbcbeaa0..00000000 --- a/src/InferenceObjects/convert_inference_data.jl +++ /dev/null @@ -1,90 +0,0 @@ -""" - convert(::Type{InferenceData}, obj) - -Convert `obj` to an `InferenceData`. - -`obj` can be any type for which [`convert_to_inference_data`](@ref) is defined. -""" -Base.convert(::Type{InferenceData}, obj) = convert_to_inference_data(obj) -Base.convert(::Type{InferenceData}, obj::InferenceData) = obj -Base.convert(::Type{NamedTuple}, data::InferenceData) = NamedTuple(data) -NamedTuple(data::InferenceData) = parent(data) - -""" - convert_to_inference_data(obj; group, kwargs...) -> InferenceData - -Convert a supported object to an [`InferenceData`](@ref) object. - -If `obj` converts to a single dataset, `group` specifies which dataset in the resulting -`InferenceData` that is. - -See [`convert_to_dataset`](@ref) - -# Arguments - - - `obj` can be many objects. Basic supported types are: - - + [`InferenceData`](@ref): return unchanged - + [`Dataset`](@ref)/`DimensionalData.AbstractDimStack`: add to `InferenceData` as the only - group - + `NamedTuple`/`AbstractDict`: create a `Dataset` as the only group - + `AbstractArray{<:Real}`: create a `Dataset` as the only group, given an arbitrary - name, if the name is not set - -More specific types may be documented separately. - -# Keywords - - - `group::Symbol = :posterior`: If `obj` converts to a single dataset, assign the resulting - dataset to this group. - - - `dims`: a collection mapping variable names to collections of objects containing - dimension names. Acceptable such objects are: - - + `Symbol`: dimension name - + `Type{<:DimensionsionalData.Dimension}`: dimension type - + `DimensionsionalData.Dimension`: dimension, potentially with indices - + `Nothing`: no dimension name provided, dimension name is automatically generated - - `coords`: a collection indexable by dimension name specifying the indices of the given - dimension. If indices for a dimension in `dims` are provided, they are used even if - the dimension contains its own indices. If a dimension is missing, its indices are - automatically generated. - - `kwargs`: remaining keywords forwarded to converter functions -""" -function convert_to_inference_data end - -convert_to_inference_data(data::InferenceData; kwargs...) = data -function convert_to_inference_data(stack::DimensionalData.AbstractDimStack; kwargs...) - return convert_to_inference_data(Dataset(stack); kwargs...) -end -function convert_to_inference_data(data::Dataset; group=:posterior, kwargs...) - return convert_to_inference_data(InferenceData(; group => data); kwargs...) -end -function convert_to_inference_data(data::AbstractDict{Symbol}; kwargs...) - return convert_to_inference_data(NamedTuple(data); kwargs...) -end -function convert_to_inference_data(var_data::AbstractArray{<:Real}; kwargs...) - data = (; default_var_name(var_data) => var_data) - return convert_to_inference_data(data; kwargs...) -end -function convert_to_inference_data( - data::NamedTuple{<:Any,<:Tuple{Vararg{AbstractArray{<:Real}}}}; - group=:posterior, - kwargs..., -) - ds = namedtuple_to_dataset(data; kwargs...) - return convert_to_inference_data(ds; group) -end - -""" - default_var_name(data) -> Symbol - -Return the default name for the variable whose values are stored in `data`. -""" -default_var_name(data) = :x -function default_var_name(data::DimensionalData.AbstractDimArray) - name = DimensionalData.name(data) - name isa Symbol && return name - name isa AbstractString && !isempty(name) && return Symbol(name) - return default_var_name(parent(data)) -end diff --git a/src/InferenceObjects/dataset.jl b/src/InferenceObjects/dataset.jl deleted file mode 100644 index 23cdec69..00000000 --- a/src/InferenceObjects/dataset.jl +++ /dev/null @@ -1,128 +0,0 @@ -""" - Dataset{L} <: DimensionalData.AbstractDimStack{L} - -Container of dimensional arrays sharing some dimensions. - -This type is an -[`DimensionalData.AbstractDimStack`](https://rafaqz.github.io/DimensionalData.jl/stable/api/#DimensionalData.AbstractDimStack) -that implements the same interface as `DimensionalData.DimStack` and has identical usage. - -When a `Dataset` is passed to Python, it is converted to an `xarray.Dataset` without copying -the data. That is, the Python object shares the same memory as the Julia object. However, -if an `xarray.Dataset` is passed to Julia, its data must be copied. - -# Constructors - - Dataset(data::DimensionalData.AbstractDimArray...) - Dataset(data::Tuple{Vararg{<:DimensionalData.AbstractDimArray}}) - Dataset(data::NamedTuple{Keys,Vararg{<:DimensionalData.AbstractDimArray}}) - Dataset( - data::NamedTuple, - dims::Tuple{Vararg{DimensionalData.Dimension}}; - metadata=DimensionalData.NoMetadata(), - ) - -In most cases, use [`convert_to_dataset`](@ref) to create a `Dataset` instead of directly -using a constructor. -""" -struct Dataset{L,D<:DimensionalData.AbstractDimStack{L}} <: - DimensionalData.AbstractDimStack{L} - data::D -end - -Dataset(args...; kwargs...) = Dataset(DimensionalData.DimStack(args...; kwargs...)) -Dataset(data::Dataset) = data - -Base.parent(data::Dataset) = getfield(data, :data) - -Base.propertynames(data::Dataset) = keys(data) - -Base.getproperty(data::Dataset, k::Symbol) = getindex(data, k) - -function setattribute!(data::Dataset, k::Symbol, value) - setindex!(DimensionalData.metadata(data), value, k) - return value -end -@deprecate setattribute!(data::Dataset, k::AbstractString, value) setattribute!( - data, Symbol(k), value -) false - -""" - namedtuple_to_dataset(data; kwargs...) -> Dataset - -Convert `NamedTuple` mapping variable names to arrays to a [`Dataset`](@ref). - -# Keywords - - - `attrs`: a Symbol-indexable collection of metadata to attach to the dataset, in addition - to defaults. Values should be JSON serializable. - - - `library::Union{String,Module}`: library used for performing inference. Will be attached - to the `attrs` metadata. - - `dims`: a collection mapping variable names to collections of objects containing dimension - names. Acceptable such objects are: - - + `Symbol`: dimension name - + `Type{<:DimensionsionalData.Dimension}`: dimension type - + `DimensionsionalData.Dimension`: dimension, potentially with indices - + `Nothing`: no dimension name provided, dimension name is automatically generated - - `coords`: a collection indexable by dimension name specifying the indices of the given - dimension. If indices for a dimension in `dims` are provided, they are used even if - the dimension contains its own indices. If a dimension is missing, its indices are - automatically generated. -""" -function namedtuple_to_dataset end -function namedtuple_to_dataset( - data; attrs=(;), library=nothing, dims=(;), coords=(;), default_dims=DEFAULT_SAMPLE_DIMS -) - dim_arrays = map(keys(data)) do var_name - var_data = data[var_name] - var_dims = get(dims, var_name, ()) - return array_to_dimarray(var_data, var_name; dims=var_dims, coords, default_dims) - end - attributes = merge(default_attributes(library), attrs) - metadata = OrderedDict{Symbol,Any}(pairs(attributes)) - return Dataset(dim_arrays...; metadata) -end - -""" - default_attributes(library=nothing) -> NamedTuple - -Generate default attributes metadata for a dataset generated by inference library `library`. - -`library` may be a `String` or a `Module`. -""" -function default_attributes(library=nothing) - return ( - created_at=Dates.format(Dates.now(), Dates.ISODateTimeFormat), - library_attributes(library)..., - ) -end - -library_attributes(library) = (; inference_library=string(library)) -library_attributes(::Nothing) = (;) -function library_attributes(library::Module) - return ( - inference_library=string(library), - inference_library_version=string(package_version(library)), - ) -end - -# DimensionalData interop - -for f in [:data, :dims, :refdims, :metadata, :layerdims, :layermetadata] - @eval begin - DimensionalData.$(f)(ds::Dataset) = DimensionalData.$(f)(parent(ds)) - end -end - -# 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)) - -function DimensionalData.rebuild(data::Dataset; kwargs...) - return Dataset(DimensionalData.rebuild(parent(data); kwargs...)) -end diff --git a/src/InferenceObjects/dimensions.jl b/src/InferenceObjects/dimensions.jl deleted file mode 100644 index 006eec2f..00000000 --- a/src/InferenceObjects/dimensions.jl +++ /dev/null @@ -1,119 +0,0 @@ -has_all_sample_dims(dims) = all(Dimensions.hasdim(dims, DEFAULT_SAMPLE_DIMS)) - -""" - as_dimension(dim, coords, axis) -> DimensionsionalData.Dimension - -Convert `dim`, `coords`, and `axis` to a `Dimension` object. - -# Arguments - - - `dim`: An object specifying the name and potentially indices of a dimension. Can be the - following types: - - + `Symbol`: dimension name. - + `Type{<:DimensionsionalData.Dimension}`: dimension type - + `DimensionsionalData.Dimension`: dimension, potentially with indices - - - `coords`: a collection indexable by dimension name specifying the indices of the given - dimension. If indices are provided, they are used even if `dim` contains its own - indices. If a dimension is missing, its indices are automatically generated. - - `axis`: A default axis to be used if `coords` and `dim` indices are not provided. -""" -function as_dimension(dim, coords, axis) - D = Dimensions.basetypeof(Dimensions.basedims(dim)) - inds = if dim isa Dimensions.Dimension - vals = LookupArrays.val(dim) - vals isa AbstractVector ? vals : axis - else - axis - end - return D(get(coords, Dimensions.name(D), inds)) -end - -""" - generate_dims(array, name; dims, coords, default_dims) - -Generate `DimensionsionalData.Dimension` objects for each dimension of `array`. - -`name` indicates the name of the variable represented by array. - -# Keywords - - - `dims`: A collection of objects indicating dimension names. If any dimensions are not - provided, their names are automatically generated. Acceptable types of entries are: - - + `Symbol`: dimension name - + `Type{<:DimensionsionalData.Dimension}`: dimension type - + `DimensionsionalData.Dimension`: dimension, potentially with indices - + `Nothing`: no dimension name provided, dimension name is automatically generated - - - `coords`: a collection indexable by dimension name specifying the indices of the given - dimension. If indices for a dimension in `dims` are provided, they are used even if - the dimension contains its own indices. If a dimension is missing, its indices are - automatically generated. - - `default_dims`: A collection of dims to be prepended to `dims` whose elements have the - same constraints. -""" -function generate_dims(array, name; dims=(), coords=(;), default_dims=()) - num_default_dims = length(default_dims) - length(dims) + num_default_dims > ndims(array) && @error "blah" - dims_named = ntuple(ndims(array) - length(default_dims)) do i - dim = get(dims, i, nothing) - dim === nothing && return Symbol("$(name)_dim_$(i)") - return dim - end - dims_all = (default_dims..., dims_named...) - axes_all = axes(array) - 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 -end - -""" - array_to_dimarray(array, name; kwargs...) -> DimensionalData.AbstractDimArray - -Convert `array` to a `AbstractDimArray` with name `name`. - -If `array` is already an `AbstractDimArray`, then it is returned without modification. -See [`generate_dims`](@ref) for a description of `kwargs`. -""" -function array_to_dimarray(data, name; dims=(), coords=(;), default_dims=()) - array = if ndims(data) < 2 && has_all_sample_dims(default_dims) - reshape(data, 1, :) - else - data - end - array_dims = generate_dims(array, name; dims, coords, default_dims) - return DimensionalData.DimArray(array, array_dims; name) -end -function array_to_dimarray(array::DimensionalData.AbstractDimArray, name; kwargs...) - return DimensionalData.rebuild(array; name) -end - -""" - AsSlice{T<:LookupArrays.Selector} <: LookupArrays.Selector{T} - - AsSlice(selector) - -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} - val::T -end - -function LookupArrays.selectindices(l::LookupArrays.LookupArray, sel::AsSlice; kw...) - i = LookupArrays.selectindices(l, LookupArrays.val(sel); kw...) - inds = i isa AbstractVector ? i : [i] - return inds -end - -""" - index_to_indices(index) - -Convert `index` to a collection of indices or a selector representing such a collection. -""" -index_to_indices(i) = i -index_to_indices(i::Int) = [i] -index_to_indices(sel::LookupArrays.Selector) = AsSlice(sel) diff --git a/src/InferenceObjects/from_namedtuple.jl b/src/InferenceObjects/from_namedtuple.jl deleted file mode 100644 index e57735d0..00000000 --- a/src/InferenceObjects/from_namedtuple.jl +++ /dev/null @@ -1,203 +0,0 @@ -""" - from_namedtuple(posterior::NamedTuple; kwargs...) -> InferenceData - from_namedtuple(posterior::Vector{<:NamedTuple}; kwargs...) -> InferenceData - from_namedtuple(posterior::Matrix{<:NamedTuple}; kwargs...) -> InferenceData - from_namedtuple(posterior::Vector{Vector{<:NamedTuple}}; kwargs...) -> InferenceData - from_namedtuple( - posterior::NamedTuple, - sample_stats::Any, - posterior_predictive::Any, - predictions::Any, - log_likelihood::Any; - kwargs... - ) -> InferenceData - -Convert a `NamedTuple` or container of `NamedTuple`s to an `InferenceData`. - -If containers are passed, they are flattened into a single `NamedTuple` with array elements -whose first dimensions correspond to the dimensions of the containers. - -# Arguments - - - `posterior`: The data to be converted. It may be of the following types: - - + `::NamedTuple`: The keys are the variable names and the values are arrays with - dimensions `(nchains, ndraws, sizes...)`. - + `::Matrix{<:NamedTuple}`: Each element is a single draw from a single chain, with - array/scalar values with dimensions `sizes`. The dimensions of the matrix container - are `(nchains, ndraws)` - + `::Vector{Vector{<:NamedTuple}}`: The same as the above case. - -# Keywords - - - `posterior_predictive::Any=nothing`: Draws from the posterior predictive distribution - - `sample_stats::Any=nothing`: Statistics of the posterior sampling process - - `predictions::Any=nothing`: Out-of-sample predictions for the posterior. - - `prior::Any=nothing`: Draws from the prior - - `prior_predictive::Any=nothing`: Draws from the prior predictive distribution - - `sample_stats_prior::Any=nothing`: Statistics of the prior sampling process - - `observed_data::NamedTuple`: Observed data on which the `posterior` is - conditional. It should only contain data which is modeled as a random variable. Keys - are parameter names and values. - - `constant_data::NamedTuple`: Model constants, data included in the model - which is not modeled as a random variable. Keys are parameter names and values. - - `predictions_constant_data::NamedTuple`: Constants relevant to the model - predictions (i.e. new `x` values in a linear regression). - - `log_likelihood`: Pointwise log-likelihood for the data. It is recommended - to use this argument as a `NamedTuple` whose keys are observed variable names and whose - values are log likelihood arrays. - - `library`: Name of library that generated the draws - - `coords`: Map from named dimension to named indices - - `dims`: Map from variable name to names of its dimensions - -# Returns - - - `InferenceData`: The data with groups corresponding to the provided data - -# Examples - -```@example -using ArviZ -nchains, ndraws = 2, 10 - -data1 = ( - x=rand(nchains, ndraws), y=randn(nchains, ndraws, 2), z=randn(nchains, ndraws, 3, 2) -) -idata1 = from_namedtuple(data1) - -data2 = [(x=rand(ndraws), y=randn(ndraws, 2), z=randn(ndraws, 3, 2)) for _ in 1:nchains]; -idata2 = from_namedtuple(data2) - -data3 = [(x=rand(), y=randn(2), z=randn(3, 2)) for _ in 1:nchains, _ in 1:ndraws]; -idata3 = from_namedtuple(data3) - -data4 = [[(x=rand(), y=randn(2), z=randn(3, 2)) for _ in 1:ndraws] for _ in 1:nchains]; -idata4 = from_namedtuple(data4) -``` -""" -from_namedtuple - -function from_namedtuple( - posterior, posterior_predictive, sample_stats, predictions, log_likelihood; kwargs... -) - all_idata = InferenceData() - post_data = posterior === nothing ? posterior : namedtuple_of_arrays(posterior) - for (group, group_data) in [ - :posterior_predictive => posterior_predictive, - :sample_stats => sample_stats, - :predictions => predictions, - :log_likelihood => log_likelihood, - ] - group_data === nothing && continue - if post_data !== nothing - if group_data isa Symbol - group_data = (Symbol(group_data),) - end - if all(Base.Fix2(isa, Symbol), group_data) - group_data = NamedTuple{Tuple(group_data)}(post_data) - post_data = NamedTuple{Tuple(setdiff(keys(post_data), keys(group_data)))}( - post_data - ) - end - isempty(group_data) && continue - end - group_dataset = convert_to_dataset(group_data; kwargs...) - all_idata = merge(all_idata, InferenceData(; group => group_dataset)) - end - - (post_data === nothing || isempty(post_data)) && return all_idata - - post_dataset = convert_to_dataset(post_data; kwargs...) - all_idata = merge(all_idata, InferenceData(; posterior=post_dataset)) - - return all_idata -end -function from_namedtuple( - posterior::Union{NamedTuple,Nothing}=nothing; - posterior_predictive=nothing, - sample_stats=nothing, - predictions=nothing, - prior=nothing, - prior_predictive=nothing, - sample_stats_prior=nothing, - observed_data=nothing, - constant_data=nothing, - predictions_constant_data=nothing, - log_likelihood=nothing, - library=nothing, - kwargs..., -) - all_idata = from_namedtuple( - posterior, - posterior_predictive, - sample_stats, - predictions, - log_likelihood; - library=library, - kwargs..., - ) - - if any(x -> x !== nothing, [prior, prior_predictive, sample_stats_prior]) - pre_prior_idata = from_namedtuple( - prior; - posterior_predictive=prior_predictive, - sample_stats=sample_stats_prior, - library, - kwargs..., - ) - prior_idata = rekey( - pre_prior_idata, - ( - posterior=:prior, - posterior_predictive=:prior_predictive, - sample_stats=:sample_stats_prior, - ), - ) - all_idata = merge(all_idata, prior_idata) - end - - for (group, group_data) in [ - :observed_data => observed_data, - :constant_data => constant_data, - :predictions_constant_data => predictions_constant_data, - ] - group_data === nothing && continue - group_dataset = convert_to_dataset(group_data; library, default_dims=(), kwargs...) - all_idata = merge(all_idata, InferenceData(; group => group_dataset)) - end - - return all_idata -end -function from_namedtuple(data::AbstractVector{<:NamedTuple}; kwargs...) - return from_namedtuple(namedtuple_of_arrays(data); kwargs...) -end -function from_namedtuple(data::AbstractMatrix{<:NamedTuple}; kwargs...) - return from_namedtuple(namedtuple_of_arrays(data); kwargs...) -end -function from_namedtuple(data::AbstractVector{<:AbstractVector{<:NamedTuple}}; kwargs...) - return from_namedtuple(namedtuple_of_arrays(data); kwargs...) -end - -""" - convert_to_inference_data(obj::NamedTuple; kwargs...) -> InferenceData - convert_to_inference_data(obj::Vector{<:NamedTuple}; kwargs...) -> InferenceData - convert_to_inference_data(obj::Matrix{<:NamedTuple}; kwargs...) -> InferenceData - convert_to_inference_data(obj::Vector{Vector{<:NamedTuple}}; kwargs...) -> InferenceData - -Convert `obj` to an [`InferenceData`](@ref). See [`from_namedtuple`](@ref) for a description -of `obj` possibilities and `kwargs`. -""" -function convert_to_inference_data( - data::T; group=:posterior, kwargs... -) where { - T<:Union{ - NamedTuple, - AbstractVector{<:NamedTuple}, - AbstractMatrix{<:NamedTuple}, - AbstractVector{<:AbstractVector{<:NamedTuple}}, - }, -} - group = Symbol(group) - group === :posterior && return from_namedtuple(data; kwargs...) - return from_namedtuple(; group => data, kwargs...) -end diff --git a/src/InferenceObjects/inference_data.jl b/src/InferenceObjects/inference_data.jl deleted file mode 100644 index 5488d285..00000000 --- a/src/InferenceObjects/inference_data.jl +++ /dev/null @@ -1,252 +0,0 @@ -""" - InferenceData{group_names,group_types} - -Container for inference data storage using DimensionalData. - -This object implements the [InferenceData schema](https://python.arviz.org/en/latest/schema/schema.html). - -Internally, groups are stored in a `NamedTuple`, which can be accessed using -`parent(::InferenceData)`. - -# Constructors - - InferenceData(groups::NamedTuple) - InferenceData(; groups...) - -Construct an inference data from either a `NamedTuple` or keyword arguments of groups. - -Groups must be [`Dataset`](@ref) objects. - -Instead of directly creating an `InferenceData`, use the exported `from_xyz` functions or -[`convert_to_inference_data`](@ref). -""" -struct InferenceData{group_names,group_types<:Tuple{Vararg{Dataset}}} - groups::NamedTuple{group_names,group_types} - function InferenceData( - groups::NamedTuple{group_names,<:Tuple{Vararg{Dataset}}} - ) where {group_names} - group_names_ordered = _reorder_group_names(Val{group_names}()) - groups_ordered = NamedTuple{group_names_ordered}(groups) - return new{group_names_ordered,typeof(values(groups_ordered))}(groups_ordered) - end -end -InferenceData(; kwargs...) = InferenceData(NamedTuple(kwargs)) -InferenceData(data::InferenceData) = data - -Base.parent(data::InferenceData) = getfield(data, :groups) - -# these 3 interfaces ensure InferenceData behaves like a NamedTuple - -# properties interface -""" - propertynames(data::InferenceData) -> Tuple{Symbol} - -Get names of groups -""" -Base.propertynames(data::InferenceData) = propertynames(parent(data)) - -""" - getproperty(data::InferenceData, name::Symbol) -> Dataset - -Get group with the specified `name`. -""" -Base.getproperty(data::InferenceData, k::Symbol) = getproperty(parent(data), k) - -# indexing interface -""" - Base.getindex(data::InferenceData, groups::Symbol; coords...) -> Dataset - Base.getindex(data::InferenceData, groups; coords...) -> InferenceData - -Return a new `InferenceData` containing the specified groups sliced to the specified coords. - -`coords` specifies a dimension name mapping to an index, a `DimensionalData.Selector`, or -an `IntervalSets.AbstractInterval`. - -If one or more groups lack the specified dimension, a warning is raised but can be ignored. -All groups that contain the dimension must also contain the specified indices, or an -exception will be raised. - -# Examples - -Select data from all groups for just the specified id values. - -```@repl getindex -julia> using ArviZ, DimensionalData - -julia> idata = from_namedtuple( - (θ=randn(4, 100, 4), τ=randn(4, 100)); - prior=(θ=randn(4, 100, 4), τ=randn(4, 100)), - observed_data=(y=randn(4),), - dims=(θ=[:id], y=[:id]), - coords=(id=["a", "b", "c", "d"],), - ) -InferenceData with groups: - > posterior - > prior - > observed_data - -julia> idata.posterior -Dataset with dimensions: - Dim{:chain} Sampled 1:4 ForwardOrdered Regular Points, - Dim{:draw} Sampled 1:100 ForwardOrdered Regular Points, - Dim{:id} Categorical String[a, b, c, d] ForwardOrdered -and 2 layers: - :θ Float64 dims: Dim{:chain}, Dim{:draw}, Dim{:id} (4×100×4) - :τ Float64 dims: Dim{:chain}, Dim{:draw} (4×100) - -with metadata OrderedCollections.OrderedDict{Symbol, Any} with 1 entry: - :created_at => "2022-08-11T11:15:21.4" - -julia> idata_sel = idata[id=At(["a", "b"])] -InferenceData with groups: - > posterior - > prior - > observed_data - -julia> idata_sel.posterior -Dataset with dimensions: - Dim{:chain} Sampled 1:4 ForwardOrdered Regular Points, - Dim{:draw} Sampled 1:100 ForwardOrdered Regular Points, - Dim{:id} Categorical String[a, b] ForwardOrdered -and 2 layers: - :θ Float64 dims: Dim{:chain}, Dim{:draw}, Dim{:id} (4×100×2) - :τ Float64 dims: Dim{:chain}, Dim{:draw} (4×100) - -with metadata OrderedCollections.OrderedDict{Symbol, Any} with 1 entry: - :created_at => "2022-08-11T11:15:21.4" -``` - -Select data from just the posterior, returning a `Dataset` if the indices index more than -one element from any of the variables: - -```@repl getindex -julia> idata[:observed_data, id=At(["a"])] -Dataset with dimensions: - Dim{:id} Categorical String[a] ForwardOrdered -and 1 layer: - :y Float64 dims: Dim{:id} (1) - -with metadata OrderedCollections.OrderedDict{Symbol, Any} with 1 entry: - :created_at => "2022-08-11T11:19:25.982" -``` - -Note that if a single index is provided, the behavior is still to slice so that the -dimension is preserved. -""" -Base.getindex(data::InferenceData, groups...; kwargs...) -function Base.getindex(data::InferenceData, k::Symbol; kwargs...) - ds = parent(data)[k] - isempty(kwargs) && return ds - return getindex(ds; kwargs...) -end -function Base.getindex(data::InferenceData, i::Int; kwargs...) - ds = parent(data)[i] - isempty(kwargs) && return ds - return getindex(ds; kwargs...) -end -function Base.getindex(data::InferenceData, ks; kwargs...) - data_new = InferenceData(parent(data)[ks]) - isempty(kwargs) && return data_new - return getindex(data_new; kwargs...) -end -function Base.getindex(data::InferenceData; kwargs...) - # if a single index is requested, then the return type of each group - # will be a `Dataset` if the group has other dimensions or `NamedTuple` - # if it has no other dimensions. - # So we promote to an array of indices - new_kwargs = map(index_to_indices, NamedTuple(kwargs)) - groups = map(parent(data)) do ds - return getindex(ds; new_kwargs...) - end - return InferenceData(groups) -end - -""" - Base.setindex(data::InferenceData, group::Dataset, name::Symbol) -> InferenceData - -Create a new `InferenceData` containing the `group` with the specified `name`. - -If a group with `name` is already in `data`, it is replaced. -""" -function Base.setindex(data::InferenceData, v, k::Symbol) - return InferenceData(Base.setindex(parent(data), v, k)) -end - -# iteration interface -Base.keys(data::InferenceData) = keys(parent(data)) -Base.haskey(data::InferenceData, k::Symbol) = haskey(parent(data), k) -Base.values(data::InferenceData) = values(parent(data)) -Base.pairs(data::InferenceData) = pairs(parent(data)) -Base.length(data::InferenceData) = length(parent(data)) -Base.iterate(data::InferenceData, i...) = iterate(parent(data), i...) -Base.eltype(data::InferenceData) = eltype(parent(data)) - -function Base.show(io::IO, ::MIME"text/plain", data::InferenceData) - print(io, "InferenceData with groups:") - prefix = "\n > " - for name in groupnames(data) - print(io, prefix, name) - end - return nothing -end -function Base.show(io::IO, mime::MIME"text/html", data::InferenceData) - show(io, mime, HTML("
InferenceData")) - for (name, group) in pairs(groups(data)) - show(io, mime, HTML(""" -
- $name -
$(sprint(show, "text/plain", group))
-
- """)) - end - return show(io, mime, HTML("
")) -end - -""" - groups(data::InferenceData) - -Get the groups in `data` as a named tuple mapping symbols to [`Dataset`](@ref)s. -""" -groups(data::InferenceData) = parent(data) - -""" - groupnames(data::InferenceData) - -Get the names of the groups (datasets) in `data` as a tuple of symbols. -""" -groupnames(data::InferenceData) = keys(groups(data)) - -""" - hasgroup(data::InferenceData, name::Symbol) -> Bool - -Return `true` if a group with name `name` is stored in `data`. -""" -hasgroup(data::InferenceData, name::Symbol) = haskey(data, name) - -@generated function _reorder_group_names(::Val{names}) where {names} - lt = (a, b) -> (a isa Integer && b isa Integer) ? a < b : string(a) < string(b) - return Tuple(sort(collect(names); lt, by=k -> get(SCHEMA_GROUPS_DICT, k, string(k)))) -end - -@generated _keys_and_types(::NamedTuple{keys,types}) where {keys,types} = (keys, types) - -""" - merge(data::InferenceData, others::InferenceData...) -> InferenceData - -Merge [`InferenceData`](@ref) objects. - -The result contains all groups in `data` and `others`. -If a group appears more than once, the one that occurs first is kept. - -See [`concat`](@ref) -""" -function Base.merge(data::InferenceData, others::InferenceData...) - return InferenceData(Base.merge(groups(data), map(groups, others)...)) -end - -function rekey(data::InferenceData, keymap) - groups_old = groups(data) - names_new = map(k -> get(keymap, k, k), propertynames(groups_old)) - groups_new = NamedTuple{names_new}(Tuple(groups_old)) - return InferenceData(groups_new) -end diff --git a/src/InferenceObjects/utils.jl b/src/InferenceObjects/utils.jl deleted file mode 100644 index 7c63026d..00000000 --- a/src/InferenceObjects/utils.jl +++ /dev/null @@ -1,79 +0,0 @@ -""" - flatten(x) - -If `x` is an array of arrays, flatten into a single array whose dimensions are ordered with -dimensions of the outermost container first and innermost container last. -""" -flatten(x) = x -flatten(x::AbstractArray{<:Number}) = convert(Array, x) -function flatten(x::AbstractArray{S}) where {T<:Number,N,S<:AbstractArray{T,N}} - ret = Array{T}(undef, (size(x)..., size(x[1])...)) - for k in keys(x) - setindex!(ret, x[k], k, (Colon() for _ in 1:N)...) - end - return ret -end - -""" - namedtuple_of_arrays(x::NamedTuple) -> NamedTuple - namedtuple_of_arrays(x::AbstractArray{NamedTuple}) -> NamedTuple - namedtuple_of_arrays(x::AbstractArray{AbstractArray{<:NamedTuple}}) -> NamedTuple - -Given a container of `NamedTuple`s, concatenate them, using the container dimensions as the -dimensions of the resulting arrays. - -# Examples - -```@example -using ArviZ -nchains, ndraws = 4, 100 -data = [(x=rand(), y=randn(2), z=randn(2, 3)) for _ in 1:nchains, _ in 1:ndraws]; -ntarray = ArviZ.namedtuple_of_arrays(data); -``` -""" -function namedtuple_of_arrays end -namedtuple_of_arrays(x::NamedTuple) = map(flatten, x) -namedtuple_of_arrays(x::AbstractArray) = namedtuple_of_arrays(namedtuple_of_arrays.(x)) -function namedtuple_of_arrays(x::AbstractArray{<:NamedTuple{K}}) where {K} - return mapreduce(merge, K) do k - v = flatten.(getproperty.(x, k)) - return (; k => flatten(v)) - end -end - -""" - package_version(pkg::Module) -> Union{Nothing,VersionNumber} - -Return version number of package `pkg`. - -If `pkg` does not have a version module (e.g. it is a submodule), then `nothing` is -returned. -""" -function package_version(pkg::Module) - @static if isdefined(Base, :pkgversion) - return Base.pkgversion(pkg) - end - pkg_path = pathof(pkg) - pkg_path === nothing && return nothing - project = joinpath(dirname(dirname(pkg_path)), "Project.toml") - isfile(project) || return nothing - toml = read(project, String) - m = match(r"(*ANYCRLF)^version\s*=\s\"(.*)\"$"m, toml) - return VersionNumber(m[1]) -end - -""" - rekey(collection, keymap) -> rekeyed_collection - -Return a new collection where values for specific keys have been moved to other keys. - -`keymap` must be a keyed collection mapping from keys of the same type as `collection` to -other keys of the same type. - -Keys present in `keymap` but absent from `collection` are ignored. -""" -rekey(d, keymap) = Dict(get(keymap, k, k) => d[k] for k in keys(d)) -function rekey(d::NamedTuple, keymap) - new_keys = map(k -> get(keymap, k, k), keys(d)) - return NamedTuple{new_keys}(values(d)) -end diff --git a/test/InferenceObjects/convert_dataset.jl b/test/InferenceObjects/convert_dataset.jl deleted file mode 100644 index 37b46943..00000000 --- a/test/InferenceObjects/convert_dataset.jl +++ /dev/null @@ -1,58 +0,0 @@ -using ArviZ.InferenceObjects, DimensionalData, Test - -@testset "conversion to Dataset" begin - @testset "conversion" begin - J = 8 - K = 6 - L = 3 - nchains = 4 - ndraws = 500 - vars = (a=randn(nchains, ndraws, J), b=randn(nchains, ndraws, K, L)) - coords = (bi=2:(K + 1), draw=1:2:1_000) - dims = (b=[:bi, nothing],) - attrs = Dict(:mykey => 5) - ds = namedtuple_to_dataset(vars; library="MyLib", coords, dims, attrs) - @test convert(Dataset, ds) === ds - ds2 = convert(Dataset, [1.0, 2.0, 3.0, 4.0]) - @test ds2 isa Dataset - @test ds2 == convert_to_dataset([1.0, 2.0, 3.0, 4.0]) - @test convert(DimensionalData.DimStack, ds) === parent(ds) - end - - @testset "convert_to_dataset" begin - nchains = 4 - ndraws = 100 - nshared = 3 - xdims = (:chain, :draw, :shared) - x = DimArray(randn(nchains, ndraws, nshared), xdims) - ydims = (:chain, :draw, Dim{:ydim1}(Any["a", "b"]), Dim{:shared}) - y = DimArray(randn(nchains, ndraws, 2, nshared), ydims) - metadata = Dict(:prop1 => "val1", :prop2 => "val2") - ds = Dataset((; x, y); metadata) - - @testset "convert_to_dataset(::Dataset; kwargs...)" begin - @test convert_to_dataset(ds) isa Dataset - @test convert_to_dataset(ds) === ds - end - - @testset "convert_to_dataset(::$T; kwargs...)" for T in (Dict, NamedTuple) - data = (x=randn(4, 100), y=randn(4, 100, 2)) - if T <: Dict - data = T(pairs(data)) - end - ds2 = convert_to_dataset(data) - @test ds2 isa Dataset - @test ds2.x == data[:x] - @test DimensionalData.name(DimensionalData.dims(ds2.x)) == (:chain, :draw) - @test ds2.y == data[:y] - @test DimensionalData.name(DimensionalData.dims(ds2.y)) == - (:chain, :draw, :y_dim_1) - end - - @testset "convert_to_dataset(::InferenceData; kwargs...)" begin - idata = random_data() - @test convert_to_dataset(idata) === idata.posterior - @test convert_to_dataset(idata; group=:prior) === idata.prior - end - end -end diff --git a/test/InferenceObjects/convert_inference_data.jl b/test/InferenceObjects/convert_inference_data.jl deleted file mode 100644 index f5d48dd2..00000000 --- a/test/InferenceObjects/convert_inference_data.jl +++ /dev/null @@ -1,84 +0,0 @@ -using ArviZ.InferenceObjects, DimensionalData, Test - -@testset "conversion to InferenceData" begin - @testset "default_var_name" begin - x = randn(4, 5) - @test InferenceObjects.default_var_name(x) === :x - @test InferenceObjects.default_var_name(DimensionalData.DimArray(x, (:a, :b))) === - :x - @test InferenceObjects.default_var_name( - DimensionalData.DimArray(x, (:a, :b); name=:y) - ) === :y - end - - @testset "conversion" begin - var_names = (:a, :b) - data_names = (:y,) - coords = ( - chain=1:4, draw=1:100, shared=["s1", "s2", "s3"], dima=1:4, dimb=2:6, dimy=1:5 - ) - dims = (a=(:shared, :dima), b=(:shared, :dimb), y=(:shared, :dimy)) - metadata = (inference_library="PPL",) - posterior = random_dataset(var_names, dims, coords, metadata) - prior = random_dataset(var_names, dims, coords, metadata) - observed_data = random_dataset(data_names, dims, coords, metadata) - group_data = (; prior, observed_data, posterior) - idata = InferenceData(group_data) - @test convert(InferenceData, idata) === idata - @test convert(NamedTuple, idata) === parent(idata) - @test NamedTuple(idata) === parent(idata) - a = idata.posterior.a - @test convert(InferenceData, a) isa InferenceData - @test convert(InferenceData, a).posterior.a == a - end - - @testset "convert_to_inference_data" begin - @testset "convert_to_inference_data(::AbstractDimStack)" begin - ds = namedtuple_to_dataset((x=randn(4, 10), y=randn(4, 10, 5))) - idata1 = convert_to_inference_data(ds; group=:prior) - @test InferenceObjects.groupnames(idata1) == (:prior,) - idata2 = InferenceData(; prior=ds) - @test idata2 == idata1 - idata3 = convert_to_inference_data(parent(ds); group=:prior) - @test idata3 == idata1 - end - - @testset "convert_to_inference_data(::$T)" for T in (NamedTuple, Dict) - data = (A=randn(2, 10, 2), B=randn(2, 10, 5, 2)) - if T <: Dict - data = Dict(pairs(data)) - end - idata = convert_to_inference_data(data) - check_idata_schema(idata) - @test InferenceObjects.groupnames(idata) == (:posterior,) - posterior = idata.posterior - @test posterior.A == data[:A] - @test posterior.B == data[:B] - idata2 = convert_to_inference_data(data; group=:prior) - check_idata_schema(idata2) - @test InferenceObjects.groupnames(idata2) == (:prior,) - @test idata2.prior == idata.posterior - end - - @testset "convert_to_inference_data(::$T)" for T in - (Array, DimensionalData.DimArray) - data = randn(2, 10, 2) - if T <: DimensionalData.DimArray - data = DimensionalData.DimArray(data, (:a, :b, :c); name=:y) - end - idata = convert_to_inference_data(data) - check_idata_schema(idata) - @test InferenceObjects.groupnames(idata) == (:posterior,) - posterior = idata.posterior - if T <: DimensionalData.DimArray - @test posterior.y == data - else - @test posterior.x == data - end - idata2 = convert_to_inference_data(data; group=:prior) - check_idata_schema(idata2) - @test InferenceObjects.groupnames(idata2) == (:prior,) - @test idata2.prior == idata.posterior - end - end -end diff --git a/test/InferenceObjects/dataset.jl b/test/InferenceObjects/dataset.jl deleted file mode 100644 index f4ef9e31..00000000 --- a/test/InferenceObjects/dataset.jl +++ /dev/null @@ -1,156 +0,0 @@ -using ArviZ.InferenceObjects, DimensionalData, OrderedCollections, Test - -@testset "dataset" begin - @testset "Dataset" begin - @testset "Constructors" begin - nchains = 4 - ndraws = 100 - nshared = 3 - xdims = (:chain, :draw, :shared) - x = DimArray(randn(nchains, ndraws, nshared), xdims) - ydims = (:chain, :draw, :ydim1, :shared) - y = DimArray(randn(nchains, ndraws, 2, nshared), ydims) - metadata = Dict(:prop1 => "val1", :prop2 => "val2") - - @testset "from NamedTuple" begin - data = (; x, y) - ds = Dataset(data; metadata) - @test ds isa Dataset - @test DimensionalData.data(ds) == data - for dim in xdims - @test DimensionalData.hasdim(ds, dim) - end - for dim in ydims - @test DimensionalData.hasdim(ds, dim) - end - for (var_name, dims) in ((:x, xdims), (:y, ydims)) - da = ds[var_name] - @test DimensionalData.name(da) === var_name - @test DimensionalData.name(DimensionalData.dims(da)) === dims - end - @test DimensionalData.metadata(ds) == metadata - end - - @testset "from DimArrays" begin - data = ( - DimensionalData.rebuild(x; name=:x), DimensionalData.rebuild(y; name=:y) - ) - ds = Dataset(data...; metadata) - @test ds isa Dataset - @test values(DimensionalData.data(ds)) == data - for dim in xdims - @test DimensionalData.hasdim(ds, dim) - end - for dim in ydims - @test DimensionalData.hasdim(ds, dim) - end - for (var_name, dims) in ((:x, xdims), (:y, ydims)) - da = ds[var_name] - @test DimensionalData.name(da) === var_name - @test DimensionalData.name(DimensionalData.dims(da)) === dims - end - @test DimensionalData.metadata(ds) == metadata - end - - @testset "idempotent" begin - ds = Dataset((; x, y); metadata) - @test Dataset(ds) === ds - end - - @testset "errors with mismatched dimensions" begin - data_bad = ( - x=DimArray(randn(3, 100, 3), (:chains, :draws, :shared)), - y=DimArray(randn(4, 100, 2, 3), (:chains, :draws, :ydim1, :shared)), - ) - @test_throws Exception Dataset(data_bad) - end - end - - nchains = 4 - ndraws = 100 - nshared = 3 - xdims = (:chain, :draw, :shared) - x = DimArray(randn(nchains, ndraws, nshared), xdims) - ydims = (:chain, :draw, :ydim1, :shared) - y = DimArray(randn(nchains, ndraws, 2, nshared), ydims) - metadata = Dict(:prop1 => "val1", :prop2 => "val2") - ds = Dataset((; x, y); metadata) - - @testset "parent" begin - @test parent(ds) isa DimStack - @test parent(ds) == ds - end - - @testset "properties" begin - @test propertynames(ds) == (:x, :y) - @test ds.x isa DimArray - @test ds.x == x - @test ds.y isa DimArray - @test ds.y == y - end - - @testset "getindex" begin - @test ds[:x] isa DimArray - @test ds[:x] == x - @test ds[:y] isa DimArray - @test ds[:y] == y - end - - @testset "copy/deepcopy" begin - @test copy(ds) == ds - @test deepcopy(ds) == ds - end - - @testset "attributes" begin - @test InferenceObjects.attributes(ds) == metadata - dscopy = deepcopy(ds) - InferenceObjects.setattribute!(dscopy, :prop3, "val3") - @test InferenceObjects.attributes(dscopy)[:prop3] == "val3" - @test_deprecated InferenceObjects.setattribute!(dscopy, "prop3", "val4") - @test InferenceObjects.attributes(dscopy)[:prop3] == "val4" - end - end - - @testset "namedtuple_to_dataset" begin - J = 8 - K = 6 - L = 3 - nchains = 4 - ndraws = 500 - vars = (a=randn(nchains, ndraws, J), b=randn(nchains, ndraws, K, L)) - coords = (bi=2:(K + 1), draw=1:2:1_000) - dims = (b=[:bi, nothing],) - expected_dims = ( - a=( - Dimensions.Dim{:chain}(1:nchains), - Dimensions.Dim{:draw}(1:2:1_000), - Dimensions.Dim{:a_dim_1}(1:J), - ), - b=( - Dimensions.Dim{:chain}(1:nchains), - Dimensions.Dim{:draw}(1:2:1_000), - Dimensions.Dim{:bi}(2:(K + 1)), - Dimensions.Dim{:b_dim_2}(1:L), - ), - ) - attrs = Dict(:mykey => 5) - @test_broken @inferred namedtuple_to_dataset( - vars; library="MyLib", coords, dims, attrs - ) - ds = namedtuple_to_dataset(vars; library="MyLib", coords, dims, attrs) - @test ds isa Dataset - for (var_name, var_data) in pairs(DimensionalData.layers(ds)) - @test var_data isa DimensionalData.DimArray - @test var_name === DimensionalData.name(var_data) - @test var_data == vars[var_name] - _dims = DimensionalData.dims(var_data) - @test _dims == expected_dims[var_name] - end - metadata = DimensionalData.metadata(ds) - @test metadata isa OrderedDict - @test haskey(metadata, :created_at) - @test metadata[:inference_library] == "MyLib" - @test !haskey(metadata, :inference_library_version) - @test metadata[:mykey] == 5 - end -end diff --git a/test/InferenceObjects/dimensions.jl b/test/InferenceObjects/dimensions.jl deleted file mode 100644 index 7b3be715..00000000 --- a/test/InferenceObjects/dimensions.jl +++ /dev/null @@ -1,115 +0,0 @@ -using ArviZ.InferenceObjects, DimensionalData, OffsetArrays, Test - -@testset "dimension-related functions" begin - @testset "has_all_sample_dims" begin - @test !InferenceObjects.has_all_sample_dims((:chain,)) - @test !InferenceObjects.has_all_sample_dims((:draw,)) - @test InferenceObjects.has_all_sample_dims((:chain, :draw)) - @test InferenceObjects.has_all_sample_dims((:draw, :chain)) - @test InferenceObjects.has_all_sample_dims((:draw, :chain, :x)) - - @test !InferenceObjects.has_all_sample_dims((Dim{:chain},)) - @test !InferenceObjects.has_all_sample_dims((Dim{:draw},)) - @test InferenceObjects.has_all_sample_dims((Dim{:chain}, Dim{:draw})) - @test InferenceObjects.has_all_sample_dims((Dim{:draw}, Dim{:chain})) - @test InferenceObjects.has_all_sample_dims((Dim{:draw}, Dim{:chain}, Dim{:x})) - - @test !InferenceObjects.has_all_sample_dims((Dim{:chain}(1:4),)) - @test !InferenceObjects.has_all_sample_dims((Dim{:draw}(1:10),)) - @test InferenceObjects.has_all_sample_dims((Dim{:chain}(1:4), Dim{:draw}(1:10))) - @test InferenceObjects.has_all_sample_dims((Dim{:draw}(1:10), Dim{:chain}(1:4))) - @test InferenceObjects.has_all_sample_dims(( - Dim{:draw}(1:10), Dim{:chain}(1:4), Dim{:x}(1:2) - )) - end - - @testset "as_dimension" begin - coords = (;) - @testset for dim in (:foo, Dim{:foo}, Dim{:foo,Colon}) - @test InferenceObjects.as_dimension(dim, coords, 2:10) === Dim{:foo}(2:10) - dim === :foo || @inferred InferenceObjects.as_dimension(dim, coords, 2:10) - end - @test InferenceObjects.as_dimension(Dim{:foo}(1:5), coords, 2:10) === Dim{:foo}(1:5) - coords = (; foo=3:8) - @testset for dim in (:foo, Dim{:foo}, Dim{:foo,Colon}, Dim{:foo}(1:5)) - @test InferenceObjects.as_dimension(dim, coords, 2:10) === Dim{:foo}(3:8) - dim === :foo || @inferred InferenceObjects.as_dimension(dim, coords, 2:10) - end - end - - @testset "generate_dims" begin - x = OffsetArray(randn(4, 10, 2, 3), 0:3, 11:20, -1:0, 2:4) - gdims = @inferred NTuple{4,Dimensions.Dimension} InferenceObjects.generate_dims( - x, :x - ) - @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) == (0:3, 11:20, -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) == (0:3, 11:20, -1:0, 2:4) - - gdims = @inferred NTuple{4,Dimensions.Dimension} InferenceObjects.generate_dims( - x, :z; dims=(:c, :d), default_dims=(:chain, :draw) - ) - @test gdims isa NTuple{4,Dim} - @test Dimensions.name(gdims) === (:chain, :draw, :c, :d) - @test Dimensions.index(gdims) == (0:3, 11:20, -1:0, 2:4) - end - - @testset "array_to_dim_array" begin - x = OffsetArray(randn(4, 10, 2, 3), 0:3, 11:20, -1:0, 2:4) - da = @inferred DimArray InferenceObjects.array_to_dimarray(x, :x) - @test da == x - @test DimensionalData.name(da) === :x - 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) == (0:3, 11:20, -1:0, 2:4) - - da = @inferred DimArray InferenceObjects.array_to_dimarray(x, :y; dims=(:a, :b)) - @test da == x - @test DimensionalData.name(da) === :y - 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) == (0:3, 11:20, -1:0, 2:4) - - da = @inferred DimArray InferenceObjects.array_to_dimarray( - x, :z; dims=(:c, :d), default_dims=(:chain, :draw) - ) - @test da == x - @test DimensionalData.name(da) === :z - gdims = Dimensions.dims(da) - @test gdims isa NTuple{4,Dim} - @test Dimensions.name(gdims) === (:chain, :draw, :c, :d) - @test Dimensions.index(gdims) == (0:3, 11:20, -1:0, 2:4) - 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_sel isa DimArray - @test Dimensions.dims(da_sel) == (Dim{:a}(["foo"]),) - @test da_sel == da[a=At(["foo"])] - - 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 - end - - @testset "index_to_indices" begin - @test InferenceObjects.index_to_indices(1) == [1] - @test InferenceObjects.index_to_indices(2) == [2] - @test InferenceObjects.index_to_indices([2]) == [2] - @test InferenceObjects.index_to_indices(1:10) === 1:10 - @test InferenceObjects.index_to_indices(At(1)) === InferenceObjects.AsSlice(At(1)) - @test InferenceObjects.index_to_indices(At(1)) === InferenceObjects.AsSlice(At(1)) - end -end diff --git a/test/InferenceObjects/from_namedtuple.jl b/test/InferenceObjects/from_namedtuple.jl deleted file mode 100644 index 506c7fec..00000000 --- a/test/InferenceObjects/from_namedtuple.jl +++ /dev/null @@ -1,70 +0,0 @@ -@testset "from_namedtuple" begin - nchains, ndraws = 4, 10 - sizes = (x=(), y=(2,), z=(3, 5)) - dims = (y=[:yx], z=[:zx, :zy]) - coords = (yx=["y1", "y2"], zx=1:3, zy=1:5) - - nts = [ - "NamedTuple" => map(sz -> randn(nchains, ndraws, sz...), sizes), - "Vector{NamedTuple}" => [map(sz -> randn(ndraws, sz...), sizes) for _ in 1:nchains], - "Matrix{NamedTuple}" => - [map(sz -> randn(sz...), sizes) for _ in 1:nchains, _ in 1:ndraws], - "Vector{Vector{NamedTuple}}" => - [[map(sz -> randn(sz...), sizes) for _ in 1:ndraws] for _ in 1:nchains], - ] - - @testset "posterior::$(type)" for (type, nt) in nts - @test_broken @inferred from_namedtuple(nt; dims, coords, library="MyLib") - idata1 = from_namedtuple(nt; dims, coords, library="MyLib") - idata2 = convert_to_inference_data(nt; dims, coords, library="MyLib") - test_idata_approx_equal(idata1, idata2) - end - - @testset "$(group)" for group in [ - :posterior_predictive, :sample_stats, :predictions, :log_likelihood - ] - library = "MyLib" - @testset "::$(type)" for (type, nt) in nts - idata1 = from_namedtuple(nt; group => nt, dims, coords, library) - test_idata_group_correct(idata1, group, keys(sizes); library, dims, coords) - - idata2 = from_namedtuple(nt; group => (:x,), dims, coords, library) - test_idata_group_correct(idata2, :posterior, (:y, :z); library, dims, coords) - test_idata_group_correct(idata2, group, (:x,); library, dims, coords) - end - end - - @testset "$(group)" for group in [:prior_predictive, :sample_stats_prior] - library = "MyLib" - @testset "::$(type)" for (type, nt) in nts - idata1 = from_namedtuple(; prior=nt, group => nt, dims, coords, library) - test_idata_group_correct(idata1, :prior, keys(sizes); library, dims, coords) - test_idata_group_correct(idata1, group, keys(sizes); library, dims, coords) - - idata2 = from_namedtuple(; prior=nt, group => (:x,), dims, coords, library) - test_idata_group_correct(idata2, :prior, (:y, :z); library, dims, coords) - test_idata_group_correct(idata2, group, (:x,); library, dims, coords) - end - end - - @testset "$(group)" for group in - [:observed_data, :constant_data, :predictions_constant_data] - _, nt = nts[1] - library = "MyLib" - dims = (; w=[:wx]) - coords = (; wx=1:2) - idata1 = from_namedtuple(nt; group => (w=[1.0, 2.0],), dims, coords, library) - test_idata_group_correct(idata1, :posterior, keys(sizes); library, dims, coords) - test_idata_group_correct( - idata1, group, (:w,); library, dims, coords, default_dims=() - ) - - # ensure that dims are matched to named tuple keys - # https://github.com/arviz-devs/ArviZ.jl/issues/96 - idata2 = from_namedtuple(nt; group => (w=[1.0, 2.0],), dims, coords, library) - test_idata_group_correct(idata2, :posterior, keys(sizes); library, dims, coords) - test_idata_group_correct( - idata2, group, (:w,); library, dims, coords, default_dims=() - ) - end -end diff --git a/test/InferenceObjects/inference_data.jl b/test/InferenceObjects/inference_data.jl deleted file mode 100644 index a8e3ab16..00000000 --- a/test/InferenceObjects/inference_data.jl +++ /dev/null @@ -1,127 +0,0 @@ -using ArviZ.InferenceObjects, DimensionalData, Test - -@testset "InferenceData" begin - var_names = (:a, :b) - data_names = (:y,) - coords = ( - chain=1:4, draw=1:100, shared=["s1", "s2", "s3"], dima=1:4, dimb=2:6, dimy=1:5 - ) - dims = (a=(:shared, :dima), b=(:shared, :dimb), y=(:shared, :dimy)) - metadata = (inference_library="PPL",) - posterior = random_dataset(var_names, dims, coords, metadata) - prior = random_dataset(var_names, dims, coords, metadata) - observed_data = random_dataset(data_names, dims, coords, metadata) - group_data = (; prior, observed_data, posterior) - group_data_ordered = (; posterior, prior, observed_data) - - @testset "constructors" begin - idata = @inferred(InferenceData(group_data)) - @test idata isa InferenceData - @test getfield(idata, :groups) === group_data_ordered - - @test InferenceData(; group_data...) == idata - @test InferenceData(idata) === idata - end - - idata = InferenceData(group_data) - - @testset "properties" begin - @test propertynames(idata) === propertynames(group_data_ordered) - @test getproperty(idata, :posterior) === posterior - @test getproperty(idata, :prior) === prior - @test hasproperty(idata, :posterior) - @test hasproperty(idata, :prior) - @test !hasproperty(idata, :prior_predictive) - end - - @testset "iteration" begin - @test keys(idata) === keys(group_data_ordered) - @test haskey(idata, :posterior) - @test haskey(idata, :prior) - @test !haskey(idata, :log_likelihood) - @test values(idata) === values(group_data_ordered) - @test pairs(idata) isa Base.Iterators.Pairs - @test pairs(idata) === pairs(group_data_ordered) - @test length(idata) == length(group_data_ordered) - @test iterate(idata) === iterate(group_data_ordered) - for i in 1:(length(idata) + 1) - @test iterate(idata, i) === iterate(group_data_ordered, i) - end - @test eltype(idata) <: Dataset - @test collect(idata) isa Vector{<:Dataset} - end - - @testset "indexing" begin - @test idata[:posterior] === posterior - @test idata[:prior] === prior - @test idata[1] === posterior - @test idata[2] === prior - - 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] - - if VERSION ≥ v"1.7" - 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"] - end - - ds_sel = idata[:posterior, chain=1] - @test ds_sel isa Dataset - @test !hasdim(ds_sel, :chain) - - idata2 = Base.setindex(idata, posterior, :warmup_posterior) - @test keys(idata2) === (keys(idata)..., :warmup_posterior) - @test idata2[:warmup_posterior] === posterior - end - - @testset "isempty" begin - @test !isempty(idata) - @test isempty(InferenceData()) - end - - @testset "groups" begin - @test InferenceObjects.groups(idata) === group_data_ordered - @test InferenceObjects.groups(InferenceData(; prior)) === (; prior) - end - - @testset "hasgroup" begin - @test InferenceObjects.hasgroup(idata, :posterior) - @test InferenceObjects.hasgroup(idata, :prior) - @test !InferenceObjects.hasgroup(idata, :prior_predictive) - end - - @testset "groupnames" begin - @test InferenceObjects.groupnames(idata) === propertynames(group_data_ordered) - @test InferenceObjects.groupnames(InferenceData(; posterior)) === (:posterior,) - end - - @testset "show" begin - @testset "plain" begin - text = sprint(show, MIME("text/plain"), idata) - @test text == """ - InferenceData with groups: - > posterior - > prior - > observed_data""" - end - - @testset "html" begin - # TODO: improve test - text = sprint(show, MIME("text/html"), idata) - @test text isa String - @test occursin("InferenceData", text) - @test occursin("Dataset", text) - end - end -end diff --git a/test/InferenceObjects/runtests.jl b/test/InferenceObjects/runtests.jl deleted file mode 100644 index 20970b1a..00000000 --- a/test/InferenceObjects/runtests.jl +++ /dev/null @@ -1,12 +0,0 @@ -using ArviZ.InferenceObjects, Test - -@testset "InferenceObjects" begin - include("test_helpers.jl") - include("utils.jl") - include("dimensions.jl") - include("dataset.jl") - include("inference_data.jl") - include("convert_dataset.jl") - include("convert_inference_data.jl") - include("from_namedtuple.jl") -end diff --git a/test/InferenceObjects/test_helpers.jl b/test/InferenceObjects/test_helpers.jl deleted file mode 100644 index 68ad03e4..00000000 --- a/test/InferenceObjects/test_helpers.jl +++ /dev/null @@ -1,123 +0,0 @@ -using ArviZ.InferenceObjects, DimensionalData - -function random_dim_array(var_name, dims, coords, default_dims=()) - _dims = (default_dims..., dims...) - _coords = NamedTuple{_dims}(getproperty.(Ref(coords), _dims)) - size = map(length, values(_coords)) - data = randn(size) - return DimArray(data, _coords; name=var_name) -end - -function random_dim_stack(var_names, dims, coords, metadata, default_dims=(:chain, :draw)) - dim_arrays = map(var_names) do k - return random_dim_array(k, getproperty(dims, k), coords, default_dims) - end - return DimStack(dim_arrays...; metadata) -end - -random_dataset(args...) = Dataset(random_dim_stack(args...)) - -function random_data() - var_names = (:a, :b) - data_names = (:y,) - coords = ( - chain=1:4, draw=1:100, shared=["s1", "s2", "s3"], dima=1:4, dimb=2:6, dimy=1:5 - ) - dims = (a=(:shared, :dima), b=(:shared, :dimb), y=(:shared, :dimy)) - metadata = (inference_library="PPL",) - posterior = random_dataset(var_names, dims, coords, metadata) - posterior_predictive = random_dataset(data_names, dims, coords, metadata) - prior = random_dataset(var_names, dims, coords, metadata) - prior_predictive = random_dataset(data_names, dims, coords, metadata) - observed_data = random_dataset(data_names, dims, coords, metadata, ()) - return InferenceData(; - posterior, posterior_predictive, prior, prior_predictive, observed_data - ) -end - -function check_idata_schema(idata) - @testset "check InferenceData schema" begin - @test idata isa InferenceData - @testset "$name" for (name, group) in pairs(idata) - @test name ∈ InferenceObjects.SCHEMA_GROUPS - @test group isa Dataset - for (var_name, var_data) in pairs(group) - @test var_data isa DimensionalData.AbstractDimArray - if InferenceObjects.has_all_sample_dims(var_data) - @test Dimensions.name(Dimensions.dims(var_data)[1]) === :chain - @test Dimensions.name(Dimensions.dims(var_data)[2]) === :draw - end - end - @testset "attributes" begin - attrs = InferenceObjects.attributes(group) - @test attrs isa AbstractDict{Symbol,Any} - @test :created_at in keys(attrs) - end - end - end -end - -function test_idata_approx_equal( - idata1::InferenceData, idata2::InferenceData; check_metadata=true -) - @test InferenceObjects.groupnames(idata1) === InferenceObjects.groupnames(idata2) - for (ds1, ds2) in zip(idata1, idata2) - @test issetequal(keys(ds1), keys(ds2)) - for var_name in keys(ds1) - da1 = ds1[var_name] - da2 = ds2[var_name] - @test da1 ≈ da2 - dims1 = DimensionalData.dims(da1) - dims2 = DimensionalData.dims(da2) - @test DimensionalData.name(dims1) == DimensionalData.name(dims2) - @test DimensionalData.index(dims1) == DimensionalData.index(dims2) - end - if check_metadata - metadata1 = DimensionalData.metadata(ds1) - metadata2 = DimensionalData.metadata(ds2) - @test issetequal(keys(metadata1), keys(metadata2)) - for k in keys(metadata1) - Symbol(k) === :created_at && continue - @test metadata1[k] == metadata2[k] - end - end - end -end - -function test_idata_group_correct( - idata, - group_name, - var_names; - library=nothing, - dims=(;), - coords=(;), - default_dims=(:chain, :draw), -) - @test idata isa InferenceData - @test InferenceObjects.hasgroup(idata, group_name) - ds = getproperty(idata, group_name) - @test ds isa Dataset - @test issetequal(keys(ds), var_names) - for name in var_names - da = ds[name] - @test DimensionalData.name(da) === name - _dims = DimensionalData.dims(da) - _dim_names_exp = (default_dims..., get(dims, name, ())...) - _dim_names = DimensionalData.name(_dims) - @test issubset(_dim_names_exp, _dim_names) - for dim in _dims - dim_name = DimensionalData.name(dim) - if dim_name ∈ keys(coords) - @test coords[dim_name] == DimensionalData.index(dim) - end - end - end - metadata = DimensionalData.metadata(ds) - if library !== nothing - @test metadata[:inference_library] == library - end - for k in [:created_at] - @test k in keys(metadata) - end - return nothing -end diff --git a/test/InferenceObjects/utils.jl b/test/InferenceObjects/utils.jl deleted file mode 100644 index c3f7e59e..00000000 --- a/test/InferenceObjects/utils.jl +++ /dev/null @@ -1,44 +0,0 @@ -using ArviZ, Test -using ArviZ.InferenceObjects - -module TestSubModule end - -@testset "utils" begin - @testset "flatten" begin - @test InferenceObjects.flatten([1, 2]) == [1, 2] - @test InferenceObjects.flatten([[1, 2]]) == [1 2] - @test InferenceObjects.flatten([[1, 3], [2, 4]]) == reshape(1:4, 2, 2) - @test InferenceObjects.flatten(1) === 1 - @test InferenceObjects.flatten(1:5) isa Array - end - - @testset "namedtuple_of_arrays" begin - @test InferenceObjects.namedtuple_of_arrays((x=3, y=4)) === (x=3, y=4) - @test InferenceObjects.namedtuple_of_arrays([(x=3, y=4), (x=5, y=6)]) == - (x=[3, 5], y=[4, 6]) - @test InferenceObjects.namedtuple_of_arrays([ - [(x=3, y=4), (x=5, y=6)], [(x=7, y=8), (x=9, y=10)] - ]) == (x=[3 5; 7 9], y=[4 6; 8 10]) - end - - @testset "package_version" begin - @test InferenceObjects.package_version(ArviZ) isa VersionNumber - @test InferenceObjects.package_version(TestSubModule) === nothing - end - - @testset "rekey" begin - orig = (x=3, y=4, z=5) - keymap = (x=:y, y=:a) - @testset "NamedTuple" begin - new = @inferred NamedTuple InferenceObjects.rekey(orig, keymap) - @test new isa NamedTuple - @test new == (y=3, a=4, z=5) - end - @testset "Dict" begin - orig_dict = Dict(pairs(orig)) - new = @inferred InferenceObjects.rekey(orig_dict, keymap) - @test new isa typeof(orig_dict) - @test new == Dict(:y => 3, :a => 4, :z => 5) - end - end -end diff --git a/test/runtests.jl b/test/runtests.jl index 9e624a93..5fdba0c4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,8 +1,6 @@ using ArviZ using Test -include("InferenceObjects/runtests.jl") - @testset "ArviZ" begin include("helpers.jl") include("test_rcparams.jl") diff --git a/test/test_mcmcchains.jl b/test/test_mcmcchains.jl index 268c8853..ac19268c 100644 --- a/test/test_mcmcchains.jl +++ b/test/test_mcmcchains.jl @@ -1,5 +1,5 @@ using MCMCChains: MCMCChains -using CmdStan +using CmdStan, OrderedCollections const noncentered_schools_stan_model = """ data {