Commit 9de6858764937e33dd2090be46587d1b9659d8b2
Committed by
GitHub
1 parent
85de3a6a
Exists in
master
Coil projection on peel (#308)
* add add_object_orientation_disk and add_addobjectArrow functions, add orientation disk and projection arrow actors * add getCenter and getNormal functions, create locator and add self.peel_centers and self.peel_normals variables, add to calculate normals and centers when calling getPeelActor (new peel) * add GetPeelCenters and Initlocator_viewer and corresponding publisher call * add in OnLinkBrain and TractographyPanel class (OnSelectPeelingDepth) call to get peel centers and normals and initiator) * remove print on GetPeelCenters and Initlocator_viewer * add objectArrowlocation to calculate coil norms and directions * Add UpdateObjectArrowOrientation and Getcellintersection - getcellintersection function calculates the intersection between the coil normal and the peel center -calculates the angle between the coil normal and the normal of the center of the intersected cell -shows the coil projected with arrow and disk -Color of the disk and arrow change according to the value of the angle between the normal of the coil and the peel center mesh intersected. -updateobjectarroworientation is used to show and update the position of the projected arrow and disk * add comments, removed not used code on class def, modify currentPeel as local variable * modify getPeelActor removing input currentPeel * add affine_vtk matrix as input to getPeelActor, add change position of curent peel * add case when not intersection found in getcellintersection function * add remove arrow and disk actor only when intersecting with the peel * add comments to getcellintersection function, remove TODO * add comment to getcellintersection * add transformpeelposition function * add setvisibility to arrow and disk actor on OnNavigationStatus * add tangent lines for debuggint at getcellintersection function * add coil_dir from coordinates from tracker to objectArrowlocation * modify visibility of disk and coil projection arrow, to be shown when coil is not shown * comment tangent lines for debuggin on getcellintersection * modify names of functions to invesalius naming convention * correct mispelling error when calling GetCellIntersection * add angle threshold for projectio arrow in constansts * add angle threshold for arrow projection in constants * change size of disk and arrow in coil projection * add normal lines for debugging arrow projection * Modify function names to invensalius convention * add condition for track if peel is loaded or not * fix removing arrow and disk projection when distance is larger than set value, removing normal lines for debugging * clean comments * add self.peel_loaded to vis_components * Modify UpdatePeelVisualization to pass peel_loaded from navigation class * change color disk and arrow
Showing
4 changed files
with
269 additions
and
47 deletions
Show diff stats
invesalius/constants.py
@@ -781,6 +781,7 @@ ARROW_UPPER_LIMIT = 15 | @@ -781,6 +781,7 @@ ARROW_UPPER_LIMIT = 15 | ||
781 | COIL_ANGLES_THRESHOLD = 3 | 781 | COIL_ANGLES_THRESHOLD = 3 |
782 | COIL_COORD_THRESHOLD = 3 | 782 | COIL_COORD_THRESHOLD = 3 |
783 | TIMESTAMP = 2.0 | 783 | TIMESTAMP = 2.0 |
784 | +COIL_ANGLE_ARROW_PROJECTION_THRESHOLD = 10 | ||
784 | 785 | ||
785 | CAM_MODE = True | 786 | CAM_MODE = True |
786 | 787 |
invesalius/data/brainmesh_handler.py
@@ -8,34 +8,33 @@ import pyvista | @@ -8,34 +8,33 @@ import pyvista | ||
8 | 8 | ||
9 | class Brain: | 9 | class Brain: |
10 | def __init__(self, img_path, mask_path, n_peels, affine_vtk): | 10 | def __init__(self, img_path, mask_path, n_peels, affine_vtk): |
11 | + # Create arrays to access the peel data and peel Actors | ||
11 | self.peel = [] | 12 | self.peel = [] |
12 | self.peelActors = [] | 13 | self.peelActors = [] |
13 | - | 14 | + # Read the image |
14 | T1_reader = vtk.vtkNIFTIImageReader() | 15 | T1_reader = vtk.vtkNIFTIImageReader() |
15 | T1_reader.SetFileName(img_path) | 16 | T1_reader.SetFileName(img_path) |
16 | T1_reader.Update() | 17 | T1_reader.Update() |
17 | - | ||
18 | - # self.refImage = vtk.vtkImageData() | 18 | + # Image |
19 | self.refImage = T1_reader.GetOutput() | 19 | self.refImage = T1_reader.GetOutput() |
20 | - | 20 | + # Read the mask |
21 | mask_reader = vtk.vtkNIFTIImageReader() | 21 | mask_reader = vtk.vtkNIFTIImageReader() |
22 | mask_reader.SetFileName(mask_path) | 22 | mask_reader.SetFileName(mask_path) |
23 | mask_reader.Update() | 23 | mask_reader.Update() |
24 | - | 24 | + # Use the mask to create isosurface |
25 | mc = vtk.vtkContourFilter() | 25 | mc = vtk.vtkContourFilter() |
26 | mc.SetInputConnection(mask_reader.GetOutputPort()) | 26 | mc.SetInputConnection(mask_reader.GetOutputPort()) |
27 | mc.SetValue(0, 1) | 27 | mc.SetValue(0, 1) |
28 | mc.Update() | 28 | mc.Update() |
29 | 29 | ||
30 | - refSurface = vtk.vtkPolyData() | 30 | + # Mask isosurface |
31 | refSurface = mc.GetOutput() | 31 | refSurface = mc.GetOutput() |
32 | - | ||
33 | - tmpPeel = vtk.vtkPolyData() | 32 | + # Create a uniformly meshed surface |
34 | tmpPeel = downsample(refSurface) | 33 | tmpPeel = downsample(refSurface) |
35 | - | ||
36 | - mask_sFormMatrix = vtk.vtkMatrix4x4() | 34 | + # Standard space coordinates |
37 | mask_sFormMatrix = mask_reader.GetSFormMatrix() | 35 | mask_sFormMatrix = mask_reader.GetSFormMatrix() |
38 | 36 | ||
37 | + # Apply coordinate transform to the meshed mask | ||
39 | mask_ijk2xyz = vtk.vtkTransform() | 38 | mask_ijk2xyz = vtk.vtkTransform() |
40 | mask_ijk2xyz.SetMatrix(mask_sFormMatrix) | 39 | mask_ijk2xyz.SetMatrix(mask_sFormMatrix) |
41 | 40 | ||
@@ -44,17 +43,21 @@ class Brain: | @@ -44,17 +43,21 @@ class Brain: | ||
44 | mask_ijk2xyz_filter.SetTransform(mask_ijk2xyz) | 43 | mask_ijk2xyz_filter.SetTransform(mask_ijk2xyz) |
45 | mask_ijk2xyz_filter.Update() | 44 | mask_ijk2xyz_filter.Update() |
46 | 45 | ||
46 | + # Smooth the mesh | ||
47 | tmpPeel = smooth(mask_ijk2xyz_filter.GetOutput()) | 47 | tmpPeel = smooth(mask_ijk2xyz_filter.GetOutput()) |
48 | + # Configure calculation of normals | ||
48 | tmpPeel = fixMesh(tmpPeel) | 49 | tmpPeel = fixMesh(tmpPeel) |
50 | + # Remove duplicate points etc | ||
49 | tmpPeel = cleanMesh(tmpPeel) | 51 | tmpPeel = cleanMesh(tmpPeel) |
52 | + # Generate triangles | ||
50 | tmpPeel = upsample(tmpPeel) | 53 | tmpPeel = upsample(tmpPeel) |
54 | + | ||
51 | tmpPeel = smooth(tmpPeel) | 55 | tmpPeel = smooth(tmpPeel) |
52 | tmpPeel = fixMesh(tmpPeel) | 56 | tmpPeel = fixMesh(tmpPeel) |
53 | tmpPeel = cleanMesh(tmpPeel) | 57 | tmpPeel = cleanMesh(tmpPeel) |
54 | 58 | ||
55 | - # sFormMatrix = vtk.vtkMatrix4x4() | 59 | + # Scanner coordinates from image |
56 | qFormMatrix = T1_reader.GetQFormMatrix() | 60 | qFormMatrix = T1_reader.GetQFormMatrix() |
57 | - # sFormMatrix = T1_reader.GetSFormMatrix() | ||
58 | 61 | ||
59 | refImageSpace2_xyz_transform = vtk.vtkTransform() | 62 | refImageSpace2_xyz_transform = vtk.vtkTransform() |
60 | refImageSpace2_xyz_transform.SetMatrix(qFormMatrix) | 63 | refImageSpace2_xyz_transform.SetMatrix(qFormMatrix) |
@@ -69,29 +72,32 @@ class Brain: | @@ -69,29 +72,32 @@ class Brain: | ||
69 | self.xyz2_refImageSpace = vtk.vtkTransformPolyDataFilter() | 72 | self.xyz2_refImageSpace = vtk.vtkTransformPolyDataFilter() |
70 | self.xyz2_refImageSpace.SetTransform(xyz2_refImageSpace_transform) | 73 | self.xyz2_refImageSpace.SetTransform(xyz2_refImageSpace_transform) |
71 | 74 | ||
72 | - # self.currentPeel = vtk.vtkPolyData() | ||
73 | - self.currentPeel = tmpPeel | 75 | + currentPeel = tmpPeel |
74 | self.currentPeelNo = 0 | 76 | self.currentPeelNo = 0 |
75 | - self.mapImageOnCurrentPeel() | 77 | + currentPeel= self.MapImageOnCurrentPeel(currentPeel) |
76 | 78 | ||
77 | newPeel = vtk.vtkPolyData() | 79 | newPeel = vtk.vtkPolyData() |
78 | - newPeel.DeepCopy(self.currentPeel) | 80 | + newPeel.DeepCopy(currentPeel) |
81 | + newPeel.DeepCopy(currentPeel) | ||
82 | + self.peel_normals = vtk.vtkFloatArray() | ||
83 | + self.peel_centers = vtk.vtkFloatArray() | ||
79 | self.peel.append(newPeel) | 84 | self.peel.append(newPeel) |
80 | self.currentPeelActor = vtk.vtkActor() | 85 | self.currentPeelActor = vtk.vtkActor() |
81 | self.currentPeelActor.SetUserMatrix(affine_vtk) | 86 | self.currentPeelActor.SetUserMatrix(affine_vtk) |
82 | - self.getCurrentPeelActor() | 87 | + self.GetCurrentPeelActor(currentPeel) |
83 | self.peelActors.append(self.currentPeelActor) | 88 | self.peelActors.append(self.currentPeelActor) |
84 | - | 89 | + # locator will later find the triangle on the peel surface where the coil's normal intersect |
90 | + self.locator = vtk.vtkCellLocator() | ||
85 | self.numberOfPeels = n_peels | 91 | self.numberOfPeels = n_peels |
86 | - self.peelDown() | 92 | + self.PeelDown(currentPeel) |
87 | 93 | ||
88 | - def get_actor(self, n): | ||
89 | - return self.getPeelActor(n) | 94 | + def get_actor(self, n, affine_vtk): |
95 | + return self.GetPeelActor(n, affine_vtk) | ||
90 | 96 | ||
91 | - def sliceDown(self): | 97 | + def SliceDown(self, currentPeel): |
92 | # Warp using the normals | 98 | # Warp using the normals |
93 | warp = vtk.vtkWarpVector() | 99 | warp = vtk.vtkWarpVector() |
94 | - warp.SetInputData(fixMesh(downsample(self.currentPeel))) # fixMesh here updates normals needed for warping | 100 | + warp.SetInputData(fixMesh(downsample(currentPeel))) # fixMesh here updates normals needed for warping |
95 | warp.SetInputArrayToProcess(0, 0, 0, vtk.vtkDataObject().FIELD_ASSOCIATION_POINTS, | 101 | warp.SetInputArrayToProcess(0, 0, 0, vtk.vtkDataObject().FIELD_ASSOCIATION_POINTS, |
96 | vtk.vtkDataSetAttributes().NORMALS) | 102 | vtk.vtkDataSetAttributes().NORMALS) |
97 | warp.SetScaleFactor(-1) | 103 | warp.SetScaleFactor(-1) |
@@ -103,8 +109,8 @@ class Brain: | @@ -103,8 +109,8 @@ class Brain: | ||
103 | out = fixMesh(out) | 109 | out = fixMesh(out) |
104 | out = cleanMesh(out) | 110 | out = cleanMesh(out) |
105 | 111 | ||
106 | - self.currentPeel = out | ||
107 | - | 112 | + currentPeel = out |
113 | + return currentPeel | ||
108 | # def sliceUp(self): | 114 | # def sliceUp(self): |
109 | # # Warp using the normals | 115 | # # Warp using the normals |
110 | # warp = vtk.vtkWarpVector() | 116 | # warp = vtk.vtkWarpVector() |
@@ -122,8 +128,8 @@ class Brain: | @@ -122,8 +128,8 @@ class Brain: | ||
122 | # | 128 | # |
123 | # currentPeel = out | 129 | # currentPeel = out |
124 | 130 | ||
125 | - def mapImageOnCurrentPeel(self): | ||
126 | - self.xyz2_refImageSpace.SetInputData(self.currentPeel) | 131 | + def MapImageOnCurrentPeel(self, currentPeel): |
132 | + self.xyz2_refImageSpace.SetInputData(currentPeel) | ||
127 | self.xyz2_refImageSpace.Update() | 133 | self.xyz2_refImageSpace.Update() |
128 | 134 | ||
129 | probe = vtk.vtkProbeFilter() | 135 | probe = vtk.vtkProbeFilter() |
@@ -134,25 +140,36 @@ class Brain: | @@ -134,25 +140,36 @@ class Brain: | ||
134 | self.refImageSpace2_xyz.SetInputData(probe.GetOutput()) | 140 | self.refImageSpace2_xyz.SetInputData(probe.GetOutput()) |
135 | self.refImageSpace2_xyz.Update() | 141 | self.refImageSpace2_xyz.Update() |
136 | 142 | ||
137 | - self.currentPeel = self.refImageSpace2_xyz.GetOutput() | 143 | + currentPeel = self.refImageSpace2_xyz.GetOutput() |
144 | + return currentPeel | ||
138 | 145 | ||
139 | - def peelDown(self): | 146 | + def PeelDown(self, currentPeel): |
140 | for i in range(0, self.numberOfPeels): | 147 | for i in range(0, self.numberOfPeels): |
141 | - self.sliceDown() | ||
142 | - self.mapImageOnCurrentPeel() | 148 | + currentPeel = self.SliceDown(currentPeel) |
149 | + currentPeel = self.MapImageOnCurrentPeel(currentPeel) | ||
143 | 150 | ||
144 | newPeel = vtk.vtkPolyData() | 151 | newPeel = vtk.vtkPolyData() |
145 | - newPeel.DeepCopy(self.currentPeel) | 152 | + newPeel.DeepCopy(currentPeel) |
146 | self.peel.append(newPeel) | 153 | self.peel.append(newPeel) |
147 | 154 | ||
148 | - # getCurrentPeelActor() | 155 | + # GetCurrentPeelActor() |
149 | # newPeelActor = vtk.vtkActor() | 156 | # newPeelActor = vtk.vtkActor() |
150 | # newPeelActor = currentPeelActor | 157 | # newPeelActor = currentPeelActor |
151 | # peelActors.push_back(newPeelActor) | 158 | # peelActors.push_back(newPeelActor) |
152 | 159 | ||
153 | self.currentPeelNo += 1 | 160 | self.currentPeelNo += 1 |
154 | 161 | ||
155 | - def getPeelActor(self, p): | 162 | + def TransformPeelPosition(self, p, affine_vtk): |
163 | + peel_transform = vtk.vtkTransform() | ||
164 | + peel_transform.SetMatrix(affine_vtk) | ||
165 | + refpeelspace = vtk.vtkTransformPolyDataFilter() | ||
166 | + refpeelspace.SetInputData(self.peel[p]) | ||
167 | + refpeelspace.SetTransform(peel_transform) | ||
168 | + refpeelspace.Update() | ||
169 | + currentPeel = refpeelspace.GetOutput() | ||
170 | + return currentPeel | ||
171 | + | ||
172 | + def GetPeelActor(self, p, affine_vtk): | ||
156 | colors = vtk.vtkNamedColors() | 173 | colors = vtk.vtkNamedColors() |
157 | # Create the color map | 174 | # Create the color map |
158 | colorLookupTable = vtk.vtkLookupTable() | 175 | colorLookupTable = vtk.vtkLookupTable() |
@@ -179,9 +196,16 @@ class Brain: | @@ -179,9 +196,16 @@ class Brain: | ||
179 | # Set actor | 196 | # Set actor |
180 | self.currentPeelActor.SetMapper(mapper) | 197 | self.currentPeelActor.SetMapper(mapper) |
181 | 198 | ||
199 | + currentPeel = self.TransformPeelPosition(p, affine_vtk) | ||
200 | + | ||
201 | + self.locator.SetDataSet(currentPeel) | ||
202 | + self.locator.BuildLocator() | ||
203 | + self.GetCenters(currentPeel) | ||
204 | + self.GetNormals(currentPeel) | ||
205 | + | ||
182 | return self.currentPeelActor | 206 | return self.currentPeelActor |
183 | 207 | ||
184 | - def getCurrentPeelActor(self): | 208 | + def GetCurrentPeelActor(self, currentPeel): |
185 | colors = vtk.vtkNamedColors() | 209 | colors = vtk.vtkNamedColors() |
186 | 210 | ||
187 | # Create the color map | 211 | # Create the color map |
@@ -198,7 +222,7 @@ class Brain: | @@ -198,7 +222,7 @@ class Brain: | ||
198 | 222 | ||
199 | # Set mapper auto | 223 | # Set mapper auto |
200 | mapper = vtk.vtkOpenGLPolyDataMapper() | 224 | mapper = vtk.vtkOpenGLPolyDataMapper() |
201 | - mapper.SetInputData(self.currentPeel) | 225 | + mapper.SetInputData(currentPeel) |
202 | # mapper.SetScalarRange(0, 1000) | 226 | # mapper.SetScalarRange(0, 1000) |
203 | # mapper.SetScalarRange(0, 250) | 227 | # mapper.SetScalarRange(0, 250) |
204 | mapper.SetScalarRange(0, 200) | 228 | mapper.SetScalarRange(0, 200) |
@@ -213,6 +237,26 @@ class Brain: | @@ -213,6 +237,26 @@ class Brain: | ||
213 | 237 | ||
214 | return self.currentPeelActor | 238 | return self.currentPeelActor |
215 | 239 | ||
240 | + def GetCenters(self, currentPeel): | ||
241 | + # Compute centers of triangles | ||
242 | + centerComputer = vtk.vtkCellCenters() # This computes centers of the triangles on the peel | ||
243 | + centerComputer.SetInputData(currentPeel) | ||
244 | + centerComputer.Update() | ||
245 | + # This stores the centers for easy access | ||
246 | + peel_centers = centerComputer.GetOutput() | ||
247 | + self.peel_centers = peel_centers | ||
248 | + | ||
249 | + def GetNormals(self, currentPeel): | ||
250 | + # Compute normals of triangles | ||
251 | + normalComputer = vtk.vtkPolyDataNormals() # This computes normals of the triangles on the peel | ||
252 | + normalComputer.SetInputData(currentPeel) | ||
253 | + normalComputer.ComputePointNormalsOff() | ||
254 | + normalComputer.ComputeCellNormalsOn() | ||
255 | + normalComputer.Update() | ||
256 | + # This converts to the normals to an array for easy access | ||
257 | + peel_normals = normalComputer.GetOutput().GetCellData().GetNormals() | ||
258 | + self.peel_normals = peel_normals | ||
259 | + | ||
216 | 260 | ||
217 | def cleanMesh(inp): | 261 | def cleanMesh(inp): |
218 | cleaned = vtk.vtkCleanPolyData() | 262 | cleaned = vtk.vtkCleanPolyData() |
invesalius/data/viewer_volume.py
@@ -173,6 +173,8 @@ class Viewer(wx.Panel): | @@ -173,6 +173,8 @@ class Viewer(wx.Panel): | ||
173 | self.y_actor = None | 173 | self.y_actor = None |
174 | self.z_actor = None | 174 | self.z_actor = None |
175 | self.mark_actor = None | 175 | self.mark_actor = None |
176 | + self.obj_projection_arrow_actor = None | ||
177 | + self.object_orientation_disk_actor = None | ||
176 | 178 | ||
177 | self._mode_cross = False | 179 | self._mode_cross = False |
178 | self._to_show_ball = 0 | 180 | self._to_show_ball = 0 |
@@ -192,6 +194,7 @@ class Viewer(wx.Panel): | @@ -192,6 +194,7 @@ class Viewer(wx.Panel): | ||
192 | self.polydata = None | 194 | self.polydata = None |
193 | self.anglethreshold = const.COIL_ANGLES_THRESHOLD | 195 | self.anglethreshold = const.COIL_ANGLES_THRESHOLD |
194 | self.distthreshold = const.COIL_COORD_THRESHOLD | 196 | self.distthreshold = const.COIL_COORD_THRESHOLD |
197 | + self.angle_arrow_projection_threshold = const.COIL_ANGLE_ARROW_PROJECTION_THRESHOLD | ||
195 | 198 | ||
196 | self.actor_tracts = None | 199 | self.actor_tracts = None |
197 | self.actor_peel = None | 200 | self.actor_peel = None |
@@ -293,6 +296,7 @@ class Viewer(wx.Panel): | @@ -293,6 +296,7 @@ class Viewer(wx.Panel): | ||
293 | # Related to object tracking during neuronavigation | 296 | # Related to object tracking during neuronavigation |
294 | Publisher.subscribe(self.OnNavigationStatus, 'Navigation status') | 297 | Publisher.subscribe(self.OnNavigationStatus, 'Navigation status') |
295 | Publisher.subscribe(self.UpdateObjectOrientation, 'Update object matrix') | 298 | Publisher.subscribe(self.UpdateObjectOrientation, 'Update object matrix') |
299 | + Publisher.subscribe(self.UpdateObjectArrowOrientation, 'Update object arrow matrix') | ||
296 | Publisher.subscribe(self.UpdateTrackObjectState, 'Update track object state') | 300 | Publisher.subscribe(self.UpdateTrackObjectState, 'Update track object state') |
297 | Publisher.subscribe(self.UpdateShowObjectState, 'Update show object state') | 301 | Publisher.subscribe(self.UpdateShowObjectState, 'Update show object state') |
298 | 302 | ||
@@ -310,6 +314,8 @@ class Viewer(wx.Panel): | @@ -310,6 +314,8 @@ class Viewer(wx.Panel): | ||
310 | Publisher.subscribe(self.UpdateMarkerOffsetState, 'Update marker offset state') | 314 | Publisher.subscribe(self.UpdateMarkerOffsetState, 'Update marker offset state') |
311 | Publisher.subscribe(self.UpdateMarkerOffsetPosition, 'Update marker offset') | 315 | Publisher.subscribe(self.UpdateMarkerOffsetPosition, 'Update marker offset') |
312 | Publisher.subscribe(self.AddPeeledSurface, 'Update peel') | 316 | Publisher.subscribe(self.AddPeeledSurface, 'Update peel') |
317 | + Publisher.subscribe(self.GetPeelCenters, 'Get peel centers and normals') | ||
318 | + Publisher.subscribe(self.Initlocator_viewer, 'Get init locator') | ||
313 | 319 | ||
314 | Publisher.subscribe(self.load_mask_preview, 'Load mask preview') | 320 | Publisher.subscribe(self.load_mask_preview, 'Load mask preview') |
315 | Publisher.subscribe(self.remove_mask_preview, 'Remove mask preview') | 321 | Publisher.subscribe(self.remove_mask_preview, 'Remove mask preview') |
@@ -1320,11 +1326,18 @@ class Viewer(wx.Panel): | @@ -1320,11 +1326,18 @@ class Viewer(wx.Panel): | ||
1320 | self.y_actor = self.add_line([0., 0., 0.], [0., 1., 0.], color=[.0, 1.0, .0]) | 1326 | self.y_actor = self.add_line([0., 0., 0.], [0., 1., 0.], color=[.0, 1.0, .0]) |
1321 | self.z_actor = self.add_line([0., 0., 0.], [0., 0., 1.], color=[1.0, .0, .0]) | 1327 | self.z_actor = self.add_line([0., 0., 0.], [0., 0., 1.], color=[1.0, .0, .0]) |
1322 | 1328 | ||
1329 | + self.obj_projection_arrow_actor = self.Add_ObjectArrow([0., 0., 0.], [0., 0., 0.], vtk_colors.GetColor3d('Red'), | ||
1330 | + 15) | ||
1331 | + self.object_orientation_disk_actor = self.Add_Object_Orientation_Disk([0., 0., 0.], [0., 0., 0.], | ||
1332 | + vtk_colors.GetColor3d('Red')) | ||
1333 | + #self.obj_projection_arrow_actor.SetVisibility(False) | ||
1334 | + #self.object_orientation_disk_actor.SetVisibility(False) | ||
1323 | self.ren.AddActor(self.obj_actor) | 1335 | self.ren.AddActor(self.obj_actor) |
1324 | self.ren.AddActor(self.x_actor) | 1336 | self.ren.AddActor(self.x_actor) |
1325 | self.ren.AddActor(self.y_actor) | 1337 | self.ren.AddActor(self.y_actor) |
1326 | self.ren.AddActor(self.z_actor) | 1338 | self.ren.AddActor(self.z_actor) |
1327 | - | 1339 | + #self.ren.AddActor(self.obj_projection_arrow_actor) |
1340 | + #self.ren.AddActor(self.object_orientation_disk_actor) | ||
1328 | # self.obj_axes = vtk.vtkAxesActor() | 1341 | # self.obj_axes = vtk.vtkAxesActor() |
1329 | # self.obj_axes.SetShaftTypeToCylinder() | 1342 | # self.obj_axes.SetShaftTypeToCylinder() |
1330 | # self.obj_axes.SetXAxisLabelText("x") | 1343 | # self.obj_axes.SetXAxisLabelText("x") |
@@ -1334,6 +1347,63 @@ class Viewer(wx.Panel): | @@ -1334,6 +1347,63 @@ class Viewer(wx.Panel): | ||
1334 | 1347 | ||
1335 | # self.ren.AddActor(self.obj_axes) | 1348 | # self.ren.AddActor(self.obj_axes) |
1336 | 1349 | ||
1350 | + def Add_Object_Orientation_Disk(self, position, orientation, color=[0.0, 0.0, 1.0]): | ||
1351 | + # Create a disk to show target | ||
1352 | + disk = vtk.vtkDiskSource() | ||
1353 | + disk.SetInnerRadius(5) | ||
1354 | + disk.SetOuterRadius(15) | ||
1355 | + disk.SetRadialResolution(100) | ||
1356 | + disk.SetCircumferentialResolution(100) | ||
1357 | + disk.Update() | ||
1358 | + | ||
1359 | + disk_mapper = vtk.vtkPolyDataMapper() | ||
1360 | + disk_mapper.SetInputData(disk.GetOutput()) | ||
1361 | + disk_actor = vtk.vtkActor() | ||
1362 | + disk_actor.SetMapper(disk_mapper) | ||
1363 | + disk_actor.GetProperty().SetColor(color) | ||
1364 | + disk_actor.GetProperty().SetOpacity(1) | ||
1365 | + disk_actor.SetPosition(position) | ||
1366 | + disk_actor.SetOrientation(orientation) | ||
1367 | + | ||
1368 | + return disk_actor | ||
1369 | + | ||
1370 | + def Add_ObjectArrow(self, direction, orientation, color=[0.0, 0.0, 1.0], size=2): | ||
1371 | + vtk_colors = vtk.vtkNamedColors() | ||
1372 | + | ||
1373 | + arrow = vtk.vtkArrowSource() | ||
1374 | + | ||
1375 | + mapper = vtk.vtkPolyDataMapper() | ||
1376 | + mapper.SetInputConnection(arrow.GetOutputPort()) | ||
1377 | + | ||
1378 | + actor = vtk.vtkActor() | ||
1379 | + actor.SetMapper(mapper) | ||
1380 | + actor.GetProperty().SetColor(color) | ||
1381 | + actor.GetProperty().SetLineWidth(5) | ||
1382 | + actor.AddPosition(0, 0, 0) | ||
1383 | + actor.SetScale(size) | ||
1384 | + actor.SetPosition(direction) | ||
1385 | + actor.SetOrientation(orientation) | ||
1386 | + | ||
1387 | + return actor | ||
1388 | + | ||
1389 | + def ObjectArrowLocation(self, m_img, coord): | ||
1390 | + # m_img[:3, 0] is from posterior to anterior direction of the coil | ||
1391 | + # m_img[:3, 1] is from left to right direction of the coil | ||
1392 | + # m_img[:3, 2] is from bottom to up direction of the coil | ||
1393 | + vec_length = 70 | ||
1394 | + m_img_flip = m_img.copy() | ||
1395 | + m_img_flip[1, -1] = -m_img_flip[1, -1] | ||
1396 | + p1 = m_img_flip[:-1, -1] # coil center | ||
1397 | + coil_dir = m_img_flip[:-1, 0] | ||
1398 | + coil_face = m_img_flip[:-1, 1] | ||
1399 | + | ||
1400 | + coil_norm = np.cross(coil_dir, coil_face) | ||
1401 | + p2_norm = p1 - vec_length * coil_norm # point normal to the coil away from the center by vec_length | ||
1402 | + coil_dir = np.array([coord[3], coord[4], coord[5]]) | ||
1403 | + | ||
1404 | + return coil_dir, p2_norm, coil_norm, p1 | ||
1405 | + | ||
1406 | + | ||
1337 | def add_line(self, p1, p2, color=[0.0, 0.0, 1.0]): | 1407 | def add_line(self, p1, p2, color=[0.0, 0.0, 1.0]): |
1338 | line = vtk.vtkLineSource() | 1408 | line = vtk.vtkLineSource() |
1339 | line.SetPoint1(p1) | 1409 | line.SetPoint1(p1) |
@@ -1357,6 +1427,80 @@ class Viewer(wx.Panel): | @@ -1357,6 +1427,80 @@ class Viewer(wx.Panel): | ||
1357 | self.actor_peel = actor | 1427 | self.actor_peel = actor |
1358 | self.Refresh() | 1428 | self.Refresh() |
1359 | 1429 | ||
1430 | + def GetPeelCenters(self, centers, normals): | ||
1431 | + self.peel_centers = centers | ||
1432 | + self.peel_normals = normals | ||
1433 | + | ||
1434 | + self.Refresh() | ||
1435 | + | ||
1436 | + def Initlocator_viewer(self, locator): | ||
1437 | + self.locator = locator | ||
1438 | + self.Refresh() | ||
1439 | + | ||
1440 | + def GetCellIntersection(self, p1, p2, coil_norm, coil_dir): | ||
1441 | + | ||
1442 | + vtk_colors = vtk.vtkNamedColors() | ||
1443 | + # This find store the triangles that intersect the coil's normal | ||
1444 | + intersectingCellIds = vtk.vtkIdList() | ||
1445 | + | ||
1446 | + #for debugging | ||
1447 | + self.x_actor = self.add_line(p1,p2,vtk_colors.GetColor3d('Blue')) | ||
1448 | + #self.ren.AddActor(self.x_actor) # remove comment for testing | ||
1449 | + | ||
1450 | + self.locator.FindCellsAlongLine(p1, p2, .001, intersectingCellIds) | ||
1451 | + | ||
1452 | + closestDist = 50 | ||
1453 | + | ||
1454 | + #if find intersection , calculate angle and add actors | ||
1455 | + if intersectingCellIds.GetNumberOfIds() != 0: | ||
1456 | + for i in range(intersectingCellIds.GetNumberOfIds()): | ||
1457 | + cellId = intersectingCellIds.GetId(i) | ||
1458 | + point = np.array(self.peel_centers.GetPoint(cellId)) | ||
1459 | + distance = np.linalg.norm(point - p1) | ||
1460 | + | ||
1461 | + #print('distance:', distance, point - p1) | ||
1462 | + self.ren.RemoveActor(self.y_actor) | ||
1463 | + | ||
1464 | + if distance < closestDist: | ||
1465 | + closestDist = distance | ||
1466 | + closestPoint = point | ||
1467 | + pointnormal = np.array(self.peel_normals.GetTuple(cellId)) | ||
1468 | + angle = np.rad2deg(np.arccos(np.dot(pointnormal, coil_norm))) | ||
1469 | + #print('the angle:', angle) | ||
1470 | + | ||
1471 | + #for debbuging | ||
1472 | + self.y_actor = self.add_line(closestPoint, closestPoint + 75 * pointnormal, | ||
1473 | + vtk_colors.GetColor3d('Yellow')) | ||
1474 | + | ||
1475 | + #self.ren.AddActor(self.y_actor)# remove comment for testing | ||
1476 | + | ||
1477 | + | ||
1478 | + self.ren.AddActor(self.obj_projection_arrow_actor) | ||
1479 | + self.ren.AddActor(self.object_orientation_disk_actor) | ||
1480 | + | ||
1481 | + self.obj_projection_arrow_actor.SetPosition(closestPoint) | ||
1482 | + self.obj_projection_arrow_actor.SetOrientation(coil_dir) | ||
1483 | + | ||
1484 | + self.object_orientation_disk_actor.SetPosition(closestPoint) | ||
1485 | + self.object_orientation_disk_actor.SetOrientation(coil_dir) | ||
1486 | + | ||
1487 | + # change color of arrow and disk according to angle | ||
1488 | + if angle < self.angle_arrow_projection_threshold: | ||
1489 | + self.object_orientation_disk_actor.GetProperty().SetColor(vtk_colors.GetColor3d('Green')) | ||
1490 | + self.obj_projection_arrow_actor.GetProperty().SetColor(vtk_colors.GetColor3d('Green')) | ||
1491 | + else: | ||
1492 | + self.object_orientation_disk_actor.GetProperty().SetColor(vtk_colors.GetColor3d('indian_red')) | ||
1493 | + self.obj_projection_arrow_actor.GetProperty().SetColor(vtk_colors.GetColor3d('indian_red')) | ||
1494 | + else: | ||
1495 | + self.ren.RemoveActor(self.y_actor) | ||
1496 | + | ||
1497 | + else: | ||
1498 | + self.ren.RemoveActor(self.obj_projection_arrow_actor) | ||
1499 | + self.ren.RemoveActor(self.object_orientation_disk_actor) | ||
1500 | + self.ren.RemoveActor(self.x_actor) | ||
1501 | + #self.ren.RemoveActor(self.y_actor) | ||
1502 | + self.Refresh() | ||
1503 | + | ||
1360 | def OnNavigationStatus(self, nav_status, vis_status): | 1504 | def OnNavigationStatus(self, nav_status, vis_status): |
1361 | self.nav_status = nav_status | 1505 | self.nav_status = nav_status |
1362 | self.tracts_status = vis_status[1] | 1506 | self.tracts_status = vis_status[1] |
@@ -1368,7 +1512,8 @@ class Viewer(wx.Panel): | @@ -1368,7 +1512,8 @@ class Viewer(wx.Panel): | ||
1368 | self.x_actor.SetVisibility(self.obj_state) | 1512 | self.x_actor.SetVisibility(self.obj_state) |
1369 | self.y_actor.SetVisibility(self.obj_state) | 1513 | self.y_actor.SetVisibility(self.obj_state) |
1370 | self.z_actor.SetVisibility(self.obj_state) | 1514 | self.z_actor.SetVisibility(self.obj_state) |
1371 | - | 1515 | + #self.object_orientation_disk_actor.SetVisibility(self.obj_state) |
1516 | + #self.obj_projection_arrow_actor.SetVisibility(self.obj_state) | ||
1372 | self.Refresh() | 1517 | self.Refresh() |
1373 | 1518 | ||
1374 | def UpdateSeedOffset(self, data): | 1519 | def UpdateSeedOffset(self, data): |
@@ -1419,6 +1564,19 @@ class Viewer(wx.Panel): | @@ -1419,6 +1564,19 @@ class Viewer(wx.Panel): | ||
1419 | 1564 | ||
1420 | self.Refresh() | 1565 | self.Refresh() |
1421 | 1566 | ||
1567 | + | ||
1568 | + def UpdateObjectArrowOrientation(self, m_img, coord, flag): | ||
1569 | + | ||
1570 | + [coil_dir, norm, coil_norm, p1 ]= self.ObjectArrowLocation(m_img,coord) | ||
1571 | + | ||
1572 | + if flag: | ||
1573 | + self.ren.RemoveActor(self.x_actor) | ||
1574 | + #self.ren.RemoveActor(self.y_actor) | ||
1575 | + self.ren.RemoveActor(self.obj_projection_arrow_actor) | ||
1576 | + self.ren.RemoveActor(self.object_orientation_disk_actor) | ||
1577 | + self.GetCellIntersection(p1, norm, coil_norm, coil_dir) | ||
1578 | + self.Refresh() | ||
1579 | + | ||
1422 | def UpdateTrackObjectState(self, evt=None, flag=None, obj_name=None, polydata=None): | 1580 | def UpdateTrackObjectState(self, evt=None, flag=None, obj_name=None, polydata=None): |
1423 | if flag: | 1581 | if flag: |
1424 | self.obj_name = obj_name | 1582 | self.obj_name = obj_name |
@@ -1432,11 +1590,15 @@ class Viewer(wx.Panel): | @@ -1432,11 +1590,15 @@ class Viewer(wx.Panel): | ||
1432 | self.ren.RemoveActor(self.y_actor) | 1590 | self.ren.RemoveActor(self.y_actor) |
1433 | self.ren.RemoveActor(self.z_actor) | 1591 | self.ren.RemoveActor(self.z_actor) |
1434 | self.ren.RemoveActor(self.mark_actor) | 1592 | self.ren.RemoveActor(self.mark_actor) |
1593 | + self.ren.RemoveActor(self.obj_projection_arrow_actor) | ||
1594 | + self.ren.RemoveActor(self.object_orientation_disk_actor) | ||
1435 | self.obj_actor = None | 1595 | self.obj_actor = None |
1436 | self.x_actor = None | 1596 | self.x_actor = None |
1437 | self.y_actor = None | 1597 | self.y_actor = None |
1438 | self.z_actor = None | 1598 | self.z_actor = None |
1439 | self.mark_actor = None | 1599 | self.mark_actor = None |
1600 | + self.obj_projection_arrow_actor = None | ||
1601 | + self.object_orientation_disk_actor=None | ||
1440 | self.Refresh() | 1602 | self.Refresh() |
1441 | 1603 | ||
1442 | def UpdateShowObjectState(self, state): | 1604 | def UpdateShowObjectState(self, state): |
invesalius/gui/task_navigator.py
@@ -326,6 +326,7 @@ class Navigation(): | @@ -326,6 +326,7 @@ class Navigation(): | ||
326 | self.trekker = None | 326 | self.trekker = None |
327 | self.n_threads = None | 327 | self.n_threads = None |
328 | self.view_tracts = False | 328 | self.view_tracts = False |
329 | + self.peel_loaded = False | ||
329 | self.enable_act = False | 330 | self.enable_act = False |
330 | self.act_data = None | 331 | self.act_data = None |
331 | self.n_tracts = const.N_TRACTS | 332 | self.n_tracts = const.N_TRACTS |
@@ -363,7 +364,7 @@ class Navigation(): | @@ -363,7 +364,7 @@ class Navigation(): | ||
363 | if self.event.is_set(): | 364 | if self.event.is_set(): |
364 | self.event.clear() | 365 | self.event.clear() |
365 | 366 | ||
366 | - vis_components = [self.trigger_state, self.view_tracts] | 367 | + vis_components = [self.trigger_state, self.view_tracts, self.peel_loaded] |
367 | vis_queues = [self.coord_queue, self.trigger_queue, self.tracts_queue, self.icp_queue] | 368 | vis_queues = [self.coord_queue, self.trigger_queue, self.tracts_queue, self.icp_queue] |
368 | 369 | ||
369 | Publisher.sendMessage("Navigation status", nav_status=True, vis_status=vis_components) | 370 | Publisher.sendMessage("Navigation status", nav_status=True, vis_status=vis_components) |
@@ -458,7 +459,7 @@ class Navigation(): | @@ -458,7 +459,7 @@ class Navigation(): | ||
458 | self.tracts_queue.clear() | 459 | self.tracts_queue.clear() |
459 | self.tracts_queue.join() | 460 | self.tracts_queue.join() |
460 | 461 | ||
461 | - vis_components = [self.trigger_state, self.view_tracts] | 462 | + vis_components = [self.trigger_state, self.view_tracts, self.peel_loaded] |
462 | Publisher.sendMessage("Navigation status", nav_status=False, vis_status=vis_components) | 463 | Publisher.sendMessage("Navigation status", nav_status=False, vis_status=vis_components) |
463 | 464 | ||
464 | 465 | ||
@@ -870,6 +871,7 @@ class NeuronavigationPanel(wx.Panel): | @@ -870,6 +871,7 @@ class NeuronavigationPanel(wx.Panel): | ||
870 | Publisher.subscribe(self.UpdateSleep, 'Update sleep') | 871 | Publisher.subscribe(self.UpdateSleep, 'Update sleep') |
871 | Publisher.subscribe(self.UpdateNumberThreads, 'Update number of threads') | 872 | Publisher.subscribe(self.UpdateNumberThreads, 'Update number of threads') |
872 | Publisher.subscribe(self.UpdateTractsVisualization, 'Update tracts visualization') | 873 | Publisher.subscribe(self.UpdateTractsVisualization, 'Update tracts visualization') |
874 | + Publisher.subscribe(self.UpdatePeelVisualization, 'Update peel visualization') | ||
873 | Publisher.subscribe(self.EnableACT, 'Enable ACT') | 875 | Publisher.subscribe(self.EnableACT, 'Enable ACT') |
874 | Publisher.subscribe(self.UpdateACTData, 'Update ACT data') | 876 | Publisher.subscribe(self.UpdateACTData, 'Update ACT data') |
875 | Publisher.subscribe(self.UpdateNavigationStatus, 'Navigation status') | 877 | Publisher.subscribe(self.UpdateNavigationStatus, 'Navigation status') |
@@ -918,6 +920,10 @@ class NeuronavigationPanel(wx.Panel): | @@ -918,6 +920,10 @@ class NeuronavigationPanel(wx.Panel): | ||
918 | self.ResetICP() | 920 | self.ResetICP() |
919 | self.tracker.UpdateUI(self.select_tracker_elem, self.numctrls_coord[3:6], self.txtctrl_fre) | 921 | self.tracker.UpdateUI(self.select_tracker_elem, self.numctrls_coord[3:6], self.txtctrl_fre) |
920 | 922 | ||
923 | + | ||
924 | + def UpdatePeelVisualization(self, data): | ||
925 | + self.navigation.peel_loaded = data | ||
926 | + | ||
921 | def UpdateNavigationStatus(self, nav_status, vis_status): | 927 | def UpdateNavigationStatus(self, nav_status, vis_status): |
922 | self.nav_status = nav_status | 928 | self.nav_status = nav_status |
923 | if nav_status and self.icp.m_icp is not None: | 929 | if nav_status and self.icp.m_icp is not None: |
@@ -1044,6 +1050,7 @@ class NeuronavigationPanel(wx.Panel): | @@ -1044,6 +1050,7 @@ class NeuronavigationPanel(wx.Panel): | ||
1044 | self.navigation.UpdateFiducialRegistrationError(self.tracker) | 1050 | self.navigation.UpdateFiducialRegistrationError(self.tracker) |
1045 | fre, fre_ok = self.navigation.GetFiducialRegistrationError(self.icp) | 1051 | fre, fre_ok = self.navigation.GetFiducialRegistrationError(self.icp) |
1046 | 1052 | ||
1053 | + | ||
1047 | self.txtctrl_fre.SetValue(str(round(fre, 2))) | 1054 | self.txtctrl_fre.SetValue(str(round(fre, 2))) |
1048 | if fre_ok: | 1055 | if fre_ok: |
1049 | self.txtctrl_fre.SetBackgroundColour('GREEN') | 1056 | self.txtctrl_fre.SetBackgroundColour('GREEN') |
@@ -1862,7 +1869,7 @@ class TractographyPanel(wx.Panel): | @@ -1862,7 +1869,7 @@ class TractographyPanel(wx.Panel): | ||
1862 | self.tracts_run = None | 1869 | self.tracts_run = None |
1863 | self.trekker_cfg = const.TREKKER_CONFIG | 1870 | self.trekker_cfg = const.TREKKER_CONFIG |
1864 | self.nav_status = False | 1871 | self.nav_status = False |
1865 | - | 1872 | + self.peel_loaded = False |
1866 | self.SetAutoLayout(1) | 1873 | self.SetAutoLayout(1) |
1867 | self.__bind_events() | 1874 | self.__bind_events() |
1868 | 1875 | ||
@@ -2040,9 +2047,12 @@ class TractographyPanel(wx.Panel): | @@ -2040,9 +2047,12 @@ class TractographyPanel(wx.Panel): | ||
2040 | def OnSelectPeelingDepth(self, evt, ctrl): | 2047 | def OnSelectPeelingDepth(self, evt, ctrl): |
2041 | self.peel_depth = ctrl.GetValue() | 2048 | self.peel_depth = ctrl.GetValue() |
2042 | if self.checkpeeling.GetValue(): | 2049 | if self.checkpeeling.GetValue(): |
2043 | - actor = self.brain_peel.get_actor(self.peel_depth) | 2050 | + actor = self.brain_peel.get_actor(self.peel_depth, self.affine_vtk) |
2044 | Publisher.sendMessage('Update peel', flag=True, actor=actor) | 2051 | Publisher.sendMessage('Update peel', flag=True, actor=actor) |
2045 | - | 2052 | + Publisher.sendMessage('Get peel centers and normals', centers=self.brain_peel.peel_centers, |
2053 | + normals=self.brain_peel.peel_normals) | ||
2054 | + Publisher.sendMessage('Get init locator', locator=self.brain_peel.locator) | ||
2055 | + self.peel_loaded = True | ||
2046 | def OnSelectNumTracts(self, evt, ctrl): | 2056 | def OnSelectNumTracts(self, evt, ctrl): |
2047 | self.n_tracts = ctrl.GetValue() | 2057 | self.n_tracts = ctrl.GetValue() |
2048 | # self.tract.n_tracts = ctrl.GetValue() | 2058 | # self.tract.n_tracts = ctrl.GetValue() |
@@ -2070,7 +2080,7 @@ class TractographyPanel(wx.Panel): | @@ -2070,7 +2080,7 @@ class TractographyPanel(wx.Panel): | ||
2070 | def OnShowPeeling(self, evt, ctrl): | 2080 | def OnShowPeeling(self, evt, ctrl): |
2071 | # self.view_peeling = ctrl.GetValue() | 2081 | # self.view_peeling = ctrl.GetValue() |
2072 | if ctrl.GetValue(): | 2082 | if ctrl.GetValue(): |
2073 | - actor = self.brain_peel.get_actor(self.peel_depth) | 2083 | + actor = self.brain_peel.get_actor(self.peel_depth, self.affine_vtk) |
2074 | else: | 2084 | else: |
2075 | actor = None | 2085 | actor = None |
2076 | Publisher.sendMessage('Update peel', flag=ctrl.GetValue(), actor=actor) | 2086 | Publisher.sendMessage('Update peel', flag=ctrl.GetValue(), actor=actor) |
@@ -2114,13 +2124,18 @@ class TractographyPanel(wx.Panel): | @@ -2114,13 +2124,18 @@ class TractographyPanel(wx.Panel): | ||
2114 | 2124 | ||
2115 | try: | 2125 | try: |
2116 | self.brain_peel = brain.Brain(img_path, mask_path, self.n_peels, self.affine_vtk) | 2126 | self.brain_peel = brain.Brain(img_path, mask_path, self.n_peels, self.affine_vtk) |
2117 | - self.brain_actor = self.brain_peel.get_actor(self.peel_depth) | 2127 | + self.brain_actor = self.brain_peel.get_actor(self.peel_depth, self.affine_vtk) |
2118 | self.brain_actor.GetProperty().SetOpacity(self.brain_opacity) | 2128 | self.brain_actor.GetProperty().SetOpacity(self.brain_opacity) |
2119 | Publisher.sendMessage('Update peel', flag=True, actor=self.brain_actor) | 2129 | Publisher.sendMessage('Update peel', flag=True, actor=self.brain_actor) |
2130 | + Publisher.sendMessage('Get peel centers and normals', centers=self.brain_peel.peel_centers, | ||
2131 | + normals=self.brain_peel.peel_normals) | ||
2132 | + Publisher.sendMessage('Get init locator', locator=self.brain_peel.locator) | ||
2120 | self.checkpeeling.Enable(1) | 2133 | self.checkpeeling.Enable(1) |
2121 | self.checkpeeling.SetValue(True) | 2134 | self.checkpeeling.SetValue(True) |
2122 | self.spin_opacity.Enable(1) | 2135 | self.spin_opacity.Enable(1) |
2123 | Publisher.sendMessage('Update status text in GUI', label=_("Brain model loaded")) | 2136 | Publisher.sendMessage('Update status text in GUI', label=_("Brain model loaded")) |
2137 | + self.peel_loaded = True | ||
2138 | + Publisher.sendMessage('Update peel visualization', data= self.peel_loaded) | ||
2124 | except: | 2139 | except: |
2125 | wx.MessageBox(_("Unable to load brain mask."), _("InVesalius 3")) | 2140 | wx.MessageBox(_("Unable to load brain mask."), _("InVesalius 3")) |
2126 | 2141 | ||
@@ -2308,7 +2323,7 @@ class UpdateNavigationScene(threading.Thread): | @@ -2308,7 +2323,7 @@ class UpdateNavigationScene(threading.Thread): | ||
2308 | """ | 2323 | """ |
2309 | 2324 | ||
2310 | threading.Thread.__init__(self, name='UpdateScene') | 2325 | threading.Thread.__init__(self, name='UpdateScene') |
2311 | - self.trigger_state, self.view_tracts = vis_components | 2326 | + self.trigger_state, self.view_tracts, self.peel_loaded = vis_components |
2312 | self.coord_queue, self.trigger_queue, self.tracts_queue, self.icp_queue = vis_queues | 2327 | self.coord_queue, self.trigger_queue, self.tracts_queue, self.icp_queue = vis_queues |
2313 | self.sle = sle | 2328 | self.sle = sle |
2314 | self.event = event | 2329 | self.event = event |
@@ -2347,7 +2362,7 @@ class UpdateNavigationScene(threading.Thread): | @@ -2347,7 +2362,7 @@ class UpdateNavigationScene(threading.Thread): | ||
2347 | 2362 | ||
2348 | if view_obj: | 2363 | if view_obj: |
2349 | wx.CallAfter(Publisher.sendMessage, 'Update object matrix', m_img=m_img, coord=coord) | 2364 | wx.CallAfter(Publisher.sendMessage, 'Update object matrix', m_img=m_img, coord=coord) |
2350 | - | 2365 | + wx.CallAfter(Publisher.sendMessage, 'Update object arrow matrix',m_img=m_img, coord=coord, flag= self.peel_loaded) |
2351 | self.coord_queue.task_done() | 2366 | self.coord_queue.task_done() |
2352 | # print('UpdateScene: done {}'.format(count)) | 2367 | # print('UpdateScene: done {}'.format(count)) |
2353 | # count += 1 | 2368 | # count += 1 |