Metadata-Version: 2.4
Name: plume-nav-sim
Version: 0.1.0
Summary: Proof-of-life Gymnasium-compatible reinforcement learning environment for plume navigation research
Project-URL: Homepage, https://github.com/SamuelBrudner/plume_nav_sim
Project-URL: Documentation, https://github.com/SamuelBrudner/plume_nav_sim/tree/main/src/backend/docs
Project-URL: Repository, https://github.com/SamuelBrudner/plume_nav_sim.git
Project-URL: Issues, https://github.com/SamuelBrudner/plume_nav_sim/issues
Project-URL: Changelog, https://github.com/SamuelBrudner/plume_nav_sim/blob/main/src/backend/CHANGELOG.md
Author-email: plume_nav_sim Development Team <plume-nav-sim@example.com>
Maintainer-email: plume_nav_sim Development Team <plume-nav-sim@example.com>
License: MIT
Keywords: autonomous navigation,chemical plume,gymnasium,olfactory navigation,plume navigation,reinforcement learning,robotics,scientific computing,simulation
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.10
Requires-Dist: gymnasium>=0.29.0
Requires-Dist: numpy>=2.1.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: typing-extensions>=4.7.0
Provides-Extra: all
Requires-Dist: bandit>=1.7.0; extra == 'all'
Requires-Dist: black>=24.0.0; extra == 'all'
Requires-Dist: flake8-bugbear>=24.0.0; extra == 'all'
Requires-Dist: flake8-comprehensions>=3.14.0; extra == 'all'
Requires-Dist: flake8>=7.0.0; extra == 'all'
Requires-Dist: h5py>=3.11.0; extra == 'all'
Requires-Dist: hydra-core>=1.3.0; extra == 'all'
Requires-Dist: hypothesis>=6.0.0; extra == 'all'
Requires-Dist: imageio-ffmpeg>=0.4.9; extra == 'all'
Requires-Dist: imageio>=2.31.0; extra == 'all'
Requires-Dist: ipykernel>=6.0.0; extra == 'all'
Requires-Dist: ipympl>=0.9; extra == 'all'
Requires-Dist: ipywidgets>=8.0.0; extra == 'all'
Requires-Dist: isort>=5.12.0; extra == 'all'
Requires-Dist: jupyter>=1.0.0; extra == 'all'
Requires-Dist: loguru>=0.7.0; extra == 'all'
Requires-Dist: matplotlib>=3.9.0; extra == 'all'
Requires-Dist: memory-profiler>=0.61.0; extra == 'all'
Requires-Dist: mypy>=1.8.0; extra == 'all'
Requires-Dist: nbconvert>=7.0.0; extra == 'all'
Requires-Dist: nbformat>=5.10.0; extra == 'all'
Requires-Dist: numcodecs>=0.12.0; extra == 'all'
Requires-Dist: omegaconf>=2.3.0; extra == 'all'
Requires-Dist: orjson>=3.9.0; extra == 'all'
Requires-Dist: pandas>=2.2.0; (python_version >= '3.10') and extra == 'all'
Requires-Dist: pandera>=0.18.0; extra == 'all'
Requires-Dist: pillow>=10.0.0; extra == 'all'
Requires-Dist: psutil>=5.9.0; extra == 'all'
Requires-Dist: pyarrow>=14.0.0; (python_version >= '3.10') and extra == 'all'
Requires-Dist: pyside6>=6.7.0; extra == 'all'
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'all'
Requires-Dist: pytest-cov>=4.0.0; extra == 'all'
Requires-Dist: pytest-mock>=3.12.0; extra == 'all'
Requires-Dist: pytest-xdist>=3.0.0; extra == 'all'
Requires-Dist: pytest>=8.0.0; extra == 'all'
Requires-Dist: safety>=2.0.0; extra == 'all'
Requires-Dist: seaborn>=0.13.0; extra == 'all'
Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == 'all'
Requires-Dist: sphinx>=7.0.0; extra == 'all'
Requires-Dist: sphinxcontrib-napoleon>=0.7; extra == 'all'
Requires-Dist: tomli>=2.0.1; extra == 'all'
Requires-Dist: types-requests; extra == 'all'
Requires-Dist: types-setuptools; extra == 'all'
Requires-Dist: xarray>=2024.1.0; extra == 'all'
Requires-Dist: zarr>=2.16.0; extra == 'all'
Provides-Extra: benchmark
Requires-Dist: memory-profiler>=0.61.0; extra == 'benchmark'
Requires-Dist: psutil>=5.9.0; extra == 'benchmark'
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'benchmark'
Provides-Extra: data
Requires-Dist: orjson>=3.9.0; extra == 'data'
Requires-Dist: pandas>=2.2.0; (python_version >= '3.10') and extra == 'data'
Requires-Dist: pandera>=0.18.0; extra == 'data'
Requires-Dist: pyarrow>=14.0.0; (python_version >= '3.10') and extra == 'data'
Provides-Extra: dev
Requires-Dist: bandit>=1.7.0; extra == 'dev'
Requires-Dist: black>=24.0.0; extra == 'dev'
Requires-Dist: flake8-bugbear>=24.0.0; extra == 'dev'
Requires-Dist: flake8-comprehensions>=3.14.0; extra == 'dev'
Requires-Dist: flake8>=7.0.0; extra == 'dev'
Requires-Dist: hypothesis>=6.0.0; extra == 'dev'
Requires-Dist: isort>=5.12.0; extra == 'dev'
Requires-Dist: memory-profiler>=0.61.0; extra == 'dev'
Requires-Dist: mypy>=1.8.0; extra == 'dev'
Requires-Dist: nbconvert>=7.0.0; extra == 'dev'
Requires-Dist: nbformat>=5.10.0; extra == 'dev'
Requires-Dist: psutil>=5.9.0; extra == 'dev'
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest-mock>=3.12.0; extra == 'dev'
Requires-Dist: pytest-xdist>=3.0.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: safety>=2.0.0; extra == 'dev'
Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == 'dev'
Requires-Dist: sphinx>=7.0.0; extra == 'dev'
Requires-Dist: sphinxcontrib-napoleon>=0.7; extra == 'dev'
Requires-Dist: tomli>=2.0.1; extra == 'dev'
Requires-Dist: types-requests; extra == 'dev'
Requires-Dist: types-setuptools; extra == 'dev'
Provides-Extra: docs
Requires-Dist: nbconvert>=7.0.0; extra == 'docs'
Requires-Dist: nbformat>=5.10.0; extra == 'docs'
Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == 'docs'
Requires-Dist: sphinx>=7.0.0; extra == 'docs'
Requires-Dist: sphinxcontrib-napoleon>=0.7; extra == 'docs'
Provides-Extra: gui
Requires-Dist: pyside6>=6.7.0; extra == 'gui'
Provides-Extra: hydra
Requires-Dist: hydra-core>=1.3.0; extra == 'hydra'
Requires-Dist: omegaconf>=2.3.0; extra == 'hydra'
Provides-Extra: lint
Requires-Dist: black>=24.0.0; extra == 'lint'
Requires-Dist: flake8-bugbear>=24.0.0; extra == 'lint'
Requires-Dist: flake8-comprehensions>=3.14.0; extra == 'lint'
Requires-Dist: flake8>=7.0.0; extra == 'lint'
Requires-Dist: isort>=5.12.0; extra == 'lint'
Requires-Dist: mypy>=1.8.0; extra == 'lint'
Requires-Dist: tomli>=2.0.1; extra == 'lint'
Requires-Dist: types-requests; extra == 'lint'
Requires-Dist: types-setuptools; extra == 'lint'
Provides-Extra: media
Requires-Dist: h5py>=3.11.0; extra == 'media'
Requires-Dist: imageio-ffmpeg>=0.4.9; extra == 'media'
Requires-Dist: imageio>=2.31.0; extra == 'media'
Requires-Dist: matplotlib>=3.9.0; extra == 'media'
Requires-Dist: numcodecs>=0.12.0; extra == 'media'
Requires-Dist: pillow>=10.0.0; extra == 'media'
Requires-Dist: xarray>=2024.1.0; extra == 'media'
Requires-Dist: zarr>=2.16.0; extra == 'media'
Provides-Extra: notebooks
Requires-Dist: ipykernel>=6.0.0; extra == 'notebooks'
Requires-Dist: ipympl>=0.9; extra == 'notebooks'
Requires-Dist: ipywidgets>=8.0.0; extra == 'notebooks'
Requires-Dist: jupyter>=1.0.0; extra == 'notebooks'
Requires-Dist: seaborn>=0.13.0; extra == 'notebooks'
Provides-Extra: ops
Requires-Dist: loguru>=0.7.0; extra == 'ops'
Provides-Extra: security
Requires-Dist: bandit>=1.7.0; extra == 'security'
Requires-Dist: safety>=2.0.0; extra == 'security'
Provides-Extra: test
Requires-Dist: hypothesis>=6.0.0; extra == 'test'
Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
Requires-Dist: pytest-mock>=3.12.0; extra == 'test'
Requires-Dist: pytest-xdist>=3.0.0; extra == 'test'
Requires-Dist: pytest>=8.0.0; extra == 'test'
Description-Content-Type: text/markdown

