Flow cytometry in Cell Death

Flow cytometery for Cancer Biologists

Anjan Kr Dasgupta (Calcutta University)https://scholar.google.com/citations?hl=en&user=9Xc_04IAAAAJ&view_op=list_works&sortby=pubdate
2021-12-02

Cell Death probes

Let us first discuss some flow cytometric probes used in exploring the cellular death.

PI

PI spectrum

PI structure

Annexin V

Fluorescent conjugates of annexin V are commonly used to identify apoptotic cells.

More about biophysical characters of Annexin V

The Annexin V apoptotic scheme

The list of annexin conjugates

https://www.thermofisher.com/in/en/home/life-science/cell-analysis/cell-viability-and-regulation/apoptosis/annexin-v-staining.html?ef_id=Cj0KCQiAifz-BRDjARIsAEElyGI0uAvRJQlBJSl1C0GOnDIBtpWMfUYT-dAYu3fd_K9lZ-3AF8PSIkAaAne0EALw_wcB:G:s&s_kwcid=AL!3652!3!270996052709!e!!g!!annexin%20v&cid=bid_pca_frg_r01_co_cp1359_pjt0000_bid00000_0se_gaw_nt_pur_con&gclid=Cj0KCQiAifz-BRDjARIsAEElyGI0uAvRJQlBJSl1C0GOnDIBtpWMfUYT-dAYu3fd_K9lZ-3AF8PSIkAaAne0EALw_wcB

PE (Annexin conjugate)

Annexin V staining provides a very sensitive method for detecting cellular apoptosis, while propidium iodide (PI) is used to detect necrotic or late apoptotic cells, characterized by the loss of the integrity of the plasma and nuclear membranes.

Table Showing Classifier

Stain Viable Apoptotic LateApoptotic Necrotic
PI 0 0 1 1
PE 0 1 1 0

How it will look in the Scatter plot of Annexin V conjugate-PI

A set of FCS files

library(flowCore)
library(flowClust)
# read files with pattern dct
gh=read.flowSet(files=NULL, path="./isha/5thJan20",pattern="hct")
fnames.h=gh@phenoData@data$name
gc=read.flowSet(files=NULL, path="./isha/5thJan20",invert.pattern="hct")
fnames.c=gc@phenoData@data$name
doublet = function (a,h){
  x=log(a)
  y=log(h)
  l=lm(y~x)
  m=l$coefficients[2]
  c=l$coefficients[1]
  ik=which(y>m*x+c)
return(ik)}
i=4
f=fnames.h[i]
f= paste0('./isha/5thJan20/',sep='',f)
ff=read.FCS(f)
df=data.frame(ff@exprs[,1:6])
attach(df)
a=df$FSC.A
h=df$FSC.H
ik=doublet(a,h)
A=a[ik]
H=h[ik]
plot(a,h,pch=16,cex=0.5)
points(A,H,pch=16,cex=0.5,col="red")

library(flowClust)
# defining a singlet dataframe 
df.singlet=data.frame(sFSC.A=FSC.A[ik],sFSC.H=FSC.H[ik],sSSC.A=SSC.A[ik],sSSC.H=SSC.H[ik],sPE.A=PE.A[ik],sPI.A=PI.A[ik])
#plot(FSC.H,SSC.H,pch=16,cex=0.5)
res1 <- flowClust(df.singlet,
varNames=c("sFSC.H", "sSSC.H"), K=1) 
df2=Subset(df.singlet,res1)
res2<-flowClust(df2, varNames=c("sFSC.H", "sSSC.H"), K=1:3, B=100)
criterion(res2,"BIC")
[1] -129001.3 -123283.7 -122903.8
plot(res2[[3]], data=df2, level=0.8, z.cutoff=0)

Rule of identifying outliers: 80% quantile
ik1=which(res2[[3]]@label==1)
ik2=which(res2[[3]]@label==2)
ik3=which(res2[[3]]@label==3)

A visually interactive gate post-clustering

attach(df.singlet)
iik=which(sFSC.H<100 & sSSC.H<1560)
plot(sFSC.H,sSSC.H,pch=16,col="brown",cex=0.5)
points(sFSC.H[iik],sSSC.H[iik],pch=16,col="blue",cex=0.5)

Fishing the celluar debris out

df.singlet.nodebris = 
  data.frame(mFSC.A=sFSC.A[-iik],mFSC.H=sFSC.H[-iik],mSSC.A=sSSC.A[-iik],mSSC.H=sSSC.H[-iik],mPE.A=sPE.A[-iik],mPI.A=sPI.A[-iik])
plot(df.singlet.nodebris$mFSC.H,df.singlet.nodebris$mSSC.H,pch=16,cex=0.5)

Density plot

res2.den <- density(res2[[3]], data = df.singlet)
plot(res2.den,type="image")

Table showing the cluster population

table(Map(res2,echo=TRUE))

   1    2    3 
1644 2578 1352 

Exploring individual clusers among singlet

attach(df.singlet)
plot(sFSC.H,sSSC.H,pch=16,cex=0.5)
points(sFSC.H[ik3],sSSC.H[ik3],pch=16,cex=0.5,col="blue")

Splitting the clusters

s1=split(df.singlet, res2)[[1]]
s2=split(df.singlet, res2)[[2]]
s3=split(df.singlet, res2)[[3]]
#plot(s1$sFSC.H,s1$sSSC.H,pch=19,col="red",cex=0.1)

plot(s3$sFSC.H,s3$sSSC.H,pch=19,col="green",cex=0.1)
#points(s3$sFSC.H,s3$sSSC.H,pch=19,col="blue",cex=0.1)

Working with the PI-PE

We now have a dataframe with the “iik” s which has actually gated out the singlet as well as the debris population.

attach(df.singlet.nodebris)
plot(mPE.A,mPI.A,pch=16,cex=0.5)

FlowCluster of the double split population

mres1 <- flowClust(df.singlet.nodebris,
varNames=c("mPE.A", "mPI.A"), K=1)
df2m=Subset(df.singlet.nodebris,mres1)
mres2<-flowClust(df2m, varNames=c("mPE.A", "mPI.A"), K=1:2, B=1000)
criterion(mres2,"BIC")
[1] -28032.00 -27490.53
plot(mres2[[2]], data=df2m, level=0.8, z.cutoff=0)

Rule of identifying outliers: 80% quantile
mres2.den <- density(mres2[[2]], data = df.singlet.nodebris)
plot(mres2.den)