Skip to content
Snippets Groups Projects
ImageAnalysisGolgi3D_PerField.m 5.74 KiB
Newer Older
MatthieuGobin's avatar
MatthieuGobin committed
function [Objects] = ImageAnalysisGolgi3D_PerField(ch1,ch2,InfoTableThis, PreviewPath)
%UNTITLED Summary of this function goes here
%   Detailed explanation goes here
%vol(ch1)
%vol(ch2, 0, 1000)
    %% Segment nuclei
    NucleiBlurred = imfilter(ch1, fspecial('gaussian',5, 4)); % vol(NucleiBlurred)
    NucleiMask = NucleiBlurred > 50; % vol(NucleiMask)
        if sum(NucleiMask(:))== 0
            Objects = {}; 
            return
        end
    %% Segment Golgi
    GolgiDoG = imfilter(ch2, fspecial('gaussian', 7, 1), 'symmetric') - imfilter(ch2, fspecial('gaussian', 7, 2), 'symmetric'); % vol(GolgiDoG, 0, 100, 'hot')
    GolgiMaskLocal = GolgiDoG > 10; % vol(GolgiMaskLocal)
    GolgiMask = GolgiMaskLocal; % & GolgiGlobalMask;
    GolgiMask = bwareaopen (GolgiMask, 7);
    if sum(GolgiMask(:))== 0
            Objects = {}; 
            return
        end% vol(GolgiMask)

    %% Morphometrics
    GolgiLM = bwlabeln(GolgiMask);
    GolgiObjects = regionprops('table', GolgiLM, {'Area'});
    %% Extract features

    Objects = table();
    Objects.File = InfoTableThis.files;
    Objects.Barcode = InfoTableThis.Barcode;
    Objects.AreaName = InfoTableThis.AreaName;
    Objects.ROW = InfoTableThis.Row;
    Objects.COL = InfoTableThis.Column;
    Objects.Field = InfoTableThis.field;
    %% Nucleus derived
    Objects.NucArea = sum(NucleiMask(:));
    %% Golgi derived
    Objects.GolgiArea = sum(GolgiMask(:));% ATPB plus Tom20
    Objects.GolgiAreaNorm = sum(GolgiMask(:))/sum(NucleiMask(:));
    voxelSizeX = 0.2152;%Bin2
    voxelSizeY = 0.2152; 
    voxelSizeZ = 1;
    Objects.MinGolgiVol = min(GolgiObjects.Area) * voxelSizeX * voxelSizeY * voxelSizeZ;
    Objects.MaxGolgiVol = max(GolgiObjects.Area) * voxelSizeX * voxelSizeY * voxelSizeZ;
    Objects.MeanGolgiVol = mean(GolgiObjects.Area) * voxelSizeX * voxelSizeY * voxelSizeZ;
    Objects.StdGolgiVol = std(GolgiObjects.Area) * voxelSizeX * voxelSizeY * voxelSizeZ;
    Objects.MedGolgiVol = median(GolgiObjects.Area) * voxelSizeX * voxelSizeY * voxelSizeZ;
    Objects.MadGolgiVol = mad(GolgiObjects.Area, 1) * voxelSizeX * voxelSizeY * voxelSizeZ;
    Objects.TotGolgiVolume = sum(GolgiMask(:)) * voxelSizeX * voxelSizeY * voxelSizeZ;
    Objects.TotGolgiVolumeNorm = (sum(GolgiMask(:)) * voxelSizeX * voxelSizeY * voxelSizeZ)/sum(NucleiMask(:));
    Objects.CountGolgi = size(GolgiObjects, 1);  
    Objects.CountGolgiNorm = size(GolgiObjects, 1)/sum(NucleiMask(:));
    Objects.AreaVectors = {GolgiObjects.Area};
 
    % Shape
    Conn6Strel = {};
    Conn6Strel{1} = [0 0 0; 0 1 0; 0 0 0];
    Conn6Strel{2} = [0 1 0; 1 1 1; 0 1 0];
    Conn6Strel{3} = [0 0 0; 0 1 0; 0 0 0];
    Conn6Strel = logical(cat(3, Conn6Strel{:}));
    GolgiErodedMask = imerode(GolgiMask, Conn6Strel);
    GolgiPerimMask = (GolgiMask - GolgiErodedMask) > 0;

    % skeleton  
    skel = Skeleton3D(GolgiMask);    
    
    [AdjacencyMatrix, node, link] = Skel2Graph3D(skel,0); % 0 for keeping all branches 

    %% Additional feature images and vectors
    GolgiBodyLabelIm = bwlabeln(GolgiErodedMask, 6);
    Objects.NodeDegreeVector = {sum(AdjacencyMatrix, 1)};

    % Erosion derived
    Objects.GolgiSkelPixels = sum(skel(:));
    Objects.GolgiPerimPixels = sum(GolgiPerimMask(:));
    Objects.GolgiBodyPixels = sum(GolgiErodedMask(:)); 
    Objects.GolgiBodyCount = max(GolgiBodyLabelIm(:)); % Needed for invagination feature
    Objects.GolgiShapeBySurface = Objects.GolgiBodyPixels / Objects.GolgiPerimPixels; % Roundness feature
    Objects.GolgiBodycountByGolgicount = Objects.GolgiBodyCount / Objects.CountGolgi; % Invagination feature

    % Skeleton derived
    Objects.TotalNodeCount = size(node, 2);
    Objects.AverageNodePerGolgi = Objects.TotalNodeCount / Objects.CountGolgi;
    Objects.TotalLinkCount = size(link, 2);
    Objects.NodesPerGolgiMean = Objects.TotalNodeCount / Objects.CountGolgi;
    Objects.LinksPerGolgiMean = Objects.TotalLinkCount / Objects.CountGolgi;
    Objects.AverageNodeDegree = mean(Objects.NodeDegreeVector{:}); %average lenght of branch in pixels
    Objects.MedianNodeDegree = median(Objects.NodeDegreeVector{:});
    Objects.StdNodeDegree = std(Objects.NodeDegreeVector{:});
    Objects.MadNodeDegree = mad(Objects.NodeDegreeVector{:}, 1);
       
    %% 2D previews
    
    % Scalebar
    imSize = size(ch1);
    [BarMask, BarCenter] = f_barMask(20, voxelSizeX, imSize, imSize(1)-100, 100, 10);
    %vol(BarMask)
    RGB = cat(3, imadjust(ch2(:,:,3)),zeros([size(ch1,1),size(ch1,2)], 'uint16'), imadjust(ch1(:,:,3)));
    %RGB = cat(3, imadjust(max(ch2, [], 3), [0; 0.01],[0; 1]),zeros([size(ch1,1),size(ch1,2)], 'uint16'), imadjust(max(ch1, [], 3)));
    RGB = imoverlay(RGB, BarMask, [1 1 1]);
    % imtool(RGB)
  
    GolgiMaskPreview = imoverlay(imadjust(max(ch2, [], 3)), bwperim(max(GolgiMask, [], 3)), [1 0 0]);
    GolgiMaskPreview = imoverlay(GolgiMaskPreview, BarMask, [1 1 1]);
    %imtool(GolgiMaskPreview )
    GolgiRawPreview = imadjust(max(ch2, [], 3));
    GolgiRawPreview = imoverlay(GolgiRawPreview, BarMask, [1 1 1]);
    %imtool(GolgiRawPreview)
    
    SavePathGolgiMaskPreview = [PreviewPath, filesep, Objects.Barcode{:}, '_', num2str(Objects.ROW), '_', num2str(Objects.COL), '_', num2str(Objects.Field), '_Golgi_mask.png'];
    SavePathGolgirawPreview = [PreviewPath, filesep, Objects.Barcode{:}, '_', num2str(Objects.ROW), '_', num2str(Objects.COL), '_', num2str(Objects.Field), '_Golgi_raw.png'];
    SavePathRGBPreview = [PreviewPath, filesep, Objects.Barcode{:}, '_', num2str(Objects.ROW), '_', num2str(Objects.COL), '_', num2str(Objects.Field), '_RGB.png'];
   
   
    imwrite(GolgiMaskPreview, SavePathGolgiMaskPreview)
    imwrite(GolgiRawPreview,  SavePathGolgirawPreview)
    imwrite(RGB, SavePathRGBPreview)

end