Skip to content

Commit

Permalink
Latest update to Seurat analysis with reprocessed data.
Browse files Browse the repository at this point in the history
  • Loading branch information
FloWuenne committed Jan 15, 2024
1 parent a48c822 commit f4d5c82
Show file tree
Hide file tree
Showing 29 changed files with 12,793 additions and 1,645 deletions.
3 changes: 2 additions & 1 deletion analysis/data_analysis.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ These scripts were used to analyze Molecular Cartography data following processi

## Cell type calling
- [Seurat analysis of Molkart output](./molkart.process_quantifications_seurat.Rmd)
- [Misty and abundance analysis](./molkart.misty_neighbourhood_analysis.Rmd)
- [Misty spatial analysis](./molkart.misty_analysis.Rmd)
- [Liana bivariate cell-type analysis](./molecular_cartography_python/molkart.local_analysis_lianaplus.ipynb)

# Lunaphore

Expand Down
1 change: 0 additions & 1 deletion analysis/data_processing.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,3 @@ All downstream processing after nf-core/molkart was performed in R and python us
# Lunaphore

Raw Lunaphore images were processed using [MCMICRO](https://mcmicro.org/). The configurations, parameters and commands used can be found in the following files:

2 changes: 1 addition & 1 deletion analysis/figures.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ editor_options:
# Supplementary Figures

- [Supplementary Figure 1](../figures/Supplementary_Figure_1_Molecular_Cartography_ROIs.png)
- [Supplementary Figure 2](./figures.supplementary_figure_3.html)
- [Supplementary Figure 2](./figures)
- Supplementary Figure 3
- Supplementary Figure 4
- [Supplementary Figure 5](./figures.supplementary_figure_5.html)
15 changes: 8 additions & 7 deletions analysis/figures.supplementary_figure_2.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ source("./code/functions.R")

# Supplementary Figure 2 - Quality control (QC) of Molecular Cartography data

## A) Correlation between technical replicates
The data used in this plot was calculated using the following scripts:

- [molkart.QC_spots](./analysis/molkart.QC_spots.Rmd)
* [Quantification of RNA spots on tissue](./analysis/molecular_cartography_python/molkart.count_spots_on_tissue.ipynb)

The data used in this plot was calculated here:[1_QC_spots.Rmd](../analysis/1_QC_spots.Rmd)
## A) Correlation between technical replicates

```{r}
merge_tx_sums <- vroom("./output/mol_cart/tx_abundances_per_slide.tsv")
merge_tx_sums <- vroom("./output/molkart/tx_abundances_per_slide.tsv")
```

```{r}
Expand Down Expand Up @@ -63,10 +66,9 @@ tx_correlation_plot

## B) Transcripts per uM of tissue

The data used in this plot was calculated here: {1_QC_spots.Rmd}(../analysis/1_count_spots_on_tissue.ipynb)

```{r}
spots_tissue <- vroom("./output/mol_cart/spots_per_tissue.tsv")
spots_tissue <- vroom("./output/molkart/molkart.spots_per_tissue.tsv")
spots_tissue <- spots_tissue %>%
separate(sample, into =c("sample","time","replicate","slide"), sep = "_")

Expand Down Expand Up @@ -100,10 +102,9 @@ spots_per_um <- ggbarplot(spots_tissue,

## C) Principal component analysis between samples

The data used in this plot was calculated here: {1_QC_spots.Rmd}(../analysis/1_QC_spots.Rmd)

```{r}
pcs <- vroom("./output/mol_cart/pca_spots.tsv")
pcs <- vroom("./output/molkart/pca_spots.tsv")
pcs$time <- factor(pcs$time,
levels = c("control","4h","2d","4d"))
```
Expand Down
188 changes: 188 additions & 0 deletions analysis/mistyfy.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
library(tidyverse)
library(mistyR)
library(rlist)
library(FNN)
library(future)
library(cowplot)
library(igraph)
library(ClusterR)

plan(multisession, workers = 8)


# MISTy ----

all.data <- read_tsv("molcart.misty_celltype_table.tsv")

samples <- all.data %>%
pull(sample_ID) %>%
unique()
cts <- all.data %>%
pull(anno_cell_type_lv2) %>%
unique()

cts.names <- make.names(cts, allow_ = FALSE)


samples %>% walk(\(sample){

sample.cells <- all.data %>%
filter(sample_ID == sample) %>%
pull(anno_cell_type_lv2) %>%
map(~ .x == cts) %>%
list.rbind() %>%
`colnames<-`(cts.names) %>%
as_tibble()

sample.pos <- all.data %>%
filter(sample_ID == sample) %>%
select(X_centroid, Y_centroid)

#l <- ceiling(knn.dist(sample.pos, 1) %>% mean())
#l <- 20/0.138
#l <- 50/0.138
l <- 100/0.138

misty.views.cts <- create_initial_view(sample.cells) %>%
add_paraview(sample.pos, l) %>%
rename_view(paste0("paraview.", l), "paraview") %>%
select_markers("intraview", where(~ sd(.) != 0))

run_misty(misty.views.cts, sample, "results_cts_100.sqm", bypass.intra = TRUE)
})


# Output ----

interaction_communities_info <- function(misty.results, concat.views, view,
trim = 0, trim.measure = "gain.R2",
cutoff = 1, resolution = 1) {


inv <- sign((stringr::str_detect(trim.measure, "gain") |
stringr::str_detect(trim.measure, "RMSE", negate = TRUE)) - 0.5)

targets <- misty.results$improvements.stats %>%
dplyr::filter(
measure == trim.measure,
inv * mean >= inv * trim
) %>%
dplyr::pull(target)

view.wide <- misty.results$importances.aggregated %>%
filter(view == !!view) %>%
pivot_wider(
names_from = "Target", values_from = "Importance",
id_cols = -c(view, nsamples)
) %>% mutate(across(-c(Predictor,all_of(targets)), \(x) x = NA))


mistarget <- setdiff(view.wide$Predictor, colnames(view.wide)[-1])
mispred <- setdiff(colnames(view.wide)[-1], view.wide$Predictor)

if(length(mispred) != 0){
view.wide.aug <- view.wide %>% add_row(Predictor = mispred)
} else {
view.wide.aug <- view.wide
}

if(length(mistarget) != 0){
view.wide.aug <- view.wide.aug %>%
bind_cols(mistarget %>%
map_dfc(~tibble(!!.x := NA)))
}

A <- view.wide.aug %>%
column_to_rownames("Predictor") %>%
as.matrix()
A[A < cutoff | is.na(A)] <- 0

## !!! Was buggy
G <- graph.adjacency(A[,rownames(A)], mode = "plus", weighted = TRUE) %>%
set.vertex.attribute("name", value = names(V(.))) %>%
delete.vertices(which(degree(.) == 0))

Gdir <- graph.adjacency(A[,rownames(A)], "directed", weighted = TRUE) %>%
set.vertex.attribute("name", value = names(V(.))) %>%
delete.vertices(which(degree(.) == 0))

C <- cluster_leiden(G, resolution_parameter = resolution, n_iterations = -1)

mem <- membership(C)

Gdir <- set_vertex_attr(Gdir, "community", names(mem), as.numeric(mem))

# careful here the first argument is the predictor and the second the target,
# it might need to come from different view
corrs <- as_edgelist(Gdir) %>% apply(1, \(x) cor(
concat.views[[view]][, x[1]],
concat.views[["intraview"]][, x[2]]
)) %>% replace_na(0)

Gdir <- set_edge_attr(Gdir, "cor", value = corrs)
return(Gdir)
}

groups <- samples %>% str_extract("(?<=sample_).+(?=_r)") %>% unique()

misty.results.g <- groups %>% map(~ collect_results("results_cts_100.sqm", .x))
names(misty.results.g) <- groups

dir.create("misty_figures_100")

misty.results.g %>% iwalk(\(misty.results, cond){
plot.list <- list()
plot_improvement_stats(misty.results, "gain.R2")
plot.list <- list.append(plot.list, last_plot())
plot_interaction_heatmap(misty.results, "paraview", cutoff = 0.5, clean = TRUE, trim = 5)
plot.list <- list.append(plot.list, last_plot())
plot_grid(plotlist = plot.list, ncol = 2)
ggsave(paste0("misty_figures_100/", cond, "_stats.pdf"), width = 10, height = 10)
})

dir.create("graphs", recursive = TRUE)


names(misty.results.g) %>% walk(\(g){
concat.views <- samples %>% str_subset(g) %>% map(\(sample){
sample.cells <- all.data %>%
filter(sample_ID == sample) %>%
pull(anno_cell_type_lv2) %>%
map(~ .x == cts) %>%
list.rbind() %>%
`colnames<-`(cts.names) %>%
as_tibble()

sample.pos <- all.data %>%
filter(sample_ID == sample) %>%
select(X_centroid, Y_centroid)

#l <- ceiling(knn.dist(sample.pos, 1) %>% mean())
#l <- 20/0.138
#l <- 50/0.138
l <- 100/0.138

misty.views.cts <- create_initial_view(sample.cells) %>%
add_paraview(sample.pos, l) %>%
rename_view(paste0("paraview.", l), "paraview") %>%
select_markers("intraview", where(~ sd(.) != 0))

}) %>% list.clean() %>% reduce(\(acc, nxt){
list(
intraview = bind_rows(acc[["intraview"]], nxt[["intraview"]]),
paraview = bind_rows(acc[["paraview"]], nxt[["paraview"]])
)
}, .init = list(intraview = NULL, paraview = NULL))


out <- interaction_communities_info(misty.results.g[[g]], concat.views,
view = "paraview", trim = 5, cutoff = 0.5)
write_graph(out, paste0("graphs/para.100.", g, ".graphml"), "graphml")
})


cellular_neighborhoods <- function(sample.cells, sample.pos, n, k){
misty.views <- create_initial_view(sample.cells) %>% add_paraview(sample.pos, family = "constant", l = n)
clust <- KMeans_rcpp(misty.views[[paste0("paraview.",n)]], k)
return(clust$clusters)
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"text": [
"/Users/florian_wuennemann/miniconda3/envs/spatialomics_MI/lib/python3.11/site-packages/IPython/core/interactiveshell.py:3448: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.\n",
" if await self.run_code(code, result, async_=asy):\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_16373/2441794372.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_11974/747545723.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"\n",
" total_area = gdf_geojson.geometry.area.sum() * 0.138 * 0.138\n"
]
Expand All @@ -87,7 +87,7 @@
"text": [
"/Users/florian_wuennemann/miniconda3/envs/spatialomics_MI/lib/python3.11/site-packages/IPython/core/interactiveshell.py:3448: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.\n",
" if await self.run_code(code, result, async_=asy):\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_16373/2441794372.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_11974/747545723.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"\n",
" total_area = gdf_geojson.geometry.area.sum() * 0.138 * 0.138\n"
]
Expand All @@ -105,7 +105,7 @@
"text": [
"/Users/florian_wuennemann/miniconda3/envs/spatialomics_MI/lib/python3.11/site-packages/IPython/core/interactiveshell.py:3448: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.\n",
" if await self.run_code(code, result, async_=asy):\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_16373/2441794372.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_11974/747545723.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"\n",
" total_area = gdf_geojson.geometry.area.sum() * 0.138 * 0.138\n"
]
Expand All @@ -123,7 +123,7 @@
"text": [
"/Users/florian_wuennemann/miniconda3/envs/spatialomics_MI/lib/python3.11/site-packages/IPython/core/interactiveshell.py:3448: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.\n",
" if await self.run_code(code, result, async_=asy):\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_16373/2441794372.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_11974/747545723.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"\n",
" total_area = gdf_geojson.geometry.area.sum() * 0.138 * 0.138\n"
]
Expand All @@ -141,7 +141,7 @@
"text": [
"/Users/florian_wuennemann/miniconda3/envs/spatialomics_MI/lib/python3.11/site-packages/IPython/core/interactiveshell.py:3448: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.\n",
" if await self.run_code(code, result, async_=asy):\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_16373/2441794372.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_11974/747545723.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"\n",
" total_area = gdf_geojson.geometry.area.sum() * 0.138 * 0.138\n"
]
Expand All @@ -159,7 +159,7 @@
"text": [
"/Users/florian_wuennemann/miniconda3/envs/spatialomics_MI/lib/python3.11/site-packages/IPython/core/interactiveshell.py:3448: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.\n",
" if await self.run_code(code, result, async_=asy):\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_16373/2441794372.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_11974/747545723.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"\n",
" total_area = gdf_geojson.geometry.area.sum() * 0.138 * 0.138\n"
]
Expand All @@ -177,7 +177,7 @@
"text": [
"/Users/florian_wuennemann/miniconda3/envs/spatialomics_MI/lib/python3.11/site-packages/IPython/core/interactiveshell.py:3448: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.\n",
" if await self.run_code(code, result, async_=asy):\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_16373/2441794372.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_11974/747545723.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"\n",
" total_area = gdf_geojson.geometry.area.sum() * 0.138 * 0.138\n"
]
Expand All @@ -195,7 +195,7 @@
"text": [
"/Users/florian_wuennemann/miniconda3/envs/spatialomics_MI/lib/python3.11/site-packages/IPython/core/interactiveshell.py:3448: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.\n",
" if await self.run_code(code, result, async_=asy):\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_16373/2441794372.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"/var/folders/ph/m6mhj3s541799cykzbp3dx0m0000gn/T/ipykernel_11974/747545723.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.\n",
"\n",
" total_area = gdf_geojson.geometry.area.sum() * 0.138 * 0.138\n"
]
Expand All @@ -206,7 +206,7 @@
"df = pd.DataFrame(columns=['tissue_area', 'spot_count'])\n",
"\n",
"## Iterate over each geojson file\n",
"geojson_dir = \"../../references/mol_cart.heart_regions\"\n",
"geojson_dir = \"../../annotations/molkart/heart_regions\"\n",
"spot_dir = \"../../../data/nf_molkart_results/dedup_spots\"\n",
"# Iterate over each file in geojson_dir\n",
"for file in os.listdir(geojson_dir):\n",
Expand Down Expand Up @@ -243,7 +243,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -254,7 +254,7 @@
"df['spots_per_um2'] = df['spot_count'] / df['tissue_area']\n",
"df\n",
"## Write dataframe to csv without rownames and with tab as separator\n",
"df.to_csv(\"../../output/mol_cart/molkart.spots_per_tissue.tsv\", sep='\\t', index=False) \n"
"df.to_csv(\"../../output/molkart/molkart.spots_per_tissue.tsv\", sep='\\t', index=False) "
]
}
],
Expand Down
Loading

0 comments on commit f4d5c82

Please sign in to comment.