diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..85223e81651b3b3988329852ccbfbf6f788e6c2a --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ + +bin/*.c +bin/*.log +*.mat +bin/*.prj +bin/*.txt + +#ignore thumbnails created by windows +Thumbs.db +#Ignore files build by Visual Studio +*.obj +*.exe +*.pdb +*.user +*.aps +*.pch +*.vspscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.cache +*.ilk +*.log +src/c/[Bb]in +src/c/[Dd]ebug*/ +*.lib +*.sbr +src/c/obj/ +src/c/[Rr]elease*/ +src/c/_ReSharper*/ +src/c/[Tt]est[Rr]esult* \ No newline at end of file diff --git a/bin/CompileLEVer.m b/bin/CompileLEVer.m new file mode 100644 index 0000000000000000000000000000000000000000..fec620633231ae59caa46b9169a4ae779d5c8c9c --- /dev/null +++ b/bin/CompileLEVer.m @@ -0,0 +1 @@ +mcc -m ../LEVer.m \ No newline at end of file diff --git a/src/MATLAB/AddHull.m b/src/MATLAB/AddHull.m new file mode 100644 index 0000000000000000000000000000000000000000..090b6e82aa6f76b7997ccf65e267e9ff4a2eb24b --- /dev/null +++ b/src/MATLAB/AddHull.m @@ -0,0 +1,57 @@ +function AddHull(num) +global Figures CellHulls + +if(num>6) + msgbox('Please limit number of new cells to 6','Add Hull Limit','help'); + return +end + +[hullID trackID] = GetClosestCell(1); +clickPt = get(gca,'CurrentPoint'); + +if ( ~CHullContainsPoint(clickPt(1,1:2), CellHulls(hullID)) ) + trackID = []; +end + +if(~isempty(trackID)) + % Try to split the existing hull + History('Push'); + try + newTracks = SplitHull(hullID,num+1);%adding one to the number so that the original hull is accounted for + if(isempty(newTracks)) + msgbox(['Unable to split ' num2str(trackID) ' any further in this frame'],'Unable to Split','help','modal'); + return + end + catch errorMessage + try + ErrorHandeling(['SplitHull(' num2str(hullID) ' ' num2str(num+1) ') -- ' errorMessage.message]); + return + catch errorMessage2 + fprintf(errorMessage2.message); + return + end + end + LogAction('Split cell',trackID,[trackID newTracks]); +elseif ( num<2 ) + % Try to run local segmentation and find a hull we missed or place a + % point-hull at least + History('Push'); + try + newTrack = AddNewSegmentHull(clickPt(1,1:2)); + catch errorMessage + try + ErrorHandeling(['AddNewSegmentHull(clickPt(1,1:2)) -- ' errorMessage.message]); + return + catch errorMessage2 + fprintf(errorMessage2.message); + return + end + end + LogAction('Added cell',[],newTrack); +else + return; +end + +DrawTree(Figures.tree.familyID); +DrawCells(); +end \ No newline at end of file diff --git a/src/MATLAB/AddNewSegmentHull.m b/src/MATLAB/AddNewSegmentHull.m index c0533b1419c8bd2f138cffd9fd9cd2bde1871333..e75faa3ebdae598f79907bf249e750ab9e343620 100644 --- a/src/MATLAB/AddNewSegmentHull.m +++ b/src/MATLAB/AddNewSegmentHull.m @@ -14,7 +14,7 @@ function newTrackID = AddNewSegmentHull(clickPt) newHull.time = Figures.time; newHull.points = round(clickPt); newHull.centerOfMass = [clickPt(2) clickPt(1)]; - newHull.indexPixels = sub2ind(size(img), clickPt(2), clickPt(1)); + newHull.indexPixels = sub2ind(size(img), newHull.points(2), newHull.points(1)); else newHull.time = Figures.time; newHull.points = newObj.points; diff --git a/src/MATLAB/CHullContainsPoint.m b/src/MATLAB/CHullContainsPoint.m index 7292d5cbf87edf195d64f18ee7af20f95b452f2d..45b31b9d014983e26ab194b6576b1033a36b46d0 100644 --- a/src/MATLAB/CHullContainsPoint.m +++ b/src/MATLAB/CHullContainsPoint.m @@ -1,5 +1,5 @@ function bInHull = CHullContainsPoint(pt, hulls) - bInHull = boolean(zeros(length(hulls),1)); + bInHull = false(length(hulls),1); for i=1:length(hulls) @@ -7,17 +7,19 @@ function bInHull = CHullContainsPoint(pt, hulls) continue; end - cvpts = hulls(i).points; - hullvec = diff(cvpts); - - outnrm = [-hullvec(:,2) hullvec(:,1)]; - %outnrm = outnrm ./ sqrt(sum(outnrm.^2,2)); - - ptvec = cvpts(1:end-1,:) - ones(size(outnrm,1),1)*pt; - %ptvec = ptvec ./ sqrt(sum(ptvec.^2,2)); - - chkIn = sign(sum(outnrm .* ptvec,2)); - - bInHull(i) = all(chkIn >= 0); +% cvpts = hulls(i).points; +% hullvec = diff(cvpts); +% +% outnrm = [-hullvec(:,2) hullvec(:,1)]; +% %outnrm = outnrm ./ sqrt(sum(outnrm.^2,2)); +% +% ptvec = cvpts(1:end-1,:) - ones(size(outnrm,1),1)*pt; +% %ptvec = ptvec ./ sqrt(sum(ptvec.^2,2)); +% +% chkIn = sign(sum(outnrm .* ptvec,2)); +% +% bInHull(i) = all(chkIn >= 0); + + bInHull(i) = inpolygon(pt(1), pt(2), hulls(i).points(:,1), hulls(i).points(:,2)); end end \ No newline at end of file diff --git a/src/MATLAB/ChangeTrackParent.m b/src/MATLAB/ChangeTrackParent.m index 0685e1a3186781ded8ab35df49c24e374ded0371..736aef8c5d811f043b44fd94fc5ae5614e232b77 100644 --- a/src/MATLAB/ChangeTrackParent.m +++ b/src/MATLAB/ChangeTrackParent.m @@ -1,9 +1,10 @@ function ChangeTrackParent(parentTrackID,time,childTrackID) -%This will take the childTrack and connect it to the parent track. It also -%takes the hulls that exist in the parent track that are come after the -%childTrack root and makes a new track with said hulls. When finished -%there should be a new track and the child track that are siblings with the -%parent track being the parent. +%ChangeTrackParent(parentTrackID,time,childTrackID) will take the +%childTrack and connect it to the parent track. It also takes the hulls +%that exist in the parent track that are come after the childTrack root and +%makes a new track with said hulls. When finished there should be a new +%track and the child track that are siblings with the parent track being +%the parent. %--Eric Wait diff --git a/src/MATLAB/ContextChangeLabel.m b/src/MATLAB/ContextChangeLabel.m index 42380afded85939b9e5fc8e628ffcd81696cf81f..5e0f8143ac17dd50ffc14871587cabfbc00bdb05 100644 --- a/src/MATLAB/ContextChangeLabel.m +++ b/src/MATLAB/ContextChangeLabel.m @@ -19,7 +19,18 @@ elseif(length(CellTracks)<newTrackID || isempty(CellTracks(newTrackID).hulls)) switch choice case 'Continue' newLabel = length(CellTracks) + 1; - ContextRemoveFromTree(time,trackID); + History('Push'); + try + ContextRemoveFromTree(time,trackID); + catch errorMessage + try + ErrorHandeling(['ContextRemoveFromTree(' num2str(time) ' ' num2str(trackID) ' ) -- ' errorMessage.message]); + return + catch errorMessage2 + fprintf(errorMessage2.message); + return + end + end msgbox(['The new cell label is ' num2str(newLabel)],'Remove From Tree','help'); return case 'Cancel' @@ -37,6 +48,7 @@ elseif(newTrackID>length(CellTracks) || isempty(CellTracks(newTrackID).hulls)) catch errorMessage try ErrorHandeling(['RemoveFromTree(' num2str(time) ' ' num2str(trackID) ' yes) -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -48,27 +60,38 @@ elseif(newTrackID>length(CellTracks) || isempty(CellTracks(newTrackID).hulls)) return end elseif(~isempty(find([HashedCells{time}.trackID]==newTrackID,1))) - choice = questdlg(['Label ' num2str(newTrackID) ' exist on this frame. Would you like these labels to swap from here forward or just this frame?'],... - 'Swap Labels?','Forward','This Frame','Cancel','Cancel'); - switch choice - case 'Forward' +% choice = questdlg(['Label ' num2str(newTrackID) ' exist on this frame. Would you like these labels to swap from here forward or just this frame?'],... +% 'Swap Labels?','Forward','This Frame','Cancel','Cancel'); +% switch choice +% case 'Forward' History('Push'); try SwapTrackLabels(time,trackID,newTrackID); catch errorMessage try ErrorHandeling(['SwapTrackLabels(' num2str(time) ' ' num2str(trackID) ' ' num2str(newTrackID) ') -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return end end LogAction('Swapped Labels',trackID,newTrackID); - case 'This Frame' - SwapHulls(time,trackID,newTrackID); - case 'Cancel' - return - end +% case 'This Frame' +% History('Push'); +% try +% SwapHulls(time,trackID,newTrackID); +% catch errorMessage +% try +% ErrorHandeling(['SwapHulls(' num2str(time) ' ' num2str(trackID) num2str(newTrackID) ') -- ' errorMessage.message]); +% catch errorMessage2 +% fprintf(errorMessage2.message); +% return +% end +% end +% case 'Cancel' +% return +% end elseif(isempty(CellTracks(trackID).parentTrack) && isempty(CellTracks(trackID).childrenTracks) && 1==length(CellTracks(trackID).hulls)) hullID = CellTracks(trackID).hulls(1); History('Push'); @@ -77,6 +100,7 @@ elseif(isempty(CellTracks(trackID).parentTrack) && isempty(CellTracks(trackID).c catch errorMessage try ErrorHandeling(['AddSingleHullToTrack(' num2str(trackID) ' ' num2str(newTrackID) ') -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -90,6 +114,7 @@ elseif(~isempty(CellTracks(trackID).parentTrack) && CellTracks(trackID).parentTr catch errorMessage try ErrorHandeling(['MoveMitosisUp(' num2str(time) ' ' num2str(trackID) ') -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -103,6 +128,7 @@ elseif(~isempty(CellTracks(newTrackID).parentTrack) && CellTracks(newTrackID).pa catch errorMessage try ErrorHandeling(['MoveMitosisUp(' num2str(time) ' ' num2str(newTrackID) ') -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -116,6 +142,7 @@ else catch errorMessage try ErrorHandeling(['ChangeLabel(' num2str(time) ' ' num2str(trackID) ' ' num2str(newTrackID) ') -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return diff --git a/src/MATLAB/ContextChangeParent.m b/src/MATLAB/ContextChangeParent.m index 3648ed93cef73b22f4d2f58aa1387a3008436a2a..83c0db2da38f8978e8e3d7180e19c23c28ec8c3f 100644 --- a/src/MATLAB/ContextChangeParent.m +++ b/src/MATLAB/ContextChangeParent.m @@ -29,6 +29,7 @@ try catch errorMessage try ErrorHandeling(['ChangeTrackParent(' num2str(newParentID) ' ' num2str(time) ' ' num2str(trackID) ') -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return diff --git a/src/MATLAB/ContextRemoveFromTree.m b/src/MATLAB/ContextRemoveFromTree.m index ce6726cea646da81621b9519c43cf02cc8581e8b..e81d3b85b6e43cec16263f75201ae62932bde64e 100644 --- a/src/MATLAB/ContextRemoveFromTree.m +++ b/src/MATLAB/ContextRemoveFromTree.m @@ -12,6 +12,7 @@ try catch errorMessage try ErrorHandeling(['RemoveFromTree(' num2str(time) ' ' num2str(trackID) ' yes) -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return diff --git a/src/MATLAB/ConvertTrackingData.m b/src/MATLAB/ConvertTrackingData.m index f4890427f47646fb2b711282172640216b125d2b..78f1f72eebab7be8becc23b82f6f5581c0089d90 100644 --- a/src/MATLAB/ConvertTrackingData.m +++ b/src/MATLAB/ConvertTrackingData.m @@ -17,6 +17,7 @@ CONSTANTS.minFamilyTimeFrame = 5; CONSTANTS.maxFrameDifference = 5; CONSTANTS.historySize = 50; CONSTANTS.clickMargin = 500; +CONSTANTS.timeResolution = 10; %in frames per min Costs = gConnect; %Initialize Structures diff --git a/src/MATLAB/CreateContextMenuCells.m b/src/MATLAB/CreateContextMenuCells.m index 1faefc483ce227ef44c1a66eda7f3d4752ad9c19..426a271c4ac5c7ab4b58896ed61dded67b995175 100644 --- a/src/MATLAB/CreateContextMenuCells.m +++ b/src/MATLAB/CreateContextMenuCells.m @@ -103,6 +103,7 @@ switch choice try ErrorHandeling(['RemoveFromTree(' num2str(CellTracks(CellTracks(object.UserData).siblingTrack).startTime)... num2str(CellTracks(object.UserData).siblingTrack) ' yes) -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -115,7 +116,9 @@ switch choice newTree = RemoveFromTree(CellTracks(object.UserData).startTime,object.UserData,'yes'); catch errorMessage try - ErrorHandeling(['RemoveFromTree(CellTracks(' num2str(CellTracks(object.UserData).startTime) ' ' num2str(object.UserData) ' yes) -- ' errorMessage.message]); + ErrorHandeling(['RemoveFromTree(CellTracks(' num2str(CellTracks(object.UserData).startTime) ' '... + num2str(object.UserData) ' yes) -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -130,9 +133,9 @@ DrawCells(); end function addMitosis(src,evnt) -global CellTracks Figures +global CellTracks Figures HashedCells -[hullID trackID] = getClosestCell(); +[hullID trackID] = GetClosestCell(0); if(isempty(trackID)),return,end % answer = inputdlg({['Enter new sibling of ' num2str(trackID)],'Enter Time of Mitosis'},... @@ -146,29 +149,115 @@ if(isempty(answer)),return,end siblingTrack = str2double(answer(1)); time = Figures.time; -if(isempty(CellTracks(siblingTrack).hulls)) - msgbox([answer(2) ' is not a valid cell'],'Not a valid cell','error'); +if(siblingTrack>length(CellTracks) || isempty(CellTracks(siblingTrack).hulls)) + msgbox([answer(1) ' is not a valid cell'],'Not a valid cell','error'); + return +end +if(CellTracks(siblingTrack).endTime<time || siblingTrack==trackID) + msgbox([answer(1) ' is not a valid sibling'],'Not a valid sibling','error'); return end if(CellTracks(trackID).startTime>time) msgbox([num2str(trackID) ' exists after ' answer(1)],'Not a valid child','error'); return end +if(~isempty(CellTracks(siblingTrack).timeOfDeath) && CellTracks(siblingTrack).timeOfDeath<=time) + msgbox(['Cannot attach a cell to cell ' num2str(siblingTrack) ' beacuse it is dead at this time'],'Dead Cell','help'); + return +end +if(~isempty(CellTracks(trackID).timeOfDeath) && CellTracks(trackID).timeOfDeath<=time) + msgbox(['Cannot attach a cell to cell ' num2str(trackID) ' beacuse it is dead at this time'],'Dead Cell','help'); + return +end -oldParent = CellTracks(siblingTrack).parentTrack; - -if(CellTracks(trackID).startTime==time) +if(CellTracks(trackID).startTime==time && CellTracks(siblingTrack).startTime<time) History('Push'); try ChangeTrackParent(siblingTrack,time,trackID); catch errorMessage try ErrorHandeling(['ChangeTrackParent(' num2str(siblingTrack) ' ' num2str(time) ' ' num2str(trackID) ') -- ' errorMessage.message]); + return + catch errorMessage2 + fprintf(errorMessage2.message); + return + end + end + Figures.tree.familyID = CellTracks(siblingTrack).familyID; +elseif(CellTracks(siblingTrack).startTime==time && CellTracks(trackID).startTime<time) + History('Push'); + try + ChangeTrackParent(trackID,time,siblingTrack); + catch errorMessage + try + ErrorHandeling(['ChangeTrackParent(' num2str(trackID) ' ' num2str(time) ' ' num2str(siblingTrack) ') -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return end end + Figures.tree.familyID = CellTracks(trackID).familyID; +elseif(CellTracks(siblingTrack).startTime==time && CellTracks(trackID).startTime==time) + valid = 0; + while(~valid) + answer = inputdlg({'Enter parent of these siblings '},'Parent',1,{''}); + if(isempty(answer)),return,end + parentTrack = str2double(answer(1)); + + if(CellTracks(parentTrack).startTime>=time || isempty(CellTracks(parentTrack).hulls) ||... + (~isempty(CellTracks(parentTrack).timeOfDeath) && CellTracks(parentTrack).timeOfDeath<=time)) + choice = questdlg([num2str(parentTrack) ' is an invalid parent for these cells, please choose another'],... + 'Not a valid parent','Enter a different parent','Cancel','Cancel'); + switch choice + case 'Cancel' + return + end + else + valid = 1; + end + end + + History('Push'); + if(~isempty(find([HashedCells{time}.trackID]==parentTrack,1))) + try + SwapTrackLabels(time,trackID,parentTrack); + catch errorMessage + try + ErrorHandeling(['SwapTrackLabels(' num2str(time) ' ' num2str(trackID) ' ' num2str(parentTrack) ') -- ' errorMessage.message]); + return + catch errorMessage2 + fprintf(errorMessage2.message); + return + end + end + LogAction('Swapped Labels',trackID,parentTrack); + else + try + ChangeLabel(time,trackID,parentTrack); + catch errorMessage + try + ErrorHandeling(['ChangeLabel(' num2str(time) ' ' num2str(trackID) ' ' num2str(parentTrack) ') -- ' errorMessage.message]); + return + catch errorMessage2 + fprintf(errorMessage2.message); + return + end + end + end + + try + ChangeTrackParent(parentTrack,time,siblingTrack); + catch errorMessage + try + ErrorHandeling(['ChangeTrackParent(' num2str(parentTrack) ' ' num2str(time) ' ' num2str(siblingTrack) ') -- ' errorMessage.message]); + return + catch errorMessage2 + fprintf(errorMessage2.message); + return + end + end + Figures.tree.familyID = CellTracks(parentTrack).familyID; else History('Push'); try @@ -176,23 +265,25 @@ else catch errorMessage try ErrorHandeling(['ChangeTrackParent(' num2str(trackID) ' ' num2str(time) ' ' num2str(siblingTrack) ') -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return end end + Figures.tree.familyID = CellTracks(trackID).familyID; end -LogAction(['Changed parent of ' num2str(siblingTrack)],oldParent,trackID); +LogAction(['Changed parent of ' num2str(trackID) ' and ' num2str(siblingTrack)],[],[]); -DrawTree(CellTracks(trackID).familyID); +DrawTree(Figures.tree.familyID); DrawCells(); end function changeLabel(src,evnt) global Figures -[hullID trackID] = getClosestCell(); +[hullID trackID] = GetClosestCell(0); if(isempty(trackID)),return,end ContextChangeLabel(Figures.time,trackID); @@ -200,39 +291,39 @@ end function changeParent(src,evnt) global Figures -[hullID trackID] = getClosestCell(); +[hullID trackID] = GetClosestCell(0); if(isempty(trackID)),return,end ContextChangeParent(trackID,Figures.time); end function addHull1(src,evnt) -addHull(1); +AddHull(1); end function addHull2(src,evnt) -addHull(2); +AddHull(2); end function addHull3(src,evnt) -addHull(3); +AddHull(3); end function addHull4(src,evnt) -addHull(4); +AddHull(4); end function addHullOther(src,evnt) -num = inputdlg('Enter Number of Hulls to Add','Add Hulls',1,{1}); +num = inputdlg('Enter Number of Hulls to Add','Add Hulls',1,{'1'}); if(isempty(num)),return,end; num = str2double(num(1)); -addHull(num); +AddHull(num); end function removeHull(src,evnt) global Figures CellFamilies -[hullID trackID] = getClosestCell(); +[hullID trackID] = GetClosestCell(0); if(isempty(trackID)),return,end History('Push'); @@ -241,6 +332,7 @@ try catch errorMessage try ErrorHandeling(['RemoveHull(' num2str(hullID) ') -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -271,7 +363,7 @@ end function markDeath(src,evnt) global Figures CellTracks -[hullID trackID] = getClosestCell(); +[hullID trackID] = GetClosestCell(0); if(isempty(trackID)),return,end CellTracks(trackID).timeOfDeath = Figures.time; @@ -284,6 +376,7 @@ if(~isempty(CellTracks(trackID).childrenTracks)) catch errorMessage try ErrorHandeling(['ProcessNewborns(StraightenTrack(' num2str(trackID) ')-- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -300,78 +393,17 @@ end function removeFromTree(src,evnt) global Figures -[hullID trackID] = getClosestCell(); +[hullID trackID] = GetClosestCell(0); if(isempty(trackID)),return,end ContextRemoveFromTree(Figures.time,trackID); end function properties(src,evnt) -[hullID trackID] = getClosestCell(); +[hullID trackID] = GetClosestCell(0); if(isempty(trackID)),return,end ContextProperties(hullID,trackID); end %% Helper functions -function addHull(num) -global Figures CellHulls - -[hullID trackID] = getClosestCell(num<2); -clickPt = get(gca,'CurrentPoint'); - -if ( ~CHullContainsPoint(clickPt(1,1:2), CellHulls(hullID)) ) - trackID = []; -end - -if(~isempty(trackID)) - % Try to split the existing hull - History('Push'); - try - newTracks = SplitHull(hullID,num+1);%adding one to the number so that the original hull is accounted for - catch errorMessage - try - ErrorHandeling(['SplitHull(' num2str(hullID) ' ' num2str(num+1) ') -- ' errorMessage.message]); - catch errorMessage2 - fprintf(errorMessage2.message); - return - end - end - LogAction('Split cell',trackID,[trackID newTracks]); -elseif ( num<2 ) - % Try to run local segmentation and find a hull we missed or place a - % point-hull at least - History('Push'); - try - newTrack = AddNewSegmentHull(clickPt(1,1:2)); - catch errorMessage - try - ErrorHandeling(['AddNewSegmentHull(clickPt(1,1:2)) -- ' errorMessage.message]); - catch errorMessage2 - fprintf(errorMessage2.message); - return - end - end - LogAction('Added cell',[],newTrack); -else - return; -end - -DrawTree(Figures.tree.familyID); -DrawCells(); -end - -function [hullID trackID] = getClosestCell(allowEmpty) -hullID = FindHull(get(gca,'CurrentPoint')); -if(0>=hullID) - if (allowEmpty ) - hullID = []; - else - warndlg('Please click closer to the center of the desired cell','Unknown Cell'); - end - trackID = []; - return -end -trackID = GetTrackID(hullID); - -end diff --git a/src/MATLAB/CreateContextMenuTree.m b/src/MATLAB/CreateContextMenuTree.m index 63019c70106b5a27f564b1529710396f22d0deb2..25cb6f83cf9a4287d1e0a7bf4e839c1b333b5757 100644 --- a/src/MATLAB/CreateContextMenuTree.m +++ b/src/MATLAB/CreateContextMenuTree.m @@ -58,7 +58,10 @@ else msgbox('Please Click on the Node or the Vertical Edge to Remove Mitosis','Unable to Remove Mitosis','warn'); return end + switch choice + case 'Cancel' + return case num2str(object.UserData) remove = CellTracks(object.UserData).siblingTrack; History('Push'); @@ -69,6 +72,7 @@ switch choice try ErrorHandeling(['RemoveFromTree(' num2str(CellTracks(CellTracks(object.UserData).siblingTrack).startTime) ' '... num2str(CellTracks(object.UserData).siblingTrack) ' yes) -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -81,7 +85,9 @@ switch choice newTree = RemoveFromTree(CellTracks(object.UserData).startTime,object.UserData,'yes'); catch errorMessage try - ErrorHandeling(['RemoveFromTree(' num2str(CellTracks(object.UserData).startTime) ' ' num2str(object.UserData) ' yes) -- ' errorMessage.message]); + ErrorHandeling(['RemoveFromTree(' num2str(CellTracks(object.UserData).startTime) ' '... + num2str(object.UserData) ' yes) -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -97,6 +103,7 @@ switch choice try ErrorHandeling(['RemoveFromTree(' num2str(CellTracks(CellTracks(object.UserData).childrenTracks(2)).startTime) ' '... num2str(CellTracks(object.UserData).childrenTracks(2)) ' yes) -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -112,6 +119,7 @@ switch choice try ErrorHandeling(['RemoveFromTree(' num2str(CellTracks(CellTracks(object.UserData).childrenTracks(1)).startTime) ' '... num2str(CellTracks(object.UserData).childrenTracks(1)) ' yes) -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return @@ -140,7 +148,7 @@ if(isempty(answer)),return,end time = str2double(answer(1)); siblingTrack = str2double(answer(2)); -if(isempty(CellTracks(siblingTrack).hulls)) +if(siblingTrack>length(CellTracks) || isempty(CellTracks(siblingTrack).hulls)) msgbox([answer(2) ' is not a valid cell'],'Not a valid cell','error'); return end @@ -156,7 +164,9 @@ try ChangeTrackParent(trackID,time,siblingTrack); catch errorMessage try - ErrorHandeling(['ChangeTrackParent(' num2str(trackID) ' ' num2str(time) ' ' num2str(siblingTrack) ') -- ' errorMessage.message]); + ErrorHandeling(['ChangeTrackParent(' num2str(trackID) ' ' num2str(time) ' '... + num2str(siblingTrack) ') -- ' errorMessage.message]); + return catch errorMessage2 fprintf(errorMessage2.message); return diff --git a/src/MATLAB/CreateMenuBar.m b/src/MATLAB/CreateMenuBar.m index 167fe30bbd09c2a945ee4b001e93fb7ec233dc77..6996080838151aee3b9fa140e56cf3fe2482c91a 100644 --- a/src/MATLAB/CreateMenuBar.m +++ b/src/MATLAB/CreateMenuBar.m @@ -37,6 +37,7 @@ uimenu(... saveMenu = uimenu(... 'Parent', fileMenu,... 'Label', 'Save',... + 'Separator', 'on',... 'HandleVisibility', 'callback', ... 'Callback', @saveFile,... 'Enable', 'off',... @@ -53,14 +54,23 @@ uimenu(... 'Label', 'Export Image',... 'Separator', 'on',... 'HandleVisibility', 'callback', ... - 'Callback', @exportImage); + 'Callback', @exportImage,... + 'Visible', 'off'); uimenu(... 'Parent', fileMenu,... 'Label', 'Print',... + 'Separator', 'on',... 'HandleVisibility', 'callback', ... 'Callback', @printFigure); +uimenu(... + 'Parent', fileMenu,... + 'Label', 'Export Movie Tiffs',... + 'Separator', 'on',... + 'HandleVisibility', 'callback', ... + 'Callback', @makeMovie); + undoMenu = uimenu(... 'Parent', editMenu,... 'Label', 'Undo',... @@ -170,8 +180,29 @@ function printFigure(src,evnt) printdlg; end +function makeMovie(src,evnt) +global CONSTANTS Figures +choice = questdlg('Please set the zoom that you would like for the duration of the movie. Click OK when accomplished.','Set Zoom','OK','Cancel','OK'); +switch choice + case 'Cancel' + return +end +xLim = get(get(Figures.cells.handle, 'CurrentAxes'),'XLim'); +yLim = get(get(Figures.cells.handle, 'CurrentAxes'),'YLim'); +dim = [floor(xLim(2)-xLim(1)) floor(yLim(2)-yLim(1))]; +answer = inputdlg({'Enter the prefix for the exported files:','Enter Frames Per Second:','Enter X Dimension:','Enter Y Dimension'},... + 'Movie Options',1,{CONSTANTS.datasetName,'1',num2str(1024),num2str(384)});%num2str(CONSTANTS.imageSize(2)),num2str(CONSTANTS.imageSize(1)) +if(isempty(answer)),return,end + +filename = answer(1); +try + MakeMovie(filename{1},str2double(answer(2)),[str2double(answer(3)) str2double(answer(4))]); +catch errorMessage + disp(errorMessage); +end +end + function undo(src,evnt) -History('Push');%put the current state on the stack then go to the previous History('Pop'); end diff --git a/src/MATLAB/DrawTree.m b/src/MATLAB/DrawTree.m index 9afd693de35fa164300d2bb552b28683d12af661..7aca6f234f3e2dab161e66224a0dd1a274743406 100644 --- a/src/MATLAB/DrawTree.m +++ b/src/MATLAB/DrawTree.m @@ -3,7 +3,11 @@ function DrawTree(familyID) %--Eric Wait -global CellFamilies HashedCells Figures +global CellFamilies HashedCells Figures CONSTANTS + +if(~isfield(CONSTANTS,'timeResolution')) + CONSTANTS.timeResolution = 10; +end if(isempty(CellFamilies(familyID).tracks)),return,end @@ -17,20 +21,42 @@ trackID = CellFamilies(familyID).tracks(1); figure(Figures.tree.handle); delete(gca); +% delete(gca); +% hold off +% +% underAxes = axes; +% +% set(underAxes,... +% 'YDir', 'reverse',... +% 'YLim', [0 length(HashedCells)],... +% 'Position', [.07 .06 .80 .90],... +% 'YAxisLocation', 'right',... +% 'YLim', [0 length(HashedCells)*CONSTANTS.timeResolution/60],... +% 'XColor', 'w',... +% 'XTick', [],... +% 'Box', 'off'); +% ylabel('Time (Hours)'); +% axis off + +overAxes = axes; -set(gca,... +set(overAxes,... 'YDir', 'reverse',... 'YLim', [0 length(HashedCells)],... 'Position', [.06 .06 .90 .90],... 'XColor', 'w',... - 'XTick', []); + 'XTick', [],... + 'Box', 'off'); +% ylabel('Time (Frames)'); hold on [xMin xCenter xMax] = traverseTree(trackID,0); -set(gca,... +% set(underAxes,... +% 'XLim', [xMin-1 xMax+1]); +set(overAxes,... 'XLim', [xMin-1 xMax+1]); -Figures.tree.axesHandle = gca; +Figures.tree.axesHandle = overAxes; hold off UpdateTimeIndicatorLine(); diff --git a/src/MATLAB/ErrorHandeling.m b/src/MATLAB/ErrorHandeling.m index 8b665bcad77813aec1278ecd72870ab3c8a9cd2a..35b41df9859e979febc29b87067452463aeba082 100644 --- a/src/MATLAB/ErrorHandeling.m +++ b/src/MATLAB/ErrorHandeling.m @@ -12,7 +12,7 @@ History('Pop'); History('Redo');%this is to get to the state just before the error, it was on the top of the stack msgboxHandle = msgbox('Attempting to fix database. Will take some time depending on the size of the database. This window will close when done',... - 'Fixing Database','help','modal'); + 'Fixing Database','warn','modal'); LogAction(errorMessage,[],[]); %let the user know that this might take a while diff --git a/src/MATLAB/GetClosestCell.m b/src/MATLAB/GetClosestCell.m new file mode 100644 index 0000000000000000000000000000000000000000..340f2cd403a0a175e4f8fd16c6e827cd47f71559 --- /dev/null +++ b/src/MATLAB/GetClosestCell.m @@ -0,0 +1,14 @@ +function [hullID trackID] = GetClosestCell(allowEmpty) +hullID = FindHull(get(gca,'CurrentPoint')); +if(0>=hullID) + if (allowEmpty ) + hullID = []; + else + warndlg('Please click closer to the center of the desired cell','Unknown Cell'); + end + trackID = []; + return +end +trackID = GetTrackID(hullID); + +end \ No newline at end of file diff --git a/src/MATLAB/GetPixelSize.m b/src/MATLAB/GetPixelSize.m new file mode 100644 index 0000000000000000000000000000000000000000..eb6c6618eac217fc36c73de2667c01549475e77b --- /dev/null +++ b/src/MATLAB/GetPixelSize.m @@ -0,0 +1,12 @@ +function pixSz = GetPixelSize(axisHandle) + +%--Mark Winter + + oldUnits = get(axisHandle, 'Units'); + set(axisHandle, 'Units','pixels'); + + pos = get(axisHandle, 'Position'); + set(axisHandle, 'Units',oldUnits); + + pixSz = pos(3:4); +end \ No newline at end of file diff --git a/src/MATLAB/InitializeFigures.m b/src/MATLAB/InitializeFigures.m index 64d28f9e90d811eb8b29300623f23d2dcd47573e..835b86ed5ccb3e0e2be2bb3855f5fe2092996c53 100644 --- a/src/MATLAB/InitializeFigures.m +++ b/src/MATLAB/InitializeFigures.m @@ -127,6 +127,8 @@ if(strcmp(get(Figures.cells.handle,'SelectionType'),'normal')) return end set(Figures.cells.handle,'WindowButtonUpFcn',@figureCellUp); +elseif(strcmp(get(Figures.cells.handle,'SelectionType'),'extend')) + AddHull(1); end if(strcmp(Figures.advanceTimerHandle.Running,'on')) TogglePlay(src,evnt); @@ -134,17 +136,36 @@ end end function figureCellUp(src,evnt) -global Figures HashedCells CellTracks +global Figures CellTracks + +set(Figures.cells.handle,'WindowButtonUpFcn',''); if(Figures.cells.currentHullID == -1) return end -trackID = [HashedCells{Figures.time}(:).hullID]==Figures.cells.currentHullID; -trackID = HashedCells{Figures.time}(trackID).trackID; -if(CellTracks(trackID).familyID~=Figures.tree.familyID) - DrawTree(CellTracks(trackID).familyID); - DrawCells(); + +currentHullID = FindHull(get(gca,'CurrentPoint')); +previousTrackID = GetTrackID(Figures.cells.currentHullID); + +if(currentHullID~=Figures.cells.currentHullID) + History('Push') + try + SwapTrackLabels(Figures.time,GetTrackID(currentHullID),previousTrackID); + catch errorMessage + try + ErrorHandeling(['SwapTrackLabels(' num2str(Figures.time) ' ' num2str(GetTrackID(currentHullID))... + ' ' num2str(previousTrackID) ') -- ' errorMessage.message]); + return + catch errorMessage2 + fprintf(errorMessage2.message); + return + end + end +elseif(CellTracks(previousTrackID).familyID==Figures.tree.familyID) + %no change and the current tree contains the cell clicked on + return end -set(Figures.cells.handle,'WindowButtonUpFcn',''); +DrawTree(CellTracks(previousTrackID).familyID); +DrawCells(); end function figureTreeDown(src,evnt) diff --git a/src/MATLAB/LEVer.m b/src/MATLAB/LEVer.m index 64cc06cfc088fee13def8d3b9f0f8af219650957..7a9767a52fe34ac44131354cc6206fa8dc219df6 100644 --- a/src/MATLAB/LEVer.m +++ b/src/MATLAB/LEVer.m @@ -8,13 +8,17 @@ global Figures %if LEVer is already opened, save state just in case the User cancels the %open if(~isempty(Figures)) + saveEnabled = strcmp(get(Figures.cells.menuHandles.saveMenu,'Enable'),'on'); History('Push'); + if(~saveEnabled) + set(Figures.cells.menuHandles.saveMenu,'Enable','off'); + end end if(OpenData()) InitializeFigures(); History('Init'); -else %if(~isempty(Figures)) +elseif(~isempty(Figures)) History('Pop'); DrawTree(Figures.tree.familyID); DrawCells(); diff --git a/src/MATLAB/MakeMovie.m b/src/MATLAB/MakeMovie.m new file mode 100644 index 0000000000000000000000000000000000000000..3f91c97452b40e339750cf700ebcf0c643320867 --- /dev/null +++ b/src/MATLAB/MakeMovie.m @@ -0,0 +1,70 @@ +function MakeMovie(filename, fps, outRes) + +%--Mark Winter + +global CONSTANTS Figures HashedCells; + +axHandles = [get(Figures.cells.handle, 'CurrentAxes') get(Figures.tree.handle, 'CurrentAxes')]; + +lims.cells = [get(axHandles(1), 'XLim'); get(axHandles(1), 'YLim')]; +lims.tree = [get(axHandles(2), 'XLim'); get(axHandles(2), 'YLim')]; + +figpos.cells = get(Figures.cells.handle, 'Position'); +figpos.tree = get(Figures.tree.handle, 'Position'); + +spc = 10; +set(axHandles(2), 'YLim', [lims.tree(2,1)-spc lims.tree(2,2)+spc]); + +cellSz = GetPixelSize(axHandles(1)); +cellApsect = cellSz(1) / cellSz(2); + +treeSz = GetPixelSize(axHandles(2)); +treeApsect = treeSz(1) / treeSz(2); + +outCellSz = floor([outRes(2)*cellApsect outRes(2)]); +outTreeSz = [outRes(1)-outCellSz(1) outRes(2)]; + +oldtime = Figures.time; + +% movfile = avifile(fname, 'Compression','cinepak', 'fps',fps); + +if ( ~exist(filename,'dir') ) + mkdir(filename); +end + +save(fullfile(filename,'params.mat'), 'outRes', 'lims'); + +% set(axHandles(1), 'XLim', [1 ); + +for t=1:length(HashedCells) + Figures.time = t; + + set(Figures.cells.timeLabel,'String',['Time: ' num2str(Figures.time)]); + set(Figures.tree.timeLabel,'String',['Time: ' num2str(Figures.time)]); + UpdateTimeIndicatorLine(); + SetPixelSize(axHandles(2), outTreeSz); + treeFrm = getframe(axHandles(2)); + + DrawCells(); + SetPixelSize(axHandles(1), outCellSz); + cellFrm = getframe(axHandles(1)); + + fullFrm = cellFrm; + fullFrm.cdata = [cellFrm.cdata(1:outCellSz(2),1:outCellSz(1),:) treeFrm.cdata(1:outTreeSz(2),1:outTreeSz(1),:)]; + + imwrite(fullFrm.cdata, fullfile(filename,[filename '_' num2str(t,'%04d') '.tif']), 'tif'); + + % movfile = addframe(movfile,fullFrame); +end + +% movfile = close(movfile); + +Figures.time = oldtime; +set(Figures.cells.timeLabel,'String',['Time: ' num2str(Figures.time)]); +set(Figures.tree.timeLabel,'String',['Time: ' num2str(Figures.time)]); + +set(Figures.cells.handle, 'Position',figpos.cells); +set(Figures.tree.handle, 'Position',figpos.tree); +UpdateTimeIndicatorLine(); +DrawCells(); +end \ No newline at end of file diff --git a/src/MATLAB/OpenData.m b/src/MATLAB/OpenData.m index 7b4f4082cf3ef6071f5b38c2f2e8106514ddceb8..e25f185e07d77748b9e636859e7d61d5508d3e9e 100644 --- a/src/MATLAB/OpenData.m +++ b/src/MATLAB/OpenData.m @@ -7,7 +7,7 @@ function opened = OpenData() global Figures Colors CONSTANTS CellFamilies CellHulls HashedCells Costs CellTracks if(isempty(Figures)) - fprintf('LEVer ver 3.6\n***DO NOT DISTRIBUTE***\n\n'); + fprintf('LEVer ver 3.7\n***DO NOT DISTRIBUTE***\n\n'); end if(exist('ColorScheme.mat','file')) @@ -38,6 +38,24 @@ imageDataset = []; goodLoad = 0; opened = 0; +if(~isempty(Figures)) + if(strcmp(get(Figures.cells.menuHandles.saveMenu,'Enable'),'on')) + choice = questdlg('Save current edits before opening new data?','Closing','Yes','No','Cancel','Cancel'); + switch choice + case 'Yes' + SaveData(); + set(Figures.cells.menuHandles.saveMenu,'Enable','off'); + case 'Cancel' + return + case 'No' + set(Figures.cells.menuHandles.saveMenu,'Enable','off'); + otherwise + return + end + end +end + +oldCONSTANTS = CONSTANTS; % .mat file handling while(~goodLoad) fprintf('Select .mat data file...\n'); @@ -92,7 +110,10 @@ imageFilter = [settings.imagePath '*' CONSTANTS.datasetName '*.TIF']; while (filterIndexImage==0) fprintf('\nSelect first .TIF image...\n\n'); [imageFile,imagePath,filterIndexImage] = uigetfile(imageFilter,['Open First Image in dataset: ' CONSTANTS.datasetName]); - if (filterIndexImage==0),return,end + if (filterIndexImage==0) + CONSTANTS = oldCONSTANTS; + return + end end index = strfind(imageFile,'t'); @@ -106,7 +127,10 @@ end while (isempty(index) || ~exist(fileName,'file')) fprintf(['Image file name not in correct format: ' CONSTANTS.datasetName '_t001.TIF\nPlease choose another...\n']); [imageFile,imagePath,filterIndexImage] = uigetfile(settings.imagePath,'Open First Image'); - if(filterIndexImage==0),return,end + if(filterIndexImage==0) + CONSTANTS = oldCONSTANTS; + return + end index = strfind(imageFile,'t'); CONSTANTS.rootImageFolder = [imgPath '\']; imageDataset = imageFile(1:(index(length(index))-2)); diff --git a/src/MATLAB/PartialImageSegment.m b/src/MATLAB/PartialImageSegment.m index 010ad7970ae4562f38bc6297e11b2b8486ff033f..73838a4e6351f3c2f19193ab3e2bf33e56574fe8 100644 --- a/src/MATLAB/PartialImageSegment.m +++ b/src/MATLAB/PartialImageSegment.m @@ -172,6 +172,46 @@ function hull = PartialImageSegment(img, centerPt, subSize, alpha) no.Eccentricity=stats(idx(i)).Eccentricity; objs = [objs no]; end + + % bright interiors + igm=bwig|bwHalo; + se=strel('square',5); + igm=imclose(igm,se); + igm=imfill(igm,'holes'); + igm(logical(bwCellFG))=0; + se=strel('square',13); + igm=imerode(igm,se); + + CC = bwconncomp(igm,8); + Ligm = labelmatrix(CC); + stats = regionprops(CC, 'Area','Eccentricity'); + idx = find( [stats.Area] >25 & [stats.Area] <1000 & [stats.Eccentricity]<.95 ) ; + for i=1:length(idx) + pix = find(Ligm==idx(i)); + [r c] = ind2sub(size(subImg),pix); + ch = convhull(r,c); + + bwPoly = poly2mask(c(ch),r(ch),size(subImg,1),size(subImg,2)); + if length(find(bwCellFG & bwPoly)) + continue; + end + + glc = c + coordMin(1); + glr = r + coordMin(2); + + no=[]; + + no.points=[glc(ch),glr(ch)]; + no.centerOfMass = mean([glr glc]); + + no.indexPixels = sub2ind(imSize,[glr glc]); + no.imagePixels=img(no.indexPixels); + + no.ID=-1; + no.BrightInterior=1; + no.Eccentricity=stats(idx(i)).Eccentricity; + objs=[objs no]; + end bInHull = CHullContainsPoint(centerPt, objs); diff --git a/src/MATLAB/ProcessNewborns.m b/src/MATLAB/ProcessNewborns.m index 74c253f737e373eb0de0e86721f338543b69141e..86fecd5b7438745ecb83eb49dc93e36095d771d6 100644 --- a/src/MATLAB/ProcessNewborns.m +++ b/src/MATLAB/ProcessNewborns.m @@ -54,6 +54,7 @@ for i=1:size if(isempty(parentTrackID)) try ErrorHandeling(['GetTrackID(' num2str(parentHullID) ') -- while in ProcessNewborns']); + return catch errorMessage2 fprintf(errorMessage2); return diff --git a/src/MATLAB/RemoveChildren.m b/src/MATLAB/RemoveChildren.m index 43e6be64c13fe2bbdf710a2e18aed48cbad74ab2..99ee3985cf2acf83d5e4d492d47136000f7702c4 100644 --- a/src/MATLAB/RemoveChildren.m +++ b/src/MATLAB/RemoveChildren.m @@ -14,5 +14,5 @@ end CellTracks(trackID).childrenTracks = []; %run processNewborns on them -ProcessNewborns(familyIDs); +% ProcessNewborns(familyIDs); end diff --git a/src/MATLAB/SetPixelSize.m b/src/MATLAB/SetPixelSize.m new file mode 100644 index 0000000000000000000000000000000000000000..addcca60659e096262123a1aa3ec4a0244307bd6 --- /dev/null +++ b/src/MATLAB/SetPixelSize.m @@ -0,0 +1,23 @@ +function SetPixelSize(axisHandle, pixSz) + +%--Mark Winter + + parentHandle = get(axisHandle, 'Parent'); + if ( ~ishandle(parentHandle) ) + return + end + + oldUnits = get(axisHandle, 'Units'); + set(axisHandle, 'Units','pixels'); + + curPos = get(axisHandle, 'Position'); + newPos = [curPos(1:2) pixSz]; + + %figPos = get(parentHandle, 'Position'); + figPos = [1 1 (2*newPos(1:2)+newPos(3:4))]; + + set(parentHandle, 'Position',figPos); + set(axisHandle, 'Position',newPos); + + set(axisHandle, 'Units',oldUnits); +end \ No newline at end of file diff --git a/src/MATLAB/SplitHull.m b/src/MATLAB/SplitHull.m index b2586ef4a2bb8ddc00fe54a243fe0679ab232ca5..1d01f1aa269bfe2dae916da674dbcb5c080e026b 100644 --- a/src/MATLAB/SplitHull.m +++ b/src/MATLAB/SplitHull.m @@ -9,6 +9,7 @@ global CellHulls CellFamilies newHulls = ResegmentHull(CellHulls(hullID), k); if ( isempty(newHulls) ) + newTrackIDs = []; return; end diff --git a/src/MATLAB/TestDataIntegrity.m b/src/MATLAB/TestDataIntegrity.m index 4d5d189d87737d0ab1f1cd8f2b5be4f3156a096c..2f73721a3f61f9e97d2d1da8eee7bdc10ba6b24d 100644 --- a/src/MATLAB/TestDataIntegrity.m +++ b/src/MATLAB/TestDataIntegrity.m @@ -123,4 +123,6 @@ if(~isempty(missingHulls)) end error('HullsList ~= CellHulls'); end + +fprintf('\n'); end