# FTrack

## PURPOSE

FTRACK

## SYNOPSIS

function varargout = FTrack(varargin)

## DESCRIPTION

     FTRACK
     For all your fly-tracking needs! . See documentation for usage details.

## CROSS-REFERENCE INFORMATION

This function calls:

- CleanData CLEANDATA
- FlyTracker FLYTRACKER
- fit_ellipse
- close VR=CLOSE(VR)
- getframe FRAME=GETFRAME(VR)
- getinfo INFO=GETINFO(VR)
- seek WORKED=SEEK(VR,FNUM)
- videoReader videoReader class constructor
- close VW=CLOSE(VW)
- getinfo INFO=GETINFO(VW)
- close VR=CLOSE(VR)
- getframe FRAME=GETFRAME(VR)
- getinfo INFO=GETINFO(VR)
- seek WORKED=SEEK(VR,FNUM)
- videoReader videoReader class constructor
- close VW=CLOSE(VW)
- getinfo INFO=GETINFO(VW)
- close VR=CLOSE(VR)
- getframe FRAME=GETFRAME(VR)
- getinfo INFO=GETINFO(VR)
- seek WORKED=SEEK(VR,FNUM)
- videoReader videoReader class constructor
- close VW=CLOSE(VW)
- getinfo INFO=GETINFO(VW)

This function is called by:

## SUBFUNCTIONS

- function FTrack_OpeningFcn(hObject, eventdata, handles, varargin)
- function varargout = FTrack_OutputFcn(hObject, eventdata, handles)
- function load_video_Callback(hObject, eventdata, handles)
- function viewframe_Callback(hObject, eventdata, handles)
- function arena_dims_Callback(hObject, eventdata, handles)
- function input_params_Callback(hObject, eventdata, handles)
- function find_opt_CreateFcn(hObject, eventdata, handles)
- function find_opt_SelectionChangeFcn(hObject, eventdata, handles)
- function neg_opt_CreateFcn(hObject, eventdata, handles)
- function neg_opt_SelectionChangeFcn(hObject, eventdata, handles)
- function TrackStart_Callback(hObject, eventdata, handles)
- function view_traj_Callback(hObject, eventdata, handles)
- function clean_x_Callback(hObject, eventdata, handles)
- function clean_y_Callback(hObject, eventdata, handles)
- function out = SaveFiles(i,handles)
- function tilt_correct_Callback(hObject, eventdata, handles)

