Skip to content

0.41.0 — Interactive Slice tool

Choose a tag to compare

@jrvannucci jrvannucci released this 20 Sep 13:34
· 40 commits to main since this release

Added

  • Interactive Slice tool for pcolormesh/imshow (options=["slice"]).
    Scrub any row or column of a mesh as a 1-D profile with a play/step
    slider, toggle between the heatmap (with a dashed cursor) and the profile,
    fix the value axis to auto / colorbar / custom bounds, and couple every
    mesh sharing the same grid to one global slider with "Link all matching
    axes" -- built for figures with hundreds of meshes, where per-axes link
    checkboxes are not workable. Off until "Enable Slice" is checked; curvilinear
    meshes are excluded (no single row/column to slice).

  • Modular toolbar via options=. to_html/save/show/
    show_in_jupyter/Report.save (and PlotPressWidget) take
    options=[...] for tools beyond the core toolbar (Pan/Zoom, Home, Fit
    Width, Axes, Point Picking, Annotate, File), which every page keeps.
    Nothing existing changes unless asked for.

  • Slice companion panel. The Slice menu's profile can be drawn in a
    strip carved out of the mesh's own axes (above it for an X slice, to its
    left for a Y slice), beside the heatmap and aligned through every pan/zoom,
    instead of replacing it. A radio in the menu switches between that
    (the default), the profile replacing the heatmap, and a cursor-only heatmap.
    Point Picking works on the strip -- a click pins the nearest profile sample
    (x, y, value), which follows the slider and pan/zoom, steps with the
    arrow keys (staying on the strip's edge, value in red, if it goes off the
    range) -- and Snap pins to
    slice
    (a checkbox in the menu's own "Slice view" group) links pins in both
    directions: a heatmap pin gets a mirror on the shown profile, and a pin placed
    on the profile gets one on the heatmap cell it points at. Extract ignores profile
    pins and reports the heatmap cell instead (never the same cell twice). When profile pins are left out
    (Snap off), the Extract panel warns and points to Snap pins to slice. The original stays
    put and each pair shares a label color.
    A colorbar attached to a sliced mesh shrinks to the heatmap's share of its axes
    when the strip is above it, so the two stay aligned.

  • A colorbar shared by several axes shrinks with their heatmaps when every one of
    them gets a strip (it stays as drawn if only some do).

  • Save / Save As keep the Slice state. A saved page reopens with Slice enabled,
    in the same view and orientation, on the same chosen axes, with the same link/snap
    settings, value range and slider position, and with its profile pins.

  • Point Picking works on the "Profile replaces heatmap" view too. A click picks a
    profile sample instead of a hidden heatmap cell, and pins carry across a switch
    between the two profile views.

  • The companion strip now works on more axes. Axes with fixed ticks
    (set_xticks/set_yticks), axis("off"), and axes with a twinx/twiny
    or secondary axes (which shrink together with their parent) get a strip too;
    their static ticks are remapped to the smaller heatmap. An inset axes is left
    out of Slice altogether, and the axes it sits on still gets just the cursor and
    slider. Also
    fixes a twin's ticks being redrawn on the wrong edge (and its parent's axis
    doubled) when the view changed.

  • Choose which axes to slice. The Slice menu has an "Axes to slice" radio --
    All axes or Selected axes -- where selecting axes is done by clicking them on the
    figure; only the chosen axes get a slider, cursor and strip,
    and "Link all matching axes" couples just those. The axes startup setting takes
    the axes (or indices) to start with.

  • Startup settings for a tool. Pass options as a dict to start a tool in
    a chosen state -- e.g. options={"slice": {"enabled": True, "view": "companion", "orientation": "y", "link_all": True, "range": "colorbar"}} --
    rather than switched off; values are validated up front.

  • Gridlines on the Slice profile. A "Gridlines on profile" checkbox (and a
    grid startup setting, default on) draws light lines on the strip and on the
    profile-replaces-heatmap view at both the value ticks and the heatmap's own ticks.

  • Docs: Slice examples. Four examples in the gridded-data gallery (a heatmap
    row, columns with the replace view, linked meshes, chosen axes) and one at scale
    (a thousand meshes). Every live pcolormesh/image figure in the plot-type
    reference and real-application galleries now opens with Slice enabled, and an
    example can set its own state with _gallery_interactive_options.

Performance

  • Slice on a figure with ~1000 pcolormeshes. Enabling Slice went from ~14 s
    (without "Link all") to under a second, a linked slider step from ~3 s to under
    0.1 s, and view/orientation switches from 7-9 s to under 0.5 s. Choosing a subset
    of axes stays at tens of milliseconds per step. The cost was layout thrashing
    (measuring while writing) and per-axes scans of the whole document.

Changed

  • The Extract panel now shows JSON by default, with CSV/JSON radios to switch
    the text, and its "Copy CSV" button is now "Copy" (it copies whichever format is
    showing). The two download buttons are unchanged.
  • New logo, docs sidebar image and favicon. Refreshed artwork for the three
    images already wired in (assets/plotpress-logo.png, docs/_static/logo.png,
    docs/_static/favicon.png); nothing that references them changed.

Fixed

  • Slice: a strip could take more than its own axes. The strip's 28px
    legibility floor ignored how tall the axes actually was, so on a stack of short
    panels (14 rows in a 5in figure is ~23px each) it claimed more than the whole
    rect and left the heatmap with a negative one -- which draws nothing at all,
    silently, since a negative width/height raises no error. The floor now gives way
    on an axes too small to hold both.
  • Slice: an all-NaN row showed the previous row's profile. Under "Profile
    replaces heatmap", stepping onto a row with no values left the last row's line on
    screen: the slider read row 4 while the profile plotted row 3. A pin on such a
    slice likewise stayed visible, still reporting the value it last read.
  • Slice no longer fights the legend. Slice and the legend's click-to-hide
    toggle both wrote a mesh's own style.display, so a slider step brought back a
    mesh the reader had just hidden. Each now has its own channel, and a mesh stays
    hidden while either wants it hidden.
  • Tick labels stayed put through a zoom. Three long-standing divergences
    between the labels Python renders and the ones the interactive view recomputes:
    an axis with a fractional set_xlocator base relabelled 0/2.5/5/7.5/10 as
    0/3/5/8/10 after the first pan; a lone tick at 0 rendered 0e0; and a tick at
    exactly +-0.5 read 0/-0 as drawn but 1/-1 once zoomed, because
    JavaScript rounds a halfway value away from zero where Python rounds half to
    even. A new 2,707-case parity sweep (tests/test_tick_parity_node.py) covers
    the whole range x locator x format x date x categorical x log grid.
  • Tick positions land on their exact step multiples. nice_ticks and
    multiple_ticks accumulated their step by repeated addition, so a tick that
    should be 5.5 came out at 5.499999999999998 and one that should be 0 at
    -3.4e-13 -- the latter printed as a literal -3.4e-13 axis label in the static
    SVG.