Skip to content

1-Manifold Learning Circles

1-Manifold Learning Circles  example Image

Pipeline description

This example first loads a point cloud from disk. The points are arranged in mainly two concentric circles, one bigger than the other.

In a pre-processing, the data is converted to a format understandable by Paraview using the TableToPoints filter (upper left view, above screenshot). GaussianResampling is applied to the data. This filter has the effect of injecting input points to a structured data. For each injection, each point will "splat", or distribute values to nearby vertices. Only a slice of the data is kept (upper right, above screenshot). The resulting SplatterValues field is a density estimation (with a Gaussian kernel) of the point cloud in 2D.

Then, the PersistenceDiagram is computed and thresholds are applied base on persistence to maintain only the most persistent features. This results in a simplified persistence diagram (bottom left view, above screenshot).

The simplified persistence diagram is then used as a constraint for the TopologicalSimplification of the input scalar data.

This simplified data is then used as the input of the computation of MorseSmaleComplex (bottom right view, above screenshot). This complex is composed of elements of 3 dimensions: dimension 0, which corresponds to the critical points of the Morse-Smale Complex, dimension 1, which corresponds to its edges and dimension 2, which corresponds to its surfaces. The generators of the clusters are edges of the Morse-Smale Complex. Not all edges of the Complex are useful: using thresholds, only the separatrices connected to maxima are kept (Separatrix = 1). Then the edges with the field SeparatrixFunctionMinimum below a certain value (here 2) are also discarded. This corresponds to the two green and yellow generators (bottom right view, above screenshot).

ParaView

To reproduce the above screenshot, go to your ttk-data directory and enter the following command:

paraview states/1manifoldLearningCircles.pvsm

Python code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/env python

from paraview.simple import *

# create a new 'CSV Reader'
clustering0csv = CSVReader(FileName=["clustering0.csv"])

# create a new 'Table To Points'
tableToPoints1 = TableToPoints(Input=clustering0csv)
tableToPoints1.XColumn = "X"
tableToPoints1.YColumn = "Y"
tableToPoints1.a2DPoints = 1
tableToPoints1.KeepAllDataArrays = 1

# create a new 'Gaussian Resampling'
gaussianResampling1 = GaussianResampling(Input=tableToPoints1)
gaussianResampling1.ResampleField = ["POINTS", "ignore arrays"]
gaussianResampling1.ResamplingGrid = [256, 256, 3]
gaussianResampling1.SplatAccumulationMode = "Sum"

# create a new 'Slice'
slice1 = Slice(Input=gaussianResampling1)
slice1.SliceType = "Plane"

# init the 'Plane' selected for 'SliceType'
slice1.SliceType.Normal = [0.0, 0.0, 1.0]

# create a new 'TTK PersistenceDiagram'
tTKPersistenceDiagram1 = TTKPersistenceDiagram(Input=slice1)
tTKPersistenceDiagram1.ScalarField = ["POINTS", "SplatterValues"]
tTKPersistenceDiagram1.IgnoreBoundary = True

# create a new 'Threshold'
threshold1 = Threshold(Input=tTKPersistenceDiagram1)
threshold1.Scalars = ["CELLS", "PairIdentifier"]
threshold1.ThresholdMethod = "Between"
threshold1.LowerThreshold = -0.1
threshold1.UpperThreshold = 999999999

# create a new 'Threshold'
persistenceThreshold0 = Threshold(Input=threshold1)
persistenceThreshold0.Scalars = ["CELLS", "Persistence"]
persistenceThreshold0.ThresholdMethod = "Between"
persistenceThreshold0.LowerThreshold = 10.0
persistenceThreshold0.UpperThreshold = 999999999

# create a new 'TTK TopologicalSimplification'
tTKTopologicalSimplification1 = TTKTopologicalSimplification(
    Domain=slice1, Constraints=persistenceThreshold0
)
tTKTopologicalSimplification1.ScalarField = ["POINTS", "SplatterValues"]

# create a new 'TTK MorseSmaleComplex'
tTKMorseSmaleComplex1 = TTKMorseSmaleComplex(Input=tTKTopologicalSimplification1)
tTKMorseSmaleComplex1.ScalarField = ["POINTS", "SplatterValues"]

# create a new 'Threshold'
threshold2 = Threshold(Input=OutputPort(tTKMorseSmaleComplex1, 1))
threshold2.Scalars = ["CELLS", "SeparatrixType"]
threshold2.ThresholdMethod = "Between"
threshold2.LowerThreshold = 1.0
threshold2.UpperThreshold = 1.0

# create a new 'Threshold'
threshold3 = Threshold(Input=threshold2)
threshold3.Scalars = ["CELLS", "SeparatrixFunctionMinimum"]
threshold3.ThresholdMethod = "Between"
threshold3.LowerThreshold = 2.0
threshold3.UpperThreshold = 999999999

# create a new 'Resample With Dataset'
resampleWithDataset1 = ResampleWithDataset(
    SourceDataArrays=OutputPort(tTKMorseSmaleComplex1, 3),
    DestinationMesh=tableToPoints1,
)

# save the ouput
SaveData("Clustering.csv", resampleWithDataset1)
SaveData("Generators.vtu", threshold3)

To run the above Python script, go to your ttk-data directory and enter the following command:

pvpython python/1manifoldLearningCircles.py

Inputs

    • clustering0.csv: a table containing 2D point coordinates arranged in concentric circles.

Outputs

  • Clustering.csv: Resampled dataset to store the clustering (field AscendingManifold). You are free to change the vtu file extension to that of any other supported file format (e.g. csv) in the above python script.
  • Generators.vtu: edges (or 1 dimensional elements) of the output Morse Smale Complex after passing through two thresholds in VTK file format (bottom right view, above screenshot). Only the edges connected to maximam with the field SeparatrixFunctionMinimum below 2 are saved in this file. You are free to change the vtu file extension to that of any other supported file format (e.g. csv) in the above python script.

C++/Python API

GeometrySmoother

MorseSmaleComplex

PersistenceDiagram

TopologicalSimplification