forked from dscho/fiji
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bfopen.m
289 lines (266 loc) · 9.8 KB
/
bfopen.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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
function [result] = bfopen(id)
% A script for opening microscopy images in MATLAB using Bio-Formats.
%
% The function returns a list of image series; i.e., a cell array of cell
% arrays of (matrix, label) pairs, with each matrix representing a single
% image plane, and each inner list of matrices representing an image
% series. See below for examples of usage.
%
% Portions of this code were adapted from:
% http://www.mathworks.com/support/solutions/en/data/1-2WPAYR/
%
% This method is ~1.5x-2.5x slower than Bio-Formats's command line
% showinf tool (MATLAB 7.0.4.365 R14 SP2 vs. java 1.6.0_20),
% due to overhead from copying arrays.
%
% Thanks to all who offered suggestions and improvements:
% * Ville Rantanen
% * Brett Shoelson
% * Martin Offterdinger
% * Tony Collins
% * Cris Luengo
% * Arnon Lieber
% * Jimmy Fong
%
% NB: Internet Explorer sometimes erroneously renames the Bio-Formats library
% to loci_tools.zip. If this happens, rename it back to loci_tools.jar.
%
% Here are some examples of accessing data using the bfopen function:
%
% % read the data using Bio-Formats
% data = bfopen('C:/data/experiment.lif');
%
% % unwrap some specific image planes from the result
% numSeries = size(data, 1);
% series1 = data{1, 1};
% series2 = data{2, 1};
% series3 = data{3, 1};
% metadataList = data{1, 2};
% % ...etc.
% series1_numPlanes = size(series1, 1);
% series1_plane1 = series1{1, 1};
% series1_label1 = series1{1, 2};
% series1_plane2 = series1{2, 1};
% series1_label2 = series1{2, 2};
% series1_plane3 = series1{3, 1};
% series1_label3 = series1{3, 2};
% % ...etc.
%
% % plot the 1st series's 1st image plane in a new figure
% series1_colorMaps = data{1, 3};
% figure('Name', series1_label1);
% if isempty(series1_colorMaps{1})
% colormap(gray);
% else
% colormap(series1_colorMaps{1});
% end
% imagesc(series1_plane1);
%
% % Or if you have the image processing toolbox, you could use:
% % imshow(series1_plane1, []);
%
% % Or animate as a movie (assumes 8-bit unsigned data)
% v = linspace(0, 1, 256)';
% cmap = [v v v];
% for p = 1:series1_numPlanes
% M(p) = im2frame(uint8(series1{p, 1}), cmap);
% end
% movie(M);
%
% % Query some metadata fields (keys are format-dependent)
% subject = metadataList.get('Subject');
% title = metadataList.get('Title');
% -- Configuration - customize this section to your liking --
% Toggle the autoloadBioFormats flag to control automatic loading
% of the Bio-Formats library using the javaaddpath command.
%
% For static loading, you can add the library to MATLAB's class path:
% 1. Type "edit classpath.txt" at the MATLAB prompt.
% 2. Go to the end of the file, and add the path to your JAR file
% (e.g., C:/Program Files/MATLAB/work/loci_tools.jar).
% 3. Save the file and restart MATLAB.
%
% There are advantages to using the static approach over javaaddpath:
% 1. If you use bfopen within a loop, it saves on overhead
% to avoid calling the javaaddpath command repeatedly.
% 2. Calling 'javaaddpath' may erase certain global parameters.
autoloadBioFormats = 1;
% Toggle the stitchFiles flag to control grouping of similarly
% named files into a single dataset based on file numbering.
stitchFiles = 0;
% To work with compressed Evotec Flex, fill in your LuraWave license code.
%lurawaveLicense = 'xxxxxx-xxxxxxx';
% -- Main function - no need to edit anything past this point --
% load the Bio-Formats library into the MATLAB environment
if autoloadBioFormats
path = fullfile(fileparts(mfilename('fullpath')), '../plugins/loci_tools.jar');
javaaddpath(path);
end
% set LuraWave license code, if available
if exist('../jars/lurawaveLicense')
path = fullfile(fileparts(mfilename('fullpath')), '../jars/lwf_jsdk2.6.jar');
javaaddpath(path);
java.lang.System.setProperty('lurawave.license', fullfile(fileparts(mfilename('fullpath')), '../jars/lurawaveLicense'));
end
% check MATLAB version, since typecast function requires MATLAB 7.1+
canTypecast = versionCheck(version, 7, 1);
% check Bio-Formats version, since makeDataArray2D function requires trunk
bioFormatsVersion = char(loci.formats.FormatTools.VERSION);
isBioFormatsTrunk = versionCheck(bioFormatsVersion, 5, 0);
% initialize logging
loci.common.DebugTools.enableLogging('INFO');
r = loci.formats.ChannelFiller();
r = loci.formats.ChannelSeparator(r);
if stitchFiles
r = loci.formats.FileStitcher(r);
end
tic
r.setMetadataStore(loci.formats.MetadataTools.createOMEXMLMetadata());
r.setId(id);
numSeries = r.getSeriesCount();
result = cell(numSeries, 2);
for s = 1:numSeries
fprintf('Reading series #%d', s);
r.setSeries(s - 1);
width = r.getSizeX();
height = r.getSizeY();
pixelType = r.getPixelType();
bpp = loci.formats.FormatTools.getBytesPerPixel(pixelType);
fp = loci.formats.FormatTools.isFloatingPoint(pixelType);
sgn = loci.formats.FormatTools.isSigned(pixelType);
bppMax = power(2, bpp * 8);
little = r.isLittleEndian();
numImages = r.getImageCount();
imageList = cell(numImages, 2);
colorMaps = cell(numImages);
for i = 1:numImages
if mod(i, 72) == 1
fprintf('\n ');
end
fprintf('.');
plane = r.openBytes(i - 1);
% retrieve color map data
if bpp == 1
colorMaps{s, i} = r.get8BitLookupTable()';
else
colorMaps{s, i} = r.get16BitLookupTable()';
end
if ~isempty(colorMaps{s, i})
newMap = colorMaps{s, i};
m = newMap(row, col) < 0;
newMap(m) = newMap(m) + bppMax;
colorMaps{s, i} = newMap / (bppMax - 1);
end
% convert byte array to MATLAB image
if isBioFormatsTrunk && (sgn || ~canTypecast)
% can get the data directly to a matrix
arr = loci.common.DataTools.makeDataArray2D(plane, ...
bpp, fp, little, height);
else
% get the data as a vector, either because makeDataArray2D
% is not available, or we need a vector for typecast
arr = loci.common.DataTools.makeDataArray(plane, ...
bpp, fp, little);
end
% Java does not have explicitly unsigned data types;
% hence, we must inform MATLAB when the data is unsigned
if ~sgn
if canTypecast
% TYPECAST requires at least MATLAB 7.1
% NB: arr will always be a vector here
switch class(arr)
case 'int8'
arr = typecast(arr, 'uint8');
case 'int16'
arr = typecast(arr, 'uint16');
case 'int32'
arr = typecast(arr, 'uint32');
case 'int64'
arr = typecast(arr, 'uint64');
end
else
% adjust apparent negative values to actual positive ones
% NB: arr might be either a vector or a matrix here
mask = arr < 0;
adjusted = arr(mask) + bppMax / 2;
switch class(arr)
case 'int8'
arr = uint8(arr);
adjusted = uint8(adjusted);
case 'int16'
arr = uint16(arr);
adjusted = uint16(adjusted);
case 'int32'
arr = uint32(arr);
adjusted = uint32(adjusted);
case 'int64'
arr = uint64(arr);
adjusted = uint64(adjusted);
end
adjusted = adjusted + bppMax / 2;
arr(mask) = adjusted;
end
end
if isvector(arr)
% convert results from vector to matrix
shape = [width height];
arr = reshape(arr, shape)';
end
% build an informative title for our figure
label = id;
if numSeries > 1
qs = int2str(s);
label = [label, '; series ', qs, '/', int2str(numSeries)];
end
if numImages > 1
qi = int2str(i);
label = [label, '; plane ', qi, '/', int2str(numImages)];
if r.isOrderCertain()
lz = 'Z';
lc = 'C';
lt = 'T';
else
lz = 'Z?';
lc = 'C?';
lt = 'T?';
end
zct = r.getZCTCoords(i - 1);
sizeZ = r.getSizeZ();
if sizeZ > 1
qz = int2str(zct(1) + 1);
label = [label, '; ', lz, '=', qz, '/', int2str(sizeZ)];
end
sizeC = r.getSizeC();
if sizeC > 1
qc = int2str(zct(2) + 1);
label = [label, '; ', lc, '=', qc, '/', int2str(sizeC)];
end
sizeT = r.getSizeT();
if sizeT > 1
qt = int2str(zct(3) + 1);
label = [label, '; ', lt, '=', qt, '/', int2str(sizeT)];
end
end
% save image plane and label into the list
imageList{i, 1} = arr;
imageList{i, 2} = label;
end
% extract metadata table for this series
metadataList = r.getMetadata();
% save images and metadata into our master series list
result{s, 1} = imageList;
result{s, 2} = metadataList;
result{s, 3} = colorMaps;
result{s, 4} = r.getMetadataStore();
fprintf('\n');
end
r.close();
toc
% -- Helper functions --
function [result] = versionCheck(v, maj, min)
tokens = regexp(v, '[^\d]*(\d+)[^\d]+(\d+).*', 'tokens');
majToken = tokens{1}(1);
minToken = tokens{1}(2);
major = str2num(majToken{1});
minor = str2num(minToken{1});
result = major > maj || (major == maj && minor >= min);