diff --git a/src/MATLAB/AddHashedCell.m b/src/MATLAB/AddHashedCell.m index a6c71dd9713a18ac2a7f5cbe9b591ffa8f650b30..a0260fd928c5fe297bc978558d7f9f6216064eb5 100644 --- a/src/MATLAB/AddHashedCell.m +++ b/src/MATLAB/AddHashedCell.m @@ -2,6 +2,8 @@ function AddHashedCell(t,cellHullID,cellTrackID) %This will either add an entry to HashedHulls or update an entry based on %cellHullID +%--Eric Wait + global HashedCells if(isempty(HashedCells)) diff --git a/src/MATLAB/AddHullToTrack.m b/src/MATLAB/AddHullToTrack.m index ae8d4b5d14ea1dbc90d632542faac9b77e6fe5b8..1b72f845bc7ae9f898a26880444a18f356e47297 100644 --- a/src/MATLAB/AddHullToTrack.m +++ b/src/MATLAB/AddHullToTrack.m @@ -8,6 +8,7 @@ function AddHullToTrack(hullID,trackID,previousHullID) %previousHullID at previousTime exists in that track. Also, it has been %removed from any previous track assosiation. +%--Eric Wait global HashedCells CellTracks CellFamilies CellHulls @@ -37,7 +38,6 @@ if(0 >= hash) end end CellTracks(curTrackID).hulls(hash) = hullID; -% CellTracks(curTrackID).hulls(hash).time = time; if(CellTracks(curTrackID).endTime < time) CellTracks(curTrackID).endTime = time; diff --git a/src/MATLAB/ChangeLabel.m b/src/MATLAB/ChangeLabel.m index 3fe1b834f6e07e9f41b2e5e76696e34fc6a78ff3..4d8109b0142dd6dfb93fa368edccd6bcab58ba56 100644 --- a/src/MATLAB/ChangeLabel.m +++ b/src/MATLAB/ChangeLabel.m @@ -1,4 +1,5 @@ function ChangeLabel(time,oldTrackID,newTrackID) +%ChangLabel(time,oldTrackID,newTrackID) %This will attempt to change the trackID from a given time until the end of %the track. However, the trackID will only be changed up to the point that %the newTrackID does not exist. If when moving hulls from the oldTrack to @@ -14,6 +15,8 @@ function ChangeLabel(time,oldTrackID,newTrackID) %The only time that the subtree would not move with the change would be as %stated above. +%--Eric Wait + global CellTracks CellFamilies CellHulls bothHaveChildren = 0;%flag to deal with conflicting children @@ -51,70 +54,91 @@ else RehashCellTracks(oldTrackID,CellHulls(firstHull).time); end -%Handle children if(oldEmptied) - %update parent and sibling - if(~isempty(CellTracks(oldTrackID).siblingTrack)) - CombineTrackWithParent(CellTracks(oldTrackID).siblingTrack); - index = CellTracks(CellTracks(oldTrackID).parentTrack).childrenTracks == oldTrackID; - CellTracks(CellTracks(oldTrackID).parentTrack).childrenTracks(index) = []; - end - - %update family - index = [CellFamilies(CellTracks(oldTrackID).familyID).tracks]==oldTrackID; - CellFamilies(CellTracks(oldTrackID).familyID).tracks(index) = []; - - %clean up other fields - CellTracks(oldTrackID).parentTrack = []; - CellTracks(oldTrackID).siblingTrack = []; - CellTracks(oldTrackID).startTime = []; - CellTracks(oldTrackID).endTime = []; - CellTracks(oldTrackID).color = []; - - %deal with any children if(oldBeforeNew) + %deal with any children if(~isempty(CellTracks(oldTrackID).childrenTracks)) - dropChildren(CellTracks(oldTrackID).childrenTracks); + dropChildren(oldTrackID); + end + if(~isempty(CellTracks(newTrackID).siblingTrack) && ... + isempty(find(CellTracks(oldTrackID).childrenTracks==CellTracks(newTrackID).siblingTrack, 1))) + CombineTrackWithParent(CellTracks(newTrackID).siblingTrack); end + CellTracks(newTrackID).parentTrack = CellTracks(oldTrackID).parentTrack; + index = CellTracks(CellTracks(newTrackID).parentTrack).childrenTracks==oldTrackID; + CellTracks(CellTracks(newTrackID).parentTrack).childrenTracks(index) = newTrackID; + CellTracks(newTrackID).siblingTrack = CellTracks(oldTrackID).siblingTrack; + CellTracks(newTrackID).familyID = CellTracks(oldTrackID).familyID; elseif(newBeforeOld) + %deal with any children if(bothHaveChildren) - dropChildren(CellTracks(newTrackID).childrenTracks); + index = CellTracks(newTrackID).childrenTracks==oldTrackID; + if(~isempty(find(index, 1))) + RemoveFromTree(CellTracks(CellTracks(newTrackID).childrenTracks(~index)).startTime,... + CellTracks(newTrackID).childrenTracks(~index),'no'); + CellTracks(newTrackID).childrenTracks = []; + CellTracks(oldTrackID).siblingTrack = []; + else + dropChildren(newTrackID); + end moveChildren(oldTrackID,newTrackID); elseif(~isempty(CellTracks(newTrackID).childrenTracks)) - dropChildren(CellTracks(newTrackID).childrenTracks); + index = CellTracks(newTrackID).childrenTracks==oldTrackID; + if(~isempty(find(index, 1))) + RemoveFromTree(CellTracks(CellTracks(newTrackID).childrenTracks(~index)).startTime,... + CellTracks(newTrackID).childrenTracks(~index),'no'); + CellTracks(newTrackID).childrenTracks = []; + CellTracks(oldTrackID).siblingTrack = []; + else + dropChildren(newTrackID); + end elseif(~isempty(CellTracks(oldTrackID).childrenTracks)) moveChildren(oldTrackID,newTrackID); end + if(~isempty(CellTracks(oldTrackID).siblingTrack) && ... + isempty(find(CellTracks(newTrackID).childrenTracks==CellTracks(oldTrackID).siblingTrack, 1))) + CombineTrackWithParent(CellTracks(oldTrackID).siblingTrack); + end end + + %clean up other fields + RemoveTrackFromFamily(oldTrackID); + CellTracks(oldTrackID).parentTrack = []; + CellTracks(oldTrackID).siblingTrack = []; + CellTracks(oldTrackID).startTime = []; + CellTracks(oldTrackID).endTime = []; + CellTracks(oldTrackID).color = []; else %the old track still exists in some fasion if(isempty(find(CellTracks(oldTrackID).hulls==lastOldHull, 1)) &&... ~isempty(CellTracks(oldTrackID).childrenTracks)) %the last hull from the old track has been moved over and had %children if(CellHulls(lastOldHull).time<CellTracks(newTrackID).endTime) - dropChildren(CellTracks(oldTrackID).childrenTracks); + dropChildren(oldTrackID); elseif(CellHulls(lastOldHull).time>=CellTracks(newTrackID).endTime) if(~isempty(CellTracks(newTrackID).childrenTracks)) - dropChildren(CellTracks(newTrackID).childrenTracks); + dropChildren(newTrackID); end moveChildren(oldTrackID,newTrackID); end elseif(isempty(find(CellTracks(oldTrackID).hulls==lastOldHull, 1)) &&... CellHulls(lastOldHull).time>CellTracks(newTrackID).endTime &&... ~isempty(CellTracks(newTrackID).childrenTracks)) - dropChildren(CellTracks(newTrackID).childrenTracks); + dropChildren(newTrackID); end end end -function dropChildren(children) +function dropChildren(trackID) %remove children from tree global CellTracks familyIDs = []; -for i=1:length(children) - familyIDs = [familyIDs RemoveFromTree(CellTracks(children(i)).startTime,children(i))]; +while ~isempty(CellTracks(trackID).childrenTracks) + familyIDs = [familyIDs RemoveFromTree(CellTracks(CellTracks(trackID).childrenTracks(1)).startTime,CellTracks(trackID).childrenTracks(1),'no')]; end + +CellTracks(trackID).childrenTracks = []; %run processNewborns on them ProcessNewborns(familyIDs); end diff --git a/src/MATLAB/ChangeTrackAndChildrensFamily.m b/src/MATLAB/ChangeTrackAndChildrensFamily.m index 227c1b91b19a1693cd6b118d5c7d6a38f0bd6a72..043a07ee89ab7983ee599b696ace05101dacd50d 100644 --- a/src/MATLAB/ChangeTrackAndChildrensFamily.m +++ b/src/MATLAB/ChangeTrackAndChildrensFamily.m @@ -4,6 +4,8 @@ function ChangeTrackAndChildrensFamily(oldFamilyID,newFamilyID,trackID) %This DOES NOT make the parent child relationship, it is just updates the %CellFamilies data structure. +%--Eric Wait + global CellFamilies CellTracks %get the full list of tracks to be updateded @@ -12,8 +14,7 @@ trackList = traverseTree(newFamilyID,trackID); %remove tracks from family for i=1:length(trackList) CellTracks(trackList(i)).familyID = newFamilyID; - index = CellFamilies(oldFamilyID).tracks == trackList(i); - CellFamilies(oldFamilyID).tracks(index) = []; +% RemoveTrackFromFamily(trackList(i)); end if(isempty(CellFamilies(oldFamilyID).tracks)) @@ -22,16 +23,8 @@ if(isempty(CellFamilies(oldFamilyID).tracks)) CellFamilies(oldFamilyID).endTime = []; else %update times - CellFamilies(oldFamilyID).startTime = CellTracks(CellFamilies(oldFamilyID).tracks(1)).startTime; - CellFamilies(oldFamilyID).endTime = CellTracks(CellFamilies(oldFamilyID).tracks(1)).endTime; - for i=2:length(CellFamilies(oldFamilyID).tracks) - if(CellTracks(CellFamilies(oldFamilyID).tracks(i)).startTime < CellFamilies(oldFamilyID).startTime) - CellFamilies(oldFamilyID).startTime = CellTracks(CellFamilies(oldFamilyID).tracks(i)).startTime; - end - if(CellTracks(CellFamilies(oldFamilyID).tracks(i)).endTime > CellFamilies(oldFamilyID).endTime) - CellFamilies(oldFamilyID).endTime = CellTracks(CellFamilies(oldFamilyID).tracks(i)).endTime; - end - end + CellFamilies(oldFamilyID).startTime = min([CellTracks(CellFamilies(oldFamilyID).tracks).startTime]); + CellFamilies(oldFamilyID).endTime = max([CellTracks(CellFamilies(oldFamilyID).tracks).endTime]); end end @@ -57,4 +50,6 @@ if(~isempty(CellTracks(trackID).childrenTracks)) trackList = [trackList traverseTree(newFamilyID, CellTracks(trackID).childrenTracks(i))]; end end + +RemoveTrackFromFamily(trackID); end diff --git a/src/MATLAB/ChangeTrackParent.m b/src/MATLAB/ChangeTrackParent.m index c4e4216de4b5553b88560dfb229643171e53b7d0..fcc5aef54a441e864fc33d52e692112c7a8caf72 100644 --- a/src/MATLAB/ChangeTrackParent.m +++ b/src/MATLAB/ChangeTrackParent.m @@ -5,7 +5,15 @@ function ChangeTrackParent(parentTrackID,time,childTrackID) %there should be a new track and the child track that are siblings with the %parent track being the parent. -global CellTracks +%--Eric Wait + +global CellTracks CellFamilies + +%see if the child exists before time +if(time > CellTracks(childTrackID).startTime) + newFamilyID = RemoveFromTree(time,childTrackID,'yes'); + childTrackID = CellFamilies(newFamilyID).rootTrackID; +end %find where the child should attach to the parent hash = time - CellTracks(parentTrackID).startTime + 1; diff --git a/src/MATLAB/CloseFigure.m b/src/MATLAB/CloseFigure.m index edb65e730b27fea60b17d283b203ca4a31795661..d6cc45334aab91aabad1c2d8e255f1d8b94eb90b 100644 --- a/src/MATLAB/CloseFigure.m +++ b/src/MATLAB/CloseFigure.m @@ -1,4 +1,8 @@ function CloseFigure(varargin) +%Closes both figures and cleans up the Figures global var + +%--Eric Wait + global Figures if(strcmp(get(Figures.cells.menuHandles.saveMenu,'Enable'),'on')) choice = questdlg('Save current edits before closing?','Closing','Yes','No','Cancel','Cancel'); diff --git a/src/MATLAB/CombineTrackWithParent.m b/src/MATLAB/CombineTrackWithParent.m index 9a0556bd4cb2955a02426a5d8806514e934b0e41..b55598dfff7ae4be0b025c25c49754c9d0a13ad0 100644 --- a/src/MATLAB/CombineTrackWithParent.m +++ b/src/MATLAB/CombineTrackWithParent.m @@ -1,4 +1,5 @@ function CombineTrackWithParent(trackID) +% CombineTrackWithParent(trackID) %Combine childTrack with its parent track - in otherwords the childtrack %will be merged into the parent track making it all one edge. %Afterward all of the hulls previously associated with the given track will @@ -7,6 +8,8 @@ function CombineTrackWithParent(trackID) %***Make sure that the sibling of the given track has been delt with prior %to calling this function. IT WILL BE LOST +%--Eric Wait + global CellFamilies CellTracks CellHulls parentID = CellTracks(trackID).parentTrack; diff --git a/src/MATLAB/ContextChangeLabel.m b/src/MATLAB/ContextChangeLabel.m index 05111ec71e1cafad2717e75b16358bf2e50bf6d5..5ce3f1451cc29b296ed0aa1347f188cebc60bf96 100644 --- a/src/MATLAB/ContextChangeLabel.m +++ b/src/MATLAB/ContextChangeLabel.m @@ -1,5 +1,8 @@ function ContextChangeLabel(time,trackID) %context menu callback function + +%--Eric Wait + global CellTracks HashedCells newTrackID = inputdlg('Enter New Label','New Label',1,{num2str(trackID)}); @@ -11,7 +14,7 @@ if(newTrackID>length(CellTracks) || isempty(CellTracks(newTrackID).hulls)) switch choice case 'Yes' oldFamily = CellTracks(trackID).familyID; - RemoveFromTree(time,trackID); + RemoveFromTree(time,trackID,'yes'); History('Push'); LogAction(['Removed ' num2str(trackID) ' From Tree'], oldFamily,CellTracks(trackID).familyID); case 'Cancel' diff --git a/src/MATLAB/ContextChangeParent.m b/src/MATLAB/ContextChangeParent.m index 82714593bf03df76a7c84d0c57c5569034fb660b..2172cf5f96957ffc1045a9db0dfd3fc2a94a8e61 100644 --- a/src/MATLAB/ContextChangeParent.m +++ b/src/MATLAB/ContextChangeParent.m @@ -1,12 +1,15 @@ -function ContextChangeParent(trackID) +function ContextChangeParent(trackID,time) %Function for context menu call back + +%--Eric Wait + global CellTracks newParentID = inputdlg('Enter New Parent','New Parent',1,{num2str(CellTracks(trackID).parentTrack)}); if(isempty(newParentID)),return,end; newParentID = str2double(newParentID(1)); -if(CellTracks(newParentID).startTime > CellTracks(trackID).startTime) +if(CellTracks(newParentID).startTime > time) msgbox(['Parent ' num2str(newParentID) ' comes after ' num2str(trackID) ' consider a different edit.'],'Parent Change','warn'); return elseif(CellTracks(trackID).endTime < CellTracks(newParentID).startTime) @@ -15,11 +18,11 @@ elseif(CellTracks(trackID).endTime < CellTracks(newParentID).startTime) end oldParent = CellTracks(trackID).parentTrack; -ChangeTrackParent(newParentID,CellTracks(trackID).startTime,trackID); +ChangeTrackParent(newParentID,time,trackID); History('Push'); LogAction(['Changed parent of ' num2str(trackID)],oldParent,newParentID); -DrawTree(CellTracks(trackID).familyID); +DrawTree(CellTracks(newParentID).familyID); DrawCells(); end diff --git a/src/MATLAB/ContextProperties.m b/src/MATLAB/ContextProperties.m index a528f090165b908b4f9711a738993b38956f5a53..7e007c8f2e7dbe471cb6b6a92fa01160798e3eac 100644 --- a/src/MATLAB/ContextProperties.m +++ b/src/MATLAB/ContextProperties.m @@ -1,6 +1,8 @@ function ContextProperties(hullID,trackID) %context menu callback function +%--Eric Wait + global CellTracks Figures %collect all the data that will be passed to the properties UI diff --git a/src/MATLAB/ContextRemoveFromTree.m b/src/MATLAB/ContextRemoveFromTree.m index c32bad1c9ee4759cc46570949611dd1203762fb0..fc187c9f0ce5d29a4354405cc813f6743d0fcb84 100644 --- a/src/MATLAB/ContextRemoveFromTree.m +++ b/src/MATLAB/ContextRemoveFromTree.m @@ -1,10 +1,13 @@ function ContextRemoveFromTree(time,trackID) %context menu callback function + +%--Eric Wait + global CellTracks oldFamilyID = CellTracks(trackID).familyID; -newFamilyID = RemoveFromTree(time, trackID); +newFamilyID = RemoveFromTree(time, trackID,'yes'); History('Push'); LogAction(['Removed part or all of ' num2str(trackID) ' from tree'],oldFamilyID,newFamilyID); diff --git a/src/MATLAB/ConvertTrackingData.m b/src/MATLAB/ConvertTrackingData.m index 8141d4ebe68f7c79d3f0c856557f4dd5013e1cd0..bad774e2072d58db887b1df21f56c50c646ab35d 100644 --- a/src/MATLAB/ConvertTrackingData.m +++ b/src/MATLAB/ConvertTrackingData.m @@ -2,10 +2,12 @@ function ConvertTrackingData(objHulls,gConnect) %Takes the data structure from the tracking data and creates LEVer's data %scheme +%--Eric Wait + global CONSTANTS Costs HashedCells CellHulls CellFamilies %Initialize CONSTANTS -CONSTANTS.ImageSize = unique([objHulls(:).imSize]); +CONSTANTS.imageSize = unique([objHulls(:).imSize]); CONSTANTS.maxPixelDistance = 40; CONSTANTS.maxCenterOfMassDistance = 80; CONSTANTS.minParentCandidateTimeFrame = 5; @@ -23,7 +25,8 @@ CellHulls = struct(... 'time', {objHulls(1).t},... 'points', {objHulls(1).pts},... 'centerOfMass', {objHulls(1).COM},... - 'indexPixels', {objHulls(1).indPixels}); + 'indexPixels', {objHulls(1).indPixels},... + 'deleted', {0}); if objHulls(1).inID == 0 NewCellFamily(1,objHulls(1).t); @@ -37,6 +40,7 @@ for i=2:length(objHulls) CellHulls(i).points = objHulls(i).pts; CellHulls(i).centerOfMass = objHulls(i).COM; CellHulls(i).indexPixels = objHulls(i).indPixels; + CellHulls(i).deleted = 0; if objHulls(i).inID == 0 NewCellFamily(i,objHulls(i).t); diff --git a/src/MATLAB/CreateColors.m b/src/MATLAB/CreateColors.m index 7a41b7fe0026474e9e018bdc1cbeb3c720790970..04f7f8a05ac8bb52989aad6894f07a63a479337a 100644 --- a/src/MATLAB/CreateColors.m +++ b/src/MATLAB/CreateColors.m @@ -4,6 +4,8 @@ function colors = CreateColors() %the text is typicaly white or black depending on the darkness of the %background +%--Eric Wait + colors = [1,0,0,0,0,0,0.4,0.15,0.15;... 1,0.5,0,0,0,0,0.4,0.2,0.15;... 1,1,0,0,0,0,0.4,0.4,0.15;... diff --git a/src/MATLAB/CreateContextMenuCells.m b/src/MATLAB/CreateContextMenuCells.m index 7fc174a8b50c6dd800f162946a1a09c3b053f189..544d213a0434f257c27f8f9a32f4e7cd93161a24 100644 --- a/src/MATLAB/CreateContextMenuCells.m +++ b/src/MATLAB/CreateContextMenuCells.m @@ -2,6 +2,8 @@ function CreateContextMenuCells() %creates the context menu for the figure that displays the image data and %the subsequent function calls +%--Eric Wait + global Figures figure(Figures.cells.handle); @@ -15,16 +17,38 @@ uimenu(Figures.cells.contextMenuHandle,... 'Label', 'Change Parent',... 'CallBack', @changeParent); -uimenu(Figures.cells.contextMenuHandle,... +addHull = uimenu(Figures.cells.contextMenuHandle,... 'Label', 'Add Hull',... - 'CallBack', @addHull,... + 'Separator', 'on'); + +uimenu(addHull,... + 'Label', 'Number of Hulls to add'); + +uimenu(addHull,... + 'Label', '1',... 'Separator', 'on',... - 'Enable', 'off'); + 'CallBack', @addHull1); + +uimenu(addHull,... + 'Label', '2',... + 'CallBack', @addHull2); + +uimenu(addHull,... + 'Label', '3',... + 'CallBack', @addHull3); + +uimenu(addHull,... + 'Label', '4',... + 'CallBack', @addHull4); + +uimenu(addHull,... + 'Label', 'Other',... + 'Separator', 'on',... + 'CallBack', @addHullOther); uimenu(Figures.cells.contextMenuHandle,... 'Label', 'Remove Hull',... - 'CallBack', @removeHull,... - 'Enable', 'off'); + 'CallBack', @removeHull); uimenu(Figures.cells.contextMenuHandle,... 'Label', 'Mark Death',... @@ -43,37 +67,63 @@ end %% Callback functions function changeLabel(src,evnt) -global Figures HashedCells +global Figures -hullID = FindHull(get(gca,'CurrentPoint')); -tempIndex = [HashedCells{Figures.time}.hullID]==hullID; -trackID = HashedCells{Figures.time}(tempIndex).trackID; +[hullID trackID] = getClosestCell(); +if(isempty(trackID)),return,end ContextChangeLabel(Figures.time,trackID); end function changeParent(src,evnt) -global Figures HashedCells +global Figures +[hullID trackID] = getClosestCell(); +if(isempty(trackID)),return,end -hullID = FindHull(get(gca,'CurrentPoint')); -tempIndex = [HashedCells{Figures.time}.hullID]==hullID; -trackID = HashedCells{Figures.time}(tempIndex).trackID; +ContextChangeParent(trackID,Figures.time); +end + +function addHull1(src,evnt) +addHull(1); +end -ContextChangeParent(trackID); +function addHull2(src,evnt) +addHull(2); end -function addHull(src,evnt) +function addHull3(src,evnt) +addHull(3); +end + +function addHull4(src,evnt) +addHull(4); +end + +function addHullOther(src,evnt) +num = inputdlg('Enter Number of Hulls to Add','Add Hulls',1,{1}); +if(isempty(num)),return,end; +num = str2double(num(1)); +addHull(num); end function removeHull(src,evnt) +global Figures + +[hullID trackID] = getClosestCell(); +if(isempty(trackID)),return,end + +RemoveHull(hullID); +History('Push'); +LogAction(['Removed hull from track ' num2str(trackID)],hullID,[]); +DrawTree(Figures.tree.familyID); +DrawCells(); end function markDeath(src,evnt) -global Figures HashedCells CellTracks +global Figures CellTracks -hullID = FindHull(get(gca,'CurrentPoint')); -tempIndex = [HashedCells{Figures.time}.hullID]==hullID; -trackID = HashedCells{Figures.time}(tempIndex).trackID; +[hullID trackID] = getClosestCell(); +if(isempty(trackID)),return,end CellTracks(trackID).timeOfDeath = Figures.time; @@ -83,7 +133,7 @@ if(~isempty(CellTracks(trackID).childrenTracks)) for i=1:length(CellTracks(trackID).childrenTracks) familyIDs = [familyIDs ... RemoveFromTree(CellTracks(CellTracks(trackID).childrenTracks(i)).startTime,... - CellTracks(trackID).childrenTracks(i))]; + CellTracks(trackID).childrenTracks(i),'yes')]; end CellTracks(trackID).childrenTracks = []; ProcessNewborns(familyIDs); @@ -97,20 +147,42 @@ DrawCells(); end function removeFromTree(src,evnt) -global Figures HashedCells +global Figures -hullID = FindHull(get(gca,'CurrentPoint')); -tempIndex = [HashedCells{Figures.time}.hullID]==hullID; -trackID = HashedCells{Figures.time}(tempIndex).trackID; +[hullID trackID] = getClosestCell(); +if(isempty(trackID)),return,end ContextRemoveFromTree(Figures.time,trackID); end function properties(src,evnt) -global Figures HashedCells +[hullID trackID] = getClosestCell(); +if(isempty(trackID)),return,end -hullID = FindHull(get(gca,'CurrentPoint')); -tempIndex = [HashedCells{Figures.time}.hullID]==hullID; -trackID = HashedCells{Figures.time}(tempIndex).trackID; ContextProperties(hullID,trackID); end + +%% Helper functions +function addHull(num) +global Figures + +[hullID trackID] = getClosestCell(); +if(isempty(trackID)),return,end + +newTracks = SplitHull(hullID,num+1);%adding one to the number so that the original hull is accounted for + +History('Push'); +LogAction('Split cell',trackID,[trackID newTracks]); +DrawTree(Figures.tree.familyID); +DrawCells(); +end + +function [hullID trackID] = getClosestCell() +hullID = FindHull(get(gca,'CurrentPoint')); +if(0>=hullID) + warndlg('Please click closer to the center of the desired cell','Unknown Cell'); + trackID = []; + return +end +trackID = GetTrackID(hullID); +end diff --git a/src/MATLAB/CreateContextMenuTree.m b/src/MATLAB/CreateContextMenuTree.m index 70472b0883322fe8e5108210772739ca0174d377..ac1a048c7cc3b43540572c7ad109517a5e35f018 100644 --- a/src/MATLAB/CreateContextMenuTree.m +++ b/src/MATLAB/CreateContextMenuTree.m @@ -2,6 +2,8 @@ function CreateContextMenuTree() %creates the context menu for the figure that displays the tree data and %the subsequent function calls +%--Eric Wait + global Figures figure(Figures.tree.handle); @@ -33,8 +35,9 @@ ContextChangeLabel(CellTracks(trackID).startTime,trackID); end function changeParent(src,evnt) +global CellTracks trackID = get(gco,'UserData'); -ContextChangeParent(trackID); +ContextChangeParent(trackID,CellTracks(trackID).startTime); end function removeFromTree(src,evnt) @@ -45,7 +48,6 @@ end function properties(src,evnt) global CellTracks - trackID = get(gco,'UserData'); ContextProperties(CellTracks(trackID).hulls(1),trackID); end diff --git a/src/MATLAB/CreateMenuBar.m b/src/MATLAB/CreateMenuBar.m index 4a4f530a1cefa25f29d33fc31e48e73e8d5a18bb..2f456f0582f3b6d10150d56aa380561d2810b6ad 100644 --- a/src/MATLAB/CreateMenuBar.m +++ b/src/MATLAB/CreateMenuBar.m @@ -1,6 +1,8 @@ function CreateMenuBar(handle) %This sets up the custom menu bar for the given figure handle +%--Eric Wait + global Figures fileMenu = uimenu(... @@ -98,6 +100,13 @@ uimenu(... 'Callback', @timeJump,... 'Accelerator', 't'); +uimenu(... + 'Parent', viewMenu,... + 'Label', 'Display Largest Tree',... + 'HandleVisibility', 'callback',... + 'Callback', @largestTree,... + 'Separator', 'on'); + if(strcmp(get(handle,'Tag'),'cells')) Figures.cells.menuHandles.saveMenu = saveMenu; @@ -174,3 +183,19 @@ end UpdateTimeIndicatorLine(); DrawCells(); end + +function largestTree(src,evnt) +global CellFamilies Figures + +maxID = 1; +for i=2:length(CellFamilies) + if(length(CellFamilies(maxID).tracks) < length(CellFamilies(i).tracks)) + maxID = i; + end +end +if(Figures.tree.familyID == maxID),return,end + +Figures.tree.familyID = maxID; +DrawTree(maxID); +DrawCells(); +end diff --git a/src/MATLAB/DeleteHullFromTrack.m b/src/MATLAB/DeleteHullFromTrack.m index 67f2a5ca0acbd7994e18eed813c2da0a33bd60f2..e48f2f188b09bfb8bf99ae0c59b7da0eb760978c 100644 --- a/src/MATLAB/DeleteHullFromTrack.m +++ b/src/MATLAB/DeleteHullFromTrack.m @@ -6,4 +6,6 @@ function DeleteHullFromTrack(hullID,trackID) %It is intended that AddHullToTrack will be run after this function, %otherwise this hull will cease to exist in any family or track +%--Eric Wait + end diff --git a/src/MATLAB/DrawCells.m b/src/MATLAB/DrawCells.m index ec170ab94a3b1bbedccd16b5789f91ae1ebb4a4c..301da85cb7b20c10398b88bd9ca4ee204d7dc5aa 100644 --- a/src/MATLAB/DrawCells.m +++ b/src/MATLAB/DrawCells.m @@ -5,6 +5,8 @@ function DrawCells() %will be more boldly colored, others will be with square labels and be %slightly grayed out +%--Eric Wait + global CellFamilies CellTracks CellHulls HashedCells Figures CONSTANTS if(isempty(CellFamilies(Figures.tree.familyID).tracks)),return,end @@ -20,7 +22,8 @@ yl=ylim; %adjust the image display hold off; -imagesc(img); +im = imagesc(img); +set(im,'uicontextmenu',Figures.cells.contextMenuHandle); set(gca,'Position',[.01 .01 .98 .98],'uicontextmenu',Figures.cells.contextMenuHandle); axis off; if xl(1)~=0 && xl(2)~=1 diff --git a/src/MATLAB/DrawTree.m b/src/MATLAB/DrawTree.m index bf464e404b227925763f208536d2b4e5b8fd598d..9afd693de35fa164300d2bb552b28683d12af661 100644 --- a/src/MATLAB/DrawTree.m +++ b/src/MATLAB/DrawTree.m @@ -1,10 +1,16 @@ function DrawTree(familyID) -%This will draw the family tree of the given family. Assumes binary tree +%This will draw the family tree of the given family. + +%--Eric Wait global CellFamilies HashedCells Figures if(isempty(CellFamilies(familyID).tracks)),return,end +%let the user know that this might take a while +set(Figures.tree.handle,'Pointer','watch'); +set(Figures.cells.handle,'Pointer','watch'); + Figures.tree.familyID = familyID; trackID = CellFamilies(familyID).tracks(1); @@ -27,6 +33,10 @@ set(gca,... Figures.tree.axesHandle = gca; hold off UpdateTimeIndicatorLine(); + +%let the user know that the drawing is done +set(Figures.tree.handle,'Pointer','arrow'); +set(Figures.cells.handle,'Pointer','arrow'); end function [xMin xCenter xMax] = traverseTree(trackID,initXmin) diff --git a/src/MATLAB/ExportImage.m b/src/MATLAB/ExportImage.m index fc07b4d76a88fc8d24a638aa503e2eccb4d4874f..247a888f8757f4086ffe572963a606a53695eb1c 100644 --- a/src/MATLAB/ExportImage.m +++ b/src/MATLAB/ExportImage.m @@ -2,6 +2,8 @@ function ExportImage(figureHandle) %this function is intended to create a high resolution file of the given %figure for printing or sharing +%--Eric Wait + global Figures if(figureHandle == Figures.cells.handle) diff --git a/src/MATLAB/FindHull.m b/src/MATLAB/FindHull.m index cb4556ed749112bb22483629b73db00ca93c8eba..aab175210f1c29b5e182c56a66935a6bbebfe027 100644 --- a/src/MATLAB/FindHull.m +++ b/src/MATLAB/FindHull.m @@ -2,6 +2,8 @@ function hullID = FindHull(curPoint) %This function will find the closest hull to the given point and return the %hullID if it is within CONSTANTS.clickMargin +%--Eric Wait + global CONSTANTS CellHulls HashedCells Figures centerOfMasses = reshape([CellHulls([HashedCells{Figures.time}(:).hullID]).centerOfMass]',2,[])'; diff --git a/src/MATLAB/GetNextColor.m b/src/MATLAB/GetNextColor.m index ddc3f5a5f7ff3a1b44e469310989dabb25dad480..63d7ab1d10d1dffafbf4d17240b3f3a3dc7fedce 100644 --- a/src/MATLAB/GetNextColor.m +++ b/src/MATLAB/GetNextColor.m @@ -2,6 +2,8 @@ function color = GetNextColor() %Takes the global Colors list and selects the next in the list and returns %it +%--Eric Wait + global Colors persistent index diff --git a/src/MATLAB/GetTrackID.m b/src/MATLAB/GetTrackID.m index aeac124982d49dab353be1e7a4cbec4e453f86c5..856b576c98755f2f003c73ec42a1f3abd32aa99a 100644 --- a/src/MATLAB/GetTrackID.m +++ b/src/MATLAB/GetTrackID.m @@ -1,6 +1,8 @@ function trackID = GetTrackID(hullID) %Given a hull ID a track ID will be returned +%--Eric Wait + global CellHulls HashedCells hullTime = CellHulls(hullID).time; diff --git a/src/MATLAB/GrayOutColor.m b/src/MATLAB/GrayOutColor.m index 8529fe2a8a22cf78252ad74ec1d0f0eb0b340408..1972f7b24fb933c3acc670a475c0a25cbf3f6ebe 100644 --- a/src/MATLAB/GrayOutColor.m +++ b/src/MATLAB/GrayOutColor.m @@ -1,7 +1,9 @@ function grayedColor = GrayOutColor(color) -%this will take the given color and give back a grayed out color of similar +%This will take the given color and give back a grayed out color of similar %hue +%--Eric Wait + grayedColor = [0 0 0]; parfor i=1:3 if(0==color(i)) diff --git a/src/MATLAB/History.m b/src/MATLAB/History.m index cc2aad3268369497217bcc3e36d909590ff83648..ed2d84e58f2f1edf1950ad1b25e2fb4890da49a1 100644 --- a/src/MATLAB/History.m +++ b/src/MATLAB/History.m @@ -1,5 +1,6 @@ function History(action) -%This will keep track of any state changes. +%This will keep track of any state changes. Call this function once the +%new state is established. After the changes take place. %Possible actions are: %History('Push') = save current state to the stack %History('Pop') = retrive the last state @@ -10,158 +11,194 @@ function History(action) %All of the data structures are saved on the stack, so do not set this %value too high or you might run out of working memory +%--Eric Wait + global CellFamilies CellTracks HashedCells CONSTANTS Figures CellHulls -persistent hist; -persistent top; -persistent bottom; -persistent redo; -persistent empty; -persistent full; +persistent hist; %stack +persistent current; %points to the last state saved on the stack +persistent bottom; %points to the oldest or bottom most valid history +persistent top; %points to the youngest or top most valid history +persistent empty; %flag will be "empty" if only the original opened state is on the stack +persistent full; %flag +persistent exceededLimit; %flag to denote if CONSTANTS.historySize has ever been reached if (isempty(hist)) - top = 1;%points to next place to push or is one greater than the current history - bottom = 0;%points to the oldest or bottom most valid history - redo = 0;%points to the youngest or top most valid history - empty = 1;%flag will be "empty" if only the original opened state is on the stack - full = 0;%flag + current = 1; + bottom = 0; + top = 0; + empty = 1; + full = 0; + exceededLimit = 0; end switch action case 'Push' - set(Figures.cells.menuHandles.undoMenu,'Enable','on'); - set(Figures.cells.menuHandles.saveMenu,'Enable','on'); - set(Figures.tree.menuHandles.undoMenu,'Enable','on'); - set(Figures.tree.menuHandles.saveMenu,'Enable','on'); if (empty) empty = 0; bottom = 1; elseif (full) %drop oldest history + exceededLimit = 1; if (bottom < CONSTANTS.historySize) bottom = bottom + 1; else bottom = 1; end end - - hist(top).CellFamilies = CellFamilies; - hist(top).CellTracks = CellTracks; - hist(top).HashedCells = HashedCells; - hist(top).CellHulls = CellHulls; - hist(top).Figures.tree.familyID = Figures.tree.familyID; - - redo = top; - top = top + 1; - if (top > CONSTANTS.historySize) - top = 1; + current = current + 1; + if (current > CONSTANTS.historySize) + current = 1; end - if (top==bottom) + top = current; + + hist(current).CellFamilies = CellFamilies; + hist(current).CellTracks = CellTracks; + hist(current).HashedCells = HashedCells; + hist(current).CellHulls = CellHulls; + hist(current).Figures.tree.familyID = Figures.tree.familyID; + + if (current==bottom) full = 1; empty = 0; end - - %"Disable" redo - set(Figures.cells.menuHandles.redoMenu,'Enable','off'); - set(Figures.tree.menuHandles.redoMenu,'Enable','off'); - + setMenus(); case 'Pop' if (~empty) - if(redo < top) - top = top - 2; - else - top = top - 1; - end - if (top == 0) - top = CONSTANTS.historySize; + current = current - 1; + if (current == 0) + current = CONSTANTS.historySize; end full = 0; - if (top==bottom) + if (current==bottom) empty = 1; - set(Figures.cells.menuHandles.undoMenu,'Enable','off'); - set(Figures.cells.menuHandles.saveMenu,'Enable','off'); - set(Figures.tree.menuHandles.undoMenu,'Enable','off'); - set(Figures.tree.menuHandles.saveMenu,'Enable','off'); - else - set(Figures.cells.menuHandles.saveMenu,'Enable','on'); - set(Figures.tree.menuHandles.saveMenu,'Enable','on'); - end - - CellFamilies = hist(top).CellFamilies; - CellTracks = hist(top).CellTracks; - HashedCells = hist(top).HashedCells; - CellHulls = hist(top).CellHulls; - Figures.tree.familyID = hist(top).Figures.tree.familyID; - - %increment again so that top is always the next available place - top = top + 1; - if (top > CONSTANTS.historySize) - top = 1; end - set(Figures.cells.menuHandles.redoMenu,'Enable','on'); - set(Figures.tree.menuHandles.redoMenu,'Enable','on'); + CellFamilies = hist(current).CellFamilies; + CellTracks = hist(current).CellTracks; + HashedCells = hist(current).HashedCells; + CellHulls = hist(current).CellHulls; + Figures.tree.familyID = hist(current).Figures.tree.familyID; %Update displays DrawTree(Figures.tree.familyID); DrawCells(); - + setMenus(); LogAction('Undo',[],[]); - else - set(Figures.cells.menuHandles.redoMenu,'Enable','off'); - set(Figures.tree.menuHandles.redoMenu,'Enable','off'); end - case 'Redo' - if (redo>=top || (top<bottom && redo<top)) + if (top>current || (bottom>top && top~=current)) %redo possible - - CellFamilies = hist(top).CellFamilies; - CellTracks = hist(top).CellTracks; - HashedCells = hist(top).HashedCells; - CellHulls = hist(top).CellHulls; - Figures.tree.familyID = hist(top).Figures.tree.familyID; - - %increment again so that top is always the next available place - top = top + 1; - if (top > CONSTANTS.historySize) - top = 1; + current = current + 1; + if (current > CONSTANTS.historySize) + current = 1; end + CellFamilies = hist(current).CellFamilies; + CellTracks = hist(current).CellTracks; + HashedCells = hist(current).HashedCells; + CellHulls = hist(current).CellHulls; + Figures.tree.familyID = hist(current).Figures.tree.familyID; + empty = 0; - if(top==bottom) + if(current==bottom) full = 1; end %Update displays DrawTree(Figures.tree.familyID); DrawCells(); - - if (top>redo) + setMenus(); + LogAction('Redo',[],[]); + end + case 'Init' + current = 1; + bottom = 1; + top = 1; + empty = 0; + full = 0; + exceededLimit = 0; + hist(current).CellFamilies = CellFamilies; + hist(current).CellTracks = CellTracks; + hist(current).HashedCells = HashedCells; + hist(current).CellHulls = CellHulls; + hist(current).Figures.tree.familyID = Figures.tree.familyID; + set(Figures.cells.menuHandles.redoMenu,'Enable','off'); + set(Figures.tree.menuHandles.redoMenu,'Enable','off'); + set(Figures.cells.menuHandles.undoMenu,'Enable','off'); + set(Figures.tree.menuHandles.undoMenu,'Enable','off'); + set(Figures.cells.menuHandles.saveMenu,'Enable','off'); + set(Figures.tree.menuHandles.saveMenu,'Enable','off'); +end + + function setMenus() + if(top>bottom) + %not "rolled over" + if(current<top) + %redo possible + set(Figures.cells.menuHandles.redoMenu,'Enable','on'); + set(Figures.tree.menuHandles.redoMenu,'Enable','on'); + else set(Figures.cells.menuHandles.redoMenu,'Enable','off'); - set(Figures.cells.menuHandles.undoMenu,'Enable','on'); set(Figures.tree.menuHandles.redoMenu,'Enable','off'); + end + if(current>bottom) + %undo possible + set(Figures.cells.menuHandles.undoMenu,'Enable','on'); + set(Figures.tree.menuHandles.undoMenu,'Enable','on'); + else + set(Figures.cells.menuHandles.undoMenu,'Enable','off'); + set(Figures.tree.menuHandles.undoMenu,'Enable','off'); + end + elseif(top==bottom && ~empty) + if(current~=top) + %redo and undo possible + set(Figures.cells.menuHandles.redoMenu,'Enable','on'); + set(Figures.tree.menuHandles.redoMenu,'Enable','on'); + set(Figures.cells.menuHandles.undoMenu,'Enable','on'); set(Figures.tree.menuHandles.undoMenu,'Enable','on'); + else + set(Figures.cells.menuHandles.redoMenu,'Enable','off'); + set(Figures.tree.menuHandles.redoMenu,'Enable','off'); + set(Figures.cells.menuHandles.undoMenu,'Enable','off'); + set(Figures.tree.menuHandles.undoMenu,'Enable','off'); end + else + %"rolled over" + if(current>=bottom || current<top) + %redo possible + set(Figures.cells.menuHandles.redoMenu,'Enable','on'); + set(Figures.tree.menuHandles.redoMenu,'Enable','on'); + else + set(Figures.cells.menuHandles.redoMenu,'Enable','off'); + set(Figures.tree.menuHandles.redoMenu,'Enable','off'); + end + if(current>bottom || current<=top) + %undo possible + set(Figures.cells.menuHandles.undoMenu,'Enable','on'); + set(Figures.tree.menuHandles.undoMenu,'Enable','on'); + else + set(Figures.cells.menuHandles.undoMenu,'Enable','off'); + set(Figures.tree.menuHandles.undoMenu,'Enable','off'); + end + end + + %check to see if we are at the original state from the .mat file + if(exceededLimit) set(Figures.cells.menuHandles.saveMenu,'Enable','on'); set(Figures.tree.menuHandles.saveMenu,'Enable','on'); - LogAction('Redo',[],[]); + else + if(empty) + set(Figures.cells.menuHandles.saveMenu,'Enable','off'); + set(Figures.tree.menuHandles.saveMenu,'Enable','off'); + else + set(Figures.cells.menuHandles.saveMenu,'Enable','on'); + set(Figures.tree.menuHandles.saveMenu,'Enable','on'); + end end - case 'Init' - top = 1; - bottom = 1; - redo = 1; - empty = 0; - full = 0; - hist(top).CellFamilies = CellFamilies; - hist(top).CellTracks = CellTracks; - hist(top).HashedCells = HashedCells; - hist(top).CellHulls = CellHulls; - hist(top).Figures.tree.familyID = Figures.tree.familyID; - top = 2; -end + end %setMenu end diff --git a/src/MATLAB/InSubTree.m b/src/MATLAB/InSubTree.m index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..10d43adb529ec5d57cd77e4d8a3be29afaf51b3f 100644 --- a/src/MATLAB/InSubTree.m +++ b/src/MATLAB/InSubTree.m @@ -0,0 +1,42 @@ +function bool = InSubTree(rootTrack,questionTrack) +% InSubTree(rootTrack,questionTrack) will return a flag which represents +% whether or not the questionTrack falls within the subtree rooted at +% rootTrack + +%--Eric Wait + +global CellTracks +bool = 0; + +%check if they are in the same family +if(CellTracks(rootTrack).familyID ~= CellTracks(questionTrack).familyID),return,end + +%check if the track in question exists after the root +if(CellTracks(rootTrack).endTime > CellTracks(questionTrack).startTime),return,end + +bool = traverse(rootTrack,questionTrack); +end + +function bool = traverse(rootTrack,questionTrack) +%modified depth first search wich does not go passed the time of the +%questionTrack + +global CellTracks + +bool = 0; + +if (rootTrack == questionTrack) + bool = 1; + return +elseif (CellTracks(rootTrack).endTime > CellTracks(questionTrack).startTime) + return +end + +for i=1:length(CellTracks(rootTrack).childrenTracks) + bool = traverse(CellTracks(rootTrack).childrenTracks(i),questionTrack); + %once found, return + if(bool) + return + end +end +end diff --git a/src/MATLAB/InitializeFigures.m b/src/MATLAB/InitializeFigures.m index 16e63ce607d3a9bc8724d2faab0f3543a2c98c85..6fbebddfc2e04edcd0e785743023f1f058fa7f56 100644 --- a/src/MATLAB/InitializeFigures.m +++ b/src/MATLAB/InitializeFigures.m @@ -4,6 +4,8 @@ function InitializeFigures() %Figures will have all the menus, button actions, and context menus set up %here +%--Eric Wait + global Figures CONSTANTS Figures.time = 1; diff --git a/src/MATLAB/LEVer.m b/src/MATLAB/LEVer.m index 8c121922b828e983559b09bbb46ef3ad0585d95d..4752b1f653f68949405739cbacf0aa4842dfd7d4 100644 --- a/src/MATLAB/LEVer.m +++ b/src/MATLAB/LEVer.m @@ -1,4 +1,8 @@ function LEVer() +%Main program + +%--Eric Wait + global Figures %if LEVer is already opened, save state just in case the User cancels the diff --git a/src/MATLAB/LogAction.m b/src/MATLAB/LogAction.m index e6537f2ccc68d1977b6f83cdadcf7936d7a3f693..fda88eddadf2dbeb4630af5e994d855664f1adc5 100644 --- a/src/MATLAB/LogAction.m +++ b/src/MATLAB/LogAction.m @@ -5,6 +5,8 @@ function LogAction(action,oldValue,newValue) %oldValue and newValue are used to show what numbers are changed. Please %use the action string to denote what the values represent +%--Eric Wait + global Figures CONSTANTS time = clock;%[year month day hour minute seconds] diff --git a/src/MATLAB/NewCellFamily.m b/src/MATLAB/NewCellFamily.m index 9bae982004c4b2c134880c8cbd1ba2a61a0cc73d..a7d130f6800bf2e149469cf52e2f5b717a4e2fae 100644 --- a/src/MATLAB/NewCellFamily.m +++ b/src/MATLAB/NewCellFamily.m @@ -1,4 +1,9 @@ function curFamilyID = NewCellFamily(cellHullID,t) +%Create a empty Family that will contain one track that contains only one +%hull + +%--Eric Wait + global CellFamilies if(isempty(CellFamilies)) diff --git a/src/MATLAB/NewCellTrack.m b/src/MATLAB/NewCellTrack.m index 87c4a14c76e4ee6d1a5d6ffc001e3effd1354c27..6f5b311653db80d093515012bbaddaae03ab88f6 100644 --- a/src/MATLAB/NewCellTrack.m +++ b/src/MATLAB/NewCellTrack.m @@ -1,4 +1,9 @@ function curCellTrackID = NewCellTrack(familyID,cellHullID,t) +%Creates a new track in the Family that contains just the given hull. +%***Use this with empty Families only*** + +%--Eric Wait + global CellTracks curCellTrackID = 1; diff --git a/src/MATLAB/OpenData.m b/src/MATLAB/OpenData.m index e2b4f237e2921aed1ee7ad3afb95d4c7f1ed764b..6506455d56a214e8a82266b0295dc3fd8c8fec14 100644 --- a/src/MATLAB/OpenData.m +++ b/src/MATLAB/OpenData.m @@ -3,9 +3,11 @@ function opened = OpenData() %results. If the latter, the data will be converted to LEVer's data scheme %and save out to a new file. +%--Eric Wait + global Figures Colors CONSTANTS CellFamilies CellHulls HashedCells Costs CellTracks if(isempty(Figures)) - fprintf('LEVer ver 3.0\n***DO NOT DISTRIBUTE***\n\n'); + fprintf('LEVer ver 3.1\n***DO NOT DISTRIBUTE***\n\n'); end if(exist('ColorScheme.mat','file')) diff --git a/src/MATLAB/ProcessNewborns.m b/src/MATLAB/ProcessNewborns.m index ee67775e5f62f3565c48d83469ba2a866dc80dba..e1eee9cf8549374f5c2fe46d3bc1f0827ac012f7 100644 --- a/src/MATLAB/ProcessNewborns.m +++ b/src/MATLAB/ProcessNewborns.m @@ -2,6 +2,8 @@ function ProcessNewborns(families) %This takes all the families with start times > 1 and attempts to attach %that families' tracks to other families that start before said family +%--Eric Wait + global CellFamilies CellTracks CellHulls Costs CONSTANTS size = length(families); for i=1:size diff --git a/src/MATLAB/RehashCellTracks.m b/src/MATLAB/RehashCellTracks.m index da27879244541a6169c25dd96465cd3886c585f8..4e6ef60805c4354dc455ca1529e88de6dbe7f1b1 100644 --- a/src/MATLAB/RehashCellTracks.m +++ b/src/MATLAB/RehashCellTracks.m @@ -1,25 +1,30 @@ function RehashCellTracks(trackID, newStartTime) -%This function will rearange the hulls in the given track so that the -%newTime will hash correctly +%RehashedCellTracks(trackID,newStartTime) will rearange the hulls in the +%given track so that the newTime will hash correctly. %The hulls are hashed so that the index into the cell array is time of hull %subtract start time of track. eg hash = time of hull - %CellTracks(i).startTime % +%If newStartTime == oldStartTime, only the endTime will change. Good for +%removing all of the 0's at the end of the hulls list for a given track. +% %***WARNING*** if oldStartTime < newStartTime and there are hulls within %[oldStartTime newStartTime) THEY WILL BE REMOVED FROM THE TRACK!!! +%--Eric Wait + global CellTracks CellHulls dif = CellTracks(trackID).startTime - newStartTime; -if(sign(dif)) +if(0<dif) for i=length(CellTracks(trackID).hulls):-1:1 CellTracks(trackID).hulls(i+dif) = CellTracks(trackID).hulls(i); end for i=1:dif CellTracks(trackID).hulls(i) = 0; end -else +elseif(0>dif) oldLength = length(CellTracks(trackID).hulls); for i=1-dif:length(CellTracks(trackID).hulls) CellTracks(trackID).hulls(i+dif) = CellTracks(trackID).hulls(i); @@ -35,4 +40,6 @@ if(indexOfLastHull~=length(CellTracks(trackID).hulls)) CellTracks(trackID).hulls = CellTracks(trackID).hulls(1:indexOfLastHull); CellTracks(trackID).endTime = CellHulls(CellTracks(trackID).hulls(end)).time; end + +CellTracks(trackID).startTime = newStartTime; end diff --git a/src/MATLAB/RemoveFromTree.m b/src/MATLAB/RemoveFromTree.m index 98b1635333f6472cc624e8f7a5b9d265ba04a4e3..7064453dce414cf8c13bc43275af724d74b08a38 100644 --- a/src/MATLAB/RemoveFromTree.m +++ b/src/MATLAB/RemoveFromTree.m @@ -1,6 +1,14 @@ -function newFamilyID = RemoveFromTree(time,trackID) +function newFamilyID = RemoveFromTree(time,trackID,combineSiblingWithParent) +%newFamily = RemoveFromTree(time,trackID,dealWithSibling) %This will remove the track and any of its children from its current family %and create a new family rooted at the given track +%If you want the current track's sibling to be combined with its parent, +%pass combineSiblingWithParent='yes' otherwise 'no' +% +%***IF YOU PASS 'NO', YOU MUST DEAL WITH ANY SIBLING YOURSELF!!! OTHERWISE +%THERE WILL BE ISSUES WITH THE DATA**** + +%--Eric Wait global CellFamilies CellTracks CellHulls @@ -8,8 +16,9 @@ hash = time - CellTracks(trackID).startTime + 1; oldFamilyID = CellTracks(trackID).familyID; newFamilyID = NewCellFamily(CellTracks(trackID).hulls(hash),time); newTrackID = CellFamilies(newFamilyID).rootTrackID; +CellTracks(trackID).hulls(hash) = 0; -for i=0:length(CellTracks(trackID).hulls(hash+1:end)) +for i=1:length(CellTracks(trackID).hulls(hash:end))-1 if(CellTracks(trackID).hulls(hash+i)~=0) AddHullToTrack(CellTracks(trackID).hulls(hash+i),newTrackID,[]); end @@ -20,29 +29,37 @@ for i=1:length(CellTracks(trackID).childrenTracks) ChangeTrackAndChildrensFamily(oldFamilyID,newFamilyID,CellTracks(trackID).childrenTracks(i)); CellTracks(CellTracks(trackID).childrenTracks(i)).parentTrack = newTrackID; end -index = CellFamilies(oldFamilyID).tracks == trackID; -CellFamilies(oldFamilyID).tracks(index) = []; -CellFamilies(newFamilyID).tracks(end+1) = newTrackID; + +if(~isempty(find(CellFamilies(oldFamilyID).tracks==newTrackID, 1))) + CellFamilies(newFamilyID).tracks(end+1) = newTrackID; +end CellTracks(newTrackID).familyID = newFamilyID; CellTracks(newTrackID).childrenTracks = CellTracks(trackID).childrenTracks; +for i=1:length(CellTracks(newTrackID).childrenTracks) + CellTracks(CellTracks(newTrackID).childrenTracks(i)).parentTrack = newTrackID; +end +CellTracks(trackID).childrenTracks = []; %clean up old track if(isempty(find([CellTracks(trackID).hulls]~=0, 1))) - if(~isempty(CellTracks(trackID).siblingTrack)) - if(~isempty(CellTracks(CellTracks(trackID).parentTrack).startTime)) + if(~isempty(CellTracks(trackID).siblingTrack)&& strcmp(combineSiblingWithParent,'yes')) +% if(~isempty(CellTracks(CellTracks(trackID).parentTrack).startTime)) CombineTrackWithParent(CellTracks(trackID).siblingTrack); - end +% end + end + RemoveTrackFromFamily(trackID); + if(~isempty(CellTracks(trackID).parentTrack)) + index = CellTracks(CellTracks(trackID).parentTrack).childrenTracks==trackID; + CellTracks(CellTracks(trackID).parentTrack).childrenTracks(index) = []; end CellTracks(trackID).familyID = []; CellTracks(trackID).parentTrack = []; CellTracks(trackID).siblingTrack = []; - CellTracks(trackID).childrenTracks = []; CellTracks(trackID).hulls = []; CellTracks(trackID).startTime = []; CellTracks(trackID).endTime = []; CellTracks(trackID).color = []; else - CellTracks(trackID).childrenTracks = []; index = find([CellTracks(trackID).hulls]~=0, 1,'last'); CellTracks(trackID).endTime = CellHulls(CellTracks(trackID).hulls(index)).time; end diff --git a/src/MATLAB/RemoveHull.m b/src/MATLAB/RemoveHull.m new file mode 100644 index 0000000000000000000000000000000000000000..91d039c4fb51b8573194e9aca0ce742846f7b29e --- /dev/null +++ b/src/MATLAB/RemoveHull.m @@ -0,0 +1,28 @@ +function RemoveHull(hullID) +% RemoveHull(hullID) will LOGICALLY remove the hull. Which means that the +% hull will have a flag set that means that it does not exist anywhere and +% should not be drawn on the cells figure + +%--Eric Wait + +global CellTracks HashedCells CellHulls + +trackID = GetTrackID(hullID); + +%remove hull from its track +index = find(CellTracks(trackID).hulls==hullID); +CellTracks(trackID).hulls(index) = 0; +if(1==index) + index = find(CellTracks(trackID).hulls,1,'first'); + RehashCellTracks(trackID,CellHulls(CellTracks(trackID).hulls(index)).time); +elseif(index==length(CellTracks(trackID).hulls)) + RehashCellTracks(trackID,CellTracks(trackID).startTime); +end + +%remove hull from HashedCells +time = CellHulls(hullID).time; +index = [HashedCells{time}.hullID]==hullID; +HashedCells{time}(index) = []; + +CellHulls(hullID).deleted = 1; +end diff --git a/src/MATLAB/RemoveTrackFromFamily.m b/src/MATLAB/RemoveTrackFromFamily.m new file mode 100644 index 0000000000000000000000000000000000000000..cf564045eed8a1ab5fe0e28e18801a2915bfd147 --- /dev/null +++ b/src/MATLAB/RemoveTrackFromFamily.m @@ -0,0 +1,28 @@ +function RemoveTrackFromFamily(trackID) +% RemoveTrackFromFamily(trackID) only removes the track from the tracks +% list currently assosiated in the CellFamily entery and updated the other +% CellFamily fields. +% This is not intended to change the structure, just to keep the data +% correct + +%--Eric Wait + +global CellFamilies CellTracks +familyID = CellTracks(trackID).familyID; +if(isempty(familyID)),return,end + +index = CellFamilies(familyID).tracks==trackID; + +%remove track +CellFamilies(familyID).tracks(index) = []; + +%update times +[minimum index] = min([CellTracks(CellFamilies(familyID).tracks).startTime]); +CellFamilies(familyID).startTime = minimum; +CellFamilies(familyID).endTime = max([CellTracks(CellFamilies(familyID).tracks).endTime]); + +%set new root +if(CellFamilies(familyID).rootTrackID == trackID) + CellFamilies(familyID).rootTrackID = CellFamilies(familyID).tracks(index); +end +end diff --git a/src/MATLAB/ResegmentHull.m b/src/MATLAB/ResegmentHull.m new file mode 100644 index 0000000000000000000000000000000000000000..dc58f94af6c03eecc22ed1f6d719862fea894dcd --- /dev/null +++ b/src/MATLAB/ResegmentHull.m @@ -0,0 +1,48 @@ +function newHulls = ResegmentHull(hull, k) +% Splits hull int k pieces using kmeans, returns the k split hulls or [] if +% there are errors. + +%--Mark Winter + +global CONSTANTS + +newHulls = []; + +% k-means clustering of (x,y) coordinates of cell interior +[r c] = ind2sub(CONSTANTS.imageSize, hull.indexPixels); +kIdx = kmeans([c,r], k, 'Replicates',5, 'EmptyAction','drop'); + +if ( any(isnan(kIdx)) ) + return; +end + +nh = struct('time', [], 'points', [], 'centerOfMass', [], 'indexPixels', [], 'deleted', 0); +for i=1:k + bIdxPix = (kIdx == i); + + hx = c(bIdxPix); + hy = r(bIdxPix); + + % If any sub-object is less than 15 pixels then cannot split this + % hull + if ( nnz(bIdxPix) < 15 ) + newHulls = []; + return; + end + + nh.indexPixels = hull.indexPixels(bIdxPix); + nh.centerOfMass = mean([hx hy]); + nh.time = hull.time; + + try + chIdx = convhull(hx, hy); + catch excp + newHulls = []; + return; + end + + nh.points = [hx(chIdx) hy(chIdx)]; + + newHulls = [newHulls nh]; +end +end diff --git a/src/MATLAB/SaveData.m b/src/MATLAB/SaveData.m index e4f57dfe3c6c1471d5b49dbe9f021a1fc7b1ea22..03269839817b3e1bdc87a4d67c8c56a95dfd2964 100644 --- a/src/MATLAB/SaveData.m +++ b/src/MATLAB/SaveData.m @@ -1,14 +1,21 @@ function SaveData() %This will save the current state back to the opened dataset -global CellFamilies CellTracks HashedCells CONSTANTS Costs CellHulls + +%--Eric Wait + +global CellFamilies CellTracks HashedCells CONSTANTS Costs CellHulls Figures if (exist('LEVerSettings.mat','file')~=0) load('LEVerSettings.mat'); else - settings.matPath = ['.\' CONSTANTS.datasetName '_v3.mat']; + settings.matPath = ['.\' CONSTANTS.datasetName '_LEVer_edits.mat']; end -save(settings.matPath,... +%let the user know that this might take a while +set(Figures.tree.handle,'Pointer','watch'); +set(Figures.cells.handle,'Pointer','watch'); + +save([settings.matFilePath CONSTANTS.datasetName '_LEVer_edits.mat'],... 'CellFamilies','CellHulls','CellTracks','HashedCells','Costs','CONSTANTS'); %no longer "dirty" @@ -16,4 +23,8 @@ set(Figures.tree.menuHandles.saveMenu,'Enable','off'); set(Figures.cells.menuHandles.saveMenu,'Enable','off'); LogAction('Saved',[],[]); + +%let the user know that the drawing is done +set(Figures.tree.handle,'Pointer','arrow'); +set(Figures.cells.handle,'Pointer','arrow'); end diff --git a/src/MATLAB/SaveDataAs.m b/src/MATLAB/SaveDataAs.m index 327c01ba3727f32bb5e4291584fb669b8e921412..b0af3b07fe8f43d1de707786c85c568ddc24366e 100644 --- a/src/MATLAB/SaveDataAs.m +++ b/src/MATLAB/SaveDataAs.m @@ -1,4 +1,8 @@ function SaveDataAs() +%Save the current state to a user defined dir + +%--Eric Wait + global CellFamilies CellTracks HashedCells CONSTANTS Costs CellHulls Figures if (exist('LEVerSettings.mat','file')~=0) diff --git a/src/MATLAB/SiblingDistance.m b/src/MATLAB/SiblingDistance.m index 129cb9be2afac8ae065b16698fdb56392e71e91c..bc3fd117fa0ce3299ee58c290c396dd3ba8bce2b 100644 --- a/src/MATLAB/SiblingDistance.m +++ b/src/MATLAB/SiblingDistance.m @@ -4,8 +4,9 @@ function distance = SiblingDistance(cell1HullID,cell2HullID) %and maxPixelDistance. Make sure they are set in the global CONSTANTS %variable. +%--Eric Wait + global CellHulls CONSTANTS -distance = Inf; pixelsCell1 = CellHulls(cell1HullID).indexPixels; pixelsCell2 = CellHulls(cell2HullID).indexPixels; @@ -16,8 +17,8 @@ if (length(pixelsCell2) < length(pixelsCell1)) pixelsCell2 = temp; end -[yCell1 xCell1] = ind2sub(CONSTANTS.ImageSize,pixelsCell1); -[yCell2 xCell2] = ind2sub(CONSTANTS.ImageSize,pixelsCell2); +[yCell1 xCell1] = ind2sub(CONSTANTS.imageSize,pixelsCell1); +[yCell2 xCell2] = ind2sub(CONSTANTS.imageSize,pixelsCell2); minPixelDistance = Inf; diff --git a/src/MATLAB/SplitHull.m b/src/MATLAB/SplitHull.m new file mode 100644 index 0000000000000000000000000000000000000000..7e8bebccf1edadbe6e8d0946fe410804928445e4 --- /dev/null +++ b/src/MATLAB/SplitHull.m @@ -0,0 +1,25 @@ +function newTrackIDs = SplitHull(hullID, k) +% Attempt to split hull corresponding to hullId into k pieces, and update +% associated data structures if successful. + +%--Mark Winter + +global CellHulls + +newHulls = ResegmentHull(CellHulls(hullID), k); + +if ( isempty(newHulls) ) + return; +end + +% Just arbitrarily assign clone's hull for now +CellHulls(hullID) = newHulls(1); + +newTrackIDs = [length(CellHulls)+1 length(CellHulls)+length(newHulls)]; +% Other hulls are just added off the clone +for i=2:length(newHulls) + CellHulls(end+i-1) = newHulls(i); + NewCellFamily(length(CellHulls), newHulls(i).time); +end + +end diff --git a/src/MATLAB/SplitTrack.m b/src/MATLAB/SplitTrack.m index 22f9815396ff977d7485e2b40a273a86ef725525..944b5691da57134760b1ae5e8492b6a36a4e25bc 100644 --- a/src/MATLAB/SplitTrack.m +++ b/src/MATLAB/SplitTrack.m @@ -4,6 +4,8 @@ function newTrackID = SplitTrack(trackID,hullID) %given track. Returns the trackID of the new track, which is the first %child of the given track. +%--Eric Wait + global CellFamilies CellTracks %get all the hulls that come after hullID (in time that is) diff --git a/src/MATLAB/SwapTrackLabels.m b/src/MATLAB/SwapTrackLabels.m index 5d036872f50eda5543eda0099572aa21cb9f06d0..63fa5fbe3753e9be0bde3704a8390f47bc2b2900 100644 --- a/src/MATLAB/SwapTrackLabels.m +++ b/src/MATLAB/SwapTrackLabels.m @@ -2,6 +2,8 @@ function SwapTrackLabels(time,trackID1,trackID2) %This function will swap the hulls of the two tracks from the given time %forward. Any children will also be swaped +%--Eric Wait + global CellTracks CellHulls track1Hash = time - CellTracks(trackID1).startTime + 1; diff --git a/src/MATLAB/TimeChange.m b/src/MATLAB/TimeChange.m index 0a7bf2548725b44761066759136bff0ac57d60fe..05dea7652652dc91265d544c50cb3691e3d9d731 100644 --- a/src/MATLAB/TimeChange.m +++ b/src/MATLAB/TimeChange.m @@ -2,6 +2,8 @@ function TimeChange(time) %Takes the given time and changes the figures to that time or the closest %time within [1 length(HashedCells)] +%--Eric Wait + global Figures HashedCells if(time > length(HashedCells)) diff --git a/src/MATLAB/TogglePlay.m b/src/MATLAB/TogglePlay.m index b067bcc022670facbf95994a87dfa8bfd9fca796..214b7d2e367bbb77c40f820de403c0759642eb49 100644 --- a/src/MATLAB/TogglePlay.m +++ b/src/MATLAB/TogglePlay.m @@ -1,5 +1,10 @@ function TogglePlay(src,evnt) +% Turn the timer on and off depending on previous state + +%--Eric Wait + global Figures + if(strcmp(Figures.advanceTimerHandle.Running,'off')) set(Figures.cells.menuHandles.playMenu, 'Checked', 'on'); start(Figures.advanceTimerHandle); diff --git a/src/MATLAB/UpdateHashedCellsTrackID.m b/src/MATLAB/UpdateHashedCellsTrackID.m index 9826e2cccdc225bdee85dda4fd5e288e245af774..d803e733080d8f2724e39b05adbdcbba680662e4 100644 --- a/src/MATLAB/UpdateHashedCellsTrackID.m +++ b/src/MATLAB/UpdateHashedCellsTrackID.m @@ -2,13 +2,13 @@ function UpdateHashedCellsTrackID(newTrackID,hulls,startTime) %This will take the list of hulls and update their trackIDs to the given %trackID +%--Eric Wait + global HashedCells for i=1:length(hulls) if(~hulls(i)),continue,end - index = [HashedCells{startTime+i-1}(:).hullID]==hulls(i); - %if(~isempty(index)) - HashedCells{startTime+i-1}(index).trackID = newTrackID; - %end + index = [HashedCells{startTime+i-1}.hullID]==hulls(i); + HashedCells{startTime+i-1}(index).trackID = newTrackID; end end diff --git a/src/MATLAB/UpdateTimeIndicatorLine.m b/src/MATLAB/UpdateTimeIndicatorLine.m index 0b732814b01db9c644b4e2b85c531de2e571acbd..19d114e378330c3c96e44b680d8e4a71b91e136d 100644 --- a/src/MATLAB/UpdateTimeIndicatorLine.m +++ b/src/MATLAB/UpdateTimeIndicatorLine.m @@ -2,6 +2,8 @@ function UpdateTimeIndicatorLine() %Changes the postition of the Red Line that indicates the current time %displayed +%--Eric Wait + global Figures if(ishandle(Figures.tree.timeIndicatorLine)) diff --git a/src/MATLAB/driver.m b/src/MATLAB/driver.m deleted file mode 100644 index 521b01547feb2f9de2d27accc1903d89d8f25e67..0000000000000000000000000000000000000000 --- a/src/MATLAB/driver.m +++ /dev/null @@ -1,65 +0,0 @@ -function convert() -%preallocate tables for speed - -global CellFamilies CellHulls HashedCells Costs CONSTANTS Figures Colors -%CONSTANTS.datasetName = 'ER81_E12pt5_0527090025_3_3AC05_07'; -CONSTANTS.datasetName = 'ER81_E12_0527090025_3_3AC03_02'; -%CONSTANTS.datasetName = 'ER81_E12pt5_0527090025_3_2AB02_05'; -data = [CONSTANTS.datasetName ' tracked_hulls.mat']; -CONSTANTS.rootFolder = ['..\..\Templetiffs\Temple Lineages\' CONSTANTS.datasetName '\']; -load(data); -load 'colors.mat' - -Colors = colors; -Costs = gConnect; - -CONSTANTS.ImageSize = unique([objHulls(:).imSize]); -CONSTANTS.maxPixelDistance = 40; -CONSTANTS.maxCenterOfMassDistance = 80; -CONSTANTS.minParentCandidateTimeFrame = 5; -CONSTANTS.minParentHistoryTimeFrame = 5; -CONSTANTS.minFamilyTimeFrame = 5; -CONSTANTS.maxFrameDifference = 1; - -HashedCells = cell(0,length(objHulls)); -i=1; - -CellHulls = struct(... - 'time', {objHulls(i).t},... - 'points', {objHulls(i).pts},... - 'centerOfMass', {objHulls(i).COM},... - 'indexPixels', {objHulls(i).indPixels}); - -if objHulls(i).inID == 0 - NewCellFamily(i,objHulls(i).t); -else - AddHullToTrack(i,[],objHulls(i).inID); -end - -for i=2:length(objHulls) - CellHulls(i).time = objHulls(i).t; - CellHulls(i).points = objHulls(i).pts; - CellHulls(i).centerOfMass = objHulls(i).COM; - CellHulls(i).indexPixels = objHulls(i).indPixels; - - if objHulls(i).inID == 0 - NewCellFamily(i,objHulls(i).t); - else - AddHullToTrack(i,[],objHulls(i).inID); - end -end - -ProcessNewborns(); -Figures.tree = figure; -Figures.cells = figure; - -% for i=1:length(CellFamilies) -% if(isempty(CellFamilies(i).tracks)),return,end -% DrawTree(i); -% DrawCells(450,i); -% pause(1); -% i -% end -DrawTree(10); -DrawCells(1,10); -end