Commit e2a484bd6cf01d05f6daaf85ee8feeb6a7285194

Authored by rmatsuda
2 parents 78c5f802 d498a62e
Exists in master

Merge branch 'master' into icp

Showing 113 changed files with 355 additions and 317 deletions   Show diff stats
@@ -40,7 +40,11 @@ if sys.platform == 'win32': @@ -40,7 +40,11 @@ if sys.platform == 'win32':
40 # #wxversion.ensureMinimal('2.8-unicode', optionsRequired=True) 40 # #wxversion.ensureMinimal('2.8-unicode', optionsRequired=True)
41 # #wxversion.select('2.8-unicode', optionsRequired=True) 41 # #wxversion.select('2.8-unicode', optionsRequired=True)
42 # # wxversion.ensureMinimal('4.0') 42 # # wxversion.ensureMinimal('4.0')
43 - 43 +
  44 +# Forcing to use X11, OpenGL in wxPython doesn't work with Wayland.
  45 +if sys.platform not in ("win32", "darwin"):
  46 + os.environ["GDK_BACKEND"] = "x11"
  47 +
44 import wx 48 import wx
45 try: 49 try:
46 from wx.adv import SplashScreen 50 from wx.adv import SplashScreen
@@ -98,7 +102,7 @@ class InVesalius(wx.App): @@ -98,7 +102,7 @@ class InVesalius(wx.App):
98 """ 102 """
99 Initialize splash screen and main frame. 103 Initialize splash screen and main frame.
100 """ 104 """
101 - 105 +
102 from multiprocessing import freeze_support 106 from multiprocessing import freeze_support
103 freeze_support() 107 freeze_support()
104 108
@@ -179,18 +183,18 @@ class Inv3SplashScreen(SplashScreen): @@ -179,18 +183,18 @@ class Inv3SplashScreen(SplashScreen):
179 183
180 # session.SaveConfigFileBackup() 184 # session.SaveConfigFileBackup()
181 185
182 - 186 +
183 # Only after language was defined, splash screen will be 187 # Only after language was defined, splash screen will be
184 # shown 188 # shown
185 if lang: 189 if lang:
186 - 190 +
187 #import locale 191 #import locale
188 #try: 192 #try:
189 # locale.setlocale(locale.LC_ALL, '') 193 # locale.setlocale(locale.LC_ALL, '')
190 #except locale.Error: 194 #except locale.Error:
191 # pass 195 # pass
192 -  
193 - 196 +
  197 +
194 # For pt_BR, splash_pt.png should be used 198 # For pt_BR, splash_pt.png should be used
195 if (lang.startswith('pt')): 199 if (lang.startswith('pt')):
196 icon_file = "splash_pt.png" 200 icon_file = "splash_pt.png"
@@ -202,13 +206,13 @@ class Inv3SplashScreen(SplashScreen): @@ -202,13 +206,13 @@ class Inv3SplashScreen(SplashScreen):
202 abs_file_path = os.path.abspath(".." + os.sep) 206 abs_file_path = os.path.abspath(".." + os.sep)
203 path = abs_file_path 207 path = abs_file_path
204 path = os.path.join(path, 'icons', icon_file) 208 path = os.path.join(path, 'icons', icon_file)
205 - 209 +
206 else: 210 else:
207 211
208 path = os.path.join(".","icons", icon_file) 212 path = os.path.join(".","icons", icon_file)
209 if not os.path.exists(path): 213 if not os.path.exists(path):
210 path = os.path.join(".", "icons", "splash_en.png") 214 path = os.path.join(".", "icons", "splash_en.png")
211 - 215 +
212 bmp = wx.Image(path).ConvertToBitmap() 216 bmp = wx.Image(path).ConvertToBitmap()
213 217
214 try: 218 try:
@@ -232,10 +236,10 @@ class Inv3SplashScreen(SplashScreen): @@ -232,10 +236,10 @@ class Inv3SplashScreen(SplashScreen):
232 from invesalius.gui.frame import Frame 236 from invesalius.gui.frame import Frame
233 from invesalius.control import Controller 237 from invesalius.control import Controller
234 from invesalius.project import Project 238 from invesalius.project import Project
235 - 239 +
236 self.main = Frame(None) 240 self.main = Frame(None)
237 self.control = Controller(self.main) 241 self.control = Controller(self.main)
238 - 242 +
239 self.fc = wx.CallLater(200, self.ShowMain) 243 self.fc = wx.CallLater(200, self.ShowMain)
240 options, args = parse_comand_line() 244 options, args = parse_comand_line()
241 wx.CallLater(1, use_cmd_optargs, options, args) 245 wx.CallLater(1, use_cmd_optargs, options, args)
@@ -498,7 +502,7 @@ def main(): @@ -498,7 +502,7 @@ def main():
498 if __name__ == '__main__': 502 if __name__ == '__main__':
499 #Is needed because of pyinstaller 503 #Is needed because of pyinstaller
500 multiprocessing.freeze_support() 504 multiprocessing.freeze_support()
501 - 505 +
502 #Needed in win 32 exe 506 #Needed in win 32 exe
503 if hasattr(sys,"frozen") and sys.platform.startswith('win'): 507 if hasattr(sys,"frozen") and sys.platform.startswith('win'):
504 508
@@ -523,4 +527,3 @@ if __name__ == '__main__': @@ -523,4 +527,3 @@ if __name__ == '__main__':
523 527
524 # Init application 528 # Init application
525 main() 529 main()
526 -  
icons/3D_glasses_original.png

12.6 KB | W: | H:

2 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/be.bmp
No preview for this file type
icons/be.png 0 → 100644

595 Bytes

icons/brush_circle.jpg

1.17 KB

icons/brush_circle.png 0 → 100644

1.07 KB

icons/brush_square.jpg

1022 Bytes

icons/brush_square.png 0 → 100644

934 Bytes

icons/ca.bmp
No preview for this file type
icons/ca.png 0 → 100644

307 Bytes

icons/cross_original.png

1.37 KB | W: | H:

1.48 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/cs.bmp
No preview for this file type
icons/cs.png 0 → 100644

646 Bytes

icons/de_DE.bmp
No preview for this file type
icons/de_DE.png 0 → 100644

562 Bytes

icons/el_GR.bmp
No preview for this file type
icons/el_GR.png 0 → 100644

576 Bytes

icons/en.bmp
No preview for this file type
icons/en.png 0 → 100644

957 Bytes

icons/es.bmp
No preview for this file type
icons/es.png 0 → 100644

472 Bytes

icons/file_from_internet_original.png

3.04 KB | W: | H:

3.15 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/file_import_original.png

1.96 KB | W: | H:

2.07 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/file_open_original.png

1.93 KB | W: | H:

2.04 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/file_save_original.png

1.71 KB | W: | H:

1.82 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/fr.bmp
No preview for this file type
icons/fr.png 0 → 100644

360 Bytes

icons/it.bmp
No preview for this file type
icons/it.png

196 Bytes | W: | H:

488 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/ja.bmp
No preview for this file type
icons/ja.png 0 → 100644

431 Bytes

icons/ko.bmp
No preview for this file type
icons/ko.png 0 → 100644

721 Bytes

icons/layout_data_only.gif

1.17 KB

icons/layout_data_only.png

1.43 KB | W: | H:

931 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/layout_data_only_original.gif

788 Bytes

icons/layout_data_only_original.png

1004 Bytes | W: | H:

855 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/layout_full.gif

1.17 KB

icons/layout_full.png

1.46 KB | W: | H:

917 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/layout_full_original.gif

804 Bytes

icons/layout_full_original.png

996 Bytes | W: | H:

883 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/measure_angle.jpg

701 Bytes

icons/measure_angle.png

1.79 KB | W: | H:

4.7 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/measure_angle_original.jpg

1.79 KB

icons/measure_angle_original.png

2.16 KB | W: | H:

6.49 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/measure_line_original.png

2.09 KB | W: | H:

2.21 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/object_add.gif

1.58 KB

icons/object_add_original.png

9.17 KB | W: | H:

2.03 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/object_colour.jpg

360 Bytes

icons/object_colour.png 0 → 100644

352 Bytes

icons/object_invisible.jpg

297 Bytes

icons/object_invisible.png 0 → 100644

284 Bytes

icons/object_remove.gif

1.65 KB

icons/object_remove_original.png

9.47 KB | W: | H:

1.97 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/object_visible.jpg

1.88 KB

icons/object_visible.png 0 → 100644

3.34 KB

icons/print_original.png

2.21 KB | W: | H:

2.32 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/pt.bmp
No preview for this file type
icons/pt.png 0 → 100644

651 Bytes

icons/pt_BR.bmp
No preview for this file type
icons/pt_BR.png 0 → 100644

596 Bytes

icons/redo_original.png

1.64 KB | W: | H:

1.75 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/ro.bmp
No preview for this file type
icons/ro.png 0 → 100644

278 Bytes

icons/ru.bmp
No preview for this file type
icons/ru.png 0 → 100644

289 Bytes

icons/slice_original.png

828 Bytes | W: | H:

942 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/slice_plane_original.png

2.64 KB | W: | H:

2.01 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/surface_export_original.png

27.4 KB | W: | H:

3.25 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/text.gif

243 Bytes

icons/text.png

477 Bytes | W: | H:

422 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/text_inverted_original.png

541 Bytes | W: | H:

655 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/text_original.png

567 Bytes | W: | H:

681 Bytes | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/tool_annotation_original.png

21.6 KB | W: | H:

2.21 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/tool_contrast_original.png

1.65 KB | W: | H:

1.76 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/tool_photo_original.png

2.87 KB | W: | H:

2.99 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/tool_rotate_original.gif

1.63 KB

icons/tool_rotate_original.png

2.45 KB | W: | H:

2.57 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/tool_translate_original.png

2.21 KB | W: | H:

2.32 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/tool_zoom_in_original.png

13.5 KB | W: | H:

2.64 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/tool_zoom_original.png

2.11 KB | W: | H:

2.22 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/tool_zoom_out_original.png

13.6 KB | W: | H:

2.64 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/tool_zoom_select_original.png

2.23 KB | W: | H:

2.35 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/tr_TR.bmp
No preview for this file type
icons/tr_TR.png 0 → 100644

409 Bytes

icons/undo_original.png

1.72 KB | W: | H:

1.83 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/volume_raycasting_original.png

3.03 KB | W: | H:

2.21 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
icons/zh_TW.bmp
No preview for this file type
icons/zh_TW.png 0 → 100644

846 Bytes

invesalius/data/imagedata_utils.py
@@ -500,34 +500,6 @@ def img2memmap(group): @@ -500,34 +500,6 @@ def img2memmap(group):
500 return matrix, scalar_range, temp_file 500 return matrix, scalar_range, temp_file
501 501
502 502
503 -def imgnormalize(data, srange=(0, 255)):  
504 - """  
505 - Normalize image pixel intensity for int16 gray scale values.  
506 -  
507 - :param data: image matrix  
508 - :param srange: range for normalization, default is 0 to 255  
509 - :return: normalized pixel intensity matrix  
510 - """  
511 -  
512 - dataf = numpy.asarray(data)  
513 - rangef = numpy.asarray(srange)  
514 - faux = numpy.ravel(dataf).astype(float)  
515 - minimum = numpy.min(faux)  
516 - maximum = numpy.max(faux)  
517 - lower = rangef[0]  
518 - upper = rangef[1]  
519 -  
520 - if minimum == maximum:  
521 - datan = numpy.ones(dataf.shape)*(upper + lower) / 2.  
522 - else:  
523 - datan = (faux-minimum)*(upper-lower) / (maximum-minimum) + lower  
524 -  
525 - datan = numpy.reshape(datan, dataf.shape)  
526 - datan = datan.astype(numpy.int16)  
527 -  
528 - return datan  
529 -  
530 -  
531 def get_LUT_value_255(data, window, level): 503 def get_LUT_value_255(data, window, level):
532 shape = data.shape 504 shape = data.shape
533 data_ = data.ravel() 505 data_ = data.ravel()
@@ -539,6 +511,8 @@ def get_LUT_value_255(data, window, level): @@ -539,6 +511,8 @@ def get_LUT_value_255(data, window, level):
539 return data 511 return data
540 512
541 513
542 -def image_normalize(image, min_=0.0, max_=1.0): 514 +def image_normalize(image, min_=0.0, max_=1.0, output_dtype=np.int16):
  515 + output = np.empty(shape=image.shape, dtype=output_dtype)
543 imin, imax = image.min(), image.max() 516 imin, imax = image.min(), image.max()
544 - return (image - imin) * ((max_ - min_) / (imax - imin)) + min_ 517 + output[:] = (image - imin) * ((max_ - min_) / (imax - imin)) + min_
  518 + return output
invesalius/data/slice_.py
@@ -301,7 +301,10 @@ class Slice(metaclass=utils.Singleton): @@ -301,7 +301,10 @@ class Slice(metaclass=utils.Singleton):
301 301
302 for name in self.aux_matrices: 302 for name in self.aux_matrices:
303 m = self.aux_matrices[name] 303 m = self.aux_matrices[name]
304 - f = m.filename 304 + try:
  305 + f = m.filename
  306 + except AttributeError:
  307 + continue
