@datagrok/helm 0.0.4 → 1.0.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/package.json CHANGED
@@ -1,48 +1,52 @@
1
1
  {
2
- "name": "@datagrok/helm",
3
- "beta": false,
4
- "friendlyName": "Helm",
5
- "version": "0.0.4",
6
- "description": "",
7
- "dependencies": {
8
- "datagrok-api": "latest",
2
+ "name": "@datagrok/helm",
3
+ "beta": false,
4
+ "friendlyName": "Helm",
5
+ "version": "1.0.1",
6
+ "description": "",
7
+ "dependencies": {
8
+ "datagrok-api": "latest",
9
9
  "cash-dom": "latest",
10
10
  "dayjs": "latest",
11
- "@datagrok-libraries/utils": "latest"
12
- },
13
- "sources": [
14
- "css/helm.css",
15
- "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js",
16
- "helm/JSDraw/Scilligence.JSDraw2.Lite.js",
17
- "helm/JSDraw/Scilligence.JSDraw2.Resources.js",
18
- "helm/JSDraw/Pistoia.HELM-uncompressed.js"
19
- ],
20
- "devDependencies": {
21
- "webpack": "latest",
22
- "webpack-cli": "latest",
23
- "ts-loader": "latest",
24
- "typescript": "latest"
25
- },
26
- "scripts": {
27
- "link-all": "",
28
- "debug-helm": "webpack && grok publish ",
29
- "release-helm": "webpack && grok publish --release",
30
- "build-helm": "webpack",
31
- "build": "webpack",
32
- "debug-helm-dev": "grok publish dev --rebuild",
33
- "release-helm-dev": "grok publish dev --rebuild --release",
34
- "debug-helm-public": "grok publish public --rebuild",
35
- "release-helm-public": "grok publish public --rebuild --release"
36
- },
37
- "canEdit": [
38
- "Developers"
39
- ],
40
- "canView": [
41
- "All users"
42
- ],
43
- "repository": {
44
- "type": "git",
45
- "url": "https://github.com/datagrok-ai/public.git",
46
- "directory": "packages/Helm"
47
- }
11
+ "@datagrok-libraries/utils": "latest",
12
+ "@datagrok-libraries/bio": "^2.8.2",
13
+ "ts-loader": "^9.2.5",
14
+ "typescript": "^4.4.2"
15
+ },
16
+ "sources": [
17
+ "css/helm.css",
18
+ "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js",
19
+ "helm/JSDraw/Scilligence.JSDraw2.Lite.js",
20
+ "helm/JSDraw/Scilligence.JSDraw2.Resources.js",
21
+ "helm/JSDraw/Pistoia.HELM-uncompressed.js"
22
+ ],
23
+ "devDependencies": {
24
+ "webpack": "latest",
25
+ "webpack-cli": "latest",
26
+ "ts-loader": "latest",
27
+ "typescript": "latest"
28
+ },
29
+ "scripts": {
30
+ "link-all": "npm link datagrok-api @datagrok-libraries/utils",
31
+ "debug-helm": "webpack && grok publish ",
32
+ "release-helm": "webpack && grok publish --release",
33
+ "build-helm": "webpack",
34
+ "build": "webpack",
35
+ "debug-helm-dev": "grok publish dev --rebuild",
36
+ "release-helm-dev": "grok publish dev --rebuild --release",
37
+ "debug-helm-public": "grok publish public --rebuild",
38
+ "release-helm-public": "grok publish public --rebuild --release"
39
+ },
40
+ "canEdit": [
41
+ "Developers"
42
+ ],
43
+ "canView": [
44
+ "All users"
45
+ ],
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/datagrok-ai/public.git",
49
+ "directory": "packages/Helm"
50
+ },
51
+ "category": "Bioinformatics"
48
52
  }
@@ -1,13 +1,18 @@
1
1
  import * as DG from "datagrok-api/dg";
2
2
  import * as grok from "datagrok-api/grok";
