Commit 2c9f1dc3e11f144a94eee586edf61a86b17338c5

Authored by Thiago Franco de Moraes
Committed by GitHub
1 parent 7c1411a5

Gui improvements to Fill holes and remove parts (#48)

Improved the dialog interface used to config the fill holes and remove parts. Also, when using 3D connectivity, it show a progressdialog.
invesalius/data/styles.py
@@ -22,6 +22,8 @@ import multiprocessing @@ -22,6 +22,8 @@ import multiprocessing
22 import tempfile 22 import tempfile
23 import time 23 import time
24 24
  25 +from concurrent import futures
  26 +
25 import vtk 27 import vtk
26 import wx 28 import wx
27 29
@@ -1779,6 +1781,8 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle): @@ -1779,6 +1781,8 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle):
1779 self.fill_value = 254 1781 self.fill_value = 254
1780 1782
1781 self._dlg_title = _(u"Fill holes") 1783 self._dlg_title = _(u"Fill holes")
  1784 + self._progr_title = _(u"Fill hole")
  1785 + self._progr_msg = _(u"Filling hole ...")
1782 1786
1783 self.AddObserver("LeftButtonPressEvent", self.OnFFClick) 1787 self.AddObserver("LeftButtonPressEvent", self.OnFFClick)
1784 1788
@@ -1837,10 +1841,8 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle): @@ -1837,10 +1841,8 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle):
1837 bstruct = np.zeros((3, 3, 1), dtype='uint8') 1841 bstruct = np.zeros((3, 3, 1), dtype='uint8')
1838 bstruct[:, :, 0] = _bstruct 1842 bstruct[:, :, 0] = _bstruct
1839 1843
1840 -  
1841 - floodfill.floodfill_threshold(mask, [[x, y, z]], self.t0, self.t1, self.fill_value, bstruct, mask)  
1842 -  
1843 if self.config.target == '2D': 1844 if self.config.target == '2D':
  1845 + floodfill.floodfill_threshold(mask, [[x, y, z]], self.t0, self.t1, self.fill_value, bstruct, mask)
1844 b_mask = self.viewer.slice_.buffer_slices[self.orientation].mask 1846 b_mask = self.viewer.slice_.buffer_slices[self.orientation].mask
1845 index = self.viewer.slice_.buffer_slices[self.orientation].index 1847 index = self.viewer.slice_.buffer_slices[self.orientation].index
1846 1848
@@ -1853,6 +1855,16 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle): @@ -1853,6 +1855,16 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle):
1853 1855
1854 self.viewer.slice_.current_mask.save_history(index, self.orientation, p_mask, b_mask) 1856 self.viewer.slice_.current_mask.save_history(index, self.orientation, p_mask, b_mask)
1855 else: 1857 else:
  1858 + with futures.ThreadPoolExecutor(max_workers=1) as executor:
  1859 + future = executor.submit(floodfill.floodfill_threshold, mask, [[x, y, z]], self.t0, self.t1, self.fill_value, bstruct, mask)
  1860 +
  1861 + dlg = wx.ProgressDialog(self._progr_title, self._progr_msg, parent=None, style=wx.PD_APP_MODAL)
  1862 + while not future.done():
  1863 + dlg.Pulse()
  1864 + time.sleep(0.1)
  1865 +
  1866 + dlg.Destroy()
  1867 +
1856 self.viewer.slice_.current_mask.save_history(0, 'VOLUME', self.viewer.slice_.current_mask.matrix.copy(), cp_mask) 1868 self.viewer.slice_.current_mask.save_history(0, 'VOLUME', self.viewer.slice_.current_mask.matrix.copy(), cp_mask)
1857 1869
1858 self.viewer.slice_.buffer_slices['AXIAL'].discard_mask() 1870 self.viewer.slice_.buffer_slices['AXIAL'].discard_mask()
@@ -1912,6 +1924,8 @@ class RemoveMaskPartsInteractorStyle(FloodFillMaskInteractorStyle): @@ -1912,6 +1924,8 @@ class RemoveMaskPartsInteractorStyle(FloodFillMaskInteractorStyle):
1912 self.fill_value = 1 1924 self.fill_value = 1
1913 1925
1914 self._dlg_title = _(u"Remove parts") 1926 self._dlg_title = _(u"Remove parts")
  1927 + self._progr_title = _(u"Remove part")
  1928 + self._progr_msg = _(u"Removing part ...")
