From 75badbb73893ea7e980cc019df8de7e5db96c594 Mon Sep 17 00:00:00 2001 From: AStaroverov Date: Thu, 11 Jun 2026 11:51:17 +0200 Subject: [PATCH 1/4] feat: add support for per-cluster centroid dataset in sequence processing --- model/src/index.ts | 10 ++++++++++ workflow/src/main.tpl.tengo | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/model/src/index.ts b/model/src/index.ts index bc1eb47..0f9c56d 100644 --- a/model/src/index.ts +++ b/model/src/index.ts @@ -33,6 +33,16 @@ const inputAnchorSpecs = [ axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/vdj/scClonotypeKey" }], annotations: { "pl7.app/isAnchor": "true" }, }, + // Per-cluster centroid dataset (clonotype-clustering). A clonotype-shaped 2-axis + // dataset where the row entity is a cluster: axis[0] = sampleId (real per-sample + // abundance anchor), axis[1] = "pl7.app/clustering/centroidId" (values = real + // clusterId) carrying the synthetic per-cluster centroid sequence. The dedicated + // centroidId axis (not the producer's plain clusterId) keeps anchoring here from + // pulling its clusters table's centroid_*/reference_centroid_* columns. + { + axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/clustering/centroidId" }], + annotations: { "pl7.app/isAnchor": "true" }, + }, ]; export const platforma = BlockModelV3.create(blockDataModel) diff --git a/workflow/src/main.tpl.tengo b/workflow/src/main.tpl.tengo index 603fcf7..076c023 100644 --- a/workflow/src/main.tpl.tengo +++ b/workflow/src/main.tpl.tengo @@ -52,6 +52,13 @@ detectMode := func(axisSpec) { if axisSpec.name == "pl7.app/vdj/scClonotypeKey" { return "antibody_tcr_legacy_sc" } + // Per-cluster centroid dataset (clonotype-clustering): synthetic pl7.app/vdj/sequence + // (aminoacid) per cluster on a 2-axis [sampleId, centroidId] anchor. Treat as legacy-bulk + // vdj for sequence pulling; single-cell centroids still carry the chain domain on the + // sequence columns, so the per-chain handling in the body works unchanged. + if axisSpec.name == "pl7.app/clustering/centroidId" { + return "antibody_tcr_legacy_bulk" + } return "" } From 32d5946c615f8c68bd968ffd8f3ed1e6a430748b Mon Sep 17 00:00:00 2001 From: AStaroverov Date: Mon, 15 Jun 2026 16:10:22 +0200 Subject: [PATCH 2/4] feat: add support for per-cluster centroid datasets in sequence processing --- .changeset/per-cluster-centroid-dataset.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/per-cluster-centroid-dataset.md diff --git a/.changeset/per-cluster-centroid-dataset.md b/.changeset/per-cluster-centroid-dataset.md new file mode 100644 index 0000000..31fbf0e --- /dev/null +++ b/.changeset/per-cluster-centroid-dataset.md @@ -0,0 +1,6 @@ +--- +"@platforma-open/milaboratories.sequence-properties.workflow": patch +"@platforma-open/milaboratories.sequence-properties.model": patch +--- + +Add support for per-cluster centroid datasets (clonotype-clustering). The model accepts a 2-axis `[sampleId, centroidId]` anchor, and the workflow treats the synthetic per-cluster centroid sequence as legacy-bulk VDJ for sequence pulling. From 8d8bc4ccb765f1dd6e767fa24413e69b5fc02cd0 Mon Sep 17 00:00:00 2001 From: AStaroverov Date: Mon, 15 Jun 2026 16:13:11 +0200 Subject: [PATCH 3/4] feat: clarify receptor resolution logic for centroidId axis in detectMode function --- workflow/src/main.tpl.tengo | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/workflow/src/main.tpl.tengo b/workflow/src/main.tpl.tengo index 076c023..998348b 100644 --- a/workflow/src/main.tpl.tengo +++ b/workflow/src/main.tpl.tengo @@ -56,6 +56,10 @@ detectMode := func(axisSpec) { // (aminoacid) per cluster on a 2-axis [sampleId, centroidId] anchor. Treat as legacy-bulk // vdj for sequence pulling; single-cell centroids still carry the chain domain on the // sequence columns, so the per-chain handling in the body works unchanged. + // The centroidId axis carries no VDJ receptor/chain keys, so receptor is resolved + // solely from the chain domain on the sequence columns. A producer that omits chain + // metadata leaves receptorSeen false and falls back to the IG default — surfaced (not + // silent) by the R13b receptorNotDetected() warning at the !receptorSeen check below. if axisSpec.name == "pl7.app/clustering/centroidId" { return "antibody_tcr_legacy_bulk" } From 97f7d09830b50d1b28ee9ac6ddc3ab06eb7bac37 Mon Sep 17 00:00:00 2001 From: AStaroverov Date: Tue, 16 Jun 2026 18:35:01 +0200 Subject: [PATCH 4/4] Treat per-cluster centroid dataset as peptide The clonotype-clustering centroid dataset export is peptide-only, so detectMode now maps the pl7.app/clustering/centroidId axis to peptide mode (was antibody_tcr_legacy_bulk, which filtered by VDJ REQUIRED_FEATURES and crashed building an empty XSV). Co-Authored-By: Claude Opus 4.8 (1M context) --- .changeset/per-cluster-centroid-dataset.md | 2 +- workflow/src/main.tpl.tengo | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.changeset/per-cluster-centroid-dataset.md b/.changeset/per-cluster-centroid-dataset.md index 31fbf0e..c65b688 100644 --- a/.changeset/per-cluster-centroid-dataset.md +++ b/.changeset/per-cluster-centroid-dataset.md @@ -3,4 +3,4 @@ "@platforma-open/milaboratories.sequence-properties.model": patch --- -Add support for per-cluster centroid datasets (clonotype-clustering). The model accepts a 2-axis `[sampleId, centroidId]` anchor, and the workflow treats the synthetic per-cluster centroid sequence as legacy-bulk VDJ for sequence pulling. +Add support for per-cluster centroid datasets (clonotype-clustering). The model accepts a 2-axis `[sampleId, centroidId]` anchor, and the workflow processes the synthetic per-cluster consensus sequence in peptide mode (the upstream "Export consensus sequences as a dataset" feature is peptide-only, so the centroid sequence column is a peptide amino-acid column). diff --git a/workflow/src/main.tpl.tengo b/workflow/src/main.tpl.tengo index 998348b..960105d 100644 --- a/workflow/src/main.tpl.tengo +++ b/workflow/src/main.tpl.tengo @@ -52,16 +52,16 @@ detectMode := func(axisSpec) { if axisSpec.name == "pl7.app/vdj/scClonotypeKey" { return "antibody_tcr_legacy_sc" } - // Per-cluster centroid dataset (clonotype-clustering): synthetic pl7.app/vdj/sequence - // (aminoacid) per cluster on a 2-axis [sampleId, centroidId] anchor. Treat as legacy-bulk - // vdj for sequence pulling; single-cell centroids still carry the chain domain on the - // sequence columns, so the per-chain handling in the body works unchanged. - // The centroidId axis carries no VDJ receptor/chain keys, so receptor is resolved - // solely from the chain domain on the sequence columns. A producer that omits chain - // metadata leaves receptorSeen false and falls back to the IG default — surfaced (not - // silent) by the R13b receptorNotDetected() warning at the !receptorSeen check below. + // Per-cluster centroid dataset (clonotype-clustering): a synthetic 2-axis + // [sampleId, centroidId] anchor carrying one consensus sequence per cluster. The + // "Export consensus sequences as a dataset" feature is peptide-only (the producer + // gates the export on peptide inputs), so the centroid sequence column is a peptide + // aminoacid column (pl7.app/sequence, pl7.app/feature: "peptide") and the dataset is + // processed in peptide mode — the peptideSequences matcher in prepare() picks it up. + // NOTE: if VDJ/single-cell centroid export is ever re-enabled upstream, this must + // branch on the centroid sequence column's feature instead of assuming peptide. if axisSpec.name == "pl7.app/clustering/centroidId" { - return "antibody_tcr_legacy_bulk" + return "peptide" } return "" }