3
3
  import {runTests, tests} from '@datagrok-libraries/utils/src/test';
4
+ import './tests/helm-tests.ts'
5
+
6
+ export const _package = new DG.Package();
7
+ export {tests};
4
8
 
5
- export let _package = new DG.Package();
6
- export {tests}
7
9
 
8
10
  //name: test
11
+ //input: string category {optional: true}
12
+ //input: string test {optional: true}
9
13
  //output: dataframe result
10
- export async function test(): Promise<DG.DataFrame> {
11
- let data = await runTests();
14
+ //top-menu: Tools | Dev | JS API Tests
15
+ export async function test(category: string, test: string): Promise<DG.DataFrame> {
16
+ const data = await runTests({category, test});
12
17
  return DG.DataFrame.fromObjects(data)!;
13
- }
18
+ }
package/src/package.ts CHANGED
@@ -2,9 +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
+ import {NotationConverter, NOTATION} from '@datagrok-libraries/bio/src/utils/notation-converter';
7
+ //import {ConverterFunc, DfReaderFunc} from '../../Bio/src/tests/types';
5
8
 
6
9
  export const _package = new DG.Package();
7
10
 
11
+ const lru = new DG.LruCache<any, any>();
12
+
13
+
8
14
 
9
15
  //tags: init
10
16
  export async function initChem(): Promise<void> {
@@ -15,73 +21,217 @@ export async function initChem(): Promise<void> {
15
21
  });
16
22
  }
17
23
 
18
-
19
- //name: helmCellRenderer
20
- //tags: cellRenderer,cellRenderer-HELM
21
- //meta.cellType: HELM
22
- //meta-cell-renderer-sem-type: HELM
23
- //output: grid_cell_renderer result
24
- export function helmCellRenderer(): DG.GridCellRenderer {
25
- return new HelmCellRenderer();
26
- }
27
-
28
24
  //tags: cellEditor
29
- //description: HELM
25
+ //description: Macromolecule
30
26
  //input: grid_cell cell
