You can register your frames using the first channel of the recording,
or using the second channel. Say your first channel shows GCaMP and your
second channel shows td-Tomato, you might want to use the second channel
for registration if it has higher SNR. If so, set
ops['align_by_chan']=2. Otherwise, leave
Finding a target reference image¶
To perform registration, we need a reference image to align all the
frames to. This requires an initial alignment step. Consider we just
took the average of a subset of frames. Because these frames are not
motion-corrected, the average will not be crisp - there will be fuzzy
edges because objects in the image have been moving around across the
frames. Therefore, we do an initial iterative alignment procedure on a
random subset of frames in order to get a crisp reference image for
registration. We first take
ops['nimg_init'] random frames of the
movie. Then from those frames, we take the top 20 frames that are most
correlated to each other and take the mean of those frames as our
initial reference image. Then we refine this reference image iteratively
by aligning all the random frames to the reference image, and then
recomputing the reference image as the mean of the best aligned frames.
The function that performs these steps can be run as follows (where ops needs the reg_file, Ly, Lx, and nimg_init parameters):
from suite2p.registration import register refImg = register.pick_initial_reference(ops)
Here is an example reference image on the right, compared to just taking the average of a random subset of frames (on the left):
If the reference image doesn’t look good, try increasing
Registering the frames to the reference image¶
Once the reference image is obtained, we align each frame to the
reference image. The frames are registered in batches of size
ops['batch_size'] (default is 200 frames per batch).
We first perform rigid registration (assuming that the whole image
shifts by some (dy,dx)), and then optionally after that we perform
non-rigid registration (assuming that subsegments of the image shift by
separate amounts). To turn on non-rigid registration, set
ops['nonrigid']=True. We will outline the parameters of each
registration step below.
1. Rigid registration¶
Rigid registration computes the shifts between the frame and the reference image using phase-correlation. We have found on simulated data that phase-correlation is more accurate than cross-correlation. Phase-correlation is a well-established method to compute the relative movement between two images. Phase-correlation normalizes the Fourier spectra of the images before multiplying them (whereas cross-correlation would just multiply them). This normalization emphasizes the correlation between the higher frequency components of the images, which in most cases makes it more robust to noise.
You can set a maximum shift size using the option
ops['maxregshift']. By default, it is 0.1, which means that the
maximum shift of the frame from the reference in the Y direction is
0.1 * ops['Ly'] and in X is
0.1 * ops['Lx'] where Ly and Lx are
the Y and X sizes of the frame.
After computing the shifts, the frames are shifted in the Fourier domain
(allowing subpixel shifts of the images). The shifts are saved in
ops['xoff'] for y and x shifts respectively. The
peak of the phase-correlation of each frame with the reference image is
You can run this independently from the pipeline, if you have a reference image (ops requires the parameters nonrigid=False, num_workers, and maxregshift):
maskMul,maskOffset,cfRefImg = register.prepare_masks(refImg) refAndMasks = [maskMul,maskOffset,cfRefImg] aligned_data, yshift, xshift, corrXY, yxnr = register.phasecorr(data, refAndMasks, ops)
(see bioRxiv preprint comparing cross/phase here)
2. Non-rigid registration (optional)¶
If you run rigid registration and find that there is still motion in your frames, then you should run non-rigid registration. Non-rigid registration divides the image into subsections and computes the shift of each subsection (called a block) separately. Non-rigid registration will approximately double the registration time.
The size of the blocks to divide the image into is defined by
ops['block_size'] = [128,128] which is the size in Y and X in
pixels. If Y is the direction of line-scanning for 2p imaging, you may
want to divide it into smaller blocks in that direction.
Each block is able to shift up to
ops['maxregshiftNR'] pixels in Y
and X. We recommend to keep this small unless you’re in a very high
signal-to-noise ratio regime and your motion is very large. For subpixel shifts,
we use Kriging interpolation and run it on each block.
Phase correlation of each block:
Shift of each block from phase corr:
In a low signal-to-noise ratio regime, there may be blocks which on a
given frame do not have sufficient information from which to align with
the reference image. We compute a given block’s maximum phase
correlation with the reference block, and determine how much greater this max is than
the surrounding phase correlations. The ratio
between these two is defined as the
snr of that block at that given
time point. We smooth over high snr blocks and use bilinear interpolation
to upsample create the final shifts:
We then use bilinear interpolation to warp the frame using these shifts.
Metrics for registration quality¶
The inputs required for PC metrics are the following fields in ops:
reg_file. Your movie must have at least 1500 frames in each plane
for the metrics to be calculated. You can run on the red channel (ops[‘reg_file_chan2’]) if use_red=True.
The outputs saved from the PC metrics are
from suite2p.registration import metrics ops = metrics.get_pc_metrics(ops, use_red=False)
ops['tPC'] are the time courses of each of the principal
components of the registered movie. Note
the time-course is not the entire movie, it’s only the subset of frames used to
compute the PCs (2000-5000 frames equally sampled throughout the movie).
ops['regPC'] are computed from the spatial principal components of the
ops['regPC'][0,0,:,:] is the average of the top
500 frames of the 1st PC,
ops['regPC'][1,0,:,:] is the average of
the bottom 500 frames of the 1st PC.
ops['regDX'] quantifies the
movement in each PC (
iPC) by registering
ops['regPC'][1,iPC,:,:] to the reference image
ops['refImg'] (if available,
if not the mean of all the frames is used as the reference image)
and computing the registration shifts.
Here’s a twitter thread with multiple examples.
Suite2p provides a CLI (Command-Line Interface) script that calculates the registration metrics for a given input tif and outputs some statistics on those metrics. You can use this script to determine the quality of registration and tune your registration parameters (e.g: determine if non-rigid registration is necessary).
To run the script, use the following command:
reg_metrics <INSERT_OPS_DATA_PATH> # Add --tiff_list <INSERT_INPUT_TIF_FILENAME_HERE>.tif to select a subset of tifs
Once you run the
reg_metrics command, registration will be performed for the input file with default
ops parameters and an output similar to the following will be shown:
# Average NR refers to the average nonrigid offsets of the blocks for a PC # Max NR refers to the max nonrigid offsets of the blocks for a PC Plane 0: Avg_Rigid: 0.000000 Avg_Average NR: 0.028889 Avg_Max NR: 0.120000 Max_Rigid: 0.000000 Max_Average NR: 0.044444 Max_Max NR: 0.200000
nplane, these statistics (Average and Max) are calculated across PCs on the offsets found in
If the registration works perfectly and most of the motion is removed from the registered dataset, these scores
should all be very close to zero.
Make sure to also inspect the registered video to check the quality of registration. You can see an example of how this is done in the GUI here.
You may notice that upon visual inspection, the registered video may look fine/contain little motion even if the statistics are not close to zero. You should always visually check the registration output and prioritize what your eyes say over what the CLI script reports.
All suite2p registration settings can be modified in this CLI script. Just pass the setting with its value as an optional argument. For instance,
reg_metrics path_to_data_tif --nplanes 2 --smooth_sigma 1.2
runs the script with
ops['nplanes'] = 2 and
ops['smooth_sigma'] = 1.2.
You can see all the arguments
reg_metrics takes with the following command: