Metadata-Version: 2.5
Name: particle-wave
Version: 1.4.0
Summary: CLI toolchain to convert images into .pwcloud particle-wave point clouds
Project-URL: Homepage, https://github.com/CoronRing/ParticleWave
Project-URL: Repository, https://github.com/CoronRing/ParticleWave
Project-URL: Issues, https://github.com/CoronRing/ParticleWave/issues
Project-URL: Changelog, https://github.com/CoronRing/ParticleWave/blob/main/CHANGELOG.md
Project-URL: Documentation, https://github.com/CoronRing/ParticleWave/blob/main/docs/particle_wave_design.md
Author: Guan Zheng Huang
License: MIT License
        
        Copyright (c) 2026 Guan Zheng Huang
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: canvas,edge-detection,image-processing,particles,point-cloud,visualization
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
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 :: Multimedia :: Graphics
Classifier: Topic :: Scientific/Engineering :: Image Processing
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: numpy>=1.24
Requires-Dist: pillow>=10.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: scipy>=1.10
Requires-Dist: typer[all]>=0.9
Provides-Extra: cv2
Requires-Dist: opencv-python-headless>=4.8; extra == 'cv2'
Provides-Extra: debug
Requires-Dist: matplotlib>=3.7; extra == 'debug'
Provides-Extra: dev
Requires-Dist: matplotlib>=3.7; extra == 'dev'
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: onnxruntime>=1.16; extra == 'dev'
Requires-Dist: opencv-python-headless>=4.8; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Provides-Extra: full
Requires-Dist: matplotlib>=3.7; extra == 'full'
Requires-Dist: onnxruntime>=1.16; extra == 'full'
Requires-Dist: opencv-python-headless>=4.8; extra == 'full'
Provides-Extra: ml
Requires-Dist: onnxruntime>=1.16; extra == 'ml'
Provides-Extra: ml-gpu
Requires-Dist: onnxruntime-gpu>=1.16; extra == 'ml-gpu'
Description-Content-Type: text/markdown

# Particle Wave

Turn a static image into an interactive, physics-driven particle cloud in the browser.

The work splits cleanly in two, and so does the distribution:

| Package | Registry | What it does |
|---------|----------|--------------|
| `particle-wave` | PyPI | Offline CLI. Image -> edge/feature map -> sampled point cloud -> `.pwcloud` |
| `@npmring/particle-wave` | npm | Browser ES module. Loads a `.pwcloud`, simulates spring physics, renders to canvas |

The halves are decoupled by the `.pwcloud` format, not by a shared runtime: the
engine never sees your image, and the tool never sees a canvas. Either one can
be swapped as long as the format contract in
[`docs/particle_wave_design.md`](docs/particle_wave_design.md) is honoured.

---

## Repository layout

```
.
├── pyproject.toml               # particle-wave  (PyPI)
├── LICENSE  CHANGELOG.md
├── docs/                        # design spec, parameter reference, module map
├── scripts/bump_version.py      # keeps both package versions in step
├── sample/                      # sample inputs
└── src/particle_wave/
    ├── __init__.py              # single source of truth for the version
    ├── tool/                    # Python: CLI, pipeline, stages, exporters
    └── FE/                      # @npmring/particle-wave (npm package root)
        ├── package.json
        ├── particle-wave.js     # public entry
        ├── particle-wave.d.ts   # hand-maintained type surface
        ├── engine_fields.json   # config schema for host UIs
        ├── core/ interaction/ utils/ style/
        └── demo/index.html      # live demo with sliders (not published)
```

`src/particle_wave/FE/` is deliberately both a subdirectory of the Python
package and the root of the npm package. That is what lets the wheel ship the
exact engine build that matches its exporter, so a `pip install` alone gives you
a working pair without vendoring JS separately and keeping the two in step by
hand.

---

## Quick start

### Convert an image

```bash
pip install "particle-wave[cv2]"
particle-wave convert logo.png -o logo.pwcloud
particle-wave inspect logo.pwcloud
```

### Render it

```bash
npm install @npmring/particle-wave
```

```html
<canvas id="pw" style="width:600px;height:400px"></canvas>
<script type="module">
  import ParticleWave from '@npmring/particle-wave';

  const pw = await ParticleWave.init(document.getElementById('pw'), {
    src: '/assets/logo.pwcloud',
    mouseMode: 'repel',
    particleColor: '#7b93ff',
    leftClickMode: 'outward_wave',
  });
</script>
```

Full API, CLI flags, and the complete config schema live in
[`src/particle_wave/README.md`](src/particle_wave/README.md) and
[`docs/`](docs/).

---

## Development

```bash
# Python
uv sync --extra dev
uv run pytest
uv run ruff check .

# Frontend (no build step; the published files are the sources)
cd src/particle_wave/FE
npm run check          # syntax-check every module
npm run demo           # serve demo/index.html
```

### Releasing

Both packages share one version number, kept in `src/particle_wave/__init__.py`.
Neither registry lets a version be reused, so the version, the changelog entry,
and the tag are all checked before anything is uploaded.

```bash
python scripts/bump_version.py 1.4.0     # rewrites __init__.py + FE/package.json
# add the CHANGELOG.md entry, commit, then:
git tag v1.4.0 && git push --tags        # CI builds and publishes both
```

The tagged workflow needs `PYPI_TOKEN` and `NPM_TOKEN` as repository secrets.

To publish from a local checkout instead — for the first release, or to recover
when one registry accepted a version and the other did not:

```bash
cp .env.example .env && $EDITOR .env     # PYPI_TOKEN, NPM_TOKEN
python scripts/publish.py                # dry run: build + validate, no upload
python scripts/publish.py --publish
python scripts/publish.py --publish --only npm
```

`.env` is gitignored and the tokens are never echoed or written into the tree.

## License

MIT — see [LICENSE](LICENSE).
