Run SMA data with SCrOFit

This notebook demosntrate how to use SCrOFit to run SMA data.

%autoreload

import anndata as ad
import os
import pandas as pd

import sys
sys.path.append('../../')

from scrofit.scrofit import SCrOFit

df = pd.read_csv('../../../data/MSA_data/corHstr_onlyCdSpots.csv', index_col=0)
SMA_cor_df = df[(df['FDR'] < 0.05) & (df['rho'].abs() > 0.2)]


def run_align(in_dir, sample):

    st_adata = ad.read_h5ad(f'{in_dir}/{sample}_st_raw.adata')
    sm_adata = ad.read_h5ad(f'{in_dir}/{sample}_sm_raw.adata')
    adata_dict = {'ST': st_adata, 'SM': sm_adata}

    out_dir = os.path.join(in_dir, 'scrofit_out')

    obj = SCrOFit(adata_dict=adata_dict, out_dir=out_dir, sample=sample)

    obj.align_slides()

    print('---start mapping---')
    obj.mapping(mapping_method='MCMF', ccs_type='spatial_rir',
                alpha=1, beta=1, n_neighbors=3,
                n_thread=6, n_batch=250,
                verbose=False)  

    obj.check_slides()

    headers = ['RegionLoupe', 'MSN.D2.PenkPos_2', 'MSN.D1.TacNeg_3', 'MSN.D2.PenkNeg_5',
               'MSN.D1.TacPosB_6', 'MSN.D1.TacPosA_9', 'MSN.D2_C_18'] + SMA_cor_df['gene'].tolist()
    obj.transfer_anno(headers)

    for key, adata in adata_dict.items():
        fn = '{}/{}_{}_pp.adata'.format(in_dir, sample, key.lower())
        adata.write_h5ad(fn)

    return obj, adata_dict

obj_dict = {}
for sample in ['V11T17-102']:
    for block in ['A1', 'B1', 'C1', 'D1']:
        print(block)
        in_dir = f'../../../data/MSA_data/{sample}'
        obj, adata_dict = run_align(in_dir, sample + '_' + block)
        obj_dict[block] = obj
%autoreload

import anndata as ad
import os
import numpy as np
from scrofit.mapping import init_mdata

def merge_celltype(st_adata):
    cell_types = ["Astro_0","Oligo_1","MSN.D2.PenkPos_2","MSN.D1.TacNeg_3","Oligo_4","MSN.D2.PenkNeg_5",
    "MSN.D1.TacPosB_6","OPC_7","Mi.MiR.Ma_8","MSN.D1.TacPosA_9","Astro_10","Astro_11","Inhib_MSN_12",
    "Inhib_13","unk_14","unk_15","unk_16","Astro_17","MSN.D2_C_18","unk_19","OPC_20","Oligo_21","unk_22"]
    X = st_adata.obs[cell_types].to_numpy()
    st_adata.obs['Cell Type'] = np.array(cell_types)[X.argmax(axis=1)]
    st_adata.obs['Cell Type'] = st_adata.obs['Cell Type'].apply(lambda x: '_'.join(x.split('_')[:-1]))
    st_adata.obs['Cell Type'] = st_adata.obs['Cell Type'].apply(lambda x: np.nan if x == 'unk' else x)
    mymap = {
        'MSN.D2.PenkNeg': 'MSN',
        'MSN.D1.TacPosB': 'MSN', 
        'MSN.D1.TacPosA': 'MSN', 
        'MSN.D2.PenkPos': 'MSN', 
        'MSN.D1.TacNeg': 'MSN',  
        'MSN.D2_C': 'MSN', 
    }
    st_adata.obs['Cell_Type']  =st_adata.obs['Cell Type'].apply(lambda x: mymap.get(x, x))


def replace_y_coord(in_dir, sample, block, i):
    st_adata = ad.read_h5ad(f'{in_dir}/{sample}_{block}_st_pp.adata')
    sm_adata = ad.read_h5ad(f'{in_dir}/{sample}_{block}_sm_pp.adata')

    for key in  ['spatial_rir', 'spatial_rir_filtered', 'spatial_MCMF_map', 'spatial']:
        if key in st_adata.obsm:
            st_adata.obsm[key][:, 1] += 45000*i
            print(sample, key, 'ST', st_adata.obsm[key][:, 1].min(), st_adata.obsm[key][:, 1].max())
        if key in sm_adata.obsm:
            if key == 'spatial':
                sm_adata.obsm[key][:, 1] += 70*i
            else:
                sm_adata.obsm[key][:, 1] += 45000*i
            print(sample, key, 'ST', sm_adata.obsm[key][:, 1].min(), sm_adata.obsm[key][:, 1].max())

    return st_adata, sm_adata

st_adata_list, sm_adata_list = [], []
mdata_list = []
for sample in ['V11T17-102']:
    image_list = []
    for i, block in enumerate(['A1', 'B1', 'C1', 'D1']):
        in_dir = f'../../../data/MSA_data/{sample}'
        st_adata, sm_adata = replace_y_coord(in_dir, sample, block, i)
        merge_celltype(st_adata)

        st_adata_list.append(st_adata)
        sm_adata_list.append(sm_adata)

        image = st_adata.uns['spatial'][f'{sample}_{block}']['images']['hires']
        scalefactors = st_adata.uns['spatial'][f'{sample}_{block}']['scalefactors']

        image_list.append(image)

        #for col in sm_adata.obs.columns:
        #    if col.startswith('ST'):
        #        del sm_adata.obs[col]
        mdata = init_mdata(sm_adata, st_adata)  
        mdata_list.append(mdata)


    st_adata = ad.concat(st_adata_list)
    print(st_adata_list[0].uns['spatial'][f'{sample}_A1']['scalefactors'])
    print(st_adata_list[1].uns['spatial'][f'{sample}_B1']['scalefactors'])
    print(st_adata_list[2].uns['spatial'][f'{sample}_C1']['scalefactors'])
    print(st_adata_list[3].uns['spatial'][f'{sample}_D1']['scalefactors'])    
    st_adata.uns['spatial'] = {sample:{
        'images': {'hires': np.concatenate(image_list)},
        'scalefactors': scalefactors
        }}

    sm_adata = ad.concat(sm_adata_list)
    sm_adata.uns['spatial'] = {sample:{'images': {'hires': np.concatenate(image_list)}}}

    mdata = ad.concat(mdata_list)


    st_adata.write_h5ad(f'{in_dir}/{sample}_st_pp.adata')
    sm_adata.write_h5ad(f'{in_dir}/{sample}_sm_pp.adata')
V11T17-102 spatial_rir ST 3267 41826
V11T17-102 spatial_rir ST 3559.905021567236 40827.900430471855
V11T17-102 spatial_rir_filtered ST 3267 41826
V11T17-102 spatial_rir_filtered ST nan nan
V11T17-102 spatial_MCMF_map ST nan nan
V11T17-102 spatial ST 3267 41826
V11T17-102 spatial ST 0 64
V11T17-102 spatial_rir ST 47834 86785
V11T17-102 spatial_rir ST 48144.84619771383 85815.9645796817
V11T17-102 spatial_rir_filtered ST 47834 86785
V11T17-102 spatial_rir_filtered ST nan nan
V11T17-102 spatial_MCMF_map ST nan nan
V11T17-102 spatial ST 47834 86785
V11T17-102 spatial ST 70 134
V11T17-102 spatial_rir ST 92762 131250
V11T17-102 spatial_rir ST 92999.24074128651 130552.32918017515
V11T17-102 spatial_rir_filtered ST 92762 131250
V11T17-102 spatial_rir_filtered ST nan nan
V11T17-102 spatial_MCMF_map ST nan nan
V11T17-102 spatial ST 92762 131250
V11T17-102 spatial ST 140 204
V11T17-102 spatial_rir ST 137673 176669
V11T17-102 spatial_rir ST 137570.2394988102 177668.60153934648
V11T17-102 spatial_rir_filtered ST 137673 176669
V11T17-102 spatial_rir_filtered ST nan nan
V11T17-102 spatial_MCMF_map ST nan nan
V11T17-102 spatial ST 137673 176669
V11T17-102 spatial ST 210 275
{'fiducial_diameter_fullres': np.float64(610.9539999999998), 'spot_diameter_fullres': np.float64(378.20962999999995), 'tissue_hires_scalef': np.float64(0.04111842), 'tissue_lowres_scalef': np.float64(0.012335527)}
{'fiducial_diameter_fullres': np.float64(609.50275), 'spot_diameter_fullres': np.float64(377.31122), 'tissue_hires_scalef': np.float64(0.04111842), 'tissue_lowres_scalef': np.float64(0.012335527)}
{'fiducial_diameter_fullres': np.float64(609.6982399999999), 'spot_diameter_fullres': np.float64(377.43224999999995), 'tissue_hires_scalef': np.float64(0.04111842), 'tissue_lowres_scalef': np.float64(0.012335527)}
{'fiducial_diameter_fullres': np.float64(609.4973), 'spot_diameter_fullres': np.float64(377.30785999999995), 'tissue_hires_scalef': np.float64(0.04111842), 'tissue_lowres_scalef': np.float64(0.012335527)}

/Users/chenlingxi/miniconda3/envs/dev/lib/python3.11/site-packages/anndata/_core/aligned_df.py:68: ImplicitModificationWarning: Transforming to str index.
/Users/chenlingxi/miniconda3/envs/dev/lib/python3.11/site-packages/anndata/_core/anndata.py:1756: UserWarning: Observation names are not unique. To make them unique, call `.obs_names_make_unique`.

mdata
AnnData object with n_obs × n_vars = 15813 × 13934
    obs: 'SM_index', 'SM_sample', 'SM_block', 'SM_n_genes', 'SM_ST_RegionLoupe', 'SM_ST_MSN.D2.PenkNeg_5', 'SM_ST_MSN.D1.TacNeg_3', 'SM_ST_MSN.D2_C_18', 'SM_ST_MSN.D1.TacPosB_6', 'SM_ST_MSN.D1.TacPosA_9', 'SM_ST_MSN.D2.PenkPos_2', 'SM_ST_ST_id', 'SM_LY6H', 'SM_THY1', 'SM_VSNL1', 'SM_PCDH11X', 'SM_MBP', 'SM_PLP1', 'SM_CHN1', 'SM_SYNPR', 'SM_NCDN', 'SM_MAP2', 'SM_GDA', 'SM_HPCAL4', 'SM_RTN1', 'SM_NNAT', 'SM_TSPAN7', 'SM_PEG10', 'SM_SCG2', 'SM_TF', 'SM_CRYM', 'SM_GFAP', 'SM_MT1G', 'ST_index', 'ST_in_tissue', 'ST_array_row', 'ST_array_col', 'ST_dopamine', 'ST_cell_type', 'ST_sample', 'ST_block', 'ST_orig.ident', 'ST_nCount_RNA', 'ST_nFeature_RNA', 'ST_Protocol', 'ST_Path.To.File', 'ST_File.Name', 'ST_Data.Type', 'ST_Glass.Type', 'ST_ArrayID', 'ST_Sample.ID', 'ST_Matrix', 'ST_Laser', 'ST_Laser.resolution', 'ST_Condition', 'ST_Brain.area', 'ST_Visium.Protocol', 'ST_id', 'ST_labels', 'ST_Prot.Short', 'ST_section_number', 'ST_type', 'ST_type.area', 'ST_lesion', 'ST_region', 'ST_RegionLoupe', 'ST_percent.mito', 'ST_percent.ribo', 'ST_Astrocytes', 'ST_Cerebellum.neurons', 'ST_Cholinergic.and.monoaminergic.neurons', 'ST_Cholinergic.and.monoaminergic.neurons.MBDOP1', 'ST_Cholinergic.and.monoaminergic.neurons.MBDOP2', 'ST_Choroid.epithelial.cells', 'ST_Dentate.gyrus.granule.neurons', 'ST_Dentate.gyrus.radial.glia.like.cells', 'ST_Di..and.mesencephalon.excitatory.neurons', 'ST_Di..and.mesencephalon.inhibitory.neurons', 'ST_Enteric.glia', 'ST_Enteric.neurons', 'ST_Ependymal.cells', 'ST_Glutamatergic.neuroblasts', 'ST_Hindbrain.neurons', 'ST_Microglia', 'ST_Non.glutamatergic.neuroblasts', 'ST_Olfactory.ensheathing.cells', 'ST_Olfactory.inhibitory.neurons', 'ST_Olfactory.inhibitory.neurons.OBDOP1', 'ST_Olfactory.inhibitory.neurons.OBDOP2', 'ST_Oligodendrocyte.precursor.cells', 'ST_Oligodendrocytes', 'ST_Peptidergic.neurons', 'ST_Pericytes', 'ST_Peripheral.sensory.neurofilament.neurons', 'ST_Peripheral.sensory.non.peptidergic.neurons', 'ST_Peripheral.sensory.peptidergic.neurons', 'ST_Perivascular.macrophages', 'ST_Satellite.glia', 'ST_Schwann.cells', 'ST_Spinal.cord.excitatory.neurons', 'ST_Spinal.cord.inhibitory.neurons', 'ST_Subcommissural.organ.hypendymal.cells', 'ST_Subventricular.zone.radial.glia.like.cells', 'ST_Sympathetic.cholinergic.neurons', 'ST_Sympathetic.noradrenergic.neurons', 'ST_Telencephalon.inhibitory.interneurons', 'ST_Telencephalon.projecting.excitatory.neurons', 'ST_Telencephalon.projecting.inhibitory.neurons.MSN1', 'ST_Telencephalon.projecting.inhibitory.neurons.MSN2', 'ST_Telencephalon.projecting.inhibitory.neurons.MSN3', 'ST_Telencephalon.projecting.inhibitory.neurons.MSN4', 'ST_Telencephalon.projecting.inhibitory.neurons.MSN5', 'ST_Telencephalon.projecting.inhibitory.neurons.MSN6', 'ST_Vascular.and.leptomeningeal.cells', 'ST_Vascular.endothelial.cells', 'ST_Vascular.smooth.muscle.cells', 'ST_nCount_SCT', 'ST_nFeature_SCT', 'ST_Astro_0', 'ST_Oligo_1', 'ST_MSN.D2.PenkPos_2', 'ST_MSN.D1.TacNeg_3', 'ST_Oligo_4', 'ST_MSN.D2.PenkNeg_5', 'ST_MSN.D1.TacPosB_6', 'ST_OPC_7', 'ST_Mi.MiR.Ma_8', 'ST_MSN.D1.TacPosA_9', 'ST_Astro_10', 'ST_Astro_11', 'ST_Inhib_MSN_12', 'ST_Inhib_13', 'ST_unk_14', 'ST_unk_15', 'ST_unk_16', 'ST_Astro_17', 'ST_MSN.D2_C_18', 'ST_unk_19', 'ST_OPC_20', 'ST_Oligo_21', 'ST_unk_22', 'ST_barcode', 'ST_library', 'ST_n_genes', 'SM_i', 'ST_i'
    obsm: 'SM_XY_spatial_euclidean_dist', 'SM_mappingflow_MCMF', 'SM_spatial', 'SM_spatial_MCMF_map', 'SM_spatial_normalized', 'SM_spatial_rir', 'SM_spatial_rir_filtered', 'ST_spatial', 'ST_spatial_normalized', 'ST_spatial_rir', 'ST_spatial_rir_filtered'
    layers: 'log1p', 'raw'
%autoreload
from scrofit.embedding import embedding

embedding(mdata)
mdata.write_h5ad(f'{in_dir}/{sample}_m_pp.adata')