Introduction

This R Markdown is meant to facilitate the reproducibility of the findings in https://docs.google.com/document/d/166X4o_6HegeS0uUHRa4ahKedkaVEMeiRagCm7T9nOVU/edit?usp=sharing. Here we specifically focus on the c-Fos and Slide-seq data, as detailed in Figure 7.

First, we load relevant packages.

library(nat)
library(plyr)
library(cocoframer)
library(purrr)
library(rgl)
library(RNifti)
library(tidyverse)
library(ggplot2)
library(ggrepel)
library(RColorBrewer)
library(tidyr)
library(plotly)
library(data.table)
library(dplyr)
'%notin%' = Negate('%in%')

Visualization of Whole-Brain c-Fos and Slide-seq Data

Our first object is to view the c-Fos data at the whole brain level. For this visualization, we limit the voxels shown to those for which we have Slide-seq data, and those that have a non-zero number of c-Fos expressing cells. Here we load the Slide-seq and c-Fos data, limiting the data to voxels where the Slide-seq data is found.

slideseq = readRDS("Data/Vascular/SupportFiles/100um_Celltypes_in_each_Voxel_and_totalsums.rds")
cfos_data = readRDS("Data/cFos/DataFiles/CFOS_data_registeredto_100UmABA_OrganizedbyTimepoint.rds")
slideseq = filter(slideseq, slideseq$total_sums >= 1)
joint = left_join(slideseq, cfos_data)
#For all instances where we have a Slideseq voxel, but do not have a c-Fos score, we set these values to zero
joint[is.na(joint)] <- 0

We load the Allen Brain Atlas mesh and shift it slightly so it has the same coordinates as the c-Fos and Slide-seq data.

structures <- c("root")
mesh_list <- map(structures, ccf_2017_mesh)
names(mesh_list) <- structures
#Shift the ABA to fit the coordinate system
mesh_list$root$vb[2,] = mesh_list$root$vb[2,] - 500
mesh_list$root$vb[3,] = mesh_list$root$vb[3,] - 500

Plot the Slide-seq voxels within the brain.

try(close3d(), silent = TRUE)
plot3d(mesh_list$root, col = "grey", alpha = 0.1, add= TRUE)
plot3d(joint$Voxel_X, joint$Voxel_Y, joint$Voxel_Z, col = "black", add = TRUE)

Plot the c-Fos data for voxels with greater than 0 c-Fos expressing cells that overlap with the Slide-seq voxels for T30:

cfosT30 = select(joint, c("Voxel_ID", "Voxel_X", "Voxel_Y", "Voxel_Z", "Change_T30"))
cfosFinal = filter(cfosT30, cfosT30$Change_T30 > 0)
cfosFinal$Colors = as.numeric(cut(cfosFinal$Change_T30,breaks=50))
voxelcolors = grDevices::palette(viridis::viridis(option="A",n=50,direction = -1))
try(close3d(), silent = TRUE)
plot3d(cfosFinal$Voxel_X,cfosFinal$Voxel_Y,cfosFinal$Voxel_Z,col = cfosFinal$Colors,xlab="Anterior-Posterior",ylab="Inferior-Superior",zlab="Left-Right",size=5, add = TRUE)

For T90:

cfosT90 = select(joint, c("Voxel_ID", "Voxel_X", "Voxel_Y", "Voxel_Z", "Change_T90"))
cfosFinal = filter(cfosT90, cfosT90$Change_T90 > 0)
cfosFinal$Colors = as.numeric(cut(cfosFinal$Change_T90,breaks=50))
voxelcolors = grDevices::palette(viridis::viridis(option="A",n=50,direction = -1))
try(close3d(), silent = TRUE)
plot3d(cfosFinal$Voxel_X,cfosFinal$Voxel_Y,cfosFinal$Voxel_Z,col = cfosFinal$Colors,xlab="Anterior-Posterior",ylab="Inferior-Superior",zlab="Left-Right",size=5, add = TRUE)

For T180:

cfosT180 = select(joint, c("Voxel_ID", "Voxel_X", "Voxel_Y", "Voxel_Z", "Change_T180"))
cfosFinal = filter(cfosT180, cfosT180$Change_T180 > 0)
cfosFinal$Colors = as.numeric(cut(cfosFinal$Change_T180,breaks=50))
voxelcolors = grDevices::palette(viridis::viridis(option="A",n=50,direction = -1))
try(close3d(), silent = TRUE)
plot3d(cfosFinal$Voxel_X,cfosFinal$Voxel_Y,cfosFinal$Voxel_Z,col = cfosFinal$Colors,xlab="Anterior-Posterior",ylab="Inferior-Superior",zlab="Left-Right",size=5, add = TRUE)

