From 207d318863808de13efbc0777c15d4b23a2f93bd Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Thu, 6 Jan 2022 16:50:23 +0000 Subject: [PATCH 1/7] Issue #21 added a parameter to change line thickness --- glenoidplanefitting/widgets/visualisation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/glenoidplanefitting/widgets/visualisation.py b/glenoidplanefitting/widgets/visualisation.py index 7d0eb51..cc3cd04 100644 --- a/glenoidplanefitting/widgets/visualisation.py +++ b/glenoidplanefitting/widgets/visualisation.py @@ -41,7 +41,7 @@ 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): """ simplifies adding a vtk geometry source to a renderer @@ -52,6 +52,7 @@ def add_vtk_source(renderer, source): mapper.SetInputConnection(source.GetOutputPort()) actor = vtk.vtkActor() #pylint:disable=no-member actor.SetMapper(mapper) + actor.GetProperty().SetLineWidth(linewidth) renderer.AddActor(actor) def vis_planes(bone, planes): @@ -82,7 +83,7 @@ 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) + add_vtk_source(renderer, glenoid_line, linewidth = 10 ) friedman_line = make_friedman_model(glenoid1,result) add_vtk_source(renderer, friedman_line) From 8ba624d45830c5ac7a4ba41d14daa2b993eb34cf Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Thu, 13 Jan 2022 13:01:23 +0000 Subject: [PATCH 2/7] Issue #21 added some spheres for points and started setting up a config file --- docs/dependency_graph.dot | 1 + glenoidplanefitting/algorithms/models.py | 18 ++++++++++++++- .../ui/glenoidplanefitting_command_line.py | 12 ++++++++-- .../ui/glenoidplanefitting_demo.py | 22 +++++++++++++++---- glenoidplanefitting/widgets/visualisation.py | 17 +++++++++----- requirements.txt | 1 + setup.py | 1 + 7 files changed, 59 insertions(+), 13 deletions(-) diff --git a/docs/dependency_graph.dot b/docs/dependency_graph.dot index 695adb7..4372be7 100644 --- a/docs/dependency_graph.dot +++ b/docs/dependency_graph.dot @@ -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"; diff --git a/glenoidplanefitting/algorithms/models.py b/glenoidplanefitting/algorithms/models.py index 282973f..b49b394 100644 --- a/glenoidplanefitting/algorithms/models.py +++ b/glenoidplanefitting/algorithms/models.py @@ -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): @@ -56,3 +56,19 @@ def make_vault_model(point1,point2): line.SetPoint1(point1) line.SetPoint2(point2) return line + +def make_sphere_model(point): + """ + 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(5.0) + return sphere_source diff --git a/glenoidplanefitting/ui/glenoidplanefitting_command_line.py b/glenoidplanefitting/ui/glenoidplanefitting_command_line.py index 8b5b7ba..520280c 100644 --- a/glenoidplanefitting/ui/glenoidplanefitting_command_line.py +++ b/glenoidplanefitting/ui/glenoidplanefitting_command_line.py @@ -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="", @@ -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( @@ -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) diff --git a/glenoidplanefitting/ui/glenoidplanefitting_demo.py b/glenoidplanefitting/ui/glenoidplanefitting_demo.py index 68dbeb1..1322eba 100644 --- a/glenoidplanefitting/ui/glenoidplanefitting_demo.py +++ b/glenoidplanefitting/ui/glenoidplanefitting_demo.py @@ -5,6 +5,9 @@ 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 @@ -13,7 +16,7 @@ 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. @@ -51,9 +54,19 @@ 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() + background_colour = configuration.get('background colour', [0.8, 0.8, 0.8]) + model_colour = configuration.get('model colour', [0.8, 0.8, 0.8]) + + + model = VTKSurfaceModel(model_file_name, model_colour) version = None if planes != "": @@ -76,8 +89,9 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="", result3 = plane_fitting.fit_plane_transverse(points1, points3, return_meta3) + print(points1) if visualise: - vis_planes(model, [result, result2, result3]) + vis_planes(model, [result, result2, result3], points1) if fried_points != "": diff --git a/glenoidplanefitting/widgets/visualisation.py b/glenoidplanefitting/widgets/visualisation.py index cc3cd04..2363935 100644 --- a/glenoidplanefitting/widgets/visualisation.py +++ b/glenoidplanefitting/widgets/visualisation.py @@ -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 -def renderer_common(bone): +def renderer_common(bone, background_colour = [0.9, 0.9, 0.9]): """ Initialises a vtk renderer and adds the bone model """ renderer = vtk.vtkRenderer() #pylint:disable=no-member + renderer.SetBackground(background_colour) - bone.ambient = 1.0 - bone.diffuse = 1.0 - bone.specular = 1.0 + bone.ambient = 0.0 + bone.diffuse = 0.0 + bone.specular = 0.0 bone.actor.GetProperty().SetAmbient(1) bone.actor.GetProperty().SetDiffuse(1) bone.actor.GetProperty().SetSpecular(1) @@ -55,7 +56,7 @@ def add_vtk_source(renderer, source, linewidth = 1.0): actor.GetProperty().SetLineWidth(linewidth) renderer.AddActor(actor) -def vis_planes(bone, planes): +def vis_planes(bone, planes, points = []): """ Visualisation for plane fitting methods @@ -69,6 +70,10 @@ def vis_planes(bone, planes): plane_source = make_plane_model(plane[1], plane[2]) add_vtk_source(renderer, plane_source) + for point in points: + sphere_source = make_sphere_model(point) + add_vtk_source(renderer, sphere_source) + render_window_common(renderer, "Fitted Planes") def vis_fried(bone, cross1, cross2, glenoid1, result): diff --git a/requirements.txt b/requirements.txt index 1e6c820..5b4f389 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ numpy vtk scikit-surgeryvtk +scikit-surgerycore diff --git a/setup.py b/setup.py index 5ba06bf..165b161 100644 --- a/setup.py +++ b/setup.py @@ -54,6 +54,7 @@ 'numpy', 'vtk', 'scikit-surgeryvtk' + 'scikit-surgerycore' ], entry_points={ From d1cb55397a8ce923cdb05d9917d2a2f625cc958c Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Thu, 13 Jan 2022 15:29:31 +0000 Subject: [PATCH 3/7] Issue #21 more visualisation implementation --- CITATION.cff | 43 +++++++++++++++++++ .../ui/glenoidplanefitting_demo.py | 7 ++- glenoidplanefitting/widgets/visualisation.py | 22 ++++++---- vis_config.json | 5 +++ 4 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 CITATION.cff create mode 100644 vis_config.json diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..bafcbaf --- /dev/null +++ b/CITATION.cff @@ -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 diff --git a/glenoidplanefitting/ui/glenoidplanefitting_demo.py b/glenoidplanefitting/ui/glenoidplanefitting_demo.py index 1322eba..9b16df6 100644 --- a/glenoidplanefitting/ui/glenoidplanefitting_demo.py +++ b/glenoidplanefitting/ui/glenoidplanefitting_demo.py @@ -63,7 +63,10 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="", configurer = ConfigurationManager(config_file) configuration = configurer.get_copy() background_colour = configuration.get('background colour', [0.8, 0.8, 0.8]) - model_colour = configuration.get('model colour', [0.8, 0.8, 0.8]) + 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) model = VTKSurfaceModel(model_file_name, model_colour) @@ -91,7 +94,7 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="", print(points1) if visualise: - vis_planes(model, [result, result2, result3], points1) + vis_planes(model, [result, result2, result3], points1, plane_resolution, plane_size) if fried_points != "": diff --git a/glenoidplanefitting/widgets/visualisation.py b/glenoidplanefitting/widgets/visualisation.py index 2363935..7e0920c 100644 --- a/glenoidplanefitting/widgets/visualisation.py +++ b/glenoidplanefitting/widgets/visualisation.py @@ -13,9 +13,6 @@ def renderer_common(bone, background_colour = [0.9, 0.9, 0.9]): renderer = vtk.vtkRenderer() #pylint:disable=no-member renderer.SetBackground(background_colour) - bone.ambient = 0.0 - bone.diffuse = 0.0 - bone.specular = 0.0 bone.actor.GetProperty().SetAmbient(1) bone.actor.GetProperty().SetDiffuse(1) bone.actor.GetProperty().SetSpecular(1) @@ -42,7 +39,7 @@ def render_window_common(renderer, window_name): render_window.Finalize() del render_window_interactor, render_window -def add_vtk_source(renderer, source, linewidth = 1.0): +def add_vtk_source(renderer, source, linewidth = 1.0, opacity = 1.0, wireframe = False): """ simplifies adding a vtk geometry source to a renderer @@ -54,9 +51,15 @@ def add_vtk_source(renderer, source, linewidth = 1.0): actor = vtk.vtkActor() #pylint:disable=no-member actor.SetMapper(mapper) actor.GetProperty().SetLineWidth(linewidth) + actor.GetProperty().SetOpacity(opacity) + if wireframe: + actor.GetProperty().SetRepresentationToWireframe() + else: + actor.GetProperty().SetRepresentationToSurface() + renderer.AddActor(actor) -def vis_planes(bone, planes, points = []): +def vis_planes(bone, planes, points = [], resolution = 1, plane_size = 200.0): """ Visualisation for plane fitting methods @@ -67,8 +70,9 @@ def vis_planes(bone, planes, points = []): """ renderer = renderer_common(bone) for plane in planes: - plane_source = make_plane_model(plane[1], plane[2]) - add_vtk_source(renderer, plane_source) + plane_source = make_plane_model(plane[1], plane[2], resolution, plane_size) + add_vtk_source(renderer, plane_source, opacity = 0.3) + add_vtk_source(renderer, plane_source, linewidth = 2, opacity = 1.0, wireframe = True) for point in points: sphere_source = make_sphere_model(point) @@ -76,7 +80,7 @@ def vis_planes(bone, planes, points = []): render_window_common(renderer, "Fitted Planes") -def vis_fried(bone, cross1, cross2, glenoid1, result): +def vis_fried(bone, cross1, cross2, glenoid1, result, resolution = 1, plane_size = 200.0): """ Visualise the lines resulting from the friedman method. @@ -96,7 +100,7 @@ def vis_fried(bone, cross1, cross2, glenoid1, result): render_window_common(renderer, "Friedman Lines") -def vis_vault(bone, cross1, cross2, glenoid1, result): +def vis_vault(bone, cross1, cross2, glenoid1, result, resolution = 1, plane_size = 200.0): """ Visualise the lines resulting from the vault method. diff --git a/vis_config.json b/vis_config.json new file mode 100644 index 0000000..e6eb4a6 --- /dev/null +++ b/vis_config.json @@ -0,0 +1,5 @@ +{ + "model colour" : [0.89, 0.86, 0.79], + "plane resolution" : 1, + "plane size" : 200.0 +} From f28f4a73f2e1affb1ad36dd3a572fbb509c8405a Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Thu, 13 Jan 2022 16:32:59 +0000 Subject: [PATCH 4/7] Issue #21 more visualisation --- glenoidplanefitting/ui/glenoidplanefitting_demo.py | 6 ++++-- glenoidplanefitting/widgets/visualisation.py | 10 +++++++--- vis_config.json | 4 +++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/glenoidplanefitting/ui/glenoidplanefitting_demo.py b/glenoidplanefitting/ui/glenoidplanefitting_demo.py index 9b16df6..7a74774 100644 --- a/glenoidplanefitting/ui/glenoidplanefitting_demo.py +++ b/glenoidplanefitting/ui/glenoidplanefitting_demo.py @@ -67,7 +67,9 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="", [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) - + point_colour = configuration.get('point colour', + [0.0, 0.384, 0.490]) #WEISS Blue + point_size = configuration.get('point size', 3.0) model = VTKSurfaceModel(model_file_name, model_colour) version = None @@ -94,7 +96,7 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="", print(points1) if visualise: - vis_planes(model, [result, result2, result3], points1, plane_resolution, plane_size) + vis_planes(model, [result, result2, result3], points1, plane_resolution, plane_size, point_colour, point_size) if fried_points != "": diff --git a/glenoidplanefitting/widgets/visualisation.py b/glenoidplanefitting/widgets/visualisation.py index 7e0920c..ef9792e 100644 --- a/glenoidplanefitting/widgets/visualisation.py +++ b/glenoidplanefitting/widgets/visualisation.py @@ -39,7 +39,8 @@ def render_window_common(renderer, window_name): render_window.Finalize() del render_window_interactor, render_window -def add_vtk_source(renderer, source, linewidth = 1.0, opacity = 1.0, wireframe = False): +def add_vtk_source(renderer, source, linewidth = 1.0, opacity = 1.0, wireframe = False, + colour = [1.0, 1.0, 1.0]): """ simplifies adding a vtk geometry source to a renderer @@ -56,10 +57,13 @@ def add_vtk_source(renderer, source, linewidth = 1.0, opacity = 1.0, wireframe = actor.GetProperty().SetRepresentationToWireframe() else: actor.GetProperty().SetRepresentationToSurface() + + actor.GetProperty().SetColor(colour) renderer.AddActor(actor) -def vis_planes(bone, planes, points = [], resolution = 1, plane_size = 200.0): +def vis_planes(bone, planes, points = [], resolution = 1, plane_size = 200.0, + point_colour = [1.0, 1.0, 1.0], point_size = 1.0): """ Visualisation for plane fitting methods @@ -76,7 +80,7 @@ def vis_planes(bone, planes, points = [], resolution = 1, plane_size = 200.0): for point in points: sphere_source = make_sphere_model(point) - add_vtk_source(renderer, sphere_source) + add_vtk_source(renderer, sphere_source, colour = point_colour) render_window_common(renderer, "Fitted Planes") diff --git a/vis_config.json b/vis_config.json index e6eb4a6..b9d9305 100644 --- a/vis_config.json +++ b/vis_config.json @@ -1,5 +1,7 @@ { "model colour" : [0.89, 0.86, 0.79], "plane resolution" : 1, - "plane size" : 200.0 + "plane size" : 200.0, + "point colour" : [0.0, 0.384, 0.490], + "point size" : 3.0 } From 90ed349df5f8bdd2505db2a4be23e3b86319dffa Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Tue, 18 Jan 2022 11:45:26 +0000 Subject: [PATCH 5/7] Issue #21 added a colour blind aware palette and used to vary point and line colours --- .../algorithms/colour_palette.py | 27 ++++++++++++++++ .../ui/glenoidplanefitting_demo.py | 8 ++--- glenoidplanefitting/widgets/visualisation.py | 32 +++++++++++++++---- vis_config.json | 2 +- 4 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 glenoidplanefitting/algorithms/colour_palette.py diff --git a/glenoidplanefitting/algorithms/colour_palette.py b/glenoidplanefitting/algorithms/colour_palette.py new file mode 100644 index 0000000..5fde8f2 --- /dev/null +++ b/glenoidplanefitting/algorithms/colour_palette.py @@ -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 diff --git a/glenoidplanefitting/ui/glenoidplanefitting_demo.py b/glenoidplanefitting/ui/glenoidplanefitting_demo.py index 7a74774..3a4fe99 100644 --- a/glenoidplanefitting/ui/glenoidplanefitting_demo.py +++ b/glenoidplanefitting/ui/glenoidplanefitting_demo.py @@ -67,8 +67,7 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="", [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) - point_colour = configuration.get('point colour', - [0.0, 0.384, 0.490]) #WEISS Blue + vary_plane_colour = configuration.get('vary plane colour', True) point_size = configuration.get('point size', 3.0) model = VTKSurfaceModel(model_file_name, model_colour) @@ -94,9 +93,10 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="", result3 = plane_fitting.fit_plane_transverse(points1, points3, return_meta3) - print(points1) if visualise: - vis_planes(model, [result, result2, result3], points1, plane_resolution, plane_size, point_colour, point_size) + vis_planes(model, [result, result2, result3], points1, points2, + plane_resolution, plane_size, vary_plane_colour, + point_size) if fried_points != "": diff --git a/glenoidplanefitting/widgets/visualisation.py b/glenoidplanefitting/widgets/visualisation.py index ef9792e..1ce7c8b 100644 --- a/glenoidplanefitting/widgets/visualisation.py +++ b/glenoidplanefitting/widgets/visualisation.py @@ -4,6 +4,7 @@ import vtk from glenoidplanefitting.algorithms.models import make_plane_model, \ make_friedman_model, make_vault_model, make_sphere_model +from glenoidplanefitting.algorithms.colour_palette import bang_list def renderer_common(bone, background_colour = [0.9, 0.9, 0.9]): """ @@ -55,15 +56,21 @@ def add_vtk_source(renderer, source, linewidth = 1.0, opacity = 1.0, wireframe = 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, points = [], resolution = 1, plane_size = 200.0, - point_colour = [1.0, 1.0, 1.0], point_size = 1.0): +def vis_planes(bone, planes, points1 = [], points2 = [], + resolution = 1, plane_size = 200.0, + vary_plane_colour = False, + point_size = 1.0): """ Visualisation for plane fitting methods @@ -73,14 +80,25 @@ def vis_planes(bone, planes, points = [], resolution = 1, plane_size = 200.0, """ renderer = renderer_common(bone) - for plane in planes: + 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.3) - add_vtk_source(renderer, plane_source, linewidth = 2, opacity = 1.0, wireframe = True) + 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) + + for point in points1: + colour = bang_list()[0] + sphere_source = make_sphere_model(point) + add_vtk_source(renderer, sphere_source, colour = colour) - for point in points: + for point in points2: + colour = bang_list()[1] sphere_source = make_sphere_model(point) - add_vtk_source(renderer, sphere_source, colour = point_colour) + add_vtk_source(renderer, sphere_source, colour = colour) render_window_common(renderer, "Fitted Planes") diff --git a/vis_config.json b/vis_config.json index b9d9305..a7d9260 100644 --- a/vis_config.json +++ b/vis_config.json @@ -2,6 +2,6 @@ "model colour" : [0.89, 0.86, 0.79], "plane resolution" : 1, "plane size" : 200.0, - "point colour" : [0.0, 0.384, 0.490], + "vary plane colour" : true, "point size" : 3.0 } From a27bbbe524e6e33cee78f057f09a3c6187592e29 Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Tue, 18 Jan 2022 12:00:31 +0000 Subject: [PATCH 6/7] Added visualisation for Friedman --- .../ui/glenoidplanefitting_demo.py | 3 ++- glenoidplanefitting/widgets/visualisation.py | 17 ++++++++++++++--- vis_config.json | 3 ++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/glenoidplanefitting/ui/glenoidplanefitting_demo.py b/glenoidplanefitting/ui/glenoidplanefitting_demo.py index 3a4fe99..82e3f55 100644 --- a/glenoidplanefitting/ui/glenoidplanefitting_demo.py +++ b/glenoidplanefitting/ui/glenoidplanefitting_demo.py @@ -69,6 +69,7 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="", 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 @@ -111,7 +112,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 !="": diff --git a/glenoidplanefitting/widgets/visualisation.py b/glenoidplanefitting/widgets/visualisation.py index 1ce7c8b..a8d975b 100644 --- a/glenoidplanefitting/widgets/visualisation.py +++ b/glenoidplanefitting/widgets/visualisation.py @@ -102,7 +102,8 @@ def vis_planes(bone, planes, points1 = [], points2 = [], render_window_common(renderer, "Fitted Planes") -def vis_fried(bone, cross1, cross2, glenoid1, result, resolution = 1, plane_size = 200.0): +def vis_fried(bone, cross1, cross2, glenoid1, result, resolution = 1, plane_size = 200.0, + line_width = 5): """ Visualise the lines resulting from the friedman method. @@ -114,10 +115,20 @@ def vis_fried(bone, cross1, cross2, glenoid1, result, resolution = 1, plane_size renderer = renderer_common(bone) glenoid_line = make_friedman_model(cross1,cross2) - add_vtk_source(renderer, glenoid_line, linewidth = 10 ) + 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") diff --git a/vis_config.json b/vis_config.json index a7d9260..3c470dd 100644 --- a/vis_config.json +++ b/vis_config.json @@ -3,5 +3,6 @@ "plane resolution" : 1, "plane size" : 200.0, "vary plane colour" : true, - "point size" : 3.0 + "point size" : 3.0, + "line width" : 4 } From de8dafcba708aa2e79ee6a39c7518a654aa46c72 Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Tue, 18 Jan 2022 15:03:15 +0000 Subject: [PATCH 7/7] Issue #21 tidied code --- glenoidplanefitting/algorithms/models.py | 6 +- .../ui/glenoidplanefitting_demo.py | 11 ++- glenoidplanefitting/widgets/visualisation.py | 70 ++++++++++++------- 3 files changed, 53 insertions(+), 34 deletions(-) diff --git a/glenoidplanefitting/algorithms/models.py b/glenoidplanefitting/algorithms/models.py index b49b394..fff16d5 100644 --- a/glenoidplanefitting/algorithms/models.py +++ b/glenoidplanefitting/algorithms/models.py @@ -57,9 +57,9 @@ def make_vault_model(point1,point2): line.SetPoint2(point2) return line -def make_sphere_model(point): +def make_sphere_model(point, radius = 5.0): """ - Make a sphere source which we can use to represent a landmark + Make a sphere source which we can use to represent a landmark point :param point: the point @@ -70,5 +70,5 @@ def make_sphere_model(point): sphere_source.SetCenter(point) sphere_source.SetThetaResolution(12) sphere_source.SetPhiResolution(12) - sphere_source.SetRadius(5.0) + sphere_source.SetRadius(radius) return sphere_source diff --git a/glenoidplanefitting/ui/glenoidplanefitting_demo.py b/glenoidplanefitting/ui/glenoidplanefitting_demo.py index 82e3f55..aa00e69 100644 --- a/glenoidplanefitting/ui/glenoidplanefitting_demo.py +++ b/glenoidplanefitting/ui/glenoidplanefitting_demo.py @@ -14,7 +14,7 @@ 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, config_file = None): """ @@ -55,15 +55,14 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="", slice for picking the new landmark points for the 3D corrected Friedman method. - :param config_file: We can pass a configuration file, currently + :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() - background_colour = configuration.get('background colour', [0.8, 0.8, 0.8]) - model_colour = configuration.get('model colour', + 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) @@ -96,7 +95,7 @@ def run_demo(model_file_name, planes="", fried_points="", vault_points="", if visualise: vis_planes(model, [result, result2, result3], points1, points2, - plane_resolution, plane_size, vary_plane_colour, + plane_resolution, plane_size, vary_plane_colour, point_size) @@ -125,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 !="": diff --git a/glenoidplanefitting/widgets/visualisation.py b/glenoidplanefitting/widgets/visualisation.py index a8d975b..821da02 100644 --- a/glenoidplanefitting/widgets/visualisation.py +++ b/glenoidplanefitting/widgets/visualisation.py @@ -6,10 +6,12 @@ make_friedman_model, make_vault_model, make_sphere_model from glenoidplanefitting.algorithms.colour_palette import bang_list -def renderer_common(bone, background_colour = [0.9, 0.9, 0.9]): +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) @@ -40,14 +42,16 @@ def render_window_common(renderer, window_name): render_window.Finalize() del render_window_interactor, render_window -def add_vtk_source(renderer, source, linewidth = 1.0, opacity = 1.0, wireframe = False, - colour = [1.0, 1.0, 1.0]): +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 @@ -61,16 +65,16 @@ def add_vtk_source(renderer, source, linewidth = 1.0, opacity = 1.0, wireframe = actor.GetProperty().SetSpecularColor(colour) else: actor.GetProperty().SetRepresentationToSurface() - + actor.GetProperty().SetColor(colour) actor.GetProperty().SetEdgeColor(colour) renderer.AddActor(actor) -def vis_planes(bone, planes, points1 = [], points2 = [], - resolution = 1, plane_size = 200.0, +def vis_planes(bone, planes, points1 = False, points2 = False, + resolution = 1, plane_size = 200.0, vary_plane_colour = False, - point_size = 1.0): + point_size = 5.0): """ Visualisation for plane fitting methods @@ -85,25 +89,27 @@ def vis_planes(bone, planes, points1 = [], points2 = [], if vary_plane_colour: colour = bang_list()[item] - plane_source = make_plane_model(plane[1], plane[2], resolution, plane_size) + 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) + add_vtk_source(renderer, plane_source, linewidth = 2, opacity = 1.0, + wireframe = True, colour = colour) - for point in points1: - colour = bang_list()[0] - sphere_source = make_sphere_model(point) - add_vtk_source(renderer, sphere_source, 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) - for point in points2: - colour = bang_list()[1] - sphere_source = make_sphere_model(point) - 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, resolution = 1, plane_size = 200.0, - line_width = 5): +def vis_fried(bone, cross1, cross2, glenoid1, result, line_width = 5): """ Visualise the lines resulting from the friedman method. @@ -116,7 +122,8 @@ def vis_fried(bone, cross1, cross2, glenoid1, result, resolution = 1, plane_size glenoid_line = make_friedman_model(cross1,cross2) colour = bang_list()[0] - add_vtk_source(renderer, glenoid_line, linewidth = line_width, colour = colour ) + 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) @@ -128,12 +135,13 @@ def vis_fried(bone, cross1, cross2, glenoid1, result, resolution = 1, plane_size add_vtk_source(renderer, sphere_source, colour = colour) friedman_line = make_friedman_model(glenoid1,result) - add_vtk_source(renderer, friedman_line, linewidth = line_width, colour = colour) + 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, resolution = 1, plane_size = 200.0): +def vis_vault(bone, cross1, cross2, glenoid1, result, line_width = 5): """ Visualise the lines resulting from the vault method. @@ -145,9 +153,21 @@ def vis_vault(bone, cross1, cross2, glenoid1, result, resolution = 1, plane_size 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")