insitupy-spatial 0.6.1__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.
- insitupy_spatial-0.6.1/LICENSE +29 -0
- insitupy_spatial-0.6.1/PKG-INFO +164 -0
- insitupy_spatial-0.6.1/README.md +130 -0
- insitupy_spatial-0.6.1/insitupy/__init__.py +33 -0
- insitupy_spatial-0.6.1/insitupy/_constants.py +68 -0
- insitupy_spatial-0.6.1/insitupy/_core/__init__.py +0 -0
- insitupy_spatial-0.6.1/insitupy/_core/_callbacks.py +168 -0
- insitupy_spatial-0.6.1/insitupy/_core/_checks.py +197 -0
- insitupy_spatial-0.6.1/insitupy/_core/_deprecated.py +24 -0
- insitupy_spatial-0.6.1/insitupy/_core/_layers.py +312 -0
- insitupy_spatial-0.6.1/insitupy/_core/_mixins.py +22 -0
- insitupy_spatial-0.6.1/insitupy/_core/_save.py +150 -0
- insitupy_spatial-0.6.1/insitupy/_core/_widgets.py +521 -0
- insitupy_spatial-0.6.1/insitupy/_core/_xenium.py +201 -0
- insitupy_spatial-0.6.1/insitupy/_core/config.py +91 -0
- insitupy_spatial-0.6.1/insitupy/_core/dataclasses.py +1214 -0
- insitupy_spatial-0.6.1/insitupy/_core/insitudata.py +2298 -0
- insitupy_spatial-0.6.1/insitupy/_core/insituexperiment.py +908 -0
- insitupy_spatial-0.6.1/insitupy/_core/reader.py +137 -0
- insitupy_spatial-0.6.1/insitupy/_core/registration.py +290 -0
- insitupy_spatial-0.6.1/insitupy/_exceptions.py +163 -0
- insitupy_spatial-0.6.1/insitupy/_warnings.py +5 -0
- insitupy_spatial-0.6.1/insitupy/datasets/README.md +4 -0
- insitupy_spatial-0.6.1/insitupy/datasets/__init__.py +6 -0
- insitupy_spatial-0.6.1/insitupy/datasets/datasets.py +467 -0
- insitupy_spatial-0.6.1/insitupy/datasets/download.py +70 -0
- insitupy_spatial-0.6.1/insitupy/images/__init__.py +5 -0
- insitupy_spatial-0.6.1/insitupy/images/axes.py +41 -0
- insitupy_spatial-0.6.1/insitupy/images/io.py +317 -0
- insitupy_spatial-0.6.1/insitupy/images/registration.py +425 -0
- insitupy_spatial-0.6.1/insitupy/images/utils.py +301 -0
- insitupy_spatial-0.6.1/insitupy/io/__init__.py +2 -0
- insitupy_spatial-0.6.1/insitupy/io/baysor.py +53 -0
- insitupy_spatial-0.6.1/insitupy/io/files.py +56 -0
- insitupy_spatial-0.6.1/insitupy/io/geo.py +142 -0
- insitupy_spatial-0.6.1/insitupy/io/io.py +261 -0
- insitupy_spatial-0.6.1/insitupy/io/plots.py +27 -0
- insitupy_spatial-0.6.1/insitupy/palettes.py +81 -0
- insitupy_spatial-0.6.1/insitupy/plotting/__init__.py +5 -0
- insitupy_spatial-0.6.1/insitupy/plotting/_colors.py +178 -0
- insitupy_spatial-0.6.1/insitupy/plotting/expression_along_axis.py +980 -0
- insitupy_spatial-0.6.1/insitupy/plotting/go.py +255 -0
- insitupy_spatial-0.6.1/insitupy/plotting/plots.py +186 -0
- insitupy_spatial-0.6.1/insitupy/plotting/volcano.py +110 -0
- insitupy_spatial-0.6.1/insitupy/utils/__init__.py +3 -0
- insitupy_spatial-0.6.1/insitupy/utils/_calc.py +173 -0
- insitupy_spatial-0.6.1/insitupy/utils/_patterns.py +522 -0
- insitupy_spatial-0.6.1/insitupy/utils/_regression.py +326 -0
- insitupy_spatial-0.6.1/insitupy/utils/_scanorama.py +69 -0
- insitupy_spatial-0.6.1/insitupy/utils/deg.py +58 -0
- insitupy_spatial-0.6.1/insitupy/utils/go.py +429 -0
- insitupy_spatial-0.6.1/insitupy/utils/panels.py +69 -0
- insitupy_spatial-0.6.1/insitupy/utils/preprocessing.py +151 -0
- insitupy_spatial-0.6.1/insitupy/utils/qc.py +87 -0
- insitupy_spatial-0.6.1/insitupy/utils/spatialdata.py +307 -0
- insitupy_spatial-0.6.1/insitupy/utils/utils.py +393 -0
- insitupy_spatial-0.6.1/pyproject.toml +41 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024, J. Wirth
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
* Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
* Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: insitupy-spatial
|
|
3
|
+
Version: 0.6.1
|
|
4
|
+
Summary: Package introducing the InSituPy framework to analyze single-cell spatial transcriptomics data.
|
|
5
|
+
License: BSD-3-Clause
|
|
6
|
+
Author: Johannes Wirth
|
|
7
|
+
Author-email: jwrth <j.wirth@tum.de>
|
|
8
|
+
Requires-Python: >=3.9.0,<3.10.0
|
|
9
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Requires-Dist: adjusttext (>=1.3.0,<2.0.0)
|
|
13
|
+
Requires-Dist: dask (>=2023.9.2,<2024.0.0)
|
|
14
|
+
Requires-Dist: dask-image (==2023.8.1)
|
|
15
|
+
Requires-Dist: fastparquet (>=2023.10.1,<2024.0.0)
|
|
16
|
+
Requires-Dist: fiona (==1.10.0)
|
|
17
|
+
Requires-Dist: geopandas (>=0.14.4,<1.0.0)
|
|
18
|
+
Requires-Dist: napari[all] (==0.4.18)
|
|
19
|
+
Requires-Dist: numpy (==1.26.4)
|
|
20
|
+
Requires-Dist: opencv-python (==4.8.0.76)
|
|
21
|
+
Requires-Dist: openpyxl (>=3.1.2,<4.0.0)
|
|
22
|
+
Requires-Dist: parse (==1.19.1)
|
|
23
|
+
Requires-Dist: plottable (==0.1.5)
|
|
24
|
+
Requires-Dist: pyarrow (>=14.0.1,<15.0.0)
|
|
25
|
+
Requires-Dist: pytest (>=7.4.2,<8.0.0)
|
|
26
|
+
Requires-Dist: scanpy[leiden] (==1.10.3)
|
|
27
|
+
Requires-Dist: scikit-image (>=0.21.0,<1.0.0)
|
|
28
|
+
Requires-Dist: scikit-misc (==0.3.1)
|
|
29
|
+
Requires-Dist: toml (>=0.10.2,<1.0.0)
|
|
30
|
+
Requires-Dist: xmltodict (==0.13.0)
|
|
31
|
+
Requires-Dist: zarr (>=2.16.1,<3.0.0)
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# InSituPy: A framework for histology-guided, multi-sample analysis of single-cell spatial transcriptomics data
|
|
35
|
+
|
|
36
|
+
<p align="center">
|
|
37
|
+
<img src="https://github.com/SpatialPathology/InSituPy/blob/main/logo/insitupy_logo.png?raw=true?raw=true" width="500">
|
|
38
|
+
</p>
|
|
39
|
+
|
|
40
|
+
InSituPy is a Python package designed to facilitate the analysis of single-cell spatial transcriptomics data. With InSituPy, you can easily load, visualize, and analyze the data, enabling and simplifying the comprehensive exploration of spatial gene expression patterns within tissue sections and across multiple samples.
|
|
41
|
+
Currently the analysis is focused on data from the [_Xenium In Situ_](https://www.10xgenomics.com/platforms/xenium) methodology but a broader range of reading functions will be implemented in the future.
|
|
42
|
+
|
|
43
|
+
## Latest changes
|
|
44
|
+
|
|
45
|
+
### Update to `>=0.6.0`
|
|
46
|
+
* Changed reading logic of `cell_names` in `BoundariesData`: this might lead to issues with backward compatibility but generalizes the reading of boundaries data opening it for other technologies.
|
|
47
|
+
* Adapt viewer for smaller screens
|
|
48
|
+
* Revised automated registration pipeline:
|
|
49
|
+
* Fixed issue with large multiplexed IF images.
|
|
50
|
+
* Area dependent number of minimum matches to make registration pipeline also work on small images.
|
|
51
|
+
* add registration demo notebook for pancreas data
|
|
52
|
+
* by default remove history of variable data when calling `.save()`
|
|
53
|
+
|
|
54
|
+
### Update to `0.5.0`
|
|
55
|
+
#### Major changes in reading/loading logic!
|
|
56
|
+
This might conflict with the backwards compatibility of this version! If there are issues with loading reading `InSituPy` projects saved with older version, please let me know to find workarounds!
|
|
57
|
+
* Reduced focus on Xenium method in data structure
|
|
58
|
+
* `InSituData.read()` substitutes `read_xenium` for reading of `InSituPy` projects. `read_xenium` used now to read data from Xenium data folders
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
### Prerequisites
|
|
63
|
+
|
|
64
|
+
1. **Create and activate a conda environment:**
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
conda create --name insitupy python=3.9
|
|
68
|
+
conda activate insitupy
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Method 1: Installation from Cloned Repository
|
|
72
|
+
|
|
73
|
+
1. **Clone the repository to your local machine:**
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
git clone https://github.com/jwrth/InSituPy.git
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
2. **Navigate to the cloned repository and select the right branch:**
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
cd InSituPy
|
|
83
|
+
|
|
84
|
+
# Optionally: switch to dev branch
|
|
85
|
+
git checkout dev
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
3. **Install the required packages using `pip` within the conda environment:**
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# basic installation
|
|
92
|
+
pip install .
|
|
93
|
+
|
|
94
|
+
# for developmental purposes add the -e flag
|
|
95
|
+
pip install -e .
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Method 2: Direct Installation from GitHub
|
|
99
|
+
|
|
100
|
+
1. **Install directly from GitHub:**
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# for installation without napari use
|
|
104
|
+
pip install git+https://github.com/jwrth/InSituPy.git
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Make sure you have Conda installed on your system before proceeding with these steps. If not, you can install Miniconda or Anaconda from [https://docs.conda.io/en/latest/miniconda.html](https://docs.conda.io/en/latest/miniconda.html).
|
|
108
|
+
|
|
109
|
+
To ensure that the InSituPy package is available as a kernel in Jupyter notebooks within your conda environment, you can follow the instructions [here](https://ipython.readthedocs.io/en/stable/install/kernel_install.html).
|
|
110
|
+
|
|
111
|
+
## Getting started
|
|
112
|
+
|
|
113
|
+
### Documentation
|
|
114
|
+
|
|
115
|
+
For detailed instructions on using InSituPy, refer to the [official documentation](https://InSituPy.readthedocs.io), which will be made public after publication. The documentation will provide comprehensive guides on installation, usage, and advanced features.
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
### Tutorials
|
|
119
|
+
|
|
120
|
+
Explore the tutorials in `./notebooks/` to learn how to use InSituPy:
|
|
121
|
+
|
|
122
|
+
#### Sample level analysis
|
|
123
|
+
|
|
124
|
+
These tutorials focus on the preprocessing, analysis and handling of individual samples.
|
|
125
|
+
|
|
126
|
+
1. [Registration of additional images](notebooks/01_InSituPy_demo_register_images.ipynb) - Learn how to register additional images to the spatial transcriptomics data.
|
|
127
|
+
1. Alternatively this is also implemented for an example dataset from [pancreatic cancer](notebooks/pancreas/01panc_InSituPy_demo_register_images.ipynb)
|
|
128
|
+
3. [Basic analysis functionalities](notebooks/02_InSituPy_demo_analyze.ipynb) - Learn about the basic functionalities, such as loading of data, basic preprocessing and interactive visualization with napari.
|
|
129
|
+
4. [Add annotations](notebooks/03_InSituPy_demo_annotations.ipynb) - Learn how to add annotations from external software such as [QuPath](https://qupath.github.io/) and do annotations in the napari viewer.
|
|
130
|
+
5. [Crop data](notebooks/04_InSituPy_demo_crop.ipynb) - Learn how to crop your data to focus your analysis on specific areas in the tissue.
|
|
131
|
+
6. [Cell type annotation](notebooks/05_InSituPy_cell_type_annotation.ipynb) - Shows an example workflow to annotate the cell types.
|
|
132
|
+
7. [Explore gene expression along axis](notebooks/06_InSituPy_gene_expression_along_axis_pattern.ipynb) - Example cases showing how to correlate gene expression with e.g. the distance to histological annotations.
|
|
133
|
+
8. [Build an `InSituData` object from scratch](notebooks/09_InSituPy_build_objects_from_scratch.ipynb) - General introduction on how to build an `InSituData` object from scratch.
|
|
134
|
+
|
|
135
|
+
#### Experiment-level analysis
|
|
136
|
+
|
|
137
|
+
This set of tutorials focuses on
|
|
138
|
+
|
|
139
|
+
1. [Analyze multiple samples at once with InSituPy](notebooks/07_InSituPy_InSituExperiment.ipynb) - Introduces the main concepts behind the `InSituExperiment` class and how to work with multiple samples at once.
|
|
140
|
+
2. [Differential gene expression analysis](notebooks/08_InSituPy_differential_gene_expression.ipynb) - Perform differential gene expression analysis within one sample and across multiple samples.
|
|
141
|
+
|
|
142
|
+
### Example data
|
|
143
|
+
|
|
144
|
+
If you want to test the pipeline on different example datasets, [this notebook](notebooks/00_InSituPy_demo_datasets.ipynb) provides an overview of functions to download _Xenium In Situ_ data from official sources.
|
|
145
|
+
|
|
146
|
+
## Features
|
|
147
|
+
|
|
148
|
+
- **Data Preprocessing:** InSituPy provides functions for normalizing, filtering, and transforming raw in situ transcriptomics data.
|
|
149
|
+
- **Interactive Visualization:** Create interactive plots using [napari](https://napari.org/stable/#) to easily explore spatial gene expression patterns.
|
|
150
|
+
- **Annotation:** Annotate _Xenium In Situ_ data in the napari viewer or import annotations from external tools like [QuPath](https://qupath.github.io/).
|
|
151
|
+
- **Multi-sample analysis:** Perform analysis on an experiment-level, i.e. with multiple samples at once.
|
|
152
|
+
|
|
153
|
+
## Contributing
|
|
154
|
+
|
|
155
|
+
Contributions are welcome! If you find any issues or have suggestions for new features, please open an [issue](https://github.com/SpatialPathology/InSituPy/issues) or submit a pull request.
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
InSituPy is licensed under the [BSD-3-Clause](LICENSE).
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
**InSituPy** is developed and maintained by [Johannes Wirth](https://github.com/jwrth) and [Anna Chernysheva](https://github.com/annachernysheva179). Feedback is highly appreciated and hopefully **InSituPy** helps you with your analysis of spatial transcriptomics data. The package is thought to be a starting point to simplify the analysis of in situ sequencing data in Python and it would be exciting to integrate functionalities for larger and more comprehensive data structures. Currently, the framework focuses on the analysis of _Xenium In Situ_ data but it is planned to integrate more methodologies and any support on this is highly welcomed.
|
|
164
|
+
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# InSituPy: A framework for histology-guided, multi-sample analysis of single-cell spatial transcriptomics data
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://github.com/SpatialPathology/InSituPy/blob/main/logo/insitupy_logo.png?raw=true?raw=true" width="500">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
InSituPy is a Python package designed to facilitate the analysis of single-cell spatial transcriptomics data. With InSituPy, you can easily load, visualize, and analyze the data, enabling and simplifying the comprehensive exploration of spatial gene expression patterns within tissue sections and across multiple samples.
|
|
8
|
+
Currently the analysis is focused on data from the [_Xenium In Situ_](https://www.10xgenomics.com/platforms/xenium) methodology but a broader range of reading functions will be implemented in the future.
|
|
9
|
+
|
|
10
|
+
## Latest changes
|
|
11
|
+
|
|
12
|
+
### Update to `>=0.6.0`
|
|
13
|
+
* Changed reading logic of `cell_names` in `BoundariesData`: this might lead to issues with backward compatibility but generalizes the reading of boundaries data opening it for other technologies.
|
|
14
|
+
* Adapt viewer for smaller screens
|
|
15
|
+
* Revised automated registration pipeline:
|
|
16
|
+
* Fixed issue with large multiplexed IF images.
|
|
17
|
+
* Area dependent number of minimum matches to make registration pipeline also work on small images.
|
|
18
|
+
* add registration demo notebook for pancreas data
|
|
19
|
+
* by default remove history of variable data when calling `.save()`
|
|
20
|
+
|
|
21
|
+
### Update to `0.5.0`
|
|
22
|
+
#### Major changes in reading/loading logic!
|
|
23
|
+
This might conflict with the backwards compatibility of this version! If there are issues with loading reading `InSituPy` projects saved with older version, please let me know to find workarounds!
|
|
24
|
+
* Reduced focus on Xenium method in data structure
|
|
25
|
+
* `InSituData.read()` substitutes `read_xenium` for reading of `InSituPy` projects. `read_xenium` used now to read data from Xenium data folders
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
### Prerequisites
|
|
30
|
+
|
|
31
|
+
1. **Create and activate a conda environment:**
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
conda create --name insitupy python=3.9
|
|
35
|
+
conda activate insitupy
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Method 1: Installation from Cloned Repository
|
|
39
|
+
|
|
40
|
+
1. **Clone the repository to your local machine:**
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
git clone https://github.com/jwrth/InSituPy.git
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
2. **Navigate to the cloned repository and select the right branch:**
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
cd InSituPy
|
|
50
|
+
|
|
51
|
+
# Optionally: switch to dev branch
|
|
52
|
+
git checkout dev
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
3. **Install the required packages using `pip` within the conda environment:**
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# basic installation
|
|
59
|
+
pip install .
|
|
60
|
+
|
|
61
|
+
# for developmental purposes add the -e flag
|
|
62
|
+
pip install -e .
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Method 2: Direct Installation from GitHub
|
|
66
|
+
|
|
67
|
+
1. **Install directly from GitHub:**
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# for installation without napari use
|
|
71
|
+
pip install git+https://github.com/jwrth/InSituPy.git
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Make sure you have Conda installed on your system before proceeding with these steps. If not, you can install Miniconda or Anaconda from [https://docs.conda.io/en/latest/miniconda.html](https://docs.conda.io/en/latest/miniconda.html).
|
|
75
|
+
|
|
76
|
+
To ensure that the InSituPy package is available as a kernel in Jupyter notebooks within your conda environment, you can follow the instructions [here](https://ipython.readthedocs.io/en/stable/install/kernel_install.html).
|
|
77
|
+
|
|
78
|
+
## Getting started
|
|
79
|
+
|
|
80
|
+
### Documentation
|
|
81
|
+
|
|
82
|
+
For detailed instructions on using InSituPy, refer to the [official documentation](https://InSituPy.readthedocs.io), which will be made public after publication. The documentation will provide comprehensive guides on installation, usage, and advanced features.
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
### Tutorials
|
|
86
|
+
|
|
87
|
+
Explore the tutorials in `./notebooks/` to learn how to use InSituPy:
|
|
88
|
+
|
|
89
|
+
#### Sample level analysis
|
|
90
|
+
|
|
91
|
+
These tutorials focus on the preprocessing, analysis and handling of individual samples.
|
|
92
|
+
|
|
93
|
+
1. [Registration of additional images](notebooks/01_InSituPy_demo_register_images.ipynb) - Learn how to register additional images to the spatial transcriptomics data.
|
|
94
|
+
1. Alternatively this is also implemented for an example dataset from [pancreatic cancer](notebooks/pancreas/01panc_InSituPy_demo_register_images.ipynb)
|
|
95
|
+
3. [Basic analysis functionalities](notebooks/02_InSituPy_demo_analyze.ipynb) - Learn about the basic functionalities, such as loading of data, basic preprocessing and interactive visualization with napari.
|
|
96
|
+
4. [Add annotations](notebooks/03_InSituPy_demo_annotations.ipynb) - Learn how to add annotations from external software such as [QuPath](https://qupath.github.io/) and do annotations in the napari viewer.
|
|
97
|
+
5. [Crop data](notebooks/04_InSituPy_demo_crop.ipynb) - Learn how to crop your data to focus your analysis on specific areas in the tissue.
|
|
98
|
+
6. [Cell type annotation](notebooks/05_InSituPy_cell_type_annotation.ipynb) - Shows an example workflow to annotate the cell types.
|
|
99
|
+
7. [Explore gene expression along axis](notebooks/06_InSituPy_gene_expression_along_axis_pattern.ipynb) - Example cases showing how to correlate gene expression with e.g. the distance to histological annotations.
|
|
100
|
+
8. [Build an `InSituData` object from scratch](notebooks/09_InSituPy_build_objects_from_scratch.ipynb) - General introduction on how to build an `InSituData` object from scratch.
|
|
101
|
+
|
|
102
|
+
#### Experiment-level analysis
|
|
103
|
+
|
|
104
|
+
This set of tutorials focuses on
|
|
105
|
+
|
|
106
|
+
1. [Analyze multiple samples at once with InSituPy](notebooks/07_InSituPy_InSituExperiment.ipynb) - Introduces the main concepts behind the `InSituExperiment` class and how to work with multiple samples at once.
|
|
107
|
+
2. [Differential gene expression analysis](notebooks/08_InSituPy_differential_gene_expression.ipynb) - Perform differential gene expression analysis within one sample and across multiple samples.
|
|
108
|
+
|
|
109
|
+
### Example data
|
|
110
|
+
|
|
111
|
+
If you want to test the pipeline on different example datasets, [this notebook](notebooks/00_InSituPy_demo_datasets.ipynb) provides an overview of functions to download _Xenium In Situ_ data from official sources.
|
|
112
|
+
|
|
113
|
+
## Features
|
|
114
|
+
|
|
115
|
+
- **Data Preprocessing:** InSituPy provides functions for normalizing, filtering, and transforming raw in situ transcriptomics data.
|
|
116
|
+
- **Interactive Visualization:** Create interactive plots using [napari](https://napari.org/stable/#) to easily explore spatial gene expression patterns.
|
|
117
|
+
- **Annotation:** Annotate _Xenium In Situ_ data in the napari viewer or import annotations from external tools like [QuPath](https://qupath.github.io/).
|
|
118
|
+
- **Multi-sample analysis:** Perform analysis on an experiment-level, i.e. with multiple samples at once.
|
|
119
|
+
|
|
120
|
+
## Contributing
|
|
121
|
+
|
|
122
|
+
Contributions are welcome! If you find any issues or have suggestions for new features, please open an [issue](https://github.com/SpatialPathology/InSituPy/issues) or submit a pull request.
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
InSituPy is licensed under the [BSD-3-Clause](LICENSE).
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
**InSituPy** is developed and maintained by [Johannes Wirth](https://github.com/jwrth) and [Anna Chernysheva](https://github.com/annachernysheva179). Feedback is highly appreciated and hopefully **InSituPy** helps you with your analysis of spatial transcriptomics data. The package is thought to be a starting point to simplify the analysis of in situ sequencing data in Python and it would be exciting to integrate functionalities for larger and more comprehensive data structures. Currently, the framework focuses on the analysis of _Xenium In Situ_ data but it is planned to integrate more methodologies and any support on this is highly welcomed.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
__author__ = "Johannes Wirth"
|
|
2
|
+
__email__ = "j.wirth@tum.de"
|
|
3
|
+
__version__ = "0.6.1"
|
|
4
|
+
|
|
5
|
+
# check if napari is available
|
|
6
|
+
try:
|
|
7
|
+
import napari
|
|
8
|
+
WITH_NAPARI = True
|
|
9
|
+
except ImportError:
|
|
10
|
+
WITH_NAPARI = False
|
|
11
|
+
|
|
12
|
+
from insitupy._constants import CACHE
|
|
13
|
+
|
|
14
|
+
from . import images as im
|
|
15
|
+
from . import io
|
|
16
|
+
from . import plotting as pl
|
|
17
|
+
from . import utils
|
|
18
|
+
from ._core.dataclasses import AnnotationsData, BoundariesData, ImageData
|
|
19
|
+
from ._core.insitudata import (InSituData, calc_distance_of_cells_from,
|
|
20
|
+
differential_gene_expression)
|
|
21
|
+
from ._core.insituexperiment import InSituExperiment
|
|
22
|
+
from ._core.reader import read_xenium
|
|
23
|
+
from ._core.registration import register_images
|
|
24
|
+
from .palettes import CustomPalettes
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"InSituData",
|
|
28
|
+
"AnnotationsData",
|
|
29
|
+
"BoundariesData",
|
|
30
|
+
"ImageData",
|
|
31
|
+
"im",
|
|
32
|
+
"utils"
|
|
33
|
+
]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import string
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import matplotlib
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
|
|
7
|
+
from insitupy.palettes import CustomPalettes
|
|
8
|
+
|
|
9
|
+
# make sure that images do not exceed limits in c++ (required for cv2::remap function in cv2::warpAffine)
|
|
10
|
+
# see also https://www.geeksforgeeks.org/climits-limits-h-cc/
|
|
11
|
+
SHRT_MAX = 2**15-1 # 32767
|
|
12
|
+
SHRT_MIN = -(2**15-1) # -32767
|
|
13
|
+
|
|
14
|
+
# create cache dir
|
|
15
|
+
CACHE = Path.home() / ".cache/InSituPy/"
|
|
16
|
+
|
|
17
|
+
# modalities
|
|
18
|
+
MODALITIES = ["annotations", "cells", "images", "regions", "transcripts"]
|
|
19
|
+
LOAD_FUNCS = [
|
|
20
|
+
'load_annotations',
|
|
21
|
+
'load_cells',
|
|
22
|
+
'load_images',
|
|
23
|
+
'load_regions',
|
|
24
|
+
'load_transcripts'
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
# naming
|
|
28
|
+
ISPY_METADATA_FILE = ".ispy"
|
|
29
|
+
XENIUM_HEX_RANGE = string.ascii_lowercase[:16]
|
|
30
|
+
NORMAL_HEX_RANGE = "".join([str(e) for e in range(10)]) + string.ascii_lowercase[:6]
|
|
31
|
+
XENIUM_INT_TO_HEX_CONV_DICT = {k:v for k,v in zip(NORMAL_HEX_RANGE, XENIUM_HEX_RANGE)}
|
|
32
|
+
XENIUM_HEX_TO_INT_CONV_DICT = {v:k for k,v in zip(NORMAL_HEX_RANGE, XENIUM_HEX_RANGE)}
|
|
33
|
+
|
|
34
|
+
# napari layer symbols
|
|
35
|
+
# SHAPES_SYMBOL = "\u2605" # Star: ★
|
|
36
|
+
# POINTS_SYMBOL = "\u2022" # Bullet: •
|
|
37
|
+
ANNOTATIONS_SYMBOL = "\U0001F52C" # 🔬
|
|
38
|
+
POINTS_SYMBOL = "\U0001F4CD" # 📍
|
|
39
|
+
REGIONS_SYMBOL = "\U0001F30D" # 🌍
|
|
40
|
+
|
|
41
|
+
# annotations
|
|
42
|
+
FORBIDDEN_ANNOTATION_NAMES = ["rest"]
|
|
43
|
+
|
|
44
|
+
## Matplotlib settings
|
|
45
|
+
# cmaps
|
|
46
|
+
palettes = CustomPalettes()
|
|
47
|
+
DEFAULT_CATEGORICAL_CMAP = palettes.tab20_mod
|
|
48
|
+
REGION_CMAP = matplotlib.colormaps["tab10"]
|
|
49
|
+
DEFAULT_CONTINUOUS_CMAP = "viridis"
|
|
50
|
+
|
|
51
|
+
# font size
|
|
52
|
+
def _init_mpl_fontsize(scale_factor=1):
|
|
53
|
+
'''
|
|
54
|
+
https://matplotlib.org/stable/api/matplotlib_configuration_api.html#matplotlib.rcParams
|
|
55
|
+
'''
|
|
56
|
+
SMALL_SIZE = 14*scale_factor
|
|
57
|
+
MEDIUM_SIZE = 16*scale_factor
|
|
58
|
+
BIGGER_SIZE = 18*scale_factor
|
|
59
|
+
|
|
60
|
+
plt.rc('font', size=SMALL_SIZE) # controls default text sizes
|
|
61
|
+
plt.rc('axes', titlesize=MEDIUM_SIZE) # fontsize of the axes title
|
|
62
|
+
plt.rc('axes', labelsize=MEDIUM_SIZE) # fontsize of the x and y labels
|
|
63
|
+
plt.rc('xtick', labelsize=SMALL_SIZE) # fontsize of the tick labels
|
|
64
|
+
plt.rc('ytick', labelsize=SMALL_SIZE) # fontsize of the tick labels
|
|
65
|
+
plt.rc('legend', fontsize=SMALL_SIZE) # legend fontsize
|
|
66
|
+
plt.rc('figure', titlesize=BIGGER_SIZE) # fontsize of the figure title
|
|
67
|
+
|
|
68
|
+
_init_mpl_fontsize()
|
|
File without changes
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from matplotlib.gridspec import GridSpec
|
|
6
|
+
from matplotlib.lines import Line2D
|
|
7
|
+
from pandas.api.types import is_numeric_dtype
|
|
8
|
+
|
|
9
|
+
import insitupy._core.config as config
|
|
10
|
+
from insitupy import WITH_NAPARI
|
|
11
|
+
from insitupy._constants import POINTS_SYMBOL
|
|
12
|
+
|
|
13
|
+
if WITH_NAPARI:
|
|
14
|
+
import napari
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# geometry widget
|
|
18
|
+
def _update_keys_based_on_geom_type(widget, xdata):
|
|
19
|
+
# retrieve current value
|
|
20
|
+
current_geom_type = widget.geom_type.value
|
|
21
|
+
current_key = widget.key.value
|
|
22
|
+
|
|
23
|
+
# get either regions or annotations object
|
|
24
|
+
geom_data = getattr(xdata, current_geom_type.lower())
|
|
25
|
+
widget.key.choices = sorted(geom_data.metadata.keys(), key=str.casefold)
|
|
26
|
+
|
|
27
|
+
def _update_classes_on_key_change(widget, xdata):
|
|
28
|
+
# get current values for geom_type and key
|
|
29
|
+
current_geom_type = widget.geom_type.value
|
|
30
|
+
current_key = widget.key.value
|
|
31
|
+
|
|
32
|
+
# get either regions or annotations object
|
|
33
|
+
geom_data = getattr(xdata, current_geom_type.lower())
|
|
34
|
+
|
|
35
|
+
# update annot_class choices
|
|
36
|
+
widget.annot_class.choices = ["all"] + sorted(geom_data.metadata[current_key]['classes'])
|
|
37
|
+
|
|
38
|
+
def _set_show_names_based_on_geom_type(widget):
|
|
39
|
+
# retrieve current value
|
|
40
|
+
current_geom_type = widget.geom_type.value
|
|
41
|
+
|
|
42
|
+
# set the show_names tick box
|
|
43
|
+
if current_geom_type == "Annotations":
|
|
44
|
+
widget.show_names.value = False
|
|
45
|
+
|
|
46
|
+
if current_geom_type == "Regions":
|
|
47
|
+
widget.show_names.value = True
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Function to update the legend
|
|
51
|
+
def _update_categorical_legend(static_canvas, mapping, label, max_rows: int = 6):
|
|
52
|
+
|
|
53
|
+
# Calculate the number of columns needed
|
|
54
|
+
num_items = len(mapping)
|
|
55
|
+
ncols = math.ceil(num_items / max_rows)
|
|
56
|
+
|
|
57
|
+
static_canvas.figure.clear() # Clear the current figure
|
|
58
|
+
axes = static_canvas.figure.subplots() # Create new axes
|
|
59
|
+
legend_handles = [Line2D([0], [0],
|
|
60
|
+
marker='o', color='w', label=n,
|
|
61
|
+
markerfacecolor=c, markeredgecolor='k',
|
|
62
|
+
markersize=7) for n,c in mapping.items()]
|
|
63
|
+
axes.legend(handles=legend_handles, loc="center", title=label, ncols=ncols,
|
|
64
|
+
fontsize=8, title_fontsize=10,
|
|
65
|
+
labelspacing=0.7, borderpad=0.5)
|
|
66
|
+
axes.set_axis_off()
|
|
67
|
+
static_canvas.draw() # Redraw the canvas
|
|
68
|
+
|
|
69
|
+
def _update_continuous_legend(static_canvas, mapping, label):
|
|
70
|
+
static_canvas.figure.clear() # Clear the current figure
|
|
71
|
+
gs = GridSpec(1, 1, top=1.2, bottom=0.6, left=-0.5, right=1.5) # Define the grid spec
|
|
72
|
+
axes = static_canvas.figure.add_subplot(gs[0]) # Add subplot with the grid spec
|
|
73
|
+
|
|
74
|
+
colorbar = static_canvas.figure.colorbar(mapping, ax=axes, orientation='horizontal')
|
|
75
|
+
colorbar.set_label(label, fontsize=10)
|
|
76
|
+
colorbar.ax.tick_params(labelsize=8) # Adjust tick label size
|
|
77
|
+
#colorbar.set_ticks(np.linspace(norm.vmin, norm.vmax, num=5)) # Set the number of ticks
|
|
78
|
+
axes.set_axis_off()
|
|
79
|
+
static_canvas.draw() # Redraw the canvas
|
|
80
|
+
|
|
81
|
+
def _update_colorlegend():
|
|
82
|
+
|
|
83
|
+
# # automatically get layer
|
|
84
|
+
# candidate_layers = [l for l in config.viewer.layers if l.name.startswith(f"{config.current_data_name}")]
|
|
85
|
+
# try:
|
|
86
|
+
# # always choose the candidate layer that is on top
|
|
87
|
+
# layer_name = candidate_layers[-1].name
|
|
88
|
+
# except IndexError:
|
|
89
|
+
# raise ValueError("No layer with cellular transcriptomic data found. First add a layer using the 'Show Data' widget.")
|
|
90
|
+
|
|
91
|
+
# # extract layer
|
|
92
|
+
# layer = config.viewer.layers[layer_name]
|
|
93
|
+
|
|
94
|
+
layer = config.viewer.layers.selection.active
|
|
95
|
+
|
|
96
|
+
if isinstance(layer, napari.layers.points.points.Points):
|
|
97
|
+
# get values
|
|
98
|
+
values = layer.properties["value"]
|
|
99
|
+
color_values = layer.face_color
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
from insitupy.plotting._colors import continuous_data_to_rgba
|
|
103
|
+
if is_numeric_dtype(values):
|
|
104
|
+
rgba_list, mapping = continuous_data_to_rgba(data=values,
|
|
105
|
+
cmap=layer.face_colormap.name,
|
|
106
|
+
#upper_climit_pct=upper_climit_pct,
|
|
107
|
+
return_mapping=True
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
_update_continuous_legend(static_canvas=config.static_canvas,
|
|
111
|
+
mapping=mapping,
|
|
112
|
+
label=layer.name)
|
|
113
|
+
|
|
114
|
+
else:
|
|
115
|
+
# substitute pd.NA with np.nan
|
|
116
|
+
values = pd.Series(values).fillna(np.nan).values
|
|
117
|
+
# assume the data is categorical
|
|
118
|
+
#mapping = {category: tuple(rgba) for category, rgba in zip(values, color_values)}
|
|
119
|
+
unique_values = list(set(values))
|
|
120
|
+
mapping = {str(v): tuple(color_values[list(values).index(v)]) for v in unique_values}
|
|
121
|
+
# sort mapping dict
|
|
122
|
+
mapping = {elem: mapping[elem] for elem in sorted(mapping.keys())}
|
|
123
|
+
|
|
124
|
+
_update_categorical_legend(static_canvas=config.static_canvas,
|
|
125
|
+
mapping=mapping, label=layer.name)
|
|
126
|
+
|
|
127
|
+
# # create color mapping
|
|
128
|
+
# rgba_list, mapping = _data_to_rgba(values, return_mapping=True)
|
|
129
|
+
|
|
130
|
+
# if isinstance(mapping, dict):
|
|
131
|
+
# _update_categorical_legend(static_canvas=config.static_canvas,
|
|
132
|
+
# mapping=mapping, label=layer.name)
|
|
133
|
+
# else:
|
|
134
|
+
# _update_continuous_legend(static_canvas=config.static_canvas,
|
|
135
|
+
# mapping=mapping,
|
|
136
|
+
# label=layer.name)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _refresh_widgets_after_data_change(xdata, points_widget, boundaries_widget, filter_widget):
|
|
140
|
+
config.init_viewer_config(xdata)
|
|
141
|
+
|
|
142
|
+
# set choices
|
|
143
|
+
boundaries_widget.key.choices = config.masks
|
|
144
|
+
|
|
145
|
+
# reset the currently selected key to None
|
|
146
|
+
points_widget.value.value = None
|
|
147
|
+
|
|
148
|
+
# add last addition to recent
|
|
149
|
+
points_widget.recent.choices = sorted(config.recent_selections)
|
|
150
|
+
points_widget.recent.value = None
|
|
151
|
+
|
|
152
|
+
# update obs in filter widget
|
|
153
|
+
filter_widget.obs_key.choices = config.value_dict["obs"]
|
|
154
|
+
|
|
155
|
+
# set only the last cell layer visible
|
|
156
|
+
cell_layers = []
|
|
157
|
+
for elem in xdata.viewer.layers:
|
|
158
|
+
if isinstance(elem, napari.layers.points.points.Points):
|
|
159
|
+
if not elem.name.startswith(POINTS_SYMBOL):
|
|
160
|
+
# only if the layer is not a point annotation layer, it is added
|
|
161
|
+
cell_layers.append(elem)
|
|
162
|
+
#point_layers = [elem for elem in xdata.viewer.layers if isinstance(elem, napari.layers.points.points.Points)]
|
|
163
|
+
n_cell_layers = len(cell_layers)
|
|
164
|
+
|
|
165
|
+
# # make only last cell layer visible
|
|
166
|
+
# for i, l in enumerate(cell_layers):
|
|
167
|
+
# if i < n_cell_layers-1:
|
|
168
|
+
# l.visible = False
|