Skip to content

Watermark — Stamp a Logo or Brand Text on a Figure#

The cleopatra.styling.watermark module puts a mark on a finished matplotlib Figure with a single call, so anything you publish or share can carry one without re-rolling the same glue in every notebook. Two entry points, designed to be used together:

  • glyph.stamp_mark(...) — a logo image, anchored in a corner.
  • glyph.stamp_watermark(...) — diagonal brand text across the middle, with an optional credit line along the bottom.

Both size by a fraction of the figure and position by a margin from its edge, so a mark keeps its proportions across the several dpis a figure is exported at.

Both are also available on every glyph as methods, so the common case needs no import:

glyph.plot()
glyph.stamp_mark(LOGO, frac=0.18, corner="lower left")
glyph.stamp_watermark("earthlens", credit="github.com/serapeum-org/earthlens")

Both stamp the glyph's own figure, and for the common single-glyph case both are the way in: the functions underneath (_stamp_mark, _stamp_watermark) are private, so a stamp goes through the glyph rather than a second equivalent free function. A stamp lands on the whole figure, so on a figure carrying several glyphs it does not matter which one you call it through.

The one sanctioned exception is the mark image on a composite figure no single glyph owns — several glyphs' panels laid out in one plt.figure (the documented multi-panel pattern), or a figure built entirely outside cleopatra. For that, the module-level stamp_mark_on(fig, path, ...) is a supported, public escape hatch onto the same image stamp — see the stamp_mark_on section below. (Brand text on such a figure stays glyph-only; there is no stamp_watermark_on.)

stamp_mark — a logo image#

glyph.stamp_mark(path, *, frac=0.11, corner="lower right", margin=0.025, shadow=True, blur=0.065). Two things make it more than a one-liner over imshow:

  • Fraction-of-figure sizing. The mark is drawn on a frameless inset axes in figure-fraction coordinates, so it stays the same proportion (and corner offset) no matter what dpi the figure is later saved at — the MP4 master, the smaller web copy, and the GIF all get a mark of the same relative size. frac sets the width relative to the figure width; the height is derived from the image and figure aspect ratios, so the image is never stretched. (This is the dpi-independent counterpart of Figure.figimage, which is pixel-based.)
  • Optional halo. With shadow=True (the default) a gaussian-blurred black copy of the mark's alpha is composited behind it so the mark separates from a busy or dark canvas. The blur uses Pillow (already a cleopatra dependency), so no new dependency — and no SciPy — is pulled in.

The halo is centred, not offset. A mark is composited over arbitrary imagery — night ocean, sunlit cloud, a bright limb — and a symmetric halo reads the same whichever way the background falls, where a down-right drop shadow implies a light direction nothing else in the frame has. blur is the halo's sigma as a fraction of the mark's own width.

It is a presentation helper, not a glyph: it takes whatever Figure you hand it and draws on top. Single-image, corner-anchored marks only — tiled / repeated marks and any licensing / provenance semantics are out of scope.

stamp_mark takes the mark either as a file path (any format Pillow can open, read as RGBA) or as an in-memory (H, W, 3) / (H, W, 4) NumPy array (uint8 0-255 or float 0-1; RGB gains an opaque alpha). It returns the frameless inset Axes it drew on, so you can adjust it further.

stamp_mark_on — a figure no glyph owns#

stamp_mark_on(fig, path, *, frac=0.11, corner="lower right", margin=0.025, shadow=True, blur=0.065) is the module-level counterpart of glyph.stamp_mark, for a composite figure no single glyph owns: several glyphs' panels laid out in one plt.figure (the sanctioned multi-panel pattern — each panel drawn by a glyph bound to that panel's axes, ArrayGlyph(arr, ax=ax).plot()), or a figure built entirely outside cleopatra. There is no one glyph whose stamp_mark covers the shared figure, so this takes the Figure directly. It draws the same corner mark with the same options and returns the same frameless inset Axes.

import matplotlib.pyplot as plt
from cleopatra.glyphs.gridded.array_glyph import ArrayGlyph
from cleopatra.styling.watermark import stamp_mark_on

fig, axes = plt.subplots(1, 3, figsize=(15, 4))
for ax, arr in zip(axes, arrays):
    ArrayGlyph(arr, ax=ax).plot()   # each glyph owns only its own panel axes
stamp_mark_on(fig, "brand/logo.png", corner="lower right")

