Skip to content

Commit

Permalink
Merge pull request #23 from SciKit-Surgery/21-visualisation
Browse files Browse the repository at this point in the history
21 visualisation
  • Loading branch information
thompson318 authored Jan 18, 2022
2 parents 43aeb36 + de8dafc commit de70287
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 26 deletions.
43 changes: 43 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
cff-version: 1.2.0
message: "If you use any SciKit-Surgery packages in your research, please cite it as below."
authors:
- family-names: "Olafsdottir"
given-names: "Asta"
- family-names: "Thompson"
given-names: "Stephen"
orcid: "https://orcid.org/0000-0001-7286-1326"
title: "SciKit-SurgeryGlenoid"
url: "https://github.com/SciKit-Surgery/scikit-surgery"
preferred-citation:
type: article
authors:
- family-names: "Thompson"
given-names: "Stephen"
orcid: "https://orcid.org/0000-0001-7286-1326"
- family-names: "Dowrick"
given-names: "Thomas"
orcid: "https://orcid.org/0000-0002-2712-4447"
- family-names: "Ahmad"
given-names: "Mian"
orcid: "https://orcid.org/0000-0002-4706-4146"
- family-names: "Xiao"
given-names: "Guofang"
- family-names: "Koo"
given-names: "Bongjin"
orcid: "https://orcid.org/0000-0002-3611-4988"
- family-names: "Bonmati"
given-names: "Ester"
orcid: "https://orcid.org/0000-0001-9217-5438"
- family-names: "Kahl"
given-names: "Kim"
- family-names: "Clarkson"
given-names: "Matthew"
orcid: "https://orcid.org/0000-0002-5565-1252"
doi: 10.1007/s11548-020-02180-5
journal: "International journal of computer assisted radiology and surgery"
start: 1075
end: 1084
title: "SciKit-Surgery: Compact Libraries for Surgical Navigation"
volume: 15
issue: 7
year: 2020
1 change: 1 addition & 0 deletions docs/dependency_graph.dot
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ digraph prof {
node [style=filled];
"SciKit-SurgeryGlenoid" -> "NumPy";
"SciKit-SurgeryGlenoid" -> "SciKit-SurgeryVTK" [color="0.515 0.762 0.762"];
"SciKit-SurgeryGlenoid" -> "SciKit-SurgeryCore" [color="0.515 0.762 0.762"];
"SciKit-SurgeryGlenoid" -> "VTK";

"SciKit-SurgeryVTK" -> "NumPy";
Expand Down
27 changes: 27 additions & 0 deletions glenoidplanefitting/algorithms/colour_palette.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
A colour palette based on Bang's colour pallette
Wong, B. Points of view: Color blindness. Nat Methods 8, 441 (2011).
https://doi.org/10.1038/nmeth.1618
"""

bang_palette={ 'black' : [0,0,0],
'orange' : [230./255., 159./255., 0],
'sky blue' : [86./255., 180./255., 233./255.],
'bluish green' : [0./255., 158./255., 115./255.],
'yellow' : [240./255., 228./255., 66./255.],
'blue' : [0./255., 114./255., 178./255.],
'vermillion' : [213./255., 94./255., 0./255.],
'reddish purple' : [204./255., 121./255., 167./255.]
}

weiss_light_blue = [0.0, 0.384, 0.490]


def bang_list():
"""
Returns the bang palette as a list
"""
bp_list = []
for _key, value in bang_palette.items():
bp_list.append(value)
return bp_list
18 changes: 17 additions & 1 deletion glenoidplanefitting/algorithms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Functions to create vtk models for visualisation of
results
"""
from vtk import vtkPlaneSource, vtkLineSource #pylint:disable=no-name-in-module
from vtk import vtkPlaneSource, vtkLineSource, vtkSphereSource #pylint:disable=no-name-in-module

def make_plane_model(plane_centre, normal_vector, resolution = 10,
plane_size = 200.0):
Expand Down Expand Up @@ -56,3 +56,19 @@ def make_vault_model(point1,point2):
line.SetPoint1(point1)
line.SetPoint2(point2)
return line

def make_sphere_model(point, radius = 5.0):
"""
Make a sphere source which we can use to represent a landmark
point
:param point: the point
:returns the vtkPointSource
"""
sphere_source = vtkSphereSource()
sphere_source.SetCenter(point)
sphere_source.SetThetaResolution(12)
sphere_source.SetPhiResolution(12)
sphere_source.SetRadius(radius)
return sphere_source
12 changes: 10 additions & 2 deletions glenoidplanefitting/ui/glenoidplanefitting_command_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def main(args=None):
help="Landmark points file (vault)"
)

