Skip to content

Commit

Permalink
turn most deps into weakdeps
Browse files Browse the repository at this point in the history
  • Loading branch information
aplavin committed Mar 2, 2024
1 parent b333dbe commit ab577cd
Show file tree
Hide file tree
Showing 15 changed files with 156 additions and 87 deletions.
29 changes: 28 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"

[weakdeps]
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
CovarianceEstimation = "587fd27a-f159-11e8-2dae-1979310e6154"
InvertedIndices = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
LazyStack = "1fad7336-0346-5a1a-a56f-a06ba010965b"
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"

[extensions]
AbstractFFTsExt = "AbstractFFTs"
ChainRulesCoreExt = "ChainRulesCore"
CovarianceEstimationExt = "CovarianceEstimation"
InvertedIndicesExt = "InvertedIndices"
LazyStackExt = "LazyStack"
OffsetArraysExt = "OffsetArrays"
StatisticsExt = "Statistics"
StatsBaseExt = "StatsBase"

[compat]
AbstractFFTs = "0.5, 1.0"
BenchmarkTools = "0.5, 1.0"
Expand All @@ -36,15 +56,22 @@ julia = "1.6"

[extras]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
ChainRulesTestUtils = "cdddcdb0-9152-4a09-a978-84456f9df70a"
CovarianceEstimation = "587fd27a-f159-11e8-2dae-1979310e6154"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000"
InvertedIndices = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
LazyStack = "1fad7336-0346-5a1a-a56f-a06ba010965b"
NamedArrays = "86f7a689-2022-50b4-a561-43c23ac3c673"
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
UniqueVectors = "2fbcfb34-fd0c-5fbb-b5d7-e826d8f5b0a9"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[targets]
test = ["BenchmarkTools", "ChainRulesTestUtils", "DataFrames", "Dates", "FiniteDifferences", "FFTW", "NamedArrays", "Test", "UniqueVectors", "Unitful"]
test = ["BenchmarkTools", "CovarianceEstimation", "ChainRulesCore", "ChainRulesTestUtils", "DataFrames", "Dates", "FiniteDifferences", "FFTW", "InvertedIndices", "LazyStack", "NamedArrays", "OffsetArrays", "Test", "Statistics", "StatsBase", "UniqueVectors", "Unitful"]
8 changes: 6 additions & 2 deletions src/fft.jl → ext/AbstractFFTsExt.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
module AbstractFFTsExt

using AxisKeys: KeyedArray, NdaKa, axiskeys, keyless, NamedDims
using AbstractFFTs

#=
Simple support for FFTs using:
Expand All @@ -7,8 +11,6 @@ Does not (yet) cover plan_fft & friends,
because extracting the dimensions from those is tricky
=#

using AbstractFFTs

for fun in [:fft, :ifft, :bfft, :rfft]
@eval function AbstractFFTs.$fun(A::Union{KeyedArray,NdaKa}, dims = ntuple(+,ndims(A)))
numerical_dims = NamedDims.dim(A, dims)
Expand Down Expand Up @@ -80,3 +82,5 @@ function irfft_un_freq(x, len)
s = inv(step(x) * len)
range(zero(s), step = s, length = len)
end

end
5 changes: 5 additions & 0 deletions src/chainrules.jl → ext/ChainRulesCoreExt.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
module ChainRulesCoreExt

using AxisKeys: KeyedArray, KaNda, NdaKa, keyless, keyless_unname, axiskeys, named_axiskeys, wrapdims
using ChainRulesCore

function ChainRulesCore.ProjectTo(x::Union{KaNda, NdaKa})
Expand All @@ -19,3 +22,5 @@ function ChainRulesCore.rrule(::typeof(keyless_unname), x)
pb(y) = _KeyedArray_pullback(y, ProjectTo(x))
return keyless_unname(x), pb
end

end
33 changes: 33 additions & 0 deletions ext/CovarianceEstimationExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module CovarianceEstimationExt

