@datagrok/helm 1.0.1 → 1.0.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/.eslintignore ADDED
@@ -0,0 +1,2 @@
1
+ src/**/*.d.ts*
2
+ src/seq_align.ts
package/.eslintrc.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "env": {
3
+ "browser": true,
4
+ "es2021": true
5
+ },
6
+ "extends": [
7
+ "google"
8
+ ],
9
+ "parser": "@typescript-eslint/parser",
10
+ "parserOptions": {
11
+ "ecmaVersion": 12,
12
+ "sourceType": "module"
13
+ },
14
+ "plugins": [
15
+ "@typescript-eslint"
16
+ ],
17
+ "rules": {
18
+ "indent": [
19
+ "error",
20
+ 2
21
+ ],
22
+ "max-len": [
23
+ "error",
24
+ 120
25
+ ],
26
+ "no-unused-vars": "warn",
27
+ "require-jsdoc": "off",
28
+ "spaced-comment": "off",
29
+ "linebreak-style": "off",
30
+ "curly": [
31
+ "error",
32
+ "multi-or-nest",
33
+ "consistent"
34
+ ],
35
+ "brace-style": [
36
+ "error",
37
+ "1tbs",
38
+ {
39
+ "allowSingleLine": true
40
+ }
41
+ ],
42
+ "block-spacing": [2, "always"],
43
+ "comma-dangle": ["error", {
44
+ "arrays": "only-multiline",
45
+ "functions": "never",
46
+ "objects": "only-multiline",
47
+ "imports": "only-multiline"
48
+ }],
49
+ "guard-for-in": "off"
50
+ }
51
+ }
package/package.json CHANGED
@@ -2,16 +2,16 @@
2
2
  "name": "@datagrok/helm",
3
3
  "beta": false,
4
4
  "friendlyName": "Helm",
5
- "version": "1.0.1",
5
+ "version": "1.0.2",
6
6
  "description": "",
7
7
  "dependencies": {
8
- "datagrok-api": "latest",
9
- "cash-dom": "latest",
10
- "dayjs": "latest",
11
- "@datagrok-libraries/utils": "latest",
12
- "@datagrok-libraries/bio": "^2.8.2",
13
- "ts-loader": "^9.2.5",
14
- "typescript": "^4.4.2"
8
+ "datagrok-api": "^1.4.12",
9
+ "cash-dom": "latest",
10
+ "dayjs": "latest",
11
+ "@datagrok-libraries/utils": "latest",
12
+ "@datagrok-libraries/bio": "^2.8.3",
13
+ "ts-loader": "^9.2.5",
14
+ "typescript": "^4.4.2"
15
15
  },
16
16
  "sources": [
17
17
  "css/helm.css",
@@ -21,21 +21,29 @@
21
21
  "helm/JSDraw/Pistoia.HELM-uncompressed.js"
22
22
  ],
23
23
  "devDependencies": {
24
- "webpack": "latest",
25
- "webpack-cli": "latest",
24
+ "@typescript-eslint/eslint-plugin": "latest",
25
+ "@typescript-eslint/parser": "latest",
26
+ "eslint": "latest",
27
+ "eslint-config-google": "latest",
26
28
  "ts-loader": "latest",
27
- "typescript": "latest"
29
+ "typescript": "latest",
30
+ "webpack": "latest",
31
+ "webpack-cli": "latest"
28
32
  },
29
33
  "scripts": {
30
- "link-all": "npm link datagrok-api @datagrok-libraries/utils",
34
+ "link-all": "npm link datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
31
35
  "debug-helm": "webpack && grok publish ",
32
36
  "release-helm": "webpack && grok publish --release",
33
37
  "build-helm": "webpack",
34
38
  "build": "webpack",
39
+ "debug-local": "grok publish local",
40
+ "release-local": "grok publish local --release",
35
41
  "debug-helm-dev": "grok publish dev --rebuild",
36
42
  "release-helm-dev": "grok publish dev --rebuild --release",
37
43
  "debug-helm-public": "grok publish public --rebuild",
38
- "release-helm-public": "grok publish public --rebuild --release"
44
+ "release-helm-public": "grok publish public --rebuild --release",
45
+ "lint": "eslint \"./src/**/*.ts\"",
46
+ "lint-fix": "eslint \"./src/**/*.ts\" --fix"
39
47
  },