305 m._mmap.close() 308 m._mmap.close()
306 m = None 309 m = None
307 os.remove(f) 310 os.remove(f)
@@ -347,6 +350,8 @@ class Slice(metaclass=utils.Singleton): @@ -347,6 +350,8 @@ class Slice(metaclass=utils.Singleton):
347 self.SetMaskEditionThreshold(index, threshold_range) 350 self.SetMaskEditionThreshold(index, threshold_range)
348 351
349 def __set_current_mask_threshold(self, threshold_range): 352 def __set_current_mask_threshold(self, threshold_range):
  353 + if self.current_mask is None:
  354 + return
350 index = self.current_mask.index 355 index = self.current_mask.index
351 self.num_gradient += 1 356 self.num_gradient += 1
352 self.current_mask.matrix[:] = 0 357 self.current_mask.matrix[:] = 0
@@ -387,6 +392,8 @@ class Slice(metaclass=utils.Singleton): @@ -387,6 +392,8 @@ class Slice(metaclass=utils.Singleton):
387 Publisher.sendMessage("Reload actual slice") 392 Publisher.sendMessage("Reload actual slice")
388 393
389 def __set_current_mask_threshold_actual_slice(self, threshold_range): 394 def __set_current_mask_threshold_actual_slice(self, threshold_range):
  395 + if self.current_mask is None:
  396 + return
390 index = self.current_mask.index 397 index = self.current_mask.index
391 for orientation in self.buffer_slices: 398 for orientation in self.buffer_slices:
392 self.buffer_slices[orientation].discard_vtk_mask() 399 self.buffer_slices[orientation].discard_vtk_mask()
@@ -624,7 +631,7 @@ class Slice(metaclass=utils.Singleton): @@ -624,7 +631,7 @@ class Slice(metaclass=utils.Singleton):
624 self.buffer_slices[orientation].vtk_image = image 631 self.buffer_slices[orientation].vtk_image = image
625 self.buffer_slices[orientation].vtk_mask = mask 632 self.buffer_slices[orientation].vtk_mask = mask
626 633
627 - if self.to_show_aux == "watershed" and self.current_mask.is_shown: 634 + if self.to_show_aux == "watershed" and self.current_mask is not None and self.current_mask.is_shown:
628 m = self.get_aux_slice("watershed", orientation, slice_number) 635 m = self.get_aux_slice("watershed", orientation, slice_number)
629 tmp_vimage = converters.to_vtk(m, self.spacing, slice_number, orientation) 636 tmp_vimage = converters.to_vtk(m, self.spacing, slice_number, orientation)
630 cimage = self.do_custom_colour( 637 cimage = self.do_custom_colour(
invesalius/data/viewer_slice.py
@@ -102,13 +102,13 @@ class ContourMIPConfig(wx.Panel): @@ -102,13 +102,13 @@ class ContourMIPConfig(wx.Panel):
102 self.txt_mip_border = wx.StaticText(self, -1, _("Sharpness")) 102 self.txt_mip_border = wx.StaticText(self, -1, _("Sharpness"))
103 103
104 sizer = wx.BoxSizer(wx.HORIZONTAL) 104 sizer = wx.BoxSizer(wx.HORIZONTAL)
105 - sizer.Add(txt_mip_size, 0, wx.EXPAND | wx.ALL, 2) 105 + sizer.Add(txt_mip_size, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 2)
106 sizer.Add(self.mip_size_spin, 0) 106 sizer.Add(self.mip_size_spin, 0)
107 try: 107 try:
108 sizer.Add(10, 0) 108 sizer.Add(10, 0)
109 except TypeError: 109 except TypeError:
110 sizer.Add((10, 0)) 110 sizer.Add((10, 0))
111 - sizer.Add(self.txt_mip_border, 0, wx.EXPAND | wx.ALL, 2) 111 + sizer.Add(self.txt_mip_border, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 2)
112 sizer.Add(self.border_spin, 0, wx.EXPAND) 112 sizer.Add(self.border_spin, 0, wx.EXPAND)
113 try: 113 try:
114 sizer.Add(10, 0) 114 sizer.Add(10, 0)
@@ -1438,8 +1438,12 @@ class Viewer(wx.Panel): @@ -1438,8 +1438,12 @@ class Viewer(wx.Panel):
1438 index = max_slice_number - 1 1438 index = max_slice_number - 1
1439 inverted = self.mip_ctrls.inverted.GetValue() 1439 inverted = self.mip_ctrls.inverted.GetValue()
1440 border_size = self.mip_ctrls.border_spin.GetValue() 1440 border_size = self.mip_ctrls.border_spin.GetValue()
1441 - image = self.slice_.GetSlices(self.orientation, index,  
1442 - self.number_slices, inverted, border_size) 1441 + try:
  1442 + image = self.slice_.GetSlices(self.orientation, index,
  1443 + self.number_slices, inverted,
  1444 + border_size)
  1445 + except IndexError:
  1446 + return
1443 self.slice_data.actor.SetInputData(image) 1447 self.slice_data.actor.SetInputData(image)
1444 for actor in self.actors_by_slice_number[self.slice_data.number]: 1448 for actor in self.actors_by_slice_number[self.slice_data.number]:
1445 self.slice_data.renderer.RemoveActor(actor) 1449 self.slice_data.renderer.RemoveActor(actor)
invesalius/gui/brain_seg_dialog.py
@@ -81,6 +81,8 @@ class BrainSegmenterDialog(wx.Dialog): @@ -81,6 +81,8 @@ class BrainSegmenterDialog(wx.Dialog):
81 self.txt_threshold.SetMinClientSize((w, -1)) 81 self.txt_threshold.SetMinClientSize((w, -1))
82 self.chk_new_mask = wx.CheckBox(self, wx.ID_ANY, _("Create new mask")) 82 self.chk_new_mask = wx.CheckBox(self, wx.ID_ANY, _("Create new mask"))
83 self.chk_new_mask.SetValue(True) 83 self.chk_new_mask.SetValue(True)
  84 + self.chk_apply_wwwl = wx.CheckBox(self, wx.ID_ANY, _("Apply WW&WL"))
  85 + self.chk_apply_wwwl.SetValue(False)
84 self.progress = wx.Gauge(self, -1) 86 self.progress = wx.Gauge(self, -1)
85 self.lbl_progress_caption = wx.StaticText(self, -1, _("Elapsed time:")) 87 self.lbl_progress_caption = wx.StaticText(self, -1, _("Elapsed time:"))
86 self.lbl_time = wx.StaticText(self, -1, _("00:00:00")) 88 self.lbl_time = wx.StaticText(self, -1, _("00:00:00"))
@@ -115,11 +117,12 @@ class BrainSegmenterDialog(wx.Dialog): @@ -115,11 +117,12 @@ class BrainSegmenterDialog(wx.Dialog):
115 sizer_3.Add( 117 sizer_3.Add(
116 self.sld_threshold, 118 self.sld_threshold,
117 1, 119 1,
118 - wx.ALIGN_CENTER | wx.BOTTOM | wx.EXPAND | wx.LEFT | wx.RIGHT, 120 + wx.BOTTOM | wx.EXPAND | wx.LEFT | wx.RIGHT,
119 5, 121 5,
120 ) 122 )
121 sizer_3.Add(self.txt_threshold, 0, wx.ALL, 5) 123 sizer_3.Add(self.txt_threshold, 0, wx.ALL, 5)
122 main_sizer.Add(sizer_3, 0, wx.EXPAND, 0) 124 main_sizer.Add(sizer_3, 0, wx.EXPAND, 0)
  125 + main_sizer.Add(self.chk_apply_wwwl, 0, wx.EXPAND | wx.ALL, 5)
123 main_sizer.Add(self.chk_new_mask, 0, wx.EXPAND | wx.ALL, 5) 126 main_sizer.Add(self.chk_new_mask, 0, wx.EXPAND | wx.ALL, 5)
124 main_sizer.Add(self.progress, 0, wx.EXPAND | wx.ALL, 5) 127 main_sizer.Add(self.progress, 0, wx.EXPAND | wx.ALL, 5)
125 time_sizer = wx.BoxSizer(wx.HORIZONTAL) 128 time_sizer = wx.BoxSizer(wx.HORIZONTAL)
@@ -128,15 +131,15 @@ class BrainSegmenterDialog(wx.Dialog): @@ -128,15 +131,15 @@ class BrainSegmenterDialog(wx.Dialog):
128 main_sizer.Add(time_sizer, 0, wx.EXPAND | wx.ALL, 5) 131 main_sizer.Add(time_sizer, 0, wx.EXPAND | wx.ALL, 5)
129 sizer_buttons = wx.BoxSizer(wx.HORIZONTAL) 132 sizer_buttons = wx.BoxSizer(wx.HORIZONTAL)
130 sizer_buttons.Add( 133 sizer_buttons.Add(
131 - self.btn_close, 0, wx.ALIGN_BOTTOM | wx.ALIGN_RIGHT | wx.ALL, 5 134 + self.btn_close, 0, wx.ALIGN_BOTTOM | wx.ALL, 5
132 ) 135 )
133 sizer_buttons.Add( 136 sizer_buttons.Add(
134 - self.btn_stop, 0, wx.ALIGN_BOTTOM | wx.ALIGN_RIGHT | wx.ALL, 5 137 + self.btn_stop, 0, wx.ALIGN_BOTTOM | wx.ALL, 5
135 ) 138 )
136 sizer_buttons.Add( 139 sizer_buttons.Add(
137 - self.btn_segment, 0, wx.ALIGN_BOTTOM | wx.ALIGN_RIGHT | wx.ALL, 5 140 + self.btn_segment, 0, wx.ALIGN_BOTTOM | wx.ALL, 5
138 ) 141 )
139 - main_sizer.Add(sizer_buttons, 0, wx.ALIGN_BOTTOM | wx.ALIGN_RIGHT | wx.ALL, 0) 142 + main_sizer.Add(sizer_buttons, 0, wx.ALIGN_RIGHT | wx.ALL, 0)
140 self.SetSizer(main_sizer) 143 self.SetSizer(main_sizer)
141 main_sizer.Fit(self) 144 main_sizer.Fit(self)
142 main_sizer.SetSizeHints(self) 145 main_sizer.SetSizeHints(self)
@@ -216,6 +219,7 @@ class BrainSegmenterDialog(wx.Dialog): @@ -216,6 +219,7 @@ class BrainSegmenterDialog(wx.Dialog):
216 device_id = self.plaidml_devices[self.cb_devices.GetValue()] 219 device_id = self.plaidml_devices[self.cb_devices.GetValue()]
217 except (KeyError, AttributeError): 220 except (KeyError, AttributeError):
218 device_id = "llvm_cpu.0" 221 device_id = "llvm_cpu.0"
  222 + apply_wwwl = self.chk_apply_wwwl.GetValue()
219 create_new_mask = self.chk_new_mask.GetValue() 223 create_new_mask = self.chk_new_mask.GetValue()
220 use_gpu = self.chk_use_gpu.GetValue() 224 use_gpu = self.chk_use_gpu.GetValue()
221 prob_threshold = self.sld_threshold.GetValue() / 100.0 225 prob_threshold = self.sld_threshold.GetValue() / 100.0
@@ -224,8 +228,11 @@ class BrainSegmenterDialog(wx.Dialog): @@ -224,8 +228,11 @@ class BrainSegmenterDialog(wx.Dialog):
224 self.btn_segment.Disable() 228 self.btn_segment.Disable()
225 self.chk_new_mask.Disable() 229 self.chk_new_mask.Disable()
226 230
  231 + window_width = slc.Slice().window_width
  232 + window_level = slc.Slice().window_level
  233 +
227 try: 234 try:
228 - self.ps = segment.SegmentProcess(image, create_new_mask, backend, device_id, use_gpu) 235 + self.ps = segment.SegmentProcess(image, create_new_mask, backend, device_id, use_gpu, apply_wwwl, window_width, window_level)
229 self.ps.start() 236 self.ps.start()
230 except (multiprocessing.ProcessError, OSError, ValueError) as err: 237 except (multiprocessing.ProcessError, OSError, ValueError) as err:
231 self.OnStop(None) 238 self.OnStop(None)
invesalius/gui/data_notebook.py
@@ -351,18 +351,89 @@ class ButtonControlPanel(wx.Panel): @@ -351,18 +351,89 @@ class ButtonControlPanel(wx.Panel):
351 else: 351 else:
352 dlg.MaskSelectionRequiredForDuplication() 352 dlg.MaskSelectionRequiredForDuplication()
353 353
354 -class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCtrlMixin):  
355 354
  355 +class InvListCtrl(wx.ListCtrl):
356 def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, 356 def __init__(self, parent, ID=-1, pos=wx.DefaultPosition,
357 - size=wx.DefaultSize, style=wx.LC_REPORT): 357 + size=wx.DefaultSize, style=wx.LC_REPORT | wx.LC_EDIT_LABELS):
  358 + wx.ListCtrl.__init__(self, parent, ID, pos, size, style=style)
  359 + self.__bind_events_wx()
