Revision 6aeb3593a5fd3ace9b0663d1bf0334decfb99835 authored by Sangyoon Han on 22 March 2021, 06:43:02 UTC, committed by GitHub on 22 March 2021, 06:43:02 UTC
1 parent 03cf15c
Raw File
trackingProcessGUI.m
function varargout = trackingProcessGUI(varargin)
% TRACKINGPROCESSGUI M-file for trackingProcessGUI.fig
%      TRACKINGPROCESSGUI, by itself, creates a new TRACKINGPROCESSGUI or raises the existing
%      singleton*.
%
%      H = TRACKINGPROCESSGUI returns the handle to a new TRACKINGPROCESSGUI or the handle to
%      the existing singleton*.
%
%      TRACKINGPROCESSGUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in TRACKINGPROCESSGUI.M with the given input arguments.
%
%      TRACKINGPROCESSGUI('Property','Value',...) creates a new TRACKINGPROCESSGUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before trackingProcessGUI_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to trackingProcessGUI_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

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

% Last Modified by GUIDE v2.5 05-Mar-2012 18:28:45

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @trackingProcessGUI_OpeningFcn, ...
                   'gui_OutputFcn',  @trackingProcessGUI_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before trackingProcessGUI is made visible.
function trackingProcessGUI_OpeningFcn(hObject, eventdata, handles, varargin)

processGUI_OpeningFcn(hObject, eventdata, handles, varargin{:},'initChannel',1);

% Parameter Setup
userData = get(handles.figure1, 'UserData');
if(isempty(userData)), userData = struct(); end;

funParams = userData.crtProc.funParams_;

set(handles.popupmenu_probDim,'String',{'2','3'},'UserData',[2 3],...
    'Value',find(funParams.probDim==[2 3]));
set(handles.checkbox_verbose, 'Value', funParams.verbose)

% gapCloseParam
set(handles.edit_maxgap, 'String', num2str(funParams.gapCloseParam.timeWindow - 1))
set(handles.edit_minlength, 'String', num2str(funParams.gapCloseParam.minTrackLen))
set(handles.checkbox_histogram, 'Value', funParams.gapCloseParam.diagnostics)

set(handles.checkbox_merging, 'Value',ismember(funParams.gapCloseParam.mergeSplit,[1 2]));
set(handles.checkbox_splitting, 'Value',ismember(funParams.gapCloseParam.mergeSplit,[1 3]));
    
% Set cost matrics
defaultLinkingCostMat = userData.crtProc.getDefaultLinkingCostMatrices(userData.MD,funParams.gapCloseParam.timeWindow);
defaultGapClosingCostMat = userData.crtProc.getDefaultGapClosingCostMatrices(userData.MD,funParams.gapCloseParam.timeWindow);
userData.cost_linking = {defaultLinkingCostMat.funcName};
userData.cost_gapclosing = {defaultGapClosingCostMat.funcName};
userData.fun_cost_linking = {defaultLinkingCostMat.GUI};
userData.fun_cost_gap = {defaultGapClosingCostMat.GUI};

% Retrieve index of default cost matrices
i1 = find(strcmp(funParams.costMatrices(1).funcName, userData.cost_linking));
i2 = find(strcmp(funParams.costMatrices(2).funcName, userData.cost_gapclosing));
assert(isscalar(i1) && isscalar(i2),'User-defined: the length of matching methods must be 1.')
nLinking=numel(defaultLinkingCostMat);
nGapClosing=numel(defaultGapClosingCostMat);
u1 = cell(1,nLinking);
u2 = cell(1,nGapClosing);
u1{i1} = funParams.costMatrices(1).parameters;
u2{i2} = funParams.costMatrices(2).parameters;
for i=setdiff(1:nLinking,i1), u1{i}=defaultLinkingCostMat(i).parameters; end
for i=setdiff(1:nGapClosing,i1), u2{i}=defaultGapClosingCostMat(i).parameters; end

set(handles.popupmenu_linking, 'Value', i1, 'UserData', u1,...
    'String',{defaultLinkingCostMat.name})
