Skip to content

Commit

Permalink
added DataAnnotationSuggestion
Browse files Browse the repository at this point in the history
  • Loading branch information
avenix committed Dec 11, 2019
1 parent e004448 commit 130d62d
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 2 deletions.
36 changes: 36 additions & 0 deletions 1-Annotation/AnnotationApp.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
annotationSet;
eventAnnotationsPlotter;
rangeAnnotationsPlotter;
annotationSuggestionPlotter;

%markers
markers;
Expand Down Expand Up @@ -86,6 +87,9 @@
obj.rangeAnnotationsPlotter = AnnotationRangeAnnotationsPlotter(obj.labeling);
obj.rangeAnnotationsPlotter.delegate = obj;

obj.annotationSuggestionPlotter = AnnotationSuggestionPlotter(obj.labeling);
obj.annotationSuggestionPlotter.delegate = obj;

obj.loadUI();
end

Expand Down Expand Up @@ -586,11 +590,43 @@ function addCurrentRange(obj)
rangeAnnotation = RangeAnnotation(obj.rangeSelection.sample1,...
obj.rangeSelection.sample2,label);
obj.rangeAnnotationsPlotter.addAnnotation(obj.plotAxes, rangeAnnotation);

if obj.getSuggestAnnotations()
suggestedAnnotations = obj.generateAnnotationSuggestionsWithRange(rangeAnnotation);
obj.plotSuggestedAnnotations(suggestedAnnotations);
end
end
end

function suggestedAnnotations = generateAnnotationSuggestionsWithRange(obj,rangeAnnotation)
numColumns = obj.dataFile.numColumns;
templateData = obj.dataFile.rawDataForRowsAndColumns(rangeAnnotation.startSample,rangeAnnotation.endSample,1,numColumns);
nSamples = obj.dataFile.numRows;
rangeSize = rangeAnnotation.endSample - rangeAnnotation.startSample;

DTW_SIMILARITY_THRESHOLD = 100;
suggestedAnnotations = [];

for sample = rangeAnnotation.endSample : nSamples
windowData = obj.dataFile.rawDataForRowsAndColumns(sample,sample+rangeSize,1,numColumns);
dist = dtw(templateData,windowData);
if dist < DTW_SIMILARITY_THRESHOLD
suggestedAnnotations(end+1) = RangeAnnotation(sample,sample+rangeSize,rangeAnnotation.label);
end
end

end

function plotSuggestedAnnotations(obj,suggestedAnnotations)
annotationSuggestionPlotter.addAnnotations(suggestedAnnotations);
end

%% UI

function b = getSuggestAnnotations(obj)
b = obj.uiHandles.suggestAnnotationsCheckBox.Value;
end

function updateLoadDataTextbox(obj,~,~)
obj.uiHandles.loadDataTextbox.String = sprintf('data size:\n %d x %d',obj.dataFile.numRows,obj.dataFile.numColumns);
end
Expand Down
1 change: 0 additions & 1 deletion 1-Annotation/helper/AnnotationRangeAnnotationsPlotter.m
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ function deletePlotHandle(~,annotationHandle)
delete(annotationHandle.textSymbolUI);
end


function rectangleHandle = plotRectangle(obj,plotAxes,rangeAnnotation)
rectangleHeight = obj.rectanglesYRange(2) - obj.rectanglesYRange(1);

Expand Down
182 changes: 182 additions & 0 deletions 1-Annotation/helper/AnnotationSuggestionPlotter.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
classdef AnnotationSuggestionPlotter < handle

properties (Access = private,Constant)
AnnotationColor = [100,100,100] / 255;
kAnnotationLineWidth = 2;
FontSize = 20;

AnnotationLabelStairsCount = 10;
AnnotationLabelStairsYDiff = 0.05;
end

properties (Access = public)
delegate;
rectanglesYRange;
shouldShowAnnotations = true;
end

properties (Access = private)
annotationsMap;
labeling;
shouldPlotUpperYLabel = false;

currentAnnotationLabelStairs = 1;
end

methods
function set.shouldShowAnnotations(obj,visible)
obj.setAnnotationVisibility(visible);
obj.shouldShowAnnotations = visible;
end
end

methods (Access = public)
function obj = AnnotationRangeAnnotationsPlotter(labeling)
if nargin > 0
obj.labeling = labeling;
end
obj.initAnnotationsMap();
end

function addAnnotations(obj, plotAxes, rangeAnnotations)
for i = 1 : length(rangeAnnotations)
rangeAnnotation = rangeAnnotations(i);
obj.addAnnotation(plotAxes,rangeAnnotation);
end
obj.setAnnotationVisibility(obj.shouldShowAnnotations);
end

function addAnnotation(obj, plotAxes, rangeAnnotation)
%plot rectangle
rectangleHandle = obj.plotRectangle(plotAxes,rangeAnnotation);

%plot label
textHandle = obj.plotText(plotAxes,rangeAnnotation);

annotationHandle = AnnotationRangePlotHandle(rangeAnnotation,...
rectangleHandle,textHandle);

obj.annotationsMap(rangeAnnotation.startSample) = annotationHandle;
end

function didModifyAnnotation = modifyAnnotationToClass(obj,key,class)

didModifyAnnotation = false;

if isKey(obj.annotationsMap,key)

annotation = obj.annotationsMap(key);