358 360
359 - # native look and feel for MacOS  
360 - #if wx.Platform == "__WXMAC__":  
361 - # wx.SystemOptions.SetOptionInt("mac.listctrl.always_use_generic", 0) 361 + def __bind_events_wx(self):
  362 + self.Bind(wx.EVT_LEFT_DOWN, self.OnClickItem)
  363 + self.Bind(wx.EVT_LEFT_DCLICK, self.OnDblClickItem)
  364 +
  365 + def CreateColourBitmap(self, colour):
  366 + """
  367 + Create a wx Image with a mask colour.
  368 + colour: colour in rgb format(0 - 1)
  369 + """
  370 + image = self.image_gray
  371 + new_image = Image.new("RGB", image.size)
  372 + for x in range(image.size[0]):
  373 + for y in range(image.size[1]):
  374 + pixel_colour = [int(i*image.getpixel((x,y)))
  375 + for i in colour]
  376 + new_image.putpixel((x,y), tuple(pixel_colour))
  377 +
  378 + wx_image = wx.Image(new_image.size[0],
  379 + new_image.size[1])
  380 + try:
  381 + wx_image.SetData(new_image.tostring())
  382 + except Exception:
  383 + wx_image.SetData(new_image.tobytes())
  384 + return wx.Bitmap(wx_image.Scale(16, 16))
  385 +
  386 + def OnClickItem(self, evt):
  387 + self._click_check = False
  388 + item_idx, flag = (self.HitTest(evt.GetPosition()))
  389 + if item_idx > -1:
  390 + column_clicked = self.get_column_clicked(evt.GetPosition())
  391 + if column_clicked == 0:
  392 + self._click_check = True
  393 + item = self.GetItem(item_idx, 0)
  394 + flag = not bool(item.GetImage())
  395 + self.SetItemImage(item_idx, int(flag))
  396 + self.OnCheckItem(item_idx, flag)
  397 + return
  398 + evt.Skip()
362 399
363 - wx.ListCtrl.__init__(self, parent, ID, pos, size, style=wx.LC_REPORT)  
364 - listmix.TextEditMixin.__init__(self)  
365 - listmix.CheckListCtrlMixin.__init__(self) 400 + def OnDblClickItem(self, evt):
  401 + self._click_check = False
  402 + item_idx, flag = (self.HitTest(evt.GetPosition()))
  403 + if item_idx > -1:
  404 + column_clicked = self.get_column_clicked(evt.GetPosition())
  405 + if column_clicked == 1:
  406 + item = self.GetItem(item_idx, 1)
  407 + self.enter_edition(item)
  408 + return
  409 + evt.Skip()
  410 +
  411 + def enter_edition(self, item):
  412 + ctrl = self.EditLabel(item.GetId())
  413 + w, h = ctrl.GetClientSize()
  414 + w = self.GetColumnWidth(1)
  415 + ctrl.SetClientSize(w, h)
  416 + ctrl.SetValue(item.GetText())
  417 + ctrl.SelectAll()
  418 +
  419 +
  420 + def get_column_clicked(self, position):
  421 + epx, epy = position
  422 + wpx, wpy = self.GetPosition()
  423 + width_sum = 0
  424 + for i in range(self.GetColumnCount()):
  425 + width_sum += self.GetColumnWidth(i)
  426 + if (epx - wpx) <= width_sum:
  427 + return i
  428 + return -1
  429 +
  430 +
  431 +
  432 +class MasksListCtrlPanel(InvListCtrl):
  433 + def __init__(self, parent, ID=-1, pos=wx.DefaultPosition,
  434 + size=wx.DefaultSize, style=wx.LC_REPORT | wx.LC_EDIT_LABELS):
  435 + super().__init__(parent, ID, pos, size, style=style)
  436 + self._click_check = False
366 self.mask_list_index = {} 437 self.mask_list_index = {}
367 self.current_index = 0 438 self.current_index = 0
368 self.__init_columns() 439 self.__init_columns()
@@ -371,12 +442,9 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt @@ -371,12 +442,9 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt
371 self.__bind_events() 442 self.__bind_events()
372 443
373 def __bind_events_wx(self): 444 def __bind_events_wx(self):
374 - self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)  
375 - self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginLabelEdit)  
376 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEditLabel) 445 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEditLabel)
377 self.Bind(wx.EVT_KEY_UP, self.OnKeyEvent) 446 self.Bind(wx.EVT_KEY_UP, self.OnKeyEvent)
378 447
379 -  
380 def __bind_events(self): 448 def __bind_events(self):
381 Publisher.subscribe(self.AddMask, 'Add mask') 449 Publisher.subscribe(self.AddMask, 'Add mask')
382 Publisher.subscribe(self.EditMaskThreshold, 450 Publisher.subscribe(self.EditMaskThreshold,
@@ -438,7 +506,6 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt @@ -438,7 +506,6 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt
438 self.current_index -= 1 506 self.current_index -= 1
439 self.SetItemImage(self.current_index, 1) 507 self.SetItemImage(self.current_index, 1)
440 508
441 -  
442 def OnCloseProject(self): 509 def OnCloseProject(self):
443 self.DeleteAllItems() 510 self.DeleteAllItems()
444 self.mask_list_index = {} 511 self.mask_list_index = {}
@@ -475,13 +542,13 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt @@ -475,13 +542,13 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt
475 def __init_image_list(self): 542 def __init_image_list(self):
476 self.imagelist = wx.ImageList(16, 16) 543 self.imagelist = wx.ImageList(16, 16)
477 544
478 - image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_invisible.jpg")) 545 + image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_invisible.png"))
479 bitmap = wx.Bitmap(image.Scale(16, 16)) 546 bitmap = wx.Bitmap(image.Scale(16, 16))
480 bitmap.SetWidth(16) 547 bitmap.SetWidth(16)
481 bitmap.SetHeight(16) 548 bitmap.SetHeight(16)
482 img_null = self.imagelist.Add(bitmap) 549 img_null = self.imagelist.Add(bitmap)
483 550
484 - image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_visible.jpg")) 551 + image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_visible.png"))
485 bitmap = wx.Bitmap(image.Scale(16, 16)) 552 bitmap = wx.Bitmap(image.Scale(16, 16))
486 bitmap.SetWidth(16) 553 bitmap.SetWidth(16)
487 bitmap.SetHeight(16) 554 bitmap.SetHeight(16)
@@ -489,23 +556,16 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt @@ -489,23 +556,16 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt
489 556
490 self.SetImageList(self.imagelist,wx.IMAGE_LIST_SMALL) 557 self.SetImageList(self.imagelist,wx.IMAGE_LIST_SMALL)
491 558
492 - self.image_gray = Image.open(os.path.join(inv_paths.ICON_DIR, "object_colour.jpg"))  
493 -  
494 - def OnBeginLabelEdit(self, evt):  
495 - if evt.GetColumn() == 1:  
496 - evt.Skip()  
497 - else:  
498 - evt.Veto() 559 + self.image_gray = Image.open(os.path.join(inv_paths.ICON_DIR, "object_colour.png"))
499 560
500 def OnEditLabel(self, evt): 561 def OnEditLabel(self, evt):
501 - Publisher.sendMessage('Change mask name',  
502 - index=evt.GetIndex(), name=evt.GetLabel()) 562 + if not evt.IsEditCancelled():
  563 + index = evt.GetIndex()
  564 + self.SetItem(index, 1, evt.GetLabel())
  565 + Publisher.sendMessage('Change mask name',
  566 + index=evt.GetIndex(), name=evt.GetLabel())
503 evt.Skip() 567 evt.Skip()
504 568
505 - def OnItemActivated(self, evt):  
506 - self.ToggleItem(evt.Index)  
507 - # pass  
508 -  
509 def OnCheckItem(self, index, flag): 569 def OnCheckItem(self, index, flag):
510 if flag: 570 if flag:
511 for key in self.mask_list_index.keys(): 571 for key in self.mask_list_index.keys():
@@ -515,26 +575,7 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt @@ -515,26 +575,7 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt
515 self.current_index = index 575 self.current_index = index
516 Publisher.sendMessage('Show mask', index=index, value=flag) 576 Publisher.sendMessage('Show mask', index=index, value=flag)
517 577
518 - def CreateColourBitmap(self, colour):  
519 - """  
520 - Create a wx Image with a mask colour.  
521 - colour: colour in rgb format(0 - 1)  
522 - """  
523 - image = self.image_gray  
524 - new_image = Image.new("RGB", image.size)  
525 - for x in range(image.size[0]):  
526 - for y in range(image.size[1]):  
527 - pixel_colour = [int(i*image.getpixel((x,y)))  
528 - for i in colour]  
529 - new_image.putpixel((x,y), tuple(pixel_colour))  
530 578
531 - wx_image = wx.Image(new_image.size[0],  
532 - new_image.size[1])  
533 - try:  
534 - wx_image.SetData(new_image.tostring())  
535 - except Exception:  
536 - wx_image.SetData(new_image.tobytes())  
537 - return wx.Bitmap(wx_image.Scale(16, 16))  
538 579
539 def InsertNewItem(self, index=0, label=_("Mask"), threshold="(1000, 4500)", 580 def InsertNewItem(self, index=0, label=_("Mask"), threshold="(1000, 4500)",
540 colour=None): 581 colour=None):
@@ -718,19 +759,11 @@ class SurfaceButtonControlPanel(wx.Panel): @@ -718,19 +759,11 @@ class SurfaceButtonControlPanel(wx.Panel):
718 def AffineStatus(self, affine, status): 759 def AffineStatus(self, affine, status):
719 self.affinestatus = status 760 self.affinestatus = status
720 761
721 -class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCtrlMixin):  
722 - 762 +class SurfacesListCtrlPanel(InvListCtrl):
723 def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, 763 def __init__(self, parent, ID=-1, pos=wx.DefaultPosition,
724 - size=wx.DefaultSize, style=wx.LC_REPORT):  
725 -  
726 - # native look and feel for MacOS  
727 - #if wx.Platform == "__WXMAC__":  
728 - # wx.SystemOptions.SetOptionInt("mac.listctrl.always_use_generic", 0)  
729 -  
730 - wx.ListCtrl.__init__(self, parent, ID, pos, size, style=wx.LC_REPORT)  
731 - listmix.TextEditMixin.__init__(self)  
732 - listmix.CheckListCtrlMixin.__init__(self)  
733 - 764 + size=wx.DefaultSize, style=wx.LC_REPORT | wx.LC_EDIT_LABELS):
  765 + super().__init__(parent, ID, pos, size, style=style)
  766 + self._click_check = False
734 self.__init_columns() 767 self.__init_columns()
735 self.__init_image_list() 768 self.__init_image_list()
736 self.__init_evt() 769 self.__init_evt()
@@ -752,8 +785,6 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -752,8 +785,6 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
752 Publisher.subscribe(self.OnShowMultiple, 'Show multiple surfaces') 785 Publisher.subscribe(self.OnShowMultiple, 'Show multiple surfaces')
753 786
754 def __bind_events_wx(self): 787 def __bind_events_wx(self):
755 - self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)  
756 - self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginLabelEdit)  
757 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEditLabel) 788 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEditLabel)
758 #self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected_) 789 #self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected_)
759 self.Bind(wx.EVT_KEY_UP, self.OnKeyEvent) 790 self.Bind(wx.EVT_KEY_UP, self.OnKeyEvent)
@@ -841,13 +872,13 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -841,13 +872,13 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
841 def __init_image_list(self): 872 def __init_image_list(self):
842 self.imagelist = wx.ImageList(16, 16) 873 self.imagelist = wx.ImageList(16, 16)
843 874
844 - image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_invisible.jpg")) 875 + image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_invisible.png"))
845 bitmap = wx.Bitmap(image.Scale(16, 16)) 876 bitmap = wx.Bitmap(image.Scale(16, 16))
846 bitmap.SetWidth(16) 877 bitmap.SetWidth(16)
847 bitmap.SetHeight(16) 878 bitmap.SetHeight(16)
848 img_null = self.imagelist.Add(bitmap) 879 img_null = self.imagelist.Add(bitmap)
849 880
850 - image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_visible.jpg")) 881 + image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_visible.png"))
851 bitmap = wx.Bitmap(image.Scale(16, 16)) 882 bitmap = wx.Bitmap(image.Scale(16, 16))
852 bitmap.SetWidth(16) 883 bitmap.SetWidth(16)
853 bitmap.SetHeight(16) 884 bitmap.SetHeight(16)
@@ -855,7 +886,7 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -855,7 +886,7 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
855 886
856 self.SetImageList(self.imagelist,wx.IMAGE_LIST_SMALL) 887 self.SetImageList(self.imagelist,wx.IMAGE_LIST_SMALL)
857 888
858 - self.image_gray = Image.open(os.path.join(inv_paths.ICON_DIR, "object_colour.jpg")) 889 + self.image_gray = Image.open(os.path.join(inv_paths.ICON_DIR, "object_colour.png"))
859 890
860 def OnBeginLabelEdit(self, evt): 891 def OnBeginLabelEdit(self, evt):
861 if evt.GetColumn() == 1: 892 if evt.GetColumn() == 1:
@@ -864,11 +895,10 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -864,11 +895,10 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
864 evt.Veto() 895 evt.Veto()
865 896
866 def OnEditLabel(self, evt): 897 def OnEditLabel(self, evt):
867 - Publisher.sendMessage('Change surface name', index=evt.GetIndex(), name=evt.GetLabel())  
868 - evt.Skip()  
869 -  
870 - def OnItemActivated(self, evt):  
871 - self.ToggleItem(evt.Index) 898 + if not evt.IsEditCancelled():
  899 + index = evt.GetIndex()
  900 + self.SetItem(index, 1, evt.GetLabel())
  901 + Publisher.sendMessage('Change surface name', index=evt.GetIndex(), name=evt.GetLabel())
872 evt.Skip() 902 evt.Skip()
873 903
874 def OnCheckItem(self, index, flag): 904 def OnCheckItem(self, index, flag):
@@ -944,28 +974,6 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -944,28 +974,6 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
944 self.SetItem(index, 4, transparency) 974 self.SetItem(index, 4, transparency)
945 self.SetItemImage(index, 1) 975 self.SetItemImage(index, 1)
946 976
947 - def CreateColourBitmap(self, colour):  
948 - """  
949 - Create a wx Image with a mask colour.  
950 - colour: colour in rgb format(0 - 1)  
951 - """  
952 - image = self.image_gray  
953 - new_image = Image.new("RGB", image.size)  
954 - for x in range(image.size[0]):  
955 - for y in range(image.size[1]):  
956 - pixel_colour = [int(i*image.getpixel((x,y)))  
957 - for i in colour]  
958 - new_image.putpixel((x,y), tuple(pixel_colour))  
959 -  
960 - wx_image = wx.Image(new_image.size[0],  
961 - new_image.size[1])  
962 - try:  
963 - wx_image.SetData(new_image.tostring())  
964 - except Exception:  
965 - wx_image.SetData(new_image.tobytes())  
966 -  
967 - return wx.Bitmap(wx_image.Scale(16, 16))  
968 -  
969 def EditSurfaceTransparency(self, surface_index, transparency): 977 def EditSurfaceTransparency(self, surface_index, transparency):
970 """ 978 """
971 Set actor transparency (oposite to opacity) according to given actor 979 Set actor transparency (oposite to opacity) according to given actor
@@ -985,19 +993,11 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -985,19 +993,11 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
985 #------------------------------------------------- 993 #-------------------------------------------------
986 #------------------------------------------------- 994 #-------------------------------------------------
987 995
988 -class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCtrlMixin):  
989 - 996 +class MeasuresListCtrlPanel(InvListCtrl):
990 def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, 997 def __init__(self, parent, ID=-1, pos=wx.DefaultPosition,
991 - size=wx.DefaultSize, style=wx.LC_REPORT):  
992 -  
993 - # native look and feel for MacOS  
994 - #if wx.Platform == "__WXMAC__":  
995 - # wx.SystemOptions.SetOptionInt("mac.listctrl.always_use_generic", 0)  
996 -  
997 - wx.ListCtrl.__init__(self, parent, ID, pos, size, style=wx.LC_REPORT)  
998 - listmix.TextEditMixin.__init__(self)  
999 - listmix.CheckListCtrlMixin.__init__(self)  
1000 - 998 + size=wx.DefaultSize, style=wx.LC_REPORT | wx.LC_EDIT_LABELS):
  999 + super().__init__(parent, ID, pos, size, style=style)
  1000 + self._click_check = False
1001 self.__init_columns() 1001 self.__init_columns()
1002 self.__init_image_list() 1002 self.__init_image_list()
1003 self.__init_evt() 1003 self.__init_evt()
@@ -1017,13 +1017,10 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -1017,13 +1017,10 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1017 Publisher.subscribe(self.OnRemoveGUIMeasure, 'Remove GUI measurement') 1017 Publisher.subscribe(self.OnRemoveGUIMeasure, 'Remove GUI measurement')
1018 1018
1019 def __bind_events_wx(self): 1019 def __bind_events_wx(self):
1020 - self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)  
1021 - self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginLabelEdit)  
1022 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEditLabel) 1020 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEditLabel)
1023 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected_) 1021 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected_)
1024 self.Bind(wx.EVT_KEY_UP, self.OnKeyEvent) 1022 self.Bind(wx.EVT_KEY_UP, self.OnKeyEvent)
1025 1023
1026 -  
1027 def OnKeyEvent(self, event): 1024 def OnKeyEvent(self, event):
1028 keycode = event.GetKeyCode() 1025 keycode = event.GetKeyCode()
1029 # Delete key 1026 # Delete key
@@ -1116,13 +1113,13 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -1116,13 +1113,13 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1116 def __init_image_list(self): 1113 def __init_image_list(self):
1117 self.imagelist = wx.ImageList(16, 16) 1114 self.imagelist = wx.ImageList(16, 16)
1118 1115
1119 - image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_invisible.jpg")) 1116 + image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_invisible.png"))
1120 bitmap = wx.Bitmap(image.Scale(16, 16)) 1117 bitmap = wx.Bitmap(image.Scale(16, 16))
1121 bitmap.SetWidth(16) 1118 bitmap.SetWidth(16)
1122 bitmap.SetHeight(16) 1119 bitmap.SetHeight(16)
1123 img_null = self.imagelist.Add(bitmap) 1120 img_null = self.imagelist.Add(bitmap)
1124 1121
1125 - image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_visible.jpg")) 1122 + image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_visible.png"))
1126 bitmap = wx.Bitmap(image.Scale(16, 16)) 1123 bitmap = wx.Bitmap(image.Scale(16, 16))
1127 bitmap.SetWidth(16) 1124 bitmap.SetWidth(16)
1128 bitmap.SetHeight(16) 1125 bitmap.SetHeight(16)
@@ -1130,7 +1127,7 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -1130,7 +1127,7 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1130 1127
1131 self.SetImageList(self.imagelist,wx.IMAGE_LIST_SMALL) 1128 self.SetImageList(self.imagelist,wx.IMAGE_LIST_SMALL)
1132 1129
1133 - self.image_gray = Image.open(os.path.join(inv_paths.ICON_DIR, "object_colour.jpg")) 1130 + self.image_gray = Image.open(os.path.join(inv_paths.ICON_DIR, "object_colour.png"))
1134 1131
1135 def OnBeginLabelEdit(self, evt): 1132 def OnBeginLabelEdit(self, evt):
1136 if evt.GetColumn() == 1: 1133 if evt.GetColumn() == 1:
@@ -1139,14 +1136,12 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -1139,14 +1136,12 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1139 evt.Veto() 1136 evt.Veto()
1140 1137
1141 def OnEditLabel(self, evt): 1138 def OnEditLabel(self, evt):
1142 - Publisher.sendMessage('Change measurement name', index=evt.GetIndex(), name=evt.GetLabel()) 1139 + if not evt.IsEditCancelled():
  1140 + index = evt.GetIndex()
  1141 + self.SetItem(index, 1, evt.GetLabel())
  1142 + Publisher.sendMessage('Change measurement name', index=evt.GetIndex(), name=evt.GetLabel())
1143 evt.Skip() 1143 evt.Skip()
1144 1144
1145 - def OnItemActivated(self, evt):  
1146 - self.ToggleItem(evt.Index)  
1147 - evt.Skip()  
1148 -  
1149 -  
1150 def OnCheckItem(self, index, flag): 1145 def OnCheckItem(self, index, flag):
1151 Publisher.sendMessage('Show measurement', index=index, visibility=flag) 1146 Publisher.sendMessage('Show measurement', index=index, visibility=flag)
1152 1147
@@ -1238,27 +1233,6 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -1238,27 +1233,6 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1238 self.SetItemImage(index, 1) 1233 self.SetItemImage(index, 1)
1239 self.Refresh() 1234 self.Refresh()
1240 1235
1241 - def CreateColourBitmap(self, colour):  
1242 - """  
1243 - Create a wx Image with a mask colour.  
1244 - colour: colour in rgb format(0 - 1)  
1245 - """  
1246 - image = self.image_gray  
1247 - new_image = Image.new("RGB", image.size)  
1248 - for x in range(image.size[0]):  
1249 - for y in range(image.size[1]):  
1250 - pixel_colour = [int(i*image.getpixel((x,y)))  
1251 - for i in colour]  
1252 - new_image.putpixel((x,y), tuple(pixel_colour))  
1253 -  
1254 - wx_image = wx.Image(new_image.size[0],  
1255 - new_image.size[1])  
1256 - try:  
1257 - wx_image.SetData(new_image.tostring())  
1258 - except:  
1259 - wx_image.SetData(new_image.tobytes())  
1260 - return wx.Bitmap(wx_image.Scale(16, 16))  
1261 -  
1262 def EditItemColour(self, measure_index, colour): 1236 def EditItemColour(self, measure_index, colour):
1263 """ 1237 """
1264 """ 1238 """
@@ -1273,19 +1247,12 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis @@ -1273,19 +1247,12 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1273 #******************************************************************* 1247 #*******************************************************************
1274 1248
1275 1249
1276 -class AnnotationsListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCtrlMixin): 1250 +class AnnotationsListCtrlPanel(wx.ListCtrl):
1277 # TODO: Remove edimixin, allow only visible and invisible 1251 # TODO: Remove edimixin, allow only visible and invisible
1278 def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, 1252 def __init__(self, parent, ID=-1, pos=wx.DefaultPosition,
1279 - size=wx.DefaultSize, style=wx.LC_REPORT):  
1280 -  
1281 - # native look and feel for MacOS  
1282 - #if wx.Platform == "__WXMAC__":  
1283 - # wx.SystemOptions.SetOptionInt("mac.listctrl.always_use_generic", 0)  
1284 -  
1285 - wx.ListCtrl.__init__(self, parent, ID, pos, size, style=wx.LC_REPORT)  
1286 - listmix.TextEditMixin.__init__(self)  
1287 - listmix.CheckListCtrlMixin.__init__(self)  
1288 - 1253 + size=wx.DefaultSize, style=wx.LC_REPORT | wx.LC_EDIT_LABELS):
  1254 + wx.ListCtrl.__init__(self, parent, ID, pos, size, style=style)
  1255 + self._click_check = False
1289 self.__init_columns() 1256 self.__init_columns()
1290 self.__init_image_list() 1257 self.__init_image_list()
1291 self.__init_evt() 1258 self.__init_evt()
@@ -1311,19 +1278,19 @@ class AnnotationsListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.Check @@ -1311,19 +1278,19 @@ class AnnotationsListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.Check
1311 def __init_image_list(self): 1278 def __init_image_list(self):
1312 self.imagelist = wx.ImageList(16, 16) 1279 self.imagelist = wx.ImageList(16, 16)
1313 1280
1314 - image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_visible.jpg")) 1281 + image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_visible.png"))
1315 bitmap = wx.Bitmap(image.Scale(16, 16)) 1282 bitmap = wx.Bitmap(image.Scale(16, 16))
1316 bitmap.SetWidth(16) 1283 bitmap.SetWidth(16)
1317 bitmap.SetHeight(16) 1284 bitmap.SetHeight(16)
1318 img_check = self.imagelist.Add(bitmap) 1285 img_check = self.imagelist.Add(bitmap)
1319 1286
1320 - image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_invisible.jpg")) 1287 + image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_invisible.png"))
1321 bitmap = wx.Bitmap(image.Scale(16, 16)) 1288 bitmap = wx.Bitmap(image.Scale(16, 16))
1322 bitmap.SetWidth(16) 1289 bitmap.SetWidth(16)
1323 bitmap.SetHeight(16) 1290 bitmap.SetHeight(16)
1324 img_null = self.imagelist.Add(bitmap) 1291 img_null = self.imagelist.Add(bitmap)
1325 1292
1326 - image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_colour.jpg")) 1293 + image = wx.Image(os.path.join(inv_paths.ICON_DIR, "object_colour.png"))
1327 bitmap = wx.Bitmap(image.Scale(16, 16)) 1294 bitmap = wx.Bitmap(image.Scale(16, 16))
1328 bitmap.SetWidth(16) 1295 bitmap.SetWidth(16)
1329 bitmap.SetHeight(16) 1296 bitmap.SetHeight(16)
invesalius/gui/default_tasks.py
@@ -123,6 +123,7 @@ class Panel(wx.Panel): @@ -123,6 +123,7 @@ class Panel(wx.Panel):
123 123
124 #self.SetSizerAndFit(sizer) 124 #self.SetSizerAndFit(sizer)
125 self.SetSizer(sizer) 125 self.SetSizer(sizer)
  126 + self.Layout()
