コード例 #1
0
def fourier_rotate_vol(v, angle):
    """
    """
    if v.dtype != np.dtype('float32') or np.isfortran(v) is False:
        v = np.array(v, dtype="float32", order="F")

    # get the rotation matrix
    from pytom.basic.structures import Rotation
    rot = Rotation(angle)
    m = rot.toMatrix()
    m = m.transpose()  # get the invert rotation matrix
    m = np.array([m.getRow(0), m.getRow(1), m.getRow(2)], dtype="float32")
    m = m.flatten()

    dim_x, dim_y, dim_z = v.shape

    # # Do the ifftshift first and then fftshift!
    # v = np.fft.fftshift(np.fft.ifftshift(v))

    # linearize it
    v = v.reshape((v.size))

    # allocate the memory for the result
    res = np.zeros(v.size * 2, dtype="float32")

    # call the low level c function
    swig_nufft.fourier_rotate_vol(v, dim_x, dim_y, dim_z, m, res)

    res = res[::2] + 1j * res[1::2]
    res = res.reshape((dim_x, dim_y, dim_z), order='F')

    # inverse fft
    ans = np.fft.fftshift(np.real(np.fft.ifftn(np.fft.ifftshift(res))))

    return np.array(ans, dtype="float32", order="F")
コード例 #2
0
    def nextRotation(self):
        """
        nextRotation : 
        @return: [z1 z2 x] for the next rotation or [None,None,None] after all rotations were sampled
        @author: Friedrich Foerster
        @change: Local Rotation had a bug causing too large rotations in Phi
        @date: 07/07/2014
        """

        if self._finished:
            return [None, None, None]

        from math import sin, ceil, pi, sqrt, atan2  #,modf
        from pytom.basic.structures import Rotation
        from pytom.angles.angleFnc import matToZXZ

        phi = self._currentZ1
        if self._currentX == 0:
            npsi = 1
            dpsi = 360.
        else:
            dpsi = self._increment / sin(
                float(self._currentX * self._increment) / 180. * pi)
            npsi = ceil(360. / dpsi)
            #make dpsi equidistant again
            dpsi = 360. / npsi

        localRotation = Rotation(z1=phi - self._currentZ2 * dpsi,
                                 z2=self._currentZ2 * dpsi,
                                 x=self._currentX * self._increment,
                                 paradigm='ZXZ')

        globalMatrix = localRotation.toMatrix() * self._startMatrix

        [phi, psi, theta] = matToZXZ(globalMatrix)

        if self._currentZ2 >= npsi - 1:
            self._currentZ2 = 0
            if self._currentX >= ceil(self._shells / 2):
                self._currentX = 0
                if self._currentZ1 >= self._shells * self._increment:
                    self._finished = True
                    return [self._startZ1, self._startZ2, self._startX]
                else:
                    self._currentZ1 = self._currentZ1 + self._increment
            else:
                self._currentX = self._currentX + 1
        else:
            self._currentZ2 = self._currentZ2 + 1

        return [phi % 360, psi % 360, theta % 360]
コード例 #3
0
ファイル: maths.py プロジェクト: xmzzaa/PyTom
 def __init__(self, rotation, translation):
     from pytom.basic.structures import Rotation, Shift
     if rotation.__class__ == Rotation:
         pass
     elif rotation.__class__ == list:
         rotation = Rotation(rotation)
     else:
         raise RuntimeError("Rotation should be of type list or pytom.basic.structures.Rotation!")
     if not isinstance(translation, (Shift, list)):
         raise RuntimeError("Translation should be of type list or pytom.basic.structures.Shift!")
     
     super(TransformationMatrix, self).__init__(4,4)
     self.setRotationCoef(rotation.toMatrix())
     self.setTranslationCoef(translation)