parser.add_argument("-c", "--corr_fried",
parser.add_argument("-cf", "--corr_fried",
required=False,
type=str,
default="",
Expand All @@ -62,6 +62,14 @@ def main(args=None):
help="Visualise the results"
)

parser.add_argument("-c", "--config",
required=False,
type=str,
default=None,
help="A configuration file"
)


version_string = __version__
friendly_version_string = version_string if version_string else 'unknown'
parser.add_argument(
Expand All @@ -73,4 +81,4 @@ def main(args=None):

run_demo(args.model, args.planes, args.fried_points,
args.vault_points,args.corr_fried, args.output,
args.visualise)
args.visualise, args.config)
33 changes: 26 additions & 7 deletions glenoidplanefitting/ui/glenoidplanefitting_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
from vtk import vtkXMLPolyDataWriter #pylint:disable=no-name-in-module
import numpy as np
from sksurgeryvtk.models.vtk_surface_model import VTKSurfaceModel
from sksurgerycore.configuration.configuration_manager import (
ConfigurationManager
)
from glenoidplanefitting.algorithms import plane_fitting, friedman, vault
from glenoidplanefitting.widgets.visualisation import vis_planes, vis_fried, \
vis_vault
from glenoidplanefitting.algorithms.models import make_plane_model, \
make_friedman_model, make_vault_model


#pylint: disable=too-many-locals
def run_demo(model_file_name, planes="", fried_points="", vault_points="",
corr_fried="", output="", visualise = False):
corr_fried="", output="", visualise = False, config_file = None):
"""
:param planes: File name pointing to file containing points for
planes method.
Expand Down Expand Up @@ -51,9 +54,23 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="",
used as the new axial
slice for picking
the new landmark points for the 3D corrected Friedman method.
"""
model = VTKSurfaceModel(model_file_name, [1., 0., 0.])
:param config_file: We can pass a configuration file, currently
focusing on visualisation parameters
"""
configuration = {}
if config_file is not None:
configurer = ConfigurationManager(config_file)
configuration = configurer.get_copy()
model_colour = configuration.get('model colour',
[0.89, 0.86, 0.79]) #bone from https://www.colorhexa.com/e3dac9
plane_resolution = configuration.get('plane resolution', 1)
plane_size = configuration.get('plane size' , 200.0)
vary_plane_colour = configuration.get('vary plane colour', True)
point_size = configuration.get('point size', 3.0)
line_width = configuration.get('line width', 5)

model = VTKSurfaceModel(model_file_name, model_colour)
version = None
if planes != "":

Expand All @@ -77,7 +94,9 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="",
return_meta3)

if visualise:
vis_planes(model, [result, result2, result3])
vis_planes(model, [result, result2, result3], points1, points2,
plane_resolution, plane_size, vary_plane_colour,
point_size)


if fried_points != "":
Expand All @@ -92,7 +111,7 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="",
posterior_glenoid)
if visualise:
vis_fried(model, anterior_glenoid, posterior_glenoid,
glenoid_centre, result)
glenoid_centre, result, line_width = line_width)


if vault_points !="":
Expand All @@ -105,7 +124,7 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="",
result = vault.create_vault_line(anterior_glenoid,posterior_glenoid)
if visualise:
vis_vault(model, anterior_glenoid, posterior_glenoid,
glenoid_centre, result)
glenoid_centre, result, line_width = line_width)

if corr_fried !="":

Expand Down
95 changes: 79 additions & 16 deletions glenoidplanefitting/widgets/visualisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@
"""
import vtk
from glenoidplanefitting.algorithms.models import make_plane_model, \
make_friedman_model, make_vault_model
make_friedman_model, make_vault_model, make_sphere_model
from glenoidplanefitting.algorithms.colour_palette import bang_list

def renderer_common(bone):
def renderer_common(bone, background_colour = None):
"""
Initialises a vtk renderer and adds the bone model
"""
if background_colour is None:
background_colour = [0.9, 0.9, 0.9]

renderer = vtk.vtkRenderer() #pylint:disable=no-member
renderer.SetBackground(background_colour)

bone.ambient = 1.0
bone.diffuse = 1.0
bone.specular = 1.0
bone.actor.GetProperty().SetAmbient(1)
bone.actor.GetProperty().SetDiffuse(1)
bone.actor.GetProperty().SetSpecular(1)
Expand All @@ -41,20 +42,39 @@ def render_window_common(renderer, window_name):
render_window.Finalize()
del render_window_interactor, render_window

def add_vtk_source(renderer, source):
def add_vtk_source(renderer, source, linewidth = 1.0, opacity = 1.0,
wireframe = False, colour = None):
"""
simplifies adding a vtk geometry source to a renderer
:param renderer: a vtk renderer to add to
:param source: a vtk geometry source
"""
if colour is None:
colour = [1.0, 1.0, 1.0]
mapper = vtk.vtkPolyDataMapper() #pylint:disable=no-member
mapper.SetInputConnection(source.GetOutputPort())
actor = vtk.vtkActor() #pylint:disable=no-member
actor.SetMapper(mapper)
actor.GetProperty().SetLineWidth(linewidth)
actor.GetProperty().SetOpacity(opacity)
if wireframe:
actor.GetProperty().SetRepresentationToWireframe()
actor.GetProperty().SetAmbientColor(colour)
actor.GetProperty().SetDiffuseColor(colour)
actor.GetProperty().SetSpecularColor(colour)
else:
actor.GetProperty().SetRepresentationToSurface()

