@datagrok/helm 2.0.2 → 2.0.3
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/README.md +1 -1
- package/dist/package-test.js +2789 -32
- package/dist/package.js +411 -118
- package/helm/JSDraw/test.html +3 -0
- package/package.json +25 -20
- package/src/__jest__/remote.test.ts +4 -4
- package/src/__jest__/test-node.ts +3 -2
- package/src/package-test.ts +0 -1
- package/src/package.ts +269 -76
- package/src/tests/helm-tests.ts +32 -4
- package/{test-Helm-4f0c8bae6479-a2fd943e.html → test-Helm-4f0c8bae6479-d7a9fa45.html} +13 -7
- /package/{images → vendor}/helm-rendering.png +0 -0
package/helm/JSDraw/test.html
CHANGED
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
<script type="text/javascript">
|
|
16
16
|
dojo.ready(function () {
|
|
17
17
|
var jsd = new JSDraw("Div2", { width: 800, height: 400, skin: "w8", viewonly: true });
|
|
18
|
+
var mol = jsd.getMolfile();
|
|
19
|
+
var m = new JSDraw2.Mol();
|
|
20
|
+
console.log(JSDraw2.FormulaParser.getAtomStats(m.setMolfile(mol)));
|
|
18
21
|
});
|
|
19
22
|
</script>
|
|
20
23
|
</body>
|
package/package.json
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/helm",
|
|
3
|
-
"beta": false,
|
|
4
3
|
"friendlyName": "Helm",
|
|
5
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.3",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Oleksandra Serhiienko",
|
|
7
|
+
"email": "oserhiienko@datagrok.ai"
|
|
8
|
+
},
|
|
6
9
|
"description": "",
|
|
7
10
|
"dependencies": {
|
|
8
|
-
"datagrok-api": "^1.
|
|
9
|
-
"cash-dom": "
|
|
10
|
-
"dayjs": "
|
|
11
|
-
"@datagrok-libraries/utils": "^1.
|
|
12
|
-
"@datagrok-libraries/bio": "^3.
|
|
13
|
-
|
|
14
|
-
"typescript": "^4.4.2"
|
|
11
|
+
"datagrok-api": "^1.6.0",
|
|
12
|
+
"cash-dom": "^8.1.1",
|
|
13
|
+
"dayjs": "^1.10.6",
|
|
14
|
+
"@datagrok-libraries/utils": "^1.6.2",
|
|
15
|
+
"@datagrok-libraries/bio": "^3.1.1"
|
|
16
|
+
|
|
15
17
|
},
|
|
16
18
|
"sources": [
|
|
17
19
|
"css/helm.css",
|
|
@@ -21,21 +23,24 @@
|
|
|
21
23
|
"helm/JSDraw/Pistoia.HELM-uncompressed.js"
|
|
22
24
|
],
|
|
23
25
|
"devDependencies": {
|
|
24
|
-
"@typescript-eslint/eslint-plugin": "latest",
|
|
25
|
-
"@typescript-eslint/parser": "latest",
|
|
26
|
-
"eslint": "latest",
|
|
27
|
-
"eslint-config-google": "latest",
|
|
28
|
-
"ts-loader": "latest",
|
|
29
|
-
"typescript": "latest",
|
|
30
|
-
"webpack": "latest",
|
|
31
|
-
"webpack-cli": "latest",
|
|
32
26
|
"@types/jest": "^27.0.0",
|
|
33
27
|
"jest": "^27.0.0",
|
|
34
|
-
"jest-html-reporter": "^3.
|
|
28
|
+
"jest-html-reporter": "^3.6.0",
|
|
29
|
+
"path": "^0.12.7",
|
|
35
30
|
"puppeteer": "^13.7.0",
|
|
36
31
|
"ts-jest": "^27.0.0",
|
|
32
|
+
"ts-loader": "^9.2.6",
|
|
33
|
+
"typescript": "^4.4.4",
|
|
34
|
+
"webpack": "^5.59.1",
|
|
35
|
+
"webpack-cli": "^4.9.1",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "^5.11.0",
|
|
37
|
+
"@typescript-eslint/parser": "^5.11.0",
|
|
38
|
+
"eslint": "^8.18.0",
|
|
39
|
+
"eslint-config-google": "^0.14.0",
|
|
37
40
|
"@types/js-yaml": "^4.0.5",
|
|
38
|
-
"
|
|
41
|
+
"js-yaml": "^4.1.0",
|
|
42
|
+
"@types/node-fetch": "^2.6.2",
|
|
43
|
+
"node-fetch": "^2.6.7"
|
|
39
44
|
},
|
|
40
45
|
"scripts": {
|
|
41
46
|
"link-all": "npm link datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
|
|
@@ -51,7 +56,7 @@
|
|
|
51
56
|
"release-helm-public": "grok publish public --release",
|
|
52
57
|
"lint": "eslint \"./src/**/*.ts\"",
|
|
53
58
|
"lint-fix": "eslint \"./src/**/*.ts\" --fix",
|
|
54
|
-
"test": "
|
|
59
|
+
"test": "jest",
|
|
55
60
|
"test-dev": "set HOST=dev && jest",
|
|
56
61
|
"test-local": "set HOST=localhost && jest"
|
|
57
62
|
},
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as utils from './test-node';
|
|
6
6
|
import puppeteer from 'puppeteer';
|
|
7
7
|
|
|
8
|
-
const P_START_TIMEOUT: number =
|
|
8
|
+
const P_START_TIMEOUT: number = 3600000;
|
|
9
9
|
let browser: puppeteer.Browser;
|
|
10
10
|
let page: puppeteer.Page;
|
|
11
11
|
|
|
@@ -51,10 +51,10 @@ it('TEST', async () => {
|
|
|
51
51
|
let failReport = '';
|
|
52
52
|
for (let i = 0; i < df.rowCount; i++) {
|
|
53
53
|
if (cStatus.get(i)) {
|
|
54
|
-
passReport += `Test result : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
54
|
+
passReport += `Test result : Success : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
55
55
|
} else {
|
|
56
56
|
failed = true;
|
|
57
|
-
failReport += `Test result : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
57
|
+
failReport += `Test result : Failed : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
resolve({failReport, passReport, failed});
|
|
@@ -65,4 +65,4 @@ it('TEST', async () => {
|
|
|
65
65
|
console.log(r.passReport);
|
|
66
66
|
// @ts-ignore
|
|
67
67
|
expect(r.failed).checkOutput(false, r.failReport);
|
|
68
|
-
},
|
|
68
|
+
}, 3600000);
|
|
@@ -66,6 +66,7 @@ export async function getBrowserPage(puppeteer: any): Promise<{browser: any, pag
|
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
let page = await browser.newPage();
|
|
69
|
+
await page.setDefaultNavigationTimeout(0);
|
|
69
70
|
await page.goto(`${url}/oauth/`);
|
|
70
71
|
await page.setCookie({name: 'auth', value: token});
|
|
71
72
|
await page.evaluate((token: any) => {
|
|
@@ -73,8 +74,8 @@ export async function getBrowserPage(puppeteer: any): Promise<{browser: any, pag
|
|
|
73
74
|
}, token);
|
|
74
75
|
await page.goto(url);
|
|
75
76
|
try {
|
|
76
|
-
await page.waitForSelector('.grok-preloader');
|
|
77
|
-
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout:
|
|
77
|
+
await page.waitForSelector('.grok-preloader', { timeout: 1800000 });
|
|
78
|
+
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout: 3600000});
|
|
78
79
|
} catch (error) {
|
|
79
80
|
throw error;
|
|
80
81
|
}
|
package/src/package-test.ts
CHANGED
|
@@ -11,7 +11,6 @@ export {tests};
|
|
|
11
11
|
//input: string category {optional: true}
|
|
12
12
|
//input: string test {optional: true}
|
|
13
13
|
//output: dataframe result
|
|
14
|
-
//top-menu: Tools | Dev | JS API Tests
|
|
15
14
|
export async function test(category: string, test: string): Promise<DG.DataFrame> {
|
|
16
15
|
const data = await runTests({category, test});
|
|
17
16
|
return DG.DataFrame.fromObjects(data)!;
|
package/src/package.ts
CHANGED
|
@@ -2,17 +2,15 @@
|
|
|
2
2
|
import * as grok from 'datagrok-api/grok';
|
|
3
3
|
import * as ui from 'datagrok-api/ui';
|
|
4
4
|
import * as DG from 'datagrok-api/dg';
|
|
5
|
-
//import {lru} from '../../Bio/src/utils/cell-renderer';
|
|
6
5
|
import {NotationConverter} from '@datagrok-libraries/bio/src/utils/notation-converter';
|
|
7
|
-
import {NOTATION} from '@datagrok-libraries/bio/src/utils/units-handler';
|
|
8
|
-
import {WebLogo} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
9
6
|
import {createJsonMonomerLibFromSdf} from './utils';
|
|
10
7
|
import {MONOMER_MANAGER_MAP, RGROUPS, RGROUP_CAP_GROUP_NAME, RGROUP_LABEL, SMILES} from './constants';
|
|
11
|
-
|
|
8
|
+
import {printLeftOrCentered} from '@datagrok-libraries/bio/src/utils/cell-renderer';
|
|
12
9
|
|
|
13
10
|
export const _package = new DG.Package();
|
|
14
11
|
|
|
15
12
|
const lru = new DG.LruCache<any, any>();
|
|
13
|
+
const molfiles = new DG.LruCache<any, any>();
|
|
16
14
|
const STORAGE_NAME = 'Libraries';
|
|
17
15
|
let i = 0;
|
|
18
16
|
const LIB_PATH = 'libraries/';
|
|
@@ -25,22 +23,24 @@ export async function initHelm(): Promise<void> {
|
|
|
25
23
|
await monomerManager(await grok.dapi.userDataStorage.getValue(STORAGE_NAME, j.toString(), true));
|
|
26
24
|
}
|
|
27
25
|
grid.invalidate();
|
|
26
|
+
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
dojo.ready(function() { resolve(null); });
|
|
30
|
+
});
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
//name:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
//name: helmCellRenderer
|
|
34
|
+
//tags: cellRenderer
|
|
35
|
+
//meta.cellType: helm
|
|
36
|
+
//meta.columnTags: units=helm
|
|
37
|
+
//output: grid_cell_renderer result
|
|
38
|
+
export function helmCellRenderer(): HelmCellRenderer {
|
|
39
|
+
return new HelmCellRenderer();
|
|
33
40
|
}
|
|
34
41
|
|
|
35
|
-
//name: getLru
|
|
36
|
-
export async function getLru() {
|
|
37
|
-
return await grok.functions.call('Bio:Lru');
|
|
38
|
-
}
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
//description: Macromolecule
|
|
42
|
-
//input: grid_cell cell
|
|
43
|
-
export function editMoleculeCell(cell: DG.GridCell): void {
|
|
43
|
+
export function webEditor(value: string) {
|
|
44
44
|
let view = ui.div();
|
|
45
45
|
org.helm.webeditor.MolViewer.molscale = 0.8;
|
|
46
46
|
let app = new scil.helm.App(view, {
|
|
@@ -65,55 +65,72 @@ export function editMoleculeCell(cell: DG.GridCell): void {
|
|
|
65
65
|
scil.apply(app.properties.parent.style, s);
|
|
66
66
|
app.structureview.resize(sizes.rightwidth, sizes.bottomheight + app.toolbarheight);
|
|
67
67
|
app.mex.resize(sizes.topheight - 80);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
cell.cell.value;
|
|
90
|
-
}).show({modal: true, fullScreen: true});
|
|
68
|
+
setTimeout(function() {
|
|
69
|
+
app.canvas.helm.setSequence(value, 'HELM');
|
|
70
|
+
}, 200);
|
|
71
|
+
//@ts-ignore
|
|
72
|
+
ui.dialog({showHeader: false, showFooter: true})
|
|
73
|
+
.add(view)
|
|
74
|
+
.onOK(() => {
|
|
75
|
+
const val = app.canvas.getHelm(true).replace(/<\/span>/g, '').replace(/<span style='background:#bbf;'>/g, '');
|
|
76
|
+
value = val;
|
|
77
|
+
}).show({modal: true, fullScreen: true});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
//tags: cellEditor
|
|
82
|
+
//description: Macromolecule
|
|
83
|
+
//input: grid_cell cell
|
|
84
|
+
export function editMoleculeCell(cell: DG.GridCell): void {
|
|
85
|
+
if (cell.gridColumn.column.tags[DG.TAGS.UNITS] === 'helm') {
|
|
86
|
+
let grid = grok.shell.tv.grid;
|
|
87
|
+
webEditor(cell.cell.value);
|
|
88
|
+
grid.invalidate();
|
|
91
89
|
}
|
|
92
90
|
}
|
|
93
91
|
|
|
94
|
-
//name:
|
|
92
|
+
//name: Open Helm Web Editor
|
|
93
|
+
//description: Adds editor
|
|
94
|
+
//meta.action: Open Helm Web Editor
|
|
95
|
+
//input: string mol { semType: Macromolecule }
|
|
96
|
+
export function openEditor(mol: string): void {
|
|
97
|
+
let df = grok.shell.tv.grid.dataFrame;
|
|
98
|
+
let converter = new NotationConverter(df.columns.bySemType('Macromolecule'));
|
|
99
|
+
const resStr = converter.convertStringToHelm(mol, '/');
|
|
100
|
+
webEditor(resStr);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
//name: Properties
|
|
95
104
|
//tags: panel, widgets
|
|
96
105
|
//input: string helmString {semType: Macromolecule}
|
|
97
106
|
//output: widget result
|
|
98
|
-
export async function
|
|
99
|
-
const lru = await getLru();
|
|
107
|
+
export async function propertiesPanel(helmString: string) {
|
|
108
|
+
//const lru = await getLru();
|
|
100
109
|
const result = lru.get(helmString).split(',');
|
|
101
110
|
return new DG.Widget(
|
|
102
111
|
ui.tableFromMap({
|
|
103
112
|
'formula': result[0].replace(/<sub>/g, '').replace(/<\/sub>/g, ''),
|
|
104
113
|
'molecular weight': result[1],
|
|
105
114
|
'extinction coefficient': result[2],
|
|
106
|
-
'
|
|
107
|
-
'fasta': ui.wait(async () => ui.divText(await helmToFasta(helmString))),
|
|
115
|
+
/*'fasta': ui.wait(async () => ui.divText(await helmToFasta(helmString))),
|
|
108
116
|
'rna analogue sequence': ui.wait(async () => ui.divText(await helmToRNA(helmString))),
|
|
109
117
|
'smiles': ui.wait(async () => ui.divText(await helmToSmiles(helmString))),
|
|
110
|
-
//'peptide analogue sequence': ui.wait(async () => ui.divText(await helmToPeptide(helmString)))
|
|
118
|
+
//'peptide analogue sequence': ui.wait(async () => ui.divText(await helmToPeptide(helmString))),*/
|
|
111
119
|
})
|
|
112
120
|
);
|
|
113
121
|
}
|
|
114
122
|
|
|
123
|
+
//name: Molfile
|
|
124
|
+
//tags: panel, widgets
|
|
125
|
+
//input: string helmString {semType: Macromolecule}
|
|
126
|
+
//output: widget result
|
|
127
|
+
export async function molfilePanel(helmString: string) {
|
|
128
|
+
return ui.textInput('', await getMolfile(helmString));
|
|
129
|
+
}
|
|
130
|
+
|
|
115
131
|
|
|
116
|
-
|
|
132
|
+
//name: loadDialog
|
|
133
|
+
export async function loadDialog() {
|
|
117
134
|
let res = (await _package.files.list(`${LIB_PATH}`, false, '')).map(it => it.fileName);
|
|
118
135
|
let FilesList = await ui.choiceInput('Monomer Libraries', ' ', res);
|
|
119
136
|
let grid = grok.shell.tv.grid;
|
|
@@ -159,7 +176,7 @@ export async function libraryPanel(helmColumn: DG.Column) {
|
|
|
159
176
|
}
|
|
160
177
|
|
|
161
178
|
//name: manageFiles
|
|
162
|
-
function manageFiles() {
|
|
179
|
+
export async function manageFiles() {
|
|
163
180
|
const a = ui.dialog({title: 'Manage files'})
|
|
164
181
|
//@ts-ignore
|
|
165
182
|
.add(ui.fileBrowser({path: 'System:AppData/Helm/libraries'}).root)
|
|
@@ -167,6 +184,8 @@ function manageFiles() {
|
|
|
167
184
|
.show();
|
|
168
185
|
}
|
|
169
186
|
|
|
187
|
+
|
|
188
|
+
|
|
170
189
|
async function accessServer(url: string, key: string) {
|
|
171
190
|
const params: RequestInit = {
|
|
172
191
|
method: 'GET',
|
|
@@ -238,12 +257,22 @@ function getRS(smiles: string) {
|
|
|
238
257
|
return res;
|
|
239
258
|
}
|
|
240
259
|
|
|
241
|
-
|
|
260
|
+
//name: monomerManager
|
|
261
|
+
//input: string value
|
|
262
|
+
export async function monomerManager(value: string) {
|
|
242
263
|
let df: any[];
|
|
264
|
+
let file;
|
|
265
|
+
let dfSdf;
|
|
243
266
|
if (value.endsWith('.sdf')) {
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
267
|
+
const funcList: DG.Func[] = DG.Func.find({package: 'Chem', name: 'importSdf'});
|
|
268
|
+
console.debug(`Helm: initHelm() funcList.length = ${funcList.length}`);
|
|
269
|
+
if (funcList.length === 1) {
|
|
270
|
+
file = await _package.files.readAsBytes(`${LIB_PATH}${value}`);
|
|
271
|
+
dfSdf = await grok.functions.call('Chem:importSdf', {bytes: file});
|
|
272
|
+
df = createJsonMonomerLibFromSdf(dfSdf[0]);
|
|
273
|
+
} else {
|
|
274
|
+
grok.shell.warning("Chem package is not installed");
|
|
275
|
+
}
|
|
247
276
|
} else {
|
|
248
277
|
const file = await _package.files.readAsText(`${LIB_PATH}${value}`);
|
|
249
278
|
df = JSON.parse(file);
|
|
@@ -275,28 +304,161 @@ export function helmColumnToSmiles(helmColumn: DG.Column) {
|
|
|
275
304
|
//todo: add column with smiles to col.dataFrame.
|
|
276
305
|
}
|
|
277
306
|
|
|
307
|
+
//name: getMolfile
|
|
308
|
+
//input: string helmString {semType: Macromolecule}
|
|
309
|
+
export async function getMolfile(helmString) {
|
|
310
|
+
return molfiles.get(helmString);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function split(s: string, sep: string) {
|
|
314
|
+
var ret = [];
|
|
315
|
+
var frag = "";
|
|
316
|
+
var parentheses = 0;
|
|
317
|
+
var bracket = 0;
|
|
318
|
+
var braces = 0;
|
|
319
|
+
var quote = 0;
|
|
320
|
+
for (var i = 0; i < s.length; ++i) {
|
|
321
|
+
var c = s.substring(i, i + 1);
|
|
322
|
+
if (c == sep && bracket == 0 && parentheses == 0 && braces == 0 && quote == 0) {
|
|
323
|
+
ret.push(frag);
|
|
324
|
+
frag = "";
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
frag += c;
|
|
328
|
+
if (quote > 0) {
|
|
329
|
+
if (c == '\\' && i + 1 < s.length) {
|
|
330
|
+
++i;
|
|
331
|
+
var c2 = s.substring(i, i + 1);
|
|
332
|
+
frag += c2;
|
|
333
|
+
c += c2;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (c == '\"') {
|
|
337
|
+
if (!(i > 0 && s.substring(i - 1, i) == '\\'))
|
|
338
|
+
quote = quote == 0 ? 1 : 0;
|
|
339
|
+
}
|
|
340
|
+
else if (c == '[')
|
|
341
|
+
++bracket;
|
|
342
|
+
else if (c == ']')
|
|
343
|
+
--bracket;
|
|
344
|
+
else if (c == '(')
|
|
345
|
+
++parentheses;
|
|
346
|
+
else if (c == ')')
|
|
347
|
+
--parentheses;
|
|
348
|
+
else if (c == '{')
|
|
349
|
+
++braces;
|
|
350
|
+
else if (c == '}')
|
|
351
|
+
--braces;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
ret.push(frag);
|
|
355
|
+
return ret;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function detachAnnotation(s: string) {
|
|
359
|
+
var ret = _detachAppendix(s, '\"');
|
|
360
|
+
if (ret.tag != null)
|
|
361
|
+
return ret;
|
|
362
|
+
|
|
363
|
+
var r = _detachAppendix(s, '\'');
|
|
364
|
+
return { tag: ret.tag, repeat: r.tag, str: r.str };
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function _detachAppendix(s: string, c: string) {
|
|
368
|
+
var tag = null;
|
|
369
|
+
//@ts-ignore
|
|
370
|
+
if (scil.Utils.endswith(s, c)) {
|
|
371
|
+
var p = s.length - 1;
|
|
372
|
+
while (p > 0) {
|
|
373
|
+
p = s.lastIndexOf(c, p - 1);
|
|
374
|
+
if (p <= 0 || s.substring(p - 1, p) != '\\')
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (p > 0 && p < s.length - 1) {
|
|
379
|
+
tag = s.substring(p + 1, s.length - 1);
|
|
380
|
+
s = s.substring(0, p);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (tag != null)
|
|
384
|
+
tag = tag.replace(new RegExp("\\" + c, "g"), c);
|
|
385
|
+
return { tag: unescape(tag), str: s };
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function unescape(s: string) {
|
|
389
|
+
//@ts-ignore
|
|
390
|
+
if (scil.Utils.isNullOrEmpty(s))
|
|
391
|
+
return s;
|
|
392
|
+
|
|
393
|
+
return s.replace(/[\\]./g, function (m) {
|
|
394
|
+
switch (m) {
|
|
395
|
+
case "\\r":
|
|
396
|
+
return "\r";
|
|
397
|
+
case "\\n":
|
|
398
|
+
return "\n";
|
|
399
|
+
case "\\t":
|
|
400
|
+
return "\t";
|
|
401
|
+
default:
|
|
402
|
+
return m.substring(1);
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function parseHelm(s: string) {
|
|
408
|
+
var sections = split(s, '$');
|
|
409
|
+
s = sections[0];
|
|
410
|
+
var monomers = [];
|
|
411
|
+
//@ts-ignore
|
|
412
|
+
if (!scil.Utils.isNullOrEmpty(s)) {
|
|
413
|
+
var seqs = split(s, '|');
|
|
414
|
+
for (var i = 0; i < seqs.length; ++i) {
|
|
415
|
+
var e = detachAnnotation(seqs[i]);
|
|
416
|
+
s = e.str;
|
|
417
|
+
|
|
418
|
+
var p = s.indexOf("{");
|
|
419
|
+
|
|
420
|
+
s = s.substring(p + 1);
|
|
421
|
+
p = s.indexOf('}');
|
|
422
|
+
s = s.substring(0, p);
|
|
423
|
+
|
|
424
|
+
var ss = split(s, '.');
|
|
425
|
+
for (var monomer of ss) {
|
|
426
|
+
if (monomer.includes('(') && monomer.includes(')')) {
|
|
427
|
+
var elements = monomer.replace(/[()]/g, "").split("");
|
|
428
|
+
for (var el of elements) {
|
|
429
|
+
monomers.push(el);
|
|
430
|
+
}
|
|
431
|
+
} else {
|
|
432
|
+
monomers.push(monomer);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return monomers;
|
|
438
|
+
}
|
|
439
|
+
|
|
278
440
|
//name: findMonomers
|
|
279
|
-
//input: string helmString
|
|
280
|
-
export
|
|
441
|
+
//input: string helmString
|
|
442
|
+
export function findMonomers(helmString: string) {
|
|
443
|
+
//@ts-ignore
|
|
281
444
|
const types = Object.keys(org.helm.webeditor.monomerTypeList());
|
|
282
|
-
const monomers = [];
|
|
283
|
-
const
|
|
284
|
-
for (
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
monomerNames.push(monomers[i][k].id);
|
|
445
|
+
const monomers: any = [];
|
|
446
|
+
const monomer_names: any = [];
|
|
447
|
+
for (var i = 0; i < types.length; i++) {
|
|
448
|
+
//@ts-ignore
|
|
449
|
+
monomers.push(new scil.helm.Monomers.getMonomerSet(types[i]));
|
|
450
|
+
Object.keys(monomers[i]).forEach(k => {
|
|
451
|
+
monomer_names.push(monomers[i][k].id);
|
|
290
452
|
});
|
|
291
453
|
}
|
|
292
|
-
const
|
|
293
|
-
return new Set(
|
|
454
|
+
const split_string = parseHelm(helmString);
|
|
455
|
+
return new Set(split_string.filter(val => !monomer_names.includes(val)));
|
|
294
456
|
}
|
|
295
457
|
|
|
296
458
|
class HelmCellRenderer extends DG.GridCellRenderer {
|
|
297
|
-
get name() { return '
|
|
459
|
+
get name() { return 'helm'; }
|
|
298
460
|
|
|
299
|
-
get cellType() { return '
|
|
461
|
+
get cellType() { return 'helm'; }
|
|
300
462
|
|
|
301
463
|
get defaultWidth(): number | null { return 400; }
|
|
302
464
|
|
|
@@ -305,18 +467,49 @@ class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
305
467
|
render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
|
|
306
468
|
gridCell: DG.GridCell, cellStyle: DG.GridCellStyle
|
|
307
469
|
) {
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
470
|
+
const grid = gridCell.gridRow !== -1 ? gridCell.grid : undefined;
|
|
471
|
+
const undefinedColor = 'rgb(100,100,100)';
|
|
472
|
+
const grayColor = '#808080';
|
|
473
|
+
const monomers = findMonomers(gridCell.cell.value);
|
|
474
|
+
if (monomers.size == 0) {
|
|
475
|
+
const host = ui.div([], {style: {width: `${w}px`, height: `${h}px`}});
|
|
476
|
+
host.setAttribute('dataformat', 'helm');
|
|
477
|
+
host.setAttribute('data', gridCell.cell.value);
|
|
478
|
+
gridCell.element = host;
|
|
479
|
+
//@ts-ignore
|
|
480
|
+
const canvas = new JSDraw2.Editor(host, {width: w, height: h, skin: 'w8', viewonly: true});
|
|
481
|
+
const formula = canvas.getFormula(true);
|
|
482
|
+
if (!formula) {
|
|
483
|
+
gridCell.element = ui.divText(gridCell.cell.value, {style: {color: 'red'}});
|
|
484
|
+
}
|
|
485
|
+
const molWeight = Math.round(canvas.getMolWeight() * 100) / 100;
|
|
486
|
+
const coef = Math.round(canvas.getExtinctionCoefficient(true) * 100) / 100;
|
|
487
|
+
const molfile = canvas.getMolfile();
|
|
488
|
+
const result = formula + ', ' + molWeight + ', ' + coef;
|
|
489
|
+
lru.set(gridCell.cell.value, result);
|
|
490
|
+
molfiles.set(gridCell.cell.value, molfile);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
if (monomers.size > 0) {
|
|
494
|
+
w = grid ? Math.min(grid.canvas.width - x, w) : g.canvas.width - x;
|
|
495
|
+
g.save();
|
|
496
|
+
g.beginPath();
|
|
497
|
+
g.rect(x, y, w, h);
|
|
498
|
+
g.clip();
|
|
499
|
+
g.font = '12px monospace';
|
|
500
|
+
g.textBaseline = 'top';
|
|
501
|
+
let x1 = x;
|
|
502
|
+
const s: string = gridCell.cell.value ?? '';
|
|
503
|
+
let subParts: string[] = parseHelm(s);
|
|
504
|
+
subParts.forEach((amino, index) => {
|
|
505
|
+
let color = monomers.has(amino) ? 'red' : grayColor;
|
|
506
|
+
g.fillStyle = undefinedColor;
|
|
507
|
+
let last = index === subParts.length - 1;
|
|
508
|
+
x1 = printLeftOrCentered(x1, y, w, h, g, amino, color, 0, true, 1.0, '/', last);
|
|
509
|
+
});
|
|
510
|
+
g.restore();
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
320
513
|
}
|
|
321
514
|
}
|
|
322
515
|
|
package/src/tests/helm-tests.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {before, category, expect, test} from '@datagrok-libraries/utils/src/test';
|
|
2
|
-
import {helmToFasta, helmToPeptide, helmToRNA} from '../package';
|
|
1
|
+
import {after, before, category, delay, expect, test} from '@datagrok-libraries/utils/src/test';
|
|
2
|
+
//import {findMonomers, helmToFasta, helmToPeptide, helmToRNA, initHelm} from '../package';
|
|
3
3
|
import {_package} from '../package-test';
|
|
4
|
+
import {loadDialog, manageFiles, monomerManager} from '../package';
|
|
4
5
|
import * as DG from 'datagrok-api/dg';
|
|
5
6
|
import * as grok from 'datagrok-api/grok';
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
category('Helm', () => {
|
|
9
|
-
|
|
10
|
-
// These tests require webservice that is not present on test stand
|
|
10
|
+
//These tests require webservice that is not present on test stand
|
|
11
11
|
// test('helmToFasta', async () => {
|
|
12
12
|
// expect(await helmToFasta('RNA1{R(U)P.R(T)P.R(G)P.R(C)P.R(A)}$$$$'), '>RNA1UTGCA');
|
|
13
13
|
// expect(await helmToFasta('RNA1{P.R(U).P.R(T)}$$$$'), '>RNA1UT');
|
|
@@ -45,4 +45,32 @@ category('Helm', () => {
|
|
|
45
45
|
// await grok.data.detectSemanticTypes(df);
|
|
46
46
|
// expect(col.tags[DG.TAGS.UNITS], 'HELM');
|
|
47
47
|
// });
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
test('manageFiles', async () => {
|
|
51
|
+
return await manageFiles();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('loadDialog', async() => {
|
|
55
|
+
return await grok.functions.call('Helm:loadDialog');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('monomerManager', async() => {
|
|
59
|
+
await grok.functions.call('Helm:monomerManager', {value: 'HELMCoreLibrary.json'});
|
|
60
|
+
const checkName = '2-Chloroadenine';
|
|
61
|
+
let flag = false;
|
|
62
|
+
const types = Object.keys(org.helm.webeditor.monomerTypeList());
|
|
63
|
+
const monomers: any = [];
|
|
64
|
+
for (var i = 0; i < types.length; i++) {
|
|
65
|
+
//@ts-ignore
|
|
66
|
+
monomers.push(new scil.helm.Monomers.getMonomerSet(types[i]));
|
|
67
|
+
Object.keys(monomers[i]).forEach(k => {
|
|
68
|
+
if (monomers[i][k].n == checkName){
|
|
69
|
+
flag = true;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
expect(flag, true);
|
|
74
|
+
});
|
|
75
|
+
|
|
48
76
|
});
|