Units (dm.Length / dm.cm / dm.inch / dm.mm / dm.pt)

Free-form width/aspect input helpers (0.4+).

The 0.4 figure-creation API takes a free-form width= value plus a separate aspect= (height / width). This module is the parser that turns user inputs — unit-suffixed strings or Length instances — into a single inch-valued float that matplotlib’s figsize argument expects, and resolves named aspect tokens (square / portrait / standard / golden / wide / cinema) into a height/width ratio.

Most callers never touch this module directly: they hand a string or a helper call to dartwork_mpl.figsize(), and the parser runs underneath. The names below are the underlying primitives in case you need to share a length across several figures or convert ad-hoc.

import dartwork_mpl as dm

# Helper calls — return Length (Color-pattern wrapper)
dm.cm(13)            # Length(13.0000cm)
dm.inch(6.7)         # Length(6.7000in)
dm.mm(170)           # Length(17.0000cm)
dm.pt(24)            # Length(0.8467cm)

# Multi-unit views as properties
dm.cm(13).inch       # 5.118...
dm.cm(13).pt         # 368.5...

# parse_width accepts unit strings or Length instances
from dartwork_mpl.units import parse_width, parse_aspect
parse_width("13cm")     # 5.118...
parse_width("6.7in")    # 6.7
parse_width(dm.cm(13))  # 5.118... (Length pass-through)
parse_aspect("standard")  # 0.75

# dm.figsize's second argument is polymorphic — pick whichever
# form reads naturally for the call site:
dm.figsize("13cm", "wide")        # aspect token
dm.figsize("13cm", 0.6)           # numeric ratio (height/width)
dm.figsize("13cm", "8cm")         # unit-string height
dm.figsize("13cm", dm.cm(8))      # Length height
dm.figsize("13cm", "5in")         # mixed units (height in inches)

API

Free-form length and aspect parsing helpers.

dartwork-mpl 0.4+ accepts user-supplied widths in physical units (cm/in/mm/pt) rather than fixed tokens. This module is the parser that converts those inputs into a Length value matplotlib’s figsize= (and friends) can ultimately consume.

It also resolves named aspect tokens (square/portrait/standard/ golden/wide/cinema) into a height/width ratio.

class dartwork_mpl.units.Length(value: str | Length)[source]

Bases: object

Physical length with multi-unit views.

Mirrors the Color design: an opaque wrapper with a single canonical store (inches) and per-unit property views (length.cm, length.mm, length.inch, length.pt). Deliberately not a float subclass — passing a Length directly to a matplotlib API would silently mis-interpret the unit at non-inch boundaries (fontsize= / linewidth= are pt; transform offsets are px), so callers must always pick a unit explicitly when crossing out of dartwork-mpl. For figsize specifically, use dartwork_mpl.figsize() (the recommended idiom) or the explicit length.inch view.

DPI-dependent units (px) are not exposed on the class itself — a caller that needs pixels can write length.inch * fig.dpi and keep the dependency explicit at the call site.

Parameters:

value (str | Length) – Either a parseable unit string ("13cm", "5in", "170mm", "24pt") or another Length. Bare int/float are rejected — they carry no unit and the cm/inch ambiguity is exactly the bug this class exists to prevent. Use from_cm() / from_inch() / from_mm() / from_pt() (or the top-level wrappers cm() / inch() / mm() / pt()) for already-typed numeric input.

Examples

>>> import dartwork_mpl as dm
>>> w = dm.Length("13cm")
>>> w.cm, w.mm, w.inch, w.pt
(13.0, 130.0, 5.118110236220472, 368.5039370078739)
>>> # Crossing into matplotlib — pick the unit explicitly:
>>> import matplotlib.pyplot as plt
>>> fig, ax = plt.subplots(figsize=dm.figsize("13cm", "wide"))
>>> ax.set_xlabel("x", fontsize=dm.pt(10).pt)
property cm: float

Length expressed in centimeters.

classmethod from_cm(value: float) Length[source]

Construct from centimeters.

classmethod from_inch(value: float) Length[source]

Construct from inches.

classmethod from_mm(value: float) Length[source]

Construct from millimeters.

classmethod from_pt(value: float) Length[source]

Construct from PostScript points (1 pt = 1/72 in).

property inch: float

Length expressed in inches (the canonical internal unit).

property mm: float

Length expressed in millimeters.

property pt: float

