MERFISH whole brain spatial transcriptomics (part 2b)#

We can continue to explore our examples looking at the expression of canonical neurotransmitter transporter genes and gene Tac2 over the whole brain.

You need to be connected to the internet to run this notebook and that you have downloaded the example data via the getting started notebook.

import os
import pandas as pd
from pathlib import Path
import numpy as np
import anndata
import time
import matplotlib.pyplot as plt

from abc_atlas_access.abc_atlas_cache.abc_project_cache import AbcProjectCache

%matplotlib inline

We will interact with the data using the AbcProjectCache. This cache object tracks which data has been downloaded and serves the path to the requsted data on disk. For metadata, the cache can also directly serve a up a Pandas Dataframe. See the getting_started notebook for more details on using the cache including installing it if it has not already been.

Change the download_base variable to where you have downloaded the data in your system.

download_base = Path('../../abc_download_root')
abc_cache = AbcProjectCache.from_s3_cache(download_base)
abc_cache.current_manifest
'releases/20240330/manifest.json'

Read in the expanded cell metadata table that was created by the code in part 1.

cell = abc_cache.get_metadata_dataframe(
    directory='MERFISH-C57BL6J-638850',
    file_name='cell_metadata_with_cluster_annotation',
    dtype={"cell_label": str,
           "neurotransmitter": str}
)
cell.set_index('cell_label', inplace=True)

Read in the gene expression dataframe we created in part 2a.

exp = abc_cache.get_metadata_dataframe(
    directory='MERFISH-C57BL6J-638850',
    file_name='example_genes_all_cells_expression',
    dtype={"cell_label": str}
)
exp.set_index('cell_label', inplace=True)
example_genes_all_cells_expression.csv: 100%|██████████| 360M/360M [00:11<00:00, 30.5MMB/s]    

We define a helper functions aggregate_by_metadata to compute the average expression for a given catergory.

def aggregate_by_metadata(df, gnames, value, sort=False) :
    grouped = df.groupby(value)[gnames].mean()
    if sort :
        grouped = grouped.sort_values(by=gnames[0], ascending=False)
    return grouped

Expression of canonical neurotransmitter transporter genes#

During analysis, clusters were assigned neurotransmitter identities based on the expression of of canonical neurotransmitter transporter genes. In this example, we create a dataframe comprising of expression of the 9 solute carrier family genes for all the cells in the dataset. We then group the cells by the assigned neurotransmitter class and compute the mean expression for each group and visualized as a colorized table.

The results are similar that in part 1. Using data from the whole brain, gene Slc17a7 is now most enriched in glutamatergic assigned cells. Gene Slc17a6 is most enriched in noradrenergic, then cholinergic types. Genes Slc6a5, Slc6a3 and Slc6a4 shows high specificity to glycinergic, dopaminergic, serotonergic respectively.

def plot_heatmap(df, fig_width = 8, fig_height = 4, cmap = plt.cm.magma_r, vmin = 0, vmax = 5):

    arr = df.to_numpy()

    fig, ax = plt.subplots()
    fig.set_size_inches(fig_width,fig_height)

    res = ax.imshow(arr, cmap=cmap, aspect='auto', vmin=vmin, vmax=vmax)
    xlabs = df.columns.values
    ylabs = df.index.values

    ax.set_xticks(range(len(xlabs)))
    ax.set_xticklabels(xlabs)

    ax.set_yticks(range(len(ylabs)))
    res = ax.set_yticklabels(ylabs)
ntgenes = ['Slc17a7', 'Slc17a6', 'Slc17a8', 'Slc32a1', 'Slc6a5', 'Slc6a3', 'Slc6a4']
filtered = exp[ntgenes]
joined = cell.join(filtered)
agg = aggregate_by_metadata(joined, ntgenes, 'neurotransmitter')
agg = agg[ntgenes]
plot_heatmap(agg, 8, 3, vmax=4)
../_images/2ad36fb8383506da26985997da76fc75af751aa5030a034307c38f9da04e60f6.png

Grouping expression by dissection region of interest shows that each of these genes have distinct spatial patterns. The MERFISH data allows us to visualize these patterns in anatomical context.

