https://github.com/OpticalDiffractionTomography/NucleiAnalysis
Tip revision: ee5da0592cb893bac393f5cd19c223a518495c4a authored by Kyoohyun Kim on 20 July 2020, 16:08:37 UTC
Analysis pipeline for RI tomograms
Analysis pipeline for RI tomograms
Tip revision: ee5da05
Nucleus_RI_Analysis.m
clear all
close all
%% Parameters
% input variables:
% Reconimg : RI tomogram (x,y,z)
% res3 : Lateral resolution [um]
% res4 : Axial resolution [um]
% lambda : Illumination wavelength [um]
% fluoImg : colocalized epi-fluorescence image (Green and Red channels
% for FUCCI marker (fluoImg(:,:,1) is Green, fluoImg(:,:,2)
% is red channel fluorescence.
RII=0.19; % RI increment [mL/g] = [fL/pg]
n_m=1.337; % RI of medium
n_s=n_m+0.04; % maximum RI value for images (only visualization pulpose)
%% Matching resolution of fluorescence and RI tomogram
% measured epi-fluorescence image is oversampled.
% By cropping fluorescence images in the Fourier space, the spatial
% resolution of fluorescence images and RI tomogram are matched.
combinedAnalysis=zeros(size(Reconimg,1),size(Reconimg,2),3);
for mm=1:2
temp=fluoImg(:,:,mm);
temp=temp-mean2(temp(end-15:end-5,5:15));
temp=conv2(temp,fspecial('disk',2),'same');
pmap=imgaussfilt(temp,300); % Flattening images
temp=temp-pmap;
temp = wiener2(temp,[5 5]); % Reducing noise
ii=length(temp);
Ftemp=fftshift(fft2(temp./max(max(temp))*255))/(ii^2); % 2D Fourier cropping
Ftemp=Ftemp(end/2-size(Reconimg,1)/2+1:end/2+size(Reconimg,1)/2,end/2-size(Reconimg,1)/2+1:end/2+size(Reconimg,1)/2);
sizeFimg=length(Ftemp);
Ftemp=ifft2(ifftshift(Ftemp))*(sizeFimg^2);
combinedAnalysis(:,:,3-mm)=abs(Ftemp);
end
% Reducing noise in the tomogram
for zz=1:size(Reconimg,3)
temp=conv2(squeeze(Reconimg(:,:,zz)),fspecial('disk',0.7),'same');
temp=temp(3:end-2,3:end-2);
temp=padarray(temp,[2 2],n_m);
Reconimg(:,:,zz)=temp;
end
%% Cell Segmentation #1
% Applying the Otsu's method to segment cell
% Output: 3D masks of individual cell
level = multithresh(Reconimg,1);
cellMap_temp=((Reconimg)>level);
% connect neighboring fractions
se=strel('sphere',4);
cellMap_temp=imfill(cellMap_temp,'holes');
cellMap_temp=imdilate(cellMap_temp,se);
cellMap_temp=imfill(cellMap_temp,'holes');
se=strel('sphere',4);
cellMap_temp=imerode(cellMap_temp,se);
cellMap_temp=bwareaopen(cellMap_temp,500);
% Labeling individual cell by the watershed algorithm
D = bwdist(~cellMap_temp);
D = -D;
D(~cellMap_temp) = -Inf;
cellMap_seg1 = watershed(imhmin(D,3));
cellMap_seg1(~cellMap_temp) = 0;
se=strel('sphere',1);
cellMap_seg1=single(imdilate(cellMap_seg1,se));
%% Nuclei Segmentation #1
% Nuclei are segmented from epi-fluorescence images of FUCCI-stained cells
% Output: 2D mask of nuclei in the FOV
nucMap_seg1=zeros(size(combinedAnalysis,1),size(combinedAnalysis,2));
for cellNum=1:max(max(max(cellMap_seg1)))
cellMap=(cellMap_seg1==(cellNum));
cellMap=imfill(cellMap,'holes');
try
%%
z=-1; % The axial position at the epi-fluorescence is lying at the center of the RI tomogram.
nucMap2=ones(size(combinedAnalysis,1),size(combinedAnalysis,2));
tempVal=max(combinedAnalysis,[],3).*cellMap(:,:,end/2+z);
level = multithresh(tempVal(tempVal>0),1);
nucMap_temp=(max(combinedAnalysis,[],3).*cellMap(:,:,end/2+z))>level;
% segment nuclei in both channels
if level>median(median(max(combinedAnalysis,[],3)))+10
nucMap_temp=imfill(nucMap_temp,'holes');
nucMap_temp=bwareafilt(nucMap_temp,[500 100000]);
nucMap2=nucMap2.*~nucMap_temp;
end
nucMap2=1-nucMap2;
% connect neighboring fractions
se=strel('disk',2);
nucMap_temp=imfill(nucMap2,'holes');
nucMap_temp=imdilate(nucMap_temp,se);
nucMap_temp=imfill(nucMap_temp,'holes');
nucMap_temp=imerode(nucMap_temp,se);
nucMap_seg1=nucMap_seg1+nucMap_temp;
catch
end
end
% Labeling individual nuclei by the watershed algorithm
D = bwdist(~nucMap_seg1);
D = -D;
D(~nucMap_seg1) = -Inf;
nucMap_seg2 = watershed(imhmin(D,3));
nucMap_seg2(~nucMap_seg1) = 0;
se=strel('sphere',1);
nucMap_seg2=single(imdilate(nucMap_seg2,se));
%% Cell Segmentation #2
% weighting nuclear regions labeled in the previous step,
% Nuclei Segmentation #1, to the 3D masks of individual cell
cellMap=cellMap_seg1>0;
cellMap=bwareaopen(cellMap,500);
nucMap=repmat(nucMap_seg2,[1 1 size(cellMap,3)]);
cellMap=cellMap+nucMap;
D = bwdist(~cellMap);
D = -D;
D(~cellMap) = -Inf;
cellMap4 = watershed(imhmin(D,3));
cellMap4(~cellMap) = 0;
se=strel('sphere',1);
cellMap4=single(imdilate(cellMap4,se));
cellMap4(cellMap_seg1==0)=0;
cellMap_seg2=cellMap4;
%% Quantitative Characterization
qData=[];
tic
for cellNum=1:max(max(max(cellMap_seg2)))
cellMap_selected=(cellMap_seg2==(cellNum)); % Choose labeled cells
cellMap_selected=imfill(cellMap_selected,'holes');
[tempX tempY tempZ]=ind2sub(size(cellMap_selected),find(cellMap_selected));
qDataTemp=zeros(1,20);
try
%%
% Erosion of cell mask along the axial direction to take into
% account the lower spatial resolution along the axial direction
kk=1;
[xxx yyy zzz]=meshgrid(-15:15,-15:15,-15:15);
se=real(single((xxx.^2/kk.^2+yyy.^2/kk.^2+zzz.^2/(kk/(res3/res4)+1).^2)<1^2));
cellMap_selected=imerode(cellMap_selected,se);
Reconimg_selected=Reconimg.*cellMap_selected;
%% Surface Area Calculation
% Summation of areas of triangles in the mesh of isosurface of cells
p2 = isosurface(cellMap_selected,0.8);
v = p2.vertices;
v(:,1:2)=v(:,1:2)*res3;
v(:,3)=v(:,3)*res4;
f = p2.faces;
a = v(f(:,2),:) - v(f(:,1),:);
b = v(f(:,3),:) - v(f(:,1),:);
c = cross(a,b,2);
area = 0.5*sum(sqrt(sum(c.^2,2)));
%% Nucleus Segmentation #2
% segment nucleus in the cell selected in 3D
nucleusMap=ones(size(combinedAnalysis,1),size(combinedAnalysis,2));
for mm=1:2
tempVal=combinedAnalysis(:,:,3-mm).*cellMap_selected(:,:,end/2+z);
level = multithresh(tempVal(tempVal>0),1);
nucMap_temp=((combinedAnalysis(:,:,3-mm).*cellMap_selected(:,:,end/2+z))>level(1));
if level>median(median(combinedAnalysis(:,:,3-mm)))+10
nucMap_temp=imfill(nucMap_temp,'holes');
nucMap_temp=bwareafilt(nucMap_temp,[500 100000]);
nucleusMap=nucleusMap.*~nucMap_temp;
end
end
nucleusMap=1-nucleusMap;
% connect neighboring fractions
se=strel('disk',2);
nucMap_temp=imfill(nucleusMap,'holes');
nucMap_temp=imdilate(nucMap_temp,se);
nucMap_temp=imfill(nucMap_temp,'holes');
se=strel('disk',3);
nucMap_temp=imerode(nucMap_temp,se);
se=strel('disk',1);
nucMap_temp=imdilate(nucMap_temp,se);
Reconimg3=Reconimg_selected.*repmat(nucMap_temp,[1 1 size(Reconimg_selected,3)]);
Reconimg3=Reconimg3.*imerode(cellMap_selected,strel('sphere',3));
%
nucleusMap=((Reconimg3)>0);
nucleusMap=imfill(nucleusMap,'holes');
nucleusMap=bwareaopen(nucleusMap,500);
%% Nucleoli Segmentation
% segment nucleoli inside nucleus in RI tomograms, and segment nucleoplasm
level = multithresh(Reconimg3(Reconimg3>0),2);
nucleoliMap=((Reconimg3)>level(2));
nucleoliMap=nucleoliMap.*cellMap_selected;
% connect neighboring fractions
se=strel('sphere',1);
nucleoliMap=imfill(nucleoliMap,'holes');
nucleoliMap=imdilate(nucleoliMap,se);
nucleoliMap=imfill(nucleoliMap,'holes');
nucleoliMap=imerode(nucleoliMap,se);
nucleoliMap=bwareaopen(nucleoliMap,500).*imerode(cellMap_selected,strel('sphere',4));
%
[tempXR tempYR tempZR]=ind2sub(size(cellMap),find(nucleoliMap));
nucleoliRI=(Reconimg_selected).*nucleoliMap;
nucleoplasmRI=(Reconimg_selected).*nucleusMap.*~imdilate(nucleoliMap,strel('sphere',1));
%% Peripheral Region Mask
se=strel('sphere',8);
periMap=imdilate((nucleusMap),se);
se=strel('sphere',2);
periMap=periMap-((nucleusMap+imdilate((nucleoliMap),se))>0);
periMap=(periMap.*cellMap_selected)>0;
%%
nucleusRI=(Reconimg).*((nucleusMap+((nucleoliMap)))>0);
periRI=(Reconimg).*periMap;
periRI(:,:,max(tempZ)-3:end)=0;
cytoplasmRI=(Reconimg_selected).*(~nucleusMap.*~imdilate((nucleoliMap),se));
cytoplasmRI(:,:,max(tempZ)-3:end)=0; % discard RI under coverslip
%% Nuclear Surface Area Calculation
% Summation of areas of triangles in the mesh of isosurface of nuclei
p2 = isosurface(((nucleusMap+((nucleoliMap)))>0),0.8);
v = p2.vertices;
v(:,1:2)=v(:,1:2)*res3;
v(:,3)=v(:,3)*res4;
f = p2.faces;
a = v(f(:,2),:) - v(f(:,1),:);
b = v(f(:,3),:) - v(f(:,1),:);
c = cross(a,b,2);
NucArea = 0.5*sum(sqrt(sum(c.^2,2)));
qDataTemp(20)=NucArea;
%% Quantification #1: Entire cell
%1: 3D Volume
%2: 3D Dry mass
%3: 3D RI
%4: Surface Area
qDataTemp(1)=sum(sum(sum(cellMap_selected))).*(res3.^2*res4);%volume
qDataTemp(2)=sum(sum(sum((Reconimg-1.337).*cellMap_selected))).*(res3.^2*res4)/RII;%mass
qDataTemp(3)=mean(Reconimg_selected(cellMap_selected));
qDataTemp(4)=area;
%% Quantification #2: RI of compartments
%5: 3D Cytoplasm RI
%6: 3D Peripheral RI
%7: 3D Nucleus RI
%8: 3D Nucleolus RI
%9: 3D Nucleoplasm RI
qDataTemp(5)=sum(sum(sum(cytoplasmRI)))./sum(sum(sum(cytoplasmRI>0.1)));
qDataTemp(6)=sum(sum(sum(periRI(:,:,min(tempZR):max(tempZR)))))./sum(sum(sum(periRI(:,:,min(tempZR):max(tempZR))>0.1)));
qDataTemp(7)=sum(sum(sum(nucleusRI)))./sum(sum(sum(nucleusRI>0.1)));
qDataTemp(8)=sum(sum(sum(nucleoliRI)))./sum(sum(sum(nucleoliRI>0.1)));
qDataTemp(9)=sum(sum(sum(nucleoplasmRI)))./sum(sum(sum(nucleoplasmRI>0.1)));
%% Quantification #3: Volume and mass of compartments
%10: 3D Cytoplasm volume
%11: 3D Cytoplasm drymass
%12: 3D Nucleus volume
%13: 3D Nucleus drymass
%14: 3D Nucleolus volume
%15: 3D Nucleolus drymass
%16: 3D Nucleoplasm volume
%17: 3D Nucleoplasm drymass
qDataTemp(10)=sum(sum(sum((cytoplasmRI>0)))).*(res3.^2*res4);%volume
qDataTemp(11)=sum(sum(sum((Reconimg-1.337).*(cytoplasmRI>0)))).*(res3.^2*res4)/RII;%mass
qDataTemp(12)=sum(sum(sum((nucleusRI>0)))).*(res3.^2*res4);%volume
qDataTemp(13)=sum(sum(sum((Reconimg-1.337).*(nucleusRI>0)))).*(res3.^2*res4)/RII;%mass
qDataTemp(14)=sum(sum(sum((nucleoliRI>0)))).*(res3.^2*res4);%volume
qDataTemp(15)=sum(sum(sum((Reconimg-1.337).*(nucleoliRI>0)))).*(res3.^2*res4)/RII;%mass
qDataTemp(16)=sum(sum(sum((nucleoplasmRI>0)))).*(res3.^2*res4);%volume
qDataTemp(17)=sum(sum(sum((Reconimg-1.337).*(nucleoplasmRI>0)))).*(res3.^2*res4)/RII;%mass
%% Quantification #4: Cell Cycle determination
%18: Intensity in Green channel
%19: Intensity in Red channel
if max(max(squeeze(nucleusMap(:,:,end/2+z))))>0
qDataTemp(18)=sum(sum(squeeze(combinedAnalysis(:,:,2).*squeeze(nucleusMap(:,:,end/2+z)))))./sum(sum(squeeze(nucleusMap(:,:,end/2+z))));
qDataTemp(19)=sum(sum(squeeze(combinedAnalysis(:,:,1).*squeeze(nucleusMap(:,:,end/2+z)))))./sum(sum(squeeze(nucleusMap(:,:,end/2+z))));
else
qDataTemp(18)=sum(sum(squeeze(combinedAnalysis(:,:,2).*(squeeze(cytoplasmRI(:,:,end/2+z))>0.1))))./sum(sum((squeeze(cytoplasmRI(:,:,end/2+z))>0.1)));
qDataTemp(19)=sum(sum(squeeze(combinedAnalysis(:,:,1).*(squeeze(cytoplasmRI(:,:,end/2+z))>0.1))))./sum(sum((squeeze(cytoplasmRI(:,:,end/2+z))>0.1)));
end
qData=[qData;qDataTemp];
catch
end
end