├── .github
└── workflows
│ ├── publish.yaml
│ └── test.yaml
├── .gitignore
├── LICENSE
├── MOp_MERFISH_tutorial.ipynb
├── README.md
├── dist
├── scenvi-0.1.0-py3-none-any.whl
├── scenvi-0.1.0.tar.gz
├── scenvi-0.2.0-py3-none-any.whl
├── scenvi-0.2.0.tar.gz
├── scenvi-0.2.1-py3-none-any.whl
├── scenvi-0.2.1.tar.gz
├── scenvi-0.2.2-py3-none-any.whl
├── scenvi-0.2.2.tar.gz
├── scenvi-0.2.3-py3-none-any.whl
├── scenvi-0.2.3.tar.gz
├── scenvi-0.2.4-py3-none-any.whl
├── scenvi-0.2.4.tar.gz
├── scenvi-0.2.5-py3-none-any.whl
├── scenvi-0.2.5.tar.gz
├── scenvi-0.2.6-py3-none-any.whl
└── scenvi-0.2.6.tar.gz
├── docs
├── Makefile
├── build
│ ├── doctrees
│ │ ├── ENVI.doctree
│ │ ├── environment.pickle
│ │ ├── index.doctree
│ │ ├── nbsphinx
│ │ │ ├── tutorial
│ │ │ │ └── MOp_MERFISH_tutorial.ipynb
│ │ │ ├── tutorial_MOp_MERFISH_tutorial_15_0.png
│ │ │ ├── tutorial_MOp_MERFISH_tutorial_18_0.png
│ │ │ ├── tutorial_MOp_MERFISH_tutorial_29_0.png
│ │ │ ├── tutorial_MOp_MERFISH_tutorial_40_0.png
│ │ │ ├── tutorial_MOp_MERFISH_tutorial_41_0.png
│ │ │ ├── tutorial_MOp_MERFISH_tutorial_45_0.png
│ │ │ ├── tutorial_MOp_MERFISH_tutorial_51_0.png
│ │ │ └── tutorial_MOp_MERFISH_tutorial_54_0.png
│ │ ├── tutorial
│ │ │ └── MOp_MERFISH_tutorial.doctree
│ │ └── utils.doctree
│ └── html
│ │ ├── .buildinfo
│ │ ├── ENVI.html
│ │ ├── _images
│ │ ├── tutorial_MOp_MERFISH_tutorial_15_0.png
│ │ ├── tutorial_MOp_MERFISH_tutorial_18_0.png
│ │ ├── tutorial_MOp_MERFISH_tutorial_29_0.png
│ │ ├── tutorial_MOp_MERFISH_tutorial_40_0.png
│ │ ├── tutorial_MOp_MERFISH_tutorial_41_0.png
│ │ ├── tutorial_MOp_MERFISH_tutorial_45_0.png
│ │ ├── tutorial_MOp_MERFISH_tutorial_51_0.png
│ │ └── tutorial_MOp_MERFISH_tutorial_54_0.png
│ │ ├── _sources
│ │ ├── ENVI.rst.txt
│ │ ├── index.rst.txt
│ │ ├── tutorial
│ │ │ └── MOp_MERFISH_tutorial.ipynb.txt
│ │ └── utils.rst.txt
│ │ ├── _static
│ │ ├── basic.css
│ │ ├── debug.css
│ │ ├── doctools.js
│ │ ├── documentation_options.js
│ │ ├── file.png
│ │ ├── language_data.js
│ │ ├── minus.png
│ │ ├── nbsphinx-broken-thumbnail.svg
│ │ ├── nbsphinx-code-cells.css
│ │ ├── nbsphinx-gallery.css
│ │ ├── nbsphinx-no-thumbnail.svg
│ │ ├── plus.png
│ │ ├── pygments.css
│ │ ├── scripts
│ │ │ ├── furo-extensions.js
│ │ │ ├── furo.js
│ │ │ ├── furo.js.LICENSE.txt
│ │ │ └── furo.js.map
│ │ ├── searchtools.js
│ │ ├── skeleton.css
│ │ ├── sphinx_highlight.js
│ │ └── styles
│ │ │ ├── furo-extensions.css
│ │ │ ├── furo-extensions.css.map
│ │ │ ├── furo.css
│ │ │ └── furo.css.map
│ │ ├── genindex.html
│ │ ├── index.html
│ │ ├── objects.inv
│ │ ├── search.html
│ │ ├── searchindex.js
│ │ ├── tutorial
│ │ ├── MOp_MERFISH_tutorial.html
│ │ └── MOp_MERFISH_tutorial.ipynb
│ │ └── utils.html
├── docs_requirements.txt
├── make.bat
└── source
│ ├── ENVI.rst
│ ├── conf.py
│ ├── index.rst
│ ├── tutorial
│ └── MOp_MERFISH_tutorial.ipynb
│ └── utils.rst
├── pyproject.toml
├── readthedocs.yaml
├── scenvi
├── ENVI.py
├── __init__.py
├── __pycache__
│ ├── ENVI.cpython-39.pyc
│ ├── __init__.cpython-38.pyc
│ ├── __init__.cpython-39.pyc
│ ├── dists.cpython-39.pyc
│ └── utils.cpython-39.pyc
├── _dists.py
└── utils.py
└── tests
└── test_ENVI.py
/.github/workflows/publish.yaml:
--------------------------------------------------------------------------------
1 | name: Publish to PyPI
2 | on:
3 | pull_request:
4 | types:
5 | - closed
6 | branches:
7 | - main
8 | jobs:
9 | publish:
10 | if: github.event.pull_request.merged == true
11 | runs-on: ubuntu-latest
12 | permissions:
13 | contents: write # This is needed to push changes back to the repository
14 | steps:
15 | - uses: actions/checkout@v3
16 | with:
17 | fetch-depth: 0 # Get full history for version tracking
18 |
19 | - name: Set up Python
20 | uses: actions/setup-python@v4
21 | with:
22 | python-version: '3.x'
23 |
24 | - name: Install Poetry
25 | uses: snok/install-poetry@v1
26 | with:
27 | version: '1.5.1'
28 | virtualenvs-create: true
29 |
30 | - name: Configure Git
31 | run: |
32 | git config --global user.name "github-actions[bot]"
33 | git config --global user.email "github-actions[bot]@users.noreply.github.com"
34 |
35 | - name: Update version and commit
36 | run: |
37 | # Get current version
38 | CURRENT_VERSION=$(poetry version -s)
39 | echo "Current version: $CURRENT_VERSION"
40 |
41 | # Bump patch version
42 | poetry version patch
43 | NEW_VERSION=$(poetry version -s)
44 | echo "New version: $NEW_VERSION"
45 |
46 | # Commit the version change
47 | git add pyproject.toml
48 | git commit -m "Bump version to $NEW_VERSION [skip ci]"
49 | git tag v$NEW_VERSION
50 |
51 | - name: Build and publish
52 | env:
53 | PYPI_API_TOKEN: ${{ secrets.PYPI_TOKEN }}
54 | run: |
55 | poetry config pypi-token.pypi "$PYPI_API_TOKEN"
56 | poetry build
57 | poetry publish --username __token__ --password "$PYPI_API_TOKEN"
58 |
59 | - name: Push changes to GitHub
60 | run: |
61 | git push origin HEAD:main
62 | git push origin v$(poetry version -s)
--------------------------------------------------------------------------------
/.github/workflows/test.yaml:
--------------------------------------------------------------------------------
1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
3 |
4 | name: Test Mappers
5 |
6 | on:
7 | workflow_dispatch:
8 | pull_request:
9 | branches: [main]
10 |
11 | jobs:
12 | build:
13 |
14 | runs-on: ubuntu-latest
15 | strategy:
16 | matrix:
17 | python-version: ["3.10", "3.11", "3.12", "3.13"]
18 |
19 | steps:
20 | - uses: actions/checkout@v4
21 | - name: Set up Python ${{ matrix.python-version }}
22 | uses: actions/setup-python@v3
23 | with:
24 | python-version: ${{ matrix.python-version }}
25 | - name: Install dependencies
26 | run: |
27 | python -m pip install --upgrade pip
28 | python -m pip install flake8 pytest
29 | - name: Install package
30 | run: |
31 | pip install -e .
32 | - name: Lint with flake8
33 | run: |
34 | # stop the build if there are Python syntax errors or undefined names
35 | flake8 . \
36 | --count \
37 | --select=E9,F63,F7,F82 \
38 | --show-source \
39 | --statistics \
40 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
41 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
42 | - name: Test with pytest
43 | run: |
44 | pytest
45 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #https://github.com/github/gitignore/blob/main/Python.gitignore
2 |
3 | # Byte-compiled / optimized / DLL files
4 | __pycache__/
5 | *.py[cod]
6 | *$py.class
7 |
8 | # C extensions
9 | *.so
10 |
11 | .ipynb_checkpoints
12 |
13 |
14 |
15 | # Distribution / packaging
16 | .Python
17 |
18 | develop-eggs/
19 | dist/
20 | downloads/
21 | eggs/
22 | .eggs/
23 | lib/
24 | lib64/
25 | parts/
26 | sdist/
27 | var/
28 | wheels/
29 | share/python-wheels/
30 | *.egg-info/
31 | .installed.cfg
32 | *.egg
33 | MANIFEST
34 |
35 | # PyInstaller
36 | # Usually these files are written by a python script from a template
37 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
38 | *.manifest
39 | *.spec
40 |
41 | # Installer logs
42 | pip-log.txt
43 | pip-delete-this-directory.txt
44 |
45 | # Unit test / coverage reports
46 | htmlcov/
47 | .tox/
48 | .nox/
49 | .coverage
50 | .coverage.*
51 | .cache
52 | nosetests.xml
53 | coverage.xml
54 | *.cover
55 | *.py,cover
56 | .hypothesis/
57 | .pytest_cache/
58 | cover/
59 |
60 | # Translations
61 | *.mo
62 | *.pot
63 |
64 | # Django stuff:
65 | *.log
66 | local_settings.py
67 | db.sqlite3
68 | db.sqlite3-journal
69 |
70 | # Flask stuff:
71 | instance/
72 | .webassets-cache
73 |
74 | # Scrapy stuff:
75 | .scrapy
76 |
77 | # Sphinx documentation
78 | docs/_build/
79 |
80 | # PyBuilder
81 | .pybuilder/
82 | target/
83 |
84 | # Jupyter Notebook
85 | .ipynb_checkpoints
86 |
87 | # IPython
88 | profile_default/
89 | ipython_config.py
90 |
91 | # pyenv
92 | # For a library or package, you might want to ignore these files since the code is
93 | # intended to run in multiple environments; otherwise, check them in:
94 | # .python-version
95 |
96 | # pipenv
97 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
98 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
99 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
100 | # install all needed dependencies.
101 | #Pipfile.lock
102 |
103 | # poetry
104 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105 | # This is especially recommended for binary packages to ensure reproducibility, and is more
106 | # commonly ignored for libraries.
107 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108 | #poetry.lock
109 |
110 | # pdm
111 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
112 | #pdm.lock
113 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
114 | # in version control.
115 | # https://pdm.fming.dev/#use-with-ide
116 | .pdm.toml
117 |
118 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
119 | __pypackages__/
120 |
121 | # Celery stuff
122 | celerybeat-schedule
123 | celerybeat.pid
124 |
125 | # SageMath parsed files
126 | *.sage.py
127 |
128 | # Environments
129 | .env
130 | .venv
131 | env/
132 | venv/
133 | ENV/
134 | env.bak/
135 | venv.bak/
136 |
137 | # Spyder project settings
138 | .spyderproject
139 | .spyproject
140 |
141 | # Rope project settings
142 | .ropeproject
143 |
144 | # mkdocs documentation
145 | /site
146 |
147 | # mypy
148 | .mypy_cache/
149 | .dmypy.json
150 | dmypy.json
151 |
152 | # Pyre type checker
153 | .pyre/
154 |
155 | # pytype static type analyzer
156 | .pytype/
157 |
158 | # Cython debug symbols
159 | cython_debug/
160 |
161 | # PyCharm
162 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
163 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
164 | # and can be added to the global gitignore or merged into this file. For a more nuclear
165 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
166 | #.idea
167 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018 The Python Packaging Authority
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ENVI & COVET
2 | ======================
3 |
4 |
5 | ENVI is a deep learnining based variational inference method to integrate scRNA-seq with spatial transcriptomics data. ENVI learns to reconstruct spatial onto for dissociated scRNA-seq data and impute unimagd genes onto spatial data.
6 |
7 | This implementation is written in Python3 and relies on jax, flax, sklearn, scipy and scanpy.
8 |
9 |
10 | To install JAX, simply run the command:
11 |
12 | pip install -U "jax[cuda12]"
13 |
14 | And to install ENVI along with the rest of the requirements:
15 |
16 | pip install scenvi
17 |
18 | To run ENVI:
19 |
20 | import scenvi
21 |
22 | envi_model = scenvi.ENVI(spatial_data = st_data, sc_data = sc_data)
23 |
24 | envi_model.train()
25 | envi_model.impute_genes()
26 | envi_model.infer_niche_covet()
27 | envi_model.infer_niche_celltype()
28 |
29 | st_data.obsm['envi_latent'] = envi_model.spatial_data.obsm['envi_latent']
30 | st_data.uns['COVET_genes'] = envi_model.CovGenes
31 | st_data.obsm['COVET'] = envi_model.spatial_data.obsm['COVET']
32 | st_data.obsm['COVET_SQRT'] = envi_model.spatial_data.obsm['COVET_SQRT']
33 | st_data.obsm['cell_type_niche'] = envi_model.spatial_data.obsm['cell_type_niche']
34 | st_data.obsm['imputation'] = envi_model.spatial_data.obsm['imputation']
35 |
36 |
37 | sc_data.obsm['envi_latent'] = envi_model.sc_data.obsm['envi_latent']
38 | sc_data.uns['COVET_genes'] = envi_model.CovGenes
39 | sc_data.obsm['COVET'] = envi_model.sc_data.obsm['COVET']
40 | sc_data.obsm['COVET_SQRT'] = envi_model.sc_data.obsm['COVET_SQRT']
41 | sc_data.obsm['cell_type_niche'] = envi_model.sc_data.obsm['cell_type_niche']
42 |
43 |
44 | And to just compute COVET for spatial data:
45 |
46 | st_data.obsm['COVET'], st_data.obsm['COVET_SQRT'], st_data.uns['CovGenes'] = scenvi.compute_covet(st_data)
47 |
48 | Please read our documentation and see a full tutorial at https://scenvi.readthedocs.io/.
49 |
--------------------------------------------------------------------------------
/dist/scenvi-0.1.0-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.1.0-py3-none-any.whl
--------------------------------------------------------------------------------
/dist/scenvi-0.1.0.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.1.0.tar.gz
--------------------------------------------------------------------------------
/dist/scenvi-0.2.0-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.0-py3-none-any.whl
--------------------------------------------------------------------------------
/dist/scenvi-0.2.0.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.0.tar.gz
--------------------------------------------------------------------------------
/dist/scenvi-0.2.1-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.1-py3-none-any.whl
--------------------------------------------------------------------------------
/dist/scenvi-0.2.1.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.1.tar.gz
--------------------------------------------------------------------------------
/dist/scenvi-0.2.2-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.2-py3-none-any.whl
--------------------------------------------------------------------------------
/dist/scenvi-0.2.2.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.2.tar.gz
--------------------------------------------------------------------------------
/dist/scenvi-0.2.3-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.3-py3-none-any.whl
--------------------------------------------------------------------------------
/dist/scenvi-0.2.3.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.3.tar.gz
--------------------------------------------------------------------------------
/dist/scenvi-0.2.4-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.4-py3-none-any.whl
--------------------------------------------------------------------------------
/dist/scenvi-0.2.4.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.4.tar.gz
--------------------------------------------------------------------------------
/dist/scenvi-0.2.5-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.5-py3-none-any.whl
--------------------------------------------------------------------------------
/dist/scenvi-0.2.5.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.5.tar.gz
--------------------------------------------------------------------------------
/dist/scenvi-0.2.6-py3-none-any.whl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.6-py3-none-any.whl
--------------------------------------------------------------------------------
/dist/scenvi-0.2.6.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/dist/scenvi-0.2.6.tar.gz
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/docs/build/doctrees/ENVI.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/ENVI.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/environment.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/environment.pickle
--------------------------------------------------------------------------------
/docs/build/doctrees/index.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/index.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_15_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_15_0.png
--------------------------------------------------------------------------------
/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_18_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_18_0.png
--------------------------------------------------------------------------------
/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_29_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_29_0.png
--------------------------------------------------------------------------------
/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_40_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_40_0.png
--------------------------------------------------------------------------------
/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_41_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_41_0.png
--------------------------------------------------------------------------------
/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_45_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_45_0.png
--------------------------------------------------------------------------------
/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_51_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_51_0.png
--------------------------------------------------------------------------------
/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_54_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/nbsphinx/tutorial_MOp_MERFISH_tutorial_54_0.png
--------------------------------------------------------------------------------
/docs/build/doctrees/tutorial/MOp_MERFISH_tutorial.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/tutorial/MOp_MERFISH_tutorial.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/utils.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/doctrees/utils.doctree
--------------------------------------------------------------------------------
/docs/build/html/.buildinfo:
--------------------------------------------------------------------------------
1 | # Sphinx build info version 1
2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3 | config: ef9216dd0783c9a330a1f77e3b1bbc54
4 | tags: 645f666f9bcd5a90fca523b33c5a78b7
5 |
--------------------------------------------------------------------------------
/docs/build/html/ENVI.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | ENVI - scenvi 0.3.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 | Contents
48 |
49 |
50 |
51 |
52 |
61 |
62 | Expand
63 |
65 |
66 |
67 |
68 |
69 | Light mode
70 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | Dark mode
85 |
87 |
88 |
89 |
90 |
91 |
92 | Auto light/dark mode
93 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
111 |
112 | Hide table of contents sidebar
113 |
114 |
115 |
116 |
117 |
118 |
143 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 | Back to top
182 |
183 |
184 |
185 |
186 |
187 | Toggle Light / Dark / Auto color theme
188 |
189 |
190 |
191 |
192 |
193 |
194 | Toggle table of contents sidebar
195 |
196 |
197 |
198 |
199 |
202 |
203 |
204 |
205 |
206 |
207 |
229 |
230 |
231 |
232 | Copyright © 2024, Doron Haviv
233 |
234 | Made with
Sphinx and
@pradyunsg 's
235 |
236 |
Furo
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
--------------------------------------------------------------------------------
/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_15_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_15_0.png
--------------------------------------------------------------------------------
/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_18_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_18_0.png
--------------------------------------------------------------------------------
/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_29_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_29_0.png
--------------------------------------------------------------------------------
/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_40_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_40_0.png
--------------------------------------------------------------------------------
/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_41_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_41_0.png
--------------------------------------------------------------------------------
/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_45_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_45_0.png
--------------------------------------------------------------------------------
/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_51_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_51_0.png
--------------------------------------------------------------------------------
/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_54_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_images/tutorial_MOp_MERFISH_tutorial_54_0.png
--------------------------------------------------------------------------------
/docs/build/html/_sources/ENVI.rst.txt:
--------------------------------------------------------------------------------
1 | ENVI
2 | =========
3 |
4 | .. automodule:: scenvi.ENVI
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/build/html/_sources/index.rst.txt:
--------------------------------------------------------------------------------
1 | .. scenvi documentation master file, created by
2 | sphinx-quickstart on Wed Apr 24 12:13:12 2024.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | .. toctree::
7 | :hidden:
8 | :caption: Tutorials:
9 |
10 | tutorial/MOp_MERFISH_tutorial
11 |
12 | .. toctree::
13 | :hidden:
14 | :caption: Modules:
15 |
16 | ENVI
17 | Utilities
18 |
19 |
20 | .. mdinclude:: ../../README.md
21 |
22 | Index
23 | =====
24 |
25 | * :ref:`genindex`
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/docs/build/html/_sources/utils.rst.txt:
--------------------------------------------------------------------------------
1 | Utilities
2 | =========
3 |
4 | .. automodule:: scenvi.utils
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/build/html/_static/basic.css:
--------------------------------------------------------------------------------
1 | /*
2 | * basic.css
3 | * ~~~~~~~~~
4 | *
5 | * Sphinx stylesheet -- basic theme.
6 | *
7 | * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | /* -- main layout ----------------------------------------------------------- */
13 |
14 | div.clearer {
15 | clear: both;
16 | }
17 |
18 | div.section::after {
19 | display: block;
20 | content: '';
21 | clear: left;
22 | }
23 |
24 | /* -- relbar ---------------------------------------------------------------- */
25 |
26 | div.related {
27 | width: 100%;
28 | font-size: 90%;
29 | }
30 |
31 | div.related h3 {
32 | display: none;
33 | }
34 |
35 | div.related ul {
36 | margin: 0;
37 | padding: 0 0 0 10px;
38 | list-style: none;
39 | }
40 |
41 | div.related li {
42 | display: inline;
43 | }
44 |
45 | div.related li.right {
46 | float: right;
47 | margin-right: 5px;
48 | }
49 |
50 | /* -- sidebar --------------------------------------------------------------- */
51 |
52 | div.sphinxsidebarwrapper {
53 | padding: 10px 5px 0 10px;
54 | }
55 |
56 | div.sphinxsidebar {
57 | float: left;
58 | width: 230px;
59 | margin-left: -100%;
60 | font-size: 90%;
61 | word-wrap: break-word;
62 | overflow-wrap : break-word;
63 | }
64 |
65 | div.sphinxsidebar ul {
66 | list-style: none;
67 | }
68 |
69 | div.sphinxsidebar ul ul,
70 | div.sphinxsidebar ul.want-points {
71 | margin-left: 20px;
72 | list-style: square;
73 | }
74 |
75 | div.sphinxsidebar ul ul {
76 | margin-top: 0;
77 | margin-bottom: 0;
78 | }
79 |
80 | div.sphinxsidebar form {
81 | margin-top: 10px;
82 | }
83 |
84 | div.sphinxsidebar input {
85 | border: 1px solid #98dbcc;
86 | font-family: sans-serif;
87 | font-size: 1em;
88 | }
89 |
90 | div.sphinxsidebar #searchbox form.search {
91 | overflow: hidden;
92 | }
93 |
94 | div.sphinxsidebar #searchbox input[type="text"] {
95 | float: left;
96 | width: 80%;
97 | padding: 0.25em;
98 | box-sizing: border-box;
99 | }
100 |
101 | div.sphinxsidebar #searchbox input[type="submit"] {
102 | float: left;
103 | width: 20%;
104 | border-left: none;
105 | padding: 0.25em;
106 | box-sizing: border-box;
107 | }
108 |
109 |
110 | img {
111 | border: 0;
112 | max-width: 100%;
113 | }
114 |
115 | /* -- search page ----------------------------------------------------------- */
116 |
117 | ul.search {
118 | margin: 10px 0 0 20px;
119 | padding: 0;
120 | }
121 |
122 | ul.search li {
123 | padding: 5px 0 5px 20px;
124 | background-image: url(file.png);
125 | background-repeat: no-repeat;
126 | background-position: 0 7px;
127 | }
128 |
129 | ul.search li a {
130 | font-weight: bold;
131 | }
132 |
133 | ul.search li p.context {
134 | color: #888;
135 | margin: 2px 0 0 30px;
136 | text-align: left;
137 | }
138 |
139 | ul.keywordmatches li.goodmatch a {
140 | font-weight: bold;
141 | }
142 |
143 | /* -- index page ------------------------------------------------------------ */
144 |
145 | table.contentstable {
146 | width: 90%;
147 | margin-left: auto;
148 | margin-right: auto;
149 | }
150 |
151 | table.contentstable p.biglink {
152 | line-height: 150%;
153 | }
154 |
155 | a.biglink {
156 | font-size: 1.3em;
157 | }
158 |
159 | span.linkdescr {
160 | font-style: italic;
161 | padding-top: 5px;
162 | font-size: 90%;
163 | }
164 |
165 | /* -- general index --------------------------------------------------------- */
166 |
167 | table.indextable {
168 | width: 100%;
169 | }
170 |
171 | table.indextable td {
172 | text-align: left;
173 | vertical-align: top;
174 | }
175 |
176 | table.indextable ul {
177 | margin-top: 0;
178 | margin-bottom: 0;
179 | list-style-type: none;
180 | }
181 |
182 | table.indextable > tbody > tr > td > ul {
183 | padding-left: 0em;
184 | }
185 |
186 | table.indextable tr.pcap {
187 | height: 10px;
188 | }
189 |
190 | table.indextable tr.cap {
191 | margin-top: 10px;
192 | background-color: #f2f2f2;
193 | }
194 |
195 | img.toggler {
196 | margin-right: 3px;
197 | margin-top: 3px;
198 | cursor: pointer;
199 | }
200 |
201 | div.modindex-jumpbox {
202 | border-top: 1px solid #ddd;
203 | border-bottom: 1px solid #ddd;
204 | margin: 1em 0 1em 0;
205 | padding: 0.4em;
206 | }
207 |
208 | div.genindex-jumpbox {
209 | border-top: 1px solid #ddd;
210 | border-bottom: 1px solid #ddd;
211 | margin: 1em 0 1em 0;
212 | padding: 0.4em;
213 | }
214 |
215 | /* -- domain module index --------------------------------------------------- */
216 |
217 | table.modindextable td {
218 | padding: 2px;
219 | border-collapse: collapse;
220 | }
221 |
222 | /* -- general body styles --------------------------------------------------- */
223 |
224 | div.body {
225 | min-width: 360px;
226 | max-width: 800px;
227 | }
228 |
229 | div.body p, div.body dd, div.body li, div.body blockquote {
230 | -moz-hyphens: auto;
231 | -ms-hyphens: auto;
232 | -webkit-hyphens: auto;
233 | hyphens: auto;
234 | }
235 |
236 | a.headerlink {
237 | visibility: hidden;
238 | }
239 |
240 | a:visited {
241 | color: #551A8B;
242 | }
243 |
244 | h1:hover > a.headerlink,
245 | h2:hover > a.headerlink,
246 | h3:hover > a.headerlink,
247 | h4:hover > a.headerlink,
248 | h5:hover > a.headerlink,
249 | h6:hover > a.headerlink,
250 | dt:hover > a.headerlink,
251 | caption:hover > a.headerlink,
252 | p.caption:hover > a.headerlink,
253 | div.code-block-caption:hover > a.headerlink {
254 | visibility: visible;
255 | }
256 |
257 | div.body p.caption {
258 | text-align: inherit;
259 | }
260 |
261 | div.body td {
262 | text-align: left;
263 | }
264 |
265 | .first {
266 | margin-top: 0 !important;
267 | }
268 |
269 | p.rubric {
270 | margin-top: 30px;
271 | font-weight: bold;
272 | }
273 |
274 | img.align-left, figure.align-left, .figure.align-left, object.align-left {
275 | clear: left;
276 | float: left;
277 | margin-right: 1em;
278 | }
279 |
280 | img.align-right, figure.align-right, .figure.align-right, object.align-right {
281 | clear: right;
282 | float: right;
283 | margin-left: 1em;
284 | }
285 |
286 | img.align-center, figure.align-center, .figure.align-center, object.align-center {
287 | display: block;
288 | margin-left: auto;
289 | margin-right: auto;
290 | }
291 |
292 | img.align-default, figure.align-default, .figure.align-default {
293 | display: block;
294 | margin-left: auto;
295 | margin-right: auto;
296 | }
297 |
298 | .align-left {
299 | text-align: left;
300 | }
301 |
302 | .align-center {
303 | text-align: center;
304 | }
305 |
306 | .align-default {
307 | text-align: center;
308 | }
309 |
310 | .align-right {
311 | text-align: right;
312 | }
313 |
314 | /* -- sidebars -------------------------------------------------------------- */
315 |
316 | div.sidebar,
317 | aside.sidebar {
318 | margin: 0 0 0.5em 1em;
319 | border: 1px solid #ddb;
320 | padding: 7px;
321 | background-color: #ffe;
322 | width: 40%;
323 | float: right;
324 | clear: right;
325 | overflow-x: auto;
326 | }
327 |
328 | p.sidebar-title {
329 | font-weight: bold;
330 | }
331 |
332 | nav.contents,
333 | aside.topic,
334 | div.admonition, div.topic, blockquote {
335 | clear: left;
336 | }
337 |
338 | /* -- topics ---------------------------------------------------------------- */
339 |
340 | nav.contents,
341 | aside.topic,
342 | div.topic {
343 | border: 1px solid #ccc;
344 | padding: 7px;
345 | margin: 10px 0 10px 0;
346 | }
347 |
348 | p.topic-title {
349 | font-size: 1.1em;
350 | font-weight: bold;
351 | margin-top: 10px;
352 | }
353 |
354 | /* -- admonitions ----------------------------------------------------------- */
355 |
356 | div.admonition {
357 | margin-top: 10px;
358 | margin-bottom: 10px;
359 | padding: 7px;
360 | }
361 |
362 | div.admonition dt {
363 | font-weight: bold;
364 | }
365 |
366 | p.admonition-title {
367 | margin: 0px 10px 5px 0px;
368 | font-weight: bold;
369 | }
370 |
371 | div.body p.centered {
372 | text-align: center;
373 | margin-top: 25px;
374 | }
375 |
376 | /* -- content of sidebars/topics/admonitions -------------------------------- */
377 |
378 | div.sidebar > :last-child,
379 | aside.sidebar > :last-child,
380 | nav.contents > :last-child,
381 | aside.topic > :last-child,
382 | div.topic > :last-child,
383 | div.admonition > :last-child {
384 | margin-bottom: 0;
385 | }
386 |
387 | div.sidebar::after,
388 | aside.sidebar::after,
389 | nav.contents::after,
390 | aside.topic::after,
391 | div.topic::after,
392 | div.admonition::after,
393 | blockquote::after {
394 | display: block;
395 | content: '';
396 | clear: both;
397 | }
398 |
399 | /* -- tables ---------------------------------------------------------------- */
400 |
401 | table.docutils {
402 | margin-top: 10px;
403 | margin-bottom: 10px;
404 | border: 0;
405 | border-collapse: collapse;
406 | }
407 |
408 | table.align-center {
409 | margin-left: auto;
410 | margin-right: auto;
411 | }
412 |
413 | table.align-default {
414 | margin-left: auto;
415 | margin-right: auto;
416 | }
417 |
418 | table caption span.caption-number {
419 | font-style: italic;
420 | }
421 |
422 | table caption span.caption-text {
423 | }
424 |
425 | table.docutils td, table.docutils th {
426 | padding: 1px 8px 1px 5px;
427 | border-top: 0;
428 | border-left: 0;
429 | border-right: 0;
430 | border-bottom: 1px solid #aaa;
431 | }
432 |
433 | th {
434 | text-align: left;
435 | padding-right: 5px;
436 | }
437 |
438 | table.citation {
439 | border-left: solid 1px gray;
440 | margin-left: 1px;
441 | }
442 |
443 | table.citation td {
444 | border-bottom: none;
445 | }
446 |
447 | th > :first-child,
448 | td > :first-child {
449 | margin-top: 0px;
450 | }
451 |
452 | th > :last-child,
453 | td > :last-child {
454 | margin-bottom: 0px;
455 | }
456 |
457 | /* -- figures --------------------------------------------------------------- */
458 |
459 | div.figure, figure {
460 | margin: 0.5em;
461 | padding: 0.5em;
462 | }
463 |
464 | div.figure p.caption, figcaption {
465 | padding: 0.3em;
466 | }
467 |
468 | div.figure p.caption span.caption-number,
469 | figcaption span.caption-number {
470 | font-style: italic;
471 | }
472 |
473 | div.figure p.caption span.caption-text,
474 | figcaption span.caption-text {
475 | }
476 |
477 | /* -- field list styles ----------------------------------------------------- */
478 |
479 | table.field-list td, table.field-list th {
480 | border: 0 !important;
481 | }
482 |
483 | .field-list ul {
484 | margin: 0;
485 | padding-left: 1em;
486 | }
487 |
488 | .field-list p {
489 | margin: 0;
490 | }
491 |
492 | .field-name {
493 | -moz-hyphens: manual;
494 | -ms-hyphens: manual;
495 | -webkit-hyphens: manual;
496 | hyphens: manual;
497 | }
498 |
499 | /* -- hlist styles ---------------------------------------------------------- */
500 |
501 | table.hlist {
502 | margin: 1em 0;
503 | }
504 |
505 | table.hlist td {
506 | vertical-align: top;
507 | }
508 |
509 | /* -- object description styles --------------------------------------------- */
510 |
511 | .sig {
512 | font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
513 | }
514 |
515 | .sig-name, code.descname {
516 | background-color: transparent;
517 | font-weight: bold;
518 | }
519 |
520 | .sig-name {
521 | font-size: 1.1em;
522 | }
523 |
524 | code.descname {
525 | font-size: 1.2em;
526 | }
527 |
528 | .sig-prename, code.descclassname {
529 | background-color: transparent;
530 | }
531 |
532 | .optional {
533 | font-size: 1.3em;
534 | }
535 |
536 | .sig-paren {
537 | font-size: larger;
538 | }
539 |
540 | .sig-param.n {
541 | font-style: italic;
542 | }
543 |
544 | /* C++ specific styling */
545 |
546 | .sig-inline.c-texpr,
547 | .sig-inline.cpp-texpr {
548 | font-family: unset;
549 | }
550 |
551 | .sig.c .k, .sig.c .kt,
552 | .sig.cpp .k, .sig.cpp .kt {
553 | color: #0033B3;
554 | }
555 |
556 | .sig.c .m,
557 | .sig.cpp .m {
558 | color: #1750EB;
559 | }
560 |
561 | .sig.c .s, .sig.c .sc,
562 | .sig.cpp .s, .sig.cpp .sc {
563 | color: #067D17;
564 | }
565 |
566 |
567 | /* -- other body styles ----------------------------------------------------- */
568 |
569 | ol.arabic {
570 | list-style: decimal;
571 | }
572 |
573 | ol.loweralpha {
574 | list-style: lower-alpha;
575 | }
576 |
577 | ol.upperalpha {
578 | list-style: upper-alpha;
579 | }
580 |
581 | ol.lowerroman {
582 | list-style: lower-roman;
583 | }
584 |
585 | ol.upperroman {
586 | list-style: upper-roman;
587 | }
588 |
589 | :not(li) > ol > li:first-child > :first-child,
590 | :not(li) > ul > li:first-child > :first-child {
591 | margin-top: 0px;
592 | }
593 |
594 | :not(li) > ol > li:last-child > :last-child,
595 | :not(li) > ul > li:last-child > :last-child {
596 | margin-bottom: 0px;
597 | }
598 |
599 | ol.simple ol p,
600 | ol.simple ul p,
601 | ul.simple ol p,
602 | ul.simple ul p {
603 | margin-top: 0;
604 | }
605 |
606 | ol.simple > li:not(:first-child) > p,
607 | ul.simple > li:not(:first-child) > p {
608 | margin-top: 0;
609 | }
610 |
611 | ol.simple p,
612 | ul.simple p {
613 | margin-bottom: 0;
614 | }
615 |
616 | aside.footnote > span,
617 | div.citation > span {
618 | float: left;
619 | }
620 | aside.footnote > span:last-of-type,
621 | div.citation > span:last-of-type {
622 | padding-right: 0.5em;
623 | }
624 | aside.footnote > p {
625 | margin-left: 2em;
626 | }
627 | div.citation > p {
628 | margin-left: 4em;
629 | }
630 | aside.footnote > p:last-of-type,
631 | div.citation > p:last-of-type {
632 | margin-bottom: 0em;
633 | }
634 | aside.footnote > p:last-of-type:after,
635 | div.citation > p:last-of-type:after {
636 | content: "";
637 | clear: both;
638 | }
639 |
640 | dl.field-list {
641 | display: grid;
642 | grid-template-columns: fit-content(30%) auto;
643 | }
644 |
645 | dl.field-list > dt {
646 | font-weight: bold;
647 | word-break: break-word;
648 | padding-left: 0.5em;
649 | padding-right: 5px;
650 | }
651 |
652 | dl.field-list > dd {
653 | padding-left: 0.5em;
654 | margin-top: 0em;
655 | margin-left: 0em;
656 | margin-bottom: 0em;
657 | }
658 |
659 | dl {
660 | margin-bottom: 15px;
661 | }
662 |
663 | dd > :first-child {
664 | margin-top: 0px;
665 | }
666 |
667 | dd ul, dd table {
668 | margin-bottom: 10px;
669 | }
670 |
671 | dd {
672 | margin-top: 3px;
673 | margin-bottom: 10px;
674 | margin-left: 30px;
675 | }
676 |
677 | .sig dd {
678 | margin-top: 0px;
679 | margin-bottom: 0px;
680 | }
681 |
682 | .sig dl {
683 | margin-top: 0px;
684 | margin-bottom: 0px;
685 | }
686 |
687 | dl > dd:last-child,
688 | dl > dd:last-child > :last-child {
689 | margin-bottom: 0;
690 | }
691 |
692 | dt:target, span.highlighted {
693 | background-color: #fbe54e;
694 | }
695 |
696 | rect.highlighted {
697 | fill: #fbe54e;
698 | }
699 |
700 | dl.glossary dt {
701 | font-weight: bold;
702 | font-size: 1.1em;
703 | }
704 |
705 | .versionmodified {
706 | font-style: italic;
707 | }
708 |
709 | .system-message {
710 | background-color: #fda;
711 | padding: 5px;
712 | border: 3px solid red;
713 | }
714 |
715 | .footnote:target {
716 | background-color: #ffa;
717 | }
718 |
719 | .line-block {
720 | display: block;
721 | margin-top: 1em;
722 | margin-bottom: 1em;
723 | }
724 |
725 | .line-block .line-block {
726 | margin-top: 0;
727 | margin-bottom: 0;
728 | margin-left: 1.5em;
729 | }
730 |
731 | .guilabel, .menuselection {
732 | font-family: sans-serif;
733 | }
734 |
735 | .accelerator {
736 | text-decoration: underline;
737 | }
738 |
739 | .classifier {
740 | font-style: oblique;
741 | }
742 |
743 | .classifier:before {
744 | font-style: normal;
745 | margin: 0 0.5em;
746 | content: ":";
747 | display: inline-block;
748 | }
749 |
750 | abbr, acronym {
751 | border-bottom: dotted 1px;
752 | cursor: help;
753 | }
754 |
755 | .translated {
756 | background-color: rgba(207, 255, 207, 0.2)
757 | }
758 |
759 | .untranslated {
760 | background-color: rgba(255, 207, 207, 0.2)
761 | }
762 |
763 | /* -- code displays --------------------------------------------------------- */
764 |
765 | pre {
766 | overflow: auto;
767 | overflow-y: hidden; /* fixes display issues on Chrome browsers */
768 | }
769 |
770 | pre, div[class*="highlight-"] {
771 | clear: both;
772 | }
773 |
774 | span.pre {
775 | -moz-hyphens: none;
776 | -ms-hyphens: none;
777 | -webkit-hyphens: none;
778 | hyphens: none;
779 | white-space: nowrap;
780 | }
781 |
782 | div[class*="highlight-"] {
783 | margin: 1em 0;
784 | }
785 |
786 | td.linenos pre {
787 | border: 0;
788 | background-color: transparent;
789 | color: #aaa;
790 | }
791 |
792 | table.highlighttable {
793 | display: block;
794 | }
795 |
796 | table.highlighttable tbody {
797 | display: block;
798 | }
799 |
800 | table.highlighttable tr {
801 | display: flex;
802 | }
803 |
804 | table.highlighttable td {
805 | margin: 0;
806 | padding: 0;
807 | }
808 |
809 | table.highlighttable td.linenos {
810 | padding-right: 0.5em;
811 | }
812 |
813 | table.highlighttable td.code {
814 | flex: 1;
815 | overflow: hidden;
816 | }
817 |
818 | .highlight .hll {
819 | display: block;
820 | }
821 |
822 | div.highlight pre,
823 | table.highlighttable pre {
824 | margin: 0;
825 | }
826 |
827 | div.code-block-caption + div {
828 | margin-top: 0;
829 | }
830 |
831 | div.code-block-caption {
832 | margin-top: 1em;
833 | padding: 2px 5px;
834 | font-size: small;
835 | }
836 |
837 | div.code-block-caption code {
838 | background-color: transparent;
839 | }
840 |
841 | table.highlighttable td.linenos,
842 | span.linenos,
843 | div.highlight span.gp { /* gp: Generic.Prompt */
844 | user-select: none;
845 | -webkit-user-select: text; /* Safari fallback only */
846 | -webkit-user-select: none; /* Chrome/Safari */
847 | -moz-user-select: none; /* Firefox */
848 | -ms-user-select: none; /* IE10+ */
849 | }
850 |
851 | div.code-block-caption span.caption-number {
852 | padding: 0.1em 0.3em;
853 | font-style: italic;
854 | }
855 |
856 | div.code-block-caption span.caption-text {
857 | }
858 |
859 | div.literal-block-wrapper {
860 | margin: 1em 0;
861 | }
862 |
863 | code.xref, a code {
864 | background-color: transparent;
865 | font-weight: bold;
866 | }
867 |
868 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
869 | background-color: transparent;
870 | }
871 |
872 | .viewcode-link {
873 | float: right;
874 | }
875 |
876 | .viewcode-back {
877 | float: right;
878 | font-family: sans-serif;
879 | }
880 |
881 | div.viewcode-block:target {
882 | margin: -1px -10px;
883 | padding: 0 10px;
884 | }
885 |
886 | /* -- math display ---------------------------------------------------------- */
887 |
888 | img.math {
889 | vertical-align: middle;
890 | }
891 |
892 | div.body div.math p {
893 | text-align: center;
894 | }
895 |
896 | span.eqno {
897 | float: right;
898 | }
899 |
900 | span.eqno a.headerlink {
901 | position: absolute;
902 | z-index: 1;
903 | }
904 |
905 | div.math:hover a.headerlink {
906 | visibility: visible;
907 | }
908 |
909 | /* -- printout stylesheet --------------------------------------------------- */
910 |
911 | @media print {
912 | div.document,
913 | div.documentwrapper,
914 | div.bodywrapper {
915 | margin: 0 !important;
916 | width: 100%;
917 | }
918 |
919 | div.sphinxsidebar,
920 | div.related,
921 | div.footer,
922 | #top-link {
923 | display: none;
924 | }
925 | }
--------------------------------------------------------------------------------
/docs/build/html/_static/debug.css:
--------------------------------------------------------------------------------
1 | /*
2 | This CSS file should be overridden by the theme authors. It's
3 | meant for debugging and developing the skeleton that this theme provides.
4 | */
5 | body {
6 | font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
7 | "Apple Color Emoji", "Segoe UI Emoji";
8 | background: lavender;
9 | }
10 | .sb-announcement {
11 | background: rgb(131, 131, 131);
12 | }
13 | .sb-announcement__inner {
14 | background: black;
15 | color: white;
16 | }
17 | .sb-header {
18 | background: lightskyblue;
19 | }
20 | .sb-header__inner {
21 | background: royalblue;
22 | color: white;
23 | }
24 | .sb-header-secondary {
25 | background: lightcyan;
26 | }
27 | .sb-header-secondary__inner {
28 | background: cornflowerblue;
29 | color: white;
30 | }
31 | .sb-sidebar-primary {
32 | background: lightgreen;
33 | }
34 | .sb-main {
35 | background: blanchedalmond;
36 | }
37 | .sb-main__inner {
38 | background: antiquewhite;
39 | }
40 | .sb-header-article {
41 | background: lightsteelblue;
42 | }
43 | .sb-article-container {
44 | background: snow;
45 | }
46 | .sb-article-main {
47 | background: white;
48 | }
49 | .sb-footer-article {
50 | background: lightpink;
51 | }
52 | .sb-sidebar-secondary {
53 | background: lightgoldenrodyellow;
54 | }
55 | .sb-footer-content {
56 | background: plum;
57 | }
58 | .sb-footer-content__inner {
59 | background: palevioletred;
60 | }
61 | .sb-footer {
62 | background: pink;
63 | }
64 | .sb-footer__inner {
65 | background: salmon;
66 | }
67 | .sb-article {
68 | background: white;
69 | }
70 |
--------------------------------------------------------------------------------
/docs/build/html/_static/doctools.js:
--------------------------------------------------------------------------------
1 | /*
2 | * doctools.js
3 | * ~~~~~~~~~~~
4 | *
5 | * Base JavaScript utilities for all Sphinx HTML documentation.
6 | *
7 | * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 | "use strict";
12 |
13 | const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
14 | "TEXTAREA",
15 | "INPUT",
16 | "SELECT",
17 | "BUTTON",
18 | ]);
19 |
20 | const _ready = (callback) => {
21 | if (document.readyState !== "loading") {
22 | callback();
23 | } else {
24 | document.addEventListener("DOMContentLoaded", callback);
25 | }
26 | };
27 |
28 | /**
29 | * Small JavaScript module for the documentation.
30 | */
31 | const Documentation = {
32 | init: () => {
33 | Documentation.initDomainIndexTable();
34 | Documentation.initOnKeyListeners();
35 | },
36 |
37 | /**
38 | * i18n support
39 | */
40 | TRANSLATIONS: {},
41 | PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
42 | LOCALE: "unknown",
43 |
44 | // gettext and ngettext don't access this so that the functions
45 | // can safely bound to a different name (_ = Documentation.gettext)
46 | gettext: (string) => {
47 | const translated = Documentation.TRANSLATIONS[string];
48 | switch (typeof translated) {
49 | case "undefined":
50 | return string; // no translation
51 | case "string":
52 | return translated; // translation exists
53 | default:
54 | return translated[0]; // (singular, plural) translation tuple exists
55 | }
56 | },
57 |
58 | ngettext: (singular, plural, n) => {
59 | const translated = Documentation.TRANSLATIONS[singular];
60 | if (typeof translated !== "undefined")
61 | return translated[Documentation.PLURAL_EXPR(n)];
62 | return n === 1 ? singular : plural;
63 | },
64 |
65 | addTranslations: (catalog) => {
66 | Object.assign(Documentation.TRANSLATIONS, catalog.messages);
67 | Documentation.PLURAL_EXPR = new Function(
68 | "n",
69 | `return (${catalog.plural_expr})`
70 | );
71 | Documentation.LOCALE = catalog.locale;
72 | },
73 |
74 | /**
75 | * helper function to focus on search bar
76 | */
77 | focusSearchBar: () => {
78 | document.querySelectorAll("input[name=q]")[0]?.focus();
79 | },
80 |
81 | /**
82 | * Initialise the domain index toggle buttons
83 | */
84 | initDomainIndexTable: () => {
85 | const toggler = (el) => {
86 | const idNumber = el.id.substr(7);
87 | const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
88 | if (el.src.substr(-9) === "minus.png") {
89 | el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
90 | toggledRows.forEach((el) => (el.style.display = "none"));
91 | } else {
92 | el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
93 | toggledRows.forEach((el) => (el.style.display = ""));
94 | }
95 | };
96 |
97 | const togglerElements = document.querySelectorAll("img.toggler");
98 | togglerElements.forEach((el) =>
99 | el.addEventListener("click", (event) => toggler(event.currentTarget))
100 | );
101 | togglerElements.forEach((el) => (el.style.display = ""));
102 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
103 | },
104 |
105 | initOnKeyListeners: () => {
106 | // only install a listener if it is really needed
107 | if (
108 | !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
109 | !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
110 | )
111 | return;
112 |
113 | document.addEventListener("keydown", (event) => {
114 | // bail for input elements
115 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
116 | // bail with special keys
117 | if (event.altKey || event.ctrlKey || event.metaKey) return;
118 |
119 | if (!event.shiftKey) {
120 | switch (event.key) {
121 | case "ArrowLeft":
122 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
123 |
124 | const prevLink = document.querySelector('link[rel="prev"]');
125 | if (prevLink && prevLink.href) {
126 | window.location.href = prevLink.href;
127 | event.preventDefault();
128 | }
129 | break;
130 | case "ArrowRight":
131 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
132 |
133 | const nextLink = document.querySelector('link[rel="next"]');
134 | if (nextLink && nextLink.href) {
135 | window.location.href = nextLink.href;
136 | event.preventDefault();
137 | }
138 | break;
139 | }
140 | }
141 |
142 | // some keyboard layouts may need Shift to get /
143 | switch (event.key) {
144 | case "/":
145 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
146 | Documentation.focusSearchBar();
147 | event.preventDefault();
148 | }
149 | });
150 | },
151 | };
152 |
153 | // quick alias for translations
154 | const _ = Documentation.gettext;
155 |
156 | _ready(Documentation.init);
157 |
--------------------------------------------------------------------------------
/docs/build/html/_static/documentation_options.js:
--------------------------------------------------------------------------------
1 | const DOCUMENTATION_OPTIONS = {
2 | VERSION: '0.3.2',
3 | LANGUAGE: 'en',
4 | COLLAPSE_INDEX: false,
5 | BUILDER: 'html',
6 | FILE_SUFFIX: '.html',
7 | LINK_SUFFIX: '.html',
8 | HAS_SOURCE: true,
9 | SOURCELINK_SUFFIX: '.txt',
10 | NAVIGATION_WITH_KEYS: false,
11 | SHOW_SEARCH_SUMMARY: true,
12 | ENABLE_SEARCH_SHORTCUTS: true,
13 | };
--------------------------------------------------------------------------------
/docs/build/html/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_static/file.png
--------------------------------------------------------------------------------
/docs/build/html/_static/language_data.js:
--------------------------------------------------------------------------------
1 | /*
2 | * language_data.js
3 | * ~~~~~~~~~~~~~~~~
4 | *
5 | * This script contains the language-specific data used by searchtools.js,
6 | * namely the list of stopwords, stemmer, scorer and splitter.
7 | *
8 | * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS.
9 | * :license: BSD, see LICENSE for details.
10 | *
11 | */
12 |
13 | var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"];
14 |
15 |
16 | /* Non-minified version is copied as a separate JS file, if available */
17 |
18 | /**
19 | * Porter Stemmer
20 | */
21 | var Stemmer = function() {
22 |
23 | var step2list = {
24 | ational: 'ate',
25 | tional: 'tion',
26 | enci: 'ence',
27 | anci: 'ance',
28 | izer: 'ize',
29 | bli: 'ble',
30 | alli: 'al',
31 | entli: 'ent',
32 | eli: 'e',
33 | ousli: 'ous',
34 | ization: 'ize',
35 | ation: 'ate',
36 | ator: 'ate',
37 | alism: 'al',
38 | iveness: 'ive',
39 | fulness: 'ful',
40 | ousness: 'ous',
41 | aliti: 'al',
42 | iviti: 'ive',
43 | biliti: 'ble',
44 | logi: 'log'
45 | };
46 |
47 | var step3list = {
48 | icate: 'ic',
49 | ative: '',
50 | alize: 'al',
51 | iciti: 'ic',
52 | ical: 'ic',
53 | ful: '',
54 | ness: ''
55 | };
56 |
57 | var c = "[^aeiou]"; // consonant
58 | var v = "[aeiouy]"; // vowel
59 | var C = c + "[^aeiouy]*"; // consonant sequence
60 | var V = v + "[aeiou]*"; // vowel sequence
61 |
62 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
63 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
64 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
65 | var s_v = "^(" + C + ")?" + v; // vowel in stem
66 |
67 | this.stemWord = function (w) {
68 | var stem;
69 | var suffix;
70 | var firstch;
71 | var origword = w;
72 |
73 | if (w.length < 3)
74 | return w;
75 |
76 | var re;
77 | var re2;
78 | var re3;
79 | var re4;
80 |
81 | firstch = w.substr(0,1);
82 | if (firstch == "y")
83 | w = firstch.toUpperCase() + w.substr(1);
84 |
85 | // Step 1a
86 | re = /^(.+?)(ss|i)es$/;
87 | re2 = /^(.+?)([^s])s$/;
88 |
89 | if (re.test(w))
90 | w = w.replace(re,"$1$2");
91 | else if (re2.test(w))
92 | w = w.replace(re2,"$1$2");
93 |
94 | // Step 1b
95 | re = /^(.+?)eed$/;
96 | re2 = /^(.+?)(ed|ing)$/;
97 | if (re.test(w)) {
98 | var fp = re.exec(w);
99 | re = new RegExp(mgr0);
100 | if (re.test(fp[1])) {
101 | re = /.$/;
102 | w = w.replace(re,"");
103 | }
104 | }
105 | else if (re2.test(w)) {
106 | var fp = re2.exec(w);
107 | stem = fp[1];
108 | re2 = new RegExp(s_v);
109 | if (re2.test(stem)) {
110 | w = stem;
111 | re2 = /(at|bl|iz)$/;
112 | re3 = new RegExp("([^aeiouylsz])\\1$");
113 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
114 | if (re2.test(w))
115 | w = w + "e";
116 | else if (re3.test(w)) {
117 | re = /.$/;
118 | w = w.replace(re,"");
119 | }
120 | else if (re4.test(w))
121 | w = w + "e";
122 | }
123 | }
124 |
125 | // Step 1c
126 | re = /^(.+?)y$/;
127 | if (re.test(w)) {
128 | var fp = re.exec(w);
129 | stem = fp[1];
130 | re = new RegExp(s_v);
131 | if (re.test(stem))
132 | w = stem + "i";
133 | }
134 |
135 | // Step 2
136 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
137 | if (re.test(w)) {
138 | var fp = re.exec(w);
139 | stem = fp[1];
140 | suffix = fp[2];
141 | re = new RegExp(mgr0);
142 | if (re.test(stem))
143 | w = stem + step2list[suffix];
144 | }
145 |
146 | // Step 3
147 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
148 | if (re.test(w)) {
149 | var fp = re.exec(w);
150 | stem = fp[1];
151 | suffix = fp[2];
152 | re = new RegExp(mgr0);
153 | if (re.test(stem))
154 | w = stem + step3list[suffix];
155 | }
156 |
157 | // Step 4
158 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
159 | re2 = /^(.+?)(s|t)(ion)$/;
160 | if (re.test(w)) {
161 | var fp = re.exec(w);
162 | stem = fp[1];
163 | re = new RegExp(mgr1);
164 | if (re.test(stem))
165 | w = stem;
166 | }
167 | else if (re2.test(w)) {
168 | var fp = re2.exec(w);
169 | stem = fp[1] + fp[2];
170 | re2 = new RegExp(mgr1);
171 | if (re2.test(stem))
172 | w = stem;
173 | }
174 |
175 | // Step 5
176 | re = /^(.+?)e$/;
177 | if (re.test(w)) {
178 | var fp = re.exec(w);
179 | stem = fp[1];
180 | re = new RegExp(mgr1);
181 | re2 = new RegExp(meq1);
182 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
183 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
184 | w = stem;
185 | }
186 | re = /ll$/;
187 | re2 = new RegExp(mgr1);
188 | if (re.test(w) && re2.test(w)) {
189 | re = /.$/;
190 | w = w.replace(re,"");
191 | }
192 |
193 | // and turn initial Y back to y
194 | if (firstch == "y")
195 | w = firstch.toLowerCase() + w.substr(1);
196 | return w;
197 | }
198 | }
199 |
200 |
--------------------------------------------------------------------------------
/docs/build/html/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_static/minus.png
--------------------------------------------------------------------------------
/docs/build/html/_static/nbsphinx-broken-thumbnail.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/docs/build/html/_static/nbsphinx-code-cells.css:
--------------------------------------------------------------------------------
1 | /* remove conflicting styling from Sphinx themes */
2 | div.nbinput.container div.prompt *,
3 | div.nboutput.container div.prompt *,
4 | div.nbinput.container div.input_area pre,
5 | div.nboutput.container div.output_area pre,
6 | div.nbinput.container div.input_area .highlight,
7 | div.nboutput.container div.output_area .highlight {
8 | border: none;
9 | padding: 0;
10 | margin: 0;
11 | box-shadow: none;
12 | }
13 |
14 | div.nbinput.container > div[class*=highlight],
15 | div.nboutput.container > div[class*=highlight] {
16 | margin: 0;
17 | }
18 |
19 | div.nbinput.container div.prompt *,
20 | div.nboutput.container div.prompt * {
21 | background: none;
22 | }
23 |
24 | div.nboutput.container div.output_area .highlight,
25 | div.nboutput.container div.output_area pre {
26 | background: unset;
27 | }
28 |
29 | div.nboutput.container div.output_area div.highlight {
30 | color: unset; /* override Pygments text color */
31 | }
32 |
33 | /* avoid gaps between output lines */
34 | div.nboutput.container div[class*=highlight] pre {
35 | line-height: normal;
36 | }
37 |
38 | /* input/output containers */
39 | div.nbinput.container,
40 | div.nboutput.container {
41 | display: -webkit-flex;
42 | display: flex;
43 | align-items: flex-start;
44 | margin: 0;
45 | width: 100%;
46 | }
47 | @media (max-width: 540px) {
48 | div.nbinput.container,
49 | div.nboutput.container {
50 | flex-direction: column;
51 | }
52 | }
53 |
54 | /* input container */
55 | div.nbinput.container {
56 | padding-top: 5px;
57 | }
58 |
59 | /* last container */
60 | div.nblast.container {
61 | padding-bottom: 5px;
62 | }
63 |
64 | /* input prompt */
65 | div.nbinput.container div.prompt pre,
66 | /* for sphinx_immaterial theme: */
67 | div.nbinput.container div.prompt pre > code {
68 | color: #307FC1;
69 | }
70 |
71 | /* output prompt */
72 | div.nboutput.container div.prompt pre,
73 | /* for sphinx_immaterial theme: */
74 | div.nboutput.container div.prompt pre > code {
75 | color: #BF5B3D;
76 | }
77 |
78 | /* all prompts */
79 | div.nbinput.container div.prompt,
80 | div.nboutput.container div.prompt {
81 | width: 4.5ex;
82 | padding-top: 5px;
83 | position: relative;
84 | user-select: none;
85 | }
86 |
87 | div.nbinput.container div.prompt > div,
88 | div.nboutput.container div.prompt > div {
89 | position: absolute;
90 | right: 0;
91 | margin-right: 0.3ex;
92 | }
93 |
94 | @media (max-width: 540px) {
95 | div.nbinput.container div.prompt,
96 | div.nboutput.container div.prompt {
97 | width: unset;
98 | text-align: left;
99 | padding: 0.4em;
100 | }
101 | div.nboutput.container div.prompt.empty {
102 | padding: 0;
103 | }
104 |
105 | div.nbinput.container div.prompt > div,
106 | div.nboutput.container div.prompt > div {
107 | position: unset;
108 | }
109 | }
110 |
111 | /* disable scrollbars and line breaks on prompts */
112 | div.nbinput.container div.prompt pre,
113 | div.nboutput.container div.prompt pre {
114 | overflow: hidden;
115 | white-space: pre;
116 | }
117 |
118 | /* input/output area */
119 | div.nbinput.container div.input_area,
120 | div.nboutput.container div.output_area {
121 | -webkit-flex: 1;
122 | flex: 1;
123 | overflow: auto;
124 | }
125 | @media (max-width: 540px) {
126 | div.nbinput.container div.input_area,
127 | div.nboutput.container div.output_area {
128 | width: 100%;
129 | }
130 | }
131 |
132 | /* input area */
133 | div.nbinput.container div.input_area {
134 | border: 1px solid #e0e0e0;
135 | border-radius: 2px;
136 | /*background: #f5f5f5;*/
137 | }
138 |
139 | /* override MathJax center alignment in output cells */
140 | div.nboutput.container div[class*=MathJax] {
141 | text-align: left !important;
142 | }
143 |
144 | /* override sphinx.ext.imgmath center alignment in output cells */
145 | div.nboutput.container div.math p {
146 | text-align: left;
147 | }
148 |
149 | /* standard error */
150 | div.nboutput.container div.output_area.stderr {
151 | background: #fdd;
152 | }
153 |
154 | /* ANSI colors */
155 | .ansi-black-fg { color: #3E424D; }
156 | .ansi-black-bg { background-color: #3E424D; }
157 | .ansi-black-intense-fg { color: #282C36; }
158 | .ansi-black-intense-bg { background-color: #282C36; }
159 | .ansi-red-fg { color: #E75C58; }
160 | .ansi-red-bg { background-color: #E75C58; }
161 | .ansi-red-intense-fg { color: #B22B31; }
162 | .ansi-red-intense-bg { background-color: #B22B31; }
163 | .ansi-green-fg { color: #00A250; }
164 | .ansi-green-bg { background-color: #00A250; }
165 | .ansi-green-intense-fg { color: #007427; }
166 | .ansi-green-intense-bg { background-color: #007427; }
167 | .ansi-yellow-fg { color: #DDB62B; }
168 | .ansi-yellow-bg { background-color: #DDB62B; }
169 | .ansi-yellow-intense-fg { color: #B27D12; }
170 | .ansi-yellow-intense-bg { background-color: #B27D12; }
171 | .ansi-blue-fg { color: #208FFB; }
172 | .ansi-blue-bg { background-color: #208FFB; }
173 | .ansi-blue-intense-fg { color: #0065CA; }
174 | .ansi-blue-intense-bg { background-color: #0065CA; }
175 | .ansi-magenta-fg { color: #D160C4; }
176 | .ansi-magenta-bg { background-color: #D160C4; }
177 | .ansi-magenta-intense-fg { color: #A03196; }
178 | .ansi-magenta-intense-bg { background-color: #A03196; }
179 | .ansi-cyan-fg { color: #60C6C8; }
180 | .ansi-cyan-bg { background-color: #60C6C8; }
181 | .ansi-cyan-intense-fg { color: #258F8F; }
182 | .ansi-cyan-intense-bg { background-color: #258F8F; }
183 | .ansi-white-fg { color: #C5C1B4; }
184 | .ansi-white-bg { background-color: #C5C1B4; }
185 | .ansi-white-intense-fg { color: #A1A6B2; }
186 | .ansi-white-intense-bg { background-color: #A1A6B2; }
187 |
188 | .ansi-default-inverse-fg { color: #FFFFFF; }
189 | .ansi-default-inverse-bg { background-color: #000000; }
190 |
191 | .ansi-bold { font-weight: bold; }
192 | .ansi-underline { text-decoration: underline; }
193 |
194 |
195 | div.nbinput.container div.input_area div[class*=highlight] > pre,
196 | div.nboutput.container div.output_area div[class*=highlight] > pre,
197 | div.nboutput.container div.output_area div[class*=highlight].math,
198 | div.nboutput.container div.output_area.rendered_html,
199 | div.nboutput.container div.output_area > div.output_javascript,
200 | div.nboutput.container div.output_area:not(.rendered_html) > img{
201 | padding: 5px;
202 | margin: 0;
203 | }
204 |
205 | /* fix copybtn overflow problem in chromium (needed for 'sphinx_copybutton') */
206 | div.nbinput.container div.input_area > div[class^='highlight'],
207 | div.nboutput.container div.output_area > div[class^='highlight']{
208 | overflow-y: hidden;
209 | }
210 |
211 | /* hide copy button on prompts for 'sphinx_copybutton' extension ... */
212 | .prompt .copybtn,
213 | /* ... and 'sphinx_immaterial' theme */
214 | .prompt .md-clipboard.md-icon {
215 | display: none;
216 | }
217 |
218 | /* Some additional styling taken form the Jupyter notebook CSS */
219 | .jp-RenderedHTMLCommon table,
220 | div.rendered_html table {
221 | border: none;
222 | border-collapse: collapse;
223 | border-spacing: 0;
224 | color: black;
225 | font-size: 12px;
226 | table-layout: fixed;
227 | }
228 | .jp-RenderedHTMLCommon thead,
229 | div.rendered_html thead {
230 | border-bottom: 1px solid black;
231 | vertical-align: bottom;
232 | }
233 | .jp-RenderedHTMLCommon tr,
234 | .jp-RenderedHTMLCommon th,
235 | .jp-RenderedHTMLCommon td,
236 | div.rendered_html tr,
237 | div.rendered_html th,
238 | div.rendered_html td {
239 | text-align: right;
240 | vertical-align: middle;
241 | padding: 0.5em 0.5em;
242 | line-height: normal;
243 | white-space: normal;
244 | max-width: none;
245 | border: none;
246 | }
247 | .jp-RenderedHTMLCommon th,
248 | div.rendered_html th {
249 | font-weight: bold;
250 | }
251 | .jp-RenderedHTMLCommon tbody tr:nth-child(odd),
252 | div.rendered_html tbody tr:nth-child(odd) {
253 | background: #f5f5f5;
254 | }
255 | .jp-RenderedHTMLCommon tbody tr:hover,
256 | div.rendered_html tbody tr:hover {
257 | background: rgba(66, 165, 245, 0.2);
258 | }
259 |
260 |
--------------------------------------------------------------------------------
/docs/build/html/_static/nbsphinx-gallery.css:
--------------------------------------------------------------------------------
1 | .nbsphinx-gallery {
2 | display: grid;
3 | grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
4 | gap: 5px;
5 | margin-top: 1em;
6 | margin-bottom: 1em;
7 | }
8 |
9 | .nbsphinx-gallery > a {
10 | padding: 5px;
11 | border: 1px dotted currentColor;
12 | border-radius: 2px;
13 | text-align: center;
14 | }
15 |
16 | .nbsphinx-gallery > a:hover {
17 | border-style: solid;
18 | }
19 |
20 | .nbsphinx-gallery img {
21 | max-width: 100%;
22 | max-height: 100%;
23 | }
24 |
25 | .nbsphinx-gallery > a > div:first-child {
26 | display: flex;
27 | align-items: start;
28 | justify-content: center;
29 | height: 120px;
30 | margin-bottom: 5px;
31 | }
32 |
--------------------------------------------------------------------------------
/docs/build/html/_static/nbsphinx-no-thumbnail.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/docs/build/html/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_static/plus.png
--------------------------------------------------------------------------------
/docs/build/html/_static/scripts/furo-extensions.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/_static/scripts/furo-extensions.js
--------------------------------------------------------------------------------
/docs/build/html/_static/scripts/furo.js:
--------------------------------------------------------------------------------
1 | /*! For license information please see furo.js.LICENSE.txt */
2 | (()=>{var t={212:function(t,e,n){var o,r;r=void 0!==n.g?n.g:"undefined"!=typeof window?window:this,o=function(){return function(t){"use strict";var e={navClass:"active",contentClass:"active",nested:!1,nestedClass:"active",offset:0,reflow:!1,events:!0},n=function(t,e,n){if(n.settings.events){var o=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n});e.dispatchEvent(o)}},o=function(t){var e=0;if(t.offsetParent)for(;t;)e+=t.offsetTop,t=t.offsetParent;return e>=0?e:0},r=function(t){t&&t.sort((function(t,e){return o(t.content)=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},l=function(t,e){var n=t[t.length-1];if(function(t,e){return!(!s()||!c(t.content,e,!0))}(n,e))return n;for(var o=t.length-1;o>=0;o--)if(c(t[o].content,e))return t[o]},a=function(t,e){if(e.nested&&t.parentNode){var n=t.parentNode.closest("li");n&&(n.classList.remove(e.nestedClass),a(n,e))}},i=function(t,e){if(t){var o=t.nav.closest("li");o&&(o.classList.remove(e.navClass),t.content.classList.remove(e.contentClass),a(o,e),n("gumshoeDeactivate",o,{link:t.nav,content:t.content,settings:e}))}},u=function(t,e){if(e.nested){var n=t.parentNode.closest("li");n&&(n.classList.add(e.nestedClass),u(n,e))}};return function(o,c){var s,a,d,f,m,v={setup:function(){s=document.querySelectorAll(o),a=[],Array.prototype.forEach.call(s,(function(t){var e=document.getElementById(decodeURIComponent(t.hash.substr(1)));e&&a.push({nav:t,content:e})})),r(a)},detect:function(){var t=l(a,m);t?d&&t.content===d.content||(i(d,m),function(t,e){if(t){var o=t.nav.closest("li");o&&(o.classList.add(e.navClass),t.content.classList.add(e.contentClass),u(o,e),n("gumshoeActivate",o,{link:t.nav,content:t.content,settings:e}))}}(t,m),d=t):d&&(i(d,m),d=null)}},h=function(e){f&&t.cancelAnimationFrame(f),f=t.requestAnimationFrame(v.detect)},g=function(e){f&&t.cancelAnimationFrame(f),f=t.requestAnimationFrame((function(){r(a),v.detect()}))};return v.destroy=function(){d&&i(d,m),t.removeEventListener("scroll",h,!1),m.reflow&&t.removeEventListener("resize",g,!1),a=null,s=null,d=null,f=null,m=null},m=function(){var t={};return Array.prototype.forEach.call(arguments,(function(e){for(var n in e){if(!e.hasOwnProperty(n))return;t[n]=e[n]}})),t}(e,c||{}),v.setup(),v.detect(),t.addEventListener("scroll",h,!1),m.reflow&&t.addEventListener("resize",g,!1),v}}(r)}.apply(e,[]),void 0===o||(t.exports=o)}},e={};function n(o){var r=e[o];if(void 0!==r)return r.exports;var c=e[o]={exports:{}};return t[o].call(c.exports,c,c.exports,n),c.exports}n.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var o in e)n.o(e,o)&&!n.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{"use strict";var t=n(212),e=n.n(t),o=null,r=null,c=window.pageYOffset||document.documentElement.scrollTop;const s=64;function l(){const t=localStorage.getItem("theme")||"auto";var e;"light"!==(e=window.matchMedia("(prefers-color-scheme: dark)").matches?"auto"===t?"light":"light"==t?"dark":"auto":"auto"===t?"dark":"dark"==t?"light":"auto")&&"dark"!==e&&"auto"!==e&&(console.error(`Got invalid theme mode: ${e}. Resetting to auto.`),e="auto"),document.body.dataset.theme=e,localStorage.setItem("theme",e),console.log(`Changed to ${e} mode.`)}function a(){!function(){const t=document.getElementsByClassName("theme-toggle");Array.from(t).forEach((t=>{t.addEventListener("click",l)}))}(),function(){let t=0,e=!1;window.addEventListener("scroll",(function(n){t=window.scrollY,e||(window.requestAnimationFrame((function(){var n;n=t,0==Math.floor(r.getBoundingClientRect().top)?r.classList.add("scrolled"):r.classList.remove("scrolled"),function(t){tc&&document.documentElement.classList.remove("show-back-to-top"),c=t}(n),function(t){null!==o&&(0==t?o.scrollTo(0,0):Math.ceil(t)>=Math.floor(document.documentElement.scrollHeight-window.innerHeight)?o.scrollTo(0,o.scrollHeight):document.querySelector(".scroll-current"))}(n),e=!1})),e=!0)})),window.scroll()}(),null!==o&&new(e())(".toc-tree a",{reflow:!0,recursive:!0,navClass:"scroll-current",offset:()=>{let t=parseFloat(getComputedStyle(document.documentElement).fontSize);return r.getBoundingClientRect().height+.5*t+1}})}document.addEventListener("DOMContentLoaded",(function(){document.body.parentNode.classList.remove("no-js"),r=document.querySelector("header"),o=document.querySelector(".toc-scroll"),a()}))})()})();
3 | //# sourceMappingURL=furo.js.map
--------------------------------------------------------------------------------
/docs/build/html/_static/scripts/furo.js.LICENSE.txt:
--------------------------------------------------------------------------------
1 | /*!
2 | * gumshoejs v5.1.2 (patched by @pradyunsg)
3 | * A simple, framework-agnostic scrollspy script.
4 | * (c) 2019 Chris Ferdinandi
5 | * MIT License
6 | * http://github.com/cferdinandi/gumshoe
7 | */
8 |
--------------------------------------------------------------------------------
/docs/build/html/_static/skeleton.css:
--------------------------------------------------------------------------------
1 | /* Some sane resets. */
2 | html {
3 | height: 100%;
4 | }
5 |
6 | body {
7 | margin: 0;
8 | min-height: 100%;
9 | }
10 |
11 | /* All the flexbox magic! */
12 | body,
13 | .sb-announcement,
14 | .sb-content,
15 | .sb-main,
16 | .sb-container,
17 | .sb-container__inner,
18 | .sb-article-container,
19 | .sb-footer-content,
20 | .sb-header,
21 | .sb-header-secondary,
22 | .sb-footer {
23 | display: flex;
24 | }
25 |
26 | /* These order things vertically */
27 | body,
28 | .sb-main,
29 | .sb-article-container {
30 | flex-direction: column;
31 | }
32 |
33 | /* Put elements in the center */
34 | .sb-header,
35 | .sb-header-secondary,
36 | .sb-container,
37 | .sb-content,
38 | .sb-footer,
39 | .sb-footer-content {
40 | justify-content: center;
41 | }
42 | /* Put elements at the ends */
43 | .sb-article-container {
44 | justify-content: space-between;
45 | }
46 |
47 | /* These elements grow. */
48 | .sb-main,
49 | .sb-content,
50 | .sb-container,
51 | article {
52 | flex-grow: 1;
53 | }
54 |
55 | /* Because padding making this wider is not fun */
56 | article {
57 | box-sizing: border-box;
58 | }
59 |
60 | /* The announcements element should never be wider than the page. */
61 | .sb-announcement {
62 | max-width: 100%;
63 | }
64 |
65 | .sb-sidebar-primary,
66 | .sb-sidebar-secondary {
67 | flex-shrink: 0;
68 | width: 17rem;
69 | }
70 |
71 | .sb-announcement__inner {
72 | justify-content: center;
73 |
74 | box-sizing: border-box;
75 | height: 3rem;
76 |
77 | overflow-x: auto;
78 | white-space: nowrap;
79 | }
80 |
81 | /* Sidebars, with checkbox-based toggle */
82 | .sb-sidebar-primary,
83 | .sb-sidebar-secondary {
84 | position: fixed;
85 | height: 100%;
86 | top: 0;
87 | }
88 |
89 | .sb-sidebar-primary {
90 | left: -17rem;
91 | transition: left 250ms ease-in-out;
92 | }
93 | .sb-sidebar-secondary {
94 | right: -17rem;
95 | transition: right 250ms ease-in-out;
96 | }
97 |
98 | .sb-sidebar-toggle {
99 | display: none;
100 | }
101 | .sb-sidebar-overlay {
102 | position: fixed;
103 | top: 0;
104 | width: 0;
105 | height: 0;
106 |
107 | transition: width 0ms ease 250ms, height 0ms ease 250ms, opacity 250ms ease;
108 |
109 | opacity: 0;
110 | background-color: rgba(0, 0, 0, 0.54);
111 | }
112 |
113 | #sb-sidebar-toggle--primary:checked
114 | ~ .sb-sidebar-overlay[for="sb-sidebar-toggle--primary"],
115 | #sb-sidebar-toggle--secondary:checked
116 | ~ .sb-sidebar-overlay[for="sb-sidebar-toggle--secondary"] {
117 | width: 100%;
118 | height: 100%;
119 | opacity: 1;
120 | transition: width 0ms ease, height 0ms ease, opacity 250ms ease;
121 | }
122 |
123 | #sb-sidebar-toggle--primary:checked ~ .sb-container .sb-sidebar-primary {
124 | left: 0;
125 | }
126 | #sb-sidebar-toggle--secondary:checked ~ .sb-container .sb-sidebar-secondary {
127 | right: 0;
128 | }
129 |
130 | /* Full-width mode */
131 | .drop-secondary-sidebar-for-full-width-content
132 | .hide-when-secondary-sidebar-shown {
133 | display: none !important;
134 | }
135 | .drop-secondary-sidebar-for-full-width-content .sb-sidebar-secondary {
136 | display: none !important;
137 | }
138 |
139 | /* Mobile views */
140 | .sb-page-width {
141 | width: 100%;
142 | }
143 |
144 | .sb-article-container,
145 | .sb-footer-content__inner,
146 | .drop-secondary-sidebar-for-full-width-content .sb-article,
147 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
148 | width: 100vw;
149 | }
150 |
151 | .sb-article,
152 | .match-content-width {
153 | padding: 0 1rem;
154 | box-sizing: border-box;
155 | }
156 |
157 | @media (min-width: 32rem) {
158 | .sb-article,
159 | .match-content-width {
160 | padding: 0 2rem;
161 | }
162 | }
163 |
164 | /* Tablet views */
165 | @media (min-width: 42rem) {
166 | .sb-article-container {
167 | width: auto;
168 | }
169 | .sb-footer-content__inner,
170 | .drop-secondary-sidebar-for-full-width-content .sb-article,
171 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
172 | width: 42rem;
173 | }
174 | .sb-article,
175 | .match-content-width {
176 | width: 42rem;
177 | }
178 | }
179 | @media (min-width: 46rem) {
180 | .sb-footer-content__inner,
181 | .drop-secondary-sidebar-for-full-width-content .sb-article,
182 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
183 | width: 46rem;
184 | }
185 | .sb-article,
186 | .match-content-width {
187 | width: 46rem;
188 | }
189 | }
190 | @media (min-width: 50rem) {
191 | .sb-footer-content__inner,
192 | .drop-secondary-sidebar-for-full-width-content .sb-article,
193 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
194 | width: 50rem;
195 | }
196 | .sb-article,
197 | .match-content-width {
198 | width: 50rem;
199 | }
200 | }
201 |
202 | /* Tablet views */
203 | @media (min-width: 59rem) {
204 | .sb-sidebar-secondary {
205 | position: static;
206 | }
207 | .hide-when-secondary-sidebar-shown {
208 | display: none !important;
209 | }
210 | .sb-footer-content__inner,
211 | .drop-secondary-sidebar-for-full-width-content .sb-article,
212 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
213 | width: 59rem;
214 | }
215 | .sb-article,
216 | .match-content-width {
217 | width: 42rem;
218 | }
219 | }
220 | @media (min-width: 63rem) {
221 | .sb-footer-content__inner,
222 | .drop-secondary-sidebar-for-full-width-content .sb-article,
223 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
224 | width: 63rem;
225 | }
226 | .sb-article,
227 | .match-content-width {
228 | width: 46rem;
229 | }
230 | }
231 | @media (min-width: 67rem) {
232 | .sb-footer-content__inner,
233 | .drop-secondary-sidebar-for-full-width-content .sb-article,
234 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
235 | width: 67rem;
236 | }
237 | .sb-article,
238 | .match-content-width {
239 | width: 50rem;
240 | }
241 | }
242 |
243 | /* Desktop views */
244 | @media (min-width: 76rem) {
245 | .sb-sidebar-primary {
246 | position: static;
247 | }
248 | .hide-when-primary-sidebar-shown {
249 | display: none !important;
250 | }
251 | .sb-footer-content__inner,
252 | .drop-secondary-sidebar-for-full-width-content .sb-article,
253 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
254 | width: 59rem;
255 | }
256 | .sb-article,
257 | .match-content-width {
258 | width: 42rem;
259 | }
260 | }
261 |
262 | /* Full desktop views */
263 | @media (min-width: 80rem) {
264 | .sb-article,
265 | .match-content-width {
266 | width: 46rem;
267 | }
268 | .sb-footer-content__inner,
269 | .drop-secondary-sidebar-for-full-width-content .sb-article,
270 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
271 | width: 63rem;
272 | }
273 | }
274 |
275 | @media (min-width: 84rem) {
276 | .sb-article,
277 | .match-content-width {
278 | width: 50rem;
279 | }
280 | .sb-footer-content__inner,
281 | .drop-secondary-sidebar-for-full-width-content .sb-article,
282 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
283 | width: 67rem;
284 | }
285 | }
286 |
287 | @media (min-width: 88rem) {
288 | .sb-footer-content__inner,
289 | .drop-secondary-sidebar-for-full-width-content .sb-article,
290 | .drop-secondary-sidebar-for-full-width-content .match-content-width {
291 | width: 67rem;
292 | }
293 | .sb-page-width {
294 | width: 88rem;
295 | }
296 | }
297 |
--------------------------------------------------------------------------------
/docs/build/html/_static/sphinx_highlight.js:
--------------------------------------------------------------------------------
1 | /* Highlighting utilities for Sphinx HTML documentation. */
2 | "use strict";
3 |
4 | const SPHINX_HIGHLIGHT_ENABLED = true
5 |
6 | /**
7 | * highlight a given string on a node by wrapping it in
8 | * span elements with the given class name.
9 | */
10 | const _highlight = (node, addItems, text, className) => {
11 | if (node.nodeType === Node.TEXT_NODE) {
12 | const val = node.nodeValue;
13 | const parent = node.parentNode;
14 | const pos = val.toLowerCase().indexOf(text);
15 | if (
16 | pos >= 0 &&
17 | !parent.classList.contains(className) &&
18 | !parent.classList.contains("nohighlight")
19 | ) {
20 | let span;
21 |
22 | const closestNode = parent.closest("body, svg, foreignObject");
23 | const isInSVG = closestNode && closestNode.matches("svg");
24 | if (isInSVG) {
25 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
26 | } else {
27 | span = document.createElement("span");
28 | span.classList.add(className);
29 | }
30 |
31 | span.appendChild(document.createTextNode(val.substr(pos, text.length)));
32 | const rest = document.createTextNode(val.substr(pos + text.length));
33 | parent.insertBefore(
34 | span,
35 | parent.insertBefore(
36 | rest,
37 | node.nextSibling
38 | )
39 | );
40 | node.nodeValue = val.substr(0, pos);
41 | /* There may be more occurrences of search term in this node. So call this
42 | * function recursively on the remaining fragment.
43 | */
44 | _highlight(rest, addItems, text, className);
45 |
46 | if (isInSVG) {
47 | const rect = document.createElementNS(
48 | "http://www.w3.org/2000/svg",
49 | "rect"
50 | );
51 | const bbox = parent.getBBox();
52 | rect.x.baseVal.value = bbox.x;
53 | rect.y.baseVal.value = bbox.y;
54 | rect.width.baseVal.value = bbox.width;
55 | rect.height.baseVal.value = bbox.height;
56 | rect.setAttribute("class", className);
57 | addItems.push({ parent: parent, target: rect });
58 | }
59 | }
60 | } else if (node.matches && !node.matches("button, select, textarea")) {
61 | node.childNodes.forEach((el) => _highlight(el, addItems, text, className));
62 | }
63 | };
64 | const _highlightText = (thisNode, text, className) => {
65 | let addItems = [];
66 | _highlight(thisNode, addItems, text, className);
67 | addItems.forEach((obj) =>
68 | obj.parent.insertAdjacentElement("beforebegin", obj.target)
69 | );
70 | };
71 |
72 | /**
73 | * Small JavaScript module for the documentation.
74 | */
75 | const SphinxHighlight = {
76 |
77 | /**
78 | * highlight the search words provided in localstorage in the text
79 | */
80 | highlightSearchWords: () => {
81 | if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight
82 |
83 | // get and clear terms from localstorage
84 | const url = new URL(window.location);
85 | const highlight =
86 | localStorage.getItem("sphinx_highlight_terms")
87 | || url.searchParams.get("highlight")
88 | || "";
89 | localStorage.removeItem("sphinx_highlight_terms")
90 | url.searchParams.delete("highlight");
91 | window.history.replaceState({}, "", url);
92 |
93 | // get individual terms from highlight string
94 | const terms = highlight.toLowerCase().split(/\s+/).filter(x => x);
95 | if (terms.length === 0) return; // nothing to do
96 |
97 | // There should never be more than one element matching "div.body"
98 | const divBody = document.querySelectorAll("div.body");
99 | const body = divBody.length ? divBody[0] : document.querySelector("body");
100 | window.setTimeout(() => {
101 | terms.forEach((term) => _highlightText(body, term, "highlighted"));
102 | }, 10);
103 |
104 | const searchBox = document.getElementById("searchbox");
105 | if (searchBox === null) return;
106 | searchBox.appendChild(
107 | document
108 | .createRange()
109 | .createContextualFragment(
110 | ' ' +
111 | '' +
112 | _("Hide Search Matches") +
113 | "
"
114 | )
115 | );
116 | },
117 |
118 | /**
119 | * helper function to hide the search marks again
120 | */
121 | hideSearchWords: () => {
122 | document
123 | .querySelectorAll("#searchbox .highlight-link")
124 | .forEach((el) => el.remove());
125 | document
126 | .querySelectorAll("span.highlighted")
127 | .forEach((el) => el.classList.remove("highlighted"));
128 | localStorage.removeItem("sphinx_highlight_terms")
129 | },
130 |
131 | initEscapeListener: () => {
132 | // only install a listener if it is really needed
133 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return;
134 |
135 | document.addEventListener("keydown", (event) => {
136 | // bail for input elements
137 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
138 | // bail with special keys
139 | if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return;
140 | if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) {
141 | SphinxHighlight.hideSearchWords();
142 | event.preventDefault();
143 | }
144 | });
145 | },
146 | };
147 |
148 | _ready(() => {
149 | /* Do not call highlightSearchWords() when we are on the search page.
150 | * It will highlight words from the *previous* search query.
151 | */
152 | if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords();
153 | SphinxHighlight.initEscapeListener();
154 | });
155 |
--------------------------------------------------------------------------------
/docs/build/html/_static/styles/furo-extensions.css:
--------------------------------------------------------------------------------
1 | #furo-sidebar-ad-placement{padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)}#furo-sidebar-ad-placement .ethical-sidebar{background:var(--color-background-secondary);border:none;box-shadow:none}#furo-sidebar-ad-placement .ethical-sidebar:hover{background:var(--color-background-hover)}#furo-sidebar-ad-placement .ethical-sidebar a{color:var(--color-foreground-primary)}#furo-sidebar-ad-placement .ethical-callout a{color:var(--color-foreground-secondary)!important}#furo-readthedocs-versions{background:transparent;display:block;position:static;width:100%}#furo-readthedocs-versions .rst-versions{background:#1a1c1e}#furo-readthedocs-versions .rst-current-version{background:var(--color-sidebar-item-background);cursor:unset}#furo-readthedocs-versions .rst-current-version:hover{background:var(--color-sidebar-item-background)}#furo-readthedocs-versions .rst-current-version .fa-book{color:var(--color-foreground-primary)}#furo-readthedocs-versions>.rst-other-versions{padding:0}#furo-readthedocs-versions>.rst-other-versions small{opacity:1}#furo-readthedocs-versions .injected .rst-versions{position:unset}#furo-readthedocs-versions:focus-within,#furo-readthedocs-versions:hover{box-shadow:0 0 0 1px var(--color-sidebar-background-border)}#furo-readthedocs-versions:focus-within .rst-current-version,#furo-readthedocs-versions:hover .rst-current-version{background:#1a1c1e;font-size:inherit;height:auto;line-height:inherit;padding:12px;text-align:right}#furo-readthedocs-versions:focus-within .rst-current-version .fa-book,#furo-readthedocs-versions:hover .rst-current-version .fa-book{color:#fff;float:left}#furo-readthedocs-versions:focus-within .fa-caret-down,#furo-readthedocs-versions:hover .fa-caret-down{display:none}#furo-readthedocs-versions:focus-within .injected,#furo-readthedocs-versions:focus-within .rst-current-version,#furo-readthedocs-versions:focus-within .rst-other-versions,#furo-readthedocs-versions:hover .injected,#furo-readthedocs-versions:hover .rst-current-version,#furo-readthedocs-versions:hover .rst-other-versions{display:block}#furo-readthedocs-versions:focus-within>.rst-current-version,#furo-readthedocs-versions:hover>.rst-current-version{display:none}.highlight:hover button.copybtn{color:var(--color-code-foreground)}.highlight button.copybtn{align-items:center;background-color:var(--color-code-background);border:none;color:var(--color-background-item);cursor:pointer;height:1.25em;opacity:1;right:.5rem;top:.625rem;transition:color .3s,opacity .3s;width:1.25em}.highlight button.copybtn:hover{background-color:var(--color-code-background);color:var(--color-brand-content)}.highlight button.copybtn:after{background-color:transparent;color:var(--color-code-foreground);display:none}.highlight button.copybtn.success{color:#22863a;transition:color 0ms}.highlight button.copybtn.success:after{display:block}.highlight button.copybtn svg{padding:0}body{--sd-color-primary:var(--color-brand-primary);--sd-color-primary-highlight:var(--color-brand-content);--sd-color-primary-text:var(--color-background-primary);--sd-color-shadow:rgba(0,0,0,.05);--sd-color-card-border:var(--color-card-border);--sd-color-card-border-hover:var(--color-brand-content);--sd-color-card-background:var(--color-card-background);--sd-color-card-text:var(--color-foreground-primary);--sd-color-card-header:var(--color-card-marginals-background);--sd-color-card-footer:var(--color-card-marginals-background);--sd-color-tabs-label-active:var(--color-brand-content);--sd-color-tabs-label-hover:var(--color-foreground-muted);--sd-color-tabs-label-inactive:var(--color-foreground-muted);--sd-color-tabs-underline-active:var(--color-brand-content);--sd-color-tabs-underline-hover:var(--color-foreground-border);--sd-color-tabs-underline-inactive:var(--color-background-border);--sd-color-tabs-overline:var(--color-background-border);--sd-color-tabs-underline:var(--color-background-border)}.sd-tab-content{box-shadow:0 -2px var(--sd-color-tabs-overline),0 1px var(--sd-color-tabs-underline)}.sd-card{box-shadow:0 .1rem .25rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)}.sd-shadow-sm{box-shadow:0 .1rem .25rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-shadow-md{box-shadow:0 .3rem .75rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-shadow-lg{box-shadow:0 .6rem 1.5rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-card-hover:hover{transform:none}.sd-cards-carousel{gap:.25rem;padding:.25rem}body{--tabs--label-text:var(--color-foreground-muted);--tabs--label-text--hover:var(--color-foreground-muted);--tabs--label-text--active:var(--color-brand-content);--tabs--label-text--active--hover:var(--color-brand-content);--tabs--label-background:transparent;--tabs--label-background--hover:transparent;--tabs--label-background--active:transparent;--tabs--label-background--active--hover:transparent;--tabs--padding-x:0.25em;--tabs--margin-x:1em;--tabs--border:var(--color-background-border);--tabs--label-border:transparent;--tabs--label-border--hover:var(--color-foreground-muted);--tabs--label-border--active:var(--color-brand-content);--tabs--label-border--active--hover:var(--color-brand-content)}[role=main] .container{max-width:none;padding-left:0;padding-right:0}.shadow.docutils{border:none;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1)!important}.sphinx-bs .card{background-color:var(--color-background-secondary);color:var(--color-foreground)}
2 | /*# sourceMappingURL=furo-extensions.css.map*/
--------------------------------------------------------------------------------
/docs/build/html/_static/styles/furo-extensions.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"styles/furo-extensions.css","mappings":"AAGA,2BACE,oFACA,4CAKE,6CAHA,YACA,eAEA,CACA,kDACE,yCAEF,8CACE,sCAEJ,8CACE,kDAEJ,2BAGE,uBACA,cAHA,gBACA,UAEA,CAGA,yCACE,mBAEF,gDAEE,gDADA,YACA,CACA,sDACE,gDACF,yDACE,sCAEJ,+CACE,UACA,qDACE,UAGF,mDACE,eAEJ,yEAEE,4DAEA,mHASE,mBAPA,kBAEA,YADA,oBAGA,aADA,gBAIA,CAEA,qIAEE,WADA,UACA,CAEJ,uGACE,aAEF,iUAGE,cAEF,mHACE,aC1EJ,gCACE,mCAEF,0BAKE,mBAUA,8CACA,YAFA,mCAKA,eAZA,cALA,UASA,YADA,YAYA,iCAdA,YAcA,CAEA,gCAEE,8CADA,gCACA,CAEF,gCAGE,6BADA,mCADA,YAEA,CAEF,kCAEE,cADA,oBACA,CACA,wCACE,cAEJ,8BACE,UC5CN,KAEE,6CAA8C,CAC9C,uDAAwD,CACxD,uDAAwD,CAGxD,iCAAsC,CAGtC,+CAAgD,CAChD,uDAAwD,CACxD,uDAAwD,CACxD,oDAAqD,CACrD,6DAA8D,CAC9D,6DAA8D,CAG9D,uDAAwD,CACxD,yDAA0D,CAC1D,4DAA6D,CAC7D,2DAA4D,CAC5D,8DAA+D,CAC/D,iEAAkE,CAClE,uDAAwD,CACxD,wDAAyD,CAG3D,gBACE,qFAGF,SACE,6EAEF,cACE,uFAEF,cACE,uFAEF,cACE,uFAGF,qBACE,eAEF,mBACE,WACA,eChDF,KACE,gDAAiD,CACjD,uDAAwD,CACxD,qDAAsD,CACtD,4DAA6D,CAC7D,oCAAqC,CACrC,2CAA4C,CAC5C,4CAA6C,CAC7C,mDAAoD,CACpD,wBAAyB,CACzB,oBAAqB,CACrB,6CAA8C,CAC9C,gCAAiC,CACjC,yDAA0D,CAC1D,uDAAwD,CACxD,8DAA+D,CCbjE,uBACE,eACA,eACA,gBAGF,iBACE,YACA,+EAGF,iBACE,mDACA","sources":["webpack:///./src/furo/assets/styles/extensions/_readthedocs.sass","webpack:///./src/furo/assets/styles/extensions/_copybutton.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-design.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-inline-tabs.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-panels.sass"],"sourcesContent":["// This file contains the styles used for tweaking how ReadTheDoc's embedded\n// contents would show up inside the theme.\n\n#furo-sidebar-ad-placement\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n .ethical-sidebar\n // Remove the border and box-shadow.\n border: none\n box-shadow: none\n // Manage the background colors.\n background: var(--color-background-secondary)\n &:hover\n background: var(--color-background-hover)\n // Ensure the text is legible.\n a\n color: var(--color-foreground-primary)\n\n .ethical-callout a\n color: var(--color-foreground-secondary) !important\n\n#furo-readthedocs-versions\n position: static\n width: 100%\n background: transparent\n display: block\n\n // Make the background color fit with the theme's aesthetic.\n .rst-versions\n background: rgb(26, 28, 30)\n\n .rst-current-version\n cursor: unset\n background: var(--color-sidebar-item-background)\n &:hover\n background: var(--color-sidebar-item-background)\n .fa-book\n color: var(--color-foreground-primary)\n\n > .rst-other-versions\n padding: 0\n small\n opacity: 1\n\n .injected\n .rst-versions\n position: unset\n\n &:hover,\n &:focus-within\n box-shadow: 0 0 0 1px var(--color-sidebar-background-border)\n\n .rst-current-version\n // Undo the tweaks done in RTD's CSS\n font-size: inherit\n line-height: inherit\n height: auto\n text-align: right\n padding: 12px\n\n // Match the rest of the body\n background: #1a1c1e\n\n .fa-book\n float: left\n color: white\n\n .fa-caret-down\n display: none\n\n .rst-current-version,\n .rst-other-versions,\n .injected\n display: block\n\n > .rst-current-version\n display: none\n",".highlight\n &:hover button.copybtn\n color: var(--color-code-foreground)\n\n button.copybtn\n // Make it visible\n opacity: 1\n\n // Align things correctly\n align-items: center\n\n height: 1.25em\n width: 1.25em\n\n top: 0.625rem // $code-spacing-vertical\n right: 0.5rem\n\n // Make it look better\n color: var(--color-background-item)\n background-color: var(--color-code-background)\n border: none\n\n // Change to cursor to make it obvious that you can click on it\n cursor: pointer\n\n // Transition smoothly, for aesthetics\n transition: color 300ms, opacity 300ms\n\n &:hover\n color: var(--color-brand-content)\n background-color: var(--color-code-background)\n\n &::after\n display: none\n color: var(--color-code-foreground)\n background-color: transparent\n\n &.success\n transition: color 0ms\n color: #22863a\n &::after\n display: block\n\n svg\n padding: 0\n","body\n // Colors\n --sd-color-primary: var(--color-brand-primary)\n --sd-color-primary-highlight: var(--color-brand-content)\n --sd-color-primary-text: var(--color-background-primary)\n\n // Shadows\n --sd-color-shadow: rgba(0, 0, 0, 0.05)\n\n // Cards\n --sd-color-card-border: var(--color-card-border)\n --sd-color-card-border-hover: var(--color-brand-content)\n --sd-color-card-background: var(--color-card-background)\n --sd-color-card-text: var(--color-foreground-primary)\n --sd-color-card-header: var(--color-card-marginals-background)\n --sd-color-card-footer: var(--color-card-marginals-background)\n\n // Tabs\n --sd-color-tabs-label-active: var(--color-brand-content)\n --sd-color-tabs-label-hover: var(--color-foreground-muted)\n --sd-color-tabs-label-inactive: var(--color-foreground-muted)\n --sd-color-tabs-underline-active: var(--color-brand-content)\n --sd-color-tabs-underline-hover: var(--color-foreground-border)\n --sd-color-tabs-underline-inactive: var(--color-background-border)\n --sd-color-tabs-overline: var(--color-background-border)\n --sd-color-tabs-underline: var(--color-background-border)\n\n// Tabs\n.sd-tab-content\n box-shadow: 0 -2px var(--sd-color-tabs-overline), 0 1px var(--sd-color-tabs-underline)\n\n// Shadows\n.sd-card // Have a shadow by default\n box-shadow: 0 0.1rem 0.25rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n.sd-shadow-sm\n box-shadow: 0 0.1rem 0.25rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n.sd-shadow-md\n box-shadow: 0 0.3rem 0.75rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n.sd-shadow-lg\n box-shadow: 0 0.6rem 1.5rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n// Cards\n.sd-card-hover:hover // Don't change scale on hover\n transform: none\n\n.sd-cards-carousel // Have a bit of gap in the carousel by default\n gap: 0.25rem\n padding: 0.25rem\n","// This file contains styles to tweak sphinx-inline-tabs to work well with Furo.\n\nbody\n --tabs--label-text: var(--color-foreground-muted)\n --tabs--label-text--hover: var(--color-foreground-muted)\n --tabs--label-text--active: var(--color-brand-content)\n --tabs--label-text--active--hover: var(--color-brand-content)\n --tabs--label-background: transparent\n --tabs--label-background--hover: transparent\n --tabs--label-background--active: transparent\n --tabs--label-background--active--hover: transparent\n --tabs--padding-x: 0.25em\n --tabs--margin-x: 1em\n --tabs--border: var(--color-background-border)\n --tabs--label-border: transparent\n --tabs--label-border--hover: var(--color-foreground-muted)\n --tabs--label-border--active: var(--color-brand-content)\n --tabs--label-border--active--hover: var(--color-brand-content)\n","// This file contains styles to tweak sphinx-panels to work well with Furo.\n\n// sphinx-panels includes Bootstrap 4, which uses .container which can conflict\n// with docutils' `.. container::` directive.\n[role=\"main\"] .container\n max-width: initial\n padding-left: initial\n padding-right: initial\n\n// Make the panels look nicer!\n.shadow.docutils\n border: none\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n// Make panel colors respond to dark mode\n.sphinx-bs .card\n background-color: var(--color-background-secondary)\n color: var(--color-foreground)\n"],"names":[],"sourceRoot":""}
--------------------------------------------------------------------------------
/docs/build/html/genindex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Index - scenvi 0.3.2 documentation
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
36 |
37 |
38 |
41 |
42 |
43 |
44 |
45 | Contents
46 |
47 |
48 |
49 |
50 |
59 |
60 | Expand
61 |
63 |
64 |
65 |
66 |
67 | Light mode
68 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | Dark mode
83 |
85 |
86 |
87 |
88 |
89 |
90 | Auto light/dark mode
91 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
109 |
110 | Hide table of contents sidebar
111 |
112 |
113 |
114 |
115 |
116 |
141 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 | Back to top
180 |
181 |
182 |
183 |
184 | Toggle Light / Dark / Auto color theme
185 |
186 |
187 |
188 |
189 |
190 |
191 | Toggle table of contents sidebar
192 |
193 |
194 |
195 |
196 |
197 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 | Copyright © 2024, Doron Haviv
214 |
215 | Made with
Sphinx and
@pradyunsg 's
216 |
217 |
Furo
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
--------------------------------------------------------------------------------
/docs/build/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | scenvi 0.3.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 | Contents
48 |
49 |
50 |
51 |
52 |
61 |
62 | Expand
63 |
65 |
66 |
67 |
68 |
69 | Light mode
70 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | Dark mode
85 |
87 |
88 |
89 |
90 |
91 |
92 | Auto light/dark mode
93 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
111 |
112 | Hide table of contents sidebar
113 |
114 |
115 |
116 |
117 |
118 |
143 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 | Back to top
182 |
183 |
184 |
185 |
186 |
187 | Toggle Light / Dark / Auto color theme
188 |
189 |
190 |
191 |
192 |
193 |
194 | Toggle table of contents sidebar
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 | ENVI & COVET
205 | ENVI is a deep learnining based variational inference method to integrate scRNA-seq with spatial transcriptomics data. ENVI learns to reconstruct spatial onto for dissociated scRNA-seq data and impute unimagd genes onto spatial data.
206 | This implementation is written in Python3 and relies on jax, flax, sklearn, scipy and scanpy.
207 | To install JAX, simply run the command:
208 | pip install -U "jax[cuda12_pip]" -f https://storage.googleapis.com/jax-releases/jax_cuda_releases.html
209 |
210 |
211 | And to install ENVI along with the rest of the requirements:
212 |
215 | To run ENVI:
216 | import scenvi
217 |
218 | envi_model = scenvi.ENVI(spatial_data = st_data, sc_data = sc_data)
219 |
220 | envi_model.train()
221 | envi_model.impute_genes()
222 | envi_model.infer_niche_covet()
223 | envi_model.infer_niche_celltype()
224 |
225 | st_data.obsm['envi_latent'] = envi_model.spatial_data.obsm['envi_latent']
226 | st_data.uns['COVET_genes'] = envi_model.CovGenes
227 | st_data.obsm['COVET'] = envi_model.spatial_data.obsm['COVET']
228 | st_data.obsm['COVET_SQRT'] = envi_model.spatial_data.obsm['COVET_SQRT']
229 | st_data.obsm['cell_type_niche'] = envi_model.spatial_data.obsm['cell_type_niche']
230 | st_data.obsm['imputation'] = envi_model.spatial_data.obsm['imputation']
231 |
232 |
233 | sc_data.obsm['envi_latent'] = envi_model.sc_data.obsm['envi_latent']
234 | sc_data.uns['COVET_genes'] = envi_model.CovGenes
235 | sc_data.obsm['COVET'] = envi_model.sc_data.obsm['COVET']
236 | sc_data.obsm['COVET_SQRT'] = envi_model.sc_data.obsm['COVET_SQRT']
237 | sc_data.obsm['cell_type_niche'] = envi_model.sc_data.obsm['cell_type_niche']
238 |
239 |
240 | And to just compute COVET for spatial data:
241 | st_data.obsm['COVET'], st_data.obsm['COVET_SQRT'], st_data.uns['CovGenes'] = scenvi.compute_covet(st_data)
242 |
243 |
244 | Please read our documentation and see a full tutorial at https://scenvi.readthedocs.io/ .
245 |
246 |
252 |
253 |
254 |
255 |
256 |
257 |
269 |
270 |
271 |
272 | Copyright © 2024, Doron Haviv
273 |
274 | Made with
Sphinx and
@pradyunsg 's
275 |
276 |
Furo
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
--------------------------------------------------------------------------------
/docs/build/html/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/docs/build/html/objects.inv
--------------------------------------------------------------------------------
/docs/build/html/search.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Search - scenvi 0.3.2 documentation
8 |
9 |
10 |
11 |
12 |
13 |
14 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
44 | Contents
45 |
46 |
47 |
48 |
49 |
58 |
59 | Expand
60 |
62 |
63 |
64 |
65 |
66 | Light mode
67 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | Dark mode
82 |
84 |
85 |
86 |
87 |
88 |
89 | Auto light/dark mode
90 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
108 |
109 | Hide table of contents sidebar
110 |
111 |
112 |
113 |
114 |
115 |
140 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 | Back to top
179 |
180 |
181 |
182 |
183 | Toggle Light / Dark / Auto color theme
184 |
185 |
186 |
187 |
188 |
189 |
190 | Toggle table of contents sidebar
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
Error
199 |
200 | Please activate JavaScript to enable the search functionality.
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 | Copyright © 2024, Doron Haviv
219 |
220 | Made with
Sphinx and
@pradyunsg 's
221 |
222 |
Furo
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
--------------------------------------------------------------------------------
/docs/build/html/searchindex.js:
--------------------------------------------------------------------------------
1 | Search.setIndex({"alltitles": {"Calculating FDL and DC on COVET": [[2, "Calculating-FDL-and-DC-on-COVET"]], "Data": [[2, "Data"]], "ENVI": [[0, "envi"]], "ENVI & COVET": [[1, "envi-covet"]], "ENVI COVET analysis": [[2, "ENVI-COVET-analysis"]], "ENVI Tutorial": [[2, "ENVI-Tutorial"]], "ENVI imputation on Spatial Data": [[2, "ENVI-imputation-on-Spatial-Data"]], "Importing": [[2, "Importing"]], "Index": [[1, "index"]], "Install ENVI": [[2, "Install-ENVI"]], "Niche Cell Type Composition": [[2, "Niche-Cell-Type-Composition"]], "Plot DC and Depth": [[2, "Plot-DC-and-Depth"]], "Plot UMAPs of ENVI latent": [[2, "Plot-UMAPs-of-ENVI-latent"]], "Plot as Stacked Bar Plots": [[2, "Plot-as-Stacked-Bar-Plots"]], "Plotting the Motor Cortex MERFISH": [[2, "Plotting-the-Motor-Cortex-MERFISH"]], "Plotting the Motor Cortex scRNAseq": [[2, "Plotting-the-Motor-Cortex-scRNAseq"]], "Reverse DC if needed": [[2, "Reverse-DC-if-needed"]], "Running ENVI": [[2, "Running-ENVI"]], "Subtype Depth": [[2, "Subtype-Depth"]], "Utilities": [[3, "utilities"]], "Utility Functions:": [[2, "Utility-Functions:"]], "What is COVET?": [[2, "What-is-COVET?"]], "What is ENVI?": [[2, "What-is-ENVI?"]]}, "docnames": ["ENVI", "index", "tutorial/MOp_MERFISH_tutorial", "utils"], "envversion": {"nbsphinx": 4, "sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["ENVI.rst", "index.rst", "tutorial/MOp_MERFISH_tutorial.ipynb", "utils.rst"], "indexentries": {}, "objects": {}, "objnames": {}, "objtypes": {}, "terms": {"": 2, "0": 2, "00": 2, "007843": 2, "01": 2, "015686": 2, "02": 2, "027451": 2, "03": 2, "03it": 2, "04": 2, "1": 2, "10": 2, "100": 2, "1000": 2, "106": 2, "108": 2, "10it": 2, "11": 2, "12": 2, "121": 2, "122": 2, "13": 2, "131": 2, "14": 2, "147": 2, "148": 2, "15": 2, "151": 2, "153": 2, "16": 2, "16000": 2, "17": 2, "18": 2, "185": 2, "188235": 2, "19": 2, "1e": 2, "2": 2, "2024": 2, "2048": 2, "207": 2, "21": 2, "22": 2, "23": 2, "231373": 2, "235294": 2, "24": 2, "25": 2, "255": 2, "256": 2, "26": 2, "27": 2, "28": 2, "29": 2, "294118": 2, "3": 2, "30": 2, "309804": 2, "31": 2, "329412": 2, "33": 2, "339e": 2, "341176": 2, "345098": 2, "34902": 2, "352941": 2, "368627": 2, "39": 2, "392157": 2, "4": 2, "415686": 2, "423529": 2, "431e": 2, "447059": 2, "454902": 2, "458824": 2, "466667": 2, "470588": 2, "473e": 2, "47451": 2, "478431": 2, "482353": 2, "494118": 2, "498039": 2, "5": 2, "500": 2, "533333": 2, "54902": 2, "556441": 2, "560784": 2, "564706": 2, "584314": 2, "59": 2, "596078": 2, "6": 2, "607843": 2, "631373": 2, "643137": 2, "647059": 2, "65098": 2, "67451": 2, "693e": 2, "7": 2, "709804": 2, "717647": 2, "718": 2, "72549": 2, "737255": 2, "752941": 2, "780392": 2, "8": 2, "80": 2, "811765": 2, "819608": 2, "843137": 2, "847059": 2, "866667": 2, "894118": 2, "9": 2, "92549": 2, "933333": 2, "94": 2, "95": 2, "960784": 2, "992157": 2, "996078": 2, "And": 1, "For": 2, "The": 2, "To": 1, "__module__": 2, "__name__": 2, "abund": 2, "adamts18": 2, "adapt": 2, "adaptive_k": 2, "adaptive_std": 2, "adjac": 2, "adjusts": 2, "adjustspeedandapplyforc": 2, "affin": 2, "affinity_matrix": 2, "all": 2, "along": 1, "alpha": 2, "altern": 2, "amazonaw": 2, "analy": 2, "anisotrop": 2, "anndata": 2, "approxim": 2, "ar": 2, "arang": 2, "arbitrari": 2, "argsort": 2, "arr": 2, "arrai": 2, "asarrai": 2, "ascend": 2, "astro": 2, "attract": 2, "auxiliari": 2, "aw": 2, "ax": 2, "axi": 2, "backward": 2, "barneshut": 2, "barneshutoptim": 2, "barneshuttheta": 2, "base": [1, 2], "batch": 2, "bbox_to_anchor": 2, "becaus": 2, "behavior": 2, "between": 2, "blue": 2, "box": 2, "boxenplot": 2, "bw": 2, "c": 2, "calb2": 2, "can": 2, "canon": 2, "cc": 2, "cell_label_palett": 2, "cell_nam": 2, "cell_typ": 2, "cell_type_nich": [1, 2], "cell_type_palett": 2, "cellular": 2, "cet_cet_d13": 2, "chang": 2, "check": 2, "chodl": 2, "cluster_label": 2, "cmap": 2, "co": 2, "col": 2, "color": 2, "colorcet": 2, "column": 2, "com": [1, 2], "command": [1, 2], "compat": 2, "compil": 2, "compon": 2, "comput": [1, 2], "compute_covet": 1, "concaten": 2, "construct": 2, "context": 2, "correspond": 2, "cortic": 2, "cov": 2, "covari": 2, "covet_gen": [1, 2], "covet_sqrt": [1, 2], "covgen": [1, 2], "cpu": 2, "creat": 2, "crh": 2, "crhr2": 2, "csr_matrix": 2, "cuda": 2, "cuda12_pip": 1, "cuda_device_ord": 2, "cuda_visible_devic": 2, "cvae": 2, "cvec": 2, "d": 2, "data": 1, "data_df": 2, "datafram": 2, "dataset": 2, "dc_covet": 2, "dcomposit": 2, "deep": [1, 2], "def": 2, "defin": 2, "delta": 2, "depth_df": 2, "determ": 2, "determin": 2, "devic": 2, "dictionari": 2, "diffus": 2, "direct": 2, "directli": 2, "disabl": 2, "dissoci": [1, 2], "dist": 2, "distanc": 2, "div": 2, "dkkl1": 2, "document": 1, "dot": 2, "doubl": 2, "down": 2, "download": 2, "dp": 2, "driver": 2, "drop": 2, "each": 2, "edgecolor": 2, "edgeweightinflu": 2, "eig": 2, "eigen": 2, "eigenvalu": 2, "eigenvector": 2, "els": 2, "emb": 2, "embed": 2, "endo": 2, "enumer": 2, "envi_lat": [1, 2], "envi_model": [1, 2], "environ": 2, "equal": 2, "er": 2, "etc": 2, "etv1": 2, "euclidean": 2, "everi": 2, "exp": 2, "extern": 2, "f": 1, "fa2": 2, "fals": 2, "fdl_covet": 2, "feel": 2, "fig": 2, "figsiz": 2, "figur": 2, "filterwarn": 2, "find": 2, "finish": 2, "first": 2, "fit": 2, "fit_transform": 2, "flatten": 2, "flax": 1, "flip": 2, "floor": 2, "follow": 2, "font_scal": 2, "fontsiz": 2, "forc": 2, "force_directed_layout": 2, "forceatla": 2, "forceatlas2": 2, "forward": 2, "frame": 2, "free": 2, "from": 2, "full": 1, "gabaerg": 2, "gene": [1, 2], "get_titl": 2, "glutamaterg": 2, "go": 2, "googleapi": 1, "gpu": 2, "gran_sst_palett": 2, "graph": 2, "gravit": 2, "graviti": 2, "green": 2, "groupbi": 2, "h5ad": 2, "highly_vari": 2, "highly_variable_gen": 2, "hpse": 2, "hs6st2": 2, "hspe": 2, "html": 1, "http": [1, 2], "hue": 2, "i": 1, "ighm": 2, "ignor": 2, "implement": 1, "import": 1, "imput": 1, "impute_gen": [1, 2], "ind": 2, "index": 2, "indptr": 2, "infer": 1, "infer_niche_celltyp": [1, 2], "infer_niche_covet": [1, 2], "init_coord": 2, "initi": 2, "inlin": 2, "inplac": 2, "input": 2, "instal": 1, "int": 2, "integr": [1, 2], "intial": 2, "io": 1, "isspars": 2, "iter": 2, "jax": 1, "jax_cuda_releas": 1, "jittertoler": 2, "just": 1, "k": 2, "kernel": 2, "kind": 2, "kl": 2, "kneighbors_graph": 2, "knn": 2, "l2": 2, "l23_it": 2, "l45_it": 2, "l56_np": 2, "l5_et": 2, "l5_it": 2, "l5_pt": 2, "l6_ct": 2, "l6_it": 2, "l6_it_car3": 2, "l6b": 2, "l_alpha": 2, "lab": 2, "label": 2, "lamp5": 2, "latent_umap": 2, "layer": 2, "layout": 2, "learn": 1, "learnin": 1, "left": 2, "legend": 2, "len": 2, "lim_arr": 2, "linalg": 2, "linlogmod": 2, "load": 2, "loc": 2, "log": 2, "lower": 2, "lt": 2, "mai": 2, "map": 2, "marker": 2, "markerscal": 2, "markov": 2, "mat": 2, "matplotlib": 2, "matric": 2, "matrix": 2, "max": 2, "maxit": 2, "mean": 2, "method": [1, 2], "metric": 2, "microglia": 2, "min_dist": 2, "miss": 2, "mode": 2, "model": 2, "mouse1_slice10": 2, "mouse1_slice162": 2, "mouse1_slice212": 2, "mouse1_slice40": 2, "mouse1_slice71": 2, "mouse2_slice270": 2, "multithread": 2, "myh8": 2, "n": 2, "n_compon": 2, "n_job": 2, "n_neighbor": 2, "n_pc": 2, "n_top_gen": 2, "name": 2, "nbr": 2, "ncol": 2, "nearest": 2, "nearestneighbor": 2, "neighbor": 2, "neuron": 2, "non": 2, "none": 2, "norm": 2, "normal": 2, "note": 2, "np": 2, "number": 2, "numpi": 2, "nvidia": 2, "nvptx_compil": 2, "o": 2, "ob": 2, "object": 2, "obsm": [1, 2], "obsp": 2, "off": 2, "older": 2, "oligo": 2, "onto": 1, "opc": 2, "oper": 2, "order": 2, "our": 1, "outboundattractiondistribut": 2, "own": 2, "packag": 2, "pair": 2, "palett": 2, "pamr1": 2, "panda": 2, "parallel": 2, "param": 2, "paramet": 2, "pca": 2, "pci_bus_id": 2, "pd": 2, "pe": 2, "percentil": 2, "perform": 2, "pericyt": 2, "phenograph": 2, "pip": [1, 2], "pleas": 1, "plt": 2, "po": 2, "posit": 2, "pp": 2, "pre": 2, "predict": 2, "prefer": 2, "print": 2, "produc": 2, "project": 2, "prop": 2, "proport": 2, "provid": 2, "pseudo": 2, "ptxa": 2, "public": 2, "pvalb": 2, "pyplot": 2, "python3": 1, "quantifi": 2, "random": 2, "rang": 2, "ravel": 2, "re": 2, "read": [1, 2], "read_h5ad": 2, "readthedoc": 1, "real": 2, "reconstruct": 1, "red": 2, "releas": 1, "reli": [1, 2], "repres": 2, "represent": 2, "repuls": 2, "requir": 1, "reshap": 2, "rest": 1, "result": 2, "return": 2, "run": 1, "run_diffusion_map": 2, "s3": 2, "sc": 2, "sc_data": [1, 2], "sc_data_sst": 2, "scalingratio": 2, "scanpi": [1, 2], "scatterplot": 2, "scenvi": [1, 2], "scipi": [1, 2], "scrna": [1, 2], "scrna_seq": 2, "seaborn": 2, "second": 2, "see": [1, 2], "seq": [1, 2], "seri": 2, "servic": 2, "set": 2, "set_styl": 2, "setp": 2, "shallow": 2, "shape": 2, "should": 2, "show": 2, "simpli": [1, 2], "size": 2, "sklearn": [1, 2], "slit1": 2, "slow": 2, "small": 2, "smc": 2, "sn": 2, "sncg": 2, "so": 2, "some": 2, "sort": 2, "sort_valu": 2, "spars": 2, "spatial": 1, "spatial_data": [1, 2], "specif": 2, "sqrt": 2, "sst": 2, "st_data": [1, 2], "st_data_sst": 2, "st_databatch": 2, "st_dataplotbatch": 2, "std": 2, "step": 2, "storag": 1, "stronggravitymod": 2, "subplot": 2, "subtype_canon": 2, "subtype_depth_ord": 2, "sum": 2, "switch": 2, "t": 2, "take": 2, "temp": 2, "th": 2, "than": 2, "thi": [1, 2], "tick_gen": 2, "tight_layout": 2, "titl": 2, "todens": 2, "tol": 2, "took": 2, "train": [1, 2], "transcriptom": 1, "true": 2, "tune": 2, "tutori": 1, "u": 1, "umap_": 2, "umap_exp": 2, "un": [1, 2], "unimagd": 1, "updat": 2, "us": 2, "v": 2, "vae": 2, "valu": 2, "var": 2, "variat": 1, "verbos": 2, "version": 2, "vip": 2, "vlmc": 2, "vmax": 2, "vmin": 2, "w": 2, "want": 2, "warn": 2, "we": 2, "wget": 2, "which": 2, "whitegrid": 2, "width": 2, "written": 1, "x": 2, "xla": 2, "xlabel": 2, "xlim": 2, "xmax": 2, "xmin": 2, "y": 2, "ylabel": 2, "ylim": 2, "ymax": 2, "ymin": 2, "you": 2, "your": 2, "zero": 2, "zoom": 2}, "titles": ["ENVI", "ENVI & COVET", "ENVI Tutorial", "Utilities"], "titleterms": {"analysi": 2, "bar": 2, "calcul": 2, "cell": 2, "composit": 2, "cortex": 2, "covet": [1, 2], "data": 2, "dc": 2, "depth": 2, "envi": [0, 1, 2], "fdl": 2, "function": 2, "i": 2, "import": 2, "imput": 2, "index": 1, "instal": 2, "latent": 2, "merfish": 2, "motor": 2, "need": 2, "nich": 2, "plot": 2, "revers": 2, "run": 2, "scrnaseq": 2, "spatial": 2, "stack": 2, "subtyp": 2, "tutori": 2, "type": 2, "umap": 2, "util": [2, 3], "what": 2}})
--------------------------------------------------------------------------------
/docs/build/html/utils.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Utilities - scenvi 0.3.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 | Contents
48 |
49 |
50 |
51 |
52 |
61 |
62 | Expand
63 |
65 |
66 |
67 |
68 |
69 | Light mode
70 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | Dark mode
85 |
87 |
88 |
89 |
90 |
91 |
92 | Auto light/dark mode
93 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
111 |
112 | Hide table of contents sidebar
113 |
114 |
115 |
116 |
117 |
118 |
143 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 | Back to top
182 |
183 |
184 |
185 |
186 |
187 | Toggle Light / Dark / Auto color theme
188 |
189 |
190 |
191 |
192 |
193 |
194 | Toggle table of contents sidebar
195 |
196 |
197 |
198 |
199 |
202 |
203 |
204 |
205 |
206 |
207 |
221 |
222 |
223 |
224 | Copyright © 2024, Doron Haviv
225 |
226 | Made with
Sphinx and
@pradyunsg 's
227 |
228 |
Furo
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
--------------------------------------------------------------------------------
/docs/docs_requirements.txt:
--------------------------------------------------------------------------------
1 | sphinxcontrib-autoprogram
2 | sphinxcontrib-napoleon
3 | sphinx-autodocgen
4 | sphinx-github-style
5 | sphinx-mdinclude
6 | m2r2
7 | nbsphinx
8 | furo
9 | typing-extensions
10 | IPython
11 | pandoc
12 | tomli
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | %SPHINXBUILD% >NUL 2>NUL
14 | if errorlevel 9009 (
15 | echo.
16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
17 | echo.installed, then set the SPHINXBUILD environment variable to point
18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
19 | echo.may add the Sphinx directory to PATH.
20 | echo.
21 | echo.If you don't have Sphinx installed, grab it from
22 | echo.https://www.sphinx-doc.org/
23 | exit /b 1
24 | )
25 |
26 | if "%1" == "" goto help
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/source/ENVI.rst:
--------------------------------------------------------------------------------
1 | ENVI
2 | =========
3 |
4 | .. automodule:: scenvi.ENVI
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # For the full list of built-in configuration values, see the documentation:
4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
5 |
6 | # -- Project information -----------------------------------------------------
7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
8 |
9 | # Configuration file for the Sphinx documentation builder.
10 | #
11 | # This file only contains a selection of the most common options. For a full
12 | # list see the documentation:
13 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
14 |
15 | # -- Path setup --------------------------------------------------------------
16 |
17 | # If extensions (or modules to document with autodoc) are in another directory,
18 | # add these directories to sys.path here. If the directory is relative to the
19 | # documentation root, use os.path.abspath to make it absolute, like shown here.
20 | #
21 | import os
22 | import sys
23 | from pathlib import Path
24 | import datetime
25 | import tomli
26 |
27 | sys.path.insert(0, os.path.abspath("../../src"))
28 |
29 | this_directory = Path(__file__).parent
30 |
31 | # Get current year for copyright
32 | current_year = datetime.datetime.now().year
33 |
34 | # Get package version from pyproject.toml
35 | try:
36 | pyproject_path = Path(__file__).parents[2] / "pyproject.toml"
37 | if pyproject_path.exists():
38 | with open(pyproject_path, "rb") as f:
39 | pyproject_data = tomli.load(f)
40 | package_version = pyproject_data.get("tool", {}).get("poetry", {}).get("version", "0.1.0")
41 | else:
42 | package_version = "0.1.0"
43 | except Exception as e:
44 | print(f"Warning: Could not read version from pyproject.toml: {e}")
45 | package_version = "0.1.0"
46 |
47 | # -- Project information -----------------------------------------------------
48 |
49 | project = "scenvi"
50 | copyright = f"{current_year}, Doron Haviv"
51 | author = 'Doron Haviv'
52 |
53 | # The full version, including alpha/beta/rc tags
54 | release = package_version
55 |
56 |
57 | # -- General configuration ---------------------------------------------------
58 |
59 | # Add any Sphinx extension module names here, as strings. They can be
60 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
61 | # ones.
62 | extensions = [
63 | "sphinx.ext.autodoc",
64 | "nbsphinx",
65 | "sphinx.ext.napoleon",
66 | "sphinx_mdinclude",
67 | ]
68 | if os.environ.get('READTHEDOCS') == 'True':
69 | extensions.append("sphinx_github_style")
70 |
71 | source_suffix = [".rst", ".md"]
72 |
73 | # Add any paths that contain templates here, relative to this directory.
74 | templates_path = ["_templates"]
75 |
76 | # List of patterns, relative to source directory, that match files and
77 | # directories to ignore when looking for source files.
78 | # This pattern also affects html_static_path and html_extra_path.
79 | exclude_patterns = ["_build", "**.ipynb_checkpoints"]
80 |
81 | # GitHub repository info
82 | github_user = "dpeerlabs" # Replace with your actual GitHub username
83 | github_repo = "scenvi" # Replace with your actual repository name
84 | github_version = "main" # Or your default branch
85 |
86 | # For sphinx-github-style extension when on ReadTheDocs
87 | if os.environ.get('READTHEDOCS') == 'True':
88 | linkcode_url = f"https://github.com/{github_user}/{github_repo}/blob/{github_version}"
89 |
90 | # -- Options for HTML output -------------------------------------------------
91 |
92 | # The theme to use for HTML and HTML Help pages. See the documentation for
93 | # a list of builtin themes.
94 | #
95 | html_theme = "furo"
96 | pygments_style = "tango"
97 |
98 | highlight_language = "none"
99 |
100 | # Add any paths that contain custom static files (such as style sheets) here,
101 | # relative to this directory. They are copied after the builtin static files,
102 | # so a file named "default.css" will overwrite the builtin "default.css".
103 | html_static_path = []
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. scenvi documentation master file, created by
2 | sphinx-quickstart on Wed Apr 24 12:13:12 2024.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | .. toctree::
7 | :hidden:
8 | :caption: Tutorials:
9 |
10 | tutorial/MOp_MERFISH_tutorial
11 |
12 | .. toctree::
13 | :hidden:
14 | :caption: Modules:
15 |
16 | ENVI
17 | Utilities
18 |
19 |
20 | .. mdinclude:: ../../README.md
21 |
22 | Index
23 | =====
24 |
25 | * :ref:`genindex`
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/docs/source/utils.rst:
--------------------------------------------------------------------------------
1 | Utilities
2 | =========
3 |
4 | .. automodule:: scenvi.utils
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "scenvi"
3 | version = "0.4.5"
4 | description = "Integration of scRNA-seq and spatial transcpriptomics data"
5 | authors = ["Doron Haviv"]
6 | license = "MIT"
7 | readme = "README.md"
8 |
9 | [tool.poetry.dependencies]
10 | scanpy = "^1.11.0"
11 | python = "^3.9"
12 | flax = "^0.10.4"
13 | optax = "^0.2.4"
14 | tensorflow_probability = "^0.22.0"
15 | clu = "^0.0.11"
16 | tqdm = "^4.66.1"
17 |
18 | [build-system]
19 | requires = ["poetry-core"]
20 | build-backend = "poetry.core.masonry.api"
21 |
--------------------------------------------------------------------------------
/readthedocs.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | build:
4 | os: ubuntu-20.04
5 | tools:
6 | python: "3.11"
7 |
8 | sphinx:
9 | configuration: docs/source/conf.py
10 |
11 | python:
12 | install:
13 | - requirements: docs/docs_requirements.txt
14 | - method: pip
15 | path: .
--------------------------------------------------------------------------------
/scenvi/__init__.py:
--------------------------------------------------------------------------------
1 | from scenvi.ENVI import ENVI # noqa: F401
2 | from scenvi.utils import compute_covet # noqa: F401
3 |
--------------------------------------------------------------------------------
/scenvi/__pycache__/ENVI.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/scenvi/__pycache__/ENVI.cpython-39.pyc
--------------------------------------------------------------------------------
/scenvi/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/scenvi/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/scenvi/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/scenvi/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/scenvi/__pycache__/dists.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/scenvi/__pycache__/dists.cpython-39.pyc
--------------------------------------------------------------------------------
/scenvi/__pycache__/utils.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dpeerlab/ENVI/b433de227c7d90bb5ef355bd9cb961f4b1a422dc/scenvi/__pycache__/utils.cpython-39.pyc
--------------------------------------------------------------------------------
/scenvi/_dists.py:
--------------------------------------------------------------------------------
1 | import jax.numpy as jnp
2 | import tensorflow_probability.substrates.jax.distributions as jnd
3 |
4 |
5 | def KL(mean, log_std):
6 | """
7 | :meta private:
8 | """
9 | KL = 0.5 * (jnp.square(mean) + jnp.square(jnp.exp(log_std)) - 2 * log_std)
10 | return jnp.mean(KL, axis=-1)
11 |
12 |
13 | def log_pos_pdf(sample, l): # noqa: E741
14 | """
15 | :meta private:
16 | """
17 |
18 | log_prob = jnd.Poisson(rate=l).log_prob(sample)
19 | return jnp.mean(log_prob, axis=-1)
20 |
21 |
22 | def log_nb_pdf(sample, r, p):
23 | """
24 | :meta private:
25 | """
26 |
27 | log_prob = jnd.NegativeBinomial(total_count=r, logits=p).log_prob(sample)
28 | return jnp.mean(log_prob, axis=-1)
29 |
30 |
31 | def log_zinb_pdf(sample, r, p, d):
32 | """
33 | :meta private:
34 | """
35 |
36 | log_prob = jnd.Inflated(
37 | jnd.NegativeBinomial(total_count=r, logits=p), inflated_loc_logits=d
38 | ).log_prob(sample)
39 | return jnp.mean(log_prob, axis=-1)
40 |
41 |
42 | def log_normal_pdf(sample, mean):
43 | """
44 | :meta private:
45 | """
46 |
47 | log_prob = jnd.Normal(loc=mean, scale=1).log_prob(sample)
48 | return jnp.mean(log_prob, axis=-1)
49 |
50 |
51 | def AOT_Distance(sample, mean):
52 | """
53 | :meta private:
54 | """
55 |
56 | sample = jnp.reshape(sample, [sample.shape[0], -1])
57 | mean = jnp.reshape(mean, [mean.shape[0], -1])
58 | log_prob = -jnp.square(sample - mean)
59 | return jnp.mean(log_prob, axis=-1)
60 |
--------------------------------------------------------------------------------
/scenvi/utils.py:
--------------------------------------------------------------------------------
1 | import jax
2 | import jax.numpy as jnp
3 | import numpy as np
4 | import pandas as pd
5 | import scanpy as sc
6 | import sklearn.neighbors
7 | from clu import metrics
8 | from flax import linen as nn
9 | from flax import struct
10 | from flax.training import train_state
11 | from jax import random
12 |
13 | from sklearn.preprocessing import OneHotEncoder
14 | from tqdm import tqdm
15 | import scipy.sparse
16 |
17 | class FeedForward(nn.Module):
18 | """
19 | :meta private:
20 | """
21 |
22 | n_layers: int
23 | n_neurons: int
24 | n_output: int
25 |
26 | @nn.compact
27 | def __call__(self, x):
28 | """
29 | :meta private:
30 | """
31 |
32 | n_layers = self.n_layers
33 | n_neurons = self.n_neurons
34 | n_output = self.n_output
35 |
36 | x = nn.Dense(
37 | features=n_neurons,
38 | dtype=jnp.float32,
39 | kernel_init=nn.initializers.glorot_uniform(),
40 | bias_init=nn.initializers.zeros_init(),
41 | )(x)
42 | x = nn.leaky_relu(x)
43 | x = nn.LayerNorm(dtype=jnp.float32)(x)
44 |
45 | for _ in range(n_layers - 1):
46 |
47 | x = nn.Dense(
48 | features=n_neurons,
49 | dtype=jnp.float32,
50 | kernel_init=nn.initializers.glorot_uniform(),
51 | bias_init=nn.initializers.zeros_init(),
52 | )(x)
53 | x = nn.leaky_relu(x) + x
54 | x = nn.LayerNorm(dtype=jnp.float32)(x)
55 |
56 | output = nn.Dense(
57 | features=n_output,
58 | dtype=jnp.float32,
59 | kernel_init=nn.initializers.glorot_uniform(),
60 | bias_init=nn.initializers.zeros_init(),
61 | )(x)
62 |
63 | return output
64 |
65 |
66 | class CVAE(nn.Module):
67 | """
68 | :meta private:
69 | """
70 |
71 | n_layers: int
72 | n_neurons: int
73 | n_latent: int
74 | n_output_exp: int
75 | n_output_cov: int
76 |
77 | def setup(self):
78 | """
79 | :meta private:
80 | """
81 |
82 | n_layers = self.n_layers
83 | n_neurons = self.n_neurons
84 | n_latent = self.n_latent
85 | n_output_exp = self.n_output_exp
86 | n_output_cov = self.n_output_cov
87 |
88 | self.encoder = FeedForward(
89 | n_layers=n_layers, n_neurons=n_neurons, n_output=n_latent * 2
90 | )
91 |
92 | self.decoder_exp = FeedForward(
93 | n_layers=n_layers, n_neurons=n_neurons, n_output=n_output_exp
94 | )
95 |
96 | self.decoder_cov = FeedForward(
97 | n_layers=n_layers, n_neurons=n_neurons, n_output=n_output_cov
98 | )
99 |
100 | def __call__(self, x, mode="spatial", key=random.key(0)):
101 | """
102 | :meta private:
103 | """
104 |
105 | conf_const = 0 if mode == "spatial" else 1
106 | conf_neurons = jax.nn.one_hot(
107 | conf_const * jnp.ones(x.shape[0], dtype=jnp.int8), 2, dtype=jnp.float32
108 | )
109 |
110 | x_conf = jnp.concatenate([x, conf_neurons], axis=-1)
111 | enc_mu, enc_logstd = jnp.split(self.encoder(x_conf), 2, axis=-1)
112 |
113 | key, subkey = random.split(key)
114 | z = enc_mu + random.normal(key=subkey, shape=enc_logstd.shape) * jnp.exp(
115 | enc_logstd
116 | )
117 | z_conf = jnp.concatenate([z, conf_neurons], axis=-1)
118 |
119 | dec_exp = self.decoder_exp(z_conf)
120 |
121 | if mode == "spatial":
122 | dec_cov = self.decoder_cov(z)
123 | return (enc_mu, enc_logstd, dec_exp, dec_cov)
124 | return (enc_mu, enc_logstd, dec_exp)
125 |
126 |
127 | @struct.dataclass
128 | class Metrics(metrics.Collection):
129 | """
130 | :meta private:
131 | """
132 |
133 | enc_loss: metrics.Average
134 | dec_loss: metrics.Average
135 | enc_corr: metrics.Average
136 |
137 |
138 | class TrainState(train_state.TrainState):
139 | """
140 | :meta private:
141 | """
142 |
143 | metrics: Metrics
144 |
145 | def batch_matrix_sqrt(Mats):
146 | """
147 | :meta private:
148 | """
149 |
150 | e, v = np.linalg.eigh(Mats)
151 | e = np.where(e < 0, 0, e)
152 | e = np.sqrt(e)
153 |
154 | m, n = e.shape
155 | diag_e = np.zeros((m, n, n), dtype=e.dtype)
156 | diag_e.reshape(-1, n**2)[..., :: n + 1] = e
157 | return np.matmul(np.matmul(v, diag_e), v.transpose([0, 2, 1]))
158 |
159 |
160 | def batch_knn(data, batch, k):
161 | """
162 | :meta private:
163 | """
164 |
165 | kNNGraphIndex = np.zeros(shape=(data.shape[0], k))
166 |
167 | for val in np.unique(batch):
168 | val_ind = np.where(batch == val)[0]
169 |
170 | batch_knn = sklearn.neighbors.kneighbors_graph(
171 | data[val_ind], n_neighbors=k, mode="connectivity", n_jobs=-1
172 | ).tocoo()
173 | batch_knn_ind = np.reshape(
174 | np.asarray(batch_knn.col), [data[val_ind].shape[0], k]
175 | )
176 | kNNGraphIndex[val_ind] = val_ind[batch_knn_ind]
177 |
178 | return kNNGraphIndex.astype("int")
179 |
180 |
181 | def calculate_covariance_matrices(spatial_data, kNN, exp_data, spatial_key="spatial", batch_key=-1, batch_size=None):
182 | """
183 | Calculate covariance matrices for each cell/spot in spatial data using provided expression data
184 |
185 | :param spatial_data: AnnData object with spatial coordinates
186 | :param kNN: Number of nearest neighbors
187 | :param exp_data: Pre-processed expression data to use for covariance calculation
188 | :param spatial_key: Key for spatial coordinates in obsm
189 | :param batch_key: Key for batch information in obs, or -1 for no batch
190 | :param batch_size: Number of cells to process at once (for memory efficiency)
191 |
192 | :return: 3D array of covariance matrices
193 | """
194 |
195 | # Get the KNN graph
196 | if batch_key == -1:
197 | kNNGraph = sklearn.neighbors.kneighbors_graph(
198 | spatial_data.obsm[spatial_key],
199 | n_neighbors=kNN,
200 | mode="connectivity",
201 | n_jobs=-1,
202 | ).tocoo()
203 | kNNGraphIndex = np.reshape(
204 | np.asarray(kNNGraph.col), [spatial_data.obsm[spatial_key].shape[0], kNN]
205 | )
206 | else:
207 | kNNGraphIndex = batch_knn(
208 | spatial_data.obsm[spatial_key], spatial_data.obs[batch_key], kNN
209 | )
210 |
211 | # Get the global mean for each feature
212 | global_mean = exp_data.mean(axis=0)
213 |
214 | # Initialize the output covariance matrices
215 | n_cells = exp_data.shape[0]
216 | n_features = exp_data.shape[1]
217 | CovMats = np.zeros((n_cells, n_features, n_features), dtype=np.float32)
218 |
219 | # Process in batches if requested
220 | if batch_size is None or batch_size >= n_cells:
221 | # Process all cells at once
222 | print("Calculating covariance matrices for all cells/spots")
223 | DistanceMatWeighted = (
224 | global_mean[None, None, :]
225 | - exp_data[kNNGraphIndex[np.arange(n_cells)]]
226 | )
227 |
228 | CovMats = np.matmul(
229 | DistanceMatWeighted.transpose([0, 2, 1]), DistanceMatWeighted
230 | ) / (kNN - 1)
231 | else:
232 | # Process in batches to save memory
233 | batch_indices = np.array_split(np.arange(n_cells), np.ceil(n_cells / batch_size))
234 |
235 | for batch_idx in tqdm(batch_indices, desc="Calculating covariance matrices"):
236 | # Get neighbor indices for this batch
237 | batch_neighbors = kNNGraphIndex[batch_idx]
238 |
239 | # Calculate the distance matrices for this batch
240 | batch_distances = (
241 | global_mean[None, None, :]
242 | - exp_data[batch_neighbors]
243 | )
244 |
245 | # Calculate the covariance matrices for this batch
246 | batch_covs = np.matmul(
247 | batch_distances.transpose([0, 2, 1]), batch_distances
248 | ) / (kNN - 1)
249 |
250 | # Store the results
251 | CovMats[batch_idx] = batch_covs
252 |
253 | # Add a small regularization term to ensure positive definiteness
254 | reg_term = CovMats.mean() * 0.00001
255 | identity = np.eye(n_features)[None, :, :]
256 | CovMats = CovMats + reg_term * identity
257 |
258 | return CovMats
259 |
260 | def niche_cell_type(
261 | spatial_data, kNN, spatial_key="spatial", cell_type_key="cell_type", batch_key=-1
262 | ):
263 | """
264 | :meta private:
265 | """
266 |
267 |
268 |
269 | if batch_key == -1:
270 | kNNGraph = sklearn.neighbors.kneighbors_graph(
271 | spatial_data.obsm[spatial_key],
272 | n_neighbors=kNN,
273 | mode="connectivity",
274 | n_jobs=-1,
275 | ).tocoo()
276 | knn_index = np.reshape(
277 | np.asarray(kNNGraph.col), [spatial_data.obsm[spatial_key].shape[0], kNN]
278 | )
279 | else:
280 | knn_index = batch_knn(
281 | spatial_data.obsm[spatial_key], spatial_data.obs[batch_key], kNN
282 | )
283 |
284 | one_hot_enc = OneHotEncoder().fit(
285 | np.asarray(list(set(spatial_data.obs[cell_type_key]))).reshape([-1, 1])
286 | )
287 | cell_type_one_hot = (
288 | one_hot_enc.transform(
289 | np.asarray(spatial_data.obs[cell_type_key]).reshape([-1, 1])
290 | )
291 | .reshape([spatial_data.obs["cell_type"].shape[0], -1])
292 | .todense()
293 | )
294 |
295 | cell_type_niche = pd.DataFrame(
296 | cell_type_one_hot[knn_index].sum(axis=1),
297 | index=spatial_data.obs_names,
298 | columns=list(one_hot_enc.categories_[0]),
299 | )
300 | return cell_type_niche
301 |
302 | def compute_covet(
303 | spatial_data, k=8, g=64, genes=None, spatial_key="spatial", batch_key="batch",
304 | batch_size=None, use_obsm=None, use_layer=None
305 | ):
306 | """
307 | Compute niche covariance matrices for spatial data, run with scenvi.compute_covet
308 |
309 | :param spatial_data: (anndata) spatial data, with an obsm indicating spatial location of spot/segmented cell
310 | :param k: (int) number of nearest neighbours to define niche (default 8)
311 | :param g: (int) number of HVG to compute COVET representation on (default 64)
312 | :param genes: (list of str) list of genes to keep for niche covariance (default [])
313 | :param spatial_key: (str) obsm key name with physical location of spots/cells (default 'spatial')
314 | :param batch_key: (str) obs key name of batch/sample of spatial data (default 'batch' if in spatial_data.obs, else -1)
315 | :param batch_size: (int) Number of cells/spots to process at once for large datasets (default None)
316 | :param use_obsm: (str) obsm key to use for COVET calculation instead of gene expression (e.g. 'X_pca', 'X_dc') (default None)
317 | :param use_layer: (str) layer to use for COVET calculation instead of log-transformed X (e.g. 'log', 'log1p') (default None)
318 |
319 | :return COVET: niche covariance matrices
320 | :return COVET_SQRT: matrix square-root of niche covariance matrices for approximate OT
321 | :return CovGenes: list of genes selected for COVET representation (or feature names if using obsm)
322 | """
323 |
324 | genes = [] if genes is None else genes
325 |
326 | # Handle batch key
327 | if batch_key not in spatial_data.obs.columns:
328 | batch_key = -1
329 |
330 | # Determine data source: obsm, layer, or X
331 | if use_obsm is not None:
332 | if use_obsm not in spatial_data.obsm:
333 | raise ValueError(f"obsm key '{use_obsm}' not found in spatial_data.obsm")
334 |
335 | # Use the specified obsm embedding
336 | print(f"Computing COVET using obsm '{use_obsm}' with {spatial_data.obsm[use_obsm].shape[1]} dimensions")
337 | CovGenes = [f"{use_obsm}_{i}" for i in range(spatial_data.obsm[use_obsm].shape[1])]
338 | exp_data = spatial_data.obsm[use_obsm]
339 |
340 | else:
341 | # Select genes for covariance calculation
342 | if g == -1 or g >= spatial_data.shape[1]:
343 | # Use all genes
344 | CovGenes = spatial_data.var_names
345 | print(f"Computing COVET using all {len(CovGenes)} genes")
346 | else:
347 | # Check if highly variable genes need to be calculated
348 | if "highly_variable" not in spatial_data.var.columns:
349 | print(f"Identifying top {g} highly variable genes for COVET calculation")
350 | # Create a copy to avoid modifying the input
351 | spatial_data_copy = spatial_data.copy()
352 |
353 | # Determine appropriate layer for HVG calculation
354 | if use_layer is None:
355 | if 'log' in spatial_data_copy.layers:
356 | layer = "log"
357 | elif 'log1p' in spatial_data_copy.layers:
358 | layer = "log1p"
359 | elif spatial_data_copy.X.min() < 0:
360 | # Data is already log-transformed
361 | layer = None
362 | else:
363 | # Create log layer
364 | spatial_data_copy.layers["log"] = np.log(spatial_data_copy.X + 1)
365 | layer = "log"
366 | else:
367 | layer = use_layer
368 |
369 | # Calculate HVGs
370 | sc.pp.highly_variable_genes(
371 | spatial_data_copy,
372 | n_top_genes=g,
373 | layer=layer if layer else None
374 | )
375 | # Get HVG names
376 | hvg_genes = spatial_data_copy.var_names[spatial_data_copy.var.highly_variable]
377 | if(len(hvg_genes) > g):
378 | print(f"Found {len(hvg_genes)} HVGs")
379 | else:
380 | # HVGs already calculated
381 | hvg_genes = spatial_data.var_names[spatial_data.var.highly_variable]
382 | print(f"Using {len(hvg_genes)} pre-calculated highly variable genes for COVET")
383 |
384 | # Combine HVGs with manually specified genes
385 | CovGenes = np.asarray(hvg_genes)
386 | if len(genes) > 0:
387 | CovGenes = np.union1d(CovGenes, genes)
388 | print(f"Added {len(genes)} user-specified genes to COVET calculation")
389 |
390 | print(f"Computing COVET using {len(CovGenes)} genes")
391 |
392 | # Get expression data based on selected genes and specified layer
393 | if use_layer is not None:
394 | if use_layer not in spatial_data.layers:
395 | raise ValueError(f"Layer '{use_layer}' not found in spatial_data.layers")
396 | print(f"Using expression data from layer '{use_layer}'")
397 | exp_data = spatial_data[:, CovGenes].layers[use_layer].toarray() if scipy.sparse.issparse(spatial_data.layers[use_layer]) else spatial_data[:, CovGenes].layers[use_layer]
398 | else:
399 | # Default: log-transform X if needed
400 | if spatial_data.X.min() < 0:
401 | # Data is already log-transformed
402 | print("Using expression data from X (appears to be log-transformed)")
403 | exp_data = spatial_data[:, CovGenes].X.toarray() if scipy.sparse.issparse(spatial_data.X) else spatial_data[:, CovGenes].X
404 | else:
405 | print("Log-transforming expression data from X")
406 | exp_data = np.log(spatial_data[:, CovGenes].X.toarray() + 1) if scipy.sparse.issparse(spatial_data.X) else np.log(spatial_data[:, CovGenes].X + 1)
407 |
408 | # Calculate covariance matrices with batch processing
409 | COVET = calculate_covariance_matrices(
410 | spatial_data, k, exp_data, spatial_key=spatial_key,
411 | batch_key=batch_key, batch_size=batch_size
412 | )
413 |
414 | # Calculate matrix square root
415 | if batch_size is None or batch_size >= COVET.shape[0]:
416 | print("Computing matrix square root...")
417 | COVET_SQRT = batch_matrix_sqrt(COVET)
418 | else:
419 | # Process matrix square root in batches too
420 | n_cells = COVET.shape[0]
421 | COVET_SQRT = np.zeros_like(COVET)
422 |
423 | # Split into batches
424 | batch_indices = np.array_split(np.arange(n_cells), np.ceil(n_cells / batch_size))
425 |
426 | for batch_idx in tqdm(batch_indices, desc="Computing matrix square roots"):
427 | # Process this batch of matrices
428 | batch_sqrt = batch_matrix_sqrt(COVET[batch_idx])
429 | COVET_SQRT[batch_idx] = batch_sqrt
430 |
431 | # Return results with proper types
432 | return (
433 | COVET.astype("float32"),
434 | COVET_SQRT.astype("float32"),
435 | np.asarray(CovGenes, dtype=str),
436 | )
--------------------------------------------------------------------------------
/tests/test_ENVI.py:
--------------------------------------------------------------------------------
1 | import pytest # type: ignore
2 |
3 | import anndata
4 | import numpy as np
5 |
6 | import scenvi
7 |
8 | @pytest.fixture
9 | def example_model():
10 | st_data = anndata.AnnData(X=np.random.uniform(low=0, high=100, size=(16, 4)),
11 | obsm={'spatial': np.random.normal(size=[16, 2])})
12 | sc_data = anndata.AnnData(X=np.random.uniform(low=0, high=100, size=(16, 8)))
13 |
14 | envi_model = scenvi.ENVI(spatial_data=st_data, sc_data=sc_data, batch_key=-1)
15 | return envi_model
16 |
17 | @pytest.fixture
18 | def example_model_with_hvg():
19 | # Create data with pre-computed HVGs
20 | st_data = anndata.AnnData(X=np.random.uniform(low=0, high=100, size=(16, 4)),
21 | obsm={'spatial': np.random.normal(size=[16, 2])})
22 | sc_data = anndata.AnnData(X=np.random.uniform(low=0, high=100, size=(16, 8)))
23 |
24 | # Add highly_variable column
25 | sc_data.var['highly_variable'] = [True, False, True, False, True, False, True, False]
26 |
27 | envi_model = scenvi.ENVI(spatial_data=st_data, sc_data=sc_data, batch_key=-1)
28 | return envi_model
29 |
30 | @pytest.fixture
31 | def example_model_with_user_genes():
32 | st_data = anndata.AnnData(X=np.random.uniform(low=0, high=100, size=(16, 4)),
33 | obsm={'spatial': np.random.normal(size=[16, 2])})
34 | st_data.var_names = [f"gene{i}" for i in range(4)]
35 |
36 | sc_data = anndata.AnnData(X=np.random.uniform(low=0, high=100, size=(16, 8)))
37 | sc_data.var_names = [f"gene{i}" for i in range(8)]
38 |
39 | # Specify user genes to include
40 | user_genes = ["gene1", "gene3", "gene5"]
41 |
42 | envi_model = scenvi.ENVI(spatial_data=st_data, sc_data=sc_data, batch_key=-1, sc_genes=user_genes)
43 | return envi_model
44 |
45 | @pytest.fixture
46 | def large_example_model():
47 | # Create larger dataset to test batch processing
48 | st_data = anndata.AnnData(X=np.random.uniform(low=0, high=100, size=(100, 32)),
49 | obsm={'spatial': np.random.normal(size=[100, 2])})
50 | sc_data = anndata.AnnData(X=np.random.uniform(low=0, high=100, size=(100, 64)))
51 |
52 | envi_model = scenvi.ENVI(spatial_data=st_data, sc_data=sc_data, batch_key=-1, num_cov_genes = 16)
53 | return envi_model
54 |
55 | def test_train(example_model):
56 | example_model.train(training_steps=1)
57 |
58 | assert 'COVET' in example_model.spatial_data.obsm
59 | assert 'COVET_SQRT' in example_model.spatial_data.obsm
60 |
61 | assert 'envi_latent' in example_model.spatial_data.obsm
62 | assert example_model.spatial_data.obsm['envi_latent'].shape == (example_model.spatial_data.shape[0], example_model.latent_dim)
63 |
64 | assert 'envi_latent' in example_model.sc_data.obsm
65 | assert example_model.sc_data.obsm['envi_latent'].shape == (example_model.sc_data.shape[0], example_model.latent_dim)
66 |
67 | def test_impute(example_model):
68 | example_model.train(training_steps=1)
69 | example_model.impute_genes()
70 |
71 | assert 'imputation' in example_model.spatial_data.obsm
72 |
73 | def test_infer_niche(example_model):
74 | example_model.train(training_steps=1)
75 | example_model.infer_niche_covet()
76 |
77 | assert 'COVET_SQRT' in example_model.sc_data.obsm
78 | assert 'COVET' in example_model.sc_data.obsm
79 |
80 | def test_precomputed_hvg(example_model_with_hvg):
81 | """Test that pre-computed highly variable genes are correctly used"""
82 | # Check that the HVGs from input were maintained
83 | hvg_count = sum(example_model_with_hvg.sc_data.var['highly_variable'])
84 | assert hvg_count > 0
85 |
86 | # Train and verify
87 | example_model_with_hvg.train(training_steps=1)
88 | assert 'envi_latent' in example_model_with_hvg.spatial_data.obsm
89 | assert 'envi_latent' in example_model_with_hvg.sc_data.obsm
90 |
91 | def test_user_specified_genes(example_model_with_user_genes):
92 | """Test that user-specified genes are correctly included"""
93 | # Check that user-specified genes are included
94 | for gene in ["gene1", "gene3", "gene5"]:
95 | if gene in example_model_with_user_genes.sc_data.var_names:
96 | assert gene in example_model_with_user_genes.sc_data.var_names
97 |
98 | # Train and verify
99 | example_model_with_user_genes.train(training_steps=1)
100 | example_model_with_user_genes.impute_genes()
101 |
102 | # Check that imputation includes these genes
103 | assert 'imputation' in example_model_with_user_genes.spatial_data.obsm
104 | imputed_genes = example_model_with_user_genes.spatial_data.obsm['imputation'].columns
105 |
106 | for gene in ["gene1", "gene3", "gene5"]:
107 | if gene in example_model_with_user_genes.sc_data.var_names:
108 | assert gene in imputed_genes
109 |
110 | def test_all_genes_covet():
111 | """Test using all genes for COVET calculation"""
112 | # Create a new model using all genes for COVET
113 | st_data = anndata.AnnData(X=np.random.uniform(low=0, high=100, size=(16, 4)),
114 | obsm={'spatial': np.random.normal(size=[16, 2])})
115 | sc_data = anndata.AnnData(X=np.random.uniform(low=0, high=100, size=(16, 8)))
116 |
117 | # Set num_cov_genes=-1 to use all genes
118 | envi_model = scenvi.ENVI(spatial_data=st_data, sc_data=sc_data, batch_key=-1, num_cov_genes=-1)
119 |
120 | # Verify all genes are used
121 | assert len(envi_model.CovGenes) == st_data.shape[1]
122 |
123 | # Train and verify
124 | envi_model.train(training_steps=1)
125 | assert 'COVET' in envi_model.spatial_data.obsm
126 |
127 | def test_covet_with_batches(large_example_model):
128 | """Test COVET calculation with batch processing"""
129 | # Calculate COVET matrices using batch processing
130 |
131 |
132 |
133 | (covet, covet_sqrt, cov_genes) = scenvi.compute_covet(
134 | large_example_model.spatial_data,
135 | k=5,
136 | g=6,
137 | batch_size=20 # Process in batches of 20
138 | )
139 | # Verify the results
140 | assert covet.shape[0] == large_example_model.spatial_data.shape[0]
141 | assert covet_sqrt.shape[0] == large_example_model.spatial_data.shape[0]
142 | assert len(cov_genes) >= 6
143 |
144 | # Verify shapes match expected dimensions
145 | assert covet.shape[1] == covet.shape[2] # Square matrices
146 | assert covet_sqrt.shape[1] == covet_sqrt.shape[2] # Square matrices
147 | assert covet.shape[1] == len(cov_genes) # Matrix size matches gene count
148 |
149 | def test_niche_cell_type(example_model):
150 | """Test niche cell type inference"""
151 | # Add cell type information
152 | example_model.spatial_data.obs['cell_type'] = np.random.choice(
153 | ['Type1', 'Type2', 'Type3'], size=example_model.spatial_data.shape[0]
154 | )
155 |
156 | # Train model
157 | example_model.train(training_steps=1)
158 | example_model.infer_niche_covet()
159 | # Infer niche cell types
160 |
161 | example_model.infer_niche_celltype(cell_type_key='cell_type')
162 |
163 | # Verify results
164 | assert 'cell_type_niche' in example_model.spatial_data.obsm
165 | assert 'cell_type_niche' in example_model.sc_data.obsm
166 |
167 | # Check the columns of the cell_type_niche match the unique cell types
168 | unique_cell_types = sorted(example_model.spatial_data.obs['cell_type'].unique())
169 | niche_columns = sorted(example_model.sc_data.obsm['cell_type_niche'].columns)
170 | assert unique_cell_types == niche_columns
--------------------------------------------------------------------------------