Commit 6b667326 authored by Sebastien Herbert's avatar Sebastien Herbert
Browse files

Main Scripts first commit

parents
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_v0p3';
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.doApical = false;
% dataBool.doNeighbours = false;
% dataBool.doAreaRatioRP = false;
% dataBool.doAreaRatioPB = false;
% dataBool.doPerimeter = false;
% dataBool.doAnisotropy = false;
% dataBool.doCircularity = true;
% dataBool.doRoundness = false;
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';
dispMap(dataVal,titleFig,figName,contour3D);
end
% Nbr of neighbours
if dataBool.doNeighbours
dataVal = tableOutputDeproj.NbrNeighbours;
titleFig = 'Nbr of neighbours';
figName = 'mapNbrNeighbours';
dispMap(dataVal,titleFig,figName,contour3D);
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';
dispMap(dataVal,titleFig,figName,contour3D);
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';
dispMap(dataVal,titleFig,figName,contour3D);
end
% Perimeter
if dataBool.doPerimeter
dataVal = tableOutputDeproj.PerimeterReal;
titleFig = 'Cell perimeter (Real)';
figName = 'mapPerimeter';
dispMap(dataVal,titleFig,figName,contour3D);
end
% Anisotropy (Real) (as calculated by Bellaiche lab: 1-1/elongation)
if dataBool.doAnisotropy
dataVal = tableOutputDeproj.AnisotropyReal;
titleFig = 'Cell anisotropy (Real)';
figName = 'mapAnisotropy';
dispMap(dataVal,titleFig,figName,contour3D);
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';
dispMap(dataVal,titleFig,figName,contour3D);
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';
dispMap(dataVal,titleFig,figName,contour3D);
end
end
function dispMap(dataVal,titleFig,figName,contour3D)
%% 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}.VerticesOrdered(:,1),...
contour3D{bioCell}.VerticesOrdered(:,2),...
contour3D{bioCell}.VerticesOrdered(:,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 (µm)'); ylabel('Y position (µm)');
zlabel('Z position (µm)');
savefig(figName)
end
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_v0p2';
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 = false; % keep it that way until bug fix!
% dataBool.doRoundness = true;
dataBool.doApical = false;
dataBool.doNeighbours = false;
dataBool.doAreaRatioRP = false;
dataBool.doAreaRatioPB = false;
dataBool.doPerimeter = false;
dataBool.doAnisotropy = false;
dataBool.doCircularity = true;
dataBool.doRoundness = false;
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';
dispMap(dataVal,titleFig,figName,contour3D);
end
% Nbr of neighbours
if dataBool.doNeighbours
dataVal = tableOutputDeproj.NbrNeighbours;
titleFig = 'Nbr of neighbours';
figName = 'mapNbrNeighbours';
dispMap(dataVal,titleFig,figName,contour3D);
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';
dispMap(dataVal,titleFig,figName,contour3D);
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';
dispMap(dataVal,titleFig,figName,contour3D);
end
% Perimeter
if dataBool.doPerimeter
dataVal = tableOutputDeproj.PerimeterReal;
titleFig = 'Cell perimeter (Real)';
figName = 'mapPerimeter';
dispMap(dataVal,titleFig,figName,contour3D);
end
% Anisotropy (Real) (as calculated by Bellaiche lab: 1-1/elongation)
if dataBool.doAnisotropy
dataVal = tableOutputDeproj.AnisotropyReal;
titleFig = 'Cell anisotropy (Real)';
figName = 'mapAnisotropy';
dispMap(dataVal,titleFig,figName,contour3D);
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 * area) ./ (Perimeter .^ 2);
dataVal = (4*pi*(tableOutputDeproj.AreaReal) ./ (tableOutputDeproj.PerimeterReal.^2));
titleFig = 'Cell circularity (Real)';
figName = 'mapCircularity';
dispMap(dataVal,titleFig,figName,contour3D);
end
% Roundness is similar to circularity but is insensitive to irregular borders along the perimeter
if dataBool.doRoundness
dataVal = 4*tableOutputDeproj.AreaReal./(pi*(tableOutputDeproj.semiMajAxReal*2).^2);
titleFig = 'Cell roundness (Real)';
figName = 'mapRoundness';
dispMap(dataVal,titleFig,figName,contour3D);
end
end
function dispMap(dataVal,titleFig,figName,contour3D)
%% 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}.VerticesOrdered(:,1),...
contour3D{bioCell}.VerticesOrdered(:,2),...
contour3D{bioCell}.VerticesOrdered(:,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 (µm)'); ylabel('Y position (µm)');
zlabel('Z position (µm)');
savefig(figName)
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.VerticesOrdered: 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}.VerticesOrdered = 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}.VerticesOrdered = 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}.VerticesOrdered = tempVert;
clear tempVert
end
cellContour2D{bioCell}.VerticesOrdered = cellContour2D{bioCell}.VerticesOrdered*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 areas
for bioCell = 1:numel(dataCells.numbers)
areaEllReal(bioCell) = dataCells.cellContour3D{bioCell}.ellipseFlatten.areaEllipse;
areaEllProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseFlatten.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)
for bioCell = 1:numel(dataCells.numbers)
elongationReal(bioCell) = dataCells.cellContour3D{bioCell}.ellipseFlatten.semiMajAx / ...
dataCells.cellContour3D{bioCell}.ellipseFlatten.semiMinAx;
elongationProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseFlatten.semiMajAx / ...
dataCells.cellContour2D{bioCell}.ellipseFlatten.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}.ellipseFlatten.semiMajAx;
semiMajorAxisProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseFlatten.semiMajAx;
end
tableOutputDeproj.semiMajAxisReal = semiMajorAxisReal';
tableOutputDeproj.semiMajAxisProj = semiMajorAxisProj';
%% Cell angle (Projected only)
for bioCell = 1:length(dataCells.numbers)
% angleReal(bioCell) =
% dataCells.cellContour3D{bioCell}.ellipseFlatten.alpha; => Not
% calculated yet
angleProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseFlatten.alpha;
angleBell(bioCell) = dataSeg.CELLS.orientations(dataCells.numbers(bioCell));
end
% tableOutputDeproj.angleReal = angleReal';
tableOutputDeproj.angleProj = angleProj';
tableOutputBell.angleBell = angleBell';
%% Cell perimeters
for bioCell = 1:length(dataCells.numbers)
perimeterReal(bioCell) = dataCells.cellContour3D{bioCell}.perimeter3D;
perimeterProj(bioCell) = dataCells.cellContour2D{bioCell}.perimeterProj;
perimeterEllipseReal(bioCell) = dataCells.cellContour3D{bioCell}.ellipseFlatten.perimeterEllipse;
end
tableOutputDeproj.perimeterReal = perimeterReal';
tableOutputDeproj.perimeterProj = perimeterProj';
tableOutputDeproj.perimeterEllipseReal = perimeterEllipseReal';
tableOutputBell.perimeterBell = dataSeg.CELLS.perimeters(dataCells.numbers);
%% Field naming
tableOutputDeproj.Properties.VariableNames = {'cellID' 'AreaReal' 'AreaProj' 'AreaEllipseReal' 'AreaEllipseProj'...
'NbrNeighbours' 'AnisotropyReal' 'AnisotropyProj' 'semiMajAxReal' 'semiMajAxProj' 'AngleProj'...
'PerimeterReal' 'PerimeterProj' 'PerimeterEllipseReal'};
tableOutputBell.Properties.VariableNames = {'cellID' 'AreaBell' 'NbrNeighbours' 'AnisotropyBell' 'AngleBell'...
'PerimeterBell'};
end
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 areas
for bioCell = 1:numel(dataCells.numbers)
areaEllReal(bioCell) = dataCells.cellContour3D{bioCell}.ellipseFlatten.areaEllipse;
areaEllProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseFlatten.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)
for bioCell = 1:numel(dataCells.numbers)
elongationReal(bioCell) = dataCells.cellContour3D{bioCell}.ellipseFlatten.semiMajAx / ...
dataCells.cellContour3D{bioCell}.ellipseFlatten.semiMinAx;
elongationProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseFlatten.semiMajAx / ...
dataCells.cellContour2D{bioCell}.ellipseFlatten.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}.ellipseFlatten.semiMajAx;
semiMajorAxisProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseFlatten.semiMajAx;
end
tableOutputDeproj.semiMajAxisReal = semiMajorAxisReal';
tableOutputDeproj.semiMajAxisProj = semiMajorAxisProj';
%% Cell angle (Projected only)
for bioCell = 1:length(dataCells.numbers)
% angleReal(bioCell) =
% dataCells.cellContour3D{bioCell}.ellipseFlatten.alpha; => Not
% calculated yet
angleProj(bioCell) = dataCells.cellContour2D{bioCell}.ellipseFlatten.alpha;
angleBell(bioCell) = dataSeg.CELLS.orientations(dataCells.numbers(bioCell));
end
% tableOutputDeproj.angleReal = angleReal';
tableOutputDeproj.angleProj = angleProj';
tableOutputBell.angleBell = angleBell';
%% Cell perimeters
for bioCell = 1:length(dataCells.numbers)
perimeterReal(bioCell) = dataCells.cellContour3D{bioCell}.perimeter3D;
perimeterProj(bioCell) = dataCells.cellContour2D{bioCell}.perimeterProj;
perimeterEllipseReal(bioCell) = dataCells.cellContour3D{bioCell}.ellipseFlatten.perimeterEllipse;
end
tableOutputDeproj.perimeterReal = perimeterReal';
tableOutputDeproj.perimeterProj = perimeterProj';
tableOutputDeproj.perimeterEllipseReal = perimeterEllipseReal';
tableOutputBell.perimeterBell = dataSeg.CELLS.perimeters(dataCells.numbers);