Reworking the API and Docs to merge in DynamicalSystems.jl#19
Reworking the API and Docs to merge in DynamicalSystems.jl#19
Conversation
|
Following the todo list, I'm renaming the microstates shape types, using something like: "Rect" -> "RectMicrostate", and also removing the recurrence expression dependence from them. However, I don't understand the item "Furthermore, they should be orthogonal inputs to the main outcome space t" ... |
…rface; add some recurrence microstates convenience constructors
|
I changed the histogram input, it now uses the RecurrenceMicrostate type instead of the core. I also implemented the interface with ComplexityMeasures, but I am not sure whether it is working correctly. When I tried to test it, I got the following error: About the outcomes, I used the indices given by "eachindex(counts)". I'm not sure if it is the best approach. Other alternatives could be matrix representations, but for spatial data this can be problematic, not to mention the memory allocation cost. Another option is the binary representation, but it can be harder to read. Since the decimal representation is already used for counting the microstates when computing the histogram, the indices of eachindex(counts) are also a representation of the microstates. Another question: What do I do with the distribution functions? Delete them, or try to adapt them and mark them as deprecated? |
|
when reporting error messages please put the whole stack trace (and make sure to wrap it in tripple back ticks so it is formatted as code) . I don't know if your error is internal or just because you didn't pass the proper outcome space struct.
This is something we can think at the end, it is not important right now. I assume that for a given |
|
Understood. I fixed it. I was returning the wrong value in the function
Yes. A recurrence microstate can be interpreted as a binary number, since it is composed of 0s and 1s. When we define the microstate shape, we also define how to read this microstate as a binary number. Then, the package using the sampling process takes an initial position of the time series, Each of these recurrences are associated with a power of 2 from a power vector provided by the function And, of course, each index can be easily converted to its binary representation using For a 3x3 microstate, it is: Or for a triangle microstate with size 3 (the reading order is different): Note: |
|
I think it is working now. I had to add a function ComplexityMeasures.probabilities(o::RecurrenceMicrostates, x, y)
return first(probabilities_and_outcomes(o, x, y))
end
function ComplexityMeasures.probabilities_and_outcomes(o::RecurrenceMicrostates, x, y)
cts, outs = counts_and_outcomes(o, x, y)
probs = Probabilities(cts, outs)
return probs, outcomes(probs)
endI also remove the Then, the RecurrenceMicrostates struct now is: struct RecurrenceMicrostates{MS <: MicrostateShape, RE <: RecurrenceExpression, SM <: SamplingMode} <: ComplexityMeasures.CountBasedOutcomeSpace
shape::MS
expr::RE
sampling::SM
end |
|
Alright @gabriel-ferr I am back here. I've updated the structure of the documentation to reflect a more standardized setup where information across DynamicalSystems.jl shares the same strcuture and hence it is easier to access. Here is the plan I propose going forwards:
Done! |
|
Hello @Datseris 0/ I have two questions:
# All of these quantities like laminarity are in fact _complexity measures_
# which is why RecurrenceMicrostateAnalysis.jl fits so well within the
# interface of ComplexityMeasures.jl.Would it be a good idea to rewrite these quantifiers (DET, LAM, RR, and Disorder) as a However, I'm not entirely sure where each of them fits 🙃. RR as information, and the others as complexity?? My intuition is that this could improve the integration between the two libraries and make it easier to use. Edit: Currently RMA.jl implements a owner type
I was thinking about adding a fourth question:
Would it be okay to include this in the current PR, or would it be better to finish this one and open a new PR later? About it: # TODO: The two numbers reported above are not the same.
# Perhaps the logarithm base is off?Yes, internally |
|
Question 1: yes. How to make a distinction: quantities that can be estimated from probabilities are information measures. Quantities that must be estimated directly from input data are complexity measures. Perhaps you can write here a list of each measure and where you think it fits before committing to changing the code? Question 2: better to do it in a new PR. You can open an issue (feature request) listing this for now so that you don't forget it. Point 3: logarithm base. All default functions from ComplexityMeasures.jl use logarithm with base 2, so if we go ahead with the change outlined in question 1, the same will be done for all recurrence measures here. So in the end the two numbers will be the same, it will be taken care of internally. |
Understood, I'll open an issue 🙂
Ok, I'll change all to use base 2.
Ok, let's try it.
measure(settings::Disorder{N}, probs::Probabilities, norm_param::Int) # for a distribution
measure(settings::Disorder{N}, class::Int, probs::Probabilities) # for a specific classReally, classify them is a little strange ... but probably: RecurrenceRate <: DiscreteInfoEstimator
RecurrenceDeterminism <: ComplexityEstimator
RecurrenceLaminarity <: ComplexityEstimator
Disorder <: ComplexityEstimator
PartialDisorder <: DiscreteInfoEstimator
PartialClassDisorder <: DiscreteInfoEstimator |
This is a common missconception. What you wrote above means that Recurrence rate is not an information measure. Because it cannot be estimated from any probability distribution. It has to be the probabilities of the RMA distribution. Think of the Shannon entropy: doesn't matter Where the probabilities come from, their Shannon entropy is the same. Now what about permutation entropy? It is the shannon entropy if probabilities of the ordinal pattern distributions. As such, permutation entropy is not an information measure, it is a complexity measure. So, in summary, I can see now that all recurrence measures are complexity measures and not information measures! The next question is: is there any overlap in the estimation of these measures? Do you have to estimate first same things (same probabilities) for many various measures such as recurrence rate or determinism? |
|
Oh, fine, I understand now.
Well, recurrence entropy and recurrence rate can be estimated from any recurrence distribution — e.g. if you compute a recurrence distribution for microstates For determinism and laminarity you need to use a square Disorder only works for square microstates. Usually Then, you don't need to estimate same probabilities for all of these things, and in some situations you cannot do it. But if you want, it is possible (e.g. always using |
|
Okay I think there is two things we should do:
|
|
Hello @Datseris 0/ I think I’ve finished the documentation, but there are two things that still need to be fixed:
disorder = Disorder()it prints everything to the terminal... for I overwrote the default display with: function Base.show(io::IO, ::MIME"text/plain", x::Disorder)
print(io, "TODO: Disorder")
endand I did the same for That’s it for now... I’ll fix the tests next 🙂 Edit: about the function similar to |
|
Fantastic Gabriel, I'll have a look! |
Datseris
left a comment
There was a problem hiding this comment.
This is all great work Gabriel. I only have minor comments. Once these are addressed this should be good to go! I'll add a second example on recurrence microstates missing patterns later. Regarding your comment on the display, I'll have a look at it as well.
| positions of the `AbstractGPUVector` are accessed (`i` for `x`, and `j` for `y`), and `n` is the number | ||
| of dimensions of the system. | ||
| 3. Add a docstring to your metric describing it. | ||
| 4. Add your metric to `docs/src/api.md`. |
There was a problem hiding this comment.
| 4. Add your metric to `docs/src/api.md`. | |
| using RecurrenceMicrostatesAnalysis | |
| using Distances: Euclidean |
| ```@docs | ||
| RecurrenceMicrostatesAnalysis | ||
| ``` | ||
|
|
There was a problem hiding this comment.
We have moved all packages to display as the starting information to the docs their own README.md file. E>g., have a look at the Attractors.jl docs to see how this is done (where the module Attractors is defined).
In the readme you should also have the citation request info.
There was a problem hiding this comment.
Yes, this is the first issue I mentioned. The README.md apparently contains a broken link, which causes an error when Documenter.jl checks links. I removed it temporarily to allow the docs to build.
I think I fixed it in this PR, but I’ll check it again and standardize the README following the other packages.
| Finally, developers interested in contributing to RecurrenceMicrostatesAnalysis.jl are encouraged to read the [RecurrenceMicrostatesAnalysis.jl for Devs](@ref) section. | ||
|
|
||
| ## Input data for RecurrenceMicrostatesAnalysis.jl | ||
| ### Input data for RecurrenceMicrostatesAnalysis.jl |
There was a problem hiding this comment.
The inpout and output sections should be in the API page.
|
|
||
| # ## Crash-course into RMA | ||
|
|
||
| # Recurrence Plots (RPs) were introduced in 1987 by Eckmann et al. |
There was a problem hiding this comment.
I think this sentence should be removed.
|
|
||
| #  | ||
|
|
||
| # A recurrence microstate is a local structure extracted from an RP. For a given microstate |
There was a problem hiding this comment.
| # A recurrence microstate is a local structure extracted from an RP. For a given microstate | |
| # A recurrence microstate is a local structure extracted from a recurrence matrix. For a given microstate |
|
|
||
| # 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 as we described in [Input data for RecurrenceMicrostatesAnalysis.jl](@ref). |
There was a problem hiding this comment.
I recommend to not refer to section headers by name, but rather use an id. Documenter.jl allows you to encapsulate a section header in a [text](@id id_name) specifier, and later refer to it as [hyperlinked](@ref id_name). This is more robust.
| @@ -0,0 +1,94 @@ | |||
| # GPU | |||
There was a problem hiding this comment.
I think this section should become a final subsection of the main tutorial. It feels a somewhat central part of this package that it allows this flexibility of computing over different architectures so it should be in the main tutorial as one of the "key features". This also allows you to re-use the data generated in the main tutorial, reducing the overall length here.
There was a problem hiding this comment.
Ok, I’ll do it, but we cannot run the code in this section in Actions because it requires a GPU >.<
I tested it using Metal.jl on my PC, and I can also test it using CUDA on a machine in the physics department here.
Of course, I tested all of this code locally before writing it here 🙂 (I'll check again using CUDA later)
There was a problem hiding this comment.
It's okay if it cannot run in Actions, you can write a julia code snippet by doing writing markdown julia snippet, like # ```julia.
| complexity(WindowedDisorder(W, N; metric = GPUEuclidean()), X_gpu) | ||
| ``` | ||
|
|
||
| !!! info "Performance" |
There was a problem hiding this comment.
Haha, this is great but why not prove it? You should paste here a runnable code snippet that you run on your local machine and paste the output.
| # In this section, we provide some examples where it is possible | ||
| # to apply RMA to analyze data. | ||
|
|
||
| # ## Classifying data with a multi-layer perceptron and RMA |
There was a problem hiding this comment.
This example needs a bit more clarification.
- What are you classifying? What are you trying to achieve? You are trying to classify the data into what? Into e.g., chaotic and non chaotic regimes? Below you state "classify them based on a parameter used to generate them", but what does this mean? You have 5 parameters and you are hoping to generate 5 classes?
|
@gabriel-ferr , here is the answer to your pretty printing question. You have to add a new method to the function |
High level description: rework API so that it directly inherits and expands the types and functions from ComplexityMeasures.jl. Also re-work the docs to have the style of DynamicalSystems.jl with a main Tutorial and then a formal API page that lists all docstrings.