Example #1
0
    def OnButtonNextTask(self, evt):
        overwrite = self.check_box.IsChecked()
        algorithm = 'Default'
        options = {}
        to_generate = True
        if self.GetMaskSelected() != -1:
            sl = slice_.Slice()
            if sl.current_mask.was_edited:
                dlgs = dlg.SurfaceDialog()
                if dlgs.ShowModal() == wx.ID_OK:
                    algorithm = dlgs.GetAlgorithmSelected()
                    options = dlgs.GetOptions()
                else:
                    to_generate = False

                dlgs.Destroy()

            if to_generate:
                mask_index = sl.current_mask.index
                method = {'algorithm': algorithm,
                          'options': options}
                srf_options = {"index": mask_index,
                               "name": '',
                               "quality": _('Optimal *'),
                               "fill": False,
                               "keep_largest": False,
                               "overwrite": overwrite}

                Publisher.sendMessage('Create surface from index',
                                      {'method': method, 'options': srf_options})
                Publisher.sendMessage('Fold surface task')

        else:
            dlg.InexistentMask()
Example #2
0
 def OnClutChange(self, evt):
     Publisher.sendMessage(
         'Change colour table from background image from widget',
         evt.GetNodes())
     slc = sl.Slice()
     Publisher.sendMessage('Update window level value',
                           (slc.window_width, slc.window_level))
Example #3
0
    def OnButtonInfo(self, evt):
        sl = slice_.Slice()
        overlay_data = sl.overlay

        if overlay_data is not None:
            ovdlg = dlg.OverlayDialog(overlay_data)
            ovdlg.Show()
Example #4
0
    def OnOpenOverlay(self, pubsub_evt):
        dirpath = dialog.ShowOpenNiftiDialog()
        nifti_image = nifti.ReadNifti(dirpath)

        if nifti_image:
            # Rearranges the axes of the image to be closest to RAS+ orientation,
            # so the slices of the image (axial, coronal, sagittal) are shown correctly.
            # See http://nipy.org/nibabel/image_orientation.html
            nifti_image = as_closest_canonical(nifti_image)

            imagedata = nifti_image.get_data()

            # Conversion of type of numpy array (to unsigned char)
            imagedata = imagedata.astype('f')

            slc = sl.Slice()
            y, x = slc.buffer_slices["AXIAL"].image.shape
            z = slc.buffer_slices["SAGITAL"].image.shape[0]

            # Add borders (with zero values) to overlay array to fit the dimensions of the 3D image
            pad_x = numpy.abs((x / 2.0) - (imagedata.shape[0] / 2.0))
            pad_y = numpy.abs((y / 2.0) - (imagedata.shape[1] / 2.0))
            pad_z = numpy.abs((z / 2.0) - (imagedata.shape[2] / 2.0))
            final_overlay = numpy.pad(imagedata,
                                      ((pad_x, pad_x), (pad_y, pad_y),
                                       (pad_z, pad_z)),
                                      mode='constant',
                                      constant_values=0)

            # Modifications to work with Invesalius (Z,Y,X)
            final_overlay = numpy.swapaxes(final_overlay, 0, 2)
            final_overlay = numpy.fliplr(final_overlay)

            Publisher.sendMessage('Set slice overlay', final_overlay)
Example #5
0
    def LoadProject(self):
        proj = prj.Project()
        
        const.THRESHOLD_OUTVALUE = proj.threshold_range[0]
        const.THRESHOLD_INVALUE = proj.threshold_range[1]

        const.WINDOW_LEVEL[_('Default')] = (proj.window, proj.level)
        const.WINDOW_LEVEL[_('Manual')] = (proj.window, proj.level)

        self.Slice = sl.Slice()
        self.Slice.spacing = proj.spacing

        Publisher.sendMessage('Load slice to viewer',
                        (proj.mask_dict))

        
        Publisher.sendMessage('Load slice plane') 

        Publisher.sendMessage('Bright and contrast adjustment image',\
                                   (proj.window, proj.level))
        Publisher.sendMessage('Update window level value',\
                                    (proj.window, proj.level))

        Publisher.sendMessage('Set project name', proj.name)
        Publisher.sendMessage('Load surface dict',
                                    proj.surface_dict)
        Publisher.sendMessage('Hide surface items',
                                     proj.surface_dict)
        self.LoadImagedataInfo() # TODO: where do we insert this <<<?
        
        Publisher.sendMessage('Show content panel')
        Publisher.sendMessage('Update AUI')

        if len(proj.mask_dict):
            mask_index = len(proj.mask_dict) -1
            for m in proj.mask_dict.values():
                Publisher.sendMessage('Add mask',
                                           (m.index, m.name,
                                            m.threshold_range, m.colour))
            self.Slice.current_mask = proj.mask_dict[mask_index]
            Publisher.sendMessage('Show mask', (mask_index, True))
        else:
            mask_name = const.MASK_NAME_PATTERN % (1,)
            thresh = const.THRESHOLD_RANGE
            colour = const.MASK_COLOUR[0]

            Publisher.sendMessage('Create new mask',
                                       (mask_name, thresh, colour))

        Publisher.sendMessage('Load measurement dict',
                                    (proj.measurement_dict, self.Slice.spacing))

        Publisher.sendMessage(('Set scroll position', 'AXIAL'),proj.matrix_shape[0]/2)
        Publisher.sendMessage(('Set scroll position', 'SAGITAL'),proj.matrix_shape[1]/2)
        Publisher.sendMessage(('Set scroll position', 'CORONAL'),proj.matrix_shape[2]/2)
        
        Publisher.sendMessage('End busy cursor')
