Skip to content

Commit

Permalink
CompatHelper: bump compat for StateSpaceSets to 2, (keep existing com…
Browse files Browse the repository at this point in the history
…pat) (#426)

* CompatHelper: bump compat for StateSpaceSets to 2, (keep existing compat)

* use v2 exclusively

* bump project version

* fix approx entr argumenterror

* make `codify` do what was promised

* typing

* fix doc compat

* fix entropy sample problem (?)

* stop rounding 0 to 0...

* FIX DOCS ERROR

---------

Co-authored-by: CompatHelper Julia <[email protected]>
Co-authored-by: Datseris <[email protected]>
  • Loading branch information
3 people authored Sep 22, 2024
1 parent ba9849b commit fd2a5eb
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 68 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

Changelog is kept with respect to version 0.11 of Entropies.jl. From version v2.0 onwards, this package has been renamed to ComplexityMeasures.jl.

## 3.6
## 3.7

- Updated to StateSpaceSets.jl v2.0
- Fixed a bug in `codify` with `StateSpaceSet`. Now it does exactly as described in the docstring.

## 3.6

- New information measure: `FluctuationComplexity`.

Expand Down
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name = "ComplexityMeasures"
uuid = "ab4b797d-85ee-42ba-b621-05d793b346a2"
authors = "Kristian Agasøster Haaga <[email protected]>, George Datseries <[email protected]>"
repo = "https://github.com/juliadynamics/ComplexityMeasures.jl.git"
version = "3.6.6"
version = "3.7.0"

[deps]
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
Expand Down Expand Up @@ -32,10 +32,10 @@ Neighborhood = "0.2.4"
QuadGK = "2.9"
Reexport = "1"
SpecialFunctions = "0.10, 1.0, 2"
StateSpaceSets = "1.0.4"
StateSpaceSets = "2.1"
StaticArrays = "0.12, 1.0"
Statistics = "1"
StatsBase = "0.33, 0.34"
StatsFuns = "1.3"
Wavelets = "0.10"
Wavelets = "0.9, 0.10"
julia = "1.5"
1 change: 0 additions & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,3 @@ TimeseriesSurrogates = "c804724b-8c18-5caa-8579-6025a0767c70"

[compat]
DynamicalSystemsBase = "3"
StateSpaceSets = "1"
2 changes: 1 addition & 1 deletion docs/src/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ using CairoMakie
N, a = 2000, 10
t = LinRange(0, 2*a*π, N)
x = repeat([-5:5 |> collect; 4:-1:-4 |> collect], N ÷ 20);
x = repeat([-5:5.0 |> collect; 4.0:-1:-4 |> collect], N ÷ 20);
y = sin.(t .+ cos.(t/0.5));
z = rand(N)
Expand Down
4 changes: 3 additions & 1 deletion src/complexity_measures/approximate_entropy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ Base.@kwdef struct ApproximateEntropy{I, B, R} <: ComplexityEstimator
end
end


function complexity(c::ApproximateEntropy, x::AbstractStateSpaceSet)
throw(ArgumentError("Approximate entropy is only computable for timeseries."))
end

function complexity(c::ApproximateEntropy, x::AbstractVector{T}) where T
(; m, τ, r, base) = c
Expand Down
4 changes: 3 additions & 1 deletion src/core/encodings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,6 @@ spaces preserve the input data length (e.g. [`UniqueElements`](@ref)), while
some outcome spaces (e.g. [`OrdinalPatterns`](@ref)) do e.g. delay embeddings before
encoding, so that `length(s) < length(x)`.
"""
function codify end
function codify(o::OutcomeSpace, s::AbstractStateSpaceSet)
return map(x -> codify(o, x), columns(s))
end
6 changes: 3 additions & 3 deletions src/outcome_spaces/cosine_similarity_binning.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ An alias to [`CosineSimilarityBinning`](@ref).
const Diversity = CosineSimilarityBinning

function counts_and_outcomes(o::CosineSimilarityBinning, x::AbstractVector{T}) where T <: Real
# Cosine similarities are all on [-1.0, 1.0], so just discretize this interval. To
# do so, we call the `counts_and_outcomes(::RectangularBinEncoding, x)` in the file
# Cosine similarities are all on [-1.0, 1.0], so just discretize this interval. To
# do so, we call the `counts_and_outcomes(::RectangularBinEncoding, x)` in the file
# `encoding_implementations/rectangular_binning.jl`.
rbc::RectangularBinEncoding = encoding_for_diversity(o.nbins)
cdists = cosine_similarity_distances(o, x)
Expand Down Expand Up @@ -87,7 +87,7 @@ function encoding_for_diversity(nbins::Int)
return RectangularBinEncoding(binning)
end

function codify(o::CosineSimilarityBinning, x::AbstractVector{T}) where T
function codify(o::CosineSimilarityBinning, x::AbstractVector{<:Real})
τs = 0:o.τ:(o.m - 1)*o.τ
Y = genembed(x, τs)
ds = zeros(Float64, length(Y) - 1)
Expand Down
73 changes: 26 additions & 47 deletions src/outcome_spaces/ordinal_patterns.jl
Original file line number Diff line number Diff line change
Expand Up @@ -200,18 +200,18 @@ is_counting_based(o::AmplitudeAwareOrdinalPatterns) = false
function OrdinalPatterns{m}= 1, lt = isless_rand; kwargs...) where {m}
if haskey(kwargs, )
msg = "Keyword argument `τ` to `OrdinalPatterns` is deprecated. " *
"The signature is now " *
"`OrdinalPatterns{m}(τ = 1, lt::Function = ComplexityMeasures.isless_rand)`" *
", so provide `τ` as a positional argument instead. " *
"The signature is now " *
"`OrdinalPatterns{m}(τ = 1, lt::Function = ComplexityMeasures.isless_rand)`" *
", so provide `τ` as a positional argument instead. " *
"In this call, the given keyword `τ` is used instead of the positional `τ`."
@warn msg
τ = kwargs[]
end
if haskey(kwargs, :lt)
msg = "Keyword argument `lt` to `OrdinalPatterns` is deprecated. " *
"The signature is now " *
"`OrdinalPatterns{m}(τ = 1, lt::Function = ComplexityMeasures.isless_rand)`" *
", so provide `lt` as a positional argument instead. " *
"The signature is now " *
"`OrdinalPatterns{m}(τ = 1, lt::Function = ComplexityMeasures.isless_rand)`" *
", so provide `lt` as a positional argument instead. " *
"In this call, the given keyword `lt` is used instead of the positional `lt`."
@warn msg
lt = kwargs[:lt]
Expand All @@ -225,18 +225,18 @@ end
function WeightedOrdinalPatterns{m}= 1, lt = isless_rand; kwargs...) where {m}
if haskey(kwargs, )
msg = "Keyword argument `τ` to `WeightedOrdinalPatterns` is deprecated. " *
"The signature is now " *
"`WeightedOrdinalPatterns{m}(τ::Int = 1, lt::F=ComplexityMeasures.isless_rand)`" *
", so provide `τ` as a positional argument instead. " *
"The signature is now " *
"`WeightedOrdinalPatterns{m}(τ::Int = 1, lt::F=ComplexityMeasures.isless_rand)`" *
", so provide `τ` as a positional argument instead. " *
"In this call, the given keyword `τ` is used instead of the positional `τ`."
@warn msg
τ = kwargs[]
end
if haskey(kwargs, :lt)
msg = "Keyword argument `lt` to `WeightedOrdinalPatterns` is deprecated. " *
"The signature is now " *
"`WeightedOrdinalPatterns{m}(τ = 1, lt::Function = ComplexityMeasures.isless_rand)`" *
", so provide `lt` as a positional argument instead. " *
"The signature is now " *
"`WeightedOrdinalPatterns{m}(τ = 1, lt::Function = ComplexityMeasures.isless_rand)`" *
", so provide `lt` as a positional argument instead. " *
"In this call, the given keyword `lt` is used instead of the positional `lt`."
@warn msg
lt = kwargs[:lt]
Expand All @@ -248,38 +248,38 @@ function WeightedOrdinalPatterns{m}(τ = 1, lt = isless_rand; kwargs...) where {
return WeightedOrdinalPatterns{m, F, I}(OrdinalPatternEncoding{m}(lt), τ)
end

function AmplitudeAwareOrdinalPatterns{m}= 1, A = 0.5, lt = isless_rand;
function AmplitudeAwareOrdinalPatterns{m}= 1, A = 0.5, lt = isless_rand;
kwargs...) where {m}
# because the order of the arguments is different from the other ordinal outcome spaces
if A isa Function
msg = "Second argument to `AmplitudeAwareOrdinalPatterns` must be a function. " *
"Got a $(typeof(A)).";
throw(ArgumentError(msg))
end

if haskey(kwargs, )
msg = "Keyword argument `τ` to `AmplitudeAwareOrdinalPatterns` is deprecated. " *
"The signature is now " *
"`AmplitudeAwareOrdinalPatterns{m}(τ::Int = 1, A = 0.5, lt::F=isless_rand)`" *
", so provide `τ` as a positional argument instead. " *
"The signature is now " *
"`AmplitudeAwareOrdinalPatterns{m}(τ::Int = 1, A = 0.5, lt::F=isless_rand)`" *
", so provide `τ` as a positional argument instead. " *
"In this call, the given keyword `τ` is used instead of the positional `τ`."
@warn msg
τ = kwargs[]
end
if haskey(kwargs, :lt)
msg = "Keyword argument `lt` to `AmplitudeAwareOrdinalPatterns` is deprecated. " *
"The signature is now " *
"`AmplitudeAwareOrdinalPatterns{m}(τ::Int = 1, A = 0.5, lt::F=isless_rand)`" *
", so provide `lt` as a positional argument instead. " *
"The signature is now " *
"`AmplitudeAwareOrdinalPatterns{m}(τ::Int = 1, A = 0.5, lt::F=isless_rand)`" *
", so provide `lt` as a positional argument instead. " *
"In this call, the given keyword `lt` is used instead of the positional `lt`."
@warn msg
lt = kwargs[:lt]
end
if haskey(kwargs, :A)
msg = "Keyword argument `A` to `AmplitudeAwareOrdinalPatterns` is deprecated. " *
"The signature is now " *
"`AmplitudeAwareOrdinalPatterns{m}(τ::Int = 1, A = 0.5, lt::F=isless_rand)`" *
", so provide `A` as a positional argument instead. " *
"The signature is now " *
"`AmplitudeAwareOrdinalPatterns{m}(τ::Int = 1, A = 0.5, lt::F=isless_rand)`" *
", so provide `A` as a positional argument instead. " *
"In this call, the given keyword `A` is used instead of the positional `A`."
@warn msg
A = kwargs[:A]
Expand Down Expand Up @@ -335,25 +335,9 @@ function fasthist!(πs::Vector{Int}, est::OrdinalOutcomeSpace{m}, x::AbstractSta
return cts
end

function codify(est::OrdinalOutcomeSpace{m}, x) where m
if x isa AbstractVector
dataset = embed(x, m, est.τ)
elseif x isa AbstractStateSpaceSet && dimension(x) == 1
err = "Convert your univariate time series to a subtype of `AbstractVector` to " *
"codify with ordinal patterns! A `StateSpaceSet` input is assumed to be " *
"already embedded in D = m >= 2 dimensional space."
throw(ArgumentError(err))
else
dataset = x
end
m != dimension(dataset) && throw(ArgumentError(
"Order of ordinal patterns and dimension of `StateSpaceSet` must match!"
))
πs = zeros(Int, length(dataset))
@inbounds for (i, χ) in enumerate(dataset)
πs[i] = encode(est.encoding, χ)
end
return πs
function codify(o::OrdinalOutcomeSpace{m}, x::AbstractVector{<:Real}) where {m}
emb = embed(x, m, o.τ).data
return encode.(Ref(o.encoding), emb)
end

# Special treatment for counting-based
Expand Down Expand Up @@ -448,8 +432,3 @@ Encode relative amplitude information of the elements of `a`.
function AAPE(x, A::Real = 0.5, m::Int = length(x))
(A/m)*sum(abs.(x)) + (1-A)/(m-1)*sum(abs.(diff(x)))
end

function codify(o::OrdinalPatterns{m}, x::AbstractVector) where {m}
emb = embed(x, m, o.τ).data
return encode.(Ref(o.encoding), emb)
end
15 changes: 8 additions & 7 deletions test/complexity/measures/entropy_sample.jl
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
using ComplexityMeasures
using ComplexityMeasures, Test

@test_throws UndefKeywordError SampleEntropy()

# Analytical examples seem to be lacking in the literature. As a next-best-test,
# we just check that we get a sample entropy sufficiently close to zero for a completely
# regular signal.
N = 6000
c = SampleEntropy(m = 2, τ = 1, r = 0.1)
x = repeat([-5:5 |> collect; 4:-1:-4 |> collect], N ÷ 20);
@test round(complexity(c, x), digits = 3) == round(0.0, digits = 3)
@test round(complexity_normalized(c, x), digits = 3) == round(0.0, digits = 3)
x = repeat([-5.0:5 |> collect; 4.0:-1:-4 |> collect], N ÷ 20);
@test round(complexity(c, x), digits = 3) == 0.0
@test round(complexity_normalized(c, x), digits = 3) == 0.0

# Conversely, a non-regular signal should result in a sample entropy
# greater than zero.
x = rand(N)
@test round(complexity(c, x), digits = 2) > round(0.0, digits = 2)
@test round(complexity_normalized(c, x), digits = 2) > round(0.0, digits = 2)
@test round(complexity(c, x), digits = 2) > 0.0
@test round(complexity_normalized(c, x), digits = 2) > 0.0

# Automatically deducing radius
@test round(complexity(SampleEntropy(x, m = 2, τ = 1), x), digits = 2) > round(0.0, digits = 2)
@test round(complexity(SampleEntropy(x, m = 2, τ = 1), x), digits = 2) > 0.0
9 changes: 7 additions & 2 deletions test/outcome_spaces/implementations/permutation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ end
WeightedOrdinalPatterns, AmplitudeAwareOrdinalPatterns)
# Codification of vector inputs (time series)
x = rand(30)
@test codify(S(), x) isa Vector{Int}
@test_throws ArgumentError codify(S(),StateSpaceSet(x))
y = rand(30)
s = StateSpaceSet(x, y)
c1 = codify(S(), x)
@test c1 isa Vector{Int}
out = codify(S(), s)
@test out isa Tuple
@test out[1] == c1
end
2 changes: 1 addition & 1 deletion test/outcome_spaces/implementations/unique_elements.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ end

# Codification of vector inputs (time series)
x = [1, 3, 2, 1, 2, 2, 1, 3, 1]
y = StateSpaceSet(["a", "b", "c", "b", "a"])
y = ["a", "b", "c", "b", "a"]

@test codify(UniqueElements(), x) isa Vector{Int}
@test codify(UniqueElements(), y) isa Vector{Int}

0 comments on commit fd2a5eb

Please sign in to comment.