File: vmtksurfaceextractannularwalls.py

package info (click to toggle)
vmtk 1.3%2Bdfsg-2.1%2Bdeb9u1
  • links: PTS, VCS
  • area: non-free
  • in suites: stretch
  • size: 8,932 kB
  • sloc: cpp: 82,947; ansic: 31,817; python: 21,462; perl: 381; makefile: 93; ruby: 41; sh: 19
file content (134 lines) | stat: -rw-r--r-- 5,105 bytes parent folder | download | duplicates (2)
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python

import sys
import math
import numpy
import vtk
from vmtk import pypes
from vmtk import vmtkscripts

vmtksurfaceextractannularwalls = 'VmtkSurfaceExtractAnnularWalls'

class VmtkSurfaceExtractAnnularWalls(pypes.pypeScript):
    def __init__(self):
        pypes.pypeScript.__init__(self)

        self.SetScriptName(vmtksurfaceextractannularwalls)
        self.SetScriptDoc('Extract wall surfaces from an annular-cylindric surface.')

        # Define members
        self.Surface = None

        self.DoubleSurface = None
        self.ColoredSurface = None
        self.InnerSurface = None
        self.OuterSurface = None

        self.CellEntityIdsArrayName = 'CellEntityIds'
        self.EndcapsThresholdLow = 0
        self.EndcapsThresholdHigh = 1

        # Potential output values
        self.InnerRegionId = None
        self.OuterRegionId = None

        # Member info: name, cmdlinename, typename, num, default, desc[, defaultpipetoscript]
        self.SetInputMembers([
                ['Surface', 'i', 'vtkPolyData', 1, '',
                 'the input surface', 'vmtksurfacereader'],
                ['CellEntityIdsArrayName', 'entityidsarray', 'str', 1, '',
                 'name of the array where entity ids have been stored'],
                ['EndcapsThresholdLow', 'lowthreshold', 'int', 1, '',
                 'lower threshold for encaps filtering', ''],
                ['EndcapsThresholdHigh', 'highthreshold', 'int', 1, '',
                 'higher threshold for encaps filtering', ''],
                ])
        self.SetOutputMembers([
                ['DoubleSurface', 'doublesurface', 'vtkPolyData', 1, '',
                 'the double surface without caps', 'vmtksurfacewriter'],
                ['ColoredSurface', 'o', 'vtkPolyData', 1, '',
                 'the colored surface', 'vmtksurfacewriter'],
                ['InnerSurface', 'innersurface', 'vtkPolyData', 1, '',
                 'the innermost surface', 'vmtksurfacewriter'],
                ['OuterSurface', 'outersurface', 'vtkPolyData', 1, '',
                 'the outermost surface', 'vmtksurfacewriter'],
                ['CellEntityIdsArrayName', 'entityidsarray', 'str', 1, '',
                 'name of the array where entity ids have been stored'],
                ])

    def Execute(self):
        if self.Surface == None:
            self.PrintError('Error: No Surface.')

        self.removeEndCaps()
        self.colorSurfaceRegions()
        self.extractSurfaces()

    def removeEndCaps(self):
        self.PrintLog("Using thresholding to remove endcaps.")

        th = vtk.vtkThreshold()
        th.SetInputData(self.Surface)
        th.SetInputArrayToProcess(0, 0, 0, 1, self.CellEntityIdsArrayName)
        th.ThresholdBetween(self.EndcapsThresholdLow, self.EndcapsThresholdHigh)
        th.Update()

        gf = vtk.vtkGeometryFilter()
        gf.SetInputConnection(th.GetOutputPort())
        gf.Update()

        self.DoubleSurface = gf.GetOutput()

    def colorSurfaceRegions(self):
        self.PrintLog("Coloring surface regions.")

        connectivityFilter = vtk.vtkPolyDataConnectivityFilter()
        connectivityFilter.SetInputData(self.DoubleSurface)
        connectivityFilter.ColorRegionsOn()
        connectivityFilter.SetExtractionModeToAllRegions()
        connectivityFilter.Update()

        assert connectivityFilter.GetNumberOfExtractedRegions() == 2

        self.ColoredSurface = connectivityFilter.GetOutput()

    def extractSurfaces(self):
        self.PrintLog("Extracting surfaces.")

        def bnorm(data):
            bounds = data.GetBounds()
            return math.sqrt(sum((bounds[2*i+1]-bounds[2*i])**2 for i in range(3)))

        # Get bounds of entire surface
        bounds_norm = bnorm(self.Surface)

        # Currently assuming that this is the region numbers that were produced by coloring!
        # TODO: If necessary, get from array to be more robust.
        region_ids = (0, 1)

        # Extract each surface in turn to find the smallest one
        subsurfaces = {}
        for k in region_ids:
            connectivityFilter = vtk.vtkPolyDataConnectivityFilter()
            connectivityFilter.SetInputData(self.ColoredSurface)
            connectivityFilter.SetExtractionModeToSpecifiedRegions()
            connectivityFilter.AddSpecifiedRegion(k)
            connectivityFilter.ColorRegionsOff()
            connectivityFilter.SetScalarConnectivity(0)
            connectivityFilter.Update()
            subsurfaces[k] = connectivityFilter.GetOutput()

        # The inner surface has smaller bounds
        if bnorm(subsurfaces[region_ids[0]]) < bnorm(subsurfaces[region_ids[1]]):
            self.InnerRegionId = region_ids[0]
            self.OuterRegionId = region_ids[1]
        else:
            self.InnerRegionId = region_ids[1]
            self.OuterRegionId = region_ids[0]
        self.InnerSurface = subsurfaces[self.InnerRegionId]
        self.OuterSurface = subsurfaces[self.OuterRegionId]

if __name__ == '__main__':
    main = pypes.pypeMain()
    main.Arguments = sys.argv
    main.Execute()