# plume-nav-sim

🧪 Proof-of-Life Gymnasium Environment for Plume Navigation Research

[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/) [![Gymnasium](https://img.shields.io/badge/gymnasium-0.29%2B-green.svg)](https://gymnasium.farama.org/) [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](../../LICENSE)

`plume-nav-sim` is a Gymnasium-compatible plume navigation environment built for researcher workflows: start quickly with a default setup, then plug in your own action, observation, and reward logic through a component architecture designed for controlled experimentation and reproducible comparisons. For direct component extension patterns, start with [`EXTENDING.md`](./EXTENDING.md).

## Quick Start

Install:

```bash
# Preferred for released versions:
pip install plume-nav-sim

# Local development:
pip install -e .
```

For another project, pin the Git tag in `pyproject.toml`:

```toml
[project]
dependencies = [
  "plume-nav-sim @ git+https://github.com/SamuelBrudner/plume_nav_sim.git@v0.1.0#subdirectory=src/backend",
]
```

Run a minimal episode (5 lines):

```python
import plume_nav_sim as pns
env = pns.make_env()
obs, info = env.reset(seed=0)
obs, reward, terminated, truncated, info = env.step(env.action_space.sample())
env.close()
```

## Extend It

The fastest way to add your own navigation behavior is to build custom components and inject them into `ComponentBasedEnvironment`. Use `EXTENDING.md` as the researcher entry point: it shows minimal interfaces, implementation templates, and a full custom-components example.

Read: [`EXTENDING.md`](./EXTENDING.md)

## Architecture Overview

`plume-nav-sim` supports two main usage modes:

- `PlumeEnv`: standard, ready-to-run Gymnasium environment
- `ComponentBasedEnvironment`: dependency-injected environment for custom research logic

`ComponentBasedEnvironment` centers on three swappable components:

- `ActionProcessor`: maps policy actions to next agent state
- `ObservationModel`: maps environment state to observations
- `RewardFunction`: maps transitions to scalar reward

These interfaces make it straightforward to test alternate assumptions without rewriting the full environment stack.

## Installation Details

Requirements:

- Python 3.10+
- Gymnasium 0.29+

Extras:

```bash
pip install -e ".[notebooks]"  # Jupyter widgets
pip install -e ".[media]"      # video/movie plume support
pip install -e ".[data]"       # data capture and analysis

# Once published:
# pip install plume-nav-sim[media]
```

Editable install for local development:

```bash
git clone https://github.com/SamuelBrudner/plume_nav_sim.git
cd plume_nav_sim/src/backend
python -m venv .venv && source .venv/bin/activate
pip install -e .[dev]
```

Verify install:

```bash
python -c "import plume_nav_sim; print(plume_nav_sim.PACKAGE_VERSION)"
```

## Contributing / License

- Contributing guide: [`CONTRIBUTING.md`](./CONTRIBUTING.md)
- License: [MIT (`../../LICENSE`)](../../LICENSE)
