Ejemplo n.º 1
0
    def execute_module(self):
        # get the vtkDICOMVolumeReader to try and execute
        self._reader.Update()
        
        # now get some metadata out and insert it in our output stream

        # first determine axis labels based on IOP ####################
        iop = self._reader.GetImageOrientationPatient()
        row = iop[0:3]
        col = iop[3:6]
        # the cross product (plane normal) based on the row and col will
        # also be in the LPH coordinate system
        norm = [0,0,0]
        vtk.vtkMath.Cross(row, col, norm)

        xl = misc_utils.major_axis_from_iop_cosine(row)
        yl = misc_utils.major_axis_from_iop_cosine(col)
        zl = misc_utils.major_axis_from_iop_cosine(norm)

        lut = {'L' : 0, 'R' : 1, 'P' : 2, 'A' : 3, 'F' : 4, 'H' : 5}

        if xl and yl and zl:
            # add this data as a vtkFieldData
            fd = self._reader.GetOutput().GetFieldData()

            axis_labels_array = vtk.vtkIntArray()
            axis_labels_array.SetName('axis_labels_array')

            for l in xl + yl + zl:
                axis_labels_array.InsertNextValue(lut[l])

            fd.AddArray(axis_labels_array)
Ejemplo n.º 2
0
    def execute_module(self):
        # get the vtkDICOMVolumeReader to try and execute
        self._reader.Update()

        # now get some metadata out and insert it in our output stream

        # first determine axis labels based on IOP ####################
        iop = self._reader.GetImageOrientationPatient()
        row = iop[0:3]
        col = iop[3:6]
        # the cross product (plane normal) based on the row and col will
        # also be in the LPH coordinate system
        norm = [0, 0, 0]
        vtk.vtkMath.Cross(row, col, norm)

        xl = misc_utils.major_axis_from_iop_cosine(row)
        yl = misc_utils.major_axis_from_iop_cosine(col)
        zl = misc_utils.major_axis_from_iop_cosine(norm)

        lut = {'L': 0, 'R': 1, 'P': 2, 'A': 3, 'F': 4, 'H': 5}

        if xl and yl and zl:
            # add this data as a vtkFieldData
            fd = self._reader.GetOutput().GetFieldData()

            axis_labels_array = vtk.vtkIntArray()
            axis_labels_array.SetName('axis_labels_array')

            for l in xl + yl + zl:
                axis_labels_array.InsertNextValue(lut[l])

            fd.AddArray(axis_labels_array)
Ejemplo n.º 3
0
    def _update_image(self, gdcm_reader):
        """Given a vtkGDCMImageReader instance that has read the given
        file, update the image viewer.
        """

        r = gdcm_reader

        self._image_viewer.SetInput(r.GetOutput())
        #if r.GetNumberOfOverlays():
        #    self._image_viewer.AddInput(r.GetOverlay(0))

        # now make the nice text overlay thingies!

        # DirectionCosines: first two columns are X and Y in the LPH
        # coordinate system
        dc = r.GetDirectionCosines()

        x_cosine = \
                dc.GetElement(0,0), dc.GetElement(1,0), dc.GetElement(2,0)

        lph = misc_utils.major_axis_from_iop_cosine(x_cosine)
        if lph:
            self._image_viewer.xl_text_actor.SetInput(lph[0])
            self._image_viewer.xr_text_actor.SetInput(lph[1])
        else:
            self._image_viewer.xl_text_actor.SetInput('X')
            self._image_viewer.xr_text_actor.SetInput('X')

        y_cosine = \
                dc.GetElement(0,1), dc.GetElement(1,1), dc.GetElement(2,1)
        lph = misc_utils.major_axis_from_iop_cosine(y_cosine)

        if lph:
            if r.GetFileLowerLeft():
                # no swap
                b = lph[0]
                t = lph[1]
            else:
                # we have to swap these around because VTK has the
                # convention of image origin at the upper left and GDCM
                # dutifully swaps the images when loading to follow this
                # convention.  Direction cosines (IOP) is not swapped, so
                # we have to compensate here.
                b = lph[1]
                t = lph[0]

            self._image_viewer.yb_text_actor.SetInput(b)
            self._image_viewer.yt_text_actor.SetInput(t)

        else:
            self._image_viewer.yb_text_actor.SetInput('X')
            self._image_viewer.yt_text_actor.SetInput('X')

        mip = r.GetMedicalImageProperties()
        
        d = r.GetOutput().GetDimensions()

        ul = self._image_viewer.ul_text_actor
        ul.imsize = (d[0], d[1])
        ul.imnum = mip.GetImageNumber() # string
        ul.frnum = self._image_viewer.GetSlice()
        self._update_image_ul_text()

        ur = self._image_viewer.ur_text_actor
        ur.SetInput('%s\n%s\n%s\n%s' % (
            mip.GetPatientName(),
            mip.GetPatientID(),
            mip.GetStudyDescription(),
            mip.GetSeriesDescription()))

        br = self._image_viewer.br_text_actor
        br.SetInput('DeVIDE\nTU Delft')

        # we have a new image in the image_viewer, so we have to reset
        # the camera so that the image is visible.
        if not self._config.lock_pz:
            self._reset_image_pz()

        # also reset window level
        if not self._config.lock_wl:
            self._reset_image_wl()

        self._image_viewer.Render()