126 127
127 128
128 # Lower fold panel 129 # Lower fold panel
invesalius/gui/default_viewers.py
@@ -111,7 +111,7 @@ class Panel(wx.Panel): @@ -111,7 +111,7 @@ class Panel(wx.Panel):
111 p3.SetPopupMenu(menu) 111 p3.SetPopupMenu(menu)
112 112
113 113
114 - if sys.platform == 'win32': 114 + if sys.platform == 'win32' or wx.VERSION >= (4, 1):
115 self.aui_manager.AddPane(p1, s1) 115 self.aui_manager.AddPane(p1, s1)
116 self.aui_manager.AddPane(p2, s2) 116 self.aui_manager.AddPane(p2, s2)
117 self.aui_manager.AddPane(p3, s3) 117 self.aui_manager.AddPane(p3, s3)
@@ -604,7 +604,7 @@ class VolumeToolPanel(wx.Panel): @@ -604,7 +604,7 @@ class VolumeToolPanel(wx.Panel):
604 id = evt.GetId() 604 id = evt.GetId()
605 item = ID_TO_ITEMSLICEMENU[id] 605 item = ID_TO_ITEMSLICEMENU[id]
606 checked = item.IsChecked() 606 checked = item.IsChecked()
607 - label = item.GetLabel() 607 + label = item.GetItemLabelText()
608 608
609 if not (checked): 609 if not (checked):
610 Publisher.sendMessage('Disable plane', plane_label=label) 610 Publisher.sendMessage('Disable plane', plane_label=label)
invesalius/gui/dialogs.py
@@ -245,9 +245,7 @@ WILDCARD_OPEN = &quot;InVesalius 3 project (*.inv3)|*.inv3|&quot; \ @@ -245,9 +245,7 @@ WILDCARD_OPEN = &quot;InVesalius 3 project (*.inv3)|*.inv3|&quot; \
245 WILDCARD_ANALYZE = "Analyze 7.5 (*.hdr)|*.hdr|" \ 245 WILDCARD_ANALYZE = "Analyze 7.5 (*.hdr)|*.hdr|" \
246 "All files (*.*)|*.*" 246 "All files (*.*)|*.*"
247 247
248 -WILDCARD_NIFTI = "NIfTI 1 (*.nii)|*.nii|" \  
249 - "Compressed NIfTI (*.nii.gz)|*.nii.gz|" \  
250 - "HDR NIfTI (*.hdr)|*.hdr|" \ 248 +WILDCARD_NIFTI = "NIfTI 1 (*.nii;*.nii.gz;*.hdr)|*.nii;*.nii.gz;*.hdr|" \
251 "All files (*.*)|*.*" 249 "All files (*.*)|*.*"
252 #".[jJ][pP][gG]" 250 #".[jJ][pP][gG]"
253 WILDCARD_PARREC = "PAR/REC (*.par)|*.par|" \ 251 WILDCARD_PARREC = "PAR/REC (*.par)|*.par|" \
@@ -1950,17 +1948,17 @@ class WatershedOptionsPanel(wx.Panel): @@ -1950,17 +1948,17 @@ class WatershedOptionsPanel(wx.Panel):
1950 min_value=1, max_value=10) 1948 min_value=1, max_value=10)
1951 1949
1952 box_sizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Conectivity"), wx.VERTICAL) 1950 box_sizer = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Conectivity"), wx.VERTICAL)
1953 - box_sizer.Add(self.choice_2dcon, 0, wx.ALIGN_CENTER_VERTICAL,2)  
1954 - box_sizer.Add(self.choice_3dcon, 0, wx.ALIGN_CENTER_VERTICAL,2) 1951 + box_sizer.Add(self.choice_2dcon, 0, wx.ALL, 5)
  1952 + box_sizer.Add(self.choice_3dcon, 0, wx.ALL, 5)
1955 1953
1956 g_sizer = wx.BoxSizer(wx.HORIZONTAL) 1954 g_sizer = wx.BoxSizer(wx.HORIZONTAL)
1957 - g_sizer.Add(wx.StaticText(self, -1, _("Gaussian sigma")), 0, wx.ALIGN_RIGHT | wx.ALL, 5)  
1958 - g_sizer.Add(self.gaussian_size, 0, wx.ALIGN_LEFT | wx.ALL, 5) 1955 + g_sizer.Add(wx.StaticText(self, -1, _("Gaussian sigma")), 0, wx.ALIGN_CENTER | wx.ALL, 5)
  1956 + g_sizer.Add(self.gaussian_size, 0, wx.ALL, 5)
1959 1957
1960 sizer = wx.BoxSizer(wx.VERTICAL) 1958 sizer = wx.BoxSizer(wx.VERTICAL)
1961 - sizer.Add(self.choice_algorithm, 0, wx.ALIGN_CENTER_VERTICAL,2)  
1962 - sizer.Add(box_sizer, 1, wx.EXPAND,2)  
1963 - sizer.Add(g_sizer, 0, wx.ALIGN_LEFT, 2) 1959 + sizer.Add(self.choice_algorithm, 0, wx.ALL, 5)
  1960 + sizer.Add(box_sizer, 1, wx.EXPAND | wx.ALL, 5)
  1961 + sizer.Add(g_sizer, 0, wx.ALL, 5)
1964 1962
1965 self.SetSizer(sizer) 1963 self.SetSizer(sizer)
1966 sizer.Fit(self) 1964 sizer.Fit(self)
@@ -1998,8 +1996,7 @@ class WatershedOptionsDialog(wx.Dialog): @@ -1998,8 +1996,7 @@ class WatershedOptionsDialog(wx.Dialog):
1998 btnsizer.Realize() 1996 btnsizer.Realize()
1999 1997
2000 sizer.Add(wop, 0, wx.EXPAND) 1998 sizer.Add(wop, 0, wx.EXPAND)
2001 - sizer.Add(btnsizer, 0, wx.EXPAND)  
2002 - sizer.AddSpacer(5) 1999 + sizer.Add(btnsizer, 0, wx.ALIGN_RIGHT | wx.BOTTOM, 5)
2003 2000
2004 self.SetSizer(sizer) 2001 self.SetSizer(sizer)
2005 sizer.Fit(self) 2002 sizer.Fit(self)
@@ -2060,16 +2057,16 @@ class MaskBooleanDialog(wx.Dialog): @@ -2060,16 +2057,16 @@ class MaskBooleanDialog(wx.Dialog):
2060 2057
2061 gsizer = wx.FlexGridSizer(rows=3, cols=2, hgap=5, vgap=5) 2058 gsizer = wx.FlexGridSizer(rows=3, cols=2, hgap=5, vgap=5)
2062 2059
2063 - gsizer.Add(wx.StaticText(self, -1, _(u"Mask 1"))) 2060 + gsizer.Add(wx.StaticText(self, -1, _(u"Mask 1")), 0, wx.ALIGN_CENTER_VERTICAL)
2064 gsizer.Add(self.mask1, 1, wx.EXPAND) 2061 gsizer.Add(self.mask1, 1, wx.EXPAND)
2065 - gsizer.Add(wx.StaticText(self, -1, _(u"Operation"))) 2062 + gsizer.Add(wx.StaticText(self, -1, _(u"Operation")), 0, wx.ALIGN_CENTER_VERTICAL)
2066 gsizer.Add(self.op_boolean, 1, wx.EXPAND) 2063 gsizer.Add(self.op_boolean, 1, wx.EXPAND)
2067 - gsizer.Add(wx.StaticText(self, -1, _(u"Mask 2"))) 2064 + gsizer.Add(wx.StaticText(self, -1, _(u"Mask 2")), 0, wx.ALIGN_CENTER_VERTICAL)
2068 gsizer.Add(self.mask2, 1, wx.EXPAND) 2065 gsizer.Add(self.mask2, 1, wx.EXPAND)
2069 2066
2070 sizer = wx.BoxSizer(wx.VERTICAL) 2067 sizer = wx.BoxSizer(wx.VERTICAL)
2071 - sizer.Add(gsizer, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5)  
2072 - sizer.Add(btnsizer, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5) 2068 + sizer.Add(gsizer, 0, wx.EXPAND | wx.ALL, border=5)
  2069 + sizer.Add(btnsizer, 0, wx.EXPAND | wx.ALL, border=5)
2073 2070
2074 self.SetSizer(sizer) 2071 self.SetSizer(sizer)
2075 sizer.Fit(self) 2072 sizer.Fit(self)
@@ -2798,8 +2795,8 @@ class SelectPartsOptionsDialog(wx.Dialog): @@ -2798,8 +2795,8 @@ class SelectPartsOptionsDialog(wx.Dialog):
2798 sizer.AddSpacer(5) 2795 sizer.AddSpacer(5)
2799 2796
2800 btn_sizer = wx.BoxSizer(wx.HORIZONTAL) 2797 btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
2801 - btn_sizer.Add(self.btn_ok, 0, flag=wx.ALIGN_RIGHT, border=5)  
2802 - btn_sizer.Add(self.btn_cancel, 0, flag=wx.LEFT|wx.ALIGN_RIGHT, border=5) 2798 + btn_sizer.Add(self.btn_ok, 0)# flag=wx.ALIGN_RIGHT, border=5)
  2799 + btn_sizer.Add(self.btn_cancel, 0, flag=wx.LEFT, border=5)
2803 2800
2804 sizer.Add(btn_sizer, 0, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT, border=5) 2801 sizer.Add(btn_sizer, 0, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT, border=5)
2805 sizer.AddSpacer(5) 2802 sizer.AddSpacer(5)
@@ -3202,8 +3199,8 @@ class FillHolesAutoDialog(wx.Dialog): @@ -3202,8 +3199,8 @@ class FillHolesAutoDialog(wx.Dialog):
3202 sizer.AddSpacer(5) 3199 sizer.AddSpacer(5)
3203 3200
3204 btn_sizer = wx.BoxSizer(wx.HORIZONTAL) 3201 btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
3205 - btn_sizer.Add(self.apply_btn, 0, flag=wx.ALIGN_RIGHT, border=5)  
3206 - btn_sizer.Add(self.close_btn, 0, flag=wx.LEFT|wx.ALIGN_RIGHT, border=5) 3202 + btn_sizer.Add(self.apply_btn, 0)# flag=wx.ALIGN_RIGHT, border=5)
  3203 + btn_sizer.Add(self.close_btn, 0, flag=wx.LEFT, border=5)
3207 3204
3208 sizer.Add(btn_sizer, 0, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT, border=5) 3205 sizer.Add(btn_sizer, 0, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT, border=5)
3209 3206
invesalius/gui/dicom_preview_panel.py
@@ -789,8 +789,8 @@ class SingleImagePreview(wx.Panel): @@ -789,8 +789,8 @@ class SingleImagePreview(wx.Panel):
789 in_sizer.Add(checkbox, 0) 789 in_sizer.Add(checkbox, 0)
790 790
791 sizer = wx.BoxSizer(wx.VERTICAL) 791 sizer = wx.BoxSizer(wx.VERTICAL)
792 - sizer.Add(self.panel, 20, wx.GROW|wx.EXPAND)  
793 - sizer.Add(in_sizer, 1, wx.GROW|wx.EXPAND) 792 + sizer.Add(self.panel, 1, wx.GROW|wx.EXPAND)
  793 + sizer.Add(in_sizer, 0, wx.GROW|wx.EXPAND)
794 sizer.Fit(self) 794 sizer.Fit(self)
795 795
796 self.SetSizer(sizer) 796 self.SetSizer(sizer)
invesalius/gui/frame.py
@@ -214,7 +214,7 @@ class Frame(wx.Frame): @@ -214,7 +214,7 @@ class Frame(wx.Frame):
214 # Add toolbars to manager 214 # Add toolbars to manager
215 # This is pretty tricky -- order on win32 is inverted when 215 # This is pretty tricky -- order on win32 is inverted when
216 # compared to linux2 & darwin 216 # compared to linux2 & darwin
217 - if sys.platform == 'win32': 217 + if sys.platform == 'win32' or wx.VERSION >= (4, 1):
218 t1 = ProjectToolBar(self) 218 t1 = ProjectToolBar(self)
219 t2 = HistoryToolBar(self) 219 t2 = HistoryToolBar(self)
220 t3 = LayoutToolBar(self) 220 t3 = LayoutToolBar(self)
@@ -259,6 +259,8 @@ class Frame(wx.Frame): @@ -259,6 +259,8 @@ class Frame(wx.Frame):
259 # TODO: Allow saving and restoring perspectives 259 # TODO: Allow saving and restoring perspectives
260 self.perspective_all = aui_manager.SavePerspective() 260 self.perspective_all = aui_manager.SavePerspective()
261 261
  262 + self.Layout()
  263 +
262 def _BeginBusyCursor(self): 264 def _BeginBusyCursor(self):
263 """ 265 """
264 Start busy cursor. 266 Start busy cursor.
@@ -1941,11 +1943,11 @@ class LayoutToolBar(AuiToolBar): @@ -1941,11 +1943,11 @@ class LayoutToolBar(AuiToolBar):
1941 d = inv_paths.ICON_DIR 1943 d = inv_paths.ICON_DIR
1942 if sys.platform == 'darwin': 1944 if sys.platform == 'darwin':
1943 # Bitmaps for show/hide task panel item 1945 # Bitmaps for show/hide task panel item
1944 - p = os.path.join(d, "layout_data_only_original.gif")  
1945 - self.BMP_WITH_MENU = wx.Bitmap(str(p), wx.BITMAP_TYPE_GIF) 1946 + p = os.path.join(d, "layout_data_only_original.png")
  1947 + self.BMP_WITH_MENU = wx.Bitmap(str(p), wx.BITMAP_TYPE_PNG)
1946 1948
1947 - p = os.path.join(d, "layout_full_original.gif")  
1948 - self.BMP_WITHOUT_MENU = wx.Bitmap(str(p), wx.BITMAP_TYPE_GIF) 1949 + p = os.path.join(d, "layout_full_original.png")
  1950 + self.BMP_WITHOUT_MENU = wx.Bitmap(str(p), wx.BITMAP_TYPE_PNG)
