Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 50 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@ report = nstat_install()
Python no-op because import paths are managed by the environment rather than a
MATLAB-style saved user path.

## Quickstart

```bash
git clone https://github.com/cajigaslab/nSTAT-python
cd nSTAT-python
python -m pip install -e .[dev]
python -m nstat.install --download-example-data prompt
pytest -q
```

For a gallery refresh that mirrors the MATLAB repo's paper-example workflow:

```bash
python tools/paper_examples/build_gallery.py
python tools/parity/build_report.py
```

## Examples

### Paper Examples (Self-Contained)
Expand All @@ -78,17 +95,17 @@ Single command to regenerate the paper-example gallery metadata:
python tools/paper_examples/build_gallery.py
```

This writes `docs/paper_examples.md` and `docs/figures/manifest.json`, and
ensures canonical figure-gallery directories exist under
`docs/figures/example01/` through `docs/figures/example05/`.
This writes `docs/paper_examples.md`, `docs/figures/manifest.json`, and
refreshes the canonical README paper-example table from
`examples/paper/manifest.yml`.

| Example | Thumbnail | What question it answers | Run command | Links |
|---|---|---|---|---|
| Example 01 | ![Example 01](docs/figures/example01/fig01_constant_mg_summary.png) | Does Mg2+ washout produce firing-rate dynamics beyond a constant Poisson baseline? | `python examples/paper/example01_mepsc_poisson.py` | [Script](examples/paper/example01_mepsc_poisson.py) · [Figures](docs/figures/example01/) |
| Example 02 | ![Example 02](docs/figures/example02/fig01_data_overview.png) | What stimulus lag and history order best explain whisker-evoked spike trains? | `python examples/paper/example02_whisker_stimulus_thalamus.py` | [Script](examples/paper/example02_whisker_stimulus_thalamus.py) · [Figures](docs/figures/example02/) |
| Example 03 | ![Example 03](docs/figures/example03/fig01_simulated_and_real_rasters.png) | How do PSTH and SSGLM differ in capturing trial learning dynamics? | `python examples/paper/example03_psth_and_ssglm.py` | [Script](examples/paper/example03_psth_and_ssglm.py) · [Figures](docs/figures/example03/) |
| Example 04 | ![Example 04](docs/figures/example04/fig01_example_cells_path_overlay.png) | How do Gaussian and Zernike basis models compare for place-field mapping? | `python examples/paper/example04_place_cells_continuous_stimulus.py` | [Script](examples/paper/example04_place_cells_continuous_stimulus.py) · [Figures](docs/figures/example04/) |
| Example 05 | ![Example 05](docs/figures/example05/fig01_univariate_setup.png) | How accurately can neural populations decode latent stimulus and reach state? | `python examples/paper/example05_decoding_ppaf_pphf.py` | [Script](examples/paper/example05_decoding_ppaf_pphf.py) · [Figures](docs/figures/example05/) |
| Example 01 | ![Example 01](docs/figures/example01/fig01_constant_mg_summary.png) | Do mEPSCs follow constant vs piecewise Poisson firing under Mg2+ washout? | `python examples/paper/example01_mepsc_poisson.py` | [Script](examples/paper/example01_mepsc_poisson.py) · [Figures](docs/figures/example01/) |
| Example 02 | ![Example 02](docs/figures/example02/fig01_data_overview.png) | How do explicit whisker stimulus and spike history improve thalamic GLM fits? | `python examples/paper/example02_whisker_stimulus_thalamus.py` | [Script](examples/paper/example02_whisker_stimulus_thalamus.py) · [Figures](docs/figures/example02/) |
| Example 03 | ![Example 03](docs/figures/example03/fig01_simulated_and_real_rasters.png) | How do PSTH and SSGLM capture within-trial and across-trial dynamics? | `python examples/paper/example03_psth_and_ssglm.py` | [Script](examples/paper/example03_psth_and_ssglm.py) · [Figures](docs/figures/example03/) |
| Example 04 | ![Example 04](docs/figures/example04/fig01_example_cells_path_overlay.png) | Which receptive-field basis (Gaussian vs Zernike) better fits place cells? | `python examples/paper/example04_place_cells_continuous_stimulus.py` | [Script](examples/paper/example04_place_cells_continuous_stimulus.py) · [Figures](docs/figures/example04/) |
| Example 05 | ![Example 05](docs/figures/example05/fig01_univariate_setup.png) | How well do adaptive/hybrid point-process filters decode stimulus and reach state? | `python examples/paper/example05_decoding_ppaf_pphf.py` | [Script](examples/paper/example05_decoding_ppaf_pphf.py) · [Figures](docs/figures/example05/) |

Expanded paper-example index and figure gallery:
- [docs/paper_examples.md](docs/paper_examples.md)
Expand All @@ -102,11 +119,34 @@ These smaller demos remain useful as quick install and plotting checks.
| Multitaper spectrum + spectrogram | `python examples/readme_examples/example1_multitaper_and_spectrogram.py` | [PNG](examples/readme_examples/images/readme_example1_multitaper_and_spectrogram.png) |
| Simulated CIF spike train | `python examples/readme_examples/example2_simulate_cif_spiketrain_10s.py` | [PNG](examples/readme_examples/images/readme_example2_simulate_cif_spiketrain_10s.png) |
| Spike-train raster | `python examples/readme_examples/example3_nstcoll_raster_from_example2.py` | [PNG](examples/readme_examples/images/readme_example3_nstcoll_raster.png) |

## Documentation

- Docs home: [cajigaslab.github.io/nSTAT-python](https://cajigaslab.github.io/nSTAT-python/)
- Help index: [cajigaslab.github.io/nSTAT-python/help](https://cajigaslab.github.io/nSTAT-python/help/)
- Help home: [cajigaslab.github.io/nSTAT-python/NeuralSpikeAnalysis_top.html](https://cajigaslab.github.io/nSTAT-python/NeuralSpikeAnalysis_top.html)
- Paper overview: [cajigaslab.github.io/nSTAT-python/PaperOverview.html](https://cajigaslab.github.io/nSTAT-python/PaperOverview.html)
- Example index: [cajigaslab.github.io/nSTAT-python/Examples.html](https://cajigaslab.github.io/nSTAT-python/Examples.html)
- Class definitions: [cajigaslab.github.io/nSTAT-python/ClassDefinitions.html](https://cajigaslab.github.io/nSTAT-python/ClassDefinitions.html)
- Documentation setup: [cajigaslab.github.io/nSTAT-python/DocumentationSetup.html](https://cajigaslab.github.io/nSTAT-python/DocumentationSetup.html)

Source pages:
- [docs/NeuralSpikeAnalysis_top.md](docs/NeuralSpikeAnalysis_top.md)
- [docs/PaperOverview.md](docs/PaperOverview.md)
- [docs/Examples.md](docs/Examples.md)
- [docs/ClassDefinitions.md](docs/ClassDefinitions.md)
- [docs/DocumentationSetup.md](docs/DocumentationSetup.md)

## Paper-Aligned Toolbox Map

The Python port now mirrors the MATLAB repo's paper-aligned toolbox map through
[docs/PaperOverview.md](docs/PaperOverview.md). That page ties the Python
toolbox to the 2012 paper's workflow categories:

- class hierarchy and object model (`SignalObj`, `Covariate`, `Trial`,
`Analysis`, `FitResult`, `DecodingAlgorithms`)
- fitting and assessment workflow (GLM fitting, diagnostics, summaries)
- simulation workflow (conditional intensity and thinning examples)
- decoding workflow (univariate, bivariate, and history-aware decoding)
- example-to-paper section mapping via `nSTATPaperExamples`

## Developer notes

Expand Down
26 changes: 26 additions & 0 deletions docs/ClassDefinitions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Class Definitions

The Python port preserves the MATLAB-facing class names as canonical imports or
compatibility adapters.

| MATLAB-facing name | Python target | Primary example surface |
|---|---|---|
| `SignalObj` | `nstat.SignalObj` | `notebooks/SignalObjExamples.ipynb` |
| `Covariate` | `nstat.Covariate` | `notebooks/CovariateExamples.ipynb` |
| `ConfidenceInterval` | `nstat.ConfidenceInterval` | `notebooks/ConfidenceIntervalOverview.ipynb` |
| `CovColl` | `nstat.CovColl` | `notebooks/CovCollExamples.ipynb` |
| `Events` | `nstat.Events` | `notebooks/EventsExamples.ipynb` |
| `History` | `nstat.History` | `notebooks/HistoryExamples.ipynb` |
| `Trial` | `nstat.Trial` | `notebooks/TrialExamples.ipynb` |
| `TrialConfig` | `nstat.TrialConfig` | `notebooks/TrialConfigExamples.ipynb` |
| `ConfigColl` | `nstat.ConfigColl` | `notebooks/ConfigCollExamples.ipynb` |
| `nspikeTrain` | `nstat.nspikeTrain` | `notebooks/nSpikeTrainExamples.ipynb` |
| `nstColl` | `nstat.nstColl` | `notebooks/nstCollExamples.ipynb` |
| `Analysis` | `nstat.Analysis` | `notebooks/AnalysisExamples.ipynb` |
| `FitResult` | `nstat.FitResult` | `notebooks/FitResultExamples.ipynb` |
| `FitResSummary` | `nstat.FitResSummary` | `notebooks/FitResSummaryExamples.ipynb` |
| `CIF` | `nstat.CIF` | `notebooks/PPSimExample.ipynb` |
| `DecodingAlgorithms` | `nstat.DecodingAlgorithms` | `notebooks/DecodingExample.ipynb` |

See [Examples](Examples.md) for the full help-style index and
[API Reference](api.rst) for the module layout.
65 changes: 65 additions & 0 deletions docs/DocumentationSetup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Documentation Setup

This page is the Python-native equivalent of the MATLAB help-integration
guide. `nSTAT-python` does not register pages inside the MATLAB help browser;
instead it ships a static Sphinx documentation site and local rebuild hooks.

## Install and Configure

Install from PyPI:

```bash
python -m pip install nstat-toolbox
```

Install from source:

```bash
git clone https://github.com/cajigaslab/nSTAT-python
cd nSTAT-python
python -m pip install -e .[dev]
```

Run the installer helper:

```bash
nstat-install --download-example-data prompt
```

Equivalent module form:

```bash
python -m nstat.install --download-example-data prompt
```

## Build and Refresh the Search Database

The Python installer can rebuild the local Sphinx HTML search index:

```bash
nstat-install
```

or directly:

```bash
python -m sphinx -W -b html docs docs/_build/html
```

The resulting search index is written to `docs/_build/html/searchindex.js`.

## Documentation Entry Points

Use these pages as the Python documentation entry points:

- [nSTAT Home](NeuralSpikeAnalysis_top.md)
- [Class Definitions](ClassDefinitions.md)
- [Example Index](Examples.md)
- [Paper Examples](paper_examples.md)

## Troubleshooting

- If example data is missing, rerun `nstat-install --download-example-data always`.
- If local docs are stale, rebuild with `python -m sphinx -W -b html docs docs/_build/html`.
- If you need a different example-data cache, set `NSTAT_DATA_DIR` before
running the installer or examples.
55 changes: 55 additions & 0 deletions docs/Examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Example Index

This page mirrors the MATLAB `Examples` help index and points to the canonical
Python notebook or script equivalent for each workflow.

Paper cross-reference:

- [Paper-Aligned Toolbox Map](PaperOverview.md)

## Class and Object Workflows

- `SignalObjExamples`: `notebooks/SignalObjExamples.ipynb`
- `CovariateExamples`: `notebooks/CovariateExamples.ipynb`
- `CovCollExamples`: `notebooks/CovCollExamples.ipynb`
- `nSpikeTrainExamples`: `notebooks/nSpikeTrainExamples.ipynb`
- `nstCollExamples`: `notebooks/nstCollExamples.ipynb`
- `EventsExamples`: `notebooks/EventsExamples.ipynb`
- `HistoryExamples`: `notebooks/HistoryExamples.ipynb`
- `TrialExamples`: `notebooks/TrialExamples.ipynb`
- `TrialConfigExamples`: `notebooks/TrialConfigExamples.ipynb`
- `ConfigCollExamples`: `notebooks/ConfigCollExamples.ipynb`
- `ConfidenceIntervalOverview`: `notebooks/ConfidenceIntervalOverview.ipynb`

## Fitting, Assessment, and Analysis

- `AnalysisExamples`: `notebooks/AnalysisExamples.ipynb`
- `AnalysisExamples2`: `notebooks/AnalysisExamples2.ipynb`
- `FitResultExamples`: `notebooks/FitResultExamples.ipynb`
- `FitResultReference`: `notebooks/FitResultReference.ipynb`
- `FitResSummaryExamples`: `notebooks/FitResSummaryExamples.ipynb`

## Simulation and Example-Data Analyses

- `PPThinning`: `notebooks/PPThinning.ipynb`
- `PPSimExample`: `notebooks/PPSimExample.ipynb`
- `PSTHEstimation`: `notebooks/PSTHEstimation.ipynb`
- `ValidationDataSet`: `notebooks/ValidationDataSet.ipynb`
- `mEPSCAnalysis`: `notebooks/mEPSCAnalysis.ipynb`
- `ExplicitStimulusWhiskerData`: `notebooks/ExplicitStimulusWhiskerData.ipynb`
- `HippocampalPlaceCellExample`: `notebooks/HippocampalPlaceCellExample.ipynb`

## Decoding and Network Workflows

- `DecodingExample`: `notebooks/DecodingExample.ipynb`
- `DecodingExampleWithHist`: `notebooks/DecodingExampleWithHist.ipynb`
- `StimulusDecode2D`: `notebooks/StimulusDecode2D.ipynb`
- `HybridFilterExample`: `notebooks/HybridFilterExample.ipynb`
- `NetworkTutorial`: `notebooks/NetworkTutorial.ipynb`

## Consolidated Paper Workflow

- `nSTATPaperExamples`: `notebooks/nSTATPaperExamples.ipynb`
- Canonical standalone scripts: `examples/paper/example01_mepsc_poisson.py`
through `examples/paper/example05_decoding_ppaf_pphf.py`
- Generated gallery and figure index: [Paper Examples](paper_examples.md)
33 changes: 33 additions & 0 deletions docs/NeuralSpikeAnalysis_top.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Neural Spike Train Analysis Toolbox (nSTAT)

`nSTAT-python` is the standalone Python port of the neural spike-train analysis
toolbox. It preserves the MATLAB toolbox's public API naming, paper-example
structure, and help/example coverage wherever a Python equivalent is
reasonable.

## Documentation Navigation

- [Paper-Aligned Toolbox Map](PaperOverview.md)
- [Class Definitions](ClassDefinitions.md)
- [Example Index](Examples.md)
- [nSTAT Paper Examples](paper_examples.md)
- [Documentation Setup](DocumentationSetup.md)
- [API Reference](api.rst)

## Purpose

The toolbox consolidates point-process and GLM-based neural data analysis into
a coherent Python package with:

- MATLAB-compatible public entry points such as `Analysis`, `TrialConfig`,
`FitResult`, `DecodingAlgorithms`, `nSTAT_Install`, and `getPaperDataDirs`
- Canonical paper examples exported as `examples/paper/example01` through
`example05`
- Notebook-backed help workflows mirroring the MATLAB helpfiles
- A generated figure gallery under `docs/figures/`

## Citation

Cajigas I, Malik WQ, Brown EN. *nSTAT: Open-source neural spike train analysis
toolbox for Matlab*. Journal of Neuroscience Methods 211:245-264 (2012).
DOI: [10.1016/j.jneumeth.2012.08.009](https://doi.org/10.1016/j.jneumeth.2012.08.009)
72 changes: 72 additions & 0 deletions docs/PaperOverview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Paper-Aligned Toolbox Map

This page aligns the Python port with the original nSTAT toolbox paper:

- Cajigas I, Malik WQ, Brown EN. *nSTAT: Open-source neural spike train
analysis toolbox for Matlab*. Journal of Neuroscience Methods 211:245-264
(2012)
- DOI: [10.1016/j.jneumeth.2012.08.009](https://doi.org/10.1016/j.jneumeth.2012.08.009)
- PubMed: [22981419](https://pubmed.ncbi.nlm.nih.gov/22981419/)
- PMC full text: [PMC3491120](https://pmc.ncbi.nlm.nih.gov/articles/PMC3491120/)

## Class Hierarchy and Object Model

The Python port preserves the MATLAB toolbox's core object groupings:

- Signal and covariate primitives: `SignalObj`, `Covariate`,
`ConfidenceInterval`, `CovColl`
- Spiking data structures: `nspikeTrain`, `nstColl`, `History`, `Events`
- Experiment and configuration objects: `Trial`, `TrialConfig`, `ConfigColl`
- Modeling and inference objects: `CIF`, `Analysis`, `FitResult`,
`FitResSummary`, `DecodingAlgorithms`

Related navigation pages:

- [Class Definitions](ClassDefinitions.md)
- [Example Index](Examples.md)

## Fitting and Assessment Workflow

The paper's core GLM workflow maps to Python as:

1. Build trial data with `Trial`, `CovColl`, and `nstColl`.
2. Define model configurations with `TrialConfig` and `ConfigColl`.
3. Fit and evaluate analyses with `Analysis` and `FitResult`.
4. Summarize across fits with `FitResSummary`.

Representative notebooks are indexed in [Examples](Examples.md), especially
`AnalysisExamples`, `FitResultExamples`, and `FitResSummaryExamples`.

## Simulation Workflow

The simulation workflow remains centered on conditional intensity functions
and thinning-based point-process simulation:

- `CIF`
- `PPThinning`
- `PPSimExample`

These are covered by the corresponding notebooks listed in
[Examples](Examples.md).

## Decoding Workflow

The adaptive filtering and decoding portions of the paper map to:

- `DecodingAlgorithms`
- `DecodingExample`
- `DecodingExampleWithHist`
- `StimulusDecode2D`
- `HybridFilterExample`

## Example-to-Paper Section Mapping

The paper's representative workflows align to the following Python surfaces:

- `mEPSCAnalysis` and `PSTHEstimation`: event-process and PSTH analysis
- `ExplicitStimulusWhiskerData` and `HippocampalPlaceCellExample`:
stimulus-response and receptive-field modeling
- `DecodingExample`, `DecodingExampleWithHist`, and `StimulusDecode2D`:
decoding and state estimation
- `nSTATPaperExamples` and the canonical gallery in [Paper Examples](paper_examples.md):
consolidated reproduction workflow for the toolbox paper
10 changes: 5 additions & 5 deletions docs/figures/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"source_script": "examples/paper/example01_mepsc_poisson.py",
"matlab_source": "examples/paper/example01_mepsc_poisson.m",
"description": "Fits constant and piecewise Poisson GLM baselines to mEPSC spike trains.",
"question": "Does Mg2+ washout produce firing-rate dynamics beyond a constant Poisson baseline?",
"question": "Do mEPSCs follow constant vs piecewise Poisson firing under Mg2+ washout?",
"run_command": "python examples/paper/example01_mepsc_poisson.py",
"figure_dir": "docs/figures/example01",
"figure_files": [
Expand All @@ -26,7 +26,7 @@
"source_script": "examples/paper/example02_whisker_stimulus_thalamus.py",
"matlab_source": "examples/paper/example02_whisker_stimulus_thalamus.m",
"description": "Fits explicit-stimulus point-process GLMs and compares baseline, stimulus, and history models.",
"question": "What stimulus lag and history order best explain whisker-evoked spike trains?",
"question": "How do explicit whisker stimulus and spike history improve thalamic GLM fits?",
"run_command": "python examples/paper/example02_whisker_stimulus_thalamus.py",
"figure_dir": "docs/figures/example02",
"figure_files": [
Expand All @@ -44,7 +44,7 @@
"source_script": "examples/paper/example03_psth_and_ssglm.py",
"matlab_source": "examples/paper/example03_psth_and_ssglm.m",
"description": "Bundles simulated PSTH and SSGLM examples from the canonical paper workflow.",
"question": "How do PSTH and SSGLM differ in capturing trial learning dynamics?",
"question": "How do PSTH and SSGLM capture within-trial and across-trial dynamics?",
"run_command": "python examples/paper/example03_psth_and_ssglm.py",
"figure_dir": "docs/figures/example03",
"figure_files": [
Expand All @@ -67,7 +67,7 @@
"source_script": "examples/paper/example04_place_cells_continuous_stimulus.py",
"matlab_source": "examples/paper/example04_place_cells_continuous_stimulus.m",
"description": "Loads place-cell datasets and compares receptive-field model families.",
"question": "How do Gaussian and Zernike basis models compare for place-field mapping?",
"question": "Which receptive-field basis (Gaussian vs Zernike) better fits place cells?",
"run_command": "python examples/paper/example04_place_cells_continuous_stimulus.py",
"figure_dir": "docs/figures/example04",
"figure_files": [
Expand All @@ -90,7 +90,7 @@
"source_script": "examples/paper/example05_decoding_ppaf_pphf.py",
"matlab_source": "examples/paper/example05_decoding_ppaf_pphf.m",
"description": "Bundles univariate, reaching, and hybrid decoding examples from the paper workflow.",
"question": "How accurately can neural populations decode latent stimulus and reach state?",
"question": "How well do adaptive/hybrid point-process filters decode stimulus and reach state?",
"run_command": "python examples/paper/example05_decoding_ppaf_pphf.py",
"figure_dir": "docs/figures/example05",
"figure_files": [
Expand Down
Loading