├── .gitignore ├── .gitmodules ├── .readthedocs.yaml ├── Dockerfile ├── LICENSE.txt ├── README.md ├── demos ├── simple_demo.py └── tutorial.ipynb ├── docs ├── Makefile ├── build │ ├── doctrees │ │ ├── advanced.doctree │ │ ├── api.doctree │ │ ├── environment.pickle │ │ ├── generated │ │ │ ├── pyspi.calculator.Calculator.doctree │ │ │ └── pyspi.data.Data.doctree │ │ ├── index.doctree │ │ ├── statistics.doctree │ │ └── usage.doctree │ └── html │ │ ├── .buildinfo │ │ ├── _sources │ │ ├── advanced.rst.txt │ │ ├── api.rst.txt │ │ ├── generated │ │ │ ├── pyspi.calculator.Calculator.rst.txt │ │ │ └── pyspi.data.Data.rst.txt │ │ ├── index.rst.txt │ │ ├── statistics.rst.txt │ │ └── usage.rst.txt │ │ ├── _static │ │ ├── basic.css │ │ ├── css │ │ │ ├── badge_only.css │ │ │ ├── fonts │ │ │ │ ├── Roboto-Slab-Bold.woff │ │ │ │ ├── Roboto-Slab-Bold.woff2 │ │ │ │ ├── Roboto-Slab-Regular.woff │ │ │ │ ├── Roboto-Slab-Regular.woff2 │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ ├── fontawesome-webfont.woff2 │ │ │ │ ├── lato-bold-italic.woff │ │ │ │ ├── lato-bold-italic.woff2 │ │ │ │ ├── lato-bold.woff │ │ │ │ ├── lato-bold.woff2 │ │ │ │ ├── lato-normal-italic.woff │ │ │ │ ├── lato-normal-italic.woff2 │ │ │ │ ├── lato-normal.woff │ │ │ │ └── lato-normal.woff2 │ │ │ └── theme.css │ │ ├── doctools.js │ │ ├── documentation_options.js │ │ ├── file.png │ │ ├── jquery-3.5.1.js │ │ ├── jquery.js │ │ ├── js │ │ │ ├── badge_only.js │ │ │ ├── html5shiv-printshiv.min.js │ │ │ ├── html5shiv.min.js │ │ │ └── theme.js │ │ ├── language_data.js │ │ ├── minus.png │ │ ├── plus.png │ │ ├── pygments.css │ │ ├── searchtools.js │ │ ├── underscore-1.13.1.js │ │ └── underscore.js │ │ ├── advanced.html │ │ ├── api.html │ │ ├── generated │ │ ├── pyspi.calculator.Calculator.html │ │ └── pyspi.data.Data.html │ │ ├── genindex.html │ │ ├── index.html │ │ ├── objects.inv │ │ ├── search.html │ │ ├── searchindex.js │ │ ├── statistics.html │ │ └── usage.html ├── make.bat ├── requirements.txt └── source │ ├── _build │ ├── doctrees │ │ ├── advanced.doctree │ │ ├── api.doctree │ │ ├── environment.pickle │ │ ├── generated │ │ │ ├── pyspi.calculator.Calculator.doctree │ │ │ └── pyspi.data.Data.doctree │ │ ├── index.doctree │ │ ├── statistics.doctree │ │ └── usage.doctree │ └── html │ │ ├── .buildinfo │ │ ├── _sources │ │ ├── advanced.rst.txt │ │ ├── api.rst.txt │ │ ├── generated │ │ │ ├── pyspi.calculator.Calculator.rst.txt │ │ │ └── pyspi.data.Data.rst.txt │ │ ├── index.rst.txt │ │ ├── statistics.rst.txt │ │ └── usage.rst.txt │ │ ├── _static │ │ ├── basic.css │ │ ├── css │ │ │ ├── badge_only.css │ │ │ ├── fonts │ │ │ │ ├── Roboto-Slab-Bold.woff │ │ │ │ ├── Roboto-Slab-Bold.woff2 │ │ │ │ ├── Roboto-Slab-Regular.woff │ │ │ │ ├── Roboto-Slab-Regular.woff2 │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ ├── fontawesome-webfont.woff2 │ │ │ │ ├── lato-bold-italic.woff │ │ │ │ ├── lato-bold-italic.woff2 │ │ │ │ ├── lato-bold.woff │ │ │ │ ├── lato-bold.woff2 │ │ │ │ ├── lato-normal-italic.woff │ │ │ │ ├── lato-normal-italic.woff2 │ │ │ │ ├── lato-normal.woff │ │ │ │ └── lato-normal.woff2 │ │ │ └── theme.css │ │ ├── doctools.js │ │ ├── documentation_options.js │ │ ├── file.png │ │ ├── jquery-3.5.1.js │ │ ├── jquery.js │ │ ├── js │ │ │ ├── badge_only.js │ │ │ ├── html5shiv-printshiv.min.js │ │ │ ├── html5shiv.min.js │ │ │ └── theme.js │ │ ├── language_data.js │ │ ├── minus.png │ │ ├── plus.png │ │ ├── pygments.css │ │ ├── searchtools.js │ │ ├── underscore-1.13.1.js │ │ └── underscore.js │ │ ├── advanced.html │ │ ├── api.html │ │ ├── generated │ │ ├── pyspi.calculator.Calculator.html │ │ └── pyspi.data.Data.html │ │ ├── genindex.html │ │ ├── index.html │ │ ├── objects.inv │ │ ├── search.html │ │ ├── searchindex.js │ │ ├── statistics.html │ │ └── usage.html │ ├── advanced.rst │ ├── api.rst │ ├── conf.py │ ├── faq.rst │ ├── generated │ ├── pyspi.calculator.Calculator.rst │ └── pyspi.data.Data.rst │ ├── img │ ├── pyspi_scaling_heatmaps.png │ └── pyspi_scaling_line_plots.png │ ├── index.rst │ ├── installation.rst │ ├── statistics.rst │ └── usage.rst ├── img └── pyspi_logo.png ├── pyspi ├── __init__.py ├── base.py ├── calculator.py ├── config.yaml ├── data.py ├── data │ ├── cml.npy │ └── forex.npy ├── fabfour_config.yaml ├── fast_config.yaml ├── lib │ ├── PhiToolbox │ │ ├── .gitattributes │ │ ├── Phi │ │ │ ├── __init__.py │ │ │ ├── phi_G_Gauss.m │ │ │ ├── phi_G_Gauss_AL.m │ │ │ ├── phi_G_Gauss_LBFGS.m │ │ │ ├── phi_Gauss.m │ │ │ ├── phi_comp.m │ │ │ ├── phi_comp_probs.m │ │ │ └── phi_star_Gauss.m │ │ ├── __init__.py │ │ └── utility │ │ │ ├── Gauss │ │ │ ├── Cov_comp.m │ │ │ ├── Cov_cond.m │ │ │ ├── H_gauss.m │ │ │ ├── __init__.py │ │ │ └── logdet.m │ │ │ ├── I_s_I_s_d.m │ │ │ ├── __init__.py │ │ │ └── data_to_probs.m │ ├── __init__.py │ └── jidt │ │ ├── __init__.py │ │ ├── build.xml │ │ ├── infodynamics.jar │ │ ├── license-gplv3.txt │ │ ├── readme.txt │ │ └── version-1.5.txt ├── sonnet_config.yaml ├── statistics │ ├── __init__.py │ ├── basic.py │ ├── causal.py │ ├── distance.py │ ├── infotheory.py │ ├── misc.py │ ├── spectral.py │ └── wavelet.py └── utils.py ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | pyspi.egg-info 2 | pyspi/__pycache__ 3 | **/__pycache__/** 4 | dist 5 | *.pkl 6 | *.log 7 | *.bkp 8 | .vscode 9 | build 10 | octave-workspace 11 | readme.html 12 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "pyspi/lib/tigramite"] 2 | path = pyspi/lib/tigramite 3 | url = https://github.com/jakobrunge/tigramite.git 4 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | # Set the version of Python and other tools you might need 4 | build: 5 | os: ubuntu-20.04 6 | tools: 7 | python: '3.9' 8 | 9 | # Build documentation in the docs/ directory with Sphinx 10 | sphinx: 11 | configuration: docs/source/conf.py 12 | 13 | # If using Sphinx, optionally build your docs in additional formats such as PDF 14 | formats: all 15 | 16 | # Optionally set the version of Python and requirements required to build your docs 17 | python: 18 | install: 19 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Debian linux distribution with python 3.9 2 | FROM --platform=linux/amd64 python:3.9-slim-buster 3 | 4 | # Set the working directory 5 | WORKDIR /pyspi_project 6 | 7 | # Copy the current directory contents into the container 8 | COPY . . 9 | 10 | # Update the package index and install essential packages 11 | RUN apt-get update && apt-get install -y build-essential octave 12 | 13 | # Upgrade pip and setuptools 14 | RUN pip install --upgrade pip setuptools 15 | 16 | # Install any needed packages specified in requirements.txt 17 | RUN pip install --no-cache-dir -r requirements.txt && \ 18 | python setup.py install 19 | 20 | # Make port 80 available to communicate with other containters if needed 21 | # EXPOSE 80 22 | 23 | # Run app.py when the container launches 24 | CMD ["python"] 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NOTE: This repo has been archived, please use the maintained version at https://github.com/DynamicsAndNeuralSystems 2 | -------------------------------------------------------------------------------- /demos/simple_demo.py: -------------------------------------------------------------------------------- 1 | """ This simple demo will show you how to quickly get started with PySPI. 2 | """ 3 | import numpy as np 4 | from pyspi.calculator import Calculator 5 | import matplotlib.pyplot as plt 6 | 7 | dataset = np.random.randn( 8 | 3, 1000 9 | ) # Generate multivariate data with 3 processes and 100 observations 10 | 11 | calc = Calculator( 12 | dataset=dataset, fast=True 13 | ) # Instantiate the calculator with only fast SPIs (set fast=False to compute all SPIs) 14 | 15 | calc.compute() # Compute all SPIs 16 | 17 | print(f"Obtained results table of shape {calc.table.shape}:") 18 | print(calc.table) # Print the table of results. 19 | 20 | R = calc.table[ 21 | "cov_EmpiricalCovariance" 22 | ] # Extract the results for an individual SPI (we're using covariance here) 23 | 24 | plt.imshow(R) 25 | plt.colorbar() 26 | plt.ylabel("Process") 27 | plt.xlabel("Process") 28 | plt.show() 29 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/build/doctrees/advanced.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/doctrees/advanced.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/api.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/doctrees/api.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/build/doctrees/generated/pyspi.calculator.Calculator.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/doctrees/generated/pyspi.calculator.Calculator.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/generated/pyspi.data.Data.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/doctrees/generated/pyspi.data.Data.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/statistics.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/doctrees/statistics.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/usage.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/doctrees/usage.doctree -------------------------------------------------------------------------------- /docs/build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 156e67aeef1241dfc58561413874e38d 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/build/html/_sources/advanced.rst.txt: -------------------------------------------------------------------------------- 1 | Advanced 2 | ======== 3 | 4 | The Data object 5 | --------------------- 6 | 7 | The MTS data is contained within the :class:`~pyspi.data.Data` object, along with preprocessed properties of the MTS that allows us to efficiently compute the methods. 8 | If you want more control over how the MTS are treated upon input, you can directly instantiate a :class:`~pyspi.data.Data` object for inputting to the calculator: 9 | 10 | .. code-block:: 11 | 12 | from pyspi.data import Data 13 | from pyspi.calculator import Calculator 14 | import numpy as np 15 | 16 | M = 10 # Number of processes 17 | T = 1000 # Number of observations 18 | 19 | z = np.random.rand(M,T) 20 | 21 | # The dim_order argument specifies which dimension is a process (p) and an observation (s). 22 | # The normalise argument specifies if we should z-score the data. 23 | dataset = Data(data=z,dim_order='ps',normalise=False) 24 | 25 | calc = Calculator(dataset=dataset) 26 | 27 | 28 | Using a reduced SPI set 29 | ----------------------- 30 | 31 | You can easily use a subset of the SPIs by copying a version of the :code:`config.yaml` file to a local directory and removing those you don't want the calculator to compute. 32 | First, copy the :code:`config.yaml` file to your workspace: 33 | 34 | .. code-block:: console 35 | 36 | $ cp /pyspi/config.yaml myconfig.yaml 37 | 38 | Once you've got a local version, edit the :code:`myconfig.yaml` file to remove any SPIs you're not interested in. 39 | A minimal configuration file might look like the following if you're only interested in computing a covariance matrix using the maximum likelihood estimator: 40 | 41 | .. code-block:: 42 | 43 | # Basic statistics 44 | .statistics.basic: 45 | # Covariance 46 | covariance: 47 | # Maximum likehood estimator 48 | - estimator: EmpiricalCovariance 49 | 50 | Now, when you instantiate the calculator, instead of using the default :code:`config.yaml`, you can input your bespoke configuration file: 51 | 52 | .. code-block:: 53 | 54 | from pyspi.calculator import Calculator 55 | 56 | calc = Caculator(dataset=dataset,configfile='myconfig.yaml') 57 | 58 | Then use the calculator as normal (see :ref:`Usage`). 59 | 60 | .. note:: 61 | We have provided a detailed list of many of the statistics included in this toolkit (and the configuration file) in the Supplementary Material of our `preprint `_, and will include an up-to-date list of statistics in this documentation shortly. 62 | However, if you have any questions about a particular implementation, do not hesitate to `contact me `_ for any assistance. 63 | 64 | Using the toolkit without Octave 65 | -------------------------------- 66 | 67 | If you do not wish to first install Octave before using the toolkit, remove the yaml entries for :code:`integrated_information` in the :code:`config.yaml` file (see :ref:`Using a reduced SPI set`). -------------------------------------------------------------------------------- /docs/build/html/_sources/api.rst.txt: -------------------------------------------------------------------------------- 1 | API 2 | === 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | pyspi.calculator.Calculator 8 | pyspi.data.Data -------------------------------------------------------------------------------- /docs/build/html/_sources/generated/pyspi.calculator.Calculator.rst.txt: -------------------------------------------------------------------------------- 1 | pyspi.calculator.Calculator 2 | =========================== 3 | 4 | .. currentmodule:: pyspi.calculator 5 | 6 | .. autoclass:: Calculator 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | .. rubric:: Methods 13 | 14 | .. autosummary:: 15 | 16 | ~Calculator.__init__ 17 | ~Calculator.compute 18 | ~Calculator.getstatlabels 19 | ~Calculator.load_dataset 20 | ~Calculator.set_group 21 | 22 | 23 | 24 | 25 | 26 | .. rubric:: Attributes 27 | 28 | .. autosummary:: 29 | 30 | ~Calculator.dataset 31 | ~Calculator.group 32 | ~Calculator.group_name 33 | ~Calculator.labels 34 | ~Calculator.n_spis 35 | ~Calculator.name 36 | ~Calculator.spis 37 | ~Calculator.table 38 | 39 | -------------------------------------------------------------------------------- /docs/build/html/_sources/generated/pyspi.data.Data.rst.txt: -------------------------------------------------------------------------------- 1 | pyspi.data.Data 2 | =============== 3 | 4 | .. currentmodule:: pyspi.data 5 | 6 | .. autoclass:: Data 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | .. rubric:: Methods 13 | 14 | .. autosummary:: 15 | 16 | ~Data.__init__ 17 | ~Data.add_process 18 | ~Data.convert_to_numpy 19 | ~Data.remove_process 20 | ~Data.set_data 21 | ~Data.to_numpy 22 | 23 | 24 | 25 | 26 | 27 | .. rubric:: Attributes 28 | 29 | .. autosummary:: 30 | 31 | ~Data.name 32 | ~Data.procnames 33 | 34 | -------------------------------------------------------------------------------- /docs/build/html/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | Welcome to PySPI's documentation! 2 | =================================== 3 | 4 | **PySPI** (/pie'spy/) is a Python library for simultaneously evaluating hundreds of pairwise interactions directly from multivariate time-series data. 5 | 6 | It provides easy access to over 250 methods for evaluating the relationship between pairs of time series, from simple statistics (like correlation coefficients) to advanced multi-step algorithms (like Granger causality). 7 | 8 | Check out the :doc:`usage` section for further information, including :ref:`Installation` instructions. 9 | 10 | .. note:: 11 | 12 | This documentation and project is under active development. 13 | 14 | Contents 15 | -------- 16 | 17 | .. toctree:: 18 | 19 | usage 20 | advanced 21 | api -------------------------------------------------------------------------------- /docs/build/html/_sources/statistics.rst.txt: -------------------------------------------------------------------------------- 1 | List of methods 2 | =========================== 3 | 4 | The full default set of over 250 pairwise interactions are produced by running all of the code files below. 5 | In our default statistics set, most functions are run with multiple input parameters. 6 | 7 | Basic statistics 8 | ---------------- 9 | 10 | In this section, we detail SPIs that are traditional techniques for performing statistical inference in bivariate systems. 11 | 12 | .. list-table:: 13 | :widths: 25 25 50 14 | :header-rows: 1 15 | 16 | * - Method name 17 | - Description 18 | - Identifier 19 | * - :code:`covariance` 20 | - Covariance matrix 21 | - :code:`cov` 22 | * - :code:`precision` 23 | - Precision matrix 24 | - :code:`prec` 25 | * - :code:`spearmanr` 26 | - Spearman correlation 27 | - :code:`spearmanr` 28 | 29 | Distance similarity 30 | ------------------- 31 | 32 | In this section, we detail SPIs that we have categorized as distance-based similarity measures in that they 33 | aim to establish statistical similarity or independence based on the pairwise distance between bivariate 34 | observations 35 | 36 | Causal indices 37 | -------------- 38 | 39 | In this section, we detail the 10 SPIs that are derived from causal inference models. 40 | 41 | Information Theory 42 | ------------------ 43 | 44 | The pairwise measures that we employ from information theory are either intended to operate on serially independent observations (e.g., joint entropy and mutual information) or bivariate time series (e.g., 45 | transfer entropy and stochastic interaction). 46 | 47 | Spectral measures 48 | ----------------- 49 | 50 | Spectral SPIs are computed in the frequency or time-frequency domain, using either Fourier or wavelet 51 | transformations to derive spectral matrices. 52 | 53 | Miscellaneous 54 | ------------- 55 | 56 | A small number of methods do not fit squarely into any category listed above, and so we place them 57 | in a 'miscellaneous' category -------------------------------------------------------------------------------- /docs/build/html/_sources/usage.rst.txt: -------------------------------------------------------------------------------- 1 | Usage 2 | ===== 3 | 4 | Pre-installation 5 | ---------------- 6 | 7 | The code requires GNU's `Octave `_ by default, which is freely available on all popular operating systems. 8 | See the `installation instructions `_ to find out how to install Octave on your system. 9 | 10 | .. note:: 11 | You can safely install `PySPI` without first installing Octave but you will not have access to the `Integrated Information Theory` statistics, see :ref:`Using the toolkit without Octave`. 12 | 13 | While you can also install `PySPI` outside of a `conda `_ environment, it depends on a lot of user packages that may make managing dependencies quite difficult. 14 | So, we would also recommend installing `PySPI` in a conda environment. 15 | After `installing conda `_, create a new environment for using the toolkit: 16 | 17 | .. code-block:: console 18 | 19 | $ conda create -n pyspi python=3.9.0 20 | $ conda activate pyspi 21 | 22 | 23 | Installation 24 | ------------ 25 | 26 | Next, download or clone the `latest version `_ from GitHub, unpack and install: 27 | 28 | .. code-block:: console 29 | 30 | $ git clone https://github.com/olivercliff/pyspi.git 31 | $ cd pyspi 32 | $ pip install . 33 | 34 | 35 | Getting Started 36 | --------------- 37 | 38 | In order to demonstrate the functionality of this software, we will first need a sample multivariate time series (MTS). 39 | We will use data generated from a multivariate Gaussian: 40 | 41 | .. code-block:: 42 | 43 | import numpy as np 44 | import random 45 | 46 | random.seed(42) 47 | 48 | M = 5 # 5 processes 49 | T = 500 # 500 observations 50 | 51 | dataset = np.random.randn(M,T) 52 | 53 | Now, given our dataset, we can instantiate the :class:`~pyspi.calculator.Calculator` object: 54 | 55 | .. code-block:: 56 | 57 | from pyspi.calculator import Calculator 58 | 59 | calc = Calculator(dataset=dataset) 60 | 61 | And, using only the :meth:`~pyspi.calculator.Calculator.compute` method, we can compute over 250 statistics for analysing pairwise interactions in the MTS. 62 | 63 | .. code-block:: 64 | 65 | calc.compute() 66 | 67 | .. note:: 68 | While we tried to make the calculator as efficient as possible, computing all statistics can take a while (depending on the size of your dataset). 69 | It might be good practice to begin with a subset of the statistics while you're getting started, see :ref:`Using a reduced SPI set`. 70 | 71 | Once the calculator has computed each of the statistics, you can access all values using the :attr:`~pyspi.calculator.Calculator.table` property: 72 | 73 | .. code-block:: 74 | 75 | print(calc.table) 76 | 77 | Or, extract one matrix of pairwise interactions (MPI) for a given method using their unique `identifier`. 78 | For instance, the following code will extract the covariance matrix computed with the maximum likelihood estimator: 79 | 80 | .. code-block:: 81 | 82 | print(calc.table['cov_EmpiricalCovariance']) 83 | 84 | The identifiers for many of the statistics are outlined in the Supplementary Material of our `preprint `_, and an up-to-date list of included statistics will be provided in this documentation shortly. -------------------------------------------------------------------------------- /docs/build/html/_static/css/badge_only.css: -------------------------------------------------------------------------------- 1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-bold-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/lato-bold-italic.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-bold-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/lato-bold-italic.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/lato-bold.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/lato-bold.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-normal-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/lato-normal-italic.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-normal-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/lato-normal-italic.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/lato-normal.woff -------------------------------------------------------------------------------- /docs/build/html/_static/css/fonts/lato-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/css/fonts/lato-normal.woff2 -------------------------------------------------------------------------------- /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.1', 4 | LANGUAGE: 'None', 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 | }; -------------------------------------------------------------------------------- /docs/build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/_static/file.png -------------------------------------------------------------------------------- /docs/build/html/_static/js/badge_only.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}}); -------------------------------------------------------------------------------- /docs/build/html/_static/js/html5shiv-printshiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /docs/build/html/_static/js/html5shiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /docs/build/html/_static/js/theme.js: -------------------------------------------------------------------------------- 1 | !function(n){var e={};function t(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return n[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(i,o,function(e){return n[e]}.bind(null,o));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){t(1),n.exports=t(3)},function(n,e,t){(function(){var e="undefined"!=typeof window?window.jQuery:t(2);n.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var t=this;void 0===n&&(n=!0),t.isRunning||(t.isRunning=!0,e((function(e){t.init(e),t.reset(),t.win.on("hashchange",t.reset),n&&t.win.on("scroll",(function(){t.linkScroll||t.winScroll||(t.winScroll=!0,requestAnimationFrame((function(){t.onScroll()})))})),t.win.on("resize",(function(){t.winResize||(t.winResize=!0,requestAnimationFrame((function(){t.onResize()})))})),t.onResize()})))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",(function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")})).on("click",".wy-menu-vertical .current ul li a",(function(){var t=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(t),e.hashChange()})).on("click","[data-toggle='rst-current-version']",(function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")})),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t 2 | 3 | 4 | 5 | 6 | 7 | API — PySPI 0.1 documentation 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 56 | 57 |
61 | 62 |
63 |
64 |
65 | 72 |
73 |
74 |
75 |
76 | 77 |
78 |

API

79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 |

pyspi.calculator.Calculator([dataset, name, ...])

Compute all pairwise interactions.

pyspi.data.Data([data, dim_order, ...])

Store data for dependency analysis.

93 |
94 | 95 | 96 |
97 |
98 |
102 | 103 |
104 | 105 |
106 |

© Copyright 2022, Oliver M. Cliff.

107 |
108 | 109 | Built with Sphinx using a 110 | theme 111 | provided by Read the Docs. 112 | 113 | 114 |
115 |
116 |
117 |
118 |
119 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /docs/build/html/genindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Index — PySPI 0.1 documentation 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 49 | 50 |
54 | 55 |
56 |
57 |
58 |
    59 |
  • »
  • 60 |
  • Index
  • 61 |
  • 62 |
  • 63 |
64 |
65 |
66 |
67 |
68 | 69 | 70 |

Index

71 | 72 |
73 | _ 74 | | C 75 | | D 76 | 77 |
78 |

_

79 | 80 | 88 |
89 | 90 |

C

91 | 92 | 96 |
97 | 98 |

D

99 | 100 | 104 |
105 | 106 | 107 | 108 |
109 |
110 |
111 | 112 |
113 | 114 |
115 |

© Copyright 2022, Oliver M. Cliff.

116 |
117 | 118 | Built with Sphinx using a 119 | theme 120 | provided by Read the Docs. 121 | 122 | 123 |
124 |
125 |
126 |
127 |
128 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /docs/build/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Welcome to PySPI’s documentation! — PySPI 0.1 documentation 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 51 | 52 |
56 | 57 |
58 |
59 |
60 |
    61 |
  • »
  • 62 |
  • Welcome to PySPI’s documentation!
  • 63 |
  • 64 | View page source 65 |
  • 66 |
67 |
68 |
69 |
70 |
71 | 72 |
73 |

Welcome to PySPI’s documentation!

74 |

PySPI (/pie’spy/) is a Python library for simultaneously evaluating hundreds of pairwise interactions directly from multivariate time-series data.

75 |

It provides easy access to over 250 methods for evaluating the relationship between pairs of time series, from simple statistics (like correlation coefficients) to advanced multi-step algorithms (like Granger causality).

76 |

Check out the Usage section for further information, including Installation instructions.

77 |
78 |

Note

79 |

This documentation and project is under active development.

80 |
81 |
82 |

Contents

83 |
84 | 103 |
104 |
105 |
106 | 107 | 108 |
109 |
110 |
113 | 114 |
115 | 116 |
117 |

© Copyright 2022, Oliver M. Cliff.

118 |
119 | 120 | Built with Sphinx using a 121 | theme 122 | provided by Read the Docs. 123 | 124 | 125 |
126 |
127 |
128 |
129 |
130 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /docs/build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/build/html/objects.inv -------------------------------------------------------------------------------- /docs/build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Search — PySPI 0.1 documentation 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 52 | 53 |
57 | 58 |
59 |
60 |
61 |
    62 |
  • »
  • 63 |
  • Search
  • 64 |
  • 65 |
  • 66 |
67 |
68 |
69 |
70 |
71 | 72 | 79 | 80 | 81 |
82 | 83 |
84 | 85 |
86 |
87 |
88 | 89 |
90 | 91 |
92 |

© Copyright 2022, Oliver M. Cliff.

93 |
94 | 95 | Built with Sphinx using a 96 | theme 97 | provided by Read the Docs. 98 | 99 | 100 |
101 |
102 |
103 |
104 |
105 | 110 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["advanced","api","generated/pyspi.calculator.Calculator","generated/pyspi.data.Data","index","statistics","usage"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.intersphinx":1,sphinx:56},filenames:["advanced.rst","api.rst","generated/pyspi.calculator.Calculator.rst","generated/pyspi.data.Data.rst","index.rst","statistics.rst","usage.rst"],objects:{"pyspi.calculator":[[2,0,1,"","Calculator"]],"pyspi.calculator.Calculator":[[2,1,1,"","__init__"]],"pyspi.data":[[3,0,1,"","Data"]],"pyspi.data.Data":[[3,1,1,"","__init__"]]},objnames:{"0":["py","class","Python class"],"1":["py","method","Python method"]},objtypes:{"0":"py:class","1":"py:method"},terms:{"0":6,"1":3,"10":[0,5],"1000":[0,3],"2":3,"250":[4,5,6],"3":[3,6],"3000":3,"42":6,"5":[2,6],"500":[2,6],"5000":3,"9":6,"class":[2,3],"default":[0,2,3,5,6],"do":[0,5],"function":[5,6],"import":[0,2,6],"int":3,"new":6,"true":3,"while":6,A:[0,5],And:6,For:6,If:[0,3],In:[5,6],It:[2,4,6],Or:6,The:[2,4,5,6],Then:0,__init__:[2,3],about:0,abov:5,accept:3,access:[4,6],activ:[4,6],actual:3,advanc:4,after:6,aim:5,algorithm:4,all:[2,5,6],allow:0,along:[0,3],also:6,an:[0,3,6],analys:6,analysi:3,ani:[0,2,5],api:4,ar:[0,5,6],arang:3,argument:0,arrai:3,array_lik:[2,3],assist:0,attribut:[2,3],avail:6,base:5,basic:0,befor:0,begin:6,below:5,bespok:0,between:[4,5],bivari:5,bool:3,cacul:0,calc:[0,2,6],calcul:[0,4,6],can:[0,2,6],categor:5,categori:5,causal:4,cd:6,charact:3,check:4,classif:2,clone:6,code:[2,5,6],coeffici:4,com:6,combin:3,comput:[0,2,5,6],conda:6,config:[0,2],configfil:[0,2],configur:[0,2],contact:0,contain:0,control:0,copi:0,correl:[4,5],cov:5,cov_empiricalcovari:6,covari:[0,5,6],cp:0,creat:[2,3,6],d:3,data:[2,4,6],data_2:3,data_forex:3,data_new:3,dataset:[0,2,3,6],date:[0,6],demonstr:6,depend:[3,6],deriv:5,descript:5,detail:[0,5],develop:4,dict:[],difficult:6,dim_ord:[0,3],dimens:[0,3],dimension:3,directli:[0,4],directori:0,document:[0,6],domain:5,don:0,download:6,dropbox:2,e:[3,5],each:6,easi:4,easili:0,edit:0,effici:[0,6],either:5,empiricalcovari:0,emploi:5,empti:3,entri:0,entropi:5,environ:6,establish:5,estim:[0,6],evalu:4,exampl:[2,3],exist:3,extract:6,fals:0,file:[0,2,5],financi:3,find:6,first:[0,6],fit:5,follow:[0,6],forex:3,fourier:5,freeli:6,frequenc:5,from:[0,4,5,6],full:5,further:4,g:[3,5],gaussian:6,gener:6,get:4,git:6,github:6,given:6,gnu:6,good:6,got:0,granger:4,ha:6,have:[0,2,5,6],hesit:0,home:2,how:[0,6],howev:0,http:6,hundr:4,identifi:[5,6],implement:0,includ:[0,4,6],independ:5,indic:3,infer:5,inform:[4,6],initialis:3,input:[0,5],instal:[0,4],instanc:[2,6],instanti:[0,2,6],instead:0,instruct:[4,6],integr:6,integrated_inform:0,intend:5,interact:[2,4,5,6],interest:0,joint:5,label:2,later:2,latest:6,length:3,librari:4,like:[0,4],likehood:0,likelihood:[0,6],line:[],list:[0,3,6],load:3,load_dataset:3,local:0,locat:2,look:0,lot:6,m:[0,2,6],mai:6,mainli:2,make:6,manag:6,mani:[0,3,6],materi:[0,6],matric:5,matrix:[0,5,6],maximum:[0,6],me:0,method:[0,2,3,4,6],might:[0,6],minim:0,model:5,modifi:2,more:0,most:5,mpi:6,mt:[0,2,6],multi:4,multipl:[2,5],multivari:[2,4,6],mutual:5,myconfig:0,n:6,n_observ:3,n_process:3,name:[2,3,5],need:6,next:6,none:[2,3],normal:0,normalis:[0,3],now:[0,6],np:[0,2,3,6],number:[0,3,5],numpi:[0,2,6],object:[3,4,6],observ:[0,2,3,5,6],octav:[4,6],oliv:2,olivercliff:6,onc:[0,6],one:6,onli:[0,6],oper:[5,6],option:[2,3],order:[2,3,6],our:[0,5,6],out:[4,6],outlin:6,outsid:6,over:[0,3,4,5,6],overwrit:3,p:[0,3],packag:6,pair:4,pairwis:[2,4,5,6],paramet:[2,3,5],particular:0,path:[0,2],per:[],perform:5,pie:4,pip:6,place:5,popular:6,possibl:6,practic:6,pre:4,prec:5,precis:5,prefil:3,preprint:[0,6],preprocess:0,print:[2,6],proc:3,process:[0,2,3,6],procnam:3,produc:5,project:4,properti:[0,6],provid:[0,3,4,6],ps:[0,3],purpos:2,pyspi:[0,6],python:[4,6],question:0,quit:6,rand:0,randn:[2,6],random:[0,2,3,6],raw:3,re:[0,6],realis:3,recommend:6,reduc:[2,4,6],relationship:4,remov:0,repres:3,requir:6,research:2,reshap:3,result:2,run:5,s:[0,3,6],safe:6,sampl:6,score:[0,3],section:[4,5],see:[0,2,6],seed:6,seri:[2,4,5,6],serial:5,set:[2,4,5,6],set_data:3,shortli:[0,6],should:0,simpl:4,simultan:4,size:[3,6],small:5,so:[5,6],softwar:6,spearman:5,spearmanr:5,specifi:0,spi:[2,4,5,6],spy:4,squar:5,start:4,statist:[0,4,6],step:4,stochast:5,store:[2,3],str:[2,3],string:[2,3],subset:[0,6],supplementari:[0,6],system:[5,6],t:[0,2,6],tabl:6,take:[2,3,6],techniqu:5,thei:5,them:5,theori:6,thi:[0,2,3,4,5,6],those:0,time:[2,3,4,5,6],toolkit:[4,6],tradit:5,transfer:5,transform:5,treat:0,tri:6,truncat:3,two:3,under:4,uniqu:6,unpack:6,up:[0,6],upon:0,us:[2,4,5,6],usag:[0,4],user:6,valu:6,variabl:3,variou:3,ve:0,version:[0,6],want:[0,2],wavelet:5,we:[0,5,6],when:0,which:[0,2,6],wish:0,within:0,without:[4,6],workspac:[0,2],would:6,yaml:[0,2],you:[0,2,6],your:[0,6],z:[0,3]},titles:["Advanced","API","pyspi.calculator.Calculator","pyspi.data.Data","Welcome to PySPI\u2019s documentation!","List of methods","Usage"],titleterms:{The:0,advanc:0,api:1,basic:5,calcul:2,causal:5,content:4,data:[0,3],distanc:5,document:4,get:6,indic:5,inform:5,instal:6,list:5,measur:5,method:5,miscellan:5,object:0,octav:0,pre:6,pyspi:[2,3,4],reduc:0,s:4,set:0,similar:5,spectral:5,spi:0,start:6,statist:5,theori:5,toolkit:0,us:0,usag:6,welcom:4,without:0}}) -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 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/requirements.txt: -------------------------------------------------------------------------------- 1 | -e .[docs] -------------------------------------------------------------------------------- /docs/source/_build/doctrees/advanced.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/doctrees/advanced.doctree -------------------------------------------------------------------------------- /docs/source/_build/doctrees/api.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/doctrees/api.doctree -------------------------------------------------------------------------------- /docs/source/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/source/_build/doctrees/generated/pyspi.calculator.Calculator.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/doctrees/generated/pyspi.calculator.Calculator.doctree -------------------------------------------------------------------------------- /docs/source/_build/doctrees/generated/pyspi.data.Data.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/doctrees/generated/pyspi.data.Data.doctree -------------------------------------------------------------------------------- /docs/source/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/source/_build/doctrees/statistics.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/doctrees/statistics.doctree -------------------------------------------------------------------------------- /docs/source/_build/doctrees/usage.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/doctrees/usage.doctree -------------------------------------------------------------------------------- /docs/source/_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: 156e67aeef1241dfc58561413874e38d 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/source/_build/html/_sources/advanced.rst.txt: -------------------------------------------------------------------------------- 1 | Advanced 2 | ======== 3 | 4 | The Data object 5 | --------------------- 6 | 7 | The MTS data is contained within the :class:`~pyspi.data.Data` object, along with preprocessed properties of the MTS that allows us to efficiently compute the methods. 8 | If you want more control over how the MTS are treated upon input, you can directly instantiate a :class:`~pyspi.data.Data` object for inputting to the calculator: 9 | 10 | .. code-block:: 11 | 12 | from pyspi.data import Data 13 | from pyspi.calculator import Calculator 14 | import numpy as np 15 | 16 | M = 10 # Number of processes 17 | T = 1000 # Number of observations 18 | 19 | z = np.random.rand(M,T) 20 | 21 | # The dim_order argument specifies which dimension is a process (p) and an observation (s). 22 | # The normalise argument specifies if we should z-score the data. 23 | dataset = Data(data=z,dim_order='ps',normalise=False) 24 | 25 | calc = Calculator(dataset=dataset) 26 | 27 | 28 | Using a reduced SPI set 29 | ----------------------- 30 | 31 | You can easily use a subset of the SPIs by copying a version of the :code:`config.yaml` file to a local directory and removing those you don't want the calculator to compute. 32 | First, copy the :code:`config.yaml` file to your workspace: 33 | 34 | .. code-block:: console 35 | 36 | $ cp /pyspi/config.yaml myconfig.yaml 37 | 38 | Once you've got a local version, edit the :code:`myconfig.yaml` file to remove any SPIs you're not interested in. 39 | A minimal configuration file might look like the following if you're only interested in computing a covariance matrix using the maximum likelihood estimator: 40 | 41 | .. code-block:: 42 | 43 | # Basic statistics 44 | .statistics.basic: 45 | # Covariance 46 | covariance: 47 | # Maximum likehood estimator 48 | - estimator: EmpiricalCovariance 49 | 50 | Now, when you instantiate the calculator, instead of using the default :code:`config.yaml`, you can input your bespoke configuration file: 51 | 52 | .. code-block:: 53 | 54 | from pyspi.calculator import Calculator 55 | 56 | calc = Caculator(dataset=dataset,configfile='myconfig.yaml') 57 | 58 | Then use the calculator as normal (see :ref:`Usage`). 59 | 60 | .. note:: 61 | We have provided a detailed list of many of the statistics included in this toolkit (and the configuration file) in the Supplementary Material of our `preprint `_, and will include an up-to-date list of statistics in this documentation shortly. 62 | However, if you have any questions about a particular implementation, do not hesitate to `contact me `_ for any assistance. 63 | 64 | Using the toolkit without Octave 65 | -------------------------------- 66 | 67 | If you do not wish to first install Octave before using the toolkit, remove the yaml entries for :code:`integrated_information` in the :code:`config.yaml` file (see :ref:`Using a reduced SPI set`). -------------------------------------------------------------------------------- /docs/source/_build/html/_sources/api.rst.txt: -------------------------------------------------------------------------------- 1 | API 2 | === 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | pyspi.calculator.Calculator 8 | pyspi.data.Data -------------------------------------------------------------------------------- /docs/source/_build/html/_sources/generated/pyspi.calculator.Calculator.rst.txt: -------------------------------------------------------------------------------- 1 | pyspi.calculator.Calculator 2 | =========================== 3 | 4 | .. currentmodule:: pyspi.calculator 5 | 6 | .. autoclass:: Calculator 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | .. rubric:: Methods 13 | 14 | .. autosummary:: 15 | 16 | ~Calculator.__init__ 17 | ~Calculator.compute 18 | ~Calculator.getstatlabels 19 | ~Calculator.load_dataset 20 | ~Calculator.set_group 21 | 22 | 23 | 24 | 25 | 26 | .. rubric:: Attributes 27 | 28 | .. autosummary:: 29 | 30 | ~Calculator.dataset 31 | ~Calculator.group 32 | ~Calculator.group_name 33 | ~Calculator.labels 34 | ~Calculator.n_spis 35 | ~Calculator.name 36 | ~Calculator.spis 37 | ~Calculator.table 38 | 39 | -------------------------------------------------------------------------------- /docs/source/_build/html/_sources/generated/pyspi.data.Data.rst.txt: -------------------------------------------------------------------------------- 1 | pyspi.data.Data 2 | =============== 3 | 4 | .. currentmodule:: pyspi.data 5 | 6 | .. autoclass:: Data 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | .. rubric:: Methods 13 | 14 | .. autosummary:: 15 | 16 | ~Data.__init__ 17 | ~Data.add_process 18 | ~Data.convert_to_numpy 19 | ~Data.remove_process 20 | ~Data.set_data 21 | ~Data.to_numpy 22 | 23 | 24 | 25 | 26 | 27 | .. rubric:: Attributes 28 | 29 | .. autosummary:: 30 | 31 | ~Data.name 32 | ~Data.procnames 33 | 34 | -------------------------------------------------------------------------------- /docs/source/_build/html/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | Welcome to PySPI's documentation! 2 | =================================== 3 | 4 | **PySPI** (/pie'spy/) is a Python library for simultaneously evaluating hundreds of pairwise interactions directly from multivariate time-series data. 5 | 6 | It provides easy access to over 250 methods for evaluating the relationship between pairs of time series, from simple statistics (like correlation coefficients) to advanced multi-step algorithms (like Granger causality). 7 | 8 | Check out the :doc:`usage` section for further information, including :ref:`Installation` instructions. 9 | 10 | .. note:: 11 | 12 | This documentation and project is under active development. 13 | 14 | Contents 15 | -------- 16 | 17 | .. toctree:: 18 | 19 | usage 20 | advanced 21 | api -------------------------------------------------------------------------------- /docs/source/_build/html/_sources/statistics.rst.txt: -------------------------------------------------------------------------------- 1 | List of methods 2 | =========================== 3 | 4 | The full default set of over 250 pairwise interactions are produced by running all of the code files below. 5 | In our default statistics set, most functions are run with multiple input parameters. 6 | 7 | Basic statistics 8 | ---------------- 9 | 10 | In this section, we detail SPIs that are traditional techniques for performing statistical inference in bivariate systems. 11 | 12 | .. list-table:: 13 | :widths: 25 25 50 14 | :header-rows: 1 15 | 16 | * - Method name 17 | - Description 18 | - Identifier 19 | * - :code:`covariance` 20 | - Covariance matrix 21 | - :code:`cov` 22 | * - :code:`precision` 23 | - Precision matrix 24 | - :code:`prec` 25 | * - :code:`spearmanr` 26 | - Spearman correlation 27 | - :code:`spearmanr` 28 | 29 | Distance similarity 30 | ------------------- 31 | 32 | In this section, we detail SPIs that we have categorized as distance-based similarity measures in that they 33 | aim to establish statistical similarity or independence based on the pairwise distance between bivariate 34 | observations 35 | 36 | Causal indices 37 | -------------- 38 | 39 | In this section, we detail the 10 SPIs that are derived from causal inference models. 40 | 41 | Information Theory 42 | ------------------ 43 | 44 | The pairwise measures that we employ from information theory are either intended to operate on serially independent observations (e.g., joint entropy and mutual information) or bivariate time series (e.g., 45 | transfer entropy and stochastic interaction). 46 | 47 | Spectral measures 48 | ----------------- 49 | 50 | Spectral SPIs are computed in the frequency or time-frequency domain, using either Fourier or wavelet 51 | transformations to derive spectral matrices. 52 | 53 | Miscellaneous 54 | ------------- 55 | 56 | A small number of methods do not fit squarely into any category listed above, and so we place them 57 | in a 'miscellaneous' category -------------------------------------------------------------------------------- /docs/source/_build/html/_sources/usage.rst.txt: -------------------------------------------------------------------------------- 1 | Usage 2 | ===== 3 | 4 | Pre-installation 5 | ---------------- 6 | 7 | The code requires GNU's `Octave `_ by default, which is freely available on all popular operating systems. 8 | See the `installation instructions `_ to find out how to install Octave on your system. 9 | 10 | .. note:: 11 | You can safely install `PySPI` without first installing Octave but you will not have access to the `Integrated Information Theory` statistics, see :ref:`Using the toolkit without Octave`. 12 | 13 | While you can also install `PySPI` outside of a `conda `_ environment, it depends on a lot of user packages that may make managing dependencies quite difficult. 14 | So, we would also recommend installing `PySPI` in a conda environment. 15 | After `installing conda `_, create a new environment for using the toolkit: 16 | 17 | .. code-block:: console 18 | 19 | $ conda create -n pyspi python=3.9.0 20 | $ conda activate pyspi 21 | 22 | 23 | Installation 24 | ------------ 25 | 26 | Next, download or clone the `latest version `_ from GitHub, unpack and install: 27 | 28 | .. code-block:: console 29 | 30 | $ git clone https://github.com/olivercliff/pyspi.git 31 | $ cd pyspi 32 | $ pip install . 33 | 34 | 35 | Getting Started 36 | --------------- 37 | 38 | In order to demonstrate the functionality of this software, we will first need a sample multivariate time series (MTS). 39 | We will use data generated from a multivariate Gaussian: 40 | 41 | .. code-block:: 42 | 43 | import numpy as np 44 | import random 45 | 46 | random.seed(42) 47 | 48 | M = 5 # 5 processes 49 | T = 500 # 500 observations 50 | 51 | dataset = np.random.randn(M,T) 52 | 53 | Now, given our dataset, we can instantiate the :class:`~pyspi.calculator.Calculator` object: 54 | 55 | .. code-block:: 56 | 57 | from pyspi.calculator import Calculator 58 | 59 | calc = Calculator(dataset=dataset) 60 | 61 | And, using only the :meth:`~pyspi.calculator.Calculator.compute` method, we can compute over 250 statistics for analysing pairwise interactions in the MTS. 62 | 63 | .. code-block:: 64 | 65 | calc.compute() 66 | 67 | .. note:: 68 | While we tried to make the calculator as efficient as possible, computing all statistics can take a while (depending on the size of your dataset). 69 | It might be good practice to begin with a subset of the statistics while you're getting started, see :ref:`Using a reduced SPI set`. 70 | 71 | Once the calculator has computed each of the statistics, you can access all values using the :attr:`~pyspi.calculator.Calculator.table` property: 72 | 73 | .. code-block:: 74 | 75 | print(calc.table) 76 | 77 | Or, extract one matrix of pairwise interactions (MPI) for a given method using their unique `identifier`. 78 | For instance, the following code will extract the covariance matrix computed with the maximum likelihood estimator: 79 | 80 | .. code-block:: 81 | 82 | print(calc.table['cov_EmpiricalCovariance']) 83 | 84 | The identifiers for many of the statistics are outlined in the Supplementary Material of our `preprint `_, and an up-to-date list of included statistics will be provided in this documentation shortly. -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/badge_only.css: -------------------------------------------------------------------------------- 1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/lato-bold-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/lato-bold-italic.woff -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/lato-bold-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/lato-bold-italic.woff2 -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/lato-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/lato-bold.woff -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/lato-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/lato-bold.woff2 -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/lato-normal-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/lato-normal-italic.woff -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/lato-normal-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/lato-normal-italic.woff2 -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/lato-normal.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/lato-normal.woff -------------------------------------------------------------------------------- /docs/source/_build/html/_static/css/fonts/lato-normal.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/css/fonts/lato-normal.woff2 -------------------------------------------------------------------------------- /docs/source/_build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: '0.1', 4 | LANGUAGE: 'None', 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 | }; -------------------------------------------------------------------------------- /docs/source/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/_static/file.png -------------------------------------------------------------------------------- /docs/source/_build/html/_static/js/badge_only.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}}); -------------------------------------------------------------------------------- /docs/source/_build/html/_static/js/html5shiv-printshiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /docs/source/_build/html/_static/js/html5shiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); -------------------------------------------------------------------------------- /docs/source/_build/html/_static/js/theme.js: -------------------------------------------------------------------------------- 1 | !function(n){var e={};function t(i){if(e[i])return e[i].exports;var o=e[i]={i:i,l:!1,exports:{}};return n[i].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,i){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:i})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var i=Object.create(null);if(t.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(i,o,function(e){return n[e]}.bind(null,o));return i},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){t(1),n.exports=t(3)},function(n,e,t){(function(){var e="undefined"!=typeof window?window.jQuery:t(2);n.exports.ThemeNav={navBar:null,win:null,winScroll:!1,winResize:!1,linkScroll:!1,winPosition:0,winHeight:null,docHeight:null,isRunning:!1,enable:function(n){var t=this;void 0===n&&(n=!0),t.isRunning||(t.isRunning=!0,e((function(e){t.init(e),t.reset(),t.win.on("hashchange",t.reset),n&&t.win.on("scroll",(function(){t.linkScroll||t.winScroll||(t.winScroll=!0,requestAnimationFrame((function(){t.onScroll()})))})),t.win.on("resize",(function(){t.winResize||(t.winResize=!0,requestAnimationFrame((function(){t.onResize()})))})),t.onResize()})))},enableSticky:function(){this.enable(!0)},init:function(n){n(document);var e=this;this.navBar=n("div.wy-side-scroll:first"),this.win=n(window),n(document).on("click","[data-toggle='wy-nav-top']",(function(){n("[data-toggle='wy-nav-shift']").toggleClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift")})).on("click",".wy-menu-vertical .current ul li a",(function(){var t=n(this);n("[data-toggle='wy-nav-shift']").removeClass("shift"),n("[data-toggle='rst-versions']").toggleClass("shift"),e.toggleCurrent(t),e.hashChange()})).on("click","[data-toggle='rst-current-version']",(function(){n("[data-toggle='rst-versions']").toggleClass("shift-up")})),n("table.docutils:not(.field-list,.footnote,.citation)").wrap("
"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t 2 | 3 | 4 | 5 | 6 | 7 | API — PySPI 0.1 documentation 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 56 | 57 |
61 | 62 |
63 |
64 |
65 | 72 |
73 |
74 |
75 |
76 | 77 |
78 |

API

79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 |

pyspi.calculator.Calculator([dataset, name, ...])

Compute all pairwise interactions.

pyspi.data.Data([data, dim_order, ...])

Store data for dependency analysis.

93 |
94 | 95 | 96 |
97 |
98 |
102 | 103 |
104 | 105 |
106 |

© Copyright 2022, Oliver M. Cliff.

107 |
108 | 109 | Built with Sphinx using a 110 | theme 111 | provided by Read the Docs. 112 | 113 | 114 |
115 |
116 |
117 |
118 |
119 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /docs/source/_build/html/genindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Index — PySPI 0.1 documentation 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 49 | 50 |
54 | 55 |
56 |
57 |
58 |
    59 |
  • »
  • 60 |
  • Index
  • 61 |
  • 62 |
  • 63 |
64 |
65 |
66 |
67 |
68 | 69 | 70 |

Index

71 | 72 |
73 | _ 74 | | C 75 | | D 76 | 77 |
78 |

_

79 | 80 | 88 |
89 | 90 |

C

91 | 92 | 96 |
97 | 98 |

D

99 | 100 | 104 |
105 | 106 | 107 | 108 |
109 |
110 |
111 | 112 |
113 | 114 |
115 |

© Copyright 2022, Oliver M. Cliff.

116 |
117 | 118 | Built with Sphinx using a 119 | theme 120 | provided by Read the Docs. 121 | 122 | 123 |
124 |
125 |
126 |
127 |
128 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /docs/source/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/_build/html/objects.inv -------------------------------------------------------------------------------- /docs/source/_build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Search — PySPI 0.1 documentation 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 52 | 53 |
57 | 58 |
59 |
60 |
61 |
    62 |
  • »
  • 63 |
  • Search
  • 64 |
  • 65 |
  • 66 |
67 |
68 |
69 |
70 |
71 | 72 | 79 | 80 | 81 |
82 | 83 |
84 | 85 |
86 |
87 |
88 | 89 |
90 | 91 |
92 |

© Copyright 2022, Oliver M. Cliff.

93 |
94 | 95 | Built with Sphinx using a 96 | theme 97 | provided by Read the Docs. 98 | 99 | 100 |
101 |
102 |
103 |
104 |
105 | 110 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/source/_build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["advanced","api","generated/pyspi.calculator.Calculator","generated/pyspi.data.Data","index","statistics","usage"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.intersphinx":1,sphinx:56},filenames:["advanced.rst","api.rst","generated/pyspi.calculator.Calculator.rst","generated/pyspi.data.Data.rst","index.rst","statistics.rst","usage.rst"],objects:{"pyspi.calculator":[[2,0,1,"","Calculator"]],"pyspi.calculator.Calculator":[[2,1,1,"","__init__"]],"pyspi.data":[[3,0,1,"","Data"]],"pyspi.data.Data":[[3,1,1,"","__init__"]]},objnames:{"0":["py","class","Python class"],"1":["py","method","Python method"]},objtypes:{"0":"py:class","1":"py:method"},terms:{"0":6,"1":3,"10":[0,5],"1000":[0,3],"2":3,"250":[4,5,6],"3":[3,6],"3000":3,"42":6,"5":[2,6],"500":[2,6],"5000":3,"9":6,"class":[2,3],"default":[0,2,3,5,6],"do":[0,5],"function":[5,6],"import":[0,2,6],"int":3,"new":6,"true":3,"while":6,A:[0,5],And:6,For:6,If:[0,3],In:[5,6],It:[2,4,6],Or:6,The:[2,4,5,6],Then:0,__init__:[2,3],about:0,abov:5,accept:3,access:[4,6],activ:[4,6],actual:3,advanc:4,after:6,aim:5,algorithm:4,all:[2,5,6],allow:0,along:[0,3],also:6,an:[0,3,6],analys:6,analysi:3,ani:[0,2,5],api:4,ar:[0,5,6],arang:3,argument:0,arrai:3,array_lik:[2,3],assist:0,attribut:[2,3],avail:6,base:5,basic:0,befor:0,begin:6,below:5,bespok:0,between:[4,5],bivari:5,bool:3,cacul:0,calc:[0,2,6],calcul:[0,4,6],can:[0,2,6],categor:5,categori:5,causal:4,cd:6,charact:3,check:4,classif:2,clone:6,code:[2,5,6],coeffici:4,com:6,combin:3,comput:[0,2,5,6],conda:6,config:[0,2],configfil:[0,2],configur:[0,2],contact:0,contain:0,control:0,copi:0,correl:[4,5],cov:5,cov_empiricalcovari:6,covari:[0,5,6],cp:0,creat:[2,3,6],d:3,data:[2,4,6],data_2:3,data_forex:3,data_new:3,dataset:[0,2,3,6],date:[0,6],demonstr:6,depend:[3,6],deriv:5,descript:5,detail:[0,5],develop:4,difficult:6,dim_ord:[0,3],dimens:[0,3],dimension:3,directli:[0,4],directori:0,document:[0,6],domain:5,don:0,download:6,dropbox:2,e:[3,5],each:6,easi:4,easili:0,edit:0,effici:[0,6],either:5,empiricalcovari:0,emploi:5,empti:3,entri:0,entropi:5,environ:6,establish:5,estim:[0,6],evalu:4,exampl:[2,3],exist:3,extract:6,fals:0,file:[0,2,5],financi:3,find:6,first:[0,6],fit:5,follow:[0,6],forex:3,fourier:5,freeli:6,frequenc:5,from:[0,4,5,6],full:5,further:4,g:[3,5],gaussian:6,gener:6,get:4,git:6,github:6,given:6,gnu:6,good:6,got:0,granger:4,ha:6,have:[0,2,5,6],hesit:0,home:2,how:[0,6],howev:0,http:6,hundr:4,identifi:[5,6],implement:0,includ:[0,4,6],independ:5,indic:3,infer:5,inform:[4,6],initialis:3,input:[0,5],instal:[0,4],instanc:[2,6],instanti:[0,2,6],instead:0,instruct:[4,6],integr:6,integrated_inform:0,intend:5,interact:[2,4,5,6],interest:0,joint:5,label:2,later:2,latest:6,length:3,librari:4,like:[0,4],likehood:0,likelihood:[0,6],list:[0,3,6],load:3,load_dataset:3,local:0,locat:2,look:0,lot:6,m:[0,2,6],mai:6,mainli:2,make:6,manag:6,mani:[0,3,6],materi:[0,6],matric:5,matrix:[0,5,6],maximum:[0,6],me:0,method:[0,2,3,4,6],might:[0,6],minim:0,model:5,modifi:2,more:0,most:5,mpi:6,mt:[0,2,6],multi:4,multipl:[2,5],multivari:[2,4,6],mutual:5,myconfig:0,n:6,n_observ:3,n_process:3,name:[2,3,5],need:6,next:6,none:[2,3],normal:0,normalis:[0,3],now:[0,6],np:[0,2,3,6],number:[0,3,5],numpi:[0,2,6],object:[3,4,6],observ:[0,2,3,5,6],octav:[4,6],oliv:2,olivercliff:6,onc:[0,6],one:6,onli:[0,6],oper:[5,6],option:[2,3],order:[2,3,6],our:[0,5,6],out:[4,6],outlin:6,outsid:6,over:[0,3,4,5,6],overwrit:3,p:[0,3],packag:6,pair:4,pairwis:[2,4,5,6],paramet:[2,3,5],particular:0,path:[0,2],perform:5,pie:4,pip:6,place:5,popular:6,possibl:6,practic:6,pre:4,prec:5,precis:5,prefil:3,preprint:[0,6],preprocess:0,print:[2,6],proc:3,process:[0,2,3,6],procnam:3,produc:5,project:4,properti:[0,6],provid:[0,3,4,6],ps:[0,3],purpos:2,pyspi:[0,6],python:[4,6],question:0,quit:6,rand:0,randn:[2,6],random:[0,2,3,6],raw:3,re:[0,6],realis:3,recommend:6,reduc:[2,4,6],relationship:4,remov:0,repres:3,requir:6,research:2,reshap:3,result:2,run:5,s:[0,3,6],safe:6,sampl:6,score:[0,3],section:[4,5],see:[0,2,6],seed:6,seri:[2,4,5,6],serial:5,set:[2,4,5,6],set_data:3,shortli:[0,6],should:0,simpl:4,simultan:4,size:[3,6],small:5,so:[5,6],softwar:6,spearman:5,spearmanr:5,specifi:0,spi:[2,4,5,6],spy:4,squar:5,start:4,statist:[0,4,6],step:4,stochast:5,store:[2,3],str:[2,3],string:[2,3],subset:[0,6],supplementari:[0,6],system:[5,6],t:[0,2,6],tabl:6,take:[2,3,6],techniqu:5,thei:5,them:5,theori:6,thi:[0,2,3,4,5,6],those:0,time:[2,3,4,5,6],toolkit:[4,6],tradit:5,transfer:5,transform:5,treat:0,tri:6,truncat:3,two:3,under:4,uniqu:6,unpack:6,up:[0,6],upon:0,us:[2,4,5,6],usag:[0,4],user:6,valu:6,variabl:3,variou:3,ve:0,version:[0,6],want:[0,2],wavelet:5,we:[0,5,6],when:0,which:[0,2,6],wish:0,within:0,without:[4,6],workspac:[0,2],would:6,yaml:[0,2],you:[0,2,6],your:[0,6],z:[0,3]},titles:["Advanced","API","pyspi.calculator.Calculator","pyspi.data.Data","Welcome to PySPI\u2019s documentation!","List of methods","Usage"],titleterms:{The:0,advanc:0,api:1,basic:5,calcul:2,causal:5,content:4,data:[0,3],distanc:5,document:4,get:6,indic:5,inform:5,instal:6,list:5,measur:5,method:5,miscellan:5,object:0,octav:0,pre:6,pyspi:[2,3,4],reduc:0,s:4,set:0,similar:5,spectral:5,spi:0,start:6,statist:5,theori:5,toolkit:0,us:0,usag:6,welcom:4,without:0}}) -------------------------------------------------------------------------------- /docs/source/advanced.rst: -------------------------------------------------------------------------------- 1 | Advanced 2 | ======== 3 | 4 | The Data object 5 | --------------------- 6 | 7 | The MTS data is contained within the :class:`~pyspi.data.Data` object, along with preprocessed properties of the MTS that allows us to efficiently compute the methods. 8 | If you want more control over how the MTS are treated upon input, you can directly instantiate a :class:`~pyspi.data.Data` object for inputting to the calculator: 9 | 10 | .. code-block:: 11 | 12 | from pyspi.data import Data 13 | from pyspi.calculator import Calculator 14 | import numpy as np 15 | 16 | M = 10 # Number of processes 17 | T = 1000 # Number of observations 18 | 19 | z = np.random.rand(M,T) 20 | 21 | # The dim_order argument specifies which dimension is a process (p) and an observation (s). 22 | # The normalise argument specifies if we should z-score the data. 23 | dataset = Data(data=z,dim_order='ps',normalise=False) 24 | 25 | calc = Calculator(dataset=dataset) 26 | 27 | 28 | Using a reduced SPI set 29 | ----------------------- 30 | 31 | The :class:`~pyspi.calculator.Calculator` object computes 283 SPIs by default, but you may only be interested in a subset of these. 32 | We provide three pre-configured reduced SPI subsets that you may wish to try: 33 | 34 | * :code:`fast`: Most SPIs (excluding those that are computationally expensive) 35 | * :code:`sonnet` - 14 SPIs, one from each of the data-driven clusters as described in `Cliff et al. (2023) `_ 36 | * :code:`fabfour` - 4 SPIs that are simple and computationally efficient: Pearson correlation, Spearman correlation, directed information with a Gaussian density estimator, and the power envelope correlation. 37 | 38 | You may specify any one of these subsets when you instantiate the :code:`Calculator` object: 39 | 40 | .. code-block:: 41 | 42 | from pyspi.calculator import Calculator 43 | calc = Calculator(dataset=dataset, subset='sonnet') 44 | 45 | Alternatively, if you would like to use your own bespoke set of SPIs, you can copy a version of the :code:`config.yaml` file to your workspace and edit it to remove any SPIs that you would not like the :code:`Calculator` to compute. 46 | First, copy the :code:`config.yaml` file to your workspace: 47 | 48 | .. code-block:: console 49 | 50 | $ cp /pyspi/config.yaml myconfig.yaml 51 | 52 | Once you've got a local version, edit the :code:`myconfig.yaml` file to remove any SPIs you're not interested in. 53 | A minimal configuration file might look like the following if you're only interested in computing a covariance matrix using the maximum likelihood estimator: 54 | 55 | .. code-block:: 56 | 57 | # Basic statistics 58 | .statistics.basic: 59 | # Covariance 60 | covariance: 61 | # Maximum likehood estimator 62 | - estimator: EmpiricalCovariance 63 | 64 | Now, when you instantiate the calculator, instead of using the default :code:`config.yaml`, you can input your bespoke configuration file: 65 | 66 | .. code-block:: 67 | 68 | from pyspi.calculator import Calculator 69 | 70 | calc = Caculator(dataset=dataset,configfile='myconfig.yaml') 71 | 72 | Then use the calculator as normal (see :ref:`Usage`). 73 | 74 | .. note:: 75 | We have provided a detailed list of many of the statistics included in this toolkit (and the configuration file) in the Supplementary Material of our `preprint `_, and will include an up-to-date list of statistics in this documentation shortly. 76 | However, if you have any questions about a particular implementation, do not hesitate to raise an issue in the `github repo `_ for any assistance. 77 | 78 | Using the toolkit without Octave 79 | -------------------------------- 80 | 81 | If you do not wish to first install Octave before using the toolkit, remove the yaml entries for :code:`integrated_information` in the :code:`config.yaml` file (see :ref:`Using a reduced SPI set`). -------------------------------------------------------------------------------- /docs/source/api.rst: -------------------------------------------------------------------------------- 1 | API 2 | === 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | pyspi.calculator.Calculator 8 | pyspi.data.Data -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | 3 | # -- Project information 4 | 5 | project = 'pyspi' 6 | copyright = '2022, Oliver M. Cliff' 7 | author = 'Oliver M. Cliff' 8 | 9 | release = '0.4' 10 | version = '0.4.0' 11 | 12 | # -- General configuration 13 | 14 | extensions = [ 15 | 'sphinx.ext.duration', 16 | 'sphinx.ext.doctest', 17 | 'sphinx.ext.autodoc', 18 | 'sphinx.ext.autosummary', 19 | 'sphinx.ext.autosectionlabel', 20 | 'sphinx.ext.intersphinx', 21 | 'sphinx.ext.napoleon' 22 | ] 23 | 24 | napoleon_use_param = True 25 | 26 | intersphinx_mapping = { 27 | 'python': ('https://docs.python.org/3/', None), 28 | 'sphinx': ('https://www.sphinx-doc.org/en/master/', None), 29 | 'numpy': ('https://numpy.org/doc/stable/', None), 30 | 'pandas': ('https://pandas.pydata.org/docs/',None) 31 | } 32 | intersphinx_disabled_domains = ['std'] 33 | 34 | templates_path = ['_templates'] 35 | 36 | # -- Options for HTML output 37 | 38 | html_theme = 'sphinx_rtd_theme' 39 | 40 | # -- Options for EPUB output 41 | epub_show_urls = 'footnote' 42 | 43 | napoleon_type_aliases = { 44 | 'array-like': ':term:`array-like `', 45 | 'array_like': ':term:`array_like`', 46 | "dict-like": ":term:`dict-like `", 47 | } -------------------------------------------------------------------------------- /docs/source/generated/pyspi.calculator.Calculator.rst: -------------------------------------------------------------------------------- 1 | pyspi.calculator.Calculator 2 | =========================== 3 | 4 | .. currentmodule:: pyspi.calculator 5 | 6 | .. autoclass:: Calculator 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | .. rubric:: Methods 13 | 14 | .. autosummary:: 15 | 16 | ~Calculator.__init__ 17 | ~Calculator.compute 18 | ~Calculator.getstatlabels 19 | ~Calculator.load_dataset 20 | ~Calculator.set_group 21 | 22 | 23 | 24 | 25 | 26 | .. rubric:: Attributes 27 | 28 | .. autosummary:: 29 | 30 | ~Calculator.dataset 31 | ~Calculator.group 32 | ~Calculator.group_name 33 | ~Calculator.labels 34 | ~Calculator.n_spis 35 | ~Calculator.name 36 | ~Calculator.spis 37 | ~Calculator.table 38 | 39 | -------------------------------------------------------------------------------- /docs/source/generated/pyspi.data.Data.rst: -------------------------------------------------------------------------------- 1 | pyspi.data.Data 2 | =============== 3 | 4 | .. currentmodule:: pyspi.data 5 | 6 | .. autoclass:: Data 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | .. rubric:: Methods 13 | 14 | .. autosummary:: 15 | 16 | ~Data.__init__ 17 | ~Data.add_process 18 | ~Data.convert_to_numpy 19 | ~Data.remove_process 20 | ~Data.set_data 21 | ~Data.to_numpy 22 | 23 | 24 | 25 | 26 | 27 | .. rubric:: Attributes 28 | 29 | .. autosummary:: 30 | 31 | ~Data.name 32 | ~Data.procnames 33 | 34 | -------------------------------------------------------------------------------- /docs/source/img/pyspi_scaling_heatmaps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/img/pyspi_scaling_heatmaps.png -------------------------------------------------------------------------------- /docs/source/img/pyspi_scaling_line_plots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/docs/source/img/pyspi_scaling_line_plots.png -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to pyspi's documentation! 2 | =================================== 3 | 4 | **pyspi** (/pie'spy/) is a Python library for simultaneously evaluating hundreds of pairwise interactions directly from multivariate time-series data. 5 | 6 | It provides easy access to over 250 methods for evaluating the relationship between pairs of time series, from simple statistics (like correlation coefficients) to advanced multi-step algorithms (like Granger causality). 7 | 8 | Check out the :doc:`usage` section for further information, including :ref:`Installation` instructions. 9 | 10 | .. note:: 11 | 12 | This documentation and project is under active development. 13 | 14 | Contents 15 | -------- 16 | 17 | .. toctree:: 18 | 19 | installation 20 | usage 21 | advanced 22 | api 23 | faq -------------------------------------------------------------------------------- /docs/source/installation.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | =================================== 3 | 4 | We make two key recommendations for using `pyspi` described in the pre-installation. 5 | 6 | Pre-installation 7 | ---------------- 8 | 9 | The code requires GNU's `Octave `_ by default, which is freely available on all popular operating systems. 10 | See the `installation instructions `_ to find out how to install Octave on your system. 11 | 12 | .. note:: 13 | You can safely install `pyspi` without first installing Octave but you will not have access to the `Integrated Information Theory` statistics, see :ref:`Using the toolkit without Octave`. 14 | 15 | While you can also install `pyspi` outside of a `conda `_ environment, it depends on a lot of user packages that may make managing dependencies quite difficult. 16 | So we recommend installing `pyspi` in a conda environment. 17 | After `installing conda `_, create a new environment for using the toolkit: 18 | 19 | .. code-block:: console 20 | 21 | $ conda create -n pyspi python=3.9.0 22 | $ conda activate pyspi 23 | 24 | 25 | Installation 26 | ------------ 27 | 28 | Download or clone the `latest version of pyspi `_ from GitHub, unpack and install: 29 | 30 | .. code-block:: console 31 | 32 | $ git clone https://github.com/olivercliff/pyspi.git 33 | $ cd pyspi 34 | $ pip install . 35 | 36 | You can confirm that `pyspi` and dependencies installed properly with the following command: 37 | 38 | .. code-block:: console 39 | 40 | $ setup.py test 41 | 42 | If you have issues with installation (e.g., on Mac or Windows), check out the FAQ page. 43 | 44 | Docker Image 45 | ------------ 46 | 47 | Alternatively, you can use the `pyspi Docker image `_, which contains all the dependencies and the toolkit itself. 48 | After downloading Docker Desktop and creating an account, you can run the following commands to pull and run the image: 49 | 50 | .. code-block:: console 51 | 52 | $ docker pull arianguyen/pyspi:v1.0 53 | $ docker run -it arianguyen/pyspi:v1.0 54 | 55 | This should start a python session with `pyspi` installed and ready to import. 56 | -------------------------------------------------------------------------------- /docs/source/statistics.rst: -------------------------------------------------------------------------------- 1 | List of methods 2 | =========================== 3 | 4 | The full default set of over 250 pairwise interactions are produced by running all of the code files below. 5 | In our default statistics set, most functions are run with multiple input parameters. 6 | 7 | Basic statistics 8 | ---------------- 9 | 10 | In this section, we detail SPIs that are traditional techniques for performing statistical inference in bivariate systems. 11 | 12 | .. list-table:: 13 | :widths: 25 25 50 14 | :header-rows: 1 15 | 16 | * - Method name 17 | - Description 18 | - Identifier 19 | * - :code:`covariance` 20 | - Covariance matrix 21 | - :code:`cov` 22 | * - :code:`precision` 23 | - Precision matrix 24 | - :code:`prec` 25 | * - :code:`spearmanr` 26 | - Spearman correlation 27 | - :code:`spearmanr` 28 | 29 | Distance similarity 30 | ------------------- 31 | 32 | In this section, we detail SPIs that we have categorized as distance-based similarity measures in that they 33 | aim to establish statistical similarity or independence based on the pairwise distance between bivariate 34 | observations 35 | 36 | Causal indices 37 | -------------- 38 | 39 | In this section, we detail the 10 SPIs that are derived from causal inference models. 40 | 41 | Information Theory 42 | ------------------ 43 | 44 | The pairwise measures that we employ from information theory are either intended to operate on serially independent observations (e.g., joint entropy and mutual information) or bivariate time series (e.g., 45 | transfer entropy and stochastic interaction). 46 | 47 | Spectral measures 48 | ----------------- 49 | 50 | Spectral SPIs are computed in the frequency or time-frequency domain, using either Fourier or wavelet 51 | transformations to derive spectral matrices. 52 | 53 | Miscellaneous 54 | ------------- 55 | 56 | A small number of methods do not fit squarely into any category listed above, and so we place them 57 | in a 'miscellaneous' category -------------------------------------------------------------------------------- /docs/source/usage.rst: -------------------------------------------------------------------------------- 1 | Usage 2 | ===== 3 | 4 | 5 | Getting Started 6 | --------------- 7 | 8 | In order to demonstrate the functionality of this software, we will first need a sample multivariate time series (MTS). 9 | We will use data generated from a multivariate Gaussian: 10 | 11 | .. code-block:: 12 | 13 | import numpy as np 14 | import random 15 | 16 | random.seed(42) 17 | 18 | M = 5 # 5 processes 19 | T = 500 # 500 observations 20 | 21 | dataset = np.random.randn(M,T) 22 | 23 | Now, given our dataset, we can instantiate the :class:`~pyspi.calculator.Calculator` object: 24 | 25 | .. code-block:: 26 | 27 | from pyspi.calculator import Calculator 28 | 29 | calc = Calculator(dataset=dataset) 30 | 31 | And, using only the :meth:`~pyspi.calculator.Calculator.compute` method, we can compute over 250 statistics for analysing pairwise interactions in the MTS. 32 | 33 | .. code-block:: 34 | 35 | calc.compute() 36 | 37 | .. note:: 38 | While we tried to make the calculator as efficient as possible, computing all statistics can take a while (depending on the size of your dataset). 39 | You can use a faster set of statistics by instantiating the calculator with :code:`subset=fast`, see :class:`~pyspi.calculator.Calculator`. 40 | We also provide a reduced set of statistics that are useful for many applications, with the option for users to design their own subset of statistics; see :ref:`Using a reduced SPI set`. 41 | 42 | Once the calculator has computed each of the statistics, you can access all values using the :attr:`~pyspi.calculator.Calculator.table` property: 43 | 44 | .. code-block:: 45 | 46 | print(calc.table) 47 | 48 | Or, extract one matrix of pairwise interactions (MPI) for a given method using their unique `identifier`. 49 | For instance, the following code will extract the covariance matrix computed with the maximum likelihood estimator: 50 | 51 | .. code-block:: 52 | 53 | print(calc.table['cov_EmpiricalCovariance']) 54 | 55 | The identifiers for many of the statistics are outlined in the Supplementary Material of our `preprint `_. 56 | -------------------------------------------------------------------------------- /img/pyspi_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/img/pyspi_logo.png -------------------------------------------------------------------------------- /pyspi/__init__.py: -------------------------------------------------------------------------------- 1 | # For some reason the JVM causes a segfault with OpenBLAS (numpy's linalg sovler). Need to halt multithreading before starting JVM: 2 | import os, logging, sys 3 | 4 | os.environ['OMP_NUM_THREADS'] = '1' 5 | 6 | # formatter = logging.Formatter('[%(levelname)s: %(asctime)s]: %(message)s') 7 | 8 | # ch = logging.StreamHandler() 9 | # ch.setFormatter(formatter) 10 | # ch.setLevel(logging.DEBUG) 11 | 12 | # logger = logging.getLogger() 13 | # logger.addHandler(ch) 14 | # logger.setLevel(logging.INFO) 15 | 16 | # logging.captureWarnings(True) 17 | # logging.basicConfig(stream=, level=logging.INFO) -------------------------------------------------------------------------------- /pyspi/base.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from pyspi.data import Data 3 | import warnings, copy 4 | 5 | """ 6 | Some parsing functions for decorating so that we can either input the time series directly or use the data structure 7 | """ 8 | def parse_univariate(function): 9 | def parsed_function(self,data,i=None,inplace=True): 10 | if not isinstance(data,Data): 11 | data1 = data 12 | data = Data(data=data1) 13 | elif not inplace: 14 | # Ensure we don't write over the original 15 | data = copy.deepcopy(data) 16 | 17 | if i is None: 18 | if data.n_processes == 1: 19 | i = 0 20 | else: 21 | raise ValueError('Require argument i to be set.') 22 | 23 | return function(self,data,i=i) 24 | 25 | return parsed_function 26 | 27 | def parse_bivariate(function): 28 | def parsed_function(self,data,data2=None,i=None,j=None,inplace=True): 29 | if not isinstance(data,Data): 30 | if data2 is None: 31 | raise TypeError('Input must be either a pyspi.data object or two 1D-array inputs.' 32 | f' Received {type(data)} and {type(data2)}.') 33 | data1 = data 34 | data = Data() 35 | data.add_process(data1) 36 | data.add_process(data2) 37 | elif not inplace: 38 | # Ensure we don't write over the original 39 | data = copy.deepcopy(data) 40 | 41 | if i is None and j is None: 42 | if data.n_processes == 2: 43 | i,j = 0,1 44 | else: 45 | Warning('i and j not set.') 46 | 47 | return function(self,data,i=i,j=j) 48 | 49 | return parsed_function 50 | 51 | def parse_multivariate(function): 52 | def parsed_function(self,data,inplace=True): 53 | if not isinstance(data,Data): 54 | # Create a pyspi.Data object from iterable data object 55 | try: 56 | procs = data 57 | data = Data() 58 | for p in procs: 59 | data.add_process(p) 60 | except IndexError: 61 | raise TypeError('Data must be either a pyspi.data.Data object or an and iterable of numpy.ndarray''s.') 62 | elif not inplace: 63 | # Ensure we don't write over the original 64 | data = copy.deepcopy(data) 65 | 66 | return function(self,data) 67 | 68 | return parsed_function 69 | 70 | class Directed: 71 | """ Base class for directed statistics 72 | """ 73 | 74 | name = 'Bivariate base class' 75 | identifier = 'bivariate_base' 76 | labels = ['signed'] 77 | 78 | @parse_bivariate 79 | def bivariate(self,data,i=None,j=None): 80 | """ Overload method for getting the pairwise dependencies 81 | """ 82 | raise NotImplementedError("Method not yet overloaded.") 83 | 84 | @parse_multivariate 85 | def multivariate(self,data): 86 | """ Compute the dependency statistics for the entire multivariate dataset 87 | """ 88 | A = np.empty((data.n_processes,data.n_processes)) 89 | A[:] = np.NaN 90 | 91 | for j in range(data.n_processes): 92 | for i in [ii for ii in range(data.n_processes) if ii != j]: 93 | A[i,j] = self.bivariate(data,i=i,j=j) 94 | return A 95 | 96 | def get_group(self,classes): 97 | for i, i_cls in enumerate(classes): 98 | for j, j_cls in enumerate(classes): 99 | if i == j: 100 | continue 101 | assert not set(i_cls).issubset(set(j_cls)), (f'Class {i_cls} is a subset of class {j_cls}.') 102 | 103 | self._group = None 104 | self._group_name = None 105 | 106 | labset = set(self.labels) 107 | matches = [set(cls).issubset(labset) for cls in classes] 108 | 109 | if np.count_nonzero(matches) > 1: 110 | warnings.warn(f'More than one match for classes {classes}') 111 | else: 112 | try: 113 | id = np.where(matches)[0][0] 114 | self._group = id 115 | self._group_name = ', '.join(classes[id]) 116 | return self._group, self._group_name 117 | except (TypeError,IndexError): 118 | pass 119 | return None 120 | 121 | class Undirected(Directed): 122 | """ Base class for directed statistics 123 | """ 124 | 125 | name = 'Base class' 126 | identifier = 'base' 127 | labels = ['unsigned'] 128 | 129 | def ispositive(self): 130 | return False 131 | 132 | @parse_multivariate 133 | def multivariate(self,data): 134 | A = super(Undirected,self).multivariate(data) 135 | 136 | li = np.tril_indices(data.n_processes,-1) 137 | A[li] = A.T[li] 138 | return A 139 | 140 | class Signed: 141 | """ Base class for signed SPIs 142 | """ 143 | def issigned(self): 144 | return True 145 | 146 | class Unsigned: 147 | """ Base class for unsigned SPIs 148 | """ 149 | def issigned(self): 150 | return False -------------------------------------------------------------------------------- /pyspi/data/cml.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/pyspi/data/cml.npy -------------------------------------------------------------------------------- /pyspi/data/forex.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/pyspi/data/forex.npy -------------------------------------------------------------------------------- /pyspi/fabfour_config.yaml: -------------------------------------------------------------------------------- 1 | # Pearson and Spearman correlation statistics 2 | .statistics.basic: 3 | # Covariance 4 | Covariance: 5 | - estimator: EmpiricalCovariance 6 | 7 | # Spearman's correlation coefficient 8 | SpearmanR: 9 | - squared: True 10 | 11 | # Directed information with a Gaussian density estimator 12 | .statistics.infotheory: 13 | DirectedInfo: 14 | - estimator: gaussian 15 | 16 | # Power envelope correlation 17 | .statistics.misc: 18 | PowerEnvelopeCorrelation: 19 | - orth: False 20 | log: False 21 | absolute: False -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/Phi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/pyspi/lib/PhiToolbox/Phi/__init__.py -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/Phi/phi_G_Gauss.m: -------------------------------------------------------------------------------- 1 | function [ phi_G, Cov_E_p, A_p ] = phi_G_Gauss( Cov_X, Cov_XY, Cov_Y, Z, method, normalization ) 2 | % Calculate integrated information "phi_G" based on information geometry. 3 | % See Oizumi et al., 2016, PNAS for the details. 4 | % http://www.pnas.org/content/113/51/14817.full 5 | % 6 | % INPUTS: 7 | % Cov_X: covariance of data X (past, t-tau). n by n matrix (n is the number of variables). 8 | % Cov_XY: cross-covariance of X (past, t-tau) and Y (present, t). 9 | % Cov_Y: covariance of data Y (present, t) 10 | % Z: partition 11 | % - 1 by n matrix. Each element value indicates the group number which the element belongs to. 12 | % - Ex.1: (1:n) (atomic partition) [default] 13 | % - Ex.2: [1, 2,2,2, 3,3, ..., K,K] (K is the number of groups) 14 | % - Ex.3: [3, 1, K, 2, 2, ..., K, 2] (Groups don't have to be sorted in ascending order) 15 | % method: optimization method, 'AL'|'LI' 16 | % - 'AL': Augmented Lagrangian 17 | % - 'LI': a combination of LBFGS method and Iterative method 18 | % Note: AL tends to be faster than LI when the number of gropus K is small 19 | % but is slower when K is large. Thus, by default, this function 20 | % chooses AL when K<=3 and LI when K>3. 21 | % 22 | % normalization: 23 | % 0: without normalization by Entropy (default) 24 | % 1: with normalization by Entropy 25 | % 26 | % 27 | % OUTPUTS: 28 | % phi_G: integrated information based on information geometry 29 | % Cov_E_p: covariance of noise E in the disconnected model 30 | % A_p: connectivity matrix in the disconnected model 31 | % 32 | % Jun Kitazono & Masafumi Oizumi, 2017 33 | 34 | 35 | % Transform covariance matrices to parameters in AR model, Y = AX+E. 36 | A = Cov_XY'/Cov_X; 37 | Cov_E = Cov_Y - Cov_XY'/Cov_X*Cov_XY; 38 | 39 | if nargin < 4 || isempty(Z) 40 | n = size(Cov_X,1); 41 | Z = 1:n; 42 | end 43 | if nargin < 5 || isempty(method) 44 | K = length(unique(Z)); 45 | if K <= 3 46 | method = 'AL'; 47 | else 48 | method = 'LI'; 49 | end 50 | end 51 | if nargin < 6 || isempty(normalization) 52 | normalization = 0; 53 | end 54 | 55 | switch method 56 | case 'AL' 57 | [phi_G, Cov_E_p, A_p] = phi_G_Gauss_AL( Cov_X, Cov_E, A, Z, normalization ); 58 | case 'LI' 59 | [phi_G, Cov_E_p, A_p] = phi_G_Gauss_LBFGS( Cov_X, Cov_E, A, Z, normalization ); 60 | end 61 | 62 | 63 | end 64 | 65 | -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/Phi/phi_G_Gauss_AL.m: -------------------------------------------------------------------------------- 1 | function [ phi_G, Cov_E_p, A_p ] = phi_G_Gauss_AL( Cov_X, Cov_E, A, Z, normalization ) 2 | % Calculate integrated information "phi_G" based on information geometry 3 | % with an augmented Lagrangian method 4 | % 5 | % See Oizumi et al., 2016, PNAS for the details of phi_G 6 | % http://www.pnas.org/content/113/51/14817.full 7 | % 8 | % The code assumes a vector AutoRegressive (VAR) model Y = AX+E, 9 | % where X and Y are the past and present states, A is the connectivity matrix, and E is Gaussian random variables. 10 | % 11 | % INPUTS: 12 | % Cov_X: equal time covariace of X. n by n matrix (n is the number of variables). 13 | % Cov_E: covariance of noise E. n by n matrix. 14 | % A: connectivity (autoregressive) matrix (n by n). 15 | % Z: partition 16 | % - 1 by n matrix. Each element value indicates the group number to which the element belongs. 17 | % - Ex.1: (1:n) (atomic partition) 18 | % - Ex.2: [1, 2,2,2, 3,3, ..., K,K] (K is the number of groups) 19 | % - Ex.3: [3, 1, K, 2, 2, ..., K, 2] (Groups don't have to be sorted in ascendeing order) 20 | % normalization: 21 | % 0: without normalization by Entropy (default) 22 | % 1: with normalization by Entropy 23 | % 24 | % OUTPUTS: 25 | % phi_G: integrated information based on information geometry 26 | % Cov_E_p: covariance of noise E in the disconnected model 27 | % A_p: connectivity matrix in the disconnected model 28 | % 29 | % Masafumi Oizumi, 2016 30 | % Jun Kitazono, 2017 31 | % 32 | % Modification History 33 | % - made the code able to receive any partition as input (J. Kitazono) 34 | % - changed the optimization method from steepest descent to Augmented Lagrangian 35 | % (J. Kitazono) 36 | 37 | maxiter = 100000; 38 | error = 10^-10; 39 | mu = 2; 40 | alpha = 0.9; 41 | gamma = 1.01; 42 | 43 | if nargin < 4 44 | Z = 1: 1: N; 45 | end 46 | if nargin < 5 47 | normalization = 0; 48 | end 49 | 50 | n = size(Cov_X,1); 51 | 52 | N_c = max(Z); % number of groups 53 | M_cell = cell(N_c,1); 54 | for i=1: N_c 55 | M_cell{i} = find(Z==i); 56 | end 57 | 58 | % set initial values of the connectivity matrix in disconnected model 59 | A_p = zeros(n,n); 60 | for i=1: N_c 61 | M = M_cell{i}; 62 | A_p(M,M) = A(M,M); 63 | end 64 | B = A_p; 65 | 66 | Lambda = zeros(n,n); 67 | 68 | [Q, D_Cov_X] = eig( Cov_X ); 69 | 70 | Cov_E_p = Cov_E; 71 | for iter = 1:maxiter 72 | Cov_E_p_past = Cov_E_p; 73 | A_diff = A-A_p; 74 | Cov_E_p = Cov_E + A_diff*Cov_X*A_diff'; 75 | 76 | [P, D_Cov_E_p] = eig(Cov_E_p); 77 | 78 | A_p = P* ( ( P'*(B + Lambda/mu )*Q + D_Cov_E_p\P'*A*Q*D_Cov_X/mu ) ./ ... 79 | (1 + bsxfun(@ldivide, diag(D_Cov_E_p), diag(D_Cov_X)')/mu) ) * Q'; 80 | 81 | B = A_p/2 ; 82 | for i=1: N_c 83 | M = M_cell{i}; 84 | B(M,M) = B(M,M)*2; 85 | end 86 | 87 | Lambda = Lambda - mu * (A_p-B); 88 | 89 | val_constraint = sum((A_p(:)-B(:)).^2); 90 | if iter > 1 91 | if val_constraint > alpha*val_constraint_past 92 | mu = gamma*mu; 93 | end 94 | end 95 | val_constraint_past = val_constraint; 96 | 97 | phi_update = logdet(Cov_E_p) - logdet(Cov_E_p_past); 98 | if abs(phi_update) < error 99 | break; 100 | end 101 | 102 | end 103 | 104 | phi_G = (logdet(Cov_E_p)-logdet(Cov_E))/2; 105 | % disp(['iter: ', num2str(iter), ', phi: ', num2str(phi_G)]) 106 | 107 | if normalization == 1 108 | H_p = zeros(N_c,1); 109 | for i=1: N_c 110 | M = M_cell{i}; 111 | Cov_X_p = Cov_X(M,M); 112 | H_p(i) = H_gauss(Cov_X_p); 113 | end 114 | if N_c == 1 115 | phi_G = phi_G/H_p(1); 116 | else 117 | phi_G = phi_G/( (N_c-1)*min(H_p) ); 118 | end 119 | end 120 | 121 | end 122 | 123 | -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/Phi/phi_G_Gauss_LBFGS.m: -------------------------------------------------------------------------------- 1 | function [phi_G, Cov_E_p, A_p] = phi_G_Gauss_LBFGS( Cov_X, Cov_E, A, Z, normalization ) 2 | % Calculate integrated information "phi_G" based on information geometry 3 | % with a combination of an interative method and a quasi-Newton (LBFGS) method. 4 | % 5 | % See Oizumi et al., 2016, PNAS for the details of phi_G 6 | % http://www.pnas.org/content/113/51/14817.full 7 | % 8 | % The code assumes a vector AutoRegressive (VAR) model Y = AX+E, 9 | % where X and Y are the past and present states, A is the connectivity matrix, and E is Gaussian random variables. 10 | % 11 | % 12 | % INPUTS: 13 | % Cov_X: equal time covariace of X. n by n matrix (n is the number of variables). 14 | % Cov_E: covariance of noise E. n by n matrix. 15 | % A: connectivity (autoregressive) matrix (n by n). 16 | % Z: partition 17 | % - 1 by n matrix. Each element value indicates the group number to which the element belongs. 18 | % - Ex.1: (1:n) (atomic partition) 19 | % - Ex.2: [1, 2,2,2, 3,3, ..., K,K] (K is the number of groups) 20 | % - Ex.3: [3, 1, K, 2, 2, ..., K, 2] (Groups don't have to be sorted in ascending order) 21 | % normalization: 22 | % 0: without normalization by Entropy (default) 23 | % 1: with normalization by Entropy 24 | % 25 | % OUTPUTS: 26 | % phi_G: integrated information based on information geometry 27 | % Cov_E_p: covariance of noise E in the disconnected model 28 | % A_p: connectivity matrix in the disconnected model 29 | % 30 | % 31 | % Masafumi Oizumi, 2016 32 | % Jun Kitazono, 2017 33 | % 34 | % Modification History 35 | % - made the code able to receive any partition as input (J. Kitazono) 36 | % - changed the optimization method from steepest descent to an interative method and a quasi-Newton (LBFGS) method. 37 | % (J. Kitazono) 38 | % 39 | % This code uses an open optimization toolbox "minFunc" written by M. Shmidt. 40 | % M. Schmidt. minFunc: unconstrained differentiable multivariate optimization in Matlab. 41 | % http://www.cs.ubc.ca/~schmidtm/Software/minFunc.html 42 | % [Copyright 2005-2015 Mark Schmidt. All rights reserved] 43 | 44 | addpath(genpath('minFunc_2012')) 45 | 46 | if nargin < 4 47 | Z = 1: 1: N; 48 | end 49 | if nargin < 5 50 | normalization = 0; 51 | end 52 | 53 | n = size(Cov_X,1); 54 | 55 | n_c = max(Z); % number of groups 56 | M_cell = cell(n_c,1); 57 | for i=1: n_c 58 | M_cell{i} = find(Z==i); 59 | end 60 | 61 | % set initial values of the connectivity matrix in the disconnected model 62 | A_p = zeros(n,n); 63 | nnz_A_p = 0; 64 | for i=1: n_c 65 | M = M_cell{i}; 66 | A_p(M,M) = A(M,M); 67 | nnz_A_p = nnz_A_p + length(M)^2; 68 | end 69 | 70 | iter_max = 10000; 71 | error = 10^-10; 72 | 73 | % set options of minFunc 74 | Options.Method = 'lbfgs'; 75 | Options.progTol = 10^-10; 76 | Options.MaxFunEvals = 4000; 77 | Options.MaxIter = 2000; 78 | Options.display = 'off'; 79 | % Options.useMex = 0; 80 | 81 | Cov_E_p = Cov_E; 82 | for iter=1: iter_max 83 | Cov_E_p_past = Cov_E_p; 84 | 85 | x = A_p2vec(A_p, nnz_A_p, M_cell); 86 | 87 | f = @(x)phi_G_grad_Ap( x, Cov_E_p, Cov_X, Cov_E, A, M_cell ); 88 | [x, ~, ~, ~] = minFunc(f, x, Options); 89 | 90 | A_p = vec2A_p( x, n, M_cell ); 91 | 92 | Cov_E_p = Cov_E + (A-A_p)*Cov_X*(A-A_p)'; 93 | 94 | phi_update = logdet(Cov_E_p) - logdet(Cov_E_p_past); 95 | if abs(phi_update) < error 96 | break; 97 | end 98 | 99 | end 100 | 101 | phi_G = 1/2*(logdet(Cov_E_p)-logdet(Cov_E)); 102 | % disp(['iter: ', num2str(iter), ', phi: ', num2str(phi_G)]) 103 | 104 | if normalization == 1 105 | H_p = zeros(N_c,1); 106 | for i=1: N_c 107 | M = M_cell{i}; 108 | Cov_X_p = Cov_X(M,M); 109 | H_p(i) = H_gauss(Cov_X_p); 110 | end 111 | if N_c == 1 112 | phi_G = phi_G/H_p(1); 113 | else 114 | phi_G = phi_G/( (N_c-1)*min(H_p) ); 115 | end 116 | end 117 | 118 | end 119 | 120 | function [phi_IG, D_A_vec] = phi_G_grad_Ap( x, Cov_E_p, Cov_X, Cov_E, A, partition_cell ) 121 | 122 | 123 | N = size(Cov_X,1); 124 | 125 | A_p = zeros(size(A)); 126 | idx_st = 0; 127 | for i = 1:length(partition_cell) 128 | M = partition_cell{i}; 129 | nnz_cell_i = length(M); 130 | idx_end = nnz_cell_i^2; 131 | A_p(M,M) = reshape(x(idx_st + (1:idx_end)), [nnz_cell_i, nnz_cell_i]); 132 | idx_st = idx_st + idx_end; 133 | end 134 | 135 | R = [Cov_X Cov_X*A'; A*Cov_X Cov_E+A*Cov_X*A']; 136 | Rd = [Cov_X Cov_X*A_p'; A_p*Cov_X Cov_E_p+A_p*Cov_X*A_p']; 137 | Rd_inv = [inv(Cov_X)+A_p'/Cov_E_p*A_p -A_p'/Cov_E_p; -Cov_E_p\A_p inv(Cov_E_p)]; 138 | 139 | TR = trace(R*Rd_inv); 140 | phi_IG = 1/2*(-logdet(R) + TR + logdet(Rd) - 2*N); 141 | 142 | 143 | A_diff = A_p - A; 144 | 145 | D_A = 2*Cov_E_p\A_diff*Cov_X; 146 | D_A_vec = zeros(length(x),1); 147 | idx_st = 0; 148 | for i = 1:length(partition_cell) 149 | M = partition_cell{i}; 150 | nnz_cell_i = length(M); 151 | idx_end = nnz_cell_i^2; 152 | D_A_vec(idx_st + (1:idx_end)) = reshape(D_A(M,M), [idx_end, 1]); 153 | idx_st = idx_st + idx_end; 154 | end 155 | 156 | 157 | end 158 | 159 | function A_p = vec2A_p( x, N, partition_cell ) 160 | % tramsform vector to matrix 161 | 162 | A_p = zeros(N,N); 163 | idx_st = 0; 164 | for i = 1:length(partition_cell) 165 | M = partition_cell{i}; 166 | nnz_cell_i = length(M); 167 | idx_end = nnz_cell_i^2; 168 | 169 | A_p(M,M) = reshape(x(idx_st+(1:idx_end)), [nnz_cell_i, nnz_cell_i]); 170 | idx_st = idx_st + idx_end; 171 | end 172 | 173 | 174 | end 175 | 176 | function x = A_p2vec( A_p, nnz_A_p, partition_cell ) 177 | % transform matrix to vector 178 | 179 | x = zeros(nnz_A_p,1); 180 | idx_st = 0; 181 | for i = 1:length(partition_cell) 182 | M = partition_cell{i}; 183 | idx_end = length(M)^2; 184 | x(idx_st + (1:idx_end)) = reshape(A_p(M,M), [idx_end 1]); 185 | idx_st = idx_st + idx_end; 186 | end 187 | 188 | 189 | end 190 | 191 | -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/Phi/phi_Gauss.m: -------------------------------------------------------------------------------- 1 | function phi = phi_Gauss( type_of_phi, Z, probs, options) 2 | % Compute phi for Gaussian disbributions 3 | % 4 | % INPUTS: 5 | % type_of_phi: 6 | % 'MI1': Multi (Mutual) information, e.g., I(X_1; X_2). (IIT1.0) 7 | % 'MI': Multi (Mutual) information, e.g., I(X_1, Y_1; X_2, Y_2) 8 | % 'SI': phi_H, stochastic interaction 9 | % 'star': phi_star, based on mismatched decoding 10 | % 'Geo': phi_G, information geometry version 11 | % Z: partition 12 | % - 1 by n matrix. Each element indicates the group number. 13 | % - Ex.1: (1:n) (atomic partition) 14 | % - Ex.2: [1, 2,2,2, 3,3, ..., K,K] (K is the number of groups) 15 | % - Ex.3: [3, 1, K, 2, 2, ..., K, 2] (Groups don't have to be sorted in ascending order) 16 | % - Not accept [1, 3], [1,2,4,2] (Group indices must be consecutive numbers from 1 to K) 17 | % 18 | % probs: probability distributions for computing phi 19 | % probs.Cov_X: covariance of data X (past, t-tau) 20 | % probs.Cov_XY: cross-covariance of X (past, t-tau) and Y (present, t) 21 | % probs.Cov_Y: covariance of data Y (present, t) 22 | % 23 | % options 24 | % options.normalization: 25 | % 0: without normalization by Entropy (default) 26 | % 1: with normalization by Entropy 27 | % options.phi_G_OptimMethod: 28 | % 'AL': Augmented Lagrangian 29 | % 'LI': a combination of LBFGS method and Iterative method 30 | % 31 | % OUTPUT: 32 | % phi: amount of integrated information 33 | %----------------------------------------------------------------------- 34 | 35 | Cov_X = probs.Cov_X; 36 | if ~strcmp(type_of_phi,'MI1') 37 | Cov_XY = probs.Cov_XY; 38 | Cov_Y = probs.Cov_Y; 39 | end 40 | 41 | % check type_of_phi 42 | assert( isa( type_of_phi, 'char' ) ) 43 | list_types_of_phi = {'MI1', 'MI', 'SI', 'star', 'Geo'}; 44 | if ~any( strcmp(type_of_phi, list_types_of_phi) ) 45 | error('type_of_phi must be selected from MI1, MI, SI, star or Geo!') 46 | end 47 | 48 | % check Z 49 | assert( isa( Z, 'double' ) ) 50 | [nZr, nZc] = size(Z); 51 | if nZr~=1 && nZc~=1 52 | error('Partition Z must be 1 by n row vector or n by 1 column vector.') 53 | end 54 | unique_Z = unique(Z); 55 | if ~isequal( max(Z), length(unique_Z) ) 56 | error('Group indices must be consecutive numbers from 1 to K.') 57 | %error('Partition Z must include at least one elment from each group!') 58 | end 59 | % if length(unique_Z) < 2 60 | % error('Partition Z must consist of multiple groups!') 61 | % end 62 | 63 | % check Cov_X 64 | assert( isa( Cov_X, 'double' ) ) 65 | [nXr, nXc] = size(Cov_X); 66 | if ~isequal( max(nZr,nZc), nXr, nXc) 67 | error('Sizes of Z and Cov_X do not match! Z: 1 by n vector, Cov_X: n by n matrix') 68 | end 69 | 70 | % % check Cov_XY and Cov_Y 71 | % if nargin >= 4 72 | % % if strcmp( type_of_phi, 'MI1' ) 73 | % % error('Cov_XY and Cov_Y are not needed for computation of MI1!') 74 | % % end 75 | % assert( isa( Cov_XY, 'double' ) ) 76 | % assert( isa( Cov_Y, 'double' ) ) 77 | % [nYr, nYc] = size(Cov_Y); 78 | % [nXYr, nXYc] = size(Cov_XY); 79 | % if ~isequal(max(nZr,nZc), nYr, nYc, nXYr, nXYc) 80 | % error('Sizes of Cov_X and Cov_Y (Cov_XY) do not match!') 81 | % end 82 | % end 83 | 84 | % check Geo_OptimMethod 85 | % if nargin == 4 86 | % % if ~strcmp( type_of_phi, 'Geo' ) 87 | % % error('The option phi_G_OptimMethod is available only for phi_G!') 88 | % % end 89 | % assert( isa( phi_G_OptimMethod, 'char' ) ) 90 | % if ~any(strcmp(phi_G_OptimMethod, {'AL', 'LI'})) 91 | % error('OptimMethod of phi_G must be AL or LI!') 92 | % end 93 | % end 94 | 95 | if isfield(options, 'normalization') 96 | normalization = options.normalization; 97 | else 98 | normalization = []; 99 | end 100 | if isfield(options, 'phi_G_OptimMethod') 101 | phi_G_OptimMethod = options.phi_G_OptimMethod; 102 | else 103 | phi_G_OptimMethod = []; 104 | end 105 | 106 | switch type_of_phi 107 | case 'MI1' 108 | phi = MI1_Gauss(Cov_X, Z, normalization); 109 | case 'MI' 110 | phi = MI_Gauss(Cov_X, Cov_XY, Cov_Y, Z, normalization); 111 | case 'SI' 112 | phi = SI_Gauss(Cov_X, Cov_XY, Cov_Y, Z, normalization); 113 | case 'star' 114 | beta_init = 1; 115 | phi = phi_star_Gauss(Cov_X, Cov_XY, Cov_Y, Z, beta_init, normalization); 116 | case 'Geo' 117 | phi = phi_G_Gauss(Cov_X, Cov_XY, Cov_Y, Z, phi_G_OptimMethod, normalization); 118 | end 119 | 120 | 121 | end -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/Phi/phi_comp.m: -------------------------------------------------------------------------------- 1 | function phi = phi_comp(X, Z, params, options) 2 | % Compute phi from time series data 3 | % 4 | % INPUTS: 5 | % X: time series data in the form (units X time) 6 | % Z: partition 7 | % - 1 by n matrix. Each element indicates the group number. 8 | % - Ex.1: (1:n) (atomic partition) 9 | % - Ex.2: [1, 2,2,2, 3,3, ..., K,K] (K is the number of groups) 10 | % - Ex.3: [3, 1, K, 2, 2, ..., K, 2] (Groups don't have to be sorted in ascending order) 11 | % params: parameters used for estimating probability distributions 12 | % (covariances in the case of Gaussian distribution) from time 13 | % series data 14 | % 15 | % params.tau: time lag between past and present states 16 | % params.number_of_states: number of states (only for the discrete case) 17 | % 18 | % options: options for computing phi 19 | % 20 | % options.type_of_dist: 21 | % 'Gauss': Gaussian distribution 22 | % 'discrete': discrete probability distribution 23 | % options.type_of_phi: 24 | % 'SI': phi_H, stochastic interaction 25 | % 'Geo': phi_G, information geometry version 26 | % 'star': phi_star, based on mismatched decoding 27 | % 'MI': Multi (Mutual) information, I(X_1, Y_1; X_2, Y_2) 28 | % 'MI1': Multi (Mutual) information. I(X_1; X_2). (IIT1.0) 29 | % options.normalization (available only for Gaussian dist.) 30 | % 0: without normalization by Entropy (default) 31 | % 1: with normalization by Entropy 32 | % options.phi_G_OptimMethod (available only for Gaussian dist.) 33 | % 'AL': Augmented Lagrangian 34 | % 'LI': a combination of LBFGS method and Iterative method 35 | % 36 | % 37 | % OUTPUT: 38 | % phi: integrated information 39 | 40 | probs = data_to_probs(X, params, options); 41 | phi = phi_comp_probs(options.type_of_dist, options.type_of_phi, Z, probs, options); 42 | 43 | end -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/Phi/phi_comp_probs.m: -------------------------------------------------------------------------------- 1 | function phi = phi_comp_probs(type_of_dist, type_of_phi, Z, probs, options) 2 | % Compute phi from probability distributions 3 | % 4 | % INPUTS: 5 | % type_of_dist: 6 | % 'Gauss': Gaussian distribution 7 | % 'dis': discrete probability distribution 8 | % type_of_phi: 9 | % 'SI': phi_H, stochastic interaction 10 | % 'Geo': phi_G, information geometry version 11 | % 'star': phi_star, based on mismatched decoding 12 | % 'MI': Multi (Mutual) information, I(X_1, Y_1; X_2, Y_2) 13 | % 'MI1': Multi (Mutual) information. I(X_1; X_2). (IIT1.0) 14 | % Z: partition 15 | % - 1 by n matrix. Each element indicates the group number. 16 | % - Ex.1: (1:n) (atomic partition) 17 | % - Ex.2: [1, 2,2,2, 3,3, ..., K,K] (K is the number of groups) 18 | % - Ex.3: [3, 1, K, 2, 2, ..., K, 2] (Groups don't have to be sorted in ascending order) 19 | % probs: probability distributions for computing phi 20 | % 21 | % In the Gaussian case 22 | % probs.Cov_X: covariance of data X (past, t-tau) 23 | % probs.Cov_XY: cross-covariance of X (past, t-tau) and Y (present, t) 24 | % probs.Cov_Y: covariance of data Y (present, t) 25 | % In the discrete case 26 | % probs.past: probability distribution of past state (X^t-tau) 27 | % probs.joint: joint distribution of X^t (present) and X^(t-\tau) (past) 28 | % probs.present: probability distribution of present state (X^t-tau) 29 | % 30 | % probs.p: probability distribution of X (only used for MI) 31 | % 32 | % options.normalization (available only for Gaussian dist.) 33 | % 0: without normalization by Entropy (default) 34 | % 1: with normalization by Entropy 35 | % options.phi_G_OptimMethod (available only for Gaussian dist.) 36 | % 'AL': Augmented Lagrangian 37 | % 'LI': a combination of LBFGS method and Iterative method 38 | % 39 | % 40 | % OUTPUT: 41 | % phi: integrated information 42 | 43 | switch type_of_dist 44 | case 'Gauss' 45 | phi = phi_Gauss( type_of_phi, Z, probs, options); 46 | case 'discrete' 47 | phi = phi_dis(type_of_phi, Z, probs); 48 | end 49 | 50 | end -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/Phi/phi_star_Gauss.m: -------------------------------------------------------------------------------- 1 | function [phi_star, I, beta_opt] = phi_star_Gauss(Cov_X,Cov_XY,Cov_Y,Z,beta_init, normalization) 2 | % Calculate integrated information "phi_star" based on mismatched decoding 3 | % See Oizumi et al., 2016, PLoS Comp for the details 4 | % http://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1004654 5 | % 6 | % INPUTS: 7 | % Cov_X: covariance of data X (PAST, t-tau) 8 | % Cov_XY: cross-covariance of X (past, t-tau) and Y (present, t) 9 | % Cov_Y: covariance of data Y (PRESENT, t) 10 | % Z: partition of each channel (default: atomic partition) 11 | % beta_init: initial value of beta (default: beta_int=1) 12 | % normalization: 13 | % 0: without normalization by Entropy (default) 14 | % 1: with normalization by Entropy 15 | % 16 | % OUTPUT: 17 | % phi_star: integrated information based on mismatched decoding 18 | % I: mutual information between X (past, t-tau) and Y (present, t) 19 | % 20 | % 21 | % Masafumi Oizumi, 2016 22 | % Jun Kitazono, 2017 23 | % 24 | % Modification History 25 | % - Changed the optimization method for beta from steepest descent to 26 | % a quasi-Newton method (Jun Kitazono) 27 | % - Fixed a bug in computing phi_star (Masafumi Oizumi) 28 | % 29 | % This code uses an open optimization toolbox "minFunc" written by M. Shmidt. 30 | % M. Schmidt. minFunc: unconstrained differentiable multivariate optimization in Matlab. 31 | % http://www.cs.ubc.ca/~schmidtm/Software/minFunc.html 32 | % [Copyright 2005-2015 Mark Schmidt. All rights reserved] 33 | % 34 | % Last update: Feb 12, 2018 35 | 36 | N = size(Cov_X,1); % number of channels 37 | if nargin < 3 || isempty(Cov_Y) 38 | Cov_Y = Cov_X; 39 | end 40 | if nargin < 4 || isempty(Z) 41 | Z = 1: 1: N; 42 | end 43 | if nargin < 5 || isempty(beta_init) 44 | beta_init = 1; 45 | end 46 | if nargin < 6 || isempty(normalization) 47 | normalization = 0; 48 | end 49 | 50 | Cov_Y_X = Cov_cond(Cov_Y,Cov_XY',Cov_X); % conditional covariance matrix 51 | H_cond = H_gauss(Cov_Y_X); 52 | 53 | if isinf(H_cond) == 1 54 | fprintf('Alert: Infinite Entropy\n') 55 | end 56 | 57 | if isreal(H_cond) == 0 58 | fprintf('Alert: Complex Entropy\n') 59 | end 60 | 61 | H = H_gauss(Cov_Y); % entropy 62 | I = H - H_cond; % mutual information 63 | 64 | N_c = max(Z); % number of clusters 65 | M_cell = cell(N_c,1); 66 | for i=1: N_c 67 | M_cell{i} = find(Z==i); 68 | end 69 | 70 | X_D = zeros(N,N); % Cov_D(X^t-tau) 71 | YX_D = zeros(N,N); % Cov_D(X^t,X^t-tau) 72 | C_D_cond = zeros(N,N); 73 | for i=1: N_c 74 | M = M_cell{i}; 75 | Cov_X_p = Cov_X(M,M); 76 | Cov_Y_p = Cov_Y(M,M); 77 | Cov_YX_p = Cov_XY(M,M)'; 78 | Cov_Y_X_p = Cov_cond(Cov_Y_p,Cov_YX_p,Cov_X_p); 79 | 80 | X_D(M,M) = Cov_X_p; 81 | YX_D(M,M) = Cov_YX_p; 82 | C_D_cond(M,M) = Cov_Y_X_p; 83 | end 84 | 85 | Cov_X_inv = inv(Cov_X); 86 | 87 | C_D_beta1_inv = X_D\YX_D'/C_D_cond*YX_D/X_D; % 2nd term of eq. (26)/beta 88 | S_left = C_D_cond'\YX_D/X_D; 89 | S_right = X_D\YX_D'/C_D_cond; 90 | 91 | I_s_d_Const_part = 1/2*N; 92 | 93 | %% find beta by a quasi-Newton method 94 | % if nargin < 3 95 | % beta_init = 1; 96 | % end 97 | beta = beta_init; 98 | 99 | % set options of minFunc 100 | Options.Method = 'lbfgs'; 101 | Options.Display = 'off'; 102 | % Options.useMex = 0; 103 | 104 | %% minimize negative I_s 105 | 106 | fh = @(beta)I_s_I_s_d(beta,C_D_beta1_inv,Cov_X_inv,Cov_X,Cov_Y,C_D_cond,S_left,S_right,I_s_d_Const_part); 107 | 108 | [beta_opt,minus_I_s,~,~] = fminunc(fh,beta,Options); 109 | I_s = -minus_I_s; 110 | 111 | %% 112 | phi_star = I - I_s; 113 | 114 | if normalization == 1 115 | H_p = zeros(N_c,1); 116 | for i=1: N_c 117 | M = M_cell{i}; 118 | Cov_X_p = Cov_X(M,M); 119 | H_p(i) = H_gauss(Cov_X_p); 120 | end 121 | if N_c == 1 122 | phi_star = phi_star/H_p(1); 123 | else 124 | phi_star = phi_star/( (N_c-1)*min(H_p) ); 125 | end 126 | end 127 | 128 | 129 | end -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/pyspi/lib/PhiToolbox/__init__.py -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/utility/Gauss/Cov_comp.m: -------------------------------------------------------------------------------- 1 | function probs = Cov_comp(X,tau,isjoint) 2 | %: Compute covarance matrices from time series data X 3 | % 4 | %----------------------------------------------------------------------- 5 | % INPUTS: 6 | % X: time series data in the form (units X time) 7 | % tau: time lag between past and present states 8 | % isjoint: whether or not joint covraiance matrices are computed 9 | % 10 | % OUTPUT: 11 | % probs: coraince matrices 12 | % When isjoint == 1 13 | % probs.Cov_X: covariance of data X (past, t-tau) 14 | % probs.Cov_XY: cross-covariance of X (past, t-tau) and Y (present, t) 15 | % probs.Cov_Y: covariance of data Y (present, t) 16 | % When isjoint == 0 17 | % probs.Cov_X: covariance of data X 18 | % 19 | %----------------------------------------------------------------------- 20 | 21 | if nargin < 3 22 | isjoint = 1; 23 | end 24 | 25 | T = size(X,2); 26 | 27 | if isjoint 28 | t_range1 = 1: 1: T-tau; 29 | t_range2 = 1+tau: 1: T; 30 | 31 | X1 = X(:,t_range1); 32 | X1 = bsxfun(@minus, X1, mean(X1,2)); % subtract mean 33 | X2 = X(:,t_range2); 34 | X2 = bsxfun(@minus, X2, mean(X2,2)); % subtract mean 35 | 36 | Cov_X = X1*X1'/(T-tau-1); % equal-time covariance matrix at "PAST" 37 | Cov_Y = X2*X2'/(T-tau-1); % equal-time covariance matrix at "PRESENT" 38 | Cov_XY = X1*X2'/(T-tau-1); % time-lagged covariance matrix 39 | 40 | probs.Cov_Y = Cov_Y; 41 | probs.Cov_XY = Cov_XY; 42 | else 43 | X = bsxfun(@minus, X, mean(X,2)); % subtract mean 44 | Cov_X = X*X'/(T-1); % equal-time covariance matrix 45 | end 46 | 47 | probs.Cov_X = Cov_X; 48 | 49 | end -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/utility/Gauss/Cov_cond.m: -------------------------------------------------------------------------------- 1 | function Cov_X_Y = Cov_cond(Cov_X,Cov_XY,Cov_Y) 2 | %% compute the partial covariance of X given Y 3 | % Input 4 | % Cov_X, Cov_Y: covariance of data X and Y 5 | % Cov_XY: cross covariance of X and Y 6 | 7 | % Output 8 | % Cov_X_Y: partial covariance of X given Y 9 | 10 | if nargin < 3 11 | Cov_Y = Cov_X; 12 | end 13 | 14 | Cov_X_Y = Cov_X - Cov_XY/Cov_Y*Cov_XY'; 15 | 16 | end 17 | -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/utility/Gauss/H_gauss.m: -------------------------------------------------------------------------------- 1 | function H = H_gauss(Cov_X) 2 | %----------------------------------------------------------------------- 3 | % FUNCTION: H_gauss.m 4 | % PURPOSE: calculate entropy under the gaussian assumption 5 | % 6 | % INPUTS: 7 | % Cov_X: covariance of data X 8 | % 9 | % OUTPUT: 10 | % H: entropy of X 11 | %----------------------------------------------------------------------- 12 | 13 | n = size(Cov_X,1); 14 | H = 1/2*logdet(Cov_X) + 1/2*n*log(2*pi*exp(1)); 15 | 16 | end -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/utility/Gauss/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/pyspi/lib/PhiToolbox/utility/Gauss/__init__.py -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/utility/Gauss/logdet.m: -------------------------------------------------------------------------------- 1 | function logdet_X = logdet(X) 2 | %% compute log of determinant of X 3 | 4 | n = size(X,1); 5 | Const = exp( sum( log(diag(X)) )/n ); 6 | 7 | X = X/Const; 8 | 9 | logdet_X = log(det(X)) + log(Const)*n; 10 | -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/utility/I_s_I_s_d.m: -------------------------------------------------------------------------------- 1 | function [minus_I_s, minus_I_s_d] = I_s_I_s_d(beta,C_D_beta1_inv,Cov_X_inv,Cov_X,Cov_Y,C_D_cond,S_left,S_right,I_s_d_Const_part) 2 | C_D_beta_inv = beta*C_D_beta1_inv; % 2nd term of eq. (26) 3 | Q_inv = Cov_X_inv + C_D_beta_inv; % Q_inv 4 | 5 | norm_t = 1/2*logdet(Q_inv) + 1/2*logdet(Cov_X); 6 | R = beta*inv(C_D_cond) - beta^2*S_left/Q_inv*S_right; 7 | 8 | trace_t = 1/2*trace(Cov_Y*R); 9 | I_s = norm_t + trace_t - beta*I_s_d_Const_part; 10 | minus_I_s = -I_s; 11 | 12 | Q_d = -Q_inv\C_D_beta1_inv/Q_inv; %derivative of Q 13 | R_d = inv(C_D_cond) - beta*S_left*2/Q_inv*S_right - beta*S_left*beta*Q_d*S_right; 14 | 15 | I_s_d = 1/2*(-trace(Q_inv*Q_d) + trace(Cov_Y*R_d)) - I_s_d_Const_part; % derivative of I_s 16 | minus_I_s_d = -I_s_d; 17 | end -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/utility/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/pyspi/lib/PhiToolbox/utility/__init__.py -------------------------------------------------------------------------------- /pyspi/lib/PhiToolbox/utility/data_to_probs.m: -------------------------------------------------------------------------------- 1 | function probs = data_to_probs(X, params, options) 2 | % Compute probability distributions for time series data X 3 | % 4 | %----------------------------------------------------------------------- 5 | % INPUTS: 6 | % X: time series data in the form (units X time) 7 | % 8 | % params: parameters used for estimating probability distributions 9 | % (covariances in the case of Gaussian distribution) from time 10 | % series data 11 | % 12 | % params.tau: time lag between past and present states 13 | % params.number_of_states: number of states (only for the discrete case) 14 | % 15 | % options: options for computing phi and for MIP search 16 | % 17 | % options.type_of_dist: 18 | % 'Gauss': Gaussian distribution 19 | % 'discrete': discrete probability distribution 20 | % options.type_of_phi: 21 | % 'SI': phi_H, stochastic interaction 22 | % 'Geo': phi_G, information geometry version 23 | % 'star': phi_star, based on mismatched decoding 24 | % 'MI': Multi (Mutual) information, I(X_1, Y_1; X_2, Y_2) 25 | % 'MI1': Multi (Mutual) information. I(X_1; X_2). (IIT1.0) 26 | % OUTPUTS: 27 | % probs: probability distributions used for computing phi 28 | % 29 | % In the Gaussian case 30 | % When options.type_of_phi is 'MI1' 31 | % probs.Cov_X: covariance of data X 32 | % When options.type_of_phi is NOT 'MI1' 33 | % probs.Cov_X: covariance of data X (past, t-tau) 34 | % probs.Cov_XY: cross-covariance of X (past, t-tau) and Y (present, t) 35 | % probs.Cov_Y: covariance of data Y (present, t) 36 | % In the discrete case 37 | % When options.type_of_phi is 'MI1' 38 | % probs.past: probability distribution of past state (X^t-tau) 39 | % probs.joint: joint distribution of X^t (present) and X^(t-\tau) (past) 40 | % probs.present: probability distribution of present state (X^t-tau) 41 | % When options.type_of_phi is NOT 'MI1' 42 | % probs.p: probability distribution of X 43 | % 44 | % 45 | %----------------------------------------------------------------------- 46 | 47 | 48 | tau = params.tau; 49 | 50 | switch options.type_of_phi 51 | case 'MI1' 52 | isjoint = 0; 53 | otherwise 54 | isjoint = 1; 55 | end 56 | 57 | switch options.type_of_dist 58 | case 'Gauss' 59 | probs = Cov_comp(X, tau, isjoint); 60 | case 'discrete' 61 | number_of_states = params.number_of_states; 62 | probs = est_p(X, number_of_states, tau, isjoint); 63 | probs.number_of_states = number_of_states; 64 | otherwise 65 | error('type_of_dist must be ''Guass'' or ''discrete''.') 66 | end 67 | 68 | probs.number_of_elements = size(X,1); 69 | 70 | end -------------------------------------------------------------------------------- /pyspi/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/pyspi/lib/__init__.py -------------------------------------------------------------------------------- /pyspi/lib/jidt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/pyspi/lib/jidt/__init__.py -------------------------------------------------------------------------------- /pyspi/lib/jidt/infodynamics.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/pyspi/lib/jidt/infodynamics.jar -------------------------------------------------------------------------------- /pyspi/lib/jidt/version-1.5.txt: -------------------------------------------------------------------------------- 1 | Java Information Dynamics Toolkit 2 | Copyright (C) 2012-2014 Joseph T. Lizier 3 | Copyright (C) 2014-2016 Joseph T. Lizier and Ipek Özdemir 4 | 5 | Version 1.5 6 | 7 | 25/11/2018 8 | 9 | -------------------------------------------------------------------------------- /pyspi/sonnet_config.yaml: -------------------------------------------------------------------------------- 1 | # Basic statistics 2 | .statistics.basic: 3 | # Covariance 4 | Covariance: 5 | - estimator: EmpiricalCovariance 6 | 7 | .statistics.distance: 8 | DynamicTimeWarping: 9 | - global_constraint: itakura 10 | 11 | Barycenter: 12 | - mode: dtw 13 | statistic: mean 14 | 15 | .statistics.causal: 16 | 17 | # Additive noise model 18 | AdditiveNoiseModel: 19 | 20 | 21 | # Information-theoretic statistics 22 | .statistics.infotheory: 23 | DirectedInfo: # No theiler window yet 24 | - estimator: gaussian 25 | 26 | # Transfer entropy 27 | TransferEntropy: 28 | - estimator: kraskov 29 | prop_k: 4 30 | auto_embed_method: MAX_CORR_AIS 31 | k_search_max: 10 32 | tau_search_max: 4 33 | dyn_corr_excl: AUTO 34 | 35 | # Integrated information 36 | IntegratedInformation: 37 | - phitype: 'star' 38 | 39 | # statistics that analyse in the frequency-domain (see Schoegl and Supp, 2006) 40 | .statistics.spectral: 41 | 42 | CoherenceMagnitude: 43 | - fs: 1 44 | 45 | PhaseSlopeIndex: 46 | - fmin: 0 47 | fmax: 0.5 48 | 49 | PhaseLagIndex: 50 | 51 | - fs: 1 52 | statistic: max 53 | 54 | SpectralGrangerCausality: 55 | # Non-parametric Granger causality (no VAR model) 56 | - method: nonparametric 57 | fmin: 0 58 | fmax: 0.5 59 | statistic: mean 60 | 61 | # statistics that analyse in the wavlet-domain (only Mortlet wavelet's at the moment) 62 | .statistics.wavelet: 63 | PhaseSlopeIndex: 64 | - fs: 1 65 | 66 | .statistics.misc: 67 | # Cointegration 68 | Cointegration: 69 | - method: aeg 70 | statistic: tstat 71 | autolag: aic 72 | maxlag: 10 73 | trend: ct 74 | 75 | # Power envelope correlation 76 | PowerEnvelopeCorrelation: 77 | - orth: False 78 | log: False 79 | absolute: False -------------------------------------------------------------------------------- /pyspi/statistics/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DynamicsAndNeuralSystems/pyspi_tmp/547babedc7192c0100f5de83a28adc59e877a65b/pyspi/statistics/__init__.py -------------------------------------------------------------------------------- /pyspi/statistics/basic.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | import sklearn.covariance as cov 3 | from scipy import stats, signal 4 | import numpy as np 5 | 6 | from pyspi.base import Undirected, Signed, parse_bivariate, parse_multivariate 7 | 8 | 9 | class Estimators(Undirected, Signed): 10 | """Base class for (functional) connectivity-based statistics 11 | 12 | Information on covariance estimators at: https://scikit-learn.org/stable/modules/covariance.html 13 | """ 14 | 15 | name = "Covariance" 16 | labels = ["basic", "unordered", "linear", "undirected"] 17 | 18 | def __init__(self, kind, estimator="EmpiricalCovariance", squared=False): 19 | paramstr = f"_{estimator}" 20 | if squared: 21 | paramstr = "-sq" + paramstr 22 | self.labels = Estimators.labels + ["unsigned"] 23 | self.issigned = lambda: False 24 | else: 25 | self.labels = Estimators.labels + ["signed"] 26 | self.identifier = self.identifier + paramstr 27 | self._squared = squared 28 | self._estimator = estimator 29 | self._kind = kind 30 | 31 | def _from_cache(self, data): 32 | try: 33 | mycov = data.covariance[self._estimator] 34 | except (AttributeError, KeyError): 35 | z = data.to_numpy(squeeze=True).T 36 | 37 | with warnings.catch_warnings(): 38 | warnings.simplefilter("ignore") 39 | mycov = getattr(cov, self._estimator)().fit(z) 40 | try: 41 | data.covariance[self._estimator] = mycov 42 | except AttributeError: 43 | data.covariance = {self._estimator: mycov} 44 | return mycov 45 | 46 | @parse_multivariate 47 | def multivariate(self, data): 48 | mycov = self._from_cache(data) 49 | matrix = getattr(mycov, self._kind + "_") 50 | np.fill_diagonal(matrix, np.nan) 51 | if self._squared: 52 | return np.square(matrix) 53 | else: 54 | return matrix 55 | 56 | 57 | class Covariance(Estimators): 58 | 59 | name = "Covariance" 60 | identifier = "cov" 61 | 62 | def __init__(self, estimator="EmpiricalCovariance", squared=False): 63 | super().__init__(kind="covariance", squared=squared, estimator=estimator) 64 | 65 | 66 | class Precision(Estimators): 67 | 68 | name = "Precision" 69 | identifier = "prec" 70 | 71 | def __init__(self, estimator="EmpiricalCovariance", squared=False): 72 | super().__init__(kind="precision", squared=squared, estimator=estimator) 73 | 74 | 75 | class CrossCorrelation(Undirected, Signed): 76 | 77 | name = "Cross correlation" 78 | labels = ["basic", "linear", "undirected", "temporal"] 79 | 80 | def __init__(self, squared=False, statistic="max", sigonly=True): 81 | self.identifier = "xcorr" 82 | self._squared = squared 83 | self._statistic = statistic 84 | self._sigonly = sigonly 85 | 86 | if self._squared: 87 | self.issigned = lambda: False 88 | self.identifier = self.identifier + "-sq" 89 | self.labels = CrossCorrelation.labels + ["unsigned"] 90 | else: 91 | self.labels = CrossCorrelation.labels + ["signed"] 92 | self.identifier += f"_{statistic}_sig-{sigonly}" 93 | 94 | @parse_bivariate 95 | def bivariate(self, data, i=None, j=None): 96 | 97 | T = data.n_observations 98 | try: 99 | r_ij = data.xcorr[(i, j)] 100 | except (KeyError, AttributeError): 101 | x, y = data.to_numpy()[[i, j]] 102 | 103 | r_ij = np.squeeze(signal.correlate(x, y, "full")) 104 | r_ij = r_ij / x.std() / y.std() / (T - 1) 105 | 106 | # Truncate to T/4 107 | r_ij = r_ij[T - T // 4 : T + T // 4] 108 | 109 | try: 110 | data.xcorr[(i, j)] = r_ij 111 | except AttributeError: 112 | data.xcorr = {(i, j): r_ij} 113 | data.xcorr[(j, i)] = data.xcorr[(i, j)] 114 | 115 | # Truncate at first statistically significant zero (i.e., |r| <= 1.96/sqrt(T)) 116 | if self._sigonly: 117 | N = len(r_ij) // 2 118 | fzf = np.where(np.abs(r_ij[len(r_ij) // 2 :]) <= 1.96 / np.sqrt(N))[0][0] 119 | fzr = np.where(np.abs(r_ij[: len(r_ij) // 2]) <= 1.96 / np.sqrt(N))[0][-1] 120 | r_ij = r_ij[N - fzr : N + fzf] 121 | 122 | if self._statistic == "max": 123 | if self._squared: 124 | return np.max(r_ij**2) 125 | else: 126 | return np.max(r_ij) 127 | elif self._statistic == "mean": 128 | if self._squared: 129 | return np.mean(r_ij**2) 130 | else: 131 | return np.mean(r_ij) 132 | else: 133 | raise TypeError(f"Unknown statistic: {self._statistic}") 134 | 135 | 136 | class SpearmanR(Undirected, Signed): 137 | 138 | name = "Spearman's correlation coefficient" 139 | identifier = "spearmanr" 140 | labels = ["basic", "unordered", "rank", "linear", "undirected"] 141 | 142 | def __init__(self, squared=False): 143 | self._squared = squared 144 | if squared: 145 | self.issigned = lambda: False 146 | self.identifier = self.identifier + "-sq" 147 | self.labels += ["unsigned"] 148 | else: 149 | self.labels += ["signed"] 150 | 151 | @parse_bivariate 152 | def bivariate(self, data, i=None, j=None): 153 | x, y = data.to_numpy()[[i, j]] 154 | if self._squared: 155 | return stats.spearmanr(x, y).correlation ** 2 156 | else: 157 | return stats.spearmanr(x, y).correlation 158 | 159 | 160 | class KendallTau(Undirected, Signed): 161 | 162 | name = "Kendall's tau" 163 | identifier = "kendalltau" 164 | labels = ["basic", "unordered", "rank", "linear", "undirected"] 165 | 166 | def __init__(self, squared=False): 167 | self._squared = squared 168 | if squared: 169 | self.issigned = lambda: False 170 | self.identifier = self.identifier + "-sq" 171 | self.labels += ["unsigned"] 172 | else: 173 | self.labels += ["signed"] 174 | 175 | @parse_bivariate 176 | def bivariate(self, data, i=None, j=None): 177 | x, y = data.to_numpy()[[i, j]] 178 | if self._squared: 179 | return stats.kendalltau(x, y).correlation ** 2 180 | else: 181 | return stats.kendalltau(x, y).correlation 182 | -------------------------------------------------------------------------------- /pyspi/statistics/causal.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | from cdt.causality.pairwise import ANM, CDS, IGCI, RECI 4 | import pyEDM 5 | 6 | from pyspi.base import Directed, Unsigned, Signed, parse_bivariate, parse_multivariate 7 | 8 | 9 | class AdditiveNoiseModel(Directed, Unsigned): 10 | 11 | name = "Additive noise model" 12 | identifier = "anm" 13 | labels = ["unsigned", "causal", "unordered", "linear", "directed"] 14 | 15 | @parse_bivariate 16 | def bivariate(self, data, i=None, j=None): 17 | z = data.to_numpy() 18 | return ANM().anm_score(z[i], z[j]) 19 | 20 | 21 | class ConditionalDistributionSimilarity(Directed, Unsigned): 22 | 23 | name = "Conditional distribution similarity statistic" 24 | identifier = "cds" 25 | labels = ["unsigned", "causal", "unordered", "nonlinear", "directed"] 26 | 27 | @parse_bivariate 28 | def bivariate(self, data, i=None, j=None): 29 | z = data.to_numpy() 30 | return CDS().cds_score(z[i], z[j]) 31 | 32 | 33 | class RegressionErrorCausalInference(Directed, Unsigned): 34 | 35 | name = "Regression error-based causal inference" 36 | identifier = "reci" 37 | labels = ["unsigned", "causal", "unordered", "nonlinear", "directed"] 38 | 39 | @parse_bivariate 40 | def bivariate(self, data, i=None, j=None): 41 | z = data.to_numpy() 42 | return RECI().b_fit_score(z[i], z[j]) 43 | 44 | 45 | class InformationGeometricConditionalIndependence(Directed, Unsigned): 46 | 47 | name = "Information-geometric conditional independence" 48 | identifier = "igci" 49 | labels = ["causal", "directed", "nonlinear", "unsigned", "unordered"] 50 | 51 | @parse_bivariate 52 | def bivariate(self, data, i=None, j=None): 53 | z = data.to_numpy() 54 | return IGCI().predict_proba((z[i], z[j])) 55 | 56 | 57 | class ConvergentCrossMapping(Directed, Signed): 58 | 59 | name = "Convergent cross-mapping" 60 | identifier = "ccm" 61 | labels = ["causal", "directed", "nonlinear", "temporal", "signed"] 62 | 63 | def __init__(self, statistic="mean", embedding_dimension=None): 64 | self._statistic = statistic 65 | self._E = embedding_dimension 66 | 67 | self.identifier += f"_E-{embedding_dimension}_{statistic}" 68 | 69 | @property 70 | def key(self): 71 | return self._E 72 | 73 | def _from_cache(self, data): 74 | try: 75 | ccmf = data.ccm[self.key] 76 | except (AttributeError, KeyError): 77 | z = data.to_numpy(squeeze=True) 78 | 79 | M = data.n_processes 80 | N = data.n_observations 81 | df = pd.DataFrame( 82 | np.concatenate([np.atleast_2d(np.arange(0, N)), z]).T, 83 | columns=["index"] + [f"proc{p}" for p in range(M)], 84 | ) 85 | 86 | # Get the embedding 87 | if self._E is None: 88 | embedding = np.zeros((M, 1)) 89 | 90 | # Infer optimal embedding from simplex projection 91 | for _i in range(M): 92 | pred = str(10) + " " + str(N - 10) 93 | embed_df = pyEDM.EmbedDimension( 94 | dataFrame=df, 95 | lib=pred, 96 | pred=pred, 97 | columns=df.columns.values[_i + 1], 98 | showPlot=False, 99 | ) 100 | embedding[_i] = embed_df.max()["E"] 101 | else: 102 | embedding = np.array([self._E] * M) 103 | 104 | # Compute CCM from the fixed or optimal embedding 105 | nlibs = 21 106 | ccmf = np.zeros((M, M, nlibs + 1)) 107 | for _i in range(M): 108 | for _j in range(_i + 1, M): 109 | try: 110 | E = int(max(embedding[[_i, _j]])) 111 | except NameError: 112 | E = int(self._E) 113 | 114 | # Get list of library sizes given nlibs and lower/upper bounds based on embedding dimension 115 | upperE = int(np.floor((N - E - 1) / 10) * 10) 116 | lowerE = int(np.ceil(2 * E / 10) * 10) 117 | inc = int((upperE - lowerE) / nlibs) 118 | lib_sizes = str(lowerE) + " " + str(upperE) + " " + str(inc) 119 | srcname = df.columns.values[_i + 1] 120 | targname = df.columns.values[_j + 1] 121 | ccm_df = pyEDM.CCM( 122 | dataFrame=df, 123 | E=E, 124 | columns=srcname, 125 | target=targname, 126 | libSizes=lib_sizes, 127 | sample=100, 128 | ) 129 | ccmf[_i, _j] = ccm_df.iloc[:, 1].values[: (nlibs + 1)] 130 | ccmf[_j, _i] = ccm_df.iloc[:, 2].values[: (nlibs + 1)] 131 | 132 | try: 133 | data.ccm[self.key] = ccmf 134 | except AttributeError: 135 | data.ccm = {self.key: ccmf} 136 | return ccmf 137 | 138 | @parse_multivariate 139 | def multivariate(self, data): 140 | ccmf = self._from_cache(data) 141 | 142 | if self._statistic == "mean": 143 | return np.nanmean(ccmf, axis=2) 144 | elif self._statistic == "max": 145 | return np.nanmax(ccmf, axis=2) 146 | elif self._statistic == "diff": 147 | return np.nanmean(ccmf - np.transpose(ccmf, axes=[1, 0, 2]), axis=2) 148 | else: 149 | raise TypeError(f"Unknown statistic: {self._statistic}") 150 | -------------------------------------------------------------------------------- /pyspi/statistics/misc.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | import numpy as np 3 | 4 | from statsmodels.tsa import stattools 5 | from statsmodels.tsa.vector_ar.vecm import coint_johansen 6 | from sklearn.gaussian_process import kernels, GaussianProcessRegressor 7 | from sklearn.metrics import mean_squared_error 8 | from sklearn import linear_model 9 | import mne.connectivity as mnec 10 | 11 | from pyspi.base import ( 12 | Directed, 13 | Undirected, 14 | Unsigned, 15 | parse_bivariate, 16 | parse_multivariate, 17 | ) 18 | 19 | 20 | class Cointegration(Undirected, Unsigned): 21 | 22 | name = "Cointegration" 23 | identifier = "coint" 24 | labels = ["misc", "unsigned", "temporal", "undirected", "nonlinear"] 25 | 26 | def __init__( 27 | self, 28 | method="johansen", 29 | statistic="trace_stat", 30 | det_order=1, 31 | k_ar_diff=1, 32 | autolag="aic", 33 | maxlag=10, 34 | trend="c", 35 | ): 36 | self._method = method 37 | self._statistic = statistic 38 | if method == "johansen": 39 | self.identifier += ( 40 | f"_{method}_{statistic}_order-{det_order}_ardiff-{k_ar_diff}" 41 | ) 42 | self._det_order = det_order 43 | self._k_ar_diff = k_ar_diff 44 | else: 45 | self._autolag = autolag 46 | self._maxlag = maxlag 47 | self._trend = trend 48 | self.identifier += ( 49 | f"_{method}_{statistic}_trend-{trend}_autolag-{autolag}_maxlag-{maxlag}" 50 | ) 51 | 52 | @property 53 | def key(self): 54 | key = (self._method,) 55 | if self._method == "johansen": 56 | return key + (self._det_order, self._k_ar_diff) 57 | else: 58 | return key + (self._autolag, self._maxlag, self._trend) 59 | 60 | def _from_cache(self, data, i, j): 61 | idx = (i, j) 62 | try: 63 | ci = data.coint[self.key][idx] 64 | except (KeyError, AttributeError): 65 | z = data.to_numpy(squeeze=True) 66 | 67 | if self._method == "aeg": 68 | stats = stattools.coint( 69 | z[i], 70 | z[j], 71 | autolag=self._autolag, 72 | maxlag=self._maxlag, 73 | trend=self._trend, 74 | ) 75 | 76 | ci = {"tstat": stats[0]} 77 | else: 78 | stats = coint_johansen( 79 | z[[i, j]].T, det_order=self._det_order, k_ar_diff=self._k_ar_diff 80 | ) 81 | 82 | ci = { 83 | "max_eig_stat": stats.max_eig_stat[0], 84 | "trace_stat": stats.trace_stat[0], 85 | } 86 | 87 | try: 88 | data.coint[self.key][idx] = ci 89 | except AttributeError: 90 | data.coint = {self.key: {idx: ci}} 91 | except KeyError: 92 | data.coint[self.key] = {idx: ci} 93 | data.coint[self.key][(j, i)] = ci 94 | 95 | return ci 96 | 97 | # Return the negative t-statistic (proxy for how co-integrated they are) 98 | @parse_bivariate 99 | def bivariate(self, data, i=None, j=None, verbose=False): 100 | ci = self._from_cache(data, i, j) 101 | return ci[self._statistic] 102 | 103 | 104 | class LinearModel(Directed, Unsigned): 105 | name = "Linear model regression" 106 | identifier = "lmfit" 107 | labels = ["misc", "unsigned", "unordered", "normal", "linear", "directed"] 108 | 109 | def __init__(self, model): 110 | self.identifier += f"_{model}" 111 | self._model = getattr(linear_model, model) 112 | 113 | @parse_bivariate 114 | def bivariate(self, data, i=None, j=None): 115 | z = data.to_numpy() 116 | with warnings.catch_warnings(): 117 | warnings.simplefilter("ignore") 118 | mdl = self._model().fit(z[i], np.ravel(z[j])) 119 | y_predict = mdl.predict(z[i]) 120 | return mean_squared_error(y_predict, np.ravel(z[j])) 121 | 122 | 123 | class GPModel(Directed, Unsigned): 124 | name = "Gaussian process regression" 125 | identifier = "gpfit" 126 | labels = ["misc", "unsigned", "unordered", "normal", "nonlinear", "directed"] 127 | 128 | def __init__(self, kernel="RBF"): 129 | self.identifier += f"_{kernel}" 130 | self._kernel = kernels.ConstantKernel() + kernels.WhiteKernel() 131 | self._kernel += getattr(kernels, kernel)() 132 | 133 | @parse_bivariate 134 | def bivariate(self, data, i=None, j=None): 135 | z = data.to_numpy() 136 | 137 | with warnings.catch_warnings(): 138 | warnings.simplefilter("ignore") 139 | gp = GaussianProcessRegressor(kernel=self._kernel).fit(z[i], np.ravel(z[j])) 140 | y_predict = gp.predict(z[i]) 141 | return mean_squared_error(y_predict, np.ravel(z[j])) 142 | 143 | 144 | class PowerEnvelopeCorrelation(Undirected, Unsigned): 145 | humanname = "Power envelope correlation" 146 | identifier = "pec" 147 | labels = ["unsigned", "misc", "undirected"] 148 | 149 | def __init__(self, orth=False, log=False, absolute=False): 150 | self._orth = False 151 | if orth: 152 | self._orth = "pairwise" 153 | self.identifier += "_orth" 154 | self._log = log 155 | if log: 156 | self.identifier += "_log" 157 | self._absolute = absolute 158 | if absolute: 159 | self.identifier += "_abs" 160 | 161 | @parse_multivariate 162 | def multivariate(self, data): 163 | z = np.moveaxis(data.to_numpy(), 2, 0) 164 | adj = np.squeeze( 165 | mnec.envelope_correlation( 166 | z, orthogonalize=self._orth, log=self._log, absolute=self._absolute 167 | ) 168 | ) 169 | np.fill_diagonal(adj, np.nan) 170 | return adj 171 | -------------------------------------------------------------------------------- /pyspi/utils.py: -------------------------------------------------------------------------------- 1 | """pyspi utility functions.""" 2 | import numpy as np 3 | from scipy.stats import zscore 4 | import warnings 5 | import pandas as pd 6 | 7 | def _contains_nan(a, nan_policy='propagate'): 8 | policies = ['propagate', 'raise', 'omit'] 9 | if nan_policy not in policies: 10 | raise ValueError("nan_policy must be one of {%s}" % 11 | ', '.join("'%s'" % s for s in policies)) 12 | try: 13 | # Calling np.sum to avoid creating a huge array into memory 14 | # e.g. np.isnan(a).any() 15 | with np.errstate(invalid='ignore'): 16 | contains_nan = np.isnan(np.sum(a)) 17 | except TypeError: 18 | # If the check cannot be properly performed we fallback to omitting 19 | # nan values and raising a warning. This can happen when attempting to 20 | # sum things that are not numbers (e.g. as in the function `mode`). 21 | contains_nan = False 22 | nan_policy = 'omit' 23 | warnings.warn("The input array could not be properly checked for nan " 24 | "values. nan values will be ignored.", RuntimeWarning) 25 | 26 | if contains_nan and nan_policy == 'raise': 27 | raise ValueError("The input contains nan values") 28 | 29 | return (contains_nan, nan_policy) 30 | 31 | 32 | def strshort(instr,mlength): 33 | """Shorten a string using ellipsis 34 | """ 35 | if isinstance(instr,list): 36 | outstr = [] 37 | for i in range(len(instr)): 38 | cstr = instr[i] 39 | outstr.append((cstr[:mlength-6] + '...' + cstr[-3:]) if len(cstr) > mlength else cstr) 40 | else: 41 | outstr = (instr[:mlength-6] + '...' + instr[-3:]) if len(instr) > mlength else instr 42 | return outstr 43 | 44 | def acf(x,mode='positive'): 45 | """Return the autocorrelation function 46 | """ 47 | if x.ndim > 1: 48 | x = np.squeeze(x) 49 | 50 | x = zscore(x) 51 | acf = np.correlate(x,x,mode='full') 52 | acf = acf / acf[acf.size//2] 53 | 54 | if mode == 'positive': 55 | return acf[acf.size//2:] 56 | else: 57 | return acf 58 | 59 | def swap_chars(s, i_1, i_2): 60 | """Swap to characters in a string. 61 | 62 | Example: 63 | >>> print(swap_chars('heLlotHere', 2, 6)) 64 | 'heHlotLere' 65 | """ 66 | if i_1 > i_2: 67 | i_1, i_2 = i_2, i_1 68 | return ''.join([s[0:i_1], s[i_2], s[i_1+1:i_2], s[i_1], s[i_2+1:]]) 69 | 70 | def normalise(a, axis=0, nan_policy='propogate'): 71 | 72 | contains_nan, nan_policy = _contains_nan(a, nan_policy) 73 | 74 | if contains_nan and nan_policy == 'omit': 75 | return (a - np.nanmin(a,axis=axis)) / (np.nanmax(a,axis=axis) - np.nanmin(a,axis=axis)) 76 | else: 77 | return (a - np.min(a,axis=axis)) / (np.max(a,axis=axis) - np.min(a,axis=axis)) 78 | 79 | def standardise(a, dimension=0, df=1): 80 | """Z-standardise a numpy array along a given dimension. 81 | 82 | Standardise array along the axis defined in dimension using the denominator 83 | (N - df) for the calculation of the standard deviation. 84 | 85 | Args: 86 | a : numpy array 87 | data to be standardised 88 | dimension : int [optional] 89 | dimension along which array should be standardised 90 | df : int [optional] 91 | degrees of freedom for the denominator of the standard derivation 92 | 93 | Returns: 94 | numpy array 95 | standardised data 96 | """ 97 | # Avoid division by standard devitation if the process is constant. 98 | a_sd = a.std(axis=dimension, ddof=df) 99 | 100 | if np.isclose(a_sd, 0): 101 | return a - a.mean(axis=dimension) 102 | else: 103 | return (a - a.mean(axis=dimension)) / a_sd 104 | 105 | def convert_mdf_to_ddf(df): 106 | ddf = pd.pivot_table(data=df.stack(dropna=False).reset_index(),index='Dataset',columns=['SPI-1', 'SPI-2'],dropna=False).T.droplevel(0) 107 | return ddf -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | scikit-learn==0.24.1 3 | scipy==1.7.3 4 | numpy>=1.21.1 5 | pandas>=1.3.3 6 | statsmodels==0.12.1 7 | pyyaml==5.4 8 | tqdm==4.50.2 9 | nitime==0.9 10 | hyppo==0.2.1 11 | pyEDM==1.9.3 12 | jpype1==1.2.0 13 | sktime==0.8.0 14 | dill==0.3.2 15 | spectral-connectivity==0.2.4.dev0 16 | torch==1.10.0 17 | cdt==0.5.23 18 | oct2py==5.2.0 19 | tslearn==0.5.2 20 | mne==0.23.0 21 | seaborn==0.11.0 22 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | # http://www.diveintopython3.net/packaging.html 4 | # https://pypi.python.org/pypi?:action=list_classifiers 5 | 6 | with open('README.md') as file: 7 | long_description = file.read() 8 | 9 | 10 | install_requires = [ 11 | 'scikit-learn==0.24.1', 12 | 'scipy==1.7.3', 13 | 'numpy>=1.21.1', 14 | 'pandas>=1.3.3', 15 | 'statsmodels==0.12.1', 16 | 'pyyaml==5.4', 17 | 'tqdm==4.50.2', 18 | 'nitime==0.9', 19 | 'hyppo==0.2.1', 20 | 'pyEDM==1.9.3', 21 | 'jpype1==1.2.0', 22 | 'sktime==0.8.0', 23 | 'dill==0.3.2', 24 | 'spectral-connectivity==0.2.4.dev0', 25 | 'torch==1.10.0', 26 | 'cdt==0.5.23', 27 | 'oct2py==5.2.0', 28 | 'tslearn==0.5.2', 29 | 'mne==0.23.0', 30 | 'seaborn==0.11.0' 31 | ] 32 | 33 | testing_extras = [ 34 | 'pytest==5.4.2', # unittest.TestCase funkyness, see commit 77c1505ab 35 | ] 36 | 37 | docs_extras = [ 38 | 'Sphinx >= 3.0.0', # Force RTD to use >= 3.0.0 39 | 'docutils', 40 | 'pylons-sphinx-themes >= 1.0.8', # Ethical Ads 41 | 'pylons_sphinx_latesturl', 42 | 'repoze.sphinx.autointerface', 43 | 'sphinx-copybutton', 44 | 'sphinxcontrib-autoprogram', 45 | ] 46 | 47 | setup( 48 | name='pyspi', 49 | packages=find_packages(), 50 | package_data={'': ['config.yaml', 51 | 'sonnet_config.yaml', 52 | 'fast_config.yaml', 53 | 'fabfour_config.yaml', 54 | 'lib/jidt/infodynamics.jar', 55 | 'lib/PhiToolbox/Phi/phi_comp.m', 56 | 'lib/PhiToolbox/Phi/phi_star_Gauss.m', 57 | 'lib/PhiToolbox/Phi/phi_G_Gauss.m', 58 | 'lib/PhiToolbox/Phi/phi_G_Gauss_AL.m', 59 | 'lib/PhiToolbox/Phi/phi_G_Gauss_LBFGS.m', 60 | 'lib/PhiToolbox/Phi/phi_comp_probs.m', 61 | 'lib/PhiToolbox/Phi/phi_Gauss.m', 62 | 'lib/PhiToolbox/utility/I_s_I_s_d.m', 63 | 'lib/PhiToolbox/utility/data_to_probs.m', 64 | 'lib/PhiToolbox/utility/Gauss/Cov_comp.m', 65 | 'lib/PhiToolbox/utility/Gauss/Cov_cond.m', 66 | 'lib/PhiToolbox/utility/Gauss/H_gauss.m', 67 | 'lib/PhiToolbox/utility/Gauss/logdet.m', 68 | 'data/cml.npy', 69 | 'data/forex.npy']}, 70 | include_package_data=True, 71 | version='0.4.0', 72 | description='Network analysis for time series', 73 | author='Oliver M. Cliff', 74 | author_email='oliver.m.cliff@gmail.com', 75 | url='https://github.com/olivercliff/pyspi', 76 | long_description=long_description, 77 | classifiers=[ 78 | "Programming Language :: Python", 79 | "Programming Language :: Python :: 3", 80 | "Development Status :: 1 - Planning", 81 | "Operating System :: POSIX :: Linux", 82 | "Intended Audience :: Science/Research", 83 | "Environment :: Console", 84 | "Environment :: Other Environment", 85 | "Topic :: Scientific/Engineering :: Physics", 86 | "Topic :: Scientific/Engineering :: Bio-Informatics", 87 | "Topic :: Scientific/Engineering :: Information Analysis", 88 | "Topic :: Scientific/Engineering :: Medical Science Apps.", 89 | ], 90 | install_requires=install_requires, 91 | extras_require={'testing': testing_extras, 'docs': docs_extras} 92 | ) 93 | --------------------------------------------------------------------------------