@datagrok/helm 2.7.0 → 2.7.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,51 @@
1
+ DBID,HELM,Activity,Cluster
2
+ DBID55,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Aze.dV.E.N.dV.Phe_4Me}$$$$,2.1058521,1
3
+ DBID83,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.meM.D-Chg.dV.E.N.D-Orn.D-aThr.Phe_4Me}$$$$,4.4416509,3
4
+ DBID02,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.D-Cit.N.D-Orn.D-aThr.Phe_4Me}$$$$,5.0234375,1
5
+ DBID05,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.Dsu.N.D-Orn.D-aThr.Phe_4Me}$$$$,5.0660219,2
6
+ DBID34,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.Tyr_tBu.N.D-Orn.D-aThr.Phe_4Me}$$$$,5.6578050,4
7
+ DBID02,PEPTIDE1{aHyp.Hcy.N.T.W.Q.Phe_4NH2.D-Tyr_Et.Tyr_ab-dehydroMe.dV.Cys_SEt.N.D-Orn.D-aThr.Phe_4Me}$$$$,7.9036875,3
8
+ DBID64,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.A.D-aThr.Phe_4Me}$$$$,3.8863654,2
9
+ DBID75,PEPTIDE1{meI.hHis.Aca.N.T.Tyr_Me.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.dV.Phe_4Me}$$$$,4.6697459,2
10
+ DBID74,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.A.dV.E.N.D-Orn.D-aThr.Phe_4Me}$$$$,2.7280300,4
11
+ DBID60,"PEPTIDE1{meI.Pip.dK.Thr_PO3H2.[L-hArg(Et,Et)].D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.D-Orn.D-aThr.Phe_4Me}$$$$",4.4462886,2
12
+ DBID96,PEPTIDE1{meI.hHis.D-Hyp.N.T.dK.Thr_PO3H2.Trp_Ome.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.D-Orn.D-aThr.Phe_4Me}$$$$,4.3900189,4
13
+ DBID56,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.Phe_3Cl.meK.Phe_4Me}$$$$,3.6875632,4
14
+ DBID65,PEPTIDE1{Gly_allyl.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.Thr_PO3H2.N.D-Orn.D-aThr.Phe_4Me}$$$$,6.1076937,1
15
+ DBID45,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.Nle.D-aThr.Phe_4Me}$$$$,3.2512414,0
16
+ DBID13,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.D-Orn.dF.Phe_4Me}$$$$,7.2294617,0
17
+ DBID94,PEPTIDE1{meI.hHis.Aca.N.T.D-Orn.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.pnG.Phe_4Me}$$$$,0.6217819,3
18
+ DBID79,PEPTIDE1{meI.Pip.dK.Thr_PO3H2.D-Thz.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.D-Thz.N.D-Orn.D-aThr.Phe_4Me}$$$$,4.4476070,1
19
+ DBID21,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.Nle.aIle.Phe_4Me}$$$$,4.9557114,1
20
+ DBID10,PEPTIDE1{meY.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.pnG.Phe_4Me}$$$$,1.3188239,1
21
+ DBID86,PEPTIDE1{meI.Aca.N.T.W.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.D-Orn.D-aThr.Phe_4Me}$$$$,7.6897125,2
22
+ DBID52,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.hHis.D-aThr.Phe_4Me}$$$$,4.0970631,2
23
+ DBID27,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.3Pal.D-aThr.Phe_4Me}$$$$,2.7782860,3
24
+ DBID98,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.Thr_PO3H2.D-aThr.Phe_4Me}$$$$,4.9825664,2
25
+ DBID94,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.D-Nle.Phe_4Me}$$$$,4.0829563,2
26
+ DBID86,PEPTIDE1{D-Nva.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.pnG.Phe_4Me}$$$$,2.7203233,3
27
+ DBID48,PEPTIDE1{meI.Thr_PO3H2.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Cys_SEt.N.Phe_3Cl.aIle.Phe_4Me}$$$$,0.7954721,1
28
+ DBID22,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.seC.Tyr_ab-dehydroMe.meN.E.N.dV.Phe_4Me}$$$$,5.0775967,1
29
+ DBID54,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.meN.E.N.3Pal.D-aThr.Phe_4Me}$$$$,4.1724143,3
30
+ DBID17,PEPTIDE1{D-Tic.Hcy.N.T.W.Q.Phe_4NH2.D-Tyr_Et.Tyr_ab-dehydroMe.dV.Cys_SEt.N.dV.Phe_4Me}$$$$,3.1429222,3
31
+ DBID76,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.meN.E.N.dV.meF}$$$$,3.1327622,0
32
+ DBID20,PEPTIDE1{meI.Aca.N.T.Ser_PO3H2.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.pnG.Phe_4Me}$$$$,3.8640671,1
33
+ DBID01,PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.H.P.Phe_4Me}$$$$,4.1827374,3
34
+ DBID93,PEPTIDE1{Phe_4Sdihydroorotamido.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.pnG.Phe_4Me}$$$$,2.6165285,1
35
+ DBID89,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.D-Thz.Phe_4Me}$$$$,3.2189791,0
36
+ DBID30,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Met_O2.dV.E.N.H.D-aThr.Phe_4Me}$$$$,1.0362210,3
37
+ DBID07,PEPTIDE1{meI.Aca.N.T.D-1Nal.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.H.D-aThr.Phe_4Me}$$$$,3.8830254,4
38
+ DBID51,PEPTIDE1{meI.Aca.N.T.meV.Thr_PO3H2.Aca.D-Tyr_Et.Met_O2.D-Dap.Thr_PO3H2.N.H.D-aThr.Phe_4Me}$$$$,5.1701312,2
39
+ DBID95,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.pnG.Phe_4Br.Phe_4Me}$$$$,3.1820068,1
40
+ DBID47,PEPTIDE1{meI.Aca.N.T.dK.Q.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.dV.Phe_4Me}$$$$,4.4652672,1
41
+ DBID16,PEPTIDE1{meI.Aca.Q.T.W.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.dV.Phe_4Me}$$$$,2.8669512,4
42
+ DBID52,PEPTIDE1{meI.hHis.Hcy.Q.T.W.Q.Phe_4NH2.D-Tyr_Et.Tyr_ab-dehydroMe.dV.pnG.N.aMePhe.Phe_4Me}$$$$,3.2571971,1
43
+ DBID41,PEPTIDE1{meI.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.V.Phe_4Me}$$$$,4.4447875,0
44
+ DBID78,PEPTIDE1{meI.Aca.Aca.T.dK.Q.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.D-Dap.Thr_PO3H2.N.Thr_PO3H2.Phe_4Me}$$$$,2.4899697,4
45
+ DBID95,PEPTIDE1{meI.hHis.Aca.Q.T.W.Q.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.Cya.N.F.Phe_4Me}$$$$,0.3957288,4
46
+ DBID92,PEPTIDE1{meI.hHis.Aca.Q.T.W.Q.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.pnG.N.F.aIle.Phe_4Me}$$$$,2.9058776,3
47
+ DBID88,PEPTIDE1{meI.hHis.Hcy.Q.T.W.Q.Phe_4NH2.D-Tyr_Et.Tyr_ab-dehydroMe.dV.pnG.N.dV.Phe_4Me}$$$$,2.1254258,0
48
+ DBID10,PEPTIDE1{meI.Bux.Hcy.Q.T.W.Q.Phe_4NH2.D-Tyr_Et.Tyr_ab-dehydroMe.dV.Cys_SEt.N.Bmt.Phe_4Me}$$$$,1.7159123,0
49
+ DBID86,PEPTIDE1{D-Tyr_Et.hHis.Aca.Q.T.W.Q.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.dV.Phe_4Me}$$$$,1.5285099,0
50
+ DBID43,PEPTIDE1{meI.hHis.Hcy.Q.T.W.Q.Phe_4NH2.dP.Tyr_ab-dehydroMe.dV.E.N.Bmt.Phe_4Me}$$$$,3.9470999,3
51
+ DBID26,PEPTIDE1{meI.hHis.Hcy.Q.T.W.Q.Phe_4NH2.D-Tyr_Et.Tyr_ab-dehydroMe.dV.pnG.N.Bmt.Phe_4Me}$$$$,3.7495575,4
@@ -0,0 +1,5 @@
1
+ HELM string
2
+ "PEPTIDE1{D.E.F.G}|PEPTIDE2{C.E}$PEPTIDE1,PEPTIDE2,2:R3-1:R1$$$V2.0"
3
+ "PEPTIDE1{L.M.P.Q.R.S.T}$PEPTIDE1,PEPTIDE1,7:R2-1:R1$$$"
4
+ "PEPTIDE1{N.P.F.V.L.P.[dV]}$PEPTIDE1,PEPTIDE1,7:R2-1:R1$$$"
5
+ "PEPTIDE1{A.R.C.A.A.K.T.C.D.A}$PEPTIDE1,PEPTIDE1,8:R3-3:R3$$$"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/helm",
3
3
  "friendlyName": "Helm",
