Metadata-Version: 2.4
Name: cmglaciology
Version: 0.2.0
Summary: Colormaps for glaciology
Author-email: Andy Aschwanden <aaschwanden@alaska.edu>
License-Expression: MIT
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: matplotlib>=3.6
Requires-Dist: numpy
Provides-Extra: cvd
Requires-Dist: colorspacious; extra == "cvd"
Provides-Extra: test
Requires-Dist: colorspacious; extra == "test"
Requires-Dist: pytest; extra == "test"
Dynamic: license-file

# cmglaciology

Colormaps for glaciology, packaged for Matplotlib.

![colormaps](https://raw.githubusercontent.com/pism/cmglaciology/main/cmglaciology/colormaps.png)

| Name           | Type        | Intended use                                |
| -------------- | ----------- | ------------------------------------------- |
| `speed`        | Sequential  | Ice surface speed                           |
| `akbathtopo`   | Topographic | Bathymetry and surface elevation, Alaska    |
| `aktopo`       | Topographic | Surface elevation (land only), Alaska       |
| `grisbathtopo` | Topographic | Bathymetry and surface elevation, Greenland |
| `gristopo`     | Topographic | Surface elevation (land only), Greenland    |

Contributions are welcome. Do you have a favorite colormap for ice thickness? Please let us know.

## Install

```sh
python -m pip install cmglaciology
```

For the development version:

```sh
python -m pip install git+https://github.com/pism/cmglaciology.git
```

or, from a clone:

```sh
python -m pip install -e .
```

## Usage example

```python
import cmglaciology.cm as cmg
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 1, 100)[np.newaxis, :]

plt.imshow(x, aspect='auto', cmap=cmg.speed)
plt.axis('off')
plt.show()
```

For a reversed colormap, append `_r` to the colormap name:

```python
plt.imshow(x, aspect='auto', cmap=cmg.speed_r)
```

For a discretized colormap, use the
[`.resampled`](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib.colors.ListedColormap.resampled)
method on any of the colormaps:

```python
plt.imshow(x, aspect='auto', cmap=cmg.speed.resampled(25))
```

Alternatively, the registered name string can be used. Names are prefixed
with `cmg.`:

```python
import cmglaciology  # required in order to register the colormaps with Matplotlib
...
plt.imshow(x, aspect='auto', cmap='cmg.speed')
plt.imshow(x, aspect='auto', cmap='cmg.speed_r')
```

For an image of all the available colormaps:

```python
from cmglaciology import show_cmaps

show_cmaps()
```

To also see how the colormaps look with a color vision deficiency, pass
`cvd=True`. This needs the
[colorspacious](https://colorspacious.readthedocs.io/) package, which the
`cvd` extra installs:

```sh
python -m pip install "cmglaciology[cvd]"
```

```python
show_cmaps(cvd=True)
```

`simulate_cvd` returns a single colormap as it is seen with a deficiency, to
use in a plot of your own:

```python
from cmglaciology import simulate_cvd

plt.imshow(x, aspect='auto', cmap=simulate_cvd(cmg.speed, "deuteranomaly"))
```

See [the figure at the bottom](#color-vision-deficiency).

## Notes on the colormaps

The colormaps were designed in QGIS against data values, so their color stops
are not evenly spaced. The stops are (data value → position in the colormap
is linear between the first and last value):

- `speed`: 10, 30, 100, 250, 750 (m/yr)
- `akbathtopo`: -2000, 0, 1, 1250, 2000, 2500, 3000, 3500 (m)
- `aktopo`: 0, 1, 1250, 2000, 2500, 3000, 3500 (m)
- `grisbathtopo`: -500, 0, 1, 1500, 2000 (m)
- `gristopo`: 0, 1, 1500, 2000 (m)

To reproduce the QGIS rendering, use `vmin`/`vmax` equal to the first and last
stop. The topographic maps have a sharp break at sea level (0–1 m).

## Adding a colormap

1. Export the color ramp from QGIS (*Layer Properties → Symbology → Save color
   map to file*) and put the file in `qgis/`.
2. Run `python scripts/qgis2txt.py` to regenerate the 256-level RGB tables in
   `cmglaciology/cmaps/`.
3. Add the name to one of the groups at the top of `cmglaciology/cm.py`.
4. Run `python cm.py` from the `cmglaciology/` directory to
   refresh `colormaps.png`, `python scripts/show_cvd.py` to refresh
   `colormaps_cvd.png`, and `pytest` to check everything.

## Releasing

Development happens on `main`; releases are cut from the `release` branch by
the [ASFHyP3 actions](https://github.com/ASFHyP3/actions) workflows in
`.github/workflows/`, as in [pism-terra](https://github.com/pism/pism-terra):

1. Every pull request to `main` adds an entry to [CHANGELOG.md](CHANGELOG.md)
   under a heading with the next version number, e.g. `## [0.2.0]` (or carries
   the `bumpless` label if it changes nothing a user would notice).
2. To release, open a pull request from `main` to `release` and give it one of
   the labels `major`, `minor`, `patch` or `bumpless`.
3. Merging it tags the new version (`v0.2.0`), which creates a GitHub release
   with the matching changelog section as its notes, brings `release` back
   into `main`, and publishes the package to [PyPI](https://pypi.org/project/cmglaciology/).

The version number of an installed package comes from the git tags, through
`setuptools_scm`.

## Acknowledgements

The structure of this package — one text file of RGB values per colormap,
loaded and registered with Matplotlib on import, with reversed `_r` versions
and a `show_cmaps()` overview — is taken from
[cmcrameri](https://github.com/callumrollo/cmcrameri) by Callum Rollo and
contributors, which packages Fabio Crameri's
[Scientific colour maps](https://www.fabiocrameri.ch/colourmaps/).
`cmglaciology/cm.py` and the tests are adapted from cmcrameri's code, which is
distributed under the MIT License, Copyright (c) 2020 Callum Rollo. Many
thanks to Callum and the cmcrameri contributors for making this so easy to
reuse. Any errors in this adaptation are our own.

No colormap data from cmcrameri or the Scientific colour maps is included
here. If you need perceptually uniform colormaps, use
[cmcrameri](https://github.com/callumrollo/cmcrameri) directly.

## License

MIT, see [LICENSE.txt](LICENSE.txt).

## Color vision deficiency

The colormaps as they are seen with normal vision and with protanopia,
deuteranopia and tritanopia, in which the red, green or blue cones do not
work:

![colormaps with color vision deficiencies](https://raw.githubusercontent.com/pism/cmglaciology/main/cmglaciology/colormaps_cvd.png)

The figure is made with `show_cmaps(cvd=True)`, by `python scripts/show_cvd.py`.
The simulation follows Machado et al. (2009), as implemented in
[colorspacious](https://colorspacious.readthedocs.io/). With protanopia and
deuteranopia, the orange-to-magenta upper part of `speed` turns into a single
olive ramp, so high speeds are harder to tell apart.

Example of Kennicott Glacier, Alaska, using `aktopo` and `speed` colormaps, rendered with [pyvista](https://docs.pyvista.org/):

![Kennicott Glacier, Alaska](https://raw.githubusercontent.com/pism/cmglaciology/main/cmglaciology/example.jpg)