Reach for the glyph method glyph.stamp_mark for the common single-glyph case — it stays the primary API. stamp_mark_on is the explicit, supported escape hatch so a composite layout never has to import the private _stamp_mark.

stamp_watermark — brand text#

glyph.stamp_watermark(text, *, frac=0.55, angle=30.0, alpha=0.65, color="white", credit=None, credit_frac=0.28, credit_alpha=1.0, margin=0.014) stamps translucent brand text across the middle of the figure, and optionally a credit line along the bottom.

  • The fraction means the same thing for any text. Scaling a point size off the figure width — the obvious shortcut — renders a short word small and a long one straight off the canvas, because how much of a frame a string covers depends on how many characters it has. frac is measured on what is actually rendered, so a two-letter brand and a twenty-character one both land at the fraction you asked for.
  • The credit line is placed by margin, a fraction of the figure height above the bottom edge, and sized by credit_frac — the same shapes stamp_mark uses, rather than a hardcoded offset and point size.
  • Only the credit line is outlined. That asymmetry is deliberate: an outline on the large diagonal text makes it read as a solid caption rather than a watermark, while the credit is small enough that it needs the stroke to stay legible against whatever the frame contains.

It returns (brand_text, credit_text) — the second is None when no credit was given.

glyph.stamp_mark(LOGO, frac=0.18, corner="lower left")
glyph.stamp_watermark("earthlens", credit="github.com/serapeum-org/earthlens")

Call both last

Like stamp_mark, the text size is baked from the figure's current size, so stamp after any tight_layout() and after the final set_size_inches. The proportion holds across dpi. It does not survive a later set_size_inches, and here the text differs from the mark: a mark lives on an inset axes in figure-fraction coordinates and keeps its share of a figure resized proportionally afterwards, whereas text is measured in points and keeps its absolute size, halving its share when the figure doubles.

Usage#

import numpy as np
from cleopatra.glyphs.gridded.array_glyph import ArrayGlyph

glyph = ArrayGlyph(np.arange(60.0).reshape(6, 10))
glyph.plot()

fig = plt.figure(figsize=(12, 8))
fig.add_subplot(111).imshow(np.random.default_rng(0).random((60, 90)), cmap="magma")

# a file on disk...
glyph.stamp_mark("brand/logo.png", frac=0.12, corner="lower right")

# ...or an in-memory RGBA array, in a different corner, without the shadow
logo = np.zeros((80, 160, 4), dtype=np.uint8)
logo[..., :3] = 255
logo[..., 3] = 255
glyph.stamp_mark(logo, frac=0.09, corner="upper left", shadow=False)

fig.savefig("figure.png", dpi=200)  # the mark keeps its proportion at any dpi

corner is one of "lower right" (default), "lower left", "upper right", or "upper left"; anything else raises a ValueError naming the bad value. margin is the gap between the mark and the figure edges as a fraction of the figure — either a scalar for both axes or an (x, y) pair. The pair matters when a mark has to tuck hard into a corner on one axis while keeping a gap on the other:

glyph.stamp_mark("brand/logo.png", margin=(0.025, 0.0))  # flush with the bottom, inset from the right

Stamp last, and save the whole figure

The mark is baked at stamp time from the figure's current size, so stamp after any tight_layout() / layout finalization and after the final set_size_inches (stamping first then calling tight_layout() emits a UserWarning). The fraction-of-figure sizing assumes the whole figure is saved: a plain dpi= save keeps the mark proportional, but savefig(bbox_inches="tight") crops surrounding whitespace and so changes the mark's relative margin and size.

frac sizes the mark, not the halo canvas

The halo needs a transparent pad of three sigmas on each side to hold its own tail, which makes the composited canvas about 1.39x the mark's width at the default blur. stamp_mark grows the inset axes by exactly that factor, so the visible mark still measures frac. Sizing the padded canvas to frac instead would render the mark at roughly 72 % of the requested size — easy to miss, because the axes bounding box still looks correct. With shadow=True the returned axes' bbox therefore covers mark and halo, and is larger than frac; margin is still measured to the mark, so a halo beside a small margin is clipped at the figure edge (which is what you want when tucking a mark into a corner).

Method Documentation#

cleopatra.styling.watermark.WatermarkMixin #

The glyph-side entry point for both figure stamps.