using AxisKeys: KeyedArray, KeyedMatrix, NamedDims, NamedDimsArray, axiskeys, dimnames, keyless_unname, hasnames
using CovarianceEstimation
using CovarianceEstimation: AbstractWeights
using CovarianceEstimation.Statistics

# Since we get ambiguity errors with specific implementations we need to wrap each supported method
# A better approach might be to add `NamedDims` support to CovarianceEstimators.jl in the future.

estimators = [
:SimpleCovariance,
:LinearShrinkage,
:DiagonalUnitVariance,
:DiagonalCommonVariance,
:DiagonalUnequalVariance,
:CommonCovariance,
:PerfectPositiveCorrelation,
:ConstantCorrelation,
:AnalyticalNonlinearShrinkage,
]
for estimator in estimators
@eval function Statistics.cov(ce::$estimator, A::KeyedMatrix, wv::Vararg{AbstractWeights}; dims=1, kwargs...)
d = NamedDims.dim(A, dims)
data = cov(ce, keyless_unname(A), wv...; dims=d, kwargs...)
L1 = dimnames(A, 3 - d)
data2 = hasnames(A) ? NamedDimsArray(data, (L1, L1)) : data
K1 = axiskeys(A, 3 - d)
KeyedArray(data2, (copy(K1), copy(K1)))
end
end

end
10 changes: 10 additions & 0 deletions ext/InvertedIndicesExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module InvertedIndicesExt

using AxisKeys
using InvertedIndices

# needs only Base.to_indices in struct.jl to work,
# plus this to work when used in round brackets:
AxisKeys.findindex(not::InvertedIndex, r::AbstractVector) = Base.unalias(r, not)

end
4 changes: 4 additions & 0 deletions src/stack.jl → ext/LazyStackExt.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
module LazyStackExt

using AxisKeys: KeyedArray, NamedDims, NamedDimsArray, axiskeys, hasnames, dimnames, keys_or_axes
import LazyStack

# for stack_iter
Expand Down Expand Up @@ -57,3 +59,5 @@ function LazyStack.getnames(xs::AbstractArray{<:KeyedArray{T,N,IT}}) where {T,N,
out_names = hasnames(xs) ? dimnames(xs) : NamedDims.dimnames(xs)
(NamedDims.dimnames(IT)..., out_names...)
end

end
9 changes: 9 additions & 0 deletions ext/OffsetArraysExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module OffsetArraysExt

using AxisKeys
using OffsetArrays

AxisKeys.no_offset(x::OffsetArray) = parent(x)
AxisKeys.shorttype(r::OffsetArray) = "OffsetArray(::" * shorttype(parent(r)) * ",...)"

end
37 changes: 37 additions & 0 deletions ext/StatisticsExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module StatisticsExt

using AxisKeys: KeyedArray, KeyedMatrix, NamedDims, axiskeys
using Statistics

for fun in [:mean, :std, :var] # These don't use mapreduce, but could perhaps be handled better?
@eval function Statistics.$fun(A::KeyedArray; dims=:, kwargs...)
dims === Colon() && return $fun(parent(A); kwargs...)
numerical_dims = NamedDims.dim(A, dims)
data = $fun(parent(A); dims=numerical_dims, kwargs...)
new_keys = ntuple(d -> d in numerical_dims ? Base.OneTo(1) : axiskeys(A,d), ndims(A))
return KeyedArray(data, map(copy, new_keys))#, copy(A.meta))
end
end

# Handle function interface for `mean` only
if VERSION >= v"1.3"
@eval function Statistics.mean(f, A::KeyedArray; dims=:, kwargs...)
dims === Colon() && return mean(f, parent(A); kwargs...)
numerical_dims = NamedDims.dim(A, dims)
data = mean(f, parent(A); dims=numerical_dims, kwargs...)
new_keys = ntuple(d -> d in numerical_dims ? Base.OneTo(1) : axiskeys(A,d), ndims(A))
return KeyedArray(data, map(copy, new_keys))#, copy(A.meta))
end
end

for fun in [:cov, :cor] # Returned the axes work are different for cov and cor
@eval function Statistics.$fun(A::KeyedMatrix; dims=1, kwargs...)
numerical_dim = NamedDims.dim(A, dims)
data = $fun(parent(A); dims=numerical_dim, kwargs...)
# Use same remaining axis for both dimensions of data
rem_key = axiskeys(A, 3-numerical_dim)
KeyedArray(data, (copy(rem_key), copy(rem_key)))
end
end

end
27 changes: 3 additions & 24 deletions src/statsbase.jl → ext/StatsBaseExt.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
module StatsBaseExt

using AxisKeys: KeyedArray, KeyedMatrix, NamedDims, NamedDimsArray, axiskeys, dimnames, keyless_unname, hasnames
using StatsBase
using StatsBase.Statistics

# Support some of the weighted statistics function in StatsBase
# NOTES:
Expand Down Expand Up @@ -55,28 +58,4 @@ for fun in (:std, :var, :cov)
)
end