40
48
  "canEdit": [
41
49
  "Developers"
@@ -1,7 +1,7 @@
1
- import * as DG from "datagrok-api/dg";
2
- import * as grok from "datagrok-api/grok";
1
+ import * as DG from 'datagrok-api/dg';
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'
4
+ import './tests/helm-tests.ts';
5
5
 
6
6
  export const _package = new DG.Package();
7
7
  export {tests};
package/src/package.ts CHANGED
@@ -4,12 +4,12 @@ import * as ui from 'datagrok-api/ui';
4
4
  import * as DG from 'datagrok-api/dg';
5
5
  //import {lru} from '../../Bio/src/utils/cell-renderer';
6
6
  import {NotationConverter, NOTATION} from '@datagrok-libraries/bio/src/utils/notation-converter';
7
+ import {WebLogo} from '@datagrok-libraries/bio/src/viewers/web-logo';
7
8
  //import {ConverterFunc, DfReaderFunc} from '../../Bio/src/tests/types';
8
9
 
9
10
  export const _package = new DG.Package();
10
11
 
11
- const lru = new DG.LruCache<any, any>();
12
-
12
+ const lru = new DG.LruCache<any, any>();
13
13
 
14
14
 
15
15
  //tags: init
@@ -17,7 +17,7 @@ export async function initChem(): Promise<void> {
17
17
  // apparently HELMWebEditor requires dojo to be initialized first
18
18
  return new Promise((resolve, reject) => {
19
19
  // @ts-ignore
20
- dojo.ready(function () { resolve(null); });
20
+ dojo.ready(function() { resolve(null); });
21
21
  });
22
22
  }
23
23
 
@@ -25,54 +25,57 @@ export async function initChem(): Promise<void> {
25
25
  //description: Macromolecule
26
26
  //input: grid_cell cell
27
27
  export function editMoleculeCell(cell: DG.GridCell): void {
28
- let view = ui.div();
28
+ const view = ui.div();
29
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();
30
+ const app = new scil.helm.App(view, {
31
+ showabout: false,
32
+ mexfontsize: '90%',
33
+ mexrnapinontab: true,
34
+ topmargin: 20,
35
+ mexmonomerstab: true,
36
+ sequenceviewonly: false,
37
+ mexfavoritefirst: true,
38
+ mexfilter: true
39
+ });
40
+ const sizes = app.calculateSizes();
32
41
  app.canvas.resize(sizes.rightwidth, sizes.topheight - 210);
33
- var s = { width: sizes.rightwidth + "px", height: sizes.bottomheight + "px" };
42
+ let s = {width: sizes.rightwidth + 'px', height: sizes.bottomheight + 'px'};
34
43
  //@ts-ignore
35
44
  scil.apply(app.sequence.style, s);
36
45
  //@ts-ignore
37
46
  scil.apply(app.notation.style, s);
38
- s = { width: sizes.rightwidth + "px", height: (sizes.bottomheight + app.toolbarheight) + "px" };
47
+ s = {width: sizes.rightwidth + 'px', height: (sizes.bottomheight + app.toolbarheight) + 'px'};
39
48
  //@ts-ignore
40
49
  scil.apply(app.properties.parent.style, s);
41
50
  app.structureview.resize(sizes.rightwidth, sizes.bottomheight + app.toolbarheight);
42
51
  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);
47
- //@ts-ignore
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});
52
+
53
+ let dialogValue: string;
54
+ if (cell.gridColumn.column.tags[DG.TAGS.UNITS] === 'HELM') {
55
+ dialogValue = cell.cell.value;
56
+ } else {
57
+ const converter: NotationConverter = new NotationConverter(cell.cell.column);
58
+ dialogValue = converter.convertStringToHelm(cell.cell.value);
53
59
  }
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);
60
- //@ts-ignore
61
- ui.dialog({ showHeader: false, showFooter: true })
60
+
61
+ setTimeout(function() {
62
+ app.canvas.helm.setSequence(dialogValue, 'HELM');
63
+ }, 200);
64
+ //@ts-ignore
65
+ ui.dialog({showHeader: false, showFooter: true})
62
66
  .add(view)