set(handles.popupmenu_gapclosing, 'Value', i2, 'UserData', u2,...
    'String',{defaultGapClosingCostMat.name})

% Kalman functions
userData.kalmanFunctions = TrackingProcess.getKalmanFunctions;
nKalmanFunctions = numel(userData.kalmanFunctions);
kalmanFields = {'reserveMem','initialize','calcGain','timeReverse'};

index=true(1,nKalmanFunctions);
for i=1:numel(kalmanFields)
    index=index & strcmp(funParams.kalmanFunctions.(kalmanFields{i}),...
        {userData.kalmanFunctions.(kalmanFields{i})});
end

assert(sum(index)==1, 'Did not find a unique Kalman set.');

u2 = cell(1,nKalmanFunctions);
u2{index} = funParams.costMatrices(1).parameters.kalmanInitParam;

set(handles.popupmenu_kalmanFunctions,'UserData',u2,...
    'String', {userData.kalmanFunctions.name}, 'Value', find(index))

set(handles.checkbox_export, 'Value', funParams.saveResults.export)

% Initialize children figure handles
userData.linkingFig=-1;
userData.gapclosingFig=-1;
userData.kalmanFig=-1;

% Choose default command line output for trackingProcessGUI
handles.output = hObject;

% Update user data and GUI data
set(hObject, 'UserData', userData);

uicontrol(handles.pushbutton_done);
guidata(hObject, handles);


% --- Outputs from this function are returned to the command line.
function varargout = trackingProcessGUI_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


% --- Executes on button press in pushbutton_done.
function pushbutton_done_Callback(hObject, eventdata, handles)

userData = get(handles.figure1, 'UserData');
if(isempty(userData)), userData = struct(); end;


% Check User Input
if isempty(get(handles.listbox_selectedChannels, 'String'))
    errordlg('Please select at least one input channel from ''Available Channels''.','Setting Error','modal')
    return;
end

props = get(handles.popupmenu_probDim, {'UserData','Value'});
probDim=props{1}(props{2});

timeWindow = str2double(get(handles.edit_maxgap, 'String'))+1;
if isnan(timeWindow) || timeWindow < 0 || floor(timeWindow) ~= ceil(timeWindow)
    errordlg('Please provide a valid value to parameter "Maximum Gap to Close".','Error','modal')
    return
end

minTrackLen = str2double(get(handles.edit_minlength, 'String'));
if isnan(minTrackLen) || minTrackLen < 0 || floor(minTrackLen) ~= ceil(minTrackLen)
    errordlg('Please provide a valid value to parameter "Minimum Length of Track Segment from First Step to use in Second Step".','Error','modal')
    return
end

% -------- Set parameter --------
channelIndex = get (handles.listbox_selectedChannels, 'Userdata');
funParams.ChannelIndex = channelIndex;

funParams.probDim = probDim;
funParams.verbose = get(handles.checkbox_verbose, 'Value');
funParams.gapCloseParam.timeWindow = timeWindow;
funParams.gapCloseParam.minTrackLen = minTrackLen;
funParams.gapCloseParam.diagnostics = get(handles.checkbox_histogram, 'Value');

if get(handles.checkbox_merging, 'Value') && get(handles.checkbox_splitting, 'Value')
    funParams.gapCloseParam.mergeSplit = 1;
elseif get(handles.checkbox_merging, 'Value') && ~get(handles.checkbox_splitting, 'Value')
    funParams.gapCloseParam.mergeSplit = 2;
elseif ~get(handles.checkbox_merging, 'Value') && get(handles.checkbox_splitting, 'Value')
    funParams.gapCloseParam.mergeSplit = 3;
elseif ~get(handles.checkbox_merging, 'Value') && ~get(handles.checkbox_splitting, 'Value')
    funParams.gapCloseParam.mergeSplit = 0;
end

funParams.saveResults.export = get(handles.checkbox_export, 'Value');

% Cost matrices
i_linking = get(handles.popupmenu_linking, 'Value');
i_gapclosing = get(handles.popupmenu_gapclosing, 'Value');

u_linking = get(handles.popupmenu_linking, 'UserData');
u_gapclosing = get(handles.popupmenu_gapclosing, 'UserData');

