Aligning partial coronal brain sections with the Allen Brain Altas

In this notebook, we align a STARmap dataset of a the right hemisphere of a mouse brain to the Allen Brain Atlas.

We will use STalign to achieve this alignment. We will first load the relevant code libraries.

[1]:
#Import dependencies

import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd # for csv.
from matplotlib import cm
from matplotlib.lines import Line2D
import os
from os.path import exists,split,join,splitext
from os import makedirs
import glob
import requests
from collections import defaultdict
import nrrd
import torch
from torch.nn.functional import grid_sample
import tornado
from STalign import STalign
import copy
import pandas as pd

We have already downloaded STARmap datasets and stored them in a folder called starmap_data.

Now, we can read in the cell infomation using pandas as pd.

We must load all cell x and y positions into the variable x and y respectively. Importantly, the scale of the loaded data must approximately match the Allen Brain Atlas, where ~1 pixel unit is ~1 um

[2]:
#Load file

filename = '__'
df = pd.read_csv('../starmap_data/well11_spatial.csv.gz')

#Load x position
x = np.array(df['X'])[1:].astype(float) #change to x positions of cells

#Load y position
y = np.array(df['Y'])[1:].astype(float) #change to column y positions of cells

[3]:
dx=50
blur = 1

Now we can load in data from the Allen Brain Altas.

We need to load in and save files containing the ontology of regions, a 3D cell density atlas, and annotations of brain regions in the aforementioned 3D atlas.

Depending on which Allen Atlas you would like to use, you can change the url that you download these files from. In this example, we are aligning the adult mouse (P56) Allen Atlas.

[4]:
url = 'http://api.brain-map.org/api/v2/data/query.csv?criteria=model::Structure,rma::criteria,[ontology_id$eq1],rma::options[order$eq%27structures.graph_order%27][num_rows$eqall]'

ontology_name,namesdict = STalign.download_aba_ontology(url, 'allen_ontology.csv') #url for adult mouse
<Response [200]>
[5]:
imageurl = 'http://download.alleninstitute.org/informatics-archive/current-release/mouse_ccf/ara_nissl/ara_nissl_50.nrrd'
labelurl = 'http://download.alleninstitute.org/informatics-archive/current-release/mouse_ccf/annotation/ccf_2017/annotation_50.nrrd'
imagefile, labelfile = STalign.download_aba_image_labels(imageurl, labelurl, 'aba_nissl.nrrd', 'aba_annotation.nrrd')

Our first step in this alignment will be to rasterize the single cell centroid positions into an image. This converts our x and y arrays of cells into a pixelated image. For this example, we choose to rasterize at a resolution of 15 (um).