Both stamps act on a whole Figure, and every glyph knows its own, so the glyph is where they are offered: glyph.stamp_mark(logo). The functions underneath are private, which makes this the one supported way in rather than a convenience beside an equally public free function.

A figure is what these need, and glyphs spell it differently. Glyph keeps the one it rendered on in fig. HistogramGlyph and TexturedGlobeGlyph do not inherit Glyph and use _fig for something else -- the figure bound at construction, consulted on every render to decide where to draw -- so they record the figure actually drawn on as _rendered_fig. _watermark_figure prefers that, then fig, then _fig, then the axes' own figure, so the mixin works on any of them without first making them agree on a name.

Note that a figure may carry several glyphs. The stamp lands on the whole figure, not on the glyph's own axes, whichever glyph it was called through.

Source code in src/cleopatra/styling/watermark.py
class WatermarkMixin:
    """The glyph-side entry point for both figure stamps.

    Both stamps act on a whole `Figure`, and every glyph knows its own, so the
    glyph is where they are offered: `glyph.stamp_mark(logo)`. The functions
    underneath are private, which makes this the one supported way in rather
    than a convenience beside an equally public free function.

    A figure is what these need, and glyphs spell it differently. `Glyph` keeps
    the one it rendered on in `fig`. `HistogramGlyph` and `TexturedGlobeGlyph`
    do not inherit `Glyph` and use `_fig` for something else -- the figure bound
    at *construction*, consulted on every render to decide where to draw -- so
    they record the figure actually drawn on as `_rendered_fig`.
    `_watermark_figure` prefers that, then `fig`, then `_fig`, then the axes'
    own figure, so the mixin works on any of them without first making them
    agree on a name.

    Note that a figure may carry several glyphs. The stamp lands on the whole
    figure, not on the glyph's own axes, whichever glyph it was called through.
    """

    def _watermark_figure(self) -> Figure:
        """Resolve the figure to stamp.

        Returns:
            Figure: The glyph's figure.

        Raises:
            ValueError: If the glyph has no figure yet, which means it has not
                been rendered.
        """
        for name in ("fig", "_rendered_fig", "_fig"):
            figure = getattr(self, name, None)
            if figure is not None:
                return figure
        for name in ("ax", "_ax"):
            axes = getattr(self, name, None)
            if axes is not None:
                figure = axes.get_figure()
                if figure is not None:
                    return figure
        raise ValueError(
            f"{type(self).__name__} has no figure to stamp yet -- render it "
            f"first (e.g. plot()), then stamp."
        )

    def stamp_mark(self, path: str | os.PathLike | np.ndarray, **kwargs: Any) -> Axes:
        """Stamp a logo image on this glyph's figure.

        The primary way to stamp a logo, for the common single-glyph case.
        `_stamp_mark` underneath takes a bare `Figure` and is private; a
        *composite* figure no single glyph owns has its own supported entry
        point, `stamp_mark_on`.

        Args:
            path: The mark image, as `_stamp_mark` accepts it.
            **kwargs: Forwarded verbatim (`frac`, `corner`, `margin`, `shadow`,
                `blur`).

        Returns:
            Axes: The frameless inset axes the mark was drawn on.

        Raises:
            ValueError: If the glyph has not been rendered yet, or as
                `_stamp_mark` raises.

        See Also:
            cleopatra.styling.watermark.stamp_mark_on: The figure-taking
                counterpart, for a composite figure no single glyph owns.
            cleopatra.styling.watermark._stamp_mark: The private figure stamp
                underneath.
        """
        # The bare name is the module-level function, not this method: a method
        # name never enters the enclosing scope its body is resolved in.
        return _stamp_mark(self._watermark_figure(), path, **kwargs)

    def stamp_watermark(self, text: str, **kwargs: Any) -> tuple[Text, Text | None]:
        """Stamp diagonal brand text on this glyph's figure.

        The supported way to stamp brand text. `_stamp_watermark` underneath
        takes a bare `Figure` and is private: a figure no glyph owns is out of
        scope.

        Args:
            text: The brand text.
            **kwargs: Forwarded verbatim (`frac`, `angle`, `alpha`, `color`,
                `credit`, `credit_frac`, `credit_alpha`, `margin`).

        Returns:
            tuple[Text, Text | None]: The brand-text artist and the credit-line
            artist, the second being `None` when no `credit` was given.

        Raises:
            ValueError: If the glyph has not been rendered yet, or as
                `_stamp_watermark` raises.

        See Also:
            cleopatra.styling.watermark._stamp_watermark: The private
                function underneath.

        Examples:
            - Stamp a logo and brand text without importing either:
                ```python
                >>> import matplotlib
                >>> matplotlib.use("Agg")
                >>> import numpy as np
                >>> import matplotlib.pyplot as plt
                >>> from cleopatra.glyphs.gridded.array_glyph import ArrayGlyph
                >>> glyph = ArrayGlyph(np.arange(60.0).reshape(6, 10))
                >>> _ = glyph.plot()
                >>> brand, credit = glyph.stamp_watermark("cleopatra")
                >>> brand.get_text()
                'cleopatra'
                >>> plt.close("all")

                ```
        """
        return _stamp_watermark(self._watermark_figure(), text, **kwargs)

