-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathFeaturesDetector.m
More file actions
166 lines (118 loc) · 5.48 KB
/
FeaturesDetector.m
File metadata and controls
166 lines (118 loc) · 5.48 KB
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
classdef FeaturesDetector < FeaturesReporter
properties
detectedTimeRanges; % An nx2 matrix of non-overlapping time ranges (start, end) in ascending order.
end
events
DetectedTimeRangesDidChange
end
methods(Static)
function n = typeName()
% Return a name for this type of detector.
n = 'Feature';
end
function initialize
% Perform any set up for all instances of this detector type.
end
function n = actionName()
n = 'Detecting features...';
end
end
methods
function obj = FeaturesDetector(controller, varargin)
obj = obj@FeaturesReporter(controller, varargin{:});
% Default the name of the reporter to the reporter type.
obj.name = obj.typeName();
obj.detectedTimeRanges = [];
end
function f = settingsFunc(obj)
% Return the function used to edit the settings of this detector.
% By default the function is determined from the name of the object's class by
% replacing 'Detector' with 'Settings', but this behavior can be overridden.
% Determine the function name from the class name.
settingsFuncName = class(obj);
if strcmp(settingsFuncName(end-7:end), 'Detector')
settingsFuncName = settingsFuncName(1:end-8);
end
settingsFuncName = [settingsFuncName 'Settings'];
% Return the function's handle.
f = str2func(settingsFuncName);
end
function sn = settingNames(obj) %#ok<MANU>
% Return the names of all settings.
sn = {};
end
function edited = editSettings(obj)
% Present a GUI to edit this detector's settings.
% Returns true if the settings were changed, false if the user cancelled.
% Pass this detector to the GUI.
settingsFunc = obj.settingsFunc();
try
edited = settingsFunc(obj);
catch ME
if strcmp(ME.identifier, 'MATLAB:UndefinedFunction')
edited = true;
else
rethrow(ME);
end
end
end
function showSettings(obj)
% Present a GUI to edit this detector's settings.
% Returns true if the settings were changed, false if the user cancelled.
% Pass this detector to the GUI.
settingsFunc = obj.settingsFunc();
try
settingsFunc(obj, 'Editable', false);
catch ME
if ~strcmp(ME.identifier, 'MATLAB:UndefinedFunction')
rethrow(ME);
end
end
end
function s = settings(obj)
% Return a structure containing all of the settings of this detector.
s = struct();
for setting = obj.settingNames()
s.(setting{1}) = obj.(setting{1});
end
end
function addFeaturesInTimeRange(obj, features, timeRange)
% Merge the new time range with the existing time ranges.
% The new range can intersect or completely replace existing ranges.
% TODO: this breaks if timeRange is entirely within obj.detectedTimeRanges
if isempty(obj.detectedTimeRanges)
obj.detectedTimeRanges = timeRange;
elseif timeRange(2) < obj.detectedTimeRanges(1, 1)
obj.detectedTimeRanges = vertcat(timeRange, obj.detectedTimeRanges);
elseif timeRange(1) > obj.detectedTimeRanges(end, 2)
obj.detectedTimeRanges = vertcat(obj.detectedTimeRanges, timeRange);
else
firstRange = find(obj.detectedTimeRanges(:,2) >= timeRange(1), 1, 'first');
lastRange = find(obj.detectedTimeRanges(:,1) < timeRange(2), 1, 'last');
if obj.detectedTimeRanges(firstRange, 1) < timeRange(1)
timeRange(1) = obj.detectedTimeRanges(firstRange, 1);
end
if obj.detectedTimeRanges(lastRange, 2) > timeRange(2)
timeRange(2) = obj.detectedTimeRanges(lastRange, 2);
end
if lastRange > firstRange
obj.detectedTimeRanges(firstRange+1:lastRange, :) = [];
end
obj.detectedTimeRanges(firstRange,:) = timeRange;
end
% Add the features after updating the time ranges so they get drawn correctly.
obj.addFeatures(features);
notify(obj, 'DetectedTimeRangesDidChange');
end
function removeFeaturesInTimeRange(obj, features, timeRange)
obj.removeFeatures(features);
% TODO: remove the time range from obj.detectedTimeRanges.
% may require truncating or splitting a range.
notify(obj, 'DetectedTimeRangesDidChange');
end
end
methods (Abstract)
% Subclasses must define this method.
features = detectFeatures(obj, timeRange)
end
end