@datagrok/sequence-translator 1.10.17 → 1.10.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/CLAUDE.md +15 -12
- package/dist/package-test.js +1 -1
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +1 -1
- package/src/apps/common/model/oligo-toolkit-package.ts +13 -1
- package/src/oligo-renderer/analog-cache.ts +48 -0
- package/src/oligo-renderer/canvas-renderer.ts +121 -12
- package/src/oligo-renderer/helm-parser.ts +3 -2
- package/src/oligo-renderer/legend-panel.ts +31 -6
- package/src/oligo-renderer/types.ts +21 -0
- package/src/package-api.ts +7 -0
- package/src/package-test.ts +1 -0
- package/src/package.g.ts +8 -0
- package/src/package.ts +32 -2
- package/src/tests/oligo-cell-editor-tests.ts +83 -0
- package/src/tests/oligo-renderer-tests.ts +64 -1
- package/test-console-output-1.log +185 -137
- package/test-record-1.mp4 +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {category, test, expect} from '@datagrok-libraries/test/src/test';
|
|
2
2
|
|
|
3
|
-
import {parseHelmDuplex, looksLikeHelm} from '../oligo-renderer/helm-parser';
|
|
3
|
+
import {parseHelmDuplex, looksLikeHelm, canonicalizeHelm} from '../oligo-renderer/helm-parser';
|
|
4
|
+
import {ParsedNucleotide} from '../oligo-renderer/types';
|
|
4
5
|
import {computeLayout, hitTest, drawDuplex} from '../oligo-renderer/canvas-renderer';
|
|
5
6
|
import {
|
|
6
7
|
resolveSugar, resolvePhosphate, resolveConjugate,
|
|
@@ -94,6 +95,68 @@ category('OligoRenderer: parser', () => {
|
|
|
94
95
|
expect(m0.phosphate, 'zp');
|
|
95
96
|
}
|
|
96
97
|
});
|
|
98
|
+
|
|
99
|
+
test('parser strips brackets from multi-char base in parens', async () => {
|
|
100
|
+
// Bug: pre-fix, cleanupHelmSymbol was not called on the base, so base === '[5Br-dC]'.
|
|
101
|
+
// Post-fix: cleanupHelmSymbol('[5Br-dC]') → '5Br-dC'.
|
|
102
|
+
const dup = parseHelmDuplex('RNA1{r([5Br-dC])p}$$$$');
|
|
103
|
+
const m = dup.sense.monomers[0] as ParsedNucleotide;
|
|
104
|
+
expect(m.kind, 'nucleotide');
|
|
105
|
+
expect(m.sugar, 'r');
|
|
106
|
+
// pre-fix: '[5Br-dC]' post-fix: '5Br-dC'
|
|
107
|
+
expect(m.base, '5Br-dC');
|
|
108
|
+
expect(m.phosphate, 'p');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('parser strips brackets from multi-char base on both strands', async () => {
|
|
112
|
+
// Covers both strands and different modification combinations.
|
|
113
|
+
// pre-fix: base === '[5meC]', '[5Br-dC]', '[5fU]' post-fix: '5meC', '5Br-dC', '5fU'
|
|
114
|
+
const dup = parseHelmDuplex('RNA1{r([5meC])p.[fl2r]([5Br-dC])[sp]}|RNA2{r([5fU])p}$$$$');
|
|
115
|
+
const senseFirst = dup.sense.monomers[0] as ParsedNucleotide;
|
|
116
|
+
const senseSecond = dup.sense.monomers[1] as ParsedNucleotide;
|
|
117
|
+
const antiFirst = dup.antisense!.monomers[0] as ParsedNucleotide;
|
|
118
|
+
// pre-fix: '[5meC]' post-fix: '5meC'
|
|
119
|
+
expect(senseFirst.base, '5meC');
|
|
120
|
+
expect(senseSecond.sugar, 'fl2r');
|
|
121
|
+
// pre-fix: '[5Br-dC]' post-fix: '5Br-dC'
|
|
122
|
+
expect(senseSecond.base, '5Br-dC');
|
|
123
|
+
expect(senseSecond.phosphate, 'sp');
|
|
124
|
+
// pre-fix: '[5fU]' post-fix: '5fU'
|
|
125
|
+
expect(antiFirst.base, '5fU');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('parser leaves bare-letter base unchanged', async () => {
|
|
129
|
+
// Regression guard: single-letter bases must NOT be transformed.
|
|
130
|
+
// A, G, C, T, U are all single-char and do not have brackets → unchanged by cleanupHelmSymbol.
|
|
131
|
+
const dup = parseHelmDuplex('RNA1{r(A)p.r(G)p.r(C)p.r(T)p.r(U)p}$$$$');
|
|
132
|
+
const bases = dup.sense.monomers.map((m) => (m as ParsedNucleotide).base);
|
|
133
|
+
// Expected: ['A', 'G', 'C', 'T', 'U'] — unchanged for all five bases.
|
|
134
|
+
expect(bases.join(','), 'A,G,C,T,U');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test('canonicalizeHelm re-brackets multi-char base on output', async () => {
|
|
138
|
+
// serializeCanonicalMonomer emits `([${base}])` when base.length > 1.
|
|
139
|
+
// pre-fix: emitted '(5Br-dC)' (invalid HELM, missing brackets).
|
|
140
|
+
// post-fix: emits '([5Br-dC])' — round-trip is valid HELM.
|
|
141
|
+
const out = canonicalizeHelm('RNA1{r([5Br-dC])p}$$$$');
|
|
142
|
+
// Must contain the bracketed base form.
|
|
143
|
+
expect(out.includes('([5Br-dC])'), true,
|
|
144
|
+
`expected canonicalized HELM to contain '([5Br-dC])', got: ${out}`);
|
|
145
|
+
// Must NOT contain the bare (unbracketed) form.
|
|
146
|
+
expect(out.includes('(5Br-dC)') && !out.includes('([5Br-dC])'), false,
|
|
147
|
+
`must not emit unbracketed (5Br-dC) without wrapping brackets, got: ${out}`);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test('canonicalizeHelm keeps single-letter base unbracketed', async () => {
|
|
151
|
+
// serializeCanonicalMonomer: base.length === 1 → `(${base})`, not `([${base}])`.
|
|
152
|
+
// Expected output contains 'r(A)p' — single letter stays bare.
|
|
153
|
+
const out = canonicalizeHelm('RNA1{r(A)p}$$$$');
|
|
154
|
+
expect(out.includes('r(A)p'), true,
|
|
155
|
+
`expected single-letter base to stay unbracketed, got: ${out}`);
|
|
156
|
+
// Single-letter base must NOT get double-bracketed.
|
|
157
|
+
expect(out.includes('([A])'), false,
|
|
158
|
+
`single-letter base must NOT be wrapped in brackets, got: ${out}`);
|
|
159
|
+
});
|
|
97
160
|
});
|
|
98
161
|
|
|
99
162
|
category('OligoRenderer: modification dictionary', () => {
|