stamp_mark(path, **kwargs) #

Stamp a logo image on this glyph's figure.

The primary way to stamp a logo, for the common single-glyph case. _stamp_mark underneath takes a bare Figure and is private; a composite figure no single glyph owns has its own supported entry point, stamp_mark_on.

Parameters:

Name Type Description Default
path str | PathLike | ndarray

The mark image, as _stamp_mark accepts it.

required
**kwargs Any

Forwarded verbatim (frac, corner, margin, shadow, blur).

{}

Returns:

Name Type Description
Axes Axes

The frameless inset axes the mark was drawn on.

Raises:

Type Description
ValueError

If the glyph has not been rendered yet, or as _stamp_mark raises.

See Also

cleopatra.styling.watermark.stamp_mark_on: The figure-taking counterpart, for a composite figure no single glyph owns. cleopatra.styling.watermark._stamp_mark: The private figure stamp underneath.

Source code in src/cleopatra/styling/watermark.py
def stamp_mark(self, path: str | os.PathLike | np.ndarray, **kwargs: Any) -> Axes:
    """Stamp a logo image on this glyph's figure.

    The primary way to stamp a logo, for the common single-glyph case.
    `_stamp_mark` underneath takes a bare `Figure` and is private; a
    *composite* figure no single glyph owns has its own supported entry
    point, `stamp_mark_on`.

    Args:
        path: The mark image, as `_stamp_mark` accepts it.
        **kwargs: Forwarded verbatim (`frac`, `corner`, `margin`, `shadow`,
            `blur`).

    Returns:
        Axes: The frameless inset axes the mark was drawn on.

    Raises:
        ValueError: If the glyph has not been rendered yet, or as
            `_stamp_mark` raises.

    See Also:
        cleopatra.styling.watermark.stamp_mark_on: The figure-taking
            counterpart, for a composite figure no single glyph owns.
        cleopatra.styling.watermark._stamp_mark: The private figure stamp
            underneath.
    """
    # The bare name is the module-level function, not this method: a method
    # name never enters the enclosing scope its body is resolved in.
    return _stamp_mark(self._watermark_figure(), path, **kwargs)

stamp_watermark(text, **kwargs) #

Stamp diagonal brand text on this glyph's figure.

The supported way to stamp brand text. _stamp_watermark underneath takes a bare Figure and is private: a figure no glyph owns is out of scope.

Parameters:

Name Type Description Default
text str

The brand text.

required
**kwargs Any

Forwarded verbatim (frac, angle, alpha, color, credit, credit_frac, credit_alpha, margin).

{}

Returns:

Type Description
Text

tuple[Text, Text | None]: The brand-text artist and the credit-line

Text | None

artist, the second being None when no credit was given.

Raises:

Type Description
ValueError

If the glyph has not been rendered yet, or as _stamp_watermark raises.

See Also

cleopatra.styling.watermark._stamp_watermark: The private function underneath.

Examples:

  • Stamp a logo and brand text without importing either:
    >>> import matplotlib
    >>> matplotlib.use("Agg")
    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> from cleopatra.glyphs.gridded.array_glyph import ArrayGlyph
    >>> glyph = ArrayGlyph(np.arange(60.0).reshape(6, 10))
    >>> _ = glyph.plot()
    >>> brand, credit = glyph.stamp_watermark("cleopatra")
    >>> brand.get_text()
    'cleopatra'
    >>> plt.close("all")
    
