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
app.py
... ... @@ -40,7 +40,11 @@ if sys.platform == 'win32':
40 40 # #wxversion.ensureMinimal('2.8-unicode', optionsRequired=True)
41 41 # #wxversion.select('2.8-unicode', optionsRequired=True)
42 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 48 import wx
45 49 try:
46 50 from wx.adv import SplashScreen
... ... @@ -98,7 +102,7 @@ class InVesalius(wx.App):
98 102 """
99 103 Initialize splash screen and main frame.
100 104 """
101   -
  105 +
102 106 from multiprocessing import freeze_support
103 107 freeze_support()
104 108  
... ... @@ -179,18 +183,18 @@ class Inv3SplashScreen(SplashScreen):
179 183  
180 184 # session.SaveConfigFileBackup()
181 185  
182   -
  186 +
183 187 # Only after language was defined, splash screen will be
184 188 # shown
185 189 if lang:
186   -
  190 +
187 191 #import locale
188 192 #try:
189 193 # locale.setlocale(locale.LC_ALL, '')
190 194 #except locale.Error:
191 195 # pass
192   -
193   -
  196 +
  197 +
194 198 # For pt_BR, splash_pt.png should be used
195 199 if (lang.startswith('pt')):
196 200 icon_file = "splash_pt.png"
... ... @@ -202,13 +206,13 @@ class Inv3SplashScreen(SplashScreen):
202 206 abs_file_path = os.path.abspath(".." + os.sep)
203 207 path = abs_file_path
204 208 path = os.path.join(path, 'icons', icon_file)
205   -
  209 +
206 210 else:
207 211  
208 212 path = os.path.join(".","icons", icon_file)
209 213 if not os.path.exists(path):
210 214 path = os.path.join(".", "icons", "splash_en.png")
211   -
  215 +
212 216 bmp = wx.Image(path).ConvertToBitmap()
213 217  
214 218 try:
... ... @@ -232,10 +236,10 @@ class Inv3SplashScreen(SplashScreen):
232 236 from invesalius.gui.frame import Frame
233 237 from invesalius.control import Controller
234 238 from invesalius.project import Project
235   -
  239 +
236 240 self.main = Frame(None)
237 241 self.control = Controller(self.main)
238   -
  242 +
239 243 self.fc = wx.CallLater(200, self.ShowMain)
240 244 options, args = parse_comand_line()
241 245 wx.CallLater(1, use_cmd_optargs, options, args)
... ... @@ -498,7 +502,7 @@ def main():
498 502 if __name__ == '__main__':
499 503 #Is needed because of pyinstaller
500 504 multiprocessing.freeze_support()
501   -
  505 +
502 506 #Needed in win 32 exe
503 507 if hasattr(sys,"frozen") and sys.platform.startswith('win'):
504 508  
... ... @@ -523,4 +527,3 @@ if __name__ == '__main__':
523 527  
524 528 # Init application
525 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 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 503 def get_LUT_value_255(data, window, level):
532 504 shape = data.shape
533 505 data_ = data.ravel()
... ... @@ -539,6 +511,8 @@ def get_LUT_value_255(data, window, level):
539 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 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 301  
302 302 for name in self.aux_matrices:
303 303 m = self.aux_matrices[name]
304   - f = m.filename
  304 + try:
  305 + f = m.filename
  306 + except AttributeError:
  307 + continue
305 308 m._mmap.close()
306 309 m = None
307 310 os.remove(f)
... ... @@ -347,6 +350,8 @@ class Slice(metaclass=utils.Singleton):
347 350 self.SetMaskEditionThreshold(index, threshold_range)
348 351  
349 352 def __set_current_mask_threshold(self, threshold_range):
  353 + if self.current_mask is None:
  354 + return
350 355 index = self.current_mask.index
351 356 self.num_gradient += 1
352 357 self.current_mask.matrix[:] = 0
... ... @@ -387,6 +392,8 @@ class Slice(metaclass=utils.Singleton):
387 392 Publisher.sendMessage("Reload actual slice")
388 393  
389 394 def __set_current_mask_threshold_actual_slice(self, threshold_range):
  395 + if self.current_mask is None:
  396 + return