actor.GetProperty().SetColor(colour)
actor.GetProperty().SetEdgeColor(colour)

renderer.AddActor(actor)

def vis_planes(bone, planes):
def vis_planes(bone, planes, points1 = False, points2 = False,
resolution = 1, plane_size = 200.0,
vary_plane_colour = False,
point_size = 5.0):
"""
Visualisation for plane fitting methods
Expand All @@ -64,13 +84,32 @@ def vis_planes(bone, planes):
"""
renderer = renderer_common(bone)
for plane in planes:
plane_source = make_plane_model(plane[1], plane[2])
add_vtk_source(renderer, plane_source)
for item, plane in enumerate(planes):
colour = [1., 1., 1.]
if vary_plane_colour:
colour = bang_list()[item]

plane_source = make_plane_model(plane[1], plane[2], resolution,
plane_size)
add_vtk_source(renderer, plane_source, opacity = 0.15, colour = colour)
add_vtk_source(renderer, plane_source, linewidth = 2, opacity = 1.0,
wireframe = True, colour = colour)

if points1:
for point in points1:
colour = bang_list()[0]
sphere_source = make_sphere_model(point, point_size)
add_vtk_source(renderer, sphere_source, colour = colour)

if points2:
for point in points2:
colour = bang_list()[1]
sphere_source = make_sphere_model(point, point_size)
add_vtk_source(renderer, sphere_source, colour = colour)

render_window_common(renderer, "Fitted Planes")

def vis_fried(bone, cross1, cross2, glenoid1, result):
def vis_fried(bone, cross1, cross2, glenoid1, result, line_width = 5):
"""
Visualise the lines resulting from the friedman
method.
Expand All @@ -82,15 +121,27 @@ def vis_fried(bone, cross1, cross2, glenoid1, result):
renderer = renderer_common(bone)

glenoid_line = make_friedman_model(cross1,cross2)
add_vtk_source(renderer, glenoid_line)
colour = bang_list()[0]
add_vtk_source(renderer, glenoid_line, linewidth = line_width,
colour = colour )

sphere_source = make_sphere_model(cross1)
add_vtk_source(renderer, sphere_source, colour = colour)
sphere_source = make_sphere_model(cross2)
add_vtk_source(renderer, sphere_source, colour = colour)

colour = bang_list()[1]
sphere_source = make_sphere_model(glenoid1)
add_vtk_source(renderer, sphere_source, colour = colour)

friedman_line = make_friedman_model(glenoid1,result)
add_vtk_source(renderer, friedman_line)
add_vtk_source(renderer, friedman_line, linewidth = line_width,
colour = colour)

render_window_common(renderer, "Friedman Lines")


def vis_vault(bone, cross1, cross2, glenoid1, result):
def vis_vault(bone, cross1, cross2, glenoid1, result, line_width = 5):
"""
Visualise the lines resulting from the vault
method.
Expand All @@ -102,9 +153,21 @@ def vis_vault(bone, cross1, cross2, glenoid1, result):
renderer = renderer_common(bone)

glenoid_line = make_vault_model(cross1,cross2)
add_vtk_source(renderer, glenoid_line)
colour = bang_list()[0]
add_vtk_source(renderer, glenoid_line, linewidth = line_width,
colour = colour)

sphere_source = make_sphere_model(cross1)
add_vtk_source(renderer, sphere_source, colour = colour)
sphere_source = make_sphere_model(cross2)
add_vtk_source(renderer, sphere_source, colour = colour)

colour = bang_list()[1]
sphere_source = make_sphere_model(glenoid1)
add_vtk_source(renderer, sphere_source, colour = colour)

vault_line = make_vault_model(glenoid1, result)
add_vtk_source(renderer, vault_line)
add_vtk_source(renderer, vault_line, linewidth = line_width,
colour = colour)

render_window_common(renderer, "Vault Lines")
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
numpy
vtk
scikit-surgeryvtk
scikit-surgerycore
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
'numpy',
'vtk',
'scikit-surgeryvtk'
'scikit-surgerycore'
],

entry_points={
Expand Down
8 changes: 8 additions & 0 deletions vis_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"model colour" : [0.89, 0.86, 0.79],
"plane resolution" : 1,
"plane size" : 200.0,
"vary plane colour" : true,
"point size" : 3.0,
"line width" : 4
}

0 comments on commit de70287

Please sign in to comment.