Support disjoint assembling features for mid-region germline imputation (FR3 gap) - #91
Merged
Merged
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
Comment on lines
+475
to
+481
| <PlTextField | ||
| v-if="isCustomAssemblingFeature" | ||
| v-model="assemblingFeature" | ||
| label="Custom assembling feature" | ||
| placeholder="e.g. FR1Begin:FR3Begin(+40),FR3Begin(+46):FR4End" | ||
| clearable | ||
| > |
There was a problem hiding this comment.
Empty custom feature crashes workflow
When a user selects Custom (advanced) and leaves or clears this field, the empty string passes argument validation and reaches parseAssemblingFeature, which panics because the value has no valid endpoints, causing the analysis run to fail.
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/pages/SettingsPanel.vue
Line: 475-481
Comment:
**Empty custom feature crashes workflow**
When a user selects Custom (advanced) and leaves or clears this field, the empty string passes argument validation and reaches `parseAssemblingFeature`, which panics because the value has no valid endpoints, causing the analysis run to fail.
How can I resolve this? If you propose a fix, please make it concise.The assembling feature can now be a disjoint, comma-separated list of pieces
(e.g. FR1Begin:FR3Begin(+40),FR3Begin(+46):FR4End) that brackets an uncovered
mid-region window. formatAssemblingFeature emits the MiXCR disjoint
--assemble-clonotypes-by [{..},{..}] form; parseAssemblingFeature classifies
fully-covered regions as exported-as-is and the partially-covered gap region,
flanks, and the full VDJRegion as germline-imputed. This recovers long-CDR3
clones whose 2x150 reads leave a ~6 nt uncovered window in FR3.
The "Assembling feature" dropdown gains a "Custom (advanced)" free-text option
for entering an arbitrary MiXCR gene feature (including a disjoint one).
Unit tests (exportSpecs) cover the grammar/classification; a wf.test e2e case
exercises a disjoint feature end-to-end. Based on the structurer migration (#90).
PoslavskySV
force-pushed
the
feat/germline-imputation-fr3-gap
branch
from
July 24, 2026 17:13
ca117b8 to
06d4a75
Compare
exportClones -nFeature/-aaFeature/-isProductive parse a single composite
GeneFeature (pieces joined with "+"), not the "[{..},{..}]" list that
--assemble-clonotypes-by accepts — MiXCR rejected the list form at export with
"Unknown feature". The export-side formatAssemblingFeature now emits
"{A:B}+{C:D}"; the assemble side keeps the list form (verified working).
MiXCR's GeneFeature.encode names a range's start with a "Begin" point and its end
with an "End" point, canonicalizing boundary points (e.g. a range ending at
FR3Begin is exported as CDR2End, since FR3Begin == CDR2End). The block now
predicts the same canonical composite name, so the nSeq/aaSeq/isProductive columns
it references match MiXCR's actual exported headers — the downstream key-hash and
productive-filter were failing with ColumnNotFound on the non-canonical name.
Confirmed from the run: CDR1Begin:FR3Begin,CDR3Begin:FR4End exports as
{CDR1Begin:CDR2End}+{CDR3Begin:FR4End}.
MiXCR's GeneFeature.encode rewrites a composite feature's exported column header
unpredictably — ref-point duals (FR3Begin -> CDR2End) and whole-region ranges
collapsing to their name ({CDR3Begin:CDR3End} -> CDR3) — so predicting that name
is a losing game (each feature variant hit a new rule). For a disjoint assembling
feature the block now avoids the composite column entirely:
- clonotype key = the individual covered regions (nSeqCDR1, nSeqFR2, ... — names
MiXCR produces verbatim) + bestVGene + bestJGene. Keying on all covered regions
(not just CDR3) matters for synthetic fixed-framework libraries where CDR1/CDR2
are independently diversified.
- productivity is driven off CDR3 (isProductiveCDR3), and the full-length imputed
VDJRegion is the main sequence.
- no combined assembling-feature column is exported.
exportClones no longer receives any composite -nFeature/-isProductive arg, so the
downstream key-hash and productive-filter reference only real, verbatim columns.
Selecting "Custom (advanced)" and leaving the field empty let "" reach
parseAssemblingFeature, which panics ("must be in the format of 'begin:end'"),
failing the run (flagged in review). Fixes:
- argsValid now rejects an empty assemblingFeature, blocking the run until the
field is filled;
- the Custom field shows a validation message when empty.
Also add the model package to the changeset, and correct a stale comment in
mixcr-analyze (the export side keys on covered regions, not a "+" composite).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds support for a disjoint assembling feature to the MiXCR Amplicon Alignment block, so clonotypes can be assembled across an uncovered mid-region window.
assemblingFeaturemay now be a disjoint, comma-separated list of pieces with explicit reference points, e.g.FR1Begin:FR3Begin(+40),FR3Begin(+46):FR4End.formatAssemblingFeatureemits the MiXCR--assemble-clonotypes-by [{…},{…}]form;parseAssemblingFeatureclassifies fully-covered regions as exported-as-is and the partially-covered gap region, flanks, and fullVDJRegionas germline-imputed.assemblingFeatureas a free string.Why
With 2×150 sequencing, long-CDR3 clones can have paired reads that don't overlap, leaving a short uncovered window in FR3. Default full-
VDJRegionassembly drops those clones. A disjoint assembling feature that brackets the gap lets each mate fully cover one piece, so the clone survives; enabling "Impute non-covered parts from germline" reconstructs the skipped window (and the full VDJRegion) from the assigned V/J germline — the same way the parental/reference sequence fills the gap.Testing
exportSpecsunit tests (grammar + region classification): 37/37, incl. 6 new disjoint cases.pl-tengo check); UI type-check + lint + build green.wf.teste2e case (disjoint FR3-gap feature with imputation) exercising a disjoint feature end-to-end on thes1fixture. Not yet run in a dev backend (native-module / registry-auth gap in the local env) — relying on CI to run it here.Notes
nSeq[{…}],isProductive[{…}]). The code extends the existing braced-range pattern (nSeq{CDR1Begin:CDR3End}, already covered by tests); if MiXCR names them differently, thewf.testsurfaces it and theoutputProductiveFeature/key wiring is the adjustment point.@platforma-sdk/block-toolsin the workspace catalog is2.12.0(latest2.12.9) — pre-existing onmain, not bumped here.Greptile Summary
Adds configurable disjoint clonotype assembly across uncovered mid-region windows.
[{…},{…}]syntax.FR3Begin(+40); newly parsed to determine whole-region coverage.Confidence Score: 4/5
The empty custom assembling-feature path must be rejected or defaulted before merging because it currently causes the workflow to panic.
The new clearable custom field can persist an empty assemblingFeature, argument validation allows it through, and the export-spec parser then panics on the invalid shape.
ui/src/pages/SettingsPanel.vue, workflow/src/calculate-export-specs.lib.tengo
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart LR UI[Custom assembling feature] --> F[Format comma-separated pieces] F --> A[MiXCR assemble-clonotypes-by] F --> C[Classify covered regions] C --> N[Export covered regions as-is] C --> I[Impute gaps and VDJRegion] A --> K[Disjoint sequence clonotype key] N --> O[Clonotype outputs] I --> O K --> OPrompt To Fix All With AI
Reviews (1): Last reviewed commit: "Add a "Custom (advanced)" assembling-fea..." | Re-trigger Greptile