390 397 index = self.current_mask.index
391 398 for orientation in self.buffer_slices:
392 399 self.buffer_slices[orientation].discard_vtk_mask()
... ... @@ -624,7 +631,7 @@ class Slice(metaclass=utils.Singleton):
624 631 self.buffer_slices[orientation].vtk_image = image
625 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 635 m = self.get_aux_slice("watershed", orientation, slice_number)
629 636 tmp_vimage = converters.to_vtk(m, self.spacing, slice_number, orientation)
630 637 cimage = self.do_custom_colour(
... ...
invesalius/data/viewer_slice.py
... ... @@ -102,13 +102,13 @@ class ContourMIPConfig(wx.Panel):
102 102 self.txt_mip_border = wx.StaticText(self, -1, _("Sharpness"))
103 103  
104 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 106 sizer.Add(self.mip_size_spin, 0)
107 107 try:
108 108 sizer.Add(10, 0)
109 109 except TypeError:
110 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 112 sizer.Add(self.border_spin, 0, wx.EXPAND)
113 113 try:
114 114 sizer.Add(10, 0)
... ... @@ -1438,8 +1438,12 @@ class Viewer(wx.Panel):
1438 1438 index = max_slice_number - 1
1439 1439 inverted = self.mip_ctrls.inverted.GetValue()
1440 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 1447 self.slice_data.actor.SetInputData(image)
1444 1448 for actor in self.actors_by_slice_number[self.slice_data.number]:
1445 1449 self.slice_data.renderer.RemoveActor(actor)
... ...
invesalius/gui/brain_seg_dialog.py
... ... @@ -81,6 +81,8 @@ class BrainSegmenterDialog(wx.Dialog):
81 81 self.txt_threshold.SetMinClientSize((w, -1))
82 82 self.chk_new_mask = wx.CheckBox(self, wx.ID_ANY, _("Create new mask"))
83 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 86 self.progress = wx.Gauge(self, -1)
85 87 self.lbl_progress_caption = wx.StaticText(self, -1, _("Elapsed time:"))
86 88 self.lbl_time = wx.StaticText(self, -1, _("00:00:00"))
... ... @@ -115,11 +117,12 @@ class BrainSegmenterDialog(wx.Dialog):
115 117 sizer_3.Add(
116 118 self.sld_threshold,
117 119 1,
118   - wx.ALIGN_CENTER | wx.BOTTOM | wx.EXPAND | wx.LEFT | wx.RIGHT,
  120 + wx.BOTTOM | wx.EXPAND | wx.LEFT | wx.RIGHT,
119 121 5,
120 122 )
121 123 sizer_3.Add(self.txt_threshold, 0, wx.ALL, 5)
122 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 126 main_sizer.Add(self.chk_new_mask, 0, wx.EXPAND | wx.ALL, 5)
124 127 main_sizer.Add(self.progress, 0, wx.EXPAND | wx.ALL, 5)
125 128 time_sizer = wx.BoxSizer(wx.HORIZONTAL)
... ... @@ -128,15 +131,15 @@ class BrainSegmenterDialog(wx.Dialog):
128 131 main_sizer.Add(time_sizer, 0, wx.EXPAND | wx.ALL, 5)
129 132 sizer_buttons = wx.BoxSizer(wx.HORIZONTAL)
130 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 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 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 143 self.SetSizer(main_sizer)
141 144 main_sizer.Fit(self)
142 145 main_sizer.SetSizeHints(self)
... ... @@ -216,6 +219,7 @@ class BrainSegmenterDialog(wx.Dialog):
216 219 device_id = self.plaidml_devices[self.cb_devices.GetValue()]
217 220 except (KeyError, AttributeError):
218 221 device_id = "llvm_cpu.0"
  222 + apply_wwwl = self.chk_apply_wwwl.GetValue()
219 223 create_new_mask = self.chk_new_mask.GetValue()
220 224 use_gpu = self.chk_use_gpu.GetValue()
221 225 prob_threshold = self.sld_threshold.GetValue() / 100.0
... ... @@ -224,8 +228,11 @@ class BrainSegmenterDialog(wx.Dialog):
224 228 self.btn_segment.Disable()
225 229 self.chk_new_mask.Disable()
226 230  
  231 + window_width = slc.Slice().window_width
  232 + window_level = slc.Slice().window_level
  233 +
227 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 236 self.ps.start()
230 237 except (multiprocessing.ProcessError, OSError, ValueError) as err:
231 238 self.OnStop(None)
... ...
invesalius/gui/data_notebook.py
... ... @@ -351,18 +351,89 @@ class ButtonControlPanel(wx.Panel):
351 351 else:
352 352 dlg.MaskSelectionRequiredForDuplication()
353 353  
354   -class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCtrlMixin):
355 354  
  355 +class InvListCtrl(wx.ListCtrl):
