@datagrok/sequence-translator 1.4.3 → 1.4.5

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/detectors.js +24 -0
  3. package/dist/455.js +2 -0
  4. package/dist/455.js.map +1 -0
  5. package/dist/package-test.js +2 -1
  6. package/dist/package-test.js.LICENSE.txt +8 -0
  7. package/dist/package-test.js.map +1 -1
  8. package/dist/package.js +1 -1
  9. package/dist/package.js.map +1 -1
  10. package/files/polytool-rules/rules_example.json +4 -4
  11. package/files/samples/cyclized.csv +3 -2
  12. package/package.json +14 -14
  13. package/src/apps/common/model/oligo-toolkit-package.ts +12 -0
  14. package/src/apps/common/view/components/molecule-img.ts +2 -2
  15. package/src/apps/pattern/model/data-manager.ts +9 -9
  16. package/src/apps/translator/view/ui.ts +8 -8
  17. package/src/package-test.ts +2 -0
  18. package/src/package.ts +30 -4
  19. package/src/polytool/pt-conversion.ts +361 -32
  20. package/src/polytool/pt-dialog.ts +18 -25
  21. package/src/polytool/pt-enumeration-helm-dialog.ts +18 -11
  22. package/src/polytool/pt-enumeration-helm.ts +3 -2
  23. package/src/polytool/pt-unrule-dialog.ts +2 -2
  24. package/src/polytool/pt-unrule.ts +1 -1
  25. package/src/polytool/types.ts +18 -0
  26. package/src/tests/polytool-chain-from-notation-tests.ts +45 -0
  27. package/src/tests/polytool-chain-parse-notation-tests.ts +59 -0
  28. package/src/tests/polytool-detectors-custom-notation-test.ts +43 -0
  29. package/src/tests/toAtomicLevel-tests.ts +26 -1
  30. package/src/tests/utils/detect-macromolecule-utils.ts +64 -0
  31. package/src/tests/{utils.ts → utils/index.ts} +2 -2
  32. package/src/utils/context-menu.ts +0 -3
  33. package/src/utils/cyclized.ts +90 -0
  34. package/src/utils/dimerized.ts +10 -0
@@ -1,29 +1,40 @@
1
- // import * as grok from 'datagrok-api/grok';
2
- // import * as DG from 'datagrok-api/dg';
3
-
4
-
5
- //import {ALIGNMENT, ALPHABET} from '@datagrok-libraries/bio/src/utils/macromolecule';
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
+
7
+ import {HelmTypes, PolymerTypes} from '@datagrok-libraries/bio/src/helm/consts';
8
+ import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
9
+ import {IMonomerLib, IMonomerLibBase, Monomer, MonomerLibData, RGroup} from '@datagrok-libraries/bio/src/types';
10
+ import {RDModule, RDMol, RDReaction, MolList, RDReactionResult} from '@datagrok-libraries/chem-meta/src/rdkit-api';
11
+ import {HELM_REQUIRED_FIELD as REQ, HELM_OPTIONAL_FIELDS as OPT, HELM_RGROUP_FIELDS, HELM_OPTIONAL_FIELDS} from '@datagrok-libraries/bio/src/utils/const';
12
+ import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
13
+ import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
14
+ import {HelmMol, HelmType, JSDraw2ModuleType, OrgType} from '@datagrok-libraries/bio/src/helm/types';
15
+ import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
6
16
 
7
17
  import {Rules, RuleLink, RuleReaction} from './pt-rules';
18
+ import {InvalidReactionError, MonomerNotFoundError} from './types';
19
+
20
+ import {_package} from '../package';
8
21
 
9
- export const RULES_DIMER = '(#2)';
10
- export const RULES_HETERODIMER = '($2)';
22
+ declare const JSDraw2: JSDraw2ModuleType;
23
+ declare const org: OrgType;
11
24
 
12
- // function addCommonTags(col: DG.Column): void {
13
- // col.semType = DG.SEMTYPE.MACROMOLECULE;
14
- // col.setTag('aligned', ALIGNMENT.SEQ);
15
- // col.setTag('alphabet', ALPHABET.PT);
16
- // }
17
25
 
