function varargout = MotionAnalyst3D_cal(varargin)
%MotionAnalyst3D_cal M-file for MotionAnalyst3D_cal.fig
% Author:	Robb Colbrunn, Cleveland Clinic BioRobotics and Mechanical Testing Core
% Date:		2-10-10
% Last change:  2-12-10
% Version:	1.2

%License
%     Copyright (C) 2010  Colbrunn
% 
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     any later version.
% 
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
% 
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.

%      MOTIONANALYST3D_cal, by itself, creates a new MOTIONANALYST3D_cal or raises the existing
%      singleton*.
%
%      H = MOTIONANALYST3D_cal returns the handle to a new MOTIONANALYST3D_cal or the handle to
%      the existing singleton*.
%
%      MOTIONANALYST3D_cal('Property','Value',...) creates a new MOTIONANALYST3D_cal using the
%      given property value pairs. Unrecognized properties are passed via
%      varargin to MotionAnalyst3D_cal_OpeningFcn.  This calling syntax produces a
%      warning when there is an existing singleton*.
%
%      MOTIONANALYST3D_cal('CALLBACK') and MOTIONANALYST3D_cal('CALLBACK',hObject,...) call the
%      local function named CALLBACK in MOTIONANALYST3D_cal.M with the given input
%      arguments.
%
%      *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 MotionAnalyst3D_cal

% Last Modified by GUIDE v2.5 25-Jan-2010 11:19:07

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @MotionAnalyst3D_cal_OpeningFcn, ...
                   'gui_OutputFcn',  @MotionAnalyst3D_cal_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 MotionAnalyst3D_cal is made visible.
function MotionAnalyst3D_cal_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   unrecognized PropertyName/PropertyValue pairs from the
%            command line (see VARARGIN)

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

% Update handles structure
guidata(hObject, handles);

%display icon
axes(handles.analysticon);
imshow('analyst.png');

%initialize tables
table(:,:,1) = [1 0 0];
table(:,:,2) = [1 0 0];
set(handles.mrktable1,'Data', table(:,:,1));
set(handles.mrktable2,'Data', table(:,:,2));

% create calibration device list
calpath = [cd '\*_cal.mat']; % search for all files with the proper _cal.mat extension
dir_info = dir(calpath);
number_of_files = length(dir_info); % count files
for i = 1:number_of_files
    name = regexprep(dir_info(i).name, '_cal.mat', ''); %remove _cal.mat from filename
    callist(i) = {name}; %build list