356 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 437 self.mask_list_index = {}
367 438 self.current_index = 0
368 439 self.__init_columns()
... ... @@ -371,12 +442,9 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt
371 442 self.__bind_events()
372 443  
373 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 445 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEditLabel)
377 446 self.Bind(wx.EVT_KEY_UP, self.OnKeyEvent)
378 447  
379   -
380 448 def __bind_events(self):
381 449 Publisher.subscribe(self.AddMask, 'Add mask')
382 450 Publisher.subscribe(self.EditMaskThreshold,
... ... @@ -438,7 +506,6 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt
438 506 self.current_index -= 1
439 507 self.SetItemImage(self.current_index, 1)
440 508  
441   -
442 509 def OnCloseProject(self):
443 510 self.DeleteAllItems()
444 511 self.mask_list_index = {}
... ... @@ -475,13 +542,13 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt
475 542 def __init_image_list(self):
476 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 546 bitmap = wx.Bitmap(image.Scale(16, 16))
480 547 bitmap.SetWidth(16)
481 548 bitmap.SetHeight(16)
482 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 552 bitmap = wx.Bitmap(image.Scale(16, 16))
486 553 bitmap.SetWidth(16)
487 554 bitmap.SetHeight(16)
... ... @@ -489,23 +556,16 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt
489 556  
490 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 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 567 evt.Skip()
504 568  
505   - def OnItemActivated(self, evt):
506   - self.ToggleItem(evt.Index)
507   - # pass
508   -
509 569 def OnCheckItem(self, index, flag):
510 570 if flag:
511 571 for key in self.mask_list_index.keys():
... ... @@ -515,26 +575,7 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCt
515 575 self.current_index = index
516 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 580 def InsertNewItem(self, index=0, label=_("Mask"), threshold="(1000, 4500)",
540 581 colour=None):
... ... @@ -718,19 +759,11 @@ class SurfaceButtonControlPanel(wx.Panel):
718 759 def AffineStatus(self, affine, status):
719 760 self.affinestatus = status
720 761  
721   -class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckListCtrlMixin):
722   -
  762 +class SurfacesListCtrlPanel(InvListCtrl):
