@datagrok/helm 2.1.25 → 2.1.26

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,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/helm",
3
3
  "friendlyName": "Helm",
4
- "version": "2.1.25",
4
+ "version": "2.1.26",
5
5
  "author": {
6
6
  "name": "Oleksandra Serhiienko",
7
7
  "email": "oserhiienko@datagrok.ai"
@@ -15,22 +15,23 @@
15
15
  "helm/JSDraw/Pistoia.HELM-uncompressed.js"
16
16
  ],
17
17
  "dependencies": {
18
- "@datagrok-libraries/bio": "^5.39.18",
18
+ "@datagrok-libraries/bio": "^5.39.24",
19
19
  "@datagrok-libraries/chem-meta": "^1.2.1",
20
- "@datagrok-libraries/utils": "^4.0.17",
20
+ "@datagrok-libraries/utils": "^4.1.42",
21
21
  "cash-dom": "^8.1.1",
22
- "datagrok-api": "^1.10.2",
22
+ "datagrok-api": "^1.17.0",
23
23
  "dayjs": "^1.10.6",
24
24
  "rxjs": "^6.5.5",
25
25
  "wu": "latest"
26
26
  },
27
27
  "devDependencies": {
28
+ "@types/node": "17.0.45",
28
29
  "@types/wu": "latest",
29
30
  "path": "^0.12.7",
30
31
  "source-map-loader": "^4.0.1",
31
32
  "ts-loader": "^9.2.6",
32
33
  "typescript": "^4.8.4",
33
- "webpack": "^5.59.1",
34
+ "webpack": "^5.76.3",
34
35
  "webpack-cli": "^4.9.1",
35
36
  "@typescript-eslint/eslint-plugin": "^5.11.0",
36
37
  "@typescript-eslint/parser": "^5.11.0",
@@ -0,0 +1,62 @@
1
+ import * as grok from 'datagrok-api/grok';
2
+ import * as ui from 'datagrok-api/ui';
3
+ import * as DG from 'datagrok-api/dg';
4
+
5
+ import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
6
+ import {IHelmWebEditor, IWebEditorApp} from '@datagrok-libraries/bio/src/helm/types';
7
+ import {HelmWebEditor} from './helm-web-editor';
8
+
9
+ type HelmHelperWindowType = Window & {
10
+ $helmHelper?: HelmHelper,
11
+ }
12
+ declare const window: HelmHelperWindowType;
13
+
14
+ export class HelmHelper implements IHelmHelper {
15
+ createHelmWebEditor(): IHelmWebEditor {
16
+ return new HelmWebEditor();
17
+ }
18
+
19
+ createWebEditorApp(host: HTMLDivElement, helm: string): IWebEditorApp {
20
+ // @ts-ignore
21
+ org.helm.webeditor.MolViewer.molscale = 0.8;
22
+ // @ts-ignore
23
+ const webEditorApp = new scil.helm.App(host, {
24
+ showabout: false,
25
+ mexfontsize: '90%',
26
+ mexrnapinontab: true,
27
+ topmargin: 20,
28
+ mexmonomerstab: true,
29
+ sequenceviewonly: false,
30
+ mexfavoritefirst: true,
31
+ mexfilter: true
32
+ }) as IWebEditorApp;
33
+ const sizes = webEditorApp.calculateSizes();
34
+ webEditorApp.canvas.resize(sizes.rightwidth - 100, sizes.topheight - 210);
35
+ let s = {width: sizes.rightwidth - 100 + 'px', height: sizes.bottomheight + 'px'};
36
+ //@ts-ignore
37
+ scil.apply(webEditorApp.sequence.style, s);
38
+ //@ts-ignore
39
+ scil.apply(webEditorApp.notation.style, s);
40
+ s = {width: sizes.rightwidth + 'px', height: (sizes.bottomheight + webEditorApp.toolbarheight) + 'px'};
41
+ //@ts-ignore
42
+ scil.apply(webEditorApp.properties.parent.style, s);
43
+ webEditorApp.structureview.resize(sizes.rightwidth, sizes.bottomheight + webEditorApp.toolbarheight);
44
+ webEditorApp.mex.resize(sizes.topheight - 80);
45
+ setTimeout(() => {
46
+ webEditorApp.canvas.helm.setSequence(helm, 'HELM');
47
+ }, 200);
48
+ return webEditorApp;
49
+ }
50
+
51
+ // -- Instance singleton --
52
+
53
+ public static async getInstance(): Promise<IHelmHelper> {
54
+ let res: HelmHelper = window.$helmHelper!;
55
+ if (!res) {
56
+ // create & init singleton
57
+ window.$helmHelper = res = new HelmHelper();
58
+ // await res.init();
59
+ }
60
+ return res;
61
+ }
62
+ }
@@ -2,7 +2,7 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
- import {IHelmWebEditor} from '@datagrok-libraries/bio/src/types/editor';
5
+ import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
6
6
 
7
7
  export class HelmWebEditor implements IHelmWebEditor {
8
8
  host: any;
@@ -18,38 +18,5 @@ export class HelmWebEditor implements IHelmWebEditor {
18
18
  resizeEditor(w: number, h: number) {
19
19
  this.editor.setSize(w, h);
20
20
  }
21
-
22
- createWebEditor(value: string) {
23
- const editorView = ui.div();
24
- // @ts-ignore
25
- org.helm.webeditor.MolViewer.molscale = 0.8;
26
- // @ts-ignore
27
- const webEditor = new scil.helm.App(editorView, {
28
- showabout: false,
29
- mexfontsize: '90%',
30
- mexrnapinontab: true,
31
- topmargin: 20,
32
- mexmonomerstab: true,
33
- sequenceviewonly: false,
34
- mexfavoritefirst: true,
35
- mexfilter: true
36
- });
37
- const sizes = webEditor.calculateSizes();
38
- webEditor.canvas.resize(sizes.rightwidth - 100, sizes.topheight - 210);
39
- let s = {width: sizes.rightwidth - 100 + 'px', height: sizes.bottomheight + 'px'};
40
- //@ts-ignore
41
- scil.apply(webEditor.sequence.style, s);
42
- //@ts-ignore
43
- scil.apply(webEditor.notation.style, s);
44
- s = {width: sizes.rightwidth + 'px', height: (sizes.bottomheight + webEditor.toolbarheight) + 'px'};
45
- //@ts-ignore
46
- scil.apply(webEditor.properties.parent.style, s);
47
- webEditor.structureview.resize(sizes.rightwidth, sizes.bottomheight + webEditor.toolbarheight);
48
- webEditor.mex.resize(sizes.topheight - 80);
49
- setTimeout(() => {
50
- webEditor.canvas.helm.setSequence(value, 'HELM');
51
- }, 200);
52
- return {editorDiv: editorView, webEditor: webEditor};
53
- }
54
21
  }
55
22
 
@@ -7,6 +7,7 @@ import './tests/helm-tests.ts';
7
7
  import './tests/findMonomers-tests';
8
8
  import './tests/renderers-tests';
9
9
  import './tests/get-molfiles';
10
+ import './tests/properties-widget-tests';
10
11
 
11
12
  export const _package = new DG.Package();
12
13
  export {tests};
package/src/package.ts CHANGED
@@ -7,10 +7,12 @@ import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
7
7
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
8
8
  import {GapSymbols, UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
9
9
  import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
10
+ import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
10
11
 
11
12
  import {findMonomers, parseHelm} from './utils';
12
- import {HelmWebEditor} from './helm-web-editor';
13
13
  import {HelmCellRenderer} from './cell-renderer';
14
+ import {HelmHelper} from './helm-helper';
15
+ import {getPropertiesWidget} from './widgets/properties-widget';
14
16
 
15
17
  let monomerLib: IMonomerLib | null = null;
16
18
 
@@ -159,29 +161,11 @@ export function openEditor(mol: string): void {
159
161
  }
160
162
 
161
163
  //name: Properties
162
- //tags: panel, widgets
163
- //input: string helmString {semType: Macromolecule}
164
+ //tags: panel, bio, helm, widgets
165
+ //input: semantic_value sequence {semType: Macromolecule}
164
166
  //output: widget result
165
- export async function propertiesPanel(helmString: string) {
166
- const grid = grok.shell.tv.grid;
167
- const parent = grid.root.parentElement!;
168
- const host = ui.div([]);
169
- parent.appendChild(host);
170
- const editor = new JSDraw2.Editor(host, {viewonly: true});
171
- host.style.width = '0px';
172
- host.style.height = '0px';
173
- editor.setHelm(helmString);
174
- const formula = editor.getFormula(true);
175
- const molWeight = Math.round(editor.getMolWeight() * 100) / 100;
176
- const coef = Math.round(editor.getExtinctionCoefficient(true) * 100) / 100;
177
- parent.lastChild!.remove();
178
- return new DG.Widget(
179
- ui.tableFromMap({
180
- 'formula': formula.replace(/<sub>/g, '').replace(/<\/sub>/g, ''),
181
- 'molecular weight': molWeight,
182
- 'extinction coefficient': coef,
183
- })
184
- );
167
+ export function propertiesWidget(sequence: DG.SemanticValue): DG.Widget {
168
+ return getPropertiesWidget(sequence);
185
169
  }
186
170
 
187
171
  function webEditor(cell?: DG.Cell, value?: string, units?: string) {
@@ -282,8 +266,10 @@ export function getMolfiles(col: DG.Column): DG.Column {
282
266
  return res;
283
267
  }
284
268
 
285
- //name: helmWebEditor
269
+ // -- Utils --
270
+
271
+ //name: getHelmHelper
286
272
  //output: object result
287
- export function helmWebEditor(): HelmWebEditor {
288
- return new HelmWebEditor();
273
+ export async function getHelmHelper(): Promise<IHelmHelper> {
274
+ return HelmHelper.getInstance();
289
275
  }
@@ -0,0 +1,81 @@
1
+ import * as ui from 'datagrok-api/ui';
2
+ import * as DG from 'datagrok-api/dg';
3
+ import * as grok from 'datagrok-api/grok';
4
+
5
+ import {category, expect, expectObject, test} from '@datagrok-libraries/utils/src/test';
6
+ import {ALPHABET, NOTATION, TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
7
+ import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
8
+
9
+ import {getPropertiesDict} from '../widgets/properties-widget';
10
+
11
+ const enum MolProps {
12
+ formula = 'formula',
13
+ mw = 'molecular weight',
14
+ extinctCoef = 'extinction coefficient',
15
+ }
16
+
17
+ const enum Tests {
18
+ helm = 'Helm',
19
+ separator = 'separator',
20
+ separator2 = 'separator2', // with a few gaps in a row
21
+ separatorGaps = 'separator-gaps',
22
+ fastaPt = 'fasta-PT',
23
+ fastaPtMsa = 'fasta-PT-MSA',
24
+ fastaDna = 'fasta-DNA',
25
+ }
26
+
27
+ const TestsData: {
28
+ [testName: string]: { seq: string, units: NOTATION, separator?: string, alphabet?: ALPHABET, res: {} }
29
+ } = {
30
+ [Tests.helm]: {
31
+ seq: 'PEPTIDE1{I.H.A.C.T.[Thr_PO3H2].[Aca].[D-Tyr_Et]}|PEPTIDE2{E.A.[meG]}$PEPTIDE1,PEPTIDE2,4:R3-1:R1$$$V2.0',
32
+ units: NOTATION.HELM,
33
+ res: {[MolProps.formula]: 'C58H94N13O21SP', [MolProps.mw]: 1372.48, [MolProps.extinctCoef]: 1.55}
34
+ },
35
+ [Tests.separator]: {
36
+ seq: 'I/H/A/C/T/Thr_PO3H2/Aca/D-Tyr_Et',
37
+ units: NOTATION.SEPARATOR, separator: '/', alphabet: ALPHABET.UN,
38
+ res: {[MolProps.formula]: 'C47H77N10O15SP', [MolProps.mw]: 1085.21, [MolProps.extinctCoef]: 1.55}
39
+ },
40
+ [Tests.separator2]: {
41
+ seq: 'meI/hHis/Aca/N/T/dK/Thr_PO3H2/Aca/D-Tyr_Et/Aze/dV/E/N////Phe_4Me',
42
+ units: NOTATION.SEPARATOR, separator: '/', alphabet: ALPHABET.UN,
43
+ res: {[MolProps.formula]: 'C91H146N19O25P', [MolProps.mw]: 1937.21, [MolProps.extinctCoef]: 1.49},
44
+ },
45
+ [Tests.separatorGaps]: {
46
+ seq: 'I/H/A//T/Thr_PO3H2/Aca/D-Tyr_Et',
47
+ units: NOTATION.SEPARATOR, separator: '/', alphabet: ALPHABET.UN,
48
+ res: {[MolProps.formula]: 'C44H72N9O14P', [MolProps.mw]: 982.07, [MolProps.extinctCoef]: 1.49},
49
+ },
50
+ [Tests.fastaPt]: {
51
+ seq: 'IHACTTAY',
52
+ units: NOTATION.FASTA, alphabet: ALPHABET.PT,
53
+ res: {[MolProps.formula]: 'C38H58N10O12S', [MolProps.mw]: 878.99, [MolProps.extinctCoef]: 1.55}
54
+ },
55
+ [Tests.fastaDna]: {
56
+ seq: 'ACGTATTCC',
57
+ units: NOTATION.FASTA, alphabet: ALPHABET.DNA,
58
+ res: {[MolProps.formula]: 'C87H113N30O56P9', [MolProps.mw]: 2753.76, [MolProps.extinctCoef]: 91.74}
59
+ }
60
+ };
61
+
62
+ category('properties-widget', () => {
63
+ for (const [testName, testData] of Object.entries(TestsData)) {
64
+ test(testName, async () => {
65
+ testPropertiesDict(testData.seq, testData.units, testData.separator, testData.alphabet, testData.res);
66
+ });
67
+ }
68
+ });
69
+
70
+ function testPropertiesDict(
71
+ seq: string, units: NOTATION, separator: string | undefined, alphabet: ALPHABET | undefined, expPropDict: {}
72
+ ) {
73
+ const col = DG.Column.fromList(DG.COLUMN_TYPE.STRING, 'seq', [seq]);
74
+ col.semType = DG.SEMTYPE.MACROMOLECULE;
75
+ col.setTag(DG.TAGS.UNITS, units);
76
+ if (separator) col.setTag(bioTAGS.separator, separator);
77
+ if (alphabet) col.setTag(bioTAGS.alphabet, alphabet);
78
+ const uh = UnitsHandler.getOrCreate(col);
79
+ const actPropDict = getPropertiesDict(seq, uh);
80
+ expectObject(actPropDict, expPropDict);
81
+ }
@@ -0,0 +1,43 @@
1
+ import * as grok from 'datagrok-api/grok';
2
+ import * as ui from 'datagrok-api/ui';
3
+ import * as DG from 'datagrok-api/dg';
4
+
5
+ import $ from 'cash-dom';
6
+
7
+ import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
8
+ import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
9
+
10
+ export function getPropertiesDict(seq: string, uh: UnitsHandler): {} {
11
+ const helmString = uh.isHelm() ? seq : uh.getConverter(NOTATION.HELM)(seq);
12
+ // Remove gap symbols for compatibility with WebEditor
13
+ const helmString2 = helmString.replaceAll(/\.(\*\.)+/g, '.')
14
+ .replaceAll(/\{(\*\.)+/g, '{').replaceAll(/(\.\*)+}/g, '}');
15
+
16
+ const host = ui.div([], {style: {width: '0', height: '0'}});
17
+ try {
18
+ document.documentElement.appendChild(host);
19
+ const editor = new JSDraw2.Editor(host, {viewonly: true});
20
+ editor.setHelm(helmString2);
21
+
22
+ const formula = editor.getFormula(true);
23
+ const molWeight = Math.round(editor.getMolWeight() * 100) / 100;
24
+ const coef = Math.round(editor.getExtinctionCoefficient(true) * 100) / 100;
25
+ return {
26
+ 'formula': formula.replace(/<sub>/g, '').replace(/<\/sub>/g, ''),
27
+ 'molecular weight': molWeight,
28
+ 'extinction coefficient': coef,
29
+ };
30
+ } finally {
31
+ $(host).empty();
32
+ host.remove();
33
+ }
34
+ }
35
+
36
+
37
+ export function getPropertiesWidget(value: DG.SemanticValue): DG.Widget {
38
+ const uh = UnitsHandler.getOrCreate(value.cell.column);
39
+ const propDict = getPropertiesDict(value.value, uh);
40
+ return new DG.Widget(
41
+ ui.tableFromMap(propDict)
42
+ );
43
+ }
package/tsconfig.json CHANGED
@@ -4,9 +4,9 @@
4
4
 
5
5
  /* Basic Options */
6
6
  // "incremental": true, /* Enable incremental compilation */
7
- "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
7
+ "target": "es2020", /* 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
- "lib": ["ES2022", "dom"], /* Specify library files to be included in the compilation. */
9
+ "lib": ["ES2022", "ES2022.String", "dom"], /* Specify library files to be included in the compilation. */
10
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'. */
@@ -61,11 +61,12 @@
61
61
  // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
62
62
 
63
63
  /* Experimental Options */
64
- // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
65
- // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
64
+ "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
65
+ "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
66
66
 
67
67
  /* Advanced Options */
68
68
  "skipLibCheck": false, /* Skip type checking of declaration files. */
69
- "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
69
+ "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
70
+ //"jsx": "react"
70
71
  }
71
72
  }