Example #6
0
    def UpdateWindowLevelValue(self, pubsub_evt):
        window, level = pubsub_evt.data
        self.acum_achange_window, self.acum_achange_level = (window, level)
        self.SetWLText(window, level)

        slc = sl.Slice()
        slc._update_wwwl_widget_nodes(window, level)

        Publisher.sendMessage('Update all slice')
        Publisher.sendMessage('Update clut imagedata widget')
Example #7
0
    def SetLayout(self, layout):
        self.layout = layout
        if (layout == (1, 1)) and self.on_text:
            self.ShowTextActors()
        else:
            self.HideTextActors(change_status=False)

        slice_ = sl.Slice()
        self.LoadRenderers(slice_.GetOutput())
        self.__configure_renderers()
        self.__configure_scroll()
Example #8
0
    def SetInput(self, mask_dict):
        self.slice_ = sl.Slice()

        max_slice_number = sl.Slice().GetNumberOfSlices(self.orientation)
        self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number,
                                 max_slice_number)

        self.slice_data = self.create_slice_window()
        self.slice_data.SetCursor(self.__create_cursor())
        self.cam = self.slice_data.renderer.GetActiveCamera()
        self.__build_cross_lines()

        # Set the slice number to the last slice to ensure the camera is far
        # enough to show all slices.
        self.set_slice_number(max_slice_number - 1)
        self.__update_camera()
        self.slice_data.renderer.ResetCamera()
        self.interactor.GetRenderWindow().AddRenderer(self.slice_data.renderer)
        self.interactor.Render()

        self.EnableText()
        self.wl_text.Hide()
        ## Insert cursor
        self.SetInteractorStyle(const.STATE_DEFAULT)
Example #9
0
    def OnNew(self):
        sl = slice_.Slice()
        dialog = dlg.SurfaceCreationDialog(
            None, -1, _('New surface'), mask_edited=sl.current_mask.was_edited)
        try:
            if dialog.ShowModal() == wx.ID_OK:
                ok = 1
            else:
                ok = 0
        except (wx._core.PyAssertionError):  #TODO FIX: win64
            ok = 1

        if ok:
            surface_options = dialog.GetValue()

            Publisher.sendMessage('Create surface from index', surface_options)
        dialog.Destroy()
Example #10
0
    def OnLinkNewSurface(self, evt=None):
        #import gui.dialogs as dlg
        sl = slice_.Slice()
        dialog = dlg.SurfaceCreationDialog(None, -1,
                            _('New surface'),
                            mask_edited=sl.current_mask.was_edited)

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

        if (ok):
            ## Retrieve information from dialog
            #(mask_index, surface_name, surface_quality, fill_holes,\
            #keep_largest) = dialog.GetValue()

            ## Retrieve information from mask
            #proj = prj.Project()
            #mask = proj.mask_dict[mask_index]

            ## Send all information so surface can be created
            #surface_data = [proj.imagedata,
                            #mask.colour,
                            #mask.threshold_range,
                            #mask.edited_points,
                            #False, # overwrite
                            #surface_name,
                            #surface_quality,
                            #fill_holes,
                            #keep_largest]


            surface_options = dialog.GetValue()

            Publisher.sendMessage('Create surface from index', surface_options)
        dialog.Destroy()
        if evt:
            evt.Skip()