1915 1929
1916 1930
1917 def get_style(style): 1931 def get_style(style):
invesalius/gui/dialogs.py
@@ -1851,14 +1851,11 @@ class FFillOptionsDialog(wx.Dialog): @@ -1851,14 +1851,11 @@ class FFillOptionsDialog(wx.Dialog):
1851 self._init_gui() 1851 self._init_gui()
1852 1852
1853 def _init_gui(self): 1853 def _init_gui(self):
1854 - sizer = wx.GridBagSizer(5, 6)  
1855 -  
1856 - flag_labels = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL  
1857 -  
1858 - # self.target = wx.RadioBox(self, -1, "",  
1859 - # choices=[_(u"2D - Actual slice"), _(u"3D - Entire volume")],  
1860 - # style=wx.NO_BORDER | wx.VERTICAL)  
1861 - self.target_2d = wx.RadioButton(self, -1, _(u"2D - Actual slice")) 1854 + """
  1855 + Create the widgets.
  1856 + """
  1857 + # Target
  1858 + self.target_2d = wx.RadioButton(self, -1, _(u"2D - Actual slice"), style=wx.RB_GROUP)
1862 self.target_3d = wx.RadioButton(self, -1, _(u"3D - All slices")) 1859 self.target_3d = wx.RadioButton(self, -1, _(u"3D - All slices"))
1863 1860
1864 if self.config.target == "2D": 1861 if self.config.target == "2D":
@@ -1866,54 +1863,77 @@ class FFillOptionsDialog(wx.Dialog): @@ -1866,54 +1863,77 @@ class FFillOptionsDialog(wx.Dialog):
1866 else: 1863 else:
1867 self.target_3d.SetValue(1) 1864 self.target_3d.SetValue(1)
1868 1865
1869 - choices2d = ["4", "8"]  
1870 - choices3d = ["6", "18", "26"]  
1871 - self.conect2D = wx.RadioBox(self, -1, _(u"2D Connectivity"), choices=choices2d, style=wx.NO_BORDER | wx.HORIZONTAL)  
1872 - self.conect3D = wx.RadioBox(self, -1, _(u"3D Connectivity"), choices=choices3d, style=wx.NO_BORDER | wx.HORIZONTAL) 1866 + # Connectivity 2D
  1867 + self.conect2D_4 = wx.RadioButton(self, -1, "4", style=wx.RB_GROUP)
  1868 + self.conect2D_8 = wx.RadioButton(self, -1, "8")
1873 1869
1874 - try:  
1875 - self.conect2D.SetSelection(choices2d.index(str(self.config.con_2d)))  
1876 - except ValueError:  
1877 - print "ERROR 2D"  
1878 - self.conect2D.SetSelection(0) 1870 + if self.config.con_2d == 8:
  1871 + self.conect2D_8.SetValue(1)
  1872 + else:
  1873 + self.conect2D_4.SetValue(1)
1879 self.config.con_2d = 4 1874 self.config.con_2d = 4
1880 1875
1881 - try:  
1882 - self.conect3D.SetSelection(choices3d.index(str(self.config.con_3d)))  
1883 - except ValueError:  
1884 - print "ERROR 3D"  
1885 - self.conect3D.SetSelection(0)  
1886 - self.config.con_3d = 6 1876 + # Connectivity 3D
  1877 + self.conect3D_6 = wx.RadioButton(self, -1, "6", style=wx.RB_GROUP)
  1878 + self.conect3D_18 = wx.RadioButton(self, -1, "18")
  1879 + self.conect3D_26 = wx.RadioButton(self, -1, "26")
  1880 +
  1881 + if self.config.con_3d == 18:
  1882 + self.conect3D_18.SetValue(1)
  1883 + elif self.config.con_3d == 26:
  1884 + self.conect3D_26.SetValue(1)
  1885 + else:
  1886 + self.conect3D_6.SetValue(1)
  1887 +
  1888 + # Sizer
  1889 + sizer = wx.GridBagSizer(11, 6)
  1890 + sizer.AddStretchSpacer((0, 0))
  1891 +
  1892 + sizer.Add(wx.StaticText(self, -1, _(u"Parameters")), (1, 0), (1, 6), flag=wx.LEFT, border=7)
  1893 + sizer.Add(self.target_2d, (2, 0), (1, 6), flag=wx.LEFT, border=9)
  1894 + sizer.Add(self.target_3d, (3, 0), (1, 6), flag=wx.LEFT, border=9)
  1895 +
  1896 + sizer.AddStretchSpacer((4, 0))
