HIPPOCAMPAL PLACE CELL - RECEPTIVE FIELD ESTIMATION

Estimation of receptive fields of neurons is a very common data analysis problem in neuroscience. Here we use the nSTAT software to perform an estimation of the receptive fields of hippocampal place cells using a bivariate Gaussian model and Zernike polynomials. The number of zernike polynomials is based on "An Analysis of Hippocampal Spatio-Temporal Representations Using a Bayesian Algorithm for Neural Spike Train Decoding" Barbieri et. al 2005. The data used herein in was provided by Dr. Ricardo Barbieri on 2/28/2011.

Author: Iahn Cajigas

Date: 3/1/2011

Contents

close all
[~,~,~,~,placeCellDataDir] = getPaperDataDirs();

Example Data

The x and y coordinates of a freely foraging rat in a circular environment (70cm in diameter and 30cm high walls) and a fixed visual cue. The x and y coordinates at the time when a spike was observed are marked in red. The position coordinates have been normalized to be between -1 and 1 to allow to simplify the analysis.

    load(fullfile(placeCellDataDir,'PlaceCellDataAnimal1.mat'));
    exampleCell = 25;
    figure(1);
    plot(x,y,'b',neuron{exampleCell}.xN,neuron{exampleCell}.yN,'r.');
    xlabel('x'); ylabel('y');
    title(['Animal#1, Cell#' num2str(exampleCell)]);

Analyze All Cells

 numAnimals =2;
for n=1:numAnimals
    % load the data
    clear x y neuron time nst tc tcc z;
    load(fullfile(placeCellDataDir,['PlaceCellDataAnimal' num2str(n) '.mat']));

    % Create the spikeTrains for each cell
    for i=1:length(neuron)
        nst{i} = nspikeTrain(neuron{i}.spikeTimes);
    end


    % Convert to polar coordinates
    [theta,r] = cart2pol(x,y);


    % Evaluate the Zernike Polynomials
    % Number of polynomials from "An Analysis of Hippocampal
    % Spatio-Temporal Representations Using a Bayesian Algorithm for Neural
    % Spike Train Decoding" Barbieri et. al 2005
    cnt=0;
    for l=0:3
       for m=-l:l
           if(~any(mod(l-m,2))) % otherwise the polynomial = 0
            cnt = cnt+1;
            z(:,cnt) = zernfun(l,m,r,theta,'norm');
            % zernfun by Paul Fricker
            % http://www.mathworks.com/matlabcentral/fileexchange/7687
           end
       end
    end

    % Data sampled at 30 Hz but just to be sure
    delta=min(diff(time));
    sampleRate = round(1/delta);

    % Define Covariates for the analysis
    baseline = Covariate(time,ones(length(x),1),'Baseline','time','s','',...
                        {'mu'});
    zernike  = Covariate(time,z,'Zernike','time','s','m',{'z1','z2','z3',...
                        'z4','z5','z6','z7','z8','z9','z10'});
    gaussian = Covariate(time,[x y x.^2 y.^2 x.*y],'Gaussian','time',...
                        's','m',{'x','y','x^2','y^2','x*y'});
    covarColl = CovColl({baseline,gaussian,zernike});

    % Create the trial structure
    spikeColl = nstColl(nst);
    trial     = Trial(spikeColl,covarColl);


    % Define how we want to analyze the data
    tc{1} = TrialConfig({{'Baseline','mu'},{'Gaussian',...
                        'x','y','x^2','y^2','x*y'}},sampleRate,[]);
    tc{1}.setName('Gaussian');
    tc{2} = TrialConfig({{'Zernike' 'z1','z2','z3','z4','z5','z6',...
                        'z7','z8','z9','z10'}},sampleRate,[]);
    tc{2}.setName('Zernike');
    tcc = ConfigColl(tc);

    % Perform Analysis (Commented to since data already saved)
%     results =Analysis.RunAnalysisForAllNeurons(trial,tcc,0);

    % Save results
%     resStruct =FitResult.CellArrayToStructure(results);
%     filename = ['PlaceCellAnimal' num2str(n) 'Results'];
%     save(filename,'resStruct');
end

View Summary Statistics

Note the Zernike Polynomials yield better fits in terms of decreased KS Statistics (less deviation from the 45 degree line), reduced AIC and reduced BIC across the majority of cells and for both animals

for n=1:numAnimals
    resData=load(fullfile(fileparts(placeCellDataDir),['PlaceCellAnimal' num2str(n) 'Results.mat']));
    results = FitResult.fromStructure(resData.resStruct);
    Summary = FitResSummary(results);
    Summary.plotSummary;
end

Visualize the results

% Define a grid
[x_new,y_new]=meshgrid(-1:.01:1); %define new x and y
y_new = flipud(y_new); x_new = fliplr(x_new);
[theta_new,r_new] = cart2pol(x_new,y_new);