end
callist(i+1) = {'Custom'};%add custom option at end of list
set(handles.CalDevice, 'String', callist')%write filled array to control
caldevs = get(handles.CalDevice, 'String'); % get new calibration list
caldevnum = get(handles.CalDevice, 'Value');
caldev = char(caldevs(caldevnum));
CalFile = strcat(caldev, '_cal.mat');% open default file
load (CalFile);
set(handles.CalDevice, 'UserData', calpoints);
set(handles.units, 'String', units);
% UIWAIT makes MotionAnalyst3D_cal wait for user response (see UIRESUME)
% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = MotionAnalyst3D_cal_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;

function NumMarkers_Callback(hObject, eventdata, handles)
% hObject    handle to NumMarkers (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
table1 = get(handles.mrktable1,'Data');
table2 = get(handles.mrktable2,'Data');
numold = get(hObject,'UserData'); %old value stored in UserData
numstr = get(hObject, 'String');
numnew = str2double(numstr);
set(hObject,'UserData', numnew); %store new value as old value
%update table depending on new size.  Keep old values
% numcam = round(str2double(get(handles.NumCameras,'String')));
% for j=1:numcam
if numnew == numold
    return;
elseif numnew < numold
    for i = numnew+1:numold
        table1(numnew+1,:) = [];
        table2(numnew+1,:) = [];
    end
elseif numnew > numold
    for i = numold+1:numnew
        table1(i,:) = [i 0 0];
        table2(i,:) = [i 0 0];
    end
end

set(handles.mrktable1,'Data', table1);
set(handles.mrktable2,'Data', table2);
drawmrkrs(handles);

% --- Executes during object creation, after setting all properties.
function NumMarkers_CreateFcn(hObject, eventdata, handles)
% hObject    handle to NumMarkers (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');

end

function NumCameras_Callback(hObject, eventdata, handles)
% hObject    handle to NumCameras (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
drawmrkrs(handles);


% --- Executes during object creation, after setting all properties.
function NumCameras_CreateFcn(hObject, eventdata, handles)
% hObject    handle to NumCameras (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called
% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes during object creation, after setting all properties.
function analysticon_CreateFcn(hObject, eventdata, handles)
% hObject    handle to analysticon (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called
% Hint: place code in OpeningFcn to populate analysticon

% --------------------------------------------------------------------
function FileMenu_Callback(hObject, eventdata, handles)
% hObject    handle to FileMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --------------------------------------------------------------------
function OpenMenuItem_Callback(hObject, eventdata, handles)
% hObject    handle to OpenMenuItem (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --------------------------------------------------------------------
function PrintMenuItem_Callback(hObject, eventdata, handles)
% hObject    handle to PrintMenuItem (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --------------------------------------------------------------------
function CloseMenuItem_Callback(hObject, eventdata, handles)
% hObject    handle to CloseMenuItem (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

function path1_Callback(hObject, eventdata, handles)
% hObject    handle to path1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --- Executes during object creation, after setting all properties.
function path1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to path1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function path2_Callback(hObject, eventdata, handles)
% hObject    handle to path2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --- Executes during object creation, after setting all properties.
function path2_CreateFcn(hObject, eventdata, handles)
% hObject    handle to path2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in browsebutton2.
function browsebutton2_Callback(hObject, eventdata, handles)
% hObject    handle to browsebutton2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global filename datafolder;
[fname,pname] = uigetfile('*.*','Enter data file');
if (fname ~= 0)
pathname = sprintf('%s%s',pname,fname);
%filename = fname;
filename = pathname;  % remove later
datafolder = [pname '/'];
else
    return
end
axes(handles.axes2);
set(handles.axes2, 'Visible', 'on');
Imagraw = imread(pathname);
imagedims = size(Imagraw);
if max(size(size(Imagraw)))==2 % if it is greyscale (2 dimensional array)
    for i=1:3
    Imagraw = im2uint8(Imagraw);%ensure images are converted to 8-bit.
    Imagrgb(:,:,i) = Imagraw; %convert to rgb by making all colors the same
    end
elseif imagedims(3)==4 % if it contains alpha channel (4 dimensional array)
    Imagraw = im2uint8(Imagraw);%ensure images are converted to 8-bit.
    Imagraw(:,:,4) = []; %remove alpha channel
    Imagrgb = Imagraw; %convert to rgb by making all colors the same
else
    Imagrgb = Imagraw;
end
Imagesize = size(Imagrgb);
ImageProp = struct('Data', Imagrgb, 'Xdim', Imagesize(2), 'Ydim', Imagesize(1));
setappdata(handles.axes2, 'PropData', ImageProp);
imshow(pathname);
set(handles.path2,'TooltipString', pathname);
[pathstr, name, ext, versn] = fileparts(pathname);
set(handles.path2,'String', name);


% --- Executes on button press in browsebutton1.
function browsebutton1_Callback(hObject, eventdata, handles)
% hObject    handle to browsebutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global filename datafolder;
[fname,pname] = uigetfile('*.*','Enter data file');
if (fname ~= 0)
pathname = sprintf('%s%s',pname,fname);
%filename = fname;
filename = pathname;  % remove later
datafolder = [pname '/'];
else
    return
end
axes(handles.axes1);
set(handles.axes1, 'Visible', 'on');
Imagraw = imread(pathname);
imagedims = size(Imagraw);
if max(size(size(Imagraw)))==2 % if it is greyscale (2 dimensional array)
    for i=1:3
    Imagraw = im2uint8(Imagraw);%ensure images are converted to 8-bit.
    Imagrgb(:,:,i) = Imagraw; %convert to rgb by making all colors the same
    end
elseif imagedims(3)==4 % if it contains alpha channel (4 dimensional array)
    Imagraw = im2uint8(Imagraw);%ensure images are converted to 8-bit.
    Imagraw(:,:,4) = []; %remove alpha channel
    Imagrgb = Imagraw; %convert to rgb by making all colors the same
else
    Imagrgb = Imagraw;
end
Imagesize = size(Imagrgb);
ImageProp = struct('Data', Imagrgb, 'Xdim', Imagesize(2), 'Ydim', Imagesize(1));
setappdata(handles.axes1, 'PropData', ImageProp);
imshow(pathname);
set(handles.path1,'TooltipString', pathname);
[pathstr, name, ext, versn] = fileparts(pathname);
set(handles.path1,'String', name);



    %===========================================================
function [Imageout] = addxhairs(Image, cntrpnt, radius, colors)
% add cross hairs to an image

%find maximum size of image
Imagesize = size(Image);
Xmax = Imagesize(2);
Ymax = Imagesize(1);

Imageout = Image;%set out = in
if (cntrpnt(1)==0)||(cntrpnt(1)==0) % if marker locations have not been filled, don't draw
    return
end

for i = (-radius):radius
    Imageout(cntrpnt(2),bound(cntrpnt(1)+i, Xmax, 1),:) = colors; %draw x line.  bound to within image
end
for j = (-radius):radius
    Imageout(bound(cntrpnt(2)+j, Ymax, 1),cntrpnt(1),:) = colors; %draw y line
end

    %===========================================================
function addlabel(Image, cntrpnt, markernum, handles, cameranum)
% add marker labels to an image
if (cntrpnt(1)==0)||(cntrpnt(1)==0)
    return
end
%find maximum size of image
Imagesize = size(Image);
Xmax = Imagesize(2);
Ymax = Imagesize(1);

offset = 10; % offset location for label

if cameranum==1
    axes(handles.axes1);
    text('Position',[bound(cntrpnt(1)+offset,Xmax,1), bound(cntrpnt(2)+offset,Ymax,1)],'String', num2str(markernum), 'FontSize', 8, 'Color', 'Red')
elseif cameranum==2
    axes(handles.axes2);
    text('Position',[bound(cntrpnt(1)+offset,Xmax,1), bound(cntrpnt(2)+offset,Ymax,1)],'String', num2str(markernum), 'FontSize', 8, 'Color', 'Red')
end

    %===========================================================
function [Imageout] = drawmrkrs(handles)
% add cross hairs and circles to an image
Imageout(1) = getappdata(handles.axes1, 'PropData');
Imageout(2) = getappdata(handles.axes2, 'PropData');
%Imageout = Image;

table(:,:,1) = get(handles.mrktable1,'Data'); % get marker data from table1
table(:,:,2) = get(handles.mrktable2,'Data'); % get marker data from table2
tableSize = size(table);  % assume equal number of markers in each table
nummark = tableSize(1);

%set colors
xhaircolor = 255 * get(handles.MarkerColor,'BackgroundColor');

numcam = str2num(get(handles.NumCameras,'String'));
for j=1:numcam
    for i = 1:nummark
        Imageout(j).Data = addxhairs(Imageout(j).Data, [table(i,2,j),table(i,3,j)],5,xhaircolor);     
    end
    if j==1
    axes(handles.axes1);
    else
    axes(handles.axes2);
    end
    imshow(Imageout(j).Data);
for i = 1:nummark
        addlabel(Imageout(j).Data,[table(i,2,j),table(i,3,j)], i, handles, j);        
end
end

%===========================================================
function [data] = bound(data, uplim, lolim)
% add cross hairs and circles to an image
if data >= uplim
    data = uplim;
elseif data <= lolim
    data = lolim;
else
    data = data;
end
    

% --- Executes during object creation, after setting all properties.
function mrktable1_CreateFcn(hObject, eventdata, handles)
% hObject    handle to mrktable1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called


% --- Executes when selected cell(s) is changed in mrktable1.
function mrktable1_CellSelectionCallback(hObject, eventdata, handles)
% hObject    handle to mrktable1 (see GCBO)
% eventdata  structure with the following fields (see UITABLE)
%	Indices: row and column indices of the cell(s) currently selecteds
% handles    structure with handles and user data (see GUIDATA)
ImageProp = getappdata(handles.axes1, 'PropData');
sel = eventdata.Indices;
if (numel(sel) == 0)||(sel(2)~= 1)%only go on if first column is selected
    return
end
ActiveMarker = sel(1);
axes(handles.axes1);
%prompt to pick point
prompt = strcat('Select Marker #',num2str(ActiveMarker));
set(text(10,32,prompt), 'FontSize', 14, 'Color', 'Red')
[x,y] = ginput(1); % get marker location
if (x<0)||(y<0)||(x>ImageProp.Xdim)||(y>ImageProp.Ydim)%bound to be within figure limits
    return
end
table = get(hObject,'Data');
table(ActiveMarker,2) = round(x);
table(ActiveMarker,3) = round(y);
set(hObject,'Data', table);
Imageout = drawmrkrs(handles);

% --- Executes when entered data in editable cell(s) in mrktable1.
function mrktable1_CellEditCallback(hObject, eventdata, handles)
% hObject    handle to mrktable1 (see GCBO)
% eventdata  structure with the following fields (see UITABLE)
%	Indices: row and column indices of the cell(s) edited
%	PreviousData: previous data for the cell(s) edited
%	EditData: string(s) entered by the user
%	NewData: EditData or its converted form set on the Data property. Empty if Data was not changed
%	Error: error string when failed to convert EditData to appropriate value for Data
% handles    structure with handles and user data (see GUIDATA)
ImageProp = getappdata(handles.axes1, 'PropData');
sel = eventdata.Indices;
if (numel(sel) == 0)||(sel(2)== 1)%only go on if first column is not selected
    return
end
% check which column it is and cap the data at the image size
if sel(2)==2
    newval = bound(str2double(eventdata.EditData),ImageProp.Xdim,1);
elseif sel(2)==3
    newval = bound(str2double(eventdata.EditData),ImageProp.Ydim,1);
end
table = get(hObject,'Data');
table(sel(1),sel(2)) = newval;
set(hObject,'Data', table);

drawmrkrs(handles);


% --- Executes during object creation, after setting all properties.
function mrktable2_CreateFcn(hObject, eventdata, handles)
% hObject    handle to mrktable2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called


% --- Executes when selected cell(s) is changed in mrktable2.
function mrktable2_CellSelectionCallback(hObject, eventdata, handles)
% hObject    handle to mrktable2 (see GCBO)
% eventdata  structure with the following fields (see UITABLE)
%	Indices: row and column indices of the cell(s) currently selecteds
% handles    structure with handles and user data (see GUIDATA)
ImageProp = getappdata(handles.axes2, 'PropData');
sel = eventdata.Indices;
if (numel(sel) == 0)||(sel(2)~= 1)%only go on if first column is selected
    return
end
ActiveMarker = sel(1);
axes(handles.axes2);
%prompt to pick point
prompt = strcat('Select Marker #',num2str(ActiveMarker));
set(text(10,32,prompt), 'FontSize', 14, 'Color', 'Red')
[x,y] = ginput(1); % get marker location
if (x<0)||(y<0)||(x>ImageProp.Xdim)||(y>ImageProp.Ydim)%bound to be within figure limits
    return
end
table = get(hObject,'Data');
table(ActiveMarker,2) = round(x);
table(ActiveMarker,3) = round(y);
set(hObject,'Data', table);
Imageout = drawmrkrs(handles);


% --- Executes when entered data in editable cell(s) in mrktable2.
function mrktable2_CellEditCallback(hObject, eventdata, handles)
% hObject    handle to mrktable2 (see GCBO)
% eventdata  structure with the following fields (see UITABLE)
%	Indices: row and column indices of the cell(s) edited
%	PreviousData: previous data for the cell(s) edited
%	EditData: string(s) entered by the user
%	NewData: EditData or its converted form set on the Data property. Empty if Data was not changed
%	Error: error string when failed to convert EditData to appropriate value for Data
% handles    structure with handles and user data (see GUIDATA)
ImageProp = getappdata(handles.axes2, 'PropData');
sel = eventdata.Indices;
if (numel(sel) == 0)||(sel(2)== 1)%only go on if first column is not selected
    return
end
% check which column it is and cap the data at the image size
if sel(2)==2
    newval = bound(str2double(eventdata.EditData),ImageProp.Xdim,1);
elseif sel(2)==3
    newval = bound(str2double(eventdata.EditData),ImageProp.Ydim,1);
end
table = get(hObject,'Data');
table(sel(1),sel(2)) = newval;
set(hObject,'Data', table);

drawmrkrs(handles);


% --- Executes on button press in help.
function help_Callback(hObject, eventdata, handles)
% hObject    handle to help (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
open('MotionAnalyst3D_cal_help.pdf');


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

%get image data
Imageout1 = getappdata(handles.axes1, 'PropData');
Imageout2 = getappdata(handles.axes2, 'PropData');
Image1 = Imageout1.Data;
Image2 = Imageout2.Data;

%format marker positions to write to file
    table1 = get(handles.mrktable1,'Data');
    table2 = get(handles.mrktable2,'Data');
    for i=1:2
    data1(:,i) = table1(:,i+1);
    data2(:,i) = table2(:,i+1);
    end
    
[data1_out, data2_out] = cpselect(Image1,Image2,data1,data2,'Wait', true);

data1_out = round(data1_out);
data2_out = round(data2_out);
sizedata = size(data1_out);
nummarks=sizedata(1);
set(handles.NumMarkers,'String', num2str(nummarks));

    for i = 1:nummarks
        for j=1:2
            table1(i,1) = i;
            table1(i,j+1) = data1_out(i,j);
            table2(i,1) = i;
            table2(i,j+1) = data2_out(i,j);
        end
    end
    set(handles.mrktable1,'Data', table1);
    set(handles.mrktable2,'Data', table2);
    drawmrkrs(handles);

% --- Executes when user attempts to close figure1.
function figure1_CloseRequestFcn(hObject, eventdata, handles)
% hObject    handle to figure1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% Hint: delete(hObject) closes the figure
if isequal(get(hObject, 'waitstatus'), 'waiting')
    % The GUI is still in UIWAIT, use UIRESUME and return
    uiresume(hObject);
else
    % The GUI is no longer waiting, so destroy it now.
    delete(hObject);
end



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

%build path to coefficients file. Assume it is in same folder as camera 1 file
path = get(handles.path1,'TooltipString');
[pathstr, name, ext, versn] = fileparts(path);
coefpath = [pathstr '\*coefficients.mat'];
    
[fname,pname] = uiputfile(coefpath,'Enter Calibration File');
if (fname ~= 0)
filename = [pname '\' fname];
writedata(filename, handles);
end

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

%build path1 to cal file. Assume it is in same folder as camera 1 file
path = get(handles.path1,'TooltipString');
[pathstr, name, ext, versn] = fileparts(path);

    % Read cal file (*.mat)
    calpath = [pathstr '\*.mat'];
    [fname,pname] = uigetfile(calpath,'Select Calibration File');
    if (fname ~= 0)
        filepath = strcat(pname,fname);
        readdata(filepath, handles);
    end
    
     

% --- Executes on button press in MarkerColor.
function MarkerColor_Callback(hObject, eventdata, handles)
% hObject    handle to MarkerColor (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
color = uisetcolor;
set(hObject,'BackgroundColor',color);
ImageProp = getappdata(handles.axes1, 'PropData');
drawmrkrs(handles);

%===========================================================
function writedata(filename, handles)
	% write the data to the calibration file
    
    %get all data required for calibration file
    date = datestr(now);
    nummark = get(handles.NumMarkers, 'String');
    numcam = get(handles.NumCameras, 'String');
    caldevs = get(handles.CalDevice, 'String');
    caldevnum = get(handles.CalDevice, 'Value');
    caldev = caldevs(caldevnum);
    path1 = get(handles.path1, 'TooltipString');
    path2 = get(handles.path2, 'TooltipString');
    res1 = get(handles.Residual1,'String');
    res2 = get(handles.Residual2,'String');
    
    CoefFileHeader = {'Date/Time', datestr(now);
                    'Number of Markers', nummark;
                    'Number of Cameras', numcam;
                    'Calibration Device', caldev;
                    'Calibration Image 1', path1;
                    'Calibration Image 2', path2;
                    'Norm of Residuals - Cam 1', res1;
                    'Norm of Residuals - Cam 2', res2};
                
    %format marker positions to write to file
    Table_Cam1 = get(handles.mrktable1,'Data');
    Table_Cam2 = get(handles.mrktable2,'Data');
    
    %get calibration matrix and write to file
    CoefMatrix = get(handles.Calibrate,'UserData');
    %get units and write to file
    units = get(handles.units,'String');
    
    save(filename, 'CoefFileHeader', 'Table_Cam1', 'Table_Cam2', 'CoefMatrix', 'units');

%===========================================================
function readdata(filename, handles)
load(filename);
    
    %set variables
    set(handles.NumMarkers, 'String',CoefFileHeader{2,2});
    set(handles.NumCameras, 'String',CoefFileHeader{3,2});
  
    %determine which cal device was used and set value
    caldev = CoefFileHeader{4,2}; %get string from file
    caldevs = get(handles.CalDevice, 'String'); %get all possible devices
    numdevs = max(size(caldevs));
    TF = strcmp(caldev, caldevs);
    for i=1:numdevs
        if TF(i)==1
            set(handles.CalDevice, 'Value', i);
        end
    end
  
    set(handles.Residual1,'String', CoefFileHeader{7,2}); %this is the norm of residuals for cam 1
    set(handles.Residual2,'String', CoefFileHeader{8,2}); %this is the norm of residuals for cam 2
    
    %format marker positions to write to file
    set(handles.mrktable1,'Data', Table_Cam1);
    set(handles.mrktable2,'Data', Table_Cam2);

    %set calibration matrix
    set(handles.Calibrate,'UserData', CoefMatrix);
    
    %draw markers on image
    Imageout = drawmrkrs(handles);    
    
% --- Executes on selection change in CalDevice.
function CalDevice_Callback(hObject, eventdata, handles)
% hObject    handle to CalDevice (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% if Custom, ask user to load appropriate marker 3D reference file. Otherwise, load
% the file for the preset. At start of program, load the file for the
% default.
caldevs = get(handles.CalDevice, 'String');
caldevnum = get(handles.CalDevice, 'Value');
caldev = char(caldevs(caldevnum));
if strcmp(caldev,'Custom')
    % browse to file
    calpath = [pwd '\*.mat'];
    [fname,pname] = uigetfile(calpath,'Select Device Calibration File');
    if (fname ~= 0)
        CalFile = strcat(pname,fname);
    else
        return
    end
else
    CalFile = strcat(caldev, '_cal.mat');
end
%add try-catch loop in future to handle bogus files
load (CalFile);
set(handles.CalDevice, 'UserData', calpoints);
set(handles.units, 'String', units);



% --- Executes during object creation, after setting all properties.
function CalDevice_CreateFcn(hObject, eventdata, handles)
% hObject    handle to CalDevice (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


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

% get calibration matrix for selected device
DevCalMatrix = get(handles.CalDevice,'UserData');

%format marker positions
    table1 = get(handles.mrktable1,'Data');
    table2 = get(handles.mrktable2,'Data');
    for i=1:2 %remove marker indices
    data1(:,i) = table1(:,i+1);
    data2(:,i) = table2(:,i+1);
    end
    
[a1, res1] = dltfu(DevCalMatrix,data1); %these are the calibration coefficients for cam 1
[a2, res2] = dltfu(DevCalMatrix,data2); %these are the calibration coefficients for cam 2
CoefMatrix=[a1,a2]; %This is the combined calibration coefficients matrix
set(handles.Residual1,'String', num2str(res1)); %this is the norm of residuals for cam 1
set(handles.Residual2,'String', num2str(res2)); %this is the norm of residuals for cam 2
set(hObject,'UserData', CoefMatrix);%locally store calibration coefficients

%build path to coefficients file. Assume it is in same folder as camera 1 file
path = get(handles.path1,'TooltipString');
[pathstr, name, ext, versn] = fileparts(path);

coefpath = [pathstr '\*coefficients.mat'];

% select output file to write data to it.
[fname,pname] = uiputfile(coefpath,'Enter Camera Coefficients File');
if (fname ~= 0)
filename = [pname '\' fname];
writedata(filename, handles);
end