723 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 767 self.__init_columns()
735 768 self.__init_image_list()
736 769 self.__init_evt()
... ... @@ -752,8 +785,6 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
752 785 Publisher.subscribe(self.OnShowMultiple, 'Show multiple surfaces')
753 786  
754 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 788 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEditLabel)
758 789 #self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected_)
759 790 self.Bind(wx.EVT_KEY_UP, self.OnKeyEvent)
... ... @@ -841,13 +872,13 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
841 872 def __init_image_list(self):
842 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 876 bitmap = wx.Bitmap(image.Scale(16, 16))
846 877 bitmap.SetWidth(16)
847 878 bitmap.SetHeight(16)
848 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 882 bitmap = wx.Bitmap(image.Scale(16, 16))
852 883 bitmap.SetWidth(16)
853 884 bitmap.SetHeight(16)
... ... @@ -855,7 +886,7 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
855 886  
856 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 891 def OnBeginLabelEdit(self, evt):
861 892 if evt.GetColumn() == 1:
... ... @@ -864,11 +895,10 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
864 895 evt.Veto()
865 896  
866 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 902 evt.Skip()
873 903  
874 904 def OnCheckItem(self, index, flag):
... ... @@ -944,28 +974,6 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
944 974 self.SetItem(index, 4, transparency)
945 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 977 def EditSurfaceTransparency(self, surface_index, transparency):
970 978 """
971 979 Set actor transparency (oposite to opacity) according to given actor
... ... @@ -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 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 1001 self.__init_columns()
1002 1002 self.__init_image_list()
1003 1003 self.__init_evt()
... ... @@ -1017,13 +1017,10 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1017 1017 Publisher.subscribe(self.OnRemoveGUIMeasure, 'Remove GUI measurement')
1018 1018  
1019 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 1020 self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEditLabel)
1023 1021 self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected_)
1024 1022 self.Bind(wx.EVT_KEY_UP, self.OnKeyEvent)
1025 1023  
1026   -
1027 1024 def OnKeyEvent(self, event):
1028 1025 keycode = event.GetKeyCode()
1029 1026 # Delete key
... ... @@ -1116,13 +1113,13 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1116 1113 def __init_image_list(self):
1117 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 1117 bitmap = wx.Bitmap(image.Scale(16, 16))
1121 1118 bitmap.SetWidth(16)
1122 1119 bitmap.SetHeight(16)
1123 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 1123 bitmap = wx.Bitmap(image.Scale(16, 16))
1127 1124 bitmap.SetWidth(16)
1128 1125 bitmap.SetHeight(16)
... ... @@ -1130,7 +1127,7 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1130 1127  
1131 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 1132 def OnBeginLabelEdit(self, evt):
1136 1133 if evt.GetColumn() == 1:
... ... @@ -1139,14 +1136,12 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1139 1136 evt.Veto()
1140 1137  
1141 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 1143 evt.Skip()
1144 1144  
1145   - def OnItemActivated(self, evt):
1146   - self.ToggleItem(evt.Index)
1147   - evt.Skip()
1148   -
1149   -
1150 1145 def OnCheckItem(self, index, flag):
1151 1146 Publisher.sendMessage('Show measurement', index=index, visibility=flag)
1152 1147  
... ... @@ -1238,27 +1233,6 @@ class MeasuresListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.CheckLis
1238 1233 self.SetItemImage(index, 1)
1239 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 1236 def EditItemColour(self, measure_index, colour):
1263 1237 """
1264 1238 """
... ... @@ -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 1251 # TODO: Remove edimixin, allow only visible and invisible
1278 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 1256 self.__init_columns()
1290 1257 self.__init_image_list()
1291 1258 self.__init_evt()
... ... @@ -1311,19 +1278,19 @@ class AnnotationsListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin, listmix.Check
1311 1278 def __init_image_list(self):
1312 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 1282 bitmap = wx.Bitmap(image.Scale(16, 16))
1316 1283 bitmap.SetWidth(16)
1317 1284 bitmap.SetHeight(16)
1318 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 1288 bitmap = wx.Bitmap(image.Scale(16, 16))
1322 1289 bitmap.SetWidth(16)
1323 1290 bitmap.SetHeight(16)
1324 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 1294 bitmap = wx.Bitmap(image.Scale(16, 16))
1328 1295 bitmap.SetWidth(16)
1329 1296 bitmap.SetHeight(16)
... ...
invesalius/gui/default_tasks.py
... ... @@ -123,6 +123,7 @@ class Panel(wx.Panel):
123 123  
124 124 #self.SetSizerAndFit(sizer)
125 125 self.SetSizer(sizer)
  126 + self.Layout()
126 127  
127 128  
128 129 # Lower fold panel
... ...
invesalius/gui/default_viewers.py
... ... @@ -111,7 +111,7 @@ class Panel(wx.Panel):
111 111 p3.SetPopupMenu(menu)
112 112  
113 113  
114   - if sys.platform == 'win32':
  114 + if sys.platform == 'win32' or wx.VERSION >= (4, 1):
115 115 self.aui_manager.AddPane(p1, s1)
116 116 self.aui_manager.AddPane(p2, s2)
117 117 self.aui_manager.AddPane(p3, s3)
... ... @@ -604,7 +604,7 @@ class VolumeToolPanel(wx.Panel):
604 604 id = evt.GetId()
605 605 item = ID_TO_ITEMSLICEMENU[id]
606 606 checked = item.IsChecked()
607   - label = item.GetLabel()
  607 + label = item.GetItemLabelText()
608 608  
609 609 if not (checked):
610 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 245 WILDCARD_ANALYZE = "Analyze 7.5 (*.hdr)|*.hdr|" \
246 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 249 "All files (*.*)|*.*"
252 250 #".[jJ][pP][gG]"
253 251 WILDCARD_PARREC = "PAR/REC (*.par)|*.par|" \
... ... @@ -1950,17 +1948,17 @@ class WatershedOptionsPanel(wx.Panel):
1950 1948 min_value=1, max_value=10)
1951 1949  
1952 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 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 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 1963 self.SetSizer(sizer)
1966 1964 sizer.Fit(self)
... ... @@ -1998,8 +1996,7 @@ class WatershedOptionsDialog(wx.Dialog):
1998 1996 btnsizer.Realize()
1999 1997  
2000 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 2001 self.SetSizer(sizer)
2005 2002 sizer.Fit(self)
... ... @@ -2060,16 +2057,16 @@ class MaskBooleanDialog(wx.Dialog):
2060 2057  
2061 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 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 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 2065 gsizer.Add(self.mask2, 1, wx.EXPAND)
2069 2066  
2070 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 2071 self.SetSizer(sizer)
2075 2072 sizer.Fit(self)
... ... @@ -2798,8 +2795,8 @@ class SelectPartsOptionsDialog(wx.Dialog):
2798 2795 sizer.AddSpacer(5)
2799 2796  
2800 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 2801 sizer.Add(btn_sizer, 0, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT, border=5)
2805 2802 sizer.AddSpacer(5)
... ... @@ -3202,8 +3199,8 @@ class FillHolesAutoDialog(wx.Dialog):
3202 3199 sizer.AddSpacer(5)
3203 3200  
3204 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 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 789 in_sizer.Add(checkbox, 0)
790 790  
791 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 794 sizer.Fit(self)
795 795  
796 796 self.SetSizer(sizer)
... ...
invesalius/gui/frame.py
... ... @@ -214,7 +214,7 @@ class Frame(wx.Frame):
214 214 # Add toolbars to manager
215 215 # This is pretty tricky -- order on win32 is inverted when
216 216 # compared to linux2 & darwin
217   - if sys.platform == 'win32':
  217 + if sys.platform == 'win32' or wx.VERSION >= (4, 1):
218 218 t1 = ProjectToolBar(self)
219 219 t2 = HistoryToolBar(self)
220 220 t3 = LayoutToolBar(self)
... ... @@ -259,6 +259,8 @@ class Frame(wx.Frame):
259 259 # TODO: Allow saving and restoring perspectives
260 260 self.perspective_all = aui_manager.SavePerspective()
261 261  
  262 + self.Layout()
  263 +
262 264 def _BeginBusyCursor(self):
263 265 """
264 266 Start busy cursor.
... ... @@ -1941,11 +1943,11 @@ class LayoutToolBar(AuiToolBar):
1941 1943 d = inv_paths.ICON_DIR
1942 1944 if sys.platform == 'darwin':
1943 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 1952 # Bitmaps for show/hide task item
1951 1953 p = os.path.join(d, "text_inverted_original.png")
... ... @@ -1956,11 +1958,11 @@ class LayoutToolBar(AuiToolBar):
1956 1958  
1957 1959 else:
1958 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 1967 # Bitmaps for show/hide task item
1966 1968 p = os.path.join(d, "text_inverted.png")
... ...
invesalius/gui/import_panel.py
... ... @@ -104,7 +104,7 @@ class InnerPanel(wx.Panel):
104 104  
105 105 inner_sizer = wx.BoxSizer(wx.HORIZONTAL)
106 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 108 panel.SetSizer(inner_sizer)
109 109 inner_sizer.Fit(panel)
110 110  
... ...
invesalius/gui/language_dialog.py
... ... @@ -71,8 +71,8 @@ class ComboBoxLanguage:
71 71 self.bitmapCmb = bitmapCmb = BitmapComboBox(parent, style=wx.CB_READONLY)
72 72 for key in self.locales_key:
73 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 76 # Add bitmap and info to Combo
77 77 bitmapCmb.Append(dict_locales[key], bmp, key)
78 78 # Set default combo item if available on the list
... ... @@ -123,8 +123,8 @@ class LanguageDialog(wx.Dialog):
123 123 # self.bitmapCmb = bitmapCmb = BitmapComboBox(self, style=wx.CB_READONLY)
124 124 # for key in self.locales_key:
125 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 128 # # Add bitmap and info to Combo
129 129 # bitmapCmb.Append(dict_locales[key], bmp, key)
130 130 # # Set default combo item if available on the list
... ...
invesalius/gui/preferences.py
... ... @@ -49,13 +49,13 @@ class Preferences(wx.Dialog):
49 49 self.book.AddPage(self.pnl_language, _("Language"))
50 50  
51 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 54 btnsizer = self.CreateStdDialogButtonSizer(wx.OK | wx.CANCEL)
55 55 sizer.Add(
56 56 btnsizer,
57 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 59 5,
60 60 )
61 61  
... ...
invesalius/gui/task_navigator.py
... ... @@ -211,7 +211,7 @@ class InnerFoldPanel(wx.Panel):
211 211 line_sizer = wx.BoxSizer(wx.HORIZONTAL)
212 212 line_sizer.Add(checkcamera, 0, wx.ALIGN_LEFT | wx.RIGHT | wx.LEFT, 5)
213 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 215 line_sizer.Fit(self)
216 216  
217 217 # Panel sizer to expand fold panel
... ... @@ -410,7 +410,7 @@ class NeuronavigationPanel(wx.Panel):
410 410 (nav_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL)])
411 411  
412 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 414 self.sizer = main_sizer
415 415 self.SetSizer(main_sizer)
416 416 self.Fit()
... ... @@ -852,7 +852,7 @@ class ObjectRegistrationPanel(wx.Panel):
852 852  
853 853 line_checks = wx.BoxSizer(wx.HORIZONTAL)
854 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 857 # Add line sizers into main sizer
858 858 main_sizer = wx.BoxSizer(wx.VERTICAL)
... ... @@ -1082,7 +1082,7 @@ class MarkersPanel(wx.Panel):
1082 1082 group_sizer.Add(sizer_create, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_HORIZONTAL, 5)
1083 1083 group_sizer.Add(sizer_btns, 0, wx.BOTTOM | wx.ALIGN_CENTER_HORIZONTAL, 5)
1084 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 1086 group_sizer.Fit(self)
1087 1087  
1088 1088 self.SetSizer(group_sizer)
... ...
invesalius/gui/task_slice.py
... ... @@ -141,7 +141,7 @@ class InnerTaskPanel(wx.Panel):
141 141  
142 142 line_sizer = wx.BoxSizer(wx.HORIZONTAL)
143 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 145 line_sizer.Fit(self)
146 146  
147 147 # Add line sizers into main sizer
... ... @@ -423,6 +423,7 @@ class InnerFoldPanel(wx.Panel):
423 423 try:
424 424 _id = panel_seg_id[panel_id]
425 425 self.fold_panel.Expand(self.fold_panel.GetFoldPanel(_id))
  426 + self.Layout()
