Skip to content

Commit 9dbcb43

Browse files
authored
[WIP] Dedicated structs for recurrence matrices (#25)
* export Dataset as well, seems useful. * recurrence matrix type and its pretty printing * change function return types * each matrix gets its own type. * more necessary method propagation * more elegant method propagation * update recurrence rate * enforce as constant that RecurrenceMatrix is symmetric * correct mistake: Int instead of Int64 * replace all dispatches with ARM and comment out windowed for now. * use new types in tests * update plotting to new types * remove `AbstractMatrix` methods for diagonal and vertical histograms * extend iterate and uncomment windowed * type stability in trend and recurrencerate * fix windowed with JointRecurrenceMatrix * change field from .m to .data * fix windowed rqa functions * change gensym by local variable declarations in windowed * added documentation and comments on windowed * delete "= true" in pretty printing of recurrence matrices (#27) * docstring fixes * deprecations
1 parent 17edc3e commit 9dbcb43

File tree

6 files changed

+208
-199
lines changed

6 files changed

+208
-199
lines changed

src/RecurrenceAnalysis.jl

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ module RecurrenceAnalysis
33
using Distances, Statistics, LinearAlgebra, SparseArrays, DelayEmbeddings, StaticArrays
44
import Base.Meta.parse
55

6+
export RecurrenceMatrix, CrossRecurrenceMatrix, JointRecurrenceMatrix
67
export embed,
78
reconstruct,
9+
Dataset,
810
distancematrix,
911
recurrencematrix,
1012
crossrecurrencematrix,
@@ -21,21 +23,9 @@ export embed,
2123
trappingtime,
2224
maxvert,
2325
rqa,
24-
autocorrelation,
25-
ami,
26-
gmi,
2726
sorteddistances,
2827
@windowed
2928

30-
# column values in sparse matrix (parallel to rowvals)
31-
function colvals(x::SparseMatrixCSC)
32-
cv = zeros(Int,nnz(x))
33-
@inbounds for c=1:size(x,2)
34-
cv[nzrange(x,c)] .= c
35-
end
36-
cv
37-
end
38-
3929
include("matrices.jl")
4030
include("plot.jl")
4131
include("rqa.jl")

src/matrices.jl

Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,66 @@ function _distancematrix(x::Dataset{S,Tx}, y::Dataset{S,Ty},
8484
end
8585

8686

87-
#### Recurrence matrix ####
88-
# Defined as a wrapper of crossrecurrencematrix
87+
88+
#######################
89+
# Type
90+
#######################
91+
abstract type AbstractRecurrenceMatrix end
92+
const ARM = AbstractRecurrenceMatrix
93+
struct RecurrenceMatrix <: AbstractRecurrenceMatrix
94+
data::SparseMatrixCSC{Bool,Int}
95+
end
96+
struct CrossRecurrenceMatrix <: AbstractRecurrenceMatrix
97+
data::SparseMatrixCSC{Bool,Int}
98+
end
99+
struct JointRecurrenceMatrix <: AbstractRecurrenceMatrix
100+
data::SparseMatrixCSC{Bool,Int}
101+
end
102+
103+
function Base.summary(R::AbstractRecurrenceMatrix)
104+
N = nnz(R.data)
105+
return "$(nameof(typeof(R))) of size $(size(R.data)) with $N entries:"
106+
end
107+
function Base.show(io::IO, R::AbstractRecurrenceMatrix)
108+
s = sprint(io -> show(IOContext(io, :limit=>true), MIME"text/plain"(), R.data))
109+
s = split(s, '\n')[2:end]
110+
s = [replace(line, "= true"=>"", count=1) for line in s]
111+
s = join(s, '\n')
112+
tos = summary(R)*"\n"*s
113+
println(io, tos)
114+
end
115+
116+
# Propagate used functions:
117+
begin
118+
extentions = [
119+
(:Base, (:getindex, :size, :length, :view, :iterate)),
120+
(:LinearAlgebra, (:diag, :triu, :tril, :issymmetric)),
121+
(:SparseArrays, (:nnz, :rowvals, :nzrange))
122+
]
123+
for (M, fs) in extentions
124+
for f in fs
125+
@eval $M.$(f)(x::ARM, args...) = $(f)(x.data, args...)
126+
end
127+
end
128+
end
129+
LinearAlgebra.issymmetric(::RecurrenceMatrix) = true
130+
# column values in sparse matrix (parallel to rowvals)
131+
function colvals(x::SparseMatrixCSC)
132+
cv = zeros(Int,nnz(x))
133+
@inbounds for c=1:size(x,2)
134+
cv[nzrange(x,c)] .= c
135+
end
136+
cv
137+
end
138+
colvals(x::ARM) = colvals(x.data)
139+
140+
@deprecate recurrencematrix RecurrenceMatrix
141+
@deprecate crossrecurrencematrix CrossRecurrenceMatrix
142+
@deprecate jointrecurrencematrix JointRecurrenceMatrix
143+
89144

90145
"""
91-
recurrencematrix(x, ε; kwargs...)
146+
RecurrenceMatrix(x, ε; kwargs...)
92147
93148
Create a recurrence matrix from an embedded time series.
94149
@@ -115,7 +170,7 @@ by the following keyword arguments:
115170
and `scale` is ignored.
116171
* `metric` : metric of the distances, as in [`distancematrix`](@ref).
117172
118-
See also: [`crossrecurrencematrix`](@ref), [`jointrecurrencematrix`](@ref) and
173+
See also: [`CrossRecurrenceMatrix`](@ref), [`JointRecurrenceMatrix`](@ref) and
119174
use [`recurrenceplot`](@ref) to turn the result of these functions into a plottable format.
120175
121176
## References
@@ -126,13 +181,16 @@ use [`recurrenceplot`](@ref) to turn the result of these functions into a plotta
126181
recurrence quantifications", in: Webber, C.L. & N. Marwan (eds.), *Recurrence
127182
Quantification Analysis. Theory and Best Practices*, Springer, pp. 3-43 (2015).
128183
"""
129-
recurrencematrix(x, ε; kwargs...) = crossrecurrencematrix(x, x, ε; kwargs...)
184+
function RecurrenceMatrix(x, ε; kwargs...)
185+
m = crossrecurrencematrix(x, x, ε; kwargs...)
186+
return RecurrenceMatrix(m)
187+
end
130188

131189

132190
#### Cross recurrence matrix ####
133191

134192
"""
135-
crossrecurrencematrix(x, y, ε; kwargs...)
193+
CrossRecurrenceMatrix(x, y, ε; kwargs...)
136194
137195
Create a cross recurrence matrix from the time series `x` and `y`.
138196
@@ -141,17 +199,23 @@ For the time series `x`, `y`, of length `n` and `m`, respectively, it is a
141199
sparse `n×m` matrix of Boolean values, such that if `d(x[i], y[j]) ≤ ε`,
142200
then the cell `(i, j)` of the matrix will have a `true` value.
143201
144-
See [`recurrencematrix`](@ref) for details, references and keywords.
145-
See also: [`jointrecurrencematrix`](@ref).
202+
See [`RecurrenceMatrix`](@ref) for details, references and keywords.
203+
See also: [`JointRecurrenceMatrix`](@ref).
146204
"""
205+
function CrossRecurrenceMatrix(x, y, ε; kwargs...)
206+
m = crossrecurrencematrix(x, y, ε; kwargs...)
207+
return CrossRecurrenceMatrix(m)
208+
end
209+
147210
function crossrecurrencematrix(x, y, ε; scale=1, fixedrate=false, metric=Chebyshev())
148211
# Check fixed recurrence rate - ε must be within (0, 1)
149212
if fixedrate
150213
sfun = (m) -> quantile(m[:], ε)
151214
return crossrecurrencematrix(x, y, 1; scale=sfun, fixedrate=false, metric=metric)
152215
else
153216
scale_value = _computescale(scale, x, y, metric)
154-
return _crossrecurrencematrix(x, y, ε*scale_value, metric)
217+
spm = _crossrecurrencematrix(x, y, ε*scale_value, metric)
218+
return spm
155219
end
156220
end
157221

@@ -195,7 +259,7 @@ end
195259
#### Joint recurrence matrix ####
196260

197261
"""
198-
jointrecurrencematrix(x, y, ε; kwargs...)
262+
JointRecurrenceMatrix(x, y, ε; kwargs...)
199263
200264
Create a joint recurrence matrix from the time series `x` and `y`.
201265
@@ -205,12 +269,12 @@ simultaneously. It is calculated by the element-wise multiplication
205269
of the recurrence matrices of `x` and `y`. If `x` and `y` are of different
206270
length, the recurrences are only calculated until the length of the shortest one.
207271
208-
See [`recurrencematrix`](@ref) for details, references and keywords.
209-
See also: [`crossrecurrencematrix`](@ref).
272+
See [`RecurrenceMatrix`](@ref) for details, references and keywords.
273+
See also: [`CrossRecurrenceMatrix`](@ref).
210274
"""
211-
function jointrecurrencematrix(x, y, ε; kwargs...)
275+
function JointRecurrenceMatrix(x, y, ε; kwargs...)
212276
n = min(size(x,1), size(y,1))
213-
rm1 = recurrencematrix(x[1:n,:], ε, kwargs...)
214-
rm2 = recurrencematrix(y[1:n,:], ε, kwargs...)
215-
return rm1 .* rm2
277+
rm1 = RecurrenceMatrix( (@view x[1:n,:]), ε, kwargs...)
278+
rm2 = RecurrenceMatrix( (@view y[1:n,:]), ε, kwargs...)
279+
return JointRecurrenceMatrix(rm1.data .* rm2.data)
216280
end

src/plot.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ function checkgridsize(width::T, height::T, dims::Tuple{T,T}) where T<:Integer
88
(height,width-1) => height/(width-1))
99
distances = Dict(d=>(r-ratio) for (d,r) in intratios)
1010
distancesigns = sign.(collect(values(distances)))
11-
if all(distancesigns .>= 0) || all(distancesigns .<= 0)
11+
if all(x -> x >= 0, distancesigns) || all(x -> x <= 0, distancesigns)
1212
width_adj = round(Integer, height*dims[1]/dims[2])
1313
height_adj = round(Integer, width*dims[2]/dims[1])
1414
width = min(width, width_adj)
1515
height = min(height, height_adj)
16-
@warn """the specified dimensions are not proportional to the matrix size
17-
The size of the plot will be $width×$height."""
16+
@warn "The specified dimensions are not proportional to the matrix size. "*
17+
"The size of the plot will be $width×$height."
1818
end
1919
(width, height)
2020
end
@@ -29,7 +29,7 @@ function overlapgrid(m::T, n::T) where T<:Integer
2929
end
3030

3131
# Calculate the level of "gray" (0=white, 1=black) corresponding to a matrix block
32-
function block2grayscale(x::AbstractMatrix, rind::Tuple{T,T}, cind::Tuple{T,T}) where T<:Integer
32+
function block2grayscale(x, rind::Tuple{T,T}, cind::Tuple{T,T}) where T<:Integer
3333
submat = @view x[rind[1]:rind[2], cind[1]:cind[2]]
3434
ratio = count(!iszero, submat)/prod(size(submat))
3535
end
@@ -63,7 +63,7 @@ is calculated for each element of the grid, proportional to the number of
6363
recurrent points contained in it. The levels of gray are coded as numbers of the
6464
same type as the black and white codes.
6565
"""
66-
function recurrenceplot(x::AbstractMatrix, bwcode::Tuple{TT,T}=(0.0,1.0);
66+
function recurrenceplot(x, bwcode::Tuple{TT,T}=(0.0,1.0);
6767
exactsize=false, kwargs...) where {TT<:Real, T<:Real}
6868

6969
dims = size(x)

0 commit comments

Comments
 (0)