I’ve run into a few different artefacts that are both spread across sensors, ideal for cleaning with SSP or ICA, but also very limited in frequency, such that they could be removed with a notch filter. Instead of having to choose between these approaches, each removing different parts of the signal we’d like to keep, it would be best to clean with both simultaneously, only subtracting a filtered version of a component from the component topography. As a simple example (but not the artefacts I mentioned), this could be applied to clean line noise. This is different from the current process that uses a given frequency band only to find the component, but still removes it unfiltered.
First question: is there a way to do this currently in Brainstorm?
Second: It should be fairly easy to “hack” this into the code: we simply need to filter the component time series just before it gets subtracted. But it’s not obvious where to put this in the Brainstorm GUI and workflow, since the actual cleaning usually happens “later” when importing the data, not when finding or selecting the components. And in practice one would want to filter only specific components, possibly multiple with different filters. So I’d like to hear your thoughts on how we could do this.
If I understand you correctly, you want to apply some narrow-band bandpass filters to the components, then project out these filtered components from the signal, and I have several thoughts on this.
1. Maybe we can firstly bandpass filter the raw signal, then use the filtered data to compute SSP or ICA, and remove the components form the raw, unfiltered data. Brainstorm provides bandpass filter choice both on the SSP and ICA panels. However, this filter data→SSP/ICA→remove components procedure is slightly different than the SSP/ICA→filter components→remove components procedure. It may not remove the noise satisfactorily.
2. You may be looking for the place to add the code to filter the SSP/ICA components. I happened to check out the code the other day. Maybe we can add a few lines in process_ssp2.m at these spots:
% Apply component selection (if set explicitly)
if ~isempty(SelectComp)
proj.CompMask(SelectComp) = 1;
end
% Compute IC
if isempty(Y)
Y = W * F; % maybe we can filter the ICA components here?
end
% Compute mixing matrix
if diff(size(W)) == 0
M = inv(W);
else
M = pinv(W);
end
and for SSP:
%% ===== COMPUTE PROJECTOR =====
function proj = Compute(F, chanmask)
% SVD decomposition
[U,S,V] = svd(F, 'econ'); % maybe we can filter the SSP components here?
% Create projector structure
proj = db_template('projector');
% Keep all the dimensions
nChannel = length(chanmask);
nProj = size(U,2);
proj.Components = zeros(nChannel, nProj);
proj.Components(chanmask == 1,:) = U;
% Other fields
proj.SingVal = diag(S)';
proj.CompMask = zeros(1,nProj);
proj.Status = 1;
end
But I’m not sure about that, since I’m not familiar with the computations.
3. Sounds like the other multivariable mode decomposition methods are really effective at noise removal, such as memd or mvmd method. These methods can be used to process multi-channel data and decompose it into narrow band Intrinsic Mode Function (IMF), just remove the IMF which contains the narrow-band noise and reconstruct the data.
I’m still not clear on how we could do that currently in Brainstorm: the third step: “remove the components from the raw unfiltered data”. First we’d need to save the component we want to remove. One way I can think of (maybe there’s an easier way?): after filtering, we would use the process to apply the projectors, selecting every other component to keep only the component we want to remove. But then we’d still need to subtract that from the raw unfiltered data. I don’t think there’s a process to directly subract two raw “studies”, right?
Note that it would be relatively easy with exporting things to Matlab or scripting, but this first question is whether it’s currently doable in Brainstorm.
My second question was rather about how we could design this feature into Brainstorm’s GUI and workflow. As I said, it would be relatively easy to edit the code to do it for myself.
In terms of GUI, I guess the easiest way would be to add a separate “apply projectors - filtered” process, where one could 1. review the selected projectors and 2. select a filter to apply to the subtracted component. I still expect it would require some modification of other related files to “bring” the filter parameters all the way to where the actual projection happens, but I haven’t looked at the code yet. I first wanted to pick the brains of the rest of the team. Maybe others have done this or thought about it before.