Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] improve MEM performance #25

Open
wants to merge 49 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
c153b37
improve MNE solver
Edouard2laire Jul 24, 2024
aee123a
use scale 3 for nirs noise covariance
Edouard2laire Jul 25, 2024
83d47f9
disable noise covariance in MNE for now
Edouard2laire Jul 25, 2024
11d434b
keep all the power for nirs
Edouard2laire Jul 31, 2024
87e0bf2
Par-for optimization (#8)
Edouard2laire Aug 21, 2024
74767e9
MNE kernel (#9)
Edouard2laire Aug 21, 2024
fe22b41
small changes (#10)
Edouard2laire Aug 21, 2024
06104bf
don't transpose the inversion matrix
Edouard2laire Aug 21, 2024
9a50128
oups
Edouard2laire Aug 21, 2024
a9974ba
Move the normalization outside be_launch_mem
Edouard2laire Aug 21, 2024
6b66e33
Move the conversion to time-series outside be_launch_mem
Edouard2laire Oct 2, 2024
495be0b
minor changes
Edouard2laire Aug 22, 2024
ee42333
clean up output
Edouard2laire Aug 22, 2024
73ca08d
more clean-up on be_slice_obj
Edouard2laire Aug 23, 2024
a1a2807
Merge pull request #11 from Edouard2laire/be_free_energy
Edouard2laire Aug 23, 2024
654648b
save sigma_s under obj rather than option
Edouard2laire Oct 2, 2024
b9dae0c
pre-compute G * active_var
Edouard2laire Aug 26, 2024
8c470b4
some cleaning
Edouard2laire Aug 26, 2024
9db0652
Even more optim
Edouard2laire Aug 26, 2024
f852199
last changes
Edouard2laire Aug 26, 2024
6a8e3aa
fix call to be_fusion_of_modalities
Edouard2laire Oct 2, 2024
ac8778e
cleam up MNE code
Edouard2laire Oct 7, 2024
02c634f
Save wMEM results as factor decomposition
Edouard2laire Aug 27, 2024
dfccf7a
fix format of obj.data
Edouard2laire Oct 7, 2024
05e4e51
Merge pull request #15 from Edouard2laire/storage
Edouard2laire Oct 8, 2024
66ee9c9
[bugfix] Fix the covariance matrix along the cortical surface (#17)
Edouard2laire Oct 15, 2024
96240ab
update optimization function (#16)
Edouard2laire Oct 15, 2024
05c4145
Merge branch 'multifunkim:master' into wMEM-nirs2
Edouard2laire Oct 23, 2024
da4683c
[refactor] call be_fusion_of_modality in MNE
Edouard2laire Oct 28, 2024
14cbf86
[be_fusion_of_modality] also create the normalized data/gain
Edouard2laire Oct 28, 2024
56a1a61
Some refactor on MNE
Edouard2laire Oct 28, 2024
d00433d
continuation
Edouard2laire Oct 28, 2024
e2a295e
remove progress bar
Edouard2laire Oct 28, 2024
3321a57
several bugfixes
Edouard2laire Oct 28, 2024
b6a1d97
put back quasi-netwon for now
Edouard2laire Oct 28, 2024
b89b868
Improve code performance (#18)
Edouard2laire Oct 29, 2024
b95fa1e
Add option to use noise covariance in MNE. (default to false)
Edouard2laire Nov 1, 2024
3af7b4a
Refactor memstruct (#19)
Edouard2laire Nov 11, 2024
40b2b6e
also reduce cMEM file size if only a part of the signal is localized
Edouard2laire Nov 27, 2024
b20cbb9
Put back for loop (so much faster for nirs)
Edouard2laire Nov 27, 2024
36fb6b3
Add datatype to pipeline options
Edouard2laire Dec 4, 2024
cdc84ee
wavvelet_inverse_projection: use sparse matrix to avoid memory issue
Edouard2laire Dec 4, 2024
89a502a
remove extra message from be_slice_obj
Edouard2laire Dec 4, 2024
294b563
bugfix when using inactive variance
Edouard2laire Dec 4, 2024
1f6ac16
Add be_pagemtimes for backward compatibility
Edouard2laire Dec 6, 2024
7724734
officially replace be_free_energy
Edouard2laire Dec 6, 2024
9ae6076
Remove be_launch_mem2
Edouard2laire Dec 6, 2024
370214e
Apply comments
Edouard2laire Dec 7, 2024
58b8e63
FIx QR decomposition for matlab < 2022a
Edouard2laire Jan 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions best/cmem/clusters/be_scores2alpha.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,6 @@
ALPHA_METHOD = OPTIONS.model.alpha_method;
alpha_threshold = OPTIONS.model.alpha_threshold;


% Progress bar
hmem = [];
if numel(varargin)
hmem = varargin{1}(1);
st = varargin{1}(2);
dr = varargin{1}(3);
end

for jj=1:size(SCR,2)
clusters = CLS(:,jj);
scores = SCR(:,jj);
Expand Down Expand Up @@ -94,11 +85,6 @@
curr_cls = curr_cls + 1;
end

% update progress bar
if hmem
prg = round( (st + dr * (jj - 1 + ii/nb_clusters) / (size(SCR,2))) * 100 );
waitbar(prg/100, hmem, {[OPTIONS.automatic.InverseMethod, 'Step 1/2 : Running cortex parcellization ... ' num2str(prg) ' % done']});
end
end

end
Expand Down
11 changes: 5 additions & 6 deletions best/cmem/clusters/be_spatial_priorw.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function [OPTIONS, W] = be_spatial_priorw(OPTIONS, neighbors)
% This function returns the W Green matrix from which the local
% covariance matrices will be obtained.
% This function returns the W spatial filter matrix.
% The local covariance matrices can be obtained as C = W' * W
%
% INUPTS:
% - OPTIONS : structure of parameters
Expand Down Expand Up @@ -41,10 +41,10 @@
OPTIONS = Def_OPTIONS;
return
end

% Check field names of passed OPTIONS and fill missing ones with default values
OPTIONS = be_struct_copy_fields(OPTIONS, Def_OPTIONS, {'solver'}, 0);
clear Def_OPTIONS
%%

% Parameters:
nb_vertices = size(OPTIONS.automatic.Modality(1).gain,2);
rho = OPTIONS.solver.spatial_smoothing; % scalar that weight the adjacency matrix
Expand All @@ -66,6 +66,5 @@
A0 = rho/2*A0*A / (i+1);
end
W = W.*(W > exp(-8));
W = W'*W;

return
end
34 changes: 34 additions & 0 deletions best/cmem/preprocess/be_unormalize_and_units.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
function [obj, OPTIONS] = be_unormalize_and_units(obj, OPTIONS)
% be_unormalize_and_units: Un-normalize the result source map.
% Inverse function of be_normalize_and_units
% -------------------------------------------------------------------------
% Author: LATIS 2012
%
% ==============================================
% License
%
% BEst is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% BEst is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with BEst. If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------


if strcmp(OPTIONS.optional.normalization,'adaptive')
obj.ImageGridAmp = obj.ImageGridAmp/OPTIONS.automatic.Modality(1,1).ratioAmp;
else
obj.ImageGridAmp = obj.ImageGridAmp*OPTIONS.automatic.Modality(1).units_dipoles; %Modified by JSB August 17th 2015
end

OPTIONS.automatic.Modality(1).Jmne = OPTIONS.automatic.Modality(1).Jmne * OPTIONS.automatic.Modality(1).MNEAmp;


end
5 changes: 3 additions & 2 deletions best/cmem/solver/be_cmem_pipelineoptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@

% solver
DEF.solver.NoiseCov_method = 2;

DEF.solver.mne_use_noiseCov = 0;

% optional
DEF.optional.normalization = 'adaptive';

return
end
23 changes: 15 additions & 8 deletions best/cmem/solver/be_cmem_solver.m
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@
if OPTIONS.optional.verbose
fprintf('\n\n===== pipeline cMEM\n');
end
obj = struct('hfig', [] , 'hfigtab', [] );

obj = struct();
[obj.hfig, obj.hfigtab] = be_create_figure(OPTIONS);

%% Retrieve vertex connectivity - needed for clustering
[OPTIONS, obj.VertConn] = be_vertex_connectivity(HeadModel, OPTIONS);
Expand Down Expand Up @@ -154,8 +156,6 @@
% and the leadfields
[OPTIONS] = be_normalize_and_units(OPTIONS);



%% ===== Double precision to single ===== %%
% relax the double precision for the msp (leadfield and data)
[OPTIONS] = be_switch_precision( OPTIONS, 'single' );
Expand Down Expand Up @@ -184,6 +184,12 @@
%% ===== Solve the MEM ===== %%

[obj.ImageGridAmp, OPTIONS] = be_launch_mem(obj, OPTIONS);
if OPTIONS.optional.display
be_display_entropy_drops(obj,OPTIONS);
end

%% ===== Un-Normalization ===== %%
[obj, OPTIONS] = be_unormalize_and_units(obj, OPTIONS);


%% ===== Inverse temporal data window ===== %%
Expand All @@ -199,12 +205,13 @@
'minimum_norm',OPTIONS.automatic.Modality(1).Jmne, ...
'MSP',obj.SCR);

% Results (full temporal sequence)
% Results
Results = struct(...
'ImageGridAmp', obj.ImageGridAmp, ...
'ImagingKernel', [], ...
'MEMoptions', OPTIONS); % ...
%'MEMdata', obj);
'ImageGridAmp', [], ...
'ImagingKernel', [], ...
'nComponents', round( length(obj.iModS) / obj.nb_sources ), ...
'MEMoptions', OPTIONS);
Results.ImageGridAmp = obj.ImageGridAmp;

disp('Bye.')
end
Expand Down
1 change: 1 addition & 0 deletions best/main/be_main_call.m
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
% MEM solver
Def_OPTIONS.solver.NoiseCov = [];
Def_OPTIONS.solver.NoiseCov_method = [];
Def_OPTIONS.solver.mne_use_noiseCov = 0;
Def_OPTIONS.solver.NoiseCov_recompute = 1;
Def_OPTIONS.solver.spatial_smoothing = 0.6;
Def_OPTIONS.solver.active_var_mult = 0.05;
Expand Down
6 changes: 3 additions & 3 deletions best/main/be_main_clustering.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@
% rmem
switch OPTIONS.mandatory.pipeline
case 'cMEM'
[CLS, SCR, OPTIONS] = be_cmem_clusterize_multim(obj, OPTIONS); %TO DO: CHECK IF DATA SHOULD BE MINUS BSL OR NOT
[CLS, SCR, OPTIONS] = be_cmem_clusterize_multim(obj, OPTIONS);
[ALPHA, CLS, OPTIONS] = be_scores2alpha(SCR, CLS, OPTIONS);
case 'wMEM'
[CLS, SCR, OPTIONS] = be_wmem_clusterize_multim(obj, OPTIONS);

if OPTIONS.model.alpha_method ~= 6
if OPTIONS.model.alpha_method < 6
[ALPHA, CLS, OPTIONS] = be_scores2alpha(SCR, CLS, OPTIONS);
else % We compute the score using MNE
[ALPHA, CLS, OPTIONS] = be_gain2alpha(obj , CLS, OPTIONS);
[ALPHA, CLS, OPTIONS] = be_mne2alpha(obj , CLS, OPTIONS);
end

case 'rMEM'
Expand Down
2 changes: 1 addition & 1 deletion best/main/be_main_data_preprocessing.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
% ===== call of specific pre-processing depending on the pipeline:
switch OPTIONS.mandatory.pipeline

case 'cMEM' % === this is the standard MEM (Chowdhurry and Grova) =====
case {'cMEM','cMNE'} % === this is the standard MEM (Chowdhurry and Grova) =====
[noise_var] = covariance_processing(OPTIONS);
% we nomalize the cov of each modalities (we regularize the cov matrices)
for ii = 1 : numel( OPTIONS.automatic.Modality )
Expand Down
28 changes: 20 additions & 8 deletions best/mem/be_estimate_active_state.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,15 @@
xi_trans = xi';

% F0 is set to a dirac by default (omega=0).
if isempty(omega)
F0=0;
else
F0 = 0;
if ~isempty(omega)
F0 = 1/2 * xi_trans * omega * xi;
end
F1 = 1/2 * xi_trans * sigma * xi + xi_trans * mu;

F1 = 1/2 * xi_trans * sigma * xi;
if ~isempty(mu)
F1 = F1 + xi_trans * mu;
end

F = F0 - F1;

Expand All @@ -92,10 +95,19 @@


% Estimating amplitudes*
estimated_amp{ii} = estimated_alpha * mu + ...
((1 - estimated_alpha) * omega * xi) + ...
estimated_alpha * sigma * xi;
estimated_amp{ii} = estimated_alpha * sigma * xi;

if ~isempty(mu)
estimated_amp{ii} = estimated_amp{ii} + ...
estimated_alpha * mu;
end

if ~isempty(omega)
estimated_amp{ii} = estimated_amp{ii} + ...
((1 - estimated_alpha) * omega * xi);
end

end

return
end

Loading