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 22 import tempfile
23 23 import time
24 24  
  25 +from concurrent import futures
  26 +
25 27 import vtk
26 28 import wx
27 29  
... ... @@ -1779,6 +1781,8 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle):
1779 1781 self.fill_value = 254
1780 1782  
1781 1783 self._dlg_title = _(u"Fill holes")
  1784 + self._progr_title = _(u"Fill hole")
  1785 + self._progr_msg = _(u"Filling hole ...")
1782 1786  
1783 1787 self.AddObserver("LeftButtonPressEvent", self.OnFFClick)
1784 1788  
... ... @@ -1837,10 +1841,8 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle):
1837 1841 bstruct = np.zeros((3, 3, 1), dtype='uint8')
1838 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 1844 if self.config.target == '2D':
  1845 + floodfill.floodfill_threshold(mask, [[x, y, z]], self.t0, self.t1, self.fill_value, bstruct, mask)
1844 1846 b_mask = self.viewer.slice_.buffer_slices[self.orientation].mask
1845 1847 index = self.viewer.slice_.buffer_slices[self.orientation].index
1846 1848  
... ... @@ -1853,6 +1855,16 @@ class FloodFillMaskInteractorStyle(DefaultInteractorStyle):
1853 1855  
1854 1856 self.viewer.slice_.current_mask.save_history(index, self.orientation, p_mask, b_mask)
1855 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 1868 self.viewer.slice_.current_mask.save_history(0, 'VOLUME', self.viewer.slice_.current_mask.matrix.copy(), cp_mask)
1857 1869  
1858 1870 self.viewer.slice_.buffer_slices['AXIAL'].discard_mask()
... ... @@ -1912,6 +1924,8 @@ class RemoveMaskPartsInteractorStyle(FloodFillMaskInteractorStyle):
1912 1924 self.fill_value = 1
1913 1925  
1914 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 1931 def get_style(style):
... ...
invesalius/gui/dialogs.py
... ... @@ -1851,14 +1851,11 @@ class FFillOptionsDialog(wx.Dialog):
1851 1851 self._init_gui()
1852 1852  
1853 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 1859 self.target_3d = wx.RadioButton(self, -1, _(u"3D - All slices"))
1863 1860  
1864 1861 if self.config.target == "2D":
... ... @@ -1866,54 +1863,77 @@ class FFillOptionsDialog(wx.Dialog):
1866 1863 else:
1867 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 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 1910 self.SetSizer(sizer)
1896 1911 sizer.Fit(self)
1897 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 1915 self.Bind(wx.EVT_CLOSE, self.OnClose)
1903 1916  
1904   - def OnSetTarget(self, evt):
  1917 + def OnSetRadio(self, evt):
  1918 + # Target
1905 1919 if self.target_2d.GetValue():
1906 1920 self.config.target = "2D"
1907 1921 else:
1908 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 1938 def OnClose(self, evt):
1919 1939 if self.config.dlg_visible:
... ...