Skip to content

Commit 052b828

Browse files
committed
Added the display2D pyfast shortcut function
1 parent c7dff82 commit 052b828

File tree

3 files changed

+222
-0
lines changed

3 files changed

+222
-0
lines changed

source/FAST/Python/Core.i.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ static float* _intToFloatPointer(std::size_t intPointer) {
630630

631631
// Include some python code
632632
%pythoncode "@PROJECT_SOURCE_DIR@/source/FAST/Python/DataStream.py"
633+
%pythoncode "@PROJECT_SOURCE_DIR@/source/FAST/Python/Shortcuts.py"
633634

634635
%extend fast::ProcessObject {
635636
%pythoncode %{

source/FAST/Python/Shortcuts.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
"""
2+
A few shortcut functions
3+
"""
4+
from typing import Dict, Union
5+
6+
def display2D(
7+
image:Union[Image, ProcessObject]=None,
8+
segmentation:Union[Image, ProcessObject]=None,
9+
lines:Union[Mesh, ProcessObject]=None,
10+
vertices: Union[Mesh, ProcessObject]=None,
11+
intensityLevel:float=None,
12+
intensityWindow:float=None,
13+
segmentationColors:Dict[int, Color]=None,
14+
segmentationOpacity:float=0.5,
15+
segmentationBorderOpacity:float=None,
16+
segmentationBorderRadius:int=1,
17+
lineWidth:float=1,
18+
lineColor:Color=Color.Green(),
19+
vertexSize:float=10.0,
20+
vertexSizeIsInPixels:bool=True,
21+
vertexMinSize:float=1.0,
22+
vertexColor:Color=Color.Null(),
23+
vertexOpacity:float=1.0,
24+
bgcolor:Color=Color.White(),
25+
width:int=None,
26+
height:int=None,
27+
timeout:int=None,
28+
renderToImage:bool=False,
29+
returnWindow:bool=False,
30+
):
31+
"""
32+
@brief Shortcut for displaying image, segmentation and meshes using SimpleWindow2D
33+
34+
:param image: Image to display
35+
:param segmentation: Segmentation to display
36+
:param lines: Lines to display
37+
:param vertices: Vertices to display
38+
:param intensityLevel: Intensity level for image rendering
39+
:param intensityWindow: Intensity window for image rendering
40+
:param segmentationColors: Colors to use for segmentation
41+
:param segmentationOpacity: Opacity of segmentation
42+
:param segmentationBorderOpacity: Border opacity of segmentation
43+
:param segmentationBorderRadius: Size of segmentation border
44+
:param lineWidth: Width of line
45+
:param lineColor: Color of line
46+
:param vertexSize Vertex point size (can be in pixels or millimeters, see sizeIsInPixels parameter)
47+
:param vertexSizeIsInPixels Whether size is given in pixels or millimeters
48+
:param vertexMinSize Minimum size in pixels, used when sizeInPixels = false
49+
:param vertexColor Override color stored for each vertex
50+
:param vertexOpacity Opacity of vertices: 1 = no transparency, 0 = fully transparent
51+
:param bgcolor: Background color
52+
:param width: Width of window
53+
:param height: Height of window
54+
:param timeout: If set to a number, the window will auto close after this many milliseconds
55+
:param renderToImage: Use RenderToImage instead of SimpleWindow and return the resulting image
56+
:param returnWindow: Whether to return the window object, or to run it
57+
:return:
58+
"""
59+
60+
if image is None and segmentation is None and lines is None and vertices is None:
61+
raise ValueError('No data was given to display2D')
62+
63+
def set_default_value(x, default):
64+
return default if x is None else x
65+
66+
width = set_default_value(width, 0)
67+
height = set_default_value(height, 0)
68+
intensityLevel = set_default_value(intensityLevel, -1)
69+
intensityWindow = set_default_value(intensityWindow, -1)
70+
segmentationColors = set_default_value(segmentationColors, LabelColors())
71+
segmentationBorderOpacity = set_default_value(segmentationBorderOpacity, -1)
72+
73+
renderers = []
74+
75+
renderer = ImageRenderer.create(
76+
level=intensityLevel,
77+
window=intensityWindow
78+
).connect(image)
79+
renderers.append(renderer)
80+
81+
if segmentation is not None:
82+
renderer = SegmentationRenderer.create(
83+
colors=segmentationColors,
84+
opacity=segmentationOpacity,
85+
borderOpacity=segmentationBorderOpacity,
86+
borderRadius=segmentationBorderRadius
87+
).connect(segmentation)
88+
renderers.append(renderer)
89+
90+
if lines is not None:
91+
renderer = LineRenderer.create(
92+
lineWidth=lineWidth,
93+
color=lineColor
94+
).connect(lines)
95+
renderers.append(renderer)
96+
97+
if vertices is not None:
98+
renderer = VertexRenderer.create(
99+
size=vertexSize,
100+
sizeIsInPixels=vertexSizeIsInPixels,
101+
minSize=vertexMinSize,
102+
color=vertexColor,
103+
opacity=vertexOpacity,
104+
).connect(vertices)
105+
renderers.append(renderer)
106+
107+
if renderToImage:
108+
render = RenderToImage.create(
109+
bgcolor=bgcolor,
110+
width=width,
111+
height=height
112+
).connect(renderers)
113+
return render.runAndGetOutputData()
114+
else:
115+
window = SimpleWindow2D.create(
116+
bgcolor=bgcolor,
117+
width=width,
118+
height=height
119+
).connect(renderers)
120+
if timeout:
121+
window.setTimeout(timeout)
122+
if returnWindow:
123+
return window
124+
else:
125+
window.run()
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import fast
2+
import pytest
3+
4+
timeout = 1000 # Set to None for debugging
5+
6+
def test_display2D():
7+
importer = fast.ImageFileImporter.create(fast.Config.getTestDataPath() + 'US/JugularVein/US-2D_100.mhd')
8+
segmentation = fast.BinaryThresholding.create(100).connect(importer)
9+
10+
fast.display2D(importer, segmentation, timeout=timeout, bgcolor=fast.Color.Black())
11+
12+
fast.display2D(
13+
importer,
14+
segmentation,
15+
timeout=timeout,
16+
bgcolor=fast.Color.Black(),
17+
segmentationColors={1: fast.Color.Red()},
18+
width=1024,
19+
height=512,
20+
intensityLevel=10,
21+
intensityWindow=100
22+
)
23+
24+
25+
def test_display2D_render_to_image():
26+
importer = fast.ImageFileImporter.create(fast.Config.getTestDataPath() + 'US/JugularVein/US-2D_100.mhd')
27+
segmentation = fast.BinaryThresholding.create(100).connect(importer)
28+
29+
image = fast.display2D(
30+
importer,
31+
segmentation,
32+
timeout=timeout,
33+
bgcolor=fast.Color.Black(),
34+
segmentationColors={1: fast.Color.Red()},
35+
width=1024,
36+
height=512,
37+
intensityLevel=10,
38+
intensityWindow=100,
39+
renderToImage=True,
40+
)
41+
assert image.getWidth() == 1024
42+
assert image.getHeight() == 512
43+
assert image.getNrOfChannels() == 3
44+
45+
46+
def test_display2D_return_window():
47+
importer = fast.ImageFileImporter.create(fast.Config.getTestDataPath() + 'US/JugularVein/US-2D_100.mhd')
48+
segmentation = fast.BinaryThresholding.create(100).connect(importer)
49+
50+
window = fast.display2D(importer, returnWindow=True)
51+
renderer = fast.SegmentationRenderer.create().connect(segmentation)
52+
window.connect(renderer)
53+
if timeout:
54+
window.setTimeout(timeout)
55+
window.run()
56+
57+
58+
def test_display2D_mesh():
59+
importer = fast.ImageFileImporter.create(fast.Config.getTestDataPath() + 'US/JugularVein/US-2D_100.mhd')
60+
image = importer.runAndGetOutputData()
61+
spacing = image.getSpacing()
62+
63+
vertices = [
64+
fast.MeshVertex([10*spacing[0], 10*spacing[1], 0]),
65+
fast.MeshVertex([10*spacing[0], 50*spacing[1], 0]),
66+
fast.MeshVertex([200*spacing[0], 200*spacing[1], 0]),
67+
]
68+
lines = [
69+
fast.MeshLine(0, 1),
70+
fast.MeshLine(1, 2),
71+
]
72+
73+
mesh = fast.Mesh.create(vertices, lines)
74+
75+
fast.display2D(
76+
importer,
77+
lines=mesh,
78+
lineColor=fast.Color.Red(),
79+
lineWidth=1,
80+
timeout=timeout,
81+
)
82+
83+
fast.display2D(
84+
importer,
85+
vertices=mesh,
86+
vertexSize=2,
87+
vertexSizeIsInPixels=False,
88+
vertexMinSize=1,
89+
vertexOpacity=0.5,
90+
timeout=timeout,
91+
)
92+
93+
94+
def test_display2D_no_input():
95+
with pytest.raises(ValueError):
96+
fast.display2D()

0 commit comments

Comments
 (0)