Plot and explore effect of the contrast transfer function

IPLT comes with a CTF object that allows you to quickly test the effect of the CTF on an image. In the same lines, the built-in plot viewer can be used to draw CTF curves at different defocus.

Setting up a CTF object

CTF objects take two principal arguments. The first is a MicroscopeData object that holds all the relevant parameters of the microscope such as accelereation voltage as well asenergy spread, spherical and chromatic abberation of the objective lense. The second is a Defocus object. We don't care about most options here, since they deal with astigmatism and tilt. Since we want to play around with these parameters we create a small wrapper function that allows us to change each of these parameters in a more pythonic way:

import ex.alg

def setup_ctf(**kwargs):
    """
    Returns a CTF object with your parameters of choice. The convention for
    defocus is such that positive values depict underfocus and negative
    values are overfocus.
    """
    options = {
        'defocus'   : 1000,
        'cs'        : 2*1e7, # defaults to 2mm
        'cc'        : 2*1e7  # defaults to 2mm
    }
    options.update(**kwargs)
    microscope_data=ex.MicroscopeData(options['cs'],options['cc'],0)
    microscope_data.SetAccelerationVoltage(100*1.0e23)
    ctf=ex.alg.CTF(ex.TCIFData(microscope_data,
        ex.Defocus(options['defocus'])))
    return ctf

Now you can change one parameter of the microscope at a time:

# smaller spherical abberation
setup_ctf(cs=1.6*1e7)
# or set defocus to Scherzer
setup_ctf(defocus=858)

Plotting CTF curves

To plot CTF curves we need to know the values of the CTF at all frequencies. To do so, we create an image in Fourier space and set all pixel values to 1. Reading out the pixel values afterwards gives the CTF values

def ctf_values(**kwargs):
    """
    Returns a one-dimensional array containing the CTF values.
    """
    options = {
        'sampling'  : 1,
    }
    options.update(kwargs)
    ctf=setup_ctf(**kwargs)
    im=CreateImage(Size(2048,1))
    im.SetPixelSampling(Vec3(options['sampling'],
        options['sampling'],options['sampling']))
    im.ApplyIP(alg.FFT())   
    im.ApplyIP(alg.Fill(1))        
    ctf_values=im.Apply(ctf)
    return [ctf_values.GetComplex(Point(x,0)).real for x in range(0,1024)]

def plot_ctf(**kwargs):
    """
    Returns plot data for CTF with the given parameters
    """
    ctf_val=ctf_values(**kwargs)
    pd=gui.PlotData()
    for x in range(0,1024):
        pd.AddXY(x,ctf_val[x])
    return pd

# Create plot viewer and add CTF curve to it.
pv=gui.CreatePlotViewer()
pv.AddData(plot_ctf()).SetMode(pv.LINES)

This is the resulting plot at Scherzer defocus (85.8nm)

CTF at Scherzer defocus

Perfect (Gaussian) defocus (0nm)

CTF at perfect (Gaussian) focus

Applying the CTF to an image

This is straight forward. The CTF is an image algorithm, so we can just apply it to our image

def image_ctf(image,**kwargs):
    ctf=setup_ctf(**kwargs)
    image=LoadImage(image)
    image.SetPixelSampling(Vec3(1,1,1))
    image.ApplyIP(alg.FFT())
    ctf_mod=image.Apply(ctf)
    return ctf_mod.Apply(alg.FFT())

The source image

After applying the CTF

and its Fourier Transform

Attachments