コード例 #4
0
def fourier_rotate_vol(v, angle):
    """Be careful with rotating a odd-sized volume, since nfft will not give correct result!
	"""
    # get the rotation matrix
    from pytom.basic.structures import Rotation
    rot = Rotation(angle)
    m = rot.toMatrix()
    m = m.transpose()  # get the invert rotation matrix
    m = np.array([m.getRow(0), m.getRow(1), m.getRow(2)], dtype="float32")
    m = m.flatten()

    # prepare the volume
    from pytom_numpy import vol2npy

    v = vol2npy(v)
    dim_x, dim_y, dim_z = v.shape

    # twice shift means no shift!
    # v = np.fft.fftshift(v)

    # linearize it
    v = v.reshape((v.size))

    # allocate the memory for the result
    res = np.zeros(v.size * 2, dtype="float32")

    # call the low level c function
    swig_nufft.fourier_rotate_vol(v, dim_x, dim_y, dim_z, m, res)

    res = res[::2] + 1j * res[1::2]
    res = res.reshape((dim_x, dim_y, dim_z), order='F')

    # inverse fft
    ans = np.fft.ifftshift(np.real(np.fft.ifftn(np.fft.ifftshift(res))))

    # transfer to pytom volume format
    from sh.frm import np2vol
    res = np2vol(ans)

    return res
