Skip to content

Commit dd27212

Browse files
Merge pull request #30 from MATLAB-Community-Toolboxes-at-INCF/integrate-custom-datastore
Integrate custom datastore
2 parents c282d3d + 4ec9031 commit dd27212

10 files changed

+631
-0
lines changed

.gitattributes

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
*.fig binary
2+
*.mat binary
3+
*.mdl binary diff merge=mlAutoMerge
4+
*.mdlp binary
5+
*.mexa64 binary
6+
*.mexw64 binary
7+
*.mexmaci64 binary
8+
*.mlapp binary
9+
*.mldatx binary
10+
*.mlproj binary
11+
*.mlx binary
12+
*.p binary
13+
*.sfx binary
14+
*.sldd binary
15+
*.slreqx binary merge=mlAutoMerge
16+
*.slmx binary merge=mlAutoMerge
17+
*.sltx binary
18+
*.slxc binary
19+
*.slx binary merge=mlAutoMerge
20+
*.slxp binary
21+
22+
## Other common binary file types
23+
*.docx binary
24+
*.exe binary
25+
*.jpg binary
26+
*.pdf binary
27+
*.png binary
28+
*.xlsx binary

.gitignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Windows default autosave extension
2+
*.asv
3+
4+
# OSX / *nix default autosave extension
5+
*.m~
6+
7+
# Compiled MEX binaries (all platforms)
8+
*.mex*
9+
10+
# Packaged app and toolbox files
11+
*.mlappinstall
12+
*.mltbx
13+
14+
# Generated helpsearch folders
15+
helpsearch*/
16+
17+
# Simulink code generation folders
18+
slprj/
19+
sccprj/
20+
21+
# Matlab code generation folders
22+
codegen/
23+
24+
# Simulink autosave extension
25+
*.autosave
26+
27+
# Simulink cache files
28+
*.slxc
29+
30+
# Octave session info
31+
octave-workspace
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
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

Comments
 (0)