Scanbox Searches for a Population

In some instances, people need to image the same population of neurons across days.   It can be easy to go back to approximately the same position, but finding the best alignment can be time consuming.

Now Scanbox provides a plugin that searches for the optimal location and automatically moves the microscope to the estimated position, and the entire process takes ~2 min.

Here is an example of how to do this:

In this demo, I first accumulate a few frames and take a snapshot that is stored as a reference image.  This is the population we will want to return to.

Then, I image the same area again but move the microsocope in (x,y) and also depth. This simulates returning to roughly the same location in a subsequent day.

Once we are in roughly the same location, we can enable the “searchref” plug-in and allow it to run while focusing.

As we start imaging again, the plugin will request the name of the file with the reference image we want to align.  I selected the one I had created earlier.

A z-stack starts automatically and the plugin displays in real-time a fused image with the reference image in red and the incoming images from the z-stack in green.

Once the z-stack is complete, the plugin computes the optimal (x,y,z) translation and moves the scope to best align the images.

Here is the searchref.m plug-in code:

% Searches for a reference image

global refimg fnum

if(flag) % first call? Format chA/chB according to lines/columns in data
    sb = udp('localhost','RemotePort',7000);  % local connection to Scanbox
    mmfile.Format = {'int16' [1 16] 'header' ; ...
        'uint16' double([mmfile.Data.header(2) mmfile.Data.header(3)]) 'chA' ; ...
        'uint16' double([mmfile.Data.header(2) mmfile.Data.header(3)]) 'chB'};
    mchA = double(intmax('uint16')-mmfile.Data.chA);
    % setup fig
    pickref([],[]); % select reference image
    close all
    f = figure(1);
    f.MenuBar = 'none';
    f.NumberTitle = 'off';
    f.Name = 'Search Display';
    C = imfuse(refimg,mchA,'falsecolor','ColorChannels',[1 2 0]);
    h = imshow(C);
    ttl = title('');
    zrange  = sbconfig.plugin_param.searchref.zrange;
    zdelta  = sbconfig.plugin_param.searchref.zdelta;
    nframes = sbconfig.plugin_param.searchref.nframes;
    zpos = round(zrange:-zdelta:-zrange);
    idx = 0;
    midx = length(zpos);
    acc = zeros([size(mchA) midx]);
    fprintf(sb,'Ks'); % set knobby in superfine mode
    fprintf(sb,sprintf('PZ%d',zrange)); % move to start zstack
    flag = 0;
    newblock = true;
    done = false;
    k = 1;
    if ~done
        %%[idx k newblock fnum]
        mchA = double(intmax('uint16')-mmfile.Data.chA);
        if idx<=midx
            if newblock
                idx = idx + 1;
                k = 1;
                acc(:,:,idx) = mchA;
                newblock = false;
                ttl.String = sprintf('z-stack: slice %d of %d (red = reference image)',idx,midx);
                acc(:,:,idx) = acc(:,:,idx) + mchA;    % accumulate
                k = k + 1;
                newblock = (k>=nframes);
                if newblock
                    C = imfuse(refimg,squeeze(acc(:,:,idx)),'falsecolor','ColorChannels',[1 2 0]);
                    h.CData = C;
                    fprintf(sb,sprintf('PZ-%d',zdelta)); % move down by delta
            fprintf(sb,sprintf('PZ%d',zrange+zdelta)); % move back to center
            % compute optimal translation
            cc = zeros(1,midx);
            u = zeros(1,midx);
            v = zeros(1,midx);
            for i = 1:midx
                [u(i),v(i),cc(i)] = search_fftalign(refimg,squeeze(acc(:,:,i)));
            [mcc,q] = max(cc);
            fprintf(sb,sprintf('PZ%d',zpos(q))); % move to optimal location
            done = true;
            %         fprintf(sb,'S');      % stop sampling...
            %         fprintf(sb,'I0');     % disable plugins
        % just display result...
        ttl.String = 'Optimal alignment';
        mchA = double(intmax('uint16')-mmfile.Data.chA);
        C = imfuse(refimg,mchA,'falsecolor','ColorChannels',[1 2 0]);
        h.CData = C;        


You will also need this search_fftalign.m file:

function [u,v,mc] = search_fftalign(A,B)

N = min(size(A))-80;    % leave out margin

yidx = round(size(A,1)/2)-N/2 + 1 : round(size(A,1)/2)+ N/2;
xidx = round(size(A,2)/2)-N/2 + 1 : round(size(A,2)/2)+ N/2;

A = A(yidx,xidx);
B = B(yidx,xidx);

C = fftshift(real(ifft2(fft2(A).*fft2(rot90(B,2)))));
[mc,i] = max(C(:));
[ii jj] = ind2sub(size(C),i);

u = N/2-ii;
v = N/2-jj;

Ba = circshift(B,-[u,v]);
mc = corrcoef(A(:),Ba(:));
mc = mc(1,2);

Place them both in the scanbox/mmap folder and define the ‘searchref’ plugin option in the sbconfig.plugin configuration variable.