%Data for the gaussian fit
newData{1} =ones(size(x_new));
newData{2} =x_new; newData{3} =y_new;
newData{4} =x_new.^2; newData{5} =y_new.^2;
newData{6} =x_new.*y_new;


% Zernike polynomials only defined on the unit disk
idx = r_new<=1;
zpoly = cell(1,10);
cnt=0;
for l=0:3
   for m=-l:l
       if(~any(mod(l-m,2)))
        cnt = cnt+1;
        temp = nan(size(x_new));
        temp(idx) = zernfun(l,m,r_new(idx),theta_new(idx),'norm');
        zpoly{cnt} = temp;
       end
   end
end



for n=1:numAnimals

    clear lambdaGaussian lambdaZernike;
    load(fullfile(placeCellDataDir,['PlaceCellDataAnimal' num2str(n) '.mat']));
    resData=load(fullfile(fileparts(placeCellDataDir),['PlaceCellAnimal' num2str(n) 'Results.mat']));
    results = FitResult.fromStructure(resData.resStruct);

    for i=1:length(neuron)
        % Evaluate our fits using the new data and the estimated parameters
        lambdaGaussian{i} = results{i}.evalLambda(1,newData);
        lambdaZernike{i} =  results{i}.evalLambda(2,zpoly);
    end




    % Plot the receptive fields
    for i=1:length(neuron)
        % 3d plot of an example place field


        % 2d plot of all the cell's fields
        if(n==1)
            h4=figure(4);
            if(i==1)
                annotation(h4,'textbox',...
                    [0.343261904761904 0.928571428571418 ...
                    0.392857142857143 0.0595238095238095],...
                    'String',{['Gaussian Place Fields - Animal#' ...
                    num2str(n)]},'FitBoxToText','on'); hold on;
            end
            subplot(7,7,i);
        elseif(n==2)
            h6=figure(6);
            if(i==1)
                annotation(h6,'textbox',...
                    [0.343261904761904 0.928571428571418 ...
                    0.392857142857143 0.0595238095238095],...
                    'String',{['Gaussian Place Fields - Animal#' ...
                    num2str(n)]},'FitBoxToText','on'); hold on;
            end
            subplot(6,7,i);
        end
        pcolor(x_new,y_new,lambdaGaussian{i}), shading interp
        axis square; set(gca,'xtick',[],'ytick',[]);


        if(n==1)
            h5=figure(5);
            if(i==1)
                annotation(h5,'textbox',...
                    [0.343261904761904 0.928571428571418 ...
                    0.392857142857143 0.0595238095238095],...
                    'String',{['Zernike Place Fields - Animal#' ...
                    num2str(n)]},'FitBoxToText','on'); hold on;

            end
            subplot(7,7,i);
        elseif(n==2)
            h7=figure(7);
            if(i==1)
               annotation(h7,'textbox',...
                    [0.343261904761904 0.928571428571418 ...
                    0.392857142857143 0.0595238095238095],...
                    'String',{['Zernike Place Fields - Animal#' ...
                    num2str(n)]},'FitBoxToText','on'); hold on;
            end
            subplot(6,7,i);
        end
        pcolor(x_new,y_new,lambdaZernike{i}), shading interp
        axis square;
        set(gca,'xtick',[],'ytick',[]);
    end




end



    clear lambdaGaussian lambdaZernike;
    load(fullfile(placeCellDataDir,'PlaceCellDataAnimal1.mat'));
    resData=load(fullfile(fileparts(placeCellDataDir),'PlaceCellAnimal1Results.mat'));
    results = FitResult.fromStructure(resData.resStruct);

    for i=1:length(neuron)
        % Evaluate our fits using the new data and the estimated parameters
        lambdaGaussian{i} = results{i}.evalLambda(1,newData);
        lambdaZernike{i} =  results{i}.evalLambda(2,zpoly);
    end



    exampleCell = 25;
    figure(8);
    plot(x,y,'b',neuron{exampleCell}.xN,neuron{exampleCell}.yN,'r.');
    xlabel('x'); ylabel('y');
    title(['Animal#1, Cell#' num2str(exampleCell)]);

    figure(9);
    h_mesh = mesh(x_new,y_new,lambdaGaussian{exampleCell},'AlphaData',0);
    get(h_mesh,'AlphaData');
    set(h_mesh,'FaceAlpha',0.2,'EdgeAlpha',0.2,'EdgeColor','b');
    hold on;
    h_mesh = mesh(x_new,y_new,lambdaZernike{exampleCell},'AlphaData',0);
    get(h_mesh,'AlphaData');
    set(h_mesh,'FaceAlpha',0.2,'EdgeAlpha',0.2,'EdgeColor','g');

    legend(results{exampleCell}.lambda.dataLabels);
    plot(x,y,neuron{exampleCell}.xN,neuron{exampleCell}.yN,'r.');
    axis tight square;
    xlabel('x position'); ylabel('y position');
    title(['Animal#1, Cell#' num2str(exampleCell)]);