@datagrok/sequence-translator 1.4.5 → 1.4.6
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 +13 -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/files/polytool-rules/rules_example.json +1 -1
- package/files/samples/HELM.csv +6 -0
- package/files/samples/cyclized.csv +3 -2
- package/files/samples/cyclized_MSA.csv +5 -0
- package/package.json +5 -5
- package/src/apps/common/model/oligo-toolkit-package.ts +11 -4
- package/src/consts.ts +12 -0
- package/src/global.d.ts +13 -0
- package/src/package-test.ts +1 -0
- package/src/package.ts +5 -4
- package/src/polytool/pt-conversion.ts +222 -70
- package/src/polytool/pt-dialog.ts +17 -11
- package/src/polytool/pt-enumeration-helm-dialog.ts +63 -25
- package/src/polytool/pt-enumeration-helm.ts +9 -6
- package/src/polytool/pt-placeholders-breadth-input.ts +4 -4
- package/src/polytool/pt-placeholders-input.ts +6 -6
- package/src/polytool/pt-unrule-dialog.ts +5 -1
- package/src/polytool/pt-unrule.ts +3 -2
- package/src/polytool/types.ts +4 -4
- package/src/tests/polytool-chain-from-notation-tests.ts +108 -18
- package/src/tests/polytool-chain-parse-notation-tests.ts +52 -11
- package/src/tests/polytool-convert-tests.ts +102 -25
- package/src/tests/polytool-detectors-custom-notation-test.ts +1 -1
- package/src/tests/polytool-enumerate-breadth-tests.ts +4 -4
- package/src/utils/context-menu.ts +2 -2
- package/src/utils/cyclized.ts +6 -8
|
@@ -38,17 +38,18 @@ type PolyToolEnumerateChemSerialized = {
|
|
|
38
38
|
screenLibrary: string | null;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export function polyToolEnumerateChemUI(cell?: DG.Cell): void {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
export async function polyToolEnumerateChemUI(cell?: DG.Cell): Promise<void> {
|
|
42
|
+
await _package.initPromise;
|
|
43
|
+
try {
|
|
44
|
+
const dialog = await getPolyToolEnumerationChemDialog(cell);
|
|
45
|
+
dialog.show({resizable: true});
|
|
46
|
+
} catch (_err: any) {
|
|
47
|
+
grok.shell.warning('To run PolyTool Enumeration, sketch the molecule and specify the R group to vary');
|
|
48
|
+
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
export async function polyToolConvertUI(): Promise<void> {
|
|
52
|
+
await _package.initPromise;
|
|
52
53
|
let dialog: DG.Dialog;
|
|
53
54
|
try {
|
|
54
55
|
dialog = await getPolyToolConvertDialog();
|
|
@@ -234,6 +235,11 @@ async function getPolyToolEnumerationChemDialog(cell?: DG.Cell): Promise<DG.Dial
|
|
|
234
235
|
}
|
|
235
236
|
}
|
|
236
237
|
|
|
238
|
+
function dealGroups(col: DG.Column<string>): void {
|
|
239
|
+
for (let i = 0; i < col.length; i++)
|
|
240
|
+
col.set(i, col.get(i)!.replaceAll('undefined', 'H'));
|
|
241
|
+
}
|
|
242
|
+
|
|
237
243
|
/** Returns Helm and molfile columns. */
|
|
238
244
|
export async function polyToolConvert(
|
|
239
245
|
seqCol: DG.Column<string>, generateHelm: boolean, chiralityEngine: boolean, ruleFiles: string[]
|
|
@@ -244,11 +250,11 @@ export async function polyToolConvert(
|
|
|
244
250
|
if (!df) return colName;
|
|
245
251
|
return df.columns.getUnusedName(colName);
|
|
246
252
|
};
|
|
247
|
-
await getHelmHelper(); // initializes JSDraw and org
|
|
253
|
+
const helmHelper = await getHelmHelper(); // initializes JSDraw and org
|
|
248
254
|
|
|
249
255
|
const table = seqCol.dataFrame;
|
|
250
256
|
const rules = await getRules(ruleFiles);
|
|
251
|
-
const resList = doPolyToolConvert(seqCol.toList(), rules);
|
|
257
|
+
const resList = doPolyToolConvert(seqCol.toList(), rules, helmHelper);
|
|
252
258
|
|
|
253
259
|
const resHelmColName = getUnusedName(table, `transformed(${seqCol.name})`);
|
|
254
260
|
const resHelmCol = DG.Column.fromType(DG.COLUMN_TYPE.STRING, resHelmColName, resList.length)
|
|
@@ -267,7 +273,7 @@ export async function polyToolConvert(
|
|
|
267
273
|
const toAtomicLevelRes =
|
|
268
274
|
await seqHelper.helmToAtomicLevel(resHelmCol, chiralityEngine, /* highlight */ generateHelm, lib);
|
|
269
275
|
const resMolCol = toAtomicLevelRes.molCol!;
|
|
270
|
-
|
|
276
|
+
dealGroups(resMolCol);
|
|
271
277
|
resMolCol.name = getUnusedName(table, `molfile(${seqCol.name})`);
|
|
272
278
|
resMolCol.semType = DG.SEMTYPE.MOLECULE;
|
|
273
279
|
if (table) {
|
|
@@ -5,10 +5,8 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
import $ from 'cash-dom';
|
|
6
6
|
import wu from 'wu';
|
|
7
7
|
import {fromEvent, Unsubscribable} from 'rxjs';
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import {HelmAtom, HelmMol} from '@datagrok-libraries/helm-web-editor/src/types/org-helm';
|
|
11
|
-
import {getHelmHelper, HelmInputBase} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
8
|
+
import {HelmAtom} from '@datagrok-libraries/helm-web-editor/src/types/org-helm';
|
|
9
|
+
import {getHelmHelper, HelmInputBase, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
12
10
|
import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
13
11
|
import {HelmType, PolymerType} from '@datagrok-libraries/bio/src/helm/types';
|
|
14
12
|
import {helmTypeToPolymerType} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
|
|
@@ -17,17 +15,17 @@ import '@datagrok-libraries/bio/src/types/input';
|
|
|
17
15
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
18
16
|
import {InputColumnBase} from '@datagrok-libraries/bio/src/types/input';
|
|
19
17
|
|
|
20
|
-
import {
|
|
21
|
-
PolyToolEnumeratorParams, PolyToolEnumeratorType, PolyToolEnumeratorTypes
|
|
22
|
-
} from './types';
|
|
18
|
+
import {PolyToolEnumeratorParams, PolyToolEnumeratorType, PolyToolEnumeratorTypes} from './types';
|
|
23
19
|
import {getLibrariesList} from './utils';
|
|
24
20
|
import {doPolyToolEnumerateHelm, PT_HELM_EXAMPLE} from './pt-enumeration-helm';
|
|
25
21
|
import {PolyToolPlaceholdersInput} from './pt-placeholders-input';
|
|
26
22
|
import {defaultErrorHandler} from '../utils/err-info';
|
|
27
23
|
import {PolyToolPlaceholdersBreadthInput} from './pt-placeholders-breadth-input';
|
|
28
24
|
import {PT_UI_DIALOG_ENUMERATION} from './const';
|
|
25
|
+
import {PolyToolDataRole, PolyToolTags} from '../consts';
|
|
26
|
+
import {Chain} from './pt-conversion';
|
|
29
27
|
|
|
30
|
-
import {_package} from '../package';
|
|
28
|
+
import {_package, applyNotationProviderForCyclized} from '../package';
|
|
31
29
|
|
|
32
30
|
type PolyToolEnumerateInputs = {
|
|
33
31
|
macromolecule: HelmInputBase;
|
|
@@ -52,6 +50,8 @@ type PolyToolEnumerateHelmSerialized = {
|
|
|
52
50
|
};
|
|
53
51
|
|
|
54
52
|
export async function polyToolEnumerateHelmUI(cell?: DG.Cell): Promise<void> {
|
|
53
|
+
await _package.initPromise;
|
|
54
|
+
|
|
55
55
|
const maxWidth = window.innerWidth;
|
|
56
56
|
const maxHeight = window.innerHeight;
|
|
57
57
|
|
|
@@ -118,7 +118,6 @@ export async function polyToolEnumerateHelmUI(cell?: DG.Cell): Promise<void> {
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
122
121
|
async function getPolyToolEnumerateDialog(
|
|
123
122
|
cell?: DG.Cell, resizeInputs?: () => void
|
|
124
123
|
): Promise<DG.Dialog> {
|
|
@@ -312,11 +311,12 @@ async function getPolyToolEnumerateDialog(
|
|
|
312
311
|
inputs.macromolecule.root.style.setProperty('min-width', '250px', 'important');
|
|
313
312
|
// inputs.macromolecule.root.style.setProperty('max-height', '300px', 'important');
|
|
314
313
|
|
|
314
|
+
const phPosSet = new Set<number>(inputs.placeholders.placeholdersValue.map((ph) => ph.position));
|
|
315
315
|
const updateMolView = () => {
|
|
316
316
|
const mol = inputs.macromolecule.molValue;
|
|
317
317
|
for (let aI = 0; aI < mol.atoms.length; aI++) {
|
|
318
318
|
const a = mol.atoms[aI];
|
|
319
|
-
a.highlighted = aI
|
|
319
|
+
a.highlighted = phPosSet.has(aI);
|
|
320
320
|
}
|
|
321
321
|
inputs.macromolecule.redraw();
|
|
322
322
|
};
|
|
@@ -363,23 +363,33 @@ async function getPolyToolEnumerateDialog(
|
|
|
363
363
|
if (resizeInputs) resizeInputs();
|
|
364
364
|
};
|
|
365
365
|
|
|
366
|
-
const fillForCurrentCell = async (cell?: DG.Cell): Promise<
|
|
366
|
+
const fillForCurrentCell = async (cell?: DG.Cell): Promise<PolyToolDataRole> => {
|
|
367
|
+
let resDataRole;
|
|
367
368
|
let helmValue: string;
|
|
368
369
|
let table: DG.DataFrame | undefined = undefined;
|
|
369
370
|
if (cell && cell.rowIndex >= 0 && cell?.column.semType == DG.SEMTYPE.MACROMOLECULE) {
|
|
370
371
|
const sh = _package.seqHelper.getSeqHandler(cell.column);
|
|
371
|
-
const
|
|
372
|
-
helmValue =
|
|
372
|
+
const mValue = await sh.getValue(cell.rowIndex);
|
|
373
|
+
helmValue = mValue.value;
|
|
373
374
|
table = cell.dataFrame;
|
|
375
|
+
resDataRole = (mValue.tags[PolyToolTags.dataRole] as PolyToolDataRole.template) ?? PolyToolDataRole.macromolecule;
|
|
374
376
|
} else {
|
|
375
377
|
helmValue = PT_HELM_EXAMPLE;
|
|
378
|
+
resDataRole = PolyToolDataRole.macromolecule;
|
|
376
379
|
}
|
|
377
|
-
|
|
378
380
|
inputs.macromolecule.stringValue = helmValue;
|
|
381
|
+
|
|
382
|
+
if (resDataRole === PolyToolDataRole.template) {
|
|
383
|
+
inputs.toAtomicLevel.root.style.display = 'none';
|
|
384
|
+
} else {
|
|
385
|
+
inputs.toAtomicLevel.root.style.removeProperty('display');
|
|
386
|
+
}
|
|
387
|
+
|
|
379
388
|
fillTrivialNameList(table);
|
|
389
|
+
return resDataRole;
|
|
380
390
|
};
|
|
381
391
|
|
|
382
|
-
await fillForCurrentCell(cell);
|
|
392
|
+
let dataRole: PolyToolDataRole = await fillForCurrentCell(cell);
|
|
383
393
|
|
|
384
394
|
const exec = async (): Promise<void> => {
|
|
385
395
|
try {
|
|
@@ -402,10 +412,12 @@ async function getPolyToolEnumerateDialog(
|
|
|
402
412
|
const params: PolyToolEnumeratorParams = {
|
|
403
413
|
placeholders: inputs.placeholders.placeholdersValue,
|
|
404
414
|
type: inputs.enumeratorType.value!,
|
|
405
|
-
|
|
415
|
+
breadthPlaceholders: inputs.placeholdersBreadth.placeholdersBreadthValue,
|
|
406
416
|
keepOriginal: inputs.keepOriginal.value,
|
|
407
417
|
};
|
|
408
|
-
const
|
|
418
|
+
const toAtomicLevelV = inputs.toAtomicLevel.value && dataRole == PolyToolDataRole.macromolecule;
|
|
419
|
+
const enumeratorResDf = await polyToolEnumerateHelm(srcHelm, dataRole, srcId, params,
|
|
420
|
+
toAtomicLevelV, seqHelper, helmHelper);
|
|
409
421
|
grok.shell.addTableView(enumeratorResDf);
|
|
410
422
|
}
|
|
411
423
|
} catch (err: any) {
|
|
@@ -460,23 +472,49 @@ async function getPolyToolEnumerateDialog(
|
|
|
460
472
|
}
|
|
461
473
|
}
|
|
462
474
|
|
|
475
|
+
/**
|
|
476
|
+
* @param {DG.SemanticValue} srcValue Source value to enumerate, either of data role
|
|
477
|
+
* {@link PolyToolDataRole.template} or {@link PolyToolDataRole.macromolecule}
|
|
478
|
+
* */
|
|
463
479
|
async function polyToolEnumerateHelm(
|
|
464
|
-
srcHelm: string, srcId: { value: string, colName: string } | null,
|
|
465
|
-
toAtomicLevel: boolean, seqHelper: ISeqHelper,
|
|
480
|
+
srcHelm: string, dataRole: PolyToolDataRole, srcId: { value: string, colName: string } | null,
|
|
481
|
+
params: PolyToolEnumeratorParams, toAtomicLevel: boolean, seqHelper: ISeqHelper, helmHelper: IHelmHelper
|
|
466
482
|
): Promise<DG.DataFrame> {
|
|
467
483
|
const pi = DG.TaskBarProgressIndicator.create('PolyTool enumerating...');
|
|
468
484
|
try {
|
|
469
485
|
await getHelmHelper(); // initializes JSDraw and org
|
|
470
486
|
|
|
471
487
|
const resList = doPolyToolEnumerateHelm(srcHelm, srcId?.value ?? '', params);
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
488
|
+
let enumCol: DG.Column<string>;
|
|
489
|
+
switch (dataRole) {
|
|
490
|
+
case PolyToolDataRole.macromolecule: {
|
|
491
|
+
enumCol = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'Enumerated', resList.length)
|
|
492
|
+
.init((rowIdx: number) => resList[rowIdx][0]);
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
495
|
+
case PolyToolDataRole.template: {
|
|
496
|
+
const templateList: string[] = new Array<string>(resList.length);
|
|
497
|
+
for (let rowIdx = 0; rowIdx < resList.length; rowIdx++) {
|
|
498
|
+
const pseudoHelm = resList[rowIdx][0];
|
|
499
|
+
const chain = Chain.parseHelm(pseudoHelm, helmHelper);
|
|
500
|
+
templateList[rowIdx] = chain.getNotation();
|
|
501
|
+
}
|
|
502
|
+
enumCol = DG.Column.fromList(DG.COLUMN_TYPE.STRING, 'Enumerated', templateList);
|
|
503
|
+
// enumCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
504
|
+
// enumCol.setTag(PolyToolTags.dataRole, PolyToolDataRole.template);
|
|
505
|
+
// applyNotationProviderForCyclized(enumCol, '-');
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
const enumeratorResDf = DG.DataFrame.fromColumns([enumCol]);
|
|
510
|
+
await grok.data.detectSemanticTypes(enumeratorResDf);
|
|
511
|
+
if (dataRole == PolyToolDataRole.template) {
|
|
512
|
+
applyNotationProviderForCyclized(enumCol, '-');
|
|
513
|
+
}
|
|
475
514
|
|
|
476
|
-
if (toAtomicLevel) {
|
|
515
|
+
if (toAtomicLevel && dataRole != PolyToolDataRole.template) {
|
|
477
516
|
const seqHelper: ISeqHelper = await getSeqHelper();
|
|
478
|
-
const toAtomicLevelRes = await seqHelper.helmToAtomicLevel(
|
|
479
|
-
toAtomicLevelRes.molCol!.semType = DG.SEMTYPE.MOLECULE;
|
|
517
|
+
const toAtomicLevelRes = await seqHelper.helmToAtomicLevel(enumCol, true, true);
|
|
480
518
|
enumeratorResDf.columns.add(toAtomicLevelRes.molCol!, false);
|
|
481
519
|
}
|
|
482
520
|
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
|
|
12
12
|
import {Chain} from './pt-conversion';
|
|
13
13
|
import {getAvailableMonomers} from './utils';
|
|
14
|
-
import {PolyToolEnumeratorParams, PolyToolEnumeratorTypes,
|
|
14
|
+
import {PolyToolEnumeratorParams, PolyToolEnumeratorTypes, PolyToolPlaceholder, PolyToolBreadthPlaceholder} from './types';
|
|
15
15
|
|
|
16
16
|
// For example keep monomers presented in HELMCoreLibrary.json only (not [NH2])
|
|
17
17
|
export const PT_HELM_EXAMPLE = 'PEPTIDE1{R.[Aca].T.G.H.F.G.A.A.Y.P.E.[meI]}$$$$';
|
|
@@ -44,14 +44,14 @@ function polyToolEnumeratorCore(m: HelmMol, start: number, end: number, monomerL
|
|
|
44
44
|
* @param placeholders Placeholders by zero-based position key
|
|
45
45
|
* @returns {string[]} List of enumerated molecules in Helm format
|
|
46
46
|
*/
|
|
47
|
-
function getPtEnumeratorSingle(m: HelmMol, placeholders:
|
|
47
|
+
function getPtEnumeratorSingle(m: HelmMol, placeholders: PolyToolPlaceholder[]): HelmMol[] {
|
|
48
48
|
const coreResList: HelmMol[][] = placeholders
|
|
49
49
|
.map((ph) => polyToolEnumeratorCore(m, ph.position, ph.position, ph.monomers));
|
|
50
50
|
const resMolList = coreResList.reduce((acc, posList) => acc.concat(posList), []);
|
|
51
51
|
return resMolList;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
function getPtEnumeratorMatrix(m: HelmMol, placeholders:
|
|
54
|
+
function getPtEnumeratorMatrix(m: HelmMol, placeholders: PolyToolPlaceholder[]): HelmMol[] {
|
|
55
55
|
let resMolList = [m];
|
|
56
56
|
for (const ph of placeholders) {
|
|
57
57
|
const phResMolList: HelmMol[][] = resMolList.map((m: HelmMol) => polyToolEnumeratorCore(m, ph.position, ph.position, ph.monomers));
|
|
@@ -60,7 +60,10 @@ function getPtEnumeratorMatrix(m: HelmMol, placeholders: PolyToolPlaceholders):
|
|
|
60
60
|
return resMolList;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
function getPtEnumeratorBreadth(m: HelmMol, placeholdersBreadth:
|
|
63
|
+
function getPtEnumeratorBreadth(m: HelmMol, placeholdersBreadth: PolyToolBreadthPlaceholder[]): HelmMol[] {
|
|
64
|
+
if (placeholdersBreadth.length == 0)
|
|
65
|
+
return [];
|
|
66
|
+
|
|
64
67
|
let resMolList = [m];
|
|
65
68
|
for (const phb of placeholdersBreadth) {
|
|
66
69
|
const phResMolList: HelmMol[][] = resMolList.map((m: HelmMol) => polyToolEnumeratorCore(m, phb.start, phb.end, phb.monomers));
|
|
@@ -94,8 +97,8 @@ export function doPolyToolEnumerateHelm(
|
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
let resBreadthMolList: HelmMol[] = [];
|
|
97
|
-
if (params.
|
|
98
|
-
resBreadthMolList = getPtEnumeratorBreadth(molHandler.m, params.
|
|
100
|
+
if (params.breadthPlaceholders) {
|
|
101
|
+
resBreadthMolList = getPtEnumeratorBreadth(molHandler.m, params.breadthPlaceholders);
|
|
99
102
|
}
|
|
100
103
|
resMolList = resMolList.concat(resBreadthMolList);
|
|
101
104
|
|
|
@@ -3,7 +3,7 @@ import * as grok from 'datagrok-api/grok';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
5
|
import {Unsubscribable} from 'rxjs';
|
|
6
|
-
import {
|
|
6
|
+
import {PolyToolBreadthPlaceholder} from './types';
|
|
7
7
|
import {parseMonomerSymbolList} from './pt-placeholders-input';
|
|
8
8
|
|
|
9
9
|
export class PolyToolPlaceholdersBreadthInput extends DG.JsInputBase<DG.DataFrame> {
|
|
@@ -21,7 +21,7 @@ export class PolyToolPlaceholdersBreadthInput extends DG.JsInputBase<DG.DataFram
|
|
|
21
21
|
|
|
22
22
|
setStringValue(str: string): void { this.grid.dataFrame = DG.DataFrame.fromCsv(str); }
|
|
23
23
|
|
|
24
|
-
get placeholdersBreadthValue():
|
|
24
|
+
get placeholdersBreadthValue(): PolyToolBreadthPlaceholder[] {
|
|
25
25
|
return dfToPlaceholdersBreadth(this.grid.dataFrame);
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -97,8 +97,8 @@ export class PolyToolPlaceholdersBreadthInput extends DG.JsInputBase<DG.DataFram
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
export function dfToPlaceholdersBreadth(df: DG.DataFrame):
|
|
101
|
-
const res:
|
|
100
|
+
export function dfToPlaceholdersBreadth(df: DG.DataFrame): PolyToolBreadthPlaceholder[] {
|
|
101
|
+
const res: PolyToolBreadthPlaceholder[] = [];
|
|
102
102
|
for (let rowI = 0; rowI < df.rowCount; rowI++) {
|
|
103
103
|
const startPos = parseInt(df.get('Start', rowI)) - 1;
|
|
104
104
|
const endPos = parseInt(df.get('End', rowI)) - 1;
|
|
@@ -4,7 +4,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
|
|
5
5
|
import {Unsubscribable} from 'rxjs';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {PolyToolPlaceholder} from './types';
|
|
8
8
|
|
|
9
9
|
export class PolyToolPlaceholdersInput extends DG.JsInputBase<DG.DataFrame> {
|
|
10
10
|
get inputType(): string { return 'Positions'; }
|
|
@@ -21,7 +21,7 @@ export class PolyToolPlaceholdersInput extends DG.JsInputBase<DG.DataFrame> {
|
|
|
21
21
|
|
|
22
22
|
setStringValue(str: string): void { this.grid.dataFrame = DG.DataFrame.fromCsv(str); }
|
|
23
23
|
|
|
24
|
-
get placeholdersValue():
|
|
24
|
+
get placeholdersValue(): PolyToolPlaceholder[] {
|
|
25
25
|
return dfToPlaceholders(this.grid.dataFrame);
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -95,8 +95,8 @@ export class PolyToolPlaceholdersInput extends DG.JsInputBase<DG.DataFrame> {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
export function getPlaceholdersFromText(src: string):
|
|
99
|
-
const res:
|
|
98
|
+
export function getPlaceholdersFromText(src: string): PolyToolPlaceholder[] {
|
|
99
|
+
const res: PolyToolPlaceholder[] = [];
|
|
100
100
|
for (const line of src.split('\n')) {
|
|
101
101
|
const lineM = /^\s*(?<pos>\d+)\s*:\s*(?<monomers>.+)$/.exec(line);
|
|
102
102
|
if (lineM) {
|
|
@@ -108,8 +108,8 @@ export function getPlaceholdersFromText(src: string): PolyToolPlaceholders {
|
|
|
108
108
|
return res;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
export function dfToPlaceholders(df: DG.DataFrame):
|
|
112
|
-
const res:
|
|
111
|
+
export function dfToPlaceholders(df: DG.DataFrame): PolyToolPlaceholder[] {
|
|
112
|
+
const res: PolyToolPlaceholder[] = [];
|
|
113
113
|
for (let rowI = 0; rowI < df.rowCount; rowI++) {
|
|
114
114
|
const pos = parseInt(df.get('Position', rowI)) - 1;
|
|
115
115
|
if (!isNaN(pos)) {
|
|
@@ -6,11 +6,13 @@ import {Unsubscribable} from 'rxjs';
|
|
|
6
6
|
|
|
7
7
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
8
8
|
import {getUnusedColName} from '@datagrok-libraries/bio/src/monomer-works/utils';
|
|
9
|
+
import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
9
10
|
|
|
10
11
|
import {defaultErrorHandler} from '../utils/err-info';
|
|
11
12
|
import {doPolyToolUnrule} from './pt-unrule';
|
|
12
13
|
import {getRules, RuleInputs, RULES_PATH, RULES_STORAGE_NAME} from './pt-rules';
|
|
13
14
|
import {PT_ERROR_DATAFRAME, PT_UI_DIALOG_UNRULE, PT_UI_RULES_USED} from './const';
|
|
15
|
+
|
|
14
16
|
import {_package} from '../package';
|
|
15
17
|
|
|
16
18
|
type PolyToolUnruleSerialized = {
|
|
@@ -87,9 +89,11 @@ export async function polyToolUnrule(
|
|
|
87
89
|
): Promise<DG.Column> {
|
|
88
90
|
const pi = DG.TaskBarProgressIndicator.create('PolyTool unrule...');
|
|
89
91
|
try {
|
|
92
|
+
const helmHelper = await getHelmHelper();
|
|
93
|
+
|
|
90
94
|
const table = srcCol.dataFrame;
|
|
91
95
|
const rules = await getRules(ruleFiles);
|
|
92
|
-
const resHelmList = doPolyToolUnrule(srcCol.toList(), rules);
|
|
96
|
+
const resHelmList = doPolyToolUnrule(srcCol.toList(), rules, helmHelper);
|
|
93
97
|
const resHelmColName = `harmonized(srcCol.name)`;
|
|
94
98
|
const resHelmCol = DG.Column.fromList(DG.COLUMN_TYPE.STRING, resHelmColName, resHelmList,);
|
|
95
99
|
resHelmCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
@@ -9,6 +9,7 @@ import {getPolyToolUnruleDialog} from './pt-unrule-dialog';
|
|
|
9
9
|
import {Rules} from './pt-rules';
|
|
10
10
|
|
|
11
11
|
import {_package} from '../package';
|
|
12
|
+
import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
12
13
|
|
|
13
14
|
export async function polyToolUnruleUI(): Promise<void> {
|
|
14
15
|
let dialog: DG.Dialog;
|
|
@@ -23,13 +24,13 @@ export async function polyToolUnruleUI(): Promise<void> {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/** Returns list of harmonized sequences. Covered with tests. */
|
|
26
|
-
export function doPolyToolUnrule(helms: string[], rules: Rules): string[] {
|
|
27
|
+
export function doPolyToolUnrule(helms: string[], rules: Rules, helmHelper: IHelmHelper): string[] {
|
|
27
28
|
const resHrzSeqList = new Array<string>(helms.length);
|
|
28
29
|
for (let i = 0; i < helms.length; ++i) {
|
|
29
30
|
if (!helms[i])
|
|
30
31
|
resHrzSeqList[i] = '';
|
|
31
32
|
else {
|
|
32
|
-
const chain = Chain.
|
|
33
|
+
const chain = Chain.parseHelm(helms[i], helmHelper);
|
|
33
34
|
resHrzSeqList[i] = chain.getNotation();
|
|
34
35
|
}
|
|
35
36
|
}
|
package/src/polytool/types.ts
CHANGED
|
@@ -11,15 +11,15 @@ export enum PolyToolEnumeratorTypes {
|
|
|
11
11
|
|
|
12
12
|
export type PolyToolEnumeratorType = typeof PolyToolEnumeratorTypes[keyof typeof PolyToolEnumeratorTypes];
|
|
13
13
|
|
|
14
|
-
export type
|
|
14
|
+
export type PolyToolPlaceholder = { position: number, monomers: string[] };
|
|
15
15
|
|
|
16
|
-
export type
|
|
16
|
+
export type PolyToolBreadthPlaceholder = { start: number, end: number, monomers: string[] };
|
|
17
17
|
|
|
18
18
|
export type PolyToolEnumeratorParams = {
|
|
19
19
|
type: PolyToolEnumeratorType;
|
|
20
20
|
/** position key is zero-based */
|
|
21
|
-
placeholders?:
|
|
22
|
-
|
|
21
|
+
placeholders?: PolyToolPlaceholder[];
|
|
22
|
+
breadthPlaceholders?: PolyToolBreadthPlaceholder[];
|
|
23
23
|
keepOriginal?: boolean;
|
|
24
24
|
trivialName?: boolean;
|
|
25
25
|
}
|
|
@@ -5,41 +5,131 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
import {before, after, category, expect, test, expectArray, testEvent, delay} from '@datagrok-libraries/utils/src/test';
|
|
6
6
|
import {Chain} from '../polytool/pt-conversion';
|
|
7
7
|
import {getRules} from '../polytool/pt-rules';
|
|
8
|
+
import {getHelmHelper, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
9
|
+
|
|
10
|
+
category('PolyTool: Chain', () => {
|
|
11
|
+
let helmHelper: IHelmHelper;
|
|
12
|
+
|
|
13
|
+
before(async () => {
|
|
14
|
+
helmHelper = await getHelmHelper();
|
|
15
|
+
});
|
|
8
16
|
|
|
9
|
-
category('PolyTool: Chain: fromNotation', () => {
|
|
10
17
|
const tests = {
|
|
11
18
|
'cyclized': {
|
|
12
|
-
|
|
19
|
+
data: {
|
|
20
|
+
templateSeq: 'R-F-C(1)-T-G-H-F-Y-P-C(1)-meI',
|
|
21
|
+
templateHelm: 'PEPTIDE1{R.F.[C(1)].T.G.H.F.Y.P.[C(1)].[meI]}$$$$V2.0',
|
|
22
|
+
mmHelm: 'PEPTIDE1{R.F.C.T.G.H.F.Y.P.C.[meI]}$PEPTIDE1,PEPTIDE1,3:R3-10:R3$$$V2.0',
|
|
23
|
+
},
|
|
13
24
|
tgt: {
|
|
14
|
-
monomerCount: [11], linkageCount:
|
|
15
|
-
|
|
25
|
+
templateChain: {monomerCount: [11], linkageCount: 0},
|
|
26
|
+
mmChain: {monomerCount: [11], linkageCount: 1,}
|
|
16
27
|
},
|
|
17
28
|
},
|
|
18
29
|
'reaction1': {
|
|
19
|
-
|
|
30
|
+
data: {
|
|
31
|
+
templateSeq: 'R-F-azG(4)-T-G-H-F-Y-P-aG(4)-meI',
|
|
32
|
+
templateHelm: 'PEPTIDE1{R.F.[azG(4)].T.G.H.F.Y.P.[aG(4)].[meI]}$$$$V2.0',
|
|
33
|
+
mmHelm: 'PEPTIDE1{R.F.[GGaz].T.G.H.F.Y.P}|PEPTIDE2{[meI]}$PEPTIDE1,PEPTIDE1,3:R3-9:R2|PEPTIDE1,PEPTIDE2,3:R4-1:R1$$$V2.0',
|
|
34
|
+
},
|
|
20
35
|
tgt: {
|
|
21
|
-
monomerCount: [
|
|
22
|
-
|
|
36
|
+
templateChain: {monomerCount: [11], linkageCount: 0,},
|
|
37
|
+
mmChain: {monomerCount: [9, 1], linkageCount: 2,}
|
|
23
38
|
}
|
|
24
39
|
},
|
|
25
40
|
'reaction2': {
|
|
26
|
-
|
|
41
|
+
data: {
|
|
42
|
+
templateSeq: 'R-F-aG(4)-T-G-H-F-Y-P-azG(4)-meI',
|
|
43
|
+
templateHelm: 'PEPTIDE1{R.F.[aG(4)].T.G.H.F.Y.P.[azG(4)].[meI]}$$$$V2.0',
|
|
44
|
+
mmHelm: 'PEPTIDE1{R.F}|PEPTIDE2{T.G.H.F.Y.P.[GGaz].[meI]}$PEPTIDE1,PEPTIDE2,2:R2-7:R3|PEPTIDE2,PEPTIDE2,1:R1-7:R4,$$$V2.0',
|
|
45
|
+
},
|
|
46
|
+
tgt: {
|
|
47
|
+
templateChain: {monomerCount: [11], linkageCount: 0,},
|
|
48
|
+
mmChain: {monomerCount: [2, 8], linkageCount: 2,}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
'dimerized1': {
|
|
52
|
+
data: {
|
|
53
|
+
templateSeq: '(#3)Succ-{A(CHOL)-F-C(1)-T-G-H-Y-P-C(1)-NH2}',
|
|
54
|
+
templateHelm: 'PEPTIDE1{[(#3)Succ]}' + '|' +
|
|
55
|
+
'PEPTIDE2{[A(CHOL)].F.[C(1)].T.G.H.Y.P.[C(1)].[NH2]}' + '$' +
|
|
56
|
+
'PEPTIDE1,PEPTIDE2,1:R1-1:R1' + '$$$' + 'V2.0',
|
|
57
|
+
mmHelm: 'PEPTIDE1{[Succ].[A(CHOL)].F.C.T.G.H.Y.P.C.[NH2]}' + '|' +
|
|
58
|
+
'PEPTIDE2{[A(CHOL)].F.C.T.G.H.Y.P.C.[NH2]}' + '$' +
|
|
59
|
+
'PEPTIDE1,PEPTIDE2,1:R1-1:R1' + '|' +
|
|
60
|
+
'PEPTIDE1,PEPTIDE1,4:R3-10:R3' + '|' +
|
|
61
|
+
'PEPTIDE2,PEPTIDE2,3:R3-9:R3' + '$$$V2.0',
|
|
62
|
+
},
|
|
63
|
+
tgt: {
|
|
64
|
+
templateChain: {monomerCount: [1, 10], linkageCount: 1},
|
|
65
|
+
mmChain: {monomerCount: [11, 10], linkageCount: 3,}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
'dimerized2': {
|
|
69
|
+
data: {
|
|
70
|
+
templateSeq: '($3)Succ-{R-F-C(1)-T-G-H-F-P-C(1)-NH2}($3){A(CHOL)-F-C(1)-Y-H-G-D-N-C(1)-meI}',
|
|
71
|
+
templateHelm: 'PEPTIDE1{[($3)Succ]}' + '|' +
|
|
72
|
+
'PEPTIDE2{R.F.[C(1)].T.G.H.F.P.[C(1)].[NH2]}' + '|' +
|
|
73
|
+
'PEPTIDE3{[($3)A(CHOL)].F.[C(1)].Y.H.G.D.N.[C(1)].[meI]}' + '$' +
|
|
74
|
+
'PEPTIDE1,PEPTIDE2,1:R1-1:R1' + '$$$' + 'V2.0',
|
|
75
|
+
mmHelm: 'PEPTIDE1{[Succ].R.F.C.T.G.H.F.P.C.[NH2]}' + '|' +
|
|
76
|
+
'PEPTIDE2{[A(CHOL)].F.C.Y.H.G.D.N.C.[meI]}' + '$' +
|
|
77
|
+
'PEPTIDE1,PEPTIDE2,1:R1-1:R1' + '|' +
|
|
78
|
+
'PEPTIDE1,PEPTIDE1,4:R3-10:R3' + '|' +
|
|
79
|
+
'PEPTIDE2,PEPTIDE2,3:R3-9:R3' + '$$$V2.0',
|
|
80
|
+
},
|
|
27
81
|
tgt: {
|
|
28
|
-
|
|
29
|
-
monomerCount: [
|
|
30
|
-
helm: 'PEPTIDE1{R.F}|PEPTIDE2{T.G.H.F.Y.P.[GGaz].[meI]}$PEPTIDE1,PEPTIDE2,2:R2-7:R3|PEPTIDE2,PEPTIDE2,1:R1-7:R4,$$$',
|
|
82
|
+
templateChain: {monomerCount: [1, 10, 10], linkageCount: 1,},
|
|
83
|
+
mmChain: {monomerCount: [11, 10], linkageCount: 3,}
|
|
31
84
|
}
|
|
32
85
|
}
|
|
33
|
-
|
|
34
86
|
};
|
|
35
87
|
|
|
36
|
-
for (const [testName,
|
|
37
|
-
test(
|
|
88
|
+
for (const [testName, {data, tgt}] of Object.entries(tests)) {
|
|
89
|
+
test(`fromNotation-${testName}`, async () => {
|
|
38
90
|
const rules = await getRules(['rules_example.json']);
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
expect(
|
|
91
|
+
const resMmChain = Chain.fromNotation(data.templateSeq, rules, helmHelper);
|
|
92
|
+
resMmChain.check(true);
|
|
93
|
+
expectArray(resMmChain.monomers.map((mL) => mL.length), tgt.mmChain.monomerCount);
|
|
94
|
+
expect(resMmChain.linkages.length, tgt.mmChain.linkageCount);
|
|
95
|
+
expect(resMmChain.getHelm(), data.mmHelm);
|
|
43
96
|
}, testName == 'reaction2' ? {skipReason: 'reverse reaction'} : undefined);
|
|
44
97
|
}
|
|
98
|
+
|
|
99
|
+
for (const [testName, {data, tgt}] of Object.entries(tests)) {
|
|
100
|
+
test(`parseNotation-${testName}`, async () => {
|
|
101
|
+
const rules = await getRules(['rules_example.json']);
|
|
102
|
+
const resTemplateChain = Chain.parseNotation(data.templateSeq, helmHelper);
|
|
103
|
+
resTemplateChain.check(true);
|
|
104
|
+
expectArray(resTemplateChain.monomers.map((mL) => mL.length), tgt.templateChain.monomerCount);
|
|
105
|
+
expect(resTemplateChain.linkages.length, tgt.templateChain.linkageCount);
|
|
106
|
+
expect(resTemplateChain.getHelm(), data.templateHelm);
|
|
107
|
+
expect(resTemplateChain.getNotation(), data.templateSeq);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
for (const [testName, {data, tgt}] of Object.entries(tests)) {
|
|
112
|
+
test(`parseHelm-${testName}`, async () => {
|
|
113
|
+
const rules = await getRules(['rules_example.json']);
|
|
114
|
+
const resTemplateChain = Chain.parseHelm(data.templateHelm, helmHelper);
|
|
115
|
+
resTemplateChain.check(true);
|
|
116
|
+
expectArray(resTemplateChain.monomers.map((mL) => mL.length), tgt.templateChain.monomerCount);
|
|
117
|
+
expect(resTemplateChain.linkages.length, tgt.templateChain.linkageCount);
|
|
118
|
+
expect(resTemplateChain.getHelm(), data.templateHelm);
|
|
119
|
+
expect(resTemplateChain.getNotation(), data.templateSeq);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
for (const [testName, {data, tgt}] of Object.entries(tests)) {
|
|
124
|
+
test(`applyRules-${testName}`, async () => {
|
|
125
|
+
const rules = await getRules(['rules_example.json']);
|
|
126
|
+
const resTemplateChain = Chain.parseNotation(data.templateSeq, helmHelper);
|
|
127
|
+
const resMmChain = resTemplateChain.applyRules(rules);
|
|
128
|
+
resMmChain.check(true);
|
|
129
|
+
expectArray(resMmChain.monomers.map((mL) => mL.length), tgt.mmChain.monomerCount);
|
|
130
|
+
expect(resMmChain.linkages.length, tgt.mmChain.linkageCount);
|
|
131
|
+
expect(resMmChain.getHelm(), data.mmHelm);
|
|
132
|
+
}, {skipReason: 'applyRules is not implemented'});
|
|
133
|
+
}
|
|
134
|
+
|
|
45
135
|
});
|