如何在stomics平台使用spateo圈细胞
时空云平台(STOmics Cloud)是以时空为特色的多组学数据分析平台,可以管理和分析多组学数据。 STOmics Cloud以项目为核心,用户可快速将数据和工具整合到项目,实现分析过程可追溯,结果可复现,知识可分享,项目可协作,形成项目分析体系。并通过一个用户友好的门户,提供灵活易于使用的无代码标准和高级分析,高分辨率可视化分析,以及个性化的分析服务,任何注册登录的用户可以轻松在平台上访问,分析,使用和共享数据和工具。
总体来说,STOmics 平台是一个很出色的多组学的数据分析平台,但是仍然有一些不足,STOmics 在做数据分析的时候无法连接外部网络,如果说我们需要用到一些外部的模型或是其他资源的时候,则是会遇到十分大的阻碍,尤其是当我们调用 keras 的某些模型的时候,是需要进行联网下载的,那我们就需要对源码进行一些修改。
Spateo 利用 Stereo-seq 的超高空间分辨率、大视野和高 RNA 捕获灵敏度,通过核染色和基于 RNA 信号的细胞分割实现单细胞分辨率空间转录组学。Spateo 还提供了空间约束聚类的新方法,以识别连续的组织域,空间感知差异分析以揭示空间基因表达热点和模块,以及复杂的配体-受体相互作用。
首先我们需要在 STOmics
上构建镜像,通过测试,以下镜像构建代码是有较为不错的效果,基础镜像选择为Python 3 and R image
,也可以采用已经构建好的
spateo_zt
镜像。镜像使用需要在自己的工作目录创建/data/work/.keras/models
和/data/work/.cellpose/models
文件夹。
stardist需要下载 python_2D_versatile_fluo.zip
并且改名为 2D_versatile_fluo.zip
,放置于
/data/work/.keras/models/StarDist2D/2D_versatile_fluo/2D_versatile_fluo.zip
。cellpose需要下载
nucleitorch_0
和 size_nucleitorch_0.npy
放置于 /data/work/.cellpose/models/nucleitorch_0
和/data/work/.cellpose/models/size_nucleitorch_0.npy
。deepcell需要下载
NuclearSegmentation-75.tar.gz
并且改名为 NuclearSegmentation.tgz
,放置于
/data/work/.keras/models/NuclearSegmentation.tgz
之后便可进行正常的圈细胞。
/opt/software/python/bin/python3.8 -m pip install --upgrade pip
pip install scanpy
pip install spateo-release
pip install tensorflow==2.12.0
pip install stardist
pip install cellpose
pip install DeepCell
sed -i '214a \ \ \ \ cache_dir="/data/work/.keras"' /opt/software/python/lib/python3.8/site-packages/keras/utils/data_utils.py
sed -i '221a \ \ \ \ datadir_base="/data/work/.keras"' /opt/software/python/lib/python3.8/site-packages/keras/utils/data_utils.py
sed -i '17a MODEL_DIR = pathlib.Path("/data/work/.cellpose/models")' /opt/software/python/lib/python3.8/site-packages/cellpose/models.py
构建镜像完成之后便是可以使用空间组芯片数据gem和空间组拍照数据tif进行圈细胞。我写的代码如下所示
def cellbin_spateo(gem_path, ssDNA_path, save_path):
adata = st.io.read_bgi_agg(
gem_path, ssDNA_path,
)
name = gem_path.split('/')[-1].split('.')[0]
## stain mask
st.cs.mask_nuclei_from_stain(adata)
st.pl.imshow(adata, 'stain_mask', save_show_or_return = 'save', save_kwargs={'path':save_path + '01.stain_mask_' + name})
## watershed_labels
st.cs.find_peaks_from_mask(adata, 'stain', 7)
st.cs.watershed(adata, 'stain', 5, out_layer='watershed_labels')
fig, ax = st.pl.imshow(adata, 'stain', save_show_or_return='return')
st.pl.imshow(adata, 'watershed_labels', labels=True, alpha=0.5, ax=ax, save_show_or_return='save', save_kwargs={'path':save_path + '02.watershed_labels_' + name})
## stardist_labels
st.cs.stardist(adata, tilesize=-1, equalize=2.0, out_layer='stardist_labels')
fig, ax = st.pl.imshow(adata, 'stain', save_show_or_return='return')
st.pl.imshow(adata, 'stardist_labels', labels=True, alpha=0.5, ax=ax, save_show_or_return='save', save_kwargs={'path':save_path + '03.stardist_labels_' + name})
## augmented_labels
st.cs.augment_labels(adata, 'watershed_labels', 'stardist_labels', out_layer='augmented_labels')
fig, ax = st.pl.imshow(adata, 'stain', save_show_or_return='return')
st.pl.imshow(adata, 'augmented_labels', labels=True, alpha=0.5, ax=ax, save_show_or_return='save', save_kwargs={'path':save_path + '04.augmented_labels_' + name})
##
st.cs.mask_cells_from_stain(adata, out_layer='stain_cell_mask')
st.cs.watershed(
adata, 'stain',
mask_layer='stain_cell_mask',
markers_layer='augmented_labels',
out_layer='cell_labels',
)
##
fig, ax = st.pl.imshow(adata, 'stain', save_show_or_return='return')
st.pl.imshow(adata, 'cell_labels', labels=True, alpha=0.5, ax=ax, save_show_or_return='save', save_kwargs={'path':save_path + '05.cell_labels_' + name})
## expand_labels
st.cs.expand_labels(adata, 'augmented_labels', distance=20, max_area=1600)
fig, ax = st.pl.imshow(adata, 'stain', save_show_or_return='return')
st.pl.imshow(adata, 'augmented_labels_expanded', labels=True, alpha=0.5, ax=ax, save_show_or_return='save', save_kwargs={'path':save_path + '06.augmented_labels_expanded_' + name})
## label adata
adata.write(save_path + '07.labeled_adata_' + name + '.h5ad')
## final adata
cell_adata = st.io.read_bgi(
gem_path,
segmentation_adata=adata,
labels_layer='augmented_labels_expanded',
)
cell_adata.write(save_path + '08.final_adata_' + name + '.h5ad')
return 0
使用上述代码则可以正常在 STOmics 平台上进行圈细胞。获得单细胞分辨率的空间组的数据。需要注意的是我们的拍照的 tif 数据是需要和 gem 数据的空间位置对应上的。那么应该如何对应呢?这里使用师兄 liaokuo 的代码,生成由 gem 文件生成的灰度图,将灰度图放置于 PhotoShop 中作为底图,然后将 tif 图与灰度图手动配准(因为自动配准效果不好),导出以 灰度图大小画布为底的、调整过的 tif 图片,然后将此图片拿去与gem文件做圈细胞。
# author: liaokuo
# time: 2022/4/1
# this is to generate grey graphic from spatial RNA.
# create_greyplot.py input_file_path out_put_directory
import sys
import os
inpath=sys.argv[1]
outpath=sys.argv[2]
os.chdir(outpath) # change the working directory
file=inpath.rsplit("/",1)[1]
name=file.split(".")[0]
import pandas as pd
import numpy as np
def mRNA_image_load(path, gray_factor=25):
cbs = pd.read_csv(path, sep='\t',comment='#') # therefore, the input file must be a clear txt or csv file.
cbs['coor'] = cbs['x'].astype(str) + '_' + cbs['y'].astype(str)
cbs2 = cbs[['coor', 'UMICount']] if 'UMICount' in cbs.columns else cbs[['coor', 'MIDCount']] # there must be careful.
cbs2 = cbs2['coor'].value_counts().reset_index()
cbs2['x'] = cbs2['index'].str.split('_', expand=True)[0].astype(int)
cbs2['y'] = cbs2['index'].str.split('_', expand=True)[1].astype(int)
#cbs2['x'] -= cbs2['x'].min()
#cbs2['y'] -= cbs2['y'].min()
h = cbs2['x'].max()
w = cbs2['y'].max()
mtx = cbs2.pivot_table(values='coor', index='x', columns='y', aggfunc='sum')
for i in range(h):
if i not in mtx.index:
mtx.loc[i] = 0
for j in range(w):
if j not in mtx.columns:
mtx.loc[:, j] = 0
mtx = mtx.fillna(0).sort_index().sort_index(axis=1)
mtx = mtx * gray_factor
mtx[mtx>255] = 255
mtx = mtx.astype(np.uint8).values
return mtx
# get the grey scale matrix
mtx=mRNA_image_load(path=inpath)
data=pd.DataFrame(mtx)
data.to_csv(name+"_grey.csv")
# draw grep scale plot in format of png
from PIL import Image
im = Image.fromarray(np.uint8(data))# image object should be an array in 0-255
im = im.convert('L')# L means grey scale, while RGB means color scale
im.save(name+"_grey.png")