Skip to content
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
20 changes: 20 additions & 0 deletions src/quantem/core/visualization/show_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,23 @@ class Scalebar:
Font size of the scale bar label in points. Default 12.
bold : bool
Whether to render the label in bold. Default True.
box : bool
Draw a translucent box behind the bar and label. Default False.
box_color : str
Fill colour of the box. Default ``"black"``.
box_alpha : float
Opacity of the box, between 0 and 1. Default 0.5.
outline_color : str or None
Colour of an outline drawn around the bar and label (matplotlib
path effects). ``None`` draws no outline. Default ``None``.
outline_width : float
Width of the outline in points. Default 2.0.

Examples
--------
>>> ShowParams.Scalebar(sampling=0.5, units="Å")
>>> ShowParams.Scalebar(sampling=0.02, units="1/Å", color="black", fontsize=16)
>>> ShowParams.Scalebar(sampling=0.5, units="Å", outline_color="black")
"""

sampling: float = 1.0
Expand All @@ -264,13 +276,21 @@ class Scalebar:
loc: Literal["lower right", "lower left", "upper right", "upper left"] = "lower right"
fontsize: int = 12
bold: bool = False
box: bool = False
box_color: str = "black"
box_alpha: float = 0.5
outline_color: str | None = None
outline_width: float = 2.0

def __post_init__(self) -> None:
validate_gt(self.sampling, 0, "sampling")
if self.length is not None:
validate_gt(self.length, 0, "length")
validate_gt(self.width_px, 0, "width_px")
validate_gt(self.fontsize, 0, "fontsize")
validate_gt(self.outline_width, 0, "outline_width")
if not 0 <= self.box_alpha <= 1:
raise ValueError(f"box_alpha must be between 0 and 1, got {self.box_alpha}")

def to_config(self) -> ScalebarConfig:
"""Convert to a ``ScalebarConfig``."""
Expand Down
10 changes: 10 additions & 0 deletions src/quantem/core/visualization/visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ def _show_2d_array(
scalebar_config.loc,
scalebar_config.fontsize,
scalebar_config.bold,
box=scalebar_config.box,
box_color=scalebar_config.box_color,
box_alpha=scalebar_config.box_alpha,
outline_color=scalebar_config.outline_color,
outline_width=scalebar_config.outline_width,
)

for spine in ax.spines.values(): # fixes asymmetry of bbox for some reason
Expand Down Expand Up @@ -297,6 +302,11 @@ def _show_2d_combined(
scalebar_config.loc,
scalebar_config.fontsize,
scalebar_config.bold,
box=scalebar_config.box,
box_color=scalebar_config.box_color,
box_alpha=scalebar_config.box_alpha,
outline_color=scalebar_config.outline_color,
outline_width=scalebar_config.outline_width,
)

return fig, ax
Expand Down
38 changes: 34 additions & 4 deletions src/quantem/core/visualization/visualization_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import matplotlib.pyplot as plt
import numpy as np
from colorspacious import cspace_convert
from matplotlib import cm, colors, legend, ticker
from matplotlib import cm, colors, legend, patheffects, ticker
from matplotlib.axes import Axes
from matplotlib.colorbar import Colorbar
from matplotlib.figure import Figure
Expand Down Expand Up @@ -144,6 +144,18 @@ class ScalebarConfig:
Font size of the scale bar label in points.
bold : bool, default=True
Whether to render the scale bar label in bold.
box : bool, default=False
Draw a translucent box behind the bar and label.
box_color : str, default="black"
Fill color of the box.
box_alpha : float, default=0.5
Opacity of the box.
outline_color : str, optional
Color of an outline drawn around the bar and label (via matplotlib
path effects) so the scale bar stays readable on any background.
If None, no outline is drawn.
outline_width : float, default=2.0
Width of the outline in points.
"""

sampling: float = 1.0
Expand All @@ -155,6 +167,11 @@ class ScalebarConfig:
loc: str | int = "lower right"
fontsize: int = 12
bold: bool = True
box: bool = False
box_color: str = "black"
box_alpha: float = 0.5
outline_color: str | None = None
outline_width: float = 2.0


SCALEBAR_KWARGS = [
Expand Down Expand Up @@ -350,6 +367,8 @@ def add_scalebar_to_ax(
box: bool = False,
box_color: str = "black",
box_alpha: float = 0.5,
outline_color: str | None = None,
outline_width: float = 2.0,
) -> None:
"""Add a scale bar to a matplotlib axis.

Expand Down Expand Up @@ -381,13 +400,16 @@ def add_scalebar_to_ax(
box : bool, default=False
Draw a translucent box behind the bar and label so it stays
readable on any image (e.g. white bar on a black box, or black bar
on a white box). Padding follows ``pad_px``. ``box``, ``box_color``
and ``box_alpha`` are only available when calling this function
directly; ScalebarConfig and show_2d do not pass them.
on a white box). Padding follows ``pad_px``.
box_color : str, default="black"
Fill color of the box.
box_alpha : float, default=0.5
Opacity of the box.
outline_color : str, optional
Color of an outline drawn around the bar and label using
matplotlib path effects. If None, no outline is drawn.
outline_width : float, default=2.0
Width of the outline in points.
"""
from matplotlib.font_manager import FontProperties

Expand Down Expand Up @@ -426,6 +448,14 @@ def add_scalebar_to_ax(
)
if box:
bar.patch.set(facecolor=box_color, edgecolor="none", alpha=box_alpha)
if outline_color is not None:
effects = [
patheffects.withStroke(linewidth=outline_width, foreground=outline_color)
]
for artist in bar.size_bar.get_children():
artist.set_path_effects(effects)
for artist in bar.txt_label.get_children():
artist.set_path_effects(effects)
ax.add_artist(bar)


Expand Down
Loading