Skip to content

Commit 9273f9e

Browse files
authored
Allow rqa and associated functions to allow SparseMatrixCSC. (#122)
* Allow `rqa` and associated functions to allow `SparseMatrixCSC`. * `theiler=1` by default for `SparseMatrixCSC`
1 parent b87595b commit 9273f9e

File tree

5 files changed

+51
-25
lines changed

5 files changed

+51
-25
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "RecurrenceAnalysis"
22
uuid = "639c3291-70d9-5ea2-8c5b-839eba1ee399"
33
repo = "https://github.com/JuliaDynamics/RecurrenceAnalysis.jl.git"
4-
version = "1.6.1"
4+
version = "1.6.2"
55

66
[deps]
77
DelayEmbeddings = "5732040d-69e3-5649-938a-b6b4f237613f"

src/matrices/plot.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export recurrenceplot, coordinates, grayscale
77
coordinates(R) -> xs, ys
88
Return the coordinates of the recurrence points of `R` (in indices).
99
"""
10-
function coordinates(R::ARM) # TODO: allow scan every ÷100 elements?
10+
function coordinates(R::SparseMatrixCSC) # TODO: allow scan every ÷100 elements?
1111
rows = rowvals(R)
1212
is = zeros(Int, nnz(R))
1313
js = zeros(Int, nnz(R))
@@ -22,8 +22,8 @@ function coordinates(R::ARM) # TODO: allow scan every ÷100 elements?
2222
end
2323
return is, js
2424
end
25-
26-
recurrenceplot(R::ARM; kwargs...) = recurrenceplot(stdout, R::ARM; kwargs...)
25+
coordinates(R::ARM) = coordinates(R.data)
26+
recurrenceplot(R::Union{ARM,SparseMatrixCSC}; kwargs...) = recurrenceplot(stdout, R::Union{ARM,SparseMatrixCSC}; kwargs...)
2727

2828
"""
2929
recurrenceplot([io,] R; minh = 25, maxh = 0.5, ascii, kwargs...) -> u
@@ -44,7 +44,7 @@ Notice that the accuracy of this function drops drastically for matrices whose s
4444
is significantly bigger than the width and height of the display (assuming each
4545
index of the matrix is one character).
4646
"""
47-
function recurrenceplot(io::IO, R::ARM; minh = 25, maxh = 0.5, ascii = nothing, kwargs...)
47+
function recurrenceplot(io::IO, R::Union{ARM,SparseMatrixCSC}; minh = 25, maxh = 0.5, ascii = nothing, kwargs...)
4848
@assert maxh 1
4949
h, w = displaysize(io)
5050
h = max(minh, round(Int, maxh * h)) # make matrix as long as half the screen (but not too short)
@@ -85,7 +85,7 @@ function recurrenceplot(io::IO, R::ARM; minh = 25, maxh = 0.5, ascii = nothing,
8585
)
8686
end
8787

88-
function Base.show(io::IO, ::MIME"text/plain", R::ARM)
88+
function Base.show(io::IO, ::MIME"text/plain", R::Union{ARM,SparseMatrixCSC})
8989
a = recurrenceplot(io, R)
9090
show(io, a)
9191
end

src/rqa/histograms.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ end
101101

102102
deftheiler(x::Union{RecurrenceMatrix,JointRecurrenceMatrix}) = 1
103103
deftheiler(x::CrossRecurrenceMatrix) = 0
104-
105-
function diagonalhistogram(x::ARM; lmin::Integer=2, theiler::Integer=deftheiler(x), kwargs...)
104+
deftheiler(x::SparseMatrixCSC) = 1
105+
function diagonalhistogram(x::Union{ARM,SparseMatrixCSC}; lmin::Integer=2, theiler::Integer=deftheiler(x), kwargs...)
106106
(theiler < 0) && throw(ErrorException(
107107
"Theiler window length must be greater than or equal to 0"))
108108
(lmin < 1) && throw(ErrorException("lmin must be 1 or greater"))
@@ -113,7 +113,13 @@ function diagonalhistogram(x::ARM; lmin::Integer=2, theiler::Integer=deftheiler(
113113
if issymmetric(x)
114114
# If theiler==0, the LOI is counted separately to avoid duplication
115115
if theiler == 0
116-
loi_hist = verticalhistograms(CrossRecurrenceMatrix(hcat(diag(x,0))),lmin=lmin)[1]
116+
if all(isequal(1),x.nzval)==false #CrossRecurrenceMatrix won't work if all values aren't equal to 1 and theiler=0
117+
xtmp = deepcopy(x)
118+
xtmp.nzval .= 1
119+
loi_hist = verticalhistograms(CrossRecurrenceMatrix(hcat(diag(xtmp,0))),lmin=lmin)[1]
120+
else
121+
loi_hist = verticalhistograms(CrossRecurrenceMatrix(hcat(diag(x,0))),lmin=lmin)[1]
122+
end
117123
end
118124
inside = (dv .< max(theiler,1))
119125
f = 2
@@ -140,7 +146,8 @@ function diagonalhistogram(x::ARM; lmin::Integer=2, theiler::Integer=deftheiler(
140146
return dh
141147
end
142148

143-
function verticalhistograms(x::ARM;
149+
150+
function verticalhistograms(x::Union{ARM,SparseMatrixCSC};
144151
lmin::Integer=2, theiler::Integer=deftheiler(x), distances=true, kwargs...)
145152
(theiler < 0) && throw(ErrorException(
146153
"Theiler window length must be greater than or equal to 0"))
@@ -199,7 +206,7 @@ estimator of the Poincaré recurrence times [2].
199206
recurrence quantifications", in: Webber, C.L. & N. Marwan (eds.), *Recurrence
200207
Quantification Analysis. Theory and Best Practices*, Springer, pp. 3-43 (2015).
201208
"""
202-
function recurrencestructures(x::ARM;
209+
function recurrencestructures(x::Union{ARM,SparseMatrixCSC};
203210
diagonal=true, vertical=true, recurrencetimes=true,
204211
theiler=deftheiler(x), kwargs...)
205212

src/rqa/rqa.jl

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ URL: https://www.nsf.gov/pubs/2005/nsf05057/nmbs/nmbs.pdf
5252
recurrence quantifications", in: Webber, C.L. & N. Marwan (eds.), *Recurrence
5353
Quantification Analysis. Theory and Best Practices*, Springer, pp. 3-43 (2015).
5454
"""
55-
function recurrencerate(R::ARM; theiler::Integer=deftheiler(R), kwargs...)::Float64
55+
function recurrencerate(R::Union{ARM,SparseMatrixCSC}; theiler::Integer=deftheiler(R), kwargs...)::Float64
5656
(theiler < 0) && throw(ErrorException(
5757
"Theiler window length must be greater than or equal to 0"))
5858
if theiler == 0
@@ -69,6 +69,13 @@ end
6969
# Calculate the denominator for the recurrence rate
7070
_rrdenominator(R::ARM; theiler=0, kwargs...) = length(R)
7171

72+
function _rrdenominator(R::SparseMatrixCSC; theiler=0, kwargs...)
73+
74+
(theiler == 0) && (return length(R))
75+
k = size(R,1) - theiler
76+
return k*(k+1)
77+
end
78+
7279
function _rrdenominator(R::M; theiler=0, kwargs...) where
7380
M<:Union{RecurrenceMatrix,JointRecurrenceMatrix}
7481

@@ -153,7 +160,7 @@ is the number of lines of length equal to ``l``.
153160
points inside the Theiler window (see [`rqa`](@ref) for the
154161
default values and usage of the keyword argument `theiler`).
155162
"""
156-
function determinism(R::ARM; kwargs...)
163+
function determinism(R::Union{ARM,SparseMatrixCSC}; kwargs...)
157164
npoints = recurrencerate(R; kwargs...)*_rrdenominator(R; kwargs...)
158165
return _determinism(diagonalhistogram(R; kwargs...), npoints)
159166
end
@@ -171,8 +178,7 @@ end
171178
Calculate the divergence of the recurrence matrix `R`
172179
(actually the inverse of [`dl_max`](@ref)).
173180
"""
174-
divergence(R::ARM; kwargs...) = ( 1.0/dl_max(R; kwargs...) )
175-
181+
divergence(R::Union{ARM,SparseMatrixCSC}; kwargs...) = ( 1.0/dl_max(R; kwargs...) )
176182

177183
"""
178184
trend(R[; border=10, theiler])
@@ -217,10 +223,10 @@ Dynamical Systems", in: Riley MA & Van Orden GC, *Tutorials in Contemporary
217223
Nonlinear Methods for the Behavioral Sciences*, 2005, 26-94.
218224
https://www.nsf.gov/pubs/2005/nsf05057/nmbs/nmbs.pdf
219225
"""
220-
trend(R::ARM; theiler=deftheiler(R), kwargs...) =
226+
trend(R::Union{ARM,SparseMatrixCSC}; theiler=deftheiler(R), kwargs...) =
221227
_trend(tau_recurrence(R); theiler=theiler, kwargs...)
222-
223-
function tau_recurrence(R::ARM)
228+
229+
function tau_recurrence(R::Union{ARM,SparseMatrixCSC})
224230
n = minimum(size(R))
225231
rv = rowvals(R)
226232
rr_τ = zeros(n)
@@ -290,7 +296,7 @@ is the number of lines of length equal to ``v``.
290296
points inside the Theiler window (see [`rqa`](@ref) for the
291297
default values and usage of the keyword argument `theiler`).
292298
"""
293-
function laminarity(R::ARM; kwargs...)
299+
function laminarity(R::Union{ARM,SparseMatrixCSC}; kwargs...)
294300
npoints = recurrencerate(R)*_rrdenominator(R; kwargs...)
295301
return _laminarity(verticalhistograms(R; kwargs...)[1], npoints)
296302
end
@@ -308,8 +314,7 @@ default values and usage of the keyword argument `theiler`).
308314
The trapping time is the average of the vertical line structures and thus equal
309315
to [`vl_average`](@ref).
310316
"""
311-
trappingtime(R::ARM; kwargs...) = vl_average(R; kwargs...)
312-
317+
trappingtime(R::Union{ARM,SparseMatrixCSC}; kwargs...) = vl_average(R; kwargs...)
313318
###########################################################################################
314319
# 3. Based on recurrence times
315320
###########################################################################################
@@ -327,8 +332,7 @@ default values and usage of the keyword argument `theiler`).
327332
328333
Equivalent to [`rt_average`](@ref).
329334
"""
330-
meanrecurrencetime(R::ARM; kwargs...) = rt_average(R; kwargs...)
331-
335+
meanrecurrencetime(R::Union{ARM,SparseMatrixCSC}; kwargs...) = rt_average(R; kwargs...)
332336

333337
"""
334338
nmprt(R[; lmin=2, theiler])
@@ -349,8 +353,7 @@ of recurrence times [1].
349353
[DOI:10.1103/physreve.75.036222](https://doi.org/10.1103/physreve.75.036222)
350354
351355
"""
352-
nmprt(R::ARM; kwargs) = maximum(verticalhistograms(R; kwargs...)[2])
353-
356+
nmprt(R::Union{ARM,SparseMatrixCSC}, kwargs...) = maximum(verticalhistograms(R;theiler=deftheiler(R), kwargs...)[2])
354357
###########################################################################################
355358
# 4. All in one
356359
###########################################################################################

test/dynamicalsystems.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,20 @@ dict_keys = ["Sine wave","White noise","Hénon (chaotic)","Hénon (periodic)"]
124124
@test amat == Matrix(rmat) - I
125125
rna_dict = rna(rmat)
126126
rna_dict[:density] == recurrencerate(rmat)
127+
128+
#test sparse matrices
129+
rqapar_sparse = rqa(rmat.data, theiler=1, lmin=3, border=20)
130+
rqadiag_sparse = rqa(rmat.data, theiler=1, lmin=3, border=20, onlydiagonal=true)
131+
for p in keys(rqadiag_sparse)
132+
@test rqapar_sparse[p]==rqadiag_sparse[p]
133+
end
134+
135+
#check for erroring here with sparse matrices
136+
@windowed(rrw2 = recurrencerate(rmat.data,theiler=1), width=50, step=40)
137+
@windowed(rqaw2 = rqa(rmat.data,theiler=1), width=50, step =40)
138+
@test rqaw2[:RR]==rrw2
139+
rc1 = coordinates(rmat)
140+
rc2 = coordinates(rmat.data)
141+
@test isequal(rc1[1],rc2[1])
142+
@test isequal(rc2[2],rc2[2])
127143
end

0 commit comments

Comments
 (0)