Source code in src/cleopatra/styling/watermark.py
def stamp_watermark(self, text: str, **kwargs: Any) -> tuple[Text, Text | None]:
    """Stamp diagonal brand text on this glyph's figure.

    The supported way to stamp brand text. `_stamp_watermark` underneath
    takes a bare `Figure` and is private: a figure no glyph owns is out of
    scope.

    Args:
        text: The brand text.
        **kwargs: Forwarded verbatim (`frac`, `angle`, `alpha`, `color`,
            `credit`, `credit_frac`, `credit_alpha`, `margin`).

    Returns:
        tuple[Text, Text | None]: The brand-text artist and the credit-line
        artist, the second being `None` when no `credit` was given.

    Raises:
        ValueError: If the glyph has not been rendered yet, or as
            `_stamp_watermark` raises.

    See Also:
        cleopatra.styling.watermark._stamp_watermark: The private
            function underneath.

    Examples:
        - Stamp a logo and brand text without importing either:
            ```python
            >>> import matplotlib
            >>> matplotlib.use("Agg")
            >>> import numpy as np
            >>> import matplotlib.pyplot as plt
            >>> from cleopatra.glyphs.gridded.array_glyph import ArrayGlyph
            >>> glyph = ArrayGlyph(np.arange(60.0).reshape(6, 10))
            >>> _ = glyph.plot()
            >>> brand, credit = glyph.stamp_watermark("cleopatra")
            >>> brand.get_text()
            'cleopatra'
            >>> plt.close("all")

            ```
    """
    return _stamp_watermark(self._watermark_figure(), text, **kwargs)

cleopatra.styling.watermark.stamp_mark_on(fig, path, *, frac=0.11, corner=_DEFAULT_CORNER, margin=0.025, shadow=True, blur=DEFAULT_BLUR) #

Stamp a logo image on a figure that no single glyph owns.

The supported escape hatch for a composite figure -- one assembled from several glyphs' panels (a GridSpec whose panels are each an ArrayGlyph(arr, ax=ax).plot()), or one built entirely outside cleopatra -- where no single glyph owns the whole figure, so there is no glyph whose stamp_mark covers it. For the common single-glyph case use the glyph method WatermarkMixin.stamp_mark, which stays the primary, discoverable API; this is its figure-taking counterpart, so a composite layout need not reach for the private _stamp_mark. It draws the same corner mark; the options below are _stamp_mark's, forwarded unchanged.

Parameters:

Name Type Description Default
fig Figure

The matplotlib Figure to stamp -- typically a multi-panel composite. The mark is drawn on top of whatever it already holds.

required
path str | PathLike | ndarray

The mark image: a file path (any format PIL can open, read as RGBA) or an in-memory (H, W, 3) / (H, W, 4) array.

required
frac float

The mark's longer on-figure side as a fraction of the figure, in (0, 1], so the mark stays proportional across dpis. Defaults to 0.11.

0.11
corner str

Which corner to anchor to -- "lower right" (default), "lower left", "upper right", or "upper left".

_DEFAULT_CORNER
margin float | tuple[float, float]

The gap between the mark and the figure edges, a scalar or an (x, y) pair each in [0, 1). Defaults to 0.025.

0.025
shadow bool

Whether to composite a gaussian-blurred halo behind the mark so it reads on a busy or dark canvas. Defaults to True.

True
blur float

Halo blur sigma as a fraction of the mark's own width; must be non-negative. Defaults to DEFAULT_BLUR.

DEFAULT_BLUR

Returns:

Name Type Description
Axes Axes

The frameless inset axes the mark was drawn on.

Raises:

Type Description
ValueError

For an unknown corner, a frac outside (0, 1], a margin that is not a scalar or (x, y) pair in [0, 1) (or one that pushes the mark off the figure), a negative blur, or an out-of-contract image array.

FileNotFoundError

If path is a file path that does not exist.

UnidentifiedImageError

If path is a file that is not an image PIL can decode.

Examples:

  • Stamp a logo once on a composite figure built from several panels:
    >>> import matplotlib
    >>> matplotlib.use("Agg")
    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> from cleopatra.styling.watermark import stamp_mark_on
    >>> fig, axes = plt.subplots(1, 3, figsize=(8, 6))
    >>> for panel in axes:  # three glyph panels no single glyph owns
    ...     _ = panel.imshow(np.zeros((4, 4)))
    >>> logo = np.full((40, 80, 4), 255, dtype=np.uint8)
    >>> ax = stamp_mark_on(fig, logo, frac=0.2, shadow=False)
    >>> [round(float(v), 3) for v in ax.get_position().bounds]
    [0.775, 0.025, 0.2, 0.133]
    >>> plt.close(fig)
    
