/
combine_abf_data.m
executable file
·208 lines (172 loc) · 6.78 KB
/
combine_abf_data.m
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
function allData = combine_abf_data (abfPaths, varargin)
%% Combine data from many .abf files and return a structure
% Usage: allData = combine_abf_data (abfPaths, varargin)
% Explanation:
% TODO
% Note: Current and voltage vectors are identified using
% identify_channels.m by default. If it's already labelled
% correctly in the abf files, set 'UseOriginal' to be true.
%
% Example(s):
% [~, abfPaths] = all_files('Ext', 'abf', 'SortBy', 'date');
% allData = combine_abf_data(abfPaths, 'SaveMatFlag', false)
% combine_abf_data(abfPaths);
% combine_abf_data(abfPaths, 'UseOriginal', true);
% combine_abf_data(abfPaths, 'SaveSheetFlag', false);
%
% Outputs:
% allData - a structure with fields:
% siMs -
% vVecs - voltage vectors
% iVecs - current vectors
% phaseBoundaries -
% phaseStrs -
% specified as a scalar structure
%
% Arguments:
% abfPaths - full paths to abf files to combine
% must be a character vector, a string array
% or a cell array of character arrays
% varargin - 'SaveMatFlag': whether to save combined data as mat file
% must be numeric/logical 1 (true) or 0 (false)
% default == true
% - 'RegexpPhaseStr': phase string regular expression
% must be a string scalar or a character vector
% default == ''
% - Any other parameter-value pair for parse_all_abfs()
% or parse_abf()
%
% Requires:
% cd/argfun.m
% cd/combine_data_from_same_slice.m
% cd/compute_index_boundaries.m
% cd/count_A_each_C.m
% cd/count_samples.m
% cd/count_vectors.m
% cd/create_error_for_nargin.m
% cd/extract_fileparts.m
% cd/force_matrix.m
% cd/struct2arglist.m
%
% Used by:
% cd/combine_data_from_same_slice.m
% File History:
% 2019-08-23 Pulled from combine_data_from_same_slice.m
% 2019-08-23 Now passes unmatched optional arguments to parse_all_abfs
% TODO: 2020-01-04 Fixed the ordering of trace numbers
% TODO: Combine gVecs as well
%
%% Hard-coded parameters
%% Default values for optional arguments
saveMatFlagDefault = true; % save combined data by default
regexpPhaseStrDefault = ''; % no phase string regular expression by default
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Deal with arguments
% Check number of required arguments
if nargin < 1
error(create_error_for_nargin(mfilename));
end
% Set up Input Parser Scheme
iP = inputParser;
iP.FunctionName = mfilename;
iP.KeepUnmatched = true; % allow extraneous options
% Add required inputs to the Input Parser
addRequired(iP, 'abfPaths', ...
@(x) isempty(x) || ischar(x) || iscellstr(x) || isstring(x));
% Add parameter-value pairs to the Input Parser
addParameter(iP, 'SaveMatFlag', saveMatFlagDefault, ...
@(x) validateattributes(x, {'logical', 'numeric'}, {'binary'}));
addParameter(iP, 'RegexpPhaseStr', regexpPhaseStrDefault, ...
@(x) validateattributes(x, {'char', 'string'}, {'scalartext'}));
% Read from the Input Parser
parse(iP, abfPaths, varargin{:});
saveMatFlag = iP.Results.SaveMatFlag;
regexpPhaseStr = iP.Results.RegexpPhaseStr;
% Keep unmatched arguments for the parse_all_abfs() or parse_abf() function
otherArguments = struct2arglist(iP.Unmatched);
%% Preparation
% Extract file bases
allFileNames = extract_fileparts(abfPaths, 'name');
% Extract phase strings
if isempty(regexpPhaseStr)
allPhaseStrs = extract_fileparts(allFileNames, 'distinct', ...
'Delimiter', '_');
else
% Note: must pass in file names with the extension
% or else extract_fileparts() thinks they are directories
allPhaseStrs = extract_fileparts(allFileNames, 'base', ...
'RegExp', regexpPhaseStr);
end
% Get the unique phase strings in original order
phaseStrs = unique(allPhaseStrs, 'stable');
% Make sure it is a cell array
phaseStrs = force_column_cell(phaseStrs);
% Count the number of phases
nPhases = numel(phaseStrs);
%% Extract data to combine
% Parse all multi-unit recordings for this slice
[allParams, allAbfData] = ...
parse_all_abfs('FileNames', abfPaths, otherArguments{:});
% Extract parameters, then clear unused parameters
siMs = allParams.siMs;
clear allParams;
% Extract data, then clear unused data
vVecsAll = allAbfData.vVecs;
iVecsAll = allAbfData.iVecs;
clear allAbfData;
% Find the indices for each phase
indEachPhase = cellfun(@(x) find_in_strings(x, allFileNames), ...
phaseStrs, 'UniformOutput', false);
%% Order the data correctedly (may not be needed)
% Put them all together
sortOrder = vertcat(indEachPhase{:});
% Reorder data so that the order matches that of phaseStrs
[siMsSorted, vVecsSorted, iVecsSorted] = ...
argfun(@(x) x(sortOrder), siMs, vVecsAll, iVecsAll);
%% Combine the data
% Compute the new siMs
siMsSl = mean(siMsSorted);
% Check if all vectors have the same number of rows
% TODO
% Concatenate vectors
% TODO: Fix force_matrix.m to accept cell arrays of non-vectors with an
% optional argument
% [vVecsCombined, iVecsCombined] = argfun(@force_matrix, vVecsSorted, iVecsSorted);
[vVecsCombined, iVecsCombined] = ...
argfun(@(x) horzcat(x{:}), vVecsSorted, iVecsSorted);
%% Create phase boundaries
% Count the number of phase boundaries
nBoundaries = nPhases - 1;
% Compute phase boundaries
if nBoundaries == 0
phaseBoundaries = [];
else
% Count the number of sweeps in each file
nSweepsEachFile = cellfun(@count_vectors, vVecsSorted);
% Count the number of files for each phase
nFilesEachPhase = cellfun(@count_samples, indEachPhase);
% Count the number of sweeps in each phase
nSweepsEachPhase = count_A_each_C(nSweepsEachFile, nFilesEachPhase);
% Compute the phase boundaries
phaseBoundaries = compute_index_boundaries('NEachGroup', nSweepsEachPhase);
end
%% Output as a structure
allData.vVecs = vVecsCombined;
allData.siMs = siMsSl;
allData.iVecs = iVecsCombined;
allData.phaseBoundaries = phaseBoundaries;
allData.phaseStrs = phaseStrs;
%% Save to a matfile if requested
if saveMatFlag
% Create a matfile path
commonPrefix = extract_fileparts(abfPaths, 'commonprefix');
commonDir = extract_fileparts(abfPaths, 'commondirectory');
matPath = fullfile(commonDir, [commonPrefix, '.mat']);
% Save data for this slice
save(matPath, '-struct', 'allData');
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%{
OLD CODE:
%}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%