Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ DynamicalSystems = "61744808-ddfa-5f27-97ff-6e42cc95d634"
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
RecurrenceMicrostatesAnalysis = "cb83a08b-85c6-4e94-91aa-4e946c7d4f0c"
StateSpaceSets = "40b095a5-5852-4c12-98c7-d43bf788e795"
Expand Down
65 changes: 34 additions & 31 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,48 @@ using DocumenterCitations
using RecurrenceMicrostatesAnalysis
using StateSpaceSets

# Convert tutorial file to markdown
import Literate
Literate.markdown("src/tutorial.jl", "src"; credit = false)

pages = [
"Welcome" => "index.md",
"Tutorial" => [
"Distributions" => "tutorial/distributions.md",
"Quantifiers" => "tutorial/quantifiers.md",
"Recurrence Functions" => "tutorial/recurrences.md",
"Shapes and Sampling" => "tutorial/shapes_and_sampling.md",
"GPU" => "tutorial/gpu.md",
"Utils" => "tutorial/utils.md",
],
"Examples" => [
"Machine Learning" => "examples/ml.md",
],
"Developers" => "dev.md",
"Tutorial" => "tutorial.md",
# "API" => "api.md",
# "Tutorial" => [
# "Distributions" => "tutorial/distributions.md",
# "Quantifiers" => "tutorial/quantifiers.md",
# "Recurrence Functions" => "tutorial/recurrences.md",
# "Shapes and Sampling" => "tutorial/shapes_and_sampling.md",
# "GPU" => "tutorial/gpu.md",
# "Utils" => "tutorial/utils.md",
# ],
# "Ecosystem Integration" => [
# "Machine Learning" => "examples/ml.md",
# ],
"Developers docs" => "dev.md",
"References" => "refs.md",
]

# Apply JuliaDynamics theme, choosing a specific branch (easier debugging)
github_user = "JuliaDynamics"
branch = "master"
download_path = "https://raw.githubusercontent.com/$github_user/doctheme/$branch/"

import Downloads
Downloads.download(
"$download_path/build_docs_with_style.jl",
joinpath(@__DIR__, "build_docs_with_style.jl")
)
include("build_docs_with_style.jl")

using DocumenterCitations

bib = CitationBibliography(
joinpath(@__DIR__, "refs.bib");
style=:authoryear
)

