@datagrok/helm 2.5.0 → 2.5.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.
@@ -0,0 +1,14 @@
1
+ id,helm,description
2
+ 1,"PEPTIDE1{A.G.C.P.C.T.D.S.C.N}$$$$V2.0","linear natural"
3
+ 2,"PEPTIDE1{*.G.C.P.C.T.D.S.C.N}$$$$V2.0","linear natural with start gap"
4
+ 2,"PEPTIDE1{A.G.C.P.*.T.D.S.C.N}$$$$V2.0","linear natural with middle gap"
5
+ 2,"PEPTIDE1{A.G.C.P.C.T.D.S.C.*}$$$$V2.0","linear natural with end gap"
6
+ 3,"PEPTIDE1{[meI].G.C.[Nva].C.[meT].[meD].S.C.[Aca]}$$$$V2.0","linear non-natural"
7
+ 3,PEPTIDE1{*.G.C.[Nva].C.[meT].[meD].S.C.[Aca]}$$$$V2.0,linear non-natural with start gap
8
+ 3,"PEPTIDE1{[meI].G.C.[Nva].*.[meT].[meD].S.C.[Aca]}$$$$V2.0","linear non-natural with middle gap"
9
+ 3,"PEPTIDE1{[meI].G.C.[Nva].C.[meT].[meD].S.C.*}$$$$V2.0","linear non-natural with end gap"
10
+ 1,"PEPTIDE1{A.G.C.P.C.T.D.S.C.N}$PEPTIDE1,PEPTIDE1,3:R3-9:R3$$$V2.0","cycled natural"
11
+ 2,"PEPTIDE1{*.G.C.P.C.T.D.S.C.N}$PEPTIDE1,PEPTIDE1,3:R3-9:R3$$$V2.0","cycled natural with start gap"
12
+ 2,"PEPTIDE1{A.G.C.P.*.T.D.S.C.N}$PEPTIDE1,PEPTIDE1,3:R3-9:R3$$$V2.0","cycled natural with middle gap"
13
+ 2,"PEPTIDE1{A.G.C.P.C.T.D.S.C.*}$PEPTIDE1,PEPTIDE1,3:R3-9:R3$$$V2.0","cycled natural with end gap"
14
+
@@ -0,0 +1,41 @@
1
+ import type {DojoWindowType} from './types';
2
+
3
+ declare const window: Window & DojoWindowType;
4
+
5
+ export async function initDojo(): Promise<void> {
6
+ window.dojo$ = window.dojo$ || {};
7
+ if (!window.dojo$.initPromise) {
8
+ window.dojo$.initPromise = (async () => {
9
+ const logPrefix: string = `dojo: _package.initDojo()`;
10
+ console.debug(`${logPrefix}, start`);
11
+
12
+ console.debug(`${logPrefix}, loadModules(), before`);
13
+ const t1 = window.performance.now();
14
+ await loadModules();
15
+ const t2 = window.performance.now();
16
+ console.debug(`${logPrefix}, loadModules(), after, ET: ${t2 - t1} ms`);
17
+
18
+ console.debug(`${logPrefix}, end`);
19
+ })();
20
+ }
21
+ return window.dojo$.initPromise;
22
+ }
23
+
24
+ const dojoPath = '../../vendor/dojo-1.10.10';
25
+
26
+ async function loadModules(): Promise<void> {
27
+ const logPrefix: string = `dojo: _package.loadModules()`;
28
+
29
+ const unc = '';
30
+ window.dojo$.ctx = require.context('../../vendor/dojo-1.10.10', true, /\.js$/);
31
+ // const unc = '.uncompressed.js'; // '';
32
+ // window.dojo$.ctx = require.context('../../vendor/dojo-1.10.10', true, /\.js\.uncompressed\.js$/);
33
+
34
+ window.dojo$.uncompressed = unc;
35
+ window.dojo$.ctx(`./dojo/dojo.js${unc}`);
36
+ }
37
+
38
+
39
+ (async () => {
40
+ await initDojo();
41
+ })();
@@ -0,0 +1,12 @@
1
+ import type {DojoType, DojoxType} from '@datagrok-libraries/js-draw-lite/src/types/dojo';
2
+
3
+ export type DojoWindowType = {
4
+ dojo$: {
5
+ /** dojo source file postfix: '' for compressed, '.uncompressed.js' for uncompressed */
6
+ uncompressed: string;
7
+ ctx: { <T>(id: string): T };
8
+ initPromise: Promise<void>;
9
+ },
10
+ dojo: DojoType;
11
+ dojox: DojoxType;
12
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/helm",
3
3
  "friendlyName": "Helm",
4
- "version": "2.5.0",
4
+ "version": "2.5.2",
5
5
  "author": {
6
6
  "name": "Aleksandr Tanas",
7
7
  "email": "atanas@datagrok.ai"
@@ -16,9 +16,9 @@
16
16
  "css/helm.css"
17
17
  ],
18
18
  "dependencies": {
19
- "@datagrok-libraries/bio": "^5.42.15",
20
- "@datagrok-libraries/chem-meta": "^1.2.5",
21
- "@datagrok-libraries/utils": "^4.3.0",
19
+ "@datagrok-libraries/bio": "^5.44.1",
20
+ "@datagrok-libraries/chem-meta": "^1.2.7",
21
+ "@datagrok-libraries/utils": "^4.3.4",
22
22
  "cash-dom": "^8.1.1",
23
23
  "datagrok-api": "^1.21.1",
24
24
  "dayjs": "^1.10.6",
@@ -28,9 +28,10 @@
28
28
  "devDependencies": {
29
29
  "@datagrok-libraries/helm-web-editor": "^1.1.11",
30
30
  "@datagrok-libraries/js-draw-lite": "^0.0.8",
31
- "@datagrok/bio": "^2.15.1",
32
- "@datagrok/chem": "^1.12.0",
31
+ "@datagrok/bio": "^2.15.5",
32
+ "@datagrok/chem": "^1.12.1",
33
33
  "@types/node": "17.0.45",
34
+ "@types/webpack-env": "^1.18.5",
34
35
  "@types/wu": "latest",
35
36
  "@typescript-eslint/eslint-plugin": "^7.16.0",
36
37
  "@typescript-eslint/parser": "^7.16.0",
@@ -5,29 +5,35 @@ import * as DG from 'datagrok-api/dg';
5
5
  import $ from 'cash-dom';
6
6
 
7
7
  import {
8
- App, Atom, HelmType, GetMonomerFunc, GetMonomerResType, HelmString, HelmMol,
9
- MonomerExplorer, TabDescType, MonomersFuncs, MonomerSetType, HelmAtom, ISeqMonomer, PolymerType, MonomerType, type DojoType
8
+ App, Point, HelmAtom, HelmBond, HelmMol, HelmType, GetMonomerFunc, GetMonomerResType,
9
+ MonomerExplorer, TabDescType, MonomersFuncs, MonomerSetType, ISeqMonomer, PolymerType, MonomerType,
10
+ DojoType, JSDraw2ModuleType,
10
11
  } from '@datagrok-libraries/bio/src/helm/types';
11
12
  import {HelmTypes, MonomerTypes, PolymerTypes} from '@datagrok-libraries/bio/src/helm/consts';
12
13
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
13
14
  import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
14
- import {HelmInputBase, IHelmHelper, IHelmInputInitOptions} from '@datagrok-libraries/bio/src/helm/helm-helper';
15
+ import {
16
+ HelmConvertRes, HelmInputBase, HelmNotSupportedError, IHelmHelper, IHelmInputInitOptions
17
+ } from '@datagrok-libraries/bio/src/helm/helm-helper';
15
18
  import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
16
- import {IMonomerLib, IMonomerLinkData, IMonomerSetPlaceholder} from '@datagrok-libraries/bio/src/types/index';
19
+ import {IMonomerLib, IMonomerLibBase, IMonomerLinkData, IMonomerSetPlaceholder} from '@datagrok-libraries/bio/src/types/index';
17
20
  import {HelmTabKeys, IHelmDrawOptions} from '@datagrok-libraries/helm-web-editor/src/types/org-helm';
21
+ import {GAP_SYMBOL, GapOriginals, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
18
22
 
19
23
  import {HelmWebEditor} from './helm-web-editor';
20
24
  import {OrgHelmModule, ScilModule} from './types';
21
- import {getWebEditorMonomer} from './utils/get-monomer';
22
25
  import {HelmInput} from './widgets/helm-input';
23
26
  import {getHoveredMonomerFromEditorMol} from './utils/get-hovered';
24
27
 
25
28
  import {_package} from './package';
26
29
 
27
30
  declare const dojo: DojoType;
31
+ declare const JSDraw2: JSDraw2ModuleType;
28
32
  declare const scil: ScilModule;
29
33
  declare const org: OrgHelmModule;
30
34
 
35
+ const HELM_GAP_SYMBOL: string = GapOriginals[NOTATION.HELM];
36
+
31
37
  export class HelmHelper implements IHelmHelper {
32
38
  private static instanceCount: number = 0;
33
39
 
@@ -41,7 +47,7 @@ export class HelmHelper implements IHelmHelper {
41
47
 
42
48
  createHelmInput(name?: string, options?: IHelmInputInitOptions): HelmInputBase {
43
49
  try {
44
- const monomerLib: IMonomerLib = _package.libHelper!.getMonomerLib();
50
+ const monomerLib: IMonomerLibBase = _package.libHelper!.getMonomerLib();
45
51
  return HelmInput.create(this, monomerLib, name, options);
46
52
  } catch (err: any) {
47
53
  const [errMsg, errStack] = errInfo(err);
@@ -256,7 +262,7 @@ export class HelmHelper implements IHelmHelper {
256
262
  // logger.debug(`${logPrefixInt}, a: ${JSON.stringify(a, helmJsonReplacer)}, name: '${name}'`);
257
263
 
258
264
  // Creates monomers in lib
259
- const dgWem = getWebEditorMonomer(monomerLib, a, name);
265
+ const dgWem = monomerLib.getWebEditorMonomer(a, name);
260
266
 
261
267
  return dgWem; //dgWem;
262
268
  } catch (err) {
@@ -332,4 +338,69 @@ export class HelmHelper implements IHelmHelper {
332
338
  host.remove();
333
339
  }
334
340
  }
341
+
342
+ public parse(helm: string, origin?: Point): HelmMol {
343
+ const molHandler = new JSDraw2.MolHandler<HelmType>();
344
+ const plugin = new org.helm.webeditor.Plugin(molHandler);
345
+ org.helm.webeditor.IO.parseHelm(plugin, helm, origin ?? new JSDraw2.Point(0, 0));
346
+ return plugin.jsd.m;
347
+ }
348
+
349
+ removeGaps(srcHelm: string): HelmConvertRes {
350
+ const monomerMap = new Map<number, number>();
351
+ const mol: HelmMol = this.parse(srcHelm);
352
+ for (let aI: number = mol.atoms.length - 1; aI >= 0; --aI) {
353
+ const a = mol.atoms[aI];
354
+ if (a.elem === HELM_GAP_SYMBOL /* '*' - original */) {
355
+ const leftBondList: { aI: number, bI: number }[] = [];
356
+ const rightBondList: { aI: number, bI: number }[] = [];
357
+ for (let bI: number = mol.bonds.length - 1; bI >= 0; --bI) {
358
+ const b = mol.bonds[bI];
359
+ if (b.a1 !== a && b.a2 === a) leftBondList.push({aI, bI});
360
+ if (b.a1 === a && b.a2 !== a) rightBondList.push({aI, bI});
361
+ }
362
+ if (leftBondList.length > 1 || rightBondList.length > 1)
363
+ throw new HelmNotSupportedError(`Removing a gap monomer #${aI} with more than two bonds is unsupported.`);
364
+
365
+ const lb = leftBondList[0];
366
+ const rb = rightBondList[0];
367
+ if (lb && !rb) {
368
+ mol.bonds.splice(lb.bI, 1);
369
+ mol.atoms.splice(lb.aI, 1);
370
+ } else if (!lb && rb) {
371
+ const rb = rightBondList[0];
372
+ mol.bonds.splice(rb.bI, 1);
373
+ mol.atoms.splice(rb.aI, 1);
374
+ } else {
375
+ if (lb.aI !== rb.aI)
376
+ throw new Error('Something is really wrong here.');
377
+
378
+ // is not enough, breaks the simple polymer
379
+ //mol.delAtom(a, true);
380
+
381
+ const leftBond = mol.bonds[lb.bI];
382
+ const rightBond = mol.bonds[rb.bI];
383
+ const a2 = leftBond.a2 = rightBond.a2; // right atom
384
+ leftBond.r2 = rightBond.r2;
385
+ leftBond.apo2 = rightBond.apo2;
386
+
387
+ if (a2.bonds)
388
+ throw new Error('Bond list of the atom is not corrected.');
389
+ // a2.bonds!.splice(a2.bonds!.indexOf(rightBond), 1); // remove the right bond from links of the right atom
390
+ // a2.bonds!.push(leftBond); // put the left bond to links of the right atom
391
+
392
+ mol.bonds.splice(rb.bI, 1); // remove right bond
393
+ mol.atoms.splice(lb.aI, 1);
394
+ }
395
+ }
396
+ }
397
+
398
+ for (let aI: number = 0; aI < mol.atoms.length; ++aI) {
399
+ const a: HelmAtom = mol.atoms[aI];
400
+ monomerMap.set(parseInt(a.bio!.continuousId as string) - 1, aI);
401
+ }
402
+
403
+ const resHelm = org.helm.webeditor.IO.getHelm(mol)!;
404
+ return {srcHelm, resHelm, monomerMap};
405
+ }
335
406
  }
@@ -28,6 +28,12 @@ export class HelmMonomerPlacer extends CellRendererBackBase<string> {
28
28
  super(gridCol, tableCol, _package.logger);
29
29
  }
30
30
 
31
+ render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
32
+ gridCell: DG.GridCell, cellStyle: DG.GridCellStyle
33
+ ) {
34
+ throw new Error('Not implemented');
35
+ }
36
+
31
37
  protected override reset(): void {
32
38
  this._allPartsList = new Array<string[] | null>(this.tableCol.length).fill(null);
33
39
  this._lengthsList = new Array<number[] | null>(this.tableCol.length).fill(null);
@@ -5,7 +5,7 @@ import * as grok from 'datagrok-api/grok';
5
5
  // import {JSDraw2ModuleType} from '@datagrok/js-draw-lite/src/types/jsdraw2';
6
6
  // import {HelmType, OrgHelmModuleType} from '@datagrok/helm-web-editor/src/types/org-helm';
7
7
 
8
- import {runTests, tests, TestContext} from '@datagrok-libraries/utils/src/test';
8
+ import {runTests, tests, TestContext, initAutoTests as initTests } from '@datagrok-libraries/utils/src/test';
9
9
 
10
10
  import './tests/_first-tests';
11
11
  import './tests/helm-tests';
@@ -19,6 +19,7 @@ import './tests/get-monomer-tests';
19
19
  import './tests/parse-helm-tests';
20
20
  import './tests/helm-web-editor-tests';
21
21
  import './tests/helm-input-tests';
22
+ import './tests/helm-helper-tests';
22
23
 
23
24
  export const _package = new DG.Package();
24
25
  export {tests};
@@ -33,3 +34,8 @@ export async function test(category: string, test: string, testContext: TestCont
33
34
  const data = await runTests({category, test, testContext, verbose: true});
34
35
  return DG.DataFrame.fromObjects(data)!;
35
36
  }
37
+
38
+ //name: initAutoTests
39
+ export async function initAutoTests() {
40
+ await initTests(_package, _package.getModule('package-test.js'));
41
+ }
@@ -20,6 +20,8 @@ import {HelmService} from './utils/helm-service';
20
20
  import {OrgHelmModule, ScilModule} from './types';
21
21
  import {rewriteLibraries} from './utils/get-monomer';
22
22
 
23
+ import type {DojoWindowType} from '../helm/dojo/types';
24
+
23
25
  import {_package} from './package';
24
26
 
25
27
  declare const dojo: DojoType;
@@ -29,15 +31,17 @@ declare const org: OrgHelmModule;
29
31
 
30
32
  type DojoConfigWindowType = {
31
33
  dojoConfig: {
34
+ baseUrl: string,
32
35
  packages?: (string | { name: string, location: string })[],
33
36
  deps?: string[], callback: Function, has?: any, parseOnLoad?: boolean, async?: boolean | string, locale?: string,
37
+ loaderPatch: any,
34
38
  },
35
39
  };
36
40
  type HelmWindowType = {
37
41
  $helmService?: HelmServiceBase,
38
- require: Function,
42
+ require: any,
39
43
  };
40
- declare const window: Window & DojoConfigWindowType & HweWindow & HelmWindowType;
44
+ declare const window: Window & DojoConfigWindowType & DojoWindowType & HweWindow & HelmWindowType;
41
45
 
42
46
  export function _getHelmService(): HelmServiceBase {
43
47
  let res = window.$helmService;
@@ -46,7 +50,7 @@ export function _getHelmService(): HelmServiceBase {
46
50
  }
47
51
 
48
52
  export async function initHelmLoadAndPatchDojo(): Promise<void> {
49
- const logPrefix = `Helm: _package.initHelmPatchDojo()`;
53
+ const logPrefix = `Helm: _package.initHelmLoadAndPatchDojo()`;
50
54
  // patch window.dojox.gfx.svg.Text.prototype.getTextWidth hangs
51
55
  /** get the text width in pixels */
52
56
  const pi = DG.TaskBarProgressIndicator.create('Loading Helm Web Editor ...');
@@ -55,23 +59,23 @@ export async function initHelmLoadAndPatchDojo(): Promise<void> {
55
59
 
56
60
  // dojo.window','dojo.io.script','dojo.io.iframe','dojo.dom','dojox.gfx','dojox.gfx.svg','dojox.gfx.shape','dojox.charting'
57
61
  const dojoTargetList: { name: string, checker: () => boolean }[] = [
58
- {name: 'dojo.window', checker: () => !!dojo?.window},
59
- {name: 'dojo.ready', checker: () => !!dojo?.ready},
60
- {name: 'dojo.io.script', checker: () => !!dojo?.io?.script},
61
- {name: 'dojo.io.iframe', checker: () => !!dojo?.io?.iframe},
62
- // {name: 'dojo.dom', checker: () => !!dojo?.dom},
63
- {name: 'dojox.gfx', checker: () => !!dojox?.gfx},
64
- {name: 'dojox.gfx.svg', checker: () => !!dojox?.gfx?.svg},
65
- {name: 'dojox.gfx.createSurface', checker: () => !!dojox?.gfx?.createSurface},
66
- {name: 'dojox.gfx.shape', checker: () => !!dojox?.gfx?.shape},
67
- {name: 'dojox.storage.Provider', checker: () => !!dojox?.storage?.Provider},
68
- {name: 'dojox.storage.LocalStorageProvider', checker: () => !!dojox?.storage?.LocalStorageProvider},
69
- // {name: 'dojox.charting', checker: () => !!dojox.charting},
70
- // {name: 'dojox.charting.themes.Claro', checker: () => !!dojox.charting?.themes?.Claro},
71
- // {name: 'dojox.charting.themes.Wetland', checker: () => !!dojox.charting?.themes?.Wetland},
72
- // {name: 'dojox.charting.plot2d.Base', checker: () => !!dojox.charting?.plot2d?.Base},
73
- // {name: 'dojox.charting.Series', checker: () => !!dojox?.charting?.Series},
74
- // {name: 'dojox.charting.Chart2D', checker: () => !!dojox?.charting?.Chart2D},
62
+ {name: 'dojo.window', checker: () => !!(window.dojo?.window)},
63
+ {name: 'dojo.ready', checker: () => !!(window.dojo?.ready)},
64
+ {name: 'dojo.io.script', checker: () => !!(window.dojo?.io?.script)},
65
+ {name: 'dojo.io.iframe', checker: () => !!(window.dojo?.io?.iframe)},
66
+ // {name: 'dojo.dom', checker: () => !!(window.dojo?.dom)},
67
+ {name: 'dojox.gfx', checker: () => !!(window.dojox?.gfx)},
68
+ {name: 'dojox.gfx.svg', checker: () => !!(window.dojox?.gfx?.svg)},
69
+ {name: 'dojox.gfx.createSurface', checker: () => !!(window.dojox?.gfx?.createSurface)},
70
+ {name: 'dojox.gfx.shape', checker: () => !!(window.dojox?.gfx?.shape)},
71
+ {name: 'dojox.storage.Provider', checker: () => !!(window.dojox?.storage?.Provider)},
72
+ {name: 'dojox.storage.LocalStorageProvider', checker: () => !!(window.dojox?.storage?.LocalStorageProvider)},
73
+ // {name: 'dojox.charting', checker: () => !!(window.dojox.charting)},
74
+ // {name: 'dojox.charting.themes.Claro', checker: () => !!(window.dojox.charting?.themes?.Claro)},
75
+ // {name: 'dojox.charting.themes.Wetland', checker: () => !!(window.dojox.charting?.themes?.Wetland)},
76
+ // {name: 'dojox.charting.plot2d.Base', checker: () => !!(window.dojox.charting?.plot2d?.Base)},
77
+ // {name: 'dojox.charting.Series', checker: () => !!(window.dojox?.charting?.Series)},
78
+ // {name: 'dojox.charting.Chart2D', checker: () => !!(window.dojox?.charting?.Chart2D)},
75
79
  ];
76
80
  /** Gets list ofd modules not ready yet */
77
81
  const getDojoNotReadyList = (): string[] => {
@@ -85,15 +89,30 @@ export async function initHelmLoadAndPatchDojo(): Promise<void> {
85
89
  await timeout(async () => {
86
90
  await new Promise<void>((resolve, reject) => {
87
91
  window.dojoConfig = {
92
+ baseUrl: '/dojo',
88
93
  callback: () => { resolve(); },
89
- parseOnLoad: true,
90
- async: false,
94
+ parseOnLoad: false,
95
+ async: true,
91
96
  locale: 'en-us', // to limit dijit/nls file set
97
+ loaderPatch: {
98
+ injectUrl: (url: string, callback: any, owner: any) => {
99
+ const logPrefixInt = `${logPrefix} dojoConfig.loaderPatch.injectUrl()`;
100
+ _package.logger.debug(`${logPrefixInt}, url: ${url}`);
101
+ try {
102
+ const bundledFn = `.${url}${window.dojo$.uncompressed}`;
103
+ window.dojo$.ctx(bundledFn);
104
+ callback();
105
+ } catch (err: any) {
106
+ _package.logger.warning(`${logPrefixInt}: not loaded url: '${url}'.`);
107
+ }
108
+ },
109
+ },
92
110
  };
93
111
  // Load dojo without package/sources section for the settings dojoConfig to take effect
94
112
  DG.Utils.loadJsCss([
95
113
  // 'https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js.uncompressed.js',
96
- `${_package.webRoot}/vendor/dojo-1.10.10/dojo/dojo.js.uncompressed.js`,
114
+ // `${_package.webRoot}/vendor/dojo-1.10.10/dojo/dojo.js.uncompressed.js`,
115
+ `${_package.webRoot}/dist/package-dojo.js`,
97
116
  ]).then(() => {});
98
117
  });
99
118
 
package/src/package.ts CHANGED
@@ -6,23 +6,17 @@ import * as DG from 'datagrok-api/dg';
6
6
  import $ from 'cash-dom';
7
7
 
8
8
  import {testEvent} from '@datagrok-libraries/utils/src/test';
9
- import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
10
9
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
11
10
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
12
11
  import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
13
- import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
14
12
  import {App, Editor, HelmMol, HelmType, HweWindow} from '@datagrok-libraries/bio/src/helm/types';
15
13
  import {HelmInputBase, IHelmHelper, IHelmInputInitOptions} from '@datagrok-libraries/bio/src/helm/helm-helper';
16
14
  import {HelmServiceBase} from '@datagrok-libraries/bio/src/viewers/helm-service';
17
15
  import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
18
16
 
19
- import {HelmCellRenderer} from './cell-renderer';
20
- import {HelmHelper} from './helm-helper';
21
17
  import {getPropertiesWidget} from './widgets/properties-widget';
22
18
  import {HelmGridCellRenderer, HelmGridCellRendererBack} from './utils/helm-grid-cell-renderer';
23
19
  import {_getHelmService, HelmPackage, initHelmLoadAndPatchDojo} from './package-utils';
24
- import {RGROUP_CAP_GROUP_NAME, RGROUP_LABEL, SMILES} from './constants';
25
- import {getRS} from './utils/get-monomer-dummy';
26
20
 
27
21
  // Do not import anything than types from @datagrok/helm-web-editor/src/types
28
22
  import type {JSDraw2Module, OrgHelmModule, ScilModule} from './types';
@@ -42,8 +36,17 @@ declare const scil: ScilModule;
42
36
  declare const JSDraw2: JSDraw2Module;
43
37
  declare const org: OrgHelmModule;
44
38
 
39
+ let initHelmPromise: Promise<void> | null = null;
40
+
45
41
  //tags: init
46
42
  export async function initHelm(): Promise<void> {
43
+ if (initHelmPromise === null) {
44
+ initHelmPromise = initHelmInt();
45
+ }
46
+ await initHelmPromise;
47
+ }
48
+
49
+ async function initHelmInt(): Promise<void> {
47
50
  const logPrefix: string = 'Helm: _package.initHelm()';
48
51
  _package.logger.debug(`${logPrefix}, start`);
49
52
 
@@ -79,7 +82,7 @@ export function getHelmService(): HelmServiceBase {
79
82
  //meta.cellType: helm
80
83
  //meta.columnTags: quality=Macromolecule, units=helm
81
84
  //output: grid_cell_renderer result
82
- export function helmCellRenderer(): HelmCellRenderer {
85
+ export function helmCellRenderer(): DG.GridCellRenderer {
83
86
  const logPrefix = `Helm: _package.getHelmCellRenderer()`;
84
87
  _package.logger.debug(`${logPrefix}, start`);
85
88
  // return new HelmCellRenderer(); // old
@@ -189,7 +192,7 @@ export async function getHelmHelper(): Promise<IHelmHelper> {
189
192
  export async function measureCellRenderer(): Promise<void> {
190
193
  const grid = grok.shell.tv.grid;
191
194
  const gridCol = grid.columns.byName('sequence')!;
192
- const back = gridCol.temp['rendererBack'] as HelmGridCellRendererBack;
195
+ const back = gridCol.temp.rendererBack as HelmGridCellRendererBack;
193
196
 
194
197
  let etSum: number = 0;
195
198
  let etCount: number = 0;
@@ -217,3 +220,27 @@ export async function measureCellRenderer(): Promise<void> {
217
220
  }
218
221
  _package.logger.info(`measureCellRenderer(), avg ET: ${etSum / etCount} ms`);
219
222
  }
223
+
224
+ // -- Test apps --
225
+
226
+ //name: Highlight Monomers
227
+ //tags: app
228
+ //output: view result
229
+ export async function highlightMonomers(): Promise<void> {
230
+ const pi = DG.TaskBarProgressIndicator.create('Test app highlight monomers');
231
+ try {
232
+ const df = await _package.files.readCsv('tests/peptide.csv');
233
+ df.name = 'peptide.csv';
234
+ await initHelmPromise;
235
+
236
+ const seqCol = df.columns.byName('helm')!;
237
+ await grok.data.detectSemanticTypes(df);
238
+ await grok.functions.call('Bio:toAtomicLevel', {table: df, seqCol: seqCol, nonlinear: true, highlight: true});
239
+
240
+ // const resView = DG.TableView.create(df, false);
241
+ // return resView;
242
+ grok.shell.addTableView(df);
243
+ } finally {
244
+ pi.close();
245
+ }
246
+ }
@@ -7,10 +7,10 @@ import wu from 'wu';
7
7
  import {
8
8
  after, before, category, delay, expect, test, expectArray, testEvent, expectFloat, timeout
9
9
  } from '@datagrok-libraries/utils/src/test';
10
- import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
10
+ import {getHelmHelper, getMonomerHandleArgs} from '@datagrok-libraries/bio/src/helm/helm-helper';
11
11
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
12
- import {Atom, HelmType, IJsAtom, IWebEditorMonomer, GetMonomerFunc} from '@datagrok-libraries/bio/src/helm/types';
13
- import {IMonomerLib, Monomer, MonomerLibSummaryType} from '@datagrok-libraries/bio/src/types';
12
+ import {Atom, HelmType, IJsAtom, GetMonomerFunc} from '@datagrok-libraries/bio/src/helm/types';
13
+ import {MonomerLibSummaryType} from '@datagrok-libraries/bio/src/types';
14
14
  import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
15
15
  import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
16
16
  import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
@@ -19,12 +19,9 @@ import {
19
19
  } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
20
20
  import {defaultMonomerLibSummary, expectMonomerLib} from '@datagrok-libraries/bio/src/tests/monomer-lib-tests';
21
21
 
22
- import {getMonomerHandleArgs, rewriteLibraries} from '../utils/get-monomer';
22
+ import {rewriteLibraries} from '../utils/get-monomer';
23
23
  import {JSDraw2Module, OrgHelmModule} from '../types';
24
24
 
25
- import {HelmHelper} from '../helm-helper';
26
- import {RGROUP_CAP_GROUP_NAME, RGROUP_LABEL, SMILES} from '../constants';
27
- import {getRS} from '../utils/get-monomer-dummy';
28
25
  import {initHelmMainPackage} from './utils';
29
26
 
30
27
  import {_package} from '../package-test';
@@ -71,9 +68,7 @@ const tests: { [testName: string]: TestDataType } = {
71
68
  };
72
69
 
73
70
  category('getMonomer', ()=>{
74
- let libHelper: IMonomerLibHelper;
75
71
  let helmHelper: IHelmHelper;
76
-
77
72
  let monomerLibHelper: IMonomerLibHelper;
78
73
  /** Backup actual user's monomer libraries settings */
79
74
  let userLibSettings: UserLibSettings;
@@ -81,20 +76,12 @@ category('getMonomer', ()=>{
81
76
  before(async ()=>{
82
77
  await initHelmMainPackage();
83
78
 
84
- [libHelper, helmHelper] = await Promise.all([getMonomerLibHelper(), getHelmHelper()]);
85
-
86
- await timeout(async () => { monomerLibHelper = await getMonomerLibHelper(); }, 5000,
87
- 'get monomerLibHelper');
88
- await timeout(async () => { userLibSettings = await getUserLibSettings(); }, 5000,
89
- 'get user lib settings for backup');
79
+ [monomerLibHelper, helmHelper, userLibSettings] = await Promise.all(
80
+ [getMonomerLibHelper(), getHelmHelper(), getUserLibSettings()]);
90
81
 
91
- // Tests 'findMonomers' requires default monomer library loaded
92
- await timeout(async () => { await setUserLibSettingsForTests(); }, 5000,
93
- 'set user lib settings for tests');
94
- await timeout(async ()=> { await monomerLibHelper.awaitLoaded(); }, 5000,
95
- 'await monomerLib to be loaded');
96
- await timeout(async () => { await monomerLibHelper.loadMonomerLib(true); }, 5000,
97
- 'reload monomerLib with settings for tests'); // load default libraries for tests
82
+ await setUserLibSettingsForTests();
83
+ await monomerLibHelper.awaitLoaded();
84
+ await monomerLibHelper.loadMonomerLib(true); // load default libraries for tests
98
85
  });
99
86
 
100
87
  after(async ()=>{
@@ -103,7 +90,7 @@ category('getMonomer', ()=>{
103
90
  });
104
91
 
105
92
  test('original', async () =>{
106
- const monomerLib = libHelper.getMonomerLib();
93
+ const monomerLib = monomerLibHelper.getMonomerLib();
107
94
  rewriteLibraries(monomerLib);
108
95
 
109
96
  // const overriddenMonomersFuncs = helmHelper.revertOriginalMonomersFuncs();
@@ -0,0 +1,94 @@
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 {after, before, category, delay, expect, expectArray, test, testEvent} from '@datagrok-libraries/utils/src/test';
6
+ import {HelmNotSupportedError, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
7
+ import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
8
+
9
+ import {_package} from '../package-test';
10
+
11
+ type TestSrcType = { helm: string };
12
+ type TestTgtType = { helm: string | null, map: [number, number][] };
13
+
14
+ category('HelmHelper: removeGaps', () => {
15
+ let helmHelper: IHelmHelper;
16
+
17
+ before(async () => {
18
+ helmHelper = await getHelmHelper();
19
+ });
20
+
21
+ const tests: { [testName: string]: { src: TestSrcType, tgt: TestTgtType } } = {
22
+ 'single-linear-start': {
23
+ src: {helm: 'PEPTIDE1{*.[meY].A.G.T}$$$$V2.0'},
24
+ tgt: {
25
+ helm: 'PEPTIDE1{[meY].A.G.T}$$$$V2.0',
26
+ map: [[1, 0], [2, 1], [3, 2], [4, 3]],
27
+ }
28
+ },
29
+ 'single-linear-end': {
30
+ src: {helm: 'PEPTIDE1{[meY].A.G.T.*}$$$$V2.0'},
31
+ tgt: {
32
+ helm: 'PEPTIDE1{[meY].A.G.T}$$$$V2.0',
33
+ map: [[0, 0], [1, 1], [2, 2], [3, 3]],
34
+ }
35
+ },
36
+ 'single-linear-middle': {
37
+ src: {helm: 'PEPTIDE1{[meY].A.*.G.T}$$$$V2.0'},
38
+ tgt: {
39
+ helm: 'PEPTIDE1{[meY].A.G.T}$$$$V2.0',
40
+ map: [[0, 0], [1, 1], [3, 2], [4, 3]],
41
+ }
42
+ },
43
+ 'single-cycle-start': {
44
+ src: {helm: 'PEPTIDE1{*.[meY].C.R.N.P.C.T}$PEPTIDE1,PEPTIDE1,3:R3-7:R3$$$V2.0'},
45
+ tgt: {
46
+ helm: 'PEPTIDE1{[meY].C.R.N.P.C.T}$PEPTIDE1,PEPTIDE1,2:R3-6:R3$$$V2.0',
47
+ map: [[1, 0], [2, 1], [3, 2], [4, 3], [5, 4], [6, 5], [7, 6]],
48
+ }
49
+ },
50
+ 'single-cycle-end': {
51
+ src: {helm: 'PEPTIDE1{[meY].C.R.N.P.C.T.*}$PEPTIDE1,PEPTIDE1,2:R3-6:R3$$$V2.0'},
52
+ tgt: {
53
+ helm: 'PEPTIDE1{[meY].C.R.N.P.C.T}$PEPTIDE1,PEPTIDE1,2:R3-6:R3$$$V2.0',
54
+ map: [[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6]],
55
+ }
56
+ },
57
+ 'single-cycle-middle': {
58
+ src: {helm: 'PEPTIDE1{[meY].C.R.N.*.P.C.T}$PEPTIDE1,PEPTIDE1,2:R3-7:R3$$$V2.0'},
59
+ tgt: {
60
+ helm: 'PEPTIDE1{[meY].C.R.N.P.C.T}$PEPTIDE1,PEPTIDE1,2:R3-6:R3$$$V2.0',
61
+ map: [[0, 0], [1, 1], [2, 2], [3, 3], [5, 4], [6, 5], [7, 6]],
62
+ }
63
+ },
64
+ 'single-cycle-gap-at-connection': {
65
+ src: {helm: 'PEPTIDE1{[meY].*.C.R.N.P.C.T}$PEPTIDE1,PEPTIDE1,2:R3-7:R3$$$V2.0'},
66
+ tgt: {helm: null, map: []}
67
+ }
68
+ };
69
+
70
+ for (const [testName, testData] of Object.entries(tests)) {
71
+ test(`${testName}`, async () => {
72
+ let resErr: any = null;
73
+ try {
74
+ const res = helmHelper.removeGaps(testData.src.helm);
75
+ expect(res.resHelm, testData.tgt.helm);
76
+ expectArray(Array.from(res.monomerMap!.entries()), testData.tgt.map);
77
+ } catch (err: any) {
78
+ resErr = err;
79
+ }
80
+
81
+ if (testData.tgt.helm === null) { // err expected, for debug on GitHub CI
82
+ expect(resErr != null, true, 'Error expected');
83
+ const isErrorInstance = resErr instanceof HelmNotSupportedError;
84
+ const errCtorName = resErr.constructor.name;
85
+ const isErrorCtor = errCtorName === 'HelmNotSupportedError';
86
+ _package.logger.debug(`Check error object. ` +
87
+ `isErrorInstance: ${isErrorInstance}, isErrorCtor: ${isErrorCtor}, errCtorName: ${errCtorName}`);
88
+ }
89
+
90
+ expect((resErr instanceof HelmNotSupportedError) || resErr?.constructor.name === 'HelmNotSupportedError',
91
+ testData.tgt.helm === null, 'HelmNotSupportedError thrown expected');
92
+ }, testData.tgt.helm == null ? {skipReason: 'GitHub CI does not support testing exceptions'} : undefined);
93
+ }
94
+ });