Length expressed in PostScript points (1 pt = 1/72 in).

dartwork_mpl.units.cm(value: float) Length[source]

Construct a Length from centimeters.

dartwork_mpl.units.figsize(width: str | Length, aspect: str | int | float | Length = 'standard') tuple[float, float][source]

Return a matplotlib figsize tuple from a physical width and an aspect-or-height specifier.

Drop-in replacement for inline figsize=(w, h) literals. Pairs cleanly with plt.subplots and plt.figure:

fig, ax = plt.subplots(figsize=dm.figsize("13cm", "wide"))
fig = plt.figure(figsize=dm.figsize("15cm", "9cm"))     # explicit height
fig = plt.figure(figsize=dm.figsize(dm.col1, "standard"))
Parameters:
  • width (str | Length) – Physical width — either a unit string ("13cm", "5in", "170mm", "24pt") or a Length value (dm.cm(13), dm.col1, dm.col2). Bare int/float are rejected — the unit must always be explicit.

  • aspect (str | int | float | Length, optional) –

    Specifies the figure’s height in one of four forms; the first matching form wins:

    1. Aspect token — one of {"square", "portrait", "standard", "golden", "wide", "cinema"}. Sets height = width * ratio where the ratio is taken from ASPECT_TOKENS. Default "standard" (3 : 4).

    2. Numeric ratio (positive int / float, non-bool) — interpreted as height / width.

    3. Unit-suffix string"12cm", "5in", "170mm", "24pt". Interpreted as a literal height. The unit need not match the width’s unit.

    4. Length valuedm.cm(12), dm.col1, etc. Interpreted as a literal height.

    Bare numeric strings ("0.5") and unknown aspect tokens raise ValueError with a “did-you-mean” hint.

Returns:

(width_in_inches, height_in_inches) — plain floats ready to hand to matplotlib’s figsize= argument.

Return type:

tuple[float, float]

Examples

All four forms produce the same 13 cm by 8 cm figure (within floating-point tolerance), letting callers pick whichever notation reads most naturally for the call site:

>>> import dartwork_mpl as dm
>>> dm.figsize("13cm", 8 / 13)                       # ratio
(5.118..., 3.149...)
>>> dm.figsize("13cm", "8cm")                        # height (str)
(5.118..., 3.149...)
>>> dm.figsize("13cm", dm.cm(8))                     # height (Length)
(5.118..., 3.149...)
>>> dm.figsize("13cm", "wide")                       # token (≈ 8.67 cm)
(5.118..., 3.412...)

Common idioms:

>>> dm.figsize("17cm", 0.6)                          # journal two-column
>>> dm.figsize(dm.col1, "golden")                    # academic, golden ratio
>>> dm.figsize("15cm", "12cm")                       # explicit dimensions
>>> dm.figsize("100mm", "75mm")                      # all-mm
dartwork_mpl.units.inch(value: float) Length[source]

Construct a Length from inches.

dartwork_mpl.units.length(value: str | Length) Length[source]

Parse a unit string (or pass through a Length) into Length.

The string-parser counterpart to cm() / inch() / mm() / pt(). Mirrors dartwork_mpl.colors.hex().

dartwork_mpl.units.mm(value: float) Length[source]

Construct a Length from millimeters.

dartwork_mpl.units.parse_aspect(value: str | int | float) float[source]

Resolve an aspect specification to a height/width ratio.

Parameters:

value (str | int | float) – Either a known aspect token ("square", "portrait", "standard", "golden", "wide", "cinema") or a positive number interpreted directly as height / width.

Returns:

The height/width ratio. Always strictly positive.

Return type:

float

dartwork_mpl.units.parse_width(value: str | Length) float[source]

Parse a width specification into inches.

Parameters:

value (str | Length) –

A unit string like "9cm", "6.7in", "170mm", "24pt" or a Length value. Surrounding whitespace and matched quote characters are stripped from string inputs.

Bare int/float are rejected: matplotlib’s figsize is in inches but dartwork-mpl widths are typically given in cm, so an unannotated number has no safe interpretation.

Returns:

Width in inches. Always strictly positive.

Return type:

float

Raises:
  • TypeError – If value is a bare int/float/bool (no unit).

  • ValueError – If the input cannot be parsed, has an unknown unit, or is non-positive.

dartwork_mpl.units.pt(value: float) Length[source]

Construct a Length from PostScript points.