[6]:
#Rasterize Image
X_,Y_,W = STalign.rasterize(x,y,dx=dx, blur = blur,draw=False)
[7]:
X_
[7]:
array([-1.42879227e+03, -1.37879227e+03, -1.32879227e+03, -1.27879227e+03,
       -1.22879227e+03, -1.17879227e+03, -1.12879227e+03, -1.07879227e+03,
       -1.02879227e+03, -9.78792270e+02, -9.28792270e+02, -8.78792270e+02,
       -8.28792270e+02, -7.78792270e+02, -7.28792270e+02, -6.78792270e+02,
       -6.28792270e+02, -5.78792270e+02, -5.28792270e+02, -4.78792270e+02,
       -4.28792270e+02, -3.78792270e+02, -3.28792270e+02, -2.78792270e+02,
       -2.28792270e+02, -1.78792270e+02, -1.28792270e+02, -7.87922701e+01,
       -2.87922701e+01,  2.12077299e+01,  7.12077299e+01,  1.21207730e+02,
        1.71207730e+02,  2.21207730e+02,  2.71207730e+02,  3.21207730e+02,
        3.71207730e+02,  4.21207730e+02,  4.71207730e+02,  5.21207730e+02,
        5.71207730e+02,  6.21207730e+02,  6.71207730e+02,  7.21207730e+02,
        7.71207730e+02,  8.21207730e+02,  8.71207730e+02,  9.21207730e+02,
        9.71207730e+02,  1.02120773e+03,  1.07120773e+03,  1.12120773e+03,
        1.17120773e+03,  1.22120773e+03,  1.27120773e+03,  1.32120773e+03,
        1.37120773e+03,  1.42120773e+03,  1.47120773e+03,  1.52120773e+03,
        1.57120773e+03,  1.62120773e+03,  1.67120773e+03,  1.72120773e+03,
        1.77120773e+03,  1.82120773e+03,  1.87120773e+03,  1.92120773e+03,
        1.97120773e+03,  2.02120773e+03,  2.07120773e+03,  2.12120773e+03,
        2.17120773e+03,  2.22120773e+03,  2.27120773e+03,  2.32120773e+03,
        2.37120773e+03,  2.42120773e+03,  2.47120773e+03,  2.52120773e+03,
        2.57120773e+03,  2.62120773e+03,  2.67120773e+03,  2.72120773e+03,
        2.77120773e+03,  2.82120773e+03,  2.87120773e+03,  2.92120773e+03,
        2.97120773e+03,  3.02120773e+03,  3.07120773e+03,  3.12120773e+03,
        3.17120773e+03,  3.22120773e+03,  3.27120773e+03,  3.32120773e+03,
        3.37120773e+03,  3.42120773e+03,  3.47120773e+03,  3.52120773e+03,
        3.57120773e+03,  3.62120773e+03,  3.67120773e+03,  3.72120773e+03,
        3.77120773e+03,  3.82120773e+03,  3.87120773e+03,  3.92120773e+03,
        3.97120773e+03,  4.02120773e+03,  4.07120773e+03,  4.12120773e+03,
        4.17120773e+03,  4.22120773e+03,  4.27120773e+03,  4.32120773e+03,
        4.37120773e+03,  4.42120773e+03,  4.47120773e+03,  4.52120773e+03,
        4.57120773e+03,  4.62120773e+03,  4.67120773e+03,  4.72120773e+03,
        4.77120773e+03,  4.82120773e+03,  4.87120773e+03,  4.92120773e+03,
        4.97120773e+03,  5.02120773e+03,  5.07120773e+03,  5.12120773e+03,
        5.17120773e+03,  5.22120773e+03,  5.27120773e+03,  5.32120773e+03,
        5.37120773e+03,  5.42120773e+03,  5.47120773e+03,  5.52120773e+03,
        5.57120773e+03,  5.62120773e+03,  5.67120773e+03,  5.72120773e+03,
        5.77120773e+03,  5.82120773e+03,  5.87120773e+03,  5.92120773e+03,
        5.97120773e+03,  6.02120773e+03,  6.07120773e+03,  6.12120773e+03,
        6.17120773e+03,  6.22120773e+03,  6.27120773e+03,  6.32120773e+03,
        6.37120773e+03,  6.42120773e+03,  6.47120773e+03,  6.52120773e+03,
        6.57120773e+03,  6.62120773e+03,  6.67120773e+03,  6.72120773e+03,
        6.77120773e+03,  6.82120773e+03,  6.87120773e+03,  6.92120773e+03,
        6.97120773e+03,  7.02120773e+03,  7.07120773e+03,  7.12120773e+03,
        7.17120773e+03,  7.22120773e+03,  7.27120773e+03,  7.32120773e+03,
        7.37120773e+03,  7.42120773e+03,  7.47120773e+03,  7.52120773e+03,
        7.57120773e+03,  7.62120773e+03,  7.67120773e+03,  7.72120773e+03,
        7.77120773e+03,  7.82120773e+03,  7.87120773e+03,  7.92120773e+03,
        7.97120773e+03,  8.02120773e+03,  8.07120773e+03,  8.12120773e+03,
        8.17120773e+03,  8.22120773e+03,  8.27120773e+03,  8.32120773e+03,
        8.37120773e+03,  8.42120773e+03,  8.47120773e+03,  8.52120773e+03,
        8.57120773e+03,  8.62120773e+03,  8.67120773e+03,  8.72120773e+03,
        8.77120773e+03,  8.82120773e+03,  8.87120773e+03,  8.92120773e+03,
        8.97120773e+03,  9.02120773e+03,  9.07120773e+03,  9.12120773e+03,
        9.17120773e+03,  9.22120773e+03,  9.27120773e+03,  9.32120773e+03,
        9.37120773e+03,  9.42120773e+03,  9.47120773e+03,  9.52120773e+03,
        9.57120773e+03,  9.62120773e+03,  9.67120773e+03,  9.72120773e+03,
        9.77120773e+03,  9.82120773e+03,  9.87120773e+03,  9.92120773e+03,
        9.97120773e+03,  1.00212077e+04,  1.00712077e+04,  1.01212077e+04,
        1.01712077e+04,  1.02212077e+04,  1.02712077e+04,  1.03212077e+04,
        1.03712077e+04,  1.04212077e+04,  1.04712077e+04,  1.05212077e+04,
        1.05712077e+04,  1.06212077e+04,  1.06712077e+04,  1.07212077e+04,
        1.07712077e+04,  1.08212077e+04,  1.08712077e+04,  1.09212077e+04,
        1.09712077e+04,  1.10212077e+04,  1.10712077e+04,  1.11212077e+04,
        1.11712077e+04,  1.12212077e+04,  1.12712077e+04,  1.13212077e+04,
        1.13712077e+04,  1.14212077e+04,  1.14712077e+04,  1.15212077e+04,
        1.15712077e+04,  1.16212077e+04,  1.16712077e+04,  1.17212077e+04,
        1.17712077e+04,  1.18212077e+04,  1.18712077e+04,  1.19212077e+04,
        1.19712077e+04,  1.20212077e+04,  1.20712077e+04,  1.21212077e+04,
        1.21712077e+04,  1.22212077e+04,  1.22712077e+04,  1.23212077e+04,
        1.23712077e+04,  1.24212077e+04,  1.24712077e+04,  1.25212077e+04,
        1.25712077e+04,  1.26212077e+04,  1.26712077e+04,  1.27212077e+04,
        1.27712077e+04,  1.28212077e+04,  1.28712077e+04,  1.29212077e+04,
        1.29712077e+04,  1.30212077e+04,  1.30712077e+04,  1.31212077e+04,
        1.31712077e+04,  1.32212077e+04,  1.32712077e+04,  1.33212077e+04,
        1.33712077e+04,  1.34212077e+04,  1.34712077e+04,  1.35212077e+04,
        1.35712077e+04,  1.36212077e+04,  1.36712077e+04,  1.37212077e+04,
        1.37712077e+04,  1.38212077e+04,  1.38712077e+04,  1.39212077e+04,
        1.39712077e+04,  1.40212077e+04,  1.40712077e+04,  1.41212077e+04,
        1.41712077e+04,  1.42212077e+04,  1.42712077e+04,  1.43212077e+04,
        1.43712077e+04,  1.44212077e+04,  1.44712077e+04,  1.45212077e+04,
        1.45712077e+04,  1.46212077e+04,  1.46712077e+04,  1.47212077e+04,
        1.47712077e+04,  1.48212077e+04,  1.48712077e+04,  1.49212077e+04,
        1.49712077e+04,  1.50212077e+04,  1.50712077e+04,  1.51212077e+04,
        1.51712077e+04,  1.52212077e+04,  1.52712077e+04,  1.53212077e+04,
        1.53712077e+04,  1.54212077e+04,  1.54712077e+04,  1.55212077e+04,
        1.55712077e+04,  1.56212077e+04,  1.56712077e+04,  1.57212077e+04,
        1.57712077e+04,  1.58212077e+04,  1.58712077e+04,  1.59212077e+04,
        1.59712077e+04,  1.60212077e+04,  1.60712077e+04,  1.61212077e+04,
        1.61712077e+04,  1.62212077e+04,  1.62712077e+04,  1.63212077e+04,
        1.63712077e+04,  1.64212077e+04,  1.64712077e+04,  1.65212077e+04,
        1.65712077e+04,  1.66212077e+04,  1.66712077e+04,  1.67212077e+04,
        1.67712077e+04,  1.68212077e+04,  1.68712077e+04,  1.69212077e+04,
        1.69712077e+04,  1.70212077e+04,  1.70712077e+04,  1.71212077e+04,
        1.71712077e+04,  1.72212077e+04,  1.72712077e+04,  1.73212077e+04,
        1.73712077e+04,  1.74212077e+04,  1.74712077e+04,  1.75212077e+04,
        1.75712077e+04,  1.76212077e+04,  1.76712077e+04,  1.77212077e+04,
        1.77712077e+04,  1.78212077e+04,  1.78712077e+04,  1.79212077e+04,
        1.79712077e+04,  1.80212077e+04,  1.80712077e+04,  1.81212077e+04,
        1.81712077e+04,  1.82212077e+04,  1.82712077e+04,  1.83212077e+04,
        1.83712077e+04,  1.84212077e+04,  1.84712077e+04,  1.85212077e+04,
        1.85712077e+04,  1.86212077e+04,  1.86712077e+04,  1.87212077e+04,
        1.87712077e+04,  1.88212077e+04,  1.88712077e+04,  1.89212077e+04,
        1.89712077e+04,  1.90212077e+04,  1.90712077e+04,  1.91212077e+04,
        1.91712077e+04,  1.92212077e+04,  1.92712077e+04,  1.93212077e+04,
        1.93712077e+04,  1.94212077e+04,  1.94712077e+04,  1.95212077e+04,
        1.95712077e+04,  1.96212077e+04,  1.96712077e+04,  1.97212077e+04,
        1.97712077e+04,  1.98212077e+04,  1.98712077e+04,  1.99212077e+04,
        1.99712077e+04,  2.00212077e+04,  2.00712077e+04,  2.01212077e+04,
        2.01712077e+04,  2.02212077e+04,  2.02712077e+04,  2.03212077e+04,
        2.03712077e+04,  2.04212077e+04,  2.04712077e+04,  2.05212077e+04,
        2.05712077e+04,  2.06212077e+04,  2.06712077e+04,  2.07212077e+04,
        2.07712077e+04,  2.08212077e+04,  2.08712077e+04,  2.09212077e+04,
        2.09712077e+04,  2.10212077e+04,  2.10712077e+04,  2.11212077e+04,
        2.11712077e+04,  2.12212077e+04,  2.12712077e+04,  2.13212077e+04,
        2.13712077e+04,  2.14212077e+04,  2.14712077e+04,  2.15212077e+04,
        2.15712077e+04,  2.16212077e+04,  2.16712077e+04,  2.17212077e+04,
        2.17712077e+04,  2.18212077e+04,  2.18712077e+04,  2.19212077e+04,
        2.19712077e+04,  2.20212077e+04,  2.20712077e+04,  2.21212077e+04,
        2.21712077e+04,  2.22212077e+04,  2.22712077e+04,  2.23212077e+04,
        2.23712077e+04,  2.24212077e+04,  2.24712077e+04,  2.25212077e+04,
        2.25712077e+04,  2.26212077e+04,  2.26712077e+04,  2.27212077e+04,
        2.27712077e+04,  2.28212077e+04,  2.28712077e+04,  2.29212077e+04,
        2.29712077e+04,  2.30212077e+04,  2.30712077e+04,  2.31212077e+04,
        2.31712077e+04,  2.32212077e+04,  2.32712077e+04,  2.33212077e+04,
        2.33712077e+04,  2.34212077e+04,  2.34712077e+04,  2.35212077e+04,
        2.35712077e+04,  2.36212077e+04,  2.36712077e+04,  2.37212077e+04,
        2.37712077e+04,  2.38212077e+04,  2.38712077e+04,  2.39212077e+04,
        2.39712077e+04,  2.40212077e+04,  2.40712077e+04,  2.41212077e+04,
        2.41712077e+04,  2.42212077e+04,  2.42712077e+04,  2.43212077e+04,
        2.43712077e+04,  2.44212077e+04,  2.44712077e+04,  2.45212077e+04,
        2.45712077e+04,  2.46212077e+04,  2.46712077e+04,  2.47212077e+04,
        2.47712077e+04,  2.48212077e+04,  2.48712077e+04,  2.49212077e+04,
        2.49712077e+04,  2.50212077e+04,  2.50712077e+04,  2.51212077e+04,
        2.51712077e+04,  2.52212077e+04,  2.52712077e+04,  2.53212077e+04,
        2.53712077e+04,  2.54212077e+04,  2.54712077e+04,  2.55212077e+04,
        2.55712077e+04,  2.56212077e+04,  2.56712077e+04,  2.57212077e+04,
        2.57712077e+04,  2.58212077e+04,  2.58712077e+04,  2.59212077e+04,
        2.59712077e+04,  2.60212077e+04,  2.60712077e+04,  2.61212077e+04,
        2.61712077e+04,  2.62212077e+04,  2.62712077e+04,  2.63212077e+04,
        2.63712077e+04,  2.64212077e+04,  2.64712077e+04,  2.65212077e+04,
        2.65712077e+04,  2.66212077e+04,  2.66712077e+04,  2.67212077e+04,
        2.67712077e+04,  2.68212077e+04,  2.68712077e+04,  2.69212077e+04,
        2.69712077e+04,  2.70212077e+04,  2.70712077e+04,  2.71212077e+04,
        2.71712077e+04,  2.72212077e+04,  2.72712077e+04,  2.73212077e+04,
        2.73712077e+04,  2.74212077e+04,  2.74712077e+04,  2.75212077e+04,
        2.75712077e+04,  2.76212077e+04,  2.76712077e+04,  2.77212077e+04,
        2.77712077e+04,  2.78212077e+04,  2.78712077e+04,  2.79212077e+04,
        2.79712077e+04,  2.80212077e+04,  2.80712077e+04,  2.81212077e+04,
        2.81712077e+04,  2.82212077e+04,  2.82712077e+04,  2.83212077e+04,
        2.83712077e+04,  2.84212077e+04,  2.84712077e+04,  2.85212077e+04,
        2.85712077e+04,  2.86212077e+04,  2.86712077e+04,  2.87212077e+04,
        2.87712077e+04,  2.88212077e+04,  2.88712077e+04,  2.89212077e+04,
        2.89712077e+04,  2.90212077e+04,  2.90712077e+04,  2.91212077e+04,
        2.91712077e+04,  2.92212077e+04,  2.92712077e+04,  2.93212077e+04,
        2.93712077e+04,  2.94212077e+04,  2.94712077e+04,  2.95212077e+04,
        2.95712077e+04,  2.96212077e+04,  2.96712077e+04,  2.97212077e+04,
        2.97712077e+04,  2.98212077e+04,  2.98712077e+04,  2.99212077e+04,
        2.99712077e+04,  3.00212077e+04,  3.00712077e+04,  3.01212077e+04,
        3.01712077e+04,  3.02212077e+04,  3.02712077e+04,  3.03212077e+04,
        3.03712077e+04,  3.04212077e+04,  3.04712077e+04,  3.05212077e+04,
        3.05712077e+04,  3.06212077e+04,  3.06712077e+04,  3.07212077e+04,
        3.07712077e+04,  3.08212077e+04,  3.08712077e+04,  3.09212077e+04,
        3.09712077e+04,  3.10212077e+04,  3.10712077e+04,  3.11212077e+04,
        3.11712077e+04,  3.12212077e+04,  3.12712077e+04,  3.13212077e+04,
        3.13712077e+04,  3.14212077e+04,  3.14712077e+04,  3.15212077e+04,
        3.15712077e+04,  3.16212077e+04,  3.16712077e+04,  3.17212077e+04,
        3.17712077e+04,  3.18212077e+04,  3.18712077e+04,  3.19212077e+04,
        3.19712077e+04,  3.20212077e+04,  3.20712077e+04,  3.21212077e+04,
        3.21712077e+04,  3.22212077e+04,  3.22712077e+04,  3.23212077e+04,
        3.23712077e+04,  3.24212077e+04,  3.24712077e+04,  3.25212077e+04,
        3.25712077e+04,  3.26212077e+04,  3.26712077e+04,  3.27212077e+04,
        3.27712077e+04,  3.28212077e+04,  3.28712077e+04,  3.29212077e+04,
        3.29712077e+04,  3.30212077e+04,  3.30712077e+04,  3.31212077e+04,
        3.31712077e+04,  3.32212077e+04,  3.32712077e+04,  3.33212077e+04,
        3.33712077e+04,  3.34212077e+04,  3.34712077e+04,  3.35212077e+04,
        3.35712077e+04,  3.36212077e+04,  3.36712077e+04,  3.37212077e+04,
        3.37712077e+04,  3.38212077e+04,  3.38712077e+04,  3.39212077e+04,
        3.39712077e+04,  3.40212077e+04,  3.40712077e+04,  3.41212077e+04,
        3.41712077e+04,  3.42212077e+04,  3.42712077e+04,  3.43212077e+04,
        3.43712077e+04,  3.44212077e+04,  3.44712077e+04,  3.45212077e+04,
        3.45712077e+04,  3.46212077e+04,  3.46712077e+04,  3.47212077e+04,
        3.47712077e+04,  3.48212077e+04,  3.48712077e+04,  3.49212077e+04,
        3.49712077e+04,  3.50212077e+04,  3.50712077e+04,  3.51212077e+04,
        3.51712077e+04,  3.52212077e+04,  3.52712077e+04,  3.53212077e+04,
        3.53712077e+04,  3.54212077e+04,  3.54712077e+04,  3.55212077e+04,
        3.55712077e+04,  3.56212077e+04,  3.56712077e+04,  3.57212077e+04,
        3.57712077e+04,  3.58212077e+04,  3.58712077e+04,  3.59212077e+04,
        3.59712077e+04,  3.60212077e+04,  3.60712077e+04,  3.61212077e+04,
        3.61712077e+04,  3.62212077e+04,  3.62712077e+04,  3.63212077e+04,
        3.63712077e+04,  3.64212077e+04,  3.64712077e+04,  3.65212077e+04])