# Since we get ambiguity errors with specific implementations we need to wrap each supported method
# A better approach might be to add `NamedDims` support to CovarianceEstimators.jl in the future.
using CovarianceEstimation

estimators = [
:SimpleCovariance,
:LinearShrinkage,
:DiagonalUnitVariance,
:DiagonalCommonVariance,
:DiagonalUnequalVariance,
:CommonCovariance,
:PerfectPositiveCorrelation,
:ConstantCorrelation,
:AnalyticalNonlinearShrinkage,
]
for estimator in estimators
@eval function Statistics.cov(ce::$estimator, A::KeyedMatrix, wv::Vararg{AbstractWeights}; dims=1, kwargs...)
d = NamedDims.dim(A, dims)
data = cov(ce, keyless_unname(A), wv...; dims=d, kwargs...)
L1 = dimnames(A, 3 - d)
data2 = hasnames(A) ? NamedDimsArray(data, (L1, L1)) : data
K1 = axiskeys(A, 3 - d)
KeyedArray(data2, (copy(K1), copy(K1)))
end
end
16 changes: 10 additions & 6 deletions src/AxisKeys.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@ include("show.jl")

include("tables.jl") # Tables.jl

include("stack.jl") # LazyStack.jl

include("fft.jl") # AbstractFFTs.jl

include("statsbase.jl") # StatsBase.jl
if !isdefined(Base, :get_extension)
include("../ext/AbstractFFTsExt.jl")
include("../ext/ChainRulesCoreExt.jl")
include("../ext/CovarianceEstimationExt.jl")
include("../ext/InvertedIndicesExt.jl")
include("../ext/LazyStackExt.jl")
include("../ext/OffsetArraysExt.jl")
include("../ext/StatisticsExt.jl")
include("../ext/StatsBaseExt.jl")
end

include("chainrules.jl")
end
32 changes: 0 additions & 32 deletions src/functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,38 +43,6 @@ function Base.mapreduce(f, op, A::KeyedArray; dims=:, kwargs...) # sum, prod, et
return KeyedArray(data, map(copy, new_keys))#, copy(A.meta))
end

using Statistics
for fun in [:mean, :std, :var] # These don't use mapreduce, but could perhaps be handled better?
@eval function Statistics.$fun(A::KeyedArray; dims=:, kwargs...)
dims === Colon() && return $fun(parent(A); kwargs...)
numerical_dims = NamedDims.dim(A, dims)
data = $fun(parent(A); dims=numerical_dims, kwargs...)
new_keys = ntuple(d -> d in numerical_dims ? Base.OneTo(1) : axiskeys(A,d), ndims(A))
return KeyedArray(data, map(copy, new_keys))#, copy(A.meta))
end
end

