Beispiel #1
0
def subPixelPeak(inp, k=1, ignore_border=1):
    from pytom.voltools import transform
    is2d = len(inp.shape.squeeze()) == 2
    if is2d:
        inp2 = inp.squeeze()[ignore_border:-ignore_border,
                             ignore_border:-ignore_border]
        scale = (k, k, 1)
        out = xp.array(inp.squeeze(), dtype=xp.float32)
        x, y = xp.array(xp.unravel_index(inp2.argmax(),
                                         inp2.shape)) + ignore_border
        out = xp.expand_dims(out, 2)
        translation = [inp.shape[0] // 2 - x, inp.shape[1] // 2 - y, 0]
    else:
        inp2 = inp[ignore_border:-ignore_border, ignore_border:-ignore_border,
                   ignore_border:-ignore_border]
        scale = (k, k, k)
        out = xp.array(inp, dtype=xp.float32)
        x, y, z = xp.array(xp.unravel_index(inp2.argmax(),
                                            inp2.shape)) + ignore_border
        translation = [
            inp.shape[0] // 2 - x, inp.shape[1] // 2 - y, inp.shape[2] // 2 - z
        ]

    zoomed = xp.zeros_like(out, dtype=xp.float32)
    transform(out,
              output=zoomed,
              scale=scale,
              translation=translation,
              device='gpu:0',
              interpolation='filt_bspline')

    shifts = [x2, y2, z2] = xp.unravel_index(zoomed.argmax(), zoomed.shape)

    return [zoomed[x2, y2, z2], shifts[3 - is2d]]
def back_projection(image, angle, interpolation=None):
    '''
    back_projection: Returns 3D volume with values projected under an angle
    @param image: 2d projection image
    @type image: 2d numpy/cupy array of floats
    @param angle: Tilt angle of projection
    @type angle: float32
    @param interpolation: interpolation type using in rotation. filtered bspline is recommended.
    @return:
    @author Gijs van der Schot
    '''

    dimx, dimy = image.shape
    dims = [dimx, dimy, dimx]

    ndim = (dimx * 3) // 2

    out = xp.dstack([image] * (ndim))

    bp = xp.zeros_like(out)
    transform(out,
              output=bp,
              rotation=(0, angle, 0),
              rotation_order='sxyz',
              interpolation=interpolation,
              center=numpy.array([dims[0] // 2, dims[1] // 2, ndim // 2]),
              device=device)

    return bp[:, :, ndim // 2 - dimx // 2:ndim // 2 + dimx // 2].copy()
Beispiel #3
0
def subPixelShifts(volume, scale=[1, 1, 1], cutout=20, shifts=True):
    from pytom.voltools import transform
    import numpy as np

    volC = xp.array(
        [volume.shape[0] // 2, volume.shape[1] // 2, volume.shape[2] // 2])
    cx, cy, cz = center = find_coords_max_ccmap(volume)

    x, y, z = volume.shape
    if cx - cutout // 2 < 0 or cy - cutout // 2 < 0 or cz - cutout // 2 < 0 or cx + cutout // 2 >= x or cy + cutout // 2 >= y or cz + cutout // 2 >= z:
        return [
            volume.max(),
            xp.array([cx - x // 2, cy - y // 2, cz - z // 2])
        ]

    cutvol = volume[cx - cutout // 2:cx + cutout // 2,
                    cy - cutout // 2:cy + cutout // 2,
                    cz - cutout // 2:cz + cutout // 2]
    nx, ny, nz = [int(np.ceil(cutout / s)) for s in scale]
    nC = xp.array([nx // 2, ny // 2, nz // 2])
    centered = xp.zeros((nx, ny, nz), dtype=xp.float32)
    centered[nx // 2 - cutout // 2:nx // 2 + cutout // 2,
             ny // 2 - cutout // 2:ny // 2 + cutout // 2,
             nz // 2 - cutout // 2:nz // 2 + cutout // 2] = cutvol
    interpolated_peak = xp.zeros_like(centered)
    transform(centered,
              scale=scale,
              device=device,
              interpolation='filt_bspline',
              output=interpolated_peak)
    interpol_center = find_coords_max_ccmap(interpolated_peak)
    shifts = xp.array(center) - volC + (xp.array(interpol_center) -
                                        xp.array(nC)) * xp.array(scale)

    return [interpolated_peak.max(), shifts]
def fourierReconstructGPU(vol_img,
                          vol_bp,
                          vol_phi,
                          vol_the,
                          recPosVol=[0, 0, 0],
                          vol_offsetProjections=[0, 0, 0]):
    from pytom_numpy import vol2npy
    import cupy as cp
    from pytom.voltools import transform
    from cupy.fft import fftshift, ifftn, fftn
    import numpy
    from cupyx.scipy.ndimage import rotate
    interpolation = 'filt_bspline'
    projections = vol2npy(vol_img)
    projections = cp.array(projections)
    proj_angles = vol2npy(vol_the)[0, 0, :]
    dims = (projections.shape[0], projections.shape[0], projections.shape[0])
    tot = cp.zeros(dims, cp.complex64)

    for n in range(projections.shape[2]):
        org = cp.zeros(dims, dtype=cp.complex64)
        rot = cp.zeros(dims, dtype=cp.complex64)
        ff = fftshift(fftn(fftshift(projections[:, :, n])))

        org[:, :, dims[0] // 2] = ff
        #print(n,ff.shape, org.shape)
        if 0:
            rot.real = rotate(org.real,
                              proj_angles[n],
                              axes=(2, 0),
                              reshape=False)
            rot.imag = rotate(org.imag,
                              proj_angles[n],
                              axes=(2, 0),
                              reshape=False)
        else:
            rot.real = transform(org.real,
                                 rotation=(0, proj_angles[n], 0),
                                 rotation_order='sxyz',
                                 interpolation=interpolation)
            rot.imag = transform(org.imag,
                                 rotation=(0, proj_angles[n], 0),
                                 rotation_order='sxyz',
                                 interpolation=interpolation)
        tot += rot
        del org, rot

    if dims[0] % 2:
        t = cp.zeros_like(tot)
        t[1:, 1:, 1:] = tot[:-1, :-1, :-1]
    else:
        t = tot

    return fftshift((ifftn(fftshift(t)).real)).get()
Beispiel #5
0
def applyRotatedFilter(particle, filter, rotation, rotation_order='rzxz'):
    return applyFourierFilter(
        particle,
        transform(filter,
                  rotation=rotation,
                  rotation_order=rotation_order,
                  device=device))
Beispiel #6
0
def subPixelShiftsImage(volume, scale=[1, 1, 1], cutout=20, shifts=True):
    from pytom.voltools import transform
    import numpy as np

    if shifts:
        volC = xp.array(
            [vol.shape[0] // 2, volume.shape[1] // 2, vol.shape[2] // 2])
    else:
        volC = xp.array([0, 0, 0], dtype=xp.int32)

    cx, cy, cz = center = find_coords_max_ccmap(volume)
    cutvol = volume[cx - cutout // 2:cx + cutout // 2,
                    cy - cutout // 2:cy + cutout // 2, :]
    nx, ny, nz = [int(np.ceil(cutout / s)) for s in scale]
    nC = xp.array([nx // 2, ny // 2, 0])
    centered = xp.zeros((nx, ny, 1), dtype=xp.float32)
    centered[nx // 2 - cutout // 2:nx // 2 + cutout // 2,
             ny // 2 - cutout // 2:ny // 2 + cutout // 2, :] = cutvol

    interpolated_peak = transform(centered,
                                  scale=scale,
                                  device=device,
                                  interpolation='filt_bspline')

    interpol_center = find_coords_max_ccmap(interpolated_peak)
    shifts = xp.array(center) - volC + (xp.array(interpol_center) -
                                        xp.array(nC)) * xp.array(scale)

    return [interpolated_peak.max(), shifts]
Beispiel #7
0
def rotateWeighting(weighting, rotation, mask=None, binarize=False):
    """
    rotateWeighting: Rotates a frequency weighting volume around the center. If the volume provided is reduced complex, it will be rescaled to full size, ftshifted, rotated, iftshifted and scaled back to reduced size.
    @param weighting: A weighting volume in reduced complex convention
    @type weighting: cupy or numpy array
    @param rotation: rotation angles in zxz order
    @type rotation: list
    @param mask:=None is there a rotation mask? A mask with all = 1 will be generated otherwise. Such mask should be \
        provided anyway.
    @type mask: cupy or numpy ndarray
    @return: weight as reduced complex volume
    @rtype: L{pytom_volume.vol_comp}
    """
    from pytom_volume import vol, limit, vol_comp
    from pytom_volume import rotate
    from pytom.voltools import transform
    assert type(weighting) == vol or type(
        weighting
    ) == vol_comp, "rotateWeighting: input neither vol nor vol_comp"
    from pytom.tompy.transform import fourier_reduced2full, fourier_full2reduced

    weighting = fourier_reduced2full(weighting,
                                     isodd=weighting.shape[0] % 2 == 1)
    weighting = xp.fft.fftshift(weighting)

    weightingRotated = xp.zeros_like(weighting)

    transform(weighting,
              output=weightingRotated,
              rotation=rotation,
              rotation_order='rzxz',
              device=device,
              interpolation='filt_bspline')

    if not mask is None:
        weightingRotated *= mask

    weightingRotated = xp.fft.fftshift(weightingRotated)
    returnVolume = fourier_full2reduced(weightingRotated)

    if binarize:
        returnVolume[returnVolume < 0.5] = 0
        returnVolume[returnVolume >= 0.5] = 1

    return returnVolume
Beispiel #8
0
def cut_patch(projection,
              ang,
              pick_position,
              vol_size=200,
              binning=8,
              dimz=None,
              offset=[0, 0, 0],
              projection_name=None):
    from pytom.tompy.tools import taper_edges
    #from pytom.gpu.initialize import xp
    from pytom.voltools import transform
    from pytom.tompy.transform import rotate3d, rotate_axis
    from pytom.tompy.transform import cut_from_projection
    from pytom.tompy.io import read

    # Get the size of the original projection
    dim_x = projection.shape[0]
    dim_z = dim_x if dimz is None else dimz

    x, y, z = pick_position
    x = (x + offset[0]) * binning
    y = (y + offset[1]) * binning
    z = (z + offset[2]) * binning

    # Get coordinates of the paricle adjusted for the tilt angle
    yy = y  # assume the rotation axis is around y
    xx = (xp.cos(ang * xp.pi / 180) *
          (x - dim_x / 2) - xp.sin(ang * xp.pi / 180) *
          (z - dim_z / 2)) + dim_x / 2

    # Cut the small patch out

    patch = projection[max(0,
                           int(xp.floor(xx)) -
                           vol_size // 2):int(xp.floor(xx)) + vol_size // 2,
                       int(yy) - vol_size // 2:int(yy) + vol_size // 2, :]
    shiftedPatch = xp.zeros_like(patch)
    transform(patch,
              output=shiftedPatch,
              translation=[xx % 1, yy % 1, 0],
              device=device,
              interpolation='filt_bspline')
    return shiftedPatch.squeeze()
Beispiel #9
0
def find_sub_pixel_max_value_voltools(inp, k=.1, ignore_border=50):
    """
    To find the highest point in a 2D array, with subpixel accuracy based on 1D spline interpolation.
    The algorithm is based on a matlab script "tom_peak.m"

    @param inp: A 2D numpy array containing the data points.
    @type inp: numpy array 2D
    @param k: The smoothing factor used in the spline interpolation, must be 1 <= k <= 5.
    @type k: int
    @return: A list of all points of maximal value in the structure of tuples with the x position, the y position and
        the value.
    @returntype: list
    """
    # assert len(ixp.shape) == 2
    # assert isinstance(k, int) and 1 <= k <= 5

    import cupy
    import numpy as xp
    from scipy.interpolate import InterpolatedUnivariateSpline
    from pytom.voltools import transform

    inp2 = inp[ignore_border:-ignore_border, ignore_border:-ignore_border]

    out = cupy.array(inp, dtype=cupy.float32)
    x, y = xp.array(xp.unravel_index(inp2.argmax(),
                                     inp2.shape)) + ignore_border

    out = cupy.expand_dims(out, 2)
    zoomed = cupy.zeros_like(out, dtype=cupy.float32)
    transform(out,
              output=zoomed,
              scale=(k, k, 1),
              translation=[inp.shape[0] // 2 - x, inp.shape[1] // 2 - y, 0],
              device='gpu:0',
              interpolation='filt_bspline')

    z = zoomed.get().squeeze()

    x2, y2 = xp.unravel_index(z.argmax(), z.shape)
    return [
        x + (x2 - z.shape[0] // 2) * k - z.shape[0] // 2,
        y + (y2 - z.shape[1] // 2) * k - z.shape[0] // 2, z, x, y, x2, y2
    ]
def find_sub_pixel_voltools(inp, k=0.1, border=75, max_shift=15):
    import pytom.voltools as vt
    inp = xp.ascontiguousarray(inp)

    # find the position of the initial maximum
    dimx, dimy = inp.squeeze().shape
    initial_max = xp.unravel_index(
        inp[border:-border, border:-border].argmax(),
        (dimx - border * 2, dimy - border * 2))
    ix, iy = [v + border for v in initial_max]

    # Create an array with specific size so the zoom fits in (size = max_shift * 2 /k)
    # Center of array is initial max
    out = int(xp.around(max_shift * 2 / k))
    model = xp.zeros((out, out), dtype=xp.float32)
    model[out // 2 - max_shift:out // 2 + max_shift, out // 2 -
          max_shift:out // 2 + max_shift] = inp[ix - max_shift:ix + max_shift,
                                                iy - max_shift:iy + max_shift]
    zoomedVol = xp.expand_dims(model, 2)

    # Scale image
    vt.transform(zoomedVol,
                 scale=(k, k, 1),
                 interpolation='filt_bspline',
                 device=device,
                 output=zoomedVol)

    # fig, ax = subplots(1, 2, figsize=(10, 5))
    # ax[0].imshow(inp.get().squeeze())
    # ax[1].imshow(zoomedVol.squeeze().get())
    # show()

    # Find new max and update the initial max according to the shift
    transformed_max = xp.unravel_index(zoomedVol.argmax(), zoomedVol.shape)
    interpolX, interpolY = ix + (transformed_max[0] - out // 2) * k, iy + (
        transformed_max[1] - out // 2) * k

    return interpolX, interpolY, zoomedVol.squeeze()
Beispiel #11
0
def add_transformed_particle_to_sum(particle,
                                    sum,
                                    rotation=None,
                                    rotation_order='rzxz',
                                    translation=None,
                                    scale=None):
    from pytom.voltools import transform
    rot = transform(particle,
                    rotation=rotation,
                    translation=translation,
                    scale=scale,
                    rotation_order=rotation_order,
                    device=device,
                    interpolation='filt_bspline')
    sum += xp.array(rot)
    return sum
Beispiel #12
0
def subPixelMax3D(volume,
                  k=.01,
                  ignore_border=50,
                  interpolation='filt_bspline',
                  plan=None,
                  profile=True,
                  num_threads=1024,
                  zoomed=None,
                  fast_sum=None,
                  max_id=None):
    """
    Function to find the highest point in a 3D array, with subpixel accuracy using cubic spline interpolation.

    @param inp: A 3D numpy/cupy array containing the data points.
    @type inp: numpy/cupy array 3D
    @param k: The interpolation factor used in the spline interpolation, k < 1 is zoomed in, k>1 zoom out.
    @type k: float
    @return: A list of maximal value in the interpolated volume and a list of  x position, the y position and
        the value.
    @returntype: list
    """

    from pytom.voltools import transform
    from pytom.tompy.io import write

    ox, oy, oz = volume.shape
    ib = ignore_border
    cropped_volume = volume[ib:ox - ib, ib:oy - ib,
                            ib:oz - ib].astype(xp.float32)

    if profile:
        stream = xp.cuda.Stream.null
        t_start = stream.record()

    # x,y,z = xp.array(maxIndex(cropped_volume)) + ignore_border
    x, y, z = xp.array(
        xp.unravel_index(cropped_volume.argmax(),
                         cropped_volume.shape)) + ignore_border

    dx, dy, dz = volume.shape
    translation = [dx // 2 - x, dy // 2 - y, dz // 2 - z]

    if profile:
        t_end = stream.record()
        t_end.synchronize()

        time_took = xp.cuda.get_elapsed_time(t_start, t_end)
        print(f'initial find max time: \t{time_took:.3f}ms')
        t_start = stream.record()

    b = border = max(0, int(volume.shape[0] // 2 - 4 / k))
    zx, zy, zz = volume.shape
    out = volume[b:zx - b, b:zy - b, b:zz - b]

    transform(out,
              output=zoomed,
              scale=(k, k, k),
              device=device,
              translation=translation,
              interpolation=interpolation)

    if profile:
        t_end = stream.record()
        t_end.synchronize()

        time_took = xp.cuda.get_elapsed_time(t_start, t_end)
        print(f'transform finished in \t{time_took:.3f}ms')
        t_start = stream.record()

    nblocks = int(xp.ceil(zoomed.size / num_threads / 2))
    argmax((
        nblocks,
        1,
    ), (num_threads, 1, 1), (zoomed, fast_sum, max_id, zoomed.size),
           shared_mem=8 * num_threads)
    x2, y2, z2 = xp.unravel_index(max_id[fast_sum.argmax()], zoomed.shape)

    peakValue = zoomed[x2][y2][z2]
    peakShift = [
        x + (x2 - zoomed.shape[0] // 2) * k - volume.shape[0] // 2,
        y + (y2 - zoomed.shape[1] // 2) * k - volume.shape[1] // 2,
        z + (z2 - zoomed.shape[2] // 2) * k - volume.shape[2] // 2
    ]

    if profile:
        t_end = stream.record()
        t_end.synchronize()

        time_took = xp.cuda.get_elapsed_time(t_start, t_end)
        print(f'argmax finished in \t{time_took:.3f}ms')
        t_start = stream.record()
        print()

    return [peakValue, peakShift]
Beispiel #13
0
def alignImagesUsingAlignmentResultFile(alignmentResultsFile,
                                        weighting=None,
                                        lowpassFilter=0.9,
                                        binning=1,
                                        circleFilter=False):
    import os
    from pytom.basic.files import read as readCVol
    from pytom_numpy import vol2npy, npy2vol
    from pytom.gui.guiFunctions import fmtAR, headerAlignmentResults, datatype, datatypeAR, loadstar
    from pytom.reconstruction.reconstructionStructures import Projection, ProjectionList
    from pytom.tompy.io import read, write, read_size
    from pytom.tompy.tools import taper_edges, create_circle
    from pytom.tompy.filter import circle_filter, ramp_filter, exact_filter
    import pytom.voltools as vt
    from pytom.gpu.initialize import xp, device
    print("Create aligned images from alignResults.txt")

    alignmentResults = loadstar(alignmentResultsFile, dtype=datatypeAR)
    imageList = alignmentResults['FileName']
    tilt_angles = alignmentResults['TiltAngle']

    imdim = read_size(imageList[0], 'x')

    if binning > 1:
        imdim = int(float(imdim) / float(binning) + .5)
    else:
        imdim = imdim

    sliceWidth = imdim

    if (weighting != None) and (float(weighting) < -0.001):
        weightSlice = xp.fft.fftshift(ramp_filter(imdim, imdim))

    if circleFilter:
        circleFilterRadius = imdim // 2
        circleSlice = xp.fft.fftshift(
            circle_filter(imdim, imdim, circleFilterRadius))
    else:
        circleSlice = xp.ones((imdim, imdim))

    # design lowpass filter
    if lowpassFilter:
        if lowpassFilter > 1.:
            lowpassFilter = 1.
            print("Warning: lowpassFilter > 1 - set to 1 (=Nyquist)")

        # weighting filter: arguments: (()dimx, dimy), cutoff radius, sigma
        lpf = xp.fft.fftshift(
            create_circle((imdim, imdim),
                          lowpassFilter * (imdim // 2),
                          sigma=0.4 * lowpassFilter * (imdim // 2)))

    projectionList = ProjectionList()
    for n, image in enumerate(imageList):
        atx = alignmentResults['AlignmentTransX'][n] / binning
        aty = alignmentResults['AlignmentTransY'][n] / binning
        rot = alignmentResults['InPlaneRotation'][n]
        mag = 1 / alignmentResults['Magnification'][n]
        projection = Projection(imageList[n],
                                tiltAngle=tilt_angles[n],
                                alignmentTransX=atx,
                                alignmentTransY=aty,
                                alignmentRotation=rot,
                                alignmentMagnification=mag)
        projectionList.append(projection)

    stack = xp.zeros((imdim, imdim, len(imageList)), dtype=xp.float32)
    phiStack = xp.zeros((1, 1, len(imageList)), dtype=xp.float32)
    thetaStack = xp.zeros((1, 1, len(imageList)), dtype=xp.float32)
    offsetStack = xp.zeros((1, 2, len(imageList)), dtype=xp.float32)

    for (ii, projection) in enumerate(projectionList):
        print(f'Align {projection._filename}')
        image = read(str(projection._filename))[::binning, ::binning].squeeze()

        if lowpassFilter:
            image = xp.abs((xp.fft.ifftn(xp.fft.fftn(image) * lpf)))

        tiltAngle = projection._tiltAngle

        # normalize to contrast - subtract mean and norm to mean
        immean = image.mean()
        image = (image - immean) / immean

        # smoothen borders to prevent high contrast oscillations
        image = taper_edges(image, imdim // 30)[0]

        # transform projection according to tilt alignment
        transX = projection._alignmentTransX / binning
        transY = projection._alignmentTransY / binning
        rot = float(projection._alignmentRotation)
        mag = float(projection._alignmentMagnification)

        inputImage = xp.expand_dims(image, 2).copy()
        outputImage = xp.zeros_like(inputImage, dtype=xp.float32)

        vt.transform(inputImage.astype(xp.float32),
                     rotation=[0, 0, rot],
                     rotation_order='rxyz',
                     output=outputImage,
                     device=device,
                     translation=[transX, transY, 0],
                     scale=[mag, mag, 1],
                     interpolation='filt_bspline')

        image = outputImage.squeeze()

        # smoothen once more to avoid edges
        image = taper_edges(image, imdim // 30)[0]

        # analytical weighting
        if (weighting != None) and (weighting < 0):
            # image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ()))
            image = xp.fft.ifftn(
                xp.fft.fftn(image) * weightSlice * circleSlice)

        elif (weighting != None) and (weighting > 0):
            weightSlice = xp.fft.fftshift(
                exact_filter(tilt_angles, tiltAngle, imdim, imdim, sliceWidth))
            image = xp.fft.ifftn(
                xp.fft.fftn(image) * weightSlice * circleSlice)

        thetaStack[0, 0, ii] = int(round(projection.getTiltAngle()))
        offsetStack[0, :, ii] = xp.array([
            int(round(projection.getOffsetX())),
            int(round(projection.getOffsetY()))
        ])

        stack[:, :, ii] = image

    arrays = []

    for fname, arr in (('stack.mrc', stack), ('offsetStack.mrc', offsetStack),
                       ('thetaStack.mrc', thetaStack), ('phiStack.mrc',
                                                        phiStack)):
        if 'gpu' in device:
            arr = arr.get()
        import numpy as np
        res = npy2vol(np.array(arr, dtype='float32', order='F'), 3)
        arrays.append(res)

    #
    #     write('stack.mrc', stack)
    #     stack = readCVol('stack.mrc')
    # write('offsetstack.mrc', offsetStack)
    # offsetStack = readCVol('offsetstack.mrc')
    # write('thetastack.mrc', thetaStack)
    # thetaStack = readCVol('thetastack.mrc')
    # write('phistack.mrc', phiStack)
    # phiStack = readCVol('phistack.mrc')
    #
    # os.remove('stack.mrc')
    # os.remove('offsetstack.mrc')
    # os.remove('thetastack.mrc')
    # os.remove('psistack.mrc')

    return arrays
Beispiel #14
0
def alignImageUsingAlignmentResultFile(alignmentResultsFile,
                                       indexImage,
                                       weighting=None,
                                       lowpassFilter=0.9,
                                       binning=1,
                                       circleFilter=False):
    import pytom_freqweight
    from pytom_numpy import vol2npy
    from pytom.gui.guiFunctions import fmtAR, headerAlignmentResults, datatype, datatypeAR, loadstar
    from pytom.reconstruction.reconstructionStructures import Projection, ProjectionList
    from pytom.tompy.io import read, write, read_size
    from pytom.tompy.tools import taper_edges, create_circle
    from pytom.tompy.filter import circle_filter, ramp_filter, exact_filter, ellipse_filter
    import pytom.voltools as vt
    from pytom.gpu.initialize import xp, device

    # print("Create aligned images from alignResults.txt")

    alignmentResults = loadstar(alignmentResultsFile, dtype=datatypeAR)
    imageList = alignmentResults['FileName']
    tilt_angles = alignmentResults['TiltAngle']

    imdimX = read_size(imageList[0], 'x')
    imdimY = read_size(imageList[0], 'y')

    if binning > 1:
        imdimX = int(float(imdimX) / float(binning) + .5)
        imdimY = int(float(imdimY) / float(binning) + .5)

    sliceWidth = imdimX

    if (weighting != None) and (float(weighting) < -0.001):
        weightSlice = xp.fft.fftshift(ramp_filter(imdimY, imdimX))

    if circleFilter:
        circleFilterRadiusX = imdimX // 2
        circleFilterRadiusY = imdimY // 2

        circleSlice = xp.fft.fftshift(
            ellipse_filter(imdimX, imdimY, circleFilterRadiusX,
                           circleFilterRadiusY))
    else:
        circleSlice = xp.ones((imdimX, imdimY))

    # design lowpass filter
    if lowpassFilter:
        if lowpassFilter > 1.:
            lowpassFilter = 1.
            print("Warning: lowpassFilter > 1 - set to 1 (=Nyquist)")

        # weighting filter: arguments: (()dimx, dimy), cutoff radius, sigma
        # lpf = xp.fft.fftshift(create_circle((imdimX,imdimY),lowpassFilter*(imdim//2), sigma=0.4*lowpassFilter*(imdim//2)))

    projectionList = ProjectionList()
    for n, image in enumerate(imageList):
        atx = alignmentResults['AlignmentTransX'][n]
        aty = alignmentResults['AlignmentTransY'][n]
        rot = alignmentResults['InPlaneRotation'][n]
        mag = 1 / (alignmentResults['Magnification'][n])
        projection = Projection(imageList[n],
                                tiltAngle=tilt_angles[n],
                                alignmentTransX=atx,
                                alignmentTransY=aty,
                                alignmentRotation=rot,
                                alignmentMagnification=mag)
        projectionList.append(projection)

    imdim = min(imdimY, imdimX)

    for (ii, projection) in enumerate(projectionList):
        if not ii == indexImage:
            continue
        from pytom.tompy.transform import resize

        # print(f'read {projection._filename}')
        image = read(str(projection._filename)).squeeze()

        if binning > 1:
            image = resize(image, 1 / binning)

        #write(f'test/image_{ii}.mrc', image, tilt_angle=tilt_angles[ii])

        tiltAngle = projection._tiltAngle

        # 1 -- normalize to contrast - subtract mean and norm to mean
        immean = image.mean()
        image = (image - immean) / immean

        # 2 -- smoothen borders to prevent high contrast oscillations
        image = taper_edges(image, imdim // 30)[0]

        # 3 -- square if needed
        if 0 and imdimY != imdimX:
            newImage = xp.zeros((imdim, imdim, 1), dtype=xp.float32)
            pasteCenter(image, newImage)
            image = newImage

        # 4 -- transform projection according to tilt alignment
        transX = projection._alignmentTransX / binning
        transY = projection._alignmentTransY / binning
        rot = float(projection._alignmentRotation)
        mag = float(projection._alignmentMagnification)

        inputImage = xp.expand_dims(image, 2).copy()
        outputImage = xp.zeros_like(inputImage, dtype=xp.float32)

        vt.transform(
            inputImage.astype(xp.float32),
            rotation=[0, 0, rot],
            rotation_order='rxyz',
            output=outputImage,
            center=[inputImage.shape[0] // 2, inputImage.shape[1] // 2, 0],
            device=device,
            translation=[transX, transY, 0],
            scale=[mag, mag, 1],
            interpolation='filt_bspline')

        del image
        image = outputImage.squeeze()

        # 5 -- Optional Low Pass Filter
        if lowpassFilter:
            from pytom.tompy.filter import bandpass_circle

            image = bandpass_circle(
                image,
                high=lowpassFilter * (min(imdimX, imdimY) // 2),
                sigma=0.4 * lowpassFilter * (min(imdimX, imdimY) // 2))
            # image = xp.abs((xp.fft.ifftn(xp.fft.fftn(image) * lpf)))

        # 6 -- smoothen once more to avoid edges
        image = taper_edges(image, imdim // 30)[0]

        # 7 -- analytical weighting
        if (weighting != None) and (weighting < 0):

            # image = (ifft(complexRealMult(fft(image), w_func)) / (image.sizeX() * image.sizeY() * image.sizeZ()))
            image = xp.fft.ifftn(
                xp.fft.fftn(image) * weightSlice.T * circleSlice).real

        elif (weighting != None) and (weighting > 0):
            weightSlice = xp.fft.fftshift(
                exact_filter(tilt_angles, tiltAngle, imdim, imdim, sliceWidth))
            image = xp.fft.ifftn(
                xp.fft.fftn(image) * weightSlice * circleSlice).real

        del inputImage, outputImage, circleSlice

        write(f'inputImage_{ii}.mrc', image)

        return image.astype(xp.float32)
Beispiel #15
0
def scale(volume, factor, interpolation='Spline'):
    """
    scale: Scale a volume by a factor in REAL SPACE - see also resize function for more accurate operation in Fourier \
    space
    @param volume: input volume
    @type volume: L{pytom_volume.vol}
    @param factor: a factor > 0. Factors < 1 will de-magnify the volume, factors > 1 will magnify.
    @type factor: L{float}
    @param interpolation: Can be Spline (default), Cubic or Linear
    @type interpolation: L{str}

    @return: The scaled volume
    @author: Thomas Hrabe
    """

    from pytom.voltools import transform
    from pytom.tompy.tools import paste_in_center
    if factor <= 0:
        raise RuntimeError('Scaling factor must be > 0!')

    interpolation_dict = {
        'Spline': 'filt_bspline',
        'Linear': 'linear',
        'Cubic': 'filt_bspline',
        'filt_bspline': 'filt_bspline',
        'linear': 'linear'
    }
    interpolation = interpolation_dict[interpolation]

    volume = volume.squeeze()

    sizeX = volume.shape[0]
    sizeY = volume.shape[1]
    sizeZ = 1
    newSizeX = int(xp.floor(sizeX * float(factor) + 0.5))
    newSizeY = int(xp.floor(sizeY * float(factor) + 0.5))
    newSizeZ = 1

    if len(volume.shape) == 3:
        sizeZ = volume.shape[2]
        newSizeZ = int(xp.floor(sizeZ * factor + 0.5))
        scaleF = [1 / factor, 1 / factor, 1 / factor]
    else:
        scaleF = [1 / factor, 1 / factor, 1]
        volume = xp.expand_dims(volume, 2)

    if factor == 1:
        rescaledVolume = volume
    elif factor > 1:
        newVolume = xp.zeros((newSizeX, newSizeY, newSizeZ),
                             dtype=volume.dtype)
        newVolume = paste_in_center(volume, newVolume)
        rescaledVolume = xp.zeros_like(newVolume)
        transform(newVolume,
                  scale=scaleF,
                  output=rescaledVolume,
                  device=device,
                  interpolation=interpolation)
    else:
        rescaledVolumeFull = xp.zeros_like(volume)
        transform(volume,
                  scale=scaleF,
                  output=rescaledVolumeFull,
                  device=device,
                  interpolation=interpolation)
        rescaledVolume = xp.zeros((newSizeX, newSizeY, newSizeZ),
                                  dtype=volume.dtype)
        rescaledVolume = paste_in_center(rescaledVolumeFull, rescaledVolume)

    return rescaledVolume
Beispiel #16
0
def alignVolumesAndFilterByFSC(vol1,
                               vol2,
                               mask=None,
                               nband=None,
                               iniRot=None,
                               iniTrans=None,
                               interpolation='linear',
                               fsc_criterion=0.143,
                               verbose=0):
    """
    align two volumes, compute their FSC, and filter by FSC
    @param vol1: volume 1
    @param vol2: volume 2
    @mask: mask volume
    @type mask: L{pytom_volume.vol}
    @param nband: Number of bands
    @type nband: L{int}
    @param iniRot: initial guess for rotation
    @param iniTrans: initial guess for translation
    @param interpolation: interpolation type - 'linear' (default) or 'spline'
    @param fsc_criterion: filter -> 0 according to resolution criterion
    @type fsc_criterion: float
    @param verbose: verbose level (0=mute, 1 some output, 2=talkative)
    @type verbose: int
    @type interpolation: str
    @return: (filvol1, filvol2, fsc, fsc_fil, optiRot, optiTrans) i.e., filtered volumes, their FSC, the corresponding\
        filter that was applied to the volumes, and the optimal rotation and translation of vol2 with respect to vol1\
        note: filvol2 is NOT rotated and translated!
    @author: FF
    """
    from pytom_volume import transformSpline, vol
    from pytom.tompy.correlation import FSC
    from pytom.tompy.filter import filter_volume_by_profile
    from pytom.tompy.structures import Alignment
    from pytom.tompy.correlation import nxcc
    from pytom.voltools import transform

    assert isinstance(object=vol1, class_or_type_or_tuple=vol
                      ), "alignVolumesAndFilterByFSC: vol1 must be of type vol"
    assert isinstance(object=vol2, class_or_type_or_tuple=vol
                      ), "alignVolumesAndFilterByFSC: vol2 must be of type vol"
    # filter volumes prior to alignment according to SNR
    fsc = FSC(volume1=vol1, volume2=vol2, numberBands=nband)
    fil = design_fsc_filter(fsc=fsc, fildim=int(vol2.shape[2] // 2))
    #filter only one volume so that resulting CCC is weighted by SNR only once
    filvol2 = filter_volume_by_profile(volume=vol2, profile=fil)
    # align vol2 to vol1
    if verbose == 2:
        alignment = Alignment(vol1=vol1,
                              vol2=filvol2,
                              score=nxcc,
                              mask=mask,
                              iniRot=iniRot,
                              iniTrans=iniTrans,
                              opti='fmin_powell',
                              interpolation=interpolation,
                              verbose=verbose)
    else:
        alignment = Alignment(vol1=vol1,
                              vol2=filvol2,
                              score=nxcc,
                              mask=mask,
                              iniRot=iniRot,
                              iniTrans=iniTrans,
                              opti='fmin_powell',
                              interpolation=interpolation,
                              verbose=False)
    optiScore, optiRot, optiTrans = alignment.localOpti(iniRot=iniRot,
                                                        iniTrans=iniTrans)
    if verbose:
        from pytom.angles.angleFnc import differenceAngleOfTwoRotations
        from pytom.basic.structures import Rotation
        diffAng = differenceAngleOfTwoRotations(rotation1=Rotation(0, 0, 0),
                                                rotation2=optiRot)
        print(
            "Alignment densities: Rotations: %2.3f, %2.3f, %2.3f; Translations: %2.3f, %2.3f, %2.3f "
            % (optiRot[0], optiRot[1], optiRot[2], optiTrans[0], optiTrans[1],
               optiTrans[2]))
        print("Orientation difference: %2.3f deg" % diffAng)
    vol2_alig = xp.zeros(vol2.shape, dtype=xp.float32)
    transform(vol2,
              output=vol2_alig,
              rotation=[optiRot[0], optiRot[2], optiRot[1]],
              rotation_order='rzxz',
              center=[
                  int(vol2.shape[0] // 2),
                  int(vol2.shape[1] // 2),
                  int(vol2.shape[2] // 2)
              ],
              interpolation='filt_bspline',
              translation=[optiTrans[0], optiTrans[1], optiTrans[2]],
              device=device)
    # finally compute FSC and filter of both volumes
    if not nband:
        nband = int(vol2.sizeX() / 2)
    fsc = FSC(volume1=vol1, volume2=vol2_alig, numberBands=nband)
    fil = design_fsc_filter(fsc=fsc,
                            fildim=int(vol2.shape[0] // 2),
                            fsc_criterion=fsc_criterion)
    filvol1 = filter_volume_by_profile(volume=vol1, profile=fil)
    #filvol2 = filter_volume_by_profile( volume=vol2_alig, profile=fil)
    filvol2 = filter_volume_by_profile(volume=vol2, profile=fil)

    return (filvol1, filvol2, fsc, fil, optiRot, optiTrans)