We can visualize the resulting rasterized image.

[8]:
#Plot unrasterized/rasterized images
fig,ax = plt.subplots(1,2)
ax[0].scatter(x,y,s=0.5,alpha=0.25)
ax[0].invert_yaxis()
ax[0].set_title('List of cells')
ax[0].set_aspect('equal')

W = W[0]
extent = (X_[0],X_[-1],Y_[0],Y_[-1])
ax[1].imshow(W,  origin='lower')
ax[1].invert_yaxis()
ax[1].set_title('Rasterized')

# save figure
#fig.canvas.draw()
#fig.savefig(outname[:-4]+'_image.png')
[8]:
Text(0.5, 1.0, 'Rasterized')
../_images/notebooks_starmap-allen3Datlas-alignment_15_1.png

Now we need to find an approximate slice number in the Allen Atlas to initialize the alignment. Evaluate whether the value of slice is similar to the target image by viewing a side by side comparison of the ABA slice and the target image. If not, change the value of slice. In this example, slice = 0 is anterior and slice = 264 is posterior.

[9]:
#find slice
#peruse through images in atlas
# Loading the atlas
slice = 140

vol,hdr = nrrd.read(imagefile)
A = vol
vol,hdr = nrrd.read(labelfile)
L = vol

dxA = np.diag(hdr['space directions'])
nxA = A.shape
xA = [np.arange(n)*d - (n-1)*d/2.0 for n,d in zip(nxA,dxA)]
XA = np.meshgrid(*xA,indexing='ij')

fig,ax = plt.subplots(1,2)
extentA = STalign.extent_from_x(xA[1:])
ax[0].imshow(A[slice],extent=extentA)
ax[0].set_title('Atlas Slice')

ax[1].imshow(W,extent=extentA)
ax[1].set_title('Target Image')
fig.canvas.draw()

../_images/notebooks_starmap-allen3Datlas-alignment_17_0.png
[10]:
len(xA[2])
[10]:
228

Next, we need to find an approximate rotation angle of the Allen Atlas to initialize the alignment. Evaluate whether the rotation of the atlas is similar to the target image by viewing a side by side comparison of the ABA slice and the target image. If not, change the value of theta_deg. Note: the rotation here is defined in degrees.

[11]:
from scipy.ndimage import rotate

theta_deg = 90

fig,ax = plt.subplots(1,2)
extentA = STalign.extent_from_x(xA[1:])
ax[0].imshow(rotate(A[slice], angle=theta_deg),extent=extentA)
ax[0].set_title('Atlas Slice')

ax[1].imshow(W,extent=extentA)
ax[1].set_title('Target Image')
fig.canvas.draw()

../_images/notebooks_starmap-allen3Datlas-alignment_20_0.png

Next, specify if there are any points on the image above that can be approximately matched with eachother and add them in the following format. This helps speed up alignment. (OPTIONAL)