コード例 #5
0
def fourier_2d1d_iter_reconstruct(projections, tilt_angles, iteration=10, err=None):
    """Do the reconstruction on a projection list using direct Fourier inversion (2D+1D iterative).
    For noisy situation, the #iter should be small
    @param projections: projections
    @param tilt_angles: tilt angles of projections
    @param err: the percentage of allowed error
    """
    from pytom.basic.structures import Rotation

    if len(projections) != len(tilt_angles):
        raise Exception("Length of projections and tilt angles not consistent!")

    freal = None # Fourier coefficients
    fimag = None
    kx = None # nodes positions
    kz = None
    weights = None # weights

    for i in range(len(tilt_angles)):
        proj = projections[i]
        if len(proj.shape) == 3:
            NX, NY, NZ = proj.shape
            assert NZ == 1 and NX == NY # for now only supports the square
            proj = proj.reshape((NX, NY)) # make it 2D
        elif len(proj.shape) == 2:
            NX, NY = proj.shape
            NZ = 1
        else:
            raise Exception("Projection shape incorrect!")

        if i == 0:
            # nodes in 0 degree
            x, y = np.meshgrid(np.array(np.linspace(-0.5, 0.5, NX, endpoint=False), dtype="float32"), np.array(np.linspace(-0.5, 0.5, NY, endpoint=False), dtype="float32"))
            x = x.reshape((1, x.size))
            y = y.reshape((1, y.size))
            z = np.zeros(x.size, dtype="float32")
            xyz = np.vstack((x,y,z))

            freal = np.zeros((NX, NY, len(tilt_angles)), dtype="float32")
            fimag = np.zeros((NX, NY, len(tilt_angles)), dtype="float32")

        # do the 2D Fourier transform on each projection
        fproj = np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(proj)))
        freal[:,:,i] = np.array(np.real(fproj), dtype="float32")
        fimag[:,:,i] = np.array(np.imag(fproj), dtype="float32")

        # calculate the nodes positions
        ang = tilt_angles[i] # get the tilt angle of this projection
        rot = Rotation([270, 90, ang]) # rotate around y axis
        m = rot.toMatrix()
        m = np.array([m.getRow(0), m.getRow(1), m.getRow(2)], dtype="float32")
        kk = np.dot(m, xyz)
        kk = np.array(kk, dtype="float32")
        if kx is None:
            kx = kk[0][:NX]
            kz = kk[2][:NX]
        else:
            kx = np.hstack((kx, kk[0][:NX]))
            kz = np.hstack((kz, kk[2][:NX]))

        # compute the weights
        if i == 0:
            ang_interval = tilt_angles[1]-tilt_angles[0]
        elif i == len(tilt_angles)-1:
            ang_interval = tilt_angles[-1]-tilt_angles[-2]
        else:
            ang_interval = (tilt_angles[i+1] - tilt_angles[i-1])/2
        w = np.abs(ang_interval/180.*np.pi*(np.array(list(range(NX//2, -NX//2, -1)), dtype="float32")*2)/(NX//2)**2)
        w[NX//2] = np.pi/(4*len(tilt_angles)*(NX//2)**2) # take care of the duplicates
        if weights is None:
            weights = w.reshape((w.size))
        else:
            weights = np.hstack((weights, w.reshape((w.size))))

    # change the Y and Z axis
    freal = np.swapaxes(freal, 1,2)
    freal = freal.reshape((freal.size), order="F")
    fimag = np.swapaxes(fimag, 1,2)
    fimag = fimag.reshape((fimag.size), order="F")

    # construct the damping factors
    damping = np.ones((NX, NX), dtype="float32")
    # radius = 25
    # sigma = 5
    # [xx, yy] = np.mgrid[0:NX, 0:NX]
    # rr = np.sqrt((xx-NX/2)**2+(yy-NX/2)**2)
    # ind = rr>radius
    # damping[ind] = np.exp(-((rr[ind] - radius)/sigma)**2/2)
    damping = damping.reshape((damping.size))

    # estimate the variance of the noise
    if err and err > 0:
        data = np.array(projections)
        var_all = np.var(data)
        var_err = err*var_all
        threshold = var_err
    else:
        threshold = -1

    # reconstruct
    M = freal.size
    Z = NX
    res_real = np.zeros(NX*NY*Z, dtype="float32")
    res_imag = np.zeros(NX*NY*Z, dtype="float32")
    weights = np.float32(weights)

    # weird!
    print(weights.shape, weights.dtype)
    swig_nufft.fourier_2d1d_iter_reconstruct(freal, fimag, NX, Z, M, weights, kz, kx, res_real, res_imag, iteration, threshold, damping)

    # resize and return the real part
    res = res_real.reshape((NX,NY,Z), order="F") # weird!
    res = np.swapaxes(res, 1,2) # weird!

    return res
コード例 #6
0
def fourier_3d_iter_reconstruct(projections, tilt_angles, iteration=10):
    """Do the reconstruction on a projection list using direct Fourier inversion (3D iterative).
    @param projections: projections
    @param tilt_angles: tilt angles of projections
    """
    from pytom.basic.structures import Rotation

    if len(projections) != len(tilt_angles):
        raise Exception("Length of projections and tilt angles not consistent!")

    freal = None # Fourier coefficients
    fimag = None
    kx = None # nodes positions
    ky = None
    kz = None
    weights = None # weights

    for i in range(len(tilt_angles)):
        proj = projections[i]
        NX, NY, NZ = proj.shape
        assert NZ == 1 and NX == NY # for now only supports the square
        proj = proj.reshape((NX, NY)) # make it 2D

        if i == 0:
            # nodes in 0 degree
            x, y = np.meshgrid(np.array(np.linspace(-0.5, 0.5, NX, endpoint=False), dtype="float32"), np.array(np.linspace(-0.5, 0.5, NY, endpoint=False), dtype="float32"))
            x = x.reshape((1, x.size))
            y = y.reshape((1, y.size))
            z = np.zeros(x.size, dtype="float32")
            xyz = np.vstack((x,y,z))

        # do the 2D Fourier transform on each projection
        fproj = np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(proj)))
        fproj_real = np.array(np.real(fproj), dtype="float32")
        fproj_imag = np.array(np.imag(fproj), dtype="float32")

        if freal is None:
            freal = fproj_real.reshape((fproj_real.size), order='F') # to be consistent with the order of kx,ky,kz
            fimag = fproj_imag.reshape((fproj_imag.size), order='F')
        else:
            freal = np.hstack((freal, fproj_real.reshape((fproj_real.size), order='F') ))
            fimag = np.hstack((fimag, fproj_imag.reshape((fproj_imag.size), order='F') ))

        # calculate the nodes positions
        ang = tilt_angles[i] # get the tilt angle of this project
        rot = Rotation([270, 90, ang]) # rotate around y axis
        m = rot.toMatrix()
        m = np.array([m.getRow(0), m.getRow(1), m.getRow(2)], dtype="float32")
        kk = np.dot(m, xyz)
        if kx is None:
            kx = kk[0]
            ky = kk[1]
            kz = kk[2]
        else:
            kx = np.hstack((kx, kk[0]))
            ky = np.hstack((ky, kk[1]))
            kz = np.hstack((kz, kk[2]))

        # compute the weights
        if i == 0:
            ang_interval = tilt_angles[1]-tilt_angles[0]
        elif i == len(tilt_angles)-1:
            ang_interval = tilt_angles[-1]-tilt_angles[-2]
        else:
            ang_interval = (tilt_angles[i+1] - tilt_angles[i-1])/2
        w = np.abs(ang_interval/360.*(np.array(list(range(NX//2, -NX//2, -1)), dtype="float32")*2))
        wei = np.tile(w, (NY, 1))
        if weights is None:
            weights = wei.reshape((wei.size))
        else:
            weights = np.hstack((weights, wei.reshape((wei.size))))

    # reconstruct
    M = freal.size
    Z = NX
    res_real = np.zeros(NX*NY*Z, dtype="float32")
    res_imag = np.zeros(NX*NY*Z, dtype="float32")
    weights = np.float32(weights)

    swig_nufft.fourier_3d_iter_reconstruct(freal, fimag, NX, Z, M, weights, kx, ky, kz, res_real, res_imag, iteration)

    # resize and return the real part
    res = res_real.reshape((NX,NY,Z))

    return res
コード例 #7
0
def fourier_2d1d_gridding_reconstruct(projections, tilt_angles):
    """Do the reconstruction on a projection list using direct Fourier inversion (2D+1D gridding).
    @param projections: projections
    @param tilt_angles: tilt angles of projections
    """
    from pytom.basic.structures import Rotation

    if len(projections) != len(tilt_angles):
        raise Exception("Length of projections and tilt angles not consistent!")

    freal = None # Fourier coefficients
    fimag = None
    kx = None # nodes positions
    kz = None
    weights = None # weights

    for i in range(len(tilt_angles)):
        proj = projections[i]
        NX, NY, NZ = proj.shape
        assert NZ == 1 and NX == NY # for now only supports the square
        proj = proj.reshape((NX, NY)) # make it 2D

        if i == 0:
            # nodes in 0 degree
            x, y = np.meshgrid(np.array(np.linspace(-0.5, 0.5, NX, endpoint=False), dtype="float32"), np.array(np.linspace(-0.5, 0.5, NY, endpoint=False), dtype="float32"))
            x = x.reshape((1, x.size))
            y = y.reshape((1, y.size))
            z = np.zeros(x.size, dtype="float32")
            xyz = np.vstack((x,y,z))

            freal = np.zeros((NX, NY, len(tilt_angles)), dtype="float32")
            fimag = np.zeros((NX, NY, len(tilt_angles)), dtype="float32")

        # do the 2D Fourier transform on each projection
        fproj = np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(proj)))
        freal[:,:,i] = np.array(np.real(fproj), dtype="float32")
        fimag[:,:,i] = np.array(np.imag(fproj), dtype="float32")

        # calculate the nodes positions
        ang = tilt_angles[i] # get the tilt angle of this project
        rot = Rotation([270, 90, ang]) # rotate around y axis
        m = rot.toMatrix()
        m = np.array([m.getRow(0), m.getRow(1), m.getRow(2)], dtype="float32")
        kk = np.dot(m, xyz)
        if kx is None:
            kx = kk[0][:NX]
            kz = kk[2][:NX]
        else:
            kx = np.hstack((kx, kk[0][:NX]))
            kz = np.hstack((kz, kk[2][:NX]))

        # compute the weights
        if i == 0:
            ang_interval = tilt_angles[1]-tilt_angles[0]
        elif i == len(tilt_angles)-1:
            ang_interval = tilt_angles[-1]-tilt_angles[-2]
        else:
            ang_interval = (tilt_angles[i+1] - tilt_angles[i-1])/2
        w = np.abs(ang_interval/180.*np.pi*(np.array(list(range(NX//2, -NX//2, -1)), dtype="float32")*2)/(NX//2)**2)
        w[NX//2] = np.pi/(4*len(tilt_angles)*(NX//2)**2) # take care of the duplicates
        if weights is None:
            weights = w.reshape((w.size))
        else:
            weights = np.hstack((weights, w.reshape((w.size))))

    # change the Y and Z axis
    freal = np.swapaxes(freal, 1,2)
    freal = freal.reshape((freal.size), order="F")
    fimag = np.swapaxes(fimag, 1,2)
    fimag = fimag.reshape((fimag.size), order="F")

    # reconstruct
    M = freal.size
    Z = NX
    res_real = np.zeros(NX*NY*Z, dtype="float32")
    res_imag = np.zeros(NX*NY*Z, dtype="float32")
    weights = np.float32(weights)

    # weird!
    swig_nufft.fourier_2d1d_gridding_reconstruct(freal, fimag, NX, Z, M, weights, kz, kx, res_real, res_imag)

    # resize and return the real part
    res = res_real.reshape((NX,NY,Z), order="F") # weird!
    res = np.swapaxes(res, 1,2) # weird!

    return res
コード例 #8
0
class LocalSampling(AngleObject):
    """
    LocalSampling: Angular sampling identical to the AV3 package. \
    See http://pytom.org/doc/pytom/alignment.html for more information.
    """
    def __init__(self,
                 shells=3,
                 increment=3,
                 z1Start=0.0,
                 z2Start=0.0,
                 xStart=0.0):
        """
        @param shells: Number of shells to be scanned
        @param increment: Angular increment used
        @param z1Start: Start angle for Z1 rotation 
        @param z2Start: Start angle for Z2 rotation 
        @param xStart: Start angle for X rotation 
        @author: Thomas Hrabe     
        """
        from pytom.basic.structures import Rotation
        self._shells = float(shells)

        if increment == 0.0:
            raise ValueError('LocalSampling : Increment is 0!')
        else:
            self._increment = float(increment)

        if shells == 0:
            raise ValueError('LocalSampling : Shells is 0!')

        self.setStartRotation(Rotation(z1=z1Start, z2=z2Start, x=xStart))
        # initialize final rotation around z-axis of REFERENCE
        self.reset()

    def setStartRotation(self, startRotation):
        """
        setStartRotation: Sets start rotation.
        @param startRotation: The start rotation.
        @type startRotation: L{pytom.basic.structures.Rotation}
        @return: Reference to current object
        @author: FF
        """
        from pytom.basic.structures import Rotation

        self._startZ1 = float(startRotation[0])
        self._startZ2 = float(startRotation[1])
        self._startX = float(startRotation[2])

        self._startRotation = Rotation(z1=self._startZ1,
                                       z2=self._startZ2,
                                       x=self._startX,
                                       paradigm='ZXZ')

        self._startMatrix = self._startRotation.toMatrix()
        self.reset()

        return self

    def getNumberShells(self):
        """
        get number of shells for alignment

        @return: number of shells
        @rtype: L{int}
        """
        return self._shells

    def setNumberShells(self, shells):
        """
        set number of shells
        @param shells: number of shells
        @type shells: L{int}
        """
        self._shells = shells

    def getIncrement(self):
        """
        get angular increment
        @return: angular increment
        @rtype: L{float}
        """
        return self._increment

    def setIncrement(self, increment):
        """
        set angular increment
        @param increment: new increment in deg
        @type increment: L{float}
        @author: FF
        """
        self._increment = increment

    def nextRotation(self):
        """
        nextRotation : 
        @return: [z1 z2 x] for the next rotation or [None,None,None] after all rotations were sampled
        @author: Friedrich Foerster
        @change: Local Rotation had a bug causing too large rotations in Phi
        @date: 07/07/2014
        """

        if self._finished:
            return [None, None, None]

        from math import sin, ceil, pi, sqrt, atan2  #,modf
        from pytom.basic.structures import Rotation
        from pytom.angles.angleFnc import matToZXZ

        phi = self._currentZ1
        if self._currentX == 0:
            npsi = 1
            dpsi = 360.
        else:
            dpsi = self._increment / sin(
                float(self._currentX * self._increment) / 180. * pi)
            npsi = ceil(360. / dpsi)
            #make dpsi equidistant again
            dpsi = 360. / npsi

        localRotation = Rotation(z1=phi - self._currentZ2 * dpsi,
                                 z2=self._currentZ2 * dpsi,
                                 x=self._currentX * self._increment,
                                 paradigm='ZXZ')

        globalMatrix = localRotation.toMatrix() * self._startMatrix

        [phi, psi, theta] = matToZXZ(globalMatrix)

        if self._currentZ2 >= npsi - 1:
            self._currentZ2 = 0
            if self._currentX >= ceil(self._shells / 2):
                self._currentX = 0
                if self._currentZ1 >= self._shells * self._increment:
                    self._finished = True
                    return [self._startZ1, self._startZ2, self._startX]
                else:
                    self._currentZ1 = self._currentZ1 + self._increment
            else:
                self._currentX = self._currentX + 1
        else:
            self._currentZ2 = self._currentZ2 + 1

        return [phi % 360, psi % 360, theta % 360]

    def focusRotation(self, rotation=None, refinementAngle=10):
        """
        focusRotation: Will focus this object on a given rotation by tightening the scan area. 
        @param rotation: The rotation to focus on
        @type rotation: [phi,psi,theta] list 
        @return: New LocaLSampling object
        @rtype: L{pytom.angles.localSampling.LocalSampling}
        @author: Thomas Hrabe 
        """
        if not rotation:
            rotation = [0, 0, 0]

        if not refinementAngle:
            refinementAngle = 10

        return LocalSampling(self._shells, refinementAngle, rotation[0],
                             rotation[1], rotation[2])

    def distanceFunction(self, rotation):
        """
        distanceFunction: determines the distance of of given rotation to old rotation
        @param rotation: rotation
        @type rotation: L{pytom.basic.structures.Rotation}
        @return: proposed increment for next iteration
        @author: FF
        """
        from pytom.tools.maths import rotation_distance
        increment = rotation_distance(ang1=self._startRotation, ang2=rotation)

        #from math import sqrt,ceil
        #sqrt2 = 1.4142135623730951
        ##must modulo 360 each value for avoiding negative values
        #deltaTheta  = (self._startX % 360) - (rotation[2] % 360)
        #deltaPhi    = (self._startZ1 % 360)   - (rotation[0] % 360)
        #
        #increment   = sqrt(pow(deltaTheta,2)+pow(deltaPhi,2)) / sqrt2

        return increment

    def toXML(self):
        from lxml import etree

        try:
            angles_element = etree.Element("Angles", Type='AV3Sampling')
            angles_element.set("Increment", str(self._increment))
            angles_element.set("Shells", str(self._shells))
            angles_element.set("Phi_old", str(self._startZ1))
            angles_element.set("Psi_old", str(self._startZ2))
            angles_element.set("Theta_old", str(self._startX))
            angles_element.set("ShellsParameter", str(self._shellsParameter))
            angles_element.set("IncrementParameter",
                               str(self._incrementParameter))
        except:
            angles_element = etree.Element("Angles", Type='LocalSampling')
            angles_element.set("Increment", str(self._increment))
            angles_element.set("Shells", str(self._shells))
            angles_element.set("StartZ1", str(self._startZ1))
            angles_element.set("StartZ2", str(self._startZ2))
            angles_element.set("StartX", str(self._startX))

        return angles_element

    def fromXML(self, xmlObj=-1):
        """
        fromXML : Assigns values to job attributes from XML object
        @param xmlObj: A xml object  
        @author: Thomas Hrabe 
        """
        from lxml.etree import _Element
        from pytom.basic.structures import Rotation

        if xmlObj.__class__ != _Element or xmlObj.get('Type') not in [
                'LocalSampling', 'Equidistant', 'AV3Sampling'
        ]:
            raise TypeError(
                'You must provide a valid XML-LocalSampling object.')

        if xmlObj.get('Type') == 'Equidistant':
            xmlObj = xmlObj.xpath('Parameters')[0]

        try:
            self._increment = float(xmlObj.get('Increment'))
        except TypeError:
            self._increment = float(xmlObj.get('AngleIncrement'))

        try:
            self._shells = float(xmlObj.get('Shells'))
        except TypeError:
            self._shells = float(xmlObj.get('NumberShells'))

        try:
            self._startZ1 = float(xmlObj.get('StartZ1'))
            self.av3 = False
        except:
            self._startZ1 = float(xmlObj.get('Phi_old'))
            self.av3 = True
        try:
            self._startZ2 = float(xmlObj.get('StartZ2'))
        except:
            self._startZ2 = float(xmlObj.get('Psi_old'))
        try:
            self._startX = float(xmlObj.get('StartX'))
        except:
            self._startX = float(xmlObj.get('Theta_old'))

        if self.av3:
            try:
                self._shellsParameter = int(xmlObj.get('ShellsParameter'))
            except TypeError:
                raise Exception('No ShellsParameter Defined')
            try:
                self._incrementParameter = int(
                    xmlObj.get('IncrementParameter'))
            except TypeError:
                raise Exception('No IncrementParameter Defined')

        self.reset()

        self.setStartRotation(startRotation=Rotation(
            z1=self._startZ1, z2=self._startZ2, x=self._startX))

    def numberRotations(self):
        """
        numberRotations: Returns the total number of rotations for the current object
        @author: Thomas Hrabe 
        """

        ang = [0, 0, 0]
        counter = 0

        while not ang == [None, None, None]:
            ang = self.nextRotation()
            counter = counter + 1

        self.reset()

        return counter

    def reset(self):
        """
        reset: Resets the object that nextRotation would return the same sequence of results again
        @author: FF
        """
        self._currentZ1 = -1. * self._shells * self._increment
        self._currentZ2 = 0
        self._currentX = 0
        self._finished = False
        #self._startRotation = None

    def copy(self, rotation):
        """
        copy: Copies the current angle object to a new one with same settings but different starting rotation
        @param rotation: The other starting rotation   
        @author: Thomas Hrabe 
        """
        if rotation.__class__ == list:
            return LocalSampling(self._shells, self._increment, rotation[0],
                                 rotation[1], rotation[2])
        else:
            return LocalSampling(self._shells, self._increment,
                                 rotation.getPhi(), rotation.getPsi(),
                                 rotation.getTheta())
コード例 #9
0
ファイル: transformations.py プロジェクト: xmzzaa/PyTom
def general_transform(v, rot=None, shift=None, scale=None, order=[0, 1, 2]):
    """Perform general transformation using 3rd order spline interpolation.
    @param v: volume
    @type v: L{pytom_volume.vol}
    @param rot: rotate
    @type rot: pytom.basic.structures.Rotate or list
    @param shift: shift
    @type shift: pytom.basic.structures.Shift or list
    @param scale: scale / magnification along each dimension
    @type scale: list
    @param order: the order in which the three operations are performed (smaller means first)
    @type order: list
    @return: pytom_volume
    """
    from pytom.basic.structures import Rotation, Shift

    from pytom_volume import vol
    if not isinstance(v,vol):
        raise TypeError('general_transform: v must be of type pytom_volume.vol! Got ' + str(v.__class__) + ' instead!')

    if rot is None:
        rot = Rotation(0.,0.,0.)
    if rot.__class__ == list and len(rot) == 3:
        rot = Rotation(rot[0], rot[1], rot[2])
    if shift is None:
        shift = Shift(0.,0.,0.)
    if shift.__class__ == list and len(shift) == 3:
        shift = Shift(shift[0], shift[1], shift[2])
    if scale is None:
        scale = [1.0, 1.0, 1.0]
    if scale.__class__ == list and len(scale) == 3:
        #check
        if int(v.sizeX()*scale[0]) < 1 or int(v.sizeY()*scale[1]) < 1 or int(v.sizeZ()*scale[2]) < 1:
            raise Exception("Scale not possible! Please check all the dimension after scaling is bigger than 1!")
    else:
        raise Exception("Scale parameter invalid! Should be a list of 3 values!")
    
    from pytom_volume import vol, general_transform
    from pytom.tools.maths import Matrix
    
    # invert matrix
    rotM = rot.toMatrix(True)
    shiftM = shift.toMatrix()
    scaleM = Matrix(4,4)
    scaleM[0,0] = scale[0]
    scaleM[1,1] = scale[1]
    scaleM[2,2] = scale[2]
    scaleM[3,3] = 1
    
    # multiply them according to the order
    all_mtx = [None, None, None]
    try:
        if order[2] > order[0]: # rotation first
            rotCenter1 = Shift(-int(v.sizeX()/2), -int(v.sizeY()/2), -int(v.sizeZ()/2)).toMatrix()
            rotCenter2 = Shift(int(v.sizeX()/2), int(v.sizeY()/2), int(v.sizeZ()/2)).toMatrix()
        else: # scale first, so the center is different
            rotCenter1 = Shift(-int(v.sizeX()*scale)/2, -int(v.sizeY()*scale)/2, -int(v.sizeZ()*scale)/2).toMatrix()
            rotCenter2 = Shift(int(v.sizeX()*scale)/2, int(v.sizeY()*scale)/2, int(v.sizeZ()*scale)/2).toMatrix()
        all_mtx[order[0]] = rotCenter2 * (rotM * rotCenter1) # for the rotation center!
        all_mtx[order[1]] = shiftM
        all_mtx[order[2]] = scaleM
    except:
        raise Exception("The given order is wrong! Should be a list of 0,1,2!")
    
    mtx = all_mtx[2] * (all_mtx[1] * all_mtx[0])
    
    res = vol(int(v.sizeX()*scale[0]), int(v.sizeY()*scale[1]), int(v.sizeZ()*scale[2]))
    general_transform(v, res, mtx._matrix)
    return res