1949 1951
1950 # Bitmaps for show/hide task item 1952 # Bitmaps for show/hide task item
1951 p = os.path.join(d, "text_inverted_original.png") 1953 p = os.path.join(d, "text_inverted_original.png")
@@ -1956,11 +1958,11 @@ class LayoutToolBar(AuiToolBar): @@ -1956,11 +1958,11 @@ class LayoutToolBar(AuiToolBar):
1956 1958
1957 else: 1959 else:
1958 # Bitmaps for show/hide task panel item 1960 # Bitmaps for show/hide task panel item
1959 - p = os.path.join(d, "layout_data_only.gif")  
1960 - self.BMP_WITH_MENU = wx.Bitmap(str(p), wx.BITMAP_TYPE_GIF) 1961 + p = os.path.join(d, "layout_data_only.png")
  1962 + self.BMP_WITH_MENU = wx.Bitmap(str(p), wx.BITMAP_TYPE_PNG)
1961 1963
1962 - p = os.path.join(d, "layout_full.gif")  
1963 - self.BMP_WITHOUT_MENU = wx.Bitmap(str(p), wx.BITMAP_TYPE_GIF) 1964 + p = os.path.join(d, "layout_full.png")
  1965 + self.BMP_WITHOUT_MENU = wx.Bitmap(str(p), wx.BITMAP_TYPE_PNG)
1964 1966
1965 # Bitmaps for show/hide task item 1967 # Bitmaps for show/hide task item
1966 p = os.path.join(d, "text_inverted.png") 1968 p = os.path.join(d, "text_inverted.png")
invesalius/gui/import_panel.py
@@ -104,7 +104,7 @@ class InnerPanel(wx.Panel): @@ -104,7 +104,7 @@ class InnerPanel(wx.Panel):
104 104
105 inner_sizer = wx.BoxSizer(wx.HORIZONTAL) 105 inner_sizer = wx.BoxSizer(wx.HORIZONTAL)
106 inner_sizer.Add(btnsizer, 0, wx.LEFT|wx.TOP, 5) 106 inner_sizer.Add(btnsizer, 0, wx.LEFT|wx.TOP, 5)
107 - inner_sizer.Add(self.combo_interval, 0, wx.LEFT|wx.RIGHT|wx.TOP, 5) 107 + inner_sizer.Add(self.combo_interval, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT|wx.TOP, 5)
108 panel.SetSizer(inner_sizer) 108 panel.SetSizer(inner_sizer)
109 inner_sizer.Fit(panel) 109 inner_sizer.Fit(panel)
110 110
invesalius/gui/language_dialog.py
@@ -71,8 +71,8 @@ class ComboBoxLanguage: @@ -71,8 +71,8 @@ class ComboBoxLanguage:
71 self.bitmapCmb = bitmapCmb = BitmapComboBox(parent, style=wx.CB_READONLY) 71 self.bitmapCmb = bitmapCmb = BitmapComboBox(parent, style=wx.CB_READONLY)
72 for key in self.locales_key: 72 for key in self.locales_key:
73 # Based on composed flag filename, get bitmap 73 # Based on composed flag filename, get bitmap
74 - filepath = os.path.join(ICON_DIR, "%s.bmp"%(key))  
75 - bmp = wx.Bitmap(filepath, wx.BITMAP_TYPE_BMP) 74 + filepath = os.path.join(ICON_DIR, "%s.png" % (key))
  75 + bmp = wx.Bitmap(filepath, wx.BITMAP_TYPE_PNG)
76 # Add bitmap and info to Combo 76 # Add bitmap and info to Combo
77 bitmapCmb.Append(dict_locales[key], bmp, key) 77 bitmapCmb.Append(dict_locales[key], bmp, key)
78 # Set default combo item if available on the list 78 # Set default combo item if available on the list
@@ -123,8 +123,8 @@ class LanguageDialog(wx.Dialog): @@ -123,8 +123,8 @@ class LanguageDialog(wx.Dialog):
123 # self.bitmapCmb = bitmapCmb = BitmapComboBox(self, style=wx.CB_READONLY) 123 # self.bitmapCmb = bitmapCmb = BitmapComboBox(self, style=wx.CB_READONLY)
124 # for key in self.locales_key: 124 # for key in self.locales_key:
125 # # Based on composed flag filename, get bitmap 125 # # Based on composed flag filename, get bitmap
126 - # filepath = os.path.join(ICON_DIR, "%s.bmp"%(key))  
127 - # bmp = wx.Bitmap(filepath, wx.BITMAP_TYPE_BMP) 126 + # filepath = os.path.join(ICON_DIR, "%s.png"%(key))
  127 + # bmp = wx.Bitmap(filepath, wx.BITMAP_TYPE_PNG)
128 # # Add bitmap and info to Combo 128 # # Add bitmap and info to Combo
129 # bitmapCmb.Append(dict_locales[key], bmp, key) 129 # bitmapCmb.Append(dict_locales[key], bmp, key)
130 # # Set default combo item if available on the list 130 # # Set default combo item if available on the list
invesalius/gui/preferences.py
@@ -49,13 +49,13 @@ class Preferences(wx.Dialog): @@ -49,13 +49,13 @@ class Preferences(wx.Dialog):
49 self.book.AddPage(self.pnl_language, _("Language")) 49 self.book.AddPage(self.pnl_language, _("Language"))
50 50
51 line = wx.StaticLine(self, -1, size=(20, -1), style=wx.LI_HORIZONTAL) 51 line = wx.StaticLine(self, -1, size=(20, -1), style=wx.LI_HORIZONTAL)
52 - sizer.Add(line, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.TOP, 5) 52 + sizer.Add(line, 0, wx.GROW | wx.RIGHT | wx.TOP, 5)
53 53
54 btnsizer = self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL) 54 btnsizer = self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL)
55 sizer.Add( 55 sizer.Add(
56 btnsizer, 56 btnsizer,
57 0, 57 0,
58 - wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.TOP | wx.BOTTOM, 58 + wx.GROW | wx.RIGHT | wx.TOP | wx.BOTTOM,
59 5, 59 5,
60 ) 60 )
61 61
invesalius/gui/task_navigator.py
@@ -211,7 +211,7 @@ class InnerFoldPanel(wx.Panel): @@ -211,7 +211,7 @@ class InnerFoldPanel(wx.Panel):
211 line_sizer = wx.BoxSizer(wx.HORIZONTAL) 211 line_sizer = wx.BoxSizer(wx.HORIZONTAL)
212 line_sizer.Add(checkcamera, 0, wx.ALIGN_LEFT | wx.RIGHT | wx.LEFT, 5) 212 line_sizer.Add(checkcamera, 0, wx.ALIGN_LEFT | wx.RIGHT | wx.LEFT, 5)
213 line_sizer.Add(checktrigger, 0, wx.ALIGN_CENTER) 213 line_sizer.Add(checktrigger, 0, wx.ALIGN_CENTER)
214 - line_sizer.Add(checkobj, 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.LEFT, 5) 214 + line_sizer.Add(checkobj, 0, wx.RIGHT | wx.LEFT, 5)
215 line_sizer.Fit(self) 215 line_sizer.Fit(self)
216 216
217 # Panel sizer to expand fold panel 217 # Panel sizer to expand fold panel
@@ -410,7 +410,7 @@ class NeuronavigationPanel(wx.Panel): @@ -410,7 +410,7 @@ class NeuronavigationPanel(wx.Panel):
410 (nav_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL)]) 410 (nav_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL)])
411 411
412 main_sizer = wx.BoxSizer(wx.HORIZONTAL) 412 main_sizer = wx.BoxSizer(wx.HORIZONTAL)
413 - main_sizer.Add(group_sizer, 1, wx.ALIGN_CENTER_HORIZONTAL, 10) 413 + main_sizer.Add(group_sizer, 1)# wx.ALIGN_CENTER_HORIZONTAL, 10)
414 self.sizer = main_sizer 414 self.sizer = main_sizer
415 self.SetSizer(main_sizer) 415 self.SetSizer(main_sizer)
416 self.Fit() 416 self.Fit()
@@ -852,7 +852,7 @@ class ObjectRegistrationPanel(wx.Panel): @@ -852,7 +852,7 @@ class ObjectRegistrationPanel(wx.Panel):
852 852
853 line_checks = wx.BoxSizer(wx.HORIZONTAL) 853 line_checks = wx.BoxSizer(wx.HORIZONTAL)
854 line_checks.Add(checkrecordcoords, 0, wx.ALIGN_LEFT | wx.RIGHT | wx.LEFT, 5) 854 line_checks.Add(checkrecordcoords, 0, wx.ALIGN_LEFT | wx.RIGHT | wx.LEFT, 5)
855 - line_checks.Add(checktrack, 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.LEFT, 5) 855 + line_checks.Add(checktrack, 0, wx.RIGHT | wx.LEFT, 5)
856 856
857 # Add line sizers into main sizer 857 # Add line sizers into main sizer
858 main_sizer = wx.BoxSizer(wx.VERTICAL) 858 main_sizer = wx.BoxSizer(wx.VERTICAL)
@@ -1082,7 +1082,7 @@ class MarkersPanel(wx.Panel): @@ -1082,7 +1082,7 @@ class MarkersPanel(wx.Panel):
1082 group_sizer.Add(sizer_create, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_HORIZONTAL, 5) 1082 group_sizer.Add(sizer_create, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_HORIZONTAL, 5)
1083 group_sizer.Add(sizer_btns, 0, wx.BOTTOM | wx.ALIGN_CENTER_HORIZONTAL, 5) 1083 group_sizer.Add(sizer_btns, 0, wx.BOTTOM | wx.ALIGN_CENTER_HORIZONTAL, 5)
1084 group_sizer.Add(sizer_delete, 0, wx.BOTTOM | wx.ALIGN_CENTER_HORIZONTAL, 5) 1084 group_sizer.Add(sizer_delete, 0, wx.BOTTOM | wx.ALIGN_CENTER_HORIZONTAL, 5)
1085 - group_sizer.Add(self.lc, 0, wx.EXPAND | wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5) 1085 + group_sizer.Add(self.lc, 0, wx.EXPAND | wx.ALL, 5)
1086 group_sizer.Fit(self) 1086 group_sizer.Fit(self)
1087 1087
1088 self.SetSizer(group_sizer) 1088 self.SetSizer(group_sizer)
invesalius/gui/task_slice.py
@@ -141,7 +141,7 @@ class InnerTaskPanel(wx.Panel): @@ -141,7 +141,7 @@ class InnerTaskPanel(wx.Panel):
141 141
142 line_sizer = wx.BoxSizer(wx.HORIZONTAL) 142 line_sizer = wx.BoxSizer(wx.HORIZONTAL)
143 line_sizer.Add(check_box, 0, wx.ALIGN_LEFT|wx.RIGHT|wx.LEFT, 5) 143 line_sizer.Add(check_box, 0, wx.ALIGN_LEFT|wx.RIGHT|wx.LEFT, 5)
144 - line_sizer.Add(next_btn_sizer, 1, wx.EXPAND|wx.ALIGN_RIGHT|wx.RIGHT|wx.LEFT, 5) 144 + line_sizer.Add(next_btn_sizer, 1, wx.EXPAND|wx.RIGHT|wx.LEFT, 5)
145 line_sizer.Fit(self) 145 line_sizer.Fit(self)
146 146
147 # Add line sizers into main sizer 147 # Add line sizers into main sizer
@@ -423,6 +423,7 @@ class InnerFoldPanel(wx.Panel): @@ -423,6 +423,7 @@ class InnerFoldPanel(wx.Panel):
423 try: 423 try:
424 _id = panel_seg_id[panel_id] 424 _id = panel_seg_id[panel_id]
425 self.fold_panel.Expand(self.fold_panel.GetFoldPanel(_id)) 425 self.fold_panel.Expand(self.fold_panel.GetFoldPanel(_id))
  426 + self.Layout()
426 except KeyError: 427 except KeyError:
427 pass 428 pass
428 429
@@ -688,11 +689,11 @@ class EditionTools(wx.Panel): @@ -688,11 +689,11 @@ class EditionTools(wx.Panel):
688 ## LINE 2 689 ## LINE 2
689 menu = wx.Menu() 690 menu = wx.Menu()
690 691
691 - CIRCLE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_circle.jpg"), wx.BITMAP_TYPE_JPEG) 692 + CIRCLE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_circle.png"), wx.BITMAP_TYPE_PNG)
692 item = wx.MenuItem(menu, MENU_BRUSH_CIRCLE, _("Circle")) 693 item = wx.MenuItem(menu, MENU_BRUSH_CIRCLE, _("Circle"))
693 item.SetBitmap(CIRCLE_BMP) 694 item.SetBitmap(CIRCLE_BMP)
694 695
695 - SQUARE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_square.jpg"), wx.BITMAP_TYPE_JPEG) 696 + SQUARE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_square.png"), wx.BITMAP_TYPE_PNG)
696 item2 = wx.MenuItem(menu, MENU_BRUSH_SQUARE, _("Square")) 697 item2 = wx.MenuItem(menu, MENU_BRUSH_SQUARE, _("Square"))
697 item2.SetBitmap(SQUARE_BMP) 698 item2.SetBitmap(SQUARE_BMP)
698 699
@@ -803,8 +804,8 @@ class EditionTools(wx.Panel): @@ -803,8 +804,8 @@ class EditionTools(wx.Panel):
803 threshold_range=(thresh_min, thresh_max)) 804 threshold_range=(thresh_min, thresh_max))
804 805
805 def OnMenu(self, evt): 806 def OnMenu(self, evt):
806 - SQUARE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_square.jpg"), wx.BITMAP_TYPE_JPEG)  
807 - CIRCLE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_circle.jpg"), wx.BITMAP_TYPE_JPEG) 807 + SQUARE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_square.png"), wx.BITMAP_TYPE_PNG)
  808 + CIRCLE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_circle.png"), wx.BITMAP_TYPE_PNG)
808 809
809 brush = {MENU_BRUSH_CIRCLE: const.BRUSH_CIRCLE, 810 brush = {MENU_BRUSH_CIRCLE: const.BRUSH_CIRCLE,
810 MENU_BRUSH_SQUARE: const.BRUSH_SQUARE} 811 MENU_BRUSH_SQUARE: const.BRUSH_SQUARE}
@@ -852,11 +853,11 @@ class WatershedTool(EditionTools): @@ -852,11 +853,11 @@ class WatershedTool(EditionTools):
852 ## LINE 2 853 ## LINE 2
853 menu = wx.Menu() 854 menu = wx.Menu()
854 855
855 - CIRCLE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_circle.jpg"), wx.BITMAP_TYPE_JPEG) 856 + CIRCLE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_circle.png"), wx.BITMAP_TYPE_PNG)
856 item = wx.MenuItem(menu, MENU_BRUSH_CIRCLE, _("Circle")) 857 item = wx.MenuItem(menu, MENU_BRUSH_CIRCLE, _("Circle"))
857 item.SetBitmap(CIRCLE_BMP) 858 item.SetBitmap(CIRCLE_BMP)
858 859
859 - SQUARE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_square.jpg"), wx.BITMAP_TYPE_JPEG) 860 + SQUARE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_square.png"), wx.BITMAP_TYPE_PNG)
860 item2 = wx.MenuItem(menu, MENU_BRUSH_SQUARE, _("Square")) 861 item2 = wx.MenuItem(menu, MENU_BRUSH_SQUARE, _("Square"))
861 item2.SetBitmap(SQUARE_BMP) 862 item2.SetBitmap(SQUARE_BMP)
862 863
@@ -973,8 +974,8 @@ class WatershedTool(EditionTools): @@ -973,8 +974,8 @@ class WatershedTool(EditionTools):
973 self.gradient_thresh.SetMaxValue(thresh_max) 974 self.gradient_thresh.SetMaxValue(thresh_max)
974 975
975 def OnMenu(self, evt): 976 def OnMenu(self, evt):
976 - SQUARE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_square.jpg"), wx.BITMAP_TYPE_JPEG)  
977 - CIRCLE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_circle.jpg"), wx.BITMAP_TYPE_JPEG) 977 + SQUARE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_square.png"), wx.BITMAP_TYPE_PNG)
  978 + CIRCLE_BMP = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "brush_circle.png"), wx.BITMAP_TYPE_PNG)
978 979
979 brush = {MENU_BRUSH_CIRCLE: const.BRUSH_CIRCLE, 980 brush = {MENU_BRUSH_CIRCLE: const.BRUSH_CIRCLE,
980 MENU_BRUSH_SQUARE: const.BRUSH_SQUARE} 981 MENU_BRUSH_SQUARE: const.BRUSH_SQUARE}
invesalius/gui/task_surface.py
@@ -30,6 +30,7 @@ except ImportError: @@ -30,6 +30,7 @@ except ImportError:
30 30
31 from pubsub import pub as Publisher 31 from pubsub import pub as Publisher
32 import wx.lib.colourselect as csel 32 import wx.lib.colourselect as csel
  33 +import wx.lib.scrolledpanel as scrolled
33 34
34 import invesalius.constants as const 35 import invesalius.constants as const
35 import invesalius.data.slice_ as slice_ 36 import invesalius.data.slice_ as slice_
@@ -74,9 +75,9 @@ class TaskPanel(wx.Panel): @@ -74,9 +75,9 @@ class TaskPanel(wx.Panel):
74 # Contour - slider 75 # Contour - slider
75 # enable / disable Fill holes 76 # enable / disable Fill holes
76 77
77 -class InnerTaskPanel(wx.Panel): 78 +class InnerTaskPanel(scrolled.ScrolledPanel):
78 def __init__(self, parent): 79 def __init__(self, parent):
79 - wx.Panel.__init__(self, parent) 80 + scrolled.ScrolledPanel.__init__(self, parent)
80 default_colour = self.GetBackgroundColour() 81 default_colour = self.GetBackgroundColour()
81 backgroud_colour = wx.Colour(255,255,255) 82 backgroud_colour = wx.Colour(255,255,255)
82 self.SetBackgroundColour(backgroud_colour) 83 self.SetBackgroundColour(backgroud_colour)
@@ -134,6 +135,13 @@ class InnerTaskPanel(wx.Panel): @@ -134,6 +135,13 @@ class InnerTaskPanel(wx.Panel):
134 135
135 self.sizer = main_sizer 136 self.sizer = main_sizer
136 137
  138 + self.SetupScrolling()
  139 +
  140 + self.Bind(wx.EVT_SIZE, self.OnSize)
  141 +
  142 + def OnSize(self, evt):
  143 + self.SetupScrolling()
  144 +
137 def OnButton(self, evt): 145 def OnButton(self, evt):
138 id = evt.GetId() 146 id = evt.GetId()
139 if id == BTN_NEW: 147 if id == BTN_NEW:
@@ -437,9 +445,9 @@ class SurfaceTools(wx.Panel): @@ -437,9 +445,9 @@ class SurfaceTools(wx.Panel):
437 445
438 446
439 447
440 -class SurfaceProperties(wx.Panel): 448 +class SurfaceProperties(scrolled.ScrolledPanel):
441 def __init__(self, parent): 449 def __init__(self, parent):
442 - wx.Panel.__init__(self, parent) 450 + scrolled.ScrolledPanel.__init__(self, parent)
443 try: 451 try:
444 default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR) 452 default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR)
445 except AttributeError: 453 except AttributeError:
@@ -507,8 +515,16 @@ class SurfaceProperties(wx.Panel): @@ -507,8 +515,16 @@ class SurfaceProperties(wx.Panel):
507 self.Update() 515 self.Update()
508 #self.SetAutoLayout(1) 516 #self.SetAutoLayout(1)
509 517
  518 + self.SetupScrolling()
  519 +
  520 + self.Bind(wx.EVT_SIZE, self.OnResize)
  521 +
510 self.__bind_events() 522 self.__bind_events()
511 523
  524 + def OnResize(self, evt):
  525 + print("Resize")
  526 + self.SetupScrolling()
  527 +
512 def __bind_events(self): 528 def __bind_events(self):
513 Publisher.subscribe(self.InsertNewSurface, 529 Publisher.subscribe(self.InsertNewSurface,
514 'Update surface info in GUI') 530 'Update surface info in GUI')
invesalius/gui/task_tools.py
@@ -79,7 +79,7 @@ class InnerTaskPanel(wx.Panel): @@ -79,7 +79,7 @@ class InnerTaskPanel(wx.Panel):
79 79
80 # Image(s) for buttons 80 # Image(s) for buttons
81 BMP_ANNOTATE = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "annotation.png"), wx.BITMAP_TYPE_PNG) 81 BMP_ANNOTATE = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "annotation.png"), wx.BITMAP_TYPE_PNG)
82 - BMP_ANGLE = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "measure_angle.jpg"), wx.BITMAP_TYPE_JPEG) 82 + BMP_ANGLE = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "measure_angle.png"), wx.BITMAP_TYPE_PNG)
83 BMP_DISTANCE = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "measure_line.png"), wx.BITMAP_TYPE_PNG) 83 BMP_DISTANCE = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "measure_line.png"), wx.BITMAP_TYPE_PNG)
84 BMP_ANNOTATE.SetWidth(25) 84 BMP_ANNOTATE.SetWidth(25)
85 BMP_ANNOTATE.SetHeight(25) 85 BMP_ANNOTATE.SetHeight(25)
invesalius/gui/widgets/gradient.py
@@ -26,7 +26,15 @@ from wx.lib import intctrl @@ -26,7 +26,15 @@ from wx.lib import intctrl
26 26
27 from invesalius.gui.widgets.inv_spinctrl import InvSpinCtrl 27 from invesalius.gui.widgets.inv_spinctrl import InvSpinCtrl
28 28
29 -PUSH_WIDTH = 7 29 +try:
  30 + dc = wx.MemoryDC()
  31 + font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
  32 + dc.SetFont(font)
  33 + PUSH_WIDTH = dc.GetTextExtent("M")[0] // 2 + 1
  34 + del dc
  35 + del font
  36 +except Exception:
  37 + PUSH_WIDTH = 7
30 38
31 myEVT_SLIDER_CHANGED = wx.NewEventType() 39 myEVT_SLIDER_CHANGED = wx.NewEventType()
32 EVT_SLIDER_CHANGED = wx.PyEventBinder(myEVT_SLIDER_CHANGED, 1) 40 EVT_SLIDER_CHANGED = wx.PyEventBinder(myEVT_SLIDER_CHANGED, 1)
@@ -70,6 +78,8 @@ class GradientSlider(wx.Panel): @@ -70,6 +78,8 @@ class GradientSlider(wx.Panel):
70 self.colour = colour 78 self.colour = colour
71 self.selected = 0 79 self.selected = 0
72 80
  81 + self._gradient_colours = None
  82 +
73 self.CalculateControlPositions() 83 self.CalculateControlPositions()
74 84
75 def _bind_events_wx(self): 85 def _bind_events_wx(self):
@@ -131,27 +141,43 @@ class GradientSlider(wx.Panel): @@ -131,27 +141,43 @@ class GradientSlider(wx.Panel):
131 141
132 width_transparency = self.max_position - self.min_position 142 width_transparency = self.max_position - self.min_position
133 143
134 - # Drawing the left blank area.  
135 - pen = wx.Pen((0, 0, 0))  
136 - brush = wx.Brush((0, 0, 0))  
137 - dc.SetPen(pen)  
138 - dc.SetBrush(brush)  
139 - dc.DrawRectangle(0, 0, PUSH_WIDTH, h)  
140 -  
141 - # Drawing the right blank area.  
142 - pen = wx.Pen((255, 255, 255))  
143 - brush = wx.Brush((255, 255, 255))  
144 - dc.SetPen(pen)  
145 - dc.SetBrush(brush)  
146 - dc.DrawRectangle(x_init_gradient + width_gradient, 0, PUSH_WIDTH, h)  
147 -  
148 - # Drawing the gradient.  
149 - dc.GradientFillLinear(  
150 - (x_init_gradient, y_init_gradient, width_gradient, height_gradient),  
151 - (0, 0, 0),  
152 - (255, 255, 255),  
153 - )  
154 - 144 + gc = wx.GraphicsContext.Create(dc)
  145 +
  146 + points = ((0, PUSH_WIDTH, (0, 0, 0), (0, 0, 0)),
  147 + (PUSH_WIDTH, w - PUSH_WIDTH, (0, 0, 0), (255, 255, 255)),
  148 + (w - PUSH_WIDTH, w, (255, 255, 255), (255, 255, 255)))
  149 +
  150 + # Drawing the gradient background
  151 + for p1, p2, c1, c2 in points:
  152 + brush = gc.CreateLinearGradientBrush(p1, 0, p2, h, c1, c2)
  153 + gc.SetBrush(brush)
  154 + path = gc.CreatePath()
  155 + path.AddRectangle(p1, 0, p2 - p1, h)
  156 + gc.StrokePath(path)
  157 + gc.FillPath(path)
  158 +
  159 + # Drawing the transparent coloured overlay
  160 + if self._gradient_colours is None:
  161 + brush = wx.Brush(wx.Colour(*self.colour))
  162 + pen = wx.Pen(wx.Colour(*self.colour))
  163 + gc.SetBrush(brush)
  164 + gc.SetPen(pen)
  165 + path = gc.CreatePath()
  166 + path.AddRectangle(self.min_position, 0, width_transparency, h)
  167 + gc.FillPath(path)
  168 + gc.StrokePath(path)
  169 + else:
  170 + for i, (c1, c2) in enumerate(zip(self._gradient_colours, self._gradient_colours[1:])):
  171 + p1 = self.min_position + i * width_transparency / len(self._gradient_colours)
  172 + p2 = self.min_position + (i + 1) * width_transparency / len(self._gradient_colours)
  173 + brush = gc.CreateLinearGradientBrush(p1, 0, p2, h, c1, c2)
  174 + gc.SetBrush(brush)
  175 + path = gc.CreatePath()
  176 + path.AddRectangle(p1, 0, p2 - p1, h)
  177 + gc.StrokePath(path)
  178 + gc.FillPath(path)
  179 +
  180 + # Drawing the pushes