63
67
  .onOK(() => {
64
68
  cell.cell.value;
65
- }).show({ modal: true, fullScreen: true});
66
- }
69
+ }).show({modal: true, fullScreen: true});
67
70
  }
68
71
 
69
72
  //name: Details
70
73
  //tags: panel, widgets
71
74
  //input: string helmString {semType: Macromolecule}
72
75
  //output: widget result
73
- export function detailsPanel(helmString: string){
76
+ export function detailsPanel(helmString: string) {
74
77
  //return new DG.Widget(ui.divText(lru.get(helmString)));
75
- var result = lru.get(helmString).split(',');
78
+ const result = lru.get(helmString).split(',');
76
79
  return new DG.Widget(
77
80
  ui.tableFromMap({
78
81
  'formula': result[0].replace(/<sub>/g, '').replace(/<\/sub>/g, ''),
@@ -84,24 +87,24 @@ export function detailsPanel(helmString: string){
84
87
  'smiles': ui.wait(async () => ui.divText(await helmToSmiles(helmString))),
85
88
  //'peptide analogue sequence': ui.wait(async () => ui.divText(await helmToPeptide(helmString))),
86
89
  })
87
- )
90
+ );
88
91
  }
89
92
 
90
93
 
91
- async function loadDialog () {
94
+ async function loadDialog() {
92
95
  //@ts-ignore
93
96
  let res = await grok.dapi.files.list('System:AppData/Helm', false, '');
94
97
  //@ts-ignore
95
98
  res = res.map((e) => e.path);
96
99
  //@ts-ignore
97
- let FilesList = await ui.choiceInput('Monomer Libraries', ' ', res);
98
- let grid = grok.shell.tv.grid;
100
+ const FilesList = await ui.choiceInput('Monomer Libraries', ' ', res);
101
+ const grid = grok.shell.tv.grid;
99
102
  ui.dialog('Load library from file')
100
- .add(FilesList)
101
- .onOK(async () => {
102
- await monomerManager(FilesList.value);
103
- grid.invalidate()
104
- }).show();
103
+ .add(FilesList)
104
+ .onOK(async () => {
105
+ await monomerManager(FilesList.value);
106
+ grid.invalidate();
107
+ }).show();
105
108
  };
106
109
 
107
110
  //name: Library
@@ -110,14 +113,14 @@ async function loadDialog () {
110
113
  //output: widget result
111
114
  export function libraryPanel(helmString: string) {
112
115
  //@ts-ignore
113
- let loadButton = ui.button('Load Library');
116
+ const loadButton = ui.button('Load Library');
114
117
  loadButton.addEventListener('click', loadDialog);
115
118
  return new DG.Widget(ui.divH([loadButton]));
116
119
  }
117
120
 
118
121
  async function accessServer(url: string, key: string) {
119
122
  const params: RequestInit = {
120
- method: 'GET',
123
+ method: 'GET',
121
124
  headers: {
122
125
  'Accept': 'application/json',
123
126
  }
@@ -132,7 +135,7 @@ async function accessServer(url: string, key: string) {
132
135
  //input: string helmString {semType: Macromolecule}
133
136
  //output: string res
134
137
  export async function helmToFasta(helmString: string) {
135
- const url = `http://localhost:8081/WebService/service/Fasta/Produce/${helmString}`
138
+ const url = `http://localhost:8081/WebService/service/Fasta/Produce/${helmString}`;
136
139
  return await accessServer(url, 'FastaFile');
137
140
  }
138
141
 
@@ -141,7 +144,7 @@ export async function helmToFasta(helmString: string) {
141
144
  //input: string helmString {semType: Macromolecule}
142
145
  //output: string res
143
146
  export async function helmToRNA(helmString: string) {
144
- const url = `http://localhost:8081/WebService/service/Fasta/Convert/RNA/${helmString}`
147
+ const url = `http://localhost:8081/WebService/service/Fasta/Convert/RNA/${helmString}`;
145
148
  return await accessServer(url, 'Sequence');
146
149
  }
147
150
 
@@ -151,7 +154,7 @@ export async function helmToRNA(helmString: string) {
151
154
  //input: string helmString {semType: Macromolecule}
152
155
  //output: string res
153
156
  export async function helmToPeptide(helmString: string) {
154
- const url = `http://localhost:8081/WebService/service/Fasta/Convert/PEPTIDE/${helmString}`
157
+ const url = `http://localhost:8081/WebService/service/Fasta/Convert/PEPTIDE/${helmString}`;
155
158
  return await accessServer(url, 'Sequence');
156
159
  }
157
160
 
@@ -160,24 +163,23 @@ export async function helmToPeptide(helmString: string) {
160
163
  //input: string helmString {semType: Macromolecule}
161
164
  //output: string smiles {semType: Molecule}
162
165
  export async function helmToSmiles(helmString: string) {
163
- const url = `http://localhost:8081/WebService/service/SMILES/${helmString}`
166
+ const url = `http://localhost:8081/WebService/service/SMILES/${helmString}`;
164
167
  return await accessServer(url, 'SMILES');
165
168
  }
166
169
 
167
170
  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
- }
171
+ const newS = smiles.match(/(?<=\[)[^\][]*(?=])/gm);
172
+ const res = {};
173
+ let el = '';
174
+ let digit;
175
+ for (let i = 0; i < newS.length; i++) {
176
+ if (newS[i] != null) {
177
+ if (/\d/.test(newS[i])) {
178
+ digit = newS[i][newS[i].length - 1];
179
+ newS[i] = newS[i].replace(/[0-9]/g, '');
180
+ for (let j = 0; j < newS[i].length; j++) {
181
+ if (newS[i][j] != ':')
182
+ el += newS[i][j];
181
183
  }
182
184
  res['R' + digit] = el;
183
185
  el = '';
@@ -190,18 +192,18 @@ function getRS(smiles: string) {
190
192
  async function monomerManager(value: string) {
191
193
  const file = await _package.files.readAsText(value.split('/')[1]);
192
194
  const df = DG.DataFrame.fromJson(file);
193
- var m;
194
- for (var i = 0; i < df.rowCount; i++){
195
+ let m;
196
+ for (let i = 0; i < df.rowCount; i++) {
195
197
  m = {
196
- 'id': df.get('symbol', i).toString(),
198
+ 'id': df.get('symbol', i).toString(),
197
199
  'n': df.get('name', i).toString(),
198
200
  'na': df.get('naturalAnalog', i).toString(),
199
201
  '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
- }
202
+ 'mt': df.get('monomerType', i).toString(),
203
+ 'm': df.get('molfile', i).toString(),
204
+ 'rs': Object.keys(getRS(df.get('smiles', i).toString())).length,
205
+ 'at': getRS(df.get('smiles', i).toString()),
206
+ };
205
207
  org.helm.webeditor.Monomers.addOneMonomer(m);
206
208
  }
207
209
  }
@@ -212,41 +214,48 @@ export function helmColumnToSmiles(helmColumn: DG.Column) {
212
214
  //todo: add column with smiles to col.dataFrame.
213
215
  }
214
216
 
217
+ // Synonym to overcome eslint error
218
+ const GetMonomerSet = scil.helm.Monomers.getMonomerSet;
219
+
215
220
  //name: findMonomers
216
221
  //input: string helmString { semType: Macromolecule }
217
222
  export async function findMonomers(helmString: string) {
218
223
  const types = Object.keys(org.helm.webeditor.monomerTypeList());
219
224
  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
+ const monomerNames = [];
226
+ for (let i = 0; i < types.length; i++) {
227
+ monomers.push(new GetMonomerSet(types[i]));
228
+ Object.keys(monomers[i]).forEach((k) => {
229
+ monomerNames.push(monomers[i][k].id);
225
230
  });
226
231
  }
227
- const split_string = helmString.match(/[^\s.,\/\\(){}$]+/gim);
228
- return new Set(split_string.filter(val => !monomer_names.includes(val)));
232
+ const splitString = WebLogo.splitterAsHelm(helmString);
233
+ return new Set(splitString.filter((val) => !monomerNames.includes(val)));
229
234
  }
230
235
 
231
236
  class HelmCellRenderer extends DG.GridCellRenderer {
232
-
233
237
  get name() { return 'macromolecule'; }
238
+
234
239
  get cellType() { return 'macromolecule'; }
240
+
235
241
  get defaultWidth(): number | null { return 400; }
242
+
236
243
  get defaultHeight(): number | null { return 100; }
237
244
 
238
- render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, gridCell: DG.GridCell, cellStyle: DG.GridCellStyle) {
239
- let host = ui.div([], { style: { width: `${w}px`, height: `${h}px`}});
245
+ render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
246
+ gridCell: DG.GridCell, cellStyle: DG.GridCellStyle
247
+ ) {
248
+ const host = ui.div([], {style: {width: `${w}px`, height: `${h}px`}});
240
249
  host.setAttribute('dataformat', 'helm');
241
250
  host.setAttribute('data', gridCell.cell.value);
242
251
 
243
252
  gridCell.element = host;
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;
253
+ const canvas = new JSDraw2.Editor(host, {width: w, height: h, skin: 'w8', viewonly: true});
254
+ const formula = canvas.getFormula(true);
255
+ const molWeight = Math.round(canvas.getMolWeight() * 100) / 100;
256
+ const coef = Math.round(canvas.getExtinctionCoefficient(true) * 100) / 100;
257
+ const molfile = canvas.getMolfile();
258
+ const result = formula + ', ' + molWeight + ', ' + coef + ', ' + molfile;
250
259
  lru.set(gridCell.cell.value, result);
251
260
  }
252
261
  }
@@ -1,43 +1,44 @@
1
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';
2
+ import {helmToFasta, helmToPeptide, helmToRNA} from '../package';
3
+ import {_package} from '../package-test';
4
4
  import * as DG from 'datagrok-api/dg';
5
5
  import * as grok from 'datagrok-api/grok';
6
6
 
7
7
 
8
8
  category('Helm', () => {
9
-
10
9
  test('helmToFasta', async () => {
11
10
  expect(await helmToFasta('RNA1{R(U)P.R(T)P.R(G)P.R(C)P.R(A)}$$$$'), '>RNA1UTGCA');
12
11
  expect(await helmToFasta('RNA1{P.R(U).P.R(T)}$$$$'), '>RNA1UT');
13
- expect(await helmToFasta('PEPTIDE1{A.G}$$$$V2.0'), '>PEPTIDE1AG')
12
+ expect(await helmToFasta('PEPTIDE1{A.G}$$$$V2.0'), '>PEPTIDE1AG');
14
13
  });
15
14
 
16
15
  test('helmToRNA', async () => {
17
16
  expect(await helmToRNA('RNA1{R(U)P.R(T)P.R(G)P.R(C)P.R(A)}$$$$'), 'UTGCA');
18
17
  expect(await helmToRNA('RNA1{P.R(U).P.R(T)}$$$$'), 'UT');
18
+ // eslint-disable-next-line max-len
19
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
20
  });
21
21
 
22
22
  test('helmToPeptide', async () => {
23
23
  expect(await helmToPeptide('PEPTIDE1{A.G}$$$$V2.0'), 'AG');
24
24
  expect(await helmToPeptide('PEPTIDE1{L.V.A}|PEPTIDE2{L.V.A}$$$$'), 'LVA LVA');
25
+ // eslint-disable-next-line max-len
25
26
  expect(await helmToPeptide('PEPTIDE1{A.R.C.A.A.K.T.C.D.A}$PEPTIDE1,PEPTIDE1,8:R3-3:R3$$$'), 'ARCAAKTCDA');
26
27
  });
27
28
 
28
29
  test('detectMacromolecule', async () => {
29
- const file = await _package.files.readAsText('test.csv')
30
+ const file = await _package.files.readAsText('test.csv');
30
31
  const df = DG.DataFrame.fromCsv(file);
31
- let col = df.columns.byName('HELM string');
32
+ const col = df.columns.byName('HELM string');
32
33
  await grok.data.detectSemanticTypes(df);
33
34
  expect(col.semType, DG.SEMTYPE.MACROMOLECULE);
34
35
  });
35
36
 
36
37
  test('detectHelm', async () => {
37
- const file = await _package.files.readAsText('test.csv')
38
+ const file = await _package.files.readAsText('test.csv');
38
39
  const df = DG.DataFrame.fromCsv(file);
39
- let col = df.columns.byName('HELM string');
40
+ const col = df.columns.byName('HELM string');
40
41
  await grok.data.detectSemanticTypes(df);
41
- expect(col.tags[DG.TAGS.UNITS], "HELM");
42
+ expect(col.tags[DG.TAGS.UNITS], 'HELM');
42
43
  });
43
44
  });