FTrack.m 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. function varargout = FTrack(varargin)
  2. % FTRACK
  3. % For all your fly-tracking needs! . See documentation for usage details.
  4. % Last Modified by GUIDE v2.5 26-Nov-2007 18:07:29
  5. % Begin initialization code - DO NOT EDIT
  6. gui_Singleton = 1;
  7. gui_State = struct('gui_Name', mfilename, ...
  8. 'gui_Singleton', gui_Singleton, ...
  9. 'gui_OpeningFcn', @FTrack_OpeningFcn, ...
  10. 'gui_OutputFcn', @FTrack_OutputFcn, ...
  11. 'gui_LayoutFcn', [] , ...
  12. 'gui_Callback', []);
  13. if nargin && ischar(varargin{1})
  14. gui_State.gui_Callback = str2func(varargin{1});
  15. end
  16. if nargout
  17. [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
  18. else
  19. gui_mainfcn(gui_State, varargin{:});
  20. end
  21. % End initialization code - DO NOT EDIT
  22. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  23. % --- Executes just before FTrack is made visible.
  24. function FTrack_OpeningFcn(hObject, eventdata, handles, varargin)
  25. % This function has no output args, see OutputFcn.
  26. % hObject handle to figure
  27. % eventdata reserved - to be defined in a future version of MATLAB
  28. % handles structure with handles and user data (see GUIDATA)
  29. % varargin command line arguments to FTrack (see VARARGIN)
  30. % Choose default command line output for FTrack
  31. handles.output = hObject;
  32. % Update handles structure
  33. guidata(hObject, handles);
  34. disp('Welcome to FTrack!')
  35. warning off all
  36. % UIWAIT makes FTrack wait for user response (see UIRESUME)
  37. % uiwait(handles.figure1);
  38. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  39. % --- Outputs from this function are returned to the command line.
  40. function varargout = FTrack_OutputFcn(hObject, eventdata, handles)
  41. % varargout cell array for returning output args (see VARARGOUT);
  42. % hObject handle to figure
  43. % eventdata reserved - to be defined in a future version of MATLAB
  44. % handles structure with handles and user data (see GUIDATA)
  45. % Get default command line output from handles structure
  46. varargout{1} = handles.output;
  47. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  48. % --- Executes on button press in load_video.
  49. function load_video_Callback(hObject, eventdata, handles)
  50. % hObject handle to load_video (see GCBO)
  51. % eventdata reserved - to be defined in a future version of MATLAB
  52. % handles structure with handles and user data (see GUIDATA
  53. %The following allows the user to select multiple videos to be tracked.
  54. %The videos will be tracked sequentially, not in parallel. The filenames
  55. %will be displayed in the message center.
  56. [filename, pathname] = uigetfile({'*.avi;*.mpg;*.mp2','Video Files (*.avi,*.mpg,*.mp2)'}, 'Pick a video', 'MultiSelect','on');
  57. if iscell(filename)
  58. NFiles = length(filename);
  59. else
  60. NFiles = 1;
  61. filename = {filename};
  62. end
  63. if isequal(filename,0) || isequal(pathname,0)
  64. disp('File select canceled')
  65. else
  66. for i = 1:NFiles
  67. disp(['Video selected: ', fullfile(pathname, filename{i})])
  68. handles.filename{i} = fullfile(pathname, filename{i});
  69. end
  70. end
  71. guidata(gcbo,handles);
  72. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  73. % --- Executes on button press in viewframe.
  74. function viewframe_Callback(hObject, eventdata, handles)
  75. % hObject handle to viewframe (see GCBO)
  76. % eventdata reserved - to be defined in a future version of MATLAB
  77. % handles structure with handles and user data (see GUIDATA)
  78. %This is the single frame viewer. It simply gives the user some info about
  79. %the video (displayed in the message center), and also shows the user a
  80. %single frame of the movie so that they can make sure it looks correct and
  81. %they can get some parameters off of the frame if need be (such as fly size
  82. %or a pixel/cm calilbration).
  83. filename = handles.filename;
  84. if iscell(filename)
  85. NFiles = length(filename);
  86. else
  87. NFiles = 1;
  88. filename = {filename};
  89. end
  90. for i = 1:NFiles
  91. video = videoReader(filename{i});
  92. seek(video,1);
  93. info = getinfo(video);
  94. img = getframe(video);
  95. figure
  96. imagesc(img)
  97. title(filename{i})
  98. disp(['Video name:',filename{i}])
  99. disp(['Video dimensions [Width, Height]: [', num2str(info.width),' , ' num2str(info.height),']'])
  100. disp(['Number of frames: ',num2str(info.numFrames)])
  101. disp(['Frame rate: ',num2str(info.fps),' frames/s'])
  102. handles.VideoInfo(i) = info;
  103. end
  104. disp('Frame Viewer Finished')
  105. guidata(gcbo, handles);
  106. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  107. % --- Executes on button press in arena_dims.
  108. function arena_dims_Callback(hObject, eventdata, handles)
  109. % hObject handle to arena_dims (see GCBO)
  110. % eventdata reserved - to be defined in a future version of MATLAB
  111. % handles structure with handles and user data (see GUIDATA)
  112. filename = handles.filename;
  113. if iscell(filename)
  114. NFiles = length(filename);
  115. else
  116. NFiles = 1;
  117. filename = {filename};
  118. end
  119. p = [];
  120. q = [];
  121. for i = 1:NFiles
  122. video = videoReader(filename{i});
  123. info = getinfo(video);
  124. seek(video,1);
  125. img = getframe(video);
  126. sz = size(img);
  127. figure
  128. colormap gray
  129. imagesc(img)
  130. axis image
  131. title({filename{i}; 'Left click to select points on boundary of arena. Press return when done.'})
  132. % Choose points on arena boundary
  133. [p q] = ginput;
  134. %Find center and radius of arena
  135. ellipse = fit_ellipse(p',q','y');
  136. semiminor = min(ellipse.a,ellipse.b);
  137. semimajor = max(ellipse.a,ellipse.b);
  138. ellipse.epsilon = sqrt(1-semiminor^2/semimajor^2);
  139. ellipse.psi = asin(ellipse.epsilon);
  140. ellipse.semiminor = semiminor;
  141. ellipse.semimajor = semimajor;
  142. rotated_ellipse = ellipse.rotated_ellipse;
  143. ellipse.points_selected = [p q];
  144. title('Arena w/ Boundary')
  145. ellipse.boundaries = [ rotated_ellipse(1,:)', info.height-rotated_ellipse(2,:)'];
  146. info = handles.VideoInfo(i);
  147. figure
  148. title('Masking arena. Please wait...')
  149. drawnow
  150. disp('Masking arena...')
  151. mask = zeros(info.height, info.width);
  152. for k=1:info.height
  153. for j=1:info.width
  154. rot = inv(ellipse.R)*[j;k];
  155. testpoint = (rot(1)-ellipse.X0).^2/(ellipse.a).^2+(rot(2)-ellipse.Y0).^2/(ellipse.b).^2;
  156. if (testpoint <= 1.01) %giving a little lee-way near boundary
  157. mask(k,j) = 1;
  158. end
  159. end
  160. end
  161. ellipse.mask = double(mask);
  162. handles.arena{i} = ellipse;
  163. imagesc(double(img(:,:,1)).*double(mask))
  164. axis image
  165. colormap gray
  166. title('Portion to be tracked')
  167. end
  168. %setting things up to only consider pixels within selected arena...
  169. disp('Arena Dimensions Calculated')
  170. disp(ellipse)
  171. guidata(gcbo, handles);
  172. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  173. % --- Executes on button press in input_params.
  174. function input_params_Callback(hObject, eventdata, handles)
  175. % hObject handle to input_params (see GCBO)
  176. % eventdata reserved - to be defined in a future version of MATLAB
  177. % handles structure with handles and user data (see GUIDATA)
  178. %Opens up a dialog box so that the user can input relevant parameters for
  179. %each video that is being tracked. A separate box will open for each
  180. %video.
  181. filename = handles.filename;
  182. if iscell(filename)
  183. NFiles = length(filename);
  184. else
  185. Nfiles = 1;
  186. filename = {filename};
  187. end
  188. UserIn = [];
  189. for i = 1:NFiles
  190. first = strvcat(filename{i}, ' ','Output directory');
  191. 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)'};
  192. dlg_title = ['Input Paramters'];
  193. num_lines = 1;
  194. defaults = {'C:\Documents and Settings\liam\My Documents\LabVIEW Data\FTrack output','0','999', '100','7.5','10','0.9'};
  195. options.Resize='on';
  196. options.WindowStyle='normal';
  197. answer = inputdlg(prompt,dlg_title,num_lines,defaults, options);
  198. UserIn = [UserIn answer];
  199. disp(['Input parameters have been entered for ', filename{i}])
  200. InputData(i).OutputPath = UserIn{1,i};
  201. InputData(i).StartFrame = str2double(UserIn(2,i));
  202. InputData(i).EndFrame = str2double(UserIn(3,i));
  203. InputData(i).NBackFrames = str2double(UserIn(4,i));
  204. InputData(i).ArenaRadius = str2double(UserIn(5,i));
  205. InputData(i).sqrsize = str2double(UserIn(6,i));
  206. InputData(i).alpha = str2double(UserIn(7,i));
  207. end
  208. handles.InputData = InputData;
  209. guidata(gcbo, handles);
  210. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  211. % Radio Buttons to select fly finding option
  212. % --- Executes during object creation, after setting all properties.
  213. function find_opt_CreateFcn(hObject, eventdata, handles)
  214. % hObject handle to find_opt (see GCBO)
  215. % eventdata reserved - to be defined in a future version of MATLAB
  216. % handles empty - handles not created until after all CreateFcns called
  217. % --------------------------------------------------------------------
  218. function find_opt_SelectionChangeFcn(hObject, eventdata, handles)
  219. % hObject handle to find_opt (see GCBO)
  220. % eventdata reserved - to be defined in a future version of MATLAB
  221. % handles structure with handles and user data (see GUIDATA)
  222. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  223. % Radio buttons to select whether fly is white on black or black on white
  224. % --- Executes during object creation, after setting all properties.
  225. function neg_opt_CreateFcn(hObject, eventdata, handles)
  226. % hObject handle to neg_opt (see GCBO)
  227. % eventdata reserved - to be defined in a future version of MATLAB
  228. % handles empty - handles not created until after all CreateFcns called
  229. % --------------------------------------------------------------------
  230. function neg_opt_SelectionChangeFcn(hObject, eventdata, handles)
  231. % hObject handle to neg_opt (see GCBO)
  232. % eventdata reserved - to be defined in a future version of MATLAB
  233. % handles structure with handles and user data (see GUIDATA)
  234. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  235. % --- Executes on button press in TrackStart.
  236. function TrackStart_Callback(hObject, eventdata, handles)
  237. % hObject handle to TrackStart (see GCBO)
  238. % eventdata reserved - to be defined in a future version of MATLAB
  239. % handles structure with handles and user data (see GUIDATA)
  240. %This part of the calls FlyTracker to do the actual tracking.
  241. %grab the filename and user input parameters
  242. filename = handles.filename;
  243. InputData = handles.InputData;
  244. if iscell(filename)
  245. NVideos = length(filename);
  246. else
  247. NVideos = 1;
  248. filename = {filename};
  249. end
  250. neg_opt = get(get(handles.neg_opt,'SelectedObject'), 'Tag');
  251. % Call FlyTracker
  252. for i=1:NVideos
  253. %video parameters, just because...
  254. info = handles.VideoInfo(i);
  255. FrameRate = info.fps;
  256. FrameRange = [InputData(i).StartFrame:InputData(i).EndFrame];
  257. %Track the fly!
  258. [x, y, orientation] = FlyTracker(filename{i}, FrameRange,...
  259. InputData(i).NBackFrames, neg_opt, InputData(i).sqrsize,...
  260. InputData(i).alpha, handles.arena{i});
  261. %Time vector
  262. if (info.numFrames == InputData(i).EndFrame)
  263. InputData(i).EndFrame = InputData(i).EndFrame-1;
  264. elseif (info.numFrames < InputData(i).EndFrame)
  265. InputData(i).EndFrame = info.numFrames-1;
  266. end
  267. t = [InputData(i).StartFrame:InputData.EndFrame(i)]/FrameRate;
  268. %Save data to handles so the rest of the GUI can access it.
  269. handles.x = x;
  270. handles.y = y;
  271. handles.orientation = orientation;
  272. handles.t = t;
  273. guidata(gcbo, handles);
  274. %Also, save variables as a .mat file so that the user will be able to
  275. %load in the tracked data later on.
  276. out = SaveFiles(i,handles);
  277. end
  278. disp('Tracking Complete.')
  279. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  280. % --- Executes on button press in view_traj.
  281. function view_traj_Callback(hObject, eventdata, handles)
  282. % hObject handle to view_traj (see GCBO)
  283. % eventdata reserved - to be defined in a future version of MATLAB
  284. % handles structure with handles and user data (see GUIDATA)
  285. [filename, pathname] = ...
  286. uigetfile({'*.mat'},'Select Raw Trajectory Data');
  287. if isequal(filename,0) || isequal(pathname,0)
  288. disp('File select canceled')
  289. return;
  290. else
  291. fullname = fullfile(pathname, filename);
  292. end
  293. load(fullname)
  294. figure
  295. set(gcf,'Name',fullname)
  296. subplot(2,2,1)
  297. plot(t,x)
  298. xlim([0 t(end)])
  299. xlabel('Time (s)')
  300. ylabel('cm')
  301. title('Raw x data')
  302. subplot(2,2,3)
  303. plot(t,y)
  304. xlim([0 t(end)])
  305. xlabel('Time (s)')
  306. ylabel('cm')
  307. title('Raw y data')
  308. subplot(2,2,[2 4])
  309. plot(x,y)
  310. xlabel('x position (cm)')
  311. ylabel('y position (cm)')
  312. title('Raw Trajectory')
  313. axis equal
  314. handles.filename = filename;
  315. handles.x = x;
  316. handles.y = y;
  317. handles.orientation = orientation;
  318. handles.t = t;
  319. handles.VideoInfo = VideoInfo;
  320. handles.InputData = InputData;
  321. handles.arena{1} = arena;
  322. guidata(gcbo, handles);
  323. % --- Executes on button press in clean_x.
  324. function clean_x_Callback(hObject, eventdata, handles)
  325. % hObject handle to clean_x (see GCBO)
  326. % eventdata reserved - to be defined in a future version of MATLAB
  327. % handles structure with handles and user data (see GUIDATA)
  328. x = handles.x;
  329. filename = handles.filename;
  330. %open up plot to examine data
  331. figure
  332. plot(x)
  333. title('Zoom in if necessary. Press any key to continue.')
  334. xlabel('Frame')
  335. ylabel('cm')
  336. pause
  337. % This loop runs until the user hits return to exit. We wait for the user
  338. % to click four points on the graph, and then run the CleanData function on
  339. % the region defined by those four points.
  340. while(1)
  341. title('Define region of data to clean: left, right, baseline, threshold. Hit Return to exit.')
  342. [p q] = ginput(4);
  343. if isempty(p)
  344. close;
  345. disp('X data has been cleaned.')
  346. out = SaveFiles(1,handles);
  347. return;
  348. else
  349. rnge = floor(p(1)):floor(p(2));
  350. end
  351. if (q(3) > q(4))
  352. choice = 'below';
  353. elseif (q(3) < q(4));
  354. choice = 'above';
  355. end
  356. epsilon = q(4);
  357. x = CleanData(x, rnge, choice, epsilon);
  358. handles.x = x;
  359. guidata(gcbo, handles)
  360. ax = gca;
  361. xlim_temp = get(ax, 'XLim');
  362. ylim_temp = get(ax, 'YLim');
  363. %Show plot of clean data
  364. figure
  365. plot(x)
  366. xlim(xlim_temp);
  367. ylim(ylim_temp);
  368. xlabel('Frame')
  369. ylabel('cm')
  370. title('Zoom in if necessary. Press any key to continue.')
  371. pause
  372. end
  373. % --- Executes on button press in clean_y.
  374. function clean_y_Callback(hObject, eventdata, handles)
  375. % hObject handle to clean_y (see GCBO)
  376. % eventdata reserved - to be defined in a future version of MATLAB
  377. % handles structure with handles and user data (see GUIDATA)
  378. y = handles.y;
  379. filename = handles.filename;
  380. %open up plot to examine data
  381. figure(2)
  382. plot(y)
  383. xlabel('Frame')
  384. ylabel('cm')
  385. title('Zoom in if necessary. Press any key to continue.')
  386. pause
  387. % This loop runs until the user hits return to exit. We wait for the user
  388. % to click four points on the graph, and then run the CleanData function on
  389. % the region defined by those four points.
  390. while(1)
  391. title('Define region of data to clean: left, right, baseline, threshold. Hit Return to exit.')
  392. [p q] = ginput(4);
  393. if isempty(p)
  394. close;
  395. disp('Y data has been cleaned.')
  396. out = SaveFiles(1,handles);
  397. return;
  398. else
  399. rnge = floor(p(1)):floor(p(2));
  400. end
  401. if (q(3) > q(4))
  402. choice = 'below';
  403. elseif (q(3) < q(4));
  404. choice = 'above';
  405. end
  406. epsilon = q(4);
  407. y = CleanData(y, rnge, choice, epsilon);
  408. handles.y = y;
  409. guidata(gcbo, handles)
  410. ax = gca;
  411. xlim_temp = get(ax, 'XLim');
  412. ylim_temp = get(ax, 'YLim');
  413. %Show plot of clean data
  414. figure(2)
  415. plot(y)
  416. xlim(xlim_temp);
  417. ylim(ylim_temp);
  418. xlabel('Frame')
  419. ylabel('cm')
  420. title('Zoom in if necessary. Press any key to continue.')
  421. pause
  422. end
  423. return;
  424. function out = SaveFiles(i,handles)
  425. if iscell(handles.filename)
  426. filename = handles.filename{i};
  427. else
  428. filename = handles.filename;
  429. end
  430. OutputPath = handles.InputData(i).OutputPath;
  431. x = handles.x;
  432. y = handles.y;
  433. t = handles.t;
  434. orientation = handles.orientation;
  435. InputData = handles.InputData(i);
  436. VideoInfo = handles.VideoInfo(i);
  437. arena = handles.arena{i};
  438. [temp, name, ext, versn] = fileparts(filename);
  439. name_mat = strcat(name,'.mat');
  440. name_xy=strcat(name,'.xy');
  441. name_ori=strcat(name,'.ori');
  442. save_filename = fullfile(OutputPath,name);
  443. save_filename_xy = fullfile(OutputPath,name_xy);
  444. save_filename_ori = fullfile(OutputPath,name_ori);
  445. ori=handles.orientation(1,:)';
  446. xy=[handles.x' handles.y'];
  447. save(save_filename,'x','y','t','orientation','InputData', 'VideoInfo','arena')
  448. disp(['Saved ',save_filename])
  449. save(save_filename_xy,'xy','-ascii','-tabs');
  450. disp(['Saved ',save_filename_xy])
  451. save(save_filename_ori,'ori','-ascii','-tabs');
  452. disp(['Saved ',save_filename_ori])
  453. out = 1;
  454. return;
  455. % --- Executes on button press in tilt_correct.
  456. function tilt_correct_Callback(hObject, eventdata, handles)
  457. % hObject handle to tilt_correct (see GCBO)
  458. % eventdata reserved - to be defined in a future version of MATLAB
  459. % handles structure with handles and user data (see GUIDATA)
  460. %Note. This is a slightly different version of tilt correction than
  461. %described in the PLoS paper. I think this is more robust and general.
  462. x = handles.x;
  463. y = handles.y;
  464. t = handles.t;
  465. ellipse = handles.arena{1};
  466. radius_in_cm = handles.InputData.ArenaRadius;
  467. video = videoReader(handles.VideoInfo.url);
  468. info = getinfo(video);
  469. height = info.height;
  470. psi = ellipse.psi;
  471. phi = ellipse.phi;
  472. %redefining coordinate system so center of arena is at (0,0)
  473. rotated_ellipse(:,1) = ellipse.boundaries(:,1)-ellipse.X0_in;
  474. rotated_ellipse(:,2) = ellipse.boundaries(:,2)-(height-ellipse.Y0_in);
  475. M = [cos(phi) sin(phi);-sin(phi) cos(phi)]; %rotation matrix.
  476. %stretch ellipse only in shortest dimension to length of longest.
  477. if (ellipse.a > ellipse.b)
  478. L = [1 0; 0 ellipse.a/ellipse.b];
  479. else
  480. L = [ellipse.b/ellipse.a 0; 0 1];
  481. end
  482. T = L*M; %transformation matrix. A rotation and a stretch to turn an ellipse into a circle.
  483. disp('Correcting for camera tilt. This may take a few minutes, so be patient!')
  484. z = zeros(1,length(rotated_ellipse(:,1)));
  485. %Transform boundary line
  486. for j = 1:length(rotated_ellipse(:,1))
  487. temp = T*[rotated_ellipse(j,1); rotated_ellipse(j,2)];
  488. xe(j) = temp(1);
  489. ye(j) = temp(2);
  490. end
  491. %fit new ellipse
  492. z = zeros(1,length(x));
  493. new_ellipse = fit_ellipse(xe',ye','n');
  494. semiminor = min(new_ellipse.a,new_ellipse.b);
  495. semimajor = max(new_ellipse.a,new_ellipse.b);
  496. new_ellipse.epsilon = sqrt(1-semiminor^2/semimajor^2);
  497. new_ellipse.psi = asin(new_ellipse.epsilon);
  498. new_ellipse.semiminor = semiminor;
  499. new_ellipse.semimajor = semimajor;
  500. new_ellipse.boundaries = [xe' ye'];
  501. %Now transform trajectory
  502. for j = 1:length(x)
  503. temp = T*[x(j)-ellipse.X0_in; y(j)-(height-ellipse.Y0_in)];
  504. xp(j) = temp(1);
  505. yp(j) = temp(2);
  506. end
  507. if (abs(new_ellipse.b-new_ellipse.a) <= 2) %2 pixel accuracy seems adequate
  508. disp('Tilt corrected')
  509. pixels_in_cm = semimajor/radius_in_cm;
  510. x = (xp)/pixels_in_cm;
  511. y = (yp)/pixels_in_cm;
  512. figure
  513. plot(x,y,new_ellipse.boundaries(:,1)/pixels_in_cm,new_ellipse.boundaries(:,2)/pixels_in_cm,'r')
  514. title('Transformed trajectory with boundary')
  515. handles.arena{1}=new_ellipse;
  516. handles.x = x;
  517. handles.y = y;
  518. handles.InputData.pixels_in_cm = pixels_in_cm;
  519. out = SaveFiles(1,handles);
  520. else
  521. disp('Something went wrong. Arena is still an ellipse. ')
  522. end
  523. guidata(gcbo, handles)