See Also

WatermarkMixin.stamp_mark: The glyph method for the common single-glyph case -- the primary API. cleopatra.styling.watermark._stamp_mark: The private figure stamp this delegates to.

Source code in src/cleopatra/styling/watermark.py
def stamp_mark_on(
    fig: Figure,
    path: str | os.PathLike | np.ndarray,
    *,
    frac: float = 0.11,
    corner: str = _DEFAULT_CORNER,
    margin: float | tuple[float, float] = 0.025,
    shadow: bool = True,
    blur: float = DEFAULT_BLUR,
) -> Axes:
    """Stamp a logo image on a figure that no single glyph owns.

    The supported escape hatch for a *composite* figure -- one assembled from
    several glyphs' panels (a `GridSpec` whose panels are each an
    `ArrayGlyph(arr, ax=ax).plot()`), or one built entirely outside cleopatra
    -- where no single glyph owns the
    whole figure, so there is no glyph whose `stamp_mark` covers it. For the
    common single-glyph case use the glyph method `WatermarkMixin.stamp_mark`,
    which stays the primary, discoverable API; this is its figure-taking
    counterpart, so a composite layout need not reach for the private
    `_stamp_mark`. It draws the same corner mark; the options below are
    `_stamp_mark`'s, forwarded unchanged.

    Args:
        fig: The matplotlib `Figure` to stamp -- typically a multi-panel
            composite. The mark is drawn on top of whatever it already holds.
        path: The mark image: a file path (any format `PIL` can open, read as
            RGBA) or an in-memory `(H, W, 3)` / `(H, W, 4)` array.
        frac: The mark's longer on-figure side as a fraction of the figure, in
            `(0, 1]`, so the mark stays proportional across dpis. Defaults to
            `0.11`.
        corner: Which corner to anchor to -- `"lower right"` (default),
            `"lower left"`, `"upper right"`, or `"upper left"`.
        margin: The gap between the mark and the figure edges, a scalar or an
            `(x, y)` pair each in `[0, 1)`. Defaults to `0.025`.
        shadow: Whether to composite a gaussian-blurred halo behind the mark so
            it reads on a busy or dark canvas. Defaults to `True`.
        blur: Halo blur sigma as a fraction of the mark's own width; must be
            non-negative. Defaults to `DEFAULT_BLUR`.

    Returns:
        Axes: The frameless inset axes the mark was drawn on.

    Raises:
        ValueError: For an unknown `corner`, a `frac` outside `(0, 1]`, a
            `margin` that is not a scalar or `(x, y)` pair in `[0, 1)` (or one
            that pushes the mark off the figure), a negative `blur`, or an
            out-of-contract image array.
        FileNotFoundError: If `path` is a file path that does not exist.
        PIL.UnidentifiedImageError: If `path` is a file that is not an image
            `PIL` can decode.

    Examples:
        - Stamp a logo once on a composite figure built from several panels:
            ```python
            >>> import matplotlib
            >>> matplotlib.use("Agg")
            >>> import numpy as np
            >>> import matplotlib.pyplot as plt
            >>> from cleopatra.styling.watermark import stamp_mark_on
            >>> fig, axes = plt.subplots(1, 3, figsize=(8, 6))
            >>> for panel in axes:  # three glyph panels no single glyph owns
            ...     _ = panel.imshow(np.zeros((4, 4)))
            >>> logo = np.full((40, 80, 4), 255, dtype=np.uint8)
            >>> ax = stamp_mark_on(fig, logo, frac=0.2, shadow=False)
            >>> [round(float(v), 3) for v in ax.get_position().bounds]
            [0.775, 0.025, 0.2, 0.133]
            >>> plt.close(fig)

            ```

    See Also:
        WatermarkMixin.stamp_mark: The glyph method for the common
            single-glyph case -- the primary API.
        cleopatra.styling.watermark._stamp_mark: The private figure stamp this
            delegates to.
    """
    return _stamp_mark(
        fig, path, frac=frac, corner=corner, margin=margin, shadow=shadow, blur=blur
    )