Skip to content
Closed
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
49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: CI

on:
push:
branches: [master, main]
pull_request:

# These jobs mirror `pyclawd check` (format-check -> lint -> typecheck -> test):
# the same tools (ruff check, ruff format --check, mypy, pytest) run here and
# locally, so a green `pyclawd check` predicts a green CI. CI deliberately does
# NOT depend on pyclawd being installed/published — it calls the tools directly.
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
- name: Ruff lint
run: uvx ruff check .
- name: Ruff format check
run: uvx ruff format --check .

typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: python -m pip install --upgrade pip mypy
- run: python -m pip install -e .
- name: Mypy
run: mypy src

test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- run: python -m pip install --upgrade pip pytest
- run: python -m pip install -e .
- name: Pytest
run: pytest
6 changes: 2 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,6 @@ target/
# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

Expand All @@ -105,5 +102,6 @@ venv.bak/
# mkdocs documentation
/site

# mypy
# mypy / ruff
.mypy_cache/
.ruff_cache/
48 changes: 48 additions & 0 deletions .pyclawd/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""pysampling's pyclawd config — drives `pyclawd test/lint/typecheck/docs/...` for this repo."""

from pyclawd import DocsConfig, DoctorConfig, Project, QualityConfig, TestConfig

project = Project(
name="pysampling",
conda_env="default",
root_markers=["pyproject.toml"],
# Where pyclawd writes this project's transient files (run logs, junit, scratch).
work_dir="/tmp/pysampling",
# Default directory `pyclawd ls` lists (the code/source root).
src_dir="src",
quality=QualityConfig(
lint_cmd=["ruff", "check"],
lint_fix_cmd=["ruff", "check", "--fix"],
format_cmd=["ruff", "format"],
format_check_cmd=["ruff", "format", "--check"],
typecheck_cmd=["mypy", "src"],
check_sequence=["format-check", "lint", "typecheck", "test"],
),
# Docs build runs in the project env: `pip install -e . --group docs`, then
# `pyclawd docs build` → `python docs/cli.py all`. (Swap `runner` for an
# isolated env, e.g. uvx, if you'd rather not install the docs deps here.)
docs=DocsConfig(
runner=["python", "docs/cli.py"],
source_dir="docs/source",
cache_dir="docs/.jupyter_cache",
cache_db="docs/.jupyter_cache/global.db",
build_html="docs/build/html",
branch="master",
),
test=TestConfig(
tests_dir="tests/",
classname_prefix="tests.",
integration_files=[],
markers={"default": "not slow", "fast": "not slow", "all": ""},
),
doctor=DoctorConfig(
core_deps=["numpy"],
dev_deps=["pytest"],
tool_files=[],
binaries=[
("ruff", "pip install ruff"),
("mypy", "pip install mypy"),
("pandoc", "conda install -c conda-forge pandoc"), # nbsphinx HTML render
],
),
)
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12
11 changes: 0 additions & 11 deletions .travis.yml

This file was deleted.

37 changes: 37 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Changelog

All notable changes to this project are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

### Added
- Modern Sphinx documentation under `docs/` with a cached build pipeline
(`pyclawd docs build`): MyST Markdown sources → executed notebooks
(jupyter-cache) → Sphinx + nbsphinx HTML. The builder is the standalone
`docs/cli.py`, run with the project Python; its toolchain is the `docs`
dependency group (`pip install -e . --group docs`).

