Skip to content

Resource catalog 3d docs#1042

Open
norle wants to merge 26 commits into
PyLabRobot:mainfrom
norle:resource-catalog-3d-docs
Open

Resource catalog 3d docs#1042
norle wants to merge 26 commits into
PyLabRobot:mainfrom
norle:resource-catalog-3d-docs

Conversation

@norle
Copy link
Copy Markdown
Contributor

@norle norle commented May 15, 2026

Replaced resource catalog with a more interactive list, lmk what you think. I added 3d models to the labware. I'm thinking of making a gui with a more sophisticated simulation/visualization (basically making biolint opensource but less complicated) proabbly in a new repo.

Summary

This PR replaces the old per-manufacturer resource-library listing with a single Resource Catalog page backed by generated geometry metadata and inline 3D previews.

What changed

Catalog + 3D infrastructure

  • Added catalog index build extension:
    • docs/_exts/pylabrobot_labware_catalog.py
  • Added frontend assets:
    • docs/_static/plr_labware_catalog.js
    • docs/_static/plr_labware_catalog.css
    • docs/_static/plr_geometry_viewer.js
  • Added catalog page:
    • docs/resources/catalog.md

Geometry generation support

  • Added geometry module/tests:
    • pylabrobot/resources/geometry.py
    • pylabrobot/resources/geometry_tests.py
  • Exported geometry utilities:
    • pylabrobot/resources/__init__.py
  • Updated API docs:
    • docs/api/pylabrobot.resources.rst

Resource docs restructuring

  • Renamed Resource Library wording to Resource Catalog:
    • docs/resources/index.md
  • Removed old manufacturer-page listing from nav and redirected legacy URLs to catalog:
    • docs/conf.py
  • Updated notebook links that referenced removed library pages:
    • docs/resources/carrier/plate-carrier/plate_carrier.ipynb
    • docs/user_guide/01_material-handling/heating_shaking/hamilton.ipynb
  • Updated docs workflow/build files as part of catalog pipeline:
    • .github/workflows/docs.yml
    • Makefile

Why

The old manufacturer page tree was redundant and harder to navigate. The new catalog centralizes metadata, search/filtering, and 3D previews in one place.

Testing

  • Ran docs build (make docs) and resolved broken cross-references from removed library pages by updating links + redirects.
  • Ran make test locally; run reaches an existing stall point at:
    • pylabrobot/visualizer/visualizer_tests.py::VisualizerSetupStopTests::test_setup_stop

Notes

This branch consists of:

  • 35f426db geometry
  • ea1972e7 remade resource catalog with 3d models
  • 712eff09 remove old resource libarry
  • 2c214a79 replace resource libary with resource catalog

norle and others added 5 commits May 15, 2026 15:51
Replace hardcoded colors in plr_labware_catalog.css with pydata-sphinx-theme
CSS variables (--pst-color-background/surface/border/text-base/text-muted/
primary) so the catalog grid and modal pick up the active theme. The labware
image tile stays white because the photos use mix-blend-mode: multiply.

In plr_geometry_viewer.js read the same vars at render time and use them for
the background gradient, ground grid and face edges. Alpha-blended strokes
use ctx.globalAlpha so the canvas parses the CSS color itself instead of
hand-parsing rgb() strings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rickwierenga
Copy link
Copy Markdown
Member

this is sick, we've been wanting to replace the static pages with a searchable/filterable list for a long time

rickwierenga and others added 2 commits May 15, 2026 15:56
readUrlState/writeUrlState read and update q/vendor/section query params via
URLSearchParams + history.replaceState, so refreshing or sharing the URL
preserves the active filters. Wrap the definition name in <code> in the card
title and modal title so pydata-sphinx-theme renders it monospaced.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When no Type is selected the cards are grouped under their section headers
(e.g. "96-well plates", "Plate carriers") so a single result page does not
mix unrelated labware. Picking a Type collapses back to a flat grid.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@BioCam
Copy link
Copy Markdown
Collaborator

BioCam commented May 16, 2026

This is amazing! Thank you @norle !!

BioCam and others added 8 commits May 16, 2026 12:42
… viewer

Replace the arbitrary floor grid with a true mm grid (nice 1-2-5 step),
add labeled X/Y/Z axes in Blender colors (X red, Y green, Z blue) with a
camera-facing Z axis sharing the X/Y origin corner, thicker axis lines,
bold tick labels, a tuned default camera, and a small -Z drop so Y tick
labels stay clear of the body.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tion to 3D viewer

