siibra 1.0.1a2__tar.gz → 1.0.1a5__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.
Potentially problematic release.
This version of siibra might be problematic. Click here for more details.
- {siibra-1.0.1a2/siibra.egg-info → siibra-1.0.1a5}/PKG-INFO +28 -12
- {siibra-1.0.1a2 → siibra-1.0.1a5}/README.rst +25 -10
- siibra-1.0.1a5/siibra/VERSION +1 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/commons.py +10 -1
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/configuration/configuration.py +0 -1
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/configuration/factory.py +4 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/core/assignment.py +18 -7
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/explorer/url.py +2 -2
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/anchor.py +1 -3
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/connectivity/regional_connectivity.py +41 -27
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/feature.py +8 -2
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/image/__init__.py +2 -1
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/image/volume_of_interest.py +9 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/tabular/gene_expression.py +28 -11
- siibra-1.0.1a5/siibra/features/tabular/layerwise_cell_density.py +154 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/tabular/tabular.py +10 -2
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/livequeries/allen.py +3 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/locations/boundingbox.py +4 -3
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/locations/location.py +10 -4
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/locations/point.py +7 -3
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/locations/pointcloud.py +7 -3
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/volumes/parcellationmap.py +3 -1
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/volumes/sparsemap.py +13 -21
- {siibra-1.0.1a2 → siibra-1.0.1a5/siibra.egg-info}/PKG-INFO +28 -12
- siibra-1.0.1a2/siibra/VERSION +0 -1
- siibra-1.0.1a2/siibra/features/tabular/layerwise_cell_density.py +0 -93
- {siibra-1.0.1a2 → siibra-1.0.1a5}/LICENSE +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/MANIFEST.in +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/setup.cfg +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/setup.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/configuration/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/core/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/core/atlas.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/core/concept.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/core/parcellation.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/core/region.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/core/space.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/core/structure.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/exceptions.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/explorer/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/explorer/util.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/connectivity/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/connectivity/functional_connectivity.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/connectivity/streamline_counts.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/connectivity/streamline_lengths.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/connectivity/tracing_connectivity.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/dataset/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/dataset/ebrains.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/image/image.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/image/sections.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/tabular/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/tabular/bigbrain_intensity_profile.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/tabular/cell_density_profile.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/tabular/cortical_profile.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/tabular/layerwise_bigbrain_intensities.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/tabular/receptor_density_fingerprint.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/tabular/receptor_density_profile.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/features/tabular/regional_timeseries_activity.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/livequeries/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/livequeries/bigbrain.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/livequeries/ebrains.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/livequeries/query.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/locations/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/locations/experimental.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/retrieval/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/retrieval/cache.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/retrieval/datasets.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/retrieval/exceptions/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/retrieval/repositories.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/retrieval/requests.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/vocabularies/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/vocabularies/gene_names.json +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/vocabularies/receptor_symbols.json +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/vocabularies/region_aliases.json +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/volumes/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/volumes/providers/__init__.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/volumes/providers/freesurfer.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/volumes/providers/gifti.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/volumes/providers/neuroglancer.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/volumes/providers/nifti.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/volumes/providers/provider.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra/volumes/volume.py +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra.egg-info/SOURCES.txt +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra.egg-info/dependency_links.txt +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra.egg-info/requires.txt +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/siibra.egg-info/top_level.txt +0 -0
- {siibra-1.0.1a2 → siibra-1.0.1a5}/test/test_siibra.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: siibra
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1a5
|
|
4
4
|
Summary: siibra - Software interfaces for interacting with brain atlases
|
|
5
5
|
Home-page: https://github.com/FZJ-INM1-BDA/siibra-python
|
|
6
6
|
Author: Big Data Analytics Group, Forschungszentrum Juelich, Institute of Neuroscience and Medicine (INM-1)
|
|
@@ -33,6 +33,7 @@ Dynamic: classifier
|
|
|
33
33
|
Dynamic: description
|
|
34
34
|
Dynamic: description-content-type
|
|
35
35
|
Dynamic: home-page
|
|
36
|
+
Dynamic: license-file
|
|
36
37
|
Dynamic: requires-dist
|
|
37
38
|
Dynamic: requires-python
|
|
38
39
|
Dynamic: summary
|
|
@@ -43,18 +44,16 @@ Dynamic: summary
|
|
|
43
44
|
siibra - Software interface for interacting with brain atlases
|
|
44
45
|
==============================================================
|
|
45
46
|
|
|
46
|
-
Copyright 2018-
|
|
47
|
+
Copyright 2018-2025, Forschungszentrum Jülich GmbH
|
|
47
48
|
|
|
48
49
|
*Authors: Big Data Analytics Group, Institute of Neuroscience and
|
|
49
50
|
Medicine (INM-1), Forschungszentrum Jülich GmbH*
|
|
50
51
|
|
|
51
52
|
.. intro-start
|
|
52
53
|
|
|
53
|
-
``siibra`` is a Python client to a brain atlas framework that integrates brain parcellations and reference spaces at different spatial scales, and connects them with a broad range of multimodal regional data features.
|
|
54
|
+
``siibra-python`` is a Python client to a brain atlas framework that integrates brain parcellations and reference spaces at different spatial scales, and connects them with a broad range of multimodal regional data features.
|
|
54
55
|
It aims to facilitate programmatic and reproducible incorporation of brain parcellations and brain region features from different sources into neuroscience workflows.
|
|
55
56
|
|
|
56
|
-
**Note:** ``siibra-python`` *is still in development. While care is taken that it works reliably, its API is not yet stable and you may still encounter bugs when using it.*
|
|
57
|
-
|
|
58
57
|
``siibra`` provides structured access to parcellation schemes in different brain reference spaces, including volumetric reference templates at macroscopic and microscopic resolutions as well as surface representations.
|
|
59
58
|
It supports both discretely labelled and statistical (probabilistic) parcellation maps, which can be used to assign brain regions to spatial locations and image signals, to retrieve region-specific neuroscience datasets from multiple online repositories, and to sample information from high-resolution image data.
|
|
60
59
|
The datasets anchored to brain regions address features of molecular, cellular and architecture as well as connectivity, and are complemented with live queries to external repositories as well as dynamic extraction from "big" image volumes such as the 20 micrometer BigBrain model.
|
|
@@ -84,10 +83,26 @@ Installation
|
|
|
84
83
|
|
|
85
84
|
``siibra`` is available on pypi.
|
|
86
85
|
To install the latest released version, simply run ``pip install siibra``.
|
|
86
|
+
The installation typically takes about 2 minutes on a standard computer where Python is already installed.
|
|
87
87
|
In order to work with the latest version from github, use ``pip install git+https://github.com/FZJ-INM1-BDA/siibra-python.git@main``.
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
``siibra-python`` should be installable on recent versions of Windows, Linux and Mac OS in a recent Python 3 environment.
|
|
90
|
+
We run continuous integration tests for versions 3.7 - 3.12 on recent Ubuntu images.
|
|
91
|
+
|
|
92
|
+
The library requires a couple of open source packages, namely:
|
|
93
|
+
```
|
|
94
|
+
anytree >= 2.12.1
|
|
95
|
+
nibabel >= 5.3.2
|
|
96
|
+
appdirs >= 1.4.4
|
|
97
|
+
scikit-image >= 0.25.0
|
|
98
|
+
requests >= 2.32.3
|
|
99
|
+
neuroglancer-scripts >= 1.2.0
|
|
100
|
+
nilearn >= 0.11.0
|
|
101
|
+
filelock >= 3.16.1
|
|
102
|
+
ebrains-drive >= 0.6.0
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
You can also install a docker image with all dependencies included:
|
|
91
106
|
.. code-block:: sh
|
|
92
107
|
|
|
93
108
|
docker run -dit \
|
|
@@ -97,19 +112,20 @@ There is also an image based on jupyter:scipy-notebook, which already includes `
|
|
|
97
112
|
docker-registry.ebrains.eu/siibra/siibra-python:latest
|
|
98
113
|
|
|
99
114
|
|
|
115
|
+
|
|
100
116
|
Documentation & Help
|
|
101
117
|
====================
|
|
102
118
|
|
|
103
119
|
``siibra-python``\ ’s documentation is hosted on https://siibra-python.readthedocs.io.
|
|
104
120
|
The documentation includes a catalogue of documented code examples that walk you through the different concepts and functionalities.
|
|
121
|
+
These examples use real data and include both the code and the produced expected outputs.
|
|
122
|
+
They can be accessed at https://siibra-python.readthedocs.io/en/latest/examples.html, and are
|
|
123
|
+
automatically tested and updated whenever a new version of ``siibra-python`` is published.
|
|
105
124
|
As a new user, it is recommended to go through these examples - they are easy and will quickly provide you with the right code snippets that get you started.
|
|
106
|
-
|
|
107
|
-
We are working on a full API documentation of the library. You find the current status on readthedocs, but be aware that it is not yet complete and as up-to-date as the code examples.
|
|
125
|
+
The documentation on readthedocs further includes introductory explanations and an API reference.
|
|
108
126
|
|
|
109
127
|
If you run into issues, please open a ticket on `EBRAINS support <https://ebrains.eu/support/>`__ or file bugs and
|
|
110
128
|
feature requests on `github <https://github.com/FZJ-INM1-BDA/siibra-python/issues>`__.
|
|
111
|
-
Please keep in mind that ``siibra-python`` is still in development.
|
|
112
|
-
While care is taken to make everything work reliably, the API of the library is not yet stable, and the software is not yet fully tested.
|
|
113
129
|
|
|
114
130
|
.. getting-started-end
|
|
115
131
|
|
|
@@ -4,18 +4,16 @@
|
|
|
4
4
|
siibra - Software interface for interacting with brain atlases
|
|
5
5
|
==============================================================
|
|
6
6
|
|
|
7
|
-
Copyright 2018-
|
|
7
|
+
Copyright 2018-2025, Forschungszentrum Jülich GmbH
|
|
8
8
|
|
|
9
9
|
*Authors: Big Data Analytics Group, Institute of Neuroscience and
|
|
10
10
|
Medicine (INM-1), Forschungszentrum Jülich GmbH*
|
|
11
11
|
|
|
12
12
|
.. intro-start
|
|
13
13
|
|
|
14
|
-
``siibra`` is a Python client to a brain atlas framework that integrates brain parcellations and reference spaces at different spatial scales, and connects them with a broad range of multimodal regional data features.
|
|
14
|
+
``siibra-python`` is a Python client to a brain atlas framework that integrates brain parcellations and reference spaces at different spatial scales, and connects them with a broad range of multimodal regional data features.
|
|
15
15
|
It aims to facilitate programmatic and reproducible incorporation of brain parcellations and brain region features from different sources into neuroscience workflows.
|
|
16
16
|
|
|
17
|
-
**Note:** ``siibra-python`` *is still in development. While care is taken that it works reliably, its API is not yet stable and you may still encounter bugs when using it.*
|
|
18
|
-
|
|
19
17
|
``siibra`` provides structured access to parcellation schemes in different brain reference spaces, including volumetric reference templates at macroscopic and microscopic resolutions as well as surface representations.
|
|
20
18
|
It supports both discretely labelled and statistical (probabilistic) parcellation maps, which can be used to assign brain regions to spatial locations and image signals, to retrieve region-specific neuroscience datasets from multiple online repositories, and to sample information from high-resolution image data.
|
|
21
19
|
The datasets anchored to brain regions address features of molecular, cellular and architecture as well as connectivity, and are complemented with live queries to external repositories as well as dynamic extraction from "big" image volumes such as the 20 micrometer BigBrain model.
|
|
@@ -45,10 +43,26 @@ Installation
|
|
|
45
43
|
|
|
46
44
|
``siibra`` is available on pypi.
|
|
47
45
|
To install the latest released version, simply run ``pip install siibra``.
|
|
46
|
+
The installation typically takes about 2 minutes on a standard computer where Python is already installed.
|
|
48
47
|
In order to work with the latest version from github, use ``pip install git+https://github.com/FZJ-INM1-BDA/siibra-python.git@main``.
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
``siibra-python`` should be installable on recent versions of Windows, Linux and Mac OS in a recent Python 3 environment.
|
|
50
|
+
We run continuous integration tests for versions 3.7 - 3.12 on recent Ubuntu images.
|
|
51
|
+
|
|
52
|
+
The library requires a couple of open source packages, namely:
|
|
53
|
+
```
|
|
54
|
+
anytree >= 2.12.1
|
|
55
|
+
nibabel >= 5.3.2
|
|
56
|
+
appdirs >= 1.4.4
|
|
57
|
+
scikit-image >= 0.25.0
|
|
58
|
+
requests >= 2.32.3
|
|
59
|
+
neuroglancer-scripts >= 1.2.0
|
|
60
|
+
nilearn >= 0.11.0
|
|
61
|
+
filelock >= 3.16.1
|
|
62
|
+
ebrains-drive >= 0.6.0
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
You can also install a docker image with all dependencies included:
|
|
52
66
|
.. code-block:: sh
|
|
53
67
|
|
|
54
68
|
docker run -dit \
|
|
@@ -58,19 +72,20 @@ There is also an image based on jupyter:scipy-notebook, which already includes `
|
|
|
58
72
|
docker-registry.ebrains.eu/siibra/siibra-python:latest
|
|
59
73
|
|
|
60
74
|
|
|
75
|
+
|
|
61
76
|
Documentation & Help
|
|
62
77
|
====================
|
|
63
78
|
|
|
64
79
|
``siibra-python``\ ’s documentation is hosted on https://siibra-python.readthedocs.io.
|
|
65
80
|
The documentation includes a catalogue of documented code examples that walk you through the different concepts and functionalities.
|
|
81
|
+
These examples use real data and include both the code and the produced expected outputs.
|
|
82
|
+
They can be accessed at https://siibra-python.readthedocs.io/en/latest/examples.html, and are
|
|
83
|
+
automatically tested and updated whenever a new version of ``siibra-python`` is published.
|
|
66
84
|
As a new user, it is recommended to go through these examples - they are easy and will quickly provide you with the right code snippets that get you started.
|
|
67
|
-
|
|
68
|
-
We are working on a full API documentation of the library. You find the current status on readthedocs, but be aware that it is not yet complete and as up-to-date as the code examples.
|
|
85
|
+
The documentation on readthedocs further includes introductory explanations and an API reference.
|
|
69
86
|
|
|
70
87
|
If you run into issues, please open a ticket on `EBRAINS support <https://ebrains.eu/support/>`__ or file bugs and
|
|
71
88
|
feature requests on `github <https://github.com/FZJ-INM1-BDA/siibra-python/issues>`__.
|
|
72
|
-
Please keep in mind that ``siibra-python`` is still in development.
|
|
73
|
-
While care is taken to make everything work reliably, the API of the library is not yet stable, and the software is not yet fully tested.
|
|
74
89
|
|
|
75
90
|
.. getting-started-end
|
|
76
91
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.0.1-alpha.5
|
|
@@ -534,13 +534,21 @@ def resample_img_to_img(
|
|
|
534
534
|
-------
|
|
535
535
|
Nifti1Image
|
|
536
536
|
"""
|
|
537
|
+
from nilearn._version import version as nilearn_version
|
|
538
|
+
from packaging.version import Version
|
|
539
|
+
|
|
537
540
|
interpolation = "nearest" if np.array_equal(np.unique(source_img.dataobj), [0, 1]) else "linear"
|
|
538
|
-
|
|
541
|
+
kwargs = dict(
|
|
539
542
|
source_img=source_img,
|
|
540
543
|
target_img=target_img,
|
|
541
544
|
interpolation=interpolation,
|
|
542
545
|
force_resample=True, # False is intended for testing. see nilearn docs
|
|
543
546
|
)
|
|
547
|
+
if Version(nilearn_version) >= Version("0.11.0"):
|
|
548
|
+
# because nilearn>=0.11.0 don't support "copy_header" and python <= 3.8
|
|
549
|
+
kwargs["copy_header"] = True # use new default in nilearn >= 0.11.0
|
|
550
|
+
|
|
551
|
+
resampled_img = resample_to_img(**kwargs)
|
|
544
552
|
return resampled_img
|
|
545
553
|
|
|
546
554
|
|
|
@@ -725,6 +733,7 @@ class Species(Enum):
|
|
|
725
733
|
MACACA_MULATTA = 5
|
|
726
734
|
MACACA_FUSCATA = 6
|
|
727
735
|
CHLOROCEBUS_AETHIOPS_SABAEUS = 7
|
|
736
|
+
CALLITHRIX_JACCHUS = 8
|
|
728
737
|
|
|
729
738
|
UNSPECIFIED_SPECIES = 999
|
|
730
739
|
|
|
@@ -487,6 +487,10 @@ class Factory:
|
|
|
487
487
|
return volume_of_interest.LSFMVolumeOfInterest(
|
|
488
488
|
modality="Light Sheet Fluorescence Microscopy", **kwargs
|
|
489
489
|
)
|
|
490
|
+
elif modality == "morphometry":
|
|
491
|
+
return volume_of_interest.MorphometryVolumeOfInterest(
|
|
492
|
+
modality="Morphometry", **kwargs
|
|
493
|
+
)
|
|
490
494
|
else:
|
|
491
495
|
raise ValueError(
|
|
492
496
|
f"No method for building image section feature type {modality}."
|
|
@@ -26,12 +26,12 @@ T = TypeVar("T")
|
|
|
26
26
|
|
|
27
27
|
class Qualification(Enum):
|
|
28
28
|
EXACT = 1
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
APPROXIMATE = 2
|
|
30
|
+
OTHER_VERSION = 3
|
|
31
|
+
CONTAINED = 4
|
|
32
|
+
CONTAINS = 5
|
|
33
|
+
OVERLAPS = 6
|
|
34
|
+
HOMOLOGOUS = 7
|
|
35
35
|
|
|
36
36
|
@property
|
|
37
37
|
def verb(self):
|
|
@@ -67,6 +67,17 @@ class Qualification(Enum):
|
|
|
67
67
|
assert self in inverses, f"{str(self)} inverses cannot be found."
|
|
68
68
|
return inverses[self]
|
|
69
69
|
|
|
70
|
+
def __lt__(self, other: "Qualification"):
|
|
71
|
+
"""
|
|
72
|
+
This is used to sort feature query results. Since it is very difficult
|
|
73
|
+
to determine a well-ordering principle and it is difficult to sort
|
|
74
|
+
without one, the enum values are used for sorting. This means
|
|
75
|
+
not all comparisons have logical basis but they are well-defined,
|
|
76
|
+
making it reproducible but also clearly distinguishes important
|
|
77
|
+
comparisons.
|
|
78
|
+
"""
|
|
79
|
+
return self.value < other.value
|
|
80
|
+
|
|
70
81
|
def __str__(self):
|
|
71
82
|
return f"{self.__class__.__name__}={self.name.lower()}"
|
|
72
83
|
|
|
@@ -108,4 +119,4 @@ class AnatomicalAssignment(Generic[T]):
|
|
|
108
119
|
def __lt__(self, other: 'AnatomicalAssignment'):
|
|
109
120
|
if not isinstance(other, AnatomicalAssignment):
|
|
110
121
|
raise ValueError(f"Cannot compare AnatomicalAssignment with instances of '{type(other)}'")
|
|
111
|
-
return self.qualification
|
|
122
|
+
return self.qualification < other.qualification
|
|
@@ -136,7 +136,7 @@ def encode_url(
|
|
|
136
136
|
|
|
137
137
|
try:
|
|
138
138
|
result_props = region.spatial_props(space, maptype="labelled")
|
|
139
|
-
if len(result_props
|
|
139
|
+
if len(result_props) == 0:
|
|
140
140
|
return return_url + nav_string.format(encoded_nav=encoded_position or "0.0.0", **zoom_kwargs)
|
|
141
141
|
except Exception as e:
|
|
142
142
|
print(f"Cannot get_spatial_props {str(e)}")
|
|
@@ -144,7 +144,7 @@ def encode_url(
|
|
|
144
144
|
raise e
|
|
145
145
|
return return_url + nav_string.format(encoded_nav=encoded_position or "0.0.0", **zoom_kwargs)
|
|
146
146
|
|
|
147
|
-
centroid = result_props
|
|
147
|
+
centroid = result_props[0].centroid
|
|
148
148
|
|
|
149
149
|
encoded_centroid = separator.join(
|
|
150
150
|
[encode_number(math.floor(val * 1e6)) for val in centroid]
|
|
@@ -176,9 +176,7 @@ class AnatomicalAnchor:
|
|
|
176
176
|
assignments.append(region.assign(concept))
|
|
177
177
|
self._assignments[concept] = sorted(a for a in assignments if a is not None)
|
|
178
178
|
|
|
179
|
-
self._last_matched_concept = concept
|
|
180
|
-
if len(self._assignments[concept]) > 0 \
|
|
181
|
-
else None
|
|
179
|
+
self._last_matched_concept = concept if len(self._assignments[concept]) > 0 else None
|
|
182
180
|
return self._assignments[concept]
|
|
183
181
|
|
|
184
182
|
def matches(self, concept: Union[BrainStructure, Space]) -> bool:
|
|
@@ -104,6 +104,7 @@ class RegionalConnectivity(Feature, Compoundable):
|
|
|
104
104
|
self._matrix = None
|
|
105
105
|
self._subject = subject
|
|
106
106
|
self._feature = feature
|
|
107
|
+
self._matrix_std = None # only used for compound feature
|
|
107
108
|
|
|
108
109
|
@property
|
|
109
110
|
def subject(self):
|
|
@@ -170,6 +171,9 @@ class RegionalConnectivity(Feature, Compoundable):
|
|
|
170
171
|
merged._matrix = elements[0]._arraylike_to_dataframe(
|
|
171
172
|
np.stack(all_arrays).mean(0)
|
|
172
173
|
)
|
|
174
|
+
merged._matrix_std = elements[0]._arraylike_to_dataframe(
|
|
175
|
+
np.stack(all_arrays).std(0)
|
|
176
|
+
)
|
|
173
177
|
return merged
|
|
174
178
|
|
|
175
179
|
def _plot_matrix(
|
|
@@ -258,10 +262,14 @@ class RegionalConnectivity(Feature, Compoundable):
|
|
|
258
262
|
non-symmetric matrices. ('column' or 'row')
|
|
259
263
|
"""
|
|
260
264
|
matrix = self.data
|
|
265
|
+
assert isinstance(matrix, pd.DataFrame)
|
|
266
|
+
matrix_std = self._matrix_std
|
|
261
267
|
if direction.lower() not in ['column', 'row']:
|
|
262
268
|
raise ValueError("Direction can only be 'column' or 'row'")
|
|
263
269
|
if direction.lower() == 'row':
|
|
264
270
|
matrix = matrix.transpose()
|
|
271
|
+
if matrix_std is not None:
|
|
272
|
+
matrix_std = matrix_std.transpose()
|
|
265
273
|
|
|
266
274
|
def matches(r1, r2):
|
|
267
275
|
if isinstance(r1, tuple):
|
|
@@ -270,32 +278,38 @@ class RegionalConnectivity(Feature, Compoundable):
|
|
|
270
278
|
assert isinstance(r1, _region.Region)
|
|
271
279
|
return r1.matches(r2)
|
|
272
280
|
|
|
273
|
-
|
|
274
|
-
if
|
|
281
|
+
# decode region spec
|
|
282
|
+
region_candidates = [r for r in matrix.index if matches(r, region)]
|
|
283
|
+
if len(region_candidates) == 0:
|
|
275
284
|
raise ValueError(f"Invalid region specification: {region}")
|
|
276
|
-
|
|
277
|
-
raise ValueError(f"Region specification {region} matched more than one profile: {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
285
|
+
if len(region_candidates) > 1:
|
|
286
|
+
raise ValueError(f"Region specification {region} matched more than one profile: {region_candidates}")
|
|
287
|
+
region = region_candidates[0]
|
|
288
|
+
|
|
289
|
+
# create DataFrame
|
|
290
|
+
data = matrix[region].to_frame('mean')
|
|
291
|
+
if matrix_std is not None:
|
|
292
|
+
data = pd.concat([data, matrix_std[region].rename('std')], axis=1)
|
|
293
|
+
|
|
294
|
+
last_index = len(data) if max_rows is None else min(max_rows, len(data))
|
|
295
|
+
|
|
296
|
+
data = (
|
|
297
|
+
data
|
|
298
|
+
.query(f'`mean` > {min_connectivity}')
|
|
299
|
+
.sort_values(by="mean", ascending=False)
|
|
300
|
+
.rename_axis('Target regions')
|
|
301
|
+
)[:last_index]
|
|
302
|
+
|
|
303
|
+
return Tabular(
|
|
304
|
+
description=self.description,
|
|
305
|
+
modality=f"{self.modality} {self.cohort}",
|
|
306
|
+
anchor=_anchor.AnatomicalAnchor(
|
|
307
|
+
species=list(self.anchor.species)[0],
|
|
308
|
+
region=region
|
|
309
|
+
),
|
|
310
|
+
data=data,
|
|
311
|
+
datasets=self.datasets
|
|
312
|
+
)
|
|
299
313
|
|
|
300
314
|
def plot(
|
|
301
315
|
self,
|
|
@@ -336,8 +350,8 @@ class RegionalConnectivity(Feature, Compoundable):
|
|
|
336
350
|
profile = self.get_profile(regions, min_connectivity, max_rows, direction)
|
|
337
351
|
kwargs["kind"] = kwargs.get("kind", "barh")
|
|
338
352
|
if backend == "matplotlib":
|
|
339
|
-
kwargs["
|
|
340
|
-
return profile.
|
|
353
|
+
kwargs["logy"] = kwargs.get("logy", logscale)
|
|
354
|
+
return profile.plot(*args, backend=backend, **kwargs)
|
|
341
355
|
elif backend == "plotly":
|
|
342
356
|
kwargs.update({
|
|
343
357
|
"color": kwargs.get("color", profile.data.columns[0]),
|
|
@@ -232,7 +232,10 @@ class Feature:
|
|
|
232
232
|
from ..configuration.configuration import Configuration
|
|
233
233
|
conf = Configuration()
|
|
234
234
|
Configuration.register_cleanup(cls._clean_instances)
|
|
235
|
-
|
|
235
|
+
if cls._configuration_folder not in conf.folders:
|
|
236
|
+
logger.debug(f"{cls._configuration_folder} is not in current configuration")
|
|
237
|
+
return []
|
|
238
|
+
|
|
236
239
|
cls._preconfigured_instances = [
|
|
237
240
|
o for o in conf.build_objects(cls._configuration_folder)
|
|
238
241
|
if isinstance(o, cls)
|
|
@@ -580,7 +583,10 @@ class Feature:
|
|
|
580
583
|
# with the query concept.
|
|
581
584
|
live_instances = feature_type._livequery(concept, **kwargs)
|
|
582
585
|
|
|
583
|
-
results =
|
|
586
|
+
results = sorted(
|
|
587
|
+
dict.fromkeys(preconfigured_instances + live_instances), # to remove duplicates
|
|
588
|
+
key=lambda f: min(f.last_match_result) if f.last_match_result else False, # to order according to assignmnent ranking
|
|
589
|
+
)
|
|
584
590
|
return CompoundFeature._compound(results, concept)
|
|
585
591
|
|
|
586
592
|
@classmethod
|
|
@@ -78,3 +78,12 @@ class LSFMVolumeOfInterest(
|
|
|
78
78
|
):
|
|
79
79
|
def __init__(self, modality, **kwargs):
|
|
80
80
|
image.Image.__init__(self, **kwargs, modality=modality)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class MorphometryVolumeOfInterest(
|
|
84
|
+
image.Image,
|
|
85
|
+
configuration_folder="features/images/vois/morphometry",
|
|
86
|
+
category="macrostructural"
|
|
87
|
+
):
|
|
88
|
+
def __init__(self, modality, **kwargs):
|
|
89
|
+
image.Image.__init__(self, **kwargs, modality=modality)
|
|
@@ -225,6 +225,7 @@ class GeneExpressions(
|
|
|
225
225
|
datasets=datasets
|
|
226
226
|
)
|
|
227
227
|
self.unit = "expression level"
|
|
228
|
+
self._genes = list(set(genes))
|
|
228
229
|
|
|
229
230
|
def plot(self, *args, backend="matplotlib", **kwargs):
|
|
230
231
|
"""
|
|
@@ -239,18 +240,34 @@ class GeneExpressions(
|
|
|
239
240
|
Keyword arguments are passed on to the plot command.
|
|
240
241
|
"""
|
|
241
242
|
wrapwidth = kwargs.pop("textwrap") if "textwrap" in kwargs else 40
|
|
242
|
-
kwargs["title"] = kwargs.pop(
|
|
243
|
-
|
|
244
|
-
|
|
243
|
+
kwargs["title"] = kwargs.pop(
|
|
244
|
+
"title",
|
|
245
|
+
"\n".join(wrap(
|
|
246
|
+
f"{self.modality}\n{self.anchor._regionspec or self.anchor.location}",
|
|
247
|
+
wrapwidth
|
|
248
|
+
))
|
|
249
|
+
)
|
|
250
|
+
kwargs["kind"] = kwargs.get("kind", "box")
|
|
245
251
|
if backend == "matplotlib":
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
252
|
+
if kwargs["kind"] == "box":
|
|
253
|
+
from matplotlib.pyplot import tight_layout
|
|
254
|
+
|
|
255
|
+
title = kwargs.pop("title")
|
|
256
|
+
default_kwargs = {
|
|
257
|
+
"grid": True,
|
|
258
|
+
'by': "gene",
|
|
259
|
+
'column': ['level'],
|
|
260
|
+
'showfliers': False,
|
|
261
|
+
'ylabel': 'expression level',
|
|
262
|
+
'xlabel': 'gene',
|
|
263
|
+
'color': 'dimgray',
|
|
264
|
+
'rot': 90 if len(self._genes) > 1 else 0,
|
|
265
|
+
}
|
|
266
|
+
ax, *_ = self.data.plot(*args, backend=backend, **{**default_kwargs, **kwargs})
|
|
267
|
+
ax.set_title(title)
|
|
268
|
+
tight_layout()
|
|
269
|
+
return ax
|
|
270
|
+
return self.data.plot(*args, backend=backend, **kwargs)
|
|
254
271
|
elif backend == "plotly":
|
|
255
272
|
kwargs["title"] = kwargs["title"].replace('\n', "<br>")
|
|
256
273
|
return self.data.plot(y='level', x='gene', backend=backend, **kwargs)
|