4
- "version": "2.7.0",
4
+ "version": "2.7.2",
5
5
  "author": {
6
6
  "name": "Maria Dolotova",
7
7
  "email": "mdolotova@datagrok.ai"
@@ -16,7 +16,7 @@
16
16
  "css/helm.css"
17
17
  ],
18
18
  "dependencies": {
19
- "@datagrok-libraries/bio": "^5.45.11",
19
+ "@datagrok-libraries/bio": "^5.48.2",
20
20
  "@datagrok-libraries/chem-meta": "^1.2.7",
21
21
  "cash-dom": "^8.1.1",
22
22
  "@datagrok-libraries/utils": "^4.4.0",
@@ -29,7 +29,7 @@
29
29
  "devDependencies": {
30
30
  "@datagrok-libraries/helm-web-editor": "^1.1.13",
31
31
  "@datagrok-libraries/js-draw-lite": "^0.0.10",
32
- "@datagrok/bio": "latest",
32
+ "@datagrok/bio": "^2.18.1",
33
33
  "@datagrok/chem": "^1.13.0",
34
34
  "@types/node": "17.0.45",
35
35
  "@types/webpack-env": "^1.18.5",
@@ -50,6 +50,7 @@
50
50
  },
51
51
  "scripts": {
52
52
  "link-all": "npm link @datagrok-libraries/chem-meta datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
53
+ "link-bio": "npm link @datagrok-libraries/bio",
53
54
  "debug-helm": "webpack && grok publish",
54
55
  "release-helm": "webpack && grok publish --release",
55
56
  "build-helm": "webpack",
@@ -19,6 +19,9 @@ import './tests/parse-helm-tests';
19
19
  import './tests/helm-web-editor-tests';
20
20
  import './tests/helm-input-tests';
21
21
  import './tests/helm-helper-tests';
22
+ import './tests/helm-substructure-filter';
23
+ import './tests/helm-activity-cliffs';
24
+ import './tests/to-atomic-level-ui-non-linear';
22
25
 
23
26
  export const _package = new DG.Package();
24
27
  export {tests};
@@ -0,0 +1,77 @@
1
+ import * as grok from 'datagrok-api/grok';
2
+ import * as DG from 'datagrok-api/dg';
3
+
4
+ import {after, before, category, test} from '@datagrok-libraries/utils/src/test';
5
+
6
+ import {BitArrayMetricsNames} from '@datagrok-libraries/ml/src/typed-metrics';
7
+ import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
8
+ import {
9
+ getUserLibSettings, setUserLibSettings
10
+ } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
11
+ import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
12
+ import {DimReductionMethods} from '@datagrok-libraries/ml/src/multi-column-dimensionality-reduction/types';
13
+ import {getHelmHelper, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
14
+ import {expect} from '@datagrok-libraries/utils/src/test';
15
+ import {MmDistanceFunctionsNames} from '@datagrok-libraries/ml/src/macromolecule-distance-functions';
16
+ import {BitArrayMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
17
+ import {BYPASS_LARGE_DATA_WARNING} from '@datagrok-libraries/ml/src/functionEditors/consts';
18
+
19
+ import {_package} from '../package-test';
20
+
21
+
22
+ category('activityCliffs', async () => {
23
+ let helmHelper: IHelmHelper;
24
+ let monomerLibHelper: IMonomerLibHelper;
25
+ /** Backup actual user's monomer libraries settings */
26
+ let userLibSettings: UserLibSettings;
27
+ const helmEncodingFunc = DG.Func.find({name: 'helmPreprocessingFunction', package: 'Bio'})[0];
28
+ before(async () => {
29
+ helmHelper = await getHelmHelper(); // init Helm package
30
+ monomerLibHelper = await getMonomerLibHelper();
31
+ userLibSettings = await getUserLibSettings();
32
+
33
+ // Test 'helm' requires default monomer library loaded
34
+ await monomerLibHelper.loadMonomerLibForTests();
35
+ });
36
+
37
+ after(async () => {
38
+ // UserDataStorage.put() replaces existing data
39
+ await setUserLibSettings(userLibSettings);
40
+ await monomerLibHelper.loadMonomerLib(true); // load user settings libraries
41
+ });
42
+
43
+
44
+ test('Helm', async () => {
45
+ const df = await _package.files.readCsv('samples/HELM_50.csv');
46
+ const _view = grok.shell.addTableView(df);
47
+
48
+ await _testActivityCliffsOpen(df, DimReductionMethods.UMAP,
49
+ 'HELM', 'Activity', 65, 20, BitArrayMetricsNames.Tanimoto, helmEncodingFunc);
50
+ });
51
+ });
52
+
53
+
54
+ async function _testActivityCliffsOpen(df: DG.DataFrame, drMethod: DimReductionMethods,
55
+ seqColName: string, activityColName: string, similarityThr: number, tgtNumberCliffs: number,
56
+ similarityMetric: MmDistanceFunctionsNames | BitArrayMetrics, preprocessingFunction: DG.Func,
57
+ ): Promise<void> {
58
+ await grok.data.detectSemanticTypes(df);
59
+ const scatterPlot = (await grok.functions.call('Bio:activityCliffs', {
60
+ table: df,
61
+ molecules: df.getCol(seqColName),
62
+ activities: df.getCol(activityColName),
63
+ similarity: similarityThr,
64
+ methodName: drMethod,
65
+ similarityMetric: similarityMetric,
66
+ preprocessingFunction: preprocessingFunction,
67
+ options: {[`${BYPASS_LARGE_DATA_WARNING}`]: true},
68
+ demo: false,
69
+ })) as DG.Viewer | undefined;
70
+ expect(scatterPlot != null, true);
71
+
72
+ const cliffsLink = Array.from(scatterPlot!.root.children).find((el) => {
73
+ const classList: string[] = el.className.split(' ');
74
+ return ['ui-btn', 'ui-btn-ok'].every((reqClassName) => classList.includes(reqClassName));
75
+ });
76
+ expect((cliffsLink as HTMLElement).innerText.toLowerCase(), `${tgtNumberCliffs} cliffs`);
77
+ }
@@ -0,0 +1,163 @@
1
+ /* eslint-disable max-lines */
2
+ /* eslint-disable max-lines-per-function */
3
+ import * as grok from 'datagrok-api/grok';
4
+ import * as ui from 'datagrok-api/ui';
5
+ import * as DG from 'datagrok-api/dg';
6
+
7
+ import {after, before, category, test, expect, delay, testEvent} from '@datagrok-libraries/utils/src/test';
8
+ import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
9
+ import {
10
+ getUserLibSettings, setUserLibSettings
11
+ } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
12
+ import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
13
+ import {getSeqHelper, ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
14
+
15
+ import {awaitGrid, readDataframe} from './utils';
16
+
17
+ import {BioFilterProps, IBioFilter}
18
+ from '@datagrok-libraries/bio/src/substructure-filter/bio-substructure-filter-types';
19
+
20
+ import {_package} from '../package-test';
21
+
22
+ category('bio-substructure-filters', async () => {
23
+ let seqHelper: ISeqHelper;
24
+ let monomerLibHelper: IMonomerLibHelper;
25
+ /** Backup actual user's monomer libraries settings */
26
+ let userLibSettings: UserLibSettings;
27
+
28
+ before(async () => {
29
+ seqHelper = await getSeqHelper();
30
+ monomerLibHelper = await getMonomerLibHelper();
31
+ userLibSettings = await getUserLibSettings();
32
+
33
+ // Test 'helm' requires default monomer library loaded
34
+ await monomerLibHelper.loadMonomerLibForTests(); // load default libraries
35
+ });
36
+
37
+ after(async () => {
38
+ // UserDataStorage.put() replaces existing data
39
+ await setUserLibSettings(userLibSettings);
40
+ await monomerLibHelper.loadMonomerLib(true); // load user settings libraries
41
+ });
42
+
43
+
44
+ test('helm-dialog', async () => {
45
+ const logPrefix = 'Bio tests: substructureFilters/helm-dialog';
46
+ const df = await readDataframe('tests/filter_HELM.csv');
47
+ const view = grok.shell.addTableView(df);
48
+ await grok.data.detectSemanticTypes(df);
49
+ await df.meta.detectSemanticTypes();
50
+
51
+ _package.logger.debug(`${logPrefix}, filter attaching.`);
52
+ const filter = await grok.functions.call('Bio:bioSubstructureFilterTest');
53
+ filter.attach(df);
54
+ const dlg = ui.dialog('Test filters').add(filter.root).show(); // to waitForElementInDom
55
+ await filter.awaitRendered();
56
+ try {
57
+ const bf = filter.bioFilter as IBioFilter;
58
+ expect(filter.bioFilter !== null, true, 'bioFilter is not created');
59
+
60
+ // filter 1
61
+ _package.logger.debug(`${logPrefix}, filter 1 change awaiting...`);
62
+ await testEvent(df.onRowsFiltered, () => {}, () => {
63
+ bf.props = new BioFilterProps('PEPTIDE1{A.C}$$$$V2.0', undefined, _package.logger);
64
+ }, 20000);
65
+ _package.logger.debug(`${logPrefix}, filter 1 changed.`);
66
+ expect(filter.dataFrame!.filter.trueCount, 1);
67
+ expect(filter.dataFrame!.filter.toBinaryString(), '0001');
68
+
69
+ // filter 2
70
+ _package.logger.debug(`${logPrefix}, filter 2 change awaiting...`);
71
+ await testEvent(df.onRowsFiltered, () => {}, () => {
72
+ bf.props = new BioFilterProps('PEPTIDE1{C}$$$$V2.0', undefined, _package.logger);
73
+ }, 20000);
74
+ setTimeout(() => view.grid.invalidate(), 500);
75
+ await awaitGrid(view.grid);
76
+ await delay(1000);
77
+ _package.logger.debug(`${logPrefix}, filter 2 changed.`);
78
+ expect(filter.dataFrame!.filter.trueCount, 2);
79
+ expect(filter.dataFrame!.filter.toBinaryString(), '1001');
80
+ } finally {
81
+ dlg.close();
82
+ }
83
+ await filter.awaitRendered();
84
+ await delay(3000); //TODO: await for grid.onLookChanged
85
+ }, {});
86
+
87
+
88
+ // Generates unhandled exception accessing isFiltering before bioFilter created
89
+ test('helm-view', async () => {
90
+ const logPrefix = 'Bio tests: substructureFilters/helm-view';
91
+ const df = await readDataframe('tests/filter_HELM.csv');
92
+ const col = df.getCol('HELM string');
93
+ await grok.data.detectSemanticTypes(df);
94
+ const view = grok.shell.addTableView(df);
95
+
96
+ const fg = view.getFiltersGroup();
97
+
98
+ // await awaitCheck(() => fg.filters.length == 1, 'await filters.length == 1', 1000);
99
+ // const filter = fg.filters.filter((f) => f.columnName == col.name)[0] as BioSubstructureFilter;
100
+ await awaitGrid(view.grid);
101
+ });
102
+
103
+
104
+ test('sync-helm', async () => {
105
+ const df = await _package.files.readCsv('tests/filter_HELM.csv');
106
+ await grok.data.detectSemanticTypes(df);
107
+ const view = grok.shell.addTableView(df);
108
+
109
+ const fSubStr: string = 'PEPTIDE1{A.C}$$$$V2.0';
110
+ const fTrueCount: number = 1;
111
+
112
+ const f1 = await createFilter('HELM string', df);
113
+ const f2 = await createFilter('HELM string', df);
114
+ const dlg = ui.dialog('Test filters').add(f1.root).add(f2.root).show(); // to waitForElementInDom
115
+ await Promise.all([f1.awaitRendered(), f2.awaitRendered()]);
116
+ try {
117
+ expect(!!f1.bioFilter, true);
118
+ expect(!!f2.bioFilter, true);
119
+ expect(f1.bioFilter!.type, 'HelmBioFilter');
120
+ expect(f2.bioFilter!.type, 'HelmBioFilter');
121
+ const bf1 = f1.bioFilter as IBioFilter;
122
+ const bf2 = f2.bioFilter as IBioFilter;
123
+
124
+ await testEvent(df.onRowsFiltered, () => {}, () => {
125
+ bf1.props = new BioFilterProps(fSubStr, undefined, _package.logger);
126
+ }, 60000, 'await onRowsFiltered'); // wait to load monomers
127
+ await awaitGrid(view.grid);
128
+ //debugger;
129
+
130
+ _package.logger.debug('Bio tests: substructureFilters/sync-helm, before changed event');
131
+ await delay(f1.debounceTime * 2);
132
+ _package.logger.debug('Bio tests: substructureFilters/sync-helm, after changed event');
133
+ expect(df.filter.trueCount, fTrueCount);
134
+
135
+ await f1.awaitRendered();
136
+ expect((bf2.props as BioFilterProps).substructure, fSubStr);
137
+ } finally {
138
+ f1.detach();
139
+ f2.detach();
140
+ dlg.close();
141
+ }
142
+ await Promise.all([f1.awaitRendered(), f2.awaitRendered()]);
143
+ await awaitGrid(view.grid);
144
+ await delay(3000); //TODO: await for grid.onLookChanged
145
+ });
146
+
147
+
148
+ async function createFilter(colName: string, df: DG.DataFrame): Promise<any> {
149
+ if (!df.columns.names().includes(colName)) {
150
+ throw new Error(`The column '${colName}' not found. ` +
151
+ `Available in data frame are ${JSON.stringify(df.columns.names())}`);
152
+ }
153
+
154
+ const filter = await grok.functions.call('Bio:bioSubstructureFilterTest');
155
+ filter.attach(df);
156
+ filter.applyState({columnName: colName});
157
+ filter.column = df.col(colName);
158
+ filter.columnName = colName;
159
+ //filter.tableName = df.name;
160
+ return filter;
161
+ };
162
+ } );
163
+
@@ -0,0 +1,96 @@
1
+ import * as DG from 'datagrok-api/dg';
2
+ import * as grok from 'datagrok-api/grok';
3
+
4
+ import {after, before, category, expect, test} from '@datagrok-libraries/utils/src/test';
5
+ import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
6
+ import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
7
+ import {getUserLibSettings, setUserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
8
+ import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
9
+
10
+ import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
11
+ import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
12
+ import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
13
+
14
+ type TestDataTargetType = { atomCount: number, bondCount: number };
15
+ type TestDataType = {
16
+ src: { seq: string, units: NOTATION },
17
+ tgt: TestDataTargetType,
18
+ };
19
+
20
+ category('toAtomicLevel-ui', () => {
21
+ let monomerLibHelper: IMonomerLibHelper;
22
+ let userLibSettings: UserLibSettings;
23
+ let monomerLib: IMonomerLib;
24
+ let rdKitModule: RDModule;
25
+
26
+ before(async () => {
27
+ rdKitModule = await getRdKitModule();
28
+ monomerLibHelper = await getMonomerLibHelper();
29
+ userLibSettings = await getUserLibSettings();
30
+
31
+ // Test 'helm' requires default monomer library loaded
32
+ await monomerLibHelper.loadMonomerLibForTests(); // load default libraries
33
+
34
+ monomerLib = monomerLibHelper.getMonomerLib();
35
+ });
36
+
37
+ after(async () => {
38
+ // UserDataStorage.put() replaces existing data
39
+ await setUserLibSettings(userLibSettings);
40
+ await monomerLibHelper.loadMonomerLib(true); // load user settings libraries
41
+ });
42
+
43
+ const tests: { [testName: string]: TestDataType } = {
44
+ 'fasta': {
45
+ src: {seq: 'MDYKETLLMPK', units: NOTATION.FASTA},
46
+ tgt: {atomCount: 94, bondCount: 95},
47
+ },
48
+ 'fasta-with-gap': {
49
+ src: {seq: 'MD-YKETLLMPK', units: NOTATION.FASTA},
50
+ tgt: {atomCount: 94, bondCount: 95},
51
+ },
52
+ 'helm': {
53
+ src: {seq: 'PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2}$$$$', units: NOTATION.HELM},
54
+ tgt: {atomCount: 68, bondCount: 68},
55
+ },
56
+ 'helm-with-gap': {
57
+ src: {seq: 'PEPTIDE1{meI.hHis.*.Aca.N.T.dK.Thr_PO3H2}$$$$', units: NOTATION.HELM},
58
+ tgt: {atomCount: 68, bondCount: 68},
59
+ },
60
+ };
61
+
62
+ const getDfAndSeqCol = async (testData: TestDataType): Promise<{df: DG.DataFrame, seqCol: DG.Column<string>}> => {
63
+ const seq = testData.src.seq;
64
+ const df = DG.DataFrame.fromColumns([DG.Column.fromList(DG.COLUMN_TYPE.STRING, 'seq', [seq])]);
65
+ await grok.data.detectSemanticTypes(df);
66
+ return {df: df, seqCol: df.getCol('seq')};
67
+ };
68
+
69
+ for (const [testName, testData] of Object.entries(tests)) {
70
+ test(`${testName}-nonlinear`, async () => {
71
+ const res = await getDfAndSeqCol(testData);
72
+ await _testToAtomicLevelFunc(res.df, res.seqCol, true, testData.tgt);
73
+ });
74
+ }
75
+
76
+ async function _testToAtomicLevelFunc(
77
+ df: DG.DataFrame, seqCol: DG.Column<string>, nonlinear: boolean, tgt: TestDataTargetType,
78
+ ): Promise<void> {
79
+ await grok.functions.call('Bio:toAtomicLevel', {
80
+ table: df, seqCol: seqCol, nonlinear: true, highlight: false
81
+ });
82
+ const molCol = df.col('molfile(seq)');
83
+ expect(molCol?.semType, DG.SEMTYPE.MOLECULE);
84
+ const resMolStr = molCol?.get(0)!;
85
+ const resRdMol = rdKitModule.get_mol(resMolStr);
86
+ expect(resRdMol != null, true, 'No molecule generated');
87
+ try {
88
+ const resAtomCount = resRdMol.get_num_atoms();
89
+ const resBondCount = resRdMol.get_num_bonds();
90
+ expect(resAtomCount, tgt.atomCount);
91
+ expect(resBondCount, tgt.bondCount);
92
+ } finally {
93
+ resRdMol.delete();
94
+ }
95
+ }
96
+ });
@@ -4,6 +4,7 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {delay, testEvent} from '@datagrok-libraries/utils/src/test';
6
6
  import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
7
+ import {_package} from '../package-test';
7
8
 
8
9
 
9
10
  export async function initHelmMainPackage(): Promise<void> {
@@ -15,3 +16,14 @@ export async function awaitGrid(grid: DG.Grid, timeout: number = 5000): Promise<
15
16
  await testEvent(grid.onAfterDrawContent, () => {},
16
17
  () => { grid.invalidate(); }, timeout);
17
18
  }
19
+
20
+ export async function readDataframe(tableName: string): Promise<DG.DataFrame> {
21
+ const file = await loadFileAsText(tableName);
22
+ const df = DG.DataFrame.fromCsv(file);
23
+ df.name = tableName.replace('.csv', '');
24
+ return df;
25
+ }
26
+
27
+ export async function loadFileAsText(name: string): Promise<string> {
28
+ return await _package.files.readAsText(name);
29
+ }
@@ -23,7 +23,7 @@ import {getHoveredMonomerFromEditorMol, getSeqMonomerFromHelmAtom} from './get-h
23
23
  import {_package, getHelmService} from '../package';
24
24
 
25
25
  export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProps, HelmAux> {
26
- private _auxList: (HelmAux | null)[];
26
+ private _auxList: Map<string, HelmAux | null>;
27
27
 
28
28
  private sysMonomerLib: IMonomerLibBase | null = null;
29
29
  private helmHelper: IHelmHelper | null = null;
@@ -70,7 +70,7 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
70
70
  const logPrefix = `${this.toLog()}.reset()`;
71
71
  this.logger.debug(`${logPrefix}, start`);
72
72
  super.reset();
73
- this._auxList = new Array<HelmAux | null>(this.tableCol.length).fill(null);
73
+ this._auxList = new Map<string, HelmAux | null>();
74
74
  this.invalidateGrid();
75
75
  this.logger.debug(`${logPrefix}, end`);
76
76
  }
@@ -89,8 +89,8 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
89
89
  protected override storeAux(gridCell: DG.GridCell, aux: HelmAux): void {
90
90
  const logPrefix = `${this.toLog()}.storeAux()`;
91
91
  this.logger.debug(`${logPrefix}, start`);
92
- if (gridCell.tableRowIndex !== null)
93
- this._auxList[gridCell.tableRowIndex] = aux;
92
+ if (!!gridCell.cell?.value)
93
+ this._auxList.set(gridCell.cell.value, aux);
94
94
  }
95
95
 
96
96
  /** Renders cell from image data (cache), returns true to update the cell by service.
@@ -104,9 +104,11 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
104
104
 
105
105
  const gcb = gridCellBounds;
106
106
  const dpr = window.devicePixelRatio;
107
- if (gridCell.tableRowIndex === null) return false;
108
- const aux = this._auxList[gridCell.tableRowIndex];
109
- if (!aux) return true;
107
+ if (!gridCell.cell?.value)
108
+ return false;
109
+ const aux = this._auxList.get(gridCell.cell.value);
110
+ if (!aux)
111
+ return true;
110
112
 
111
113
  const [cellWidth, cellHeight] = [gcb.width * dpr - 2, gcb.height * dpr - 2];
112
114
  const cellDScale = Math.min(0.95 * cellWidth / aux.dBox.width, 0.95 * cellHeight / aux.dBox.height);
@@ -158,8 +160,8 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
158
160
  }
159
161
 
160
162
  onMouseMove(gridCell: DG.GridCell, e: MouseEvent): void {
161
- if (gridCell.tableRowIndex === null || !this._auxList) return;
162
- const aux = this._auxList[gridCell.tableRowIndex];
163
+ if (!gridCell.cell?.value || !this._auxList || !!e.buttons) return;
164
+ const aux = this._auxList.get(gridCell.cell.value);
163
165
  if (!aux) return;
164
166
 
165
167
  const logPrefix = `${this.toLog()}.onMouseMove()`;
@@ -192,8 +194,11 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
192
194
  // Tooltip for missing monomers
193
195
  ui.tooltip.hide();
194
196
  }
195
-
196
197
  execMonomerHoverLinks(gridCell, seqMonomer);
198
+
199
+ e.preventDefault();
200
+ e.stopPropagation();
201
+
197
202
  }
198
203
 
199
204
  onMouseLeave(gridCell: DG.GridCell, e: MouseEvent): void {
@@ -237,9 +242,6 @@ export class HelmGridCellRenderer extends DG.GridCellRenderer {
237
242
  } catch (err: any) {
238
243
  const [errMsg, errStack] = errInfo(err);
239
244
  _package.logger.error(errMsg, undefined, errStack);
240
- } finally {
241
- e.preventDefault();
242
- e.stopPropagation();
243
245
  }
244
246
  }
245
247