Pure-Python port of the R funkyheatmap package — generate publication-ready dataframe heatmaps with funky rectangles, pies, bars and more.
Project description
py-funkyheatmap
Pure-Python port of the R package funkyheatmap, built under the omicverse-rebuildr reference-driven porting protocol.
Generate publication-ready, dynbenchmark-style data-frame heatmaps with
funky rectangles, circles, bars, pies, and text — directly from
pandas.DataFrame inputs, rendered with matplotlib, no R / ggplot
dependency.
| Upstream | funkyheatmap 0.5.2 (R, MIT) |
| Algorithm class | Visualisation / layout — adapted Class 1 (deterministic geometry) |
| Parity gate | max|Δ| over funkyrect_data / circle_data ≤ 1e-6 on canonical fixture |
| Achieved parity | max|Δ| = 0.0 on xmin / xmax / ymin / ymax / corner_size / color_value |
| License | MIT (matches upstream) |
Install
pip install -e . # editable, from this directory
pyfunkyheatmap needs only numpy, pandas, matplotlib — no R, no
rpy2, no system-level dependencies.
Quick start
import pandas as pd
from pyfunkyheatmap import funky_heatmap
df = pd.DataFrame({
"id": ["A", "B", "C", "D"],
"x": [0.10, 0.55, 0.80, 0.95],
"y": [0.50, 0.25, 0.75, 0.60],
"tag": ["alpha", "beta", "gamma", "delta"],
})
fh = funky_heatmap(df)
fh.save("out.png", dpi=150, bbox_inches="tight")
See:
examples/tutorial.ipynb— five-example tour (default heatmap → custom column info → pies → multi-group dynbenchmark layout → R⇄Python parity diff).examples/scIB.ipynb— Python equivalent of the RscIBvignette. Same fixture, samecolumn_info, same legends.examples/dynbenchmark.ipynb— Python equivalent of the Rdynbenchmarkvignette. Reproduces the Saelens et al. (2019) figure off the bundleddynbenchmark_dataobject.
All three notebooks ship pre-executed so GitHub renders them inline.
Public API
funky_heatmap(data, column_info, row_info, column_groups, row_groups, palettes, legends, position_args, scale_column, add_abc, *, fig=None, ax=None, fig_scale=0.25, dpi=100)
Mirrors the R funky_heatmap signature. Returns a FunkyHeatmap object with:
fh.figure— the matplotlibFigurefh.geom_positions— dict of per-glyph DataFrames (row_pos,column_pos,rect_data,circle_data,funkyrect_data,pie_data,img_data,text_data,segment_data)fh.bounds,fh.width,fh.height— layout extentsfh.save(path, **kwargs)— convenience wrapper aroundFigure.savefig
Side-API: verify_data, verify_column_info, verify_row_info,
verify_column_groups, verify_row_groups, verify_palettes,
verify_legends, scale_minmax, position_arguments. Each matches its
R counterpart.
Refactoring notes
The port is not a literal R-to-Python transliteration:
- One dataclass for layout knobs.
position_arguments(...)returns a typed dataclass that supportspa.row_heightandpa["row_height"]— both styles work, so R-style mapping access and Python attribute access stay open. - Geometry tables are first-class. The R package builds them internally and emits ggplot layers; we keep them on the result so downstream code (e.g. custom annotations, alternative renderers) can subclass without forking.
- No
cowplot/patchwork/ggforce. Rounded rectangles are drawn from a hand-rolled cubic-Bézier path; pies usematplotlib.patches.Wedge; layout is bare matplotlib. - Default-palette parity. The
RColorBrewercolour stops for theBlues / Reds / YlOrBr / Greens / GreysandSet1 / Set2 / Set3 / Dark2palettes are copied verbatim and interpolated with the same linear RGB ramp thatcolorRampPaletteuses, sopalettes="Blues"produces the same hex strings as in R.
Parity gate
$ Rscript tests/r_reference_driver.R data # produces data/r_basic_*.csv + data/r_basic.png
$ pytest tests/ # 8 / 8 pass
$ python examples/build_tutorial.py # rebuilds and re-executes the notebook
The pre-registered gate is max|Δ| over the funkyrect / circle geometry
columns on the canonical fixture (tests/r_reference_driver.R).
Achieved: max|Δ| = 0.0 — every coordinate matches R bit-for-bit.
See RECONSTRUCTION_REPORT.md for the full
audit trail.
Layout
pyfunkyheatmap/
├── __init__.py public surface
├── api.py funky_heatmap entry point
├── verify.py verify_* validators (one per R counterpart)
├── position.py PositionArguments dataclass
├── positions.py calculate_geom_positions + row/column layout
├── scale.py scale_minmax
├── palettes.py DEFAULT_PALETTES + brewer_pal + smear
└── figure.py compose_figure + FunkyHeatmap + matplotlib draw
examples/
├── build_tutorial.py nbformat script that builds + executes tutorial.ipynb
└── tutorial.ipynb pre-executed tutorial (5 examples + R parity diff)
tests/
├── r_reference_driver.R Rscript that produces data/r_basic_*.csv
└── test_basic.py pytest, 8 tests
funkyheatmap-ref/ upstream R source vendored for reference
data/ canonical fixture (R + Python outputs)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyfunkyheatmap-0.1.8.tar.gz.
File metadata
- Download URL: pyfunkyheatmap-0.1.8.tar.gz
- Upload date:
- Size: 32.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73ca2fad6a173820389621844f7fc5a9b30b3e2dc4a3a8397289f71e60152a33
|
|
| MD5 |
003f7ed6999c3205a774ec3efcbded58
|
|
| BLAKE2b-256 |
b2a71d665eecf9d10dc8f316e3979d20b127a7e15557dd3b8bfb08fa06a23706
|
File details
Details for the file pyfunkyheatmap-0.1.8-py3-none-any.whl.
File metadata
- Download URL: pyfunkyheatmap-0.1.8-py3-none-any.whl
- Upload date:
- Size: 32.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02ce171c3e06972de233a20cc62747af97c0c317541b8a9f7330653ad3e9eb54
|
|
| MD5 |
d3c1ace41912e301fdb03be700b6ec46
|
|
| BLAKE2b-256 |
124644f77131c3abae08098a2d04e0191bac1a5b6bbb1a00c07cdcc50d52b288
|