Example #11
0
    def CreateNiftiProject(self, imagedata):
        header = imagedata.get_header()
        proj = prj.Project()
        proj.imagedata = None
        proj.name = _("Untitled")
        proj.SetAcquisitionModality("MRI")
        #TODO: Verify if all Nifti are in AXIAL orientation

        # To get  Z, X, Y (used by InVesalius), not X, Y, Z
        matrix, matrix_filename = image_utils.nifti2mmap(imagedata)
        #         if header['orient'] == 0:
        #             proj.original_orientation =  const.AXIAL
        #         elif header['orient'] == 1:
        #             proj.original_orientation = const.CORONAL
        #         elif header['orient'] == 2:
        #             proj.original_orientation = const.SAGITAL
        #         else:
        #             proj.original_orientation =  const.SAGITAL
        # Project orientation set CORONAL as default
        proj.original_orientation = const.CORONAL

        proj.threshold_range = (numpy.amin(matrix), numpy.amax(matrix))
        proj.window = proj.threshold_range[1] - proj.threshold_range[0]
        proj.level = (0.5 *
                      (proj.threshold_range[1] + proj.threshold_range[0]))
        proj.spacing = header['pixdim'][1:4]
        proj.matrix_shape = matrix.shape

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

        self.Slice.window_level = proj.level
        self.Slice.window_width = proj.window
        self.Slice.spacing = header.get_zooms()[:3]

        Publisher.sendMessage('Update threshold limits list',
                              proj.threshold_range)
Example #12
0
    def OpenProject(self, filepath):
        Publisher.sendMessage('Begin busy cursor')
        path = os.path.abspath(filepath)

        proj = prj.Project()
        proj.OpenPlistProject(path)
        proj.SetAcquisitionModality(proj.modality)
        self.Slice = sl.Slice()
        self.Slice._open_image_matrix(proj.matrix_filename,
                                      tuple(proj.matrix_shape),
                                      proj.matrix_dtype)

        self.Slice.window_level = proj.level
        self.Slice.window_width = proj.window

        Publisher.sendMessage('Update threshold limits list',
                                   proj.threshold_range)

        self.LoadProject()

        session = ses.Session()
        session.OpenProject(filepath)
        Publisher.sendMessage("Enable state project", True)
Example #13
0
    def CreateAnalyzeProject(self, imagedata):
        header = imagedata.get_header()
        proj = prj.Project()
        proj.imagedata = None
        proj.name = _("Untitled")
        proj.SetAcquisitionModality("MRI")
        #TODO: Verify if all Analyze are in AXIAL orientation

        # To get  Z, X, Y (used by InVesalius), not X, Y, Z
        matrix, matrix_filename = image_utils.analyze2mmap(imagedata)
        if header['orient'] == 0:
            proj.original_orientation = const.AXIAL
        elif header['orient'] == 1:
            proj.original_orientation = const.CORONAL
        elif header['orient'] == 2:
            proj.original_orientation = const.SAGITAL
        else:
            proj.original_orientation = const.SAGITAL

        proj.threshold_range = (header['glmin'], header['glmax'])
        # Window level and wide are normalized to best visualization experience in NIFTI
        proj.window = proj.threshold_range[1] - proj.threshold_range[0]
        proj.level = (0.5 *
                      (proj.threshold_range[1] + proj.threshold_range[0]))
        proj.spacing = header['pixdim'][1:4]
        proj.matrix_shape = matrix.shape

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

        self.Slice.window_level = proj.level
        self.Slice.window_width = proj.window
        self.Slice.spacing = header.get_zooms()[:3]

        Publisher.sendMessage('Update threshold limits list',
                              proj.threshold_range)
Example #14
0
 def OnUpdateScroll(self, pubsub_evt):
     max_slice_number = sl.Slice().GetNumberOfSlices(self.orientation)
     self.scroll.SetScrollbar(wx.SB_VERTICAL, 1, max_slice_number,
                              max_slice_number)