Calculating a c-Fos Score

Next, we calculate a whole-brain c-Fos score for each molecular cell type.

time = c("Change_T180", "Change_T90", "Change_T30", "Timepoint_0")
for(point in time){
  running_list = c()
  celltypes = colnames(joint)[1:1937]
  for (type in celltypes){
    ratio = joint[,type]/joint[, "total_sums"]
    cfos_count = joint[,point]
    products = ratio*cfos_count
    cfos_score = sum(products)/sum(joint[,type] != 0)
    newAdd =  data.frame(cfos_score, type, sum(joint[,type] != 0))
    colnames(newAdd) = c("CFOSScore", "CellType", "VoxelsOccupied")
    if(length(running_list) == 0){
      running_list = newAdd
    } else{
      running_list = rbind(running_list, newAdd)
    }
  }
  
  saveRDS(running_list, paste0("Data/cFos/Results/WholeBrain_specific_CFOS_expression_score_", point, ".RDS"))
}

Observing the Spatial Distribution of High Scoring Molecular Cell Types

For each timepoint, we read in the c-Fos scores for each molecular cell type. We filter for significant cell types (those that occupy more than 20 voxels brain wide), and then select the ten highest scoring cell types. We graph these cell types using their centroid.

#Read in cell type centroids
centroids = readRDS("Data/cFos/SupportFiles/Centroids_Slideseq_hr.RDS")

For T0

close3d()
#0
t0 = readRDS("Data/cFos/Results/WholeBrain_specific_CFOS_expression_score_Timepoint_0.RDS")
t0 = filter(t0, t0$VoxelsOccupied > 20)
t0 = t0[order(t0$CFOSScore, decreasing = TRUE),]
t0 = t0[1:10,]
t0 = left_join(t0, centroids)
cols =  c( "lightsalmon", "midnightblue", "wheat","deeppink", "thistle", "greenyellow","slategray","khaki","blueviolet","brown") 
plot3d(mesh_list$root, col = "grey", alpha = 0.1, add= TRUE)
with(t0,plot3d(Voxel_X,Voxel_Y, Voxel_Z,type="s",radius=CFOSScore*10, col=cols, add = TRUE))
close3d()

Now, T30 Unfortuantely, hosting all four of these distinct brains causes the Markdown to exceed Githubs storage limit. Therefore, we provide the code but not the 3D spinning objects for T30, 90, and 180.

#T30
close3d()
t30 = readRDS("Data/cFos/Results/WholeBrain_specific_CFOS_expression_score_Change_T30.RDS")
t30 = filter(t30, t30$VoxelsOccupied > 20)
t30 = t30[order(t30$CFOSScore, decreasing = TRUE),]
t30 = t30[1:10,]
t30 = left_join(t30, centroids)
cols =  c("deepskyblue","darkgreen", "maroon", "darkcyan","darkseagreen", "darkslategray","greenyellow", "gold" ,"darkorchid", "springgreen")   
plot3d(mesh_list$root, col = "grey", alpha = 0.1, add= TRUE)
with(t30,plot3d(Voxel_X,Voxel_Y, Voxel_Z,type="s",radius=CFOSScore*10, col=cols, add = TRUE))

Now, T90

#T90
close3d()
t90 = readRDS("Data/cFos/Results/WholeBrain_specific_CFOS_expression_score_Change_T90.RDS")
t90 = filter(t90, t90$VoxelsOccupied > 20)
t90 = t90[order(t90$CFOSScore, decreasing = TRUE),]
t90 = t90[1:10,]
t90 = left_join(t90, centroids)
cols =  c("deepskyblue","gold", "darkseagreen","maroon","darkgreen","red","darkorange", "darkorchid", "springgreen","chocolate")
plot3d(mesh_list$root, col = "grey", alpha = 0.1, add= TRUE)
with(t90,plot3d(Voxel_X,Voxel_Y, Voxel_Z,type="s",radius=CFOSScore*10, col=cols, add = TRUE))

Now, T180

#T180
close3d()
t180 = readRDS("Data/cFos/Results/WholeBrain_specific_CFOS_expression_score_Change_T180.RDS")
t180 = filter(t180, t180$VoxelsOccupied > 20)
t180 = t180[order(t180$CFOSScore, decreasing = TRUE),]
t180 = t180[1:10,]
t180 = left_join(t180, centroids)
cols =  c("deepskyblue", "red","maroon","darkgreen","darkorange","darkorchid","darkseagreen",  "deeppink", "gold", "mediumblue")  
plot3d(mesh_list$root, col = "grey", alpha = 0.1, add= TRUE)
with(t180,plot3d(Voxel_X,Voxel_Y, Voxel_Z,type="s",radius=CFOSScore*10, col=cols, add = TRUE))

Onset of Experimental Condition

First, we read all the c-Fos scores in and save them as a dataframe

cfos_t30 = readRDS("Data/cFos/Results/WholeBrain_specific_CFOS_expression_score_Change_T30.RDS")
colnames(cfos_t30)[1] = "CFOSScore_T30"

cfos_t90 = readRDS("Data/cFos/Results/WholeBrain_specific_CFOS_expression_score_Change_T90.RDS")
colnames(cfos_t90)[1] = "CFOSScore_T90"
cfos_t90 = select(cfos_t90, c("CFOSScore_T90", "CellType"))

cfos_t180 = readRDS("Data/cFos/Results/WholeBrain_specific_CFOS_expression_score_Change_T180.RDS")
colnames(cfos_t180)[1] = "CFOSScore_T180"
cfos_t180 = select(cfos_t180, c("CFOSScore_T180", "CellType"))

cfos_t0 = readRDS("Data/cFos/Results/WholeBrain_specific_CFOS_expression_score_Timepoint_0.RDS")
colnames(cfos_t0)[1] = "CFOSScore_T0"
cfos_t0 = select(cfos_t0, c("CFOSScore_T0", "CellType"))

allFOS = left_join(cfos_t0, cfos_t30)
allFOS = left_join(allFOS, cfos_t90)
allFOS = left_join(allFOS, cfos_t180) 

allFOS = filter(allFOS, allFOS$VoxelsOccupied > 20)
allFOS = filter(allFOS, !is.na(allFOS$CFOSScore_T30))
#Seperate into major cell classes
allFOS = separate(allFOS, CellType, into = c("Broad"), remove = FALSE, sep = "_")
#Make an average change score, i.e. the average cFOS score over T30, T90 and T180
allFOS = mutate(allFOS, ExperimentalAverage = rowMeans(select(allFOS, c(CFOSScore_T30, CFOSScore_T90, CFOSScore_T180)), na.rm = TRUE))
ex  = filter(allFOS, allFOS$Broad == "Ex") 
headEx = head(arrange(ex,desc(ExperimentalAverage)), n = 15)
tailEx = head(arrange(ex,ExperimentalAverage), n = 15)
excit = rbind(headEx, tailEx)
excit = select(excit, -c("ExperimentalAverage", "VoxelsOccupied", "Broad"))
excit <- melt(setDT(excit), id.vars = c("CellType"), variable.name = "TimePoint")

excit$TimePoint = sub("CFOSScore_", "", excit$TimePoint)
excit$TimePoint  = factor(excit$TimePoint, levels=c("T0", "T30", "T90", "T180"))

p = excit %>%
  mutate(label = if_else(TimePoint == "T180", as.character(CellType), NA_character_)) %>%
  ggplot(aes(x=TimePoint, y=value, group=CellType, colour=CellType)) +
  geom_line(linewidth = 2) + theme_bw() + xlab("Time") + ylab("cFOS Score") + ggtitle("Excitatory")  +
  geom_label_repel(aes(label = label),
                   nudge_x = 1,
                   na.rm = TRUE,max.overlaps = 25) + theme(legend.position = "none")

print(p)

inh  = filter(allFOS, allFOS$Broad == "Inh") 
headInh = head(arrange(inh,desc(ExperimentalAverage)), n = 15)
tailInh = head(arrange(inh,ExperimentalAverage), n = 15)
inhib = rbind(headInh, tailInh)
inhib = select(inhib, -c("ExperimentalAverage", "VoxelsOccupied", "Broad"))
inhib <- melt(setDT(inhib), id.vars = c("CellType"), variable.name = "TimePoint")

inhib$TimePoint = sub("CFOSScore_", "", inhib$TimePoint)
inhib$TimePoint  = factor(inhib$TimePoint, levels=c("T0", "T30", "T90", "T180"))

p = inhib %>%
  mutate(label = if_else(TimePoint == "T180", as.character(CellType), NA_character_)) %>%
  ggplot(aes(x=TimePoint, y=value, group=CellType, colour=CellType)) +
  geom_line(linewidth = 2) + theme_bw() + xlab("Time") + ylab("cFOS Score") + ggtitle("Inhibitory")  +
  geom_label_repel(aes(label = label),
                   nudge_x = 1,
                   na.rm = TRUE,max.overlaps = 25) + theme(legend.position = "none")

print(p)