示例#1
0
    def OnSplitSurface(self, pubsub_evt):
        """
        Create n new surfaces, based on the last selected surface,
        according to their connectivity.
        """
        index = self.last_surface_index
        proj = prj.Project()
        surface = proj.surface_dict[index]

        index_list = []
        new_polydata_list = pu.SplitDisconectedParts(surface.polydata)
        for polydata in new_polydata_list:
            index = self.CreateSurfaceFromPolydata(polydata)
            index_list.append(index)
            #self.ShowActor(index, True)

        Publisher.sendMessage('Show multiple surfaces', (index_list, True))
示例#2
0
    def CloseProject(self):
        Publisher.sendMessage('Set slice interaction style', style=const.STATE_DEFAULT)
        Publisher.sendMessage('Hide content panel')
        Publisher.sendMessage('Close project data')

        if self.img_type == 1:
            Publisher.sendMessage('Show import panel in frame')

        if self.img_type == 2:
            Publisher.sendMessage('Show import bitmap panel in frame')


        proj = prj.Project()
        proj.Close()

        session = ses.Session()
        session.CloseProject()
示例#3
0
    def _remove_measurements(self, indexes):
        for index in indexes:
            m, mr = self.measures.pop(index)
            try:
                mr.Remove()
            except AttributeError:
                # The is not being displayed
                pass
            prj.Project().RemoveMeasurement(index)
            if m.location == const.SURFACE:
                Publisher.sendMessage('Remove actors ' + str(m.location),
                                      actors=mr.GetActors())
        Publisher.sendMessage('Redraw canvas')
        Publisher.sendMessage('Render volume viewer')

        session = ses.Session()
        session.ChangeProject()
示例#4
0
    def CreateBitmapProject(self, bmp_data, rec_data, matrix, matrix_filename):
        name_to_const = {
            "AXIAL": const.AXIAL,
            "CORONAL": const.CORONAL,
            "SAGITTAL": const.SAGITAL
        }

        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])

        bits = bmp_data.GetFirstPixelSize()
        sx, sy = size = bmp_data.GetFirstBitmapSize()

        proj = prj.Project()
        proj.name = name
        proj.modality = 'UNKNOWN'
        proj.SetAcquisitionModality(proj.modality)
        proj.matrix_shape = matrix.shape
        proj.matrix_dtype = matrix.dtype.name
        proj.matrix_filename = matrix_filename
        #proj.imagedata = imagedata
        #proj.dicom_sample = dicom

        proj.original_orientation =\
                    name_to_const[orientation.upper()]
        proj.window = float(matrix.max())
        proj.level = float(matrix.max() / 4)

        proj.threshold_range = int(matrix.min()), int(matrix.max())
        #const.THRESHOLD_RANGE = proj.threshold_range

        proj.spacing = self.Slice.spacing

        ######
        session = ses.Session()
        filename = proj.name + ".inv3"

        filename = filename.replace("/",
                                    "")  #Fix problem case other/Skull_DICOM

        dirpath = session.CreateProject(filename)
示例#5
0
 def OnDuplicate(self, surface_indexes):
     proj = prj.Project()
     surface_dict = proj.surface_dict
     for index in surface_indexes:
         original_surface = surface_dict[index]
         # compute copy name
         name = original_surface.name
         names_list = [surface_dict[i].name for i in surface_dict.keys()]
         new_name = utl.next_copy_name(name, names_list)
         # create new mask
         self.CreateSurfaceFromPolydata(
             polydata=original_surface.polydata,
             overwrite=False,
             name=new_name,
             colour=original_surface.colour,
             transparency=original_surface.transparency,
             volume=original_surface.volume,
             area=original_surface.area)
示例#6
0
    def CloseProject(self):
        Publisher.sendMessage('Enable style', style=const.STATE_DEFAULT)
        Publisher.sendMessage('Hide content panel')
        Publisher.sendMessage('Close project data')

        if self.img_type == 1:
            Publisher.sendMessage('Show import panel in frame')

        if self.img_type == 2:
            Publisher.sendMessage('Show import bitmap panel in frame')

        proj = prj.Project()
        proj.Close()

        session = ses.Session()
        session.CloseProject()

        Publisher.sendMessage('Update status text in GUI', label=_("Ready"))