# Handle function interface for `mean` only
if VERSION >= v"1.3"
@eval function Statistics.mean(f, A::KeyedArray; dims=:, kwargs...)
dims === Colon() && return mean(f, parent(A); kwargs...)
numerical_dims = NamedDims.dim(A, dims)
data = mean(f, parent(A); dims=numerical_dims, kwargs...)
new_keys = ntuple(d -> d in numerical_dims ? Base.OneTo(1) : axiskeys(A,d), ndims(A))
return KeyedArray(data, map(copy, new_keys))#, copy(A.meta))
end
end

for fun in [:cov, :cor] # Returned the axes work are different for cov and cor
@eval function Statistics.$fun(A::KeyedMatrix; dims=1, kwargs...)
numerical_dim = NamedDims.dim(A, dims)
data = $fun(parent(A); dims=numerical_dim, kwargs...)
# Use same remaining axis for both dimensions of data
rem_key = axiskeys(A, 3-numerical_dim)
KeyedArray(data, (copy(rem_key), copy(rem_key)))
end
end

function Base.dropdims(A::KeyedArray; dims)
numerical_dims = NamedDims.dim(A, dims)
data = dropdims(parent(A); dims=dims)
Expand Down
7 changes: 0 additions & 7 deletions src/selectors.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@

using InvertedIndices
# needs only Base.to_indices in struct.jl to work,
# plus this to work when used in round brackets:

findindex(not::InvertedIndex, r::AbstractVector) = Base.unalias(r, not)

using IntervalSets

findindex(int::Interval, r::AbstractVector) =
Expand Down
2 changes: 0 additions & 2 deletions src/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ end
shorttype(r::Vector{T}) where {T} = "Vector{$T}"
shorttype(r::OneTo) = "OneTo{Int}"
shorttype(r::SubArray) = "view(::" * shorttype(parent(r)) * ",...)"
shorttype(r::OffsetArray) = "OffsetArray(::" * shorttype(parent(r)) * ",...)"
function shorttype(r)
bits = split(string(typeof(r)),',')
length(bits) == 1 && return bits[1]
Expand Down Expand Up @@ -122,7 +121,6 @@ function keyed_print_matrix(io::IO, A, reduce_size::Bool=false)
end

no_offset(x) = x
no_offset(x::OffsetArray) = parent(x)

full(x::DenseArray) = x
full(x::AbstractArray) = collect(x) # deal with sparse
Expand Down
4 changes: 1 addition & 3 deletions src/wrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ for fast lookup.
wrapdims(A::AbstractArray, T::Type, r::Union{AbstractVector,Nothing}, keys::Union{AbstractVector,Nothing}...) =
KeyedArray(A, map(T, check_keys(A, (r, keys...))))

using OffsetArrays

function check_keys(A, keys)
ndims(A) == length(keys) || throw(ArgumentError(
"wrong number of key vectors, got $(length(keys)) with ndims(A) == $(ndims(A))"))
Expand All @@ -65,7 +63,7 @@ function check_keys(A, keys)
elseif axes(r,1) == axes(A,d)
r
elseif length(r) == size(A,d)
OffsetArray(r, axes(A,d))
reshape(r, Base.IdentityUnitRange(axes(A,d)))
elseif r isa AbstractRange
l = size(A,d)
r′ = extend_range(r, l)
Expand Down
20 changes: 10 additions & 10 deletions test/_packages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ end

end
@testset "namedarrays" begin
using NamedArrays

# NamedArrays lets us have strings as well as symbols for dimension names. Make sure
# we can handle both.
for dimension_name in (:aa, "aa")
x = NamedArray([1])
setdimnames!(x, dimension_name, 1)
k = wrapdims(x)
@test dimnames(k) == (:aa,)
end
# using NamedArrays

# # NamedArrays lets us have strings as well as symbols for dimension names. Make sure
# # we can handle both.
# for dimension_name in (:aa, "aa")
# x = NamedArray([1])
# setdimnames!(x, dimension_name, 1)
# k = wrapdims(x)
# @test dimnames(k) == (:aa,)
# end
end
@testset "DataFrames" begin
using DataFrames: DataFrame
Expand Down

0 comments on commit ab577cd

Please sign in to comment.