@datagrok/helm 2.2.1 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/package-test.js +1 -1
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/files/tests/helm2-bracket.csv +2 -0
- package/package.json +13 -10
- package/src/cell-renderer.ts +8 -33
- package/src/helm-helper.ts +67 -17
- package/src/helm-monomer-placer.ts +7 -9
- package/src/helm-web-editor.ts +33 -3
- package/src/package-test.ts +8 -3
- package/src/package-utils.ts +69 -42
- package/src/package.ts +121 -141
- package/src/tests/findMonomers-tests.ts +2 -0
- package/src/tests/get-all-parts-tests.ts +5 -0
- package/src/tests/get-molfiles-tests.ts +3 -1
- package/src/tests/get-monomer-tests.ts +88 -19
- package/src/tests/helm-service-tests.ts +4 -0
- package/src/tests/helm-tests.ts +7 -1
- package/src/tests/helm-web-editor-tests.ts +55 -0
- package/src/tests/parse-helm-tests.ts +98 -0
- package/src/tests/properties-widget-tests.ts +33 -4
- package/src/tests/renderers-tests.ts +3 -1
- package/src/tests/utils.ts +6 -0
- package/src/types/index.ts +5 -0
- package/src/utils/get-hovered.ts +3 -4
- package/src/utils/{dummy-monomer.ts → get-monomer-dummy.ts} +10 -45
- package/src/utils/get-monomer-of-library.ts +90 -0
- package/src/utils/get-monomer.ts +23 -21
- package/src/utils/helm-grid-cell-renderer.ts +19 -3
- package/src/utils/helm-service.ts +6 -5
- package/src/utils/index.ts +11 -17
- package/src/widgets/properties-widget.ts +29 -9
- package/tsconfig.json +1 -1
- package/vendor/helm-web-editor.development.js +39640 -0
- package/vendor/helm-web-editor.production.js +2 -0
- package/vendor/helm-web-editor.production.js.map +1 -0
- package/webpack.config.js +15 -12
- package/helm/JSDraw/Pistoia.HELM.js +0 -27
- package/helm/JSDraw/Scilligence.JSDraw2.Lite.js +0 -12
- package/helm/JSDraw/Scilligence.JSDraw2.Resources.js +0 -762
- package/helm/JSDraw/dojo.js +0 -250
- 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 {
|
|
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
|
|
99
|
-
const actPropDict = getPropertiesDict(seq,
|
|
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
|
|
package/src/tests/utils.ts
CHANGED
|
@@ -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);
|
package/src/types/index.ts
CHANGED
package/src/utils/get-hovered.ts
CHANGED
|
@@ -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
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
98
|
-
/** monomer type */ public readonly mt:
|
|
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
|
+
}
|
package/src/utils/get-monomer.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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:
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
76
|
-
):
|
|
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:
|
|
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';
|
|
@@ -18,6 +18,8 @@ import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
|
|
|
18
18
|
import {getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
19
19
|
|
|
20
20
|
import {_package, getMonomerLib} from '../package';
|
|
21
|
+
import {IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
|
|
22
|
+
import {GridCell, GridCellStyle, x} from 'datagrok-api/dg';
|
|
21
23
|
|
|
22
24
|
class WrapLogger implements ILogger {
|
|
23
25
|
constructor(
|
|
@@ -44,6 +46,8 @@ class WrapLogger implements ILogger {
|
|
|
44
46
|
export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProps, HelmAux> {
|
|
45
47
|
private _auxList: (HelmAux | null)[];
|
|
46
48
|
|
|
49
|
+
private monomerLib: IMonomerLib | null = null;
|
|
50
|
+
|
|
47
51
|
constructor(
|
|
48
52
|
gridCol: DG.GridColumn | null,
|
|
49
53
|
tableCol: DG.Column<string>,
|
|
@@ -134,7 +138,7 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
|
|
|
134
138
|
const argsX = (e.offsetX - gcb.x) * dpr;
|
|
135
139
|
const argsY = (e.offsetY - gcb.y) * dpr;
|
|
136
140
|
|
|
137
|
-
const editorMol:
|
|
141
|
+
const editorMol: Mol<HelmType> | null = aux.mol;
|
|
138
142
|
if (!editorMol) {
|
|
139
143
|
this.logger.warning(`${logPrefix}, editorMol of the cell not found.`);
|
|
140
144
|
return; // The gridCell is not rendered yet
|
|
@@ -152,10 +156,22 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
|
|
|
152
156
|
}
|
|
153
157
|
}
|
|
154
158
|
|
|
159
|
+
public override render(g: CanvasRenderingContext2D,
|
|
160
|
+
x: number, y: number, w: number, h: number,
|
|
161
|
+
gridCell: GridCell, cellStyle: GridCellStyle) {
|
|
162
|
+
if (!this.monomerLib) {
|
|
163
|
+
this.monomerLib = getMonomerLib();
|
|
164
|
+
if (this.monomerLib) {
|
|
165
|
+
this.subs.push(this.monomerLib.onChanged.subscribe(this.monomerLibOnChanged.bind(this)));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
super.render(g, x, y, w, h, gridCell, cellStyle);
|
|
169
|
+
}
|
|
170
|
+
|
|
155
171
|
// -- Handle events --
|
|
172
|
+
|
|
156
173
|
private monomerLibOnChanged(_value: any): void {
|
|
157
174
|
this.reset();
|
|
158
|
-
this.invalidateGrid();
|
|
159
175
|
}
|
|
160
176
|
|
|
161
177
|
static getOrCreate(gridCell: DG.GridCell): HelmGridCellRendererBack {
|
|
@@ -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!:
|
|
24
|
+
private editor!: Editor<HelmType>;
|
|
24
25
|
private image: HTMLImageElement | null = null;
|
|
25
26
|
|
|
26
27
|
constructor() {
|