From 1a15b12cdce9ad70e461fd3177fe10d77d35f52d Mon Sep 17 00:00:00 2001 From: tatiana Date: Tue, 24 Nov 2009 16:43:24 +0000 Subject: [PATCH] ADD: Project close feature (under devel) --- invesalius/constants.py | 8 ++++++++ invesalius/control.py | 38 +++++++++++++++++++++++++++++++++----- invesalius/data/mask.py | 3 ++- invesalius/data/slice_.py | 17 +++++++++++++++-- invesalius/data/surface.py | 15 +++++++++++++-- invesalius/gui/data_notebook.py | 14 +++++++++++++- invesalius/gui/dialogs.py | 6 +----- invesalius/gui/frame.py | 8 +++++++- invesalius/gui/task_slice.py | 13 +++++++++++++ invesalius/gui/task_surface.py | 12 ++++++++++-- invesalius/project.py | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------- invesalius/session.py | 12 +++++++++--- 12 files changed, 183 insertions(+), 74 deletions(-) diff --git a/invesalius/constants.py b/invesalius/constants.py index 6d12b2b..b849763 100644 --- a/invesalius/constants.py +++ b/invesalius/constants.py @@ -85,10 +85,18 @@ SLICE_POSITION = {AXIAL:[AXIAL_SLICE_CAM_VIEW_UP, AXIAL_SLICE_CAM_POSITION], PROJ_NEW = 0 PROJ_OPEN = 1 PROJ_CHANGE = 2 +PROJ_CLOSE = 3 PROJ_MAX = 4 +#### +MODE_RP = 0 +MODE_NAVIGATOR = 1 +MODE_RADIOLOGY = 2 +MODE_ODONTOLOGY = 3 + + #Color Table from Slice #NumberOfColors, SaturationRange, HueRange, ValueRange diff --git a/invesalius/control.py b/invesalius/control.py index e8dc566..847b315 100755 --- a/invesalius/control.py +++ b/invesalius/control.py @@ -27,7 +27,8 @@ import constants as const import project as prj import data.imagedata_utils as utils -import data.surface as surface +import data.mask as msk +import data.surface as srf import data.volume as volume import reader.dicom_grouper as dg import gui.dialogs as dialog @@ -40,7 +41,7 @@ DEFAULT_THRESH_MODE = 0 class Controller(): def __init__(self, frame): - self.surface_manager = surface.SurfaceManager() + self.surface_manager = srf.SurfaceManager() self.volume = volume.Volume() self.__bind_events() self.frame = frame @@ -51,7 +52,6 @@ class Controller(): def __bind_events(self): ps.Publisher().subscribe(self.OnImportMedicalImages, 'Import directory') - #ps.Publisher().subscribe(self.StartImportPanel, "Load data to import panel") ps.Publisher().subscribe(self.OnShowDialogImportDirectory, 'Show import directory dialog') ps.Publisher().subscribe(self.OnShowDialogOpenProject, @@ -68,8 +68,6 @@ class Controller(): ps.Publisher().subscribe(self.Progress, "Update dicom load") ps.Publisher().subscribe(self.OnLoadImportPanel, "End dicom load") ps.Publisher().subscribe(self.OnCancelImport, 'Cancel DICOM load') - #ps.Publisher().subscribe(self.OnSaveProject, 'Save Project') - #ps.Publisher().subscribe(self.OnOpenProject, 'Open Project') ps.Publisher().subscribe(self.OnCloseProject, 'Close Project') @@ -110,6 +108,12 @@ class Controller(): session = ses.Session() session.OpenProject(path) + mask = msk.Mask() + mask._set_class_index(proj.last_mask_index) + + surface = srf.Surface() + surface._set_class_index(proj.last_surface_index) + self.LoadProject() def ShowDialogSaveProject(self, saveas=False): @@ -139,6 +143,26 @@ class Controller(): proj = prj.Project() prj.Project().SavePlistProject(dirpath, filename) + def CloseProject(self): + print "Close Project" + session = ses.Session() + session.CloseProject() + + proj = prj.Project() + proj.Close() + + # TODO: + # Remove items from combo of masks + # Remove items from combo of surfaces + # Remove items from dictionaries + # Slice + # Surface + # -------------- + # + + ps.Publisher().sendMessage('Hide content panel') + + ################################## @@ -348,11 +372,15 @@ class Controller(): answer = dialog.SaveChangesDialog(filename) if not answer: print "Close without changes" + self.CloseProject() elif answer == 1: + self.ShowDialogSaveProject() print "Save changes and close" + self.CloseProject() #else: # print "Cancel" else: print ":) Close without changes" + self.CloseProject() diff --git a/invesalius/data/mask.py b/invesalius/data/mask.py index f40be89..366a188 100644 --- a/invesalius/data/mask.py +++ b/invesalius/data/mask.py @@ -78,4 +78,5 @@ class Mask(): else: setattr(self, key, mask[key]) - + def _set_class_index(self, index): + Mask.general_index = index diff --git a/invesalius/data/slice_.py b/invesalius/data/slice_.py index 5cc6855..f725f1f 100644 --- a/invesalius/data/slice_.py +++ b/invesalius/data/slice_.py @@ -85,6 +85,19 @@ class Slice(object): ps.Publisher().subscribe(self.InputImageWidget, 'Input Image in the widget') ps.Publisher().subscribe(self.OnExportMask,'Export mask to file') + ps.Publisher().subscribe(self.OnCloseProject, 'Close Project') + + def OnCloseProject(self, pubsub_evt): + self.CloseProject() + + def CloseProject(self): + self.imagedata = None + self.current_mask = None + self.blend_filter = None + #self.blend_filter = None + #self.num_gradient = 0 + + def __set_current_mask_threshold_limits(self, pubsub_evt): thresh_min = pubsub_evt.data[0] thresh_max = pubsub_evt.data[1] @@ -523,8 +536,8 @@ class Slice(object): # insert new mask into project and retrieve its index proj = Project() - proj.AddMask(future_mask.index, future_mask) - + index = proj.AddMask(future_mask) + future_mask.index = index # update gui related to mask ps.Publisher().sendMessage('Add mask', diff --git a/invesalius/data/surface.py b/invesalius/data/surface.py index de5b68c..0d6a5e2 100644 --- a/invesalius/data/surface.py +++ b/invesalius/data/surface.py @@ -71,7 +71,8 @@ class Surface(): else: setattr(self, key, surface[key]) - + def _set_class_index(self, index): + Surface.general_index = index # TODO: will be initialized inside control as it is being done? @@ -102,6 +103,15 @@ class SurfaceManager(): ps.Publisher().subscribe(self.OnShowSurface, 'Show surface') ps.Publisher().subscribe(self.OnExportSurface,'Export surface to file') ps.Publisher().subscribe(self.OnLoadSurfaceDict, 'Load surface dict') + ps.Publisher().subscribe(self.OnCloseProject, 'Close Project') + + def OnCloseProject(self, pubsub_evt): + self.CloseProject() + + def CloseProject(self): + del self.actors_dict + self.actors_dict = {} + def OnLoadSurfaceDict(self, pubsub_evt): surface_dict = pubsub_evt.data @@ -291,7 +301,8 @@ class SurfaceManager(): # Append surface into Project.surface_dict proj = prj.Project() - proj.surface_dict[surface.index] = surface + index = proj.AddSurface(surface) + surface.index = index session = ses.Session() diff --git a/invesalius/gui/data_notebook.py b/invesalius/gui/data_notebook.py index 54edbe0..c7a699b 100644 --- a/invesalius/gui/data_notebook.py +++ b/invesalius/gui/data_notebook.py @@ -84,7 +84,13 @@ class MasksListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): 'Change mask colour in notebook') ps.Publisher().subscribe(self.OnChangeCurrentMask, 'Change mask selected') - + ps.Publisher().subscribe(self.OnCloseProject, 'Close Project') + + def OnCloseProject(self, pubsub_evt): + self.DeleteAllItems() + self.mask_list_index = {} + self.mask_bmp_idx_to_name = {} + def OnChangeCurrentMask(self, pubsub_evt): mask_index = pubsub_evt.data @@ -211,6 +217,12 @@ class SurfacesListCtrlPanel(wx.ListCtrl, listmix.TextEditMixin): 'Set surface transparency') ps.Publisher().subscribe(self.EditSurfaceColour, 'Set surface colour') + ps.Publisher().subscribe(self.OnCloseProject, 'Close Project') + + def OnCloseProject(self, pubsub_evt): + self.DeleteAllItems() + self.surface_list_index = {} + self.surface_bmp_idx_to_name = {} def __bind_events_wx(self): self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated) diff --git a/invesalius/gui/dialogs.py b/invesalius/gui/dialogs.py index e4ced68..77461f1 100644 --- a/invesalius/gui/dialogs.py +++ b/invesalius/gui/dialogs.py @@ -132,13 +132,9 @@ WILDCARD_OPEN = "InVesalius 3 project (*.inv3)|*.inv3|"\ def ShowOpenProjectDialog(): # Default system path - if sys.platform == 'win32': - default_path = "" - else: - default_path = os.getcwd() dlg = wx.FileDialog(None, message="Open InVesalius 3 project...", - defaultDir=default_path, + defaultDir="", defaultFile="", wildcard=WILDCARD_OPEN, style=wx.OPEN|wx.CHANGE_DIR) diff --git a/invesalius/gui/frame.py b/invesalius/gui/frame.py index 30ef74e..2811277 100755 --- a/invesalius/gui/frame.py +++ b/invesalius/gui/frame.py @@ -89,7 +89,7 @@ class Frame(wx.Frame): ps.Publisher().subscribe(self.HideImportPanel, 'Hide import panel') ps.Publisher().subscribe(self.BeginBusyCursor, 'Begin busy cursor') ps.Publisher().subscribe(self.EndBusyCursor, 'End busy cursor') - + ps.Publisher().subscribe(self.HideContentPanel, 'Hide content panel') def EndBusyCursor(self, pubsub_evt=None): wx.EndBusyCursor() @@ -209,6 +209,12 @@ class Frame(wx.Frame): aui_manager.GetPane("Tasks").Show(1) aui_manager.Update() + def HideContentPanel(self, pubsub_evt): + aui_manager = self.aui_manager + aui_manager.GetPane("Data").Show(0) + aui_manager.GetPane("Tasks").Show(1) + aui_manager.Update() + def OnSize(self, evt): ps.Publisher().sendMessage(('ProgressBar Reposition')) evt.Skip() diff --git a/invesalius/gui/task_slice.py b/invesalius/gui/task_slice.py index b77331f..da799b4 100644 --- a/invesalius/gui/task_slice.py +++ b/invesalius/gui/task_slice.py @@ -291,6 +291,19 @@ class MaskProperties(wx.Panel): 'Set threshold values in gradient') ps.Publisher().subscribe(self.SelectMaskName, 'Select mask name in combo') ps.Publisher().subscribe(self.ChangeMaskName, 'Change mask name') + ps.Publisher().subscribe(self.OnCloseProject, 'Close Project') + + def OnCloseProject(self, pubsub_evt): + self.CloseProject() + + def CloseProject(self): + n = self.combo_mask_name.GetCount() + for i in xrange(n-1, -1, -1): + self.combo_mask_name.Delete(i) + n = self.combo_thresh.GetCount() + for i in xrange(n-1, -1, -1): + self.combo_thresh.Delete(i) + def __bind_events_wx(self): self.Bind(grad.EVT_THRESHOLD_CHANGE, self.OnSlideChanged, self.gradient) diff --git a/invesalius/gui/task_surface.py b/invesalius/gui/task_surface.py index 2e62406..bbe472f 100644 --- a/invesalius/gui/task_surface.py +++ b/invesalius/gui/task_surface.py @@ -339,11 +339,19 @@ class SurfaceProperties(wx.Panel): def __bind_events(self): ps.Publisher().subscribe(self.InsertNewSurface, 'Update surface info in GUI') - ps.Publisher().subscribe(self.ChangeMaskName, + ps.Publisher().subscribe(self.ChangeSurfaceName, 'Change surface name') + ps.Publisher().subscribe(self.OnCloseProject, 'Close Project') + def OnCloseProject(self, pubsub_evt): + self.CloseProject() - def ChangeMaskName(self, pubsub_evt): + def CloseProject(self): + n = self.combo_surface_name.GetCount() + for i in xrange(n-1, -1, -1): + self.combo_surface_name.Delete(i) + + def ChangeSurfaceName(self, pubsub_evt): index, name = pubsub_evt.data self.combo_surface_name.SetString(index, name) self.combo_surface_name.Refresh() diff --git a/invesalius/project.py b/invesalius/project.py index 1eae61f..2537117 100755 --- a/invesalius/project.py +++ b/invesalius/project.py @@ -43,80 +43,61 @@ class Project(object): __metaclass__= Singleton def __init__(self): - # TODO: Discuss - # [Tati] Will this type of data be written on project file? What if user - # changes file name and directory? I guess no... But, who knows... - #self.name = "Default" - #self.dir_ = "C:\\" - - # Original vtkImageData, build based on medical images read. - # To be used for general 2D slices rendering both on 2D and 3D - # coordinate systems. It might be used, as well, for 3D raycasting. - # rendering. - # TODO: Discuss when this will be used. - self.imagedata = '' - + # Patient/ acquistion information self.name = '' #self.dicom = '' self.modality = '' - self.original_orientation = -1 - - # Masks are related to vtkImageData - self.mask_dict = {} - # Predefined threshold values + self.original_orientation = '' self.min_threshold = '' self.max_threshold = '' - self.window = '' self.level = '' + # Original imagedata (shouldn't be changed) + self.imagedata = '' + + # Masks (vtkImageData) + self.mask_dict = {} + self.last_mask_index = 0 + + # Surfaces are (vtkPolyData) + self.surface_dict = {} + self.last_surface_index = -1 + + # TODO: Future + self.measure_dict = {} + + # TODO: Future ++ + self.annotation_dict = {} + + # InVesalius related data + # So we can find bugs and reproduce user-related problems + self.invesalius_version = version.get_svn_revision() + self.presets = Presets() + self.threshold_modes = self.presets.thresh_ct self.threshold_range = '' - - self.original_orientation = '' - # MRI ? CT? + self.raycasting_preset = '' - # TODO: define how we will relate these threshold values to - # default threshold labels - # TODO: Future + - # Allow insertion of new threshold modes - # Surfaces are related to vtkPolyDataa - self.surface_dict = {} #self.surface_quality_list = ["Low", "Medium", "High", "Optimal *", - # "Custom"] + # "Custom"i] + # TOOD: define how we will relate this quality possibilities to # values set as decimate / smooth # TODO: Future + # Allow insertion of new surface quality modes - self.measure_dict = {} + def Close(self): + for name in self.__dict__: + attr = getattr(self, name) + del attr - # TODO: Future ++ - #self.annotation_dict = {} + self.__init__() - # TODO: Future + - # Volume rendering modes related to vtkImageData - # this will need to be inserted both in the project and in the user - # InVesalius configuration file - # self.render_mode = {} - - # The raycasting preset setted in this project - self.raycasting_preset = '' - - self.invesalius_version = version.get_svn_revision() - print self.invesalius_version - - #self.save_as = True - - #self.path = "" - self.debug = 0 - - ####### MASK OPERATIONS - - def AddMask(self, index, mask): + def AddMask(self, mask): """ Insert new mask (Mask) into project data. @@ -126,11 +107,37 @@ class Project(object): output @ index: index of item that was inserted """ + self.last_mask_index = mask.index + index = len(self.mask_dict) self.mask_dict[index] = mask + return index + + def RemoveMask(self, index): + new_dict = {} + for i in self.mask_dict: + if i < index: + new_dict[i] = self.mask_dict[i] + if i > index: + new_dict[i-1] = self.mask_dict[i] + self.mask_dict = new_dict def GetMask(self, index): return self.mask_dict[index] + def AddSurface(self, surface): + self.last_surface_index = surface.index + index = len(self.surface_dict) + self.surface_dict[index] = surface + return index + + def RemoveSurface(self, index): + new_dict = {} + for i in self.surface_dict: + if i < index: + new_dict[i] = self.surface_dict[i] + if i > index: + new_dict[i-1] = self.surface_dict[i] + self.surface_dict = new_dict def SetAcquisitionModality(self, type_=None): if type_ is None: diff --git a/invesalius/session.py b/invesalius/session.py index 5036ba4..a60c8b9 100644 --- a/invesalius/session.py +++ b/invesalius/session.py @@ -11,10 +11,11 @@ class Session(object): def __init__(self): self.project_path = () - self.project_status = const.PROJ_NEW - # const.PROJ_NEW*, const.PROJ_OPEN, const.PROJ_CHANGE* + self.project_status = const.PROJ_CLOSE + # const.PROJ_NEW*, const.PROJ_OPEN, const.PROJ_CHANGE*, + # const.PROJ_CLOSE - self.mode = "" + self.mode = const.MODE_RP # const.MODE_RP, const.MODE_NAVIGATOR, const.MODE_RADIOLOGY, # const.MODE_ODONTOLOGY @@ -30,6 +31,11 @@ class Session(object): # Recent projects list self.recent_projects = [] + def CloseProject(self): + self.project_path = () + self.project_status = const.PROJ_CLOSE + self.mode = const.MODE_RP + self.temp_item = False def SaveProject(self, path=()): self.project_status = const.PROJ_OPEN -- libgit2 0.21.2