426 427 except KeyError:
427 428 pass
428 429  
... ... @@ -688,11 +689,11 @@ class EditionTools(wx.Panel):
688 689 ## LINE 2
689 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 693 item = wx.MenuItem(menu, MENU_BRUSH_CIRCLE, _("Circle"))
693 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 697 item2 = wx.MenuItem(menu, MENU_BRUSH_SQUARE, _("Square"))
697 698 item2.SetBitmap(SQUARE_BMP)
698 699  
... ... @@ -803,8 +804,8 @@ class EditionTools(wx.Panel):
803 804 threshold_range=(thresh_min, thresh_max))
804 805  
805 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 810 brush = {MENU_BRUSH_CIRCLE: const.BRUSH_CIRCLE,
810 811 MENU_BRUSH_SQUARE: const.BRUSH_SQUARE}
... ... @@ -852,11 +853,11 @@ class WatershedTool(EditionTools):
852 853 ## LINE 2
853 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 857 item = wx.MenuItem(menu, MENU_BRUSH_CIRCLE, _("Circle"))
857 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 861 item2 = wx.MenuItem(menu, MENU_BRUSH_SQUARE, _("Square"))
861 862 item2.SetBitmap(SQUARE_BMP)
862 863  
... ... @@ -973,8 +974,8 @@ class WatershedTool(EditionTools):
973 974 self.gradient_thresh.SetMaxValue(thresh_max)
974 975  
975 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 980 brush = {MENU_BRUSH_CIRCLE: const.BRUSH_CIRCLE,
980 981 MENU_BRUSH_SQUARE: const.BRUSH_SQUARE}
... ...
invesalius/gui/task_surface.py
... ... @@ -30,6 +30,7 @@ except ImportError:
30 30  
31 31 from pubsub import pub as Publisher
32 32 import wx.lib.colourselect as csel
  33 +import wx.lib.scrolledpanel as scrolled
33 34  
34 35 import invesalius.constants as const
35 36 import invesalius.data.slice_ as slice_
... ... @@ -74,9 +75,9 @@ class TaskPanel(wx.Panel):
74 75 # Contour - slider
75 76 # enable / disable Fill holes
76 77  
77   -class InnerTaskPanel(wx.Panel):
  78 +class InnerTaskPanel(scrolled.ScrolledPanel):
78 79 def __init__(self, parent):
79   - wx.Panel.__init__(self, parent)
  80 + scrolled.ScrolledPanel.__init__(self, parent)
80 81 default_colour = self.GetBackgroundColour()
81 82 backgroud_colour = wx.Colour(255,255,255)
82 83 self.SetBackgroundColour(backgroud_colour)
... ... @@ -134,6 +135,13 @@ class InnerTaskPanel(wx.Panel):
134 135  
135 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 145 def OnButton(self, evt):
138 146 id = evt.GetId()
139 147 if id == BTN_NEW:
... ... @@ -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 449 def __init__(self, parent):
442   - wx.Panel.__init__(self, parent)
  450 + scrolled.ScrolledPanel.__init__(self, parent)
443 451 try:
444 452 default_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_MENUBAR)
445 453 except AttributeError:
... ... @@ -507,8 +515,16 @@ class SurfaceProperties(wx.Panel):
507 515 self.Update()
508 516 #self.SetAutoLayout(1)
509 517  
  518 + self.SetupScrolling()
  519 +
  520 + self.Bind(wx.EVT_SIZE, self.OnResize)
  521 +
