plotastro 1.1.0__tar.gz → 1.1.0b2__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.
- {plotastro-1.1.0 → plotastro-1.1.0b2}/.gitignore +2 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/CHANGELOG.md +0 -21
- {plotastro-1.1.0 → plotastro-1.1.0b2}/PKG-INFO +2 -9
- {plotastro-1.1.0 → plotastro-1.1.0b2}/README.md +1 -8
- plotastro-1.1.0b2/docs/api.md +94 -0
- plotastro-1.1.0b2/docs/colors.md +190 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/docs/index.md +2 -2
- {plotastro-1.1.0 → plotastro-1.1.0b2}/docs/installation.md +3 -13
- plotastro-1.1.0b2/examples/make_reference_figures.py +117 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/tutorial.ipynb +128 -468
- {plotastro-1.1.0 → plotastro-1.1.0b2}/pyproject.toml +1 -1
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/_colors.py +4 -46
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/_core.py +1 -42
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/_extras.py +3 -38
- plotastro-1.1.0/CITATION.cff +0 -25
- plotastro-1.1.0/docs/api/accessibility.md +0 -16
- plotastro-1.1.0/docs/api/authors.md +0 -48
- plotastro-1.1.0/docs/api/cmasher.md +0 -45
- plotastro-1.1.0/docs/api/colors.md +0 -136
- plotastro-1.1.0/docs/api/markers.md +0 -61
- plotastro-1.1.0/docs/api/styles.md +0 -122
- plotastro-1.1.0/docs/api.md +0 -102
- plotastro-1.1.0/docs/colors.md +0 -392
- plotastro-1.1.0/examples/figures/cmasher_examples.png +0 -0
- plotastro-1.1.0/examples/figures/cmasher_maps.png +0 -0
- plotastro-1.1.0/examples/make_reference_figures.py +0 -211
- plotastro-1.1.0/tests/test_docs.py +0 -46
- {plotastro-1.1.0 → plotastro-1.1.0b2}/.github/workflows/ci.yml +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/.github/workflows/publish.yml +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/.readthedocs.yaml +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/LICENSE +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/docs/authors.md +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/docs/changelog.md +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/docs/conf.py +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/docs/faq.md +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/docs/journals.md +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/docs/markers.md +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/docs/quickstart.md +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/docs/requirements.txt +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/authors_example.csv +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/figures/cmasher.png +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/figures/cvd_check.png +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/figures/example_column.png +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/figures/example_full.png +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/figures/linestyles.png +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/figures/markers.png +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/figures/palette.png +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/figures/palette_okabe_ito.png +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/examples/figures/redundant_encoding.png +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/requirements-dev.txt +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/requirements.txt +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/__init__.py +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/_authors.py +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/styles/aanda.mplstyle +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/styles/apj.mplstyle +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/styles/euclid.mplstyle +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/styles/jcap.mplstyle +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/styles/mnras.mplstyle +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/styles/natastro.mplstyle +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/styles/oja.mplstyle +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/styles/prd.mplstyle +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/src/plotastro/styles/rasti.mplstyle +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/tests/conftest.py +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/tests/test_authors.py +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/tests/test_colors.py +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/tests/test_extras.py +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/tests/test_sizing.py +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/tests/test_styles.py +0 -0
- {plotastro-1.1.0 → plotastro-1.1.0b2}/tools/generate_styles.py +0 -0
|
@@ -1,26 +1,5 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 1.1.0 — 2026-10-06
|
|
4
|
-
|
|
5
|
-
The stable release of the 1.1 series: everything in the 1.1.0b1 and
|
|
6
|
-
1.1.0b2 betas below, plus documentation. `pip install plotastro` now
|
|
7
|
-
gives this version. No change in behaviour since 1.1.0b2.
|
|
8
|
-
|
|
9
|
-
### Added
|
|
10
|
-
- Install instructions for conda-forge
|
|
11
|
-
(`conda install -c conda-forge plotastro`, Python 3.11 or newer).
|
|
12
|
-
- The API reference is split into one page per topic (styles, colours,
|
|
13
|
-
CMasher, markers, authors, accessibility). The colours page has a
|
|
14
|
-
longer guide to colormaps: which map suits which kind of data, lines
|
|
15
|
-
coloured by a parameter with a colour bar, diverging and cyclic data,
|
|
16
|
-
and common errors. The tutorial notebook runs the same examples.
|
|
17
|
-
- The docstrings of `lighten`, `darken`, `check_colors`,
|
|
18
|
-
`current_journal`, `subplots`, `set_size`, `style_cycler`,
|
|
19
|
-
`show_colors`, `show_markers` and `show_linestyles` now list their
|
|
20
|
-
parameters and return values.
|
|
21
|
-
- A test checks that every public name is in the API reference and that
|
|
22
|
-
the constants it shows match the code.
|
|
23
|
-
|
|
24
3
|
## 1.1.0b2 — 2026-10-06 (beta)
|
|
25
4
|
|
|
26
5
|
A pre-release: `pip install plotastro` still gives the stable 1.0.1. To try
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: plotastro
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.0b2
|
|
4
4
|
Summary: Publication-quality matplotlib styles and helpers for astronomy journals (MNRAS, A&A, ApJ, OJA, PRD, JCAP, Nature Astronomy)
|
|
5
5
|
Project-URL: Homepage, https://github.com/BehnoodBandi/plotastro
|
|
6
6
|
Project-URL: Issues, https://github.com/BehnoodBandi/plotastro/issues
|
|
@@ -28,7 +28,6 @@ Description-Content-Type: text/markdown
|
|
|
28
28
|
# plotastro
|
|
29
29
|
|
|
30
30
|
[](https://pypi.org/project/plotastro/)
|
|
31
|
-
[](https://anaconda.org/conda-forge/plotastro)
|
|
32
31
|
[](https://pypi.org/project/plotastro/)
|
|
33
32
|
[](https://github.com/BehnoodBandi/plotastro/actions/workflows/ci.yml)
|
|
34
33
|
[](https://plotastro.readthedocs.io)
|
|
@@ -44,7 +43,7 @@ helpers that make the tedious parts (sizing, panel labels, accessibility
|
|
|
44
43
|
checks, saving) one-liners.
|
|
45
44
|
|
|
46
45
|
```bash
|
|
47
|
-
pip install plotastro
|
|
46
|
+
pip install plotastro
|
|
48
47
|
```
|
|
49
48
|
|
|
50
49
|
**Simplest usage — no new API to learn.** Importing plotastro registers the
|
|
@@ -275,12 +274,6 @@ map with a fixed number of lines, sample exactly that many:
|
|
|
275
274
|
`pa.cmasher_colors("rainforest", n=len(models))`. Please cite CMasher if
|
|
276
275
|
you use it (`cmasher.get_bibtex()`).
|
|
277
276
|
|
|
278
|
-
The [colours page of the documentation](https://plotastro.readthedocs.io/en/latest/colors.html)
|
|
279
|
-
has more: which map suits which kind of data, lines coloured by a
|
|
280
|
-
parameter with a colour bar, diverging and cyclic data, and common
|
|
281
|
-
errors. The [tutorial notebook](examples/tutorial.ipynb) runs the same
|
|
282
|
-
examples.
|
|
283
|
-
|
|
284
277
|
### Checking accessibility yourself
|
|
285
278
|
|
|
286
279
|

|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# plotastro
|
|
2
2
|
|
|
3
3
|
[](https://pypi.org/project/plotastro/)
|
|
4
|
-
[](https://anaconda.org/conda-forge/plotastro)
|
|
5
4
|
[](https://pypi.org/project/plotastro/)
|
|
6
5
|
[](https://github.com/BehnoodBandi/plotastro/actions/workflows/ci.yml)
|
|
7
6
|
[](https://plotastro.readthedocs.io)
|
|
@@ -17,7 +16,7 @@ helpers that make the tedious parts (sizing, panel labels, accessibility
|
|
|
17
16
|
checks, saving) one-liners.
|
|
18
17
|
|
|
19
18
|
```bash
|
|
20
|
-
pip install plotastro
|
|
19
|
+
pip install plotastro
|
|
21
20
|
```
|
|
22
21
|
|
|
23
22
|
**Simplest usage — no new API to learn.** Importing plotastro registers the
|
|
@@ -248,12 +247,6 @@ map with a fixed number of lines, sample exactly that many:
|
|
|
248
247
|
`pa.cmasher_colors("rainforest", n=len(models))`. Please cite CMasher if
|
|
249
248
|
you use it (`cmasher.get_bibtex()`).
|
|
250
249
|
|
|
251
|
-
The [colours page of the documentation](https://plotastro.readthedocs.io/en/latest/colors.html)
|
|
252
|
-
has more: which map suits which kind of data, lines coloured by a
|
|
253
|
-
parameter with a colour bar, diverging and cyclic data, and common
|
|
254
|
-
errors. The [tutorial notebook](examples/tutorial.ipynb) runs the same
|
|
255
|
-
examples.
|
|
256
|
-
|
|
257
250
|
### Checking accessibility yourself
|
|
258
251
|
|
|
259
252
|

|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# API reference
|
|
2
|
+
|
|
3
|
+
Everything is available at the top level:
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import plotastro as pa
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Styles and sizing
|
|
10
|
+
|
|
11
|
+
```{eval-rst}
|
|
12
|
+
.. autofunction:: plotastro.set_style
|
|
13
|
+
.. autofunction:: plotastro.figsize
|
|
14
|
+
.. autofunction:: plotastro.subplots
|
|
15
|
+
.. autofunction:: plotastro.savefig
|
|
16
|
+
.. autofunction:: plotastro.current_journal
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`pa.use(...)` is an alias of {func}`plotastro.set_style`.
|
|
20
|
+
|
|
21
|
+
## Colours
|
|
22
|
+
|
|
23
|
+
```{eval-rst}
|
|
24
|
+
.. autofunction:: plotastro.lighten
|
|
25
|
+
.. autofunction:: plotastro.darken
|
|
26
|
+
.. autofunction:: plotastro.simulate_cvd
|
|
27
|
+
.. autofunction:: plotastro.check_colors
|
|
28
|
+
.. autofunction:: plotastro.check_figure
|
|
29
|
+
.. autofunction:: plotastro.euclid_colors
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### CMasher (optional)
|
|
33
|
+
|
|
34
|
+
These need the optional `cmasher` package (`pip install cmasher`); see
|
|
35
|
+
{doc}`colors`. `set_style(palette="cmr.<name>", cmap="cmr.<name>")` uses
|
|
36
|
+
them too.
|
|
37
|
+
|
|
38
|
+
```{eval-rst}
|
|
39
|
+
.. autofunction:: plotastro.cmasher_colors
|
|
40
|
+
.. autofunction:: plotastro.cmasher_cmap
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Palette constants
|
|
44
|
+
|
|
45
|
+
| name | contents |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `pa.COLORS` | the default 12-colour colour-blind-friendly cycle, by name |
|
|
48
|
+
| `pa.CYCLE` | the same colours as an ordered list |
|
|
49
|
+
| `pa.OKABE_ITO` | Okabe & Ito (2008) 8-colour CVD-safe palette |
|
|
50
|
+
| `pa.PETROFF10` | Petroff (2021) 10-colour CVD-optimised palette |
|
|
51
|
+
| `pa.PETROFF8` | Petroff (2021) 8-colour palette — the Euclid niceplots default |
|
|
52
|
+
| `pa.TOL_VIBRANT` | Paul Tol's *vibrant* 7-colour CVD-safe scheme |
|
|
53
|
+
| `pa.PAIRED` | light/dark pairs: `pa.PAIRED["blue"] -> (light, dark)` |
|
|
54
|
+
|
|
55
|
+
## Markers, line styles and labels
|
|
56
|
+
|
|
57
|
+
```{eval-rst}
|
|
58
|
+
.. autofunction:: plotastro.style_cycler
|
|
59
|
+
.. autofunction:: plotastro.label_panels
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
| name | contents |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `pa.MARKERS` | marker sequence that stays distinguishable at 4 pt |
|
|
65
|
+
| `pa.LINESTYLES` | named dash patterns beyond matplotlib's built-ins |
|
|
66
|
+
|
|
67
|
+
## Reference charts
|
|
68
|
+
|
|
69
|
+
```{eval-rst}
|
|
70
|
+
.. autofunction:: plotastro.show_colors
|
|
71
|
+
.. autofunction:: plotastro.show_markers
|
|
72
|
+
.. autofunction:: plotastro.show_linestyles
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Author lists
|
|
76
|
+
|
|
77
|
+
```{eval-rst}
|
|
78
|
+
.. autofunction:: plotastro.authorlist
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The `plotastro-authors` command-line tool wraps this function; run
|
|
82
|
+
`plotastro-authors --help` for its options.
|
|
83
|
+
|
|
84
|
+
## Journal data and legacy
|
|
85
|
+
|
|
86
|
+
```{eval-rst}
|
|
87
|
+
.. autofunction:: plotastro.set_size
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| name | contents |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `pa.JOURNALS` | per-journal column/full widths (LaTeX points) and metadata |
|
|
93
|
+
| `pa.GOLDEN` | the golden ratio (default figure aspect), ≈ 0.618 |
|
|
94
|
+
| `pa.STYLE_DIR` | path to the bundled `.mplstyle` files |
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Colours
|
|
2
|
+
|
|
3
|
+
## The default palette
|
|
4
|
+
|
|
5
|
+
```{image} _figures/palette.png
|
|
6
|
+
:alt: The default colour-blind-friendly cycle
|
|
7
|
+
:width: 85%
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
The default cycle has 12 colours, all accessible by name via
|
|
11
|
+
`plotastro.COLORS` (e.g. `pa.COLORS["blue"]`), or as matplotlib's
|
|
12
|
+
`"C0"`…`"C11"` shorthands:
|
|
13
|
+
|
|
14
|
+
- **C0–C8** are a colour-blind-safe re-ordering of the
|
|
15
|
+
[ColorBrewer](https://colorbrewer2.org) *Set1* qualitative palette
|
|
16
|
+
(popularised by [Thøger Rivera-Thorsen's CBcycle](https://gist.github.com/thriveth/8560036)).
|
|
17
|
+
Consecutive colours differ in **lightness as well as hue**, so adjacent
|
|
18
|
+
lines stay distinguishable under the common deficiencies (deuteranopia,
|
|
19
|
+
protanopia) *and* in greyscale print; the notorious red–green pair is
|
|
20
|
+
pushed far apart in the cycle (green is C2, red is C7), so plots with a
|
|
21
|
+
handful of lines never rely on it.
|
|
22
|
+
- **C9–C11** are light companions (from Tableau's *Color Blind 10*): use
|
|
23
|
+
them for uncertainty bands, reference curves, or de-emphasised data
|
|
24
|
+
underneath a saturated line of the same hue.
|
|
25
|
+
|
|
26
|
+
## Matched shades without transparency
|
|
27
|
+
|
|
28
|
+
Better for print and EPS than `alpha=` (no colour shifts where elements
|
|
29
|
+
overlap):
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
ax.plot(x, y, color=pa.COLORS["blue"])
|
|
33
|
+
ax.fill_between(x, lo, hi, color=pa.lighten(pa.COLORS["blue"], 0.7))
|
|
34
|
+
pa.darken(pa.COLORS["orange"], 0.3) # the other direction
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## More palettes
|
|
38
|
+
|
|
39
|
+
- `pa.OKABE_ITO` — [Okabe & Ito (2008)](https://jfly.uni-koeln.de/color/),
|
|
40
|
+
*the* classic CVD-safe recommendation for categorical colours in science;
|
|
41
|
+
- `pa.PETROFF10` — [Petroff (2021)](https://arxiv.org/abs/2107.02270), the
|
|
42
|
+
CVD-optimised 10-colour cycle used across particle physics;
|
|
43
|
+
- `pa.PETROFF8` — Petroff's 8-colour sibling, the default cycle of the
|
|
44
|
+
Euclid Consortium's [niceplots](https://gitlab.euclid-sgs.uk/ECEB/niceplots)
|
|
45
|
+
(and of the `euclid` style here);
|
|
46
|
+
- `pa.TOL_VIBRANT` — [Paul Tol's](https://personal.sron.nl/~pault/) *vibrant*
|
|
47
|
+
qualitative scheme, 7 CVD-safe colours;
|
|
48
|
+
- `pa.PAIRED` — light/dark pairs for data/model or before/after
|
|
49
|
+
comparisons: `pa.PAIRED["blue"]` → `("#a6cee3", "#1f78b4")`.
|
|
50
|
+
|
|
51
|
+
Any of them can become the active cycle when you activate a style —
|
|
52
|
+
`pa.set_style("mnras", palette="okabe_ito")` — or pass your own list of
|
|
53
|
+
colours.
|
|
54
|
+
|
|
55
|
+
## Euclid colour schemes
|
|
56
|
+
|
|
57
|
+
The `euclid` style (see {doc}`journals`) and these colour schemes are
|
|
58
|
+
adapted from the Euclid Consortium Editorial Board's
|
|
59
|
+
[niceplots](https://gitlab.euclid-sgs.uk/ECEB/niceplots) (Euclid-internal,
|
|
60
|
+
GPL-3.0): the colours are re-expressed here, nothing is copied from it.
|
|
61
|
+
{func}`plotastro.euclid_colors` returns each scheme under its niceplots name:
|
|
62
|
+
|
|
63
|
+
| scheme | colours |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `"categorical1"` | Petroff (2021) 8 colours — `pa.PETROFF8`; the Euclid default |
|
|
66
|
+
| `"categorical2"` | Okabe & Ito — `pa.OKABE_ITO` |
|
|
67
|
+
| `"categorical3"` | black, then Tol's *vibrant* scheme — `pa.TOL_VIBRANT` |
|
|
68
|
+
| `"sequential"` | `n` colours of increasing brightness from `copper` |
|
|
69
|
+
| `"diverging"` | `n` colours from blue to red from `coolwarm` |
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
pa.set_style("euclid", palette="categorical3") # by name
|
|
73
|
+
ax.set_prop_cycle(color=pa.euclid_colors("sequential", n=6)) # per axes
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Checking accessibility yourself
|
|
77
|
+
|
|
78
|
+
```{image} _figures/cvd_check.png
|
|
79
|
+
:alt: The default palette under simulated colour-vision deficiencies
|
|
80
|
+
:width: 85%
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Don't take the palette's word for it — simulate it (Machado et al. 2009
|
|
84
|
+
model, no extra dependencies):
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
pa.check_colors() # any palette under deuteranopia/protanopia/greyscale
|
|
88
|
+
pa.check_colors(pa.PAIRED) # works on your own colour lists/dicts too
|
|
89
|
+
pa.check_figure(fig) # simulate a whole rendered figure — the
|
|
90
|
+
# final check before submission
|
|
91
|
+
pa.simulate_cvd("#e41a1c", "deuteranopia") # the raw transform
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
If two lines merge in any panel, add markers or dash patterns (see
|
|
95
|
+
{doc}`markers`), or pick colours further apart in the cycle. MNRAS
|
|
96
|
+
recommends [Color Oracle](https://colororacle.org) and ColorBrewer for
|
|
97
|
+
exactly this; with plotastro it's built in.
|
|
98
|
+
|
|
99
|
+
## Colormaps
|
|
100
|
+
|
|
101
|
+
The styles default to `viridis` (perceptually uniform, CVD-safe). Good
|
|
102
|
+
picks: `viridis`/`magma`/`cividis` for sequential data, `RdBu_r` or
|
|
103
|
+
`coolwarm` for diverging data (red–*blue*, not red–green). Avoid
|
|
104
|
+
`jet`/`rainbow`. To change the default for every `imshow`, `pcolormesh`,
|
|
105
|
+
`scatter`, … pass `cmap=` when you activate a style:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
pa.set_style("mnras", cmap="cividis")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For many more maps, plotastro can use CMasher (next section); see also
|
|
112
|
+
[cmocean](https://matplotlib.org/cmocean/).
|
|
113
|
+
|
|
114
|
+
## CMasher colours and colormaps (optional)
|
|
115
|
+
|
|
116
|
+
```{image} _figures/cmasher.png
|
|
117
|
+
:alt: A CMasher colour cycle for a family of lines, and a CMasher colormap on an image
|
|
118
|
+
:width: 100%
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
[CMasher](https://cmasher.readthedocs.io) (van der Velden 2020,
|
|
122
|
+
[JOSS 5, 2004](https://doi.org/10.21105/joss.02004)) is a collection of
|
|
123
|
+
scientific colormaps: sequential, diverging and cyclic, all designed to be
|
|
124
|
+
perceptually uniform, and most of them colour-vision-deficiency friendly.
|
|
125
|
+
plotastro can use them for discrete colours and for colormaps. CMasher is
|
|
126
|
+
**not** a dependency of plotastro: install it only if you want it,
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
pip install cmasher # or: pip install "plotastro[cmasher]"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
and plotastro imports it only when you ask for a CMasher colour. Every
|
|
133
|
+
other feature works the same without it. CMasher names start with
|
|
134
|
+
`cmr.` (`"cmr.rainforest"`, `"cmr.iceburn"`, …), which is also how its
|
|
135
|
+
maps are registered with matplotlib; append `_r` for the reversed map.
|
|
136
|
+
Browse them all in the
|
|
137
|
+
[CMasher colormap overview](https://cmasher.readthedocs.io), or list them
|
|
138
|
+
with `cmasher.get_cmap_list()`.
|
|
139
|
+
|
|
140
|
+
### Discrete colours
|
|
141
|
+
|
|
142
|
+
Pass a `"cmr."` name as the palette to get a colour cycle of 8 colours
|
|
143
|
+
sampled from that map, or use {func}`plotastro.cmasher_colors` for a
|
|
144
|
+
different number:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
pa.set_style("mnras", palette="cmr.rainforest") # 8-colour cycle
|
|
148
|
+
ax.set_prop_cycle(color=pa.cmasher_colors("torch", n=5)) # 5, this axes only
|
|
149
|
+
colors = pa.cmasher_colors("ocean", n=4, cmap_range=(0.2, 0.8))
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The colours are hex strings, equally spaced over `cmap_range`. Its default,
|
|
153
|
+
`(0.15, 0.85)`, follows CMasher's own advice: most of its sequential maps
|
|
154
|
+
run from black to white, and those ends disappear against the axes or the
|
|
155
|
+
page. Sequential maps work best for lines. CMasher recommends:
|
|
156
|
+
|
|
157
|
+
- **for lines that must be easy to tell apart:** maps with a large
|
|
158
|
+
perceptual range, such as `apple`, `chroma`, `neon`, `rainforest` and
|
|
159
|
+
`torch`;
|
|
160
|
+
- **for lines that are steps of one quantity** (redshifts, masses, …): a
|
|
161
|
+
single-hue map, such as `flamingo`, `freeze`, `gothic`, `jungle` and
|
|
162
|
+
`ocean`.
|
|
163
|
+
|
|
164
|
+
These cycles are ordered from dark to light, and a matplotlib cycle starts
|
|
165
|
+
at the first colour. So for a fixed number of lines, sample exactly that
|
|
166
|
+
many, `pa.cmasher_colors("rainforest", n=len(models))`, and they will span
|
|
167
|
+
the whole map. Check the result with `pa.check_colors(...)` as for any other
|
|
168
|
+
palette.
|
|
169
|
+
|
|
170
|
+
### Colormaps
|
|
171
|
+
|
|
172
|
+
Make a CMasher map the default colormap with `set_style(cmap=...)`, or get
|
|
173
|
+
the colormap itself with {func}`plotastro.cmasher_cmap`. It can also cut
|
|
174
|
+
the map to part of its range, or split it into a few discrete levels:
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
pa.set_style("mnras", cmap="cmr.ocean") # default for imshow etc.
|
|
178
|
+
|
|
179
|
+
ax.imshow(img, cmap=pa.cmasher_cmap("rainforest"))
|
|
180
|
+
ax.pcolormesh(x, y, z, cmap=pa.cmasher_cmap("ocean", cmap_range=(0.15, 0.85)))
|
|
181
|
+
ax.contourf(x, y, z, levels=6, cmap=pa.cmasher_cmap("iceburn", n=6))
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Once CMasher has been imported (by plotastro or by `import cmasher`), every
|
|
185
|
+
matplotlib function also accepts its maps by name: `cmap="cmr.iceburn"`.
|
|
186
|
+
Some of CMasher's diverging maps (`iceburn`, `redshift`, `seaweed`,
|
|
187
|
+
`watermelon`, `wildfire`) have a **black** centre instead of a white one.
|
|
188
|
+
|
|
189
|
+
If you use CMasher in a paper, please cite it; `cmasher.get_bibtex()`
|
|
190
|
+
prints the reference.
|
|
@@ -10,7 +10,7 @@ helpers that make the tedious parts (sizing, panel labels, accessibility
|
|
|
10
10
|
checks, author lists, saving) one-liners.
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
pip install plotastro
|
|
13
|
+
pip install plotastro
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
**Simplest usage — no new API to learn.** Importing plotastro registers the
|
|
@@ -72,7 +72,7 @@ deliberately matches the Euclid Consortium's own niceplots look instead
|
|
|
72
72
|
- {doc}`quickstart` — the five-minute version
|
|
73
73
|
- {doc}`tutorial` — the full hands-on notebook, rendered
|
|
74
74
|
- {doc}`journals` — supported journals and their figure widths
|
|
75
|
-
- {doc}`colors` — the palettes
|
|
75
|
+
- {doc}`colors` — the palettes and colour-blindness checking
|
|
76
76
|
- {doc}`markers` — markers, line styles, cyclers and panel labels
|
|
77
77
|
- {doc}`authors` — LaTeX author lists from your collaboration's CSV
|
|
78
78
|
- {doc}`api` — every public function
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
pip install plotastro
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
stable version
|
|
9
|
+
To try the latest **beta** (a pre-release; plain `pip install` keeps giving
|
|
10
|
+
you the stable version):
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
pip install --pre plotastro
|
|
13
|
+
pip install --pre plotastro # or: pip install "plotastro==1.1.0b2"
|
|
14
14
|
pip install --pre "plotastro[cmasher]" # the beta with CMasher
|
|
15
15
|
```
|
|
16
16
|
|
|
@@ -31,16 +31,6 @@ pip install "plotastro[cmasher]" # or simply: pip install cmasher
|
|
|
31
31
|
plotastro imports CMasher only when you ask for a CMasher colour, so it is
|
|
32
32
|
never needed otherwise. (Installing with conda? `conda install -c conda-forge cmasher`.)
|
|
33
33
|
|
|
34
|
-
## From conda-forge
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
conda install -c conda-forge plotastro # or: mamba install -c conda-forge plotastro
|
|
38
|
-
conda install -c conda-forge plotastro cmasher # with CMasher
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
The conda-forge package needs Python 3.11 or newer (conda-forge's current
|
|
42
|
-
minimum); on older Pythons, install with pip instead.
|
|
43
|
-
|
|
44
34
|
## From a clone
|
|
45
35
|
|
|
46
36
|
```bash
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""Generate the reference figures embedded in README.md.
|
|
2
|
+
|
|
3
|
+
Run from the repository root: python examples/make_reference_figures.py
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import matplotlib
|
|
10
|
+
|
|
11
|
+
matplotlib.use("Agg")
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
13
|
+
import numpy as np
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
import plotastro as pa
|
|
17
|
+
except ImportError: # running from a source checkout without installing
|
|
18
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
19
|
+
import plotastro as pa
|
|
20
|
+
|
|
21
|
+
FIGDIR = Path(__file__).resolve().parent / "figures"
|
|
22
|
+
FIGDIR.mkdir(exist_ok=True)
|
|
23
|
+
rng = np.random.default_rng(42)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def save(fig, name):
|
|
27
|
+
fig.savefig(FIGDIR / f"{name}.png", dpi=300)
|
|
28
|
+
plt.close(fig)
|
|
29
|
+
print(f"wrote figures/{name}.png")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# ---------------------------------------------------------------- column plot
|
|
33
|
+
pa.set_style("mnras")
|
|
34
|
+
|
|
35
|
+
x = np.linspace(0.5, 10, 18)
|
|
36
|
+
truth = 2.0 * x ** -0.7
|
|
37
|
+
y = truth * rng.normal(1, 0.08, x.size)
|
|
38
|
+
yerr = 0.08 * truth
|
|
39
|
+
xf = np.linspace(0.4, 11, 200)
|
|
40
|
+
|
|
41
|
+
fig, ax = pa.subplots()
|
|
42
|
+
ax.errorbar(x, y, yerr=yerr, fmt="o", color=pa.COLORS["blue"],
|
|
43
|
+
label="mock data", zorder=3)
|
|
44
|
+
ax.plot(xf, 2.0 * xf ** -0.7, color=pa.COLORS["red"], label=r"$2\,x^{-0.7}$")
|
|
45
|
+
ax.fill_between(xf, 1.8 * xf ** -0.7, 2.2 * xf ** -0.7,
|
|
46
|
+
color=pa.lighten(pa.COLORS["red"], 0.75), zorder=0,
|
|
47
|
+
label=r"$1\sigma$ band")
|
|
48
|
+
ax.set_xscale("log")
|
|
49
|
+
ax.set_yscale("log")
|
|
50
|
+
ax.set_xlabel(r"$r\ \mathrm{[Mpc]}$")
|
|
51
|
+
ax.set_ylabel(r"$\xi(r)$")
|
|
52
|
+
ax.legend()
|
|
53
|
+
save(fig, "example_column")
|
|
54
|
+
|
|
55
|
+
# ------------------------------------------------------------ full-width plot
|
|
56
|
+
k = np.logspace(-3, 1, 300)
|
|
57
|
+
fig, axes = pa.subplots(1, 2, width="full", aspect=0.75)
|
|
58
|
+
for i, z in enumerate([0, 0.5, 1, 2]):
|
|
59
|
+
pk = 1e4 * k / (1 + (k / 0.02) ** 2.2) / (1 + z) ** 1.5
|
|
60
|
+
axes[0].loglog(k, pk, label=f"$z={z}$")
|
|
61
|
+
axes[1].semilogx(k, pk / (1e4 * k / (1 + (k / 0.02) ** 2.2)),
|
|
62
|
+
label=f"$z={z}$")
|
|
63
|
+
axes[0].set_xlabel(r"$k\ [h\,\mathrm{Mpc}^{-1}]$")
|
|
64
|
+
axes[0].set_ylabel(r"$P(k)\ [h^{-3}\,\mathrm{Mpc}^{3}]$")
|
|
65
|
+
axes[1].set_xlabel(r"$k\ [h\,\mathrm{Mpc}^{-1}]$")
|
|
66
|
+
axes[1].set_ylabel(r"$P(k)/P(k, z=0)$")
|
|
67
|
+
axes[0].legend()
|
|
68
|
+
pa.label_panels(axes)
|
|
69
|
+
save(fig, "example_full")
|
|
70
|
+
|
|
71
|
+
# ------------------------------------------------- palette / marker reference
|
|
72
|
+
save(pa.show_colors(), "palette")
|
|
73
|
+
save(pa.show_colors(pa.OKABE_ITO, title="Okabe & Ito (2008) — plotastro.OKABE_ITO"),
|
|
74
|
+
"palette_okabe_ito")
|
|
75
|
+
save(pa.show_markers(), "markers")
|
|
76
|
+
save(pa.show_linestyles(), "linestyles")
|
|
77
|
+
|
|
78
|
+
# ------------------------------------------------------- redundant encoding
|
|
79
|
+
x = np.linspace(0, 3, 60)
|
|
80
|
+
fig, ax = pa.subplots()
|
|
81
|
+
ax.set_prop_cycle(pa.style_cycler(markers=True, linestyles=True))
|
|
82
|
+
for n in range(4):
|
|
83
|
+
ax.plot(x, x ** (0.5 + 0.4 * n), markevery=7, label=f"model {n + 1}")
|
|
84
|
+
ax.set_xlabel("$x$")
|
|
85
|
+
ax.set_ylabel("$y$")
|
|
86
|
+
ax.legend()
|
|
87
|
+
save(fig, "redundant_encoding")
|
|
88
|
+
|
|
89
|
+
# --------------------------------------------------------------- CVD check
|
|
90
|
+
save(pa.check_colors(), "cvd_check")
|
|
91
|
+
|
|
92
|
+
# ------------------------------------------- CMasher colours (optional extra)
|
|
93
|
+
try:
|
|
94
|
+
import cmasher # noqa: F401 (only to check it is installed)
|
|
95
|
+
except ImportError:
|
|
96
|
+
print("cmasher not installed: skipping figures/cmasher.png")
|
|
97
|
+
else:
|
|
98
|
+
pa.set_style("mnras", palette="cmr.rainforest", cmap="cmr.ocean")
|
|
99
|
+
fig, axes = pa.subplots(1, 2, width="full", aspect=0.75)
|
|
100
|
+
x = np.linspace(0, 1, 200)
|
|
101
|
+
for n in range(8): # the 8-colour CMasher cycle
|
|
102
|
+
axes[0].plot(x, x ** (0.4 + 0.3 * n), label=f"$n={n + 1}$")
|
|
103
|
+
axes[0].set_xlabel("$x$")
|
|
104
|
+
axes[0].set_ylabel("$x^{\\alpha_n}$")
|
|
105
|
+
axes[0].set_title("palette='cmr.rainforest'", family="monospace", fontsize=8)
|
|
106
|
+
axes[0].legend(ncol=2, fontsize=6)
|
|
107
|
+
yy, xx = np.mgrid[-3:3:200j, -3:3:200j]
|
|
108
|
+
field = (np.exp(-((xx - 0.8) ** 2 + yy ** 2)) + 0.6 * np.exp(
|
|
109
|
+
-((xx + 1.2) ** 2 + (yy - 1) ** 2) / 0.5))
|
|
110
|
+
im = axes[1].imshow(field, origin="lower", extent=(-3, 3, -3, 3))
|
|
111
|
+
axes[1].grid(False)
|
|
112
|
+
axes[1].set_xlabel("$x$")
|
|
113
|
+
axes[1].set_ylabel("$y$")
|
|
114
|
+
axes[1].set_title("cmap='cmr.ocean'", family="monospace", fontsize=8)
|
|
115
|
+
fig.colorbar(im, ax=axes[1], label="density")
|
|
116
|
+
pa.label_panels(axes, loc="lower right")[1].set_color("white")
|
|
117
|
+
save(fig, "cmasher")
|