Example CIAtah
pipeline via the command line.¶
Below is an example CIAtah
pipeline using the command line for those that do not want to use the class or want to create their own custom batch analyses. It assumes you have already run example_downloadTestData
to download the example test data and have MATLAB path set to the CIAtah
root directory.
Can also access the pipeline by typing edit ciapkg.demo.cmdLinePipeline
into the MATLAB command window or run by typing in ciapkg.demo.cmdLinePipeline;
.
Setup¶
% Running CIAtah from MATLAB command line/window
guiEnabled = 1;
saveAnalysis = 1;
inputDatasetName = '/1';
rawFileRegexp = 'concat';
% Setup folder paths
analysisFolderPath = [ciapkg.getDir() filesep 'data' filesep '2014_04_01_p203_m19_check01'];
[~,folderName,~] = fileparts(analysisFolderPath);
% Setup NWB folder paths
nwbFilePath = [analysisFolderPath filesep 'nwbFiles' filesep folderName];
nwbFileFolderPath = [analysisFolderPath filesep 'nwbFiles'];
% Load CIAtah functions
loadBatchFxns();
%% Download test data, only a single session
ciapkg.api.example_downloadTestData('downloadExtraFiles',0);
%% Load movie to analyze
inputMoviePath = ciapkg.api.getFileList(analysisFolderPath,rawFileRegexp,'sortMethod','natural');
% inputMoviePath = [analysisFolderPath filesep 'concat_recording_20140401_180333.h5'];
inputMovie = ciapkg.api.loadMovieList(inputMoviePath,'inputDatasetName',inputDatasetName);
Visualize movie¶
%% Visualize slice of the movie
ciapkg.api.playMovie(inputMovie(:,:,1:500),'extraTitleText','Raw movie');
% Alternatively, visualize by entering the file path
ciapkg.api.playMovie(inputMoviePath,'extraTitleText','Raw movie directly from file');
Downsample movie¶
%% Downsample input movie if need to
inputMovieD = ciapkg.api.downsampleMovie(inputMovie,'downsampleDimension','space','downsampleFactor',4);
ciapkg.api.playMovie(inputMovie,'extraMovie',inputMovieD,'extraTitleText','Raw movie vs. down-sampled movie');
% Alternatively, if you have Inscopix ISXD files, downsample by reading segments from disk using.
moviePath = 'PATH_TO_ISXD';
opts.maxChunkSize = 5000; % Max chunk size in Mb to load into RAM.
opts.downsampleFactor = 4; % How much to downsample original movie, set to 1 for no downsampling.
ciapkg.api.convertInscopixIsxdToHdf5(moviePath,'options',opts);
Remove stripe artifacts (e.g. from camera) from movie¶
%% Remove stripes from movie if needed
% Show full filter sequence for one frame
sopts.stripOrientation = 'both';
sopts.meanFilterSize = 1;
sopts.freqLowExclude = 10;
sopts.bandpassType = 'highpass';
ciapkg.api.removeStripsFromMovie(inputMovie(:,:,1),'options',sopts,'showImages',1);
% Run on the entire movie
ciapkg.api.removeStripsFromMovie(inputMovie,'options',sopts);
Detrend movie if needed (default linear trend), e.g. to compensate for bleaching over time.¶
%% Detrend movie
inputMovie = ciapkg.api.normalizeMovie(inputMovie,'normalizationType','detrend','detrendDegree',1);
Run motion correction¶
%% Get coordinates to crop from the user separately or set automatically
if guiEnabled==1
[cropCoords] = ciapkg.api.getCropCoords(squeeze(inputMovie(:,:,1)));
toptions.cropCoords = cropCoords;
% Or have turboreg function itself directly ask the user for manual area from which to obtain correction coordinates
% toptions.cropCoords = 'manual';
else
toptions.cropCoords = [26 34 212 188];
end
%% Motion correction
% Or have turboreg run manual correction
toptions.cropCoords = 'manual';
toptions.turboregRotation = 0;
toptions.removeEdges = 1;
toptions.pxToCrop = 10;
% Pre-motion correction
toptions.complementMatrix = 1;
toptions.meanSubtract = 1;
toptions.meanSubtractNormalize = 1;
toptions.normalizeType = 'matlabDisk';
% Spatial filter
toptions.normalizeBeforeRegister = 'divideByLowpass';
toptions.freqLow = 0;
toptions.freqHigh = 7;
[inputMovie2, ~] = ciapkg.api.turboregMovie(inputMovie,'options',toptions);
%% Compare raw and motion corrected movies
ciapkg.api.playMovie(inputMovie,'extraMovie',inputMovie2);
Convert movie to units of relative fluorescence¶
%% Run dF/F
inputMovie3 = ciapkg.api.dfofMovie(single(inputMovie2),'dfofType','dfof');
Downsample movie¶
%% Run temporal downsampling
inputMovie3 = ciapkg.api.downsampleMovie(inputMovie3,'downsampleDimension','time','downsampleFactor',4);
%% Final check of movie before cell extraction
ciapkg.api.playMovie(inputMovie3);
Run PCA-ICA¶
%% Run PCA-ICA cell extraction. CNMF-e, CNMF, ROI, and other cell-extraction algorithms are also available.
nPCs = 300;
nICs = 225;
pcaicaStruct = ciapkg.signal_extraction.runPcaIca(inputMovie3,nPCs,nICs,'version',2,'output_units','fl','mu',0.1,'term_tol',5e-6,'max_iter',1e3);
%% Save outputs to NWB format
if saveAnalysis==1
ciapkg.api.saveNeurodataWithoutBorders(pcaicaStruct.IcaFilters,{pcaicaStruct.IcaTraces},'pcaica',[nwbFilePath '_pcaicaAnalysis.nwb']);
end
Run CNMF or CNMF-e cell extraction.¶
%% Run CNMF or CNMF-e cell extraction
numExpectedComponents = 225;
cellWidth = 10;
cnmfOptions.otherCNMF.tau = cellWidth/2; % expected width of cells
% Run CNMF
[success] = ciapkg.api.cnmfVersionDirLoad('current');
[cnmfAnalysisOutput] = ciapkg.api.computeCnmfSignalExtractionClass(inputMovie3,numExpectedComponents,'options',cnmfOptions);
% Run CNMF-e
[success] = ciapkg.api.cnmfVersionDirLoad('cnmfe');
cnmfeOptions.gSiz = cellWidth;
cnmfeOptions.gSig = ceil(cellWidth/4);
[cnmfeAnalysisOutput] = ciapkg.api.computeCnmfeSignalExtraction_batch(outputMoviePath,'options',cnmfeOptions);
% Save outputs to NWB format
if saveAnalysis==1
% Save CNMF
ciapkg.api.saveNeurodataWithoutBorders(cnmfAnalysisOutput.extractedImages,{cnmfAnalysisOutput.extractedSignals,cnmfAnalysisOutput.extractedSignalsEst},'cnmf',[nwbFilePath '_cnmf.nwb']);
% Save CNMF-E
ciapkg.api.saveNeurodataWithoutBorders(cnmfeAnalysisOutput.extractedImages,{cnmfeAnalysisOutput.extractedSignals,cnmfeAnalysisOutput.extractedSignalsEst},'cnmfe',[nwbFilePath '_cnmfe.nwb']);
end
[success] = ciapkg.api.cnmfVersionDirLoad('none');
Run EXTRACT cell extraction.¶
%% Run EXTRACT cell extraction. Check each function with "edit" for options.
% Load default configuration
ciapkg.loadBatchFxns('loadEverything');
extractConfig = get_defaults([]);
% See https://github.com/schnitzer-lab/EXTRACT-public#configurations.
cellWidth = 10;
extractConfig.avg_cell_radius = cellWidth;
extractConfig.num_partitions_x = 2;
extractConfig.num_partitions_y = 2;
extractConfig.use_sparse_arrays = 0;
outStruct = extractor(inputMovie3,extractConfig);
% Grab outputs and put into standard format
extractAnalysisOutput.filters = outStruct.spatial_weights;
% permute so it is [nCells frames]
extractAnalysisOutput.traces = permute(outStruct.temporal_weights, [2 1]);
% Other run information if saving as a MAT-file.
extractAnalysisOutput.info = outStruct.info;
extractAnalysisOutput.config = outStruct.config;
extractAnalysisOutput.info = outStruct.info;
extractAnalysisOutput.userInputConfig = extractConfig;
extractAnalysisOutput.opts = outStruct.config;
% Save outputs to NWB format
if saveAnalysis==1
ciapkg.api.saveNeurodataWithoutBorders(extractAnalysisOutput.filters,{extractAnalysisOutput.traces},'extract',[nwbFilePath '_extract.nwb']);
end
% Remove EXTRACT from the path.
ciapkg.loadBatchFxns();
Manual sort output cells¶
%% Run signal sorting using matrix inputs
[outImages, outSignals, choices] = ciapkg.api.signalSorter(IcaFilters,IcaTraces,'inputMovie',inputMovie3);
Run signal sorting using NWB¶
%% Run signal sorting using NWB
[outImages, outSignals, choices] = ciapkg.api.signalSorter([nwbFilePath '_pcaicaAnalysis.nwb'],[],'inputMovie',inputMovie3);
%% Plot results of sorting
figure;
subplot(1,2,1);imagesc(max(IcaFilters,[],3));axis equal tight; title('Raw filters')
subplot(1,2,2);imagesc(max(outImages,[],3));axis equal tight; title('Sorted filters')
Run signal sorting using multiple NWB files from cell extraction.¶
% Run signal sorting using NWB files from cell extraction.
if saveAnalysis==1&guiEnabled==1
disp(repmat('=',1,21));disp('Running signalSorter using NWB file input.')
nwbFileList = ciapkg.api.getFileList(nwbFileFolderPath,'.nwb');
if ~isempty(nwbFileList)
nFiles = length(nwbFileList);
outImages = {};
outSignals = {};
choices = {};
for fileNo = 1:nFiles
[outImages{fileNo}, outSignals{fileNo}, choices{fileNo}] = ciapkg.api.signalSorter(nwbFileList{fileNo},[],'inputMovie',inputMovie3);
end
% Plot results of sorting
for fileNo = 1:nFiles
try
[inputImagesTmp,inputSignalsTmp,infoStructTmp,algorithmStrTmp,inputSignals2Tmp] = ciapkg.io.loadSignalExtraction(nwbFileList{fileNo});
figure;
subplot(1,2,1);
imagesc(max(inputImagesTmp,[],3));
axis equal tight;
title([algorithmStrTmp ' | Raw filters'])
subplot(1,2,2);
imagesc(max(outImages{fileNo},[],3));
axis equal tight;
title('Sorted filters')
catch err
disp(repmat('@',1,7))
disp(getReport(err,'extended','hyperlinks','on'));
disp(repmat('@',1,7))
end
end
end
end
Overlay cells on movies as sanity check¶
%% Create an overlay of extraction outputs on the movie and signal-based movie
[inputMovieO] = ciapkg.api.createImageOutlineOnMovie(inputMovie3,IcaFilters,'dilateOutlinesFactor',0);
[signalMovie] = ciapkg.api.createSignalBasedMovie(IcaTraces,IcaFilters,'signalType','peak');
%% Play all three movies
% Normalize all the movies
movieM = cellfun(@(x) ciapkg.api.normalizeVector(x,'normRange','zeroToOne'),{inputMovie3,inputMovieO,signalMovie},'UniformOutput',false);
ciapkg.api.playMovie(cat(2,movieM{:}));
Batch process example movies and perform cross-session cell alignment¶
%% Run pre-processing on 3 batch movies then do cross-session alignment
batchMovieList = {...
[ciapkg.getDir() filesep 'data' filesep 'batch' filesep '2014_08_05_p104_m19_PAV08'],...
[ciapkg.getDir() filesep 'data' filesep 'batch' filesep '2014_08_06_p104_m19_PAV09'],...
[ciapkg.getDir() filesep 'data' filesep 'batch' filesep '2014_08_07_p104_m19_PAV10']...
};
% USER INTERFACE Get the motion correction crop coordinates
cropCoordsCell = {};
nFolders = length(batchMovieList);
for folderNo = 1:nFolders
analysisFolderPath = batchMovieList{folderNo};
inputMoviePath = ciapkg.api.getFileList(analysisFolderPath,rawFileRegexp,'sortMethod','natural');
% inputMoviePath = [analysisFolderPath filesep 'concat_recording_20140401_180333.h5'];
inputMovie = ciapkg.api.loadMovieList(inputMoviePath,'inputDatasetName',inputDatasetName,'frameList',1:2);
[cropCoords] = ciapkg.api.getCropCoords(squeeze(inputMovie(:,:,1)));
% toptions.cropCoords = cropCoords;
cropCoordsCell{folderNo} = cropCoords;
end
%% Run pre-processing on each of the movies.
procMovieCell = cell([1 nFolders]);
for folderNo = 1:nFolders
inputMoviePath = ciapkg.api.getFileList(analysisFolderPath,rawFileRegexp,'sortMethod','natural');
inputMovie = ciapkg.api.loadMovieList(inputMoviePath,'inputDatasetName',inputDatasetName,'frameList',[]);
procOpts.motionCorrectionCropCoords = cropCoordsCell{folderNo};
procOpts.dfofMovie = 1;
procOpts.motionCorrectionFlag = 1;
procOpts.normalizeMovieFlag = 1;
procOpts.normalizeType = 'divideByLowpass';
procOpts.freqLow = 0;
procOpts.freqHigh = 7;
procOpts.downsampleTimeFactor = 4;
procMovieCell{folderNo} = ciapkg.demo.runPreprocessing(inputMovie,'options',procOpts);
end
disp('Done with pre-processing!')
%% Run cell-extraction on the movies
pcaicaStructCell = cell([1 nFolders]);
nPCs = 300;
nICs = 225;
for folderNo = 1:nFolders
inputMoviePath = ciapkg.api.getFileList(analysisFolderPath,rawFileRegexp,'sortMethod','natural');
pcaicaStruct{folderNo} = ciapkg.signal_extraction.runPcaIca(procMovieCell{folderNo},nPCs,nICs,'version',2,'outputUnits','fl','mu',0.1,'term_tol',5e-6,'max_iter',1e3);
end
disp('Done with PCA-ICA analysis pre-processing!')
%% Run cross-session alignment of cells
% Create input images, cell array of [x y nCells] matrices
inputImages = cellfun(@(x) x.IcaFilters,pcaicaStruct,'UniformOutput',false);
% options to change
opts.maxDistance = 5; % distance in pixels between centroids for them to be grouped
opts.trialToAlign = 1; % which session to start alignment on
opts.nCorrections = 1; %number of rounds to register session cell maps.
opts.RegisTypeFinal = 2; % 3 = rotation/translation and iso scaling; 2 = rotation/translation, no iso scaling
% Run alignment code
[alignmentStruct] = ciapkg.api.matchObjBtwnTrials(inputImages,'options',opts);
% Global IDs is a matrix of [globalID sessionID]
% Each (globalID, sessionID) pair gives the within session ID for that particular global ID
globalIDs = alignmentStruct.globalIDs;
% View the cross-session matched cells, saved to `private\_tmpFiles` sub-folder.
[success] = ciapkg.api.createMatchObjBtwnTrialsMaps(inputImages,alignmentStruct);
%% Display cross-session matching movies
disp('Playing movie frames')
crossSessionMovie1 = [ciapkg.getDir filesep 'private' filesep '_tmpFiles' filesep 'matchObjColorMap50percentMatchedSession_matchedCells.avi'];
crossSessionMovie2 = [ciapkg.getDir filesep 'private' filesep '_tmpFiles' filesep 'matchObjColorMapAllMatchedSession_matchedCells.avi'];
ciapkg.api.playMovie(crossSessionMovie1,'extraMovie',crossSessionMovie2,'rgbDisplay',1);