Skip to content

Render only the interaction types a community actually has (#199) - #268

Merged
realmarcin merged 2 commits into
mainfrom
fix-network-legend-present-types
Jul 31, 2026
Merged

Render only the interaction types a community actually has (#199)#268
realmarcin merged 2 commits into
mainfrom
fix-network-legend-present-types

Conversation

@realmarcin

@realmarcin realmarcin commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Resolves the network-legend item tracked in #199, and confirms the sibling item there is already done. #199 itself stays open for its two remaining cosmetic items (hero gradient on the UMAP/graph header, filter placement).

The legend showed every interaction type on every page

src/communitymech/templates/community.html emitted a static block of ten legend rows — a Taxon swatch plus all nine interaction types — on every community page, regardless of what that community contained. Across the 300 pages that have a network, only 857 rows were meaningful; the other ~2100 advertised categories the graph did not contain.

distinct types in record pages legend rows before → after
1 120 10 → 2
2 108 10 → 3
3 67 10 → 4
4 5 10 → 5

Changes

The nine colours are now declared once, in an interaction_legend list, and drive both the legend markup and the script's interactionColors map. Previously those were two hand-maintained copies of the same palette that could silently drift apart. The legend renders only the types present, in canonical order, and the SVG <desc> (the accessible description) now lists those same types rather than a hard-coded "cross-feeding, mutualism, syntrophy, competition, commensalism" example that was wrong on most pages.

Colour collision fixed. Taxon nodes were filled #3b82f6 — the same hex as MUTUALISM — so a taxon circle and a mutualism rectangle were indistinguishable by colour. Taxa are now neutral slate (#94a3b8, stroke #475569), so every hue in the diagram means an interaction type. Slate reads against both the light and dark themes.

Typeless interactions. The script falls back to grey for an interaction with no interaction_type; the legend now mirrors that with an "Other" swatch instead of omitting it. One record hits this path (SynCom_Sesame_Flavor_Baijiu_Fuqu_13Genus).

Also in #199: the stale template is already gone

The issue asks to delete templates/community.html.j2 as a dead duplicate. That file no longer exists — templates/ now holds only two research Markdown files. The similarly-named src/communitymech/templates/community.html.j2 is a different, live file driving just gen-community-pages via render_community_pages.py:121 and must not be deleted. That checkbox can be ticked as-is.

Verification

  • 266 tests pass.
  • All 305 pages regenerated with just gen-html; docs/ is committed and served verbatim by the Pages workflow, so the regenerated pages are included here.
  • The 5 communities with no interactions correctly render no legend at all.
  • docs/browser.html and docs/index.html are byte-identical — the diff is confined to the per-community pages.
  • Spot-checked the three interesting cases: single-type (ANME_SRB_Marine_Methane_Seep_Consortium → Taxon + Syntrophy), four-type (SF356_Cellulose_Degrader), and typeless (Taxon + Other).

🤖 Generated with Claude Code


Review round

Reviewing this PR surfaced four findings, filed as #269#272. Two are fixed here; two are deliberately left open.

Fixed — #269, the palette was not colorblind-safe. The nine interaction colors had never been held to the bar PR #198 applied to the UMAP. Ten of 55 swatch pairs measured below ΔE 15 under simulated protanopia/deuteranopia, and two failures were serious: COMPETITION #ef4444 and PREDATION #dc2626 were only ΔE 10.7 apart in normal vision, and MUTUALISM/SYNTROPHY collapsed to ΔE 4.1 under deuteranopia — the two most common interaction types after cross-feeding. The palette is now selected for separation instead of picked by eye; the full-set minimum goes from 0.0 to 15.4 with no pair under the floor. Original semantics are kept where possible (cross-feeding green, mutualism blue, syntrophy purple, competition red); predation moves off red and niche partitioning off teal, which is where the collisions were.

Re-picking the taxon and "Other" neutrals turned out to matter: the first candidate plum for PREDATION landed ΔE 6.5 from the grey "Other" swatch — a collision visible only when the neutrals are measured as part of the same set rather than bolted on afterwards.

Fixed — #271, nothing kept the palette in sync with the schema. tests/test_network_palette.py now asserts the palette covers InteractionTypeEnum exactly and holds the ΔE floor. Without it a tenth enum value would render silently grey on every page rather than failing anything. Verified by mutation: restoring the old reds fails four tests, removing a type fails the coverage test.

Left open — #270, interaction type is encoded by color alone. Every interaction is the same rounded rectangle, so color is the only channel. Nine categories is past what color can reliably carry: reaching ΔE ~30 requires an aesthetically extreme set that collapses back to ΔE 5–9 if any single color shifts, and tritanopia still merges two of them. The UMAP already solves this with a redundant symbol scale; the network needs the same. That is a feature, not a rendering fix.

Left open — #272, network-quality.yml is invalid YAML and has failed every run for at least 15 runs, so its audit has never executed. Pre-existing and unrelated. Not fixed here because repairing the parse would activate a dormant job that calls a paid API and writes PR comments.

The per-community network legend was a static block of ten rows — a Taxon
swatch plus all nine interaction types — emitted regardless of what the
community contained. Most records use one or two types (120 pages needed
2 rows, 108 needed 3), so nearly every legend was mostly absent categories:
857 meaningful rows were padded out to 3000.

The nine colours are now declared once in `interaction_legend` and drive both
the legend and the script's `interactionColors` map, so the two can no longer
drift. The legend renders only the types present, in canonical order, and the
SVG `<desc>` lists those same types instead of a hard-coded example set.

Taxon nodes were `#3b82f6`, the same hex as MUTUALISM, making a taxon circle
and a mutualism rectangle identical in colour. Taxa are now neutral slate
(`#94a3b8`), which keeps every hue meaning an interaction type and reads on
both the light and dark themes.

Interactions with no `interaction_type` are drawn grey by the script's
`or "UNKNOWN"` fallback; the legend now mirrors that with an "Other" swatch
(one record, SynCom_Sesame_Flavor_Baijiu_Fuqu_13Genus).

`docs/` is committed and served verbatim by the Pages workflow, so the 305
regenerated community pages are included. 266 tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…269, #271)

Review of this PR found the nine interaction colours had never been held to the
colour-vision bar PR #198 applied to the UMAP. Measuring CIE ΔE under simulated
protanopia and deuteranopia (Viénot–Brettel–Mollon), 10 of 55 swatch pairs sat
below ΔE 15. Two were serious: COMPETITION #ef4444 and PREDATION #dc2626 were
ΔE 10.7 apart in *normal* vision — the same red to everyone — and
MUTUALISM/SYNTROPHY collapsed to ΔE 4.1 under deuteranopia, which are the two
most common interaction types after cross-feeding.

The palette is now chosen for separation rather than by eye. Minimum distance
across all eleven swatches rises from 0.0 (taxon and MUTUALISM shared a hex) to
15.4, with no pair below the floor. Hue assignment keeps the original semantics
where it could — cross-feeding stays green, mutualism blue, syntrophy purple,
competition red — but predation moves off red onto plum and niche partitioning
off teal onto blue, which is where the collisions were.

The taxon and "Other" neutrals were re-picked alongside the hues rather than
after them: the first candidate plum for PREDATION landed ΔE 6.5 from the grey
"Other" swatch, a collision that only shows up if the neutrals are measured as
part of the same set.

tests/test_network_palette.py pins both properties — the palette must cover
InteractionTypeEnum exactly (a tenth enum value would otherwise render silently
grey rather than fail) and must hold the ΔE floor. Verified by mutation: putting
the old reds back fails four tests, dropping a type fails the coverage test.
Tritanopia is reported, not enforced; no nine-colour set survives all three
deficiency types, which is issue #270.

275 tests pass; black, ruff and mypy clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@realmarcin
realmarcin merged commit 5255f01 into main Jul 31, 2026
@realmarcin
realmarcin deleted the fix-network-legend-present-types branch July 31, 2026 01:50
realmarcin added a commit that referenced this pull request Jul 31, 2026
…) (#275)

* NEXT_TASKS: reconcile to 2026-07-30 (PR #268, issues #269-#273, PR #274)

Records the network-rendering batch that started from the last actionable
in-repo item on the web design review (#199) and the CI hygiene work it turned
up. Adds a "Per-community network rendering + CI hygiene" section covering:

- PR #268 (merged): legend renders only the interaction types a community
  actually has, the palette is CVD-verified (full-set minimum ΔE 0.0 → 15.4),
  and tests/test_network_palette.py gates both enum coverage and the ΔE floor.
  Closes #269 and #271.
- #270 (open): interaction type is carried by colour alone; no nine-colour set
  is safe under all three deficiency types, so a redundant channel is the real
  fix. Records that the UMAP already solves this with a symbol scale.
- PR #274 (open) / #272: network-quality.yml could not be parsed, so it had
  never run; also documents the two conditions that could never have fired even
  once it parsed.
- #273 (open): the 26 audit findings split 22 soft / 4 genuine dangling
  references, plus the missing auditor severity levels and the broken
  `audit-network --json`.

Also notes for future readers that the surviving community.html.j2 under
src/communitymech/templates/ is live and must not be confused with the stale
top-level duplicate #199 asked to delete, and that the taxon/"Other" neutrals
have to be re-picked alongside the hues rather than after them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* NEXT_TASKS: add a prioritized menu, correct three drifted numbers (#276)

Reconciling the backlog against the KB found three recorded numbers had drifted,
and one large gap that had never been tracked at all.

Corrections, all re-measured 2026-07-30 across 305 records:
- Causal-edge coverage is 59/305, not the "~65/304" the causal-graph section
  claimed. 246 records carry no downstream edge.
- Records with no growth conditions is 80/305, not the 52/295 issue #183 states.
  But 52 of the 80 are NATURAL field communities that legitimately have none, so
  the curatable slice is the 28 ENGINEERED records, and even that includes pure
  computational models. Real target is ~24.
- GTDB grounding was never tracked despite the schema slot and the
  ground-taxa-gtdb skill both existing: 569/995 taxa (57%), spread as 91 records
  fully grounded, 140 partially, 72 with none. Filed as #276 and added as its own
  section.

Adds a priority menu at the top ranking the six actionable items, with GTDB
grounding recommended first — it is the largest gap depending on nothing outside
this repo, and the 140 partially-grounded records are the sharpest part of it
because a half-grounded record cannot be distinguished from one where GTDB has
no equivalent.

The blocked items are listed separately with the reason each is blocked, so they
stop being re-litigated every reconcile: #259 (publisher download), #183's
closed-access remainder, #30 (sibling-repo schema), the validate-terms-all
residuals (terms we cannot mint), and the 4 space-regolith candidates with
undefined membership.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* NEXT_TASKS: apply review corrections; add #183/#182/#259 sections (#277)

Review of this PR — with the numeric claims re-derived independently rather than
trusted — confirmed every measurement but found four things to correct.

**§1 was overstated.** The blocked-items entry claimed "every one of the 34
residuals needs a term that does not exist and that we cannot mint". §1 itself
contradicts that twice: ~12 of the 34 are obsolete GO ids needing a
curator-accepted repoint rather than minting, and §1 already records a
near-repoint found for sodium metasilicate. Roughly 14 of the 34 are genuinely
un-mintable. The gate stays blocked overall, but part of the set is decidable
here, and saying otherwise buries actionable work on the blocked list.

**The NATURAL split was ambiguous.** "52 of the 80 are NATURAL" is true by
ecological_state but invites recomputing by community_origin and getting 57 —
the difference being 5 NATURAL-origin records that are ENGINEERED in state and
so belong with the curatable set. Both occurrences now say STABLE or PERTURBED
and explain the 57.

**Two smaller fixes:** the growth-conditions target is 25, not ~24 (only three
of the 28 ENGINEERED records are pure computational models), and the JSON print
is cli.py:91, not :90 — line 90 is the `if output_json:` guard.

Also adds sections for #183, #182 and #259, each of which had been carried on
the blocked list more pessimistically than the code supports:

- **#183** — its own "52/295" is stale (now 80/305), and the curatable slice is
  25 named records. Of those, 1 has real full text, 18 have abstract stubs and
  **6 have nothing cached at all** — never attempted, which is not the same as
  paywalled, and is the cheapest next step in the section.
- **#182** — not blocked, just undecided; a curator has to choose per row. Flags
  GO:0055114 → GO:0016491 as the one remap wrong on type grounds (BP → MF)
  rather than merely broad, and distinguishes this surface from §1's residuals,
  which are easy to conflate.
- **#259** — mostly shipped in #260/#261. What remains is that Unpaywall is
  queried only to name an OA location, never to fetch it, so an OA-but-not-PMC
  source still costs a manual round trip. Self-contained work, not blocked.

Menu grows to 8 items; #277 filed for the four dangling [[wiki-links]].

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <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.

1 participant