@datagrok/sequence-translator 1.4.7 → 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/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@datagrok/sequence-translator",
3
3
  "friendlyName": "Sequence Translator",
4
- "version": "1.4.7",
4
+ "version": "1.4.10",
5
5
  "author": {
6
- "name": "Alexey Chopovsky",
7
- "email": "achopovsky@datagrok.ai"
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.5",
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.6",
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.12",
43
- "@datagrok-libraries/js-draw-lite": "^0.0.9",
44
- "@datagrok/bio": "^2.16.6",
45
- "@datagrok/helm": "^2.5.7",
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
- private _seqHelper: ISeqHelper;
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
- if (!this._seqHelper)
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(seqHelper: ISeqHelper): void {
64
- this._seqHelper = seqHelper;
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-enumeration-helm-dialog';
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 [seqHelper] = await Promise.all([
45
- getSeqHelper(),
45
+ const [helmHelper] = await Promise.all([
46
+ getHelmHelper(),
46
47
  ]);
47
- _package.completeInit(seqHelper);
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.seqHelper);
306
+ col.temp[SeqTemps.notationProvider] = new CyclizedNotationProvider(separator, _package.helmHelper);
306
307
  }
@@ -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 * as grok from 'datagrok-api/grok';
2
- import * as ui from 'datagrok-api/ui';
3
- import * as DG from 'datagrok-api/dg';
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 {_package} from '../package';
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 PolyToolBio = HelmBio & { i: number, j: number };
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
- linkages: Linkage[],
45
- mol: HelmMol) {
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: PolyToolBio = {type: HelmTypes.AA, i: i, j: j, continuousId: counter};
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
- // Clone this
131
- const resMonomers: string[][] = this.monomers.map((mL) => [...mL]);
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: PolyToolBio = {type: HelmTypes.AA, i: i, j: j, continuousId: counter};
234
- const atom: HelmAtom = new JSDraw2.Atom<HelmType>(p, elem, bio);
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: PolyToolBio = {type: HelmTypes.AA, i: i, j: j, continuousId: counter};
251
- const atom: HelmAtom = new JSDraw2.Atom<HelmType>(p, elem, bio);
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: PolyToolBio = {type: HelmTypes.AA, i: i, j: j, continuousId: counter};
308
- const atom: HelmAtom = new JSDraw2.Atom<HelmType>(p, elem, bio);
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: PolyToolBio = {type: HelmTypes.AA, i: i, j: j, continuousId: counter};
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
+ }