Ejemplo n.º 4
0
    def execute_module(self):
        # have to  cast to normal strings (from unicode)
        filenames = [str(i) for i in self._config.dicom_filenames]

        # make sure all is zeroed.
        self._reader.SetFileName(None)
        self._reader.SetFileNames(None)

        # we only sort and derive slice-based spacing if there are
        # more than 1 filenames
        if len(filenames) > 1:
            sorter = gdcm.IPPSorter()
            sorter.SetComputeZSpacing(True)
            sorter.SetZSpacingTolerance(1e-2)

            ret = sorter.Sort(filenames)
            alpha_sorted = False
            if not ret:
                if self._config.robust_spacing:
                    self._module_manager.log_warning(
                        'Could not sort DICOM filenames by IPP. Doing alphabetical sorting.')
                    filenames.sort()
                    alpha_sorted = True
                    
                else:
                    raise RuntimeError(
                    'Could not sort DICOM filenames before loading.')

            if sorter.GetZSpacing() == 0.0 and not alpha_sorted:
                msg = 'DICOM IPP sorting yielded incorrect results.'
                raise RuntimeError(msg)

            # then give the reader the sorted list of files
            sa = vtk.vtkStringArray()
            if alpha_sorted:
                flist = filenames
            else:
                flist = sorter.GetFilenames()
                
            for fn in flist: 
                sa.InsertNextValue(fn)

            self._reader.SetFileNames(sa)

        elif len(filenames) == 1:
            self._reader.SetFileName(filenames[0])

        else:
            raise RuntimeError(
                    'No DICOM filenames to read.')

        # now do the actual reading
        self._reader.Update()

        # see what the reader thinks the spacing is
        spacing = list(self._reader.GetDataSpacing())

        if len(filenames) > 1 and not alpha_sorted:
            # after the reader has done its thing,
            # impose derived spacing on the vtkImageChangeInformation
            # (by default it takes the SpacingBetweenSlices, which is
            # not always correct)
            spacing[2] = sorter.GetZSpacing()

        # single or multiple filenames, we have to set the correct
        # output spacing on the image change information
        print "SPACING: ", spacing
        self._ici.SetOutputSpacing(spacing)
        self._ici.Update()


        # integrate DirectionCosines into output data ###############
        # DirectionCosines: first two columns are X and Y in the LPH
        # coordinate system
        dc = self._reader.GetDirectionCosines()

        x_cosine = \
                dc.GetElement(0,0), dc.GetElement(1,0), dc.GetElement(2,0)
        y_cosine = \
                dc.GetElement(0,1), dc.GetElement(1,1), dc.GetElement(2,1)

        # calculate plane normal (z axis) in LPH coordinate system by taking the cross product
        norm = [0,0,0]
        vtk.vtkMath.Cross(x_cosine, y_cosine, norm)

        xl = misc_utils.major_axis_from_iop_cosine(x_cosine)
        yl = misc_utils.major_axis_from_iop_cosine(y_cosine)

        # vtkGDCMImageReader swaps the y (to fit the VTK convention),
        # but does not flip the DirectionCosines here, so we do that.
        # (only if the reader is flipping)
        if yl and not self._reader.GetFileLowerLeft():
            yl = tuple((yl[1], yl[0]))

        zl = misc_utils.major_axis_from_iop_cosine(norm)

        lut = {'L' : 0, 'R' : 1, 'P' : 2, 'A' : 3, 'F' : 4, 'H' : 5}
    
        if xl and yl and zl:
            # add this data as a vtkFieldData
            fd = self._ici.GetOutput().GetFieldData()

            axis_labels_array = vtk.vtkIntArray()
            axis_labels_array.SetName('axis_labels_array')

            for l in xl + yl + zl:
                axis_labels_array.InsertNextValue(lut[l])

            fd.AddArray(axis_labels_array)
