Cubical Ripser Python binding
Project description
CubicalRipser : Persistent homology for 2D image and 3D voxel data (and 1D scalar timeseries)
copyright by Takeki Sudo and Kazushi Ahara, Meiji University, 2018
modified by Shizuo Kaji, Kyushu University, 2019
Description
CubicalRipser is an adaptation of Ripser by Ulrich Bauer to computation of persistent homology of weighted cubical complexes.
- For 2 and 3 dimensional cubical complexes, CubicalRipser is among the fastest programs for computing persistent homology
- Cubical Ripser implements both the V- and the T- constructions for the filtration of cubical complexes (see V and T constructions).
- The coefficients are taken in the field with two elements.
- See Other software for persistent homology of cubical complexes
For details, please look at our paper Cubical Ripser: Software for computing persistent homology of image and volume data by Shizuo Kaji, Takeki Sudo, Kazushi Ahara.
License
CubicalRipser is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Get Started
- You can try Cubical Ripser on Google Colaboratory
- You may also want to look at A guide through TDA tools giving a hands-on tutorial for various tools for topological data analysis including Cubical Ripser
- How Deep-learning and Persistent homology can be combined is demonstrated: Example 1 and Example 2
Installation
Recommended: pip
Install the Python module only:
% pip install -U cripser
Build from source
The command-line executable should be easily build with C++11 compilers such as G++, Clang, or Microsoft C++. To build the command-line executable from source:
% cd build
% cmake ..
% make
The executable is "cubicalripser".
If cmake is not available on your system, you can also do
% cd src
% make all
but perhaps you have to manually modify "Makefile".
To install Python module,
% pip install .
Windows specifics
On Windows, you may get an error like "Python config failure: Python is 64-bit, chosen compiler is 32-bit". Then, you have to specify your compiler; for example
% cmake .. -G"Visual Studio 15 2017 Win64"
% cmake --build . --target ALL_BUILD --config Release
Also, due to the non-standard type used in pybind11, you may encounter an error saying "the type ssize_t is undefined". This error may be resolved by adding
typedef SSIZE_T ssize_t;
right after the first appearance of
#if defined(_MSC_VER)
in pybind11/include/pybind11/numpy.h
How to use
Python module
To use from python,
import cripser
pd = cripser.computePH(arr,maxdim=2)
where arr is a 2D or 3D numpy array of type numpy.float64. The result is stored in (n,9)-array, where n is the number of cycles. Each row consists of
dim birth death x1 y1 z1 x2 y2 z2
where (x1,y1,z1) is the location of the creator cell of the cycle and (x2,y2,z2) is the location of the destroyer cell of the cycle. See also Creator and Destroyer cells.
If you want to compute with the T-construction instead of the V-construction,
import tcripser
pd = tcripser.computePH(arr,maxdim=2)
Look at the Jupyter notebook demo/cubicalripser.ipynb and https://github.com/shizuo-kaji/HomologyCNN for practical usage.
Command-line executable
(See also 2D Image file for a Python-based command-line utility.)
To see the command-line options:
% ./cubicalripser
Example:
% ./cubicalripser --print --maxdim 2 --output out.csv demo/3dimsample.txt
The results are recorded in result.csv. Each line in the output result.csv consists of nine numbers indicating the dimension of the cycle, birth-time, death-time, the creator location (x,y,z), and the destroyer location (x,y,z).
Cubical Ripser accepts 1D/2D/3D Numpy arrays
% ./cubicalripser --output result.csv input.npy
Input file format
The python version accepts NUMPY arrays as input. A small utility is included that converts images in various formats into NUMPU arrays.
The command-line version of CubicalRipser accepts three types of input files: NUMPY (.npy), Perseus TEXT (.txt), CSV (.csv), DIPHA (.complex).
2D Image file
Given a JPEG image input.jpg, we can compute its persistent homology by
% python demo/cr.py input.jpg -o output.csv
The result is saved in the CSV file output.csv whose rows look
dim birth death x1 y1 z1 x2 y2 z2
where (x1,y1,z1) is the location of the creator cell of the cycle and (x2,y2,z2) is the location of the destroyer cell of the cycle.
Alternatively, we can first convert the image into a 2D Numpy array input.npy by
% python demo/img2npy.py input.jpg input.npy
and compute its persistent homology by the python module:
import numpy as np # import the Numpy module
import cripser # import the Cubical Ripser python module
arr = np.load("input.npy").astype(np.float64) # load the image in the numpy array format
result = cripser.computePH(arr,maxdim=1) # compute the persistent homology up to degree 1
Here, result is another 2D Numpy array of shape (M,9), where M is the number of cycles. The none numbers of each row indicate the dimension of the cycle, birth-time, death-time, location (x1,y1,z1) of the cell giving birth to the cycle, and location (x2,y2,z2) of the cell destroying the cycle.
3D Volume file
Given a series of DICOM files named input00.dcm, input01.dcm, input02.dcm... under the directory dicom, we can compute its persistent homology by
% python demo/cr.py dicom --sort -it dcm -o output.csv
by reading .dcm files from the directry dicom in a sorted order.
Alternatively, we can first convert the DICOM files to a single 3D Numpy array volume.npy that is compatible with Cubical Ripser by
% python demo/img2npy.py dicom/input*.dcm volume.npy
A series of image files such as JPEG and PNG files (as long as the Pillow library can handle them) can also be made into a volume in a similar way:
% python demo/img2npy.py input*.jpg volume.npy
Note that here we rely on the shell's path expansion. If your shell does not support it, you can manually specify file names as in the following:
% python demo/img2npy.py input00.dcm input01.dcm input02.dcm volume.npy
1D time series
A scalar time-series can be considered as a 1D image, so Cubical Ripser can compute its persistent homology. Note that other software would be more efficient for this purpose.
An example of regressing the frequency of noisy sine curves is demonstrated here.
Deep Learning X Persistent homology
Lifetime enhanced image is a way to feed the topological features obtained by persistent homology into convolutional neural networks (CNNs).
% ./cubicalripser --output result.npy input.npy
% python demo/stackPH.py result.npy -o lifetime_image.npy -i input.npy
In lifetime_image.npy, persistent homology is encoded as the extra channels so that it can be used as input for CNNs.
Please look at the example section of our paper and the demonstration for details.
Similarly, the persistent histogram image can be obtained by
% python demo/stackPH.py result.npy -o lifetime_image.npy -t hist -i input.npy
CSV file (only for 2D image)
The filename should end with ".csv".
Text file (Perseus)
The filename should end with ".txt". Please look at Perseus Dense Cubical Grids format for specification.
3
max_x
max_y
max_z
val[1,1,1]
val[2,1,1]
...
val[max_x,max_y,max_z]
DIPHA file
The filename should end with ".complex". Look at DIPHA binary format for specification.
We can convert input and output files between Cubical Ripser and DIPHA.
-
to convert an Numpy array img.npy into DIPHA's format img.complex
% python dipha2npy.py img.npy img.complex
-
the other way around
% python dipha2npy.py img.complex img.npy
-
convert DIPHA's output result.output into an Numpy array result.npy
% python dipha2npy.py result.output result.npy
V and T constructions
There are two major ways to build a filtred cubical complex from an image (that is, a function over a grid).
- In the V-construction, each pixel in the image corresponds to the 0 cell.
- In the T-construction, each pixel in the image corresponds to the top cell.
In the 2D setting, the V-construction amounts to considering 4-neighbour pixel connectivity, whereas the T-construction amounts to considering 8-neighbour pixel connectivity.
Cubical Ripser provides two versions of executables:
- for the V-construction: cubicalripser, cripser (python module)
- for the T-construction: tcubicalripser (no python module provided)
By the Alexander duality, the following two give essentially the same results:
./cubicalripser input.npy
./tcubicalripser --embedded input.npy
The difference is in the sign of the filtration and the permanent cycle. Here, (--embedded) converts the input I to -I^\infty described in the paper below.
Look at the following paper for details: Duality in Persistent Homology of Images by Adélie Garin, Teresa Heiss, Kelly Maggs, Bea Bleile, Vanessa Robins
Creator and Destroyer cells
The creator of a cycle is the cell which gives birth to the cycle. For example, the voxel in a connected component with the lowest filtration value creates a 0-dimensional cycle, and the voxel which connects two separate connected components destroys the component with a higher birth time. The creator and the destroyer cells are not uniquely determined, but they provide useful information to localise the cycle. Cubical Ripser adopts the following convention on the location of these cells: when the lifetime of a cycle is finte,
arr[x2,y2,z2] - arr[x1,y1,z1] = death - birth = lifetime
where arr is the image, (x1,y1,z1) is the location of the creator cell, and (x2,y2,z2) is the location of the destroyer cell. Note that when computed with the (--embedded) option, the roles of creator and destroyer are switched:
arr[x1,y1,z1] - arr[x2,y2,z2] = death - birth = lifetime
The authors thank Nicholas Byrne for suggesting the convention and providing a test code.
Other software for persistent homology of cubical complexes
We give a referece to various software for persistent homology of images. The comments are based on our limited understanding and tests, and hence, could be wrong.
- Cubicle by Hubert Wagner
It computes for the V-construction of the image. Its parallelised algorithm offers faster computation on multi-core machines. Also, it reads the input image in small chunks so that it requires much less memory footprint.
- HomcCube By Ippei Obayashi.
It computes for the V-construction of the image. It is integrated into Homcloud developed by the same author.
- DIPHA by Ulrich Bauer and Michael Kerber
It computes for the V-construction of the image. It is parallelised with MPI so it works on a cluster. The software has been used in various projects. The memory footprint is relatively large.
- GUDHI developed at INRIA
It computes for the T-construction of the image. It is well-documented and offers a well-organised and easy to use interface. It focuses more on usability than performance.
- diamorse developed at The Australian National University.
It computes for the V-construction of the image.
- Perseus by Vidit Nanda
It computes for the V-construction of the image.
Release Notes
- (v0.0.8) fixed memory leak in Python bindings (pointed out by Nicholas Byrne)
- (v0.0.7) slight speed up
- (v0.0.6) changes in the definition of birth/death location (suggested by Nicholas Byrne)
- (up to v0.0.5, difference from the original version
- optimised codes (much less memory footprint, much faster for certain data; sometimes more than 100 times.)
- Python friendly: see the Jupyter Notebook example found under the demo directory.
- virtually infinite input size (compared to 510x510x510)
- cache control
- option to use the Alexander duality for the highest degree persistent homology
- V and T construction for building cubical complexes from an image
- output birth/death location
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Hashes for cripser-0.0.13-cp312-cp312-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e4de2f91d43a68ad99eab3598f9e94ac4f86e3b92d733aa27e3d9f17da767fd6 |
|
MD5 | bf5345c6d9c8d9a8e0379c9b8e3ef4d1 |
|
BLAKE2b-256 | f87edc0c27dbf7ebae00650bfd131a739fbe130f3aafca0b806fbc6e21214914 |
Hashes for cripser-0.0.13-cp312-cp312-manylinux_2_34_x86_64.manylinux_2_35_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7315d3385316b601bd583b06be2362dbbadb8237a9bff7267d35a3d25cb2906a |
|
MD5 | 590981eea25328387e4136685e9b9708 |
|
BLAKE2b-256 | d0c882d92755f4c89ab57b4b0fa4da21f7e3ba1b504e856b3487d8ee0014493b |
Hashes for cripser-0.0.13-cp312-cp312-macosx_14_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d6d646fccf39483a5ebb530a5501ded75c3514f42f4199d454ad1e137a5778f5 |
|
MD5 | 36242205adc4dc1bed5955b6f6c97068 |
|
BLAKE2b-256 | dec2877585b4d396b11339a44cb97581f10c1676503b18556d371bd9bac86071 |
Hashes for cripser-0.0.13-cp311-cp311-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | bea5f9ce8f03047db052e68abfb17f243634a38047b69659d38a33071cb634d9 |
|
MD5 | 4bc962a628de343ee37335a13cfcd87c |
|
BLAKE2b-256 | dbe1adbdaad68b0c33b62cbed326612c83a6b5c00a1068e82cd61cb6de92ed32 |
Hashes for cripser-0.0.13-cp311-cp311-manylinux_2_34_x86_64.manylinux_2_35_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 758120d45aa119f671c68cb53ff861eea45f93920904b1e009f5e58fdd014cf2 |
|
MD5 | 02467764650b379cfb08f0d865862ce3 |
|
BLAKE2b-256 | 5b7f49ff5ac417d7c2238584503912409d6bf136ae6153b3f68031c1809219b9 |
Hashes for cripser-0.0.13-cp311-cp311-macosx_14_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2087db0ce326497ca4cf3fdc24cd7b26993973341e4177dea71ea87388033caa |
|
MD5 | c1644e6f139935d1ce5d1d1df38fabde |
|
BLAKE2b-256 | 39ec32b1ef11c1e22788b695da8397a409fb96a501d80d0047b59c6ab4b12fe9 |
Hashes for cripser-0.0.13-cp310-cp310-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 01db4da721b5b9746e08b9f82b9d6fae68cb34a9747632935f1bcbab7116a180 |
|
MD5 | 8171f1590efc5d7fd387a4395c2c859c |
|
BLAKE2b-256 | 98427f2d0112ba120d2559fdffa63d63f1e44db615aec44fdb0a2addcec3cda8 |
Hashes for cripser-0.0.13-cp310-cp310-manylinux_2_34_x86_64.manylinux_2_35_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6a56c64d112eff32ba10af2590762d761d3453a77788fb5f7e1c1c8c77082cea |
|
MD5 | 6f440a7a8c3e2a97ebcda4ed337acaa6 |
|
BLAKE2b-256 | 5dad657c0302532279d7f532d4008b7cfd075f660e2d3c9adc8ac1c2842e858d |
Hashes for cripser-0.0.13-cp310-cp310-macosx_14_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f0a514a5362743c111a47f15a4ca0a1b89cf53c18363bc8cb3508790001e9e6b |
|
MD5 | eaacfd3608be2110bf33cd9cbfc16de1 |
|
BLAKE2b-256 | f3fc616193b89539107333ad04c7d5153c214750b3048ccca9b262c138100efd |
Hashes for cripser-0.0.13-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 354d4efd6ac3caa0d23ff06c52358bbbf8a309e242d83d93c02c897b4a728825 |
|
MD5 | fcb1753c2085880d4ed8034354fdc0df |
|
BLAKE2b-256 | 49dc536bc13fd892c5b1d996ecf5f99745cde9a83eff5b9d23566103335c1c1b |
Hashes for cripser-0.0.13-cp39-cp39-manylinux_2_34_x86_64.manylinux_2_35_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | cc3b5e42dd7f2cf0288b5d267f154430cf637b212181b1e2a25c934b893a144d |
|
MD5 | 561e2882276944be33818fbf6a972d6e |
|
BLAKE2b-256 | 38da007d01bdbfc6da39f746cd1c183450a16a9c3bf4d36c72098d3d504a4c96 |
Hashes for cripser-0.0.13-cp39-cp39-macosx_14_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 30d6f6f4a8d79568ddbbc816b598054c3012f430cd69fa4028f6b9a0c31e4b5f |
|
MD5 | 7a44e4211a4e383ac0a1b566c9004173 |
|
BLAKE2b-256 | 5bd2f8ce66cafbddeb98da186e1a3c362b5c9d07388093b972626c2a5521de99 |