Add a corner size readout (X×Y×Z mm + well/tip count), middle-drag /
shift+left-drag panning, double-click view reset, open the interactive
pitch clamp to the full ±90°, and skip overlapping tick labels when an
axis goes near edge-on.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a Visualizer-style reset/home button overlaid top-right of the 3D
stage (same action as double-click), short tick marks on the X/Y axes,
a tighter default framing (model fills more of the canvas), and bump the
size readout to 2 decimal places.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a non-interactive Fusion-style orientation cube (top-right, beside
the home button) that mirrors the camera: chamfered corners, octagon
faces with labels painted flat onto each surface, and the "Tip Spots"
readout wording fixed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rename the field end-to-end (extension JSON key, JS state/URL param,
filter label, card class, CSS) since the value is sourced from each
library page's manufacturer title.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Decompose the plate wireframe into subdivided edge segments merged into
the depth-sorted draw list (instead of a flat final overlay), so wells
correctly occlude the tray's back/bottom edges. Also enlarge the
orientation cube slightly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
project() recomputed yaw/pitch sin-cos and allocated three temp objects
on every projected vertex. Hoist the camera transform into a
once-per-frame cache and reuse it; the math and output are identical.
On the heaviest catalog resources (384-well plates, ~41.8k project()
calls/frame) this removes ~167k trig calls and ~125k allocations per
frame, mainly reducing GC pressure / jank potential during a drag.

Also route the high-frequency handlers (pointermove, wheel, resize)
through requestAnimationFrame so a burst of events coalesces to at
most one render per animation frame instead of one synchronous
full-scene render per event.

This is low-risk hygiene, not a headline speedup: the dominant frame
cost is canvas rasterization of thousands of translucent polygons,
which is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Circular wells now render their bottom type from the catalog data
(flat = flat cylinder, V = shallow cone over the lower 20%, U = rounded
cap) instead of always flat. Also color the orientation-cube faces by
the axis their long edge spans (FRONT/BACK red = X, LEFT/RIGHT green =
Y, TOP/BOTTOM blue = Z).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@BioCam
Copy link
Copy Markdown
Collaborator

BioCam commented May 16, 2026

Hi @norle - thanks for this, this is a great improvmenet!
I've pushed a series of commits onto the branch to build on it:

3D viewer: true mm rulers + Blender-colored XYZ axes, a tuned default camera, size readout (X×Y×Z + well/tip count), pan (MMB / Shift-drag), a reset/home button, full ±90° pitch, tick decimation, a chamfered orientation cube with on-surface labels, depth-correct plate-outline vs. wells, well bottom-type rendering (flat/V/U), and a projection/render perf pass (per-frame transform cache + rAF-coalesced renders).

Catalog: renamed the "Vendor" filter/field to "Manufacturer" end-to-end, since the value is sourced from each library page's manufacturer title.
Also, quick note: we do not name resources in PLR based on vendor (anyone who sells something) because they constantly change, but instead on the original equipment manufacturer.

One thing I'd like to raise rather than change unilaterally:
commit 2c214a7 renames "Resource Library" → "Resource Catalog" across the landing page, captions, and the PLR-RL term. I'd gently suggest keeping the existing "Resource Library":

  • "Catalog" carries a commercial/storefront connotation, whereas this collection is explicitly open-source and crowd-sourced/peer-reviewed — "Library" fits that ethos and avoids implying a vendor catalog.
  • The feature is modeled after Opentrons, which calls theirs the "Labware Library", not a catalog.
  • It's the long-standing PLR term — "Resource Library (PLR-RL)" is still what main and the wider docs/community use; this PR is the first to drop it.

Please let us know what you think :)

BioCam and others added 6 commits May 16, 2026 19:23
When a specific manufacturer is selected, show a collapsed details panel
above the cards: reference link (Website/Wikipedia by host), an
extracted "about" blurb, the curated brand-structure tree (verbatim
code block where present), and a sub-type count breakdown in the
summary line. Extension now emits section_path per entry and a
manufacturers map (company_url/blurb/brand_tree); JSON changes are
additive so existing keys/filters are unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Proposal (not yet enforced/wired) for a deterministic vendor-file
structure: one H1, labelled OEM metadata, reserved About/Brand
structure sections, heading-derived organisation, and a fixed
definition-table shape. Placed outside resources/library/ so the
catalog extension does not scrape them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ion)

Pre-PR, Sphinx/MyST rendered inline HTML (e.g. <ul><li> part-number
lists) in library table cells; routing through the catalog extension
html.escape()'d it, so tags showed as literal text. Escape everything
then re-enable only an attribute-less allowlist (br/p/ul/ol/li/b/
strong/i/em/sub/sup) plus scheme-checked <a href> -- safe by
construction (scripts/handlers/js: hrefs stay inert). Clamp the card
description (max-height + scroll) so a pathological cell can't dominate
the layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mark both proposal docs `orphan` (intentional standalone references, not
in the nav) and present the example vendor file as a fenced code block
so its placeholder images/headings are not resolved. Fixes the
image.not_readable + toc.not_included warnings that failed the -W docs
build. Also folds in the proposal revisions: About/Brand-structure
sections made explicitly optional with fallbacks, and Wikipedia
de-emphasised (Website is the only "primary" key; all metadata optional).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread docs/_static/plr_geometry_viewer.js
@norle
Copy link
Copy Markdown
Contributor Author

norle commented May 17, 2026

Hi!

I like all the changes, I think it looks a lot better now!

About the catalog naming, it was my and my AIs halucination, at first I thought of not replacing the previous version of the library in the docs so I named it different and then I remove the previous version. I renamed it back to resource library now, I hope I reverted everything.

