├── app └── stand_alone_app │ ├── GraFT.exe │ ├── splash.png │ └── readme.txt ├── code ├── nwb_tutorials │ ├── graft_demo_nwb.mlx │ └── nwb_ophys_tutorial.mlx ├── external-code │ ├── RANN │ │ ├── rann32c.mexa64 │ │ ├── rann32c.mexw64 │ │ ├── rann32c.mexmaci64 │ │ ├── compile_rann32c.m │ │ ├── rann32c.c │ │ └── myprin.c │ ├── colormaps_mathworks_v11 │ │ ├── .DS_Store │ │ ├── matlab │ │ │ ├── .DS_Store │ │ │ ├── ametrine.m │ │ │ └── isolum.m │ │ └── README.txt │ ├── from_caiman │ │ ├── graph_conn_comp_mex.mexa64 │ │ ├── graph_conn_comp_mex.mexw64 │ │ ├── graph_conn_comp_mex.mexmaci64 │ │ ├── graph_connected_comp.m │ │ ├── construct_patches.m │ │ └── graph_conn_comp_mex.cpp │ ├── license.txt │ └── distinguishable_colors.m ├── dictionary-learning │ ├── dict_learn_test.mat │ ├── partialDCT.m │ ├── objfun_l2l1.m │ ├── SolveMP_wrapper.m │ ├── l1ls_wrapper.m │ ├── perform_omp_wrapper.m │ ├── SolveOOMP_wrapper.m │ ├── cg_l2l1_wrapper.m │ ├── l1ls_nneg_wrapper.m │ ├── groupLCA_wrapper.m │ ├── greed_omp_qr_wrapper.m │ ├── cg_l2l1.m │ ├── sparseDeconvDictEst.m │ ├── rwLCA_wrapper.m │ ├── group_rwLCA_wrapper.m │ ├── groupLCA.m │ ├── bilin_Hessfun.m │ ├── gen_multi_infer.m │ ├── initialize_dictionary.m │ ├── rwLCA.m │ ├── bilin_fun.m │ ├── dictionary_learn_script_1d.m │ ├── group_rwLCA.m │ ├── multi_infer.m │ ├── dictionary_learn_script.m │ ├── sample_exemplars.m │ └── mintotol.m ├── plotting-code │ ├── viewMovAndRes.m │ ├── hyper_plot.m │ ├── plotDecomps.m │ ├── basis2img2.m │ ├── correlation_image.m │ └── dict_plot1d.m ├── support-functions │ ├── verbPrint.m │ ├── vec.m │ ├── rotateSpatialMaps.m │ ├── setParams.m │ ├── dictInitialize.m │ ├── tiff_reader.m │ ├── robustSTD.m │ ├── isInMatFile.m │ ├── reCalcCoefWithLS.m │ ├── mkCorrKern.m │ ├── load_app_data.m │ ├── combineDictionaryPatches.m │ ├── mkDataEmbedding.m │ ├── calcAffinityMat.m │ ├── denoiseCIinSpace.m │ ├── bilin_fun.m │ ├── checkCorrKern.m │ ├── denoiseCIinTime.m │ ├── reCalcCoefSparse.m │ └── preprocessData.m ├── graph-sparse-coding │ ├── MutualInfo.m │ ├── EuDist2.m │ ├── NormalizeFea.m │ ├── PCA.m │ ├── GraphRegularizedSparseCodingDemo.m │ ├── constructKernel.m │ ├── learn_basis.m │ ├── mySVD.m │ └── GraphSC.m ├── graft-main │ ├── singlePoiNeuroInfer.m │ └── singleGaussNeuroInfer.m ├── installGraFT.m └── simple-simulation │ ├── simSpatialData2.m │ └── simSpatialData.m ├── LICENSE ├── README.md └── .gitignore /app/stand_alone_app/GraFT.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/app/stand_alone_app/GraFT.exe -------------------------------------------------------------------------------- /app/stand_alone_app/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/app/stand_alone_app/splash.png -------------------------------------------------------------------------------- /code/nwb_tutorials/graft_demo_nwb.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/nwb_tutorials/graft_demo_nwb.mlx -------------------------------------------------------------------------------- /code/external-code/RANN/rann32c.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/external-code/RANN/rann32c.mexa64 -------------------------------------------------------------------------------- /code/external-code/RANN/rann32c.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/external-code/RANN/rann32c.mexw64 -------------------------------------------------------------------------------- /code/external-code/RANN/rann32c.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/external-code/RANN/rann32c.mexmaci64 -------------------------------------------------------------------------------- /code/nwb_tutorials/nwb_ophys_tutorial.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/nwb_tutorials/nwb_ophys_tutorial.mlx -------------------------------------------------------------------------------- /code/dictionary-learning/dict_learn_test.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/dictionary-learning/dict_learn_test.mat -------------------------------------------------------------------------------- /code/external-code/colormaps_mathworks_v11/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/external-code/colormaps_mathworks_v11/.DS_Store -------------------------------------------------------------------------------- /code/external-code/from_caiman/graph_conn_comp_mex.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/external-code/from_caiman/graph_conn_comp_mex.mexa64 -------------------------------------------------------------------------------- /code/external-code/from_caiman/graph_conn_comp_mex.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/external-code/from_caiman/graph_conn_comp_mex.mexw64 -------------------------------------------------------------------------------- /code/external-code/colormaps_mathworks_v11/matlab/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/external-code/colormaps_mathworks_v11/matlab/.DS_Store -------------------------------------------------------------------------------- /code/external-code/from_caiman/graph_conn_comp_mex.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamshch/GraFT-analysis/HEAD/code/external-code/from_caiman/graph_conn_comp_mex.mexmaci64 -------------------------------------------------------------------------------- /code/plotting-code/viewMovAndRes.m: -------------------------------------------------------------------------------- 1 | function viewMovAndRes(mov,S,D) 2 | 3 | 4 | recon = reshape(reshape(S,[],size(D,2))*D', size(mov)); 5 | res = mov-recon; 6 | 7 | MovieSlider(cat(1, mov, recon, 1+res)) -------------------------------------------------------------------------------- /code/dictionary-learning/partialDCT.m: -------------------------------------------------------------------------------- 1 | function res = partialDCT(n,m,J) 2 | 3 | res.adjoint = 0; 4 | res.n = n; 5 | res.m = m; 6 | res.J = J(1:m); 7 | 8 | % Register this variable as a partialDCT class 9 | res = class(res,'partialDCT'); 10 | -------------------------------------------------------------------------------- /code/external-code/RANN/compile_rann32c.m: -------------------------------------------------------------------------------- 1 | setenv('PATH', [getenv('PATH') ':/usr/local/bin']); 2 | setenv('DYLD_LIBRARY_PATH', '/usr/local/bin/'); 3 | 4 | d=which('rann32c.c'); 5 | [d,~,~]=fileparts(d); 6 | cur_dir = pwd; 7 | cd(d); 8 | 9 | 10 | mex rann32c.c myprin.c rann_core.c rann_utils.c 11 | 12 | cd(cur_dir); -------------------------------------------------------------------------------- /code/dictionary-learning/objfun_l2l1.m: -------------------------------------------------------------------------------- 1 | function [f,g] = objfun_l2l1(x0,A,I,lambda); 2 | 3 | [L M]=size(A); 4 | batch_size = size(I,2); 5 | a = reshape(x0,M,batch_size); 6 | 7 | Ihat = A*a; 8 | 9 | e = I - Ihat; 10 | 11 | f = 0.5*sum(e(:).^2) + lambda*sum(abs(a(:))); 12 | 13 | df = -(A'*e) + lambda*sign(a); 14 | g = df(:); 15 | 16 | -------------------------------------------------------------------------------- /code/plotting-code/hyper_plot.m: -------------------------------------------------------------------------------- 1 | function hyper_plot(basis, wl_vect, plot_dims, fig_no) 2 | 3 | % function hyper_plot(basis, size) 4 | % 5 | % Function to plot Hyperspectral Basis Funcitons 6 | % 7 | % Inputs: 8 | % basis - basis of images 9 | 10 | figure(fig_no); 11 | for index = 1:size(basis, 2) 12 | subplot(plot_dims(1), plot_dims(2), index), plot(wl_vect, basis(:, index)) 13 | end 14 | 15 | end 16 | -------------------------------------------------------------------------------- /code/support-functions/verbPrint.m: -------------------------------------------------------------------------------- 1 | function verbPrint(verbLvl, verbCut, messOut) 2 | 3 | % verbPrint(verbLvl, verbCut, messOut) 4 | % 5 | % Function to output messages at a given level of verbosity 6 | % 7 | % 2019 - Adam Charles 8 | 9 | if verbLvl >= verbCut 10 | fprintf('%s\n',messOut) 11 | end 12 | 13 | 14 | end 15 | 16 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/dictionary-learning/SolveMP_wrapper.m: -------------------------------------------------------------------------------- 1 | function coef_vals = SolveMP_wrapper(dictionary_n, x_im, opts) 2 | 3 | % coef_vals = l1ls_wrapper(dictionary_n, x_im, opts) 4 | % 5 | % Wrapper for Matching Pursuit 6 | % 7 | % Last Modified 6/10/2010 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Run l1ls on the desired parameters 11 | 12 | coef_vals = SolveMP(dictionary_n, x_im, opts.n_elem); 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/dictionary-learning/l1ls_wrapper.m: -------------------------------------------------------------------------------- 1 | function coef_vals = l1ls_wrapper(dictionary_n, x_im, opts) 2 | 3 | % coef_vals = l1ls_wrapper(dictionary_n, x_im, opts) 4 | % 5 | % Wrapper for the l1ls minimization function 6 | % 7 | % Last Modified 6/10/2010 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Run l1ls on the desired parameters 11 | 12 | coef_vals = l1_ls(dictionary_n, x_im, opts.lambda, opts.tol,1); 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/dictionary-learning/perform_omp_wrapper.m: -------------------------------------------------------------------------------- 1 | function coef_vals = perform_omp_wrapper(dictionary_n, x_im, opts) 2 | 3 | % coef_vals = l1ls_wrapper(dictionary_n, x_im, opts) 4 | % 5 | % Wrapper for Orthogonal Matching Pursuit 6 | % 7 | % Last Modified 6/10/2010 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Run l1ls on the desired parameters 11 | 12 | coef_vals = perform_omp(dictionary_n, x_im, opts); 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/dictionary-learning/SolveOOMP_wrapper.m: -------------------------------------------------------------------------------- 1 | function coef_vals = SolveOOMP_wrapper(dictionary_n, x_im, opts) 2 | 3 | % coef_vals = l1ls_wrapper(dictionary_n, x_im, opts) 4 | % 5 | % Wrapper for Optimized Orthogonal Matching Pursuit 6 | % 7 | % Last Modified 6/10/2010 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Run l1ls on the desired parameters 11 | 12 | coef_vals = SolveOOMP(dictionary_n, x_im, opts.tol, Inf, opts.tol); 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/dictionary-learning/cg_l2l1_wrapper.m: -------------------------------------------------------------------------------- 1 | function coef_vals = cg_l2l1_wrapper(dictionary_n, x_im, opts) 2 | 3 | % coef_vals = l1ls_wrapper(dictionary_n, x_im, opts) 4 | % 5 | % Wrapper for the l2l1 conjugate gradient minimization function 6 | % 7 | % Last Modified 6/10/2010 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Run l1ls on the desired parameters 11 | 12 | coef_vals = cg_l2l1(dictionary_n, opts.tol, x_im, opts.lambda); 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/dictionary-learning/l1ls_nneg_wrapper.m: -------------------------------------------------------------------------------- 1 | function coef_vals = l1ls_nneg_wrapper(dictionary_n, x_im, opts) 2 | 3 | % coef_vals = l1ls_wrapper(dictionary_n, x_im, opts) 4 | % 5 | % Wrapper for the l1ls non negative minimization function 6 | % 7 | % Last Modified 6/10/2010 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Run l1ls on the desired parameters 11 | 12 | coef_vals = l1_ls_nonneg(dictionary_n, x_im, opts.lambda, opts.tol,1); 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/dictionary-learning/groupLCA_wrapper.m: -------------------------------------------------------------------------------- 1 | function coef_vals = groupLCA_wrapper(dictionary_n, x_im, opts) 2 | 3 | % coef_vals = l1ls_wrapper(dictionary_n, x_im, opts) 4 | % 5 | % Wrapper for the block l1 minimization function 6 | % 7 | % Last Modified 1/28/2015 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Run l1ls on the desired parameters 11 | 12 | coef_vals = groupLCA(x_im, dictionary_n, opts.lambda, opts.groups, opts.tol); 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | -------------------------------------------------------------------------------- /code/dictionary-learning/greed_omp_qr_wrapper.m: -------------------------------------------------------------------------------- 1 | function coef_vals = greed_omp_qr_wrapper(dictionary_n, x_im, opts) 2 | 3 | % coef_vals = l1ls_wrapper(dictionary_n, x_im, opts) 4 | % 5 | % Wrapper for the QR implementation of Orthogonal Matching Pursuit 6 | % 7 | % Last Modified 6/10/2010 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Run l1ls on the desired parameters 11 | 12 | [coef_vals, ~, ~] = greed_omp_qr(x_im, dictionary_n, opts.n_elem); 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/support-functions/vec.m: -------------------------------------------------------------------------------- 1 | function y = vec(x) 2 | 3 | % y = vec(x) 4 | % 5 | % This function is a very useful function that just reshapes an N-D array 6 | % as a vector. Useful when reshaping the output of a function without 7 | % creating clutter in the variable space 8 | % 9 | % 2020 - Adam Charles 10 | 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | 13 | y = x(:); % Just reshape the array as a vector 14 | 15 | end 16 | 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 19 | -------------------------------------------------------------------------------- /code/dictionary-learning/cg_l2l1.m: -------------------------------------------------------------------------------- 1 | function S = cg_l2l1(A,tol,X,lambda) 2 | 3 | [L,batch_size] = size(X); 4 | [L,M] = size(A); 5 | 6 | normA = sum(A.*A)'; 7 | 8 | % if some of the basis functions have length zero 9 | % (this can happen when all coefficients in frame 0 have value zero) 10 | % ..then initialized the coefficients to zero, instead of the projection 11 | % (this prevents the coefficients from being initialized to NaN) 12 | if (min(normA) == 0) 13 | S0 = zeros(M,batch_size); 14 | else 15 | S0 = A'*X; 16 | for i=1:batch_size 17 | S0(:,i) = S0(:,i) ./ normA; 18 | end 19 | end 20 | 21 | [S1,fX,ri] = mintotol(S0(:),'objfun_l2l1',100,tol,A,X,lambda); 22 | 23 | S=reshape(S1,M,batch_size); 24 | 25 | -------------------------------------------------------------------------------- /code/external-code/from_caiman/graph_connected_comp.m: -------------------------------------------------------------------------------- 1 | function [l c] = graph_connected_comp(sA) 2 | % 3 | % Computing connected components of an undirected graph - assuming sA is symmetric 4 | % 5 | % Usage: 6 | % [l c] = graph_conn_comp(sA); 7 | % 8 | % Inputs: 9 | % sA - sparse adjacency matrix (for directed graph - does not have to be symmetric) 10 | % 11 | % Outputs: 12 | % l - components labels 13 | % c - number of connected components 14 | % 15 | % 16 | % Compile using: 17 | % >> mex -O -largeArrayDims graph_conn_comp_mex.cpp 18 | % 19 | % 20 | 21 | sA = spfun(@(x) ones(size(x)),sA); 22 | if ~isequal(sA, sA') 23 | [ii jj] = find(sA); 24 | sA = sparse([ii jj],[jj ii], ones(1, 2*numel(ii)), size(sA,1), size(sA,2)); 25 | end 26 | [l c] = graph_conn_comp_mex(sA); 27 | l = double(l); % make it compatible of the rest of Matlab -------------------------------------------------------------------------------- /code/support-functions/rotateSpatialMaps.m: -------------------------------------------------------------------------------- 1 | function SN = rotateSpatialMaps(SN) 2 | 3 | % SN = rotateSpatialMaps(SN) 4 | % 5 | % Code to rotate spatial maps to beter align or visualize them. 6 | % 7 | % 2019 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Rotate all the spatial maps 11 | 12 | if iscell(SN) 13 | for ll = 1:numel(SN) 14 | SN{ll} = rotateSpatialMaps(SN{ll}); % Iterate over all spatial map instantiations 15 | end 16 | else 17 | for i =1:size(SN,3) 18 | SN(:,:,i) = rot90(SN(:,:,i),2); % Rotate each map 19 | end 20 | % mask = rot90(mask,2); 21 | end 22 | 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/dictionary-learning/sparseDeconvDictEst.m: -------------------------------------------------------------------------------- 1 | function D = sparseDeconvDictEst(D, Y, A, h, opts) 2 | 3 | % This function should return the solution to the optimiation 4 | % 5 | % S = argmin[||Y - (h*S)A||_F^2 + ] 6 | % 7 | % D_i = h*S_i 8 | 9 | 10 | Dfun = @(Z) bilin_fun(Z, Y, A, h, D, opts); 11 | Hfun = @(x, lambda, Z) bilin_Hessfun(x, lambda, Z, Y, A, h, opts); 12 | 13 | % minopts = optimset(); 14 | minopts = optimoptions(@fmincon,'Algorithm','interior-point','Display','off'); % interior-point 15 | minopts = optimoptions(minopts,'SpecifyObjectiveGradient',true,'CheckGradients',false); 16 | minopts = optimoptions(minopts, 'SubproblemAlgorithm', 'cg', 'HessianMultiplyFcn', Hfun, 'HessianFcn', []); 17 | D = fmincon(Dfun, vec(D), [], [], [], [], zeros(numel(D),1), [], [], minopts); 18 | 19 | D = convn(reshape(D,[size(Y,1),size(A,1)]), h, 'same'); 20 | 21 | end 22 | 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 25 | -------------------------------------------------------------------------------- /code/dictionary-learning/rwLCA_wrapper.m: -------------------------------------------------------------------------------- 1 | function coef_vals = rwLCA_wrapper(dictionary_n, x_im, opts) 2 | 3 | % coef_vals = rwLCA_wrapper(dictionary_n, x_im, opts) 4 | % 5 | % Wrapper for the l1ls minimization function 6 | % Required parameters: 7 | % opts.eta: 2-D vecotr of Delta/T for LCA (1 for coefficients, one 8 | % for weights. Typically eta(2) < eta(1)/2 9 | % opts.gamma_val: Denominator bias for re-weighting. Typically 10 | % ~0.01*||a||_\infty 11 | % opts.tol: `tolerance' parameter used here to set maximum number 12 | % of LCA iterations to run. maxIters = floor(1./opts.tol) 13 | % 14 | % Last Modified 2/16/2015 - Adam Charles 15 | 16 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 17 | %% Run l1ls on the desired parameters 18 | 19 | coef_vals = rwLCA(x_im, dictionary_n, 1, opts.eta, opts.gamma_val, floor(1./opts.tol), 0) 20 | 21 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 22 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Adam 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /code/support-functions/setParams.m: -------------------------------------------------------------------------------- 1 | function paramsOut = setParams(dParams, paramsIn) 2 | 3 | % paramsOut = setParams(dParams, paramsIn) 4 | % 5 | % paramsOut = setParams(dParams, paramsIn) 6 | % 7 | % The output params struct will include the fields of dParams and paramsIn. 8 | % If the same field exists in both of them, the value will be taken from 'paramsIn' 9 | % 10 | % 11 | 12 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 | 14 | paramsOut = dParams; 15 | if isempty(paramsIn) 16 | return; 17 | end 18 | 19 | fnames = fieldnames(paramsIn); 20 | for f=1:length(fnames) 21 | if isfield(paramsOut, fnames{f}) 22 | if isstruct(paramsOut.(fnames{f})) 23 | val = setParams(paramsOut.(fnames{f}), paramsIn.(fnames{f})); 24 | else 25 | val = paramsIn.(fnames{f}); 26 | end 27 | paramsOut.(fnames{f}) = val; 28 | else 29 | paramsOut.(fnames{f}) = paramsIn.(fnames{f}); 30 | end 31 | end 32 | 33 | end 34 | 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/dictionary-learning/group_rwLCA_wrapper.m: -------------------------------------------------------------------------------- 1 | function coef_vals = group_rwLCA_wrapper(dictionary_n, x_im, opts) 2 | 3 | % coef_vals = group_rwLCA_wrapper(dictionary_n, x_im, opts) 4 | % 5 | % Wrapper for the l1ls minimization function 6 | % Required parameters: 7 | % opts.eta: 2-D vecotr of Delta/T for LCA (1 for coefficients, one 8 | % for weights. Typically eta(2) < eta(1)/2 9 | % opts.gamma_val: Denominator bias for re-weighting. Typically 10 | % ~0.01*||a||_\infty 11 | % opts.tol: `tolerance' parameter used here to set maximum number 12 | % of LCA iterations to run. maxIters = floor(1./opts.tol) 13 | % opts.groups: Group structure of coefficients (same as for groupLCA) 14 | % 15 | % Last Modified 2/16/2015 - Adam Charles 16 | 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 | %% Run l1ls on the desired parameters 19 | 20 | coef_vals = rwLCA(x_im, dictionary_n, 1, opts.eta, opts.gamma_val, floor(1./opts.tol), opts.groups) 21 | 22 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | -------------------------------------------------------------------------------- /code/support-functions/dictInitialize.m: -------------------------------------------------------------------------------- 1 | function dict_out = dictInitialize(dict_init, T, N) 2 | 3 | % dict_out = dictInitialize(dict_init, T, N) 4 | % 5 | % Function to initialize a TxN sized dictionary. The columns of the 6 | % dictionary are normalized to unit norm. If a matrix is fed in as the 7 | % first input, that dictionary is just normalized (no random 8 | % initialization performed). 9 | % 10 | % 2019 - Adam Charles 11 | 12 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 | %% 14 | 15 | if isempty(dict_init) % If no dictionary is provided: 16 | dict_out = rand(T,N); % - Initialize dictionary randomly 17 | dict_out = dict_out*diag(1./sqrt(sum(dict_out.^2,1))); % - Normlize each vector in the dictionary 18 | else % Otherwise: 19 | dict_out = dict_init; % - Use given initial dicitonary 20 | dict_out = dict_out*diag(1./sqrt(sum(dict_out.^2,1))); % - Normlize each vector in the dictionary 21 | end 22 | 23 | end 24 | 25 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 26 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 27 | -------------------------------------------------------------------------------- /code/support-functions/tiff_reader.m: -------------------------------------------------------------------------------- 1 | function Y = tiff_reader(name,T) 2 | 3 | % Y = tiff_reader(name,T) 4 | % 5 | % read tiff stack. Optional truncate to first T timesteps 6 | % 7 | % The inputs to this function are 8 | % name: String pointing to the tif file to load 9 | % T: Number of frames to extract 10 | % 11 | % The output to this function is 12 | % Y: 3D array of the tif frames 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %% Parse inputs and set variables 16 | 17 | info = imfinfo(name); % Get TIFF info 18 | 19 | if (nargin == 1)||(isempty(T)) 20 | T = numel(info); 21 | end 22 | 23 | d1 = info(1).Height; % Find height and width 24 | d2 = info(1).Width; 25 | 26 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 27 | %% Read in image 28 | 29 | Y = zeros(d1,d2,T); % Pre-allocate data 30 | for t = 1:T 31 | Y(:,:,t) = imread(name, t, 'Info',info); % Read in TIFF one frame at a time 32 | end 33 | 34 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | -------------------------------------------------------------------------------- /code/graph-sparse-coding/MutualInfo.m: -------------------------------------------------------------------------------- 1 | function MIhat = MutualInfo(L1,L2) 2 | % mutual information 3 | % 4 | % version 2.0 --May/2007 5 | % version 1.0 --November/2003 6 | % 7 | % Written by Deng Cai (dengcai AT gmail.com) 8 | %=========== 9 | L1 = L1(:); 10 | L2 = L2(:); 11 | if size(L1) ~= size(L2) 12 | error('size(L1) must == size(L2)'); 13 | end 14 | 15 | Label = unique(L1); 16 | nClass = length(Label); 17 | 18 | Label2 = unique(L2); 19 | nClass2 = length(Label2); 20 | if nClass2 < nClass 21 | % smooth 22 | L1 = [L1; Label]; 23 | L2 = [L2; Label]; 24 | elseif nClass2 > nClass 25 | % smooth 26 | L1 = [L1; Label2]; 27 | L2 = [L2; Label2]; 28 | end 29 | 30 | 31 | G = zeros(nClass); 32 | for i=1:nClass 33 | for j=1:nClass 34 | G(i,j) = sum(L1 == Label(i) & L2 == Label(j)); 35 | end 36 | end 37 | sumG = sum(G(:)); 38 | 39 | P1 = sum(G,2); P1 = P1/sumG; 40 | P2 = sum(G,1); P2 = P2/sumG; 41 | if sum(P1==0) > 0 || sum(P2==0) > 0 42 | % smooth 43 | error('Smooth fail!'); 44 | else 45 | H1 = sum(-P1.*log2(P1)); 46 | H2 = sum(-P2.*log2(P2)); 47 | P12 = G/sumG; 48 | PPP = P12./repmat(P2,nClass,1)./repmat(P1,1,nClass); 49 | PPP(abs(PPP) < 1e-12) = 1; 50 | MI = sum(P12(:) .* log2(PPP(:))); 51 | MIhat = MI / max(H1,H2); 52 | %%%%%%%%%%%%% why complex ? %%%%%%%% 53 | MIhat = real(MIhat); 54 | end 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /code/external-code/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Matthias Geissbuehler 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the distribution 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /code/graph-sparse-coding/EuDist2.m: -------------------------------------------------------------------------------- 1 | function D = EuDist2(fea_a,fea_b,bSqrt) 2 | %EUDIST2 Efficiently Compute the Euclidean Distance Matrix by Exploring the 3 | %Matlab matrix operations. 4 | % 5 | % D = EuDist(fea_a,fea_b) 6 | % fea_a: nSample_a * nFeature 7 | % fea_b: nSample_b * nFeature 8 | % D: nSample_a * nSample_a 9 | % or nSample_a * nSample_b 10 | % 11 | % Examples: 12 | % 13 | % a = rand(500,10); 14 | % b = rand(1000,10); 15 | % 16 | % A = EuDist2(a); % A: 500*500 17 | % D = EuDist2(a,b); % D: 500*1000 18 | % 19 | % version 2.1 --November/2011 20 | % version 2.0 --May/2009 21 | % version 1.0 --November/2005 22 | % 23 | % Written by Deng Cai (dengcai AT gmail.com) 24 | 25 | 26 | if ~exist('bSqrt','var') 27 | bSqrt = 1; 28 | end 29 | 30 | if (~exist('fea_b','var')) || isempty(fea_b) 31 | aa = sum(fea_a.*fea_a,2); 32 | ab = fea_a*fea_a'; 33 | 34 | if issparse(aa) 35 | aa = full(aa); 36 | end 37 | 38 | D = bsxfun(@plus,aa,aa') - 2*ab; 39 | D(D<0) = 0; 40 | if bSqrt 41 | D = sqrt(D); 42 | end 43 | D = max(D,D'); 44 | else 45 | aa = sum(fea_a.*fea_a,2); 46 | bb = sum(fea_b.*fea_b,2); 47 | ab = fea_a*fea_b'; 48 | 49 | if issparse(aa) 50 | aa = full(aa); 51 | bb = full(bb); 52 | end 53 | 54 | D = bsxfun(@plus,aa,bb') - 2*ab; 55 | D(D<0) = 0; 56 | if bSqrt 57 | D = sqrt(D); 58 | end 59 | end 60 | 61 | -------------------------------------------------------------------------------- /code/support-functions/robustSTD.m: -------------------------------------------------------------------------------- 1 | function rstd = robustSTD(data) 2 | % robustSTD compute robust standard deviation 3 | % 4 | % usage: rstd = robustSTD(data) 5 | % 6 | % arguments: data - vector of numbers 7 | % or array - operates along 1st dim 8 | % 9 | % outputs: rstd - robust standard deviation 10 | % 11 | % 12 | % translated from lisp (statistics.lisp) to matlab by JLG, 2007-07-17 13 | % 14 | % ;; Function ROBUST-STANDARD-DEVIATION 15 | % ;; ESF 2003-08-13 16 | % ;; made more efficient by EJC 2003-08-14 17 | % ;; calculates a robust standard deviation 18 | % ;; see PJ Huber (1981), Robust Statistics, Wiley, call number QA 276.H785 19 | % ;; hardcoded constant is inverse cumulative normal evaluated at 0.75 20 | % ;; this computation performs well if 21 | % ;; (1) data near the mean approximately follow a normal distribution, 22 | % ;; (2) the outliers are outside the 25%-75% percentiles. 23 | % 24 | % 2008-10 greschner loop over 2nd dim 25 | % 2008-10 gauthier remove loop for increased speed 26 | % 27 | 28 | 29 | % handle empty case 30 | if isempty(data) 31 | rstd = []; 32 | return 33 | end 34 | 35 | % if one dimensional, make sure it is a column 36 | if find(size(data)==1)==1 37 | data=data'; 38 | end 39 | 40 | % identify median of each column, and subtract it from each entry in the column 41 | data = data - repmat(nanmedian(data),size(data,1),1); 42 | 43 | % rest of computation 44 | rstd = nanmedian(abs(data)) ./ 0.6741891400433162; 45 | 46 | -------------------------------------------------------------------------------- /code/plotting-code/plotDecomps.m: -------------------------------------------------------------------------------- 1 | function plotDecomps(SN, DN, varargin) 2 | 3 | % plotDecomps(SN, DN, {mask}) 4 | % 5 | % Plot the outputs of decomposition of calcium imaging data. 6 | % 7 | % 2019 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Parse inputs 11 | 12 | if nargin > 2 13 | mask = varargin{1}; 14 | else 15 | mask = 1; 16 | end 17 | 18 | if isempty(mask) 19 | mask = 1; 20 | end 21 | 22 | if nargin > 3 23 | figno = varargin{2}; 24 | else 25 | figno = 101; 26 | end 27 | 28 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 29 | %% Set up plots 30 | 31 | figure(figno); 32 | SN = bsxfun(@times, SN, ~isnan(mask)); 33 | S2 = SN; 34 | % S2(SN==0) = mean(SN(SN~=0)); 35 | % S2 = S2 - mean(SN(SN~=0)); 36 | 37 | % subplot(3,2,[3,6]), imagesc(basis2img2(reshape(S2,[],size(S,3)),size(S(:,:,1)), ceil(sqrt(size(S,3)))*[1,1]),[0.8,1]) 38 | subplot(1,2,1), imagesc(basis2img2(reshape(S2,[],size(SN,3)), size(SN(:,:,1)), [5,6], true),[0,1]) 39 | axis image; axis off; 40 | set(gcf, 'color', [1,1,1]) 41 | 42 | subplot(1,2,2), plot(1:(size(DN,1)), bsxfun(@plus,bsxfun(@times, DN, 1*vec(max(max(SN,[],1),[],2)).'),0:(size(DN,2)-1))) 43 | set(gca, 'XLim',[0, (size(DN,1)-1)],'YLim',[1,1.1*(size(DN,2))]) 44 | box off 45 | 46 | end 47 | 48 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 49 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/graph-sparse-coding/NormalizeFea.m: -------------------------------------------------------------------------------- 1 | function fea = NormalizeFea(fea,row) 2 | % if row == 1, normalize each row of fea to have unit norm; 3 | % if row == 0, normalize each column of fea to have unit norm; 4 | % 5 | % version 3.0 --Jan/2012 6 | % version 2.0 --Jan/2012 7 | % version 1.0 --Oct/2003 8 | % 9 | % Written by Deng Cai (dengcai AT gmail.com) 10 | % 11 | 12 | if ~exist('row','var') 13 | row = 1; 14 | end 15 | 16 | if row 17 | nSmp = size(fea,1); 18 | feaNorm = max(1e-14,full(sum(fea.^2,2))); 19 | fea = spdiags(feaNorm.^-.5,0,nSmp,nSmp)*fea; 20 | else 21 | nSmp = size(fea,2); 22 | feaNorm = max(1e-14,full(sum(fea.^2,1))'); 23 | fea = fea*spdiags(feaNorm.^-.5,0,nSmp,nSmp); 24 | end 25 | 26 | return; 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | if row 35 | [nSmp, mFea] = size(fea); 36 | if issparse(fea) 37 | fea2 = fea'; 38 | feaNorm = mynorm(fea2,1); 39 | for i = 1:nSmp 40 | fea2(:,i) = fea2(:,i) ./ max(1e-10,feaNorm(i)); 41 | end 42 | fea = fea2'; 43 | else 44 | feaNorm = sum(fea.^2,2).^.5; 45 | fea = fea./feaNorm(:,ones(1,mFea)); 46 | end 47 | else 48 | [mFea, nSmp] = size(fea); 49 | if issparse(fea) 50 | feaNorm = mynorm(fea,1); 51 | for i = 1:nSmp 52 | fea(:,i) = fea(:,i) ./ max(1e-10,feaNorm(i)); 53 | end 54 | else 55 | feaNorm = sum(fea.^2,1).^.5; 56 | fea = fea./feaNorm(ones(1,mFea),:); 57 | end 58 | end 59 | 60 | 61 | -------------------------------------------------------------------------------- /app/stand_alone_app/readme.txt: -------------------------------------------------------------------------------- 1 | GraFT Executable 2 | 3 | 1. Prerequisites for Deployment 4 | 5 | Verify that MATLAB Runtime(R2022b) is installed. 6 | If not, you can run the MATLAB Runtime installer. 7 | To find its location, enter 8 | 9 | >>mcrinstaller 10 | 11 | at the MATLAB prompt. 12 | NOTE: You will need administrator rights to run the MATLAB Runtime installer. 13 | 14 | Alternatively, download and install the Windows version of the MATLAB Runtime for R2022b 15 | from the following link on the MathWorks website: 16 | 17 | https://www.mathworks.com/products/compiler/mcr/index.html 18 | 19 | For more information about the MATLAB Runtime and the MATLAB Runtime installer, see 20 | "Distribute Applications" in the MATLAB Compiler documentation 21 | in the MathWorks Documentation Center. 22 | 23 | 2. Files to Deploy and Package 24 | 25 | Files to Package for Standalone 26 | ================================ 27 | -GraFT.exe 28 | -MCRInstaller.exe 29 | Note: if end users are unable to download the MATLAB Runtime using the 30 | instructions in the previous section, include it when building your 31 | component by clicking the "Runtime included in package" link in the 32 | Deployment Tool. 33 | -This readme file 34 | 35 | 36 | 37 | 3. Definitions 38 | 39 | For information on deployment terminology, go to 40 | https://www.mathworks.com/help and select MATLAB Compiler > 41 | Getting Started > About Application Deployment > 42 | Deployment Product Terms in the MathWorks Documentation 43 | Center. 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /code/graft-main/singlePoiNeuroInfer.m: -------------------------------------------------------------------------------- 1 | function S = singlePoiNeuroInfer(tau_vec, mov_vec, D, maxiter, tolerance, verbose) 2 | 3 | % S = singlePoiNeuroInfer(tau_vec, mov_vec, D, maxiter, tolerance, verbose) 4 | % 5 | % Use SpiralTAP for a single vector 6 | % 7 | % 2018 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Set up problem 11 | 12 | % Set up the linear operator for use in SPIRALtap 13 | A = @(x) D*x; 14 | AT = @(x) D.'*x; 15 | 16 | mov_vec = max(vec(round(squeeze(mov_vec))),0); % Make sure the time trace is a positive vector 17 | tau_vec = vec(tau_vec); % Make sure the weight vector is a vector 18 | 19 | finit = (sum(sum(mov_vec)).*numel(AT(mov_vec)))... 20 | ./(sum(sum(AT(mov_vec))) .*sum(sum((AT(ones(size(mov_vec)))))))... 21 | .*AT(mov_vec); % Calculate a good initial point (adapted from SPIRALtap 22 | 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | %% Run SPIRAL TAP to get the coefficients 25 | 26 | [S, ~, ~, ~] = SPIRALTAP(mov_vec, A, tau_vec, 'maxiter', maxiter,... 27 | 'Initialization', finit, 'AT', AT, 'miniter', 5, 'stopcriterion', 3,... 28 | 'tolerance', tolerance, 'alphainit', 1, 'alphamin', 1e-30, ... 29 | 'alphamax', 1e30, 'alphaaccept', 1e30, 'logepsilon', 1e-10, ... 30 | 'saveobjective', 1, 'savereconerror', 0, 'savecputime', 1,... 31 | 'savesolutionpath', 0, 'truth', false, 'verbose', verbose); 32 | 33 | end 34 | 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/support-functions/isInMatFile.m: -------------------------------------------------------------------------------- 1 | function checkVars = isInMatFile(fileName, varName) 2 | 3 | % isInMatFile(fileName, varName) 4 | % 5 | % Chech if a variable called "varName", or list of variables as a cell 6 | % array of variable names in 'varName' exist in the file "fileName" 7 | % 8 | % 2018 - Adam Charles 9 | 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | %% Input checking 12 | 13 | if ~ischar(fileName); error('The file name must be a string!'); end % Make sure the filename is a string 14 | 15 | if ~isequal(fileName(end-3:end),'.mat') 16 | error('The file name must p[oint to a mat file!') % Make sure the filename is a .mat file 17 | end 18 | 19 | if ischar(varName); vN{1} = varName; % Check if varName is a string. If so make a 1x1 cell array with that name in it 20 | elseif iscell(varName); vN = varName; % Otherwise if varName is a cell array, just pass it through 21 | end 22 | 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | %% Check if the variable name exists 25 | 26 | variableInfo = who('-file', fileName); % Get the variable list of the variables in the file 'filename' 27 | checkVars = zeros(numel(vN),1); % Initialize 28 | for kk = 1:numel(checkVars) 29 | checkVars(kk) = ismember(vN{kk}, variableInfo); % Check if the kk^th variable is present in the list of variables ('variableInfo') 30 | end 31 | 32 | end 33 | 34 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | -------------------------------------------------------------------------------- /code/support-functions/reCalcCoefWithLS.m: -------------------------------------------------------------------------------- 1 | function S = reCalcCoefWithLS(data, D, S, nonneg) 2 | 3 | % S = recalcCoefWithLS(data, D, S) 4 | % 5 | % 6 | % 7 | % 202 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | 11 | S_on = abs(S)>10*eps; % Compute the support of all pixels 12 | classS = class(S); 13 | if ndims(S)==3 14 | nPix = size(S,1)*size(S,2); % get number of pixels 15 | nCoef = size(S,3); 16 | for ll = 1:nPix 17 | [iX,iY] = ind2sub([size(S,1),size(S,2)],ll); 18 | idxCoef = squeeze(S_on(iX,iY,:))'==1; 19 | 20 | TMP = cast(zeros(nCoef,1),classS); 21 | %S(iX,iY,idxCoef) = cast(lsqnonneg(double(D(:,idxCoef)),... 22 | TMP(idxCoef) = cast(lsqnonneg(double(D(:,idxCoef)),... 23 | double(squeeze(data(iX,iY,:))).'),class(S)); % Compute the least-squares solution for the coefficient 24 | %S(iX,iY,~idxCoef) = cast(0,class(S)); 25 | S(iX,iY,:) = TMP; 26 | end 27 | elseif ndims(S)==2 28 | nPix = size(S,1); 29 | nCoef = size(S,2); 30 | parfor ll = 1:nPix 31 | idxCoef = squeeze(S_on(ll,:))'==1; 32 | TMP = cast(zeros(nCoef,1),classS); 33 | %S(ll,idxCoef) = cast(lsqnonneg(double(D(:,idxCoef)),... 34 | TMP(idxCoef) = cast(lsqnonneg(double(D(:,idxCoef)),... 35 | double(squeeze(data(ll,:))).'),classS); % Compute the least-squares solution for the coefficient 36 | %S(ll,~idxCoef) = cast(0,classS); 37 | S(ll,:) = TMP; 38 | end 39 | else 40 | error('Bad format for coefficient array') 41 | end 42 | 43 | end 44 | 45 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 46 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 47 | 48 | 49 | -------------------------------------------------------------------------------- /code/dictionary-learning/groupLCA.m: -------------------------------------------------------------------------------- 1 | function a = groupLCA(y, A, lambda, group_cell, varargin) 2 | 3 | % a = solve_grouplasso_lca(y, A, lambda, group_cell, tol) 4 | % 5 | % Block l1 minimization (group lasso) function. Uses LCA to optimize. 6 | % 7 | % y - vector to infer decomposition 8 | % A - sparsity matrix (generative mode: y = A*a) 9 | % lambda - regularization trade-off parameter 10 | % group cell - cell of groups (each cell has indices for one group) 11 | % tol - algorithm tolerance. runs until ||u_t - u_{t-1}||_2^2 < tol 12 | % 13 | % 14 | % Last Modified 1/28/2015 - Adam Charles 15 | 16 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 17 | %% Run l1ls on the desired parameters 18 | 19 | if nargin < 4 20 | error('Too few inputs to solve_grouplasso_lca!') 21 | elseif nargin == 4 22 | tol = 1e-3; 23 | DeltaT = 0.1; 24 | elseif nargin == 5 25 | tol = varargin{1}; 26 | DeltaT = 0.1; 27 | elseif nargin == 6 28 | tol = varargin{1}; 29 | DeltaT = 0.1; 30 | else 31 | error('Too many inputs to solve_grouplasso_lca!') 32 | end 33 | 34 | u = zeros(size(A, 1), 1); 35 | a = zeros(size(A, 1), 1); 36 | 37 | 38 | deta_u = 1; 39 | while delta_u > tol 40 | 41 | % update u 42 | u2 = DeltaT*(Aty - u2- AtA*a)+u2 ; 43 | % threshold for a 44 | for kk = 1:numel(group_cell) 45 | u_tmp = u(group_cell{kk}); 46 | if sqrt(sum(u_tmp.^2)) < lambda 47 | a(group_cell{kk}) = zeros(size(u_tmp)); 48 | elseif sqrt(sum(u_tmp.^2)) >= lambda 49 | a(group_cell{kk}) = u_tmp*(1-lambda./sqrt(sum(u_tmp.^2))); 50 | else 51 | end 52 | end 53 | 54 | delta_u = sum((u2 - u).^2); 55 | u = u2; 56 | end 57 | 58 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 59 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 60 | -------------------------------------------------------------------------------- /code/external-code/colormaps_mathworks_v11/README.txt: -------------------------------------------------------------------------------- 1 | This archive contains three colormaps that have been discussed in detail in the following article: 2 | 3 | M. Geissbuehler and T. Lasser "How to display data by color schemes compatible with red-green 4 | color perception deficiencies" Opt. Express 21, 9862-9874 (2013) 5 | http://www.opticsinfobase.org/oe/abstract.cfm?URI=oe-21-8-9862 6 | 7 | 8 | Please feel free to use them at your own convenience. A citation to the original article is of course 9 | appreciated, however not "mandatory" :-) 10 | 11 | 12 | 13 | 14 | Copyright (c) 2013, Matthias Geissbuehler 15 | All rights reserved. 16 | 17 | Redistribution and use in source and binary forms, with or without 18 | modification, are permitted provided that the following conditions are 19 | met: 20 | 21 | * Redistributions of source code must retain the above copyright 22 | notice, this list of conditions and the following disclaimer. 23 | * Redistributions in binary form must reproduce the above copyright 24 | notice, this list of conditions and the following disclaimer in 25 | the documentation and/or other materials provided with the distribution 26 | 27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 31 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 | POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /code/installGraFT.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%% Install GraFT %%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | 7 | % This script adds all the necessary subfolders etc. to run GraFT 8 | % 9 | % 10 | % 2021 - Adam Charles & Gal Mishne 11 | 12 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 | %% 14 | 15 | currentFolder = pwd; % Get base folder 16 | 17 | addpath(genpath([currentFolder,'/dictionary-learning'])); % Add folder for dictionary learning 18 | addpath(genpath([currentFolder,'/graft-main'])); % Add folder for Misc files 19 | addpath(genpath([currentFolder,'/graph-sparse-coding'])); % Add folder for Optics simulation files 20 | addpath(genpath([currentFolder,'/external-code'])); % Add folder for Time-trace simulation files 21 | addpath(genpath([currentFolder,'/plotting-code'])); % Add folder for Neural volume simulation files 22 | addpath(genpath([currentFolder,'/simple-simulation'])); % Add folder for Scanning simulation files 23 | addpath(genpath([currentFolder,'/support-functions'])); % Add folder for various analysis scripts 24 | addpath(genpath([currentFolder,'/neurofinder.02.00'])); % Add folder for external packages 25 | 26 | cd(currentFolder); % Return to the main folder 27 | clear currentFolder ans 28 | 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 31 | 32 | -------------------------------------------------------------------------------- /code/support-functions/mkCorrKern.m: -------------------------------------------------------------------------------- 1 | function corr_kern = mkCorrKern(kern_opts) 2 | 3 | % corr_kern = mkCorrKern(kern_opts) 4 | % 5 | % Create a convolutional correlation kernel that relates neighboring 6 | % points. 7 | % 8 | % 2018 - Adam Charles 9 | 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | %% Check parameters 12 | 13 | 14 | if nargin < 1 || isempty(kern_opts) % Make sure that sim_opts is a struct 15 | clear kern_opts 16 | kern_opts = struct; 17 | end 18 | if (~isfield(kern_opts,'w_space'))||isempty(kern_opts.w_space) 19 | w_space = 3; 20 | else 21 | w_space = kern_opts.w_space ; 22 | end 23 | if (~isfield(kern_opts,'w_scale'))||isempty(kern_opts.w_scale) 24 | w_scale = 4; 25 | else 26 | w_scale = kern_opts.w_scale ; 27 | end 28 | if (~isfield(kern_opts,'w_scale2'))||isempty(kern_opts.w_scale2) 29 | w_scale2 = 0.5; 30 | else 31 | w_scale2 = kern_opts.w_scale2 ; 32 | end 33 | if (~isfield(kern_opts,'w_power'))||isempty(kern_opts.w_power) 34 | w_power = 2; 35 | else 36 | w_power = kern_opts.w_power ; 37 | end 38 | if (~isfield(kern_opts,'w_time'))||isempty(kern_opts.w_time) 39 | w_time = 0; 40 | else 41 | w_time = kern_opts.w_time ; 42 | end 43 | 44 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 45 | %% Make the kernel 46 | 47 | range_vec = vec(linspace(-w_scale,w_scale,1+2*w_space)); 48 | range_vec2 = vec(linspace(-w_scale2,w_scale2,1+2*w_time)); 49 | corr_kern = exp(-0.5*(1/w_space)*(abs(range_vec*ones(size(range_vec'))).^w_power ... 50 | +abs(ones(size(range_vec))*(range_vec.')).^w_power)); 51 | corr_kern = bsxfun(@times,corr_kern,exp(-0.5*(1/max(w_time,1))*reshape(range_vec2.^2,[1,1,numel(range_vec2)]))); 52 | corr_kern(w_space+1,w_space+1,w_time+1) = 0; 53 | corr_kern = corr_kern/(sum(corr_kern(:)) + eps); 54 | 55 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 56 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/plotting-code/basis2img2.m: -------------------------------------------------------------------------------- 1 | function I = basis2img2(A, dimI, dims,varargin) 2 | 3 | % function I = basis2img2(A, dims) 4 | % 5 | % A - matrix of image patches 6 | % dim - a 2x1 vector specifying number of rows and cols 7 | % for reshaping A 8 | % dimI - a 2x1 vector specifying number of rows and cols 9 | % for reshaping each of the columns of A 10 | % outputs I, an RGB image. red dots indicate the relative max 11 | % pixel intensity level. 12 | 13 | 14 | if nargin > 3 15 | nonneg = varargin{1}; 16 | else 17 | nonneg = false; 18 | end 19 | if nargin > 4 20 | mask = varargin{2}; 21 | end 22 | 23 | N = size(A,1); 24 | % M = size(A,2); 25 | 26 | 27 | spacing = 5; 28 | if nargin < 3 29 | a = floor(sqrt(size(A,2))); 30 | if size(A,2) > a*(a+1), nrows = a+1; 31 | else , nrows = a; end 32 | ncols = ceil(sqrt(size(A,2))); 33 | else 34 | nrows = dims(1); ncols = dims(2); 35 | end 36 | 37 | if nargin < 2 38 | wx = sqrt(N); 39 | wy = sqrt(N); 40 | else 41 | wx = dimI(1); 42 | wy = dimI(2); 43 | end 44 | 45 | if nonneg 46 | I = ones(wx*nrows+(nrows+1)*spacing, wy*ncols+(ncols+1)*spacing,3); 47 | else 48 | I = zeros(wx*nrows+(nrows+1)*spacing, wy*ncols+(ncols+1)*spacing,3); 49 | end 50 | 51 | % maxrange = max(abs(A(:))); 52 | 53 | for i = 1:size(A,2) 54 | if size(A,1) == wx*wy 55 | patch = reshape(A(:,i), wx, wy); 56 | else 57 | patch = zeros(wx, wy); 58 | patch(mask(:)) = A(:,i); 59 | [dx, dy] = gradient(mask); 60 | patch = patch + dx + dy; 61 | end 62 | sx = (wy+spacing) * floor((i-1)/nrows)+1 + 1; 63 | sy = (wx+spacing) * rem(i-1,nrows)+1 + 1; 64 | 65 | prange = max(abs(patch(:))); 66 | if prange > .00001 67 | if nonneg 68 | patch = patch / prange; 69 | else 70 | patch = .5 + .5*patch / prange; 71 | end 72 | else 73 | if nonneg 74 | patch = patch; % + .5; 75 | else 76 | end 77 | end 78 | % I(sy+wx-1-floor((wx-1)*prange/maxrange), sx+wy,:) = [1 0 0]; 79 | 80 | I(sy:sy+wx-1, sx:sx+wy-1,:) = repmat(patch,[1,1,3]); 81 | end 82 | -------------------------------------------------------------------------------- /code/support-functions/load_app_data.m: -------------------------------------------------------------------------------- 1 | function Data = load_app_data(app) 2 | %LOADS IMAGE used for GraFT functional application GUI 3 | % Takes in structure with .nam and .files, indicating path and file name 4 | % for images under said directory. Creates a simple uiprogressdlg figure 5 | % which reports progress. 6 | % 7 | % Created by Alex Estrada 10/19/2022 8 | %% 9 | 10 | 11 | 12 | %% Inputs 13 | Data = app.Data; 14 | 15 | %% Progress bar 16 | d = uiprogressdlg(app.UIFigure,'Title','Loading Images',... 17 | 'Message','1','Cancelable','on'); 18 | 19 | %% Data Loading & Updating 20 | if strcmp(Data.type, '.tif') 21 | tempFsim = Data.temp; 22 | steps = Data.Steps(1); 23 | Data.Fsim = zeros([size(tempFsim), steps]); 24 | 25 | for ll = 1:Data.Steps 26 | % Check for Cancel button press 27 | if d.CancelRequested 28 | Data.flag = 'Request Cancelled'; 29 | close(d) 30 | return 31 | end 32 | % Update progress, report current estimate 33 | d.Value = ll/steps; 34 | d.Message = sprintf('%d out of %d', ll, steps); 35 | 36 | % Load image 37 | Data.Fsim(:,:,ll) = imread(Data.name, ll); 38 | end 39 | 40 | else 41 | tempFsim = imread([Data.name, '\', Data.files(1).name]); 42 | steps = length(Data.files); 43 | Data.Fsim = zeros([size(tempFsim), steps]); 44 | 45 | for ll = 1:steps 46 | % Check for Cancel button press 47 | if d.CancelRequested 48 | Data.flag = 'Request Cancelled'; 49 | close(d) 50 | return 51 | end 52 | % Update progress, report current estimate 53 | d.Value = ll/steps; 54 | d.Message = sprintf('%d out of %d', ll, steps); 55 | 56 | % Load image 57 | fname = Data.files(ll).name; 58 | Data.Fsim(:,:,ll) = imread([Data.name, '\', fname]); 59 | end 60 | end 61 | 62 | d.Message = 'Done loading, finalizing structure type...'; 63 | Data.Fsim = im2double(Data.Fsim); 64 | Data.flag = 'Complete'; 65 | 66 | % Close the dialog box 67 | close(d); 68 | end -------------------------------------------------------------------------------- /code/external-code/RANN/rann32c.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mex.h" 3 | #include 4 | #include 5 | 6 | /* Output Arguments */ 7 | #define Idx plhs[0] 8 | #define Dis plhs[1] 9 | 10 | #if !defined(MAX) 11 | #define MAX(A, B) ((A) > (B) ? (A) : (B)) 12 | #endif 13 | 14 | #if !defined(MIN) 15 | #define MIN(A, B) ((A) < (B) ? (A) : (B)) 16 | #endif 17 | 18 | 19 | void mexFunction( int nlhs, mxArray *plhs[], 20 | int nrhs, const mxArray*prhs[] ) 21 | 22 | { 23 | double *yp; 24 | double *a,*dis, *w; 25 | int knn, m, n, isuper,numit, istat, nwords, i; 26 | int* idx; 27 | int nm = n*m; 28 | //double *a = (double*)(malloc(sizeof(double)*n*m)); 29 | 30 | 31 | if (nrhs !=5) { 32 | mexErrMsgTxt( "usage [Idx Dis] = rann_32(X,k,numit,isuper,istat)"); 33 | 34 | 35 | } 36 | if(nlhs != 2){ 37 | mexErrMsgTxt( "usage [Idx Dis] = rann_32(X,k,numit,isuper,istat)"); 38 | 39 | } 40 | 41 | a = mxGetPr(prhs[0]); 42 | knn =mxGetScalar(prhs[1]); 43 | numit = mxGetScalar(prhs[2]); 44 | isuper = mxGetScalar(prhs[3]); 45 | istat = mxGetScalar(prhs[4]); 46 | 47 | m = mxGetM(prhs[0]); 48 | n = mxGetN(prhs[0]); 49 | 50 | Idx = mxCreateNumericMatrix(knn,n,mxINT32_CLASS, mxREAL); 51 | if (Idx==NULL) { 52 | mexErrMsgTxt("Cannot allocate enough memory\n"); 53 | 54 | } 55 | 56 | Dis = mxCreateDoubleMatrix(knn,n, mxREAL); 57 | if (Dis==NULL) { 58 | mexErrMsgTxt("Cannot allocate enough memory\n"); 59 | 60 | } 61 | 62 | 63 | idx = mxGetData(Idx); 64 | dis = mxGetPr(Dis); 65 | 66 | 67 | nwords = 0; 68 | get_rann_memory(n,m,knn,numit, &nwords); 69 | 70 | w = (double *)malloc(sizeof(double)*nwords); 71 | if (w == 0) { 72 | mexErrMsgTxt("Cannot allocate enough memory\n"); 73 | 74 | } 75 | 76 | rann_all(n,m,a,numit,isuper,istat,idx,dis,knn,w,nwords); 77 | //tree_test_(&n,&m,a,&numit,&isuper,&istat,idx,dis,&knn,w,&nwords); 78 | 79 | 80 | label_report_done: 81 | 82 | 83 | return; 84 | 85 | } 86 | -------------------------------------------------------------------------------- /code/graph-sparse-coding/PCA.m: -------------------------------------------------------------------------------- 1 | function [eigvector, eigvalue] = PCA(data, options) 2 | %PCA Principal Component Analysis 3 | % 4 | % Usage: 5 | % [eigvector, eigvalue] = PCA(data, options) 6 | % [eigvector, eigvalue] = PCA(data) 7 | % 8 | % Input: 9 | % data - Data matrix. Each row vector of fea is a data point. 10 | % 11 | % options.ReducedDim - The dimensionality of the reduced subspace. If 0, 12 | % all the dimensions will be kept. 13 | % Default is 0. 14 | % 15 | % Output: 16 | % eigvector - Each column is an embedding function, for a new 17 | % data point (row vector) x, y = x*eigvector 18 | % will be the embedding result of x. 19 | % eigvalue - The sorted eigvalue of PCA eigen-problem. 20 | % 21 | % Examples: 22 | % fea = rand(7,10); 23 | % options=[]; 24 | % options.ReducedDim=4; 25 | % [eigvector,eigvalue] = PCA(fea,4); 26 | % Y = fea*eigvector; 27 | % 28 | % version 3.0 --Dec/2011 29 | % version 2.2 --Feb/2009 30 | % version 2.1 --June/2007 31 | % version 2.0 --May/2007 32 | % version 1.1 --Feb/2006 33 | % version 1.0 --April/2004 34 | % 35 | % Written by Deng Cai (dengcai AT gmail.com) 36 | % 37 | 38 | if (~exist('options','var')) 39 | options = []; 40 | end 41 | 42 | ReducedDim = 0; 43 | if isfield(options,'ReducedDim') 44 | ReducedDim = options.ReducedDim; 45 | end 46 | 47 | 48 | [nSmp,nFea] = size(data); 49 | if (ReducedDim > nFea) || (ReducedDim <=0) 50 | ReducedDim = nFea; 51 | end 52 | 53 | 54 | if issparse(data) 55 | data = full(data); 56 | end 57 | sampleMean = mean(data,1); 58 | data = (data - repmat(sampleMean,nSmp,1)); 59 | 60 | [eigvector, eigvalue] = mySVD(data',ReducedDim); 61 | eigvalue = full(diag(eigvalue)).^2; 62 | 63 | if isfield(options,'PCARatio') 64 | sumEig = sum(eigvalue); 65 | sumEig = sumEig*options.PCARatio; 66 | sumNow = 0; 67 | for idx = 1:length(eigvalue) 68 | sumNow = sumNow + eigvalue(idx); 69 | if sumNow >= sumEig 70 | break; 71 | end 72 | end 73 | eigvector = eigvector(:,1:idx); 74 | end 75 | 76 | 77 | -------------------------------------------------------------------------------- /code/dictionary-learning/bilin_Hessfun.m: -------------------------------------------------------------------------------- 1 | function Happ = bilin_Hessfun(x, lambda, S, Y, A, h, opt) 2 | 3 | % function [fun,varargout] = bilin_Hessfun(S, Y, A, h, D, opt) 4 | % 5 | % Function to calculate hessian multiplication function 6 | % for 'HessianMultiplyFcn' 7 | % 8 | % 9 | % calculate Hessians 10 | % First term dS 2*vec((H^T*H)*S*(A*A^T)) = 2*kron((A*A^T),(H^T*H)) 11 | % Second term dS 2*H^T*H*S = 2*kron(I,(H^T*H)) 12 | % Third term dS 2*(H^T*H)*S = 2*kron(I,(H^T*H)) 13 | % Fourth term dS 2*H^T*H*S*W = 2*kron(W,(H^T*H)); W = 1-I 14 | % 15 | % 2018 - Adam Charles 16 | 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 | 19 | h = vec(h); 20 | 21 | S = reshape(S(:),[size(Y,1), size(A,1)]); % Make sure that S is a matrix of the correct size 22 | 23 | W = ones(size(A,1)); 24 | W(1:size(W,1)+1:end) = 0; 25 | 26 | HHS = 2*applyH(applyH(S,h,1),h,2); 27 | 28 | % H = hankel(flipud([h;zeros(size(S,1),1)])); 29 | % H = flipud(H(ceil(size(h,1)/2) +(1:size(S,1)),1:size(S,1))); 30 | % varargout{2} = 2*kron(A*A' + (opt.lambda2+opt.lambda3)*eye(size(A,1)) + opt.lambda3*W, H'*H); 31 | % varargout{2} = double(varargout{2}); 32 | 33 | Happ = vec(HHS*(double(A*A') + (opt.lambda2+opt.lambda3)*eye(size(A,1)) + opt.lambda3*W)); 34 | 35 | end 36 | 37 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 38 | %% Auxiliary function to apply H and H^T 39 | 40 | function Y = applyH(X,h,T) 41 | 42 | % Function to apply the linear operator H and it's transpose H^T using 43 | % convolutional operators. H is defined as: 44 | % H = hankel(flipud([h;zeros(size(X,1),1)])); 45 | % H = flipud(H(ceil(size(h,1)/2) +(1:size(X,1)),1:size(X,1))); 46 | 47 | if T == 1 48 | Y = convn(X, h, 'same'); % y = flipud(H*x); 49 | elseif T == 2 50 | Y = convn(X, flipud([h;0]),'same'); % z1 = H.'*y1; 51 | else 52 | error('T invalid: options for T are T=1 for H(X) and T=2 for H^T(X)!') 53 | end 54 | 55 | end 56 | 57 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/plotting-code/correlation_image.m: -------------------------------------------------------------------------------- 1 | function Cn = correlation_image(Y,sz,d1,d2,flag_norm) 2 | %%%%% from CNMF 3 | % construct correlation image based on neighboing pixels 4 | % Y: raw data 5 | % sz: define the relative location of neighbours. it can be scalar, 2 6 | % element vector or a binary matrix 7 | % scalar: number of nearest neighbours, either 4 or 8, default 4 8 | % 2 element vector: [rmin, rmax], the range of neighbours. the 9 | % distance between the neighbour and the pixel is d, dmin <= r < 10 | % dmax. 11 | % matrix: a squared matrix (2k+1)*(2k+1)indicating the location of neighbours 12 | % d1,d2: spatial dimensions 13 | % flag_norm: indicate whether Y has been normalized and centered ( 1 is 14 | % yes, 0 is no) 15 | 16 | % Author: Eftychios A. Pnevmatikakis, Simons Foundation, 2015 17 | % with modifications from Pengcheng Zhou, Carnegie Mellon University, 2015 18 | 19 | %% preprocess the raw data 20 | if nargin<5; flag_norm = false; end 21 | if ismatrix(Y) 22 | Y = reshape(Y,d1,d2,size(Y,2)); 23 | end 24 | if ~strcmpi(class(Y),'single'); Y = single(Y); end 25 | if (nargin<2); sz = [0,1,0; 1,0,1; 0,1,0]; end 26 | 27 | [d1,d2,~] = size(Y); % image dimension 28 | 29 | if (~flag_norm) 30 | % centering 31 | mY = mean(Y,3); 32 | Y = bsxfun(@minus, Y, mY); 33 | % normalizing 34 | sY = sqrt(mean(Y.*Y, 3)); 35 | Y = bsxfun(@times, Y, 1./sY); 36 | end 37 | 38 | %% construct a matrix indicating location of the matrix 39 | if isscalar(sz) 40 | if sz == 8 % 8 nearest neighbours 41 | sz = [1,1,1; 1,0,1; 1,1,1]; 42 | elseif sz==4 43 | sz = [0,1,0; 1,0,1; 0,1,0]; 44 | end 45 | elseif length(sz(:)) == 2 46 | % the specified neighbours has a distance within the domain [dmin, 47 | % dmax) 48 | sz = ceil(sz); 49 | dmin = min(sz); dmax = max(sz); 50 | rsub = (-dmax+1):(dmax-1); % row subscript 51 | csub = rsub; % column subscript 52 | [cind, rind] = meshgrid(csub, rsub); 53 | R = sqrt(cind.^2+rind.^2); 54 | sz = (R>=dmin) .* (R size(RESULTS(i).S,2) 13 | break; 14 | end 15 | cnt = cnt + 1; 16 | S(patch_lin_idx,cnt) = reshape(RESULTS(i).S(:,:,k),[],1); 17 | end 18 | MASK(patch_lin_idx) = MASK(patch_lin_idx) + 1; 19 | end 20 | %% 21 | S(:,cnt+1:end) = []; 22 | D = cell2mat({RESULTS(:).D}); 23 | ff = find(sum(S,1)==0); 24 | 25 | D(:,ff) = []; % Initialize the full dictionary 26 | S(:,ff) = []; % Initialize the full presence maps 27 | 28 | graphK = sparse(size(S,1),size(S,1)); 29 | for i = 1:n_patches 30 | patch_lin_idx = patch_to_linear(patches{i}, sizY); 31 | graphK(patch_lin_idx,patch_lin_idx) = graphK(patch_lin_idx,patch_lin_idx) + RESULTS(i).K; 32 | end 33 | %% normalize graph 34 | deg = sum(graphK,2)+eps; 35 | one_over_D = spdiags(1./deg,0,size(graphK,1),size(graphK,2)); 36 | graphK = one_over_D*graphK; 37 | 38 | %%%%%%%%% 39 | end 40 | 41 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 42 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 43 | 44 | function idx = patch_to_linear(patch, sizY) 45 | % helper function to build linear indices from patch start/stop indices 46 | slice_idx = patch_to_indices(patch); 47 | subs_idx = cell(1, numel(slice_idx)); 48 | [subs_idx{:}] = ndgrid(slice_idx{:}); 49 | subs_idx = cellfun(@(x) x(:), subs_idx, 'un', false); 50 | idx = sub2ind(sizY(1:end-1), subs_idx{:}); 51 | end 52 | 53 | function idx = patch_to_indices(patch) 54 | % helper function to build indices vector from patch start/stop indices 55 | idx = arrayfun(@(x,y) x:y, patch(1:2:end), patch(2:2:end), 'un', false); 56 | end 57 | 58 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 59 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/external-code/from_caiman/construct_patches.m: -------------------------------------------------------------------------------- 1 | function patches = construct_patches(sizY,siz,overlap,min_size) 2 | 3 | % constructs the coordinates of the different patches for batch processing 4 | % INPUTS 5 | % sizY: size of input data (excluding time dimension) 6 | % siz: size of each patch (default: [32,32,4], if third spatial dimension is present) 7 | % overlap: amount of overlap in each direction (default: [4,4,2], if third spatial dimension is present) 8 | % min_size: minimum patch size is each direction, otherwise merge with previous patch (defalt: [4,4,2]) 9 | 10 | % OUTPUT 11 | % patches: cell structure with start/end points for each patch 12 | 13 | % Author: Eftychios A. Pnevmatikakis, Simons Foundation, 2016 14 | 15 | dimY = length(sizY); % dimension of dataset (2d or 3d) 16 | 17 | if nargin < 4 || isempty(min_size) 18 | min_size = [8,8,3*ones(1,dimY-2)]; 19 | end 20 | 21 | if nargin < 3 || isempty(overlap) 22 | overlap = [4,4,2*ones(1,dimY-2)]; 23 | end 24 | 25 | if nargin < 2 || isempty(siz) 26 | siz = [32,32,4*ones(1,dimY-2)]; 27 | end 28 | 29 | if any(siz<=overlap); error('Size of patch must be greater than the amount of overlap'); end 30 | 31 | x_start = 1:siz(1)-overlap(1):sizY(1); 32 | x_end = min(x_start + siz(1) - 1,sizY(1)); 33 | x_start = x_end - siz(1)+1; 34 | if (x_end(end) - x_start(end) + 1 < min_size(1)) || (length(x_end) > 1 && (x_end(end) - x_end(end-1) < min_size(1))) 35 | x_start(end) = []; 36 | x_end(end-1) = []; 37 | end 38 | 39 | y_start = 1:siz(2)-overlap(2):sizY(2); 40 | y_end = min(y_start + siz(2) - 1,sizY(2)); 41 | y_start = y_end - siz(2)+1; 42 | if (y_end(end) - y_start(end) + 1 < min_size(2)) || (length(y_end) > 1 && (y_end(end) - y_end(end-1) < min_size(2))) 43 | y_start(end) = []; 44 | y_end(end-1) = []; 45 | end 46 | 47 | if dimY == 3 48 | z_start = 1:siz(3)-overlap(3):sizY(3); 49 | z_end = min(z_start + siz(3) - 1,sizY(3)); 50 | if z_end(end) - z_start(end) + 1 < min_size(3) 51 | z_start(end) = []; 52 | z_end(end-1) = []; 53 | end 54 | else 55 | z_start = 1; 56 | z_end = 1; 57 | end 58 | 59 | [X1,Y1,Z1] = meshgrid(x_start,y_start,z_start); 60 | [X2,Y2,Z2] = meshgrid(x_end,y_end,z_end); 61 | 62 | if dimY == 2 63 | Z1 = []; 64 | Z2 = []; 65 | end 66 | 67 | patches = mat2cell([X1(:),X2(:),Y1(:),Y2(:),Z1(:),Z2(:)],ones(numel(X1),1),2*dimY); -------------------------------------------------------------------------------- /code/graph-sparse-coding/GraphRegularizedSparseCodingDemo.m: -------------------------------------------------------------------------------- 1 | clear; 2 | load('lights=27.mat'); 3 | nClass = length(unique(gnd)); 4 | 5 | %Normalize each data vector to have L2-norm equal to 1 6 | fea = NormalizeFea(fea); 7 | 8 | %Clustering in the original space 9 | rand('twister',5489); 10 | label = litekmeans(fea,nClass,'Replicates',10); 11 | MIhat = MutualInfo(gnd,label); 12 | disp(['kmeans use all the features. MIhat: ',num2str(MIhat)]); 13 | %kmeans in the original space. MIhat: 0.66064 14 | 15 | options.ReducedDim = 64; 16 | eigvector = PCA(fea, options); 17 | newfea = fea*eigvector; 18 | newfea = NormalizeFea(newfea); 19 | %Clustering in 64-dim PCA subspace 20 | rand('twister',5489); 21 | label = litekmeans(newfea,nClass,'Replicates',10); 22 | MIhat = MutualInfo(gnd,label); 23 | disp(['kmeans in the 64-dim PCA subspace. MIhat: ',num2str(MIhat)]); 24 | %kmeans in the 64-dim PCA subspace. MIhat: 0.65946 25 | 26 | rand('twister',5489); 27 | W = constructW(fea); 28 | 29 | nBasis = 128; 30 | alpha = 1; 31 | beta = 0.1; 32 | nIters = 15; 33 | rand('twister',5489); 34 | warning('off', 'all'); 35 | [B, S, stat] = GraphSC(newfea', W, nBasis, alpha, beta, nIters); %' 36 | %Clustering in 128-dim GraphSC subspace 37 | rand('twister',5489); 38 | label = litekmeans(S',nClass,'Replicates',10); %' 39 | MIhat = MutualInfo(gnd,label); 40 | disp(['Clustering in the ',num2str(nBasis),'-dim GraphSC subspace with ',num2str(nIters),' iterations. MIhat: ',num2str(MIhat)]); 41 | %Clustering in the 128-dim GraphSC subspace with 15 iterations. MIhat: 0.80253 42 | 43 | nIters = 30; 44 | rand('twister',5489); 45 | warning('off', 'all'); 46 | [B, S, stat] = GraphSC(newfea', W, nBasis, alpha, beta, nIters); %' 47 | rand('twister',5489); 48 | label = litekmeans(S',nClass,'Replicates',10); %' 49 | MIhat = MutualInfo(gnd,label); 50 | disp(['Clustering in the ',num2str(nBasis),'-dim GraphSC subspace with ',num2str(nIters),' iterations. MIhat: ',num2str(MIhat)]); 51 | %Clustering in the 128-dim GraphSC subspace with 30 iterations. MIhat: 0.86948 52 | 53 | nIters = 100; 54 | rand('twister',5489); 55 | warning('off', 'all'); 56 | [B, S, stat] = GraphSC(newfea', W, nBasis, alpha, beta, nIters); %' 57 | rand('twister',5489); 58 | label = litekmeans(S',nClass,'Replicates',10); %' 59 | MIhat = MutualInfo(gnd,label); 60 | disp(['Clustering in the ',num2str(nBasis),'-dim GraphSC subspace with ',num2str(nIters),' iterations. MIhat: ',num2str(MIhat)]); 61 | %Clustering in the 128-dim GraphSC subspace with 100 iterations. MIhat: 0.92865 -------------------------------------------------------------------------------- /code/dictionary-learning/gen_multi_infer.m: -------------------------------------------------------------------------------- 1 | function coef_vals = gen_multi_infer(dictionary_n, x_im, infer_hand, opts) 2 | 3 | % coef_vals = multi_l1ls(dictionary_n, x_im, infer_type, opts) 4 | % 5 | % Function to perform inference on a multitude of test vectors. The 6 | % inference algorithm given by infer_type is run on each column of x_im 7 | % with repect to dictionary_n. 8 | % 9 | % Inputs: 10 | % dictionary_n - The dictionary to decompose the data into 11 | % x_im - A matrix with the columns as data to decompose 12 | % infer_hand - Handle for a wrapper that calls an inference 13 | % function. Included in the package is the default 14 | % conjugate gradient descent method (both wrapper 15 | % and function) as well as wrappers for some 16 | % recommended inference functions easily available 17 | % online. Some included wrappers are The 'MP' and 18 | % 'OOMP' from the SparseLab100 library available at 19 | % http://sparselab.stanford.edu, the OMP_qr from 20 | % the sparsify package (v4 or later) available at 21 | % http://www.personal.soton.ac.uk/tb1m08/sparsify/s 22 | % parsify.html, and the L1-regularized functions 23 | % l1_ls and l1_ls_nonneg available at 24 | % http://www.stanford.edu/~boyd/l1_ls/. To use a 25 | % different inference function, simply create a 26 | % wrapper as per the examples for the functions 27 | % above. 28 | % opts - A struct of options needed for the optimization 29 | % program selected. 30 | % 31 | % Outputs: 32 | % coef_vals - optimized coefficients 33 | % 34 | % Last Modified 6/3/2010 - Adam Charles 35 | 36 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37 | %% Initializations 38 | 39 | % Initialize coefficients 40 | coef_vals = zeros(size(dictionary_n, 2), opts.in_iter); 41 | 42 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 43 | %% Perform the L1-regulized optimization on the data 44 | 45 | 46 | parfor index_in = 1:opts.in_iter 47 | coef_vals(:, index_in) = feval(infer_hand, dictionary_n, x_im(:,index_in),... 48 | opts); 49 | end 50 | 51 | 52 | end 53 | 54 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 55 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 56 | -------------------------------------------------------------------------------- /code/support-functions/mkDataEmbedding.m: -------------------------------------------------------------------------------- 1 | function corr_kern = mkDataEmbedding(data_obj, configParams) 2 | 3 | % corr_kern = mkDataEmbedding(configParams) 4 | % 5 | % Make an embedding matrix (rename eventually to "mkDataGraph" 6 | % 7 | % 2019 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Input parsing 11 | 12 | if nargin < 2 || isempty(configParams) % Make sure that configParams is a struct 13 | clear configParams 14 | configParams = struct; 15 | end 16 | 17 | dParams.self_tune = 7; % self-tuning adaptive scale (Zelnik-Manor & Perona) 18 | dParams.dist_type = 'euclidean'; % distance type for kNN calculation ('euclidean' will use RANN) 19 | dParams.kNN = 49; % kNN 20 | dParams.reduce_dim = false; % apply PCA dim reduction to make knn search faster 21 | configParams = setParams(dParams, configParams); % Set the parameters 22 | 23 | 24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 25 | %% Create the embedding 26 | 27 | % reduce the time dimension with pca to make knn search faster 28 | if configParams.reduce_dim 29 | if size(data_obj,3)>1 % If the data is in a 3D array (instead of 2D)... 30 | data_obj = reshape(data_obj,[],size(data_obj,3)); % ... Then reshape the array to do PCA 31 | end 32 | [U,S,~] = pcafast(data_obj,15); % Run a fast version of OCA 33 | data_obj = U; % Save the principle components as the data to embed 34 | end 35 | 36 | if size(data_obj,3) > 1 37 | [K, ~] = calcAffinityMat(double(reshape(data_obj, [], ... 38 | size(data_obj,3)))', configParams); % Calculate the affinity matrix (reshaped from a 3D array) 39 | else 40 | [K, ~] = calcAffinityMat(double(data_obj'), configParams); % Calculate the affinity matrix (if matrix is given directly) 41 | end 42 | K(1:(size(K,1)+1):end) = 0; % Set the diagonal elements to zero 43 | corr_kern = bsxfun(@rdivide,K,(sum(K,2)+eps)); % Normalize the rows to make the graph matrix 44 | 45 | end 46 | 47 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 48 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 49 | -------------------------------------------------------------------------------- /code/support-functions/calcAffinityMat.m: -------------------------------------------------------------------------------- 1 | function [K, nnData] = calcAffinityMat(X, configParams) 2 | % calculate affinity matrix of data matrix X, size N by M 3 | % N - length of feature vector, M - number of vectors 4 | % affinity matrix is calculated for kNN nearest neighbors, resulting in 5 | % sparse matrix. This saves on runtime. 6 | % the scale for the affinity matrix can be set using auto-tuning 7 | % 8 | % Gal Mishne 9 | 10 | dParams.dist_type = 'euclidean'; 11 | dParams.kNN = 16; 12 | dParams.self_tune = 0; 13 | dParams.verbose = false; 14 | dParams.isuper = 1; 15 | configParams = setParams(dParams, configParams); 16 | 17 | [~,M] = size(X); 18 | configParams.kNN = min(configParams.kNN,M); 19 | 20 | %% affinity matrix 21 | %tic 22 | if exist('rann32c','file') == 3 23 | [Inds, Dis] = rann32c(X,configParams.kNN-1,5,configParams.isuper,0); 24 | nnData.nnDist = sqrt([0*ones(1,M);Dis]); 25 | nnData.nnInds = [1:M;Inds]; 26 | elseif exist('rann32','file') && strcmp(configParams.dist_type,'euclidean') 27 | [Inds, Dis] = rann32(X,configParams.kNN-1,5,configParams.isuper,0); 28 | nnData.nnDist = sqrt([0*ones(1,M);Dis]); 29 | nnData.nnInds = [1:M;Inds]; 30 | else 31 | [Inds, Dis] = knnsearch(X',X','K',configParams.kNN); 32 | nnData.nnDist = Dis'; 33 | nnData.nnInds = Inds'; 34 | end 35 | %toc 36 | 37 | % Total number of entries in the W matrix 38 | numNonZeros = configParams.kNN * M; 39 | % Using sparse matrix for affinity matrix 40 | ind = 1; 41 | 42 | % calc the sparse row and column indices 43 | rowInds = repmat((1:M),configParams.kNN,1); 44 | rowInds = rowInds(:); 45 | colInds = double(nnData.nnInds(:)); 46 | vals = nnData.nnDist(:); 47 | 48 | autotuneVals = zeros(numNonZeros,1); 49 | if configParams.self_tune 50 | nnAutotune = min(configParams.self_tune,size(nnData.nnDist,2)); 51 | sigmaKvec = (nnData.nnDist(nnAutotune,:)); 52 | end 53 | if configParams.self_tune 54 | for i = 1:M 55 | autotuneVals(ind : ind + configParams.kNN - 1) = sigmaKvec(i) * sigmaKvec(nnData.nnInds(:,i)); 56 | ind = ind + configParams.kNN; 57 | end 58 | end 59 | % sparse affinity matrix of dataset X 60 | nnData.dstsX = sparse(rowInds, colInds, vals, M, M); 61 | nnData.indsXX = sub2ind([M, M], rowInds, colInds); 62 | 63 | 64 | % setting local scale for each sample, 65 | % following "Self-tuning Clustering", Zelink-Manor and Perona 66 | if configParams.self_tune 67 | vals = exp(-vals.^2./(autotuneVals+eps)); 68 | K = sparse(rowInds, colInds, vals, M, M); 69 | else 70 | sig = median(vals); 71 | vals = exp(-vals.^2/sig^2); 72 | K = sparse(rowInds, colInds, vals, M, M); 73 | end 74 | K = (K + K')/2; 75 | return 76 | -------------------------------------------------------------------------------- /code/graph-sparse-coding/constructKernel.m: -------------------------------------------------------------------------------- 1 | function K = constructKernel(fea_a,fea_b,options) 2 | % function K = constructKernel(fea_a,fea_b,options) 3 | % Usage: 4 | % K = constructKernel(fea_a,[],options) 5 | % 6 | % K = constructKernel(fea_a,fea_b,options) 7 | % 8 | % fea_a, fea_b : Rows of vectors of data points. 9 | % 10 | % options : Struct value in Matlab. The fields in options that can 11 | % be set: 12 | % KernelType - Choices are: 13 | % 'Gaussian' - e^{-(|x-y|^2)/2t^2} 14 | % 'Polynomial' - (x'*y)^d 15 | % 'PolyPlus' - (x'*y+1)^d 16 | % 'Linear' - x'*y 17 | % 18 | % t - parameter for Gaussian 19 | % d - parameter for Poly 20 | % 21 | % version 1.0 --Sep/2006 22 | % 23 | % Written by Deng Cai (dengcai2 AT cs.uiuc.edu) 24 | % 25 | 26 | if (~exist('options','var')) 27 | options = []; 28 | else 29 | if ~isstruct(options) 30 | error('parameter error!'); 31 | end 32 | end 33 | 34 | 35 | 36 | %================================================= 37 | if ~isfield(options,'KernelType') 38 | options.KernelType = 'Gaussian'; 39 | end 40 | 41 | switch lower(options.KernelType) 42 | case {lower('Gaussian')} % e^{-(|x-y|^2)/2t^2} 43 | if ~isfield(options,'t') 44 | options.t = 1; 45 | end 46 | case {lower('Polynomial')} % (x'*y)^d 47 | if ~isfield(options,'d') 48 | options.d = 2; 49 | end 50 | case {lower('PolyPlus')} % (x'*y+1)^d 51 | if ~isfield(options,'d') 52 | options.d = 2; 53 | end 54 | case {lower('Linear')} % x'*y 55 | otherwise 56 | error('KernelType does not exist!'); 57 | end 58 | 59 | 60 | %================================================= 61 | 62 | switch lower(options.KernelType) 63 | case {lower('Gaussian')} 64 | if isempty(fea_b) 65 | D = EuDist2(fea_a,[],0); 66 | else 67 | D = EuDist2(fea_a,fea_b,0); 68 | end 69 | K = exp(-D/(2*options.t^2)); 70 | case {lower('Polynomial')} 71 | if isempty(fea_b) 72 | D = full(fea_a * fea_a'); 73 | else 74 | D = full(fea_a * fea_b'); 75 | end 76 | K = D.^options.d; 77 | case {lower('PolyPlus')} 78 | if isempty(fea_b) 79 | D = full(fea_a * fea_a'); 80 | else 81 | D = full(fea_a * fea_b'); 82 | end 83 | K = (D+1).^options.d; 84 | case {lower('Linear')} 85 | if isempty(fea_b) 86 | K = full(fea_a * fea_a'); 87 | else 88 | K = full(fea_a * fea_b'); 89 | end 90 | otherwise 91 | error('KernelType does not exist!'); 92 | end 93 | 94 | if isempty(fea_b) 95 | K = max(K,K'); 96 | end 97 | 98 | 99 | -------------------------------------------------------------------------------- /code/support-functions/denoiseCIinSpace.m: -------------------------------------------------------------------------------- 1 | function mov = denoiseCIinSpace(mov, varargin) 2 | 3 | % denoiseCIinSpace(fuObj, varargin) 4 | % 5 | % Function to denoise calcium imaging data in space using wavelet 6 | % denoising. To avoid the missing data problem, error frames from burst 7 | % errors are filled in using cubic spline interpolation. 8 | % 9 | % 2020 - Adam Charles 10 | 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | %% Input parsing 13 | 14 | p = inputParser; % Set up an object to parse all of the various inputs 15 | p.addParameter('smoothLvl' , 4 ); % Select at what wavelet level to smooth at 16 | p.addParameter('DenoisingMethod' , 'Bayes' ); % For the situation that 'prctile' is chosen, which percentile should the baseline image be calculated using 17 | p.addParameter('wDenoiseFun' , 'wdenoise2'); % Select which pixels to select: either an array or 'vary' or 'rand' 18 | p.addParameter('Wavelet' , 'sym4' ); % Select hoe many traces to select 19 | 20 | parse(p,varargin{:}); 21 | p = p.Results; 22 | 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | %% Some initializations 25 | 26 | movSize = [size(mov,1), size(mov,2), size(mov,3)]; % Get size of movie 27 | matSize = [movSize(1)*movSize(2),movSize(3)]; % Get size of reshaped matrix (pix X frames) 28 | 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | %% Function to denoise time traces 31 | 32 | fprintf('Smoothing...') 33 | if p.smoothLvl == 0 % No smoothing, nothing to do 34 | elseif p.smoothLvl > 0 35 | switch p.wDenoiseFun 36 | case 'wdenoise2' % Choise to use 'wdenoise' for denoising 37 | wdMeth = p.DenoisingMethod; 38 | wdSmth = p.smoothLvl; 39 | wdWave = p.Wavelet; 40 | fprintf('starting denoising\n') 41 | parfor ll = 1:movSize(3) 42 | mov(:,:,ll) = cast(wdenoise2(double(mov(:,:,ll)),... 43 | wdSmth,'DenoisingMethod',wdMeth,... 44 | 'Wavelet', wdWave), 'like', mov(:,:,ll));% Run the wavelet denoising 45 | end 46 | otherwise 47 | warning('No valid denoising function chosen! Skipping denoising step.\n') 48 | end 49 | else 50 | warning('Bad value for smoothLvl: defaulting to NOT smoothing time traces') 51 | end 52 | fprintf('done.\n') 53 | 54 | end 55 | 56 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 57 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GraFT-analysis 2 | 3 | GraFT (Graph-Filtered Temporal) dictionary learning is a signal extraction method for spatio-temporal data. GraFT uses a diffusion map to learn a graph over spatial pixels that enables for stochastic filtering of learned sparse representations over each pixel's time-trace. The sparse representations are modeled as in a hierarchical dictionary learning framework with correlated decompositions over the graph. 4 | 5 | # Use case 6 | 7 | GraFT can be applied to any 3D tensor dataset where each vector at each position in the first two 'ways' can be decomposed as a sparse sum and the decomposition can be correlated along complex spatial morphologies. The main use case we present is to calcium imaging data, where data at different zoom levels can have highly varying spatial statistics, yet similar temporal sparse decompositions. Please see the demo file for an example on how to use the main function. 8 | 9 | # Implementation notes 10 | 11 | GraFT is implemented in MATLAB, and at its core uses a sparse decomposition (re-weighted l1-optimization) over every pixel. This step is embarrassingly parallel and so using a parallel pool is highly encouraged to increase runtime. Moreover we provide a patch-based version of GraFT that splits the full field-of-view into smaller, overlapping sections. Each patch is independently analyzed and the results are merged for a full decomposition of the data. 12 | 13 | # Compatibility 14 | 15 | With many different ways to load data, GraFT is now compatible with Neurodata Without Borders (NWB) file formats! Included in this repository are helpful tutorials that cover how to create an optical physiology experiment with standard two-photon imaging data, as well as a walk-through tutorial of how one can run GraFT on existing NWB files. 16 | 17 | # Toolboxes 18 | * [Econometrics Toolbox](https://www.mathworks.com/products/econometrics.html) (required) 19 | * [Statistics and Machine Learning Toolbox](https://www.mathworks.com/products/statistics.html) (required) 20 | * [Parallel Computing Toolbox](https://www.mathworks.com/products/parallel-computing.html) (highly recommended) 21 | * [Model Predictive Control Toolbox](https://www.mathworks.com/help/mpc/index.html?s_tid=CRUX_lftnav) (QP, recommended) 22 | * [Wavelet Toolbox](https://www.mathworks.com/help/wavelet/getting-started-with-wavelet-toolbox.html) (Denoising, pre-processing recommended) 23 | * [NoRMCorre](https://github.com/flatironinstitute/NoRMCorre) (Motion Correction, optional) 24 | * [MovieSlider](https://github.com/sakoay/MovieSlider) (Plotting, optional) 25 | * [MatNWB](https://github.com/NeurodataWithoutBorders/matnwb) (Optional) 26 | 27 | # Manuscript 28 | 29 | The details of GraFT are described in: 30 | 31 | A.S. Charles, N. Cermak, R. Affan, B. Scott, J. Schiller & G. Mishne. GraFT: Graph Filtered Temporal Dictionary Learning for Functional Neural Imaging. 32 | 33 | https://pubmed.ncbi.nlm.nih.gov/35533160/ 34 | -------------------------------------------------------------------------------- /code/dictionary-learning/initialize_dictionary.m: -------------------------------------------------------------------------------- 1 | function dictionary_initial = initialize_dictionary(varargin) 2 | 3 | % dictionary_initial = initialize_dictionary(varargin) 4 | % 5 | % Function to generate a random initial dictionary, or to load a dictionary 6 | % from a file. 7 | % 8 | % Use: 9 | % - initialize_dictionary(n_elem, v_size) creates a radom matrix with 10 | % zero mean and unit variance of size (v_size)x(n_elem). The columns 11 | % (the dictionary elements) are normalized to the unit circle. 12 | % - initialize_dictionary(n_elem, v_size, nneg) where nneg is a 13 | % scalar generates the dictionary from a uniform distribution, then 14 | % normalizes the columns to the unit circle (for non-negativity 15 | % constraints) 16 | % - initialize_dictionary(n_elem, v_size, save_name) loads the 17 | % dictionary from the string specified in save_name, and checks the 18 | % dictionary dimensions against the desired dimensions. 19 | % 20 | % 21 | % Last Modified 6/3/2010 - Adam Charles 22 | 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | %% Parse Inputs 25 | 26 | 27 | if nargin == 2 28 | n_elem = varargin{1}; 29 | v_size = varargin{2}; 30 | new_basis = 1; 31 | nneg_opt = 0; 32 | elseif nargin == 3 33 | n_elem = varargin{1}; 34 | v_size = varargin{2}; 35 | save_name = varargin{3}; 36 | if isscalar(save_name) 37 | new_basis = 1; 38 | nneg_opt = save_name; 39 | elseif ischar(save_name) 40 | new_basis = 0; 41 | else 42 | error('Third input must be a string for the dictionary to load, or a scalar nonegativity indicator!') 43 | end 44 | end 45 | 46 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 47 | %% Generate initial dictionary 48 | 49 | fprintf('Using %d dictionary elements...\n', n_elem) 50 | % Initialize Elements 51 | if new_basis == 1 52 | if nneg_opt == 1; 53 | dictionary_initial = abs(rand(v_size, n_elem)); 54 | else 55 | dictionary_initial = randn(v_size, n_elem); 56 | end 57 | % Normalize the initial basis 58 | dictionary_initial = (dictionary_initial./(ones(v_size, 1)*... 59 | sqrt(sum(dictionary_initial.^2, 1)))); 60 | fprintf('Starting with random initial Dictionary Elements.\n') 61 | else 62 | load(save_name) 63 | fprintf('Starting with older Basis Elements.\n') 64 | dictionary_initial = basic_cell.basis; 65 | % Test loaded image size for compatability 66 | if (size(dictionary_initial, 1) ~= v_size) || (size(dictionary_initial, 2) ~= n_elem) 67 | error('Loaded dictionary size does not match required numbers!!') 68 | end 69 | end 70 | 71 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 72 | end 73 | 74 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 75 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 76 | -------------------------------------------------------------------------------- /code/graph-sparse-coding/learn_basis.m: -------------------------------------------------------------------------------- 1 | function B = learn_basis(X, S, l2norm, Binit) 2 | % Learning basis using Lagrange dual (with basis normalization) 3 | % 4 | % This code solves the following problem: 5 | % 6 | % minimize_B 0.5*||X - B*S||^2 7 | % subject to ||B(:,j)||_2 <= l2norm, forall j=1...size(S,1) 8 | % 9 | % The detail of the algorithm is described in the following paper: 10 | % 'Efficient Sparse Codig Algorithms', Honglak Lee, Alexis Battle, Rajat Raina, Andrew Y. Ng, 11 | % Advances in Neural Information Processing Systems (NIPS) 19, 2007 12 | % 13 | % Written by Honglak Lee 14 | % Copyright 2007 by Honglak Lee, Alexis Battle, Rajat Raina, and Andrew Y. Ng 15 | 16 | L = size(X,1); 17 | N = size(X,2); 18 | M = size(S, 1); 19 | 20 | % tic 21 | SSt = S*S'; 22 | XSt = X*S'; 23 | 24 | if exist('Binit', 'var') 25 | dual_lambda = diag(Binit\XSt - SSt); 26 | else 27 | dual_lambda = 10*abs(rand(M,1)); % any arbitrary initialization should be ok. 28 | end 29 | 30 | c = l2norm^2; 31 | trXXt = sum(sum(X.^2)); 32 | 33 | lb=zeros(size(dual_lambda)); 34 | options = optimset('GradObj','on', 'Hessian','on','Display','off');%, 'HessFc',@(x) hessian(x, SSt, XSt)); 35 | % options = optimset('GradObj','on', 'Hessian','on', 'TolFun', 1e-7); 36 | [x, fval, exitflag, output] = fmincon(@(x) fobj_basis_dual(x, SSt, XSt, X, c, trXXt), dual_lambda, [], [], [], [], lb, [], [], options); 37 | % output.iterations 38 | fval_opt = -0.5*N*fval; 39 | dual_lambda= x; 40 | 41 | Bt = (SSt+diag(dual_lambda)) \ XSt'; 42 | B_dual= Bt'; 43 | fobjective_dual = fval_opt; 44 | 45 | 46 | B= B_dual; 47 | % fobjective = fobjective_dual; 48 | % toc 49 | 50 | return; 51 | 52 | 53 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 | 55 | function [f,g,H] = fobj_basis_dual(dual_lambda, SSt, XSt, X, c, trXXt) 56 | % Compute the objective function value at x 57 | L= size(XSt,1); 58 | M= length(dual_lambda); 59 | 60 | SSt_inv = inv(SSt + diag(dual_lambda)); 61 | 62 | % trXXt = sum(sum(X.^2)); 63 | if L>M 64 | % (M*M)*((M*L)*(L*M)) => MLM + MMM = O(M^2(M+L)) 65 | f = -trace(SSt_inv*(XSt'*XSt))+trXXt-c*sum(dual_lambda); 66 | 67 | else 68 | % (L*M)*(M*M)*(M*L) => LMM + LML = O(LM(M+L)) 69 | f = -trace(XSt*SSt_inv*XSt')+trXXt-c*sum(dual_lambda); 70 | end 71 | f= -f; 72 | 73 | if nargout > 1 % fun called with two output arguments 74 | % Gradient of the function evaluated at x 75 | g = zeros(M,1); 76 | temp = XSt*SSt_inv; 77 | g = sum(temp.^2) - c; 78 | g= -g; 79 | 80 | 81 | if nargout > 2 82 | % Hessian evaluated at x 83 | % H = -2.*((SSt_inv*XSt'*XSt*SSt_inv).*SSt_inv); 84 | H = -2.*((temp'*temp).*SSt_inv); 85 | H = -H; 86 | end 87 | end 88 | 89 | function [H] = hessian(dual_lambda, SSt, XSt) 90 | % Compute the hessian 91 | 92 | SSt_inv = inv(SSt + diag(dual_lambda)); 93 | 94 | temp = XSt*SSt_inv; 95 | 96 | % Hessian evaluated at x 97 | % H = -2.*((SSt_inv*XSt'*XSt*SSt_inv).*SSt_inv); 98 | H = -2.*((temp'*temp).*SSt_inv); 99 | H = -H; 100 | 101 | 102 | return -------------------------------------------------------------------------------- /code/plotting-code/dict_plot1d.m: -------------------------------------------------------------------------------- 1 | function dict_plot1d(varargin) 2 | 3 | % function dict_plot1d(varargin) 4 | % 5 | % Function to plot Dictionary elements for 'vector' types. Each column is 6 | % one dictionary element, and is plotted in its own subplot. The subplots 7 | % are placed in an array with dimensions given by plot_dims. The x-axis is 8 | % given by either a vector x_vect, or simply indexed to the size of the 9 | % dictionary elements. 10 | % 11 | % Inputs: 12 | % dictionary_n - dictionary to plot 13 | % plot_dims - 2-element vector with dimensions of the subplots 14 | % within the figure 15 | % x_vect - vector of x-axis positions 16 | % fig_no - optional figure number (to keep overwriting the same 17 | % figure 18 | % 19 | % Use: 20 | % dict_plot1d(dictionary_n, plot_dims) 21 | % Plot the columns of dictionary_n in a subplot array 22 | % with dimensions plot_dims(1)Xplot_dims(2). 23 | % dict_plot1d(dictionary_n, x_vect, plot_dims) 24 | % Plot the columns of dictionary_n in a subplot array 25 | % with dimensions plot_dims(1)Xplot_dims(2). The x-axis 26 | % domain is given by x_vect. 27 | % dict_plot1d(dictionary_n, x_vect, plot_dims, fig_no) 28 | % Plot the columns of dictionary_n in a subplot array 29 | % with dimensions plot_dims(1)Xplot_dims(2). The x-axis 30 | % domain is given by x_vect. The figure number to plot in 31 | % is given by fig_no. 32 | % 33 | % Last Modified 6/12/2010 - Adam Charles 34 | 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | %% Check Inputs 37 | if nargin == 2 38 | dictionary_n = varargin{1}; 39 | plot_dims = varargin{2}; 40 | x_vect = 1:size(dictionary_n, 1); 41 | elseif nargin == 3 42 | dictionary_n = varargin{1}; 43 | x_vect = varargin{2}; 44 | plot_dims = varargin{3}; 45 | elseif nargin == 4 46 | dictionary_n = varargin{1}; 47 | x_vect = varargin{2}; 48 | plot_dims = varargin{3}; 49 | fig_no = varargin{4}; 50 | end 51 | 52 | if prod(plot_dims) < size(dictionary_n, 2) 53 | warning('Input:DimensionMismatch', ['Warning, the plotting '... 54 | 'dimensions do not match the number of dictionary elements! '... 55 | 'Not all dictionary elements will be plotted!']) 56 | elseif prod(plot_dims) > size(dictionary_n, 2) 57 | warning('Input:DimensionMismatch', ['Warning, the plotting '... 58 | 'dimensions do not match the number of dictionary elements! '... 59 | 'There will be blank plots in the figure!']) 60 | end 61 | 62 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 63 | %% Plot Dictionary 64 | if nargin == 4 65 | figure(fig_no); 66 | else 67 | figure; 68 | end 69 | 70 | for index = 1:min(prod(plot_dims),size(dictionary_n, 2)) 71 | subplot(plot_dims(1), plot_dims(2), index), ... 72 | plot(x_vect, dictionary_n(:, index)) 73 | end 74 | 75 | end 76 | 77 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 78 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79 | -------------------------------------------------------------------------------- /code/simple-simulation/simSpatialData2.m: -------------------------------------------------------------------------------- 1 | function [data,profile_set,Ca] = simSpatialData2(sim_opts) 2 | 3 | if nargin < 1 || isempty(sim_opts) % Make sure that sim_opts is a struct 4 | clear sim_opts 5 | sim_opts = struct; 6 | end 7 | %% 8 | if (~isfield(sim_opts,'dims'))||isempty(sim_opts.dims) 9 | sim_opts.dims = [50,50,100]; 10 | end 11 | if (~isfield(sim_opts,'n_dict'))||isempty(sim_opts.n_dict) 12 | sim_opts.n_dict = 20; 13 | end 14 | if (~isfield(sim_opts,'p_evt'))||isempty(sim_opts.p_evt) 15 | sim_opts.p_evt = 0.8; 16 | end 17 | if (~isfield(sim_opts,'circ_rad'))||isempty(sim_opts.circ_rad) 18 | sim_opts.circ_rad = 5; 19 | end 20 | if (~isfield(sim_opts,'noise_var'))||isempty(sim_opts.noise_var) 21 | sim_opts.noise_var = 0.1; 22 | end 23 | if (~isfield(sim_opts,'gamma'))||isempty(sim_opts.gamma) 24 | sim_opts.gamma = 0.9; 25 | end 26 | if (~isfield(sim_opts,'r0'))||isempty(sim_opts.r0) 27 | sim_opts.r0 = 0.4; 28 | end 29 | 30 | %% Initialization 31 | 32 | nrows = sim_opts.dims(1); % Extract dimensions of the simulated dataset 33 | ncols = sim_opts.dims(2); % | 34 | T = sim_opts.dims(3); % | 35 | N = sim_opts.n_dict; % --- 36 | sig_r = sim_opts.circ_rad; 37 | r0 = sim_opts.r0 ; 38 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 39 | %% 40 | G = toeplitz(0:(T-1), zeros(1,T)); 41 | G_gam = tril(sim_opts.gamma.^G,0); 42 | %% 43 | margin = floor([nrows * 0.1, ncols * 0.1]); 44 | %% 45 | % [x0,y0] = meshgrid(margin(1):10:30,10:10:30); 46 | % x0 = x0(:); 47 | % y0 = y0(:); 48 | % x0 = x0 + 3*randn(N,1); 49 | % y0 = y0 + 3*randn(N,1); 50 | % 51 | x0 = margin(2) + randsample((ncols-2*margin(2)) ,N) + 3*randn(N,1); 52 | y0 = margin(1) + randsample((nrows-2*margin(1)) ,N) + 3*randn(N,1); 53 | % 54 | [x,y] = meshgrid(1:ncols,1:nrows); 55 | Atruth = zeros(nrows*ncols,N); 56 | profile_set = zeros(nrows,ncols,N); 57 | for i = 1:N 58 | xscale = max(1,1.2*rand(1)); 59 | yscale = 1/xscale; %max(1,1.3*rand(1)); 60 | data = exp(-(sqrt(((x-x0(i))/xscale).^2+max(-1,min(1,randn(1)))*(x-x0(i)).*(y-y0(i)) +((y-y0(i))/yscale).^2) - r0*(1+0.1*randn(1))).^2/(2*(1+0.1*randn(1))*sig_r^2)); 61 | %Atruth(:,i) = ceil((0.5*rand(1)+0.5)*10)/10*data(:).*(data(:) > 0.1); 62 | Atruth(:,i) = data(:).*(data(:) > 0.1); 63 | profile_set(:,:,i) = reshape(Atruth(:,i),nrows,ncols); 64 | end 65 | figure;imagesc(reshape(sum(Atruth,2),nrows,ncols));axis image 66 | %% 67 | p = 1-sim_opts.p_evt; 68 | t = rand(N,T) < p; 69 | Ca = G_gam*double(t'); 70 | %% 71 | data = zeros(size(Atruth,1),size(Ca,1)); 72 | for i =1:N 73 | data = data + Atruth(:,i)*Ca(:,i)'; 74 | end 75 | data = reshape(data,nrows, ncols,T); 76 | %% 77 | data = data + sim_opts.noise_var * randn(size(data)); 78 | data(data(:) < 0) = 0; 79 | %% 80 | if nargout < 1 81 | figure; 82 | subplot(131) 83 | imagesc(max(data,[],3));axis image;colorbar 84 | subplot(132) 85 | imagesc(mean(data,3));axis image;colorbar 86 | subplot(133) 87 | imagesc(std(data,0,3));axis image;colorbar 88 | %% 89 | figure;for i =1:T;imagesc(data(:,:,i),[0 max(Ca(:))]);pause(0.1);end 90 | end -------------------------------------------------------------------------------- /code/support-functions/bilin_fun.m: -------------------------------------------------------------------------------- 1 | function [fun,varargout] = bilin_fun(S, Y, A, h, D, opt) 2 | 3 | % function [fun,varargout] = bilin_fun(S, Y, A, h, D, opt) 4 | % 5 | % Function to calculate function value and gradiet for a bilinear 6 | % function. 7 | % 8 | % 2018 - Adam Charles 9 | 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | 12 | S = reshape(S(:),[size(Y,1), size(A,1)]); % Make sure that S is a matrix of the correct size 13 | H = hankel(flipud([h;zeros(size(S,1),1)])); 14 | H = flipud(H(ceil(size(h,1)/2) +(1:size(S,1)),1:size(S,1))); 15 | % 16 | % h = vec(h); % ensure that h is a vector 17 | % H = h; 18 | % D2 = applyH(S,h,1); % Calculate current dictionary 19 | D2 = H*S; % Calculate current dictionary 20 | Y2 = D2*A; % Compute the 21 | C = D2.'*D2; 22 | C(1:size(C,1)+1:end) = 0; 23 | 24 | % fun = opt.lambda2*sum(D2(:).^2) + opt.lambdaS*sum(S(:)); % Calculate function value 25 | %fun = sum(vec(Y - H*S*A).^2); 26 | fun = (norm((H*S)*A-Y,'fro').^2); 27 | 28 | 29 | % fun = sum(vec(Y - Y2).^2) + opt.lambdaS*sum(S(:)) + ... 30 | % opt.lambda2*sum(D2(:).^2) + opt.lambda3*sum(vec(D-D2).^2) + .... 31 | % opt.lambda4*sum(abs(C(:))); % Calculate function value 32 | fun = double(fun); 33 | 34 | if nargout > 1 35 | % calculate deriative 36 | % First term dS||Y-H*S*A||_F^2 = 2*H^T(H*S*A - Y)A^T 37 | % Second term dS||H*S||_F^2 = 2*H^T*H*S 38 | % Third term dS||D-H*S||_F^2 = 2*H^T*(H*S - D) 39 | % Fourth term dS||(H*S)^T*H*S||_{od-sav} = 2*H^T*H*S*W; W = 1-I 40 | W = ones(size(D2,2)); 41 | W(1:size(W,1)+1:end) = 0; 42 | 43 | % varargout{1} = opt.lambdaS*ones(size(S)) + opt.lambda2*2*applyH(D2,h,2); % Calculate the gradient 44 | varargout{1} = (2*(H')*((H*S)*A-Y))*(A'); % Calculate the gradient 45 | % varargout{1} = 2*applyH((Y2-Y)*(A'),h,2); % Calculate the gradient 46 | % varargout{1} = opt.lambdaS*ones(size(S)) + 2*applyH(((Y2-Y)*A' + ... 47 | % opt.lambda2*D2 + opt.lambda3*(D2-D) + opt.lambda4*D2*W),h,2); % Calculate the gradient 48 | varargout{1} = double(vec(varargout{1})); 49 | end 50 | 51 | if nargout > 2 % Too large to implement currently 52 | 53 | end 54 | 55 | end 56 | 57 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 | %% Auxiliary function to apply H and H^T 59 | 60 | function Y = applyH(X,h,T) 61 | 62 | % Function to apply the linear operator H and it's transpose H^T using 63 | % convolutional operators. H is defined as: 64 | % H = hankel(flipud([h;zeros(size(X,1),1)])); 65 | % H = flipud(H(ceil(size(h,1)/2) +(1:size(X,1)),1:size(X,1))); 66 | 67 | if T == 1 68 | Y = convn(X, h, 'same'); % y = flipud(H*x); 69 | elseif T == 2 70 | Y = convn(X, flipud([h;0]),'same'); % z1 = H.'*y1; 71 | else 72 | error('T invalid: options for T are T=1 for H(X) and T=2 for H^T(X)!') 73 | end 74 | 75 | end 76 | 77 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 78 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79 | -------------------------------------------------------------------------------- /code/support-functions/checkCorrKern.m: -------------------------------------------------------------------------------- 1 | function [corr_kern, varargout] = checkCorrKern(data_obj, corr_kern, varargin) 2 | 3 | % corr_kern = checkCorrKern(data_obj,corr_kern) 4 | % 5 | % Check the correlational kernel and make sure that everythign is correct. 6 | % 7 | % 2019 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Input Parsing 11 | 12 | if nargin > 2; pVerbose = varargin{1}; % If provided set the verbose level 13 | else; pVerbose = 0; % Otherwise don't set outputs 14 | end 15 | 16 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 17 | %% Check the correlation kernel and create the kernel or embedding 18 | 19 | embed_flag = false; % Unless otherwise noted, set the flag for using the graph embedding to false 20 | if isempty(corr_kern) % Check if a spatial kernel is NOT provided 21 | verbPrint(pVerbose, 2, 'Empty kernel, creating kernel with default params.') % Optional verbose output (level 2) 22 | corr_kern = mkCorrKern([]); % If an empty array, make the kernel using the default parameters 23 | elseif isstruct(corr_kern) 24 | verbPrint(pVerbose, 2, 'Struct provided, creating kernel with provided params.') % Optional verbose output (level 2) 25 | if ~isfield(corr_kern,'corrType') 26 | corr_kern.corrType = 'convolution'; % The default correlation type is a convolutional kernel 27 | end 28 | if isequal(corr_kern.corrType,'convolution') 29 | corr_kern = mkCorrKern(corr_kern); % If it is a struct then parameters were provided: make the kernel using those parameters 30 | elseif isequal(corr_kern.corrType,'embedding') 31 | corr_kern = mkDataEmbedding(data_obj, corr_kern); % Create an embedding 32 | embed_flag = true; % Set the flag for using the graph embedding to false 33 | else 34 | corr_kern = mkCorrKern(corr_kern); % If it is a struct then parameters were provided: make the kernel using those parameters 35 | end 36 | elseif ischar(corr_kern)&&isequal(corr_kern,'embed-timetrace') 37 | verbPrint(pVerbose, 2, 'Static timetrace-based embedding selected. Creating default embedding now.') % Optional verbose output (level 2)d 38 | corr_kern = mkDataEmbedding(data_obj, []); % Create an embedding 39 | embed_flag = true; % Set the flag for using the graph embedding to false 40 | elseif isnumeric(corr_kern) % Nothing to do 41 | else 42 | corr_kern = checkCorrKern(data_obj, [], pVerbose); % Otherwise rerun with an empty, default set 43 | end 44 | 45 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 46 | %% Output Parsing 47 | 48 | if nargout > 1 49 | varargout{1} = embed_flag; % If requested, output the embedding flag 50 | end 51 | 52 | end 53 | 54 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 55 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 56 | -------------------------------------------------------------------------------- /code/dictionary-learning/rwLCA.m: -------------------------------------------------------------------------------- 1 | function [a, varargout] = rwLCA(x, phi, thrtype, eta, gamma_val, maxIters, relTol, varargin) 2 | 3 | 4 | % test for number of required parametres 5 | if (nargin-length(varargin)) ~= 7 6 | error('Wrong number of required parameters'); 7 | end 8 | % set the defaults for the optional parameters 9 | compute_mse = 0; 10 | % read the optional parameters 11 | a_initialize = 0; 12 | if (rem(length(varargin), 2)==1) 13 | error('Optional parameters shoudl always go by pairs'); 14 | else 15 | for i=1:2:(length(varargin)-1) 16 | switch upper(varargin{i}) 17 | case 'TRUE_A' 18 | compute_mse = 1; 19 | % set the default outputs that may not be computed 20 | Evals = zeros(maxIters, 1); 21 | rMSEs = zeros(maxIters, 1); 22 | true_a = varargin{i+1}; 23 | case 'INIT_A' 24 | a_initialize = varargin{i+1}; 25 | end 26 | end 27 | end 28 | 29 | % compute feedforward activations 30 | b = phi'*x; 31 | % initialize lambda to the max value of b 32 | curlambda = max(0.02*abs(b))*ones(size(phi, 2), 1); 33 | lambda_mean = 0.02*abs(max(b)); 34 | 35 | lambda_thresh = max(abs(b)); 36 | % compute Gramm matrix 37 | G = phi'*phi; 38 | C = G - diag(diag(G)); 39 | % initialize a and u 40 | m = size(phi, 2); 41 | a = a_initialize.*ones(m, 1); 42 | u = a_initialize.*ones(m, 1); 43 | % initialize dual objective function 44 | dobj = -Inf; 45 | 46 | for it=1:maxIters 47 | 48 | if compute_mse 49 | rMSEs(it) = sum((a(:) - true_a(:)).^2 / sum(true_a(:).^2)); 50 | Evals(it) = sum((x - phi*a(:)).^2 + sum(curlambda.*abs(a(:)))); 51 | end 52 | 53 | % % compute duality gap 54 | % z = phi*(a) - x; 55 | % nu = 2*z; 56 | % maxPhinu = norm((phi'*nu)./curlambda, inf); 57 | % if (maxPhinu > 2) 58 | % nu = nu*2/maxPhinu; 59 | % end 60 | % pobj = z'*z + 2*norm(curlambda.*a, 1); 61 | % dobj = max(-0.25*(nu')*nu-nu'*x,dobj); 62 | % gap = pobj - dobj; 63 | % if (gap/dobj < relTol) 64 | % disp(['duality gap below threshold after iteration ' num2str(it)]); 65 | % rMSEs = rMSEs(1:it); 66 | % Evals = Evals(1:it); 67 | % return; 68 | % end 69 | % gap = 0; 70 | % dobj = 1; 71 | % 72 | % if (mod(it, 100) == 0) 73 | % disp(['rwLCA iteration ' num2str(it) ' :: dgap = ' num2str(gap/dobj)]) 74 | % end 75 | 76 | % update the internal state variables 77 | u = eta(1)*(b - C*a) + (1-eta(1))*u; 78 | % update the LCA thresholding parameters 79 | curlambda = curlambda + eta(2)*(1./curlambda - abs(a) - gamma_val); 80 | 81 | lambda_use = lambda_mean*curlambda; 82 | lambda_use(curlambda <= lambda_thresh) = lambda_thresh; 83 | 84 | lambda_thresh = lambda_thresh*0.9; 85 | 86 | if thrtype == 1 87 | % soft threshold 88 | a = (u - lambda_use.*sign(u)) .* (abs(u) > lambda_use); 89 | else 90 | % hard threshold 91 | a = u .* (abs(u) > lambda_use); 92 | end 93 | 94 | end 95 | 96 | %% Output parsing 97 | 98 | if nargout > 1 99 | if compute_mse 100 | varargout{1} = Evals; 101 | if nargout > 2 102 | varargout{2} = rMSEs; 103 | else 104 | end 105 | else 106 | for kk = 2:nargout 107 | varargout{kk-1} = []; 108 | end 109 | end 110 | else 111 | end 112 | 113 | end 114 | -------------------------------------------------------------------------------- /code/dictionary-learning/bilin_fun.m: -------------------------------------------------------------------------------- 1 | function [fun,varargout] = bilin_fun(S, Y, A, h, D, opt) 2 | 3 | % function [fun,varargout] = bilin_fun(S, Y, A, h, D, opt) 4 | % 5 | % Function to calculate function value and gradient 6 | % 7 | % 2018 - Adam Charles 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | 11 | S = reshape(S(:),[size(Y,1), size(A,1)]); % Make sure that S is a matrix of the correct size 12 | 13 | h = vec(h); % ensure that h is a vector 14 | 15 | 16 | % H = h; 17 | D2 = applyH(S,h,1); % Calculate current dictionary 18 | % D2 = H*S; % Calculate current dictionary 19 | Y2 = D2*A; 20 | C = D2.'*D2; 21 | C(1:size(C,1)+1:end) = 0; 22 | 23 | fun = sum(vec(Y-Y2).^2) + opt.lambdaS*sum(S(:)) + opt.lambda2*sum(D2(:).^2) ... 24 | + opt.lambda3*sum(vec(D-D2).^2) + opt.lambda4*sum(abs(C(:))); 25 | fun = double(fun); 26 | 27 | if nargout > 1 28 | % calculate deriative 29 | % First term dS||Y-H*S*A||_F^2 = 2*H^T(H*S*A - Y)A^T 30 | % Second term dS||H*S||_F^2 = 2*H^T*H*S 31 | % Third term dS||D-H*S||_F^2 = 2*H^T*(H*S - D) 32 | % Fourth term dS||(H*S)^T*H*S||_{od-sav} = 2*H^T*H*S*W; W = 1-I 33 | W = ones(size(D2,2)); 34 | W(1:size(W,1)+1:end) = 0; 35 | 36 | varargout{1} = opt.lambdaS*ones(size(S)) + 2*applyH((Y2-Y)*(A') +... 37 | opt.lambda2*D2 + opt.lambda3*D2-D + opt.lambda4*D2*W,h,2); % Calculate the gradient 38 | 39 | % varargout{1} = opt.lambdaS*ones(size(S)) + 2*applyH(((Y2-Y)*A' + ... 40 | % opt.lambda2*D2 + opt.lambda3*(D2-D) + opt.lambda4*D2*W),h,2); % Calculate the gradient 41 | varargout{1} = double(reshape(varargout{1},[],1)); 42 | end 43 | 44 | % if nargout > 2 % Too large to implement currently 45 | % % calculate Hessians 46 | % % First term dS 2*vec((H^T*H)*S*(A*A^T)) = 2*kron((A*A^T),(H^T*H)) 47 | % % Second term dS 2*H^T*H*S = 2*kron(I,(H^T*H)) 48 | % % Third term dS 2*(H^T*H)*S = 2*kron(I,(H^T*H)) 49 | % % Fourth term dS 2*H^T*H*S*W = 2*kron(W,(H^T*H)); W = 1-I 50 | % 51 | % H = hankel(flipud([h;zeros(size(S,1),1)])); 52 | % H = flipud(H(ceil(size(h,1)/2) +(1:size(S,1)),1:size(S,1))); 53 | % varargout{2} = 2*kron(A*A' + 2*eye(size(A,1)) + W, H'*H); 54 | % varargout{2} = double(varargout{2}); 55 | % end 56 | 57 | end 58 | 59 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 60 | %% Auxiliary function to apply H and H^T 61 | 62 | function Y = applyH(X,h,T) 63 | 64 | % Function to apply the linear operator H and it's transpose H^T using 65 | % convolutional operators. H is defined as: 66 | % H = hankel(flipud([h;zeros(size(X,1),1)])); 67 | % H = flipud(H(ceil(size(h,1)/2) +(1:size(X,1)),1:size(X,1))); 68 | 69 | if T == 1 70 | Y = convn(X, h, 'same'); % y = flipud(H*x); 71 | elseif T == 2 72 | Y = convn(X, flipud([h;0]),'same'); % z1 = H.'*y1; 73 | else 74 | error('T invalid: options for T are T=1 for H(X) and T=2 for H^T(X)!') 75 | end 76 | 77 | end 78 | 79 | 80 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 81 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 82 | -------------------------------------------------------------------------------- /code/dictionary-learning/dictionary_learn_script_1d.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | %% dictionary_learn_script.m 4 | % This scrips it an example script for basic sparse dictionary learning 5 | % based on the Olshausen and Field, 1997 paper 'Sparse Coding with 6 | % an Overcomplete Basis Set: a Strategy Employed by V1?' 7 | % 8 | % Deviations from the model presented are: 9 | % - use of L1 regularized BPDN solvers as well as options to use 10 | % hard-sparse MP-type solvers for the inference step. This allows 11 | % faster and more accurate solvutions for the sparse coefficients. 12 | % - Normalization of the dictionary elements to have unit norm at each 13 | % step rather than normalizing the variance of the coefficients. This 14 | % is the default. Also included is a method that normalizes the 15 | % dictionary elements by a Forbeneous norm. 16 | % 17 | % Other optimizations: 18 | % 19 | % - Parallel for loops are used in the inference step to speed up 20 | % run-time. If the script is to be run on a cluster, ust the 21 | % createMatlabPoolJob() function to allow for this speedup. 22 | % 23 | % 24 | % Last Updated 6/3/2010 - Adam Charles 25 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 26 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 27 | %% Set Options 28 | 29 | % Set multithreading to Ncores - 1 threads 30 | % This speeds up matrix multiplication etc. 31 | poolobj = gcp('nocreate'); 32 | if ~isempty(poolobj) 33 | delete(gcp); 34 | end 35 | parpool(); 36 | 37 | % Random number seed 38 | RandStream.setGlobalStream (RandStream('mt19937ar','seed',sum(100*clock))); 39 | 40 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 41 | %% Options 42 | 43 | % Algorithm options 44 | opts.data_type = 'vector'; % Type of data (vector, square or cube) 45 | opts.grad_type = 'norm'; % Choose weather to include the Forb norm in E(a,D) 46 | opts.n_elem = 144; % Number of dictionary elements 47 | opts.iters = 400; % Number of learning iterations 48 | opts.in_iter = 75; % Number of internal iterations 49 | % Specify Parameters 50 | opts.step_size = 2; % Initial Step Size for Gradient Descent 51 | opts.decay = 0.9995; % Step size decay factor 52 | opts.lambda = 0.6; % Lambda Value for Sparsity 53 | opts.tol = 0.001; % Sparsification Tolerance 54 | % Plotting Options 55 | opts.bshow = 0; % Number of iterations to show basis 56 | opts.disp_size = [8, 8]; % Basis display dimensions 57 | 58 | opts.div_samp = 1; 59 | 60 | %% Create Training Data 61 | 62 | S = 5; 63 | N = 144; 64 | P = 1e4; 65 | data_obj = zeros(N,P); 66 | for kk = 1:P 67 | tmp = zeros(N,1); 68 | tmp(randsample(N, S)) = 5*(rand(S,1)-0.5); 69 | data_obj(:,kk) = dct(tmp); 70 | end 71 | 72 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 73 | %% Run Learning Algorithm 74 | 75 | % Actually run the learning algorithm 76 | tic 77 | [dictionary_out] = learn_dictionary(data_obj, [], @cg_l2l1_wrapper, opts); 78 | toc 79 | 80 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 81 | %% Closing time 82 | 83 | delete(gcp); 84 | 85 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 86 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 87 | -------------------------------------------------------------------------------- /code/dictionary-learning/group_rwLCA.m: -------------------------------------------------------------------------------- 1 | function [a, varargout] = rwLCA(x, phi, thrtype, eta, gamma_val, maxIters, group_cell, varargin) 2 | 3 | 4 | % test for number of required parametres 5 | if (nargin-length(varargin)) ~= 7 6 | error('Wrong number of required parameters'); 7 | end 8 | % set the defaults for the optional parameters 9 | compute_mse = 0; 10 | % read the optional parameters 11 | a_initialize = 0; 12 | if (rem(length(varargin), 2)==1) 13 | error('Optional parameters shoudl always go by pairs'); 14 | else 15 | for i=1:2:(length(varargin)-1) 16 | switch upper(varargin{i}) 17 | case 'TRUE_A' 18 | compute_mse = 1; 19 | % set the default outputs that may not be computed 20 | Evals = zeros(maxIters, 1); 21 | rMSEs = zeros(maxIters, 1); 22 | true_a = varargin{i+1}; 23 | case 'INIT_A' 24 | a_initialize = varargin{i+1}; 25 | end 26 | end 27 | end 28 | 29 | % compute feedforward activations 30 | b = phi'*x; 31 | % initialize lambda to the max value of b 32 | curlambda = max(0.02*abs(b))*ones(numel(group_cell), 1); 33 | curlambda2 = max(0.02*abs(b))*ones(size(phi, 2), 1); 34 | lambda_mean = 0.02*abs(max(b)); 35 | 36 | lambda_thresh = max(abs(b)); 37 | % compute Gramm matrix 38 | G = phi'*phi; 39 | C = G - diag(diag(G)); 40 | % initialize a and u 41 | m = size(phi, 2); 42 | a = a_initialize.*ones(m, 1); 43 | u = a_initialize.*ones(m, 1); 44 | % initialize dual objective function 45 | dobj = -Inf; 46 | 47 | for it=1:maxIters 48 | 49 | if compute_mse 50 | rMSEs(it) = sum((a(:) - true_a(:)).^2 / sum(true_a(:).^2)); 51 | Evals(it) = sum((x - phi*a(:)).^2 + sum(curlambda.*abs(a(:)))); 52 | end 53 | 54 | % % compute duality gap 55 | % z = phi*(a) - x; 56 | % nu = 2*z; 57 | % maxPhinu = norm((phi'*nu)./curlambda, inf); 58 | % if (maxPhinu > 2) 59 | % nu = nu*2/maxPhinu; 60 | % end 61 | % pobj = z'*z + 2*norm(curlambda.*a, 1); 62 | % dobj = max(-0.25*(nu')*nu-nu'*x,dobj); 63 | % gap = pobj - dobj; 64 | % if (gap/dobj < relTol) 65 | % disp(['duality gap below threshold after iteration ' num2str(it)]); 66 | % rMSEs = rMSEs(1:it); 67 | % Evals = Evals(1:it); 68 | % return; 69 | % end 70 | % gap = 0; 71 | % dobj = 1; 72 | % 73 | % if (mod(it, 100) == 0) 74 | % disp(['rwLCA iteration ' num2str(it) ' :: dgap = ' num2str(gap/dobj)]) 75 | % end 76 | 77 | % update the internal state variables 78 | u = eta(1)*(b - C*a) + (1-eta(1))*u; 79 | % update the LCA thresholding parameters 80 | for kk = 1:numel(group_cell) 81 | curlambda(kk) = curlambda(kk) + eta(2)*(1./curlambda(kk) - sqrt(sum(a(group_cell{kk}).^2)) - gamma_val); 82 | curlambda2(group_cell{kk}) = curlambda(kk); 83 | end 84 | lambda_use = lambda_mean*curlambda2; 85 | lambda_use(curlambda <= lambda_thresh) = lambda_thresh; 86 | 87 | lambda_thresh = lambda_thresh*0.9; 88 | 89 | if thrtype == 1 90 | % soft threshold 91 | a = (u - lambda_use.*sign(u)) .* (abs(u) > lambda_use); 92 | else 93 | % hard threshold 94 | a = u .* (abs(u) > lambda_use); 95 | end 96 | 97 | end 98 | 99 | %% Output parsing 100 | 101 | if nargout > 1 102 | if compute_mse 103 | varargout{1} = Evals; 104 | if nargout > 2 105 | varargout{2} = rMSEs; 106 | else 107 | end 108 | else 109 | for kk = 2:nargout 110 | varargout{kk-1} = []; 111 | end 112 | end 113 | else 114 | end 115 | 116 | end 117 | -------------------------------------------------------------------------------- /code/support-functions/denoiseCIinTime.m: -------------------------------------------------------------------------------- 1 | function mov = denoiseCIinTime(mov, varargin) 2 | 3 | % denoiseTracesWavelet(fuObj, varargin) 4 | % 5 | % Function to denoise calcium imaging data in time using wavelet 6 | % denoising. To avoid the missing data problem, error frames from burst 7 | % errors are filled in using cubic spline interpolation. 8 | % 9 | % 2020 - Adam Charles 10 | 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | %% Input parsing 13 | 14 | p = inputParser; % Set up an object to parse all of the various inputs 15 | p.addParameter('smoothLvl' , 4 ); % Select at what wavelet level to smooth at 16 | p.addParameter('DenoisingMethod' , 'BlockJS' ); % For the situation that 'prctile' is chosen, which percentile should the baseline image be calculated using 17 | p.addParameter('wDenoiseFun' , 'wdenoise'); % Select which pixels to select: either an array or 'vary' or 'rand' 18 | p.addParameter('Wavelet' , 'sym4' ); % Select hoe many traces to select 19 | 20 | parse(p,varargin{:}); 21 | p = p.Results; 22 | 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | %% Some initializations 25 | 26 | movSize = [size(mov,1), size(mov,2), size(mov,3)]; % Get size of movie 27 | matSize = [movSize(1)*movSize(2),movSize(3)]; % Get size of reshaped matrix (pix X frames) 28 | 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | %% Function to denoise time traces 31 | 32 | fprintf('Smoothing...') 33 | if p.smoothLvl == 0 % No smoothing, nothing to do 34 | elseif p.smoothLvl > 0 35 | switch lower(p.wDenoiseFun) 36 | case 'wdenoise' % Choise to use 'wdenoise' for denoising 37 | fprintf('starting denoising\n') 38 | mov = wdenoise(... 39 | double(reshape(mov,matSize)'),... 40 | p.smoothLvl,'DenoisingMethod',... 41 | p.DenoisingMethod,'Wavelet',p.Wavelet);% Run the wavelet denoising 42 | fprintf('reshaping\n') 43 | mov = single(reshape(mov', movSize)); % Reshape to a movie 44 | case 'wdenoiseram' % Choise to use 'wdenoise' for denoising 45 | fprintf('starting denoising\n') 46 | mov = reshape(mov,matSize)'; 47 | parfor ll = 1:(movSize(1)*movSize(2)) 48 | mov(:,ll) = wdenoise(double(mov(:,ll)), p.smoothLvl,'DenoisingMethod',... 49 | p.DenoisingMethod,'Wavelet',p.Wavelet);% Run the wavelet denoising 50 | end 51 | fprintf('reshaping\n') 52 | mov = single(reshape(mov', movSize)); % Reshape to a movie 53 | case 'cmddenoise' % Choise to use 'wdenoise' for denoising 54 | for ll = 1:(movSize(1)*movSize(2)) 55 | [i1,i2] = ind2sub([movSize(1),movSize(2)],ll); % Pull out one pixel at a time 56 | mov(i1,i2,:) = cmddenoise(mov(i1,i2,:), ... 57 | p.Wavelet, smoothLvl); % Denoise that time trace (future work should parallelize this with parfor) 58 | end 59 | otherwise 60 | warning('No valid denoising function chosen! Skipping denoising step.\n') 61 | end 62 | else 63 | warning('Bad value for smoothLvl: defaulting to NOT smoothing time traces') 64 | end 65 | fprintf('done.\n') 66 | 67 | end 68 | 69 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 70 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 71 | -------------------------------------------------------------------------------- /code/external-code/from_caiman/graph_conn_comp_mex.cpp: -------------------------------------------------------------------------------- 1 | #include "mex.h" 2 | #include // for memset 3 | /* 4 | * Computing connected components of an undirected graph - assuming sA is symmetric 5 | * 6 | * Usage: 7 | * [l c] = graph_conn_comp_mex(sA); 8 | * 9 | * Inputs: 10 | * sA - sparse adjacency matrix (for directed graph - does not have to be symmetric) 11 | * 12 | * Outputs: 13 | * l - components labels 14 | * c - number of connected components 15 | * 16 | * 17 | * Compile using: 18 | * >> mex -O -largeArrayDims graph_conn_comp_mex.cpp 19 | * 20 | */ 21 | #line __LINE__ "graph_conn_comp_mex" 22 | #define STR(s) #s 23 | #define ERR_CODE(a,b) a ":" "line_" STR(b) 24 | // inputs 25 | enum { 26 | AIN = 0, 27 | NIN }; 28 | // outputs 29 | enum { 30 | LOUT = 0, 31 | COUT, 32 | NOUT }; 33 | void 34 | ConnComp(const mxArray* sA, unsigned int* pl, const double* pnc, mwIndex start_node); 35 | mwIndex 36 | FindUnLabeled(unsigned int* pl, mwIndex n); 37 | 38 | void mexFunction( 39 | int nout, 40 | mxArray* pout[], 41 | int nin, 42 | const mxArray* pin[]) { 43 | if ( nin != NIN ) 44 | mexErrMsgIdAndTxt(ERR_CODE(__FILE__, __LINE__),"must have %d inputs", NIN); 45 | if (nout==0) 46 | return; 47 | if (nout != NOUT ) 48 | mexErrMsgIdAndTxt(ERR_CODE(__FILE__, __LINE__),"must have exactly %d output", NOUT); 49 | 50 | if ( mxIsComplex(pin[AIN]) || !mxIsSparse(pin[AIN]) ) 51 | mexErrMsgIdAndTxt(ERR_CODE(__FILE__, __LINE__),"sA must be real sparse matrix"); 52 | if ( mxGetM(pin[AIN]) != mxGetN(pin[AIN]) ) 53 | mexErrMsgIdAndTxt(ERR_CODE(__FILE__, __LINE__),"sA must be square matrix"); 54 | 55 | mwIndex n = mxGetM(pin[AIN]); // number of variables 56 | mwIndex ii(0); 57 | // allocate outputs 58 | pout[LOUT] = mxCreateNumericMatrix(1, n, mxUINT32_CLASS, mxREAL); 59 | unsigned int* pl = (unsigned int*)mxGetData(pout[LOUT]); 60 | memset(pl, 0, n*sizeof(unsigned int)); // set initial labels to zero 61 | unsigned int cl = 0; 62 | // number of components 63 | pout[COUT] = mxCreateDoubleMatrix(1, 1, mxREAL); 64 | double* pnc = mxGetPr(pout[COUT]); 65 | pnc[0] = 0; // number of components 66 | ii = 0; 67 | do { 68 | ConnComp(pin[AIN], pl, pnc, ii); // find conn comp 69 | pnc[0]++; 70 | ii = FindUnLabeled(pl, n); 71 | } while ( ii < n ); 72 | } 73 | 74 | mwIndex 75 | FindUnLabeled(unsigned int* pl, mwIndex n) { 76 | for ( mwIndex ii(0); ii 0 ) { 99 | // pop start_label from stack 100 | sp--; 101 | start_node = stack[sp]; 102 | for ( ii = pjc[start_node] ; ii < pjc[start_node+1] ; ii++ ) { 103 | neighbor = pir[ii]; 104 | if (pl[neighbor]==0) { // unlabeled 105 | pl[neighbor] = curr_label; // label it 106 | // push it into stack 107 | stack[sp] = neighbor; 108 | sp++; 109 | } else { 110 | if (pl[neighbor]!=curr_label) 111 | mexErrMsgIdAndTxt(ERR_CODE(__FILE__, __LINE__),"Got mixed labeling %d <-> %d",pl[neighbor], curr_label); 112 | } 113 | } 114 | } 115 | mxFree(stack); 116 | } -------------------------------------------------------------------------------- /code/graph-sparse-coding/mySVD.m: -------------------------------------------------------------------------------- 1 | function [U, S, V] = mySVD(X,ReducedDim) 2 | %mySVD Accelerated singular value decomposition. 3 | % [U,S,V] = mySVD(X) produces a diagonal matrix S, of the 4 | % dimension as the rank of X and with nonnegative diagonal elements in 5 | % decreasing order, and unitary matrices U and V so that 6 | % X = U*S*V'. 7 | % 8 | % [U,S,V] = mySVD(X,ReducedDim) produces a diagonal matrix S, of the 9 | % dimension as ReducedDim and with nonnegative diagonal elements in 10 | % decreasing order, and unitary matrices U and V so that 11 | % Xhat = U*S*V' is the best approximation (with respect to F norm) of X 12 | % among all the matrices with rank no larger than ReducedDim. 13 | % 14 | % Based on the size of X, mySVD computes the eigvectors of X*X^T or X^T*X 15 | % first, and then convert them to the eigenvectors of the other. 16 | % 17 | % See also SVD. 18 | % 19 | % version 2.0 --Feb/2009 20 | % version 1.0 --April/2004 21 | % 22 | % Written by Deng Cai (dengcai AT gmail.com) 23 | % 24 | 25 | MAX_MATRIX_SIZE = 1600; % You can change this number according your machine computational power 26 | EIGVECTOR_RATIO = 0.1; % You can change this number according your machine computational power 27 | 28 | 29 | if ~exist('ReducedDim','var') 30 | ReducedDim = 0; 31 | end 32 | 33 | [nSmp, mFea] = size(X); 34 | if mFea/nSmp > 1.0713 35 | ddata = X*X'; 36 | ddata = max(ddata,ddata'); 37 | 38 | dimMatrix = size(ddata,1); 39 | if (ReducedDim > 0) && (dimMatrix > MAX_MATRIX_SIZE) && (ReducedDim < dimMatrix*EIGVECTOR_RATIO) 40 | option = struct('disp',0); 41 | [U, eigvalue] = eigs(ddata,ReducedDim,'la',option); 42 | eigvalue = diag(eigvalue); 43 | else 44 | if issparse(ddata) 45 | ddata = full(ddata); 46 | end 47 | 48 | [U, eigvalue] = eig(ddata); 49 | eigvalue = diag(eigvalue); 50 | [dump, index] = sort(-eigvalue); 51 | eigvalue = eigvalue(index); 52 | U = U(:, index); 53 | end 54 | clear ddata; 55 | 56 | maxEigValue = max(abs(eigvalue)); 57 | eigIdx = find(abs(eigvalue)/maxEigValue < 1e-10); 58 | eigvalue(eigIdx) = []; 59 | U(:,eigIdx) = []; 60 | 61 | if (ReducedDim > 0) && (ReducedDim < length(eigvalue)) 62 | eigvalue = eigvalue(1:ReducedDim); 63 | U = U(:,1:ReducedDim); 64 | end 65 | 66 | eigvalue_Half = eigvalue.^.5; 67 | S = spdiags(eigvalue_Half,0,length(eigvalue_Half),length(eigvalue_Half)); 68 | 69 | if nargout >= 3 70 | eigvalue_MinusHalf = eigvalue_Half.^-1; 71 | V = X'*(U.*repmat(eigvalue_MinusHalf',size(U,1),1)); 72 | end 73 | else 74 | ddata = X'*X; 75 | ddata = max(ddata,ddata'); 76 | 77 | dimMatrix = size(ddata,1); 78 | if (ReducedDim > 0) && (dimMatrix > MAX_MATRIX_SIZE) && (ReducedDim < dimMatrix*EIGVECTOR_RATIO) 79 | option = struct('disp',0); 80 | [V, eigvalue] = eigs(ddata,ReducedDim,'la',option); 81 | eigvalue = diag(eigvalue); 82 | else 83 | if issparse(ddata) 84 | ddata = full(ddata); 85 | end 86 | 87 | [V, eigvalue] = eig(ddata); 88 | eigvalue = diag(eigvalue); 89 | 90 | [dump, index] = sort(-eigvalue); 91 | eigvalue = eigvalue(index); 92 | V = V(:, index); 93 | end 94 | clear ddata; 95 | 96 | maxEigValue = max(abs(eigvalue)); 97 | eigIdx = find(abs(eigvalue)/maxEigValue < 1e-10); 98 | eigvalue(eigIdx) = []; 99 | V(:,eigIdx) = []; 100 | 101 | if (ReducedDim > 0) && (ReducedDim < length(eigvalue)) 102 | eigvalue = eigvalue(1:ReducedDim); 103 | V = V(:,1:ReducedDim); 104 | end 105 | 106 | eigvalue_Half = eigvalue.^.5; 107 | S = spdiags(eigvalue_Half,0,length(eigvalue_Half),length(eigvalue_Half)); 108 | 109 | eigvalue_MinusHalf = eigvalue_Half.^-1; 110 | U = X*(V.*repmat(eigvalue_MinusHalf',size(V,1),1)); 111 | end 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /code/external-code/RANN/myprin.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Yoel suggested to add prototypes */ 4 | void prin22_(double* a, int* n, FILE* out_file); 5 | void print_inner(int ion, char *str, double *a, int *ia, long int *la, int *n, int itype); 6 | 7 | 8 | /* 9 | 10 | PRINTING FUNCTIONS TO BE CALLED FROM FORTRAN 11 | 12 | */ 13 | 14 | void prin22_(double* a, int* n, FILE* out_file) { 15 | 16 | /* printf("a = \n"); */ 17 | int i, ix; 18 | 19 | i = 0; 20 | ix = 0; 21 | for (i = 0; i<*n; i++) { 22 | printf(" %11.4le", *(a+i)); 23 | fprintf(out_file, " %11.4le", *(a+i)); 24 | ix = ix + 1; 25 | if (ix == 6) { 26 | ix = 0; 27 | printf("\n"); 28 | fprintf(out_file, "\n"); 29 | } 30 | } 31 | if (ix > 0) { 32 | printf("\n"); 33 | fprintf(out_file, "\n"); 34 | } 35 | 36 | } 37 | 38 | 39 | void cprina_(char *str, FILE *out_file) { 40 | 41 | int i; 42 | for (i = 0; i < 100; i++) { 43 | if (str[i] == '*') goto jump1; 44 | printf("%c", str[i]); 45 | fprintf(out_file, "%c", str[i]); 46 | } 47 | jump1: 48 | 49 | printf("\n"); 50 | fprintf(out_file, "\n"); 51 | 52 | } 53 | 54 | 55 | void cprin2_(char *str, double *a, int* n, FILE *out_file) { 56 | cprina_(str, out_file); 57 | prin22_(a, n, out_file); 58 | } 59 | 60 | void cprinf_(char *str, int *a, int *n, FILE *out_file) { 61 | int i, ix; 62 | 63 | cprina_(str, out_file); 64 | 65 | 66 | i = 0; 67 | ix = 0; 68 | for (i = 0; i<*n; i++) { 69 | printf(" %7d", *(a+i)); 70 | fprintf(out_file, " %7d", *(a+i)); 71 | ix = ix + 1; 72 | if (ix == 10) { 73 | ix = 0; 74 | printf("\n"); 75 | fprintf(out_file, "\n"); 76 | } 77 | } 78 | if (ix > 0) { 79 | printf("\n"); 80 | fprintf(out_file, "\n"); 81 | } 82 | 83 | 84 | } 85 | 86 | void cprinl_(char *str, long int *a, int *n, FILE *out_file) { 87 | int i, ix; 88 | 89 | cprina_(str, out_file); 90 | 91 | 92 | i = 0; 93 | ix = 0; 94 | for (i = 0; i<*n; i++) { 95 | printf(" %7ld", *(a+i)); 96 | fprintf(out_file, " %7ld", *(a+i)); 97 | ix = ix + 1; 98 | if (ix == 10) { 99 | ix = 0; 100 | printf("\n"); 101 | fprintf(out_file, "\n"); 102 | } 103 | } 104 | if (ix > 0) { 105 | printf("\n"); 106 | fprintf(out_file, "\n"); 107 | } 108 | 109 | 110 | } 111 | 112 | /* 113 | 114 | SECOND GENERATION PRINTING FUNCTIONS 115 | 116 | */ 117 | 118 | 119 | void print_on_off__(int *ion) { 120 | char *str; 121 | double *a; 122 | int *ia; 123 | int *n; 124 | long int *la; 125 | print_inner(*ion, str, a, ia, la, n, 1); 126 | } 127 | 128 | void prina_(char* str) { 129 | double *a; 130 | int *ia; 131 | int *n; 132 | long int *la; 133 | print_inner(0, str, a, ia, la, n, 2); 134 | } 135 | 136 | void prin2_(char* str, double* a, int *n) { 137 | int *ia; 138 | long int *la; 139 | print_inner(0, str, a, ia, la, n, 3); 140 | } 141 | 142 | void prinf_(char* str, int* ia, int *n) { 143 | double *a; 144 | long int *la; 145 | print_inner(0, str, a, ia, la, n, 4); 146 | } 147 | 148 | void prinl_(char* str, long int* la, int *n) { 149 | double *a; 150 | int *ia; 151 | print_inner(0, str, a, ia, la, n, 5); 152 | } 153 | 154 | void print_inner(int ion, char *str, double *a, int *ia, long int *la, int *n, int itype) { 155 | 156 | static int iprint_on; 157 | static FILE *output_file; 158 | 159 | /* PRINT ON / OFF */ 160 | if (itype == 1) { 161 | iprint_on = ion; 162 | if (iprint_on == 0) fclose(output_file); 163 | if (iprint_on == 1) output_file = fopen("myprin.13", "w"); 164 | return; 165 | } 166 | 167 | if (iprint_on == 0) return; 168 | 169 | /* PRINT STRING */ 170 | if (itype == 2) { 171 | cprina_(str, output_file); 172 | } 173 | 174 | /* PRINT DOUBLE */ 175 | if (itype == 3) { 176 | cprin2_(str, a, n, output_file); 177 | } 178 | 179 | /* PRINT INT */ 180 | if (itype == 4) { 181 | cprinf_(str, ia, n, output_file); 182 | } 183 | 184 | if (itype == 5) { 185 | cprinl_(str, la, n, output_file); 186 | } 187 | 188 | 189 | } 190 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Demo data file 2 | neurofinder* 3 | 4 | ## Core latex/pdflatex auxiliary files: 5 | *.aux 6 | *.lof 7 | *.log 8 | *.lot 9 | *.fls 10 | *.out 11 | *.toc 12 | *.fmt 13 | *.fot 14 | *.cb 15 | *.cb2 16 | .*.lb 17 | 18 | ## Intermediate documents: 19 | *.dvi 20 | *.xdv 21 | *-converted-to.* 22 | # these rules might exclude image files for figures etc. 23 | # *.ps 24 | # *.eps 25 | # *.pdf 26 | 27 | ## Generated if empty string is given at "Please type another file name for output:" 28 | .pdf 29 | 30 | ## Bibliography auxiliary files (bibtex/biblatex/biber): 31 | *.bbl 32 | *.bcf 33 | *.blg 34 | *-blx.aux 35 | *-blx.bib 36 | *.run.xml 37 | 38 | ## Build tool auxiliary files: 39 | *.fdb_latexmk 40 | *.synctex 41 | *.synctex(busy) 42 | *.synctex.gz 43 | *.synctex.gz(busy) 44 | *.pdfsync 45 | 46 | ## Build tool directories for auxiliary files 47 | # latexrun 48 | latex.out/ 49 | 50 | ## Auxiliary and intermediate files from other packages: 51 | # algorithms 52 | *.alg 53 | *.loa 54 | 55 | # achemso 56 | acs-*.bib 57 | 58 | # amsthm 59 | *.thm 60 | 61 | # beamer 62 | *.nav 63 | *.pre 64 | *.snm 65 | *.vrb 66 | 67 | # changes 68 | *.soc 69 | 70 | # comment 71 | *.cut 72 | 73 | # cprotect 74 | *.cpt 75 | 76 | # elsarticle (documentclass of Elsevier journals) 77 | *.spl 78 | 79 | # endnotes 80 | *.ent 81 | 82 | # fixme 83 | *.lox 84 | 85 | # feynmf/feynmp 86 | *.mf 87 | *.mp 88 | *.t[1-9] 89 | *.t[1-9][0-9] 90 | *.tfm 91 | 92 | #(r)(e)ledmac/(r)(e)ledpar 93 | *.end 94 | *.?end 95 | *.[1-9] 96 | *.[1-9][0-9] 97 | *.[1-9][0-9][0-9] 98 | *.[1-9]R 99 | *.[1-9][0-9]R 100 | *.[1-9][0-9][0-9]R 101 | *.eledsec[1-9] 102 | *.eledsec[1-9]R 103 | *.eledsec[1-9][0-9] 104 | *.eledsec[1-9][0-9]R 105 | *.eledsec[1-9][0-9][0-9] 106 | *.eledsec[1-9][0-9][0-9]R 107 | 108 | # glossaries 109 | *.acn 110 | *.acr 111 | *.glg 112 | *.glo 113 | *.gls 114 | *.glsdefs 115 | *.lzo 116 | *.lzs 117 | 118 | # uncomment this for glossaries-extra (will ignore makeindex's style files!) 119 | # *.ist 120 | 121 | # gnuplottex 122 | *-gnuplottex-* 123 | 124 | # gregoriotex 125 | *.gaux 126 | *.gtex 127 | 128 | # htlatex 129 | *.4ct 130 | *.4tc 131 | *.idv 132 | *.lg 133 | *.trc 134 | *.xref 135 | 136 | # hyperref 137 | *.brf 138 | 139 | # knitr 140 | *-concordance.tex 141 | # TODO Comment the next line if you want to keep your tikz graphics files 142 | *.tikz 143 | *-tikzDictionary 144 | 145 | # listings 146 | *.lol 147 | 148 | # luatexja-ruby 149 | *.ltjruby 150 | 151 | # makeidx 152 | *.idx 153 | *.ilg 154 | *.ind 155 | 156 | # minitoc 157 | *.maf 158 | *.mlf 159 | *.mlt 160 | *.mtc[0-9]* 161 | *.slf[0-9]* 162 | *.slt[0-9]* 163 | *.stc[0-9]* 164 | 165 | # minted 166 | _minted* 167 | *.pyg 168 | 169 | # morewrites 170 | *.mw 171 | 172 | # nomencl 173 | *.nlg 174 | *.nlo 175 | *.nls 176 | 177 | # pax 178 | *.pax 179 | 180 | # pdfpcnotes 181 | *.pdfpc 182 | 183 | # sagetex 184 | *.sagetex.sage 185 | *.sagetex.py 186 | *.sagetex.scmd 187 | 188 | # scrwfile 189 | *.wrt 190 | 191 | # sympy 192 | *.sout 193 | *.sympy 194 | sympy-plots-for-*.tex/ 195 | 196 | # pdfcomment 197 | *.upa 198 | *.upb 199 | 200 | # pythontex 201 | *.pytxcode 202 | pythontex-files-*/ 203 | 204 | # tcolorbox 205 | *.listing 206 | 207 | # thmtools 208 | *.loe 209 | 210 | # TikZ & PGF 211 | *.dpth 212 | *.md5 213 | *.auxlock 214 | 215 | # todonotes 216 | *.tdo 217 | 218 | # vhistory 219 | *.hst 220 | *.ver 221 | 222 | # easy-todo 223 | *.lod 224 | 225 | # xcolor 226 | *.xcp 227 | 228 | # xmpincl 229 | *.xmpi 230 | 231 | # xindy 232 | *.xdy 233 | 234 | # xypic precompiled matrices and outlines 235 | *.xyc 236 | *.xyd 237 | 238 | # endfloat 239 | *.ttt 240 | *.fff 241 | 242 | # Latexian 243 | TSWLatexianTemp* 244 | 245 | ## Editors: 246 | # WinEdt 247 | *.bak 248 | *.sav 249 | 250 | # Texpad 251 | .texpadtmp 252 | 253 | # LyX 254 | *.lyx~ 255 | 256 | # Kile 257 | *.backup 258 | 259 | # gummi 260 | .*.swp 261 | 262 | # KBibTeX 263 | *~[0-9]* 264 | 265 | # TeXnicCenter 266 | *.tps 267 | 268 | # auto folder when using emacs and auctex 269 | ./auto/* 270 | *.el 271 | 272 | # expex forward references with \gathertags 273 | *-tags.tex 274 | 275 | # standalone packages 276 | *.sta 277 | 278 | # Makeindex log files 279 | *.lpz 280 | -------------------------------------------------------------------------------- /code/dictionary-learning/multi_infer.m: -------------------------------------------------------------------------------- 1 | function coef_vals = multi_infer(dictionary_n, x_im, infer_type, opts) 2 | 3 | % coef_vals = multi_l1ls(dictionary_n, x_im, infer_type, opts) 4 | % 5 | % Function to perform inference on a multitude of test vectors. The 6 | % inference algorithm given by infer_type is run on each column of x_im 7 | % with repect to dictionary_n. 8 | % 9 | % Inputs: 10 | % dictionary_n - The dictionary to decompose the data into 11 | % x_im - A matrix with the columns as data to decompose 12 | % infer_type - The type of inference algorithm to use. Can be: 13 | % - 'l1ls', 'l1ls_nneg', 'cg_l2l1', 14 | % 'sparsenet', 'MP', 'OMP', 'OOMP', 'OMP_qr', 15 | % or 'StOMP' 16 | % To use 'MP', 'OOMP', ot 'StOMP', the SparseLab100 17 | % library is needed (available at 18 | % http://sparselab.stanford.edu). To use OMP_qr, 19 | % the sparsify (v4 or later) library available at 20 | % http://www.personal.soton.ac.uk/tb1m08/sparsify/sparsify.html 21 | % opts - A struct of options needed for the optimization 22 | % program selected. 23 | % 24 | % Outputs: 25 | % coef_vals - optimized coefficients 26 | % 27 | % Last Modified 6/3/2010 - Adam Charles 28 | 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | %% Initializations 31 | 32 | % Initialize coefficients 33 | coef_vals = zeros(size(dictionary_n, 2), opts.in_iter); 34 | 35 | % Get necessary parameters 36 | if strcmp(infer_type, 'l1ls') || strcmp(infer_type, 'cg_l2l1') || ... 37 | strcmp(infer_type, 'l1ls_nneg') 38 | lambda_val = opts.lambda; 39 | tol = opts.tol; 40 | end 41 | 42 | if strcmp(infer_type, 'sparsenet') 43 | lambda_val = opts.lambda; 44 | end 45 | 46 | if strcmp(infer_type, 'OOMP') 47 | tol = opts.tol; 48 | end 49 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 50 | %% Perform the L1-regulized optimization on the data 51 | 52 | if strcmp(infer_type, 'l1ls') 53 | parfor index_in = 1:opts.in_iter 54 | [coef_vals(:, index_in)] = l1_ls(dictionary_n, x_im(:,index_in),... 55 | lambda_val, tol,1); 56 | end 57 | elseif strcmp(infer_type, 'cg_l2l1') 58 | parfor index_in = 1:opts.in_iter 59 | coef_vals(:, index_in) = cg_l2l1(dictionary_n, tol,... 60 | x_im(:,index_in), lambda_val); 61 | end 62 | elseif strcmp(infer_type, 'l1ls_nneg') 63 | parfor index_in = 1:opts.in_iter 64 | [coef_vals(:, index_in)] = l1_ls_nonneg(dictionary_n, x_im(:,index_in),... 65 | lambda_val, tol,1); 66 | end 67 | elseif strcmp(infer_type, 'sparsenet') 68 | % sparsenet version 69 | coef_vals = sparsenet_sparsify(x_im, dictionary_n,... 70 | opts.lambda, 'soft', 0); 71 | fprintf('used sparsenet...\n') 72 | elseif strcmp(infer_type, 'MP') 73 | for index_in = 1:opts.in_iter 74 | % Find the optimal coefficients for the given basis for each 75 | % hyperspectral image vector. This option uses hard-sparse 76 | % minimization via Matching pursuit 77 | [coef_vals(:, index_in)] = SolveMP(dictionary_n, x_im(:,index_in),... 78 | size(dictionary_n, 2)); 79 | end 80 | elseif strcmp(infer_type, 'OMP') 81 | options.tol = opts.tol; 82 | parfor index_in = 1:opts.in_iter 83 | coef_vals(:, index_in) = perform_omp(dictionary_n, x_im(:,index_in), options); 84 | end 85 | elseif strcmp(infer_type, 'OOMP') 86 | parfor index_in = 1:opts.in_iter 87 | [coef_vals(:, index_in)] = SolveOOMP(dictionary_n, x_im(:,index_in),... 88 | tol, Inf, tol); 89 | end 90 | elseif strcmp(infer_type, 'StOMP') 91 | for index_in = 1:opts.in_iter 92 | [coef_vals(:, index_in), ~] = SolveStOMP(dictionary_n, x_im(:,index_in),... 93 | opts.h_sparse); 94 | end 95 | elseif strcmp(infer_type, 'OMP_qr') 96 | parfor index_in = 1:opts.in_iter 97 | [coef_vals(:, index_in), ~, ~] = greed_omp_qr(x_im(:,index_in), ... 98 | dictionary_n,size(dictionary_n, 2)); 99 | end 100 | else 101 | error('Unknown Sparsification function!!') 102 | end 103 | 104 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 105 | 106 | end 107 | 108 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 109 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/graph-sparse-coding/GraphSC.m: -------------------------------------------------------------------------------- 1 | function [B S stat] = GraphSC(X, W, num_bases, alpha, beta, num_iters, Binit, pars) 2 | % Graph regularized sparse coding algorithms 3 | % 4 | % minimize_B,S 0.5*||X - B*S||^2 + alpha*Tr(SLS') + beta*sum(abs(S(:))) 5 | % subject to ||B(:,j)||_2 <= l2norm, forall j=1...size(S,1) 6 | % 7 | % Notation: 8 | % X: data matrix, each column is a sample vector 9 | % W: affinity graph matrix 10 | % num_bases: number of bases 11 | % alpha: Laplician parameter 12 | % beta: sparsity penalty parameter 13 | % num_iters: number of iteration 14 | % Binit: initial B matrix 15 | % pars: additional parameters to specify (see the code) 16 | % 17 | % This code is modified from the codes provided by Honglak Lee, Alexis 18 | % Battle, Rajat Raina, and Andrew Y. Ng in the following paper: 19 | % 'Efficient Sparse Codig Algorithms', Honglak Lee, Alexis Battle, Rajat Raina, Andrew Y. Ng, 20 | % Advances in Neural Information Processing Systems (NIPS) 19, 2007 21 | % 22 | % References: 23 | % [1] Miao Zheng, Jiajun Bu, Chun Chen, Can Wang, Lijun Zhang, Guang Qiu, Deng Cai. 24 | % "Graph Regularized Sparse Coding for Image Representation", 25 | % IEEE Transactions on Image Processing, Vol. 20, No. 5, pp. 1327-1336, 2011. 26 | % 27 | % Version1.0 -- Nov/2009 28 | % Version2.0 -- Jan/2012 29 | % Written by Miao Zheng 30 | % 31 | 32 | diff = 1e-7; 33 | 34 | pars.mFea = size(X,1); 35 | pars.nSmp = size(X,2); 36 | pars.num_bases = num_bases; 37 | pars.num_iters = num_iters; 38 | pars.beta = beta; 39 | pars.noise_var = 1; 40 | pars.sigma = 1; 41 | pars.VAR_basis = 1; 42 | 43 | 44 | % Sparsity parameters 45 | if ~isfield(pars,'tol') 46 | pars.tol = 0.005; 47 | end 48 | 49 | % initialize basis 50 | if ~exist('Binit','var') || isempty(Binit) 51 | B = rand(pars.mFea,pars.num_bases)-0.5; 52 | B = B - repmat(mean(B,1), size(B,1),1); 53 | B = B*diag(1./sqrt(sum(B.*B))); 54 | else 55 | disp('Using Binit...'); 56 | B = Binit; 57 | end; 58 | 59 | 60 | % initialize t only if it does not exist 61 | t=0; 62 | % statistics variable 63 | stat= []; 64 | stat.fobj_avg = []; 65 | stat.fresidue_avg = []; 66 | stat.fsparsity_avg = []; 67 | stat.var_tot = []; 68 | stat.svar_tot = []; 69 | stat.elapsed_time=0; 70 | 71 | 72 | % Construct the K-NN Graph 73 | if isempty(W) 74 | W = constructW(X'); 75 | end 76 | DCol = full(sum(W,2)); 77 | D = spdiags(DCol,0,speye(size(W,1))); 78 | L = D - W; 79 | 80 | 81 | % optimization loop 82 | while t < pars.num_iters 83 | t=t+1; 84 | start_time= cputime; 85 | 86 | stat.fobj_total=0; 87 | stat.fresidue_total=0; 88 | stat.fsparsity_total=0; 89 | stat.flaplacian_total = 0; 90 | stat.var_tot=0; 91 | stat.svar_tot=0; 92 | 93 | % learn coefficients (conjugate gradient) 94 | if t ==1 95 | S= learn_coefficients(B, X, alpha, pars.beta/pars.sigma*pars.noise_var,L); 96 | else 97 | S= learn_coefficients(B, X, alpha, pars.beta/pars.sigma*pars.noise_var, L, S); 98 | end 99 | S(isnan(S))=0; 100 | 101 | % get objective 102 | [fobj, fresidue, fsparsity, flaplacian] = getObjective(B, S, X, alpha, L, pars.noise_var, pars.beta, pars.sigma); 103 | 104 | stat.fobj_total = stat.fobj_total + fobj; 105 | stat.flaplacian_total = stat.flaplacian_total + flaplacian; 106 | stat.fresidue_total = stat.fresidue_total + fresidue; 107 | stat.fsparsity_total = stat.fsparsity_total + fsparsity; 108 | stat.var_tot = stat.var_tot + sum(sum(S.^2,1))/size(S,1); 109 | 110 | % update basis 111 | B = learn_basis(X, S, pars.VAR_basis); 112 | 113 | % get statistics 114 | stat.fobj_avg(t) = stat.fobj_total / pars.nSmp; 115 | stat.fresidue_avg(t) = stat.fresidue_total / pars.nSmp; 116 | stat.fsparsity_avg(t) = stat.fsparsity_total / pars.nSmp; 117 | stat.flaplacian_avg(t) = stat.flaplacian_total / pars.nSmp; 118 | stat.var_avg(t) = stat.var_tot / pars.nSmp; 119 | stat.svar_avg(t) = stat.svar_tot / pars.nSmp; 120 | stat.elapsed_time(t) = cputime - start_time; 121 | 122 | 123 | if t>199 124 | if(stat.fobj_avg(t-1) - stat.fobj_avg(t) 7; solveUse = varargin{1}; 19 | else; solveUse = 'quadprog'; % QUADPROG, TFOCS, FISTA 20 | end 21 | 22 | if iscell(D) 23 | if numel(D) == 1 24 | D = D{1}; 25 | DTD = double(2*(D.'*D)); 26 | elseif numel(D) == 2 27 | DTD = D{2}; 28 | D = D{1}; 29 | else 30 | error('Bad values for dictionary D input') 31 | end 32 | end 33 | 34 | if isempty(TOL); TOL = 1e-3; end 35 | if size(D,2)~=numel(tau_vec); error('Dimension mismatch!'); end 36 | 37 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 38 | %% Set up problem (Basic size/dimension re-org) 39 | 40 | mov_vec = vec(squeeze(mov_vec)); % Make sure time-trace is a column vector 41 | tau_vec = vec(tau_vec); % Make sure weight vector is a column vector 42 | N2 = numel(tau_vec); % Get the numner of dictionary atoms 43 | 44 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 45 | %% Run the weighted LASSO to get the coefficients 46 | 47 | 48 | qp_opts.Display = 'off'; 49 | 50 | if norm(mov_vec) == 0 51 | S = zeros(N2, 1); % This is the trivial solution to generate all zeros linearly. 52 | else 53 | if nonneg 54 | switch lower(solveUse) 55 | case 'mpc' 56 | mpc_opts = mpcActiveSetOptions; 57 | if ~exist('iA', 'var'); iA = false(0,1); 58 | else; iA = false(size(zeros(0,1))); end 59 | [S, ~, iA, ~] = mpcActiveSetSolver(DTD,... % Hessian matrix 60 | double(-2*D.'*mov_vec+lambda_val.*tau_vec),... % Multiplier of the objective linear function 61 | zeros(0,n),... % Linear inequality constraint coefs 62 | zeros(0,1),... % Right-hand side of inequality constraints 63 | zeros(0,n),... % Linear eq constraint coefs 64 | zeros(0,1),... % Right-hand side of eq. constraints 65 | iA,... % Initial active inequalities 66 | mpc_opts); % Using MPC to solve the non-negative weighted LASSO 67 | case 'quadprog' 68 | S = quadprog(double(2*(DTD)), ... 69 | double(-2*D.'*mov_vec+lambda_val.*tau_vec), [], ... 70 | [], [], [], zeros(N2,1), Inf*ones(N2,1), S(:), qp_opts); % Use quadratic programming to solve the non-negative LASSO 71 | case 'tfocs' 72 | opts.nonneg = true; 73 | opts.tol = TOL; % Set TFOCS tolerance 74 | opts.printEvery = 0; 75 | S = solver_L1RLS(D, mov_vec, lambda_val.*tau_vec, S(:), opts); % Solve the weighted LASSO using TFOCS and a modified linear operator 76 | case 'fista' 77 | par_spams.mode = 2; 78 | par_spams.pos = true; 79 | par_spams.lambda = max(mean(tau_vec),1e-3); 80 | S = mexLassoWeighted(double(mov_vec), D, ... 81 | double(tau_vec)./par_spams.lambda, par_spams); 82 | otherwise 83 | end 84 | else 85 | opts.nonneg = false; 86 | S = solver_L1RLS(D, mov_vec, lambda_val.*tau_vec, [], opts); % Solve the weighted LASSO using TFOCS and a modified linear operator 87 | % S = S./tau_vec; % Re-normalize to get weighted LASSO values 88 | end 89 | % if nonneg 90 | % if all(S==0) 91 | % S = quadprog(double(2*(DTD)), ... 92 | % double(-2*D.'*mov_vec+lambda_val.*tau_vec), [], ... 93 | % [], [], [], zeros(N2,1), Inf*ones(N2,1), [], qp_opts); % Use quadratic programming to solve the non-negative LASSO 94 | % else 95 | % S = quadprog(double(2*(DTD)), ... 96 | % double(-2*D.'*mov_vec+lambda_val.*tau_vec), [], ... 97 | % [], [], [], zeros(N2,1), Inf*ones(N2,1), S, qp_opts); % Use quadratic programming to solve the non-negative LASSO 98 | % end 99 | % else 100 | % opts.nonneg = false; 101 | % S = solver_L1RLS(D, mov_vec, lambda_val, zeros(N2, 1), opts ); % Solve the weighted LASSO using TFOCS and a modified linear operator 102 | % S = S./tau_vec; % Re-normalize to get weighted LASSO values 103 | % end 104 | end 105 | 106 | S(S(:)<0.1*max(S(:))) = 0; % Sparsifying step to remove small values 107 | 108 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 109 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 110 | 111 | % 112 | -------------------------------------------------------------------------------- /code/support-functions/reCalcCoefSparse.m: -------------------------------------------------------------------------------- 1 | function S = reCalcCoefSparse(data, D, S, lambda, varargin) 2 | 3 | % S = recalcCoefSparse(data, D, S) 4 | % 5 | % Function to recalulate the sparse coefficients given a dictionary D and 6 | % data "data". The current coefficeints S are used to identify support. 7 | % This function is not designed to be used instead of the inference step, 8 | % and instead to be used only after the merging of dictionary elements 9 | % in post-processing. 10 | % 11 | % 2020 - Adam Charles 12 | 13 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 14 | %% Input parsing 15 | 16 | if nargin > 4; nonneg = varargin{1}; % If provided, set non-negativity flag 17 | else nonneg = false; % Default flag is 'false' 18 | end 19 | 20 | if nargin > 5; solverOpt = varargin{2}; % If provided, set the option of what solver to use. 21 | else ; solverOpt = 'OMP'; % Default to OMP 22 | end 23 | 24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 25 | classS = class(S); % Record the data type that the coefficients were initially stored as 26 | 27 | if ndims(S)==3 28 | S3D = true; % Set flag to reshape array back to 3D array at the end 29 | Sdim = size(S); % Get full size of coefficients 30 | nPix = size(S,1)*size(S,2); % get number of pixels 31 | nCoef = size(S,3); % Get number of coefficients 32 | S = reshape(S,nPix,nCoef); % Reshape array to be pixels-by-coefficients 33 | else 34 | S3D = false; % Do not trigger the flag to 35 | nPix = size(S,1); % get number of pixels 36 | nCoef = size(S,2); % Get number of coefficients 37 | end 38 | 39 | if ndims(data) == 3; data = reshape(data,nPix,[]); end % Ensure that the data is a 2D array (reshape if a 3D array) 40 | 41 | if strcmp(lower(solverOpt),'lasso') % Solve using the convex LASSO optimization 42 | if nonneg % This is the case for non-negative inference 43 | fprintf('Nonnegative LASSO chosen.\n') % Inform the user of their choice 44 | qp_opts.Display = 'off'; % Turn off the display option for output sanity 45 | DtD = double(2*D.'*D); % Pre-compute the D^T*D matrix 46 | parfor ll = 1:nPix % Loop through all the pixels (in parallel because why not) 47 | fprintf('.') 48 | f = double(-2*(D.')*vec(data(ll,:)) + lambda); % Precompute the offset vector 49 | S_out = cast(quadprog(DtD, f, [], [], [], [],... 50 | zeros(nCoef,1), Inf*ones(nCoef,1), S(ll,:),... 51 | qp_opts), classS); % Use quadratic programming to solve the non-negative LASSO 52 | max_val = max(S_out); % Compute the max coefficient value 53 | S_out(S_out<0.1*max_val) = 0; % Threshold the output since LASSO often returns silly small values 54 | S(ll,:) = S_out; % Save the coefficients for this pixel. 55 | fprintf('.') 56 | end 57 | fprintf('done.\n') 58 | else 59 | fprintf('Regular LASSO chosen.\n') 60 | parfor ll = 1:nPix % Loop through all the pixels 61 | S(ll,:) = cast(lasso(D, vec(data(ll,:)), 'lambda', ... 62 | lambda), classS); % Use the standard LASSO inference 63 | end 64 | S(S(:)<0.1*max(S(:))) = 0; % Threshold the output since LASSO often retuens silly small values 65 | end 66 | elseif strcmp(lower(solverOpt),'omp') % Solve using OMP 67 | if nonneg 68 | % Does not exist yet 69 | S = reCalcCoefSparse(data, D, S, lambda, nonneg, 'lasso'); % Run with LASSO nonneg 70 | else 71 | DtD = double(D.'*D); % Pre-compute the D^T*D matrix 72 | parfor ll = 1:nPix % Loop through all the pixels 73 | S(ll,:) = cast(omp(D, vec(data(ll,:)), DtD), classS); % Run OMP on the ll^th pixel's time-trace 74 | end 75 | end 76 | end 77 | 78 | if S3D; S = reshape(S,Sdim); end % Reshape S back into a 3D array 79 | 80 | end 81 | 82 | 83 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 84 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 85 | 86 | 87 | %elseif ndims(S)==2 88 | % nPix = size(S,1); 89 | % nCoef = size(S,2); 90 | % parfor ll = 1:nPix 91 | % idxCoef = squeeze(S_on(ll,:))'==1; 92 | % TMP = cast(zeros(nCoef,1),classS); 93 | % TMP(idxCoef) = cast(lsqnonneg(double(D(:,idxCoef)),... 94 | % double(squeeze(data(ll,:))).'),classS); % Compute the least-squares solution for the coefficient 95 | % S(ll,:) = TMP; 96 | % end 97 | %else 98 | % error('Bad format for coefficient array') 99 | 100 | 101 | % S(ll,:) = singleGaussNeuroInfer(tau_mat(ll,:), ... 102 | % mov(ll,:), D, lambda, 1e-4, nonneg, S(ll,:)); % Perform column-wise Gaussian de-mixing - calls a LASSO solver that can be non-negative 103 | -------------------------------------------------------------------------------- /code/external-code/distinguishable_colors.m: -------------------------------------------------------------------------------- 1 | function colors = distinguishable_colors(n_colors,bg,func) 2 | % DISTINGUISHABLE_COLORS: pick colors that are maximally perceptually distinct 3 | % 4 | % When plotting a set of lines, you may want to distinguish them by color. 5 | % By default, Matlab chooses a small set of colors and cycles among them, 6 | % and so if you have more than a few lines there will be confusion about 7 | % which line is which. To fix this problem, one would want to be able to 8 | % pick a much larger set of distinct colors, where the number of colors 9 | % equals or exceeds the number of lines you want to plot. Because our 10 | % ability to distinguish among colors has limits, one should choose these 11 | % colors to be "maximally perceptually distinguishable." 12 | % 13 | % This function generates a set of colors which are distinguishable 14 | % by reference to the "Lab" color space, which more closely matches 15 | % human color perception than RGB. Given an initial large list of possible 16 | % colors, it iteratively chooses the entry in the list that is farthest (in 17 | % Lab space) from all previously-chosen entries. While this "greedy" 18 | % algorithm does not yield a global maximum, it is simple and efficient. 19 | % Moreover, the sequence of colors is consistent no matter how many you 20 | % request, which facilitates the users' ability to learn the color order 21 | % and avoids major changes in the appearance of plots when adding or 22 | % removing lines. 23 | % 24 | % Syntax: 25 | % colors = distinguishable_colors(n_colors) 26 | % Specify the number of colors you want as a scalar, n_colors. This will 27 | % generate an n_colors-by-3 matrix, each row representing an RGB 28 | % color triple. If you don't precisely know how many you will need in 29 | % advance, there is no harm (other than execution time) in specifying 30 | % slightly more than you think you will need. 31 | % 32 | % colors = distinguishable_colors(n_colors,bg) 33 | % This syntax allows you to specify the background color, to make sure that 34 | % your colors are also distinguishable from the background. Default value 35 | % is white. bg may be specified as an RGB triple or as one of the standard 36 | % "ColorSpec" strings. You can even specify multiple colors: 37 | % bg = {'w','k'} 38 | % or 39 | % bg = [1 1 1; 0 0 0] 40 | % will only produce colors that are distinguishable from both white and 41 | % black. 42 | % 43 | % colors = distinguishable_colors(n_colors,bg,rgb2labfunc) 44 | % By default, distinguishable_colors uses the image processing toolbox's 45 | % color conversion functions makecform and applycform. Alternatively, you 46 | % can supply your own color conversion function. 47 | % 48 | % Example: 49 | % c = distinguishable_colors(25); 50 | % figure 51 | % image(reshape(c,[1 size(c)])) 52 | % 53 | % Example using the file exchange's 'colorspace': 54 | % func = @(x) colorspace('RGB->Lab',x); 55 | % c = distinguishable_colors(25,'w',func); 56 | 57 | % Copyright 2010-2011 by Timothy E. Holy 58 | 59 | % Parse the inputs 60 | if (nargin < 2) 61 | bg = [1 1 1]; % default white background 62 | else 63 | if iscell(bg) 64 | % User specified a list of colors as a cell aray 65 | bgc = bg; 66 | for i = 1:length(bgc) 67 | bgc{i} = parsecolor(bgc{i}); 68 | end 69 | bg = cat(1,bgc{:}); 70 | else 71 | % User specified a numeric array of colors (n-by-3) 72 | bg = parsecolor(bg); 73 | end 74 | end 75 | 76 | % Generate a sizable number of RGB triples. This represents our space of 77 | % possible choices. By starting in RGB space, we ensure that all of the 78 | % colors can be generated by the monitor. 79 | n_grid = 30; % number of grid divisions along each axis in RGB space 80 | x = linspace(0,1,n_grid); 81 | [R,G,B] = ndgrid(x,x,x); 82 | rgb = [R(:) G(:) B(:)]; 83 | if (n_colors > size(rgb,1)/3) 84 | error('You can''t readily distinguish that many colors'); 85 | end 86 | 87 | % Convert to Lab color space, which more closely represents human 88 | % perception 89 | if (nargin > 2) 90 | lab = func(rgb); 91 | bglab = func(bg); 92 | else 93 | C = makecform('srgb2lab'); 94 | lab = applycform(rgb,C); 95 | bglab = applycform(bg,C); 96 | end 97 | 98 | % If the user specified multiple background colors, compute distances 99 | % from the candidate colors to the background colors 100 | mindist2 = inf(size(rgb,1),1); 101 | for i = 1:size(bglab,1)-1 102 | dX = bsxfun(@minus,lab,bglab(i,:)); % displacement all colors from bg 103 | dist2 = sum(dX.^2,2); % square distance 104 | mindist2 = min(dist2,mindist2); % dist2 to closest previously-chosen color 105 | end 106 | 107 | % Iteratively pick the color that maximizes the distance to the nearest 108 | % already-picked color 109 | colors = zeros(n_colors,3); 110 | lastlab = bglab(end,:); % initialize by making the "previous" color equal to background 111 | for i = 1:n_colors 112 | dX = bsxfun(@minus,lab,lastlab); % displacement of last from all colors on list 113 | dist2 = sum(dX.^2,2); % square distance 114 | mindist2 = min(dist2,mindist2); % dist2 to closest previously-chosen color 115 | [~,index] = max(mindist2); % find the entry farthest from all previously-chosen colors 116 | colors(i,:) = rgb(index,:); % save for output 117 | lastlab = lab(index,:); % prepare for next iteration 118 | end 119 | end 120 | 121 | function c = parsecolor(s) 122 | if ischar(s) 123 | c = colorstr2rgb(s); 124 | elseif isnumeric(s) && size(s,2) == 3 125 | c = s; 126 | else 127 | error('MATLAB:InvalidColorSpec','Color specification cannot be parsed.'); 128 | end 129 | end 130 | 131 | function c = colorstr2rgb(c) 132 | % Convert a color string to an RGB value. 133 | % This is cribbed from Matlab's whitebg function. 134 | % Why don't they make this a stand-alone function? 135 | rgbspec = [1 0 0;0 1 0;0 0 1;1 1 1;0 1 1;1 0 1;1 1 0;0 0 0]; 136 | cspec = 'rgbwcmyk'; 137 | k = find(cspec==c(1)); 138 | if isempty(k) 139 | error('MATLAB:InvalidColorString','Unknown color string.'); 140 | end 141 | if k~=3 || length(c)==1, 142 | c = rgbspec(k,:); 143 | elseif length(c)>2, 144 | if strcmpi(c(1:3),'bla') 145 | c = [0 0 0]; 146 | elseif strcmpi(c(1:3),'blu') 147 | c = [0 0 1]; 148 | else 149 | error('MATLAB:UnknownColorString', 'Unknown color string.'); 150 | end 151 | end 152 | end -------------------------------------------------------------------------------- /code/support-functions/preprocessData.m: -------------------------------------------------------------------------------- 1 | function X = preprocessData(X, varargin) 2 | 3 | % X = preprocessData(X, varargin) 4 | % 5 | % Function to pre-process calcium imaging data. Current order of 6 | % operations: 7 | % - Filtering 8 | % - Averaging (temporal) 9 | % - Centering 10 | % - Normalization 11 | % 12 | % 2019 - Adam Charles 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | %% Input/option parsing 16 | 17 | p = inputParser; % Initialize the input parser 18 | p.addParameter('center', true ); % true/false 19 | p.addParameter('normalize', true ); % true/false 20 | p.addParameter('filtering', false ); % true/false 21 | p.addParameter('averaging', false ); % true/false 22 | p.addParameter('pixel_center', false ); % true/false 23 | p.addParameter('norm_baseline', 'median' ); % 'median', 'mean', or 'max' 24 | p.addParameter('center_baseline', 'min' ); % 'median', 'mean', or 'min' 25 | p.addParameter('pixel_norm', false ); % true/false 26 | p.addParameter('filter_type', 'median' ); % 'median' 27 | p.addParameter('average_type', 'mean' ); % 'mean' 28 | p.addParameter('avg_win', 3 ); % 'mean' 29 | p.addParameter('filter_size', [3,3,1] ); % 2- or 3- vector 30 | 31 | parse(p,varargin{:}); % Parse the inputs. results get saved to p.Results 32 | pars = p.Results; % Change p.Results to pars for easier reference in the code 33 | clear p % Don't need p anymore 34 | 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | %% Filtering 37 | 38 | if pars.filtering % Check if filtering is required 39 | fprintf('Performing fitering...') 40 | switch pars.filter_type 41 | case 'median' 42 | X = medfilt3(X, pars.filter_size); % Median filtering over patches of size "pars.filter_size" 43 | otherwise % No filtering 44 | warning('Improper filtering paramters; skipping filtering...') 45 | end 46 | fprintf('done.\n') 47 | else 48 | fprintf('Skipping fitering.\n') 49 | end 50 | 51 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 52 | %% Temporal averaging 53 | 54 | if pars.averaging % Check if filtering is required 55 | fprintf('Performing averaging...') 56 | switch pars.average_type 57 | case 'mean' 58 | X = movmean(X, pars.avg_win, 3); % Median filtering over patches of size "pars.filter_size" 59 | otherwise % No filtering 60 | warning('Improper filtering paramters; skipping filtering...') 61 | end 62 | fprintf('done.\n') 63 | else 64 | fprintf('Skipping averaging.\n') 65 | end 66 | 67 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 68 | %% Centering 69 | 70 | if pars.center % Check if centering is required 71 | fprintf('Centering data...') 72 | if pars.pixel_center % Check if centering should be pixelwise or global 73 | switch pars.center_baseline % Check what the data should be centered to 74 | case 'median' 75 | Fcent = median(X,3); 76 | case 'mean' 77 | Fcent = mean(X,3); 78 | case 'min' 79 | Fcent = min(X,[],3); 80 | otherwise 81 | Fcent = 1; 82 | end 83 | X = bsxfun(@plus, X, -Fcent); % Center the data on a per-pixel basis 84 | else 85 | switch pars.center_baseline 86 | case 'median' 87 | Fcent = median(X(:)); 88 | case 'mean' 89 | Fcent = mean(X(:)); 90 | case 'min' 91 | Fcent = min(X(:)); 92 | otherwise 93 | Fcent = 1; 94 | end 95 | X = X - Fcent; % Center the data on a global basis 96 | end 97 | fprintf('done.\n') 98 | else 99 | fprintf('Skipping centering.\n') 100 | end 101 | 102 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 103 | %% Normalization 104 | 105 | if pars.normalize % Check if normalization is required 106 | fprintf('Normalizing data...') 107 | if pars.pixel_norm % Check if normalization should be pixelwise or global 108 | switch pars.norm_baseline % Check what the data should be normalized to 109 | case 'median' 110 | Fnorm = median(X,3); 111 | case 'mean' 112 | Fnorm = mean(X,3); 113 | case 'max' 114 | Fnorm = max(X,[],3); 115 | otherwise 116 | Fnorm = 1; 117 | end 118 | Fnorm(Fnorm==0) = 1; 119 | X = bsxfun(@times,X,1./Fnorm); % Normalize the data on a per-pixel basis 120 | else 121 | switch pars.norm_baseline 122 | case 'median' 123 | Fnorm = median(X(:)); 124 | case 'mean' 125 | Fnorm = mean(X(:)); 126 | case 'max' 127 | Fnorm = max(X(:)); 128 | otherwise 129 | Fnorm = 1; 130 | end 131 | Fnorm(Fnorm==0) = 1; 132 | X = X./Fnorm; % Normalize the data on a global basis 133 | end 134 | fprintf('done.\n') 135 | else 136 | fprintf('Skipping normalization.\n') 137 | end 138 | 139 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 140 | %% Remove NaNs 141 | 142 | fprintf('%d NaNs found. Setting to zero...', sum(isnan(X(:)))) 143 | X(isnan(X)) = 0; % Set all NaNs to zero 144 | fprintf('done.\n') 145 | 146 | end 147 | 148 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 149 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /code/dictionary-learning/sample_exemplars.m: -------------------------------------------------------------------------------- 1 | function x_im = sample_exemplars(data_obj, opts) 2 | 3 | % function x_im = sample_exemplars(data_obj, opts) 4 | % 5 | % Function to sample exemplars. Takes in a data object and a struct of 6 | % algorithmic parameters and returns either a uniform sampling of the data 7 | % or a sampling based on finding a sample set with low correlations between 8 | % the samples. 9 | % 10 | % 2018 - Adam Charles 11 | 12 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 | %% Input parsing 14 | 15 | if ~isfield(opts, 'div_samp') 16 | opts.div_samp = 0; % Default to not having negativity constraints 17 | end 18 | 19 | if ~isfield(opts, 'div_thresh') 20 | opts.div_thresh = 0.85; % Default to not having negativity constraints 21 | end 22 | 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | %% Get Training Data. 25 | % Some parts can be run in parallel with appropriate slicing. 26 | 27 | ix = ones(opts.in_iter,1); % Initialize the sample indexing to all 28 | k_start = 2; % Initialize the index start to check for correlated samples 29 | div_thr = opts.div_thresh; % Initialize the diversity threshold for resampling correlated samples 30 | x_im = []; % Initialize the exemplar sample array 31 | 32 | if strcmp(opts.data_type, 'vector') 33 | 34 | while sum(ix)~=0 35 | data_use_ind = ceil(size(data_obj, 2)*rand(1, sum(ix))); % Select a sampling of the data blindly 36 | % Possible normalization 37 | if opts.ssim_flag == 1 38 | V_norms = (sqrt(sum(data_obj(:, data_use_ind).^2))); % Calculate the norms for all the vectors 39 | V_zeros = V_norms == 0; % Locate the zero vectors to avoid NaNs 40 | V_norms(V_zeros) = 1; 41 | x_im = cat(2, x_im, data_obj(:, data_use_ind)*diag(1./V_norms)); % Add the normalized chosen samples to the sample array 42 | else 43 | x_im = cat(2,x_im,data_obj(:, data_use_ind)); % Add the chosen samples to the sample array 44 | end 45 | if opts.div_samp == 0 46 | ix = ix*0; % If no diversity required, just keep everything 47 | else 48 | ix = test_seq(x_im, k_start, div_thr); % Test the chosen exemplars for enough diversity 49 | x_im = x_im(:,~ix); % Keep only the sufficiently different vectors 50 | div_thr = div_thr + 0.05; % Increase threshold so that this does not go on forever 51 | k_start = size(x_im,2)+1; % Update the counter start to check for correlations 52 | end 53 | end 54 | elseif strcmp(opts.data_type, 'square') % Can't slice the main image cube, so extract data serially 55 | num_im = size(data_obj, 3); % Get data cube info: Number of images 56 | height_im = size(data_obj, 1) - opts.bl_size(1) + 1; % Get heights and widths for allowable starting indices for subimages 57 | width_im = size(data_obj, 2) - opts.bl_size(2) + 1; % --------------- 58 | while sum(ix)~=0 59 | start_ind = ceil(rand(sum(ix), 3).*[height_im, width_im, num_im]); % Pick random starting points 60 | end_ind = bsxfun(@plus, start_ind, ... 61 | [opts.bl_size(1), opts.bl_size(1), 1]) - 1; % Calculate ending points 62 | for index_in = 1:sum(ix) 63 | x_im = cat(2, x_im, reshape(data_obj(start_ind(index_in,1):end_ind(index_in,1),... 64 | start_ind(index_in,2):end_ind(index_in,2), start_ind(index_in,3)), [], 1)); % Pick out subimage and reshape it to a vector 65 | end 66 | if opts.ssim_flag == 1 67 | % Can use parfor here since the x_im is appropriately 'sliced' 68 | parfor index_in = 1:(size(x_im,2)-sum(ix)+1) 69 | if std(x_im(:,index_in)) > std_min_vec 70 | x_im(:,index_in) = x_im(:,index_in) - mean(x_im(:,index_in)); 71 | x_im(:,index_in) = x_im(:,index_in)/std(x_im(:,index_in)); 72 | end 73 | end 74 | end 75 | if opts.div_samp == 0 76 | ix = ix*0; % If no diversity required, just keep everything 77 | else 78 | ix = test_seq(x_im, k_start, div_thr); % Test the chosen exemplars for enough diversity 79 | x_im = x_im(:,~ix); % Keep only the sufficiently different vectors 80 | div_thr = div_thr + 0.05; % Increase threshold so that this does not go on forever 81 | k_start = size(x_im,2)+1; % Update the counter start to check for correlations 82 | end 83 | end 84 | elseif strcmp(opts.data_type, 'cube') 85 | num_im = length(data_obj); % Get sizes of the data blocks (color images or video) 86 | height_im = size(data_obj{1}, 1) - opts.bl_size(1) + 1; % Get heights and widths for allowable starting indices for subimages 87 | width_im = size(data_obj{1}, 2) - opts.bl_size(2) + 1; % ------------------- 88 | depth_im = size(data_obj{1}, 3) - opts.bl_size(3) + 1; % ------------------- 89 | 90 | start_ind = ceil(rand(sum(ix), 4).*[height_im, width_im, depth_im, num_im]); % Pick random starting points 91 | for index_in = 1:opts.in_iter 92 | x_im = cat(2,x_im,reshape(data_obj{start_ind(4)}(... 93 | start_ind(1):start_ind(1)+opts.bl_size(1)-1,... 94 | start_ind(2):start_ind(2)+opts.bl_size(2)-1, ... 95 | start_ind(3):start_ind(3)+opts.bl_size(3)-1), [], 1)); % Pick out subimage and reshape it to a vector 96 | end 97 | else 98 | error('Unknown Data Type!! Choose ''vector'', ''square'' or ''cube''...') 99 | end 100 | 101 | 102 | 103 | end 104 | 105 | function ix = test_seq(X, k_start, thresh) 106 | if isempty(k_start) % Check if a starting point to check is given 107 | k_start = 2; 108 | end 109 | ix = zeros(size(X,2),1); 110 | if norm(X(:,1)) == 0 111 | ix(1) = 1; % If the first vector is zeros, add it to the remove list 112 | end 113 | x_norms = sqrt(sum(X.^2,1)); 114 | for kk = k_start:size(X,2) 115 | if norm(X(:,kk)) == 0 116 | ix(kk) = 1; 117 | else 118 | ips = X(:,1:(kk-1)).'*X(:,kk)./(x_norms(1:(kk-1))*x_norms(kk)); 119 | ips(x_norms(1:(kk-1))==0) = 0; 120 | if max(ips) > thresh 121 | ix(kk) = 1; % If spectral angle is too high, add the vector to the remove list 122 | else 123 | end 124 | end 125 | end 126 | end 127 | 128 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 129 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 130 | -------------------------------------------------------------------------------- /code/external-code/colormaps_mathworks_v11/matlab/ametrine.m: -------------------------------------------------------------------------------- 1 | function cmap=ametrine(n,varargin) 2 | %AMETRINE "Nearly" isoluminant-Colormap compatible with red-green color perception deficiencies 3 | % 4 | % Written by Matthias Geissbuehler - matthias.geissbuehler@a3.epfl.ch 5 | % January 2013 6 | % 7 | % Features: 8 | % 1) All colors have the same luminescence (ideal for lifetime 9 | % images that will be displayed with an additional transparency map 10 | % to "mask" places where the lifetime is not well defined) 11 | % 2) Color vision deficient persons can only see reduced color: as much 12 | % as 10% of adult male persons have a red-green defiency (either 13 | % Deuteranope or Protanope) -> as a result they can only distinguish 14 | % between blue and yellow. A colormap which is "save" for color vision 15 | % deficient persons is hence only based on these colors. 16 | % However: people with normal vision DO have a larger space of colors 17 | % available: it would be a pity to discard this freedom. So the goal 18 | % must be a colormap that is both using as many colors as possible 19 | % for normal-sighted people as well as a colormap that will "look" 20 | % blue-yellow to people with colorblindness without transitions that 21 | % falsify the information by including a non-distinct transitions 22 | % (as is the case for many colormaps based on the whole spectrum 23 | % (ex. rainbow or jet). 24 | % That's what this colormap here tries to achieve. 25 | % 3) In order to be save for publications, the colormap uses colors that 26 | % are only from the CMYK colorspace (or at least not too far) 27 | % 4) In comparison to "isolum", this colormap slightly trades off 28 | % isoluminescence for a higher color contrast 29 | % 30 | % 31 | % See also: isolum, morgenstemning 32 | % 33 | % 34 | % Please feel free to use this colormap at your own convenience. 35 | % A citation to the original article is of course appreciated, however not "mandatory" :-) 36 | % 37 | % M. Geissbuehler and T. Lasser "How to display data by color schemes compatible 38 | % with red-green color perception deficiencies" Opt. Express 21, 9862-9874 (2013) 39 | % http://www.opticsinfobase.org/oe/abstract.cfm?URI=oe-21-8-9862 40 | % 41 | % 42 | % For more detailed information, please see: 43 | % http://lob.epfl.ch -> Research -> Color maps 44 | % 45 | % 46 | % Usage: 47 | % cmap = ametrine(n) 48 | % 49 | % All arguments are optional: 50 | % 51 | % n The number of elements (256) 52 | % 53 | % Further on, the following options can be applied 54 | % 'gamma' The gamma of the monitor to be used (1.8) 55 | % 'minColor' The absolute minimum value can have a different color 56 | % ('none'), 'white','black','lightgray', 'darkgray' 57 | % or any RGB value ex: [0 1 0] 58 | % 'maxColor' The absolute maximum value can have a different color 59 | % 'invert' (0), 1=invert the whole colormap 60 | % 61 | % Examples: 62 | % figure; imagesc(peaks(200)); 63 | % colormap(ametrine) 64 | % colorbar 65 | % 66 | % figure; imagesc(peaks(200)); 67 | % colormap(ametrine(256,'gamma',1.8,'minColor','black','maxColor',[0 1 0])) 68 | % colorbar 69 | % 70 | % figure; imagesc(peaks(200)); 71 | % colormap(ametrine(256,'invert',1,'minColor','white')) 72 | % colorbar 73 | % 74 | % 75 | % 76 | % 77 | % 78 | % 79 | % 80 | % Copyright (c) 2013, Matthias Geissbuehler 81 | % All rights reserved. 82 | % 83 | % Redistribution and use in source and binary forms, with or without 84 | % modification, are permitted provided that the following conditions are 85 | % met: 86 | % 87 | % * Redistributions of source code must retain the above copyright 88 | % notice, this list of conditions and the following disclaimer. 89 | % * Redistributions in binary form must reproduce the above copyright 90 | % notice, this list of conditions and the following disclaimer in 91 | % the documentation and/or other materials provided with the distribution 92 | % 93 | % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 94 | % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 95 | % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 96 | % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 97 | % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 98 | % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 99 | % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 100 | % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 101 | % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102 | % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 103 | % POSSIBILITY OF SUCH DAMAGE. 104 | 105 | % Copyright 2013 Matthias Geissbuehler - matthias.geissbuehler@a3.epfl.ch 106 | % $Revision: 3.0 $ $Date: 2013/01/29 12:00:00 $ 107 | p=inputParser; 108 | p.addParamValue('gamma',1.8, @(x)x>0); 109 | p.addParamValue('minColor','none'); 110 | p.addParamValue('maxColor','none'); 111 | p.addParamValue('invert',0, @(x)x==0 || x==1); 112 | 113 | if nargin==1 114 | p.addRequired('n', @(x)x>0 && mod(x,1)==0); 115 | p.parse(n); 116 | elseif nargin>1 117 | p.addRequired('n', @(x)x>0 && mod(x,1)==0); 118 | p.parse(n, varargin{:}); 119 | else 120 | p.addParamValue('n',256, @(x)x>0 && mod(x,1)==0); 121 | p.parse(); 122 | end 123 | config = p.Results; 124 | n=config.n; 125 | 126 | %the ControlPoints and the spacing between them 127 | 128 | %the ControlPoints in a bit more colorful variant -> slightly less 129 | %isoluminescence, but gives a more vivid look 130 | cP(:,1) = [30 60 150]./255; k(1)=1; %cyan at index 1 131 | cP(:,2) = [180 90 155]./255; k(3)=17; %purple at index 17 132 | cP(:,3) = [230 85 65 ]./255; k(4)=32; %redish at index 32 133 | cP(:,4) = [220 220 0 ]./255; k(5)=64; %yellow at index 64 134 | for i=1:3 135 | f{i} = linspace(0,1,(k(i+1)-k(i)+1))'; % linear space between these controlpoints 136 | ind{i} = linspace(k(i),k(i+1),(k(i+1)-k(i)+1))'; 137 | end 138 | cmap = interp1((1:4),cP',linspace(1,4,64)); % for non-iso points, a normal interpolation gives better results 139 | 140 | 141 | % normal linear interpolation to achieve the required number of points for the colormap 142 | cmap = abs(interp1(linspace(0,1,size(cmap,1)),cmap,linspace(0,1,n))); 143 | 144 | if config.invert 145 | cmap = flipud(cmap); 146 | end 147 | 148 | if ischar(config.minColor) 149 | if ~strcmp(config.minColor,'none') 150 | switch config.minColor 151 | case 'white' 152 | cmap(1,:) = [1 1 1]; 153 | case 'black' 154 | cmap(1,:) = [0 0 0]; 155 | case 'lightgray' 156 | cmap(1,:) = [0.8 0.8 0.8]; 157 | case 'darkgray' 158 | cmap(1,:) = [0.2 0.2 0.2]; 159 | end 160 | end 161 | else 162 | cmap(1,:) = config.minColor; 163 | end 164 | if ischar(config.maxColor) 165 | if ~strcmp(config.maxColor,'none') 166 | switch config.maxColor 167 | case 'white' 168 | cmap(end,:) = [1 1 1]; 169 | case 'black' 170 | cmap(end,:) = [0 0 0]; 171 | case 'lightgray' 172 | cmap(end,:) = [0.8 0.8 0.8]; 173 | case 'darkgray' 174 | cmap(end,:) = [0.2 0.2 0.2]; 175 | end 176 | end 177 | else 178 | cmap(end,:) = config.maxColor; 179 | end 180 | -------------------------------------------------------------------------------- /code/external-code/colormaps_mathworks_v11/matlab/isolum.m: -------------------------------------------------------------------------------- 1 | function cmap=isolum(n,varargin) 2 | %ISOLUM Isoluminant-Colormap compatible with red-green color perception deficiencies 3 | % 4 | % Written by Matthias Geissbuehler - matthias.geissbuehler@a3.epfl.ch 5 | % January 2013 6 | % 7 | % Features: 8 | % 1) All colors have the same luminescence (ideal for lifetime 9 | % images that will be displayed with an additional transparency map 10 | % to "mask" places where the lifetime is not well defined) 11 | % 2) Color vision deficient persons can only see reduced color: as much 12 | % as 10% of adult male persons have a red-green defiency (either 13 | % Deuteranope or Protanope) -> as a result they can only distinguish 14 | % between blue and yellow. A colormap which is "save" for color vision 15 | % deficient persons is hence only based on these colors. 16 | % However: people with normal vision DO have a larger space of colors 17 | % available: it would be a pity to discard this freedom. So the goal 18 | % must be a colormap that is both using as many colors as possible 19 | % for normal-sighted people as well as a colormap that will "look" 20 | % blue-yellow to people with colorblindness without transitions that 21 | % falsify the information by including a non-distinct transitions 22 | % (as is the case for many colormaps based on the whole spectrum 23 | % (ex. rainbow or jet). 24 | % That's what this colormap here tries to achieve. 25 | % 3) In order to be save for publications, the colormap uses colors that 26 | % are only from the CMYK colorspace (or at least not too far) 27 | % 28 | % 29 | % See also: ametrine, morgenstemning 30 | % 31 | % 32 | % Please feel free to use this colormap at your own convenience. 33 | % A citation to the original article is of course appreciated, however not "mandatory" :-) 34 | % 35 | % M. Geissbuehler and T. Lasser "How to display data by color schemes compatible 36 | % with red-green color perception deficiencies" Opt. Express 21, 9862-9874 (2013) 37 | % http://www.opticsinfobase.org/oe/abstract.cfm?URI=oe-21-8-9862 38 | % 39 | % 40 | % For more detailed information, please see: 41 | % http://lob.epfl.ch -> Research -> Color maps 42 | % 43 | % 44 | % Usage: 45 | % cmap = isolum(n) 46 | % 47 | % All arguments are optional: 48 | % 49 | % n The number of elements (256) 50 | % 51 | % Further on, the following options can be applied 52 | % 'gamma' The gamma of the monitor to be used (1.8) 53 | % 'minColor' The absolute minimum value can have a different color 54 | % ('none'), 'white','black','lightgray', 'darkgray' 55 | % or any RGB value ex: [0 1 0] 56 | % 'maxColor' The absolute maximum value can have a different color 57 | % 'invert' (0), 1=invert the whole colormap 58 | % 59 | % Examples: 60 | % figure; imagesc(peaks(200)); 61 | % colormap(isolum) 62 | % colorbar 63 | % 64 | % figure; imagesc(peaks(200)); 65 | % colormap(isolum(256,'gamma',1.8,'minColor','black','maxColor',[0 1 0])) 66 | % colorbar 67 | % 68 | % figure; imagesc(peaks(200)); 69 | % colormap(isolum(256,'invert',1,'minColor','white')) 70 | % colorbar 71 | % 72 | % 73 | % 74 | % 75 | % 76 | % 77 | % Copyright (c) 2013, Matthias Geissbuehler 78 | % All rights reserved. 79 | % 80 | % Redistribution and use in source and binary forms, with or without 81 | % modification, are permitted provided that the following conditions are 82 | % met: 83 | % 84 | % * Redistributions of source code must retain the above copyright 85 | % notice, this list of conditions and the following disclaimer. 86 | % * Redistributions in binary form must reproduce the above copyright 87 | % notice, this list of conditions and the following disclaimer in 88 | % the documentation and/or other materials provided with the distribution 89 | % 90 | % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 91 | % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 92 | % IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 93 | % ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 94 | % LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 95 | % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 96 | % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 97 | % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 98 | % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 99 | % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 100 | % POSSIBILITY OF SUCH DAMAGE. 101 | 102 | % Copyright 2013 Matthias Geissbuehler - matthias.geissbuehler@a3.epfl.ch 103 | % $Revision: 3.0 $ $Date: 2013/01/29 12:00:00 $ 104 | p=inputParser; 105 | p.addParamValue('gamma',1.8, @(x)x>0); 106 | p.addParamValue('minColor','none'); 107 | p.addParamValue('maxColor','none'); 108 | p.addParamValue('invert',0, @(x)x==0 || x==1); 109 | 110 | if nargin==1 111 | p.addRequired('n', @(x)x>0 && mod(x,1)==0); 112 | p.parse(n); 113 | elseif nargin>1 114 | p.addRequired('n', @(x)x>0 && mod(x,1)==0); 115 | p.parse(n, varargin{:}); 116 | else 117 | p.addParamValue('n',256, @(x)x>0 && mod(x,1)==0); 118 | p.parse(); 119 | end 120 | config = p.Results; 121 | n=config.n; 122 | 123 | %the ControlPoints and the spacing between them 124 | %the ControlPoints in a very isoluminescence case 125 | cP(:,1) = [90 190 245]./255; k(1)=1; %cyan at index 1 126 | cP(:,2) = [157 157 200]./255; k(2)=16; %purple at index 16 127 | cP(:,3) = [220 150 130]./255; k(3)=32; %purple at index 32 128 | cP(:,4) = [245 120 80 ]./255; k(4)=43; %redish at index 43 129 | cP(:,5) = [180 180 0 ]./255; k(5)=64; %yellow at index 64 130 | 131 | % Making them strictly isoluminescent 132 | tempgraymap = mean((cP).^config.gamma,1); 133 | tempgraymap = tempgraymap .^(1/config.gamma); 134 | cP(1,:)=cP(1,:)./tempgraymap.*mean(tempgraymap); 135 | cP(2,:)=cP(2,:)./tempgraymap.*mean(tempgraymap); 136 | cP(3,:)=cP(3,:)./tempgraymap.*mean(tempgraymap); 137 | 138 | for i=1:4 % interpolation between control points, while keeping the luminescence constant 139 | f{i} = linspace(0,1,(k(i+1)-k(i)+1))'; % linear space between these controlpoints 140 | ind{i} = linspace(k(i),k(i+1),(k(i+1)-k(i)+1))'; 141 | 142 | cmap(ind{i},1) = ((1-f{i})*cP(1,i)^config.gamma + f{i}*cP(1,i+1)^config.gamma).^(1/config.gamma); 143 | cmap(ind{i},2) = ((1-f{i})*cP(2,i)^config.gamma + f{i}*cP(2,i+1)^config.gamma).^(1/config.gamma); 144 | cmap(ind{i},3) = ((1-f{i})*cP(3,i)^config.gamma + f{i}*cP(3,i+1)^config.gamma).^(1/config.gamma); 145 | end 146 | 147 | 148 | % normal linear interpolation to achieve the required number of points for the colormap 149 | cmap = abs(interp1(linspace(0,1,size(cmap,1)),cmap,linspace(0,1,n))); 150 | 151 | if config.invert 152 | cmap = flipud(cmap); 153 | end 154 | 155 | if ischar(config.minColor) 156 | if ~strcmp(config.minColor,'none') 157 | switch config.minColor 158 | case 'white' 159 | cmap(1,:) = [1 1 1]; 160 | case 'black' 161 | cmap(1,:) = [0 0 0]; 162 | case 'lightgray' 163 | cmap(1,:) = [0.8 0.8 0.8]; 164 | case 'darkgray' 165 | cmap(1,:) = [0.2 0.2 0.2]; 166 | end 167 | end 168 | else 169 | cmap(1,:) = config.minColor; 170 | end 171 | if ischar(config.maxColor) 172 | if ~strcmp(config.maxColor,'none') 173 | switch config.maxColor 174 | case 'white' 175 | cmap(end,:) = [1 1 1]; 176 | case 'black' 177 | cmap(end,:) = [0 0 0]; 178 | case 'lightgray' 179 | cmap(end,:) = [0.8 0.8 0.8]; 180 | case 'darkgray' 181 | cmap(end,:) = [0.2 0.2 0.2]; 182 | end 183 | end 184 | else 185 | cmap(end,:) = config.maxColor; 186 | end 187 | -------------------------------------------------------------------------------- /code/simple-simulation/simSpatialData.m: -------------------------------------------------------------------------------- 1 | function [sim_cube,profile_set,temp_dict] = simSpatialData(sim_opts) 2 | 3 | % function sim_cube = simSpatialData(sim_opts) 4 | % 5 | % Simulate some circles with temporal activity 6 | % 7 | % 2018 - Adam Charls 8 | 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% Input parsing 11 | 12 | if isempty(sim_opts) % Make sure that sim_opts is a struct 13 | clear sim_opts 14 | sim_opts = struct; 15 | end 16 | if (~isfield(sim_opts,'dims'))||isempty(sim_opts.dims) 17 | sim_opts.dims = [100,100,50]; 18 | end 19 | if (~isfield(sim_opts,'n_dict'))||isempty(sim_opts.n_dict) 20 | sim_opts.n_dict = 20; 21 | end 22 | if (~isfield(sim_opts,'p_evt'))||isempty(sim_opts.p_evt) 23 | sim_opts.p_evt = 0.8; 24 | end 25 | if (~isfield(sim_opts,'poles'))||isempty(sim_opts.poles) 26 | sim_opts.poles = 0.8; 27 | end 28 | if (~isfield(sim_opts,'circ_rad'))||isempty(sim_opts.circ_rad) 29 | sim_opts.circ_rad = 7; 30 | end 31 | if (~isfield(sim_opts,'noise_var'))||isempty(sim_opts.noise_var) 32 | sim_opts.noise_var = 0.1; 33 | end 34 | if (~isfield(sim_opts,'AR1'))||isempty(sim_opts.AR1) 35 | sim_opts.AR1 = true; 36 | end 37 | if (~isfield(sim_opts,'r0'))||isempty(sim_opts.r0) 38 | sim_opts.r0 = 0.9; 39 | end 40 | if (~isfield(sim_opts,'prof_type'))||isempty(sim_opts.prof_type) 41 | sim_opts.prof_type = 'donut'; 42 | end 43 | if (~isfield(sim_opts,'nBG'))||isempty(sim_opts.nBG) 44 | sim_opts.nBG = 1; 45 | end 46 | 47 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 48 | %% Initialization 49 | 50 | M1 = sim_opts.dims(1); % Extract dimensions of the simulated dataset 51 | M2 = sim_opts.dims(2); % | 52 | T = sim_opts.dims(3); % | 53 | N = sim_opts.n_dict; % --- 54 | 55 | 56 | % nrows = sim_opts.dims(1); % Extract dimensions of the simulated dataset 57 | % ncols = sim_opts.dims(2); % | 58 | % T = sim_opts.dims(3); % | 59 | % N = sim_opts.n_dict; % --- 60 | sig_r = sim_opts.circ_rad; 61 | r0 = sim_opts.r0 ; 62 | margin = floor([M1 * 0.1, M2* 0.1]); 63 | 64 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 65 | %% Create temporal basis 66 | p = rand(T, N); 67 | thresh = 1-(1-sim_opts.p_evt)*rand(1,N); 68 | thresh = min(max(p),thresh); 69 | temp_dict = bsxfun(@ge, p, thresh); % Initialize dictionary to a bunch of spikes 70 | temp_dict = temp_dict.*(1+2*rand(size(temp_dict))); % Modulate the event strengths 71 | if sim_opts.AR1 72 | temp_dict = filter([1 sim_opts.poles],1,temp_dict); % Pass though an AR-1 filter 73 | else 74 | temp_dict = filter(1,[1 sim_opts.poles],temp_dict); 75 | end 76 | temp_dict = temp_dict(1:T,:); % Truncate to remove extra entries added by 'filter' 77 | 78 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79 | %% Create spatial shapes 80 | 81 | profile_set = zeros(M1,M2,N); 82 | 83 | if strcmp(sim_opts.prof_type,'donut') 84 | n_y = floor(sqrt(N)); 85 | n_x = ceil(N / n_y); 86 | 87 | height = M1 - 2*margin(1); 88 | width = M2 - 2*margin(2); 89 | Y0 = margin(1) + floor(height/n_y)*(0:n_y-1); 90 | X0 = margin(2) + floor(width/n_x)*(0:n_x-1); 91 | 92 | inds = randperm(n_x*n_y,N); 93 | [x0,y0] = meshgrid(X0,Y0); 94 | x0 = x0(inds) + randn(size(inds))*margin(2)/3; 95 | y0 = y0(inds) + randn(size(inds))*margin(1)/3; 96 | 97 | [x,y] = meshgrid(1:M2,1:M1); 98 | for kk = 1:N 99 | xscale = max(1,1.2*rand(1)); 100 | yscale = 1/xscale; 101 | off_tmp = max(-1,min(1,randn(1))); 102 | sig_tmp = (1+0.1*randn(1))*(sig_r/2)^2; 103 | data = exp(-(((x-x0(kk))/xscale).^2+((y-y0(kk))/yscale).^2+off_tmp*(x-x0(kk)).*(y-y0(kk)))/sig_tmp); 104 | tf = 0.7; 105 | data = data - r0*exp(-(((x-x0(kk))/(xscale)).^2+((y-y0(kk))/(yscale)).^2+off_tmp*(x-x0(kk)).*(y-y0(kk)))/(tf*sig_tmp)); 106 | profile_set(:,:,kk) = reshape(data(:).*(data(:) > 0.1),M1,M2); 107 | end 108 | 109 | else % strcmp(sim_opts.prof_type,'blob') 110 | circ = -ceil(sim_opts.circ_rad):ceil(sim_opts.circ_rad); 111 | circ = bsxfun(@plus, circ.^2, (circ.^2).')<=(sim_opts.circ_rad).^2; 112 | 113 | n_y = floor(sqrt(N)); 114 | n_x = ceil(N / n_y); 115 | 116 | height = M1 - margin(1); 117 | width = M2 - margin(2); 118 | Y0 = 2*margin(1) + floor(height/n_y)*(0:n_y-1); 119 | X0 = margin(2) + floor(width/n_x)*(0:n_x-1); 120 | 121 | inds = randperm(n_x*n_y,N); 122 | [x0,y0] = meshgrid(X0,Y0); 123 | x0 = round(x0(inds) + randn(size(inds))*margin(2)/3); 124 | y0 = round(y0(inds) + randn(size(inds))*margin(1)/3); 125 | % figure;scatter(x0,y0) 126 | % xlim([0 M2]) 127 | % ylim([0 M1]) 128 | for kk = 1:size(profile_set,3) 129 | profile_set(x0(kk),y0(kk),kk) = 1; 130 | profile_set(:,:,kk) = convn(profile_set(:,:,kk), circ, 'same'); 131 | profile_set(:,:,kk) = profile_set(:,:,kk) + profile_set(:,:,kk).*randn(size(profile_set(:,:,kk))); 132 | end 133 | 134 | gk_ext = 5; 135 | gk_var = 5; 136 | gk = exp(- bsxfun(@plus,vec(-gk_ext:gk_ext).^2,... 137 | (-gk_ext:gk_ext).^2)/(2*gk_var)); 138 | gk = gk./norm(gk(:)); 139 | 140 | % profile_set(profile_set>0) = abs(randn(sum(profile_set(:)>0))); 141 | for kk = 1:size(profile_set,3) 142 | profile_set(:,:,kk) = abs(convn(profile_set(:,:,kk), gk, 'same')); 143 | profile_set(:,:,kk) = profile_set(:,:,kk).*(profile_set(:,:,kk) > 0.1); 144 | end 145 | 146 | end 147 | 148 | profile_set = bsxfun(@times,profile_set,... 149 | 20*(1+5*rand(1,1,N))./sqrt(sum(sum(profile_set.^2,1),2))); % Add variation in SNR 150 | 151 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 152 | %% Optional background components 153 | 154 | if sim_opts.nBG>0 155 | 156 | bg_dict = rand(T, sim_opts.nBG) > 0.8; % Initialize background time-course dictionary to a bunch of spikes 157 | bg_dict = bg_dict.*(1+2*rand(size(bg_dict))); % Modulate the event strengths 158 | bg_dict = filter(1,[1 0.9*sim_opts.poles],bg_dict); 159 | bg_dict = bg_dict(1:T,:); % Truncate to remove extra entries added by 'filter' 160 | 161 | profile_bg = zeros(M1,M2,sim_opts.nBG); 162 | gk_ext = 20; 163 | gk_var = 15; 164 | gk = exp(- bsxfun(@plus,vec(-gk_ext:gk_ext).^2,... 165 | (-gk_ext:gk_ext).^2)/(2*gk_var)); % Create kernel for background GP 166 | gk = 0.1*gk./norm(gk(:)); 167 | for kk = 1:sim_opts.nBG 168 | profile_bg(:,:,kk) = randn(size(profile_bg(:,:,kk))); 169 | profile_bg(:,:,kk) = abs(convn(profile_bg(:,:,kk), gk, 'same')); 170 | end 171 | profile_bg = bsxfun(@times,profile_bg,... 172 | 10./sqrt(sum(sum(profile_bg.^2,1),2))); % Add variation in SNR 173 | 174 | temp_dict = cat(2,temp_dict,bg_dict); 175 | profile_set = cat(3,profile_set,profile_bg); 176 | end 177 | 178 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 179 | %% Create data 180 | 181 | sim_cube = zeros(M1,M2,T); % Initialize data cube 182 | for kk = 1:M1 183 | for ll = 1:M2 184 | sim_cube(kk,ll,:) = temp_dict*vec(profile_set(kk,ll,:));% ... 185 | % + bg_dict*vec(profile_bg(kk,ll,:)); % Generate the full time-trace at each location in the image 186 | end 187 | end 188 | sim_cube = sim_cube + sqrt(sim_opts.noise_var)*randn(size(sim_cube)); % Add some noise 189 | 190 | end 191 | 192 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 193 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 194 | -------------------------------------------------------------------------------- /code/dictionary-learning/mintotol.m: -------------------------------------------------------------------------------- 1 | function [X, fX, i] = minimize(X, f, length, tol, P1, P2, P3, P4, P5, P6, P7); 2 | 3 | % Minimize a continuous differentialble multivariate function. Starting point 4 | % is given by "X" (D by 1), and the function named in the string "f", must 5 | % return a function value and a vector of partial derivatives. The Polack- 6 | % Ribiere flavour of conjugate gradients is used to compute search directions, 7 | % and a line search using quadratic and cubic polynomial approximations and the 8 | % Wolfe-Powell stopping criteria is used together with the slope ratio method 9 | % for guessing initial step sizes. Additionally a bunch of checks are made to 10 | % make sure that exploration is taking place and that extrapolation will not 11 | % be unboundedly large. The "length" gives the length of the run: if it is 12 | % positive, it gives the maximum number of line searches, if negative its 13 | % absolute gives the maximum allowed number of function evaluations. You can 14 | % (optionally) give "length" a second component, which will indicate the 15 | % reduction in function value to be expected in the first line-search (defaults 16 | % to 1.0). The function returns when either its length is up, or if no further 17 | % progress can be made (ie, we are at a minimum, or so close that due to 18 | % numerical problems, we cannot get any closer). If the function terminates 19 | % within a few iterations, it could be an indication that the function value 20 | % and derivatives are not consistent (ie, there may be a bug in the 21 | % implementation of your "f" function). The function returns the found 22 | % solution "X", a vector of function values "fX" indicating the progress made 23 | % and "i" the number of iterations (line searches or function evaluations, 24 | % depending on the sign of "length") used. 25 | % 26 | % Usage: [X, fX, i] = minimize(X, f, length, P1, P2, P3, P4, P5) 27 | % 28 | % See also: checkgrad 29 | % 30 | % Copyright (C) 2001 and 2002 by Carl Edward Rasmussen. Date 2002-02-13 31 | 32 | RHO = 0.01; % a bunch of constants for line searches 33 | SIG = 0.5; % RHO and SIG are the constants in the Wolfe-Powell conditions 34 | INT = 0.1; % don't reevaluate within 0.1 of the limit of the current bracket 35 | EXT = 3.0; % extrapolate maximum 3 times the current bracket 36 | MAX = 20; % max function evaluations per line search 37 | RATIO = 100; % maximum allowed slope ratio 38 | 39 | argstr = [f, '(X']; % compose string used to call function 40 | for i = 1:(nargin - 4) 41 | argstr = [argstr, ',P', int2str(i)]; 42 | end 43 | argstr = [argstr, ')']; 44 | 45 | if max(size(length)) == 2, red=length(2); length=length(1); else red=1; end 46 | if length>0, S=['Linesearch']; else S=['Function evaluation']; end 47 | 48 | i = 0; % zero the run length counter 49 | ls_failed = 0; % no previous line search has failed 50 | fX = []; 51 | [f1 df1] = eval(argstr); % get function value and gradient 52 | i = i + (length<0); % count epochs?! 53 | s = -df1; % search direction is steepest 54 | d1 = -s'*s; % this is the slope 55 | z1 = red/(1-d1); % initial step is red/(|s|+1) 56 | 57 | tol_done = 0; 58 | 59 | while ~tol_done % while not finished 60 | i = i + (length>0); % count iterations?! 61 | 62 | X0 = X; f0 = f1; df0 = df1; % make a copy of current values 63 | X = X + z1*s; % begin line search 64 | [f2 df2] = eval(argstr); 65 | i = i + (length<0); % count epochs?! 66 | d2 = df2'*s; 67 | f3 = f1; d3 = d1; z3 = -z1; % initialize point 3 equal to point 1 68 | if length>0, M = MAX; else M = min(MAX, -length-i); end 69 | success = 0; limit = -1; % initialize quanteties 70 | while 1 71 | while ((f2 > f1+z1*RHO*d1) | (d2 > -SIG*d1)) & (M > 0) 72 | limit = z1; % tighten the bracket 73 | if f2 > f1 74 | z2 = z3 - (0.5*d3*z3*z3)/(d3*z3+f2-f3); % quadratic fit 75 | else 76 | A = 6*(f2-f3)/z3+3*(d2+d3); % cubic fit 77 | B = 3*(f3-f2)-z3*(d3+2*d2); 78 | z2 = (sqrt(B*B-A*d2*z3*z3)-B)/A; % numerical error possible - ok! 79 | end 80 | if isnan(z2) | isinf(z2) 81 | z2 = z3/2; % if we had a numerical problem then bisect 82 | end 83 | z2 = max(min(z2, INT*z3),(1-INT)*z3); % don't accept too close to limits 84 | z1 = z1 + z2; % update the step 85 | X = X + z2*s; 86 | [f2 df2] = eval(argstr); 87 | M = M - 1; i = i + (length<0); % count epochs?! 88 | d2 = df2'*s; 89 | z3 = z3-z2; % z3 is now relative to the location of z2 90 | end 91 | if f2 > f1+z1*RHO*d1 | d2 > -SIG*d1 92 | break; % this is a failure 93 | elseif d2 > SIG*d1 94 | success = 1; break; % success 95 | elseif M == 0 96 | break; % failure 97 | end 98 | A = 6*(f2-f3)/z3+3*(d2+d3); % make cubic extrapolation 99 | B = 3*(f3-f2)-z3*(d3+2*d2); 100 | z2 = -d2*z3*z3/(B+sqrt(B*B-A*d2*z3*z3)); % num. error possible - ok! 101 | if ~isreal(z2) | isnan(z2) | isinf(z2) | z2 < 0 % num prob or wrong sign? 102 | if limit < -0.5 % if we have no upper limit 103 | z2 = z1 * (EXT-1); % the extrapolate the maximum amount 104 | else 105 | z2 = (limit-z1)/2; % otherwise bisect 106 | end 107 | elseif (limit > -0.5) & (z2+z1 > limit) % extraplation beyond max? 108 | z2 = (limit-z1)/2; % bisect 109 | elseif (limit < -0.5) & (z2+z1 > z1*EXT) % extrapolation beyond limit 110 | z2 = z1*(EXT-1.0); % set to extrapolation limit 111 | elseif z2 < -z3*INT 112 | z2 = -z3*INT; 113 | elseif (limit > -0.5) & (z2 < (limit-z1)*(1.0-INT)) % too close to limit? 114 | z2 = (limit-z1)*(1.0-INT); 115 | end 116 | f3 = f2; d3 = d2; z3 = -z2; % set point 3 equal to point 2 117 | z1 = z1 + z2; X = X + z2*s; % update current estimates 118 | [f2 df2] = eval(argstr); 119 | M = M - 1; i = i + (length<0); % count epochs?! 120 | d2 = df2'*s; 121 | end % end of line search 122 | 123 | if success % if line search succeeded 124 | f1 = f2; 125 | 126 | num_steps = max(size(fX)); 127 | if num_steps > 0 128 | last_fX = fX(num_steps); 129 | cur_step = (last_fX - f1) / last_fX; 130 | % fprintf('frac decrease %.8f obj %.4f\n',cur_step,f1); 131 | if cur_step < tol 132 | tol_done = 1; 133 | end 134 | end 135 | 136 | fX = [fX' f1]'; 137 | 138 | % fprintf('%s %6i; Value %4.6e\r', S, i, f1); 139 | s = (df2'*df2-df1'*df2)/(df1'*df1)*s - df2; % Polack-Ribiere direction 140 | tmp = df1; df1 = df2; df2 = tmp; % swap derivatives 141 | d2 = df1'*s; 142 | if d2 > 0 % new slope must be negative 143 | s = -df1; % otherwise use steepest direction 144 | d2 = -s'*s; 145 | end 146 | z1 = z1 * min(RATIO, d1/(d2-realmin)); % slope ratio but max RATIO 147 | d1 = d2; 148 | ls_failed = 0; % this line search did not fail 149 | else 150 | X = X0; f1 = f0; df1 = df0; % restore point from before failed line search 151 | if ls_failed | i > abs(length) % line search failed twice in a row 152 | break; % or we ran out of time, so we give up 153 | end 154 | tmp = df1; df1 = df2; df2 = tmp; % swap derivatives 155 | s = -df1; % try steepest 156 | d1 = -s'*s; 157 | z1 = 1/(1-d1); 158 | ls_failed = 1; % this line search failed 159 | end 160 | end 161 | %fprintf('\n'); 162 | 163 | --------------------------------------------------------------------------------