Skip to content

Commit 4d42ddd

Browse files
authored
Merge pull request #1 from maflot/dev
Dev
2 parents e95ab8d + f621d4e commit 4d42ddd

50 files changed

Lines changed: 6506 additions & 1823 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Auto release on main
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
test:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
- name: Set up Python
16+
uses: actions/setup-python@v5
17+
with:
18+
python-version: "3.12"
19+
- name: Install package and test dependencies
20+
run: |
21+
python -m pip install --upgrade pip
22+
pip install -e . pytest matplotlib plotly pandas numpy scipy
23+
- name: Run tests
24+
run: pytest tests -v
25+
26+
release:
27+
runs-on: ubuntu-latest
28+
needs: test
29+
outputs:
30+
released: ${{ steps.create.outputs.released }}
31+
version: ${{ steps.version.outputs.version }}
32+
steps:
33+
- uses: actions/checkout@v4
34+
with:
35+
fetch-depth: 0
36+
37+
- name: Read version from pyproject.toml
38+
id: version
39+
run: |
40+
VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
41+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
42+
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
43+
echo "Detected version $VERSION"
44+
45+
- name: Check whether this tag already exists
46+
id: check_tag
47+
env:
48+
TAG: ${{ steps.version.outputs.tag }}
49+
run: |
50+
if git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
51+
echo "exists=true" >> "$GITHUB_OUTPUT"
52+
echo "Tag $TAG already exists — nothing to release."
53+
else
54+
echo "exists=false" >> "$GITHUB_OUTPUT"
55+
echo "Tag $TAG does not exist — will create release."
56+
fi
57+
58+
- name: Create tag and GitHub release
59+
id: create
60+
if: steps.check_tag.outputs.exists == 'false'
61+
env:
62+
GH_TOKEN: ${{ github.token }}
63+
TAG: ${{ steps.version.outputs.tag }}
64+
VERSION: ${{ steps.version.outputs.version }}
65+
run: |
66+
git config user.name "github-actions[bot]"
67+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
68+
git tag "$TAG"
69+
git push origin "$TAG"
70+
gh release create "$TAG" \
71+
--title "pydiceplot $VERSION" \
72+
--generate-notes
73+
echo "released=true" >> "$GITHUB_OUTPUT"

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ __pycache__/
99
*.mp4
1010
*.h5
1111
*.yml
12+
!.github/workflows/*.yml
1213

1314
*.pth
1415
*.pt
1516
*.html
1617

1718
*.png
19+
!images/domino_example.png
1820

1921
resources/
2022
cmake-build-debug/
@@ -43,4 +45,6 @@ cmake-build-debug/
4345
*.pag
4446
*.brf
4547
/build/
48+
/dist/
4649
/pyDicePlot.egg-info/
50+
/pydiceplot.egg-info/

CHANGELOG.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Changelog
2+
3+
## 1.0.0 — 2026-04-15
4+
5+
Complete rewrite of the dice-plot engine and public API, plus a full domino
6+
API refactor to match the new 1.0 conventions.
7+
8+
### Breaking changes
9+
10+
- **`dots` renamed to `pips`** throughout. The `dots` parameter, `dot_colors`,
11+
and related names are gone. Use `pips`, `pip_colors`, `pip_scale`,
12+
`pips_label`, `pips_order`, `max_pips` instead. ("Pip" is the correct term
13+
for the marks on a die face.)
14+
- **Seaborn-style function signature.** `dice_plot(data, x, y, pips, ...)`
15+
now takes positional `data`, `x`, `y`, `pips` followed by keyword-only
16+
options. The old dict-based / mixed-positional calling convention is removed.
17+
- **Native return types.** matplotlib: `(Figure, Axes)` when creating a new
18+
figure, just `Axes` when the caller supplies `ax=`. plotly: `go.Figure`.
19+
The old wrapper return types are gone.
20+
- **`domino_plot` rewritten around a column-first API.** The old
21+
`gene_list`/`var_id`/`logfc_col`/`pval_col`-style entry point is replaced by
22+
`domino_plot(data, feature, celltype, contrast, *, fill=..., size=..., ...)`
23+
with native backend returns, explicit contrast ordering, and backend-specific
24+
`ax=` / `fig=` composition hooks.
25+
- **`n=6` uses traditional die-face layout** (two vertical columns) instead
26+
of the transposed two-row layout from earlier versions. This is an
27+
intentional divergence from `ggdiceplot::make_offsets`.
28+
29+
### New features
30+
31+
- **Up to 9 pips.** The 3×3 sub-grid now supports `max_pips=9` with
32+
traditional die-face lookup for every value 1–9.
33+
- **Grid geometry ported from kuva.** `_layout.py` replaces the old ad-hoc
34+
positioning code with a direct port of `kuva/src/plot/diceplot.rs`, ensuring
35+
matplotlib and plotly produce identical pip positions and tile sizes.
36+
- **Per-pip continuous fill and size.** Pass `fill="col"` and/or `size="col"`
37+
for numeric columns — each pip gets its own colour (colorbar) and radius
38+
(size legend). Works with both backends.
39+
- **Per-pip discrete fill.** Pass `fill="col"` + `fill_palette={val: hex}`
40+
for discrete colour encoding per pip slot.
41+
- **Legend stack.** A right-side legend panel stacks position legend, colorbar,
42+
and size legend, matching `ggdiceplot::draw_key` semantics. Skipped when
43+
the caller provides `ax=` / `fig=`.
44+
- **`ax=` / `fig=` composability.** Draw into an existing matplotlib `Axes`
45+
or plotly `Figure` to build multi-panel layouts.
46+
- **Domino preprocessing rewrite.** Domino plots now validate their structural
47+
columns up front, enforce exactly two contrast slots, compute shared backend
48+
geometry once, and use the same color/size range semantics as `dice_plot`.
49+
- **Tile geometry controls.** `tile_size`, `pip_scale`, `grid_lines` parameters.
50+
- **Label controls.** `fill_label`, `size_label`, `pips_label` set legend
51+
titles; `xlabel`, `ylabel`, `title` set axis / figure titles.
52+
- **pixi environment.** `pixi.toml` with `test`, `example`, `build`, `check`
53+
tasks. The package is installed as an editable pypi dependency.
54+
55+
### Example scripts
56+
57+
- 1-to-1 ports of ggdiceplot demo plots: `oral_microbiome.py`,
58+
`oral_microbiome_fill_only.py`, `mirna_direction.py`, `zebra_domino.py`.
59+
- Standalone `example_domino.py`: demonstrates the refactored domino API.
60+
- Creative `pathways_nine.py`: nine signaling pathways on a 3×3 die face.
61+
- Showcase `example.py`: generates all `images/dice_*.png` gallery images.
62+
63+
### Tests
64+
65+
- `test_dice_plot.py`: smoke tests covering all three modes (categorical,
66+
continuous, discrete fill), both backends, return types, and preprocessing.
67+
- `test_domino_plot.py`: preprocessing, switch-axis, composition, validation,
68+
and backend smoke tests for the refactored domino API.
69+
- `test_layout.py`: geometry unit tests for pip positions and tile sizing.
70+
71+
## 0.0.2 — 2025
72+
73+
Initial PyPI release with basic dice and domino plot support.
-18.1 KB
Binary file not shown.

dist/pydiceplot-0.0.1.tar.gz

-16.5 KB
Binary file not shown.
-18.1 KB
Binary file not shown.

dist/pydiceplot-0.0.2.tar.gz

-16.5 KB
Binary file not shown.

example_code/_palette.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""The ggdiceplot diverging purple→white→green palette.
2+
3+
Registered globally as `ggdiceplot_pg` so the examples can just pass
4+
`color_map="ggdiceplot_pg"` and get the same look as the R `scale_fill_gradient2(
5+
low="#40004B", high="#00441B", mid="white")`.
6+
"""
7+
8+
from matplotlib import colormaps
9+
from matplotlib.colors import LinearSegmentedColormap
10+
11+
12+
NAME = "ggdiceplot_pg"
13+
14+
15+
def register() -> None:
16+
if NAME in colormaps:
17+
return
18+
cmap = LinearSegmentedColormap.from_list(
19+
NAME, ["#40004B", "#FFFFFF", "#00441B"],
20+
)
21+
colormaps.register(cmap, name=NAME)

0 commit comments

Comments
 (0)