## SOURCE CODE

    0001 function varargout = FTrack(varargin)
    0002 % FTRACK
    0003 % For all your fly-tracking needs! . See documentation for usage details.
    0004
    0005 % Last Modified by GUIDE v2.5 26-Nov-2007 18:07:29
    0006
    0007 % Begin initialization code - DO NOT EDIT
    0008 gui_Singleton = 1;
    0009 gui_State = struct('gui_Name',       mfilename, ...
    0010                    'gui_Singleton',  gui_Singleton, ...
    0011                    'gui_OpeningFcn', @FTrack_OpeningFcn, ...
    0012                    'gui_OutputFcn',  @FTrack_OutputFcn, ...
    0013                    'gui_LayoutFcn',  [] , ...
    0014                    'gui_Callback',   []);
    0015 if nargin && ischar(varargin{1})
    0016     gui_State.gui_Callback = str2func(varargin{1});
    0017 end
    0018
    0019 if nargout
    0020     [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
    0021 else
    0022     gui_mainfcn(gui_State, varargin{:});
    0023 end
    0024 % End initialization code - DO NOT EDIT
    0025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0026
    0027 % --- Executes just before FTrack is made visible.
    0028 function FTrack_OpeningFcn(hObject, eventdata, handles, varargin)
    0029 % This function has no output args, see OutputFcn.
    0030 % hObject    handle to figure
    0031 % eventdata  reserved - to be defined in a future version of MATLAB
    0032 % handles    structure with handles and user data (see GUIDATA)
    0033 % varargin   command line arguments to FTrack (see VARARGIN)
    0034
    0035 % Choose default command line output for FTrack
    0036 handles.output = hObject;
    0037
    0038 % Update handles structure
    0039 guidata(hObject, handles);
    0040 disp('Welcome to FTrack!')
    0041 warning off all
    0042
    0043 % UIWAIT makes FTrack wait for user response (see UIRESUME)
    0044 % uiwait(handles.figure1);
    0045
    0046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0047
    0048 % --- Outputs from this function are returned to the command line.
    0049 function varargout = FTrack_OutputFcn(hObject, eventdata, handles)
    0050 % varargout  cell array for returning output args (see VARARGOUT);
    0051 % hObject    handle to figure
    0052 % eventdata  reserved - to be defined in a future version of MATLAB
    0053 % handles    structure with handles and user data (see GUIDATA)
    0054
    0055 % Get default command line output from handles structure
    0056 varargout{1} = handles.output;
    0057
    0058 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0059 % --- Executes on button press in load_video.
    0060 function load_video_Callback(hObject, eventdata, handles)
    0061 % hObject    handle to load_video (see GCBO)
    0062 % eventdata  reserved - to be defined in a future version of MATLAB
    0063 % handles    structure with handles and user data (see GUIDATA
    0064
    0065
    0066 %The following allows the user to select multiple videos to be tracked.
    0067 %The videos will be tracked sequentially, not in parallel. The filenames
    0068 %will be displayed in the message center.
    0069
    0070 [filename, pathname] = uigetfile({'*.avi;*.mpg;*.mp2','Video Files (*.avi,*.mpg,*.mp2)'}, 'Pick a video', 'MultiSelect','on');
    0071 if iscell(filename)
    0072     NFiles = length(filename);
    0073 else
    0074     NFiles = 1;
    0075     filename = {filename};
    0076 end
    0077
    0078 if isequal(filename,0) || isequal(pathname,0)
    0079     disp('File select canceled')
    0080 else
    0081     for i = 1:NFiles
    0082         disp(['Video selected: ', fullfile(pathname, filename{i})])
    0083         handles.filename{i} = fullfile(pathname, filename{i});
    0084     end
    0085 end
    0086
    0087 guidata(gcbo,handles);
    0088
    0089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0090
    0091 % --- Executes on button press in viewframe.
    0092 function viewframe_Callback(hObject, eventdata, handles)
    0093 % hObject    handle to viewframe (see GCBO)
    0094 % eventdata  reserved - to be defined in a future version of MATLAB
    0095 % handles    structure with handles and user data (see GUIDATA)
    0096
    0097 %This is the single frame viewer.  It simply gives the user some info about
    0098 %the video (displayed in the message center), and also shows the user a
    0099 %single frame of the movie so that they can make sure it looks correct and
    0100 %they can get some parameters off of the frame if need be (such as fly size
    0101 %or a pixel/cm calilbration).
    0102
    0103 filename = handles.filename;
    0104 if iscell(filename)
    0105     NFiles = length(filename);
    0106 else
    0107     NFiles = 1;
    0108     filename = {filename};
    0109 end
    0110
    0111 for i = 1:NFiles
    0112     video = videoReader(filename{i});
    0113     seek(video,1);
    0114     info = getinfo(video);
    0115     img = getframe(video);
    0116     figure
    0117     imagesc(img)
    0118     title(filename{i})
    0119     disp(['Video name:',filename{i}])
    0120     disp(['Video dimensions [Width, Height]:  [', num2str(info.width),' , ' num2str(info.height),']'])
    0121     disp(['Number of frames:  ',num2str(info.numFrames)])
    0122     disp(['Frame rate:  ',num2str(info.fps),' frames/s'])
    0123
    0124     handles.VideoInfo(i) = info;
    0125 end
    0126
    0127 disp('Frame Viewer Finished')
    0128 guidata(gcbo, handles);
    0129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0130
    0131 % --- Executes on button press in arena_dims.
    0132 function arena_dims_Callback(hObject, eventdata, handles)
    0133 % hObject    handle to arena_dims (see GCBO)
    0134 % eventdata  reserved - to be defined in a future version of MATLAB
    0135 % handles    structure with handles and user data (see GUIDATA)
    0136
    0137 filename = handles.filename;
    0138 if iscell(filename)
    0139     NFiles = length(filename);
    0140 else
    0141     NFiles = 1;
    0142     filename = {filename};
    0143 end
    0144
    0145 p = [];
    0146 q = [];
    0147 for i = 1:NFiles
    0148     video = videoReader(filename{i});
    0149     info = getinfo(video);
    0150     seek(video,1);
    0151     img = getframe(video);
    0152     sz = size(img);
    0153     figure
    0154     colormap gray
    0155     imagesc(img)
    0156     axis image
    0157     title({filename{i}; 'Left click to select points on boundary of arena. Press return when done.'})
    0158
    0159     % Choose points on arena boundary
    0160     [p q] = ginput;
    0161
    0162     %Find center and radius of arena
    0163
    0164     ellipse = fit_ellipse(p',q','y');
    0165     semiminor = min(ellipse.a,ellipse.b);
    0166     semimajor = max(ellipse.a,ellipse.b);
    0167     ellipse.epsilon = sqrt(1-semiminor^2/semimajor^2);
    0168     ellipse.psi = asin(ellipse.epsilon);
    0169     ellipse.semiminor = semiminor;
    0170     ellipse.semimajor = semimajor;
    0171
    0172     rotated_ellipse = ellipse.rotated_ellipse;
    0173     ellipse.points_selected = [p q];
    0174     title('Arena w/ Boundary')
    0175     ellipse.boundaries = [ rotated_ellipse(1,:)', info.height-rotated_ellipse(2,:)'];
    0176
    0177     info = handles.VideoInfo(i);
    0178     figure
    0179     title('Masking arena.  Please wait...')
    0180     drawnow
    0181     disp('Masking arena...')
    0182     mask = zeros(info.height, info.width);
    0183     for k=1:info.height
    0184         for j=1:info.width
    0185             rot = inv(ellipse.R)*[j;k];
    0186             testpoint = (rot(1)-ellipse.X0).^2/(ellipse.a).^2+(rot(2)-ellipse.Y0).^2/(ellipse.b).^2;
    0187             if (testpoint <= 1.01) %giving a little lee-way near boundary
    0188                 mask(k,j) = 1;
    0189             end
    0190         end
    0191     end
    0192     ellipse.mask =  double(mask);
    0193     handles.arena{i} = ellipse;
    0194
    0195     imagesc(double(img(:,:,1)).*double(mask))
    0196     axis image
    0197     colormap gray
    0198     title('Portion to be tracked')
    0199
    0200 end
    0201
    0202 %setting things up to only consider pixels within selected arena...
    0203
    0204 disp('Arena Dimensions Calculated')
    0205 disp(ellipse)
    0206 guidata(gcbo, handles);
    0207
    0208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0209 % --- Executes on button press in input_params.
    0210 function input_params_Callback(hObject, eventdata, handles)
    0211 % hObject    handle to input_params (see GCBO)
    0212 % eventdata  reserved - to be defined in a future version of MATLAB
    0213 % handles    structure with handles and user data (see GUIDATA)
    0214
    0215
    0216 %Opens up a dialog box so that the user can input relevant parameters for
    0217 %each video that is being tracked.  A separate box will open for each
    0218 %video.
    0219
    0220 filename = handles.filename;
    0221 if iscell(filename)
    0222     NFiles = length(filename);
    0223 else
    0224     Nfiles = 1;
    0225     filename = {filename};
    0226 end
    0227 UserIn = [];
    0228
    0229 for i = 1:NFiles
    0230     first = strvcat(filename{i}, '          ','Output directory');
    0231     prompt = {first,'Start Frame (Remember that first frame is indexed 0)','End Frame:', 'Initial background size:', 'Arena radius (cm)', 'Bounding box half-size (in pixels)','Background weight (0.9 < a < 1)'};
    0232     dlg_title = ['Input Paramters'];
    0233     num_lines = 1;
    0234     defaults = {'C:\Documents and Settings\liam\My Documents\LabVIEW Data\FTrack output','0','999', '100','7.5','10','0.9'};
    0235     options.Resize='on';
    0236     options.WindowStyle='normal';
    0237     answer = inputdlg(prompt,dlg_title,num_lines,defaults, options);
    0238     UserIn = [UserIn answer];
    0239     disp(['Input parameters have been entered for ', filename{i}])
    0240
    0241     InputData(i).OutputPath = UserIn{1,i};
    0242     InputData(i).StartFrame = str2double(UserIn(2,i));
    0243     InputData(i).EndFrame = str2double(UserIn(3,i));
    0244     InputData(i).NBackFrames = str2double(UserIn(4,i));
    0245     InputData(i).ArenaRadius = str2double(UserIn(5,i));
    0246     InputData(i).sqrsize = str2double(UserIn(6,i));
    0247     InputData(i).alpha = str2double(UserIn(7,i));
    0248
    0249 end
    0250
    0251 handles.InputData = InputData;
    0252
    0253 guidata(gcbo, handles);
    0254
    0255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0256 % Radio Buttons to select fly finding option
    0257
    0258 % --- Executes during object creation, after setting all properties.
    0259 function find_opt_CreateFcn(hObject, eventdata, handles)
    0260 % hObject    handle to find_opt (see GCBO)
    0261 % eventdata  reserved - to be defined in a future version of MATLAB
    0262 % handles    empty - handles not created until after all CreateFcns called
    0263
    0264
    0265 % --------------------------------------------------------------------
    0266 function find_opt_SelectionChangeFcn(hObject, eventdata, handles)
    0267 % hObject    handle to find_opt (see GCBO)
    0268 % eventdata  reserved - to be defined in a future version of MATLAB
    0269 % handles    structure with handles and user data (see GUIDATA)
    0270
    0271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0272 %  Radio buttons to select whether fly is white on black or black on white
    0273
    0274 % --- Executes during object creation, after setting all properties.
    0275 function neg_opt_CreateFcn(hObject, eventdata, handles)
    0276 % hObject    handle to neg_opt (see GCBO)
    0277 % eventdata  reserved - to be defined in a future version of MATLAB
    0278 % handles    empty - handles not created until after all CreateFcns called
    0279
    0280 % --------------------------------------------------------------------
    0281 function neg_opt_SelectionChangeFcn(hObject, eventdata, handles)
    0282 % hObject    handle to neg_opt (see GCBO)
    0283 % eventdata  reserved - to be defined in a future version of MATLAB
    0284 % handles    structure with handles and user data (see GUIDATA)
    0285
    0286
    0287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0288 % --- Executes on button press in TrackStart.
    0289 function TrackStart_Callback(hObject, eventdata, handles)
    0290 % hObject    handle to TrackStart (see GCBO)
    0291 % eventdata  reserved - to be defined in a future version of MATLAB
    0292 % handles    structure with handles and user data (see GUIDATA)
    0293
    0294 %This part of the calls FlyTracker to do the actual tracking.
    0295
    0296 %grab the filename and user input parameters
    0297 filename = handles.filename;
    0298 InputData = handles.InputData;
    0299
    0300 if iscell(filename)
    0301     NVideos = length(filename);
    0302 else
    0303     NVideos = 1;
    0304     filename = {filename};
    0305 end
    0306
    0307 neg_opt = get(get(handles.neg_opt,'SelectedObject'), 'Tag');
    0308
    0309 % Call FlyTracker
    0310 for i=1:NVideos
    0311
    0312     %video parameters, just because...
    0313     info = handles.VideoInfo(i);
    0314     FrameRate = info.fps;
    0315     FrameRange = [InputData(i).StartFrame:InputData(i).EndFrame];
    0316
    0317     %Track the fly!
    0318     [x, y, orientation] = FlyTracker(filename{i}, FrameRange,...
    0319                        InputData(i).NBackFrames, neg_opt, InputData(i).sqrsize,...
    0320                         InputData(i).alpha, handles.arena{i});
    0321
    0322     %Time vector
    0323     if (info.numFrames == InputData(i).EndFrame)
    0324         InputData(i).EndFrame = InputData(i).EndFrame-1;
    0325     elseif (info.numFrames < InputData(i).EndFrame)
    0326         InputData(i).EndFrame = info.numFrames-1;
    0327     end
    0328
    0329     t = [InputData(i).StartFrame:InputData.EndFrame(i)]/FrameRate;
    0330
    0331     %Save data to handles so the rest of the GUI can access it.
    0332     handles.x = x;
    0333     handles.y = y;
    0334     handles.orientation = orientation;
    0335     handles.t = t;
    0336
    0337     guidata(gcbo, handles);
    0338     %Also, save variables as a .mat file so that the user will be able to
    0339     %load in the tracked data later on.
    0340
    0341     out = SaveFiles(i,handles);
    0342
    0343 end
    0344 disp('Tracking Complete.')
    0345
    0346
    0347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0348
    0349 % --- Executes on button press in view_traj.
    0350 function view_traj_Callback(hObject, eventdata, handles)
    0351 % hObject    handle to view_traj (see GCBO)
    0352 % eventdata  reserved - to be defined in a future version of MATLAB
    0353 % handles    structure with handles and user data (see GUIDATA)
    0354
    0355 [filename, pathname] = ...
    0356      uigetfile({'*.mat'},'Select Raw Trajectory Data');
    0357
    0358 if isequal(filename,0) || isequal(pathname,0)
    0359     disp('File select canceled')
    0360     return;
    0361 else
    0362     fullname = fullfile(pathname, filename);
    0363 end
    0364
    0365
    0366 load(fullname)
    0367 figure
    0368 set(gcf,'Name',fullname)
    0369 subplot(2,2,1)
    0370 plot(t,x)
    0371 xlim([0 t(end)])
    0372 xlabel('Time (s)')
    0373 ylabel('cm')
    0374 title('Raw x data')
    0375 subplot(2,2,3)
    0376 plot(t,y)
    0377 xlim([0 t(end)])
    0378 xlabel('Time (s)')
    0379 ylabel('cm')
    0380 title('Raw y data')
    0381 subplot(2,2,[2 4])
    0382 plot(x,y)
    0383 xlabel('x position (cm)')
    0384 ylabel('y position (cm)')
    0385 title('Raw Trajectory')
    0386 axis equal
    0387
    0388 handles.filename = filename;
    0389 handles.x = x;
    0390 handles.y = y;
    0391 handles.orientation = orientation;
    0392 handles.t = t;
    0393 handles.VideoInfo = VideoInfo;
    0394 handles.InputData = InputData;
    0395 handles.arena{1} = arena;
    0396
    0397 guidata(gcbo, handles);
    0398
    0399
    0400
    0401
    0402 % --- Executes on button press in clean_x.
    0403 function clean_x_Callback(hObject, eventdata, handles)
    0404 % hObject    handle to clean_x (see GCBO)
    0405 % eventdata  reserved - to be defined in a future version of MATLAB
    0406 % handles    structure with handles and user data (see GUIDATA)
    0407
    0408 x = handles.x;
    0409 filename = handles.filename;
    0410
    0411 %open up plot to examine data
    0412 figure
    0413 plot(x)
    0414 title('Zoom in if necessary.  Press any key to continue.')
    0415 xlabel('Frame')
    0416 ylabel('cm')
    0417 pause
    0418
    0419 % This loop runs until the user hits return to exit. We wait for the user
    0420 % to click four points on the graph, and then run the CleanData function on
    0421 % the region defined by those four points.
    0422
    0423 while(1)
    0424 title('Define region of data to clean: left, right, baseline, threshold. Hit Return to exit.')
    0425 [p q] = ginput(4);
    0426 if isempty(p)
    0427     close;
    0428     disp('X data has been cleaned.')
    0429     out = SaveFiles(1,handles);
    0430     return;
    0431 else
    0432     rnge = floor(p(1)):floor(p(2));
    0433 end
    0434
    0435 if (q(3) > q(4))
    0436     choice = 'below';
    0437 elseif (q(3) < q(4));
    0438     choice = 'above';
    0439 end
    0440 epsilon = q(4);
    0441
    0442 x = CleanData(x, rnge, choice, epsilon);
    0443 handles.x = x;
    0444 guidata(gcbo, handles)
    0445 ax = gca;
    0446 xlim_temp = get(ax, 'XLim');
    0447 ylim_temp = get(ax, 'YLim');
    0448
    0449 %Show plot of clean data
    0450 figure
    0451 plot(x)
    0452 xlim(xlim_temp);
    0453 ylim(ylim_temp);
    0454 xlabel('Frame')
    0455 ylabel('cm')
    0456 title('Zoom in if necessary.  Press any key to continue.')
    0457 pause
    0458 end
    0459
    0460
    0461
    0462 % --- Executes on button press in clean_y.
    0463 function clean_y_Callback(hObject, eventdata, handles)
    0464 % hObject    handle to clean_y (see GCBO)
    0465 % eventdata  reserved - to be defined in a future version of MATLAB
    0466 % handles    structure with handles and user data (see GUIDATA)
    0467
    0468 y = handles.y;
    0469 filename = handles.filename;
    0470 %open up plot to examine data
    0471 figure(2)
    0472 plot(y)
    0473 xlabel('Frame')
    0474 ylabel('cm')
    0475 title('Zoom in if necessary.  Press any key to continue.')
    0476 pause
    0477
    0478 % This loop runs until the user hits return to exit. We wait for the user
    0479 % to click four points on the graph, and then run the CleanData function on
    0480 % the region defined by those four points.
    0481
    0482 while(1)
    0483 title('Define region of data to clean: left, right, baseline, threshold. Hit Return to exit.')
    0484 [p q] = ginput(4);
    0485 if isempty(p)
    0486     close;
    0487     disp('Y data has been cleaned.')
    0488     out = SaveFiles(1,handles);
    0489     return;
    0490 else
    0491     rnge = floor(p(1)):floor(p(2));
    0492 end
    0493
    0494 if (q(3) > q(4))
    0495     choice = 'below';
    0496 elseif (q(3) < q(4));
    0497     choice = 'above';
    0498 end
    0499 epsilon = q(4);
    0500
    0501 y = CleanData(y, rnge, choice, epsilon);
    0502 handles.y = y;
    0503 guidata(gcbo, handles)
    0504 ax = gca;
    0505 xlim_temp = get(ax, 'XLim');
    0506 ylim_temp = get(ax, 'YLim');
    0507
    0508 %Show plot of clean data
    0509 figure(2)
    0510 plot(y)
    0511 xlim(xlim_temp);
    0512 ylim(ylim_temp);
    0513 xlabel('Frame')
    0514 ylabel('cm')
    0515 title('Zoom in if necessary.  Press any key to continue.')
    0516 pause
    0517 end
    0518
    0519 return;
    0520
    0521 function out = SaveFiles(i,handles)
    0522
    0523     if iscell(handles.filename)
    0524         filename = handles.filename{i};
    0525     else
    0526         filename = handles.filename;
    0527     end
    0528
    0529     OutputPath = handles.InputData(i).OutputPath;
    0530     x = handles.x;
    0531     y = handles.y;
    0532     t = handles.t;
    0533     orientation = handles.orientation;
    0534     InputData = handles.InputData(i);
    0535     VideoInfo = handles.VideoInfo(i);
    0536     arena =  handles.arena{i};
    0537
    0538     [temp, name, ext, versn] = fileparts(filename);
    0539
    0540     name_mat = strcat(name,'.mat');
    0541     name_xy=strcat(name,'.xy');
    0542     name_ori=strcat(name,'.ori');
    0543     save_filename = fullfile(OutputPath,name);
    0544     save_filename_xy = fullfile(OutputPath,name_xy);
    0545     save_filename_ori = fullfile(OutputPath,name_ori);
    0546     ori=handles.orientation(1,:)';
    0547     xy=[handles.x' handles.y'];
    0548     save(save_filename,'x','y','t','orientation','InputData', 'VideoInfo','arena')
    0549     disp(['Saved ',save_filename])
    0550     save(save_filename_xy,'xy','-ascii','-tabs');
    0551     disp(['Saved ',save_filename_xy])
    0552     save(save_filename_ori,'ori','-ascii','-tabs');
    0553     disp(['Saved ',save_filename_ori])
    0554     out = 1;
    0555
    0556 return;
    0557
    0558
    0559 % --- Executes on button press in tilt_correct.
    0560 function tilt_correct_Callback(hObject, eventdata, handles)
    0561 % hObject    handle to tilt_correct (see GCBO)
    0562 % eventdata  reserved - to be defined in a future version of MATLAB
    0563 % handles    structure with handles and user data (see GUIDATA)
    0564
    0565
    0566 %Note.  This is a slightly different version of tilt correction than
    0567 %described in the PLoS paper.  I think this is more robust and general.
    0568
    0569 x = handles.x;
    0570 y = handles.y;
    0571 t = handles.t;
    0572 ellipse = handles.arena{1};
    0573 radius_in_cm = handles.InputData.ArenaRadius;
    0574 video = videoReader(handles.VideoInfo.url);
    0575 info = getinfo(video);
    0576 height = info.height;
    0577
    0578 psi = ellipse.psi;
    0579 phi = ellipse.phi;
    0580
    0581 %redefining coordinate system so center of arena is at (0,0)
    0582 rotated_ellipse(:,1) = ellipse.boundaries(:,1)-ellipse.X0_in;
    0583 rotated_ellipse(:,2) = ellipse.boundaries(:,2)-(height-ellipse.Y0_in);
    0584
    0585 M = [cos(phi) sin(phi);-sin(phi) cos(phi)];  %rotation matrix.
    0586
    0587 %stretch ellipse only in shortest dimension to length of longest.
    0588 if (ellipse.a > ellipse.b)
    0589     L = [1 0; 0 ellipse.a/ellipse.b];
    0590 else
    0591     L = [ellipse.b/ellipse.a 0; 0 1];
    0592 end
    0593
    0594 T = L*M;  %transformation matrix.  A rotation and a stretch to turn an ellipse into a circle.
    0595
    0596 disp('Correcting for camera tilt.  This may take a few minutes, so be patient!')
    0597
    0598 z = zeros(1,length(rotated_ellipse(:,1)));
    0599
    0600 %Transform boundary line
    0601 for j = 1:length(rotated_ellipse(:,1))
    0602     temp = T*[rotated_ellipse(j,1); rotated_ellipse(j,2)];
    0603     xe(j) = temp(1);
    0604     ye(j) = temp(2);
    0605 end
    0606
    0607 %fit new ellipse
    0608 z = zeros(1,length(x));
    0609 new_ellipse = fit_ellipse(xe',ye','n');
    0610
    0611 semiminor = min(new_ellipse.a,new_ellipse.b);
    0612 semimajor = max(new_ellipse.a,new_ellipse.b);
    0613 new_ellipse.epsilon = sqrt(1-semiminor^2/semimajor^2);
    0614 new_ellipse.psi = asin(new_ellipse.epsilon);
    0615 new_ellipse.semiminor = semiminor;
    0616 new_ellipse.semimajor = semimajor;
    0617 new_ellipse.boundaries = [xe' ye'];
    0618
    0619 %Now transform trajectory
    0620 for j = 1:length(x)
    0621         temp = T*[x(j)-ellipse.X0_in; y(j)-(height-ellipse.Y0_in)];
    0622         xp(j) = temp(1);
    0623         yp(j) = temp(2);
    0624 end
    0625
    0626
    0627 if (abs(new_ellipse.b-new_ellipse.a) <= 2) %2 pixel accuracy seems adequate
    0628     disp('Tilt corrected')
    0629     pixels_in_cm = semimajor/radius_in_cm;
    0630
    0631     x = (xp)/pixels_in_cm;
    0632     y = (yp)/pixels_in_cm;
    0633
    0634     figure
    0635     plot(x,y,new_ellipse.boundaries(:,1)/pixels_in_cm,new_ellipse.boundaries(:,2)/pixels_in_cm,'r')
    0636     title('Transformed trajectory with boundary')
    0637
    0638     handles.arena{1}=new_ellipse;
    0639     handles.x = x;
    0640     handles.y = y;
    0641     handles.InputData.pixels_in_cm =  pixels_in_cm;
    0642     out = SaveFiles(1,handles);
    0643 else
    0644     disp('Something went wrong. Arena is still an ellipse. ')
    0645 end
    0646
    0647
    0648 guidata(gcbo, handles)
    0649
    0650
    0651
    0652
    0653
    0654
    0655