예제 #1
0
    def UpdateThresholdModes(self, threshold_range):
        thresh_min, thresh_max = threshold_range
        presets_list = (self.thresh_ct, self.thresh_mri)

        for presets in presets_list:
            for key in presets:
                (t_min, t_max) = presets[key]

                print(key, t_min, t_max)

                if (t_min is None) or (t_max is None):  # setting custom preset
                    t_min = thresh_min
                    t_max = thresh_max
                if (t_min < thresh_min):
                    t_min = thresh_min
                if (t_max > thresh_max):
                    t_max = thresh_max

                # This has happened in Analyze files
                # TODO: find a good solution for presets in Analyze files
                if (t_min > thresh_max):
                    t_min = thresh_min
                if (t_max < thresh_min):
                    t_max = thresh_max

                presets[key] = (t_min, t_max)

        Publisher.sendMessage('Update threshold limits',
                              threshold_range=(thresh_min, thresh_max))
예제 #2
0
def ReadBitmap(filepath):
    t = VerifyDataType(filepath)

    if _has_win32api:
        filepath = win32api.GetShortPathName(filepath)

    if t == False:
        try:
            measures_info = GetPixelSpacingFromInfoFile(filepath)
        except UnicodeDecodeError:
            measures_info = False
        if measures_info:
            Publisher.sendMessage("Set bitmap spacing", spacing=measures_info)

        return False

    img_array = VtkRead(filepath, t)

    if not (isinstance(img_array, numpy.ndarray)):

        no_error = True

        img_array = ScipyRead(filepath)

        if not (isinstance(img_array, numpy.ndarray)):
            return False

    return img_array
예제 #3
0
 def OnComboBrushOp(self, evt):
     brush_op_id = evt.GetSelection()
     Publisher.sendMessage('Set edition operation', operation=brush_op_id)
     if brush_op_id == const.BRUSH_THRESH:
         self.gradient_thresh.Enable()
     else:
         self.gradient_thresh.Disable()
예제 #4
0
    def OnRemove(self, surface_indexes):
        proj = prj.Project()

        old_dict = self.actors_dict
        new_dict = {}
        if surface_indexes:
            for index in surface_indexes:
                proj.RemoveSurface(index)
                if index in old_dict:
                    actor = old_dict[index]
                    for i in old_dict:
                        if i < index:
                            new_dict[i] = old_dict[i]
                        if i > index:
                            new_dict[i - 1] = old_dict[i]
                    old_dict = new_dict
                    Publisher.sendMessage('Remove surface actor from viewer',
                                          actor=actor)
            self.actors_dict = new_dict

        if self.last_surface_index in surface_indexes:
            if self.actors_dict:
                self.last_surface_index = 0
            else:
                self.last_surface_index = None
예제 #5
0
 def OnSlideChanging(self, evt):
     thresh_min = self.gradient.GetMinValue()
     thresh_max = self.gradient.GetMaxValue()
     Publisher.sendMessage('Changing threshold values',
                           threshold_range=(thresh_min, thresh_max))
     session = ses.Session()
     session.ChangeProject()
예제 #6
0
 def OnBrushSize(self, evt):
     """ """
     # FIXME: Using wx.EVT_SPINCTRL in MacOS it doesnt capture changes only
     # in the text ctrl - so we are capturing only changes on text
     # Strangelly this is being called twice
     Publisher.sendMessage('Set edition brush size',
                           size=self.spin.GetValue())
예제 #7
0
    def OnLinkNewMask(self, evt=None):

        try:
            evt.data
            evt = None
        except:
            pass

        dialog = dlg.NewMask()

        try:
            if dialog.ShowModal() == wx.ID_OK:
                ok = 1
            else:
                ok = 0
        except (wx._core.PyAssertionError):  #TODO FIX: win64
            ok = 1

        if ok:
            mask_name, thresh, colour = dialog.GetValue()
            if mask_name:
                Publisher.sendMessage('Create new mask',
                                      mask_name=mask_name,
                                      thresh=thresh,
                                      colour=colour)
        dialog.Destroy()
