Code Monkey home page Code Monkey logo

ripserer.jl's Introduction

Ripserer.jl

Flexible and efficient persistent homology computation.

Coverage Status Build Status Documentation status

Introduction

Ripserer is a pure Julia implementation of the Ripser algorithm for computing persistent homology. Its aims are to be easy to use, generic, and fast.

See the documentation for more information and usage examples.

If you're looking for persistence diagram-related functionality such as Wasserstein or bottleneck distances, persistence images, or persistence curves, please see PersistenceDiagrams.jl.

Quick start

This package is registered. To install it, run the following.

julia> using Pkg
julia> Pkg.add("Ripserer")

Now, generate some data.

julia> data = [(rand(), rand(), rand()) for _ in 1:200]

The main exported function in this package is ripserer. By default, it computes Vietoris-Rips persistent homology on point cloud data and distance matrices.

julia> ripserer(data)
# 2-element Vector{PersistenceDiagrams.PersistenceDiagram}:
#  200-element 0-dimensional PersistenceDiagram
#  84-element 1-dimensional PersistenceDiagram

Several other filtration types are supported. We tell ripserer to use them by passing them as the first argument.

julia> ripserer(EdgeCollapsedRips, data)
# 2-element Vector{PersistenceDiagrams.PersistenceDiagram}:
#  200-element 0-dimensional PersistenceDiagram
#  84-element 1-dimensional PersistenceDiagram

Sometimes you may want to initialize a filtration in advance.

julia> rips = EdgeCollapsedRips(data, threshold=1)
# EdgeCollapsedRips{Int64, Float64}(nv=200)
julia> ripserer(rips, dim_max=2)
# 3-element Vector{PersistenceDiagrams.PersistenceDiagram}:
#  200-element 0-dimensional PersistenceDiagram
#  84-element 1-dimensional PersistenceDiagram
#  16-element 2-dimensional PersistenceDiagram

Ripserer supports plotting with Plots.jl. Experimental Makie.jl support is also available here.

Plotting persistence diagrams and barcodes is straightforward:

using Plots
result = ripserer(data, dim_max=2)
plot(plot(result), barcode(result)

barcode(result)

ripserer.jl's People

Contributors

github-actions[bot] avatar mtsch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ripserer.jl's Issues

reconstruct_cycles in more than 2-dimension?

Is it possible to implement reconstruct_cycle for more than 2-dimension? Let's say in 3D case, the function will compute all the 2-simplexes that "minimally" surround a 3-dimensional hole.

Also the cycles.jl code has no comment, it's very difficult to understand what is going on, specially in the _find_cycle() function. For example,

best_path = edgetype(g)[]  # what does this line do?
best_sx = first(g.removed) # what does this line do?

Is it possible to add some algorithmic descriptions for the functions in the cycles.jl file? It will be really helpful.

Thanks!! I really appreciate your work.

Error when reconstructing cycles

I get the following error when trying to use the reconstruct cycles function. I have tried manually upgrading the Graphs library to see if that helps but it still gives the same error. I can provide the underlying data if needed. Thank you for including this functionality - I don't see it available in any other packages!

BoundsError: attempt to access Tuple{Int64} at index [2]

Stacktrace:
[1] getindex(t::Tuple, i::Int64)
@ Base ./tuple.jl:29
[2] getindex
@ ~/.julia/packages/StaticArrays/J9itA/src/SArray.jl:62 [inlined]
[3] _next_common
@ ~/.julia/packages/Ripserer/RPZgP/src/base/abstractsimplex.jl:232 [inlined]
[4] iterate
@ ~/.julia/packages/Ripserer/RPZgP/src/base/abstractsimplex.jl:256 [inlined]
[5] iterate
@ ~/.julia/packages/Ripserer/RPZgP/src/base/abstractsimplex.jl:252 [inlined]
[6] outneighbors(g::OneSkeleton{Simplex{1, Float64, Int64}, Rips{Int64, Float64, SparseMatrixCSC{Float64, Int64}}, Simplex{1, Float64, Int64}, SparseMatrixCSC{Float64, Int64}}, u::Int64)
@ Main ./In[108]:63
[7] a_star_impl!(g::OneSkeleton{Simplex{1, Float64, Int64}, Rips{Int64, Float64, SparseMatrixCSC{Float64, Int64}}, Simplex{1, Float64, Int64}, SparseMatrixCSC{Float64, Int64}}, goal::Int64, open_set::DataStructures.PriorityQueue{Int64, Float64, Base.Order.ForwardOrdering}, closed_set::Vector{Bool}, g_score::Vector{Float64}, came_from::Vector{Int64}, distmx::SparseMatrixCSC{Float64, Int64}, heuristic::var"#38#39"{Int64, SparseMatrixCSC{Float64, Int64}}, edgetype_to_return::Type{Graphs.SimpleGraphs.SimpleEdge{Int64}})
@ Graphs ~/.julia/packages/Graphs/7SMZs/src/shortestpaths/astar.jl:43
[8] a_star(g::OneSkeleton{Simplex{1, Float64, Int64}, Rips{Int64, Float64, SparseMatrixCSC{Float64, Int64}}, Simplex{1, Float64, Int64}, SparseMatrixCSC{Float64, Int64}}, s::Int64, t::Int64, distmx::SparseMatrixCSC{Float64, Int64}, heuristic::Function, edgetype_to_return::Type{Graphs.SimpleGraphs.SimpleEdge{Int64}})
@ Graphs ~/.julia/packages/Graphs/7SMZs/src/shortestpaths/astar.jl:94
[9] a_star
@ ~/.julia/packages/Graphs/7SMZs/src/shortestpaths/astar.jl:81 [inlined]
[10] _find_cycle(g::OneSkeleton{Simplex{1, Float64, Int64}, Rips{Int64, Float64, SparseMatrixCSC{Float64, Int64}}, Simplex{1, Float64, Int64}, SparseMatrixCSC{Float64, Int64}}, dists::SparseMatrixCSC{Float64, Int64})
@ Main ./In[108]:115
[11] reconstruct_cycle_2(filtration::Rips{Int64, Float64, SparseMatrixCSC{Float64, Int64}}, interval::PersistenceDiagrams.PersistenceInterval, r::Simplex{1, Float64, Int64}; distances::SparseMatrixCSC{Float64, Int64})
@ Main ./In[108]:179
[12] reconstruct_cycle_2(filtration::Rips{Int64, Float64, SparseMatrixCSC{Float64, Int64}}, interval::PersistenceDiagrams.PersistenceInterval, r::Simplex{1, Float64, Int64})
@ Main ./In[108]:158
[13] reconstruct_cycle_2(filtration::Rips{Int64, Float64, SparseMatrixCSC{Float64, Int64}}, interval::PersistenceDiagrams.PersistenceInterval)
@ Main ./In[108]:158
[14] top-level scope
@ In[109]:2

Performance advice

Hi,

Thanks for this awesome package.

I'm trying to use it on some fairly large set of data points (~10k data points of 5-10 dimensions). This is already after substantial dimensionality reduction and downsampling, but it still computationally very demanding to run the algorithm on.

image

Would you have any advice on things to try to speed it up? Would downsampling (e.g. dropping X% of the data points) would be a valid approach?

Thank you,
Federico

Codecov migration to marketplace app

Hi, Tom from Codecov here.

We noticed that you are using Codecov with fairly high frequency, and we’re so excited to see that! However, because you are not using our app, you may have experienced issues with uploading reports or viewing coverage information. This is due to rate-limiting issues from GitHub.

In order to prevent any future outages, we ask that you move over to our GitHub app integration.

The process is extremely simple and shouldn’t require more than a few clicks, and you should not expect any downtime. By moving to our app, you will no longer need an admin or separate account to manage the relationship with GitHub as the team bot.

Let me know if you have any questions, or if I can help at all with this process.

Cubical PH on a torus

I'm not sure how hard this would be or if it is even a new idea. One of the things I'm interested in is doing persistent homology on a Cubical complex where we identify the top and bottom of the matrix and the right and left sides, essentially wrapping around like a torus. I haven't dug into the code to see what the right approach would be. Maybe making a TorusComplex object, and that somehow tells ripserer what to identify? Or should there just be a flag to ripserer when you submit a Cubical object? Thanks!

Can Ripserer compute the discrete morse theory for a simplex, or compute the collapses?

Hello. I am still relatively new to computing with simplicial complexes, but I use Julia all the time. I was wondering if Ripserer is able to compute the discrete morse theory--or essentially the collapses of a simplicial complex? I believe Eirene does this internally, for its computation of persistent homology, but not sure about Ripserer. If you or anyone happens to know of a julia package that computes the collapses for a complex, please let me know.

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

Option to supply SparseCSCMatrix of distances directly

Hi, thank you for this awesome package. Right now if I pass a SparseCSCMatrix object to Ripserer directly it gives an error saying that some edge lengths are 0. However if I first try to specify a dense matrix (filling the 0s with a large number) and then supply it with a threshold, I run into memory issues constructing the dense matrix.

Would it be possible to allow SparseCSCMatrix inputs directly, where off-diagonal zeros are considered as above the threshold by default?

bad promote_rule

A promote_rule is not supposed to non-terminating, as that violates the specification of promote_type.
Look at the code here:

Base.promote_rule(::Type{Mod{M}}, ::Type{<:Integer}) where {M} = Mod{M}

There should be an additional rule to resolve the ambiguity there. That looks like:

Base.promote_rule(::Type{Mod{M}}, ::Type{<:Mod}) where {M} = Union{}

Additionally, I noticed that you appear to have assumed that all Integers are an Int, which is not always true. You can make your current rule more accurate by first checking it the Integer is directly promotable to Int:

Base.promote_rule(::Type{Mod{M}}, ::Type{N}) where {M, N<:Integer} = Base.promote_type(N, Int) === Int ? Mod{M} : Union{}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.