在做空间转录组分析的时候,我们大多数会使用两种类型的数据,一种是bin100,bin50此类的数据,还有一种则是cellbin的数据,通常我们会使用 bin100/bin50 这样子的数据去做区域的注释,而 cellbin 的数据则是通过单细胞映射空间组,得到细胞类型的数据。但是这两种数据之间的迁移注释是一个问题,因为他们的分辨率不一样,所以我们需要将他们进行迁移注释,让 cellbin 的数据注释上脑区的信息。

首先要明确的是,我们的 bin100/bin50 的数据都是由同一个空间组的 gem 之类的文件生成的,要保证其基准坐标保持不变,这样子才能进行迁移注释。

但是基准不变的话,其实从 bin100 映射到 bin50 与 bin100 映射到 cellbin 其实原理是一样的,都是将 bin100 的数据映射到 bin50 或者 cellbin 的数据上,所以我们可以直接使用 bin100 的数据去做迁移注释。

首先,bin100 的每个 spots 都有一个坐标,但是实际上 bin100 应该是要有 100100 个坐标的,所以我们就需要将其还原回到 100100 的坐标上,这样子才能进行迁移注释,就像图片一样填满了整个背景板,那么这个时候,我们再拿出 bin50 或者 cellbin 的坐标数据,就可以将 bin100 的数据映射到 bin50 或者 cellbin 的数据上,这样子就完成了迁移注释。

但实际上这样子还是会有一些问题,比如某些细胞在两个bin100的正中间,或是其他的一些边界问题,还有很多的其他情况,这些我也没有考虑,笔者总体上觉得大多数的细胞映射还是没有太大问题的。代码如下所示:

def bin100_2_bin50(bin50_file_path, bin100_file_path, bin100_anno, bin50_anno, bin50_save_path):
    # 没有脑区注释
    adata_bin50 = sc.read(bin50_file_path)
    adata_bin50.obs['x'] = adata_bin50.obsm['spatial'][:,0]
    adata_bin50.obs['y'] = adata_bin50.obsm['spatial'][:,1]
    adata_bin50.write(bin50_file_path)
    
    # 有脑区注释的数据
    adata_bin100 = sc.read(bin100_file_path)
    
    # 构建映射字典 region_1 = 1
    dic = {}
    for i in range(len(set(adata_bin100.obs[bin100_anno]))):
        dic[list(set(adata_bin100.obs[bin100_anno]))[i]] = i+1

    # 将每个脑区变换成为 数字 id
    celltype = []
    refined = adata_bin100.obs[bin100_anno].tolist()
    celltype = [dic[i] for i in refined]
    
    # 构建大图,并且填写上 id,指脑区信息
    x, y = adata_bin100.obs['x'], adata_bin100.obs['y']
    shape = (x.max() + 100,y.max() + 100)
    X = csr_matrix((celltype, (x, y)), shape=shape)
    X = X.toarray()
    
    obs = adata_bin100.obs

    # 求出 长度
    bin100_spot_len = len(adata_bin100)
    
    # 转为 bin1 形式,将脑区信息补全
    for i in range(bin100_spot_len):
        X[obs['x'][i]-50:obs['x'][i]+50, obs['y'][i]-50:obs['y'][i]+50] = X[obs['x'][i],obs['y'][i]]
    
    # 脑区映射信息
    dic_reverse = {}
    for index,val in enumerate(dic):
        dic_reverse[index+1] = val
    dic_reverse[0] = 'others'
    
    bin50_spot_len = len(adata_bin50)
    
    t = []
    
    for i in range(bin50_spot_len):
        t.append(X[int(adata_bin50.obs['x'][i]), int(adata_bin50.obs['y'][i])])
    
    adata_bin50_region_type = [dic_reverse[i] for i in t]
    
    adata_bin50.obs[bin50_anno] = adata_bin50_region_type
    adata_bin50.obs[bin50_anno] = adata_bin50.obs[bin50_anno].astype('category')
    
    adata_bin50.write(bin50_save_path)

欢迎各位评论留言