I noticed some things about the labware. I am not sure if these are visualization issues or resource issues.

First the tips get rendered weird
image

This troughplate doesnt look right.
image

This wellplate's wells look a bit off.
image

And this trough plate has non rectangular troughs but the irl image looks like it doesn't
image

@BioCam
Copy link
Copy Markdown
Collaborator

BioCam commented May 17, 2026

First the tips get rendered weird
image

Interestingly, this is actually very accurate, it is just the very first time I have seen PLR's current TipRack accurately rendered:

The TipRack model has always been a bit odd: it declared the position of the TipSpot at the bottom of the tips which it houses.
But in reality this has multiple issues, including (1) the TipRack itself doesn't actually differ (for Hamilton) tipracks, so the model lies, (2) TipSpots render below the tipracks as you can see in your 3D renders.

I believe @rickwierenga fixed this TipRack issue in v1. It would be very interesting to merge your PR into main AND v1 and see how the render for TipRacks differs with the new TipRack architecure :)

@BioCam
Copy link
Copy Markdown
Collaborator

BioCam commented May 17, 2026

I will have a look at the other issues you flagged - this is fantastic because it really flags up the inconsistencies in PLR's Resource Library and forces us to address them.

E.g. another issue: it clearly highlights when the resource definition is actually incorrect in the code...
Screenshot 2026-05-17 at 11 48 05

...the container inside the plate cannot be closed up by the resource; it can only be level with the top or protruding above it :)

- Content fixes: imcs.md (malformed <ul>/truncated entry/empty image
  cell), falcon→`## Plates` H1, eppendorf multi-definition row split,
  sergi "Plate Adapterrs" typo, vwr internal-host + nest 404 link rot.
- Deterministic GFM table formatting across all vendor files
  (content-safe + idempotent; incidentally recovers 15 definitions that
  ragged rows were silently dropping from the catalog).
- Consolidate Falcon (a Corning brand) from standalone falcon.md into
  corning.md `## Falcon`; verified lossless via the catalog extractor.
  Falcon no longer appears as its own manufacturer.
- Rename stale `Falcon_96_wellplate_Rb` (no backing factory) to the
  current `Cor_Falcon_96_wellplate_250ul_Rb`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@BioCam
Copy link
Copy Markdown
Collaborator

BioCam commented May 17, 2026

This also flags a wider issue:

  1. Two sources of truths for resource information: the Python function VS the docs md file -> I recommend we choose only the Python definitions docstring as sources of truth (they are easier to generate, access at runtime and live right next to the code)
  2. There is no resource definition docstring standard
  3. We are missing hundreds of definitions in the docs: this PR initially only covered 95, I fixed a couple of md file errors to get it to about 105, but there over 300 definitions in the code, and we haven't yet figured out whether to move all Tecan and Opentrons premade definitions into our standard

…deprecation target

Remove duplicate/deprecated-stub catalog rows and re-point them at canonical
definitions: Alpaqua magnum, Azenta FrameStar, and Costar 2 mL now reference
their non-deprecated names; drop the redundant Falcon stub rows
(Falcon_96_wellplate_Fl/_Black, Falcon_tube_14mL_Rb, falcon_tube_15mL/50mL)
whose canonical Cor_Falcon_* entries are already listed. Fix the Hamilton
manufacturer heading (was 'Hamilton STAR "ML_STAR"' -> 'Hamilton'). Correct
the falcon_tube_50mL deprecation message to its real target
Cor_Falcon_tube_50mL_Vb (the prior 'Cor_Falcon_tube_50mL' name does not exist).

No code or backward-compatibility impact: the deprecated aliases remain
callable; only the rendered docs catalog changes. Docs build is clean under -W.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@BioCam
Copy link
Copy Markdown
Collaborator

BioCam commented May 17, 2026

This troughplate doesnt look right.
image

All these issues in the rendering are actually not rendering issues but correct rendering flags!

These appear to be real errors people made when creating these definitions:

  • here we see the definition having flipped the x and y values for the container AND
  • because the container defaults to cross-section circle, it renders incorrectly -> no cross-section explicitly declared in this definition as shown here:
Screenshot 2026-05-17 at 17 09 26

...showcasing why your 3D render is highly valuable and improves the quality of the PLR definition by identifying mistakes made!

The resource library catalogued 8 definitions under stale names that only
resolved via the catalog extension's RESOURCE_ALIASES shim (BioRad_384_DWP,
CellTreat_6_DWP, Cor_12/24/48_wellplate, Cos_6_wellplate, PLT_CAR_P3AC,
Hamilton_mfx_plateholder_DWP_metal_tapped). Point each docs row at the real
factory name (BioRad_384_wellplate_50uL_Vb, CellTreat_6_wellplate_16300ul_Fb,
Cor_Cos_*, PLT_CAR_P3AC_A00, hamilton_mfx_plateholder_DWP_metal_tapped),
closing the docs<->code naming drift. Image asset paths left unchanged.

No code/back-compat impact: RESOURCE_ALIASES remains as a shim for user code;
the docs simply no longer depend on it. Docs build clean under -W.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants