Commit 3981b750 authored by Jean-Yves TINEVEZ's avatar Jean-Yves TINEVEZ
Browse files

Remove files from previous DeProj version.

parent 8b12fa45
function displayCombinedMap(tableOutputDeproj,tableOutputBell,contour3D,outputFolder)
% If not specified, the default display is now in real space (not projected)
% For shape descriptor see publication Zdilla et al. 2016
% Usual call is
% displayCombinedMap(tableOutputDeproj,tableOutputBell,dataCells.cellContour3D)
% close all
scriptVersion = 'displayCombinedMap_v0p5';
nSec = 5; % give 5 sec to the software to save the image before going to the next
if nargin==3
outputFolder = uigetdir(pwd,'Select the output folder');
end
cd(outputFolder);
dataBool.doApical = true;
dataBool.doNeighbours = true;
dataBool.doAreaRatioRP = true;
dataBool.doAreaRatioPB = true;
dataBool.doPerimeter = true;
dataBool.doAnisotropy = true;
dataBool.doCircularity = true;
dataBool.doRoundness = true;
dataBool.doOrientation = true;
% dataBool.doApical = false;
% dataBool.doNeighbours = false;
% dataBool.doAreaRatioRP = false;
% dataBool.doAreaRatioPB = false;
% dataBool.doPerimeter = false;
% dataBool.doAnisotropy = false;
% dataBool.doCircularity = false;
% dataBool.doRoundness = false;
% dataBool.doOrientation = true;
save('displayParameters','scriptVersion','dataBool');
% %% Ask the user for which data to plot => For later...
% prompt = {'Enter the matrix size for x^2:';'Enter the colormap name:'};
% name = 'Please select the variable to display';
% Formats = {};
% Formats(1,1).type = 'list';
% Formats(1,1).style = 'listbox';
% Formats(1,1).items = {'Apical area','Nbr of neighbours','Area ratio (Real/Proj)',...
% 'Area ratio (Proj/Bell)','Perimeter (Real)','Circularity (Real)','Roundness (Real)'};
% Formats(1,1).limits = [0 numel(Formats(1).items)]; % multi-select
% [Answer, Cancelled] = inputsdlg(prompt, name, Formats);
%% Data to plot
% Apical area
if dataBool.doApical
dataVal = tableOutputDeproj.AreaReal;
titleFig = 'Cell apical surface area (Real)';
figName = 'mapApicalArea';
dispPolygonMap(dataVal,titleFig,figName,contour3D,nSec);
end
% Nbr of neighbours
if dataBool.doNeighbours
dataVal = tableOutputDeproj.NbrNeighbours;
titleFig = 'Nbr of neighbours';
figName = 'mapNbrNeighbours';
dispPolygonMap(dataVal,titleFig,figName,contour3D,nSec);
end
% Area ratio (real vs proj)
if dataBool.doAreaRatioRP
dataVal = tableOutputDeproj.AreaReal./tableOutputDeproj.AreaProj;
titleFig = 'Cell apical surface area ratio (Real/Proj)';
figName = 'mapAreaRatio_RP';
dispPolygonMap(dataVal,titleFig,figName,contour3D,nSec);
end
% Area ratio (Proj vs Bell)
if dataBool.doAreaRatioPB
dataVal = tableOutputDeproj.AreaProj./tableOutputBell.AreaBell;
titleFig = 'Cell apical surface area ratio (Proj/Bell)';
figName = 'mapAreaRatio_PB';
dispPolygonMap(dataVal,titleFig,figName,contour3D,nSec);
end
% Perimeter
if dataBool.doPerimeter
dataVal = tableOutputDeproj.PerimeterReal;
titleFig = 'Cell perimeter (Real)';
figName = 'mapPerimeter';
dispPolygonMap(dataVal,titleFig,figName,contour3D,nSec);
end
% Anisotropy (Real) (as calculated by Bellaiche lab: 1-1/elongation)
if dataBool.doAnisotropy
dataVal = tableOutputDeproj.AnisotropyReal;
titleFig = 'Cell anisotropy (Real)';
figName = 'mapAnisotropy';
dispPolygonMap(dataVal,titleFig,figName,contour3D,nSec);
end
% Circularity is a shape descriptor that can mathematically indicate the degree of similarity to a perfect circle
if dataBool.doCircularity % Error in the method
dataVal = (4*pi*(tableOutputDeproj.AreaEllipseReal) ./ (tableOutputDeproj.PerimeterEllipseReal.^2));
titleFig = 'Cell circularity (Real)';
figName = 'mapCircularity';
dispPolygonMap(dataVal,titleFig,figName,contour3D,nSec);
end
% Roundness is similar to circularity but is insensitive to irregular borders along the perimeter
if dataBool.doRoundness
dataVal = 4*tableOutputDeproj.AreaEllipseReal./(pi*(tableOutputDeproj.semiMajAxReal*2).^2);
titleFig = 'Cell roundness (Real)';
figName = 'mapRoundness';
dispPolygonMap(dataVal,titleFig,figName,contour3D,nSec);
end
% Orientation of the cell is representing the orientation of the fitted
% ellipse on the cell contour on the mesh. Vector length is weighted by the
if dataBool.doOrientation
% Arrow length is function of the anisotropy
dataVec = tableOutputDeproj.OrientationEllipseReal.*...
tableOutputDeproj.AnisotropyReal;
% Set the origin of the arrow
dataOri = tableOutputDeproj.centerEllipseReal;
titleFig = 'Cell orientation (Real)';
figName = 'mapOrientation';
dispQuiverMap(dataOri,dataVec,titleFig,figName,nSec);
end
end
function dispPolygonMap(dataVal,titleFig,figName,contour3D,nSec)
%% Preparing the colormap
dataRange = max(dataVal)-min(dataVal);
greyLvlNbr = 200;
color2plot = round(((dataVal-min(dataVal))/dataRange)*(greyLvlNbr-1)+1);
fprintf('displaying: %s\n',titleFig);
dataColor = parula(greyLvlNbr);
%% Plot the figure
figure
hold on
for bioCell = 1:numel(dataVal)
if isnan(dataVal(bioCell))
fprintf('Warning: A value was not set properly: skipping cell %d\n',bioCell);
continue
else
fill3(contour3D{bioCell}.cellCt(:,1),...
contour3D{bioCell}.cellCt(:,2),...
contour3D{bioCell}.cellCt(:,3),...
dataColor(color2plot(bioCell),:), ...
'LineStyle', 'none');
end
end
%% Set axes and colorbar
h = colorbar;
caxis([min(dataVal) max(dataVal)])
axis equal
title(titleFig);
xlabel('X position ({\mu}m)'); ylabel('Y position ({\mu}m)');
zlabel('Z position ({\mu}m)');
savefig(figName)
export_fig(figName,'-png','-m5');
pause(nSec);
end
function dispQuiverMap(dataOri,dataVec,titleFig,figName,nSec)
fprintf('displaying: %s\n',titleFig);
% plot the figure
figure
quiver3(dataOri(:,1),dataOri(:,2),dataOri(:,3),dataVec(:,1),dataVec(:,2),dataVec(:,3),'ShowArrowHead','off')
axis equal
%% Set axes and colorbar
axis equal
title(titleFig);
xlabel('X position ({\mu}m)'); ylabel('Y position ({\mu}m)');
zlabel('Z position ({\mu}m)');
savefig(figName)
export_fig(figName,'-png','-m5');
pause(nSec);
end
function displaySubplotCellContour(cellListError, cellListContour, dim)
% Display the cell contour of a cell list into a subplot
% Display the cells with a fit error
if numel(cellListError) > 20
fprinf('Too many cells were not fitted properly. Only fitting the first 20 cells\n');
nSub = 20;
else
nSub = numel(cellListError);
end
[subPlotSize,~] = numSubplots(nSub);
figure
hold on
for bioCell = 1:nSub
subplot(subPlotSize(1),subPlotSize(2),bioCell)
plot(cellListContour{bioCell}(1,:),cellListContour{bioCell}(2,:))
legend(sprintf('cell %d',cellListError(bioCell)))
end
supAxes=[.08 .08 .84 .84];
[~,~]=suplabel(sprintf('Not fitted cells (in %d dimension)\n',dim) ,'t', supAxes);
end
%% finds the contour around a set of pixels originating from a previous segmentation
function cellContour2D = findContour(contour2Dpos,bmethod,PARAMS)
% find the correct order of the points defining the polygon contour of the
% cell instead of sorted by XY position
% Also create the connectivity pairs
% INPUT
% - contour2Dpos: a cell array with N cells each representing the biological
% cells each of dim = nx2 for the n pixels composing the segmented cell in
% 2D.
% - bmethod: 1 of 4 possibilities of boundary contour method
% - msquare
% - msquareImproved: method improved with dilatation and erosion
% - bwboundary: default Matlab method
% - mask2poly: fex boundary finding method, very close to bwboundary
% although with more options
% OUTPUT
% - cellContout2D: structure with 3 fields
% - cellContour2D.Line: paired vertices matrix to infer the pixel
% connections -> deleted
% - cellContour2D.Vertices: XY sorted vertices -> deleted
% - cellContour2D.cellCt: XY sorted vertices in "CW" order
fprintf('Recreating the cellular contours\n');
%% Create a temporary binary image of each individual cell before applying a boundary finding method
for bioCell = 1:length(contour2Dpos) % for all cells
clear miniContour miniImg
contour2Dpos{bioCell} = round(contour2Dpos{bioCell}/PARAMS.imSettings.latPixSize); % rescale from µm to pix for image creation
miniContour=[contour2Dpos{bioCell}(:,1) contour2Dpos{bioCell}(:,2)]-(min(contour2Dpos{bioCell})-1);
miniImg = zeros(max(miniContour(:,1)),max(miniContour(:,2))); % columns and lines are switched
for i = 1:size(miniContour,1)
miniImg(miniContour(i,1),miniContour(i,2))=1;
end
% append 1 layer in all directions to avoid border effect
% could be merged with the previous paragraph drawing the contour but simpler like this
miniImg = [zeros(1,size(miniImg,2)) ; miniImg ; zeros(1,size(miniImg,2))];
miniImg = [zeros(size(miniImg,1),1) , miniImg , zeros(size(miniImg,1),1)];
% figure;imshow(testIm)
% Fill contour
miniImg = imfill(miniImg,'holes');
switch bmethod
case 'msquare'
% Find contour
[cellContour2D{bioCell}.Lines,cellContour2D{bioCell}.Vertices]=isocontour(miniImg,0.5);
% Replace in full image % -1 for start table at 1 and -1 for
% appened lines
cellContour2D{bioCell}.Vertices = cellContour2D{bioCell}.Vertices+...
min(contour2Dpos{bioCell})-2; % replace in full image % -1 for start table at 1 and -1 for appened lines
case 'msquareImproved'
% Enlarge and erode
miniImg = imresize(miniImg, 2);
selem = ones(3,3); %// square, 8-Negihbours
miniImg = imerode(miniImg, selem);
% Find contour
[cellContour2D{bioCell}.Lines,cellContour2D{bioCell}.Vertices]=isocontour(miniImg,0.5);
% Replace in full image % -1 for start table at 1 and -1 for
% appened lines and /2 for the enlargment
cellContour2D.Vertices = (cellContour2D{bioCell}.Vertices)/2-2+...
min(contour2Dpos{bioCell});
case 'bwboundary'
[boundaries,~] = bwboundaries(miniImg,'noholes');
cellContour2D{bioCell}.cellCt = boundaries{1}+...
min(contour2Dpos{bioCell})-2; % replace in full image % -1 for start table at 1 and -1 for appened lines
case 'mask2poly'
polyCell=mask2poly(miniImg,'Inner','MINDIST');
% switch columns 1 and 2
polyCell(:,3) = polyCell(:,1);
polyCell(:,1) = polyCell(:,2);
polyCell(:,2) = polyCell(:,3);
polyCell(:,3) = [];
cellContour2D{bioCell}.cellCt = polyCell+...
min(contour2Dpos{bioCell})-2; % replace in full image % -1 for start table at 1 and -1 for appened lines
otherwise
fprintf('Error: Unknown contour method: %s\n', bmethod);
end
switch bmethod % this step to reorganize the msquare output
case {'msquare','msquareImproved'}
Ori = 1;
tempVert = zeros(length(cellContour2D{bioCell}.Lines),2);
for lines = 1:length(cellContour2D{bioCell}.Lines)
tempVert(lines,:) = cellContour2D{bioCell}.Vertices(cellContour2D{bioCell}.Lines(Ori,1),:);
Dest = cellContour2D{bioCell}.Lines(Ori,2);
if length(find(cellContour2D{bioCell}.Lines(:,1)==Dest))~=1
fprintf('Error: a contour line is open. Check cell %d at Origin = %d\n',...
bioCell,Dest);
break
end
Ori = find(cellContour2D{bioCell}.Lines(:,1)==Dest);
end
cellContour2D{bioCell}.cellCt = tempVert;
clear tempVert
end
cellContour2D{bioCell}.cellCt = cellContour2D{bioCell}.cellCt*PARAMS.imSettings.latPixSize; % scale back to µm
end
cellContour2D = cellContour2D';
end
\ No newline at end of file
function [tableOutputDeproj, tableOutputBell] = formatTableOuputSurfaceCombine(dataCells,dataSeg)
% Format the important variables into a table output for simpler handling
tableOutputDeproj = table;
tableOutputBell = table;
%% Cell numbering
tableOutputDeproj.Numbers = dataCells.numbers;
tableOutputBell.Numbers = dataSeg.CELLS.numbers(dataCells.numbers);
%% Cell center (ellipse real)
for bioCell = 1:numel(dataCells.numbers)
EllipseRealCenter(bioCell,:) = dataCells.cellContour3D{bioCell}.ellipseReal.center;
end
tableOutputDeproj.EllipseRealCenter = EllipseRealCenter;
%% Cell areas
for bioCell = 1:numel(dataCells.numbers)
areaEllReal(bioCell) = dataCells.cellContour3D{bioCell}.ellipseRotViaOri.areaEllipse;
areaEllProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseProj.areaEllipse;
end
tableOutputDeproj.AreaReal = cell2mat(dataCells.area.areaRealTot);
tableOutputDeproj.AreaProj = cell2mat(dataCells.area.areaProjTot);
tableOutputDeproj.AreaEllReal = areaEllReal';
tableOutputDeproj.AreaEllProj = areaEllProj';
tableOutputBell.AreaBell = dataSeg.CELLS.areas(dataCells.numbers);
%% Cell neighbours
tableOutputDeproj.nbrNeighbours = dataSeg.CELLS.n_neighbors(dataCells.numbers);
tableOutputBell.nbrNeighbours = dataSeg.CELLS.n_neighbors(dataCells.numbers);
%% Cell anisotropy (Bellaiche style) % Change for precalculated values !
for bioCell = 1:numel(dataCells.numbers)
elongationReal(bioCell) = dataCells.cellContour3D{bioCell}.ellipseRotViaOri.semiMajAx / ...
dataCells.cellContour3D{bioCell}.ellipseRotViaOri.semiMinAx;
elongationProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseProj.semiMajAx / ...
dataCells.cellContour2D{bioCell}.ellipseProj.semiMinAx;
elongationBell(bioCell) = dataSeg.CELLS.anisotropies(dataCells.numbers(bioCell));
end
tableOutputDeproj.anisostropyReal = 1-1./elongationReal';
tableOutputDeproj.anisotropyProj = 1-1./elongationProj';
tableOutputBell.anisotropyBell = elongationBell';
%% Cell longer axis
for bioCell = 1:numel(dataCells.numbers)
semiMajorAxisReal(bioCell) = dataCells.cellContour3D{bioCell}.ellipseRotViaOri.semiMajAx;
semiMajorAxisProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseProj.semiMajAx;
end
tableOutputDeproj.semiMajAxisReal = semiMajorAxisReal';
tableOutputDeproj.semiMajAxisProj = semiMajorAxisProj';
%% Cell angle (Projected only)
for bioCell = 1:length(dataCells.numbers)
% angleReal(bioCell) =
% dataCells.cellContour3D{bioCell}.ellipseRotViaOri.alpha; => Not
% calculated yet
angleProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseProj.alpha;
angleBell(bioCell) = dataSeg.CELLS.orientations(dataCells.numbers(bioCell));
end
% tableOutputDeproj.angleReal = angleReal';
tableOutputDeproj.angleProj = angleProj';
tableOutputBell.angleBell = angleBell';
%% Cell orientation real
for bioCell = 1:numel(dataCells.numbers) % Only keep the end point of the vector. The beginning is the ellipse center
if isnan(dataCells.cellContour3D{bioCell}.ellipseReal.normOrientation(1,1))
EllipseRealOrient(bioCell,:) = dataCells.cellContour3D{bioCell}.ellipseReal.normOrientation(1,1);
else
EllipseRealOrient(bioCell,:) = dataCells.cellContour3D{bioCell}.ellipseReal.normOrientation(:,2)-...
dataCells.cellContour3D{bioCell}.ellipseReal.normOrientation(:,1); % Centered on the origin
end
end
tableOutputDeproj.EllipseRealOrient = EllipseRealOrient;
%% Cell perimeters
for bioCell = 1:length(dataCells.numbers)
perimeterReal(bioCell) = dataCells.cellContour3D{bioCell}.perimeterReal;
perimeterProj(bioCell) = dataCells.cellContour2D{bioCell}.perimeterProj;
perimeterEllipseReal(bioCell) = dataCells.cellContour3D{bioCell}.ellipseRotViaOri.perimeterEllipse;
end
tableOutputDeproj.perimeterReal = perimeterReal';
tableOutputDeproj.perimeterProj = perimeterProj';
tableOutputDeproj.perimeterEllipseReal = perimeterEllipseReal';
tableOutputBell.perimeterBell = dataSeg.CELLS.perimeters(dataCells.numbers);
%% Field naming
tableOutputDeproj.Properties.VariableNames = {'cellID' 'centerEllipseReal' 'AreaReal' 'AreaProj' 'AreaEllipseReal' 'AreaEllipseProj'...
'NbrNeighbours' 'AnisotropyReal' 'AnisotropyProj' 'semiMajAxReal' 'semiMajAxProj' 'AngleProj' 'OrientationEllipseReal'...
'PerimeterReal' 'PerimeterProj' 'PerimeterEllipseReal'};
tableOutputBell.Properties.VariableNames = {'cellID' 'AreaBell' 'NbrNeighbours' 'AnisotropyBell' 'AngleBell'...
'PerimeterBell'};
end
Copyright (c) 2007, Douglas M. Schwarz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution
* Neither the name of nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment