From 3833ffd4d595bc34933706917f4b95da066b9e3f Mon Sep 17 00:00:00 2001 From: Biafra Ahanonu Date: Mon, 21 Jun 2021 16:36:32 -0700 Subject: [PATCH 1/4] Improved pre-processing UI, Bio-Formats support, easier ImageJ/Miji loading, and more. Main features and changes: - modelPreprocessMovieFunction - CIAtah now remembers the user's analysis order and there are options to reset it. Further, the pre-processing settings are now all displayed on a single page. - Bio-Formats (https://www.openmicroscopy.org/bio-formats/) support added. Currently added support for Zeiss (CZI, LSM) and Olympus (OIR) formats with more to follow. - Switch support from Miji/Fiji combination to ImageJ/Miji combination using .jar files that is easier to install and should have easier support across Windows/Linux/OSX. - Update README to include webinars and workshop recordings on calcium imaging analysis and CIAtah. ## New functions - `ciapkg.io.getOptions` - clone of `getOptions` in anticipation of moving all functions to `ciapkg` sub-package. - `@ciatah\modelVarsFromFilesCheck` - Checks whether a specific folder has cell extraction variables loaded, if not loads them. ## Updated `@ciatah` - `computeManualSortSignals` - Added modelVarsFromFilesCheck() to check and load signals if user hasn't already. - `computeMatchObjBtwnTrials` - Added modelVarsFromFilesCheck() to check and load signals if user hasn't already. - `getRegistrationSettings` - Switch to single page support. - `modelExtractSignalsFromMovie` - Use filesep in getAlgorithmRootPath to avoid issues in Unix-based systems. Fix issue of passing multiple movies to PCA-ICA. - `modelModifyMovies` - manageMiji('startStop','closeAllWindows'); added to improve support for ImageJ over Fiji implementation of Miji. - `modelModifyRegionAnalysis` - Added modelVarsFromFilesCheck() to check and load signals if user hasn't already. - `modelPreprocessMovieFunction` - Fixed thisFrame issue when displaying area to use for motion correction if treatMoviesAsContinuous=0 and processMoviesSeparately=0, e.g. would load reference frame from each and if there were 3 movies, would assume RGB, causing display to be white. - Also update so the display frame takes into account custom frame list range. Updated checking of options. Also save ordering of options selected. - Added manageMiji('startStop','closeAllWindows'); support. - `viewCellExtractionOnMovie` - Added modelVarsFromFilesCheck() to check and load signals if user hasn't already. - `viewCreateObjmaps` - Added modelVarsFromFilesCheck() to check and load signals if user hasn't already. - `viewMovie` - Added support for simple and advanced settings. Added modelVarsFromFilesCheck() to check and load signals if user hasn't already. - `viewMovieRegistrationTest` - Added modelVarsFromFilesCheck() to check and load signals if user hasn't already. - `viewObjmaps` - Added modelVarsFromFilesCheck() to check and load signals if user hasn't already. - `viewSubjectMovieFrames` - Added modelVarsFromFilesCheck() to check and load signals if user hasn't already. - ## Updated `ciapkg` - `signalSorter` - Since ciapkg.io.loadSignalExtraction already supports loading NWB or CIAtah MAT-file cell extraction files, remove remove redundancy and only call ciapkg.io.loadSignalExtraction rather than loadNeurodataWithoutBorders. Added support for progress bar when movie not input. - `cropMatrix` - Support switched from [nSignals x y] to [x y nSignals]. Updated to make imrect the default method of selecting the coordinates. - `loadMovieList` - Added support for Bio-Formats compatible files, specifically Olympus (OIR) and Zeiss (CZI, LSM). - `manageMiji` - Add support for setting up ImageJ along with closing all windows to future proof any changes to those calls. - `modelAddOutsideDependencies` - Updated to add support for ImageJ call instead of Fiji. - `saveMatrixToFile` - updated TIFF saving to add support for export of multi-channel color timeseries TIFF stack if in format [x y C t] where x,y = width/height, C = RGB channels, t = frames. - `computeManualMotionCorrection` - Add default gamma option. Update to fix issue of prior figure (even after clf) maintaining previous key press and exiting, causing uiwait to fail. - `normalizeMovie` - Detrend movie now uses nanmean to get around issues in motion corrected videos. - `createMovieFromVector` - Users can now manually change value assigned to center line or signal. - `playMovie` - Add support for playing RGB movie of dimension [x y C t] if input directly as matrix. - `loadBatchFxns` - Added manageMiji('startStop','closeAllWindows'); support. ## Updated `+ciapkg` - `cmdLinePipeline` - Added CNMF/CNMF-e and EXTRACT to cell extraction examples. - `loadDependencies` - Switched to support for original MIJ calling of ImageJ using just jar files, easier compatibility across MATLAB versions and OSes. - `updatePkg` - Added additional URLs for compatibility. Updated to ciatah from calciumImagingAnalysis URLs. --- +ciapkg/+demo/cmdLinePipeline.m | 60 ++++- +ciapkg/+io/getOptions.m | 248 +++++++++++++++++ +ciapkg/+io/loadDependencies.m | 34 ++- +ciapkg/+io/loadSignalExtraction.m | 2 + +ciapkg/+io/updatePkg.m | 5 +- +ciapkg/VERSION | 4 +- +ciapkg/exampleFxn.m | 2 +- @ciatah/ciatah.m | 12 +- @ciatah/ciatahMainGui.m | 11 +- @ciatah/computeManualSortSignals.m | 19 +- @ciatah/computeMatchObjBtwnTrials.m | 5 + @ciatah/getRegistrationSettings.m | 26 +- @ciatah/loadDependencies.m | 6 +- @ciatah/modelExtractSignalsFromMovie.m | 25 +- @ciatah/modelModifyMovies.m | 10 +- @ciatah/modelModifyRegionAnalysis.m | 3 + @ciatah/modelPreprocessMovieFunction.m | 253 +++++++++++++++--- @ciatah/modelVarsFromFilesCheck.m | 48 ++++ @ciatah/viewCellExtractionOnMovie.m | 7 +- @ciatah/viewCreateObjmaps.m | 4 + @ciatah/viewMovie.m | 62 ++++- @ciatah/viewMovieRegistrationTest.m | 3 +- @ciatah/viewObjmaps.m | 5 + @ciatah/viewSubjectMovieFrames.m | 19 +- README.md | 24 +- ciapkg/classification/signalSorter.m | 80 ++++-- ciapkg/download/downloadGithubRepositories.m | 8 +- ciapkg/image/cropMatrix.m | 36 ++- ciapkg/image/filterImages.m | 36 +-- ciapkg/io/loadMovieList.m | 103 ++++++- ciapkg/io/manageMiji.m | 42 ++- ciapkg/io/modelAddOutsideDependencies.m | 16 +- ciapkg/io/saveMatrixToFile.m | 6 +- .../computeManualMotionCorrection.m | 30 ++- ciapkg/movie_processing/normalizeMovie.m | 5 +- ciapkg/video/createMovieFromVector.m | 12 +- ciapkg/view/playMovie.m | 35 ++- ciapkg/view/viewVennDiagram.m | 1 + loadBatchFxns.m | 10 + 39 files changed, 1136 insertions(+), 181 deletions(-) create mode 100644 +ciapkg/+io/getOptions.m create mode 100644 @ciatah/modelVarsFromFilesCheck.m diff --git a/+ciapkg/+demo/cmdLinePipeline.m b/+ciapkg/+demo/cmdLinePipeline.m index 5adb32e..17c054c 100644 --- a/+ciapkg/+demo/cmdLinePipeline.m +++ b/+ciapkg/+demo/cmdLinePipeline.m @@ -9,22 +9,27 @@ % 2020.09.23 [08:35:58] - Updated to add support for cross-session analysis and use ciapkg.demo.runPreprocessing() to process the other imaging sessions. % 2020.10.17 [19:30:01] - Update to use ciapkg.signal_extraction.runPcaIca for PCA-ICA to make easier for users to run in the future. % 2021.01.17 [21:38:55] - Updated to show detrend example + % 2021.06.20 [16:04:42] - Added CNMF/CNMF-e and EXTRACT to cell extraction examples. +% ================================================= %% Initialize guiEnabled = 1; saveAnalysis = 1; inputDatasetName = '/1'; rawFileRegexp = 'concat'; +% ================================================= %% Download test data, only a single session example_downloadTestData('downloadExtraFiles',0); +% ================================================= %% Load movie to analyze analysisFolderPath = [ciapkg.getDir() filesep 'data' filesep '2014_04_01_p203_m19_check01']; inputMoviePath = getFileList(analysisFolderPath,rawFileRegexp,'sortMethod','natural'); % inputMoviePath = [analysisFolderPath filesep 'concat_recording_20140401_180333.h5']; inputMovie = loadMovieList(inputMoviePath,'inputDatasetName',inputDatasetName); +% ================================================= %% USER INTERFACE Visualize slice of the movie if guiEnabled==1 playMovie(inputMovie(:,:,1:500),'extraTitleText','Raw movie'); @@ -32,12 +37,14 @@ playMovie(inputMoviePath,'extraTitleText','Raw movie directly from file'); end +% ================================================= %% USER INTERFACE Downsample input movie if need to if guiEnabled==1 inputMovieD = downsampleMovie(inputMovie,'downsampleDimension','space','downsampleFactor',4); playMovie(inputMovie,'extraMovie',inputMovieD,'extraTitleText','Raw movie vs. down-sampled movie'); end +% ================================================= %% Remove stripes from movie if needed if guiEnabled==1 % Show full filter sequence for one frame @@ -51,9 +58,11 @@ inputMovie = removeStripsFromMovie(inputMovie,'options',sopts); end +% ================================================= %% Detrend movie if needed (default linear trend), e.g. to compensate for bleaching inputMovie = normalizeMovie(inputMovie,'normalizationType','detrend','detrendDegree',1); +% ================================================= %% USER INTERFACE Get coordinates to crop from the user separately if guiEnabled==1 [cropCoords] = getCropCoords(squeeze(inputMovie(:,:,1))); @@ -64,7 +73,9 @@ toptions.cropCoords = [26 34 212 188]; end -%% Motion correction +% ================================================= +%% Pre-process movies +% Motion correction toptions.turboregRotation = 0; toptions.removeEdges = 1; toptions.pxToCrop = 10; @@ -95,6 +106,7 @@ playMovie(inputMovie3,'extraTitleText','Processed movie for cell extraction'); end +% ================================================= %% Run PCA-ICA cell extraction nPCs = 300; nICs = 225; @@ -108,6 +120,50 @@ saveNeurodataWithoutBorders(pcaicaStruct.IcaFilters,{pcaicaStruct.IcaTraces},'pcaica',nwbFilePath); end +% ================================================= +%% Run CNMF or CNMF-e cell extraction +numExpectedComponents = 225; +cellWidth = 10; +cnmfOptions.otherCNMF.tau = cellWidth/2; % expected width of cells + +% Run CNMF +[success] = cnmfVersionDirLoad('current'); +[cnmfAnalysisOutput] = computeCnmfSignalExtractionClass(movieList,numExpectedComponents,'options',cnmfOptions); + +% Run CNMF-e +[success] = cnmfVersionDirLoad('cnmfe'); +[cnmfeAnalysisOutput] = computeCnmfeSignalExtraction_batch(movieList{1},'options',cnmfeOptions); + +% Save outputs to NWB format +if saveAnalysis==1 + saveNeurodataWithoutBorders(cnmfAnalysisOutput.extractedImages,{cnmfAnalysisOutput.extractedSignals,cnmfAnalysisOutput.extractedSignalsEst},'cnmf','cnmf.nwb'); + saveNeurodataWithoutBorders(cnmfeAnalysisOutput.extractedImages,{cnmfeAnalysisOutput.extractedSignals,cnmfeAnalysisOutput.extractedSignalsEst},'cnmfe','cnmfe.nwb'); +end +[success] = cnmfVersionDirLoad('none'); + +% ================================================= +%% Run EXTRACT cell extraction. Check each function with "edit" for options. +% Load default configuration +loadBatchFxns('loadEverything'); +extractConfig = get_defaults([]); + +outStruct = extractor(inputMovie,extractConfig); +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 +saveNeurodataWithoutBorders(extractAnalysisOutput.filters,{extractAnalysisOutput.traces},'cnmf','cnmf.nwb'); +loadBatchFxns(); + +% ================================================= %% USER INTERFACE Run cell sorting using matrix outputs from cell extraction. if guiEnabled==1 [outImages, outSignals, choices] = signalSorter(pcaicaStruct.IcaFilters,pcaicaStruct.IcaTraces,'inputMovie',inputMovie3); @@ -124,6 +180,7 @@ 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') +% ================================================= %% USER INTERFACE Create an overlay of extraction outputs on the movie and signal-based movie [inputMovieO] = createImageOutlineOnMovie(inputMovie3,IcaFilters,'dilateOutlinesFactor',0); if guiEnabled==1 @@ -138,6 +195,7 @@ movieM = cellfun(@(x) normalizeVector(x,'normRange','zeroToOne'),{inputMovie3,inputMovieO,signalMovie},'UniformOutput',false); playMovie(cat(2,movieM{:})); +% ================================================= %% 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'],... diff --git a/+ciapkg/+io/getOptions.m b/+ciapkg/+io/getOptions.m new file mode 100644 index 0000000..8cbff5f --- /dev/null +++ b/+ciapkg/+io/getOptions.m @@ -0,0 +1,248 @@ +function [options] = getOptions(options,inputArgs,varargin) + % Gets default options for a function and replaces them with inputArgs inputs if they are present in Name-Value pair input (e.g. varargin). + % Biafra Ahanonu + % Started: 2013.11.04. + % + % inputs + % options - structure passed by parent function with each fieldname containing an option to be used by the parent function. + % inputArgs - an even numbered cell array, with {'option','value'} as the ordering. Normally pass varargin. + % Outputs + % options - options structure passed back to parent function with modified Name-Value inputs to function added. + % NOTE + % Use the 'options' name-value pair to input an options structure that will overwrite default options in a function, example below. + % options.Stargazer = 1; + % options.SHH = 0; + % getMutations(mutationList,'options',options); + % + % This is in contrast to using name-value pairs, both will produce the same result. + % getMutations(mutationList,'Stargazer',1,'SHH',0); + % + % The 'passArgs' name-value pair will pass through the parent functions varargin to child functions. + % USAGE + % function [input1,input2] = exampleFxn(input1,input2,varargin) + % %======================== + % % DESCRIPTION + % options.Stargazer = ''; + % % DESCRIPTION + % options.SHH = ''; + % % DESCRIPTION + % options.Option3 = ''; + % % get options + % options = getOptions(options,varargin); % ***HERE IS WHERE getOptions IS USED*** + % % display(options) + % % unpack options into current workspace + % % fn=fieldnames(options); + % % for i=1:length(fn) + % % eval([fn{i} '=options.' fn{i} ';']); + % % end + % %======================== + % try + % % Do something. + % % How to use the passArgs feature. + % childFunction(arg1,arg2,'passArgs',varargin); + % catch err + % disp(repmat('@',1,7)) + % disp(getReport(err,'extended','hyperlinks','on')); + % disp(repmat('@',1,7)) + % end + % end + + % changelog + % 2014.02.12 [11:56:00] - added feature to allow input of an options structure that contains the options instead of having to input multiple name-value pairs. - Biafra + % 2014.07.10 [05:19:00] - added displayed warning if an option is input that was not present (this usually indicates typo). - Lacey (merged) + % 2014.12.10 [19:32:54] - now gets calling function and uses that to get default options - Biafra + % 2015.08.24 [23:31:36] - updated comments. - Biafra + % 2015.12.03 [13:52:15] - Added recursive aspect to mirrorRightStruct and added support for handling struct name-value inputs. mirrorRightStruct checks that struct options input by the user are struct in the input options. - Biafra + % 2016.xx.xx - warnings now show both calling function and it's parent function, improve debug for warnings. Slight refactoring of code to make easier to follow. - Biafra + % 2020.05.10 [18:00:23] - Updates to comments in getOptions and other minor changes. Make warnings output as actual warnings instead of just displaying as normal text on command line. + % 2020.06.29 [18:54:56] - Support case where calling getOptions from command line or where there is no stack. + % 2020.09.29 [13:21:09] - Added passArgs option, this mimics the ... construct in R, so users can pass along arguments without having to define them in the calling function (e.g. in the case of wrapper functions). + + % TODO + % Allow input of an option structure - DONE! + % Call settings function to have defaults for all functions in a single place - DONE! + % Allow recursive overwriting of options structure - DONE! + % Type checking of all field names input by the user? + + %======================== + % Options for getOptions. + % Avoid recursion here, hence don't use getOptions for getOptions's options. + % Binary: 1 = whether getOptions should use recursive structures or crawl through a structure's field names or just replace the entire structure. For example, if "1" then options that themselves are a structure or contain sub-structures, the fields will be replaced rather than the entire strucutre. + goptions.recursiveStructs = 1; + % Binary: 1 = show warning if user inputs Name-Value pair option input that is not in original structure. + goptions.showWarnings = 1; + % Int: number of parent stacks to show during warning. + goptions.nParentStacks = 1; + % Binary: 1 = get defaults for a function from getSettings. + goptions.getFunctionDefaults = 0; + % Update getOptions's options based on user input. + try + for i = 1:2:length(varargin) + inputField = varargin{i}; + if isfield(goptions, inputField) + inputValue = varargin{i+1}; + goptions.(inputField) = inputValue; + end + end + catch err + localShowErrorReport(err); + display(['Incorrect options given to getOptions"']) + end + % Don't do this! Recursion with no base case waiting to happen... + % goptions = getOptions(goptions,varargin); + %======================== + + % Get default options for a function + if goptions.getFunctionDefaults==1 + [ST,I] = dbstack; + % fieldnames(ST) + parentFunctionName = {ST.name}; + parentFunctionName = parentFunctionName{2}; + [optionsTmp] = getSettings(parentFunctionName); + if isempty(optionsTmp) + % Do nothing, don't use defaults if not present + else + options = optionsTmp; + % options = mirrorRightStruct(inputOptions,options,goptions,val); + end + end + + % Get list of available options + validOptions = fieldnames(options); + + % Loop over all input arguments, overwrite default/input options + for i = 1:2:length(inputArgs) + % inputArgs = inputArgs{1}; + val = inputArgs{i}; + if ischar(val) + %display([inputArgs{i} ': ' num2str(inputArgs{i+1})]); + if strcmp('options',val) + % Special options struct, only add field names defined by the user. Keep all original field names that are not input by the user. + inputOptions = inputArgs{i+1}; + options = mirrorRightStruct(inputOptions,options,goptions,val); + elseif strcmp('passArgs',val) + % Special argument to pass all these arguments directly through parent function to child function. + inputOptions = inputArgs{i+1}; + options = getOptions(options,inputOptions); + elseif sum(strcmp(val,validOptions))>0&isstruct(options.(val))&goptions.recursiveStructs==1 + % If struct name-value, add users field name changes only, keep all original field names in the struct intact, struct-recursion ON + inputOptions = inputArgs{i+1}; + options.(val) = mirrorRightStruct(inputOptions,options.(val),goptions,val); + elseif sum(strcmp(val,validOptions))>0 + % Non-options, non-struct value, struct-recursion OFF + % elseif ~isempty(strcmp(val,validOptions)) + % Way more elegant, directly overwrite option + options.(val) = inputArgs{i+1}; + % eval(['options.' val '=' num2str(inputArgs{i+1}) ';']); + else + if goptions.showWarnings==1 + localShowWarnings(2,'name-value','','',val,goptions.nParentStacks); + end + end + else + if goptions.showWarnings==1 + localShowWarnings(2,'name-value incorrect','','',val,goptions.nParentStacks); + end + continue; + end + end + %display(options); +end +function [toStruct] = mirrorRightStruct(fromStruct,toStruct,goptions,toStructName) + % Overwrites fields in toStruct with those in fromStruct, other toStruct fields remain intact. + % More generally, copies fields in fromStruct into toStruct, if there is an overlap in field names, fromStruct overwrites. + % Fields present in toStruct but not fromStruct are kept in toStruct output. + fromNames = fieldnames(fromStruct); + for name = 1:length(fromNames) + fromField = fromNames{name}; + % if a field name is a struct, recursively grab user options from it + if isfield(toStruct, fromField)|isprop(toStruct, fromField) + if isstruct(fromStruct.(fromField))&goptions.recursiveStructs==1 + % safety check: field exist in toStruct and is also a structure + if isstruct(toStruct.(fromField)) + toStruct.(fromField) = mirrorRightStruct(fromStruct.(fromField),toStruct.(fromField),goptions,[toStructName '.' fromField]); + else + localShowWarnings(3,'notstruct',toStructName,fromField,'',goptions.nParentStacks); + end + else + toStruct.(fromField) = fromStruct.(fromField); + end + else + if goptions.showWarnings==1 + localShowWarnings(3,'struct',toStructName,fromField,'',goptions.nParentStacks); + end + end + end +end +function localShowErrorReport(err) + % Displays an error report. + display(repmat('@',1,7)) + disp(getReport(err,'extended','hyperlinks','on')); + display(repmat('@',1,7)) +end +function localShowWarnings(stackLevel,displayType,toStructName,fromField,val,nParentStacks) + % Sub-function to centralize displaying of warnings within the function + try + % Calling localShowWarnings adds to the stack, adjust accordingly. + stackLevel = stackLevel+1; + + % Get the entire function-call stack. + [ST,~] = dbstack; + if isempty(ST)|length(ST)=(stackLevelTwo) + callingFxnParent = ST(stackLevelTwo).name; + callingFxnParentPath = which(ST(stackLevelTwo).file); + callingFxnParentLine = num2str(ST(stackLevelTwo).line); + callingFxnParentStr = [callingFxnParentStr ' | ' callingFxnParent ' line ' callingFxnParentLine]; + else + callingFxnParentStr = ''; + end + stackLevelTwo = stackLevelTwo+1; + end + + % Display different information based on what type of warning occurred. + switch displayType + case 'struct' + warning(['WARNING: ' toStructName '.' fromField ' is not a valid option for ' callingFxn ' on line ' callingFxnLine callingFxnParentStr]) + case 'notstruct' + warning(['WARNING: ' toStructName '.' fromField ' is not originally a STRUCT, ignoring. ' callingFxn ' on line ' callingFxnLine callingFxnParentStr]) + case 'name-value incorrect' + warning(['WARNING: enter the parameter name before its associated value in ' callingFxn ' on line ' callingFxnLine callingFxnParentStr]) + case 'name-value' + warning(['WARNING: ' val ' is not a valid option for ' callingFxn ' on line ' callingFxnLine callingFxnParentStr]) + otherwise + % do nothing + end + catch err + localShowErrorReport(err); + subfxnShowWarningsError(stackLevel,displayType,toStructName,fromField,val,nParentStacks); + end +end +function subfxnShowWarningsError(stackLevel,displayType,toStructName,fromField,val,nParentStacks) + callingFxn = 'UNKNOWN FUNCTION'; + % Display different information based on what type of warning occurred. + switch displayType + case 'struct' + warning(['WARNING: ' toStructName '.' fromField ' is not a valid option for "' callingFxn '"']) + case 'notstruct' + warning('Unknown error.') + case 'name-value incorrect' + warning(['WARNING: enter the parameter name before its associated value in "' callingFxn '"']) + case 'name-value' + warning(['WARNING: ' val ' is not a valid option for "' callingFxn '"']) + otherwise + % do nothing + end +end \ No newline at end of file diff --git a/+ciapkg/+io/loadDependencies.m b/+ciapkg/+io/loadDependencies.m index a8cfb01..d69b928 100644 --- a/+ciapkg/+io/loadDependencies.m +++ b/+ciapkg/+io/loadDependencies.m @@ -16,6 +16,7 @@ function loadDependencies(varargin) % 2021.02.01 [15:10:41] - Separated into non-class function for use in more functions without needing to load CIAtah class. % 2021.02.01 [‏‎15:19:40] - Update `_external_programs` to call ciapkg.getDirExternalPrograms() to standardize call across all functions. % 2021.03.20 [18:12:20] - Added EXTRACT support to list of functions to download. + % 2021.06.19 [23:46:58] - Switched to support for original MIJ calling of ImageJ using just jar files, easier compatibility across MATLAB versions and OSes. % TODO % Verify all dependencies download and if not ask user to download again. @@ -23,11 +24,11 @@ function loadDependencies(varargin) % DESCRIPTION options.externalProgramsDir = ciapkg.getDirExternalPrograms(); options.guiEnabled = 1; - options.dependencyStr = {'downloadMiji','downloadCnmfGithubRepositories','example_downloadTestData','loadMiji','downloadNeuroDataWithoutBorders','downloadEXTRACT'}; + options.dependencyStr = {'downloadMiji','downloadCnmfGithubRepositories','example_downloadTestData','loadMiji','downloadNeuroDataWithoutBorders','downloadEXTRACT','downloadBioFormats','downloadImageJ'}; - options.dispStr = {'Download Fiji (to run Miji)','Download CNMF, CNMF-E, and CVX code.','Download test one- and two photon datasets.','Load Fiji/Miji into MATLAB path.','Download NWB (NeuroDataWithoutBorders)','Download EXTRACT'}; + options.dispStr = {'Download Fiji (to run Miji)','Download CNMF, CNMF-E, and CVX code.','Download test one- and two photon datasets.','Load Fiji/Miji into MATLAB path.','Download NWB (NeuroDataWithoutBorders)','Download EXTRACT','Download Bio-Formats','Download ImageJ'}; % Int vector: index of options.dependencyStr to run by default with no GUI - options.depIdxArray = [1 2 3 5 6]; + options.depIdxArray = [2 3 5 6 7 8]; % Binary: 1 = force update even if already downloaded. 0 = skip if already downloaded options.forceUpdate = 0; % get options @@ -123,6 +124,33 @@ function loadDependencies(varargin) % Add NWB folders to path. ciapkg.nwb.setupNwb; % obj.loadBatchFunctionFolders; + case 'downloadBioFormats' + optionsH.forceUpdate = forceUpdate; + optionsH.signalExtractionDir = options.externalProgramsDir; + optionsH.gitNameDisp = {'bfmatlab'}; + optionsH.gitRepos = {'https://downloads.openmicroscopy.org/bio-formats/6.6.1/artifacts/bfmatlab.zip'}; + optionsH.outputDir = optionsH.gitNameDisp; + % optionsH.gitName = cellfun(@(x) [x '-master'],optionsH.gitNameDisp,'UniformOutput',false); + optionsH.gitName = {'bfmatlab'}; + [success] = downloadGithubRepositories('options',optionsH); + case 'downloadImageJ' + % Download mij.jar and ij.ar. + downloadFiles = {'http://bigwww.epfl.ch/sage/soft/mij/mij.jar','http://rsb.info.nih.gov/ij/upgrade/ij.jar'} + downloadFileNames = {'mij.jar','ij.jar'}; + imagejPath = [options.externalProgramsDir filesep 'imagej']; + ciapkg.io.mkdir(imagejPath); + nFiles = length(downloadFiles); + for i=1:nFiles + rawSavePathDownload = [imagejPath filesep downloadFileNames{i}]; + downloadUrl = downloadFiles{i}; + if exist(rawSavePathDownload,'file')~=2|forceUpdate==1 + fprintf('Downloading %s file to %s\n',downloadUrl,rawSavePathDownload) + websave(rawSavePathDownload,downloadUrl); + else + fprintf('Already downloaded %s\n',rawSavePathDownload) + end + end + manageMiji('startStop','setupImageJ'); otherwise % nothing end diff --git a/+ciapkg/+io/loadSignalExtraction.m b/+ciapkg/+io/loadSignalExtraction.m index 1e08480..0a33302 100644 --- a/+ciapkg/+io/loadSignalExtraction.m +++ b/+ciapkg/+io/loadSignalExtraction.m @@ -70,11 +70,13 @@ [~,~,inputEXT] = fileparts(inputFilePath); switch inputEXT case '.nwb' + disp('Loading NWB file.') nwbOpts.groupImages = options.nwbGroupImages; nwbOpts.groupSignalSeries = options.nwbGroupSignalSeries; [inputImages,inputSignals,infoStruct,algorithmStr] = loadNeurodataWithoutBorders(inputFilePath,'options',nwbOpts); return; case '.mat' + disp(['Loading ' ciapkg.pkgName ' MAT-file.']) % Do nothing, go to the next steps below. otherwise % Do nothing diff --git a/+ciapkg/+io/updatePkg.m b/+ciapkg/+io/updatePkg.m index cb14833..bd19147 100644 --- a/+ciapkg/+io/updatePkg.m +++ b/+ciapkg/+io/updatePkg.m @@ -9,8 +9,9 @@ % changelog % 2021.03.09 [21:34:52] - Option on whether to update package (only 0 for now). Also alert user if behind a version. + % 2021.06.21 [16:18:07] - Updated to ciatah from calciumImagingAnalysis URLs. % TODO - % + % Only check once every couple of days to warn user instead of every time. %======================== % Char cell array: list of directories to remove then update, lead private, _external_programs, and data directories intact. @@ -22,7 +23,7 @@ 'docs',... 'file_exchange'}; % [IGNORE] Char: GitHub API URL to VERSION file on CIAPKG repository. - options.versionURL = 'https://api.github.com/repos/bahanonu/calciumImagingAnalysis/contents/+ciapkg/VERSION'; + options.versionURL = {'https://api.github.com/repos/bahanonu/ciatah/contents/+ciapkg/VERSION','https://api.github.com/repos/bahanonu/ciatah/contents/ciapkg/VERSION','https://api.github.com/repos/bahanonu/ciatah/contents/VERSION'}; % Binary: 1 = pop-up GUI enabled options.showGui = 1; % Binary: 1 = update code, 0 = only check for update and notify user behind a version. diff --git a/+ciapkg/VERSION b/+ciapkg/VERSION index 0d30f87..680bf87 100644 --- a/+ciapkg/VERSION +++ b/+ciapkg/VERSION @@ -1,2 +1,2 @@ -v3.26.2 -20210325200706 \ No newline at end of file +v3.30.1 +2021.06.21 [14:54:33] \ No newline at end of file diff --git a/+ciapkg/exampleFxn.m b/+ciapkg/exampleFxn.m index 4dfd037..cfac8d2 100644 --- a/+ciapkg/exampleFxn.m +++ b/+ciapkg/exampleFxn.m @@ -34,7 +34,7 @@ end end -% calciumImagingAnalysis method +% CIAtah method function obj = functionName(obj,varargin) % DESCRIPTION % Biafra Ahanonu diff --git a/@ciatah/ciatah.m b/@ciatah/ciatah.m index 3701772..0f06d3c 100644 --- a/@ciatah/ciatah.m +++ b/@ciatah/ciatah.m @@ -21,6 +21,7 @@ % 2020.05.07 [15:13:53] - Refactored a bit to remove methods that do not need to be in the main class definition to allow easier updating later. % 2021.03.25 [20:15:31] - Use ciapkg.getDir() to ensure using root directory consistently rather than ciapkgRoot. % 2021.03.25 [22:46:38] - Moved many smaller helper functions in ciatah.m to their own M-files to make maintenance easier. + % 2021.06.18 [20:28:28] - Added modelVarsFromFilesCheck support. % TODO % @@ -275,9 +276,10 @@ nwbFileFolder = 'nwbFiles'; % Str: blank, use calciumImagingAnalysis regexp, else force use of this regexp for NWB files nwbFileRegexp = ''; - % Name of H5 group for images and signal series in NWB files + % Name of H5 group for movies, images, and signal series in NWB files nwbGroupImages = '/processing/ophys/ImageSegmentation/PlaneSegmentation'; nwbGroupSignalSeries = '/processing/ophys/Fluorescence/RoiResponseSeries'; + nwbGroupMovie = '/acquisition/TwoPhotonSeries/data'; settingOptions = struct(... 'analysisType', {{'group','individual'}},... @@ -453,12 +455,13 @@ 'modelLoadSaveData', 'modelExportData', '', - '------- PREPROCESS -------', - 'modelDownsampleRawMovies', + '------- VISUALIZATION/PREPROCESS CHECK -------', 'viewMovieFiltering', 'viewMovieRegistrationTest', - '', 'viewMovie', + '', + '------- PREPROCESS -------', + 'modelDownsampleRawMovies', 'modelPreprocessMovie', 'modelModifyMovies', 'removeConcurrentAnalysisFiles', @@ -822,5 +825,6 @@ obj = makeFolderDirs(obj) [flagOut] = usaflag(obj) obj = saveObj(obj) + obj = modelVarsFromFilesCheck(obj,folderNo,varargin) end end \ No newline at end of file diff --git a/@ciatah/ciatahMainGui.m b/@ciatah/ciatahMainGui.m index cb0bc94..18897d9 100644 --- a/@ciatah/ciatahMainGui.m +++ b/@ciatah/ciatahMainGui.m @@ -103,7 +103,11 @@ tmpList2 = fieldnames(selBoxInfo); for ff = 1:length(tmpList2) try - hListboxS.(tmpList2{ff}) = uicontrol(hFig, 'style','listbox','Units','normalized','position',selBoxInfo.(tmpList2{ff}).loc/100, 'string',selBoxInfo.(tmpList2{ff}).string,'Value',selBoxInfo.(tmpList2{ff}).Value,'Tag',selBoxInfo.(tmpList2{ff}).Tag); + hListboxS.(tmpList2{ff}) = uicontrol(hFig, 'style','listbox','Units','normalized',... + 'position',selBoxInfo.(tmpList2{ff}).loc/100,... + 'string',selBoxInfo.(tmpList2{ff}).string,... + 'Value',selBoxInfo.(tmpList2{ff}).Value,... + 'Tag',selBoxInfo.(tmpList2{ff}).Tag); if strcmp('methods',tmpList2{ff})==1 set(hListboxS.(tmpList2{ff}),'background',[0.8 0.9 0.8]); end @@ -114,7 +118,10 @@ hListboxT.(tmpList2{ff}) = uicontrol('Style','Text','String',selBoxInfo.(tmpList2{ff}).title,'Units','normalized','Position',selBoxInfo.(tmpList2{ff}).titleLoc/100,'BackgroundColor','white','HorizontalAlignment','Left','FontWeight','Bold'); set(hListboxS.(tmpList2{ff}),'Max',2,'Min',0); - catch + catch err + disp(repmat('@',1,7)) + disp(getReport(err,'extended','hyperlinks','on')); + disp(repmat('@',1,7)) end end hListbox = hListboxS.methods; diff --git a/@ciatah/computeManualSortSignals.m b/@ciatah/computeManualSortSignals.m index 732d51c..065d6eb 100644 --- a/@ciatah/computeManualSortSignals.m +++ b/@ciatah/computeManualSortSignals.m @@ -13,8 +13,10 @@ % 2019.09.09 [18:14:48] - Update to handling uigetfile output. % 2021.01.21 [10:37:07] - Updated to support HDF5 and regexp for movie manual names along with misc. other changes. % 2021.03.17 [16:34:59] - If user hasn't called modelVarsFromFiles, computeManualSortSignals called the function. However, this lead to a mismatch between computeManualSortSignals fileNum and obj.fileNum, leading to mismatch between xcoords, etc. and input signals/images. + % 2021.06.18 [21:41:07] - added modelVarsFromFilesCheck() to check and load signals if user hasn't already. + % ADDED + % ADD PERSONS NAME TO THE FILE - DONE. % TODO - % ADD PERSONS NAME TO THE FILE % ======= options.emSaveRaw = '_emAnalysis.mat'; @@ -40,6 +42,9 @@ % fileNum = obj.fileNum; display(repmat('#',1,21)) display([num2str(thisFileNumIdx) '/' num2str(nFilesToAnalyze) ' (' num2str(obj.fileNum) '/' num2str(nFiles) '): ' obj.fileIDNameArray{obj.fileNum}]); + + % Check that signal extraction information is loaded. + obj.modelVarsFromFilesCheck(fileNum); % ======= % path to current folder currentFolderPath = obj.inputFolders{obj.fileNum}; @@ -94,18 +99,6 @@ % usrIdxChoiceSettings = settingStruct.usrIdxChoiceSettings; end - try - [rawSignals rawImages signalPeaks signalPeaksArray, ~, ~, rawSignals2] = modelGetSignalsImages(obj,'returnType','raw'); - skipReload = 1; - catch - obj.guiEnabled = 0; - % originalFileNum = - obj.modelVarsFromFiles(); - obj.fileNum = fileNum; - obj.guiEnabled = 1; - skipReload = 0; - end - % get list of movies movieList = getFileList(currentFolderPath, fileFilterRegexp); if strcmp(usrIdxChoiceMovie,'load movie') diff --git a/@ciatah/computeMatchObjBtwnTrials.m b/@ciatah/computeMatchObjBtwnTrials.m index 276a33d..d6727a3 100644 --- a/@ciatah/computeMatchObjBtwnTrials.m +++ b/@ciatah/computeMatchObjBtwnTrials.m @@ -9,6 +9,7 @@ % changelog % 2019.07.03 [16:36:32] - Updated to call viewMatchObjBtwnSessions afterwards as an option + % 2021.06.18 [21:41:07] - added modelVarsFromFilesCheck() to check and load signals if user hasn't already. % TODO % @@ -101,6 +102,10 @@ obj.fileNum = validFoldersIdx(idx); display(repmat('*',1,7)) display([num2str(idx) '/' num2str(length(validFoldersIdx)) ': ' obj.fileIDNameArray{obj.fileNum}]); + + % Check that signal extraction information is loaded. + obj.modelVarsFromFilesCheck(obj.fileNum); + % obj.folderBaseSaveStr{obj.fileNum} % [rawSignalsTmp rawImagesTmp signalPeaks signalPeaksArray] = modelGetSignalsImages(obj,'returnType','raw'); [rawSignalsTmp, rawImagesTmp, signalPeaks, signalPeaksArray] = modelGetSignalsImages(obj,'returnType','filtered'); diff --git a/@ciatah/getRegistrationSettings.m b/@ciatah/getRegistrationSettings.m index 751e190..25b79b6 100644 --- a/@ciatah/getRegistrationSettings.m +++ b/@ciatah/getRegistrationSettings.m @@ -18,6 +18,7 @@ % 2020.05.28 [21:07:27] - Added support for nargin=1. % 2020.10.21 [16:52:06] - Add support for user canceling the input. % 2020.10.24 [18:30:56] - Added support for calculating dropped frames if entire frame of a movie is a set value. + % 2021.06.21 [14:27:26] - Switch to single page support. % TODO % DONE: Allow user to input prior settings, indicate those changed from default by orange or similar color. @@ -337,33 +338,44 @@ % propertySettingsStr.(property); end + modX = 1.55; + modX_text = 2; figNoDefault = 1337; uiListHandles = {}; uiTextHandles = {}; - uiXIncrement = 0.025; - uiXOffset = 0.02; + uiXIncrement = 0.025/modX; + uiXOffset = 0.02/modX; uiYOffset = 0.90; uiTxtSize = 0.4; uiBoxSize = 0.55; - uiFontSize = 11; + uiFontSize = 9; nGuiSubsets = 3; % subsetList = round(linspace(1,nPropertiesToChange,nGuiSubsets)); subsetList = [1 35 nPropertiesToChange]; % subsetList % for subsetNo = 1:nGuiSubsets nGuiSubsetsTrue = (nGuiSubsets-1); + + nGuiSubsets = 2; + nGuiSubsetsTrue = (nGuiSubsets-1); + % nGuiSubsetsTrue = 1; figure(figNoDefault); for thisSet = 1:nGuiSubsetsTrue % 1:nPropertiesToChange % subsetStartTime = tic; subsetStartIdx = subsetList(thisSet); subsetEndIdx = subsetList(thisSet+1); + + subsetStartIdx = 1; + subsetEndIdx = nPropertiesToChange; + if thisSet==nGuiSubsetsTrue propertySubsetList = subsetStartIdx:(subsetEndIdx); else propertySubsetList = subsetStartIdx:(subsetEndIdx-1); end + [figHandle figNo] = openFigure(figNoDefault, ''); clf uicontrol('Style','Text','String',inputTitleStr,'Units','normalized','Position',[uiXOffset uiYOffset+0.05 0.8 0.05],'BackgroundColor','white','HorizontalAlignment','Left','FontSize',uiFontSize); @@ -378,12 +390,16 @@ if propertyNo~=1 if isempty(regexp(property,'______________')) spaceMod = 0.00; + FontWeightH = 'normal'; else - spaceMod = 0.02; + spaceMod = 0.01; uiYOffset = uiYOffset-spaceMod; + FontWeightH = 'bold'; end + else + FontWeightH = 'bold'; end - uiTextHandles{propertyNo} = uicontrol('Style','text','String',[property '' 10],'Units','normalized','Position',[uiXOffset uiYOffset-uiXIncrement*propertyNoDisp+0.027 uiTxtSize 0.0225],'BackgroundColor',[0.9 0.9 0.9],'ForegroundColor','black','HorizontalAlignment','Left','FontSize',uiFontSize,'ToolTip',propertyTooltip); + uiTextHandles{propertyNo} = uicontrol('Style','text','String',[property '' 10],'Units','normalized','Position',[uiXOffset uiYOffset-uiXIncrement*propertyNoDisp+modX_text*(0.027/modX) uiTxtSize 0.0225/modX],'BackgroundColor',[0.9 0.9 0.9],'ForegroundColor','black','HorizontalAlignment','Left','FontSize',uiFontSize,'ToolTip',propertyTooltip,'FontWeight',FontWeightH); % jEdit = findjobj(uiTextHandles{propertyNo}); % lineColor = java.awt.Color(1,0,0); % =red % thickness = 3; % pixels diff --git a/@ciatah/loadDependencies.m b/@ciatah/loadDependencies.m index 1505f48..7338fe3 100644 --- a/@ciatah/loadDependencies.m +++ b/@ciatah/loadDependencies.m @@ -50,9 +50,9 @@ % end sopts.guiEnabled = obj.guiEnabled; - sopts.dependencyStr = options.dependencyStr; - sopts.dispStr = options.dispStr; - sopts.depIdxArray = options.depIdxArray; + % sopts.dependencyStr = options.dependencyStr; + % sopts.dispStr = options.dispStr; + % sopts.depIdxArray = options.depIdxArray; ciapkg.io.loadDependencies('options',sopts); diff --git a/@ciatah/modelExtractSignalsFromMovie.m b/@ciatah/modelExtractSignalsFromMovie.m index dbe2433..830e718 100644 --- a/@ciatah/modelExtractSignalsFromMovie.m +++ b/@ciatah/modelExtractSignalsFromMovie.m @@ -20,9 +20,11 @@ % 2019.10.29 [17:21:23] - Added a check to make sure that filenames produced are valid MATLAB ones for settings, e.g. for CNMF-e. % 2019.11.10 [20:34:42] - Add a warning with some common tips for users if error during cell extraction. Skip modelVarsFromFiles and viewObjmaps loading to reduce user confusion for any folders that had issues during cell extraction. % 2020.05.08 [20:01:52] - Make creation of settings an explicit option that the user can change. - % 2021.02.01 [‏‎15:19:40] - Update `_external_programs` to call ciapkg.getDirExternalPrograms() to standardize call across all functions. + % 2021.02.01 [?‎15:19:40] - Update `_external_programs` to call ciapkg.getDirExternalPrograms() to standardize call across all functions. % 2021.02.25 [16:44:41] - Update `saveRunTimes` to handle case in which user selects multiple movies for cell extraction. % 2021.03.20 [19:23:25] - Convert ndSparse outputs to single from cell-extraction algorithms (e.g. for CELLMax/EXTRACT) when saving as NWB. Updated EXTRACT support to include additional options. + % 2021.04.08 [16:23:20] - Use filesep in getAlgorithmRootPath to avoid issues in Unix-based systems. + % 2021.06.16 [09:07:46] - Fix issue of passing multiple movies to PCA-ICA. % TODO % @@ -471,7 +473,7 @@ function getAlgorithmRootPath(algorithmFile,algorithmName,obj,rootFlag) % First try to automatically add the folder try % foundFiles = dir(fullfile([obj.defaultObjDir filesep obj.externalProgramsDir], ['**\' algorithmFile ''])); - foundFiles = dir(fullfile([obj.externalProgramsDir], ['**\' algorithmFile ''])); + foundFiles = dir(fullfile([obj.externalProgramsDir], ['**' filesep algorithmFile ''])); pathToAdd = foundFiles.folder; if rootFlag==1 [pathToAdd,~,~] = fileparts(pathToAdd); @@ -498,7 +500,7 @@ function getAlgorithmRootPath(algorithmFile,algorithmName,obj,rootFlag) end if exist(algorithmFile,'file')~=2 - pathToAlgorithm = uigetdir('\.',sprintf('Enter path to %s root folder (e.g. from github)',algorithmName)); + pathToAlgorithm = uigetdir([filesep '.'],sprintf('Enter path to %s root folder (e.g. from github)',algorithmName)); if ischar(pathToAlgorithm) privateLoadBatchFxnsPath = obj.privateSettingsPath; % if exist(privateLoadBatchFxnsPath,'file')~=0 @@ -1095,6 +1097,13 @@ function runPCAICASignalFinder() nICs = nPCsnICs(2); % movieList = getFileList(obj.inputFolders{obj.fileNum}, fileFilterRegexp); + + % Ensure only a single movie is passed, else PCA-ICA runs into dimension errors. + if iscell(movieList) + if length(movieList)>2 + movieList = movieList{1}; + end + end % [inputMovie] = loadMovieList(movieList,'convertToDouble',0,'frameList',[]); if oldPCAICA==1 @@ -1115,15 +1124,17 @@ function runPCAICASignalFinder() imageSaveDimOrder = 'zxy'; end else - display('running PCA-ICA, new version...') + disp('running PCA-ICA, new version...') [PcaOutputSpatial, PcaOutputTemporal, PcaOutputSingularValues, PcaInfo] = run_pca(movieList, nPCs, 'movie_dataset_name',obj.inputDatasetName); - + disp(['PcaOutputSpatial: ' num2str(size(PcaOutputSpatial))]); + disp(['PcaOutputTemporal: ' num2str(size(PcaOutputTemporal))]); + disp(['PcaOutputSingularValues: ' num2str(size(PcaOutputSingularValues))]); if isempty(PcaOutputTemporal) - display('PCs are empty, skipping...') + disp('PCs are empty, skipping...') return; end - display('+++') + disp('+++') movieDims = loadMovieList(movieList,'convertToDouble',0,'frameList',[],'inputDatasetName',obj.inputDatasetName,'treatMoviesAsContinuous',1,'getMovieDims',1); % output_units = 'fl'; diff --git a/@ciatah/modelModifyMovies.m b/@ciatah/modelModifyMovies.m index 39cd25e..29c0cf0 100644 --- a/@ciatah/modelModifyMovies.m +++ b/@ciatah/modelModifyMovies.m @@ -10,6 +10,7 @@ % changelog % 2019.06.10 [11:01:55] - Added support for non-Miji based masking. % 2019.10.28 [15:58:45] - Cast the movie mask to be same type as the movie to deal with integer movie inputs. + % 2021.06.20 [00:21:33] - manageMiji('startStop','closeAllWindows'); added to improve support for ImageJ over Fiji implementation of Miji. % TODO % @@ -135,11 +136,13 @@ movieMaskArray{thisFileNumIdx}{maskNo} = MIJ.getCurrentImage; % Ensure that it is a binary mask, sometimes ImageJ would give out negative values movieMaskArray{thisFileNumIdx}{maskNo} = movieMaskArray{thisFileNumIdx}{maskNo}>0; - MIJ.run('Close All Without Saving'); + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); catch err movieMaskArray{thisFileNumIdx}{maskNo} = []; try - MIJ.run('Close All Without Saving'); + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); catch end display(repmat('@',1,7)) @@ -147,7 +150,8 @@ display(repmat('@',1,7)) end else - MIJ.run('Close All Without Saving'); + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); movieMaskArray{thisFileNumIdx}{maskNo} = []; end elseif strcmp(options.videoPlayer,'matlab') diff --git a/@ciatah/modelModifyRegionAnalysis.m b/@ciatah/modelModifyRegionAnalysis.m index 1a01f58..ffd5210 100644 --- a/@ciatah/modelModifyRegionAnalysis.m +++ b/@ciatah/modelModifyRegionAnalysis.m @@ -9,6 +9,7 @@ % changelog % 2017.01.14 [20:06:04] - support switched from [nSignals x y] to [x y nSignals] + % 2021.06.18 [21:41:07] - added modelVarsFromFilesCheck() to check and load signals if user hasn't already. % TODO % %======================== @@ -47,6 +48,8 @@ display(repmat('=',1,21)) display([num2str(fileNum) '/' num2str(nFolders) ': ' obj.fileIDNameArray{obj.fileNum}]); + obj.modelVarsFromFilesCheck(fileNum); + if strcmp(analysisToRun,'loadPreviousSelections') regionFile = getFileList(obj.inputFolders{obj.fileNum},obj.regionModSaveStr); % if no file, skip diff --git a/@ciatah/modelPreprocessMovieFunction.m b/@ciatah/modelPreprocessMovieFunction.m index 75b59c4..ded1682 100644 --- a/@ciatah/modelPreprocessMovieFunction.m +++ b/@ciatah/modelPreprocessMovieFunction.m @@ -31,7 +31,11 @@ % 2020.09.22 [00:11:03] - Updated to add NWB support. % 2020.10.24 [18:30:56] - Added support for calculating dropped frames if entire frame of a movie is a set value. Changed order so that dropped frames calculated before dF/F. % 2021.02.15 [12:06:59] - _inputMovieF0 now saved to processing subfolder. + % 2021.04.11 [10:52:10] - Fixed thisFrame issue when displaying area to use for motion correction if treatMoviesAsContinuous=0 and processMoviesSeparately=0, e.g. would load reference frame from each and if there were 3 movies, would assume RGB, causing display to be white. Also update so the display frame takes into account custom frame list range. + % 2021.06.09 [00:40:35] - Updated checking of options. Also save ordering of options selected. + % 2021.06.20 [00:22:38] - Added manageMiji('startStop','closeAllWindows'); support. % TODO + % Allow users to save out analysis options order and load it back in. % Insert NaNs or mean of the movie into dropped frame location, see line 260 % Allow easy switching between analyzing all files in a folder together and each file in a folder individually % FML, make this object oriented... @@ -181,6 +185,7 @@ % List of analysis options analysisOptionList = {... 'medianFilter',... + 'downsampleSpace',... 'spatialFilter',... 'stripeRemoval',... 'turboreg',... @@ -195,6 +200,12 @@ 'fft_lowpass'... }; + % List of default analysis options to select + defaultChoiceList = {'turboreg','crop','fixDropFrames','dfof','downsampleTime'}; + + analysisOptionListOrig = analysisOptionList; + defaultChoiceListOrig = defaultChoiceList; + analysisOptsInfo = struct(... 'medianFilter',struct(... 'save','medFlt',... @@ -234,8 +245,25 @@ 'str','Low-pass FFT and save (ignore most cases, check for neuropil).')... ); - % List of default analysis options to select - defaultChoiceList = {'turboreg','crop','fixDropFrames','dfof','downsampleTime'}; + + defaultChoiceIdx = find(ismember(analysisOptionList,defaultChoiceList)); + defaultChoiceIdxS = find(ismember(analysisOptionList{end},defaultChoiceList)); + if isfield(obj.functionSettings,'modelPreprocessMovieFunction') + if ~isempty(obj.functionSettings.modelPreprocessMovieFunction) + try + analysisOptionList = obj.functionSettings.modelPreprocessMovieFunction.analysisOptionList; + defaultChoiceList = obj.functionSettings.modelPreprocessMovieFunction.defaultChoiceList; + defaultChoiceIdx = obj.functionSettings.modelPreprocessMovieFunction.defaultChoiceIdx; + catch err + disp(repmat('@',1,7)) + disp(getReport(err,'extended','hyperlinks','on')); + disp(repmat('@',1,7)) + end + else + end + else + % Do nothing + end analysisOptionListStr = analysisOptionList; for optNoS = 1:length(analysisOptionListStr) @@ -245,15 +273,36 @@ % analysisOptionListStr(strcmp(analysisOptionListStr,'turboreg')) = {'turboreg (motion correction, can include spatial filtering)'}; %defaultChoiceIdx = find(cellfun(@(x) sum(strcmp(x,defaultChoiceList)),analysisOptionList)); - defaultChoiceIdx = find(ismember(analysisOptionList,defaultChoiceList)); try ok = 1; [figHandle figNo] = openFigure(1776, '');clf; - instructTextPos = [0.01 0.65 0.7 0.34]; - listTextPos = [0.01 0.01 0.98 0.6]; + instructTextPos = [1 80 70 20]/100; + listTextPos = [1 1+32 98 60-32]/100; + listTextPos2 = [1 1 98 60-31]/100; + + shortcutMenuHandle = uicontrol('style','pushbutton','Units','normalized','position',[1 65 30 3]/100,'FontSize',9,'string','Reset to default list order','callback',@subfxn_resetSetpsMenu); + shortcutMenuHandle2 = uicontrol('style','pushbutton','Units','normalized','position',[32 65 30 3]/100,'FontSize',9,'string','Select default options (e.g. post-dragging)','callback',@subfxn_highlightDefault); + shortcutMenuHandle2 = uicontrol('style','pushbutton','Units','normalized','position',[63 65 30 3]/100,'FontSize',9,'string','Finished','callback',@subfxn_closeOptions); + % shortcutMenuHandle = uicontrol('style','pushbutton','Units','normalized','position',[32 62 30 3]/100,'FontSize',9,'string','Next screen','callback',@subfxn_highlightDefault); + + + [hListbox jListbox jScrollPane jDND] = reorderableListbox('String',analysisOptionListStr,'Units','normalized','Position',listTextPos,'Max',Inf,'Min',0,'Value',defaultChoiceIdx,... + 'MousePressedCallback',@subfxn_analysisOutputMenuChange,... + 'MouseReleasedCallback',@subfxn_analysisOutputMenuChange,... + 'DragOverCallback',@subfxn_analysisOutputMenuChange2,... + 'DropCallback',@subfxn_analysisOutputMenuChange... + ); + uicontrol('Style','Text','String',['Analysis steps to perform.'],'Units','normalized','Position',[1 62 90 1]/100,'BackgroundColor','white','HorizontalAlignment','Left','FontWeight','bold'); + + [hListboxS jListboxS jScrollPaneS jDNDS] = reorderableListbox('String',analysisOptionListStr,'Units','normalized','Position',listTextPos2,'Max',Inf,'Min',0,'Value',hListbox.Value(end)); + uicontrol('Style','Text','String',['At which analysis step should files be saved to disk?'],'Units','normalized','Position',[1 30.5 90 1]/100,'BackgroundColor','white','HorizontalAlignment','Left','FontWeight','bold'); - [hListbox jListbox jScrollPane jDND] = reorderableListbox('String',analysisOptionListStr,'Units','normalized','Position',listTextPos,'Max',Inf,'Min',0,'Value',defaultChoiceIdx); - uicontrol('Style','Text','String',['Analysis step selection and ordering' 10 '=======' 10 'We can know only that we know nothing.' 10 'And that is the highest degree of human wisdom.' 10 10 '1: Click items to select.' 10 '2: Drag to re-order analysis.' 10 '3: Click command window and press ENTER to continue.'],'Units','normalized','Position',instructTextPos,'BackgroundColor','white','HorizontalAlignment','Left'); + uicontrol('Style','Text','String',['Analysis step selection and ordering' 10 '======='... + 10 'Gentlemen, you can not fight in here! This is the War Room.' 10 'We can know only that we know nothing.' 10 'And that is the highest degree of human wisdom.'... + 10 10 '1: Click items to select.' 10 '2: Drag to re-order analysis.' 10 '3: Click command window and press ENTER to continue.'],'Units','normalized','Position',instructTextPos,'BackgroundColor','white','HorizontalAlignment','Left'); + + + emptyBox = uicontrol('Style','Text','String',[''],'Units','normalized','Position',[1 1 1 1]/100,'BackgroundColor','white','HorizontalAlignment','Left','FontWeight','bold'); if ismac cmdWinEditorFont = 'Menlo-Regular'; @@ -273,8 +322,10 @@ % Wait for user input % set(gcf, 'WindowScrollWheelFcn', @mouseWheelChange); % set(gcf,'KeyPressFcn', @(src,event) set(gcf,'Tag','next')); + set(gcf,'KeyPressFcn', @subfxn_closeOptionsKey); % waitfor(gcf,'Tag'); - pause + waitfor(emptyBox); + % pause % hListbox.String(hListbox.Value) analysisOptionsIdx = hListbox.Value; analysisOptionList = hListbox.String; @@ -312,25 +363,33 @@ defaultSaveList = analysisOptionList{analysisOptionsIdx(end)}; defaultSaveIdx = find(ismember(analysisOptionList,defaultSaveList)); + % List of files to save + saveIdx = hListboxS.Value; - try - [figHandle figNo] = openFigure(1776, '');clf; - [hListbox jListbox jScrollPane jDND] = reorderableListbox('String',analysisOptionListStr,'Units','normalized','Position',listTextPos,'Max',Inf,'Min',0,'Value',defaultSaveIdx); - uicontrol('Style','Text','String',['Analysis steps to save' 10 '=======' 10 'Gentlemen, you can not fight in here! This is the War Room.' 10 10 '1: Click analysis steps to save output' 10 '2: Click command window and press ENTER to continue'],'Units','normalized','Position',instructTextPos,'BackgroundColor','white','HorizontalAlignment','Left'); - usaFlagPic(USAflagStr); - pause - saveIdx = hListbox.Value; - % close(1776); + % Whether to use the old method + oldMethod = 0; + if oldMethod==1 + try + [figHandle figNo] = openFigure(1776, '');clf; + [hListbox jListbox jScrollPane jDND] = reorderableListbox('String',analysisOptionListStr,'Units','normalized','Position',listTextPos,'Max',Inf,'Min',0,'Value',defaultSaveIdx); + uicontrol('Style','Text','String',['Analysis steps to save' 10 '=======' 10 'Gentlemen, you can not fight in here! This is the War Room.' 10 10 '1: Click analysis steps to save output' 10 '2: Click command window and press ENTER to continue'],'Units','normalized','Position',instructTextPos,'BackgroundColor','white','HorizontalAlignment','Left'); + usaFlagPic(USAflagStr); + pause + saveIdx = hListbox.Value; + % close(1776); + [figHandle figNo] = openFigure(1776, '');clf; + catch err + display(repmat('@',1,7)) + disp(getReport(err,'extended','hyperlinks','on')); + display(repmat('@',1,7)) + display('BACKUP DIALOG') + [saveIdx, ok] = listdlg('ListString',analysisOptionList,'InitialValue',defaultSaveIdx,... + 'Name','Gentlemen, you can not fight in here! This is the War Room.',... + 'PromptString','select at which stages to save a file. if option not selected for analysis, will be ignored',... + 'ListSize',[scnsize(3)*0.4 scnsize(4)*0.3]); + end + else [figHandle figNo] = openFigure(1776, '');clf; - catch err - display(repmat('@',1,7)) - disp(getReport(err,'extended','hyperlinks','on')); - display(repmat('@',1,7)) - display('BACKUP DIALOG') - [saveIdx, ok] = listdlg('ListString',analysisOptionList,'InitialValue',defaultSaveIdx,... - 'Name','Gentlemen, you can not fight in here! This is the War Room.',... - 'PromptString','select at which stages to save a file. if option not selected for analysis, will be ignored',... - 'ListSize',[scnsize(3)*0.4 scnsize(4)*0.3]); end % Update file filter to the last saved out option @@ -345,6 +404,15 @@ defaultSaveIdx = find(ismember(analysisOptionList,defaultSaveList)); end + if isfield(obj.functionSettings,'modelPreprocessMovieFunction') + % usrInput = obj.functionSettings.modelEditStimTable.usrInput; + else + obj.functionSettings.modelPreprocessMovieFunction = struct; + end + obj.functionSettings.modelPreprocessMovieFunction.analysisOptionList = analysisOptionList; + obj.functionSettings.modelPreprocessMovieFunction.defaultChoiceList = analysisOptionList(analysisOptionsIdx); + obj.functionSettings.modelPreprocessMovieFunction.defaultChoiceIdx = analysisOptionsIdx; + % ======================== movieSettings = inputdlg({... 'Select frames to use during preprocessing (e.g. 1:1000). **Leave blank to use all movie frames**:',... @@ -1004,6 +1072,109 @@ function mouseWheelChange(hObject, callbackdata, handles) set(gcf,'Tag','next') end end + function subfxn_resetSetpsMenu(src,event) + % analysisOptionListOrig = analysisOptionList; + % defaultChoiceListOrig = defaultChoiceList; + analysisOptionListStr = analysisOptionListOrig; + for optNoS = 1:length(analysisOptionListStr) + analysisOptionListStr{optNoS} = analysisOptsInfo.(analysisOptionListStr{optNoS}).str; + end + defaultChoiceIdx = find(ismember(analysisOptionListOrig,defaultChoiceListOrig)); + hListbox.String = analysisOptionListStr; + hListbox.Value = defaultChoiceIdx; + + hListboxS.String = analysisOptionListStr; + hListboxS.Value = defaultChoiceIdx(end); + end + function subfxn_highlightDefault(src,event) + % analysisOptionListOrig = analysisOptionList; + % defaultChoiceListOrig = defaultChoiceList; + % analysisOptionListStr = analysisOptionListOrig; + % for optNoS = 1:length(analysisOptionListStr) + % analysisOptionListStr{optNoS} = analysisOptsInfo.(analysisOptionListStr{optNoS}).str; + % end + % Correct back to original names before proceeding + tmpList = hListbox.String; + fnTmp = fieldnames(analysisOptsInfo); + for optNoS = 1:length(tmpList) + for fnNo = 1:length(fnTmp) + if strcmp(tmpList{optNoS},analysisOptsInfo.(fnTmp{fnNo}).str)==1 + tmpList{optNoS} = fnTmp{fnNo}; + end + end + end + + defaultChoiceIdx = find(ismember(tmpList,defaultChoiceListOrig)); + % hListbox.String = analysisOptionListStr; + hListbox.Value = defaultChoiceIdx; + hListboxS.Value = defaultChoiceIdx(end); + end + function subfxn_analysisOutputMenuChange(src,event) + % analysisOptionListOrig = analysisOptionList; + % defaultChoiceListOrig = defaultChoiceList; + % analysisOptionListStr = analysisOptionListOrig; + % for optNoS = 1:length(analysisOptionListStr) + % analysisOptionListStr{optNoS} = analysisOptsInfo.(analysisOptionListStr{optNoS}).str; + % end + % Correct back to original names before proceeding + return; + tmpList = hListbox.String; + hListboxS.String = hListbox.String + fnTmp = fieldnames(analysisOptsInfo); + for optNoS = 1:length(tmpList) + for fnNo = 1:length(fnTmp) + if strcmp(tmpList{optNoS},analysisOptsInfo.(fnTmp{fnNo}).str)==1 + tmpList{optNoS} = fnTmp{fnNo}; + end + end + end + + tmpList = tmpList{end}; + defaultChoiceIdx = find(ismember(tmpList,tmpList)); + % hListbox.String = analysisOptionListStr; + hListboxS.Value = defaultChoiceIdx; + + % defaultSaveList = analysisOptionList{analysisOptionsIdx(end)}; + % defaultSaveIdx = find(ismember(analysisOptionList,defaultSaveList)); + end + function subfxn_analysisOutputMenuChange2(src,event,PERMORDER) + % analysisOptionListOrig = analysisOptionList; + % defaultChoiceListOrig = defaultChoiceList; + % analysisOptionListStr = analysisOptionListOrig; + % for optNoS = 1:length(analysisOptionListStr) + % analysisOptionListStr{optNoS} = analysisOptsInfo.(analysisOptionListStr{optNoS}).str; + % end + % Correct back to original names before proceeding + hListboxS.String = hListbox.String(PERMORDER); + tmpList = hListboxS.String; + fnTmp = fieldnames(analysisOptsInfo); + for optNoS = 1:length(tmpList) + for fnNo = 1:length(fnTmp) + if strcmp(tmpList{optNoS},analysisOptsInfo.(fnTmp{fnNo}).str)==1 + tmpList{optNoS} = fnTmp{fnNo}; + end + end + end + + % tmpList2 = tmpList(hListbox.Value); + % tmpList2 + % tmpList2 = tmpList2{end}; + % defaultChoiceIdx = find(ismember(tmpList2,tmpList)); + % hListbox.String = analysisOptionListStr; + hListboxS.Value = hListbox.Value(end); + + % defaultSaveList = analysisOptionList{analysisOptionsIdx(end)}; + % defaultSaveIdx = find(ismember(analysisOptionList,defaultSaveList)); + end + function subfxn_closeOptions(src,event) + delete(emptyBox); + end + function subfxn_closeOptionsKey(src,event) + if event.Key=="return" + delete(emptyBox) + end + end + function subfxnAddDroppedFrames() % TODO: to make this proper, need to verify that the log file names match those of movie files display(repmat('-',1,7)); @@ -1252,8 +1423,8 @@ function downsampleSpaceInputMovie() if exist('turboRegCoords','var') % Adjust crop coordinates if downsampling in space takes place before turboreg disp(['Adjusting motion correction crop coordinates for spatial downsampling: ' num2str(turboRegCoords{fileNum}{movieNo})]); - orderCheck = find(strcmp(analysisOptionList,'downsampleSpace'))1 + % thisFrame = max(thisFrame,[],3); + thisFrame = squeeze(thisFrame(:,:,1)); + end + + [figHandle, figNo] = openFigure(9, ''); + titleStr = ['Click to drag-n-draw region.' 10 'Double-click region to continue.' 10 'Note: Only cropping for motion correction.' 10 'Original movie dimensions retained after registration.' 10 'Frame: ' num2str(frameToGrabHere)]; + subplot(1,2,1); + imagesc(thisFrame); + axis image; + colormap gray; + title(titleStr) + box off; set(0,'DefaultTextInterpreter','none'); % suptitle([num2str(fileNumIdx) '\' num2str(nFilesToRun) ': ' 10 strrep(thisDir,'\','/')],'fontSize',12,'plotregion',0.9,'titleypos',0.95); uicontrol('Style','Text','String',[num2str(fileNumIdx) '\' num2str(nFilesToRun) ': ' strrep(thisDir,'\','/')],'Units','normalized','Position',[0.1 0.9 0.8 0.10],'BackgroundColor','white','HorizontalAlignment','Center'); @@ -2168,7 +2354,8 @@ function fftLowpassInputMovie() for foobar=1:2; MIJ.run('Enhance Contrast','saturated=0.35'); end MIJ.run('Start Animation [\]'); uiwait(msgbox('press OK to move onto next movie','Success','modal')); - MIJ.run('Close All Without Saving'); + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); catch err disp(repmat('@',1,7)) disp(getReport(err,'extended','hyperlinks','on')); diff --git a/@ciatah/modelVarsFromFilesCheck.m b/@ciatah/modelVarsFromFilesCheck.m new file mode 100644 index 0000000..bb30f25 --- /dev/null +++ b/@ciatah/modelVarsFromFilesCheck.m @@ -0,0 +1,48 @@ +function obj = modelVarsFromFilesCheck(obj,folderNo,varargin) + % Checks whether a specific folder has variables loaded, if not loads them. + % Biafra Ahanonu + % started: 2021.06.18 [20:25:49] + % inputs + % + % outputs + % + + % changelog + % + % TODO + % + + + % ======================== + % DESCRIPTION + options.baseOption = ''; + % get options + options = getOptions(options,varargin); + % display(options) + % unpack options into current workspace + % fn=fieldnames(options); + % for i=1:length(fn) + % eval([fn{i} '=options.' fn{i} ';']); + % end + % ======================== + + try + try + [rawSignals rawImages signalPeaks signalPeaksArray, ~, ~, rawSignals2] = modelGetSignalsImages(obj,'returnType','raw'); + % obj.nSignals{fileNum} + skipReload = 1; + catch + obj.guiEnabled = 0; + % originalFileNum = + obj.modelVarsFromFiles(); + obj.fileNum = folderNo; + obj.guiEnabled = 1; + skipReload = 0; + end + catch err + display(repmat('@',1,7)) + disp(getReport(err,'extended','hyperlinks','on')); + display(repmat('@',1,7)) + end + +end \ No newline at end of file diff --git a/@ciatah/viewCellExtractionOnMovie.m b/@ciatah/viewCellExtractionOnMovie.m index 9664a32..6f24527 100644 --- a/@ciatah/viewCellExtractionOnMovie.m +++ b/@ciatah/viewCellExtractionOnMovie.m @@ -9,6 +9,7 @@ % changelog % 2019.10.29 [16:31:37] - Added a check for already loaded files + % 2021.06.18 [21:41:07] - added modelVarsFromFilesCheck() to check and load signals if user hasn't already. % TODO % Give users the option to scroll back and forth by having a horizontal scrollbar @@ -229,6 +230,8 @@ display(repmat('=',1,21)) display([num2str(thisFileNumIdx) '/' num2str(nFilesToAnalyze) ': ' obj.fileIDNameArray{obj.fileNum}]); + obj.modelVarsFromFilesCheck(fileNum); + if isempty(analyzeSpecificFolder) movieList = getFileList(obj.inputFolders{obj.fileNum}, fileFilterRegexp); else @@ -510,7 +513,9 @@ % 'yes','motion','other','yes'); movieDecision = 'yes'; % MIJ.run('Close'); - MIJ.run('Close All Without Saving'); + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); + manageMiji('startStop','exit'); % MIJ.exit; catch err disp(repmat('@',1,7)) diff --git a/@ciatah/viewCreateObjmaps.m b/@ciatah/viewCreateObjmaps.m index 0c72aa1..8ced981 100644 --- a/@ciatah/viewCreateObjmaps.m +++ b/@ciatah/viewCreateObjmaps.m @@ -10,6 +10,7 @@ % changelog % 2017.01.14 [20:06:04] - support switched from [nSignals x y] to [x y nSignals] % 2019.12.19 [21:18:12] - Allow user to brighten processed overlay movie. + % 2021.06.18 [21:41:07] - added modelVarsFromFilesCheck() to check and load signals if user hasn't already. % TODO % @@ -144,6 +145,9 @@ obj.fileNum = thisFileNum; display(repmat('=',1,21)) display([num2str(thisFileNum) '/' num2str(nFiles) ': ' obj.fileIDNameArray{obj.fileNum}]); + + % Check that signal extraction information is loaded. + obj.modelVarsFromFilesCheck(thisFileNum); % ===================== % for backwards compatibility, will be removed in the future. nIDs = length(obj.stimulusNameArray); diff --git a/@ciatah/viewMovie.m b/@ciatah/viewMovie.m index 7fd310a..5c3f7bc 100644 --- a/@ciatah/viewMovie.m +++ b/@ciatah/viewMovie.m @@ -12,6 +12,8 @@ % 2019.10.09 [17:58:22] - Make view movie multi-column % 2020.10.25 [21:05:21] - Added support for viewing movies from disk. % 2021.02.24 [09:04:24] - Fix treatMoviesAsContinuous=0 + playMovieFromDisk=1 issue. + % 2021.06.18 [21:41:07] - added modelVarsFromFilesCheck() to check and load signals if user hasn't already. + % 2021.06.20 [‏‎00:14:59] - Added support for simple and advanced settings. % TODO % % ===================== @@ -19,6 +21,7 @@ FRAMES_PER_SECOND = obj.FRAMES_PER_SECOND; % DOWNSAMPLE_FACTOR = obj.DOWNSAMPLE_FACTOR; options.videoPlayer = []; + options.settingsType = ''; % ===================== currentDateTimeStr = datestr(now,'yyyymmdd_HHMM','local'); if isempty(options.videoPlayer) @@ -31,6 +34,14 @@ modelAddOutsideDependencies('miji'); end + if isempty(options.settingsType) + usrIdxChoiceStr = {'Simple settings','Advanced settings'}; + usrIdxChoiceSetting = {'simple','advanced'}; + scnsize = get(0,'ScreenSize'); + [sel, ok] = listdlg('ListString',usrIdxChoiceStr,'ListSize',[scnsize(3)*0.2 scnsize(4)*0.25],'Name','Which settings to load?'); + options.settingsType = usrIdxChoiceSetting{sel}; + end + % Load folders to be analyzed. [fileIdxArray idNumIdxArray nFilesToAnalyze nFiles] = obj.getAnalysisSubsetsToAnalyze(); @@ -44,18 +55,19 @@ defaultFileFilterRegexp = obj.fileFilterRegexpRaw; end % ===================== - if iscell(obj.videoDir); + if iscell(obj.videoDir) videoDir = strjoin(obj.videoDir,','); else videoDir = obj.videoDir; - end; + end % ===================== AddOpts.Resize='on'; AddOpts.WindowStyle='normal'; AddOpts.Interpreter='tex'; - % movieSettings = inputdlg({... - movieSettings = inputdlgcol({... + options.settingsType + + settingStr = {... 'char: Imaging movie regexp (IMPORTANT, make sure matches the movie you want to view):',... 'start:end frames (leave blank for all)',... 'behavior:movie sample rate (downsample factor): ',... @@ -78,13 +90,12 @@ 'video regular expression:',... 'rotate second video (0 = no, 1 = yes)',... 'treat movie as continuous (0 = no, 1 = yes):',... - 'dataset name',... + 'HDF5 dataset name',... 'downsample factor for movie viewing (1 = no downsample):',... 'Create cell extraction outlines on movie (0 = no, 1 = yes, 2 = yes, all outputs):',... 'Cell extraction outlines threshold (float btwn 0 and 1):',... - },... - 'view movie settings',[1 100],... - {... + }; + settingDefaults = {... defaultFileFilterRegexp,... '1:500',... num2str(obj.DOWNSAMPLE_FACTOR),... @@ -111,7 +122,37 @@ '1',... '0',... '0.4',... - },AddOpts,2); + }; + + switch options.settingsType + case 'simple' + settingsKeepIdx = [1 2 3 13 17 23]; + nCols = 1; + otherwise + settingsKeepIdx = 1:length(settingStr); + nCols = 2; + % Do nothing + end + + % movieSettings = inputdlg({... + movieSettings = inputdlgcol(settingStr(settingsKeepIdx),... + 'view movie settings',[1 100],... + settingDefaults(settingsKeepIdx),... + AddOpts,nCols); + + switch options.settingsType + case 'simple' + % Add new settings to default + settingStr{settingsKeepIdx}; + sN = 1; + for ii = 1:length(settingsKeepIdx) + settingDefaults{settingsKeepIdx(ii)} = movieSettings{sN}; + sN=sN+1; + end + movieSettings = settingDefaults; + otherwise + % Do nothing + end % concat the two % movieSettings = cat(1,movieSettings,movieSettings2); @@ -665,7 +706,8 @@ 'Movie decision', ... 'yes','motion','other','yes'); % MIJ.run('Close'); - MIJ.run('Close All Without Saving'); + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); % MIJ.exit; catch err disp(repmat('@',1,7)) diff --git a/@ciatah/viewMovieRegistrationTest.m b/@ciatah/viewMovieRegistrationTest.m index 6c30d28..34a96ec 100644 --- a/@ciatah/viewMovieRegistrationTest.m +++ b/@ciatah/viewMovieRegistrationTest.m @@ -250,7 +250,8 @@ else uiwait(msgbox('Press OK to move onto next movie','Success','modal')); end - MIJ.run('Close All Without Saving'); + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); catch err disp(repmat('@',1,7)) disp(getReport(err,'extended','hyperlinks','on')); diff --git a/@ciatah/viewObjmaps.m b/@ciatah/viewObjmaps.m index 8113670..f5c3612 100644 --- a/@ciatah/viewObjmaps.m +++ b/@ciatah/viewObjmaps.m @@ -10,6 +10,7 @@ % changelog % 2017.01.14 [20:06:04] - support switched from [nSignals x y] to [x y nSignals] % 2020.05.07 [14:54:27] - Fix to deal with empty valid folders. + % 2021.06.18 [21:41:07] - added modelVarsFromFilesCheck() to check and load signals if user hasn't already. % TODO % @@ -144,6 +145,10 @@ [~,foldername,~] = fileparts(obj.inputFolders{obj.fileNum}); validType = 'NULL'; linkAx = []; + + % Check that signal extraction information is loaded. + obj.modelVarsFromFilesCheck(thisFileNum); + % ===================== % for backwards compatibility, will be removed in the future. nIDs = length(obj.stimulusNameArray); diff --git a/@ciatah/viewSubjectMovieFrames.m b/@ciatah/viewSubjectMovieFrames.m index 32738bb..db872b5 100644 --- a/@ciatah/viewSubjectMovieFrames.m +++ b/@ciatah/viewSubjectMovieFrames.m @@ -9,7 +9,7 @@ % % changelog - % + % 2021.06.18 [21:41:07] - added modelVarsFromFilesCheck() to check and load signals if user hasn't already. % TODO % @@ -80,7 +80,8 @@ % pause end uiwait(msgbox('press OK to finish','Success','modal')); - MIJ.run('Close All Without Saving'); + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); case 2 [fileIdxArray idNumIdxArray nFilesToAnalyze nFiles] = obj.getAnalysisSubsetsToAnalyze(); for thisFileNumIdx = 1:nFilesToAnalyze @@ -125,8 +126,8 @@ % pause end uiwait(msgbox('press OK to finish','Success','modal')); - MIJ.run('Close All Without Saving'); - + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); case 3 [fileIdxArray idNumIdxArray nFilesToAnalyze nFiles] = obj.getAnalysisSubsetsToAnalyze(); movieListAll = {}; @@ -157,7 +158,8 @@ MIJ.createImage('Montage', primaryMovie, true); % for foobar=1:3; MIJ.run('In [+]'); end uiwait(msgbox('press OK to finish','Success','modal')); - MIJ.run('Close All Without Saving'); + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); case 4 [fileIdxArray idNumIdxArray nFilesToAnalyze nFiles] = obj.getAnalysisSubsetsToAnalyze(); for thisSubjectStr = subjectList @@ -175,6 +177,10 @@ display('===') thisFileNum = validFoldersIdx(folderNo); obj.fileNum = thisFileNum; + + % Check that signal extraction information is loaded. + obj.modelVarsFromFilesCheck(thisFileNum); + [inputSignals inputImages signalPeaks signalPeakIdx valid] = modelGetSignalsImages(obj,'returnType','raw'); if isempty(inputSignals);display('no input signals');continue;end @@ -243,7 +249,8 @@ end end uiwait(msgbox('press OK to finish','Success','modal')); - MIJ.run('Close All Without Saving'); + % MIJ.run('Close All Without Saving'); + manageMiji('startStop','closeAllWindows'); otherwise % body end diff --git a/README.md b/README.md index d22f1f3..6b619d5 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,13 @@ ## Full documentation at https://bahanonu.github.io/ciatah/. +Below are recordings for users who want to learn more about calcium imaging analysis and the CIAtah pipeline. + +### Webinar +This webinar gives an overview of calcium imaging analysis (with a focus on CIAtah) along with tips for improving experiments and analysis: https://info.inscopix.com/inscopix-inspire-view-webinarbiafra-ahanonu-signal-in-the-noise-distinguishing-relevant-neural-activity-in-calcium-imaging. + +### Workshop tutorial +This recording gives an overview of setting up and using CIAtah: https://www.youtube.com/watch?v=I6abW3uuJJw. @@ -52,12 +59,12 @@ Made in USA.
- pre-processing (motion correction, spatiotemporal downsampling, spatial filtering, relative fluorescence calculation, etc.) - support for multiple cell-extraction methods (CELLMax, PCA-ICA, CNMF, CNMF-E, EXTRACT, etc.) - manual classification of cells via GUIs, - - automated cell classification (coming soon!), + - automated cell classification (i.e. CLEAN algorithm, coming soon!), - cross-session cell alignment, and more. - Includes example one- and two-photon calcium imaging datasets for testing `ciatah`. -- Animal position tracking (e.g. in open-field assay). -- Supports most major imaging movie file formats: HDF5, NWB, AVI, ISXD [Inscopix], and TIFF. +- Supports a plethora of major imaging movie file formats: HDF5, NWB, AVI, ISXD [Inscopix], TIFF, and [Bio-Formats](https://www.openmicroscopy.org/bio-formats/) compatible formats (Olympus [OIR] and Zeiss [CZI and LSM] currently, additional support to be added or upon request). - Supports [Neurodata Without Borders](https://www.nwb.org/) data standard (see [calcium imaging tutorial](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html)) for reading/writing cell-extraction and imaging movie files. +- Animal position tracking (e.g. in open-field assay). - Requires `MATLAB`. @@ -114,7 +121,7 @@ Made in USA.
Below are steps needed to quickly get started using the `CIAtah` software package in MATLAB. -### Install +### Download and install `CIAtah` - Clone the `CIAtah` repository (using [GitHub desktop](https://desktop.github.com/) or command line) or download the repository zip and unzip (e.g. run below MATLAB command). - Point the MATLAB path to the `CIAtah` root folder (*NOT* `@CIAtah` sub-folder in the repository). @@ -132,6 +139,14 @@ Below are steps needed to quickly get started using the `CIAtah` software packag cd('ciatah-master') ``` +### Check required toolboxes are installed + +`CIAtah` depends on several MATLAB toolboxes to run properly. Run the below command to have `CIAtah` check whether dependencies have been installed properly. If not use the `Add-Ons` (https://www.mathworks.com/help/matlab/matlab_env/get-add-ons.html) explorer to install each toolbox. + +```Matlab +ciapkg.io.matlabToolboxCheck;` +``` + ### Setup `CIAtah` - Run `CIAtah` using the below MATLAB commands. Call `obj;` in the MATLAB command window each time you want to go back to the main GUI. __Note: `calciumImagingAnalysis` class is now called `ciatah`, all functionality is the same.__ @@ -151,6 +166,7 @@ obj % then hit enter, no semicolon! - Run `obj;` in the command window to see the main GUI. - Full documentation at https://bahanonu.github.io/ciatah/. - __[Optional]__ Users on Windows systems can download `Everything` (https://www.voidtools.com/). It is a very useful and extremely fast search engine for files and folders that allows users to quickly obtain lists of full folder paths for analysis in `CIAtah`. +- __[Optional]__ If run into issues opening certain AVI files (e.g. due to codec issues) with CIAtah/MATLAB, install `K-Lite Codec Pack` (https://codecguide.com/download_kl.htm) or similar for added support. ### Visualize movies quickly using read from disk diff --git a/ciapkg/classification/signalSorter.m b/ciapkg/classification/signalSorter.m index 7b5fb16..74ea6af 100644 --- a/ciapkg/classification/signalSorter.m +++ b/ciapkg/classification/signalSorter.m @@ -71,6 +71,7 @@ % 2020.10.13 [01:22:47] - Display context menu for keyboard shortcuts, easier than separate figure. User can select with right-click or via a menu in the GUI. % 2020.10.13 [22:31:23] - Users can now scroll through cells using mouse scroll wheel. % 2021.03.10 [16:33:23] - User can now input just NWB path without a blank variable for inputSignals. Also added support for CIAtah mat files. + % 2021.05.09 [15:20:18] - Since ciapkg.io.loadSignalExtraction already supports loading NWB or CIAtah MAT-file cell extraction files, remove remove redundancy and only call ciapkg.io.loadSignalExtraction rather than loadNeurodataWithoutBorders. Added support for progress bar when movie not input. % TODO % DONE: New GUI interface to allow users to scroll through video and see cell activity at that point % DONE: allow option to mark rest as bad signals @@ -244,17 +245,8 @@ % If inputs are NWB or CIAtah mat format if nargin==1|ischar(inputImages) - [~,~,inputEXT] = fileparts(inputImages); - switch inputEXT - case '.nwb' - [inputImages,inputSignals,infoStruct,algorithmStr] = loadNeurodataWithoutBorders(inputImages); - options.nSignals = size(inputImages,3); - case '.mat' - [inputImages,inputSignals,infoStruct,algorithmStr] = ciapkg.io.loadSignalExtraction(inputImages); - options.nSignals = size(inputImages,3); - otherwise - - end + [inputImages,inputSignals,infoStruct,algorithmStr] = ciapkg.io.loadSignalExtraction(inputImages); + options.nSignals = size(inputImages,3); end % Modify dataset name if given NWB file @@ -396,6 +388,7 @@ options.movieMin = 0; end + % ===================== % Set all starting values to neutral (e.g. gray in GUI, to reduce bias). if strcmp(valid,'neutralStart')==1 valid = zeros([options.nSignals 1],'logical')+3; @@ -797,6 +790,9 @@ function plotSignalStatistics(inputSignals,inputImageSizes,inputStr,pointColor, % loop over chosen filters nImages = size(inputImages,3); + axValid = []; + axValidAll = []; + % initialize loop variables saveData=0; i = 1; % the current signal # being sorted @@ -1022,8 +1018,10 @@ function plotSignalStatistics(inputSignals,inputImageSizes,inputStr,pointColor, axis equal tight; end s2Pos = plotboxpos(inputMoviePlotLoc2Handle); - cbh = colorbar(inputMoviePlotLoc2Handle,'Location','eastoutside','Position',[s2Pos(1)+s2Pos(3)+0.005 s2Pos(2) 0.01 s2Pos(4)],'FontSize',options.fontSize-2); - ylabel(cbh,'Fluorescence (e.g. \DeltaF/F or \DeltaF/\sigma)','FontSize',options.fontSize-1); + if loopCount==1 + cbh = colorbar(inputMoviePlotLoc2Handle,'Location','eastoutside','Position',[s2Pos(1)+s2Pos(3)+0.005 s2Pos(2) 0.01 s2Pos(4)],'FontSize',options.fontSize-2); + ylabel(cbh,'Fluorescence (e.g. \DeltaF/F or \DeltaF/\sigma)','FontSize',options.fontSize-1); + end end catch err @@ -1056,11 +1054,12 @@ function plotSignalStatistics(inputSignals,inputImageSizes,inputStr,pointColor, else set(mainFig,'CurrentAxes',inputMoviePlotLoc2Handle); end - [thisImageCrop] = subfxnCropImages(thisImage); - imagesc(thisImageCrop); - % colormap gray - axis off; % ij square - title(['signal ' cellIDStr 10 '(' num2str(sum(valid==1)) ' good)'],'FontSize',options.fontSize,'Interpreter','tex'); + + [thisImageCrop] = subfxnCropImages(thisImage); + imagesc(thisImageCrop); + % colormap gray + axis off; % ij square + title(['signal ' cellIDStr 10 '(' num2str(sum(valid==1)) ' good)'],'FontSize',options.fontSize,'Interpreter','tex'); end % use thresholded image as AlphaData to overlay on cell map, reduce number of times this is accessed to speed-up analysis @@ -1368,6 +1367,7 @@ function plotSignalStatistics(inputSignals,inputImageSizes,inputStr,pointColor, set(gcf,'pointer','custom','PointerShapeCData',NaN([16 16])); end + % Display options if movie present if ~isempty(options.inputMovie) try if options.peakTrigMovieMontage==0 @@ -1513,14 +1513,6 @@ function plotSignalStatistics(inputSignals,inputImageSizes,inputStr,pointColor, title(['Press Q to change movie contrast.' 10 'Press Z to turn zoom on.' 10 'Press B to switch to movie montage.' 10 'Zoom enabled in trace panel.'],'FontSize',options.fontSize,'Interpreter','tex') end - % ========================================== - % ADD PROGRESS BAR - if exist('axValid','var')==1 - [axValid axValidAll] = subfxnSignalSorterProgressBars(i,valid,inputMoviePlotLocHandle,inputMoviePlotLoc2Handle,options,mainFig,axValid,axValidAll,cellIDStr); - else - [axValid axValidAll] = subfxnSignalSorterProgressBars(i,valid,inputMoviePlotLocHandle,inputMoviePlotLoc2Handle,options,mainFig,[],[],cellIDStr); - end - set(mainFig,'CurrentAxes',inputMoviePlotLocHandle); frameNoTotal = 0; % use this to lock @@ -1541,6 +1533,9 @@ function plotSignalStatistics(inputSignals,inputImageSizes,inputStr,pointColor, set(objMapZoomPlotLocHandle,'ButtonDownFcn',@subfxnSelectCellOnCellmap) set(mainFig, 'KeyPressFcn', @(source,eventdata) figure(mainFig)); + % Create progress bar + [axValid, axValidAll] = subfxn_progressBarCreate(axValid, axValidAll); + while strcmp(keyIn,'3') frameNoTotal = frameNoTotal+1; if frameNoTotal>3 @@ -1576,9 +1571,17 @@ function plotSignalStatistics(inputSignals,inputImageSizes,inputStr,pointColor, end else keyIn = get(gcf,'CurrentCharacter'); + % Create progress bar + [axValid, axValidAll] = subfxn_progressBarCreate(axValid, axValidAll); + + while strcmp(keyIn,'3') + keyIn = get(gcf,'CurrentCharacter'); + pause(1/options.fps); + end reply = double(keyIn); set(gcf,'currentch','3'); end + figure(mainFig); warning('on','all') @@ -1609,7 +1612,7 @@ function plotSignalStatistics(inputSignals,inputImageSizes,inputStr,pointColor, end end % loop if user gets to either end - i=i+directionOfNextChoice; + i = i+directionOfNextChoice; if i<=0; i = nImages; end if i>nImages; i = 1; end figure(mainFig); @@ -1629,6 +1632,26 @@ function plotSignalStatistics(inputSignals,inputImageSizes,inputStr,pointColor, warning('on','all') warning('query','all') safeExit = 1; + + function [axValid, axValidAll] = subfxn_progressBarCreate(axValid, axValidAll) + % ========================================== + % ADD PROGRESS BAR + if isempty(options.inputMovie) + tmpHandleProgressBar = avgSpikeTracePlotHandle; + tmpHandleProgressBar2 = inputMoviePlotLoc2Handle; + else + tmpHandleProgressBar = inputMoviePlotLocHandle; + tmpHandleProgressBar2 = inputMoviePlotLoc2Handle; + end + if isempty(axValid)==1 + % if exist('axValid','var')==0 + % if i==1&loopCount==1 + disp('Creating sorter progress bar...') + [axValid, axValidAll] = subfxnSignalSorterProgressBars(i,valid,tmpHandleProgressBar,tmpHandleProgressBar2,options,mainFig,[],[],cellIDStr); + else + [axValid, axValidAll] = subfxnSignalSorterProgressBars(i,valid,tmpHandleProgressBar,tmpHandleProgressBar2,options,mainFig,axValid,axValidAll,cellIDStr); + end + end function subfxnUserInputGui(replyTmp) if nargin>0 % Change keyIn to force while loop to exit, need for certain commands. @@ -2184,7 +2207,7 @@ function movieCallback(source,eventdata) end end end -function [axValid axValidAll] = subfxnSignalSorterProgressBars(i,valid,inputMoviePlotLocHandle,inputMoviePlotLoc2Handle,options,mainFig,axValid,axValidAll,cellIDStr) +function [axValid, axValidAll] = subfxnSignalSorterProgressBars(i,valid,inputMoviePlotLocHandle,inputMoviePlotLoc2Handle,options,mainFig,axValid,axValidAll,cellIDStr) validData = cat(3,... double(valid(:)'==0|valid(:)'>1),...% Red double(valid(:)'==1|valid(:)'>1),...% Green @@ -2206,6 +2229,7 @@ function movieCallback(source,eventdata) cbh = colorbar(inputMoviePlotLoc2Handle,'Location','eastoutside','Position',[s2Pos(1)+s2Pos(3)+0.005 s2Pos(2) 0.01 s2Pos(4)],'FontSize',options.fontSize-2); ylabel(cbh,'Fluorescence (e.g. \DeltaF/F or \DeltaF/\sigma)','FontSize',options.fontSize-1); + set(mainFig,'CurrentAxes',inputMoviePlotLocHandle); s3Pos = plotboxpos(gca); axValid = axes('Position',[s3Pos(1) 0.98 s3Pos(3) 0.02],'XTick',[],'YTick',[]); diff --git a/ciapkg/download/downloadGithubRepositories.m b/ciapkg/download/downloadGithubRepositories.m index 6c18ca0..a79de9c 100644 --- a/ciapkg/download/downloadGithubRepositories.m +++ b/ciapkg/download/downloadGithubRepositories.m @@ -104,7 +104,13 @@ % Rename to proper folder for calciumImagingAnalysis fprintf('Renaming %s to %s \n',[signalExtractionDir filesep gitName{gitNo}],[signalExtractionDir filesep outputDir{gitNo}]) - movefile([signalExtractionDir filesep gitName{gitNo}],[signalExtractionDir filesep outputDir{gitNo}]); + oldDir = [signalExtractionDir filesep gitName{gitNo}]; + newDir = [signalExtractionDir filesep outputDir{gitNo}]; + if strcmp(oldDir,newDir)==1 + disp('Same directory, ignore name change!') + else + movefile(oldDir,newDir); + end % fprintf('\n\n') end diff --git a/ciapkg/image/cropMatrix.m b/ciapkg/image/cropMatrix.m index d4165fe..0fd96c3 100644 --- a/ciapkg/image/cropMatrix.m +++ b/ciapkg/image/cropMatrix.m @@ -1,4 +1,4 @@ -function [inputMatrix] = cropMatrix(inputMatrix,varargin) +function [inputMatrix, coords] = cropMatrix(inputMatrix,varargin) % Crops a matrix either by removing rows or adding NaNs to where data was previously. % Biafra Ahanonu % 2014.01.23 [16:06:01] @@ -7,7 +7,8 @@ % outputs % inputMatrix - cropped or NaN'd matrix, same name to reduce memory usage % changelog - % 2017.01.14 [20:06:04] - support switched from [nSignals x y] to [x y nSignals] + % 2017.01.14 [20:06:04] - support switched from [nSignals x y] to [x y nSignals]. + % 2021.04.18 [14:42:53] - Updated to make imrect the default method of selecting the coordinates % TODO % @@ -43,11 +44,20 @@ elseif isempty(options.inputCoords) %figure(102020); colormap gray; thisFrame = squeeze(inputMatrix(:,:,round(end/2))); - [coords] = getCropCoords(thisFrame) + % [coords] = getCropCoords(thisFrame) + + h = subfxn_getImRect(thisFrame,'Select a region'); + p = round(wait(h)); + + % Get the x and y corner coordinates as integers + coords(1) = p(1); %xmin + coords(2) = p(2); %ymin + coords(3) = p(1)+p(3); %xmax + coords(4) = p(2)+p(4); %ymax else coords = options.inputCoords; end - display('cropping matrix...'); + disp('cropping matrix...'); switch options.cropOrNaN case 'NaN' rowLen = size(inputMatrix,1); @@ -75,7 +85,8 @@ imagesc(thisFrame); axis image; colormap parula; - title('select region') + title('Select a region. Double click region to continue.') + box off; % Use ginput to select corner points of a rectangular % region by pointing and clicking the subject twice @@ -92,4 +103,19 @@ % Display the subsetted image with appropriate axis ratio figure(9);subplot(1,2,2);imagesc(thisFrameCropped); axis image; colormap gray; title('cropped region');drawnow; +end +function h = subfxn_getImRect(thisFrame,titleStr) + % close(142568) + figure(9); + clf + subplot(1,2,1); + imagesc(thisFrame); + axis image; + % colormap parula; + title('select region') + + h = imrect(gca); + addNewPositionCallback(h,@(p) title([titleStr 10 mat2str(p,3)])); + fcn = makeConstrainToRectFcn('imrect',get(gca,'XLim'),get(gca,'YLim')); + setPositionConstraintFcn(h,fcn); end \ No newline at end of file diff --git a/ciapkg/image/filterImages.m b/ciapkg/image/filterImages.m index a4a6c48..146cc33 100644 --- a/ciapkg/image/filterImages.m +++ b/ciapkg/image/filterImages.m @@ -161,21 +161,27 @@ display('done!'); if options.makePlots==1 - [figHandle figNo] = openFigure(99, ''); - % - subplot(2,1,1) - hist(imageSizes,round(logspace(0,log10(max(imageSizes))))); - box off;title('distribution of IC sizes');xlabel('area (px^2)');ylabel('count'); - set(gca,'xscale','log'); - h = findobj(gca,'Type','patch'); - set(h,'FaceColor',[0 0 0],'EdgeColor','w'); - % - subplot(2,1,2) - hist(find(valid==0),round(logspace(0,log10(max(find(valid==0)))))); - box off;title('rank of removed ICs');xlabel('rank');ylabel('count'); - set(gca,'xscale','log') - h = findobj(gca,'Type','patch'); - set(h,'FaceColor',[0 0 0],'EdgeColor','w'); + try + [figHandle figNo] = openFigure(99, ''); + % + subplot(2,1,1) + hist(imageSizes,round(logspace(0,log10(max(imageSizes))))); + box off;title('distribution of IC sizes');xlabel('area (px^2)');ylabel('count'); + set(gca,'xscale','log'); + h = findobj(gca,'Type','patch'); + set(h,'FaceColor',[0 0 0],'EdgeColor','w'); + % + subplot(2,1,2) + hist(find(valid==0),round(logspace(0,log10(max(find(valid==0)))))); + box off;title('rank of removed ICs');xlabel('rank');ylabel('count'); + set(gca,'xscale','log') + h = findobj(gca,'Type','patch'); + set(h,'FaceColor',[0 0 0],'EdgeColor','w'); + catch err + disp(repmat('@',1,7)) + disp(getReport(err,'extended','hyperlinks','on')); + disp(repmat('@',1,7)) + end end end % for i = 1:nImages diff --git a/ciapkg/io/loadMovieList.m b/ciapkg/io/loadMovieList.m index fed47c0..116898a 100644 --- a/ciapkg/io/loadMovieList.m +++ b/ciapkg/io/loadMovieList.m @@ -50,9 +50,12 @@ % 2020.08.31 [15:47:49] - Add option to suppress warnings. % 2020.10.19 [12:11:14] - Improved comments and options descriptions. % 2021.02.15 [11:55:36] - Fixed loading HDF5 datasetname that has only a single frame, loadMovieList would ask for 3rd dimension information that did not exist. + % 2021.06.21 [10:22:32] - Added support for Bio-Formats compatible files, specifically Olympus (OIR) and Zeiss () % TODO % OPEN + % Bio-Formats + % Allow outputting as a [x y c t] matrix to allow support for multiple color channels without needing to re-read file multiple times. % Determine file type by properties of file instead of extension (don't trust input...) % Remove all use of tmpMovie.... % Add ability to degrade gracefully with HDF5 dataset names, so try several backup datasetnames if one doesn't work. @@ -65,7 +68,12 @@ % ======================== % Cell array of str: list of supported file types, in general DO NOT change. - options.supportedTypes = {'.h5','.hdf5','.nwb','.tif','.tiff','.avi','.isxd'}; + options.supportedTypes = {'.h5','.hdf5','.tif','.tiff','.avi',... + '.nwb',... % Neurodata Without Borders format + '.isxd',... % Inscopix format + '.oir',... % Olympus formats + '.czi','.lsm'... % Zeiss formats + }; % Str: movie type. options.movieType = 'tiff'; % Str: hierarchy name in HDF5 file where movie data is located. @@ -106,8 +114,12 @@ options.useH5info = 1; % Int: [] = do nothing, 1-3 indicates R,G,B channels to take from multicolor RGB AVI options.rgbChannel = []; + % Int: Bio-Formats series number to load. + options.bfSeriesNo = 1; + % Int: Bio-Formats channel number to load. + options.bfChannelNo = 1; % get options - options = getOptions(options,varargin); + options = ciapkg.io.getOptions(options,varargin); % unpack options into current workspace % fn=fieldnames(options); % for i=1:length(fn) @@ -302,6 +314,22 @@ dims.two(iMovie) = xyDims(2); dims.three(iMovie) = nFrames; tmpFrame = inputMovieIsx.get_frame_data(0); + case 'bioformats' + bfreaderTmp = bfGetReader(thisMoviePath); + omeMeta = bfreaderTmp.getMetadataStore(); + stackSizeX = omeMeta.getPixelsSizeX(0).getValue(); % image width, pixels + stackSizeY = omeMeta.getPixelsSizeY(0).getValue(); % image height, pixels + stackSizeZ = omeMeta.getPixelsSizeZ(0).getValue(); + nFrames = stackSizeZ; + xyDims = [stackSizeY stackSizeX]; + dims.x(iMovie) = xyDims(1); + dims.y(iMovie) = xyDims(2); + dims.z(iMovie) = nFrames; + dims.one(iMovie) = xyDims(1); + dims.two(iMovie) = xyDims(2); + dims.three(iMovie) = nFrames; + tmpFrame = bfGetPlane(bfreaderTmp, 1); + nChannels = omeMeta.getChannelCount(0); end if isempty(options.loadSpecificImgClass) imgClass = class(tmpFrame); @@ -684,6 +712,67 @@ iframe = iframe + 1; end % ======================== + case 'bioformats' + % Setup movie class + bfreaderTmp = bfGetReader(thisMoviePath); + omeMeta = bfreaderTmp.getMetadataStore(); + stackSizeX = omeMeta.getPixelsSizeX(0).getValue(); % image width, pixels + stackSizeY = omeMeta.getPixelsSizeY(0).getValue(); % image height, pixels + stackSizeZ = omeMeta.getPixelsSizeZ(0).getValue(); + nChannels = omeMeta.getChannelCount(0); + + nFramesHere = stackSizeZ; + xyDims = [stackSizeX stackSizeY]; + + if isempty(thisFrameList) + nFrames = nFramesHere; + framesToGrab = 1:nFrames; + else + nFrames = length(thisFrameList); + framesToGrab = thisFrameList; + end + vidHeight = xyDims(1); + vidWidth = xyDims(2); + + % Preallocate movie structure. + tmpMovie = zeros(vidHeight, vidWidth, nFrames, imgClass); + + % Read one frame at a time. + reverseStr = ''; + iframe = 1; + nFrames = length(framesToGrab); + + % Read in movie data + tmpMovie = bfopen(thisMoviePath); + + % bfopen returns an n-by-4 cell array, where n is the number of series in the dataset. If s is the series index between 1 and n: + % The data{s, 1} element is an m-by-2 cell array, where m is the number of planes in the s-th series. If t is the plane index between 1 and m: + % The data{s, 1}{t, 1} element contains the pixel data for the t-th plane in the s-th series. + % The data{s, 1}{t, 2} element contains the label for the t-th plane in the s-th series. + % The data{s, 2} element contains original metadata key/value pairs that apply to the s-th series. + % The data{s, 3} element contains color lookup tables for each plane in the s-th series. + % The data{s, 4} element contains a standardized OME metadata structure, which is the same regardless of the input file format, and contains common metadata values such as physical pixel sizes - see OME metadata below for examples. + + % Frame information + frameInfo = tmpMovie{options.bfSeriesNo, 1}(:,2); + + % Grab just the movie frames and convert from cell to matrix. + tmpMovie = tmpMovie{options.bfSeriesNo, 1}(:,1); + tmpMovie = cat(3,tmpMovie{:}); + + % Only keep single channel if more than 1 channel in an image. + if nChannels>1 + try + chanKeepIdx = cell2mat(cellfun(@(x) str2num(cell2mat(regexp(x,'(?<=C\?=|C=)\d+(?=/)','match'))),frameInfo,'UniformOutput',false)); + chanKeepIdx = chanKeepIdx==options.bfChannelNo; + tmpMovie = tmpMovie(:,:,chanKeepIdx); + catch err + disp(repmat('@',1,7)) + disp(getReport(err,'extended','hyperlinks','on')); + disp(repmat('@',1,7)) + end + end + % ======================== otherwise % let's just not deal with this for now return; @@ -840,16 +929,20 @@ return; end % files are assumed to be named correctly (lying does no one any good) - if strcmp(ext,'.h5')||strcmp(ext,'.hdf5') + if any(strcmp(ext,{'.h5','.hdf5'})) movieType = 'hdf5'; elseif strcmp(ext,'.nwb') movieType = 'hdf5'; - elseif strcmp(ext,'.tif')||strcmp(ext,'.tiff') + elseif any(strcmp(ext,{'.tif','.tiff'})) movieType = 'tiff'; elseif strcmp(ext,'.avi') movieType = 'avi'; - elseif strcmp(ext,'.isxd') + elseif strcmp(ext,'.isxd') % Inscopix file format movieType = 'isxd'; + elseif strcmp(ext,'.oir') % Olympus file format + movieType = 'bioformats'; + elseif any(strcmp(ext,{'.czi','.lsm'})) % Zeiss file format + movieType = 'bioformats'; else movieType = ''; supported = 0; diff --git a/ciapkg/io/manageMiji.m b/ciapkg/io/manageMiji.m index 7e6a843..726d5d6 100644 --- a/ciapkg/io/manageMiji.m +++ b/ciapkg/io/manageMiji.m @@ -8,7 +8,7 @@ function manageMiji(varargin) % % changelog - % + % 2021.06.20 [00:20:38] - Add support for setting up ImageJ along with closing all windows to future proof any changes to those calls. % TODO % @@ -33,7 +33,7 @@ function manageMiji(varargin) % If MIJ class not loaded, load Miji.m. if exist('MIJ','class')~=8 % Load Miji so paths added to javaclasspath('-dynamic') - currP=pwd; + currP = pwd; % Miji; Miji(false); cd(currP); @@ -60,8 +60,11 @@ function manageMiji(varargin) end % If Miji.m not in path, ask user - if exist('Miji.m','file')~=2 - modelAddOutsideDependencies('miji'); + if exist('MIJ','class')~=8 + else + if exist('Miji.m','file')~=2 + modelAddOutsideDependencies('miji'); + end end % First attempt to open Miji @@ -85,6 +88,37 @@ function manageMiji(varargin) disp(repmat('@',1,7)) end end + case 'setupImageJ' + % Sets up ImageJ by pointing Java path to the jar files. + + imagejPath = [ciapkg.getDirExternalPrograms filesep 'imagej']; + pathsToAdd = {[imagejPath filesep 'mij.jar'],[imagejPath filesep 'ij.jar']}; + nPaths = length(pathsToAdd); + for i = 1:nPaths + thisPath = pathsToAdd{i}; + disp('Loading MIJI + ImageJ.') + fprintf('Adding to Java path: %s\n',thisPath); + javaaddpath(thisPath); + end + case 'closeAllWindows' + % Closes all open windows but leaves ImageJ running. + + % MIJ.run('Close All Without Saving'); + % MIJ.closeAllWindows; + allClosedFlag = 0 + nImagesToBreak = 20; + imageNo = 1 + while allClosedFlag==0 + try + MIJ.getListImages + MIJ.run('Close') + catch + allClosedFlag = 1; + end + imageNo = imageNo + 1; + end + MIJ.closeAllWindows; + % MIJ.exit; case 'exit' try MIJ.exit; diff --git a/ciapkg/io/modelAddOutsideDependencies.m b/ciapkg/io/modelAddOutsideDependencies.m index e67cea7..f3a5bc7 100644 --- a/ciapkg/io/modelAddOutsideDependencies.m +++ b/ciapkg/io/modelAddOutsideDependencies.m @@ -9,7 +9,8 @@ % changelog % 2019.10.15 [12:29:30] - Added flag to prevent recursive loop between resetMiji and modelAddOutsideDependencies. - % 2021.02.01 [‏‎15:19:40] - Update `_external_programs` to call ciapkg.getDirExternalPrograms() to standardize call across all functions. + % 2021.02.01 [??‎15:19:40] - Update `_external_programs` to call ciapkg.getDirExternalPrograms() to standardize call across all functions. + % 2021.06.20 [00:20:12] - Updated to add support for ImageJ call instead of Fiji. % TODO % @@ -31,6 +32,17 @@ success = 0; switch dependencyName case 'miji' + if exist('MIJ','class')==8 + disp('Miji loaded!') + return; + else + manageMiji('startStop','setupImageJ'); + if exist('MIJ','class')==8 + disp('Miji loaded!') + return; + end + end + if exist('Miji.m','file')==2 display(['Miji located in: ' which('Miji.m')]); % Miji is loaded, continue @@ -61,7 +73,7 @@ if exist('pathToMiji','var')==0 if exist(options.defaultExternalProgramDir,'dir')==7 loadPathHere = options.defaultExternalProgramDir; - loadStr = ['Enter path to Miji.m in Fiji (likely in "scripts" folder, e.g. calciumImagingAnalysis\' options.defaultExternalProgramDir '\Fiji.app\scripts)']; + loadStr = ['Enter path to Miji.m in Fiji (likely in "scripts" folder, e.g. ' filesep ciapkg.pkgName options.defaultExternalProgramDir '\Fiji.app\scripts)']; else loadPathHere = '\.'; loadStr = ['Enter path to Miji.m in Fiji (likely in "scripts" folder, e.g. \Fiji.app\scripts)']; diff --git a/ciapkg/io/saveMatrixToFile.m b/ciapkg/io/saveMatrixToFile.m index 07d1644..63e329a 100644 --- a/ciapkg/io/saveMatrixToFile.m +++ b/ciapkg/io/saveMatrixToFile.m @@ -9,7 +9,7 @@ % % changelog - % + % 2021.04.24 [16:00:01] - updated TIFF saving to add support for export of multi-channel color timeseries TIFF stack if in format [x y C t] where x,y = width/height, C = RGB channels, t = frames % TODO % Add checking of data size so tiff can be automatically switched @@ -82,6 +82,10 @@ case 'tiff' tiffOptions.comp = 'no'; tiffOptions.overwrite = true; + if length(size(inputMatrix))==4 + tiffOptions.color = true; + disp('Saving TIFF as color timeseries stack.'); + end fprintf('Saving to: %s\n',savePath); saveastiff(inputMatrix, savePath, tiffOptions); case 'hdf5' diff --git a/ciapkg/motion_correction/computeManualMotionCorrection.m b/ciapkg/motion_correction/computeManualMotionCorrection.m index 17dd694..76794b3 100644 --- a/ciapkg/motion_correction/computeManualMotionCorrection.m +++ b/ciapkg/motion_correction/computeManualMotionCorrection.m @@ -15,7 +15,9 @@ % changelog % 2020.04.07 [19:39:24] - Updated to allow just using the register aspect of the function. Also made registering callback based. % 2020.04.08 [10:35:49] - Added support for rotation. - % 2020.05.28 [08:48:57] - Slight update + % 2020.05.28 [08:48:57] - Slight update. + % 2021.04.16 [10:31:29] - Add default gamma option. + % 2021.04.27 [16:26:14] - Update to fix issue of prior figure (even after clf) maintaining previous key press and exiting, causing uiwait to fail. % TODO % Add ability to auto-crop if inputs are not of the right size them convert back to correct size after manual correction % inputRegisterImage - [x y nCells] - Image to register to. @@ -35,6 +37,10 @@ options.registerUseOutlines = 1; % Cell array of matrices: cell array of {[x y z]} matrices that should match each Z dimension in inputImages options.altInputImages = {}; + % Str: max or mean + options.cellCombineType = 'max'; + % Float: default gamma. + options.gammaCorrection = 1; % get options options = getOptions(options,varargin); % display(options) @@ -58,8 +64,15 @@ options.altInputImages = inputImages; else switchInputImagesBack = 0; - end - inputImages = cellfun(@(x) nanmax(x,[],3),inputImages,'UniformOutput',false); + end + switch options.cellCombineType + case 'max' + inputImages = cellfun(@(x) nanmax(x,[],3),inputImages,'UniformOutput',false); + case 'mean' + inputImages = cellfun(@(x) nanmean(x,3),inputImages,'UniformOutput',false); + otherwise + inputImages = cellfun(@(x) nanmax(x,[],3),inputImages,'UniformOutput',false); + end inputImages = cat(3,inputImages{:}); disp(['inputImages: ' num2str(size(inputImages))]) else @@ -141,12 +154,14 @@ inputRegisterImageOutlinesOriginal = inputRegisterImageOutlines; [figHandle figNo] = openFigure(options.translationFigNo, ''); + % Force current character to be a new figure. + set(gcf,'currentch','3'); clf % normalize input marker image inputImages = normalizeVector(single(inputImages),'normRange','zeroToOne'); inputImagesOriginal = inputImages; - gammaCorrection = 1; - gammaCorrectionRef = 1; + gammaCorrection = options.gammaCorrection; + gammaCorrectionRef = options.gammaCorrection; inputImages = imadjust(inputImages,[],[],gammaCorrection); inputRegisterImage = imadjust(inputRegisterImage,[],[],gammaCorrectionRef); continueRegistering = 1; @@ -157,7 +172,7 @@ set(figHandle, 'KeyPressFcn', @(source,eventdata) subfxnRespondUser(source,eventdata)); figure(figHandle) rgbImage = subfxncreateRgbImg(); - imgTitleFxn = @(imgNo,imgN,gammaCorrection,gammaCorrectionRef,translationVector,rotationVector) sprintf('Image %d/%d\nup/down/left/right arrows for translation | "A" = rotate left, "S" = rotate right | f to finish\n1/2 keys for image gamma down/up | gamma = %0.3f | gamma_r = %0.3f | translation %d %d | rotation %d\npurple = reference image, green = image to manually translate',imgNo,imgN,gammaCorrection,gammaCorrectionRef,translationVector,rotationVector); + imgTitleFxn = @(imgNo,imgN,gammaCorrection,gammaCorrectionRef,translationVector,rotationVector) sprintf('Image %d/%d\nup/down/left/right arrows for translation | "A" = rotate left, "S" = rotate right | f to finish\n1/2 keys for image gamma down/up | gamma = %0.3f | gamma(ref) = %0.3f | translation %d %d | rotation %d\npurple = reference image, green = image to manually translate',imgNo,imgN,gammaCorrection,gammaCorrectionRef,translationVector,rotationVector); imgTitle = imgTitleFxn(imgNo,imgN,gammaCorrection,gammaCorrectionRef,translationVector,rotationVector); imgHandle = imagesc(rgbImage); @@ -226,7 +241,8 @@ function subfxnDrawImg() if gammaCorrection<=1 gDelta = gDelta/10; else - gammaCorrection = round(gammaCorrection); + gDelta = gDelta/5; + % gammaCorrection = gammaCorrection+round(gammaCorrection-round(gammaCorrection)); end gammaCorrection = gammaCorrection+gDelta; if gammaCorrection<0 diff --git a/ciapkg/movie_processing/normalizeMovie.m b/ciapkg/movie_processing/normalizeMovie.m index bdc7808..db83c84 100644 --- a/ciapkg/movie_processing/normalizeMovie.m +++ b/ciapkg/movie_processing/normalizeMovie.m @@ -13,6 +13,7 @@ % 2019.10.08 [09:14:33] - Add option for user to input crop coordinates in case they have a NaN or other border from motion correction, so that does not affect spatial filtering. User can also now input a char for inputMovie and have it load within the function to help reduce memory overhead % 2019.10.29 [13:51:04] - Added support for parallel.pool.Constant when PCT auto-start parallel pool disabled. % 2021.01.15 [21:09:55] - Moved detrend support into normalizeMovie. + % 2021.06.02 [20:04:49] - Detrend movie now uses nanmean to get around issues in motion corrected videos. % TODO % @@ -717,12 +718,12 @@ function subfxnDetrend() %Get dimension information about 3D movie matrix [inputMovieX, inputMovieY, inputMovieZ] = size(inputMovie); - frameMeanInputMovie = squeeze(mean(inputMovie,[1 2])); + frameMeanInputMovie = squeeze(nanmean(inputMovie,[1 2])); trendVals = frameMeanInputMovie - detrend(frameMeanInputMovie,option.detrendDegree); % meanInputMovie = detrend(frameMeanInputMovie,0); - meanInputMovie = mean(frameMeanInputMovie); + meanInputMovie = nanmean(frameMeanInputMovie); nFramesToNormalize = options.maxFrame; nFrames = nFramesToNormalize; diff --git a/ciapkg/video/createMovieFromVector.m b/ciapkg/video/createMovieFromVector.m index 2ea0aad..816c528 100644 --- a/ciapkg/video/createMovieFromVector.m +++ b/ciapkg/video/createMovieFromVector.m @@ -9,7 +9,7 @@ % vectorMovie - 3D movie ([x y t]) with dimensions of movieDim and class of inputVector % changelog - % + % 2021.05.04 [09:29:19] - Users can now manually change value assigned to center line or signal. % TODO % @@ -20,6 +20,10 @@ options.windowSize = [-30:30]; % movie height downsample size options.secondDimDownsample = 5; + % Float: numbers between 0 to 1, value to make for signal + options.signalValue = 0.5; + % Float: numbers between 0 to 1, value to make for center line + options.centerLineValue = 1; % get options options = getOptions(options,varargin); % display(options) @@ -41,7 +45,7 @@ nStims = length(windowSize); if ~isempty(options.normalizeVector) - display('Normalizing vector...') + disp('Normalizing vector...') inputVector = normalizeVector(inputVector,'normRange',options.normalizeVector); end @@ -66,12 +70,12 @@ relativeStimValue = round(inputVector(frameVectorIdx(thisFrameVectorNo))*movieDimY); end % add relative (to max) value of vector to movie - vectorMovie(1:relativeStimValue,thisFrameVectorNo,frameNo) = 0.05; + vectorMovie(1:relativeStimValue,thisFrameVectorNo,frameNo) = options.signalValue; end % resize vector movie to match movie dimensions given vectorMovie(:,:,frameNo) = imresize(vectorMovie(:,1:length(frameVectorIdx),frameNo),[movieDimY movieDim(2)],'bilinear'); - vectorMovie(:,round(end/2),frameNo) = 1; + vectorMovie(:,round(end/2),frameNo) = options.centerLineValue; reverseStr = cmdWaitbar(frameNo,nFrames,reverseStr,'inputStr','creating matrix: ','waitbarOn',1,'displayEvery',5); end diff --git a/ciapkg/view/playMovie.m b/ciapkg/view/playMovie.m index 852acb8..5934c7b 100644 --- a/ciapkg/view/playMovie.m +++ b/ciapkg/view/playMovie.m @@ -4,7 +4,9 @@ % started 2013.11.09 [10:39:50] % % inputs - % inputMovie - [X Y Z] matrix of X,Y height/width and Z frames + % inputMovie - either grayscale or color movie matrix: + % grayscale: [x y t] matrix of x,y height/width and t frames + % RGB: [x y C t] matrix of x,y height/width, t frames, and C color channel (3 as RGB) % options % fps - % extraMovie - extra movie to play, [X Y Z] matrix of X,Y height/width and Z frames @@ -29,6 +31,7 @@ % 2021.01.14 [20:12:10] - Update passing of HDF5 dataset name to ciapkg.io.readFrame. % 2021.01.17 [19:21:12] - Integrated contrast sliders directly into the main GUI so users don't have to open up a separate GUI. Make GUI sliders thinner. % 2021.02.05 [16:25:12] - Added feature to sub-sample movie to make display run faster for larger movies. + % 2021.04.23 [13:05:29] - Add support for playing RGB movie of dimension [x y C t] if input directly as matrix. % ======================== % options @@ -150,7 +153,11 @@ else inputMovieIsChar = 0; inputMovieDims = size(inputMovie); - nFramesOriginal = inputMovieDims(3); + if length(inputMovieDims)==4 + nFramesOriginal = inputMovieDims(4); + else + nFramesOriginal = inputMovieDims(3); + end readMovieChunks = 0; end @@ -167,7 +174,11 @@ % ========================================== if options.nFrames==0 - nFrames = size(inputMovie,3); + if length(inputMovieDims)==4 + nFrames = size(inputMovie,4); + else + nFrames = size(inputMovie,3); + end else nFrames = options.nFrames; end @@ -261,7 +272,11 @@ [tmpFrame] = ciapkg.io.readFrame(inputMovie,1,'movieFileID',movieFileID,'inputMovieDims',inputMovieDims,'inputDatasetName',options.inputDatasetName); % tmpFrame = loadMovieList(inputMovie,'inputDatasetName',options.inputDatasetName,'displayInfo',0,'displayDiagnosticInfo',0,'displayWarnings',0,'frameList',1); else - tmpFrame = squeeze(inputMovie(:,:,1)); + if length(size(inputMovie))==4 + tmpFrame = squeeze(inputMovie(:,:,:,1)); + else + tmpFrame = squeeze(inputMovie(:,:,1)); + end end if sparseInputMovie==1 tmpFrame = full(tmpFrame); @@ -457,7 +472,11 @@ % thisFrame = subfxn_readMovieDisk(inputMovie,frame,movieType); [thisFrame] = ciapkg.io.readFrame(inputMovie,frame,'movieFileID',movieFileID,'inputMovieDims',inputMovieDims,'inputDatasetName',options.inputDatasetName); else - thisFrame = squeeze(inputMovie(:,:,frame)); + if length(size(inputMovie))==4 + thisFrame = squeeze(inputMovie(:,:,:,frame)); + else + thisFrame = squeeze(inputMovie(:,:,frame)); + end end if sparseInputMovie==1 thisFrame = full(thisFrame); @@ -523,7 +542,11 @@ ssm = options.subSampleMovie; set(montageHandle,'Cdata',thisFrame(1:ssm:end,1:ssm:end),'AlphaData',imAlpha(1:ssm:end,1:ssm:end)); else - set(montageHandle,'Cdata',thisFrame,'AlphaData',imAlpha); + if length(size(thisFrame))==3 + % set(montageHandle,'Cdata',squeeze(thisFrame(:,:,1)),'AlphaData',imAlpha); + else + set(montageHandle,'Cdata',thisFrame,'AlphaData',imAlpha); + end end if strcmp(options.colormapColor,'gray') set(axHandle,'color',[1 0 0]); diff --git a/ciapkg/view/viewVennDiagram.m b/ciapkg/view/viewVennDiagram.m index 0c79cb4..265aa06 100644 --- a/ciapkg/view/viewVennDiagram.m +++ b/ciapkg/view/viewVennDiagram.m @@ -124,6 +124,7 @@ function viewVennDiagram(circleAreas,overlapAreas,totalArea,varargin) % Plot text indicating the exact numbers for each area of overlap if options.displayText==1 + rdDgts = options.roundDigits; % str1 = sprintf('%d | %0.1f | %0.1f',idPairsFixed(idPairNo,1), circleAreasOriginal(1),circleAreas(1)); % str2 = sprintf('%d | %0.1f | %0.1f',idPairsFixed(idPairNo,2), circleAreasOriginal(2),circleAreas(2)); % str3 = sprintf('%d | %0.1f | %0.1f',idPairsFixed(idPairNo,3), circleAreasOriginal(3),circleAreas(3)); diff --git a/loadBatchFxns.m b/loadBatchFxns.m index 24408e7..37284ad 100644 --- a/loadBatchFxns.m +++ b/loadBatchFxns.m @@ -126,6 +126,16 @@ function loadBatchFxns(varargin) display(repmat('@',1,7)) end + if workerCheck==1 + else + if loadMijiCheck==0 + disp('Skipping loading of Miji.') + else + manageMiji('startStop','setupImageJ'); + end + end + loadMijiCheck = 0; + if loadMijiCheck==0 disp('Skipping loading of Miji.') elseif workerCheck==1 From 4d2477e3c97c5a275606ea28adb8aedf4e6b0582 Mon Sep 17 00:00:00 2001 From: Biafra Ahanonu Date: Mon, 21 Jun 2021 16:36:46 -0700 Subject: [PATCH 2/4] Update docs --- docs/docs/acknowledgments.md | 2 +- docs/docs/all_docs.md | 47 +++++ docs/docs/api_ciapkg.md | 53 +++++ docs/docs/api_example_pipeline.md | 196 ++++++++++++++++++ docs/docs/blank.md | 91 ++++++++ docs/docs/example_data.md | 7 + docs/docs/help_animal_tracking.md | 49 +++-- docs/docs/help_cell_extraction.md | 2 + docs/docs/help_contrast.md | 32 +++ docs/docs/help_large_movie_analysis.md | 44 ++++ docs/docs/help_motion_correction.md | 78 +++++++ docs/docs/help_nwb.md | 41 ++++ docs/docs/img/ciapkg_pipeline.png | Bin 0 -> 279452 bytes docs/docs/img/favicon.ico | Bin 0 -> 4286 bytes docs/docs/index.md | 34 ++- docs/docs/install.md | 26 ++- docs/docs/install_alt.md | 19 ++ docs/docs/install_gui_notes.md | 40 ++++ docs/docs/pipeline_detailed_all.md | 20 ++ docs/docs/pipeline_detailed_cross_session.md | 33 +++ docs/docs/pipeline_detailed_downsample_raw.md | 30 +++ docs/docs/pipeline_detailed_modify_movies.md | 13 ++ docs/docs/pipeline_detailed_preprocess.md | 40 ++++ .../pipeline_detailed_preprocess_check.md | 20 ++ .../pipeline_detailed_signal_extraction.md | 21 ++ ...ipeline_detailed_signal_extraction_load.md | 34 +++ ...e_detailed_signal_extraction_validation.md | 13 ++ ...ipeline_detailed_signal_region_analysis.md | 11 + ...pipeline_detailed_signal_sorting_manual.md | 73 +++++++ docs/docs/pipeline_overview.md | 11 + docs/docs/questions.md | 2 +- docs/docs/references.md | 2 +- docs/make_docs.py | 34 ++- docs/mkdocs.yml | 42 +++- 34 files changed, 1122 insertions(+), 38 deletions(-) create mode 100644 docs/docs/all_docs.md create mode 100644 docs/docs/api_ciapkg.md create mode 100644 docs/docs/api_example_pipeline.md create mode 100644 docs/docs/blank.md create mode 100644 docs/docs/example_data.md create mode 100644 docs/docs/help_cell_extraction.md create mode 100644 docs/docs/help_contrast.md create mode 100644 docs/docs/help_large_movie_analysis.md create mode 100644 docs/docs/help_motion_correction.md create mode 100644 docs/docs/help_nwb.md create mode 100644 docs/docs/img/ciapkg_pipeline.png create mode 100644 docs/docs/img/favicon.ico create mode 100644 docs/docs/install_alt.md create mode 100644 docs/docs/install_gui_notes.md create mode 100644 docs/docs/pipeline_detailed_all.md create mode 100644 docs/docs/pipeline_detailed_cross_session.md create mode 100644 docs/docs/pipeline_detailed_downsample_raw.md create mode 100644 docs/docs/pipeline_detailed_modify_movies.md create mode 100644 docs/docs/pipeline_detailed_preprocess.md create mode 100644 docs/docs/pipeline_detailed_preprocess_check.md create mode 100644 docs/docs/pipeline_detailed_signal_extraction.md create mode 100644 docs/docs/pipeline_detailed_signal_extraction_load.md create mode 100644 docs/docs/pipeline_detailed_signal_extraction_validation.md create mode 100644 docs/docs/pipeline_detailed_signal_region_analysis.md create mode 100644 docs/docs/pipeline_detailed_signal_sorting_manual.md diff --git a/docs/docs/acknowledgments.md b/docs/docs/acknowledgments.md index e6dc51e..8647c23 100644 --- a/docs/docs/acknowledgments.md +++ b/docs/docs/acknowledgments.md @@ -1,4 +1,4 @@ -## Acknowledgments +# Acknowledgments Thanks to Jones G. Parker, PhD () for providing extensive user feedback during development of the `{{ site.name }}` software package. diff --git a/docs/docs/all_docs.md b/docs/docs/all_docs.md new file mode 100644 index 0000000..7d75f6f --- /dev/null +++ b/docs/docs/all_docs.md @@ -0,0 +1,47 @@ +# {{ site.name }} one-page README + +This page contains all the documents in a single page and is automatically updated to reflect the current state of each page. + +##
—Setup—
+ +{!install.md!} +{!install_alt.md!} +{!example_data.md!} +{!dependencies.md!} + +##
—Repository—
+{!data.md!} +{!notes.md!} +{!organization.md!} + +##
—Processing data—
+{!pipeline_overview.md!} +{!pipeline_detailed.md!} +{!pipeline_animal_tracking.md!} + +##
—API—
+{!api_example_pipeline.md!} +{!api_ciapkg.md!} + +##
—Help—
+{!help_issues.md!} +{!help_inscopix.md!} +{!help_nwb.md!} +{!help_contrast.md!} +{!help_analysis_methods.md!} +{!help_large_movie_analysis.md!} +{!help_stripe_removal.md!} +{!help_snr.md!} +{!help_spatial_filtering.md!} +{!help_temporal_downsampling.md!} +{!help_motion_correction.md!} +{!help_cell_extraction.md!} +{!help_manual_cell_sorting.md!} +{!help_cross_session_alignment.md!} +{!help_animal_tracking.md!} + +##
—Misc—
+{!acknowledgments.md!} +{!references.md!} +{!questions.md!} +{!license.md!} \ No newline at end of file diff --git a/docs/docs/api_ciapkg.md b/docs/docs/api_ciapkg.md new file mode 100644 index 0000000..907a847 --- /dev/null +++ b/docs/docs/api_ciapkg.md @@ -0,0 +1,53 @@ +# `{{ site.name }}` functions within `{{ code.package }}` sub-package. + +`{{ site.name }}` contains many functions for imaging analysis, from processing videos to wrappers for running cell extraction algorithms and GUIs for visualizing movies and evaluating cell extraction outputs. Several are detailed below. For each users can visualize options with `help FUN` or `edit FUN`. If attempting to load a non-package function (e.g. it does not start with `{{ code.package }}`), then append `{{ code.package }}.api.`, e.g. `playMovie` would become `{{ code.package }}.api.playMovie`. Alternatively, load all the functions into the workspace with `import ciapkg.api.*`. + +## Visualizing movies + +`playMovie` + +`ciapkg.io.loadMovie` or `loadMovieList` + +`createImageOutlineOnMovie` + +`createSignalBasedMovie` + +`ciapkg.io.readFrame` + +## Get movie information + +`ciapkg.io.getMovieInfo` + +## Sorting cells + +`signalSorter` + +## Pre-processing + +`ciapkg.demo.runPreprocessing` + +`downsampleHdf5Movie` + +`removeStripsFromMovie` + +`turboregMovie` + +`dfofMovie` + +`downsampleMovie` + +`normalizeMovie` + +## Cell extraction + +- _PCA-ICA_ - `ciapkg.signal_extraction.runPcaIca`. +- _CNMF_ - ``. +- _CNMF-E_ - ``. +- _EXTRACT_ - ``. +- _ROI_ - ``. + +## Cross-session alignment + +`matchObjBtwnTrials` + +`createMatchObjBtwnTrialsMaps` \ No newline at end of file diff --git a/docs/docs/api_example_pipeline.md b/docs/docs/api_example_pipeline.md new file mode 100644 index 0000000..146d151 --- /dev/null +++ b/docs/docs/api_example_pipeline.md @@ -0,0 +1,196 @@ +# Example `{{ site.name }}` pipeline via the command line. + +Below is an example `{{ site.name }}` 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 `{{ site.name }}` 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;`. + +```MATLAB +% Running {{ site.name }} from MATLAB command line/window + +%% Load {{ site.name }} functions +loadBatchFxns(); + +%% Load movie to analyze +inputMovie = loadMovieList([ciapkg.getDir() filesep 'data' filesep '2014_04_01_p203_m19_check01' filesep 'concat_recording_20140401_180333.h5']); +``` + +```MATLAB +%% Visualize slice of the movie +playMovie(inputMovie(:,:,1:500)); +% Alternatively, visualize by entering the file path +playMovie(inputMoviePath); +``` + +```MATLAB +%% Downsample input movie if need to +inputMovieD = downsampleMovie(inputMovie,'downsampleDimension','space','downsampleFactor',4); +playMovie(inputMovie,'extraMovie',inputMovieD); + +% 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. +convertInscopixIsxdToHdf5(moviePath,'options',opts); +``` + +```MATLAB +%% 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'; +removeStripsFromMovie(inputMovie(:,:,1),'options',sopts,'showImages',1); +% Run on the entire movie +removeStripsFromMovie(inputMovie,'options',sopts); +``` + +```MATLAB +%% Get coordinates to crop +[cropCoords] = getCropCoords(squeeze(inputMovie(:,:,1))); +toptions.cropCoords = cropCoords; +``` + +```MATLAB +%% 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, ~] = turboregMovie(inputMovie,'options',toptions); +``` + +```MATLAB +%% Compare raw and motion corrected movies +playMovie(inputMovie,'extraMovie',inputMovie2); +``` + +```MATLAB +%% Run dF/F +inputMovie3 = dfofMovie(single(inputMovie2),'dfofType','dfof'); +``` + +```MATLAB +%% Run temporal downsampling +inputMovie3 = downsampleMovie(inputMovie3,'downsampleDimension','time','downsampleFactor',4); +``` + +```MATLAB +%% Final check of movie before cell extraction +playMovie(inputMovie3); +``` + +```MATLAB +%% Run PCA-ICA cell extraction. CNMF-e, CNMF, ROI, and other cell-extraction algorithms are also available. +nPCs = 300; nICs = 225; +[PcaOutputSpatial, PcaOutputTemporal, PcaOutputSingularValues, PcaInfo] = run_pca(inputMovie3, nPCs, 'movie_dataset_name','/1'); +[IcaFilters, IcaTraces, IcaInfo] = run_ica(PcaOutputSpatial, PcaOutputTemporal, PcaOutputSingularValues, size(inputMovie3,1), size(inputMovie3,2), nICs, 'output_units','fl','mu',0.1,'term_tol',5e-6,'max_iter',1e3); +IcaTraces = permute(IcaTraces,[2 1]); +``` + +```MATLAB +%% Save outputs to NWB format +saveNeurodataWithoutBorders(IcaFilters,{IcaTraces},'pcaica','pcaica.nwb'); +``` + +Run CNMF or CNMF-e cell extraction. +```MATLAB +%% Run CNMF or CNMF-e cell extraction. Check each function with "edit" for options. +numExpectedComponents = 225; +cellWidth = 10; +cnmfOptions.otherCNMF.tau = cellWidth/2; % expected width of cells + +% Run CNMF +[cnmfAnalysisOutput] = computeCnmfSignalExtractionClass(movieList,numExpectedComponents,'options',cnmfOptions); + +% Run CNMF-e +[cnmfeAnalysisOutput] = computeCnmfeSignalExtraction_batch(movieList{1},'options',cnmfeOptions); + +%% Save outputs to NWB format +saveNeurodataWithoutBorders(cnmfAnalysisOutput.extractedImages,{cnmfAnalysisOutput.extractedSignals,cnmfAnalysisOutput.extractedSignalsEst},'cnmf','cnmf.nwb'); +saveNeurodataWithoutBorders(cnmfeAnalysisOutput.extractedImages,{cnmfeAnalysisOutput.extractedSignals,cnmfeAnalysisOutput.extractedSignalsEst},'cnmfe','cnmfe.nwb'); +``` + +Run EXTRACT cell extraction. +```MATLAB +%% Run EXTRACT cell extraction. Check each function with "edit" for options. +% Load default configuration +extractConfig = get_defaults([]); + +outStruct = extractor(inputMovie,extractConfig); +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 +saveNeurodataWithoutBorders(extractAnalysisOutput.filters,{extractAnalysisOutput.traces},'cnmf','cnmf.nwb'); +``` + +```MATLAB +%% Run signal sorting using matrix inputs +[outImages, outSignals, choices] = signalSorter(IcaFilters,IcaTraces,'inputMovie',inputMovie3); +``` + +```MATLAB +%% Run signal sorting using NWB +[outImages, outSignals, choices] = signalSorter('pcaica.nwb',[],'inputMovie',inputMovie3); +``` + +```MATLAB +%% 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') +``` + +```MATLAB +%% Create an overlay of extraction outputs on the movie and signal-based movie +[inputMovieO] = createImageOutlineOnMovie(inputMovie3,IcaFilters,'dilateOutlinesFactor',0); +[signalMovie] = createSignalBasedMovie(IcaTraces,IcaFilters,'signalType','peak'); +``` + +```MATLAB +%% Play all three movies +% Normalize all the movies +movieM = cellfun(@(x) normalizeVector(x,'normRange','zeroToOne'),{inputMovie3,inputMovieO,signalMovie},'UniformOutput',false); +playMovie(cat(2,movieM{:})); +``` + +```MATLAB +%% Run cross-session alignment of cells +% Create input images, cell array of [x y nCells] matrices +inputImages = {day1Images,day2Images,day3Images}; + +% 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] = 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] = createMatchObjBtwnTrialsMaps(inputImages,alignmentStruct); +``` \ No newline at end of file diff --git a/docs/docs/blank.md b/docs/docs/blank.md new file mode 100644 index 0000000..2ae31d9 --- /dev/null +++ b/docs/docs/blank.md @@ -0,0 +1,91 @@ +# {{ site.name }} + +![GitHub top language](https://img.shields.io/github/languages/top/bahanonu/calciumImagingAnalysis?style=flat-square&logo=appveyor) +![GitHub license](https://img.shields.io/github/license/bahanonu/calciumImagingAnalysis?style=flat-square&logo=appveyor) +[![GitHub release (latest by date)](https://img.shields.io/github/v/release/bahanonu/calciumImagingAnalysis?style=flat-square&logo=appveyor)](https://github.com/bahanonu/calciumImagingAnalysis/releases/latest?style=flat-square&logo=appveyor) +![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/bahanonu/calciumImagingAnalysis?style=flat-square&logo=appveyor) +[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg?style=flat-square)](https://github.com/bahanonu/calciumImagingAnalysis/graphs/commit-activity?style=flat-square&logo=appveyor) + + + +
+ +Created by __Biafra Ahanonu, PhD__. + +`{{ site.name }}` (pronounced cheetah, formerly `calciumImagingAnalysis` [`CIAPKG`]) is a software package for analysis of one- and two-photon calcium imaging datasets. + +__Download the software at [https://github.com/bahanonu/calciumImagingAnalysis](https://github.com/bahanonu/calciumImagingAnalysis).__ + +CIAtah_logo + +- This user guide contains instructions to setup, run, and troubleshoot `{{ site.name }}`. +- Note: `{{ site.name }}` is a class (`{{ site.namelow }}` within MATLAB) with various GUIs to allow processing of calcium imaging data. In addition, users can access the underlying `{{ site.name }}` functions to make custom workflows. See [Custom command-line pipelines](api_example_pipeline.md). +- Read my overview of calcium imaging analysis methods at [Calcium imaging cell identification and fluorescence activity trace reconstruction, part 1](https://bahanonu.com/brain/#c20181209). + + + +

+Movie processing, cell extraction, and analysis validation. +

+

+ + ciapkgMovie + +

+ +

+ {{ site.name }} cell sorting GUI +

+

+ + ciapkgMovie + +

+ +

+ Stable cell alignment across imaging sessions. +

+

+ + m121_matchedCells + +

+ +`{{ site.name }}` features: + +- Includes a GUI to allow users to do large-scale batch analysis, accessed via the repository's `{{ site.name }}` class. +- The underlying functions can also be used to create GUI-less, command line-ready analysis pipelines. Functions located in `ciapkg` and `+ciapkg` sub-folders. +- Includes all major calcium imaging analysis steps: pre-processing (motion correction, spatiotemporal downsampling, spatial filtering, relative fluorescence calculation, etc.), support for multiple cell-extraction methods, automated cell classification (coming soon!), cross-session cell alignment, and more. +- Has several example one- and two-photon calcium imaging datasets that it will automatically download to help users test out the package. +- Includes code for determining animal position (e.g. in open-field assay). +- Supports [Neurodata Without Borders](https://www.nwb.org/) data standard (see [calcium imaging tutorial](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html)) for reading/writing cell-extraction (e.g. outputs of PCA-ICA, CELLMax, CNMF, CNMF-E, etc.). Supports reading and writing NWB movie files with continued integration with NWB planned. +- Requires `MATLAB`. + +![ciapkg_pipeline.png](img/ciapkg_pipeline.png) + +## Navigation + +The main sections of the site: + +- `Setup` - installation of `{{ site.name }}`. +- `Repository` - notes about the software package and data formats. +- `Processing data` - sections related to processing calcium imaging movies using the `{{ site.name }}` class. +- `API` - details how to run `{{ site.name }}` from the command line. Will include more details on the many underlying functions in the future. +- `Help` - several section that provide hints and help for processing calcium imaging. +- `Misc` - miscellaneous information about the repository. + +## References + +Please cite our [Corder*, Ahanonu*, et al. _Science_, 2019](http://science.sciencemag.org/content/363/6424/276.full) publication if you used the software package or code from this repository to advance or help your research. + +## Questions? + +Please [open an issue on GitHub](https://github.com/bahanonu/calciumImagingAnalysis/issues) or email any additional questions not covered in the repository to `bahanonu [at] alum.mit.edu`. + +Made in USA.
+USA + +- ![Hits](https://hitcounter.pythonanywhere.com/count/tag.svg?url=https%3A%2F%2Fgithub.com%2Fbahanonu%2FcalciumImagingAnalysis) (starting 2020.09.16) +- ![visitors](https://visitor-badge.glitch.me/badge?page_id=bahanonu.calciumImagingAnalysis) (starting 2020.09.22) + \ No newline at end of file diff --git a/docs/docs/example_data.md b/docs/docs/example_data.md new file mode 100644 index 0000000..710ad4d --- /dev/null +++ b/docs/docs/example_data.md @@ -0,0 +1,7 @@ +### Example data + +The `{{ site.name }}` repository contains several example one-photon calcium imaging movies from miniature microscope experiments in freely moving rodents. + +To download example data, run `loadDependencies` module (e.g. `obj.loadDependencies`) and select `Download test one-photon data.` option to download one-photon miniature microscope example datasets to use for testing `{{ site.name }}` preprocessing, cell extraction, and cell classification code. The data will be located in the `data` folder within the repository root directory. + +Else run `example_downloadTestData.m` from the MATLAB command line with the working directory set to the `{{ site.name }}` repository. \ No newline at end of file diff --git a/docs/docs/help_animal_tracking.md b/docs/docs/help_animal_tracking.md index b31c80b..e0fc098 100644 --- a/docs/docs/help_animal_tracking.md +++ b/docs/docs/help_animal_tracking.md @@ -1,28 +1,51 @@ -# Tracking +# Animal tracking -Code for ImageJ and Matlab based image tracking. +Code for ImageJ- and Matlab-based image tracking. # ImageJ based tracking -Functions needed (have entire `miniscope_analysis` loaded anyways): +Functions needed (have entire `{{ site.name }}` pipeline loaded anyways to ensure all dependencies are met): - `mm_tracking.ijm` is the tracking function for use in ImageJ, place in -`plugins` folder. -- `removeIncorrectObjs.m` is a function to clean-up the ImageJ output. -- `createTrackingOverlayVideo` is a way to check the output from the -tracking by overlaying mouse tracker onto the video. +`plugins` folder. It is found in the `ciapkg\tracking` folder of the repository. +- `removeIncorrectObjs()` is a function to clean-up the ImageJ output. +- `createTrackingOverlayVideo()` is a function that allows users to check the output from the tracking by overlaying the mouse tracker onto the video. ## Instructions for ImageJ and Matlab +Run `mm_tracking` from the `Plugins` menu of ImageJ. Several settings to check: + +- `number of session folders to analyze` - this will indicate how many movies you want to analyze. Depending on `analyze movies from a list file` setting, a GUI will appear asking you to select movies to analyze (preferably AVIs) or a text file with a list of movies. +- `pixel to cm conversion, distance (cm)` - Make sure pixel to cm conversion indicates a measurable distance in the video, e.g. from one side of the box to another. The program will ask you to draw this distance to estimate pixels/cm. +- `crop stack?` - keep this selected, as allow removal of parts of movie where the animal will not go, improving results. +- `erode and dilate` - likely keep this selected, as it essentially makes sure the mouse is a solid object and smooths the tracking. +- `analyze movies from a list file` - select this option if you have a text file with the location of each movie to be analyzed on a new line. Use this to analyze many movies in batch. +- `hide loaded movie` - uncheck this to be able to visualize as ImageJ completes each step in the processing. Leave checked to improve speed of analysis. + Example screen after running `mm_tracking` within ImageJ, click to expand. -![image](https://user-images.githubusercontent.com/5241605/34800762-1fa35480-f61a-11e7-91fb-65a260436725.png) -Once ImageJ is finished, within Matlab run the following code (cleans up the ImageJ tracking by removing small objects and adding NaNs for missing frames along with making a movie to check output). Modify to point toward paths specific for your data. + +![image](https://user-images.githubusercontent.com/5241605/113023298-554a5e80-913a-11eb-88ed-181c133184f1.png) + +Once ImageJ is finished, within `MATLAB` run the following code (cleans up the ImageJ tracking by removing small objects and adding NaNs for missing frames along with making a movie to check output). Modify to point toward paths specific for your data. ```Matlab % CSV file from imageJ and AVI movie path used in ImageJ moviePath = 'PATH_TO_AVI_USED_IN_IMAEJ'; csvPath = 'PATH_TO_CSV_OUTPUT_BY_IMAGEJ'; % clean up tracking [trackingTableFilteredCell] = removeIncorrectObjs(csvPath,'inputMovie',{moviePath}); +``` + +## Example output from animal in open field during miniature microscope imaging + + +Tracking of an animal over time (green = early in session, red = late in session). +![image](https://user-images.githubusercontent.com/5241605/34800547-2a10a3b0-f619-11e7-9c88-88750c9875cd.png) + +## Tracking video + +The tracking video can be used to quickly validate that the animal is being correctly tracked. + +```Matlab % make tracking video % frames to use as example check nFrames=1500:2500; @@ -31,12 +54,10 @@ inputMovie = loadMovieList(moviePath,'frameList',nFrames); playMovie(inputTrackingVideo); ``` -## Example output from 2017_09_11_p540_m381_openfield01_091112017 -![image](https://user-images.githubusercontent.com/5241605/34800547-2a10a3b0-f619-11e7-9c88-88750c9875cd.png) - +Overlay of tracking (red circle) on the mouse in a specific frame. ![image](https://user-images.githubusercontent.com/5241605/34800536-19eefcf2-f619-11e7-954f-dba59f4fd427.png) -# Matlab based tracking + diff --git a/docs/docs/help_cell_extraction.md b/docs/docs/help_cell_extraction.md new file mode 100644 index 0000000..e91bffb --- /dev/null +++ b/docs/docs/help_cell_extraction.md @@ -0,0 +1,2 @@ +# Cell extraction + diff --git a/docs/docs/help_contrast.md b/docs/docs/help_contrast.md new file mode 100644 index 0000000..724fbe9 --- /dev/null +++ b/docs/docs/help_contrast.md @@ -0,0 +1,32 @@ +# Interpreting displayed movies + +It may appear at times that `{{ site.name }}` has introduced noise into movies after processing. However, normally that noise is already there in the movie. In the case of one-photon miniature microscope movies that noise is often small relative to the baseline background fluorescence, hence not noticeable. However, after dF/F0 or spatial filtering users will be able to see the noise more easily as it will have a relatively greater magnitude compared to the signal now present in the movie. + +Further, in many cases the contrast is automatically adjusted in `{{ site.name }}` GUIs to boost likelihood users will see cells and other biologically relevant features (even though underlying matrix values are not changed), which can sometimes lead to the perception that noise is being added depending on viewing raw vs. dF/F0 or other preprocessed movies. + +## Example + +For example of what this looks like, take one of the example movies in the {{ site.name }} repository: `2014_04_01_p203_m19_check01`. + +### Raw movie + +A frame from the raw movie looks like: + +![image](https://user-images.githubusercontent.com/5241605/104547545-a9d24900-55e3-11eb-8a91-5f4ee00b9813.png) + +Applying a simple bandpass or highpass filter (to remove the low frequency background) leads to the below (keeping contrast/brightness the same as the raw movie image): + +![image](https://user-images.githubusercontent.com/5241605/104547910-852aa100-55e4-11eb-8528-5b4f29052ec2.png) + +However, if we adjust the contrast, we can now see some of the noise present in the higher frequency components of the raw movie that was otherwise obscured or would be hard to see in the raw movie with the high baseline present: + +![image](https://user-images.githubusercontent.com/5241605/104547900-7c39cf80-55e4-11eb-86d8-9e6e80758d01.png) + +### dF/F0 +Now compare to dF/F0 of that same raw movie without any motion correction, etc. we see the below: + +![image](https://user-images.githubusercontent.com/5241605/104547830-5280a880-55e4-11eb-8b35-ad114d12a2ff.png) + +However, if you adjust the contrast, you get the below image, where the noise is much more pronounced: + +![image](https://user-images.githubusercontent.com/5241605/104547778-37159d80-55e4-11eb-8b06-643508cb38ad.png) \ No newline at end of file diff --git a/docs/docs/help_large_movie_analysis.md b/docs/docs/help_large_movie_analysis.md new file mode 100644 index 0000000..f619438 --- /dev/null +++ b/docs/docs/help_large_movie_analysis.md @@ -0,0 +1,44 @@ +# Analyzing large movies + +Some movies are larger than the available RAM on users analysis computer. Below are several ways that the underlying functions in `CIAPKG` can be used to analyze large movies. + +## Playing large movies from disk + +To directly and quickly visualize large or long movies from disk, directly input the movie path into `playMovie` as below. + +```Matlab +% Full path to the movie +inputMoviePath = 'path/to/movie.h5'; + +playMovie(inputMoviePath); +``` + +Which will produce a GUI as below that will play the movie back. + +![image](https://user-images.githubusercontent.com/5241605/97789968-fdef9480-1b81-11eb-938c-863fa5159fb5.png) + +## ROI signal extraction +The below code is an example ROI signal extraction for large movie in chunks from disk after analyzing a small chunk with PCA-ICA to obtain reference masks. Modify `inputMoviePath` to a full path to your movie (HDF5, TIF, AVI, and ISXD supported). + +```MATLAB +% Full path to the movie +inputMoviePath = 'path/to/movie.h5'; + +%% =======PCA-ICA +% Run PCA-ICA on only a subset of frames. +% OPTIONS + % Vector of frames to analyze for PCA-ICA + framesToAnalyzePcaIca = 1:300; + % Number of PCs and ICs to request + nPCs = 250; nICs = 200; +[pcaicaAnalysisOutput] = ciapkg.signal_extraction.runPcaIca(inputMoviePath,nPCs,nICs,'frameList',framesToAnalyzePcaIca,'mu',0.1,'max_iter',1e3); + +%% =======ROI extraction new version +% OPTIONS + % Number of frames to chunk from movie when doing ROI estimation, to reduce RAM usage. + movieChunks = 100; +% Normal PCA-ICA, binary masks +[roiSignals, ~] = ciapkg.signal_extraction.computeSignalsFromImages(pcaicaAnalysisOutput.IcaFilters,inputMoviePath,'frameList',[],'readMovieChunks',1,'threshold',0.4,'nFramesPerChunk',movieChunks,'weightSignalByImage',0); +% Weighted PCA-ICA, trace based on weighted pixel values of eahc ROI +[roiSignalsWeighted, ~] = ciapkg.signal_extraction.computeSignalsFromImages(pcaicaAnalysisOutput.IcaFilters,inputMoviePath,'frameList',[],'readMovieChunks',1,'threshold',0.4,'nFramesPerChunk',movieChunks,'weightSignalByImage',1); +``` \ No newline at end of file diff --git a/docs/docs/help_motion_correction.md b/docs/docs/help_motion_correction.md new file mode 100644 index 0000000..9e93cc9 --- /dev/null +++ b/docs/docs/help_motion_correction.md @@ -0,0 +1,78 @@ +Scripts to register movies to remove motion. + +## Calculating final transformation after multiple registration iterations. +It is possible to use the output from motion correction (often done with `turboregMovie` or `modelPreprocessMovieFunction`) to transform the movie at later times if needed. There are two ways to do this: + +- iteratively perform each motion correction step (e.g. same order as in `modelPreprocessMovieFunction`) or +- create the translation/skew/rotation matrices for each step using `ResultsOutOriginal` and combine for all iterations as `totalTranformMatrix = (R2'*S2'*T2'*R1'*S1'*T1')'`. Note the order matters. + - Where `1, 2, ...` indicate matrix for iterations `1,2,...` and `R, S, T` are rotation, skew (shear + scale) and translation matrices, respectively. + - For 3 iterations would be `(R3'*S3'*T3'*R2'*S2'*T2'*R1'*S1'*T1')'` or alternatively `T1*S1*R1*T3*S3*R2*T3*S3*R3`. + - For translation/rotation matrices, use definitions in https://www.mathworks.com/help/images/matrix-representation-of-geometric-transformations.html to construct them. + +## Turboreg +### Compiling `turboreg` and `transfturboreg` mex file +* Can compile on your system using the following command +```Matlab +mex('-v', '-largeArrayDims','-I.', 'turboreg.c','.\BsplnTrf.c','.\BsplnWgt.c','.\convolve.c','.\getPut.c','.\main.c','.\phil.c','.\pyrFilt.c','.\pyrGetSz.c','.\quant.c','.\reg0.c','.\reg1.c','.\reg2.c','.\reg3.c','.\regFlt3d.c','.\svdcmp.c') + +mex('-v', '-largeArrayDims','-I.', 'transfturboreg.c','.\BsplnTrf.c','.\BsplnWgt.c','.\convolve.c','.\getPut.c','.\main.c','.\phil.c','.\pyrFilt.c','.\pyrGetSz.c','.\quant.c','.\reg0.c','.\reg1.c','.\reg2.c','.\reg3.c','.\regFlt3d.c','.\svdcmp.c') +``` + + * For Linux users: http://www.walkingrandomly.com/?p=2694 +```Matlab +mex('-v', 'GCC="/usr/bin/gcc-4.9"', '-largeArrayDims','CFLAGS="\$CFLAGS -std=c99"','-I.', 'turboreg.c','./BsplnTrf.c','./BsplnWgt.c','./convolve.c','./getPut.c','./main.c','./phil.c','./pyrFilt.c','./pyrGetSz.c','./quant.c','./reg0.c','./reg1.c','./reg2.c','./reg3.c','./regFlt3d.c','./svdcmp.c') + +mex('-v', 'GCC="/usr/bin/gcc-4.9"', '-largeArrayDims','CFLAGS="\$CFLAGS -std=c99"','-I.', 'transfturboreg.c','./BsplnTrf.c','./BsplnWgt.c','./convolve.c','./getPut.c','./main.c','./phil.c','./pyrFilt.c','./pyrGetSz.c','./quant.c','./reg0.c','./reg1.c','./reg2.c','./reg3.c','./regFlt3d.c','./svdcmp.c') +``` + +* Below is an example usage of `turboregMovie`. +* To use imageJ in Matlab, download Fiji () and add Miji.m to your filepath, see . + +### Running turboreg +__Note this input was from 2017.04.19 update__ +```Matlab +% set turboreg options +ioptions.inputDatasetName = '/1'; +ioptions.turboregRotation = 0; +ioptions.RegisType = 1; +ioptions.parallel = 1; +ioptions.meanSubtract = 1; +ioptions.normalizeType = 'bandpass'; % matlabDisk is alternative input. Done on input to turboreg but NOT on final movie. +ioptions.registrationFxn = 'transfturboreg'; +ioptions.normalizeBeforeRegister = 'divideByLowpass'; % set to blank if don't want any filtering on output movie +ioptions.imagejFFTLarge = 10000; +ioptions.imagejFFTSmall = 80; +ioptions.saveNormalizeBeforeRegister = []; +ioptions.cropCoords = []; +ioptions.closeMatlabPool = 0; +ioptions.refFrame = 1; +ioptions.refFrameMatrix = []; + +% load the movie and run turboreg +inputMovieMatrix = loadMovieList('data\2014_04_01_p203_m19_check01\concat_recording_20140401_180333.h5'); +regMovie = turboregMovie(inputMovieMatrix,'options',ioptions); + +% or run turboreg function by loading movie directly within function +regMovie = turboregMovie('pathToDir\filename.h5','options',ioptions); +``` +### Old input +```Matlab +ioptions.inputDatasetName = '/1'; +ioptions.turboregRotation = 1; +ioptions.RegisType = 1; +ioptions.parallel = 1; +ioptions.meanSubtract = 1; +ioptions.normalizeType = 'divideByLowpass'; +ioptions.registrationFxn = 'transfturboreg'; +ioptions.normalizeBeforeRegister = 'imagejFFT'; +ioptions.imagejFFTLarge = 10000; +ioptions.imagejFFTSmall = 80; +ioptions.saveNormalizeBeforeRegister = []; +ioptions.cropCoords = []; +ioptions.closeMatlabPool = 0; +ioptions.refFrame = 1; +ioptions.refFrameMatrix = []; +regMovie = turboregMovie('pathToDir\filename.h5','options',ioptions); +% OR +regMovie = turboregMovie(inputMovieMatrix,'options',ioptions); +``` \ No newline at end of file diff --git a/docs/docs/help_nwb.md b/docs/docs/help_nwb.md new file mode 100644 index 0000000..c6881a8 --- /dev/null +++ b/docs/docs/help_nwb.md @@ -0,0 +1,41 @@ +# Neurodata Without Borders (NWB) + +NWB is a data standard + +Some movies are larger than the available RAM on users analysis computer. Below are several ways that the underlying functions in `CIAPKG` can be used to analyze large movies. + +https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html + +## Saving NWB + + +```Matlab +% Full path to the movie +saveNeurodataWithoutBorders(cellExtractionImages,{cellExtractionSignals},cellExtractionAlgorithm,nwbFilePath); +``` + +Where `cellExtractionAlgorithm` is the algorithm used, consisting of: +- + +## Loading NWB + + +```Matlab +% Full path to the movie +[inputImages,inputTraces,infoStruct, algorithmStr] = loadNeurodataWithoutBorders(nwbFilePath); +``` + +Outputs mean: +- `inputImages` - 3D or 4D matrix containing cells and their spatial information. +- `inputTraces` - 2D matrix containing trace outputs. +- `infoStruct` - contains information about the file, e.g. the 'description' property that can contain information about the algorithm. +- `algorithmStr` - String of the algorithm name. + +## Using NWB with `signalSorter` + +For manual sorting, users can directly input path to NWB file as below: + +```Matlab +[outImages, outSignals, choices] = signalSorter('pcaica.nwb',[],'inputMovie',inputMoviePath); + +``` \ No newline at end of file diff --git a/docs/docs/img/ciapkg_pipeline.png b/docs/docs/img/ciapkg_pipeline.png new file mode 100644 index 0000000000000000000000000000000000000000..f8faecc3004f220682fb80b3f7fd4e5996ea7bb8 GIT binary patch literal 279452 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 `7yXp^>ll|Is(I#J|M(h_gkDH02pNoW>@ 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

xb+8_#qC9u?pW`o2QJa?e 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 Yzbx0C86&nw-ONg8Yv|o5Q@45iUz~nUT>t<8 literal 0 HcmV?d00001 diff --git a/docs/docs/img/favicon.ico b/docs/docs/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..39e0920eb51a70dff90b2197752e89479bd748cc GIT binary patch literal 4286 zcmeHKF%H8Z3_PZ)Tc^$$`;0!V&*@M2Mx~Bj`hZHVk%~A)A`!$%MFi0$<^Z2X%-zGwYhZd{k#oHh9+`bWH;HQ;=@ ze!7=jm#yq2^|y$zHT|0NK3>ChE6soGtES(wKF4lhm)74xlYO+HUvtK$)|BQy<*R0_ zHGPiP+HT?eS?A3Dw#uJ%ayG|hZRa$Zx7K8Ttdp~Oez*Vr@2Oi5+xs9AAzoQ8H$I1Wz literal 0 HcmV?d00001 diff --git a/docs/docs/index.md b/docs/docs/index.md index 2ae31d9..43a1cf5 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -5,6 +5,8 @@ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/bahanonu/calciumImagingAnalysis?style=flat-square&logo=appveyor)](https://github.com/bahanonu/calciumImagingAnalysis/releases/latest?style=flat-square&logo=appveyor) ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/bahanonu/calciumImagingAnalysis?style=flat-square&logo=appveyor) [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg?style=flat-square)](https://github.com/bahanonu/calciumImagingAnalysis/graphs/commit-activity?style=flat-square&logo=appveyor) +![visitors](https://visitor-badge.glitch.me/badge?page_id=bahanonu.calciumImagingAnalysis) +![Hits](https://hitcounter.pythonanywhere.com/count/tag.svg?url=https%3A%2F%2Fgithub.com%2Fbahanonu%2FcalciumImagingAnalysis) @@ -14,14 +16,25 @@ Created by __Biafra Ahanonu, PhD__. `{{ site.name }}` (pronounced cheetah, formerly `calciumImagingAnalysis` [`CIAPKG`]) is a software package for analysis of one- and two-photon calcium imaging datasets. -__Download the software at [https://github.com/bahanonu/calciumImagingAnalysis](https://github.com/bahanonu/calciumImagingAnalysis).__ +__Download the software at [https://github.com/bahanonu/ciatah](https://github.com/bahanonu/ciatah).__ CIAtah_logo - This user guide contains instructions to setup, run, and troubleshoot `{{ site.name }}`. - Note: `{{ site.name }}` is a class (`{{ site.namelow }}` within MATLAB) with various GUIs to allow processing of calcium imaging data. In addition, users can access the underlying `{{ site.name }}` functions to make custom workflows. See [Custom command-line pipelines](api_example_pipeline.md). + +## Guides + +Below are recordings for users who want to learn more about calcium imaging analysis. + - Read my overview of calcium imaging analysis methods at [Calcium imaging cell identification and fluorescence activity trace reconstruction, part 1](https://bahanonu.com/brain/#c20181209). +### Webinar +This webinar gives an overview of calcium imaging analysis (with a focus on CIAtah) along with tips for improving experiments and analysis: https://info.inscopix.com/inscopix-inspire-view-webinarbiafra-ahanonu-signal-in-the-noise-distinguishing-relevant-neural-activity-in-calcium-imaging. + +### Workshop tutorial +This recording gives an overview of setting up and using CIAtah: https://www.youtube.com/watch?v=I6abW3uuJJw. + @@ -54,12 +67,19 @@ __Download the software at [https://github.com/bahanonu/calciumImagingAnalysis]( `{{ site.name }}` features: -- Includes a GUI to allow users to do large-scale batch analysis, accessed via the repository's `{{ site.name }}` class. -- The underlying functions can also be used to create GUI-less, command line-ready analysis pipelines. Functions located in `ciapkg` and `+ciapkg` sub-folders. -- Includes all major calcium imaging analysis steps: pre-processing (motion correction, spatiotemporal downsampling, spatial filtering, relative fluorescence calculation, etc.), support for multiple cell-extraction methods, automated cell classification (coming soon!), cross-session cell alignment, and more. -- Has several example one- and two-photon calcium imaging datasets that it will automatically download to help users test out the package. -- Includes code for determining animal position (e.g. in open-field assay). -- Supports [Neurodata Without Borders](https://www.nwb.org/) data standard (see [calcium imaging tutorial](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html)) for reading/writing cell-extraction (e.g. outputs of PCA-ICA, CELLMax, CNMF, CNMF-E, etc.). Supports reading and writing NWB movie files with continued integration with NWB planned. +- A GUI with different modules for large-scale batch analysis. +- `CIAtah` functions (in `ciapkg`/`+ciapkg` folders) can be used to create GUI-less, command line-ready analysis pipelines. +- Includes all major calcium imaging analysis steps: + - movie visualization (including reading from disk, for fast viewing of large movies) + - pre-processing (motion correction, spatiotemporal downsampling, spatial filtering, relative fluorescence calculation, etc.) + - support for multiple cell-extraction methods (CELLMax, PCA-ICA, CNMF, CNMF-E, EXTRACT, etc.) + - manual classification of cells via GUIs, + - automated cell classification (i.e. CLEAN algorithm, coming soon!), + - cross-session cell alignment, and more. +- Includes example one- and two-photon calcium imaging datasets for testing `ciatah`. +- Supports a plethora of major imaging movie file formats: HDF5, NWB, AVI, ISXD [Inscopix], TIFF, and [Bio-Formats](https://www.openmicroscopy.org/bio-formats/) compatible formats (Olympus [OIR] and Zeiss [CZI and LSM] currently, additional support to be added or upon request). +- Supports [Neurodata Without Borders](https://www.nwb.org/) data standard (see [calcium imaging tutorial](https://neurodatawithoutborders.github.io/matnwb/tutorials/html/ophys.html)) for reading/writing cell-extraction and imaging movie files. +- Animal position tracking (e.g. in open-field assay). - Requires `MATLAB`. ![ciapkg_pipeline.png](img/ciapkg_pipeline.png) diff --git a/docs/docs/install.md b/docs/docs/install.md index 66c5236..adfee5d 100644 --- a/docs/docs/install.md +++ b/docs/docs/install.md @@ -1,12 +1,28 @@ -## Quick start guide +# Quick start guide Below are steps needed to quickly get started using the `{{ site.name }}` software package in MATLAB. -- Clone the `{{ site.name }}` repository (using [GitHub desktop](https://desktop.github.com/) or command line) or download the repository zip and unzip. +## Install +- Clone the `{{ site.name }}` repository (using [GitHub desktop](https://desktop.github.com/) or command line) or download the repository zip and unzip (e.g. run below MATLAB command). - Point the MATLAB path to the `{{ site.name }}` root folder (*NOT* `@{{ code.mainclass }}` sub-folder in the repository). - Alternatively, download the package from `File Exchange` using the Add-Ons explorer in MATLAB. See `{{ site.name }}` entry at: [![View {{ site.name }} on File Exchange](https://www.mathworks.com/matlabcentral/images/matlab-file-exchange.svg)](https://www.mathworks.com/matlabcentral/fileexchange/75466-calciumimaginganalysis) or https://www.mathworks.com/matlabcentral/fileexchange/75466-calciumimaginganalysis. -- Run the below MATLAB commands. + + ```Matlab + % Optional: this will set MATLAB working folder to the default user path. Make sure you have read/write permissions. + try; cd(userpath); catch; end; + + % Download and unzip current repository + unzip('https://github.com/bahanonu/{{ code.mainclass }}/archive/master.zip'); + + % Make CIAtah the working folder + cd('{{ code.mainclass }}-master') + ``` + + +## Setup `{{ site.name }}` + +- Run `{{ site.name }}` using the below MATLAB commands. Call `obj;` in the MATLAB command window each time you want to go back to the main GUI. __Note: `calciumImagingAnalysis` class is now called `ciatah`, all functionality is the same.__ ```MATLAB % Run these commands in MATLAB to get started. @@ -25,7 +41,7 @@ obj % then hit enter, no semicolon! - [Optional] Users on Windows systems should download `Everything` (https://www.voidtools.com/). It is a very useful and extremely fast search engine for files and folders on a computer that can allow users to quickly get lists of folders then need to analyze in `{{ site.name }}`. - [Optional] Users who want to run analysis via the command line can run `edit ciapkg.demo.cmdLinePipeline` and run each segment of code there to see what commands are needed to perform each step. It assumes you have already run `example_downloadTestData`. -### `{{ site.name }}` main GUI notes +## `{{ site.name }}` main GUI notes - All main decisions for choosing a method/procedure to run, cell-extraction algorithm, and which folders to analyze are in a single window. - The GUI will real-time update the selected folders based on the selections in the subject, assay, and folder filter areas. - Sections not relevant for a specific method are grayed out. @@ -42,7 +58,7 @@ __Certain sections become available when user selects the appropriate method (e. image -### Additional quick start notes +## Additional quick start notes - See additional details in [Processing calcium imaging data](#processing-calcium-imaging-data) for running the full processing pipeline. - Settings used to pre-process imaging movies (`modelPreprocessMovie` module) are stored inside the HDF5 file to allow `{{ site.name }}` to load them again later. diff --git a/docs/docs/install_alt.md b/docs/docs/install_alt.md new file mode 100644 index 0000000..9aebdac --- /dev/null +++ b/docs/docs/install_alt.md @@ -0,0 +1,19 @@ +# Installation + +Note, this is an alternative method of installation to that outlined in [Quick Start](install.md). + +Clone the `{{ site.name }}` repository or download the repository zip and unzip. + +- Point the MATLAB path to the `{{ site.name }}` folder. +- Run `loadBatchFxns.m` before using functions in the directory. This adds all needed directories and sub-directories to the MATLAB path. +- Type `obj = {{ code.mainclass }};` into MATLAB command window and follow instructions that appear after to add data and run analysis. +- Run the `{{ code.mainclass }}` class method `loadDependencies` or type `obj.loadDependencies` after initializing a `{{ code.mainclass }}` object into the command window to download and add Fiji to path, download CNMF/CNMF-E repositories, download/setup CVX (for CNMF/CNMF-E), and download example data. + +Note + +- Place `{{ site.name }}` in a folder where MATLAB will have write permissions, as it also creates a `private` subdirectory to store some user information along with downloading required external software packages. +- `file_exchange` folder contains File Exchange functions used by `{{ site.name }}`. +- In general, it is best to set the MATLAB startup directory to the `{{ site.name }}` folder. This allows `java.opts` and `startup.m` to set the correct Java memory requirements and load the correct folders into the MATLAB path. +- If `{{ site.name }}` IS NOT the startup folder, place `java.opts` wherever the MATLAB startup folder is so the correct Java memory requirements are set (important for using ImageJ/Miji in MATLAB). +- If it appears an old `{{ site.name }}` repository is loaded after pulling a new version, run `restoredefaultpath` and check that old `{{ site.name }}` folders are not in the MATLAB path. + \ No newline at end of file diff --git a/docs/docs/install_gui_notes.md b/docs/docs/install_gui_notes.md new file mode 100644 index 0000000..f9e1c0b --- /dev/null +++ b/docs/docs/install_gui_notes.md @@ -0,0 +1,40 @@ +# Additional quick start notes + +- See additional details on the [Processing calcium imaging data](https://bahanonu.github.io/ciatah/pipeline_overview/) page for running the full processing pipeline. +- Settings used to pre-process imaging movies (`modelPreprocessMovie` module) are stored inside the processed HDF5 movie to allow `CIAtah` to load them again later. +- To force load all directories, including most external software packages (in `_external_programs` folder), type `ciapkg.loadAllDirs;` into MATLAB command line. This is most relevant when you need to access specific functions in an outside repository that are normally hidden until needed. +- When issues are encountered, first check the [Common issues and fixes](https://bahanonu.github.io/ciatah/help_issues/) page to see if a solution is there. Else, submit a new issue or email Biafra. +- There are two sets of test data that are downloaded: + - __Single session analysis__: `data\2014_04_01_p203_m19_check01_raw` can be used to test the pipeline until the cross-session alignment step. + - __Batch analysis__: `data\batch` contains three imaging sessions that should be processed and can then be used for the cross-session alignment step. Users should try these sessions to get used to batched analysis. +- For Fiji dependency, when path to `Miji.m` (e.g. `\Fiji.app\scripts` folder) is requested, likely in `[CIAtah directory]\_external_programs\FIJI_FOLDER\Fiji.app\scripts` where `FIJI_FOLDER` varies depending on OS, unless the user requested a custom path or on OSX (in which case, find Fiji the install directory). + - If you run into Java heap space memory errors when Miji tries to load Fiji in MATLAB, make sure "java.opts" file is in MATLAB start-up folder or that the `CIAtah` root folder is the MATLAB start-up folder ([instructions on changing](https://www.mathworks.com/help/matlab/matlab_env/matlab-startup-folder.html)). +- `CIAtah` often uses [regular expressions](https://www.cheatography.com/davechild/cheat-sheets/regular-expressions/) to find relevant movie and other files in folders to analyze. + - For example, by default it looks for any movie files in a folder containing `concat`, e.g. `concat_recording_20140401_180333.h5` (test data). If you have a file called `rawData_2019_01_01_myInterestingExperiment.avi` and all your raw data files start with `rawData_` then change the regular expression to `rawData_` when requested by the repository. See `setMovieInfo` module to change after adding new folders. +- `CIAtah` generally assumes users have imaging data associated with *one* imaging session and animal in a given folder. Follow folder naming conventions in [Data formats](https://bahanonu.github.io/ciatah/data/#preferred-folder-naming-format) for the best experience. +- External software packages are downloaded into `_external_programs` folder and should be placed there if done manually. + +Users can alternatively run setup as below. +```MATLAB +% Run these commands in MATLAB to get started. + +% Loads all directories +loadBatchFxns; + +% Loads the class into an object for use in this session +obj = ciatah; + +% Download and load dependent software packages into "_external_programs" folder. +% Also download test data into "data" folder. +% Normally only need to one once after first downloading CIAtah package. +obj.loadDependencies; + +% Add folders containing imaging data. +obj.modelAddNewFolders; + +% [optional] Set the names CIAtah will look for in each folder +obj.setMovieInfo; + +% Open class menu to pick module to run. +obj.runPipeline; % then hit enter! +``` diff --git a/docs/docs/pipeline_detailed_all.md b/docs/docs/pipeline_detailed_all.md new file mode 100644 index 0000000..0a9b667 --- /dev/null +++ b/docs/docs/pipeline_detailed_all.md @@ -0,0 +1,20 @@ +# Detailed {{ site.name }} processing pipeline + +The following detailed pipeline assumes you have started a {{ site.name }} object using the below command: + +```Matlab +obj = ciatah; +``` + +This is the one-page version of the guide. Visit the individual pages by using the sidebar at left, can be easier to follow for some. + +{!pipeline_detailed_downsample_raw.md!} +{!pipeline_detailed_preprocess_check.md!} +{!pipeline_detailed_preprocess.md!} +{!pipeline_detailed_modify_movies.md!} +{!pipeline_detailed_signal_extraction.md!} +{!pipeline_detailed_signal_extraction_load.md!} +{!pipeline_detailed_signal_extraction_validation.md!} +{!pipeline_detailed_signal_sorting_manual.md!} +{!pipeline_detailed_signal_region_analysis.md!} +{!pipeline_detailed_cross_session.md!} \ No newline at end of file diff --git a/docs/docs/pipeline_detailed_cross_session.md b/docs/docs/pipeline_detailed_cross_session.md new file mode 100644 index 0000000..e0fc8a8 --- /dev/null +++ b/docs/docs/pipeline_detailed_cross_session.md @@ -0,0 +1,33 @@ +--- +title: Cross-session cell alignment. +--- + +# Cross-session cell alignment with `computeMatchObjBtwnTrials` + +This step allows users to align cells across imaging sessions (e.g. those taken on different days). See the `Cross session cell alignment` wiki page for more details and notes on cross-session alignment. + +- Users run `computeMatchObjBtwnTrials` to do cross-day alignment (first row in pictures below). +- Users then run `viewMatchObjBtwnSessions` to get a sense for how well the alignment ran. +- `computeCellDistances` and `computeCrossDayDistancesAlignment` allow users to compute the within session pairwise Euclidean centroid distance for all cells and the cross-session pairwise distance for all global matched cells, respectively. + +![image](https://user-images.githubusercontent.com/5241605/49835713-eec88900-fd54-11e8-8d24-f7c426802297.png) + +Users can then get the matrix that gives the session IDs + +```Matlab +% 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 cross-session cell alignment with `viewMatchObjBtwnSessions` + +To evaluate how well cross-session alignment works, `computeMatchObjBtwnTrials` will automatically run `viewMatchObjBtwnSessions` at the end, but users can also run it separately after alignment. The left are raw dorsal striatum cell maps from a single animal. The right shows after cross-session alignment; color is used to indicate a global ID cell (e.g. the same cell matched across multiple days). Thus, same color cell = same cell across sessions. + +2017_05_02_p545_m121_p215_raw +2017_05_02_p545_m121_p215_corrected_biafraalgorithm2 + +## Save cross-session cell alignment with `modelSaveMatchObjBtwnTrials` + +Users can save out the alignment structure by running `modelSaveMatchObjBtwnTrials`. This will allow users to select a folder where `{{ site.name }}` will save a MAT-file with the alignment structure information for each animal. \ No newline at end of file diff --git a/docs/docs/pipeline_detailed_downsample_raw.md b/docs/docs/pipeline_detailed_downsample_raw.md new file mode 100644 index 0000000..0b1a049 --- /dev/null +++ b/docs/docs/pipeline_detailed_downsample_raw.md @@ -0,0 +1,30 @@ +--- +title: Spatially downsample raw movies or convert to HDF5 +--- + +# Spatially downsample raw movies or convert to HDF5 with `modelDownsampleRawMovies` + +Users have the ability to spatially downsample raw movies, often necessary to denoise the data, save storage space, and improve runtimes of later processing steps. For most data, users can downsample 2 or 4 times in each spatial dimension while still retaining sufficient pixels per cell to facilitate cell-extraction. + +To run, either select `modelDownsampleRawMovies` in the GUI menu or type the below command after initializing a {{ site.name }} obj. + +```Matlab +obj.modelDownsampleRawMovies; +``` + +This will pop-up the following screen. Users can +- input several folders where ISXD files are by separating each folder path with a comma (`Folder(s) where raw HDF5s are located`), +- specify a common root folder to save files to (`Folder to save downsampled HDF5s to:`), +- and input a root directory that contains the sub-folders with the raw data (`Decompression source root folder(s)`). +The function will automatically put each file in its corresponding folder, __make sure folder names are unique__ (this should be done anyways for data analysis reasons). + +![image](https://user-images.githubusercontent.com/5241605/67715130-71b2fc00-f986-11e9-970e-9d1252c25db8.png) + + +## Converting Inscopix ISXD files to HDF5 + +To convert from Inscopix ISXD file format (output by nVista v3+ and nVoke) to HDF5 run `modelDownsampleRawMovies` without changing the regular expression or make sure it looks for `.*.isxd` or similar. Users will need the latest version of the [Inscopix Data Processing Software](https://www.inscopix.com/nVista#Data_Analysis) as these functions take advantage of their API. If {{ site.name }} cannot automatically find the API, it will ask the user to direct it to the _root_ location of the Inscopix Data Processing Software (see below). + +![image](https://user-images.githubusercontent.com/5241605/67715327-df5f2800-f986-11e9-9f91-eeabe7688fed.png) + + \ No newline at end of file diff --git a/docs/docs/pipeline_detailed_modify_movies.md b/docs/docs/pipeline_detailed_modify_movies.md new file mode 100644 index 0000000..beaba21 --- /dev/null +++ b/docs/docs/pipeline_detailed_modify_movies.md @@ -0,0 +1,13 @@ +--- +title: Manual movie cropping. +--- + +# Manual movie cropping with `modelModifyMovies` + +If users need to eliminate specific regions of their movie before running cell extraction, that option is provided. Users select a region using an ImageJ interface and select `done` when they want to move onto the next movie or start the cropping. Movies have `NaNs` or `0s` added in the cropped region rather than changing the dimensions of the movie. + +This is generally advised for movies such as miniature microscope movies imaged through a GRIN lens probe where the outside or edge or the GRIN lens are visible. This can lead to large fluctuations that can throw off some algorithms (e.g. PCA-ICA can end up assigning many components to these "signals"). + +![image](https://user-images.githubusercontent.com/5241605/49829899-8f627d00-fd44-11e8-96fb-2e909b4f0d78.png) + + \ No newline at end of file diff --git a/docs/docs/pipeline_detailed_preprocess.md b/docs/docs/pipeline_detailed_preprocess.md new file mode 100644 index 0000000..bb6b2e4 --- /dev/null +++ b/docs/docs/pipeline_detailed_preprocess.md @@ -0,0 +1,40 @@ +--- +title: Preprocessing calcium imaging movies +--- + +# Preprocessing calcium imaging movies with `modelPreprocessMovie` + +After users instantiate an object of the `{{ site.name }}` class and enter a folder, they can start preprocessing of their calcium imaging data with `modelPreprocessMovie`. + +- See below for a series of windows to get started, the options for motion correction, cropping unneeded regions, Δ_F/F_, and temporal downsampling were selected for use in the study associated with this repository. +- If users have not specified the path to Miji, a window appears asking them to select the path to Miji's `scripts` folder. +- If users are using the test dataset, it is recommended that they do not use temporal downsampling. +- Vertical and horizontal stripes in movies (e.g. CMOS camera artifacts) can be removed via `stripeRemoval` step. Remember to select correct `stripOrientationRemove`,`stripSize`, and `stripfreqLowExclude` options in the preprocessing options menu. + +![image](https://user-images.githubusercontent.com/5241605/49827992-93d86700-fd3f-11e8-9936-d7143bbec3db.png) + +Next the user is presented with a series of options for motion correction, image registration, and cropping.: + +- The options highlighted in green are those that should be considered by users. +- Users can over their mouse over each option to get tips on what they mean. +- In particular, make sure that `inputDatasetName` is correct for HDF5 files and that `fileFilterRegexp` matches the form of the calcium imaging movie files to be analyzed. +- After this, the user is asked to let the algorithm know how many frames of the movie to analyze (defaults to all frames). +- Then the user is asked to select a region to use for motion correction. In general, it is best to select areas with high contrast and static markers such as blood vessels. Stay away from the edge of the movie or areas outside the brain (e.g. the edge of microendoscope GRIN lens in one-photon miniature microscope movies). + +![image](https://user-images.githubusercontent.com/5241605/49828665-4ceb7100-fd41-11e8-9da6-9f5a510f1c13.png) + +## Save/load preprocessing settings + +Users can also enable saving and loading of previously selected pre-processing settings by changing the red option below. + +![image](https://user-images.githubusercontent.com/5241605/70419318-10b52400-1a1a-11ea-9b43-782ac6624042.png) + +Settings loaded from previous run (e.g. of `modelPreprocessMovie`) or file (e.g. from `viewMovieRegistrationTest` runs) are highlighted in orange. Settings that user has just changed are still highlighted in green. + +![image](https://user-images.githubusercontent.com/5241605/70418766-e6169b80-1a18-11ea-9713-f5a8301fe1c1.png) + +The algorithm will then run all the requested preprocessing steps and presented the user with the option of viewing a slice of the processed file. Users have now completed pre-processing. + +![image](https://user-images.githubusercontent.com/5241605/49829599-b53b5200-fd43-11e8-82eb-1e94fd7950e7.png) + + \ No newline at end of file diff --git a/docs/docs/pipeline_detailed_preprocess_check.md b/docs/docs/pipeline_detailed_preprocess_check.md new file mode 100644 index 0000000..b2408a7 --- /dev/null +++ b/docs/docs/pipeline_detailed_preprocess_check.md @@ -0,0 +1,20 @@ +--- +title: Check movie registration before pre-processing +--- + +# Check movie registration before pre-processing with `viewMovieRegistrationTest` + +Users should spatially filter one-photon or other data with background noise (e.g. neuropil). To get a feel for how the different spatial filtering affects SNR/movie data before running the full processing pipeline, run `viewMovieRegistrationTest` module. Then select either `matlab divide by lowpass before registering` or `matlab bandpass before registering` then change `filterBeforeRegFreqLow` and `filterBeforeRegFreqHigh` settings, see below. + +Within each folder will be a sub-folder called `preprocRunTest` inside of which is a series of sub-folders called `preprocRun##` that will contain a file called `settings.mat` that can be loaded into `modelPreprocessMovie` so the same settings that worked during the test can be used during the actual pre-processing run. + +![image](https://user-images.githubusercontent.com/5241605/52497447-f3f65880-2b8a-11e9-8875-c6b408e5c011.png) + +- You'll get an output like the below: + - __A__: The top left is without any filtering while the other 3 are with different bandpass filtering options. + - __B__: Cell ΔF/F intensity profile from the raw movie. Obtain by selecting `Analyze->Plot profile` from Fiji menu after selecting a square segment running through a cell. + - __C__: Same cell ΔF/F intensity profile from the bottom/left movie (note the y-axis is the same as above). Obtained in same manner as __B__. + +![image](https://user-images.githubusercontent.com/5241605/59561146-695ab580-8fd1-11e9-892b-ce1f5fc7800e.png) + + \ No newline at end of file diff --git a/docs/docs/pipeline_detailed_signal_extraction.md b/docs/docs/pipeline_detailed_signal_extraction.md new file mode 100644 index 0000000..c7e4fef --- /dev/null +++ b/docs/docs/pipeline_detailed_signal_extraction.md @@ -0,0 +1,21 @@ +--- +title: Automated cell extraction. +--- + +# Extracting cells with `modelExtractSignalsFromMovie` + +Users can run PCA-ICA, EXTRACT, CNMF, CNMF-E, and ROI cell extraction by following the below set of option screens. Details on running the new Schnitzer lab cell-extraction methods (e.g. CELLMax) will be added here after they are released. + +We normally estimate the number of PCs and ICs on the high end, manually sort to get an estimate of the number of cells, then run PCA-ICA again with IC 1.5-3x the number of cells and PCs 1-1.5x number of ICs. + +To run CNMF or CNMF-E, run `loadDependencies` module (e.g. `obj.loadDependencies`) after {{ site.name }} class is loaded. CVX (a CNMF dependency) will also be downloaded and `cvx_setup` run to automatically set it up. + +![image](https://user-images.githubusercontent.com/5241605/49830421-fa608380-fd45-11e8-8d9a-47a3d2921111.png) + +The resulting output (on _Figure 45+_) at the end should look something like: + +![image](https://user-images.githubusercontent.com/5241605/67053021-fe42fc00-f0f4-11e9-980c-88f463cb5043.png) + + + + diff --git a/docs/docs/pipeline_detailed_signal_extraction_load.md b/docs/docs/pipeline_detailed_signal_extraction_load.md new file mode 100644 index 0000000..dc63639 --- /dev/null +++ b/docs/docs/pipeline_detailed_signal_extraction_load.md @@ -0,0 +1,34 @@ +--- +title: Loading cell extraction data. +--- + +# Loading cell-extraction output data for custom scripts + +Users can load outputs from cell extraction using the below command. This will then allow users to use the images and activity traces for downstream analysis as needed. + +```Matlab +[inputImages,inputSignals,infoStruct,algorithmStr,inputSignals2] = ciapkg.io.loadSignalExtraction('pathToFile'); +``` + +Note, the outputs correspond to the below: + +- `inputImages` - 3D or 4D matrix containing cells and their spatial information, format: [x y nCells]. +- `inputSignals` - 2D matrix containing activity traces in [nCells nFrames] format. +- `infoStruct` - contains information about the file, e.g. the 'description' property that can contain information about the algorithm. +- `algorithmStr` - String of the algorithm name. +- `inputSignals2` - same as inputSignals but for secondary traces an algorithm outputs. + + + +## Loading cell-extraction output data with `modelVarsFromFiles` + +In general, after running cell-extraction (`modelExtractSignalsFromMovie`) on a dataset, run the `modelVarsFromFiles` module. This allows `{{ site.name }}` to load/pre-load information about that cell-extraction run. + +If you had to restart MATLAB or are just loading {{ site.name }} fresh but have previously run cell extraction, run this method before doing anything else with that cell-extraction data. + +A menu will pop-up like below when `modelVarsFromFiles` is loaded, you can normally just leave the defaults as is. + +![image](https://user-images.githubusercontent.com/5241605/67052600-7f00f880-f0f3-11e9-9555-96fe32b4de6d.png) + + + diff --git a/docs/docs/pipeline_detailed_signal_extraction_validation.md b/docs/docs/pipeline_detailed_signal_extraction_validation.md new file mode 100644 index 0000000..4d69977 --- /dev/null +++ b/docs/docs/pipeline_detailed_signal_extraction_validation.md @@ -0,0 +1,13 @@ +--- +title: Validating cell extraction data. +--- + +# Validating cell extraction with `viewCellExtractionOnMovie` + +After users have run cell extraction, they should check that cells are not being missed during the process. Running the method `viewCellExtractionOnMovie` will create a movie with outlines of cell extraction outputs overlaid on the movie. + +Below is an example, with black outlines indicating location of cell extraction outputs. If users see active cells (red flashes) that are not outlined, that indicates either exclusion or other parameters should be altered in the previous `modelExtractSignalsFromMovie` cell extraction step. + +![2014_04_01_p203_m19_check01_raw_viewCellExtractionOnMovie_ezgif-4-57913bcfdf3f_2](https://user-images.githubusercontent.com/5241605/59560798-50033a80-8fcc-11e9-8228-f9a3d83ca591.gif) + + \ No newline at end of file diff --git a/docs/docs/pipeline_detailed_signal_region_analysis.md b/docs/docs/pipeline_detailed_signal_region_analysis.md new file mode 100644 index 0000000..f56140a --- /dev/null +++ b/docs/docs/pipeline_detailed_signal_region_analysis.md @@ -0,0 +1,11 @@ +--- +title: Removing cells not within region of interest. +--- + +# Removing cells not within brain region with `modelModifyRegionAnalysis` + +If the imaging field-of-view includes cells from other brain regions, they can be removed using `modelModifyRegionAnalysis` + +![image](https://user-images.githubusercontent.com/5241605/49834696-e9b60a80-fd51-11e8-90bb-9854b7ccaeb8.png) + + \ No newline at end of file diff --git a/docs/docs/pipeline_detailed_signal_sorting_manual.md b/docs/docs/pipeline_detailed_signal_sorting_manual.md new file mode 100644 index 0000000..539e506 --- /dev/null +++ b/docs/docs/pipeline_detailed_signal_sorting_manual.md @@ -0,0 +1,73 @@ +--- +title: Sorting cell extraction outputs. +--- + +# Sorting cell extraction outputs with `computeManualSortSignals` + +

+ {{ site.name }} cell sorting GUI +

+

+ + ciapkgMovie + +

+ + +Outputs from most common cell-extraction algorithms like PCA-ICA, CNMF, etc. contain signal sources that are not cells and thus must be manually removed from the output. The repository contains a GUI for sorting cells from not cells. GUI also contains a shortcut menu that users can access by right-clicking or selecting the top-left menu. + +Below users can see a list of options that are given before running the code, those highlighted in green + +![image](https://user-images.githubusercontent.com/5241605/49845107-43322f80-fd7a-11e8-96b9-3f870d4b9009.png) + +## GUI usage on large imaging datasets + +- To manually sort on large movies that will not fit into RAM, select the below options (highlighted in green). This will load only chunks of the movie asynchronously into the GUI as you sort cell extraction outputs. +![image](https://user-images.githubusercontent.com/5241605/59215159-5d07d000-8b6d-11e9-8dd7-0d69d5fd38b6.png) + +## Cell sorting from the command line with `signalSorter` + +Usage instructions below for `signalSorter`, e.g. if not using the `{{ site.name }}` GUI. + +__Main inputs__ + +- `inputImages` - [x y N] matrix where N = number of images, x/y are dimensions. +- `inputSignals` - [N frames] _double_ matrix where N = number of signals (traces). +- `inputMovie` - [x y frames] matrix + +__Main outputs__ + +- `choices` - [N 1] vector of 1 = cell, 0 = not a cell +- `inputImagesSorted` - [x y N] filtered by `choices` +- `inputSignalsSorted` - [N frames] filtered by `choice` + +``` Matlab +iopts.inputMovie = inputMovie; % movie associated with traces +iopts.valid = 'neutralStart'; % all choices start out gray or neutral to not bias user +iopts.cropSizeLength = 20; % region, in px, around a signal source for transient cut movies (subplot 2) +iopts.cropSize = 20; % see above +iopts.medianFilterTrace = 0; % whether to subtract a rolling median from trace +iopts.subtractMean = 0; % whether to subtract the trace mean +iopts.movieMin = -0.01; % helps set contrast for subplot 2, preset movie min here or it is calculated +iopts.movieMax = 0.05; % helps set contrast for subplot 2, preset movie max here or it is calculated +iopts.backgroundGood = [208,229,180]/255; +iopts.backgroundBad = [244,166,166]/255; +iopts.backgroundNeutral = repmat(230,[1 3])/255; +[inputImagesSorted, inputSignalsSorted, choices] = signalSorter(inputImages, inputSignals, 'options',iopts); +``` + +Examples of the interface on two different datasets: + +### BLA one-photon imaging data signal sorting GUI + +![out-1](https://user-images.githubusercontent.com/5241605/34796712-3868cb3a-f60b-11e7-830e-8eec5b2c76d7.gif) + +### mPFC one-photon imaging data signal sorting GUI (from `example_downloadTestData.m`) + +![image](https://user-images.githubusercontent.com/5241605/46322488-04c00d80-c59e-11e8-9e8a-18b3b8e4567d.png) + +### Context menu + +drawing + + \ No newline at end of file diff --git a/docs/docs/pipeline_overview.md b/docs/docs/pipeline_overview.md index 70bcc41..bb2676a 100644 --- a/docs/docs/pipeline_overview.md +++ b/docs/docs/pipeline_overview.md @@ -5,6 +5,17 @@ The general pipeline for processing calcium imaging data is below. This reposito ![ciapkg_pipeline.png](img/ciapkg_pipeline.png) +## Guides +Below are recordings for users who want to learn more about calcium imaging analysis. + +### Webinar +This webinar gives an overview of calcium imaging analysis (with a focus on CIAtah) along with tips for improving experiments and analysis: https://info.inscopix.com/inscopix-inspire-view-webinarbiafra-ahanonu-signal-in-the-noise-distinguishing-relevant-neural-activity-in-calcium-imaging. + +### Workshop tutorial +This recording gives an overview of setting up and using CIAtah: https://www.youtube.com/watch?v=I6abW3uuJJw. + +## Workflow + To start using the `{{ site.name }}` software package, enter the following into the MATLAB command window. ```Matlab diff --git a/docs/docs/questions.md b/docs/docs/questions.md index 722f152..eace4cf 100644 --- a/docs/docs/questions.md +++ b/docs/docs/questions.md @@ -1,2 +1,2 @@ -## Questions? +# Questions? Please [open an issue on GitHub](https://github.com/bahanonu/calciumImagingAnalysis/issues) or email any additional questions not covered in the repository to `bahanonu [at] alum.mit.edu`. \ No newline at end of file diff --git a/docs/docs/references.md b/docs/docs/references.md index e355133..34f51d4 100644 --- a/docs/docs/references.md +++ b/docs/docs/references.md @@ -1,4 +1,4 @@ -## References +# References Please cite [Corder*, Ahanonu*, et al. 2019](http://science.sciencemag.org/content/363/6424/276.full) _Science_ publication or the [Ahanonu, 2018](https://doi.org/10.5281/zenodo.2222294) _Zenodo_ release if you used the software package or code from this repository to advance/help your research: diff --git a/docs/make_docs.py b/docs/make_docs.py index 12fceab..e0414f7 100644 --- a/docs/make_docs.py +++ b/docs/make_docs.py @@ -4,9 +4,12 @@ # Changelog # 2020.09.28 [22:35:51] - Added ssl module. # 2020.09.28 [22:42:51] - Added support to automatically install missing packages. Disabled as user should do this. + # 2021.04.05 [16:12:12] - Since all_docs uses includes, yaml extra variables are not evaluated. This is a quick way to replace them. import subprocess import sys +from bs4 import BeautifulSoup +import re # import socket # import ssl @@ -20,10 +23,39 @@ # pip install mdx_truly_sane_lists # pip install pymdown-extensions # pip install mkdocs-macros-plugin +# pip install mkdocs-markdownextradata-plugin +# pip install markdown-include # If you want to view the docs before building # mkdocs serve # Build the documents # mkdocs build -subprocess.check_call([sys.executable, "-m", "mkdocs", "build"]) \ No newline at end of file +subprocess.check_call([sys.executable, "-m", "mkdocs", "build"]) + + +# Since all_docs uses includes, yaml extra variables are not evaluated. This is a quick way to replace them. +f = open('site/all_docs/index.html','r') +html = f.read() +f.close() +soup = BeautifulSoup(html) + +extraDict = { + '{{ site.name }}': 'CIAtah', + '{{ site.namelow }}': 'ciatah', + '{{ site.nameold }}': 'calciumImagingAnalysis', + '{{ code.mainclass }}': 'ciatah', + '{{ code.mainclass }}': 'ciatah' +} +for key in extraDict: + target = soup.find_all(text=re.compile(re.escape(key))) + # target = soup.find_all(text=re.compile(r'{{ site.name }}')) + for v in target: + v.replace_with(v.replace(key,extraDict[key])) + +# print soup +f = open('site/all_docs/index.html','w') +soup_string = str(soup) +soup_string = soup_string.replace('{{ code.mainclass }}', 'ciatah') +f.write(soup_string) +f.close() \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index effd537..e039b1e 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -1,4 +1,5 @@ site_name: CIAtah +site_author: Biafra Ahanonu # For online, to end in /data instead of /data.html use_directory_urls: true theme: @@ -21,6 +22,8 @@ theme: - navigation.expand plugins: - macros + # - search + # - markdownextradata: {} markdown_extensions: - toc: permalink: true @@ -30,6 +33,14 @@ markdown_extensions: - pymdownx.highlight - pymdownx.superfences - pymdownx.inlinehilite + - pymdownx.snippets: + base_path: docs + - markdown_include.include: + base_path: docs + # headingOffset: 0 + headingOffset: 1 + # inheritHeadingDepth: True + # inheritHeadingDepth: False - pymdownx.highlight: linenums: true linenums_style: pymdownx-inline @@ -56,11 +67,14 @@ extra: nameold: calciumImagingAnalysis code: mainclass: ciatah + package: ciapkg # NAVIGATION nav: - Home: index.md - - One-page readme: alldocs.md + - End-to-end: + # - One-page readme: alldocs.md + - One-page readme: all_docs.md - Setup: - Quick Start: install.md - Install: install_alt.md @@ -70,23 +84,35 @@ nav: - Data formats: data.md - Notes: notes.md - Organization: organization.md - - Processing data: - - Overview: pipeline_overview.md - - Step-by-step: pipeline_detailed.md - - Animal tracking: pipeline_animal_tracking.md + - Processing imaging data: + - Overview: pipeline_overview.md + # - Step-by-step: pipeline_detailed.md + - One-page step-by-step: pipeline_detailed_all.md + - 1| Downsample raw movies: pipeline_detailed_downsample_raw.md + - 2| Check pre-process settings: pipeline_detailed_preprocess_check.md + - 3| Processing imaging movies: pipeline_detailed_preprocess.md + - 4| Movie clean-up: pipeline_detailed_modify_movies.md + - 5| Cell extraction: pipeline_detailed_signal_extraction.md + - 6| Loading cell extraction outputs: pipeline_detailed_signal_extraction_load.md + - 7| Cell extraction validation: pipeline_detailed_signal_extraction_validation.md + - 8| Manual cell sorting: pipeline_detailed_signal_sorting_manual.md + - 9| Region-specific analysis: pipeline_detailed_signal_region_analysis.md + - 10| Cross-session alignment: pipeline_detailed_cross_session.md + - Animal tracking: + - Animal tracking (ImageJ+MATLAB): pipeline_animal_tracking.md - API: - Custom pipelines: api_example_pipeline.md - ciapkg: api_ciapkg.md - Help: - Issues and fixes: help_issues.md - -
Data
: index.md + -
Data
: blank.md - Inscopix: help_inscopix.md - Neurodata Without Borders: help_nwb.md - -
Interface
: index.md + -
Interface
: blank.md - Movie display and noise: help_contrast.md - -
Analysis
: index.md + -
Analysis
: blank.md - Analysis methods: help_analysis_methods.md - Large movie analysis: help_large_movie_analysis.md - Stripe removal: help_stripe_removal.md From 56794a722df6eb6aab64ccc82c0edf2a2c2e063b Mon Sep 17 00:00:00 2001 From: Biafra Ahanonu Date: Mon, 21 Jun 2021 16:46:25 -0700 Subject: [PATCH 3/4] Updates --- +ciapkg/+io/loadDependencies.m | 6 +++--- @ciatah/viewMovieRegistrationTest.m | 1 + ciapkg/image/cropMatrix.m | 2 +- ciapkg/io/loadMovieList.m | 2 +- loadBatchFxns.m | 1 + 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/+ciapkg/+io/loadDependencies.m b/+ciapkg/+io/loadDependencies.m index d69b928..9475e6c 100644 --- a/+ciapkg/+io/loadDependencies.m +++ b/+ciapkg/+io/loadDependencies.m @@ -24,11 +24,11 @@ function loadDependencies(varargin) % DESCRIPTION options.externalProgramsDir = ciapkg.getDirExternalPrograms(); options.guiEnabled = 1; - options.dependencyStr = {'downloadMiji','downloadCnmfGithubRepositories','example_downloadTestData','loadMiji','downloadNeuroDataWithoutBorders','downloadEXTRACT','downloadBioFormats','downloadImageJ'}; + options.dependencyStr = {'downloadImageJ','downloadCnmfGithubRepositories','example_downloadTestData','downloadNeuroDataWithoutBorders','downloadEXTRACT','downloadBioFormats','downloadMiji','loadMiji'}; - options.dispStr = {'Download Fiji (to run Miji)','Download CNMF, CNMF-E, and CVX code.','Download test one- and two photon datasets.','Load Fiji/Miji into MATLAB path.','Download NWB (NeuroDataWithoutBorders)','Download EXTRACT','Download Bio-Formats','Download ImageJ'}; + options.dispStr = {'Download ImageJ','Download CNMF, CNMF-E, and CVX code.','Download test one- and two photon datasets.','Download NWB (NeuroDataWithoutBorders)','Download EXTRACT','Download Bio-Formats','Download Fiji (to run Miji)','Load Fiji/Miji into MATLAB path.'}; % Int vector: index of options.dependencyStr to run by default with no GUI - options.depIdxArray = [2 3 5 6 7 8]; + options.depIdxArray = [1 2 3 4 5 6]; % Binary: 1 = force update even if already downloaded. 0 = skip if already downloaded options.forceUpdate = 0; % get options diff --git a/@ciatah/viewMovieRegistrationTest.m b/@ciatah/viewMovieRegistrationTest.m index 34a96ec..2efcbab 100644 --- a/@ciatah/viewMovieRegistrationTest.m +++ b/@ciatah/viewMovieRegistrationTest.m @@ -13,6 +13,7 @@ % 2019.12.08 [23:33:25] - Save out settings structure to allow users to load it in again later for actual pre-processing. % 2020.05.13 [07:57:06] - Added a warning and check that the reference frame requested is outside bounds of input movie. % 2020.06.18 [12:38:34] - Add support for stripe removal same as modelPreprocessMovie + % 2021.06.18 [21:41:07] - Added modelVarsFromFilesCheck() to check and load signals if user hasn't already. % TODO % diff --git a/ciapkg/image/cropMatrix.m b/ciapkg/image/cropMatrix.m index 0fd96c3..84aff21 100644 --- a/ciapkg/image/cropMatrix.m +++ b/ciapkg/image/cropMatrix.m @@ -8,7 +8,7 @@ % inputMatrix - cropped or NaN'd matrix, same name to reduce memory usage % changelog % 2017.01.14 [20:06:04] - support switched from [nSignals x y] to [x y nSignals]. - % 2021.04.18 [14:42:53] - Updated to make imrect the default method of selecting the coordinates + % 2021.04.18 [14:42:53] - Updated to make imrect the default method of selecting the coordinates. % TODO % diff --git a/ciapkg/io/loadMovieList.m b/ciapkg/io/loadMovieList.m index 116898a..51dab4b 100644 --- a/ciapkg/io/loadMovieList.m +++ b/ciapkg/io/loadMovieList.m @@ -50,7 +50,7 @@ % 2020.08.31 [15:47:49] - Add option to suppress warnings. % 2020.10.19 [12:11:14] - Improved comments and options descriptions. % 2021.02.15 [11:55:36] - Fixed loading HDF5 datasetname that has only a single frame, loadMovieList would ask for 3rd dimension information that did not exist. - % 2021.06.21 [10:22:32] - Added support for Bio-Formats compatible files, specifically Olympus (OIR) and Zeiss () + % 2021.06.21 [10:22:32] - Added support for Bio-Formats compatible files, specifically Olympus (OIR) and Zeiss (CZI, LSM). % TODO % OPEN diff --git a/loadBatchFxns.m b/loadBatchFxns.m index 37284ad..975d8c4 100644 --- a/loadBatchFxns.m +++ b/loadBatchFxns.m @@ -21,6 +21,7 @@ function loadBatchFxns(varargin) % 2020.06.05 [23:35:43] - If user doesn't have Parallel Toolbox, still works % 2020.07.21 [14:11:42] - Fix to make sure all sub-folders (not just the root) are also removed in the case of certain external_programs. % 2021.02.01 [‏‎15:19:40] - Update `_external_programs` to call ciapkg.getDirExternalPrograms() to standardize call across all functions. + % 2021.06.20 [00:22:38] - Added manageMiji('startStop','closeAllWindows'); support. % TODO % From e97e4505a2b789518576e2cfd57fe0adf5c95c19 Mon Sep 17 00:00:00 2001 From: Biafra Ahanonu Date: Mon, 21 Jun 2021 21:16:06 -0700 Subject: [PATCH 4/4] Update --- +ciapkg/+io/loadDependencies.m | 1 + @ciatah/computeManualSortSignals.m | 9 +++-- @ciatah/getRegistrationSettings.m | 47 ++++++++++++++++++++------ @ciatah/modelPreprocessMovieFunction.m | 14 ++++---- @ciatah/modelVarsFromFilesCheck.m | 3 +- @ciatah/viewCellExtractionOnMovie.m | 5 +-- 6 files changed, 55 insertions(+), 24 deletions(-) diff --git a/+ciapkg/+io/loadDependencies.m b/+ciapkg/+io/loadDependencies.m index 9475e6c..9689590 100644 --- a/+ciapkg/+io/loadDependencies.m +++ b/+ciapkg/+io/loadDependencies.m @@ -17,6 +17,7 @@ function loadDependencies(varargin) % 2021.02.01 [‏‎15:19:40] - Update `_external_programs` to call ciapkg.getDirExternalPrograms() to standardize call across all functions. % 2021.03.20 [18:12:20] - Added EXTRACT support to list of functions to download. % 2021.06.19 [23:46:58] - Switched to support for original MIJ calling of ImageJ using just jar files, easier compatibility across MATLAB versions and OSes. + % 2021.06.21 [16:45:59] - Update order. % TODO % Verify all dependencies download and if not ask user to download again. diff --git a/@ciatah/computeManualSortSignals.m b/@ciatah/computeManualSortSignals.m index 065d6eb..8f807e9 100644 --- a/@ciatah/computeManualSortSignals.m +++ b/@ciatah/computeManualSortSignals.m @@ -14,6 +14,7 @@ % 2021.01.21 [10:37:07] - Updated to support HDF5 and regexp for movie manual names along with misc. other changes. % 2021.03.17 [16:34:59] - If user hasn't called modelVarsFromFiles, computeManualSortSignals called the function. However, this lead to a mismatch between computeManualSortSignals fileNum and obj.fileNum, leading to mismatch between xcoords, etc. and input signals/images. % 2021.06.18 [21:41:07] - added modelVarsFromFilesCheck() to check and load signals if user hasn't already. + % 2021.06.21 [21:03:25] - Fix check to make sure variables are loaded. % ADDED % ADD PERSONS NAME TO THE FILE - DONE. % TODO @@ -42,9 +43,6 @@ % fileNum = obj.fileNum; display(repmat('#',1,21)) display([num2str(thisFileNumIdx) '/' num2str(nFilesToAnalyze) ' (' num2str(obj.fileNum) '/' num2str(nFiles) '): ' obj.fileIDNameArray{obj.fileNum}]); - - % Check that signal extraction information is loaded. - obj.modelVarsFromFilesCheck(fileNum); % ======= % path to current folder currentFolderPath = obj.inputFolders{obj.fileNum}; @@ -99,6 +97,11 @@ % usrIdxChoiceSettings = settingStruct.usrIdxChoiceSettings; end + + % Check that signal extraction information is loaded. + obj.modelVarsFromFilesCheck(fileNum); + skipReload = 0; + % get list of movies movieList = getFileList(currentFolderPath, fileFilterRegexp); if strcmp(usrIdxChoiceMovie,'load movie') diff --git a/@ciatah/getRegistrationSettings.m b/@ciatah/getRegistrationSettings.m index 25b79b6..e6e2ce4 100644 --- a/@ciatah/getRegistrationSettings.m +++ b/@ciatah/getRegistrationSettings.m @@ -19,6 +19,7 @@ % 2020.10.21 [16:52:06] - Add support for user canceling the input. % 2020.10.24 [18:30:56] - Added support for calculating dropped frames if entire frame of a movie is a set value. % 2021.06.21 [14:27:26] - Switch to single page support. + % 2021.06.21 [20:52:36] - Multi-column layout since most computers are widescreen now. % TODO % DONE: Allow user to input prior settings, indicate those changed from default by orange or similar color. @@ -338,20 +339,22 @@ % propertySettingsStr.(property); end - modX = 1.55; - modX_text = 2; + modX = 1.05; + modX_text = 1.1; figNoDefault = 1337; uiListHandles = {}; uiTextHandles = {}; uiXIncrement = 0.025/modX; uiXOffset = 0.02/modX; uiYOffset = 0.90; + uiYOffsetOrig = uiYOffset; uiTxtSize = 0.4; uiBoxSize = 0.55; uiFontSize = 9; nGuiSubsets = 3; % subsetList = round(linspace(1,nPropertiesToChange,nGuiSubsets)); subsetList = [1 35 nPropertiesToChange]; + propNoSwitch = 36; % subsetList % for subsetNo = 1:nGuiSubsets nGuiSubsetsTrue = (nGuiSubsets-1); @@ -375,31 +378,55 @@ propertySubsetList = subsetStartIdx:(subsetEndIdx-1); end - [figHandle figNo] = openFigure(figNoDefault, ''); clf uicontrol('Style','Text','String',inputTitleStr,'Units','normalized','Position',[uiXOffset uiYOffset+0.05 0.8 0.05],'BackgroundColor','white','HorizontalAlignment','Left','FontSize',uiFontSize); uicontrol('Style','Text','String',sprintf('Options page %d/%d: Mouse over each options for tips. To continue, press enter. Orange = previous non-default settings.\n>>>On older MATLAB versions, select the command window before pressing enter.',thisSet,nGuiSubsets-1),'Units','normalized','Position',[uiXOffset uiYOffset+0.02 uiTxtSize+uiBoxSize 0.05],'BackgroundColor','white','HorizontalAlignment','Left','FontSize',uiFontSize); - propertyNoDisp = 1; + propNoDisp = 1; for propertyNo = propertySubsetList property = char(propertyList(propertyNo)); % propertyTooltip = turboregSettingTooltips.(property); propertyTooltip = char(preprocessingSettingsAll.(property).tooltip{1}); + + if propertyNo==propNoSwitch + propNoDisp = 1; + uiYOffset = uiYOffsetOrig; + end + if propertyNo>=propNoSwitch + colNo = 49/100; + uiTxtSize = 0.4/2; + uiBoxSize = 0.55/2; + else + colNo = 0/100; + uiTxtSize = 0.4/2; + uiBoxSize = 0.55/2; + end + % disp([num2str(propertyNo) ' | ' property]) - if propertyNo~=1 + if isempty(intersect(propertyNo,[1,propNoSwitch])) if isempty(regexp(property,'______________')) spaceMod = 0.00; FontWeightH = 'normal'; else - spaceMod = 0.01; + spaceMod = 0.02; uiYOffset = uiYOffset-spaceMod; FontWeightH = 'bold'; end else FontWeightH = 'bold'; end - uiTextHandles{propertyNo} = uicontrol('Style','text','String',[property '' 10],'Units','normalized','Position',[uiXOffset uiYOffset-uiXIncrement*propertyNoDisp+modX_text*(0.027/modX) uiTxtSize 0.0225/modX],'BackgroundColor',[0.9 0.9 0.9],'ForegroundColor','black','HorizontalAlignment','Left','FontSize',uiFontSize,'ToolTip',propertyTooltip,'FontWeight',FontWeightH); + + textPos = [uiXOffset+colNo uiYOffset-uiXIncrement*propNoDisp+modX_text*(0.027/modX) uiTxtSize 0.0225/modX]; + uiTextHandles{propertyNo} = uicontrol('Style','text','String',[property '' 10],'Units','normalized',... + 'Position',textPos,... + 'BackgroundColor',[0.9 0.9 0.9],'ForegroundColor','black','HorizontalAlignment','Left','FontSize',uiFontSize,'ToolTip',propertyTooltip,'FontWeight',FontWeightH); + + listPos = [uiXOffset+uiTxtSize+colNo uiYOffset-uiXIncrement*propNoDisp uiBoxSize 0.05]; + uiListHandles{propertyNo} = uicontrol('Style', 'popup','String', propertySettingsStr.(property),'Units','normalized',... + 'Position', listPos,... + 'Callback',@subfxnInterfaceCallback,'FontSize',uiFontSize,'Tag',property); + % jEdit = findjobj(uiTextHandles{propertyNo}); % lineColor = java.awt.Color(1,0,0); % =red % thickness = 3; % pixels @@ -409,17 +436,15 @@ % jEdit.repaint; % redraw the modified control % uiTextHandles{propertyNo}.Enable = 'Inactive'; % optionCallback = ['set(uiListHandles{propertyNo}, ''Backgroundcolor'', ''g'')']; - % uiListHandles{propertyNo} = uicontrol('Style', 'popup','String', propertySettingsStr.(property),'Units','normalized','Position', [uiXOffset+uiTxtSize uiYOffset-uiXIncrement*propertyNoDisp uiBoxSize 0.05],'Callback',@(hObject,callbackdata){set(hObject, 'Backgroundcolor', [208,229,180]/255);},'FontSize',uiFontSize); - uiListHandles{propertyNo} = uicontrol('Style', 'popup','String', propertySettingsStr.(property),'Units','normalized','Position', [uiXOffset+uiTxtSize uiYOffset-uiXIncrement*propertyNoDisp uiBoxSize 0.05],'Callback',@subfxnInterfaceCallback,'FontSize',uiFontSize,'Tag',property); + % uiListHandles{propertyNo} = uicontrol('Style', 'popup','String', propertySettingsStr.(property),'Units','normalized','Position', [uiXOffset+uiTxtSize uiYOffset-uiXIncrement*propNoDisp uiBoxSize 0.05],'Callback',@(hObject,callbackdata){set(hObject, 'Backgroundcolor', [208,229,180]/255);},'FontSize',uiFontSize); % ,'ToolTip',propertyTooltip % If property is non-default, set to orange to alert user. if any(ismember(nonDefaultProperties,property)) set(uiListHandles{propertyNo},'Backgroundcolor',[254 216 177]/255); - end - propertyNoDisp = propertyNoDisp+1; + propNoDisp = propNoDisp+1; end pause uiYOffset = 0.90; diff --git a/@ciatah/modelPreprocessMovieFunction.m b/@ciatah/modelPreprocessMovieFunction.m index ded1682..dd1e575 100644 --- a/@ciatah/modelPreprocessMovieFunction.m +++ b/@ciatah/modelPreprocessMovieFunction.m @@ -277,25 +277,25 @@ ok = 1; [figHandle figNo] = openFigure(1776, '');clf; instructTextPos = [1 80 70 20]/100; - listTextPos = [1 1+32 98 60-32]/100; - listTextPos2 = [1 1 98 60-31]/100; + listTextPos = [1 40 98 28]/100; + listTextPos2 = [1 1 98 28]/100; - shortcutMenuHandle = uicontrol('style','pushbutton','Units','normalized','position',[1 65 30 3]/100,'FontSize',9,'string','Reset to default list order','callback',@subfxn_resetSetpsMenu); - shortcutMenuHandle2 = uicontrol('style','pushbutton','Units','normalized','position',[32 65 30 3]/100,'FontSize',9,'string','Select default options (e.g. post-dragging)','callback',@subfxn_highlightDefault); - shortcutMenuHandle2 = uicontrol('style','pushbutton','Units','normalized','position',[63 65 30 3]/100,'FontSize',9,'string','Finished','callback',@subfxn_closeOptions); + shortcutMenuHandle = uicontrol('style','pushbutton','Units','normalized','position',[1 75 30 3]/100,'FontSize',9,'string','Reset to default list order','callback',@subfxn_resetSetpsMenu); + shortcutMenuHandle2 = uicontrol('style','pushbutton','Units','normalized','position',[32 75 30 3]/100,'FontSize',9,'string','Select default options (e.g. post-dragging)','callback',@subfxn_highlightDefault); + shortcutMenuHandle2 = uicontrol('style','pushbutton','Units','normalized','position',[63 75 30 3]/100,'FontSize',9,'string','Finished','callback',@subfxn_closeOptions); % shortcutMenuHandle = uicontrol('style','pushbutton','Units','normalized','position',[32 62 30 3]/100,'FontSize',9,'string','Next screen','callback',@subfxn_highlightDefault); + uicontrol('Style','Text','String',['Analysis steps to perform.'],'Units','normalized','Position',[1 68 90 3]/100,'BackgroundColor','white','HorizontalAlignment','Left','FontWeight','bold'); [hListbox jListbox jScrollPane jDND] = reorderableListbox('String',analysisOptionListStr,'Units','normalized','Position',listTextPos,'Max',Inf,'Min',0,'Value',defaultChoiceIdx,... 'MousePressedCallback',@subfxn_analysisOutputMenuChange,... 'MouseReleasedCallback',@subfxn_analysisOutputMenuChange,... 'DragOverCallback',@subfxn_analysisOutputMenuChange2,... 'DropCallback',@subfxn_analysisOutputMenuChange... ); - uicontrol('Style','Text','String',['Analysis steps to perform.'],'Units','normalized','Position',[1 62 90 1]/100,'BackgroundColor','white','HorizontalAlignment','Left','FontWeight','bold'); + uicontrol('Style','Text','String',['At which analysis step should files be saved to disk?'],'Units','normalized','Position',[1 30 90 3]/100,'BackgroundColor','white','HorizontalAlignment','Left','FontWeight','bold'); [hListboxS jListboxS jScrollPaneS jDNDS] = reorderableListbox('String',analysisOptionListStr,'Units','normalized','Position',listTextPos2,'Max',Inf,'Min',0,'Value',hListbox.Value(end)); - uicontrol('Style','Text','String',['At which analysis step should files be saved to disk?'],'Units','normalized','Position',[1 30.5 90 1]/100,'BackgroundColor','white','HorizontalAlignment','Left','FontWeight','bold'); uicontrol('Style','Text','String',['Analysis step selection and ordering' 10 '======='... 10 'Gentlemen, you can not fight in here! This is the War Room.' 10 'We can know only that we know nothing.' 10 'And that is the highest degree of human wisdom.'... diff --git a/@ciatah/modelVarsFromFilesCheck.m b/@ciatah/modelVarsFromFilesCheck.m index bb30f25..387498b 100644 --- a/@ciatah/modelVarsFromFilesCheck.m +++ b/@ciatah/modelVarsFromFilesCheck.m @@ -8,7 +8,7 @@ % % changelog - % + % 2021.06.21 [21:03:42] - Add check for objLocations % TODO % @@ -28,6 +28,7 @@ try try + max(1,round(obj.objLocations{folderNo}.(obj.signalExtractionMethod)(:,1))); [rawSignals rawImages signalPeaks signalPeaksArray, ~, ~, rawSignals2] = modelGetSignalsImages(obj,'returnType','raw'); % obj.nSignals{fileNum} skipReload = 1; diff --git a/@ciatah/viewCellExtractionOnMovie.m b/@ciatah/viewCellExtractionOnMovie.m index 6f24527..38d76b2 100644 --- a/@ciatah/viewCellExtractionOnMovie.m +++ b/@ciatah/viewCellExtractionOnMovie.m @@ -496,7 +496,7 @@ % 'yes','motion','other','yes'); movieDecision = 'yes'; case 'imagej' - msgbox('Change contrast by pressing ctrl+shift+c'); + msgHandle = msgbox('Change contrast by pressing ctrl+shift+c'); try % Miji; % MIJ.createImage([num2str(thisFileNumIdx) '/' num2str(nFilesToAnalyze) '[' num2str(movieNo) '/' num2str(nMovies) ']' ': ' obj.folderBaseSaveStr{obj.fileNum}], primaryMovie, true); @@ -515,8 +515,9 @@ % MIJ.run('Close'); % MIJ.run('Close All Without Saving'); manageMiji('startStop','closeAllWindows'); - manageMiji('startStop','exit'); + % manageMiji('startStop','exit'); % MIJ.exit; + delete(msgHandle); catch err disp(repmat('@',1,7)) disp(getReport(err,'extended','hyperlinks','on'));