transbrain 0.1.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- transbrain-0.1.7/LICENSE +201 -0
- transbrain-0.1.7/PKG-INFO +24 -0
- transbrain-0.1.7/README.md +161 -0
- transbrain-0.1.7/setup.cfg +4 -0
- transbrain-0.1.7/setup.py +32 -0
- transbrain-0.1.7/transbrain/__init__.py +4 -0
- transbrain-0.1.7/transbrain/atlas.py +146 -0
- transbrain-0.1.7/transbrain/base.py +81 -0
- transbrain-0.1.7/transbrain/config.py +104 -0
- transbrain-0.1.7/transbrain/trans.py +221 -0
- transbrain-0.1.7/transbrain.egg-info/PKG-INFO +24 -0
- transbrain-0.1.7/transbrain.egg-info/SOURCES.txt +13 -0
- transbrain-0.1.7/transbrain.egg-info/dependency_links.txt +1 -0
- transbrain-0.1.7/transbrain.egg-info/requires.txt +11 -0
- transbrain-0.1.7/transbrain.egg-info/top_level.txt +1 -0
transbrain-0.1.7/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
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.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: transbrain
|
|
3
|
+
Version: 0.1.7
|
|
4
|
+
Summary: TransBrain is an integrated computational framework for bidirectional translation of brain-wide phenotypes between humans and mice.
|
|
5
|
+
Home-page: https://github.com/ibpshangzheng/transbrain
|
|
6
|
+
Author: Shangzheng Huang, Tongyu Zhang
|
|
7
|
+
Author-email: huangshangzheng@ibp.ac.cn
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: matplotlib==3.7.5
|
|
15
|
+
Requires-Dist: matplotlib-inline==0.1.7
|
|
16
|
+
Requires-Dist: nibabel==5.2.1
|
|
17
|
+
Requires-Dist: nilearn==0.10.4
|
|
18
|
+
Requires-Dist: numpy==1.24.4
|
|
19
|
+
Requires-Dist: openpyxl==3.1.5
|
|
20
|
+
Requires-Dist: pandas==2.0.3
|
|
21
|
+
Requires-Dist: scikit-learn==1.3.2
|
|
22
|
+
Requires-Dist: scipy==1.10.1
|
|
23
|
+
Requires-Dist: seaborn==0.13.2
|
|
24
|
+
Requires-Dist: six==1.17.0
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# TransBrain
|
|
2
|
+
|
|
3
|
+
TransBrain is an integrated computational framework for bidirectional translation of brain-wide phenotypes between humans and mice. Specifically, TransBrain provides a systematic approach for cross-species quantitative comparison and mechanistic investigation of both normal and pathological brain functions.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
What can TransBrain do?
|
|
8
|
+
|
|
9
|
+
1. Exploring the similarity relationships at the transcriptional level.
|
|
10
|
+
|
|
11
|
+
2. Inferring the conservation of whole-brain phenotypes.
|
|
12
|
+
|
|
13
|
+
3. Transforming and annotating whole-brain functional circuits.
|
|
14
|
+
|
|
15
|
+
4. Linking specific mouse models with human diseases.
|
|
16
|
+
|
|
17
|
+
## Further Reading
|
|
18
|
+
|
|
19
|
+
If you wish to learn more about the construction details of this method, please refer to our article: [https://www.biorxiv.org/content/10.1101/2025.01.27.635016v1](https://www.biorxiv.org/content/10.1101/2025.01.27.635016v1) (in preprint).
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
TransBrain is on pypi: https://pypi.org/project/transbrain/
|
|
24
|
+
|
|
25
|
+
To install TransBrain as a package, run:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
pip install transbrain
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
You can also create a conda environment from the environment.yml file:
|
|
32
|
+
|
|
33
|
+
* First, clone this repository,
|
|
34
|
+
```sh
|
|
35
|
+
git clone https://github.com/ibpshangzheng/transbrain.git
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
* Then, create the environment,
|
|
39
|
+
```sh
|
|
40
|
+
cd transbrain
|
|
41
|
+
conda env create -f environment.yml
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
* Activate the environment,
|
|
45
|
+
```sh
|
|
46
|
+
conda activate transbrain_env
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Python Dependencies
|
|
50
|
+
|
|
51
|
+
The project mainly depends on Python (>= 3.8.5).
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
matplotlib==3.7.5,
|
|
55
|
+
matplotlib-inline==0.1.7,
|
|
56
|
+
nibabel==5.2.1,
|
|
57
|
+
nilearn==0.10.4,
|
|
58
|
+
numpy==1.24.4,
|
|
59
|
+
openpyxl==3.1.5,
|
|
60
|
+
pandas==2.0.3,
|
|
61
|
+
scikit-learn==1.3.2,
|
|
62
|
+
scipy==1.10.1,
|
|
63
|
+
seaborn==0.13.2,
|
|
64
|
+
six==1.17.0
|
|
65
|
+
```
|
|
66
|
+
See full list in environment.yml file.
|
|
67
|
+
|
|
68
|
+
## Unit Test
|
|
69
|
+
|
|
70
|
+
- We provide a [Python Unit Test](https://www.dataquest.io/blog/unit-tests-python/) module to check whether the installation was successful.
|
|
71
|
+
- Clone our repository and run this file. Make sure you are in the **root directory** (where `test_transbrain.py` is located) before running the test.
|
|
72
|
+
|
|
73
|
+
### File Structure
|
|
74
|
+
|
|
75
|
+
transbrain-main/
|
|
76
|
+
├── transbrain/
|
|
77
|
+
│ └── exampledata/
|
|
78
|
+
├── test_transbrain.py # Unit Test file
|
|
79
|
+
└── tests/ # Verification files
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
python test_transbrain.py
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- If you see the message ``🎉 TransBrain installed successfully!!!``, it means that TransBrain is ready to use.
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
## Getting Started
|
|
90
|
+
### Usage
|
|
91
|
+
- After installation, you can refer to the [**basic usage notebook**](./tests/basic_usage.ipynb) in the root directory of TransBrain to explore usage examples and other functions.
|
|
92
|
+
- You can see detailed documentation of TransBrain [here](http://192.168.193.179:10088/)
|
|
93
|
+
- We also provide a [online mapping website](http://192.168.193.179:10087/), which enables users to directly upload your data for online mapping and visualization.
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
import pandas as pd
|
|
98
|
+
import transbrain as tb
|
|
99
|
+
|
|
100
|
+
#Initialize TransBrain for specific atlas
|
|
101
|
+
Transformer = tb.trans.SpeciesTrans('bn')
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# Example from mouse to human
|
|
106
|
+
mouse_phenotype = pd.read_csv('./transbrain/exampledata/mouse/mouse_all_example_data.csv',index_col=0)
|
|
107
|
+
mouse_phenotype_in_human = Transformer.mouse_to_human(mouse_phenotype, region_type='all', normalize=True)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
# Example from human to mouse
|
|
112
|
+
human_phenotype = pd.read_csv('./transbrain/exampledata/human/bn/human_bn_all_example_data.csv',index_col=0)
|
|
113
|
+
human_phenotype_in_mouse = Transformer.human_to_mouse(human_phenotype, region_type='all', normalize=True)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
# Get human phenotypes from nii file
|
|
118
|
+
human_atlas = tb.atlas.fetch_human_atlas(atlas_type='bn',region_type='cortex')
|
|
119
|
+
phenotype_nii_path = ('./transbrain/exampledata/human/human_example_phenotype_data.nii.gz')
|
|
120
|
+
human_phenptype_extracted = tb.base.get_region_phenotypes(phenotype_nii_path, atlas_dict = human_atlas)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
# Get mouse phenotypes from nii file
|
|
125
|
+
mouse_atlas = tb.atlas.fetch_mouse_atlas(region_type='all')
|
|
126
|
+
phenotype_nii_path = ('./transbrain/exampledata/mouse/mouse_example_phenotype_data.nii.gz')
|
|
127
|
+
mouse_phenptype_extracted = tb.base.get_region_phenotypes(phenotype_nii_path, atlas_dict = mouse_atlas)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
# Get graph embeddings
|
|
133
|
+
Transformer = tb.trans.SpeciesTrans('bn')
|
|
134
|
+
Human_Mouse_embedding_bn = Transformer._load_embeddings()
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
This allows seamless integration into your existing workflows. 🚀
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
### Toturials
|
|
141
|
+
We provided [**Tutorial Cases**](#tutorial-cases) demonstrating how to apply TransBrain for cross-species translation and comparison, which includes:
|
|
142
|
+
|
|
143
|
+
* Analyzing and visualizing transcriptional similarity between humans and mice.
|
|
144
|
+
|
|
145
|
+
* Characterizing the evolutionary spectrum of resting-state fMRI network phenotypes.
|
|
146
|
+
|
|
147
|
+
* Annotating the optogenetic circuits in mice using Neurosynth.
|
|
148
|
+
|
|
149
|
+
* Linking gene mutations to imaging phenotype deviations in autism.
|
|
150
|
+
|
|
151
|
+
The analysis process and figures can be viewed in the Jupyter Notebook. The necessary files and datas for completing these analysis are included in the notebook's folder.
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
This project is covered under the Apache 2.0 License.
|
|
157
|
+
|
|
158
|
+
## Support
|
|
159
|
+
For questions and comments, please file a Github issue and/or email Shangzheng Huang(huangshangzheng@ibp.ac.cn)
|
|
160
|
+
|
|
161
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="transbrain",
|
|
5
|
+
version="0.1.7",
|
|
6
|
+
author="Shangzheng Huang, Tongyu Zhang",
|
|
7
|
+
author_email="huangshangzheng@ibp.ac.cn",
|
|
8
|
+
description="TransBrain is an integrated computational framework for bidirectional translation of brain-wide phenotypes between humans and mice.",
|
|
9
|
+
long_description_content_type="text/markdown",
|
|
10
|
+
url="https://github.com/ibpshangzheng/transbrain",
|
|
11
|
+
packages=find_packages(),
|
|
12
|
+
include_package_data=True,
|
|
13
|
+
install_requires=[
|
|
14
|
+
"matplotlib==3.7.5",
|
|
15
|
+
"matplotlib-inline==0.1.7",
|
|
16
|
+
"nibabel==5.2.1",
|
|
17
|
+
"nilearn==0.10.4",
|
|
18
|
+
"numpy==1.24.4",
|
|
19
|
+
"openpyxl==3.1.5",
|
|
20
|
+
"pandas==2.0.3",
|
|
21
|
+
"scikit-learn==1.3.2",
|
|
22
|
+
"scipy==1.10.1",
|
|
23
|
+
"seaborn==0.13.2",
|
|
24
|
+
"six==1.17.0",
|
|
25
|
+
],
|
|
26
|
+
classifiers=[
|
|
27
|
+
"Programming Language :: Python :: 3",
|
|
28
|
+
'License :: OSI Approved :: Apache Software License',
|
|
29
|
+
"Operating System :: OS Independent",
|
|
30
|
+
],
|
|
31
|
+
python_requires=">=3.8",
|
|
32
|
+
)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import numpy as np
|
|
4
|
+
from nilearn import image
|
|
5
|
+
from transbrain.config import Config
|
|
6
|
+
from typing import Literal
|
|
7
|
+
|
|
8
|
+
AtlasType = Literal['bn', 'dk', 'aal']
|
|
9
|
+
RegionType = Literal['cortex', 'subcortex', 'all']
|
|
10
|
+
|
|
11
|
+
def fetch_human_atlas(atlas_type: AtlasType = 'bn', region_type: RegionType = 'all'):
|
|
12
|
+
"""
|
|
13
|
+
Fetch a human brain atlas image and its region information.
|
|
14
|
+
|
|
15
|
+
This function loads a labeled brain atlas image (e.g., Brainnetome, Desikan-Killiany, or AAL)
|
|
16
|
+
along with its corresponding ROI (region of interest) metadata table.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
atlas_type : {'bn', 'dk', 'aal'}, optional
|
|
21
|
+
The type of atlas to load. Must be one of:
|
|
22
|
+
- 'bn' : Brainnetome Atlas
|
|
23
|
+
- 'dk' : Desikan-Killiany Atlas
|
|
24
|
+
- 'aal' : Automated Anatomical Labeling (AAL) Atlas
|
|
25
|
+
Default is 'bn'.
|
|
26
|
+
|
|
27
|
+
region_type : {'cortex', 'subcortex', 'all'}, optional
|
|
28
|
+
Which regions to include in returned region names and info table: cortical, subcortical, or all. Default is 'all'.
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
dict
|
|
33
|
+
A dictionary with the following keys:
|
|
34
|
+
- 'atlas' : nibabel.Nifti1Image
|
|
35
|
+
The loaded NIfTI image of the atlas.
|
|
36
|
+
- 'atlas_data' : np.ndarray
|
|
37
|
+
The atlas volume data as a NumPy array.
|
|
38
|
+
- 'region_info' : np.ndarray
|
|
39
|
+
A list of anatomical region names, extracted from the 'Anatomical Name' column of the label file.
|
|
40
|
+
- 'info_table' : pandas.DataFrame
|
|
41
|
+
The full region-of-interest (ROI) information table including additional metadata.
|
|
42
|
+
|
|
43
|
+
Raises
|
|
44
|
+
------
|
|
45
|
+
FileNotFoundError
|
|
46
|
+
If the atlas image file or the ROI label file is not found.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# Load the Human atlas image
|
|
50
|
+
human_atlas_path,human_labels_path = Config.atlas_resources[atlas_type]
|
|
51
|
+
|
|
52
|
+
if not os.path.exists(human_atlas_path):
|
|
53
|
+
raise FileNotFoundError(f"Human atlas file not found at {human_atlas_path}")
|
|
54
|
+
human_brain_atlas = image.load_img(human_atlas_path)
|
|
55
|
+
|
|
56
|
+
# Load the ROI information table
|
|
57
|
+
if not os.path.exists(human_labels_path):
|
|
58
|
+
raise FileNotFoundError(f"ROI information file not found at {human_labels_path}")
|
|
59
|
+
|
|
60
|
+
human_brain_info_all = pd.read_csv(human_labels_path,index_col=0)
|
|
61
|
+
human_brain_atlas_data = np.asarray(human_brain_atlas.dataobj).astype(np.int32)
|
|
62
|
+
|
|
63
|
+
# Extract region information based on region_type
|
|
64
|
+
cortex_region_list = Config.region_resources[atlas_type][0]
|
|
65
|
+
subcortex_region_list = Config.region_resources[atlas_type][1]
|
|
66
|
+
|
|
67
|
+
if region_type == 'cortex':
|
|
68
|
+
human_brain_info = human_brain_info_all.loc[human_brain_info_all['Anatomical Name'].isin(cortex_region_list)]
|
|
69
|
+
human_brain_info = human_brain_info.reset_index(drop=True)
|
|
70
|
+
region_info = human_brain_info['Anatomical Name'].values # Cortex regions
|
|
71
|
+
elif region_type == 'subcortex':
|
|
72
|
+
human_brain_info = human_brain_info_all.loc[human_brain_info_all['Anatomical Name'].isin(subcortex_region_list)]
|
|
73
|
+
human_brain_info = human_brain_info.reset_index(drop=True)
|
|
74
|
+
region_info = human_brain_info['Anatomical Name'].values # Cortex regions
|
|
75
|
+
elif region_type == 'all':
|
|
76
|
+
human_brain_info = human_brain_info_all
|
|
77
|
+
region_info = human_brain_info['Anatomical Name'].values
|
|
78
|
+
else:
|
|
79
|
+
raise ValueError(f"Invalid region_type: {region_type}")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# Return the results as a dictionary
|
|
83
|
+
return {
|
|
84
|
+
'atlas': human_brain_atlas,
|
|
85
|
+
'atlas_data': human_brain_atlas_data,
|
|
86
|
+
'region_info': region_info,
|
|
87
|
+
'info_table': human_brain_info
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def fetch_mouse_atlas(region_type: RegionType = 'all'):
|
|
92
|
+
"""
|
|
93
|
+
Fetch the Mouse atlas data and related information.
|
|
94
|
+
|
|
95
|
+
Parameters:
|
|
96
|
+
----------
|
|
97
|
+
region_type : {'cortex', 'subcortex', 'all'}, optional
|
|
98
|
+
Which regions to include in returned region names and info table: cortical, subcortical, or all. Default is 'all'.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
dict: A dictionary containing the following keys:
|
|
102
|
+
- 'atlas': The loaded Mouse atlas image.
|
|
103
|
+
- 'atlas_data': The atlas data as a numpy array.
|
|
104
|
+
- 'region_info': A list of anatomical names for the specified regions.
|
|
105
|
+
- 'info_table': The full ROI information table.
|
|
106
|
+
"""
|
|
107
|
+
mouse_atlas_path,mouse_labels_path = Config.atlas_resources['mouse']
|
|
108
|
+
|
|
109
|
+
if not os.path.exists(mouse_atlas_path):
|
|
110
|
+
raise FileNotFoundError(f"Mouse atlas file not found at {mouse_atlas_path}")
|
|
111
|
+
mouse_brain_atlas = image.load_img(mouse_atlas_path)
|
|
112
|
+
|
|
113
|
+
# Load the ROI information table
|
|
114
|
+
if not os.path.exists(mouse_labels_path):
|
|
115
|
+
raise FileNotFoundError(f"ROI information file not found at {mouse_labels_path}")
|
|
116
|
+
mouse_brain_info_all = pd.read_csv(mouse_labels_path,index_col=0)
|
|
117
|
+
|
|
118
|
+
# Extract region information based on region_type
|
|
119
|
+
cortex_region_list = Config.region_resources['mouse'][0]
|
|
120
|
+
subcortex_region_list = Config.region_resources['mouse'][1]
|
|
121
|
+
|
|
122
|
+
if region_type == 'cortex':
|
|
123
|
+
mouse_brain_info = mouse_brain_info_all.loc[mouse_brain_info_all['Anatomical Name'].isin(cortex_region_list)]
|
|
124
|
+
mouse_brain_info = mouse_brain_info.reset_index(drop=True)
|
|
125
|
+
region_info = mouse_brain_info['Anatomical Name'].values # Cortex regions
|
|
126
|
+
elif region_type == 'subcortex':
|
|
127
|
+
mouse_brain_info = mouse_brain_info_all.loc[mouse_brain_info_all['Anatomical Name'].isin(subcortex_region_list)]
|
|
128
|
+
mouse_brain_info = mouse_brain_info.reset_index(drop=True)
|
|
129
|
+
region_info = mouse_brain_info['Anatomical Name'].values # Cortex regions
|
|
130
|
+
elif region_type == 'all':
|
|
131
|
+
mouse_brain_info = mouse_brain_info_all
|
|
132
|
+
region_info = mouse_brain_info['Anatomical Name'].values
|
|
133
|
+
else:
|
|
134
|
+
raise ValueError(f"Invalid region_type: {region_type}")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
# Convert the atlas data to a numpy array
|
|
138
|
+
mouse_atlas_data = np.asarray(mouse_brain_atlas.dataobj).astype(np.float32)
|
|
139
|
+
|
|
140
|
+
# Return the results as a dictionary
|
|
141
|
+
return {
|
|
142
|
+
'atlas': mouse_brain_atlas,
|
|
143
|
+
'atlas_data': mouse_atlas_data,
|
|
144
|
+
'region_info': region_info,
|
|
145
|
+
'info_table': mouse_brain_info
|
|
146
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from scipy import ndimage
|
|
4
|
+
from nilearn import image
|
|
5
|
+
from transbrain.config import Config
|
|
6
|
+
|
|
7
|
+
def get_region_phenotypes(phenotype_nii_path: str,atlas_dict: dict,method: str = 'mean',resample: bool = True,label_column: str = 'Atlas Index',
|
|
8
|
+
region_column: str = 'Anatomical Name') -> pd.DataFrame:
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
Calculate region-wise phenotype values using a specified brain atlas.
|
|
12
|
+
|
|
13
|
+
This function extracts regional statistics (mean or sum) from a phenotype NIfTI image
|
|
14
|
+
based on a chosen human or mouse brain atlas. The phenotype image can be automatically
|
|
15
|
+
resampled to match the atlas resolution if needed.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
phenotype_nii_path : str
|
|
20
|
+
Path to the input phenotype NIfTI file. Should be in MNI space for human atlases,
|
|
21
|
+
or Allen CCFv3 space for mouse atlas.
|
|
22
|
+
atlas_dict : dict
|
|
23
|
+
A dictionary containing the following keys:
|
|
24
|
+
- 'atlas': The loaded Mouse atlas image.
|
|
25
|
+
- 'atlas_data': The atlas data as a numpy array.
|
|
26
|
+
- 'region_info': A list of anatomical names for the specified regions.
|
|
27
|
+
- 'info_table': The full ROI information table.
|
|
28
|
+
|
|
29
|
+
method : {'mean', 'sum'}, optional
|
|
30
|
+
Method for aggregating voxel values within each region. Default is 'mean'.
|
|
31
|
+
resample : bool, optional
|
|
32
|
+
If True, resample the atlas to match the shape and resolution of the phenotype image.
|
|
33
|
+
Default is True.
|
|
34
|
+
label_column : str, optional
|
|
35
|
+
Name of the column in the atlas label CSV that contains numeric label indices.
|
|
36
|
+
Default is 'Atlas Index'.
|
|
37
|
+
region_column : str, optional
|
|
38
|
+
Name of the column in the atlas label CSV that contains region names.
|
|
39
|
+
Default is 'Anatomical Name'.
|
|
40
|
+
|
|
41
|
+
Returns
|
|
42
|
+
-------
|
|
43
|
+
pandas.DataFrame
|
|
44
|
+
A DataFrame with aggregated phenotype values (mean or sum) for each region, , indexed by brain region name.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
if method not in ('mean', 'sum'):
|
|
48
|
+
raise ValueError(f"Invalid method: '{method}'. Use 'mean' or 'sum'")
|
|
49
|
+
|
|
50
|
+
atlas_path = atlas_dict['atlas']
|
|
51
|
+
atlas_arr = atlas_dict['atlas_data']
|
|
52
|
+
atlas_df = atlas_dict['info_table']
|
|
53
|
+
labels = atlas_df[label_column].values
|
|
54
|
+
|
|
55
|
+
phenotype_img = image.load_img(phenotype_nii_path)
|
|
56
|
+
atlas_img = image.load_img(atlas_path)
|
|
57
|
+
|
|
58
|
+
if resample and phenotype_img.shape != atlas_img.shape:
|
|
59
|
+
print("Resampling phenotype to match atlas...")
|
|
60
|
+
atlas_img = image.resample_to_img(atlas_img, phenotype_img, interpolation='nearest')
|
|
61
|
+
|
|
62
|
+
phenotype_arr = np.asarray(phenotype_img.dataobj)
|
|
63
|
+
|
|
64
|
+
if phenotype_arr.shape != atlas_arr.shape:
|
|
65
|
+
raise ValueError("Phenotype and atlas shape mismatch after resampling")
|
|
66
|
+
|
|
67
|
+
if method == 'mean':
|
|
68
|
+
region_values = ndimage.mean(phenotype_arr, labels=atlas_arr, index=labels)
|
|
69
|
+
else:
|
|
70
|
+
region_values = ndimage.sum(phenotype_arr, labels=atlas_arr, index=labels)
|
|
71
|
+
|
|
72
|
+
result_df = atlas_df.copy()
|
|
73
|
+
result_df['Phenotype'] = region_values
|
|
74
|
+
|
|
75
|
+
result_df = result_df[[region_column,'Phenotype']]
|
|
76
|
+
result_df.columns = ['Region name','Phenotype']
|
|
77
|
+
result_df = result_df.set_index('Region name')
|
|
78
|
+
|
|
79
|
+
return result_df
|
|
80
|
+
|
|
81
|
+
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
file_path = os.path.abspath(__file__)
|
|
4
|
+
dir_path = os.path.dirname(file_path)
|
|
5
|
+
atlas_folder = os.path.join(dir_path, 'atlas')
|
|
6
|
+
graph_embeddings_folder = os.path.join(dir_path, 'graphembeddings')
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Config:
|
|
10
|
+
"""Centralized configuration for TransBrain with minimal structure"""
|
|
11
|
+
|
|
12
|
+
# Atlas paths
|
|
13
|
+
bnatlas_path = os.path.join(atlas_folder, 'bn_atlas_2mm_symmetry.nii.gz')
|
|
14
|
+
bnatlas_label_path = os.path.join(atlas_folder, 'bn_atlas.csv')
|
|
15
|
+
dkatlas_path = os.path.join(atlas_folder, 'dk_atlas_2mm_symmetry.nii.gz')
|
|
16
|
+
dkatlas_label_path = os.path.join(atlas_folder, 'dk_atlas.csv')
|
|
17
|
+
aalatlas_path = os.path.join(atlas_folder, 'aal_atlas_2mm_symmetry.nii.gz')
|
|
18
|
+
aalatlas_label_path = os.path.join(atlas_folder, 'aal_atlas.csv')
|
|
19
|
+
mouseatlas_path = os.path.join(atlas_folder, 'mouse_atlas.nii.gz')
|
|
20
|
+
mouseatlas_label_path = os.path.join(atlas_folder, 'mouse_atlas.csv')
|
|
21
|
+
|
|
22
|
+
atlas_resources = {
|
|
23
|
+
'bn': (bnatlas_path, bnatlas_label_path),
|
|
24
|
+
'dk': (dkatlas_path, dkatlas_label_path),
|
|
25
|
+
'aal': (aalatlas_path, aalatlas_label_path),
|
|
26
|
+
'mouse': (mouseatlas_path, mouseatlas_label_path)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# Graph embeddings paths
|
|
30
|
+
bn_embeddings = os.path.join(graph_embeddings_folder, 'bn_p0.01_q0.1_graph_embeddings.pkl')
|
|
31
|
+
dk_embeddings = os.path.join(graph_embeddings_folder, 'dk_p0.01_q0.1_graph_embeddings.pkl')
|
|
32
|
+
aal_embeddings = os.path.join(graph_embeddings_folder, 'aal_p0.01_q0.1_graph_embeddings.pkl')
|
|
33
|
+
|
|
34
|
+
embeddings_resources = {
|
|
35
|
+
'bn': bn_embeddings,
|
|
36
|
+
'dk': dk_embeddings,
|
|
37
|
+
'aal': aal_embeddings,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# Region definitions
|
|
41
|
+
BN_CORTICAL = (
|
|
42
|
+
'A8m', 'A8dl', 'A9l','A6dl', 'A6m', 'A9m', 'A10m', 'A9/46d', 'IFJ', 'A46', 'A9/46v',
|
|
43
|
+
'A8vl', 'A6vl','A10l', 'A44d', 'IFS', 'A45c', 'A45r', 'A44op', 'A44v','A14m', 'A12/47o',
|
|
44
|
+
'A11l','A11m', 'A13', 'A12/47l','A32p','A32sg','A24cd','A24rv','A4hf', 'A6cdl', 'A4ul',
|
|
45
|
+
'A4t', 'A4tl', 'A6cvl','A1/2/3ll', 'A4ll','A1/2/3ulhf', 'A1/2/3tonIa', 'A2','A1/2/3tru',
|
|
46
|
+
'A7r', 'A7c', 'A5l', 'A7pc', 'A7ip', 'A39c', 'A39rd', 'A40rd', 'A40c', 'A39rv','A40rv',
|
|
47
|
+
'A7m', 'A5m', 'dmPOS','A31','A23d','A23c','A23v','cLinG', 'rCunG','cCunG', 'rLinG',
|
|
48
|
+
'vmPOS', 'mOccG', 'V5/MT+', 'OPC', 'iOccG', 'msOccG', 'lsOccG', 'G', 'vIa', 'dIa',
|
|
49
|
+
'vId/vIg', 'dIg', 'dId','A38m', 'A41/42', 'TE1.0 and TE1.2', 'A22c', 'A38l', 'A22r',
|
|
50
|
+
'A21c','A21r', 'A37dl', 'aSTS', 'A20iv', 'A37elv', 'A20r', 'A20il', 'A37vl', 'A20cl',
|
|
51
|
+
'A20cv', 'A20rv', 'A37mv', 'A37lv', 'A35/36r', 'A35/36c', 'lateral PPHC', 'A28/34',
|
|
52
|
+
'TH','TI','rpSTS','cpSTS'
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
BN_SUBCORTICAL = (
|
|
56
|
+
'mAmyg', 'lAmyg', 'CA1', 'CA4DG', 'CA2CA3', 'subiculum','Claustrum',
|
|
57
|
+
'head of caudate', 'body of caudate', 'Putamen','posterovemtral putamen',
|
|
58
|
+
'nucleus accumbens','external segment of globus pallidus',
|
|
59
|
+
'internal segment of globus pallidus', 'mPMtha', 'Stha','cTtha', 'Otha',
|
|
60
|
+
'mPFtha','lPFtha','rTtha', 'PPtha'
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
DK_CORTICAL = (
|
|
64
|
+
'caudalanteriorcingulate','rostralanteriorcingulate','caudalmiddlefrontal',
|
|
65
|
+
'rostralmiddlefrontal','superiorfrontal','lateralorbitofrontal','medialorbitofrontal',
|
|
66
|
+
'parsopercularis','parsorbitalis','parstriangularis','precentral','postcentral',
|
|
67
|
+
'inferiorparietal','superiorparietal','supramarginal','paracentral','posteriorcingulate',
|
|
68
|
+
'isthmuscingulate','pericalcarine','cuneus','lingual','lateraloccipital','insula',
|
|
69
|
+
'transversetemporal','superiortemporal','middletemporal','inferiortemporal','temporalpole',
|
|
70
|
+
'parahippocampal','entorhinal','fusiform'
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
DK_SUBCORTICAL = (
|
|
74
|
+
'Amygdala','Hippocampus','Accumbens-area','Putamen','Caudate','Pallidum','Thalamus-Proper'
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
AAL_CORTICAL = (
|
|
78
|
+
'CingulateAnt', 'CingulateMid', 'FrontalSupMedial','FrontalSup2','FrontalMid2','OFCmed',
|
|
79
|
+
'OFCant','OFCpost','OFClat','FrontalMedOrb','FrontalInfOrb2','FrontalInfOper',
|
|
80
|
+
'FrontalInfTri','RolandicOper','SuppMotorArea','Precentral','Postcentral','ParietalSup',
|
|
81
|
+
'ParietalInf','SupraMarginal','Angular','ParacentralLobule','Precuneus','CingulatePost',
|
|
82
|
+
'Calcarine','Cuneus','Lingual','OccipitalSup','OccipitalMid','OccipitalInf','Insula',
|
|
83
|
+
'Heschl','TemporalSup','TemporalMid','TemporalInf','TemporalPoleSup','TemporalPoleMid',
|
|
84
|
+
'ParaHippocampal','Fusiform'
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
AAL_SUBCORTICAL = ('Amygdala','Hippocampus','Caudate','Putamen','Pallidum','Thalamus')
|
|
88
|
+
|
|
89
|
+
MOUSE_CORTICAL = (
|
|
90
|
+
'ACAd', 'ACAv', 'PL','ILA', 'ORBl', 'ORBm', 'ORBvl','MOp','SSp-n', 'SSp-bfd', 'SSp-ll', 'SSp-m',
|
|
91
|
+
'SSp-ul', 'SSp-tr', 'SSp-un','SSs','PTLp','RSPagl','RSPd', 'RSPv','VISpm','VISp','VISal','VISl',
|
|
92
|
+
'VISpl','AId','AIp','AIv','GU','VISC','TEa', 'PERI', 'ECT','AUDd', 'AUDp','AUDpo', 'AUDv'
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
MOUSE_SUBCORTICAL = (
|
|
96
|
+
'LA', 'BLA', 'BMA', 'PA','CA1', 'CA2', 'CA3', 'DG', 'SUB', 'ACB', 'CP', 'FS', 'SF', 'SH','sAMY',
|
|
97
|
+
'PAL', 'VENT', 'SPF', 'SPA', 'PP', 'GENd', 'LAT', 'ATN','MED', 'MTN', 'ILM', 'GENv', 'EPI', 'RT'
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
region_resources = {
|
|
101
|
+
'bn': (list(BN_CORTICAL), list(BN_SUBCORTICAL)),
|
|
102
|
+
'dk': (list(DK_CORTICAL), list(DK_SUBCORTICAL)),
|
|
103
|
+
'aal': (list(AAL_CORTICAL), list(AAL_SUBCORTICAL)),
|
|
104
|
+
'mouse': (list(MOUSE_CORTICAL), list(MOUSE_SUBCORTICAL))}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import pickle
|
|
4
|
+
import logging
|
|
5
|
+
from typing import Literal
|
|
6
|
+
from sklearn.linear_model import LinearRegression
|
|
7
|
+
from sklearn.preprocessing import MinMaxScaler
|
|
8
|
+
from transbrain.config import Config
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
logging.basicConfig(level=logging.INFO)
|
|
12
|
+
RegionType = Literal['cortex', 'subcortex', 'all']
|
|
13
|
+
|
|
14
|
+
class SpeciesTrans:
|
|
15
|
+
"""
|
|
16
|
+
Transfer phenotypes between species using graph embeddings.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
atlas_type : {'bn', 'dk', 'aal'}, optional
|
|
21
|
+
The type of atlas to load:
|
|
22
|
+
- 'bn' : Brainnetome Atlas
|
|
23
|
+
- 'dk' : Desikan-Killiany Atlas
|
|
24
|
+
- 'aal' : Automated Anatomical Labeling (AAL) Atlas
|
|
25
|
+
Default is 'bn'.
|
|
26
|
+
|
|
27
|
+
Attributes
|
|
28
|
+
----------
|
|
29
|
+
atlas_type : str
|
|
30
|
+
The selected atlas type.
|
|
31
|
+
regions : dict
|
|
32
|
+
Dictionary containing human and mouse brain regions (cortex, subcortex, all).
|
|
33
|
+
embeddings : np.ndarray
|
|
34
|
+
Loaded graph embeddings used for phenotype translation.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, atlas_type: str = 'bn'):
|
|
38
|
+
self.atlas_type = atlas_type
|
|
39
|
+
self.regions = self._load_region_data()
|
|
40
|
+
self.embeddings = self._load_embeddings()
|
|
41
|
+
logging.info(f'Initialized for {atlas_type} atlas.')
|
|
42
|
+
|
|
43
|
+
def _load_region_data(self) -> dict:
|
|
44
|
+
h_cortex, h_subcortex = Config.region_resources[self.atlas_type]
|
|
45
|
+
m_cortex, m_subcortex = Config.region_resources['mouse']
|
|
46
|
+
return {
|
|
47
|
+
'human': {'cortex': h_cortex, 'subcortex': h_subcortex, 'all': h_cortex + h_subcortex},
|
|
48
|
+
'mouse': {'cortex': m_cortex, 'subcortex': m_subcortex, 'all': m_cortex + m_subcortex}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
def _load_embeddings(self) -> np.ndarray:
|
|
52
|
+
with open(Config.embeddings_resources[self.atlas_type], 'rb') as f:
|
|
53
|
+
return pickle.load(f)
|
|
54
|
+
|
|
55
|
+
def _dual_mapping(self, pheno_data: np.ndarray, source_matrix: np.ndarray,
|
|
56
|
+
target_matrix: np.ndarray, normalize: bool = False,restore: bool = False) -> np.ndarray:
|
|
57
|
+
|
|
58
|
+
"""
|
|
59
|
+
Map phenotype data from source to target space using dual regression.
|
|
60
|
+
|
|
61
|
+
Parameters
|
|
62
|
+
----------
|
|
63
|
+
pheno_data : np.ndarray
|
|
64
|
+
An array of phenotype values (regions,) in the source species.
|
|
65
|
+
source_matrix : np.ndarray
|
|
66
|
+
The embedding matrix for the source species.
|
|
67
|
+
target_matrix : np.ndarray
|
|
68
|
+
The embedding matrix for the target species.
|
|
69
|
+
normalize : bool, optional
|
|
70
|
+
Whether to normalize the phenotype values before regression. Default is False.
|
|
71
|
+
restore : bool, optional
|
|
72
|
+
Whether to inverse-transform the predicted values back to original scale.
|
|
73
|
+
Only used if `normalize=True`.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
np.ndarray
|
|
78
|
+
An array of predicted phenotype values in the target species.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
if restore and not normalize:
|
|
82
|
+
raise ValueError("Restore requires normalized input.")
|
|
83
|
+
|
|
84
|
+
y = pheno_data.reshape(-1, 1)
|
|
85
|
+
scaler = MinMaxScaler() if normalize else None
|
|
86
|
+
|
|
87
|
+
if normalize:
|
|
88
|
+
y = scaler.fit_transform(y)
|
|
89
|
+
|
|
90
|
+
model = LinearRegression().fit(source_matrix, y.ravel())
|
|
91
|
+
prediction = model.predict(target_matrix)
|
|
92
|
+
|
|
93
|
+
if restore:
|
|
94
|
+
return scaler.inverse_transform(prediction.reshape(-1, 1)).ravel()
|
|
95
|
+
return prediction
|
|
96
|
+
|
|
97
|
+
def _translate(self, phenotype: pd.DataFrame, direction: str, region_type: RegionType = 'cortex',
|
|
98
|
+
normalize: bool = True,restore: bool = False) -> pd.DataFrame:
|
|
99
|
+
"""
|
|
100
|
+
Unified translation method for both directions.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
phenotype : pd.DataFrame
|
|
105
|
+
A DataFrame where rows are brain regions and columns are phenotype types.
|
|
106
|
+
direction : {'human_to_mouse', 'mouse_to_human'}
|
|
107
|
+
The translation direction.
|
|
108
|
+
region_type : {'cortex', 'subcortex', 'all'}, optional
|
|
109
|
+
The region subset to use for translation. Default is 'cortex'.
|
|
110
|
+
normalize : bool, optional
|
|
111
|
+
Whether to normalize phenotype values before translation. Default is True.
|
|
112
|
+
restore : bool, optional
|
|
113
|
+
Whether to inverse-transform values back to original scale. Only used if normalize is True.
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
pd.DataFrame
|
|
118
|
+
Translated phenotype values in the target species, indexed by brain region name.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
if direction not in ['human_to_mouse', 'mouse_to_human']:
|
|
122
|
+
raise ValueError("Invalid translation direction.")
|
|
123
|
+
|
|
124
|
+
source_species, target_species = direction.split('_to_')
|
|
125
|
+
region_data = self.regions[source_species][region_type]
|
|
126
|
+
|
|
127
|
+
phenotype = phenotype.T[region_data].T
|
|
128
|
+
n_cortex = len(self.regions[source_species]['cortex'])
|
|
129
|
+
n_subcortex = len(self.regions[source_species]['subcortex'])
|
|
130
|
+
|
|
131
|
+
if region_type == 'cortex':
|
|
132
|
+
padding = ((0, 0), (0, n_subcortex))
|
|
133
|
+
elif region_type == 'subcortex':
|
|
134
|
+
padding = ((0, 0), (n_cortex, 0))
|
|
135
|
+
else:
|
|
136
|
+
padding = None
|
|
137
|
+
|
|
138
|
+
n_human = len(self.regions['human']['all'])
|
|
139
|
+
embed_slices = {
|
|
140
|
+
'mouse_to_human': (slice(n_human, None), slice(0, n_human)),
|
|
141
|
+
'human_to_mouse': (slice(0, n_human), slice(n_human, None))
|
|
142
|
+
}
|
|
143
|
+
src_slice, tgt_slice = embed_slices[direction]
|
|
144
|
+
|
|
145
|
+
results = {}
|
|
146
|
+
for phenotype_name, values in phenotype.items():
|
|
147
|
+
arr = np.pad(values.values[None, :], padding) if padding else values.values[None, :]
|
|
148
|
+
predictions = []
|
|
149
|
+
|
|
150
|
+
for emb in self.embeddings:
|
|
151
|
+
src_mat = emb[src_slice]
|
|
152
|
+
tgt_mat = emb[tgt_slice]
|
|
153
|
+
pred = self._dual_mapping(arr, src_mat, tgt_mat, normalize, restore)
|
|
154
|
+
predictions.append(pred)
|
|
155
|
+
|
|
156
|
+
results[phenotype_name] = np.mean(predictions, axis=0)
|
|
157
|
+
|
|
158
|
+
target_regions = self.regions[target_species]
|
|
159
|
+
if region_type == 'cortex':
|
|
160
|
+
results = {k: v[:len(target_regions['cortex'])] for k, v in results.items()}
|
|
161
|
+
index = target_regions['cortex']
|
|
162
|
+
elif region_type == 'subcortex':
|
|
163
|
+
results = {k: v[-len(target_regions['subcortex']):] for k, v in results.items()}
|
|
164
|
+
index = target_regions['subcortex']
|
|
165
|
+
else:
|
|
166
|
+
index = target_regions['all']
|
|
167
|
+
|
|
168
|
+
logging.info(f'Successfully translated {source_species} {region_type} region to {target_species}.')
|
|
169
|
+
return pd.DataFrame(results, index=index)
|
|
170
|
+
|
|
171
|
+
def mouse_to_human(self, phenotype: pd.DataFrame, region_type: RegionType = 'cortex',
|
|
172
|
+
normalize: bool = True,restore: bool = False) -> pd.DataFrame:
|
|
173
|
+
|
|
174
|
+
"""
|
|
175
|
+
Translate mouse phenotype to human.
|
|
176
|
+
|
|
177
|
+
Parameters
|
|
178
|
+
----------
|
|
179
|
+
phenotype : pd.DataFrame
|
|
180
|
+
Mouse phenotype DataFrame (regions × phenotypes).
|
|
181
|
+
region_type : {'cortex', 'subcortex', 'all'}, optional
|
|
182
|
+
The brain region type to translate. Default is 'cortex'.
|
|
183
|
+
normalize : bool, optional
|
|
184
|
+
Whether to normalize data before translation. Default is True.
|
|
185
|
+
restore : bool, optional
|
|
186
|
+
Whether to restore values back to original scale after translation. Only used if normalize is True.
|
|
187
|
+
Please enable this parameter with caution, unless you are certain that the distributions of this phenotype are consistent between the two species.
|
|
188
|
+
|
|
189
|
+
Returns
|
|
190
|
+
-------
|
|
191
|
+
pd.DataFrame
|
|
192
|
+
Translated human phenotype DataFrame (regions × phenotypes).
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
return self._translate(phenotype, 'mouse_to_human', region_type, normalize, restore)
|
|
196
|
+
|
|
197
|
+
def human_to_mouse(self, phenotype: pd.DataFrame, region_type: RegionType = 'cortex',
|
|
198
|
+
normalize: bool = True,restore: bool = False) -> pd.DataFrame:
|
|
199
|
+
|
|
200
|
+
"""
|
|
201
|
+
Translate human phenotype to mouse.
|
|
202
|
+
|
|
203
|
+
Parameters
|
|
204
|
+
----------
|
|
205
|
+
phenotype : pd.DataFrame
|
|
206
|
+
Human phenotype DataFrame (regions × phenotypes).
|
|
207
|
+
region_type : {'cortex', 'subcortex', 'all'}, optional
|
|
208
|
+
The brain region type to translate. Default is 'cortex'.
|
|
209
|
+
normalize : bool, optional
|
|
210
|
+
Whether to normalize data before translation. Default is True.
|
|
211
|
+
restore : bool, optional
|
|
212
|
+
Whether to restore values back to original scale after translation. Only used if normalize is True.
|
|
213
|
+
Please enable this parameter with caution, unless you are certain that the distributions of this phenotype are consistent between the two species.
|
|
214
|
+
|
|
215
|
+
Returns
|
|
216
|
+
-------
|
|
217
|
+
pd.DataFrame
|
|
218
|
+
Translated mouse phenotype DataFrame (regions × phenotypes).
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
return self._translate(phenotype, 'human_to_mouse', region_type, normalize, restore)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: transbrain
|
|
3
|
+
Version: 0.1.7
|
|
4
|
+
Summary: TransBrain is an integrated computational framework for bidirectional translation of brain-wide phenotypes between humans and mice.
|
|
5
|
+
Home-page: https://github.com/ibpshangzheng/transbrain
|
|
6
|
+
Author: Shangzheng Huang, Tongyu Zhang
|
|
7
|
+
Author-email: huangshangzheng@ibp.ac.cn
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: matplotlib==3.7.5
|
|
15
|
+
Requires-Dist: matplotlib-inline==0.1.7
|
|
16
|
+
Requires-Dist: nibabel==5.2.1
|
|
17
|
+
Requires-Dist: nilearn==0.10.4
|
|
18
|
+
Requires-Dist: numpy==1.24.4
|
|
19
|
+
Requires-Dist: openpyxl==3.1.5
|
|
20
|
+
Requires-Dist: pandas==2.0.3
|
|
21
|
+
Requires-Dist: scikit-learn==1.3.2
|
|
22
|
+
Requires-Dist: scipy==1.10.1
|
|
23
|
+
Requires-Dist: seaborn==0.13.2
|
|
24
|
+
Requires-Dist: six==1.17.0
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
transbrain/__init__.py
|
|
5
|
+
transbrain/atlas.py
|
|
6
|
+
transbrain/base.py
|
|
7
|
+
transbrain/config.py
|
|
8
|
+
transbrain/trans.py
|
|
9
|
+
transbrain.egg-info/PKG-INFO
|
|
10
|
+
transbrain.egg-info/SOURCES.txt
|
|
11
|
+
transbrain.egg-info/dependency_links.txt
|
|
12
|
+
transbrain.egg-info/requires.txt
|
|
13
|
+
transbrain.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
transbrain
|