diff --git a/CHANGELOG.md b/CHANGELOG.md index d244753..a243d42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # RecurrenceAnalysis.jl changelog +## v2.1.0 + +Updated to StateSpaceSets.jl v2. + ## v2.0.0 - [**BREAKING**] The `@windowed` macro is removed. It was some incredibly complicated 250 lines of code that offer little benefit. Instead of using this macro, use the new `windowed` function. It does something simple: replaces @@ -50,11 +54,11 @@ - Now `AbstractRecurrenceMatrix` types have a parameter with the possible values: * `WithinRange`: when neighboring points are determined by a given distance in the phase space. * `NeighborNumber`: when each point has a determined number of neighbors. -- Input arguments of `RecurrenceMatrix`, etc. are generalized to `AbstractDataset`. +- Input arguments of `RecurrenceMatrix`, etc. are generalized to `AbstractStateSpaceSet`. ## v1.3.2 - Bugfixes of `transitivity` -- Deprecate `AbstractMatrix` inputs to `RecurrenceMatrix` etc., in favor of `Dataset`. +- Deprecate `AbstractMatrix` inputs to `RecurrenceMatrix` etc., in favor of `StateSpaceSet`. ## v1.3.0 - Increased performance of `RecurrenceMatrix`. @@ -91,12 +95,12 @@ create a dedicated struct for each kind of matrix. ## v0.6.0 -* Rework how `recurrencematrix` is computed: now a conversion to `Dataset` is done for small dimensions. In addition, the default metric is now `Euclidean`. +* Rework how `recurrencematrix` is computed: now a conversion to `StateSpaceSet` is done for small dimensions. In addition, the default metric is now `Euclidean`. ## v0.5.0 * With this update core functionality of delay embedding and estimating embedding dimension is moved (and used from) the Julia package `DelayEmbeddings`. * `RecurrenceAnalysis` is also joining JuliaDynamics and **DynamicalSystems.jl** from 0.5.0 onwards. -* Extensions have been implemented so that most functionality works also with `Dataset`s. +* Extensions have been implemented so that most functionality works also with `StateSpaceSet`s. ## 23-09-2018 - v0.4.0 diff --git a/Project.toml b/Project.toml index 313301c..b54583e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "RecurrenceAnalysis" uuid = "639c3291-70d9-5ea2-8c5b-839eba1ee399" repo = "https://github.com/JuliaDynamics/RecurrenceAnalysis.jl.git" -version = "2.0.8" +version = "2.1.0" [deps] DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" @@ -20,7 +20,7 @@ DelimitedFiles = "1" Distances = "0.8, 0.9, 0.10" Graphs = "1.6" Reexport = "1" -StateSpaceSets = "1" +StateSpaceSets = "2" Statistics = "1" UnicodePlots = "0.3, 1, 2, 3" julia = "1.5" diff --git a/src/RecurrenceAnalysis.jl b/src/RecurrenceAnalysis.jl index 897920e..b5b4ceb 100644 --- a/src/RecurrenceAnalysis.jl +++ b/src/RecurrenceAnalysis.jl @@ -10,6 +10,14 @@ end RecurrenceAnalysis using Reexport @reexport using StateSpaceSets +# for backwards compatibility with SSSets.jl v1 +# TODO: Cleanup: go through the instances in the codebase +# where `oldsize` is called: replace it with `size` if the +# input is a `Matrix`, and with `dimension` if the input is a `StateSpaceSet`. +oldsize(s::AbstractStateSpaceSet) = (length(s), dimension(s)) +oldsize(s) = size(s) +oldsize(s, i::Int) = oldsize(s)[i] + Array_or_SSSet = Union{AbstractArray{<:Real}, AbstractStateSpaceSet} Vector_or_SSSet = Union{AbstractVector{<:Real}, AbstractStateSpaceSet} @@ -27,7 +35,7 @@ export RecurrenceMatrix, CrossRecurrenceMatrix, JointRecurrenceMatrix export embed, reconstruct, recurrence_threshold, - Dataset, + StateSpaceSet, distancematrix, textrecurrenceplot, recurrenceplot, diff --git a/src/deprecate.jl b/src/deprecate.jl index b699eb9..f17d133 100644 --- a/src/deprecate.jl +++ b/src/deprecate.jl @@ -23,24 +23,24 @@ end for T in (:WithinRange, :NeighborNumber) @eval function RecurrenceMatrix{$T}(x::AbstractMatrix, ε; kwargs...) - @warn string("`RecurrenceMatrix{", $T, "}(x::AbstractMatrix, ε; kwargs...)` is deprecated, use `RecurrenceMatrix{", $T, "}(Dataset(x), ε; kwargs...)`") - RecurrenceMatrix{$T}(Dataset(x), ε; kwargs...) + @warn string("`RecurrenceMatrix{", $T, "}(x::AbstractMatrix, ε; kwargs...)` is deprecated, use `RecurrenceMatrix{", $T, "}(StateSpaceSet(x), ε; kwargs...)`") + RecurrenceMatrix{$T}(StateSpaceSet(x), ε; kwargs...) end for call in (:CrossRecurrenceMatrix, :JointRecurrenceMatrix) @eval function $call{$T}(x::AbstractMatrix, y, ε; kwargs...) - @warn string("`", $call, "{", $T, "}(x::AbstractMatrix, y, ε; kwargs...)` is deprecated, use `", $call, "{", $T, "}(Dataset(x), y, ε; kwargs...)`") - $call{$T}(Dataset(x), y, ε; kwargs...) + @warn string("`", $call, "{", $T, "}(x::AbstractMatrix, y, ε; kwargs...)` is deprecated, use `", $call, "{", $T, "}(StateSpaceSet(x), y, ε; kwargs...)`") + $call{$T}(StateSpaceSet(x), y, ε; kwargs...) end @eval function $call{$T}(x, y::AbstractMatrix, ε; kwargs...) - @warn string("`", $call, "{", $T, "}(x, y::AbstractMatrix, ε; kwargs...)` is deprecated, use `", $call, "{", $T, "}(x, Dataset(y), ε; kwargs...)`") - $call{$T}(x, Dataset(y), ε; kwargs...) + @warn string("`", $call, "{", $T, "}(x, y::AbstractMatrix, ε; kwargs...)` is deprecated, use `", $call, "{", $T, "}(x, StateSpaceSet(y), ε; kwargs...)`") + $call{$T}(x, StateSpaceSet(y), ε; kwargs...) end @eval function $call{$T}(x::AbstractMatrix, y::AbstractMatrix, ε; kwargs...) - @warn string("`", $call, "{", $T, "}(x::AbstractMatrix, y::AbstractMatrix, ε; kwargs...)` is deprecated, use `", $call, "{", $T, "}(Dataset(x), Dataset(y), ε; kwargs...)`") - $call{$T}(Dataset(x), Dataset(y), ε; kwargs...) + @warn string("`", $call, "{", $T, "}(x::AbstractMatrix, y::AbstractMatrix, ε; kwargs...)` is deprecated, use `", $call, "{", $T, "}(StateSpaceSet(x), StateSpaceSet(y), ε; kwargs...)`") + $call{$T}(StateSpaceSet(x), StateSpaceSet(y), ε; kwargs...) end end end diff --git a/src/matrices/distance_matrix.jl b/src/matrices/distance_matrix.jl index 8894878..b588812 100644 --- a/src/matrices/distance_matrix.jl +++ b/src/matrices/distance_matrix.jl @@ -7,7 +7,7 @@ Create a matrix with the distances between each pair of points of the time series `x` and `y` using `metric`. -The time series `x` and `y` can be `AbstractDataset`s or vectors or matrices with data points +The time series `x` and `y` can be `AbstractStateSpaceSet`s or vectors or matrices with data points in rows. The data point dimensions (or number of columns) must be the same for `x` and `y`. The returned value is a `n×m` matrix, with `n` being the length (or number of rows) @@ -17,18 +17,18 @@ The metric can be any of the `Metric`s defined in the [`Distances` package](https://github.com/JuliaStats/Distances.jl) and defaults to `Euclidean()`. """ -distancematrix(x, metric::Union{Metric,String}=DEFAULT_METRIC, parallel = size(x)[1] > 500) = _distancematrix(x, getmetric(metric), Val(parallel)) +distancematrix(x, metric::Union{Metric,String}=DEFAULT_METRIC, parallel = oldsize(x)[1] > 500) = _distancematrix(x, getmetric(metric), Val(parallel)) # For 1-dimensional arrays (vectors), the distance does not depend on the metric -distancematrix(x::AbstractVector{<:Real}, y::AbstractVector{<:Real}, metric=DEFAULT_METRIC, parallel = size(x)[1] > 500) = abs.(x .- y') +distancematrix(x::AbstractVector{<:Real}, y::AbstractVector{<:Real}, metric=DEFAULT_METRIC, parallel = oldsize(x)[1] > 500) = abs.(x .- y') # If the metric is supplied as a string, get the corresponding Metric from Distances -distancematrix(x, y, metric::String, parallel = size(x)[1] > 500) = distancematrix(x, y, getmetric(metric), parallel) +distancematrix(x, y, metric::String, parallel = oldsize(x)[1] > 500) = distancematrix(x, y, getmetric(metric), parallel) const MAXDIM = 9 -function distancematrix(x::Tx, y::Ty, metric::Metric=DEFAULT_METRIC, parallel = size(x)[1] > 500) where - {Tx<:Union{AbstractMatrix, AbstractDataset}} where {Ty<:Union{AbstractMatrix, AbstractDataset}} - sx, sy = size(x), size(y) +function distancematrix(x::Tx, y::Ty, metric::Metric=DEFAULT_METRIC, parallel = oldsize(x)[1] > 500) where + {Tx<:Union{AbstractMatrix, AbstractStateSpaceSet}} where {Ty<:Union{AbstractMatrix, AbstractStateSpaceSet}} + sx, sy = oldsize(x), oldsize(y) @assert sx[2] == sy[2] """ The dimensions of the data points in `x` and `y` must be equal! Found dim(x)=$(sx[2]), dim(y)=$(sy[2]). @@ -39,7 +39,7 @@ function distancematrix(x::Tx, y::Ty, metric::Metric=DEFAULT_METRIC, parallel = elseif Tx <: Matrix && Ty <: Matrix && metric == Chebyshev() return _distancematrix(x, y, metric, Val(parallel)) else - return _distancematrix(Dataset(x), Dataset(y), metric, Val(parallel)) + return _distancematrix(StateSpaceSet(x), StateSpaceSet(y), metric, Val(parallel)) end end @@ -48,7 +48,7 @@ _distancematrix(x::AbstractMatrix, y::AbstractMatrix, metric::Metric, ::Val{fals # First we define the serial versions of the functions. # Core function for AbstractDatasets -function _distancematrix(x::AbstractDataset{S,Tx}, y::AbstractDataset{S,Ty}, +function _distancematrix(x::AbstractStateSpaceSet{S,Tx}, y::AbstractStateSpaceSet{S,Ty}, metric::Metric, ::Val{false}) where {S, Tx, Ty} x = x.data @@ -62,7 +62,7 @@ end # Now, we define the parallel versions. -function _distancematrix(x::AbstractDataset{S,Tx}, y::AbstractDataset{S,Ty}, +function _distancematrix(x::AbstractStateSpaceSet{S,Tx}, y::AbstractStateSpaceSet{S,Ty}, metric::Metric, ::Val{true}) where {S, Tx, Ty} x = x.data @@ -150,7 +150,7 @@ function _distancematrix(x::Vector{T}, metric::Metric, ::Val{true}) where T end -function _distancematrix(x::AbstractDataset{S, T}, metric::Metric, ::Val{true}) where T where S +function _distancematrix(x::AbstractStateSpaceSet{S, T}, metric::Metric, ::Val{true}) where T where S d = zeros(T, length(x), length(x)) Threads.@threads for k in partition_indices(length(x)) diff --git a/src/rna/graphs.jl b/src/rna/graphs.jl index d9d14cf..d752662 100644 --- a/src/rna/graphs.jl +++ b/src/rna/graphs.jl @@ -34,7 +34,7 @@ Theory and Best Practices*, Springer, pp. 101-165 (2015). """ function Graphs.SimpleGraphs.SimpleGraph(R::AbstractRecurrenceMatrix) graph = SimpleGraph(R.data) - delta = SimpleGraphFromIterator(Edge(v,v) for v in 1:size(graph, 1)) + delta = SimpleGraphFromIterator(Edge(v,v) for v in 1:oldsize(graph, 1)) graph = difference(graph, delta) return graph end diff --git a/src/rqa/histograms.jl b/src/rqa/histograms.jl index 54d403b..0490d0f 100644 --- a/src/rqa/histograms.jl +++ b/src/rqa/histograms.jl @@ -112,7 +112,7 @@ function diagonalhistogram(x::Union{ARM,AbstractMatrix}; lmin::Integer=2, theile (theiler < 0) && throw(ErrorException( "Theiler window length must be greater than or equal to 0")) (lmin < 1) && throw(ErrorException("lmin must be 1 or greater")) - m,n = size(x) + m,n = oldsize(x) rv = rowvals(x)[:] dv = colvals(x) .- rowvals(x) loi_hist = Int[] @@ -158,7 +158,7 @@ function verticalhistograms(x::Union{ARM,AbstractMatrix}; (theiler < 0) && throw(ErrorException( "Theiler window length must be greater than or equal to 0")) (lmin < 1) && throw(ErrorException("lmin must be 1 or greater")) - m,n=size(x) + m,n=oldsize(x) rv = rowvals(x) cv = colvals(x) return _linehistograms(rv,cv,lmin,theiler,distances) diff --git a/src/rqa/radius.jl b/src/rqa/radius.jl index fd53e51..ddc3301 100644 --- a/src/rqa/radius.jl +++ b/src/rqa/radius.jl @@ -32,7 +32,7 @@ function sorteddistances(x; theiler::Integer=0, scale=1, kwargs...) scale = (typeof(scale) <: Function) ? scale(dm) : scale dm /= scale # Browse upper triangle after Theiler window - n = size(x,1) + n = oldsize(x,1) nd = (n+1)*n/2 ntheiler = theiler*n - theiler*(theiler-1)/2 distarray = zeros(round(Int, nd-ntheiler)) diff --git a/src/rqa/rqa.jl b/src/rqa/rqa.jl index dfc8821..79549d3 100644 --- a/src/rqa/rqa.jl +++ b/src/rqa/rqa.jl @@ -77,7 +77,7 @@ _rrdenominator(R::ARM; theiler=0, kwargs...) = length(R) function _rrdenominator(R::AbstractMatrix; theiler=0, kwargs...) (theiler == 0) && (return length(R)) - k = size(R,1) - theiler + k = oldsize(R,1) - theiler return k*(k+1) end @@ -85,7 +85,7 @@ function _rrdenominator(R::M; theiler=0, kwargs...) where M<:Union{RecurrenceMatrix,JointRecurrenceMatrix} (theiler == 0) && (return length(R)) - k = size(R,1) - theiler + k = oldsize(R,1) - theiler return k*(k+1) end @@ -128,12 +128,12 @@ macro histogram_params(keyword, description, hist_fun) points inside the Theiler window (see [`rqa`](@ref) for the default values and usage of the keyword argument `theiler`). - Notes: This metric was first proposed in the paper "Exploiting Nonlinear Recurrence - and Fractal Scaling Properties for Voice Disorder Detection" as Recurrence Period - Density Entropy or Recurrence Probability Density Entropy (RPDE). - It is a normalized dimensionless metric in the range [0,1]. - In the 2018 article "Recurrence threshold selection for obtaining robust recurrence - characteristics in different embedding dimensions", the indicator RPDE is explicitly + Notes: This metric was first proposed in the paper "Exploiting Nonlinear Recurrence + and Fractal Scaling Properties for Voice Disorder Detection" as Recurrence Period + Density Entropy or Recurrence Probability Density Entropy (RPDE). + It is a normalized dimensionless metric in the range [0,1]. + In the 2018 article "Recurrence threshold selection for obtaining robust recurrence + characteristics in different embedding dimensions", the indicator RPDE is explicitly called Recurrence Time Entropy (RTE). Here RPDE and RTE are clearly the same indicator. """ else @@ -257,7 +257,7 @@ Compute the diagonalwise recurrence rate `τ-RR` from a recurrence matrix `R`. Note that this only works for squared recurrence matrices. """ function tau_recurrence(R::Union{ARM,AbstractMatrix}) - n = minimum(size(R)) + n = minimum(oldsize(R)) rv = rowvals(R) rr_τ = zeros(n) @inbounds for col in 1:n diff --git a/src/rqa/windowed_function.jl b/src/rqa/windowed_function.jl index 6251770..0011f5b 100644 --- a/src/rqa/windowed_function.jl +++ b/src/rqa/windowed_function.jl @@ -10,7 +10,7 @@ function windowed(rmat::Union{ARM,AbstractMatrix}, f::Function, width::Integer, "Window width must be must be greater than or equal to 2")) (step < 1) && throw(ErrorException( "Step size must be greater than or equal to 1")) - windows = 1:step:(size(rmat, 1)-width+1) + windows = 1:step:(oldsize(rmat, 1)-width+1) map(1:length(windows)) do i f(rmat[windows[i]:(windows[i]+width-1), windows[i]:(windows[i]+width-1)]; kwargs...) end diff --git a/test/rmatrix_analytic.jl b/test/rmatrix_analytic.jl index e972e68..df834dc 100644 --- a/test/rmatrix_analytic.jl +++ b/test/rmatrix_analytic.jl @@ -10,7 +10,7 @@ using Distances: Chebyshev t = range(0, 2π; length = 20) # length is crucial and decides distance and thresholds c = cos.(t) s = sin.(t) -X = Dataset(c, s) +X = StateSpaceSet(c, s) Y = X[1:10] dmat = distancematrix(X)