510 522 self.__bind_events()
511 523  
  524 + def OnResize(self, evt):
  525 + print("Resize")
  526 + self.SetupScrolling()
  527 +
512 528 def __bind_events(self):
513 529 Publisher.subscribe(self.InsertNewSurface,
514 530 'Update surface info in GUI')
... ...
invesalius/gui/task_tools.py
... ... @@ -79,7 +79,7 @@ class InnerTaskPanel(wx.Panel):
79 79  
80 80 # Image(s) for buttons
81 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 83 BMP_DISTANCE = wx.Bitmap(os.path.join(inv_paths.ICON_DIR, "measure_line.png"), wx.BITMAP_TYPE_PNG)
84 84 BMP_ANNOTATE.SetWidth(25)
85 85 BMP_ANNOTATE.SetHeight(25)
... ...
invesalius/gui/widgets/gradient.py
... ... @@ -26,7 +26,15 @@ from wx.lib import intctrl
26 26  
27 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 39 myEVT_SLIDER_CHANGED = wx.NewEventType()
32 40 EVT_SLIDER_CHANGED = wx.PyEventBinder(myEVT_SLIDER_CHANGED, 1)
... ... @@ -70,6 +78,8 @@ class GradientSlider(wx.Panel):
70 78 self.colour = colour
71 79 self.selected = 0
72 80  
  81 + self._gradient_colours = None
  82 +
73 83 self.CalculateControlPositions()
74 84  
75 85 def _bind_events_wx(self):
... ... @@ -131,27 +141,43 @@ class GradientSlider(wx.Panel):
131 141  
132 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 181 try:
156 182 n = wx.RendererNative.Get()
157 183 except AttributeError:
... ... @@ -161,14 +187,14 @@ class GradientSlider(wx.Panel):
161 187 n.DrawPushButton(self, dc, (x_init_push1, 0, PUSH_WIDTH, h))
162 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 199 def OnEraseBackGround(self, evt):
174 200 # Only to avoid this widget to flick.
... ... @@ -316,6 +342,9 @@ class GradientSlider(wx.Panel):
316 342 def SetColour(self, colour):
317 343 self.colour = colour
318 344  
  345 + def SetGradientColours(self, colors):
  346 + self._gradient_colours = colors
  347 +