if annotation.annotation.label ~= class
annotation.annotation.label = class;
annotation.textSymbolUI.String = obj.labeling.stringForClassAtIdx(class);

didModifyAnnotation = true;
end
end
end

function didDeleteAnnotation = deleteAnnotationAtSampleIdx(obj,startSample)

didDeleteAnnotation = false;

annotationKey = uint32(startSample);
if obj.annotationsMap.isKey(annotationKey)
plotHandle = obj.annotationsMap(annotationKey);
obj.deletePlotHandle(plotHandle);
obj.annotationsMap.remove(annotationKey);

didDeleteAnnotation = true;
end
end

function clearAnnotations(obj)

plotHandles = values(obj.annotationsMap);
for i = 1 : length(plotHandles)
plotHandle = plotHandles{i};
obj.deletePlotHandle(plotHandle);
end
remove(obj.annotationsMap, keys(obj.annotationsMap));
end

function annotationsArray = getAnnotations(obj)
annotationKeys = keys(obj.annotationsMap);
nAnnotations = length(annotationKeys);
annotationsArray = repmat(RangeAnnotation,1,nAnnotations);

for i = 1 : nAnnotations
key = annotationKeys{i};
annotationHandle = obj.annotationsMap(key);
annotationsArray(i) = annotationHandle.annotation;
end
end

function setAnnotationVisibility(obj,visible)
visibleStr = Helper.GetOnOffString(visible);
plotHandles = obj.annotationsMap.values;

for i = 1 : length(plotHandles)
plotHandle = plotHandles{i};
plotHandle.visible = visibleStr;
end
end

end

methods (Access = private)

function deletePlotHandle(~,annotationHandle)
delete(annotationHandle.rectangleUI);
delete(annotationHandle.textSymbolUI);
end

function rectangleHandle = plotRectangle(obj,plotAxes,rangeAnnotation)
rectangleHeight = obj.rectanglesYRange(2) - obj.rectanglesYRange(1);

rectangleWidth = single(rangeAnnotation.endSample - rangeAnnotation.startSample);

rectanglePosition = [single(rangeAnnotation.startSample), obj.rectanglesYRange(1),...
single(rectangleWidth), single(rectangleHeight)];

rectangleHandle = rectangle(plotAxes,'Position',rectanglePosition,'Curvature',...
[obj.RectangleCurvature obj.RectangleCurvature],'LineWidth',obj.kAnnotationLineWidth);
end

function textHandle = plotText(obj,plotAxes, rangeAnnotation )
classStr = obj.labeling.stringForClassAtIdx(rangeAnnotation.label);
xPosition = (double(rangeAnnotation.startSample) + double(rangeAnnotation.endSample)) / 2;

%compute y position
rectangleHeight = obj.rectanglesYRange(2) - obj.rectanglesYRange(1);
yPosition = obj.rectanglesYRange(1) + ...
obj.currentAnnotationLabelStairs * AnnotationEventAnnotationsPlotter.AnnotationLabelStairsYDiff * rectangleHeight;

%update label y position for next stair
obj.currentAnnotationLabelStairs = obj.currentAnnotationLabelStairs + 1;
if(obj.currentAnnotationLabelStairs > AnnotationEventAnnotationsPlotter.AnnotationLabelStairsCount)
obj.currentAnnotationLabelStairs = 1;
end

%plot text label
textHandle = text(plotAxes,xPosition,yPosition,classStr,...
'FontSize',obj.FontSize,'HorizontalAlignment','center');
set(textHandle, 'Clipping', 'on');
textHandle.Tag = int2str(rangeAnnotation.startSample);
textHandle.ButtonDownFcn = @obj.handleAnnotationClicked;
end

function handleAnnotationClicked(obj,source,target)
if ~isempty(obj.delegate)
obj.delegate.handleAnnotationClicked(source,target);
end
end

function initAnnotationsMap(obj)
rangeAnnotation = RangeAnnotation(uint32(1),uint32(1),uint8(1));
demoAnnotation = AnnotationRangePlotHandle(rangeAnnotation,1,1);
obj.annotationsMap = containers.Map(uint32(1),demoAnnotation);
remove(obj.annotationsMap,1);
end
end
end
Binary file modified 1-Annotation/ui/AnnotationUI.fig
Binary file not shown.
11 changes: 10 additions & 1 deletion 1-Annotation/ui/AnnotationUI.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

% Edit the above text to modify the response to help AnnotationUI

% Last Modified by GUIDE v2.5 29-Oct-2019 07:27:46
% Last Modified by GUIDE v2.5 11-Dec-2019 10:16:39

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
Expand Down Expand Up @@ -360,3 +360,12 @@ function currentSampleText_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in suggestAnnotationsCheckBox.
function suggestAnnotationsCheckBox_Callback(hObject, eventdata, handles)
% hObject handle to suggestAnnotationsCheckBox (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of suggestAnnotationsCheckBox
4 changes: 4 additions & 0 deletions ARC/data/DataFile.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,9 @@
function file = createFileWithColumnIndices(obj,columnIndices)
file = DataFile(obj.fileName,obj.data(:,columnIndices),obj.columnNames(columnIndices));
end

function rawData = rawDataForRowsAndColumns(obj,startRow,endRow,startColumn,endColumn)
rawData = obj.data(startRow:endRow,startColumn:endColumn);
end
end
end

0 comments on commit 130d62d

Please sign in to comment.