Skip to content
This repository has been archived by the owner on Nov 30, 2022. It is now read-only.

Comparison #43

Merged
merged 13 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 21 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,62 +17,42 @@
This package creates clean and beautiful plots that work on light and dark backgrounds.
Inspired by the work of [Edward Tufte](https://en.wikipedia.org/wiki/Edward_Tufte).

<img src="https://nschloe.github.io/dufte/ex1.svg"> | <img src="https://nschloe.github.io/dufte/bar.svg">
:----:|:----:|

To use, simply select the `dufte` style. Check out `dufte.legend()` and
`dufte.ylabel()` for more duftness.
To use, simply select the `dufte` style:
```python
import matplotlib.pyplot as plt
import dufte
import numpy as np
import matplotlib.pyplot as plt

# global setting:
plt.style.use(dufte.style)

rng = np.random.default_rng(0)

x0 = np.linspace(0.0, 3.0, 100)
y0 = x0 / (x0 + 1)
y0 += 0.1 * rng.random(len(y0))
plt.plot(x0, y0, label="no balacing")
# with a context manager:
with plt.style.context(dufte.style_bar):
# ...
pass
```

x1 = np.linspace(0.0, 3.0, 100)
y1 = 1.5 * x1 / (x1 + 1)
y1 += 0.1 * rng.random(len(y1))
plt.plot(x1, y1, label="CRV-27")
Check out `dufte.legend()`, `dufte.ylabel()`, and `dufte.show_bar_values()` for more
duftiness.

x2 = np.linspace(0.0, 3.0, 100)
y2 = 1.6 * x2 / (x2 + 1)
y2 += 0.1 * rng.random(len(y2))
plt.plot(x2, y2, label="CRV-27*")
#### Comparison with default Matplotlib

dufte.ylabel("ylabel")
dufte.legend()
See [here](tests/create_comparison.py) for how to create the below plots.

plt.show()
```
The bar plot is created with `dufte.style_bar` here and `dufte.show_bar_values()`.
Note the use of `context` instead of `style.use()`; both are appropriate.
```python
import matplotlib.pyplot as plt
import dufte
<a href="tests/create_comparison.py"><img src="https://nschloe.github.io/dufte/ex1-mpl.svg"/></a> | <a href="tests/create_comparison.py"><img src="https://nschloe.github.io/dufte/ex1-dufte.svg"/></a>
:----:|:----:|
matplotlib | dufte with `dufte.legend()` |

<a href="tests/create_comparison.py"><img src="https://nschloe.github.io/dufte/bars-mpl.svg"/></a> | <a href="tests/create_comparison.py"><img src="https://nschloe.github.io/dufte/bars-dufte1.svg"/></a> | <a href="tests/create_comparison.py"><img src="https://nschloe.github.io/dufte/bars-dufte2.svg"/></a>
:----:|:----:|:----:|
matplotlib | dufte | dufte with `dufte.show_bar_values()` |

with plt.style.context(dufte.style_bar):
labels = ["Australia", "Brazil", "China", "Germany", "Mexico", "United\nStates"]
vals = [21.65, 24.5, 6.95, 8.40, 21.00, 8.55]
xpos = range(len(vals))
plt.bar(xpos, vals)
plt.xticks(xpos, labels)
dufte.show_bar_values("{:.2f}")
plt.title("average temperature [°C]")
plt.show()
```

Further reading:

* [Remove to improve: data-ink ratio](https://www.darkhorseanalytics.com/blog/data-looks-better-naked)
<img src="https://nschloe.github.io/dufte/data-ink.webp">

<img src="https://nschloe.github.io/dufte/data-ink.webp" width="50%"/>

* [Remove to improve: Line Graph Edition](https://youtu.be/bDbJBWvonVI)
* [Show the Data - Maximize the Data Ink Ratio](https://youtu.be/pCp0a5_YIWE)
* [Randal S. Olson's blog entry](http://www.randalolson.com/2014/06/28/how-to-make-beautiful-data-visualizations-in-python-with-matplotlib/)
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = dufte
version = 0.2.24
version = 0.2.25
author = Nico Schlömer
author_email = nico.schloemer@gmail.com
description = Clean matplotlib plots
Expand Down
6 changes: 6 additions & 0 deletions src/dufte/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@
# unhide the bar labels
style_bar["xtick.major.pad"] = 13
style_bar["font.size"] = 16
# default:
style_bar["axes.xmargin"] = mpl.rcParams["axes.xmargin"]
# style_bar["ytick.major.size"] = 10


def _move_min_distance(targets, min_distance):
Expand Down Expand Up @@ -244,6 +247,9 @@ def show_bar_values(fmt="{}"):
plt.tick_params(axis="y", which="both", left=False, right=False, labelleft=False)
plt.grid(False)

# remove margins
plt.margins(x=0)

data_to_axis = ax.transData + ax.transAxes.inverted()
axis_to_data = ax.transAxes + ax.transData.inverted()

Expand Down
66 changes: 66 additions & 0 deletions tests/create_comparison.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import matplotlib.pyplot as plt
import numpy as np

import dufte


def line():
rng = np.random.default_rng(0)

offsets = [1.0, 1.50, 1.60]
labels = ["no balancing", "CRV-27", "CRV-27*"]
x0 = np.linspace(0.0, 3.0, 100)
y = [offset * x0 / (x0 + 1) + 0.1 * rng.random(len(x0)) for offset in offsets]

# default mpl
with plt.style.context("default"):
for yy, label in zip(y, labels):
plt.plot(x0, yy, label=label)
plt.xlabel("distance [m]")
plt.ylabel("voltage [V]")
plt.legend()
plt.savefig("ex1-mpl.svg", transparent=True, bbox_inches="tight")
plt.close()

# dufte
with plt.style.context(dufte.style):
for yy, label in zip(y, labels):
plt.plot(x0, yy, label=label)
plt.xlabel("distance [m]")
dufte.ylabel("voltage [V]")
dufte.legend()
plt.savefig("ex1-dufte.svg", transparent=True, bbox_inches="tight")
plt.close()


def bars():
labels = ["Australia", "Brazil", "China", "Germany", "Mexico", "United\nStates"]
vals = [21.65, 24.5, 6.95, 8.40, 21.00, 8.55]
xpos = range(len(vals))

with plt.style.context("default"):
plt.bar(xpos, vals)
plt.xticks(xpos, labels)
plt.title("average temperature [°C]")
plt.savefig("bars-mpl.svg", transparent=True, bbox_inches="tight")
plt.close()

with plt.style.context(dufte.style_bar):
plt.bar(xpos, vals)
plt.xticks(xpos, labels)
plt.title("average temperature [°C]")
plt.savefig("bars-dufte1.svg", transparent=True, bbox_inches="tight")
plt.close()

with plt.style.context(dufte.style_bar):
plt.bar(xpos, vals)
plt.xticks(xpos, labels)
dufte.show_bar_values("{:.2f}")
plt.title("average temperature [°C]")
plt.savefig("bars-dufte2.svg", transparent=True, bbox_inches="tight")
plt.close()


if __name__ == "__main__":
line()
bars()
24 changes: 6 additions & 18 deletions tests/test_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,18 @@
import dufte


def test_bar(filename=None, light=True):
def test_bar():
with plt.style.context(dufte.style_bar):
labels = ["Australia", "Brazil", "China", "Germany", "Mexico", "United\nStates"]
vals = [21.65, 24.5, 6.95, 8.40, 21.00, 8.55]
labels = ["label 1", "label 2"]
vals = [2.1, 6.3]
xpos = range(len(vals))
plt.bar(xpos, vals)
plt.xticks(xpos, labels)
dufte.show_bar_values("{:.2f}")
plt.title("average temperature [°C]")

if not light:
gh_dark_bg = "#0d1117"
plt.gca().set_facecolor(gh_dark_bg)
plt.gcf().patch.set_facecolor(gh_dark_bg)

if filename:
plt.savefig(filename, transparent=True, bbox_inches="tight")
else:
plt.show()
plt.title("some title")


if __name__ == "__main__":
# test_bar("bar-light.svg", True)
# plt.close()
# test_bar("bar-dark.svg", False)
test_bar("bar.svg", False)
test_bar()
plt.show()
plt.close()
44 changes: 13 additions & 31 deletions tests/test_plot.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,25 @@
import matplotlib.pyplot as plt
import numpy as np
import pytest

import dufte


@pytest.mark.parametrize(
"filename, light, noise, offsets",
[[None, True, 0.1, (1.0, 1.50, 1.60)], [None, True, 0.0, (1.0, 1.50, 1.51)]],
)
def test_plot(filename, light: bool, noise, offsets):
plt.style.use(dufte.style)

rng = np.random.default_rng(0)
def test_plot():
offsets = [1.0, 1.50, 1.60]
offsets = [1.0, 1.50, 1.51]

x0 = np.linspace(0.0, 3.0, 100)
labels = ["no balancing", "CRV-27", "CRV-27*"]
for label, offset in zip(labels, offsets):
y0 = offset * x0 / (x0 + 1)
y0 += noise * rng.random(len(y0))
plt.plot(x0, y0, label=label)

plt.xlabel("distance [m]")
dufte.ylabel("voltage [V]")
# plt.title("title")
dufte.legend()

if not light:
gh_dark_bg = "#0d1117"
plt.gca().set_facecolor(gh_dark_bg)
plt.gcf().patch.set_facecolor(gh_dark_bg)
with plt.style.context(dufte.style):
for label, offset in zip(labels, offsets):
y0 = offset * x0 / (x0 + 1)
plt.plot(x0, y0, label=label)

if filename:
plt.savefig(filename, transparent=True, bbox_inches="tight")
else:
plt.show()
plt.xlabel("distance [m]")
dufte.ylabel("voltage [V]")
# plt.title("title")
dufte.legend()


def test_no_labels():
Expand Down Expand Up @@ -81,9 +66,6 @@ def test_all_nan():


if __name__ == "__main__":
# test_plot(None, True, 0.1, (1.0, 1.5, 1.6))
# test_plot("ex1-light.svg", True, 0.1, (1.0, 1.5, 1.6))
# plt.close()
# test_plot("ex1-dark.svg", False, 0.1, (1.0, 1.5, 1.6))
test_plot("ex1.svg", False, 0.1, (1.0, 1.5, 1.6))
test_plot()
plt.show()
plt.close()