Commit 160fcc1f698b3818c4fa794007e190783f6337a9

Authored by tatiana
1 parent 718f8735

ADD: Export surface in several formats and vtkImageData

invesalius/constants.py
@@ -218,6 +218,10 @@ FILETYPE_RIB = wx.NewId() @@ -218,6 +218,10 @@ FILETYPE_RIB = wx.NewId()
218 FILETYPE_STL = wx.NewId() 218 FILETYPE_STL = wx.NewId()
219 FILETYPE_VRML = wx.NewId() 219 FILETYPE_VRML = wx.NewId()
220 FILETYPE_OBJ = wx.NewId() 220 FILETYPE_OBJ = wx.NewId()
  221 +FILETYPE_VTP = wx.NewId()
  222 +FILETYPE_PLY = wx.NewId()
  223 +
  224 +FILETYPE_IMAGEDATA = wx.NewId()
221 225
222 FILETYPE_BMP = wx.NewId() 226 FILETYPE_BMP = wx.NewId()
223 FILETYPE_JPG = wx.NewId() 227 FILETYPE_JPG = wx.NewId()
invesalius/data/slice_.py
@@ -4,6 +4,7 @@ import vtk @@ -4,6 +4,7 @@ import vtk
4 import wx.lib.pubsub as ps 4 import wx.lib.pubsub as ps
5 5
6 import constants as const 6 import constants as const
  7 +import imagedata_utils as iu
7 from mask import Mask 8 from mask import Mask
8 from project import Project 9 from project import Project
9 from utils import Singleton 10 from utils import Singleton
@@ -60,6 +61,7 @@ class Slice(object): @@ -60,6 +61,7 @@ class Slice(object):
60 'Change colour table from background image') 61 'Change colour table from background image')
61 62
62 ps.Publisher().subscribe(self.InputImageWidget, 'Input Image in the widget') 63 ps.Publisher().subscribe(self.InputImageWidget, 'Input Image in the widget')
  64 + ps.Publisher().subscribe(self.OnExportMask,'Export mask to file')
63 65
64 def __set_current_mask_threshold_limits(self, pubsub_evt): 66 def __set_current_mask_threshold_limits(self, pubsub_evt):
65 thresh_min = pubsub_evt.data[0] 67 thresh_min = pubsub_evt.data[0]
@@ -544,3 +546,15 @@ class Slice(object): @@ -544,3 +546,15 @@ class Slice(object):
544 imagedata_mask.Update() 546 imagedata_mask.Update()
545 547
546 return imagedata_mask 548 return imagedata_mask
  549 +
  550 +
  551 + def OnExportMask(self, pubsub_evt):
  552 + #imagedata = self.current_mask.imagedata
  553 + imagedata = self.imagedata
  554 + filename, filetype = pubsub_evt.data
  555 + if (filetype == const.FILETYPE_IMAGEDATA):
  556 + iu.Export(imagedata, filename)
  557 +
  558 +
  559 +
  560 +
invesalius/data/surface.py
@@ -284,7 +284,11 @@ class SurfaceManager(): @@ -284,7 +284,11 @@ class SurfaceManager():
284 284
285 def OnExportSurface(self, pubsub_evt): 285 def OnExportSurface(self, pubsub_evt):
286 filename, filetype = pubsub_evt.data 286 filename, filetype = pubsub_evt.data
287 - if filetype == const.FILETYPE_STL: 287 + if (filetype == const.FILETYPE_STL) or\
  288 + (filetype == const.FILETYPE_VTP):
  289 +
  290 + # First we identify all surfaces that are selected
  291 + # (if any)
288 proj = prj.Project() 292 proj = prj.Project()
289 polydata_list = [] 293 polydata_list = []
290 for index in proj.surface_dict: 294 for index in proj.surface_dict:
@@ -299,10 +303,24 @@ class SurfaceManager(): @@ -299,10 +303,24 @@ class SurfaceManager():
299 else: 303 else:
300 polydata = pu.Merge(polydata_list) 304 polydata = pu.Merge(polydata_list)
301 305
302 - writer = vtk.vtkSTLWriter()  
303 - writer.SetFileTypeToBinary() 306 +
  307 + # Having a polydata that represents all surfaces
  308 + # selected, we write it, according to filetype
  309 + if filetype == const.FILETYPE_STL:
  310 + writer = vtk.vtkSTLWriter()
  311 + writer.SetFileTypeToBinary()
  312 + elif filetype == const.FILETYPE_VTP:
  313 + writer = vtk.vtkXMLPolyDataWriter()
  314 + elif filetype == const.FILETYPE_IV:
  315 + writer = vtk.vtkIVWriter()
  316 + elif filetype == const.FILETYPE_PLY:
  317 + writer = vtk.vtkPLYWriter()
  318 + writer.SetFileTypeToBinary()
  319 + writer.SetDataByteOrderToLittleEndian()
  320 + #writer.SetColorModeToUniformCellColor()
  321 + #writer.SetColor(255, 0, 0)
  322 +
304 writer.SetFileName(filename) 323 writer.SetFileName(filename)
305 writer.SetInput(polydata) 324 writer.SetInput(polydata)
306 writer.Write() 325 writer.Write()
307 326
308 -  
invesalius/gui/task_exporter.py
@@ -28,26 +28,34 @@ import wx.lib.pubsub as ps @@ -28,26 +28,34 @@ import wx.lib.pubsub as ps
28 import constants as const 28 import constants as const
29 import project as proj 29 import project as proj
30 30
  31 +BTN_MASK = wx.NewId()
31 BTN_PICTURE = wx.NewId() 32 BTN_PICTURE = wx.NewId()
32 BTN_SURFACE = wx.NewId() 33 BTN_SURFACE = wx.NewId()
33 BTN_REPORT = wx.NewId() 34 BTN_REPORT = wx.NewId()
34 BTN_REQUEST_RP = wx.NewId() 35 BTN_REQUEST_RP = wx.NewId()
35 36
36 WILDCARD_SAVE_3D = "Inventor (*.iv)|*.iv|"\ 37 WILDCARD_SAVE_3D = "Inventor (*.iv)|*.iv|"\
  38 + "PLY (*.ply)|*.ply|"\
37 "Renderman (*.rib)|*.rib|"\ 39 "Renderman (*.rib)|*.rib|"\
38 "STL (*.stl)|*.stl|"\ 40 "STL (*.stl)|*.stl|"\
39 "VRML (*.vrml)|*.vrml|"\ 41 "VRML (*.vrml)|*.vrml|"\
  42 + "VTK PolyData (*.vtp)|*.vtp|"\
40 "Wavefront (*.obj)|*.obj" 43 "Wavefront (*.obj)|*.obj"
  44 +
41 INDEX_TO_TYPE_3D = {0: const.FILETYPE_IV, 45 INDEX_TO_TYPE_3D = {0: const.FILETYPE_IV,
42 - 1: const.FILETYPE_RIB,  
43 - 2: const.FILETYPE_STL,  
44 - 3: const.FILETYPE_VRML,  
45 - 4: const.FILETYPE_OBJ} 46 + 1: const.FILETYPE_PLY,
  47 + 2: const.FILETYPE_RIB,
  48 + 3: const.FILETYPE_STL,
  49 + 4: const.FILETYPE_VRML,
  50 + 5: const.FILETYPE_VTP,
  51 + 6: const.FILETYPE_OBJ}
46 INDEX_TO_EXTENSION = {0: "iv", 52 INDEX_TO_EXTENSION = {0: "iv",
47 - 1: "rib",  
48 - 2: "stl",  
49 - 3: "vrml",  
50 - 4: "obj"} 53 + 1: "ply",
  54 + 2: "rib",
  55 + 3: "stl",
  56 + 4: "vrml",
  57 + 5: "vtp",
  58 + 6: "obj"}
51 59
52 WILDCARD_SAVE_2D = "BMP (*.bmp)|*.bmp|"\ 60 WILDCARD_SAVE_2D = "BMP (*.bmp)|*.bmp|"\
53 "JPEG (*.jpg)|*.jpg|"\ 61 "JPEG (*.jpg)|*.jpg|"\
@@ -62,6 +70,8 @@ INDEX_TO_TYPE_2D = {0: const.FILETYPE_BMP, @@ -62,6 +70,8 @@ INDEX_TO_TYPE_2D = {0: const.FILETYPE_BMP,
62 4: const.FILETYPE_POV, 70 4: const.FILETYPE_POV,
63 5: const.FILETYPE_OBJ} 71 5: const.FILETYPE_OBJ}
64 72
  73 +WILDCARD_SAVE_MASK = "VTK ImageData (*.vti)|*.vti"
  74 +
65 75
66 class TaskPanel(wx.Panel): 76 class TaskPanel(wx.Panel):
67 def __init__(self, parent): 77 def __init__(self, parent):
@@ -109,6 +119,17 @@ class InnerTaskPanel(wx.Panel): @@ -109,6 +119,17 @@ class InnerTaskPanel(wx.Panel):
109 link_export_surface.Bind(hl.EVT_HYPERLINK_LEFT, 119 link_export_surface.Bind(hl.EVT_HYPERLINK_LEFT,
110 self.OnLinkExportSurface) 120 self.OnLinkExportSurface)
111 121
  122 + tooltip = wx.ToolTip("Export 3D mask (voxels)")
  123 + link_export_mask = hl.HyperLinkCtrl(self, -1,"Export mask...")
  124 + link_export_mask.SetUnderlines(False, False, False)
  125 + link_export_mask.SetColours("BLACK", "BLACK", "BLACK")
  126 + link_export_mask.SetToolTip(tooltip)
  127 + link_export_mask.AutoBrowse(False)
  128 + link_export_mask.UpdateLink()
  129 + link_export_mask.Bind(hl.EVT_HYPERLINK_LEFT,
  130 + self.OnLinkExportMask)
  131 +
  132 +
112 #tooltip = wx.ToolTip("Request rapid prototyping services") 133 #tooltip = wx.ToolTip("Request rapid prototyping services")
113 #link_request_rp = hl.HyperLinkCtrl(self,-1,"Request rapid prototyping...") 134 #link_request_rp = hl.HyperLinkCtrl(self,-1,"Request rapid prototyping...")
114 #link_request_rp.SetUnderlines(False, False, False) 135 #link_request_rp.SetUnderlines(False, False, False)
@@ -136,14 +157,19 @@ class InnerTaskPanel(wx.Panel): @@ -136,14 +157,19 @@ class InnerTaskPanel(wx.Panel):
136 BMP_TAKE_PICTURE = wx.Bitmap(\ 157 BMP_TAKE_PICTURE = wx.Bitmap(\
137 "../icons/tool_photo_original.png", 158 "../icons/tool_photo_original.png",
138 wx.BITMAP_TYPE_PNG) 159 wx.BITMAP_TYPE_PNG)
  160 + BMP_EXPORT_MASK = wx.Bitmap("../icons/mask.png",
  161 + wx.BITMAP_TYPE_PNG)
139 else: 162 else:
140 BMP_EXPORT_SURFACE = wx.Bitmap("../icons/surface_export.png", 163 BMP_EXPORT_SURFACE = wx.Bitmap("../icons/surface_export.png",
141 wx.BITMAP_TYPE_PNG) 164 wx.BITMAP_TYPE_PNG)
142 BMP_TAKE_PICTURE = wx.Bitmap("../icons/tool_photo.png", 165 BMP_TAKE_PICTURE = wx.Bitmap("../icons/tool_photo.png",
143 wx.BITMAP_TYPE_PNG) 166 wx.BITMAP_TYPE_PNG)
  167 + BMP_EXPORT_MASK = wx.Bitmap("../icons/mask_small.png",
  168 + wx.BITMAP_TYPE_PNG)
144 169
145 170
146 - bmp_list = [BMP_TAKE_PICTURE, BMP_EXPORT_SURFACE] 171 + bmp_list = [BMP_TAKE_PICTURE, BMP_EXPORT_SURFACE,
  172 + BMP_EXPORT_MASK]
147 for bmp in bmp_list: 173 for bmp in bmp_list:
148 bmp.SetWidth(25) 174 bmp.SetWidth(25)
149 bmp.SetHeight(25) 175 bmp.SetHeight(25)
@@ -157,6 +183,9 @@ class InnerTaskPanel(wx.Panel): @@ -157,6 +183,9 @@ class InnerTaskPanel(wx.Panel):
157 button_surface = pbtn.PlateButton(self, BTN_SURFACE, "", 183 button_surface = pbtn.PlateButton(self, BTN_SURFACE, "",
158 BMP_EXPORT_SURFACE, 184 BMP_EXPORT_SURFACE,
159 style=button_style) 185 style=button_style)
  186 + button_mask = pbtn.PlateButton(self, BTN_MASK, "",
  187 + BMP_EXPORT_MASK,
  188 + style=button_style)
