From 46d8466dbae740febdc73831a0bae4cf40516e2e Mon Sep 17 00:00:00 2001 From: Alek Petuskey Date: Tue, 1 Sep 2026 22:52:08 -0700 Subject: [PATCH 1/7] Fix the audit's 21 P1s across kernel, API, client, exports and pyplot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every finding was reproduced on main before the change and has a regression test after it; UI-visible fixes carry before/after evidence under spec/assets. Kernel (channel.py, interaction.py, lod.py): a non-string message type returns None instead of raising in the dispatcher; pick/click bound-check against the rows the columns hold (histogram bins, hexbin cells) and also catch IndexError; a subnormal-span density_view is dropped by normalize_window and aligned_window no longer overflows on tiny normal spans; view_change records only finite, ordered, non-empty ranges so view_state() round-trips into state_patch_message. API (components.py, _figure.py, _payload.py, channels.py, columns.py, facets.py): a log axis warns (RuntimeWarning) when it drops non-positive points instead of doing so silently; non-finite continuous color/size values exclude the row from geometry, shipped_sel and static exports instead of painting as the colormap floor; sankey_chart accepts xy.sankey(...) like every other *_chart; a hand-built xy.Mark is completed with the factory's defaults instead of KeyError; bare pyarrow string arrays become categorical axes; facet_chart(by='missing') is a ValueError. Client (30_ticks.ts, 50_chartview.ts) and exporters (_svg.py): a log axis with fewer than two decade ticks in view falls back to linear ticks over the span, identically in TS and Python; legend-hidden category points are out of the hover pipeline (the CPU-nearest fallback skips hidden rows and scans the full pre-filter range). Exports (_pdf.py, _svg.py): PDF honors font-style, font-family (base-14 mapping), letter-spacing and opacity on text; XML-illegal control characters are dropped by escape() so SVG and PDF always produce well-formed output. pyplot: ticklabel_format configures the ScalarFormatter instead of breaking export; spans and rules autoscale like matplotlib's dataLim, reach the exported chart as the axis domain, and take label=; series.plot(ax=) works with pandas' locators; datetime limits, ticks and fill_between coordinates; legend(handles=, labels=), integer and tuple loc, Line2D/Patch/Rectangle legend proxies; zorder/clip_on/rasterized/... as documented compat-noops; plt.subplot(n, m, i) creates only the requested cell; callable plt.cm.* colormaps; BarPatch geometry getters; and the common kwargs the audit found rejected (facecolors='none', tick_label=, log=True, hist(bottom=, align=), text(alpha=), hlines(linestyle=), errorbar(capthick=, mfc=, mec=, mew=), colorbar(fraction=)). Spec updated alongside: wire-protocol.md, interaction.md §10, renderer-architecture.md §6, chart-grammar.md, styling.md, chart-kind-contract.md, export.md §2/§9, capability-matrix.md (regenerated), compat.md / compat-matrix.md / shim-todo.md / compat-changelog.md. --- js/src/30_ticks.ts | 39 +- js/src/50_chartview.ts | 35 +- python/xy/_figure.py | 64 +- python/xy/_payload.py | 30 +- python/xy/_pdf.py | 244 +++++++- python/xy/_svg.py | 80 ++- python/xy/channel.py | 45 +- python/xy/channels.py | 13 +- python/xy/columns.py | 28 +- python/xy/components.py | 118 +++- python/xy/facets.py | 16 +- python/xy/interaction.py | 21 +- python/xy/lod.py | 28 +- python/xy/pyplot/__init__.py | 64 +- python/xy/pyplot/_artists.py | 301 ++++++++- python/xy/pyplot/_axes.py | 452 ++++++++++++-- python/xy/pyplot/_colors.py | 67 ++ python/xy/pyplot/_mplfig.py | 39 +- python/xy/pyplot/_plot_types.py | 43 +- python/xy/pyplot/_ticker.py | 112 +++- python/xy/pyplot/_translate.py | 133 ++++ python/xy/styling/capabilities.py | 4 +- spec/api/capability-matrix.md | 16 +- spec/api/chart-kind-contract.md | 7 +- spec/api/export.md | 58 +- spec/api/interaction.md | 16 +- spec/api/styling.md | 19 +- .../legend-hidden-hover-before-after.png | Bin 0 -> 59445 bytes spec/assets/log-axis-decade-before-after.png | Bin 0 -> 27167 bytes .../pdf-text-properties-before-after.png | Bin 0 -> 91520 bytes .../pyplot-span-autoscale-before-after.png | Bin 0 -> 20922 bytes .../pyplot-subplot-cells-before-after.png | Bin 0 -> 25403 bytes spec/design/chart-grammar.md | 22 +- spec/design/renderer-architecture.md | 28 + spec/design/wire-protocol.md | 35 +- spec/matplotlib/compat-changelog.md | 22 + spec/matplotlib/compat-matrix.md | 14 +- spec/matplotlib/compat.md | 44 +- spec/matplotlib/shim-todo.md | 58 +- .../56_partial_subplots_legend_proxies.py | 38 ++ tests/pyplot/test_axes_charts.py | 4 +- tests/pyplot/test_axes_helpers.py | 7 +- tests/pyplot/test_p1_axes_dates_spans.py | 443 ++++++++++++++ tests/pyplot/test_p1_kwargs_legend_subplot.py | 575 ++++++++++++++++++ tests/pyplot/test_p3_option_contracts.py | 31 +- tests/pyplot/test_pdsh_gap_features.py | 11 +- tests/test_api_p1_fixes.py | 260 ++++++++ tests/test_channel_malformed_messages.py | 333 ++++++++++ tests/test_export_text_safety.py | 126 ++++ tests/test_legend_hidden_hover.py | 197 ++++++ tests/test_log_ticks_within_decade.py | 279 +++++++++ tests/test_pdf_export.py | 194 ++++++ tests/test_scatter.py | 10 +- 53 files changed, 4582 insertions(+), 241 deletions(-) create mode 100644 spec/assets/legend-hidden-hover-before-after.png create mode 100644 spec/assets/log-axis-decade-before-after.png create mode 100644 spec/assets/pdf-text-properties-before-after.png create mode 100644 spec/assets/pyplot-span-autoscale-before-after.png create mode 100644 spec/assets/pyplot-subplot-cells-before-after.png create mode 100644 tests/pyplot/corpus/56_partial_subplots_legend_proxies.py create mode 100644 tests/pyplot/test_p1_axes_dates_spans.py create mode 100644 tests/pyplot/test_p1_kwargs_legend_subplot.py create mode 100644 tests/test_api_p1_fixes.py create mode 100644 tests/test_channel_malformed_messages.py create mode 100644 tests/test_export_text_safety.py create mode 100644 tests/test_legend_hidden_hover.py create mode 100644 tests/test_log_ticks_within_decade.py diff --git a/js/src/30_ticks.ts b/js/src/30_ticks.ts index b1809b8e6..aaea88b7b 100644 --- a/js/src/30_ticks.ts +++ b/js/src/30_ticks.ts @@ -26,6 +26,8 @@ export function linearTicks(lo, hi, target = 6) { return { ticks: out, step }; } +// Mirrored by `_log_ticks` in python/xy/_svg.py — the static exporters must +// tick a log axis exactly where the browser does (renderer-architecture §6.1). export function logTicks(lo, hi, target = 6) { if (!Number.isFinite(lo) || !Number.isFinite(hi)) return { ticks: [], step: 1 }; const a = Math.min(lo, hi); @@ -33,6 +35,22 @@ export function logTicks(lo, hi, target = 6) { if (a <= 0 || b <= 0) return { ticks: [], step: 1 }; const e0 = Math.floor(Math.log10(a)); const e1 = Math.ceil(Math.log10(b)); + // The decade ladder is multiplicative: inside one decade it has at most the + // 2 and 5 mantissas to offer, and a window like 0.3..0.35 or 100..110 holds + // none of them — every zoom past ~3x on a log axis lost all ticks, labels + // and grid. With fewer than two decades in view the ladder cannot describe + // the window, so tick it linearly across the span (matplotlib/Plotly do the + // same). `step` is the nice linear step so fmtLinear shares one decimal + // count along the axis (§6.2); every tick is labelled. + let decadesInView = 0; + for (let e = e0; e <= e1; e++) { + const v = Math.pow(10, e); + if (v >= a * (1 - 1e-12) && v <= b * (1 + 1e-12)) decadesInView++; + } + if (decadesInView < 2) { + const linear = linearTicks(a, b, target); + return { ticks: linear.ticks, labels: linear.ticks, step: linear.step, log: true }; + } const span = Math.max(1, e1 - e0); const mults = span <= Math.max(2, target) ? [1, 2, 5] : [1]; const out = []; @@ -258,13 +276,18 @@ function fmtTimeSpec(ms, format) { // Decade ticks are multiplicative, so the linear formatter's step-derived // precision rounds every decade under 1.0 to a bare "0" — 0.001 and 0.01 read -// as two identical, wrong labels. Label these from their own magnitude. +// as two identical, wrong labels. Label these from their own value: the fewest +// decimals (up to 8) that reproduce it. For the 1/2/5 ladder that is exactly +// the old magnitude rule (0.002 -> 3 decimals, 20 -> none); it differs only +// for the within-decade linear ticks a log colorbar now carries (§6.1), which +// the magnitude rule collapsed to "2 2 2 3 3 3" for a 2..3 range. // Mirrored by `_fmt_log` in python/xy/_svg.py. export function fmtLog(v) { const av = Math.abs(v); if (av >= 1e6 || (av !== 0 && av < 1e-4)) return v.toExponential(1).replace("e+", "e"); - const dec = av && av < 1 ? Math.max(0, Math.ceil(-Math.log10(av))) : 0; - return v.toFixed(Math.min(dec, 8)); + let dec = 0; + while (dec < 8 && Math.abs(Number(av.toFixed(dec)) - av) > av * 1e-9) dec++; + return v.toFixed(dec); } // Whether a formatted label has lost the value it was meant to show. Tests the @@ -300,8 +323,14 @@ export function fmtAxis(axis, v, tickStep) { const formatted = fmtNumberSpec(v, axis && axis.format); if (axis && axis.scale === "log" && Number(v) > 0 && Number(v) < 1) { // A fixed-decimal spec collapses sub-unit decades; so does the linear - // fallback. Either way the magnitude-derived label is the useful one. - if (collapsedToZero(formatted)) return fmtLog(v); + // fallback under the ladder's step of 1. Either way the value-derived + // label is the useful one — except on the within-decade linear tick set + // (§6.1), whose sub-unit step gives fmtLinear the one shared decimal + // count an axis reads by ("0.30, 0.31, ...") where the per-value fmtLog + // would go ragged ("0.3, 0.31, ..."). Mirrored by `_fmt_axis`. + if (collapsedToZero(formatted)) { + return tickStep > 0 && tickStep < 1 ? fmtLinear(v, tickStep) : fmtLog(v); + } } return formatted || fmtLinear(v, tickStep); } diff --git a/js/src/50_chartview.ts b/js/src/50_chartview.ts index 2c6df776f..48949a920 100644 --- a/js/src/50_chartview.ts +++ b/js/src/50_chartview.ts @@ -8722,6 +8722,30 @@ export class ChartView { ]; } + // Whether a legend category toggle removed shipped row `i` from the drawn + // set. A hidden series is out of every pipeline (interaction spec §10), and + // the CPU hover fallbacks below scan the UNFILTERED retained columns, so + // they must ask. `_visInv` is the shipped-row -> drawn-vertex map that + // `_filterScatterRows` maintains beside `_visMap` (-1 = hidden); reading it, + // rather than re-deriving the hidden set from the category codes, keeps the + // fallback in lockstep with what the GPU pick pass can see by construction. + _cpuRowHidden(g, i) { + const inv = g._visInv; + return !!inv && inv[i] < 0; + } + + // How many retained rows a CPU hover scan covers. `g.n` is the DRAWN count, + // which a category filter shrinks below the retained columns: capping the + // scan at it left every visible row shipped after the cut unreachable while + // hidden rows before it still answered. `_fullN` is the pre-filter count + // `_filterScatterRows` records; an unfiltered trace keeps the `g.n` cap, + // which is load-bearing there (a smooth-resampled line's `n` exceeds its + // source columns; mismatched x/y lengths undershoot them). + _cpuScanLimit(g, ...lengths) { + const n = g._fullN !== undefined ? g._fullN : g.n; + return Math.min(...lengths, n || lengths[0]); + } + _nearestCpuIndex(g, dataX) { const cpu = g && g._cpu; if (!cpu || !cpu.x || !cpu.x.length) return -1; @@ -8730,8 +8754,9 @@ export class ChartView { const target = this._axisCoord(axis, dataX); let best = -1; let bestDist = Infinity; - const limit = Math.min(cpu.x.length, g.n || cpu.x.length); + const limit = this._cpuScanLimit(g, cpu.x.length); for (let i = 0; i < limit; i++) { + if (this._cpuRowHidden(g, i)) continue; const starts = g._transitionPrevXValues; const progress = g._transitionPositionProgress; const xEncoded = starts && Number.isFinite(progress) @@ -8753,11 +8778,12 @@ export class ChartView { const xMeta = cpu.xMeta || g.xMeta; const yMeta = cpu.yMeta || g.yMeta; const progress = g._transitionPositionProgress; - const limit = Math.min(cpu.x.length, cpu.y.length, g.n || cpu.x.length); + const limit = this._cpuScanLimit(g, cpu.x.length, cpu.y.length); const geom = this._polarGeometry(); let best = -1; let bestDist = Infinity; for (let i = 0; i < limit; i++) { + if (this._cpuRowHidden(g, i)) continue; const xEncoded = g._transitionPrevXValues && Number.isFinite(progress) ? g._transitionPrevXValues[i] + (cpu.x[i] - g._transitionPrevXValues[i]) * progress : cpu.x[i]; @@ -8893,8 +8919,11 @@ export class ChartView { const cpu = g._cpu; const horizontal = g.orientation === 1; const geom = this._polarGeometry(); - const limit = Math.min(cpu.x.length, cpu.y.length, g.n || cpu.x.length); + const limit = this._cpuScanLimit(g, cpu.x.length, cpu.y.length); for (let i = 0; i < limit; i++) { + // Categorical bars filter through `_filterScatterRows` too (§10), so a + // hidden bar's footprint must not answer hover either. + if (this._cpuRowHidden(g, i)) continue; const x = this._decodeValue(cpu.x, cpu.xMeta, i); const y = this._decodeValue(cpu.y, cpu.yMeta, i); const value0 = g.value0Mode === 1 && cpu.value0 diff --git a/python/xy/_figure.py b/python/xy/_figure.py index 3f94bb5e6..61bffe32f 100644 --- a/python/xy/_figure.py +++ b/python/xy/_figure.py @@ -1234,9 +1234,9 @@ def _is_category_like(values: Any) -> bool: @staticmethod def _category_axis_labels(values: Any, axis: str) -> list[str]: - if hasattr(values, "to_numpy"): - values = values.to_numpy() - arr = np.asarray(values) + # Bare pyarrow string/dictionary/chunked arrays need the copying + # conversion here; the plain `to_numpy()` raised ArrowInvalid. + arr = columns.label_ndarray(values) if arr.ndim != 1: raise ValueError(f"{axis} categories must be 1-D, got shape {arr.shape}") if arr.dtype.kind == "U": @@ -1664,6 +1664,57 @@ def _axis_kind(self, axis_id: str) -> str: return "time" return "linear" + # Trace kinds whose emitters route rows through `_log_visible_mask` + # (`_payload.py`) and therefore drop non-positive coordinates on a log + # axis. The rectangle/segment families ship every row and let the client + # apply the axis's `nonpositive` policy per endpoint, so nothing is lost + # there and nothing to report. + _LOG_DROPPING_KINDS = frozenset({"scatter", "line", "area", "error_band"}) + + def _warn_log_nonpositive_drop(self, axis_id: str) -> None: + """Log is undefined at zero and below, so those rows are not drawn. + + Dropping them is allowed but must never be silent (§28): report the + axis, how many rows went, and the two ways out. An explicit + `nonpositive=` on the axis is the user stating the policy and + silences this (the caller checks it). Zone maps keep the all-positive + case O(chunks); the O(n) count runs only on a column that provably + holds a value <= 0 (`min` ignores NaN and ±inf, which the finiteness + pass drops on every axis regardless). + """ + dropped = 0 + total = 0 + for t in self.traces: + if t.kind not in self._LOG_DROPPING_KINDS: + continue + cols = self._range_columns(t, axis_id) + if not cols: + continue + total += t.n_points + if not any(col.min <= 0 for col in cols): + continue + # One mask per trace: area rows fail on `y` and `base` together + # and must count once. + rejected = np.zeros(t.n_points, dtype=bool) + for col in cols: + values = col.values + if len(values) == len(rejected): + rejected |= values <= 0 + dropped += int(np.count_nonzero(rejected)) + if not dropped: + return + which = self._axis_dim(axis_id) + warnings.warn( + f"{axis_id} axis is log-scaled and {dropped} of {total} points have " + "non-positive coordinates on it (log is undefined there), so they " + f"are not drawn. Pass xy.{which}_axis(type_='log', " + "nonpositive='clip') or nonpositive='mask' to state that policy " + "explicitly and silence this warning, or type_='symlog' to show " + "zero and negative values.", + RuntimeWarning, + stacklevel=4, + ) + def _axis_spec(self, axis_id: str, range_: tuple[float, float]) -> dict[str, Any]: axis = self._axis_dim(axis_id) opts = self.axis_options.get(axis_id, {}) @@ -1741,8 +1792,11 @@ def _axis_spec(self, axis_id: str, range_: tuple[float, float]) -> dict[str, Any spec["scale"] = scale if scale == "symlog": spec["constant"] = opts.get("constant") or 1.0 - if scale == "log" and opts.get("nonpositive") is not None: - spec["nonpositive"] = opts["nonpositive"] + if scale == "log": + if opts.get("nonpositive") is not None: + spec["nonpositive"] = opts["nonpositive"] + else: + self._warn_log_nonpositive_drop(axis_id) if opts.get("reverse"): spec["reverse"] = True if opts.get("domain") is not None: diff --git a/python/xy/_payload.py b/python/xy/_payload.py index a71894dbf..eba717d10 100644 --- a/python/xy/_payload.py +++ b/python/xy/_payload.py @@ -493,16 +493,36 @@ def _base_entry( @staticmethod def _finite_sel(t: Trace, xv: np.ndarray, yv: np.ndarray) -> np.ndarray | None: - """Indices where both x and y are finite, or None if nothing to drop. + """Indices where x, y, and every continuous channel are finite, or + None if nothing to drop. Non-finite (NaN or ±inf) never reaches a vertex buffer — it silently corrupts primitives, driver-dependently (§19). Zone maps count both as - null, so we only scan when a null is present. Canonical keeps every row; - real gap semantics (segment index list) arrive with validity bitmaps. + null for x/y, so those are scanned only when a null is present. + + A continuous color/size value that is NaN or ±inf has no place on its + ramp either: the normalizers floor every non-finite input, so such a + point used to draw in the domain-minimum color (+inf included). A mark + whose color is undefined is not drawn — matplotlib's transparent "bad" + color — and the same rows leave the pick/selection mapping, exactly as + an x/y NaN does. Channels carry no zone maps, so this is one + allocation-free native scan per continuous channel per build — the + same pass `_rect_finite_sel` already pays for the rectangle family; + `valid_indices_f64` allocates row ids only when a row is rejected. + Canonical keeps every row; real gap semantics (segment index list) + arrive with validity bitmaps. """ - if not (t.x.zone.null_count or t.y.zone.null_count): + candidates = [values for col, values in ((t.x, xv), (t.y, yv)) if col.zone.null_count] + for channel in (t.color_ch, t.size_ch): + if channel is None or channel.mode != "continuous" or channel.values is None: + continue + # A streaming append can leave a channel momentarily shorter than + # the geometry; never index geometry with a foreign-length mask. + if len(channel.values) == len(xv): + candidates.append(channel.values) + if not candidates: return None - return np.flatnonzero(np.isfinite(xv) & np.isfinite(yv)) + return kernels.valid_indices_f64(tuple(candidates)) def _visible_mask_needed( self, diff --git a/python/xy/_pdf.py b/python/xy/_pdf.py index c4dc813ec..d18e7b12c 100644 --- a/python/xy/_pdf.py +++ b/python/xy/_pdf.py @@ -17,12 +17,16 @@ (``fill-opacity``/``stroke-opacity``/``opacity`` and rgba() color alpha) become deduplicated ExtGStates (/ca /CA). The generator only ever emits the default nonzero winding rule, so even-odd variants are never produced. -- Text stays text: BT/Tf/Tm/Tj/ET with the base-14 Helvetica family - (weight >= 600 selects Helvetica-Bold) in WinAnsiEncoding, using the - standard AFM width tables so ``text-anchor="middle"/"end"`` offsets come - from real metrics. Characters outside WinAnsi are replaced with "?" - (``cp1252`` + ``errors="replace"``) — a deterministic, locale-independent - substitution policy. +- Text stays text: BT/Tf/Tm/Tj/ET with the base-14 fonts in WinAnsiEncoding. + ``font-family`` selects the family (a generic ``serif`` -> Times, + ``monospace`` -> Courier, everything else -> Helvetica; `_base_family` holds + the table, spec/api/export.md §9 documents it), weight >= 600 the bold face + and ``font-style: italic|oblique`` the italic/oblique face. ``letter-spacing`` + becomes the ``Tc`` character-spacing operator and ``opacity`` folds into the + text's ExtGState. The selected face's standard AFM width table makes + ``text-anchor="middle"/"end"`` offsets come from real metrics. Characters + outside WinAnsi are replaced with "?" (``cp1252`` + ``errors="replace"``) — + a deterministic, locale-independent substitution policy. - ```` becomes an axial shading (/ShadingType 2; exponential function for 2 stops, stitching for more) painted inside the gradient geometry's clip; per-stop alpha becomes a luminosity soft mask. @@ -65,8 +69,13 @@ def _unsupported(what: str) -> NoReturn: # --------------------------------------------------------------------------- -# Helvetica metrics (AFM widths for WinAnsi codes 32..255, per mille) +# Base-14 metrics (AFM widths for WinAnsi codes 32..255, per mille) # --------------------------------------------------------------------------- +# Generated from the Adobe core-14 AFM files (the copies matplotlib ships in +# mpl-data/fonts/pdfcorefonts). WinAnsi codes with no glyph (0x7F and the five +# undefined 0x8x/0x9x slots) take the bullet width, as Acrobat does. The +# Oblique faces share their upright face's advances, so they carry no table +# of their own, and every Courier face is a uniform 600. # fmt: off _HELV = ( @@ -101,12 +110,171 @@ def _unsupported(what: str) -> NoReturn: 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 584, 611, 611, 611, 611, 611, 556, 611, 556, ) +_TIMES = ( + 250, 333, 408, 500, 500, 833, 778, 180, 333, 333, 500, 564, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 564, 564, 564, 444, + 921, 722, 667, 667, 722, 611, 556, 722, 722, 333, 389, 722, 611, 889, 722, 722, + 556, 722, 667, 556, 611, 722, 722, 944, 722, 722, 611, 333, 278, 333, 469, 500, + 333, 444, 500, 444, 500, 444, 333, 500, 500, 278, 278, 500, 278, 778, 500, 500, + 500, 500, 333, 389, 278, 500, 500, 722, 500, 500, 444, 480, 200, 480, 541, 350, + 500, 350, 333, 500, 444, 1000, 500, 500, 333, 1000, 556, 333, 889, 350, 611, 350, + 350, 333, 333, 444, 444, 350, 500, 1000, 333, 980, 389, 333, 722, 350, 444, 722, + 250, 333, 500, 500, 500, 500, 200, 500, 333, 760, 276, 500, 564, 333, 760, 333, + 400, 564, 300, 300, 333, 500, 453, 250, 333, 300, 310, 500, 750, 750, 750, 444, + 722, 722, 722, 722, 722, 722, 889, 667, 611, 611, 611, 611, 333, 333, 333, 333, + 722, 722, 722, 722, 722, 722, 722, 564, 722, 722, 722, 722, 722, 722, 556, 500, + 444, 444, 444, 444, 444, 444, 667, 444, 444, 444, 444, 444, 278, 278, 278, 278, + 500, 500, 500, 500, 500, 500, 500, 564, 500, 500, 500, 500, 500, 500, 500, 500, +) +_TIMES_BOLD = ( + 250, 333, 555, 500, 500, 1000, 833, 278, 333, 333, 500, 570, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, + 930, 722, 667, 722, 722, 667, 611, 778, 778, 389, 500, 778, 667, 944, 722, 778, + 611, 778, 722, 556, 667, 722, 722, 1000, 722, 722, 667, 333, 278, 333, 581, 500, + 333, 500, 556, 444, 556, 444, 333, 500, 556, 278, 333, 556, 278, 833, 556, 500, + 556, 556, 444, 389, 333, 556, 500, 722, 500, 500, 444, 394, 220, 394, 520, 350, + 500, 350, 333, 500, 500, 1000, 500, 500, 333, 1000, 556, 333, 1000, 350, 667, 350, + 350, 333, 333, 500, 500, 350, 500, 1000, 333, 1000, 389, 333, 722, 350, 444, 722, + 250, 333, 500, 500, 500, 500, 220, 500, 333, 747, 300, 500, 570, 333, 747, 333, + 400, 570, 300, 300, 333, 556, 540, 250, 333, 300, 330, 500, 750, 750, 750, 500, + 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 389, 389, 389, 389, + 722, 722, 778, 778, 778, 778, 778, 570, 778, 722, 722, 722, 722, 722, 611, 556, + 500, 500, 500, 500, 500, 500, 722, 444, 444, 444, 444, 444, 278, 278, 278, 278, + 500, 556, 500, 500, 500, 500, 500, 570, 500, 556, 556, 556, 556, 500, 556, 500, +) +_TIMES_ITALIC = ( + 250, 333, 420, 500, 500, 833, 778, 214, 333, 333, 500, 675, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 675, 675, 675, 500, + 920, 611, 611, 667, 722, 611, 611, 722, 722, 333, 444, 667, 556, 833, 667, 722, + 611, 722, 611, 500, 556, 722, 611, 833, 611, 556, 556, 389, 278, 389, 422, 500, + 333, 500, 500, 444, 500, 444, 278, 500, 500, 278, 278, 444, 278, 722, 500, 500, + 500, 500, 389, 389, 278, 500, 444, 667, 444, 444, 389, 400, 275, 400, 541, 350, + 500, 350, 333, 500, 556, 889, 500, 500, 333, 1000, 500, 333, 944, 350, 556, 350, + 350, 333, 333, 556, 556, 350, 500, 889, 333, 980, 389, 333, 667, 350, 389, 556, + 250, 389, 500, 500, 500, 500, 275, 500, 333, 760, 276, 500, 675, 333, 760, 333, + 400, 675, 300, 300, 333, 500, 523, 250, 333, 300, 310, 500, 750, 750, 750, 500, + 611, 611, 611, 611, 611, 611, 889, 667, 611, 611, 611, 611, 333, 333, 333, 333, + 722, 667, 722, 722, 722, 722, 722, 675, 722, 722, 722, 722, 722, 556, 611, 500, + 500, 500, 500, 500, 500, 500, 667, 444, 444, 444, 444, 444, 278, 278, 278, 278, + 500, 500, 500, 500, 500, 500, 500, 675, 500, 500, 500, 500, 500, 444, 500, 444, +) +_TIMES_BOLD_ITALIC = ( + 250, 389, 555, 500, 500, 833, 778, 278, 333, 333, 500, 570, 250, 333, 250, 278, + 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, + 832, 667, 667, 667, 722, 667, 667, 722, 778, 389, 500, 667, 611, 889, 722, 722, + 611, 722, 667, 556, 611, 722, 667, 889, 667, 611, 611, 333, 278, 333, 570, 500, + 333, 500, 500, 444, 500, 444, 333, 500, 556, 278, 278, 500, 278, 778, 556, 500, + 500, 500, 389, 389, 278, 556, 444, 667, 500, 444, 389, 348, 220, 348, 570, 350, + 500, 350, 333, 500, 500, 1000, 500, 500, 333, 1000, 556, 333, 944, 350, 611, 350, + 350, 333, 333, 500, 500, 350, 500, 1000, 333, 1000, 389, 333, 722, 350, 389, 611, + 250, 389, 500, 500, 500, 500, 220, 500, 333, 747, 266, 500, 606, 333, 747, 333, + 400, 570, 300, 300, 333, 576, 500, 250, 333, 300, 300, 500, 750, 750, 750, 500, + 667, 667, 667, 667, 667, 667, 944, 667, 667, 667, 667, 667, 389, 389, 389, 389, + 722, 722, 722, 722, 722, 722, 722, 570, 722, 722, 722, 722, 722, 611, 611, 500, + 500, 500, 500, 500, 500, 500, 722, 444, 444, 444, 444, 444, 278, 278, 278, 278, + 500, 556, 500, 500, 500, 500, 500, 570, 500, 556, 556, 556, 556, 444, 500, 444, +) # fmt: on +_COURIER = (600,) * 224 + +#: AFM advance table per base-14 font name. +_WIDTHS: dict[str, tuple[int, ...]] = { + "Helvetica": _HELV, + "Helvetica-Bold": _HELV_BOLD, + "Helvetica-Oblique": _HELV, + "Helvetica-BoldOblique": _HELV_BOLD, + "Times-Roman": _TIMES, + "Times-Bold": _TIMES_BOLD, + "Times-Italic": _TIMES_ITALIC, + "Times-BoldItalic": _TIMES_BOLD_ITALIC, + "Courier": _COURIER, + "Courier-Bold": _COURIER, + "Courier-Oblique": _COURIER, + "Courier-BoldOblique": _COURIER, +} +#: The four faces of each base-14 family: (regular, bold, italic, bold-italic). +_BASE14: dict[str, tuple[str, str, str, str]] = { + "Helvetica": ("Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique"), + "Times": ("Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic"), + "Courier": ("Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique"), +} -def _text_width_px(data: bytes, size: float, bold: bool) -> float: - """String advance in px for WinAnsi bytes at `size` px, from AFM widths.""" - table = _HELV_BOLD if bold else _HELV +#: CSS `font-family` names that select a base-14 family. The writer embeds no +#: fonts (stdlib + numpy only), so a family is a *substitution*, not the face +#: the browser draws: the CSS generic families and the base-14 names (plus +#: their ubiquitous Windows aliases) are the only names whose intent is +#: unambiguous. Anything else falls back to Helvetica, the writer's default. +#: spec/api/export.md §9 publishes this table; keep the two in step. +_FAMILY_MAP: dict[str, str] = { + "serif": "Times", + "ui-serif": "Times", + "times": "Times", + "times new roman": "Times", + "monospace": "Courier", + "ui-monospace": "Courier", + "courier": "Courier", + "courier new": "Courier", + "sans-serif": "Helvetica", + "ui-sans-serif": "Helvetica", + "system-ui": "Helvetica", + "helvetica": "Helvetica", + "arial": "Helvetica", +} + + +def _base_family(value: Optional[str], default: str) -> str: + """Resolve a CSS `font-family` stack onto a base-14 family name. + + The stack is walked in author order and the first recognised name wins + (`"Georgia", serif` -> Times: the generic fallback is the author's own + statement of what the face is). A stack naming nothing recognised + resolves to Helvetica rather than raising — the value is an author's + font preference, not generator drift, and refusing the export over it + would hide the whole chart behind an unavailable typeface. + """ + if value is None: + return default + for name in value.split(","): + family = _FAMILY_MAP.get(name.strip().strip("'\"").strip().lower()) + if family is not None: + return family + return "Helvetica" + + +def _italic(value: Optional[str], default: bool) -> bool: + """`font-style` -> whether the slanted face is wanted. `oblique` may carry + an angle (`oblique 10deg`); the base-14 set has one slant, so any angle + selects it.""" + if value is None: + return default + v = value.strip().lower() + if v == "normal": + return False + if v == "italic" or v == "oblique" or v.startswith("oblique "): + return True + _unsupported(f"font-style {value!r}") + + +def _letter_spacing(value: Optional[str], font_size: float) -> float: + """`letter-spacing` in CSS px. The SVG writer emits `normal`, a unitless px + number, or the author's own CSS length; `em` is relative to the element's + resolved font size and `pt` is converted at the writer's 0.75 pt/px.""" + if value is None: + return 0.0 + v = value.strip().lower() + if v == "normal": + return 0.0 + for suffix, scale in (("px", 1.0), ("em", font_size), ("pt", 1.0 / _PX_TO_PT)): + if v.endswith(suffix): + return _float(v[: -len(suffix)], 0.0, "letter-spacing") * scale + return _float(v, 0.0, "letter-spacing") + + +def _text_width_px(data: bytes, size: float, font: str) -> float: + """String advance in px for WinAnsi bytes at `size` px, from the AFM widths + of base-14 font `font`.""" + table = _WIDTHS[font] return size * sum(table[b - 32] for b in data if b >= 32) / 1000.0 @@ -202,7 +370,20 @@ def _rgba(css: str) -> tuple[float, float, float, float]: "polyline": frozenset({"points"}) | _PAINT_ATTRS, "polygon": frozenset({"points"}) | _PAINT_ATTRS, "text": frozenset( - {"x", "y", "transform", "text-anchor", "font-size", "font-weight", "fill", "fill-opacity"} + { + "x", + "y", + "transform", + "text-anchor", + "font-size", + "font-weight", + "font-style", + "font-family", + "letter-spacing", + "opacity", + "fill", + "fill-opacity", + } ), "tspan": frozenset({"x", "y"}), "image": frozenset({"x", "y", "width", "height", "preserveAspectRatio", "style", "href"}), @@ -564,7 +745,16 @@ def serialize(self) -> bytes: class _State: """Inheritable presentation state (override semantics, like CSS).""" - __slots__ = ("fill", "fill_opacity", "font_size", "font_weight", "opacity", "stroke_opacity") + __slots__ = ( + "fill", + "fill_opacity", + "font_family", + "font_italic", + "font_size", + "font_weight", + "opacity", + "stroke_opacity", + ) def __init__(self) -> None: self.fill = "#000000" @@ -573,6 +763,8 @@ def __init__(self) -> None: self.opacity = 1.0 self.font_size = _DEFAULT_FONT_SIZE self.font_weight = 400.0 + self.font_family = "Helvetica" + self.font_italic = False def child(self) -> "_State": out = _State.__new__(_State) @@ -678,8 +870,8 @@ def _set_stroke_params( # -- resource registration --------------------------------------------- - def _font(self, bold: bool) -> str: - base = "Helvetica-Bold" if bold else "Helvetica" + def _font(self, base: str) -> str: + """Resource name for base-14 font `base`, registering it on first use.""" if base not in self.fonts: num = self.pdf.reserve() name = f"F{len(self.fonts) + 1}" @@ -1063,6 +1255,10 @@ def _render_text(self, el: ET.Element, state: _State) -> None: _check_attrs(el, "text", _ALLOWED_ATTRS["text"]) font_size = _float(el.get("font-size"), state.font_size, "font-size") bold = _weight(el.get("font-weight"), state.font_weight) >= 600 + italic = _italic(el.get("font-style"), state.font_italic) + family = _base_family(el.get("font-family"), state.font_family) + font_base = _BASE14[family][(2 if italic else 0) + (1 if bold else 0)] + spacing = _letter_spacing(el.get("letter-spacing"), font_size) anchor = el.get("text-anchor", "start") if anchor not in ("start", "middle", "end"): _unsupported(f"text-anchor {anchor!r}") @@ -1070,8 +1266,11 @@ def _render_text(self, el: ET.Element, state: _State) -> None: if fill is None or fill[0] != "solid": _unsupported("text fill paint") red, green, blue, alpha = fill[1] + # Whole-element `opacity` and the fill channel multiply, as they do for + # shapes (`_render_shape`); both land in the one deduplicated ExtGState. ca = ( state.opacity + * _float(el.get("opacity"), 1.0, "opacity") * _float(el.get("fill-opacity"), state.fill_opacity, "fill-opacity") * alpha ) @@ -1110,7 +1309,7 @@ def _render_text(self, el: ET.Element, state: _State) -> None: (_float(el.get("x"), 0.0, "x"), _float(el.get("y"), 0.0, "y"), el.text or "") ) - font_name = self._font(bold) + font_name = self._font(font_base) theta = math.radians(angle) cos_t, sin_t = math.cos(theta), math.sin(theta) for x, y, s in runs: @@ -1124,12 +1323,22 @@ def _render_text(self, el: ET.Element, state: _State) -> None: cx + cos_t * (x - cx) - sin_t * (y - cy), cy + sin_t * (x - cx) + cos_t * (y - cy), ) - width = _text_width_px(data, font_size, bold) + # Browsers add letter-spacing after every character, the last one + # included, and anchor on that full advance; Tc does the same. + width = _text_width_px(data, font_size, font_base) + spacing * len(data) dx = -width / 2.0 if anchor == "middle" else (-width if anchor == "end" else 0.0) tx = x + dx * cos_t ty = y + dx * sin_t self._set_gs(ca, ca) self._set_fill_rgb((red, green, blue)) + # Tc is graphics state (saved by q, restored by Q) and outlives the + # BT/ET block, so a spaced run must be followed by an explicit reset + # before the next plain one. Tc is in unscaled text-space units and + # Tm is a pure rotation here, so the px value passes through as-is, + # exactly like the Tf size. Untouched when nothing ever set it, so + # unstyled documents keep their bytes. + if spacing or self._cache.get("Tc"): + self._set("Tc", round(spacing, 4), f"{_f(spacing)} Tc") # Tm un-flips the top-level y flip so glyphs render upright; the # rotation is the SVG angle (clockwise in screen space). self.ops.append("BT") @@ -1272,6 +1481,9 @@ def run(self, root: ET.Element) -> bytes: state = _State() state.font_size = _float(root.get("font-size"), _DEFAULT_FONT_SIZE, "font-size") + # The root's system-ui stack resolves to Helvetica; an author root + # family (facet composition, future themes) inherits like any other. + state.font_family = _base_family(root.get("font-family"), "Helvetica") page_w = width * _PX_TO_PT page_h = height * _PX_TO_PT diff --git a/python/xy/_svg.py b/python/xy/_svg.py index 7d4301aeb..5b158cfaa 100644 --- a/python/xy/_svg.py +++ b/python/xy/_svg.py @@ -33,21 +33,51 @@ from ._arrowgeom import arrow_shapes as _arrow_shapes from .config import DEFAULT_PALETTE, polar_bar_segments +#: Code points XML 1.0 §2.2 excludes from the ``Char`` production: the C0 +#: controls other than tab, newline and carriage return, the surrogate range, +#: and the two non-characters U+FFFE/U+FFFF. No escape can represent them — a +#: character reference to U+0001 is itself not well-formed — so the writer +#: drops them (`escape`). Everything else, including DEL and the C1 range, is +#: legal and passes through untouched. +_XML_ILLEGAL: dict[int, None] = {c: None for c in range(0x20) if c not in (0x09, 0x0A, 0x0D)} +_XML_ILLEGAL.update(dict.fromkeys(range(0xD800, 0xE000))) +_XML_ILLEGAL.update({0xFFFE: None, 0xFFFF: None}) + def escape(data: str, entities: dict[str, str] | None = None) -> str: - """Escape ``&``, ``<`` and ``>`` in a string of data. + """Escape ``&``, ``<`` and ``>`` in a string of data, and drop the code + points XML cannot carry at all. - Byte-for-byte equivalent to :func:`xml.sax.saxutils.escape`, vendored so a - static export does not import it. That one function costs ~7.5 ms of cold - start: ``xml.sax.saxutils`` pulls in ``urllib.request``, which pulls in + Equivalent to :func:`xml.sax.saxutils.escape` on every string the stdlib + can produce a well-formed document from, vendored so a static export does + not import it. That one function costs ~7.5 ms of cold start: + ``xml.sax.saxutils`` pulls in ``urllib.request``, which pulls in ``http.client``, ``ssl``, ``socket`` and the whole ``email`` package — 35+ modules for three ``str.replace`` calls. Nothing else in xy needs them, and a cold ``to_png`` at 10M points spent more time on that import than on binning ten million points. - ``tests/test_svg_escape.py`` differentially fuzzes this against the stdlib - so it cannot drift. + Where it deliberately differs: the stdlib passes C0 control characters + through, and an ``a\x01b`` legend name or tick label then yields SVG that + no XML parser accepts and a PDF export that refuses the document, while + the HTML and PNG paths (which are not XML) succeed. Those code points are + *removed* — not replaced with U+FFFD — because a browser renders a control + character as nothing, so dropping it keeps the vector text visually in + step with the live chart (spec/api/export.md §2). Tab, newline and + carriage return are legal XML and are kept; every raw text sink in this + writer (labels, titles, legend names, annotation text, attribute values + via `_escape_attr`) routes through here, so this is the single choke point. + + ``tests/test_svg_escape.py`` differentially fuzzes the escaping against the + stdlib so it cannot drift; ``tests/test_export_text_safety.py`` pins the + control-character rule. """ + # `isprintable` is a C-level scan that is False for every C0 control (and + # for a few legal characters such as no-break space, which merely take the + # slower path); it keeps the hot path — thousands of tick labels — at the + # cost of the three replaces alone. + if not data.isprintable(): + data = data.translate(_XML_ILLEGAL) # must do ampersand first data = data.replace("&", "&") data = data.replace(">", ">") @@ -542,12 +572,26 @@ def _angular_ticks(lo: float, hi: float, unit: str, target: int = 6) -> tuple[li def _log_ticks(lo: float, hi: float, target: int = 6) -> tuple[list[float], list[float], float]: - """Returns (ticks, labeled_ticks, step).""" + """Returns (ticks, labeled_ticks, step). Mirrors `logTicks` in js/src/30_ticks.ts. + + The decade ladder is multiplicative: inside one decade it has at most the + 2 and 5 mantissas to offer, and a window like 0.3..0.35 or 100..110 holds + none of them, so a log axis zoomed past ~3x exported with no ticks at all. + With fewer than two decades in view the ladder cannot describe the window; + tick it linearly across the span instead (renderer-architecture §6.1), with + the nice linear step so `_fmt_linear` shares one decimal count along the + axis and every tick labelled.""" a, b = min(lo, hi), max(lo, hi) if a <= 0 or b <= 0 or not (np.isfinite(a) and np.isfinite(b)): return [], [], 1.0 e0 = int(np.floor(np.log10(a))) e1 = int(np.ceil(np.log10(b))) + decades_in_view = sum( + 1 for e in range(e0, e1 + 1) if a * (1 - 1e-12) <= 10.0**e <= b * (1 + 1e-12) + ) + if decades_in_view < 2: + ticks, step = _linear_ticks(a, b, target) + return ticks, ticks, step mults = (1, 2, 5) if max(1, e1 - e0) <= max(2, target) else (1,) label_every = max(1, int(np.ceil((e1 - e0 + 1) / max(1, target)))) out: list[float] = [] @@ -743,12 +787,19 @@ def _fmt_log(v: float) -> str: Decade ticks are multiplicative, so the linear formatter's step-derived precision rounds every decade under 1.0 to a bare "0" — - 0.001 and 0.01 became two identical, wrong labels.""" + 0.001 and 0.01 became two identical, wrong labels. Uses the fewest + decimals (up to 8) that reproduce the value: identical to the old + magnitude rule on the 1/2/5 ladder, and distinct labels for the + within-decade linear ticks a log colorbar now carries (§6.1), which the + magnitude rule collapsed to "2 2 2 3 3 3" for a 2..3 range. + Mirrors `fmtLog` in js/src/30_ticks.ts.""" av = abs(v) if av >= 1e6 or (av != 0 and av < 1e-4): return f"{v:.1e}".replace("e+0", "e").replace("e-0", "e-").replace("e+", "e") - dec = max(0, int(np.ceil(-np.log10(av)))) if av and av < 1 else 0 - return f"{v:.{min(dec, 8)}f}" + dec = 0 + while dec < 8 and abs(round(av, dec) - av) > av * 1e-9: + dec += 1 + return f"{v:.{dec}f}" # Everything a formatted number can carry that is not part of its value: @@ -820,10 +871,13 @@ def _fmt_axis(axis: dict[str, Any], v: float, step: float) -> str: return _fmt_time_spec(v, axis.get("format")) or _fmt_time(v, step) formatted = _fmt_number_spec(v, axis.get("format")) # A fixed-decimal spec collapses sub-unit decades ("0.001" at `.0f`), and so - # does the linear fallback; the magnitude-derived label is the useful one - # either way. Mirrors `fmtAxis`. + # does the linear fallback under the ladder's step of 1; the value-derived + # label is the useful one either way — except on the within-decade linear + # tick set (renderer-architecture §6.1), whose sub-unit step gives + # `_fmt_linear` the one shared decimal count an axis reads by ("0.30, + # 0.31, ...") where the per-value `_fmt_log` goes ragged. Mirrors `fmtAxis`. if axis.get("scale") == "log" and 0 < v < 1 and _collapsed_to_zero(formatted): - return _fmt_log(v) + return _fmt_linear(v, step) if 0 < step < 1 else _fmt_log(v) return formatted if formatted is not None else _fmt_linear(v, step) diff --git a/python/xy/channel.py b/python/xy/channel.py index 12639d07b..d4ed46a30 100644 --- a/python/xy/channel.py +++ b/python/xy/channel.py @@ -204,6 +204,11 @@ def handle_message( if not isinstance(content, dict): return None kind = content.get("type") + if not isinstance(kind, str): + # §1: `type` is the one field read before any coercion, so it must be + # safe to read — a list or dict here raised from the set membership + # test below instead of counting as an unknown kind. + return None if kind in {"animation_start", "animation_end"}: callback = ( callbacks.on_animation_start @@ -284,7 +289,10 @@ def handle_message( index, drill_seq, ) - except (TypeError, ValueError): + except (TypeError, ValueError, IndexError): + # IndexError is defense in depth: `pick` bounds the index against + # the readable rows, but a kind whose columns disagree with its + # advertised count must degrade to `row: null`, never raise. return None if row is not None and callbacks.on_hover is not None: callbacks.on_hover(row) @@ -299,7 +307,7 @@ def handle_message( index = _integer_id(content.get("index", -1), "index") drill_seq = None if dseq is None else _integer_id(dseq, "drill_seq") row = fig.pick(trace_id, index, drill_seq) - except (TypeError, ValueError): + except (TypeError, ValueError, IndexError): return None if row is not None and callbacks.on_click is not None: callbacks.on_click(row) @@ -307,18 +315,14 @@ def handle_message( if kind == "view_change": try: raw_ranges = content.get("ranges") - ranges: dict[str, list[float]] = {} + pairs: dict[str, Any] = {} if isinstance(raw_ranges, dict): - for axis_id, raw_range in raw_ranges.items(): - if axis_id not in fig.axis_options: - continue - if not isinstance(raw_range, (tuple, list)) or len(raw_range) != 2: - raise ValueError("invalid view range") - lo, hi = float(raw_range[0]), float(raw_range[1]) - if not math.isfinite(lo) or not math.isfinite(hi) or lo == hi: - raise ValueError("invalid view range") - ranges[axis_id] = [lo, hi] - if not ranges: + pairs = { + axis_id: pair + for axis_id, pair in raw_ranges.items() + if axis_id in fig.axis_options + } + if not pairs: x0, x1, y0, y1 = normalize_window( content["x0"], content["x1"], @@ -326,7 +330,20 @@ def handle_message( content["y1"], require_area=False, ) - ranges = {"x": [x0, x1], "y": [y0, y1]} + pairs = {"x": [x0, x1], "y": [y0, y1]} + # Both shapes meet the rules `_validated_state_ranges` applies to a + # state patch — finite, ordered, non-zero span — so the durable + # cache this feeds (view-state.md §5.1) always round-trips back + # through `state_patch_message`. A flipped pair is reordered; a + # zero-span pair rejects the whole event. + ranges: dict[str, list[float]] = {} + for axis_id, raw_range in pairs.items(): + if not isinstance(raw_range, (tuple, list)) or len(raw_range) != 2: + raise ValueError("invalid view range") + lo, hi = float(raw_range[0]), float(raw_range[1]) + if not math.isfinite(lo) or not math.isfinite(hi) or lo == hi: + raise ValueError("invalid view range") + ranges[axis_id] = [lo, hi] if lo < hi else [hi, lo] x_range = ranges.get("x") y_range = ranges.get("y") view = { diff --git a/python/xy/channels.py b/python/xy/channels.py index 323ed5e0e..c9564f680 100644 --- a/python/xy/channels.py +++ b/python/xy/channels.py @@ -500,8 +500,9 @@ def append_continuous(channel: Any, values: npt.NDArray[np.float64], label: str) Geometry columns already use a capacity-doubling buffer for streaming; channel arrays need the same contract. The domain expands monotonically so a newly appended value is not silently clamped to the old color/size scale. - Non-finite values remain valid channel inputs and are handled by the - existing normalization policy; they do not expand the domain. + Non-finite values remain valid channel inputs — the emitters skip those + rows at build (`_payload._finite_sel`, §19) — and they do not expand the + domain. """ if channel.mode != "continuous" or channel.values is None: raise ValueError(f"{label} channel is not continuous") @@ -731,9 +732,13 @@ def resolve_size(size: Any, n: int, *, range_px: tuple[float, float] = (2.0, 18. def normalize_to_unit(values: npt.NDArray[np.float64], domain: tuple[float, float]) -> np.ndarray: """Map values to [0,1] over `domain` (for continuous color/size upload). + Non-finite (NaN, ±inf) → domain floor so it never poisons a vertex - (design dossier §19); the validity story tightens with real bitmaps - later.""" + (design dossier §19). That floor is a safety net, not a rendering: the + emitters exclude rows whose continuous color/size is non-finite before + shipping (`_payload._finite_sel`, `_figure._rect_finite_sel`), so on the + build path such a value is never drawn rather than drawn in the minimum + color. The validity story tightens with real bitmaps later.""" return kernels.normalize_f32(values, domain, nonfinite="zero") diff --git a/python/xy/columns.py b/python/xy/columns.py index 7d37a745c..4c45e2e89 100644 --- a/python/xy/columns.py +++ b/python/xy/columns.py @@ -510,6 +510,32 @@ def memory_report(self) -> dict[str, Any]: } +def _is_pyarrow(data: Any) -> bool: + """Detected by module name so xy itself never imports pyarrow.""" + return (type(data).__module__ or "").split(".", 1)[0] == "pyarrow" + + +def label_ndarray(values: Any) -> np.ndarray: + """Materialize a column-like as an ndarray for *label* work — categorical + axes and facet keys — where the values are strings, not f64 geometry. + + `to_numpy()` is the pandas/pyarrow common denominator, but pyarrow's + default is `zero_copy_only=True`, which only a null-free primitive numeric + array satisfies: a string, dictionary, chunked, or nullable Arrow array + raises `ArrowInvalid` instead of copying — the error that leaked out of + `xy.scatter(x=pa.array(["a", "b"]))` while the equivalent pandas + `string[pyarrow]` Series became a categorical axis. Labels need Python + objects regardless, so the copy is the price of the path, not a regression + (§29 counts copies on canonical f64 columns, which never come through + here). Nulls arrive as `None` and take the usual `(missing)` label. + """ + if _is_pyarrow(values) and hasattr(values, "to_numpy"): + return np.asarray(values.to_numpy(zero_copy_only=False)) + if hasattr(values, "to_numpy"): + values = values.to_numpy() + return np.asarray(values) + + def _arrow_to_numpy(data: Any) -> tuple[npt.NDArray[Any], int] | None: """Ingest a pyarrow Array/ChunkedArray, zero-copy when possible. @@ -529,7 +555,7 @@ def _arrow_to_numpy(data: Any) -> tuple[npt.NDArray[Any], int] | None: Returns None when `data` is not a pyarrow value. """ - if (type(data).__module__ or "").split(".", 1)[0] != "pyarrow": + if not _is_pyarrow(data): return None copies = 0 if hasattr(data, "combine_chunks"): # ChunkedArray diff --git a/python/xy/components.py b/python/xy/components.py index f365432da..c715b1b56 100644 --- a/python/xy/components.py +++ b/python/xy/components.py @@ -30,6 +30,7 @@ from __future__ import annotations +import copy import datetime as dt import hashlib import math @@ -38,7 +39,7 @@ import warnings from collections.abc import Callable, Mapping, Sequence from dataclasses import dataclass, field, replace -from functools import lru_cache +from functools import cache, lru_cache from os import PathLike from typing import Any, Literal, Optional, TypeAlias, Union @@ -184,7 +185,9 @@ class Mark(Component): """A data series inside a chart: one mark kind plus its data/encodings. Built by the mark constructors (`scatter`, `line`, `bar`, ...) rather - than directly; ``props`` carries the kind-specific options verbatim. + than directly; ``props`` carries the kind-specific options verbatim. A + hand-built Mark may leave ``props`` partial: at chart build the missing + keys take the kind's factory defaults (`_with_factory_defaults`). """ kind: str # chart mark registry key @@ -3779,7 +3782,7 @@ def figure(self) -> Figure: if self._figure is not None: return self._figure - marks = [c for c in self.children if isinstance(c, Mark)] + marks = [_with_factory_defaults(c) for c in self.children if isinstance(c, Mark)] annotations = [c for c in self.children if isinstance(c, Annotation)] axis_children = [c for c in self.children if isinstance(c, Axis)] for axis in axis_children: @@ -6351,6 +6354,63 @@ def _apply_callout_annotation(fig: Figure, annotation: Annotation) -> None: "violin": _apply_violin, } +# The factory that builds each built-in kind, keyed like `_MARK_APPLIERS`. +# `Mark` is a public dataclass, so a caller may construct `xy.Mark(kind=...)` +# by hand with a partial (or empty) `props`; the appliers index `m.props[...]` +# and leaked `KeyError: 'size'`. The factory signature is the one source of +# truth for a kind's defaults (chart-grammar rule G0: one implementation, one +# set of defaults), so a bare Mark borrows them from a no-argument factory +# call instead of a second, hand-copied table that would drift. +_MARK_FACTORIES: dict[str, Callable[..., Mark]] = { + "area": area, + "bar": bar, + "box": box, + "column": column, + "contour": contour, + "ecdf": ecdf, + "errorbar": errorbar, + "error_band": error_band, + "hexbin": hexbin, + "heatmap": heatmap, + "histogram": histogram, + "scatter": scatter, + "segments": segments, + "line": line, + "step": step, + "stairs": stairs, + "stem": stem, + "ribbon": ribbon, + "sankey": sankey, + "funnel": funnel, + "triangle_mesh": triangle_mesh, + "violin": violin, +} + + +@cache +def _factory_default_props(kind: str) -> Optional[Mapping[str, Any]]: + """The props a data-less factory call sets for `kind`, or None for a + plugin kind (plugins read `props.get`, see `_plugin_applier`).""" + factory = _MARK_FACTORIES.get(kind) + if factory is None: + return None + return dict(factory().props) + + +def _with_factory_defaults(m: Mark) -> Mark: + """A Mark whose `props` carry every key its factory would have set. + + Factory-built marks already do and pass through untouched; a hand-built + `xy.Mark` is completed with the factory defaults, explicit props winning. + Defaults are copied per mark (a `[]` links default must not be shared). + """ + defaults = _factory_default_props(m.kind) + if defaults is None or defaults.keys() <= m.props.keys(): + return m + props = {key: copy.deepcopy(value) for key, value in defaults.items()} + props.update(m.props) + return replace(m, props=props) + def _plugin_column(values: Any) -> Any: """A plugin's declared column, as canonical f64 when it is numeric. @@ -7108,11 +7168,17 @@ def sankey_chart( ("Equities", "Growth", 61000), ]) - Keyword arguments that belong to `xy.sankey` (``nodes``, ``colors``, - ``node_width``, ``link_opacity``, ``labels``, …) are forwarded there; - everything else (``width``, ``height``, ``title``, …) styles the chart. - The diagram lives in a unit box with a small margin, y inverted so flow - reads top-down like every other Sankey. + The first positional may equally be the mark itself, the way every + sibling ``*_chart`` accepts its mark — ``xy.sankey_chart(xy.sankey(links, + node_width=0.03))`` — or any other child (``xy.legend(...)``); links and + a mark build the same figure. Keyword arguments that belong to `xy.sankey` + (``nodes``, ``colors``, ``node_width``, ``link_opacity``, ``labels``, …) + are forwarded there when links are given positionally; beside an explicit + ``xy.sankey(...)`` child they would describe a second, ghost diagram, so + that mix is refused — set them on the mark. Everything else (``width``, + ``height``, ``title``, …) styles the chart. The diagram lives in a unit + box with a small margin, y inverted so flow reads top-down like every + other Sankey. """ mark_keys = ( "nodes", @@ -7126,11 +7192,43 @@ def sankey_chart( "label_size", ) mark_kwargs = {key: props.pop(key) for key in mark_keys if key in props} + rest: list[Component] = list(children) + if isinstance(links, Component): + # `sankey_chart(xy.sankey(...))` used to reach `list(links)` inside + # the factory and die with "'Mark' object is not iterable" — the one + # `*_chart` that rejected its own mark while its docstring said to + # prefer it. + rest.insert(0, links) + links = None + explicit = [c for c in rest if isinstance(c, Mark) and c.kind == "sankey"] + if links is not None: + lead: tuple[Component, ...] = (sankey(links, **mark_kwargs),) + elif explicit: + if mark_kwargs: + raise ValueError( + f"sankey_chart got {sorted(mark_kwargs)} alongside an explicit " + "xy.sankey(...) child; set these on the mark itself" + ) + lead = () + elif rest: + # Chrome-only children build a mark-free chart, like the sibling + # factories; sankey keywords without any links are refused rather + # than describing a diagram that has nothing to lay out. + if mark_kwargs: + raise ValueError( + f"sankey_chart got {sorted(mark_kwargs)} without links; pass the " + "links positionally or set these options on an xy.sankey(...) child" + ) + lead = () + else: + # `sankey_chart()` keeps its historical shape: an empty diagram that + # the layout refuses by name at figure build. + lead = (sankey(links, **mark_kwargs),) children = ( - sankey(links, **mark_kwargs), + *lead, x_axis(domain=(-0.09, 1.09), show=False), y_axis(domain=(-0.05, 1.05), reverse=True, show=False), - *children, + *rest, ) return Chart("sankey_chart", children, **props) diff --git a/python/xy/facets.py b/python/xy/facets.py index 69d2c5a67..8fffae923 100644 --- a/python/xy/facets.py +++ b/python/xy/facets.py @@ -15,7 +15,7 @@ import numpy as np -from . import channels, export +from . import channels, columns, export from ._png import encode as encode_png from ._png import png_truecolor from ._raster import render_raster @@ -83,23 +83,27 @@ def _facet_values(data: Any, by: Any) -> tuple[np.ndarray, list[str]]: (mixed/unsortable values) fall back to a single Python pass. Rows group by their `category_label` display string, matching categorical channels. """ + # A missing column is a ValueError, the same type (and message shape) every + # other column-name resolution in the API raises (`components._resolve`); + # a KeyError here made facet_chart the one place a typo'd name needed a + # different `except`. if isinstance(by, str): if isinstance(data, Mapping): if by not in data: - raise KeyError(f"facet column {by!r} not found in data") + raise ValueError(f"facet column {by!r} not found in data") raw = data[by] elif hasattr(data, "__getitem__"): try: raw = data[by] except Exception as exc: - raise KeyError(f"facet column {by!r} not found in data") from exc + raise ValueError(f"facet column {by!r} not found in data") from exc else: raise TypeError("facet_chart by= as a string requires mapping/table data") else: raw = by - if hasattr(raw, "to_numpy"): - raw = raw.to_numpy() - arr = np.asarray(raw) + # Label materialization, not f64 ingest: a pyarrow string/dictionary + # column needs the copying conversion (`columns.label_ndarray`). + arr = columns.label_ndarray(raw) if arr.ndim != 1: raise ValueError("facet_chart by= must resolve to a 1-D column") if arr.dtype == object: diff --git a/python/xy/interaction.py b/python/xy/interaction.py index 77fc39a6b..7690d78df 100644 --- a/python/xy/interaction.py +++ b/python/xy/interaction.py @@ -172,6 +172,23 @@ def legend_toggle( t._legend_vis_cache = None +def _pick_row_count(t: "Trace") -> int: + """Rows a pick may read: the readout columns' length, capped by `n_points`. + + `n_points` is the mark count the wire advertises, and for aggregate kinds + it is not the length of the columns `row_dict` indexes — a histogram or + hexbin advertises its sample count over a few dozen bin rows, an errorbar + its points over three segment endpoints each. An index must name both an + advertised mark and a readable row (§16: exact or nothing), so the bound + is the smaller of the two. Grid marks keep only the outer edges in x/y; + their readable rows are the cells. + """ + if t.grid_shape is not None: + rows, cols = t.grid_shape + return min(t.n_points, rows * cols) + return min(t.n_points, len(t.x)) + + def pick( fig: "Figure", trace_id: int, index: int, drill_seq: Optional[int] = None ) -> Optional[dict[str, Any]]: @@ -208,7 +225,7 @@ def pick( if idx < 0 or idx >= len(shipped_sel): return None idx = int(shipped_sel[idx]) - if idx < 0 or idx >= t.n_points: + if idx < 0 or idx >= _pick_row_count(t): return None return row_dict(fig, t, idx) @@ -291,7 +308,7 @@ def selection_rows( if max_rows is not None and len(rows) >= max_rows: return rows, len(rows) < total idx = int(raw_idx) - if 0 <= idx < t.n_points: + if 0 <= idx < _pick_row_count(t): rows.append(row_dict(fig, t, idx)) return rows, len(rows) < total diff --git a/python/xy/lod.py b/python/xy/lod.py index 48c0b7d2f..862160712 100644 --- a/python/xy/lod.py +++ b/python/xy/lod.py @@ -21,6 +21,7 @@ import math import numbers +import sys from dataclasses import dataclass from typing import Any, cast @@ -155,7 +156,10 @@ def normalize_window( raise ValueError("view window bounds must be finite") lo_x, hi_x = min(vals[0], vals[1]), max(vals[0], vals[1]) lo_y, hi_y = min(vals[2], vals[3]), max(vals[2], vals[3]) - if require_area and (lo_x == hi_x or lo_y == hi_y): + if require_area and (hi_x - lo_x < sys.float_info.min or hi_y - lo_y < sys.float_info.min): + # Zero and subnormal spans alike: everything downstream divides by the + # span (the drill ladder's level, the grid's cell width, the client's + # data->clip map), and a subnormal has no finite reciprocal in f64. raise ValueError("view window must have non-zero width and height") return lo_x, hi_x, lo_y, hi_y @@ -787,10 +791,24 @@ def aligned_window( return lo, hi if pad * span >= extent: return min(extent_lo, lo), max(extent_hi, hi) - level = max(0, math.ceil(math.log2(extent / (pad * span)))) - block = extent / (1 << level) - b0 = math.floor((lo - extent_lo) / block) - b1 = math.ceil((hi - extent_lo) / block) + ratio = extent / (pad * span) + if not math.isfinite(ratio): + # A span this far below the extent has no ladder rung — the quotient + # overflowed f64 — so it passes through like the other degenerate + # inputs (the caller then drills the raw view window). + return lo, hi + level = max(0, math.ceil(math.log2(ratio))) + # `ldexp`, not `extent / (1 << level)`: a finite ratio still reaches level + # 1024, and 2**1024 is not a float. + block = math.ldexp(extent, -level) + q0 = (lo - extent_lo) / block if block > 0.0 else math.inf + q1 = (hi - extent_lo) / block if block > 0.0 else math.inf + if not (math.isfinite(q0) and math.isfinite(q1)): + # A sub-ulp block (subnormal extent, or a window far outside it) puts + # the grid beyond f64; containment is the contract, so pass through. + return lo, hi + b0 = math.floor(q0) + b1 = math.ceil(q1) # The min/max guards absorb the one-ulp case where a bound lands exactly # on a grid line and float rounding would nudge the snapped edge inside # the window — containment is the contract, alignment the optimization. diff --git a/python/xy/pyplot/__init__.py b/python/xy/pyplot/__init__.py index b6473fb54..e3478bc78 100644 --- a/python/xy/pyplot/__init__.py +++ b/python/xy/pyplot/__init__.py @@ -38,9 +38,11 @@ GroupedBarReturn, Legend, Line2D, + Patch, PathCollection, PieContainer, PolyCollection, + Rectangle, StemContainer, StepPatch, StreamplotSet, @@ -102,6 +104,8 @@ "MultipleLocator", "NullFormatter", "NullLocator", + "Patch", + "Rectangle", "ScalarFormatter", "StrMethodFormatter", "acorr", @@ -172,8 +176,10 @@ "imsave", "imshow", "legend", + "locator_params", "loglog", "magnitude_spectrum", + "margins", "matshow", "minorticks_off", "minorticks_on", @@ -220,6 +226,7 @@ "suptitle", "table", "text", + "tick_params", "ticklabel_format", "tight_layout", "title", @@ -2641,6 +2648,21 @@ def minorticks_off() -> None: return gca().minorticks_off() +def tick_params(axis: str = "both", **kwargs: Any) -> None: + """Style the current axes' ticks and tick labels (see `Axes.tick_params`).""" + return gca().tick_params(axis=axis, **kwargs) + + +def margins(*args: Any, **kwargs: Any) -> tuple[float, float] | None: + """Set or query the current axes' autoscale margins (see `Axes.margins`).""" + return gca().margins(*args, **kwargs) + + +def locator_params(axis: str = "both", nbins: int | None = None, **kwargs: Any) -> None: + """Tune the current axes' major tick locators (see `Axes.locator_params`).""" + return gca().locator_params(axis=axis, nbins=nbins, **kwargs) + + def get_xbound() -> tuple[float, float]: """The current axes' x bounds as an ascending ``(lower, upper)``.""" return gca().get_xbound() @@ -2751,13 +2773,22 @@ def subplots_adjust(**kwargs: Any) -> None: gcf().subplots_adjust(**kwargs) -def get_cmap(name: str | None = None, lut: int | None = None) -> Cmap: +def get_cmap(name: Any = None, lut: int | None = None) -> Any: """Look up a colormap by name (default viridis). - ``lut`` resamples it to that many entries. + ``lut`` resamples it to that many entries. Engine colormaps return a + `Cmap`; Matplotlib's qualitative palettes (``tab10``, ``Set2``, ...) return + a callable `ListedColormap`. A colormap object passes through. """ - from ._colors import Cmap + from ._colors import Cmap, qualitative_colormap + if name is not None and not isinstance(name, str) and callable(name): + if lut is None: + return name + return name.resampled(int(lut)) if hasattr(name, "resampled") else name + listed = qualitative_colormap(name) + if listed is not None: + return listed if lut is None else ListedColormap(listed.colors, listed.name, N=int(lut)) cmap = Cmap("viridis" if name is None else name) return cmap if lut is None else cmap.resampled(int(lut)) @@ -2851,26 +2882,37 @@ def _install_ipython_display_hook() -> None: class _CmapNamespace: - """plt.cm.viridis and friends: name carriers the shim resolves by name.""" + """plt.cm.viridis and friends: callable colormap objects, as in Matplotlib. + + Engine colormaps come back as `Cmap` (usable as ``cmap=`` and callable, + ``plt.cm.viridis(np.linspace(0, 1, 3))``); Matplotlib's qualitative + palettes (``tab10``, ``Set1``, ``Paired``, ...) come back as + `ListedColormap` — callable with integer indices or fractions, but not + passable as ``cmap=`` since the engine has no table for them. + """ @staticmethod - def get_cmap(name: str | None = None, lut: int | None = None) -> Cmap: + def get_cmap(name: str | None = None, lut: int | None = None) -> Any: # matplotlib removed cm.get_cmap in 3.9; older scripts still call it. return get_cmap(name, lut) def __getattr__(self, name: str) -> Any: - from ._colors import resolve_cmap + from ._colors import Cmap, qualitative_colormap, resolve_cmap if name == "ScalarMappable": return type("ScalarMappable", (), {"__init__": lambda self, **kwargs: None}) - + if name.startswith("__"): + raise AttributeError(name) + listed = qualitative_colormap(name) + if listed is not None: + return listed try: resolve_cmap(name) except ValueError: - pass - else: - return name - raise AttributeError(f"colormap {name!r} is not supported; see spec/matplotlib/compat.md") + raise AttributeError( + f"colormap {name!r} is not supported; see spec/matplotlib/compat.md" + ) from None + return Cmap(name) cm = _CmapNamespace() diff --git a/python/xy/pyplot/_artists.py b/python/xy/pyplot/_artists.py index bdd396979..4d64e15a4 100644 --- a/python/xy/pyplot/_artists.py +++ b/python/xy/pyplot/_artists.py @@ -18,6 +18,14 @@ from ._colors import resolve_color, resolve_rgba_array, scalar_float from ._rc import rcParams from ._transforms import Bbox, IdentityTransform +from ._translate import ( + LINESTYLE_TO_DASH, + MPL_DASH_PATTERN, + check_unsupported, + line_kwargs, + not_implemented, + strip_artist_noops, +) class _PatchFacade: @@ -91,7 +99,8 @@ def __init__(self, axes: Any, entry: dict[str, Any]) -> None: axes._register_artist(self) def _touch(self) -> None: - self._axes._invalidate() + if self._axes is not None: # legend proxies (Line2D([0], [0], ...)) own no axes + self._axes._invalidate() def _companion_entries(self) -> list[dict[str, Any]]: """Extra spec entries this one handle stands for, beside ``_entry``. @@ -264,6 +273,9 @@ def _marker_entries(self) -> list[dict[str, Any]]: if self._entry.get("kind") == "scatter": return [self._entry] + if self._axes is None: # legend proxy: its marker rides on the handle + proxy_entry = getattr(self, "_proxy_marker_entry", None) + return [proxy_entry] if proxy_entry is not None else [] entries = getattr(self._axes, "_entries", []) try: @@ -318,8 +330,90 @@ def set_markersize(self, size: Any) -> None: set_ms = set_markersize +def _line_proxy_entries( + xdata: Any, ydata: Any, kwargs: dict[str, Any] +) -> tuple[dict[str, Any], Optional[dict[str, Any]]]: + """Spec entries for a Matplotlib-style ``Line2D(xdata, ydata, **style)`` proxy. + + The proxy never renders; ``legend(handles=...)`` freezes it into a swatch + through the same ``_legend_item_from_entry`` path plotted lines use, so + the style vocabulary here mirrors ``Axes.plot``. Point-unit sizes stay in + points (``_mpl_*_points``) because the owning figure's DPI is only known + when the legend attaches. + """ + kwargs = dict(kwargs) + strip_artist_noops(kwargs) + marker = kwargs.pop("marker", None) + markersize = kwargs.pop("markersize", kwargs.pop("ms", None)) + markerfacecolor = kwargs.pop("markerfacecolor", kwargs.pop("mfc", None)) + markeredgecolor = kwargs.pop("markeredgecolor", kwargs.pop("mec", None)) + markeredgewidth = kwargs.pop("markeredgewidth", kwargs.pop("mew", None)) + style = line_kwargs(kwargs) + check_unsupported(kwargs, "Line2D()") + color = style.get("color") or resolve_color(rcParams["lines.color"]) + width = float(style.get("width", rcParams["lines.linewidth"])) + opacity = float(style.get("opacity", 1.0)) + linestyle = style.get("linestyle") + dash_name = LINESTYLE_TO_DASH.get(linestyle) if linestyle is not None else None + dash_points: Optional[list[float]] = None + if style.get("dash") is not None: + dash_points = [float(value) for value in style["dash"]] + elif dash_name not in (None, "none"): + dash_points = list(MPL_DASH_PATTERN[dash_name]) + marker_entry: Optional[dict[str, Any]] = None + if marker is not None and str(marker).lower() != "none": + from ._markers import marker_render_spec + + edge_visible = not (isinstance(markeredgecolor, str) and markeredgecolor.lower() == "none") + marker_kwargs: dict[str, Any] = { + "color": ( + resolve_color(markerfacecolor) if markerfacecolor not in (None, "auto") else color + ), + "opacity": opacity, + **marker_render_spec(marker), + "_mpl_marker_size_points": float( + rcParams["lines.markersize"] if markersize is None else markersize + ), + } + if edge_visible: + marker_kwargs["stroke"] = ( + resolve_color(markeredgecolor) if markeredgecolor not in (None, "auto") else color + ) + marker_kwargs["_mpl_marker_stroke_points"] = float( + rcParams["lines.markeredgewidth"] if markeredgewidth is None else markeredgewidth + ) + marker_entry = {"kind": "scatter", "x": xdata, "y": ydata, "kwargs": marker_kwargs} + line_kw: dict[str, Any] = {"color": color, "width": width, "opacity": opacity} + if style.get("name") is not None: + line_kw["name"] = style["name"] + if dash_points: + line_kw["_mpl_dash_points"] = dash_points + if dash_name == "none" and marker_entry is not None: + # Marker-only proxy (``linestyle="none", marker="o"``): the swatch is + # the marker itself, exactly as a marker-only ``plot`` is a scatter. + marker_entry["kwargs"]["name"] = line_kw.get("name") + return marker_entry, None + return {"kind": "line", "x": xdata, "y": ydata, "kwargs": line_kw, "_proxy": True}, marker_entry + + class Line2D(Artist): - """Handle for plt.plot lines (and their marker overlays).""" + """Handle for plt.plot lines (and their marker overlays). + + Also constructible the Matplotlib way — ``Line2D([0], [0], color="r", + linestyle="--", marker="o", label="fit")`` — as a legend proxy artist. A + proxy owns no axes and draws nothing; ``legend(handles=[...])`` freezes + its style into a swatch exactly as it does for a plotted line. + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + self._proxy_marker_entry: Optional[dict[str, Any]] = None + if len(args) == 2 and isinstance(args[1], dict) and not kwargs: + super().__init__(args[0], args[1]) # (axes, entry): a plotted line + return + if len(args) != 2: + raise TypeError("Line2D(xdata, ydata, **style) requires x and y data") + entry, self._proxy_marker_entry = _line_proxy_entries(args[0], args[1], kwargs) + super().__init__(None, entry) @staticmethod def _segment_args_from_xy(x: Any, y: Any) -> tuple[Any, Any, Any, Any]: @@ -953,6 +1047,67 @@ def get_linewidth(self) -> float: else float(np.asarray(current)[self._index]) ) + def _geometry(self) -> tuple[float, float, float, float]: + """Matplotlib's Rectangle ``(x, y, width, height)`` for this bar. + + Data space, so the ``ax.text(r.get_x() + r.get_width() / 2, + r.get_height(), ...)`` labeling idiom lands on the bar. Category + positions resolve through the axes' category order (0, 1, 2, ...), + as Matplotlib's category converter does. + """ + kw = self._entry["kwargs"] + orientation = kw.get("orientation", "vertical") + raw_center = np.asarray(self._entry.get("x", ())).reshape(-1)[self._index] + try: + center = float(np.asarray(unit_converted_values([raw_center]), dtype=np.float64)[0]) + except (TypeError, ValueError): + axis = "x" if orientation == "vertical" else "y" + center = self._container._axes._categorical_position(axis, raw_center) + values = np.asarray(self._entry.get("y", ()), dtype=np.float64).reshape(-1) + value = float(values[self._index]) + base = float( + np.broadcast_to(np.asarray(kw.get("base", 0.0), dtype=np.float64), values.shape)[ + self._index + ] + ) + thickness = float( + np.broadcast_to(np.asarray(kw.get("width", 0.8), dtype=np.float64), values.shape)[ + self._index + ] + ) + if orientation == "vertical": + return (center - thickness / 2.0, base, thickness, value) + return (base, center - thickness / 2.0, value, thickness) + + def get_x(self) -> float: + return self._geometry()[0] + + def get_y(self) -> float: + return self._geometry()[1] + + def get_width(self) -> float: + return self._geometry()[2] + + def get_height(self) -> float: + return self._geometry()[3] + + def get_xy(self) -> tuple[float, float]: + x, y, _w, _h = self._geometry() + return (x, y) + + def get_center(self) -> tuple[float, float]: + x, y, w, h = self._geometry() + return (x + w / 2.0, y + h / 2.0) + + def get_bbox(self) -> Bbox: + return Bbox.from_bounds(*self._geometry()) + + def get_label(self) -> Any: + labels = self._entry.get("patch_labels") + if labels is not None: + return labels[self._index] + return self._entry["kwargs"].get("name") + class StepPatch(Artist): """Handle for ``stairs`` output backed by a compact core stairs mark.""" @@ -976,16 +1131,43 @@ class Patch(Artist): def __init__( self, - axes: Any, - entry: dict[str, Any], + axes: Any = None, + entry: dict[str, Any] | None = None, outline_entries: list[dict[str, Any]] | None = None, + **style: Any, ) -> None: + if entry is None: + # Matplotlib's constructor form — ``Patch(facecolor="r", + # label="area")`` — builds a legend proxy that owns no axes. + if axes is not None or outline_entries is not None: + raise TypeError("Patch(**style) proxies take keyword styling only") + entry = _patch_proxy_entry(style, "Patch()") + elif style: + raise TypeError(f"Patch() got unexpected keyword argument {next(iter(style))!r}") super().__init__(axes, entry) self._outline_entries = list(outline_entries or []) def _companion_entries(self) -> list[dict[str, Any]]: return self._outline_entries + # -- Matplotlib patch property surface (legend proxies and add_patch ducks) + + def get_facecolor(self) -> Any: + return self._entry["kwargs"].get("color", "none") + + def get_edgecolor(self) -> Any: + return self._entry["kwargs"].get("stroke", "none") + + def get_linewidth(self) -> float: + return float(self._entry["kwargs"].get("stroke_width", 0.0)) + + def get_fill(self) -> bool: + face = self._entry["kwargs"].get("color") + return face is not None and str(face).lower() not in ("none", "transparent") + + def get_hatch(self) -> Any: + return self._entry["kwargs"].get("hatch") + def remove(self) -> None: for entry in self._outline_entries: self._axes._remove_entry(entry) @@ -998,6 +1180,96 @@ def set_zorder(self, level: float) -> None: super().set_zorder(level) +def _patch_proxy_entry(style: dict[str, Any], where: str) -> dict[str, Any]: + """Spec entry for a ``Patch``/``Rectangle`` legend proxy, in bar-swatch shape.""" + kwargs = dict(style) + strip_artist_noops(kwargs) + color = kwargs.pop("color", None) + facecolor = kwargs.pop("facecolor", kwargs.pop("fc", None)) + edgecolor = kwargs.pop("edgecolor", kwargs.pop("ec", None)) + linewidth = kwargs.pop("linewidth", kwargs.pop("lw", None)) + alpha = kwargs.pop("alpha", None) + label = kwargs.pop("label", None) + hatch = kwargs.pop("hatch", None) + fill = kwargs.pop("fill", True) + linestyle = kwargs.pop("linestyle", kwargs.pop("ls", None)) + check_unsupported(kwargs, where) + if linestyle is not None and LINESTYLE_TO_DASH.get(linestyle) not in (None, "none"): + raise not_implemented(f"{where[:-2]}(linestyle={linestyle!r})", "a solid outline") + if color is not None: + facecolor = color if facecolor is None else facecolor + edgecolor = color if edgecolor is None else edgecolor + + def paint(value: Any, default: Any) -> Optional[str]: + if value is None: + value = default + if value is None or (isinstance(value, str) and value.lower() == "none"): + return None + return resolve_color(value) + + face = paint(facecolor, rcParams["patch.facecolor"]) if fill else None + edge = paint(edgecolor, None) + entry_kwargs: dict[str, Any] = { + "color": face if face is not None else "transparent", + "opacity": 1.0 if alpha is None else float(alpha), + } + if label is not None: + entry_kwargs["name"] = str(label) + if edge is not None: + entry_kwargs["stroke"] = edge + entry_kwargs["stroke_width"] = float( + rcParams["patch.linewidth"] if linewidth is None else linewidth + ) + if hatch: + entry_kwargs["hatch"] = str(hatch) + return {"kind": "bar", "kwargs": entry_kwargs, "_proxy": True} + + +class Rectangle(Patch): + """``Rectangle((x, y), width, height, **style)``: a legend proxy that also + quacks like a Matplotlib rectangle for ``add_patch`` (``get_x`` and co.). + + ``angle`` other than 0 is rejected rather than drawn unrotated. + """ + + def __init__( + self, xy: Any, width: float, height: float, *, angle: float = 0.0, **style: Any + ) -> None: + if float(angle) != 0.0: + raise not_implemented("Rectangle(angle=...)", "an unrotated rectangle") + self._xy = (float(xy[0]), float(xy[1])) + self._width = float(width) + self._height = float(height) + super().__init__(None, _patch_proxy_entry(style, "Rectangle()")) + + def get_x(self) -> float: + return self._xy[0] + + def get_y(self) -> float: + return self._xy[1] + + def get_xy(self) -> tuple[float, float]: + return self._xy + + def get_width(self) -> float: + return self._width + + def get_height(self) -> float: + return self._height + + def get_bbox(self) -> Bbox: + return Bbox.from_bounds(self._xy[0], self._xy[1], self._width, self._height) + + def set_xy(self, xy: Any) -> None: + self._xy = (float(xy[0]), float(xy[1])) + + def set_width(self, width: float) -> None: + self._width = float(width) + + def set_height(self, height: float) -> None: + self._height = float(height) + + class StemContainer: """Small tuple-compatible analogue of matplotlib's StemContainer.""" @@ -1649,8 +1921,29 @@ def _legend_item_from_entry( gap_color = kw.get("_gapcolor") if isinstance(gap_color, str): style["legend_gap_color"] = gap_color + # Legend proxies (``Line2D([0], [0], ...)``) keep point-unit styling until + # a legend attaches them to a figure; scale it here like ``Axes._mpl_dash`` + # and ``plot`` do for plotted lines. + dash_points = kw.get("_mpl_dash_points") + if dash_points: + width_points = float(kw.get("width", rcParams["lines.linewidth"])) + style["dash"] = [round(float(v) * width_points * point_scale, 4) for v in dash_points] + if kind == "scatter": + size_points = kw.get("_mpl_marker_size_points") + stroke_points = kw.get("_mpl_marker_stroke_points", 0.0) + if size_points is not None: + style["size"] = (float(size_points) + float(stroke_points)) * point_scale + if stroke_points: + style["stroke_width"] = float(stroke_points) * point_scale if marker_entry is not None: style["legend_marker"] = _legend_marker_style(marker_entry) + marker_kw = marker_entry.get("kwargs") or {} + marker_points = marker_kw.get("_mpl_marker_size_points") + if marker_points is not None: + stroke_points = float(marker_kw.get("_mpl_marker_stroke_points", 0.0)) + style["legend_marker"]["size"] = (float(marker_points) + stroke_points) * point_scale + if stroke_points: + style["legend_marker"]["stroke_width"] = stroke_points * point_scale if kind == "scatter": symbol = kw.get("symbol") if symbol: diff --git a/python/xy/pyplot/_axes.py b/python/xy/pyplot/_axes.py index cff50eba7..5aa695f4b 100644 --- a/python/xy/pyplot/_axes.py +++ b/python/xy/pyplot/_axes.py @@ -12,6 +12,7 @@ import builtins import copy +import functools import math import warnings @@ -77,12 +78,15 @@ ) from ._transforms import Bbox, CoordinateTransform, IdentityTransform from ._translate import ( + ARTIST_KWARG_KEEP, + ARTIST_KWARG_METHODS, LINESTYLE_TO_DASH, MPL_DASH_PATTERN, check_unsupported, line_kwargs, marker_size_to_scatter_size, not_implemented, + strip_artist_noops, ) _UNSET = object() @@ -117,6 +121,20 @@ "upper center": (0.5, 1.0), "center": (0.5, 0.5), } +# Matplotlib's numeric location codes (``Legend.codes``), index = code. +_LEGEND_LOC_CODES = ( + "best", + "upper right", + "upper left", + "lower left", + "lower right", + "right", + "center left", + "center right", + "lower center", + "upper center", + "center", +) _BEST_LOC_ORDER = ( "upper right", "upper left", @@ -673,6 +691,8 @@ def get_major_formatter(self) -> Any: def set_minor_locator(self, locator: Any) -> None: """Set the locator used for the independent unlabeled minor tick set.""" + if self._is_units_registry_ticker(locator): + return host, key = self._ticker_slot() host._tickers[(key, "minor_locator")] = locator host._invalidate_shared_ticker_axis(key) @@ -687,6 +707,8 @@ def get_transform(self) -> _ScaleTransformProxy: def set_minor_formatter(self, formatter: Any) -> None: """Set a minor formatter, used when a labeled minor set is promoted.""" + if self._is_units_registry_ticker(formatter): + return host, key = self._ticker_slot() host._tickers[(key, "minor_formatter")] = as_formatter(formatter, "set_minor_formatter()") host._invalidate_shared_ticker_axis(key) @@ -2102,8 +2124,13 @@ def scatter( matching matplotlib; ``norm`` and other unsupported keywords raise loudly. Returns a `PathCollection`. """ + # Matplotlib's precedence: ``c``, then ``color``, then ``facecolors``/ + # ``facecolor`` (``facecolors="none"`` draws hollow markers). + facecolors = kwargs.pop("facecolors", kwargs.pop("facecolor", None)) if c is None and "color" in kwargs: c = kwargs.pop("color") + if c is None and facecolors is not None: + c = facecolors cmap = kwargs.pop("cmap", None) alpha = kwargs.pop("alpha", None) label = kwargs.pop("label", None) @@ -2443,6 +2470,10 @@ def materialize_iterable(value: Any) -> Any: align = kwargs.pop("align", "center") if align not in {"center", "edge"}: raise ValueError("bar()/barh() align must be 'center' or 'edge'") + tick_label = kwargs.pop("tick_label", None) + if kwargs.pop("log", False): + # Matplotlib sets the value axis to log before adding the bars. + (self.set_yscale if orientation == "vertical" else self.set_xscale)("log") n_bars = int(np.asarray(vals).size) thickness_array = np.asarray(thickness, dtype=np.float64) if thickness_array.ndim == 0: @@ -2548,8 +2579,31 @@ def paint(value: Any, label_text: str, default: Optional[str] = None) -> Any: ) container = BarContainer(self, entry) container.errorbar = errorbar + if tick_label is not None: + self._apply_bar_tick_labels(cats, tick_label, n_bars, orientation) return container + def _apply_bar_tick_labels( + self, positions: Any, tick_label: Any, n_bars: int, orientation: str + ) -> None: + """``bar(tick_label=...)``: one tick per bar, labeled, on the position axis.""" + if isinstance(tick_label, str) or not np.iterable(tick_label): + labels = [_plain_text(str(tick_label))] * n_bars + else: + labels = [_plain_text(str(value)) for value in tick_label] + if len(labels) != n_bars: + raise ValueError( + f"number of tick labels ({len(labels)}) does not match number of bars ({n_bars})" + ) + try: + ticks = np.asarray(unit_converted_values(np.asarray(positions)), dtype=np.float64) + except (TypeError, ValueError): + raise not_implemented( + "bar(tick_label=...) with string category positions", + "numeric positions, or set_xticks(range(n), labels)", + ) from None + (self.set_xticks if orientation == "vertical" else self.set_yticks)(ticks, labels) + def hist( self, x: Any, @@ -2584,6 +2638,9 @@ def hist( linestyle = kwargs.pop("linestyle", kwargs.pop("ls", None)) rwidth = kwargs.pop("rwidth", None) hatch = kwargs.pop("hatch", None) + log = bool(kwargs.pop("log", False)) + bottom = kwargs.pop("bottom", None) + align = kwargs.pop("align", "mid") if ( edgecolor is None and histtype in ("bar", "barstacked") @@ -2595,6 +2652,13 @@ def hist( raise ValueError("orientation must be 'vertical' or 'horizontal'") if histtype not in {"bar", "barstacked", "step", "stepfilled"}: raise ValueError(f"unsupported histtype {histtype!r}") + if align not in {"left", "mid", "right"}: + raise ValueError("hist() align must be 'left', 'mid', or 'right'") + if align != "mid" and histtype.startswith("step"): + raise not_implemented(f"hist(align={align!r}, histtype={histtype!r})", "align='mid'") + if log: + # Matplotlib puts the count axis on a log scale before drawing. + (self.set_yscale if orientation == "vertical" else self.set_xscale)("log") if np.isscalar(x): datasets = [np.atleast_1d(np.asarray(x, dtype=np.float64))] @@ -2721,8 +2785,16 @@ def dataset_values(value: Any, name: str, *, color_value: bool = False) -> list[ label_values = [] if label is None else np.atleast_1d(np.asarray(label, dtype=str)).tolist() labels = (label_values + [None] * len(datasets))[: len(datasets)] containers: list[BarContainer] = [] + # ``bottom`` lifts every baseline (scalar or per bin) and seeds the + # stack; the returned counts stay raw, as Matplotlib's do. base = np.zeros(len(edges) - 1, dtype=np.float64) + if bottom is not None: + base = base + np.broadcast_to(np.asarray(bottom, dtype=np.float64), base.shape) + floor = base.copy() centers = (edges[:-1] + edges[1:]) * 0.5 + if align != "mid": + # Matplotlib centers the bars on the left/right bin edges instead. + centers = centers + (-0.5 if align == "left" else 0.5) * np.diff(edges) # matplotlib's bin filling: a single (or stacked) series spans the full # bin so adjacent bars touch; only multiple side-by-side series shrink # to 0.8 of the bin, split evenly. The shim previously applied the 0.8 @@ -2787,7 +2859,7 @@ def add_dashed_bar_perimeters( for index, values in enumerate(counts): group_start = len(self._entries) positions = centers if stacked else centers + (index - (len(datasets) - 1) / 2) * width - current_base = base.copy() if stacked else np.zeros_like(values) + current_base = base.copy() if stacked else floor.copy() series_color = ( resolve_color(colors[index]) if colors[index] is not None else self._next_color() ) @@ -3029,8 +3101,14 @@ def fill_between( if transform not in (None, "xaxis transform"): raise not_implemented("fill_between(transform=...)") check_unsupported(kwargs, "fill_between()") + from xy.components import _is_datetime_like + + # Datetime x rides the same ms-since-epoch conversion plot() uses for + # the geometry, and is stored back as datetime64 so the axis stays a + # date axis (`_axis_holds_datetimes`) even when the fill is alone. + x_is_datetime = _is_datetime_like(x) xv, upper, lower = np.broadcast_arrays( - _masked_float(x), + _masked_float(unit_converted_values(x)), _masked_float(y1), _masked_float(y2), ) @@ -3089,7 +3167,7 @@ def fill_between( self._add( "area", { - "x": sx, + "x": _epoch_ms_to_datetime64(sx) if x_is_datetime else sx, "y": su, "kwargs": { "base": sl, @@ -3135,7 +3213,9 @@ def fill_between( self._add( "area", { - "x": np.asarray(sx), + "x": _epoch_ms_to_datetime64(sx) + if x_is_datetime + else np.asarray(sx), "y": np.asarray(su), "kwargs": { "base": np.asarray(sl), @@ -3695,8 +3775,6 @@ def _annotation(self, kind: str, args: tuple, kwargs: dict[str, Any]) -> dict[st akw["opacity"] = float(alpha) if lw is not None and kind in ("hline", "vline"): akw["width"] = float(lw) - if label is not None: - akw["text"] = str(label) if span_start != 0.0 or span_end != 1.0: akw["style"] = {"span_start": span_start, "span_end": span_end} dash = LINESTYLE_TO_DASH.get(linestyle) @@ -3708,7 +3786,23 @@ def _annotation(self, kind: str, args: tuple, kwargs: dict[str, Any]) -> dict[st ) if marker_base_color is not None: akw.setdefault("color", marker_base_color) + if label is not None: + # matplotlib: ``label=`` names the artist for the legend and draws + # no text. The legend swatch is frozen from these kwargs + # (`_legend_item_from_entry`), so spell out the engine defaults + # the annotation would otherwise inherit (xy.hline/vline and + # xy.x_band/y_band signatures) to keep the swatch and the drawn + # rule or band identical. + akw["name"] = str(label) + if kind in ("hline", "vline"): + akw.setdefault("color", "#667085") + else: + akw.setdefault("color", "#64748b") + akw.setdefault("opacity", 0.14) entry = self._add(f"@{kind}", {"args": args, "kwargs": akw}) + if kind in ("x_band", "y_band"): + # Filled legend swatch, as matplotlib's Rectangle handle for spans. + entry["_legend_kind"] = "area" if marker is not None: path_size = ( float(rcParams["lines.markersize"] if marker_size is None else marker_size) @@ -3775,11 +3869,16 @@ def text( fontstyle = kwargs.pop("fontstyle", kwargs.pop("style", None)) rotation = kwargs.pop("rotation", None) bbox = kwargs.pop("bbox", None) + alpha = kwargs.pop("alpha", None) check_unsupported(kwargs, "text()") # Matplotlib snapshots the active text default when the Text artist is # created. Preserve that value on the entry so a later style-context # change cannot recolor an already-authored label at render time. - akw = {"color": resolve_color(rcParams["text.color"] if color is None else color)} + akw: dict[str, Any] = { + "color": resolve_color(rcParams["text.color"] if color is None else color) + } + if alpha is not None: + akw["opacity"] = float(alpha) # the same slot Text.set_alpha() writes if bbox is not None: if not isinstance(bbox, Mapping): raise TypeError("text() bbox must be a mapping or None") @@ -4109,8 +4208,8 @@ def set_xlim(self, left: float | LimitsLike | None = None, right: float | None = current_start = auto_start if not np.isfinite(current_end) or current_end <= 0: current_end = auto_end - start = float(current_start if left is None else left) - end = float(current_end if right is None else right) + start = self._limit_coordinate(current_start if left is None else left, "x") + end = self._limit_coordinate(current_end if right is None else right, "x") if not np.isfinite((start, end)).all(): raise ValueError("Axis limits cannot be NaN or Inf") if spec["name"] == "log": @@ -4172,8 +4271,8 @@ def set_ylim(self, bottom: float | LimitsLike | None = None, top: float | None = current_start = auto_start if not np.isfinite(current_end) or current_end <= 0: current_end = auto_end - start = float(current_start if bottom is None else bottom) - end = float(current_end if top is None else top) + start = self._limit_coordinate(current_start if bottom is None else bottom, "y") + end = self._limit_coordinate(current_end if top is None else top, "y") if not np.isfinite((start, end)).all(): raise ValueError("Axis limits cannot be NaN or Inf") if spec["name"] == "log": @@ -4317,6 +4416,10 @@ def set_position(self, position: Bbox | tuple[float, float, float, float]) -> No def _axis_holds_datetimes(self, axis: str) -> bool: from xy.components import _is_datetime_like + if self._axis_props(axis).get("type_") == "time": + # Pinned by artists whose stored geometry is already ms floats + # (fill_betweenx with datetime y). + return True key = "x" if axis == "x" else "y" return any(key in entry and _is_datetime_like(entry[key]) for entry in self._entries) @@ -4343,6 +4446,17 @@ def _data_coordinates(self, xy: tuple) -> Optional[tuple[float, float]]: y = self._data_coordinate(xy[1], "y") return None if x is None or y is None else (x, y) + def _limit_coordinate(self, value: Any, axis: str) -> float: + """A limit argument as the engine's float: numbers as they are, + datetime-likes (``datetime``, ``date``, ``datetime64``, ``Timestamp``, + and date strings on a datetime axis) as ms since epoch — the unit + ``plot()`` reports through ``get_xlim()``. Anything else keeps + ``float()``'s own TypeError/ValueError.""" + if _is_number(value): + return float(value) + converted = self._data_coordinate(value, axis) + return float(value) if converted is None else converted + def _iter_entry_arrays(self, axis: str) -> Iterator[tuple[np.ndarray, bool]]: """Yield each (array, needs_finite_filter) an entry contributes to *axis*.""" from xy.channels import category_label @@ -4407,6 +4521,26 @@ def numeric_or_categorical(values: Any) -> np.ndarray: points.append(entry["xy2"]) yield np.asarray([point[index] for point in points], dtype=np.float64), True continue + span_axis = _SPAN_AUTOSCALE_AXIS.get(entry.get("kind")) + if span_axis is not None: + # axhline/axvline/axhspan/axvspan update matplotlib's dataLim + # only along the axis they are positioned on; their infinite + # extent (and fractional xmin/xmax bounds) never widens the + # perpendicular axis. Positions are stored untransformed, so + # move them into the scale space the other entries live in. + if span_axis == axis: + try: + positions = numeric_or_categorical(list(entry["args"])) + except (TypeError, ValueError): + continue + key = "y2" if axis == "y" and self._y2_of is not None else axis + yield ( + np.asarray( + _scale_values(positions, host._scale_specs[key]), dtype=np.float64 + ).reshape(-1), + True, + ) + continue if entry.get("kind") == "bar": kwargs = entry.get("kwargs", {}) orientation = kwargs.get("orientation", "vertical") @@ -4461,9 +4595,12 @@ def numeric_or_categorical(values: Any) -> np.ndarray: if factory == "stem" and axis == "y": yield np.asarray(entry.get("kwargs", {}).get("base", 0.0)).reshape(-1), True if factory == "errorbar": - center = np.asarray( - entry["args"][0 if axis == "x" else 1], dtype=np.float64 - ).reshape(-1) + # Category positions (``bar(["a", "b"], ..., yerr=)``) + # resolve like every other categorical coordinate. + try: + center = numeric_or_categorical(entry["args"][0 if axis == "x" else 1]) + except (TypeError, ValueError): + continue yield center, True error = entry.get("kwargs", {}).get("xerr" if axis == "x" else "yerr") if error is not None: @@ -4656,6 +4793,30 @@ def _has_nonzero_bar_baseline(self, axis: str) -> bool: return True return False + def _has_span_autoscale(self, axis: str) -> bool: + """Whether a rule/span with a finite coordinate widens *axis*. + + The engine derives an automatic domain from its traces alone, and rules + and bands are annotations, so their matplotlib ``dataLim`` contribution + (`_iter_entry_arrays`) has to reach the render as a materialized domain. + """ + host = self._y2_of or self + y_axis = "y2" if self._y2_of is not None else "y" + for entry in host._entries: + if axis == "y" and entry.get("y_axis", "y") != y_axis: + continue + if _SPAN_AUTOSCALE_AXIS.get(entry.get("kind")) != axis: + continue + try: + values = np.asarray( + unit_converted_values(np.asarray(entry["args"])), dtype=np.float64 + ) + except (TypeError, ValueError): + return True # categorical positions are always finite coordinates + if np.isfinite(values).any(): + return True + return False + def _has_fully_sticky_candidate(self, axis: str) -> bool: """Whether an entry can pin both ends of *axis*. @@ -5146,13 +5307,20 @@ def set_ybound( ) def ticklabel_format(self, **kwargs: Any) -> None: - """Configure the scalar tick-label formatter. + """Configure the scalar tick-label formatter, as Matplotlib does. Supported keywords: ``axis`` (``"both"``/``"x"``/``"y"``), ``style`` (``"plain"`` or ``"sci"``/``"scientific"``), ``scilimits=(m, n)`` - bounding the exponent range that stays plain, and ``useOffset`` - (alias ``useoffset``). ``useLocale``/``useMathText`` must stay False - and anything else raises loudly. + bounding the exponent range that stays plain, ``useOffset`` (alias + ``useoffset``), and ``useMathText``. They configure the axis's + `ScalarFormatter` (installing one when the axis has no formatter yet) + and any other installed formatter raises ``AttributeError``, like + Matplotlib. ``useLocale=True`` and unknown keywords raise loudly. + + Compat-noop: the shim has no offset-text slot, so offsets are never + factored out — labels carry the full value, and scientific style + writes the shared exponent on every label (``1.25e6``, or + ``1.25×10⁶`` under ``useMathText``) instead of once beside the axis. """ axis = kwargs.pop("axis", "both") style = kwargs.pop("style", None) @@ -5162,23 +5330,30 @@ def ticklabel_format(self, **kwargs: Any) -> None: use_math_text = kwargs.pop("useMathText", None) if use_locale not in (None, False): raise not_implemented("ticklabel_format(useLocale=True)") - if use_math_text not in (None, False): - raise not_implemented("ticklabel_format(useMathText=True)") if kwargs: raise TypeError( f"ticklabel_format() got unsupported keyword argument {next(iter(kwargs))!r}" ) if axis not in {"both", "x", "y"}: raise ValueError("ticklabel_format() axis must be 'both', 'x', or 'y'") - if style not in {None, "plain", "sci", "scientific"}: + if style not in {None, "", "plain", "sci", "scientific"}: raise ValueError("ticklabel_format() style must be 'plain' or 'sci'") for item in ("x", "y") if axis == "both" else (axis,): - props = self._axis_props(item) - props["tick_label_format"] = { - "style": "sci" if style == "scientific" else style, - "scilimits": None if scilimits is None else tuple(scilimits), - "use_offset": use_offset, - } + host, key = _AxisProxy(self, item)._ticker_slot() + formatter = host._tickers.get((key, "major_formatter")) + if formatter is None: + formatter = host._tickers[(key, "major_formatter")] = ScalarFormatter() + elif not isinstance(formatter, ScalarFormatter): + raise AttributeError("This method only works with the ScalarFormatter") + if style: + formatter.set_scientific(style != "plain") + if scilimits is not None: + formatter.set_powerlimits(scilimits) + if use_offset is not None: + formatter.set_useOffset(use_offset) + if use_math_text is not None: + formatter.set_useMathText(bool(use_math_text)) + host._invalidate_shared_ticker_axis(key) self._invalidate() def minorticks_on(self) -> None: @@ -5331,7 +5506,11 @@ def get_legend_handles_labels(self) -> tuple[list[Any], list[str]]: continue label = entry.get("kwargs", {}).get("name") if label and not str(label).startswith("_"): - handles.append(Artist(self, entry)) + handles.append( + Line2D(self, entry) + if entry.get("kind") in ("@hline", "@vline") + else Artist(self, entry) + ) labels.append(str(label)) for container in host._containers: if not isinstance(container, (BarContainer, ErrorbarContainer)): @@ -6547,6 +6726,7 @@ def set_xticks( props = host._axis["x"] if ticks is not None: spec = host._scale_specs["x"] + ticks = unit_converted_values(ticks) # datetime-likes → ms since epoch host._auto_scale_axis_ticks.discard("x") host._tickers.pop(("x", "major_locator"), None) props["tick_values"] = list(map(float, _scale_values(ticks, spec))) @@ -6588,6 +6768,7 @@ def set_yticks( props = host._axis[key] if ticks is not None: spec = host._scale_specs[key] + ticks = unit_converted_values(ticks) # datetime-likes → ms since epoch host._auto_scale_axis_ticks.discard(key) host._tickers.pop((key, "major_locator"), None) props["tick_values"] = list(map(float, _scale_values(ticks, spec))) @@ -6865,6 +7046,27 @@ def legend(self, *args: Any, **kwargs: Any) -> Any: """ host = self._y2_of or self reverse = bool(kwargs.pop("reverse", False)) + # Keyword form: legend(handles=..., labels=...), legend(handles=...) + # (labels read off the handles), or legend(labels=...); each means the + # same as its positional spelling. + if "handles" in kwargs or "labels" in kwargs: + if args: + raise TypeError( + "legend() takes handles/labels positionally or as keywords, not both" + ) + keyword_handles = kwargs.pop("handles", None) + keyword_labels = kwargs.pop("labels", None) + if keyword_handles is not None and keyword_labels is not None: + args = tuple([list(keyword_handles), list(keyword_labels)]) + elif keyword_handles is not None: + keyword_handles = list(keyword_handles) + args = tuple( + [keyword_handles, [_handle_label(handle) for handle in keyword_handles]] + ) + else: + # tuple([...]) keeps the variadic tuple type of *args, so the + # len(args) >= 2 branch below type-checks like the positional form. + args = tuple([list(keyword_labels)]) if len(args) >= 2: handles = list(args[0]) labels = [_plain_text(label) for label in args[1]] @@ -6930,6 +7132,19 @@ def _compose_legend_options(self, kwargs: dict[str, Any]) -> dict[str, Any]: second, manually added legend honors the same loc/frame/font keywords. """ loc = kwargs.pop("loc", rcParams["legend.loc"]) + if isinstance(loc, (int, np.integer)) and not isinstance(loc, bool): + # Matplotlib's numeric location codes: 0 best ... 10 center. + if not 0 <= int(loc) < len(_LEGEND_LOC_CODES): + raise ValueError(f"legend loc code must be between 0 and 10, got {loc!r}") + loc = _LEGEND_LOC_CODES[int(loc)] + elif not isinstance(loc, str) and np.iterable(loc): + # ``loc=(x, y)`` places the legend's lower-left corner at that + # axes fraction — Matplotlib's definition of a tuple location. + point = tuple(float(value) for value in loc) + if len(point) != 2 or not all(np.isfinite(value) for value in point): + raise ValueError("legend loc tuple must hold two finite axes-fraction numbers") + kwargs["bbox_to_anchor"] = point + loc = "lower left" if not isinstance(loc, str) or loc not in {"best", *_LEGEND_LOC_ANCHORS}: raise ValueError(f"legend loc must be one of {['best', *sorted(_LEGEND_LOC_ANCHORS)]}") bbox_to_anchor = kwargs.pop("bbox_to_anchor", None) @@ -7064,6 +7279,7 @@ def grid(self, visible: bool | None = True, **kwargs: Any) -> None: lines; anything else raises loudly. """ host = self._y2_of or self + strip_artist_noops(kwargs) # zorder=/clip_on=/... ride along on grid() too which = str(kwargs.pop("which", "major")).lower() axis = kwargs.pop("axis", "both") if which not in {"major", "minor", "both"}: @@ -7220,19 +7436,30 @@ def _apply_tickers( authored_labels = list(props["tick_labels"]) if "tick_labels" in props else None lo, hi = self._ticker_view(key, props) auto_log = False + located: Optional[np.ndarray] = None if locator is not None: if isinstance(locator, Locator): # Third-party locators only promise tick_values(); the density # hint is an xy-locator protocol, never forced onto them. locator._nbins_hint = nbins_hint - ticks = _locator_tick_values( + located = _locator_tick_values( locator, lo, hi, datetime_axis=self._axis_holds_datetimes("y" if key == "y2" else key), ) + if located is None and formatter is None and not is_log: + # The locator has no usable tick_values() (matplotlib's abstract + # Locator base, pandas' period-ordinal TimeSeries_DateLocator): + # leave the axis kind's own ticks in place instead of failing + # the build or pinning AutoLocator numbers onto a date axis. A + # minor tier has no drawn majors to subdivide then, so it is + # dropped with it. + props.pop("minor_tick_values", None) + return + if located is not None: pad = (hi - lo) * 1e-9 - ticks = ticks[(ticks >= lo - pad) & (ticks <= hi + pad)] + ticks = located[(located >= lo - pad) & (located <= hi + pad)] elif "tick_values" in props: ticks = np.asarray( _scale_values(props["tick_values"], spec, inverse=True), dtype=float @@ -7290,6 +7517,9 @@ def _apply_tickers( ticks, datetime_axis=self._axis_holds_datetimes("y" if key == "y2" else key), ) + if minor is None: # no usable tick_values(): no minor tier + props.pop("minor_tick_values", None) + return pad = (hi - lo) * 1e-9 minor = minor[(minor >= lo - pad) & (minor <= hi + pad)] if len(ticks) and len(minor): @@ -7562,7 +7792,7 @@ def _chart_children( ) ) elif kind == "@hline": - children.append(xy.hline(*e["args"], **kw)) + children.append(xy.hline(*e["args"], **_without_legend_name(kw))) if e.get("endpoint_marker"): x_domain = ( (resolved_domains or {}).get("x") @@ -7583,7 +7813,7 @@ def _chart_children( elif kind == "@arrow": children.append(xy.arrow(*e["args"], **kw)) elif kind == "@vline": - children.append(xy.vline(*e["args"], **kw)) + children.append(xy.vline(*e["args"], **_without_legend_name(kw))) if e.get("endpoint_marker"): y_domain = ( (resolved_domains or {}).get("y") @@ -7602,9 +7832,9 @@ def _chart_children( ) ) elif kind == "@x_band": - children.append(xy.x_band(*e["args"], **kw)) + children.append(xy.x_band(*e["args"], **_without_legend_name(kw))) elif kind == "@y_band": - children.append(xy.y_band(*e["args"], **kw)) + children.append(xy.y_band(*e["args"], **_without_legend_name(kw))) elif kind == "@text": opacity = kw.get("opacity") if opacity is not None and float(opacity) == 0.0: @@ -8552,7 +8782,13 @@ def _build_chart_uncached(self, width: int, height: int) -> Any: props["domain"] = pinned else: margin = self._effective_margin(axis) - if margin < 0.0 or self._has_nonzero_bar_baseline(axis): + if ( + margin < 0.0 + or self._has_nonzero_bar_baseline(axis) + or self._has_span_autoscale(axis) + ): + # `_auto_domain` already carries matplotlib's margins, so + # it ships as the exact domain (never alongside `margin`). props["domain"] = self._auto_domain(axis) else: props["margin"] = margin @@ -8639,7 +8875,11 @@ def _build_chart_uncached(self, width: int, height: int) -> Any: ) else: margin = self._twin._effective_margin("y") - if margin < 0.0 or self._twin._has_nonzero_bar_baseline("y"): + if ( + margin < 0.0 + or self._twin._has_nonzero_bar_baseline("y") + or self._twin._has_span_autoscale("y") + ): y2_props["domain"] = self._twin._auto_domain("y") else: y2_props["margin"] = margin @@ -8748,6 +8988,19 @@ def _build_chart_uncached(self, width: int, height: int) -> Any: core_figure.legend_options["border_pad"] = self._legend_options["border_pad"] if self._legend_items is not None: core_figure.legend_options["items"] = list(self._legend_items) + elif ( + self._legend + and self._legend_artist is None + and self._legend_handle is not None + and any( + entry.get("kind") in _SPAN_AUTOSCALE_AXIS and _legend_name(entry) is not None + for entry in self._entries + ) + ): + # Rules and bands are annotations, not traces, so no renderer can + # derive their legend rows from trace names. Ship the item list + # legend() froze instead (matplotlib's legend is that snapshot too). + core_figure.legend_options["items"] = list(self._legend_handle.spec()["items"]) best_ranges: Optional[ tuple[Optional[tuple[float, float]], Optional[tuple[float, float]]] ] = None @@ -9511,6 +9764,36 @@ def _masked_float(value: Any) -> np.ndarray: return np.ma.asarray(value, dtype=np.float64).filled(np.nan) +def _epoch_ms_to_datetime64(values: Any) -> np.ndarray: + """Finite ms-since-epoch floats back to ``datetime64[ms]`` (NaN → NaT).""" + array = np.asarray(values, dtype=np.float64).reshape(-1) + out = np.full(array.shape, np.datetime64("NaT", "ms"), dtype="datetime64[ms]") + finite = np.isfinite(array) + out[finite] = np.round(array[finite]).astype(np.int64).astype("datetime64[ms]") + return out + + +# Annotation kinds whose data coordinate autoscales exactly one axis, as +# matplotlib's axhline/axvline/axhspan/axvspan update dataLim. +_SPAN_AUTOSCALE_AXIS = {"@hline": "y", "@vline": "x", "@y_band": "y", "@x_band": "x"} + + +def _legend_name(entry: dict[str, Any]) -> Optional[str]: + """The entry's legend label, or None when unnamed or ``_``-hidden.""" + name = (entry.get("kwargs") or {}).get("name") + if not name or str(name).startswith("_"): + return None + return str(name) + + +def _without_legend_name(kwargs: dict[str, Any]) -> dict[str, Any]: + """Annotation kwargs minus the legend ``name``: xy's rule and band + annotations take ``text``, and matplotlib's ``label=`` draws no text.""" + if "name" not in kwargs: + return kwargs + return {key: value for key, value in kwargs.items() if key != "name"} + + def _resolve_imshow_sampling( source_shape: tuple[int, int], interpolation: str, @@ -9756,18 +10039,35 @@ def _locator_tick_values( hi: float, *, datetime_axis: bool, -) -> np.ndarray: - """Resolve ordinary and Matplotlib-date locators into engine units.""" - if not _is_foreign_matplotlib_date_object(locator): - return np.asarray(locator.tick_values(lo, hi), dtype=float).reshape(-1) - unit = 1.0 if not datetime_axis else _MILLISECONDS_PER_DAY +) -> Optional[np.ndarray]: + """Resolve ordinary and Matplotlib-date locators into engine units. + + Returns None when the locator has no usable ``tick_values()`` — the + abstract Locator base raises NotImplementedError, and so does pandas' + period-ordinal ``TimeSeries_DateLocator`` — unless it is bound to an axis + and callable, which is Matplotlib's own ``Locator.__call__`` protocol. + """ + foreign = _is_foreign_matplotlib_date_object(locator) + unit = _MILLISECONDS_PER_DAY if foreign and datetime_axis else 1.0 + bounds: tuple[Any, Any] = (lo, hi) + if foreign: + try: + bounds = ( + _MATPLOTLIB_EPOCH + timedelta(days=float(lo) / unit), + _MATPLOTLIB_EPOCH + timedelta(days=float(hi) / unit), + ) + except (OverflowError, OSError, ValueError): + return np.asarray([], dtype=float) try: - lo_datetime = _MATPLOTLIB_EPOCH + timedelta(days=float(lo) / unit) - hi_datetime = _MATPLOTLIB_EPOCH + timedelta(days=float(hi) / unit) - except (OverflowError, OSError, ValueError): - return np.asarray([], dtype=float) - values = np.asarray(locator.tick_values(lo_datetime, hi_datetime), dtype=float).reshape(-1) - return values * unit + values = locator.tick_values(*bounds) + except NotImplementedError: + if getattr(locator, "axis", None) is None or not callable(locator): + return None + try: + values = locator() + except (NotImplementedError, AttributeError, TypeError, ValueError): + return None + return np.asarray(values, dtype=float).reshape(-1) * unit def _formatter_tick_labels( @@ -9820,7 +10120,7 @@ def _minor_locator_tick_values( major: np.ndarray, *, datetime_axis: bool, -) -> np.ndarray: +) -> Optional[np.ndarray]: if isinstance(locator, AutoMinorLocator) or type(locator).__name__ == "AutoMinorLocator": return _auto_minor_tick_values(locator, lo, hi, major) return _locator_tick_values(locator, lo, hi, datetime_axis=datetime_axis) @@ -9869,3 +10169,59 @@ def _iter_plot_groups(args: tuple) -> list[tuple[Any, Any, Optional[str]]]: if not groups: raise TypeError("plot() requires at least y data") return groups + + +def _handle_label(handle: Any) -> str: + """The label ``legend(handles=...)`` reads off a handle (Matplotlib's rule).""" + getter = getattr(handle, "get_label", None) + label = getter() if callable(getter) else None + return "" if label is None else str(label) + + +def _hide_artists(result: Any) -> None: + """Apply ``visible=False`` to whatever a plotting call returned.""" + if hasattr(result, "set_visible"): + result.set_visible(False) + return + if isinstance(result, (list, tuple)): + for item in result: + _hide_artists(item) + return + # Containers that are not Artists themselves (ErrorbarContainer, + # StreamplotSet, ...) expose their parts through these attributes. + for attribute in ("lines", "arrows", "patches", "wedges", "texts"): + parts = getattr(result, attribute, None) + if isinstance(parts, (list, tuple)): + _hide_artists(parts) + + +def _accept_artist_kwargs(method: Any, keep: frozenset[str]) -> Any: + """Strip Matplotlib's Artist-level keywords before *method* validates its own. + + ``visible=False`` hides every artist the call returns; the remaining names + are the documented compat-noops in ``ARTIST_NOOP_KWARGS``. Calls without + keywords take the untouched fast path. + """ + + @functools.wraps(method) + def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any: + if not kwargs: + return method(self, *args) + visible = strip_artist_noops(kwargs, keep) + result = method(self, *args, **kwargs) + if not visible: + _hide_artists(result) + return result + + return wrapper + + +for _method_name in ARTIST_KWARG_METHODS: + setattr( + Axes, + _method_name, + _accept_artist_kwargs( + getattr(Axes, _method_name), ARTIST_KWARG_KEEP.get(_method_name, frozenset()) + ), + ) +del _method_name diff --git a/python/xy/pyplot/_colors.py b/python/xy/pyplot/_colors.py index 87ee9c9ef..24bd449a6 100644 --- a/python/xy/pyplot/_colors.py +++ b/python/xy/pyplot/_colors.py @@ -449,6 +449,73 @@ def resolve_rgba_array(values: object, n: int, label: str) -> np.ndarray: return np.asarray([resolve_rgba(item) for item in sequence], dtype=np.float64) +# Matplotlib's qualitative (ListedColormap) palettes, hex-sampled from +# matplotlib 3.11. They have no engine table — ``cmap="tab10"`` on a plotting +# call still fails loudly — but ``plt.cm.tab10(i)`` / ``plt.get_cmap("Set2")`` +# return callable colormaps so scripts that color series themselves work. +def _hex_table(spec: str) -> tuple[str, ...]: + return tuple(f"#{value}" for value in spec.split()) + + +QUALITATIVE_CMAPS: dict[str, tuple[str, ...]] = { + "tab10": _hex_table("1f77b4 ff7f0e 2ca02c d62728 9467bd 8c564b e377c2 7f7f7f bcbd22 17becf"), + "tab20": _hex_table( + "1f77b4 aec7e8 ff7f0e ffbb78 2ca02c 98df8a d62728 ff9896 9467bd c5b0d5 " + "8c564b c49c94 e377c2 f7b6d2 7f7f7f c7c7c7 bcbd22 dbdb8d 17becf 9edae5" + ), + "tab20b": _hex_table( + "393b79 5254a3 6b6ecf 9c9ede 637939 8ca252 b5cf6b cedb9c 8c6d31 bd9e39 " + "e7ba52 e7cb94 843c39 ad494a d6616b e7969c 7b4173 a55194 ce6dbd de9ed6" + ), + "tab20c": _hex_table( + "3182bd 6baed6 9ecae1 c6dbef e6550d fd8d3c fdae6b fdd0a2 31a354 74c476 " + "a1d99b c7e9c0 756bb1 9e9ac8 bcbddc dadaeb 636363 969696 bdbdbd d9d9d9" + ), + "set1": _hex_table("e41a1c 377eb8 4daf4a 984ea3 ff7f00 ffff33 a65628 f781bf 999999"), + "set2": _hex_table("66c2a5 fc8d62 8da0cb e78ac3 a6d854 ffd92f e5c494 b3b3b3"), + "set3": _hex_table( + "8dd3c7 ffffb3 bebada fb8072 80b1d3 fdb462 b3de69 fccde5 d9d9d9 bc80bd ccebc5 ffed6f" + ), + "paired": _hex_table( + "a6cee3 1f78b4 b2df8a 33a02c fb9a99 e31a1c fdbf6f ff7f00 cab2d6 6a3d9a ffff99 b15928" + ), + "accent": _hex_table("7fc97f beaed4 fdc086 ffff99 386cb0 f0027f bf5b17 666666"), + "dark2": _hex_table("1b9e77 d95f02 7570b3 e7298a 66a61e e6ab02 a6761d 666666"), + "pastel1": _hex_table("fbb4ae b3cde3 ccebc5 decbe4 fed9a6 ffffcc e5d8bd fddaec f2f2f2"), + "pastel2": _hex_table("b3e2cd fdcdac cbd5e8 f4cae4 e6f5c9 fff2ae f1e2cc cccccc"), +} +# Matplotlib spells these with capitals; look-ups are case-insensitive. +_QUALITATIVE_DISPLAY_NAMES = { + "set1": "Set1", + "set2": "Set2", + "set3": "Set3", + "paired": "Paired", + "accent": "Accent", + "dark2": "Dark2", + "pastel1": "Pastel1", + "pastel2": "Pastel2", +} + + +def qualitative_colormap(name: object) -> "ListedColormap | None": + """``ListedColormap`` for a Matplotlib qualitative palette name, else None. + + Accepts the ``_r`` reversal like every other colormap name. + """ + if not isinstance(name, str): + return None + key = name.lower() + reversed_ = key.endswith("_r") + if reversed_: + key = key[:-2] + table = QUALITATIVE_CMAPS.get(key) + if table is None: + return None + display = _QUALITATIVE_DISPLAY_NAMES.get(key, key) + colors: tuple[str, ...] = tuple(reversed(table)) if reversed_ else table + return ListedColormap(list(colors), name=display + ("_r" if reversed_ else "")) + + def resolve_cmap(name: object) -> str: """A matplotlib cmap (name or object) → engine colormap name.""" text = getattr(name, "name", name) diff --git a/python/xy/pyplot/_mplfig.py b/python/xy/pyplot/_mplfig.py index 2c4144e15..6c554a118 100644 --- a/python/xy/pyplot/_mplfig.py +++ b/python/xy/pyplot/_mplfig.py @@ -375,11 +375,18 @@ def add_subplot(self, *args: Any, **kwargs: Any) -> Axes: else: nrows, ncols, index = _parse_subplot_args(args) subplot_key = ("grid", nrows, ncols, index - 1) - if any(a._figure_rect is not None for a in self._axes): - # matplotlib mixes numbered subplots into figures that already - # hold free-form axes; keep the figure free-form via the cell - # rectangle. Figure.add_subplot() deliberately does not reuse - # an existing match; pyplot.subplot() owns activation/reuse. + if (nrows, ncols) != (1, 1) or any(a._figure_rect is not None for a in self._axes): + # A numbered cell of a multi-cell grid creates only that cell, + # at its GridSpec rectangle, as Matplotlib does: ``subplot(221)`` + # then ``subplot(224)`` leaves two axes (not four with two + # empty frames), and grids of another shape may join the same + # figure later (``subplot(2, 1, 2)`` under a 2x2 top row) as + # long as the cells do not overlap. Only the whole-figure + # ``111`` keeps the uniform single-chart path. The same + # rectangle path mixes numbered subplots into figures that + # already hold free-form axes. Figure.add_subplot() + # deliberately does not reuse an existing match; + # pyplot.subplot() owns activation/reuse. row, col = divmod(index - 1, ncols) grid = _GridSpec(self, nrows, ncols) rect = grid.cell_rect((row, row + 1), (col, col + 1)) @@ -636,6 +643,11 @@ def get_axes(self) -> list[Axes]: def gca(self) -> Axes: if self._current_ax is not None and self._current_ax in self._axes: return self._current_ax + if self._axes: + # Axes exist but none is current (the current one was removed): + # fall back to the first without materializing grid placeholders + # for a figure whose numbered subplots own explicit rectangles. + return self._axes[0] return self._axes_at(0) def sca(self, ax: Axes) -> Axes: @@ -1246,6 +1258,9 @@ def colorbar(self, mappable: Any = None, cax: Any = None, ax: Any = None, **kwar if not np.isfinite(pad_value) or pad_value < 0.0: raise ValueError("colorbar() pad must be a finite nonnegative number") options["pad"] = pad_value + # Matplotlib's ``fraction`` steals that share of the parent axes for + # the bar; xy reserves a fixed colorbar strip instead. + kwargs.pop("fraction", None) # compat-noop: the colorbar strip has a fixed width if cax is not None: options["placement"] = "axes" if shrink != 1.0: @@ -2452,10 +2467,16 @@ def __init__( def _parse_subplot_args(args: tuple) -> tuple[int, int, int]: if len(args) == 1 and isinstance(args[0], int) and args[0] >= 111: code = args[0] - return code // 100, (code // 10) % 10, code % 10 - if len(args) == 3: - return int(args[0]), int(args[1]), int(args[2]) - raise ValueError(f"unsupported add_subplot args: {args!r}") + nrows, ncols, index = code // 100, (code // 10) % 10, code % 10 + elif len(args) == 3: + nrows, ncols, index = int(args[0]), int(args[1]), int(args[2]) + else: + raise ValueError(f"unsupported add_subplot args: {args!r}") + if nrows < 1 or ncols < 1: + raise ValueError("Number of rows and columns must be positive") + if not 1 <= index <= nrows * ncols: + raise ValueError(f"num must be an integer with 1 <= num <= {nrows * ncols}, not {index}") + return nrows, ncols, index def make_axes_grid(fig: Figure, nrows: int, ncols: int, squeeze: bool = True) -> Any: diff --git a/python/xy/pyplot/_plot_types.py b/python/xy/pyplot/_plot_types.py index e8b171777..76dd3ff66 100644 --- a/python/xy/pyplot/_plot_types.py +++ b/python/xy/pyplot/_plot_types.py @@ -36,6 +36,7 @@ Text, Wedge, _contour_legend_colors, + unit_converted_values, ) from ._colors import ( PROP_CYCLE, @@ -1368,6 +1369,8 @@ def hlines( """ width = kwargs.pop("linewidth", kwargs.pop("linewidths", kwargs.pop("lw", 1.2))) alpha = kwargs.pop("alpha", None) + # Matplotlib forwards the singular LineCollection spelling too. + linestyles = kwargs.pop("linestyle", kwargs.pop("ls", linestyles)) data = kwargs.pop("data", None) y, xmin, xmax = (_from_data(value, data) for value in (y, xmin, xmax)) transform = kwargs.pop("transform", None) @@ -1385,7 +1388,14 @@ def hlines( if dash_pattern is not None: sx0, sy0, sx1, sy1 = _dashed_segments(sx0, sy0, sx1, sy1, dash_pattern) chosen_color = colors - if chosen_color is not None and not isinstance(chosen_color, str) and len(chosen_color): + if ( + chosen_color is not None + and not isinstance(chosen_color, str) + and len(chosen_color) + # A single RGB(A) tuple (``colors=plt.cm.tab10(3)``) is one color, + # not a per-line sequence, exactly as ``vlines`` reads it. + and not (len(chosen_color) in (3, 4) and all(np.isscalar(v) for v in chosen_color)) + ): chosen_color = chosen_color[0] entry = self._add( "@mark", @@ -1439,6 +1449,7 @@ def _vlines_entry( ) -> PolyCollection: width = kwargs.pop("linewidth", kwargs.pop("linewidths", kwargs.pop("lw", 1.2))) alpha = kwargs.pop("alpha", None) + linestyles = kwargs.pop("linestyle", kwargs.pop("ls", linestyles)) color = kwargs.pop("color", colors) if ( color is not None @@ -1553,8 +1564,15 @@ def fill_betweenx( if data is not None: # resolve string keys before any float coercion sees them y, x1, x2 = (_from_data(value, data) for value in (y, x1, x2)) + from xy.components import _is_datetime_like + + if _is_datetime_like(y): + # Datetime y takes plot()'s ms-since-epoch conversion; the mesh + # coordinates are plain floats, so pin the axis kind for the + # engine's date ticks (`Axes._axis_holds_datetimes` honours it). + self._axis_props("y")["type_"] = "time" yv, left, right = np.broadcast_arrays( - _masked_float(y), + _masked_float(unit_converted_values(y)), _masked_float(x1), _masked_float(x2), ) @@ -3161,12 +3179,13 @@ def errorbar( and markers. ``ecolor``/``elinewidth``/``capsize`` style the bars, ``errorevery`` subsamples them, and the ``*lims`` flags zero the limited side. Line keywords (``color``/``c``, ``linewidth``/``lw``, - ``alpha``, ``label``, ...) style the line; ``barsabove``, - ``capthick``, ``elinestyle``, and unknown keywords raise loudly. + ``alpha``, ``label``, ``marker``/``markersize``, ``mfc``/``mec``/ + ``mew``, ...) style the line and its markers; ``capthick`` sets the + cap stroke; ``barsabove``, ``elinestyle``, and unknown keywords raise + loudly. """ unsupported = { "barsabove": True if barsabove else None, - "capthick": capthick, "elinestyle": elinestyle, } check_unsupported( @@ -3266,6 +3285,9 @@ def subset_limit(flag: Any) -> Any: base = line_kwargs(kwargs) marker = kwargs.pop("marker", None) markersize = kwargs.pop("markersize", kwargs.pop("ms", None)) + markerfacecolor = kwargs.pop("markerfacecolor", kwargs.pop("mfc", None)) + markeredgecolor = kwargs.pop("markeredgecolor", kwargs.pop("mec", None)) + markeredgewidth = kwargs.pop("markeredgewidth", kwargs.pop("mew", None)) check_unsupported(kwargs, "errorbar()") # When ecolor is omitted, the bars inherit the resolved data-series # color, exactly as matplotlib does: an explicit color kwarg wins, then @@ -3333,7 +3355,10 @@ def subset_limit(flag: Any) -> Any: # resize keeps the marker size fixed, while a DPI change # re-resolves points to the new output pixels. "_mpl_line_marker_path_points": 2.0 * resolved_capsize, - "_mpl_line_marker_stroke_points": float(rcParams["lines.markeredgewidth"]), + # Matplotlib: capthick defaults to markeredgewidth. + "_mpl_line_marker_stroke_points": float( + rcParams["lines.markeredgewidth"] if capthick is None else capthick + ), }, ) cap_artists.append(Artist(self, cap_entry)) @@ -3371,6 +3396,12 @@ def subset_limit(flag: Any) -> Any: line_kwargs_for_plot["marker"] = marker if markersize is not None: line_kwargs_for_plot["markersize"] = markersize + if markerfacecolor is not None: + line_kwargs_for_plot["markerfacecolor"] = markerfacecolor + if markeredgecolor is not None: + line_kwargs_for_plot["markeredgecolor"] = markeredgecolor + if markeredgewidth is not None: + line_kwargs_for_plot["markeredgewidth"] = markeredgewidth data_line = self.plot(x, y, fmt, **line_kwargs_for_plot)[0] return ErrorbarContainer(Artist(self, entry), data_line, cap_artists) diff --git a/python/xy/pyplot/_ticker.py b/python/xy/pyplot/_ticker.py index ede6faf36..7b74d055c 100644 --- a/python/xy/pyplot/_ticker.py +++ b/python/xy/pyplot/_ticker.py @@ -485,10 +485,118 @@ def __repr__(self) -> str: class ScalarFormatter(Formatter): - """The default: the shim's ``%g`` rendering of tick values.""" + """The default: the shim's ``%g`` rendering of tick values. + + ``Axes.ticklabel_format`` configures it the way Matplotlib configures its + ``ScalarFormatter`` (``set_scientific``/``set_powerlimits``/ + ``set_useOffset``/``set_useMathText``). Once any of those is called the + formatter labels the located tick set with Matplotlib's plain or + scientific policy: a shared decimal count derived from the tick spacing + (``_set_format``), and — when the ticks' order of magnitude falls outside + ``powerlimits`` — mantissas over a shared exponent. Matplotlib writes that + exponent (and any ``useOffset`` offset) once, as the axis offset text; the + shim has no offset-text slot, so the exponent is written on every label + (``1.25e6`` or ``1.25×10⁶`` under ``useMathText``) and offsets are never + factored out — labels always carry the full value (compat-noop, + spec/matplotlib/compat.md). + """ + + def __init__( + self, + useOffset: Optional[bool | float] = None, + useMathText: Optional[bool] = None, + useLocale: Optional[bool] = None, + ) -> None: + del useLocale # accepted for signature parity; locale grouping is out of scope + self._configured = False + self._scientific = True + # matplotlib's ``axes.formatter.limits`` default + self._powerlimits: tuple[int, int] = (-5, 6) + self._use_offset: bool | float = True if useOffset is None else useOffset + self._use_math_text = bool(useMathText) + self._locs = np.asarray([], dtype=float) + if useOffset is not None or useMathText is not None: + self._configured = True + + def set_scientific(self, scientific: bool) -> None: + self._scientific = bool(scientific) + self._configured = True + + def set_powerlimits(self, limits: Any) -> None: + low, high = limits + self._powerlimits = (int(low), int(high)) + self._configured = True + + def set_useOffset(self, value: bool | float) -> None: + self._use_offset = value + self._configured = True + + def get_useOffset(self) -> bool | float: + return self._use_offset + + def set_useMathText(self, value: bool) -> None: + self._use_math_text = bool(value) + self._configured = True + + def get_useMathText(self) -> bool: + return self._use_math_text + + def set_locs(self, locs: Any) -> None: + self._locs = np.asarray(locs, dtype=float).reshape(-1) + + def format_ticks(self, values: Any) -> list[str]: + ticks = np.asarray(values, dtype=float).reshape(-1) + if not self._configured: + return [f"{value:g}" for value in ticks] + self.set_locs(ticks) + return [self(float(value), position) for position, value in enumerate(ticks)] + + def _order_of_magnitude(self, locs: np.ndarray) -> int: + finite = locs[np.isfinite(locs)] + if not self._scientific or finite.size == 0 or not np.any(finite): + return 0 + oom = int(math.floor(math.log10(float(np.max(np.abs(finite[finite != 0])))))) + low, high = self._powerlimits + if low == high != 0: # fixed exponent, as matplotlib + return low + return oom if (oom <= low or oom >= high) else 0 + + def _decimals(self, locs: np.ndarray, oom: int) -> int: + # Port of matplotlib ScalarFormatter._set_format over the located + # ticks (no view-interval fallback: the Axes hands us the full set). + finite = locs[np.isfinite(locs)] + if finite.size == 0: + return 0 + scaled = finite / 10.0**oom + loc_range = float(np.ptp(scaled)) if scaled.size > 1 else 0.0 + if loc_range == 0: + loc_range = float(np.max(np.abs(scaled))) + if loc_range == 0: + loc_range = 1.0 + loc_range_oom = int(math.floor(math.log10(loc_range))) + sigfigs = max(0, 3 - loc_range_oom) + thresh = 1e-3 * 10**loc_range_oom + while sigfigs >= 0: + if np.abs(scaled - np.round(scaled, decimals=sigfigs)).max() < thresh: + sigfigs -= 1 + else: + break + return sigfigs + 1 def __call__(self, value: float, pos: Optional[int] = None) -> str: - return f"{value:g}" + del pos + if not self._configured: + return f"{value:g}" + locs = self._locs if self._locs.size else np.asarray([float(value)]) + oom = self._order_of_magnitude(locs) + decimals = self._decimals(locs, oom) + mantissa = f"{float(value) / 10.0**oom:.{decimals}f}" + if oom == 0: + return mantissa + if self._use_math_text: + times = "×" # noqa: RUF001 - intentional multiplication sign + return f"{mantissa}{times}10{str(oom).translate(_SUPERSCRIPT_DIGITS)}" + return f"{mantissa}e{oom}" _SUPERSCRIPT_DIGITS = str.maketrans("0123456789-", "⁰¹²³⁴⁵⁶⁷⁸⁹⁻") diff --git a/python/xy/pyplot/_translate.py b/python/xy/pyplot/_translate.py index 88b47cc25..e5c29da13 100644 --- a/python/xy/pyplot/_translate.py +++ b/python/xy/pyplot/_translate.py @@ -133,6 +133,139 @@ def marker_size_to_scatter_size( return out +# Matplotlib ``Artist``-level keywords every plotting call accepts but that +# have no engine equivalent: draw-order overrides, clipping/rasterization +# policy, hit-testing metadata, and renderer filters. They are accepted and +# ignored (documented compat-noops in spec/matplotlib/compat.md) instead of +# raising ``TypeError`` on scripts that carry them for the real renderer. +# ``visible=False`` is *not* in this set: the entry point hides the artist. +ARTIST_NOOP_KWARGS = frozenset( + { + "zorder", + "clip_on", + "clip_box", + "rasterized", + "antialiased", + "aa", + "snap", + "gid", + "url", + "picker", + "pickradius", + "in_layout", + "agg_filter", + "sketch_params", + "path_effects", + "mouseover", + "animated", + } +) + +# Axes entry points that take the Artist-level keywords above. Every method in +# the Matplotlib 3.11 Plotting inventory plus the chrome setters scripts pass +# ``zorder=``/``clip_on=`` to. ``annotate`` and ``clabel`` honor ``zorder`` +# themselves and keep it (see the ``keep`` table below). +ARTIST_KWARG_METHODS = ( + "acorr", + "angle_spectrum", + "annotate", + "arrow", + "axhline", + "axhspan", + "axline", + "axvline", + "axvspan", + "bar", + "bar_label", + "barbs", + "barh", + "boxplot", + "broken_barh", + "bxp", + "clabel", + "cohere", + "contour", + "contourf", + "csd", + "ecdf", + "errorbar", + "eventplot", + "fill", + "fill_between", + "fill_betweenx", + "grouped_bar", + "hexbin", + "hist", + "hist2d", + "hlines", + "imshow", + "loglog", + "magnitude_spectrum", + "matshow", + "pcolor", + "pcolorfast", + "pcolormesh", + "phase_spectrum", + "pie", + "pie_label", + "plot", + "psd", + "quiver", + "quiverkey", + "scatter", + "semilogx", + "semilogy", + "specgram", + "spy", + "stackplot", + "stairs", + "stem", + "step", + "streamplot", + "table", + "text", + "tricontour", + "tricontourf", + "tripcolor", + "triplot", + "violin", + "violinplot", + "vlines", + "xcorr", + "set_title", + "set_xlabel", + "set_ylabel", +) + +# Methods that implement one of the no-op names themselves and must see it: +# annotate/clabel order their text by ``zorder``, the mesh family records +# ``rasterized`` on its handle (``get_rasterized()``), and imshow honors +# ``clip_on`` for images. +ARTIST_KWARG_KEEP: dict[str, frozenset[str]] = { + "annotate": frozenset({"zorder"}), + "clabel": frozenset({"zorder"}), + "pcolormesh": frozenset({"rasterized"}), + "pcolor": frozenset({"rasterized"}), + "pcolorfast": frozenset({"rasterized"}), + "imshow": frozenset({"clip_on"}), + "matshow": frozenset({"clip_on"}), +} + + +def strip_artist_noops(kwargs: dict[str, Any], keep: frozenset[str] = frozenset()) -> bool: + """Drop the accepted-and-ignored Artist keywords; return the ``visible`` flag. + + Mutates ``kwargs``. ``visible`` is popped too because the entry points + apply it to the artists they return (``set_visible(False)``) rather than + ignoring it; ``visible=True`` is Matplotlib's default and a no-op. + """ + for name in ARTIST_NOOP_KWARGS: + if name in kwargs and name not in keep: + kwargs.pop(name) # compat-noop: no engine equivalent (see ARTIST_NOOP_KWARGS) + visible = kwargs.pop("visible", True) + return True if visible is None else bool(visible) + + def check_unsupported(kwargs: dict[str, Any], where: str) -> None: """Anything left in kwargs is unsupported: fail loudly, never silently.""" if kwargs: diff --git a/python/xy/styling/capabilities.py b/python/xy/styling/capabilities.py index 205c04e2f..d1ee78133 100644 --- a/python/xy/styling/capabilities.py +++ b/python/xy/styling/capabilities.py @@ -251,7 +251,9 @@ class ExtensionPoint: #: and has nothing in a file to style. _SLOT_SUBSET_NOTE = ( "Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, " - "letter-spacing, opacity and the text paint (`fill`, or `color`). The raster " + "letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds " + "no fonts, so font-family there selects a base-14 substitute (serif → Times, " + "monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster " "writer's glyph primitive takes a size and one RGBA paint and nothing else, " "so it honors font-size and the paint only — font-weight, font-style, " "font-family, letter-spacing and opacity are vector-only rather than " diff --git a/spec/api/capability-matrix.md b/spec/api/capability-matrix.md index 069fc2189..18416b40e 100644 --- a/spec/api/capability-matrix.md +++ b/spec/api/capability-matrix.md @@ -116,15 +116,15 @@ contracted in [export.md](export.md) §9 and pinned by ### Notes - **`root`** (via `chart style=`) — `styles={'root': ...}` is browser-only, but the chart-level `style=` token bag targets the same element and every renderer reads it (`spec['dom']['style']`). Prefer it for anything that must survive export. -- **`title`** (via `styles={'title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`title`** (via `styles={'title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. - **`legend`** (via `styles={'legend': ...} / xy.legend(style=...) / --chart-legend-bg`) — The frame box. Both spellings and the theme token now converge on one merged declaration block before the writers see it, so what agrees in the browser agrees in a PNG. `background`, `boxShadow`, `borderRadius`, `--xy-legend-frame-alpha`, and `padding`/`rowGap` in `em` are honored; an explicit background paints opaque, as it does in the browser. -- **`legend_title`** (via `styles={'legend_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`legend_label`** (via `styles={'legend_label': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`colorbar`** (via `styles={'colorbar': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`colorbar_tick`** (via `styles={'colorbar_tick': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`colorbar_title`** (via `styles={'colorbar_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`tick_label`** (via `styles={'tick_label': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`axis_title`** (via `styles={'axis_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`legend_title`** (via `styles={'legend_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`legend_label`** (via `styles={'legend_label': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`colorbar`** (via `styles={'colorbar': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`colorbar_tick`** (via `styles={'colorbar_tick': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`colorbar_title`** (via `styles={'colorbar_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`tick_label`** (via `styles={'tick_label': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`axis_title`** (via `styles={'axis_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. ## Extension points diff --git a/spec/api/chart-kind-contract.md b/spec/api/chart-kind-contract.md index 981f9a645..ec6d9ff0b 100644 --- a/spec/api/chart-kind-contract.md +++ b/spec/api/chart-kind-contract.md @@ -56,7 +56,12 @@ by the string `K` on the wire (`trace.kind`). from one path. Most kernels should call the `Figure._ship_channels(t, sel, pw.ship_scalar, pw.ship_u8)` wrapper in `_payload.py`. A categorical channel carries its own palette (`ColorChannel.palette`, resolved at build against the - figure's cycle), so no palette is threaded through the ship call. + figure's cycle), so no palette is threaded through the ship call. Pass the + *same* row selection you shipped geometry with: `Figure._finite_sel` (points + and polylines) and `_rect_finite_sel` (rectangles) both reject rows whose + continuous color/size value is non-finite, alongside x/y NaN (§19), so a + mark with an undefined color is not drawn rather than painted at the ramp + floor. A kernel that builds its own selection must apply that rule too. #### The ribbon geometry contract diff --git a/spec/api/export.md b/spec/api/export.md index 259e403d5..d59f22dd6 100644 --- a/spec/api/export.md +++ b/spec/api/export.md @@ -86,9 +86,24 @@ them, and the client *does* draw it (T9). `_pdf.py` accepts only the SVG that `_svg.py` emits and raises `ValueError("unsupported SVG feature: ...")` on anything else, so generator -drift fails loudly rather than rendering wrong. Text stays text (base-14 -Helvetica, WinAnsiEncoding, `?` for out-of-range characters); density and -heatmap layers embed as bounded rasters. +drift fails loudly rather than rendering wrong. Text stays text: the base-14 +fonts in WinAnsiEncoding (`?` for out-of-range characters), with the face +chosen from the SVG text attributes as §9 describes — the writer embeds no +fonts, so `font-family` is a substitution onto Helvetica, Times or Courier, +never the browser's face. Density and heatmap layers embed as bounded rasters. + +Text content is sanitized once, in the SVG writer. `_svg.escape` (and +`_escape_attr` for attribute values) drops the code points XML 1.0 §2.2 cannot +carry — the C0 controls other than tab, newline and carriage return, the +surrogates, and U+FFFE/U+FFFF — so a legend name or tick label such as +`"a\x01b"` exports as `ab` in SVG and PDF instead of producing a document no +XML parser accepts (no character reference can represent them either). They +are dropped rather than replaced with U+FFFD because a browser paints a control +character as nothing, so the vector text stays visually in step with the HTML +and PNG paths, which are not XML and carry the byte through unchanged. Every +raw text sink in the writer routes through those two helpers, and +`tests/test_export_text_safety.py` pins the rule at the helper, at the original +repros, and across the whole C0 table. `quality` (1–100, default 90) applies to JPEG and to **Chromium** WebP. Requesting `quality` for native WebP is an error, not a silent no-op — the @@ -285,6 +300,43 @@ properties to the vector writers — the one documented divergence, and `tests/test_export_style_survival.py` pins it. A declaration outside the subset stays browser-only. +### What PDF makes of the typeface properties + +Before/after at `spec/assets/pdf-text-properties-before-after.png` (v0.0.7 raised; the rasterized PDF now shows an italic Times title with letter spacing, italic faded tick labels, and Courier axis titles). + +`_pdf.svg_to_pdf` reads the SVG writer's `` attributes and honors all +seven, but it embeds no fonts (stdlib + numpy only), so the typeface properties +are *mapped onto the base-14 set* rather than reproduced: + +| SVG attribute | PDF | +| --- | --- | +| `font-family` | one of the three families in the table below; weight and style then pick one of its four faces | +| `font-weight` | ≥ 600 selects the bold face | +| `font-style` | `italic` and `oblique` (with or without an angle) select the italic/oblique face, `normal` the upright one; any other value is `unsupported SVG feature` | +| `letter-spacing` | the `Tc` character-spacing operator, in px like `Tf`. `normal`, a unitless px number, `px`, `em` (× the element's resolved font size) and `pt` (÷ 0.75) are read; the `text-anchor="middle"/"end"` offset counts the spacing after every character, the last included, as browsers do | +| `opacity` | multiplied into the text's ExtGState (`/ca`) together with `fill-opacity` and the paint's own alpha, exactly as for shapes | +| `font-size`, `fill` | as before | + +The family is the first name in the CSS stack, walked in author order, that the +table recognises (`_pdf._FAMILY_MAP` is the code copy; keep the two in step). A +stack naming nothing in it resolves to Helvetica rather than raising: an +author's font preference is not generator drift, and refusing the export would +hide the whole chart behind an unavailable typeface. + +| CSS name (case-insensitive, quotes ignored) | base-14 family | faces (regular, bold, italic, bold italic) | +| --- | --- | --- | +| `serif`, `ui-serif`, `Times`, `Times New Roman` | Times | Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic | +| `monospace`, `ui-monospace`, `Courier`, `Courier New` | Courier | Courier, Courier-Bold, Courier-Oblique, Courier-BoldOblique | +| `sans-serif`, `ui-sans-serif`, `system-ui`, `Helvetica`, `Arial` — and anything unrecognised | Helvetica | Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique | + +So `styles={"title": {"font-family": "Georgia"}}` yields Helvetica in the PDF +(Georgia is not in the table) while `"Georgia, serif"` yields Times — the +generic fallback is the author's own statement of what the face is. Anchoring +uses the selected face's AFM widths, so a right-aligned Courier tick column +lines up on Courier's metrics, not Helvetica's. The root `` +(the system-ui stack) resolves through the same table, to Helvetica, so +unstyled output is unchanged. `tests/test_pdf_export.py` pins each row. + Where two surfaces name the same chrome, the narrower selector wins: an axis's own `label_color` beats `styles={"axis_title": ...}`, which beats the chart-wide default. diff --git a/spec/api/interaction.md b/spec/api/interaction.md index 33870d820..9550b8f73 100644 --- a/spec/api/interaction.md +++ b/spec/api/interaction.md @@ -490,7 +490,19 @@ non-bool hidden) are dropped without mutating state. CPU copy, are read back once (`getBufferSubData`) and cached. `_visMap` translates drawn vertices back to shipped rows so hover readouts and kernel picks stay exact; `_visInv` maps the kernel's shipped-space - selection indices onto the filtered buffers. + selection indices onto the filtered buffers. The **CPU hover fallback** + (`_nearestCpuIndex`, its polar sibling and `_barHover` — reached when the + GPU pick pass misses, and the source of point tooltips) scans the + *unfiltered* retained columns, so it consults `_visInv` too: a row it maps + to `-1` is hidden and can neither become the hover target nor show a + tooltip; the nearest *visible* row is picked instead, or nothing. The scan + covers the pre-filter row count (`_fullN`), not the drawn `g.n` — a + category filter shrinks `g.n` below the retained columns, and capping the + scan at it left every visible row shipped after the cut unreachable while + hidden rows before it still answered (the two halves of one bug; + `tests/test_legend_hidden_hover.py`). Unfiltered traces keep the `g.n` + cap, which is load-bearing for smooth-resampled lines and mismatched x/y + lengths. - **Category rows on a density-tier trace** (the rows exist because the first-paint density entry ships a slim categorical `color` spec — categories + palette, no per-point buffer; wire-protocol doc): local @@ -517,7 +529,7 @@ non-bool hidden) are dropped without mutating state. `-masked`, and stamps it with `filter: {hidden_categories}`. The client compares that stamp against its current hidden set and drops stale-predicate replies; drills ship only visible rows with canonical - `shipped_sel`. + `shipped_sel`. Before/after at `spec/assets/legend-hidden-hover-before-after.png`. **Accessibility compatibility exception.** Legend-hidden ordinary point-series rows remain in keyboard traversal in their full retained CPU order, so a screen diff --git a/spec/api/styling.md b/spec/api/styling.md index 2bbf64c88..3e823559d 100644 --- a/spec/api/styling.md +++ b/spec/api/styling.md @@ -212,7 +212,15 @@ and minor-grid tier. `minor_tick_values=[...]` supplies its positions without labels; major `tick_values`/`tick_labels` remain unchanged. On log axes, `nonpositive="clip"` maps non-positive mark coordinates below the visible range, while `"mask"` makes those endpoints non-renderable in the browser, -SVG, and native raster paths. +SVG, and native raster paths. Point and polyline marks (`scatter`, `line`, +`area`, `error_band`) never ship a non-positive coordinate on a log axis at +all — the kernel drops those rows before the wire, under every policy. That +drop is allowed but never silent (dossier §28): with no `nonpositive=` set, +the payload build emits a `RuntimeWarning` naming the axis, the number of +points dropped, and the remedies (`nonpositive="clip"|"mask"` to state the +policy explicitly, which silences the warning, or `type_="symlog"` to show +zero and negative values). Rectangle and segment families ship every row and +let the renderer apply the policy per endpoint, so they neither drop nor warn. | Axis style key | Value | | --- | --- | @@ -1288,6 +1296,15 @@ with, so what validates is exactly what renders: string is a `data=` column name. The full named-color table counts, so `color="rebeccapurple"` is a color, and a color-shaped typo reports its CSS reason instead of a misleading column-lookup error. +- **A non-finite continuous `color=`/`size=` value is not drawn.** NaN and + ±inf in a per-point numeric channel have no position on the ramp, so the + row leaves the shipped geometry, the pick/selection mapping, and the static + exports together — the same exclusion an x/y NaN gets (dossier §19), and + matplotlib's transparent "bad" colour. It is never painted as the domain + floor (the old behaviour, which drew a `+inf` point in the *minimum* + colour). The normalizers' floor for non-finite input remains only as a + vertex-safety net behind that exclusion. Missing-column names raise + `ValueError` on every surface, `facet_chart(by=...)` included. ## What CSS cannot restyle diff --git a/spec/assets/legend-hidden-hover-before-after.png b/spec/assets/legend-hidden-hover-before-after.png new file mode 100644 index 0000000000000000000000000000000000000000..814b9dd4f614f75463a384d1b997a7a53571819b GIT binary patch literal 59445 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\HE&;vc@te| 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

Q$2JO_(Zx-Rh%cdoOG8QfDs?aF zDxPYd0jB(vkjLhTQYEQj%0*^~5a!`Ir8 zhyqwX*_ILLp?1cA0^X*`Jfx0u0?bN}Yn*2*PT2zi#)(|p-LBlF>Ne~OBpQeQgGA}U z38BOr5FtZ+Nt#3Vh68#pAM5%MbV43q$h%^3lN8;|qaFjy+yn20JY|k3&UsOK^|$N8 z7ZZ(%{z5`6n@vItrit}u+!#}>=OuT;#Awi6v7oSF${~eVgbC3zL&nb+bjD9VwNZ6- z(a#Ce1S1Jj1@5jNA<_>AxQ)*KZnFeaNaQ)yeDx}yF4nz)^_)O9PESD|V;lJ&eKErz zP+uWPBI)lpgiy%;(Q9WNc^m?00`9~>u=D({H~Y|ig4uH& V%ETmG&EN-++fqum@+I#f{~wJo)+qo0 literal 0 HcmV?d00001 diff --git a/spec/assets/log-axis-decade-before-after.png b/spec/assets/log-axis-decade-before-after.png new file mode 100644 index 0000000000000000000000000000000000000000..140b79983e0c638a24f9a2f89d7eeed1e4e86842 GIT binary patch literal 27167 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 literal 0 HcmV?d00001 diff --git a/spec/assets/pdf-text-properties-before-after.png b/spec/assets/pdf-text-properties-before-after.png new file mode 100644 index 0000000000000000000000000000000000000000..704415e31dbb196f264e3e43396582efed9ab92b GIT binary patch literal 91520 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 literal 0 HcmV?d00001 diff --git a/spec/assets/pyplot-span-autoscale-before-after.png b/spec/assets/pyplot-span-autoscale-before-after.png new file mode 100644 index 0000000000000000000000000000000000000000..01ede4793ad1cd283595afadce01ea9096fe8327 GIT binary patch literal 20922 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 literal 0 HcmV?d00001 diff --git a/spec/assets/pyplot-subplot-cells-before-after.png b/spec/assets/pyplot-subplot-cells-before-after.png new file mode 100644 index 0000000000000000000000000000000000000000..aa4979e3bf451f63b64a1cc31a832ce9352ae40d GIT binary patch literal 25403 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 P0l?H$v@YbFxA6ZT@gou= literal 0 HcmV?d00001 diff --git a/spec/design/chart-grammar.md b/spec/design/chart-grammar.md index 03b6c08a6..844a120d9 100644 --- a/spec/design/chart-grammar.md +++ b/spec/design/chart-grammar.md @@ -96,7 +96,11 @@ xy.chart(xy.line(x="ts", y="value", data=df), xy.y_axis(label="watts")) (`xy.chart` is the kind-neutral container; the existing `scatter_chart`/ `line_chart`/… wrappers remain as readable aliases — they already just tag -`Chart(kind_str, children)`.) +`Chart(kind_str, children)`. Every `*_chart` accepts its own mark as the +first positional, `sankey_chart` included: `xy.sankey_chart(links)` and +`xy.sankey_chart(xy.sankey(links))` build the same figure, and sankey +keywords beside an explicit `xy.sankey(...)` child are refused rather than +appended as a second diagram — the `funnel_chart` rule.) ## 4. The 5 complex overlays (the composition stress tests) @@ -147,7 +151,13 @@ panes is layout the Figure grid owns. (planned), `chart` ★ (sugar: figure with one panel). - Marks ★: `scatter, line, area, histogram, bar/column, heatmap, errorbar, error_band, box, violin, ecdf, hexbin, contour, step, stairs, stem` (+ every - future kind — one `Mark` node each, registry-dispatched). + future kind — one `Mark` node each, registry-dispatched). `Mark` is a + public dataclass, so a hand-built `xy.Mark(kind=..., x=..., y=...)` with a + partial `props` is legal: at chart build the missing keys are completed + from the kind's factory called with no arguments (`_with_factory_defaults`, + `_MARK_FACTORIES`), so rule G0 keeps one set of defaults and a bare mark + either builds exactly like its factory or raises `ValueError` naming the + prop — never `KeyError`. - Annotations ★ (tiny data): rules `hline`/`vline`/`threshold`, bands `x_band`/`y_band`/`threshold_zone`, and `label`/`text`/`marker`/`arrow`/ `callout`. These are not literally Mark nodes: they compile to an @@ -256,7 +266,13 @@ link_select=False, gap=12)` (`python/xy/components.py:4480`, class at integer, and `gap` a non-negative one. - **Panel derivation and order.** `by` resolves to a column of the - chart-level data or to a per-row array (`python/xy/facets.py:79`). Rows + chart-level data or to a per-row array (`python/xy/facets.py:79`); a name + the data does not hold raises `ValueError("facet column 'zz' not found in + data")`, the same type every other column resolution in the API raises. A + bare pyarrow string/dictionary/chunked array is a valid `by` (and a valid + categorical axis column): label work goes through + `columns.label_ndarray`, which takes pyarrow's copying conversion instead + of leaking `ArrowInvalid`. Rows group by their `category_label` display string — matching categorical channels — and panels appear in **first-seen row order**, not sorted order; the `np.unique` fast path explicitly restores first-seen order diff --git a/spec/design/renderer-architecture.md b/spec/design/renderer-architecture.md index 79336f1d5..d79137fd3 100644 --- a/spec/design/renderer-architecture.md +++ b/spec/design/renderer-architecture.md @@ -338,6 +338,23 @@ mantissa-1 ticks are labelled, and only every `labelEvery` decade where `labelEvery = ceil((decades + 1) / target)` — so minor ticks draw unlabelled. If thinning produces nothing, every tick is labelled. +*Within-decade fallback.* The decade ladder is multiplicative: inside one +decade it has at most the 2 and 5 mantissas to offer, and a window such as +`0.3..0.35`, `2..3` or `100..110` holds none of them — so every zoom past ~3x on +a log axis used to lose all ticks, labels and grid. When **fewer than two** +decade (mantissa-1) ticks fall inside the domain (same `1e-12` slack), the +ladder cannot describe the window and `logTicks` returns `linearTicks(lo, hi, +target)` instead: linearly spaced "nice" positions across the span, every one +labelled, with `step` set to the linear step so `fmtLinear` gives the axis one +shared decimal count (`0.30, 0.31, …`, §6.2), and `log: true` still set. This is +what matplotlib and Plotly do on a sub-decade log window. The rule is +range-based, so wide windows are byte-identical to before (`0.5..50` has two +decades in view and keeps `0.5 1 2 5 10 20 50`), and it is mirrored exactly by +`_log_ticks` in `python/xy/_svg.py` — which `axis_ticks` (SVG and, through it, +the native raster/PNG/PDF path), the static colorbars and pyplot's +`get_xticks` all consume — so a static export ticks a zoomed log axis where the +browser does (`tests/test_log_ticks_within_decade.py` pins the parity). Before/after at `spec/assets/log-axis-decade-before-after.png` (a log-x view of `[0.3, 0.35]`). + An authored `tick_values` array is the labelled major tier. An optional `minor_tick_values` array is drawn separately with `minor_style`; it never participates in label formatting or collision handling. Pyplot uses this @@ -373,6 +390,17 @@ With no `format=` on the axis, labels come from the step: from the tick step — `ceil(−log10(step))`, then increments while the step is not representable at that precision to within a thousandth of itself — and caps at 8 decimals. Ticks on one axis therefore share a decimal count. +- `fmtLog` labels a log tick from its own value, not the step: the fewest + decimals (up to 8) that reproduce it, with the same exponential switch as + `fmtLinear`. On the 1/2/5 ladder that is the decade's magnitude (`0.002`, + `20`); it exists because the ladder's `step` of 1 makes `fmtLinear` collapse + every sub-unit decade to `0`. It also keeps the within-decade linear ticks a + log *colorbar* carries distinct (`2.2, 2.4` rather than `2, 2`). `fmtAxis` + routes a sub-unit log tick whose label collapsed to zero here — unless the + tick step is itself sub-unit (the within-decade fallback, or authored linear + `tick_values`), in which case `fmtLinear(v, step)` wins so the axis keeps + one shared decimal count. `_fmt_log` / `_fmt_axis` in `python/xy/_svg.py` + mirror both rules. - `fmtTime` picks the unit from the step: year alone for January on month-or-coarser steps, otherwise `Mon YYYY`; `Mon DD` at day steps; `HH:MM` at minute steps; `HH:MM:SS` at second steps; `MM:SS.mmm` below. All fields diff --git a/spec/design/wire-protocol.md b/spec/design/wire-protocol.md index c44fd4066..4360f82cc 100644 --- a/spec/design/wire-protocol.md +++ b/spec/design/wire-protocol.md @@ -19,9 +19,13 @@ emits it (§2). returns either `None` or `(message, buffers)`, where `buffers` is a list of binary attachments the reply's spec entries index into by position. -- Non-dict `content`, an unknown `type`, a missing required field, or a value - that fails coercion returns `None`. Client-supplied data never raises; - exceptions from *user callbacks* do propagate. +- Non-dict `content`, an unknown or non-string `type`, a missing required + field, or a value that fails coercion returns `None`. Client-supplied data + never raises; exceptions from *user callbacks* do propagate. A dropped + message mutates nothing: `type` is checked before any other field is read, + and every kind validates its whole payload before touching drill + bookkeeping, the view-state cache, or legend predicates + (`tests/test_channel_malformed_messages.py` fuzzes this). - Replies are return values, not sends. Python-side callbacks therefore fire before the reply leaves the process. - The `buffers` argument is accepted and unused: no inbound message carries @@ -82,6 +86,15 @@ first payload's recorded count — sits within the points band covering texture stands, however blurry; traces with no recorded counts always request. +Window bounds pass through `lod.normalize_window`, which rejects non-finite +values and spans below the smallest normal double (`sys.float_info.min`): +every consumer divides by the span — the drill ladder's level, the grid's +cell width, the client's data→clip map — and a subnormal span has no finite +reciprocal in f64, so such a request is dropped with no drill-state change. +A normal span that still out-resolves the power-of-two ladder +(`lod.aligned_window`: the extent-to-span quotient overflows, or a block +would fall below an ulp) drills the raw view window instead of a padded one. + **`pick`** — `trace` and `index` pass through `_integer_id`. `index` is a *shipped-vertex* index, translated kernel-side to a canonical row when the shipped copy dropped non-finite rows. `drill_seq`, when present, is the drill @@ -89,6 +102,11 @@ subset version the client picked against; a non-current seq translates through the kernel's bounded subset history when it is still remembered (the client may be drawing a retired cached point window, LOD doc T13) and resolves to `row: null` otherwise — never to a row in a dead index space. +`index` must also name a readable row: where a mark's advertised `n_points` +is not the length of its readout columns — a histogram's or hexbin's sample +count over its bin rows, an errorbar's points over its segment endpoints — +the bound is the smaller of the two, and an index past it resolves to +`row: null` rather than an exception. **`click`** — same fields and same `fig.pick` resolution as `pick`, minus `seq`; it fires `on_click` and returns nothing. @@ -96,7 +114,11 @@ resolves to `row: null` otherwise — never to a row in a dead index space. **`view_change`** — a per-axis `ranges` map (`{axisId: [lo, hi]}`) plus a `source` string (default `"view"`, stringified kernel-side), the changed `axes`, a `phase` (default `"end"`), and an `interaction_id`; a legacy `{x0, x1, y0, y1}` -message with no `ranges` is still accepted and normalized kernel-side. There is +message with no `ranges` is still accepted and normalized kernel-side. Each +range is coerced with `float()`, must be finite, and is stored ascending — a +flipped pair is reordered, a zero-span pair rejects the whole event — so the +cache holds only what `Figure.state_patch_message` accepts and `view_state()` +output always feeds back into a state patch (view-state.md §5.1). There is no `view_change` interaction flag: the client sends `phase: "end"` events unconditionally (rAF-coalesced — one message per gesture; they feed the kernel's `view_state()` cache, view-state.md §5.1) and streams `"update"` @@ -222,8 +244,9 @@ accepts `msg.trace` and `msg.stale` for pending-request bookkeeping — no current kernel path emits either field. **`pick_result`** — `{type, seq, row}`. `row` is `null` when the index is out -of range or `drill_seq` was stale; the reply ships regardless so the client -clears its hover state. A point row is +of range (past the advertised count or the readable rows, whichever is +smaller — §2 `pick`) or `drill_seq` was stale; the reply ships regardless so +the client clears its hover state. A point row is `{trace, index, x, y, x_kind, y_kind}` plus `color_value` or `color_category` and `size_value` when those channels exist. A heatmap row is `{trace, index, row, col}` plus `color_value` when the cell is finite. Picks diff --git a/spec/matplotlib/compat-changelog.md b/spec/matplotlib/compat-changelog.md index d3186a553..201de0173 100644 --- a/spec/matplotlib/compat-changelog.md +++ b/spec/matplotlib/compat-changelog.md @@ -4,6 +4,28 @@ This changelog records changes to the upstream compatibility target and to the meaning of xy's compatibility levels. It complements the project changelog, which covers user-visible releases across the whole package. +## Artist keywords, legend forms, partial subplot grids — 2026-09-01 + +- Matplotlib's Artist-level keywords (`zorder`, `clip_on`, `rasterized`, + `antialiased`/`aa`, `snap`, `gid`, `url`, `picker`, `in_layout`, + `agg_filter`, `sketch_params`, `path_effects`, ...) move from *unsupported* + (`TypeError`) to *accepted no-op* on every plotting method; `visible=False` + hides the returned artists. `pcolormesh(antialiased=False)` and + `quiver(zorder=)`, previously rejected as material options, are now no-ops. +- `legend()` gains the `handles=`/`labels=` keyword forms, integer `loc` + codes, tuple `loc`, and proxy handles (`plt.Line2D`, `plt.Patch`, + `plt.Rectangle` constructors). +- `subplot(n, m, i)` / `add_subplot(n, m, i)` create only the requested cell; + partial grids no longer draw empty frames and mixed grid shapes no longer + raise "cannot reshape". +- `plt.cm.` returns a callable colormap object instead of a name string + (`.name` still resolves to the engine table); qualitative palettes are + available as `ListedColormap`s. +- `colorbar(fraction=)` is an accepted no-op; `scatter(facecolors=)`, + `bar(tick_label=, log=)`, `hist(bottom=, align=, log=)`, `text(alpha=)`, + `hlines`/`vlines(linestyle=)`, `errorbar(capthick=, mfc=, mec=, mew=)`, and + `plt.tick_params`/`plt.margins`/`plt.locator_params` are supported. + ## Patch bodies and geometry — 2026-07-30 (Matplotlib 3.11.1 reference) - `xy.pyplot.Axes.add_patch` now fills a patch instead of drawing only its diff --git a/spec/matplotlib/compat-matrix.md b/spec/matplotlib/compat-matrix.md index b0ff74b19..8ccecbbc0 100644 --- a/spec/matplotlib/compat-matrix.md +++ b/spec/matplotlib/compat-matrix.md @@ -8,7 +8,7 @@ Corpus links are executable examples and are checked for every supported method. | Family | Level | Methods | Executable corpus | |---|---|---:|---:| -| Basic | equivalent semantics | 22 | 48 | +| Basic | equivalent semantics | 22 | 49 | | Spans | exact geometry | 5 | 4 | | Spectral | equivalent semantics | 9 | 2 | | Statistics | equivalent semantics | 5 | 2 | @@ -16,7 +16,7 @@ Corpus links are executable examples and are checked for every supported method. | Contours | visual approximation | 3 | 1 | | 2D arrays | equivalent semantics | 6 | 3 | | Unstructured triangles | equivalent semantics | 4 | 1 | -| Text and annotations | visual approximation | 4 | 3 | +| Text and annotations | visual approximation | 4 | 4 | | Vector fields | visual approximation | 4 | 2 | ## Method inventory @@ -25,16 +25,16 @@ Corpus links are executable examples and are checked for every supported method. Approximation level: **equivalent semantics**. -- `plot` — [`01_basic_line.py`](../../tests/pyplot/corpus/01_basic_line.py), [`02_plot_fmt_red_dashed.py`](../../tests/pyplot/corpus/02_plot_fmt_red_dashed.py), [`03_plot_fmt_green_circles.py`](../../tests/pyplot/corpus/03_plot_fmt_green_circles.py), [`04_plot_fmt_cycle_dashdot_square.py`](../../tests/pyplot/corpus/04_plot_fmt_cycle_dashdot_square.py), [`05_multi_series_one_call.py`](../../tests/pyplot/corpus/05_multi_series_one_call.py), [`06_implicit_x.py`](../../tests/pyplot/corpus/06_implicit_x.py), [`07_labels_title_legend_grid.py`](../../tests/pyplot/corpus/07_labels_title_legend_grid.py), [`08_xlim_ylim.py`](../../tests/pyplot/corpus/08_xlim_ylim.py), [`09_log_scale.py`](../../tests/pyplot/corpus/09_log_scale.py), [`20_fill_between_band.py`](../../tests/pyplot/corpus/20_fill_between_band.py), [`23_axhline_axvline.py`](../../tests/pyplot/corpus/23_axhline_axvline.py), [`24_axvspan_band.py`](../../tests/pyplot/corpus/24_axvspan_band.py), [`25_annotate_text.py`](../../tests/pyplot/corpus/25_annotate_text.py), [`26_twinx_dual_axis.py`](../../tests/pyplot/corpus/26_twinx_dual_axis.py), [`27_subplots_2x2_mixed.py`](../../tests/pyplot/corpus/27_subplots_2x2_mixed.py), [`28_subplots_figsize.py`](../../tests/pyplot/corpus/28_subplots_figsize.py), [`29_implicit_state_savefig.py`](../../tests/pyplot/corpus/29_implicit_state_savefig.py), [`30_savefig_html.py`](../../tests/pyplot/corpus/30_savefig_html.py), [`31_rcparams_figsize.py`](../../tests/pyplot/corpus/31_rcparams_figsize.py), [`33_set_data_mutation.py`](../../tests/pyplot/corpus/33_set_data_mutation.py), [`34_gray_string_color.py`](../../tests/pyplot/corpus/34_gray_string_color.py), [`35_tab_colors.py`](../../tests/pyplot/corpus/35_tab_colors.py), [`36_color_cycle_c0_c9.py`](../../tests/pyplot/corpus/36_color_cycle_c0_c9.py), [`37_markers_only_fmt.py`](../../tests/pyplot/corpus/37_markers_only_fmt.py), [`38_close_all_hygiene.py`](../../tests/pyplot/corpus/38_close_all_hygiene.py), [`39_multiple_figures.py`](../../tests/pyplot/corpus/39_multiple_figures.py), [`40_subplots_row_sharex.py`](../../tests/pyplot/corpus/40_subplots_row_sharex.py), [`41_line_kwargs.py`](../../tests/pyplot/corpus/41_line_kwargs.py), [`43_grid_html_suptitle.py`](../../tests/pyplot/corpus/43_grid_html_suptitle.py), [`44_subplot_classic.py`](../../tests/pyplot/corpus/44_subplot_classic.py), [`45_xticks_positions_labels.py`](../../tests/pyplot/corpus/45_xticks_positions_labels.py), [`55_polar_projection.py`](../../tests/pyplot/corpus/55_polar_projection.py) +- `plot` — [`01_basic_line.py`](../../tests/pyplot/corpus/01_basic_line.py), [`02_plot_fmt_red_dashed.py`](../../tests/pyplot/corpus/02_plot_fmt_red_dashed.py), [`03_plot_fmt_green_circles.py`](../../tests/pyplot/corpus/03_plot_fmt_green_circles.py), [`04_plot_fmt_cycle_dashdot_square.py`](../../tests/pyplot/corpus/04_plot_fmt_cycle_dashdot_square.py), [`05_multi_series_one_call.py`](../../tests/pyplot/corpus/05_multi_series_one_call.py), [`06_implicit_x.py`](../../tests/pyplot/corpus/06_implicit_x.py), [`07_labels_title_legend_grid.py`](../../tests/pyplot/corpus/07_labels_title_legend_grid.py), [`08_xlim_ylim.py`](../../tests/pyplot/corpus/08_xlim_ylim.py), [`09_log_scale.py`](../../tests/pyplot/corpus/09_log_scale.py), [`20_fill_between_band.py`](../../tests/pyplot/corpus/20_fill_between_band.py), [`23_axhline_axvline.py`](../../tests/pyplot/corpus/23_axhline_axvline.py), [`24_axvspan_band.py`](../../tests/pyplot/corpus/24_axvspan_band.py), [`25_annotate_text.py`](../../tests/pyplot/corpus/25_annotate_text.py), [`26_twinx_dual_axis.py`](../../tests/pyplot/corpus/26_twinx_dual_axis.py), [`27_subplots_2x2_mixed.py`](../../tests/pyplot/corpus/27_subplots_2x2_mixed.py), [`28_subplots_figsize.py`](../../tests/pyplot/corpus/28_subplots_figsize.py), [`29_implicit_state_savefig.py`](../../tests/pyplot/corpus/29_implicit_state_savefig.py), [`30_savefig_html.py`](../../tests/pyplot/corpus/30_savefig_html.py), [`31_rcparams_figsize.py`](../../tests/pyplot/corpus/31_rcparams_figsize.py), [`33_set_data_mutation.py`](../../tests/pyplot/corpus/33_set_data_mutation.py), [`34_gray_string_color.py`](../../tests/pyplot/corpus/34_gray_string_color.py), [`35_tab_colors.py`](../../tests/pyplot/corpus/35_tab_colors.py), [`36_color_cycle_c0_c9.py`](../../tests/pyplot/corpus/36_color_cycle_c0_c9.py), [`37_markers_only_fmt.py`](../../tests/pyplot/corpus/37_markers_only_fmt.py), [`38_close_all_hygiene.py`](../../tests/pyplot/corpus/38_close_all_hygiene.py), [`39_multiple_figures.py`](../../tests/pyplot/corpus/39_multiple_figures.py), [`40_subplots_row_sharex.py`](../../tests/pyplot/corpus/40_subplots_row_sharex.py), [`41_line_kwargs.py`](../../tests/pyplot/corpus/41_line_kwargs.py), [`43_grid_html_suptitle.py`](../../tests/pyplot/corpus/43_grid_html_suptitle.py), [`44_subplot_classic.py`](../../tests/pyplot/corpus/44_subplot_classic.py), [`45_xticks_positions_labels.py`](../../tests/pyplot/corpus/45_xticks_positions_labels.py), [`55_polar_projection.py`](../../tests/pyplot/corpus/55_polar_projection.py), [`56_partial_subplots_legend_proxies.py`](../../tests/pyplot/corpus/56_partial_subplots_legend_proxies.py) - `errorbar` — [`47_statistical_families.py`](../../tests/pyplot/corpus/47_statistical_families.py) -- `scatter` — [`10_scatter_basic.py`](../../tests/pyplot/corpus/10_scatter_basic.py), [`11_scatter_color_array_cmap.py`](../../tests/pyplot/corpus/11_scatter_color_array_cmap.py), [`12_scatter_size_array.py`](../../tests/pyplot/corpus/12_scatter_size_array.py), [`13_scatter_edgecolors.py`](../../tests/pyplot/corpus/13_scatter_edgecolors.py), [`27_subplots_2x2_mixed.py`](../../tests/pyplot/corpus/27_subplots_2x2_mixed.py), [`55_polar_projection.py`](../../tests/pyplot/corpus/55_polar_projection.py) +- `scatter` — [`10_scatter_basic.py`](../../tests/pyplot/corpus/10_scatter_basic.py), [`11_scatter_color_array_cmap.py`](../../tests/pyplot/corpus/11_scatter_color_array_cmap.py), [`12_scatter_size_array.py`](../../tests/pyplot/corpus/12_scatter_size_array.py), [`13_scatter_edgecolors.py`](../../tests/pyplot/corpus/13_scatter_edgecolors.py), [`27_subplots_2x2_mixed.py`](../../tests/pyplot/corpus/27_subplots_2x2_mixed.py), [`55_polar_projection.py`](../../tests/pyplot/corpus/55_polar_projection.py), [`56_partial_subplots_legend_proxies.py`](../../tests/pyplot/corpus/56_partial_subplots_legend_proxies.py) - `step` — [`22_step.py`](../../tests/pyplot/corpus/22_step.py) - `loglog` — [`51_basic_2d_aliases.py`](../../tests/pyplot/corpus/51_basic_2d_aliases.py) - `semilogx` — [`54_plotting_method_coverage.py`](../../tests/pyplot/corpus/54_plotting_method_coverage.py) - `semilogy` — [`54_plotting_method_coverage.py`](../../tests/pyplot/corpus/54_plotting_method_coverage.py) - `fill_between` — [`20_fill_between_band.py`](../../tests/pyplot/corpus/20_fill_between_band.py) - `fill_betweenx` — [`51_basic_2d_aliases.py`](../../tests/pyplot/corpus/51_basic_2d_aliases.py) -- `bar` — [`14_bar_categories.py`](../../tests/pyplot/corpus/14_bar_categories.py), [`15_bar_stacked_bottom.py`](../../tests/pyplot/corpus/15_bar_stacked_bottom.py), [`27_subplots_2x2_mixed.py`](../../tests/pyplot/corpus/27_subplots_2x2_mixed.py), [`32_xticks_rotation.py`](../../tests/pyplot/corpus/32_xticks_rotation.py), [`42_tick_params_rotation.py`](../../tests/pyplot/corpus/42_tick_params_rotation.py), [`55_polar_projection.py`](../../tests/pyplot/corpus/55_polar_projection.py) +- `bar` — [`14_bar_categories.py`](../../tests/pyplot/corpus/14_bar_categories.py), [`15_bar_stacked_bottom.py`](../../tests/pyplot/corpus/15_bar_stacked_bottom.py), [`27_subplots_2x2_mixed.py`](../../tests/pyplot/corpus/27_subplots_2x2_mixed.py), [`32_xticks_rotation.py`](../../tests/pyplot/corpus/32_xticks_rotation.py), [`42_tick_params_rotation.py`](../../tests/pyplot/corpus/42_tick_params_rotation.py), [`55_polar_projection.py`](../../tests/pyplot/corpus/55_polar_projection.py), [`56_partial_subplots_legend_proxies.py`](../../tests/pyplot/corpus/56_partial_subplots_legend_proxies.py) - `barh` — [`16_barh.py`](../../tests/pyplot/corpus/16_barh.py) - `bar_label` — [`53_matplotlib_311_plotting.py`](../../tests/pyplot/corpus/53_matplotlib_311_plotting.py) - `grouped_bar` — [`53_matplotlib_311_plotting.py`](../../tests/pyplot/corpus/53_matplotlib_311_plotting.py) @@ -45,7 +45,7 @@ Approximation level: **equivalent semantics**. - `stackplot` — [`46_stackplot.py`](../../tests/pyplot/corpus/46_stackplot.py) - `broken_barh` — [`51_basic_2d_aliases.py`](../../tests/pyplot/corpus/51_basic_2d_aliases.py) - `vlines` — [`51_basic_2d_aliases.py`](../../tests/pyplot/corpus/51_basic_2d_aliases.py) -- `hlines` — [`51_basic_2d_aliases.py`](../../tests/pyplot/corpus/51_basic_2d_aliases.py) +- `hlines` — [`51_basic_2d_aliases.py`](../../tests/pyplot/corpus/51_basic_2d_aliases.py), [`56_partial_subplots_legend_proxies.py`](../../tests/pyplot/corpus/56_partial_subplots_legend_proxies.py) - `fill` — [`54_plotting_method_coverage.py`](../../tests/pyplot/corpus/54_plotting_method_coverage.py), [`55_polar_projection.py`](../../tests/pyplot/corpus/55_polar_projection.py) ### Spans @@ -124,7 +124,7 @@ Approximation level: **equivalent semantics**. Approximation level: **visual approximation**. - `annotate` — [`25_annotate_text.py`](../../tests/pyplot/corpus/25_annotate_text.py) -- `text` — [`25_annotate_text.py`](../../tests/pyplot/corpus/25_annotate_text.py) +- `text` — [`25_annotate_text.py`](../../tests/pyplot/corpus/25_annotate_text.py), [`56_partial_subplots_legend_proxies.py`](../../tests/pyplot/corpus/56_partial_subplots_legend_proxies.py) - `table` — [`53_matplotlib_311_plotting.py`](../../tests/pyplot/corpus/53_matplotlib_311_plotting.py) - `arrow` — [`54_plotting_method_coverage.py`](../../tests/pyplot/corpus/54_plotting_method_coverage.py) diff --git a/spec/matplotlib/compat.md b/spec/matplotlib/compat.md index 3c5b02391..f1a4301fb 100644 --- a/spec/matplotlib/compat.md +++ b/spec/matplotlib/compat.md @@ -51,44 +51,46 @@ dependency-free `triangles=` shorthand into Matplotlib's equivalent | matplotlib | notes | |---|---| | `plt.plot` / `ax.plot` | format strings (`'r--o'`), multiple series per call, implicit x, `label=`, `lw=`, `ls=`, `alpha=`, marker face/edge styling, directional `^`/`v`/`<`/`>` triangles and distinct `+`/`x` glyphs, `markevery`, and dependency-free affine *data* transforms (`Affine2D + ax.transData`); axes/figure-fraction transforms on data artists, partial fill styles, and cap/join policies fail loudly | -| `scatter(x, y, s=, c=, cmap=, vmin=, vmax=, alpha=, marker=, edgecolors=, plotnonfinite=)` | `s` (pt², area) maps to pixel diameter; numeric 1-D `c` remains a colormap encoding, while `N×3`/`N×4` face and edge colors, alpha arrays, sizes, and linewidth arrays stay in one collection. Explicit alpha replaces intrinsic RGBA alpha, matching Matplotlib; custom norms/marker paths fail loudly | -| `bar`, `barh`, `grouped_bar`, `bar_label` | string categories, stacking bases, per-bar face/edge color-alpha pairs and linewidths, plus iterable/indexable `BarContainer.patches` views whose setters mutate the parent batched trace | -| `hist(bins=, range=, density=, cumulative=, weights=, orientation=, stacked=)` | Returns computed counts/edges; stacked density normalizes the combined weighted area once (including unequal bins and either cumulative direction), matching Matplotlib 3.11; bar, step, and stepfilled families render in both vertical and horizontal orientations; unfilled step outlines connect their top envelope to zero or the previous stack at both endpoints | +| `scatter(x, y, s=, c=, cmap=, vmin=, vmax=, alpha=, marker=, edgecolors=, facecolors=, plotnonfinite=)` | `s` (pt², area) maps to pixel diameter; `facecolors=`/`facecolor=` is the fallback face paint when `c` is absent (`facecolors="none"` draws hollow markers, as `c="none"` does); numeric 1-D `c` remains a colormap encoding, while `N×3`/`N×4` face and edge colors, alpha arrays, sizes, and linewidth arrays stay in one collection. Explicit alpha replaces intrinsic RGBA alpha, matching Matplotlib; custom norms/marker paths fail loudly | +| `bar`, `barh`, `grouped_bar`, `bar_label` | string categories (also with `xerr=`/`yerr=`: the error-bar centres autoscale on the category axis), `tick_label=` on numeric positions (one labeled tick per bar; with string categories it fails loudly), `log=True` (value axis on a log scale), stacking bases, per-bar face/edge color-alpha pairs and linewidths, plus iterable/indexable `BarContainer.patches` views whose setters mutate the parent batched trace and whose `get_x`/`get_y`/`get_width`/`get_height`/`get_xy`/`get_center`/`get_bbox` report Matplotlib's rectangle geometry in data space (category positions resolve to 0, 1, 2, ...), so the `ax.text(r.get_x() + r.get_width() / 2, r.get_height(), ...)` labeling idiom works | +| `hist(bins=, range=, density=, cumulative=, weights=, orientation=, stacked=, bottom=, align=, log=)` | Returns computed counts/edges (raw counts even with `bottom=`); `bottom=` lifts the baseline (scalar or per bin) and seeds the stack, `align="left"`/`"right"` centre bars on the bin edges (step histtypes accept only `"mid"` and fail loudly otherwise), `log=True` puts the count axis on a log scale; stacked density normalizes the combined weighted area once (including unequal bins and either cumulative direction), matching Matplotlib 3.11; bar, step, and stepfilled families render in both vertical and horizontal orientations; unfilled step outlines connect their top envelope to zero or the previous stack at both endpoints | | `hist2d`, `hexbin`, `ecdf` | 2D uniform binning uses the native Rust kernel. `hist2d` delegates rendering to the pseudocolor-mesh path for both uniform and non-uniform bins, supports linear and logarithmic normalization, defaults to fully opaque cells, and retains the original count domain for logarithmic mappables. Its view limits are the outer bin edges with no margin, matching Matplotlib's sticky mesh edges. Arbitrary custom normalization and `colorizer` remain unsupported. Hexbin uses Matplotlib's two-offset-grid nearest-center assignment and six-triangle data-space cells, supports `C`, arbitrary scalar reducers, and `mincnt`, and retains only the bounded lattice rather than source points. `ecdf` carries the ordinary margin on the sample axis and is sticky at 0 and 1 on the cumulative axis | | `boxplot`, `violinplot`, `bxp`, `violin`, `errorbar` | Boxplots support notches, bootstrap/user confidence intervals, median overrides (drawn median only; notch CIs stay data-derived like Matplotlib), percentile/custom whiskers, cap widths, `sym`, dashed line-component styles, and component colors/widths/alpha. Default boxes are unfilled outlines and return Matplotlib-shaped per-group component handles (two whiskers/caps and one box/median/flier handle per group). `patch_artist=True` emits mutable filled polygon boxes; statistics labels become category tick labels, while scalar or per-box legend labels bind to boxes for patch plots and medians otherwise. Violins use Gaussian KDE for the default Scott bandwidth and explicit Scott/Silverman/scalar/callable bandwidths, return one seam-free mutable body per group, cycle face and line color sequences, preserve color-alpha pairs, and support quantiles and low/high sides. `boxplot` autoscales its value axis over the Tukey whiskers plus, when `showfliers` is on, the flier points. Its default category positions are 1-based and `manage_ticks=True` reserves half a unit around the outer positions, matching Matplotlib | -| `fill_between(x, y1, y2, where=, step=)` / `fill_betweenx` | Masks are split into finite contiguous polygons; step geometry is expanded exactly | +| `errorbar(capsize=, capthick=, ecolor=, elinewidth=, fmt=, mfc=, mec=, mew=, ...)` | `capthick` sets the cap stroke (default `lines.markeredgewidth`, as Matplotlib); `markerfacecolor`/`markeredgecolor`/`markeredgewidth` and their `mfc`/`mec`/`mew` aliases style the data markers; `barsabove` and `elinestyle` fail loudly | +| `fill_between(x, y1, y2, where=, step=)` / `fill_betweenx` | Masks are split into finite contiguous polygons; step geometry is expanded exactly. Datetime-like `x` (`fill_betweenx`: `y`) — `datetime`, `date`, `datetime64`, pandas `Timestamp` — takes the same ms-since-epoch conversion `plot()` uses, and the axis stays a date axis even when the fill is the only artist (`fill_between` stores its polygons' x back as `datetime64[ms]`; `fill_betweenx` pins the y axis kind to `time`) | | `stackplot` | All four baselines are computed by the native stacked-bounds kernel | | `psd`, `csd`, `cohere`, `specgram` | Native real-valued Hann-windowed Welch spectra use Matplotlib 3.11's default `detrend_none` semantics. Callable windows/detrending, independent `pad_to`, explicit sides/frequency scaling, and complex/two-sided inputs remain unsupported and fail loudly instead of silently changing the signal; completing these is tracked acceptance debt for `statistics/psd_demo.py` | | `imshow` / `pcolormesh` (`cmap=`, `vmin=`/`vmax=`, `origin=`) | `imshow` defaults to `rcParams['image.origin']`; nearest stays cell-exact, while named smoothing modes use dependency-free per-kernel approximations over a bounded 512–1024 px intermediate for both scalar and RGB(A) data. Filter choice and intermediate size do not yet depend on final display resolution, and explicit `interpolation="auto"` remains unsupported. Unsupported stages/transforms fail loudly. Uniform meshes retain the texture fast path; nonuniform and curvilinear grids use native quad-to-triangle expansion. Both hug their outer cell edge with no margin, as Matplotlib's sticky image/mesh edges do | | `step`, `stairs`, `stem`, `eventplot` | Compact step/stem/segment marks; no Python-side vertex expansion | +| `hlines` / `vlines` | `colors` (a name, one RGB(A) tuple, or a per-line sequence whose first entry wins), `linestyles` and Matplotlib's singular `linestyle`/`ls` spelling (dashes are data-space sub-segments), `linewidth(s)`, `alpha`, `label`, `data`, `transform` | | `contour` / `contourf` / `clabel` | Native marching squares over rectilinear grids; warped grids route through native Delaunay/marching-triangle kernels; automatic labels repeat at bounded, separated positions along each level (line knockout for `inline=True` remains a visual approximation) | | `quiver`, `barbs`, `streamplot` | Quiver supports Matplotlib's width-unit vocabulary independently from length scaling. Barbs use fixed-length staffs and Matplotlib's flag/full/half decomposition, including increments, rounding, empty glyphs, colors, sizes, flipping, and pivots. Streamplot uses a dependency-free adaptive Heun integrator with occupancy-aware seeding; `start_points`, `integration_direction`, `broken_streamlines`, integration step/error scales, array widths/colors, and `num_arrows` are honored | | `tripcolor`, `triplot`, `tricontour`, `tricontourf` | Explicit topology or native dependency-free Delaunay triangulation; indexed geometry and isolines stay in Rust | | `pie` / `pie_label` | Native pie/donut tessellation and the Matplotlib 3.11 `PieContainer` (`values`, `fracs`, grouped text labels), including dtype-preserving value formats, radial label rotation/alignment, and common text properties | -| `axhline` / `axvline` / `axhspan` / `axvspan`, `text`, `annotate`, `table` | Fractional span bounds plus data/axes/figure text coordinates are supported. `annotate(arrowprops=)` draws real arrows in every output: offset-point text becomes an engine callout (arrow pinned from label to point across zoom), data-coordinate text an arrow annotation; date-string coordinates convert on datetime axes. Arrowstyles map to head/tail shapes (`->` open V, `-\|>` filled, `\|-\|`/brackets bar caps, `fancy`/`simple`/`wedge` filled tapered shafts sized by the text's mutation scale) and `connectionstyle` arc3/angle3/angle become quadratic curves (corner rounding approximated); `alpha` dims the arrow only. `bbox=` becomes label box styles (fill/edge/round corners/`pad`) in browser and static exports; its `alpha` is the *patch* alpha and dims face and edge together, as Matplotlib's element `opacity` does, and `boxstyle="round"`/`round4` corners are rounded in SVG (`rx`) and native PNG as well as in the browser. An arrow-less `text`/`annotate` label is painted with `rcParams["text.color"]` in all three renderers rather than each renderer's own annotation-label default. Text is unclipped like Matplotlib (`clip_on=False`), and axes-fraction text right of the axes box (x > 1, e.g. seaborn-style row titles) reserves right margin in every exporter. `rotation=90/270` renders vertical text in browser, PNG, and SVG with Matplotlib's rotate-then-align box semantics; other angles rotate in browser and SVG output only (native PNG draws them horizontally) | +| `axhline` / `axvline` / `axhspan` / `axvspan`, `text`, `annotate`, `table` | Fractional span bounds plus data/axes/figure text coordinates are supported; `text(alpha=)` dims the label the way `Text.set_alpha` does. Rules and spans autoscale exactly as Matplotlib's `dataLim` does: their finite data coordinate extends the axis they are positioned on (an `axhline` widens y, an `axvspan` widens x) and their infinite extent and fractional bounds never touch the perpendicular axis; a NaN position contributes nothing. Those limits reach every exporter: because the engine autoscales from its traces alone and rules/bands are annotations, an axis a rule or span widens ships the autoscaled limits (`get_xlim()`/`get_ylim()`, margins included) as its exact `domain` instead of the engine's `margin`; span-free axes keep the engine's margin-based autoscale byte for byte. `label=` names the artist for the legend and draws no text (Matplotlib draws none either): `get_legend_handles_labels()` lists rules as `Line2D` and spans as patch artists in artist order, and `legend()` ships those rows as explicit legend items — a line sample carrying the rule's color/width/dash, a filled swatch carrying the span's color/alpha — because annotations are not traces the renderers could name. `annotate(arrowprops=)` draws real arrows in every output: offset-point text becomes an engine callout (arrow pinned from label to point across zoom), data-coordinate text an arrow annotation; date-string coordinates convert on datetime axes. Arrowstyles map to head/tail shapes (`->` open V, `-\|>` filled, `\|-\|`/brackets bar caps, `fancy`/`simple`/`wedge` filled tapered shafts sized by the text's mutation scale) and `connectionstyle` arc3/angle3/angle become quadratic curves (corner rounding approximated); `alpha` dims the arrow only. `bbox=` becomes label box styles (fill/edge/round corners/`pad`) in browser and static exports; its `alpha` is the *patch* alpha and dims face and edge together, as Matplotlib's element `opacity` does, and `boxstyle="round"`/`round4` corners are rounded in SVG (`rx`) and native PNG as well as in the browser. An arrow-less `text`/`annotate` label is painted with `rcParams["text.color"]` in all three renderers rather than each renderer's own annotation-label default. Text is unclipped like Matplotlib (`clip_on=False`), and axes-fraction text right of the axes box (x > 1, e.g. seaborn-style row titles) reserves right margin in every exporter. `rotation=90/270` renders vertical text in browser, PNG, and SVG with Matplotlib's rotate-then-align box semantics; other angles rotate in browser and SVG output only (native PNG draws them horizontally). Before/after for span autoscale and legend rows: `spec/assets/pyplot-span-autoscale-before-after.png` | | `from xy.pyplot import FacetGrid` (seaborn-shaped) | Row/column small multiples with seaborn's `map` contract (subset → activate panel → call the pyplot function), shared domains, edge-only axis labels, top-row column titles, and `margin_titles=True` rotated row titles. `hue=`/`palette=`, `col_wrap=`, `map_dataframe`, and `add_legend` fail loudly | | `xlabel` / `ylabel` / `title` / `suptitle` | Suptitles are retained in HTML and multi-panel PNG/SVG. `ylabel` sits clear of the y tick labels in every renderer: the left gutter is reserved from the measured advances of the tick labels and the rotated title rather than from a fixed constant, leaving Matplotlib's `0.4 em` (5.6 px at the 10 pt/100 dpi default) title-to-tick gap — see *Measured left gutter and the rotated y-axis title* in `spec/api/styling.md` for the formula and its two documented asymmetries | -| `legend()` | `loc`, columns, title/font size/colors, frame styling, `borderpad`, `labelspacing`, `borderaxespad`, `fancybox`, `framealpha`, and `shadow` are retained across browser and static output. `loc='best'` scores the measured displayed legend box in Matplotlib location-code order using path vertices/crossings, collection offsets, and bar-rectangle overlaps. It resolves before the wire; pyplot rejects misspelled Matplotlib locations without narrowing core `xy.legend()`'s independent location vocabulary. Text-box scoring and bounded long-path sampling are documented in `spec/api/styling.md` § Legend placement | +| `legend()` | Call forms `legend()`, `legend(labels)`, `legend(handles, labels)`, and the keyword spellings `legend(handles=, labels=)`, `legend(handles=)` (labels read off the handles, underscore labels included, as Matplotlib does) and `legend(labels=)`. `loc` accepts Matplotlib's names, its integer codes 0–10 (`Legend.codes`: 0 best, 1 upper right, ... 10 center), and an `(x, y)` axes-fraction tuple that anchors the legend's lower-left corner there. Proxy handles work: `plt.Line2D([0], [0], color=, linestyle=, linewidth=, marker=, markersize=, mfc=, mec=, mew=, alpha=, label=)`, `plt.Patch(facecolor=, edgecolor=, linewidth=, alpha=, hatch=, fill=, label=)`, and `plt.Rectangle((x, y), w, h, **patch style)` (also accepted by `add_patch`) own no axes and freeze into swatches through the same path as plotted artists (dashes and marker sizes are scaled from points at the owning figure's DPI). `loc`, columns, title/font size/colors, frame styling, `borderpad`, `labelspacing`, `borderaxespad`, `fancybox`, `framealpha`, and `shadow` are retained across browser and static output. `loc='best'` scores the measured displayed legend box in Matplotlib location-code order using path vertices/crossings, collection offsets, and bar-rectangle overlaps. It resolves before the wire; pyplot rejects misspelled Matplotlib locations without narrowing core `xy.legend()`'s independent location vocabulary. Text-box scoring and bounded long-path sampling are documented in `spec/api/styling.md` § Legend placement | | `grid(True/False)` | toggles the grid via the theme | -| `xlim` / `ylim`, `set_xmargin` / `set_ymargin`, axis scales, `invert_xaxis/yaxis` | linear/log are native; symlog/logit/asinh use dependency-free monotone data transforms with inverse limit/tick semantics. Automatic linear ticks include Matplotlib's 2.5 step and use uniform decimal padding across a tick set; locations refresh as data arrives. `axes.autolimit_mode="round_numbers"` expands automatic linear limits to the first and last AutoLocator ticks after applying the configured margins. Artist `get_data()` reflects the transformed space; logit masks values at/outside (0, 1) | -| `set_major_locator` / `set_major_formatter`, `plt.NullLocator/FixedLocator/MultipleLocator/MaxNLocator/LinearLocator/LogLocator`, `plt.NullFormatter/FixedFormatter/FuncFormatter/FormatStrFormatter/StrMethodFormatter/ScalarFormatter` | xy-owned re-implementations resolved at build time against live data limits (Null/Fixed/Multiple/Linear are position-exact; MaxN/Auto port Matplotlib's `MaxNLocator._raw_ticks` — same step tables, edge extension, and offset handling — with `nbins="auto"` budgeted from the estimated plot rect like `Axis.get_tick_space()`; Log remains approximate). Third-party locator objects work if they implement `tick_values(vmin, vmax)`; minor locators/formatters are retained for round-tripping but minor ticks do not render, except that a labeled minor pair under a blanked major formatter (the centered date-label idiom) is promoted to the drawn tick set | +| `xlim` / `ylim`, `set_xmargin` / `set_ymargin`, axis scales, `invert_xaxis/yaxis` | linear/log are native; symlog/logit/asinh use dependency-free monotone data transforms with inverse limit/tick semantics. Automatic linear ticks include Matplotlib's 2.5 step and use uniform decimal padding across a tick set; locations refresh as data arrives. `axes.autolimit_mode="round_numbers"` expands automatic linear limits to the first and last AutoLocator ticks after applying the configured margins. Artist `get_data()` reflects the transformed space; logit masks values at/outside (0, 1). `set_xlim`/`set_ylim` (and `plt.xlim`/`plt.ylim`) and `set_xticks`/`set_yticks` accept every datetime-like `plot()` accepts — `datetime`, `date`, `datetime64`, pandas `Timestamp`, and date strings on a datetime axis — converting them to the engine's ms-since-epoch floats, which is also what `get_xlim()`/`get_xticks()` report on a date axis (not Matplotlib's day floats) | +| `set_major_locator` / `set_major_formatter`, `plt.NullLocator/FixedLocator/MultipleLocator/MaxNLocator/LinearLocator/LogLocator`, `plt.NullFormatter/FixedFormatter/FuncFormatter/FormatStrFormatter/StrMethodFormatter/ScalarFormatter` | xy-owned re-implementations resolved at build time against live data limits (Null/Fixed/Multiple/Linear are position-exact; MaxN/Auto port Matplotlib's `MaxNLocator._raw_ticks` — same step tables, edge extension, and offset handling — with `nbins="auto"` budgeted from the estimated plot rect like `Axis.get_tick_space()`; Log remains approximate). Third-party locator objects work if they implement `tick_values(vmin, vmax)`; one whose `tick_values` raises `NotImplementedError` (Matplotlib's abstract `Locator` base) is called through Matplotlib's own `__call__` protocol when it is bound to an axis, and otherwise dropped so the axis keeps its kind's default ticks (a date axis keeps its date ticks) instead of failing the build. Minor locators/formatters are retained for round-tripping but minor ticks do not render, except that a labeled minor pair under a blanked major formatter (the centered date-label idiom) is promoted to the drawn tick set. `ticklabel_format(axis=, style=, scilimits=, useOffset=, useMathText=)` configures the axis `ScalarFormatter` exactly as Matplotlib does (installing one when no formatter is set; any other installed formatter raises `AttributeError`): `style="plain"` labels the located ticks with the shared decimal count Matplotlib's `_set_format` derives from the tick spacing, and `style="sci"` switches to mantissas once the ticks' order of magnitude leaves `scilimits` (default `(-5, 6)`, Matplotlib's `axes.formatter.limits`). **Compat-noop:** the shim has no offset-text slot, so `useOffset` never factors an offset out — labels always carry the full value — and the scientific exponent is written on every label (`1.25e6`, or `1.25×10⁶` under `useMathText=True`) rather than once beside the axis. `useLocale=True` raises | | `plt.dates.MonthLocator/YearLocator/DayLocator/DateFormatter` | xy-owned equivalents of the `matplotlib.dates` classes gallery scripts use; they locate and format in the engine's canonical ms-since-epoch axis unit (not Matplotlib's day floats), and `interval` approximates rrule by epoch-anchored occurrence counting | -| datetime, timedelta, and string coordinates | datetime inputs use the engine's automatic date ticks, timedeltas are bounded to elapsed seconds, and common strings use categorical ticks; the general Matplotlib units registry is intentionally out of scope. pandas datetime plotting (`series.plot(ax=ax)`) works against that contract: `get_{x,y}data(orig=False)` returns ms-since-epoch floats, and pandas' period-ordinal tickers (`TimeSeries_Date*`) are accepted as no-ops so the native date ticks keep rendering | -| `xticks(positions, labels, rotation=)` / `tick_params(labelrotation=)` | Exact positions and strings render in browser, PNG, and SVG | +| datetime, timedelta, and string coordinates | datetime inputs use the engine's automatic date ticks, timedeltas are bounded to elapsed seconds, and common strings use categorical ticks; the general Matplotlib units registry is intentionally out of scope. pandas datetime plotting (`series.plot(ax=ax)`) works against that contract: `get_{x,y}data(orig=False)` returns ms-since-epoch floats, and pandas' period-ordinal tickers (`TimeSeries_Date*`) are accepted as no-ops on both the major and the minor tier so the native date ticks keep rendering (pandas 3.0.5's minor `TimeSeries_DateLocator` has no `tick_values`; see the locator row above for the general fallback) | +| `xticks(positions, labels, rotation=)` / `tick_params(labelrotation=)` | Exact positions and strings render in browser, PNG, and SVG. The stateful `plt.tick_params`, `plt.margins`, and `plt.locator_params` delegate to the current axes like every other `plt.*` wrapper | | `twinx()`, `secondary_xaxis()`, `secondary_yaxis()` | second data axes and linked tick-only secondary axes with callable forward/inverse conversions. Secondary-axis ticks are evenly spaced conversions of the primary domain (not Matplotlib's secondary-unit locators) and currently reach the interactive HTML client only — PNG/SVG export does not draw them yet | | `fig, ax = plt.subplots()`; `plt.subplots(n, m, figsize=, dpi=, squeeze=, sharex=, sharey=)` | Grid renders as CSS-grid HTML and stitched PNG/SVG; shared axes use common domains and live linked pan/zoom. `Figure.subplots_adjust(left=, right=, top=, bottom=, wspace=, hspace=)` moves the SubplotParams frame: the grid resolves to explicit figure rectangles and every exporter (HTML, PNG, SVG) positions panels at those rectangles | | `subplot(projection="polar")`; `add_subplot(..., polar=True)`; `axes(projection="polar")`; `subplots(subplot_kw={"projection": "polar"})` | Ordinary `plot`, `scatter`, `fill`, `bar`, heatmap/image, contour, and error-bar calls render through the core polar coordinate system in HTML, PNG, and SVG. The PolarAxes controls `set_theta_zero_location`, `set_theta_direction`, `set_theta_offset`, `set_thetagrids`, `set_thetamin`/`set_thetamax` (degrees), `set_rlim`, `set_rticks`, `set_rorigin`, and their theta/r limit accessors route into the same angular/radial axes. Categorical θ and log/symlog radial scales use that core transform as well. Polar `axhline`/`axvline` and span geometry, LOD, facets/animation, angular navigation/selection, and the stateful `plt.polar`/`plt.thetagrids`/`plt.rgrids` convenience wrappers remain outside this surface and fail or remain absent rather than drawing a Cartesian approximation. **Silently dropped on a polar Axes:** minor ticks and their style (`minorticks_on`, `minor` `tick_params`, `set_minor_locator`), tick-label horizontal alignment (`tick_params(ha=)`), and the tick-label collision strategies — no renderer draws minor rings or spokes, and rim labels have no edge-relative collision pass or anchor (`spec/design/polar-axes.md` §9). They are dropped rather than refused because every Axes carries an rcParam-derived `minor_style`, so refusing would break the projection over a default nobody authored; a hand-authored `xy.theta_axis`/`xy.r_axis` refuses them instead. | | `Axes.get_position(original=False)` and the rendered axes frame | Supported subplot and free-form axes report their live figure rectangle and render on it. `original=True` returns the allocated rectangle before an adjustable-box aspect correction; the default applies the correction and its anchor, matching Matplotlib. Grid cells resolve under the live SubplotParams (`wspace`/`hspace`, width/height ratios), while explicit `add_axes`/`set_position` rectangles take precedence until a later layout adjustment. Titles, top-side x axes (`matshow`), and secondary-y gutters grow the surrounding allocation instead of moving the frame. **Known exception:** an axes carrying a colorbar keeps label-aware margins because xy and Matplotlib currently reserve the colorbar strip through different layout paths | -| `fig.add_subplot(2, 2, 1)` / `add_subplot(221)` | | +| `fig.add_subplot(2, 2, 1)` / `add_subplot(221)` / `plt.subplot(n, m, i)` | A numbered cell of a multi-cell grid creates *only* that cell, positioned at its GridSpec rectangle under the live SubplotParams: `subplot(221); plot(); subplot(224); plot()` leaves two axes and two blank cells, and grids of different shapes share one figure (`subplot(2, 2, 1)`, `subplot(2, 2, 2)`, `subplot(2, 1, 2)`) as long as their cells do not overlap — Matplotlib's semantics. `plt.subplot()` returns the existing axes for a cell created before; `Figure.add_subplot()` always adds a new one. Only the whole-figure `111` keeps the uniform single-chart path, and `num` outside `1..n*m` raises Matplotlib's `ValueError`. Before/after: `spec/assets/pyplot-subplot-cells-before-after.png` | | `plt.subplot_mosaic([['A','B'],['C','C']])` / `Figure.subplot_mosaic` | Row sequences (a list of equal-length label strings, or nested label lists) resolve to a uniform grid; each distinct label, in first-appearance order, binds to the next cell, returning `(fig, {label: Axes})` with `figsize=`/`dpi=` sizing the figure. Repeated labels do not span and `'.'` does not blank a cell — the grid keeps one axes per cell — and Matplotlib's single-string forms (`'AB;CC'`, newline-separated blocks) are not parsed into rows | | `gca` / `gcf` / `sca` / `figure(num)` / `close(...)` | matplotlib's implicit-state semantics | | `savefig('x.png' / '.svg' / '.html', dpi=)` | Browser-free PNG/SVG supports both single and multi-panel figures; file-like targets require an explicit `format=` and unsupported metadata/layout/export formats fail loudly | | `plt.show()` | notebooks: inline HTML display; scripts: opens the default browser | | Artists: `set_data` / `set_ydata` / `set_color` / `set_label` / `set_linewidth` / `remove` | mutating a handle rebuilds the chart on next render. Scatter collections additionally vectorize facecolors, edgecolors, alpha, linewidths, and sizes; `alpha=None` restores intrinsic paint alpha | | Colors | single letters, `C0`–`C9`, `tab:*`, gray `'0.5'`, RGB(A) tuples, `(color, alpha)` pairs, per-item RGB(A) arrays, and any CSS color | -| `plt.cm.*` / `plt.colormaps[...]` / `cmap=` names | viridis, plasma, inferno, magma, cividis, gray, bone, autumn, winter, turbo, coolwarm, Blues, Purples, Reds, PuBu, BuPu, RdBu, RdYlGn, RdGy, PiYG, PRGn, jet, rainbow, Spectral, binary, aliases, and true `*_r` reversal resolved generically for every listed name, including `plt.cm._r` attribute access (RdGy/jet/Reds/bone/autumn/winter/BuPu render from 11-stop anchor tables sampled from Matplotlib 3.11, linearly interpolated) | +| `plt.cm.*` / `plt.colormaps[...]` / `plt.get_cmap` / `cmap=` names | `plt.cm.` and `plt.get_cmap(name)` return callable colormap objects with `.N` (`plt.cm.viridis(np.linspace(0, 1, 3))` → RGBA rows) that plotting calls accept as `cmap=`; Matplotlib's qualitative palettes tab10, tab20, tab20b, tab20c, Set1–3, Paired, Accent, Dark2, Pastel1, Pastel2 (and their `_r`) come back as callable `ListedColormap`s — indexable by integer or fraction, but not passable as `cmap=` (no engine table; fails loudly). Engine colormaps: viridis, plasma, inferno, magma, cividis, gray, bone, autumn, winter, turbo, coolwarm, Blues, Purples, Reds, PuBu, BuPu, RdBu, RdYlGn, RdGy, PiYG, PRGn, jet, rainbow, Spectral, binary, aliases, and true `*_r` reversal resolved generically for every listed name, including `plt.cm._r` attribute access (RdGy/jet/Reds/bone/autumn/winter/BuPu render from 11-stop anchor tables sampled from Matplotlib 3.11, linearly interpolated) | | `LinearSegmentedColormap.from_list` / `ListedColormap` | Python-side callables (`cmap(np.arange(cmap.N))` → RGBA) for scripts that colormap values themselves; they cannot be passed as `cmap=` to plotting calls (no engine table), which fails loudly | -| `plt.colorbar()` / `fig.colorbar()` / `plt.clim()` / `plt.gci()` | Returns a live handle (`set_label`, `set_ticks`); with no mappable it uses the current image the way pyplot does. `ticks=`/`extend=` render in PNG and SVG (the HTML colorbar stays a minimal gradient without tick text); `clim` retargets the mappable's color window and any colorbar derived from it | +| `plt.colorbar()` / `fig.colorbar()` / `plt.clim()` / `plt.gci()` | Returns a live handle (`set_label`, `set_ticks`); `fraction=` is an accepted no-op (the colorbar strip has a fixed width); with no mappable it uses the current image the way pyplot does. `ticks=`/`extend=` render in PNG and SVG (the HTML colorbar stays a minimal gradient without tick text); `clim` retargets the mappable's color window and any colorbar derived from it | | `Colorbar.set_label(...)` / `colorbar(label=...)` | Matplotlib's default label geometry in all three renderers: beside a vertical bar rotated 90° counter-clockwise and centered on it, or upright and centered below a horizontal bar. The vertical label is a quarter turn, which the native PNG rasterizer renders exactly (only arbitrary text angles fall back to upright glyphs there), and the reserved right-margin room contains its cross-axis glyph extent. `set_label` ignores Matplotlib's customization kwargs (`loc=`, `labelpad=`, `rotation=`, font properties) rather than failing — the default orientation is derived from the bar | | `rcParams` | Figure size/DPI, line width/marker size, image cmap/origin, axes color cycle, and all four `axes.spines.*` switches affect every exporter. Pyplot axes default to Matplotlib's four-sided box and each spine can be hidden independently. The chrome keys (axes face/edge/label/title styles, font family/size, tick colors/sizes, legend defaults, figure facecolor) reach the HTML renderer and multi-panel PNG stitching; single-chart PNG and SVG export currently render their own fixed chrome and ignore most of them. `axes.titleweight` and `axes.labelweight` are supported and verified to reach all three renderers (browser, single-chart SVG, single-chart native PNG); both default to `normal`, matching Matplotlib. Unknown keys warn once | | Text weight | Title, axis-label, tick-label, legend, legend-title, colorbar-title, and annotation text all default to normal (400) weight in every renderer, matching Matplotlib's `axes.titleweight`/`axes.labelweight`/`font.weight` defaults. Heavier text needs an explicit `fontweight=`, `label_font_weight`, `styles[slot]`, or rcParam. Native PNG approximates: the bounded font atlas holds one regular and one bold face, so weights `>= 600` render bold and everything lighter renders regular — intermediate weights are not distinguishable in native PNG, while browser and SVG output pass the requested weight through verbatim. See [styling § Chrome text weight](../api/styling.md#chrome-text-weight) | @@ -106,7 +108,21 @@ supported non-Cartesian projection with the boundary above. Bounded shim-owned coordinate spaces, and linked secondary axes are supported. Unknown keyword arguments on supported calls raise `TypeError` naming the -offending keyword. Known material options that the native marks cannot honor +offending keyword. Matplotlib's *Artist-level* keywords are the exception: +every plotting method in the inventory (plus `grid`, `set_title`, +`set_xlabel`, `set_ylabel`) accepts `zorder`, `clip_on`, `clip_box`, +`rasterized`, `antialiased`/`aa`, `snap`, `gid`, `url`, `picker`, `pickradius`, +`in_layout`, `agg_filter`, `sketch_params`, `path_effects`, `mouseover`, and +`animated` as **accepted no-ops** (`ARTIST_NOOP_KWARGS` in `_translate.py`): the +engine has no draw-order override, clipping policy, hit-testing metadata, or +renderer filters for a single mark, so they are ignored rather than rejected +when a script carries them for the real renderer. `visible=False` is not a +no-op — it hides every artist the call returns (`set_visible(False)`). +Methods that implement one of those names themselves keep it: `annotate` and +`clabel` order by `zorder`, `pcolormesh`/`pcolor`/`pcolorfast` record +`rasterized` on their handle, and `imshow` honors `clip_on`. The setters keep +their stricter contracts (`set_clip_on(False)`, `set_rasterized(True)`, and +`set_zorder` on a plotted handle still raise or reorder as before). Known material options that the native marks cannot honor raise `NotImplementedError`, with these documented exceptions that are accepted as visual approximations rather than rejected: imshow smoothing collapse above, `annotate(arrowprops=...)` connection curves and diff --git a/spec/matplotlib/shim-todo.md b/spec/matplotlib/shim-todo.md index 083e1e3f9..03abda9f1 100644 --- a/spec/matplotlib/shim-todo.md +++ b/spec/matplotlib/shim-todo.md @@ -263,7 +263,7 @@ appear frequently in ordinary scripts and notebooks. - [x] `plt.autoscale()`, `Axes.autoscale()`, `autoscale_view()`, and `relim()`. Evidence: `tests/pyplot/test_axes_helpers.py::test_autoscale_bounds_and_relim_helpers` verifies explicit bounds, relim, autoscale, and tight autoscale behavior. - [x] `get/set_xbound`, `get/set_ybound`, x/y margins, and sticky-edge behavior. Evidence: `tests/pyplot/test_axes_helpers.py::test_autoscale_bounds_and_relim_helpers` verifies bound setters/getters and margin-aware automatic domains. Sticky edges are derived from the entry list rather than from artist metadata (`Axes._entry_sticky_edges`): rectangle baselines for bar/histogram/contour, the outer cell edge for mesh and image entries (`imshow`/`pcolormesh`/`hist2d`/`specgram`), and 0/1 for `ecdf`. An axis whose sticky edges pin *both* ends ships a materialized `domain` instead of a `margin` (`Axes._fully_sticky_domain`), which is how a mesh stays flush with its outer cell edge; one-sided baselines still ship a `margin` and are anchored by the engine. Evidence: `tests/pyplot/test_mesh_autoscale_regressions.py`. -- [x] `ticklabel_format()`. Evidence: `tests/pyplot/test_axes_helpers.py::test_ticklabel_minor_label_axis_and_legend_helpers` verifies stored style, scientific limits, and offset policy. +- [x] `ticklabel_format()`, configuring the axis `ScalarFormatter` as Matplotlib does (plain fixed labels; scientific mantissas outside `scilimits` with the exponent written on every label because the shim has no offset text — `useOffset` is a documented compat-noop). Evidence: `tests/pyplot/test_axes_helpers.py::test_ticklabel_minor_label_axis_and_legend_helpers` verifies the configured formatter, and `tests/pyplot/test_p1_axes_dates_spans.py::test_ticklabel_format_*` verify the plain/sci/mathtext labels against Matplotlib 3.11 and that every exporter renders them (the stored-props version crashed `savefig` with `x_axis() got an unexpected keyword argument 'tick_label_format'`). - [x] `minorticks_on()` and `minorticks_off()` with an explicit minor-tick model. Evidence: `tests/pyplot/test_axes_helpers.py::test_ticklabel_minor_label_axis_and_legend_helpers` verifies explicit minor tick state toggles. - [x] `get_xlabel`, `get_ylabel`, `get_title`, `get_xaxis`, and `get_yaxis`. Evidence: `tests/pyplot/test_axes_helpers.py::test_ticklabel_minor_label_axis_and_legend_helpers` verifies label/title getters and axis proxy identity. - [x] `get_legend()` and `get_legend_handles_labels()`. Evidence: `tests/pyplot/test_axes_helpers.py::test_ticklabel_minor_label_axis_and_legend_helpers` verifies legend presence and labeled handles. @@ -308,6 +308,10 @@ method accepts the call. mask crossings, transforms and complete step semantics. - [x] `arrow`/`axline`: head shape/overhang, transforms and style fidelity. - [x] `axhline`/`axvline`/spans: linestyles and transform fidelity. +- [x] `axhline`/`axvline`/spans: Matplotlib's `dataLim` autoscale (own axis + only) and `label=` legend rows with matching swatches. Evidence: + `tests/pyplot/test_p1_axes_dates_spans.py::test_spans_and_rules_autoscale_on_their_own_axis` + and `::test_span_labels_reach_legend_with_matching_swatches`. - [x] `errorbar`: upper/lower limit flags, cap thickness, bars-above ordering, independent line styles, errorevery and full container semantics. @@ -385,7 +389,14 @@ method accepts the call. `NotImplementedError` rather than being accepted. - [x] Define a bounded units/converter story for datetime, timedelta and common categorical inputs; do not attempt the entire Matplotlib units registry - unless real usage requires it. + unless real usage requires it. Datetime-likes are accepted wherever + `plot()` accepts them, including `set_xlim`/`set_ylim`, + `set_xticks`/`set_yticks`, `fill_between` and `fill_betweenx` + (`tests/pyplot/test_p1_axes_dates_spans.py::test_set_xlim_*`, + `::test_set_xticks_*`, `::test_fill_between*`). Locators without a + usable `tick_values()` (pandas' minor `TimeSeries_DateLocator`) fall + back to the axis kind's own ticks (`::test_unusable_minor_locator_*`, + `::test_pandas_period_tickers_are_noops_on_both_tiers`). - [x] Add date locators/formatters sufficient for ordinary time-series plots. ## P4 — Artist, collection, transform and container compatibility @@ -686,6 +697,49 @@ streamplot - `get_xticks()` on category/time axes falls back to linear ticks; tick density ignores figure size. - Family-level claims in `compatibility.json` have no executable backing. +- Artist-level keywords are accepted no-ops on plotting calls (`zorder=`, + `clip_on=`, `rasterized=`, ...) while the matching setters keep their + stricter contracts: `line.set_clip_on(False)` and `line.set_rasterized(True)` + raise `NotImplementedError`, and `set_zorder()` (like `annotate(zorder=)` and + `clabel(zorder=)`) really reorders entries. `zorder=` on a plotting call is + ignored on purpose: xy's marks all default to one z-level, so honoring the + kwarg would reorder the automatic legend (which follows entry order) for the + common "emphasize one series" idiom. +- `get_yticklabels()`/`get_xticklabels()` on a category axis (`barh(["a", "b"])`) + return the numeric positions `0, 1, 2` until the chart is built; the + category strings only exist in the rendered output. +- `bar(tick_label=...)` relabels numeric positions only; with string category + positions it fails loudly (the category axis owns its labels). +- `hist(align="left"/"right")` is implemented for the bar histtypes only; the + step families accept `align="mid"` and fail loudly otherwise. + +### P1 audit fixes — 2026-09-01 + +Four clusters of everyday Matplotlib idioms that raised on the shim, each +covered by `tests/pyplot/test_p1_kwargs_legend_subplot.py` (Matplotlib 3.11 +compared directly where the semantics are "match mpl") and by the corpus +snippet `56_partial_subplots_legend_proxies.py`: + +- Legend: `legend(handles=, labels=)` keyword forms, integer `loc` codes 0–10, + `loc=(x, y)` tuples (lower-left anchor), and proxy handles — + `plt.Line2D([0], [0], ...)`, `plt.Patch(...)`, `plt.Rectangle(...)` — that + freeze into swatches through `_legend_item_from_entry` with point-unit dash + patterns and marker sizes scaled at attach time. +- Artist-level keywords: one table (`ARTIST_NOOP_KWARGS`) and one wrapper + installed over every inventory method (`ARTIST_KWARG_METHODS` in + `_translate.py`, applied at the end of `_axes.py`) strips the accepted + no-ops and applies `visible=False` to the returned artists; + `ARTIST_KWARG_KEEP` lists the methods that consume a name themselves. +- `subplot(n, m, i)` creates only cell *i* as a GridSpec-positioned axes, so + partial grids draw no empty frames and grids of different shapes share a + figure; the uniform placeholder grid is now used only by `subplots()`, + `subplot2grid`, and the whole-figure `111`. +- Kwargs and attributes: `scatter(facecolors=)`, `bar(tick_label=, log=)`, + `hist(bottom=, align=, log=)`, `text(alpha=)`, `hlines`/`vlines(linestyle=)`, + `errorbar(capthick=, mfc=, mec=, mew=)`, `colorbar(fraction=)` (no-op), + `plt.tick_params`/`plt.margins`/`plt.locator_params`, callable `plt.cm.*` + objects plus the qualitative palettes, `BarPatch` rectangle geometry + getters, and error-bar centre autoscale on category axes. ### Bottom line diff --git a/tests/pyplot/corpus/56_partial_subplots_legend_proxies.py b/tests/pyplot/corpus/56_partial_subplots_legend_proxies.py new file mode 100644 index 000000000..bd8b55521 --- /dev/null +++ b/tests/pyplot/corpus/56_partial_subplots_legend_proxies.py @@ -0,0 +1,38 @@ +"""Partial subplot grids, Artist-level keywords, legend proxies, and the bar +labeling idiom -- plain Matplotlib scripts that used to raise in the shim.""" + +import numpy as np + +import xy.pyplot as plt + +x = np.linspace(0, 2 * np.pi, 40) + +# subplot(n, m, i) creates only cell i; the empty cells stay blank. +top_left = plt.subplot(221) +top_left.plot(x, np.sin(x), zorder=3, clip_on=False, rasterized=True, label="sin") +top_left.plot(x, np.cos(x), visible=False, label="_hidden") +top_left.legend( + handles=[plt.Line2D([0], [0], color="C3", linestyle="--", label="fit")], + loc=2, +) +top_left.grid(True, zorder=0) + +bottom = plt.subplot(2, 1, 2) +bars = bottom.bar(["a", "b", "c"], [1, 2, 3], yerr=[0.1, 0.2, 0.3], tick_label=None) +for rect in bars: + bottom.text( + rect.get_x() + rect.get_width() / 2, + rect.get_height(), + f"{rect.get_height():g}", + ha="center", + alpha=0.8, + ) +bottom.scatter([0, 1, 2], [0.5, 1.5, 2.5], facecolors="none", edgecolors="k", zorder=4) +bottom.hlines(1.0, -0.5, 2.5, linestyle=":", colors=plt.cm.tab10(3)) +bottom.legend( + handles=[ + plt.Rectangle((0, 0), 1, 1, facecolor="C0", label="bars"), + plt.Line2D([0], [0], color="k", marker="o", linestyle="none", label="points"), + ], + loc=(0.02, 0.6), +) diff --git a/tests/pyplot/test_axes_charts.py b/tests/pyplot/test_axes_charts.py index 24eda6497..85d239f20 100644 --- a/tests/pyplot/test_axes_charts.py +++ b/tests/pyplot/test_axes_charts.py @@ -186,8 +186,10 @@ def test_labels_title_reach_the_chart() -> None: def test_unsupported_kwarg_is_loud() -> None: _fig, ax = plt.subplots() + # ``zorder`` is an accepted Artist-level compat-noop now; a keyword no + # Matplotlib Line2D takes must still fail loudly. with pytest.raises(TypeError, match="unsupported keyword"): - ax.plot([0, 1], [1, 2], zorder=3) + ax.plot([0, 1], [1, 2], glow=3) def test_pie_chart_is_supported() -> None: diff --git a/tests/pyplot/test_axes_helpers.py b/tests/pyplot/test_axes_helpers.py index 02e0adfc1..3ed63ce83 100644 --- a/tests/pyplot/test_axes_helpers.py +++ b/tests/pyplot/test_axes_helpers.py @@ -4,7 +4,7 @@ import xy.pyplot as plt from xy.pyplot._artists import Legend from xy.pyplot._rc import rcParams -from xy.pyplot._ticker import AutoMinorLocator, NullLocator +from xy.pyplot._ticker import AutoMinorLocator, NullLocator, ScalarFormatter def teardown_function(): @@ -45,7 +45,10 @@ def test_ticklabel_minor_label_axis_and_legend_helpers(): assert ax.get_title() == "title" assert ax.get_xaxis() is ax.xaxis assert ax.get_yaxis() is ax.yaxis - assert ax._axis_props("x")["tick_label_format"]["style"] == "sci" + # ticklabel_format configures the axis ScalarFormatter, as matplotlib does. + x_formatter = ax.xaxis.get_major_formatter() + assert isinstance(x_formatter, ScalarFormatter) and x_formatter.get_useOffset() is False + assert x_formatter._powerlimits == (-2, 3) and x_formatter._scientific is True assert isinstance(ax.xaxis.get_minor_locator(), AutoMinorLocator) assert isinstance(legend, Legend) assert ax.get_legend() is legend diff --git a/tests/pyplot/test_p1_axes_dates_spans.py b/tests/pyplot/test_p1_axes_dates_spans.py new file mode 100644 index 000000000..2646e9a57 --- /dev/null +++ b/tests/pyplot/test_p1_axes_dates_spans.py @@ -0,0 +1,443 @@ +"""P1 audit fixes: ticklabel_format export, span autoscale/legend, unusable +locators, and datetime coordinates outside plot/scatter/bar. + +Reference numbers marked *mpl 3.11* were recorded against matplotlib 3.11.1; +the cross-check tests re-derive them when matplotlib is importable. +""" + +from __future__ import annotations + +import datetime as dt +import io +import re + +import numpy as np +import pytest + +import xy.pyplot as plt +from xy.pyplot._artists import Line2D +from xy.pyplot._ticker import FuncFormatter, ScalarFormatter + + +def _ms(stamp: str) -> float: + return float(np.datetime64(stamp, "ms").astype(np.int64)) + + +def _export_all(fig) -> dict[str, bytes]: + out = {} + for fmt in ("png", "svg", "html"): + buffer = io.BytesIO() + fig.savefig(buffer, format=fmt) + out[fmt] = buffer.getvalue() + assert out["png"][:4] == b"\x89PNG" + return out + + +def _built(ax): + return ax._build_chart(640, 480).figure() + + +@pytest.fixture(autouse=True) +def _close_all(): + yield + plt.close("all") + + +# --------------------------------------------------------------------------- +# A. ticklabel_format must translate into a label policy, never a crash +# --------------------------------------------------------------------------- + + +def test_ticklabel_format_plain_exports_fixed_labels(): + fig, ax = plt.subplots() + ax.plot([0, 1, 2], [1e6, 1e6 + 1, 1e6 + 2]) + ax.ticklabel_format(style="plain", useOffset=False) + exports = _export_all(fig) + labels = _built(ax).axis_options["y"]["tick_labels"] + # mpl 3.11 with useOffset=False: full fixed values with the shared + # 2-decimal precision of the 0.25 tick step (the shim lists in-view ticks + # only; matplotlib's tick list also carries the out-of-view 999999.75). + assert labels[:3] == ["1000000.00", "1000000.25", "1000000.50"] + assert all("e" not in label for label in labels) + assert b"1000000.00" in exports["svg"] + + +def test_ticklabel_format_plain_default_offset_is_written_in_full(): + # Matplotlib would factor "+1e6" into an offset text; the shim has no + # offset-text slot, so the labels carry the full value (documented noop). + fig, ax = plt.subplots() + ax.plot([0, 1, 2], [1e6, 2e6, 3e6]) + ax.ticklabel_format(style="plain") + labels = _built(ax).axis_options["y"]["tick_labels"] + assert labels[:3] == ["1000000", "1250000", "1500000"] # mpl 3.11, in-view ticks + _export_all(fig) + + +def test_ticklabel_format_sci_writes_shared_exponent_on_each_label(): + fig, ax = plt.subplots() + ax.plot([0, 1, 2], [1e6, 2e6, 3e6]) + ax.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)) + labels = _built(ax).axis_options["y"]["tick_labels"] + # mpl 3.11 mantissas 1.00, 1.25, ... with the "1e6" exponent as offset text. + assert labels[:3] == ["1.00e6", "1.25e6", "1.50e6"] + # axis="y" leaves the x axis on the engine's own labels. + assert _built(ax).axis_options["x"].get("tick_labels") is None + _export_all(fig) + + +def test_ticklabel_format_sci_within_scilimits_stays_plain(): + fig, ax = plt.subplots() + ax.plot([0, 1, 2], [1e6, 2e6, 3e6]) + ax.ticklabel_format(style="sci", scilimits=(-5, 7)) # 1e6 is inside + labels = _built(ax).axis_options["y"]["tick_labels"] + assert labels[:2] == ["1000000", "1250000"] + + +def test_ticklabel_format_math_text_uses_unicode_power(): + fig, ax = plt.subplots() + ax.plot([0, 1, 2], [1e6, 2e6, 3e6]) + ax.ticklabel_format(style="sci", scilimits=(0, 0), useMathText=True) + labels = _built(ax).axis_options["y"]["tick_labels"] + assert labels[0] == "1.00×10⁶" # noqa: RUF001 - intentional multiplication sign + _export_all(fig) + + +def test_ticklabel_format_configures_the_scalar_formatter_like_matplotlib(): + fig, ax = plt.subplots() + ax.plot([0, 1], [1, 2]) + ax.ticklabel_format(axis="x", style="sci", scilimits=(-2, 3), useOffset=False) + formatter = ax.xaxis.get_major_formatter() + assert isinstance(formatter, ScalarFormatter) + assert formatter.get_useOffset() is False + assert ax.yaxis.get_major_formatter() is not formatter + ax.xaxis.set_major_formatter(FuncFormatter(lambda v, p: "x")) + with pytest.raises(AttributeError): # mpl: only works with the ScalarFormatter + ax.ticklabel_format(axis="x", style="plain") + + +def test_ticklabel_format_cross_check_against_matplotlib(): + mpl = pytest.importorskip("matplotlib") + mpl.use("Agg") + import matplotlib.pyplot as mplt + + ref_fig, ref_ax = mplt.subplots() + ref_ax.plot([0, 1, 2], [1e6, 1e6 + 1, 1e6 + 2]) + ref_ax.ticklabel_format(style="plain", useOffset=False) + ref_fig.canvas.draw() + reference = [t.get_text().replace("\N{MINUS SIGN}", "-") for t in ref_ax.get_yticklabels()] + mplt.close(ref_fig) + + fig, ax = plt.subplots() + ax.plot([0, 1, 2], [1e6, 1e6 + 1, 1e6 + 2]) + ax.ticklabel_format(style="plain", useOffset=False) + labels = _built(ax).axis_options["y"]["tick_labels"] + assert set(labels) <= set(reference) + assert len(labels) >= 5 + + +# --------------------------------------------------------------------------- +# B. spans and rules: autoscale on their own axis, label= reaches the legend +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize( + ("draw", "xlim", "ylim"), + [ + # mpl 3.11 reference limits for a [0, 2] x [0, 4] line plus the artist. + (lambda ax: (ax.axvspan(-5, -4), ax.axhline(10)), (-5.35, 2.35), (-0.5, 10.5)), + (lambda ax: ax.axhline(10), (-0.1, 2.1), (-0.5, 10.5)), + (lambda ax: ax.axvline(10), (-0.5, 10.5), (-0.2, 4.2)), + (lambda ax: ax.axhspan(6, 8), (-0.1, 2.1), (-0.4, 8.4)), + (lambda ax: ax.axvspan(3, 4), (-0.2, 4.2), (-0.2, 4.2)), + # Fractional bounds never touch the perpendicular axis. + (lambda ax: ax.axhline(10, xmin=0.2, xmax=0.8), (-0.1, 2.1), (-0.5, 10.5)), + (lambda ax: ax.axvspan(3, 4, ymin=0.2, ymax=0.8), (-0.2, 4.2), (-0.2, 4.2)), + (lambda ax: ax.axhline(-1), (-0.1, 2.1), (-1.25, 4.25)), + ], +) +def test_spans_and_rules_autoscale_on_their_own_axis(draw, xlim, ylim): + fig, ax = plt.subplots() + ax.plot([0, 1, 2], [0, 2, 4]) + draw(ax) + assert ax.get_xlim() == pytest.approx(xlim) + assert ax.get_ylim() == pytest.approx(ylim) + _export_all(fig) + + +def test_non_finite_rule_does_not_autoscale(): + fig, ax = plt.subplots() + ax.plot([0, 1, 2], [0, 2, 4]) + ax.axhline(np.nan) # mpl 3.11: dataLim ignores the NaN position + assert ax.get_xlim() == pytest.approx((-0.1, 2.1)) + assert ax.get_ylim() == pytest.approx((-0.2, 4.2)) + + +def test_spans_autoscale_cross_check_against_matplotlib(): + mpl = pytest.importorskip("matplotlib") + mpl.use("Agg") + import matplotlib.pyplot as mplt + + def scenario(ax): + ax.plot([0, 1, 2], [0, 2, 4]) + ax.axvspan(-5, -4) + ax.axhline(10) + ax.axhspan(-3, -2, xmin=0.1, xmax=0.4) + ax.axvline(7, ymin=0.5) + + ref_fig, ref_ax = mplt.subplots() + scenario(ref_ax) + expected = (tuple(map(float, ref_ax.get_xlim())), tuple(map(float, ref_ax.get_ylim()))) + mplt.close(ref_fig) + fig, ax = plt.subplots() + scenario(ax) + assert ax.get_xlim() == pytest.approx(expected[0]) + assert ax.get_ylim() == pytest.approx(expected[1]) + + +def test_span_only_axes_autoscale_like_matplotlib_dataless_axis(): + fig, ax = plt.subplots() + ax.axvspan(3, 4) + assert ax.get_xlim() == pytest.approx((2.95, 4.05)) # mpl 3.11 + assert ax.get_ylim() == (0.0, 1.0) + + +def test_span_autoscale_reaches_the_exported_chart(): + fig, ax = plt.subplots(figsize=(7.2, 4.0), dpi=100) + ax.plot([0, 1, 2], [0, 1, 4], label="data") + ax.axvspan(-5, -4, color="#d0342c", alpha=0.3, label="outage window") + ax.axhline(10, color="#16a34a", linestyle="--", label="target") + ax.legend(loc="upper left") + assert ax.get_xlim() == pytest.approx((-5.35, 2.35)) + assert ax.get_ylim() == pytest.approx((-0.5, 10.5)) + # The built axes carry the dataLim-based limits as their exact domain + # (matplotlib's margins are already inside them, so no `margin` rides along). + options = _built(ax).axis_options + assert options["x"]["domain"] == pytest.approx((-5.35, 2.35)) + assert options["y"]["domain"] == pytest.approx((-0.5, 10.5)) + assert options["x"].get("margin") is None and options["y"].get("margin") is None + svg = _export_all(fig)["svg"] + x_ticks = [float(t) for t in re.findall(rb'text-anchor="middle">(-?[\d.]+)<', svg)] + y_ticks = [float(t) for t in re.findall(rb'text-anchor="end">(-?[\d.]+)<', svg)] + assert min(x_ticks) <= -5 and max(x_ticks) >= 2 # the span sits inside the view + assert min(y_ticks) <= 0 and max(y_ticks) >= 10 # and so does the rule + # A span-free plot keeps the engine's own margin-based autoscale. + plain_fig, plain_ax = plt.subplots() + plain_ax.plot([0, 1, 2], [0, 1, 4]) + plain = _built(plain_ax).axis_options + assert plain["x"].get("domain") is None and plain["x"]["margin"] == pytest.approx(0.05) + + +def test_twin_axis_span_autoscale_reaches_the_exported_chart(): + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1]) + twin = ax.twinx() + twin.plot([0, 1], [0, 1]) + twin.axhline(5) + assert twin.get_ylim() == pytest.approx((-0.25, 5.25)) + assert _built(ax).axis_options["y2"]["domain"] == pytest.approx((-0.25, 5.25)) + assert _built(ax).axis_options["y"].get("domain") is None # host y is untouched + _export_all(fig) + + +def test_span_labels_reach_legend_with_matching_swatches(): + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1], label="b") + rule = ax.axhline(0.5, label="h", color="red", linestyle="--") + ax.axvspan(0.2, 0.4, label="s") + ax.axvline(0.3, label="v") + ax.axhspan(0.6, 0.7, label="hs", color="green", alpha=0.5) + handles, labels = ax.get_legend_handles_labels() + assert labels == ["b", "h", "s", "v", "hs"] # mpl 3.11 order + assert isinstance(handles[1], Line2D) and isinstance(handles[3], Line2D) + assert rule.get_label() == "h" + # The label is a legend entry, never text drawn beside the rule. + assert "text" not in rule._entry["kwargs"] + ax.legend() + items = _built(ax).legend_options["items"] + assert [item["name"] for item in items] == ["b", "h", "s", "v", "hs"] + assert [item["kind"] for item in items] == ["line", "line", "area", "line", "area"] + assert items[1]["style"]["color"] == "red" and items[1]["style"].get("dash") + assert items[4]["style"] == {"color": "green", "opacity": 0.5} + # Unlabeled defaults are spelled out so the swatch matches the drawn band. + assert items[2]["style"] == {"color": "#64748b", "opacity": 0.14} + exports = _export_all(fig) + assert b"hs" in exports["svg"] + + +def test_span_set_label_after_creation_and_underscore_labels(): + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1], label="b") + rule = ax.axhline(0.5) + ax.axvspan(0.2, 0.4, label="_hidden") + rule.set_label("late") + assert ax.get_legend_handles_labels()[1] == ["b", "late"] + ax.legend() + assert [item["name"] for item in _built(ax).legend_options["items"]] == ["b", "late"] + _export_all(fig) + + +def test_unlabeled_spans_leave_the_engine_legend_alone(): + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1], label="b") + ax.axhline(0.5) + ax.legend() + assert "items" not in _built(ax).legend_options + + +# --------------------------------------------------------------------------- +# C. locators without a usable tick_values() must not break the build +# --------------------------------------------------------------------------- + + +class _AbstractLocator: + """Mimics matplotlib's Locator base: tick_values() is abstract.""" + + axis = None + + def tick_values(self, vmin, vmax): + raise NotImplementedError("Derived must override") + + +class _CallableLocator(_AbstractLocator): + def __init__(self): + self.axis = object() + + def __call__(self): + return [0.25, 0.5, 0.75] + + +def test_unusable_minor_locator_keeps_native_date_ticks(): + fig, ax = plt.subplots() + dates = np.arange("2012-01-01", "2012-05-01", dtype="datetime64[D]") + ax.plot(dates, np.linspace(0.0, 1.0, len(dates))) + ax.xaxis.set_minor_locator(_AbstractLocator()) + ax.xaxis.set_major_locator(_AbstractLocator()) + options = _built(ax).axis_options["x"] + assert options.get("tick_values") is None # engine's own date ticks + assert options.get("minor_tick_values") is None + exports = _export_all(fig) + assert b"Feb" in exports["svg"] or b"2012-02" in exports["svg"] + + +def test_locator_with_axis_falls_back_to_calling_it(): + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1]) + ax.xaxis.set_major_locator(_CallableLocator()) + assert _built(ax).axis_options["x"]["tick_values"] == [0.25, 0.5, 0.75] + + +def test_pandas_period_tickers_are_noops_on_both_tiers(): + pd = pytest.importorskip("pandas") + index = pd.date_range("2012-01-01", periods=120, freq="D") + fig, ax = plt.subplots() + pd.Series(np.linspace(4000.0, 5000.0, 120), index=index).plot(ax=ax) + assert type(ax.xaxis.get_minor_locator()).__module__.startswith("xy.") + options = _built(ax).axis_options["x"] + assert options.get("tick_values") is None # engine's own date ticks + _export_all(fig) + + +# --------------------------------------------------------------------------- +# D. datetime coordinates in limits, ticks and fills +# --------------------------------------------------------------------------- + +_DATES = [dt.datetime(2024, 1, 1) + dt.timedelta(days=i) for i in range(3)] + + +def _datetime_likes(stamp: str): + day = dt.date.fromisoformat(stamp) + values = [ + dt.datetime(day.year, day.month, day.day), + day, + np.datetime64(stamp), + ] + pd = pytest.importorskip("pandas") + values.append(pd.Timestamp(stamp)) + return values + + +@pytest.mark.parametrize("index", range(4)) +def test_set_xlim_accepts_every_datetime_like_plot_accepts(index): + left = _datetime_likes("2023-12-31")[index] + right = _datetime_likes("2024-01-05")[index] + fig, ax = plt.subplots() + ax.plot(_DATES, [1, 2, 3]) + before = ax.get_xlim() + ax.set_xlim(left, right) + assert ax.get_xlim() == (_ms("2023-12-31"), _ms("2024-01-05")) + # Same unit plot() reports: ms since epoch, with the automatic margin. + assert before == pytest.approx((_ms("2023-12-31T21:36"), _ms("2024-01-03T02:24"))) + ax.set_xlim((left, None)) + assert ax.get_xlim() == (_ms("2023-12-31"), _ms("2024-01-05")) + _export_all(fig) + + +def test_set_ylim_and_xlim_wrapper_accept_datetimes(): + fig, ax = plt.subplots() + ax.plot([1, 2, 3], _DATES) + ax.set_ylim(dt.datetime(2023, 12, 31), dt.datetime(2024, 1, 5)) + assert ax.get_ylim() == (_ms("2023-12-31"), _ms("2024-01-05")) + plt.figure(fig.number) + plt.ylim(dt.datetime(2024, 1, 1), np.datetime64("2024-01-04")) + assert ax.get_ylim() == (_ms("2024-01-01"), _ms("2024-01-04")) + with pytest.raises(TypeError): + ax.set_xlim(object(), 1.0) + + +def test_set_xticks_accepts_datetime_likes(): + pd = pytest.importorskip("pandas") + fig, ax = plt.subplots() + ax.plot(_DATES, [1, 2, 3]) + ax.set_xticks( + [dt.datetime(2024, 1, 1), np.datetime64("2024-01-03"), pd.Timestamp("2024-01-02")] + ) + assert ax.get_xticks() == pytest.approx( + [_ms("2024-01-01"), _ms("2024-01-03"), _ms("2024-01-02")] + ) + ax.set_yticks([1, 2]) + fig2, ax2 = plt.subplots() + ax2.plot([1, 2, 3], _DATES) + ax2.set_yticks(np.asarray(["2024-01-01", "2024-01-02"], dtype="datetime64[ns]")) + assert ax2.get_yticks() == pytest.approx([_ms("2024-01-01"), _ms("2024-01-02")]) + _export_all(fig) + _export_all(fig2) + + +def test_fill_between_accepts_datetimes_and_keeps_the_time_axis(): + fig, ax = plt.subplots() + ax.plot(_DATES, [1, 2, 3]) + plotted = ax.get_xlim() + ax.fill_between(_DATES, [1, 2, 3], [0, 0, 0], alpha=0.3) + assert ax.get_xlim() == plotted + # Without any plot() call the fill alone must still make a date axis. + fig2, ax2 = plt.subplots() + ax2.fill_between(np.asarray(_DATES, dtype="datetime64[ns]"), [1, 2, 3]) + assert ax2._axis_holds_datetimes("x") + assert ax2.get_xlim() == pytest.approx(plotted) + # The fill-only chart gets the same time-axis labels as the plot() chart. + ticks = re.compile(rb'text-anchor="middle">([^<]*)<') + assert ticks.findall(_export_all(fig2)["svg"]) == ticks.findall(_export_all(fig)["svg"]) + + +def test_fill_between_datetime_where_and_interpolate(): + fig, ax = plt.subplots() + x = np.asarray(_DATES + [dt.datetime(2024, 1, 4)], dtype="datetime64[ns]") + y = np.asarray([0.0, 2.0, -1.0, 3.0]) + ax.fill_between(x, y, 0.0, where=y > 0, interpolate=True) + entries = [entry for entry in ax._entries if entry["kind"] == "area"] + assert entries and all(np.issubdtype(np.asarray(e["x"]).dtype, np.datetime64) for e in entries) + assert ax._axis_holds_datetimes("x") + _export_all(fig) + + +def test_fill_betweenx_accepts_datetime_y(): + fig, ax = plt.subplots() + ax.fill_betweenx(_DATES, [1, 2, 3], [0, 0, 0]) + assert ax._axis_holds_datetimes("y") + assert ax.get_ylim() == pytest.approx((_ms("2023-12-31T21:36"), _ms("2024-01-03T02:24"))) + reference_fig, reference_ax = plt.subplots() + reference_ax.plot([1, 2, 3], _DATES) + ticks = re.compile(rb'text-anchor="end">([^<]*)<') + assert ticks.findall(_export_all(fig)["svg"]) == ticks.findall( + _export_all(reference_fig)["svg"] + ) diff --git a/tests/pyplot/test_p1_kwargs_legend_subplot.py b/tests/pyplot/test_p1_kwargs_legend_subplot.py new file mode 100644 index 000000000..4a558368a --- /dev/null +++ b/tests/pyplot/test_p1_kwargs_legend_subplot.py @@ -0,0 +1,575 @@ +"""P1 audit fixes: legend keyword/loc forms and proxy handles (E), accepted +Artist-level keywords (F), partial ``subplot(n, m, i)`` grids (G), and the +commonly rejected kwargs / missing attributes (H). + +Where the semantics are "match Matplotlib", the expected values are taken +from Matplotlib 3.11 and asserted against it too when it is installed. +""" + +from __future__ import annotations + +import json +import re +from io import BytesIO +from pathlib import Path + +import numpy as np +import pytest + +import xy.pyplot as plt +from xy.pyplot._translate import ARTIST_KWARG_KEEP, ARTIST_KWARG_METHODS, ARTIST_NOOP_KWARGS + +INVENTORY = Path(__file__).with_name("matplotlib_311_plotting.json") + +# Matplotlib's ``Legend.codes`` (index = numeric loc code). +LEGEND_CODES = ( + "best", + "upper right", + "upper left", + "lower left", + "lower right", + "right", + "center left", + "center right", + "lower center", + "upper center", + "center", +) + + +def _matplotlib(): + return pytest.importorskip("matplotlib") + + +def _svg(fig) -> str: + target = BytesIO() + fig.savefig(target, format="svg") + return target.getvalue().decode() + + +# --- E: legend keyword forms, loc codes, proxy handles ----------------------- + + +def test_legend_keyword_handles_and_labels_match_positional_form() -> None: + _fig, ax = plt.subplots() + (a,) = ax.plot([0, 1], [0, 1], label="a") + (b,) = ax.plot([0, 1], [1, 0], label="b") + positional = ax.legend([a, b], ["A", "B"]).spec()["items"] + keyword = ax.legend(handles=[a, b], labels=["A", "B"]).spec()["items"] + assert [item["name"] for item in keyword] == ["A", "B"] + assert keyword == positional + + +def test_legend_handles_only_reads_labels_off_the_handles() -> None: + _fig, ax = plt.subplots() + (hidden,) = ax.plot([0, 1], [0, 1], label="_hidden") + (shown,) = ax.plot([0, 1], [1, 0], label="shown") + names = [item["name"] for item in ax.legend(handles=[hidden, shown]).spec()["items"]] + # Matplotlib keeps underscore labels when the handles are given explicitly. + assert names == ["_hidden", "shown"] + mpl = _matplotlib() + mpl.use("Agg") + import matplotlib.pyplot as mplt + + mfig, max_ = mplt.subplots() + (mh,) = max_.plot([0, 1], [0, 1], label="_hidden") + (ms,) = max_.plot([0, 1], [1, 0], label="shown") + assert [t.get_text() for t in max_.legend(handles=[mh, ms]).get_texts()] == names + mplt.close(mfig) + + +def test_legend_labels_only_assigns_positionally() -> None: + _fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1]) + ax.plot([0, 1], [1, 0]) + legend = ax.legend(labels=["X", "Y"]) + assert [item["name"] for item in legend.spec()["items"]] == ["X", "Y"] + with pytest.raises(TypeError, match="positionally or as keywords"): + ax.legend(["X"], labels=["Y"]) + + +@pytest.mark.parametrize("code", range(11)) +def test_legend_integer_loc_codes_map_to_matplotlib_names(code: int) -> None: + _fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1], label="a") + assert ax.legend(loc=code)._options["loc"] == LEGEND_CODES[code] + assert ax.legend(loc=np.int64(code))._options["loc"] == LEGEND_CODES[code] + + +def test_legend_loc_codes_match_matplotlib_table() -> None: + mpl = _matplotlib() + codes = {value: key for key, value in mpl.legend.Legend.codes.items()} + assert tuple(codes[i] for i in range(11)) == LEGEND_CODES + + +def test_legend_tuple_loc_anchors_the_lower_left_corner() -> None: + _fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1], label="a") + options = ax.legend(loc=(0.5, 0.25))._options + assert options["loc"] == "lower left" + assert options["anchor"] == (0.5, 0.25) + _svg(plt.gcf()) # anchored placement must export + with pytest.raises(ValueError, match="two finite"): + ax.legend(loc=(0.5, 0.25, 0.1)) + with pytest.raises(ValueError, match="between 0 and 10"): + ax.legend(loc=11) + with pytest.raises(ValueError, match="legend loc must be one of"): + ax.legend(loc="upper middle") + + +def test_line2d_proxy_constructs_and_freezes_a_legend_swatch() -> None: + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1]) + dashed = plt.Line2D([0], [0], color="r", linestyle="--", linewidth=2, label="red dashed") + dots = plt.Line2D([0], [0], color="b", marker="o", linestyle="none", ms=4, label="blue dots") + both = plt.Line2D([0], [0], color="g", marker="s", mfc="w", mec="k", label="line+square") + assert dashed.get_label() == "red dashed" + assert dashed.get_visible() is True + dashed.set_color("darkred") # proxies own no axes; mutations must not crash + legend = ax.legend(handles=[dashed, dots, both], loc=2) + items = {item["name"]: item for item in legend.spec()["items"]} + scale = ax._point_scale() + assert items["red dashed"]["kind"] == "line" + assert items["red dashed"]["style"]["color"] == "darkred" + assert items["red dashed"]["style"]["width"] == pytest.approx(2 * scale) + # Matplotlib's dashed pattern (3.7, 1.6) scaled by linewidth and DPI. + assert items["red dashed"]["style"]["dash"] == pytest.approx( + [3.7 * 2 * scale, 1.6 * 2 * scale], abs=1e-3 + ) + assert items["blue dots"]["kind"] == "scatter" + assert items["blue dots"]["style"]["symbol"] == "circle" + assert items["blue dots"]["style"]["size"] == pytest.approx((4 + 1) * scale) + assert items["line+square"]["kind"] == "line" + marker = items["line+square"]["style"]["legend_marker"] + assert marker["symbol"] == "square" + assert marker["color"] == "#ffffff" + assert marker["stroke"] == "#000000" + svg = _svg(fig) + assert "red dashed" in svg and "blue dots" in svg and "line+square" in svg + with pytest.raises(TypeError, match="Line2D\\(\\) got unsupported"): + plt.Line2D([0], [0], glow=True) + + +def test_patch_and_rectangle_proxies_are_legend_handles() -> None: + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1]) + patch = plt.Patch(facecolor="orange", edgecolor="k", label="area", alpha=0.5) + rect = plt.Rectangle((0, 0), 1, 1, color="purple", label="box") + hollow = plt.Patch(fill=False, edgecolor="green", label="outline") + assert patch.get_facecolor() == "orange" and patch.get_edgecolor() == "#000000" + assert rect.get_width() == 1.0 and rect.get_xy() == (0.0, 0.0) + assert hollow.get_fill() is False + legend = ax.legend(handles=[patch, rect, hollow]) + items = {item["name"]: item for item in legend.spec()["items"]} + assert items["area"]["kind"] == "bar" + assert items["area"]["style"]["color"] == "orange" + assert items["area"]["style"]["opacity"] == 0.5 + assert items["area"]["style"]["stroke"] == "#000000" + assert items["box"]["style"]["color"] == "purple" + assert items["box"]["style"]["stroke"] == "purple" + assert items["outline"]["style"]["color"] == "transparent" + assert items["outline"]["style"]["stroke"] == "green" + svg = _svg(fig) + assert "area" in svg and "box" in svg and "outline" in svg + with pytest.raises(NotImplementedError): + plt.Rectangle((0, 0), 1, 1, angle=30) + + +def test_rectangle_proxy_also_works_with_add_patch() -> None: + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1]) + before = len(ax._entries) + handle = ax.add_patch(plt.Rectangle((0.2, 0.2), 0.5, 0.3, facecolor="red", edgecolor="k")) + assert len(ax._entries) > before + assert handle.get_visible() + fig.savefig(BytesIO(), format="png") + + +# --- F: Artist-level keywords ------------------------------------------------- + +NOOPS = dict.fromkeys(sorted(ARTIST_NOOP_KWARGS), None) +NOOPS.update( + zorder=3, + clip_on=False, + rasterized=True, + antialiased=False, + aa=False, + snap=True, + gid="g", + url="https://example.invalid", + picker=5, + in_layout=False, + path_effects=[], + mouseover=True, + animated=False, +) +Z = np.arange(9.0).reshape(3, 3) + + +@pytest.mark.parametrize( + ("method", "args"), + [ + ("plot", ([0, 1], [0, 1])), + ("scatter", ([0, 1], [0, 1])), + ("bar", ([0, 1], [1, 2])), + ("barh", ([0, 1], [1, 2])), + ("hist", ([1, 2, 2, 3],)), + ("fill_between", ([0, 1], [0, 1])), + ("axvspan", (0.2, 0.4)), + ("axhspan", (0.2, 0.4)), + ("axhline", (0.5,)), + ("axvline", (0.5,)), + ("text", (0.5, 0.5, "t")), + ("errorbar", ([0, 1], [0, 1], 0.1)), + ("step", ([0, 1], [0, 1])), + ("imshow", (Z,)), + ("pcolormesh", (Z,)), + ("contour", (Z,)), + ("hlines", (0.5, 0, 1)), + ("vlines", (0.5, 0, 1)), + ("stem", ([0, 1], [1, 2])), + ("pie", ([1, 2],)), + ("set_title", ("T",)), + ("set_xlabel", ("x",)), + ], +) +def test_artist_noop_kwargs_are_accepted_on_every_plotting_call(method: str, args) -> None: + _fig, ax = plt.subplots() + # Names a method implements itself (ARTIST_KWARG_KEEP) keep their own + # contract, e.g. imshow rejects clip_on=False rather than ignoring it. + kept = ARTIST_KWARG_KEEP.get(method, frozenset()) + getattr(ax, method)(*args, **{k: v for k, v in NOOPS.items() if k not in kept}) + # and still loud for a keyword no Matplotlib artist takes + with pytest.raises((TypeError, NotImplementedError)): + getattr(ax, method)(*args, glow=True) + + +def test_kept_artist_kwargs_still_reach_their_implementations() -> None: + _fig, ax = plt.subplots() + mesh = ax.pcolormesh(Z, rasterized=True) + assert mesh.get_rasterized() is True + with pytest.raises(NotImplementedError, match="clip_on"): + ax.imshow(Z, clip_on=False) + + +def test_grid_accepts_artist_noops() -> None: + _fig, ax = plt.subplots() + ax.grid(True, zorder=0, clip_on=False) + assert ax._grid + + +def test_artist_kwarg_methods_cover_the_plotting_inventory() -> None: + inventory = json.loads(INVENTORY.read_text()) + methods = {name for family in inventory["families"].values() for name in family} + missing = methods - set(ARTIST_KWARG_METHODS) + assert not missing, sorted(missing) + for name in ARTIST_KWARG_METHODS: + assert callable(getattr(plt.Axes, name)), name + + +def test_visible_false_hides_the_returned_artists() -> None: + fig, ax = plt.subplots() + (line,) = ax.plot([0, 1], [0, 1], visible=False) + text = ax.text(0.5, 0.5, "HIDDEN", visible=False) + _counts, _edges, patches = ax.hist([1, 2, 2], visible=False) + collection = ax.scatter([0], [0], visible=True) + bars = ax.errorbar([0, 1], [0, 1], yerr=0.1, visible=False) + assert not line.get_visible() and line._entry["kwargs"]["opacity"] == 0.0 + assert not text.get_visible() and not patches.get_visible() + assert collection.get_visible() + assert not bars.lines[2][0].get_visible() + svg = _svg(fig) + assert "HIDDEN" not in svg + text.set_visible(True) + ax._chart = None + assert "HIDDEN" in _svg(fig) + + +def test_annotate_and_clabel_keep_honoring_zorder() -> None: + _fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1]) + note = ax.annotate("n", (0.5, 0.5), zorder=-3, clip_on=False) + assert note._entry["_zorder"] == -3.0 + contour = ax.contour(Z) + labels = ax.clabel(contour, inline=False, zorder=-2, rasterized=True) + assert {label.get_zorder() for label in labels} == {-2.0} + + +# --- G: partial subplot grids ------------------------------------------------ + + +def test_subplot_creates_only_the_requested_cells() -> None: + plt.subplot(221) + plt.plot([0, 1]) + plt.subplot(224) + plt.plot([1, 0]) + fig = plt.gcf() + assert len(fig.axes) == 2 + top_left, bottom_right = (ax.get_position().bounds for ax in fig.axes) + # Matplotlib 3.11's SubplotParams cells for a 2x2 grid. + assert top_left == pytest.approx((0.125, 0.53, 0.35227272727, 0.35)) + assert bottom_right == pytest.approx((0.54772727272, 0.11, 0.35227272727, 0.35)) + assert all(ax._entries for ax in fig.axes) + + +def test_subplot_positions_match_matplotlib() -> None: + _matplotlib().use("Agg") + import matplotlib.pyplot as mplt + + mplt.subplot(221) + mplt.subplot(224) + expected = [tuple(ax.get_position().bounds) for ax in mplt.gcf().axes] + mplt.close("all") + plt.subplot(221) + plt.subplot(224) + actual = [tuple(ax.get_position().bounds) for ax in plt.gcf().axes] + np.testing.assert_allclose(actual, expected) + + +def test_subplot_grids_of_different_shapes_share_a_figure() -> None: + first = plt.subplot(2, 2, 1) + plt.plot([0, 1]) + plt.subplot(2, 2, 2) + plt.plot([1, 0]) + bottom = plt.subplot(2, 1, 2) + plt.plot([0, 1, 0]) + fig = plt.gcf() + assert len(fig.axes) == 3 + assert bottom.get_position().bounds == pytest.approx((0.125, 0.11, 0.775, 0.35)) + assert plt.subplot(2, 2, 1) is first # pyplot.subplot() reuses a matching cell + assert plt.gca() is first + assert fig.add_subplot(2, 2, 1) is not first # Figure.add_subplot() never does + assert len(fig.axes) == 4 + + +def test_partial_grid_renders_only_its_panels_in_every_exporter() -> None: + plt.subplot(221) + plt.plot([0, 1]) + plt.subplot(224) + plt.plot([1, 0]) + fig = plt.gcf() + html = fig._to_html() + assert len(re.findall(r'style="position:absolute;left:', html)) == 2 + assert _svg(fig).count("= 0.99), "an unrequested subplot cell was drawn" + + +def test_whole_figure_subplot_keeps_the_single_chart_path() -> None: + ax = plt.subplot(111) + ax.plot([0, 1]) + fig = plt.gcf() + assert len(fig.axes) == 1 + assert ax._figure_rect is None + assert fig._single() is not None + assert plt.subplot(1, 1, 1) is ax + + +def test_subplot_rejects_an_out_of_range_index() -> None: + with pytest.raises(ValueError, match="1 <= num <= 4, not 5"): + plt.subplot(2, 2, 5) + with pytest.raises(ValueError, match="1 <= num <= 6, not 0"): + plt.figure().add_subplot(2, 3, 0) + + +# --- H: rejected kwargs and missing attributes -------------------------------- + + +def test_scatter_facecolors_none_draws_hollow_markers() -> None: + _fig, ax = plt.subplots() + hollow = ax.scatter([0, 1], [0, 1], facecolors="none", edgecolors="r") + assert hollow._entry["kwargs"]["color"] == "transparent" + assert hollow._entry["kwargs"]["stroke"] == "#ff0000" + alias = ax.scatter([0, 1], [0, 1], facecolor="none", edgecolor="b") + assert alias._entry["kwargs"]["color"] == "transparent" + # ``c`` wins over facecolors, as in Matplotlib. + filled = ax.scatter([0, 1], [0, 1], c="g", facecolors="none") + assert filled._entry["kwargs"]["color"] == "#008000" + + +def test_bar_tick_label_places_one_labeled_tick_per_bar() -> None: + _fig, ax = plt.subplots() + ax.bar([1, 2, 3], [1, 2, 3], tick_label=["x", "y", "z"]) + assert ax._axis_props("x")["tick_labels"] == ["x", "y", "z"] + assert list(ax._axis_props("x")["tick_values"]) == [1.0, 2.0, 3.0] + ax.barh([1, 2], [1, 2], tick_label="same") + assert ax._axis_props("y")["tick_labels"] == ["same", "same"] + with pytest.raises(ValueError, match="number of tick labels"): + ax.bar([1, 2], [1, 2], tick_label=["only one"]) + with pytest.raises(NotImplementedError): + ax.bar(["a", "b"], [1, 2], tick_label=["A", "B"]) + + +def test_bar_and_hist_log_put_the_value_axis_on_a_log_scale() -> None: + _fig, ax = plt.subplots() + ax.bar([1, 2, 3], [1, 10, 100], log=True) + assert ax._scale_specs["y"]["name"] == "log" + _fig, ax = plt.subplots() + ax.barh([1, 2, 3], [1, 10, 100], log=True) + assert ax._scale_specs["x"]["name"] == "log" + _fig, ax = plt.subplots() + ax.hist([1, 2, 2, 3, 3, 3], bins=3, log=True) + assert ax._scale_specs["y"]["name"] == "log" + + +def test_hist_bottom_and_align_match_matplotlib_geometry() -> None: + _fig, ax = plt.subplots() + counts, edges, patches = ax.hist([1, 2, 2, 3], bins=3, bottom=5, align="left") + np.testing.assert_allclose(counts, [1, 2, 1]) # raw counts, not lifted + geometry = [(r.get_x(), r.get_y(), r.get_height()) for r in patches] + expected = [(2 / 3, 5.0, 1.0), (4 / 3, 5.0, 2.0), (2.0, 5.0, 1.0)] + np.testing.assert_allclose(geometry, expected) + _matplotlib().use("Agg") + import matplotlib.pyplot as mplt + + mfig, max_ = mplt.subplots() + _n, _b, mpatches = max_.hist([1, 2, 2, 3], bins=3, bottom=5, align="left") + np.testing.assert_allclose(geometry, [(r.get_x(), r.get_y(), r.get_height()) for r in mpatches]) + mplt.close(mfig) + _fig, ax = plt.subplots() + _counts, _edges, right = ax.hist([1, 2, 2, 3], bins=3, bottom=[1, 2, 3], align="right") + assert [r.get_y() for r in right] == [1.0, 2.0, 3.0] + assert right[0].get_x() == pytest.approx(2 / 3 + 2 / 3) + with pytest.raises(ValueError, match="align"): + ax.hist([1, 2], align="middle") + with pytest.raises(NotImplementedError): + ax.hist([1, 2], histtype="step", align="left") + + +def test_text_alpha_reaches_the_entry_and_static_export() -> None: + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1]) + text = ax.text(0.5, 0.5, "FADED", alpha=0.3) + assert text.get_alpha() == 0.3 + assert 'fill-opacity="0.3"' in _svg(fig) + + +def test_hlines_and_vlines_accept_the_singular_linestyle_spelling() -> None: + _fig, ax = plt.subplots() + solid = ax.hlines(0.5, 0, 1) + dashed = ax.hlines(0.5, 0, 1, linestyle="--") + dotted = ax.vlines(0.5, 0, 1, ls=":") + assert len(dashed._entry["args"][0]) > len(solid._entry["args"][0]) + assert len(dotted._entry["args"][0]) > len(solid._entry["args"][0]) + + +def test_errorbar_capthick_and_marker_style_kwargs() -> None: + _fig, ax = plt.subplots() + container = ax.errorbar( + [0, 1], [0, 1], yerr=0.1, fmt="o", capsize=3, capthick=2, mfc="w", mec="k", mew=1.5 + ) + caps = container.lines[1] + assert caps and all(cap._entry["_mpl_line_marker_stroke_points"] == 2.0 for cap in caps) + (marker_entry,) = container.lines[0]._marker_entries() + assert marker_entry["kwargs"]["color"] == "#ffffff" + assert marker_entry["kwargs"]["stroke"] == "#000000" + assert marker_entry["kwargs"]["stroke_width"] == pytest.approx(1.5 * ax._point_scale()) + + +def test_colorbar_fraction_is_an_accepted_noop() -> None: + fig, ax = plt.subplots() + image = ax.imshow(Z) + fig.colorbar(image, fraction=0.046, pad=0.04) + assert ax._colorbar is not None + + +def test_stateful_tick_params_margins_and_locator_params_delegate_to_gca() -> None: + _fig, ax = plt.subplots() + ax.plot([0, 10], [0, 10]) + plt.tick_params(axis="x", labelsize=8, labelrotation=45) + assert ax._axis_props("x")["tick_label_angle"] == 45.0 + plt.margins(0.25) + assert plt.margins() == (0.25, 0.25) + plt.locator_params(axis="y", nbins=3) + assert ax._axis_props("y")["tick_count"] == 3 + for name in ("tick_params", "margins", "locator_params"): + assert name in plt.__all__ + + +def test_cm_namespace_returns_callable_colormaps() -> None: + viridis = plt.cm.viridis + assert callable(viridis) and viridis.N == 256 and viridis.name == "viridis" + assert np.asarray(viridis(np.linspace(0, 1, 3))).shape == (3, 4) + assert plt.cm.viridis_r.name == "viridis_r" + tab10 = plt.cm.tab10 + assert tab10.N == 10 + assert np.asarray(tab10(np.arange(3))).shape == (3, 4) + assert tab10(0) == pytest.approx((0x1F / 255, 0x77 / 255, 0xB4 / 255, 1.0)) + assert [plt.cm.tab20.N, plt.cm.Set1.N, plt.cm.Set2.N, plt.cm.Set3.N, plt.cm.Paired.N] == [ + 20, + 9, + 8, + 12, + 12, + ] + assert np.allclose(plt.cm.Set1_r(0), plt.cm.Set1(8)) + assert plt.get_cmap("tab10").N == 10 and plt.get_cmap("Paired", 4).N == 4 + assert plt.get_cmap(viridis) is viridis + with pytest.raises(AttributeError): + getattr(plt.cm, "not_a_colormap") # noqa: B009 - attribute access is the API under test + _fig, ax = plt.subplots() + ax.imshow(Z, cmap=plt.cm.gray) + ax.scatter([0, 1], [0, 1], c=[0, 1], cmap=plt.cm.plasma_r) + with pytest.raises(ValueError): + ax.imshow(Z, cmap=plt.cm.tab10) # no engine table: still loud + + +def test_qualitative_tables_match_matplotlib() -> None: + mpl = _matplotlib() + from matplotlib.colors import to_hex + + for name in ("tab10", "tab20", "Set1", "Set2", "Set3", "Paired", "Dark2", "Pastel1"): + reference = [to_hex(c) for c in mpl.colormaps[name].colors] + ours = [to_hex(c) for c in getattr(plt.cm, name)(np.arange(len(reference)))] + assert ours == reference, name + + +def test_bar_patch_geometry_matches_matplotlib() -> None: + _fig, ax = plt.subplots() + bars = ax.bar([1, 2, 3], [1, 2, 3], width=0.5, bottom=[0, 1, 2]) + geometry = [(r.get_x(), r.get_y(), r.get_width(), r.get_height()) for r in bars] + np.testing.assert_allclose(geometry, [(0.75, 0, 0.5, 1), (1.75, 1, 0.5, 2), (2.75, 2, 0.5, 3)]) + assert bars[1].get_xy() == pytest.approx((1.75, 1.0)) + assert bars[1].get_bbox().bounds == pytest.approx((1.75, 1.0, 0.5, 2.0)) + assert bars[1].get_center() == pytest.approx((2.0, 2.0)) + horizontal = ax.barh([0, 1], [3, 4], height=0.4, left=1) + np.testing.assert_allclose( + [(r.get_x(), r.get_y(), r.get_width(), r.get_height()) for r in horizontal], + [(1, -0.2, 3, 0.4), (1, 0.8, 4, 0.4)], + ) + _fig, ax = plt.subplots() + categorical = ax.bar(["a", "b", "c"], [1, 2, 3]) + for r in categorical: + ax.text(r.get_x() + r.get_width() / 2, r.get_height(), f"{r.get_height():g}", ha="center") + assert [r.get_x() for r in categorical] == pytest.approx([-0.4, 0.6, 1.6]) + _matplotlib().use("Agg") + import matplotlib.pyplot as mplt + + mfig, max_ = mplt.subplots() + reference = max_.bar([1, 2, 3], [1, 2, 3], width=0.5, bottom=[0, 1, 2]) + np.testing.assert_allclose( + geometry, [(r.get_x(), r.get_y(), r.get_width(), r.get_height()) for r in reference] + ) + mplt.close(mfig) + + +def test_bar_with_string_categories_and_error_bars_autoscales() -> None: + _fig, ax = plt.subplots() + ax.bar(["a", "b", "c"], [1, 2, 3], yerr=[0.1, 0.2, 0.3]) + assert ax.get_xlim() == pytest.approx((-0.54, 2.54)) + assert ax.get_ylim()[1] >= 3.3 + _fig, ax = plt.subplots() + ax.barh(["a", "b", "c"], [1, 2, 3], xerr=[0.1, 0.2, 0.3]) + assert ax.get_ylim() == pytest.approx((-0.54, 2.54)) + assert ax.get_xlim()[1] >= 3.3 + assert len(ax.get_yticklabels()) == 3 diff --git a/tests/pyplot/test_p3_option_contracts.py b/tests/pyplot/test_p3_option_contracts.py index ff3832810..0c810cffa 100644 --- a/tests/pyplot/test_p3_option_contracts.py +++ b/tests/pyplot/test_p3_option_contracts.py @@ -176,39 +176,22 @@ def _stream_args() -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: (lambda ax: ax.quiver([0, 1], [0, 1], [1, 0], [0, 1], minlength=0), "minlength"), (lambda ax: ax.quiver([0, 1], [0, 1], [1, 0], [0, 1], norm=Normalize(0, 1)), "norm"), (lambda ax: ax.quiver([0, 1], [0, 1], [1, 0], [0, 1], clim=(0, 1)), "clim"), - (lambda ax: ax.quiver([0, 1], [0, 1], [1, 0], [0, 1], zorder=3), "zorder"), (lambda ax: ax.contour(_Z, linestyles="dashed"), "linestyles"), (lambda ax: ax.contourf(_Z, corner_mask="legacy"), "corner_mask"), (lambda ax: ax.streamplot(*_stream_args(), transform="data"), "transform"), - (lambda ax: ax.streamplot(*_stream_args(), zorder=2), "zorder"), (lambda ax: ax.streamplot(*_stream_args(), minlength=0.5), "minlength"), (lambda ax: ax.streamplot(*_stream_args(), arrowstyle="->"), "arrowstyle"), - (lambda ax: ax.pcolormesh(_Z, antialiased=False), "antialiased"), - (lambda ax: ax.pcolor(_Z, antialiased=False), "antialiased"), (lambda ax: ax.table(cellText=[["a"]], loc="top"), "loc"), ( lambda ax: ax.quiverkey(_quiver(ax), 0.5, 0.5, 1, "k", fontproperties={"size": 9}), "fontproperties", ), - (lambda ax: ax.quiverkey(_quiver(ax), 0.5, 0.5, 1, "k", zorder=5), "zorder"), (lambda ax: ax.bar_label(ax.bar([0], [1]), fontproperties="serif"), "fontproperties"), (lambda ax: ax.spy(np.eye(3), aspect="auto"), "aspect"), - ( - lambda ax: ax.tripcolor([0, 1, 2], [0, 1, 0], [1.0, 2.0, 3.0], antialiased=True), - "antialiased", - ), - ( - lambda ax: ax.tricontour([0, 1, 2], [0, 1, 0], [1.0, 2.0, 3.0], antialiased=False), - "antialiased", - ), ( lambda ax: ax.tricontour([0, 1, 2], [0, 1, 0], [1.0, 2.0, 3.0], linestyles="dashed"), "linestyles", ), - ( - lambda ax: ax.tricontourf([0, 1, 2], [0, 1, 0], [1.0, 2.0, 3.0], antialiased=True), - "antialiased", - ), (lambda ax: ax.eventplot([[1, 2]], linestyles="steps"), "linestyle"), ( lambda ax: ax.triplot([0, 1, 2], [0, 1, 0], triangles=[[0, 1, 2]], dashes=(2, 1)), @@ -238,6 +221,20 @@ def _quiver(ax): return ax.quiver([0, 1], [0, 1], [1, 0], [0, 1]) +def test_artist_level_antialiased_and_zorder_are_accepted_noops() -> None: + """``antialiased``/``aa``/``zorder`` are Artist-level compat-noops (compat.md).""" + _fig, ax = plt.subplots() + ax.quiver([0, 1], [0, 1], [1, 0], [0, 1], zorder=3) + ax.streamplot(*_stream_args(), zorder=2) + ax.quiverkey(_quiver(ax), 0.5, 0.5, 1, "k", zorder=5) + ax.pcolormesh(_Z, antialiased=False) + ax.pcolor(_Z, aa=False) + ax.tripcolor([0, 1, 2], [0, 1, 0], [1.0, 2.0, 3.0], antialiased=True) + ax.tricontour([0, 1, 2], [0, 1, 0], [1.0, 2.0, 3.0], antialiased=False) + ax.tricontourf([0, 1, 2], [0, 1, 0], [1.0, 2.0, 3.0], antialiased=True) + assert ax._entries + + def test_matplotlib_default_option_values_pass_through() -> None: _fig, ax = plt.subplots() ax.pie([1, 2], shadow=False, frame=False, rotatelabels=False) diff --git a/tests/pyplot/test_pdsh_gap_features.py b/tests/pyplot/test_pdsh_gap_features.py index f928cc1fb..6090ccc48 100644 --- a/tests/pyplot/test_pdsh_gap_features.py +++ b/tests/pyplot/test_pdsh_gap_features.py @@ -236,7 +236,10 @@ def test_rdgy_and_jet_resolve_and_render(): def test_matplotlib_gallery_colormaps_resolve_and_render(name, canonical): assert plt.get_cmap(name).name == canonical assert plt.colormaps[name].name == canonical - assert getattr(plt.cm, name) == name + # plt.cm. is a callable colormap object (as in Matplotlib), not a + # bare name carrier; it still resolves to the same engine table. + assert getattr(plt.cm, name).name == canonical + assert callable(getattr(plt.cm, name)) fig, ax = plt.subplots() ax.imshow(np.arange(16.0).reshape(4, 4), cmap=name) _png(fig) @@ -352,10 +355,14 @@ def test_colorbar_ticks_and_extend_reach_both_exports(): def test_colorbar_rejects_unknown_kwargs_and_accepts_explicit_cax(): + # ``fraction`` is an accepted compat-noop (the colorbar strip has a fixed + # width); a keyword Matplotlib's colorbar does not take stays loud. + plt.colorbar(plt.imshow(np.eye(3)), fraction=0.05) + plt.close("all") fig, ax = plt.subplots() image = plt.imshow(np.eye(3)) with pytest.raises(TypeError): - plt.colorbar(image, fraction=0.05) + plt.colorbar(image, glow=0.05) cax = fig.add_axes((0.85, 0.1, 0.075, 0.8)) colorbar = plt.colorbar(image, cax=cax) assert colorbar.ax is cax diff --git a/tests/test_api_p1_fixes.py b/tests/test_api_p1_fixes.py new file mode 100644 index 000000000..6571cfbd1 --- /dev/null +++ b/tests/test_api_p1_fixes.py @@ -0,0 +1,260 @@ +"""Public-API P1 fixes: silent drops, leaked exception types, and factory +shortcuts that the composed `*_chart` builders promised but did not honor. + +Each block pins one previously reproduced defect against the public surface +(`xy.*` only), so a regression shows up as the user would have seen it. +""" + +from __future__ import annotations + +import re +import warnings + +import numpy as np +import pyarrow as pa +import pytest + +import xy +from xy import channels +from xy.components import _MARK_APPLIERS + +# -- 1. log axis drops non-positive rows loudly ------------------------------ + + +def _log_payload(**axis_kwargs): + chart = xy.scatter_chart( + xy.scatter(x=range(5), y=[-1, 0, 1, 2, 3]), + xy.y_axis(type_="log", **axis_kwargs), + ) + return chart.figure().build_payload()[0] + + +def test_log_axis_default_drop_warns_with_axis_count_and_remedy() -> None: + with pytest.warns(RuntimeWarning, match=r"y .*2 of 5 .*nonpositive=") as record: + spec = _log_payload() + assert spec["traces"][0]["n_marks"] == 3 + message = str(record[0].message) + assert "symlog" in message + + +@pytest.mark.parametrize("mode", ["clip", "mask"]) +def test_log_axis_explicit_nonpositive_policy_is_silent(mode: str) -> None: + with warnings.catch_warnings(): + warnings.simplefilter("error") + spec = _log_payload(nonpositive=mode) + assert spec["traces"][0]["n_marks"] == 3 + + +def test_log_axis_all_positive_data_is_silent() -> None: + with warnings.catch_warnings(): + warnings.simplefilter("error") + chart = xy.scatter_chart( + xy.scatter(x=range(3), y=[1, 2, 3]), + xy.y_axis(type_="log"), + ) + chart.figure().build_payload() + + +def test_log_axis_area_counts_rows_not_columns() -> None: + """y and base both fail on the same row: one dropped row, not two.""" + chart = xy.area_chart( + xy.area(x=[0, 1, 2], y=[0, 2, 3], base=[-1, 1, 1]), + xy.y_axis(type_="log"), + ) + with pytest.warns(RuntimeWarning, match=r"1 of 3"): + chart.figure().build_payload() + + +# -- 2. non-finite continuous color/size rows are not drawn ----------------- + + +def _shipped_color_u8(color: list[float]) -> tuple[int, np.ndarray]: + fig = xy.scatter_chart(xy.scatter(x=[1, 2, 3, 4, 5], y=[1, 2, 3, 4, 5], color=color)).figure() + spec, blob = fig.build_payload() + trace = spec["traces"][0] + return trace["n_marks"], fig.traces[0].shipped_sel + + +@pytest.mark.parametrize("bad", [np.nan, np.inf, -np.inf]) +def test_nonfinite_color_row_is_not_drawn(bad: float) -> None: + n_marks, sel = _shipped_color_u8([1.0, bad, 3.0, 4.0, 5.0]) + assert n_marks == 4 + np.testing.assert_array_equal(sel, [0, 2, 3, 4]) + + +def test_nonfinite_size_row_is_not_drawn() -> None: + fig = xy.scatter_chart( + xy.scatter(x=[1, 2, 3], y=[1, 2, 3], size=[4.0, np.nan, 8.0]), + ).figure() + spec, _blob = fig.build_payload() + assert spec["traces"][0]["n_marks"] == 2 + np.testing.assert_array_equal(fig.traces[0].shipped_sel, [0, 2]) + + +def test_nonfinite_color_and_xy_exclusions_compose() -> None: + fig = xy.scatter_chart( + xy.scatter(x=[1, np.nan, 3, 4], y=[1, 2, 3, 4], color=[1.0, 2.0, np.inf, 4.0]), + ).figure() + spec, _blob = fig.build_payload() + assert spec["traces"][0]["n_marks"] == 2 + np.testing.assert_array_equal(fig.traces[0].shipped_sel, [0, 3]) + + +def _svg_mark_count(svg: str) -> int: + return len(re.findall(r" None: + """The exporters read the shipped buffers, so a colour-less point cannot + reappear in SVG wearing the domain-floor colour.""" + chart = xy.scatter_chart( + xy.scatter(x=[1, 2, 3], y=[1, 2, 3], color=[1.0, np.inf, 3.0]), + width=200, + height=120, + ) + svg = chart.to_svg() + assert _svg_mark_count(svg) == 2 + + +def test_finite_channels_do_not_allocate_a_selection() -> None: + fig = xy.scatter_chart( + xy.scatter(x=[1, 2, 3], y=[1, 2, 3], color=[1.0, 2.0, 3.0], size=[1.0, 2.0, 3.0]), + ).figure() + fig.build_payload() + assert fig.traces[0].shipped_sel is None + + +def test_quantizer_contract_documented_not_silent() -> None: + # The quantizer itself still floors non-finite input: the contract is that + # the emitters exclude such rows before shipping (design dossier §19). + out = channels.quantize_unit_u8(np.array([1.0, np.nan, 3.0]), (1.0, 3.0)) + np.testing.assert_array_equal(out, [0, 0, 255]) + + +# -- 3. sankey_chart accepts its own mark ------------------------------------- + +LINKS = [("a", "b", 1.0), ("a", "c", 2.0), ("b", "d", 1.0), ("c", "d", 2.0)] + + +def _spec(chart: xy.Chart) -> dict: + spec, _blob = chart.figure().build_payload() + return spec + + +def test_sankey_chart_accepts_links_or_a_sankey_mark() -> None: + by_links = _spec(xy.sankey_chart(LINKS, width=400, height=300)) + by_mark = _spec(xy.sankey_chart(xy.sankey(LINKS), width=400, height=300)) + assert by_links == by_mark + + +def test_sankey_chart_mark_form_keeps_mark_props() -> None: + spec = _spec(xy.sankey_chart(xy.sankey(LINKS, node_width=0.1, labels=False))) + control = _spec(xy.sankey_chart(LINKS, node_width=0.1, labels=False)) + assert spec == control + + +def test_sankey_chart_refuses_mark_kwargs_beside_an_explicit_mark() -> None: + with pytest.raises(ValueError, match=r"explicit xy\.sankey"): + xy.sankey_chart(xy.sankey(LINKS), node_width=0.1) + + +def test_sankey_chart_accepts_chrome_children_first() -> None: + chart = xy.sankey_chart(xy.legend(show=False), xy.sankey(LINKS)) + spec = _spec(chart) + assert spec["traces"] == _spec(xy.sankey_chart(LINKS, xy.legend(show=False)))["traces"] + assert spec["traces"] and all(t["kind"] == "ribbon" for t in spec["traces"]) + + +def test_sankey_chart_chrome_only_is_mark_free() -> None: + assert xy.sankey_chart(xy.legend(show=False)).figure().traces == [] + + +def test_sankey_chart_refuses_mark_kwargs_without_links() -> None: + with pytest.raises(ValueError, match="without links"): + xy.sankey_chart(xy.legend(show=False), node_width=0.1) + + +# -- 4. a hand-built xy.Mark never leaks KeyError ------------------------------ + +_MINIMAL_MARK_DATA = { + "heatmap": {"x": [0, 1], "y": [0, 1], "z": [[1, 2], [3, 4]]}, +} + + +@pytest.mark.parametrize("kind", sorted(_MARK_APPLIERS)) +def test_bare_mark_builds_or_raises_value_error(kind: str) -> None: + extra = dict(_MINIMAL_MARK_DATA.get(kind, {})) + x = extra.pop("x", [1.0, 2.0, 3.0]) + y = extra.pop("y", [1.0, 2.0, 3.0]) + mark = xy.Mark(kind=kind, x=x, y=y, props=extra) + try: + xy.chart(mark).figure() + except ValueError as exc: + assert kind in str(exc) or "links" in str(exc) or "requires" in str(exc) or str(exc) + except KeyError as exc: # pragma: no cover - the defect under test + pytest.fail(f"{kind}: KeyError leaked for missing prop {exc}") + + +def test_bare_scatter_and_line_marks_match_their_factories() -> None: + bare = xy.chart(xy.Mark(kind="scatter", x=[1, 2], y=[1, 2])).figure() + made = xy.chart(xy.scatter(x=[1, 2], y=[1, 2])).figure() + assert bare.build_payload()[0]["traces"] == made.build_payload()[0]["traces"] + bare_line = xy.chart(xy.Mark(kind="line", x=[1, 2], y=[1, 2])).figure() + made_line = xy.chart(xy.line(x=[1, 2], y=[1, 2])).figure() + assert bare_line.build_payload()[0]["traces"] == made_line.build_payload()[0]["traces"] + + +def test_bare_mark_explicit_props_win_over_factory_defaults() -> None: + fig = xy.chart(xy.Mark(kind="scatter", x=[1, 2], y=[1, 2], props={"size": 9.0})).figure() + assert fig.traces[0].size_ch.constant == 9.0 + + +# -- 5. bare pyarrow string arrays are categorical axes ------------------------ + + +def _x_categories(values) -> list[str]: + fig = xy.scatter_chart(xy.scatter(x=values, y=[1, 2, 3])).figure() + return list(fig._axis_categories["x"]) + + +def test_pyarrow_string_array_is_a_categorical_axis() -> None: + assert _x_categories(pa.array(["a", "b", "c"])) == ["a", "b", "c"] + + +def test_pyarrow_chunked_string_array_is_a_categorical_axis() -> None: + assert _x_categories(pa.chunked_array([["a", "b"], ["c"]])) == ["a", "b", "c"] + + +def test_pyarrow_dictionary_array_is_a_categorical_axis() -> None: + assert _x_categories(pa.array(["a", "b", "a"]).dictionary_encode()) == ["a", "b"] + + +def test_pyarrow_string_array_with_nulls_matches_pandas() -> None: + pd = pytest.importorskip("pandas") + arrow = _x_categories(pa.array(["a", None, "c"])) + pandas = _x_categories(pd.Series(["a", None, "c"], dtype="string[pyarrow]")) + assert arrow == pandas + + +def test_pyarrow_string_facet_keys() -> None: + """`by=` as a per-row pyarrow string array factorizes like a list would.""" + data = {"x": [1, 2, 3, 4], "y": [1, 2, 3, 4]} + by = pa.array(["a", "a", "b", None]) + grid = xy.facet_chart(xy.scatter(x="x", y="y"), by=by, data=data).figure() + assert list(grid.labels) == ["a", "b", "(missing)"] + + +# -- 6. a missing facet column is a ValueError like every other column --------- + + +def test_missing_facet_column_is_a_value_error() -> None: + data = {"x": [1, 2], "y": [1, 2]} + with pytest.raises(ValueError, match="facet column 'zz' not found in data"): + xy.facet_chart(xy.scatter(x="x", y="y"), by="zz", data=data).figure() + + +def test_missing_facet_column_in_a_frame_is_a_value_error() -> None: + pd = pytest.importorskip("pandas") + df = pd.DataFrame({"x": [1, 2], "y": [1, 2]}) + with pytest.raises(ValueError, match="facet column 'zz' not found in data"): + xy.facet_chart(xy.scatter(x="x", y="y"), by="zz", data=df).figure() diff --git a/tests/test_channel_malformed_messages.py b/tests/test_channel_malformed_messages.py new file mode 100644 index 000000000..84ce49996 --- /dev/null +++ b/tests/test_channel_malformed_messages.py @@ -0,0 +1,333 @@ +"""Malformed client messages never raise and never mutate figure state. + +Wire-protocol §1: `handle_message` returns None (or a `row: null` pick reply) +for anything a hostile or racing client can send, and a dropped message +leaves drill bookkeeping, the view-state cache, and legend predicates exactly +as it found them. `tests/test_channel.py` pins the happy paths; this file is +the fuzz-shaped complement, seeded with the audit's reproductions. +""" + +from __future__ import annotations + +import math +from typing import Any + +import numpy as np +import pytest + +from xy import lod +from xy._figure import Figure +from xy.channel import ChannelCallbacks, handle_message + + +def _density_scatter(n: int = 5_000) -> Figure: + rng = np.random.default_rng(7) + return Figure().scatter(rng.uniform(0.0, 100.0, n), rng.uniform(0.0, 100.0, n), density=True) + + +def _snapshot(fig: Figure) -> dict[str, Any]: + """Everything a message may durably change, in comparable form.""" + return { + "view_state": fig.view_state(), + "traces": [ + ( + t.drill_mode, + t.drill_seq, + t.shipped_sel is None, + sorted(t.drill_history), + t.hidden, + sorted(t.hidden_categories), + ) + for t in fig.traces + ], + } + + +def _recording_callbacks(fired: list[str]) -> ChannelCallbacks: + return ChannelCallbacks( + on_hover=lambda row: fired.append("hover"), + on_click=lambda row: fired.append("click"), + on_brush=lambda brush: fired.append("brush"), + on_select=lambda sel: fired.append("select"), + on_view_change=lambda view: fired.append("view_change"), + on_animation_start=lambda ev: fired.append("animation_start"), + on_animation_end=lambda ev: fired.append("animation_end"), + ) + + +_NON_STRING_TYPES = [["view"], {"type": "view"}, 3, 1.5, None, b"pick", ("pick",)] + +_MALFORMED: list[dict[str, Any]] = [ + *[{"type": kind} for kind in _NON_STRING_TYPES], + {"type": "view", "x0": 1e-310, "x1": 2e-310}, + {"type": "view", "x0": 0.0, "x1": 1.0, "px": [512]}, + {"type": "density_view", "trace": 0, "x0": 1e-310, "x1": 2e-310, "y0": -1.0, "y1": 1.0}, + {"type": "density_view", "trace": 0, "x0": -1.0, "x1": 1.0, "y0": 1e-320, "y1": 3e-320}, + { + "type": "density_view", + "trace": 0, + "x0": 5e-324, + "x1": 1e-323, + "y0": -1.0, + "y1": 1.0, + "w": 4096, + "h": 4096, + }, + {"type": "density_view", "trace": 0, "x0": 0.0, "x1": 1.0, "y0": 0.0, "y1": 1.0, "w": [512]}, + {"type": "density_view", "trace": [0], "x0": 0.0, "x1": 1.0, "y0": 0.0, "y1": 1.0}, + {"type": "density_view", "trace": 0, "x0": 0.0, "x1": math.nan, "y0": 0.0, "y1": 1.0}, + {"type": "pick", "trace": 0, "index": 10**9}, + {"type": "pick", "trace": 0, "index": -1}, + {"type": "pick", "trace": 0, "index": [1]}, + {"type": "pick", "trace": [0], "index": 1}, + {"type": "pick", "trace": 0, "index": 1, "drill_seq": {"seq": 1}}, + {"type": "click", "trace": 0, "index": 10**9}, + {"type": "click", "trace": 0, "index": [1]}, + {"type": "click", "trace": 99, "index": 0}, + {"type": "legend_toggle", "trace": 0, "hidden": "yes"}, + {"type": "legend_toggle", "trace": 0, "hidden": True, "category": [1]}, + {"type": "legend_toggle", "trace": 0, "hidden": True, "category": 0}, + {"type": "view_change"}, + {"type": "view_change", "ranges": {"x": [1.0, 1.0]}}, + {"type": "view_change", "ranges": {"x": [1.0, 2.0, 3.0]}}, + {"type": "view_change", "ranges": {"x": "wide"}}, + {"type": "view_change", "ranges": {"x": [1.0, math.nan]}}, + {"type": "view_change", "ranges": {"x": [1.0, math.inf]}}, + {"type": "view_change", "x0": 0.0, "x1": 0.0, "y0": 0.0, "y1": 1.0}, + {"type": "view_change", "x0": 0.0, "x1": 1.0, "y0": "low", "y1": 1.0}, + {"type": "select"}, + {"type": "select", "x0": "left", "x1": 1.0, "y0": 0.0, "y1": 1.0}, + {"type": "select", "x0": math.nan, "x1": 1.0, "y0": 0.0, "y1": 1.0}, + {"type": "select_polygon"}, + {"type": "select_polygon", "points": "abc"}, + {"type": "select_polygon", "points": [[0.0, 1.0], [1.0]]}, + {"type": "select_polygon", "points": [[0.0, 1.0], ["a", 2.0]]}, +] + + +@pytest.mark.parametrize("content", _MALFORMED, ids=lambda c: repr(c)[:70]) +def test_malformed_message_is_dropped_without_side_effects(content: dict[str, Any]) -> None: + fig = _density_scatter() + fig.build_payload() + before = _snapshot(fig) + fired: list[str] = [] + + reply = handle_message(fig, content, None, callbacks=_recording_callbacks(fired)) + + # `pick` answers every well-typed miss with an empty row so the client + # clears hover; everything else malformed is silence. + if reply is not None: + assert reply[0] == {"type": "pick_result", "seq": None, "row": None} + assert fired == [] + assert _snapshot(fig) == before + + +@pytest.mark.parametrize("kind", _NON_STRING_TYPES, ids=lambda k: type(k).__name__) +def test_non_string_type_returns_none(kind: Any) -> None: + # An unhashable `type` used to raise from the animation-kind membership + # test before any other field was inspected (§1: unknown type → None). + fig = Figure().scatter(np.arange(3.0), np.arange(3.0)) + fig.build_payload() + assert handle_message(fig, {"type": kind}) is None + + +# -- pick/click index bounds (§2 `pick`) -------------------------------------- + + +def _aggregate_figures() -> list[tuple[str, Figure]]: + rng = np.random.default_rng(0) + hist = Figure().histogram(rng.normal(size=1_000)) + hexb = Figure().hexbin(rng.normal(size=5_000), rng.normal(size=5_000), gridsize=16) + return [("histogram", hist), ("hexbin", hexb)] + + +@pytest.mark.parametrize( + "label,fig", _aggregate_figures(), ids=lambda v: v if isinstance(v, str) else "" +) +def test_pick_past_readout_rows_replies_null_row(label: str, fig: Figure) -> None: + # `n_points` advertises the sample count (1000) while the readout columns + # hold the bin rows (~27): every index in between used to IndexError out + # of `row_dict`. The contract is `row: null`, never an exception. + fig.build_payload() + t = fig.traces[0] + rows = len(t.x) + assert rows < t.n_points, f"{label} no longer aggregates; pick another kind" + fired: list[str] = [] + callbacks = _recording_callbacks(fired) + + for index in (rows, rows + 1, (rows + t.n_points) // 2, t.n_points - 1, t.n_points): + reply = handle_message(fig, {"type": "pick", "trace": 0, "index": index, "seq": 4}, None) + assert reply is not None + assert reply[0] == {"type": "pick_result", "seq": 4, "row": None} + assert ( + handle_message(fig, {"type": "click", "trace": 0, "index": index}, None, callbacks) + is None + ) + assert fired == [] + + # The last readable row still resolves — the bound tightened, not vanished. + reply = handle_message(fig, {"type": "pick", "trace": 0, "index": rows - 1}, None, callbacks) + assert reply is not None and reply[0]["row"] is not None + assert reply[0]["row"]["index"] == rows - 1 + assert fired == ["hover"] + + +def test_pick_keeps_advertised_count_bound_when_columns_are_longer() -> None: + # Errorbar is the inverse shape: 50 points advertised over 150 segment + # endpoints. Indices in [n_points, len(x)) stay unpickable, exactly as + # before — the bound is the smaller of the two counts. + fig = Figure().errorbar(np.arange(50.0), np.arange(50.0), yerr=0.1) + fig.build_payload() + t = fig.traces[0] + assert len(t.x) > t.n_points + hit = handle_message(fig, {"type": "pick", "trace": 0, "index": t.n_points - 1}) + miss = handle_message(fig, {"type": "pick", "trace": 0, "index": t.n_points}) + assert hit is not None and hit[0]["row"] is not None + assert miss is not None and miss[0]["row"] is None + + +def test_pick_heatmap_bound_is_the_grid_not_the_edge_columns() -> None: + # Grid marks keep only the outer edges in x/y; the readable rows are the + # cells, so the bound must not collapse to `len(t.x) == 2`. + fig = Figure().heatmap(np.arange(42.0).reshape(6, 7)) + fig.build_payload() + last = handle_message(fig, {"type": "pick", "trace": 0, "index": 41}) + past = handle_message(fig, {"type": "pick", "trace": 0, "index": 42}) + assert last is not None and last[0]["row"] == { + "trace": 0, + "index": 41, + "row": 5, + "col": 6, + "color_value": 41.0, + } + assert past is not None and past[0]["row"] is None + + +# -- density_view windows below f64 resolution (§2 `density_view`) ----------- + + +@pytest.mark.parametrize( + "window", + [ + {"x0": 1e-310, "x1": 2e-310, "y0": -1.0, "y1": 1.0}, + {"x0": -1.0, "x1": 1.0, "y0": 1e-320, "y1": 3e-320}, + {"x0": 5e-324, "x1": 1e-323, "y0": -1.0, "y1": 1.0, "w": 4096, "h": 4096}, + ], + ids=["x-subnormal", "y-subnormal", "x-min-subnormal-4k"], +) +def test_density_view_subnormal_span_is_dropped_without_drill_mutation( + window: dict[str, float], +) -> None: + fig = _density_scatter() + fig.build_payload() + before = _snapshot(fig) + assert handle_message(fig, {"type": "density_view", "trace": 0, **window}) is None + assert _snapshot(fig) == before + + +@pytest.mark.parametrize("span", [3e-308, 1e-300, 1e-200, 1e-100, 1e-20, 1e-6]) +def test_density_view_tiny_normal_spans_reply_or_drop_without_raising(span: float) -> None: + # Spans that survive `normalize_window` but still out-resolve the drill + # ladder (`extent / (pad * span)` overflowing f64, or a sub-ulp block) must + # fall back to the raw window, not raise from `aligned_window`. + fig = _density_scatter() + fig.build_payload() + reply = handle_message( + fig, + {"type": "density_view", "trace": 0, "x0": 50.0, "x1": 50.0 + span, "y0": 0.0, "y1": 100.0}, + ) + if reply is not None: + entry = reply[0]["traces"][0] + assert entry["mode"] in {"points", "density"} + assert all(math.isfinite(v) for v in (*entry["x_range"], *entry["y_range"])) + + +def test_normalize_window_rejects_subnormal_spans_only_when_area_is_required() -> None: + with pytest.raises(ValueError): + lod.normalize_window(1e-310, 2e-310, -1.0, 1.0) + with pytest.raises(ValueError): + lod.normalize_window(-1.0, 1.0, 1e-320, 3e-320) + # The smallest normal span is the floor, not a rejection. + lo_x, hi_x, _, _ = lod.normalize_window(0.0, 2.2250738585072014e-308, -1.0, 1.0) + assert hi_x - lo_x > 0.0 + # Area-free callers (select, view_change) keep accepting anything finite. + assert lod.normalize_window(1e-310, 2e-310, 0.0, 0.0, require_area=False) == ( + 1e-310, + 2e-310, + 0.0, + 0.0, + ) + + +@pytest.mark.parametrize( + "lo,hi,extent_lo,extent_hi", + [ + (1e-310, 2e-310, -1.0, 1.0), # quotient overflows to inf + (0.0, 3e-308, 0.0, 4.0), # finite ratio, level 1024: 2**1024 is not a float + (0.0, 1e-320, 0.0, 1e-300), # subnormal block + (0.0, 1e-10, -1e250, 1e250), # huge reach over a tiny block + ], +) +def test_aligned_window_extreme_spans_never_raise_and_contain( + lo: float, hi: float, extent_lo: float, extent_hi: float +) -> None: + for pad in (1.0, 2.0, 4.0, 8.0): + a, b = lod.aligned_window(lo, hi, extent_lo, extent_hi, pad) + assert math.isfinite(a) and math.isfinite(b) + assert a <= lo and b >= hi + + +# -- view_change durability (§2 `view_change`, view-state.md §5.1) ----------- + + +def test_view_change_orders_ranges_and_round_trips_into_state_patch() -> None: + fig = Figure().scatter(np.arange(10.0), np.arange(10.0)) + fig.build_payload() + seen: list[dict[str, Any]] = [] + callbacks = ChannelCallbacks(on_view_change=seen.append) + + assert ( + handle_message( + fig, + {"type": "view_change", "ranges": {"x": [1.5, 1.0], "y": [4.0, 2.0]}}, + None, + callbacks, + ) + is None + ) + state = fig.view_state() + assert state["ranges"]["x"] == [1.0, 1.5] + assert state["ranges"]["y"] == [2.0, 4.0] + assert seen[-1]["ranges"] == {"x": [1.0, 1.5], "y": [2.0, 4.0]} + assert (seen[-1]["x0"], seen[-1]["x1"], seen[-1]["y0"], seen[-1]["y1"]) == (1.0, 1.5, 2.0, 4.0) + + # Legacy shape, flipped: same ordering rule. + handle_message(fig, {"type": "view_change", "x0": 9.0, "x1": 3.0, "y0": 1.0, "y1": 0.0}) + assert fig.view_state()["ranges"] == {"x": [3.0, 9.0], "y": [0.0, 1.0]} + + # Whatever the cache holds must feed straight back into a state patch. + patch = fig.state_patch_message(ranges=fig.view_state()["ranges"]) + assert patch["state"]["ranges"] == {"x": [3.0, 9.0], "y": [0.0, 1.0]} + + +@pytest.mark.parametrize( + "content", + [ + {"type": "view_change", "ranges": {"x": [1.0, 1.0], "y": [0.0, 2.0]}}, + {"type": "view_change", "x0": 1.0, "x1": 1.0, "y0": 2.0, "y1": 1.0}, + {"type": "view_change", "x0": 0.0, "x1": 1.0, "y0": 2.0, "y1": 2.0}, + ], + ids=["ranges-zero-span", "legacy-zero-span-x", "legacy-zero-span-y"], +) +def test_view_change_zero_span_rejects_the_whole_event(content: dict[str, Any]) -> None: + # A zero-span axis is what `Figure.state_patch_message` refuses, so the + # cache must never hold one (view-state.md §5.1 round-trip). The whole + # event drops — the same rule the `ranges` path already applied. + fig = Figure().scatter(np.arange(10.0), np.arange(10.0)) + fig.build_payload() + home = fig.view_state() + seen: list[dict[str, Any]] = [] + assert handle_message(fig, content, None, ChannelCallbacks(on_view_change=seen.append)) is None + assert fig.view_state() == home + assert seen == [] + fig.state_patch_message(ranges=fig.view_state()["ranges"]) diff --git a/tests/test_export_text_safety.py b/tests/test_export_text_safety.py new file mode 100644 index 000000000..b16e16280 --- /dev/null +++ b/tests/test_export_text_safety.py @@ -0,0 +1,126 @@ +"""Text safety of the static exports. + +XML 1.0 §2.2 forbids the C0 controls other than tab/newline/CR, the surrogate +range and U+FFFE/U+FFFF, and no character reference can smuggle them in. A +legend name or tick label carrying one used to produce SVG that no parser +accepts and a PDF export that refused the document, while the HTML and PNG +paths (not XML) succeeded — the same chart exported in two of four formats. +`xy._svg.escape` is the single choke point every raw text sink routes through, +and it now drops those code points (spec/api/export.md §2). These tests pin the +rule at the helper, at the two original repros, and across the whole C0 table. +""" + +from __future__ import annotations + +import re +import xml.etree.ElementTree as ET +import zlib + +import numpy as np +import pytest + +import xy +from xy._svg import _escape_attr, escape + +#: Every code point XML 1.0 cannot carry, as `Char` excludes them. +XML_ILLEGAL = ( + [chr(c) for c in range(0x20) if c not in (0x09, 0x0A, 0x0D)] + + ["￾", "￿"] + + ["\ud800", "\udfff"] # lone surrogates +) + +#: Neighbours the rule must NOT touch: the three legal controls, DEL, the C1 +#: range, no-break space (not `isprintable`, so it takes the slow path), the +#: replacement character and an astral code point. +XML_LEGAL_EDGE = ["\t", "\n", "\r", "\x7f", "\x80", "\x9f", "\xa0", "�", "\U0001f600"] + + +def _ident(ch: str) -> str: + return f"U+{ord(ch):04X}" + + +def _texts(svg: str) -> list[str]: + root = ET.fromstring(svg) + return ["".join(node.itertext()) for node in root.iter() if node.tag.endswith("text")] + + +def _pdf_content(pdf: bytes) -> bytes: + objs = { + int(m.group(1)): m.group(2) + for m in re.finditer(rb"(\d+) 0 obj\n(.*?)\nendobj\n", pdf, re.S) + } + page = next(body for body in objs.values() if re.search(rb"/Type /Page(?!s)", body)) + match = re.search(rb"/Contents (\d+) 0 R", page) + assert match is not None + stream = objs[int(match.group(1))].partition(b"stream\n")[2] + return zlib.decompress(stream.rsplit(b"\nendstream", 1)[0]) + + +@pytest.mark.parametrize("ch", XML_ILLEGAL, ids=_ident) +def test_escape_drops_every_xml_illegal_code_point(ch: str) -> None: + assert escape(f"a{ch}b") == "ab" + assert escape(ch) == "" + # Attribute values share the rule, on top of quoting. + assert _escape_attr(f'a{ch}"b') == "a"b" + + +@pytest.mark.parametrize("ch", XML_LEGAL_EDGE, ids=_ident) +def test_escape_keeps_every_legal_neighbour(ch: str) -> None: + assert escape(f"a{ch}b") == f"a{ch}b" + + +def test_escape_still_escapes_markup_around_dropped_characters() -> None: + assert escape("\x01&\x02<\x03>\x04") == "&<>" + assert escape("") == "" + # Dropping happens before escaping, so nothing can reassemble markup. + assert escape("&\x01amp;") == "&amp;" + # The result is always well-formed character data (the parser's own + # line-end normalisation turns the kept `\r` into `\n`; XML 1.0 §2.11). + hostile = "".join(XML_ILLEGAL + XML_LEGAL_EDGE) + "<&>" + parsed = "".join(ET.fromstring(f"{escape(hostile)}").itertext()) + assert parsed == ("".join(XML_LEGAL_EDGE) + "<&>").replace("\r", "\n") + + +def test_legend_name_with_a_control_character_exports_well_formed_svg() -> None: + # The original repro: `to_svg` produced a document `ET.fromstring` rejected. + xs = np.linspace(0.0, 6.0, 50) + chart = xy.line_chart(xy.line(xs, np.sin(xs), name="a\x01b"), width=400, height=300) + texts = _texts(chart.to_svg()) # parses + assert "ab" in texts, texts + assert not any("\x01" in t for t in texts) + + +def test_bar_category_with_an_escape_character_exports_pdf() -> None: + # The original repro: the PDF writer refused the SVG as unparsable XML. + chart = xy.bar_chart(xy.bar(["a\x1bz", "b"], [1, 2]), width=400, height=300) + pdf = chart.to_image("pdf") + assert pdf.startswith(b"%PDF-1.") + assert b"(az) Tj" in _pdf_content(pdf) + + +@pytest.mark.parametrize("ch", XML_ILLEGAL, ids=_ident) +def test_every_illegal_code_point_round_trips_through_to_svg(ch: str) -> None: + # The whole table through a real chart, hitting the legend-name, tick-label + # (categorical bar) and title sinks at once. + chart = xy.bar_chart( + xy.bar([f"c{ch}1", "c2"], [1.0, 2.0], name=f"s{ch}n"), + width=400, + height=300, + title=f"t{ch}t", + ) + texts = _texts(chart.to_svg()) + assert "c1" in texts, texts + # The title word-wrapper splits on Python whitespace, which includes the + # VT/FF/FS/GS/RS/US controls, so those reach the sink as a space; either + # way the document parses and the control character is gone. + assert "tt" in texts or "t t" in texts, texts + assert all(ch not in t for t in texts) + + +def test_html_and_png_paths_are_unchanged_by_the_rule() -> None: + # HTML carries the code point JSON-escaped (it is not XML and never + # failed); the raster path never saw the helper at all. Both still export. + xs = np.linspace(0.0, 6.0, 50) + chart = xy.line_chart(xy.line(xs, np.sin(xs), name="a\x01b"), width=400, height=300) + assert "a\\u0001b" in chart.to_html() + assert chart.to_image("png").startswith(b"\x89PNG\r\n\x1a\n") diff --git a/tests/test_legend_hidden_hover.py b/tests/test_legend_hidden_hover.py new file mode 100644 index 000000000..66a6d1a32 --- /dev/null +++ b/tests/test_legend_hidden_hover.py @@ -0,0 +1,197 @@ +"""Legend-hidden category points do not hover (interaction spec §10). + +"A hidden series is out of *every* pipeline" — but the CPU hover fallback +(`_nearestCpuIndex`, reached when the GPU pick pass misses) scanned the +unfiltered retained columns for rows `0..g.n` and never consulted the hidden +set. Two defects from one cap: a hidden point still answered hover and showed +its tooltip, and — because `g.n` is the *drawn* count after a category filter +— every visible row shipped at an index >= n became unreachable. + +The layout below puts the hidden point's visible neighbour at shipped index 9 +of 10 rows (n drops to 7 after hiding the 3-row category), so the fix must both +skip the hidden row and scan past the filtered count to pick it. + +Browser probes skip (never fail) without Chromium, like the repo's others. +""" + +from __future__ import annotations + +import sys +from pathlib import Path + +import numpy as np +import pytest + +from conftest import probe_document, run_browser_probe + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT / "python")) + +import xy # noqa: E402 +from xy.export import find_chromium # noqa: E402 + +# (x, y, category) in shipped order. Categories code alphabetically: +# alpha=0, beta=1, gamma=2. Row 3 is the hidden beta point whose only +# neighbour within hover reach is the visible alpha row 9 (0.2 data units = +# ~8 css px on a 520px-wide chart); row 6 is a hidden beta point with no +# visible neighbour within reach at all. +ROWS = [ + (0.5, 9.0, "gamma"), + (1.0, 1.0, "alpha"), + (6.5, 7.5, "beta"), + (5.0, 5.0, "beta"), + (2.0, 2.0, "alpha"), + (9.5, 9.0, "gamma"), + (8.0, 2.0, "beta"), + (3.0, 3.0, "alpha"), + (4.0, 0.5, "gamma"), + (5.2, 5.0, "alpha"), +] +HIDDEN_WITH_NEIGHBOUR = 3 +VISIBLE_NEIGHBOUR = 9 +HIDDEN_ISOLATED = 6 +PLAIN_VISIBLE = 7 + + +def _chart() -> xy.Chart: + x = np.array([r[0] for r in ROWS]) + y = np.array([r[1] for r in ROWS]) + cats = np.array([r[2] for r in ROWS]) + return xy.scatter_chart( + xy.scatter(x, y, color=cats), + xy.x_axis(domain=(0.0, 10.0)), + xy.y_axis(domain=(0.0, 10.0)), + xy.legend(), + width=520, + height=340, + ) + + +_PROBE = """ + +""" + + +def test_hidden_category_points_do_not_hover(tmp_path: Path) -> None: + chromium = find_chromium() + if chromium is None: + pytest.skip("Chromium unavailable") + result = run_browser_probe( + chromium, + probe_document(_chart(), _PROBE), + tmp_path / "legend_hidden_hover.html", + "data-xy-hidden-hover", + label="legend-hidden hover", + ) + assert result["categories"] == ["alpha", "beta", "gamma"], result + assert result["fullN"] == len(ROWS) and result["hiddenN"] == len(ROWS) - 3, result + assert result["hasVisMap"] is True, result + assert result["legendToggles"] == 2, result + + # Unfiltered: both beta points hover as themselves. + before = result["before"] + assert before["neighbour"]["target"] == HIDDEN_WITH_NEIGHBOUR, result + assert before["neighbour"]["tooltip"] and "beta" in before["neighbour"]["tooltip"], result + assert before["isolated"]["target"] == HIDDEN_ISOLATED, result + + hidden = result["hidden"] + # The pointer on a hidden point must not land on it: the CPU fallback + # picks the nearest VISIBLE row — shipped index 9, beyond the filtered + # n of 7 — and the tooltip names that row's category, not "beta". + assert hidden["neighbour"]["fallback"] is not None, result + assert hidden["neighbour"]["fallback"]["index"] == VISIBLE_NEIGHBOUR, result + assert hidden["neighbour"]["fallback"]["dist"] > 0, result + assert hidden["neighbour"]["target"] == VISIBLE_NEIGHBOUR, result + assert hidden["neighbour"]["tooltip"] and "alpha" in hidden["neighbour"]["tooltip"], result + assert "beta" not in hidden["neighbour"]["tooltip"], result + # A hidden point with nothing visible nearby is simply not there. + assert hidden["isolated"]["fallback"] is None, result + assert hidden["isolated"]["target"] is None, result + assert hidden["isolated"]["tooltip"] is None, result + # Unrelated visible rows keep hovering as before. + assert hidden["plain"]["target"] == PLAIN_VISIBLE, result + assert hidden["plain"]["tooltip"] and "alpha" in hidden["plain"]["tooltip"], result + # Keyboard traversal keeps hidden rows (§10 accessibility exception) — + # the pointer fix must not shrink the a11y walk. + assert result["a11yCount"] == len(ROWS), result + + # Untoggling restores the hidden point to hover. + assert result["restoredN"] == len(ROWS), result + assert result["restored"]["neighbour"]["target"] == HIDDEN_WITH_NEIGHBOUR, result + assert "beta" in result["restored"]["neighbour"]["tooltip"], result diff --git a/tests/test_log_ticks_within_decade.py b/tests/test_log_ticks_within_decade.py new file mode 100644 index 000000000..b85670ea8 --- /dev/null +++ b/tests/test_log_ticks_within_decade.py @@ -0,0 +1,279 @@ +"""Log axes inside one decade show linear-style ticks, not none. + +`logTicks` / `_log_ticks` only emitted 1/2/5 x 10^e, so a log axis whose view +sat inside a single decade (any zoom past ~3x) drew no ticks, labels or grid at +all. Renderer-architecture spec §6.1 (Log) now says: when fewer than two decade +ticks fall in range, fall back to `linearTicks` over the span, labelled by the +same `fmtAxis` rules. The exporters share the rule so SVG/PNG/PDF agree with +the browser for the same range. + +Three layers: the TS generator via node, the Python generator, and a parity +assertion between them; then a browser probe against the live renderer and +the SVG exporter on the same window. Browser probes skip (never fail) +without Chromium, like the repo's others. +""" + +from __future__ import annotations + +import json +import subprocess +import sys +import xml.etree.ElementTree as ET +from pathlib import Path + +import pytest + +from conftest import probe_document, run_browser_probe + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT / "python")) + +import xy # noqa: E402 +from xy._svg import _fmt_axis, _fmt_log, _log_ticks # noqa: E402 +from xy.export import find_chromium # noqa: E402 + +TICKS_TS = ROOT / "js" / "src" / "30_ticks.ts" +LOG_AXIS = {"scale": "log"} + +# Wide ranges (two or more decade ticks in view): the decade ladder, its +# thinned label tier and step 1 — captured from the pre-fix generator, so +# this pins the "byte-identical" promise for the behaviour that was right. +WIDE = { + (1e-3, 1e3): ( + [ + 0.001, + 0.002, + 0.005, + 0.01, + 0.02, + 0.05, + 0.1, + 0.2, + 0.5, + 1, + 2, + 5, + 10, + 20, + 50, + 100, + 200, + 500, + 1000, + ], + [0.001, 0.1, 10, 1000], + ), + (1, 1e4): ( + [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000], + [1, 10, 100, 1000, 10000], + ), + (0.5, 50): ([0.5, 1, 2, 5, 10, 20, 50], [1, 10]), + (1, 10): ([1, 2, 5, 10], [1, 10]), +} + +# Within-decade ranges: `linearTicks(lo, hi, 6)` positions, every tick +# labelled, step = the nice linear step so `fmtLinear` shares one decimal +# count across the axis (§6.2). +NARROW = { + (0.3, 0.35): ( + [0.30, 0.31, 0.32, 0.33, 0.34, 0.35], + 0.01, + ["0.30", "0.31", "0.32", "0.33", "0.34", "0.35"], + ), + (2, 3): ([2.0, 2.2, 2.4, 2.6, 2.8, 3.0], 0.2, ["2.0", "2.2", "2.4", "2.6", "2.8", "3.0"]), + (100, 110): ([100, 102, 104, 106, 108, 110], 2, ["100", "102", "104", "106", "108", "110"]), + (1e6, 1.5e6): ( + [1.0e6, 1.1e6, 1.2e6, 1.3e6, 1.4e6, 1.5e6], + 1e5, + ["1.0e6", "1.1e6", "1.2e6", "1.3e6", "1.4e6", "1.5e6"], + ), +} + + +def _node_log_ticks(cases: list[tuple[float, float]]) -> list[dict]: + """Run the TS generator (node imports .ts by file URL) on `cases`.""" + script = f""" +const m = await import({json.dumps(TICKS_TS.as_uri())}); +const out = []; +for (const [lo, hi] of {json.dumps(cases)}) {{ + const r = m.logTicks(lo, hi); + out.push({{ + ticks: r.ticks, labels: r.labels, step: r.step, + text: r.ticks.map((v) => m.fmtAxis({json.dumps(LOG_AXIS)}, v, r.step)), + logText: r.ticks.map((v) => m.fmtLog(v)), + }}); +}} +console.log(JSON.stringify(out)); +""" + completed = subprocess.run( + ["node", "--no-warnings", "--input-type=module", "--eval", script], + cwd=ROOT, + capture_output=True, + text=True, + timeout=60, + check=True, + ) + return json.loads(completed.stdout) + + +def _py_log_ticks(lo: float, hi: float) -> dict: + ticks, labels, step = _log_ticks(lo, hi) + return { + "ticks": ticks, + "labels": labels, + "step": step, + "text": [_fmt_axis(LOG_AXIS, v, step) for v in ticks], + "logText": [_fmt_log(v) for v in ticks], + } + + +def test_ts_wide_ranges_keep_the_decade_ladder() -> None: + results = _node_log_ticks(list(WIDE)) + for (lo, hi), got in zip(WIDE, results, strict=True): + ticks, labels = WIDE[(lo, hi)] + assert got["ticks"] == ticks, (lo, hi, got) + assert got["labels"] == labels, (lo, hi, got) + assert got["step"] == 1, (lo, hi, got) + + +def test_ts_within_decade_falls_back_to_linear_ticks() -> None: + results = _node_log_ticks(list(NARROW)) + for (lo, hi), got in zip(NARROW, results, strict=True): + ticks, step, text = NARROW[(lo, hi)] + assert got["ticks"] == pytest.approx(ticks, rel=1e-9), (lo, hi, got) + assert got["labels"] == got["ticks"], (lo, hi, got) # every tick labelled + assert got["step"] == pytest.approx(step), (lo, hi, got) + assert got["text"] == text, (lo, hi, got) + # Distinct labels: the colorbar formats log ticks by magnitude, which + # collapsed 2.2/2.4/2.6 to "2 2 3" until fmtLog kept significant digits. + assert len(set(got["logText"])) == len(got["ticks"]), (lo, hi, got) + + +def test_py_wide_ranges_keep_the_decade_ladder() -> None: + for (lo, hi), (ticks, labels) in WIDE.items(): + got = _py_log_ticks(lo, hi) + assert got["ticks"] == pytest.approx(ticks, rel=1e-12), (lo, hi, got) + assert got["labels"] == pytest.approx(labels, rel=1e-12), (lo, hi, got) + assert got["step"] == 1.0 + + +def test_py_within_decade_falls_back_to_linear_ticks() -> None: + for (lo, hi), (ticks, step, text) in NARROW.items(): + got = _py_log_ticks(lo, hi) + assert got["ticks"] == pytest.approx(ticks, rel=1e-9), (lo, hi, got) + assert got["labels"] == got["ticks"], (lo, hi, got) + assert got["step"] == pytest.approx(step), (lo, hi, got) + assert got["text"] == text, (lo, hi, got) + assert len(set(got["logText"])) == len(got["ticks"]), (lo, hi, got) + + +def test_ts_and_py_generators_agree() -> None: + """Same positions, same step, same label text on both sides — the static + exports must tick the axis exactly where the browser does.""" + cases = [*WIDE, *NARROW, (0.2, 0.7), (2, 30), (0.5, 5), (3.0, 3.0)] + js_results = _node_log_ticks(cases) + for (lo, hi), js in zip(cases, js_results, strict=True): + py = _py_log_ticks(lo, hi) + assert py["ticks"] == pytest.approx(js["ticks"], rel=1e-9, abs=0), (lo, hi, js, py) + assert py["labels"] == pytest.approx(js["labels"], rel=1e-9, abs=0), (lo, hi, js, py) + assert py["step"] == pytest.approx(js["step"], rel=1e-9), (lo, hi, js, py) + assert py["text"] == js["text"], (lo, hi, js, py) + assert py["logText"] == js["logText"], (lo, hi, js, py) + assert 1 <= len(js["ticks"]) <= 200 + + +def test_within_decade_always_shows_a_readable_tick_count() -> None: + """Every within-decade window a zoom can land on gets 3..8 ticks at the + default target — the failure mode was zero.""" + for lo, hi in [(0.3, 0.35), (2, 3), (100, 110), (1e6, 1.5e6), (7.1, 7.2), (0.011, 0.019)]: + ticks, _labels, _step = _log_ticks(lo, hi) + assert 3 <= len(ticks) <= 8, (lo, hi, ticks) + assert all(lo * (1 - 1e-9) <= v <= hi * (1 + 1e-9) for v in ticks), (lo, hi, ticks) + + +def _svg_x_tick_texts(svg: str, lo: float, hi: float) -> list[str]: + root = ET.fromstring(svg) + out = [] + for node in root.iter(): + if not node.tag.endswith("text"): + continue + text = "".join(node.itertext()) + try: + value = float(text) + except ValueError: + continue + if lo * (1 - 1e-9) <= value <= hi * (1 + 1e-9): + out.append(text) + return out + + +_LOG_ZOOM_PROBE = """ + +""" + + +def test_browser_log_axis_zoomed_inside_a_decade_keeps_ticks(tmp_path: Path) -> None: + chromium = find_chromium() + if chromium is None: + pytest.skip("Chromium unavailable") + xs = [0.001 * 10 ** (i / 4) for i in range(25)] + chart = xy.line_chart( + xy.line(x=xs, y=[float(i) for i in range(25)]), + xy.x_axis(type_="log", domain=(1e-3, 1e3)), + width=480, + height=320, + ) + result = run_browser_probe( + chromium, + probe_document(chart, _LOG_ZOOM_PROBE), + tmp_path / "log_zoom.html", + "data-xy-log-zoom", + label="log axis zoomed inside a decade", + ) + # The unzoomed axis labels decades; the zoomed one must still label, and + # every label must be a distinct value inside the window in order. + assert "0.001" in result["wide"] and "1000" in result["wide"], result + narrow = result["narrow"] + assert 3 <= len(narrow) <= 8, result + values = [float(t) for t in narrow] + assert values == sorted(values) and len(set(values)) == len(values), result + assert all(0.3 <= v <= 0.35 for v in values), result + # Browser and exporter label the same window identically at the same tick + # density: the live labels are exactly one of the Python generator's + # outputs over the densities an axis of this size can ask for. + py_options = { + tuple(_fmt_axis(LOG_AXIS, v, step) for v in ticks) + for ticks, _labels, step in (_log_ticks(0.3, 0.35, target) for target in range(3, 9)) + } + assert tuple(narrow) in py_options, (narrow, py_options) + + # The SVG export of the same window ticks it the same way (raster shares + # `axis_ticks`, so PNG/PDF follow). + svg = xy.line_chart( + xy.line(x=xs, y=[float(i) for i in range(25)]), + xy.x_axis(type_="log", domain=(0.3, 0.35)), + width=480, + height=320, + ).to_svg() + svg_labels = _svg_x_tick_texts(svg, 0.3, 0.35) + assert 3 <= len(svg_labels) <= 8, svg_labels + assert tuple(svg_labels) in py_options, (svg_labels, py_options) diff --git a/tests/test_pdf_export.py b/tests/test_pdf_export.py index 8a2109732..7afcd71d2 100644 --- a/tests/test_pdf_export.py +++ b/tests/test_pdf_export.py @@ -218,3 +218,197 @@ def test_round_trip_via_external_oracle(tmp_path: Path) -> None: assert list(tmp_path.glob("page*.png")) else: pytest.skip("no external PDF oracle (qpdf/mutool/pdftoppm) on PATH") + + +# --------------------------------------------------------------------------- +# The seven text properties the spec says vector honors (spec/api/export.md +# §9, "What PDF makes of the typeface properties"). Until these existed the +# writer refused four of them outright — `styles={"tick_label": {"font-style": +# "italic"}}` raised `unsupported SVG feature: attribute 'font-style'`. +# --------------------------------------------------------------------------- + + +def _styled_pdf(**kwargs) -> bytes: + xs = np.linspace(0.0, 6.0, 50) + chart = xy.line_chart( + xy.line(xs, np.sin(xs)), + xy.x_axis(label="x axis"), + width=400, + height=300, + title="Title here", + **kwargs, + ) + pdf = chart.to_image("pdf") + assert pdf.startswith(b"%PDF-1.") + _xref_offsets(pdf) # every object offset byte-accurate, as for any export + return pdf + + +def _base_fonts(pdf: bytes) -> set[bytes]: + return set(re.findall(rb"/BaseFont /([\w-]+)", pdf)) + + +def _tm_x_before(content: bytes, label: bytes) -> float: + """The Tm translation x of the text run that draws `label`.""" + end = content.index(b"(" + label + b") Tj") + tm = re.findall(rb"([-\d.]+) ([-\d.]+) Tm\n", content[:end])[-1] + return float(tm[0]) + + +@pytest.mark.parametrize( + ("slot", "declaration", "font"), + [ + ("tick_label", {"font-style": "italic"}, b"Helvetica-Oblique"), + ("tick_label", {"font-style": "oblique 10deg"}, b"Helvetica-Oblique"), + ("tick_label", {"font-style": "italic", "font-weight": "700"}, b"Helvetica-BoldOblique"), + ("title", {"font-family": "Georgia, serif"}, b"Times-Roman"), + ("title", {"font-family": "serif", "font-weight": "bold"}, b"Times-Bold"), + ("title", {"font-family": "'Times New Roman'", "font-style": "italic"}, b"Times-Italic"), + ( + "title", + {"font-family": "SERIF", "font-weight": 700, "font-style": "italic"}, + b"Times-BoldItalic", + ), + ("title", {"font-family": "monospace"}, b"Courier"), + ( + "title", + {"font-family": '"Courier New", monospace', "font-weight": "bold"}, + b"Courier-Bold", + ), + ( + "axis_title", + {"font-family": "ui-monospace, Menlo, monospace", "font-style": "oblique"}, + b"Courier-Oblique", + ), + ( + "axis_title", + {"font-family": "monospace", "font-weight": "700", "font-style": "italic"}, + b"Courier-BoldOblique", + ), + ( + "title", + {"font-family": "Arial, sans-serif", "font-style": "italic"}, + b"Helvetica-Oblique", + ), + ], +) +def test_font_style_and_family_select_a_base14_face(slot, declaration, font) -> None: + assert font in _base_fonts(_styled_pdf(styles={slot: declaration})) + + +def test_an_unrecognised_family_falls_back_to_helvetica_rather_than_raising() -> None: + # Georgia is not in the table and names no generic fallback: an author's + # font preference is not generator drift, so the export must not fail. + assert _base_fonts(_styled_pdf(styles={"title": {"font-family": "Georgia"}})) == {b"Helvetica"} + # ...while the same name followed by its generic resolves through it. + assert b"Times-Roman" in _base_fonts( + _styled_pdf(styles={"title": {"font-family": "Georgia, serif"}}) + ) + + +def test_axis_level_label_font_keys_reach_the_pdf() -> None: + xs = np.linspace(0.0, 6.0, 50) + cases: list[tuple[dict[str, str | int | float], bytes]] = [ + ({"label_font_family": "monospace"}, b"Courier"), + ({"label_font_style": "italic"}, b"Helvetica-Oblique"), + ({"label_font_family": "serif", "label_font_style": "oblique"}, b"Times-Italic"), + ] + for style, font in cases: + chart = xy.line_chart( + xy.line(xs, np.sin(xs)), xy.x_axis(label="x", style=style), width=400, height=300 + ) + pdf = chart.to_image("pdf") + _xref_offsets(pdf) + assert font in _base_fonts(pdf), (style, _base_fonts(pdf)) + + +def test_letter_spacing_becomes_tc_and_is_reset_before_plain_text() -> None: + content = _content(_styled_pdf(styles={"title": {"letter-spacing": "1px"}})) + # Tc is graphics state that outlives BT/ET: the spaced title sets it and + # the unspaced tick labels must see it reset, never inherit it. + assert set(re.findall(rb"[-\d.]+ Tc", content)) == {b"1 Tc", b"0 Tc"} + # Every spelling the SVG writer emits: a unitless px number (from a numeric + # slot value), px, em relative to the element's font size, and `normal`. + svg = xy.line_chart( + xy.line([0.0, 1.0], [0.0, 1.0]), + width=400, + height=300, + title="Title here", + styles={"title": {"letter-spacing": "0.5em"}}, + ).to_svg() + title = next(m for m in re.finditer(r"]*>Title here", svg)).group(0) + size_match = re.search(r'font-size="([\d.]+)"', title) + assert size_match is not None + size = float(size_match.group(1)) + for value, expected in ( + (2, b"2 Tc"), + ("2px", b"2 Tc"), + ("0.5em", f"{size * 0.5:g} Tc".encode()), + ("3pt", b"4 Tc"), # 0.75 pt/px, the writer's own scale + ): + content = _content(_styled_pdf(styles={"title": {"letter-spacing": value}})) + assert expected in content, (value, set(re.findall(rb"[-\d.]+ Tc", content))) + assert b" Tc" not in _content(_styled_pdf(styles={"title": {"letter-spacing": "normal"}})) + + +def test_letter_spacing_widens_the_anchor_offset() -> None: + # The title is `text-anchor="middle"`; ten characters at 2px extra advance + # move its start 10px left, as browsers anchor on the spaced advance. + plain = _tm_x_before(_content(_styled_pdf()), b"Title here") + spaced = _tm_x_before( + _content(_styled_pdf(styles={"title": {"letter-spacing": 2}})), b"Title here" + ) + assert spaced == pytest.approx(plain - 10.0, abs=1e-3) + + +def test_opacity_folds_into_the_text_extgstate() -> None: + # With a solid paint the element opacity is the whole /ca. + pdf = _styled_pdf(styles={"axis_title": {"opacity": "0.5", "fill": "#000000"}}) + assert b"/Type /ExtGState /ca 0.5 /CA 0.5 " in pdf + # With the theme paint (rgba with its own alpha) the two multiply, as they + # do for shapes, so the result sits below the declared 0.5. + pdf = _styled_pdf(styles={"axis_title": {"opacity": "0.5"}}) + alphas = [float(v) for v in re.findall(rb"/ExtGState /ca ([\d.]+)", pdf)] + assert alphas and min(alphas) < 0.5, alphas + + +def test_the_selected_face_metrics_drive_the_anchor() -> None: + from xy._pdf import _text_width_px + + assert _text_width_px(b"iii", 10.0, "Courier") == 18.0 # 600 per mille, every glyph + assert _text_width_px(b"iii", 10.0, "Helvetica") == pytest.approx(6.66) # 222 x 3 + assert _text_width_px(b"iii", 10.0, "Times-Roman") == pytest.approx(8.34) # 278 x 3 + # Oblique faces share their upright advances. + for face in ("Helvetica", "Times"): + upright, slanted = { + "Helvetica": ("Helvetica", "Helvetica-Oblique"), + "Times": ("Times-Roman", "Times-Italic"), + }[face] + assert _text_width_px(b"W", 10.0, upright) == _text_width_px(b"W", 10.0, upright) + assert _text_width_px(b"Wm", 12.0, slanted) > 0 + # End-anchored y tick labels start elsewhere once the face changes width. + xs = np.linspace(0.0, 6.0, 50) + sans = xy.line_chart(xy.line(xs, np.sin(xs)), width=400, height=300).to_image("pdf") + mono = xy.line_chart( + xy.line(xs, np.sin(xs)), + width=400, + height=300, + styles={"tick_label": {"font-family": "monospace"}}, + ).to_image("pdf") + assert _tm_x_before(_content(sans), b"0.5") != _tm_x_before(_content(mono), b"0.5") + + +def test_unstyled_text_is_still_helvetica_alone_with_no_tc() -> None: + # The new attributes must be inert when nobody uses them: same fonts, no + # character-spacing operator, so existing documents keep their bytes. + pdf = _styled_pdf() + assert _base_fonts(pdf) == {b"Helvetica"} + assert b" Tc" not in _content(pdf) + + +def test_text_attribute_values_outside_the_subset_still_fail_loudly() -> None: + ns = 'xmlns="http://www.w3.org/2000/svg"' + with pytest.raises(ValueError, match="unsupported SVG feature: font-style"): + svg_to_pdf(f'x') + with pytest.raises(ValueError, match="unsupported SVG feature: letter-spacing"): + svg_to_pdf(f'x') diff --git a/tests/test_scatter.py b/tests/test_scatter.py index ec5b3f01c..5d9bc5bdd 100644 --- a/tests/test_scatter.py +++ b/tests/test_scatter.py @@ -360,8 +360,12 @@ def test_numeric_object_color_payload_is_continuous(): tr = spec["traces"][0] assert tr["color"]["mode"] == "continuous" assert tr["color"]["domain"] == [1.0, 3.0] + # None/NaN colour rows are not drawn (§19): they leave the shipped + # geometry and the channel buffer together, never painted as the floor. + assert tr["n_marks"] == 2 + np.testing.assert_array_equal(fig.traces[0].shipped_sel, [0, 2]) cbuf = _col(spec, blob, tr["color"]["buf"]) - np.testing.assert_allclose(cbuf, [0.0, 0.0, 1.0, 0.0]) + np.testing.assert_allclose(cbuf, [0.0, 1.0]) def test_numeric_object_size_payload_is_continuous(): @@ -372,8 +376,10 @@ def test_numeric_object_size_payload_is_continuous(): assert tr["size"]["mode"] == "continuous" assert tr["size"]["range_px"] == [2.0, 20.0] assert tr["size"]["domain"] == [1.0, 3.0] + assert tr["n_marks"] == 2 + np.testing.assert_array_equal(fig.traces[0].shipped_sel, [0, 2]) sbuf = _col(spec, blob, tr["size"]["buf"]) - np.testing.assert_allclose(sbuf, [0.0, 0.0, 1.0, 0.0]) + np.testing.assert_allclose(sbuf, [0.0, 1.0]) def test_variable_size_shipped(): From b3c996334e07271ed37697c1936c1cf9b968d09b Mon Sep 17 00:00:00 2001 From: Alek Petuskey Date: Tue, 1 Sep 2026 22:52:13 -0700 Subject: [PATCH 2/7] Add news fragment for the P1 audit fixes (#508) --- news/508.bugfix.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 news/508.bugfix.md diff --git a/news/508.bugfix.md b/news/508.bugfix.md new file mode 100644 index 000000000..b1fdf04bc --- /dev/null +++ b/news/508.bugfix.md @@ -0,0 +1,22 @@ +Twenty-one P1 defects from the 0.0.7 audit are fixed. Kernel: a non-string +message `type`, a pick past a histogram's bin count, and a subnormal-span +`density_view` window no longer raise inside the dispatcher, and `view_change` +records only finite, ordered, non-empty ranges. API: a log axis warns when it +drops non-positive points, non-finite continuous color/size values are not +drawn instead of painting as the colormap floor, `sankey_chart(xy.sankey(...))` +works, a hand-built `xy.Mark` fills in factory defaults instead of a KeyError, +bare pyarrow string arrays become categorical axes, and a missing facet column +is a ValueError. Client: a log axis zoomed inside one decade shows linear +fallback ticks instead of none (exports agree), and legend-hidden category +points no longer hover or show a tooltip. Exports: PDF honors `font-style`, +`font-family` (mapped to the base-14 faces), `letter-spacing`, and `opacity` +on text, and XML-illegal control characters are dropped so SVG and PDF never +emit unparsable documents. pyplot: `ticklabel_format` configures the +formatter instead of breaking export; spans and rules autoscale and take +`label=`; `series.plot(ax=)` works with pandas' locators; datetime limits, +ticks, and `fill_between` coordinates are accepted; `legend(handles=, +labels=)`, integer and tuple `loc`, `Line2D`/`Patch`/`Rectangle` legend proxies, +`plt.subplot(n, m, i)` creating only the requested cell, callable `plt.cm.*` +colormaps, `BarPatch` geometry getters, and a long list of common kwargs +(`zorder`, `clip_on`, `facecolors='none'`, `tick_label=`, `log=True`, ...) +are accepted. From 7ce900ac9906fd77633c968e7c5335dd162a05d0 Mon Sep 17 00:00:00 2001 From: Alek Petuskey Date: Tue, 1 Sep 2026 23:02:07 -0700 Subject: [PATCH 3/7] Fix CI: commit the regenerated capabilities doc, make pyarrow optional in tests, cheapen the channel finite probe - docs/styling/capabilities.md is generated from the capability registry and had been regenerated but not committed. - tests/test_api_p1_fixes.py imports pyarrow lazily via importorskip; the Python-floor job has no pyarrow. - _finite_sel probes each continuous channel with NumPy's isfinite().all() and hands only channels that actually hold a non-finite value to the native valid_indices_f64 scan; the unconditional native scan had cost the first-payload continuous-channel benchmark ~17%. --- docs/styling/capabilities.md | 16 ++++++++-------- python/xy/_payload.py | 17 ++++++++++------- tests/test_api_p1_fixes.py | 3 ++- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/docs/styling/capabilities.md b/docs/styling/capabilities.md index 88ad0b0d2..7531f5590 100644 --- a/docs/styling/capabilities.md +++ b/docs/styling/capabilities.md @@ -108,15 +108,15 @@ token bag or in mark and axis `style=`, which every renderer reads. ### Notes - **`root`** (via `chart style=`) — `styles={'root': ...}` is browser-only, but the chart-level `style=` token bag targets the same element and every renderer reads it (`spec['dom']['style']`). Prefer it for anything that must survive export. -- **`title`** (via `styles={'title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`title`** (via `styles={'title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. - **`legend`** (via `styles={'legend': ...} / xy.legend(style=...) / --chart-legend-bg`) — The frame box. Both spellings and the theme token now converge on one merged declaration block before the writers see it, so what agrees in the browser agrees in a PNG. `background`, `boxShadow`, `borderRadius`, `--xy-legend-frame-alpha`, and `padding`/`rowGap` in `em` are honored; an explicit background paints opaque, as it does in the browser. -- **`legend_title`** (via `styles={'legend_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`legend_label`** (via `styles={'legend_label': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`colorbar`** (via `styles={'colorbar': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`colorbar_tick`** (via `styles={'colorbar_tick': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`colorbar_title`** (via `styles={'colorbar_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`tick_label`** (via `styles={'tick_label': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. -- **`axis_title`** (via `styles={'axis_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`legend_title`** (via `styles={'legend_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`legend_label`** (via `styles={'legend_label': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`colorbar`** (via `styles={'colorbar': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`colorbar_tick`** (via `styles={'colorbar_tick': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`colorbar_title`** (via `styles={'colorbar_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`tick_label`** (via `styles={'tick_label': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. +- **`axis_title`** (via `styles={'axis_title': ...}`) — Vector (SVG, PDF) honors font-size, font-weight, font-style, font-family, letter-spacing, opacity and the text paint (`fill`, or `color`); PDF embeds no fonts, so font-family there selects a base-14 substitute (serif → Times, monospace → Courier, otherwise Helvetica; export.md §9 has the table). The raster writer's glyph primitive takes a size and one RGBA paint and nothing else, so it honors font-size and the paint only — font-weight, font-style, font-family, letter-spacing and opacity are vector-only rather than silently approximated. Properties outside the subset stay browser-only. ## Extension points diff --git a/python/xy/_payload.py b/python/xy/_payload.py index eba717d10..e822dc12d 100644 --- a/python/xy/_payload.py +++ b/python/xy/_payload.py @@ -505,12 +505,15 @@ def _finite_sel(t: Trace, xv: np.ndarray, yv: np.ndarray) -> np.ndarray | None: point used to draw in the domain-minimum color (+inf included). A mark whose color is undefined is not drawn — matplotlib's transparent "bad" color — and the same rows leave the pick/selection mapping, exactly as - an x/y NaN does. Channels carry no zone maps, so this is one - allocation-free native scan per continuous channel per build — the - same pass `_rect_finite_sel` already pays for the rectangle family; - `valid_indices_f64` allocates row ids only when a row is rejected. - Canonical keeps every row; real gap semantics (segment index list) - arrive with validity bitmaps. + an x/y NaN does. Channels carry no zone maps, so each continuous + channel is probed with NumPy's vectorized `isfinite().all()` — about + six times cheaper than the native multi-column scan on the all-finite + common case, which would otherwise cost this first-payload path ~17% + (CodSpeed `test_first_payload_scatter_continuous_channels`) — and only + a channel that actually holds a non-finite value joins the native + `valid_indices_f64` scan, which allocates row ids only for rejected + rows. Canonical keeps every row; real gap semantics (segment index + list) arrive with validity bitmaps. """ candidates = [values for col, values in ((t.x, xv), (t.y, yv)) if col.zone.null_count] for channel in (t.color_ch, t.size_ch): @@ -518,7 +521,7 @@ def _finite_sel(t: Trace, xv: np.ndarray, yv: np.ndarray) -> np.ndarray | None: continue # A streaming append can leave a channel momentarily shorter than # the geometry; never index geometry with a foreign-length mask. - if len(channel.values) == len(xv): + if len(channel.values) == len(xv) and not np.isfinite(channel.values).all(): candidates.append(channel.values) if not candidates: return None diff --git a/tests/test_api_p1_fixes.py b/tests/test_api_p1_fixes.py index 6571cfbd1..bd25bc208 100644 --- a/tests/test_api_p1_fixes.py +++ b/tests/test_api_p1_fixes.py @@ -11,13 +11,14 @@ import warnings import numpy as np -import pyarrow as pa import pytest import xy from xy import channels from xy.components import _MARK_APPLIERS +pa = pytest.importorskip("pyarrow") # the Python-floor CI job has no pyarrow + # -- 1. log axis drops non-positive rows loudly ------------------------------ From 76bb11154e27ef75feb0c819d5032890e1a40b51 Mon Sep 17 00:00:00 2001 From: Alek Petuskey Date: Tue, 1 Sep 2026 23:33:55 -0700 Subject: [PATCH 4/7] Address the review round on the P1 fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thirty-three review findings across two bots. Each was verified before being acted on; three turned out not to be valid and are answered with evidence rather than a change. Kernel: an out-of-range pick replies `pick_result` with a null row so the client clears its hover, instead of dropping the message; the pick bound is kind-aware, so a histogram with more bins than samples is fully pickable while errorbar keeps its advertised-count cap. Sweeping every message kind for the reported `float()` overflow found eight paths, not one — `view` bounds and `px`, `density_view` bounds and `w`, both `view_change` shapes, `select` and `select_polygon` — all fixed at the root in the window coercion helpers, with eleven oversized-integer messages added to the malformed corpus. Five of the six spans in the tiny-window test collapsed to zero at its base value, so it had been asserting nothing; re-anchored, with a spy asserting the guarded path is actually reached. API: the non-finite continuous colour/size exclusion now covers the whole density path — binning, the mean-colour plane, the sample overlay, the pyramid, and the padded drill window — not just the direct tier, and the rectangle family excludes non-finite size as well as colour. `_subset_data` uses the Arrow-aware materialization so a named Arrow column in a mapping subsets like a direct array; facet column lookup catches only the three table-lookup errors instead of bare `Exception`; `sankey_chart(node_width=…)` with no links names the extraneous keyword. Client: a subnormal log window ticks its endpoints instead of showing nothing. Two reported hover defects proved unreachable through the public API — `append_data` rejects the categorical colour channels that filtering requires, and no bar-emitting mark builds a categorical channel at all — so the dead guard is removed, the limit is recorded in the spec with what a user actually sees, and two tripwire tests fail the moment either premise becomes reachable. Exports: the font-width test compared a value with itself; it now pins the genuine slanted copies against their uprights and Times italics against their own AFM widths, all six tables checked against matplotlib's bundled files. The XML-illegal set is now proven equal to the XML 1.0 Char production over all code points, so the sampled cases are demonstrably representative. pyplot: ScalarFormatter clamps exponents so extreme axes format and export; datetime ticks pin the axis kind in either authoring order; `get_cmap` with a size resamples a qualitative palette like matplotlib; a colour-name list for `hlines` takes its first entry instead of crashing; hidden titles and labels really disappear; proxy markers follow their handle's visibility; the partial subplot grid records its dimensions for `tight_layout`. Tests: the pyarrow skip is scoped to the five tests that need it, so the other twenty-one guard the P1 fixes on the Python-floor job. --- js/src/30_ticks.ts | 10 +- js/src/50_chartview.ts | 31 ++- python/xy/_figure.py | 19 +- python/xy/_payload.py | 48 +++-- python/xy/_svg.py | 8 + python/xy/channel.py | 23 +- python/xy/channels.py | 54 ++++- python/xy/components.py | 11 +- python/xy/facets.py | 11 +- python/xy/interaction.py | 66 ++++-- python/xy/lod.py | 9 +- python/xy/pyplot/__init__.py | 2 +- python/xy/pyplot/_artists.py | 29 ++- python/xy/pyplot/_axes.py | 24 ++- python/xy/pyplot/_colors.py | 7 + python/xy/pyplot/_mplfig.py | 3 + python/xy/pyplot/_plot_types.py | 14 +- python/xy/pyplot/_ticker.py | 35 +++- python/xy/pyplot/_translate.py | 7 + spec/api/chart-kind-contract.md | 6 +- spec/api/interaction.md | 28 ++- spec/api/styling.md | 19 +- spec/design/renderer-architecture.md | 9 +- spec/design/wire-protocol.md | 28 ++- spec/matplotlib/compat-changelog.md | 11 +- spec/matplotlib/compat.md | 12 +- spec/matplotlib/shim-todo.md | 6 + .../56_partial_subplots_legend_proxies.py | 3 +- tests/pyplot/test_p1_axes_dates_spans.py | 64 ++++++ tests/pyplot/test_p1_kwargs_legend_subplot.py | 140 +++++++++++++ tests/test_api_p1_fixes.py | 197 ++++++++++++++++-- tests/test_channel_malformed_messages.py | 120 +++++++++-- tests/test_export_text_safety.py | 52 ++++- tests/test_legend_hidden_hover.py | 173 +++++++++++++++ tests/test_log_ticks_within_decade.py | 20 +- tests/test_pdf_export.py | 31 ++- 36 files changed, 1162 insertions(+), 168 deletions(-) diff --git a/js/src/30_ticks.ts b/js/src/30_ticks.ts index aaea88b7b..8876e5f18 100644 --- a/js/src/30_ticks.ts +++ b/js/src/30_ticks.ts @@ -49,7 +49,15 @@ export function logTicks(lo, hi, target = 6) { } if (decadesInView < 2) { const linear = linearTicks(a, b, target); - return { ticks: linear.ticks, labels: linear.ticks, step: linear.step, log: true }; + // A positive subnormal window (1e-323..1.5e-323) is a few ulps wide: + // `(b - a) / target` underflows to 0, niceStep answers 1, and the first + // multiple of that lies past `b` — no ticks again. The window's own + // endpoints are always representable, so they stand in as the ticks + // (the formatter is exponential there regardless of step). A degenerate + // lo === hi keeps linearTicks' single tick. + const ticks = linear.ticks.length < 2 && a < b ? [a, b] : linear.ticks; + const step = ticks === linear.ticks ? linear.step : b - a; + return { ticks, labels: ticks, step, log: true }; } const span = Math.max(1, e1 - e0); const mults = span <= Math.max(2, target) ? [1, 2, 5] : [1]; diff --git a/js/src/50_chartview.ts b/js/src/50_chartview.ts index 48949a920..287e0f0a3 100644 --- a/js/src/50_chartview.ts +++ b/js/src/50_chartview.ts @@ -8737,12 +8737,23 @@ export class ChartView { // How many retained rows a CPU hover scan covers. `g.n` is the DRAWN count, // which a category filter shrinks below the retained columns: capping the // scan at it left every visible row shipped after the cut unreachable while - // hidden rows before it still answered. `_fullN` is the pre-filter count - // `_filterScatterRows` records; an unfiltered trace keeps the `g.n` cap, - // which is load-bearing there (a smooth-resampled line's `n` exceeds its - // source columns; mismatched x/y lengths undershoot them). + // hidden rows before it still answered. A filtered trace is therefore scanned + // over exactly the rows `_visInv` carries visibility for (its length is the + // pre-filter count `_filterScatterRows` built it from) — deliberately that + // array and not a separately stored count, so the scan range and the + // hidden-row test can never disagree. An unfiltered trace keeps the `g.n` + // cap, which is load-bearing there (a smooth-resampled line's `n` exceeds + // its source columns; mismatched x/y lengths undershoot them). + // + // Growing the retained columns under a live filter would leave both stale, + // but cannot happen: `_filterScatterRows` runs only on a categorical color + // channel, and `append_data` (python/xy/interaction.py) rejects exactly + // those ("append does not support categorical color channels yet"), so a + // trace is appendable or category-filterable, never both. Whoever lifts that + // restriction must re-filter on append — `tests/test_legend_hidden_hover.py` + // fails here when they do. _cpuScanLimit(g, ...lengths) { - const n = g._fullN !== undefined ? g._fullN : g.n; + const n = g._visInv ? g._visInv.length : g.n; return Math.min(...lengths, n || lengths[0]); } @@ -8919,11 +8930,13 @@ export class ChartView { const cpu = g._cpu; const horizontal = g.orientation === 1; const geom = this._polarGeometry(); - const limit = this._cpuScanLimit(g, cpu.x.length, cpu.y.length); + // No hidden-row test here: a bar trace cannot carry a categorical color + // channel (only funnels and point series build one), so it never has + // category legend rows to toggle and never reaches `_filterScatterRows`. + // Bar legends are whole-trace rows, which `_hoverAt` skips via + // `_legendHidden` before it gets here. Recorded in interaction spec §10. + const limit = Math.min(cpu.x.length, cpu.y.length, g.n || cpu.x.length); for (let i = 0; i < limit; i++) { - // Categorical bars filter through `_filterScatterRows` too (§10), so a - // hidden bar's footprint must not answer hover either. - if (this._cpuRowHidden(g, i)) continue; const x = this._decodeValue(cpu.x, cpu.xMeta, i); const y = this._decodeValue(cpu.y, cpu.yMeta, i); const value0 = g.value0Mode === 1 && cpu.value0 diff --git a/python/xy/_figure.py b/python/xy/_figure.py index 61bffe32f..c93f35ce6 100644 --- a/python/xy/_figure.py +++ b/python/xy/_figure.py @@ -2013,17 +2013,14 @@ def _rect_finite_sel( for column, values in zip(geometry, (x0v, x1v, y0v, y1v), strict=True) if column is not None and column.zone.null_count ] - if t.color_ch and t.color_ch.mode == "continuous": - values = t.color_ch.values - if values is None: - raise ValueError(f"{t.kind} continuous color channel missing values") - candidates.append(values) - elif t.color_ch and t.color_ch.mode == "categorical": - codes = t.color_ch.codes - if codes is None: - raise ValueError(f"{t.kind} categorical color channel missing codes") - # Resolved categorical codes are u8/u32 and therefore always - # finite; no source-sized pass is needed for them. + # A rectangle whose continuous color or size is non-finite is not + # drawn either (§19) — the same rule, probe, and helper as the point + # tier's `_finite_sel`: the cached `isfinite().all()` verdict keeps + # the all-finite common case off the native scan, and a channel is a + # candidate only when it really holds a non-finite value. Resolved + # categorical codes are u8/u32 and therefore always finite; no + # source-sized pass is needed for them. + candidates.extend(channels.nonfinite_channel_arrays(t, len(x0v))) if not candidates: return None return kernels.valid_indices_f64(tuple(candidates)) diff --git a/python/xy/_payload.py b/python/xy/_payload.py index e822dc12d..960315f5c 100644 --- a/python/xy/_payload.py +++ b/python/xy/_payload.py @@ -506,23 +506,19 @@ def _finite_sel(t: Trace, xv: np.ndarray, yv: np.ndarray) -> np.ndarray | None: whose color is undefined is not drawn — matplotlib's transparent "bad" color — and the same rows leave the pick/selection mapping, exactly as an x/y NaN does. Channels carry no zone maps, so each continuous - channel is probed with NumPy's vectorized `isfinite().all()` — about + channel is probed once with NumPy's vectorized `isfinite().all()` + (cached on the channel, `channels.nonfinite_channel_arrays`) — about six times cheaper than the native multi-column scan on the all-finite common case, which would otherwise cost this first-payload path ~17% (CodSpeed `test_first_payload_scatter_continuous_channels`) — and only a channel that actually holds a non-finite value joins the native `valid_indices_f64` scan, which allocates row ids only for rejected - rows. Canonical keeps every row; real gap semantics (segment index - list) arrive with validity bitmaps. + rows. The density tier applies the same rule through + `channels.finite_channel_rows`. Canonical keeps every row; real gap + semantics (segment index list) arrive with validity bitmaps. """ candidates = [values for col, values in ((t.x, xv), (t.y, yv)) if col.zone.null_count] - for channel in (t.color_ch, t.size_ch): - if channel is None or channel.mode != "continuous" or channel.values is None: - continue - # A streaming append can leave a channel momentarily shorter than - # the geometry; never index geometry with a foreign-length mask. - if len(channel.values) == len(xv) and not np.isfinite(channel.values).all(): - candidates.append(channel.values) + candidates.extend(channels.nonfinite_channel_arrays(t, len(xv))) if not candidates: return None return kernels.valid_indices_f64(tuple(candidates)) @@ -1303,10 +1299,19 @@ def _density_trace_spec(self, t: Trace, xr, yr, w, h, pw: "_PayloadWriter") -> d # so every cell covers the same strip of *screen*. The wire keeps raw # `x_range`/`y_range` endpoints; renderers interpolate between their # scale coordinates. - bx, (bx0, bx1) = self._binning_coords(t.x_axis, t.x.values, xr) - by, (by0, by1) = self._binning_coords(t.y_axis, t.y.values, yr) + # Rows whose continuous color/size is non-finite are not drawn on any + # tier (§19): they leave the count grid, the mean-color plane, and the + # sample overlay here exactly as they leave the direct tier through + # `_finite_sel`. None on the common all-finite path (cached probe). + rows = channels.finite_channel_rows(t) + xs, ys = t.x.values, t.y.values + if rows is not None: + xs, ys = xs[rows], ys[rows] + bx, (bx0, bx1) = self._binning_coords(t.x_axis, xs, xr) + by, (by0, by1) = self._binning_coords(t.y_axis, ys, yr) full_identity = ( - (not categorical or compact_categorical) + rows is None + and (not categorical or compact_categorical) and not (t.x.zone.null_count or t.y.zone.null_count) and t.x.min >= xr[0] and t.x.max <= xr[1] @@ -1323,7 +1328,7 @@ def _density_trace_spec(self, t: Trace, xr, yr, w, h, pw: "_PayloadWriter") -> d visible = int(t.n_points) sel = np.empty(0, dtype=np.uint32) sample_sel = None - grid = kernels.bin_2d(t.x.values, t.y.values, xr[0], xr[1], yr[0], yr[1], w, h) + grid = kernels.bin_2d(xs, ys, xr[0], xr[1], yr[0], yr[1], w, h) elif full_identity and not pw.point_overlay: # Raster export: no overlay is drawn, so take the plain grid kernel # instead of the fused grid+sample variants below. `bin_2d` is the @@ -1380,6 +1385,10 @@ def _density_trace_spec(self, t: Trace, xr, yr, w, h, pw: "_PayloadWriter") -> d # Fused single pass: grid (bin_2d semantics) + visible rows # (range_indices semantics) without re-reading full columns twice. grid, sel = kernels.bin_2d_indices(bx, by, bx0, bx1, by0, by1, w, h) + if rows is not None: + # The fused kernel indexed the narrowed arrays; the sample + # overlay and pick bookkeeping speak canonical rows. + sel = rows[sel] visible = int(len(sel)) encoded_grid, gmax = kernels.density_log_u8(grid) # The density surface wears the data's own colors (LOD doc §2): count @@ -1394,8 +1403,15 @@ def _density_trace_spec(self, t: Trace, xr, yr, w, h, pw: "_PayloadWriter") -> d ) dropped_channels = list(t.per_item_channel_names()) # Cached full-column resolution (LOD doc §2): the O(N) quantize pass - # is shared with the pyramid build and every later grid reply. - bin_colors = interaction.trace_bin_colors(t) + # is shared with the pyramid build and every later grid reply. A trace + # with non-finite channel rows resolves over its finite rows instead, + # row-aligned with the narrowed `bx`/`by` (uncached, like a legend + # mask: the cache is full-column by definition). + bin_colors = ( + interaction.trace_bin_colors(t) + if rows is None + else channels.resolve_bin_colors(t.color_ch, rows) + ) density = { "buf": pw.ship_u8(encoded_grid), "w": w, diff --git a/python/xy/_svg.py b/python/xy/_svg.py index 5b158cfaa..8d7afbf4b 100644 --- a/python/xy/_svg.py +++ b/python/xy/_svg.py @@ -591,6 +591,14 @@ def _log_ticks(lo: float, hi: float, target: int = 6) -> tuple[list[float], list ) if decades_in_view < 2: ticks, step = _linear_ticks(a, b, target) + # A positive subnormal window (1e-323..1.5e-323) is a few ulps wide: + # `(b - a) / target` underflows to 0, `_nice_step` answers 1, and the + # first multiple of that lies past `b` — no ticks again. The window's + # own endpoints are always representable, so they stand in as the + # ticks (the formatter is exponential there regardless of step). A + # degenerate lo == hi keeps `_linear_ticks`' single tick. + if len(ticks) < 2 and a < b: + ticks, step = [a, b], b - a return ticks, ticks, step mults = (1, 2, 5) if max(1, e1 - e0) <= max(2, target) else (1,) label_every = max(1, int(np.ceil((e1 - e0 + 1) / max(1, target)))) diff --git a/python/xy/channel.py b/python/xy/channel.py index d4ed46a30..e0b0bbb99 100644 --- a/python/xy/channel.py +++ b/python/xy/channel.py @@ -236,7 +236,7 @@ def handle_message( x1, content.get("px", 2048), ) - except (KeyError, TypeError, ValueError): + except (KeyError, TypeError, ValueError, OverflowError): return None if update["traces"]: return {"type": "tier_update", "seq": seq, **update}, out @@ -254,7 +254,7 @@ def handle_message( content.get("w", 512), content.get("h", 384), ) - except (KeyError, TypeError, ValueError, IndexError): + except (KeyError, TypeError, ValueError, IndexError, OverflowError): return None if update["traces"]: return {"type": "density_update", "seq": seq, **update}, out @@ -273,7 +273,7 @@ def handle_message( hidden, content.get("category"), ) - except (KeyError, TypeError, ValueError, IndexError): + except (KeyError, TypeError, ValueError, IndexError, OverflowError): return None return None if kind == "pick": @@ -289,11 +289,14 @@ def handle_message( index, drill_seq, ) - except (TypeError, ValueError, IndexError): - # IndexError is defense in depth: `pick` bounds the index against - # the readable rows, but a kind whose columns disagree with its - # advertised count must degrade to `row: null`, never raise. + except (TypeError, ValueError): return None + except IndexError: + # Defense in depth: `pick` bounds the index against the readable + # rows, but a kind whose columns disagree with that bound must + # degrade to `row: null`, never raise — and it must still reply, + # or the client keeps showing the previous hover row. + row = None if row is not None and callbacks.on_hover is not None: callbacks.on_hover(row) # Reply ships even when row is None (stale drill_seq): the client @@ -361,7 +364,7 @@ def handle_message( view.update({"x0": x_range[0], "x1": x_range[1]}) if y_range is not None: view.update({"y0": y_range[0], "y1": y_range[1]}) - except (KeyError, TypeError, ValueError): + except (KeyError, TypeError, ValueError, OverflowError): return None # Every committed view event feeds the figure's durable-state cache # (view-state.md §5.1) — the reason end-phase events always ship — @@ -388,7 +391,7 @@ def handle_message( y0, y1, ) - except (KeyError, TypeError, ValueError): + except (KeyError, TypeError, ValueError, OverflowError): return None fig._record_selection({"range": {"x0": x0, "x1": x1, "y0": y0, "y1": y1}}) return _selection_reply( @@ -405,7 +408,7 @@ def handle_message( points = content["points"] sel = fig.select_polygon(points) polygon = [[float(point[0]), float(point[1])] for point in points] - except (IndexError, KeyError, TypeError, ValueError): + except (IndexError, KeyError, TypeError, ValueError, OverflowError): return None fig._record_selection({"polygon": polygon}) return _selection_reply( diff --git a/python/xy/channels.py b/python/xy/channels.py index c9564f680..00b67c54e 100644 --- a/python/xy/channels.py +++ b/python/xy/channels.py @@ -182,6 +182,12 @@ class ColorChannel: _buffer: Optional[npt.NDArray[np.float64]] = field( default=None, init=False, repr=False, compare=False ) + # Cached "every value is finite" verdict, None until probed. Rows with a + # non-finite continuous value are not drawn (§19), so every emitter — the + # direct tier, the density grid/sample/mean-color path, the drill — asks; + # the probe is an O(N) `isfinite().all()` over an immutable column and must + # not repeat per request (`nonfinite_channel_arrays`). Reset on append. + _all_finite: Optional[bool] = field(default=None, init=False, repr=False, compare=False) @property def colors(self) -> list[str]: @@ -237,10 +243,11 @@ class SizeChannel: values: Optional[npt.NDArray[np.float64]] = None domain: Optional[tuple[float, float]] = None range_px: tuple[float, float] = (2.0, 18.0) - # See ColorChannel._buffer. + # See ColorChannel._buffer / ColorChannel._all_finite. _buffer: Optional[npt.NDArray[np.float64]] = field( default=None, init=False, repr=False, compare=False ) + _all_finite: Optional[bool] = field(default=None, init=False, repr=False, compare=False) def spec(self) -> dict[str, Any]: """The channel's resolved settings as a plain dict, exactly as @@ -531,6 +538,7 @@ def append_continuous(channel: Any, values: npt.NDArray[np.float64], label: str) buffer[:n_old] = current buffer[n_old:n_new] = tail channel.values = buffer[:n_new] + channel._all_finite = None # the tail may have introduced (or not) a non-finite value finite = tail[np.isfinite(tail)] if len(finite): @@ -538,6 +546,50 @@ def append_continuous(channel: Any, values: npt.NDArray[np.float64], label: str) channel.domain = (min(lo, float(finite.min())), max(hi, float(finite.max()))) +def nonfinite_channel_arrays(trace: Any, n: int) -> list[np.ndarray]: + """The continuous color/size arrays of `trace` (of length `n`) that hold + at least one non-finite value — the arrays an emitter must feed to + `kernels.valid_indices_f64` to find the rows it may not draw (§19). + + The per-channel verdict is cached on the channel (`_all_finite`), so the + common all-finite case costs one vectorized `isfinite().all()` per channel + per trace lifetime rather than per payload or per density request; the + native multi-column scan (about six times dearer on the all-finite path, + CodSpeed `test_first_payload_scatter_continuous_channels`) runs only on a + channel that really needs it. A channel whose length differs from `n` is + skipped: a streaming append can leave it momentarily shorter than the + geometry, and geometry must never be indexed with a foreign-length mask. + """ + arrays: list[np.ndarray] = [] + for channel in (trace.color_ch, trace.size_ch): + if channel is None or channel.mode != "continuous" or channel.values is None: + continue + values = channel.values + if len(values) != n: + continue + if channel._all_finite is None: + channel._all_finite = bool(np.isfinite(values).all()) + if not channel._all_finite: + arrays.append(values) + return arrays + + +def finite_channel_rows(trace: Any) -> Optional[np.ndarray]: + """Canonical row ids whose continuous color/size values are all finite, + or None when every row qualifies (the common case, answered from the + cached probe without touching the columns). + + The density tier's visible-row space: the count grid, the mean-color + plane, the sample overlay, the pyramid, and drill selections all narrow + to these rows so a point with an undefined color or size is not drawn at + any zoom level — the same exclusion the direct tier applies per row. + """ + arrays = nonfinite_channel_arrays(trace, trace.n_points) + if not arrays: + return None + return kernels.valid_indices_f64(tuple(arrays)) + + def resolve_color( color: Any, n: int, diff --git a/python/xy/components.py b/python/xy/components.py index c715b1b56..dcdb0fdf6 100644 --- a/python/xy/components.py +++ b/python/xy/components.py @@ -7222,8 +7222,15 @@ def sankey_chart( lead = () else: # `sankey_chart()` keeps its historical shape: an empty diagram that - # the layout refuses by name at figure build. - lead = (sankey(links, **mark_kwargs),) + # the layout refuses by name at figure build. Sankey keywords without + # links are refused here too, by name — otherwise the generic + # empty-links error at build would never mention the stray keyword. + if mark_kwargs: + raise ValueError( + f"sankey_chart got {sorted(mark_kwargs)} without links; pass the " + "links positionally or set these options on an xy.sankey(...) child" + ) + lead = (sankey(links),) children = ( *lead, x_axis(domain=(-0.09, 1.09), show=False), diff --git a/python/xy/facets.py b/python/xy/facets.py index 8fffae923..db6f4f8a3 100644 --- a/python/xy/facets.py +++ b/python/xy/facets.py @@ -35,7 +35,11 @@ def _subset_data(data: Any, mask: np.ndarray, n: int) -> Any: out: dict[Any, Any] = {} for key, value in data.items(): if hasattr(value, "to_numpy"): - arr = value.to_numpy() + # Arrow-aware: a pyarrow string/dictionary/chunked column + # refuses the default zero-copy `to_numpy()`; the facet key + # column itself comes through here after `_facet_values` + # already materialized it (`columns.label_ndarray`). + arr = columns.label_ndarray(value) elif isinstance(value, np.ndarray): arr = value elif isinstance(value, (list, tuple)): @@ -93,9 +97,12 @@ def _facet_values(data: Any, by: Any) -> tuple[np.ndarray, list[str]]: raise ValueError(f"facet column {by!r} not found in data") raw = data[by] elif hasattr(data, "__getitem__"): + # Only the lookup contract's own failures mean "no such column" + # (the same trio `components._resolve` normalizes); a backend + # error inside `__getitem__` is a real error and propagates. try: raw = data[by] - except Exception as exc: + except (KeyError, TypeError, IndexError) as exc: raise ValueError(f"facet column {by!r} not found in data") from exc else: raise TypeError("facet_chart by= as a string requires mapping/table data") diff --git a/python/xy/interaction.py b/python/xy/interaction.py index 7690d78df..a7cd87170 100644 --- a/python/xy/interaction.py +++ b/python/xy/interaction.py @@ -172,20 +172,26 @@ def legend_toggle( t._legend_vis_cache = None +# Kinds whose readout rows are bins, not samples: `n_points` there is the +# sample count, which can be larger (1000 samples over 27 bars) or smaller +# (5 samples over 20 bars) than the row count, so it bounds nothing. +_BINNED_ROW_KINDS = frozenset({"histogram", "hexbin"}) + + def _pick_row_count(t: "Trace") -> int: - """Rows a pick may read: the readout columns' length, capped by `n_points`. - - `n_points` is the mark count the wire advertises, and for aggregate kinds - it is not the length of the columns `row_dict` indexes — a histogram or - hexbin advertises its sample count over a few dozen bin rows, an errorbar - its points over three segment endpoints each. An index must name both an - advertised mark and a readable row (§16: exact or nothing), so the bound - is the smaller of the two. Grid marks keep only the outer edges in x/y; - their readable rows are the cells. + """Rows a pick may read (§16: exact or nothing, so never past a column). + + Binned aggregates are bounded by their bin rows and grid marks by their + cells (x/y hold only the outer edges there). Every other kind must name + both an advertised mark and a readable row: an errorbar advertises its + points over three segment endpoints each, so the bound is the smaller of + `n_points` and the column length. """ if t.grid_shape is not None: rows, cols = t.grid_shape - return min(t.n_points, rows * cols) + return rows * cols + if t.kind in _BINNED_ROW_KINDS: + return len(t.x) return min(t.n_points, len(t.x)) @@ -648,13 +654,20 @@ def _ensure_pyramid(t: Trace) -> int | None: x1 += (x1 - x0) * 1e-9 y1 += (y1 - y0) * 1e-9 base_dim = _pyramid_base_dim_for(t) - bin_colors = trace_bin_colors(t) + # Rows whose continuous color/size is non-finite are not drawn (§19), so + # they are not counted or averaged here either; the pyramid then stays + # valid for every view of such a trace (only the legend mask bypasses it). + rows = channels.finite_channel_rows(t) + if rows is None: + xs, ys = t.x.values, t.y.values + bin_colors = trace_bin_colors(t) + else: + xs, ys = t.x.values[rows], t.y.values[rows] + bin_colors = channels.resolve_bin_colors(t.color_ch, rows) if bin_colors is not None: - handle = kernels.pyramid_build_color( - t.x.values, t.y.values, x0, x1, y0, y1, base_dim, **bin_colors - ) + handle = kernels.pyramid_build_color(xs, ys, x0, x1, y0, y1, base_dim, **bin_colors) else: - handle = kernels.pyramid_build(t.x.values, t.y.values, x0, x1, y0, y1, base_dim) + handle = kernels.pyramid_build(xs, ys, x0, x1, y0, y1, base_dim) t._pyr_handle = handle t._pyr_base_dim = base_dim t._pyr_colored = bool(handle) and bin_colors is not None @@ -919,7 +932,18 @@ def density_view( # any aggregation. Everything downstream — counts, tier decisions, grids, # drill selections — then runs in visible-row space; drill selections are # translated back to canonical via `vis_rows` before they ship or persist. - vis_rows = _legend_visible_rows(t) + legend_rows = _legend_visible_rows(t) + # Rows whose continuous color/size is non-finite are not drawn (§19) and + # join the same visible-row space, so counts, mean colors, and drill + # selections all skip them; None on the common all-finite path. Only the + # legend mask disables the pyramid below — it is built over finite rows. + finite_rows = channels.finite_channel_rows(t) + if finite_rows is None: + vis_rows = legend_rows + elif legend_rows is None: + vis_rows = finite_rows + else: + vis_rows = np.intersect1d(legend_rows, finite_rows, assume_unique=True) if vis_rows is not None: xv, yv = xv[vis_rows], yv[vis_rows] # Nonlinear axes aggregate in scale coordinates (§28) so grid cells are @@ -963,7 +987,7 @@ def density_view( # the pyramid holds UNFILTERED counts, and §34's whole point is that a # static aggregate is wrong under any dynamic predicate — the masked view # takes the honest Tier-B re-bin below, recorded via the binning label. - pyr = None if (nonlinear or vis_rows is not None) else _ensure_pyramid(t) + pyr = None if (nonlinear or legend_rows is not None) else _ensure_pyramid(t) if pyr is not None: est = kernels.pyramid_count(pyr, lo_x, hi_x, lo_y, hi_y) # Serve from the pyramid when the window is clearly aggregate territory, @@ -1091,10 +1115,14 @@ def density_view( if padded is not None: lo_x, hi_x, lo_y, hi_y, sel = padded sel = _drop_hidden_rows(t, sel) + if finite_rows is not None: + # The padded window was re-selected from canonical rows; + # drop the undrawable ones the way the view rows did. + sel = np.intersect1d(sel, finite_rows, assume_unique=True) reply, reply_buffers = _drill_points( fig, t, sel, len(sel), lo_x, hi_x, lo_y, hi_y, w, h, blend_visible=visible ) - if vis_rows is not None: + if legend_rows is not None: reply["traces"][0]["filter"] = _legend_filter_spec(t) return reply, reply_buffers @@ -1143,7 +1171,7 @@ def density_view( "tier": plan.tier, "visible": visible, "reduction": plan.reduction, - "binning": binning if vis_rows is None else binning + "-masked", + "binning": binning if legend_rows is None else binning + "-masked", "density": density, } if vis_rows is not None: diff --git a/python/xy/lod.py b/python/xy/lod.py index 862160712..7e1b4bc47 100644 --- a/python/xy/lod.py +++ b/python/xy/lod.py @@ -150,7 +150,10 @@ def normalize_window( raise ValueError("view window bounds must be finite") try: vals = [float(v) for v in (x0, x1, y0, y1)] - except (TypeError, ValueError) as e: + except (TypeError, ValueError, OverflowError) as e: + # OverflowError is the oversized-integer case: a JSON literal with more + # digits than f64 can hold is client data like any other, so it must + # reject rather than escape the dispatcher. raise ValueError("view window bounds must be finite") from e if not all(np.isfinite(vals)): raise ValueError("view window bounds must be finite") @@ -177,7 +180,7 @@ def screen_shape(w: int, h: int) -> tuple[int, int]: try: wf = float(w) hf = float(h) - except (TypeError, ValueError) as e: + except (TypeError, ValueError, OverflowError) as e: raise ValueError("screen dimensions must be finite") from e if not np.isfinite(wf) or not np.isfinite(hf): raise ValueError("screen dimensions must be finite") @@ -277,7 +280,7 @@ def _float_param( raise ValueError(f"{label} must be finite") try: out = float(cast(Any, value)) - except (TypeError, ValueError) as exc: + except (TypeError, ValueError, OverflowError) as exc: raise ValueError(f"{label} must be finite") from exc if not np.isfinite(out): raise ValueError(f"{label} must be finite") diff --git a/python/xy/pyplot/__init__.py b/python/xy/pyplot/__init__.py index e3478bc78..8811ebfa5 100644 --- a/python/xy/pyplot/__init__.py +++ b/python/xy/pyplot/__init__.py @@ -2788,7 +2788,7 @@ def get_cmap(name: Any = None, lut: int | None = None) -> Any: return name.resampled(int(lut)) if hasattr(name, "resampled") else name listed = qualitative_colormap(name) if listed is not None: - return listed if lut is None else ListedColormap(listed.colors, listed.name, N=int(lut)) + return listed if lut is None else listed.resampled(int(lut)) cmap = Cmap("viridis" if name is None else name) return cmap if lut is None else cmap.resampled(int(lut)) diff --git a/python/xy/pyplot/_artists.py b/python/xy/pyplot/_artists.py index 4d64e15a4..c474475d9 100644 --- a/python/xy/pyplot/_artists.py +++ b/python/xy/pyplot/_artists.py @@ -332,8 +332,8 @@ def set_markersize(self, size: Any) -> None: def _line_proxy_entries( xdata: Any, ydata: Any, kwargs: dict[str, Any] -) -> tuple[dict[str, Any], Optional[dict[str, Any]]]: - """Spec entries for a Matplotlib-style ``Line2D(xdata, ydata, **style)`` proxy. +) -> tuple[dict[str, Any], Optional[dict[str, Any]], bool]: + """Spec entries plus the ``visible`` flag for a ``Line2D(xdata, ydata, **style)`` proxy. The proxy never renders; ``legend(handles=...)`` freezes it into a swatch through the same ``_legend_item_from_entry`` path plotted lines use, so @@ -342,7 +342,7 @@ def _line_proxy_entries( when the legend attaches. """ kwargs = dict(kwargs) - strip_artist_noops(kwargs) + visible = strip_artist_noops(kwargs) marker = kwargs.pop("marker", None) markersize = kwargs.pop("markersize", kwargs.pop("ms", None)) markerfacecolor = kwargs.pop("markerfacecolor", kwargs.pop("mfc", None)) @@ -392,8 +392,9 @@ def _line_proxy_entries( # Marker-only proxy (``linestyle="none", marker="o"``): the swatch is # the marker itself, exactly as a marker-only ``plot`` is a scatter. marker_entry["kwargs"]["name"] = line_kw.get("name") - return marker_entry, None - return {"kind": "line", "x": xdata, "y": ydata, "kwargs": line_kw, "_proxy": True}, marker_entry + return marker_entry, None, visible + line_entry = {"kind": "line", "x": xdata, "y": ydata, "kwargs": line_kw, "_proxy": True} + return line_entry, marker_entry, visible class Line2D(Artist): @@ -412,8 +413,16 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: return if len(args) != 2: raise TypeError("Line2D(xdata, ydata, **style) requires x and y data") - entry, self._proxy_marker_entry = _line_proxy_entries(args[0], args[1], kwargs) + entry, self._proxy_marker_entry, visible = _line_proxy_entries(args[0], args[1], kwargs) super().__init__(None, entry) + if not visible: + self.set_visible(False) + + def _companion_entries(self) -> list[dict[str, Any]]: + # The marker overlay of ``plot(..., marker=)`` (or a proxy's marker) is + # part of the same Matplotlib Line2D: visibility, alpha, and transform + # mutations must move it too, not only the line. + return [entry for entry in self._marker_entries() if entry is not self._entry] @staticmethod def _segment_args_from_xy(x: Any, y: Any) -> tuple[Any, Any, Any, Any]: @@ -1144,8 +1153,11 @@ def __init__( entry = _patch_proxy_entry(style, "Patch()") elif style: raise TypeError(f"Patch() got unexpected keyword argument {next(iter(style))!r}") + visible = bool(entry.pop("_proxy_visible", True)) super().__init__(axes, entry) self._outline_entries = list(outline_entries or []) + if not visible: + self.set_visible(False) def _companion_entries(self) -> list[dict[str, Any]]: return self._outline_entries @@ -1183,7 +1195,7 @@ def set_zorder(self, level: float) -> None: def _patch_proxy_entry(style: dict[str, Any], where: str) -> dict[str, Any]: """Spec entry for a ``Patch``/``Rectangle`` legend proxy, in bar-swatch shape.""" kwargs = dict(style) - strip_artist_noops(kwargs) + visible = strip_artist_noops(kwargs) color = kwargs.pop("color", None) facecolor = kwargs.pop("facecolor", kwargs.pop("fc", None)) edgecolor = kwargs.pop("edgecolor", kwargs.pop("ec", None)) @@ -1222,7 +1234,8 @@ def paint(value: Any, default: Any) -> Optional[str]: ) if hatch: entry_kwargs["hatch"] = str(hatch) - return {"kind": "bar", "kwargs": entry_kwargs, "_proxy": True} + # Consumed by Patch.__init__, which owns the handle that can be hidden. + return {"kind": "bar", "kwargs": entry_kwargs, "_proxy": True, "_proxy_visible": visible} class Rectangle(Patch): diff --git a/python/xy/pyplot/_axes.py b/python/xy/pyplot/_axes.py index 5aa695f4b..c3d6c63c9 100644 --- a/python/xy/pyplot/_axes.py +++ b/python/xy/pyplot/_axes.py @@ -4069,7 +4069,9 @@ def set_xlabel(self, label: str, **kwargs: Any) -> None: else raises loudly. Basic mathtext (``$...$``) is rendered. """ props = self._axis_props("x") - props["label"] = _plain_text(label) + # visible=False: Matplotlib keeps the hidden Text; the shim's chrome + # has no hidden state, so the label is simply not written. + props["label"] = _plain_text(label) if kwargs.pop("visible", True) else "" _apply_axis_label_kwargs(props, kwargs, "set_xlabel()", point_scale=self._point_scale()) self._invalidate() @@ -4079,7 +4081,7 @@ def set_ylabel(self, label: str, **kwargs: Any) -> None: ``loc`` takes ``"bottom"``/``"center"``/``"top"`` for this axis. """ props = self._axis_props("y") - props["label"] = _plain_text(label) + props["label"] = _plain_text(label) if kwargs.pop("visible", True) else "" _apply_axis_label_kwargs(props, kwargs, "set_ylabel()", point_scale=self._point_scale()) self._invalidate() @@ -4091,6 +4093,8 @@ def set_title(self, title: str, **kwargs: Any) -> None: Basic mathtext (``$...$``) is rendered. """ host = self._y2_of or self + if not kwargs.pop("visible", True): + title = "" # hidden title: the chrome slot is cleared (see set_xlabel) loc = str(kwargs.pop("loc", rcParams["axes.titlelocation"])).lower() if loc not in {"left", "center", "right"}: raise ValueError("set_title() loc must be 'left', 'center', or 'right'") @@ -4446,6 +4450,18 @@ def _data_coordinates(self, xy: tuple) -> Optional[tuple[float, float]]: y = self._data_coordinate(xy[1], "y") return None if x is None or y is None else (x, y) + def _tick_positions(self, ticks: Any, axis: str, props: dict[str, Any]) -> Any: + """Tick positions as engine floats; datetime-likes become ms since + epoch and pin the axis kind to ``time`` (as `fill_betweenx` does), so + ticks authored before any datetime artist still label as dates.""" + from xy.components import _is_datetime_like + + if _is_datetime_like(ticks): + props["type_"] = "time" + self._axis_props(axis)["type_"] = "time" + return unit_converted_values(ticks) + return ticks + def _limit_coordinate(self, value: Any, axis: str) -> float: """A limit argument as the engine's float: numbers as they are, datetime-likes (``datetime``, ``date``, ``datetime64``, ``Timestamp``, @@ -6726,7 +6742,7 @@ def set_xticks( props = host._axis["x"] if ticks is not None: spec = host._scale_specs["x"] - ticks = unit_converted_values(ticks) # datetime-likes → ms since epoch + ticks = self._tick_positions(ticks, "x", props) host._auto_scale_axis_ticks.discard("x") host._tickers.pop(("x", "major_locator"), None) props["tick_values"] = list(map(float, _scale_values(ticks, spec))) @@ -6768,7 +6784,7 @@ def set_yticks( props = host._axis[key] if ticks is not None: spec = host._scale_specs[key] - ticks = unit_converted_values(ticks) # datetime-likes → ms since epoch + ticks = self._tick_positions(ticks, "y", props) host._auto_scale_axis_ticks.discard(key) host._tickers.pop((key, "major_locator"), None) props["tick_values"] = list(map(float, _scale_values(ticks, spec))) diff --git a/python/xy/pyplot/_colors.py b/python/xy/pyplot/_colors.py index 24bd449a6..cf75e25ee 100644 --- a/python/xy/pyplot/_colors.py +++ b/python/xy/pyplot/_colors.py @@ -205,6 +205,13 @@ def __init__(self, colors: object, name: str = "listed", N: int | None = None) - self.name = str(name) self.N = len(table) + def resampled(self, lutsize: int) -> "ListedColormap": + """Matplotlib's ``ListedColormap.resampled``: sample the palette at + ``lutsize`` evenly spaced positions (``get_cmap("tab10", 4)`` picks + entries 0, 3, 6, 9; more entries than the palette holds repeat ends).""" + count = max(1, int(lutsize)) + return ListedColormap(self(np.linspace(0.0, 1.0, count)), name=self.name) + def __call__(self, values: object) -> object: array = np.asarray(values) if np.issubdtype(array.dtype, np.integer): diff --git a/python/xy/pyplot/_mplfig.py b/python/xy/pyplot/_mplfig.py index 6c554a118..d80a0d90c 100644 --- a/python/xy/pyplot/_mplfig.py +++ b/python/xy/pyplot/_mplfig.py @@ -391,6 +391,9 @@ def add_subplot(self, *args: Any, **kwargs: Any) -> Axes: grid = _GridSpec(self, nrows, ncols) rect = grid.cell_rect((row, row + 1), (col, col + 1)) ax = self.add_axes(rect) + # add_axes() models free-form panels as a 1×N row; record the + # requested grid so tight_layout & co. size chrome for it. + self._nrows, self._ncols = nrows, ncols ax._subplot_spec = _SubplotSpec(grid, (row, row + 1), (col, col + 1)) ax._subplot_key = subplot_key ax._subplot_claimed = True diff --git a/python/xy/pyplot/_plot_types.py b/python/xy/pyplot/_plot_types.py index 76dd3ff66..f424cd032 100644 --- a/python/xy/pyplot/_plot_types.py +++ b/python/xy/pyplot/_plot_types.py @@ -415,6 +415,13 @@ def _native_streamline_trajectories( _LINESTYLE_TO_FMT_TOKEN = {"solid": "-", "dashed": "--", "dashdot": "-.", "dotted": ":"} +def _is_rgba_channels(value: Any) -> bool: + """True for one numeric RGB(A) tuple; false for a sequence of color names.""" + return len(value) in (3, 4) and all( + np.isscalar(item) and not isinstance(item, (str, bytes)) for item in value + ) + + def _dash_segment_pattern(where: str, linestyle: Any) -> Optional[tuple[tuple[float, float], ...]]: """Dash pattern for a linestyle token or name; None means solid.""" if linestyle is None: @@ -1393,8 +1400,9 @@ def hlines( and not isinstance(chosen_color, str) and len(chosen_color) # A single RGB(A) tuple (``colors=plt.cm.tab10(3)``) is one color, - # not a per-line sequence, exactly as ``vlines`` reads it. - and not (len(chosen_color) in (3, 4) and all(np.isscalar(v) for v in chosen_color)) + # not a per-line sequence, exactly as ``vlines`` reads it. Strings + # are numpy scalars too, so a 3- or 4-name list must be excluded. + and not _is_rgba_channels(chosen_color) ): chosen_color = chosen_color[0] entry = self._add( @@ -1455,7 +1463,7 @@ def _vlines_entry( color is not None and not isinstance(color, str) and len(color) - and not (len(color) in (3, 4) and all(np.isscalar(value) for value in color)) + and not _is_rgba_channels(color) ): color = color[0] transform = kwargs.pop("transform", None) diff --git a/python/xy/pyplot/_ticker.py b/python/xy/pyplot/_ticker.py index 7b74d055c..520980388 100644 --- a/python/xy/pyplot/_ticker.py +++ b/python/xy/pyplot/_ticker.py @@ -551,31 +551,48 @@ def format_ticks(self, values: Any) -> list[str]: self.set_locs(ticks) return [self(float(value), position) for position, value in enumerate(ticks)] + # Exponents are clamped so every ``10.0 ** n`` below stays a finite double + # (``10.0 ** 309`` raises OverflowError, ``10.0 ** -324`` underflows to 0). + _EXPONENT_LIMIT = 300 + # ``np.round(x, decimals)`` scales by ``10 ** decimals`` internally, and a + # double carries ~16 significant digits, so longer labels are pure noise. + _MAX_DECIMALS = 20 + + @classmethod + def _bounded_exponent(cls, exponent: float) -> int: + return int(max(-cls._EXPONENT_LIMIT, min(cls._EXPONENT_LIMIT, exponent))) + def _order_of_magnitude(self, locs: np.ndarray) -> int: finite = locs[np.isfinite(locs)] if not self._scientific or finite.size == 0 or not np.any(finite): return 0 - oom = int(math.floor(math.log10(float(np.max(np.abs(finite[finite != 0])))))) + oom = self._bounded_exponent( + math.floor(math.log10(float(np.max(np.abs(finite[finite != 0]))))) + ) low, high = self._powerlimits if low == high != 0: # fixed exponent, as matplotlib - return low + return self._bounded_exponent(low) return oom if (oom <= low or oom >= high) else 0 - def _decimals(self, locs: np.ndarray, oom: int) -> int: + def _decimals(self, locs: np.ndarray, oom: int) -> Optional[int]: # Port of matplotlib ScalarFormatter._set_format over the located # ticks (no view-interval fallback: the Axes hands us the full set). + # None: the ticks need more decimals than a double can carry, so the + # caller falls back to ``%g`` instead of printing value-less zeros. finite = locs[np.isfinite(locs)] if finite.size == 0: return 0 - scaled = finite / 10.0**oom + scaled = finite * 10.0 ** (-oom) # multiply: never raises, unlike ``/ 10.0**oom`` loc_range = float(np.ptp(scaled)) if scaled.size > 1 else 0.0 if loc_range == 0: loc_range = float(np.max(np.abs(scaled))) - if loc_range == 0: + if loc_range == 0 or not math.isfinite(loc_range): loc_range = 1.0 - loc_range_oom = int(math.floor(math.log10(loc_range))) + loc_range_oom = self._bounded_exponent(math.floor(math.log10(loc_range))) sigfigs = max(0, 3 - loc_range_oom) - thresh = 1e-3 * 10**loc_range_oom + if sigfigs > self._MAX_DECIMALS: + return None + thresh = 10.0 ** (loc_range_oom - 3) while sigfigs >= 0: if np.abs(scaled - np.round(scaled, decimals=sigfigs)).max() < thresh: sigfigs -= 1 @@ -590,7 +607,9 @@ def __call__(self, value: float, pos: Optional[int] = None) -> str: locs = self._locs if self._locs.size else np.asarray([float(value)]) oom = self._order_of_magnitude(locs) decimals = self._decimals(locs, oom) - mantissa = f"{float(value) / 10.0**oom:.{decimals}f}" + if decimals is None: + return f"{float(value):g}" + mantissa = f"{float(value) * 10.0 ** (-oom):.{decimals}f}" if oom == 0: return mantissa if self._use_math_text: diff --git a/python/xy/pyplot/_translate.py b/python/xy/pyplot/_translate.py index e5c29da13..c26468af6 100644 --- a/python/xy/pyplot/_translate.py +++ b/python/xy/pyplot/_translate.py @@ -249,6 +249,11 @@ def marker_size_to_scatter_size( "pcolorfast": frozenset({"rasterized"}), "imshow": frozenset({"clip_on"}), "matshow": frozenset({"clip_on"}), + # Chrome setters return no artist to hide, so they apply ``visible`` + # to the stored title/label state themselves. + "set_title": frozenset({"visible"}), + "set_xlabel": frozenset({"visible"}), + "set_ylabel": frozenset({"visible"}), } @@ -262,6 +267,8 @@ def strip_artist_noops(kwargs: dict[str, Any], keep: frozenset[str] = frozenset( for name in ARTIST_NOOP_KWARGS: if name in kwargs and name not in keep: kwargs.pop(name) # compat-noop: no engine equivalent (see ARTIST_NOOP_KWARGS) + if "visible" in keep: + return True # the method applies ``visible`` to its own state visible = kwargs.pop("visible", True) return True if visible is None else bool(visible) diff --git a/spec/api/chart-kind-contract.md b/spec/api/chart-kind-contract.md index ec6d9ff0b..51a24d123 100644 --- a/spec/api/chart-kind-contract.md +++ b/spec/api/chart-kind-contract.md @@ -61,7 +61,11 @@ by the string `K` on the wire (`trace.kind`). and polylines) and `_rect_finite_sel` (rectangles) both reject rows whose continuous color/size value is non-finite, alongside x/y NaN (§19), so a mark with an undefined color is not drawn rather than painted at the ramp - floor. A kernel that builds its own selection must apply that rule too. + floor; the density tier (grid, mean-color plane, sample overlay, pyramid, + drill) narrows to `channels.finite_channel_rows(t)` for the same reason. A + kernel that builds its own selection must apply that rule too — take the + candidate arrays from `channels.nonfinite_channel_arrays(t, n)`, whose + per-channel finite verdict is cached so the all-finite case never rescans. #### The ribbon geometry contract diff --git a/spec/api/interaction.md b/spec/api/interaction.md index 9550b8f73..e5265b61c 100644 --- a/spec/api/interaction.md +++ b/spec/api/interaction.md @@ -491,18 +491,24 @@ non-bool hidden) are dropped without mutating state. translates drawn vertices back to shipped rows so hover readouts and kernel picks stay exact; `_visInv` maps the kernel's shipped-space selection indices onto the filtered buffers. The **CPU hover fallback** - (`_nearestCpuIndex`, its polar sibling and `_barHover` — reached when the + (`_nearestCpuIndex` and its polar sibling — reached when the GPU pick pass misses, and the source of point tooltips) scans the *unfiltered* retained columns, so it consults `_visInv` too: a row it maps to `-1` is hidden and can neither become the hover target nor show a tooltip; the nearest *visible* row is picked instead, or nothing. The scan - covers the pre-filter row count (`_fullN`), not the drawn `g.n` — a + covers the pre-filter row count, not the drawn `g.n` — a category filter shrinks `g.n` below the retained columns, and capping the scan at it left every visible row shipped after the cut unreachable while hidden rows before it still answered (the two halves of one bug; `tests/test_legend_hidden_hover.py`). Unfiltered traces keep the `g.n` cap, which is load-bearing for smooth-resampled lines and mismatched x/y - lengths. + lengths. The bound is `_visInv`'s own length rather than a separately + stored count, so the range scanned and the hidden-row test cannot drift + apart; rows appended under a live filter would outrun both, which + `append_data` makes impossible by rejecting categorical color channels (a + trace is appendable or category-filterable, never both — lifting that + restriction means re-filtering on append). Before/after at + `spec/assets/legend-hidden-hover-before-after.png`. - **Category rows on a density-tier trace** (the rows exist because the first-paint density entry ships a slim categorical `color` spec — categories + palette, no per-point buffer; wire-protocol doc): local @@ -529,7 +535,7 @@ non-bool hidden) are dropped without mutating state. `-masked`, and stamps it with `filter: {hidden_categories}`. The client compares that stamp against its current hidden set and drops stale-predicate replies; drills ship only visible rows with canonical - `shipped_sel`. Before/after at `spec/assets/legend-hidden-hover-before-after.png`. + `shipped_sel`. **Accessibility compatibility exception.** Legend-hidden ordinary point-series rows remain in keyboard traversal in their full retained CPU order, so a screen @@ -538,6 +544,20 @@ does not change under a visual toggle. Funnel `stageNav` is geometry-semantic: it follows the currently visible stage/category geometry, and a whole hidden funnel contributes no stages to that walk. +**Bar-family marks have no category rows.** Category rows exist only for a +trace shipping `color.mode == "categorical"`, and no bar-emitting mark builds +one: bar colors resolve to per-series constants or direct RGBA (only funnels +and point series carry categorical color). A grouped or stacked bar chart's +legend is therefore whole-trace rows, one per series, which take the +whole-trace path above — draw, pick and hover all skip the series via +`_legendHidden`. So no bar trace has a `_visInv`, and `_barHover` carries no +hidden-row test. What a user sees: hiding a bar legend row hides that entire +series, never one category within it. If a bar mark ever gains a categorical +color channel, that filter must be built — including the bar geometry buffers +(`posBuf`/`value1Buf`/`value0Buf`), which `_filterScatterRows` does not +rebuild — before its rows can be toggled; `tests/test_legend_hidden_hover.py` +fails when the channel appears. + **Deliberate limits (recorded, not silent — §28):** toggles never rescale axes (the view is the user's; Fit Data is the re-fit tool). Toggle state does not enter durable view state or gesture history yet — a context-loss diff --git a/spec/api/styling.md b/spec/api/styling.md index 3e823559d..2ba5746d9 100644 --- a/spec/api/styling.md +++ b/spec/api/styling.md @@ -1298,13 +1298,18 @@ with, so what validates is exactly what renders: CSS reason instead of a misleading column-lookup error. - **A non-finite continuous `color=`/`size=` value is not drawn.** NaN and ±inf in a per-point numeric channel have no position on the ramp, so the - row leaves the shipped geometry, the pick/selection mapping, and the static - exports together — the same exclusion an x/y NaN gets (dossier §19), and - matplotlib's transparent "bad" colour. It is never painted as the domain - floor (the old behaviour, which drew a `+inf` point in the *minimum* - colour). The normalizers' floor for non-finite input remains only as a - vertex-safety net behind that exclusion. Missing-column names raise - `ValueError` on every surface, `facet_chart(by=...)` included. + row is excluded on every tier: direct point marks and the rectangle family + (`_finite_sel`, `_rect_finite_sel`), the density tier's count grid, + mean-colour plane, sample overlay and tile pyramid, and drill-in point + views (`channels.finite_channel_rows`). It leaves the shipped geometry, + the pick/selection mapping, and the static exports together — the same + exclusion an x/y NaN gets (dossier §19), and matplotlib's transparent + "bad" colour. It is never painted as the domain floor (the old behaviour, + which drew a `+inf` point in the *minimum* colour). The normalizers' floor + for non-finite input remains only as a vertex-safety net behind that + exclusion; the per-channel finite verdict is probed once and cached, so + the all-finite common case pays no per-request scan. Missing-column names + raise `ValueError` on every surface, `facet_chart(by=...)` included. ## What CSS cannot restyle diff --git a/spec/design/renderer-architecture.md b/spec/design/renderer-architecture.md index d79137fd3..658ec31b7 100644 --- a/spec/design/renderer-architecture.md +++ b/spec/design/renderer-architecture.md @@ -347,7 +347,14 @@ ladder cannot describe the window and `logTicks` returns `linearTicks(lo, hi, target)` instead: linearly spaced "nice" positions across the span, every one labelled, with `step` set to the linear step so `fmtLinear` gives the axis one shared decimal count (`0.30, 0.31, …`, §6.2), and `log: true` still set. This is -what matplotlib and Plotly do on a sub-decade log window. The rule is +what matplotlib and Plotly do on a sub-decade log window. A positive +*subnormal* window (`1e-323..1.5e-323`, a few ulps wide) defeats even that: +`(hi − lo) / target` underflows to 0, `niceStep` answers 1 and no multiple of +it lands inside the window. When the linear fallback yields fewer than two +ticks on a non-degenerate window, the ordered endpoints `[lo, hi]` are the +ticks (both labelled, `step = hi − lo`); they are always representable and +`fmtLinear` is exponential there regardless of step. A degenerate `lo === hi` +keeps `linearTicks`' single tick. The rule is range-based, so wide windows are byte-identical to before (`0.5..50` has two decades in view and keeps `0.5 1 2 5 10 20 50`), and it is mirrored exactly by `_log_ticks` in `python/xy/_svg.py` — which `axis_ticks` (SVG and, through it, diff --git a/spec/design/wire-protocol.md b/spec/design/wire-protocol.md index 4360f82cc..e93035083 100644 --- a/spec/design/wire-protocol.md +++ b/spec/design/wire-protocol.md @@ -20,8 +20,13 @@ returns either `None` or `(message, buffers)`, where `buffers` is a list of binary attachments the reply's spec entries index into by position. - Non-dict `content`, an unknown or non-string `type`, a missing required - field, or a value that fails coercion returns `None`. Client-supplied data - never raises; exceptions from *user callbacks* do propagate. A dropped + field, or a value that fails coercion returns `None`. Coercion failure + includes the oversized-integer case: JSON admits an integer literal of any + length, and `float()` on one past the f64 ceiling raises `OverflowError` + rather than `ValueError`, so every numeric field — window bounds, `px`/`w`/ + `h`, polygon points, legend categories — rejects it like any other bad + value. Client-supplied data never raises; exceptions from *user callbacks* + do propagate. A dropped message mutates nothing: `type` is checked before any other field is read, and every kind validates its whole payload before touching drill bookkeeping, the view-state cache, or legend predicates @@ -102,11 +107,15 @@ subset version the client picked against; a non-current seq translates through the kernel's bounded subset history when it is still remembered (the client may be drawing a retired cached point window, LOD doc T13) and resolves to `row: null` otherwise — never to a row in a dead index space. -`index` must also name a readable row: where a mark's advertised `n_points` -is not the length of its readout columns — a histogram's or hexbin's sample -count over its bin rows, an errorbar's points over its segment endpoints — -the bound is the smaller of the two, and an index past it resolves to -`row: null` rather than an exception. +`index` must also name a readable row. Binned aggregates (histogram, hexbin) +are bounded by their bin rows — `n_points` there is the sample count, which +may exceed or fall short of the row count and bounds nothing — grid marks by +their cells, and every other kind by the smaller of `n_points` and its +readout columns (an errorbar advertises its points over three segment +endpoints each). An index past the bound resolves to `row: null` rather than +an exception; should a lookup still raise `IndexError`, the dispatcher +answers with the same `row: null` reply (carrying `seq`) so the client clears +its hover row, while `TypeError`/`ValueError` coercion failures stay silent. **`click`** — same fields and same `fig.pick` resolution as `pick`, minus `seq`; it fires `on_click` and returns nothing. @@ -244,9 +253,8 @@ accepts `msg.trace` and `msg.stale` for pending-request bookkeeping — no current kernel path emits either field. **`pick_result`** — `{type, seq, row}`. `row` is `null` when the index is out -of range (past the advertised count or the readable rows, whichever is -smaller — §2 `pick`) or `drill_seq` was stale; the reply ships regardless so -the client clears its hover state. A point row is +of range (past the readable rows, §2 `pick`) or `drill_seq` was stale; the +reply ships regardless so the client clears its hover state. A point row is `{trace, index, x, y, x_kind, y_kind}` plus `color_value` or `color_category` and `size_value` when those channels exist. A heatmap row is `{trace, index, row, col}` plus `color_value` when the cell is finite. Picks diff --git a/spec/matplotlib/compat-changelog.md b/spec/matplotlib/compat-changelog.md index 201de0173..8ff33bd6b 100644 --- a/spec/matplotlib/compat-changelog.md +++ b/spec/matplotlib/compat-changelog.md @@ -4,7 +4,16 @@ This changelog records changes to the upstream compatibility target and to the meaning of xy's compatibility levels. It complements the project changelog, which covers user-visible releases across the whole package. -## Artist keywords, legend forms, partial subplot grids — 2026-09-01 +## Artist keywords, legend forms, partial subplot grids — 2026-09-01 (Matplotlib 3.11.0 reference) + +Reference: the released `matplotlib==3.11.0` wheel (in-test comparisons of +legend labels, subplot rectangles, histogram geometry, bar rectangles, and +qualitative palettes); the pinned inventory snapshot `v3.11.0-348-gbde111fb4e` +is unchanged. Inventory: no methods added or removed (66). Compatibility +levels: no family level changes; the option-level moves are `pcolormesh`/ +`pcolor`/`tripcolor`/`tricontour(f)` `antialiased=`, `quiver`/`streamplot`/ +`quiverkey` `zorder=`, and `colorbar(fraction=)` from *unsupported* to +*accepted no-op*, and `plt.cm.` from a name string to a colormap object. - Matplotlib's Artist-level keywords (`zorder`, `clip_on`, `rasterized`, `antialiased`/`aa`, `snap`, `gid`, `url`, `picker`, `in_layout`, diff --git a/spec/matplotlib/compat.md b/spec/matplotlib/compat.md index f1a4301fb..077374796 100644 --- a/spec/matplotlib/compat.md +++ b/spec/matplotlib/compat.md @@ -72,8 +72,8 @@ dependency-free `triangles=` shorthand into Matplotlib's equivalent | `xlabel` / `ylabel` / `title` / `suptitle` | Suptitles are retained in HTML and multi-panel PNG/SVG. `ylabel` sits clear of the y tick labels in every renderer: the left gutter is reserved from the measured advances of the tick labels and the rotated title rather than from a fixed constant, leaving Matplotlib's `0.4 em` (5.6 px at the 10 pt/100 dpi default) title-to-tick gap — see *Measured left gutter and the rotated y-axis title* in `spec/api/styling.md` for the formula and its two documented asymmetries | | `legend()` | Call forms `legend()`, `legend(labels)`, `legend(handles, labels)`, and the keyword spellings `legend(handles=, labels=)`, `legend(handles=)` (labels read off the handles, underscore labels included, as Matplotlib does) and `legend(labels=)`. `loc` accepts Matplotlib's names, its integer codes 0–10 (`Legend.codes`: 0 best, 1 upper right, ... 10 center), and an `(x, y)` axes-fraction tuple that anchors the legend's lower-left corner there. Proxy handles work: `plt.Line2D([0], [0], color=, linestyle=, linewidth=, marker=, markersize=, mfc=, mec=, mew=, alpha=, label=)`, `plt.Patch(facecolor=, edgecolor=, linewidth=, alpha=, hatch=, fill=, label=)`, and `plt.Rectangle((x, y), w, h, **patch style)` (also accepted by `add_patch`) own no axes and freeze into swatches through the same path as plotted artists (dashes and marker sizes are scaled from points at the owning figure's DPI). `loc`, columns, title/font size/colors, frame styling, `borderpad`, `labelspacing`, `borderaxespad`, `fancybox`, `framealpha`, and `shadow` are retained across browser and static output. `loc='best'` scores the measured displayed legend box in Matplotlib location-code order using path vertices/crossings, collection offsets, and bar-rectangle overlaps. It resolves before the wire; pyplot rejects misspelled Matplotlib locations without narrowing core `xy.legend()`'s independent location vocabulary. Text-box scoring and bounded long-path sampling are documented in `spec/api/styling.md` § Legend placement | | `grid(True/False)` | toggles the grid via the theme | -| `xlim` / `ylim`, `set_xmargin` / `set_ymargin`, axis scales, `invert_xaxis/yaxis` | linear/log are native; symlog/logit/asinh use dependency-free monotone data transforms with inverse limit/tick semantics. Automatic linear ticks include Matplotlib's 2.5 step and use uniform decimal padding across a tick set; locations refresh as data arrives. `axes.autolimit_mode="round_numbers"` expands automatic linear limits to the first and last AutoLocator ticks after applying the configured margins. Artist `get_data()` reflects the transformed space; logit masks values at/outside (0, 1). `set_xlim`/`set_ylim` (and `plt.xlim`/`plt.ylim`) and `set_xticks`/`set_yticks` accept every datetime-like `plot()` accepts — `datetime`, `date`, `datetime64`, pandas `Timestamp`, and date strings on a datetime axis — converting them to the engine's ms-since-epoch floats, which is also what `get_xlim()`/`get_xticks()` report on a date axis (not Matplotlib's day floats) | -| `set_major_locator` / `set_major_formatter`, `plt.NullLocator/FixedLocator/MultipleLocator/MaxNLocator/LinearLocator/LogLocator`, `plt.NullFormatter/FixedFormatter/FuncFormatter/FormatStrFormatter/StrMethodFormatter/ScalarFormatter` | xy-owned re-implementations resolved at build time against live data limits (Null/Fixed/Multiple/Linear are position-exact; MaxN/Auto port Matplotlib's `MaxNLocator._raw_ticks` — same step tables, edge extension, and offset handling — with `nbins="auto"` budgeted from the estimated plot rect like `Axis.get_tick_space()`; Log remains approximate). Third-party locator objects work if they implement `tick_values(vmin, vmax)`; one whose `tick_values` raises `NotImplementedError` (Matplotlib's abstract `Locator` base) is called through Matplotlib's own `__call__` protocol when it is bound to an axis, and otherwise dropped so the axis keeps its kind's default ticks (a date axis keeps its date ticks) instead of failing the build. Minor locators/formatters are retained for round-tripping but minor ticks do not render, except that a labeled minor pair under a blanked major formatter (the centered date-label idiom) is promoted to the drawn tick set. `ticklabel_format(axis=, style=, scilimits=, useOffset=, useMathText=)` configures the axis `ScalarFormatter` exactly as Matplotlib does (installing one when no formatter is set; any other installed formatter raises `AttributeError`): `style="plain"` labels the located ticks with the shared decimal count Matplotlib's `_set_format` derives from the tick spacing, and `style="sci"` switches to mantissas once the ticks' order of magnitude leaves `scilimits` (default `(-5, 6)`, Matplotlib's `axes.formatter.limits`). **Compat-noop:** the shim has no offset-text slot, so `useOffset` never factors an offset out — labels always carry the full value — and the scientific exponent is written on every label (`1.25e6`, or `1.25×10⁶` under `useMathText=True`) rather than once beside the axis. `useLocale=True` raises | +| `xlim` / `ylim`, `set_xmargin` / `set_ymargin`, axis scales, `invert_xaxis/yaxis` | linear/log are native; symlog/logit/asinh use dependency-free monotone data transforms with inverse limit/tick semantics. Automatic linear ticks include Matplotlib's 2.5 step and use uniform decimal padding across a tick set; locations refresh as data arrives. `axes.autolimit_mode="round_numbers"` expands automatic linear limits to the first and last AutoLocator ticks after applying the configured margins. Artist `get_data()` reflects the transformed space; logit masks values at/outside (0, 1). `set_xlim`/`set_ylim` (and `plt.xlim`/`plt.ylim`) and `set_xticks`/`set_yticks` accept every datetime-like `plot()` accepts — `datetime`, `date`, `datetime64`, pandas `Timestamp`, and date strings on a datetime axis — converting them to the engine's ms-since-epoch floats, which is also what `get_xlim()`/`get_xticks()` report on a date axis (not Matplotlib's day floats). Datetime ticks also pin the axis kind to `time`, so ticks authored before any datetime artist (or with none at all) label as dates rather than epoch milliseconds | +| `set_major_locator` / `set_major_formatter`, `plt.NullLocator/FixedLocator/MultipleLocator/MaxNLocator/LinearLocator/LogLocator`, `plt.NullFormatter/FixedFormatter/FuncFormatter/FormatStrFormatter/StrMethodFormatter/ScalarFormatter` | xy-owned re-implementations resolved at build time against live data limits (Null/Fixed/Multiple/Linear are position-exact; MaxN/Auto port Matplotlib's `MaxNLocator._raw_ticks` — same step tables, edge extension, and offset handling — with `nbins="auto"` budgeted from the estimated plot rect like `Axis.get_tick_space()`; Log remains approximate). Third-party locator objects work if they implement `tick_values(vmin, vmax)`; one whose `tick_values` raises `NotImplementedError` (Matplotlib's abstract `Locator` base) is called through Matplotlib's own `__call__` protocol when it is bound to an axis, and otherwise dropped so the axis keeps its kind's default ticks (a date axis keeps its date ticks) instead of failing the build. Minor locators/formatters are retained for round-tripping but minor ticks do not render, except that a labeled minor pair under a blanked major formatter (the centered date-label idiom) is promoted to the drawn tick set. `ticklabel_format(axis=, style=, scilimits=, useOffset=, useMathText=)` configures the axis `ScalarFormatter` exactly as Matplotlib does (installing one when no formatter is set; any other installed formatter raises `AttributeError`): `style="plain"` labels the located ticks with the shared decimal count Matplotlib's `_set_format` derives from the tick spacing, and `style="sci"` switches to mantissas once the ticks' order of magnitude leaves `scilimits` (default `(-5, 6)`, Matplotlib's `axes.formatter.limits`). **Compat-noop:** the shim has no offset-text slot, so `useOffset` never factors an offset out — labels always carry the full value — and the scientific exponent is written on every label (`1.25e6`, or `1.25×10⁶` under `useMathText=True`) rather than once beside the axis. Exponents are clamped to ±300 and labels are limited to 20 decimals (a double carries ~16 significant digits) so extreme axes (`1e300`, `1e-300`) export instead of overflowing; a tick set that would need more decimals falls back to `%g` (`1e-300`) rather than printing value-less zeros. `useLocale=True` raises | | `plt.dates.MonthLocator/YearLocator/DayLocator/DateFormatter` | xy-owned equivalents of the `matplotlib.dates` classes gallery scripts use; they locate and format in the engine's canonical ms-since-epoch axis unit (not Matplotlib's day floats), and `interval` approximates rrule by epoch-anchored occurrence counting | | datetime, timedelta, and string coordinates | datetime inputs use the engine's automatic date ticks, timedeltas are bounded to elapsed seconds, and common strings use categorical ticks; the general Matplotlib units registry is intentionally out of scope. pandas datetime plotting (`series.plot(ax=ax)`) works against that contract: `get_{x,y}data(orig=False)` returns ms-since-epoch floats, and pandas' period-ordinal tickers (`TimeSeries_Date*`) are accepted as no-ops on both the major and the minor tier so the native date ticks keep rendering (pandas 3.0.5's minor `TimeSeries_DateLocator` has no `tick_values`; see the locator row above for the general fallback) | | `xticks(positions, labels, rotation=)` / `tick_params(labelrotation=)` | Exact positions and strings render in browser, PNG, and SVG. The stateful `plt.tick_params`, `plt.margins`, and `plt.locator_params` delegate to the current axes like every other `plt.*` wrapper | @@ -88,7 +88,7 @@ dependency-free `triangles=` shorthand into Matplotlib's equivalent | `plt.show()` | notebooks: inline HTML display; scripts: opens the default browser | | Artists: `set_data` / `set_ydata` / `set_color` / `set_label` / `set_linewidth` / `remove` | mutating a handle rebuilds the chart on next render. Scatter collections additionally vectorize facecolors, edgecolors, alpha, linewidths, and sizes; `alpha=None` restores intrinsic paint alpha | | Colors | single letters, `C0`–`C9`, `tab:*`, gray `'0.5'`, RGB(A) tuples, `(color, alpha)` pairs, per-item RGB(A) arrays, and any CSS color | -| `plt.cm.*` / `plt.colormaps[...]` / `plt.get_cmap` / `cmap=` names | `plt.cm.` and `plt.get_cmap(name)` return callable colormap objects with `.N` (`plt.cm.viridis(np.linspace(0, 1, 3))` → RGBA rows) that plotting calls accept as `cmap=`; Matplotlib's qualitative palettes tab10, tab20, tab20b, tab20c, Set1–3, Paired, Accent, Dark2, Pastel1, Pastel2 (and their `_r`) come back as callable `ListedColormap`s — indexable by integer or fraction, but not passable as `cmap=` (no engine table; fails loudly). Engine colormaps: viridis, plasma, inferno, magma, cividis, gray, bone, autumn, winter, turbo, coolwarm, Blues, Purples, Reds, PuBu, BuPu, RdBu, RdYlGn, RdGy, PiYG, PRGn, jet, rainbow, Spectral, binary, aliases, and true `*_r` reversal resolved generically for every listed name, including `plt.cm._r` attribute access (RdGy/jet/Reds/bone/autumn/winter/BuPu render from 11-stop anchor tables sampled from Matplotlib 3.11, linearly interpolated) | +| `plt.cm.*` / `plt.colormaps[...]` / `plt.get_cmap` / `cmap=` names | `plt.cm.` and `plt.get_cmap(name, lut=)` return callable colormap objects with `.N` (`lut` resamples: qualitative palettes sample `lut` evenly spaced positions like Matplotlib's `ListedColormap.resampled`) (`plt.cm.viridis(np.linspace(0, 1, 3))` → RGBA rows) that plotting calls accept as `cmap=`; Matplotlib's qualitative palettes tab10, tab20, tab20b, tab20c, Set1–3, Paired, Accent, Dark2, Pastel1, Pastel2 (and their `_r`) come back as callable `ListedColormap`s — indexable by integer or fraction, but not passable as `cmap=` (no engine table; fails loudly). Engine colormaps: viridis, plasma, inferno, magma, cividis, gray, bone, autumn, winter, turbo, coolwarm, Blues, Purples, Reds, PuBu, BuPu, RdBu, RdYlGn, RdGy, PiYG, PRGn, jet, rainbow, Spectral, binary, aliases, and true `*_r` reversal resolved generically for every listed name, including `plt.cm._r` attribute access (RdGy/jet/Reds/bone/autumn/winter/BuPu render from 11-stop anchor tables sampled from Matplotlib 3.11, linearly interpolated) | | `LinearSegmentedColormap.from_list` / `ListedColormap` | Python-side callables (`cmap(np.arange(cmap.N))` → RGBA) for scripts that colormap values themselves; they cannot be passed as `cmap=` to plotting calls (no engine table), which fails loudly | | `plt.colorbar()` / `fig.colorbar()` / `plt.clim()` / `plt.gci()` | Returns a live handle (`set_label`, `set_ticks`); `fraction=` is an accepted no-op (the colorbar strip has a fixed width); with no mappable it uses the current image the way pyplot does. `ticks=`/`extend=` render in PNG and SVG (the HTML colorbar stays a minimal gradient without tick text); `clim` retargets the mappable's color window and any colorbar derived from it | | `Colorbar.set_label(...)` / `colorbar(label=...)` | Matplotlib's default label geometry in all three renderers: beside a vertical bar rotated 90° counter-clockwise and centered on it, or upright and centered below a horizontal bar. The vertical label is a quarter turn, which the native PNG rasterizer renders exactly (only arbitrary text angles fall back to upright glyphs there), and the reserved right-margin room contains its cross-axis glyph extent. `set_label` ignores Matplotlib's customization kwargs (`loc=`, `labelpad=`, `rotation=`, font properties) rather than failing — the default orientation is derived from the bar | @@ -117,7 +117,11 @@ every plotting method in the inventory (plus `grid`, `set_title`, engine has no draw-order override, clipping policy, hit-testing metadata, or renderer filters for a single mark, so they are ignored rather than rejected when a script carries them for the real renderer. `visible=False` is not a -no-op — it hides every artist the call returns (`set_visible(False)`). +no-op — it hides every artist the call returns (`set_visible(False)`, +which on a `Line2D` also hides its marker overlay), and on `set_title` / +`set_xlabel` / `set_ylabel` it clears the chrome text (`get_title()` then +returns `""`; the shim has no hidden-text state). Legend proxies accept +`visible=` too. Methods that implement one of those names themselves keep it: `annotate` and `clabel` order by `zorder`, `pcolormesh`/`pcolor`/`pcolorfast` record `rasterized` on their handle, and `imshow` honors `clip_on`. The setters keep diff --git a/spec/matplotlib/shim-todo.md b/spec/matplotlib/shim-todo.md index 03abda9f1..9a6b94b93 100644 --- a/spec/matplotlib/shim-todo.md +++ b/spec/matplotlib/shim-todo.md @@ -712,6 +712,12 @@ streamplot positions it fails loudly (the category axis owns its labels). - `hist(align="left"/"right")` is implemented for the bar histtypes only; the step families accept `align="mid"` and fail loudly otherwise. +- `set_title`/`set_xlabel`/`set_ylabel(visible=False)` clear the text rather + than keeping a hidden `Text`, so `get_title()` reports `""`; Matplotlib + would still report the hidden string. +- `tight_layout` on a partial numbered grid (`subplot(221)`+`subplot(224)`) + sizes the inter-column gap from adjacent panels only, so panel widths differ + slightly from a full `subplots(2, 2)` — Matplotlib 3.11 behaves the same way. ### P1 audit fixes — 2026-09-01 diff --git a/tests/pyplot/corpus/56_partial_subplots_legend_proxies.py b/tests/pyplot/corpus/56_partial_subplots_legend_proxies.py index bd8b55521..49d7276a4 100644 --- a/tests/pyplot/corpus/56_partial_subplots_legend_proxies.py +++ b/tests/pyplot/corpus/56_partial_subplots_legend_proxies.py @@ -18,7 +18,8 @@ top_left.grid(True, zorder=0) bottom = plt.subplot(2, 1, 2) -bars = bottom.bar(["a", "b", "c"], [1, 2, 3], yerr=[0.1, 0.2, 0.3], tick_label=None) +bars = bottom.bar([0, 1, 2], [1, 2, 3], yerr=[0.1, 0.2, 0.3], tick_label=["a", "b", "c"]) +assert [t.get_text() for t in bottom.get_xticklabels()] == ["a", "b", "c"] for rect in bars: bottom.text( rect.get_x() + rect.get_width() / 2, diff --git a/tests/pyplot/test_p1_axes_dates_spans.py b/tests/pyplot/test_p1_axes_dates_spans.py index 2646e9a57..3ea5cc26e 100644 --- a/tests/pyplot/test_p1_axes_dates_spans.py +++ b/tests/pyplot/test_p1_axes_dates_spans.py @@ -10,6 +10,7 @@ import datetime as dt import io import re +import warnings import numpy as np import pytest @@ -135,6 +136,38 @@ def test_ticklabel_format_cross_check_against_matplotlib(): assert len(labels) >= 5 +@pytest.mark.parametrize("values", [[1e300, 2e300], [1e-300, 2e-300]]) +@pytest.mark.parametrize("style", ["sci", "plain"]) +def test_ticklabel_format_survives_extreme_magnitudes(values, style): + fig, ax = plt.subplots() + ax.plot([0, 1], values) + ax.ticklabel_format(style=style) + with warnings.catch_warnings(): + # The formatter must neither raise (10.0 ** 309) nor warn (overflow). + warnings.simplefilter("error") + formatter = ax.yaxis.get_major_formatter() + labels = formatter.format_ticks(np.linspace(values[0], values[1], 6)) + assert len(labels) == 6 and all(label for label in labels) + assert all(float(label) != 0.0 for label in labels) # every label keeps its value + _export_all(fig) + + +def test_scalar_formatter_extreme_labels_keep_their_value(): + sci = ScalarFormatter() + sci.set_scientific(True) + assert sci.format_ticks([1e300, 1.5e300, 2e300]) == ["1.0e300", "1.5e300", "2.0e300"] + assert sci.format_ticks([1e-300, 1.5e-300, 2e-300]) == ["1.0e-300", "1.5e-300", "2.0e-300"] + plain = ScalarFormatter() + plain.set_scientific(False) + # More decimals than a double carries: fall back to %g rather than zeros. + assert plain.format_ticks([1e-300, 1.5e-300, 2e-300]) == ["1e-300", "1.5e-300", "2e-300"] + assert plain.format_ticks([1e300, 2e300])[0].startswith("1000000000000000052504760") + with warnings.catch_warnings(): + warnings.simplefilter("error") + assert len(sci.format_ticks(np.linspace(0.0, 1e308, 6))) == 6 + assert len(plain.format_ticks(np.linspace(0.0, 1e308, 6))) == 6 + + # --------------------------------------------------------------------------- # B. spans and rules: autoscale on their own axis, label= reaches the legend # --------------------------------------------------------------------------- @@ -403,6 +436,37 @@ def test_set_xticks_accepts_datetime_likes(): _export_all(fig2) +def _svg_x_labels(fig) -> list[bytes]: + return re.findall(rb'text-anchor="middle">([^<]*)<', _export_all(fig)["svg"]) + + +def test_datetime_ticks_make_a_date_axis_in_either_order(): + ticks = [dt.datetime(2024, 1, 1), dt.datetime(2024, 1, 2)] + fig, ax = plt.subplots() + ax.set_xticks(ticks) # before any datetime artist: the axis was linear + ax.plot(_DATES, [1, 2, 3]) + assert _svg_x_labels(fig) == [b"Jan 01", b"Jan 02"] + fig, ax = plt.subplots() + ax.plot(_DATES, [1, 2, 3]) + ax.set_xticks(ticks) + assert _svg_x_labels(fig) == [b"Jan 01", b"Jan 02"] + fig, ax = plt.subplots() + ax.set_xticks(ticks) # ticks alone are enough + assert ax._axis_holds_datetimes("x") + assert _svg_x_labels(fig) == [b"Jan 01", b"Jan 02"] + fig, ax = plt.subplots() + ax.set_yticks(ticks) + ax.plot([1, 2], ticks) + svg = _export_all(fig)["svg"] + assert re.findall(rb'text-anchor="end">([^<]*)<', svg) == [b"Jan 01", b"Jan 02"] + # Numeric ticks never pin the axis kind. + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1]) + ax.set_xticks([0, 0.5, 1]) + assert not ax._axis_holds_datetimes("x") + assert _svg_x_labels(fig) == [b"0.0", b"0.5", b"1.0"] + + def test_fill_between_accepts_datetimes_and_keeps_the_time_axis(): fig, ax = plt.subplots() ax.plot(_DATES, [1, 2, 3]) diff --git a/tests/pyplot/test_p1_kwargs_legend_subplot.py b/tests/pyplot/test_p1_kwargs_legend_subplot.py index 4a558368a..07445ddc7 100644 --- a/tests/pyplot/test_p1_kwargs_legend_subplot.py +++ b/tests/pyplot/test_p1_kwargs_legend_subplot.py @@ -573,3 +573,143 @@ def test_bar_with_string_categories_and_error_bars_autoscales() -> None: assert ax.get_ylim() == pytest.approx((-0.54, 2.54)) assert ax.get_xlim()[1] >= 3.3 assert len(ax.get_yticklabels()) == 3 + + +# --- review round: visibility of proxies and chrome, partial-grid layout ------ + + +def test_legend_proxies_honor_visible_and_propagate_to_their_marker() -> None: + hidden_line = plt.Line2D([0], [0], color="r", marker="o", visible=False) + assert not hidden_line.get_visible() + assert hidden_line._entry["kwargs"]["opacity"] == 0.0 + assert hidden_line._proxy_marker_entry["kwargs"]["opacity"] == 0.0 + assert not plt.Patch(facecolor="r", visible=False).get_visible() + assert not plt.Rectangle((0, 0), 1, 1, visible=False).get_visible() + shown = plt.Line2D([0], [0], color="b", marker="s", alpha=0.5) + shown.set_visible(False) + assert shown._proxy_marker_entry["kwargs"]["opacity"] == 0.0 + shown.set_visible(True) + assert shown._proxy_marker_entry["kwargs"]["opacity"] == 0.5 + assert shown._entry["kwargs"]["opacity"] == 0.5 + + +def test_plotted_line_visibility_moves_its_marker_overlay_too() -> None: + _fig, ax = plt.subplots() + (line,) = ax.plot([0, 1], [0, 1], marker="o", visible=False) + kinds = [(entry["kind"], entry["kwargs"].get("opacity")) for entry in ax._entries] + assert kinds == [("line", 0.0), ("scatter", 0.0)] + line.set_visible(True) + assert [entry["kwargs"]["opacity"] for entry in ax._entries] == [1.0, 1.0] + line.set_alpha(0.4) + assert [entry["kwargs"]["opacity"] for entry in ax._entries] == [0.4, 0.4] + + +def test_chrome_setters_apply_visible_to_their_text() -> None: + fig, ax = plt.subplots() + ax.plot([0, 1], [0, 1]) + ax.set_title("HIDDENTITLE", visible=False) + ax.set_xlabel("HIDDENX", visible=False) + ax.set_ylabel("SHOWNY", visible=True) + svg = _svg(fig) + assert "HIDDENTITLE" not in svg and "HIDDENX" not in svg + assert "SHOWNY" in svg + assert ax.get_title() == "" + ax.set_title("SHOWNTITLE", visible=True, zorder=2) + assert "SHOWNTITLE" in _svg(fig) + + +def test_partial_grid_records_its_dimensions_for_tight_layout() -> None: + plt.subplot(221) + plt.plot([0, 1]) + plt.subplot(224) + plt.plot([1, 0]) + fig = plt.gcf() + assert (fig._nrows, fig._ncols) == (2, 2) + fig.tight_layout() + fig.savefig(BytesIO(), format="png") + partial = [np.asarray(ax.get_position().bounds) for ax in fig.axes] + plt.close("all") + full_fig, axes = plt.subplots(2, 2) + axes[0, 0].plot([0, 1]) + axes[1, 1].plot([1, 0]) + full_fig.tight_layout() + full_fig.savefig(BytesIO(), format="png") + full = [ + np.asarray(axes[0, 0].get_position().bounds), + np.asarray(axes[1, 1].get_position().bounds), + ] + # Row geometry (bottom, height) and the figure-edge margins are the 2x2 + # grid's; only the inter-column gap differs, because Matplotlib (and xy) + # size that gap from the chrome of *adjacent* panels, which a 221/224 + # figure does not have. Matplotlib 3.11 shows the same width difference. + for got, want in zip(partial, full, strict=True): + np.testing.assert_allclose(got[[1, 3]], want[[1, 3]], atol=1e-6) + np.testing.assert_allclose(partial[0][0], full[0][0], atol=1e-6) # left margin + np.testing.assert_allclose(partial[1][0] + partial[1][2], full[1][0] + full[1][2], atol=1e-6) + for rect in partial: # each panel stays inside its own quadrant + assert rect[2] < 0.5 and rect[3] < 0.5 + assert partial[0][0] < 0.5 < partial[1][0] + + +def test_get_cmap_lut_resamples_qualitative_palettes_like_matplotlib() -> None: + mpl = _matplotlib() + mpl.use("Agg") + import matplotlib.pyplot as mplt + from matplotlib.colors import to_hex + + for name, count in (("tab10", 4), ("tab10", 12), ("tab10_r", 4), ("Paired", 5)): + ours = plt.get_cmap(name, count) + reference = mplt.get_cmap(name, count) + assert ours.N == count == reference.N + assert [to_hex(c) for c in ours.colors] == [to_hex(c) for c in reference.colors], name + assert ours.name == reference.name + assert [to_hex(c) for c in plt.get_cmap("tab10", 4).colors] == [ + "#1f77b4", + "#d62728", + "#e377c2", + "#17becf", + ] + + +@pytest.mark.parametrize("align", ["left", "right", "mid"]) +@pytest.mark.parametrize("rwidth", [None, 0.5]) +def test_hist_align_bar_rectangles_match_matplotlib(align: str, rwidth) -> None: + mpl = _matplotlib() + mpl.use("Agg") + import matplotlib.pyplot as mplt + + data = [1, 2, 2, 3, 3.5, 2.2] + _fig, ax = plt.subplots() + _n, _e, patches = ax.hist(data, bins=3, align=align, rwidth=rwidth) + _n, _e, grouped = ax.hist([data, data], bins=3, align=align, rwidth=rwidth) + mfig, max_ = mplt.subplots() + _n, _e, reference = max_.hist(data, bins=3, align=align, rwidth=rwidth) + _n, _e, reference_grouped = max_.hist([data, data], bins=3, align=align, rwidth=rwidth) + geometry = [(r.get_x(), r.get_width()) for r in patches] + expected = [(r.get_x(), r.get_width()) for r in reference] + np.testing.assert_allclose(geometry, expected, atol=1e-9) + for ours, theirs in zip(grouped, reference_grouped, strict=True): + np.testing.assert_allclose( + [(r.get_x(), r.get_width()) for r in ours], + [(r.get_x(), r.get_width()) for r in theirs], + atol=1e-9, + ) + mplt.close(mfig) + + +@pytest.mark.parametrize( + ("colors", "expected"), + [ + (["red", "green", "blue"], "red"), # 3 names: first entry wins, not RGB + (["red", "green", "blue", "black"], "red"), # 4 names: not RGBA either + (["red", "green"], "red"), + (["red", "green", "blue", "black", "white"], "red"), + ((1.0, 0.0, 0.0), "rgb(255,0,0)"), # one numeric RGB tuple is one color + ((1.0, 0.0, 0.0, 0.5), "rgba(255,0,0,0.5)"), + ("red", "red"), + ], +) +def test_hlines_vlines_colors_read_names_first_and_rgba_tuples_whole(colors, expected) -> None: + _fig, ax = plt.subplots() + assert ax.hlines(0.5, 0, 1, colors=colors)._entry["kwargs"]["color"] == expected + assert ax.vlines(0.5, 0, 1, colors=colors)._entry["kwargs"]["color"] == expected diff --git a/tests/test_api_p1_fixes.py b/tests/test_api_p1_fixes.py index bd25bc208..e013137b6 100644 --- a/tests/test_api_p1_fixes.py +++ b/tests/test_api_p1_fixes.py @@ -16,8 +16,7 @@ import xy from xy import channels from xy.components import _MARK_APPLIERS - -pa = pytest.importorskip("pyarrow") # the Python-floor CI job has no pyarrow +from xy.config import SCATTER_DENSITY_THRESHOLD # -- 1. log axis drops non-positive rows loudly ------------------------------ @@ -125,6 +124,115 @@ def test_finite_channels_do_not_allocate_a_selection() -> None: assert fig.traces[0].shipped_sel is None +def _payload_column(spec: dict, blob: bytes, meta: dict) -> np.ndarray: + dtype = np.uint8 if meta.get("dtype") == "u8" else np.float32 + raw = np.frombuffer(blob, dtype=dtype, count=meta["len"], offset=meta["byte_offset"]) + return raw.astype(np.float64) / meta.get("scale", 1.0) + meta.get("offset", 0.0) + + +def _density_scatter(): + """A density-tier scatter whose two undrawable rows sit alone in the far + corner (x > 60), so any grid cell, sample point, or drilled row out there + can only have come from them.""" + n = SCATTER_DENSITY_THRESHOLD + 100_000 + rng = np.random.default_rng(3) + x = rng.uniform(0.0, 50.0, n) + y = rng.uniform(0.0, 50.0, n) + color = x.copy() + x[0], y[0], color[0] = 90.0, 90.0, np.nan + x[1], y[1], color[1] = 95.0, 95.0, np.inf + # A channelled scatter keeps direct draw until DIRECT_SOFT_CEILING, so the + # density tier is requested explicitly at this size. + return xy.scatter_chart(xy.scatter(x=x, y=y, color=color, density=True)).figure(), n + + +def _cols_beyond(x_range: list, w: int, x: float) -> int: + x0, x1 = x_range + return int((x - x0) / (x1 - x0) * w) + + +def test_density_first_payload_excludes_nonfinite_channel_rows() -> None: + fig, n = _density_scatter() + spec, blob = fig.build_payload() + trace = spec["traces"][0] + assert trace["tier"] == "density" + assert trace["visible"] == n - 2 + density = trace["density"] + cut = _cols_beyond(density["x_range"], density["w"], 60.0) + counts = _payload_column(spec, blob, spec["columns"][density["buf"]]).reshape( + density["h"], density["w"] + ) + assert counts[:, cut:].max() == 0, "an undrawable row was counted in the grid" + rgba = _payload_column(spec, blob, spec["columns"][density["rgba"]]).reshape( + density["h"], density["w"], 4 + ) + assert rgba[:, cut:, 3].max() == 0, "an undrawable row fed the mean-color plane" + sample = density["sample"] + xs = _payload_column(spec, blob, sample["x"]) + assert len(xs) == sample["n"] > 0 + assert xs.max() <= 50.0, "an undrawable row reached the sample overlay" + + +def test_density_view_and_drill_exclude_nonfinite_channel_rows() -> None: + fig, n = _density_scatter() + fig.build_payload() + upd, bufs = fig.density_view(0, 0.0, 100.0, 0.0, 100.0, 256, 192) + trace = upd["traces"][0] + assert trace["mode"] == "density" and trace["binning"] == "exact" + assert trace["visible"] == n - 2 + density = trace["density"] + cut = _cols_beyond(density["x_range"], density["w"], 60.0) + rgba = np.frombuffer(bufs[density["rgba"]], dtype=np.uint8).reshape( + density["h"], density["w"], 4 + ) + assert rgba[:, cut:, 3].max() == 0 + # Zoom onto a window holding good points and both bad rows: the drilled + # subset (canonical rows, via enter_drill) must skip rows 0 and 1. + reply, _bufs = fig.density_view(0, 45.0, 100.0, 45.0, 100.0, 256, 192) + assert reply["traces"][0]["mode"] == "points" + shipped = fig.traces[0].shipped_sel + assert shipped is not None and len(shipped) > 0 + assert not np.isin([0, 1], shipped).any(), "an undrawable row was drilled to a point" + + +_BAD_CHANNEL = np.array([1.0, np.nan, 3.0, np.inf, 5.0]) + + +def _bar_figure(): + return xy.bar_chart(xy.bar(x=[0, 1, 2, 3, 4], y=[1, 2, 3, 4, 5])).figure() + + +def test_rectangle_family_excludes_nonfinite_continuous_color() -> None: + """No public rectangle mark resolves a 1-D numeric `color=` as a + continuous channel (bar's numeric paint means RGB rows), so the channel + is installed on the trace directly: `_rect_finite_sel` is the contract + every rectangle emitter shares, whatever mark feeds it.""" + fig = _bar_figure() + fig.traces[0].color_ch = channels.ColorChannel( + mode="continuous", values=_BAD_CHANNEL, domain=(1.0, 5.0) + ) + spec, _blob = fig.build_payload() + assert spec["traces"][0]["n_marks"] == 3 + + +def test_rectangle_family_excludes_nonfinite_continuous_size() -> None: + fig = _bar_figure() + fig.traces[0].size_ch = channels.SizeChannel( + mode="continuous", values=_BAD_CHANNEL, domain=(1.0, 5.0) + ) + spec, _blob = fig.build_payload() + assert spec["traces"][0]["n_marks"] == 3 + + +def test_rectangle_family_all_finite_channels_ship_every_row() -> None: + fig = _bar_figure() + fig.traces[0].size_ch = channels.SizeChannel( + mode="continuous", values=np.arange(1.0, 6.0), domain=(1.0, 5.0) + ) + spec, _blob = fig.build_payload() + assert spec["traces"][0]["n_marks"] == 5 + + def test_quantizer_contract_documented_not_silent() -> None: # The quantizer itself still floors non-finite input: the contract is that # the emitters exclude such rows before shipping (design dossier §19). @@ -175,6 +283,18 @@ def test_sankey_chart_refuses_mark_kwargs_without_links() -> None: xy.sankey_chart(xy.legend(show=False), node_width=0.1) +def test_sankey_chart_bare_call_refuses_mark_kwargs_by_name() -> None: + with pytest.raises(ValueError, match=r"\['node_width'\] without links"): + xy.sankey_chart(node_width=0.1) + + +def test_sankey_chart_bare_call_keeps_its_historical_shape() -> None: + chart = xy.sankey_chart() + assert [c.kind for c in chart.children if isinstance(c, xy.Mark)] == ["sankey"] + with pytest.raises(ValueError, match="link"): + chart.figure() + + # -- 4. a hand-built xy.Mark never leaks KeyError ------------------------------ _MINIMAL_MARK_DATA = { @@ -182,18 +302,33 @@ def test_sankey_chart_refuses_mark_kwargs_without_links() -> None: } +# Kinds that x/y alone cannot build: the ValueError must name the kind and +# the prop that is missing. Every other kind builds exactly like its factory. +_BARE_MARK_RAISES = { + "contour": "z", + "error_band": "upper", + "errorbar": "yerr", + "ribbon": "source_lo", + "sankey": "link", + "segments": "geometry", + "stairs": "edges", + "triangle_mesh": "x1", +} + + @pytest.mark.parametrize("kind", sorted(_MARK_APPLIERS)) def test_bare_mark_builds_or_raises_value_error(kind: str) -> None: extra = dict(_MINIMAL_MARK_DATA.get(kind, {})) x = extra.pop("x", [1.0, 2.0, 3.0]) y = extra.pop("y", [1.0, 2.0, 3.0]) mark = xy.Mark(kind=kind, x=x, y=y, props=extra) - try: + missing = _BARE_MARK_RAISES.get(kind) + if missing is None: + assert xy.chart(mark).figure().traces, f"{kind}: bare mark built no trace" + return + # A KeyError here fails the test too: only ValueError is acceptable. + with pytest.raises(ValueError, match=rf"^{kind}\b.*{missing}"): xy.chart(mark).figure() - except ValueError as exc: - assert kind in str(exc) or "links" in str(exc) or "requires" in str(exc) or str(exc) - except KeyError as exc: # pragma: no cover - the defect under test - pytest.fail(f"{kind}: KeyError leaked for missing prop {exc}") def test_bare_scatter_and_line_marks_match_their_factories() -> None: @@ -218,26 +353,52 @@ def _x_categories(values) -> list[str]: return list(fig._axis_categories["x"]) -def test_pyarrow_string_array_is_a_categorical_axis() -> None: +@pytest.fixture +def pa(): + """pyarrow, or skip — only these tests need it. + + A module-level `importorskip` would skip the whole file on the + Python-floor CI job, silently dropping the twenty-one regression tests + below that never touch Arrow. + """ + return pytest.importorskip("pyarrow") + + +def test_pyarrow_string_array_is_a_categorical_axis(pa) -> None: assert _x_categories(pa.array(["a", "b", "c"])) == ["a", "b", "c"] -def test_pyarrow_chunked_string_array_is_a_categorical_axis() -> None: +def test_pyarrow_chunked_string_array_is_a_categorical_axis(pa) -> None: assert _x_categories(pa.chunked_array([["a", "b"], ["c"]])) == ["a", "b", "c"] -def test_pyarrow_dictionary_array_is_a_categorical_axis() -> None: +def test_pyarrow_dictionary_array_is_a_categorical_axis(pa) -> None: assert _x_categories(pa.array(["a", "b", "a"]).dictionary_encode()) == ["a", "b"] -def test_pyarrow_string_array_with_nulls_matches_pandas() -> None: +def test_pyarrow_string_array_with_nulls_matches_pandas(pa) -> None: pd = pytest.importorskip("pandas") arrow = _x_categories(pa.array(["a", None, "c"])) pandas = _x_categories(pd.Series(["a", None, "c"], dtype="string[pyarrow]")) assert arrow == pandas -def test_pyarrow_string_facet_keys() -> None: +@pytest.mark.parametrize("layout", ["string", "dictionary", "chunked"]) +def test_pyarrow_facet_column_inside_mapping_data(pa, layout: str) -> None: + """`by=` naming a pyarrow column of the data table: both the key + factorization and the per-panel row subset take the Arrow-aware path.""" + column = { + "string": lambda: pa.array(["a", "a", "b", "b"]), + "dictionary": lambda: pa.array(["a", "a", "b", "b"]).dictionary_encode(), + "chunked": lambda: pa.chunked_array([["a", "a"], ["b", "b"]]), + }[layout]() + data = {"x": [1, 2, 3, 4], "y": [1, 2, 3, 4], "g": column} + grid = xy.facet_chart(xy.scatter(x="x", y="y"), by="g", data=data).figure() + assert list(grid.labels) == ["a", "b"] + assert [f.traces[0].n_points for f in grid.figures] == [2, 2] + + +def test_pyarrow_string_facet_keys(pa) -> None: """`by=` as a per-row pyarrow string array factorizes like a list would.""" data = {"x": [1, 2, 3, 4], "y": [1, 2, 3, 4]} by = pa.array(["a", "a", "b", None]) @@ -254,6 +415,18 @@ def test_missing_facet_column_is_a_value_error() -> None: xy.facet_chart(xy.scatter(x="x", y="y"), by="zz", data=data).figure() +class _FailingTable: + """Table-like whose lookup fails for a reason that is not 'no such column'.""" + + def __getitem__(self, key): + raise RuntimeError("backend exploded") + + +def test_facet_backend_errors_are_not_mislabeled_as_missing_columns() -> None: + with pytest.raises(RuntimeError, match="backend exploded"): + xy.facet_chart(xy.scatter(x="x", y="y"), by="g", data=_FailingTable()).figure() + + def test_missing_facet_column_in_a_frame_is_a_value_error() -> None: pd = pytest.importorskip("pandas") df = pd.DataFrame({"x": [1, 2], "y": [1, 2]}) diff --git a/tests/test_channel_malformed_messages.py b/tests/test_channel_malformed_messages.py index 84ce49996..b9e310e0d 100644 --- a/tests/test_channel_malformed_messages.py +++ b/tests/test_channel_malformed_messages.py @@ -11,6 +11,7 @@ import math from typing import Any +from unittest import mock import numpy as np import pytest @@ -57,8 +58,33 @@ def _recording_callbacks(fired: list[str]) -> ChannelCallbacks: _NON_STRING_TYPES = [["view"], {"type": "view"}, 3, 1.5, None, b"pick", ("pick",)] +# A JSON client may send an integer literal of any length; `float()` on one +# raises OverflowError, which is neither TypeError nor ValueError. 10**400 is +# the smallest convenient literal past the f64 ceiling that pytest can still +# render as a test id (`int.__repr__` refuses past 4300 digits). +_HUGE_INT = 10**400 + _MALFORMED: list[dict[str, Any]] = [ *[{"type": kind} for kind in _NON_STRING_TYPES], + {"type": "view", "x0": 0, "x1": _HUGE_INT}, + {"type": "view", "x0": 0.0, "x1": 1.0, "px": _HUGE_INT}, + {"type": "density_view", "trace": 0, "x0": 0, "x1": _HUGE_INT, "y0": 0, "y1": 1}, + { + "type": "density_view", + "trace": 0, + "x0": 0.0, + "x1": 1.0, + "y0": 0.0, + "y1": 1.0, + "w": _HUGE_INT, + }, + {"type": "view_change", "ranges": {"x": [0, _HUGE_INT], "y": [0, 1]}}, + {"type": "view_change", "x0": 0, "x1": _HUGE_INT, "y0": 0, "y1": 1}, + {"type": "select", "x0": 0, "x1": _HUGE_INT, "y0": 0, "y1": 1}, + {"type": "select_polygon", "points": [[0, 0], [1, _HUGE_INT], [2, 2]]}, + {"type": "legend_toggle", "trace": 0, "hidden": True, "category": _HUGE_INT}, + {"type": "pick", "trace": 0, "index": _HUGE_INT}, + {"type": "click", "trace": 0, "index": _HUGE_INT}, {"type": "view", "x0": 1e-310, "x1": 2e-310}, {"type": "view", "x0": 0.0, "x1": 1.0, "px": [512]}, {"type": "density_view", "trace": 0, "x0": 1e-310, "x1": 2e-310, "y0": -1.0, "y1": 1.0}, @@ -186,6 +212,40 @@ def test_pick_keeps_advertised_count_bound_when_columns_are_longer() -> None: assert miss is not None and miss[0]["row"] is None +def test_pick_histogram_with_more_bins_than_samples_reads_every_bar() -> None: + # 5 samples over 20 bars: `n_points` (5) is below the row count, and every + # bar is a real mark — the bound is the bin rows, not the sample count. + fig = Figure().histogram(np.array([0.5, 1.5, 4.5, 12.5, 19.5]), bins=20) + fig.build_payload() + t = fig.traces[0] + assert t.kind == "histogram" and len(t.x) == 20 and t.n_points == 5 + hit = handle_message(fig, {"type": "pick", "trace": 0, "index": 15}) + miss = handle_message(fig, {"type": "pick", "trace": 0, "index": 20}) + assert hit is not None and hit[0]["row"] is not None + assert hit[0]["row"]["index"] == 15 + assert miss is not None and miss[0]["row"] is None + + +def test_pick_index_error_from_lookup_still_replies_null_row(monkeypatch: Any) -> None: + # The defensive IndexError path must answer, not drop: a silent drop + # would leave the client's previous hover row on screen. + fig = Figure().scatter(np.arange(3.0), np.arange(3.0)) + fig.build_payload() + + def _raise(self: Figure, *args: Any, **kwargs: Any) -> None: + raise IndexError("column shorter than advertised") + + monkeypatch.setattr(Figure, "pick", _raise) + fired: list[str] = [] + reply = handle_message( + fig, {"type": "pick", "trace": 0, "index": 1, "seq": 9}, None, _recording_callbacks(fired) + ) + assert reply == ({"type": "pick_result", "seq": 9, "row": None}, None) + assert fired == [] + # `click` has no reply to carry the clear, so it stays a silent no-op. + assert handle_message(fig, {"type": "click", "trace": 0, "index": 1}, None) is None + + def test_pick_heatmap_bound_is_the_grid_not_the_edge_columns() -> None: # Grid marks keep only the outer edges in x/y; the readable rows are the # cells, so the bound must not collapse to `len(t.x) == 2`. @@ -226,20 +286,42 @@ def test_density_view_subnormal_span_is_dropped_without_drill_mutation( @pytest.mark.parametrize("span", [3e-308, 1e-300, 1e-200, 1e-100, 1e-20, 1e-6]) -def test_density_view_tiny_normal_spans_reply_or_drop_without_raising(span: float) -> None: - # Spans that survive `normalize_window` but still out-resolve the drill - # ladder (`extent / (pad * span)` overflowing f64, or a sub-ulp block) must - # fall back to the raw window, not raise from `aligned_window`. +def test_density_view_tiny_normal_spans_are_served_from_the_raw_window(span: float) -> None: + # Spans that survive `normalize_window` but out-resolve the drill ladder + # (`extent / (pad * span)` overflows f64) must fall back to the raw view + # window instead of raising from `aligned_window`. + # + # The window is anchored at 0.0, not at some mid-domain value: 50.0 has an + # ulp of ~7e-15, so `50.0 + span` collapses back to 50.0 for every span + # here but the last, and the message would be dropped by the zero-span + # rule without ever reaching the ladder. + x0, x1 = 0.0, span + assert x1 > x0, "span must survive the addition or this case tests nothing" + + calls: list[tuple[float, ...]] = [] + original = lod.aligned_window + + def _spy(*args: float) -> tuple[float, float]: + calls.append(args) + return original(*args) + fig = _density_scatter() fig.build_payload() - reply = handle_message( - fig, - {"type": "density_view", "trace": 0, "x0": 50.0, "x1": 50.0 + span, "y0": 0.0, "y1": 100.0}, - ) - if reply is not None: - entry = reply[0]["traces"][0] - assert entry["mode"] in {"points", "density"} - assert all(math.isfinite(v) for v in (*entry["x_range"], *entry["y_range"])) + with mock.patch.object(lod, "aligned_window", _spy): + reply = handle_message( + fig, {"type": "density_view", "trace": 0, "x0": x0, "x1": x1, "y0": 0.0, "y1": 100.0} + ) + + # A reply, not a drop — proof the request reached the drill path rather + # than dying in validation, which is what made the old anchor vacuous. + assert reply is not None + assert calls, "aligned_window was never reached" + entry = reply[0]["traces"][0] + assert entry["mode"] == "points" + assert all(math.isfinite(v) for v in (*entry["x_range"], *entry["y_range"])) + # The shipped window still contains the requested one (containment is the + # `aligned_window` contract, including on the pass-through fallbacks). + assert entry["x_range"][0] <= x0 and entry["x_range"][1] >= x1 def test_normalize_window_rejects_subnormal_spans_only_when_area_is_required() -> None: @@ -262,15 +344,21 @@ def test_normalize_window_rejects_subnormal_spans_only_when_area_is_required() - @pytest.mark.parametrize( "lo,hi,extent_lo,extent_hi", [ - (1e-310, 2e-310, -1.0, 1.0), # quotient overflows to inf - (0.0, 3e-308, 0.0, 4.0), # finite ratio, level 1024: 2**1024 is not a float - (0.0, 1e-320, 0.0, 1e-300), # subnormal block - (0.0, 1e-10, -1e250, 1e250), # huge reach over a tiny block + # The two hardened branches, at pad=1.0: an infinite extent/span + # quotient, and a finite one whose level still reaches 1024 (where the + # old `extent / (1 << level)` could not build the divisor). + (1e-310, 2e-310, -1.0, 1.0), + (0.0, 3e-308, 0.0, 4.0), + # Deep-but-representable ladder rungs (levels ~67 and ~865): the + # ordinary arithmetic, kept as the surrounding coverage. + (0.0, 1e-320, 0.0, 1e-300), + (0.0, 1e-10, -1e250, 1e250), ], ) def test_aligned_window_extreme_spans_never_raise_and_contain( lo: float, hi: float, extent_lo: float, extent_hi: float ) -> None: + assert hi > lo, "span must be representable at this offset or the case is vacuous" for pad in (1.0, 2.0, 4.0, 8.0): a, b = lod.aligned_window(lo, hi, extent_lo, extent_hi, pad) assert math.isfinite(a) and math.isfinite(b) diff --git a/tests/test_export_text_safety.py b/tests/test_export_text_safety.py index b16e16280..b0e002dd8 100644 --- a/tests/test_export_text_safety.py +++ b/tests/test_export_text_safety.py @@ -22,17 +22,41 @@ import xy from xy._svg import _escape_attr, escape -#: Every code point XML 1.0 cannot carry, as `Char` excludes them. +#: Representatives of every code point XML 1.0 cannot carry. `escape` strips +#: five disjoint regions — U+0000-0008, U+000B-000C, U+000E-001F, the 2048 +#: surrogates U+D800-DFFF, and U+FFFE-FFFF — and this samples each: the C0 +#: controls exhaustively (29 of them, one parametrized case each) and the two +#: larger blocks by their endpoints. Enumerating all 2048 surrogates would add +#: nothing: the helper strips them with one contiguous `range`, so an endpoint +#: pair pins that range's bounds, and the two neighbours just outside it +#: (U+D7FF, U+E000) are in `XML_LEGAL_EDGE` below, which is what an off-by-one +#: would actually break. XML_ILLEGAL = ( [chr(c) for c in range(0x20) if c not in (0x09, 0x0A, 0x0D)] + ["￾", "￿"] - + ["\ud800", "\udfff"] # lone surrogates + + ["\ud800", "\udfff"] # lone surrogates: the block's endpoints ) #: Neighbours the rule must NOT touch: the three legal controls, DEL, the C1 #: range, no-break space (not `isprintable`, so it takes the slow path), the -#: replacement character and an astral code point. -XML_LEGAL_EDGE = ["\t", "\n", "\r", "\x7f", "\x80", "\x9f", "\xa0", "�", "\U0001f600"] +#: code points immediately outside the surrogate block, U+FFFD itself (the +#: replacement character this rule deliberately does not substitute), and the +#: first and last astral code points. +XML_LEGAL_EDGE = [ + "\t", + "\n", + "\r", + "\x7f", + "\x80", + "\x9f", + "\xa0", + "\ud7ff", + "\ue000", + "�", + "\U0001f600", + "\U00010000", + "\U0010ffff", +] def _ident(ch: str) -> str: @@ -69,6 +93,26 @@ def test_escape_keeps_every_legal_neighbour(ch: str) -> None: assert escape(f"a{ch}b") == f"a{ch}b" +def test_the_stripped_set_is_exactly_the_xml_char_production() -> None: + # The sampled tables above are representatives; this is the exhaustive + # statement they stand in for, checked against XML 1.0 §2.2 `Char` over + # every code point. It is what makes endpoint sampling sufficient. + from xy._svg import _XML_ILLEGAL + + def legal(cp: int) -> bool: + return ( + cp in (0x09, 0x0A, 0x0D) + or 0x20 <= cp <= 0xD7FF + or 0xE000 <= cp <= 0xFFFD + or 0x10000 <= cp <= 0x10FFFF + ) + + assert {cp for cp in range(0x110000) if not legal(cp)} == set(_XML_ILLEGAL) + # ...and the sampled tables really do land in that set, and outside it. + assert all(ord(ch) in _XML_ILLEGAL for ch in XML_ILLEGAL) + assert all(ord(ch) not in _XML_ILLEGAL for ch in XML_LEGAL_EDGE) + + def test_escape_still_escapes_markup_around_dropped_characters() -> None: assert escape("\x01&\x02<\x03>\x04") == "&<>" assert escape("") == "" diff --git a/tests/test_legend_hidden_hover.py b/tests/test_legend_hidden_hover.py index 66a6d1a32..f90bff88b 100644 --- a/tests/test_legend_hidden_hover.py +++ b/tests/test_legend_hidden_hover.py @@ -195,3 +195,176 @@ def test_hidden_category_points_do_not_hover(tmp_path: Path) -> None: assert result["restoredN"] == len(ROWS), result assert result["restored"]["neighbour"]["target"] == HIDDEN_WITH_NEIGHBOUR, result assert "beta" in result["restored"]["neighbour"]["tooltip"], result + + +# -------------------------------------------------------------------------- +# Scope tripwires for the two paths the CPU hover fallback deliberately does +# NOT guard. Both hold because a categorical color channel is unreachable +# there; if either fact changes, the hover fallback needs the guard and these +# fail pointing at it (js/src/50_chartview.ts `_cpuScanLimit` / `_barHover`, +# interaction spec §10). +# -------------------------------------------------------------------------- + + +def test_bar_marks_cannot_carry_a_categorical_color_channel() -> None: + """So a bar trace never has category legend rows to toggle. + + `_filterScatterRows` is gated on `colorMode === 2`; the client builds + category legend rows only for `color.mode === "categorical"`. No + bar-emitting mark produces one — bar colors resolve to per-series + constants or direct RGBA — so a bar's legend rows are whole-trace rows, + which `_hoverAt` already skips via `_legendHidden`. Hence no hidden-row + test inside `_barHover`. + """ + from xy._figure import Figure + + builders = { + "bar": lambda f: f.bar(["A", "B", "C"], [3.0, 5.0, 2.0]), + "barh": lambda f: f.bar(["A", "B"], [3.0, 5.0], orientation="horizontal"), + "grouped": lambda f: f.bar(["A", "B"], [[1.0, 2.0], [3.0, 4.0]], series=["a", "b"]), + "stacked": lambda f: f.bar( + ["A", "B"], [[1.0, 2.0], [3.0, 4.0]], series=["a", "b"], mode="stacked" + ), + "per_series_css": lambda f: f.bar(["A", "B"], [3.0, 5.0], color=["red"]), + # Numeric RGB(A) per item -> direct_rgba, the other per-row bar paint. + "direct_paints": lambda f: f.bar( + ["A", "B"], [3.0, 5.0], color=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) + ), + } + for label, build in builders.items(): + fig = Figure() + build(fig) + for trace in fig.build_payload()[0]["traces"]: + if "bar" not in trace: + continue + mode = (trace.get("color") or {}).get("mode") + assert mode != "categorical", (label, trace.get("color")) + + +def test_append_rejects_categorical_color_so_a_live_filter_cannot_go_stale() -> None: + """So `_visInv` can never be outrun by rows appended under a live filter. + + `_filterScatterRows` (and the `_visInv` the hover scan is bounded by) runs + only on a categorical color channel; `append_data` rejects exactly those. + A trace is appendable or category-filterable, never both. Lifting that + restriction means re-filtering on append — see `_cpuScanLimit`. + """ + from xy._figure import Figure + + fig = Figure() + fig.scatter(np.arange(4.0), np.arange(4.0), color=np.array(["a", "b", "a", "b"])) + fig.build_payload() + assert fig.traces[0].color_ch.mode == "categorical" + for kwargs in ({}, {"color": ["a"]}): + with pytest.raises(ValueError, match="categorical color channels"): + fig.append(0, [4.0], [4.0], **kwargs) + + +_BAR_PROBE = """ + +""" + + +def test_hidden_bar_series_does_not_hover(tmp_path: Path) -> None: + """The bar guarantee that does exist: a whole-trace legend hide takes the + series out of draw, pick and hover, and leaves its neighbours alone.""" + chromium = find_chromium() + if chromium is None: + pytest.skip("Chromium unavailable") + chart = xy.bar_chart( + xy.bar( + x=["A", "B", "C"], + y=[[3.0, 5.0, 2.0], [4.0, 1.0, 6.0], [2.0, 3.0, 5.0]], + series=["s1", "s2", "s3"], + ), + xy.legend(), + width=520, + height=340, + ) + result = run_browser_probe( + chromium, + probe_document(chart, _BAR_PROBE), + tmp_path / "bar_hidden_hover.html", + "data-xy-bar-hidden", + label="hidden bar series hover", + ) + assert result["legendNames"] == ["s1", "s2", "s3"], result + assert result["catRowCount"] == 0, result # whole-trace rows, not category rows + assert result["middleBefore"] == {"trace": 1, "index": 1}, result + assert result["lastBefore"] == {"trace": 2, "index": 1}, result + # Hidden series: out of draw/pick and out of hover. Bars never join the + # GPU pick pass (no `pointPick`), so `_hoverAt` is the entire hover path. + assert result["hiddenFlag"] is True, result + assert result["pickAtHidden"] is None, result + assert not result["pickCountRaw"], result + assert result["middleAfter"] != {"trace": 1, "index": 1}, result + assert result["middleAfter"] is None or result["middleAfter"]["trace"] != 1, result + # Its neighbour is untouched. + assert result["lastAfter"] == {"trace": 2, "index": 1}, result diff --git a/tests/test_log_ticks_within_decade.py b/tests/test_log_ticks_within_decade.py index b85670ea8..a74c4b760 100644 --- a/tests/test_log_ticks_within_decade.py +++ b/tests/test_log_ticks_within_decade.py @@ -170,7 +170,7 @@ def test_py_within_decade_falls_back_to_linear_ticks() -> None: def test_ts_and_py_generators_agree() -> None: """Same positions, same step, same label text on both sides — the static exports must tick the axis exactly where the browser does.""" - cases = [*WIDE, *NARROW, (0.2, 0.7), (2, 30), (0.5, 5), (3.0, 3.0)] + cases = [*WIDE, *NARROW, (0.2, 0.7), (2, 30), (0.5, 5), (3.0, 3.0), *SUBNORMAL] js_results = _node_log_ticks(cases) for (lo, hi), js in zip(cases, js_results, strict=True): py = _py_log_ticks(lo, hi) @@ -182,6 +182,24 @@ def test_ts_and_py_generators_agree() -> None: assert 1 <= len(js["ticks"]) <= 200 +# Positive subnormal windows: `(b - a) / target` underflows inside the linear +# fallback (a 1-ulp span / 6 is 0), so it yields nothing; the window's own +# endpoints stand in as the ticks. Both are formatted exponentially. +SUBNORMAL = [(1e-323, 1.5e-323), (5e-324, 1e-323), (2.5e-323, 4e-323)] + + +def test_subnormal_window_ticks_its_endpoints() -> None: + js_results = _node_log_ticks(SUBNORMAL) + for (lo, hi), js in zip(SUBNORMAL, js_results, strict=True): + py = _py_log_ticks(lo, hi) + for got in (js, py): + assert got["ticks"] == [lo, hi], (lo, hi, got) + assert got["labels"] == [lo, hi], (lo, hi, got) + assert got["step"] == hi - lo > 0, (lo, hi, got) + assert len(set(got["text"])) == 2, (lo, hi, got) # two distinct labels + assert py["text"] == js["text"], (lo, hi, js, py) + + def test_within_decade_always_shows_a_readable_tick_count() -> None: """Every within-decade window a zoom can land on gets 3..8 ticks at the default target — the failure mode was zero.""" diff --git a/tests/test_pdf_export.py b/tests/test_pdf_export.py index 7afcd71d2..2980b0dc4 100644 --- a/tests/test_pdf_export.py +++ b/tests/test_pdf_export.py @@ -378,14 +378,29 @@ def test_the_selected_face_metrics_drive_the_anchor() -> None: assert _text_width_px(b"iii", 10.0, "Courier") == 18.0 # 600 per mille, every glyph assert _text_width_px(b"iii", 10.0, "Helvetica") == pytest.approx(6.66) # 222 x 3 assert _text_width_px(b"iii", 10.0, "Times-Roman") == pytest.approx(8.34) # 278 x 3 - # Oblique faces share their upright advances. - for face in ("Helvetica", "Times"): - upright, slanted = { - "Helvetica": ("Helvetica", "Helvetica-Oblique"), - "Times": ("Times-Roman", "Times-Italic"), - }[face] - assert _text_width_px(b"W", 10.0, upright) == _text_width_px(b"W", 10.0, upright) - assert _text_width_px(b"Wm", 12.0, slanted) > 0 + # The Oblique faces are slanted copies of their uprights and share their + # advances glyph for glyph (Adobe core-14 AFMs)... + sample = b"Wiam 0.5" + for upright, slanted in ( + ("Helvetica", "Helvetica-Oblique"), + ("Helvetica-Bold", "Helvetica-BoldOblique"), + ("Courier", "Courier-Oblique"), + ("Courier-Bold", "Courier-BoldOblique"), + ): + assert _text_width_px(sample, 10.0, slanted) == _text_width_px(sample, 10.0, upright) + # ...whereas Times-Italic and Times-BoldItalic are their own designs with + # their own AFM tables, so the writer must not borrow the upright widths. + # Per-mille advances from matplotlib's bundled Times-*.afm: W 944/833, + # a 444/500, m 778/722 (Roman/Italic); W 1000/889 (Bold/BoldItalic). + assert _text_width_px(b"W", 10.0, "Times-Roman") == pytest.approx(9.44) + assert _text_width_px(b"W", 10.0, "Times-Italic") == pytest.approx(8.33) + assert _text_width_px(b"am", 10.0, "Times-Roman") == pytest.approx(12.22) # 444 + 778 + assert _text_width_px(b"am", 10.0, "Times-Italic") == pytest.approx(12.22) # 500 + 722 + assert _text_width_px(b"W", 10.0, "Times-Bold") == pytest.approx(10.0) + assert _text_width_px(b"W", 10.0, "Times-BoldItalic") == pytest.approx(8.89) + assert _text_width_px(sample, 10.0, "Times-Italic") != _text_width_px( + sample, 10.0, "Times-Roman" + ) # End-anchored y tick labels start elsewhere once the face changes width. xs = np.linspace(0.0, 6.0, 50) sans = xy.line_chart(xy.line(xs, np.sin(xs)), width=400, height=300).to_image("pdf") From 6599e2be963810256835102d9beefe478833ce6a Mon Sep 17 00:00:00 2001 From: Alek Petuskey Date: Tue, 1 Sep 2026 23:39:50 -0700 Subject: [PATCH 5/7] Put bar tick_label ticks at the input positions, and assert real browser/SVG tick parity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `bar(align="edge", tick_label=[...])` passed the edge-shifted bar centers to the tick-label helper, so every label sat half a bar width off. The shift is bar geometry; matplotlib puts one tick per position the caller passed under either alignment. Verified against matplotlib 3.11 for both alignments, three widths, and barh. - The log-tick test checked the browser labels and the SVG labels independently against the same set of valid densities, so it would have passed with the two disagreeing — which is exactly what its comment claimed it ruled out. The SVG assertion now compares against what the browser actually produced; it passes, so the parity is real rather than assumed. --- python/xy/pyplot/_axes.py | 6 +++- spec/matplotlib/compat.md | 2 +- tests/pyplot/test_p1_kwargs_legend_subplot.py | 35 +++++++++++++++++++ tests/test_log_ticks_within_decade.py | 9 +++-- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/python/xy/pyplot/_axes.py b/python/xy/pyplot/_axes.py index c3d6c63c9..c9a3281bf 100644 --- a/python/xy/pyplot/_axes.py +++ b/python/xy/pyplot/_axes.py @@ -2489,6 +2489,10 @@ def materialize_iterable(value: Any) -> Any: ) from None if not np.isfinite(thickness_value).all() or np.any(thickness_value <= 0.0): raise ValueError("bar thickness values must be finite and positive") + # `tick_label` ticks belong at the positions the caller passed, not at + # the bar centers `align="edge"` derives from them (Matplotlib puts one + # tick per input position under either alignment). + tick_label_positions = cats if align == "edge": try: cats = np.asarray(cats, dtype=np.float64) + thickness_value / 2.0 @@ -2580,7 +2584,7 @@ def paint(value: Any, label_text: str, default: Optional[str] = None) -> Any: container = BarContainer(self, entry) container.errorbar = errorbar if tick_label is not None: - self._apply_bar_tick_labels(cats, tick_label, n_bars, orientation) + self._apply_bar_tick_labels(tick_label_positions, tick_label, n_bars, orientation) return container def _apply_bar_tick_labels( diff --git a/spec/matplotlib/compat.md b/spec/matplotlib/compat.md index 077374796..c5db99d91 100644 --- a/spec/matplotlib/compat.md +++ b/spec/matplotlib/compat.md @@ -52,7 +52,7 @@ dependency-free `triangles=` shorthand into Matplotlib's equivalent |---|---| | `plt.plot` / `ax.plot` | format strings (`'r--o'`), multiple series per call, implicit x, `label=`, `lw=`, `ls=`, `alpha=`, marker face/edge styling, directional `^`/`v`/`<`/`>` triangles and distinct `+`/`x` glyphs, `markevery`, and dependency-free affine *data* transforms (`Affine2D + ax.transData`); axes/figure-fraction transforms on data artists, partial fill styles, and cap/join policies fail loudly | | `scatter(x, y, s=, c=, cmap=, vmin=, vmax=, alpha=, marker=, edgecolors=, facecolors=, plotnonfinite=)` | `s` (pt², area) maps to pixel diameter; `facecolors=`/`facecolor=` is the fallback face paint when `c` is absent (`facecolors="none"` draws hollow markers, as `c="none"` does); numeric 1-D `c` remains a colormap encoding, while `N×3`/`N×4` face and edge colors, alpha arrays, sizes, and linewidth arrays stay in one collection. Explicit alpha replaces intrinsic RGBA alpha, matching Matplotlib; custom norms/marker paths fail loudly | -| `bar`, `barh`, `grouped_bar`, `bar_label` | string categories (also with `xerr=`/`yerr=`: the error-bar centres autoscale on the category axis), `tick_label=` on numeric positions (one labeled tick per bar; with string categories it fails loudly), `log=True` (value axis on a log scale), stacking bases, per-bar face/edge color-alpha pairs and linewidths, plus iterable/indexable `BarContainer.patches` views whose setters mutate the parent batched trace and whose `get_x`/`get_y`/`get_width`/`get_height`/`get_xy`/`get_center`/`get_bbox` report Matplotlib's rectangle geometry in data space (category positions resolve to 0, 1, 2, ...), so the `ax.text(r.get_x() + r.get_width() / 2, r.get_height(), ...)` labeling idiom works | +| `bar`, `barh`, `grouped_bar`, `bar_label` | string categories (also with `xerr=`/`yerr=`: the error-bar centres autoscale on the category axis), `tick_label=` on numeric positions (one labeled tick per bar, at the positions the caller passed — `align="edge"` offsets the bar geometry, never the ticks; with string categories it fails loudly), `log=True` (value axis on a log scale), stacking bases, per-bar face/edge color-alpha pairs and linewidths, plus iterable/indexable `BarContainer.patches` views whose setters mutate the parent batched trace and whose `get_x`/`get_y`/`get_width`/`get_height`/`get_xy`/`get_center`/`get_bbox` report Matplotlib's rectangle geometry in data space (category positions resolve to 0, 1, 2, ...), so the `ax.text(r.get_x() + r.get_width() / 2, r.get_height(), ...)` labeling idiom works | | `hist(bins=, range=, density=, cumulative=, weights=, orientation=, stacked=, bottom=, align=, log=)` | Returns computed counts/edges (raw counts even with `bottom=`); `bottom=` lifts the baseline (scalar or per bin) and seeds the stack, `align="left"`/`"right"` centre bars on the bin edges (step histtypes accept only `"mid"` and fail loudly otherwise), `log=True` puts the count axis on a log scale; stacked density normalizes the combined weighted area once (including unequal bins and either cumulative direction), matching Matplotlib 3.11; bar, step, and stepfilled families render in both vertical and horizontal orientations; unfilled step outlines connect their top envelope to zero or the previous stack at both endpoints | | `hist2d`, `hexbin`, `ecdf` | 2D uniform binning uses the native Rust kernel. `hist2d` delegates rendering to the pseudocolor-mesh path for both uniform and non-uniform bins, supports linear and logarithmic normalization, defaults to fully opaque cells, and retains the original count domain for logarithmic mappables. Its view limits are the outer bin edges with no margin, matching Matplotlib's sticky mesh edges. Arbitrary custom normalization and `colorizer` remain unsupported. Hexbin uses Matplotlib's two-offset-grid nearest-center assignment and six-triangle data-space cells, supports `C`, arbitrary scalar reducers, and `mincnt`, and retains only the bounded lattice rather than source points. `ecdf` carries the ordinary margin on the sample axis and is sticky at 0 and 1 on the cumulative axis | | `boxplot`, `violinplot`, `bxp`, `violin`, `errorbar` | Boxplots support notches, bootstrap/user confidence intervals, median overrides (drawn median only; notch CIs stay data-derived like Matplotlib), percentile/custom whiskers, cap widths, `sym`, dashed line-component styles, and component colors/widths/alpha. Default boxes are unfilled outlines and return Matplotlib-shaped per-group component handles (two whiskers/caps and one box/median/flier handle per group). `patch_artist=True` emits mutable filled polygon boxes; statistics labels become category tick labels, while scalar or per-box legend labels bind to boxes for patch plots and medians otherwise. Violins use Gaussian KDE for the default Scott bandwidth and explicit Scott/Silverman/scalar/callable bandwidths, return one seam-free mutable body per group, cycle face and line color sequences, preserve color-alpha pairs, and support quantiles and low/high sides. `boxplot` autoscales its value axis over the Tukey whiskers plus, when `showfliers` is on, the flier points. Its default category positions are 1-based and `manage_ticks=True` reserves half a unit around the outer positions, matching Matplotlib | diff --git a/tests/pyplot/test_p1_kwargs_legend_subplot.py b/tests/pyplot/test_p1_kwargs_legend_subplot.py index 07445ddc7..04df4bea8 100644 --- a/tests/pyplot/test_p1_kwargs_legend_subplot.py +++ b/tests/pyplot/test_p1_kwargs_legend_subplot.py @@ -713,3 +713,38 @@ def test_hlines_vlines_colors_read_names_first_and_rgba_tuples_whole(colors, exp _fig, ax = plt.subplots() assert ax.hlines(0.5, 0, 1, colors=colors)._entry["kwargs"]["color"] == expected assert ax.vlines(0.5, 0, 1, colors=colors)._entry["kwargs"]["color"] == expected + + +@pytest.mark.parametrize("align", ["center", "edge"]) +@pytest.mark.parametrize("width", [0.8, 0.5, 1.0]) +def test_bar_tick_labels_sit_at_the_input_positions(align: str, width: float) -> None: + """`align="edge"` moves the bars, never the `tick_label` ticks. + + The edge shift is a bar-geometry offset; matplotlib puts one tick per + position the caller passed under either alignment, so passing the shifted + centers put every label half a bar width off. + """ + mpl = pytest.importorskip("matplotlib.pyplot") + + reference, ax = mpl.subplots() + ax.bar([0, 1, 2], [1, 2, 3], width=width, align=align, tick_label=["a", "b", "c"]) + expected = [float(v) for v in ax.get_xticks()] + mpl.close(reference) + + _fig, ours = plt.subplots() + ours.bar([0, 1, 2], [1, 2, 3], width=width, align=align, tick_label=["a", "b", "c"]) + assert [float(v) for v in ours.get_xticks()] == expected + assert [t.get_text() for t in ours.get_xticklabels()] == ["a", "b", "c"] + + +def test_barh_tick_labels_sit_at_the_input_positions() -> None: + mpl = pytest.importorskip("matplotlib.pyplot") + + reference, ax = mpl.subplots() + ax.barh([0, 1, 2], [1, 2, 3], height=0.8, align="edge", tick_label=["a", "b", "c"]) + expected = [float(v) for v in ax.get_yticks()] + mpl.close(reference) + + _fig, ours = plt.subplots() + ours.barh([0, 1, 2], [1, 2, 3], height=0.8, align="edge", tick_label=["a", "b", "c"]) + assert [float(v) for v in ours.get_yticks()] == expected diff --git a/tests/test_log_ticks_within_decade.py b/tests/test_log_ticks_within_decade.py index a74c4b760..2b4091bd3 100644 --- a/tests/test_log_ticks_within_decade.py +++ b/tests/test_log_ticks_within_decade.py @@ -284,8 +284,11 @@ def test_browser_log_axis_zoomed_inside_a_decade_keeps_ticks(tmp_path: Path) -> } assert tuple(narrow) in py_options, (narrow, py_options) - # The SVG export of the same window ticks it the same way (raster shares - # `axis_ticks`, so PNG/PDF follow). + # The SVG export of the same window ticks it *identically* — not merely at + # some valid density (raster shares `axis_ticks`, so PNG/PDF follow). The + # browser check above has to allow any density an axis of this size could + # ask for, because the test cannot know the live plot width; this one + # compares against what the browser actually produced. svg = xy.line_chart( xy.line(x=xs, y=[float(i) for i in range(25)]), xy.x_axis(type_="log", domain=(0.3, 0.35)), @@ -294,4 +297,4 @@ def test_browser_log_axis_zoomed_inside_a_decade_keeps_ticks(tmp_path: Path) -> ).to_svg() svg_labels = _svg_x_tick_texts(svg, 0.3, 0.35) assert 3 <= len(svg_labels) <= 8, svg_labels - assert tuple(svg_labels) in py_options, (svg_labels, py_options) + assert tuple(svg_labels) == tuple(narrow), (svg_labels, narrow) From 21ef2fc388618c9e432f3d4728d177e82049cd09 Mon Sep 17 00:00:00 2001 From: Farhan Ali Raza Date: Tue, 27 Oct 2026 14:00:21 +0500 Subject: [PATCH 6/7] Remove local validation artifacts from the source tree --- node_modules | 1 - python/xy/_native_lib/libxy_core.so | Bin 1304808 -> 0 bytes 2 files changed, 1 deletion(-) delete mode 120000 node_modules delete mode 100755 python/xy/_native_lib/libxy_core.so diff --git a/node_modules b/node_modules deleted file mode 120000 index f25e2d555..000000000 --- a/node_modules +++ /dev/null @@ -1 +0,0 @@ -/tools/node_modules \ No newline at end of file diff --git a/python/xy/_native_lib/libxy_core.so b/python/xy/_native_lib/libxy_core.so deleted file mode 100755 index e90938f9a4d361b08eca60ec239f229918d8b33b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1304808 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

s?dmMJh57ryP^}z-+$iYS|;o&Db zBtjpmGva|%C`ImTK!+2@AGZa^#~Kq8Os3EfT`0Ujq&^GQINl7*gqae$0$6LE5kFWc zHDP6yhl({s!B%7cPGq>r7^;tsHHGpUY`fyVkrBE`1NlT@jRwy~2{jq9|h?9*+McVujpgi)6e&Ep#J zoD;=m2n#bs8)=6g3C$5+3Nn_clW7*-GDl9N+$jhYEil=O;bn}5IEGLekBN_sL8f^KQQFF# zC~xJK*2crRl4K7{LCd#tQA5!fmqZKAVJs6DLSu_4On4GwO=dl&`nujI9W)$NTr?0| zP%Zfn#&jrLs+RIE5|c&6qPX6oY<@$vm=KE)bYl@AMi-+?)PYG%3_aV3!T3GKlpq(j zUd}N!)Q}LJxCw=9iM&b1ni6$fw`Qzm8c`|nR9r4EGj=)1Vax`7bhOTFFk*FHso0j* z!4awj3ZhRmTQz4XxHwpl2rXi4S(7@>L05^NmC0^5%^ZpOeqP5(6|UCFpsYGut`czLrpfv=t58*l-O~mm`ns9 z-%PkG$&l1AaPd*m{^7b9w6{2a8gm1WfC-JjlN>BRLq8Z2`zze2YWvGn)a-BrsyY2C zDo}1HCko1$D>#I~ZUal~e*RnxR8ZjsjC*0y$N8AT!XSXSzU{uobWk@CRT!U9IFU=Ls~;7`Cl zz+ZsB0s8?500#l|*4<&i5dhxiVaEW+0Ve<_0jB_`0cQYb0p|ec0T%!l0ha)m0apN5 z0oMT60XG0Q0sjDQ0d52C0PX^k0rvp+0S^EV0V#k-fX9GTz*E38z;nP0KpG$&AORQ# z1R8)Hz#iZLa0EC3oB=KXR{$N$>JIP#cmlit-he!SyZ{_a%JKnx0e*n|fC7MmfI@)6 zfFgjRfMS5+fD!;Lpd_FafL=5#11Jk92PhAy0HAlADgi13ssQ`}RRIBjKtMG>bwCXO zz28M|Wz`1M0n`Q51JnmJ05k;9tFVm$O#n>+%>eHK-Ul=Xd;n+x_z=(%@DZRDpf#Wk zpe>*spgo`ipd;X8KqmmsdthAvp8&c7=>7gr0o?(g0eS#>0zL->0eS&+fM7rf056R* zJs=Da4u}940KEZ`03#p@5DhQ^VgP*ru>dn54iFFM3rGO;10(|a1HJ$Z01N~S0t^O> z!vOCmz(l~WfGL1!fEj>UfZ2e#fO&vr0Qxxf3ILtBwFuumP|UunDjk zumz9=*b4XqupO`iuoJKgup6)k5RCIPLI9xvJs_VJ^$AcAPzX>IPz<02lmwIllmi3; zVgP*rae#P0UqAw&A0QFXAMgcW0AL_s5MVH12w*7SOTaL|aKH$_SAeepBLUw4MghJB zj0SuM_#W^BU@YKAz&OCqfboC{fQf)#0FwZ}0wx1y0A>Pa1Lgtd0~P=l0u})l1C{}n z16Bgo0oDUH0k!~sC<$HwyHaSI02hD{ARnMGpctSypfaE(pcg;~2nFZ?tTg<}LB{|+ zAPkTOBj5;9R?Z0o0uLoX3f_Yvv?ah<0X2>MI|DowaL1M0BgC7G>llEW0%DFqX;RxB z4S#P1)M>5(Z6*B4PXJIx@gnV@7vK&GsN+2cEfD@94>tTz-$>5PXmmay(OeWzr+FB( zUho(B6Z54fkfjEMhzE`INkB4@O9yQ(ZhV0YenRK;S^ABj6$eekgV@|ryi=f&zKBL~ zi7z?I`xVgI0T=pI%UK-}`ei|zpAD@Pm}C`iQZ_UnREDhLjmm~*2PJ0}uYWeQ2ieei zqfjVKp-(DDa;ebSCD1AW7c|lxIik7YraJJ<%C;eBRJMXfb)Ou)`MC_V&wvY>x=whY z0Z=@Wf&A5FG!!%={PHLu>L<08JD^>FKeZnMbv*h|@bD~X9U(+kw4(}*(h>la*QHOv zoZ1oTgFwyiCTOHjl0Rb}bZD?fC49y-{{oHD6#nWodm__B6Xl?$-2ttkLZdoQHUTP; zsLof+i@p^1Bx6Rs3Fh%^cG8)MM?A?<9=3qC8hB=98}BFQA+t1}f+pIE$h*)>pZsz>A-`JAN1&0eGvha+ zfE*7h=k-t>&$S?9Nm<0(0~+aCT@FH)wuNL`X8aB+G%8mDwO+aumhCRp38Ini$dS(G zfz}RqX7QdV@r16`d1zfkE+cAxB&!2};hoE~G#n=meq8zABks~{w z0Gg5j2seI^HDEMA;Hu9nS}y1Mw4iSI0Ag)-sbcNzRp^ zsnb-)t5QOykv<62w3(mh^a8wASz=`7-9cgf{CmX-q_Eih8Eb-!9O808Qvc zP3wyBj#}4h+OiBZkq64VJH|Vi<(+856dKuZ0(F|tL2Cj(Q76>2`lV%Ei*lg)O^)pK zm!Q1|JhMD(2aWPTX$b(z>r(MDa-9%$SIy4^8uc9_j+%Bwi6?04yw@r#+q%s1@H=Sg z`a)$(j@sBw(8dF&GAE$2B1g2rvrl}*ZX=O&+o(=8mx>?6-RWECrXMI~5l?OR$ zw+BF@b|hpGb)Nd$j~mEiB9U)(9$XsQ&i~Z3joHv*8f6`?OkOI`X_9@Z_hIJtnrK5oQ|nVL=hF-{b>92H zAXA;sOlJ?Xp~Zh>8&A#e320f#VrpeeqqxJ^SA2gvCK}Rs&j}7Z;+mESb$=A)cPN-=!KqGw$U8~Ez$fvSB6EtAe!Z+woPtL6Y@;e3#U(pKj_Rkg0ng@u3)>^& z5x>fykxkBwwp^hRKgu7L+AL*MueWS_gkGrJksQz8EYN!4UX+oj6U5IkQnuH`PhCHW zwhFXq@E0_?lA}CyG1|_cOF*MMWYihaYDZbuJSaW2EJH#2L5W9k)wI0Pc)kcf zibJ5TXB|NUORf{=475$4!DMF|FRw|CC-kXKb0BC`2Z;{~ID{!sB#$19sC$IA;kfm)V1pzVVn>7RhgpB&}S++VJrq8+LE z*?%G1NUDD>05!k4purqu+WztkklP={BM|Y3UlM5O0xj{>{E7^;@>9nndzJ(m#S=QS zi8n~@J4nWiaxMdn&p_*sGgC( zpiw-kOP$BaG#A_xsPq05v6B@MvI(a+yANgIZw3h14wt|sD4fWEd;p8 zpSmtR18o{;8FfwZCjBDoTEtWHbDAXQPsCI68w6TMRhptsP&?WW8k)657Lg|L`{Y-v z&NAxrZ-wTFxCCl`Eub)e#gF2tX=c#6D}LlJ_>nAsfo6nX#{7{i^?u7bf6GA2Dt~rU zZ1bm<=C*d9uk9PPy^GedqROznU`O=|;M2gQ&4Mc%2tOa`rC7PJ!z zP4H94^PMT%$joSQ8EB#(BYsCfivd3oPfcq+OQwl3qA=uWkIPEXS^^jOv*Q$bkJ1a! zw74gI6R71ZI$Pd5Ds-);6`UidX^%JrYFaPQs2nnjH(ZIA8Es!SG~c;0zs%zG$c8pE z8`^D!<^ov>sP2=aF;UHV*vAQ6(A0HzG-xeVG-|)(Xub6aXjESu6d=1zj{4~`^RZVI zcxJS23Qgoso#trJsGbR$GbIQ|ZDluTm4IhPdyoyS=z^@{waA7RlMQWBHni>8(C%hK zE4VOgIp0%gqKrrfBDmMZ(tpjLOeuAc!r9Wt;RWxf;|J1Y*+0fDyny`cFc=1aaOG5gdDges))mmm9mycxH0;UT&4s9bwe`E`c^&iIpka8EshmHpvQ1OX&trAgwBZ?OLN8=LUw}3m{DeM5ouE26a*aIJ&y03Yp;34O zAq%D1ZLQpI3Vjg`-h2$b7PKF5Pcjgw^WJiuyrv`gsq1b!Xw8)HM5naL5x*wut$UZr zU!+O8{#&7uKY==bJvYdGhv28CtpY7V2~Ylc0puvnVjHpd9Jq)lY!8j4W`P!;1+DNV zTbi2R7|@7cW@$dj5Kqm|xLHn9)N8tuBUvtj77ASGT9gshvk$h&^Zv|ece0`VoRoFE zMq6bXwOi7c&>78PuYyMJl63ntsMAMno5v*L%r+bXAinH?gX`#Re!PVlhcg23)c`GS zfc4emwLX;(-oU~k0o-48?pF-nhg8lkc)xw~P8~k@pn1>-?LK+=sD%U^K@g}dS56xt zkbc#I!sCMa1y<-6SVh~fT16sS{1V}pSgm5PAv&mfXb{fJ(&BX|oP%sRAmL>W(Kvns zC+Xt|VQ}hK&2l6|7###i2b$9<2>k-(Br_(5*Smt~jMjJ_Ny8!Z@3K{y0A!VuKYRuk|~>Z4-f5~FHn4D+&}C5_MzPTJrRpd^$v z`N$e;*hpKwR&9FA(S-LQqpFAgdwQ0NVlh5FRAGmk%Snr|r9O?PM^K-9#UJbn$dzZ{JA&*zy zk$LTXhWN02L-RTKe&d_RZ<1fx{LAwVw$!?NrzJFO2w3}ROV`#8D&Gul`DU%{IUvPRBTbnxANu6tE-Ii*Hx__;1~EH z@KCjt)qklmq^6-(m)h^usZqCVy~6c<8n`!fZsgS1xrtlTJk1KeSNi?H=1o56*h2r| zfR;ahw5-+s*7w@vYgezmuEXe#>ps5OsYsU&pM2eQYq#`I8+|sY$F`oXK_B;;qPr8^ zICQN3Mp)B`$%bdWKQnHQDr5RCCbdtP`FLEbzDWu75?A)GK48VbI)gV2Y4PR3VL>DA zeKmY!kx?tZ?eJal_donl>&G+WzWTZPgi8~Dn)K0R&6EvO6MwHa#MLG+ZbW=>72(A7-@*$%;%W)6vDawqn4P_yoxR51Vi_{l^hlf+ z03(I7Ml-YxrMX7o{DmO7pI6!ly^=M_uE~zcp2_yf?#a%{-X&NGml6&oJWAM=a4X?d!mEU)glh@M5}qaO zOSqSCF5x|uO?8>-Fx6wK-Bh=!PE)<6YNonQb)4!s)qbk`ROhMQK`h86$RWrh$S%k& z$SKGxNE755iE9(bCZ0{~o47Y|ZsNU#ZE@M+u*GAG-4?ekPFuXT zXtua+aopm$#eR$X7UwPAgV|u0!488x2HOpG8|*aLYp`ap>tM&ho`dZNyAO6A>@Be| z_G6sev-S?{?bMzh8~fhE`_XcFw7uqSp;G~t@-?7F4^-o@U) zCa^E?4!ASc*gwQRxm+ILOw{J;<y`D$$c{50AB<=15YS3r~fUqMaw ze}yzT`zx%;*0>5^~g=s2%kz**WTUa^k4RdW%lv9#ucNL z{6QVo4RE9`eGEYUh7TR$k3->O4E^**EkB?Ha#)HBI5{yc6#f~hLvMu_L5xO|H9Rh(Z2NA+0ks7|Y$sNdo$>Umbz4AuXo+YHU& zrQ3gN9xpdlqsbJh!wFiL7||iFSh>T3R8X8L2;Z>EWSJ(|fW<{D(^RNX4U0P3hWuMr z6}A3ax~&Lv!tEW|me;k*lmw(-T%LK)PkLu7W+W7YzW=hG5a%g@E6?pK<9)iI)hBjB4^*S2cCw%(BEA|aPJmSzgZG`8c$W?B$p3PlV z%Q$iQd&l-{INkK=#)X%SC#uKyIRC+Z&tqpkZFF$K!oZW|>a%klhjcu?JHPJ0mQ^V$ zOP1cg;*(!~UccXa)~2;n*4kBY8R;0b{G`XuGB@3qeLcVwkhe`lw*|#?TO0X@t^T3e znZ8baPHQ%54^6C;=V~ZK5ppf1V`OBo&RFzBpngO<7X0AO&rZfKW@(CSO>z0M>vr!)J5Mgv zceuI6=byEkza21g-HY?Z&IW(vf6DLSfWxEpZH_$erd!_j?~beL$FYqwE(LBl(rniG zR>yxn(I{&B!I{rfjvelO)A0U_lhHL>j0|6NU~R8cW`Bp~SBu%#2x{Xtf6oBVvkm(= zc9`GHu6&+6?wh~Tdh98?Dx&L(5hktck+5}Buju~vdV22jiF-~~EH&}K(v@?M?<&w} z#iv6(S5|G%W7C>N#`Q_sVQcTKUa@78$EDTwlMXG5tM}p2f0iU1`pvK0X@_C?&zODO zLoN?*5c*T&-cg=&yZ7$zzTfN0Z<6b{@{5_rt|BbK26^I{rj8O6gc|*(q1=a z96L5>+`-?sZ#z-<;|J&4-w)q#Fud!=*=L-UF#^xS;(>YC&;14^Dh z?SACY;jiAibmV^Oin9^X!%mg>EC1%9pOstp_+r9RQ^JR93SR5(GBT#Ox3sr`Q&|~hx`KI?8oT$@j@y2;OrffJjc>nSbZ%V5Ii$2)2Y1Fp$djrR<=rnuA z$}*0%53C>Obo{T1UC(vi5`MCD)&5~C*0$1Zw<{9S^QX$DN_957ul)Uck3Wi>ckKRM zvYkJ*|7O*S6#6o_cJ)6x`B!$>VGR8sC1K!KbGm=BYkafzE~8HF{%FItgQIRFKl}4! z%4LuCs}{B$w0PC`{==s1FFNt-jy~I35Tr{*v2+4I)a7R@W{i!>S1V)`zQtX40%dnIiZS7-OA zxyxZU7zsu*!_Vs94?f3`Z20x45+v#FL=bjtZ`x&RrIM(F5 zkrTYekL@t=__@6E_U$_K?BeZle?EKE<9Kjvv1^Hu=T>!YI(2yaPrLbe#6E8S>LWSah3_iF>ny8hWUwC;g+GZv54T$(znV99-RYV=CmSZT?{GK=mWXtL6O zn9o$>a@VgGlxex=AHPlqDz+H(JR(7V>2YF{fHf`4)Q&6STC7$jABP7UJGEZ%UCWPS z&gm1YB@gPA{_xuME!)!42aG*%w9&Lb_dTmUYS;$nv6K3B-nguue$L$16Nfc$n>Vr4 zo@c9ENB+4uPy3$9L0-m`7JoH488zB#Tip9T-5=VOZuZaC7~|F<%@R(0c)a!mr)&P- z?^wlV4If@)W8qQF`h2#bd&I;W3GbggY3yFSy}w`3pxPdj{fm@8Ta-2SVH4MNsy1xe z55bGSJ=kg0kNJ0`ob8&Dy#1#++mertKl%9PM(4$Izbm>X@?5pam69usxRV&UcVWwz z!=@rVQ>#{Laq(j9b79k*cMJ~ce4}$I{lm6bA1=3>xouvN@Ug=K%T1eFaqZ$ASDsEi zmsWq@!((5h-Ppe|a^8@%?#q8^>^gP%;JU*XEG<*C%6&iQTGd-rDsE1w=DhM^Ov^_H zB0JU|)}nvH@}42>jz9a;``X1r`&Ruw?%q1A%5K~HUr2X%N{C2zNOyxYNOyO4NGjbZ zjUY-XozftPfPhGYbV!%vZ?3)N9M5z1Is2UV+VA_v@42qe^PMB+81uf@x-qWh8lQi~ zKAT*W$4RS1rHQTUch1X>7HfVcZ9oHyXwOH|ErQP;j)Cz|JVV6_wp1gq{lZ5xWYAQR zvWG9k@R%key9A?pHVywRDMVvck6q;|)6{hGySmR8LX{;st-uS_ROU&)ak9^*xG}NJ zYRzd}i5tz7BU5<@J4biZj20r;D?TM@uVq`} zElCrL=pV(jF18FF=Esg~o6cXi)9kHHwJx>bU5%8Wi-g5I2>g&J(nveve2zb8^H_RK z+}G>+X|0{b?6F>84==L%t|y=D+4~CQhW%Wee9q4zF|OCN;FIv+doyi2VI0Sw!Roe2 z-F7&)nrP;~NRZW&zaybA=b#A5=%YFp zJ|L6%v_ekdRY1u=ZcI^z%1ZjuMP39ELrCGn+nH|%@#pPn*5P*gId@uSb9rp{cW z!at(D|FFjU5#@XnqqOlAgA0oA!(%cR<}S}_rmX%Gmhu8#*7n#e=d*PkmkM19w@l7i zS2DU}FGiIoo~{Rk?oux&JiKS416Ar2f(Ve%1MZs+`xm(f`y^9{dk^Hn`Cbq7`c<*C z*hfkRI?P}2Ic+9fINC?l+CAOzvc0FqZq3biWP=n`X)1#6U}pJ_(d0?Trt$b>vBh$$ zxp@;TwPmc$q7~KPq%2`RzML|px`K~KqWqQFyviUlnQ~ISp5p7d45f^$Zt2Q>1esH1 zQK=5vP)SLSAu%@{OwmVca^mDKo=d1&A81(J6$D#t$krW8T*mI;gGg4Fl>rFeJFFOLfSbJu-!Y=ErumnJXIf5N=AY+QFMPd!GPkP0JNq5YZgS7E^jqEc zz44F_%oA`$rX!qR@~KJ_19qkeKnl>98=5HUnD);`SKc<+m7T4kcwl|urHIAap=!_DMZ z!o_LtG|bZvx2RKlf)`WH`&x2`%L8-LaQR;4`&?wxI@M<2!h2=PH?zMC7(L2j(dpR`jnB!?%!;3c z3lI@TqPtE+d%l^99cG?JviocmCen6$&^El{jTi<#fH}WkewdC9K<=#h#iT zMPefLue%w}^Nu70^50(j7iOoo6^yub*RB&I)U=g|)?!BhP z^D1lV$z~&2{3e7`^#=A=iH$We^DSYEWUbSNdLMssWq?m}f$s*jYH4`hkNkGGvKB`> z-87zKf1Y>N$d0a&Z!&xDVNFkr3Q~aiVyhEOB+O*P$8Yj;-)#>$y%rX=u*`IFwTV?P z*j{hoPLc_?V^@Kymb;|9(^^XOjTjF_;p=+$s)`Du(8x%tWa8jS@xE@Imp;Lefoi1BV2_vJTr?Cen_jqumU8pHn73wT<>cb?fhv8@$91|t4M$fss{&PJCWv=#?e9M} zMV5}7Uf<;C4~>g+9?$vt@cpkR2}W8gp#tnW0%6GUC2NkHlt>*B=nlmKwM9#!tsN0p z@T?4Sg!0NKl}Db`9BJ4&G2U&A8RS#xR0^Mty;&+`+uLETzrMB`SN zYjAi#vkFgar(_&Bc@j5jy1rdEZ=@E7+{wFH>pLY4v2MBFGP1?K5EZXw#%A*C8#P>x zZB}b>E8_PKn2$V;HRbBaNcdUGuH?52UtVKJ_|>~F^l54Y8#Vc9lHMq7S~rK9HQ<5IZ-2;=}rj ziy~QU`uzj-kKeMkH+z3ozsQ$DHO1H`Mzm4PZ+r4maE6Ee8FywTHG3v5F5{l+KfTu7l*8hcj>5Il3ZNUaV zx~WLieu~nIvm2)#5<%Wjo968$DYSo;m`zYUI@x!iiC2A;T+Buo=8N^3Q{6dZnPFr> z9a8lJj%t`>L65`#T`B|A%h$fBVeM~SXd+2; zB$|}GI5Mvd)ry#D50|siljdVbKiCVMe|_>Z)Rn;C9S-9QLGe;SeCm`Pr_eEd=^wj_ zS)KY<)deO@pYA<)wP;E@y!iE3(5DaGmDM<5lv%EAn9^!!ADuYZo$!-97X%L#Fy0k> zY76Z=c04z&o*%sz_XV9=FpyRpro!-tG=*2FUsBcDd+N-H7l+Fa2E_-YPt^!4C4Yz@ z_;5%S3y0eG!m3}Ug)DzPZQ*>Qbr}}I)0=ES;7;T2DR+eN4MT#yjuVR>VKfiJa>v=d z_g%X|aoR{o1g-I#HR7tT(uR=B2WF%8o=YZD1hel&>R!SSd@IHtIK|6fPGfM%$rFVW%C!=)wc^yT1HIi40za)GOtFM8_*6KDw03D;tVm} zb+VTJX?@h$eZpZGB(Fm}q&}>o`z6foPZ4dqU9GgoD`Zy9Bk8}_Tu0`@jjtC>NYqnV z*iMqyVtMJo^AlR(ukud3{;a*>QFm6^lbfD2vw^>9*WoeV+&qztnp9gss+>yp&g$g8 zAGxOGAQ$&jl0u8Aw=wW5zWc8W2c~**rr}qaY?;Ebo3!Y(P=ciFbc0T!H?>l0_?ftm zqTw~aWKMbbGwkDw{fenYkSm;coWT{|_>g?{*}0Wem#i|~jZPB0;zqND3tvYMPt?Y1 z)P=tBhfcdS_#ad7)G%A!ohVH-<|<{m7K1oaN`^^~vnXB^5mmhIrVCs!H~n%7XEgta z_NODPv$qDST(UoXG(3c0k2zu=rC?^C*0eG&j0a!8cJEVqfp_tWRMMM? zgI4NF_Sro}lNAyD*6!Gyl%guZUAVIsedYtu=l}JX{vc|8zfy&3N(6y;;>+s9Ayx8a z-ER$S@Z=7m>O1{UFzGF6Ugmf0_u2ZjcY4j^=CnAQpa@KS&^mZ|?;EV}XiR@XA%!xx zvv_!{s7%JgWK#8rrT7UNjxmbU;P5?l^(orx`$`2mhuAiYop|n2*s>qD&1U(PtAY=C z;L8w`zwLh(Dl(VP@Zt-hk`a0po?@cSxOOrc$6ZSDH1c-)Mx&5Q^#O13$%&nVQjeqa z1_4L2w0W`6a{a|=IifEd()fen;^Gf-upYai%~IRB6lwJuRVy@K@p*%Y+rt?)EVMjm z25FaGJD#;Ve(P&+bHiI{n6q>i_O4|*u}9It{4@pEZS^ieywm%0w6E-^l!ce6MlPE$ zQ{w^#I51JD%SBJMAEGdHRa9Q&S`ZFod4C}8ttPWm<8ExgxH&_LLsOgi+ILkdEvD;B z60;;vnJ$?rp}(~~IjzF?96Kv!Zc#)xgfWp3zntq_&hkaSq8|e(R#l|UGal-u@7H>m z$4IxcZ@QjT2ud9X7{@6pStM`f@axFzl+XVVIl$+QEm=u2ykr$*aw^Td%)n+<=S&*^1PpH{@Svx`ke ztk5a?b+u|-L)0uP_gpYL}+o|&MUv1Y=Y+z##)l7f`|)6?-Jkack9`&h!{lJjdZ?U5TArPULm<&dx7yjoB-U1I)Y%qX4dl7Zujap`?-o z^!-G0(M>O>DqIr07n>vd2VA=bn?d3oweI?qw2Q$jd9RukbC@i*1Mb|C)&~(MOto zd+4joq+N=$PE4GH-!kxJ9;ZQ1r``@B8S^P@+}kK4DY%Qlu6%}cB=?sczeZ)VIf4X` zYo<3fgG{GXP5V&LN^QI|SUvv+D#@+4E#h?H=Siqzr32a@=Y)8SdSIkSC8P)nrlc* zwy9p@J}$+86D{y5DE-Q=K|UpY7~ECS#nnG$(R3P^hjERJki5RcOTUwr_=>-E_#wxD zP3=Q!9T*zTn|SiW$BzlZvy0Ij%5V@#P%gdHu2lT#^uAgS*;zU?4Q;5CBkAkdR&cQEU-45K_FJ6W$UJ8+2;G(@b zFn{}CxXUT2yXF(-y#9If1f!vk2dd;yp#Kk5^OUg_r)3Y@Cz4h3dYl9jqBHbo3S}V_ zk5|0jvL%o5KJr@(yN@P~PWdjZ5pR}`7J~~f0bb%m{pJJ>?2m%*oOAh_M@K?9MMGJW zSiL`8VrSt+`6pf1MoI**%*&MOe$~B>RBHWtzbnjR#VhKb_*T-En_*`5#HwQ5^CvPL z%%2Sy$h@@-n@+8N1&N!*O)dCXZrHhED~I0GZQwy>p?HVe%SuV~K05IMfg&BV$yNhz z^bDHdO#tJF^-k^#rTo2)Grzil;5oiydZHJ%s%_Y-4e_schZz)eA{Wk6_kAqliDXBg zIqe!X^)qh2{}}7}PP?TukBa1Qiy%sR$%JL*GMdt9|E6*2i>|+B56g7_LhrW!_GTE91ypYAu8;>Z%;MPsuoH5 zQg^=ydtEGGeJN5IDrsM>^SyLX8QZ= zl1wMp$k8VW&w#U)>Q7h6_!?_|w2ME{LXop2-CNT*zf!%JSx$*8lOkzE4X*g$|A6yN z3Sng7^7}j$4=Oy#dlAuwTlGSk+1S-~0^^9rO0HSHuO(PqzOMGcWZ}A@{H)!@f`6t* z>PkIMH?eNaQXqECCGRXJBJ}NfF8ODX6kFSZxX`Br;V0J_&1!s1RdhM;-wsv6=Qknm zj2_nme!~ckVMT9Z6E9X%0}ZCj{b4^DJXlAZo)+<+r&fYNG_L9i&@ew9`2H zSeC2K7ZN`$g?}a{#>FPjlLUSKb0BX&2O!dkFC)gsU0}#RGsjqzjYM|pB}VQ+sU=+< zV?dna)FQJrP{FU%9>s@$$$=AtUxq_9#mL_5U(1eNrNxsY+|R>xI4W{*t|Ic3 ztBh~FiGwfDGv|?ECFIeu*)p@=&j9Ap`{uNGj2E%=tdHjy+hUu&6q{^~cKDMypehL*anS@cXpZY&Lvl-kvc~=v98tgE7a7qY2PnJi24luDDJls1T)S=Ot^1kSu z`pQE$Z_v;@f975=$q^_xneky^giugyq;t1rP z3%TTli)ACXjjo8F8#eM7du!bZdx}WWYti=z*J!>RFO`YfE+M>V&f6ZL%M&B(E%}n9 zQ(|r?R*|op}A<-t%XtSXG=)zajj&eZSAf?^aqn3!ViPU z35lv@7>O6gKhr#R-O?7QZF5N;9_LoA5N3$jMrWiJ)5X*VHOEj^>%=Aq^~MSuEIhlt z6nm!0TM#zgC>ZAKF&+L`T{1i|wj_SF~WZUx@QiB&7sa-E_be(eMgAa1t z6>%~zJ6~iz!AMO=fkRCY?%zm%FYTF58goz+%<5G0X!%9;YX_Wa%zV_Qfp@7*##WxK zdz%}rQgo7)7FW}i!)*L-MB7TWxpy)xBED%h<=$m-J^{hd-_j4rSTfPWnDlojACa zd^`Qd|4pA{dUPyBa@0r1;CqW&*LQ*(s)bCfwgt{voFQEJ7ekGooCbJg4hCL5-{{f} z@$5QMO6~UVLhb&B$tzRrTPlNACodYtH!jL>JS4Ysqb?`SQKkH;g+r;mMF0Q8tTtI&PJ@(1HowNZ2i%uL>FUNk=HP z5&BEUEJS!lw!t-~k5b-D_|fCS+^X`zxvxt3v2b|#o90>Ag2t=ZCWzE|_0ooT_x0rQ z>~6>LIyiZ8m0L@3S6r${?)$NjJg*-jhvQc#uQ<8IjAJsvq+JX}dgn-n1XBPH)BWZp zjH9_X!qV0ng2Dsn^DlwtM;P(&l%+>7mLKiOj)96)x_pceiQ6X!6LX@1@6Au^3d?e0 zSW@S5G(+)@xYo4SRSuG7I{Qb58y8%}+sin#nw!sTc|vOfl~Mz6nGS>zwbw2mPcJmE z=J(qy5)p#OAF|iK%U?E|%3|^USpLE5c!TB4d**quK5m7f2ce5;F{yNK5z8#w{F^Js z$QO3{Ec+QQw-0Rh64sij82Hb*)L4X&76`%P52<(QF+a9wb7R-#ly_BY&Gp3<=SuZDie>i>Mf+*?H z8Z2hi0U~VDyd>e~rw~T-{Z0|ebyT&$Fj;B%lvv-W@-L1@O_cfa7W%d9u9?v-3e(wr z`ndbWe5xyRtf}8s3BG-1gz*$pbLG}#u-LaL(ytC!Q1HcSW95hI;k)9Kh55+DN#M8~ z^NIQFV18rJfBoG8;=btz%ar@Yy)owbnWGd&;%TMu8o(`MnD%?+-{JyTf ztvQc%%kpU|Nu@k1f~(1>sWFVKqBCX4#7`m41EQ}W7i)oJaO&E@mQD~#y8|ObWWooB zM#8EB(X>RvV{!TPuuwKe@Vk-3lg7sosZORI9~Jxv2d;bC1+jB@b*BTPF@8r$Igpj7 zM<&5U>m=!OGwBsM!#j<_;;91xTDx-%wq`4rfka0fxIXDFi1&hP9>+JHu^v}ESX6Sc zIOeg;>u)w%o^6+X^gf@-=JoXBvP|uJd$COTJE27@m1zq{wr|x27}^--7RO{83;Q@L zEHB&A>GpbpkE#5P>bVeQU6Ep3*vSqo&s`GkHCt@s2kKff2`Q03&TcoCogb$(BHc)` z)VbPpNlc8w{~CUDkFYWDu|_#OQ@Cl%QLks;3aq^RoTwrDKs2Xn#Q;5HBPMBaup;JM zx-4v811e!lSln83yl>H)%&FN)0{Z($ zhLkH&a?{`8oijfNTJeh^;`wU&!+x|m5V#76Vdlo#mh*&5Fs$Yyx7ug2biTj5P-%Kr z)KD_W5VEqMmd5;n^U$$acJ*CW&+JBA+u(KxkHDK$C1!`xc088WX4v(SX{(~{d}ot$ zCOPUIZNnp)-H4z`(h+c$3;S#pqJO~#o5-G_Ac$Fb-n?f@hH)u#k%!n4c8^SDJplB(x7 zC)I49C}N+Y9&ChE(0|*q@1J<`lxABX^K;UDDV8$%$d1Z`sz-@gu03QOK3vpqn`iE0 zzhI;ERbH?(NfOdQQT_V#y%oR3^y_aUum&o-*135<$KEK6HP{xtEv%DH>31(pcasn= zB?>90m59+Nc_>>=oE)S>f8JVexNM?n997t4#+mZOKu4>MFZ9S7VUs-)UJb$iF@JZM zI5m-pzua_O(BV%Du}s#O&z-b>hox&N2RNfa!#=nPb*96vQOM}o&p!xw)=r&g<{>ua zduOZ_QYs*w=YLlK3t$n3u$+8~t4C{rY z9WJk1Fth%9C)o(RM$ez$v^=zyS`~z7)Hoj8R-q{g8DXBH)UapwKW*vldK+2}BNalx zQ}Hq2SghCbVc|LYmf~gITuILyrK~gD`lzxKov_k4&V<{?5doAUwC`NQUwC=lf6XFO zKIVKT$=2D#ddS?E($gDxi^y=ZGBem7PfXjz#WH+tv_q8kI0!uLnEIf7|V${Pj)&_6j&x<3%Aj7YT znD!wHPVN7=_kjc5uXJ}0JpK@AAJT1aoGG{yxvwXK)L10_ne+#zhpQCvoBUVrLoabZ z@P9skp@u=Y8TGDXa@mGuT*t6yi}Tf^X` z1f;*3m-jEIjY^)W&~RDpNy}La%=h??Z0RUx@4I zXtdXXvHX!4>NZs+UZ(9LF;Ke^hX0sBYN@L!Tv*BPnNH;o$;kUOeMuxJh)OAg2#lU; zy~pRtgWabUsHEObC;?fg0|j`za`mhf(boA3Q5X`^vZF(hadg~x$`{QODz9`E<0U3z z(X@7oK1Z8c4DAJ9p|fEKO~${9AXLSXA>i4c|F#)Osd**ElS(sqmLkRAsF77tndE3B zsP=yJT78n!JQ=C=H5Pfqi;+$wrO~3TacnwhqEawn{$T<&g9Hd?{oO7GYr>- zbd5q5+H(z`!05g$P0IA3SI@xh8PNHxfI2hfOihY#vrJ-4<~#i{sdUvs zs}#A?Bs{97KJ9<>gF$+mFKt})Tuv|X7i$9&|31&Brd9MsUxBdue)=X2&0%{!0bYb# zt#2|JTfX>x@W(!JyM_CrCo&`YQn=Ns4X4Mche%M%&`2GWQ)fQ3Yv`0*24r}9v}97G)9H2) zuV@?)PNlG95~a%eg=nUqh<*$GVnbjc`iAgv0sG_%(>^xVxY_8iUcpFd!(%K@o{MBN z^fC38FdVgMljlkBd-AeP0S8eQM{Los*rjr_xz+=pio{R|9tER1_Y)6RN`FUx+NLn{ zj4kH#kFU6BLi%6hA6i|ioNWpyC!!X{DTkYe1wJ>D$cN7n?^{O&-L08-B_&Uqd zUL#x&v8(dz&6Qn65bdQ!d_ddU_v@{{xsBzBDXk9YRJ z=6D4?Mu5fgD$H1XEwmTEnc;rpiH49UP?~MB!MlY~l;jekgaW?{Q<+0C#=hy2o8o%) zlL#$2zct;=jb;%|B*HK38wKW0R&xrOEZwpjT(I}Omv|@+lkXF=;aS%XNrzS;`2{ zzh6Fi?mV9js$HRbU=ldf5Y0g!|E8Z}CRNkgO72dz7|X?$?{K=-=5k@fO;Pu`V%J=4D&*mrIGUcH zpc%n@NpiR7$W_#;f}2Tz2pRMDqMcjmv9Ri8*+V8Tfo$Wi`3@fxzumjpREi~Z;s5b; zyZ|R!ej=b}PZ`Nx?V%ObS#|oMP4{`*XCp6d4Mrl;gQ|^BPJNN#1Nx^VhAf#{m$f#} zEIJYT+jXPw>oBi5T-OnNH0$s=>eV|Ak*9q*wD-}D(xo3xeO&!{lOp{J_*5Mpt=FKR z^;cDtGihpz=HI*LD3Q0x`=focf`&;ulte6!tCH(r+beJxASl< zwl@3iLzWHLRM|)swlS~liXx&>RFQPPWQB8go)M(tHzihE=z;_unaV!=f)ml(1qEv* zi2OFnxk?E41iqb)6y;~Wf)T*mjg|B(c)0M~x$e!1ATFof#B&+AOqSVWg{pTi5%Jl! zGD5_|$7!cL5Sl7T(gj&iiT!?v~&wuz-+MGhIzVR3Pfz~wJ#&+Cl zR`R)p)jS;pw*ZGRSiKFD)W`>xMgoN&KdoOjHf04GGs#q;tzB?WIMYuTBi0xNCE6t7 zJ{`v!7(!P3+~)oX|6wVj&kwxNJoiua9&o!HWl5Y@?K*Kj#9!3!Q?{}c^)iA#?=30s zxp^g@CSNxe9N^rZLULSwG>j_)EL>`Cupcea>((j#A_SHS6tZF zpl^LA82R}Fp%-dZi{lzy*-v6MMRS*OuSxijsoo{Vwz9~Q8ZXk0&Vk1tB6P_W&_G>~ z=c#N>ew2RG-YXurF7c8`AolEQBod3Hp6Wwh`iX=53({;mnHfp zHXomg)~p+FelmUb8n0}_sg!~Jmpj=?w0foxWt{et3C^!k61y>RY{{6~#mXIz?T;jX zT(B5UA7RYET8!a4RXQfr@mKd($$wF@nZ*r*C#XP}4R+&1-q)xbv5fX^DdW1f5ZHWe zCYM6hv>>v4jzE2$X!&hi6K33$aONeIxreE6*0~ zJxzoPNZtk0cL^B;^(a$akbS@Aa>fyTU-~SYkj^$Q>FO##KY^!xN-mE)L}knvE={Tx zJpK?B8sa(MQ=5xh)?0dZ3GS?#tU{TcS0e&8Qqt=s3@`Mk_emm$!W{5q^)5d}@UXkX z?v<22-5ejEXA?)p(vPZ14X3clQ*~6Pi#|`@UgcnM6f8R85txjtUKUdih=0C&u0_uI z!x0bHsy_5f>5Qx!)4ll$cewJggSp2TBJU5Xo2;!I<68;kP|QP8x{(wZ#75_ii6<+f zUt#cRsF@yaPBxo!@%7`Dv|@+*x&^58ofb`zR200mV)PSiS|vP1H2z{dtx1Y?J<=IL zMNy%c{nBe%w9BPbNcxS)VpR8u0Xn%^a7)cPIlqHT`x#7gfa`bWyhrnfbKvoZnAqKG zUHOn=JZiNfqtWJ?mG!lOo)VSiLI&L+vU7Y;53K=aJ=!E)z!GP%ba~Lzow=mt)0@CY zc>CVEHXixIHO)it$ijHZbMK3RE~Ozb=4_U{utQ5w#I0gvX1jl&={ODdsDVVRpmZN({SBbOn?phnjMVpir_ph}!gkRI3(NC+Jm~2r$b=2%y zkq#=hHSKHbMcUw>{2vTxG`$y#U+fA&pMTFK%#TpgmY`40k+Yba=xgblT}z>xj7SbMi2`*>ZVCO+lg-5SFr*w` z9p+mEme2byYb3wD>wG=MLmb>7?_^RxSvlzYVd{|w>pe_7b@yG;FQIzz8OP1R@T@sY zKDt4>E145CA$wd*WL(%v#^U?p*9T{fVvz)Ov-+Hqd5^w+7uxd1*Ljsm(j(L2*T`<* zPTRM+==vUMZ_k!FE}86e2*#|XqTSm_iBp#X>KH@`X2R@2RQl~la7}EO7QNEDwofA@ zON94dzbRx4{5~#AhFEoS##F(A+ZYu37DZqj*^CdQ1Pf zbXr&5Yl-F$I*V{sIuHlKo$7&c6dMw^nn$-g7gvyGZ zL}TgdK9x%!JUQ+YHEV1Csu_4OJ5hHbG|h+>tsLNMEw-4iMD=R2j1`6u;fJ}&`p;iY zoiD;a(}WRey?gzTO8#x_rPJW2*tl*DC0b4)qtQ(rcSm9`q4Owe8k7T7M$g5?BDM7T}MaVr~{9hLdq>5mOzni}s zZ^edv@$n}%_?vL6(^0fUaVfp^Lis+y2*zf4 zE7}J!Lz@y;Ol$M>$dLt4Hln~cCqN(@Gnb8t?<3y$*al#mS@_31Z;RwS9KWC@!Gw7k z`8j&niO|)PAOO?qrucY%rSwD!%@yOygUIb?c2|^!O0KD7iDc&WJj==s&k3a_(*?zs z?)$4=tqK{Inh9nL{p#D#siLqrbbmO|yys8LddHIvBk|L|K_C*l^sD|BR*rB_l;^52 zJ7&BD)w)JQ=JnIYd-%cP&GuU&Z=bPu;}Rb#${aA%-$Y3a>=|dUYx$} zcZJ8Xk8ZI;I4%#H!^F${iV^REe8Pid7Dd0<;FiO&k{LHGV#-^nN%=q_ZYB3g$SPc; z9z|p{B@n!pBZWzC7>>ac2;5kC&}2%|NL# zFrtp2Y+4^d5~k#%kll2}L>2f@+()Vx^yV|%h8V@PbrS~Jj06*(x`tSsn@ZG8)coIk zmvt+Z$a|x9G1bYs%}zY7*1R97tj_3v_DBq7tuyPw=zHpAH=8mfK#n%RKL0jiLQoJR zWPJUEuRJ!2K}yRl!ARE?wLUcZ!{2CoX|-d2Cf3!IvvK{n z^NBu78kRsxId!MAq&MGspZh;!QH>PR7Pw&gxCE2>dKZGB#C=)MWfW07`z(M`Oy)$P z^cBY8$f?^hA9Iu*HFb2yz%N(t>SRotr?ST*(RdW?Cc~>fM6WZf_XEvFw_Hr+@4d}D z@@rrDkxWYY6ytk3<{GShU9JswiPwiM3WwJ1@Ni2k!7DTeX1vL?6rI{ev?@pO+D~vI zMfVrF$sdpOM2w*di@Y_FU=eR>NMG<_>*6gK^i}S!vn$3``r1OKD5ud^zt3Dgu+-zp zu0!}}M)vlA>LB8!!J?yRv97yHN$0B+eZSS4`?lzG(_;y1YLVVTrNS`UK^C6u2phz-R3d; z=9rqQk6RgM^!mrBOLWEMk>8z$QVCdX#pMXouVGfI$X=61n%Kwe4HLT(a6~N!zVg+s ztKIIMCmqe_N)=_(fBfND3JwkaRg2b7c(Fczhdu88*S$r$L)HO)B7{3z+Km*3xe4*Z zXTle}7+rS7mJXRX6_Q9{y;~eBOy-3ik^@gVUM#n(t|-;MA+Mt4_n`O|+sZ3LHj%k3 zMRedg?raon+~A3QF!J3TnSt&kL+m*sQ*=RE>k?YoG-{}jf*I5B?K^lw$F6sbX#!eJ zh-&Au)mfuc)Q3SAr-3YXRs_MBWAmj*;&q4tO)3{VjPx25xqAWe7?ESOHVy`~=kQ10 z6o;l|=3cvV(CJ4P)^O23fm~sPz-Lzu<*==VP&;+WULrJ0U1O3%A2J&5B_K@ zNQd*!L{%aQvy~CsLyv~;ejGJ<-7tZbcf5x~0>xQoDu!k`^TViYOnzO&ty}NviK{Ia zqNp)keA9Y$wh=2%b8fX!F&#x-Ur(RCuvf^X)?)G~>uV*y$BjI}Sd`HkK58uKEqcK8 z?Ss_HEzS6gC&xdp^)38U57YY%W)O6_J>2p?NBv+cdVuxJ9y0_VF2C7zm-W$dM96n- zy>otu?gZ#h55Pr2Cn{K)k|A2>l>MN9Cg_HaM@VnTHXolcf&4I5WRWjyh2`l41Fdi+FM;-1rrmAGBI=rXzpNeywALD50z6}#TTkz{cQQoR7 zYB98mWgf<)!5|HD&5hZfbr7aGxvErn8m;}In5cIeY0DMozTdKMyx6k@m=XN*O6q*J zh-x;ShrRvz6WY3;{9gZrQRDKrxk{ibN`a~QEN}#Y!!=E`ZzZ%z6^%H*-gQ^x?pvKR zuvuuTUsq;akOTh=)tDJ0=!?#21m`EK-R#F>4{F|uE0eexw^;l*7$3xvBKr|C?yh*u z6#L$yb(Jz5nVAP6Ln=e?wvwRSv9G~s8Z+^Wf|W>fbx!9a>QnpgX~I%+h+5k}4PS=& z4<9kd`8|fC+){sQi}P0dGOY6#GB3(VMzLvNK}Xa+r|P0%$I3%5RS(fAy4XhA8nV$C z={LlMll(5|#ZS>7H3n!9V}J`_Tn`QM2*@_XpjlOmLnRZ$Qcb%4G;i~0_1_e6KD*G&D*0v zJYCTsjV@>qLZIn@AWt+113(B6TY?680AK~^1MC2izfl6}3lIhf9-~2YPSGGwfkp#O z2S9yy+{Nzff2H2lhW7p|(6c~${ndZh|Je~5B<}R3gn|wc z1Zs%~`ha|IP)8kF6WE#{_66jRg8lTMX9`$f1K&MRXAocja{gb#4bJWXdUJv6`a=A_ z=YO*Af0Fahdf(N!(|?wK7jOF~*Ysz-f3&{y-6^#0pX<9mf9gMr|C#&$VhugdCU_qv z5dQD^pX~devCx}7op#p{GLwo*d7lG$W6CervcX$H(0|7du_YXe@*b9x{>0R!f zLj88XbD(?ga{sIRKjZVDPdhjx70^*4bVwu6FhCdJ5ZElBo;X-P|4jw3--9(&SAYBd z+ynLBg0nz#pnHdY=R*C^x={b_Z-w^wGY++(eW3Nm0nq%v+P|{UA?z>FAvS zgsc}GVhk7qYX_i}fG-2!*Q`OXAFu}2+KcEAjUWGe*cZ?tt@Ho;eg7xD{?VSWx&J%8 z|4-{4{JxL9;J(}fo`HLl4#-#nzwQGnX29$ATg8Ds0gwTNz;!(Ot;FDUKwCzK^aGs) z3<7^TP(6S(pye7JvhlxUo_Y&l>gZw1`8dyIAz5Z{J1nNT&F(A@N7!Xtd z5rBsr1Hwgt0cil*4^RXw0$W)Q1G1oi0Z9V90R+loKy-kj0`3E5TrnW(-v5|XkH7n6 z-7p|`+~w;0jy?9ofNZ({$NiDO2hIEMY7hU;Y5#Bf|5?KtoB?VNfL?#@(Fb*uz5cyF z>hCxr@DqSD1_Ha__g?7!+}~%tJ6jisZT-HMKl|Oq@3au~fUcpv@9_9zA9U~C881NZ zb`azJOB|Zx{l{6M_Mh4z#K@RjiR0e>a@8xgp0P%7_AD{$K{aasx zoKmn(1ylm!0Wa?q#G=94o`+yS_JQgFO%B3<9DsEmpaMV-e0_izKnB3d4+CNW{0{*OfvS2BZz>5+Jw<+~W=m$d7i=6JYce{EYie-pIeN?|gS^{YT!N z@4wRc|EA7=wdYSi^h|xD;QD{l59-~m|EeQ@c8u+2V(dj#|0=SP(3JMeaBtw&i+^GU2SOZzw)=U`~&}8e=%@QRDe0)&-E1^ zCgh9&6Jm*v33&^2m3biFc{-5B;VnT30{N{ID8pNl84dnq?QvzHqEF8gfDMxoI z=#a(#`~~X{Chlg|R3O95&d9>t%EAabw#g5L3jC*NVd<{os%B$l?JghyH6DT(1C@|4 z)!#-t2~j!On;Y2!Klq;`(|_Lbx1E38;|eYJ_YDF6`819eUjJ4R`aSM<)1&@#rkjPm zC5yEMv>J4pBp7dHVd6k#4#s9Wg4q{lPLA$iDg@QvCh$>dYDhElnNV3exq_>8hmMK> z*J}gr2y}Fx1Gqnb9~=fIba}XfF`Hlz<=;nAPkJ6o86c^Xv8nu>oL;qedd zf~(o@35{U*g}K}BagBl=j?jAM!bV1}9&YYN7LMTS^R1m+-HlAa%M5+3Eq+H#Ev&!< zvcJUKSj;Uh?!S)(UU&-uDpwCjFx8ut5bW6_dJaZ_ZJF@!tP?pL@UOJ37o>6KiJHtXZ=r_Fln%7&80MdA&S>F{Z|b zDsVAyJ#c8W7ZWqT68;Ac)NHIVY9hhQBQOv+$9*McKTTghGB_&CBUDb_9krka{Ou0* zSlrR!5y^}Q31I|z1jnG1!|bTcm|hD9fx)&L%Lw-h3H^67ZC;UKVJJ0c@-Q}f1bYKX zJpy4gddD!JqZr455D|$v;Oy05j&7 z=}v}}5o3uJ7}B+JShd>B{*R)5wG*rb`fX;H17!w;qcm9=We<=4#0~aIBZJXYOmDex z5EM*#6~Evau>zo100Xs4u`Jk&3FLwR^kE~I5d~W~oBcu}!vkX&o*;pLoA3<}XNI9h za~Lx%*T;nDFQLd#03i?w^!(q-zCYzIY7zs>^3SUOCE0(C_;+16m_wOiL4IIK2rBK( z3`gf0Sq*qJa7jp=-HIQr2fos z;qa4RaA+hdD8RT8GXkAIX4nkOK10i(YzElNjS538C2wJdg@iMi0Vv}}2BS}yBtvm- ziVTVHz=Q)6j6Gqcpo|~r5$4MTf`>$g0f%}0*zw%*WUVt`S$s1S~5@9um z#=-bTE5wl!XmB`Si^QZTDz8C;LIEMczP~#GoBP5dL!qOgevzS}7z6w z?%}-|#04rF{X!Vwftb}}Pi9OAPzG8KW}RUK_(p8}oy<1G5lsaG1xtjQx|vDx-)b8A zGuEJiU4gxVJpzIAy_xi823S`oB6xiU@&J9rAp|g(gPp{u-p-4-{43$j5cWR z2ch#>IOryRJ}?abw7(7Ah>jse2F9j}=+N*84MqDJW=ZH$FNnqTFNlbk=~cA-pqimN zP#7>T3?ncVi!u4%GyhY-q53LE2L%1+Pn8fX{+NeE8+ykCGt7cxjM=k~mj^1WpxMDn zFd?F&7D^BG2=?<*W?(`JU}gG9Q^W6RX{IiJ>UA?>|CgemPX{prdWT~OXmH+4P&)%b z&V(@;As`2U{}unUM&c7080e0wr9c6&)$Ivm`nLk2Oh>J#0Y$?jy!G{G8lbPwo^NMN zuA%bnmyI_MALvw+bJ$a@EN}-*sDTVreqeJFHW7i{wurEh7!VB*9EjEpl`S)4N*_4G zFT(A28Bs8kg)x;t;-V`E=+=#XuvoxMY{Pg&#VP2C0As~sYR*hOF{b{Da{b3Vj6;G$ z7%DKzy;RU1QvpHrTjnb>Y{O?F8A0eo$n-Y(-4`HVf*C3xo>ZVZ-e6cRBrs5J{vQGJ z<=NBf?>xRRjlj$R+=XSqsDTnGI5Nl+=mqrM=n>`}g?89X-C;@!$EE~Kqr-X!BPuFD zf!u)}5$HNXB{DorCD6|k3I`IXD0@cw1$ry_d8_;@Sy2RzGt&uM&4E4-@`%C8LA!aC zz2l71igiyUI$iy#*8M9|w%kOsf&%nsa_C`9M!JPzliImZ$RTvPS85aIaj$oyMbV20`jITem0MJdmVQ~CrOW+nC z5O=WD3I+c3_45L92g^nPn*rN}gI)$np)asLVE9Ht-@pL%1?3YY1PI0u#;*D*b)F+XK^UcStVla@PjT1h5?DKw8Hv+OAdgU#!eL-ik)wXCoYB7i3;@d7goH;p{Z_;rW;BjJLVl+=o6*c1LL%54I!#mK^QMHvISVuRus)6%-l~vl3>7WuRDD z|I({|KiPwF;lmk8*Ck6JEH;FqIwbg*%GAI8gzPC2P%-`j9z99y#@t2velp! zs0L&Ot0PnaLXoWs39&~NR{4*XR!1e{%J|~>x&-z3&M4=SOl5F_C?t~2QQ5c)7d_!ew=h1yd0lXPa$@CD%%%l`2rJIX&G2em}S`;K&n@2Am8yLvS|W@&T_S z_#43af(ru|2W}6z1K?VhPED7BUjwcg+v#Hh@T`=?hwy-#wSy0_1&8{d**^OGKRHSwAF>-cSso`{EL%zVwaSL&gx5x<_cjxEpCH(y#->a6a0cvWVtW9f zMu3jUwt#`OM`#)_kGVO_A?BP^T=b0P*{^FL?y_Ve|NSRN9-3|2cnfgw>2 zOkd6;YV#TWaqLTTd~6&-_}_gjG5q1= z9GK&C@Nw$Fk*6Fv$?-YmznYq!ehcmsxJhs<+o@?Ak8n7W!M0|+JV2pEx4XdHEk?3S zm3+weOK>(+&4*Ag@*z&=`4E9RK4fP-9})%O9!-46^9y{)5Wr>U_>f45UjomD@N85A zagblWmJca~uy>dF;BEn&S3&*=cy_-6=T9wg=6Ds(8Ugo0@b$s{=-@+?!7T%~8yvbw zK{a&t3d9pNEFO+p#D(7b7X#cgMmiym1Xg!xFf#~%b|8hQA!djN5|3Pgobg~t7e~Mm zabz47$BpC1&BifssyI`e`>!2s-~bc@8E{Ym3mxGCOwe{@79xs>gMIY{hytR47$6pi zBjSaGBZnBt&p27+88TQN z*s8{i6T1a@ga`aLczzeF_TMD`Yq4to4~hlD$p5FURsS!G{XdX>|6pxrGr}wZv8txy;IhHFfO8z; zLr#F(1#U06HQ=^?hCKg+J2VDk2plKfzCWHhVgI-O$$!Ba2Vr(x{Ky45KjOglb9nfX zt>E(5zVmE;WE;46aOg8WgCF^k&W}ujL!UV|lELSQtAF*`(f|8I|IGQ{rRNC5f940d z@c;2I6oiEm$R#}d!`X1D3iIQb6g(M^#}OCc=8CW9(x=gIvxztw$R3gc!GN|1v3#Ob5iiBw2J$BW_ccs(2uPsHO11l(La0mp^HBuIc0!i$h`XllSs#Zd@! z{9K#?;&Buz4$noy zDFMDn{CwPI0ufKckqJ+s0#I8DiV;sG)A2Y}WjwbKQI$?4$k4d)3?iPa3sI1bq)Wx) za|t*e90e_ofNwEHaLrN(VK2^|fsp<12oXnT;FseOOoY$DlW+&{VuCz48R{G^98Qs- z3T=Z*;-qmFKzlr%8(OA<(*OeC@g!*ZB0Lp0j1mq9ECFWjL0aQpLL!i-@{%CsLyc3sQJ%{7G~7n@k`B|-5hNfyII;Uwp|5=eH}a;U<*-IRaup(s%oYB zKjaSbh=!670-46cKTA|hQc7A@L0L^p*8o&%MbO>hs*56BPL56oSXr5|O%eO6tW4h~ zujukm+%soVaNp#gQNbawmj*}rjDNY-;*ILP;V|oJs{Y^pI1}tL?Ck&V2m1_nhmc?< z`(S@&|IrW5`{7&y77N(6GG{;1E0F0C92sh4BxQtM0b;_=DV&3#oB41Y!`_~ReOox+ zVQ**7oR~oU)l}70HB>cKwN$lLbyRg#_0&|=)YR0~G}JWJwA8fKbkua!^wd?=)zsD1 zHPkiLwbZrMb<}m$^)ys9)HKvJG&D3dv^2CebTo7|^fXm9)il*LH8eFfwKTOgbu@J~ z^|VyA)U?#KG_*9ew6wIfbhLD}^t4sA)wI>MHMBLgwY0Uhb+mQ0^>kEq)O6H!G;}m| zv~;v}baZre^mJ8q)pXT$HFPy~wRE+0b#!%g_4J^MdQiL`pw@$IdJv?%9tPq6uRnCq z{NMdhS^A%UgunfW=m@CpdZ zt7+<6S=-t^A4?(-l?XlroQg6lL6V@xCqa~^%_S+2EQ!2}SY>2sqBK#Cs>$U*(BzKS zp^4C`vkk2D2wqg0st8GnAWjmO(IqY+sSxQD8pV_$OXQ|$6ZA=96e2fexvh={j|N4V zN+-(@B&m4T-Ie@gDosk6x=2J!MnXuG<^Y9R^30*o$u?A3S|pdb@glMTiB4WY#*z35 zB(Akoyrkz`8!DYu54Md;~=NC}Jc zF6k$?BIlO*#J zsqv}1hyf%X0*%6-?#`Md#8;6;`2_eD(;^I6U+Ll0P+{vWLfk^!YiM&=De;R5JIwin zla|jTlUZE~Bx5ODs1iYph>tg&C!kNl#ot}TdZ<9eu`X)^v0k#i$=eg@M0}!vrM(gB zsv#LibRvms;^TQ0iQe3+>8#Vbl01q;8U@cwX5}S5CI}FC2&^Y$ZX%A4o2Uzom!m2Y z@w_zIcxS34fs0^3oD1E=8c!mDRzo6@$#@ExN}&nRCAj8r&*9n*u69ffk(L`{f z#M!tx1TmU8P69tqgh5ciD{(2~REcVMbzCXFj95U4Sz1|JcfIB2t>?Xc(+Ck85<2<@Mz(e?Nof#SRa@6` ztG%PQ5BW7<4A2qd>dj2rcj(B?_6{Bad3^&b+coQ5;k{pO3_zEK_lD_d_S zE9qQ)V^df6=*PqzdkTvho37vJc=FUHx8Y7pdxx#VvNda6-FBs=S60_FU1_<|Eg&Mg ze#6&qQ`4-VP0wHO&I=BakaXL&{q&jVFP7HTi-^vhXT8{A89HdT$6dJI+0`@p@k>~E zdPJm*vP$upnx-2a-7oSG(*wDx>GRsB9hR+IPoeVh%c=~I1c&GtnV4HS`bM_iynFA_ z<9Acj2*YiD!V6-8B~_eA7KpFlWtEc{lz0ik94d~eLewNu2sjFvB0yixCrELk5Qq|V z8i7in5I`9xa1%)cE;5c+nB+har>p@zXg2q9q6GoeUZMb*k6WK8xzLRfMD$yMl~ex5sX0> zRv;xz3(Tgf2q+Qe^GfltQi%z9B3!~dvq&nS!Qpvl(^!r3Be+=)#p3x%tXH&8M+rK# z_zgm=i&WM#AwvS4tV^|~a+4#t<`UKs*V0&tvnA*vG6)K#YGPL*XWo z63#Ogks)F)k<~~LC-CvW^;Pty(#)O3&3@i+rWk|W2KplcGz70mIHpFAM$tK9yl!>&Zh$^SC}#IIL%fqRCYvZ}I7E2ff_ z5=<+gPbLx>$Uc%g;xa2A5fo+2<7T+e8&PyuSfu(=A*3i@5nsYknmf)=MyA}gk51=n zPvWF>aC8qHX&x!va^3a=LWT);-~~FnV-hb!!I~nbhhMdY4+}p zwcK*K^>V(d;i@dvG~L6x<+^pcZKlsmM@;dy!nX3Z#w#3G_^n{A$X$DO?aj4sJSIJ6 zdusYG_Yd;l<6jnbGps+19;*<$G&VGGe_~ByPa-~5E_GRIRMxSq)~rv5B}g;>NT7e? zNn|{%^xz47K$l-60u6yjFj0U8(r$(17Jp+%P)GAlERYI2r;2gGwe~sG&SE1r|AE3_lSB7=eN#QSn$I zcmk|(sU!*w79ePSa5x$sq2Z}C5^U3<6(iBe2$4)AQYh^D<7rd`4@))zl|r6r3XVvF z%{$N|U?2i|ti41MLZTv&nFa~5Y7k&F;%NwEhcy|E-B>CaPllB<5mF&E(oDN)1Z+h} zfn+2ig*rn5BA|t(9F;;qC=>#XO;M-^m4J|m1TqkSOd~_RF&aW!aU=pBN5zwAKnNUh zhDd0mDP%G%+z3P<2||H|GFn?$3L_vx5F&|8ArPPz=<*hAJgn-WzkudY44Dj7p(5lN zGE(pq5>yx_7+^Kfo@fYxFhfxSnE>-Tl?uH`gM}WRM#4dnGsFeHq)}-^=vN|%N+J^} zBq();&NPHZq!D2m2YMLL9}h@ii8;eEM4$u6JrY8tlA$kPaSKIr7zviXApOV`5|Icp z5Dzp5qCw?mIs%kCG8OG{3Lbih4CDvu0d6+ik;qgcEUW=9Y^PEY*t7sDQfV|cGvd)z zG_-?=?z)232y6s}eNTxtu=m{Vt z#{5(&?6m+NL%k4mETMA&Z~}=y0KT2+VpQn`?G~X?p%7p?lo*g3PbO3F&|@=W5QZL+ z2<#5*1%rctk_62U6AQW_J=5{9Sb!Zh0)p-gpsYy(!k`$SlhF-n_OK!W-@uj$x^aTC zDxL!S&wv8D88(KXxUV-^(&`w}XR5YL*4BP-i zmkI-j0)i7p2b+07iU4_lO@W&*h6X7G0)hxbia-M?1H)xza8u!l4EtRuV`1z~K^YOY zc|hjSV4wg6*+YJ2>9OviLFPlpv0)Q~0NLR}y(J{cAlebzrUDD4}Ax9`iS>eRAhIU9D2P|spapwR#C|=RV`@2A%CEm0WeT8crNF z8_;TZvD;Lx5ca1oiTn(vgIdzP^)!K*UWHJowutd^6DTX2<=XZb)j;(VZN*HLm`dWTI}ppz)AwB&+_@ z;1{9}mDCb&VDI})nfV`-H)^z4+9iKGvE5lMWxeHoNvW6P{=?_D*dIMTxiL)mqPP5` zTGD{~+80)0MuZNrw+$L;@+s1nLdpYF$(~p4rmueaJ*Knz!O5KD`jpy_*Uksdj>_Ft zXp?SOQZ6sAT>UcTdDc|<9WjlCwp_K3dp4yCaY@GQxjcF-L_AH7e^uI<$4h%%Pmc~# z?2cEe3-xb$y4>T)*T;(QZw8aj9IH^1-F1J%e0{2fTH~#jyc?oZq2=VUG8?*AL(sP9 z_)ABOmOi9bc0FmUQ=~b37~P*>J-Xv$+I6b?m%4>gGDErxoCAv;K7FNM{IuvyS%@4( zF?jL4SEs9Ze9n9kyJZ!V^t7-oVd+pt>#@C$mm3~9z!YqcJCQGUp_cNIuaA4%Ki92qo%j;)y+Em{{6yAn)WxNjiJ zO8bvo`f{XeVTk4ZyKlDqkUV7>AQw(r5_R1_(X)NeCr)k87(XZ zvdsQe3*#;4OQ7w@>RyI5V0o8DRe zBvo;~p0qowgf4HkK=ES$R0h>_vybor97; zZ>YtoWj{;o66m&AZECu5LLzR&c-!ui%2EDH3X%eS8hDiw1Lj8%U-4X58 z=e!;z_)|=cI~y}LI?R6^xy(3a-*MvmBFm_C_}69Y9N+MiYTqUuzbh=fDKXDUO>V=A z2L$7kTbAqB@$6%D%{};7FzIS?))YO)`F-`v-9FRlq9?;j^ct5Q2=;uFt7JMI?$Vwv z*s3IDL?2I!lh_%z@h9sb*O7WnpSN4XjxF#%hSw`#Ib8d2WqO{3LrR6^VvCfU49^Qb z=cZ*(%rEU0o+H#hUQ+9c9Gm{Qvanbhims!h_@K+87nNQrdjCi7~H)o62LJPIaRLAitCxLxG zcOG-DAKq^?dP}x;d%2TV%muF+t;nr1InSLnRrWYtS#sQPVPdBE**cLB-1tyg<q<}CSwu_+9&`;Z%Sf6>mgRCFzNn;{w zOJXGY#7y6@WM9=J+;={$Lu*q@=iixe_Tu2Vdz6ubJGe}y&Iy-Q^}H>fmweM7@ojH! zc#+rnYX8f9#l8*Z?uc2z!#yvhgElDEwZ05;j5gh8+je?(@XqjW{Xd;;Hs)k}Ss(Z0 z=q~@|k%f9^lyI(FVh*P7B;=T{yh%<9ijM#Cs5|a_S)##%qF8EQ>%&*-9e3Q^yS(W; zGxF@_j?3JMD|l(JVMiRs*T5kjz8KaZXX60^fykG+=1e=PKD|HT$@TEStn>O8H> zoh_*n(!Sq4m)s=W_rf)Qx18wSx7qZNWQU8n*YlS#+N;NxYG?6Z?KS@*I3c_?_nN|% zR~DDDJ{{SAPBeCXi1E7hgMqg`A3k7yxMNuHAgNd_OqSZ9n$+N!n7Alct%sXQ4F(^!^kqZ=}ilOeTv#HIEAsEJqOIx^SE`l?dLfXFSBA-?gTk2jXKe|VK8 z*CM#q_Wgr~-miy8-8J@ZcwATBt+dH|@QCI$MLpKp^BrY5OJnvn_+B^r616zLCqL0? zBENfd&|Td2N10;pF3YeBN3JD{jOlqEs_D{kspx8-e?3x8LhXir!ou4-BD(h^1ZeM9 z_u5wPz3JQ02PMe|)Cl;)(=Mk!G%UT4Om!@om`ubc#(jD0qg3Eoa?AIA?4)$F*Nd>b z?)8O6rO#Q3L36*YJ$iewdGrUKy^bOth19nZqdOWOuUzf3BJ}DnDaR95@@#%?261B+Z15F3+bR_2&%H40{Equ=!-F9a3a$-sAopWTC;GOv%fiB`k zm4)|z#=B7&Yghp>USeu3!$r-9&l->-v{m2So^Wr7D$5vaKD?VOU^(%$(cn^ra97pG zF-s*IVW;uT;p?CGD3Jt2586pART6$C9$7s)9BtjTp~=N7KYCrK=l$M_MWVTM%@NJ5 ztsW+QKF;@j|?rDC}C66!LI$U=T*e3 zI+@x$vj5nkg51`9Dl2+?tN-$Ky!odt8eEK z4lCTd6#XUD_*qt7yYn2??-6wg?;fhFrU~g^!JV0BsJ+tvO+l(jedWQOAFt%e-fn(t z+0$23EX?QrCFj!R@2>j%ocb;?_Fy{))F z_RWQL?Z*Q4YYsLdk9jI@jT?;kT}`pRXkI*Qx@?7u(NB5+@w~kATfr5J1Wuf+;_i8S z^);W^xAgL`+JPPKMi=kT4}ZG<<=FYve11${siCzOcP_twarUQ|ijK|3SNt}rhC78N zhA%siIzCJP#%y!5xg7%z-pdy>ocWnc{c$w&USHx#&u!9y6;Jh=>}ssPS-l7=c4^OP zUa~8(CQUuHc2B@EfiLk}tB#g?Gu2I0N`uMAox+YE@<@KzFg3*+>qu|i5t(9zo1B%b z?dI067(s4$x3WLSY$CUqs8h2*SHMOwzxc$&3WKej> zQ6DEC9O9e&=+SjdqiAGk&p`E5Yl7p};M!X^E~f|dE1&e9iuKwkPWNm0aW=f=#Fq9+ zBPC<06-6E*haIRJint3J$rtzf_3`}_Z}y~r?pS6UY$Nlr`T73uuRs568)-iAbl19? z&H4cwo(APgyo_9DEuZt9DMU-wSh=flf%B}72hP`hja$3N_i~ZKu%fc_(6)U4h!N2m zQ(c>R7dUj_>+~!B^uq_Pmydke zd&O&P?oX4wx6UU{R_6qSSDxEiS@bAa$#fjGy7M;rmnAL9TGFLfn)KOgAO5<)i%zC%%u)Kb2h7oWEsL*RB6iakM6H)97n+FV z;06v_Iixk+YhSWlZ*Rw;@p$jc4_|FkNxtgZyEC*oVaxGtqxS0@>SV(=yEw_z?n~X_ zkQ4Hqzw0~2Uw`0?T=j^|>$*MKPV{fPh`aipo;y)~_Q`;9(m-28g_T0c&1KdBr&}|R zWC|iT_i!29u6rX&ezK*;Qb*LZF1Vf6P}XxKC1Y)$FiDc%pKjh(Jy3de)z3BQN(%(- z60A#)c{5ji?*FcI{zrLE&-~o|iyOAfhe}8Nc=2s@{eFe*(QCCw=Co`c7~iw5+R5;# z!-qA5fcz+-zMrQ*E(qYtod0&{+K!#sYmZ)fGBjwFrd{sVf5#HYPh23pDw|UvbL?uv%7@2SQnsG3JlN%CJ8G>F^lr(?{Ygr1Z^i9+sV+}8gR$dC=TYks>_Bok(#gtPA?iLqY&niS1+f|~&Tcz7v6I$iCQ+<%mG=tR{ zKb7LX9{;J%r@}&Zh209!jQKIQ>h`7S`}+B&3d`z~y&1mrTqLhQ0oIatlYGRxexNpMU}arfa(~s;V}gtOb5Hi` zos=DjE0Oj*zqmVhfeEko&a}$jWA{(#=g;AZ8%*0}Ec|15_(WobG*NY9hvOWDv~@LQ z1F41GN+d(`<`TDRH8rNw!n1dl#*l9dj%DfyG#R@&iKemca`iUuc~tlMVK8saq9c|0 z*LaVdKHcuWeh>Y=cO>z7YvfAHb?XwWJ}K`dH)ie-9vAfO8XbN8aM)<}wd&aLp~C_0 zJ8~W_wRW|=qT@Vdyjju(?{j{bL+r>me=*Q25KIAg!7FImQ*ZQ5G5X1 zx_g`6X)!7f-Sxm=xzqd`jzc{+9!uF}q-r(1%ZZHKuu5n^V&^L5CsAe(mv6tH8SZyb zTDq+N(%r6mTz$_{qV6^~DV^%{es8&?#lbbZ%Fgr20mH#0V*#!agOBSPJf8i$+pt8o zD6Q+x!0uC(gSAk|TS(%k3n`Nmjyq=uAGx*1X8X&1HTNQpZr60` z@ILMu_2h{2=7nUzmZR~D2vc_2*(5*N%&2H}CTlK)ZZ~D~~C@zwjX~UWO?;f-8R92tXx2-DF zRxgXX*qqY&^U_o!ZT+jI*BZ03-&U3GirLtxZ2!38tp2yHk{JT@uS;+`NBH<2ZJ=rO zNLOX2em;67DammbZ`Bg>S<0_!L(Y;von*@0-nl%4)>fa|X{BsglVb8?s!aMe*Yt-o zw%vNdC;igDHFga(v`@W#DzS9uI$q203kObCX`8u)?ow0D{=SpGQEj5#BS|2tt=xEP zt+oQs)yaDEEqz^CO%Iof`w=&1s2g4I3p_(=&`IX6ymHkx&!lKU(qi$&71xVbNrq|k zusZk@m~&n`i`LvLEp#xQ<D?znjo?oq_BYh1js3gB z_SqLaSZtr;<#Qg`e(T@hpMQl-5C0Wj-uzcsdh9RoughZWP)2>@U*hEghW`Tpz-Rvn zo7Py={t0uglySlqy-V81c?O>~#&~<-4>(_~)a}h5FtO>Tc-kNEb>;fwmA_$A(CE0H z|Ayc1A}+YG`#0=aas5N|sb4T_i)f8Z_oH8MMn$lCbaKisxM~gEL}X*>FSuZ+tzG=; z0}h;@BxLHbVr>!!Zaq0C5HlN?x|k1-~je!HCmC(*LLN9&oyvtiRdu1nh8l=K2N zy!^R?FY(UJPdC|cVb1(`E7PqZ6Kr_tkqe;;C8w?*nSmLjq&N23f^&4P&%knlE#fbm zSHDR5Is>cU*dP$7pTjjP4}(qP49^QwZpOABxQxO4$Cfaj+SG|%ZJ4=D*qJAlmcK4E5voVwe5c2vlMDOA(w5EnfWp-B4wpuqj=LA{jbx&5->rgm zr{I7{wxzrVK+~f}b|2^5uxL43lhX(AUDBPyK_MFkV%ycXrvrR^0g}+W=X0-ELX*pR zC~dbQ>-e)^)uRQTDq1fQgmFrT!PRB;9DnkNkyI*zXtvECld*c3ZNW?0D}M$-%;FR( zLv!q7J6Bkbetv?O3b<{4#%;)VNBXnE=0`h`R{wE7`p%P%$nZ$@e%^9qi`5n)&p_Hn zR)2Y+?)@&-qldXx8HHhHqnkeXc%9g>d~tG|!jq!KD*_#gObxkktx+ncJf>0_2d@q+2`358O-w(x%Z-gF~-q5W-^UJ7{hJqta`jDBbvZ7+tNjUYH9t>OMt0e;3}%+1xo0=-VHxYl$mskV zU$$SWxv#&}d{5WQB!yESzMp$u%uLz!@_y6~ZVfo4IHdAn=dm%THm|Otj%nL@(O1V8 z2He;b&}6tfqd87OR^;=R5i30h>ybUH^`CTXdNg#P;==7WqkAF`47T32NOS0K5IxZ- zF*Ll=NOt^Mr`mC^p=V2my-Lc8?Y~QmOS@UQX8Dgq7?<99pRV1jH(dQN@{*;3V4CCP z>+_Z_t)<@f58jDX=WHsef9h_hFFDZ2*PC%iZOXdeX;=NTorQ&`XGvZ#Yi!8%DlZQZ zD!;Qd&)NI+J*A=ThB-McgS+!X-D|e*J#M(Fqfc_~M9HbvR9)utv$vPXTezKEXdw9b z=b7Xw;b)CUKhLV+9kDIHF`*>Xq_kVdB05mrPb)a*N37msg4kM>ID|ezua9>!ri`+XF#2LP2pkrqO&}Y z?q}edGYU=UU!F3{#nPxZ5`VsodD7x56SLA}bwTB=i-o#tXYad+3tc1AQBHH6e0wK3 z#Pxy<-hL?BgR5no>seM6X}y|r{IXRK_0pm~M)u@O-KaD=4X^Ilw{GeR+CS@NzwX>S zbM)&8Zu;$Zw$aYx3vMt?^KHtBvAvhum6nJe*?ibU&YS0hXP)FH^BJteJV-Ds{1}JJ6GM+A4VWBAKus zhC-3T0}cDt#ky%qU!32G7b*HJ&0KxhEmTIvaINyI;~i1WFRKF+qqxti>rK<>YcX-L_0`E>tB-_rtRCs^dQj|ThqhKhL)?S3& zV)oI%qv{I|UOvUQHt zGrzj$(Ki`$vC^&U=FfAZSo^JA^DfWX?`;3x=tvEnT?d*~lnSn#PL%Mje7F)x3fNW^ z8%_I^SGb_TCDr$`x>x)1r5~&gytLNNsjV^nK0S^*$?y?v$bHmoP};Y=dU}g_dx?q5 zU}JmL?pgEtPP|C%XWd*}yI%)asU4^h(jq##;8oq@l8Z@ZE|!ZCu8Wd`fsYsQKX}`> zFG6_jWuBtUS-m&J1}rjEo^Cv)liQjSHTzjiLGP-nae?MstHxUSEZ0?!Zc6&U+Vb%8 z)Wab8G08ej*`q68r*iu^yA|~woZZ`xtF(G2b~Zgu`CEs}Wmgw(b4k$xsh;q8KgTR0 zLpRrMw+%Z@%-&VvC=p|4OZNAB{*?EL)z9+Gjb5Tho~9594>L2DcYl9aZEon2bidT< z>h(kGGn3aRpDVSh&0MgXOT8xHllI0>#dC$aH%3(ircHYf(Es1p8esmf=?4 z(b+OAc(HAMRrx;s^YklDFFh;DMBm0K6o^#Q+?T2a~vcWhrb zwC(DL@%~e0X_WA!##!mkLK5fSZtSz~HK@ri{`V=Xmq>}mb!TSyS4(vL#)4YbJyw&B< z)+B)^wNqLi*?tRC^`2^8J#;cV!*6@yrJokcBNV}_=kOhMV+7Y;-yd1qzF01~bjBn8 zOZ3&+;g{l)J?bJyi^XdT)J4Pn7CrX#-rsa+$G+oox2AeJ2$AWr+oI3l-)Y@GH(}h_ zY`HT0$%gV%9%pe)BS(t8fBMhbN!1sbvqj?S>458ZCofvfF569Ae=PSzSYFFlD+4k&+Hr;*>7{bFFFz|5sS@{JlXQ%$`SXKMlcQZLBnpmO z1~Dz(t&P4`b2Mk+`O3mRJMUvc9-%oGnAY{f^Pck@b1_O;8^b*@e|pV_fnuk7~AY|$-#>cPZSe3z@bv7_5B_&fRD%GyR;x3!J&3W+n8C^x4ncxwe}p1R&%`k^rn>sk(-FV z+s%v_4SoeN$C4i;^|yE;eD{`aRJ=xWzOj+|_C$2-<&{<*2|8Nb%0Cizzi3;X7g~IK zYo&R?jrv3Ts<})zyBF=8dg`)&*N^h6T7|rK_kZv3pIWK){lmA_pDmUOUc2};k@VbA zD)#d_kzBjbJzF%kgf%}b>0f*Hqj=*6d*!v4XD^H3p5+}XF?@U|{6$R2=yOkjcYBOm z?se|SDp9DgT7CQ3?pMm~I%K=zOPSiD-3rFpK?iHETu+e@c&|fz)>gguXKTLD!Ka;- z^nJ(Y(@isT4@Ktn?8I9E@T;kybhCmjFMmO!s{KY1UFa7jIKD8sFK`E9Xb^oIU7k;OtOo9OYH zgFh>nIp^POaJ=`pglB1iS+U;ixUKmTnk82J50>ZC1O;rK&t2NPkFiT(AW@xYT}~ge z+wbmDy)mG=x6ovV=<1~+Xd9)@eI(>hAC?F!U z>QHah7sE;QDF5oG3CRLA1y?2KYoykj2$Kpk7rgK4wbM8`U~;CMPbsm;K%|nC&TCry zDP`$x`R@xdZmpNRaZZqb#YjKHIO40KX2ZGO=occZ76wR{F5M?~*tB{it$a_~s&7}T zcik0ZG~Yc@9+q>uQvO1?bVX9Z`_I=>SMwP@nHzCDL#ey(=BC->qB*;mJ2Q7Ow`?s^ z*}nJrk0awBwwKimOy!Da)IC#M9lhgc(cCWPN#nTr5sRFjYX$7zAg8gzO*SPxd#8Ta zYJ&B}@K13?Iv+QFu3fZiw_?(oBL0zicXudRob`)TP&#z(tFQl;Sqb42^1Pn%28Yev z#&Fj^Bj`L3O#RQCEA+rv3HSwNlVLH=?$cnZp|75SS3T~QXfo9-_`s}3 zJ6;k=#M~dz4**45}D1Ky_thD5~!j2V3tPT$zmAc3K@ZI-kRtBF}CX~P0Pq<)y zvoE9WmMHz~J5P}(7cD&Z8_bLJH#)+7xM2Jc|GQ58Xu7Z9b?(b=X!& zbzVuty6L9XpEhntRq@|2XF}$_fZBA(pmJh(jmy=?=`PNR<=dyPJ5H*#F8rc?_j81D zp_6M|P03c{+K_W5*Hi`d?|jg5>$@-BF1Mqjc#G>2OV;`L^&MXKSTR1$E9PjsI_1yv zRBx^)z3MjAEIQVF!N0Zm=hSC~#gF$czmlG!>9ynMic3?YUvrmL-hXtd6LH;t_<_c; z)p+2U#k~^j1$#`&Z^gV?QrD%X-ww-f7s@(9zcaF86Tsfr}Dd zx-7+K6$H~>six-D4R5{Zi(f_y3=Bt91iqYTbDn*h`vrdGmX+D9A1t`%vUK<+ zJ8}}=&MvO4eY+}sp*!ipWa3t7#*5|sevCz*l`pm|-hTg%NW`A|`^@0bMN*^3UUG4~ z#0urb)hqkIpXxQ4^|CLwz^m`aqc=qhq8>lvo9&!FZRx6V*f-5)^FZ+cjc*Nnoh?iW zK30cbw)cjwnFYb?i*SD)zTe7uN6tG0zJwQyecKeih3gdopAY@@VQGd3T-8UvvljxN z%Ls!#4TN*Q?aFxD6bf_hoAr!$Vle0a*VpkL4CdU&5}4@4U_#*;i+@6rYV9tGzw-eGB%(Nm z`+P%ax($QL?DGcY=}ruOz~2A2o$kS4UiN;x*K{uie_-#AZ=W8-;5PPt^}*>e3|3_C zAD^F|z+kk`VXN(M`}FU3|Iq!__h2h?<~Ot7NkC@4u*KPboQp_c(VYE2T|^p#L)rUt zj))=#bN0)E5KRo`>|gCf3^ACqpL86t#9+?;P6J|(!JPe;N60D+=InobLN;J9XFq}m z=Z(Pw?EL{*Tp$M9vDfS7xCjj1!CpUaz-`4~&U!WqmxRHb^<^e56@xkJy$W0w2A^lI zzi!|TV=!ku^a@vq!JPHU1g-*uH?Y?WBKRr{=IHNg_<9WH=+pN2YZ%PYZ+-A>82o~* zZ^q+0F_@$O9m4luFh?J&#`j_{M?boYAH-mOw!ZQKKZd~^{eeuFz+ldN&VbAQXn;I> zel;L)V=!mFb0P@M#Ixt0P=W*obLN9R1ZfObV$0`~1Vs$y$ji$FO$;`>n0ok#s7B`# zf*}T%iodDKd^+do7lI`QKaP4)8{Cxhfsbg9!T)@{$Xgk{Mvi^d|3AhVGUVXXDTWMf zwSRd%3G({|M~0(T0saj^XyAX2!wOblcq?Ox{-;u)mdfz?DfH9eZsC!ha_oZT(U+&f z;X981_U_b7<9=m>?_NVTw6s5RVc*3--`DpBhrXwezN3%6pO3zqj~%t3@8rY#_*X(c zB`<(9@go&G)|&+>4HMxlhyuCDJ0RO+( zd+)F~k|a?)qlze~s;;8CoA%JOp`r0s$lGzUBh6@Lc5mn>?aWJ`5`XTZagxAtgig(AzWeB*uVRi9E|Z8qHOMy1QL{_E~;b?!HNE7~>6_;b%2o>#7)b&1=YyVViy8MN080j2-uB zlzi0}WNftGG{?`T`z!SxH@D>+weK8n9UsCP`R>hW)}I&(kPYSKt0C+_h~;_+yBzYt zi~4mtGxDWrPF9JCucyaLOTGcffsz)ZYo? zoLsBv{6cxf%B5DE zW0ZGTahY*8p`S7(j&fkJIe5#CJI&f%8`hb%EjGMw))v?>FTy^;#%4x1sMOl)$ zj*w?r@Nq=&lm*XNl&2OLY*nt@0CNVX)> zc`y=oMSdNR0uUW890m4;SOx4qqZpe2LHf4_S`OzRhx?Oe*7@0tyA#;Y#ihVLBiuX) z(!U#^WfQ;ycpdjIq?-)BAIZx&ek_RBflYya#NH{KxKI~=id(dd6OVH6U+gQR+f+nl z-nEu+d_NGWmfYqtxtv(U!Dziq2`6s;zRG0VrgMA_gi<}jn(G6D z>Pd&VPu+8PJ`X-&tPVnVaO@Jyq2`a`#pygu;;G;qUOddd)T!n^eQw>(@v}grrF?O7 zU5hz!69<)gpSE-2_1EemKK#b@kmHX)=mL(Nf&o-b9Vgava78ckkQ4J?u7<{u%6zwa z9{stVfmF{KPQ1s#RhiNVqgy#=H=u(ayhp|-VCMWji;elRe2rm}Dp^WD( zYZ1r)QKY41F#M6?4{+i*4ukXEVYDEJNR)`k8gCk}Z-+x)rUs^s~>T<9f^jo|bS zmGI(H9_Hv{TFHz1UM|#B)B=J`M;i-~_c{I`i1YNybP2EJ#9JI()SGyp6DbngOA`LP zU*Bn*-g6z`_zDOe!m-NcnkqT5hJ#Hy&ku0o)mNC&%!?mcD>;4wh_`@EgZ_HAIB_Wl zbM!J)y!N#+B;$XS*Yo^P_!SvD5PF7V4?(vYX7b`H9v1P`t@XTk?d5L$6|(o=m+|kS zQ@+bw`VM-?KOU?N98C;yF2_zbGn~ZXwk{6D@CHsSe4TIpLa+|v`LhtZiepzmpMcjn zv5ABGdYM7IxcK!l|9!ps*U0N%Q#Kj=gTXa{=NlljhGS2g6y@P__< z2j0`1+RgEEK^#c7RWs{pf!W5vI-QNXUso2*GW#3Xe_Qu?|G`ab+G4;)-3TW2Qrx_x z&D7Nk)mZn+l=|*^`M=Er8mG^^J3{!8Fo}d{78kmXXA8LjWDqV65jTfGWe9O%M~Lzu zx5IjNe~3N4@X4_WgNnp>=i@C+_56qrQmk zPBo&f;#0q{Th z6{sB_Varn6~k!ODp$MCES@D#9FI;C<>9Kn;}n0bq1^_)!BOet?% z%|pfOl>QR_eG~7$Yu>l<@!Rsh&;GZD2;hBoK#i zWZq<+2Qua5{<@sMESv2i#UEAz_@40Z>?84ivL6Q+8vw>4fH69O=^z$xunIECJ97u* zyjKbQMKb(t{P>pqCJ3`*2Nu;uAMbA&v#*ukZ<6hA$@|*5`+d&MZ)wBV_Uro?zrR+7 zzGeKrZOp!wzuz#{Bok(A&FsxG@on{gTmE2-Y-{$~D&+459iou9AZR8IVvJQUcc?e*onx!+&guCLbd zRamd@>v;7F-Z#^KyfBFM_5B;=~HZO;HPvt^e6gJU^j>zm|twolKhPI7Jmsp4Er2@`sY(D z-PUc@7W;GfTZycDa?}>`WC!6%V6*jW9OaxghKDLH?Jh?i4~2}?S-i1|hgEMdQ2!G9 z{{K5$`1`aw$@cjKS93TDgoAXj2I3x`c1HT4+$r6PKf!6+b$4mnY@Rlg$|fF8@x}){ z+eo{X}e13i@ zkI=V)f79I0??3H{m9ZyQp~A)n*m}RHW3q{{$tK}|iItkZkF;|%@6JUCHzU}U2=9wJ z?o-aJ&vH=h`u(<*pX>JdL6b1-I?nR>0gKc|5&;u)zBYV+s8a(%R|&HA#8I9 zDX`~qOL=!fSlerqHzPz{9>SLXIZtz$=p<_>XygZ*2xNLRpXKTY;$ykQ@jP44k-np} zD7JyV@U=mfr$n)x@(yx#jC191MNzCU%JXGCrlY((C6tX6T1^dQTLk?arn#)VfOFB2 z`F5R@PAi3#iHv^L3X!eROy@0Zj8VR6Vb{#z1V1v!;%V;kr|dxIcP zSLkv>N~yxGiHE2|Iz1bsV`lo5FNCt8Lio8*HbJ>LdnxYICRbuyvjwCBYVaz zBDxDg0vnLdwm&9k6Ka(Rn@~E0Q1jLMCUpLhqDK)3Wow1NabD^w0bFsDZ61s17%c4$lu|-yOoQvk4THs=n9fpfh?1;m9_9v*95?EcrlIP=BloJB?cs7kl zPYZL7&cI7y#)+v|E7}Nd6wNEr@sdF(O2cR2hVpbAYLlaQZ%KGw$qzN2r*dE6!W4qBIYn)+o92*sg5S9Beq7T80Q--q%DewT;cHkzJA<3f}1h8w4w zZ3J&Hn~z1~daJM`8mq0FsoA-9aVNoc_u$>gXv&=sWzX}lrBRN}9^4=0DEF|2D0O%=j&aMBGQ%Al6ODV_21-BWRw!kB zv_iKSu{#D=dmVFP*jcaI-;e!#GNp|11&8`^t|f*&~@$e{KC3t884fy#4>2?A%CP;;e zkejFyVril@E(zu(b|Cm_qF9s!cN3RTb+3wsK3BRHa5?bQ!d4sQ0akX;m~qd-W|(rR zs|zFK1`9hAAwIUSs}Xdx_9#NTWMRWC>IDm%Y*8t5o+av*g>AR!<|xrBp_?Wo9K$eb zO$Rn7G-_-Ib~j8N-+}cPZ_pxlQ|Z;vo{iAdBkkD?qx!HtJ7-cycVKr+E2z{gyL_M{ zdtjFfIWD5E>EnE~-`M^XqUNS24C$zwaRXD#H>9oecj z=8GLzQCsaQ<+im<@5pwv)y8*Z`R&d7+q0$ZO_w{cE$yc^FN9yp27Pjo-3S-&1lbZz z9G^hujNw`mI~k!i1gX1)#DIY|;aHIEwL3>9V1Yv&6pzbYHiGxN%-7@bf=l0H+=&vl z#^ZyiH3V093@78U)+3#d$Jt)-K|I^*Rf)o>X4z=;Y3CAgq+hE{#4^8Do`@U$4t;&} zTZ$6cBfn!=0=pR_QX3w`(3Kcg9;eQX$8~Ws$=>d`z`}UEtINjDpn(vN=(4dSUaE?R z9r4PABxs6P&LqI}1aV;ktV>V{-lfaNtVC&PBCJi6Y7?O*Q6oxI09Ge`WZj5Df zA|_C)tE|GZSX!N}SL5)i-FPe($GU6;FLIeT#o?7Gp*RkAdkhtEILxc8j>GL_da>WQ?OU$R5R*sST3@>f=~k z7Lbp`;w#56l!7rSaoVF8x?CH%)xQW#5gF4Q|>3g;W*`35Jm;X$w8PKq>+II z@ygnG*b=W?jfdm$D&gFXSFR*LzXXazN_-S=CBW8%LDa98r%v-7JyH#a4AfqOSnOv7 zinxg`Un+*8IJU*8migI1qpn|Wn+3WRzro^M9fNsRb%`Gr+ie8b*v*A8SZAL|I1in| zJwHBk?j(47lp!|;8=|C9F}TW2s*u&WRibdy-K<|cT0txpd$dadtng_21GwMg7#m=> zJ@#!eY=qZwHipgceneB%Yo&%1`P74cT!NeiEV6e(9zk z9{81UaWF4N85w|mG2+P>xE7-l+!#Y5bSNO53Bc8Wlotz+0xBVniB)prU|MVkf=|VY z`EhV5_H_|zDx#ZA)!ZoFQ2j$Tg@wuUpAw?N)(p1FQ;|?SXcF8UpBK>`2yY#QYC}_ddi`A6RyN$o77qP}$QT7zp#hhe~c=7~NMH_XF74 zSDE_}-03Sm=?lX?QVHJnv2x^NsQXyS`2_BLtP;+MPn6srz@$&!Civ7RV*U@{(kC

-<6($#mW7f(CbfeCU2SId}WJs2QEoh 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ⅆ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 z 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 From 2b0d1fcc4ce8436553b8a068bb9b802da79362b4 Mon Sep 17 00:00:00 2001 From: Farhan Ali Raza Date: Tue, 27 Oct 2026 14:04:39 +0500 Subject: [PATCH 7/7] Align pyplot wrappers with the shared Axes typing protocol --- python/xy/pyplot/typing.py | 8 ++++++++ spec/matplotlib/compat.md | 3 +++ 2 files changed, 11 insertions(+) diff --git a/python/xy/pyplot/typing.py b/python/xy/pyplot/typing.py index b399ba83a..8f59bb8a6 100644 --- a/python/xy/pyplot/typing.py +++ b/python/xy/pyplot/typing.py @@ -40,6 +40,14 @@ def set_xlabel(self, label: str, /, **kwargs: Any) -> Any: ... def set_ylabel(self, label: str, /, **kwargs: Any) -> Any: ... + def tick_params(self, axis: str = "both", **kwargs: Any) -> None: ... + + def margins(self, *args: Any, **kwargs: Any) -> tuple[float, float] | None: ... + + def locator_params( + self, axis: str = "both", nbins: int | None = None, **kwargs: Any + ) -> None: ... + def get_xlim(self) -> tuple[float, float]: ... def get_ylim(self) -> tuple[float, float]: ... diff --git a/spec/matplotlib/compat.md b/spec/matplotlib/compat.md index 83c11707d..22ea5f0dc 100644 --- a/spec/matplotlib/compat.md +++ b/spec/matplotlib/compat.md @@ -254,3 +254,6 @@ python scripts/sync_matplotlib_compat.py Review the snapshot and generated matrix diff as an API change. Release-level changes are recorded in [the compatibility changelog](compat-changelog.md). + +The shared `AxesProtocol` exposes `tick_params`, `margins`, and `locator_params` +so the module-level wrappers stay typed in both native and compat modes.

5k~!pRBgf{oa46=N3`c(SM`u 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%0D$##zKX)xQqd)2QVKCQo(aI1E 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