diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..b9f295a --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,61 @@ +# ... +# Copyright 2021 Brooks M. Musangu and Jan Drugowitsch. +# license Modified BSD, see LICENSE.txt for details. +# ... +name: CI Tests and Docs + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + test: + name: Run Pytest Suite + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install package and test dependencies + run: | + python -m pip install --upgrade pip + pip install .[test] + + - name: Run tests + run: | + pytest test/ + + docs: + name: Build Documentation + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install Pandoc + run: | + sudo apt-get update + sudo apt-get install -y pandoc + + - name: Install docs dependencies + run: | + python -m pip install --upgrade pip + pip install .[docs] + + - name: Build Sphinx documentation + run: | + sphinx-build -b html docs docs/_build diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..4304ba8 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,17 @@ +# .readthedocs.yml +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.13" + +python: + install: + - method: pip + path: . + extra_requirements: + - docs + +sphinx: + configuration: docs/conf.py diff --git a/README.md b/README.md index 18cf359..b5b285d 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,35 @@ -# GPFA_for_sklearn +# BlockInvGPFA + +[![Automated Tests](https://github.com/CausalityInMotion/BlockInverseGPFA/actions/workflows/tests.yml/badge.svg)](https://github.com/CausalityInMotion/BlockInverseGPFA/actions/workflows/tests.yml) +[![Documentation Status](https://readthedocs.org/projects/blockinversegpfa/badge/?version=latest)](https://blockinversegpfa.readthedocs.io/en/latest/) + +This package provides a Python implementation of **Gaussian Process Factor Analysis (GPFA)** that incorporates a novel approach to efficiently handle variable-length time series data. Building on the original method by [Byron Yu et al. (2009)](https://papers.nips.cc/paper/2009/hash/6c1b887a379c4f0c2c621f305d15f6b0-Abstract.html), this implementation introduces a **block-matrix–based inversion strategy** that reuses kernel computations across trials of different lengths. + +The package also includes **scikit-learn–compatible API** for integration into existing ML workflows such as: +- A **Modular Preprocessing** — Separates data preprocessing from model logic via a dedicated `EventTimesToCounts` transformer. + - Accepts standard array-like inputs (not `Neo` objects), simplifying integration with other tools. + - Follows scikit-learn's transformer–estimator interface for clean, reusable workflows. +- A new **variance-explained metric** to evaluate GPFA model fits. + +This implementation is adapted from [Elephant](https://elephant.readthedocs.io/en/latest/reference/gpfa.html)’s GPFA codebase with substantial modifications to improve performance, modularity, and usability in Python-based pipelines. -This package is an implementation of Gaussian Process Factor Analysis (GPFA) by Byron Yu et al., -(2009) in python. The code is based on [Elephant](https://elephant.readthedocs.io/en/latest/reference/gpfa.html)'s -python implementation plus additional modules and functional implementations. ## Usage ### Installation ----------------- -- Clone the project locally using +Install directly from GitHub using `pip`: ```bash -$ git clone https://github.com/CausalityInMotion/GPFA_for_sklearn +$ pip install git+https://github.com/CausalityInMotion/BlockInverseGPFA.git ``` - -Ensure you are in the working directory of the project. - -Then install the project's required packages uisng +Or clone the repo and install locally: ```bash -$ pip install -r requirements.txt +$ git clone https://github.com/CausalityInMotion/BlockInverseGPFA.git +$ cd BlockInverseGPFA +$ pip install . # or pip install .[test,docs] to include optional dependencies ``` You are now set to use the package. @@ -36,33 +45,38 @@ Building the documentation requires the following packages: - [numpydoc](https://numpydoc.readthedocs.io/) - [Jupyter Notebook Tools for Sphinx](https://nbsphinx.readthedocs.io/) -You can install the required packages either using the `docs/requirements.txt` file, +You can install the required documentation dependencies by: ```bash -$ pip install -r docs/requirements.txt +$ pip install .[docs] ``` or manually by calling ```bash $ pip install sphinx sphinx-rtd-theme numpydoc nbsphinx ``` -Finally, to view the documentation, run +Finally, to view the documentation locally, run ```bash $ cd docs $ make html $ open _build/html/index.html ``` +or view them online: +[BlockInvGPFA docs](https://blockinversegpfa.readthedocs.io/en/latest/) + +A detailed walkthrough of the package — including how to fit the model to real neural data — is available in the Jupyter notebook example: (link) ----------- ### Tests ----------- -To run the unittests in the [test](test) folder, use the following command in your command line/terminal: +To run the full test suite in the [test](test) folder, use: ```bash -$ python -m unittest test.gpfa -$ python -m unittest test.preprocessing +$ pip install .[test] +$ pytest test/ ``` +Tests are automatically run via [GitHub Actions](https://github.com/CausalityInMotion/BlockInverseGPFA/actions/workflows/tests.yml) on every push and pull request. ## License Modified BSD License based on Elephant, see [LICENSE.txt](LICENSE.txt) for details. @@ -70,7 +84,7 @@ Modified BSD License based on Elephant, see [LICENSE.txt](LICENSE.txt) for detai ## Copyright -:copyright: 2021 Brooks M. Musangu and Jan Drugowitsch +:copyright: 2021-2025 Brooks M. Musangu and Jan Drugowitsch ## Acknowledgments diff --git a/docs/conf.py b/docs/conf.py index 32b3f22..0d7c7b6 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -26,7 +26,8 @@ authors = 'Brooks M. Musangu and Jan Drugowitsch' copyright = "2021-{this_year}, {authors}".format( this_year=date.today().year, authors=authors) -release = '0.0.1' +release = '0.1.0.' +version = '0.1.0' # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 11b160f..0000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -nbsphinx==0.9.6 -numpydoc==1.8.0 -Sphinx==8.1.3 -sphinx-rtd-theme==3.0.2 diff --git a/gpfa/gpfa.py b/gpfa/gpfa.py index 0aad726..2d1b544 100644 --- a/gpfa/gpfa.py +++ b/gpfa/gpfa.py @@ -1,5 +1,4 @@ # ... -# Moving this here to prevent from showing up on sphinx pages # Copyright 2021 Brooks M. Musangu and Jan Drugowitsch. # Copyright 2014-2020 by the Elephant team. # Modified BSD, see LICENSE.txt for details. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..2fb27b7 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,35 @@ +[build-system] +requires = ["setuptools>=42", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "blockinversegpfa" +version = "0.1.0" +description = "A scikit-learn-compatible GPFA implementation using block matrix inversion." +authors = [ + {name = "Brooks M. MUSANGU", email = "brooks_musangu@hms.harvard.edu"}, + {name = "Jan DRUGOWITSCH", email = "jan_drugowitsch@hms.harvard.edu"} +] +license = {file = "LICENSE.txt"} +readme = "README.md" +requires-python = ">=3.9" +dependencies = [ + "numpy==2.2.1", + "scikit-learn==1.6.0", + "scipy==1.15.0", + "tqdm==4.67.1" +] + +[project.optional-dependencies] +test = [ + "pytest==7.3.1" +] +docs = [ + "nbsphinx==0.9.6", + "numpydoc==1.8.0", + "Sphinx==8.1.3", + "sphinx-rtd-theme==3.0.2" +] + +[project.urls] +Homepage = "https://github.com/CausalityInMotion/BlockInverseGPFA" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 1b1d446..0000000 --- a/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -numpy==2.2.1 -scikit-learn==1.6.0 -scipy==1.15.0 -tqdm==4.67.1 diff --git a/test/gpfa.py b/test/test_gpfa.py similarity index 100% rename from test/gpfa.py rename to test/test_gpfa.py diff --git a/test/preprocessing.py b/test/test_preprocessing.py similarity index 100% rename from test/preprocessing.py rename to test/test_preprocessing.py