### Changed
- Adopted the [pyclawd](https://github.com/anyoptimization) dev toolkit and moved
to a modern `src/` layout with a `pyproject.toml` (hatchling) build.
- Replaced Travis CI with GitHub Actions (`lint`, `typecheck`, `test` matrix).
- Converted the test suite from bespoke `unittest` runners to pytest.
- Replaced the ancient single-`index.ipynb` Sphinx setup with the new docs
pipeline above.
- Rewrote the README in Markdown.

### Fixed
- `SobolSampling` crashed on NumPy 2.x (`np.int` was removed); now uses
`np.int64`.
- Fixed an invalid regex escape in the Sobol resource parser (`"\s"` -> `r"\s"`).
- Removed unreachable/dead branches and an undefined return in `util.cdist`; the
alternative implementations are now selectable via `"matmul"` / `"broadcast"`.

## [0.1.2]

### Added
- Initial public release: random, Latin Hypercube, Halton and Sobol sampling
plus discrepancy/uniformity measures.
96 changes: 96 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# CLAUDE.md — pysampling

`pysampling` generates well-spread point sets in the unit hypercube `[0, 1]^d`
(random, Latin Hypercube, Halton, Sobol) and provides discrepancy/uniformity
measures to assess them. `README.md` is the human-facing overview; this file is
the working contract for AI agents.

## This project follows pyclawd

Development is driven by [pyclawd](https://github.com/anyoptimization) — a
project-generic Python dev-task CLI. The whole project is described by one file,
[`.pyclawd/config.py`](.pyclawd/config.py), and humans and agents drive it the
same way. **pyclawd is expected to already be installed in your environment**
(it is not vendored into this repo, and neither are its agent skills — install
those once per machine with `pyclawd skills install` if you want them).

Read `.pyclawd/config.py` before assuming how anything is wired — it is the
single source of truth for the env, paths, and checks.

## Critical rule — how to run Python

**ALWAYS run Python through `pyclawd python`. NEVER call bare `python` / `python -c`.**

```bash
pyclawd python script.py # run a script
pyclawd python -m pytest ... # run a module
pyclawd python -c "import pysampling" # quick check
```

`pyclawd python` runs in the project's configured env (`conda_env` in
`.pyclawd/config.py`) with the repo on `PYTHONPATH`. Bare `python` misses the
env and the in-tree source.

## Commands

| Task | Command |
|---|---|
| Health-check the dev env | `pyclawd doctor` |
| Run Python in the env | `pyclawd python <file>` · `-m <mod>` · `-c <code>` |
| Fast smoke tests | `pyclawd test fast` |
| Default test gate | `pyclawd test run` |
| Select tests | `pyclawd test -k <kw>` · `pyclawd test tests/path::node` |
| Lint / autofix | `pyclawd lint` · `pyclawd lint --fix` |
| Format / check | `pyclawd format` · `pyclawd format --check` |
| Type-check | `pyclawd typecheck` |
| **Aggregate quality gate** | `pyclawd check` |
| Build a source/wheel dist | `pyclawd dist` |
| Build / serve the docs | `pyclawd docs build` · `pyclawd docs serve` |

`pyclawd check` runs **format-check → lint → typecheck → test**, fail-fast — the
canonical "am I done?" gate. CI (`.github/workflows/ci.yml`) mirrors it with the
same tools, so a green `pyclawd check` predicts green CI.

## Project layout

```
src/pysampling/ # the package (src layout)
sample.py # sample(algorithm, n_points, n_dim, ...) entry point
sampling.py # abstract Sampling base class
algorithms/ # random, lhs, halton, sobol implementations
measures.py # discrepancy / uniformity measures
util.py # cdist, prime sieve, resource paths
resources/*.dat # Sobol direction-number tables (bundled package data)
tests/ # pytest suite (+ resources/ for fixtures)
examples/ # runnable demos (plot_sampling.py)
```

The single source of truth for the version is
`src/pysampling/__init__.py::__version__` (hatchling reads it). Bump it there; do
not reintroduce a separate `version.py`.

## Conventions & boundaries

### Always
- Run code via `pyclawd python` — never bare `python`.
- Run `pyclawd doctor` first when the env looks off or tests fail to import.
- **Run `pyclawd check` before declaring work done.**
- Fix the *cause* of a failing test, not the assertion — use tolerances for
floats and pinned seeds for stochastic tests (`sample(..., seed=...)`).
- Each discrepancy measure in `measures.py` has a slow loop reference in
`tests/test_discrepancy.py`; keep them in agreement when you touch either.

### Ask first
- Committing, pushing, opening PRs.
- Changing `.pyclawd/config.py`, dependencies, or the public API (`sample`).

### Never
- Never call bare `python`/`pip` outside the project env.
- Never weaken or delete a test to make a suite pass.
- Never leave the tree with a failing `pyclawd check`.

## How you know you're done

- `pyclawd check` is green (format-check, lint, typecheck, tests all ✓).
- `pyclawd doctor` exits 0.
- Behavior is verified by tests, not just by inspection.
1 change: 0 additions & 1 deletion MANIFEST.in

This file was deleted.

9 changes: 0 additions & 9 deletions Makefile

This file was deleted.

77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# pysampling

[![python](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/)
[![license](https://img.shields.io/badge/license-apache-orange.svg)](https://www.apache.org/licenses/LICENSE-2.0)

Sampling methods for design of experiments in Python. `pysampling` generates
well-spread point sets in the unit hypercube `[0, 1]^d` and provides a suite of
measures to assess their uniformity.

Detailed documentation: https://anyoptimization.com/projects/pysampling

## Algorithms

| Key | Method |
|------------|-------------------------|
| `random` | Uniform random sampling |
| `lhs` | Latin Hypercube Sampling |
| `halton` | Halton sequence |
| `sobol` | Sobol sequence |

## Installation

```bash
pip install -U pysampling
```

## Usage

Import the `sample` function and pick an algorithm. Here we draw 50 points in 2
dimensions with Latin Hypercube Sampling:

```python
from pysampling.sample import sample

X = sample("lhs", 50, 2)
```

To visualize the result (requires the optional `plot` extra, `pip install
pysampling[plot]`):

```python
import matplotlib.pyplot as plt

plt.scatter(X[:, 0], X[:, 1], s=30, facecolors="none", edgecolors="r")
plt.show()
```

See [`examples/plot_sampling.py`](examples/plot_sampling.py) for a runnable demo.

## Development

This project uses [pyclawd](https://github.com/anyoptimization) as its dev
toolkit.

```bash
pip install -e . --group dev
pyclawd check # format-check -> lint -> typecheck -> test
pyclawd test fast # quick test run
```

### Documentation

The docs are built by a cached pipeline (see [`docs/`](docs/)):

```bash
pip install -e . --group docs # one-time: install the docs toolchain
pyclawd docs build # compile -> execute (cached) -> render HTML
pyclawd docs serve # serve docs/build/html locally
```

## Contact

Julian Blank — blankjul@outlook.com

## License

Apache License 2.0 — see [LICENSE](LICENSE).
Loading
Loading