-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsmoothCalciumSignals.m
More file actions
72 lines (59 loc) · 3.07 KB
/
smoothCalciumSignals.m
File metadata and controls
72 lines (59 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
function [smooth_signal] = smoothCalciumSignals(signal_information,n)
%% Function that smooths the normalized fluorescent signals
% GOAL: Achieve a 2-minute smoothed output if possible (or whatever time
% the user sets for their f_end in ProcessNeuroCa.m
%
% INPUTS:
% fdata = dF/F matrix generated by NeuroCa (suggest running
% "ProcessNeuroCa.m" prior to running this function)
%
% f_end = variable calculated in f_end to ensure a standard signal window of 120 seconds
% (created using "ProcessNeuroCa.m")
%
% OUTPUT:
% smooth_signal = filtered dF/F signal for every detected cell in the network
% (This matrix may contain both active and inactive cells.
% To distinguish between signals and noise, run "findCalciumSpikes.m")
%% EXTRACT RELEVANT VARIABLES FROM STRUCTURE
fdata = signal_information.fdata;
f_end_target = signal_information.analysis_window_frames; % Target frame number, already capped by available frames in ProcessNeuroCa
if isempty(fdata) || f_end_target == 0
warning('smoothCalciumSignals: Input fdata is empty or analysis window has 0 frames. Returning empty.');
smooth_signal = [];
return;
end
%% CONFIGURE EXPONENTIALLY WEIGHTED MOVING FILTER
% "n" influences alpha and the lag. It is set in the Preprocessing Settings App.
alpha = 2 / (n + 1); % lower value = smoother signal
lag = round((n - 1) / 2); % amount to shift the filtered signal
if lag < 0, lag = 0; end
%% DETERMINE INPUT AND OUTPUT SIZES
% In this revised logic, we always filter the segment up to f_end_target,
% as ProcessNeuroCa has already ensured this is a valid number of frames.
% The segment of the signal we will filter is from frame 1 to f_end_target.
input_segment_to_filter = fdata(:, 1:f_end_target); % <-- THIS IS THE PRIMARY FIX.
% Check if the signal is long enough to produce a non-empty output after removing the lag.
if f_end_target <= lag
warning('Signal timelapse (length: %d frames) is not long enough to be smoothed with the current lag (%d frames). Returning empty.', f_end_target, lag);
smooth_signal = [];
return;
end
% The final smoothed signal will have the lag frames removed from the beginning.
num_output_cols = f_end_target - lag;
num_cells = size(fdata, 1);
%% RUN FILTER FOR EACH CELL
smooth_signal = zeros(num_cells, num_output_cols); % Pre-allocate output matrix
for cell_idx = 1:num_cells
% Apply the exponentially-weighted moving avarage filter
smoothed_with_lag = filter(alpha, [1, alpha - 1], input_segment_to_filter(cell_idx, :));
% Check for unexpected filter output (e.g., all NaNs)
if all(isnan(smoothed_with_lag))
warning('Filter produced all NaNs for cell %d. The output for this cell will be zeros.', cell_idx);
% The pre-allocated zeros will remain for this cell.
continue;
end
% Shift the filtered segment to account for the lag and assign to the output matrix.
% The right side will now have num_output_cols (f_end_target - lag) columns, matching the left side.
smooth_signal(cell_idx, :) = smoothed_with_lag(1, (lag + 1):end);
end
end