if isempty( u_linking{i_linking} )
    errordlg('Plese set up the selected cost function for "Step 1: frame-to-frame linking".','Error','modal')
end

if isempty( u_gapclosing{i_gapclosing} )
    errordlg('Plese set up the selected cost function for "Step 2: gap closing, mergin and splitting".','Error','modal')
end

funParams.costMatrices(1).funcName = userData.cost_linking{i_linking};
funParams.costMatrices(1).parameters = u_linking{i_linking};
funParams.costMatrices(2).funcName = userData.cost_gapclosing{i_gapclosing};
funParams.costMatrices(2).parameters = u_gapclosing{i_gapclosing};

% Get Kalman values
iKalman = get(handles.popupmenu_kalmanFunctions, 'Value');
kalmanFields = {'reserveMem','initialize','calcGain','timeReverse'};
for i=1:numel(kalmanFields)
    funParams.kalmanFunctions.(kalmanFields{i})=userData.kalmanFunctions(iKalman).(kalmanFields{i});
end
kalmanData = get(handles.popupmenu_kalmanFunctions, 'UserData');
funParams.costMatrices(1).parameters.kalmanInitParam = kalmanData{iKalman};

% Set up parameters effected by funParams.gapCloseParam.timeWindow
if isfield(funParams.costMatrices(2).parameters,'brownStdMult'),
    funParams.costMatrices(2).parameters.brownStdMult = funParams.costMatrices(2).parameters.brownStdMult(1) * ones(funParams.gapCloseParam.timeWindow,1);
end

if isfield(funParams.costMatrices(2).parameters,'linStdMult'),
    funParams.costMatrices(2).parameters.linStdMult = funParams.costMatrices(2).parameters.linStdMult(1) * ones(funParams.gapCloseParam.timeWindow,1);
end

processGUI_ApplyFcn(hObject,eventdata,handles,funParams)


% --- Executes on button press in pushbutton_cancel.
function pushbutton_cancel_Callback(hObject, eventdata, handles)
delete(handles.figure1);

% --- Executes on button press in pushbutton_set_linking.
function pushbutton_set_linking_Callback(hObject, eventdata, handles)
%       userData.linkingFig - the handle of setting panel for linking set-up
%       userData.gapclosingFig - the handle of setting panel for gap closing set-up
%       userData.kalmanFig

userData = get(handles.figure1, 'UserData');
if(isempty(userData)), userData = struct(); end;

parent = handles.popupmenu_linking;
procID = get(parent, 'Value');
if procID > length(userData.fun_cost_linking)
    warndlg('Please select a cost function for linking step.','Error','modal')
    return
else
    settingGUI = userData.fun_cost_linking{procID};
    userData.linkingFig = settingGUI(parent, procID);
end
set(handles.figure1, 'UserData', userData);

% --- Executes on button press in pushbutton_set_gapclosing.
function pushbutton_set_gapclosing_Callback(hObject, eventdata, handles)
%       userData.linkingFig - the handle of setting panel for linking set-up
%       userData.gapclosingFig - the handle of setting panel for gap closing set-up
%       userData.kalmanFig
userData = get(handles.figure1, 'UserData');
if(isempty(userData)), userData = struct(); end;

parent = handles.popupmenu_gapclosing;
procID = get(parent, 'Value');
if procID > length(userData.fun_cost_gap)
    warndlg('Please select a cost function for gap closing step.','Error','modal')
    return
else
    settingGUI = userData.fun_cost_gap{procID};
    userData.gapclosingFig = settingGUI(parent, procID);
end
set(handles.figure1, 'UserData', userData);



function edit_maxgap_Callback(hObject, eventdata, handles)

maxgap = str2double(get(handles.edit_maxgap, 'String'));
if isnan(maxgap) || maxgap < 0 || floor(maxgap) ~= ceil(maxgap)
    errordlg('Please provide a valid value to parameter "Maximum Gap to Close".','Warning','modal')
    return;
end

timeWindow = maxgap + 1; % Retrieve the new value for the time window

