petaurus 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- petaurus-0.2.0/.gitignore +57 -0
- petaurus-0.2.0/.python-version +1 -0
- petaurus-0.2.0/LICENSE +21 -0
- petaurus-0.2.0/PKG-INFO +436 -0
- petaurus-0.2.0/README.md +394 -0
- petaurus-0.2.0/docs/.nojekyll +0 -0
- petaurus-0.2.0/docs/index.html +42 -0
- petaurus-0.2.0/docs/thumbnail_light.png +0 -0
- petaurus-0.2.0/petaurus/__init__.py +6 -0
- petaurus-0.2.0/petaurus/layers.py +651 -0
- petaurus-0.2.0/petaurus/palettes.py +3030 -0
- petaurus-0.2.0/petaurus/theme.py +388 -0
- petaurus-0.2.0/petaurus/transforms.py +226 -0
- petaurus-0.2.0/pyproject.toml +48 -0
- petaurus-0.2.0/scripts/build/build_gallery.py +677 -0
- petaurus-0.2.0/scripts/build/build_palettes.py +561 -0
- petaurus-0.2.0/scripts/build/build_swatches_for_illustrator.py +60 -0
- petaurus-0.2.0/scripts/build/build_thumbnail.py +209 -0
- petaurus-0.2.0/scripts/import_palettes_to_illustrator.jsx +2943 -0
- petaurus-0.2.0/scripts/plot/area_chart.py +46 -0
- petaurus-0.2.0/scripts/plot/area_chart_gradient.py +54 -0
- petaurus-0.2.0/scripts/plot/boxplot.py +88 -0
- petaurus-0.2.0/scripts/plot/bubble.py +47 -0
- petaurus-0.2.0/scripts/plot/heatmap.py +34 -0
- petaurus-0.2.0/scripts/plot/histogram.py +39 -0
- petaurus-0.2.0/scripts/plot/line.py +34 -0
- petaurus-0.2.0/scripts/plot/p-value.py +62 -0
- petaurus-0.2.0/scripts/plot/paired.py +58 -0
- petaurus-0.2.0/scripts/plot/palette_test.py +152 -0
- petaurus-0.2.0/scripts/plot/ridgeplot.py +88 -0
- petaurus-0.2.0/scripts/plot/scatter.py +30 -0
- petaurus-0.2.0/scripts/plot/sequences.py +156 -0
- petaurus-0.2.0/scripts/plot/stacked_bar_chart.py +45 -0
- petaurus-0.2.0/scripts/plot/strip.py +32 -0
- petaurus-0.2.0/scripts/plot/violin.py +39 -0
- petaurus-0.2.0/scripts/plot/volcano.py +63 -0
- petaurus-0.2.0/uv.lock +570 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Compiled source #
|
|
2
|
+
###################
|
|
3
|
+
*.com
|
|
4
|
+
*.class
|
|
5
|
+
*.dll
|
|
6
|
+
*.exe
|
|
7
|
+
*.o
|
|
8
|
+
*.so
|
|
9
|
+
|
|
10
|
+
# Logs and databases #
|
|
11
|
+
######################
|
|
12
|
+
*.log
|
|
13
|
+
*.sql
|
|
14
|
+
*.sqlite
|
|
15
|
+
|
|
16
|
+
# Cache files #
|
|
17
|
+
###############
|
|
18
|
+
__pycache__
|
|
19
|
+
*.pyc
|
|
20
|
+
|
|
21
|
+
# OS generated files #
|
|
22
|
+
######################
|
|
23
|
+
.DS_Store
|
|
24
|
+
.DS_Store?
|
|
25
|
+
._*
|
|
26
|
+
.Spotlight-V100
|
|
27
|
+
.Trashes
|
|
28
|
+
ehthumbs.db
|
|
29
|
+
Thumbs.db
|
|
30
|
+
|
|
31
|
+
# Notes / scratchpads #
|
|
32
|
+
#########
|
|
33
|
+
*rule*.md
|
|
34
|
+
*thoughts.md
|
|
35
|
+
*notes.md
|
|
36
|
+
*planning.md
|
|
37
|
+
*plans.md
|
|
38
|
+
*scratch*
|
|
39
|
+
|
|
40
|
+
# Virtual environments #
|
|
41
|
+
########################
|
|
42
|
+
.venv
|
|
43
|
+
*venv
|
|
44
|
+
pipenv
|
|
45
|
+
*conda*
|
|
46
|
+
|
|
47
|
+
# Raw data files #
|
|
48
|
+
##################
|
|
49
|
+
*.tif
|
|
50
|
+
*.tiff
|
|
51
|
+
*.nd2
|
|
52
|
+
|
|
53
|
+
# Project-specific #
|
|
54
|
+
*.png
|
|
55
|
+
*.svg
|
|
56
|
+
*.json
|
|
57
|
+
!docs/thumbnail_light.png
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.11
|
petaurus-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dkkung
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
petaurus-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: petaurus
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Custom Altair/Vega-Lite themes, perceptually uniform palettes, and chart utilities for publication-ready scientific figures.
|
|
5
|
+
Project-URL: Repository, https://github.com/dkkung/altair_custom_themes
|
|
6
|
+
Author-email: dkkung <128324842+dkkung@users.noreply.github.com>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2026 dkkung
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Keywords: altair,color,oklab,palette,theme,vega-lite,visualization
|
|
30
|
+
Classifier: Development Status :: 4 - Beta
|
|
31
|
+
Classifier: Intended Audience :: Science/Research
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Operating System :: OS Independent
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
36
|
+
Requires-Python: >=3.11
|
|
37
|
+
Requires-Dist: altair>=5.5.0
|
|
38
|
+
Requires-Dist: numpy>=1.26.0
|
|
39
|
+
Requires-Dist: polars>=1.19.0
|
|
40
|
+
Requires-Dist: scipy>=1.11.0
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
|
|
43
|
+
# petaurus
|
|
44
|
+
|
|
45
|
+
Custom Altair/Vega-Lite themes, perceptually uniform palettes, and chart utilities for publication-ready scientific figures.
|
|
46
|
+
|
|
47
|
+
*This is a personal project under active development, so there may be breaking changes between minor versions.*
|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
# uv
|
|
55
|
+
uv pip install petaurus
|
|
56
|
+
|
|
57
|
+
# pip
|
|
58
|
+
pip install petaurus
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Requires Python 3.11+. Dependencies: `altair`, `numpy`, `polars`, `scipy`.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Quick start
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import altair as alt
|
|
69
|
+
import polars as pl
|
|
70
|
+
import petaurus
|
|
71
|
+
|
|
72
|
+
petaurus.options(chartWidth=300, chartHeight=200)
|
|
73
|
+
|
|
74
|
+
chart = (
|
|
75
|
+
alt.Chart(df)
|
|
76
|
+
.mark_point()
|
|
77
|
+
.encode(
|
|
78
|
+
x=alt.X("x:Q"),
|
|
79
|
+
y=alt.Y("y:Q"),
|
|
80
|
+
color=alt.Color("y:Q", scale=alt.Scale(range=petaurus.palette("blues"))),
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
petaurus.save(chart, "plots/myplot")
|
|
85
|
+
# writes: plots/myplot_light.png, plots/myplot_light.svg
|
|
86
|
+
# plots/myplot_dark.png, plots/myplot_dark.svg
|
|
87
|
+
# plots/myplot_vegalite.json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## petaurus.options()
|
|
93
|
+
|
|
94
|
+
**Call before building any Altair charts to configure global theme defaults.**
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
petaurus.options() # apply defaults
|
|
98
|
+
|
|
99
|
+
petaurus.options( # custom configuration
|
|
100
|
+
chartWidth=400,
|
|
101
|
+
chartHeight=250,
|
|
102
|
+
fontSize=8,
|
|
103
|
+
grid=True,
|
|
104
|
+
palette="blues",
|
|
105
|
+
)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
| Parameter | Default | Description |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| `angledX` | `False` | Angle x-axis labels 45° |
|
|
111
|
+
| `axisOffset` | `tickSize` | Distance between axis line and data area |
|
|
112
|
+
| `axisWidth` | `0.25` | Stroke width of axes, ticks, and rules |
|
|
113
|
+
| `bandPadding` | `0.1` | Inner and outer padding for ordinal bands |
|
|
114
|
+
| `chartFill` | `"white"` | Background fill of the entire chart |
|
|
115
|
+
| `chartHeight` | `100` | Default chart height in pixels |
|
|
116
|
+
| `chartWidth` | `100` | Default chart width in pixels |
|
|
117
|
+
| `closed` | auto | Draw a border around the plot area. Auto-enabled when `viewFill` is set |
|
|
118
|
+
| `darkmode` | `False` | Invert text and axis colors for dark backgrounds |
|
|
119
|
+
| `dashedLine` | `False` | Render line marks dashed |
|
|
120
|
+
| `dashedRule` | `True` | Render rule marks dashed |
|
|
121
|
+
| `dashedWidth` | `[2, 2]` | Dash/gap pattern `[dash, gap]` in pixels |
|
|
122
|
+
| `font` | `"HelveticaNeue"` | Font family for all labels and titles |
|
|
123
|
+
| `fontSize` | `7` | Font size in points |
|
|
124
|
+
| `fontWeight` | `400` | Font weight: 300 = light, 400 = normal, 700 = bold |
|
|
125
|
+
| `grid` | `False` | Show axis grid lines |
|
|
126
|
+
| `gridColor` | `"darkGray"` | Grid line color |
|
|
127
|
+
| `legend` | `True` | Show legends |
|
|
128
|
+
| `legendOffset` | `tickSize` | Distance between legend and chart edge |
|
|
129
|
+
| `legendStroke` | `False` | Draw a border around the legend box |
|
|
130
|
+
| `markFill` | `"black"` | Default fill color for marks |
|
|
131
|
+
| `markFillOpacity` | `1.0` | Default mark fill opacity |
|
|
132
|
+
| `markSize` | `min(W, H) × 0.1` | Mark size; for points, this is area in sq px |
|
|
133
|
+
| `markStroke` | `"black"` | Default stroke color for marks |
|
|
134
|
+
| `markStrokeOpacity` | `1` | Default mark stroke opacity |
|
|
135
|
+
| `palette` | `None` | Default color scheme applied to category, diverging, heatmap, and ramp scales. Accepts a key from `colors` or a raw list |
|
|
136
|
+
| `strokeCap` | `"round"` | Stroke end cap: `"butt"`, `"round"`, or `"square"` |
|
|
137
|
+
| `ticks` | `True` | Show axis ticks |
|
|
138
|
+
| `tickSize` | `5` | Tick length in pixels |
|
|
139
|
+
| `transparentBackground` | `False` | Transparent chart background (overrides `chartFill`) |
|
|
140
|
+
| `verticalY` | `False` | Rotate y-axis labels 90° |
|
|
141
|
+
| `viewFill` | `None` | Fill color of the plot area only. Setting this auto-enables `closed` |
|
|
142
|
+
| `xTicks` | `True` | Show ticks on the x-axis |
|
|
143
|
+
| `yTicks` | `True` | Show ticks on the y-axis |
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Palettes
|
|
148
|
+
|
|
149
|
+
All custom palettes are built in [Oklab](https://bottosson.github.io/posts/oklab/) (Ottosson, *A perceptual color space for image processing*, 2020) for perceptual uniformity. They are stored in `petaurus.colors`, a plain `dict[str, list[str]]` mapping palette names to 12-stop hex lists (13 stops for diverging palettes).
|
|
150
|
+
|
|
151
|
+
### Accessing palettes
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from petaurus.palettes import colors
|
|
155
|
+
|
|
156
|
+
blues = colors["blues"] # list of 12 hex strings, light → dark
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### petaurus.palette()
|
|
160
|
+
|
|
161
|
+
Samples a slice or subset from any named palette.
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
petaurus.palette("blues") # all 12 stops
|
|
165
|
+
petaurus.palette("blues", n=5) # 5 evenly-spaced stops
|
|
166
|
+
petaurus.palette("blues", start=3) # stops 3–11
|
|
167
|
+
petaurus.palette("blues", end=6, step=2) # indices 0, 2, 4, 6
|
|
168
|
+
petaurus.palette("blues", n=4, reverse=True) # reversed
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
| Parameter | Default | Description |
|
|
172
|
+
|---|---|---|
|
|
173
|
+
| `name` | required | Key in `colors` |
|
|
174
|
+
| `n` | `None` | Return `n` evenly-spaced stops (overrides `step`) |
|
|
175
|
+
| `start` | `0` | Index of the first stop to include |
|
|
176
|
+
| `end` | last | Index of the last stop to include (inclusive) |
|
|
177
|
+
| `step` | `1` | Step between indices (used when `n` is not set) |
|
|
178
|
+
| `reverse` | `False` | Reverse the returned list |
|
|
179
|
+
|
|
180
|
+
### Theme defaults
|
|
181
|
+
|
|
182
|
+
When no explicit `scale=` is set on a color encoding, Vega-Lite falls back to the theme's range defaults:
|
|
183
|
+
|
|
184
|
+
| Range type | Default palette | Used for |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| `category` | `blues` (even indices: 0, 2, 4, 6, 8, 10) | Nominal/unordered groups |
|
|
187
|
+
| `ordinal` | `blues` | Ordered discrete values |
|
|
188
|
+
| `ramp` | `blues` | Sequential continuous (legend ramps) |
|
|
189
|
+
| `heatmap` | `blues` | Rect/heatmap marks |
|
|
190
|
+
| `diverging` | `redsblues` | Diverging scales |
|
|
191
|
+
|
|
192
|
+
Setting `petaurus.options(palette="mypalette")` overrides all five types simultaneously.
|
|
193
|
+
|
|
194
|
+
### Available palettes
|
|
195
|
+
|
|
196
|
+
See the [palette gallery](https://dkkung.github.io/theme/) for a visual overview of all palettes, or open `docs/index.html` locally.
|
|
197
|
+
|
|
198
|
+
**Sequential — Single-hue** (12 stops, light → dark):
|
|
199
|
+
`blues`, `greens`, `purples`, `lavenders`, `violets`, `greys`, `reds`, `rose`, `oranges`, `browns`, `yellows`, `cyans`, `magentas`, `neongreens`
|
|
200
|
+
|
|
201
|
+
**Sequential — Single-hue 2** (12 stops, deeper saturation built with Oklab arc-length resampling):
|
|
202
|
+
`blues2`, `greens2`, `purples2`, `lavenders2`, `violets2`, `greys2`, `reds2`, `roses2`, `oranges2`, `browns2`, `yellows2`, `cyans2`, `magentas2`, `neongreens2`
|
|
203
|
+
|
|
204
|
+
**Sequential — Multi-hue** (12 stops, two or more hues blended in Oklab):
|
|
205
|
+
`yellowgreen`, `ember`, `dusk`, `shoal`, `moss`, `GnBu`, `YlGnBu`, `candy`, `lagoon`, `bluestlagoon`, `bluerlagoon`, `bluelagoon`
|
|
206
|
+
|
|
207
|
+
**Diverging** (13 stops, exact-white pivot at stop 6):
|
|
208
|
+
`RdBu`, `RdYlBu`, `PuGn`, `MgGn`, `PkTe`, `GdBu`, `BrTe`, `BrGn`
|
|
209
|
+
|
|
210
|
+
**Diverging — Sequential pairs** (13 stops, one sequential hue per arm):
|
|
211
|
+
`greensblues`, `redsblues`, `redsgreens`, `redscyans`, `redslavenders`, `redsviolets`, `redsneongreens`, `rosesblues`, `rosescyans`, `rosesgreens`, `rosesneongreens`, `orangesblues`, `orangescyans`, `orangespurples`, `orangeslavenders`, `orangesviolets`, `orangesneongreens`, `yellowsblues`, `yellowspurples`, `yellowslavenders`, `brownsblues`, `brownsgreens`, `brownscyans`, `brownsneongreens`, `magentasneongreens`, `magentasgreens`, `magentasblues`, `magentascyans`, `violetsoranges`, `violetsyellows`, `purplesgreens`, `purplesblues`, `purplesneongreens`, `lavendersgreens`, `lavendersblues`, `lavendersneongreens`, `cyanspurples`, `cyanslavenders`, `cyansviolets`, `greysblues`, `greysreds`, `greysgreens`, `greyscyans`, `greysyellows`, `greysoranges`, `greysmagentas`, `greysviolets`, `greysneongreens`, `greyspurples`, `greyslavender`, `greysrose`
|
|
212
|
+
|
|
213
|
+
**Discrete:**
|
|
214
|
+
`nucleotides` (5 colors: A, T, G, C, U), `proteins` (8 biochemical groups: hydrophobic, aromatic, positive, negative, polar, proline, glycine, cysteine)
|
|
215
|
+
|
|
216
|
+
**Matplotlib ported** (prefixed `mpl_`):
|
|
217
|
+
`mpl_viridis`, `mpl_plasma`, `mpl_inferno`, `mpl_magma`, `mpl_cividis`, `mpl_turbo`, `mpl_Blues`, `mpl_Greens`, `mpl_Greys`, `mpl_Oranges`, `mpl_Purples`, `mpl_Reds`, `mpl_YlGnBu`, `mpl_YlOrBr`, `mpl_YlOrRd`, and more.
|
|
218
|
+
|
|
219
|
+
**cmocean ported** (prefixed `cmocean_`):
|
|
220
|
+
`cmocean_algae`, `cmocean_amp`, `cmocean_balance`, `cmocean_curl`, `cmocean_deep`, `cmocean_delta`, `cmocean_dense`, `cmocean_diff`, `cmocean_gray`, `cmocean_haline`, `cmocean_ice`, `cmocean_matter`, `cmocean_oxy`, `cmocean_phase`, `cmocean_rain`, `cmocean_solar`, `cmocean_speed`, `cmocean_tarn`, `cmocean_tempo`, `cmocean_thermal`, `cmocean_topo`, `cmocean_turbid`
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Saving charts
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
petaurus.save(chart, "plots/myplot")
|
|
228
|
+
# writes: plots/myplot_light.png, plots/myplot_light.svg
|
|
229
|
+
# plots/myplot_dark.png, plots/myplot_dark.svg
|
|
230
|
+
# plots/myplot_vegalite.json
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Produces light and dark PNG and SVG files from a single call. SVG output is post-processed to flatten Vega's redundant `<g>` wrappers, making it easier to navigate in Illustrator. A Vega-Lite JSON spec is also saved by default for full reproducibility.
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
petaurus.save(chart, "myplot", ppi=1200) # default PPI; reduce for faster exports
|
|
237
|
+
petaurus.save(chart, "myplot", save_vega_spec=False) # skip the JSON spec
|
|
238
|
+
petaurus.save(chart, "myplot", description="Figure 1") # embed a description in the SVG
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Custom marks
|
|
244
|
+
|
|
245
|
+
### petaurus.mark_violin()
|
|
246
|
+
|
|
247
|
+
Violin plot with an embedded boxplot.
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
petaurus.options(chartWidth=300)
|
|
251
|
+
palette = petaurus.palette("lavenders", n=len(CATEGORIES))
|
|
252
|
+
|
|
253
|
+
chart = petaurus.mark_violin(df, "group", "value", CATEGORIES, palette=palette)
|
|
254
|
+
petaurus.save(chart, "violin")
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
| Parameter | Default | Description |
|
|
258
|
+
|---|---|---|
|
|
259
|
+
| `df` | required | Polars DataFrame |
|
|
260
|
+
| `x_col` | required | Grouping column name |
|
|
261
|
+
| `y_col` | required | Value column name |
|
|
262
|
+
| `categories` | required | Ordered list of group labels |
|
|
263
|
+
| `palette` | `None` | Single color or list of colors for violin fills |
|
|
264
|
+
| `boxplot_size` | `markSize × 0.8` | Boxplot box width in pixels |
|
|
265
|
+
| `boxplot_color` | `"black"` | Boxplot fill color |
|
|
266
|
+
| `fillOpacity` | theme default | Violin fill opacity |
|
|
267
|
+
| `stroke` | `None` | Violin outline color (`None` = no outline) |
|
|
268
|
+
| `strokeWidth` | theme default | Violin outline width |
|
|
269
|
+
| `legend` | `False` | Show a color legend |
|
|
270
|
+
| `angledX` | theme default | Angle x-axis labels |
|
|
271
|
+
| `steps` | `200` | KDE grid resolution per group |
|
|
272
|
+
|
|
273
|
+
### petaurus.mark_strip()
|
|
274
|
+
|
|
275
|
+
Jittered or beeswarm points with a median tick and optional mean ± error bars.
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
chart = petaurus.mark_strip(df, "group", "value", CATEGORIES)
|
|
279
|
+
chart = petaurus.mark_strip(df, "group", "value", CATEGORIES, scatter="beeswarm")
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
| Parameter | Default | Description |
|
|
283
|
+
|---|---|---|
|
|
284
|
+
| `scatter` | `"jitter"` | `"jitter"` (fast, random Gaussian) or `"beeswarm"` (collision-avoidance) |
|
|
285
|
+
| `palette` | `None` | List of colors for points |
|
|
286
|
+
| `point_size` | theme `markSize` | Point size in sq px |
|
|
287
|
+
| `jitter_scale` | `4.0` | Jitter standard deviation in pixels |
|
|
288
|
+
| `errorbars` | `True` | Show mean ± error bars |
|
|
289
|
+
| `errorbar_extent` | `"sem"` | `"sem"` or `"sd"` |
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Statistical annotations
|
|
294
|
+
|
|
295
|
+
Add a p-value bracket between two groups using `petaurus.pvalue_layer()`. Combine with any chart using `+`.
|
|
296
|
+
|
|
297
|
+
```python
|
|
298
|
+
ann = petaurus.pvalue_layer(
|
|
299
|
+
df, "group", "value", "Control", "Drug A",
|
|
300
|
+
test="mannwhitneyu",
|
|
301
|
+
categories=["Control", "Drug A", "Drug B"],
|
|
302
|
+
chartWidth=300,
|
|
303
|
+
y=210,
|
|
304
|
+
)
|
|
305
|
+
chart + ann
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
From a pre-computed p-value:
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
ann = petaurus.pvalue_layer(
|
|
312
|
+
group1="Control", group2="Drug A",
|
|
313
|
+
pvalue=0.023, y=210,
|
|
314
|
+
categories=CATEGORIES,
|
|
315
|
+
chartWidth=300,
|
|
316
|
+
)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
| Parameter | Default | Description |
|
|
320
|
+
|---|---|---|
|
|
321
|
+
| `df` | `None` | Polars DataFrame (required unless `pvalue` and `y` are both provided) |
|
|
322
|
+
| `x_col`, `y_col` | `None` | Column names for groups and values |
|
|
323
|
+
| `group1`, `group2` | required | Group labels to compare |
|
|
324
|
+
| `test` | `"mannwhitneyu"` | Statistical test: `"mannwhitneyu"`, `"ttest_ind"`, `"ttest_rel"`, `"wilcoxon"`, `"tukey_hsd"` |
|
|
325
|
+
| `pvalue` | `None` | Pre-computed p-value (skips the test) |
|
|
326
|
+
| `correction` | `None` | `"bonferroni"` or `None` |
|
|
327
|
+
| `n_comparisons` | `1` | Number of comparisons for Bonferroni correction |
|
|
328
|
+
| `y` | auto | Y position of the bracket in data units |
|
|
329
|
+
| `y_pad` | `5` | Padding above the group max when `y` is auto-placed |
|
|
330
|
+
| `style` | `"line"` | `"line"` (bar only) or `"bracket"` (bar + end ticks) |
|
|
331
|
+
| `categories` | inferred | Ordered list of all x-axis categories |
|
|
332
|
+
| `chartWidth` | theme default | Chart width used to compute text x position |
|
|
333
|
+
| `reverse` | `False` | Flip the annotation below the bar |
|
|
334
|
+
| `decimals` | `3` | Decimal places in the p-value label |
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Data transforms
|
|
339
|
+
|
|
340
|
+
### Jitter
|
|
341
|
+
|
|
342
|
+
Adds random Gaussian x-offsets to each row, useful for strip plots.
|
|
343
|
+
|
|
344
|
+
```python
|
|
345
|
+
df = petaurus.add_jitter_offsets(df, scale=5)
|
|
346
|
+
|
|
347
|
+
alt.Chart(df).mark_circle().encode(
|
|
348
|
+
x=alt.X("group:N"),
|
|
349
|
+
y=alt.Y("value:Q"),
|
|
350
|
+
xOffset=alt.XOffset("jitter_x:Q"),
|
|
351
|
+
)
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
| Parameter | Default | Description |
|
|
355
|
+
|---|---|---|
|
|
356
|
+
| `scale` | `5.0` | Standard deviation of jitter in pixels |
|
|
357
|
+
| `out_col` | `"jitter_x"` | Output column name |
|
|
358
|
+
| `seed` | `20220701` | Random seed |
|
|
359
|
+
|
|
360
|
+
### Beeswarm
|
|
361
|
+
|
|
362
|
+
Computes collision-avoiding x-offsets per group. Better than jitter for small n, but slower.
|
|
363
|
+
|
|
364
|
+
```python
|
|
365
|
+
df = petaurus.add_beeswarm_offsets(
|
|
366
|
+
df,
|
|
367
|
+
y_col="value",
|
|
368
|
+
group_by=["group"],
|
|
369
|
+
height_px=200,
|
|
370
|
+
markSize=10,
|
|
371
|
+
)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
| Parameter | Default | Description |
|
|
375
|
+
|---|---|---|
|
|
376
|
+
| `y_col` | required | Value column |
|
|
377
|
+
| `group_by` | required | Column(s) defining each beeswarm group |
|
|
378
|
+
| `height_px` | theme `chartHeight` | Chart height in pixels |
|
|
379
|
+
| `markSize` | `10` | Point size (area in sq px) |
|
|
380
|
+
| `out_col` | `"beeswarm_x"` | Output column name |
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## Development
|
|
385
|
+
|
|
386
|
+
### Building palettes
|
|
387
|
+
|
|
388
|
+
`scripts/build/build_palettes.py` documents the Oklab recipes for all custom palette families and prints updated hex literals to stdout. Use this to calibrate or extend palettes.
|
|
389
|
+
|
|
390
|
+
```sh
|
|
391
|
+
# uv
|
|
392
|
+
uv run python scripts/build/build_palettes.py
|
|
393
|
+
|
|
394
|
+
# pip
|
|
395
|
+
python scripts/build/build_palettes.py
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
The four recipes are:
|
|
399
|
+
|
|
400
|
+
1. **Sequential single-hue** — fix hue; sweep L from light to dark with C = `frac × Cmax(L, hue)`; arc-length resample to 12 stops.
|
|
401
|
+
2. **Sequential multi-hue** — interpolate `(L, hue)` between keyframes; same chroma and arc-length logic.
|
|
402
|
+
3. **Diverging** — two arms meeting at an exact-white pivot; 13 stops so the white center lands exactly on the V-corner.
|
|
403
|
+
4. **Chroma-scaling** — preserve L, scale `(a, b)` by a constant to derive lighter variants.
|
|
404
|
+
|
|
405
|
+
Palette hex values live in `petaurus/palettes.py` as plain lists — no color math runs at import time.
|
|
406
|
+
|
|
407
|
+
### Building the gallery
|
|
408
|
+
|
|
409
|
+
```sh
|
|
410
|
+
# uv
|
|
411
|
+
uv run python scripts/build/build_gallery.py
|
|
412
|
+
|
|
413
|
+
# pip
|
|
414
|
+
python scripts/build/build_gallery.py
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Writes `docs/index.html`. Open in a browser to browse all palettes across 11 chart types.
|
|
418
|
+
|
|
419
|
+
### Exporting swatches for Adobe Illustrator
|
|
420
|
+
|
|
421
|
+
```sh
|
|
422
|
+
# uv
|
|
423
|
+
uv run python scripts/build/build_swatches_for_illustrator.py
|
|
424
|
+
|
|
425
|
+
# pip
|
|
426
|
+
python scripts/build/build_swatches_for_illustrator.py
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Generates `scripts/import_palettes_to_illustrator.jsx`. To import into Illustrator:
|
|
430
|
+
|
|
431
|
+
1. Open or create a document in Adobe Illustrator.
|
|
432
|
+
2. Go to **File > Scripts > Other Script...**
|
|
433
|
+
3. Select `scripts/import_palettes_to_illustrator.jsx`.
|
|
434
|
+
4. All palettes are added as named swatch groups in the Swatches panel.
|
|
435
|
+
|
|
436
|
+
Re-run this script after adding or modifying palettes in `petaurus/palettes.py`.
|