agg = aggregate_by_metadata(joined, ntgenes, 'brain_section_label')
agg = agg.loc[list(reversed(list(agg.index)))]
plot_heatmap(agg, 8, 11, vmax=3)
../_images/0c42859b94749b55a7908d1090c04c200977898943a44473a3d508207f4bdbe9.png

We define a small helper function plot sections to visualize the cells for a specified set of brain sections either by colorized metadata or gene expression.

def plot_sections(df, feature, blist, cmap = None, fig_width = 20, fig_height = 5) :
    
    fig, ax = plt.subplots(1,len(blist))
    fig.set_size_inches(fig_width, fig_height)
    
    for idx,bsl in enumerate(blist):
        
        filtered = df[df['brain_section_label'] == bsl]
        xx = filtered['x']
        yy = filtered['y']
        vv = filtered[feature]
        
        if cmap is not None :
            ax[idx].scatter(xx, yy, s=1.0, c=vv, marker='.', cmap=cmap)
        else :
            ax[idx].scatter(xx, yy, s=1.0, color=vv, marker=".")
            
        ax[idx].axis('equal')
        ax[idx].set_xlim(0, 11)
        ax[idx].set_ylim(11, 0)
        ax[idx].set_xticks([])
        ax[idx].set_yticks([])
        
        ax[idx].set_title("%s" % (bsl))
        
    plt.subplots_adjust(wspace=0.01, hspace=0.01)
    return fig, ax
    

We will use the aggregate by brain section table above to pick a four sections of interest and plot cells in those sections by neurotransmitter type and by each of the transporter genes.

blist = ['C57BL6J-638850.51', 'C57BL6J-638850.31', 'C57BL6J-638850.19', 'C57BL6J-638850.01']
fig, ax = plot_sections(joined, 'neurotransmitter_color', blist, cmap=None)
../_images/53df6b4d3d3e67f32dc9ccb3193fe11b329568b100c97ca9c1f69dc7e10fb36b.png
fig, ax = plot_sections(joined, 'Slc17a7', blist, cmap=plt.cm.magma_r)
../_images/abe20e465f7e2b55ab67f9a36cba315c9a54f7b8e5f73dd8e0ac5f1f516a41ca.png
fig, ax = plot_sections(joined, 'Slc17a6', blist, cmap=plt.cm.magma_r)
../_images/fb6869836e1daf0dce4ee18c5a175111cbfa38f721c0e82f8131e6fdfd5a3162.png
fig, ax = plot_sections(joined, 'Slc17a8', blist, cmap=plt.cm.magma_r)
../_images/c3e2fd13fc250d053b7fd5f823b57c135094c339197c0ca75c2afba6a030a2f4.png
fig, ax = plot_sections(joined, 'Slc32a1', blist, cmap=plt.cm.magma_r)
../_images/1073d7dc955a00c6be6539904b3429bc012b7a642830cec62432dbc9dd69487f.png
fig, ax = plot_sections(joined, 'Slc6a5', blist, cmap=plt.cm.magma_r)
../_images/569d3888bf3bdf3fb016ffb68f71489bd6c7c1df8137b72b04618d8d1d27ba99.png
fig, ax = plot_sections(joined, 'Slc6a3', blist, cmap=plt.cm.magma_r)
../_images/8ddcb498a7b9230fb9732f940614199ef2396f09877f60c54c82349d35a1562a.png
fig, ax = plot_sections(joined, 'Slc6a4', blist, cmap=plt.cm.magma_r)
../_images/83129c4db6e3fecc76a6dea6909e3e46b8e1663a69294e8ebd77a9132c266c26.png

Expression of Tachykinin 2 (Tac2) in the whole brain#

In mice, the tachykinin 2 (Tac2) gene encodes neuropeptide called neurokinin B (NkB). Tac2 is produced by neurons in specific regions of the brain know to be invovled in emotion and social behavior. Based on ISH data from the Allen Mouse Brain Atlas, Tac 2 is sparsely expressed in the mouse isocortex and densely enriched is specific subcortical regions such the medial habenula (MH), the amygdala and hypothalamus.

In this example, we create a dataframe comprising expression values of Tac2 for all cells across the whole brain. As with the single brain section example, grouping expression by neurotransmitter show that Tac2 gene is enriched in cholinergic cell types. With the rest of brain included, we can observe that Tac2 is also enriched in Glut-GABA cell types as well.

