The CTF Model(s) used in EMAN2

This page describes CTF correction from a programmer's perspective. There is a theory page describing the theoretical underpinnings of the CTF correction method.

---

UNDER CONSTRUCTION

Like other aspects of EMAN2, the CTF model infrastructure is extensible, though less so than the Processors, Reconstructors, etc. At present, there are 2 types of CTF instances in EMAN2: EMAN1Ctf and EMAN2Ctf. The EMAN1Ctf is provided for backwards compatibility, so if particles processed in EMAN1 are read into EMAN2, they will have a valid CTF definition in their header.

The new EMAN2 CTF model is defined as follows:

                float defocus;          // defocus in microns, positive underfocus
                float dfdiff;           // defocus difference for astigmatism, defocus is the major elliptical axis
                float dfang;            // angle of the major elliptical axis in degrees measured counterclockwise from x
                float bfactor;          // B-factor in 1/A^2 expressed using the x-ray convention (e^-B/4 s^2 in amplitude space) EMAN1 used E^-B s^2
                float ampcont;          // amplitude contrast as a percentage ie- this should be 10 for 10% amp contrast
                float voltage;          // microscope voltage in kV
                float cs;                       // Cs in mm
                float apix;                     // A/pix value used when generating 2D results
                float dsbg;                     // ds value for background and SNR
                vector<float> background;       // background intensity, 1 value per radial pixel (NX/2, corners ignored)
                vector<float> snr;                      // SNR, 1 value per radial pixel (NX/2, corners assumed 0)

Astigmatism is, at present, disabled/unused, but it is on my list of things to finalize just AFTER the workshop. You can certainly store the values for it there, but the generated curves won't contain it.

The parameters can be initialized as:

ctf=EMAN2Ctf()
ctf.from_dict("defocus":2.5,"voltage":300.0", ...)

- or -

ctf.defocus=2.5
ctf.voltage=300.0

In an EMData() object:

Make the image object:

img=EMData(256,256)

Make the ctf object:

ctf=EMAN2Ctf()

Assign parameters to the ctf object as follows:

ctf.from_dict({"defocus":2.5,"voltage":300.0", ...})

(The entire list of parameters is: defocus, bfactor,ampcont,apix,voltage,cs).

**NOTE that you have to set the ctf parameters ALL at once if you use ctf.from_dict; if you set one, by doing, for example, ctf.from_dict({'apix':4.4}), and do not specify the rest, they will be substituted with default values.

img.set_attr("ctf",ctf)

This image attribute can be archived in HDF and BDB format, but will be lost in other formats.

While these parameters can obviously be extracted from the CTF object itself, this is not the normal way of using these objects. Each Ctf object (other subclasses could be added) has two functions:

                vector < float >compute_1d(int size,float ds, CtfType type, XYData * struct_factor = 0);
                void compute_2d_complex(EMData * image, CtfType type, XYData * struct_factor = 0);

These functions return computed CTF-derived curves in 1-D or 2-D. In 1-D, specify the size of the returned array, and ds (the change in spatial frequency for each element, starting at 0 for the first). For 2-D you pass in a complex image of the desired dimensions, and its contents are replaced by the requested curve (in this case, the internal apix value is used to determine an appropriate ds). The struct_fact is not required for any current operations. CtfType is one of:

Ctf.CtfType.  -->
                        CTF_AMP,                        // ctf ampltidue only
                        CTF_SIGN,                       // ctf sign (+-1)
                        CTF_BACKGROUND,         // Background, no ctf oscillation
                        CTF_SNR,                        // Signal to noise ratio
                        CTF_WIENER_FILTER,      // Weiner Filter = 1/(1+1/snr)
                        CTF_TOTAL                       // AMP*AMP+NOISE

For example, to pad (oversample) an image, and perform phase flipping, one could:

                ctf=im1["ctf"]
                im1.clip_inplace(Region(-(ys2*(oversamp-1)/2),-(ys2*(oversamp-1)/2),ys,ys))             # pad in real-space
                fft1=im1.do_fft()
                flipim=fft1.copy()
                ctf.compute_2d_complex(flipim,Ctf.CtfType.CTF_SIGN)                                     # get a phase flipping map (this could/should be cached for multiple images)
                fft1.mult(flipim)                                                                       # flip phases
                out=fft1.do_ift()
                out["ctf"]=ctf
                out.clip_inplace(Region(int(ys2*(oversamp-1)/2.0),int(ys2*(oversamp-1)/2.0),ys2,ys2))   # unpad
                out.write_image(phaseflip,i)