This script performs cluster-free compositional analysis and expression shift analysis using the R package cacoa (v0.4.0). Since clustering limits our resolution at which changes can be observed, cluster-free analysis is an annotation-independent approach. Cluster-free analysis can reveal changes in subpopulations below the resolution of the utilized annotation.

More info about the package cacoa here: https://github.com/kharchenkolab/cacoa pre-print: https://www.biorxiv.org/content/10.1101/2022.03.15.484475v1.full.pdf Vignette: https://pklab.med.harvard.edu/viktor/cacoa/walkthrough_short.html

Setup

devtools::load_all("/people/nrq364/cacoa_dev") # need to double check if dev version is necessary here
#library(cacoa)
library(magrittr)
library(qs)

1. Read in data

Read in cacoa object generated in notebook 3.

cao <- qread("cao.qs", nthreads = 10)

2. Cluster-free compositional changes

Compute cluster-free compositional changes.

cao$estimateCellDensity(method='graph',n.cores = 50) #alternative: kde (identifies more very small subclusters as changed)

cao$estimateDiffCellDensity(type='wilcox', n.cores = 50) # type = method to calculate differential cell density, options: permutation, t.test, wilcox or subtract (target subtract ref density)

Plot annotated UMAP and for multiple comparison corrected z-scores on the UMAP next to each other. Positive Z adj. means those cells are enriched in the treated condition. Negative Z adj means those cells are more abundant in controls.

plot_grid(cao$plotEmbedding(color.by='cell.groups'), cao$plotDiffCellDensity(legend.position=c(0, 1)), ncol=2)

3. Cluster-free expression shifts

Estimate cluster-free expression shifts (takes a long time, choose many cores). Z score is based on p-value and results in this version of cacoa (v0.4.0) are very conservative.

cao$estimateClusterFreeExpressionShifts(n.top.genes=300, gene.selection = "expression", normalize.both = T, n.cores = 50) 
# normalize.both whether to normalize results relative to distances within both conditions (TRUE) or only to the control (FALSE), "z" means it uses the not adjusted z scores?
# Warning: Setting normalize.both=TRUE likely leads to wrong results for cluster-free shiftsWarning: Please run estimateClusterFreeDE() first to use gene.selection='z' or 'lfc'. Fall back to gene.selection='expression'
p <- cao$plotClusterFreeExpressionShifts(legend.position=c(0, 1), font.size=c(2,3), min.z = 0.5, build.panel = F) # min.z default=qnorm(0.9)=1.28; when I change min.z to 0.5 I see significant results in adj z-scores

p1 <- p[[1]]$data %>%
         arrange(Color)  %>% ggplot(aes(x = x, y = y, color = Color)) + geom_point(size = 0.1) + scale_color_gradient2(mid = "grey90", high = "firebrick",  name = "Z score") + theme_void() # + guides(color=guide_legend(title="Z score")) #midpoint=0.0075,low = "grey95",

p2 <- p[[2]]$data%>%
         arrange(Color) %>% ggplot(aes(x = x, y = y, color = Color)) + geom_point(size = 0.1) + scale_color_gradient2(mid = "grey90", high = "firebrick", name = "Adj. Z score") + theme_void() #+ guides(color=guide_legend(title="Adj.Z score"))  midpoint = 0.3, low = "grey95",

library(patchwork)
p1+p2

LS0tCnRpdGxlOiAiNSkgQ2x1c3Rlci1mcmVlIGFuYWx5c2lzIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogbm9uZQotLS0KClRoaXMgc2NyaXB0IHBlcmZvcm1zIGNsdXN0ZXItZnJlZSBjb21wb3NpdGlvbmFsIGFuYWx5c2lzIGFuZCBleHByZXNzaW9uIHNoaWZ0IGFuYWx5c2lzIHVzaW5nIHRoZSBSIHBhY2thZ2UgY2Fjb2EgKHYwLjQuMCkuClNpbmNlIGNsdXN0ZXJpbmcgbGltaXRzIG91ciByZXNvbHV0aW9uIGF0IHdoaWNoIGNoYW5nZXMgY2FuIGJlIG9ic2VydmVkLCBjbHVzdGVyLWZyZWUgYW5hbHlzaXMgaXMgYW4gYW5ub3RhdGlvbi1pbmRlcGVuZGVudCBhcHByb2FjaC4gQ2x1c3Rlci1mcmVlIGFuYWx5c2lzIGNhbiByZXZlYWwgY2hhbmdlcyBpbiBzdWJwb3B1bGF0aW9ucyBiZWxvdyB0aGUgcmVzb2x1dGlvbiBvZiB0aGUgdXRpbGl6ZWQgYW5ub3RhdGlvbi4KCgpNb3JlIGluZm8gYWJvdXQgdGhlIHBhY2thZ2UgY2Fjb2EgaGVyZTogaHR0cHM6Ly9naXRodWIuY29tL2toYXJjaGVua29sYWIvY2Fjb2EKcHJlLXByaW50OiBodHRwczovL3d3dy5iaW9yeGl2Lm9yZy9jb250ZW50LzEwLjExMDEvMjAyMi4wMy4xNS40ODQ0NzV2MS5mdWxsLnBkZgpWaWduZXR0ZTogaHR0cHM6Ly9wa2xhYi5tZWQuaGFydmFyZC5lZHUvdmlrdG9yL2NhY29hL3dhbGt0aHJvdWdoX3Nob3J0Lmh0bWwKCiMgU2V0dXAKYGBge3J9CmRldnRvb2xzOjpsb2FkX2FsbCgiL3Blb3BsZS9ucnEzNjQvY2Fjb2FfZGV2IikgIyBuZWVkIHRvIGRvdWJsZSBjaGVjayBpZiBkZXYgdmVyc2lvbiBpcyBuZWNlc3NhcnkgaGVyZQojbGlicmFyeShjYWNvYSkKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShxcykKYGBgCgojIDEuIFJlYWQgaW4gZGF0YQpSZWFkIGluIGNhY29hIG9iamVjdCBnZW5lcmF0ZWQgaW4gbm90ZWJvb2sgMy4KYGBge3J9CmNhbyA8LSBxcmVhZCgiY2FvLnFzIiwgbnRocmVhZHMgPSAxMCkKYGBgCgojIDIuIENsdXN0ZXItZnJlZSBjb21wb3NpdGlvbmFsIGNoYW5nZXMKQ29tcHV0ZSBjbHVzdGVyLWZyZWUgY29tcG9zaXRpb25hbCBjaGFuZ2VzLgpgYGB7cn0KY2FvJGVzdGltYXRlQ2VsbERlbnNpdHkobWV0aG9kPSdncmFwaCcsbi5jb3JlcyA9IDUwKSAjYWx0ZXJuYXRpdmU6IGtkZSAoaWRlbnRpZmllcyBtb3JlIHZlcnkgc21hbGwgc3ViY2x1c3RlcnMgYXMgY2hhbmdlZCkKCmNhbyRlc3RpbWF0ZURpZmZDZWxsRGVuc2l0eSh0eXBlPSd3aWxjb3gnLCBuLmNvcmVzID0gNTApICMgdHlwZSA9IG1ldGhvZCB0byBjYWxjdWxhdGUgZGlmZmVyZW50aWFsIGNlbGwgZGVuc2l0eSwgb3B0aW9uczogcGVybXV0YXRpb24sIHQudGVzdCwgd2lsY294IG9yIHN1YnRyYWN0ICh0YXJnZXQgc3VidHJhY3QgcmVmIGRlbnNpdHkpCmBgYAoKUGxvdCBhbm5vdGF0ZWQgVU1BUCBhbmQgZm9yIG11bHRpcGxlIGNvbXBhcmlzb24gY29ycmVjdGVkIHotc2NvcmVzIG9uIHRoZSBVTUFQIG5leHQgdG8gZWFjaCBvdGhlci4KUG9zaXRpdmUgWiBhZGouIG1lYW5zIHRob3NlIGNlbGxzIGFyZSBlbnJpY2hlZCBpbiB0aGUgdHJlYXRlZCBjb25kaXRpb24uCk5lZ2F0aXZlIFogYWRqIG1lYW5zIHRob3NlIGNlbGxzIGFyZSBtb3JlIGFidW5kYW50IGluIGNvbnRyb2xzLgpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTUsIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQpwbG90X2dyaWQoY2FvJHBsb3RFbWJlZGRpbmcoY29sb3IuYnk9J2NlbGwuZ3JvdXBzJyksIGNhbyRwbG90RGlmZkNlbGxEZW5zaXR5KGxlZ2VuZC5wb3NpdGlvbj1jKDAsIDEpKSwgbmNvbD0yKQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZ9CiMgRHJhdyBjb250b3VyIGFyb3VuZCBhZmZlY3RlZCBjZWxsIHR5cGVzLgojIFRha2VzIHZlcnkgbG9uZyB0byBwbG90LCBtYXliZSB0cnkgYXMgYmFja2dyb3VuZCBqb2IgaW4gUi4gRXZlbiBhcyBzY3JpcHQgaXQgZGlkIG5vdCBmaW5pc2ggYWZ0ZXIgMTdoCgpjYW8kcGxvdERpZmZDZWxsRGVuc2l0eSh0eXBlID0gIndpbGNveCIsIG1pbi56ID0gMCwgYWRqdXN0LnB2YWx1ZXMgPSBULCAgY29udG91cnMgPSBjKCJIaWdobHlfcHJvbGlmZXJhdGl2ZV9SR19TIiwgIkhpZ2hseV9wcm9saWZlcmF0aXZlX1JHX0cyTSIpLCBjb250b3VyLmNvbmYgPSAiMjAlIikKYGBgCgojIDMuIENsdXN0ZXItZnJlZSBleHByZXNzaW9uIHNoaWZ0cwpFc3RpbWF0ZSBjbHVzdGVyLWZyZWUgZXhwcmVzc2lvbiBzaGlmdHMgKHRha2VzIGEgbG9uZyB0aW1lLCBjaG9vc2UgbWFueSBjb3JlcykuIFogc2NvcmUgaXMgYmFzZWQgb24gcC12YWx1ZSBhbmQgcmVzdWx0cyBpbiB0aGlzIHZlcnNpb24gb2YgY2Fjb2EgKHYwLjQuMCkgYXJlIHZlcnkgY29uc2VydmF0aXZlLgoKYGBge3J9CmNhbyRlc3RpbWF0ZUNsdXN0ZXJGcmVlRXhwcmVzc2lvblNoaWZ0cyhuLnRvcC5nZW5lcz0zMDAsIGdlbmUuc2VsZWN0aW9uID0gImV4cHJlc3Npb24iLCBub3JtYWxpemUuYm90aCA9IFQsIG4uY29yZXMgPSA1MCkgCiMgbm9ybWFsaXplLmJvdGggd2hldGhlciB0byBub3JtYWxpemUgcmVzdWx0cyByZWxhdGl2ZSB0byBkaXN0YW5jZXMgd2l0aGluIGJvdGggY29uZGl0aW9ucyAoVFJVRSkgb3Igb25seSB0byB0aGUgY29udHJvbCAoRkFMU0UpLCAieiIgbWVhbnMgaXQgdXNlcyB0aGUgbm90IGFkanVzdGVkIHogc2NvcmVzPwojIFdhcm5pbmc6IFNldHRpbmcgbm9ybWFsaXplLmJvdGg9VFJVRSBsaWtlbHkgbGVhZHMgdG8gd3JvbmcgcmVzdWx0cyBmb3IgY2x1c3Rlci1mcmVlIHNoaWZ0c1dhcm5pbmc6IFBsZWFzZSBydW4gZXN0aW1hdGVDbHVzdGVyRnJlZURFKCkgZmlyc3QgdG8gdXNlIGdlbmUuc2VsZWN0aW9uPSd6JyBvciAnbGZjJy4gRmFsbCBiYWNrIHRvIGdlbmUuc2VsZWN0aW9uPSdleHByZXNzaW9uJwpgYGAKCgpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTR9CnAgPC0gY2FvJHBsb3RDbHVzdGVyRnJlZUV4cHJlc3Npb25TaGlmdHMobGVnZW5kLnBvc2l0aW9uPWMoMCwgMSksIGZvbnQuc2l6ZT1jKDIsMyksIG1pbi56ID0gMC41LCBidWlsZC5wYW5lbCA9IEYpICMgbWluLnogZGVmYXVsdD1xbm9ybSgwLjkpPTEuMjg7IHdoZW4gSSBjaGFuZ2UgbWluLnogdG8gMC41IEkgc2VlIHNpZ25pZmljYW50IHJlc3VsdHMgaW4gYWRqIHotc2NvcmVzCgpwMSA8LSBwW1sxXV0kZGF0YSAlPiUKICAgICAgICAgYXJyYW5nZShDb2xvcikgICU+JSBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSBDb2xvcikpICsgZ2VvbV9wb2ludChzaXplID0gMC4xKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50MihtaWQgPSAiZ3JleTkwIiwgaGlnaCA9ICJmaXJlYnJpY2siLCAgbmFtZSA9ICJaIHNjb3JlIikgKyB0aGVtZV92b2lkKCkgIyArIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQodGl0bGU9Ilogc2NvcmUiKSkgI21pZHBvaW50PTAuMDA3NSxsb3cgPSAiZ3JleTk1IiwKCnAyIDwtIHBbWzJdXSRkYXRhJT4lCiAgICAgICAgIGFycmFuZ2UoQ29sb3IpICU+JSBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSBDb2xvcikpICsgZ2VvbV9wb2ludChzaXplID0gMC4xKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50MihtaWQgPSAiZ3JleTkwIiwgaGlnaCA9ICJmaXJlYnJpY2siLCBuYW1lID0gIkFkai4gWiBzY29yZSIpICsgdGhlbWVfdm9pZCgpICMrIGd1aWRlcyhjb2xvcj1ndWlkZV9sZWdlbmQodGl0bGU9IkFkai5aIHNjb3JlIikpICBtaWRwb2ludCA9IDAuMywgbG93ID0gImdyZXk5NSIsCgpsaWJyYXJ5KHBhdGNod29yaykKcDErcDIKYGBgCgoKYGBge3IsIGluY2x1ZGU9Rn0KI2VzdGltYXRlIGNsdXN0ZXItZnJlZSBERSBmaXJzdAojRXN0aW1hdGluZyBjbHVzdGVyLWZyZWUgWi1zY29yZXMgZm9yIDMwMCBtb3N0IGV4cHJlc3NlZCBnZW5lcy4KI3Rha2VzIHZlcnkgbG9uZyB0byBjYWxjdWxhdGUuLi4KI2NhbyRlc3RpbWF0ZUNsdXN0ZXJGcmVlREUobi50b3AuZ2VuZXM9MzAwLCBtaW4uZXhwci5mcmFjPTAuMDEsIGFkanVzdC5wdmFsdWVzPVRSVUUsIHNtb290aD1UUlVFLCB2ZXJib3NlPVRSVUUpCmBgYA==