[12]:
points_atlas = np.array([[0,0]]) #(-y,-x)
points_target = np.array([[-3700,0]]) # (-y,-x)
Li,Ti = STalign.L_T_from_points(points_atlas,points_target)

We can define atlas and target points, xI and xJ, as well as atlas and target images, I and J.

[13]:
xJ = [Y_,X_]
J = W[None]/np.mean(np.abs(W))
xI = xA
I = A[None] / np.mean(np.abs(A),keepdims=True)
I = np.concatenate((I,(I-np.mean(I))**2))
Inorm = STalign.normalize(I, t_min=0, t_max=1)
Jnorm = STalign.normalize(J, t_min=0, t_max=1)

Now that we can chosen the slice number and rotation angle, we are ready to initialize parameters related to our alignment.

[14]:
sigmaA = 0.1 #standard deviation of artifact intensities
sigmaB = 0.1 #standard deviation of background intensities
sigmaM = 0.1 #standard deviation of matching tissue intenities
muA = torch.tensor([0.7],device='cpu') #average of artifact intensities (one value per channel of J)
muB = torch.tensor([0.0],device='cpu') #average of background intensities (one value per channel of J)

We can change the parameters above by looking at the intensity histogram of our target image (below). We need to consider intensities of artifacts (tissue that is present in the target image and absent in the atlas), which is usually in the upper range of intensity values. We also need to find the intensity of the background values that does not correspond to any tissue, usually around 0, and standard deviations for these values. The matching tissue intensities are regions that should have tissue that can be aligned in both the atlas and the target image.

