1
+ classdef DeepInterpolationDataStore < matlab .io .Datastore & ...
2
+ matlab .io .datastore .Subsettable & ...
3
+ matlab .io .datastore .Shuffleable
4
+ % DEEPINTERPOLATIONDATASTORE - custom datastore for DeepInterpolation-MATLAB
5
+ %
6
+ % This custom datastore provides flanking frames and the center frame
7
+ % upon one read.
8
+ %
9
+ % dids = DeepInterpolationDataStore(pathToTiffFile, options);
10
+ %
11
+ % Input must be full path to a grayscale, single channel tiff stack of
12
+ % >'flankingFrames + 2' frames in order to work (this is according to
13
+ % the function of the DeepInterpolation network).
14
+ %
15
+ % If the image frame dimensions differ from the network input size
16
+ % the doAutoResize option controls whether the frames will be
17
+ % automatically resized to outputFrameSize before they are returned.
18
+ %
19
+ % Dr. Thomas Künzel, The MathWorks, 2023
20
+
21
+
22
+ properties
23
+ fileName string
24
+ doAutoResize logical
25
+ numberOfFlankingFrames int32
26
+ outputFrameSize int32
27
+ frameCount double
28
+ dsSetCount double
29
+ setsAvailable double
30
+ currentSet double
31
+ setFramesStartIndex double
32
+ currentFrameIndex double
33
+ allSetFrameStartIndices double
34
+ end
35
+
36
+ methods % begin methods section
37
+ function myds = DeepInterpolationDataStore(filePath , options )
38
+ arguments
39
+ filePath
40
+ options = struct();
41
+ end
42
+ if isfield(options , ' doAutoResize' )
43
+ myds.doAutoResize = logical(options .doAutoResize );
44
+ else % default
45
+ myds.doAutoResize = false ;
46
+ end
47
+ if isfield(options , ' numberOfFlankingFrames' )
48
+ assert(options .numberOfFlankingFrames > 0 )
49
+ assert(rem(options .numberOfFlankingFrames , 2 ) == 0 , " Number of flanking frames should be even." )
50
+ myds.numberOfFlankingFrames = options .numberOfFlankingFrames ;
51
+ else % default
52
+ myds.numberOfFlankingFrames = 60 ;
53
+ end
54
+ if isfield(options , ' outputFrameSize' )
55
+ if not (myds .doAutoResize )
56
+ warning(' Specified an output frame size, but auto-resize is turned off.' )
57
+ end
58
+ outputFrameSize = options .outputFrameSize ;
59
+ if not (isnumeric(outputFrameSize ) && isequal(size(outputFrameSize ), [1 , 2 ]) && all(outputFrameSize >= 0 ))
60
+ error(' outputFrameSize should be an array with dimension 1x2 and non-negative values.' );
61
+ end
62
+ myds.outputFrameSize = outputFrameSize ;
63
+ else % default
64
+ myds.outputFrameSize = [512 , 512 ];
65
+ end
66
+ assert(isfile(filePath ));
67
+ myds.fileName = filePath ;
68
+ fileInfo = imfinfo(myds .fileName );
69
+ assert(strcmp(fileInfo(1 ).Format,' tif' ), " Must be tiff format" );
70
+ if ~myds .doAutoResize
71
+ assert((fileInfo(1 ).Width == myds .outputFrameSize(1 )) ...
72
+ && (fileInfo(1 ).Height == myds .outputFrameSize(2 )),...
73
+ " Actual frame size is not equal to specified outputFrameSize" );
74
+ end
75
+ framePerSetCount = myds .numberOfFlankingFrames + 3 ;
76
+ assert(numel(fileInfo ) >= framePerSetCount , " Not enough frames in stack for DeepInterpolation" );
77
+ myds.frameCount = numel(fileInfo );
78
+ myds.dsSetCount = myds .frameCount - framePerSetCount + 1 ;
79
+ myds.allSetFrameStartIndices = 1 : myds .dsSetCount ;
80
+ reset(myds );
81
+ end
82
+
83
+ function tf = hasdata(myds )
84
+ % Return true if more data is available.
85
+ tf = myds .setsAvailable > 0 ;
86
+ end
87
+
88
+ function [data ,info ] = read(myds )
89
+ % Read data and information about the extracted data.
90
+ assert(hasdata(myds ), " No more data to read" );
91
+ rawRefFrame = imread(myds .fileName ,myds .currentFrameIndex );
92
+ if myds .doAutoResize
93
+ rawRefFrame = imresize(rawRefFrame ,myds .outputFrameSize );
94
+ end
95
+ refFrame = single(rawRefFrame );
96
+ flankingFrames = single( ...
97
+ ones(myds .outputFrameSize(1 ), ...
98
+ myds .outputFrameSize(2 ), ...
99
+ myds .numberOfFlankingFrames ) ...
100
+ );
101
+ framecount = 1 ;
102
+ for leftFrame = 0 : (myds .numberOfFlankingFrames / 2 ) - 1
103
+ rawThisFrame = imread(myds .fileName ,myds .setFramesStartIndex + leftFrame );
104
+ if myds .doAutoResize
105
+ rawThisFrame = imresize(rawThisFrame ,myds .outputFrameSize );
106
+ end
107
+ thisFrame = single(rawThisFrame );
108
+ flankingFrames(: ,: ,framecount ) = thisFrame ;
109
+ framecount = framecount + 1 ;
110
+ end
111
+ % frame myds.numberOfFlankingFrames + 1 is center frame. One
112
+ % frame before and one after is left out.
113
+ startRightFrame = myds .numberOfFlankingFrames / 2 + 3 ;
114
+ for rightFrame = startRightFrame : startRightFrame + myds .numberOfFlankingFrames / 2 - 1
115
+ rawThisFrame = imread(myds .fileName ,myds .setFramesStartIndex + rightFrame );
116
+ if myds .doAutoResize
117
+ rawThisFrame = imresize(rawThisFrame ,myds .outputFrameSize );
118
+ end
119
+ thisFrame = single(rawThisFrame );
120
+ flankingFrames(: ,: ,framecount ) = thisFrame ;
121
+ framecount = framecount + 1 ;
122
+ end
123
+ data = {flankingFrames , refFrame };
124
+ info = " set=" + num2str(myds .currentSet ) + " /centerframe=" + num2str(myds .currentFrameIndex );
125
+ myds.currentSet = myds .currentSet + 1 ;
126
+ myds.setsAvailable = myds .setsAvailable - 1 ;
127
+ if myds .setsAvailable > 0
128
+ myds.setFramesStartIndex = myds .allSetFrameStartIndices(myds .currentSet );
129
+ myds.currentFrameIndex = myds .setFramesStartIndex + myds .numberOfFlankingFrames / 2 + 1 ;
130
+ else
131
+ myds.setFramesStartIndex = nan ;
132
+ myds.currentFrameIndex = nan ;
133
+ end
134
+ end
135
+
136
+ function reset(myds )
137
+ % Reset to the start of the data.
138
+ myds.setsAvailable = myds .dsSetCount ;
139
+ myds.currentSet = 1 ;
140
+ myds.setFramesStartIndex = myds .allSetFrameStartIndices(myds .currentSet );
141
+ myds.currentFrameIndex = myds .setFramesStartIndex + myds .numberOfFlankingFrames / 2 + 1 ;
142
+ end %
143
+
144
+ function shmyds = shuffle(myds )
145
+ % shmyds = shuffle(myds) shuffles the sets
146
+ % Create a copy of datastore
147
+ shmyds = copy(myds );
148
+
149
+ % Shuffle files and corresponding labels
150
+ numObservations = shmyds .dsSetCount ;
151
+ idx = randperm(numObservations );
152
+ shmyds.allSetFrameStartIndices = myds .allSetFrameStartIndices(idx );
153
+ reset(shmyds );
154
+ end
155
+ end
156
+
157
+ methods (Hidden = true )
158
+ function frac = progress(myds )
159
+ % Determine percentage of data read from datastore
160
+ if hasdata(myds )
161
+ frac = (myds .currentSet - 1 ) / myds .dsSetCount ;
162
+ else
163
+ frac = 1 ;
164
+ end
165
+ end
166
+ end
167
+
168
+ methods (Access = protected )
169
+ function subds = subsetByReadIndices(myds , indices )
170
+ subds = copy(myds );
171
+ subds.dsSetCount = numel(indices );
172
+ subds.allSetFrameStartIndices = myds .allSetFrameStartIndices(indices );
173
+ reset(subds );
174
+ end
175
+
176
+ function n = maxpartitions(myds )
177
+ n = myds .dsSetCount ;
178
+ end
179
+ end
180
+
181
+ end
0 commit comments