Commit 13163add78ab61b1815767cccdf0887a559ab62e

Authored by Thiago Franco de Moraes
Committed by GitHub
1 parent b2b44bbc
Exists in master

Peel creation using mask and image already loaded (#359)

* Created dialog

* some testings

* Using ww and wl to set mesh colors

* Using ww and wl to set mesh colors

* Not cleaning surface before upsample

* ww and wl -> window_width and window_level

* setting affine_vtk as matrix identity

* Some cleaning and setting specular to 0.25 to make peel brighter

* created an method to create brain peel from mask

* created an method to create brain peel from files

* Starting to give support to peel using files

* Improvements in GUI

* Creating peels from files

* Added nifti wildcard

* checking if torus orientation and arrow project exists before setting visibility

* ADD: Title to the T1 and Mask dialogs for creating peel

* ADD: Last directory to load peel files

* Using image from invesalius project

* FIX: applies vtk affine only for peel from file and decouples self affine variable

Co-authored-by: Victor Hugo Souza <victor.souza@aalto.fi>
Co-authored-by: Renan <renan_hiroshi@hotmail.com>
invesalius/data/brainmesh_handler.py
@@ -2,37 +2,95 @@ import vtk @@ -2,37 +2,95 @@ import vtk
2 import pyacvd 2 import pyacvd
3 # import os 3 # import os
4 import pyvista 4 import pyvista
5 -# import numpy as np 5 +import numpy as np
6 # import Trekker 6 # import Trekker
7 7
  8 +import invesalius.data.slice_ as sl
  9 +from invesalius.data.converters import to_vtk
  10 +
8 11
9 class Brain: 12 class Brain:
10 - def __init__(self, img_path, mask_path, n_peels, affine_vtk): 13 + def __init__(self, n_peels, window_width, window_level, affine_vtk=None):
11 # Create arrays to access the peel data and peel Actors 14 # Create arrays to access the peel data and peel Actors
12 self.peel = [] 15 self.peel = []
13 self.peelActors = [] 16 self.peelActors = []
14 - # Read the image  
15 - T1_reader = vtk.vtkNIFTIImageReader()  
16 - T1_reader.SetFileName(img_path)  
17 - T1_reader.Update() 17 + self.window_width = window_width
  18 + self.window_level = window_level
  19 + self.numberOfPeels = n_peels
  20 + self.affine_vtk = affine_vtk
  21 +
  22 + def from_mask(self, mask):
  23 + mask= np.array(mask.matrix[1:, 1:, 1:])
  24 + slic = sl.Slice()
  25 + image = slic.matrix
  26 +
  27 + mask = to_vtk(mask, spacing=slic.spacing)
  28 + image = to_vtk(image, spacing=slic.spacing)
  29 +
  30 + flip = vtk.vtkImageFlip()
  31 + flip.SetInputData(image)
  32 + flip.SetFilteredAxis(1)
  33 + flip.FlipAboutOriginOn()
  34 + flip.ReleaseDataFlagOn()
  35 + flip.Update()
  36 + image = flip.GetOutput()
  37 +
  38 + flip = vtk.vtkImageFlip()
  39 + flip.SetInputData(mask)
  40 + flip.SetFilteredAxis(1)
  41 + flip.FlipAboutOriginOn()
  42 + flip.ReleaseDataFlagOn()
  43 + flip.Update()
  44 + mask = flip.GetOutput()
  45 +
18 # Image 46 # Image
19 - self.refImage = T1_reader.GetOutput() 47 + self.refImage = image
  48 +
  49 + self._do_surface_creation(mask)
  50 +
  51 +
  52 + def from_mask_file(self, mask_path):
  53 + slic = sl.Slice()
  54 + image = slic.matrix
  55 + image = to_vtk(image, spacing=slic.spacing)
  56 +
20 # Read the mask 57 # Read the mask
21 mask_reader = vtk.vtkNIFTIImageReader() 58 mask_reader = vtk.vtkNIFTIImageReader()
22 mask_reader.SetFileName(mask_path) 59 mask_reader.SetFileName(mask_path)
23 mask_reader.Update() 60 mask_reader.Update()
  61 +
  62 + mask = mask_reader.GetOutput()
  63 +
  64 + mask_sFormMatrix = mask_reader.GetSFormMatrix()
  65 +
  66 + # Image
  67 + self.refImage = image
  68 +
  69 + self._do_surface_creation(mask, mask_sFormMatrix)
  70 +
  71 +
  72 + def _do_surface_creation(self, mask, mask_sFormMatrix=None, qFormMatrix=None):
  73 + if mask_sFormMatrix is None:
  74 + mask_sFormMatrix = vtk.vtkMatrix4x4()
  75 +
  76 + if qFormMatrix is None:
  77 + qFormMatrix = vtk.vtkMatrix4x4()
  78 +
  79 + value = np.mean(mask.GetScalarRange())
  80 +
24 # Use the mask to create isosurface 81 # Use the mask to create isosurface
25 mc = vtk.vtkContourFilter() 82 mc = vtk.vtkContourFilter()
26 - mc.SetInputConnection(mask_reader.GetOutputPort())  
27 - mc.SetValue(0, 1) 83 + mc.SetInputData(mask)
  84 + mc.SetValue(0, value)
  85 + mc.ComputeNormalsOn()
28 mc.Update() 86 mc.Update()
29 87
30 # Mask isosurface 88 # Mask isosurface
31 refSurface = mc.GetOutput() 89 refSurface = mc.GetOutput()
  90 +
32 # Create a uniformly meshed surface 91 # Create a uniformly meshed surface
33 tmpPeel = downsample(refSurface) 92 tmpPeel = downsample(refSurface)
34 # Standard space coordinates 93 # Standard space coordinates
35 - mask_sFormMatrix = mask_reader.GetSFormMatrix()  
36 94
37 # Apply coordinate transform to the meshed mask 95 # Apply coordinate transform to the meshed mask
38 mask_ijk2xyz = vtk.vtkTransform() 96 mask_ijk2xyz = vtk.vtkTransform()
@@ -48,7 +106,7 @@ class Brain: @@ -48,7 +106,7 @@ class Brain:
48 # Configure calculation of normals 106 # Configure calculation of normals
49 tmpPeel = fixMesh(tmpPeel) 107 tmpPeel = fixMesh(tmpPeel)
50 # Remove duplicate points etc 108 # Remove duplicate points etc
51 - tmpPeel = cleanMesh(tmpPeel) 109 + # tmpPeel = cleanMesh(tmpPeel)
52 # Generate triangles 110 # Generate triangles
53 tmpPeel = upsample(tmpPeel) 111 tmpPeel = upsample(tmpPeel)
54 112
@@ -56,9 +114,6 @@ class Brain: @@ -56,9 +114,6 @@ class Brain:
56 tmpPeel = fixMesh(tmpPeel) 114 tmpPeel = fixMesh(tmpPeel)
57 tmpPeel = cleanMesh(tmpPeel) 115 tmpPeel = cleanMesh(tmpPeel)
58 116
59 - # Scanner coordinates from image  
60 - qFormMatrix = T1_reader.GetQFormMatrix()  
61 -  
62 refImageSpace2_xyz_transform = vtk.vtkTransform() 117 refImageSpace2_xyz_transform = vtk.vtkTransform()
63 refImageSpace2_xyz_transform.SetMatrix(qFormMatrix) 118 refImageSpace2_xyz_transform.SetMatrix(qFormMatrix)
64 119
@@ -83,16 +138,16 @@ class Brain: @@ -83,16 +138,16 @@ class Brain:
83 self.peel_centers = vtk.vtkFloatArray() 138 self.peel_centers = vtk.vtkFloatArray()
84 self.peel.append(newPeel) 139 self.peel.append(newPeel)
85 self.currentPeelActor = vtk.vtkActor() 140 self.currentPeelActor = vtk.vtkActor()
86 - self.currentPeelActor.SetUserMatrix(affine_vtk) 141 + if self.affine_vtk:
  142 + self.currentPeelActor.SetUserMatrix(self.affine_vtk)
87 self.GetCurrentPeelActor(currentPeel) 143 self.GetCurrentPeelActor(currentPeel)
88 self.peelActors.append(self.currentPeelActor) 144 self.peelActors.append(self.currentPeelActor)
89 # locator will later find the triangle on the peel surface where the coil's normal intersect 145 # locator will later find the triangle on the peel surface where the coil's normal intersect
90 self.locator = vtk.vtkCellLocator() 146 self.locator = vtk.vtkCellLocator()
91 - self.numberOfPeels = n_peels  
92 self.PeelDown(currentPeel) 147 self.PeelDown(currentPeel)
93 148
94 - def get_actor(self, n, affine_vtk):  
95 - return self.GetPeelActor(n, affine_vtk) 149 + def get_actor(self, n):
  150 + return self.GetPeelActor(n)
96 151
97 def SliceDown(self, currentPeel): 152 def SliceDown(self, currentPeel):
98 # Warp using the normals 153 # Warp using the normals
@@ -159,9 +214,10 @@ class Brain: @@ -159,9 +214,10 @@ class Brain:
159 214
160 self.currentPeelNo += 1 215 self.currentPeelNo += 1
161 216
162 - def TransformPeelPosition(self, p, affine_vtk): 217 + def TransformPeelPosition(self, p):
163 peel_transform = vtk.vtkTransform() 218 peel_transform = vtk.vtkTransform()
164 - peel_transform.SetMatrix(affine_vtk) 219 + if self.affine_vtk:
  220 + peel_transform.SetMatrix(self.affine_vtk)
165 refpeelspace = vtk.vtkTransformPolyDataFilter() 221 refpeelspace = vtk.vtkTransformPolyDataFilter()
166 refpeelspace.SetInputData(self.peel[p]) 222 refpeelspace.SetInputData(self.peel[p])
167 refpeelspace.SetTransform(peel_transform) 223 refpeelspace.SetTransform(peel_transform)
@@ -169,34 +225,26 @@ class Brain: @@ -169,34 +225,26 @@ class Brain:
169 currentPeel = refpeelspace.GetOutput() 225 currentPeel = refpeelspace.GetOutput()
170 return currentPeel 226 return currentPeel
171 227
172 - def GetPeelActor(self, p, affine_vtk):  
173 - colors = vtk.vtkNamedColors()  
174 - # Create the color map  
175 - colorLookupTable = vtk.vtkLookupTable()  
176 - colorLookupTable.SetNumberOfColors(512)  
177 - colorLookupTable.SetSaturationRange(0, 0)  
178 - colorLookupTable.SetHueRange(0, 0)  
179 - colorLookupTable.SetValueRange(0, 1)  
180 - # colorLookupTable.SetTableRange(0, 1000)  
181 - # colorLookupTable.SetTableRange(0, 250)  
182 - colorLookupTable.SetTableRange(0, 200)  
183 - # colorLookupTable.SetTableRange(0, 150)  
184 - colorLookupTable.Build() 228 + def GetPeelActor(self, p):
  229 + lut = vtk.vtkWindowLevelLookupTable()
  230 + lut.SetWindow(self.window_width)
  231 + lut.SetLevel(self.window_level)
  232 + lut.Build()
  233 +
  234 + init = self.window_level - self.window_width / 2
  235 + end = self.window_level + self.window_width / 2
185 236
186 # Set mapper auto 237 # Set mapper auto
187 - mapper = vtk.vtkOpenGLPolyDataMapper() 238 + mapper = vtk.vtkPolyDataMapper()
188 mapper.SetInputData(self.peel[p]) 239 mapper.SetInputData(self.peel[p])
189 - # mapper.SetScalarRange(0, 1000)  
190 - # mapper.SetScalarRange(0, 250)  
191 - mapper.SetScalarRange(0, 200)  
192 - # mapper.SetScalarRange(0, 150)  
193 - mapper.SetLookupTable(colorLookupTable) 240 + mapper.SetScalarRange(init, end)
  241 + mapper.SetLookupTable(lut)
194 mapper.InterpolateScalarsBeforeMappingOn() 242 mapper.InterpolateScalarsBeforeMappingOn()
195 243
196 # Set actor 244 # Set actor
197 self.currentPeelActor.SetMapper(mapper) 245 self.currentPeelActor.SetMapper(mapper)
198 246
199 - currentPeel = self.TransformPeelPosition(p, affine_vtk) 247 + currentPeel = self.TransformPeelPosition(p)
200 248
201 self.locator.SetDataSet(currentPeel) 249 self.locator.SetDataSet(currentPeel)
202 self.locator.BuildLocator() 250 self.locator.BuildLocator()
@@ -206,34 +254,26 @@ class Brain: @@ -206,34 +254,26 @@ class Brain:
206 return self.currentPeelActor 254 return self.currentPeelActor
207 255
208 def GetCurrentPeelActor(self, currentPeel): 256 def GetCurrentPeelActor(self, currentPeel):
209 - colors = vtk.vtkNamedColors()  
210 -  
211 - # Create the color map  
212 - colorLookupTable = vtk.vtkLookupTable()  
213 - colorLookupTable.SetNumberOfColors(512)  
214 - colorLookupTable.SetSaturationRange(0, 0)  
215 - colorLookupTable.SetHueRange(0, 0)  
216 - colorLookupTable.SetValueRange(0, 1)  
217 - # colorLookupTable.SetTableRange(0, 1000)  
218 - # colorLookupTable.SetTableRange(0, 250)  
219 - colorLookupTable.SetTableRange(0, 200)  
220 - # colorLookupTable.SetTableRange(0, 150)  
221 - colorLookupTable.Build() 257 + lut = vtk.vtkWindowLevelLookupTable()
  258 + lut.SetWindow(self.window_width)
  259 + lut.SetLevel(self.window_level)
  260 + lut.Build()
  261 +
  262 + init = self.window_level - self.window_width / 2
  263 + end = self.window_level + self.window_width / 2
222 264
223 # Set mapper auto 265 # Set mapper auto
224 - mapper = vtk.vtkOpenGLPolyDataMapper() 266 + mapper = vtk.vtkPolyDataMapper()
225 mapper.SetInputData(currentPeel) 267 mapper.SetInputData(currentPeel)
226 - # mapper.SetScalarRange(0, 1000)  
227 - # mapper.SetScalarRange(0, 250)  
228 - mapper.SetScalarRange(0, 200)  
229 - # mapper.SetScalarRange(0, 150)  
230 - mapper.SetLookupTable(colorLookupTable) 268 + mapper.SetScalarRange(init, end)
  269 + mapper.SetLookupTable(lut)
231 mapper.InterpolateScalarsBeforeMappingOn() 270 mapper.InterpolateScalarsBeforeMappingOn()
232 271
233 # Set actor 272 # Set actor
234 self.currentPeelActor.SetMapper(mapper) 273 self.currentPeelActor.SetMapper(mapper)
235 self.currentPeelActor.GetProperty().SetBackfaceCulling(1) 274 self.currentPeelActor.GetProperty().SetBackfaceCulling(1)
236 self.currentPeelActor.GetProperty().SetOpacity(0.5) 275 self.currentPeelActor.GetProperty().SetOpacity(0.5)
  276 + self.currentPeelActor.GetProperty().SetSpecular(0.25)
237 277
238 return self.currentPeelActor 278 return self.currentPeelActor
239 279
invesalius/gui/dialogs.py
@@ -46,6 +46,7 @@ except ImportError: @@ -46,6 +46,7 @@ except ImportError:
46 from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor 46 from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
47 from wx.lib import masked 47 from wx.lib import masked
48 from wx.lib.agw import floatspin 48 from wx.lib.agw import floatspin
  49 +import wx.lib.filebrowsebutton as filebrowse
49 from wx.lib.wordwrap import wordwrap 50 from wx.lib.wordwrap import wordwrap
50 from invesalius.pubsub import pub as Publisher 51 from invesalius.pubsub import pub as Publisher
51 import csv 52 import csv
@@ -4995,3 +4996,134 @@ class SetSpacingDialog(wx.Dialog): @@ -4995,3 +4996,134 @@ class SetSpacingDialog(wx.Dialog):
4995 4996
4996 def OnCancel(self, evt): 4997 def OnCancel(self, evt):
4997 self.EndModal(wx.ID_CANCEL) 4998 self.EndModal(wx.ID_CANCEL)
  4999 +
  5000 +
  5001 +class PeelsCreationDlg(wx.Dialog):
  5002 + FROM_MASK = 1
  5003 + FROM_FILES = 2
  5004 + def __init__(self, parent, *args, **kwds):
  5005 + wx.Dialog.__init__(self, parent, *args, **kwds)
  5006 +
  5007 + self.mask_path = ''
  5008 + self.method = self.FROM_MASK
  5009 +
  5010 + self._init_gui()
  5011 + self._bind_events_wx()
  5012 + self.get_all_masks()
  5013 +
  5014 + def _init_gui(self):
  5015 + self.SetTitle("dialog")
  5016 +
  5017 + from_mask_stbox = self._from_mask_gui()
  5018 + from_files_stbox = self._from_files_gui()
  5019 +
  5020 + main_sizer = wx.BoxSizer(wx.VERTICAL)
  5021 + main_sizer.Add(from_mask_stbox, 0, wx.EXPAND | wx.ALL, 5)
  5022 + main_sizer.Add(from_files_stbox, 0, wx.EXPAND | wx.ALL, 5)
  5023 +
  5024 + btn_sizer = wx.StdDialogButtonSizer()
  5025 + main_sizer.Add(btn_sizer, 0, wx.ALIGN_RIGHT | wx.ALL, 4)
  5026 +
  5027 + self.btn_ok = wx.Button(self, wx.ID_OK, "")
  5028 + self.btn_ok.SetDefault()
  5029 + btn_sizer.AddButton(self.btn_ok)
  5030 +
  5031 + self.btn_cancel = wx.Button(self, wx.ID_CANCEL, "")
  5032 + btn_sizer.AddButton(self.btn_cancel)
  5033 +
  5034 + btn_sizer.Realize()
  5035 +
  5036 + self.SetSizer(main_sizer)
  5037 + main_sizer.Fit(self)
  5038 +
  5039 + self.SetAffirmativeId(self.btn_ok.GetId())
  5040 + self.SetEscapeId(self.btn_cancel.GetId())
  5041 +
  5042 + self.Layout()
  5043 +
  5044 + def _from_mask_gui(self):
  5045 + mask_box = wx.StaticBox(self, -1, _("From mask"))
  5046 + from_mask_stbox = wx.StaticBoxSizer(mask_box, wx.VERTICAL)
  5047 +
  5048 + self.cb_masks = wx.ComboBox(self, wx.ID_ANY, choices=[])
  5049 + self.from_mask_rb = wx.RadioButton(self, -1, "", style = wx.RB_GROUP)
  5050 +
  5051 + internal_sizer = wx.BoxSizer(wx.HORIZONTAL)
  5052 + internal_sizer.Add(self.from_mask_rb, 0, wx.ALL | wx.EXPAND, 5)
  5053 + internal_sizer.Add(self.cb_masks, 1, wx.ALL | wx.EXPAND, 5)
  5054 +
  5055 + from_mask_stbox.Add(internal_sizer, 0, wx.EXPAND)
  5056 +
  5057 + return from_mask_stbox
  5058 +
  5059 + def _from_files_gui(self):
  5060 + session = ses.Session()
  5061 + last_directory = session.get('paths', 'last_directory_%d' % const.ID_NIFTI_IMPORT, '')
  5062 +
  5063 + files_box = wx.StaticBox(self, -1, _("From files"))
  5064 + from_files_stbox = wx.StaticBoxSizer(files_box, wx.VERTICAL)
  5065 +
  5066 + self.mask_file_browse = filebrowse.FileBrowseButton(self, -1, labelText=_("Mask file"),
  5067 + fileMask=WILDCARD_NIFTI, dialogTitle=_("Choose Mask file"), startDirectory = last_directory,
  5068 + changeCallback=lambda evt: self._set_files_callback(mask_path=evt.GetString()))
  5069 + self.from_files_rb = wx.RadioButton(self, -1, "")
  5070 +
  5071 + ctrl_sizer = wx.BoxSizer(wx.VERTICAL)
  5072 + ctrl_sizer.Add(self.mask_file_browse, 0, wx.ALL | wx.EXPAND, 5)
  5073 +
  5074 + internal_sizer = wx.BoxSizer(wx.HORIZONTAL)
  5075 + internal_sizer.Add(self.from_files_rb, 0, wx.ALL | wx.EXPAND, 5)
  5076 + internal_sizer.Add(ctrl_sizer, 0, wx.ALL | wx.EXPAND, 5)
  5077 +
  5078 + from_files_stbox.Add(internal_sizer, 0, wx.EXPAND)
  5079 +
  5080 + return from_files_stbox
  5081 +
  5082 + def _bind_events_wx(self):
  5083 + self.from_mask_rb.Bind(wx.EVT_RADIOBUTTON, self.on_select_method)
  5084 + self.from_files_rb.Bind(wx.EVT_RADIOBUTTON, self.on_select_method)
  5085 +
  5086 + def get_all_masks(self):
  5087 + import invesalius.project as prj
  5088 + inv_proj = prj.Project()
  5089 + choices = [i.name for i in inv_proj.mask_dict.values()]
  5090 + try:
  5091 + initial_value = choices[0]
  5092 + enable = True
  5093 + except IndexError:
  5094 + initial_value = ""
  5095 + enable = False
  5096 +
  5097 + self.cb_masks.SetItems(choices)
  5098 + self.cb_masks.SetValue(initial_value)
  5099 + self.btn_ok.Enable(enable)
  5100 +
  5101 + def on_select_method(self, evt):
  5102 + radio_selected = evt.GetEventObject()
  5103 + if radio_selected is self.from_mask_rb:
  5104 + self.method = self.FROM_MASK
  5105 + if self.cb_masks.GetItems():
  5106 + self.btn_ok.Enable(True)
  5107 + else:
  5108 + self.btn_ok.Enable(False)
  5109 + else:
  5110 + self.method = self.FROM_FILES
  5111 + if self._check_if_files_exists():
  5112 + self.btn_ok.Enable(True)
  5113 + else:
  5114 + self.btn_ok.Enable(False)
  5115 +
  5116 + def _set_files_callback(self, mask_path=''):
  5117 + if mask_path:
  5118 + self.mask_path = mask_path
  5119 + if self.method == self.FROM_FILES:
  5120 + if self._check_if_files_exists():
  5121 + self.btn_ok.Enable(True)
  5122 + else:
  5123 + self.btn_ok.Enable(False)
  5124 +
  5125 + def _check_if_files_exists(self):
  5126 + if self.mask_path and os.path.exists(self.mask_path):
  5127 + return True
  5128 + else:
  5129 + return False
invesalius/gui/task_navigator.py
@@ -31,7 +31,8 @@ try: @@ -31,7 +31,8 @@ try:
31 import Trekker 31 import Trekker
32 has_trekker = True 32 has_trekker = True
33 except ImportError: 33 except ImportError:
34 - has_trekker = False 34 + has_trekker = True
  35 +
35 try: 36 try:
36 import invesalius.data.elfin as elfin 37 import invesalius.data.elfin as elfin
37 import invesalius.data.elfin_processing as elfin_process 38 import invesalius.data.elfin_processing as elfin_process
@@ -40,6 +41,7 @@ except ImportError: @@ -40,6 +41,7 @@ except ImportError:
40 has_robot = False 41 has_robot = False
41 42
42 import wx 43 import wx
  44 +import vtk
43 45
44 try: 46 try:
45 import wx.lib.agw.foldpanelbar as fpb 47 import wx.lib.agw.foldpanelbar as fpb
@@ -72,6 +74,7 @@ from invesalius.navigation.icp import ICP @@ -72,6 +74,7 @@ from invesalius.navigation.icp import ICP
72 from invesalius.navigation.navigation import Navigation 74 from invesalius.navigation.navigation import Navigation
73 from invesalius.navigation.tracker import Tracker 75 from invesalius.navigation.tracker import Tracker
74 from invesalius.navigation.robot import Robot 76 from invesalius.navigation.robot import Robot
  77 +from invesalius.data.converters import to_vtk
75 78
76 from invesalius.net.neuronavigation_api import NeuronavigationApi 79 from invesalius.net.neuronavigation_api import NeuronavigationApi
77 80
@@ -1939,7 +1942,7 @@ class TractographyPanel(wx.Panel): @@ -1939,7 +1942,7 @@ class TractographyPanel(wx.Panel):
1939 def OnSelectPeelingDepth(self, evt, ctrl): 1942 def OnSelectPeelingDepth(self, evt, ctrl):
1940 self.peel_depth = ctrl.GetValue() 1943 self.peel_depth = ctrl.GetValue()
1941 if self.checkpeeling.GetValue(): 1944 if self.checkpeeling.GetValue():
1942 - actor = self.brain_peel.get_actor(self.peel_depth, self.affine_vtk) 1945 + actor = self.brain_peel.get_actor(self.peel_depth)
1943 Publisher.sendMessage('Update peel', flag=True, actor=actor) 1946 Publisher.sendMessage('Update peel', flag=True, actor=actor)
1944 Publisher.sendMessage('Get peel centers and normals', centers=self.brain_peel.peel_centers, 1947 Publisher.sendMessage('Get peel centers and normals', centers=self.brain_peel.peel_centers,
1945 normals=self.brain_peel.peel_normals) 1948 normals=self.brain_peel.peel_normals)
@@ -1972,7 +1975,7 @@ class TractographyPanel(wx.Panel): @@ -1972,7 +1975,7 @@ class TractographyPanel(wx.Panel):
1972 def OnShowPeeling(self, evt, ctrl): 1975 def OnShowPeeling(self, evt, ctrl):
1973 # self.view_peeling = ctrl.GetValue() 1976 # self.view_peeling = ctrl.GetValue()
1974 if ctrl.GetValue(): 1977 if ctrl.GetValue():
1975 - actor = self.brain_peel.get_actor(self.peel_depth, self.affine_vtk) 1978 + actor = self.brain_peel.get_actor(self.peel_depth)
1976 self.peel_loaded = True 1979 self.peel_loaded = True
1977 Publisher.sendMessage('Update peel visualization', data=self.peel_loaded) 1980 Publisher.sendMessage('Update peel visualization', data=self.peel_loaded)
1978 else: 1981 else:
@@ -2002,46 +2005,48 @@ class TractographyPanel(wx.Panel): @@ -2002,46 +2005,48 @@ class TractographyPanel(wx.Panel):
2002 2005
2003 def OnLinkBrain(self, event=None): 2006 def OnLinkBrain(self, event=None):
2004 Publisher.sendMessage('Begin busy cursor') 2007 Publisher.sendMessage('Begin busy cursor')
2005 - mask_path = dlg.ShowImportOtherFilesDialog(const.ID_NIFTI_IMPORT, _("Import brain mask"))  
2006 - img_path = dlg.ShowImportOtherFilesDialog(const.ID_NIFTI_IMPORT, _("Import T1 anatomical image"))  
2007 - # data_dir = os.environ.get('OneDrive') + r'\data\dti_navigation\baran\anat_reg_improve_20200609'  
2008 - # mask_file = 'Baran_brain_mask.nii'  
2009 - # mask_path = os.path.join(data_dir, mask_file)  
2010 - # img_file = 'Baran_T1_inFODspace.nii'  
2011 - # img_path = os.path.join(data_dir, img_file)  
2012 -  
2013 - if not self.affine_vtk: 2008 + inv_proj = prj.Project()
  2009 + peels_dlg = dlg.PeelsCreationDlg(wx.GetApp().GetTopWindow())
  2010 + ret = peels_dlg.ShowModal()
  2011 + method = peels_dlg.method
  2012 + if ret == wx.ID_OK:
2014 slic = sl.Slice() 2013 slic = sl.Slice()
2015 - prj_data = prj.Project()  
2016 - matrix_shape = tuple(prj_data.matrix_shape)  
2017 - spacing = tuple(prj_data.spacing)  
2018 - img_shift = spacing[1] * (matrix_shape[1] - 1)  
2019 - self.affine = slic.affine.copy()  
2020 - self.affine[1, -1] -= img_shift  
2021 - self.affine_vtk = vtk_utils.numpy_to_vtkMatrix4x4(self.affine)  
2022 -  
2023 - if mask_path and img_path:  
2024 - Publisher.sendMessage('Update status text in GUI', label=_("Busy"))  
2025 - try:  
2026 - self.brain_peel = brain.Brain(img_path, mask_path, self.n_peels, self.affine_vtk)  
2027 - self.brain_actor = self.brain_peel.get_actor(self.peel_depth, self.affine_vtk)  
2028 - self.brain_actor.GetProperty().SetOpacity(self.brain_opacity)  
2029 -  
2030 - self.checkpeeling.Enable(1)  
2031 - self.checkpeeling.SetValue(True)  
2032 - self.spin_opacity.Enable(1)  
2033 - self.peel_loaded = True  
2034 -  
2035 - Publisher.sendMessage('Update peel', flag=True, actor=self.brain_actor)  
2036 - Publisher.sendMessage('Get peel centers and normals', centers=self.brain_peel.peel_centers,  
2037 - normals=self.brain_peel.peel_normals)  
2038 - Publisher.sendMessage('Get init locator', locator=self.brain_peel.locator)  
2039 - Publisher.sendMessage('Update status text in GUI', label=_("Brain model loaded"))  
2040 - Publisher.sendMessage('Update peel visualization', data= self.peel_loaded)  
2041 - except:  
2042 - Publisher.sendMessage('Update status text in GUI', label=_("Brain mask initialization failed."))  
2043 - wx.MessageBox(_("Unable to load brain mask."), _("InVesalius 3")) 2014 + ww = slic.window_width
  2015 + wl = slic.window_level
  2016 + affine_vtk = vtk.vtkMatrix4x4()
  2017 +
  2018 + if method == peels_dlg.FROM_FILES:
  2019 + matrix_shape = tuple(inv_proj.matrix_shape)
  2020 + try:
  2021 + affine = slic.affine.copy()
  2022 + except AttributeError:
  2023 + affine = np.eye(4)
  2024 + affine[1, -1] -= matrix_shape[1]
  2025 + affine_vtk = vtk_utils.numpy_to_vtkMatrix4x4(affine)
  2026 +
  2027 + self.brain_peel = brain.Brain(self.n_peels, ww, wl, affine_vtk)
  2028 + if method == peels_dlg.FROM_MASK:
  2029 + choices = [i for i in inv_proj.mask_dict.values()]
  2030 + mask_index = peels_dlg.cb_masks.GetSelection()
  2031 + mask = choices[mask_index]
  2032 + self.brain_peel.from_mask(mask)
  2033 + else:
  2034 + mask_path = peels_dlg.mask_path
  2035 + self.brain_peel.from_mask_file(mask_path)
  2036 + self.brain_actor = self.brain_peel.get_actor(self.peel_depth)
  2037 + self.brain_actor.GetProperty().SetOpacity(self.brain_opacity)
  2038 + Publisher.sendMessage('Update peel', flag=True, actor=self.brain_actor)
  2039 + Publisher.sendMessage('Get peel centers and normals', centers=self.brain_peel.peel_centers,
  2040 + normals=self.brain_peel.peel_normals)
  2041 + Publisher.sendMessage('Get init locator', locator=self.brain_peel.locator)
  2042 + self.checkpeeling.Enable(1)
  2043 + self.checkpeeling.SetValue(True)
  2044 + self.spin_opacity.Enable(1)
  2045 + Publisher.sendMessage('Update status text in GUI', label=_("Brain model loaded"))
  2046 + self.peel_loaded = True
  2047 + Publisher.sendMessage('Update peel visualization', data= self.peel_loaded)
2044 2048
  2049 + peels_dlg.Destroy()
2045 Publisher.sendMessage('End busy cursor') 2050 Publisher.sendMessage('End busy cursor')
2046 2051
2047 def OnLinkFOD(self, event=None): 2052 def OnLinkFOD(self, event=None):