% Retrieve the parameters of the linking and gap closing matrices
u_linking = get(handles.popupmenu_linking, 'UserData');
linkingID = get(handles.popupmenu_linking, 'Value');
linkingParameters = u_linking{linkingID};
u_gapclosing = get(handles.popupmenu_gapclosing, 'UserData');
gapclosingID = get(handles.popupmenu_gapclosing, 'Value');
gapclosingParameters = u_gapclosing{gapclosingID};

% Check for changes
linkingnnWindowChange=(linkingParameters.nnWindow~=timeWindow);
gapclosingnnWindowChange=isfield(gapclosingParameters,'nnWindow') && (gapclosingParameters.nnWindow~=timeWindow);
gapclosingtimeReachConfBChange=isfield(gapclosingParameters,'timeReachConfB') && (gapclosingParameters.timeReachConfB~=timeWindow);
gapclosingtimeReachConfLChange=isfield(gapclosingParameters,'timeReachConfL') &&(gapclosingParameters.timeReachConfL~=timeWindow);

if ~linkingnnWindowChange && ~gapclosingnnWindowChange && ...
        ~gapclosingtimeReachConfBChange && ~gapclosingtimeReachConfLChange,
    return;
end
% Optional: asks the user if the time window value should be propagated
% to the linking and gap closing matrics
modifyParameters=questdlg('Do you want to propagate the changes in the maximum number of gaps to close?',...
    'Parameters update','Yes','No','Yes');
if ~strcmp(modifyParameters,'Yes'), return; end


% Set new linking time window
if linkingnnWindowChange, linkingParameters.nnWindow=timeWindow; end
u_linking{linkingID} = linkingParameters;
set(handles.popupmenu_linking, 'UserData', u_linking)

% Set new gap closing time window
if gapclosingnnWindowChange, gapclosingParameters.nnWindow=timeWindow; end
if gapclosingtimeReachConfBChange, gapclosingParameters.timeReachConfB=timeWindow; end
if gapclosingtimeReachConfLChange, gapclosingParameters.timeReachConfL=timeWindow; end
u_gapclosing{gapclosingID} = gapclosingParameters;
set(handles.popupmenu_gapclosing, 'UserData', u_gapclosing)
guidata(hObject,handles);


% --- Executes on button press in pushbutton_kalman_initialize.
function pushbutton_kalman_initialize_Callback(hObject, eventdata, handles)

userData = get(handles.figure1, 'UserData');
if(isempty(userData)), userData = struct(); end;

parent = handles.popupmenu_kalmanFunctions;
id = get(parent, 'Value');

settingGUI = userData.kalmanFunctions(id).initializeGUI;
userData.kalmanFig = settingGUI(parent, id);

set(handles.figure1, 'UserData', userData);

% --- Executes on key press with focus on figure1 and none of its controls.
function figure1_KeyPressFcn(hObject, eventdata, handles)

if strcmp(eventdata.Key, 'return')
    pushbutton_done_Callback(handles.pushbutton_done, [], handles);
end


% --- Executes during object deletion, before destroying properties.
function figure1_DeleteFcn(hObject, eventdata, handles)

userData = get(handles.figure1, 'UserData');
if(isempty(userData)), userData = struct(); end;

% Delete setting panels
if ishandle(userData.linkingFig), delete(userData.linkingFig);end
if ishandle(userData.gapclosingFig), delete(userData.gapclosingFig); end
if ishandle(userData.kalmanFig), delete(userData.kalmanFig); end


% --- Executes on button press in checkbox_export.
function checkbox_export_Callback(hObject, eventdata, handles)

if get(hObject,'Value')
    exportMsg=sprintf('The output matrices resulting from this process might be very large. Be cautious if you have large movies');
    if any([get(handles.checkbox_merging, 'Value') get(handles.checkbox_splitting, 'Value')])
        exportMsg =[exportMsg sprintf('\n \nAny merging and splitting information will be lost in the exported format.')];
    end
    warndlg(exportMsg,'Warning','modal')
end


% --- Executes when user attempts to close figure1.
function figure1_CloseRequestFcn(hObject, eventdata, handles)

delete(hObject);
back to top