18
26
  export class Chain {
19
27
  linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[];
20
28
  monomers: string[][];
29
+ mol: HelmMol | null;
21
30
 
22
31
  constructor(
23
32
  monomers: string[][],
24
- linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[]) {
33
+ linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[],
34
+ mol: HelmMol | null) {
25
35
  this.linkages = linkages;
26
36
  this.monomers = monomers;
37
+ this.mol = mol;
27
38
  }
28
39
 
29
40
  static fromHelm(helm: string) {
@@ -32,7 +43,14 @@ export class Chain {
32
43
  const rawLinkages = fragmentation[1].split('|');
33
44
 
34
45
  const monomers = new Array<Array<string>>(rawFragments.length);
35
- const linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[] = [];
46
+ const linkages: {
47
+ fChain: number,
48
+ sChain: number,
49
+ fMonomer: number,
50
+ sMonomer: number,
51
+ fR: number,
52
+ sR: number
53
+ }[] = [];
36
54
 
37
55
  //HELM parsing
38
56
  for (let i = 0; i < rawFragments.length; i++) {
@@ -63,7 +81,7 @@ export class Chain {
63
81
  }
64
82
  }
65
83
 
66
- return new Chain(monomers, linkages);
84
+ return new Chain(monomers, linkages, null);
67
85
  }
68
86
 
69
87
  static fromNotation(sequence: string, rules: Rules): Chain {
@@ -71,7 +89,14 @@ export class Chain {
71
89
  const homodimerCode = rules.homodimerCode;
72
90
  const mainFragments: string[] = [];
73
91
 
74
- const linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[] = [];
92
+ const linkages: {
93
+ fChain: number,
94
+ sChain: number,
95
+ fMonomer: number,
96
+ sMonomer: number,
97
+ fR: number,
98
+ sR: number
99
+ }[] = [];
75
100
 
76
101
  //NOTICE: this works only with simple single heterodimers
77
102
  const heterodimeric = heterodimerCode !== null ? sequence.split(`(${rules.heterodimerCode!})`) : '';
@@ -201,7 +226,97 @@ export class Chain {
201
226
  }
202
227
  }
203
228
 
204
- const chain = new Chain(monomersAll, linkages);
229
+ const chain = new Chain(monomersAll, linkages, null);
230
+ return chain;
231
+ }
232
+
233
+ static async parseNotation(sequence: string): Promise<Chain> {
234
+ const mainFragments: string[][] = [];
235
+
236
+ const linkages: {
237
+ fChain: number,
238
+ sChain: number,
239
+ fMonomer: number,
240
+ sMonomer: number,
241
+ fR: number,
242
+ sR: number
243
+ }[] = [];
244
+
245
+
246
+ const hh = await getHelmHelper();
247
+ // const sampleHwe = hh.createHelmWebEditor();
248
+ // sampleHwe.editor.setHelm('PEPTIDE1{R.P.D.[meI]}$$$$');
249
+
250
+ const resHwe = hh.createHelmWebEditor();
251
+ const resMol = resHwe.editor.m;
252
+
253
+ const rxp = /(\(.\d+\))?\{[^\}]*\}/g;
254
+ const seqs: string [] = [];
255
+ seqs.push(sequence.replaceAll(rxp, ''));
256
+
257
+ //const l = (rxpRes?.length) ?? -1;
258
+
259
+ const matches = sequence.matchAll(rxp);
260
+ //const rxpRes = rxp.exec(sequence);
261
+ for (const m of matches) {
262
+ const str = m![0];
263
+ if (str)
264
+ seqs.push(str);
265
+ }
266
+
267
+ let counter = 0;
268
+ for (let i = 0; i < seqs.length; i++) {
269
+ const splMonomers = seqs[i].split('-');
270
+ const monomers: string [] = new Array<string>(splMonomers.length);
271
+ for (let j = 0; j < splMonomers.length; j++) {
272
+ const monomer = splMonomers[j].replace('{', '').replace('}', '');
273
+ if (monomer !== '') {
274
+ monomers[j] = monomer;
275
+ counter++;
276
+ } else {
277
+ linkages.push({fChain: i, sChain: i + 1, fMonomer: counter, sMonomer: counter + 1, fR: 1, sR: 1});
278
+ }
279
+ }
280
+
281
+ mainFragments.push(monomers);
282
+ }
283
+
284
+ counter = 0;
285
+ const p = new JSDraw2.Point(0, 0);
286
+ for (let i = 0; i < mainFragments.length; i++) {
287
+ for (let j = 0; j < mainFragments[i].length; j++) {
288
+ if (!!mainFragments[i][j]) {
289
+ const elem = mainFragments[i][j];
290
+ const bio = {type: HelmTypes.AA, i: i, j: j};
291
+ const atom = new JSDraw2.Atom<HelmType>(p, elem, bio);
292
+ resMol.addAtom(atom);
293
+
294
+ if (j !== 0) {
295
+ const atom1 = resMol.atoms[counter - 1];
296
+ const atom2 = resMol.atoms[counter];
297
+ const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
298
+ bond.r1 = 2;
299
+ bond.r2 = 1;
300
+ resMol.addBond(bond);
301
+ }
302
+
303
+ counter++;
304
+ p.x += JSDraw2.Editor.BONDLENGTH; // Inspired by HELMWebEditor
305
+ }
306
+ p.y += 4 * JSDraw2.Editor.BONDLENGTH; // Inspired by HELMWebEditor
307
+ }
308
+ }
309
+
310
+ for (let i = 0; i < linkages.length; i++) {
311
+ const atom1 = resMol.atoms[linkages[i].fMonomer - 1];
312
+ const atom2 = resMol.atoms[linkages[i].sMonomer - 1];
313
+ const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
314
+ bond.r1 = linkages[i].fR;
315
+ bond.r2 = linkages[i].sR;
316
+ resMol.addBond(bond);
317
+ }
318
+
319
+ const chain = new Chain(mainFragments, linkages, resMol);
205
320
  return chain;
206
321
  }
207
322
 
@@ -211,17 +326,17 @@ export class Chain {
211
326
  let idx1 = 0;
212
327
  let idx2 = 0;
213
328
  loop1:
214
- for (let i = 0; i < this.monomers.length; i++) {
215
- loop2:
216
- for (let j = 0; j < this.monomers[i].length; j++) {
217
- if (counter == changeNumber) {
218
- idx1 = i;
219
- idx2 = j;
220
- break loop1;
221
- }
222
- counter++;
223
- }
329
+ for (let i = 0; i < this.monomers.length; i++) {
330
+ loop2:
331
+ for (let j = 0; j < this.monomers[i].length; j++) {
332
+ if (counter == changeNumber) {
333
+ idx1 = i;
334
+ idx2 = j;
335
+ break loop1;
336
+ }
337
+ counter++;
224
338
  }
339
+ }
225
340
 
226
341
  const previous = this.monomers[idx1][idx2];
227
342
 
@@ -232,6 +347,10 @@ export class Chain {
232
347
  return res;
233
348
  }
234
349
 
350
+ getNotationHelm(): string {
351
+ return this.getHelm();
352
+ }
353
+
235
354
  getHelm(): string {
236
355
  let helm = '';
237
356
  for (let i = 0; i < this.monomers.length; i++) {
@@ -263,8 +382,66 @@ export class Chain {
263
382
  return helm;
264
383
  }
265
384
 
266
- getNotation(rules: Rules): string {
267
- return 'not implemented';
385
+ getNotation(): string {
386
+ const atoms = this.mol!.atoms;
387
+ const bonds = this.mol!.bonds;
388
+ const chains: number[] = [];
389
+ const specialBonds: number[] = [];
390
+ for (let i = 0; i < bonds.length!; i++) {
391
+ //@ts-ignore
392
+ if (bonds[i].a1.bio.i !== bonds[i].a2.bio.i)
393
+ specialBonds.push(i);
394
+ }
395
+
396
+ for (let i = 0; i < atoms.length!; i++) {
397
+ //@ts-ignore
398
+ const atomChain = atoms[i].bio?.i;
399
+ if (atomChain + 1 > chains.length)
400
+ chains.push(1);
401
+ else
402
+ chains[atomChain]++;
403
+ }
404
+
405
+ const simpleChains: string[][] = new Array(chains.length);
406
+ let counter = 0;
407
+ for (let i = 0; i < chains.length!; i++) {
408
+ const simpleChain: string[] = new Array(chains[i]);
409
+ for (let j = 0; j < chains[i]; j++) {
410
+ simpleChain[j] = atoms[counter].elem;
411
+ counter++;
412
+ }
413
+
414
+ simpleChains[i] = simpleChain;
415
+ }
416
+
417
+ let res = '';
418
+ for (let i = 0; i < simpleChains.length; i++) {
419
+ let chainAdd = '';
420
+
421
+ for (let j = 0; j < simpleChains[i].length; j++)
422
+ chainAdd += `${j == 0 ? '' : '-'}${simpleChains[i][j]}`;
423
+
424
+ if (i !== 0) {
425
+ const rxp = /(\(.\d+\))/;
426
+ const match = chainAdd.match(rxp);
427
+ chainAdd = chainAdd.replace(match?.[0]!, '');
428
+ const group = match ? match?.[0]! : '';
429
+ chainAdd = `${group}{${chainAdd}}`;
430
+ } else {
431
+ if (simpleChains.length > 1) {
432
+ //@ts-ignore
433
+ const firstAtomLinks = bonds[specialBonds[0]].a1.bio.i == 0 && bonds[specialBonds[0]].a1.bio.j == 0;
434
+ //@ts-ignore
435
+ const secondAtomLinks = bonds[specialBonds[0]].a2.bio.i == 1 && bonds[specialBonds[0]].a1.bio.j == 0;
436
+ if (firstAtomLinks && secondAtomLinks)
437
+ chainAdd += '-';
438
+ }
439
+ }
440
+
441
+ res += chainAdd;
442
+ }
443
+
444
+ return res;
268
445
  }
269
446
 
270
447
  protected static getLinkedPositions(monomers: string[], rules: RuleLink[] | RuleReaction []):
@@ -374,10 +551,162 @@ export class Chain {
374
551
  export function doPolyToolConvert(sequences: string[], rules: Rules): string[] {
375
552
  const helms = new Array<string>(sequences.length);
376
553
  for (let i = 0; i < sequences.length; i++) {
377
- if (sequences[i] == null) { helms[i] = ''; } else {
378
- const chain = Chain.fromNotation(sequences[i], rules);
379
- helms[i] = chain.getHelm();
554
+ try {
555
+ if (sequences[i] == null) { helms[i] = ''; } else {
556
+ const chain = Chain.fromNotation(sequences[i], rules);
557
+ helms[i] = chain.getHelm();
558
+ }
559
+ } catch (err: any) {
560
+ const [errMsg, errStack] = errInfo(err);
561
+ _package.logger.error(errMsg, undefined, errStack);
562
+ helms[i] = '';
380
563
  }
381
564
  }
382
565
  return helms;
383
566
  }
567
+
568
+ function getMonomersMolBlocks(monomer1: Monomer, monomer2: Monomer): [string, string] {
569
+ const mb1 = monomer1.molfile;
570
+ let mb2 = monomer2.molfile;
571
+ const addGroups = monomer1.rgroups.length;
572
+
573
+ //mol v2000 monomer
574
+ const rgpIdx = mb2.indexOf('M RGP');
575
+ if (rgpIdx !== -1) {
576
+ const groupsCountStr = mb2.substring(rgpIdx + 6, rgpIdx + 9);
577
+ const groupsCount = Number(groupsCountStr);
578
+
579
+ for (let i = 0; i < groupsCount; i++) {
580
+ const start = rgpIdx + 9 + 4 + i * 8;
581
+ const end = rgpIdx + 9 + 8 + i * 8;
582
+ const rGroupSpecifier = mb2.substring(start, end);
583
+ const groupPosition = Number(rGroupSpecifier) + addGroups;
584
+ const digits = Math.floor(Math.log10(groupPosition) + 1);
585
+ const newSpecifier = ' '.repeat(4 - digits) + String(groupPosition);
586
+ mb2 = mb2.substring(0, start) + newSpecifier + mb2.substring(end, mb2.length);
587
+ }
588
+ }
589
+
590
+ //TODO: same for v3000 monomer
591
+
592
+ return [mb1, mb2];
593
+ }
594
+
595
+ function getSyntheticMolBlock(rdkit: RDModule, reaction: string,
596
+ mb1: string, mb2: string, monomerName: string): string {
597
+ let rxn: RDReaction | null = null;
598
+ let mols: MolList | null = null;
599
+ let mol1: RDMol | null = null;
600
+ let mol2: RDMol | null = null;
601
+ let rctns: RDReactionResult | null = null;
602
+ let molP: RDMol | null = null;
603
+ let molBlock = '';
604
+
605
+ try {
606
+ rxn = rdkit.get_rxn(reaction);
607
+ if (!rxn) throw new InvalidReactionError(reaction);
608
+ mols = new rdkit.MolList();
609
+ mol1 = rdkit.get_mol(mb1!);
610
+ mol2 = rdkit.get_mol(mb2!);
611
+ mols.append(mol1!);
612
+ mols.append(mol2!);
613
+
614
+ rctns = rxn.run_reactants(mols, 1);
615
+ //const size = rctns.size();
616
+ const element = rctns.get(0);
617
+
618
+ molP = element.next();
619
+ molBlock = molP?.get_molblock();//molP?.get_v3Kmolblock();//
620
+ } catch (err: any) {
621
+ const [errMsg, _errStack] = errInfo(err);
622
+ grok.shell.error(`Can not assemble monomer '${monomerName}': ${errMsg}.`);
623
+ throw err;
624
+ } finally {
625
+ rxn?.delete();
626
+ mols?.delete();
627
+ mol1?.delete();
628
+ mol2?.delete();
629
+ rctns?.delete();
630
+ molP?.delete();
631
+ }
632
+
633
+ return molBlock;
634
+ }
635
+
636
+ function getNewGroups(monomer1: Monomer, monomer2: Monomer): RGroup[] {
637
+ const groups = new Array<RGroup>(monomer1?.rgroups.length! + monomer2?.rgroups.length!);
638
+ const length1 = monomer1?.rgroups.length!;
639
+ const length2 = monomer2?.rgroups.length!;
640
+
641
+ for (let i = 0; i < length1; i++)
642
+ groups[i] = monomer1?.rgroups[i]!;
643
+
644
+ for (let i = 0; i < length2; i++) {
645
+ const rGroupSpecifier = monomer2?.rgroups[i]!.label.replace('R', '');
646
+ const groupPosition = Number(rGroupSpecifier) + length1;
647
+ const group: RGroup = {
648
+ //@ts-ignore
649
+ [HELM_RGROUP_FIELDS.CAP_GROUP_SMILES_UPPERCASE]: monomer2?.rgroups[i].capGroupSMILES.replace(rGroupSpecifier, String(groupPosition)),
650
+ [HELM_RGROUP_FIELDS.ALTERNATE_ID]: monomer2?.rgroups[i].alternateId.replace(rGroupSpecifier, String(groupPosition)),
651
+ [HELM_RGROUP_FIELDS.CAP_GROUP_NAME]: monomer2?.rgroups[i].capGroupName,
652
+ [HELM_RGROUP_FIELDS.LABEL]: monomer2?.rgroups[i].label.replace(rGroupSpecifier, String(groupPosition)),
653
+ };
654
+
655
+ groups[i + length1] = group;
656
+ }
657
+
658
+ return groups;
659
+ }
660
+
661
+ export function getNewMonomer(rdkit: RDModule, mLib: IMonomerLib, rule: RuleReaction): [string, Monomer] {
662
+ const reacSmarts = rule.reaction;
663
+ const monomerName = rule.name;
664
+
665
+ const monomer1 = mLib.getMonomer('PEPTIDE', rule.firstMonomer);
666
+ if (!monomer1) throw new MonomerNotFoundError('PEPTIDE', rule.firstMonomer);
667
+ const monomer2 = mLib.getMonomer('PEPTIDE', rule.secondMonomer);
668
+ if (!monomer2) throw new MonomerNotFoundError('PEPTIDE', rule.secondMonomer);
669
+
670
+ const [mb1, mb2] = getMonomersMolBlocks(monomer1!, monomer2!);
671
+ const molBlock = getSyntheticMolBlock(rdkit, reacSmarts, mb1, mb2, monomerName);
672
+ const groups: RGroup[] = getNewGroups(monomer1!, monomer2!);
673
+
674
+ const resMonomer: Monomer = {
675
+ [REQ.SYMBOL]: monomerName,
676
+ [REQ.NAME]: monomerName,
677
+ [REQ.MOLFILE]: molBlock,
678
+ [REQ.AUTHOR]: '',
679
+ [REQ.ID]: 0,
680
+ [REQ.RGROUPS]: groups,
681
+ [REQ.SMILES]: '',
682
+ [REQ.POLYMER_TYPE]: 'PEPTIDE',
683
+ [REQ.MONOMER_TYPE]: 'Backbone',
684
+ [REQ.CREATE_DATE]: null,
685
+
686
+ // // @ts-ignore
687
+ // lib: {source: 'Reaction'},
688
+ };
689
+
690
+ resMonomer[OPT.META] = Object.assign(resMonomer[OPT.META] ?? {},
691
+ {'colors': {'default': {line: '#2083D5', text: '#2083D5', background: '#F2F2F5'}}});
692
+
693
+ return [monomerName, resMonomer];
694
+ }
695
+
696
+ export async function getOverriddenLibrary(rules: Rules): Promise<IMonomerLibBase> {
697
+ const monomerLibHelper = await getMonomerLibHelper();
698
+ const systemMonomerLib = monomerLibHelper.getMonomerLib();
699
+
700
+ const rdkit = await getRdKitModule();
701
+ const argLib: { [symbol: string]: Monomer } = {};
702
+
703
+ for (let i = 0; i < rules.reactionRules.length; i++) {
704
+ const [name, monomer] = getNewMonomer(rdkit, systemMonomerLib, rules.reactionRules[i]);
705
+ argLib[name] = monomer;
706
+ }
707
+
708
+ const overrideMonomerLibData: MonomerLibData = {[PolymerTypes.PEPTIDE]: argLib};
709
+ const overriddenMonomerLib = systemMonomerLib.override(overrideMonomerLibData,
710
+ 'ST-PT-reactions.' + wu.repeat(1).map(() => Math.floor((Math.random() * 36)).toString(36)).take(4).toArray().join(''));
711
+ return overriddenMonomerLib;
712
+ }
@@ -9,10 +9,13 @@ import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
9
9
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
10
10
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
11
11
  import {getSeqHelper, ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
12
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
12
+ import {MmcrTemps} from '@datagrok-libraries/bio/src/utils/cell-renderer-consts';
13
+ import {buildMonomerHoverLink} from '@datagrok-libraries/bio/src/monomer-works/monomer-hover';
14
+ import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
15
+ import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
13
16
 
14
- import {getRules, RuleInputs, RULES_PATH, RULES_STORAGE_NAME} from './pt-rules';
15
- import {doPolyToolConvert} from './pt-conversion';
17
+ import {getRules, RuleInputs, Rules, RULES_PATH, RULES_STORAGE_NAME} from './pt-rules';
18
+ import {doPolyToolConvert, getOverriddenLibrary} from './pt-conversion';
16
19
  import {defaultErrorHandler} from '../utils/err-info';
17
20
  import {getLibrariesList} from './utils';
18
21
  import {getEnumerationChem, PT_CHEM_EXAMPLE} from './pt-enumeration-chem';
@@ -74,7 +77,7 @@ export async function getPolyToolConvertDialog(srcCol?: DG.Column): Promise<DG.D
74
77
  table: srcColVal.dataFrame, value: srcColVal,
75
78
  filter: (col: DG.Column) => {
76
79
  if (col.semType !== DG.SEMTYPE.MACROMOLECULE) return false;
77
- const sh = SeqHandler.forColumn(col);
80
+ const sh = _package.seqHelper.getSeqHandler(col);
78
81
  return sh.notation === NOTATION.CUSTOM;
79
82
  }
80
83
  });
@@ -85,7 +88,7 @@ export async function getPolyToolConvertDialog(srcCol?: DG.Column): Promise<DG.D
85
88
  const chiralityEngineInput = ui.input.bool(PT_UI_USE_CHIRALITY, {value: false});
86
89
  let ruleFileList: string[];
87
90
  const ruleInputs = new RuleInputs(RULES_PATH, RULES_STORAGE_NAME, '.json', {
88
- onValueChanged: (value: string[]) => { ruleFileList = value;}
91
+ onValueChanged: (value: string[]) => { ruleFileList = value; }
89
92
  });
90
93
  const rulesHeader = ui.inlineText([PT_UI_RULES_USED]);
91
94
  ui.tooltip.bind(rulesHeader, 'Add or specify rules to use');
@@ -256,34 +259,24 @@ export async function polyToolConvert(
256
259
  if (generateHelm && table) table.columns.add(resHelmCol, true);
257
260
 
258
261
  const seqHelper: ISeqHelper = await getSeqHelper();
259
- const toAtomicLevelRes = await seqHelper.helmToAtomicLevel(resHelmCol, chiralityEngine, /* highlight */ generateHelm);
262
+ const rdKitModule: RDModule = await getRdKitModule();
263
+ const lib = await getOverriddenLibrary(rules);
264
+ const resHelmColTemp = resHelmCol.temp;
265
+ resHelmColTemp[MmcrTemps.overriddenLibrary] = lib;
266
+ resHelmCol.temp = resHelmColTemp;
267
+ const toAtomicLevelRes =
268
+ await seqHelper.helmToAtomicLevel(resHelmCol, chiralityEngine, /* highlight */ generateHelm, lib);
260
269
  const resMolCol = toAtomicLevelRes.molCol!;
261
270
 
262
- // const rdkit = await grok.functions.call('Chem:getRdKitModule');
263
- // for (let i = 0; i < rules.reactionRules.length; i++) {
264
- // const reacSmarts = rules.reactionRules[i].reaction;
265
- // const rxn = rdkit.get_rxn(reacSmarts);
266
-
267
- // for (let j = 0; j < resMolCol.length; j++) {
268
- // const mols = new rdkit.MolList();
269
- // const mol = rdkit.get_mol(resMolCol.get(j));
270
- // mols.append(mol!);
271
- // const rctns = rxn.run_reactants(mols, 1);
272
- // const size = rctns.size();
273
- // const element = rctns.get(0);
274
- // let molP: RDMol | null = null;
275
- // molP = element.next();
276
- // const molBlock = molP?.get_v3Kmolblock();
277
- // resMolCol.set(j, molBlock!);
278
- // }
279
- // }
280
-
281
271
  resMolCol.name = getUnusedName(table, `molfile(${seqCol.name})`);
282
272
  resMolCol.semType = DG.SEMTYPE.MOLECULE;
283
273
  if (table) {
284
274
  table.columns.add(resMolCol, true);
285
275
  await grok.data.detectSemanticTypes(table);
286
276
  }
277
+
278
+ buildMonomerHoverLink(resHelmCol, resMolCol, lib, seqHelper, rdKitModule);
279
+
287
280
  return [resHelmCol, resMolCol];
288
281
  } finally {
289
282
  pi.close();
@@ -16,7 +16,6 @@ import {getSeqHelper, ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-he
16
16
  import '@datagrok-libraries/bio/src/types/input';
17
17
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
18
18
  import {InputColumnBase} from '@datagrok-libraries/bio/src/types/input';
19
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
20
19
 
21
20
  import {
22
21
  PolyToolEnumeratorParams, PolyToolEnumeratorType, PolyToolEnumeratorTypes
@@ -36,8 +35,9 @@ type PolyToolEnumerateInputs = {
36
35
  placeholdersBreadth: PolyToolPlaceholdersBreadthInput;
37
36
  enumeratorType: DG.ChoiceInput<PolyToolEnumeratorType>
38
37
  trivialNameCol: InputColumnBase,
39
- toAtomicLevel: DG.InputBase<boolean>;
40
38
  keepOriginal: DG.InputBase<boolean>;
39
+ toAtomicLevel: DG.InputBase<boolean>;
40
+ toHarmonizedSequence: DG.InputBase<boolean>;
41
41
  };
42
42
 
43
43
  type PolyToolEnumerateHelmSerialized = {
@@ -46,8 +46,9 @@ type PolyToolEnumerateHelmSerialized = {
46
46
  placeholdersBreadth: string;
47
47
  enumeratorType: PolyToolEnumeratorType;
48
48
  trivialNameCol: string;
49
- toAtomicLevel: boolean;
50
49
  keepOriginal: boolean;
50
+ toAtomicLevel: boolean;
51
+ toHarmonizedSequence: boolean;
51
52
  };
52
53
 
53
54
  export async function polyToolEnumerateHelmUI(cell?: DG.Cell): Promise<void> {
@@ -160,10 +161,12 @@ async function getPolyToolEnumerateDialog(
160
161
  showRowHeader: false,
161
162
  showCellTooltip: false,
162
163
  }),
163
- toAtomicLevel: ui.input.bool(
164
- 'To atomic level', {value: false}),
165
164
  keepOriginal: ui.input.bool(
166
165
  'Keep original', {value: false}),
166
+ toAtomicLevel: ui.input.bool(
167
+ 'To atomic level', {value: false}),
168
+ toHarmonizedSequence: ui.input.bool(
169
+ 'To harmonized sequence', {value: false}),
167
170
  trivialNameCol: ui.input.column2(
168
171
  'Trivial name', {
169
172
  table: cell?.dataFrame,
@@ -184,6 +187,7 @@ async function getPolyToolEnumerateDialog(
184
187
  }),
185
188
  };
186
189
 
190
+ inputs.toHarmonizedSequence.root.style.display = 'none';
187
191
  inputs.trivialNameCol.addOptions(trivialNameSampleDiv);
188
192
 
189
193
  let placeholdersValidity: string | null = null;
@@ -363,8 +367,9 @@ async function getPolyToolEnumerateDialog(
363
367
  let helmValue: string;
364
368
  let table: DG.DataFrame | undefined = undefined;
365
369
  if (cell && cell.rowIndex >= 0 && cell?.column.semType == DG.SEMTYPE.MACROMOLECULE) {
366
- const sh = SeqHandler.forColumn(cell.column);
367
- helmValue = await sh.getHelm(cell.rowIndex);
370
+ const sh = _package.seqHelper.getSeqHandler(cell.column);
371
+ const helmSemValue = await sh.getHelm(cell.rowIndex);
372
+ helmValue = helmSemValue.value;
368
373
  table = cell.dataFrame;
369
374
  } else {
370
375
  helmValue = PT_HELM_EXAMPLE;
@@ -414,8 +419,8 @@ async function getPolyToolEnumerateDialog(
414
419
  .add(inputs.enumeratorType)
415
420
  .add(inputs.placeholdersBreadth)
416
421
  .add(inputs.trivialNameCol)
417
- .add(inputs.toAtomicLevel)
418
- .add(inputs.keepOriginal)
422
+ .add(ui.divH([inputs.keepOriginal.root, inputs.toAtomicLevel.root, inputs.toHarmonizedSequence.root],
423
+ {style: {width: '100%'}}))
419
424
  .add(warningsTextDiv)
420
425
  // .addButton('Enumerate', () => {
421
426
  // execDialog()
@@ -433,8 +438,9 @@ async function getPolyToolEnumerateDialog(
433
438
  enumeratorType: inputs.enumeratorType.value,
434
439
  placeholdersBreadth: inputs.placeholdersBreadth.stringValue,
435
440
  trivialNameCol: inputs.trivialNameCol.stringValue,
436
- toAtomicLevel: inputs.toAtomicLevel.value,
437
441
  keepOriginal: inputs.keepOriginal.value,
442
+ toAtomicLevel: inputs.toAtomicLevel.value,
443
+ toHarmonizedSequence: inputs.toHarmonizedSequence.value,
438
444
  };
439
445
  },
440
446
  /* applyInput */ (x: PolyToolEnumerateHelmSerialized): void => {
@@ -443,8 +449,9 @@ async function getPolyToolEnumerateDialog(
443
449
  inputs.enumeratorType.value = x.enumeratorType;
444
450
  inputs.placeholdersBreadth.stringValue = x.placeholdersBreadth;
445
451
  inputs.trivialNameCol.stringValue = x.trivialNameCol;
446
- inputs.toAtomicLevel.value = x.toAtomicLevel;
447
452
  inputs.keepOriginal.value = x.keepOriginal;
453
+ inputs.toAtomicLevel.value = x.toAtomicLevel;
454
+ inputs.toHarmonizedSequence.value = x.toHarmonizedSequence;
448
455
  });
449
456
  return dialog;
450
457
  } catch (err: any) {
@@ -4,7 +4,8 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {
6
6
  HelmType, HelmMol,
7
- JSDraw2ModuleType, OrgType
7
+ JSDraw2ModuleType, OrgType,
8
+ IHelmEditorOptions
8
9
  } from '@datagrok-libraries/bio/src/helm/types';
9
10
 
10
11
 
@@ -72,7 +73,7 @@ function getPtEnumeratorBreadth(m: HelmMol, placeholdersBreadth: PolyToolPlaceho
72
73
  export function doPolyToolEnumerateHelm(
73
74
  helm: string, id: string, params: PolyToolEnumeratorParams
74
75
  ): [ /* helm */ string, /* id */ string][] {
75
- const molHandler = new JSDraw2.MolHandler<HelmType>();
76
+ const molHandler = new JSDraw2.MolHandler<HelmType, IHelmEditorOptions>();
76
77
  const plugin = new org.helm.webeditor.Plugin(molHandler);
77
78
  org.helm.webeditor.IO.parseHelm(plugin, helm, new JSDraw2.Point(0, 0), undefined);
78
79
  const m = molHandler.m;
@@ -4,7 +4,6 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {Unsubscribable} from 'rxjs';
6
6
 
7
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
8
7
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
9
8
  import {getUnusedColName} from '@datagrok-libraries/bio/src/monomer-works/utils';
10
9
 
@@ -12,6 +11,7 @@ import {defaultErrorHandler} from '../utils/err-info';
12
11
  import {doPolyToolUnrule} from './pt-unrule';
13
12
  import {getRules, RuleInputs, RULES_PATH, RULES_STORAGE_NAME} from './pt-rules';
14
13
  import {PT_ERROR_DATAFRAME, PT_UI_DIALOG_UNRULE, PT_UI_RULES_USED} from './const';
14
+ import {_package} from '../package';
15
15
 
16
16
  type PolyToolUnruleSerialized = {
17
17
  rules: string[];
@@ -34,7 +34,7 @@ export async function getPolyToolUnruleDialog(srcCol?: DG.Column<string>): Promi
34
34
  table: srcColVal.dataFrame, value: srcColVal,
35
35
  filter: (col: DG.Column) => {
36
36
  if (col.semType !== DG.SEMTYPE.MACROMOLECULE) return false;
37
- const sh = SeqHandler.forColumn(col);
37
+ const sh = _package.seqHelper.getSeqHandler(col);
38
38
  return sh.notation === NOTATION.HELM;
39
39
  }
40
40
  });