|
| 1 | +######################################### |
| 2 | +# Text-based plotting |
| 3 | +######################################### |
| 4 | +""" |
| 5 | + scatterdata(R::ARM) -> xs, ys |
| 6 | +Transform the data of a recurrence matrix to scatter data `xs, ys`. |
| 7 | +""" |
| 8 | +function scatterdata(R::ARM) # TODO: scan every ÷100 elements depending on size? |
| 9 | + rows = rowvals(R) |
| 10 | + is = zeros(Int, nnz(R)) |
| 11 | + js = zeros(Int, nnz(R)) |
| 12 | + k = 1; |
| 13 | + m, n = size(R) |
| 14 | + for j = 1:n |
| 15 | + for i in nzrange(R, j) |
| 16 | + is[k] = j |
| 17 | + js[k] = rows[i] |
| 18 | + k += 1 |
| 19 | + end |
| 20 | + end |
| 21 | + return is, js |
| 22 | +end |
| 23 | + |
| 24 | +using UnicodePlots |
| 25 | +export textrecurrenceplot |
| 26 | + |
| 27 | +textrecurrenceplot(R::ARM; kwargs...) = textrecurrenceplot(stdout, R::ARM; kwargs...) |
| 28 | + |
| 29 | +""" |
| 30 | + textrecurrenceplot([io,] R; minh = 25, maxh = 0.5, ascii, kwargs...) -> u |
| 31 | +
|
| 32 | +Obtain a text-scatterplot representation of a recurrence matrix `R` to be displayed in |
| 33 | +`io` (by default `stdout`). The matrix spans at minimum `minh` rows and at maximum |
| 34 | +`maxh*displaysize(io)[1]` (i.e. by default half the display). |
| 35 | +As we always try to plot in equal aspect ratio, if the width of the plot is even less, |
| 36 | +the minimum height is dictated by the width. |
| 37 | +
|
| 38 | +The keyword `ascii::Bool` can ensure that all elements of the plot are ASCII characters |
| 39 | +(`true`) or Unicode (`false`). |
| 40 | +
|
| 41 | +The rest of the `kwargs` are propagated into `UnicodePlots.scatterplot`. |
| 42 | +
|
| 43 | +Internally this function calls `RecurrenceAnalysis.scatterdata` to transform |
| 44 | +a recurence matrix into scatter data. |
| 45 | +""" |
| 46 | +function textrecurrenceplot(io::IO, R::ARM; minh = 25, maxh = 0.5, ascii = nothing, kwargs...) |
| 47 | + @assert maxh ≤ 1 |
| 48 | + h, w = displaysize(io) |
| 49 | + h = max(minh, round(Int, maxh * h)) # make matrix as long as half the screen (but not too short) |
| 50 | + s = 2.4 # scale that visually brings width and height to equal aspect ratio |
| 51 | + if w < round(Int, h*s) # ensure equal aspect ratio |
| 52 | + h = round(Int, w/s) |
| 53 | + else |
| 54 | + w = round(Int, h*s) |
| 55 | + end |
| 56 | + |
| 57 | + is, js = scatterdata(R) |
| 58 | + n, m = size(R) |
| 59 | + |
| 60 | + if ascii == true |
| 61 | + asciidef = (border = :ascii, canvas = DotCanvas) |
| 62 | + elseif ascii == false |
| 63 | + asciidef = (border = :solid, canvas = BrailleCanvas) |
| 64 | + #default: |
| 65 | + elseif ascii == nothing |
| 66 | + # TODO: always use ascii on Jupyter |
| 67 | + if (isdefined(Main, :Juno) && Main.Juno.isactive()) || !Sys.iswindows() |
| 68 | + asciidef = (border = :solid, canvas = BrailleCanvas) |
| 69 | + else |
| 70 | + asciidef = (border = :ascii, canvas = DotCanvas) |
| 71 | + end |
| 72 | + end |
| 73 | + |
| 74 | + # TODO: Change limits to tuples instead of arrays |
| 75 | + UnicodePlots.scatterplot( |
| 76 | + is, js; xlim = [1, n], ylim = [1, m], title = summary(R), labels = false, |
| 77 | + color = :cyan, width = w, height = h, asciidef..., kwargs... |
| 78 | + ) |
| 79 | +end |
| 80 | + |
| 81 | +function Base.show(io::IO, ::MIME"text/plain", R::ARM) |
| 82 | + a = textrecurrenceplot(io, R) |
| 83 | + show(io, a) |
| 84 | +end |
| 85 | + |
| 86 | +######################################### |
| 87 | +# Transform to full plotting |
| 88 | +######################################### |
| 89 | + |
1 | 90 | # Check the assigned width and height of the plot to ensure that they are |
2 | 91 | # approximately proportional to the matrix size |
3 | 92 | function checkgridsize(width::T, height::T, dims::Tuple{T,T}) where T<:Integer |
@@ -42,6 +131,9 @@ grayscale image. By default it returns a matrix with the same size as `x`, |
42 | 131 | but switched axes, containing "black" values in the cells that represent recurrent points, |
43 | 132 | and "white" values in the empty cells. |
44 | 133 |
|
| 134 | +**This function does not do any plotting!** You have to use the return value with |
| 135 | +the plotting library of your choice. |
| 136 | +
|
45 | 137 | The numeric codes for black and white are given in a 2-element tuple as a second |
46 | 138 | optional argument. Its default value is `(0.0, 1.0)`, i.e. black is coded as `0.0` |
47 | 139 | (no brightness) and white as `1.0` (full brightness). The type of the elements |
|
0 commit comments