Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/cluster-level-property.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@platforma-open/milaboratories.repertoire-mutation-heatmap.workflow': minor
'@platforma-open/milaboratories.repertoire-mutation-heatmap.model': minor
'@platforma-open/milaboratories.repertoire-mutation-heatmap.block': minor
---

Support cluster-level inputs (A-0016). A value computed per cluster (keyed by `pl7.app/clusterId`) is now resolved down to the individual variants through the clustering block's `variant→cluster` linker (`pl7.app/link`) with an explicit join in the precalc, so each variant inherits its cluster's value and the grid stays per variant. Applies to all three cluster-capable inputs:

- the `property` value mode,
- the property-range subset filter,
- the composition-enrichment view's per-round frequencies.

Discovery now traverses the linker (`findColumns` `maxHops: 1`) for both the property picker and the round-frequency picker, so cluster-keyed columns surface alongside variant-keyed ones; the linker column itself is excluded from the property picker.
23 changes: 15 additions & 8 deletions model/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,14 +266,21 @@ export const platforma = BlockModelV3.create(dataModel)
const numeric = new Set(["Int", "Long", "Float", "Double"]);
const seen = new Set<string>();
const options: { label: string; value: SUniversalPColumnId }[] = [];
for (const m of collection.findColumns({ mode: "enrichment", maxHops: 0 })) {
if (!numeric.has(m.column.spec.valueType as string)) continue;
// maxHops: 1 so cluster-keyed properties surface across the variant→cluster
// linker (A-0016); the workflow resolves them to per-variant via an explicit
// join. Anything reached at 0 hops (variant-keyed properties) still matches.
for (const m of collection.findColumns({ mode: "enrichment", maxHops: 1 })) {
const s = m.column.spec;
// The variant→cluster linker itself is Int-valued and would otherwise pass
// the numeric filter and show up as a bogus "property".
if (s.annotations?.["pl7.app/isLinkerColumn"] === "true") continue;
if (!numeric.has(s.valueType as string)) continue;
// Dedup a column reachable via both anchors (by identity, not anchored id).
const dedupKey = m.column.spec.name + "|" + JSON.stringify(m.column.spec.domain ?? {});
const dedupKey = s.name + "|" + JSON.stringify(s.domain ?? {});
if (seen.has(dedupKey)) continue;
seen.add(dedupKey);
options.push({
label: (m.column.spec.annotations?.["pl7.app/label"] as string | undefined) ?? m.column.id,
label: (s.annotations?.["pl7.app/label"] as string | undefined) ?? m.column.id,
value: m.column.id as SUniversalPColumnId,
});
}
Expand All @@ -292,9 +299,9 @@ export const platforma = BlockModelV3.create(dataModel)
// in the workflow's anchored query. The anchor name `freqAnchor` must match the workflow's
// `bb.addAnchor("freqAnchor", ...)`; the discovered `column.id` resolves against it there.
//
// v1: variant-level only (maxHops 0). Cluster-keyed frequencies (enrichment on clustered
// abundance) need linker traversal (maxHops > 0) + adding the `variant→cluster` linker in
// the workflow (A-0016) — deferred, shared with the property-view cluster path.
// Variant- and cluster-level: maxHops 1 so frequencies from enrichment run on clustered
// abundance (keyed by clusterId) surface across the `variant→cluster` linker; the workflow
// resolves them to per-variant via the same explicit join as the property view (A-0016).
.output("roundFrequencyOptions", (ctx) => {
const abundanceRef = ctx.data.abundanceRef;
if (abundanceRef === undefined) return undefined;
Expand All @@ -316,7 +323,7 @@ export const platforma = BlockModelV3.create(dataModel)
const matches = collection.findColumns({
include: { name: "pl7.app/frequency" },
mode: "enrichment",
maxHops: 0,
maxHops: 1,
});

return matches.map((m) => ({
Expand Down
Loading
Loading