155 try: 181 try:
156 n = wx.RendererNative.Get() 182 n = wx.RendererNative.Get()
157 except AttributeError: 183 except AttributeError:
@@ -161,14 +187,14 @@ class GradientSlider(wx.Panel): @@ -161,14 +187,14 @@ class GradientSlider(wx.Panel):
161 n.DrawPushButton(self, dc, (x_init_push1, 0, PUSH_WIDTH, h)) 187 n.DrawPushButton(self, dc, (x_init_push1, 0, PUSH_WIDTH, h))
162 n.DrawPushButton(self, dc, (x_init_push2, 0, PUSH_WIDTH, h)) 188 n.DrawPushButton(self, dc, (x_init_push2, 0, PUSH_WIDTH, h))
163 189
164 - # Drawing the transparent slider.  
165 - bytes = numpy.array(self.colour * width_transparency * h, "B")  
166 - try:  
167 - slider = wx.Bitmap.FromBufferRGBA(width_transparency, h, bytes)  
168 - except:  
169 - pass  
170 - else:  
171 - dc.DrawBitmap(slider, self.min_position, 0, True) 190 + # # Drawing the transparent slider.
  191 + # bytes = numpy.array(self.colour * width_transparency * h, "B")
  192 + # try:
  193 + # slider = wx.Bitmap.FromBufferRGBA(width_transparency, h, bytes)
  194 + # except:
  195 + # pass
  196 + # else:
  197 + # dc.DrawBitmap(slider, self.min_position, 0, True)
172 198
173 def OnEraseBackGround(self, evt): 199 def OnEraseBackGround(self, evt):
174 # Only to avoid this widget to flick. 200 # Only to avoid this widget to flick.
@@ -316,6 +342,9 @@ class GradientSlider(wx.Panel): @@ -316,6 +342,9 @@ class GradientSlider(wx.Panel):
316 def SetColour(self, colour): 342 def SetColour(self, colour):
317 self.colour = colour 343 self.colour = colour
318 344
  345 + def SetGradientColours(self, colors):
  346 + self._gradient_colours = colors
  347 +
319 def SetMinRange(self, min_range): 348 def SetMinRange(self, min_range):
320 self.min_range = min_range 349 self.min_range = min_range
321 self.CalculateControlPositions() 350 self.CalculateControlPositions()
@@ -485,6 +514,9 @@ class GradientCtrl(wx.Panel): @@ -485,6 +514,9 @@ class GradientCtrl(wx.Panel):
485 self.gradient_slider.SetColour(colour) 514 self.gradient_slider.SetColour(colour)
486 self.gradient_slider.Refresh() 515 self.gradient_slider.Refresh()
487 516
  517 + def SetGradientColours(self, colors):
  518 + self.gradient_slider.SetGradientColours(colors)
  519 +
488 def SetMaxRange(self, value): 520 def SetMaxRange(self, value):
489 self.spin_min.SetMax(value) 521 self.spin_min.SetMax(value)
490 self.spin_max.SetMax(value) 522 self.spin_max.SetMax(value)
invesalius/gui/widgets/slice_menu.py
@@ -205,7 +205,7 @@ class SliceMenu(wx.Menu): @@ -205,7 +205,7 @@ class SliceMenu(wx.Menu):
205 def OnPopup(self, evt): 205 def OnPopup(self, evt):
206 id = evt.GetId() 206 id = evt.GetId()
207 item = self.ID_TO_TOOL_ITEM[evt.GetId()] 207 item = self.ID_TO_TOOL_ITEM[evt.GetId()]
208 - key = item.GetLabel() 208 + key = item.GetItemLabelText()
209 if(key in const.WINDOW_LEVEL.keys()): 209 if(key in const.WINDOW_LEVEL.keys()):
210 window, level = const.WINDOW_LEVEL[key] 210 window, level = const.WINDOW_LEVEL[key]
211 Publisher.sendMessage('Bright and contrast adjustment image', 211 Publisher.sendMessage('Bright and contrast adjustment image',
invesalius/inv_paths.py
@@ -38,6 +38,8 @@ OLD_USER_LOG_DIR = OLD_USER_INV_DIR.joinpath(&quot;logs&quot;) @@ -38,6 +38,8 @@ OLD_USER_LOG_DIR = OLD_USER_INV_DIR.joinpath(&quot;logs&quot;)
38 38
39 INV_TOP_DIR = pathlib.Path(__file__).parent.parent.resolve() 39 INV_TOP_DIR = pathlib.Path(__file__).parent.parent.resolve()
40 40
  41 +PLUGIN_DIRECTORY = INV_TOP_DIR.joinpath("plugins")
  42 +
41 ICON_DIR = INV_TOP_DIR.joinpath("icons") 43 ICON_DIR = INV_TOP_DIR.joinpath("icons")
42 SAMPLE_DIR = INV_TOP_DIR.joinpath("samples") 44 SAMPLE_DIR = INV_TOP_DIR.joinpath("samples")
43 DOC_DIR = INV_TOP_DIR.joinpath("docs") 45 DOC_DIR = INV_TOP_DIR.joinpath("docs")
invesalius/plugins.py
@@ -25,6 +25,7 @@ from pubsub import pub as Publisher @@ -25,6 +25,7 @@ from pubsub import pub as Publisher
25 25
26 import invesalius.constants as consts 26 import invesalius.constants as consts
27 from invesalius import inv_paths 27 from invesalius import inv_paths
  28 +from itertools import chain
28 29
29 30
30 def import_source(module_name, module_file_path): 31 def import_source(module_name, module_file_path):
@@ -44,7 +45,8 @@ class PluginManager: @@ -44,7 +45,8 @@ class PluginManager:
44 45
45 def find_plugins(self): 46 def find_plugins(self):
46 self.plugins = {} 47 self.plugins = {}
47 - for p in sorted(inv_paths.USER_PLUGINS_DIRECTORY.glob("*")): 48 + for p in sorted(chain(inv_paths.USER_PLUGINS_DIRECTORY.glob("*"),\
  49 + inv_paths.PLUGIN_DIRECTORY.glob("*"))):
48 if p.is_dir(): 50 if p.is_dir():
49 try: 51 try:
50 with p.joinpath("plugin.json").open() as f: 52 with p.joinpath("plugin.json").open() as f:
invesalius/reader/dicom_grouper.py
@@ -130,23 +130,23 @@ class DicomGroup: @@ -130,23 +130,23 @@ class DicomGroup:
130 else: 130 else:
131 filelist = [dicom.image.file for dicom in 131 filelist = [dicom.image.file for dicom in
132 self.slices_dict.values()] 132 self.slices_dict.values()]
133 - 133 +
134 # Sort slices using GDCM 134 # Sort slices using GDCM
135 - if (self.dicom.image.orientation_label != "CORONAL"):  
136 - #Organize reversed image  
137 - sorter = gdcm.IPPSorter()  
138 - sorter.SetComputeZSpacing(True)  
139 - sorter.SetZSpacingTolerance(1e-10)  
140 - try:  
141 - sorter.Sort([utils.encode(i, const.FS_ENCODE) for i in filelist])  
142 - except TypeError:  
143 - sorter.Sort(filelist)  
144 - filelist = sorter.GetFilenames() 135 + #if (self.dicom.image.orientation_label != "CORONAL"):
  136 + #Organize reversed image
  137 + sorter = gdcm.IPPSorter()
  138 + sorter.SetComputeZSpacing(True)
  139 + sorter.SetZSpacingTolerance(1e-10)
  140 + try:
  141 + sorter.Sort([utils.encode(i, const.FS_ENCODE) for i in filelist])
  142 + except TypeError:
  143 + sorter.Sort(filelist)
  144 + filelist = sorter.GetFilenames()
145 145
146 # for breast-CT of koning manufacturing (KBCT) 146 # for breast-CT of koning manufacturing (KBCT)
147 if list(self.slices_dict.values())[0].parser.GetManufacturerName() == "Koning": 147 if list(self.slices_dict.values())[0].parser.GetManufacturerName() == "Koning":
148 filelist.sort() 148 filelist.sort()
149 - 149 +
150 return filelist 150 return filelist
151 151
152 def GetHandSortedList(self): 152 def GetHandSortedList(self):
invesalius/reader/dicom_reader.py
@@ -82,15 +82,15 @@ def SelectLargerDicomGroup(patient_group): @@ -82,15 +82,15 @@ def SelectLargerDicomGroup(patient_group):
82 def SortFiles(filelist, dicom): 82 def SortFiles(filelist, dicom):
83 # Sort slices 83 # Sort slices
84 # FIXME: Coronal Crash. necessary verify 84 # FIXME: Coronal Crash. necessary verify
85 - if (dicom.image.orientation_label != "CORONAL"):  
86 - ##Organize reversed image  
87 - sorter = gdcm.IPPSorter()  
88 - sorter.SetComputeZSpacing(True)  
89 - sorter.SetZSpacingTolerance(1e-10)  
90 - sorter.Sort(filelist)  
91 -  
92 - #Getting organized image  
93 - filelist = sorter.GetFilenames() 85 + # if (dicom.image.orientation_label != "CORONAL"):
  86 + ##Organize reversed image
  87 + sorter = gdcm.IPPSorter()
  88 + sorter.SetComputeZSpacing(True)
  89 + sorter.SetZSpacingTolerance(1e-10)
  90 + sorter.Sort(filelist)
  91 +
  92 + #Getting organized image
  93 + filelist = sorter.GetFilenames()
94 94
95 return filelist 95 return filelist
96 96
invesalius/segmentation/brain/segment.py
@@ -20,6 +20,17 @@ SIZE = 48 @@ -20,6 +20,17 @@ SIZE = 48
20 OVERLAP = SIZE // 2 + 1 20 OVERLAP = SIZE // 2 + 1
21 21
22 22
  23 +def get_LUT_value(data, window, level):
  24 + shape = data.shape
  25 + data_ = data.ravel()
  26 + data = np.piecewise(data_,
  27 + [data_ <= (level - 0.5 - (window-1)/2),
  28 + data_ > (level - 0.5 + (window-1)/2)],
  29 + [0, window, lambda data_: ((data_ - (level - 0.5))/(window-1) + 0.5)*(window)])
  30 + data.shape = shape
  31 + return data
  32 +
  33 +
23 def gen_patches(image, patch_size, overlap): 34 def gen_patches(image, patch_size, overlap):
24 sz, sy, sx = image.shape 35 sz, sy, sx = image.shape
25 i_cuts = list( 36 i_cuts = list(
@@ -63,8 +74,10 @@ def brain_segment(image, probability_array, comm_array): @@ -63,8 +74,10 @@ def brain_segment(image, probability_array, comm_array):
63 model = keras.models.model_from_json(json_file.read()) 74 model = keras.models.model_from_json(json_file.read())
64 model.load_weights(str(folder.joinpath("model.h5"))) 75 model.load_weights(str(folder.joinpath("model.h5")))
65 model.compile("Adam", "binary_crossentropy") 76 model.compile("Adam", "binary_crossentropy")
  77 +
  78 + keras.utils.plot_model(model, "model.png", show_shapes=True, show_layer_names=True)
66 79
67 - image = imagedata_utils.image_normalize(image, 0.0, 1.0) 80 + image = imagedata_utils.image_normalize(image, 0.0, 1.0, output_dtype=np.float32)
68 sums = np.zeros_like(image) 81 sums = np.zeros_like(image)
69 # segmenting by patches 82 # segmenting by patches
70 for completion, sub_image, patch in gen_patches(image, SIZE, OVERLAP): 83 for completion, sub_image, patch in gen_patches(image, SIZE, OVERLAP):
@@ -80,7 +93,7 @@ def brain_segment(image, probability_array, comm_array): @@ -80,7 +93,7 @@ def brain_segment(image, probability_array, comm_array):
80 93
81 ctx = multiprocessing.get_context('spawn') 94 ctx = multiprocessing.get_context('spawn')
82 class SegmentProcess(ctx.Process): 95 class SegmentProcess(ctx.Process):
83 - def __init__(self, image, create_new_mask, backend, device_id, use_gpu): 96 + def __init__(self, image, create_new_mask, backend, device_id, use_gpu, apply_wwwl=False, window_width=255, window_level=127):
84 multiprocessing.Process.__init__(self) 97 multiprocessing.Process.__init__(self)
85 98
86 self._image_filename = image.filename 99 self._image_filename = image.filename
@@ -102,6 +115,10 @@ class SegmentProcess(ctx.Process): @@ -102,6 +115,10 @@ class SegmentProcess(ctx.Process):
102 self.device_id = device_id 115 self.device_id = device_id
103 self.use_gpu = use_gpu 116 self.use_gpu = use_gpu
104 117
  118 + self.apply_wwwl = apply_wwwl
  119 + self.window_width = window_width
  120 + self.window_level = window_level
  121 +
105 self._pconn, self._cconn = multiprocessing.Pipe() 122 self._pconn, self._cconn = multiprocessing.Pipe()
106 self._exception = None 123 self._exception = None
107 124
@@ -122,6 +139,12 @@ class SegmentProcess(ctx.Process): @@ -122,6 +139,12 @@ class SegmentProcess(ctx.Process):
122 shape=self._image_shape, 139 shape=self._image_shape,
123 mode="r", 140 mode="r",
124 ) 141 )
  142 +
  143 + print(image.min(), image.max())
  144 + if self.apply_segment_threshold:
  145 + print("Applying window level")
  146 + image = get_LUT_value(image, self.window_width, self.window_level)
  147 +
125 probability_array = np.memmap( 148 probability_array = np.memmap(
126 self._prob_array_filename, 149 self._prob_array_filename,
127 dtype=np.float32, 150 dtype=np.float32,