예제 #8
0
    def OnFoldPressCaption(self, evt):
        id = evt.GetTag().GetId()
        closed = evt.GetFoldStatus()

        if self.__id_editor == id:
            if closed:
                Publisher.sendMessage('Disable style',
                                      style=const.SLICE_STATE_EDITOR)
                self.last_style = None
            else:
                Publisher.sendMessage('Enable style',
                                      style=const.SLICE_STATE_EDITOR)
                self.last_style = const.SLICE_STATE_EDITOR
        elif self.__id_watershed == id:
            if closed:
                Publisher.sendMessage('Disable style',
                                      style=const.SLICE_STATE_WATERSHED)
                self.last_style = None
            else:
                Publisher.sendMessage('Enable style',
                                      style=const.SLICE_STATE_WATERSHED)
                #  Publisher.sendMessage('Show help message', 'Mark the object and the background')
                self.last_style = const.SLICE_STATE_WATERSHED
        else:
            Publisher.sendMessage('Disable style',
                                  style=const.SLICE_STATE_EDITOR)
            self.last_style = None

        evt.Skip()
        wx.CallAfter(self.ResizeFPB)
예제 #9
0
    def OnLinkExportMask(self, evt=None):
        project = proj.Project()
        if sys.platform == 'win32':
            project_name = project.name
        else:
            project_name = project.name + ".vti"

        dlg = wx.FileDialog(
            None,
            "Save mask as...",  # title
            "",  # last used directory
            project_name,  # filename
            WILDCARD_SAVE_MASK,
            wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
        dlg.SetFilterIndex(0)  # default is VTI

        if dlg.ShowModal() == wx.ID_OK:
            filename = dlg.GetPath()
            extension = "vti"
            if sys.platform != 'win32':
                if filename.split(".")[-1] != extension:
                    filename = filename + "." + extension
            filetype = const.FILETYPE_IMAGEDATA
            Publisher.sendMessage('Export mask to file',
                                  filename=filename,
                                  filetype=filetype)
예제 #10
0
    def __init__(self, size=50):
        self.history = []
        self.index = -1
        self.size = size * 2

        Publisher.sendMessage("Enable undo", value=False)
        Publisher.sendMessage("Enable redo", value=False)
예제 #11
0
 def on_show(self):
     self.history._config_undo_redo(self.is_shown)
     if ses.Session().mask_3d_preview:
         Publisher.sendMessage('Show mask preview',
                               index=self.index,
                               flag=bool(self.is_shown))
         Publisher.sendMessage("Render volume viewer")
예제 #12
0
    def UpdateSurfaceInterpolation(self):
        interpolation = int(ses.Session().surface_interpolation)
        key_actors = self.actors_dict.keys()

        for key in self.actors_dict:
            self.actors_dict[key].GetProperty().SetInterpolation(interpolation)
        Publisher.sendMessage('Render volume viewer')
예제 #13
0
    def OnMenuView(self, evt):
        """Events from button menus."""
        bmp = wx.Bitmap(ID_TO_BMP[evt.GetId()][1], wx.BITMAP_TYPE_PNG)
        self.button_view.SetBitmapSelected(bmp)

        Publisher.sendMessage('Set volume view angle', view=evt.GetId())
        self.Refresh()
예제 #14
0
 def OnSetRelativeWindowLevel(self, diff_wl, diff_ww):
     ww = self.ww + diff_ww
     wl = self.wl + diff_wl
     Publisher.sendMessage('Set volume window and level text', ww=ww, wl=wl)
     self.SetWWWL(ww, wl)
     self.ww = ww
     self.wl = wl
예제 #15
0
 def OnEditLabel(self, evt):
     if not evt.IsEditCancelled():
         index = evt.GetIndex()
         self.SetItem(index, 1, evt.GetLabel())
         Publisher.sendMessage('Change mask name',
                               index=evt.GetIndex(), name=evt.GetLabel())
     evt.Skip()
예제 #16
0
    def _midi_to_pedal(self, msg):
        # TODO: At this stage, interpret all note_on messages as the pedal being pressed,
        #       and note_off messages as the pedal being released. Later, use the correct
        #       message types and be more stringent about the messages.
        #
        if msg.type == 'note_on':
            state = True

        elif msg.type == 'note_off':
            state = False

        else:
            print("Unknown message type received from MIDI device")
            return

        Publisher.sendMessage('Pedal state changed', state=state)
        for callback_info in self._callback_infos:
            callback = callback_info['callback']
            callback(state)

        if not state:
            self._callback_infos = [
                callback_info for callback_info in self._callback_infos
                if not callback_info['remove_when_released']
            ]
예제 #17
0
 def CleanUp(self):
     Publisher.sendMessage('Toggle toolbar item',
                           _id=self.state_code,
                           value=False)
     self.viewer.on_wl = True
     self.viewer.text.Hide()
     self.viewer.interactor.Render()
예제 #18
0
    def ImportMedicalImages(self, directory, gui=True):
        patients_groups = dcm.GetDicomGroups(directory)
        name = directory.rpartition('\\')[-1].split('.')

        if len(patients_groups):
            # OPTION 1: DICOM
            group = dcm.SelectLargerDicomGroup(patients_groups)
            matrix, matrix_filename, dicom = self.OpenDicomGroup(group,
                                                                 0, [0, 0],
                                                                 gui=gui)
            if matrix is None:
                return
            self.CreateDicomProject(dicom, matrix, matrix_filename)
        else:
            # OPTION 2: NIfTI, Analyze or PAR/REC
            if name[-1] == 'gz':
                name[1] = 'nii.gz'

            suptype = ('hdr', 'nii', 'nii.gz', 'par')
            filetype = name[1].lower()

            if filetype in suptype:
                group = oth.ReadOthers(directory)
            else:
                utils.debug("No medical images found on given directory")
                return

            if group:
                matrix, matrix_filename = self.OpenOtherFiles(group)
                self.CreateOtherProject(str(name[0]), matrix, matrix_filename)
            # OPTION 4: Nothing...

        self.LoadProject()
        Publisher.sendMessage("Enable state project", state=True)
예제 #19
0
    def OpenBitmapFiles(self, bmp_data, rec_data):
        name = rec_data[0]
        orientation = rec_data[1]
        sp_x = float(rec_data[2])
        sp_y = float(rec_data[3])
        sp_z = float(rec_data[4])
        interval = int(rec_data[5])

        interval += 1

        filelist = bmp_data.GetOnlyBitmapPath()[::interval]
        bits = bmp_data.GetFirstPixelSize()

        sx, sy = size = bmp_data.GetFirstBitmapSize()
        n_slices = len(filelist)
        resolution_percentage = utils.calculate_resizing_tofitmemory(
            int(sx), int(sy), n_slices, bits / 8)

        zspacing = sp_z * interval
        xyspacing = (sp_y, sp_x)

        if resolution_percentage < 1.0:

            re_dialog = dialog.ResizeImageDialog()
            re_dialog.SetValue(int(resolution_percentage * 100))
            re_dialog_value = re_dialog.ShowModal()
            re_dialog.Close()

            if re_dialog_value == wx.ID_OK:
                percentage = re_dialog.GetValue()
                resolution_percentage = percentage / 100.0
            else:
                return

        xyspacing = xyspacing[0] / resolution_percentage, xyspacing[
            1] / resolution_percentage

        self.matrix, scalar_range, self.filename = image_utils.bitmap2memmap(
            filelist, size, orientation, (sp_z, sp_y, sp_x),
            resolution_percentage)

        self.Slice = sl.Slice()
        self.Slice.matrix = self.matrix
        self.Slice.matrix_filename = self.filename

        if orientation == 'AXIAL':
            self.Slice.spacing = xyspacing[0], xyspacing[1], zspacing
        elif orientation == 'CORONAL':
            self.Slice.spacing = xyspacing[0], zspacing, xyspacing[1]
        elif orientation == 'SAGITTAL':
            self.Slice.spacing = zspacing, xyspacing[1], xyspacing[0]

        self.Slice.window_level = float(self.matrix.max() / 4)
        self.Slice.window_width = float(self.matrix.max())

        scalar_range = int(self.matrix.min()), int(self.matrix.max())
        Publisher.sendMessage('Update threshold limits list',
                              threshold_range=scalar_range)

        return self.matrix, self.filename  #, dicom
예제 #20
0
 def disable_mask_preview(self):
     ses.Session().mask_3d_preview = False
     mask = self.Slice.current_mask
     if mask is not None:
         Publisher.sendMessage("Remove mask preview",
                               mask_3d_actor=mask.volume._actor)
         Publisher.sendMessage("Render volume viewer")
예제 #21
0
    def SaveProject(self, path=None, compress=False):
        Publisher.sendMessage('Begin busy cursor')
        session = ses.Session()
        if path:
            dirpath, filename = os.path.split(path)
        else:
            dirpath, filename = session.project_path

        if isinstance(filename, str):
            filename = utils.decode(filename, const.FS_ENCODE)

        proj = prj.Project()
        try:
            prj.Project().SavePlistProject(dirpath, filename, compress)
        except PermissionError as err:
            if wx.GetApp() is None:
                print(
                    "Error: Permission denied, you don't have permission to write at {}"
                    .format(dirpath))
            else:
                dlg = dialogs.ErrorMessageBox(
                    None, "Save project error",
                    "It was not possible to save because you don't have permission to write at {}\n{}"
                    .format(dirpath, err))
                dlg.ShowModal()
                dlg.Destroy()
        else:
            session.SaveProject((dirpath, filename))

        Publisher.sendMessage('End busy cursor')
예제 #22
0
 def OnDuplicate(self):
     selected_items = self.parent.listctrl.GetSelected()
     if selected_items:
         Publisher.sendMessage('Duplicate surfaces',
                               surface_indexes=selected_items)
     else:
         dlg.SurfaceSelectionRequiredForDuplication()
예제 #23
0
 def OnDuplicate(self):
     selected_items = self.parent.listctrl.GetSelected()
     if selected_items:
         Publisher.sendMessage('Duplicate masks',
                               mask_indexes=selected_items)
     else:
         dlg.MaskSelectionRequiredForDuplication()
예제 #24
0
    def RemoveMeasurements(self):
        """
        Remove items selected.
        """
        # it is necessary to update internal dictionary
        # that maps bitmap given item index
        selected_items = self.GetSelected()
        selected_items.sort(reverse=True)

        old_dict = self._list_index
        if selected_items:
            for index in selected_items:
                new_dict = {}
                self.DeleteItem(index)
                for i in old_dict:
                    if i < index:
                        new_dict[i] = old_dict[i]
                    if i > index:
                        new_dict[i - 1] = old_dict[i]
                old_dict = new_dict
            self._list_index = new_dict
            Publisher.sendMessage('Remove measurements',
                                  indexes=selected_items)
        else:
            dlg.MeasureSelectionRequiredForRemoval()
예제 #25
0
    def StopNavigation(self):
        self.event.set()

        if self.pedal_connection is not None:
            self.pedal_connection.remove_callback(name='navigation')

        self.coord_queue.clear()
        self.coord_queue.join()

        if self.serial_port_connection is not None:
            self.serial_port_connection.join()

        if self.serial_port_in_use:
            self.serial_port_queue.clear()
            self.serial_port_queue.join()

        if self.view_tracts:
            self.coord_tracts_queue.clear()
            self.coord_tracts_queue.join()

            self.tracts_queue.clear()
            self.tracts_queue.join()

        vis_components = [
            self.serial_port_in_use, self.view_tracts, self.peel_loaded
        ]
        Publisher.sendMessage("Navigation status",
                              nav_status=False,
                              vis_status=vis_components)
예제 #26
0
    def find_plugins(self):
        self.plugins = {}
        for p in chain(
                glob.glob(str(
                    inv_paths.PLUGIN_DIRECTORY.joinpath("**/plugin.json")),
                          recursive=True),
                glob.glob(str(
                    inv_paths.USER_PLUGINS_DIRECTORY.joinpath(
                        "**/plugin.json")),
                          recursive=True),
        ):
            try:
                p = pathlib.Path(p)
                with p.open() as f:
                    jdict = json.load(f)
                    plugin_name = jdict["name"]
                    plugin_description = jdict["description"]
                    enable_startup = jdict.get("enable-startup", False)

                    self.plugins[plugin_name] = {
                        "name": plugin_name,
                        "description": plugin_description,
                        "folder": p.parent,
                        "enable_startup": enable_startup,
                    }
            except Exception as err:
                print("It was not possible to load plugin. Error: {}".format(
                    err))

        Publisher.sendMessage("Add plugins menu items", items=self.plugins)
예제 #27
0
 def SetUp(self):
     Publisher.sendMessage('Toggle toolbar item',
                           _id=self.state_code,
                           value=True)
     self.viewer.on_wl = True
     if self.viewer.raycasting_volume:
         self.viewer.text.Show()
         self.viewer.interactor.Render()
예제 #28
0
    def _check_disconnected(self):
        if self._midi_in is not None:
            if self._active_input not in self._midi_inputs:
                self._midi_in = None

                Publisher.sendMessage('Pedal connection', state=False)

                print("Disconnected from MIDI device")
예제 #29
0
 def OnOpenMesh(self):
     filename = dlg.ShowImportMeshFilesDialog()
     if filename:
         if not np.allclose(slice_.Slice().affine, np.eye(4)):
             convert_to_inv = dlg.ImportMeshCoordSystem()
             Publisher.sendMessage('Update convert_to_inv flag',
                                   convert_to_inv=convert_to_inv)
         Publisher.sendMessage('Import surface file', filename=filename)
예제 #30
0
 def SetActorColour(self, surface_index, colour):
     """
     """
     self.actors_dict[surface_index].GetProperty().SetColor(colour[:3])
     # Update value in project's surface_dict
     proj = prj.Project()
     proj.surface_dict[surface_index].colour = colour
     Publisher.sendMessage('Render volume viewer')