├── docs ├── requirements.txt ├── _build │ ├── html │ │ ├── _static │ │ │ ├── scripts │ │ │ │ ├── furo-extensions.js │ │ │ │ ├── furo.js.LICENSE.txt │ │ │ │ └── furo.js │ │ │ ├── file.png │ │ │ ├── minus.png │ │ │ ├── plus.png │ │ │ ├── documentation_options.js │ │ │ ├── debug.css │ │ │ ├── doctools.js │ │ │ ├── styles │ │ │ │ ├── furo-extensions.css │ │ │ │ └── furo-extensions.css.map │ │ │ ├── sphinx_highlight.js │ │ │ ├── language_data.js │ │ │ ├── skeleton.css │ │ │ └── basic.css │ │ ├── objects.inv │ │ ├── .doctrees │ │ │ ├── glhmm.doctree │ │ │ ├── index.doctree │ │ │ ├── utils.doctree │ │ │ ├── auxiliary.doctree │ │ │ ├── glossary.doctree │ │ │ ├── io_glhmm.doctree │ │ │ ├── modules.doctree │ │ │ ├── preproc.doctree │ │ │ └── environment.pickle │ │ ├── _sources │ │ │ ├── modules.md.txt │ │ │ ├── glhmm.md.txt │ │ │ ├── utils.md.txt │ │ │ ├── preproc.md.txt │ │ │ ├── auxiliary.md.txt │ │ │ ├── io_glhmm.md.txt │ │ │ ├── index.md.txt │ │ │ └── glossary.md.txt │ │ ├── .buildinfo │ │ ├── search.html │ │ ├── _modules │ │ │ └── index.html │ │ ├── searchindex.js │ │ ├── py-modindex.html │ │ ├── glossary.html │ │ ├── index.html │ │ └── io_glhmm.html │ └── doctrees │ │ ├── glhmm.doctree │ │ ├── index.doctree │ │ ├── utils.doctree │ │ ├── modules.doctree │ │ ├── preproc.doctree │ │ ├── auxiliary.doctree │ │ ├── environment.pickle │ │ ├── glossary.doctree │ │ └── io_glhmm.doctree ├── io.md ├── notebooks │ ├── files │ │ ├── mask │ │ │ └── MNI152_T1_8mm_brain.nii.gz │ │ └── parcellation │ │ │ └── fmri_d100_parcellation_with_3PCC_ips_reduced_2mm_ss5mm_ds8mm_adj.nii.gz │ └── tutorial.ipynb ├── glhmm.md ├── utils.md ├── preproc.md ├── auxiliary.md ├── graphics.md ├── spectral.md ├── prediction.md ├── statistics.md ├── palm_functions.md ├── modules.md ├── index.md ├── glossary.rst ├── Makefile ├── make.bat └── conf.py ├── logo2_full.png ├── glhmm ├── __pycache__ │ ├── glhmm.cpython-310.pyc │ ├── glhmm.cpython-38.pyc │ ├── utils.cpython-310.pyc │ ├── utils.cpython-38.pyc │ ├── io_glhmm.cpython-38.pyc │ ├── preproc.cpython-310.pyc │ ├── preproc.cpython-38.pyc │ ├── auxiliary.cpython-310.pyc │ ├── auxiliary.cpython-38.pyc │ └── io_glhmm.cpython-310.pyc ├── utils.py └── io.py ├── requirements.txt ├── pyproject.toml ├── .gitpod.yml ├── .readthedocs.yaml ├── setup.py ├── README.md └── .gitignore /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | nbsphinx 2 | ipykernel 3 | -------------------------------------------------------------------------------- /docs/_build/html/_static/scripts/furo-extensions.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /logo2_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/logo2_full.png -------------------------------------------------------------------------------- /docs/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/objects.inv -------------------------------------------------------------------------------- /docs/_build/doctrees/glhmm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/doctrees/glhmm.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/utils.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/doctrees/utils.doctree -------------------------------------------------------------------------------- /docs/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/_static/file.png -------------------------------------------------------------------------------- /docs/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/_static/plus.png -------------------------------------------------------------------------------- /docs/_build/doctrees/modules.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/doctrees/modules.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/preproc.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/doctrees/preproc.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/auxiliary.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/doctrees/auxiliary.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/_build/doctrees/glossary.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/doctrees/glossary.doctree -------------------------------------------------------------------------------- /docs/_build/doctrees/io_glhmm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/doctrees/io_glhmm.doctree -------------------------------------------------------------------------------- /glhmm/__pycache__/glhmm.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/glhmm/__pycache__/glhmm.cpython-310.pyc -------------------------------------------------------------------------------- /glhmm/__pycache__/glhmm.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/glhmm/__pycache__/glhmm.cpython-38.pyc -------------------------------------------------------------------------------- /glhmm/__pycache__/utils.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/glhmm/__pycache__/utils.cpython-310.pyc -------------------------------------------------------------------------------- /glhmm/__pycache__/utils.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/glhmm/__pycache__/utils.cpython-38.pyc -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/glhmm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/.doctrees/glhmm.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/.doctrees/index.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/utils.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/.doctrees/utils.doctree -------------------------------------------------------------------------------- /glhmm/__pycache__/io_glhmm.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/glhmm/__pycache__/io_glhmm.cpython-38.pyc -------------------------------------------------------------------------------- /glhmm/__pycache__/preproc.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/glhmm/__pycache__/preproc.cpython-310.pyc -------------------------------------------------------------------------------- /glhmm/__pycache__/preproc.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/glhmm/__pycache__/preproc.cpython-38.pyc -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/auxiliary.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/.doctrees/auxiliary.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/glossary.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/.doctrees/glossary.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/io_glhmm.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/.doctrees/io_glhmm.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/modules.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/.doctrees/modules.doctree -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/preproc.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/.doctrees/preproc.doctree -------------------------------------------------------------------------------- /glhmm/__pycache__/auxiliary.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/glhmm/__pycache__/auxiliary.cpython-310.pyc -------------------------------------------------------------------------------- /glhmm/__pycache__/auxiliary.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/glhmm/__pycache__/auxiliary.cpython-38.pyc -------------------------------------------------------------------------------- /glhmm/__pycache__/io_glhmm.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/glhmm/__pycache__/io_glhmm.cpython-310.pyc -------------------------------------------------------------------------------- /docs/_build/html/.doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/_build/html/.doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/io.md: -------------------------------------------------------------------------------- 1 | # glhmm.io 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.io 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/notebooks/files/mask/MNI152_T1_8mm_brain.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/notebooks/files/mask/MNI152_T1_8mm_brain.nii.gz -------------------------------------------------------------------------------- /docs/glhmm.md: -------------------------------------------------------------------------------- 1 | # glhmm.glhmm 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.glhmm 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/utils.md: -------------------------------------------------------------------------------- 1 | # glhmm.utils 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.utils 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/preproc.md: -------------------------------------------------------------------------------- 1 | # glhmm.preproc 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.preproc 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/modules.md.txt: -------------------------------------------------------------------------------- 1 | # API 2 | 3 | ```{toctree} 4 | :maxdepth: 4 5 | 6 | glhmm 7 | io_glhmm 8 | preproc 9 | auxiliary 10 | utils 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/auxiliary.md: -------------------------------------------------------------------------------- 1 | # glhmm.auxiliary 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.auxiliary 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/graphics.md: -------------------------------------------------------------------------------- 1 | # glhmm.graphics 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.graphics 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/spectral.md: -------------------------------------------------------------------------------- 1 | # glhmm.spectral 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.spectral 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/prediction.md: -------------------------------------------------------------------------------- 1 | # glhmm.prediction 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.prediction 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/statistics.md: -------------------------------------------------------------------------------- 1 | # glhmm.statistics 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.statistics 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/glhmm.md.txt: -------------------------------------------------------------------------------- 1 | # glhmm module 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.glhmm 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/utils.md.txt: -------------------------------------------------------------------------------- 1 | # utils module 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.utils 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/palm_functions.md: -------------------------------------------------------------------------------- 1 | # glhmm.palm_functions 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.palm_functions 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numba==0.56.4 2 | numpy==1.23.5 3 | scikit-learn==1.2.1 4 | scipy==1.10.1 5 | nbsphinx 6 | ipykernel 7 | matplotlib 8 | seaborn 9 | pickle 10 | pandas 11 | h5py -------------------------------------------------------------------------------- /docs/_build/html/_sources/preproc.md.txt: -------------------------------------------------------------------------------- 1 | # preproc module 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.preproc 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/auxiliary.md.txt: -------------------------------------------------------------------------------- 1 | # auxiliary module 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.auxiliary 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/io_glhmm.md.txt: -------------------------------------------------------------------------------- 1 | # io_glhmm module 2 | 3 | ```{eval-rst} 4 | .. automodule:: glhmm.io_glhmm 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/modules.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | ```{toctree} 4 | :maxdepth: 4 5 | 6 | glhmm 7 | io 8 | preproc 9 | auxiliary 10 | utils 11 | graphics 12 | prediction 13 | statistics 14 | palm_functions 15 | spectral 16 | ``` 17 | -------------------------------------------------------------------------------- /docs/_build/html/_sources/index.md.txt: -------------------------------------------------------------------------------- 1 | # 2 | 3 | ```{include} ../README.md 4 | ``` 5 | 6 | ## Documentation 7 | 8 | ```{toctree} 9 | :caption: 'Contents:' 10 | :maxdepth: 2 11 | 12 | modules 13 | glossary 14 | 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/notebooks/files/parcellation/fmri_d100_parcellation_with_3PCC_ips_reduced_2mm_ss5mm_ds8mm_adj.nii.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vidaurre/glhmm/HEAD/docs/notebooks/files/parcellation/fmri_d100_parcellation_with_3PCC_ips_reduced_2mm_ss5mm_ds8mm_adj.nii.gz -------------------------------------------------------------------------------- /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/.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: 1f76a16923bd6a86f8d23b39e9d8187c 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ![Overview Image](../logo2_full.png) 2 | 3 | ```{include} ../README.md 4 | ``` 5 | 6 | ## Documentation 7 | 8 | > **Warning** 9 | > The documentation of this library is under development 10 | 11 | 12 | ```{toctree} 13 | :caption: 'Contents:' 14 | :maxdepth: 2 15 | 16 | notebooks/tutorial 17 | notebooks/Preprocessing 18 | modules 19 | glossary 20 | 21 | ``` 22 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ['setuptools>=42'] 3 | build-backend = 'setuptools.build_meta' 4 | 5 | [project] 6 | name = "glhmm" 7 | authors = [{name = "Diego Vidaurre", email = "dvidaurre@cfin.au.dk"}] 8 | dynamic = ["version", "description","classifiers","dependencies"] 9 | 10 | [project.optional-dependencies] 11 | doc = [ 12 | "sphinx>=5.0", 13 | "myst_parser", 14 | "furo", 15 | "nbsphinx"] 16 | 17 | #[tool.nbsphinx] 18 | #nbsphinx_kernel_name = "python3.10" 19 | -------------------------------------------------------------------------------- /docs/_build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: '0.0.1', 4 | LANGUAGE: 'en', 5 | COLLAPSE_INDEX: false, 6 | BUILDER: 'html', 7 | FILE_SUFFIX: '.html', 8 | LINK_SUFFIX: '.html', 9 | HAS_SOURCE: true, 10 | SOURCELINK_SUFFIX: '.txt', 11 | NAVIGATION_WITH_KEYS: false, 12 | SHOW_SEARCH_SUMMARY: true, 13 | ENABLE_SEARCH_SHORTCUTS: true, 14 | }; -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | # This configuration file was automatically generated by Gitpod. 2 | # Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml) 3 | # and commit this file to your remote git repository to share the goodness with others. 4 | 5 | # Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart 6 | 7 | tasks: 8 | - init: 9 | - pip install -U pip 10 | - pip cache purge 11 | - pip install -r requirements.txt 12 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | # Sets the version of Python and other tools needed 4 | build: 5 | os: "ubuntu-22.04" 6 | apt_packages: 7 | - "pandoc" 8 | tools: 9 | python: "3.10" 10 | 11 | # Builds documentation in the docs/ directory with Sphinx 12 | sphinx: 13 | configuration: docs/conf.py 14 | 15 | # Optional, builds docs in additional formats such as PDF 16 | formats: 17 | - pdf 18 | - epub 19 | 20 | # Optional, declares the Python requirements required to build docs 21 | python: 22 | install: 23 | - requirements: docs/requirements.txt 24 | - method: pip 25 | path: . 26 | extra_requirements: 27 | - doc 28 | 29 | 30 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | setuptools.setup( 4 | name='glhmm', 5 | version='1.1.2', 6 | description='Gaussian Linear Hidden Markov Model', 7 | url='https://github.com/vidaurre/glhmm', 8 | author='Diego Vidaurre', 9 | author_email = "dvidaurre@cfin.au.dk", 10 | readme = "README.md", 11 | install_requires=['scipy','numpy','scikit-learn','matplotlib','numba','seaborn', 'pandas','igraph', 'tqdm', 'scikit-image','statsmodels', 'h5py','nibabel','requests','nilearn'], 12 | packages=["glhmm"], 13 | zip_safe=False, 14 | classifiers=[ 15 | "Intended Audience :: Science/Research", 16 | "Programming Language :: Python :: 3"] 17 | ) 18 | -------------------------------------------------------------------------------- /docs/glossary.rst: -------------------------------------------------------------------------------- 1 | .. glossary:: 2 | :sorted: 3 | 4 | HMM 5 | Hidden Markov Model. 6 | 7 | n_parcels 8 | The number of brain parcels/regions/seeds. 9 | 10 | n_samples 11 | The number of total timepoints. 12 | 13 | n_sessions 14 | The number of total sessions. 15 | 16 | n_states 17 | The number of hidden states in the *HMM*. 18 | 19 | state mixing 20 | Refers to whether the model is capable of capturing within-session state modulations, rather than assigning the entire sessions (or the largest part of them) to a single state. For more information, visit Ahrends et al. (2022) article `here `_. 21 | 22 | -------------------------------------------------------------------------------- /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 = . 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/html/_sources/glossary.md.txt: -------------------------------------------------------------------------------- 1 | # Glossary 2 | 3 | ```{eval-rst} 4 | 5 | .. glossary:: 6 | :sorted: 7 | 8 | HMM 9 | Hidden Markov Model. 10 | 11 | n_parcels 12 | The number of brain parcels/regions/seeds. 13 | 14 | n_samples 15 | The number of total timepoints. 16 | 17 | n_sessions 18 | The number of total sessions. 19 | 20 | n_states 21 | The number of hidden states in the :term:`HMM`. 22 | 23 | state mixing 24 | Refers to whether the model is capable of capturing within-session state modulations, rather than assigning the entire sessions (or the largest part of them) to a single state. For more information visit Ahrends et al. (2022) article . 25 | 26 | ``` 27 | -------------------------------------------------------------------------------- /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=. 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/_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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Overview Image](logo2_full.png) 2 | 3 | [![Documentation Status](https://readthedocs.org/projects/glhmm/badge/?version=latest)](https://glhmm.readthedocs.io/en/latest/?badge=latest) 4 | 5 | The GLHMM toolbox provides facilities to fit a variety of Hidden Markov models (HMM) based on the Gaussian distribution, which we generalise as the Gaussian-Linear HMM. The toolbox has a focus on finding associations at various levels between brain data (EEG, MEG, fMRI, ECoG, etc) and non-brain data, such as behavioural or physiological variables. A good starting point to decide what is the best way to set it up is 6 | 7 | 8 | ## Important links 9 | 10 | - Official source code repo: 11 | - Jupyter notebooks with examples: 12 | - GLHMM documentation: 13 | - Paper: 14 | 15 | In addition to using the GLHMM toolbox as a Python package, a graphical user interface (GUI) is now available. The GUI offers an intuitive, code-free way to load data, train models, run statistical tests, and visualise results. To access the GUI, visit the companion repository: 16 | **[https://github.com/Nick7900/glhmm_protocols](https://github.com/Nick7900/glhmm_protocols)** 17 | 18 | The GUI is built using Streamlit and can be launched locally. Instructions for setup and use are provided in that repository. An introductory walkthrough of the GUI is available here: 19 | [GLHMM GUI Tutorial – YouTube](https://www.youtube.com/watch?v=XPcoK5zCPtU&t=1497s) 20 | 21 | ## Dependencies 22 | 23 | The required dependencies to use glhmm are: 24 | 25 | - Python >= 3.10 26 | - NumPy 27 | - numba 28 | - scikit-learn 29 | - scipy 30 | - matplotlib 31 | - seaborn 32 | - pickle 33 | - scikit-learn 34 | 35 | - cupy (only when using GPU acceleration; requires manual install) 36 | - h5py 37 | 38 | ## Installation 39 | 40 | - To install the latest development version from the repository, use the following command: 41 | ```bash 42 | pip install git+https://github.com/vidaurre/glhmm 43 | ``` 44 | 45 | - Alternatively, to install the latest stable release from PyPI, use the command: 46 | ```bash 47 | pip install glhmm 48 | ``` 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | import re 16 | 17 | sys.path.insert(0, os.path.abspath('..')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = 'GLHMM' 23 | copyright = '2025, Sonsoles Alonso' 24 | author = 'Sonsoles Alonso' 25 | 26 | # version 27 | setup_path = os.path.abspath(os.path.join('..', 'setup.py')) 28 | with open(setup_path, 'r') as f: 29 | setup_contents = f.read() 30 | match = re.search(r"version\s*=\s*['\"]([^'\"]+)['\"]", setup_contents) 31 | if match: 32 | release = match.group(1) 33 | version = '.'.join(release.split('.')[:2]) # short version 34 | else: 35 | release = 'unknown' 36 | version = 'unknown' 37 | 38 | # -- General configuration --------------------------------------------------- 39 | 40 | # Add any Sphinx extension module names here, as strings. They can be 41 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 42 | # ones. 43 | extensions = [ 44 | 'myst_parser', 45 | 'nbsphinx', 46 | 'sphinx.ext.autodoc', 47 | 'sphinx.ext.autosummary', 48 | 'sphinx.ext.viewcode', 49 | 'sphinx.ext.napoleon', 50 | ] 51 | 52 | # Add any paths that contain templates here, relative to this directory. 53 | templates_path = ['_templates'] 54 | 55 | # List of patterns, relative to source directory, that match files and 56 | # directories to ignore when looking for source files. 57 | # This pattern also affects html_static_path and html_extra_path. 58 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 59 | 60 | 61 | # -- Options for HTML output ------------------------------------------------- 62 | 63 | # The theme to use for HTML and HTML Help pages. See the documentation for 64 | # a list of builtin themes. 65 | # 66 | html_theme = 'furo' 67 | 68 | # Add any paths that contain custom static files (such as style sheets) here, 69 | # relative to this directory. They are copied after the builtin static files, 70 | # so a file named "default.css" will overwrite the builtin "default.css". 71 | #html_static_path = ['_static'] 72 | 73 | 74 | # Set the required version of Sphinx 75 | needs_sphinx = '5.0' 76 | 77 | 78 | # Add nbsphinx_kernel_name option 79 | nbsphinx_kernel_name = 'python3' 80 | 81 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *.py~ 4 | *~ 5 | *.asv 6 | 7 | *.bak 8 | 9 | docs/notebooks/example_data 10 | 11 | # Standard Python ignore below 12 | # Byte-compiled / optimized / DLL files 13 | __pycache__/ 14 | *.py[cod] 15 | *$py.class 16 | 17 | glhmm/__pycache__/*.pyc 18 | 19 | # C extensions 20 | *.so 21 | 22 | # Distribution / packaging 23 | .Python 24 | build/ 25 | develop-eggs/ 26 | dist/ 27 | downloads/ 28 | eggs/ 29 | .eggs/ 30 | lib/ 31 | lib64/ 32 | parts/ 33 | sdist/ 34 | var/ 35 | wheels/ 36 | share/python-wheels/ 37 | *.egg-info/ 38 | .installed.cfg 39 | *.egg 40 | MANIFEST 41 | 42 | glhmm/__pycache__/* 43 | glhmm/__pycache__ 44 | 45 | # PyInstaller 46 | # Usually these files are written by a python script from a template 47 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 48 | *.manifest 49 | *.spec 50 | 51 | # Installer logs 52 | pip-log.txt 53 | pip-delete-this-directory.txt 54 | 55 | # Unit test / coverage reports 56 | htmlcov/ 57 | .tox/ 58 | .nox/ 59 | .coverage 60 | .coverage.* 61 | .cache 62 | nosetests.xml 63 | coverage.xml 64 | *.cover 65 | *.py,cover 66 | .hypothesis/ 67 | .pytest_cache/ 68 | cover/ 69 | 70 | # Translations 71 | *.mo 72 | *.pot 73 | 74 | # Django stuff: 75 | *.log 76 | local_settings.py 77 | db.sqlite3 78 | db.sqlite3-journal 79 | 80 | # Flask stuff: 81 | instance/ 82 | .webassets-cache 83 | 84 | # Scrapy stuff: 85 | .scrapy 86 | 87 | # Sphinx documentation 88 | docs/_build/ 89 | 90 | # PyBuilder 91 | .pybuilder/ 92 | target/ 93 | 94 | # Jupyter Notebook 95 | .ipynb_checkpoints 96 | 97 | # IPython 98 | profile_default/ 99 | ipython_config.py 100 | 101 | # pyenv 102 | # For a library or package, you might want to ignore these files since the code is 103 | # intended to run in multiple environments; otherwise, check them in: 104 | # .python-version 105 | 106 | # pipenv 107 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 108 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 109 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 110 | # install all needed dependencies. 111 | #Pipfile.lock 112 | 113 | # poetry 114 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 115 | # This is especially recommended for binary packages to ensure reproducibility, and is more 116 | # commonly ignored for libraries. 117 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 118 | #poetry.lock 119 | 120 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 121 | __pypackages__/ 122 | 123 | # Celery stuff 124 | celerybeat-schedule 125 | celerybeat.pid 126 | 127 | # SageMath parsed files 128 | *.sage.py 129 | 130 | # Environments 131 | .env 132 | .venv 133 | env/ 134 | venv/ 135 | ENV/ 136 | env.bak/ 137 | venv.bak/ 138 | 139 | # Spyder project settings 140 | .spyderproject 141 | .spyproject 142 | 143 | # Rope project settings 144 | .ropeproject 145 | 146 | # mkdocs documentation 147 | /site 148 | 149 | # mypy 150 | .mypy_cache/ 151 | .dmypy.json 152 | dmypy.json 153 | 154 | # Pyre type checker 155 | .pyre/ 156 | 157 | # pytype static type analyzer 158 | .pytype/ 159 | 160 | # Cython debug symbols 161 | cython_debug/ 162 | 163 | # PyCharm 164 | # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can 165 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 166 | # and can be added to the global gitignore or merged into this file. For a more nuclear 167 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 168 | #.idea/ 169 | -------------------------------------------------------------------------------- /docs/notebooks/tutorial.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Tutorial\n", 8 | "\n", 9 | "GLHMM is a Python toolbox with a focus on neuroscience applications but broadly applicable to other domains as well. It implements a generalisation of various types of Hidden Markov Model ([HMM](../glossary.html#hmm)). The toolbox can be applied on multiple data modalities, including fMRI, EEG, MEG, and ECoG, and offers a comprehensive set of HMMs tailored for different data types and analysis goals. The most important configurable aspect is the state distribution, which is parameterized using a regression model. A non-exhaustive list of possible state distributions are: \n", 10 | "\n", 11 | "- `Gaussian`: used in fMRI and other neuroimaging modalities.\n", 12 | "- `Wishart`: employed in fMRI to specifically focus on changes in connectivity (covariance).\n", 13 | "- `Time-delay embedded`: applied to whole-brain electrophysiological data (MEG or EEG), to capture spectral modulations in the data.\n", 14 | "- `Autoregressive`: provides a more detailed spectral description for electrophysiological data with a limited number of channels.\n", 15 | "- `Regression-based decoding`: describes the dynamic relationship between brain activity and ongoing stimuli.\n", 16 | "- `Regression-based encoding`: emphasizes the spatial interpretation of brain activity in relation to stimuli.\n", 17 | "\n", 18 | "\n", 19 | "## Installation\n", 20 | "If you have not done so, install the repo using:\n", 21 | "\n", 22 | "```pip install glhmm```" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "## Examples\n", 30 | "\n", 31 | "Example data is provided on the [OSF project page](https://osf.io/8qcyj/?view_only=119c38072a724e0091db5ba377935666).\n", 32 | "\n", 33 | "For an example of running a standard HMM using only one set of time series, see [Example standard Gaussian HMM](./GaussianHMM_example.ipynb).\n", 34 | "\n", 35 | "For an example of running a GLHMM using two sets of time series, see [Example GLHMM](./GLHMM_example.ipynb).\n", 36 | "\n", 37 | "For an example of running a TDE-HMM and a MAR-HMM on MEG data, and inspecting their spectral components, see [HMM-TDE vs HMM-MAR example](./HMM-TDE_vs_HMM-MAR_example.ipynb)" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "## Relations to behaviour \n", 45 | "\n", 46 | "After estimating an HMM, we can explore its connections with an external variable not initially considered in the model. This could involve tasks like predicting age from subject-specific HMMs based on neuroimaging data or examining correlations with physiological factors.
\n", 47 | "Our toolbox supports these types of analyses in the modules [Prediction](https://glhmm.readthedocs.io/en/latest/prediction.html) and [Statistics](https://glhmm.readthedocs.io/en/latest/statistics.html)\n", 48 | "\n", 49 | "### Prediction\n", 50 | "This module enables the utilization of individual brain activity patterns for various applications, including predictions (such as cognitive abilities) and classifications (of subjects or clinical groups, for example). For a tutorial, see [Prediction tutorial](./Prediction_tutorial.ipynb).\n", 51 | "\n", 52 | "### Statistics\n", 53 | "This module provides powerful permutation testing analysis, which allows for statistical significance assessment without data distribution assumptions. It supports various test types, such as between- and within-session/subject tests. Users can choose between permutation testing with regression or correlation for a wide range of research questions. For a tutorial demonstrating the application of testing look at the following examples: \n", 54 | "- [Testing across subjects](./Testing_across_subjects.ipynb)\n", 55 | "- [Testing across sessions](./Testing_across_sessions_within_subject.ipynb)\n", 56 | "- [Testing across trials](./Testing_across_trials_within_session.ipynb)\n", 57 | "- [Testing across visits](./Testing_across_visits.ipynb)\n" 58 | ] 59 | } 60 | ], 61 | "metadata": { 62 | "kernelspec": { 63 | "display_name": "Python 3 (ipykernel)", 64 | "language": "python", 65 | "name": "python3" 66 | }, 67 | "language_info": { 68 | "codemirror_mode": { 69 | "name": "ipython", 70 | "version": 3 71 | }, 72 | "file_extension": ".py", 73 | "mimetype": "text/x-python", 74 | "name": "python", 75 | "nbconvert_exporter": "python", 76 | "pygments_lexer": "ipython3", 77 | "version": "3.11.4" 78 | } 79 | }, 80 | "nbformat": 4, 81 | "nbformat_minor": 2 82 | } 83 | -------------------------------------------------------------------------------- /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;function s(){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 l(){!function(){const t=document.getElementsByClassName("theme-toggle");Array.from(t).forEach((t=>{t.addEventListener("click",s)}))}(),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){t<64?document.documentElement.classList.remove("show-back-to-top"):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"),l()}))})()})(); 3 | //# sourceMappingURL=furo.js.map -------------------------------------------------------------------------------- /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-2023 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/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/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 | parent.insertBefore( 33 | span, 34 | parent.insertBefore( 35 | document.createTextNode(val.substr(pos + text.length)), 36 | node.nextSibling 37 | ) 38 | ); 39 | node.nodeValue = val.substr(0, pos); 40 | 41 | if (isInSVG) { 42 | const rect = document.createElementNS( 43 | "http://www.w3.org/2000/svg", 44 | "rect" 45 | ); 46 | const bbox = parent.getBBox(); 47 | rect.x.baseVal.value = bbox.x; 48 | rect.y.baseVal.value = bbox.y; 49 | rect.width.baseVal.value = bbox.width; 50 | rect.height.baseVal.value = bbox.height; 51 | rect.setAttribute("class", className); 52 | addItems.push({ parent: parent, target: rect }); 53 | } 54 | } 55 | } else if (node.matches && !node.matches("button, select, textarea")) { 56 | node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); 57 | } 58 | }; 59 | const _highlightText = (thisNode, text, className) => { 60 | let addItems = []; 61 | _highlight(thisNode, addItems, text, className); 62 | addItems.forEach((obj) => 63 | obj.parent.insertAdjacentElement("beforebegin", obj.target) 64 | ); 65 | }; 66 | 67 | /** 68 | * Small JavaScript module for the documentation. 69 | */ 70 | const SphinxHighlight = { 71 | 72 | /** 73 | * highlight the search words provided in localstorage in the text 74 | */ 75 | highlightSearchWords: () => { 76 | if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight 77 | 78 | // get and clear terms from localstorage 79 | const url = new URL(window.location); 80 | const highlight = 81 | localStorage.getItem("sphinx_highlight_terms") 82 | || url.searchParams.get("highlight") 83 | || ""; 84 | localStorage.removeItem("sphinx_highlight_terms") 85 | url.searchParams.delete("highlight"); 86 | window.history.replaceState({}, "", url); 87 | 88 | // get individual terms from highlight string 89 | const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); 90 | if (terms.length === 0) return; // nothing to do 91 | 92 | // There should never be more than one element matching "div.body" 93 | const divBody = document.querySelectorAll("div.body"); 94 | const body = divBody.length ? divBody[0] : document.querySelector("body"); 95 | window.setTimeout(() => { 96 | terms.forEach((term) => _highlightText(body, term, "highlighted")); 97 | }, 10); 98 | 99 | const searchBox = document.getElementById("searchbox"); 100 | if (searchBox === null) return; 101 | searchBox.appendChild( 102 | document 103 | .createRange() 104 | .createContextualFragment( 105 | '" 109 | ) 110 | ); 111 | }, 112 | 113 | /** 114 | * helper function to hide the search marks again 115 | */ 116 | hideSearchWords: () => { 117 | document 118 | .querySelectorAll("#searchbox .highlight-link") 119 | .forEach((el) => el.remove()); 120 | document 121 | .querySelectorAll("span.highlighted") 122 | .forEach((el) => el.classList.remove("highlighted")); 123 | localStorage.removeItem("sphinx_highlight_terms") 124 | }, 125 | 126 | initEscapeListener: () => { 127 | // only install a listener if it is really needed 128 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; 129 | 130 | document.addEventListener("keydown", (event) => { 131 | // bail for input elements 132 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; 133 | // bail with special keys 134 | if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; 135 | if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { 136 | SphinxHighlight.hideSearchWords(); 137 | event.preventDefault(); 138 | } 139 | }); 140 | }, 141 | }; 142 | 143 | _ready(SphinxHighlight.highlightSearchWords); 144 | _ready(SphinxHighlight.initEscapeListener); 145 | -------------------------------------------------------------------------------- /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-2023 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, is 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/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/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/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Search - GLHMM 0.0.1 documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 35 | 36 | 37 | 40 | 41 | 42 | 43 | 44 | Contents 45 | 46 | 47 | 48 | 49 | 50 | Menu 51 | 53 | 54 | 55 | 56 | 57 | 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 | 111 | 112 | 113 | 114 |
115 |
116 |
117 | 121 |
122 | 125 |
126 |
127 | 133 |
134 | 138 |
139 |
140 | 174 |
175 |
176 |
177 | 178 | 179 | 180 | 181 | Back to top 182 | 183 |
184 |
185 | 191 |
192 | 196 |
197 |
198 | 199 | 207 | 208 |
209 | 210 |
211 |
212 |
213 | 214 | 218 |
219 |
220 | 223 | Made with Sphinx and @pradyunsg's 224 | 225 | Furo 226 | 227 |
228 |
229 | 230 |
231 |
232 | 233 |
234 |
235 | 240 |
241 |
242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /docs/_build/html/_modules/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Overview: module code - GLHMM 0.0.1 documentation 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 37 | 38 | 39 | 42 | 43 | 44 | 45 | 46 | Contents 47 | 48 | 49 | 50 | 51 | 52 | Menu 53 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Expand 62 | 64 | 65 | 66 | 67 | 68 | Light mode 69 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Dark mode 84 | 86 | 87 | 88 | 89 | 90 | 91 | Auto light/dark mode 92 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 110 | 113 | 114 | 115 | 116 |
117 |
118 |
119 | 123 |
124 | 127 |
128 |
129 | 135 |
136 | 140 |
141 |
142 | 176 |
177 |
178 |
179 | 180 | 181 | 182 | 183 | Back to top 184 | 185 |
186 |
187 | 193 |
194 | 198 |
199 | 208 |
209 |
210 | 211 | 215 |
216 |
217 | 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 | -------------------------------------------------------------------------------- /docs/_build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({"docnames": ["auxiliary", "glhmm", "glossary", "io_glhmm", "modules", "preproc", "utils"], "filenames": ["auxiliary.md", "glhmm.md", "glossary.md", "io_glhmm.md", "modules.md", "preproc.md", "utils.md"], "titles": ["auxiliary module", "glhmm module", "Glossary", "io_glhmm module", "API", "preproc module", "utils module"], "terms": {"function": [0, 1, 3, 5, 6], "gaussian": [0, 1, 3, 5, 6], "linear": [0, 1, 3, 5, 6], "hidden": [0, 1, 2, 3, 5, 6], "markov": [0, 1, 2, 3, 5, 6], "model": [0, 1, 2, 3, 5, 6], "author": [0, 1, 3, 5, 6], "diego": [0, 1, 3, 5, 6], "vidaurr": [0, 1, 3, 5, 6], "2022": [0, 2, 6], "glhmm": [0, 3, 4, 5, 6], "gamma_entropi": [0, 4], "gamma": [0, 1, 6], "xi": [0, 1], "indic": [0, 1, 3, 5, 6], "sourc": [0, 1, 3, 5, 6], "comput": [0, 1, 6], "entropi": [0, 1, 6], "distribut": [0, 1], "sequenc": [0, 1, 6], "transit": [0, 1], "probabl": [0, 1, 6], "arrai": [0, 1, 5, 6], "like": [0, 1, 5, 6], "shape": [0, 1, 5, 6], "n_sampl": [0, 1, 2, 5, 6], "n_state": [0, 1, 2, 6], "The": [0, 1, 2, 5, 6], "posterior": 0, "variabl": [0, 1, 5], "n_session": [0, 1, 2, 5, 6], "joint": [0, 1], "past": [0, 1], "futur": [0, 1], "state": [0, 1, 2, 6], "condit": [0, 1, 6], "data": [0, 1, 3, 5, 6], "2": [0, 1, 5, 6], "start": [0, 1, 5, 6], "end": [0, 1, 5, 6], "each": [0, 1, 3, 5, 6], "trial": [0, 1, 5, 6], "session": [0, 1, 2, 5, 6], "input": [0, 1, 3, 5, 6], "float": [0, 1, 5, 6], "gamma_indices_to_xi_indic": [0, 4], "convert": 0, "from": [0, 1, 3], "format": [0, 5], "note": 0, "ha": [0, 1, 5], "1": [0, 1, 5, 6], "sampl": [0, 1, 4], "less": 0, "than": [0, 2, 6], "per": [0, 1, 6], "i": [0, 1, 2, 3, 5, 6], "e": [0, 1, 5, 6], "indices_xi": 0, "approximate_xi": [0, 4], "approxim": 0, "base": [0, 1], "time": [0, 1, 6], "seri": [0, 6], "compute_alpha_beta": [0, 4], "l": [0, 1], "pi": 0, "p": 0, "alpha": 0, "beta": [0, 1], "valu": [0, 1, 6], "scale": [0, 1], "factor": [0, 1], "matrix": [0, 1, 5, 6], "initi": [0, 1, 3], "across": [0, 6], "b": 0, "sc": 0, "compute_qstar": [0, 4], "most": [0, 1, 6], "qstar": 0, "dirichlet_kl": [0, 4], "alpha_q": 0, "alpha_p": 0, "kullback": 0, "leibler": 0, "diverg": [0, 1], "between": [0, 1], "two": 0, "dirichlet": [0, 1], "concentr": 0, "first": [0, 5, 6], "second": [0, 5], "gamma_kl": [0, 4], "shape_q": 0, "rate_q": 0, "shape_p": 0, "rate_p": 0, "rate": [0, 6], "measur": 0, "how": 0, "differ": [0, 1], "ar": [0, 1, 5], "thi": [0, 1, 6], "implement": 0, "follow": [0, 1, 6], "formula": 0, "present": 0, "here": 0, "http": [0, 2, 6], "statproofbook": 0, "github": 0, "io": 0, "gam": 0, "kl": [0, 1], "book": 0, "normal": [0, 6], "wishart": 0, "densiti": 0, "penni": 0, "william": 0, "d": [0, 5], "2001": 0, "numpi": [0, 1, 5], "ndarrai": [0, 5], "gauss1d_kl": [0, 4], "mu_q": 0, "sigma_q": 0, "mu_p": 0, "sigma_p": 0, "univari": 0, "n_parcel": [0, 1, 2, 5], "mean": [0, 1, 5], "varianc": [0, 5], "gauss_kl": [0, 4], "multivari": 0, "jls_extract_def": [0, 4], "make_indices_from_t": [0, 4], "t": 0, "creat": 0, "length": [0, 1, 5, 6], "contain": [0, 1, 3], "slice_matrix": [0, 4], "m": 0, "slice": 0, "row": [0, 1, 6], "along": 0, "axi": 0, "0": [0, 1, 6], "defin": [0, 1, 6], "section": 0, "process": [0, 1], "m_slice": 0, "n_total_sampl": 0, "wishart_kl": [0, 4], "c_q": 0, "c_p": 0, "2023": [1, 3, 5, 6], "class": 1, "k": [1, 6], "10": 1, "covtyp": 1, "shareddiag": 1, "model_mean": 1, "model_beta": 1, "dirichlet_diag": 1, "connect": [1, 5, 6], "none": [1, 3, 5], "pstructur": 1, "pistructur": 1, "object": 1, "decod": [1, 4], "stimulu": 1, "int": [1, 5, 6], "default": [1, 5, 6], "number": [1, 2, 5, 6], "str": 1, "diag": 1, "type": 1, "covari": 1, "choos": 1, "have": [1, 6], "one": [1, 6], "diagon": 1, "all": [1, 6], "full": [1, 5], "If": [1, 5, 6], "timeseri": [1, 5, 6], "us": [1, 3, 5, 6], "drive": 1, "regress": [1, 5], "coeffici": 1, "higher": 1, "more": [1, 2, 6], "persist": 1, "rel": 1, "prior": 1, "compet": 1, "so": 1, "veri": 1, "long": 1, "mai": 1, "littl": 1, "effect": [1, 5], "unless": 1, "set": [1, 5], "larg": 1, "array_lik": 1, "option": [1, 5, 6], "binari": [1, 5], "can": [1, 5, 6], "onli": [1, 6], "allow": 1, "ones": 1, "possibl": 1, "vector": 1, "requir": 1, "math": 1, "scipi": 1, "sy": 1, "warn": 1, "copi": 1, "x": [1, 5], "y": [1, 5], "file": [1, 3, 5], "viterbi": [1, 6], "fals": [1, 3, 5, 6], "calcul": [1, 5, 6], "cours": 1, "either": 1, "parallel": 1, "sequenti": 1, "list": [1, 5, 6], "filenam": 1, "correspond": 1, "bool": [1, 5, 6], "whether": [1, 2, 5], "algorithm": 1, "should": [1, 5], "index": 1, "true": [1, 5, 6], "vpath": [1, 6], "free": 1, "energi": 1, "dataset": 1, "automat": 1, "except": [1, 6], "been": 1, "train": [1, 4], "dual_estim": [1, 4], "dual": 1, "estim": [1, 6], "hmm": [1, 2, 3, 5], "singl": [1, 2], "segment": [1, 5], "span": 1, "entir": [1, 2], "observ": 1, "hmm_dual": 1, "A": [1, 5, 6], "updat": 1, "dynam": 1, "get_beta": [1, 4], "specifi": 1, "which": [1, 5, 6], "retriev": 1, "yet": 1, "get_covariance_matrix": [1, 4], "get_f": [1, 4], "todo": 1, "an": [1, 5], "depend": 1, "n_term": 1, "5": 1, "element": [1, 5], "see": [1, 6], "fe_term": 1, "variat": 1, "separ": 1, "term": 1, "neg": 1, "log": 1, "likelihood": 1, "3": 1, "4": 1, "specif": 1, "For": [1, 2, 6], "inform": [1, 2, 6], "smith": 1, "j": 1, "et": [1, 2, 6], "al": [1, 2, 6], "approach": 1, "bayesian": 1, "learn": 1, "switch": [1, 6], "system": 1, "journal": 1, "machin": 1, "research": 1, "vol": 1, "18": 1, "2017": 1, "get_inverse_covariance_matrix": [1, 4], "invers": 1, "get_mean": [1, 4], "compon": [1, 5], "loglikelihood": [1, 4], "point": [1, 6], "gicven": 1, "given": [1, 6], "size": 1, "gener": [1, 5], "dimension": 1, "repres": [1, 6], "sample_gamma": [1, 4], "big": 1, "cut": 1, "assum": 1, "": 1, "load": [1, 3], "ignor": 1, "dict": 1, "dictionari": 1, "control": 1, "fe": 1, "iter": 1, "brain": 2, "parcel": 2, "region": 2, "seed": 2, "total": 2, "timepoint": 2, "mix": [2, 6], "refer": 2, "capabl": 2, "captur": 2, "within": 2, "modul": [2, 4], "rather": 2, "assign": 2, "largest": 2, "part": 2, "them": 2, "visit": [2, 6], "ahrend": [2, 6], "articl": 2, "pubm": [2, 6], "ncbi": [2, 6], "nlm": [2, 6], "nih": [2, 6], "gov": [2, 6], "35217207": [2, 6], "output": 3, "load_fil": [3, 4, 5], "do_only_indic": [3, 5], "return": 3, "individu": 3, "read_flattened_hmm_mat": [3, 4], "read": 3, "matlab": 3, "paramet": 3, "those": [3, 6], "preprocess": 5, "apply_pca": [4, 5], "whiten": 5, "exact": 5, "appli": 5, "pca": 5, "transform": 5, "keep": 5, "percentag": 5, "explain": 5, "n_compon": 5, "svd": 5, "solver": 5, "x_transform": 5, "after": 5, "build_data_autoregress": [4, 5], "autoregressive_ord": 5, "center_data": 5, "build": 5, "autoregress": 5, "well": 5, "adapt": 5, "predefin": 5, "right": 5, "center": 5, "lag": 5, "includ": 5, "regressor": 5, "predict": 5, "target": 5, "indices_new": 5, "new": 5, "connectivity_new": 5, "build_data_partial_connect": [4, 5], "partial": 5, "essenti": 5, "out": 5, "thing": 5, "when": [5, 6], "get": 5, "rid": 5, "dimens": 5, "np": 5, "affect": 5, "zero": 5, "x_new": 5, "n_active_parcel": 5, "remov": 5, "unus": 5, "predictor": 5, "y_new": 5, "same": [5, 6], "structur": 5, "build_data_td": [4, 5], "standardise_pc": 5, "tempor": 5, "delai": 5, "embed": 5, "precomput": 5, "project": 5, "skip": 5, "standardis": 5, "princip": 5, "befor": 5, "rwindow": 5, "n_lag": 5, "run": 5, "preprocess_data": [4, 5], "f": 5, "filter": 5, "detrend": 5, "onpow": 5, "exact_pca": 5, "downsampl": 5, "frequenc": 5, "standard": 5, "tupl": 5, "low": 5, "pass": 5, "high": 5, "threshold": [5, 6], "power": 5, "hilbert": 5, "data_process": 5, "n_samples_process": 5, "indices_process": 5, "n_sessions_process": 5, "some": 6, "public": 6, "get_fo": [4, 6], "summat": 6, "fraction": 6, "occup": 6, "sum": 6, "otherwis": 6, "fo": 6, "get_fo_entropi": [4, 6], "we": 6, "understand": 6, "get_life_tim": [4, 6], "averag": 6, "median": 6, "maximum": 6, "life": 6, "path": 6, "exclud": 6, "durat": 6, "below": 6, "meanlf": 6, "medianlf": 6, "maxlf": 6, "contigu": 6, "activ": 6, "get_visit": [4, 6], "get_maxfo": [4, 6], "argument": 6, "also": 6, "maxfo": 6, "assess": 6, "amount": 6, "r": 6, "consider": 6, "vari": 6, "fmri": 6, "neuroimag": 6, "252": 6, "119026": 6, "get_state_evoked_respons": [4, 6], "evok": 6, "respons": 6, "ser": 6, "violat": 6, "ani": 6, "There": 6, "Not": 6, "get_state_evoked_response_entropi": [4, 6], "get_state_onset": [4, 6], "onset": 6, "get_switching_r": [4, 6], "sr": 6, "where": 6, "greater": 6, "io_glhmm": 4, "preproc": 4, "auxiliari": 4, "util": 4}, "objects": {"glhmm": [[0, 0, 0, "-", "auxiliary"], [1, 0, 0, "-", "glhmm"], [3, 0, 0, "-", "io_glhmm"], [5, 0, 0, "-", "preproc"], [6, 0, 0, "-", "utils"]], "glhmm.auxiliary": [[0, 1, 1, "", "Gamma_entropy"], [0, 1, 1, "", "Gamma_indices_to_Xi_indices"], [0, 1, 1, "", "approximate_Xi"], [0, 1, 1, "", "compute_alpha_beta"], [0, 1, 1, "", "compute_qstar"], [0, 1, 1, "", "dirichlet_kl"], [0, 1, 1, "", "gamma_kl"], [0, 1, 1, "", "gauss1d_kl"], [0, 1, 1, "", "gauss_kl"], [0, 1, 1, "", "jls_extract_def"], [0, 1, 1, "", "make_indices_from_T"], [0, 1, 1, "", "slice_matrix"], [0, 1, 1, "", "wishart_kl"]], "glhmm.glhmm": [[1, 2, 1, "", "glhmm"]], "glhmm.glhmm.glhmm": [[1, 3, 1, "", "decode"], [1, 3, 1, "", "dual_estimate"], [1, 3, 1, "", "get_beta"], [1, 3, 1, "", "get_covariance_matrix"], [1, 3, 1, "", "get_fe"], [1, 3, 1, "", "get_inverse_covariance_matrix"], [1, 3, 1, "", "get_mean"], [1, 3, 1, "", "loglikelihood"], [1, 3, 1, "", "sample"], [1, 3, 1, "", "sample_Gamma"], [1, 3, 1, "", "train"]], "glhmm.io_glhmm": [[3, 1, 1, "", "load_files"], [3, 1, 1, "", "read_flattened_hmm_mat"]], "glhmm.preproc": [[5, 1, 1, "", "apply_pca"], [5, 1, 1, "", "build_data_autoregressive"], [5, 1, 1, "", "build_data_partial_connectivity"], [5, 1, 1, "", "build_data_tde"], [5, 1, 1, "", "load_files"], [5, 1, 1, "", "preprocess_data"]], "glhmm.utils": [[6, 1, 1, "", "get_FO"], [6, 1, 1, "", "get_FO_entropy"], [6, 1, 1, "", "get_life_times"], [6, 1, 1, "", "get_maxFO"], [6, 1, 1, "", "get_state_evoked_response"], [6, 1, 1, "", "get_state_evoked_response_entropy"], [6, 1, 1, "", "get_state_onsets"], [6, 1, 1, "", "get_switching_rate"], [6, 1, 1, "", "get_visits"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"]}, "titleterms": {"auxiliari": 0, "modul": [0, 1, 3, 5, 6], "paramet": [0, 1, 5, 6], "return": [0, 1, 5, 6], "glhmm": 1, "attribut": 1, "note": [1, 6], "rais": [1, 6], "refer": [1, 6], "glossari": 2, "io_glhmm": 3, "preproc": 5, "util": 6, "api": 4}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "nbsphinx": 4, "sphinx.ext.viewcode": 1, "sphinx": 57}, "alltitles": {"Glossary": [[2, "glossary"]], "io_glhmm module": [[3, "module-glhmm.io_glhmm"]], "auxiliary module": [[0, "module-glhmm.auxiliary"]], "Parameters:": [[0, "parameters"], [0, "id1"], [0, "id3"], [0, "id5"], [0, "id7"], [0, "id9"], [0, "id11"], [0, "id13"], [0, "id15"], [0, "id17"], [0, "id19"], [0, "id21"], [1, "parameters"], [1, "id1"], [1, "id3"], [1, "id6"], [1, "id9"], [1, "id13"], [1, "id16"], [1, "id19"], [1, "id22"], [1, "id24"], [1, "id26"], [5, "parameters"], [5, "id1"], [5, "id3"], [5, "id5"], [5, "id7"], [6, "parameters"], [6, "id1"], [6, "id3"], [6, "id5"], [6, "id8"], [6, "id10"], [6, "id12"], [6, "id15"], [6, "id17"]], "Returns:": [[0, "returns"], [0, "id2"], [0, "id4"], [0, "id6"], [0, "id8"], [0, "id10"], [0, "id12"], [0, "id14"], [0, "id16"], [0, "id18"], [0, "id20"], [0, "id22"], [1, "returns"], [1, "id2"], [1, "id4"], [1, "id7"], [1, "id10"], [1, "id14"], [1, "id17"], [1, "id20"], [1, "id23"], [1, "id25"], [1, "id27"], [5, "returns"], [5, "id2"], [5, "id4"], [5, "id6"], [5, "id8"], [6, "returns"], [6, "id2"], [6, "id4"], [6, "id6"], [6, "id9"], [6, "id11"], [6, "id13"], [6, "id16"], [6, "id18"]], "glhmm module": [[1, "module-glhmm.glhmm"]], "Attributes:": [[1, "attributes"]], "Notes:": [[1, "notes"], [1, "id12"], [6, "notes"], [6, "id7"], [6, "id14"], [6, "id19"]], "Raises:": [[1, "raises"], [1, "id5"], [1, "id8"], [1, "id11"], [1, "id15"], [1, "id18"], [1, "id21"], [6, "raises"]], "References:": [[1, "references"], [6, "references"]], "preproc module": [[5, "module-glhmm.preproc"]], "utils module": [[6, "module-glhmm.utils"]], "API": [[4, "api"]]}, "indexentries": {}}) -------------------------------------------------------------------------------- /docs/_build/html/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Python Module Index - GLHMM 0.0.1 documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | Contents 46 | 47 | 48 | 49 | 50 | 51 | Menu 52 | 54 | 55 | 56 | 57 | 58 | 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 | 112 | 113 | 114 | 115 |
116 |
117 |
118 | 122 |
123 | 126 |
127 |
128 | 134 |
135 | 139 |
140 |
141 | 175 |
176 |
177 |
178 | 179 | 180 | 181 | 182 | Back to top 183 | 184 |
185 |
186 | 192 |
193 | 197 |
198 |
199 | 200 |
201 |

Python Module Index

202 | 203 |
204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 214 | 217 | 218 | 219 | 220 | 223 | 224 | 225 | 226 | 229 | 230 | 231 | 232 | 235 | 236 | 237 | 238 | 241 | 242 | 243 | 244 | 247 | 248 |
 
g
215 | glhmm 216 |
    221 | glhmm.auxiliary 222 |
    227 | glhmm.glhmm 228 |
    233 | glhmm.io_glhmm 234 |
    239 | glhmm.preproc 240 |
    245 | glhmm.utils 246 |
249 | 250 |
251 |
252 |
253 | 254 | 258 |
259 |
260 | 263 | Made with Sphinx and @pradyunsg's 264 | 265 | Furo 266 | 267 |
268 |
269 | 270 |
271 |
272 | 273 |
274 |
275 | 280 |
281 |
282 | 283 | 284 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /glhmm/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Some public useful functions - Gaussian Linear Hidden Markov Model 5 | @author: Diego Vidaurre 2023 6 | """ 7 | 8 | import numpy as np 9 | import statistics 10 | import math 11 | from scipy.optimize import linear_sum_assignment 12 | 13 | def get_FO(Gamma,indices,summation=False): 14 | """Calculates the fractional occupancy of each state. 15 | 16 | Parameters: 17 | ----------- 18 | Gamma : array-like, shape (n_samples, n_states) 19 | The state probability time series. 20 | indices : array-like, shape (n_sessions, 2) 21 | The start and end indices of each trial/session in the input data. 22 | summation : bool, optional, default=False 23 | If True, the sum of each row is not normalized, otherwise it is. 24 | 25 | Returns: 26 | -------- 27 | FO : array-like, shape (n_sessions, n_states) 28 | The fractional occupancy of each state per session. 29 | 30 | """ 31 | 32 | N = indices.shape[0] 33 | K = Gamma.shape[1] 34 | FO = np.zeros((N,K)) 35 | for j in range(N): 36 | ind = np.arange(indices[j,0],indices[j,1]) 37 | FO[j,:] = np.sum(Gamma[ind,:],axis=0) 38 | if not summation: 39 | FO[j,:] /= np.sum(FO[j,:]) 40 | return FO 41 | 42 | 43 | def get_maxFO(Gamma,indices): 44 | """Calculates the maximum fractional occupancy per session. 45 | 46 | The first argument can also be a viterbi path (vpath). 47 | 48 | Parameters: 49 | ----------- 50 | Gamma : array-like of shape (n_samples, n_states); or a vpath, array of shape (n_samples,) 51 | The Gamma represents the state probability timeseries and the vpath represents the most likely state sequence. 52 | indices : array-like of shape (n_sessions, 2) 53 | The start and end indices of each trial/session in the input data. 54 | 55 | Returns: 56 | -------- 57 | maxFO: array-like of shape (n_sessions,) 58 | The maximum fractional occupancy across states for each trial/session 59 | 60 | Notes: 61 | ------ 62 | The maxFO is useful to assess the amount of `state mixing`. For more information, see [^1]. 63 | 64 | References: 65 | ----------- 66 | [^1]: Ahrends, R., et al. (2022). Data and model considerations for estimating time-varying functional connectivity in fMRI. NeuroImage 252, 119026. 67 | https://pubmed.ncbi.nlm.nih.gov/35217207/) 68 | 69 | """ 70 | FO = get_FO(Gamma,indices) 71 | return np.max(FO,axis=1) 72 | 73 | 74 | def get_state_evoked_response(Gamma,indices): 75 | """Calculates the state evoked response 76 | 77 | The first argument can also be a viterbi path (vpath). 78 | 79 | Parameters: 80 | --------------- 81 | Gamma : array-like of shape (n_samples, n_states), or a vpath array of shape (n_samples,) 82 | The Gamma represents the state probability timeseries and the vpath represents the most likely state sequence. 83 | indices : array-like of shape (n_sessions, 2) 84 | The start and end indices of each trial/session in the input data. 85 | 86 | Returns: 87 | ------------ 88 | ser : array-like of shape (n_samples, n_states) 89 | The state evoked response matrix. 90 | 91 | Raises: 92 | ------- 93 | Exception 94 | If the input data violates any of the following conditions: 95 | - There is only one trial/session 96 | - Not all trials/sessions have the same length. 97 | """ 98 | 99 | N = indices.shape[0] 100 | if N == 1: 101 | raise Exception("There is only one segment / trial") 102 | T = indices[:,1] - indices[:,0] 103 | if not(np.all(T[0]==T)): 104 | raise Exception("All segments / trials must have the same length") 105 | K = Gamma.shape[1] 106 | T = T[0] 107 | 108 | ser = np.mean(np.reshape(Gamma,(T,N,K),order='F'),axis=1) 109 | return ser 110 | 111 | 112 | def get_switching_rate(Gamma,indices): 113 | """Calculates the switching rate. 114 | 115 | The first argument can also be a viterbi path (vpath). 116 | 117 | Parameters: 118 | --------------- 119 | Gamma : array-like of shape (n_samples, n_states), or a vpath array of shape (n_samples,) 120 | The Gamma represents the state probability timeseries and the vpath represents the most likely state sequence. 121 | indices : array-like of shape (n_sessions, 2) 122 | The start and end indices of each trial/session in the input data. 123 | 124 | Returns: 125 | ------------ 126 | SR : array-like of shape (n_sessions, n_states) 127 | The switching rate matrix. 128 | 129 | """ 130 | N = indices.shape[0] 131 | K = Gamma.shape[1] 132 | SR = np.zeros((N,K)) 133 | for j in range(N): 134 | ind = np.arange(indices[j,0],indices[j,1]) 135 | SR[j,:] = np.mean(np.abs(Gamma[ind[1:],:]-Gamma[ind[0:-1],:]),axis=0) 136 | return SR 137 | 138 | 139 | def get_visits(vpath,k,threshold=0): 140 | """Computes a list of visits for state k, given a viterbi path (vpath). 141 | 142 | Parameters: 143 | --------------- 144 | vpath : array-like of shape (n_samples,) 145 | The viterbi path represents the most likely state sequence. 146 | k : int 147 | The state for which to compute the visits. 148 | threshold : int, optional, default=0 149 | A threshold value used to exclude visits with a duration below this value. 150 | 151 | Returns: 152 | ------------ 153 | lengths : list of floats 154 | A list of visit durations for state k, where each duration is greater than the threshold. 155 | onsets : list of ints 156 | A list of onset time points for each visit. 157 | 158 | Notes: 159 | ------ 160 | A visit to state k is defined as a contiguous sequence of time points in which state k is active. 161 | 162 | """ 163 | 164 | lengths = [] 165 | onsets = [] 166 | T = vpath.shape[0] 167 | vpath_k = vpath[:,k] 168 | t = 0 169 | while t < T: 170 | t += np.where(vpath_k[t:]==1)[0] 171 | if len(t)==0: 172 | break 173 | t = t[0] 174 | onsets.append(t) 175 | tend = np.where(vpath_k[t:]==0)[0] 176 | if len(tend)==0: 177 | length_visit = len(vpath_k)-t 178 | if length_visit > threshold: lengths.append(float(length_visit)) 179 | break 180 | tend = tend[0] 181 | length_visit = tend 182 | if length_visit > threshold: lengths.append(float(length_visit)) 183 | t += tend 184 | return lengths,onsets 185 | 186 | 187 | def get_life_times(vpath,indices,threshold=0): 188 | """Calculates the average, median and maximum life times for each state. 189 | 190 | Parameters: 191 | ----------- 192 | vpath : array-like of shape (n_samples,) 193 | The viterbi path represents the most likely state sequence. 194 | indices : array-like of shape (n_sessions, 2) 195 | The start and end indices of each trial/session in the input data. 196 | threshold : int, optional, default=0 197 | A threshold value used to exclude visits with a duration below this value. 198 | 199 | Returns: 200 | -------- 201 | meanLF : array-like of shape (n_sessions, n_states) 202 | The average visit duration for each state in each trial/session. 203 | medianLF : array-like of shape (n_sessions, n_states) 204 | The median visit duration for each state in each trial/session. 205 | maxLF : array-like of shape (n_sessions, n_states) 206 | The maximum visit duration for each state in each trial/session. 207 | 208 | Notes: 209 | ------ 210 | A visit to a state is defined as a contiguous sequence of time points in which the state is active. 211 | The duration of a visit is the number of time points in the sequence. 212 | This function uses the `get_visits` function to compute the visits and exclude those below the threshold. 213 | 214 | """ 215 | N = indices.shape[0] 216 | K = vpath.shape[1] 217 | meanLF = np.zeros((N,K)) 218 | medianLF = np.zeros((N,K)) 219 | maxLF = np.zeros((N,K)) 220 | for j in range(N): 221 | ind = np.arange(indices[j,0],indices[j,1]).astype(int) 222 | for k in range(K): 223 | visits,_ = get_visits(vpath[ind,:],k,threshold=threshold) 224 | if len(visits) > 0: 225 | meanLF[j,k] = statistics.mean(visits) 226 | medianLF[j,k] = statistics.median(visits) 227 | maxLF[j,k] = max(visits) 228 | return meanLF, medianLF, maxLF 229 | 230 | 231 | def get_state_onsets(vpath,indices,threshold=0): 232 | """Calculates the state onsets, i.e., the time points when each state activates. 233 | 234 | Parameters: 235 | --------------- 236 | vpath : array-like of shape (n_samples, n_states) 237 | The viterbi path represents the most likely state sequence. 238 | indices : array-like of shape (n_sessions, 2) 239 | The start and end indices of each trial/session in the input data. 240 | threshold : int, optional, default=0 241 | A threshold value used to exclude visits with a duration below this value. 242 | 243 | Returns: 244 | -------- 245 | onsets : list of lists of ints 246 | A list of the time points when each state activates for each trial/session. 247 | 248 | Notes: 249 | ------ 250 | A visit to a state is defined as a contiguous sequence of time points in which the state is active. 251 | This function uses the `get_visits` function to compute the visits and exclude those below the threshold. 252 | 253 | """ 254 | 255 | N = indices.shape[0] 256 | K = vpath.shape[1] 257 | onsets = [] 258 | for j in range(N): 259 | onsets_j = [] 260 | ind = np.arange(indices[j,0],indices[j,1]).astype(int) 261 | for k in range(K): 262 | _,onsets_k = get_visits(vpath[ind,:],k,threshold=threshold) 263 | onsets_j.append(onsets_k) 264 | onsets.append(onsets_j) 265 | return onsets 266 | 267 | 268 | def get_FO_entropy(Gamma,indices): 269 | """Calculates the entropy of each session, if we understand fractional occupancies as probabilities. 270 | 271 | Parameters: 272 | -------------- 273 | Gamma : array-like of shape (n_samples, n_states) 274 | The Gamma represents the state probability timeseries. 275 | indices : array-like of shape (n_sessions, 2) 276 | The start and end indices of each trial/session in the input data. 277 | 278 | Returns: 279 | -------- 280 | entropy : array-like of shape (n_sessions,) 281 | The entropy of each session. 282 | 283 | """ 284 | fo = get_FO(Gamma,indices) 285 | N,K = fo.shape 286 | entropy = np.zeros(N) 287 | for j in range(N): 288 | for k in range(K): 289 | if fo[j,k] == 0: continue 290 | entropy[j] -= math.log(fo[j,k]) * fo[j,k] 291 | return entropy 292 | 293 | 294 | def get_state_evoked_response_entropy(Gamma,indices): 295 | """Calculates the entropy of each time point, if we understand state evoked responses as probabilities. 296 | 297 | Parameters: 298 | --------------- 299 | Gamma: array-like of shape (n_samples, n_states) 300 | The Gamma represents the state probability timeseries. 301 | indices : array-like of shape (n_sessions, 2) 302 | The start and end indices of each trial/session in the input data. 303 | 304 | Returns: 305 | ------------ 306 | entropy: array-like of shape (n_samples,) 307 | The entropy of each time point. 308 | 309 | """ 310 | ser = get_state_evoked_response(Gamma,indices) 311 | T,K = ser.shape 312 | entropy = np.zeros(T) 313 | for t in range(T): 314 | for k in range(K): 315 | if ser[t,k] == 0: continue 316 | entropy[t] -= math.log(ser[t,k]) * ser[t,k] 317 | return entropy 318 | 319 | 320 | def get_gamma_similarity(gamma1, gamma2): 321 | """Computes a measure of similarity between two sets of state time courses. 322 | 323 | These can have different numbers of states, but they must have the same 324 | number of time points. 325 | 326 | Parameters: 327 | ----------- 328 | gamma1 : numpy.ndarray 329 | First set of state time courses with shape (T, K). 330 | gamma2 : numpy.ndarray 331 | Second set of state time courses with shape (T, K2), where K2 may be different from K. 332 | 333 | Returns: 334 | -------- 335 | S : float 336 | Similarity, measured as the sum of joint probabilities under the optimal state alignment. 337 | assig : numpy.ndarray 338 | Optimal state alignment for gamma2 (uses Munkres' algorithm). 339 | gamma2 : numpy.ndarray 340 | The second set of state time courses reordered to match gamma1. 341 | """ 342 | 343 | T, K = gamma1.shape 344 | gamma1_0 = gamma1.copy() 345 | g = gamma2 346 | K2 = g.shape[1] 347 | 348 | if K < K2: 349 | gamma1 = np.hstack((gamma1_0, np.zeros((T, K2 - K)))) 350 | K = K2 351 | elif K > K2: 352 | g = np.hstack((g, np.zeros((T, K - K2)))) 353 | 354 | M = np.zeros((K, K)) # cost 355 | 356 | for k1 in range(K): 357 | for k2 in range(K): 358 | M[k1, k2] += (T - np.sum(np.minimum(gamma1[:, k1], g[:, k2]))) / T 359 | 360 | row_ind, col_ind = linear_sum_assignment(M) 361 | S = K - M[row_ind, col_ind].sum() 362 | 363 | gamma2 = g[:, col_ind] 364 | 365 | return S, col_ind, gamma2 366 | 367 | 368 | -------------------------------------------------------------------------------- /docs/_build/html/glossary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Glossary - GLHMM 0.0.1 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 47 | Contents 48 | 49 | 50 | 51 | 52 | 53 | Menu 54 | 56 | 57 | 58 | 59 | 60 | 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 | 114 | 115 | 116 | 117 |
118 |
119 |
120 | 124 |
125 | 128 |
129 |
130 | 136 |
137 | 141 |
142 |
143 | 177 |
178 |
179 |
180 | 181 | 182 | 183 | 184 | Back to top 185 | 186 |
187 | 188 |
189 | 195 |
196 | 200 |
201 |
202 |
203 |

Glossary#

204 |
205 |
HMM#

Hidden Markov Model.

206 |
207 |
n_parcels#

The number of brain parcels/regions/seeds.

208 |
209 |
n_samples#

The number of total timepoints.

210 |
211 |
n_sessions#

The number of total sessions.

212 |
213 |
n_states#

The number of hidden states in the HMM.

214 |
215 |
state mixing#

Refers to whether the model is capable of capturing within-session state modulations, rather than assigning the entire sessions (or the largest part of them) to a single state. For more information visit Ahrends et al. (2022) article <https://pubmed.ncbi.nlm.nih.gov/35217207/>.

216 |
217 |
218 |
219 | 220 |
221 |
222 | 254 |
255 | 260 |
261 |
262 | 263 | 264 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /docs/_build/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | GLHMM 0.0.1 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 47 | Contents 48 | 49 | 50 | 51 | 52 | 53 | Menu 54 | 56 | 57 | 58 | 59 | 60 | 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 | 114 | 115 | 116 | 117 |
118 |
119 |
120 | 124 |
125 | 128 |
129 |
130 | 136 |
137 | 141 |
142 |
143 | 177 |
178 |
179 |
180 | 181 | 182 | 183 | 184 | Back to top 185 | 186 |
187 | 188 |
189 | 195 |
196 | 200 |
201 |
202 |
203 |

#

204 |
205 |
206 |

GLHMM#

207 |

Gaussian Linear Hidden Markov Models:

208 |
209 |

Warning: The documentation of this library is under heavy development

210 |
211 | 218 |
219 |

Dependencies#

220 |

The required dependencies to use glhmm are:

221 |
    222 |
  • Python >= 3.6

  • 223 |
  • NumPy

  • 224 |
  • scikit-learn

  • 225 |
  • scipy

  • 226 |
  • matplotlib

  • 227 |
  • numba

  • 228 |
229 |
230 |
231 |

Installation#

232 |

To install from the repo, use the following command:

233 |
pip install --user git+https://github.com/vidaurre/glhmm
234 | 
235 |
236 |
237 |
238 |

Documentation#

239 |
240 |

Contents:

241 | 252 |
253 |
254 |
255 | 256 |
257 |
258 | 288 |
289 | 294 |
295 |
296 | 297 | 298 | 299 | 300 | 301 | -------------------------------------------------------------------------------- /docs/_build/html/io_glhmm.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | io_glhmm module - GLHMM 0.0.1 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 47 | Contents 48 | 49 | 50 | 51 | 52 | 53 | Menu 54 | 56 | 57 | 58 | 59 | 60 | 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 | 114 | 115 | 116 | 117 |
118 |
119 |
120 | 124 |
125 | 128 |
129 |
130 | 136 |
137 | 141 |
142 |
143 | 177 |
178 |
179 |
180 | 181 | 182 | 183 | 184 | Back to top 185 | 186 |
187 | 188 |
189 | 195 |
196 | 200 |
201 |
202 |
203 |

io_glhmm module#

204 |

Input/output functions - Gaussian Linear Hidden Markov Model 205 | @author: Diego Vidaurre 2023

206 |
207 |
208 | glhmm.io_glhmm.load_files(files, I=None, do_only_indices=False)[source]#
209 |

Loads data from files and returns the loaded data, indices, and individual indices for each file.

210 |
211 | 212 |
213 |
214 | glhmm.io_glhmm.read_flattened_hmm_mat(file)[source]#
215 |

Reads a MATLAB file containing hidden Markov model (HMM) parameters, and initializes a Gaussian linear hidden Markov model (GLHMM) using those parameters.

216 |
217 | 218 |
219 | 220 |
221 |
222 | 262 |
263 | 288 |
289 |
290 | 291 | 292 | 293 | 294 | 295 | -------------------------------------------------------------------------------- /glhmm/io.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Input/output functions - Gaussian Linear Hidden Markov Model 5 | @author: Diego Vidaurre 2023 6 | """ 7 | 8 | import numpy as np 9 | import scipy.special 10 | import scipy.io 11 | import pickle 12 | import os 13 | import warnings 14 | import h5py 15 | 16 | from glhmm import glhmm 17 | from glhmm import auxiliary 18 | 19 | def load_files(files,I=None,do_only_indices=False): 20 | """ 21 | Loads data from files and returns the loaded data, indices, and individual indices for each file. 22 | """ 23 | 24 | X = [] 25 | Y = [] 26 | indices = [] 27 | indices_individual = [] 28 | sum_T = 0 29 | 30 | if I is None: 31 | I = np.arange(len(files)) 32 | elif type(I) is int: 33 | I = np.array([I]) 34 | 35 | for ij in range(I.shape[0]): 36 | 37 | j = I[ij] 38 | 39 | # if type(files[j]) is tuple: 40 | # if len(files[j][0]) > 0: # X 41 | # if files[j][0][-4:] == '.npy': 42 | # X.append(np.load(files[j][0])) 43 | # elif files[j][0][-4:] == '.txt': 44 | 45 | if files[j][-4:] == '.mat': 46 | # depending on the matlab version used to create the data, 47 | #scipy.io or h5py will be used to load them 48 | try: 49 | dat = scipy.io.loadmat(files[j]) 50 | except: 51 | dat = h5py.File(files[j],'r') 52 | 53 | 54 | elif files[j][-4:] == '.npz': 55 | dat = np.load(files[j]) 56 | 57 | if not do_only_indices: 58 | if ('X' in dat) and (not 'Y' in dat): 59 | Y.append(np.array(dat["X"])) 60 | else: 61 | if 'X' in dat: X.append(np.array(dat["X"])) 62 | Y.append(np.array(dat["Y"])) 63 | if 'indices' in dat: 64 | ind = np.array(dat['indices']) 65 | elif 'T' in dat: 66 | ind = auxiliary.make_indices_from_T(np.array(dat['T'])) 67 | else: 68 | ind = np.zeros((1,2)).astype(int) 69 | ind[0,0] = 0 70 | ind[0,1] = Y[-1].shape[0] 71 | if len(ind.shape) == 1: ind = np.expand_dims(ind,axis=0) 72 | indices_individual.append(ind) 73 | indices.append(ind + sum_T) 74 | 75 | sum_T += dat["Y"].shape[0] 76 | 77 | if not do_only_indices: 78 | if len(X) > 0: X = np.concatenate(X) 79 | Y = np.concatenate(Y) 80 | indices = np.concatenate(indices) 81 | if len(indices.shape) == 1: indices = np.expand_dims(indices,axis=0) 82 | if len(X) == 0: X = None 83 | 84 | return X,Y,indices,indices_individual 85 | 86 | 87 | def read_flattened_hmm_mat(file): 88 | """ 89 | Reads a MATLAB file containing hidden Markov model (HMM) parameters from the HMM-MAR toolbox, 90 | and initializes a Gaussian linear hidden Markov model (GLHMM) using those parameters. 91 | """ 92 | try: 93 | hmm_mat = scipy.io.loadmat(file,simplify_cells=True) 94 | except: 95 | hmm_mat = h5py.File(file,'r') 96 | 97 | try: 98 | K = int(hmm_mat["K"]) 99 | except: 100 | hmm_mat = hmm_mat["hmm"] 101 | K = int(hmm_mat["K"]) 102 | 103 | covtype = str(hmm_mat["train"]["covtype"]) 104 | zeromean = int(hmm_mat["train"]["zeromean"]) 105 | model_mean = 'state' if not zeromean else 'no' 106 | 107 | 108 | if not zeromean: model_mean = 'state' 109 | else: model_mean = 'no' 110 | if "state_0_Mu_W" in hmm_mat: 111 | if (model_mean == 'state') and (hmm_mat["state_0_Mu_W"].shape[0] == 1): 112 | model_beta = 'no' 113 | elif hmm_mat["state_0_Mu_W"].shape[0] == 0: 114 | model_beta = 'no' 115 | else: 116 | model_beta = 'state' 117 | else: 118 | model_beta = 'no' 119 | dirichlet_diag = int(hmm_mat["train"]["DirichletDiag"]) 120 | Pstructure = np.array(hmm_mat["train"]["Pstructure"], dtype=bool) 121 | Pistructure = np.squeeze(np.array(hmm_mat["train"]["Pistructure"], dtype=bool)) 122 | shared_covmat = (covtype == 'shareddiag') or (covtype == 'sharedfull') 123 | diagonal_covmat = (covtype == 'shareddiag') or (covtype == 'diag') 124 | # Only use S if diagonal; otherwise disable to avoid the warning. 125 | connectivity = np.array(hmm_mat["train"]["S"]) if diagonal_covmat else None 126 | 127 | 128 | # detect schema 129 | is_flat = ( 130 | ("prior_Omega_Gam_rate" in hmm_mat) or 131 | ("state_0_prior_Omega_Gam_rate" in hmm_mat) or 132 | ("state_0_Mu_W" in hmm_mat) 133 | ) 134 | is_nested = (("prior" in hmm_mat) or ("state" in hmm_mat)) 135 | 136 | 137 | # prior over Omega 138 | if is_flat: 139 | if "prior_Omega_Gam_rate" in hmm_mat and "prior_Omega_Gam_shape" in hmm_mat: 140 | prior_Omega_Gam_rate = np.array(hmm_mat["prior_Omega_Gam_rate"]) 141 | prior_Omega_Gam_shape = int(np.array(hmm_mat["prior_Omega_Gam_shape"]).squeeze()) 142 | else: 143 | prior_Omega_Gam_rate = np.array(hmm_mat["state_0_prior_Omega_Gam_rate"]) 144 | prior_Omega_Gam_shape = int(np.array(hmm_mat["state_0_prior_Omega_Gam_shape"]).squeeze()) 145 | elif is_nested: 146 | if "prior" in hmm_mat and "Omega" in hmm_mat["prior"]: 147 | prior_Omega_Gam_rate = np.array(hmm_mat["prior"]["Omega"]["Gam_rate"]) 148 | prior_Omega_Gam_shape = int(np.array(hmm_mat["prior"]["Omega"]["Gam_shape"]).squeeze()) 149 | else: 150 | prior_Omega_Gam_rate = np.array(hmm_mat["state"][0]["prior"]["Omega"]["Gam_rate"]) 151 | prior_Omega_Gam_shape = int(np.array(hmm_mat["state"][0]["prior"]["Omega"]["Gam_shape"]).squeeze()) 152 | else: 153 | raise KeyError("Unrecognized HMM .mat schema.") 154 | 155 | 156 | if diagonal_covmat: prior_Omega_Gam_rate = np.squeeze(prior_Omega_Gam_rate) 157 | q = prior_Omega_Gam_rate.shape[0] 158 | 159 | # p 160 | if is_flat: 161 | p = hmm_mat["state_0_Mu_W"].shape[0] if "state_0_Mu_W" in hmm_mat else 0 162 | else: 163 | if "state" in hmm_mat and "W" in hmm_mat["state"][0] and "Mu_W" in hmm_mat["state"][0]["W"]: 164 | p = hmm_mat["state"][0]["W"]["Mu_W"].shape[0] 165 | else: 166 | p = 0 167 | 168 | hmm = glhmm.glhmm( 169 | K=K, 170 | covtype=covtype, 171 | model_mean=model_mean, 172 | model_beta=model_beta, 173 | dirichlet_diag=dirichlet_diag, 174 | connectivity=connectivity, 175 | Pstructure=Pstructure, 176 | Pistructure=Pistructure 177 | ) 178 | 179 | # mean 180 | if model_mean == 'state': 181 | hmm.mean = [] 182 | for k in range(K): 183 | hmm.mean.append({}) 184 | if is_flat: 185 | Sigma_W = np.squeeze(hmm_mat[f"state_{k}_S_W"]) 186 | Mu_W = np.squeeze(hmm_mat[f"state_{k}_Mu_W"]) 187 | else: 188 | Sigma_W = np.squeeze(hmm_mat["state"][k]["W"]["S_W"]) 189 | Mu_W = np.squeeze(hmm_mat["state"][k]["W"]["Mu_W"]) 190 | 191 | if model_beta == 'state': 192 | if q==1: hmm.mean[k]["Mu"] = np.array(Mu_W[0]) 193 | else: hmm.mean[k]["Mu"] = Mu_W[0,:] 194 | else: 195 | if q==1: hmm.mean[k]["Mu"] = np.array(Mu_W) 196 | else: hmm.mean[k]["Mu"] = Mu_W 197 | if diagonal_covmat: 198 | if model_beta == 'state': 199 | if q==1: hmm.mean[k]["Sigma"] = np.array([[Sigma_W[0,0]]]) 200 | else: hmm.mean[k]["Sigma"] = np.diag(Sigma_W[:,0,0]) 201 | else: 202 | if q==1: hmm.mean[k]["Sigma"] = np.array([[Sigma_W]]) 203 | hmm.mean[k]["Sigma"] = np.diag(Sigma_W) 204 | else: 205 | if q==1: np.array([[Sigma_W[0,0]]]) 206 | else: hmm.mean[k]["Sigma"] = Sigma_W[0:q,0:q] 207 | 208 | # beta 209 | if model_beta == 'state': 210 | if model_mean == 'state': j0 = 1 211 | else: j0 = 0 212 | hmm.beta = [] 213 | for k in range(K): 214 | hmm.beta.append({}) 215 | if is_flat: 216 | Sigma_W = np.array(hmm_mat[f"state_{k}_S_W"]) 217 | Mu_W = np.array(hmm_mat[f"state_{k}_Mu_W"]) 218 | else: 219 | Sigma_W = np.array(hmm_mat["state"][k]["W"]["S_W"]) 220 | Mu_W = np.array(hmm_mat["state"][k]["W"]["Mu_W"]) 221 | hmm.beta[k]["Mu"] = np.zeros((p,q)) 222 | hmm.beta[k]["Mu"][:,:] = Mu_W[j0:,:] 223 | if diagonal_covmat: 224 | hmm.beta[k]["Sigma"] = np.zeros((p,p,q)) 225 | if q==1: 226 | hmm.beta[k]["Sigma"][:,:,0] = Sigma_W[j0:,j0:] 227 | else: 228 | for j in range(q): 229 | hmm.beta[k]["Sigma"][:,:,j] = Sigma_W[j,j0:,j0:] 230 | else: 231 | hmm.beta[k]["Sigma"] = Sigma_W[(j0*q):,(j0*q):] 232 | 233 | hmm._glhmm__init_priors_sub(prior_Omega_Gam_rate,prior_Omega_Gam_shape,p,q) 234 | hmm._glhmm__update_priors() 235 | 236 | # covmatrix 237 | hmm.Sigma = [] 238 | if diagonal_covmat and shared_covmat: 239 | hmm.Sigma.append({}) 240 | hmm.Sigma[0]["rate"] = np.zeros(q) 241 | if is_flat: 242 | hmm.Sigma[0]["rate"][:] = np.array(hmm_mat["Omega_Gam_rate"]) 243 | hmm.Sigma[0]["shape"] = int(np.array(hmm_mat["Omega_Gam_shape"]).squeeze()) 244 | else: 245 | hmm.Sigma[0]["rate"][:] = np.array(hmm_mat["Omega"]["Gam_rate"]) 246 | hmm.Sigma[0]["shape"] = int(np.array(hmm_mat["Omega"]["Gam_shape"]).squeeze()) 247 | 248 | elif diagonal_covmat and not shared_covmat: 249 | for k in range(K): 250 | hmm.Sigma.append({}) 251 | hmm.Sigma[k]["rate"] = np.zeros(q) 252 | if is_flat: 253 | hmm.Sigma[k]["rate"][:] = np.array(hmm_mat[f"state_{k}_Omega_Gam_rate"]) 254 | hmm.Sigma[k]["shape"] = int(np.array(hmm_mat[f"state_{k}_Omega_Gam_shape"]).squeeze()) 255 | else: 256 | hmm.Sigma[k]["rate"][:] = np.array(hmm_mat["state"][k]["Omega"]["Gam_rate"]) 257 | hmm.Sigma[k]["shape"] = int(np.array(hmm_mat["state"][k]["Omega"]["Gam_shape"]).squeeze()) 258 | 259 | hmm.Sigma[k]["rate"][:] = hmm_mat["state"][k]["Omega"]["Gam_rate"] 260 | hmm.Sigma[k]["shape"] = int(np.array(hmm_mat["state"][k]["Omega"]["Gam_shape"])) 261 | elif (not diagonal_covmat) and shared_covmat: 262 | hmm.Sigma.append({}) 263 | if is_flat: 264 | hmm.Sigma[0]["rate"] = np.array(hmm_mat["Omega_Gam_rate"]) 265 | hmm.Sigma[0]["irate"] = np.array(hmm_mat["Omega_Gam_irate"]) 266 | hmm.Sigma[0]["shape"] = int(np.array(hmm_mat["Omega_Gam_shape"]).squeeze()) 267 | else: 268 | hmm.Sigma[0]["rate"] = np.array(hmm_mat["Omega"]["Gam_rate"]) 269 | hmm.Sigma[0]["irate"] = np.array(hmm_mat["Omega"]["Gam_irate"]) 270 | hmm.Sigma[0]["shape"] = int(np.array(hmm_mat["Omega"]["Gam_shape"]).squeeze()) 271 | 272 | else: # not diagonal_covmat and not shared_covmat 273 | for k in range(K): 274 | hmm.Sigma.append({}) 275 | if is_flat: 276 | hmm.Sigma[k]["rate"] = np.array(hmm_mat[f"state_{k}_Omega_Gam_rate"]) 277 | hmm.Sigma[k]["irate"] = np.array(hmm_mat[f"state_{k}_Omega_Gam_irate"]) 278 | hmm.Sigma[k]["shape"] = int(np.array(hmm_mat[f"state_{k}_Omega_Gam_shape"]).squeeze()) 279 | else: 280 | hmm.Sigma[k]["rate"] = np.array(hmm_mat["state"][k]["Omega"]["Gam_rate"]) 281 | hmm.Sigma[k]["irate"] = np.array(hmm_mat["state"][k]["Omega"]["Gam_irate"]) 282 | hmm.Sigma[k]["shape"] = int(np.array(hmm_mat["state"][k]["Omega"]["Gam_shape"]).squeeze()) 283 | 284 | #hmm.init_dynamics() 285 | hmm.P = np.array(hmm_mat["P"]) 286 | hmm.Pi = np.squeeze(hmm_mat["Pi"]) 287 | hmm.Dir2d_alpha = np.array(hmm_mat["Dir2d_alpha"]) 288 | hmm.Dir_alpha = np.squeeze(hmm_mat["Dir_alpha"]) 289 | 290 | hmm.trained = True 291 | 292 | return hmm 293 | 294 | 295 | def save_hmm(hmm, filename, directory=None): 296 | """ 297 | Save a glhmm object in the specified directory with the given filename. 298 | 299 | Parameters: 300 | ----------- 301 | hmm (object) 302 | The glhmm object to be saved. 303 | filename (str) 304 | The name of the file to which the object will be saved. 305 | directory (str, optional), default=None: 306 | The directory where the file will be saved. If None, saves in the current working directory. 307 | 308 | """ 309 | # Combine the directory path and filename 310 | if directory: 311 | # Ensure the directory exists, create it if not 312 | if not os.path.exists(directory): 313 | print(f"Created a folder here: {directory}") 314 | os.makedirs(directory) 315 | filepath = os.path.join(directory, filename) 316 | 317 | else: 318 | filepath = filename 319 | 320 | # Save the glhmm object to the specified file 321 | with open(filepath, 'wb') as outp: # Overwrites any existing file. 322 | pickle.dump(hmm, outp, pickle.HIGHEST_PROTOCOL) 323 | 324 | print(f"{filename} saved to: {filepath}") if directory else print(f"{filename} saved") 325 | 326 | 327 | def load_hmm(filename, directory=None): 328 | """ 329 | Load a glhmm object from the specified file. 330 | 331 | Parameters: 332 | ----------- 333 | filename (str): 334 | Name of the file containing the glhmm object. 335 | directory (str, optional), default=None: 336 | Directory where the file is located. If None, searches in the current working directory. 337 | 338 | Returns: 339 | -------- 340 | glhmm : object 341 | Loaded glhmm object. 342 | """ 343 | # Combine the directory path and filename 344 | if directory: 345 | filepath = os.path.join(directory, filename) 346 | else: 347 | filepath = filename 348 | 349 | # Check if the directory exists 350 | if directory and not os.path.exists(directory): 351 | warnings.warn(f"The specified directory '{directory}' does not exist.") 352 | 353 | # Load the glhmm object from the specified file 354 | with open(filepath, 'rb') as inp: 355 | hmm = pickle.load(inp) 356 | return hmm 357 | 358 | 359 | 360 | def save_statistics(data_dict, filename='statistics', directory=None, format='npy'): 361 | """ 362 | Save statistics data to a file in the specified directory with optional format (npy or npz). 363 | 364 | Parameters 365 | ---------- 366 | data_dict (dict): 367 | Dictionary containing statistics data to be saved. 368 | filename (str, optional), default='statistics': 369 | Name of the file. 370 | directory (str, optional), default=None: 371 | Directory path where the file will be saved (default is the current working directory). 372 | format (str, optional), default='npy': 373 | Serialization format ('npy' or 'npz'). 374 | """ 375 | 376 | # Construct the full file path 377 | if directory: 378 | # Ensure the directory exists, create it if not 379 | if not os.path.exists(directory): 380 | print(f"Created a folder here: {directory}") 381 | os.makedirs(directory) 382 | filepath = os.path.join(directory, f'{filename}.{format}') 383 | else: 384 | filepath = f'{filename}.{format}' 385 | 386 | # Save the dictionary to the file using the specified format 387 | if format == 'npy': 388 | np.save(filepath, data_dict) 389 | elif format == 'npz': 390 | np.savez(filepath, **data_dict) 391 | else: 392 | raise ValueError("Invalid format. Use 'npy' or 'npz'.") 393 | print(f"{filename}.{format} saved to: {filepath}") if directory else print(f"{filename}.{format} saved") 394 | 395 | def load_statistics(filename, directory=None): 396 | """ 397 | Load statistics data from a file. 398 | 399 | Parameters 400 | ---------- 401 | filename : str 402 | The name of the file containing the saved statistics data, with or without extension. 403 | load_directory (str, optional), default=None: 404 | The directory path where the file is located (default is the current working directory). 405 | 406 | Returns 407 | ------- 408 | data_dict : dict 409 | The dictionary containing the loaded statistics data. 410 | """ 411 | # Set default directory to current working directory if not provided 412 | directory = directory or os.getcwd() 413 | 414 | # Construct the full file path 415 | file_path = os.path.join(directory, filename) 416 | 417 | if not os.path.exists(file_path): 418 | # If the file with the given name does not exist, try adding '.npy' and '.npz' extensions 419 | file_path_npy = file_path + '.npy' 420 | file_path_npz = file_path + '.npz' 421 | 422 | if not (os.path.exists(file_path_npy) or os.path.exists(file_path_npz)): 423 | raise FileNotFoundError(f"File not found: {filename} or {filename}.npy or {filename}.npz") 424 | 425 | try: 426 | if os.path.exists(file_path): 427 | # If the file exists with the given name, use it 428 | # The .item() method extracts the single item from the loaded data. 429 | data_dict = np.load(file_path, allow_pickle=True).item() 430 | elif os.path.exists(file_path_npy): 431 | data_dict = np.load(file_path_npy, allow_pickle=True).item() 432 | elif os.path.exists(file_path_npz): 433 | loaded_data = np.load(file_path_npz, allow_pickle=True) 434 | data_dict = {key: loaded_data[key] for key in loaded_data.files} 435 | except Exception as e: 436 | raise ValueError(f"Error loading data from {filename}: {e}") 437 | 438 | return data_dict 439 | 440 | 441 | -------------------------------------------------------------------------------- /docs/_build/html/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2023 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 | h1:hover > a.headerlink, 241 | h2:hover > a.headerlink, 242 | h3:hover > a.headerlink, 243 | h4:hover > a.headerlink, 244 | h5:hover > a.headerlink, 245 | h6:hover > a.headerlink, 246 | dt:hover > a.headerlink, 247 | caption:hover > a.headerlink, 248 | p.caption:hover > a.headerlink, 249 | div.code-block-caption:hover > a.headerlink { 250 | visibility: visible; 251 | } 252 | 253 | div.body p.caption { 254 | text-align: inherit; 255 | } 256 | 257 | div.body td { 258 | text-align: left; 259 | } 260 | 261 | .first { 262 | margin-top: 0 !important; 263 | } 264 | 265 | p.rubric { 266 | margin-top: 30px; 267 | font-weight: bold; 268 | } 269 | 270 | img.align-left, figure.align-left, .figure.align-left, object.align-left { 271 | clear: left; 272 | float: left; 273 | margin-right: 1em; 274 | } 275 | 276 | img.align-right, figure.align-right, .figure.align-right, object.align-right { 277 | clear: right; 278 | float: right; 279 | margin-left: 1em; 280 | } 281 | 282 | img.align-center, figure.align-center, .figure.align-center, object.align-center { 283 | display: block; 284 | margin-left: auto; 285 | margin-right: auto; 286 | } 287 | 288 | img.align-default, figure.align-default, .figure.align-default { 289 | display: block; 290 | margin-left: auto; 291 | margin-right: auto; 292 | } 293 | 294 | .align-left { 295 | text-align: left; 296 | } 297 | 298 | .align-center { 299 | text-align: center; 300 | } 301 | 302 | .align-default { 303 | text-align: center; 304 | } 305 | 306 | .align-right { 307 | text-align: right; 308 | } 309 | 310 | /* -- sidebars -------------------------------------------------------------- */ 311 | 312 | div.sidebar, 313 | aside.sidebar { 314 | margin: 0 0 0.5em 1em; 315 | border: 1px solid #ddb; 316 | padding: 7px; 317 | background-color: #ffe; 318 | width: 40%; 319 | float: right; 320 | clear: right; 321 | overflow-x: auto; 322 | } 323 | 324 | p.sidebar-title { 325 | font-weight: bold; 326 | } 327 | 328 | nav.contents, 329 | aside.topic, 330 | div.admonition, div.topic, blockquote { 331 | clear: left; 332 | } 333 | 334 | /* -- topics ---------------------------------------------------------------- */ 335 | 336 | nav.contents, 337 | aside.topic, 338 | div.topic { 339 | border: 1px solid #ccc; 340 | padding: 7px; 341 | margin: 10px 0 10px 0; 342 | } 343 | 344 | p.topic-title { 345 | font-size: 1.1em; 346 | font-weight: bold; 347 | margin-top: 10px; 348 | } 349 | 350 | /* -- admonitions ----------------------------------------------------------- */ 351 | 352 | div.admonition { 353 | margin-top: 10px; 354 | margin-bottom: 10px; 355 | padding: 7px; 356 | } 357 | 358 | div.admonition dt { 359 | font-weight: bold; 360 | } 361 | 362 | p.admonition-title { 363 | margin: 0px 10px 5px 0px; 364 | font-weight: bold; 365 | } 366 | 367 | div.body p.centered { 368 | text-align: center; 369 | margin-top: 25px; 370 | } 371 | 372 | /* -- content of sidebars/topics/admonitions -------------------------------- */ 373 | 374 | div.sidebar > :last-child, 375 | aside.sidebar > :last-child, 376 | nav.contents > :last-child, 377 | aside.topic > :last-child, 378 | div.topic > :last-child, 379 | div.admonition > :last-child { 380 | margin-bottom: 0; 381 | } 382 | 383 | div.sidebar::after, 384 | aside.sidebar::after, 385 | nav.contents::after, 386 | aside.topic::after, 387 | div.topic::after, 388 | div.admonition::after, 389 | blockquote::after { 390 | display: block; 391 | content: ''; 392 | clear: both; 393 | } 394 | 395 | /* -- tables ---------------------------------------------------------------- */ 396 | 397 | table.docutils { 398 | margin-top: 10px; 399 | margin-bottom: 10px; 400 | border: 0; 401 | border-collapse: collapse; 402 | } 403 | 404 | table.align-center { 405 | margin-left: auto; 406 | margin-right: auto; 407 | } 408 | 409 | table.align-default { 410 | margin-left: auto; 411 | margin-right: auto; 412 | } 413 | 414 | table caption span.caption-number { 415 | font-style: italic; 416 | } 417 | 418 | table caption span.caption-text { 419 | } 420 | 421 | table.docutils td, table.docutils th { 422 | padding: 1px 8px 1px 5px; 423 | border-top: 0; 424 | border-left: 0; 425 | border-right: 0; 426 | border-bottom: 1px solid #aaa; 427 | } 428 | 429 | th { 430 | text-align: left; 431 | padding-right: 5px; 432 | } 433 | 434 | table.citation { 435 | border-left: solid 1px gray; 436 | margin-left: 1px; 437 | } 438 | 439 | table.citation td { 440 | border-bottom: none; 441 | } 442 | 443 | th > :first-child, 444 | td > :first-child { 445 | margin-top: 0px; 446 | } 447 | 448 | th > :last-child, 449 | td > :last-child { 450 | margin-bottom: 0px; 451 | } 452 | 453 | /* -- figures --------------------------------------------------------------- */ 454 | 455 | div.figure, figure { 456 | margin: 0.5em; 457 | padding: 0.5em; 458 | } 459 | 460 | div.figure p.caption, figcaption { 461 | padding: 0.3em; 462 | } 463 | 464 | div.figure p.caption span.caption-number, 465 | figcaption span.caption-number { 466 | font-style: italic; 467 | } 468 | 469 | div.figure p.caption span.caption-text, 470 | figcaption span.caption-text { 471 | } 472 | 473 | /* -- field list styles ----------------------------------------------------- */ 474 | 475 | table.field-list td, table.field-list th { 476 | border: 0 !important; 477 | } 478 | 479 | .field-list ul { 480 | margin: 0; 481 | padding-left: 1em; 482 | } 483 | 484 | .field-list p { 485 | margin: 0; 486 | } 487 | 488 | .field-name { 489 | -moz-hyphens: manual; 490 | -ms-hyphens: manual; 491 | -webkit-hyphens: manual; 492 | hyphens: manual; 493 | } 494 | 495 | /* -- hlist styles ---------------------------------------------------------- */ 496 | 497 | table.hlist { 498 | margin: 1em 0; 499 | } 500 | 501 | table.hlist td { 502 | vertical-align: top; 503 | } 504 | 505 | /* -- object description styles --------------------------------------------- */ 506 | 507 | .sig { 508 | font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; 509 | } 510 | 511 | .sig-name, code.descname { 512 | background-color: transparent; 513 | font-weight: bold; 514 | } 515 | 516 | .sig-name { 517 | font-size: 1.1em; 518 | } 519 | 520 | code.descname { 521 | font-size: 1.2em; 522 | } 523 | 524 | .sig-prename, code.descclassname { 525 | background-color: transparent; 526 | } 527 | 528 | .optional { 529 | font-size: 1.3em; 530 | } 531 | 532 | .sig-paren { 533 | font-size: larger; 534 | } 535 | 536 | .sig-param.n { 537 | font-style: italic; 538 | } 539 | 540 | /* C++ specific styling */ 541 | 542 | .sig-inline.c-texpr, 543 | .sig-inline.cpp-texpr { 544 | font-family: unset; 545 | } 546 | 547 | .sig.c .k, .sig.c .kt, 548 | .sig.cpp .k, .sig.cpp .kt { 549 | color: #0033B3; 550 | } 551 | 552 | .sig.c .m, 553 | .sig.cpp .m { 554 | color: #1750EB; 555 | } 556 | 557 | .sig.c .s, .sig.c .sc, 558 | .sig.cpp .s, .sig.cpp .sc { 559 | color: #067D17; 560 | } 561 | 562 | 563 | /* -- other body styles ----------------------------------------------------- */ 564 | 565 | ol.arabic { 566 | list-style: decimal; 567 | } 568 | 569 | ol.loweralpha { 570 | list-style: lower-alpha; 571 | } 572 | 573 | ol.upperalpha { 574 | list-style: upper-alpha; 575 | } 576 | 577 | ol.lowerroman { 578 | list-style: lower-roman; 579 | } 580 | 581 | ol.upperroman { 582 | list-style: upper-roman; 583 | } 584 | 585 | :not(li) > ol > li:first-child > :first-child, 586 | :not(li) > ul > li:first-child > :first-child { 587 | margin-top: 0px; 588 | } 589 | 590 | :not(li) > ol > li:last-child > :last-child, 591 | :not(li) > ul > li:last-child > :last-child { 592 | margin-bottom: 0px; 593 | } 594 | 595 | ol.simple ol p, 596 | ol.simple ul p, 597 | ul.simple ol p, 598 | ul.simple ul p { 599 | margin-top: 0; 600 | } 601 | 602 | ol.simple > li:not(:first-child) > p, 603 | ul.simple > li:not(:first-child) > p { 604 | margin-top: 0; 605 | } 606 | 607 | ol.simple p, 608 | ul.simple p { 609 | margin-bottom: 0; 610 | } 611 | 612 | aside.footnote > span, 613 | div.citation > span { 614 | float: left; 615 | } 616 | aside.footnote > span:last-of-type, 617 | div.citation > span:last-of-type { 618 | padding-right: 0.5em; 619 | } 620 | aside.footnote > p { 621 | margin-left: 2em; 622 | } 623 | div.citation > p { 624 | margin-left: 4em; 625 | } 626 | aside.footnote > p:last-of-type, 627 | div.citation > p:last-of-type { 628 | margin-bottom: 0em; 629 | } 630 | aside.footnote > p:last-of-type:after, 631 | div.citation > p:last-of-type:after { 632 | content: ""; 633 | clear: both; 634 | } 635 | 636 | dl.field-list { 637 | display: grid; 638 | grid-template-columns: fit-content(30%) auto; 639 | } 640 | 641 | dl.field-list > dt { 642 | font-weight: bold; 643 | word-break: break-word; 644 | padding-left: 0.5em; 645 | padding-right: 5px; 646 | } 647 | 648 | dl.field-list > dd { 649 | padding-left: 0.5em; 650 | margin-top: 0em; 651 | margin-left: 0em; 652 | margin-bottom: 0em; 653 | } 654 | 655 | dl { 656 | margin-bottom: 15px; 657 | } 658 | 659 | dd > :first-child { 660 | margin-top: 0px; 661 | } 662 | 663 | dd ul, dd table { 664 | margin-bottom: 10px; 665 | } 666 | 667 | dd { 668 | margin-top: 3px; 669 | margin-bottom: 10px; 670 | margin-left: 30px; 671 | } 672 | 673 | dl > dd:last-child, 674 | dl > dd:last-child > :last-child { 675 | margin-bottom: 0; 676 | } 677 | 678 | dt:target, span.highlighted { 679 | background-color: #fbe54e; 680 | } 681 | 682 | rect.highlighted { 683 | fill: #fbe54e; 684 | } 685 | 686 | dl.glossary dt { 687 | font-weight: bold; 688 | font-size: 1.1em; 689 | } 690 | 691 | .versionmodified { 692 | font-style: italic; 693 | } 694 | 695 | .system-message { 696 | background-color: #fda; 697 | padding: 5px; 698 | border: 3px solid red; 699 | } 700 | 701 | .footnote:target { 702 | background-color: #ffa; 703 | } 704 | 705 | .line-block { 706 | display: block; 707 | margin-top: 1em; 708 | margin-bottom: 1em; 709 | } 710 | 711 | .line-block .line-block { 712 | margin-top: 0; 713 | margin-bottom: 0; 714 | margin-left: 1.5em; 715 | } 716 | 717 | .guilabel, .menuselection { 718 | font-family: sans-serif; 719 | } 720 | 721 | .accelerator { 722 | text-decoration: underline; 723 | } 724 | 725 | .classifier { 726 | font-style: oblique; 727 | } 728 | 729 | .classifier:before { 730 | font-style: normal; 731 | margin: 0 0.5em; 732 | content: ":"; 733 | display: inline-block; 734 | } 735 | 736 | abbr, acronym { 737 | border-bottom: dotted 1px; 738 | cursor: help; 739 | } 740 | 741 | /* -- code displays --------------------------------------------------------- */ 742 | 743 | pre { 744 | overflow: auto; 745 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 746 | } 747 | 748 | pre, div[class*="highlight-"] { 749 | clear: both; 750 | } 751 | 752 | span.pre { 753 | -moz-hyphens: none; 754 | -ms-hyphens: none; 755 | -webkit-hyphens: none; 756 | hyphens: none; 757 | white-space: nowrap; 758 | } 759 | 760 | div[class*="highlight-"] { 761 | margin: 1em 0; 762 | } 763 | 764 | td.linenos pre { 765 | border: 0; 766 | background-color: transparent; 767 | color: #aaa; 768 | } 769 | 770 | table.highlighttable { 771 | display: block; 772 | } 773 | 774 | table.highlighttable tbody { 775 | display: block; 776 | } 777 | 778 | table.highlighttable tr { 779 | display: flex; 780 | } 781 | 782 | table.highlighttable td { 783 | margin: 0; 784 | padding: 0; 785 | } 786 | 787 | table.highlighttable td.linenos { 788 | padding-right: 0.5em; 789 | } 790 | 791 | table.highlighttable td.code { 792 | flex: 1; 793 | overflow: hidden; 794 | } 795 | 796 | .highlight .hll { 797 | display: block; 798 | } 799 | 800 | div.highlight pre, 801 | table.highlighttable pre { 802 | margin: 0; 803 | } 804 | 805 | div.code-block-caption + div { 806 | margin-top: 0; 807 | } 808 | 809 | div.code-block-caption { 810 | margin-top: 1em; 811 | padding: 2px 5px; 812 | font-size: small; 813 | } 814 | 815 | div.code-block-caption code { 816 | background-color: transparent; 817 | } 818 | 819 | table.highlighttable td.linenos, 820 | span.linenos, 821 | div.highlight span.gp { /* gp: Generic.Prompt */ 822 | user-select: none; 823 | -webkit-user-select: text; /* Safari fallback only */ 824 | -webkit-user-select: none; /* Chrome/Safari */ 825 | -moz-user-select: none; /* Firefox */ 826 | -ms-user-select: none; /* IE10+ */ 827 | } 828 | 829 | div.code-block-caption span.caption-number { 830 | padding: 0.1em 0.3em; 831 | font-style: italic; 832 | } 833 | 834 | div.code-block-caption span.caption-text { 835 | } 836 | 837 | div.literal-block-wrapper { 838 | margin: 1em 0; 839 | } 840 | 841 | code.xref, a code { 842 | background-color: transparent; 843 | font-weight: bold; 844 | } 845 | 846 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 847 | background-color: transparent; 848 | } 849 | 850 | .viewcode-link { 851 | float: right; 852 | } 853 | 854 | .viewcode-back { 855 | float: right; 856 | font-family: sans-serif; 857 | } 858 | 859 | div.viewcode-block:target { 860 | margin: -1px -10px; 861 | padding: 0 10px; 862 | } 863 | 864 | /* -- math display ---------------------------------------------------------- */ 865 | 866 | img.math { 867 | vertical-align: middle; 868 | } 869 | 870 | div.body div.math p { 871 | text-align: center; 872 | } 873 | 874 | span.eqno { 875 | float: right; 876 | } 877 | 878 | span.eqno a.headerlink { 879 | position: absolute; 880 | z-index: 1; 881 | } 882 | 883 | div.math:hover a.headerlink { 884 | visibility: visible; 885 | } 886 | 887 | /* -- printout stylesheet --------------------------------------------------- */ 888 | 889 | @media print { 890 | div.document, 891 | div.documentwrapper, 892 | div.bodywrapper { 893 | margin: 0 !important; 894 | width: 100%; 895 | } 896 | 897 | div.sphinxsidebar, 898 | div.related, 899 | div.footer, 900 | #top-link { 901 | display: none; 902 | } 903 | } --------------------------------------------------------------------------------