Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a (skippable) check that the axes have equal aspect ratio. #61

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,16 @@ Default: `False`
### rotation

Whether to create a scale bar based on the x-axis (default) or y-axis.
*rotation* can either be `horizontal` or `vertical`.
*rotation* can either be `horizontal`, `vertical`, `horizontal-only`, or
`vertical-only`.

By default, matplotlib_scalebar checks whether the axes have equal aspect ratio
(so that the scale bar applies both for the x and the y directions), and emits
a warning if this is not the case. This warning can be suppressed by setting
*rotation* to `horizontal-only` ("the colorbar only applies to the horizontal
direction") or `vertical-only` ("the colorbar only applies to the vertical
direction").

Note you might have to adjust *scale_loc* and *label_loc* to achieve desired layout.
Default: `None`, value from matplotlibrc or `horizontal`.

Expand Down
17 changes: 14 additions & 3 deletions matplotlib_scalebar/scalebar.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"label_loc", _VALID_LABEL_LOCATIONS, ignorecase=True
)

_VALID_ROTATIONS = ["horizontal", "vertical"]
_VALID_ROTATIONS = ["horizontal", "horizontal-only", "vertical", "vertical-only"]
_validate_rotation = ValidateInStrings("rotation", _VALID_ROTATIONS, ignorecase=True)


Expand Down Expand Up @@ -298,8 +298,11 @@ def __init__(
:arg animated: animation state (default: ``False``)
:type animated: :class`bool`

:arg rotation: either ``horizontal`` or ``vertical``
(default: rcParams['scalebar.rotation'] or ``horizontal``)
:arg rotation: ``horizontal``, ``vertical``, ``horizontal-only``, or ``vertical-only``
(default: rcParams['scalebar.rotation'] or ``horizontal``).
By default, ScaleBar checks that it is getting drawn on an axes
with equal aspect ratio and emits a warning if this is not the case.
The -only variants suppress that check.
:type rotation: :class:`str`

:arg bbox_to_anchor: box that is used to position the scalebar
Expand Down Expand Up @@ -426,6 +429,14 @@ def _get_value(attr, default):
fixed_value = self.fixed_value
fixed_units = self.fixed_units or self.units
rotation = _get_value("rotation", "horizontal").lower()
if rotation.endswith("-only"):
rotation = rotation[:-5]
else: # Check aspect ratio.
if self.axes.get_aspect() != 1:
warnings.warn(
f"Drawing scalebar on axes with unequal aspect ratio; "
f"either call ax.set_aspect(1) or suppress the warning with "
f"rotation='{rotation}-only'.")
label = self.label

# Create text properties
Expand Down
34 changes: 32 additions & 2 deletions matplotlib_scalebar/test_scalebar.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

# Standard library modules.

import warnings

# Third party modules.
import matplotlib

Expand Down Expand Up @@ -33,7 +35,7 @@ def scalebar():

yield scalebar

plt.draw()
plt.close(fig)


def test_mpl_rcParams_update():
Expand Down Expand Up @@ -298,7 +300,8 @@ def test_label_formatter(scalebar):
assert scalebar.label_formatter(value, units) == "m 5"


@pytest.mark.parametrize("rotation", ["horizontal", "vertical"])
@pytest.mark.parametrize("rotation", [
"horizontal", "vertical", "horizontal-only", "vertical-only"])
def test_rotation(scalebar, rotation):
assert scalebar.get_rotation() is None
assert scalebar.rotation is None
Expand All @@ -311,6 +314,33 @@ def test_rotation(scalebar, rotation):
scalebar.set_rotation("h")


def test_rotation_checks_aspect():
fig, ax = plt.subplots()
sb = ScaleBar(0.5)
ax.add_artist(sb)

with warnings.catch_warnings():
warnings.simplefilter("error")

for aspect in ["auto", 2]:
ax.set_aspect(aspect) # Warns if not using the -only variants.
for rotation in ["horizontal", "vertical"]:
sb.rotation = rotation
with pytest.warns():
fig.canvas.draw()
sb.rotation = rotation + "-only"
fig.canvas.draw()

ax.set_aspect("equal") # Never warn.
for rotation in ["horizontal", "vertical"]:
sb.rotation = rotation
fig.canvas.draw()
sb.rotation = rotation + "-only"
fig.canvas.draw()

plt.close(fig)


def test_bbox_to_anchor(scalebar):
assert scalebar.get_bbox_to_anchor() is None
assert scalebar.bbox_to_anchor is None
Expand Down
Loading