-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfcsparse.m
158 lines (135 loc) · 5.4 KB
/
fcsparse.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
function [datastruct metadata]= fcsparse(filename, varargin)
% FCSPARSE parses an FCS 3.0 file. It works on tube-mode and plate-mode
% (single-well) data files.
%
% Created 2012/07/12 JW
% Modified 20120714 BH, include expr_name in metadata for both LSRII and
% Stratedigm, update well_id extraction for LSRII. Still need to work
% on tube data for both machine
% Modified 20120906 JW does parameter translations for LSRII as well.
% Updated 20120914 BH solve LSRII plate_name bug
% Updated 20130212 BH solve problems to read LSRII temp files directly,
% due to unspecified Cytometer type, by adding optional input argument
% parse input
parser = inputParser;
addRequired(parser,'filename',@ischar);
addOptional(parser,'paramstokeep','all',@(x) isstruct(x) || ischar(x));
addParamValue(parser,'cytometer','',@ischar);
parse(parser, filename, varargin{:});
cytometer = parser.Results.cytometer;
paramstokeep = parser.Results.paramstokeep;
%
% read data
% filename
[data,paramVals,textHeader] = fcsread(filename);
% which instrument?
cytometer = textHeader{find(strcmp('$CYT',{textHeader{:,1}})),2};
if strcmpi(cytometer,'1400-8') || strcmpi(cytometer,'S1400EX')
translatefunc = @pstrat;
elseif strcmpi(cytometer,'LSRII')
translatefunc = @plsrii;
end
% process data for each parameter (i.e. fluorescence channel)
% works on both stratedigm and lsrii except where noted
datastruct = struct;
pnamelist = {paramVals.Name};
if ischar(paramstokeep)
% keyword mode
if strcmp(paramstokeep,'all')
% grab all parameters (DEFAULT)
for c=1:length(pnamelist)
parname = underscorify(pnamelist{c});
datastruct.(parname) = data(:,c);
end
elseif strcmp(paramstokeep,'common')
% grab only common channels and rename them
datastruct = grab_specific_params(data, pnamelist, translatefunc([],0));
elseif strcmp(paramstokeep,'rename')
% grab all channels but rename common ones
nameconversions = translatefunc([],1); % param names -> nicknames
for c=1:length(pnamelist)
parname = underscorify(pnamelist{c});
% use any default nicknames that are available
if isfield(nameconversions, parname) && ~isempty(nameconversions.(parname))
parname = nameconversions.(parname);
end
datastruct.(parname) = data(:,c);
end
end
elseif isstruct(paramstokeep)
% grab only wanted parameters and rename them
datastruct = grab_specific_params(data, pnamelist, paramstokeep);
else
error('PARAMSTOKEEP must be ''all'', ''common'', or a struct with flow cytometry parameter name conversions');
end
% process metadata
metadata = struct;
metadata.cytometer = cytometer;
% metadata common to stratedigm and LSRII
% works on both - verified 2012/07/14 JW
Date = textHeader{find(strcmp('$DATE',{textHeader{:,1}})),2};
BTim = textHeader{find(strcmp('$BTIM',{textHeader{:,1}})),2};
BTim_tmp = regexp(BTim, '^(\d{2}:\d{2}:\d{2})', 'tokens');
metadata.begin_time = datenum([Date, ' ', BTim_tmp{1}{1}]);
etim = textHeader{find(strcmp('$ETIM',{textHeader{:,1}})),2};
etim_tmp = regexp(etim, '^(\d{2}:\d{2}:\d{2})', 'tokens');
metadata.end_time = datenum([Date, ' ', etim_tmp{1}{1}]);
if strcmp(cytometer,'LSRII')
% LSRII-specific metadata
metadata.plate_name = find(strcmp('PLATE NAME',{textHeader{:,1}}));
% metadata.plate_name = textHeader{find(strcmp('PLATE NAME',{textHeader{:,1}})),2}; % Bo's version, not sure which one is better
% % this works but isn't useful
% plate_id_idx = find(strcmp('PLATE ID',{textHeader{:,1}}));
% if ~isempty(plate_id_idx)
% metadata.plate_id = textHeader{plate_id_idx,2};
% end
well_id_idx = find(strcmp('WELL ID',{textHeader{:,1}}));
if ~isempty(well_id_idx)
well_id = textHeader{well_id_idx,2};
metadata.row = well_id(1)-'A'+1;
metadata.col = str2num(well_id(2:end));
metadata.well_id = well_id;
end
else
% stratedigm-specific metadata
plate_id_idx = find(strcmp('PLATE_ID',{textHeader{:,1}}));
if ~isempty(plate_id_idx)
metadata.plate_id = textHeader{plate_id_idx,2};
end
Date_idx = find(strcmp('$DATE',{textHeader{:,1}}));
if ~isempty(Date_idx)
metadata.date = textHeader{Date_idx,2};
end
well_id_idx = find(strcmp('WELL_ID',{textHeader{:,1}}));
if ~isempty(well_id_idx)
well_id = textHeader{well_id_idx,2};
metadata.row = well_id(1)-'A'+1;
metadata.col = str2num(well_id(2:end));
metadata.well_id = well_id;
end
end
% expr_name
idx_expr_strat = find(strcmp('EXPERIMENT_NAME',{textHeader{:,1}}));
idx_expr_LSR = find(strcmp('EXPERIMENT NAME',{textHeader{:,1}}));
if ~isempty(idx_expr_LSR)
idx_expr = idx_expr_LSR;
metadata.expr_name = textHeader{idx_expr, 2};
elseif ~isempty(idx_expr_strat)
idx_expr = idx_expr_strat;
metadata.expr_name = textHeader{idx_expr, 2};
else
warning('no expr id identified')
metadata.expr_name = '';
end
% BTIM
BTIMIdx = find(cellfun(@(x) ~isempty(x), regexp(textHeader, 'BTIM')));
metadata.BTim = textHeader{BTIMIdx, 2};
% helper functions
function datastruct = grab_specific_params(data, pnamelist, paramstokeep)
for par = fieldnames(paramstokeep)'
par = par{1};
k = find(strcmp(paramstokeep.(par),pnamelist));
if ~isempty(k)
datastruct.(par) = data(:,k);
end
end