示例#7
0
    def OnLinkExportSurface(self, evt=None):
        "OnLinkExportSurface"
        project = proj.Project()
        n_surface = 0

        for index in project.surface_dict:
            if project.surface_dict[index].is_shown:
                n_surface += 1

        if n_surface:
            if sys.platform == 'win32':
                project_name = project.name
            else:
                project_name = project.name+".stl"


            dlg = wx.FileDialog(None,
                                _("Save 3D surface as..."), # title
                                "", # last used directory
                                project_name, # filename
                                WILDCARD_SAVE_3D,
                                wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
            dlg.SetFilterIndex(3) # default is STL

            if dlg.ShowModal() == wx.ID_OK:
                filetype_index = dlg.GetFilterIndex()
                filetype = INDEX_TO_TYPE_3D[filetype_index]
                filename = dlg.GetPath()
                extension = INDEX_TO_EXTENSION[filetype_index]
                if sys.platform != 'win32':
                    if filename.split(".")[-1] != extension:
                        filename = filename + "."+ extension
                Publisher.sendMessage('Export surface to file',
                                            (filename, filetype))
        else:
            dlg = wx.MessageDialog(None,
                    _("You need to create a surface and make it ") +
                    _("visible before exporting it."),
                    'InVesalius 3',
                    wx.OK | wx.ICON_INFORMATION)
            try:
                dlg.ShowModal()
            finally:
                dlg.Destroy()
示例#8
0
    def CreateBallReference(self):
        MRAD = 3.0
        proj = prj.Project()
        s = proj.spacing
        # The sphere's radius will be MRAD times bigger than the media of the
        # spacing values.
        r = (s[0] + s[1] + s[2]) / 3.0 * MRAD
        self.ball_reference = vtk.vtkSphereSource()
        self.ball_reference.SetRadius(r)

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(self.ball_reference.GetOutputPort())

        p = vtk.vtkProperty()
        p.SetColor(1, 0, 0)

        self.ball_actor = vtk.vtkActor()
        self.ball_actor.SetMapper(mapper)
        self.ball_actor.SetProperty(p)
示例#9
0
    def start_new_inv_instance(self, image, name, spacing, modality, orientation, window_width, window_level):
        p = prj.Project()
        project_folder = tempfile.mkdtemp()
        p.create_project_file(name, spacing, modality, orientation, window_width, window_level, image, folder=project_folder)
        err_msg = ''
        try:
            sp = subprocess.Popen([sys.executable, sys.argv[0], '--import-folder', project_folder],
                                  stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=os.getcwd())
        except Exception as err:
            err_msg = str(err)
        else:
            try:
                if sp.wait(2):
                    err_msg = sp.stderr.read().decode('utf8')
                    sp.terminate()
            except subprocess.TimeoutExpired:
                pass

        if err_msg:
            dialog.MessageBox(None, "It was not possible to launch new instance of InVesalius3 dsfa dfdsfa sdfas fdsaf asdfasf dsaa", err_msg)
示例#10
0
    def LoadImagedataInfo(self):
        proj = prj.Project()

        thresh_modes = proj.threshold_modes.keys()
        thresh_modes = sorted(thresh_modes)
        default_threshold = const.THRESHOLD_PRESETS_INDEX
        if proj.mask_dict:
            keys = proj.mask_dict.keys()
            last = max(keys)
            (a, b) = proj.mask_dict[last].threshold_range
            default_threshold = [a, b]
            min_ = proj.threshold_range[0]
            max_ = proj.threshold_range[1]
            if default_threshold[0] < min_:
                default_threshold[0] = min_
            if default_threshold[1] > max_:
                default_threshold[1] = max_
            [a, b] = default_threshold
            default_threshold = (a, b)
        Publisher.sendMessage('Set threshold modes',
                              (thresh_modes, default_threshold))
示例#11
0
    def CreateOtherProject(self, name, matrix, matrix_filename):
        name_to_const = {
            "AXIAL": const.AXIAL,
            "CORONAL": const.CORONAL,
            "SAGITTAL": const.SAGITAL
        }

        proj = prj.Project()
        proj.name = name
        proj.modality = 'MRI'
        proj.SetAcquisitionModality('MRI')
        proj.matrix_shape = matrix.shape
        proj.matrix_dtype = matrix.dtype.name
        proj.matrix_filename = matrix_filename

        # Orientation must be CORONAL in order to as_closes_canonical and
        # swap axis in img2memmap to work in a standardized way.
        # TODO: Create standard import image for all acquisition orientations
        orientation = 'CORONAL'

        proj.original_orientation =\
            name_to_const[orientation]

        proj.window = self.Slice.window_width
        proj.level = self.Slice.window_level
        proj.threshold_range = int(matrix.min()), int(matrix.max())
        proj.spacing = self.Slice.spacing
        # TODO: Check that this is needed with the new way of using affine
        #  now the affine should be at least the identity(4) and never None
        if self.Slice.affine is not None:
            proj.affine = self.Slice.affine.tolist()

        ######
        session = ses.Session()
        filename = proj.name + ".inv3"

        filename = filename.replace("/",
                                    "")  # Fix problem case other/Skull_DICOM

        dirpath = session.CreateProject(filename)
示例#12
0
    def OnInsertLinearMeasurePoint(self, obj, evt):
        x, y = self.interactor.GetEventPosition()
        self.measure_picker.Pick(x, y, 0, self.ren)
        x, y, z = self.measure_picker.GetPickPosition()

        proj = prj.Project()
        radius = min(proj.spacing) * PROP_MEASURE
        if self.measure_picker.GetActor():
            # if not self.measures or self.measures[-1].IsComplete():
            # m = measures.LinearMeasure(self.ren)
            # m.AddPoint(x, y, z)
            # self.measures.append(m)
            # else:
            # m = self.measures[-1]
            # m.AddPoint(x, y, z)
            # if m.IsComplete():
            # Publisher.sendMessage("Add measure to list",
            # (u"3D", _(u"%.3f mm" % m.GetValue())))
            Publisher.sendMessage(
                "Add measurement point",
                ((x, y, z), const.LINEAR, const.SURFACE, radius))
            self.interactor.Render()
示例#13
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)
示例#14
0
    def CreateBallReference(self):
        """
        Red sphere on volume visualization to reference center of
        cross in slice planes.
        The sphere's radius will be scale times bigger than the average of
        image spacing values.
        """
        scale = 3.0
        proj = prj.Project()
        s = proj.spacing
        r = (s[0] + s[1] + s[2]) / 3.0 * scale

        ball_source = vtk.vtkSphereSource()
        ball_source.SetRadius(r)

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(ball_source.GetOutputPort())

        self.ball_actor = vtk.vtkActor()
        self.ball_actor.SetMapper(mapper)
        self.ball_actor.GetProperty().SetColor(1, 0, 0)

        self.ren.AddActor(self.ball_actor)
