├── .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 | ) --------------------------------------------------------------------------------