31
27
  export function editMoleculeCell(cell: DG.GridCell): void {
32
28
  let view = ui.div();
33
- let app: { canvas: { helm: { setSequence: (arg0: any, arg1: string) => void; }; }; };
34
- setTimeout(function () {
29
+ org.helm.webeditor.MolViewer.molscale = 0.8;
30
+ let app = new scil.helm.App(view, { showabout: false, mexfontsize: "90%", mexrnapinontab: true, topmargin: 20, mexmonomerstab: true, sequenceviewonly: false, mexfavoritefirst: true, mexfilter: true });
31
+ var sizes = app.calculateSizes();
32
+ app.canvas.resize(sizes.rightwidth, sizes.topheight - 210);
33
+ var s = { width: sizes.rightwidth + "px", height: sizes.bottomheight + "px" };
34
+ //@ts-ignore
35
+ scil.apply(app.sequence.style, s);
36
+ //@ts-ignore
37
+ scil.apply(app.notation.style, s);
38
+ s = { width: sizes.rightwidth + "px", height: (sizes.bottomheight + app.toolbarheight) + "px" };
39
+ //@ts-ignore
40
+ scil.apply(app.properties.parent.style, s);
41
+ app.structureview.resize(sizes.rightwidth, sizes.bottomheight + app.toolbarheight);
42
+ app.mex.resize(sizes.topheight - 80);
43
+ if (cell.gridColumn.column.tags[DG.TAGS.UNITS] === "HELM"){
44
+ setTimeout(function() {
45
+ app.canvas.helm.setSequence(cell.cell.value , 'HELM');
46
+ }, 200);
35
47
  //@ts-ignore
36
- org.helm.webeditor.MolViewer.molscale = 0.8;
37
- //@ts-ignore
38
- app = new scil.helm.App(view, { showabout: false, mexfontsize: "90%", mexrnapinontab: true, topmargin: 20, mexmonomerstab: true, sequenceviewonly: false, mexfavoritefirst: true, mexfilter: true });
39
- });
40
- setTimeout(function() {
48
+ ui.dialog({ showHeader: false, showFooter: true })
49
+ .add(view)
50
+ .onOK(() => {
51
+ cell.cell.value = app.canvas.getHelm(true);
52
+ }).show({ modal: true, fullScreen: true});
53
+ }
54
+ else if (cell.gridColumn.column.tags[DG.TAGS.UNITS] === "fasta:SEQ:PT") {
55
+ const converter = new NotationConverter(cell.gridColumn.column);
56
+ const resStr = converter.convertFastaStringToHelm(null, null, cell.cell.value);
57
+ setTimeout(function() {
58
+ app.canvas.helm.setSequence(resStr , 'HELM');
59
+ }, 200);
41
60
  //@ts-ignore
42
- app.canvas.helm.setSequence(cell.cell.value , 'HELM');
43
- }, 200);
44
-
45
- let dlg = ui.dialog()
46
- .add(view)
47
- .onOK(() => {
48
- view;
49
- }).show({ modal: true, fullScreen: true});
50
- dlg.root.children[0].remove();
51
- dlg.root.children[1].classList.remove('ui-panel');
52
- dlg.root.children[1].classList.remove('ui-box');
61
+ ui.dialog({ showHeader: false, showFooter: true })
62
+ .add(view)
63
+ .onOK(() => {
64
+ cell.cell.value;
65
+ }).show({ modal: true, fullScreen: true});
66
+ }
67
+ }
68
+
69
+ //name: Details
70
+ //tags: panel, widgets
71
+ //input: string helmString {semType: Macromolecule}
72
+ //output: widget result
73
+ export function detailsPanel(helmString: string){
74
+ //return new DG.Widget(ui.divText(lru.get(helmString)));
75
+ var result = lru.get(helmString).split(',');
76
+ return new DG.Widget(
77
+ ui.tableFromMap({
78
+ 'formula': result[0].replace(/<sub>/g, '').replace(/<\/sub>/g, ''),
79
+ 'molecular weight': result[1],
80
+ 'extinction coefficient': result[2],
81
+ 'molfile': result[3],
82
+ 'fasta': ui.wait(async () => ui.divText(await helmToFasta(helmString))),
83
+ 'rna analogue sequence': ui.wait(async () => ui.divText(await helmToRNA(helmString))),
84
+ 'smiles': ui.wait(async () => ui.divText(await helmToSmiles(helmString))),
85
+ //'peptide analogue sequence': ui.wait(async () => ui.divText(await helmToPeptide(helmString))),
86
+ })
87
+ )
88
+ }
89
+
90
+
91
+ async function loadDialog () {
92
+ //@ts-ignore
93
+ let res = await grok.dapi.files.list('System:AppData/Helm', false, '');
94
+ //@ts-ignore
95
+ res = res.map((e) => e.path);
96
+ //@ts-ignore
97
+ let FilesList = await ui.choiceInput('Monomer Libraries', ' ', res);
98
+ let grid = grok.shell.tv.grid;
99
+ ui.dialog('Load library from file')
100
+ .add(FilesList)
101
+ .onOK(async () => {
102
+ await monomerManager(FilesList.value);
103
+ grid.invalidate()
104
+ }).show();
105
+ };
106
+
107
+ //name: Library
108
+ //tags: panel, widgets
109
+ //input: string helmString {semType: Macromolecule}
110
+ //output: widget result
111
+ export function libraryPanel(helmString: string) {
112
+ //@ts-ignore
113
+ let loadButton = ui.button('Load Library');
114
+ loadButton.addEventListener('click', loadDialog);
115
+ return new DG.Widget(ui.divH([loadButton]));
116
+ }
117
+
118
+ async function accessServer(url: string, key: string) {
119
+ const params: RequestInit = {
120
+ method: 'GET',
121
+ headers: {
122
+ 'Accept': 'application/json',
123
+ }
124
+ };
125
+ const response = await fetch(url, params);
126
+ const json = await response.json();
127
+ return json[key];
128
+ }
129
+
130
+
131
+ //name: helmToFasta
132
+ //input: string helmString {semType: Macromolecule}
133
+ //output: string res
134
+ export async function helmToFasta(helmString: string) {
135
+ const url = `http://localhost:8081/WebService/service/Fasta/Produce/${helmString}`
136
+ return await accessServer(url, 'FastaFile');
137
+ }
138
+
139
+ //name: helmToRNA
140
+ //description: converts to rna analogue sequence
141
+ //input: string helmString {semType: Macromolecule}
142
+ //output: string res
143
+ export async function helmToRNA(helmString: string) {
144
+ const url = `http://localhost:8081/WebService/service/Fasta/Convert/RNA/${helmString}`
145
+ return await accessServer(url, 'Sequence');
146
+ }
147
+
148
+
149
+ //name: helmToPeptide
150
+ //description: converts to peptide analogue sequence
151
+ //input: string helmString {semType: Macromolecule}
152
+ //output: string res
153
+ export async function helmToPeptide(helmString: string) {
154
+ const url = `http://localhost:8081/WebService/service/Fasta/Convert/PEPTIDE/${helmString}`
155
+ return await accessServer(url, 'Sequence');
53
156
  }