319 348 def SetMinRange(self, min_range):
320 349 self.min_range = min_range
321 350 self.CalculateControlPositions()
... ... @@ -485,6 +514,9 @@ class GradientCtrl(wx.Panel):
485 514 self.gradient_slider.SetColour(colour)
486 515 self.gradient_slider.Refresh()
487 516  
  517 + def SetGradientColours(self, colors):
  518 + self.gradient_slider.SetGradientColours(colors)
  519 +
488 520 def SetMaxRange(self, value):
489 521 self.spin_min.SetMax(value)
490 522 self.spin_max.SetMax(value)
... ...
invesalius/gui/widgets/slice_menu.py
... ... @@ -205,7 +205,7 @@ class SliceMenu(wx.Menu):
205 205 def OnPopup(self, evt):
206 206 id = evt.GetId()
207 207 item = self.ID_TO_TOOL_ITEM[evt.GetId()]
208   - key = item.GetLabel()
  208 + key = item.GetItemLabelText()
209 209 if(key in const.WINDOW_LEVEL.keys()):
210 210 window, level = const.WINDOW_LEVEL[key]
211 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 38  
39 39 INV_TOP_DIR = pathlib.Path(__file__).parent.parent.resolve()
40 40  
  41 +PLUGIN_DIRECTORY = INV_TOP_DIR.joinpath("plugins")
  42 +
41 43 ICON_DIR = INV_TOP_DIR.joinpath("icons")
42 44 SAMPLE_DIR = INV_TOP_DIR.joinpath("samples")
43 45 DOC_DIR = INV_TOP_DIR.joinpath("docs")
... ...
invesalius/plugins.py
... ... @@ -25,6 +25,7 @@ from pubsub import pub as Publisher
25 25  
26 26 import invesalius.constants as consts
27 27 from invesalius import inv_paths
  28 +from itertools import chain
28 29  
29 30  
30 31 def import_source(module_name, module_file_path):
... ... @@ -44,7 +45,8 @@ class PluginManager:
44 45  
45 46 def find_plugins(self):
46 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 50 if p.is_dir():
49 51 try:
50 52 with p.joinpath("plugin.json").open() as f:
... ...
invesalius/reader/dicom_grouper.py
... ... @@ -130,23 +130,23 @@ class DicomGroup:
130 130 else:
131 131 filelist = [dicom.image.file for dicom in
132 132 self.slices_dict.values()]
133   -
  133 +
134 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 146 # for breast-CT of koning manufacturing (KBCT)
147 147 if list(self.slices_dict.values())[0].parser.GetManufacturerName() == "Koning":
148 148 filelist.sort()
149   -
  149 +
150 150 return filelist
151 151  
152 152 def GetHandSortedList(self):
... ...
invesalius/reader/dicom_reader.py
... ... @@ -82,15 +82,15 @@ def SelectLargerDicomGroup(patient_group):
82 82 def SortFiles(filelist, dicom):
83 83 # Sort slices
84 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 95 return filelist
96 96  
... ...
invesalius/segmentation/brain/segment.py
... ... @@ -20,6 +20,17 @@ SIZE = 48
20 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 34 def gen_patches(image, patch_size, overlap):
24 35 sz, sy, sx = image.shape
25 36 i_cuts = list(
... ... @@ -63,8 +74,10 @@ def brain_segment(image, probability_array, comm_array):
63 74 model = keras.models.model_from_json(json_file.read())
64 75 model.load_weights(str(folder.joinpath("model.h5")))
65 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 81 sums = np.zeros_like(image)
69 82 # segmenting by patches
70 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 93  
81 94 ctx = multiprocessing.get_context('spawn')
82 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 97 multiprocessing.Process.__init__(self)
85 98  
86 99 self._image_filename = image.filename
... ... @@ -102,6 +115,10 @@ class SegmentProcess(ctx.Process):
102 115 self.device_id = device_id
103 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 122 self._pconn, self._cconn = multiprocessing.Pipe()
106 123 self._exception = None
107 124  
... ... @@ -122,6 +139,12 @@ class SegmentProcess(ctx.Process):
122 139 shape=self._image_shape,
123 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 148 probability_array = np.memmap(
126 149 self._prob_array_filename,
127 150 dtype=np.float32,
... ...