Ejemplo n.º 5
0
    def _update_image(self, gdcm_reader):
        """Given a vtkGDCMImageReader instance that has read the given
        file, update the image viewer.
        """

        r = gdcm_reader

        self._image_viewer.SetInput(r.GetOutput())
        #if r.GetNumberOfOverlays():
        #    self._image_viewer.AddInput(r.GetOverlay(0))

        # now make the nice text overlay thingies!

        # DirectionCosines: first two columns are X and Y in the LPH
        # coordinate system
        dc = r.GetDirectionCosines()

        x_cosine = \
                dc.GetElement(0,0), dc.GetElement(1,0), dc.GetElement(2,0)

        lph = misc_utils.major_axis_from_iop_cosine(x_cosine)
        if lph:
            self._image_viewer.xl_text_actor.SetInput(lph[0])
            self._image_viewer.xr_text_actor.SetInput(lph[1])
        else:
            self._image_viewer.xl_text_actor.SetInput('X')
            self._image_viewer.xr_text_actor.SetInput('X')

        y_cosine = \
                dc.GetElement(0,1), dc.GetElement(1,1), dc.GetElement(2,1)
        lph = misc_utils.major_axis_from_iop_cosine(y_cosine)

        if lph:
            if r.GetFileLowerLeft():
                # no swap
                b = lph[0]
                t = lph[1]
            else:
                # we have to swap these around because VTK has the
                # convention of image origin at the upper left and GDCM
                # dutifully swaps the images when loading to follow this
                # convention.  Direction cosines (IOP) is not swapped, so
                # we have to compensate here.
                b = lph[1]
                t = lph[0]

            self._image_viewer.yb_text_actor.SetInput(b)
            self._image_viewer.yt_text_actor.SetInput(t)

        else:
            self._image_viewer.yb_text_actor.SetInput('X')
            self._image_viewer.yt_text_actor.SetInput('X')

        mip = r.GetMedicalImageProperties()

        d = r.GetOutput().GetDimensions()

        ul = self._image_viewer.ul_text_actor
        ul.imsize = (d[0], d[1])
        ul.imnum = mip.GetImageNumber()  # string
        ul.frnum = self._image_viewer.GetSlice()
        self._update_image_ul_text()

        ur = self._image_viewer.ur_text_actor
        ur.SetInput('%s\n%s\n%s\n%s' %
                    (mip.GetPatientName(), mip.GetPatientID(),
                     mip.GetStudyDescription(), mip.GetSeriesDescription()))

        br = self._image_viewer.br_text_actor
        br.SetInput('DeVIDE\nTU Delft')

        # we have a new image in the image_viewer, so we have to reset
        # the camera so that the image is visible.
        if not self._config.lock_pz:
            self._reset_image_pz()

        # also reset window level
        if not self._config.lock_wl:
            self._reset_image_wl()

        self._image_viewer.Render()