Commit e971a69900d0f036bd49404d0c75b65f5ca0e116

Authored by Olli-Pekka Kahilakoski
Committed by GitHub
1 parent df0e6ca1
Exists in master

ADD: Send coil mesh using NeuronavigationApi (#418)

* ADD: Send coil mesh using NeuronavigationApi

* Review comments, some tweaks to save memory and speed up
invesalius/gui/task_navigator.py
... ... @@ -201,7 +201,12 @@ class InnerFoldPanel(wx.Panel):
201 201  
202 202 # Fold 2 - Object registration panel
203 203 item = fold_panel.AddFoldPanel(_("Object registration"), collapsed=True)
204   - otw = ObjectRegistrationPanel(item, tracker, pedal_connection)
  204 + otw = ObjectRegistrationPanel(
  205 + parent=item,
  206 + tracker=tracker,
  207 + pedal_connection=pedal_connection,
  208 + neuronavigation_api=neuronavigation_api,
  209 + )
205 210  
206 211 fold_panel.ApplyCaptionStyle(item, style)
207 212 fold_panel.AddFoldPanelWindow(item, otw, spacing=0,
... ... @@ -889,7 +894,7 @@ class NeuronavigationPanel(wx.Panel):
889 894  
890 895  
891 896 class ObjectRegistrationPanel(wx.Panel):
892   - def __init__(self, parent, tracker, pedal_connection):
  897 + def __init__(self, parent, tracker, pedal_connection, neuronavigation_api):
893 898 wx.Panel.__init__(self, parent)
894 899 try:
895 900 default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR)
... ... @@ -901,6 +906,7 @@ class ObjectRegistrationPanel(wx.Panel):
901 906  
902 907 self.tracker = tracker
903 908 self.pedal_connection = pedal_connection
  909 + self.neuronavigation_api = neuronavigation_api
904 910  
905 911 self.nav_prop = None
906 912 self.obj_fiducials = None
... ... @@ -917,7 +923,7 @@ class ObjectRegistrationPanel(wx.Panel):
917 923 btn_new = wx.Button(self, -1, _("New"), size=wx.Size(65, 23))
918 924 btn_new.SetToolTip(tooltip)
919 925 btn_new.Enable(1)
920   - btn_new.Bind(wx.EVT_BUTTON, self.OnLinkCreate)
  926 + btn_new.Bind(wx.EVT_BUTTON, self.OnCreateNewCoil)
921 927 self.btn_new = btn_new
922 928  
923 929 # Button for import config coil file
... ... @@ -1060,13 +1066,16 @@ class ObjectRegistrationPanel(wx.Panel):
1060 1066 coil_index = evt.GetSelection()
1061 1067 Publisher.sendMessage('Change selected coil', self.coil_list[coil_index][1])
1062 1068  
1063   - def OnLinkCreate(self, event=None):
  1069 + def OnCreateNewCoil(self, event=None):
1064 1070  
1065 1071 if self.tracker.IsTrackerInitialized():
1066 1072 dialog = dlg.ObjectCalibrationDialog(self.tracker, self.pedal_connection)
1067 1073 try:
1068 1074 if dialog.ShowModal() == wx.ID_OK:
1069 1075 self.obj_fiducials, self.obj_orients, self.obj_ref_mode, self.obj_name, polydata, use_default_object = dialog.GetValue()
  1076 +
  1077 + self.neuronavigation_api.update_coil_mesh(polydata)
  1078 +
1070 1079 if np.isfinite(self.obj_fiducials).all() and np.isfinite(self.obj_orients).all():
1071 1080 self.checktrack.Enable(1)
1072 1081 Publisher.sendMessage('Update object registration',
... ...
invesalius/net/neuronavigation_api.py
... ... @@ -20,6 +20,9 @@
20 20 from invesalius.pubsub import pub as Publisher
21 21 from invesalius.utils import Singleton
22 22  
  23 +import numpy as np
  24 +from vtk.numpy_interface import dataset_adapter
  25 +
23 26 class NeuronavigationApi(metaclass=Singleton):
24 27 """
25 28 An API used internally in InVesalius to communicate with the
... ... @@ -34,6 +37,8 @@ class NeuronavigationApi(metaclass=Singleton):
34 37  
35 38 If connection object is not given or it is None, skip doing the updates.
36 39 """
  40 + N_VERTICES_IN_POLYGON = 3
  41 +
37 42 def __init__(self, connection=None):
38 43 if connection is not None:
39 44 assert self._hasmethod(connection, 'update_coil_pose')
... ... @@ -65,3 +70,28 @@ class NeuronavigationApi(metaclass=Singleton):
65 70 position=position,
66 71 orientation=orientation,
67 72 )
  73 +
  74 + def update_coil_mesh(self, polydata):
  75 + wrapped = dataset_adapter.WrapDataObject(polydata)
  76 +
  77 + points = np.asarray(wrapped.Points)
  78 + polygons_raw = np.asarray(wrapped.Polygons)
  79 +
  80 + # The polygons are returned as 1d-array of the form
  81 + #
  82 + # [n_0, id_0(0), id_0(1), ..., id_0(n_0),
  83 + # n_1, id_1(0), id_1(1), ..., id_1(n_1),
  84 + # ...]
  85 + #
  86 + # where n_i is the number of vertices in polygon i, and id_i's are indices to the vertex list.
  87 + #
  88 + # Assert that all polygons have an equal number of vertices, reshape the array, and drop n_i's.
  89 + #
  90 + assert np.all(polygons_raw[0::self.N_VERTICES_IN_POLYGON + 1] == self.N_VERTICES_IN_POLYGON)
  91 +
  92 + polygons = polygons_raw.reshape(-1, self.N_VERTICES_IN_POLYGON + 1)[:, 1:]
  93 +
  94 + self.connection.update_coil_mesh(
  95 + points=points,
  96 + polygons=polygons,
  97 + )
... ...