makedocs(
sitename = "RecurrenceMicrostatesAnalysis.jl",
format = Documenter.HTML(
prettyurls = true,
collapselevel = 3,
),
modules = [RecurrenceMicrostatesAnalysis, StateSpaceSets, ComplexityMeasures],
pages = pages,
doctest = false,
checkdocs = :exported,
warnonly = [:doctest, :missing_docs],
plugins = [bib]
build_docs_with_style(pages, RecurrenceMicrostatesAnalysis, ComplexityMeasures, StateSpaceSets;
expandfirst = ["index.md"], bib,
)

deploydocs(
repo = "github.com/DynamicsUFPR/RecurrenceMicrostatesAnalysis.jl.git",
target = "build",
push_preview = true,
versions = ["stable" => "v^", "v#.#", "dev" => "dev"]
)
79 changes: 79 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# API

# ## Probabilities and counts

```@docs
RecurrenceMicrostates
RecurrenceExpression
CorridorRecurrence
ThresholdRecurrence # What uised to be called Standard
```

# ## Specification of recurrence microstates

```@docs
RecurrenceExpression
MicrostateShape
```




Alternatively, a [`RecurrenceExpression`](@ref) can be specified directly:
```julia
distribution([x], expr::RecurrenceExpression, n::Int; kwargs...)
```
**Example:**
```@example quick_example
expr = Corridor(0.05, 0.27)
dist = distribution(ssset, expr, 2)
```

If a custom [`MicrostateShape`](@ref) is required, the call simplifies to:
```julia
distribution([x], shape::MicrostateShape; kwargs...)
```
**Example:**
```@example quick_example
shape = Triangle(Standard(0.27), 3)
dist = distribution(ssset, shape)
```


# ## Sampling modes

```@docs
SRandom
what else?
```

# ## Computational specification

```@docs
CPUCore
GPUCore
```

The following needs to change:

```
This method automatically selects a [`CPUCore`](@ref) when `x` is a [`StateSpaceSet`](@ref)
and a [`GPUCore`](@ref) when `x` is an `AbstractGPUVector`. By default, square microstates of size `n` are used.

Additional keyword arguments include:
- `rate::Float64`: Sampling rate (default: `0.05`).
- `sampling::SamplingMode`: Sampling mode (default: [`SRandom`](@ref)).
- `metric::Metric`: Distance metric from [Distances.jl](https://github.com/JuliaStats/Distances.jl). When using a [`GPUCore`](@ref), a [`GPUMetric`](@ref) must be provided.
```

all these keyword arguments should not be given to the
`probabilities` function. THey should be given to a generic computation type that is a field of the RecurrenceMicrostates!!!

The following must be in the GPUCore struct:

!!! warning
GPU backends require inputs of type `Float32`. `Float64` inputs are not supported on GPU.



# ##
6 changes: 3 additions & 3 deletions docs/src/index.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# RecurrenceMicrostatesAnalysis.jl

```@docs
RecurrenceMicrostatesAnalysis
```

!!! todo "GitHub"
RecurrenceMicrostatesAnalysis.jl is an open-source package available on [GitHub](https://github.com/DynamicsUFPR/RecurrenceMicrostatesAnalysis.jl).
!!! info "Citation and credit"
If you find this package useful, please consider giving it a star on GitHub and don't forget to cite [our work](https://doi.org/10.1063/5.0293708). 😉


## About the documentation
The documentation of **RecurrenceMicrostatesAnalysis.jl** is designed to explain how to use the package while also introducing the theoretical background of the RMA framework. The bibliography used throughout the documentation is listed in the [References](@ref) section; **please remember to cite the appropriate works if you use them**.
Expand Down
178 changes: 178 additions & 0 deletions docs/src/tutorial.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# # Tutorial for RecurrenceMicrostatesAnalysis.jl

# In this tutorial we go through a typical usage of **RecurrenceMicrostatesAnalysis.jl**.
# We'll see how to calculate distributions of recurrence microstates,
# how to optimize our choices regarding the distribution generation,
# and how to perform Recurrence Microstate Analysis (RMA).

# But first, we'll start with a crash course!

# ## Crash-course into RMA

# Recurrence Plots (RPs) were introduced in 1987 by Eckmann et al.
# [Eckmann1987RP](@cite) as a method for analyzing dynamical systems through recurrence
# properties.

# Consider a time series $\vec{x}_i \in \mathbb{R}^d$, $i \in \{1, 2, \dots, K\}$,
# where $K$ is the length of the time series and $d$ is the dimension of the phase space.
# The recurrence plot is defined by the recurrence matrix
# ```math
# R_{i,j} = \Theta(\varepsilon - \|\vec x_i - \vec x_j\|),
# ```
# where $\Theta(\cdot)$ denotes the Heaviside step function and $\varepsilon$ is the recurrence
# threshold.

# The following figure shows examples of recurrence plots for different systems:
# (a) white noise;
# (b) a superposition of harmonic oscillators;
# (c) a logistic map with a linear trend;
# (d) Brownian motion.

# ![Image of four RPs with their timeseries](../assets/rps.png)

# A recurrence microstate is a local structure extracted from an RP. For a given microstate
# shape and size, the set of possible microstates is finite. For example, square microstates
# with size $N = 2$ yield $16$ distinct configurations.

# ![Image of the 16 squared microstates to N = 2](../assets/microstates.png)

# Recurrence Microstates Analysis (RMA) uses the probability distribution of these microstates
# as a source of information for characterizing dynamical systems.

# ## Probability distributions of recurrence microstates

# Finding and counting microstates in data is straightforward.
# It amounts to passing the input data to the `probabilities` function,
# while specifying the options of the `RecurrenceMicrostates` estimator,
# which essentially means e.g., what sort of distance threshold defines a recurrence,
# and what is maximum microstate size to consider.

# Let's first generate some data of a chaotic map using **DynamicalSystems.jl**:

using DynamicalSystemsBase

function henon_rule(u, p, n)
x, y = u # system state
a, b = p # system parameters
xn = 1.0 - a*x^2 + y
yn = b*x
return SVector(xn, yn)
end

u0 = [0.2, 0.3]
p0 = [1.4, 0.3]

henon = DeterministicIteratedMap(henon_rule, u0, p0)

total_time = 10_000
X, t = trajectory(henon, total_time)
X

# Notice that `X` is already a [`StateSpaceSet`](@ref). Because **RecurrenceMicrostatesAnalysis.jl**
# is part of **DynamicalSystems.jl**, this data type is the preferred input type.
# Other types are also possible however, see the documentation of the
# [`RecurrenceMicrostates`](@ref) central type for more.

# Now, we specify the recurrence microstate configuration

ε = 0.27
N = 2
rmspace = RecurrenceMicrostates(ε, N)

# and finally call

probs = probabilities(ospace, X)

# The [`probability`](@ref) function is the same function as in [`ComplexityMeasures`](@ref).
# Given an outcome space, that is a way to _symbolize_ input data into discrete outcomes,
# `probabilities` return the probability (relative occurrence frequency) for each outcome.
# And indeed, the recurrence microstates is an outcome space.

# If instead of the probabilities of the microstates you want their direct count
# simply replace `probabilities` with `counts`.

counts(rmspace, X)


# ## Recurrence microstates analysis (RMA)

# To actually analyze your data, there are two ways forwards.
# One way, is to utilize these probabilities within the interface provided
# by [`ComplexityMeasures`](@ref) to calculate entropies.
# For example, the corresponding Shannon entropy is

entropy(Shannon(), probs)

# (note that the API of `ComplexityMeasures` is re-exported by `RecurrenceMicrostateAnalysis`).
# This number corresponds to the **recurrence microstate entropy** as defined in our
# publication [`WhichPaperIscorrectToCite`](@cite).

# `ComplexityMeasures` allows the convenience syntax of

entropy(Shannon(), rmspace, X)

# so in this case we wouldn't need to calculate the probabilities directly.
# Naturally, any other entropy could be estimated instead,

entropy(Tsallis(), rmspace, X)

# although we haven't explored alternative entropies in research yet.

# The secon way forwards is the more traditional recurrence quantification analysis
# route, where you estimate (approximate really) various quantities
# such as laminarity that fundamentally relate with the context of recurrences.
# For example,

# These quantities are listed in XXX.

# Note that if instead of



# ## Optimizing recurrence specification

# In the above example we blindly selected the recurrence threshold `ε`.
# A better approach is to optimize it, so it (for example) maximizes
# the recurrence microstate entropy.
# This can be done with the [`optimize`](@ref) function

ε, S = optimize(Threshold(), RecurrenceEntropy(), X, N)
rmspace = RecurrenceMicrostates(ε, N)
h = entropy(Shannon(), rmspace, X)
(h, S)


# ## Custom specification of recurrence microstates

# When we write `rmspace = RecurrenceMicrostates(ε, N)`,
# we are in fact accepting a default definition for both what counts as a recurrence
# as well as what recurrence microstates to examine.
# We can alter either, by choosing the recurrence expression, or the specific
# microstate(s) we wish to analyze. For example

expr = CorridorRecurrence(0.05, 0.27)
shape = MicrostateTriangle(lalala)
rmspace = RecurrenceMicrostates(; expression = expr, shape)
probabilities(rmspace, X)

# More details are given in [`RecurrenceMicrostates`](@ref)
# and the [API](@ref) section of the docs.


# ## Cross recurrence plots

# For cross-recurrences, nearly nothing changes for you, nor for the source code
# of the code base! Simply call `function(..., rmspace, X, Y)`, adding an additional
# final argument `Y` corresponding to the second trajectory from which cross recurrences are estimated.

# For example, here are the cross recurrence microstate distribution for
# the original Henon map trajectory and one at slightly different parameters

set_parameter!(henon, 1, 1.35)
Y, t = trajectory(henon, total_time)
probabilities(rmspace, X, Y)

# This augmentation from one to two input data
# works for all functions discussed in this tutorial.

# ## Spatial data
14 changes: 14 additions & 0 deletions docs/src/tutorial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
```@meta
EditURL = "tutorial.jl"
```

````@example tutorial
using Distributions, RecurrenceMicrostatesAnalysis
data = rand(Uniform(0, 1), 10_000);
ssset = StateSpaceSet(data)

ε = 0.27
N = 2
dist = distribution(ssset, ε, N)
````

Loading
Loading