[15]:
fig,ax = plt.subplots()
ax.hist(Jnorm.ravel())
plt.xlabel('Intensity')
plt.ylabel('Number of Pixels')
plt.title('Intensity Histogram of Target Image')
[15]:
Text(0.5, 1.0, 'Intensity Histogram of Target Image')
../_images/notebooks_starmap-allen3Datlas-alignment_28_1.png

The following parameters vary depending on your target image and the duration & accuracy of the alignment. The scale parameters refer to a scaling of the atlas in (x, y, z) to match the size of the target image. The nt parameter ensures smoothness and invertibility of the image transformation. The niter refers to the number of iteration steps in gradient descent to achieve minimum error between the altas and the target image.

[16]:
# initialize variables
scale_x = 4 #default = 0.9
scale_y = 4 #default = 0.9
scale_z = 0.9 #default = 0.9
theta0 = (np.pi/180)*theta_deg

# get an initial guess
# the atlas z of the inspected slice, xI[0][slice], maps to target z = 0
if 'Ti' in locals():
    T = np.array([-scale_z*xI[0][slice],np.mean(xJ[0])-(Ti[0]*scale_y),np.mean(xJ[1])-(Ti[1]*scale_x)])
else:
    T = np.array([-scale_z*xI[0][slice],np.mean(xJ[0]),np.mean(xJ[1])])
