@datagrok/helm 2.3.4 → 2.4.2
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 +26 -0
- package/dist/package-test.js +1 -1
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +8 -7
- package/src/cell-renderer.ts +9 -8
- package/src/helm-helper.ts +232 -40
- package/src/helm-monomer-placer.ts +1 -1
- package/src/helm-web-editor.ts +24 -34
- package/src/package-utils.ts +14 -20
- package/src/package.ts +13 -23
- package/src/tests/findMonomers-tests.ts +3 -3
- package/src/tests/get-molfiles-tests.ts +2 -2
- package/src/tests/get-monomer-tests.ts +19 -16
- package/src/tests/helm-input-tests.ts +4 -4
- package/src/tests/helm-service-tests.ts +3 -3
- package/src/tests/helm-tests.ts +1 -2
- package/src/tests/helm-web-editor-tests.ts +2 -2
- package/src/tests/parse-helm-tests.ts +9 -8
- package/src/tests/properties-widget-tests.ts +2 -2
- package/src/tests/renderers-tests.ts +2 -2
- package/src/types/index.ts +1 -1
- package/src/utils/get-hovered.ts +8 -10
- package/src/utils/get-monomer.ts +3 -4
- package/src/utils/helm-grid-cell-renderer.ts +16 -29
- package/src/utils/helm-service.ts +4 -6
- package/src/widgets/helm-input.ts +135 -72
- package/src/widgets/properties-widget.ts +4 -4
- package/tsconfig.json +3 -3
- package/webpack.config.js +4 -4
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/helm",
|
|
3
3
|
"friendlyName": "Helm",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.4.2",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Oleksandra Serhiienko",
|
|
7
7
|
"email": "oserhiienko@datagrok.ai"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"css/helm.css"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@datagrok-libraries/bio": "^5.42.
|
|
19
|
+
"@datagrok-libraries/bio": "^5.42.9",
|
|
20
20
|
"@datagrok-libraries/chem-meta": "^1.2.5",
|
|
21
21
|
"@datagrok-libraries/utils": "^4.2.19",
|
|
22
22
|
"cash-dom": "^8.1.1",
|
|
@@ -26,17 +26,18 @@
|
|
|
26
26
|
"wu": "latest"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@datagrok-libraries/helm-web-editor": "^1.1.
|
|
30
|
-
"@datagrok-libraries/js-draw-lite": "^0.0.
|
|
31
|
-
"@datagrok/bio": "^2.
|
|
29
|
+
"@datagrok-libraries/helm-web-editor": "^1.1.9",
|
|
30
|
+
"@datagrok-libraries/js-draw-lite": "^0.0.7",
|
|
31
|
+
"@datagrok/bio": "^2.14.1",
|
|
32
32
|
"@datagrok/chem": "^1.9.2",
|
|
33
33
|
"@types/node": "17.0.45",
|
|
34
34
|
"@types/wu": "latest",
|
|
35
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
36
|
-
"@typescript-eslint/parser": "^
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^7.16.0",
|
|
36
|
+
"@typescript-eslint/parser": "^7.16.0",
|
|
37
37
|
"datagrok-tools": "latest",
|
|
38
38
|
"eslint": "^8.18.0",
|
|
39
39
|
"eslint-config-google": "^0.14.0",
|
|
40
|
+
"eslint-plugin-rxjs": "^5.0.3",
|
|
40
41
|
"path": "^0.12.7",
|
|
41
42
|
"source-map-loader": "^4.0.1",
|
|
42
43
|
"ts-loader": "^9.2.6",
|
package/src/cell-renderer.ts
CHANGED
|
@@ -4,19 +4,19 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
|
|
5
5
|
import wu from 'wu';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {HelmMol, ISeqMonomer} from '@datagrok-libraries/bio/src/helm/types';
|
|
8
8
|
|
|
9
9
|
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
10
10
|
import {getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
11
11
|
|
|
12
12
|
import {findMonomers, parseHelm, removeGapsFromHelm} from './utils';
|
|
13
13
|
import {HelmMonomerPlacer} from './helm-monomer-placer';
|
|
14
|
-
import {getHoveredMonomerFallback, getHoveredMonomerFromEditorMol} from './utils/get-hovered';
|
|
15
|
-
import {
|
|
14
|
+
import {getHoveredMonomerFallback, getHoveredMonomerFromEditorMol, getSeqMonomerFromHelmAtom} from './utils/get-hovered';
|
|
15
|
+
import {JSDraw2Module} from './types';
|
|
16
16
|
|
|
17
17
|
import {_package} from './package';
|
|
18
18
|
|
|
19
|
-
declare const JSDraw2:
|
|
19
|
+
declare const JSDraw2: JSDraw2Module;
|
|
20
20
|
|
|
21
21
|
const enum tempTAGS {
|
|
22
22
|
helmSumMaxLengthWords = 'helm-sum-maxLengthWords',
|
|
@@ -50,12 +50,13 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
50
50
|
const argsY = e.offsetY - gcb.y;
|
|
51
51
|
|
|
52
52
|
const monomerLib = _package.monomerLib;
|
|
53
|
-
const editorMol:
|
|
53
|
+
const editorMol: HelmMol | null = helmPlacer.getEditorMol(gridCell.tableRowIndex!);
|
|
54
54
|
let seqMonomer: ISeqMonomer | null;
|
|
55
55
|
let missedMonomers: Set<string> = new Set<string>(); // of .size = 0
|
|
56
|
-
if (editorMol)
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
if (editorMol) {
|
|
57
|
+
const hoveredAtom = getHoveredMonomerFromEditorMol(argsX, argsY, editorMol, gridCell.bounds.height);
|
|
58
|
+
seqMonomer = hoveredAtom ? getSeqMonomerFromHelmAtom(hoveredAtom) : null;
|
|
59
|
+
} else {
|
|
59
60
|
const seq: string = !gridCell.cell.value ? '' : removeGapsFromHelm(gridCell.cell.value as string);
|
|
60
61
|
const monomerList = parseHelm(seq);
|
|
61
62
|
missedMonomers = findMonomers(monomerList, monomerLib);
|
package/src/helm-helper.ts
CHANGED
|
@@ -3,23 +3,26 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
|
-
App, Atom, HelmType, GetMonomerFunc, GetMonomerResType, HelmString, HelmMol
|
|
6
|
+
App, Atom, HelmType, GetMonomerFunc, GetMonomerResType, HelmString, HelmMol,
|
|
7
|
+
MonomerExplorer, TabDescType, MonomersFuncs, MonomerSetType, HelmAtom, ISeqMonomer, PolymerType, MonomerType, type DojoType
|
|
7
8
|
} from '@datagrok-libraries/bio/src/helm/types';
|
|
8
|
-
|
|
9
|
+
import {HelmTypes, MonomerTypes, PolymerTypes} from '@datagrok-libraries/bio/src/helm/consts';
|
|
9
10
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
10
11
|
import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
|
|
11
|
-
import {IHelmHelper,
|
|
12
|
+
import {HelmInputBase, IHelmHelper, IHelmInputInitOptions} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
12
13
|
import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
|
|
13
|
-
import {IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
|
|
14
|
+
import {IMonomerLib, IMonomerLinkData, IMonomerSetPlaceholder} from '@datagrok-libraries/bio/src/types/index';
|
|
15
|
+
import {HelmTabKeys, IHelmDrawOptions} from '@datagrok-libraries/helm-web-editor/src/types/org-helm';
|
|
14
16
|
|
|
15
17
|
import {HelmWebEditor} from './helm-web-editor';
|
|
16
18
|
import {OrgHelmModule, ScilModule} from './types';
|
|
17
19
|
import {getWebEditorMonomer} from './utils/get-monomer';
|
|
18
20
|
import {HelmInput} from './widgets/helm-input';
|
|
21
|
+
import {getHoveredMonomerFromEditorMol} from './utils/get-hovered';
|
|
19
22
|
|
|
20
23
|
import {_package} from './package';
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
declare const dojo: DojoType;
|
|
23
26
|
declare const scil: ScilModule;
|
|
24
27
|
declare const org: OrgHelmModule;
|
|
25
28
|
|
|
@@ -34,9 +37,9 @@ export class HelmHelper implements IHelmHelper {
|
|
|
34
37
|
throw new Error(`HelmHelper must be a single.`);
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
createHelmInput(name?: string, options?:
|
|
40
|
+
createHelmInput(name?: string, options?: IHelmInputInitOptions): HelmInputBase {
|
|
38
41
|
try {
|
|
39
|
-
const monomerLib: IMonomerLib = _package.libHelper
|
|
42
|
+
const monomerLib: IMonomerLib = _package.libHelper!.getMonomerLib();
|
|
40
43
|
return HelmInput.create(this, monomerLib, name, options);
|
|
41
44
|
} catch (err: any) {
|
|
42
45
|
const [errMsg, errStack] = errInfo(err);
|
|
@@ -45,8 +48,8 @@ export class HelmHelper implements IHelmHelper {
|
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
|
|
48
|
-
createHelmWebEditor(host?: HTMLDivElement): IHelmWebEditor {
|
|
49
|
-
return new HelmWebEditor(host);
|
|
51
|
+
createHelmWebEditor(host?: HTMLDivElement, drawOptions?: Partial<IHelmDrawOptions>): IHelmWebEditor {
|
|
52
|
+
return new HelmWebEditor(host, drawOptions);
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
createWebEditorApp(host: HTMLDivElement, helm: string): App {
|
|
@@ -59,7 +62,36 @@ export class HelmHelper implements IHelmHelper {
|
|
|
59
62
|
mexmonomerstab: true,
|
|
60
63
|
sequenceviewonly: false,
|
|
61
64
|
mexfavoritefirst: true,
|
|
62
|
-
mexfilter: true
|
|
65
|
+
mexfilter: true,
|
|
66
|
+
currentTabKey: HelmTabKeys.Helm,
|
|
67
|
+
overrideTabs: (tabs: Partial<TabDescType>[]): Partial<TabDescType>[] => {
|
|
68
|
+
const res: Partial<TabDescType>[] = [...tabs,
|
|
69
|
+
{caption: 'Placeholders', tabkey: 'placeholders'},
|
|
70
|
+
];
|
|
71
|
+
return res;
|
|
72
|
+
},
|
|
73
|
+
onShowTab: (mex: MonomerExplorer, div: HTMLDivElement, key: string): void => {
|
|
74
|
+
switch (key) {
|
|
75
|
+
case 'placeholders': {
|
|
76
|
+
this.onShowTabPlaceholders(mex, div);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case 'placeholders-meta': {
|
|
80
|
+
this.onShowTabPlaceholdersMeta(mex, div);
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
case 'placeholders-sets': {
|
|
84
|
+
this.onShowTabPlaceholdersSets(mex, div);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
dojo.connect(div, 'onmousedown', function(e: MouseEvent) {
|
|
89
|
+
mex.select(e);
|
|
90
|
+
});
|
|
91
|
+
dojo.connect(div, 'ondblclick', function(e: MouseEvent) {
|
|
92
|
+
mex.dblclick(e);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
63
95
|
});
|
|
64
96
|
const sizes = webEditorApp.calculateSizes();
|
|
65
97
|
webEditorApp.canvas!.resize(sizes.rightwidth - 100, sizes.topheight - 210);
|
|
@@ -70,55 +102,215 @@ export class HelmHelper implements IHelmHelper {
|
|
|
70
102
|
scil.apply(webEditorApp.properties!.parent.style, s);
|
|
71
103
|
webEditorApp.structureview!.resize(sizes.rightwidth, sizes.bottomheight + webEditorApp.toolbarheight);
|
|
72
104
|
webEditorApp.mex!.resize(sizes.topheight - 80);
|
|
73
|
-
|
|
74
|
-
webEditorApp.canvas!.helm!.setSequence(helm, 'HELM');
|
|
75
|
-
}, 200);
|
|
105
|
+
webEditorApp.canvas?.setHelm(helm);
|
|
76
106
|
return webEditorApp;
|
|
77
107
|
}
|
|
78
108
|
|
|
109
|
+
// -- MonomerExplorer.onShowTab --
|
|
110
|
+
|
|
111
|
+
public onShowTabPlaceholders(mex: MonomerExplorer, div: HTMLDivElement): void {
|
|
112
|
+
const d = scil.Utils.createElement(div, 'div', null, {paddingTop: '5px'});
|
|
113
|
+
|
|
114
|
+
/* eslint-disable max-len*/
|
|
115
|
+
// if (this.options.canvastoolbar == false) {
|
|
116
|
+
// const b = scil.Utils.createElement(d, 'div', '<img src=\'' + scil.Utils.imgSrc('helm/arrow.png') + '\' style=\'vertical-align:middle\'>Mouse Pointer', {cursor: 'pointer', padding: '2px', border: 'solid 1px gray', margin: '5px'});
|
|
117
|
+
// scil.connect(b, 'onclick', function() {
|
|
118
|
+
// mex.plugin.jsd.doCmd('lasso');
|
|
119
|
+
// });
|
|
120
|
+
// }
|
|
121
|
+
/* eslint-enable max-len*/
|
|
122
|
+
|
|
123
|
+
const phTabs: Partial<TabDescType>[] = [];
|
|
124
|
+
phTabs.push({caption: 'Meta', tabkey: 'placeholders-meta'});
|
|
125
|
+
phTabs.push({caption: 'Sets', tabkey: 'placeholders-sets'});
|
|
126
|
+
const placeholdersTabs = new scil.Tabs(d, {
|
|
127
|
+
onShowTab(td: HTMLTableCellElement) {
|
|
128
|
+
mex.onShowTab(td);
|
|
129
|
+
},
|
|
130
|
+
tabpadding: '5px 2px 1px 2px',
|
|
131
|
+
tabs: phTabs,
|
|
132
|
+
marginBottom: `0`,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public onShowTabPlaceholdersMeta(mex: MonomerExplorer, div: HTMLDivElement): void {
|
|
137
|
+
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public onShowTabPlaceholdersSets(mex: MonomerExplorer, div: HTMLDivElement): void {
|
|
141
|
+
const monomerSets = _package.libHelper!.getMonomerSets();
|
|
142
|
+
|
|
143
|
+
const phSet: { [polymerType: string]: { [helmType: string]: IMonomerSetPlaceholder[] } } = {};
|
|
144
|
+
for (const ph of monomerSets.placeholders) {
|
|
145
|
+
let ofPolymerTypeSet = phSet[ph.polymerType];
|
|
146
|
+
if (!ofPolymerTypeSet) ofPolymerTypeSet = phSet[ph.polymerType] = {};
|
|
147
|
+
|
|
148
|
+
const phHelmType = this.toHelmType(ph.polymerType, ph.monomerType);
|
|
149
|
+
let phList = ofPolymerTypeSet[phHelmType];
|
|
150
|
+
if (!phList) phList = ofPolymerTypeSet[phHelmType] = [];
|
|
151
|
+
phList.push(ph);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const fillPlaceholders = (
|
|
155
|
+
parentDiv: HTMLDivElement, phList: IMonomerSetPlaceholder[], helmType: HelmType
|
|
156
|
+
): void => {
|
|
157
|
+
for (const ph of phList) {
|
|
158
|
+
const phDiv = mex.createMonomerDiv(parentDiv, ph.symbol, helmType);
|
|
159
|
+
ui.tooltip.bind(phDiv, () => {
|
|
160
|
+
const phTooltipDiv = ui.div([
|
|
161
|
+
ui.table(ph.monomerLinks, (ml: IMonomerLinkData, idx: number) => {
|
|
162
|
+
return [ml.symbol, ml.source];
|
|
163
|
+
}, ['Symbol', 'Library source'])
|
|
164
|
+
]);
|
|
165
|
+
return phTooltipDiv;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const polymerTypes: [string, PolymerType][] = [
|
|
171
|
+
['Chem', PolymerTypes.CHEM],
|
|
172
|
+
['Peptide', PolymerTypes.PEPTIDE],
|
|
173
|
+
['RNA', PolymerTypes.RNA],
|
|
174
|
+
['Blob', PolymerTypes.BLOB],
|
|
175
|
+
['G', PolymerTypes.G],
|
|
176
|
+
];
|
|
177
|
+
const polymerTypeAcc = ui.accordion();
|
|
178
|
+
for (const [name, polymerType] of polymerTypes) {
|
|
179
|
+
if (polymerType in phSet) {
|
|
180
|
+
polymerTypeAcc.addPane(name, () => {
|
|
181
|
+
const polymerTypeDiv = ui.div();
|
|
182
|
+
const ofPolymerTypeSet = phSet[polymerType];
|
|
183
|
+
if (Object.keys(ofPolymerTypeSet).length == 1) {
|
|
184
|
+
const [helmType, phList] = Object.entries(ofPolymerTypeSet)[0];
|
|
185
|
+
fillPlaceholders(polymerTypeDiv, phList, helmType as HelmType);
|
|
186
|
+
} else {
|
|
187
|
+
const helmTypeAcc = ui.accordion();
|
|
188
|
+
for (const [helmTypeName, helmType] of Object.entries(HelmTypes)) {
|
|
189
|
+
if (helmType in ofPolymerTypeSet) {
|
|
190
|
+
helmTypeAcc.addPane(helmTypeName, () => {
|
|
191
|
+
const helmTypeDiv = ui.div();
|
|
192
|
+
|
|
193
|
+
const phList = ofPolymerTypeSet[helmType];
|
|
194
|
+
fillPlaceholders(helmTypeDiv, phList, helmType as HelmType);
|
|
195
|
+
|
|
196
|
+
return helmTypeDiv;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
polymerTypeDiv.appendChild(helmTypeAcc.root);
|
|
201
|
+
}
|
|
202
|
+
return polymerTypeDiv;
|
|
203
|
+
}, true, undefined, false);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
div.appendChild(polymerTypeAcc.root);
|
|
207
|
+
}
|
|
208
|
+
|
|
79
209
|
// -- GetMonomer --
|
|
80
210
|
|
|
81
|
-
public
|
|
211
|
+
public originalMonomersFuncs: MonomersFuncs | null = null;
|
|
82
212
|
|
|
83
|
-
public
|
|
213
|
+
public revertOriginalMonomersFuncs(): MonomersFuncs {
|
|
84
214
|
const logPrefix = `Helm: revertOriginalGetMonomer()`;
|
|
85
|
-
if (this.
|
|
215
|
+
if (this.originalMonomersFuncs === null)
|
|
86
216
|
throw new Error('Unable to revert original getMonomer');
|
|
87
217
|
|
|
88
218
|
const monomers = org.helm.webeditor.Monomers;
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
219
|
+
const overriddenMonomersFuncs: MonomersFuncs = {
|
|
220
|
+
getMonomer: monomers.getMonomer,
|
|
221
|
+
getMonomerSet: monomers.getMonomerSet,
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
monomers.getMonomer = this.originalMonomersFuncs.getMonomer;
|
|
225
|
+
monomers.getMonomerSet = this.originalMonomersFuncs.getMonomerSet;
|
|
226
|
+
this.originalMonomersFuncs = null;
|
|
227
|
+
|
|
228
|
+
return overriddenMonomersFuncs;
|
|
92
229
|
}
|
|
93
230
|
|
|
94
|
-
public
|
|
95
|
-
const logPrefix = `Helm: overrideGetMonomer()`;
|
|
231
|
+
public overrideMonomersFuncs(monomersFuncs: MonomersFuncs): MonomersFuncs {
|
|
232
|
+
const logPrefix = `Helm: HelmHelper.overrideGetMonomer()`;
|
|
96
233
|
|
|
97
|
-
if (this.
|
|
98
|
-
throw new Error(
|
|
234
|
+
if (this.originalMonomersFuncs != null)
|
|
235
|
+
throw new Error(`${logPrefix}, originalGetMonomer is overridden already`);
|
|
99
236
|
|
|
100
237
|
const monomers = org.helm.webeditor.Monomers;
|
|
101
|
-
this.
|
|
102
|
-
|
|
103
|
-
|
|
238
|
+
this.originalMonomersFuncs = {
|
|
239
|
+
getMonomer: monomers.getMonomer.bind(monomers),
|
|
240
|
+
getMonomerSet: monomers.getMonomerSet.bind(monomers),
|
|
241
|
+
};
|
|
242
|
+
monomers.getMonomer = monomersFuncs.getMonomer;
|
|
243
|
+
monomers.getMonomerSet = monomersFuncs.getMonomerSet;
|
|
244
|
+
return this.originalMonomersFuncs!;
|
|
104
245
|
}
|
|
105
246
|
|
|
106
|
-
public
|
|
247
|
+
public buildMonomersFuncsFromLib(monomerLib: IMonomerLib): MonomersFuncs {
|
|
107
248
|
const logPrefix = `Helm: HelmHelper.buildGetMonomerFromLib()`;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
getMonomer: (a: HelmAtom | HelmType, name?: string): GetMonomerResType => {
|
|
252
|
+
const logPrefixInt = `${logPrefix}, org.helm.webeditor.Monomers.getMonomer()`;
|
|
253
|
+
try {
|
|
254
|
+
// logger.debug(`${logPrefixInt}, a: ${JSON.stringify(a, helmJsonReplacer)}, name: '${name}'`);
|
|
255
|
+
|
|
256
|
+
// Creates monomers in lib
|
|
257
|
+
const dgWem = getWebEditorMonomer(monomerLib, a, name);
|
|
258
|
+
|
|
259
|
+
return dgWem; //dgWem;
|
|
260
|
+
} catch (err) {
|
|
261
|
+
const [errMsg, errStack] = errInfo(err);
|
|
262
|
+
this.logger.error(`${logPrefixInt}, Error: ${errMsg}`, undefined, errStack);
|
|
263
|
+
throw err;
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
getMonomerSet: (a: HelmAtom | HelmType | null): MonomerSetType | null => {
|
|
267
|
+
// if (a == null)
|
|
268
|
+
// return null;
|
|
269
|
+
// const atom = a as HelmAtom;
|
|
270
|
+
// if (atom.T === 'ATOM')
|
|
271
|
+
// a = atom.biotype();
|
|
272
|
+
// return monomerLib.getMonomerSet(a as HelmType);
|
|
273
|
+
return this.originalMonomersFuncs!.getMonomerSet(a);
|
|
121
274
|
}
|
|
122
275
|
};
|
|
123
276
|
}
|
|
277
|
+
|
|
278
|
+
// helm2type(seqM: ISeqMonomer): HelmType {
|
|
279
|
+
// if (seqM.polymerType == "PEPTIDE")
|
|
280
|
+
// return org.helm.webeditor.HELM.AA;
|
|
281
|
+
// else if (seqM.polymerType == "CHEM")
|
|
282
|
+
// return org.helm.webeditor.HELM.CHEM;
|
|
283
|
+
// else if (seqM.polymerType == "RNA") {
|
|
284
|
+
// if (seqM.mt == "Branch")
|
|
285
|
+
// return org.helm.webeditor.HELM.BASE;
|
|
286
|
+
// if (seqM.mt == "Backbone") {
|
|
287
|
+
// if (seqM.na == "P" || seqM.na == "p")
|
|
288
|
+
// return org.helm.webeditor.HELM.LINKER;
|
|
289
|
+
// else
|
|
290
|
+
// return org.helm.webeditor.HELM.SUGAR;
|
|
291
|
+
// }
|
|
292
|
+
// }
|
|
293
|
+
// throw new Error(`Not supported seq monomer ${JSON.stringify(seqM)}.`);
|
|
294
|
+
// }
|
|
295
|
+
private toHelmType(polymerType: PolymerType, monomerType: MonomerType, naturalAnalog?: string) {
|
|
296
|
+
if (polymerType == PolymerTypes.PEPTIDE)
|
|
297
|
+
return org.helm.webeditor.HELM.AA;
|
|
298
|
+
else if (polymerType == PolymerTypes.CHEM)
|
|
299
|
+
return org.helm.webeditor.HELM.CHEM;
|
|
300
|
+
else if (polymerType == PolymerTypes.RNA) {
|
|
301
|
+
if (monomerType == MonomerTypes.BRANCH)
|
|
302
|
+
return org.helm.webeditor.HELM.BASE;
|
|
303
|
+
if (monomerType == MonomerTypes.BACKBONE) {
|
|
304
|
+
if (naturalAnalog == 'P' || naturalAnalog == 'p')
|
|
305
|
+
return org.helm.webeditor.HELM.LINKER;
|
|
306
|
+
else
|
|
307
|
+
return org.helm.webeditor.HELM.SUGAR;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
throw new Error(`Not supported monomer polymerType: '${polymerType}', monomerType: '${monomerType}'.`);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
public getHoveredAtom(x: number, y: number, mol: HelmMol, height: number): HelmAtom | null {
|
|
314
|
+
return getHoveredMonomerFromEditorMol(x, y, mol, height);
|
|
315
|
+
}
|
|
124
316
|
}
|
package/src/helm-web-editor.ts
CHANGED
|
@@ -6,19 +6,19 @@ import {Unsubscribable} from 'rxjs';
|
|
|
6
6
|
|
|
7
7
|
import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
|
|
8
8
|
import {
|
|
9
|
-
App, Editor, HelmType, IHelmWebEditor
|
|
9
|
+
App, Editor, HelmType, IHelmWebEditor, HelmEditor, IHelmDrawOptions
|
|
10
10
|
} from '@datagrok-libraries/bio/src/helm/types';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import {JSDraw2Module, OrgHelmModule, ScilModule} from './types';
|
|
13
13
|
|
|
14
14
|
import {_package} from './package';
|
|
15
15
|
|
|
16
16
|
declare const scil: ScilModule;
|
|
17
|
-
declare const JSDraw2:
|
|
17
|
+
declare const JSDraw2: JSDraw2Module;
|
|
18
18
|
declare const org: OrgHelmModule;
|
|
19
19
|
|
|
20
20
|
export class HelmWebEditor implements IHelmWebEditor {
|
|
21
|
-
editor:
|
|
21
|
+
editor: HelmEditor;
|
|
22
22
|
host: HTMLDivElement;
|
|
23
23
|
|
|
24
24
|
w = 200;
|
|
@@ -27,10 +27,19 @@ export class HelmWebEditor implements IHelmWebEditor {
|
|
|
27
27
|
|
|
28
28
|
constructor(
|
|
29
29
|
host?: HTMLDivElement,
|
|
30
|
+
drawOptions?: Partial<IHelmDrawOptions>,
|
|
30
31
|
private logger: ILogger = _package.logger
|
|
31
32
|
) {
|
|
32
33
|
this.host = host ?? ui.div([], {style: {width: `${this.w}px`, height: `${this.h}px`}});
|
|
33
|
-
|
|
34
|
+
|
|
35
|
+
const styleBackup = {width: this.host.style.width, height: this.host.style.height, overflow: this.host.style.overflow};
|
|
36
|
+
this.editor = new JSDraw2.Editor(this.host, {
|
|
37
|
+
width: this.w, height: this.h, viewonly: true,
|
|
38
|
+
drawOptions: drawOptions
|
|
39
|
+
});
|
|
40
|
+
this.host.style.width = styleBackup.width;
|
|
41
|
+
this.host.style.height = styleBackup.height;
|
|
42
|
+
this.host.style.overflow = styleBackup.overflow;
|
|
34
43
|
|
|
35
44
|
this.subs = [];
|
|
36
45
|
this.subs.push(ui.onSizeChanged(this.host).subscribe(this.hostOnSizeChanged.bind(this)));
|
|
@@ -40,38 +49,19 @@ export class HelmWebEditor implements IHelmWebEditor {
|
|
|
40
49
|
return `Helm: HelmWebEditor<#>`;
|
|
41
50
|
}
|
|
42
51
|
|
|
43
|
-
private
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
private lastSize: { width: number, height: number } = {width: -1, height: -1};
|
|
53
|
+
|
|
54
|
+
private hostOnSizeChanged(value: any): void {
|
|
55
|
+
const size = {width: value.target.clientWidth, height: value.target.clientHeight};
|
|
56
|
+
if (this.lastSize.width != size.width || this.lastSize.height != size.height) {
|
|
57
|
+
const logPrefix = `${this.toLog()}.hostOnSizeChanged()`;
|
|
58
|
+
this.logger.debug(`${logPrefix}`);
|
|
59
|
+
this.editor.setSize(this.host.clientWidth, this.host.clientHeight);
|
|
60
|
+
}
|
|
61
|
+
this.lastSize = size;
|
|
47
62
|
}
|
|
48
63
|
|
|
49
64
|
resizeEditor(w: number, h: number) {
|
|
50
65
|
this.editor.setSize(w, h);
|
|
51
66
|
}
|
|
52
67
|
}
|
|
53
|
-
|
|
54
|
-
export function buildWebEditorApp(view: HTMLDivElement): App {
|
|
55
|
-
org.helm.webeditor.MolViewer.molscale = 0.8;
|
|
56
|
-
const app = new org.helm.webeditor.App(view, {
|
|
57
|
-
showabout: false,
|
|
58
|
-
mexfontsize: '90%',
|
|
59
|
-
mexrnapinontab: true,
|
|
60
|
-
topmargin: 20,
|
|
61
|
-
mexmonomerstab: true,
|
|
62
|
-
sequenceviewonly: false,
|
|
63
|
-
mexfavoritefirst: true,
|
|
64
|
-
mexfilter: true
|
|
65
|
-
});
|
|
66
|
-
const sizes = app.calculateSizes();
|
|
67
|
-
app.canvas!.resize(sizes.rightwidth - 100, sizes.topheight - 210);
|
|
68
|
-
let s = {width: sizes.rightwidth - 100 + 'px', height: sizes.bottomheight + 'px'};
|
|
69
|
-
scil.apply(app.sequence.style, s);
|
|
70
|
-
scil.apply(app.notation!.style, s);
|
|
71
|
-
s = {width: sizes.rightwidth + 'px', height: (sizes.bottomheight + app.toolbarheight) + 'px'};
|
|
72
|
-
scil.apply(app.properties!.parent.style, s);
|
|
73
|
-
app.structureview!.resize(sizes.rightwidth, sizes.bottomheight + app.toolbarheight);
|
|
74
|
-
app.mex!.resize(sizes.topheight - 80);
|
|
75
|
-
|
|
76
|
-
return app;
|
|
77
|
-
}
|
package/src/package-utils.ts
CHANGED
|
@@ -5,6 +5,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
import {Unsubscribable} from 'rxjs';
|
|
6
6
|
|
|
7
7
|
import {delay, timeout} from '@datagrok-libraries/utils/src/test';
|
|
8
|
+
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
8
9
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
9
10
|
import {
|
|
10
11
|
DojoType, DojoxType, HweWindow, IOrgHelmWebEditor, Monomers
|
|
@@ -13,7 +14,6 @@ import {HelmServiceBase} from '@datagrok-libraries/bio/src/viewers/helm-service'
|
|
|
13
14
|
import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
|
|
14
15
|
import {LoggerWrapper} from '@datagrok-libraries/bio/src/utils/logger';
|
|
15
16
|
import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
16
|
-
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
17
17
|
|
|
18
18
|
import {HelmHelper} from './helm-helper';
|
|
19
19
|
import {HelmService} from './utils/helm-service';
|
|
@@ -31,7 +31,7 @@ type DojoConfigWindowType = {
|
|
|
31
31
|
dojoConfig: {
|
|
32
32
|
packages?: (string | { name: string, location: string })[],
|
|
33
33
|
deps?: string[], callback: Function, has?: any, parseOnLoad?: boolean, async?: boolean | string, locale?: string,
|
|
34
|
-
}
|
|
34
|
+
},
|
|
35
35
|
};
|
|
36
36
|
type HelmWindowType = {
|
|
37
37
|
$helmService?: HelmServiceBase,
|
|
@@ -51,7 +51,6 @@ export async function initHelmLoadAndPatchDojo(): Promise<void> {
|
|
|
51
51
|
/** get the text width in pixels */
|
|
52
52
|
const pi = DG.TaskBarProgressIndicator.create('Loading Helm Web Editor ...');
|
|
53
53
|
try {
|
|
54
|
-
await delay(2000);
|
|
55
54
|
const requireBackup = window.require;
|
|
56
55
|
|
|
57
56
|
// dojo.window','dojo.io.script','dojo.io.iframe','dojo.dom','dojox.gfx','dojox.gfx.svg','dojox.gfx.shape','dojox.charting'
|
|
@@ -107,9 +106,7 @@ export async function initHelmLoadAndPatchDojo(): Promise<void> {
|
|
|
107
106
|
'dijit/form/DropDownButton', 'dijit/layout/AccordionContainer', 'dijit/form/ComboButton',
|
|
108
107
|
'dijit/layout/StackController', 'dijit/layout/StackContainer',
|
|
109
108
|
],
|
|
110
|
-
(...args: any[]) => {
|
|
111
|
-
resolve();
|
|
112
|
-
});
|
|
109
|
+
(...args: any[]) => { resolve(); });
|
|
113
110
|
});
|
|
114
111
|
} finally {
|
|
115
112
|
// TODO: Check interference with NGL
|
|
@@ -180,9 +177,9 @@ export const helmJsonReplacer = (key: string, value: any): any => {
|
|
|
180
177
|
};
|
|
181
178
|
|
|
182
179
|
export class HelmPackage extends DG.Package {
|
|
183
|
-
public alertOriginal: (s: string) => void;
|
|
180
|
+
public alertOriginal: ((s: string) => void) | null = null;
|
|
184
181
|
public readonly helmHelper: HelmHelper;
|
|
185
|
-
public libHelper
|
|
182
|
+
public libHelper!: IMonomerLibHelper;
|
|
186
183
|
|
|
187
184
|
constructor(opts: { debug: boolean } = {debug: false}) {
|
|
188
185
|
super();
|
|
@@ -206,6 +203,8 @@ export class HelmPackage extends DG.Package {
|
|
|
206
203
|
|
|
207
204
|
// Alternatively load old bundles by package.json/sources
|
|
208
205
|
_package.logger.debug(`${logPrefix}, HelmWebEditor awaiting …`);
|
|
206
|
+
// require('../helm/JSDraw/Scilligence.JSDraw2.Lite-uncompressed');
|
|
207
|
+
// require('../helm/JSDraw/Pistoia.HELM-uncompressed');
|
|
209
208
|
require('../node_modules/@datagrok-libraries/helm-web-editor/dist/package.js');
|
|
210
209
|
await window.helmWebEditor$.initPromise;
|
|
211
210
|
_package.logger.debug(`${logPrefix}, HelmWebEditor loaded`);
|
|
@@ -234,7 +233,7 @@ export class HelmPackage extends DG.Package {
|
|
|
234
233
|
|
|
235
234
|
this.logger.debug(`${logPrefix}, this.getMonomerOriginal stored`);
|
|
236
235
|
|
|
237
|
-
this.helmHelper.
|
|
236
|
+
this.helmHelper.overrideMonomersFuncs(this.helmHelper.buildMonomersFuncsFromLib(this.monomerLib));
|
|
238
237
|
|
|
239
238
|
// @ts-ignore, intercept with proxy to observe access and usage
|
|
240
239
|
org.helm.webeditor.Monomers = new class {
|
|
@@ -281,20 +280,15 @@ export class HelmPackage extends DG.Package {
|
|
|
281
280
|
public get monomerLib(): IMonomerLib {
|
|
282
281
|
if (!this.libHelper)
|
|
283
282
|
throw new Error(`Helm: _package.libHelper is not initialized yet`);
|
|
284
|
-
return this.libHelper.
|
|
283
|
+
return this.libHelper.getMonomerLib();
|
|
285
284
|
}
|
|
286
285
|
|
|
287
|
-
private _monomerLibSub
|
|
288
|
-
|
|
289
|
-
async initMonomerLibHelper(): Promise<void> {
|
|
290
|
-
if (!!this.libHelper)
|
|
291
|
-
throw new Error(`Helm: _package.libHelper is initialized already`);
|
|
292
|
-
|
|
293
|
-
this.libHelper = await getMonomerLibHelper();
|
|
294
|
-
}
|
|
286
|
+
private _monomerLibSub?: Unsubscribable;
|
|
295
287
|
|
|
296
288
|
/** Requires both Bio & HELMWebEditor initialized */
|
|
297
|
-
|
|
289
|
+
initMonomerLib(libHelper: IMonomerLibHelper): void {
|
|
290
|
+
this.libHelper = libHelper;
|
|
291
|
+
|
|
298
292
|
const lib = this.monomerLib;
|
|
299
293
|
rewriteLibraries(lib); // initHelm()
|
|
300
294
|
this._monomerLibSub = lib.onChanged
|
|
@@ -306,7 +300,7 @@ export class HelmPackage extends DG.Package {
|
|
|
306
300
|
monomerLibOnChangedHandler(): void {
|
|
307
301
|
const logPrefix = `Helm: _package.monomerLibOnChangedHandler()`;
|
|
308
302
|
try {
|
|
309
|
-
const libSummary = this.monomerLib
|
|
303
|
+
const libSummary = this.monomerLib!.getSummaryObj();
|
|
310
304
|
const isLibEmpty = Object.keys(libSummary).length == 0;
|
|
311
305
|
const libSummaryLog = isLibEmpty ? 'empty' : Object.entries(libSummary)
|
|
312
306
|
.map(([pt, count]) => `${pt}: ${count}`)
|