@datagrok/sequence-translator 1.4.8 → 1.4.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/.eslintrc.json +1 -1
- package/CHANGELOG.md +18 -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 +9 -9
- package/src/apps/common/model/oligo-toolkit-package.ts +13 -7
- package/src/package.ts +8 -7
- package/src/polytool/const.ts +1 -0
- package/src/polytool/{pt-conversion.ts → conversion/pt-chain.ts} +37 -241
- package/src/polytool/conversion/pt-conversion.ts +27 -0
- package/src/polytool/conversion/pt-misc.ts +183 -0
- package/src/polytool/pt-dialog.ts +133 -6
- package/src/polytool/{pt-enumeration-helm-dialog.ts → pt-enumerate-seq-dialog.ts} +241 -112
- package/src/polytool/pt-enumeration-helm.ts +2 -2
- package/src/polytool/pt-placeholders-breadth-input.ts +80 -39
- package/src/polytool/pt-placeholders-input.ts +96 -35
- package/src/polytool/pt-unrule.ts +1 -1
- package/src/polytool/types.ts +5 -1
- package/src/tests/polytool-chain-from-notation-tests.ts +3 -4
- package/src/tests/polytool-chain-parse-notation-tests.ts +2 -1
- package/src/tests/polytool-convert-tests.ts +2 -1
- package/src/tests/toAtomicLevel-tests.ts +1 -2
- package/src/utils/cell-renderer-cyclized.ts +37 -0
- package/src/utils/context-menu.ts +1 -1
- package/src/utils/cyclized.ts +23 -26
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.10",
|
|
5
5
|
"author": {
|
|
6
|
-
"name": "
|
|
7
|
-
"email": "
|
|
6
|
+
"name": "Leonid Stolbov",
|
|
7
|
+
"email": "lstolbov@datagrok.ai"
|
|
8
8
|
},
|
|
9
9
|
"description": "SequenceTranslator translates [oligonucleotide](https://en.wikipedia.org/wiki/Oligonucleotide) sequences between [different representations](https://github.com/datagrok-ai/public/tree/master/packages/SequenceTranslator#sequence-representations).",
|
|
10
10
|
"repository": {
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
}
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@datagrok-libraries/bio": "^5.45.
|
|
25
|
+
"@datagrok-libraries/bio": "^5.45.6",
|
|
26
26
|
"@datagrok-libraries/chem-meta": "^1.2.7",
|
|
27
27
|
"@datagrok-libraries/tutorials": "^1.4.3",
|
|
28
|
-
"@datagrok-libraries/utils": "^4.3.
|
|
28
|
+
"@datagrok-libraries/utils": "^4.3.7",
|
|
29
29
|
"@types/react": "^18.0.15",
|
|
30
30
|
"cash-dom": "^8.1.0",
|
|
31
31
|
"datagrok-api": "^1.21.1",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"wu": "^2.1.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@datagrok-libraries/helm-web-editor": "^1.1.
|
|
43
|
-
"@datagrok-libraries/js-draw-lite": "^0.0.
|
|
44
|
-
"@datagrok/bio": "^2.16.
|
|
45
|
-
"@datagrok/helm": "^2.5.
|
|
42
|
+
"@datagrok-libraries/helm-web-editor": "^1.1.13",
|
|
43
|
+
"@datagrok-libraries/js-draw-lite": "^0.0.10",
|
|
44
|
+
"@datagrok/bio": "^2.16.8",
|
|
45
|
+
"@datagrok/helm": "^2.5.8",
|
|
46
46
|
"@datagrok/chem": "^1.12.4",
|
|
47
47
|
"@types/jquery": "^3.5.14",
|
|
48
48
|
"@types/js-yaml": "^4.0.5",
|
|
@@ -5,6 +5,8 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
6
6
|
import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
|
|
7
7
|
import {LoggerWrapper} from '@datagrok-libraries/bio/src/utils/logger';
|
|
8
|
+
import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
9
|
+
import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
8
10
|
|
|
9
11
|
import {APP_NAME} from '../view/const';
|
|
10
12
|
import {DEFAULT_LIB_FILENAME, FALLBACK_LIB_PATH} from './data-loader/const';
|
|
@@ -16,14 +18,18 @@ import {MonomerLibWrapper} from './monomer-lib/lib-wrapper';
|
|
|
16
18
|
import {FormatConverter} from '../../translator/model/format-converter';
|
|
17
19
|
import {FormatDetector} from './parsing-validation/format-detector';
|
|
18
20
|
import {highlightInvalidSubsequence} from '../view/components/colored-input/input-painters';
|
|
19
|
-
import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
20
21
|
|
|
21
22
|
export class OligoToolkitPackage extends DG.Package implements ITranslationHelper {
|
|
22
|
-
|
|
23
|
+
|
|
24
|
+
private _helmHelper: IHelmHelper;
|
|
25
|
+
public get helmHelper(): IHelmHelper {
|
|
26
|
+
if (!this._helmHelper)
|
|
27
|
+
throw new Error('Package SequenceTranslator .helmHelper is not initialized');
|
|
28
|
+
return this._helmHelper;
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
public get seqHelper(): ISeqHelper {
|
|
24
|
-
|
|
25
|
-
throw new Error('Package SequenceTranslator .seqHelper is not initialized');
|
|
26
|
-
return this._seqHelper;
|
|
32
|
+
return this._helmHelper.seqHelper;
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
private _monomerLib?: IMonomerLib;
|
|
@@ -60,8 +66,8 @@ export class OligoToolkitPackage extends DG.Package implements ITranslationHelpe
|
|
|
60
66
|
this._initPromise = initPromise;
|
|
61
67
|
}
|
|
62
68
|
|
|
63
|
-
completeInit(
|
|
64
|
-
this.
|
|
69
|
+
completeInit(helmHelper: IHelmHelper): void {
|
|
70
|
+
this._helmHelper = helmHelper;
|
|
65
71
|
}
|
|
66
72
|
|
|
67
73
|
private initLibDataPromise?: Promise<void>;
|
package/src/package.ts
CHANGED
|
@@ -18,7 +18,7 @@ import {defaultErrorHandler} from './utils/err-info';
|
|
|
18
18
|
//polytool specific
|
|
19
19
|
import {polyToolConvert, polyToolConvertUI} from './polytool/pt-dialog';
|
|
20
20
|
import {polyToolEnumerateChemUI} from './polytool/pt-dialog';
|
|
21
|
-
import {polyToolEnumerateHelmUI} from './polytool/pt-
|
|
21
|
+
import {polyToolEnumerateHelmUI} from './polytool/pt-enumerate-seq-dialog';
|
|
22
22
|
import {_setPeptideColumn} from './polytool/utils';
|
|
23
23
|
import {PolyToolCsvLibHandler} from './polytool/csv-to-json-monomer-lib-converter';
|
|
24
24
|
import {ITranslationHelper} from './types';
|
|
@@ -27,6 +27,7 @@ import {PolyToolConvertFuncEditor} from './polytool/pt-convert-editor';
|
|
|
27
27
|
import {CyclizedNotationProvider} from './utils/cyclized';
|
|
28
28
|
import {getSeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
29
29
|
import {PolyToolTags} from './consts';
|
|
30
|
+
import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
30
31
|
|
|
31
32
|
export const _package: OligoToolkitPackage = new OligoToolkitPackage({debug: true}/**/);
|
|
32
33
|
|
|
@@ -34,17 +35,17 @@ let initSequenceTranslatorPromise: Promise<void> | null = null;
|
|
|
34
35
|
|
|
35
36
|
//tags: init
|
|
36
37
|
export async function init(): Promise<void> {
|
|
37
|
-
if (initSequenceTranslatorPromise === null)
|
|
38
|
+
if (initSequenceTranslatorPromise === null)
|
|
38
39
|
_package.startInit(initSequenceTranslatorPromise = initSequenceTranslatorInt());
|
|
39
|
-
|
|
40
|
+
|
|
40
41
|
return initSequenceTranslatorPromise;
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
async function initSequenceTranslatorInt(): Promise<void> {
|
|
44
|
-
const [
|
|
45
|
-
|
|
45
|
+
const [helmHelper] = await Promise.all([
|
|
46
|
+
getHelmHelper(),
|
|
46
47
|
]);
|
|
47
|
-
_package.completeInit(
|
|
48
|
+
_package.completeInit(helmHelper);
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
//name: Oligo Toolkit
|
|
@@ -302,5 +303,5 @@ export async function ptEnumeratorChemApp(): Promise<void> {
|
|
|
302
303
|
export function applyNotationProviderForCyclized(col: DG.Column<string>, separator: string) {
|
|
303
304
|
col.meta.units = NOTATION.CUSTOM;
|
|
304
305
|
col.tags[PolyToolTags.dataRole] = 'template';
|
|
305
|
-
col.temp[SeqTemps.notationProvider] = new CyclizedNotationProvider(separator, _package.
|
|
306
|
+
col.temp[SeqTemps.notationProvider] = new CyclizedNotationProvider(separator, _package.helmHelper);
|
|
306
307
|
}
|
package/src/polytool/const.ts
CHANGED
|
@@ -33,6 +33,7 @@ export const PT_WARNING_COLUMN = 'No marcomolecule column chosen!';
|
|
|
33
33
|
export const PT_UI_GET_HELM = 'Get HELM';
|
|
34
34
|
export const PT_UI_ADD_HELM = 'Add HELM column';
|
|
35
35
|
export const PT_UI_USE_CHIRALITY = 'Chirality engine';
|
|
36
|
+
export const PT_UI_HIGHLIGHT_MONOMERS = 'Highlight monomers';
|
|
36
37
|
export const PT_UI_DIALOG_CONVERSION = 'Poly Tool Conversion';
|
|
37
38
|
export const PT_UI_DIALOG_UNRULE = 'Poly Tool Unrule';
|
|
38
39
|
export const PT_UI_DIALOG_ENUMERATION = 'Poly Tool Enumeration';
|
|
@@ -1,24 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import wu from 'wu';
|
|
6
|
-
|
|
1
|
+
import {Atom, IHelmBio, HelmMol, HelmType, JSDraw2ModuleType, OrgType,} from '@datagrok-libraries/bio/src/helm/types';
|
|
2
|
+
import {getHelmHelper, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
3
|
+
import {HelmTypes} from '@datagrok-libraries/bio/src/helm/consts';
|
|
7
4
|
import {cleanupHelmSymbol} from '@datagrok-libraries/bio/src/helm/utils';
|
|
8
|
-
import {HelmTypes, PolymerTypes} from '@datagrok-libraries/bio/src/helm/consts';
|
|
9
|
-
import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
10
|
-
import {IMonomerLib, IMonomerLibBase, Monomer, MonomerLibData, RGroup} from '@datagrok-libraries/bio/src/types';
|
|
11
|
-
import {RDModule, RDMol, RDReaction, MolList, RDReactionResult} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
12
|
-
import {HELM_REQUIRED_FIELD as REQ, HELM_OPTIONAL_FIELDS as OPT, HELM_RGROUP_FIELDS, HELM_OPTIONAL_FIELDS} from '@datagrok-libraries/bio/src/utils/const';
|
|
13
|
-
import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
|
|
14
|
-
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
15
|
-
import {HelmAtom, HelmBio, HelmMol, HelmType, JSDraw2ModuleType, OrgType} from '@datagrok-libraries/bio/src/helm/types';
|
|
16
|
-
import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
17
|
-
|
|
18
|
-
import {Rules, RuleLink, RuleReaction} from './pt-rules';
|
|
19
|
-
import {InvalidReactionError, MonomerNotFoundError} from './types';
|
|
20
5
|
|
|
21
|
-
import {
|
|
6
|
+
import {getOuterIdx, getInnerIdx} from './pt-misc';
|
|
7
|
+
import {Rules, RuleLink, RuleReaction} from '../pt-rules';
|
|
22
8
|
|
|
23
9
|
declare const JSDraw2: JSDraw2ModuleType;
|
|
24
10
|
declare const org: OrgType;
|
|
@@ -31,8 +17,9 @@ type Linkage = {
|
|
|
31
17
|
fR: number,
|
|
32
18
|
sR: number
|
|
33
19
|
}
|
|
20
|
+
export type PtBio = IHelmBio & { i: number, j: number };
|
|
34
21
|
|
|
35
|
-
type
|
|
22
|
+
type PtAtom = Atom<HelmType, PtBio>
|
|
36
23
|
|
|
37
24
|
export class Chain {
|
|
38
25
|
linkages: Linkage[];
|
|
@@ -40,9 +27,9 @@ export class Chain {
|
|
|
40
27
|
mol: HelmMol;
|
|
41
28
|
|
|
42
29
|
constructor(
|
|
43
|
-
monomers: string[][],
|
|
44
|
-
|
|
45
|
-
|
|
30
|
+
monomers: string[][], linkages: Linkage[], mol: HelmMol,
|
|
31
|
+
protected helmHelper: IHelmHelper,
|
|
32
|
+
) {
|
|
46
33
|
this.linkages = linkages;
|
|
47
34
|
this.monomers = monomers;
|
|
48
35
|
this.mol = mol;
|
|
@@ -73,14 +60,14 @@ export class Chain {
|
|
|
73
60
|
monomers[i] = rawFragments[i].slice(idxStart + 1, idxEnd).split('.').map((s) => cleanupHelmSymbol(s));
|
|
74
61
|
for (let j = 0; j < monomers[i].length; j++) {
|
|
75
62
|
const elem = monomers[i][j];
|
|
76
|
-
const bio:
|
|
77
|
-
const atom = new JSDraw2.Atom<HelmType>(p, elem, bio);
|
|
63
|
+
const bio: PtBio = {type: HelmTypes.AA, i: i, j: j, continuousId: counter};
|
|
64
|
+
const atom = new JSDraw2.Atom<HelmType, IHelmBio>(p, elem, bio);
|
|
78
65
|
resMol.addAtom(atom);
|
|
79
66
|
|
|
80
67
|
if (j !== 0) {
|
|
81
68
|
const atom1 = resMol.atoms[counter - 1];
|
|
82
69
|
const atom2 = resMol.atoms[counter];
|
|
83
|
-
const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
|
|
70
|
+
const bond = new JSDraw2.Bond<HelmType, IHelmBio>(atom1, atom2);
|
|
84
71
|
bond.r1 = 2;
|
|
85
72
|
bond.r2 = 1;
|
|
86
73
|
resMol.addBond(bond);
|
|
@@ -116,29 +103,21 @@ export class Chain {
|
|
|
116
103
|
for (let i = 0; i < linkages.length; i++) {
|
|
117
104
|
const atom1 = resMol.atoms[linkages[i].fMonomer - 1];
|
|
118
105
|
const atom2 = resMol.atoms[linkages[i].sMonomer - 1];
|
|
119
|
-
const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
|
|
106
|
+
const bond = new JSDraw2.Bond<HelmType, IHelmBio>(atom1, atom2);
|
|
120
107
|
bond.r1 = linkages[i].fR;
|
|
121
108
|
bond.r2 = linkages[i].sR;
|
|
122
109
|
resMol.addBond(bond);
|
|
123
110
|
}
|
|
124
111
|
|
|
125
|
-
return new Chain(monomers, linkages, resMol);
|
|
112
|
+
return new Chain(monomers, linkages, resMol, helmHelper);
|
|
126
113
|
}
|
|
127
114
|
|
|
128
115
|
/** Get macromolecule from harmonized sequence (template) */
|
|
129
116
|
applyRules(rules: Rules): Chain {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const resLinkages: Linkage[] = [...this.linkages];
|
|
133
|
-
const resMol: HelmMol = this.mol.clone();
|
|
134
|
-
|
|
135
|
-
throw new Error('not implemented');
|
|
136
|
-
|
|
137
|
-
const chain = new Chain(resMonomers, resLinkages, resMol);
|
|
138
|
-
return chain;
|
|
117
|
+
const newNotation = this.getNotation();
|
|
118
|
+
return Chain.fromNotation(newNotation, rules, this.helmHelper);
|
|
139
119
|
}
|
|
140
120
|
|
|
141
|
-
/** @deprecated Use {@link parseNotation} and {@link applyRules} instead. */
|
|
142
121
|
static fromNotation(sequence: string, rules: Rules, helmHelper: IHelmHelper): Chain {
|
|
143
122
|
const heterodimerCode = rules.heterodimerCode;
|
|
144
123
|
const homodimerCode = rules.homodimerCode;
|
|
@@ -230,14 +209,14 @@ export class Chain {
|
|
|
230
209
|
const ch2 = new Array<string>(monomersCycled.length - allPos2[0]);
|
|
231
210
|
for (let j = 0; j < allPos2[0] - 1; j++) {
|
|
232
211
|
const elem = ch1[j] = monomersCycled[j];
|
|
233
|
-
const bio:
|
|
234
|
-
const atom:
|
|
212
|
+
const bio: PtBio = {type: HelmTypes.AA, i: i, j: j, continuousId: counter};
|
|
213
|
+
const atom: PtAtom = new JSDraw2.Atom<HelmType, PtBio>(p, elem, bio);
|
|
235
214
|
resMol.addAtom(atom);
|
|
236
215
|
|
|
237
216
|
if (j > 0) {
|
|
238
217
|
const atom1 = resMol.atoms[counter - 1];
|
|
239
218
|
const atom2 = resMol.atoms[counter];
|
|
240
|
-
const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
|
|
219
|
+
const bond = new JSDraw2.Bond<HelmType, IHelmBio>(atom1, atom2);
|
|
241
220
|
bond.r1 = 2;
|
|
242
221
|
bond.r2 = 1;
|
|
243
222
|
resMol.addBond(bond);
|
|
@@ -247,14 +226,14 @@ export class Chain {
|
|
|
247
226
|
|
|
248
227
|
for (let j = allPos2[0]; j < monomersCycled.length; j++) {
|
|
249
228
|
const elem = ch2[j - allPos2[0]] = monomersCycled[j];
|
|
250
|
-
const bio:
|
|
251
|
-
const atom:
|
|
229
|
+
const bio: PtBio = {type: HelmTypes.AA, i: i, j: j, continuousId: counter};
|
|
230
|
+
const atom: PtAtom = new JSDraw2.Atom<HelmType, PtBio>(p, elem, bio);
|
|
252
231
|
resMol.addAtom(atom);
|
|
253
232
|
|
|
254
233
|
if (j > allPos2[0]) {
|
|
255
234
|
const atom1 = resMol.atoms[counter - 1];
|
|
256
235
|
const atom2 = resMol.atoms[counter];
|
|
257
|
-
const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
|
|
236
|
+
const bond = new JSDraw2.Bond<HelmType, IHelmBio>(atom1, atom2);
|
|
258
237
|
bond.r1 = 2;
|
|
259
238
|
bond.r2 = 1;
|
|
260
239
|
resMol.addBond(bond);
|
|
@@ -304,14 +283,14 @@ export class Chain {
|
|
|
304
283
|
} else {
|
|
305
284
|
for (let j = 0; j < monomers[i].length; j++) {
|
|
306
285
|
const elem = monomers[i][j];
|
|
307
|
-
const bio:
|
|
308
|
-
const atom:
|
|
286
|
+
const bio: PtBio = {type: HelmTypes.AA, i: i, j: j, continuousId: counter};
|
|
287
|
+
const atom: PtAtom = new JSDraw2.Atom<HelmType, PtBio>(p, elem, bio);
|
|
309
288
|
resMol.addAtom(atom);
|
|
310
289
|
|
|
311
290
|
if (j > 0) {
|
|
312
291
|
const atom1 = resMol.atoms[counter - 1];
|
|
313
292
|
const atom2 = resMol.atoms[counter];
|
|
314
|
-
const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
|
|
293
|
+
const bond = new JSDraw2.Bond<HelmType, IHelmBio>(atom1, atom2);
|
|
315
294
|
bond.r1 = 2;
|
|
316
295
|
bond.r2 = 1;
|
|
317
296
|
resMol.addBond(bond);
|
|
@@ -325,13 +304,13 @@ export class Chain {
|
|
|
325
304
|
for (const l of linkages) {
|
|
326
305
|
const atom1 = resMol.atoms[l.fMonomer - 1];
|
|
327
306
|
const atom2 = resMol.atoms[l.sMonomer - 1];
|
|
328
|
-
const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
|
|
307
|
+
const bond = new JSDraw2.Bond<HelmType, IHelmBio>(atom1, atom2);
|
|
329
308
|
bond.r1 = l.fR;
|
|
330
309
|
bond.r2 = l.sR;
|
|
331
310
|
resMol.addBond(bond);
|
|
332
311
|
}
|
|
333
312
|
|
|
334
|
-
const chain = new Chain(monomersAll, linkages, resMol);
|
|
313
|
+
const chain = new Chain(monomersAll, linkages, resMol, helmHelper);
|
|
335
314
|
return chain;
|
|
336
315
|
}
|
|
337
316
|
|
|
@@ -382,14 +361,14 @@ export class Chain {
|
|
|
382
361
|
for (let j = 0; j < mainFragments[i].length; j++) {
|
|
383
362
|
if (!!mainFragments[i][j]) {
|
|
384
363
|
const elem = mainFragments[i][j];
|
|
385
|
-
const bio:
|
|
386
|
-
const atom = new JSDraw2.Atom<HelmType>(p, elem, bio);
|
|
364
|
+
const bio: PtBio = {type: HelmTypes.AA, i: i, j: j, continuousId: counter};
|
|
365
|
+
const atom = new JSDraw2.Atom<HelmType, IHelmBio>(p, elem, bio);
|
|
387
366
|
resMol.addAtom(atom);
|
|
388
367
|
|
|
389
368
|
if (j !== 0) {
|
|
390
369
|
const atom1 = resMol.atoms[counter - 1];
|
|
391
370
|
const atom2 = resMol.atoms[counter];
|
|
392
|
-
const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
|
|
371
|
+
const bond = new JSDraw2.Bond<HelmType, IHelmBio>(atom1, atom2);
|
|
393
372
|
bond.r1 = 2;
|
|
394
373
|
bond.r2 = 1;
|
|
395
374
|
resMol.addBond(bond);
|
|
@@ -405,13 +384,13 @@ export class Chain {
|
|
|
405
384
|
for (let i = 0; i < linkages.length; i++) {
|
|
406
385
|
const atom1 = resMol.atoms[linkages[i].fMonomer - 1];
|
|
407
386
|
const atom2 = resMol.atoms[linkages[i].sMonomer - 1];
|
|
408
|
-
const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
|
|
387
|
+
const bond = new JSDraw2.Bond<HelmType, IHelmBio>(atom1, atom2);
|
|
409
388
|
bond.r1 = linkages[i].fR;
|
|
410
389
|
bond.r2 = linkages[i].sR;
|
|
411
390
|
resMol.addBond(bond);
|
|
412
391
|
}
|
|
413
392
|
|
|
414
|
-
const chain = new Chain(mainFragments, linkages, resMol);
|
|
393
|
+
const chain = new Chain(mainFragments, linkages, resMol, helmHelper);
|
|
415
394
|
return chain;
|
|
416
395
|
}
|
|
417
396
|
|
|
@@ -648,15 +627,17 @@ export class Chain {
|
|
|
648
627
|
const errors: string[] = [];
|
|
649
628
|
|
|
650
629
|
const chainsMonomerCount = this.monomers.map((ch) => ch.length).reduce((acc, curr) => acc + curr, 0);
|
|
651
|
-
if (this.mol.atoms.length !== chainsMonomerCount)
|
|
630
|
+
if (this.mol.atoms.length !== chainsMonomerCount) {
|
|
652
631
|
errors.push(`The mol atoms count ${this.mol.atoms.length} does not match ` +
|
|
653
632
|
`the total number ${chainsMonomerCount} of chains' monomers.`);
|
|
633
|
+
}
|
|
654
634
|
|
|
655
635
|
const internalBondsCount = this.monomers.map((ch) => ch.length - 1).reduce((acc, curr) => acc + curr, 0);
|
|
656
636
|
const chainsBondCount = internalBondsCount + this.linkages.length;
|
|
657
|
-
if (this.mol.bonds.length !== chainsBondCount)
|
|
637
|
+
if (this.mol.bonds.length !== chainsBondCount) {
|
|
658
638
|
errors.push(`The mol bonds count ${this.mol.bonds.length} does not match ` +
|
|
659
639
|
`the total number ${chainsBondCount} in- and inter-chain linkages.`);
|
|
640
|
+
}
|
|
660
641
|
|
|
661
642
|
let counter: number = 0;
|
|
662
643
|
for (let spIdx = 0; spIdx < this.monomers.length; ++spIdx) {
|
|
@@ -677,188 +658,3 @@ export class Chain {
|
|
|
677
658
|
return errors;
|
|
678
659
|
}
|
|
679
660
|
}
|
|
680
|
-
|
|
681
|
-
/** The main PolyTool convert engine. Returns list of Helms. Covered with tests. */
|
|
682
|
-
export function doPolyToolConvert(sequences: string[], rules: Rules, helmHelper: IHelmHelper): string[] {
|
|
683
|
-
const helms = new Array<string>(sequences.length);
|
|
684
|
-
for (let i = 0; i < sequences.length; i++) {
|
|
685
|
-
try {
|
|
686
|
-
if (sequences[i] == null) { helms[i] = ''; } else {
|
|
687
|
-
const chain = Chain.fromNotation(sequences[i], rules, helmHelper);
|
|
688
|
-
helms[i] = chain.getHelm();
|
|
689
|
-
}
|
|
690
|
-
} catch (err: any) {
|
|
691
|
-
const [errMsg, errStack] = errInfo(err);
|
|
692
|
-
_package.logger.error(errMsg, undefined, errStack);
|
|
693
|
-
helms[i] = '';
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
return helms;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
function getMonomersMolBlocks(monomer1: Monomer, monomer2: Monomer): [string, string] {
|
|
700
|
-
const mb1 = monomer1.molfile;
|
|
701
|
-
let mb2 = monomer2.molfile;
|
|
702
|
-
const addGroups = monomer1.rgroups.length;
|
|
703
|
-
|
|
704
|
-
//mol v2000 monomer
|
|
705
|
-
const rgpIdx = mb2.indexOf('M RGP');
|
|
706
|
-
if (rgpIdx !== -1) {
|
|
707
|
-
const groupsCountStr = mb2.substring(rgpIdx + 6, rgpIdx + 9);
|
|
708
|
-
const groupsCount = Number(groupsCountStr);
|
|
709
|
-
|
|
710
|
-
for (let i = 0; i < groupsCount; i++) {
|
|
711
|
-
const start = rgpIdx + 9 + 4 + i * 8;
|
|
712
|
-
const end = rgpIdx + 9 + 8 + i * 8;
|
|
713
|
-
const rGroupSpecifier = mb2.substring(start, end);
|
|
714
|
-
const groupPosition = Number(rGroupSpecifier) + addGroups;
|
|
715
|
-
const digits = Math.floor(Math.log10(groupPosition) + 1);
|
|
716
|
-
const newSpecifier = ' '.repeat(4 - digits) + String(groupPosition);
|
|
717
|
-
mb2 = mb2.substring(0, start) + newSpecifier + mb2.substring(end, mb2.length);
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
//TODO: same for v3000 monomer
|
|
722
|
-
|
|
723
|
-
return [mb1, mb2];
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
function getSyntheticMolBlock(rdkit: RDModule, reaction: string,
|
|
727
|
-
mb1: string, mb2: string, monomerName: string): string {
|
|
728
|
-
let rxn: RDReaction | null = null;
|
|
729
|
-
let mols: MolList | null = null;
|
|
730
|
-
let mol1: RDMol | null = null;
|
|
731
|
-
let mol2: RDMol | null = null;
|
|
732
|
-
let rctns: RDReactionResult | null = null;
|
|
733
|
-
let molP: RDMol | null = null;
|
|
734
|
-
let molBlock = '';
|
|
735
|
-
|
|
736
|
-
try {
|
|
737
|
-
rxn = rdkit.get_rxn(reaction);
|
|
738
|
-
if (!rxn) throw new InvalidReactionError(reaction);
|
|
739
|
-
mols = new rdkit.MolList();
|
|
740
|
-
mol1 = rdkit.get_mol(mb1!);
|
|
741
|
-
mol2 = rdkit.get_mol(mb2!);
|
|
742
|
-
mols.append(mol1!);
|
|
743
|
-
mols.append(mol2!);
|
|
744
|
-
|
|
745
|
-
rctns = rxn.run_reactants(mols, 1);
|
|
746
|
-
//const size = rctns.size();
|
|
747
|
-
const element = rctns.get(0);
|
|
748
|
-
|
|
749
|
-
molP = element.next();
|
|
750
|
-
molBlock = molP?.get_molblock();//molP?.get_v3Kmolblock();//
|
|
751
|
-
} catch (err: any) {
|
|
752
|
-
const [errMsg, _errStack] = errInfo(err);
|
|
753
|
-
grok.shell.error(`Can not assemble monomer '${monomerName}': ${errMsg}.`);
|
|
754
|
-
throw err;
|
|
755
|
-
} finally {
|
|
756
|
-
rxn?.delete();
|
|
757
|
-
mols?.delete();
|
|
758
|
-
mol1?.delete();
|
|
759
|
-
mol2?.delete();
|
|
760
|
-
rctns?.delete();
|
|
761
|
-
molP?.delete();
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
return molBlock;
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
function getNewGroups(monomer1: Monomer, monomer2: Monomer): RGroup[] {
|
|
768
|
-
const groups = new Array<RGroup>(monomer1?.rgroups.length! + monomer2?.rgroups.length!);
|
|
769
|
-
const length1 = monomer1?.rgroups.length!;
|
|
770
|
-
const length2 = monomer2?.rgroups.length!;
|
|
771
|
-
|
|
772
|
-
for (let i = 0; i < length1; i++)
|
|
773
|
-
groups[i] = monomer1?.rgroups[i]!;
|
|
774
|
-
|
|
775
|
-
for (let i = 0; i < length2; i++) {
|
|
776
|
-
const rGroupSpecifier = monomer2?.rgroups[i]!.label.replace('R', '');
|
|
777
|
-
const groupPosition = Number(rGroupSpecifier) + length1;
|
|
778
|
-
const group: RGroup = {
|
|
779
|
-
//@ts-ignore
|
|
780
|
-
[HELM_RGROUP_FIELDS.CAP_GROUP_SMILES_UPPERCASE]: monomer2?.rgroups[i].capGroupSMILES.replace(rGroupSpecifier, String(groupPosition)),
|
|
781
|
-
[HELM_RGROUP_FIELDS.ALTERNATE_ID]: monomer2?.rgroups[i].alternateId.replace(rGroupSpecifier, String(groupPosition)),
|
|
782
|
-
[HELM_RGROUP_FIELDS.CAP_GROUP_NAME]: monomer2?.rgroups[i].capGroupName,
|
|
783
|
-
[HELM_RGROUP_FIELDS.LABEL]: monomer2?.rgroups[i].label.replace(rGroupSpecifier, String(groupPosition)),
|
|
784
|
-
};
|
|
785
|
-
|
|
786
|
-
groups[i + length1] = group;
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
return groups;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
export function getNewMonomer(rdkit: RDModule, mLib: IMonomerLib, rule: RuleReaction): [string, Monomer] {
|
|
793
|
-
const reacSmarts = rule.reaction;
|
|
794
|
-
const monomerName = rule.name;
|
|
795
|
-
|
|
796
|
-
const monomer1 = mLib.getMonomer('PEPTIDE', rule.firstMonomer);
|
|
797
|
-
if (!monomer1) throw new MonomerNotFoundError('PEPTIDE', rule.firstMonomer);
|
|
798
|
-
const monomer2 = mLib.getMonomer('PEPTIDE', rule.secondMonomer);
|
|
799
|
-
if (!monomer2) throw new MonomerNotFoundError('PEPTIDE', rule.secondMonomer);
|
|
800
|
-
|
|
801
|
-
const [mb1, mb2] = getMonomersMolBlocks(monomer1!, monomer2!);
|
|
802
|
-
const molBlock = getSyntheticMolBlock(rdkit, reacSmarts, mb1, mb2, monomerName);
|
|
803
|
-
const groups: RGroup[] = getNewGroups(monomer1!, monomer2!);
|
|
804
|
-
|
|
805
|
-
const resMonomer: Monomer = {
|
|
806
|
-
[REQ.SYMBOL]: monomerName,
|
|
807
|
-
[REQ.NAME]: monomerName,
|
|
808
|
-
[REQ.MOLFILE]: molBlock,
|
|
809
|
-
[REQ.AUTHOR]: '',
|
|
810
|
-
[REQ.ID]: 0,
|
|
811
|
-
[REQ.RGROUPS]: groups,
|
|
812
|
-
[REQ.SMILES]: '',
|
|
813
|
-
[REQ.POLYMER_TYPE]: 'PEPTIDE',
|
|
814
|
-
[REQ.MONOMER_TYPE]: 'Backbone',
|
|
815
|
-
[REQ.CREATE_DATE]: null,
|
|
816
|
-
|
|
817
|
-
// // @ts-ignore
|
|
818
|
-
// lib: {source: 'Reaction'},
|
|
819
|
-
};
|
|
820
|
-
|
|
821
|
-
resMonomer[OPT.META] = Object.assign(resMonomer[OPT.META] ?? {},
|
|
822
|
-
{'colors': {'default': {line: '#2083D5', text: '#2083D5', background: '#F2F2F5'}}});
|
|
823
|
-
|
|
824
|
-
return [monomerName, resMonomer];
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
export async function getOverriddenLibrary(rules: Rules): Promise<IMonomerLibBase> {
|
|
828
|
-
const monomerLibHelper = await getMonomerLibHelper();
|
|
829
|
-
const systemMonomerLib = monomerLibHelper.getMonomerLib();
|
|
830
|
-
|
|
831
|
-
const rdkit = await getRdKitModule();
|
|
832
|
-
const argLib: { [symbol: string]: Monomer } = {};
|
|
833
|
-
|
|
834
|
-
for (let i = 0; i < rules.reactionRules.length; i++) {
|
|
835
|
-
const [name, monomer] = getNewMonomer(rdkit, systemMonomerLib, rules.reactionRules[i]);
|
|
836
|
-
argLib[name] = monomer;
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
const overrideMonomerLibData: MonomerLibData = {[PolymerTypes.PEPTIDE]: argLib};
|
|
840
|
-
const overriddenMonomerLib = systemMonomerLib.override(overrideMonomerLibData,
|
|
841
|
-
'ST-PT-reactions.' + wu.repeat(1).map(() => Math.floor((Math.random() * 36)).toString(36)).take(4).toArray().join(''));
|
|
842
|
-
return overriddenMonomerLib;
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
/** Gets 0-based in-index (simple polymer) of out-index (continuous) {@link idx} */
|
|
846
|
-
export function getInnerIdx(outIdx: number, monomers: string[][]): [number, number] {
|
|
847
|
-
// let prevSpCount = 0;
|
|
848
|
-
// for (let spI = 0; spI < monomers.length && idx >= (prevSpCount + monomers[spI].length); ++spI)
|
|
849
|
-
// prevSpCount += monomers[spI].length;
|
|
850
|
-
// return idx - prevSpCount;
|
|
851
|
-
let inIdx = outIdx;
|
|
852
|
-
let spIdx: number;
|
|
853
|
-
for (spIdx = 0; spIdx < monomers.length && inIdx >= monomers[spIdx].length; ++spIdx)
|
|
854
|
-
inIdx -= monomers[spIdx].length;
|
|
855
|
-
return [inIdx, spIdx];
|
|
856
|
-
}
|
|
857
|
-
|
|
858
|
-
/** Gets 0-based out-index of 0-based in-index {@link inIdx} monomer of simple polymer {@link spIdx} */
|
|
859
|
-
export function getOuterIdx(inIdx: number, spIdx: number, monomers: string[][]): number {
|
|
860
|
-
let outIdx = 0;
|
|
861
|
-
for (let i = 0; i < spIdx; ++i)
|
|
862
|
-
outIdx += monomers[i].length;
|
|
863
|
-
return outIdx + inIdx;
|
|
864
|
-
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
3
|
+
import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
4
|
+
|
|
5
|
+
import {Rules, RuleReaction} from '../pt-rules';
|
|
6
|
+
import {InvalidReactionError, MonomerNotFoundError} from '../types';
|
|
7
|
+
import {Chain} from './pt-chain';
|
|
8
|
+
|
|
9
|
+
import {_package} from '../../package';
|
|
10
|
+
|
|
11
|
+
/** The main PolyTool convert engine. Returns list of Helms. Covered with tests. */
|
|
12
|
+
export function doPolyToolConvert(sequences: string[], rules: Rules, helmHelper: IHelmHelper): string[] {
|
|
13
|
+
const helms = new Array<string>(sequences.length);
|
|
14
|
+
for (let i = 0; i < sequences.length; i++) {
|
|
15
|
+
try {
|
|
16
|
+
if (sequences[i] == null) { helms[i] = ''; } else {
|
|
17
|
+
const chain = Chain.fromNotation(sequences[i], rules, helmHelper);
|
|
18
|
+
helms[i] = chain.getHelm();
|
|
19
|
+
}
|
|
20
|
+
} catch (err: any) {
|
|
21
|
+
const [errMsg, errStack] = errInfo(err);
|
|
22
|
+
_package.logger.error(errMsg, undefined, errStack);
|
|
23
|
+
helms[i] = '';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return helms;
|
|
27
|
+
}
|