exgenes = ['Tac2']
filtered = exp[exgenes]
joined = cell.join(filtered)
agg = aggregate_by_metadata(joined, exgenes, 'neurotransmitter', True)
plot_heatmap(agg, 1, 3)
../_images/c9cb182662173fcd38026dbb9daac5126c62fd14b61bf528c0d0b30ba5c8d192.png

Grouping by class, shows that Tac2 is enriched in class “16 MH-LH Glut” with cells restricted to the medial (MH) and lateral (LH) habenula and a mixture of glutamatergic and cholinergic type and “06 CTX-CGE GABA” GABAergic cells originating from the caudal ganglionic eminence (CGE).

agg = aggregate_by_metadata(joined, exgenes, 'class', True).head(8)
class_list = agg.index[0:2]
plot_heatmap(agg, 1, 3)
../_images/83e356e5823aae0c47a2bd7861fa180c454a0adedd6850771e2a9e4578137daf.png

At the next level, grouping by subclass reveals enrichment is highly anatomically localized cell types such as the medial habenula (MH), bed nuclei of the stria terminalis (BST), spinal nucleus of the trigeminal (SPVC), main olfactory blub (MOB), central amygdalar nucleus (CEA) and arcuate hypothalamic nucleus (ARH).

agg = aggregate_by_metadata(joined, exgenes, 'subclass', True).head(15)
subclass_list = agg.index[0:10]
plot_heatmap(agg, 1, 3)
../_images/6b8362bf1ce319318142e1b981b3e04c6a17c6306ca0bc8607f5088dc65c99d9.png

The MERFISH data allows us to visualize these spatial pattern in anatomical context. We can aggregate Tac2 expression by brain section so that we can find 4 sections where the enriched expression is located. We then visualize cells in those section by Tac2 expression, neurotransmitter identity, cell type classes and subclasses.

agg = aggregate_by_metadata(joined, exgenes, 'brain_section_label', False)
agg = agg.loc[list(reversed(list(agg.index)))]
plot_heatmap(agg, 1, 11, vmax=0.4)
../_images/1c8c6f297865168fb754e836c1478fff3f4ae4ac1ffba514d601430f01589f40.png
blist = ['C57BL6J-638850.69', 'C57BL6J-638850.46', 'C57BL6J-638850.38', 'C57BL6J-638850.01']
fig, ax = plot_sections(joined, 'Tac2', blist, cmap=plt.cm.magma_r)
../_images/27b42510e1ea759960605937e520de914cf9bd1ead6114020ea12dcea2f4e1c6.png
fig, ax = plot_sections(joined, 'neurotransmitter_color', blist, cmap=None)
../_images/67e50de1362dde051aa10a48ee49ff3319392169708b423d6fbc7919284babbb.png
fig, ax = plot_sections(joined, 'class_color', blist, cmap=None)
../_images/4836b8e87cfd94cd7c18ced0832b95d92aa2eff21898741e0f67b13c566cf9ef.png
fig, ax = plot_sections(joined, 'subclass_color', blist, cmap=None)
../_images/cf96ed3e191617c986c7848bd81e3e709e24bf97de4dd261deba5e2aef35a831.png

We can use the Tac2 aggregate by subclass table above and pick out the top 10 most enriched subclasses and plot only them on the same set of brain sections and observed that this set of subclasses is able recapitulate the expression pattern of Tac2.

pred = [x in subclass_list for x in joined['subclass']]
filtered = joined[pred]
fig, ax = plot_sections(filtered, 'subclass_color', blist, cmap=None)
../_images/817bb0ece77a882a438adc19e4d39d14cc82d8d1f62f575a870ff1f1bfe27bbb.png
subclass_list
Index(['088 BST Tac2 Gaba', '145 MH Tac2 Glut',
       '083 CEA-BST Rai14 Pdyn Crh Gaba', '258 SPVC Nmu Glut',
       '043 OB-mi Frmd7 Gaba', '047 Sncg Gaba', '082 CEA-BST Ebf1 Pdyn Gaba',
       '046 Vip Gaba', '103 PVHd-DMH Lhx6 Gaba', '126 ARH-PVp Tbx3 Glut'],
      dtype='object', name='subclass')