160 #button_request_rp = pbtn.PlateButton(self, BTN_REQUEST_RP, "", 189 #button_request_rp = pbtn.PlateButton(self, BTN_REQUEST_RP, "",
161 # BMP_IMPORT, style=button_style) 190 # BMP_IMPORT, style=button_style)
162 #button_report = pbtn.PlateButton(self, BTN_REPORT, "", 191 #button_report = pbtn.PlateButton(self, BTN_REPORT, "",
@@ -170,12 +199,14 @@ class InnerTaskPanel(wx.Panel): @@ -170,12 +199,14 @@ class InnerTaskPanel(wx.Panel):
170 flag_link = wx.EXPAND|wx.GROW|wx.LEFT|wx.TOP 199 flag_link = wx.EXPAND|wx.GROW|wx.LEFT|wx.TOP
171 flag_button = wx.EXPAND | wx.GROW 200 flag_button = wx.EXPAND | wx.GROW
172 201
173 - fixed_sizer = wx.FlexGridSizer(rows=2, cols=2, hgap=2, vgap=0) 202 + fixed_sizer = wx.FlexGridSizer(rows=3, cols=2, hgap=2, vgap=0)
174 fixed_sizer.AddGrowableCol(0, 1) 203 fixed_sizer.AddGrowableCol(0, 1)
175 fixed_sizer.AddMany([ (link_export_picture, 1, flag_link, 3), 204 fixed_sizer.AddMany([ (link_export_picture, 1, flag_link, 3),
176 (button_picture, 0, flag_button), 205 (button_picture, 0, flag_button),
177 (link_export_surface, 1, flag_link, 3), 206 (link_export_surface, 1, flag_link, 3),
178 - (button_surface, 0, flag_button)])#, 207 + (button_surface, 0, flag_button),#])#,
  208 + (link_export_mask, 1, flag_link, 3),
  209 + (button_mask, 0, flag_button)])
179 #(link_report, 0, flag_link, 3), 210 #(link_report, 0, flag_link, 3),
180 #(button_report, 0, flag_button), 211 #(button_report, 0, flag_button),
181 #(link_request_rp, 1, flag_link, 3), 212 #(link_request_rp, 1, flag_link, 3),
@@ -193,8 +224,37 @@ class InnerTaskPanel(wx.Panel): @@ -193,8 +224,37 @@ class InnerTaskPanel(wx.Panel):
193 def OnLinkExportPicture(self, evt=None): 224 def OnLinkExportPicture(self, evt=None):
194 pass 225 pass
195 226
  227 + def OnLinkExportMask(self, evt=None):
  228 + project = proj.Project()
  229 + print "OnLinkEportMask"
  230 + if sys.platform == 'win32':
  231 + project_name = project.name
  232 + else:
  233 + project_name = project.name+".vti"
  234 +
  235 +
  236 + dlg = wx.FileDialog(None,
  237 + "Save mask as...", # title
  238 + "", # last used directory
  239 + project_name, # filename
  240 + WILDCARD_SAVE_MASK,
  241 + wx.SAVE|wx.OVERWRITE_PROMPT)
  242 + dlg.SetFilterIndex(0) # default is VTI
  243 +
  244 + if dlg.ShowModal() == wx.ID_OK:
  245 + filename = dlg.GetPath()
  246 + print "filename", filename
  247 + extension = "vti"
  248 + if sys.platform != 'win32':
  249 + if filename.split(".")[-1] != extension:
  250 + filename = filename + "."+ extension
  251 + filetype = const.FILETYPE_IMAGEDATA
  252 + ps.Publisher().sendMessage('Export mask to file',
  253 + (filename, filetype))
  254 +
196 255
197 def OnLinkExportSurface(self, evt=None): 256 def OnLinkExportSurface(self, evt=None):
  257 + "OnLinkExportSurface"
198 project = proj.Project() 258 project = proj.Project()
199 n_surface = 0 259 n_surface = 0
200 260
@@ -215,7 +275,7 @@ class InnerTaskPanel(wx.Panel): @@ -215,7 +275,7 @@ class InnerTaskPanel(wx.Panel):
215 project_name, # filename 275 project_name, # filename
216 WILDCARD_SAVE_3D, 276 WILDCARD_SAVE_3D,
217 wx.SAVE|wx.OVERWRITE_PROMPT) 277 wx.SAVE|wx.OVERWRITE_PROMPT)
218 - dlg.SetFilterIndex(2) # default is STL 278 + dlg.SetFilterIndex(3) # default is STL
219 279
220 if dlg.ShowModal() == wx.ID_OK: 280 if dlg.ShowModal() == wx.ID_OK:
221 filetype_index = dlg.GetFilterIndex() 281 filetype_index = dlg.GetFilterIndex()
@@ -252,5 +312,7 @@ class InnerTaskPanel(wx.Panel): @@ -252,5 +312,7 @@ class InnerTaskPanel(wx.Panel):
252 self.OnLinkExportSurface() 312 self.OnLinkExportSurface()
253 elif id == BTN_REPORT: 313 elif id == BTN_REPORT:
254 self.OnLinkReport() 314 self.OnLinkReport()
255 - else: #elif id == BTN_REQUEST_RP: 315 + elif id == BTN_REQUEST_RP:
256 self.OnLinkRequestRP() 316 self.OnLinkRequestRP()
  317 + else:# id == BTN_MASK:
  318 + self.OnLinkExportMask()