示例#15
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
示例#16
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 Analyse are in AXIAL orientation

        # To get  Z, X, Y (used by InVesaliu), 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 = (int(header['glmin']), int(header['glmax']))
        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)
示例#17
0
    def OnRemove(self, pubsub_evt):
        selected_items = pubsub_evt.data
        proj = prj.Project()

        old_dict = self.actors_dict
        new_dict = {}
        if selected_items:
            for index in selected_items:
                proj.RemoveSurface(index)
                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)
            self.actors_dict = new_dict

        if self.last_surface_index in selected_items:
            if self.actors_dict:
                self.last_surface_index = 0
            else:
                self.last_surface_index = None
示例#18
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, filetype))
示例#19
0
    def create_project_from_matrix(self,
                                   name,
                                   matrix,
                                   orientation="AXIAL",
                                   spacing=(1.0, 1.0, 1.0),
                                   modality="CT",
                                   window_width=None,
                                   window_level=None,
                                   new_instance=False):
        """
        Creates a new project from a Numpy 3D array.

        name: Name of the project.
        matrix: A Numpy 3D array. It only works with int16 arrays.
        spacing: The spacing between the center of the voxels in X, Y and Z direction.
        modality: Imaging modality.
        """
        if window_width is None:
            window_width = (matrix.max() - matrix.min())
        if window_level is None:
            window_level = (matrix.max() + matrix.min()) // 2

        window_width = int(window_width)
        window_level = int(window_level)

        name_to_const = {
            "AXIAL": const.AXIAL,
            "CORONAL": const.CORONAL,
            "SAGITTAL": const.SAGITAL
        }

        if new_instance:
            self.start_new_inv_instance(matrix, name, spacing, modality,
                                        name_to_const[orientation],
                                        window_width, window_level)
        else:
            # Verifying if there is a project open
            s = ses.Session()
            if s.IsOpen():
                Publisher.sendMessage('Close Project')
                Publisher.sendMessage('Disconnect tracker')

            # Check if user really closed the project, if not, stop project creation
            if s.IsOpen():
                return

            mmap_matrix = image_utils.array2memmap(matrix)

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

            self.Slice.window_width = window_width
            self.Slice.window_level = window_level

            proj = prj.Project()
            proj.name = name
            proj.modality = modality
            proj.SetAcquisitionModality(modality)
            proj.matrix_shape = matrix.shape
            proj.matrix_dtype = matrix.dtype.name
            proj.matrix_filename = self.Slice.matrix_filename
            proj.window = window_width
            proj.level = window_level


            proj.original_orientation =\
                name_to_const[orientation]

            proj.threshold_range = int(matrix.min()), int(matrix.max())
            proj.spacing = self.Slice.spacing

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

            ######
            session = ses.Session()
            filename = proj.name + ".inv3"

            filename = filename.replace("/", "")

            dirpath = session.CreateProject(filename)

            self.LoadProject()
            Publisher.sendMessage("Enable state project", state=True)
示例#20
0
 def SetBitmapSpacing(self, pubsub_evt):
     proj = prj.Project()
     proj.spacing = pubsub_evt.data
