Skip to content

Tribute to Edelsbrunner and Harer's book

Pipeline description

This example loads a PNG microscopy image from disk, from which gray-scale scalar values are created.

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 (top right; non-simplified persistence diagram shown in gray).

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 the MorseSmaleComplex. Its ascending manifolds, separatrices and critical points are shown in the bottom views (with scalar value mapped to height in the bottom right view). The separatrices are also shown, as overlay over the original scalar data, in the top left view.

In this example, the MorseSmaleComplex segments the input microscopy data into biological cells.

ParaView

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

paraview states/tribute.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
80
81
82
83
84
85
86
#!/usr/bin/env python
from paraview.simple import *

# create a new 'PNG Series Reader'
tributepng = PNGSeriesReader(FileNames=["tribute.png"])

# create a new 'Calculator'
calculator1 = Calculator(Input=tributepng)
calculator1.ResultArrayName = "originalData"
calculator1.Function = "-sqrt(PNGImage_X*PNGImage_X+PNGImage_Y*PNGImage_Y)"

# create a new 'TTK PersistenceDiagram'
tTKPersistenceDiagram1 = TTKPersistenceDiagram(Input=calculator1)
tTKPersistenceDiagram1.ScalarField = ["POINTS", "originalData"]

# 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'
minimumPairs = Threshold(Input=threshold1)
minimumPairs.Scalars = ["CELLS", "PairType"]
minimumPairs.ThresholdMethod = "Between"
minimumPairs.LowerThreshold = -1.0
minimumPairs.UpperThreshold = 0.0

# create a new 'Calculator'
calculator6 = Calculator(Input=minimumPairs)
calculator6.AttributeType = "Cell Data"
calculator6.ResultArrayName = "Death"
calculator6.Function = "Birth+Persistence"

# create a new 'Threshold'
deathThreshold = Threshold(Input=calculator6)
deathThreshold.Scalars = ["CELLS", "Death"]
deathThreshold.LowerThreshold = -297.0
deathThreshold.UpperThreshold = -257.391

# create a new 'Threshold'
maximumPairs = Threshold(Input=threshold1)
maximumPairs.Scalars = ["POINTS", "CriticalType"]
maximumPairs.LowerThreshold = 3.0
maximumPairs.UpperThreshold = 3.0
maximumPairs.AllScalars = 0

# create a new 'Append Datasets'
appendDatasets1 = AppendDatasets(Input=[deathThreshold, maximumPairs])

# create a new 'Threshold'
persistenceThreshold = Threshold(Input=appendDatasets1)
persistenceThreshold.Scalars = ["CELLS", "Persistence"]
persistenceThreshold.ThresholdMethod = "Between"
persistenceThreshold.LowerThreshold = 8.5
persistenceThreshold.UpperThreshold = 999999999

# create a new 'TTK TopologicalSimplification'
tTKTopologicalSimplification1 = TTKTopologicalSimplification(
    Domain=calculator1, Constraints=persistenceThreshold
)
tTKTopologicalSimplification1.ScalarField = ["POINTS", "originalData"]

# create a new 'Calculator'
calculator7 = Calculator(Input=tTKTopologicalSimplification1)
calculator7.ResultArrayName = "originalData"
calculator7.Function = "-originalData"

# create a new 'Calculator'
calculator8 = Calculator(Input=calculator7)
calculator8.ResultArrayName = "originalData_Order"
calculator8.Function = "-originalData_Order"

# create a new 'TTK MorseSmaleComplex'
tTKMorseSmaleComplex2 = TTKMorseSmaleComplex(Input=calculator8)
tTKMorseSmaleComplex2.ScalarField = ["POINTS", "originalData_Order"]

# create a new 'TTK IdentifierRandomizer'
tTKIdentifierRandomizer2 = TTKIdentifierRandomizer(
    Input=OutputPort(tTKMorseSmaleComplex2, 3)
)
tTKIdentifierRandomizer2.ScalarField = ["POINTS", "AscendingManifold"]

# save the output
SaveData("tribute_segmentation.vti", tTKIdentifierRandomizer2)

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

pvpython python/tribute.py

Inputs

  • tribute.png: PNG image of a microscopy of cell sheet morphogenesis (from Edelsbrunner & Harer's book, page 217)

Outputs

  • triubute_segmentation.vtu: segmentation of tribute.png into cells (Morse–Smale complex; data array AscendingManifold)

C++/Python API

IdentifierRandomizer

MorseSmaleComplex

PersistenceDiagram

TopologicalSimplification