Example #15
0
    def OpenDicomGroup(self, dicom_group, interval, file_range, gui=True):
        # Retrieve general DICOM headers
        dicom = dicom_group.GetDicomSample()

        # Create imagedata
        interval += 1
        filelist = dicom_group.GetFilenameList()[::interval]
        if not filelist:
            utils.debug("Not used the IPPSorter")
            filelist = [i.image.file for i in dicom_group.GetHandSortedList()[::interval]]
        
        if file_range != None and file_range[1] > file_range[0]:
            filelist = filelist[file_range[0]:file_range[1] + 1]

        zspacing = dicom_group.zspacing * interval

        size = dicom.image.size
        bits = dicom.image.bits_allocad
        sop_class_uid = dicom.acquisition.sop_class_uid
        xyspacing = dicom.image.spacing
        orientation = dicom.image.orientation_label

        if sop_class_uid == '1.2.840.10008.5.1.4.1.1.7': #Secondary Capture Image Storage
            use_dcmspacing = 1
        else:
            use_dcmspacing = 0

        imagedata = None
        
        sx, sy = size
        n_slices = len(filelist)
        resolution_percentage = utils.calculate_resizing_tofitmemory(int(sx), int(sy), n_slices, bits/8)
        
        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
       
 
        wl = float(dicom.image.level)
        ww = float(dicom.image.window)
        self.matrix, scalar_range, self.filename = image_utils.dcm2memmap(filelist, size,
                                                                    orientation, 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]

        # 1(a): Fix gantry tilt, if any
        tilt_value = dicom.acquisition.tilt
        if (tilt_value) and (gui):
            # Tell user gantry tilt and fix, according to answer
            message = _("Fix gantry tilt applying the degrees below")
            value = -1*tilt_value
            tilt_value = dialog.ShowNumberDialog(message, value)
            image_utils.FixGantryTilt(self.matrix, self.Slice.spacing, tilt_value)
        elif (tilt_value) and not (gui):
            tilt_value = -1*tilt_value
            image_utils.FixGantryTilt(self.matrix, self.Slice.spacing, tilt_value)

        self.Slice.window_level = wl
        self.Slice.window_width = ww

        scalar_range = int(self.matrix.min()), int(self.matrix.max())

        Publisher.sendMessage('Update threshold limits list', scalar_range)

        return self.matrix, self.filename, dicom
Example #16
0
    def OnPopup(self, evt):
        id = evt.GetId()
        item = self.ID_TO_TOOL_ITEM[evt.GetId()]
        key = item.GetLabel()
        if(key in const.WINDOW_LEVEL.keys()):
            window, level = const.WINDOW_LEVEL[key]
            Publisher.sendMessage('Bright and contrast adjustment image',
                    (window, level))
            Publisher.sendMessage('Update window level value',\
               (window, level))
            Publisher.sendMessage('Update window and level text',\
                           "WL: %d  WW: %d"%(level, window))
            Publisher.sendMessage('Update slice viewer')

            #Necessary update the slice plane in the volume case exists
            Publisher.sendMessage('Render volume viewer')

        elif(key in const.SLICE_COLOR_TABLE.keys()):
            values = const.SLICE_COLOR_TABLE[key]
            Publisher.sendMessage('Change colour table from background image', values)
            Publisher.sendMessage('Update slice viewer')

            if sys.platform == 'linux2':
                for i in self.pseudo_color_items:
                    it = self.pseudo_color_items[i]
                    if it.IsChecked():
                        it.Toggle()

                item.Toggle()
            self.HideClutDialog()
            self._gen_event = True

        elif key in self.plist_presets:
            values = presets.get_wwwl_preset_colours(self.plist_presets[key])
            Publisher.sendMessage('Change colour table from background image from plist', values)
            Publisher.sendMessage('Update slice viewer')

            if sys.platform == 'linux2':
                for i in self.pseudo_color_items:
                    it = self.pseudo_color_items[i]
                    if it.IsChecked():
                        it.Toggle()

                item.Toggle()
            self.HideClutDialog()
            self._gen_event = True

        elif(key in const.IMAGE_TILING.keys()):
            values = const.IMAGE_TILING[key]
            Publisher.sendMessage('Set slice viewer layout', values)
            Publisher.sendMessage('Update slice viewer')

        elif key in PROJECTIONS_ID:
            pid = PROJECTIONS_ID[key]
            Publisher.sendMessage('Set projection type', pid)
            Publisher.sendMessage('Reload actual slice')

        elif key == _('Custom'):
            if self.cdialog is None:
                slc = sl.Slice()
                histogram = slc.histogram
                init = slc.matrix.min()
                end = slc.matrix.max()
                nodes = slc.nodes
                self.cdialog = ClutImagedataDialog(histogram, init, end, nodes)
                self.cdialog.Show()
            else:
                self.cdialog.Show(self._gen_event)

            if sys.platform == 'linux2':
                for i in self.pseudo_color_items:
                    it = self.pseudo_color_items[i]
                    if it.IsChecked():
                        it.Toggle()

                item.Toggle()
            item = self.ID_TO_TOOL_ITEM[evt.GetId()]
            item.Check(True)
            self._gen_event = False

        evt.Skip()