示例#21
0
    def LoadProject(self):
        proj = prj.Project()

        const.THRESHOLD_OUTVALUE = proj.threshold_range[0]
        const.THRESHOLD_INVALUE = proj.threshold_range[1]
        const.THRESHOLD_RANGE = proj.threshold_modes[_("Bone")]

        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', mask_dict=proj.mask_dict)

        Publisher.sendMessage('Load slice plane')

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

        Publisher.sendMessage('Set project name', proj_name=proj.name)
        Publisher.sendMessage('Load surface dict',
                              surface_dict=proj.surface_dict)
        Publisher.sendMessage('Hide surface items',
                              surface_dict=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', mask=m)
                if m.is_shown:
                    self.Slice.current_mask = proj.mask_dict[mask_index]
                    Publisher.sendMessage('Show mask',
                                          index=m.index,
                                          value=True)
                    Publisher.sendMessage('Change mask selected',
                                          index=m.index)
        else:
            mask_name = const.MASK_NAME_PATTERN % (1, )

            if proj.modality != "UNKNOWN":
                thresh = const.THRESHOLD_RANGE
            else:
                thresh = proj.threshold_range

            colour = const.MASK_COLOUR[0]
            Publisher.sendMessage('Create new mask',
                                  mask_name=mask_name,
                                  thresh=thresh,
                                  colour=colour)

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

        Publisher.sendMessage(('Set scroll position', 'AXIAL'),
                              index=proj.matrix_shape[0] / 2)
        Publisher.sendMessage(('Set scroll position', 'SAGITAL'),
                              index=proj.matrix_shape[1] / 2)
        Publisher.sendMessage(('Set scroll position', 'CORONAL'),
                              index=proj.matrix_shape[2] / 2)

        Publisher.sendMessage('End busy cursor')
示例#22
0
 def __load_preset_config(self):
     self.config = prj.Project().raycasting_preset
示例#23
0
 def SetBitmapSpacing(self, spacing):
     proj = prj.Project()
     proj.spacing = spacing
示例#24
0
 def ShowBooleanOpDialog(self):
     dlg = dialogs.MaskBooleanDialog(prj.Project().mask_dict)
     dlg.Show()
示例#25
0
 def OnChangeSurfaceName(self, index, name):
     proj = prj.Project()
     proj.surface_dict[index].name = name
示例#26
0
    def _add_point(self, pubsub_evt):
        position = pubsub_evt.data[0]
        type = pubsub_evt.data[1]  # Linear or Angular
        location = pubsub_evt.data[2]  # 3D, AXIAL, SAGITAL, CORONAL

        if location == const.SURFACE:
            slice_number = 0
            try:
                radius = pubsub_evt.data[3]
            except IndexError:
                radius = const.PROP_MEASURE
        else:
            try:
                slice_number = pubsub_evt.data[3]
            except IndexError:
                slice_number = 0

            try:
                radius = pubsub_evt.data[4]
            except IndexError:
                radius = const.PROP_MEASURE

        to_remove = False
        if self.current is None:
            to_create = True
        elif self.current[0].location != location:
            to_create = True
            to_remove = True
        elif self.current[0].slice_number != slice_number:
            to_create = True
            to_remove = True
        else:
            to_create = False

        if to_create:
            m = Measurement()
            m.index = len(self.measures)
            m.location = location
            m.slice_number = slice_number
            m.type = type
            representation = CirclePointRepresentation(m.colour, radius)
            if type == const.LINEAR:
                mr = LinearMeasure(m.colour, representation)
            else:
                mr = AngularMeasure(m.colour, representation)
            if to_remove:
                #  actors = self.current[1].GetActors()
                #  slice_number = self.current[0].slice_number
                #  Publisher.sendMessage(('Remove actors ' + str(self.current[0].location)),
                #  (actors, slice_number))
                self.measures.pop()[1].Remove()
                if self.current[0].location == const.SURFACE:
                    Publisher.sendMessage('Render volume viewer')
                else:
                    Publisher.sendMessage('Redraw canvas')

            session = ses.Session()
            session.ChangeProject()

            self.current = (m, mr)

        mr = self.current[1]
        m = self.current[0]

        x, y, z = position
        actors = mr.AddPoint(x, y, z)
        m.points.append(position)

        if m.location == const.SURFACE:
            Publisher.sendMessage("Add actors " + str(location),
                                  (actors, m.slice_number))

        if self.current not in self.measures:
            self.measures.append(self.current)

        if mr.IsComplete():
            index = prj.Project().AddMeasurement(m)
            #m.index = index # already done in proj
            name = m.name
            colour = m.colour
            m.value = mr.GetValue()
            type_ = TYPE[type]
            location = LOCATION[location]
            if type == const.LINEAR:
                value = u"%.3f mm" % m.value
            else:
                value = u"%.3f°" % m.value

            msg = 'Update measurement info in GUI',
            Publisher.sendMessage(
                msg, (index, name, colour, location, type_, value))
            self.current = None
示例#27
0
    def LoadVolume(self):
        proj = prj.Project()
        #image = imagedata_utils.to_vtk(n_array, spacing, slice_number, orientation)

        if not self.loaded_image:
            self.LoadImage()
            self.loaded_image = 1

        image = self.image

        number_filters = len(self.config['convolutionFilters'])

        if (prj.Project().original_orientation == const.AXIAL):
            flip_image = True
        else:
            flip_image = False

        #if (flip_image):
        update_progress = vtk_utils.ShowProgress(2 + number_filters)
        # Flip original vtkImageData
        flip = vtk.vtkImageFlip()
        flip.SetInputData(image)
        flip.SetFilteredAxis(1)
        flip.FlipAboutOriginOn()
        #  flip.ReleaseDataFlagOn()

        flip_ref = weakref.ref(flip)
        flip_ref().AddObserver(
            "ProgressEvent",
            lambda obj, evt: update_progress(flip_ref(), "Rendering..."))
        flip.Update()
        image = flip.GetOutput()

        scale = image.GetScalarRange()
        self.scale = scale

        cast = vtk.vtkImageShiftScale()
        cast.SetInputData(image)
        cast.SetShift(abs(scale[0]))
        cast.SetOutputScalarTypeToUnsignedShort()
        #  cast.ReleaseDataFlagOn()
        cast_ref = weakref.ref(cast)
        cast_ref().AddObserver(
            "ProgressEvent",
            lambda obj, evt: update_progress(cast_ref(), "Rendering..."))
        cast.Update()
        image2 = cast

        self.imagedata = image2
        if self.config['advancedCLUT']:
            self.Create16bColorTable(scale)
            self.CreateOpacityTable(scale)
        else:
            self.Create8bColorTable(scale)
            self.Create8bOpacityTable(scale)

        image2 = self.ApplyConvolution(image2.GetOutput(), update_progress)
        self.final_imagedata = image2

        # Changed the vtkVolumeRayCast to vtkFixedPointVolumeRayCastMapper
        # because it's faster and the image is better
        # TODO: To test if it's true.
        if const.TYPE_RAYCASTING_MAPPER:
            volume_mapper = vtk.vtkVolumeRayCastMapper()
            #volume_mapper.AutoAdjustSampleDistancesOff()
            #volume_mapper.SetInput(image2)
            #volume_mapper.SetVolumeRayCastFunction(composite_function)
            #volume_mapper.SetGradientEstimator(gradientEstimator)
            volume_mapper.IntermixIntersectingGeometryOn()
            self.volume_mapper = volume_mapper
        else:

            if int(ses.Session().rendering) == 0:
                volume_mapper = vtk.vtkFixedPointVolumeRayCastMapper()
                #volume_mapper.AutoAdjustSampleDistancesOff()
                self.volume_mapper = volume_mapper
                volume_mapper.IntermixIntersectingGeometryOn()
            else:
                volume_mapper = vtk.vtkGPUVolumeRayCastMapper()
                volume_mapper.UseJitteringOn()
                self.volume_mapper = volume_mapper

        self.SetTypeRaycasting()
        volume_mapper.SetInputData(image2)

        # TODO: Look to this
        #volume_mapper_hw = vtk.vtkVolumeTextureMapper3D()
        #volume_mapper_hw.SetInput(image2)

        #Cut Plane
        #CutPlane(image2, volume_mapper)

        #self.color_transfer = color_transfer

        volume_properties = vtk.vtkVolumeProperty()
        #volume_properties.IndependentComponentsOn()
        volume_properties.SetInterpolationTypeToLinear()
        volume_properties.SetColor(self.color_transfer)

        try:
            volume_properties.SetScalarOpacity(self.opacity_transfer_func)
        except NameError:
            pass

        if not self.volume_mapper.IsA("vtkGPUVolumeRayCastMapper"):
            # Using these lines to improve the raycasting quality. These values
            # seems related to the distance from ray from raycasting.
            # TODO: Need to see values that improve the quality and don't decrease
            # the performance. 2.0 seems to be a good value to pix_diag
            pix_diag = 2.0
            volume_mapper.SetImageSampleDistance(0.25)
            volume_mapper.SetSampleDistance(pix_diag / 5.0)
            volume_properties.SetScalarOpacityUnitDistance(pix_diag)

        self.volume_properties = volume_properties

        self.SetShading()

        volume = vtk.vtkVolume()
        volume.SetMapper(volume_mapper)
        volume.SetProperty(volume_properties)
        self.volume = volume

        colour = self.GetBackgroundColour()

        self.exist = 1

        if self.plane:
            self.plane.SetVolumeMapper(volume_mapper)

        Publisher.sendMessage('Load volume into viewer',
                              volume=volume,
                              colour=colour,
                              ww=self.ww,
                              wl=self.wl)

        del flip
        del cast
示例#28
0
    def CreateSurfaceFromPolydata(self,
                                  polydata,
                                  overwrite=False,
                                  name=None,
                                  colour=None,
                                  transparency=None,
                                  volume=None,
                                  area=None):
        normals = vtk.vtkPolyDataNormals()
        normals.SetInputData(polydata)
        normals.SetFeatureAngle(80)
        normals.AutoOrientNormalsOn()
        normals.Update()

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputData(normals.GetOutput())
        mapper.ScalarVisibilityOff()
        mapper.ImmediateModeRenderingOn()  # improve performance

        actor = vtk.vtkActor()
        actor.SetMapper(mapper)

        if overwrite:
            surface = Surface(index=self.last_surface_index)
        else:
            surface = Surface()

        if not colour:
            surface.colour = random.choice(const.SURFACE_COLOUR)
        else:
            surface.colour = colour
        surface.polydata = polydata

        if transparency:
            surface.transparency = transparency

        if name:
            surface.name = name

        # Append surface into Project.surface_dict
        proj = prj.Project()
        if overwrite:
            proj.ChangeSurface(surface)
        else:
            index = proj.AddSurface(surface)
            surface.index = index
            self.last_surface_index = index

        # Set actor colour and transparency
        actor.GetProperty().SetColor(surface.colour)
        actor.GetProperty().SetOpacity(1 - surface.transparency)
        self.actors_dict[surface.index] = actor

        session = ses.Session()
        session.ChangeProject()

        # The following lines have to be here, otherwise all volumes disappear
        if not volume or not area:
            triangle_filter = vtk.vtkTriangleFilter()
            triangle_filter.SetInputData(polydata)
            triangle_filter.Update()

            measured_polydata = vtk.vtkMassProperties()
            measured_polydata.SetInputConnection(
                triangle_filter.GetOutputPort())
            measured_polydata.Update()
            volume = measured_polydata.GetVolume()
            area = measured_polydata.GetSurfaceArea()
            surface.volume = volume
            surface.area = area
            print(">>>>", surface.volume)
        else:
            surface.volume = volume
            surface.area = area

        self.last_surface_index = surface.index

        Publisher.sendMessage('Load surface actor into viewer', actor=actor)

        Publisher.sendMessage('Update surface info in GUI', surface=surface)
        return surface.index
示例#29
0
    def OnLinkExportSurface(self, evt=None):
        "OnLinkExportSurface"
        project = proj.Project()
        n_surface = 0

        for index in project.surface_dict:
            if project.surface_dict[index].is_shown:
                n_surface += 1

        if n_surface:
            if sys.platform == 'win32':
                project_name = project.name
            else:
                project_name = project.name + ".stl"

            session = ses.Session()
            last_directory = session.get('paths', 'last_directory_3d_surface',
                                         '')

            dlg = wx.FileDialog(
                None,
                _("Save 3D surface as..."),  # title
                last_directory,  # last used directory
                project_name,  # filename
                WILDCARD_SAVE_3D,
                wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
            dlg.SetFilterIndex(3)  # default is STL

            if dlg.ShowModal() == wx.ID_OK:
                filetype_index = dlg.GetFilterIndex()
                filetype = INDEX_TO_TYPE_3D[filetype_index]
                filename = dlg.GetPath()
                extension = INDEX_TO_EXTENSION[filetype_index]
                if sys.platform != 'win32':
                    if filename.split(".")[-1] != extension:
                        filename = filename + "." + extension

                if filename:
                    session['paths'][
                        'last_directory_3d_surface'] = os.path.split(
                            filename)[0]
                    session.WriteSessionFile()

                Publisher.sendMessage('Export surface to file',
                                      filename=filename,
                                      filetype=filetype)
                if not os.path.exists(filename):
                    dlg = wx.MessageDialog(
                        None, _("It was not possible to save the surface."),
                        _("Error saving surface"), wx.OK | wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
        else:
            dlg = wx.MessageDialog(
                None,
                _("You need to create a surface and make it ") +
                _("visible before exporting it."), 'InVesalius 3',
                wx.OK | wx.ICON_INFORMATION)
            try:
                dlg.ShowModal()
            finally:
                dlg.Destroy()
示例#30
0
    def AddNewActor(self, slice_, mask, surface_parameters):
        """
        Create surface actor, save into project and send it to viewer.
        """
        matrix = slice_.matrix
        filename_img = slice_.matrix_filename
        spacing = slice_.spacing

        algorithm = surface_parameters['method']['algorithm']
        options = surface_parameters['method']['options']

        surface_name = surface_parameters['options']['name']
        quality = surface_parameters['options']['quality']
        fill_holes = surface_parameters['options']['fill']
        keep_largest = surface_parameters['options']['keep_largest']

        mode = 'CONTOUR'  # 'GRAYSCALE'
        min_value, max_value = mask.threshold_range
        colour = mask.colour[:3]

        try:
            overwrite = surface_parameters['options']['overwrite']
        except KeyError:
            overwrite = False
        mask.matrix.flush()

        if quality in const.SURFACE_QUALITY.keys():
            imagedata_resolution = const.SURFACE_QUALITY[quality][0]
            smooth_iterations = const.SURFACE_QUALITY[quality][1]
            smooth_relaxation_factor = const.SURFACE_QUALITY[quality][2]
            decimate_reduction = const.SURFACE_QUALITY[quality][3]

        #if imagedata_resolution:
        #imagedata = iu.ResampleImage3D(imagedata, imagedata_resolution)

        pipeline_size = 4
        if decimate_reduction:
            pipeline_size += 1
        if (smooth_iterations and smooth_relaxation_factor):
            pipeline_size += 1
        if fill_holes:
            pipeline_size += 1
        if keep_largest:
            pipeline_size += 1

        ## Update progress value in GUI
        UpdateProgress = vu.ShowProgress(pipeline_size)
        UpdateProgress(0, _("Creating 3D surface..."))

        language = ses.Session().language

        if (prj.Project().original_orientation == const.CORONAL):
            flip_image = False
        else:
            flip_image = True

        n_processors = multiprocessing.cpu_count()

        pipe_in, pipe_out = multiprocessing.Pipe()
        o_piece = 1
        piece_size = 2000

        n_pieces = int(round(matrix.shape[0] / piece_size + 0.5, 0))

        q_in = multiprocessing.Queue()
        q_out = multiprocessing.Queue()

        p = []
        for i in range(n_processors):
            sp = surface_process.SurfaceProcess(
                pipe_in, filename_img, matrix.shape, matrix.dtype,
                mask.temp_file, mask.matrix.shape, mask.matrix.dtype, spacing,
                mode, min_value, max_value, decimate_reduction,
                smooth_relaxation_factor, smooth_iterations, language,
                flip_image, q_in, q_out, algorithm != 'Default', algorithm,
                imagedata_resolution)
            p.append(sp)
            sp.start()

        for i in range(n_pieces):
            init = i * piece_size
            end = init + piece_size + o_piece
            roi = slice(init, end)
            q_in.put(roi)
            print("new_piece", roi)

        for i in p:
            q_in.put(None)

        none_count = 1
        while 1:
            msg = pipe_out.recv()
            if (msg is None):
                none_count += 1
            else:
                UpdateProgress(msg[0] / (n_pieces * pipeline_size), msg[1])

            if none_count > n_pieces:
                break

        polydata_append = vtk.vtkAppendPolyData()
        #  polydata_append.ReleaseDataFlagOn()
        t = n_pieces
        while t:
            filename_polydata = q_out.get()

            reader = vtk.vtkXMLPolyDataReader()
            reader.SetFileName(filename_polydata)
            #  reader.ReleaseDataFlagOn()
            reader.Update()
            #  reader.GetOutput().ReleaseDataFlagOn()

            polydata = reader.GetOutput()
            #  polydata.SetSource(None)

            polydata_append.AddInputData(polydata)
            del reader
            del polydata
            t -= 1

        polydata_append.Update()
        #  polydata_append.GetOutput().ReleaseDataFlagOn()
        polydata = polydata_append.GetOutput()
        #polydata.Register(None)
        #  polydata.SetSource(None)
        del polydata_append

        if algorithm == 'ca_smoothing':
            normals = vtk.vtkPolyDataNormals()
            normals_ref = weakref.ref(normals)
            normals_ref().AddObserver(
                "ProgressEvent", lambda obj, evt: UpdateProgress(
                    normals_ref(), _("Creating 3D surface...")))
            normals.SetInputData(polydata)
            #  normals.ReleaseDataFlagOn()
            #normals.SetFeatureAngle(80)
            #normals.AutoOrientNormalsOn()
            normals.ComputeCellNormalsOn()
            #  normals.GetOutput().ReleaseDataFlagOn()
            normals.Update()
            del polydata
            polydata = normals.GetOutput()
            #  polydata.SetSource(None)
            del normals

            clean = vtk.vtkCleanPolyData()
            #  clean.ReleaseDataFlagOn()
            #  clean.GetOutput().ReleaseDataFlagOn()
            clean_ref = weakref.ref(clean)
            clean_ref().AddObserver(
                "ProgressEvent", lambda obj, evt: UpdateProgress(
                    clean_ref(), _("Creating 3D surface...")))
            clean.SetInputData(polydata)
            clean.PointMergingOn()
            clean.Update()

            del polydata
            polydata = clean.GetOutput()
            #  polydata.SetSource(None)
            del clean

            #  try:
            #  polydata.BuildLinks()
            #  except TypeError:
            #  polydata.BuildLinks(0)
            #  polydata = ca_smoothing.ca_smoothing(polydata, options['angle'],
            #  options['max distance'],
            #  options['min weight'],
            #  options['steps'])

            mesh = cy_mesh.Mesh(polydata)
            cy_mesh.ca_smoothing(mesh, options['angle'],
                                 options['max distance'],
                                 options['min weight'], options['steps'])
            #  polydata = mesh.to_vtk()

            #  polydata.SetSource(None)
            #  polydata.DebugOn()
        else:
            #smoother = vtk.vtkWindowedSincPolyDataFilter()
            smoother = vtk.vtkSmoothPolyDataFilter()
            smoother_ref = weakref.ref(smoother)
            smoother_ref().AddObserver(
                "ProgressEvent", lambda obj, evt: UpdateProgress(
                    smoother_ref(), _("Creating 3D surface...")))
            smoother.SetInputData(polydata)
            smoother.SetNumberOfIterations(smooth_iterations)
            smoother.SetRelaxationFactor(smooth_relaxation_factor)
            smoother.SetFeatureAngle(80)
            #smoother.SetEdgeAngle(90.0)
            #smoother.SetPassBand(0.1)
            smoother.BoundarySmoothingOn()
            smoother.FeatureEdgeSmoothingOn()
            #smoother.NormalizeCoordinatesOn()
            #smoother.NonManifoldSmoothingOn()
            #  smoother.ReleaseDataFlagOn()
            #  smoother.GetOutput().ReleaseDataFlagOn()
            smoother.Update()
            del polydata
            polydata = smoother.GetOutput()
            #polydata.Register(None)
            #  polydata.SetSource(None)
            del smoother

        if decimate_reduction:
            print("Decimating", decimate_reduction)
            decimation = vtk.vtkQuadricDecimation()
            #  decimation.ReleaseDataFlagOn()
            decimation.SetInputData(polydata)
            decimation.SetTargetReduction(decimate_reduction)
            decimation_ref = weakref.ref(decimation)
            decimation_ref().AddObserver(
                "ProgressEvent", lambda obj, evt: UpdateProgress(
                    decimation_ref(), _("Creating 3D surface...")))
            #decimation.PreserveTopologyOn()
            #decimation.SplittingOff()
            #decimation.BoundaryVertexDeletionOff()
            #  decimation.GetOutput().ReleaseDataFlagOn()
            decimation.Update()
            del polydata
            polydata = decimation.GetOutput()
            #polydata.Register(None)
            #  polydata.SetSource(None)
            del decimation

        #to_measure.Register(None)
        #  to_measure.SetSource(None)

        if keep_largest:
            conn = vtk.vtkPolyDataConnectivityFilter()
            conn.SetInputData(polydata)
            conn.SetExtractionModeToLargestRegion()
            conn_ref = weakref.ref(conn)
            conn_ref().AddObserver(
                "ProgressEvent", lambda obj, evt: UpdateProgress(
                    conn_ref(), _("Creating 3D surface...")))
            conn.Update()
            #  conn.GetOutput().ReleaseDataFlagOn()
            del polydata
            polydata = conn.GetOutput()
            #polydata.Register(None)
            #  polydata.SetSource(None)
            del conn

        #Filter used to detect and fill holes. Only fill boundary edges holes.
        #TODO: Hey! This piece of code is the same from
        #polydata_utils.FillSurfaceHole, we need to review this.
        if fill_holes:
            filled_polydata = vtk.vtkFillHolesFilter()
            #  filled_polydata.ReleaseDataFlagOn()
            filled_polydata.SetInputData(polydata)
            filled_polydata.SetHoleSize(300)
            filled_polydata_ref = weakref.ref(filled_polydata)
            filled_polydata_ref().AddObserver(
                "ProgressEvent", lambda obj, evt: UpdateProgress(
                    filled_polydata_ref(), _("Creating 3D surface...")))
            filled_polydata.Update()
            #  filled_polydata.GetOutput().ReleaseDataFlagOn()
            del polydata
            polydata = filled_polydata.GetOutput()
            #polydata.Register(None)
            #  polydata.SetSource(None)
            #  polydata.DebugOn()
            del filled_polydata

        to_measure = polydata

        # If InVesalius is running without GUI
        if wx.GetApp() is None:
            proj = prj.Project()
            #Create Surface instance
            if overwrite:
                surface = Surface(index=self.last_surface_index)
                proj.ChangeSurface(surface)
            else:
                surface = Surface(name=surface_name)
                index = proj.AddSurface(surface)
                surface.index = index
                self.last_surface_index = index
            surface.colour = colour
            surface.polydata = polydata

        # With GUI
        else:
            normals = vtk.vtkPolyDataNormals()
            #  normals.ReleaseDataFlagOn()
            normals_ref = weakref.ref(normals)
            normals_ref().AddObserver(
                "ProgressEvent", lambda obj, evt: UpdateProgress(
                    normals_ref(), _("Creating 3D surface...")))
            normals.SetInputData(polydata)
            normals.SetFeatureAngle(80)
            normals.AutoOrientNormalsOn()
            #  normals.GetOutput().ReleaseDataFlagOn()
            normals.Update()
            del polydata
            polydata = normals.GetOutput()
            #polydata.Register(None)
            #  polydata.SetSource(None)
            del normals

            # Improve performance
            stripper = vtk.vtkStripper()
            #  stripper.ReleaseDataFlagOn()
            stripper_ref = weakref.ref(stripper)
            stripper_ref().AddObserver(
                "ProgressEvent", lambda obj, evt: UpdateProgress(
                    stripper_ref(), _("Creating 3D surface...")))
            stripper.SetInputData(polydata)
            stripper.PassThroughCellIdsOn()
            stripper.PassThroughPointIdsOn()
            #  stripper.GetOutput().ReleaseDataFlagOn()
            stripper.Update()
            del polydata
            polydata = stripper.GetOutput()
            #polydata.Register(None)
            #  polydata.SetSource(None)
            del stripper

            # Map polygonal data (vtkPolyData) to graphics primitives.
            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputData(polydata)
            mapper.ScalarVisibilityOff()
            #  mapper.ReleaseDataFlagOn()
            mapper.ImmediateModeRenderingOn()  # improve performance

            # Represent an object (geometry & properties) in the rendered scene
            actor = vtk.vtkActor()
            actor.SetMapper(mapper)
            del mapper
            #Create Surface instance
            if overwrite:
                surface = Surface(index=self.last_surface_index)
            else:
                surface = Surface(name=surface_name)
            surface.colour = colour
            surface.polydata = polydata
            del polydata

            # Set actor colour and transparency
            actor.GetProperty().SetColor(colour)
            actor.GetProperty().SetOpacity(1 - surface.transparency)

            prop = actor.GetProperty()

            interpolation = int(ses.Session().surface_interpolation)

            prop.SetInterpolation(interpolation)

            proj = prj.Project()
            if overwrite:
                proj.ChangeSurface(surface)
            else:
                index = proj.AddSurface(surface)
                surface.index = index
                self.last_surface_index = index

            session = ses.Session()
            session.ChangeProject()

            measured_polydata = vtk.vtkMassProperties()
            #  measured_polydata.ReleaseDataFlagOn()
            measured_polydata.SetInputData(to_measure)
            volume = float(measured_polydata.GetVolume())
            area = float(measured_polydata.GetSurfaceArea())
            surface.volume = volume
            surface.area = area
            self.last_surface_index = surface.index
            del measured_polydata
            del to_measure

            Publisher.sendMessage('Load surface actor into viewer',
                                  actor=actor)

            # Send actor by pubsub to viewer's render
            if overwrite and self.actors_dict.keys():
                old_actor = self.actors_dict[self.last_surface_index]
                Publisher.sendMessage('Remove surface actor from viewer',
                                      actor=old_actor)

            # Save actor for future management tasks
            self.actors_dict[surface.index] = actor

            Publisher.sendMessage('Update surface info in GUI',
                                  surface=surface)

            #When you finalize the progress. The bar is cleaned.
            UpdateProgress = vu.ShowProgress(1)
            UpdateProgress(0, _("Ready"))
            Publisher.sendMessage('Update status text in GUI',
                                  label=_("Ready"))

            Publisher.sendMessage('End busy cursor')
            del actor