#T = np.array([-scale_z*xI[0][slice],0,0])


scale_atlas = np.array([[scale_z,0,0],
                        [0,scale_y,0],   # rows (y)
                        [0,0,scale_x]])  # columns (x)
L = np.array([[1.0,0.0,0.0],
             [0.0,np.cos(theta0),-np.sin(theta0)],
              [0.0,np.sin(theta0),np.cos(theta0)]])
L = np.matmul(L,scale_atlas)#np.identity(3)

Now, we can perform alignment of the atlas to our target slice.

[17]:
%%time
#returns mat = affine transform, v = velocity, xv = pixel locations of velocity points
transform = STalign.LDDMM_3D_to_slice(
    xI,Inorm,xJ,Jnorm,
    T=T,L=L,
    nt=4,niter=800,
    a=250,
    device='cpu',
    sigmaA = sigmaA, #standard deviation of artifact intensities
    sigmaB = sigmaB, #standard deviation of background intensities
    sigmaM = sigmaM, #standard deviation of matching tissue intenities
    muA = muA, #average of artifact intensities
    muB = muB #average of background intensities
)

CPU times: user 6min 36s, sys: 7.26 s, total: 6min 43s
Wall time: 29.7 s
../_images/notebooks_starmap-allen3Datlas-alignment_32_1.png
../_images/notebooks_starmap-allen3Datlas-alignment_32_2.png
../_images/notebooks_starmap-allen3Datlas-alignment_32_3.png
[18]:
A = transform['A']
v = transform['v']
xv = transform['xv']
Xs = transform['Xs']
[19]:
print(A)
tensor([[ 8.9086e-01,  1.0892e-01,  5.8417e-02, -4.3068e+02],
        [ 2.6707e-01,  6.8566e-02, -5.0799e+00,  2.6065e+04],
        [-5.5221e-01,  4.7034e+00, -1.2547e-01,  1.8870e+04],
        [ 0.0000e+00,  0.0000e+00,  0.0000e+00,  1.0000e+00]],
       dtype=torch.float64)

Once we have aligned the atlas to our target image, we can project the brain regions defined in the atlas to our target image and export these annotations, along with information about the positions of the atlas that align with the slice.

[20]:
df = STalign.analyze3Dalign(labelfile,  xv,v,A, xJ, dx, scale_x=scale_x, scale_y=scale_y,x=x,y=y, X_=X_, Y_=Y_, namesdict=namesdict,device='cpu')
[21]:
df
[21]:
coord0 coord1 coord2 x y struct_id acronym
0 365.834215 -1490.828274 4767.707715 10834.272727 1488.454545 0 bg
1 359.239693 -1231.470456 4868.662553 12139.406780 864.788136 527 AUDd1
2 360.277175 -1288.299728 4804.451198 11848.132075 1225.679245 527 AUDd1
3 363.061917 -1438.882031 4792.399274 11090.980392 1342.539216 527 AUDd1
4 361.356520 -1353.258453 4784.952035 11517.905660 1351.735849 527 AUDd1
... ... ... ... ... ... ... ...
43336 31.034556 3402.225383 128.143466 34741.963636 25621.704545 0 bg
43337 53.669809 3261.895261 361.125714 34380.794118 24686.573529 223 ARH
43338 59.235433 3209.381251 284.542091 34106.068182 25049.780303 223 ARH
43339 47.036578 3317.748867 398.877626 34648.200000 24484.694118 0 bg
43340 32.887034 3396.605124 159.689550 34753.990385 25492.134615 0 bg

43341 rows × 7 columns

Now, we can explore our alignment and brain region annotations!

We can visualize the MERFISH slice overlayed with the matched section in the Allen Brain Atlas.

[22]:
It = torch.tensor(I,device='cpu',dtype=torch.float64)
AI = STalign.interp3D(xI,It,Xs.permute(3,0,1,2),padding_mode="border")
Ishow_source = ((AI-torch.amin(AI,(1,2,3))[...,None,None])/(torch.amax(AI,(1,2,3))-torch.amin(AI,(1,2,3)))[...,None,None,None]).permute(1,2,3,0).clone().detach().cpu()
Jt = torch.tensor(J,device='cpu',dtype=torch.float64)
Ishow_target = Jt.permute(1,2,0).cpu()/torch.max(Jt).item()

import matplotlib as mpl
fig,ax = plt.subplots(1,3, figsize=(15,5))
ax0 = ax[0].imshow(Ishow_target, cmap = mpl.cm.Blues,alpha=0.9)
ax[0].set_title('STARmap Slice')
ax1 = ax[1].imshow(Ishow_source[0,:,:,0], cmap = mpl.cm.Reds,alpha=0.2)
ax[1].set_title('z=0 slice of Aligned 3D Allen Brain Atlas')
ax2 = ax[2].imshow(Ishow_target, cmap = mpl.cm.Blues,alpha=0.9)
ax2 = ax[2].imshow(Ishow_source[0,:,:,0], cmap = mpl.cm.Reds,alpha=0.3)
ax[2].set_title('Overlayed')

plt.show()
../_images/notebooks_starmap-allen3Datlas-alignment_40_0.png
[23]:
from mpl_toolkits import mplot3d

x=df['coord0']
y=-df['coord1']
z=df['coord2']

fig = plt.figure()
ax = plt.axes(projection='3d')

ax.scatter3D(x,y,z,s=0.05)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
[23]:
Text(0.5, 0, 'z')
../_images/notebooks_starmap-allen3Datlas-alignment_41_1.png

We can also plot all of the brain regions that are captured in the slice, as defined by our alignment.

[24]:
STalign.plot_brain_regions(df)
[24]:
(<Figure size 640x480 with 1 Axes>, <Axes: >)
../_images/notebooks_starmap-allen3Datlas-alignment_43_1.png

If we also interested in only a few regions, in this example let’s take VISp4 and VISp5, we can plot those regions using the following function.

[25]:
brain_regions = ['CA1']
STalign.plot_subset_brain_regions(df, brain_regions)
[25]:
(<Figure size 640x480 with 1 Axes>, <Axes: >)
../_images/notebooks_starmap-allen3Datlas-alignment_45_1.png
[ ]: