Decomposition Analysis

Environment Setup: Package Loading

[ ]:
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import scanpy as sc
import cv2
from tqdm import tqdm

results_folder = 'Spotiphy_Result/'
if not os.path.exists(results_folder):
    # Create result folder if it does not exist
    os.makedirs(results_folder)

Data Loading

[ ]:
# Load the Visium data
adata_st = sc.read_h5ad("data/ST_mouse_brain.h5ad")
adata_st.var_names_make_unique()
# Load the cluster information
meta = pd.read_excel("ST_decomposition.seurat_meta.xlsx", header=0)
meta['seurat_clusters'].value_counts()

Map Cells from iscRNA Data to Corresponding Spots. Spots with no cells will be labels as -1.

[ ]:
cell_location = meta[['location_x', 'location_y']].values
spot_location = adata_st.obsm['spatial']
d = np.sum(np.abs(spot_location[:, :, np.newaxis] - cell_location.T), axis=1)
adata_st.obs['cluster'] = '-1'
adata_st.obs[['x', 'y']] = spot_location
cluster_column = 'seurat_clusters'
for i in range(len(adata_st)):
    if min(d[i]) < 1:
        idx = np.where(d[i]==0)[0][0]
        adata_st.obs.iloc[i, -3] = str(meta.iloc[idx][cluster_column])
[ ]:
img = adata_st.uns['spatial']['sampleID']['images']['hires'].copy() #sampleID varies depends on Input.
if img.shape[2] == 3:
    # Add an alpha channel if it doesn't exist
    alpha_channel = np.ones((*img.shape[:2], 1))
    img = np.concatenate([img, alpha_channel], axis=2)

img[np.max(img[:, :, :3], axis=2)-np.min(img[:, :, :3], axis=2)<30/255] = [1., 1., 1. ,1.]
adata_st.uns['spatial']['sampleID']['images']['hires'] = img.copy()
[ ]:
adata_st.obs['cluster'].value_counts()
[ ]:
# Remove spots with no cells for clear visualization
adata_st_temp = adata_st[adata_st.obs['cluster']!= '-1' ]

with mpl.rc_context({'figure.figsize': [4, 4.5], 'figure.dpi': 400}):
    ax = sc.pl.spatial(adata_st_temp, color=['cluster'], img_key='hires', size=1.3, show=False)
    ax[0].get_figure().savefig(results_folder+'Tumor_cluster_RL_cycling.jpg', bbox_inches='tight')
    mpl.pyplot.show()
[ ]:
with open(results_folder+"type_list.txt", "r") as file:
    type_list = [line.strip() for line in file.readlines()]
print(type_list)
[ ]:
cell_proportion = np.load(results_folder+'proportion.npy')
adata_st.obs['proportion'] = cell_proportion
adata_st.obs.groupby('cluster')['proportion'].quantile(0.9)
[ ]:
img = cv2.imread("data/img_mouse_brain.png")[:, :, [2, 1, 0]]
img[np.max(img, axis=2)-np.min(img, axis=2)<30] = [255, 255, 255]
alpha = 0.4
img = img * alpha + np.ones(img.shape) * 255 * (1 - alpha)
img = img.astype(np.int32)

colors = {'1': [180, 119, 31], '2': [14, 127, 255], '3': [44, 160, 44], '4': [40, 39, 214]}
adata_st_temp = adata_st[adata_st.obs['cluster']!='-1']
img1 = img.copy()
img2 = np.ones(img.shape)

quantile = adata_st.obs.groupby('cluster')['proportion'].quantile(0.9)
for i in tqdm(range(len(adata_st_temp))):
    cluster = adata_st_temp.obs.iloc[i, -4]
    location = adata_st_temp.obs.iloc[i, -3:-1]
    alpha = adata_st_temp.obs.iloc[i, -1] * (1/quantile.loc[cluster])
    if alpha > 1:
        alpha = 1.
    cv2.circle(img1, location, int(73*1.3/2), colors[cluster], -1)
    cv2.circle(img2, location, int(73*1.3/2), (alpha, alpha, alpha), -1)
[ ]:
img = img1 * img2 + img * (1-img2)
img = img.astype(np.int32)
cv2.imwrite(f'{results_folder}Seurat_cluster.jpg', img[:, :, [2, 1, 0]])
[ ]:
mpl.pyplot.imshow(img)