|
| 1 | +function [frames, headers] = loadFramesBuff(tiff, firstIdx, lastIdx, stride, temp_file) |
| 2 | +%loadFrames Loads the frames of a Tiff file into an array (Y,X,T) |
| 3 | +% MOVIE = loadFrames(TIFF, [FIRST], [LAST], [STRIDE], []) loads |
| 4 | +% frames from the Tiff file specified by TIFF, which should be a filename |
| 5 | +% or an already open Tiff object. Optionallly FIRST, LAST and STRIDE |
| 6 | +% specify the range of frame indices to load. |
| 7 | + |
| 8 | +if nargin>4 && ~isempty(temp_file) |
| 9 | + if ~isequal(tiff, temp_file) % do not copy if already copied |
| 10 | + % in case copying fails (server hangs) |
| 11 | + iscopied = 0; |
| 12 | + firstfail = 1; |
| 13 | + while ~iscopied |
| 14 | + try |
| 15 | + copyfile(tiff,temp_file, 'f'); |
| 16 | + iscopied = 1; |
| 17 | + if ~firstfail |
| 18 | + fprintf(' succeeded!\n'); |
| 19 | + end |
| 20 | + catch |
| 21 | + if firstfail |
| 22 | + fprintf('copy tiff failed, retrying...'); |
| 23 | + end |
| 24 | + firstfail = 0; |
| 25 | + pause(10); |
| 26 | + end |
| 27 | + end |
| 28 | + tiff = temp_file; |
| 29 | + end |
| 30 | + info = imfinfo(temp_file); % get info after copying |
| 31 | + if isnan(lastIdx) |
| 32 | + lastIdx = length(info); % get number of frames |
| 33 | + end |
| 34 | +end |
| 35 | + |
| 36 | +% initChars = overfprintf(0, 'Loading TIFF frame '); |
| 37 | +warning('off', 'MATLAB:imagesci:tiffmexutils:libtiffWarning'); |
| 38 | + |
| 39 | +warningsBackOn = onCleanup(... |
| 40 | + @() warning('on', 'MATLAB:imagesci:tiffmexutils:libtiffWarning')); |
| 41 | + |
| 42 | +if ischar(tiff) |
| 43 | + tiff = Tiff(tiff, 'r'); |
| 44 | + closeTiff = onCleanup(@() close(tiff)); |
| 45 | +end |
| 46 | + |
| 47 | +if nargin < 2 || isempty(firstIdx) |
| 48 | + firstIdx = 1; |
| 49 | +end |
| 50 | + |
| 51 | +if nargin < 3 || isempty(lastIdx) |
| 52 | + lastIdx = nFramesTiff(tiff); |
| 53 | +end |
| 54 | + |
| 55 | +if nargin < 4 || isempty(stride) |
| 56 | + stride = 1; |
| 57 | +end |
| 58 | + |
| 59 | +if nargout > 1 |
| 60 | + loadHeaders = true; |
| 61 | +else |
| 62 | + loadHeaders = false; |
| 63 | +end |
| 64 | + |
| 65 | +if true %nargin <=4 %if the file was not copied locally use Tiff library |
| 66 | + w = tiff.getTag('ImageWidth'); |
| 67 | + h = tiff.getTag('ImageLength'); |
| 68 | + dataClass = class(read(tiff)); |
| 69 | + nFrames = ceil((lastIdx - firstIdx + 1)/stride); |
| 70 | + frames = zeros(h, w, nFrames, dataClass); |
| 71 | + if loadHeaders |
| 72 | + headers = cell(1, nFrames); |
| 73 | + end |
| 74 | + |
| 75 | + nMsgChars = 0; |
| 76 | + setDirectory(tiff, firstIdx); |
| 77 | + for t = 1:nFrames |
| 78 | + if mod(t, 100) == 0 |
| 79 | + %nMsgChars = overfprintf(nMsgChars, '%i/%i', t, nFrames); |
| 80 | + end |
| 81 | + |
| 82 | + |
| 83 | + frames(:,:,t) = read(tiff); |
| 84 | + |
| 85 | + if loadHeaders |
| 86 | + headerNames = tiff.getTagNames; |
| 87 | + headers{t} = getTag(tiff, 'ImageDescription'); |
| 88 | + try |
| 89 | + headers{t} = [headers{t} getTag(tiff,'Software')]; |
| 90 | + catch |
| 91 | + end |
| 92 | + end |
| 93 | + |
| 94 | + if t < nFrames |
| 95 | + for i = 1:stride |
| 96 | + nextDirectory(tiff); |
| 97 | + end |
| 98 | + end |
| 99 | + end |
| 100 | + %overfprintf(initChars + nMsgChars, ''); |
| 101 | +else % if the file is local (and on SSD) this way of reading works much faster |
| 102 | + info = imfinfo(temp_file); |
| 103 | + offset = info(1).Offset; |
| 104 | + w = info(1).Width; |
| 105 | + h = info(1).Height; |
| 106 | + dataClass = 'int16'; % this is true for our ScanImage recordings, |
| 107 | + % it is possible to use info.BitDepth to try and figure out nBytesPerSample |
| 108 | + |
| 109 | + % MK: using memmapfile here, but just reading as a binary file might be |
| 110 | + % faster, worth trying |
| 111 | + m = memmapfile(temp_file, 'Format', dataClass, 'Offset', offset); |
| 112 | + data = m.Data; |
| 113 | +% clear m; |
| 114 | + nPixels = w*h; |
| 115 | + frameIdx = firstIdx:stride:lastIdx; |
| 116 | + data = reshape(data, [], length(info)); |
| 117 | + nSamples = size(data, 1); % number of values in each frame related vector |
| 118 | + % the images are the last nPixels values of this vector |
| 119 | + % here we assume all the headers occupy the same number of bytes, |
| 120 | + % this is true for ScanImage recordings. info.Offset is a useful field |
| 121 | + % otherwise. |
| 122 | + frames = data(nSamples-nPixels+1:nSamples, frameIdx); |
| 123 | + frames = reshape(frames, w, h, []); |
| 124 | + frames = permute(frames, [2 1 3]); |
| 125 | + if loadHeaders |
| 126 | + headers = {info(frameIdx).ImageDescription}; |
| 127 | + end |
| 128 | +end |
| 129 | + |
| 130 | + |
| 131 | +end |
| 132 | + |
| 133 | + |
| 134 | +%% |
| 135 | +% |
| 136 | +% figure |
| 137 | +% for i=1:3:nFrames |
| 138 | +% subplot(1, 3, 1) |
| 139 | +% imagesc(frames(:,:,i)); |
| 140 | +% subplot(1, 3, 2); |
| 141 | +% imagesc(data(:,:,i)); |
| 142 | +% subplot(1, 3, 3); |
| 143 | +% imagesc(frames(:,:,i)-data(:,:,i)); |
| 144 | +% drawnow; |
| 145 | +% end |
| 146 | + |
0 commit comments