Skip to content

Commit

Permalink
feat: added matplotlib support (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
miloth authored Jun 18, 2024
1 parent 12fcd21 commit 580dabc
Show file tree
Hide file tree
Showing 46 changed files with 1,188 additions and 81 deletions.
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,60 @@ and ensuring `catppuccin[pygments]` is installed in the same environment will
give you Catppuccin Mocha syntax highlighting in the REPL. See [here](https://github.com/backwardspy/dots/blob/f6991570d6691212e27e266517656192f910ccbf/dot_config/ipython/profile_default/ipython_config.py)
for an example of a more complete configuration.

## Matplotlib

The library tries to register styles and colormaps if `matplotlib` is installed.
See the examples below for some use cases:

1. Load a style, using `mpl.style.use`
```python
import catppuccin
import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.style.use(catppuccin.PALETTE.mocha.identifier)
plt.plot([0,1,2,3], [1,2,3,4])
plt.show()
```
1. Mix it with different stylesheets!
```python
import catppuccin
import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.style.use(["ggplot", catppuccin.PALETTE.mocha.identifier])
plt.plot([0,1,2,3], [1,2,3,4])
plt.show()
```
1. Load individual colors
```python
import matplotlib.pyplot as plt
import catppuccin
from catppuccin.extras.matplotlib import load_color

color = load_color(catppuccin.PALETTE.latte.identifier, "peach")
plt.plot([0,1,2,3], [1,2,3,4], color=color)
plt.show()
```
1. Define custom colormaps
```python
import matplotlib.pyplot as plt
import numpy as np
import catppuccin
from catppuccin.extras.matplotlib import get_colormap_from_list

cmap = get_colormap_from_list(
catppuccin.PALETTE.frappe.identifier,
["red", "peach", "yellow", "green"],
)
rng = np.random.default_rng()
data = rng.integers(2, size=(30, 30))

plt.imshow(data, cmap=cmap)
plt.show()
```


## Contribution

If you are looking to contribute, please read through our
Expand Down
Binary file added assets/frappe/bar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/frappe/boxplot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/frappe/imshow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/frappe/palette.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/frappe/patches.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/frappe/plot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/frappe/scatter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/latte/bar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/latte/boxplot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/latte/imshow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/latte/palette.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/latte/patches.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/latte/plot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/latte/scatter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/macchiato/bar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/macchiato/boxplot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/macchiato/imshow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/macchiato/palette.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/macchiato/patches.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/macchiato/plot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/macchiato/scatter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/mocha/bar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/mocha/boxplot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/mocha/imshow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/mocha/palette.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/mocha/patches.png
Binary file added assets/mocha/plot.png
Binary file added assets/mocha/scatter.png
56 changes: 55 additions & 1 deletion build.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
"""Code generation script for creating the global palette constant."""

from __future__ import annotations

import json
import subprocess
from dataclasses import asdict
from pathlib import Path
from typing import Any, cast

from catppuccin.models import HSL, RGB, Color, Flavor, FlavorColors, Palette
from example_plots import example_plots, plot_palette

HEADER = '''"""Catppuccin palette definition."""
from catppuccin.models import HSL, RGB, Color, Flavor, FlavorColors, Palette'''

DPI = 200


def load_palette_json() -> dict[str, Any]:
"""Load palette data from `./palette.json`."""
Expand Down Expand Up @@ -65,6 +71,54 @@ def codegen() -> str:


if __name__ == "__main__":
with Path("catppuccin/palette.py").open("w") as f:
# Generate the palette.py file

palette_path = Path.cwd() / "catppuccin" / "palette.py"
with palette_path.open("w") as f:
source = codegen()
print(source, file=f)
# Run `ruff format` on the generated file
ruff_format = f"ruff format {palette_path}"
subprocess.run(ruff_format.split(), check=True) # noqa: S603

# Generate the matplotlib styles

from catppuccin.extras.matplotlib import CATPPUCCIN_STYLE_DIRECTORY
from catppuccin.palette import PALETTE

template_text = (
CATPPUCCIN_STYLE_DIRECTORY / "_catppuccin_template.txt"
).read_text()

for key, palette in asdict(PALETTE).items():
text = template_text
text = text.replace("<palette>", key)
for color in palette["colors"]:
text = text.replace(
f"<{color}>",
palette["colors"][color]["hex"].replace("#", ""),
)
with (CATPPUCCIN_STYLE_DIRECTORY / f"{key}.mplstyle").open("w") as f:
f.write(text)

# Generate matplotlib assets for the docs
import matplotlib as mpl
import matplotlib.pyplot as plt

import catppuccin # This loads the styles in matplotlib # noqa: F401

for palette_name in asdict(PALETTE):
mpl.style.use(palette_name)

palette_path = Path.cwd() / "assets" / palette_name
palette_path.mkdir(exist_ok=True, parents=True)

# Plot palette separately
fig = plot_palette(palette_name)
fig.savefig(palette_path / "palette.png", dpi=DPI)

# Plot examples
for filename, plot_function in example_plots.items():
fig = plot_function()
fig.savefig(palette_path / f"{filename}.png", dpi=DPI)
plt.close()
10 changes: 10 additions & 0 deletions catppuccin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
"""🐍 Soothing pastel theme for Python."""

import importlib.util

from catppuccin.palette import PALETTE

__all__ = ["PALETTE"]

# Attempt to register styles and colormaps if matplotlib is available
if importlib.util.find_spec("matplotlib") is not None:
from catppuccin.extras.matplotlib import _register_colormap_list, _register_styles

_register_styles()
_register_colormap_list()
53 changes: 53 additions & 0 deletions catppuccin/extras/matplotlib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""Soothing pastel theme for `matplotlib`.
The following code was ported from [catppuccin/matplotlib](https://github.com/catppuccin/matplotlib).
Thanks to [Bram de Wilde](https://github.com/brambozz) for the original source code and
for allowing this port.
"""

from __future__ import annotations

from dataclasses import asdict
from pathlib import Path
from typing import Iterable, cast

import matplotlib as mpl
import matplotlib.colors
import matplotlib.style

from catppuccin.palette import PALETTE

CATPPUCCIN_STYLE_DIRECTORY = Path(__file__).parent / "matplotlib_styles"
DEFAULT_COLORMAP_COLORS = ("base", "blue")


def _register_styles() -> None:
"""Register the included stylesheets in the mpl style library."""
catppuccin_stylesheets = mpl.style.core.read_style_directory( # type: ignore [attr-defined]
CATPPUCCIN_STYLE_DIRECTORY
)
mpl.style.core.update_nested_dict(mpl.style.library, catppuccin_stylesheets) # type: ignore [attr-defined]


def _register_colormap_list() -> None:
"""Register the included color maps in the `matplotlib` colormap library."""
for palette_name in asdict(PALETTE):
cmap = get_colormap_from_list(palette_name, DEFAULT_COLORMAP_COLORS)
mpl.colormaps.register(cmap=cmap, name=palette_name)


def get_colormap_from_list(
palette_name: str,
color_names: Iterable[str],
) -> matplotlib.colors.LinearSegmentedColormap:
"""Get a `matplotlib` colormap from a list of colors for a specific palette."""
colors = [load_color(palette_name, color_name) for color_name in color_names]
return matplotlib.colors.LinearSegmentedColormap.from_list(palette_name, colors)


def load_color(palette_name: str, color_name: str) -> str:
"""Load the color for a given palette and color name."""
return cast(
str,
PALETTE.__getattribute__(palette_name).colors.__getattribute__(color_name).hex,
)
43 changes: 43 additions & 0 deletions catppuccin/extras/matplotlib_styles/_catppuccin_template.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Note: this explicitly only alters colors and should be combined with
# other stylesheets if you want to edit other aspects, like linewidth,
# margins, etc.

# Original matplotlib cycle is blue, orange, green, red, purple, brown, pink, grey, light green, light blue
# Main colors: blue, peach, green, red, mauve, maroon, pink, rosewater, teal, lavender
axes.prop_cycle: cycler('color', ['<blue>', '<peach>', '<green>', '<red>', '<mauve>', '<maroon>', '<pink>', '<rosewater>', '<teal>', '<lavender>'])

image.cmap: <palette>

# Font color: Text
text.color: <text>
axes.labelcolor: <text>
xtick.labelcolor: <text>
ytick.labelcolor: <text>

# Background color: Base
figure.facecolor: <base>
axes.facecolor: <base>
savefig.facecolor: <base>

# Edge color: Surface 0
axes.edgecolor: <surface0>
legend.edgecolor: <surface0>
xtick.color: <surface0>
ytick.color: <surface0>
patch.edgecolor: <surface0>
hatch.color: <surface0>

# Grid color: Surface 0
grid.color: <surface0>

# Boxplots: Overlay 0
boxplot.flierprops.color: <overlay0>
boxplot.flierprops.markerfacecolor: <overlay0>
boxplot.flierprops.markeredgecolor: <overlay0>
boxplot.boxprops.color: <overlay0>
boxplot.whiskerprops.color: <overlay0>
boxplot.capprops.color: <overlay0>
boxplot.medianprops.color: <overlay0>
boxplot.meanprops.color: <overlay0>
boxplot.meanprops.markerfacecolor: <overlay0>
boxplot.meanprops.markeredgecolor: <overlay0>
43 changes: 43 additions & 0 deletions catppuccin/extras/matplotlib_styles/frappe.mplstyle
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Note: this explicitly only alters colors and should be combined with
# other stylesheets if you want to edit other aspects, like linewidth,
# margins, etc.

# Original matplotlib cycle is blue, orange, green, red, purple, brown, pink, grey, light green, light blue
# Main colors: blue, peach, green, red, mauve, maroon, pink, rosewater, teal, lavender
axes.prop_cycle: cycler('color', ['8caaee', 'ef9f76', 'a6d189', 'e78284', 'ca9ee6', 'ea999c', 'f4b8e4', 'f2d5cf', '81c8be', 'babbf1'])

image.cmap: frappe

# Font color: Text
text.color: c6d0f5
axes.labelcolor: c6d0f5
xtick.labelcolor: c6d0f5
ytick.labelcolor: c6d0f5

# Background color: Base
figure.facecolor: 303446
axes.facecolor: 303446
savefig.facecolor: 303446

# Edge color: Surface 0
axes.edgecolor: 414559
legend.edgecolor: 414559
xtick.color: 414559
ytick.color: 414559
patch.edgecolor: 414559
hatch.color: 414559

# Grid color: Surface 0
grid.color: 414559

# Boxplots: Overlay 0
boxplot.flierprops.color: 737994
boxplot.flierprops.markerfacecolor: 737994
boxplot.flierprops.markeredgecolor: 737994
boxplot.boxprops.color: 737994
boxplot.whiskerprops.color: 737994
boxplot.capprops.color: 737994
boxplot.medianprops.color: 737994
boxplot.meanprops.color: 737994
boxplot.meanprops.markerfacecolor: 737994
boxplot.meanprops.markeredgecolor: 737994
43 changes: 43 additions & 0 deletions catppuccin/extras/matplotlib_styles/latte.mplstyle
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Note: this explicitly only alters colors and should be combined with
# other stylesheets if you want to edit other aspects, like linewidth,
# margins, etc.

# Original matplotlib cycle is blue, orange, green, red, purple, brown, pink, grey, light green, light blue
# Main colors: blue, peach, green, red, mauve, maroon, pink, rosewater, teal, lavender
axes.prop_cycle: cycler('color', ['1e66f5', 'fe640b', '40a02b', 'd20f39', '8839ef', 'e64553', 'ea76cb', 'dc8a78', '179299', '7287fd'])

image.cmap: latte

# Font color: Text
text.color: 4c4f69
axes.labelcolor: 4c4f69
xtick.labelcolor: 4c4f69
ytick.labelcolor: 4c4f69

# Background color: Base
figure.facecolor: eff1f5
axes.facecolor: eff1f5
savefig.facecolor: eff1f5

# Edge color: Surface 0
axes.edgecolor: ccd0da
legend.edgecolor: ccd0da
xtick.color: ccd0da
ytick.color: ccd0da
patch.edgecolor: ccd0da
hatch.color: ccd0da

# Grid color: Surface 0
grid.color: ccd0da

# Boxplots: Overlay 0
boxplot.flierprops.color: 9ca0b0
boxplot.flierprops.markerfacecolor: 9ca0b0
boxplot.flierprops.markeredgecolor: 9ca0b0
boxplot.boxprops.color: 9ca0b0
boxplot.whiskerprops.color: 9ca0b0
boxplot.capprops.color: 9ca0b0
boxplot.medianprops.color: 9ca0b0
boxplot.meanprops.color: 9ca0b0
boxplot.meanprops.markerfacecolor: 9ca0b0
boxplot.meanprops.markeredgecolor: 9ca0b0
43 changes: 43 additions & 0 deletions catppuccin/extras/matplotlib_styles/macchiato.mplstyle
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Note: this explicitly only alters colors and should be combined with
# other stylesheets if you want to edit other aspects, like linewidth,
# margins, etc.

# Original matplotlib cycle is blue, orange, green, red, purple, brown, pink, grey, light green, light blue
# Main colors: blue, peach, green, red, mauve, maroon, pink, rosewater, teal, lavender
axes.prop_cycle: cycler('color', ['8aadf4', 'f5a97f', 'a6da95', 'ed8796', 'c6a0f6', 'ee99a0', 'f5bde6', 'f4dbd6', '8bd5ca', 'b7bdf8'])

image.cmap: macchiato

# Font color: Text
text.color: cad3f5
axes.labelcolor: cad3f5
xtick.labelcolor: cad3f5
ytick.labelcolor: cad3f5

# Background color: Base
figure.facecolor: 24273a
axes.facecolor: 24273a
savefig.facecolor: 24273a

# Edge color: Surface 0
axes.edgecolor: 363a4f
legend.edgecolor: 363a4f
xtick.color: 363a4f
ytick.color: 363a4f
patch.edgecolor: 363a4f
hatch.color: 363a4f

# Grid color: Surface 0
grid.color: 363a4f

# Boxplots: Overlay 0
boxplot.flierprops.color: 6e738d
boxplot.flierprops.markerfacecolor: 6e738d
boxplot.flierprops.markeredgecolor: 6e738d
boxplot.boxprops.color: 6e738d
boxplot.whiskerprops.color: 6e738d
boxplot.capprops.color: 6e738d
boxplot.medianprops.color: 6e738d
boxplot.meanprops.color: 6e738d
boxplot.meanprops.markerfacecolor: 6e738d
boxplot.meanprops.markeredgecolor: 6e738d
Loading

0 comments on commit 580dabc

Please sign in to comment.