1887 1897
1888 - sizer.Add(wx.StaticText(self, -1, _(u"Parameters")), (0, 0), flag=wx.TOP|wx.LEFT|wx.RIGHT, border=7)  
1889 - sizer.AddStretchSpacer((0, 5))  
1890 - sizer.Add(self.target_2d, (1, 0), (1, 3), flag=wx.LEFT|wx.RIGHT, border=9)  
1891 - sizer.Add(self.target_3d, (2, 0), (1, 3), flag=wx.LEFT|wx.RIGHT, border=9)  
1892 - sizer.Add(self.conect2D, (3, 0), flag=wx.TOP|wx.LEFT|wx.RIGHT, border=9)  
1893 - sizer.Add(self.conect3D, (4, 0), flag=wx.ALL, border=9) 1898 + sizer.Add(wx.StaticText(self, -1, _(u"2D Connectivity")), (5, 0), (1, 6), flag=wx.LEFT, border=9)
  1899 + sizer.Add(self.conect2D_4, (6, 0), flag=wx.LEFT, border=9)
  1900 + sizer.Add(self.conect2D_8, (6, 1), flag=wx.LEFT, border=9)
  1901 +
  1902 + sizer.AddStretchSpacer((7, 0))
  1903 +
  1904 + sizer.Add(wx.StaticText(self, -1, _(u"3D Connectivity")), (8, 0), (1, 6), flag=wx.LEFT, border=9)
  1905 + sizer.Add(self.conect3D_6, (9, 0), flag=wx.LEFT, border=9)
  1906 + sizer.Add(self.conect3D_18, (9, 1), flag=wx.LEFT, border=9)
  1907 + sizer.Add(self.conect3D_26, (9, 2), flag=wx.LEFT, border=9)
  1908 + sizer.AddStretchSpacer((10, 0))
1894 1909
1895 self.SetSizer(sizer) 1910 self.SetSizer(sizer)
1896 sizer.Fit(self) 1911 sizer.Fit(self)
1897 self.Layout() 1912 self.Layout()
1898 1913
1899 - self.Bind(wx.EVT_RADIOBUTTON, self.OnSetTarget)  
1900 - self.conect2D.Bind(wx.EVT_RADIOBOX, self.OnSetCon2D)  
1901 - self.conect3D.Bind(wx.EVT_RADIOBOX, self.OnSetCon3D) 1914 + self.Bind(wx.EVT_RADIOBUTTON, self.OnSetRadio)
1902 self.Bind(wx.EVT_CLOSE, self.OnClose) 1915 self.Bind(wx.EVT_CLOSE, self.OnClose)
1903 1916
1904 - def OnSetTarget(self, evt): 1917 + def OnSetRadio(self, evt):
  1918 + # Target
1905 if self.target_2d.GetValue(): 1919 if self.target_2d.GetValue():
1906 self.config.target = "2D" 1920 self.config.target = "2D"
1907 else: 1921 else:
1908 self.config.target = "3D" 1922 self.config.target = "3D"
1909 1923
1910 - def OnSetCon2D(self, evt):  
1911 - self.config.con_2d = int(self.conect2D.GetStringSelection())  
1912 - print self.config.con_2d 1924 + # 2D
  1925 + if self.conect2D_4.GetValue():
  1926 + self.config.con_2d = 4
  1927 + elif self.conect2D_8.GetValue():
  1928 + self.config.con_2d = 8
1913 1929
1914 - def OnSetCon3D(self, evt):  
1915 - self.config.con_3d = int(self.conect3D.GetStringSelection())  
1916 - print self.config.con_3d 1930 + # 3D
  1931 + if self.conect3D_6.GetValue():
  1932 + self.config.con_3d = 6
  1933 + elif self.conect3D_18.GetValue():
  1934 + self.config.con_3d = 18
  1935 + elif self.conect3D_26.GetValue():
  1936 + self.config.con_3d = 26
1917 1937
1918 def OnClose(self, evt): 1938 def OnClose(self, evt):
1919 if self.config.dlg_visible: 1939 if self.config.dlg_visible: