@datagrok/helm 2.2.1 → 2.3.0

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 (46) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/package-test.js +1 -1
  3. package/dist/package-test.js.map +1 -1
  4. package/dist/package.js +1 -1
  5. package/dist/package.js.map +1 -1
  6. package/package.json +9 -10
  7. package/src/cell-renderer.ts +8 -33
  8. package/src/helm-helper.ts +67 -17
  9. package/src/helm-monomer-placer.ts +7 -9
  10. package/src/helm-web-editor.ts +33 -3
  11. package/src/package-test.ts +8 -3
  12. package/src/package-utils.ts +69 -42
  13. package/src/package.ts +121 -141
  14. package/src/tests/findMonomers-tests.ts +2 -0
  15. package/src/tests/get-all-parts-tests.ts +5 -0
  16. package/src/tests/get-molfiles-tests.ts +3 -1
  17. package/src/tests/get-monomer-tests.ts +88 -19
  18. package/src/tests/helm-service-tests.ts +4 -0
  19. package/src/tests/helm-tests.ts +7 -1
  20. package/src/tests/helm-web-editor-tests.ts +55 -0
  21. package/src/tests/parse-helm-tests.ts +98 -0
  22. package/src/tests/properties-widget-tests.ts +33 -4
  23. package/src/tests/renderers-tests.ts +3 -1
  24. package/src/tests/utils.ts +6 -0
  25. package/src/types/index.ts +5 -0
  26. package/src/utils/get-hovered.ts +3 -4
  27. package/src/utils/{dummy-monomer.ts → get-monomer-dummy.ts} +10 -45
  28. package/src/utils/get-monomer-of-library.ts +90 -0
  29. package/src/utils/get-monomer.ts +23 -21
  30. package/src/utils/helm-grid-cell-renderer.ts +9 -2
  31. package/src/utils/helm-service.ts +6 -5
  32. package/src/utils/index.ts +11 -17
  33. package/src/widgets/properties-widget.ts +29 -9
  34. package/tsconfig.json +1 -1
  35. package/vendor/helm-web-editor.development.js +39640 -0
  36. package/vendor/helm-web-editor.production.js +2 -0
  37. package/vendor/helm-web-editor.production.js.map +1 -0
  38. package/webpack.config.js +14 -11
  39. package/helm/JSDraw/Pistoia.HELM-uncompressed.js +0 -9694
  40. package/helm/JSDraw/Pistoia.HELM.js +0 -27
  41. package/helm/JSDraw/ReadMe.txt +0 -8
  42. package/helm/JSDraw/Scilligence.JSDraw2.Lite-uncompressed.js +0 -31126
  43. package/helm/JSDraw/Scilligence.JSDraw2.Lite.js +0 -12
  44. package/helm/JSDraw/Scilligence.JSDraw2.Resources.js +0 -762
  45. package/helm/JSDraw/dojo.js +0 -250
  46. package/helm/JSDraw/test.html +0 -24
@@ -0,0 +1,55 @@
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 {after, before, category, delay, expect, test, expectArray} from '@datagrok-libraries/utils/src/test';
6
+ import {IHelmHelper, getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
7
+ import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
8
+ import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
9
+ import {
10
+ getUserLibSettings, setUserLibSettings, setUserLibSettingsForTests
11
+ } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
12
+
13
+ import {initHelmMainPackage} from './utils';
14
+
15
+ category('helm-web-editor', async () => {
16
+ let monomerLibHelper: IMonomerLibHelper;
17
+ let userLibSettings: UserLibSettings;
18
+
19
+ let hh: IHelmHelper;
20
+
21
+ before(async () => {
22
+ await initHelmMainPackage();
23
+ monomerLibHelper = await getMonomerLibHelper();
24
+ userLibSettings = await getUserLibSettings();
25
+ await setUserLibSettingsForTests();
26
+ await monomerLibHelper.awaitLoaded();
27
+ await monomerLibHelper.loadLibraries(true);
28
+
29
+ hh = await getHelmHelper();
30
+ });
31
+
32
+ after(async () => {
33
+ await setUserLibSettings(userLibSettings);
34
+ await monomerLibHelper.loadLibraries(true);
35
+ });
36
+
37
+ test('helm-web-editor', async () => {
38
+ const editor = hh.createHelmWebEditor();
39
+ });
40
+
41
+ test('web-editor-app', async () => {
42
+ const helmStr: string = 'PEPTIDE1{I.H.A.N.T.Thr_PO3H2.Aca.D-Tyr_Et}$$$$';
43
+
44
+ const appHost = ui.div([],
45
+ {style: {width: '700px', height: '432px'}});
46
+ const app = hh.createWebEditorApp(appHost, helmStr);
47
+
48
+ const dlg = ui.dialog().add(appHost).show();
49
+ try {
50
+
51
+ } finally {
52
+ dlg.close();
53
+ }
54
+ });
55
+ });
@@ -0,0 +1,98 @@
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
+
6
+ import {after, before, category, delay, expect, test, expectArray, timeout} from '@datagrok-libraries/utils/src/test';
7
+ import {HelmType, Mol, OrgType} from '@datagrok-libraries/bio/src/helm/types';
8
+ import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
9
+ import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
10
+ import {
11
+ getUserLibSettings, setUserLibSettings, setUserLibSettingsForTests
12
+ } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
13
+
14
+ import {JSDraw2HelmModule} from '../types';
15
+ import {initHelmMainPackage} from './utils';
16
+
17
+ declare const org: OrgType;
18
+ declare const JSDraw2: JSDraw2HelmModule;
19
+
20
+ type TestTgtType = { atomCount: number, bondCount: number };
21
+
22
+ category('parseHelm', () => {
23
+ const testData: { [testName: string]: { src: string, tgt: TestTgtType } } = {
24
+ 'PT': {
25
+ src: 'PEPTIDE1{[L-hArg(Et,Et)].E.F.G}|PEPTIDE2{C.E}$PEPTIDE1,PEPTIDE2,2:R3-1:R1$$$V2.0',
26
+ tgt: {atomCount: 6, bondCount: 5}
27
+ },
28
+ 'RNA': {
29
+ src: 'RNA1{[dhp]([m1A])p.r(T)p.r(T)p.r(G)p}$$$$V2.0',
30
+ tgt: {atomCount: 12, bondCount: 11}
31
+ }
32
+ };
33
+
34
+ let libHelper: IMonomerLibHelper;
35
+ /** Backup actual user's monomer libraries settings */
36
+ let userLibSettings: UserLibSettings;
37
+
38
+ before(async () => {
39
+ await initHelmMainPackage();
40
+
41
+ libHelper = await getMonomerLibHelper();
42
+
43
+ await timeout(async () => { userLibSettings = await getUserLibSettings(); }, 5000,
44
+ 'get user lib settings for backup');
45
+
46
+ // parseHelm is dependent on monomers RGroups available, test requires default monomer library
47
+ await setUserLibSettingsForTests();
48
+ await timeout(async () => { await libHelper.awaitLoaded(); }, 5000,
49
+ 'await monomerLib to be loaded');
50
+ await libHelper.loadLibraries(true);
51
+ });
52
+
53
+ after(async () => {
54
+ await setUserLibSettings(userLibSettings);
55
+ await libHelper.loadLibraries(true);
56
+ });
57
+
58
+ for (const [testName, {src, tgt}] of Object.entries(testData)) {
59
+ test(`Editor-${testName}`, async () => {
60
+ _testParseHelmWithEditor(src, tgt);
61
+ });
62
+ }
63
+
64
+ for (const [testName, {src, tgt}] of Object.entries(testData)) {
65
+ test(`woDOM-${testName}`, async () => {
66
+ _testParseHelmWithoutDOM(src, tgt);
67
+ });
68
+ }
69
+ });
70
+
71
+ function _testParseHelmWithEditor(src: string, tgt: TestTgtType): void {
72
+ const io = org.helm.webeditor.IO;
73
+
74
+ const editorHost = ui.div();
75
+ const editor = new JSDraw2.Editor(editorHost, {viewonly: true});
76
+
77
+ const plugin = new org.helm.webeditor.Plugin(editor);
78
+ const origin = new JSDraw2.Point(0, 0);
79
+ io.parseHelm(plugin, src, origin, null);
80
+
81
+ const m: Mol<HelmType> = plugin.jsd.m;
82
+ expect(m.atoms.length, tgt.atomCount);
83
+ expect(m.bonds.length, tgt.bondCount);
84
+ }
85
+
86
+ function _testParseHelmWithoutDOM(src: string, tgt: TestTgtType): void {
87
+ const io = org.helm.webeditor.IO;
88
+
89
+ const molHandler = new JSDraw2.MolHandler();
90
+
91
+ const plugin = new org.helm.webeditor.Plugin(molHandler);
92
+ const origin = new JSDraw2.Point(0, 0);
93
+ io.parseHelm(plugin, src, origin, null);
94
+
95
+ const m: Mol<HelmType> = plugin.jsd.m;
96
+ expect(m.atoms.length, tgt.atomCount);
97
+ expect(m.bonds.length, tgt.bondCount);
98
+ }
@@ -2,15 +2,17 @@ import * as ui from 'datagrok-api/ui';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
  import * as grok from 'datagrok-api/grok';
4
4
 
5
- import {after, before, category, expect, expectObject, test} from '@datagrok-libraries/utils/src/test';
5
+ import {after, before, category, expect, expectObject, test, timeout} from '@datagrok-libraries/utils/src/test';
6
6
  import {ALPHABET, NOTATION, TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
7
7
  import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
8
8
  import {
9
9
  getUserLibSettings, setUserLibSettings, setUserLibSettingsForTests
10
10
  } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
11
11
  import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
12
+ import {generateLongSequence} from '@datagrok-libraries/bio/src/utils/generator';
12
13
 
13
- import {getPropertiesDict} from '../widgets/properties-widget';
14
+ import {initHelmMainPackage} from './utils';
15
+ import {getPropertiesDict, SeqPropertiesError} from '../widgets/properties-widget';
14
16
 
15
17
  const enum MolProps {
16
18
  formula = 'formula',
@@ -25,6 +27,7 @@ const enum Tests {
25
27
  separatorGaps = 'separator-gaps',
26
28
  fastaPt = 'fasta-PT',
27
29
  fastaPtMsa = 'fasta-PT-MSA',
30
+ fastaRna = 'fasta-RNA',
28
31
  fastaDna = 'fasta-DNA',
29
32
  }
30
33
 
@@ -56,6 +59,11 @@ const TestsData: {
56
59
  units: NOTATION.FASTA, alphabet: ALPHABET.PT,
57
60
  res: {[MolProps.formula]: 'C38H58N10O12S', [MolProps.mw]: 878.99, [MolProps.extinctCoef]: 1.55}
58
61
  },
62
+ [Tests.fastaRna]: {
63
+ seq: 'ACGUAUUCC',
64
+ units: NOTATION.FASTA, alphabet: ALPHABET.RNA,
65
+ res: {[MolProps.formula]: 'C84H107N30O65P9', [MolProps.mw]: 2855.67, [MolProps.extinctCoef]: 96.27}
66
+ },
59
67
  [Tests.fastaDna]: {
60
68
  seq: 'ACGTATTCC',
61
69
  units: NOTATION.FASTA, alphabet: ALPHABET.DNA,
@@ -69,9 +77,14 @@ category('properties-widget', () => {
69
77
  let userLibSettings: any = null;
70
78
 
71
79
  before(async () => {
80
+ await initHelmMainPackage();
81
+
72
82
  monomerLibHelper = await getMonomerLibHelper();
73
83
  userLibSettings = getUserLibSettings();
84
+
74
85
  await setUserLibSettingsForTests();
86
+ await timeout(async () => { await monomerLibHelper.awaitLoaded(); },
87
+ 5000, 'MonomerLibHelper.awaitLoaded() timeout');
75
88
  await monomerLibHelper.loadLibraries(true); // load default libraries
76
89
  });
77
90
 
@@ -85,6 +98,22 @@ category('properties-widget', () => {
85
98
  testPropertiesDict(testData.seq, testData.units, testData.separator, testData.alphabet, testData.res);
86
99
  });
87
100
  }
101
+
102
+ test('too-long', async () => {
103
+ const colList = generateLongSequence();
104
+ const df = DG.DataFrame.fromColumns(colList);
105
+ const col = df.getCol('MSA');
106
+
107
+ const sh = SeqHandler.forColumn(col);
108
+ let errCatched = true;
109
+ try {
110
+ const _actPropDict = getPropertiesDict(col.get(0), sh);
111
+ const k = 11;
112
+ } catch (err: any) {
113
+ if (err instanceof SeqPropertiesError) errCatched = true;
114
+ }
115
+ expect(errCatched, true);
116
+ });
88
117
  });
89
118
 
90
119
  function testPropertiesDict(
@@ -95,7 +124,7 @@ function testPropertiesDict(
95
124
  col.setTag(DG.TAGS.UNITS, units);
96
125
  if (separator) col.setTag(bioTAGS.separator, separator);
97
126
  if (alphabet) col.setTag(bioTAGS.alphabet, alphabet);
98
- const uh = SeqHandler.forColumn(col);
99
- const actPropDict = getPropertiesDict(seq, uh);
127
+ const sh = SeqHandler.forColumn(col);
128
+ const actPropDict = getPropertiesDict(seq, sh);
100
129
  expectObject(actPropDict, expPropDict);
101
130
  }
@@ -15,7 +15,7 @@ import {
15
15
  getUserLibSettings, setUserLibSettings, setUserLibSettingsForTests
16
16
  } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
17
17
 
18
- import {awaitGrid} from './utils';
18
+ import {awaitGrid, initHelmMainPackage} from './utils';
19
19
  import {TAGS as helmTAGS} from '../constants';
20
20
 
21
21
  import {_package} from '../package-test';
@@ -26,6 +26,8 @@ category('renderers', () => {
26
26
  let userLibSettings: UserLibSettings;
27
27
 
28
28
  before(async () => {
29
+ await initHelmMainPackage();
30
+
29
31
  monomerLibHelper = await getMonomerLibHelper();
30
32
  userLibSettings = await getUserLibSettings();
31
33
 
@@ -3,6 +3,12 @@ import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {delay, testEvent} from '@datagrok-libraries/utils/src/test';
6
+ import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
7
+
8
+
9
+ export async function initHelmMainPackage(): Promise<void> {
10
+ await getHelmHelper();
11
+ }
6
12
 
7
13
  export async function awaitGrid(grid: DG.Grid, timeout: number = 5000): Promise<void> {
8
14
  await delay(100);
@@ -0,0 +1,5 @@
1
+ import {HelmType, JSDraw2ModuleType, OrgType, ScilModuleType} from '@datagrok-libraries/bio/src/helm/types';
2
+
3
+ export type ScilModule = ScilModuleType;
4
+ export type JSDraw2HelmModule = JSDraw2ModuleType<HelmType>;
5
+ export type OrgHelmModule = OrgType;
@@ -2,15 +2,14 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
  import * as ui from 'datagrok-api/ui';
4
4
 
5
- import * as JSDraw2 from 'JSDraw2';
5
+ import {HelmType, PolymerType, Atom, Mol} from '@datagrok-libraries/bio/src/helm/types';
6
6
 
7
7
  import {helmTypeToPolymerType} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
8
- import {PolymerType} from '@datagrok-libraries/bio/src/types';
9
8
 
10
9
  import {HelmMonomerPlacer, ISeqMonomer} from '../helm-monomer-placer';
11
10
 
12
11
  export function getHoveredMonomerFromEditorMol(
13
- argsX: number, argsY: number, gridCell: DG.GridCell, mol: JSDraw2.IEditorMol
12
+ argsX: number, argsY: number, gridCell: DG.GridCell, mol: Mol<HelmType>
14
13
  ): ISeqMonomer | null {
15
14
  let hoveredSeqMonomer: ISeqMonomer | null = null;
16
15
 
@@ -84,7 +83,7 @@ export function getHoveredMonomerFallback(
84
83
  return hoveredSeqMonomer;
85
84
  }
86
85
 
87
- function getSeqMonomerFromHelmAtom(atom: JSDraw2.IEditorMolAtom): ISeqMonomer {
86
+ function getSeqMonomerFromHelmAtom(atom: Atom<HelmType>): ISeqMonomer {
88
87
  const polymerType = helmTypeToPolymerType(atom.bio.type);
89
88
  return {symbol: atom.elem, polymerType: polymerType};
90
89
  }
@@ -2,7 +2,9 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
- import * as org from 'org';
5
+ import {
6
+ HelmType, IWebEditorMonomer, MonomerType, PolymerType, WebEditorRGroups
7
+ } from '@datagrok-libraries/bio/src/helm/types';
6
8
 
7
9
  import {Monomer} from '@datagrok-libraries/bio/src/types/index';
8
10
  import {
@@ -33,56 +35,18 @@ export function getRS(smiles: string) {
33
35
  return res;
34
36
  }
35
37
 
36
- export class LibraryWebEditorMonomer implements org.helm.WebEditorMonomer {
37
- public get rs(): number { return Object.keys(this.at).length; }
38
-
39
- /* eslint-disable max-params */
40
- protected constructor(
41
- public readonly id: string,
42
- public readonly m: string,
43
- public readonly n: string,
44
- public readonly na: string | undefined,
45
- public readonly type: org.helm.PolymerType,
46
- public readonly mt: org.helm.MonomerType,
47
- public readonly at: org.helm.WebEditorRGroups,
48
- ) /* eslint-enable max-params */ {}
49
-
50
- static fromMonomer(biotype: org.helm.HelmType, monomer: Monomer): org.helm.WebEditorMonomer {
51
- let at: org.helm.WebEditorRGroups = {};
52
- const smiles = monomer[REQ.SMILES];
53
- if (monomer.rgroups.length > 0) {
54
- monomer.rgroups.forEach((it) => {
55
- at[it[RGP.LABEL]] = it[RGP.CAP_GROUP_NAME];
56
- });
57
- } else if (smiles) {
58
- // Generate R-Groups from SMILES
59
- at = getRS(smiles);
60
- } else {
61
- // broken
62
- return new BrokenWebEditorMonomer(biotype, monomer[REQ.SYMBOL]);
63
- }
64
-
65
- return new LibraryWebEditorMonomer(
66
- monomer[REQ.SYMBOL],
67
- monomer[REQ.MOLFILE],
68
- monomer[REQ.NAME],
69
- monomer[OPT.NATURAL_ANALOG],
70
- monomer[REQ.POLYMER_TYPE],
71
- monomer[REQ.MONOMER_TYPE],
72
- at);
73
- }
74
- }
75
-
76
38
  /* eslint-disable camelcase */
77
- export abstract class DummyWebEditorMonomer implements org.helm.WebEditorMonomer {
39
+ export abstract class DummyWebEditorMonomer implements IWebEditorMonomer {
78
40
  //@formatter:off
79
41
  public abstract get backgroundcolor(): string | undefined;
80
42
  public abstract get linecolor(): string | undefined;
81
43
  public abstract get textcolor(): string | undefined;
82
44
  //@formatter:on
83
45
 
46
+ get issmiles(): boolean { return !!this.smiles; }
47
+
84
48
  /** R-Group index os single digit only is allowed in Pistoia code */
85
- public readonly at: org.helm.WebEditorRGroups = {
49
+ public readonly at: WebEditorRGroups = {
86
50
  R1: 'H', R2: 'H', R3: 'H', R4: 'H', R5: 'H', R6: 'H', R7: 'H', R8: 'H', R9: 'H'
87
51
  };
88
52
 
@@ -94,8 +58,9 @@ export abstract class DummyWebEditorMonomer implements org.helm.WebEditorMonomer
94
58
  /** name */ public readonly n: string | undefined = 'missing',
95
59
  /** molfile */ public readonly m: string | undefined = undefined,
96
60
  /* Pistoia.HELM deletes .type and .mt in Monomers.addOneMonomer() */
97
- /** polymer type */ public readonly type: org.helm.PolymerType | undefined = undefined,
98
- /** monomer type */ public readonly mt: org.helm.MonomerType | undefined = undefined,
61
+ /** polymer type */ public readonly type: PolymerType | undefined = undefined,
62
+ /** monomer type */ public readonly mt: MonomerType | undefined = undefined,
63
+ public readonly smiles?: string,
99
64
  ) {
100
65
  if (!this.id)
101
66
  throw new Error('Invalid arg undefined [id].');
@@ -0,0 +1,90 @@
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 {
6
+ HelmType, IWebEditorMonomer, IMonomerColors, MonomerType, PolymerType, WebEditorRGroups
7
+ } from '@datagrok-libraries/bio/src/helm/types';
8
+ import {Monomer} from '@datagrok-libraries/bio/src/types';
9
+ import {
10
+ HELM_OPTIONAL_FIELDS as OPT, HELM_REQUIRED_FIELD as REQ, HELM_RGROUP_FIELDS as RGP
11
+ } from '@datagrok-libraries/bio/src/utils/const';
12
+ import {BrokenWebEditorMonomer, getRS, MissingWebEditorMonomer} from './get-monomer-dummy';
13
+
14
+ function getMonomerColors(monomer: Monomer): IMonomerColors | null {
15
+ const currentMonomerSchema = 'default';
16
+ let monomerSchema: string = currentMonomerSchema;
17
+ if (!monomer.meta || !monomer.meta.colors) return null;
18
+
19
+ const monomerColors: { [colorSchemaName: string]: any } = monomer.meta.colors;
20
+
21
+ if (!(currentMonomerSchema in monomerColors)) monomerSchema = 'default';
22
+
23
+ const res = monomerColors[monomerSchema];
24
+
25
+ return !res ? null : {
26
+ textcolor: res.text ?? res.textColor,
27
+ linecolor: res.line ?? res.lineColor,
28
+ backgroundcolor: res.background ?? res.backgroundColor
29
+ } as IMonomerColors;
30
+ }
31
+
32
+ export class LibraryWebEditorMonomer implements IWebEditorMonomer {
33
+ public get rs(): number { return Object.keys(this.at).length; }
34
+
35
+ public get issmiles(): boolean { return !!this.smiles; }
36
+
37
+ public linecolor?: string;
38
+ public backgroundcolor?: string;
39
+ public textcolor?: string;
40
+
41
+ /* eslint-disable max-params */
42
+ protected constructor(
43
+ public readonly id: string,
44
+ public readonly m: string,
45
+ public readonly n: string,
46
+ public readonly na: string | undefined,
47
+ public readonly type: PolymerType,
48
+ public readonly mt: MonomerType,
49
+ public readonly at: WebEditorRGroups,
50
+ public readonly smiles?: string,
51
+ ) /* eslint-enable max-params */ {}
52
+
53
+ static fromMonomer(biotype: HelmType, monomer: Monomer): IWebEditorMonomer {
54
+ let at: WebEditorRGroups = {};
55
+ const symbol = monomer[REQ.SYMBOL];
56
+ const smiles = monomer[REQ.SMILES];
57
+ if (monomer.rgroups.length > 0) {
58
+ monomer.rgroups.forEach((it) => {
59
+ at[it[RGP.LABEL]] = it[RGP.CAP_GROUP_NAME];
60
+ });
61
+ } else if (smiles) {
62
+ // Generate R-Groups from SMILES
63
+ at = getRS(smiles);
64
+ } else if (!monomer.lib) {
65
+ // missing
66
+ return new MissingWebEditorMonomer(biotype, symbol);
67
+ } else {
68
+ // broken
69
+ return new BrokenWebEditorMonomer(biotype, symbol);
70
+ }
71
+
72
+ const res = new LibraryWebEditorMonomer(
73
+ monomer[REQ.SYMBOL],
74
+ monomer[REQ.MOLFILE],
75
+ monomer[REQ.NAME],
76
+ monomer[OPT.NATURAL_ANALOG],
77
+ monomer[REQ.POLYMER_TYPE],
78
+ monomer[REQ.MONOMER_TYPE],
79
+ at);
80
+
81
+ const colors = getMonomerColors(monomer);
82
+ if (colors) {
83
+ res.textcolor = colors?.textcolor;
84
+ res.linecolor = colors?.linecolor;
85
+ res.backgroundcolor = colors?.backgroundcolor;
86
+ }
87
+
88
+ return res;
89
+ }
90
+ }
@@ -2,30 +2,30 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
- import * as org from 'org';
6
- import * as scil from 'scil';
7
- import * as JSDraw2 from 'JSDraw2';
8
- import Atom = JSDraw2.Atom;
9
-
10
5
  import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
11
- import {HelmType, IMonomerLib, Monomer, WebEditorMonomer} from '@datagrok-libraries/bio/src/types';
6
+ import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
7
+ import {Atom, HelmType, IWebEditorMonomer, GetMonomerResType} from '@datagrok-libraries/bio/src/helm/types';
12
8
  import {helmTypeToPolymerType} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
13
- import {PolymerTypes, HelmTypes} from '@datagrok-libraries/bio/src/utils/const';
14
9
  import {
15
10
  HELM_REQUIRED_FIELD as REQ
16
11
  } from '@datagrok-libraries/bio/src/utils/const';
12
+ import {HelmTypes} from '@datagrok-libraries/bio/src/helm/consts';
13
+
14
+ import {AmbiguousWebEditorMonomer, GapWebEditorMonomer, MissingWebEditorMonomer} from './get-monomer-dummy';
15
+ import {LibraryWebEditorMonomer} from './get-monomer-of-library';
16
+ import {OrgHelmModule, ScilModule} from '../types';
17
+
18
+ import {_package} from '../package';
17
19
 
18
- import {AmbiguousWebEditorMonomer, GapWebEditorMonomer, LibraryWebEditorMonomer} from './dummy-monomer';
20
+ declare const org: OrgHelmModule;
21
+ declare const scil: ScilModule;
19
22
 
20
23
  const monomerRe = /[\w()]+/;
21
24
  //** Do not mess with monomer symbol with parenthesis enclosed in square brackets */
22
25
  const ambMonomerRe = RegExp(String.raw`\(${monomerRe}(,${monomerRe})+\)`);
23
26
 
24
- export type GetMonomerResType = WebEditorMonomer | null;
25
-
26
- export type GetMonomerFunc = (a: Atom<HelmType> | HelmType, name: string | undefined) => GetMonomerResType;
27
27
  type GetMonomerOverridingFunc = (
28
- a: Atom<HelmType> | HelmType, name: string, monomerLib: IMonomerLib,
28
+ a: Atom<HelmType> | HelmType, name: string | undefined, monomerLib: IMonomerLib,
29
29
  originalGetMonomer: (a: Atom<HelmType> | HelmType, name: string) => GetMonomerResType) => GetMonomerResType;
30
30
 
31
31
  export function getMonomerOverrideAndLogAlert(
@@ -36,11 +36,10 @@ export function getMonomerOverrideAndLogAlert(
36
36
  const getMonomerOriginal = monomers.getMonomer.bind(monomers);
37
37
  const alertOriginal = scil.Utils.alert;
38
38
  try {
39
- org.helm.webeditor.Monomers.getMonomer = (
40
- a: Atom<HelmType> | HelmType, name: string
41
- ): GetMonomerResType => {
42
- return getMonomerOverriding(a, name, monomerLib, getMonomerOriginal);
43
- };
39
+ org.helm.webeditor.Monomers.getMonomer =
40
+ (a: Atom<HelmType> | HelmType, name?: string): GetMonomerResType => {
41
+ return getMonomerOverriding(a, name, monomerLib, getMonomerOriginal);
42
+ };
44
43
  // Preventing alert message box for missing monomers with compressed Scilligence.JSDraw2.Lite.js
45
44
  scil.Utils.alert = (s: string): void => {
46
45
  logger.warning(`${logPrefix}, scil.Utils.alert() s = 's'.`);
@@ -59,7 +58,7 @@ export function getMonomerHandleArgs(
59
58
  let biotype: HelmType;
60
59
  let elem: string;
61
60
  if ((a as Atom<HelmType>).T === 'ATOM') {
62
- biotype = (a as Atom<HelmType>).biotype();
61
+ biotype = (a as Atom<HelmType>).biotype()!;
63
62
  elem = (a as Atom<HelmType>).elem;
64
63
  } else {
65
64
  biotype = a as HelmType;
@@ -72,8 +71,8 @@ export function getMonomerHandleArgs(
72
71
  /** Substitutes {@link org.helm.webeditor.Monomers.getMonomer()} */
73
72
  export function getWebEditorMonomer(
74
73
  monomerLib: IMonomerLib,
75
- a: Atom<HelmType> | HelmType, argName: string,
76
- ): WebEditorMonomer | null {
74
+ a: Atom<HelmType> | HelmType, argName?: string,
75
+ ): IWebEditorMonomer | null {
77
76
  const [biotype, elem] = getMonomerHandleArgs(a, argName);
78
77
  const pt = helmTypeToPolymerType(biotype);
79
78
 
@@ -91,7 +90,7 @@ export function getWebEditorMonomer(
91
90
  m = monomerLib.addMissingMonomer(pt, elem);
92
91
 
93
92
  /** Get or create {@link org,helm.WebEditorMonomer} */
94
- let resWem: WebEditorMonomer | undefined = m.wem;
93
+ let resWem: IWebEditorMonomer | null = m.wem ?? null;
95
94
  if (!resWem) {
96
95
  if (elem === '*')
97
96
  resWem = m.wem = new GapWebEditorMonomer(biotype, elem);
@@ -102,6 +101,9 @@ export function getWebEditorMonomer(
102
101
  ambMonomerRe.test(elem) // e.g. (A,R,_)
103
102
  )
104
103
  resWem = m.wem = new AmbiguousWebEditorMonomer(biotype, elem);
104
+ else if (!m.lib)
105
+ resWem = m.wem = new MissingWebEditorMonomer(biotype, elem);
106
+
105
107
 
106
108
  if (!resWem)
107
109
  resWem = m.wem = LibraryWebEditorMonomer.fromMonomer(biotype, m);
@@ -2,9 +2,9 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
  import * as ui from 'datagrok-api/ui';
4
4
 
5
- import * as JSDraw2 from 'JSDraw2';
6
5
  import wu from 'wu';
7
6
 
7
+ import {HelmType, Mol} from '@datagrok-libraries/bio/src/helm/types';
8
8
  import {
9
9
  CellRendererBackAsyncBase, RenderServiceBase
10
10
  } from '@datagrok-libraries/bio/src/utils/cell-renderer-async-base';
@@ -49,6 +49,13 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
49
49
  tableCol: DG.Column<string>,
50
50
  ) {
51
51
  super(gridCol, tableCol, new WrapLogger(_package.logger) /* _package.logger */, true);
52
+
53
+ const monomerLib = getMonomerLib();
54
+ if (!monomerLib)
55
+ throw new Error('Helm package is not initialized yet.');
56
+ this.subs.push(monomerLib.onChanged.subscribe(() => {
57
+ this.reset();
58
+ }));
52
59
  }
53
60
 
54
61
  protected override reset(): void {
@@ -134,7 +141,7 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
134
141
  const argsX = (e.offsetX - gcb.x) * dpr;
135
142
  const argsY = (e.offsetY - gcb.y) * dpr;
136
143
 
137
- const editorMol: JSDraw2.IEditorMol | null = aux.mol;
144
+ const editorMol: Mol<HelmType> | null = aux.mol;
138
145
  if (!editorMol) {
139
146
  this.logger.warning(`${logPrefix}, editorMol of the cell not found.`);
140
147
  return; // The gridCell is not rendered yet
@@ -2,25 +2,26 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
- import * as org from 'org';
6
- import * as scil from 'scil';
7
- import * as JSDraw2 from 'JSDraw2';
8
-
9
5
  import $ from 'cash-dom';
10
6
  import {Subject, Unsubscribable} from 'rxjs';
11
7
 
12
8
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
13
9
  import {IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
10
+ import {Editor, HelmType} from '@datagrok-libraries/bio/src/helm/types';
14
11
  import {RenderTask} from '@datagrok-libraries/bio/src/utils/cell-renderer-async-base';
15
12
  import {HelmAux, HelmProps, HelmServiceBase} from '@datagrok-libraries/bio/src/viewers/helm-service';
16
13
  import {svgToImage} from '@datagrok-libraries/utils/src/svg';
17
14
 
15
+ import {JSDraw2HelmModule} from '../types';
16
+
18
17
  import {_package} from '../package';
19
18
 
19
+ declare const JSDraw2: JSDraw2HelmModule;
20
+
20
21
  export class HelmService extends HelmServiceBase {
21
22
  private readonly hostDiv: HTMLDivElement;
22
23
 
23
- private editor!: JSDraw2.Editor;
24
+ private editor!: Editor<HelmType>;
24
25
  private image: HTMLImageElement | null = null;
25
26
 
26
27
  constructor() {