54
157
 
55
158
  //name: helmToSmiles
56
- //tags: converter
159
+ //description: converts to smiles
160
+ //input: string helmString {semType: Macromolecule}
57
161
  //output: string smiles {semType: Molecule}
58
- export function helmToSmiles(helm: string): string {
59
- //todo: call webservice
60
- return 'foo';
162
+ export async function helmToSmiles(helmString: string) {
163
+ const url = `http://localhost:8081/WebService/service/SMILES/${helmString}`
164
+ return await accessServer(url, 'SMILES');
61
165
  }
62
166
 
63
- //name: helmToFasta
64
- //tags: converter
65
- //output: string smiles {semType: fasta}
66
- export function helmToFasta(helm: string): string {
67
- return 'foo';
167
+ function getRS(smiles: string) {
168
+ var new_s = smiles.match(/(?<=\[)[^\][]*(?=])/gm);
169
+ var res = {};
170
+ var el = '';
171
+ var digit;
172
+ for (var i = 0; i < new_s.length; i++) {
173
+ if (new_s[i] != null){
174
+ if (/\d/.test(new_s[i])) {
175
+ digit = new_s[i][new_s[i].length - 1];
176
+ new_s[i] = new_s[i].replace(/[0-9]/g, '');
177
+ for (var j = 0; j < new_s[i].length; j++) {
178
+ if (new_s[i][j] != ':'){
179
+ el += new_s[i][j];
180
+ }
181
+ }
182
+ res['R' + digit] = el;
183
+ el = '';
184
+ }
185
+ }
186
+ }
187
+ return res;
68
188
  }
69
189
 
190
+ async function monomerManager(value: string) {
191
+ const file = await _package.files.readAsText(value.split('/')[1]);
192
+ const df = DG.DataFrame.fromJson(file);
193
+ var m;
194
+ for (var i = 0; i < df.rowCount; i++){
195
+ m = {
196
+ 'id': df.get('symbol', i).toString(),
197
+ 'n': df.get('name', i).toString(),
198
+ 'na': df.get('naturalAnalog', i).toString(),
199
+ 'type': df.get('polymerType', i).toString(),
200
+ 'mt': df.get('monomerType', i).toString(),
201
+ 'm': df.get('molfile', i).toString(),
202
+ rs: Object.keys(getRS(df.get('smiles', i).toString())).length,
203
+ at: getRS(df.get('smiles', i).toString()),
204
+ }
205
+ org.helm.webeditor.Monomers.addOneMonomer(m);
206
+ }
207
+ }
70
208
 
71
209
  //name: helmColumnToSmiles
72
- //input: column helmColumn {semType: HELM}
210
+ //input: column helmColumn {semType: Macromolecule}
73
211
  export function helmColumnToSmiles(helmColumn: DG.Column) {
74
212
  //todo: add column with smiles to col.dataFrame.
75
213
  }
76
214
 
77
- // todo: "Details" panel (see Toxicity)
78
- // smiles, mol weight, mol formula, extinction coefficient, "combined"
79
-
215
+ //name: findMonomers
216
+ //input: string helmString { semType: Macromolecule }
217
+ export async function findMonomers(helmString: string) {
218
+ const types = Object.keys(org.helm.webeditor.monomerTypeList());
219
+ const monomers = [];
220
+ const monomer_names = [];
221
+ for (var i = 0; i < types.length; i++) {
222
+ monomers.push(new scil.helm.Monomers.getMonomerSet(types[i]));
223
+ Object.keys(monomers[i]).forEach(k => {
224
+ monomer_names.push(monomers[i][k].id);
225
+ });
226
+ }
227
+ const split_string = helmString.match(/[^\s.,\/\\(){}$]+/gim);
228
+ return new Set(split_string.filter(val => !monomer_names.includes(val)));
229
+ }
80
230
 
81
231
  class HelmCellRenderer extends DG.GridCellRenderer {
82
232
 
83
- get name() { return 'helm'; }
84
- get cellType() { return 'helm'; }
233
+ get name() { return 'macromolecule'; }
234
+ get cellType() { return 'macromolecule'; }
85
235
  get defaultWidth(): number | null { return 400; }
86
236
  get defaultHeight(): number | null { return 100; }
87
237
 
@@ -91,7 +241,12 @@ class HelmCellRenderer extends DG.GridCellRenderer {
91
241
  host.setAttribute('data', gridCell.cell.value);
92
242
 
93
243
  gridCell.element = host;
94
- // @ts-ignore
95
- new JSDraw2.Editor(host, { width: w, height: h, skin: "w8", viewonly: true });
244
+ var canvas = new JSDraw2.Editor(host, { width: w, height: h, skin: "w8", viewonly: true });
245
+ var formula = canvas.getFormula(true);
246
+ var molWeight = Math.round(canvas.getMolWeight() * 100) / 100;
247
+ var coef = Math.round(canvas.getExtinctionCoefficient(true) * 100) / 100;
248
+ var molfile = canvas.getMolfile();
249
+ var result = formula + ', ' + molWeight + ', ' + coef + ', ' + molfile;
250
+ lru.set(gridCell.cell.value, result);
96
251
  }
97
252
  }
@@ -0,0 +1,43 @@
1
+ import {before, category, expect, test} from '@datagrok-libraries/utils/src/test';
2
+ import { helmToFasta, helmToPeptide, helmToRNA } from '../package';
3
+ import { _package } from '../package-test';
4
+ import * as DG from 'datagrok-api/dg';
5
+ import * as grok from 'datagrok-api/grok';
6
+
7
+
8
+ category('Helm', () => {
9
+
10
+ test('helmToFasta', async () => {
11
+ expect(await helmToFasta('RNA1{R(U)P.R(T)P.R(G)P.R(C)P.R(A)}$$$$'), '>RNA1UTGCA');
12
+ expect(await helmToFasta('RNA1{P.R(U).P.R(T)}$$$$'), '>RNA1UT');
13
+ expect(await helmToFasta('PEPTIDE1{A.G}$$$$V2.0'), '>PEPTIDE1AG')
14
+ });
15
+
16
+ test('helmToRNA', async () => {
17
+ expect(await helmToRNA('RNA1{R(U)P.R(T)P.R(G)P.R(C)P.R(A)}$$$$'), 'UTGCA');
18
+ expect(await helmToRNA('RNA1{P.R(U).P.R(T)}$$$$'), 'UT');
19
+ expect(await helmToRNA('RNA1{R(U)P.R(T)P}|RNA2{P.R(A)P.R(A)}$RNA1,RNA2,2:pair-6:pair|RNA1,RNA2,5:pair-3:pair$$$'), 'UT AA');
20
+ });
21
+
22
+ test('helmToPeptide', async () => {
23
+ expect(await helmToPeptide('PEPTIDE1{A.G}$$$$V2.0'), 'AG');
24
+ expect(await helmToPeptide('PEPTIDE1{L.V.A}|PEPTIDE2{L.V.A}$$$$'), 'LVA LVA');
25
+ expect(await helmToPeptide('PEPTIDE1{A.R.C.A.A.K.T.C.D.A}$PEPTIDE1,PEPTIDE1,8:R3-3:R3$$$'), 'ARCAAKTCDA');
26
+ });
27
+
28
+ test('detectMacromolecule', async () => {
29
+ const file = await _package.files.readAsText('test.csv')
30
+ const df = DG.DataFrame.fromCsv(file);
31
+ let col = df.columns.byName('HELM string');
32
+ await grok.data.detectSemanticTypes(df);
33
+ expect(col.semType, DG.SEMTYPE.MACROMOLECULE);
34
+ });
35
+
36
+ test('detectHelm', async () => {
37
+ const file = await _package.files.readAsText('test.csv')
38
+ const df = DG.DataFrame.fromCsv(file);
39
+ let col = df.columns.byName('HELM string');
40
+ await grok.data.detectSemanticTypes(df);
41
+ expect(col.tags[DG.TAGS.UNITS], "HELM");
42
+ });
43
+ });
package/tsconfig.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
8
8
  "module": "es2020", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
9
9
  "lib": ["es2020", "dom"], /* Specify library files to be included in the compilation. */
10
- // "allowJs": true, /* Allow javascript files to be compiled. */
10
+ "allowJs": true, /* Allow javascript files to be compiled. */
11
11
  // "checkJs": true, /* Report errors in .js files. */
12
12
  // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
13
13
  // "declaration": true, /* Generates corresponding '.d.ts' file. */
@@ -25,7 +25,7 @@
25
25
  // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26
26
 
27
27
  /* Strict Type-Checking Options */
28
- "strict": true, /* Enable all strict type-checking options. */
28
+ "strict": false, /* Enable all strict type-checking options. */
29
29
  // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
30
30
  // "strictNullChecks": true, /* Enable strict null checks. */
31
31
  // "strictFunctionTypes": true, /* Enable strict checking of function types. */
package/webpack.config.js CHANGED
@@ -4,15 +4,28 @@ const packageName = path.parse(require('./package.json').name).name.toLowerCase(
4
4
  module.exports = {
5
5
  mode: 'development',
6
6
  entry: {
7
- test: {filename: 'package-test.js', library: {type: 'var', name:`${packageName}_test`}, import: './src/package-test.ts'},
8
- package: './src/package.ts'
7
+ package: './src/package.ts',
8
+ test: {
9
+ filename: 'package-test.js',
10
+ library: {type: 'var', name: `${packageName}_test`},
11
+ import: './src/package-test.ts',
12
+ },
9
13
  },
10
14
  resolve: {
11
15
  extensions: ['.wasm', '.mjs', '.js', '.json', '.ts', '.tsx'],
12
16
  },
13
17
  module: {
14
18
  rules: [
15
- { test: /\.tsx?$/, loader: 'ts-loader' }
19
+ {
20
+ test: /\.ts(x?)$/,
21
+ use: 'ts-loader',
22
+ exclude: /node_modules/,
23
+ },
24
+ {
25
+ test: /\.css$/,
26
+ use: ['style-loader', 'css-loader'],
27
+ exclude: /node_modules/,
28
+ },
16
29
  ],
17
30
  },
18
31
  devtool: 'inline-source-map',