@datagrok/sequence-translator 1.10.8 → 1.10.10
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/CLAUDE.md +452 -0
- 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 +2 -2
- package/src/demo/demo-st-ui.ts +1 -2
- package/src/polytool/const.ts +0 -1
- package/src/polytool/pt-enumerate-seq-dialog.ts +9 -96
- package/src/polytool/types.ts +0 -1
- package/test-console-output-1.log +82 -82
- package/test-record-1.mp4 +0 -0
- package/src/polytool/pt-monomer-selection-dialog.ts +0 -237
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "1.10.
|
|
4
|
+
"version": "1.10.10",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Davit Rizhinashvili",
|
|
7
7
|
"email": "drizhinashvili@datagrok.ai"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
}
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@datagrok-libraries/bio": "^5.
|
|
25
|
+
"@datagrok-libraries/bio": "^5.62.1",
|
|
26
26
|
"@datagrok-libraries/chem-meta": "^1.2.8",
|
|
27
27
|
"@datagrok-libraries/tutorials": "^1.6.1",
|
|
28
28
|
"@datagrok-libraries/utils": "^4.6.5",
|
package/src/demo/demo-st-ui.ts
CHANGED
|
@@ -2,7 +2,6 @@ import * as grok from 'datagrok-api/grok';
|
|
|
2
2
|
import * as ui from 'datagrok-api/ui';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
-
import {delay} from '@datagrok-libraries/test/src/test';
|
|
6
5
|
import {PackageFunctions} from '../package';
|
|
7
6
|
import {tryCatch} from '../apps/common/model/helpers';
|
|
8
7
|
|
|
@@ -23,7 +22,7 @@ export async function demoOligoPatternUI() {
|
|
|
23
22
|
export async function demoOligoStructureUI() {
|
|
24
23
|
await tryCatch(async () => {
|
|
25
24
|
async function setInputValue(idx: number, sequence: string): Promise<void> {
|
|
26
|
-
await delay(500);
|
|
25
|
+
await DG.delay(500);
|
|
27
26
|
const textInputs: NodeListOf<HTMLTextAreaElement> = document.querySelectorAll('.st-colored-text-input > textarea');
|
|
28
27
|
const textarea = textInputs[idx];
|
|
29
28
|
textarea.value = sequence;
|
package/src/polytool/const.ts
CHANGED
|
@@ -45,5 +45,4 @@ export const PT_ENUM_TYPE_TOOLTIPS: Record<string, string> = {
|
|
|
45
45
|
'single': 'Each position is enumerated independently. Total results = sum of monomers across all positions.',
|
|
46
46
|
'parallel': 'The i-th result uses the i-th monomer from every position (zip). All positions must have the same number of monomers. Total results = number of monomers per position.',
|
|
47
47
|
'matrix': 'Cartesian product of all positions. Total results = product of monomer counts across all positions.',
|
|
48
|
-
'library': 'Substitutes all monomers from a selected library at a single position.',
|
|
49
48
|
};
|
|
@@ -22,10 +22,9 @@ import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
|
22
22
|
import {SeqTemps} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
|
|
23
23
|
|
|
24
24
|
import {PolyToolEnumeratorParams, PolyToolEnumeratorType, PolyToolEnumeratorTypes} from './types';
|
|
25
|
-
import {getLibrariesList, LIB_PATH} from './utils';
|
|
26
25
|
import {doPolyToolEnumerateHelm, PT_HELM_EXAMPLE} from './pt-enumeration-helm';
|
|
27
26
|
import {PolyToolPlaceholdersInput} from './pt-placeholders-input';
|
|
28
|
-
import {showMonomerSelectionDialog} from '
|
|
27
|
+
import {showMonomerSelectionDialog} from '@datagrok-libraries/bio/src/utils/monomer-selection-dialog';
|
|
29
28
|
import {defaultErrorHandler} from '../utils/err-info';
|
|
30
29
|
import {PolyToolPlaceholdersBreadthInput} from './pt-placeholders-breadth-input';
|
|
31
30
|
import {PT_ENUM_TYPE_TOOLTIPS, PT_UI_DIALOG_ENUMERATION, PT_UI_GET_HELM, PT_UI_HIGHLIGHT_MONOMERS, PT_UI_RULES_USED, PT_UI_USE_CHIRALITY} from './const';
|
|
@@ -47,7 +46,7 @@ import {INotationProvider, NotationProviderBase} from '@datagrok-libraries/bio/s
|
|
|
47
46
|
*
|
|
48
47
|
* Provides the UI for enumerating macromolecule variants. The user selects positions
|
|
49
48
|
* on a HELM molecule and specifies substitute monomers at each position. Supports
|
|
50
|
-
* multiple enumeration strategies (Single, Parallel, Matrix
|
|
49
|
+
* multiple enumeration strategies (Single, Parallel, Matrix) and optional
|
|
51
50
|
* downstream processing (atomic-level conversion, chirality, rules).
|
|
52
51
|
*
|
|
53
52
|
* Architecture:
|
|
@@ -67,7 +66,6 @@ type PolyToolEnumerateInputs = {
|
|
|
67
66
|
generateHelm: DG.InputBase<boolean>;
|
|
68
67
|
chiralityEngine: DG.InputBase<boolean>;
|
|
69
68
|
highlightMonomers: DG.InputBase<boolean>;
|
|
70
|
-
library: DG.InputBase<string>;
|
|
71
69
|
rules: { header: HTMLElement, form: HTMLDivElement },
|
|
72
70
|
};
|
|
73
71
|
|
|
@@ -84,7 +82,6 @@ type PolyToolEnumerateHelmSerialized = {
|
|
|
84
82
|
chiralityEngine: boolean;
|
|
85
83
|
highlightMonomers: boolean;
|
|
86
84
|
rules: string[],
|
|
87
|
-
library: string;
|
|
88
85
|
};
|
|
89
86
|
|
|
90
87
|
/** Entry point: creates, sizes, and shows the enumeration dialog. */
|
|
@@ -163,7 +160,6 @@ async function getPolyToolEnumerateDialog(
|
|
|
163
160
|
const logPrefix = `ST: PT: HelmDialog()`;
|
|
164
161
|
let inputs: PolyToolEnumerateInputs;
|
|
165
162
|
const subs: Unsubscribable[] = [];
|
|
166
|
-
// Track previous enumeration type to clean up state when switching to/from Library mode
|
|
167
163
|
let prevEnumerationType: PolyToolEnumeratorType = PolyToolEnumeratorTypes.Single;
|
|
168
164
|
const destroy = () => {
|
|
169
165
|
for (const sub of subs) sub.unsubscribe();
|
|
@@ -176,7 +172,7 @@ async function getPolyToolEnumerateDialog(
|
|
|
176
172
|
const seqHelper = await getSeqHelper();
|
|
177
173
|
const emptyDf: DG.DataFrame = DG.DataFrame.fromColumns([]);
|
|
178
174
|
|
|
179
|
-
const
|
|
175
|
+
const helmHelper = await getHelmHelper();
|
|
180
176
|
const monomerLibFuncs = helmHelper.buildMonomersFuncsFromLib(monomerLib);
|
|
181
177
|
|
|
182
178
|
// Resolves the source macromolecule from the given cell or falls back to a default example.
|
|
@@ -310,7 +306,6 @@ async function getPolyToolEnumerateDialog(
|
|
|
310
306
|
},
|
|
311
307
|
nullable: true,
|
|
312
308
|
}),
|
|
313
|
-
library: ui.input.choice('Monomer Library', {items: _libList, value: _libList[0], nullable: true}) as DG.InputBase<string>,
|
|
314
309
|
};
|
|
315
310
|
// #### Inputs END
|
|
316
311
|
|
|
@@ -321,7 +316,6 @@ async function getPolyToolEnumerateDialog(
|
|
|
321
316
|
};
|
|
322
317
|
updateEnumTypeTooltip();
|
|
323
318
|
|
|
324
|
-
inputs.library.root.style.setProperty('display', 'none');
|
|
325
319
|
inputs.trivialNameCol.addOptions(trivialNameSampleDiv);
|
|
326
320
|
|
|
327
321
|
// Wire up monomer cell double-click to open selection dialog
|
|
@@ -332,7 +326,7 @@ async function getPolyToolEnumerateDialog(
|
|
|
332
326
|
const atom = mol.atoms[position];
|
|
333
327
|
const helmType: HelmType = atom.biotype()!;
|
|
334
328
|
const polymerType = helmTypeToPolymerType(helmType);
|
|
335
|
-
return showMonomerSelectionDialog(monomerLib, polymerType, currentMonomers);
|
|
329
|
+
return showMonomerSelectionDialog(monomerLib, polymerType, currentMonomers, libHelper);
|
|
336
330
|
};
|
|
337
331
|
|
|
338
332
|
// Wire up breadth monomer cell double-click to open selection dialog
|
|
@@ -345,7 +339,7 @@ async function getPolyToolEnumerateDialog(
|
|
|
345
339
|
const atom = mol.atoms[start];
|
|
346
340
|
const helmType: HelmType = atom.biotype()!;
|
|
347
341
|
const polymerType = helmTypeToPolymerType(helmType);
|
|
348
|
-
return showMonomerSelectionDialog(monomerLib, polymerType, currentMonomers);
|
|
342
|
+
return showMonomerSelectionDialog(monomerLib, polymerType, currentMonomers, libHelper);
|
|
349
343
|
};
|
|
350
344
|
|
|
351
345
|
// === VALIDATORS ===
|
|
@@ -356,20 +350,6 @@ async function getPolyToolEnumerateDialog(
|
|
|
356
350
|
const errors: string[] = [];
|
|
357
351
|
setTimeout(() => { updateWarnings(); }, 100);
|
|
358
352
|
try {
|
|
359
|
-
// for library, ony one placeholder is allowed
|
|
360
|
-
if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library) {
|
|
361
|
-
const pcs = inputs.placeholders.placeholdersValue;
|
|
362
|
-
if (pcs.length > 1)
|
|
363
|
-
placeholdersValidity = 'Only one placeholder is allowed for Library mode';
|
|
364
|
-
if (pcs.length === 1) {
|
|
365
|
-
if (pcs[0].position == null)
|
|
366
|
-
placeholdersValidity = 'Position is required for Library mode';
|
|
367
|
-
if (pcs[0].position > inputs.macromolecule.molValue.atoms.length)
|
|
368
|
-
placeholdersValidity = `There is no monomer at position ${pcs[0].position + 1}.`;
|
|
369
|
-
}
|
|
370
|
-
return placeholdersValidity;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
353
|
// Parallel mode: all placeholders must have the same monomer count
|
|
374
354
|
if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Parallel) {
|
|
375
355
|
const pcs = inputs.placeholders.placeholdersValue;
|
|
@@ -480,32 +460,7 @@ async function getPolyToolEnumerateDialog(
|
|
|
480
460
|
// return placeholdersValidity;
|
|
481
461
|
// });
|
|
482
462
|
|
|
483
|
-
inputs.library.addValidator((_value) => {
|
|
484
|
-
if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library && !inputs.library.value)
|
|
485
|
-
return 'Monomer Library is required for this enumerator type';
|
|
486
|
-
return null;
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
inputs.library.onChanged.subscribe(() => {
|
|
490
|
-
if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library)
|
|
491
|
-
inputs.placeholders.setMonomersValue(0, inputs.library.value ?? '');
|
|
492
|
-
});
|
|
493
|
-
|
|
494
463
|
inputs.enumeratorType.onChanged.subscribe((_) => {
|
|
495
|
-
const isLibraryModeChosen = inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library;
|
|
496
|
-
inputs.library.root.style.setProperty('display', isLibraryModeChosen ? 'flex' : 'none');
|
|
497
|
-
try {
|
|
498
|
-
if ((prevEnumerationType !== PolyToolEnumeratorTypes.Library && isLibraryModeChosen) || (prevEnumerationType === PolyToolEnumeratorTypes.Library && !isLibraryModeChosen)) {
|
|
499
|
-
const prevSinglePosition = inputs.placeholders.placeholdersValue.length === 1 ? inputs.placeholders.placeholdersValue[0].position : null;
|
|
500
|
-
// clear the placeHolders input and helm inputs if switching happened to/from Library mode
|
|
501
|
-
inputs.placeholders.clearInput();
|
|
502
|
-
inputs.placeholdersBreadth.clearInput();
|
|
503
|
-
if (isLibraryModeChosen && prevSinglePosition != null)
|
|
504
|
-
inputs.placeholders.addPosition(prevSinglePosition, inputs.library.value ?? '');
|
|
505
|
-
}
|
|
506
|
-
} catch (err: any) {
|
|
507
|
-
defaultErrorHandler(err, false);
|
|
508
|
-
}
|
|
509
464
|
prevEnumerationType = inputs.enumeratorType.value;
|
|
510
465
|
updateEnumTypeTooltip();
|
|
511
466
|
// Re-validate placeholders (Parallel mode has different constraints than Single/Matrix)
|
|
@@ -550,13 +505,7 @@ async function getPolyToolEnumerateDialog(
|
|
|
550
505
|
const clickedAtom = helmHelper.getHoveredAtom(argsX, argsY, mol, inputs.macromolecule.root.clientHeight);
|
|
551
506
|
if (clickedAtom) {
|
|
552
507
|
const clickedAtomContIdx = clickedAtom._parent.atoms.indexOf(clickedAtom);
|
|
553
|
-
|
|
554
|
-
let monomerValue = '';
|
|
555
|
-
if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library) {
|
|
556
|
-
inputs.placeholders.clearInput();
|
|
557
|
-
monomerValue = inputs.library.value ?? '';
|
|
558
|
-
}
|
|
559
|
-
inputs.placeholders.addPosition(clickedAtomContIdx, monomerValue);
|
|
508
|
+
inputs.placeholders.addPosition(clickedAtomContIdx, '');
|
|
560
509
|
}
|
|
561
510
|
} catch (err: any) {
|
|
562
511
|
defaultErrorHandler(err);
|
|
@@ -660,23 +609,10 @@ async function getPolyToolEnumerateDialog(
|
|
|
660
609
|
updateViewRules();
|
|
661
610
|
|
|
662
611
|
// === EXECUTION (OK button handler) ===
|
|
663
|
-
// Pre-flight validates inputs,
|
|
612
|
+
// Pre-flight validates inputs, builds params, and runs enumeration.
|
|
664
613
|
const exec = async (): Promise<void> => {
|
|
665
614
|
try {
|
|
666
615
|
const srcHelm = inputs.macromolecule.stringValue;
|
|
667
|
-
const helmSelections = wu.enumerate<HelmAtom>(inputs.macromolecule.molValue.atoms)
|
|
668
|
-
.filter(([a, aI]) => a.highlighted)
|
|
669
|
-
.map(([a, aI]) => a).toArray();
|
|
670
|
-
if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library) {
|
|
671
|
-
if (helmSelections.length === 0) {
|
|
672
|
-
grok.shell.warning('PolyTool: position for enumeration was not selected');
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
if (!inputs.library.value) {
|
|
676
|
-
grok.shell.warning('PolyTool: No monomer library was selected');
|
|
677
|
-
return;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
616
|
if (srcHelm === undefined || srcHelm === '') {
|
|
681
617
|
grok.shell.warning('PolyTool: no molecule was provided');
|
|
682
618
|
} else {
|
|
@@ -689,28 +625,7 @@ async function getPolyToolEnumerateDialog(
|
|
|
689
625
|
await getHelmHelper(); // initializes JSDraw and org
|
|
690
626
|
|
|
691
627
|
const placeHoldersValue = inputs.placeholders.placeholdersValue;
|
|
692
|
-
|
|
693
|
-
let enumerationType = inputs.enumeratorType.value;
|
|
694
|
-
if (enumerationType === PolyToolEnumeratorTypes.Library) {
|
|
695
|
-
if (placeHoldersValue.length !== 1) {
|
|
696
|
-
grok.shell.warning('Only one placeholder is allowed for Library mode');
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
|
-
if (!placeHoldersValue[0].monomers || !_libList.includes(placeHoldersValue[0].monomers[0])) {
|
|
700
|
-
grok.shell.warning('Valid Monomer Library is required for this enumerator type');
|
|
701
|
-
return;
|
|
702
|
-
}
|
|
703
|
-
const monLibName = placeHoldersValue[0].monomers[0];
|
|
704
|
-
const monLib = await libHelper.readSingleLibraryByName(monLibName);
|
|
705
|
-
if (!monLib) {
|
|
706
|
-
grok.shell.warning(`Monomer Library '${monLibName}' was not found`);
|
|
707
|
-
return;
|
|
708
|
-
}
|
|
709
|
-
const polymerType = helmTypeToPolymerType(helmSelections[0].biotype() ?? 'HELM_AA');
|
|
710
|
-
const peptideMonomers = monLib.getMonomerSymbolsByType(polymerType);
|
|
711
|
-
placeHoldersValue[0].monomers = peptideMonomers;
|
|
712
|
-
enumerationType = PolyToolEnumeratorTypes.Single;
|
|
713
|
-
}
|
|
628
|
+
const enumerationType = inputs.enumeratorType.value;
|
|
714
629
|
|
|
715
630
|
if (enumerationType === PolyToolEnumeratorTypes.Parallel) {
|
|
716
631
|
const nonEmpty = placeHoldersValue.filter((ph) => ph.monomers.length > 0);
|
|
@@ -762,7 +677,7 @@ async function getPolyToolEnumerateDialog(
|
|
|
762
677
|
.add(ui.divH([
|
|
763
678
|
ui.divV([
|
|
764
679
|
inputs.placeholders.root,
|
|
765
|
-
inputs.enumeratorType.root
|
|
680
|
+
inputs.enumeratorType.root],
|
|
766
681
|
{style: {width: '50%'}}
|
|
767
682
|
),
|
|
768
683
|
ui.divV([
|
|
@@ -810,7 +725,6 @@ async function getPolyToolEnumerateDialog(
|
|
|
810
725
|
chiralityEngine: inputs.chiralityEngine.value,
|
|
811
726
|
highlightMonomers: inputs.highlightMonomers.value,
|
|
812
727
|
rules: ruleFileList,
|
|
813
|
-
library: inputs.library.value,
|
|
814
728
|
};
|
|
815
729
|
},
|
|
816
730
|
/* applyInput */ (x: PolyToolEnumerateHelmSerialized): void => {
|
|
@@ -825,7 +739,6 @@ async function getPolyToolEnumerateDialog(
|
|
|
825
739
|
inputs.chiralityEngine.value = x.chiralityEngine ?? false;
|
|
826
740
|
inputs.highlightMonomers.value = x.highlightMonomers ?? false;
|
|
827
741
|
ruleInputs.setActive(x.rules);
|
|
828
|
-
inputs.library.value = x.library;
|
|
829
742
|
setTimeout(() => {
|
|
830
743
|
inputs.placeholders.invalidateGrid();
|
|
831
744
|
inputs.placeholdersBreadth.invalidateGrid();
|
package/src/polytool/types.ts
CHANGED