├── .gitignore
├── .readthedocs.yml
├── 0_CellChatDB
├── 1_human
│ ├── complex_input_CellChatDB.csv
│ └── t.csv
└── 2_mouse
│ ├── complex_input_CellChatDB.csv
│ └── interaction_input_CellChatDB.csv
├── LICENSE
├── README.rst
├── docs
├── .figs
│ ├── AvsB-1.png
│ ├── SPP1_CD44.png
│ ├── global_plot.png
│ └── runtime_aug16-1.png
├── Makefile
├── api.rst
├── autosummary
│ ├── base.rst
│ └── class.rst
├── conf.py
├── custom.css
├── differential_test_intestine.ipynb
├── index.rst
├── install.rst
├── melanoma.ipynb
├── release.rst
└── requirements.txt
├── requirements.txt
├── setup.py
├── spatialdm
├── __init__.py
├── datasets
│ ├── LR_data
│ │ ├── human-complex_input_CellChatDB.csv
│ │ ├── human-interaction_input_CellChatDB.csv.gz
│ │ ├── mouse-complex_input_CellChatDB.csv
│ │ ├── mouse-interaction_input_CellChatDB.csv.gz
│ │ ├── zerafish-complex_input_CellChatDB.csv
│ │ └── zerafish-interaction_input_CellChatDB.csv.gz
│ ├── __init__.py
│ ├── _util_dataset.py
│ └── dataset.py
├── diff_utils.py
├── main.py
├── plottings.py
├── utils.py
└── version.py
└── tutorial
├── differential_test_intestine.ipynb
├── melanoma.ipynb
└── simulation
├── ligand_recptor_pairs_sim.csv
├── pos.txt
└── simulation_code.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | .vscode/
3 |
4 | # Byte-compiled / optimized / DLL files
5 | __pycache__/
6 | *.py[cod]
7 | *$py.class
8 |
9 | # C extensions
10 | *.so
11 |
12 | # Distribution / packaging
13 | .Python
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | .eggs/
20 | lib/
21 | lib64/
22 | parts/
23 | sdist/
24 | var/
25 | wheels/
26 | *.egg-info/
27 | .installed.cfg
28 | *.egg
29 | MANIFEST
30 |
31 | # PyInstaller
32 | # Usually these files are written by a python script from a template
33 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
34 | *.manifest
35 | *.spec
36 |
37 | # Installer logs
38 | pip-log.txt
39 | pip-delete-this-directory.txt
40 |
41 | # Unit test / coverage reports
42 | htmlcov/
43 | .tox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | .hypothesis/
51 | .pytest_cache/
52 |
53 | # Translations
54 | *.mo
55 | *.pot
56 |
57 | # Django stuff:
58 | *.log
59 | local_settings.py
60 | db.sqlite3
61 |
62 | # Flask stuff:
63 | instance/
64 | .webassets-cache
65 |
66 | # Scrapy stuff:
67 | .scrapy
68 |
69 | # Sphinx documentation
70 | doc/_build/
71 |
72 | # PyBuilder
73 | target/
74 |
75 | # Jupyter Notebook
76 | .ipynb_checkpoints
77 |
78 | # pyenv
79 | .python-version
80 |
81 | # celery beat schedule file
82 | celerybeat-schedule
83 |
84 | # SageMath parsed files
85 | *.sage.py
86 |
87 | # Environments
88 | .env
89 | .venv
90 | env/
91 | venv/
92 | ENV/
93 | env.bak/
94 | venv.bak/
95 |
96 | # Spyder project settings
97 | .spyderproject
98 | .spyproject
99 |
100 | # Rope project settings
101 | .ropeproject
102 |
103 | # mkdocs documentation
104 | /site
105 |
106 | # mypy
107 | .mypy_cache/
108 |
109 | # test and data
110 | data/outs
111 | temp/
112 |
113 | #output
114 | tutorial/*.h5ad
115 |
--------------------------------------------------------------------------------
/.readthedocs.yml:
--------------------------------------------------------------------------------
1 | sphinx:
2 | configuration: docs/conf.py
3 | build:
4 | image: latest
5 | python:
6 | version: 3.7
7 | install:
8 | - requirements: docs/requirements.txt
9 | - requirements: requirements.txt
10 | - method: pip
11 | path: .
12 | extra_requirements:
13 | - docs
14 | - method: setuptools
15 | path: package
16 | system_packages: true
17 |
--------------------------------------------------------------------------------
/0_CellChatDB/1_human/complex_input_CellChatDB.csv:
--------------------------------------------------------------------------------
1 | "","subunit_1","subunit_2","subunit_3","subunit_4"
2 | "Activin AB","INHBA","INHBB","",""
3 | "Inhibin A","INHA","INHBA","",""
4 | "Inhibin B","INHA","INHBB","",""
5 | "IL12AB","IL12A","IL12B","",""
6 | "IL23 complex","IL12B","IL23A","",""
7 | "IL27 complex","IL27","EBI3","",""
8 | "IL17AF","IL17A","IL17F","",""
9 | "LTa1b2","LTA","LTB","",""
10 | "GP complex","GP1BA","GP1BB","GP5","GP9"
11 | "ACVR1_ACVR2A","ACVR1","ACVR2A","",""
12 | "ACVR1_ACVR2B","ACVR1","ACVR2B","",""
13 | "ACVR1_BMPR2","ACVR1","BMPR2","",""
14 | "ACVR1_TGFbR","ACVR1","TGFBR1","TGFBR2",""
15 | "ACVR1B_ACVR2A","ACVR1B","ACVR2A","",""
16 | "ACVR1B_ACVR2A_CFC1","ACVR1B","ACVR2A","CFC1",""
17 | "ACVR1B_ACVR2B","ACVR1B","ACVR2B","",""
18 | "ACVR1B_ACVR2B_CFC1","ACVR1B","ACVR2B","CFC1",""
19 | "ACVR1B_BMPR2","ACVR1B","BMPR2","",""
20 | "ACVR1B_TGFbR2","ACVR1B","TGFBR2","",""
21 | "ACVR1C_ACVR2A","ACVR1C","ACVR2A","",""
22 | "ACVR1C_ACVR2A_CFC1","ACVR1C","ACVR2A","CFC1",""
23 | "ACVR1C_ACVR2B","ACVR1C","ACVR2B","",""
24 | "ACVR1C_ACVR2B_CFC1","ACVR1C","ACVR2B","CFC1",""
25 | "ACVR1C_TGFbR2","ACVR1C","TGFBR2","",""
26 | "ACVRL1_ACVR2A","ACVRL1","ACVR2A","",""
27 | "ACVRL1_BMPR2","ACVRL1","BMPR2","",""
28 | "AMHR2_ACVR1","AMHR2","ACVR1","",""
29 | "AMHR2_BMPR1A","AMHR2","BMPR1A","",""
30 | "BMPR1A_ACVR2A","BMPR1A","ACVR2A","",""
31 | "BMPR1A_ACVR2B","BMPR1A","ACVR2B","",""
32 | "BMPR1A_BMPR2","BMPR1A","BMPR2","",""
33 | "BMPR1B_ACVR2A","BMPR1B","ACVR2A","",""
34 | "BMPR1B_ACVR2B","BMPR1B","ACVR2B","",""
35 | "BMPR1B_BMPR2","BMPR1B","BMPR2","",""
36 | "CD74_CD44","CD74","CD44","",""
37 | "CD74_CXCR2","CD74","CXCR2","",""
38 | "CD74_CXCR4","CD74","CXCR4","",""
39 | "CD8 receptor","CD8A","CD8B","",""
40 | "CNTFR_LIFR","CNTFR","LIFR","IL6ST",""
41 | "CNTN1_CNTNAP1","CNTN1","CNTNAP1","",""
42 | "CNTN2_CNTNAP2","CNTN2","CNTNAP2","",""
43 | "CSF2RA_CSF2RB","CSF2RA","CSF2RB","",""
44 | "EGFR_ERBB2","EGFR","ERBB2","",""
45 | "ERBB2_ERBB3","ERBB2","ERBB3","",""
46 | "ERBB2_ERBB4","ERBB2","ERBB4","",""
47 | "FLT1_KDR","FLT1","KDR","",""
48 | "FLT4_KDR","FLT4","KDR","",""
49 | "FPR2_LXA4","FPR2","FPR3","",""
50 | "FZD1_LRP5","FZD1","LRP5","",""
51 | "FZD1_LRP6","FZD1","LRP6","",""
52 | "FZD10_LRP5","FZD10","LRP5","",""
53 | "FZD10_LRP6","FZD10","LRP6","",""
54 | "FZD2_LRP5","FZD2","LRP5","",""
55 | "FZD2_LRP6","FZD2","LRP6","",""
56 | "FZD3_LRP5","FZD3","LRP5","",""
57 | "FZD3_LRP6","FZD3","LRP6","",""
58 | "FZD4_LRP5","FZD4","LRP5","",""
59 | "FZD4_LRP6","FZD4","LRP6","",""
60 | "FZD5_LRP5","FZD5","LRP5","",""
61 | "FZD5_LRP6","FZD5","LRP6","",""
62 | "FZD6_LRP5","FZD6","LRP5","",""
63 | "FZD6_LRP6","FZD6","LRP6","",""
64 | "FZD7_LRP5","FZD7","LRP5","",""
65 | "FZD7_LRP6","FZD7","LRP6","",""
66 | "FZD8_LRP5","FZD8","LRP5","",""
67 | "FZD8_LRP6","FZD8","LRP6","",""
68 | "FZD9_LRP5","FZD9","LRP5","",""
69 | "FZD9_LRP6","FZD9","LRP6","",""
70 | "GFRA1_RET","GFRA1","RET","",""
71 | "GFRA2_RET","GFRA2","RET","",""
72 | "GFRA3_RET","GFRA3","RET","",""
73 | "GFRA4_RET","GFRA4","RET","",""
74 | "IFNAR1_IFNAR2","IFNAR1","IFNAR2","",""
75 | "IFNGR1_IFNGR2","IFNGR1","IFNGR2","",""
76 | "IFNLR1_IL10RB","IFNLR1","IL10RB","",""
77 | "IL10RA_IL10RB","IL10RA","IL10RB","",""
78 | "IL11R complex","IL11RA","IL6ST","",""
79 | "IL12RB1_IL12RB2","IL12RB1","IL12RB2","",""
80 | "IL15RA_IL2RB","IL15RA","IL2RB","IL2RG",""
81 | "IL17RA_IL17RB","IL17RA","IL17RB","",""
82 | "IL17RA_IL17RC","IL17RA","IL17RC","",""
83 | "IL17RA_IL17RE","IL17RA","IL17RE","",""
84 | "IL18R1_IL18RAP","IL18R1","IL18RAP","",""
85 | "IL1R1_IL1RAP","IL1R1","IL1RAP","",""
86 | "IL1RL1_IL1RAP","IL1RL1","IL1RAP","",""
87 | "IL1RL2_IL1RAP","IL1RL2","IL1RAP","",""
88 | "IL2RA_IL2RB_IL2RG","IL20RA","IL20RB","IL2RG",""
89 | "IL21R_IL2RG","IL21R","IL2RG","",""
90 | "IL22RA1_IL10RB","IL22RA1","IL10RB","",""
91 | "IL22RA1_IL20RB","IL22RA1","IL20RB","",""
92 | "IL20RA_IL20RB","IL20RA","IL20RB","",""
93 | "IL20RA_IL10RB","IL20RA","IL10RB","",""
94 | "IL23R_IL12RB1","IL23R","IL12RB1","",""
95 | "IL27RA_IL6ST","IL27RA","IL6ST","",""
96 | "IL28RA_IL10RB","IFNLR1","IL10RB","",""
97 | "IL2RB_IL2RG","IL2RB","IL2RG","",""
98 | "IL2RA_IL2RB","IL2RA","IL2RB","IL2RG",""
99 | "IL31RA_OSMR","IL31RA","OSMR","",""
100 | "IL3RA_CSF2RB","IL3RA","CSF2RB","",""
101 | "IL4R_IL13RA1","IL4R","IL13RA1","",""
102 | "IL4R_IL13RA2","IL4R","IL13RA2","",""
103 | "IL4R_IL2RG","IL4R","IL2RG","",""
104 | "IL5RA_CSF2RB","IL5RA","CSF2RB","",""
105 | "IL6R_IL6ST","IL6R","IL6ST","",""
106 | "IL7R_CRLF2","IL7R","CRLF2","",""
107 | "IL7R_IL2RG","IL7R","IL2RG","",""
108 | "IL9R_IL2RG","IL9R","IL2RG","",""
109 | "ITGA1_ITGB1","ITGA1","ITGB1","",""
110 | "ITGA10_ITGB1","ITGA10","ITGB1","",""
111 | "ITGA11_ITGB1","ITGA11","ITGB1","",""
112 | "ITGA2_ITGB1","ITGA2","ITGB1","",""
113 | "ITGA2B_ITGB3","ITGA2B","ITGB3","",""
114 | "ITGA3_ITGB1","ITGA3","ITGB1","",""
115 | "ITGA4_ITGB1","ITGA4","ITGB1","",""
116 | "ITGA4_ITGB7","ITGA4","ITGB7","",""
117 | "ITGA5_ITGB1","ITGA5","ITGB1","",""
118 | "ITGA6_ITGB1","ITGA6","ITGB1","",""
119 | "ITGA6_ITGB4","ITGA6","ITGB4","",""
120 | "ITGA7_ITGB1","ITGA7","ITGB1","",""
121 | "ITGA8_ITGB1","ITGA8","ITGB1","",""
122 | "ITGA9_ITGB1","ITGA9","ITGB1","",""
123 | "ITGAE_ITGB7","ITGAE","ITGB7","",""
124 | "ITGAL_ITGB2","ITGAL","ITGB2","",""
125 | "ITGAM_ITGB2","ITGAM","ITGB2","",""
126 | "ITGAV_ITGB1","ITGAV","ITGB1","",""
127 | "ITGAV_ITGB3","ITGAV","ITGB3","",""
128 | "ITGAV_ITGB5","ITGAV","ITGB5","",""
129 | "ITGAV_ITGB6","ITGAV","ITGB6","",""
130 | "ITGAV_ITGB8","ITGAV","ITGB8","",""
131 | "ITGAX_ITGB2","ITGAX","ITGB2","",""
132 | "ITGB1_ITGA1","ITGB1","ITGA1","",""
133 | "KLRD1_KLRC1","KLRD1","KLRC1","",""
134 | "KLRD1_KLRC2","KLRD1","KLRC2","",""
135 | "KLRK1_HCST","KLRK1","HCST","",""
136 | "LIFR_IL6ST","LIFR","IL6ST","",""
137 | "Npnt complex 1","NPNT","FRAS1","FREM1",""
138 | "Npnt complex 2","NPNT","FRAS1","FREM2",""
139 | "NRP1_NRP2","NRP1","NRP2","PLXND1",""
140 | "NRP1_PLXNA1","NRP1","PLXNA1","",""
141 | "NRP1_PLXNA2","NRP1","PLXNA2","",""
142 | "NRP1_PLXNA3","NRP1","PLXNA3","",""
143 | "NRP1_PLXNA4","NRP1","PLXNA4","",""
144 | "NRP2_PLXNA1","NRP2","PLXNA1","",""
145 | "NRP2_PLXNA2","NRP2","PLXNA2","",""
146 | "NRP2_PLXNA3","NRP2","PLXNA3","",""
147 | "NRP2_PLXNA4","NRP2","PLXNA4","",""
148 | "OSMR_IL6ST","OSMR","IL6ST","",""
149 | "PLXNA1_KDR","PLXNA1","KDR","",""
150 | "PLXNA1_TREM2","PLXNA1","TREM2","TYROBP",""
151 | "PTCH1_SMO","PTCH1","SMO","",""
152 | "PTCH2_SMO","PTCH2","SMO","",""
153 | "TGFBR1_ACVR2A","TGFBR1","ACVR2A","",""
154 | "TGFBR1_ACVR2B","TGFBR1","ACVR2B","",""
155 | "TGFbR1_R2","TGFBR1","TGFBR2","",""
156 | "CD94:NKG2A","KLRD1","KLRC1","",""
157 | "CD94:NKG2C","KLRD1","KLRC2","",""
158 | "CD94:NKG2E","KLRD1","KLRC3","",""
159 |
--------------------------------------------------------------------------------
/0_CellChatDB/2_mouse/complex_input_CellChatDB.csv:
--------------------------------------------------------------------------------
1 | "","subunit_1","subunit_2","subunit_3","subunit_4"
2 | "Activin AB","Inhba","Inhbb","",""
3 | "Inhibin A","Inha","Inhba","",""
4 | "Inhibin B","Inha","Inhbb","",""
5 | "IL12AB","Il12a","Il12b","",""
6 | "IL23 complex","Il12b","Il23a","",""
7 | "IL27 complex","Il27","Ebi3","",""
8 | "IL17AF","Il17a","Il17f","",""
9 | "LTa1b2","Lta","Ltb","",""
10 | "GP complex","Gp1ba","Gp1bb","Gp5","Gp9"
11 | "ACVR1_ACVR2A","Acvr1","Acvr2a","",""
12 | "ACVR1_ACVR2B","Acvr1","Acvr2b","",""
13 | "ACVR1_BMPR2","Acvr1","Bmpr2","",""
14 | "ACVR1_TGFbR","Acvr1","Tgfbr1","Tgfbr2",""
15 | "ACVR1B_ACVR2A","Acvr1b","Acvr2a","",""
16 | "ACVR1B_ACVR2A_CFC1","Acvr1b","Acvr2a","Cfc1",""
17 | "ACVR1B_ACVR2B","Acvr1b","Acvr2b","",""
18 | "ACVR1B_ACVR2B_CFC1","Acvr1b","Acvr2b","Cfc1",""
19 | "ACVR1B_BMPR2","Acvr1b","Bmpr2","",""
20 | "ACVR1B_TGFbR2","Acvr1b","Tgfbr2","",""
21 | "ACVR1C_ACVR2A","Acvr1c","Acvr2a","",""
22 | "ACVR1C_ACVR2A_CFC1","Acvr1c","Acvr2a","Cfc1",""
23 | "ACVR1C_ACVR2B","Acvr1c","Acvr2b","",""
24 | "ACVR1C_ACVR2B_CFC1","Acvr1c","Acvr2b","Cfc1",""
25 | "ACVR1C_TGFbR2","Acvr1c","Tgfbr2","",""
26 | "ACVRL1_ACVR2A","Acvrl1","Acvr2a","",""
27 | "ACVRL1_BMPR2","Acvrl1","Bmpr2","",""
28 | "AMHR2_ACVR1","Amhr2","Acvr1","",""
29 | "AMHR2_BMPR1A","Amhr2","Bmpr1a","",""
30 | "BMPR1A_ACVR2A","Bmpr1a","Acvr2a","",""
31 | "BMPR1A_ACVR2B","Bmpr1a","Acvr2b","",""
32 | "BMPR1A_BMPR2","Bmpr1a","Bmpr2","",""
33 | "BMPR1B_ACVR2A","Bmpr1b","Acvr2a","",""
34 | "BMPR1B_ACVR2B","Bmpr1b","Acvr2b","",""
35 | "BMPR1B_BMPR2","Bmpr1b","Bmpr2","",""
36 | "CD74_CD44","Cd74","Cd44","",""
37 | "CD74_CXCR2","Cd74","Cxcr2","",""
38 | "CD74_CXCR4","Cd74","Cxcr4","",""
39 | "CD8 receptor","Cd8a","Cd8b1","",""
40 | "CNTFR_LIFR","Cntfr","Lifr","Il6st",""
41 | "CNTN1_CNTNAP1","Cntn1","Cntnap1","",""
42 | "CNTN2_CNTNAP2","Cntn2","Cntnap2","",""
43 | "CSF2RA_CSF2RB","Csf2ra","Csf2rb","",""
44 | "EGFR_ERBB2","Egfr","Erbb2","",""
45 | "ERBB2_ERBB3","Erbb2","Erbb3","",""
46 | "ERBB2_ERBB4","Erbb2","Erbb4","",""
47 | "FLT1_KDR","Flt1","Kdr","",""
48 | "FLT4_KDR","Flt4","Kdr","",""
49 | "FPR2_LXA4","Fpr2","Fpr3","",""
50 | "FZD1_LRP5","Fzd1","Lrp5","",""
51 | "FZD1_LRP6","Fzd1","Lrp6","",""
52 | "FZD10_LRP5","Fzd10","Lrp5","",""
53 | "FZD10_LRP6","Fzd10","Lrp6","",""
54 | "FZD2_LRP5","Fzd2","Lrp5","",""
55 | "FZD2_LRP6","Fzd2","Lrp6","",""
56 | "FZD3_LRP5","Fzd3","Lrp5","",""
57 | "FZD3_LRP6","Fzd3","Lrp6","",""
58 | "FZD4_LRP5","Fzd4","Lrp5","",""
59 | "FZD4_LRP6","Fzd4","Lrp6","",""
60 | "FZD5_LRP5","Fzd5","Lrp5","",""
61 | "FZD5_LRP6","Fzd5","Lrp6","",""
62 | "FZD6_LRP5","Fzd6","Lrp5","",""
63 | "FZD6_LRP6","Fzd6","Lrp6","",""
64 | "FZD7_LRP5","Fzd7","Lrp5","",""
65 | "FZD7_LRP6","Fzd7","Lrp6","",""
66 | "FZD8_LRP5","Fzd8","Lrp5","",""
67 | "FZD8_LRP6","Fzd8","Lrp6","",""
68 | "FZD9_LRP5","Fzd9","Lrp5","",""
69 | "FZD9_LRP6","Fzd9","Lrp6","",""
70 | "GFRA1_RET","Gfra1","Ret","",""
71 | "GFRA2_RET","Gfra2","Ret","",""
72 | "GFRA3_RET","Gfra3","Ret","",""
73 | "GFRA4_RET","Gfra4","Ret","",""
74 | "IFNAR1_IFNAR2","Ifnar1","Ifnar2","",""
75 | "IFNGR1_IFNGR2","Ifngr1","Ifngr2","",""
76 | "IFNLR1_IL10RB","Ifnlr1","Il10rb","",""
77 | "IL10RA_IL10RB","Il10ra","Il10rb","",""
78 | "IL11R complex 1","Il11ra1","Il6st","",""
79 | "IL11R complex 2","Il11ra2","Il6st","",""
80 | "IL12RB1_IL12RB2","Il12rb1","Il12rb2","",""
81 | "IL15RA_IL2RB","Il15ra","Il2rb","Il2rg",""
82 | "IL17RA_IL17RB","Il17ra","Il17rb","",""
83 | "IL17RA_IL17RC","Il17ra","Il17rc","",""
84 | "IL17RA_IL17RE","Il17ra","Il17re","",""
85 | "IL18R1_IL18RAP","Il18r1","Il18rap","",""
86 | "IL1R1_IL1RAP","Il1r1","Il1rap","",""
87 | "IL1RL1_IL1RAP","Il1rl1","Il1rap","",""
88 | "IL1RL2_IL1RAP","Il1rl2","Il1rap","",""
89 | "IL20RA_IL20RB","Il20ra","Il20rb","",""
90 | "IL21R_IL2RG","Il21r","Il2rg","",""
91 | "IL22RA1_IL10RB","Il22ra1","Il10rb","",""
92 | "IL22RA1_IL20RB","Il22ra1","Il20rb","",""
93 | "IL23R_IL12RB1","Il23r","Il12rb1","",""
94 | "IL27RA_IL6ST","Il27ra","Il6st","",""
95 | "IL28RA_IL10RB","Ifnlr1","Il10rb","",""
96 | "IL2RB_IL2RG","Il2rb","Il2rg","",""
97 | "IL2RA_IL2RB","Il2ra","Il2rb","Il2rg",""
98 | "IL31RA_OSMR","Il31ra","Osmr","",""
99 | "IL3RA_CSF2RB","Il3ra","Csf2rb","",""
100 | "IL4R_IL13RA1","Il4ra","Il13ra1","",""
101 | "IL4R_IL13RA2","Il4ra","Il13ra2","",""
102 | "IL4R_IL2RG","Il4ra","Il2rg","",""
103 | "IL5RA_CSF2RB","Il5ra","Csf2rb","",""
104 | "IL6R_IL6ST","Il6ra","Il6st","",""
105 | "IL7R_CRLF2","Il7r","Crlf2","",""
106 | "IL7R_IL2RG","Il7r","Il2rg","",""
107 | "IL9R_IL2RG","Il9r","Il2rg","",""
108 | "ITGA1_ITGB1","Itga1","Itgb1","",""
109 | "ITGA10_ITGB1","Itga10","Itgb1","",""
110 | "ITGA11_ITGB1","Itga11","Itgb1","",""
111 | "ITGA2_ITGB1","Itga2","Itgb1","",""
112 | "ITGA2B_ITGB3","Itga2b","Itgb3","",""
113 | "ITGA3_ITGB1","Itga3","Itgb1","",""
114 | "ITGA4_ITGB1","Itga4","Itgb1","",""
115 | "ITGA4_ITGB7","Itga4","Itgb7","",""
116 | "ITGA5_ITGB1","Itga5","Itgb1","",""
117 | "ITGA6_ITGB1","Itga6","Itgb1","",""
118 | "ITGA6_ITGB4","Itga6","Itgb4","",""
119 | "ITGA7_ITGB1","Itga7","Itgb1","",""
120 | "ITGA8_ITGB1","Itga8","Itgb1","",""
121 | "ITGA9_ITGB1","Itga9","Itgb1","",""
122 | "ITGAE_ITGB7","Itgae","Itgb7","",""
123 | "ITGAL_ITGB2","Itgal","Itgb2","",""
124 | "ITGAL_ITGB2L","Itgal","Itgb2l","",""
125 | "ITGAM_ITGB2","Itgam","Itgb2","",""
126 | "ITGAM_ITGB2L","Itgam","Itgb2l","",""
127 | "ITGAV_ITGB1","Itgav","Itgb1","",""
128 | "ITGAV_ITGB3","Itgav","Itgb3","",""
129 | "ITGAV_ITGB5","Itgav","Itgb5","",""
130 | "ITGAV_ITGB6","Itgav","Itgb6","",""
131 | "ITGAV_ITGB8","Itgav","Itgb8","",""
132 | "ITGAX_ITGB2","Itgax","Itgb2","",""
133 | "ITGB1_ITGA1","Itgb1","Itga1","",""
134 | "KLRD1_KLRC1","Klrd1","Klrc1","",""
135 | "KLRD1_KLRC2","Klrd1","Klrc2","",""
136 | "KLRK1_HCST","Klrk1","Hcst","",""
137 | "LIFR_IL6ST","Lifr","Il6st","",""
138 | "Npnt complex 1","Npnt","Fras1","Frem1",""
139 | "Npnt complex 2","Npnt","Fras1","Frem2",""
140 | "NRP1_NRP2","Nrp1","Nrp2","Plxnd1",""
141 | "NRP1_PLXNA1","Nrp1","Plxna1","",""
142 | "NRP1_PLXNA2","Nrp1","Plxna2","",""
143 | "NRP1_PLXNA3","Nrp1","Plxna3","",""
144 | "NRP1_PLXNA4","Nrp1","Plxna4","",""
145 | "NRP2_PLXNA1","Nrp2","Plxna1","",""
146 | "NRP2_PLXNA2","Nrp2","Plxna2","",""
147 | "NRP2_PLXNA3","Nrp2","Plxna3","",""
148 | "NRP2_PLXNA4","Nrp2","Plxna4","",""
149 | "OSMR_IL6ST","Osmr","Il6st","",""
150 | "PLXNA1_KDR","Plxna1","Kdr","",""
151 | "PLXNA1_TREM2","Plxna1","Trem2","Tyrobp",""
152 | "PTCH1_SMO","Ptch1","Smo","",""
153 | "PTCH2_SMO","Ptch2","Smo","",""
154 | "TGFBR1_ACVR2A","Tgfbr1","Acvr2a","",""
155 | "TGFBR1_ACVR2B","Tgfbr1","Acvr2b","",""
156 | "TGFbR1_R2","Tgfbr1","Tgfbr2","",""
157 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | ===============================================================
2 | SpatialDM: Spatial Direct Messaging Detected by bivariate Moran
3 | ===============================================================
4 |
5 | About
6 | =====
7 |
8 | SpatialDM (Spatial Direct Messaging, or Spatial co-expressed ligand and receptor Detected by Moran's bivariant extension), a statistical model and toolbox to identify the spatial co-expression (i.e., spatial association) between a pair of ligand and receptor. \
9 |
10 | Uniquely, SpatialDM can distinguish co-expressed ligand and receptor pairs from spatially separating pairs, and identify the spots of interaction.
11 |
12 | .. image:: https://github.com/StatBiomed/SpatialDM/blob/main/docs/.figs/AvsB-1.png?raw=true
13 | :width: 900px
14 | :align: center
15 |
16 | With the analytical testing method, SpatialDM is scalable to 1 million spots within 12 min with only one core.
17 |
18 | .. image:: https://github.com/StatBiomed/SpatialDM/blob/main/docs/.figs/runtime_aug16-1.png?raw=true
19 | :width: 600px
20 | :align: center
21 |
22 | It comprises two main steps: \
23 | 1) global selection `spatialdm_global` to identify significantly interacting LR pairs; \
24 | 2) local selection `spatialdm_local` to identify local spots for each interaction.
25 |
26 | Installation
27 | ============
28 |
29 | SpatialDM is available through `PyPI `_.
30 | To install, type the following command line and add ``-U`` for updates:
31 |
32 | .. code-block:: bash
33 |
34 | pip install -U SpatialDM
35 |
36 | Alternatively, you can install from this GitHub repository for latest (often
37 | development) version by the following command line:
38 |
39 | .. code-block:: bash
40 |
41 | pip install -U git+https://github.com/StatBiomed/SpatialDM
42 |
43 | Installation time: < 1 min
44 |
45 |
46 |
47 | Quick example
48 | =============
49 |
50 | Using the build-in melanoma dataset as an example, the following Python script
51 | will compute the p-value indicating whether a certain Ligand-Receptor is
52 | spatially co-expressed.
53 |
54 |
55 | .. code-block:: python
56 |
57 | import spatialdm as sdm
58 | adata = sdm.datasets.dataset.melanoma()
59 | sdm.weight_matrix(adata, l=1.2, cutoff=0.2, single_cell=False) # weight_matrix by rbf kernel
60 | sdm.extract_lr(adata, 'human', min_cell=3) # find overlapping LRs from CellChatDB
61 | sdm.spatialdm_global(adata, 1000, specified_ind=None, method='both', nproc=1) # global Moran selection
62 | sdm.sig_pairs(adata, method='permutation', fdr=True, threshold=0.1) # select significant pairs
63 | sdm.spatialdm_local(adata, n_perm=1000, method='both', specified_ind=None, nproc=1) # local spot selection
64 | sdm.sig_spots(adata, method='permutation', fdr=False, threshold=0.1) # significant local spots
65 |
66 | # visualize global and local pairs
67 | import spatialdm.plottings as pl
68 | pl.global_plot(adata, pairs=['SPP1_CD44'])
69 | pl.plot_pairs(adata, ['SPP1_CD44'], marker='s')
70 |
71 | .. image:: https://github.com/StatBiomed/SpatialDM/blob/main/docs/.figs/global_plot.png?raw=true
72 | :width: 200px
73 | :align: center
74 |
75 | .. image:: https://github.com/StatBiomed/SpatialDM/blob/main/docs/.figs/SPP1_CD44.png?raw=true
76 | :width: 600px
77 | :align: center
78 |
79 |
80 |
81 | Detailed Manual
82 | ===============
83 |
84 | The full manual is at https://spatialdm.readthedocs.io, including:
85 |
86 | * `Permutation-based SpatialDM (Recommended for small datasets, <10k spots)`_.
87 |
88 | * `Differential analyses of whole interactome among varying conditions`_.
89 |
90 | .. _Permutation-based SpatialDM (Recommended for small datasets, <10k spots): tutorial/melanoma.ipynb
91 |
92 | .. _Differential analyses of whole interactome among varying conditions: tutorial/differential_test_intestine.ipynb
93 |
94 |
95 |
96 |
97 | References
98 | ==========
99 |
100 | SpatialDM manuscript with more details is available on bioRxiv_ now and is currently under review.
101 |
102 | .. _bioRxiv: https://www.biorxiv.org/content/10.1101/2022.08.19.504616v1/
103 |
104 |
--------------------------------------------------------------------------------
/docs/.figs/AvsB-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StatBiomed/SpatialDM/bfd2c3739abf5432549aad67c74b3f51f4817c9e/docs/.figs/AvsB-1.png
--------------------------------------------------------------------------------
/docs/.figs/SPP1_CD44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StatBiomed/SpatialDM/bfd2c3739abf5432549aad67c74b3f51f4817c9e/docs/.figs/SPP1_CD44.png
--------------------------------------------------------------------------------
/docs/.figs/global_plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StatBiomed/SpatialDM/bfd2c3739abf5432549aad67c74b3f51f4817c9e/docs/.figs/global_plot.png
--------------------------------------------------------------------------------
/docs/.figs/runtime_aug16-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StatBiomed/SpatialDM/bfd2c3739abf5432549aad67c74b3f51f4817c9e/docs/.figs/runtime_aug16-1.png
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = _build
9 |
10 | # User-friendly check for sphinx-build
11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
13 | endif
14 |
15 | # Internal variables.
16 | PAPEROPT_a4 = -D latex_paper_size=a4
17 | PAPEROPT_letter = -D latex_paper_size=letter
18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
19 | # the i18n builder cannot share the environment and doctrees with the others
20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
21 |
22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
23 |
24 | help:
25 | @echo "Please use \`make ' where is one of"
26 | @echo " html to make standalone HTML files"
27 | @echo " dirhtml to make HTML files named index.html in directories"
28 | @echo " singlehtml to make a single large HTML file"
29 | @echo " pickle to make pickle files"
30 | @echo " json to make JSON files"
31 | @echo " htmlhelp to make HTML files and a HTML help project"
32 | @echo " qthelp to make HTML files and a qthelp project"
33 | @echo " devhelp to make HTML files and a Devhelp project"
34 | @echo " epub to make an epub"
35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
36 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
38 | @echo " text to make text files"
39 | @echo " man to make manual pages"
40 | @echo " texinfo to make Texinfo files"
41 | @echo " info to make Texinfo files and run them through makeinfo"
42 | @echo " gettext to make PO message catalogs"
43 | @echo " changes to make an overview of all changed/added/deprecated items"
44 | @echo " xml to make Docutils-native XML files"
45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes"
46 | @echo " linkcheck to check all external links for integrity"
47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
48 |
49 | clean:
50 | rm -rf $(BUILDDIR)/*
51 |
52 | html:
53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
54 | @echo
55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
56 |
57 | dirhtml:
58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
59 | @echo
60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
61 |
62 | singlehtml:
63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
64 | @echo
65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
66 |
67 | pickle:
68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
69 | @echo
70 | @echo "Build finished; now you can process the pickle files."
71 |
72 | json:
73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
74 | @echo
75 | @echo "Build finished; now you can process the JSON files."
76 |
77 | htmlhelp:
78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
79 | @echo
80 | @echo "Build finished; now you can run HTML Help Workshop with the" \
81 | ".hhp project file in $(BUILDDIR)/htmlhelp."
82 |
83 | qthelp:
84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
85 | @echo
86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/mytest.qhcp"
89 | @echo "To view the help file:"
90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/mytest.qhc"
91 |
92 | devhelp:
93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
94 | @echo
95 | @echo "Build finished."
96 | @echo "To view the help file:"
97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/mytest"
98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/mytest"
99 | @echo "# devhelp"
100 |
101 | epub:
102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
103 | @echo
104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
105 |
106 | latex:
107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
108 | @echo
109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
111 | "(use \`make latexpdf' here to do that automatically)."
112 |
113 | latexpdf:
114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
115 | @echo "Running LaTeX files through pdflatex..."
116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
118 |
119 | latexpdfja:
120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
121 | @echo "Running LaTeX files through platex and dvipdfmx..."
122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
124 |
125 | text:
126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
127 | @echo
128 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
129 |
130 | man:
131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
132 | @echo
133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
134 |
135 | texinfo:
136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
137 | @echo
138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
139 | @echo "Run \`make' in that directory to run these through makeinfo" \
140 | "(use \`make info' here to do that automatically)."
141 |
142 | info:
143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
144 | @echo "Running Texinfo files through makeinfo..."
145 | make -C $(BUILDDIR)/texinfo info
146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
147 |
148 | gettext:
149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
150 | @echo
151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
152 |
153 | changes:
154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
155 | @echo
156 | @echo "The overview file is in $(BUILDDIR)/changes."
157 |
158 | linkcheck:
159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
160 | @echo
161 | @echo "Link check complete; look for any errors in the above output " \
162 | "or in $(BUILDDIR)/linkcheck/output.txt."
163 |
164 | doctest:
165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
166 | @echo "Testing of doctests in the sources finished, look at the " \
167 | "results in $(BUILDDIR)/doctest/output.txt."
168 |
169 | xml:
170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
171 | @echo
172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
173 |
174 | pseudoxml:
175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
176 | @echo
177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
178 |
--------------------------------------------------------------------------------
/docs/api.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: spatialdm
2 |
3 | API
4 | ===
5 |
6 | Import SpatialDM as::
7 | import spatialdm as sdm
8 |
9 | Datasets
10 | --------
11 | The `spatialdm.datasets` module provides functions for loading and accessing spatial transcriptomics datasets. The following datasets are currently available:
12 |
13 | * `dataset.melanoma()`: Sample 1 rep 2 human melanoma slide from Thrane's melanoma dataset.
14 | * `dataset.SVZ()`: Mouse sub-ventricular zone (SVZ) from Eng's seqfish+ dataset.
15 | * `dataset.A1()`: Adult colon with colorectal cancer or IBD, pcw: Adult.
16 | * `dataset.A2()`: Adult colon with colorectal cancer or IBD, pcw: Adult.
17 | * `dataset.A3()`: Fetal colon, pcw: 12PCW.
18 | * `dataset.A4()`: Fetal colon, pcw: 19PCW.
19 | * `dataset.A6()`: Fetal small intestine, pcw: 12PCW.
20 | * `dataset.A7()`: Fetal small intestine, pcw: 12PCW.
21 | * `dataset.A8()`: Fetal small intestine, pcw: 12PCW.
22 | * `dataset.A9()`: Fetal small intestine, pcw: 12PCW.
23 |
24 | Usage
25 | -----
26 |
27 | To use the `spatialdm.datasets` module, simply import it as follows:
28 |
29 | .. code-block:: python
30 |
31 | from spatialdm.datasets import dataset
32 |
33 | Then, you can load a dataset using the corresponding function. For example, to load the melanoma dataset:
34 |
35 | .. code-block:: python
36 |
37 | adata = dataset.melanoma()
38 |
39 | This will return an `anndata` object containing the expression data for the melanoma dataset in `.X`, the cell type decomposition values in `.obs`, and the spatial coordinates in `.obsm['spatial']`.
40 |
41 | .. autosummary::
42 | :toctree: _autosummary
43 | weight_matrix()
44 | extract_lr()
45 | datasets.dataset.A1()
46 | datasets.dataset.A11()
47 | datasets.dataset.A2()
48 |
--------------------------------------------------------------------------------
/docs/autosummary/base.rst:
--------------------------------------------------------------------------------
1 | :github_url: {{ fullname | modurl }}
2 |
3 | {{ fullname | api_image }}
4 |
5 | {% extends "!autosummary/base.rst" %}
6 |
7 | .. http://www.sphinx-doc.org/en/stable/ext/autosummary.html#customizing-templates
8 |
--------------------------------------------------------------------------------
/docs/autosummary/class.rst:
--------------------------------------------------------------------------------
1 | :github_url: {{ fullname | modurl }}
2 |
3 | {{ fullname | escape | underline}}
4 |
5 | .. currentmodule:: {{ module }}
6 |
7 | .. add toctree option to make autodoc generate the pages
8 |
9 | .. autoclass:: {{ objname }}
10 |
11 | {% block attributes %}
12 | {% if attributes %}
13 | .. rubric:: Attributes
14 |
15 | .. autosummary::
16 | :toctree: .
17 | {% for item in attributes %}
18 | ~{{ fullname }}.{{ item }}
19 | {%- endfor %}
20 | {% endif %}
21 | {% endblock %}
22 |
23 | {% block methods %}
24 | {% if methods %}
25 | .. rubric:: Methods
26 |
27 | .. autosummary::
28 | :toctree: .
29 | {% for item in methods %}
30 | {%- if item != '__init__' %}
31 | ~{{ fullname }}.{{ item }}
32 | {%- endif -%}
33 | {%- endfor %}
34 | {% endif %}
35 | {% endblock %}
36 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # mytest documentation build configuration file, created by
4 | # sphinx-quickstart on Sat Dec 19 19:34:52 2015.
5 | #
6 | # This file is execfile()d with the current directory set to its
7 | # containing dir.
8 | #
9 | # Note that not all possible configuration values are present in this
10 | # autogenerated file.
11 | #
12 | # All configuration values have a default; values that are commented out
13 | # serve to show the default.
14 |
15 | import sys
16 | import os
17 | from datetime import datetime
18 |
19 | # If extensions (or modules to document with autodoc) are in another directory,
20 | # add these directories to sys.path here. If the directory is relative to the
21 | # documentation root, use os.path.abspath to make it absolute, like shown here.
22 | #sys.path.insert(0, os.path.abspath('.'))
23 |
24 | from pathlib import Path
25 | from sphinx.application import Sphinx
26 | from sphinx.ext import autosummary
27 |
28 | HERE = Path(__file__).parent
29 | sys.path.insert(0, f"{HERE.parent.parent}")
30 | sys.path.insert(0, os.path.abspath("_ext"))
31 |
32 | # -- Retrieve notebooks ------------------------------------------------
33 |
34 | from urllib.request import urlretrieve
35 |
36 | notebooks_url = "https://github.com/leeyoyohku/SpatialDM/raw/main/tutorial/"
37 | notebooks = [
38 | "melanoma.ipynb",
39 | "differential_test_intestine.ipynb"
40 | ]
41 | for nb in notebooks:
42 | try:
43 | urlretrieve(notebooks_url + nb, nb)
44 | except:
45 | raise ValueError(f'{nb} cannot be retrieved.')
46 |
47 |
48 | # -- General configuration ------------------------------------------------
49 |
50 | # If your documentation needs a minimal Sphinx version, state it here.
51 | #needs_sphinx = '1.0'
52 |
53 | # Add any Sphinx extension module names here, as strings. They can be
54 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
55 | # ones.
56 |
57 | needs_sphinx = "1.7"
58 |
59 | extensions = [
60 | "sphinx.ext.autodoc",
61 | "sphinx.ext.doctest",
62 | "sphinx.ext.coverage",
63 | "sphinx.ext.mathjax",
64 | "sphinx.ext.autosummary",
65 | "sphinx.ext.napoleon",
66 | "sphinx.ext.intersphinx",
67 | "sphinx.ext.githubpages",
68 | "sphinx_autodoc_typehints",
69 | "nbsphinx",
70 | # "edit_on_github",
71 | ]
72 |
73 | autosummary_generate = True
74 | # Add any paths that contain templates here, relative to this directory.
75 | templates_path = ['_templates']
76 |
77 | # The suffix of source filenames.
78 | source_suffix = ['.rst']
79 | ## don't add '.ipynb' for nbsphinx>=0.8.7
80 |
81 | # The encoding of source files.
82 | #source_encoding = 'utf-8-sig'
83 |
84 | # The master toctree document.
85 | master_doc = 'index'
86 |
87 | # General information about the project.
88 | project = "SpatialDM"
89 | author = "Zhuoxuan Li"
90 | title = "Spatial Direct Messaging Detected by Bivariate Moran"
91 | copyright = f"{datetime.now():%Y}, {author}"
92 |
93 | # Disable pdf and epub generation
94 | enable_pdf_build = False
95 | enable_epub_build = False
96 |
97 | # The version info for the project you're documenting, acts as replacement for
98 | # |version| and |release|, also used in various other places throughout the
99 | # built documents.
100 | #
101 | # The short X.Y version.
102 | import spatialdm
103 | version = spatialdm.__version__ #'0.0.2' #
104 | # The full version, including alpha/beta/rc tags.
105 | release = version
106 |
107 | def setup(app):
108 | """TODO."""
109 | app.add_css_file("custom.css")
110 |
111 | def process_generate_options(app: Sphinx):
112 | """TODO."""
113 | genfiles = app.config.autosummary_generate
114 |
115 | if genfiles and not hasattr(genfiles, "__len__"):
116 | env = app.builder.env
117 | genfiles = [
118 | env.doc2path(x, base=None)
119 | for x in env.found_docs
120 | if Path(env.doc2path(x)).is_file()
121 | ]
122 | if not genfiles:
123 | return
124 |
125 | from sphinx.ext.autosummary.generate import generate_autosummary_docs
126 |
127 | ext = app.config.source_suffix
128 | genfiles = [
129 | genfile + (not genfile.endswith(tuple(ext)) and ext[0] or "")
130 | for genfile in genfiles
131 | ]
132 |
133 | suffix = autosummary.get_rst_suffix(app)
134 | if suffix is None:
135 | return
136 |
137 | generate_autosummary_docs(
138 | genfiles,
139 | builder=app.builder,
140 | warn=logger.warning,
141 | info=logger.info,
142 | suffix=suffix,
143 | base_path=app.srcdir,
144 | imported_members=True,
145 | app=app,
146 | )
147 |
148 |
149 | autosummary.process_generate_options = process_generate_options
150 |
151 | # The language for content autogenerated by Sphinx. Refer to documentation
152 | # for a list of supported languages.
153 | #language = None
154 |
155 | # There are two options for replacing |today|: either, you set today to some
156 | # non-false value, then it is used:
157 | #today = ''
158 | # Else, today_fmt is used as the format for a strftime call.
159 | #today_fmt = '%B %d, %Y'
160 |
161 | # List of patterns, relative to source directory, that match files and
162 | # directories to ignore when looking for source files.
163 | exclude_patterns = ['_build']
164 |
165 | # The reST default role (used for this markup: `text`) to use for all
166 | # documents.
167 | #default_role = None
168 |
169 | # If true, '()' will be appended to :func: etc. cross-reference text.
170 | #add_function_parentheses = True
171 |
172 | # If true, the current module name will be prepended to all description
173 | # unit titles (such as .. function::).
174 | #add_module_names = True
175 |
176 | # If true, sectionauthor and moduleauthor directives will be shown in the
177 | # output. They are ignored by default.
178 | #show_authors = False
179 |
180 | # The name of the Pygments (syntax highlighting) style to use.
181 | pygments_style = 'sphinx'
182 |
183 | # A list of ignored prefixes for module index sorting.
184 | #modindex_common_prefix = []
185 |
186 | # If true, keep warnings as "system message" paragraphs in the built documents.
187 | #keep_warnings = False
188 |
189 |
190 | # -- Options for HTML output ----------------------------------------------
191 |
192 | # The theme to use for HTML and HTML Help pages. See the documentation for
193 | # a list of builtin themes.
194 | # html_theme = 'default'
195 | # html_theme = "bizstyle"
196 | # html_theme = "nature"
197 | html_theme = 'sphinx_rtd_theme'
198 | github_repo = 'SpatialDM'
199 | github_nb_repo = 'SpatialDM'
200 | html_theme_options = dict(navigation_depth=1, titles_only=True)
201 |
202 |
203 | # import sphinx_bootstrap_theme
204 | # html_theme = 'bootstrap'
205 | # html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
206 |
207 | # Theme options are theme-specific and customize the look and feel of a theme
208 | # further. For a list of options available for each theme, see the
209 | # documentation.
210 | #html_theme_options = {}
211 |
212 |
213 | # Add any paths that contain custom themes here, relative to this directory.
214 | #html_theme_path = []
215 |
216 | # The name for this set of Sphinx documents. If None, it defaults to
217 | # " v documentation".
218 | #html_title = None
219 |
220 | # A shorter title for the navigation bar. Default is the same as html_title.
221 | #html_short_title = None
222 |
223 | # The name of an image file (relative to this directory) to place at the top
224 | # of the sidebar.
225 | #html_logo = None
226 |
227 | # The name of an image file (within the static path) to use as favicon of the
228 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
229 | # pixels large.
230 | #html_favicon = None
231 |
232 | # Add any paths that contain custom static files (such as style sheets) here,
233 | # relative to this directory. They are copied after the builtin static files,
234 | # so a file named "default.css" will overwrite the builtin "default.css".
235 | html_static_path = ['_static']
236 |
237 | # Add any extra paths that contain custom files (such as robots.txt or
238 | # .htaccess) here, relative to this directory. These files are copied
239 | # directly to the root of the documentation.
240 | #html_extra_path = []
241 |
242 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
243 | # using the given strftime format.
244 | #html_last_updated_fmt = '%b %d, %Y'
245 |
246 | # If true, SmartyPants will be used to convert quotes and dashes to
247 | # typographically correct entities.
248 | #html_use_smartypants = True
249 |
250 | # Custom sidebar templates, maps document names to template names.
251 | # html_sidebars = {
252 | # '**': ['install.html','usage.html', 'tutorial.html', 'api.html', 'faq.html', 'release.html']}
253 |
254 | # Additional templates that should be rendered to pages, maps page names to
255 | # template names.
256 | #html_additional_pages = {}
257 |
258 | # If false, no module index is generated.
259 | #html_domain_indices = True
260 |
261 | # If false, no index is generated.
262 | #html_use_index = True
263 |
264 | # If true, the index is split into individual pages for each letter.
265 | #html_split_index = False
266 |
267 | # If true, links to the reST sources are added to the pages.
268 | #html_show_sourcelink = True
269 |
270 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
271 | #html_show_sphinx = True
272 |
273 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
274 | #html_show_copyright = True
275 |
276 | # If true, an OpenSearch description file will be output, and all pages will
277 | # contain a tag referring to it. The value of this option must be the
278 | # base URL from which the finished HTML is served.
279 | #html_use_opensearch = ''
280 |
281 | # This is the file name suffix for HTML files (e.g. ".xhtml").
282 | #html_file_suffix = None
283 |
284 | # Output file base name for HTML help builder.
285 | htmlhelp_basename = 'SpatialDM'
286 |
287 |
288 | # -- Options for LaTeX output ---------------------------------------------
289 |
290 | latex_elements = {
291 | # The paper size ('letterpaper' or 'a4paper').
292 | #'papersize': 'letterpaper',
293 |
294 | # The font size ('10pt', '11pt' or '12pt').
295 | #'pointsize': '10pt',
296 |
297 | # Additional stuff for the LaTeX preamble.
298 | #'preamble': '',
299 | }
300 |
301 | # Grouping the document tree into LaTeX files. List of tuples
302 | # (source start file, target name, title,
303 | # author, documentclass [howto, manual, or own class]).
304 | latex_documents = [
305 | ('index', 'SpatialDM.tex', u'SpatialDM Documentation',
306 | u'Zhuoxuan Li', 'manual'),
307 | ]
308 |
309 | # The name of an image file (relative to this directory) to place at the top of
310 | # the title page.
311 | #latex_logo = None
312 |
313 | # For "manual" documents, if this is true, then toplevel headings are parts,
314 | # not chapters.
315 | #latex_use_parts = False
316 |
317 | # If true, show page references after internal links.
318 | #latex_show_pagerefs = False
319 |
320 | # If true, show URL addresses after external links.
321 | #latex_show_urls = False
322 |
323 | # Documents to append as an appendix to all manuals.
324 | #latex_appendices = []
325 |
326 | # If false, no module index is generated.
327 | #latex_domain_indices = True
328 |
329 |
330 | # -- Options for manual page output ---------------------------------------
331 |
332 | # One entry per manual page. List of tuples
333 | # (source start file, name, description, authors, manual section).
334 | man_pages = [
335 | ('index', 'SpatialDM', u'SpatialDM Documentation',
336 | [u'Zhuoxuan Li'], 1)
337 | ]
338 |
339 | # If true, show URL addresses after external links.
340 | #man_show_urls = False
341 |
342 |
343 | # -- Options for Texinfo output -------------------------------------------
344 |
345 | # Grouping the document tree into Texinfo files. List of tuples
346 | # (source start file, target name, title, author,
347 | # dir menu entry, description, category)
348 | texinfo_documents = [
349 | ('index', 'SpatialDM', u'SpatialDM Documentation',
350 | u'Zhuoxuan Li', 'SpatialDM', 'One line description of project.',
351 | 'Miscellaneous'),
352 | ]
353 |
354 | # Documents to append as an appendix to all manuals.
355 | #texinfo_appendices = []
356 |
357 | # If false, no module index is generated.
358 | #texinfo_domain_indices = True
359 |
360 | # How to display URL addresses: 'footnote', 'no', or 'inline'.
361 | #texinfo_show_urls = 'footnote'
362 |
363 | # If true, do not generate a @detailmenu in the "Top" node's menu.
364 | #texinfo_no_detailmenu = False
365 |
366 |
--------------------------------------------------------------------------------
/docs/custom.css:
--------------------------------------------------------------------------------
1 | /* ReadTheDocs theme colors */
2 |
3 | .wy-nav-top {
4 | background-color: #404040;
5 | }
6 | .wy-nav-content {
7 | max-width: 950px;
8 | }
9 | .wy-side-nav-search {
10 | background-color: transparent;
11 | }
12 | .wy-side-nav-search input[type="text"] {
13 | border-width: 0;
14 | }
15 |
16 | /* Custom classes */
17 | .small {
18 | font-size: 40%;
19 | }
20 | .smaller,
21 | .pr {
22 | font-size: 70%;
23 | }
24 |
25 | /* Custom classes with bootstrap buttons */
26 |
27 | .tutorial,
28 | .tutorial:visited,
29 | .tutorial:hover {
30 | /* text-decoration: underline; */
31 | font-weight: bold;
32 | padding: 2px 5px;
33 | white-space: nowrap;
34 | max-width: 100%;
35 | background: #ef3270;
36 | border: solid 1px #ef3270;
37 | border-radius: 0.25rem;
38 | font-size: 75%;
39 | /* font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace; */
40 | color: #404040;
41 | overflow-x: auto;
42 | box-sizing: border-box;
43 | }
44 |
45 | /* Formatting of RTD markup: rubrics and sidebars and admonitions */
46 |
47 | /* rubric */
48 | .rst-content p.rubric {
49 | margin-bottom: 6px;
50 | font-weight: normal;
51 | }
52 | .rst-content p.rubric::after {
53 | content: ":";
54 | }
55 |
56 | /* sidebar */
57 | .rst-content .sidebar {
58 | /* margin: 0px 0px 0px 12px; */
59 | padding-bottom: 0px;
60 | }
61 | .rst-content .sidebar p {
62 | margin-bottom: 12px;
63 | }
64 | .rst-content .sidebar p,
65 | .rst-content .sidebar ul,
66 | .rst-content .sidebar dl {
67 | font-size: 13px;
68 | }
69 |
70 | /* less space after bullet lists in admonitions like warnings and notes */
71 | .rst-content .section .admonition ul {
72 | margin-bottom: 6px;
73 | }
74 |
75 | /* Code: literals and links */
76 |
77 | .rst-content tt.literal,
78 | .rst-content code.literal {
79 | color: #404040;
80 | }
81 | /* slim font weight for non-link code */
82 | .rst-content tt:not(.xref),
83 | .rst-content code:not(.xref),
84 | .rst-content *:not(a) > tt.xref,
85 | .rst-content *:not(a) > code.xref,
86 | .rst-content a > tt.xref,
87 | .rst-content a > code.xref,
88 | .rst-content dl:not(.docutils) a > tt.xref,
89 |
90 |
91 | /* Just one box for annotation code for a less noisy look */
92 |
93 | .rst-content .annotation {
94 | padding: 2px 5px;
95 | background-color: white;
96 | border: 1px solid #e1e4e5;
97 | }
98 | .rst-content .annotation tt,
99 | .rst-content .annotation code {
100 | padding: 0 0;
101 | background-color: transparent;
102 | border: 0 solid transparent;
103 | }
104 |
105 | /* Parameter lists */
106 |
107 | .rst-content dl:not(.docutils) dl dt {
108 | /* mimick numpydoc’s blockquote style */
109 | font-weight: normal;
110 | background: none transparent;
111 | border-left: none;
112 | margin: 0 0 12px;
113 | padding: 3px 0 0;
114 | font-size: 100%;
115 | }
116 |
117 | .rst-content dl:not(.docutils) dl dt code {
118 | font-size: 100%;
119 | font-weight: normal;
120 | background: none transparent;
121 | border: none;
122 | padding: 0 2px;
123 | }
124 |
125 | .rst-content dl:not(.docutils) dl dt a.reference > code {
126 | text-decoration: underline;
127 | }
128 |
129 | /* Mimick rubric style used for other headings */
130 | .rst-content dl:not(.docutils) dl > dt {
131 | font-weight: bold;
132 | background: none transparent;
133 | border-left: none;
134 | margin: 0 0 12px;
135 | padding: 3px 0 0;
136 | font-size: 100%;
137 | }
138 | /* Parameters contain parts and don’t need bold font */
139 | .rst-content dl.field-list dl > dt {
140 | font-weight: unset;
141 | }
142 | /* Add colon between return tuple element name and type */
143 | .rst-content dl:not(.docutils) dl > dt .classifier::before {
144 | content: " : ";
145 | }
146 |
147 | /* Function headers */
148 |
149 | .rst-content dl:not(.docutils) dt {
150 | background: #edf0f2;
151 | color: #404040;
152 | border-top: solid 3px #343131;
153 | }
154 |
155 | .rst-content .section ul li p:last-child {
156 | margin-bottom: 0;
157 | margin-top: 0;
158 | }
159 |
160 | /* Adjust width of navigation bar on mobile */
161 | @media screen and (max-width: 768px) {
162 | .header-bar {
163 | display: none;
164 | }
165 |
166 | .wy-nav-content-wrap {
167 | margin-left: 0px;
168 | }
169 |
170 | .wy-nav-side {
171 | width: 300px;
172 | }
173 |
174 | .wy-nav-side.shift {
175 | max-width: 320px;
176 | }
177 |
178 | /* Fix sidebar adjust */
179 | .rst-versions {
180 | width: 40%;
181 | max-width: 320px;
182 | }
183 | }
184 |
185 | /* Handle landscape */
186 | @media screen and (min-width: 377px) {
187 | .wy-nav-content-wrap.shift {
188 | left: 320px;
189 | }
190 | }
191 |
192 | /* make height responsive for notebook figures */
193 | .rst-content .image-reference img {
194 | max-width: 100% !important;
195 | height: auto !important;
196 | }
197 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | |PyPI| |Docs| |Build Status|
2 |
3 | .. |PyPI| image:: https://img.shields.io/pypi/v/SpatialDM.svg
4 | :target: https://pypi.org/project/SpatialDM/
5 | .. |Docs| image:: https://readthedocs.org/projects/spatialdm/badge/?version=latest
6 | :target: https://SpatialDM.readthedocs.io
7 | .. |Build Status| image:: https://travis-ci.org/leeyoyohku/SpatialDM.svg?branch=main
8 | :target: https://travis-ci.org/leeyoyohku/SpatialDM
9 |
10 | ====
11 | Home
12 | ====
13 |
14 |
15 | About SpatialDM
16 | ===============
17 |
18 | SpatialDM (Spatial Direct Messaging, or Spatial co-expressed ligand and receptor Detected by Moran's bivariant extension) is a statistical model and toolbox to identify the spatial co-expression (i.e., spatial association) between a pair of ligand and receptor.
19 |
20 | Uniquely, SpatialDM can distinguish co-expressed ligand and receptor pairs from spatially separating pairs, and identify the spots of interaction.
21 |
22 | .. image:: https://github.com/StatBiomed/SpatialDM/blob/main/docs/.figs/AvsB-1.png?raw=true
23 | :width: 900px
24 | :align: center
25 |
26 | With the analytical testing method, SpatialDM is scalable to 1 million spots within 12 min with only one core.
27 |
28 | .. image:: https://github.com/StatBiomed/SpatialDM/blob/main/docs/.figs/runtime_aug16-1.png?raw=true
29 | :width: 600px
30 | :align: center
31 |
32 | SpatialDM comprises two main steps: \
33 | 1) global selection with ``spatialdm_global`` to identify significantly interacting LR pairs; \
34 | 2) local selection with ``spatialdm_local`` to identify local spots for each interaction.
35 |
36 | Please refer to our tutorials for details:
37 |
38 | * `Permutation-based SpatialDM (Recommended for small datasets, <10k spots)`_.
39 |
40 | * `Differential analyses of whole interactome among varying conditions`_.
41 |
42 | .. _Permutation-based SpatialDM (Recommended for small datasets, <10k spots): melanoma.ipynb
43 |
44 | .. _Differential analyses of whole interactome among varying conditions: differential_test_intestine.ipynb
45 |
46 |
47 |
48 | References
49 | ==========
50 | SpatialDM manuscript with more details is available on bioRxiv_ now and is currently under review.
51 |
52 | .. _bioRxiv: https://www.biorxiv.org/content/10.1101/2022.08.19.504616v1/
53 |
54 |
55 |
56 | .. toctree::
57 | :caption: Main
58 | :maxdepth: 1
59 | :hidden:
60 |
61 | index
62 | install
63 | quick_start
64 | api
65 | release
66 |
67 | .. toctree::
68 | :caption: Examples
69 | :maxdepth: 1
70 | :hidden:
71 |
72 | melanoma
73 | differential_test_intestine
74 |
--------------------------------------------------------------------------------
/docs/install.rst:
--------------------------------------------------------------------------------
1 | Installation
2 | ============
3 |
4 | SpatialDM is available through `PyPI `_.
5 | To install, type the following command line and add ``-U`` for updates:
6 |
7 | .. code-block:: bash
8 |
9 | pip install -U SpatialDM
10 |
11 | Alternatively, you can install from this GitHub repository for latest (often
12 | development) version by the following command line:
13 |
14 | .. code-block:: bash
15 |
16 | pip install -U git+https://github.com/leeyoyohku/SpatialDM
17 |
18 | Installation time: < 1 min
--------------------------------------------------------------------------------
/docs/release.rst:
--------------------------------------------------------------------------------
1 | Release History
2 | ===============
3 |
4 | TODO
5 | ----
6 | - support cache for downloaded h5ad data
7 | - rename local_permI to local_permI_L (also global)
8 | - tentatively: make new adata with LR genes only (if raw exist, other make raw)
9 |
10 | Version 0.1.0 (15/04/2023)
11 | -------------------
12 | - Minor fix with supporting sparse matrix for `adata.X`
13 | - Disabled the output of local permutaiton data in notebook
14 | - More efficient KNN graph construction, with obsp elements into sparse matrix
15 | - Added LR data into package
16 | - Minor fix concat_obj() function
17 | - Minor updates on notebooks: SpatialDE limited one CPU; diff-test only z-score
18 | - Suggest adding `adata.obsm['celltypes']` dataframe to replace `adata.obs`
19 |
20 | Version 0.0.8 (14/03/2023)
21 | --------------------------
22 |
23 | - SpatialDM wrapped into AnnData object, fixed typos
24 |
25 | Version 0.0.1 (11/08/2022)
26 | --------------------------
27 |
28 | - Alpha version of SpatialDM released
29 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | # Just until rtd.org understands pyproject.toml
2 | spatialdm
3 | setuptools
4 | setuptools_scm
5 | typing_extensions
6 | importlib_metadata
7 | sphinx_rtd_theme>=0.3
8 | sphinx_autodoc_typehints
9 |
10 | # converting notebooks to html
11 | ipykernel
12 | sphinx>=1.7
13 | nbsphinx>=0.8.7
14 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # Single-cell sequencing analysis
2 | anndata>=0.6
3 | scanpy>=1.5
4 | SpatialDE
5 |
6 | # Data analysis
7 | numpy>=1.9.0
8 | scipy>=1.4.0
9 | statsmodels>=0.11
10 | pandas>=0.23.0
11 | h5py>=2.9.0
12 |
13 | # Plotting
14 | matplotlib>=3.1.2
15 | holoviews
16 | seaborn
17 | selenium
18 |
19 | # Machine learning
20 | scikit-learn>=0.23
21 | hilearn
22 |
23 | # Others
24 | threadpoolctl
25 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | """
2 | SpatialDM: Spatial co-expression Detected by bivariate Moran
3 | SpatialDM: Spatial ligand-receptor co-expression for Direct Messaging
4 | See: https://github.com/leeyoyohku/SpatialDM
5 | """
6 |
7 | # Always prefer setuptools over distutils
8 | from setuptools import setup, find_packages
9 | # To use a consistent encoding
10 | from codecs import open
11 | from os import path
12 | from pathlib import Path
13 |
14 | here = path.abspath(path.dirname(__file__))
15 |
16 | # Set __version__ for the project.
17 | exec(open("./spatialdm/version.py").read())
18 |
19 | # Get the long description from the relevant file
20 | long_description=Path("README.rst").read_text("utf-8")
21 |
22 | setup(
23 | name='SpatialDM',
24 |
25 | # Versions should comply with PEP440. For a discussion on single-sourcing
26 | # the version across setup.py and the project code, see
27 | # https://packaging.python.org/en/latest/single_source_version.html
28 | version=__version__,
29 |
30 | description='SpatialDM: Spatial co-expression Detected by bivariate Moran',
31 | long_description=long_description,
32 |
33 | # The project's main homepage.
34 | url='https://github.com/leeyoyohku/SpatialDM',
35 |
36 | # Author details
37 | author=['Zhouxuan Li', 'Tianjie Wang', 'Yuanhua Huang'],
38 | author_email='leeyoyo@connect.hku.hk',
39 |
40 | # Choose your license
41 | license='Apache-2.0',
42 |
43 | # What does your project relate to?
44 | keywords=[
45 | 'Spatial transcriptomics',
46 | 'Spatial association',
47 | 'Ligand-recptor interaction'
48 | ],
49 |
50 | # You can just specify the packages manually here if your project is
51 | # simple. Or you can use find_packages().
52 | packages=find_packages(),
53 |
54 | # entry_points={
55 | # 'console_scripts': [
56 | # ],
57 | # },
58 |
59 | # List run-time dependencies here. These will be installed by pip when
60 | # your project is installed. For an analysis of "install_requires" vs pip's
61 | # requirements files see:
62 | # https://packaging.python.org/en/latest/requirements.html
63 |
64 | # install_requires=reqs,
65 | install_requires=[
66 | l.strip() for l in Path('requirements.txt').read_text('utf-8').splitlines()
67 | ],
68 |
69 | include_package_data=True,
70 | package_data={'': ['datasets/*.csv', 'datasets/*.csv.gz']},
71 |
72 | extras_require={
73 | 'docs': [
74 | #'sphinx == 1.8.3',
75 | 'sphinx_bootstrap_theme']},
76 |
77 | py_modules = ['SpatialDM']
78 |
79 | # buid the distribution: python setup.py sdist
80 | # upload to pypi: twine upload dist/...
81 | )
82 |
--------------------------------------------------------------------------------
/spatialdm/__init__.py:
--------------------------------------------------------------------------------
1 | # add shortcuts to the package's first level
2 |
3 | from . import datasets
4 | from .main import *
5 | from .version import __version__
6 |
--------------------------------------------------------------------------------
/spatialdm/datasets/LR_data/human-complex_input_CellChatDB.csv:
--------------------------------------------------------------------------------
1 | "","subunit_1","subunit_2","subunit_3","subunit_4"
2 | "Activin AB","INHBA","INHBB","",""
3 | "Inhibin A","INHA","INHBA","",""
4 | "Inhibin B","INHA","INHBB","",""
5 | "IL12AB","IL12A","IL12B","",""
6 | "IL23 complex","IL12B","IL23A","",""
7 | "IL27 complex","IL27","EBI3","",""
8 | "IL17AF","IL17A","IL17F","",""
9 | "LTa1b2","LTA","LTB","",""
10 | "GP complex","GP1BA","GP1BB","GP5","GP9"
11 | "ACVR1_ACVR2A","ACVR1","ACVR2A","",""
12 | "ACVR1_ACVR2B","ACVR1","ACVR2B","",""
13 | "ACVR1_BMPR2","ACVR1","BMPR2","",""
14 | "ACVR1_TGFbR","ACVR1","TGFBR1","TGFBR2",""
15 | "ACVR1B_ACVR2A","ACVR1B","ACVR2A","",""
16 | "ACVR1B_ACVR2A_CFC1","ACVR1B","ACVR2A","CFC1",""
17 | "ACVR1B_ACVR2B","ACVR1B","ACVR2B","",""
18 | "ACVR1B_ACVR2B_CFC1","ACVR1B","ACVR2B","CFC1",""
19 | "ACVR1B_BMPR2","ACVR1B","BMPR2","",""
20 | "ACVR1B_TGFbR2","ACVR1B","TGFBR2","",""
21 | "ACVR1C_ACVR2A","ACVR1C","ACVR2A","",""
22 | "ACVR1C_ACVR2A_CFC1","ACVR1C","ACVR2A","CFC1",""
23 | "ACVR1C_ACVR2B","ACVR1C","ACVR2B","",""
24 | "ACVR1C_ACVR2B_CFC1","ACVR1C","ACVR2B","CFC1",""
25 | "ACVR1C_TGFbR2","ACVR1C","TGFBR2","",""
26 | "ACVRL1_ACVR2A","ACVRL1","ACVR2A","",""
27 | "ACVRL1_BMPR2","ACVRL1","BMPR2","",""
28 | "AMHR2_ACVR1","AMHR2","ACVR1","",""
29 | "AMHR2_BMPR1A","AMHR2","BMPR1A","",""
30 | "BMPR1A_ACVR2A","BMPR1A","ACVR2A","",""
31 | "BMPR1A_ACVR2B","BMPR1A","ACVR2B","",""
32 | "BMPR1A_BMPR2","BMPR1A","BMPR2","",""
33 | "BMPR1B_ACVR2A","BMPR1B","ACVR2A","",""
34 | "BMPR1B_ACVR2B","BMPR1B","ACVR2B","",""
35 | "BMPR1B_BMPR2","BMPR1B","BMPR2","",""
36 | "CD74_CD44","CD74","CD44","",""
37 | "CD74_CXCR2","CD74","CXCR2","",""
38 | "CD74_CXCR4","CD74","CXCR4","",""
39 | "CD8 receptor","CD8A","CD8B","",""
40 | "CNTFR_LIFR","CNTFR","LIFR","IL6ST",""
41 | "CNTN1_CNTNAP1","CNTN1","CNTNAP1","",""
42 | "CNTN2_CNTNAP2","CNTN2","CNTNAP2","",""
43 | "CSF2RA_CSF2RB","CSF2RA","CSF2RB","",""
44 | "EGFR_ERBB2","EGFR","ERBB2","",""
45 | "ERBB2_ERBB3","ERBB2","ERBB3","",""
46 | "ERBB2_ERBB4","ERBB2","ERBB4","",""
47 | "FLT1_KDR","FLT1","KDR","",""
48 | "FLT4_KDR","FLT4","KDR","",""
49 | "FPR2_LXA4","FPR2","FPR3","",""
50 | "FZD1_LRP5","FZD1","LRP5","",""
51 | "FZD1_LRP6","FZD1","LRP6","",""
52 | "FZD10_LRP5","FZD10","LRP5","",""
53 | "FZD10_LRP6","FZD10","LRP6","",""
54 | "FZD2_LRP5","FZD2","LRP5","",""
55 | "FZD2_LRP6","FZD2","LRP6","",""
56 | "FZD3_LRP5","FZD3","LRP5","",""
57 | "FZD3_LRP6","FZD3","LRP6","",""
58 | "FZD4_LRP5","FZD4","LRP5","",""
59 | "FZD4_LRP6","FZD4","LRP6","",""
60 | "FZD5_LRP5","FZD5","LRP5","",""
61 | "FZD5_LRP6","FZD5","LRP6","",""
62 | "FZD6_LRP5","FZD6","LRP5","",""
63 | "FZD6_LRP6","FZD6","LRP6","",""
64 | "FZD7_LRP5","FZD7","LRP5","",""
65 | "FZD7_LRP6","FZD7","LRP6","",""
66 | "FZD8_LRP5","FZD8","LRP5","",""
67 | "FZD8_LRP6","FZD8","LRP6","",""
68 | "FZD9_LRP5","FZD9","LRP5","",""
69 | "FZD9_LRP6","FZD9","LRP6","",""
70 | "GFRA1_RET","GFRA1","RET","",""
71 | "GFRA2_RET","GFRA2","RET","",""
72 | "GFRA3_RET","GFRA3","RET","",""
73 | "GFRA4_RET","GFRA4","RET","",""
74 | "IFNAR1_IFNAR2","IFNAR1","IFNAR2","",""
75 | "IFNGR1_IFNGR2","IFNGR1","IFNGR2","",""
76 | "IFNLR1_IL10RB","IFNLR1","IL10RB","",""
77 | "IL10RA_IL10RB","IL10RA","IL10RB","",""
78 | "IL11R complex","IL11RA","IL6ST","",""
79 | "IL12RB1_IL12RB2","IL12RB1","IL12RB2","",""
80 | "IL15RA_IL2RB","IL15RA","IL2RB","IL2RG",""
81 | "IL17RA_IL17RB","IL17RA","IL17RB","",""
82 | "IL17RA_IL17RC","IL17RA","IL17RC","",""
83 | "IL17RA_IL17RE","IL17RA","IL17RE","",""
84 | "IL18R1_IL18RAP","IL18R1","IL18RAP","",""
85 | "IL1R1_IL1RAP","IL1R1","IL1RAP","",""
86 | "IL1RL1_IL1RAP","IL1RL1","IL1RAP","",""
87 | "IL1RL2_IL1RAP","IL1RL2","IL1RAP","",""
88 | "IL2RA_IL2RB_IL2RG","IL20RA","IL20RB","IL2RG",""
89 | "IL21R_IL2RG","IL21R","IL2RG","",""
90 | "IL22RA1_IL10RB","IL22RA1","IL10RB","",""
91 | "IL22RA1_IL20RB","IL22RA1","IL20RB","",""
92 | "IL20RA_IL20RB","IL20RA","IL20RB","",""
93 | "IL20RA_IL10RB","IL20RA","IL10RB","",""
94 | "IL23R_IL12RB1","IL23R","IL12RB1","",""
95 | "IL27RA_IL6ST","IL27RA","IL6ST","",""
96 | "IL28RA_IL10RB","IFNLR1","IL10RB","",""
97 | "IL2RB_IL2RG","IL2RB","IL2RG","",""
98 | "IL2RA_IL2RB","IL2RA","IL2RB","IL2RG",""
99 | "IL31RA_OSMR","IL31RA","OSMR","",""
100 | "IL3RA_CSF2RB","IL3RA","CSF2RB","",""
101 | "IL4R_IL13RA1","IL4R","IL13RA1","",""
102 | "IL4R_IL13RA2","IL4R","IL13RA2","",""
103 | "IL4R_IL2RG","IL4R","IL2RG","",""
104 | "IL5RA_CSF2RB","IL5RA","CSF2RB","",""
105 | "IL6R_IL6ST","IL6R","IL6ST","",""
106 | "IL7R_CRLF2","IL7R","CRLF2","",""
107 | "IL7R_IL2RG","IL7R","IL2RG","",""
108 | "IL9R_IL2RG","IL9R","IL2RG","",""
109 | "ITGA1_ITGB1","ITGA1","ITGB1","",""
110 | "ITGA10_ITGB1","ITGA10","ITGB1","",""
111 | "ITGA11_ITGB1","ITGA11","ITGB1","",""
112 | "ITGA2_ITGB1","ITGA2","ITGB1","",""
113 | "ITGA2B_ITGB3","ITGA2B","ITGB3","",""
114 | "ITGA3_ITGB1","ITGA3","ITGB1","",""
115 | "ITGA4_ITGB1","ITGA4","ITGB1","",""
116 | "ITGA4_ITGB7","ITGA4","ITGB7","",""
117 | "ITGA5_ITGB1","ITGA5","ITGB1","",""
118 | "ITGA6_ITGB1","ITGA6","ITGB1","",""
119 | "ITGA6_ITGB4","ITGA6","ITGB4","",""
120 | "ITGA7_ITGB1","ITGA7","ITGB1","",""
121 | "ITGA8_ITGB1","ITGA8","ITGB1","",""
122 | "ITGA9_ITGB1","ITGA9","ITGB1","",""
123 | "ITGAE_ITGB7","ITGAE","ITGB7","",""
124 | "ITGAL_ITGB2","ITGAL","ITGB2","",""
125 | "ITGAM_ITGB2","ITGAM","ITGB2","",""
126 | "ITGAV_ITGB1","ITGAV","ITGB1","",""
127 | "ITGAV_ITGB3","ITGAV","ITGB3","",""
128 | "ITGAV_ITGB5","ITGAV","ITGB5","",""
129 | "ITGAV_ITGB6","ITGAV","ITGB6","",""
130 | "ITGAV_ITGB8","ITGAV","ITGB8","",""
131 | "ITGAX_ITGB2","ITGAX","ITGB2","",""
132 | "ITGB1_ITGA1","ITGB1","ITGA1","",""
133 | "KLRD1_KLRC1","KLRD1","KLRC1","",""
134 | "KLRD1_KLRC2","KLRD1","KLRC2","",""
135 | "KLRK1_HCST","KLRK1","HCST","",""
136 | "LIFR_IL6ST","LIFR","IL6ST","",""
137 | "Npnt complex 1","NPNT","FRAS1","FREM1",""
138 | "Npnt complex 2","NPNT","FRAS1","FREM2",""
139 | "NRP1_NRP2","NRP1","NRP2","PLXND1",""
140 | "NRP1_PLXNA1","NRP1","PLXNA1","",""
141 | "NRP1_PLXNA2","NRP1","PLXNA2","",""
142 | "NRP1_PLXNA3","NRP1","PLXNA3","",""
143 | "NRP1_PLXNA4","NRP1","PLXNA4","",""
144 | "NRP2_PLXNA1","NRP2","PLXNA1","",""
145 | "NRP2_PLXNA2","NRP2","PLXNA2","",""
146 | "NRP2_PLXNA3","NRP2","PLXNA3","",""
147 | "NRP2_PLXNA4","NRP2","PLXNA4","",""
148 | "OSMR_IL6ST","OSMR","IL6ST","",""
149 | "PLXNA1_KDR","PLXNA1","KDR","",""
150 | "PLXNA1_TREM2","PLXNA1","TREM2","TYROBP",""
151 | "PTCH1_SMO","PTCH1","SMO","",""
152 | "PTCH2_SMO","PTCH2","SMO","",""
153 | "TGFBR1_ACVR2A","TGFBR1","ACVR2A","",""
154 | "TGFBR1_ACVR2B","TGFBR1","ACVR2B","",""
155 | "TGFbR1_R2","TGFBR1","TGFBR2","",""
156 | "CD94:NKG2A","KLRD1","KLRC1","",""
157 | "CD94:NKG2C","KLRD1","KLRC2","",""
158 | "CD94:NKG2E","KLRD1","KLRC3","",""
159 |
--------------------------------------------------------------------------------
/spatialdm/datasets/LR_data/human-interaction_input_CellChatDB.csv.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StatBiomed/SpatialDM/bfd2c3739abf5432549aad67c74b3f51f4817c9e/spatialdm/datasets/LR_data/human-interaction_input_CellChatDB.csv.gz
--------------------------------------------------------------------------------
/spatialdm/datasets/LR_data/mouse-complex_input_CellChatDB.csv:
--------------------------------------------------------------------------------
1 | "","subunit_1","subunit_2","subunit_3","subunit_4"
2 | "Activin AB","Inhba","Inhbb","",""
3 | "Inhibin A","Inha","Inhba","",""
4 | "Inhibin B","Inha","Inhbb","",""
5 | "IL12AB","Il12a","Il12b","",""
6 | "IL23 complex","Il12b","Il23a","",""
7 | "IL27 complex","Il27","Ebi3","",""
8 | "IL17AF","Il17a","Il17f","",""
9 | "LTa1b2","Lta","Ltb","",""
10 | "GP complex","Gp1ba","Gp1bb","Gp5","Gp9"
11 | "ACVR1_ACVR2A","Acvr1","Acvr2a","",""
12 | "ACVR1_ACVR2B","Acvr1","Acvr2b","",""
13 | "ACVR1_BMPR2","Acvr1","Bmpr2","",""
14 | "ACVR1_TGFbR","Acvr1","Tgfbr1","Tgfbr2",""
15 | "ACVR1B_ACVR2A","Acvr1b","Acvr2a","",""
16 | "ACVR1B_ACVR2A_CFC1","Acvr1b","Acvr2a","Cfc1",""
17 | "ACVR1B_ACVR2B","Acvr1b","Acvr2b","",""
18 | "ACVR1B_ACVR2B_CFC1","Acvr1b","Acvr2b","Cfc1",""
19 | "ACVR1B_BMPR2","Acvr1b","Bmpr2","",""
20 | "ACVR1B_TGFbR2","Acvr1b","Tgfbr2","",""
21 | "ACVR1C_ACVR2A","Acvr1c","Acvr2a","",""
22 | "ACVR1C_ACVR2A_CFC1","Acvr1c","Acvr2a","Cfc1",""
23 | "ACVR1C_ACVR2B","Acvr1c","Acvr2b","",""
24 | "ACVR1C_ACVR2B_CFC1","Acvr1c","Acvr2b","Cfc1",""
25 | "ACVR1C_TGFbR2","Acvr1c","Tgfbr2","",""
26 | "ACVRL1_ACVR2A","Acvrl1","Acvr2a","",""
27 | "ACVRL1_BMPR2","Acvrl1","Bmpr2","",""
28 | "AMHR2_ACVR1","Amhr2","Acvr1","",""
29 | "AMHR2_BMPR1A","Amhr2","Bmpr1a","",""
30 | "BMPR1A_ACVR2A","Bmpr1a","Acvr2a","",""
31 | "BMPR1A_ACVR2B","Bmpr1a","Acvr2b","",""
32 | "BMPR1A_BMPR2","Bmpr1a","Bmpr2","",""
33 | "BMPR1B_ACVR2A","Bmpr1b","Acvr2a","",""
34 | "BMPR1B_ACVR2B","Bmpr1b","Acvr2b","",""
35 | "BMPR1B_BMPR2","Bmpr1b","Bmpr2","",""
36 | "CD74_CD44","Cd74","Cd44","",""
37 | "CD74_CXCR2","Cd74","Cxcr2","",""
38 | "CD74_CXCR4","Cd74","Cxcr4","",""
39 | "CD8 receptor","Cd8a","Cd8b1","",""
40 | "CNTFR_LIFR","Cntfr","Lifr","Il6st",""
41 | "CNTN1_CNTNAP1","Cntn1","Cntnap1","",""
42 | "CNTN2_CNTNAP2","Cntn2","Cntnap2","",""
43 | "CSF2RA_CSF2RB","Csf2ra","Csf2rb","",""
44 | "EGFR_ERBB2","Egfr","Erbb2","",""
45 | "ERBB2_ERBB3","Erbb2","Erbb3","",""
46 | "ERBB2_ERBB4","Erbb2","Erbb4","",""
47 | "FLT1_KDR","Flt1","Kdr","",""
48 | "FLT4_KDR","Flt4","Kdr","",""
49 | "FPR2_LXA4","Fpr2","Fpr3","",""
50 | "FZD1_LRP5","Fzd1","Lrp5","",""
51 | "FZD1_LRP6","Fzd1","Lrp6","",""
52 | "FZD10_LRP5","Fzd10","Lrp5","",""
53 | "FZD10_LRP6","Fzd10","Lrp6","",""
54 | "FZD2_LRP5","Fzd2","Lrp5","",""
55 | "FZD2_LRP6","Fzd2","Lrp6","",""
56 | "FZD3_LRP5","Fzd3","Lrp5","",""
57 | "FZD3_LRP6","Fzd3","Lrp6","",""
58 | "FZD4_LRP5","Fzd4","Lrp5","",""
59 | "FZD4_LRP6","Fzd4","Lrp6","",""
60 | "FZD5_LRP5","Fzd5","Lrp5","",""
61 | "FZD5_LRP6","Fzd5","Lrp6","",""
62 | "FZD6_LRP5","Fzd6","Lrp5","",""
63 | "FZD6_LRP6","Fzd6","Lrp6","",""
64 | "FZD7_LRP5","Fzd7","Lrp5","",""
65 | "FZD7_LRP6","Fzd7","Lrp6","",""
66 | "FZD8_LRP5","Fzd8","Lrp5","",""
67 | "FZD8_LRP6","Fzd8","Lrp6","",""
68 | "FZD9_LRP5","Fzd9","Lrp5","",""
69 | "FZD9_LRP6","Fzd9","Lrp6","",""
70 | "GFRA1_RET","Gfra1","Ret","",""
71 | "GFRA2_RET","Gfra2","Ret","",""
72 | "GFRA3_RET","Gfra3","Ret","",""
73 | "GFRA4_RET","Gfra4","Ret","",""
74 | "IFNAR1_IFNAR2","Ifnar1","Ifnar2","",""
75 | "IFNGR1_IFNGR2","Ifngr1","Ifngr2","",""
76 | "IFNLR1_IL10RB","Ifnlr1","Il10rb","",""
77 | "IL10RA_IL10RB","Il10ra","Il10rb","",""
78 | "IL11R complex 1","Il11ra1","Il6st","",""
79 | "IL11R complex 2","Il11ra2","Il6st","",""
80 | "IL12RB1_IL12RB2","Il12rb1","Il12rb2","",""
81 | "IL15RA_IL2RB","Il15ra","Il2rb","Il2rg",""
82 | "IL17RA_IL17RB","Il17ra","Il17rb","",""
83 | "IL17RA_IL17RC","Il17ra","Il17rc","",""
84 | "IL17RA_IL17RE","Il17ra","Il17re","",""
85 | "IL18R1_IL18RAP","Il18r1","Il18rap","",""
86 | "IL1R1_IL1RAP","Il1r1","Il1rap","",""
87 | "IL1RL1_IL1RAP","Il1rl1","Il1rap","",""
88 | "IL1RL2_IL1RAP","Il1rl2","Il1rap","",""
89 | "IL20RA_IL20RB","Il20ra","Il20rb","",""
90 | "IL21R_IL2RG","Il21r","Il2rg","",""
91 | "IL22RA1_IL10RB","Il22ra1","Il10rb","",""
92 | "IL22RA1_IL20RB","Il22ra1","Il20rb","",""
93 | "IL23R_IL12RB1","Il23r","Il12rb1","",""
94 | "IL27RA_IL6ST","Il27ra","Il6st","",""
95 | "IL28RA_IL10RB","Ifnlr1","Il10rb","",""
96 | "IL2RB_IL2RG","Il2rb","Il2rg","",""
97 | "IL2RA_IL2RB","Il2ra","Il2rb","Il2rg",""
98 | "IL31RA_OSMR","Il31ra","Osmr","",""
99 | "IL3RA_CSF2RB","Il3ra","Csf2rb","",""
100 | "IL4R_IL13RA1","Il4ra","Il13ra1","",""
101 | "IL4R_IL13RA2","Il4ra","Il13ra2","",""
102 | "IL4R_IL2RG","Il4ra","Il2rg","",""
103 | "IL5RA_CSF2RB","Il5ra","Csf2rb","",""
104 | "IL6R_IL6ST","Il6ra","Il6st","",""
105 | "IL7R_CRLF2","Il7r","Crlf2","",""
106 | "IL7R_IL2RG","Il7r","Il2rg","",""
107 | "IL9R_IL2RG","Il9r","Il2rg","",""
108 | "ITGA1_ITGB1","Itga1","Itgb1","",""
109 | "ITGA10_ITGB1","Itga10","Itgb1","",""
110 | "ITGA11_ITGB1","Itga11","Itgb1","",""
111 | "ITGA2_ITGB1","Itga2","Itgb1","",""
112 | "ITGA2B_ITGB3","Itga2b","Itgb3","",""
113 | "ITGA3_ITGB1","Itga3","Itgb1","",""
114 | "ITGA4_ITGB1","Itga4","Itgb1","",""
115 | "ITGA4_ITGB7","Itga4","Itgb7","",""
116 | "ITGA5_ITGB1","Itga5","Itgb1","",""
117 | "ITGA6_ITGB1","Itga6","Itgb1","",""
118 | "ITGA6_ITGB4","Itga6","Itgb4","",""
119 | "ITGA7_ITGB1","Itga7","Itgb1","",""
120 | "ITGA8_ITGB1","Itga8","Itgb1","",""
121 | "ITGA9_ITGB1","Itga9","Itgb1","",""
122 | "ITGAE_ITGB7","Itgae","Itgb7","",""
123 | "ITGAL_ITGB2","Itgal","Itgb2","",""
124 | "ITGAL_ITGB2L","Itgal","Itgb2l","",""
125 | "ITGAM_ITGB2","Itgam","Itgb2","",""
126 | "ITGAM_ITGB2L","Itgam","Itgb2l","",""
127 | "ITGAV_ITGB1","Itgav","Itgb1","",""
128 | "ITGAV_ITGB3","Itgav","Itgb3","",""
129 | "ITGAV_ITGB5","Itgav","Itgb5","",""
130 | "ITGAV_ITGB6","Itgav","Itgb6","",""
131 | "ITGAV_ITGB8","Itgav","Itgb8","",""
132 | "ITGAX_ITGB2","Itgax","Itgb2","",""
133 | "ITGB1_ITGA1","Itgb1","Itga1","",""
134 | "KLRD1_KLRC1","Klrd1","Klrc1","",""
135 | "KLRD1_KLRC2","Klrd1","Klrc2","",""
136 | "KLRK1_HCST","Klrk1","Hcst","",""
137 | "LIFR_IL6ST","Lifr","Il6st","",""
138 | "Npnt complex 1","Npnt","Fras1","Frem1",""
139 | "Npnt complex 2","Npnt","Fras1","Frem2",""
140 | "NRP1_NRP2","Nrp1","Nrp2","Plxnd1",""
141 | "NRP1_PLXNA1","Nrp1","Plxna1","",""
142 | "NRP1_PLXNA2","Nrp1","Plxna2","",""
143 | "NRP1_PLXNA3","Nrp1","Plxna3","",""
144 | "NRP1_PLXNA4","Nrp1","Plxna4","",""
145 | "NRP2_PLXNA1","Nrp2","Plxna1","",""
146 | "NRP2_PLXNA2","Nrp2","Plxna2","",""
147 | "NRP2_PLXNA3","Nrp2","Plxna3","",""
148 | "NRP2_PLXNA4","Nrp2","Plxna4","",""
149 | "OSMR_IL6ST","Osmr","Il6st","",""
150 | "PLXNA1_KDR","Plxna1","Kdr","",""
151 | "PLXNA1_TREM2","Plxna1","Trem2","Tyrobp",""
152 | "PTCH1_SMO","Ptch1","Smo","",""
153 | "PTCH2_SMO","Ptch2","Smo","",""
154 | "TGFBR1_ACVR2A","Tgfbr1","Acvr2a","",""
155 | "TGFBR1_ACVR2B","Tgfbr1","Acvr2b","",""
156 | "TGFbR1_R2","Tgfbr1","Tgfbr2","",""
157 |
--------------------------------------------------------------------------------
/spatialdm/datasets/LR_data/mouse-interaction_input_CellChatDB.csv.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StatBiomed/SpatialDM/bfd2c3739abf5432549aad67c74b3f51f4817c9e/spatialdm/datasets/LR_data/mouse-interaction_input_CellChatDB.csv.gz
--------------------------------------------------------------------------------
/spatialdm/datasets/LR_data/zerafish-complex_input_CellChatDB.csv:
--------------------------------------------------------------------------------
1 | "","subunit_1","subunit_2"
2 | "Activin AB_1","inhbab","inhbb"
3 | "Activin AB_2","inhbaa","inhbb"
4 | "Inhibin A_1","inha","inhbab"
5 | "Inhibin A_2","inha","inhbaa"
6 | "Inhibin B","inha","inhbb"
7 | "IL12AB_1","il12a","il12ba"
8 | "IL12AB_2","il12a","il12bb"
9 | "IL12AB_3","zmp:0000001127","il12ba"
10 | "IL12AB_4","zmp:0000001127","il12bb"
11 | "ACVR1B_ACVR2A_1","acvr1bb","acvr2aa"
12 | "ACVR1B_ACVR2A_2","acvr1bb","acvr2ab"
13 | "ACVR1B_ACVR2A_3","acvr1ba","acvr2aa"
14 | "ACVR1B_ACVR2A_4","acvr1ba","acvr2ab"
15 | "ACVR1B_ACVR2A_CFC1_1","acvr1bb","acvr2aa"
16 | "ACVR1B_ACVR2A_CFC1_2","acvr1bb","acvr2ab"
17 | "ACVR1B_ACVR2A_CFC1_3","acvr1ba","acvr2aa"
18 | "ACVR1B_ACVR2A_CFC1_4","acvr1ba","acvr2ab"
19 | "ACVR1B_ACVR2B_1","acvr1bb","acvr2ba"
20 | "ACVR1B_ACVR2B_2","acvr1bb","acvr2bb"
21 | "ACVR1B_ACVR2B_3","acvr1ba","acvr2ba"
22 | "ACVR1B_ACVR2B_4","acvr1ba","acvr2bb"
23 | "ACVR1B_ACVR2B_CFC1_1","acvr1bb","acvr2ba"
24 | "ACVR1B_ACVR2B_CFC1_2","acvr1bb","acvr2bb"
25 | "ACVR1B_ACVR2B_CFC1_3","acvr1ba","acvr2ba"
26 | "ACVR1B_ACVR2B_CFC1_4","acvr1ba","acvr2bb"
27 | "ACVR1B_BMPR2_1","acvr1bb","bmpr2b"
28 | "ACVR1B_BMPR2_2","acvr1ba","bmpr2b"
29 | "ACVR1B_TGFbR2_1","acvr1bb","tgfbr2b"
30 | "ACVR1B_TGFbR2_2","acvr1bb","tgfbr2a"
31 | "ACVR1B_TGFbR2_3","acvr1ba","tgfbr2b"
32 | "ACVR1B_TGFbR2_4","acvr1ba","tgfbr2a"
33 | "ACVR1C_TGFbR2_1","acvr1cb","tgfbr2b"
34 | "ACVR1C_TGFbR2_2","acvr1cb","tgfbr2a"
35 | "ACVR1C_TGFbR2_3","acvr1ca","tgfbr2b"
36 | "ACVR1C_TGFbR2_4","acvr1ca","tgfbr2a"
37 | "ACVRL1_ACVR2A_1","acvr1l","acvr2aa"
38 | "ACVRL1_ACVR2A_2","acvr1l","acvr2ab"
39 | "ACVRL1_ACVR2A_3","acvrl1","acvr2aa"
40 | "ACVRL1_ACVR2A_4","acvrl1","acvr2ab"
41 | "ACVRL1_BMPR2_1","acvr1l","bmpr2b"
42 | "ACVRL1_BMPR2_2","acvrl1","bmpr2b"
43 | "BMPR1A_ACVR2A_1","bmpr1ab","acvr2aa"
44 | "BMPR1A_ACVR2A_2","bmpr1ab","acvr2ab"
45 | "BMPR1A_ACVR2A_3","bmpr1aa","acvr2aa"
46 | "BMPR1A_ACVR2A_4","bmpr1aa","acvr2ab"
47 | "BMPR1A_ACVR2B_1","bmpr1ab","acvr2ba"
48 | "BMPR1A_ACVR2B_2","bmpr1ab","acvr2bb"
49 | "BMPR1A_ACVR2B_3","bmpr1aa","acvr2ba"
50 | "BMPR1A_ACVR2B_4","bmpr1aa","acvr2bb"
51 | "BMPR1A_BMPR2_1","bmpr1ab","bmpr2b"
52 | "BMPR1A_BMPR2_2","bmpr1aa","bmpr2b"
53 | "BMPR1B_ACVR2A_1","bmpr1ba","acvr2aa"
54 | "BMPR1B_ACVR2A_2","bmpr1ba","acvr2ab"
55 | "BMPR1B_ACVR2A_3","bmpr1bb","acvr2aa"
56 | "BMPR1B_ACVR2A_4","bmpr1bb","acvr2ab"
57 | "BMPR1B_ACVR2B_1","bmpr1ba","acvr2ba"
58 | "BMPR1B_ACVR2B_2","bmpr1ba","acvr2bb"
59 | "BMPR1B_ACVR2B_3","bmpr1bb","acvr2ba"
60 | "BMPR1B_ACVR2B_4","bmpr1bb","acvr2bb"
61 | "BMPR1B_BMPR2_1","bmpr1ba","bmpr2b"
62 | "BMPR1B_BMPR2_2","bmpr1bb","bmpr2b"
63 | "CD74_CD44_1","cd74a","cd44a"
64 | "CD74_CD44_2","cd74a","cd44b"
65 | "CD74_CD44_3","cd74b","cd44a"
66 | "CD74_CD44_4","cd74b","cd44b"
67 | "CD74_CXCR2_1","cd74a","cxcr2"
68 | "CD74_CXCR2_2","cd74b","cxcr2"
69 | "CD74_CXCR4_1","cd74a","cxcr4a"
70 | "CD74_CXCR4_2","cd74a","cxcr4b"
71 | "CD74_CXCR4_3","cd74b","cxcr4a"
72 | "CD74_CXCR4_4","cd74b","cxcr4b"
73 | "CD8 receptor","cd8a","cd8b"
74 | "CNTFR_LIFR","cntfr","osmr"
75 | "CNTN2_CNTNAP2","robo4","cntnap2b"
76 | "EGFR_ERBB2","egfra","erbb2"
77 | "ERBB2_ERBB3_1","erbb2","erbb3a"
78 | "ERBB2_ERBB3_2","erbb2","erbb3b"
79 | "ERBB2_ERBB4_1","erbb2","erbb4a"
80 | "ERBB2_ERBB4_2","erbb2","si:ch73-383l1.1"
81 | "ERBB2_ERBB4_3","erbb2","erbb4b"
82 | "FLT1_KDR","flt1","kdr"
83 | "FLT4_KDR","flt4","kdr"
84 | "FZD1_LRP5","fzd1","lrp5"
85 | "FZD1_LRP6","fzd1","lrp6"
86 | "FZD10_LRP5","fzd10","lrp5"
87 | "FZD10_LRP6","fzd10","lrp6"
88 | "FZD2_LRP5","fzd2","lrp5"
89 | "FZD2_LRP6","fzd2","lrp6"
90 | "FZD3_LRP5_1","fzd3b","lrp5"
91 | "FZD3_LRP5_2","fzd3a","lrp5"
92 | "FZD3_LRP6_1","fzd3b","lrp6"
93 | "FZD3_LRP6_2","fzd3a","lrp6"
94 | "FZD4_LRP5","fzd4","lrp5"
95 | "FZD4_LRP6","fzd4","lrp6"
96 | "FZD5_LRP5","fzd5","lrp5"
97 | "FZD5_LRP6","fzd5","lrp6"
98 | "FZD6_LRP5","fzd6","lrp5"
99 | "FZD6_LRP6","fzd6","lrp6"
100 | "FZD7_LRP5_1","fzd7b","lrp5"
101 | "FZD7_LRP5_2","fzd7a","lrp5"
102 | "FZD7_LRP6_1","fzd7b","lrp6"
103 | "FZD7_LRP6_2","fzd7a","lrp6"
104 | "FZD8_LRP5_1","fzd8a","lrp5"
105 | "FZD8_LRP5_2","fzd8b","lrp5"
106 | "FZD8_LRP6_1","fzd8a","lrp6"
107 | "FZD8_LRP6_2","fzd8b","lrp6"
108 | "FZD9_LRP5_1","fzd9b","lrp5"
109 | "FZD9_LRP5_2","fzd9a","lrp5"
110 | "FZD9_LRP6_1","fzd9b","lrp6"
111 | "FZD9_LRP6_2","fzd9a","lrp6"
112 | "GFRA1_RET_1","gfra1a","ret"
113 | "GFRA1_RET_2","gfra1b","ret"
114 | "GFRA2_RET_1","gfra2a","ret"
115 | "GFRA2_RET_2","gfra2b","ret"
116 | "GFRA3_RET","gfra3","ret"
117 | "GFRA4_RET_1","gfra4a","ret"
118 | "GFRA4_RET_2","gfra4b","ret"
119 | "CRFB2_CRFB4","crfb2","crfb4"
120 | "CRFB15_CRFB4","crfb15","crfb4"
121 | "CRFB16_CRFB4","crfb16","crfb4"
122 | "IFNGR1L_CRFB4","ifngr1l","crfb4"
123 | "IFNGR2_CRFB4","ifngr2","crfb4"
124 | "IFNGR1_CRFB4","ifngr1","crfb4"
125 | "IFNLR1_CRFB4","ifnlr1","crfb4"
126 | "LIFRB_GHRB","lifrb","ghrb"
127 | "LIFRB_LIFRB","lifrb","lifrb"
128 | "LIFRB_LIFRA","lifrb","lifra"
129 | "LIFRB_GHRA","lifrb","ghra"
130 | "LIFRB_IL11RA","lifrb","il11ra"
131 | "LIFRB_IL6R","lifrb","il6r"
132 | "LIFRB_IL23R","lifrb","il23r"
133 | "LIFRA_GHRB","lifra","ghrb"
134 | "LIFRA_LIFRB","lifra","lifrb"
135 | "LIFRA_LIFRA","lifra","lifra"
136 | "LIFRA_GHRA","lifra","ghra"
137 | "LIFRA_IL11RA","lifra","il11ra"
138 | "LIFRA_IL6R","lifra","il6r"
139 | "LIFRA_IL23R","lifra","il23r"
140 | "GHRA_GHRB","ghra","ghrb"
141 | "GHRA_LIFRB","ghra","lifrb"
142 | "GHRA_LIFRA","ghra","lifra"
143 | "GHRA_GHRA","ghra","ghra"
144 | "GHRA_IL11RA","ghra","il11ra"
145 | "GHRA_IL6R","ghra","il6r"
146 | "GHRA_IL23R","ghra","il23r"
147 | "GHRB_GHRB","ghrb","ghrb"
148 | "GHRB_LIFRB","ghrb","lifrb"
149 | "GHRB_LIFRA","ghrb","lifra"
150 | "GHRB_GHRA","ghrb","ghra"
151 | "GHRB_IL11RA","ghrb","il11ra"
152 | "GHRB_IL6R","ghrb","il6r"
153 | "GHRB_IL23R","ghrb","il23r"
154 | "CSF2RB_GHRB","csf2rb","ghrb"
155 | "CSF2RB_IL2RGA","csf2rb","il2rga"
156 | "CSF2RB_IL2RGB","csf2rb","il2rgb"
157 | "CSF2RB_LIFRB","csf2rb","lifrb"
158 | "CSF2RB_LIFRA","csf2rb","lifra"
159 | "CSF2RB_GHRA","csf2rb","ghra"
160 | "CSF2RB_IL11RA","csf2rb","il11ra"
161 | "CSF2RB_IL6R","csf2rb","il6r"
162 | "IL2RB_GHRB","il2rb","ghrb"
163 | "IL2RB_IL2RGA","il2rb","il2rga"
164 | "IL2RB_IL2RGB","il2rb","il2rgb"
165 | "IL2RB_LIFRB","il2rb","lifrb"
166 | "IL2RB_LIFRA","il2rb","lifra"
167 | "IL2RB_GHRA","il2rb","ghra"
168 | "IL2RB_IL11RA","il2rb","il11ra"
169 | "IL2RB_IL6R","il2rb","il6r"
170 | "IL6R_GHRB","il6r","ghrb"
171 | "IL6R_LIFRB","il6r","lifrb"
172 | "IL6R_LIFRA","il6r","lifra"
173 | "IL6R_GHRA","il6r","ghra"
174 | "IL6R_IL11RA","il6r","il11ra"
175 | "IL6R_IL6R","il6r","il6r"
176 | "IL6R_IL23R","il6r","il23r"
177 | "IL10RB_CRFB15","il10rb","crfb15"
178 | "IL10RB_IL22RA2","il10rb","il22ra2"
179 | "IL10RB_IFNGR1L","il10rb","ifngr1l"
180 | "IL10RB_CRFB16","il10rb","crfb16"
181 | "IL10RB_IFNGR2","il10rb","ifngr2"
182 | "IL10RB_IL10RA","il10rb","il10ra"
183 | "IL10RB_IFNGR1","il10rb","ifngr1"
184 | "IL10RB_IFNLR1","il10rb","ifnlr1"
185 | "IL11RA_GHRB","il11ra","ghrb"
186 | "IL11RA_LIFRB","il11ra","lifrb"
187 | "IL11RA_LIFRA","il11ra","lifra"
188 | "IL11RA_GHRA","il11ra","ghra"
189 | "IL11RA_IL11RA","il11ra","il11ra"
190 | "IL11RA_IL6R","il11ra","il6r"
191 | "IL11RA_IL23R","il11ra","il23r"
192 | "IL15RA_IL2RB","il15ra","il2rb"
193 | "IL15RA_CSF2RB","il15ra","csf2rb"
194 | "IL15RA_IL21R1","il15ra","il21r.1"
195 | "IL21R1_GHRB","il21r.1","ghrb"
196 | "IL21R1_IL2RGA","il21r.1","il2rga"
197 | "IL21R1_IL2RGB","il21r.1","il2rgb"
198 | "IL21R1_LIFRB","il21r.1","lifrb"
199 | "IL21R1_LIFRA","il21r.1","lifra"
200 | "IL21R1_GHRA","il21r.1","ghra"
201 | "IL21R1_IL11RA","il21r.1","il11ra"
202 | "IL21R1_IL6R","il21r.1","il6r"
203 | "IL22RA2_CRFB4","il22ra2","crfb4"
204 | "MPL_GHRB","mpl","ghrb"
205 | "MPL_IL2RG_1","mpl","il2rga"
206 | "MPL_IL2RG_2","mpl","il2rgb"
207 | "MPL_LIFRB","mpl","lifrb"
208 | "MPL_LIFRA","mpl","lifra"
209 | "MPL_GHRA","mpl","ghra"
210 | "MPL_IL11RA","mpl","il11ra"
211 | "MPL_IL6R","mpl","il6r"
212 | "ITGA2B_ITGB3_1","itga2b","itgb3b"
213 | "ITGA2B_ITGB3_2","itga2b","itgb3a"
214 | "ITGA4_ITGB7","itga4","itgb7"
215 | "ITGA6_ITGB4_1","itga6b","itgb4"
216 | "ITGA6_ITGB4_2","itga6a","itgb4"
217 | "ITGAE_ITGB7","itgae.2","itgb7"
218 | "ITGAV_ITGB3_1","itgav","itgb3b"
219 | "ITGAV_ITGB3_2","itgav","itgb3a"
220 | "ITGAV_ITGB5","itgav","itgb5"
221 | "ITGAV_ITGB6","itgav","itgb6"
222 | "ITGAV_ITGB8","itgav","itgb8"
223 | "ITGAX_ITGB2","itgax","itgb2"
224 | "ITGAM_ITGB2","itgam","itgb2"
225 | "KLRD1_KLRC1_1","si:ch211-193e13.5","si:ch211-193e13.5"
226 | "KLRD1_KLRC1_2","si:ch211-193e13.5","si:ch211-170d8.8"
227 | "KLRD1_KLRC1_3","si:ch211-193e13.5","si:dkey-26c10.5"
228 | "KLRD1_KLRC1_4","si:ch211-170d8.8","si:ch211-193e13.5"
229 | "KLRD1_KLRC1_5","si:ch211-170d8.8","si:ch211-170d8.8"
230 | "KLRD1_KLRC1_6","si:ch211-170d8.8","si:dkey-26c10.5"
231 | "KLRD1_KLRC1_7","si:dkey-26c10.5","si:ch211-193e13.5"
232 | "KLRD1_KLRC1_8","si:dkey-26c10.5","si:ch211-170d8.8"
233 | "KLRD1_KLRC1_9","si:dkey-26c10.5","si:dkey-26c10.5"
234 | "KLRD1_KLRC2_1","si:ch211-193e13.5","si:ch211-193e13.5"
235 | "KLRD1_KLRC2_2","si:ch211-193e13.5","si:ch211-170d8.8"
236 | "KLRD1_KLRC2_3","si:ch211-193e13.5","si:dkey-26c10.5"
237 | "KLRD1_KLRC2_4","si:ch211-170d8.8","si:ch211-193e13.5"
238 | "KLRD1_KLRC2_5","si:ch211-170d8.8","si:ch211-170d8.8"
239 | "KLRD1_KLRC2_6","si:ch211-170d8.8","si:dkey-26c10.5"
240 | "KLRD1_KLRC2_7","si:dkey-26c10.5","si:ch211-193e13.5"
241 | "KLRD1_KLRC2_8","si:dkey-26c10.5","si:ch211-170d8.8"
242 | "KLRD1_KLRC2_9","si:dkey-26c10.5","si:dkey-26c10.5"
243 | "NRP1_NRP2_1","nrp1a","nrp2a"
244 | "NRP1_NRP2_2","nrp1a","nrp2b"
245 | "NRP1_PLXNA1","nrp1a","plxna1a"
246 | "NRP1_PLXNA2","nrp1a","plxna2"
247 | "NRP1_PLXNA3","nrp1a","plxna3"
248 | "NRP2_PLXNA1_1","nrp2a","plxna1a"
249 | "NRP2_PLXNA1_2","nrp2b","plxna1a"
250 | "NRP2_PLXNA2_1","nrp2a","plxna2"
251 | "NRP2_PLXNA2_2","nrp2b","plxna2"
252 | "NRP2_PLXNA3_1","nrp2a","plxna3"
253 | "NRP2_PLXNA3_2","nrp2b","plxna3"
254 | "PLXNA1_KDR","plxna1a","kdr"
255 | "PTCH1_SMO","ptch1","smo"
256 | "PTCH2_SMO","ptch2","smo"
257 | "TGFBR1_ACVR2A_1","tgfbr1a","acvr2aa"
258 | "TGFBR1_ACVR2A_2","tgfbr1a","acvr2ab"
259 | "TGFBR1_ACVR2A_3","tgfbr1b","acvr2aa"
260 | "TGFBR1_ACVR2A_4","tgfbr1b","acvr2ab"
261 | "TGFBR1_ACVR2B_1","tgfbr1a","acvr2ba"
262 | "TGFBR1_ACVR2B_2","tgfbr1a","acvr2bb"
263 | "TGFBR1_ACVR2B_3","tgfbr1b","acvr2ba"
264 | "TGFBR1_ACVR2B_4","tgfbr1b","acvr2bb"
265 | "TGFbR1_R2_1","tgfbr1a","tgfbr2b"
266 | "TGFbR1_R2_2","tgfbr1a","tgfbr2a"
267 | "TGFbR1_R2_3","tgfbr1b","tgfbr2b"
268 | "TGFbR1_R2_4","tgfbr1b","tgfbr2a"
269 |
--------------------------------------------------------------------------------
/spatialdm/datasets/LR_data/zerafish-interaction_input_CellChatDB.csv.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StatBiomed/SpatialDM/bfd2c3739abf5432549aad67c74b3f51f4817c9e/spatialdm/datasets/LR_data/zerafish-interaction_input_CellChatDB.csv.gz
--------------------------------------------------------------------------------
/spatialdm/datasets/__init__.py:
--------------------------------------------------------------------------------
1 | from .dataset import * # noqa: F403
2 |
--------------------------------------------------------------------------------
/spatialdm/datasets/_util_dataset.py:
--------------------------------------------------------------------------------
1 | from abc import ABC, abstractmethod
2 | from typing import Any, Dict, Tuple, Union, Callable, Optional, Sequence
3 | from inspect import Parameter, signature, Signature
4 | from pathlib import Path
5 | from dataclasses import field, dataclass
6 | import os
7 |
8 | from scanpy import read, logging as logg
9 | from anndata import AnnData
10 | from scanpy._utils import check_presence_download
11 | import anndata
12 |
13 | PathLike = Union[os.PathLike, str]
14 | Function_t = Callable[..., Union[AnnData, Any]]
15 |
16 |
17 | @dataclass(frozen=True) # type: ignore[misc]
18 | class Metadata(ABC):
19 | """Base class handling metadata."""
20 |
21 | name: str
22 | url: str
23 |
24 | doc_header: Optional[str] = field(default=None, repr=False)
25 | path: Optional[PathLike] = field(default=None, repr=False)
26 | shape: Optional[Tuple[int, int]] = field(default=None, repr=False)
27 | library_id: Optional[Union[str, Sequence[str]]] = field(default=None, repr=False)
28 |
29 | _DOC_FMT = ""
30 |
31 | def __post_init__(self) -> None:
32 | if self.doc_header is None:
33 | object.__setattr__(self, "doc_header", f"Download `{self.name.title().replace('_', ' ')}` data.")
34 | if self.path is None:
35 | object.__setattr__(self, "path", os.path.expanduser(f"~/.cache/spatialdm/{self.name}"))
36 |
37 | @property
38 | @abstractmethod
39 | def _extension(self) -> str:
40 | pass
41 |
42 | @abstractmethod
43 | def _download(self, fpath: PathLike, backup_url: str, **kwargs: Any) -> Any:
44 | pass
45 |
46 | @abstractmethod
47 | def _create_signature(self) -> Signature:
48 | pass
49 |
50 | def _create_function(self, name: str, glob_ns: Dict[str, Any]) -> None:
51 | # if name in globals():
52 | # raise KeyError(f"Function name `{name}` is already present in `{sorted(globals().keys())}`.")
53 |
54 | sig = self._create_signature()
55 | globals()["NoneType"] = type(None) # __post_init__ return annotation
56 | globals()[name] = self
57 |
58 | exec(
59 | f"def {self.name}{sig}:\n"
60 | f' """'
61 | f" {self._DOC_FMT.format(doc_header=self.doc_header, shape=self.shape)}"
62 | f' """\n'
63 | f" return {name}.download(path, **kwargs)".replace(" /,", ""),
64 | globals(),
65 | glob_ns,
66 | )
67 |
68 | def download(self, fpath: Optional[PathLike] = None, **kwargs: Any) -> Any:
69 | """Download the dataset into ``fpath``."""
70 | fpath = str(self.path if fpath is None else fpath)
71 | if not fpath.endswith(self._extension):
72 | fpath += self._extension
73 |
74 | if os.path.isfile(fpath):
75 | logg.debug(f"Loading dataset `{self.name}` from `{fpath}`")
76 | else:
77 | logg.debug(f"Downloading dataset `{self.name}` from `{self.url}` as `{fpath}`")
78 |
79 | dirname = Path(fpath).parent
80 | try:
81 | if not dirname.is_dir():
82 | logg.info(f"Creating directory `{dirname}`")
83 | dirname.mkdir(parents=True, exist_ok=True)
84 | except OSError as e:
85 | logg.error(f"Unable to create directory `{dirname}`. Reason `{e}`")
86 |
87 | data = self._download(fpath=fpath, backup_url=self.url, **kwargs)
88 |
89 | if self.shape is not None and data.shape != self.shape:
90 | raise ValueError(f"Expected the data to have shape `{self.shape}`, found `{data.shape}`.")
91 |
92 | return data
93 |
94 |
95 | class AMetadata(Metadata):
96 | """Metadata class for :class:`anndata.AnnData`."""
97 |
98 | _DOC_FMT = """
99 | {doc_header}
100 |
101 | The shape of this :class:`anndata.AnnData` object ``{shape}``.
102 |
103 | Parameters
104 | ----------
105 | path
106 | Path where to save the dataset.
107 | kwargs
108 | Keyword arguments for :func:`scanpy.read`.
109 |
110 | Returns
111 | -------
112 | The dataset."""
113 |
114 | def _create_signature(self) -> Signature:
115 | return signature(lambda _: _).replace(
116 | parameters=[
117 | Parameter("path", kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=PathLike, default=None),
118 | Parameter("kwargs", kind=Parameter.VAR_KEYWORD, annotation=Any),
119 | ],
120 | return_annotation=anndata.AnnData,
121 | )
122 |
123 | def _download(self, fpath: PathLike, backup_url: str, **kwargs: Any) -> AnnData:
124 | kwargs.setdefault("sparse", False)
125 | kwargs.setdefault("cache", True)
126 |
127 | return read(filename=fpath, backup_url=backup_url, **kwargs)
128 |
129 | @property
130 | def _extension(self) -> str:
131 | return ".h5ad"
132 |
133 |
134 | class ImgMetadata(Metadata):
135 | """Metadata class for :class:`spatialdm.im.ImageContainer`."""
136 |
137 | _DOC_FMT = """
138 | {doc_header}
139 |
140 | The shape of this image is ``{shape}``.
141 |
142 | Parameters
143 | ----------
144 | path
145 | Path where to save the .tiff image.
146 | kwargs
147 | Keyword arguments for :meth:`spatialdm.im.ImageContainer.add_img`.
148 |
149 | Returns
150 | -------
151 | :class:`spatialdm.im.ImageContainer`
152 | The image data."""
153 | # not the perfect annotation, but better than nothing
154 | _EXT = ".tiff"
155 |
156 | def _create_signature(self) -> Signature:
157 | return signature(lambda _: _).replace(
158 | parameters=[
159 | Parameter("path", kind=Parameter.POSITIONAL_OR_KEYWORD, annotation=PathLike, default=None),
160 | Parameter("kwargs", kind=Parameter.VAR_KEYWORD, annotation=Any),
161 | ],
162 | )
163 |
164 | def _download(self, fpath: PathLike, backup_url: str, **kwargs: Any) -> Any:
165 | from spatialdm.im import ImageContainer # type: ignore[attr-defined]
166 |
167 | check_presence_download(Path(fpath), backup_url)
168 |
169 | img = ImageContainer()
170 | img.add_img(fpath, layer="image", library_id=self.library_id, **kwargs)
171 |
172 | return img
173 |
174 | @property
175 | def _extension(self) -> str:
176 | return ".tiff"
177 |
--------------------------------------------------------------------------------
/spatialdm/datasets/dataset.py:
--------------------------------------------------------------------------------
1 | from copy import copy
2 | from ._util_dataset import AMetadata
3 |
4 |
5 | _mel = AMetadata(
6 | name="melanoma",
7 | doc_header="melanoma dataset from `Thrane et al `__.",
8 | shape=(293, 16148),
9 | url="https://ndownloader.figshare.com/files/40178320",
10 | )
11 |
12 | _SVZ = AMetadata(
13 | name="SVZ",
14 | doc_header="SVZ dataset from `Eng et al `__.",
15 | shape=(281, 10000),
16 | url="https://ndownloader.figshare.com/files/40178041",
17 | )
18 |
19 | _A1 = AMetadata(
20 | name="A1",
21 | doc_header="Adult colon rep 1 from Corbett, et al. `__.",
22 | shape=(2649, 33538),
23 | url="https://ndownloader.figshare.com/files/40178029",
24 | )
25 |
26 | _A2 = AMetadata(
27 | name="A2",
28 | doc_header="Adult colon rep 2 from Corbett, et al. `__.",
29 | shape=(2316, 33538),
30 | url="https://figshare.com/ndownloader/files/40178317",
31 | )
32 |
33 | _A3 = AMetadata(
34 | name="A3",
35 | doc_header="12-PCW Fetus colon single rep from Corbett, et al. `__.",
36 | shape=(1080, 33538),
37 | url="https://figshare.com/ndownloader/files/40178311",
38 | )
39 |
40 | _A4 = AMetadata(
41 | name="A4",
42 | doc_header="19-PCW Fetus colon single rep from Corbett, et al. `__.",
43 | shape=(1242, 33538),
44 | url="https://figshare.com/ndownloader/files/40178314",
45 | )
46 |
47 | _A6 = AMetadata(
48 | name="A6",
49 | doc_header="12-PCW TI rep 1 from Corbett, et al. `__.",
50 | shape=(346, 33538),
51 | url="https://figshare.com/ndownloader/files/40178017",
52 | )
53 |
54 | _A7 = AMetadata(
55 | name="A7",
56 | doc_header="12-PCW TI rep 2 from Corbett, et al. `__.",
57 | shape=(344, 33538),
58 | url="https://figshare.com/ndownloader/files/40178014",
59 | )
60 |
61 | _A8 = AMetadata(
62 | name="A8",
63 | doc_header="12-PCW colon rep 1 from Corbett, et al. `__.",
64 | shape=(709, 33538),
65 | url="https://figshare.com/ndownloader/files/40178011",
66 | )
67 |
68 | _A9 = AMetadata(
69 | name="A9",
70 | doc_header="12-PCW colon rep 2 from Corbett, et al. `__.",
71 | shape=(644, 33538),
72 | url="https://figshare.com/ndownloader/files/40178308",
73 | )
74 |
75 |
76 | for name, var in copy(locals()).items():
77 | if isinstance(var, AMetadata):
78 | var._create_function(name, globals())
79 |
80 |
81 | __all__ = [ # noqa: F822
82 | "melanoma", "SVZ",
83 | "A1","A2","A3","A4","A6","A7","A8","A9"]
84 |
--------------------------------------------------------------------------------
/spatialdm/diff_utils.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import numpy as np
3 | import anndata as ann
4 | from statsmodels.stats.multitest import fdrcorrection
5 |
6 | def concat_db(adatas, species):
7 | """
8 | Merge all interaction database from a list of spatialdm obj.
9 | :param samples: a list of spatialdm obj to be merged.
10 | :param species: str. 'human' or 'mouse'.
11 | :return:
12 | """
13 | if species == 'mouse':
14 | geneInter = pd.read_csv('https://figshare.com/ndownloader/files/36638919', index_col=0)
15 | comp = pd.read_csv('https://figshare.com/ndownloader/files/36638916', header=0, index_col=0)
16 | elif species == 'human':
17 | geneInter = pd.read_csv('https://figshare.com/ndownloader/files/36638943', header=0, index_col=0)
18 | comp = pd.read_csv('https://figshare.com/ndownloader/files/36638940', header=0, index_col=0)
19 | else:
20 | raise ValueError("species type: {} is not supported currently. Please have a check.".format(species))
21 | ligand = pd.concat([sample.uns['ligand'] for sample in adatas], axis=1)
22 | receptor = pd.concat([sample.uns['receptor'] for sample in adatas], axis=1)
23 | ligand=ligand[~ligand.index.duplicated()]
24 | receptor=receptor[~receptor.index.duplicated()]
25 | geneInter = geneInter.loc[ligand.index]
26 | return ligand, receptor, geneInter
27 |
28 | def concat_obj(samples, names, species, method='z-score', fdr=False):
29 | # def __init__(self, samples, names, species, method='z-score', fdr=False):
30 | """
31 | Merge all global results from a list of spatialdm obj
32 | :param samples: a list of spatialdm obj to be merged.
33 | :param names: a list of str for each sample's name.
34 | :param species: str. 'human' or 'mouse'.
35 | :param dir_db']: dir containing 0_CellChatdb'] folder.
36 | :param method: 'z-score' or 'permutation'. Should be the commonly selected method from all samples.
37 | :param fdr: If use fdr or p-values for differential analysis
38 | """
39 | cdata = ann.concat(samples, join='outer')
40 | cdata.obs['batch'] = np.repeat(names, [sample.shape[0] for sample in samples])
41 | cdata.uns['ligand'], cdata.uns['receptor'], cdata.uns['geneInter'] = concat_db(samples, species)
42 | n_samples = len(samples)
43 | cdata.uns['method'] = method
44 | cdata.uns['p_df'] = pd.DataFrame(np.zeros((cdata.uns['ligand'].shape[0], n_samples)),
45 | index=cdata.uns['ligand'].index, columns=names)
46 | cdata.uns['tf_df'] = cdata.uns['p_df'].copy()
47 | if method == 'z-score':
48 | cdata.uns['zscore_df'] = cdata.uns['p_df'].copy()
49 | for sample, d in zip(samples, names):
50 | sample.uns['global_res']['z'] = pd.Series(sample.uns['global_res']['z'],
51 | index=sample.uns['ligand'].index)
52 | if fdr:
53 | cdata.uns['p_df'][d] = sample.uns['global_res'].fdr
54 | else:
55 | cdata.uns['p_df'][d] = sample.uns['global_res'].z_pval
56 | cdata.uns['p_df'][d] = np.where(np.isnan(cdata.uns['p_df'][d]), 1, cdata.uns['p_df'][d])
57 | cdata.uns['zscore_df'][d] = sample.uns['global_res']['z']
58 | cdata.uns['zscore_df'][d] = np.where(np.isnan(cdata.uns['zscore_df'][d]), 0, cdata.uns['zscore_df'][d])
59 | cdata.uns['tf_df'][d] = sample.uns['global_res'].selected
60 | elif method == 'permutation':
61 | print('This function to be updated') #TODO: update!
62 | for sample, d in zip(samples, names):
63 | sample.uns['z']['z'] = pd.Series(sample.uns['z']['z'], sample.uns['global_res'].index)
64 | if fdr:
65 | cdata.uns['p_df'][d] = sample.uns['global_res'].fdr
66 | else:
67 | cdata.uns['p_df'][d] = sample.uns['global_res'].perm_pval
68 | else:
69 | raise ValueError("Only one of ['z-score', 'permutation'] is supported")
70 | cdata.uns['tf_df'] = cdata.uns['tf_df'].fillna(False)
71 | cdata.uns['tf_df'] = cdata.uns['tf_df'].astype(bool)
72 | return cdata
73 |
74 | def differential_test(cdata, subset, conditions):
75 | """
76 | Test whether each pair is differential among 2 or more conditions by likehood ratio
77 | :param subset: list of concat_obj names to perform differential test on.
78 | :param conditions: numeric label distinguishing conditions for each selected sample from the subset
79 | :return:
80 | cdata.uns['p_val']: dataframe containing differential p-values
81 | cdata.uns['diff_fdr']: dataframe containing fdr corrected differential p-values
82 | """
83 | if cdata.uns['method'] == 'z-score':
84 | import statsmodels.api as sm
85 | import scipy
86 | cdata.uns['subset'] = subset
87 | cdata.uns['conditions'] = conditions
88 | n_sub = len(subset)
89 | cdata.uns['n_sub'] = n_sub
90 | LR_statistic = np.zeros((len(cdata.uns['p_df'])))
91 | cdata.uns['p_val'] = np.zeros((len(cdata.uns['p_df'])))
92 | x = conditions
93 | for i in range(len(cdata.uns['p_df'])):
94 | # full model
95 | p = cdata.uns['zscore_df'].index[i]
96 | y = np.where(cdata.uns['zscore_df'].loc[p, subset].isna(), 0, cdata.uns['zscore_df'].loc[p, subset].values)
97 | y1 = y
98 | x1 = np.vstack((np.ones(n_sub), x)).T
99 | full_model = sm.OLS(y1, x1).fit()
100 | full_ll = full_model.llf
101 |
102 | # reduced model
103 | y2 = y
104 | x2 = np.ones(n_sub)
105 | reduced_model = sm.OLS(y2, x2).fit()
106 | reduced_ll = reduced_model.llf
107 |
108 | # calculate likelihood ratio Chi-Squared test statistic
109 | LR_statistic[i] = -2 * (reduced_ll - full_ll)
110 | cdata.uns['p_val'][i] = scipy.stats.chi2.sf(LR_statistic[i], 1)
111 |
112 | cdata.uns['diff'] = cdata.uns['zscore_df'].loc[:, np.array(subset)[conditions == 1]].mean(1) - \
113 | cdata.uns['zscore_df'].loc[:, np.array(subset)[conditions == 0]].mean(1)
114 |
115 | cdata.uns['p_val'] = np.where(np.isnan(cdata.uns['p_val']), 1, cdata.uns['p_val'])
116 |
117 | cdata.uns['diff_fdr'] = fdrcorrection(cdata.uns['p_val'])[1]
118 |
119 | def group_differential_pairs(cdata, c1_name, c2_name, diff_quantile1=0.7, diff_quantile2=0.3, fdr_co=0.1):
120 | '''
121 | :param cdata: concatenated adata object
122 | :param c1_name: (str) condition 1 name
123 | :param c2_name: (str) condition 2 name
124 | :param diff_quantile1: (float) quantile for highlighting
125 | :param diff_quantile2: (float)
126 | :param fdr_co: (float) fdr cutoff
127 | :return: specific pairs for c1 and c2
128 | '''
129 | _range = np.arange(1, cdata.uns['n_sub'])
130 | cdata.uns['q1'] = np.quantile(cdata.uns['diff'], diff_quantile1)
131 | cdata.uns['q2'] = np.quantile(cdata.uns['diff'], diff_quantile2)
132 | cdata.uns['fdr_co'] = fdr_co
133 | fdr = cdata.uns['diff_fdr']
134 | tf_df = cdata.uns['tf_df']
135 | diff = cdata.uns['diff']
136 |
137 | c1_only = tf_df.loc[(tf_df.loc[:, np.array(cdata.uns['subset'])[cdata.uns['conditions'] == 1]].sum(1) == \
138 | (cdata.uns['conditions'] == 1).sum()) & \
139 | (tf_df.loc[:, np.array(cdata.uns['subset'])[cdata.uns['conditions'] == 0]].sum(1) == 0)].index
140 |
141 | c2_only = tf_df.loc[(tf_df.loc[:, np.array(cdata.uns['subset'])[cdata.uns['conditions'] == 1]].sum(1) == 0) & \
142 | (tf_df.loc[:, np.array(cdata.uns['subset'])[cdata.uns['conditions'] == 0]].sum(1) == \
143 | (cdata.uns['conditions'] == 0).sum())].index
144 |
145 | c1_specific = np.hstack((c1_only, diff[(diff > cdata.uns['q1']) & (fdr < fdr_co) & \
146 | (tf_df.sum(1).isin(_range))].index))
147 |
148 | cdata.uns[c1_name + '_specific'] = pd.Series(c1_specific).drop_duplicates().values
149 | c2_specific = np.hstack((c2_only, diff[(diff < cdata.uns['q2']) & (fdr < fdr_co) & \
150 | ((tf_df.sum(1).isin(_range)))].index))
151 | cdata.uns[c2_name + '_specific'] = pd.Series(c2_specific).drop_duplicates().values
152 | cdata.uns[c1_name + '_only'] = c1_only.values
153 | cdata.uns[c2_name + '_only'] = c2_only.values
154 |
155 |
156 |
--------------------------------------------------------------------------------
/spatialdm/main.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pandas as pd
3 | import numpy as np
4 | from sklearn.neighbors import NearestNeighbors
5 | from statsmodels.stats.multitest import fdrcorrection
6 | from scipy import spatial
7 | # import json
8 | from threadpoolctl import threadpool_limits
9 | from .utils import *
10 | from itertools import zip_longest
11 | import anndata as ann
12 |
13 |
14 | def weight_matrix(adata, l=None, cutoff=0.1, n_neighbors=None, n_nearest_neighbors=6, single_cell=False, eff_dist=None):
15 | """
16 | compute weight matrix based on radial basis kernel.
17 | cutoff & n_neighbors are two alternative options to restrict signaling range.
18 | :param l: radial basis kernel parameter, need to be customized for optimal weight gradient and \
19 | to restrain the range of signaling before downstream processing.
20 | :param cutoff: (for secreted signaling) minimum weight to be kept from the rbf weight matrix. \
21 | Weight below cutoff will be made zero
22 | :param n_neighbors: (for secreted signaling) number of neighbors per spot from the rbf weight matrix.
23 | :param n_nearest_neighbors: (for adjacent signaling) number of neighbors per spot from the rbf \
24 | weight matrix.
25 | Non-neighbors will be made 0
26 | :param single_cell: if single cell resolution, diagonal will be made 0.
27 | :return: secreted signaling weight matrix: adata.obsp['weight'], \
28 | and adjacent signaling weight matrix: adata.obsp['nearest_neighbors']
29 | """
30 | def _Euclidean_to_RBF(X, l, singlecell=single_cell):
31 | """Convert Euclidean distance to RBF distance"""
32 | from scipy.sparse import issparse
33 | if issparse:
34 | rbf_d = X
35 | rbf_d[X.nonzero()] = np.exp(-X[X.nonzero()].A**2 / (2 * l ** 2))
36 | else:
37 | rbf_d = np.exp(- X**2 / (2 * l ** 2))
38 |
39 | # At single-cell resolution, no within-spot communications
40 | if singlecell:
41 | np.fill_diagonal(rbf_d, 0)
42 | else:
43 | rbf_d.setdiag(np.exp(-X.diagonal()**2 / (2 * l ** 2)))
44 |
45 | return rbf_d
46 |
47 | adata.uns['single_cell'] = single_cell
48 | if isinstance(adata.obsm['spatial'], pd.DataFrame):
49 | X_loc = adata.obsm['spatial'].values
50 | else:
51 | X_loc = adata.obsm['spatial']
52 |
53 | if n_neighbors is None:
54 | n_neighbors = n_nearest_neighbors * 31
55 |
56 | if l is None:
57 | if eff_dist is None:
58 | raise ValueError('At least one of l and eff_dist params should be specified')
59 | else:
60 | l = np.sqrt(-eff_dist/(2*np.log(cutoff)))
61 | ## large neighborhood for W (5 layers)
62 | nnbrs = NearestNeighbors(
63 | n_neighbors=n_neighbors,
64 | algorithm='ball_tree',
65 | metric='euclidean'
66 | ).fit(X_loc)
67 | nbr_d = nnbrs.kneighbors_graph(X_loc, mode='distance')
68 | rbf_d = _Euclidean_to_RBF(nbr_d, l, single_cell)
69 |
70 | ## small neighborhood for RBF
71 | nnbrs0 = NearestNeighbors(
72 | n_neighbors=n_nearest_neighbors,
73 | algorithm='ball_tree',
74 | metric='euclidean'
75 | ).fit(X_loc)
76 | nbr_d0 = nnbrs0.kneighbors_graph(X_loc, mode='distance')
77 | rbf_d0 = _Euclidean_to_RBF(nbr_d0, l, single_cell)
78 |
79 | # NOTE: add more info about cutoff, n_neighbors and n_nearest_neighbors
80 | #if cutoff:
81 | # not efficient
82 | # rbf_d[rbf_d < cutoff] = 0
83 |
84 | # more efficient:
85 | # https://seanlaw.github.io/2019/02/27/set-values-in-sparse-matrix/
86 | nonzero_mask = np.array(rbf_d[rbf_d.nonzero()] < cutoff)[0]
87 | rows = rbf_d.nonzero()[0][nonzero_mask]
88 | cols = rbf_d.nonzero()[1][nonzero_mask]
89 | rbf_d[rows, cols] = 0
90 |
91 | # elif n_neighbors:
92 | # nbrs = NearestNeighbors(n_neighbors=n_neighbors, algorithm='ball_tree').fit(rbf_d)
93 | # knn = nbrs.kneighbors_graph(rbf_d).toarray()
94 | # rbf_d = rbf_d * knn
95 |
96 | adata.obsp['weight'] = rbf_d * adata.shape[0] / rbf_d.sum()
97 | adata.obsp['nearest_neighbors'] = rbf_d0 * adata.shape[0] / rbf_d0.sum()
98 | return
99 |
100 | def extract_lr(adata, species, mean='algebra', min_cell=0, datahost='builtin'):
101 | """
102 | find overlapping LRs from CellChatDB
103 | :param adata: AnnData object
104 | :param species: support 'human', 'mouse' and 'zebrafish'
105 | :param mean: 'algebra' (default) or 'geometric'
106 | :param min_cell: for each selected pair, the spots expressing ligand or receptor should be larger than the min,
107 | respectively.
108 | :param datahost: the host of the ligand-receptor data. 'builtin' for package built-in otherwise from figshare
109 | :return: ligand, receptor, geneInter (containing comprehensive info from CellChatDB) dataframes \
110 | in adata.uns
111 | """
112 | if mean=='geometric':
113 | from scipy.stats.mstats import gmean
114 | adata.uns['mean'] = mean
115 |
116 | if datahost == 'package':
117 | if species in ['mouse', 'human', 'zerafish']:
118 | datapath = './datasets/LR_data/%s-' %(species)
119 | else:
120 | raise ValueError("species type: {} is not supported currently. Please have a check.".format(species))
121 |
122 | import pkg_resources
123 | stream1 = pkg_resources.resource_stream(__name__, datapath + 'interaction_input_CellChatDB.csv.gz')
124 | geneInter = pd.read_csv(stream1, index_col=0, compression='gzip')
125 |
126 | stream2 = pkg_resources.resource_stream(__name__, datapath + 'complex_input_CellChatDB.csv')
127 | comp = pd.read_csv(stream2, header=0, index_col=0)
128 | else:
129 | if species == 'mouse':
130 | geneInter = pd.read_csv('https://figshare.com/ndownloader/files/36638919', index_col=0)
131 | comp = pd.read_csv('https://figshare.com/ndownloader/files/36638916', header=0, index_col=0)
132 | elif species == 'human':
133 | geneInter = pd.read_csv('https://figshare.com/ndownloader/files/36638943', header=0, index_col=0)
134 | comp = pd.read_csv('https://figshare.com/ndownloader/files/36638940', header=0, index_col=0)
135 | elif species == 'zebrafish':
136 | geneInter = pd.read_csv('https://figshare.com/ndownloader/files/38756022', header=0, index_col=0)
137 | comp = pd.read_csv('https://figshare.com/ndownloader/files/38756019', header=0, index_col=0)
138 | else:
139 | raise ValueError("species type: {} is not supported currently. Please have a check.".format(species))
140 |
141 | geneInter = geneInter.sort_values('annotation')
142 | ligand = geneInter.ligand.values
143 | receptor = geneInter.receptor.values
144 | geneInter.pop('ligand')
145 | geneInter.pop('receptor')
146 |
147 | ## NOTE: the following for loop needs speed up
148 | t = []
149 | for i in range(len(ligand)):
150 | for n in [ligand, receptor]:
151 | l = n[i]
152 | if l in comp.index:
153 | n[i] = comp.loc[l].dropna().values[pd.Series \
154 | (comp.loc[l].dropna().values).isin(adata.var_names)]
155 | else:
156 | n[i] = pd.Series(l).values[pd.Series(l).isin(adata.var_names)]
157 | if (len(ligand[i]) > 0) * (len(receptor[i]) > 0):
158 | if mean=='geometric':
159 | meanL = gmean(adata[:, ligand[i]].X, axis=1)
160 | meanR = gmean(adata[:, receptor[i]].X, axis=1)
161 | else:
162 | meanL = adata[:, ligand[i]].X.mean(axis=1)
163 | meanR = adata[:, receptor[i]].X.mean(axis=1)
164 | if (sum(meanL > 0) >= min_cell) * \
165 | (sum(meanR > 0) >= min_cell):
166 | t.append(True)
167 | else:
168 | t.append(False)
169 | else:
170 | t.append(False)
171 | ind = geneInter[t].index
172 | adata.uns['ligand'] = pd.DataFrame.from_records(zip_longest(*pd.Series(ligand[t]).values)).transpose()
173 | adata.uns['ligand'].columns = ['Ligand' + str(i) for i in range(adata.uns['ligand'].shape[1])]
174 | adata.uns['ligand'].index = ind
175 | adata.uns['receptor'] = pd.DataFrame.from_records(zip_longest(*pd.Series(receptor[t]).values)).transpose()
176 | adata.uns['receptor'].columns = ['Receptor' + str(i) for i in range(adata.uns['receptor'].shape[1])]
177 | adata.uns['receptor'].index = ind
178 | adata.uns['num_pairs'] = len(ind)
179 | adata.uns['geneInter'] = geneInter.loc[ind]
180 | if adata.uns['num_pairs'] == 0:
181 | raise ValueError("No effective RL. Please have a check on input count matrix/species.")
182 | return
183 |
184 | def spatialdm_global(adata, n_perm=1000, specified_ind=None, method='z-score', nproc=1):
185 | """
186 | global selection. 2 alternative methods can be specified.
187 | :param n_perm: number of times for shuffling receptor expression for a given pair, default to 1000.
188 | :param specified_ind: array containing queried indices for quick test/only run selected pair(s).
189 | If not specified, selection will be done for all extracted pairs
190 | :param method: default to 'z-score' for computation efficiency.
191 | Alternatively, can specify 'permutation' or 'both'.
192 | Two approaches should generate consistent results in general.
193 | :param nproc: default to 1. Please decide based on your system.
194 | :return: 'global_res' dataframe in adata.uns containing pair info and Moran p-values
195 | """
196 | if specified_ind is None:
197 | specified_ind = adata.uns['geneInter'].index.values # default to all pairs
198 | else:
199 | adata.uns['geneInter'] = adata.uns['geneInter'].loc[specified_ind]
200 | total_len = len(specified_ind)
201 | adata.uns['ligand'] = adata.uns['ligand'].loc[specified_ind]#.values
202 | adata.uns['receptor'] = adata.uns['receptor'].loc[specified_ind]#.values
203 | adata.uns['global_I'] = np.zeros(total_len)
204 | adata.uns['global_stat'] = {}
205 | if method in ['z-score', 'both']:
206 | adata.uns['global_stat']['z']={}
207 | adata.uns['global_stat']['z']['st'] = globle_st_compute(adata)
208 | adata.uns['global_stat']['z']['z'] = np.zeros(total_len)
209 | adata.uns['global_stat']['z']['z_p'] = np.zeros(total_len)
210 | if method in ['both', 'permutation']:
211 | adata.uns['global_stat']['perm']={}
212 | adata.uns['global_stat']['perm']['global_perm'] = np.zeros((total_len, n_perm)).astype(np.float16)
213 |
214 | if not (method in ['both', 'z-score', 'permutation']):
215 | raise ValueError("Only one of ['z-score', 'both', 'permutation'] is supported")
216 |
217 | with threadpool_limits(limits=nproc, user_api='blas'):
218 | pair_selection_matrix(adata, n_perm, specified_ind, method)
219 |
220 | adata.uns['global_res'] = pd.concat((adata.uns['ligand'], adata.uns['receptor']),axis=1)
221 | # adata.uns['global_res'].columns = ['Ligand1', 'Ligand2', 'Ligand3', 'Receptor1', 'Receptor2', 'Receptor3', 'Receptor4']
222 | if method in ['z-score', 'both']:
223 | adata.uns['global_stat']['z']['z_p'] = np.where(np.isnan(adata.uns['global_stat']['z']['z_p']),
224 | 1, adata.uns['global_stat']['z']['z_p'])
225 | adata.uns['global_res']['z_pval'] = adata.uns['global_stat']['z']['z_p']
226 | adata.uns['global_res']['z'] = adata.uns['global_stat']['z']['z']
227 |
228 | if method in ['both', 'permutation']:
229 | adata.uns['global_stat']['perm']['global_p'] = 1 - (adata.uns['global_I'] \
230 | > adata.uns['global_stat']['perm']['global_perm'].T).sum(axis=0) / n_perm
231 | adata.uns['global_res']['perm_pval'] = adata.uns['global_stat']['perm']['global_p']
232 | return
233 |
234 | def sig_pairs(adata, method='z-score', fdr=True, threshold=0.1):
235 | """
236 | select significant pairs
237 | :param method: only one of 'z-score' or 'permutation' to select significant pairs.
238 | :param fdr: True or False. If fdr correction will be done for p-values.
239 | :param threshold: 0-1. p-value or fdr cutoff to retain significant pairs. Default to 0.1.
240 | :return: 'selected' column in global_res containing whether or not a pair should be retained
241 | """
242 | adata.uns['global_stat']['method'] = method
243 | if method == 'z-score':
244 | _p = adata.uns['global_res']['z_pval'].values
245 | elif method == 'permutation':
246 | _p = adata.uns['global_res']['perm_pval'].values
247 | else:
248 | raise ValueError("Only one of ['z-score', 'permutation'] is supported")
249 | if fdr:
250 | _p = fdrcorrection(_p)[1]
251 | adata.uns['global_res']['fdr'] = _p
252 | adata.uns['global_res']['selected'] = (_p < threshold)
253 |
254 | def spatialdm_local(adata, n_perm=1000, method='z-score', specified_ind=None,
255 | nproc=1, scale_X=True):
256 | """
257 | local spot selection
258 | :param n_perm: number of times for shuffling neighbors partner for a given spot, default to 1000.
259 | :param method: default to 'z-score' for computation efficiency.
260 | Alternatively, can specify 'permutation' or 'both' (recommended for spot number < 1000, multiprocesing).
261 | :param specified_ind: array containing queried indices in sample pair(s).
262 | If not specified, local selection will be done for all sig pairs
263 | :param nproc: default to 1.
264 | :return: 'local_stat' & 'local_z_p' and/or 'local_perm_p' in adata.uns.
265 | """
266 | adata.uns['local_stat'] = {}
267 | if (int(n_perm / nproc) != (n_perm / nproc)):
268 | raise ValueError("n_perm should be divisible by nproc")
269 | if type(specified_ind) == type(None):
270 | specified_ind = adata.uns['global_res'][
271 | adata.uns['global_res']['selected']].index # default to global selected pairs
272 | # total_len = len(specified_ind)
273 | ligand = adata.uns['ligand'].loc[specified_ind]
274 | receptor = adata.uns['receptor'].loc[specified_ind]
275 | ind = ligand.index
276 | adata.uns['local_stat']['local_I'] = np.zeros((adata.shape[0], len(ind)))
277 | adata.uns['local_stat']['local_I_R'] = np.zeros((adata.shape[0], len(ind)))
278 | N = adata.shape[0]
279 | if method in ['both', 'permutation']:
280 | adata.uns['local_stat']['local_permI'] = np.zeros((len(ind), n_perm, N))
281 | adata.uns['local_stat']['local_permI_R'] = np.zeros((len(ind), n_perm, N))
282 | if method in ['both', 'z-score']:
283 | adata.uns['local_z'] = np.zeros((len(ind), adata.shape[0]))
284 | adata.uns['local_z_p'] = np.zeros((len(ind), adata.shape[0]))
285 |
286 | ## different approaches
287 | with threadpool_limits(limits=nproc, user_api='blas'):
288 | spot_selection_matrix(adata, ligand, receptor, ind, n_perm, method, scale_X)
289 |
290 |
291 | def sig_spots(adata, method='z-score', fdr=True, threshold=0.1):
292 | """
293 | pick significantly co-expressing spots
294 | :param method: one of the methods from spatialdm_local, default to 'z-score'.
295 | :param fdr: True or False, default to True
296 | :param threshold: p-value or fdr cutoff to retain significant pairs. Default to 0.1.
297 | :return: 1) 'selected_spots' in adata.uns: a binary frame of which spots being selected for each pair;
298 | 2) 'n_spots' in adata.uns['local_stat']: number of selected spots for each pair.
299 | """
300 | if method == 'z-score':
301 | _p = adata.uns['local_z_p']
302 | if method == 'permutation':
303 | _p = adata.uns['local_perm_p']
304 | if fdr:
305 | _fdr = fdrcorrection(np.hstack(_p.values))[1].reshape(_p.shape)
306 | _p.loc[:,:] = _fdr
307 | adata.uns['local_stat']['local_fdr'] = _p
308 | adata.uns['selected_spots'] = (_p < threshold)
309 | adata.uns['local_stat']['n_spots'] = adata.uns['selected_spots'].sum(1)
310 | adata.uns['local_stat']['local_method'] = method
311 | return
312 |
313 | def drop_uns_na(adata, global_stat=False, local_stat=False):
314 | adata.uns['geneInter'] = adata.uns['geneInter'].fillna('NA')
315 | adata.uns['global_res'] = adata.uns['global_res'].fillna('NA')
316 | adata.uns['ligand'] = adata.uns['ligand'].fillna('NA')
317 | adata.uns['receptor'] = adata.uns['receptor'].fillna('NA')
318 | adata.uns['local_stat']['n_spots'] = pd.DataFrame(adata.uns['local_stat']['n_spots'], columns=['n_spots'])
319 | if global_stat and ('global_stat' in adata.uns.keys()):
320 | adata.uns.pop('global_stat')
321 | if local_stat and ('local_stat' in adata.uns.keys()):
322 | adata.uns.pop('local_stat')
323 |
324 | def restore_uns_na(adata):
325 | adata.uns['geneInter'] = adata.uns['geneInter'].replace('NA', np.nan)
326 | adata.uns['global_res'] = adata.uns['global_res'].replace('NA', np.nan)
327 | adata.uns['ligand'] = adata.uns['ligand'].replace('NA', np.nan)
328 | adata.uns['receptor'] = adata.uns['receptor'].replace('NA', np.nan)
329 | adata.uns['local_stat']['n_spots'] = adata.uns['local_stat']['n_spots'].n_spots
330 |
331 | def write_spatialdm_h5ad(adata, filename=None):
332 | if filename is None:
333 | filename = 'spatialdm_out.h5ad'
334 | elif not filename.endswith('h5ad'):
335 | filename = filename+'.h5ad'
336 | drop_uns_na(adata)
337 | adata.write(filename)
338 |
339 | def read_spatialdm_h5ad(filename):
340 | adata = ann.read_h5ad(filename)
341 | restore_uns_na(adata)
342 | return adata
343 |
344 | def compute_pathway(sample=None,
345 | all_interactions=None,
346 | interaction_ls=None, name=None, dic=None):
347 | """
348 | Compute enriched pathways for a list of pairs or a dic of SpatialDE results.
349 | :param sample: spatialdm obj
350 | :param ls: a list of LR interaction names for the enrichment analysis
351 | :param path_name: str. For later recall sample.path_summary[path_name]
352 | :param dic: a dic of SpatialDE results (See tutorial)
353 | """
354 | if interaction_ls is not None:
355 | dic = {name: interaction_ls}
356 | if sample is not None:
357 | all_interactions = sample.uns['geneInter']
358 | df = pd.DataFrame(all_interactions.groupby('pathway_name').interaction_name)
359 | df = df.set_index(0)
360 | total_feature_num = len(all_interactions)
361 | result = []
362 | all_path_genes = set(np.concatenate(list(dic.values())))
363 | all_path_genes = {x.upper() for x in all_path_genes}.intersection(all_interactions.index)
364 | for n,ls in dic.items():
365 | qset = set([x.upper() for x in ls]).intersection(all_interactions.index)
366 | query_set_size = len(qset)
367 | background = all_path_genes - qset
368 | for modulename, members in df.iterrows():
369 | module_size = len(members[1])
370 | overlap_features = qset.intersection(members[1])
371 | overlap_size = len(overlap_features)
372 |
373 | background_mapped = background.intersection(members[1])
374 | background_unmapped = background-background_mapped
375 |
376 | negneg = total_feature_num + overlap_size - module_size - query_set_size
377 | # Fisher's exact test
378 | p_FET = stats.fisher_exact([[overlap_size, query_set_size - overlap_size],
379 | [module_size - overlap_size, negneg]], 'greater')[1]
380 | #result.append((p_FET, modulename, module_size, overlap_size, overlap_features, n))
381 | result.append((modulename,members[1],qset,overlap_features,background_mapped,
382 | background_unmapped,overlap_size,p_FET,n))
383 | result = pd.DataFrame(result).set_index(0)
384 | result.index.name = 'pathway'
385 | result.columns = ['total_genes', 'query_genes', 'overlapped_genes','background_mapped_genes',
386 | 'background_unmapped_genes', 'selected','fisher_p','pattern']
387 | # if sample is not None:
388 | # sample.uns['pathway_summary'] = result
389 | return result
390 | # def save_spataildm(adata, result_dir, exclude=[]):
391 | # """
392 | # save spataildm output to a specified folder
393 | # :param result_dir: name of the specified folder
394 | # """
395 | # try:
396 | # os.makedirs(result_dir)
397 | # except OSError as e:
398 | # if e.errno != e.errno:
399 | # raise
400 | # dic = {}
401 | # for attr in adata.__dict__.keys():
402 | # if not attr in exclude:
403 | # res = getattr(self, attr)
404 | # if attr in ['logcounts', 'rawcounts']:
405 | # save_npz(result_dir + attr + '.npz', csc_matrix(res))
406 | # elif type(res) == pd.core.frame.DataFrame:
407 | # res.to_csv(os.path.join(result_dir, attr + '.csv'), index=True)
408 | # elif type(res) == np.ndarray:
409 | # np.save(os.path.join(result_dir, attr), res)
410 | # elif type(res) in [pd.core.indexes.base.Index, pd.core.series.Series]:
411 | # adata.__dict__[attr] = res.values
412 | # np.save(os.path.join(result_dir, attr), res)
413 | # else:
414 | # dic[attr] = res
415 | #
416 | # with open(os.path.join(result_dir, 'other'), "w") as fp:
417 | # json.dump(dic, fp)
418 | # return
419 | #
420 | # def read_spataildm(read_dir):
421 | # """
422 | # read previously save spatialdm obj from a folder
423 | # :param read_dir: the dir of saved spatialdm obj
424 | # :return: spatialdm obj
425 | # """
426 | # spot_names = np.load(os.path.join(read_dir, 'spot_names'), allow_pickle=True)
427 | # gene_names = np.load(os.path.join(read_dir, 'spot_names'), allow_pickle=True)
428 | #
429 | # logcounts = load_npz(os.path.join(read_dir, 'logcounts.csv'))
430 | # logcounts = pd.DataFrame(logcounts, index=spot_names, columns=gene_names)
431 | #
432 | # spatialcoord = pd.read_csv(os.path.join(read_dir, 'spatialcoord.csv'), index_col=0)
433 | #
434 | # rawcounts = load_npz(os.path.join(read_dir, 'rawcounts.csv'))
435 | # rawcounts = pd.DataFrame(rawcounts, index=spot_names, columns=gene_names)
436 | #
437 | # read_sample = SpatialDM(logcounts, rawcounts, spatialcoord) # load spatial data
438 | #
439 | # for f in os.listdir(read_dir):
440 | # if f in ['logcounts.csv', 'rawcounts.csv', 'spatialcoord.csv']:
441 | # pass
442 | # elif f.endswith('csv'):
443 | # read_sample.__dict__[f.split('.')[0]] = pd.read_csv(os.path.join(read_dir, f), index_col=0)
444 | # elif f.endswith('npy'):
445 | # read_sample.__dict__[f.split('.')[0]] = np.load(os.path.join(read_dir, f), allow_pickle=True)
446 | # elif f == 'other':
447 | # with open(os.path.join(read_dir, 'other')) as json_file:
448 | # _data = json.load(json_file)
449 | # for k in _data.keys():
450 | # read_sample.__dict__[k] = _data[k]
451 | # return read_sample
452 |
--------------------------------------------------------------------------------
/spatialdm/plottings.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import pandas as pd
3 | import numpy as np
4 | from matplotlib.backends.backend_pdf import PdfPages
5 | from sklearn import linear_model
6 | import scipy.stats as stats
7 | import seaborn as sns
8 | #from utils import compute_pathway
9 | from .utils import *
10 | import holoviews as hv
11 | from holoviews import opts, dim
12 | from bokeh.io import output_file, show
13 | from bokeh.plotting import figure
14 | from bokeh.io import export_svg, export_png
15 | from bokeh.layouts import gridplot
16 | from scipy.sparse import csc_matrix
17 |
18 | hv.extension('bokeh')
19 | hv.output(size=200)
20 |
21 | import math
22 | from matplotlib.cm import hsv
23 |
24 | def generate_colormap(number_of_distinct_colors, number_of_shades = 7):
25 | '''
26 | Ref: https://stackoverflow.com/questions/42697933/colormap-with-maximum-distinguishable-colours
27 | :param number_of_distinct_colors:
28 | :param number_of_shades:
29 | :return: n distinct colors
30 | '''
31 | number_of_distinct_colors_with_multiply_of_shades = int(math.ceil(number_of_distinct_colors \
32 | / number_of_shades) * number_of_shades)
33 |
34 | linearly_distributed_nums = np.arange(number_of_distinct_colors_with_multiply_of_shades) / \
35 | number_of_distinct_colors_with_multiply_of_shades
36 | arr_by_shade_rows = linearly_distributed_nums.reshape(number_of_shades, number_of_distinct_colors_with_multiply_of_shades // number_of_shades)
37 | arr_by_shade_columns = arr_by_shade_rows.T
38 | number_of_partitions = arr_by_shade_columns.shape[0]
39 | nums_distributed_like_rising_saw = arr_by_shade_columns.reshape(-1)
40 | initial_cm = hsv(nums_distributed_like_rising_saw)
41 | lower_partitions_half = number_of_partitions // 2
42 | upper_partitions_half = number_of_partitions - lower_partitions_half
43 | lower_half = lower_partitions_half * number_of_shades
44 | for i in range(3):
45 | initial_cm[0:lower_half, i] *= np.arange(0.2, 1, 0.8/lower_half)
46 | for i in range(3):
47 | for j in range(upper_partitions_half):
48 | modifier = np.ones(number_of_shades) - initial_cm[lower_half + j * number_of_shades: lower_half + (j + 1) * number_of_shades, i]
49 | modifier = j * modifier / upper_partitions_half
50 | initial_cm[lower_half + j * number_of_shades: lower_half + (j + 1) * number_of_shades, i] += modifier
51 | initial_cm = initial_cm[:,:3] * 255
52 | initial_cm = initial_cm.astype(int)
53 | initial_cm = np.array(['#%02x%02x%02x' % tuple(initial_cm[i]) for i in range(len(initial_cm))])
54 | return initial_cm
55 |
56 | def ligand_ct(adata, pair):
57 | ct_L = (
58 | adata.uns['local_stat']['local_I'][:,adata.uns['selected_spots'].index==pair] *
59 | adata.obsm['celltypes']
60 | )
61 | return ct_L
62 |
63 | def receptor_ct(adata, pair):
64 | ct_R = (
65 | adata.uns['local_stat']['local_I_R'][:,adata.uns['selected_spots'].index==pair] *
66 | adata.obsm['celltypes']
67 | )
68 | return ct_R
69 |
70 | def chord_celltype(adata, pairs, color_dic=None, title=None, min_quantile=0.5, ncol=1, save=None):
71 | """
72 | Plot aggregated cell type weights given a list of interaction pairs
73 | :param adata: Anndata object
74 | :param pairs: List of interactions. Must be consistent with adata.uns['selected_spots'].index
75 | :param color_dic: dict containing specified colors for each cell type
76 | :param title: default to names provided in pairs
77 | :param min_quantile: Minimum edge numbers (in quantile) to show in the plot, default to 0.5.
78 | :param ncol: number of columns if more than one pair will be plotted.
79 | :param save: 'svg' or 'png' or None
80 | :return: Chord diagram showing enriched cell types. Edge color indicates source cell types.
81 | """
82 |
83 | if color_dic is None:
84 | # adata.obsm['celltypes'] = adata.obs[adata.obs.columns]
85 | ct = adata.obsm['celltypes'].columns.sort_values()
86 | l = len(ct)
87 | l0 = max(l, 10)
88 | gen_col = generate_colormap(l0)[:l]
89 | color_dic = {ct[i]: gen_col[i] for i in range(len(ct))}
90 | ls = []
91 |
92 | if type(min_quantile) is float:
93 | min_quantile = np.repeat(min_quantile, len(pairs))
94 | for i, pair in enumerate(pairs):
95 | if title is None:
96 | t = pair
97 | type_interaction = adata.uns['geneInter'].loc[pair, 'annotation']
98 | if type_interaction == 'Secreted Signaling':
99 | w = adata.obsp['weight']
100 | else:
101 | w = adata.obsp['nearest_neighbors']
102 |
103 | ct_L = ligand_ct(adata, pair)
104 | ct_R = receptor_ct(adata, pair)
105 |
106 | sparse_ct_sum = [[(csc_matrix(w).multiply(ct_L[n1].values).T.multiply(ct_R[n2].values)).sum() \
107 | for n1 in ct_L.columns] for n2 in ct_R.columns]
108 | sparse_ct_sum = np.array(sparse_ct_sum)
109 |
110 | Links = pd.DataFrame({'source': np.tile(ct_L.columns, ct_R.shape[1]),
111 | 'target': np.repeat(ct_R.columns, ct_L.shape[1]),
112 | 'value': sparse_ct_sum.reshape(1, -1)[0]})
113 |
114 | Nodes = pd.DataFrame({'name': ct_L.columns})
115 | Nodes.index = Nodes.name.values
116 | nodes = hv.Dataset(Nodes, 'index')
117 |
118 | chord = hv.Chord((Links.loc[Links.value > 0], nodes)).select( # Links.value>min_link[i]
119 | value=(Links.value.quantile(min_quantile[i]), None))
120 | cmap_ct = pd.Series(color_dic)[chord.nodes.data['index'].values].values.tolist()
121 | adata.uns[pair + '_link'] = Links
122 | chord.opts(
123 | opts.Chord( # cmap='Category20',
124 | edge_cmap=cmap_ct,
125 | edge_color=dim('source').str(),
126 | labels='name', node_color=dim('index').str(),
127 | node_cmap=cmap_ct,
128 | title=t))
129 | ls.append(chord)
130 |
131 | ar = np.array([hv.render(fig) for fig in ls])
132 | for n in ar:
133 | n.output_backend = "svg"
134 | plots = ar.reshape(-1, ncol).tolist()
135 | grid = gridplot(plots)
136 | if save is not None:
137 | file_format = save.split('.')[-1]
138 | if file_format == 'svg':
139 | export_svg(grid, filename=save)
140 | elif file_format == 'png':
141 | export_png(grid, filename=save)
142 | show(grid)
143 | return grid
144 |
145 | def chord_LR(adata, senders, receivers, color_dic=None,
146 | title=None, min_quantile=0.5, ncol=1, save=None):
147 | """
148 | Plot aggregated interaction scores given a list of sender-receiver combinations.
149 | :param adata: Anndata object
150 | :param senders: (list) Sender cell types
151 | :param senders: (list) Receiver cell types. Must be of the same length with sender cell types.
152 | :param color_dic: dict containing specified colors for each sender-receiver combination.
153 | :param title: default to sender_receiver
154 | :param min_quantile: Minimum edge numbers (in quantile) to show in the plot, default to 0.5.
155 | :param ncol: number of columns if more than one combination will be plotted.
156 | :param save: 'svg' or 'png' or None
157 | :return: Chord diagram showing enriched interactions. Edge color indicates ligand.
158 | """
159 | if color_dic is None:
160 | subgeneInter = adata.uns['geneInter'].loc[adata.uns['selected_spots'].index]
161 | type_interaction = subgeneInter.annotation
162 | n_short_lri = (type_interaction!='Secreted Signaling').sum()
163 | ligand_all = subgeneInter.interaction_name_2.str.split('-').str[0]
164 | receptor_all = subgeneInter.interaction_name_2.str.split('-').str[1]
165 | genes_all = np.hstack((ligand_all, receptor_all))
166 | genes_all = pd.Series(genes_all).drop_duplicates().values
167 | l = len(genes_all)
168 | l0 = max(l, 10)
169 | gen_col = generate_colormap(l0)[:l]
170 | color_dic = {genes_all[i]: gen_col[i] for i in range(l)}
171 |
172 | ls = []
173 | if type(min_quantile) is float:
174 | min_quantile = np.repeat(min_quantile, len(senders))
175 |
176 | for i, (sender, receiver) in enumerate(zip(senders, receivers)):
177 | if title is None:
178 | t = ('_').join((sender, receiver))
179 |
180 | ct_L = adata.obs.loc[:,sender].values * adata.uns['local_stat']['local_I'].T
181 | ct_R = adata.obs.loc[:,receiver].values * adata.uns['local_stat']['local_I_R'].T
182 |
183 | sparse_ct_sum = np.hstack(([csc_matrix(adata.obsp['nearest_neighbors']).multiply(n1).T.multiply(n2).sum() \
184 | for n1,n2 in zip(ct_L[:n_short_lri], ct_R[:n_short_lri])],
185 | [csc_matrix(adata.obsp['weight']).multiply(n1).T.multiply(n2).sum() \
186 | for n1,n2 in zip(ct_L[n_short_lri:], ct_R[n_short_lri:])]))
187 |
188 |
189 | Links = pd.DataFrame({'source':ligand_all,
190 | 'target':receptor_all,
191 | 'value': sparse_ct_sum})
192 | adata.uns[t+'_link'] = Links
193 |
194 | Nodes = pd.DataFrame({'name': genes_all.astype(str)})
195 | Nodes.index = Nodes.name.values
196 |
197 | Nodes=Nodes.drop_duplicates()
198 |
199 | nodes = hv.Dataset(Nodes, 'index')
200 |
201 | chord = hv.Chord((Links.loc[Links.value>0], nodes)).select(
202 | value=(Links.value.quantile(min_quantile).drop_duplicates().values, None))
203 |
204 | cmap_ct = pd.Series(color_dic)[chord.nodes.data['index'].values].values.tolist()
205 |
206 | chord.opts(
207 | opts.Chord(#cmap='Category20',
208 | edge_cmap=cmap_ct,
209 | edge_color=dim('source').str(),
210 | labels='name', node_color=dim('index').str(),
211 | node_cmap=cmap_ct,
212 | title = 'Undifferentiated_Colonocytes'))
213 | ls.append(chord)
214 |
215 | ar = np.array([hv.render(fig) for fig in ls])
216 | for n in ar:
217 | n.output_backend = "svg"
218 | plots = ar.reshape(-1, ncol).tolist()
219 | grid = gridplot(plots)
220 | if save is not None:
221 | file_format = save.split('.')[-1]
222 | if file_format == 'svg':
223 | export_svg(grid, filename=save)
224 | elif file_format == 'png':
225 | export_png(grid, filename=save)
226 | show(grid)
227 | return grid
228 |
229 | def chord_celltype_allpairs(adata, color_dic=None,
230 | min_quantile=0.9, ncol=3, save=None):
231 | """
232 | Plot aggregated cell type weights for all pairs in adata.uns['selected_spots']
233 | :param adata: Anndata object
234 | :param pairs: List of interactions. Must be consistent with adata.uns['selected_spots'].index
235 | :param color_dic: dict containing specified colors for each cell type
236 | :param title: default to names provided in pairs
237 | :param min_quantile: Minimum edge numbers (in quantile) to show in the plot, default to 0.5.
238 | :param ncol: number of columns if more than one pair will be plotted.
239 | :param save: 'svg' or 'png' or None
240 | :return: 3 chord diagrams showing enriched cell types, one for adjacent signaling, \
241 | one for secreted signaling, and the other for the aggregated.
242 | """
243 |
244 | if color_dic is None:
245 | ct = adata.obs.columns.sort_values()
246 | l = len(ct)
247 | l0 = max(l, 10)
248 | gen_col = generate_colormap(l0)[:l]
249 | color_dic = {ct[i]: gen_col[i] for i in range(len(ct))}
250 |
251 | long_pairs = adata.uns['geneInter'][adata.uns['geneInter'].annotation == \
252 | 'Secreted Signaling'].index.intersection(adata.uns['selected_spots'].index)
253 | short_pairs = adata.uns['geneInter'][adata.uns['geneInter'].annotation != \
254 | 'Secreted Signaling'].index.intersection(adata.uns['selected_spots'].index)
255 | ls=[]
256 |
257 | for by_range,pairs,w in zip(['long', 'short'],
258 | [long_pairs, short_pairs],
259 | [adata.obsp['weight'], adata.obsp['nearest_neighbors']]):
260 | sparse_ct_sum = [[[(csc_matrix(w).multiply(ligand_ct(adata, p)[n1].values).T.multiply(receptor_ct(adata, p)[n2].values)).sum() \
261 | for n1 in ct] for n2 in ct] for p in pairs]
262 | sparse_ct_sum = np.array(sparse_ct_sum).sum(0)
263 |
264 | Links = pd.DataFrame({'source':np.tile(ct, l),
265 | 'target':np.repeat(ct, l),
266 | 'value': sparse_ct_sum.reshape(1,-1)[0]})
267 | adata.uns[by_range]=Links
268 |
269 | Nodes = pd.DataFrame({'name': ct})
270 | Nodes.index = Nodes.name.values
271 | nodes = hv.Dataset(Nodes, 'index')
272 |
273 | chord = hv.Chord((Links.loc[Links.value>0], nodes)).select( #Links.value>min_link[i]
274 | value=(Links.value.quantile(min_quantile), None))
275 | cmap_ct = pd.Series(color_dic)[chord.nodes.data['index'].values].values.tolist()
276 | chord.opts(
277 | opts.Chord(#cmap='Category20',
278 | edge_cmap=cmap_ct,
279 | edge_color=dim('source').str(),
280 | labels='name', node_color=dim('index').str(),
281 | node_cmap=cmap_ct,
282 | title = by_range))
283 | ls.append(chord)
284 |
285 | value = (len(long_pairs) * adata.uns['long'].value + len(short_pairs) * adata.uns['short'].value)/ \
286 | (len(long_pairs) + len(short_pairs))
287 | Links.value = value
288 | chord = hv.Chord((Links.loc[Links.value>0], nodes)).select( #Links.value>min_link[i]
289 | value=(Links.value.quantile(min_quantile), None))
290 | cmap_ct = pd.Series(color_dic)[chord.nodes.data['index'].values].values.tolist()
291 | chord.opts(
292 | opts.Chord(#cmap='Category20',
293 | edge_cmap=cmap_ct,
294 | edge_color=dim('source').str(),
295 | labels='name', node_color=dim('index').str(),
296 | node_cmap=cmap_ct,
297 | title = 'Cell_type_interactions_between_all_identified_pairs'))
298 | ls.append(chord)
299 |
300 | ar = np.array([hv.render(fig) for fig in ls])
301 | for n in ar:
302 | n.output_backend = "svg"
303 | plots = ar.reshape(-1, ncol).tolist()
304 | grid = gridplot(plots)
305 | if save is not None:
306 | file_format = save.split('.')[-1]
307 | if file_format == 'svg':
308 | export_svg(grid, filename=save)
309 | elif file_format == 'png':
310 | export_png(grid, filename=save)
311 | show(grid)
312 | return grid
313 |
314 |
315 | def plt_util(title):
316 | plt.xticks([])
317 | plt.yticks([])
318 | plt.title(title)
319 | plt.colorbar()
320 |
321 |
322 | def plot_selected_pair(sample, pair, spots, selected_ind, figsize, cmap, cmap_l, cmap_r, **kwargs):
323 | i = pd.Series(selected_ind == pair).idxmax()
324 | L = sample.uns['ligand'].loc[pair].dropna().values
325 | R = sample.uns['receptor'].loc[pair].dropna().values
326 | l1, l2 = len(L), len(R)
327 |
328 | if isinstance(sample.obsm['spatial'], pd.DataFrame):
329 | spatial_loc = sample.obsm['spatial'].values
330 | else:
331 | spatial_loc = sample.obsm['spatial']
332 |
333 | plt.figure(figsize=figsize)
334 | plt.subplot(1, 5, 1)
335 | plt.scatter(spatial_loc[:,0], spatial_loc[:,1], c=spots.loc[pair], cmap=cmap,
336 | vmax=1, **kwargs)
337 | plt_util('Moran: ' + str(sample.uns['local_stat']['n_spots'].loc[pair]) + ' spots')
338 |
339 | for l in range(l1):
340 | plt.subplot(1, 5, 2 + l)
341 | plt.scatter(spatial_loc[:,0], spatial_loc[:,1], c=sample[:,L[l]].X.toarray(),
342 | cmap=cmap_l, **kwargs)
343 | plt_util('Ligand: ' + L[l])
344 | for l in range(l2):
345 | plt.subplot(1, 5, 2 + l1 + l)
346 | plt.scatter(spatial_loc[:,0], spatial_loc[:,1], c=sample[:,R[l]].X.toarray(),
347 | cmap=cmap_r, **kwargs)
348 | plt_util('Receptor: ' + R[l])
349 |
350 | def plot_pairs(sample, pairs_to_plot, pdf=None, figsize=(35, 5),
351 | cmap='Greens', cmap_l='Reds', cmap_r='Reds', **kwargs):
352 | """
353 | plot selected spots as well as LR expression.
354 | :param sample: AnnData object.
355 | :param pairs_to_plot: list or arrays. pair name(s), should be from spatialdm_local pairs .
356 | :param pdf: str. pdf file prefix. save plots in a pdf file.
357 | :param figsize: figsize for each pair. Default to (35, 5).
358 | :param markersize: markersize for each spot. Default
359 | :param cmap: cmap for selected local spots.
360 | :param cmap_l: cmap for selected ligand. If None, no subplot for ligand expression.
361 | :param cmap_r: cmap for selected receptor. If None, no subplot for receptor expression
362 | :return: subplots of spatial scatter plots, 1 for local Moran p-values, others for the original expression values
363 | """
364 | if sample.uns['local_stat']['local_method'] == 'z-score':
365 | selected_ind = sample.uns['local_z_p'].index
366 | spots = 1 - sample.uns['local_z_p']
367 | if sample.uns['local_stat']['local_method'] == 'permutation':
368 | selected_ind = sample.uns['local_perm_p'].index
369 | spots = 1 - sample.uns['local_perm_p']
370 | if pdf != None:
371 | with PdfPages(pdf + '.pdf') as pdf:
372 | for pair in pairs_to_plot:
373 | plot_selected_pair(sample, pair, spots, selected_ind, figsize, cmap=cmap,
374 | cmap_l=cmap_l, cmap_r=cmap_r, **kwargs)
375 | pdf.savefig()
376 | plt.show()
377 | plt.close()
378 |
379 | else:
380 | for pair in pairs_to_plot:
381 | plot_selected_pair(sample, pair, spots, selected_ind, figsize, cmap=cmap,
382 | cmap_l=cmap_l, cmap_r=cmap_r, **kwargs)
383 | plt.show()
384 | plt.close()
385 |
386 | from matplotlib import gridspec
387 | def make_grid_spec(
388 | ax_or_figsize,
389 | nrows: int,
390 | ncols: int,
391 | wspace= None,
392 | hspace = None,
393 | width_ratios = None,
394 | height_ratios= None,
395 | ):
396 | kw = dict(
397 | wspace=wspace,
398 | hspace=hspace,
399 | width_ratios=width_ratios,
400 | height_ratios=height_ratios,
401 | )
402 | if isinstance(ax_or_figsize, tuple):
403 | fig = plt.figure(figsize=ax_or_figsize)
404 | return fig, gridspec.GridSpec(nrows, ncols, **kw)
405 | else:
406 | ax = ax_or_figsize
407 | ax.axis('off')
408 | ax.set_frame_on(False)
409 | ax.set_xticks([])
410 | ax.set_yticks([])
411 | return ax.figure, ax.get_subplotspec().subgridspec(nrows, ncols, **kw)
412 |
413 | def dot(pathway_res, figsize, markersize, pdf):
414 | for i, name in enumerate(pathway_res.pattern.unique()):
415 | fig, legend_gs = make_grid_spec(figsize,
416 | nrows=2, ncols=1,
417 | height_ratios=(4, 1))
418 | dotplot = fig.add_subplot(legend_gs[0])
419 | result1 = pathway_res.loc[pathway_res.pattern == name]
420 | result1 = result1.sort_values('selected', ascending=False)
421 | cts = result1.selected
422 | perc = result1.selected / result1['total_genes'].apply(len)
423 | value = -np.log10(result1.loc[:, 'fisher_p'].values)
424 | size = value * markersize
425 | im = dotplot.scatter(result1.selected.values, result1.index, c=perc.loc[result1.index].values,
426 | s=size, cmap='Reds')
427 | dotplot.set_xlabel('Number of pairs')
428 | dotplot.set_xticks(np.arange(0, max(result1.selected.values) + 2))
429 | dotplot.tick_params(axis='y', labelsize=10)
430 | dotplot.set_title(name)
431 | plt.colorbar(im, location='bottom', label='percentage of pairs out of CellChatDB')
432 | # dotplot.tight_layout()
433 |
434 | # plot size bar
435 | size_uniq = np.quantile(size, np.arange(1, 0, -0.1))
436 | value_uniq = np.quantile(value, np.arange(1, 0, -0.1))
437 | size_range = value_uniq
438 | size_legend_ax = fig.add_subplot(legend_gs[1])
439 | size_legend_ax.scatter(
440 | np.arange(len(size_uniq)) + 0.5,
441 | np.repeat(0, len(size_uniq)),
442 | s=size_uniq,
443 | color='gray',
444 | edgecolor='black',
445 | zorder=100,
446 | )
447 | size_legend_ax.set_xticks(np.arange(len(value_uniq)) + 0.5)
448 | # labels = [
449 | # "{}".format(np.round((x * 100), decimals=0).astype(int)) for x in size_range
450 | # ]
451 | size_legend_ax.set_xticklabels(np.round(np.exp(-value_uniq), 3),
452 | rotation=60, fontsize='small')
453 |
454 | # remove y ticks and labels
455 | size_legend_ax.tick_params(
456 | axis='y', left=False, labelleft=False, labelright=False
457 | )
458 |
459 | # remove surrounding lines
460 | size_legend_ax.spines['right'].set_visible(False)
461 | size_legend_ax.spines['top'].set_visible(False)
462 | size_legend_ax.spines['left'].set_visible(False)
463 | size_legend_ax.spines['bottom'].set_visible(False)
464 | size_legend_ax.grid(False)
465 |
466 | ymax = size_legend_ax.get_ylim()[1]
467 | size_legend_ax.set_title('fisher exact p-value (right tile)', y=ymax + 0.9, size='small')
468 |
469 | xmin, xmax = size_legend_ax.get_xlim()
470 | size_legend_ax.set_xlim(xmin - 0.15, xmax + 0.5)
471 | if pdf != None:
472 | pdf.savefig()
473 |
474 |
475 | def dot_path(pathway_res, cut_off=1, groups=None, markersize=50,
476 | figsize=(6, 8), pdf=None,
477 | **kwargs):
478 | """
479 | Either input a dict containing lists of interactions, or specify a dict key in adata.uns
480 | :param sample: AnnData object.
481 | :param uns_key: a dict key in adata.uns
482 | :param dic: a dict containing 1 or more list(s) of interactions
483 | :param cut_off: Minimum number of spots to be plotted.
484 | :param groups: subgroups from all dict keys.
485 | :param markersize:
486 | :param figsize:
487 | :param pdf: export pdf under your current directory
488 | :param kwargs:
489 | :return:
490 | """
491 | # plt.figure(figsize=figsize)
492 |
493 |
494 | pathway_res = pathway_res[pathway_res.selected >= cut_off]
495 | if groups is not None:
496 | pathway_res = pathway_res.loc[pathway_res.pattern.isin(groups)]
497 | n_subplot = len(pathway_res.pattern.unique())
498 | if pdf != None:
499 | with PdfPages(pdf + '.pdf') as pdf:
500 | dot(pathway_res, figsize, markersize, pdf)
501 | plt.show()
502 | plt.close()
503 | else:
504 | dot(pathway_res, figsize, markersize, pdf)
505 |
506 |
507 |
508 | def corr_plot(x, y, max_num=10000, outlier=0.01, line_on=True, method='spearman',
509 | legend_on=True, size=30, dot_color=None, outlier_color="r",
510 | alpha=0.8, color_rate=10, corr_on=None):
511 | """
512 | Please see hilearn package for more details
513 | x: `array_like`, (1, )
514 | Values on x-axis
515 | y: `array_like`, (1, )
516 | Values on y-axis
517 | max_num: int
518 | Maximum number of dots to plotting by subsampling
519 | outlier: float
520 | The proportion of dots as outliers in different color
521 | line_on : bool
522 | If True, show the regression line
523 | method: 'spearman' or 'pearson'
524 | Method for coefficient R computation
525 | legend_on: bool
526 | If True, show the Pearson's correlation coefficient in legend. Replace
527 | of *corr_on*
528 | size: float
529 | The dot size
530 | dot_color: string
531 | The dot color. If None (by default), density color will be use
532 | outlier_color: string
533 | The color for outlier dot
534 | alpha : float
535 | The transparency: 0 (fully transparent) to 1
536 | color_rate: float
537 | Color rate for density
538 | :return:
539 | ax: matplotlib Axes
540 | The Axes object containing the plot.
541 | """
542 | if method == 'pearson':
543 | score = stats.pearsonr(x, y)
544 | if method == 'spearman':
545 | score = stats.spearmanr(x, y)
546 | np.random.seed(0)
547 | if len(x) > max_num:
548 | idx = np.random.permutation(len(x))[:max_num]
549 | x, y = x[idx], y[idx]
550 | outlier = int(len(x) * outlier)
551 |
552 | xy = np.vstack([x, y])
553 | z = stats.gaussian_kde(xy)(xy)
554 | idx = z.argsort()
555 | idx1, idx2 = idx[outlier:], idx[:outlier]
556 |
557 | if dot_color is None:
558 | c_score = np.log2(z[idx] + color_rate * np.min(z[idx]))
559 | else:
560 | c_score = dot_color
561 |
562 | plt.set_cmap("Blues")
563 | plt.scatter(x[idx], y[idx], c=c_score, edgecolor=None, s=size, alpha=alpha)
564 | plt.scatter(x[idx2], y[idx2], c=outlier_color, edgecolor=None, s=size / 5,
565 | alpha=alpha / 3.0)
566 |
567 | if line_on:
568 | clf = linear_model.LinearRegression()
569 | clf.fit(x.reshape(-1, 1), y)
570 | xx = np.linspace(x.min(), x.max(), 1000).reshape(-1, 1)
571 | yy = clf.predict(xx)
572 | plt.plot(xx, yy, "k--", label="R=%.3f" % score[0])
573 |
574 | if legend_on or corr_on:
575 | plt.legend(loc="best", fancybox=True, ncol=1)
576 |
577 | def global_plot(sample, pairs=None, figsize=(3,4),loc=2, **kwarg):
578 | """
579 | overview of global selected pairs for a SpatialDM obj
580 | :param sample: AnnData object
581 | :param pairs: list
582 | list of pairs to be highlighted in the scatter plot, e.g. ['SPP1_CD44'] or ['SPP1_CD44','ANGPTL4_SDC2']
583 | :param figsize: tuple
584 | default to (3,4)
585 | :param kwarg: plt.scatter arguments
586 | :return: ax: matplotlib Axes.
587 | """
588 | if pairs is not None:
589 | color_codes = generate_colormap(max(10, len(pairs)+2))[2:]
590 | fig = plt.figure(figsize=figsize)
591 | ax = plt.axes()
592 | if sample.uns['global_stat']['method'] == 'permutation':
593 | p = 'perm_pval'
594 | elif sample.uns['global_stat']['method'] == 'z-score':
595 | p = 'z_pval'
596 | plt.scatter(np.log1p(sample.uns['global_I']), -np.log1p(sample.uns['global_res'][p]),
597 | c=sample.uns['global_res'].selected, **kwarg)
598 | if pairs!=None:
599 | for i,pair in enumerate(pairs):
600 | plt.scatter(np.log1p(sample.uns['global_I'])[sample.uns['ligand'].index==pair],
601 | -np.log1p(sample.uns['global_res'][p])[sample.uns['ligand'].index==pair],
602 | c=color_codes[i]) #TODO: perm pval only?
603 | plt.xlabel('log1p Global I')
604 | plt.ylabel('-log1p(pval)')
605 | ax.spines['top'].set_visible(False)
606 | ax.spines['right'].set_visible(False)
607 | plt.legend(np.hstack(([''], pairs)), loc=loc)
608 |
609 | def differential_dendrogram(sample):
610 | _range = np.arange(1, sample.uns['n_sub'])
611 | ax = sns.clustermap(1-sample.uns['p_df'].loc[(sample.uns['p_val']<0.1) & (sample.uns['tf_df'].sum(1).isin(_range)),
612 | sample.uns['subset']])
613 | return ax
614 |
615 | def differential_volcano(sample, pairs=None, legend=None, xmax = 25, xmin = -20):
616 | """
617 | Volcano plot for a differential obj
618 | :param sample: concatenated AnnData after running spatialdm separately
619 | :param pairs: list
620 | list of pairs to be highlighted in the volcano plot, e.g. ['SPP1_CD44'] or ['SPP1_CD44','ANGPTL4_SDC2']
621 | :param legend: list
622 | list of specified names for each side of the volcano plot
623 | :param xmax: float
624 | max z-score difference
625 | :param xmin: float
626 | min z-score difference
627 | :return: ax: matplotlib Axes.
628 | """
629 | if pairs is not None:
630 | color_codes = generate_colormap(max(10, len(pairs)+8))[8:]
631 | q1 = sample.uns['q1']
632 | q2 = sample.uns['q2']
633 | fdr_co = sample.uns['fdr_co']
634 |
635 | _range = np.arange(1, sample.uns['n_sub'])
636 | diff_cp = sample.uns['diff'].copy()
637 | diff_cp = np.where((diff_cp>xmax), xmax, diff_cp)
638 | diff_cp = np.where((diff_cpq1) & (sample.uns['diff_fdr']q1) & (sample.uns['diff_fdr'] 5000
68 | R_val = (spatial_W @ X * Y).sum(axis=0) / np.sum(spatial_W)
69 |
70 | _R_std = Moran_R_std(spatial_W)
71 | R_z_score = R_val / _R_std
72 | R_p_val = stats.norm.sf(R_z_score)
73 |
74 | return R_val, R_z_score, R_p_val
75 |
76 |
77 | # global variance
78 | def globle_st_compute(adata):
79 | N = adata.shape[0]
80 |
81 | if issparse(adata.obsp['weight']):
82 | nm = N ** 2 * adata.obsp['weight'].multiply(adata.obsp['weight'].T).sum() \
83 | - 2 * N * (adata.obsp['weight'].sum(0) @ adata.obsp['weight'].sum(1)).sum() \
84 | + adata.obsp['weight'].sum() ** 2
85 | nm0 = N ** 2 * adata.obsp['nearest_neighbors'].multiply(adata.obsp['nearest_neighbors'].T).sum() \
86 | - 2 * N * (adata.obsp['nearest_neighbors'].sum(0) @ adata.obsp['nearest_neighbors'].sum(1)).sum() \
87 | + adata.obsp['nearest_neighbors'].sum() ** 2
88 | else:
89 | nm = N ** 2 * (adata.obsp['weight'] * adata.obsp['weight'].T).sum() \
90 | - 2 * N * (adata.obsp['weight'].sum(1) * adata.obsp['weight'].sum(0)).sum() \
91 | + adata.obsp['weight'].sum() ** 2
92 | nm0 = N ** 2 * (adata.obsp['nearest_neighbors'] * adata.obsp['nearest_neighbors'].T).sum() \
93 | - 2 * N * (adata.obsp['nearest_neighbors'].sum(1) * adata.obsp['nearest_neighbors'].sum(0)).sum() \
94 | + adata.obsp['nearest_neighbors'].sum() ** 2
95 |
96 | dm = N ** 2 * (N - 1) ** 2
97 | var = np.hstack(
98 | (np.repeat(nm0, adata.uns['geneInter'].annotation.isin(['ECM-Receptor', 'Cell-Cell Contact']).sum()),
99 | np.repeat(nm, adata.uns['geneInter'].annotation.isin(['Secreted Signaling']).sum()))) / dm
100 | st = var ** (1 / 2)
101 | return st
102 |
103 | def global_I_compute(adata, L_mat, R_mat, n_short_lri, permute=False):
104 | """Calculate global I (i.e., R) values
105 | Make sure L_mat and R_mat are numpy.array not matrix
106 | """
107 | if permute:
108 | _idx = np.random.permutation(L_mat.shape[0])
109 | L_mat0, R_mat0 = L_mat[_idx, :n_short_lri], R_mat[_idx, :n_short_lri]
110 | L_mat1, R_mat1 = L_mat[_idx, n_short_lri:], R_mat[_idx, n_short_lri:]
111 | else:
112 | L_mat0, R_mat0 = L_mat[:, :n_short_lri], R_mat[:, :n_short_lri]
113 | L_mat1, R_mat1 = L_mat[:, n_short_lri:], R_mat[:, n_short_lri:]
114 |
115 | # Consider to dense array for speedup (numpy's codes is optimised)
116 | if adata.shape[0] >= 5000 or ~issparse(adata.obsp['weight']):
117 | RV = np.hstack((
118 | (adata.obsp['nearest_neighbors'] @ L_mat0 * R_mat0).sum(axis=0),
119 | (adata.obsp['weight'] @ L_mat1 * R_mat1).sum(axis=0)
120 | ))
121 | else:
122 | # Note, numpy may use unnessary too many threads
123 | # You may use threadpool.threadpool_limits() outside
124 | RV = np.hstack((
125 | (adata.obsp['nearest_neighbors'].A @ L_mat0 * R_mat0).sum(axis=0),
126 | (adata.obsp['weight'].A @ L_mat1 * R_mat1).sum(axis=0)
127 | ))
128 |
129 | return RV
130 |
131 |
132 | def generate_perm_tbl(adata, n_perm, num_spots):
133 | """shuffle neighbors for n_perm times by shuffling spot lables"""
134 | perm = np.zeros((n_perm, num_spots))
135 | perm = perm.astype(type(adata.obs_names.values[0]))
136 | mylist = list(adata.obs_names)
137 | for i in range(n_perm):
138 | random.shuffle(mylist)
139 | perm[i] = mylist
140 | return perm
141 |
142 |
143 | def compute_var_local(adata, sigma1_sq,sigma2_sq,wij_sq,n ,wii=1):
144 | if adata.uns['single_cell']:
145 | wii = 0
146 | var_I = (2 * (n-1)**2/n**2* wij_sq * sigma1_sq * sigma2_sq +
147 | 2 * (n-1)**2/n**2 * sigma1_sq * sigma2_sq * wii)
148 |
149 | std_I=var_I**(1/2)
150 | return std_I
151 |
152 | def _standardise(X, Local=False, axis=None):
153 | """Standardise an array
154 | """
155 | N = len(X)
156 | if type(X[0]) == csr_matrix:
157 | X = np.array([i.A[:,0] for i in X])
158 | # X = X.T
159 | if Local==False:
160 | X = X.T
161 | N = 1
162 | X = X - X.mean(axis=axis, keepdims=True)
163 | X = X / np.sqrt(np.sum(X**2, axis=axis, keepdims=True)/N)
164 | return X
165 |
166 |
167 | def pair_selection_matrix(adata, n_perm, sel_ind, method):
168 | if adata.uns['mean'] == 'geometric':
169 | from scipy.stats.mstats import gmean
170 | # local variables (only live in this function scope)
171 | ligand = adata.uns['ligand'].loc[sel_ind]
172 | receptor = adata.uns['receptor'].loc[sel_ind]
173 | type_interaction = adata.uns['geneInter'].loc[sel_ind, 'annotation']
174 | n_short_lri = (type_interaction != 'Secreted Signaling').sum()
175 |
176 | # averaged ligand values
177 | L1 = [pd.Series(x[0]).dropna().values for x in ligand.values]
178 | L_mat = [adata[:, L1[l]].X.astype(np.float64)[:, 0] for l in range(len(L1))]
179 | for i, k in enumerate(ligand.index):
180 | if len(ligand.loc[k].dropna()) > 1:
181 | if adata.uns['mean'] == 'geometric':
182 | L_mat[i] = gmean(adata[:, ligand.loc[k].dropna()].X, axis=1)
183 | else:
184 | L_mat[i] = adata[:, ligand.loc[k].dropna()].X.mean(1)
185 |
186 | # averaged receptor values
187 | R1 = [pd.Series(x[0]).dropna().values for x in receptor.values]
188 | R_mat = [adata[:, R1[r]].X.astype(np.float64)[:, 0] for r in range(len(R1))]
189 | for i, k in enumerate(receptor.index):
190 | if len(receptor.loc[k].dropna()) > 1:
191 | if adata.uns['mean'] == 'geometric':
192 | R_mat[i] = gmean(adata[:, receptor.loc[k].dropna()].X, axis=1)
193 | else:
194 | R_mat[i] = adata[:, receptor.loc[k].dropna()].X.mean(1)
195 |
196 | ## Check non-expressed pairs
197 | idx_use = np.array([(L_mat[i].sum() > 0) * (R_mat[i].sum() > 0) for i in range(len(L_mat))])
198 | if (np.mean(idx_use) < 1):
199 | print('Warning: some LR pairs have no expression.')
200 | adata.uns['ligand'] = ligand.loc[idx_use]
201 | adata.uns['receptor'] = receptor.loc[idx_use]
202 |
203 | if issparse(adata.X):
204 | L_mat = csc_matrix(hstack(L_mat)).T
205 | R_mat = csc_matrix(hstack(R_mat)).T
206 |
207 | # TODO: not support sparse matrix as intermediate results
208 | L_mat = L_mat.toarray()
209 | R_mat = R_mat.toarray()
210 | else:
211 | R_mat = np.array(R_mat)
212 | L_mat = np.array(L_mat)
213 |
214 | R_mat_use = _standardise(R_mat[idx_use], axis=0)
215 | L_mat_use = _standardise(L_mat[idx_use], axis=0)
216 | adata.uns['global_I'] = global_I_compute(adata, L_mat_use, R_mat_use, n_short_lri)
217 |
218 | ## Calculate p values
219 | if method in ['both', 'z-score']:
220 | adata.uns['global_stat']['z']['z'] = (
221 | adata.uns['global_I'] / adata.uns['global_stat']['z']['st'][idx_use])
222 | adata.uns['global_stat']['z']['z'] = adata.uns['global_stat']['z']['z'].astype(np.float64)
223 | adata.uns['global_stat']['z']['z_p'] = stats.norm.sf(
224 | adata.uns['global_stat']['z']['z'])
225 | if method in ['both', 'permutation']:
226 | adata.uns['global_stat']['perm']['global_perm'] = np.zeros((L_mat_use.shape[1], n_perm))
227 | for i in tqdm(range(n_perm)):
228 | ## NOTE: most heavy computation, consider speedup in future (e.g., in parallel or tensor)
229 | adata.uns['global_stat']['perm']['global_perm'][:, i] = global_I_compute(
230 | adata, L_mat_use, R_mat_use, n_short_lri, permute=True
231 | )
232 |
233 | def norm_max(X):
234 | if type(X)==csr_matrix:
235 | X=X.A[0]
236 | X = X/X.max()
237 | X=np.where(np.isnan(X), 0, X)
238 | return X
239 |
240 |
241 | def spot_selection_matrix(adata, ligand, receptor, ind, n_perm, method, scale_X=True):
242 | # local variables (only live in this function scope)
243 | # normalize raw counts
244 | raw_norm = adata.raw.to_adata()
245 | raw_norm.X = csr_matrix([norm_max(X) for X in raw_norm.X.T]).T
246 | import scanpy as sc
247 | if scale_X:
248 | sc.pp.scale(raw_norm, zero_center=False)
249 | if adata.uns['mean'] == 'geometric':
250 | from scipy.stats.mstats import gmean
251 | L1 = [pd.Series(x[0]).dropna().values for x in ligand.values]
252 | L_mat0 = [raw_norm[:, L1[l]].X.A.astype(np.float64)[:, 0] for l in range(len(L1))]
253 | for i, k in enumerate(ligand.index):
254 | if len(ligand.loc[k].dropna()) > 1:
255 | if adata.uns['mean'] == 'geometric':
256 | L_mat0[i] = gmean(raw_norm[:, ligand.loc[k].dropna()].X.A, axis=1)
257 | else:
258 | L_mat0[i] = raw_norm[:, ligand.loc[k].dropna()].X.A.mean(1)
259 |
260 | # averaged receptor values
261 | R1 = [pd.Series(x[0]).dropna().values for x in receptor.values]
262 | R_mat0 = [raw_norm[:, R1[r]].X.A.astype(np.float64)[:, 0] for r in range(len(R1))]
263 | for i, k in enumerate(receptor.index):
264 | if len(receptor.loc[k].dropna()) > 1:
265 | if adata.uns['mean'] == 'geometric':
266 | R_mat0[i] = gmean(raw_norm[:, receptor.loc[k].dropna()].X.A, axis=1)
267 | else:
268 | R_mat0[i] = raw_norm[:, receptor.loc[k].dropna()].X.A.mean(1)
269 | n_short_lri = (adata.uns['geneInter'].loc[ligand.index, 'annotation'] \
270 | != 'Secreted Signaling').sum()
271 | ranges = [np.arange(n_short_lri), np.arange(n_short_lri, len(L1))]
272 | weight_matrices = [adata.obsp['nearest_neighbors'], adata.obsp['weight']]
273 | N = adata.shape[0]
274 | L_mat0 = np.array(L_mat0)
275 | R_mat0 = np.array(R_mat0)
276 | pos = np.zeros((N, len(ligand)))
277 |
278 | for r, weight_matrix in zip(ranges, weight_matrices):
279 | if len(r) == 0:
280 | continue
281 | R_mat = R_mat0[r].T
282 | L_mat = L_mat0[r].T
283 | R_mat_use = _standardise(R_mat, Local=True, axis=0)
284 | L_mat_use = _standardise(L_mat, Local=True, axis=0)
285 | pos[:, r] = (L_mat_use > 0) + (R_mat_use > 0)
286 |
287 | if issparse(weight_matrix):
288 | wij_sq = weight_matrix.power(2).sum(1).A.reshape(-1)
289 | else:
290 | wij_sq = (weight_matrix ** 2).sum(1)
291 | rbf_d = csc_matrix(weight_matrix)
292 | adata.uns['local_stat']['local_I'][:, r] = (rbf_d @ R_mat_use) * L_mat_use
293 | adata.uns['local_stat']['local_I_R'][:, r] = (rbf_d @ L_mat_use) * R_mat_use
294 | ## Calculate p values
295 | if method in ['both', 'z-score']:
296 | norm_res1 = [stats.norm.fit(L_mat_use[:, i]) for i in range(L_mat_use.shape[1])]
297 | norm_res2 = [stats.norm.fit(R_mat_use[:, i]) for i in range(R_mat_use.shape[1])]
298 | norm_res1 = np.array(norm_res1)
299 | norm_res2 = np.array(norm_res2)
300 | mu1_ls, std_L_ls = norm_res1[:, 0], norm_res1[:, 1]
301 | mu2_ls, std_R_ls = norm_res2[:, 0], norm_res2[:, 1]
302 | sigma1_sq_ls = [(std1 * N / (N - 1)) for std1 in std_L_ls]
303 | sigma2_sq_ls = [(std2 * N / (N - 1)) for std2 in std_R_ls]
304 | std_ls = [compute_var_local(adata, sigma1_sq, sigma2_sq, wij_sq, N) \
305 | for (sigma1_sq, sigma2_sq) in zip(sigma1_sq_ls, sigma2_sq_ls)]
306 | adata.uns['local_z'][r] = (adata.uns['local_stat']['local_I'][:, r] + \
307 | adata.uns['local_stat']['local_I_R'][:, r]).T / std_ls
308 | adata.uns['local_z_p'][r] = stats.norm.sf(adata.uns['local_z'][r])
309 |
310 | if method in ['both', 'permutation']:
311 | for i in tqdm(range(n_perm)):
312 | _idx = np.random.permutation(L_mat.shape[0])
313 | adata.uns['local_stat']['local_permI'][r, i, :] = ((rbf_d @ R_mat_use[_idx, :]) * L_mat_use).T
314 | adata.uns['local_stat']['local_permI_R'][r, i, :] = ((rbf_d @ L_mat_use[_idx, :]) * R_mat_use).T
315 |
316 | try:
317 | adata.uns['local_z_p'] = np.where(pos.T == False, 1, adata.uns['local_z_p'])
318 | adata.uns['local_z_p'] = pd.DataFrame(adata.uns['local_z_p'], index=ind, columns=adata.obs_names)
319 | except Exception:
320 | pass
321 |
322 | try:
323 | adata.uns['local_perm_p'] = (np.expand_dims(adata.uns['local_stat']['local_I'].T + \
324 | adata.uns['local_stat']['local_I_R'].T, 1) <= \
325 | (adata.uns['local_stat']['local_permI'] + adata.uns['local_stat'][
326 | 'local_permI_R'])).sum(1) / n_perm
327 | adata.uns['local_perm_p'] = np.where(pos.T == False, 1, adata.uns['local_perm_p'])
328 | adata.uns['local_perm_p'] = pd.DataFrame(adata.uns['local_perm_p'], index=ind, columns=adata.obs_names)
329 | except Exception:
330 | pass
331 |
332 | # def compute_pathway(sample=None,
333 | # all_interactions=None,
334 | # interaction_ls=None, name=None, dic=None):
335 | # """
336 | # Compute enriched pathways for a list of pairs or a dic of SpatialDE results.
337 | # :param sample: spatialdm obj
338 | # :param ls: a list of LR interaction names for the enrichment analysis
339 | # :param path_name: str. For later recall sample.path_summary[path_name]
340 | # :param dic: a dic of SpatialDE results (See tutorial)
341 | # """
342 | # if interaction_ls is not None:
343 | # dic = {name: interaction_ls}
344 | # if sample is not None:
345 | # all_interactions = sample.uns['geneInter']
346 | # df = pd.DataFrame(all_interactions.groupby('pathway_name').interaction_name)
347 | # df = df.set_index(0)
348 | # total_feature_num = len(all_interactions)
349 | # result = []
350 | # for n,ls in dic.items():
351 | # qset = set([x.upper() for x in ls]).intersection(all_interactions.index)
352 | # query_set_size = len(qset)
353 | # for modulename, members in df.iterrows():
354 | # module_size = len(members.values[0])
355 | # overlap_features = qset.intersection(members.values[0])
356 | # overlap_size = len(overlap_features)
357 |
358 | # negneg = total_feature_num + overlap_size - module_size - query_set_size
359 | # # Fisher's exact test
360 | # p_FET = stats.fisher_exact([[overlap_size, query_set_size - overlap_size],
361 | # [module_size - overlap_size, negneg]], 'greater')[1]
362 | # result.append((p_FET, modulename, module_size, overlap_size, overlap_features, n))
363 | # result = pd.DataFrame(result).set_index(1)
364 | # result.columns = ['fisher_p', 'pathway_size', 'selected', 'selected_inters', 'name']
365 | # if sample is not None:
366 | # sample.uns['pathway_summary'] = result
367 | # return result
--------------------------------------------------------------------------------
/spatialdm/version.py:
--------------------------------------------------------------------------------
1 | __version__ = '0.2.0'
2 |
--------------------------------------------------------------------------------
/tutorial/simulation/ligand_recptor_pairs_sim.csv:
--------------------------------------------------------------------------------
1 | ,L,R1,R2
2 | 0,TGFB1,TGFBR1,TGFBR2
3 | 1,TGFB2,TGFBR1,TGFBR2
4 | 2,TGFB3,TGFBR1,TGFBR2
5 | 3,TGFB1,ACVR1B,TGFBR2
6 | 4,TGFB1,ACVR1C,TGFBR2
7 | 5,TGFB2,ACVR1B,TGFBR2
8 | 6,TGFB2,ACVR1C,TGFBR2
9 | 7,TGFB3,ACVR1B,TGFBR2
10 | 8,TGFB3,ACVR1C,TGFBR2
11 | 9,TGFB3,ACVR1C,TGFBR2
12 | 10,TGFB3,ACVR1C,TGFBR2
13 | 11,TGFB3,ACVR1C,TGFBR2
14 | 12,BMP2,BMPR1A,ACVR2A
15 | 13,BMP2,BMPR1A,ACVR2B
16 | 14,BMP2,BMPR1A,BMPR2
17 | 15,BMP2,ACVR2A,nan
18 | 16,BMP2,ACVR2B,nan
19 | 17,BMP2,BMPR2,nan
20 | 18,BMP4,BMPR1A,ACVR2A
21 | 19,BMP4,BMPR1A,ACVR2B
22 | 20,BMP4,BMPR1A,BMPR2
23 | 21,BMP4,ACVR2A,nan
24 | 22,BMP4,ACVR2B,nan
25 | 23,BMP4,BMPR2,nan
26 | 24,GDF6,BMPR1A,ACVR2A
27 | 25,GDF6,BMPR1A,ACVR2B
28 | 26,GDF6,BMPR1A,BMPR2
29 | 27,GDF6,ACVR2A,nan
30 | 28,GDF6,ACVR2B,nan
31 | 29,GDF6,BMPR2,nan
32 | 30,BMP5,ACVR1,ACVR2A
33 | 31,BMP5,ACVR1,ACVR2B
34 | 32,BMP5,ACVR1,BMPR2
35 | 33,BMP5,BMPR1A,ACVR2A
36 | 34,BMP5,BMPR1A,ACVR2B
37 | 35,BMP5,BMPR1A,BMPR2
38 | 36,BMP5,ACVR2A,nan
39 | 37,BMP5,ACVR2B,nan
40 | 38,BMP5,BMPR2,nan
41 | 39,BMP6,ACVR1,ACVR2A
42 | 40,BMP6,ACVR1,ACVR2B
43 | 41,BMP6,ACVR1,BMPR2
44 | 42,BMP6,BMPR1A,ACVR2A
45 | 43,BMP6,BMPR1A,ACVR2B
46 | 44,BMP6,BMPR1A,BMPR2
47 | 45,BMP6,ACVR2A,nan
48 | 46,BMP6,ACVR2B,nan
49 | 47,BMP6,BMPR2,nan
50 | 48,BMP8A,ACVR1,ACVR2A
51 | 49,BMP8A,ACVR1,ACVR2B
52 | 50,BMP8A,ACVR1,BMPR2
53 | 51,BMP8A,BMPR1A,ACVR2A
54 | 52,BMP8A,BMPR1A,ACVR2B
55 | 53,BMP8A,BMPR1A,BMPR2
56 | 54,BMP8A,ACVR2A,nan
57 | 55,BMP8A,ACVR2B,nan
58 | 56,BMP8A,BMPR2,nan
59 | 57,BMP8B,ACVR1,ACVR2A
60 | 58,BMP8B,ACVR1,ACVR2B
61 | 59,BMP8B,ACVR1,BMPR2
62 | 60,BMP8B,BMPR1A,ACVR2A
63 | 61,BMP8B,BMPR1A,ACVR2B
64 | 62,BMP8B,BMPR1A,BMPR2
65 | 63,BMP8B,ACVR2A,nan
66 | 64,BMP8B,ACVR2B,nan
67 | 65,BMP8B,BMPR2,nan
68 | 66,GDF9,ACVR1B,BMPR2
69 | 67,GDF10,ACVR1B,ACVR2A
70 | 68,GDF11,TGFBR1,ACVR2A
71 | 69,GDF11,TGFBR1,ACVR2B
72 | 70,GDF11,ACVR1B,ACVR2B
73 | 71,GDF15,TGFBR2,nan
74 | 72,AMH,ACVR1,nan
75 | 73,AMH,BMPR1A,nan
76 | 74,GDNF,GFRA1,nan
77 | 75,NRTN,GFRA2,nan
78 | 76,ARTN,GFRA3,nan
79 | 77,ARTN,GFRA1,nan
80 | 78,INHBA,ACVR1B,ACVR2A
81 | 79,INHBA,ACVR1B,ACVR2B
82 | 80,INHBB,ACVR1B,ACVR2A
83 | 81,INHBB,ACVR1B,ACVR2B
84 | 82,INHBB,ACVR1C,ACVR2A
85 | 83,INHBB,ACVR1C,ACVR2B
86 | 84,INHBB,ACVR1C,ACVR2B
87 | 85,INHBB,ACVR1C,ACVR2B
88 | 86,INHBB,ACVR1C,ACVR2B
89 | 87,INHBB,ACVR1C,ACVR2B
90 | 88,INHBB,ACVR1C,ACVR2B
91 | 89,INHBB,ACVR1C,ACVR2B
92 | 90,WNT10A,FZD1,LRP5
93 | 91,WNT10A,FZD10,LRP5
94 | 92,WNT10A,FZD2,LRP5
95 | 93,WNT10A,FZD3,LRP5
96 | 94,WNT10A,FZD4,LRP5
97 | 95,WNT10A,FZD5,LRP5
98 | 96,WNT10A,FZD6,LRP5
99 | 97,WNT10A,FZD7,LRP5
100 | 98,WNT10A,FZD8,LRP5
101 | 99,WNT10A,FZD9,LRP5
102 | 100,WNT16,FZD1,LRP5
103 | 101,WNT16,FZD10,LRP5
104 | 102,WNT16,FZD2,LRP5
105 | 103,WNT16,FZD3,LRP5
106 | 104,WNT16,FZD4,LRP5
107 | 105,WNT16,FZD5,LRP5
108 | 106,WNT16,FZD6,LRP5
109 | 107,WNT16,FZD7,LRP5
110 | 108,WNT16,FZD8,LRP5
111 | 109,WNT16,FZD9,LRP5
112 | 110,WNT2,FZD1,LRP5
113 | 111,WNT2,FZD10,LRP5
114 | 112,WNT2,FZD2,LRP5
115 | 113,WNT2,FZD3,LRP5
116 | 114,WNT2,FZD4,LRP5
117 | 115,WNT2,FZD5,LRP5
118 | 116,WNT2,FZD6,LRP5
119 | 117,WNT2,FZD7,LRP5
120 | 118,WNT2,FZD8,LRP5
121 | 119,WNT2,FZD9,LRP5
122 | 120,WNT2B,FZD1,LRP5
123 | 121,WNT2B,FZD10,LRP5
124 | 122,WNT2B,FZD2,LRP5
125 | 123,WNT2B,FZD3,LRP5
126 | 124,WNT2B,FZD4,LRP5
127 | 125,WNT2B,FZD5,LRP5
128 | 126,WNT2B,FZD6,LRP5
129 | 127,WNT2B,FZD7,LRP5
130 | 128,WNT2B,FZD8,LRP5
131 | 129,WNT2B,FZD9,LRP5
132 | 130,WNT4,FZD1,LRP5
133 | 131,WNT4,FZD10,LRP5
134 | 132,WNT4,FZD2,LRP5
135 | 133,WNT4,FZD3,LRP5
136 | 134,WNT4,FZD4,LRP5
137 | 135,WNT4,FZD5,LRP5
138 | 136,WNT4,FZD6,LRP5
139 | 137,WNT4,FZD7,LRP5
140 | 138,WNT4,FZD8,LRP5
141 | 139,WNT4,FZD9,LRP5
142 | 140,WNT6,FZD1,LRP5
143 | 141,WNT6,FZD10,LRP5
144 | 142,WNT6,FZD2,LRP5
145 | 143,WNT6,FZD3,LRP5
146 | 144,WNT6,FZD4,LRP5
147 | 145,WNT6,FZD5,LRP5
148 | 146,WNT6,FZD6,LRP5
149 | 147,WNT6,FZD7,LRP5
150 | 148,WNT6,FZD8,LRP5
151 | 149,WNT6,FZD9,LRP5
152 | 150,WNT9A,FZD1,LRP5
153 | 151,WNT9A,FZD10,LRP5
154 | 152,WNT9A,FZD2,LRP5
155 | 153,WNT9A,FZD3,LRP5
156 | 154,WNT9A,FZD4,LRP5
157 | 155,WNT9A,FZD5,LRP5
158 | 156,WNT9A,FZD6,LRP5
159 | 157,WNT9A,FZD7,LRP5
160 | 158,WNT9A,FZD8,LRP5
161 | 159,WNT9A,FZD9,LRP5
162 | 160,WNT10A,FZD1,LRP6
163 | 161,WNT10A,FZD10,LRP6
164 | 162,WNT10A,FZD2,LRP6
165 | 163,WNT10A,FZD3,LRP6
166 | 164,WNT10A,FZD4,LRP6
167 | 165,WNT10A,FZD5,LRP6
168 | 166,WNT10A,FZD6,LRP6
169 | 167,WNT10A,FZD7,LRP6
170 | 168,WNT10A,FZD8,LRP6
171 | 169,WNT10A,FZD9,LRP6
172 | 170,WNT16,FZD1,LRP6
173 | 171,WNT16,FZD10,LRP6
174 | 172,WNT16,FZD2,LRP6
175 | 173,WNT16,FZD3,LRP6
176 | 174,WNT16,FZD4,LRP6
177 | 175,WNT16,FZD5,LRP6
178 | 176,WNT16,FZD6,LRP6
179 | 177,WNT16,FZD7,LRP6
180 | 178,WNT16,FZD8,LRP6
181 | 179,WNT16,FZD9,LRP6
182 | 180,WNT2,FZD1,LRP6
183 | 181,WNT2,FZD10,LRP6
184 | 182,WNT2,FZD2,LRP6
185 | 183,WNT2,FZD3,LRP6
186 | 184,WNT2,FZD4,LRP6
187 | 185,WNT2,FZD5,LRP6
188 | 186,WNT2,FZD6,LRP6
189 | 187,WNT2,FZD7,LRP6
190 | 188,WNT2,FZD8,LRP6
191 | 189,WNT2,FZD9,LRP6
192 | 190,WNT2B,FZD1,LRP6
193 | 191,WNT2B,FZD10,LRP6
194 | 192,WNT2B,FZD2,LRP6
195 | 193,WNT2B,FZD3,LRP6
196 | 194,WNT2B,FZD4,LRP6
197 | 195,WNT2B,FZD5,LRP6
198 | 196,WNT2B,FZD6,LRP6
199 | 197,WNT2B,FZD7,LRP6
200 | 198,WNT2B,FZD8,LRP6
201 | 199,WNT2B,FZD9,LRP6
202 | 200,WNT4,FZD1,LRP6
203 | 201,WNT4,FZD10,LRP6
204 | 202,WNT4,FZD2,LRP6
205 | 203,WNT4,FZD3,LRP6
206 | 204,WNT4,FZD4,LRP6
207 | 205,WNT4,FZD5,LRP6
208 | 206,WNT4,FZD6,LRP6
209 | 207,WNT4,FZD7,LRP6
210 | 208,WNT4,FZD8,LRP6
211 | 209,WNT4,FZD9,LRP6
212 | 210,WNT6,FZD1,LRP6
213 | 211,WNT6,FZD10,LRP6
214 | 212,WNT6,FZD2,LRP6
215 | 213,WNT6,FZD3,LRP6
216 | 214,WNT6,FZD4,LRP6
217 | 215,WNT6,FZD5,LRP6
218 | 216,WNT6,FZD6,LRP6
219 | 217,WNT6,FZD7,LRP6
220 | 218,WNT6,FZD8,LRP6
221 | 219,WNT6,FZD9,LRP6
222 | 220,WNT9A,FZD1,LRP6
223 | 221,WNT9A,FZD10,LRP6
224 | 222,WNT9A,FZD2,LRP6
225 | 223,WNT9A,FZD3,LRP6
226 | 224,WNT9A,FZD4,LRP6
227 | 225,WNT9A,FZD5,LRP6
228 | 226,WNT9A,FZD6,LRP6
229 | 227,WNT9A,FZD7,LRP6
230 | 228,WNT9A,FZD8,LRP6
231 | 229,WNT9A,FZD9,LRP6
232 | 230,WNT5A,FZD1,nan
233 | 231,WNT5A,FZD10,nan
234 | 232,WNT5A,FZD2,nan
235 | 233,WNT5A,FZD3,nan
236 | 234,WNT5A,FZD4,nan
237 | 235,WNT5A,FZD5,nan
238 | 236,WNT5A,FZD6,nan
239 | 237,WNT5A,FZD7,nan
240 | 238,WNT5A,FZD8,nan
241 | 239,WNT5A,FZD9,nan
242 | 240,WNT5A,MCAM,nan
243 | 241,WNT5B,FZD1,nan
244 | 242,WNT5B,FZD10,nan
245 | 243,WNT5B,FZD2,nan
246 | 244,WNT5B,FZD3,nan
247 | 245,WNT5B,FZD4,nan
248 | 246,WNT5B,FZD5,nan
249 | 247,WNT5B,FZD6,nan
250 | 248,WNT5B,FZD7,nan
251 | 249,WNT5B,FZD8,nan
252 | 250,WNT5B,FZD9,nan
253 | 251,WNT11,FZD1,nan
254 | 252,WNT11,FZD10,nan
255 | 253,WNT11,FZD2,nan
256 | 254,WNT11,FZD3,nan
257 | 255,WNT11,FZD4,nan
258 | 256,WNT11,FZD5,nan
259 | 257,WNT11,FZD6,nan
260 | 258,WNT11,FZD7,nan
261 | 259,WNT11,FZD8,nan
262 | 260,WNT11,FZD9,nan
263 | 261,TGFA,EGFR,nan
264 | 262,TGFA,EGFR,ERBB2
265 | 263,BTC,EGFR,nan
266 | 264,BTC,EGFR,ERBB2
267 | 265,BTC,ERBB4,nan
268 | 266,BTC,ERBB2,ERBB4
269 | 267,HBEGF,EGFR,nan
270 | 268,HBEGF,EGFR,ERBB2
271 | 269,HBEGF,ERBB4,nan
272 | 270,HBEGF,ERBB2,ERBB4
273 | 271,NRG2,ERBB3,nan
274 | 272,NRG2,ERBB2,ERBB3
275 | 273,NRG2,ERBB4,nan
276 | 274,NRG2,ERBB2,ERBB4
277 | 275,NRG3,ERBB4,nan
278 | 276,NRG3,ERBB2,ERBB4
279 | 277,FGF1,FGFR1,nan
280 | 278,FGF1,FGFR2,nan
281 | 279,FGF1,FGFR3,nan
282 | 280,FGF1,FGFR4,nan
283 | 281,FGF2,FGFR1,nan
284 | 282,FGF2,FGFR2,nan
285 | 283,FGF2,FGFR3,nan
286 | 284,FGF2,FGFR4,nan
287 | 285,FGF7,FGFR1,nan
288 | 286,FGF7,FGFR2,nan
289 | 287,FGF18,FGFR1,nan
290 | 288,FGF18,FGFR2,nan
291 | 289,FGF18,FGFR3,nan
292 | 290,FGF18,FGFR4,nan
293 | 291,FGF9,FGFR1,nan
294 | 292,FGF9,FGFR2,nan
295 | 293,FGF9,FGFR3,nan
296 | 294,FGF9,FGFR4,nan
297 | 295,PDGFA,PDGFRA,nan
298 | 296,PDGFA,PDGFRB,nan
299 | 297,PDGFB,PDGFRA,nan
300 | 298,PDGFB,PDGFRB,nan
301 | 299,PDGFC,PDGFRA,nan
302 | 300,PDGFD,PDGFRB,nan
303 | 301,VEGFA,FLT1,nan
304 | 302,VEGFA,KDR,nan
305 | 303,VEGFB,FLT1,nan
306 | 304,VEGFC,FLT4,nan
307 | 305,VEGFC,KDR,nan
308 | 306,PGF,FLT1,nan
309 | 307,VEGFA,FLT1,KDR
310 | 308,VEGFC,FLT4,KDR
311 | 309,IGF1,IGF1R,nan
312 | 310,IGF2,IGF1R,nan
313 | 311,IGF2,IGF2R,nan
314 | 312,IGF1,ITGAV,ITGB3
315 | 313,IGF1,ITGA6,ITGB4
316 | 314,IGF2,ITGAV,ITGB3
317 | 315,IGF2,ITGA6,ITGB4
318 | 316,APLN,APLNR,nan
319 | 317,DHH,PTCH1,SMO
320 | 318,DHH,PTCH2,SMO
321 | 319,CCL5,CCR1,nan
322 | 320,CCL3,CCR1,nan
323 | 321,CCL3L3,CCR1,nan
324 | 322,CCL8,CCR1,nan
325 | 323,CCL7,CCR1,nan
326 | 324,CCL13,CCR1,nan
327 | 325,CCL8,CCR2,nan
328 | 326,CCL7,CCR2,nan
329 | 327,CCL2,CCR2,nan
330 | 328,CCL27,CCR2,nan
331 | 329,CCL4,CCR5,nan
332 | 330,CCL5,CCR5,nan
333 | 331,CCL3,CCR5,nan
334 | 332,CCL20,CCR6,nan
335 | 333,CCL19,CCR7,nan
336 | 334,CCL21,CCR7,nan
337 | 335,CCL19,ACKR4,nan
338 | 336,CCL21,ACKR4,nan
339 | 337,CCL28,CCR10,nan
340 | 338,CCL27,CCR10,nan
341 | 339,CCL13,ACKR4,nan
342 | 340,CCL8,ACKR4,nan
343 | 341,CCL2,ACKR1,nan
344 | 342,CCL5,ACKR1,nan
345 | 343,CCL8,ACKR1,nan
346 | 344,CCL13,ACKR1,nan
347 | 345,CCL18,ACKR1,nan
348 | 346,CXCL1,ACKR1,nan
349 | 347,CXCL2,ACKR1,nan
350 | 348,CXCL5,ACKR1,nan
351 | 349,CXCL8,ACKR1,nan
352 | 350,CXCL9,ACKR1,nan
353 | 351,CXCL10,ACKR1,nan
354 | 352,CXCL11,ACKR1,nan
355 | 353,CXCL13,ACKR1,nan
356 | 354,CCL2,ACKR2,nan
357 | 355,CCL3,ACKR2,nan
358 | 356,CCL4,ACKR2,nan
359 | 357,CCL5,ACKR2,nan
360 | 358,CCL7,ACKR2,nan
361 | 359,CCL8,ACKR2,nan
362 | 360,CCL7,ACKR1,nan
363 | 361,CCL11,ACKR1,nan
364 | 362,CCL11,ACKR2,nan
365 | 363,CCL13,ACKR2,nan
366 | 364,CCL22,ACKR2,nan
367 | 365,CCL24,ACKR2,nan
368 | 366,CCL26,ACKR2,nan
369 | 367,CCL17,ACKR1,nan
370 | 368,CCL17,ACKR2,nan
371 | 369,CXCL1,CXCR2,nan
372 | 370,CXCL2,CXCR2,nan
373 | 371,CXCL5,CXCR2,nan
374 | 372,CXCL8,CXCR2,nan
375 | 373,CXCL9,CXCR3,nan
376 | 374,CXCL10,CXCR3,nan
377 | 375,CXCL11,CXCR3,nan
378 | 376,CXCL13,CXCR3,nan
379 | 377,CXCL12,CXCR4,nan
380 | 378,CXCL11,ACKR3,nan
381 | 379,CXCL12,ACKR3,nan
382 | 380,CXCL16,CXCR6,nan
383 | 381,MIF,CD74,CXCR4
384 | 382,MIF,CD74,CD44
385 | 383,MIF,CD74,CXCR2
386 | 384,MIF,ACKR3,nan
387 | 385,CX3CL1,CX3CR1,nan
388 | 386,XCL1,XCR1,nan
389 | 387,IL7,IL7R,IL2RG
390 | 388,IL7,IL7R,IL2RG
391 | 389,IL6,IL6R,IL6ST
392 | 390,IL11,IL11RA,IL6ST
393 | 391,IL23A,IL12RB1,nan
394 | 392,IL23A,IL12RB1,nan
395 | 393,CLCF1,LIFR,IL6ST
396 | 394,CTF1,LIFR,IL6ST
397 | 395,LIF,LIFR,IL6ST
398 | 396,OSM,LIFR,IL6ST
399 | 397,OSM,OSMR,IL6ST
400 | 398,IL10,IL10RA,IL10RB
401 | 399,IL24,IL20RB,nan
402 | 400,IL24,IL20RB,nan
403 | 401,IL1B,IL1R1,IL1RAP
404 | 402,IL1B,IL1R2,nan
405 | 403,IL18,IL18R1,IL18RAP
406 | 404,IL33,IL1RAP,nan
407 | 405,IL17B,IL17RB,nan
408 | 406,IL17C,IL17RA,IL17RE
409 | 407,IL25,IL17RA,IL17RB
410 | 408,IL34,CSF1R,nan
411 | 409,CSF1,CSF1R,nan
412 | 410,IL16,CD4,nan
413 | 411,GH1,GHR,nan
414 | 412,CSF3,CSF3R,nan
415 | 413,IFNW1,IFNAR1,IFNAR2
416 | 414,IFNG,IFNGR1,IFNGR2
417 | 415,TNF,TNFRSF1A,nan
418 | 416,TNF,TNFRSF1B,nan
419 | 417,LTA,TNFRSF1A,nan
420 | 418,LTA,TNFRSF1B,nan
421 | 419,LTA,TNFRSF14,nan
422 | 420,LTA,TNFRSF14,nan
423 | 421,TNFSF14,LTBR,nan
424 | 422,TNFSF14,TNFRSF14,nan
425 | 423,FASLG,FAS,nan
426 | 424,TNFSF15,TNFRSF25,nan
427 | 425,TNFSF10,TNFRSF10A,nan
428 | 426,NGF,NGFR,nan
429 | 427,TNFSF11,TNFRSF11A,nan
430 | 428,TNFSF11,TNFRSF11B,nan
431 | 429,TNFSF12,TNFRSF12A,nan
432 | 430,CD70,CD27,nan
433 | 431,TNFSF8,TNFRSF8,nan
434 | 432,TNFSF9,TNFRSF9,nan
435 | 433,TNFSF4,TNFRSF4,nan
436 | 434,TNFSF18,TNFRSF18,nan
437 | 435,TNFSF13B,TNFRSF17,nan
438 | 436,TNFSF13B,TNFRSF13B,nan
439 | 437,TNFSF13B,TNFRSF13C,nan
440 | 438,CD40LG,ITGB3,nan
441 | 439,CD40LG,ITGA5,ITGB1
442 | 440,CD40LG,ITGAM,ITGB2
443 | 441,SPP1,CD44,nan
444 | 442,SPP1,ITGAV,ITGB3
445 | 443,SPP1,ITGAV,ITGB1
446 | 444,SPP1,ITGAV,ITGB5
447 | 445,SPP1,ITGAV,ITGB6
448 | 446,SPP1,ITGA4,ITGB1
449 | 447,SPP1,ITGA9,ITGB1
450 | 448,SPP1,ITGA8,ITGB1
451 | 449,SPP1,ITGA5,ITGB1
452 | 450,ADIPOQ,ADIPOR1,nan
453 | 451,ADIPOQ,ADIPOR2,nan
454 | 452,RETN,TLR4,nan
455 | 453,RETN,CAP1,nan
456 | 454,NAMPT,INSR,nan
457 | 455,NAMPT,ITGA5,ITGB1
458 | 456,ANGPTL1,ITGA1,ITGB1
459 | 457,ANGPTL2,ITGA5,ITGB1
460 | 458,ANGPTL2,TLR4,nan
461 | 459,ANGPTL2,LILRB3,nan
462 | 460,ANGPTL1,LILRB3,nan
463 | 461,ANGPTL7,LILRB3,nan
464 | 462,ANGPTL4,ITGA5,ITGB1
465 | 463,ANGPTL4,ITGAV,ITGB3
466 | 464,ANGPTL4,CDH5,nan
467 | 465,ANGPTL4,CDH11,nan
468 | 466,ANGPTL4,SDC1,nan
469 | 467,ANGPTL4,SDC2,nan
470 | 468,ANGPTL4,SDC3,nan
471 | 469,ANGPTL4,SDC4,nan
472 | 470,ANGPT1,TEK,nan
473 | 471,ANGPT2,TEK,nan
474 | 472,ANGPT2,ITGA5,ITGB1
475 | 473,MDK,SDC1,nan
476 | 474,MDK,SDC2,nan
477 | 475,MDK,SDC4,nan
478 | 476,MDK,PTPRZ1,nan
479 | 477,MDK,ITGA4,ITGB1
480 | 478,MDK,ITGA6,ITGB1
481 | 479,MDK,LRP1,nan
482 | 480,MDK,NCL,nan
483 | 481,MDK,ALK,nan
484 | 482,PTN,PTPRZ1,nan
485 | 483,PTN,SDC1,nan
486 | 484,PTN,SDC2,nan
487 | 485,PTN,SDC3,nan
488 | 486,PTN,SDC4,nan
489 | 487,PTN,ITGAV,ITGB3
490 | 488,PTN,NCL,nan
491 | 489,PTN,ALK,nan
492 | 490,POSTN,ITGAV,ITGB3
493 | 491,POSTN,ITGAV,ITGB5
494 | 492,AGT,AGTR1,nan
495 | 493,C3,C3AR1,nan
496 | 494,C3,CR2,nan
497 | 495,C3,ITGAM,ITGB2
498 | 496,C3,ITGAX,ITGB2
499 | 497,C4A,C3AR1,nan
500 | 498,C4A,CR2,nan
501 | 499,C5,C5AR1,nan
502 | 500,EDN1,EDNRA,nan
503 | 501,EDN1,EDNRB,nan
504 | 502,POMC,MC1R,nan
505 | 503,PYY,NPY1R,nan
506 | 504,PYY,NPY2R,nan
507 | 505,PYY,NPY5R,nan
508 | 506,NTS,NTSR1,nan
509 | 507,POMC,OPRL1,nan
510 | 508,CORT,SSTR2,nan
511 | 509,CORT,SSTR3,nan
512 | 510,TAC4,TACR1,nan
513 | 511,CTSG,F2R,nan
514 | 512,GZMA,F2R,nan
515 | 513,CTSG,F2RL1,nan
516 | 514,GZMA,F2RL1,nan
517 | 515,CTSG,F2RL2,nan
518 | 516,GZMA,F2RL2,nan
519 | 517,CTSG,F2RL3,nan
520 | 518,GZMA,F2RL3,nan
521 | 519,CTSG,PARD3,nan
522 | 520,GZMA,PARD3,nan
523 | 521,NPPA,NPR1,nan
524 | 522,NPPC,NPR2,nan
525 | 523,KITLG,KIT,nan
526 | 524,BDNF,NTRK2,nan
527 | 525,NGF,NTRK1,nan
528 | 526,FLT3LG,FLT3,nan
529 | 527,HGF,MET,nan
530 | 528,SEMA3A,NRP1,PLXNA1
531 | 529,SEMA3A,NRP1,PLXNA2
532 | 530,SEMA3A,NRP1,PLXNA3
533 | 531,SEMA3A,NRP1,PLXNA4
534 | 532,SEMA3B,NRP1,PLXNA1
535 | 533,SEMA3B,NRP1,PLXNA2
536 | 534,SEMA3B,NRP1,PLXNA3
537 | 535,SEMA3B,NRP1,PLXNA4
538 | 536,SEMA3C,NRP1,PLXNA1
539 | 537,SEMA3C,NRP1,PLXNA2
540 | 538,SEMA3C,NRP1,PLXNA3
541 | 539,SEMA3C,NRP1,PLXNA4
542 | 540,SEMA3D,NRP1,PLXNA1
543 | 541,SEMA3D,NRP1,PLXNA2
544 | 542,SEMA3D,NRP1,PLXNA3
545 | 543,SEMA3D,NRP1,PLXNA4
546 | 544,SEMA3B,NRP2,PLXNA1
547 | 545,SEMA3B,NRP2,PLXNA2
548 | 546,SEMA3B,NRP2,PLXNA3
549 | 547,SEMA3B,NRP2,PLXNA4
550 | 548,SEMA3C,NRP2,PLXNA1
551 | 549,SEMA3C,NRP2,PLXNA2
552 | 550,SEMA3C,NRP2,PLXNA3
553 | 551,SEMA3C,NRP2,PLXNA4
554 | 552,SEMA3D,NRP2,PLXNA1
555 | 553,SEMA3D,NRP2,PLXNA2
556 | 554,SEMA3D,NRP2,PLXNA3
557 | 555,SEMA3D,NRP2,PLXNA4
558 | 556,SEMA3F,NRP2,PLXNA1
559 | 557,SEMA3F,NRP2,PLXNA2
560 | 558,SEMA3F,NRP2,PLXNA3
561 | 559,SEMA3F,NRP2,PLXNA4
562 | 560,SEMA3F,NRP2,PLXNA4
563 | 561,SEMA3C,PLXND1,nan
564 | 562,SEMA3E,PLXND1,nan
565 | 563,ADM,CALCRL,nan
566 | 564,ANXA1,FPR2,nan
567 | 565,ANXA1,FPR1,nan
568 | 566,ENHO,GPR19,nan
569 | 567,GAS6,AXL,nan
570 | 568,GAS6,MERTK,nan
571 | 569,GAS6,TYRO3,nan
572 | 570,GH1,GHR,nan
573 | 571,GH1,PRLR,nan
574 | 572,GRN,SORT1,nan
575 | 573,LGALS9,PTPRC,nan
576 | 574,OSTN,NPR3,nan
577 | 575,PROS1,AXL,nan
578 | 576,PROS1,TYRO3,nan
579 | 577,PSAP,GPR37,nan
580 | 578,PTHLH,PTH1R,nan
581 | 579,RARRES2,GPR1,nan
582 | 580,RARRES2,CMKLR1,nan
583 | 581,SAA1,FPR2,nan
584 | 582,BTLA,TNFRSF14,nan
585 | 583,BAG6,NCR3,nan
586 | 584,LGALS9,HAVCR2,nan
587 | 585,LGALS9,CD44,nan
588 | 586,COL1A1,ITGA1,ITGB1
589 | 587,COL1A2,ITGA1,ITGB1
590 | 588,COL2A1,ITGA1,ITGB1
591 | 589,COL4A1,ITGA1,ITGB1
592 | 590,COL4A2,ITGA1,ITGB1
593 | 591,COL4A3,ITGA1,ITGB1
594 | 592,COL4A4,ITGA1,ITGB1
595 | 593,COL4A5,ITGA1,ITGB1
596 | 594,COL6A1,ITGA1,ITGB1
597 | 595,COL6A2,ITGA1,ITGB1
598 | 596,COL6A3,ITGA1,ITGB1
599 | 597,COL6A6,ITGA1,ITGB1
600 | 598,COL9A1,ITGA1,ITGB1
601 | 599,COL9A2,ITGA1,ITGB1
602 | 600,COL9A3,ITGA1,ITGB1
603 | 601,COL1A1,ITGA2,ITGB1
604 | 602,COL1A2,ITGA2,ITGB1
605 | 603,COL2A1,ITGA2,ITGB1
606 | 604,COL4A1,ITGA2,ITGB1
607 | 605,COL4A2,ITGA2,ITGB1
608 | 606,COL4A3,ITGA2,ITGB1
609 | 607,COL4A4,ITGA2,ITGB1
610 | 608,COL4A5,ITGA2,ITGB1
611 | 609,COL6A1,ITGA2,ITGB1
612 | 610,COL6A2,ITGA2,ITGB1
613 | 611,COL6A3,ITGA2,ITGB1
614 | 612,COL6A6,ITGA2,ITGB1
615 | 613,COL9A1,ITGA2,ITGB1
616 | 614,COL9A2,ITGA2,ITGB1
617 | 615,COL9A3,ITGA2,ITGB1
618 | 616,FN1,ITGA3,ITGB1
619 | 617,FN1,ITGA4,ITGB1
620 | 618,FN1,ITGA5,ITGB1
621 | 619,FN1,ITGA8,ITGB1
622 | 620,LAMA1,ITGA1,ITGB1
623 | 621,LAMA2,ITGA1,ITGB1
624 | 622,LAMA3,ITGA1,ITGB1
625 | 623,LAMA4,ITGA1,ITGB1
626 | 624,LAMA5,ITGA1,ITGB1
627 | 625,LAMB1,ITGA1,ITGB1
628 | 626,LAMB2,ITGA1,ITGB1
629 | 627,LAMB3,ITGA1,ITGB1
630 | 628,LAMC1,ITGA1,ITGB1
631 | 629,LAMC2,ITGA1,ITGB1
632 | 630,LAMC3,ITGA1,ITGB1
633 | 631,LAMA1,ITGA2,ITGB1
634 | 632,LAMA2,ITGA2,ITGB1
635 | 633,LAMA3,ITGA2,ITGB1
636 | 634,LAMA4,ITGA2,ITGB1
637 | 635,LAMA5,ITGA2,ITGB1
638 | 636,LAMB1,ITGA2,ITGB1
639 | 637,LAMB2,ITGA2,ITGB1
640 | 638,LAMB3,ITGA2,ITGB1
641 | 639,LAMC1,ITGA2,ITGB1
642 | 640,LAMC2,ITGA2,ITGB1
643 | 641,LAMC3,ITGA2,ITGB1
644 | 642,LAMA1,ITGA3,ITGB1
645 | 643,LAMA2,ITGA3,ITGB1
646 | 644,LAMA3,ITGA3,ITGB1
647 | 645,LAMA4,ITGA3,ITGB1
648 | 646,LAMA5,ITGA3,ITGB1
649 | 647,LAMB1,ITGA3,ITGB1
650 | 648,LAMB2,ITGA3,ITGB1
651 | 649,LAMB3,ITGA3,ITGB1
652 | 650,LAMC1,ITGA3,ITGB1
653 | 651,LAMC2,ITGA3,ITGB1
654 | 652,LAMC3,ITGA3,ITGB1
655 | 653,RELN,ITGA3,ITGB1
656 | 654,THBS1,ITGA3,ITGB1
657 | 655,THBS2,ITGA3,ITGB1
658 | 656,THBS3,ITGA3,ITGB1
659 | 657,THBS4,ITGA3,ITGB1
660 | 658,COMP,ITGA3,ITGB1
661 | 659,COL1A1,ITGA3,ITGB1
662 | 660,COL1A2,ITGA3,ITGB1
663 | 661,COL2A1,ITGA3,ITGB1
664 | 662,COL4A1,ITGA3,ITGB1
665 | 663,COL4A2,ITGA3,ITGB1
666 | 664,COL4A3,ITGA3,ITGB1
667 | 665,COL4A4,ITGA3,ITGB1
668 | 666,COL4A5,ITGA3,ITGB1
669 | 667,COL6A1,ITGA3,ITGB1
670 | 668,COL6A2,ITGA3,ITGB1
671 | 669,COL6A3,ITGA3,ITGB1
672 | 670,COL6A6,ITGA3,ITGB1
673 | 671,COL9A1,ITGA3,ITGB1
674 | 672,COL9A2,ITGA3,ITGB1
675 | 673,COL9A3,ITGA3,ITGB1
676 | 674,LAMA1,ITGA6,ITGB1
677 | 675,LAMA2,ITGA6,ITGB1
678 | 676,LAMA3,ITGA6,ITGB1
679 | 677,LAMA4,ITGA6,ITGB1
680 | 678,LAMA5,ITGA6,ITGB1
681 | 679,LAMB1,ITGA6,ITGB1
682 | 680,LAMB2,ITGA6,ITGB1
683 | 681,LAMB3,ITGA6,ITGB1
684 | 682,LAMC1,ITGA6,ITGB1
685 | 683,LAMC2,ITGA6,ITGB1
686 | 684,LAMC3,ITGA6,ITGB1
687 | 685,LAMA1,ITGA7,ITGB1
688 | 686,LAMA2,ITGA7,ITGB1
689 | 687,LAMA3,ITGA7,ITGB1
690 | 688,LAMA4,ITGA7,ITGB1
691 | 689,LAMA5,ITGA7,ITGB1
692 | 690,LAMB1,ITGA7,ITGB1
693 | 691,LAMB2,ITGA7,ITGB1
694 | 692,LAMB3,ITGA7,ITGB1
695 | 693,LAMC1,ITGA7,ITGB1
696 | 694,LAMC2,ITGA7,ITGB1
697 | 695,LAMC3,ITGA7,ITGB1
698 | 696,VTN,ITGA8,ITGB1
699 | 697,TNC,ITGA8,ITGB1
700 | 698,TNR,ITGA8,ITGB1
701 | 699,TNXB,ITGA8,ITGB1
702 | 700,TNXB,ITGA8,ITGB1
703 | 701,TNXB,ITGA8,ITGB1
704 | 702,TNC,ITGA9,ITGB1
705 | 703,TNR,ITGA9,ITGB1
706 | 704,TNXB,ITGA9,ITGB1
707 | 705,COL1A1,ITGA9,ITGB1
708 | 706,COL1A2,ITGA9,ITGB1
709 | 707,COL2A1,ITGA9,ITGB1
710 | 708,COL4A1,ITGA9,ITGB1
711 | 709,COL4A2,ITGA9,ITGB1
712 | 710,COL4A3,ITGA9,ITGB1
713 | 711,COL4A4,ITGA9,ITGB1
714 | 712,COL4A5,ITGA9,ITGB1
715 | 713,COL6A1,ITGA9,ITGB1
716 | 714,COL6A2,ITGA9,ITGB1
717 | 715,COL6A3,ITGA9,ITGB1
718 | 716,COL6A6,ITGA9,ITGB1
719 | 717,COL9A1,ITGA9,ITGB1
720 | 718,COL9A2,ITGA9,ITGB1
721 | 719,COL9A3,ITGA9,ITGB1
722 | 720,LAMA1,ITGA9,ITGB1
723 | 721,LAMA2,ITGA9,ITGB1
724 | 722,LAMA3,ITGA9,ITGB1
725 | 723,LAMA4,ITGA9,ITGB1
726 | 724,LAMA5,ITGA9,ITGB1
727 | 725,LAMB1,ITGA9,ITGB1
728 | 726,LAMB2,ITGA9,ITGB1
729 | 727,LAMB3,ITGA9,ITGB1
730 | 728,LAMC1,ITGA9,ITGB1
731 | 729,LAMC2,ITGA9,ITGB1
732 | 730,LAMC3,ITGA9,ITGB1
733 | 731,COL1A1,ITGA10,ITGB1
734 | 732,COL1A2,ITGA10,ITGB1
735 | 733,COL2A1,ITGA10,ITGB1
736 | 734,COL4A1,ITGA10,ITGB1
737 | 735,COL4A2,ITGA10,ITGB1
738 | 736,COL4A3,ITGA10,ITGB1
739 | 737,COL4A4,ITGA10,ITGB1
740 | 738,COL4A5,ITGA10,ITGB1
741 | 739,COL6A1,ITGA10,ITGB1
742 | 740,COL6A2,ITGA10,ITGB1
743 | 741,COL6A3,ITGA10,ITGB1
744 | 742,COL6A6,ITGA10,ITGB1
745 | 743,COL9A1,ITGA10,ITGB1
746 | 744,COL9A2,ITGA10,ITGB1
747 | 745,COL9A3,ITGA10,ITGB1
748 | 746,COL1A1,ITGA11,ITGB1
749 | 747,COL1A2,ITGA11,ITGB1
750 | 748,COL2A1,ITGA11,ITGB1
751 | 749,COL4A1,ITGA11,ITGB1
752 | 750,COL4A2,ITGA11,ITGB1
753 | 751,COL4A3,ITGA11,ITGB1
754 | 752,COL4A4,ITGA11,ITGB1
755 | 753,COL4A5,ITGA11,ITGB1
756 | 754,COL6A1,ITGA11,ITGB1
757 | 755,COL6A2,ITGA11,ITGB1
758 | 756,COL6A3,ITGA11,ITGB1
759 | 757,COL6A6,ITGA11,ITGB1
760 | 758,COL9A1,ITGA11,ITGB1
761 | 759,COL9A2,ITGA11,ITGB1
762 | 760,COL9A3,ITGA11,ITGB1
763 | 761,FN1,ITGAV,ITGB1
764 | 762,VTN,ITGAV,ITGB1
765 | 763,FN1,ITGA4,nan
766 | 764,FN1,ITGAV,ITGB3
767 | 765,VTN,ITGAV,ITGB3
768 | 766,VWF,ITGAV,ITGB3
769 | 767,TNC,ITGAV,ITGB3
770 | 768,TNR,ITGAV,ITGB3
771 | 769,TNXB,ITGAV,ITGB3
772 | 770,THBS1,ITGAV,ITGB3
773 | 771,THBS2,ITGAV,ITGB3
774 | 772,THBS3,ITGAV,ITGB3
775 | 773,THBS4,ITGAV,ITGB3
776 | 774,COMP,ITGAV,ITGB3
777 | 775,FN1,ITGB3,nan
778 | 776,VTN,ITGB3,nan
779 | 777,VWF,ITGB3,nan
780 | 778,TNC,ITGB3,nan
781 | 779,TNR,ITGB3,nan
782 | 780,TNXB,ITGB3,nan
783 | 781,VTN,ITGAV,ITGB5
784 | 782,TNC,ITGAV,ITGB6
785 | 783,TNR,ITGAV,ITGB6
786 | 784,TNXB,ITGAV,ITGB6
787 | 785,FN1,ITGAV,ITGB6
788 | 786,VTN,ITGAV,ITGB8
789 | 787,FN1,ITGAV,ITGB8
790 | 788,LAMA1,ITGAV,ITGB8
791 | 789,LAMA2,ITGAV,ITGB8
792 | 790,LAMA3,ITGAV,ITGB8
793 | 791,LAMA4,ITGAV,ITGB8
794 | 792,LAMA5,ITGAV,ITGB8
795 | 793,LAMB1,ITGAV,ITGB8
796 | 794,LAMB2,ITGAV,ITGB8
797 | 795,LAMB3,ITGAV,ITGB8
798 | 796,LAMC1,ITGAV,ITGB8
799 | 797,LAMC2,ITGAV,ITGB8
800 | 798,LAMC3,ITGAV,ITGB8
801 | 799,COL1A1,ITGAV,ITGB8
802 | 800,COL1A2,ITGAV,ITGB8
803 | 801,COL2A1,ITGAV,ITGB8
804 | 802,COL4A1,ITGAV,ITGB8
805 | 803,COL4A2,ITGAV,ITGB8
806 | 804,COL4A3,ITGAV,ITGB8
807 | 805,COL4A4,ITGAV,ITGB8
808 | 806,COL4A5,ITGAV,ITGB8
809 | 807,COL6A1,ITGAV,ITGB8
810 | 808,COL6A2,ITGAV,ITGB8
811 | 809,COL6A3,ITGAV,ITGB8
812 | 810,COL6A6,ITGAV,ITGB8
813 | 811,COL9A1,ITGAV,ITGB8
814 | 812,COL9A2,ITGAV,ITGB8
815 | 813,COL9A3,ITGAV,ITGB8
816 | 814,LAMA1,ITGA6,ITGB4
817 | 815,LAMA2,ITGA6,ITGB4
818 | 816,LAMA3,ITGA6,ITGB4
819 | 817,LAMA4,ITGA6,ITGB4
820 | 818,LAMA5,ITGA6,ITGB4
821 | 819,LAMB1,ITGA6,ITGB4
822 | 820,LAMB2,ITGA6,ITGB4
823 | 821,LAMB3,ITGA6,ITGB4
824 | 822,LAMC1,ITGA6,ITGB4
825 | 823,LAMC2,ITGA6,ITGB4
826 | 824,LAMC3,ITGA6,ITGB4
827 | 825,FN1,CD44,nan
828 | 826,COL1A1,CD44,nan
829 | 827,COL1A2,CD44,nan
830 | 828,COL2A1,CD44,nan
831 | 829,COL4A1,CD44,nan
832 | 830,COL4A2,CD44,nan
833 | 831,COL4A3,CD44,nan
834 | 832,COL4A4,CD44,nan
835 | 833,COL4A5,CD44,nan
836 | 834,COL6A1,CD44,nan
837 | 835,COL6A2,CD44,nan
838 | 836,COL6A3,CD44,nan
839 | 837,COL6A6,CD44,nan
840 | 838,COL9A1,CD44,nan
841 | 839,COL9A2,CD44,nan
842 | 840,COL9A3,CD44,nan
843 | 841,LAMA1,CD44,nan
844 | 842,LAMA2,CD44,nan
845 | 843,LAMA3,CD44,nan
846 | 844,LAMA4,CD44,nan
847 | 845,LAMA5,CD44,nan
848 | 846,LAMB1,CD44,nan
849 | 847,LAMB2,CD44,nan
850 | 848,LAMB3,CD44,nan
851 | 849,LAMC1,CD44,nan
852 | 850,LAMC2,CD44,nan
853 | 851,LAMC3,CD44,nan
854 | 852,COL1A1,SDC1,nan
855 | 853,COL1A2,SDC1,nan
856 | 854,COL2A1,SDC1,nan
857 | 855,COL4A1,SDC1,nan
858 | 856,COL4A2,SDC1,nan
859 | 857,COL4A3,SDC1,nan
860 | 858,COL4A4,SDC1,nan
861 | 859,COL4A5,SDC1,nan
862 | 860,COL6A1,SDC1,nan
863 | 861,COL6A2,SDC1,nan
864 | 862,COL6A3,SDC1,nan
865 | 863,COL6A6,SDC1,nan
866 | 864,COL9A1,SDC1,nan
867 | 865,COL9A2,SDC1,nan
868 | 866,COL9A3,SDC1,nan
869 | 867,FN1,SDC1,nan
870 | 868,TNC,SDC1,nan
871 | 869,TNR,SDC1,nan
872 | 870,TNXB,SDC1,nan
873 | 871,THBS1,SDC1,nan
874 | 872,THBS2,SDC1,nan
875 | 873,THBS3,SDC1,nan
876 | 874,THBS4,SDC1,nan
877 | 875,COMP,SDC1,nan
878 | 876,COL1A1,SDC4,nan
879 | 877,COL1A2,SDC4,nan
880 | 878,COL2A1,SDC4,nan
881 | 879,COL4A1,SDC4,nan
882 | 880,COL4A2,SDC4,nan
883 | 881,COL4A3,SDC4,nan
884 | 882,COL4A4,SDC4,nan
885 | 883,COL4A5,SDC4,nan
886 | 884,COL6A1,SDC4,nan
887 | 885,COL6A2,SDC4,nan
888 | 886,COL6A3,SDC4,nan
889 | 887,COL6A6,SDC4,nan
890 | 888,COL9A1,SDC4,nan
891 | 889,COL9A2,SDC4,nan
892 | 890,COL9A3,SDC4,nan
893 | 891,FN1,SDC4,nan
894 | 892,TNC,SDC4,nan
895 | 893,TNR,SDC4,nan
896 | 894,TNXB,SDC4,nan
897 | 895,THBS1,SDC4,nan
898 | 896,THBS2,SDC4,nan
899 | 897,THBS3,SDC4,nan
900 | 898,THBS4,SDC4,nan
901 | 899,COMP,SDC4,nan
902 | 900,LAMA1,SV2A,nan
903 | 901,LAMA2,SV2A,nan
904 | 902,LAMA3,SV2A,nan
905 | 903,LAMA4,SV2A,nan
906 | 904,LAMA5,SV2A,nan
907 | 905,LAMB1,SV2A,nan
908 | 906,LAMB2,SV2A,nan
909 | 907,LAMB3,SV2A,nan
910 | 908,LAMC1,SV2A,nan
911 | 909,LAMC2,SV2A,nan
912 | 910,LAMC3,SV2A,nan
913 | 911,LAMA1,SV2B,nan
914 | 912,LAMA2,SV2B,nan
915 | 913,LAMA3,SV2B,nan
916 | 914,LAMA4,SV2B,nan
917 | 915,LAMA5,SV2B,nan
918 | 916,LAMB1,SV2B,nan
919 | 917,LAMB2,SV2B,nan
920 | 918,LAMB3,SV2B,nan
921 | 919,LAMC1,SV2B,nan
922 | 920,LAMC2,SV2B,nan
923 | 921,LAMC3,SV2B,nan
924 | 922,THBS1,CD36,nan
925 | 923,THBS2,CD36,nan
926 | 924,THBS3,CD36,nan
927 | 925,THBS4,CD36,nan
928 | 926,COMP,CD36,nan
929 | 927,VWF,GP1BA,GP5
930 | 928,THBS1,CD47,nan
931 | 929,THBS2,CD47,nan
932 | 930,THBS3,CD47,nan
933 | 931,THBS4,CD47,nan
934 | 932,COMP,CD47,nan
935 | 933,AGRN,DAG1,nan
936 | 934,HSPG2,DAG1,nan
937 | 935,LAMA1,DAG1,nan
938 | 936,LAMA2,DAG1,nan
939 | 937,LAMA3,DAG1,nan
940 | 938,LAMA4,DAG1,nan
941 | 939,LAMA5,DAG1,nan
942 | 940,LAMB1,DAG1,nan
943 | 941,LAMB2,DAG1,nan
944 | 942,LAMB3,DAG1,nan
945 | 943,LAMC1,DAG1,nan
946 | 944,LAMC2,DAG1,nan
947 | 945,LAMC3,DAG1,nan
948 | 946,ALCAM,CD6,nan
949 | 947,ANXA1,FPR2,FPR3
950 | 948,APP,CD74,nan
951 | 949,CADM1,CADM1,nan
952 | 950,CADM3,CADM3,nan
953 | 951,CD22,PTPRC,nan
954 | 952,CD226,PVR,nan
955 | 953,FCER2,ITGAM,ITGB2
956 | 954,FCER2,ITGAX,ITGB2
957 | 955,FCER2,ITGAV,ITGB3
958 | 956,FCER2,CR2,nan
959 | 957,CD34,SELP,nan
960 | 958,ENTPD1,ADORA1,nan
961 | 959,ENTPD1,ADORA2A,nan
962 | 960,ENTPD1,ADORA2B,nan
963 | 961,CD40LG,CD40,nan
964 | 962,PTPRC,CD22,nan
965 | 963,PTPRC,MRC1,nan
966 | 964,CD46,JAG1,nan
967 | 965,CD48,CD244,nan
968 | 966,CD6,ALCAM,nan
969 | 967,CD80,CD274,nan
970 | 968,CD80,CD28,nan
971 | 969,CD80,CTLA4,nan
972 | 970,CD86,CD28,nan
973 | 971,CD86,CTLA4,nan
974 | 972,CD96,PVR,nan
975 | 973,CD99,PILRA,nan
976 | 974,CD99,CD99,nan
977 | 975,CD99,CD99L2,nan
978 | 976,CDH4,CDH4,nan
979 | 977,CDH2,CDH2,nan
980 | 978,CDH1,CDH1,nan
981 | 979,CDH1,ITGA2,ITGB1
982 | 980,CDH1,ITGAE,nan
983 | 981,CDH1,KLRG1,nan
984 | 982,CDH5,CDH5,nan
985 | 983,CD209,CEACAM1,nan
986 | 984,SELE,CEACAM1,nan
987 | 985,CLDN11,CLDN11,nan
988 | 986,CLEC2D,KLRB1,nan
989 | 987,CLEC2B,KLRB1,nan
990 | 988,CD69,KLRB1,nan
991 | 989,CLEC2L,KLRB1,nan
992 | 990,NFASC,CNTN1,CNTNAP1
993 | 991,CNTN1,NRCAM,nan
994 | 992,CSPG4,ITGA3,ITGB1
995 | 993,DSC1,DSG2,nan
996 | 994,DSC2,DSG2,nan
997 | 995,DSG2,DSC3,nan
998 | 996,EFNA1,EPHA1,nan
999 | 997,EFNA1,EPHA2,nan
1000 | 998,EFNA1,EPHA3,nan
1001 | 999,EFNA1,EPHA4,nan
1002 | 1000,EFNA1,EPHA5,nan
1003 | 1001,EFNA3,EPHA1,nan
1004 | 1002,EFNA3,EPHA2,nan
1005 | 1003,EFNA3,EPHA3,nan
1006 | 1004,EFNA3,EPHA4,nan
1007 | 1005,EFNA3,EPHA5,nan
1008 | 1006,EFNA4,EPHA1,nan
1009 | 1007,EFNA4,EPHA2,nan
1010 | 1008,EFNA4,EPHA3,nan
1011 | 1009,EFNA4,EPHA4,nan
1012 | 1010,EFNA4,EPHA5,nan
1013 | 1011,EFNA5,EPHA1,nan
1014 | 1012,EFNA5,EPHA2,nan
1015 | 1013,EFNA5,EPHA3,nan
1016 | 1014,EFNA5,EPHA4,nan
1017 | 1015,EFNA5,EPHA5,nan
1018 | 1016,EFNA5,EPHB2,nan
1019 | 1017,EFNB1,EPHA4,nan
1020 | 1018,EFNB1,EPHB2,nan
1021 | 1019,EFNB1,EPHB3,nan
1022 | 1020,EFNB1,EPHB4,nan
1023 | 1021,EFNB2,EPHA4,nan
1024 | 1022,EFNB2,EPHB2,nan
1025 | 1023,EFNB2,EPHB3,nan
1026 | 1024,EFNB2,EPHB4,nan
1027 | 1025,EFNB3,EPHA4,nan
1028 | 1026,EFNB3,EPHB2,nan
1029 | 1027,EFNB3,EPHB3,nan
1030 | 1028,EFNB3,EPHB4,nan
1031 | 1029,EFNB3,EPHB6,nan
1032 | 1030,ESAM,ESAM,nan
1033 | 1031,GP1BA,ITGAM,ITGB2
1034 | 1032,ICAM1,ITGAX,ITGB2
1035 | 1033,ICAM1,ITGAL,ITGB2
1036 | 1034,ICAM2,ITGAL,ITGB2
1037 | 1035,ICAM1,ITGAM,ITGB2
1038 | 1036,ICAM2,ITGAM,ITGB2
1039 | 1037,ICAM1,ITGAL,nan
1040 | 1038,ICAM1,SPN,nan
1041 | 1039,ICAM5,CD209,nan
1042 | 1040,ITGB2,CD226,nan
1043 | 1041,ITGB2,ICAM1,nan
1044 | 1042,ITGB2,ICAM2,nan
1045 | 1043,JAM2,ITGA3,ITGB1
1046 | 1044,JAM2,ITGAV,ITGB1
1047 | 1045,JAM3,ITGAM,ITGB2
1048 | 1046,F11R,ITGAL,ITGB2
1049 | 1047,JAM2,JAM3,nan
1050 | 1048,F11R,F11R,nan
1051 | 1049,F11R,JAM2,nan
1052 | 1050,F11R,JAM3,nan
1053 | 1051,JAM2,F11R,nan
1054 | 1052,JAM2,JAM2,nan
1055 | 1053,JAM3,F11R,nan
1056 | 1054,JAM3,JAM2,nan
1057 | 1055,JAM3,JAM3,nan
1058 | 1056,L1CAM,ITGAV,ITGB3
1059 | 1057,L1CAM,ITGA4,nan
1060 | 1058,L1CAM,L1CAM,nan
1061 | 1059,LCK,CD8A,CD8B
1062 | 1060,MADCAM1,ITGA4,nan
1063 | 1061,HLA-A,CD8A,nan
1064 | 1062,HLA-B,CD8A,nan
1065 | 1063,HLA-C,CD8A,nan
1066 | 1064,HLA-E,CD8A,nan
1067 | 1065,HLA-F,CD8A,nan
1068 | 1066,HLA-G,CD8A,nan
1069 | 1067,HLA-A,CD8B,nan
1070 | 1068,HLA-B,CD8B,nan
1071 | 1069,HLA-C,CD8B,nan
1072 | 1070,HLA-E,CD8B,nan
1073 | 1071,HLA-F,CD8B,nan
1074 | 1072,HLA-G,CD8B,nan
1075 | 1073,HLA-G,LILRB1,nan
1076 | 1074,HLA-G,LILRB2,nan
1077 | 1075,HLA-F,KIR3DL1,nan
1078 | 1076,HLA-E,KLRC1,nan
1079 | 1077,HLA-E,KLRC2,nan
1080 | 1078,HLA-A,KIR3DL1,nan
1081 | 1079,HLA-F,LILRB1,nan
1082 | 1080,HLA-E,KLRD1,KLRC1
1083 | 1081,HLA-E,KLRD1,KLRC2
1084 | 1082,HLA-E,KLRD1,KLRC3
1085 | 1083,HLA-DPA1,CD4,nan
1086 | 1084,HLA-DPB1,CD4,nan
1087 | 1085,HLA-DQA1,CD4,nan
1088 | 1086,HLA-DMA,CD4,nan
1089 | 1087,HLA-DMB,CD4,nan
1090 | 1088,HLA-DQA2,CD4,nan
1091 | 1089,HLA-DOA,CD4,nan
1092 | 1090,HLA-DOB,CD4,nan
1093 | 1091,HLA-DQB1,CD4,nan
1094 | 1092,HLA-DRA,CD4,nan
1095 | 1093,HLA-DRB1,CD4,nan
1096 | 1094,HLA-DRB5,CD4,nan
1097 | 1095,MPZ,MPZL1,nan
1098 | 1096,MPZ,MPZ,nan
1099 | 1097,MPZL1,MPZL1,nan
1100 | 1098,NCAM1,FGFR1,nan
1101 | 1099,NCAM1,NCAM1,nan
1102 | 1100,NCAM1,NCAM2,nan
1103 | 1101,NCAM1,L1CAM,nan
1104 | 1102,NCAM2,L1CAM,nan
1105 | 1103,NEGR1,NEGR1,nan
1106 | 1104,LRRC4C,NTNG1,nan
1107 | 1105,LRRC4B,PTPRF,nan
1108 | 1106,DLL1,NOTCH1,nan
1109 | 1107,DLL1,NOTCH3,nan
1110 | 1108,DLL1,NOTCH4,nan
1111 | 1109,DLL3,NOTCH1,nan
1112 | 1110,DLL3,NOTCH2,nan
1113 | 1111,DLL3,NOTCH3,nan
1114 | 1112,DLL3,NOTCH4,nan
1115 | 1113,DLL4,NOTCH1,nan
1116 | 1114,DLL4,NOTCH2,nan
1117 | 1115,DLL4,NOTCH3,nan
1118 | 1116,DLL4,NOTCH4,nan
1119 | 1117,JAG1,NOTCH1,nan
1120 | 1118,JAG1,NOTCH2,nan
1121 | 1119,JAG1,NOTCH3,nan
1122 | 1120,JAG1,NOTCH4,nan
1123 | 1121,JAG2,NOTCH1,nan
1124 | 1122,JAG2,NOTCH2,nan
1125 | 1123,JAG2,NOTCH3,nan
1126 | 1124,JAG2,NOTCH4,nan
1127 | 1125,DLL1,NOTCH2,nan
1128 | 1126,NRXN1,NLGN1,nan
1129 | 1127,NRXN1,NLGN2,nan
1130 | 1128,NRXN1,NLGN3,nan
1131 | 1129,NRXN2,NLGN1,nan
1132 | 1130,NRXN2,NLGN2,nan
1133 | 1131,NRXN2,NLGN3,nan
1134 | 1132,NRXN3,NLGN1,nan
1135 | 1133,NRXN3,NLGN2,nan
1136 | 1134,NRXN3,NLGN3,nan
1137 | 1135,OCLN,OCLN,nan
1138 | 1136,CD274,PDCD1,nan
1139 | 1137,PDCD1LG2,PDCD1,nan
1140 | 1138,PECAM1,PECAM1,nan
1141 | 1139,PTPRM,PTPRM,nan
1142 | 1140,PVR,CD226,nan
1143 | 1141,PVR,TIGIT,nan
1144 | 1142,SELE,CD44,nan
1145 | 1143,SELE,GLG1,nan
1146 | 1144,SELL,CD34,nan
1147 | 1145,SELL,PODXL,nan
1148 | 1146,SELL,MADCAM1,nan
1149 | 1147,SELPLG,SELE,nan
1150 | 1148,SELPLG,SELL,nan
1151 | 1149,SELPLG,SELP,nan
1152 | 1150,SEMA4A,NRP1,PLXNA1
1153 | 1151,SEMA4A,NRP1,PLXNA2
1154 | 1152,SEMA4A,NRP1,PLXNA3
1155 | 1153,SEMA4A,NRP1,PLXNA4
1156 | 1154,SEMA4A,PLXNB1,nan
1157 | 1155,SEMA4A,PLXNB2,nan
1158 | 1156,SEMA4D,PLXNB1,nan
1159 | 1157,SEMA4D,PLXNB2,nan
1160 | 1158,SEMA4C,PLXNB2,nan
1161 | 1159,SEMA4G,PLXNB2,nan
1162 | 1160,SEMA4D,CD72,nan
1163 | 1161,SEMA5A,PLXNA1,nan
1164 | 1162,SEMA5A,PLXNA3,nan
1165 | 1163,SEMA6D,PLXNA1,KDR
1166 | 1164,SEMA6D,PLXNA1,KDR
1167 | 1165,SEMA6D,PLXNA1,nan
1168 | 1166,SEMA6A,PLXNA2,nan
1169 | 1167,SEMA6B,PLXNA2,nan
1170 | 1168,SEMA6A,PLXNA4,nan
1171 | 1169,SEMA6B,PLXNA4,nan
1172 | 1170,SEMA7A,ITGB1,ITGA1
1173 | 1171,SEMA7A,PLXNC1,nan
1174 | 1172,SIGLEC1,SPN,nan
1175 | 1173,THY1,ITGAM,ITGB2
1176 | 1174,THY1,ITGAX,ITGB2
1177 | 1175,THY1,ITGAV,ITGB3
1178 | 1176,TIGIT,PVR,nan
1179 | 1177,TIGIT,PVR,nan
1180 | 1178,TIGIT,PVR,nan
1181 | 1179,ITGA4,VCAM1,nan
1182 |
--------------------------------------------------------------------------------
/tutorial/simulation/pos.txt:
--------------------------------------------------------------------------------
1 | 328.0,7.0
2 | 337.611111111,7.0
3 | 7.0,6.5
4 | 38.5,4.5
5 | 91.0,7.5
6 | 55.5,10.5
7 | 65.5,9.0
8 | 402.0,11.5
9 | 293.0,16.5
10 | 183.5,16.0
11 | 374.0,20.5
12 | 399.0,22.5
13 | 383.5,23.5
14 | 73.0,26.0
15 | 361.0,25.0
16 | 423.5,26.5
17 | 46.0,28.0
18 | 127.0,29.5
19 | 404.0,28.0
20 | 69.0,35.5
21 | 421.0,36.0
22 | 35.0,36.5
23 | 161.5,35.5
24 | 369.5,36.0
25 | 383.0,37.0
26 | 118.0,36.0
27 | 8.0,41.5
28 | 128.0,40.5
29 | 272.0,41.5
30 | 429.5,46.5
31 | 149.5,43.5
32 | 182.5,44.5
33 | 288.0,46.5
34 | 411.0,45.5
35 | 165.0,46.5
36 | 401.0,42.0
37 | 157.5,48.0
38 | 195.0,50.0
39 | 347.0,48.0
40 | 351.5,47.0
41 | 111.0,47.5
42 | 339.0,50.5
43 | 390.0,49.5
44 | 286.0,53.0
45 | 372.5,51.5
46 | 52.5,54.0
47 | 377.0,58.5
48 | 326.5,52.5
49 | 396.0,57.0
50 | 419.5,60.0
51 | 405.5,67.0
52 | 13.5,59.5
53 | 52.0,64.5
54 | 383.5,65.5
55 | 34.5,71.5
56 | 63.0,66.5
57 | 12.0,72.0
58 | 428.0,67.5
59 | 179.5,70.5
60 | 298.5,70.0
61 | 437.5,70.0
62 | 4.5,72.0
63 | 424.0,76.0
64 | 303.0,76.0
65 | 162.5,84.5
66 | 336.0,82.5
67 | 432.5,85.0
68 | 11.5,87.5
69 | 393.5,88.5
70 | 40.5,95.0
71 | 317.5,101.5
72 | 394.5,104.0
73 | 44.0,107.0
74 | 362.5,103.5
75 | 387.0,107.0
76 | 425.5,119.5
77 | 118.5,125.0
78 | 446.0,123.0
79 | 128.0,126.0
80 | 7.0,132.5
81 | 282.5,137.5
82 | 327.5,144.5
83 | 421.0,148.5
84 | 73.5,142.5
85 | 99.5,155.0
86 | 214.5,156.5
87 | 259.5,157.5
88 | 112.0,157.0
89 | 148.5,161.5
90 | 405.0,162.0
91 | 266.0,165.5
92 | 442.5,163.0
93 | 421.5,166.5
94 | 25.5,177.0
95 | 357.0,182.5
96 | 71.0,183.0
97 | 273.5,183.5
98 | 412.5,193.0
99 | 396.5,197.0
100 | 432.5,195.5
101 | 440.0,201.0
102 | 405.5,200.0
103 | 422.0,201.0
104 | 291.5,201.0
105 | 395.0,207.5
106 | 429.5,209.5
107 | 379.0,209.5
108 | 408.0,209.5
109 | 420.5,209.0
110 | 411.0,215.0
111 | 391.0,217.0
112 | 399.0,217.0
113 | 435.0,221.0
114 | 427.5,221.0
115 | 419.5,220.0
116 | 334.0,228.0
117 | 413.5,226.0
118 | 392.0,228.5
119 | 307.5,229.5
120 | 146.0,227.5
121 | 429.5,232.5
122 | 331.5,231.0
123 | 398.5,232.5
124 | 385.5,237.0
125 | 74.0,241.0
126 | 316.0,233.5
127 | 414.5,239.5
128 | 332.0,241.0
129 | 424.0,240.5
130 | 353.5,243.0
131 | 393.0,244.5
132 | 81.5,247.5
133 | 326.0,249.5
134 | 405.0,255.5
135 | 111.5,258.0
136 | 375.5,258.5
137 | 440.0,262.0
138 | 400.0,265.5
139 | 441.5,274.0
140 | 134.5,275.5
141 | 420.5,275.5
142 | 430.5,275.5
143 | 354.0,275.0
144 | 217.5,285.5
145 | 362.5,285.5
146 | 353.0,285.5
147 | 430.5,287.0
148 | 93.0,288.0
149 | 410.0,286.5
150 | 338.5,286.0
151 | 384.0,293.0
152 | 242.5,299.0
153 | 343.0,301.0
154 | 359.5,295.0
155 | 333.0,299.5
156 | 226.0,303.0
157 | 356.0,307.5
158 | 364.0,299.0
159 | 313.0,303.5
160 | 420.5,302.5
161 | 373.0,305.0
162 | 387.5,310.5
163 | 246.0,308.0
164 | 290.0,307.0
165 | 306.5,307.0
166 | 256.0,312.0
167 | 226.0,313.0
168 | 238.0,315.5
169 | 310.0,318.0
170 | 251.5,318.0
171 | 423.5,319.5
172 | 298.0,322.0
173 | 250.0,323.5
174 | 181.5,327.0
175 | 432.5,325.5
176 | 306.0,328.0
177 | 361.0,324.5
178 | 172.0,330.0
179 | 236.0,329.0
180 | 279.0,333.0
181 | 385.0,330.5
182 | 303.0,335.5
183 | 391.0,331.0
184 | 314.0,333.0
185 | 375.5,335.5
186 | 26.0,335.5
187 | 263.0,345.0
188 | 184.5,348.0
189 | 239.0,349.5
190 | 302.0,347.5
191 | 391.0,347.5
192 | 253.5,347.5
193 | 152.0,352.5
194 | 311.0,350.0
195 | 399.0,353.0
196 | 147.0,357.5
197 | 292.0,353.0
198 | 215.0,354.5
199 | 350.0,359.5
200 | 199.0,355.5
201 | 136.5,362.5
202 | 179.5,362.5
203 | 207.0,367.0
204 | 251.0,365.0
205 | 195.0,368.5
206 | 361.0,365.0
207 | 232.0,362.0
208 | 310.5,371.0
209 | 219.0,372.0
210 | 363.0,373.0
211 | 438.5,367.5
212 | 320.5,368.0
213 | 419.0,375.5
214 | 175.0,375.0
215 | 186.5,373.5
216 | 349.5,378.5
217 | 234.5,381.5
218 | 428.5,380.0
219 | 196.0,379.0
220 | 441.5,382.0
221 | 187.0,382.0
222 | 344.5,382.5
223 | 211.5,381.5
224 | 126.5,384.0
225 | 179.5,381.5
226 | 175.5,388.0
227 | 333.5,376.5
228 | 199.5,388.0
229 | 264.5,385.0
230 | 367.0,390.0
231 | 433.0,389.0
232 | 217.5,391.0
233 | 229.5,391.5
234 | 272.0,391.0
235 | 299.5,392.0
236 | 168.0,392.5
237 | 186.5,395.5
238 | 383.0,389.5
239 | 123.5,391.5
240 | 260.0,396.0
241 | 321.5,395.5
242 | 412.0,394.0
243 | 211.0,396.5
244 | 294.5,401.0
245 | 279.5,403.0
246 | 250.5,400.5
247 | 155.0,404.0
248 | 207.5,406.5
249 | 435.0,404.0
250 | 264.5,402.0
251 | 221.0,406.5
252 | 249.5,408.0
253 | 289.0,406.5
254 | 181.0,407.0
255 | 240.0,408.5
256 | 262.5,414.0
257 | 152.0,413.0
258 | 169.5,408.0
259 | 283.5,413.0
260 | 352.5,411.0
261 | 399.5,410.0
262 | 339.0,407.5
263 | 332.0,407.5
264 | 321.0,413.0
265 | 184.0,415.5
266 | 332.0,423.0
267 | 387.5,415.5
268 | 420.0,416.0
269 | 290.0,417.0
270 | 404.5,419.0
271 | 216.5,421.0
272 | 281.0,426.0
273 | 131.0,422.5
274 | 240.0,423.5
275 | 173.0,427.0
276 | 413.5,426.5
277 | 148.0,423.5
278 | 343.5,426.5
279 | 296.5,428.0
280 | 308.0,428.0
281 | 395.0,429.5
282 | 129.0,431.0
283 | 269.0,430.0
284 | 220.5,428.0
285 | 358.0,430.5
286 | 298.0,436.5
287 | 382.0,436.0
288 | 345.0,435.0
289 | 130.5,436.5
290 | 185.5,431.5
291 | 213.0,436.5
292 | 176.0,439.5
293 | 186.0,443.0
294 | 340.5,441.0
295 | 393.5,438.5
296 | 102.5,443.5
297 |
--------------------------------------------------------------------------------
/tutorial/simulation/simulation_code.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | import os
4 | from svca.models.model1 import Model1
5 | from svca.simulations.from_real import FromRealSimulation
6 | from svca.util_functions import utils
7 |
8 |
9 | def load_data(data_dir, pair_index):
10 | # data directory
11 | db_path = os.path.join(data_dir, ‘ligand_recptor_pairs_sim.csv
12 | ')
13 | expression_path = os.path.join(data_dir, 'reduced2_exp.txt')
14 | position_path = os.path.join(data_dir, 'pos.txt')
15 |
16 | # read in pairs
17 | pair_db = pd.read_csv(db_path, index_col=0)
18 | pair_names, phenotypes, positions = utils.read_data(expression_path, position_path)
19 |
20 | # for a specific target pair, choose ligand
21 | target_pair = pair_db.index[pair_index]
22 | print(f"Processing pair: {target_pair}")
23 | phenotype_mask = (pair_names == target_pair.split("_")[0]).flatten()
24 | main_phenotype = phenotypes[:, phenotype_mask]
25 |
26 | # match receptor
27 | receptor_pairs = pair_db.loc[target_pair, ['R1', 'R2']].dropna().values
28 | selector = [p in receptor_pairs for p in pair_names[:, 0]]
29 | kin_data = phenotypes[:, selector]
30 |
31 | return positions, main_phenotype, kin_data, target_pair
32 |
33 |
34 | def run_simulation(positions, phenotype, kin_data, output_dir, pair_name, interactions_size=0.25):
35 | sim = FromRealSimulation(positions, phenotype.flatten(), kin_data)
36 | simulated_data = sim.simulate(interactions_size=interactions_size)
37 |
38 | os.makedirs(output_dir, exist_ok=True)
39 | output_path = os.path.join(output_dir, f"{pair_name}_sim.npy")
40 | np.save(output_path, simulated_data)
41 | return simulated_data
42 |
43 |
44 | def train_model(data, positions, kin_data, output_dir, pair_name, bootstrap_idx, normalization='standard'):
45 | “””tra””” in SVCA
46 | model
47 | model = Model1(
48 | Y=data,
49 | positions=positions,
50 | norm=normalization,
51 | oos_predictions=0.,
52 | cov_terms=['intrinsic', 'environmental'],
53 | kin_from=kin_data
54 | )
55 |
56 | model.reset_params()
57 | model.train_gp(grid_size=10)
58 |
59 | base_prefix = f"{pair_name}_{bootstrap_idx}_base"
60 | utils.write_variance_explained(model, output_dir, base_prefix)
61 | utils.write_LL(model, output_dir, base_prefix)
62 |
63 | # bring in interaction cov
64 | model.add_cov(['interactions'])
65 | best_params = optimize_parameters(model)
66 | model.gp.setParams(best_params)
67 |
68 | # save
69 | final_prefix = f"{pair_name}_{bootstrap_idx}_final"
70 | utils.write_variance_explained(model, output_dir, final_prefix)
71 | utils.write_r2(model, output_dir, final_prefix)
72 | return model
73 |
74 |
75 | def optimize_parameters(model, n_trials=5):
76 | best_ll = np.inf
77 | best_params = None
78 |
79 | for _ in range(n_trials):
80 | params = {
81 | 'intrinsic': model.intrinsic_cov.getParams() * np.random.uniform(0.8, 1.2),
82 | 'environmental': model.environmental_cov.getParams() * np.random.uniform(0.8, 1.2),
83 | 'noise': model.noise_cov.getParams() * np.random.uniform(0.8, 1.2)
84 | }
85 |
86 | model.set_initCovs(params)
87 | model.reset_params()
88 | model.train_gp(grid_size=10)
89 |
90 | current_ll = model.gp.LML()
91 | if current_ll < best_ll:
92 | best_ll = current_ll
93 | best_params = model.gp.getParams()
94 |
95 | return best_params
96 |
97 |
98 | def main(data_dir, output_dir, pair_index, bootstrap_idx, normalization='quantile'):
99 | positions, phenotype, kin_data, pair_name = load_data(data_dir, pair_index)
100 | simulated_data = run_simulation(positions, phenotype, kin_data, output_dir, pair_name)
101 | trained_model = train_model(simulated_data, positions, kin_data, output_dir, pair_name, bootstrap_idx,
102 | normalization)
103 |
104 |
105 | if __name__ == '__main__':
106 | import argparse
107 |
108 | parser = argparse.ArgumentParser(description='SVCA Simulation Pipeline')
109 | parser.add_argument('--data_dir', required=True, help='Input data directory')
110 | parser.add_argument('--output_dir', required=True, help='Output directory')
111 | parser.add_argument('--pair_index', type=int, required=True, help='Index of target pair')
112 | parser.add_argument('--bootstrap_idx', type=int, default=1, help='Bootstrap iteration index')
113 | parser.add_argument('--normalization', default='quantile', help='Normalization method')
114 |
115 | args = parser.parse_args()
116 |
117 | main(
118 | data_dir=args.data_dir,
119 | output_dir=args.output_dir,
120 | pair_index=args.pair_index,
121 | bootstrap_idx=args.bootstrap_idx,
122 | normalization=args.normalization
123 | )
--------------------------------------------------------------------------------