@datagrok/peptides 1.9.3 → 1.11.3
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/CHANGELOG.md +81 -0
- package/dist/209.js +2 -0
- package/dist/521.js +2 -0
- package/dist/535.js +2 -0
- package/dist/729.js +2 -0
- package/dist/959.js +2 -0
- package/dist/package-test.js +2 -2
- package/dist/package.js +2 -2
- package/package.json +13 -11
- package/setup-unlink-clean.sh +0 -0
- package/src/model.ts +302 -232
- package/src/package-test.ts +2 -1
- package/src/package.ts +14 -16
- package/src/tests/algorithms.ts +4 -1
- package/src/tests/core.ts +100 -14
- package/src/tests/model.ts +16 -14
- package/src/tests/peptide-space-test.ts +7 -7
- package/src/tests/table-view.ts +63 -54
- package/src/tests/utils.ts +1 -1
- package/src/tests/viewers.ts +40 -6
- package/src/tests/widgets.ts +100 -18
- package/src/utils/cell-renderer.ts +38 -20
- package/src/utils/constants.ts +3 -0
- package/src/utils/misc.ts +41 -10
- package/src/utils/peptide-similarity-space.ts +3 -4
- package/src/utils/statistics.ts +2 -2
- package/src/utils/types.ts +3 -1
- package/src/viewers/logo-summary.ts +132 -140
- package/src/viewers/peptide-space-viewer.ts +2 -1
- package/src/viewers/sar-viewer.ts +46 -39
- package/src/widgets/distribution.ts +17 -17
- package/src/widgets/mutation-cliffs.ts +91 -19
- package/src/widgets/peptides.ts +11 -11
- package/src/widgets/settings.ts +47 -25
- package/src/widgets/similarity.ts +39 -0
- package/dist/168.js +0 -2
- package/dist/478.js +0 -2
- package/dist/802.js +0 -2
- package/dist/951.js +0 -2
package/src/package-test.ts
CHANGED
|
@@ -2,7 +2,8 @@ import * as DG from 'datagrok-api/dg';
|
|
|
2
2
|
import {runTests, tests, TestContext} from '@datagrok-libraries/utils/src/test';
|
|
3
3
|
|
|
4
4
|
import './tests/core';
|
|
5
|
-
|
|
5
|
+
//FIXME: fails on CI; crashes browser
|
|
6
|
+
// import './tests/peptide-space-test';
|
|
6
7
|
import './tests/algorithms';
|
|
7
8
|
import './tests/viewers';
|
|
8
9
|
import './tests/widgets';
|
package/src/package.ts
CHANGED
|
@@ -6,7 +6,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
6
6
|
import {analyzePeptidesUI} from './widgets/peptides';
|
|
7
7
|
import {PeptideSimilaritySpaceWidget} from './utils/peptide-similarity-space';
|
|
8
8
|
import {manualAlignmentWidget} from './widgets/manual-alignment';
|
|
9
|
-
import {MonomerPosition,
|
|
9
|
+
import {MonomerPosition, MostPotentResidues} from './viewers/sar-viewer';
|
|
10
10
|
import {getTreeHelper, ITreeHelper} from '@datagrok-libraries/bio/src/trees/tree-helper';
|
|
11
11
|
import {IDendrogramService, getDendrogramService} from '@datagrok-libraries/bio/src/trees/dendrogram';
|
|
12
12
|
import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
|
|
@@ -17,27 +17,25 @@ import {macromoleculeSarFastaDemoUI} from './demo/fasta';
|
|
|
17
17
|
|
|
18
18
|
let monomerWorks: MonomerWorks | null = null;
|
|
19
19
|
let treeHelper: ITreeHelper | null = null;
|
|
20
|
-
let dendrogramService: IDendrogramService | null = null;
|
|
21
20
|
|
|
22
21
|
export const _package = new DG.Package();
|
|
23
22
|
|
|
24
|
-
export function getMonomerWorksInstance(): MonomerWorks {
|
|
25
|
-
return monomerWorks
|
|
23
|
+
export function getMonomerWorksInstance(): MonomerWorks | null {
|
|
24
|
+
return monomerWorks;
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
export function getTreeHelperInstance(): ITreeHelper {
|
|
29
|
-
return treeHelper
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function getDendrogramServiceInstance(): IDendrogramService {
|
|
33
|
-
return dendrogramService!;
|
|
27
|
+
export function getTreeHelperInstance(): ITreeHelper | null {
|
|
28
|
+
return treeHelper;
|
|
34
29
|
}
|
|
35
30
|
|
|
36
31
|
//tags: init
|
|
37
32
|
export async function initPeptides(): Promise<void> {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
try {
|
|
34
|
+
monomerWorks ??= new MonomerWorks(await grok.functions.call('Bio:getBioLib'));
|
|
35
|
+
treeHelper ??= await getTreeHelper();
|
|
36
|
+
} catch (e) {
|
|
37
|
+
grok.log.error(e as string);
|
|
38
|
+
}
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
async function openDemoData(chosenFile: string): Promise<void> {
|
|
@@ -92,7 +90,7 @@ export function Peptides(): void {
|
|
|
92
90
|
]);
|
|
93
91
|
}
|
|
94
92
|
|
|
95
|
-
//top-menu: Bio |
|
|
93
|
+
//top-menu: Bio | Analyze | SAR...
|
|
96
94
|
//name: Bio Peptides
|
|
97
95
|
export function peptidesDialog(): DG.Dialog {
|
|
98
96
|
const analyzeObject = analyzePeptidesUI(grok.shell.t);
|
|
@@ -127,8 +125,8 @@ export function monomerPosition(): MonomerPosition {
|
|
|
127
125
|
//tags: viewer
|
|
128
126
|
//meta.icon: files/icons/peptide-sar-vertical-viewer.svg
|
|
129
127
|
//output: viewer result
|
|
130
|
-
export function mostPotentResidues():
|
|
131
|
-
return new
|
|
128
|
+
export function mostPotentResidues(): MostPotentResidues {
|
|
129
|
+
return new MostPotentResidues();
|
|
132
130
|
}
|
|
133
131
|
|
|
134
132
|
//name: Logo Summary Table
|
package/src/tests/algorithms.ts
CHANGED
|
@@ -56,6 +56,9 @@ category('Algorithms', () => {
|
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
test('MutationCliffs - Benchmark 5k', async () => {
|
|
59
|
+
if (!DG.Test.isInBenchmark)
|
|
60
|
+
return;
|
|
61
|
+
|
|
59
62
|
const df = (await _package.files.readBinaryDataFrames('tests/aligned_5k.d42'))[0];
|
|
60
63
|
const activityCol: type.RawData = df.getCol('Activity').getRawData();
|
|
61
64
|
const monomerCols: type.RawColumn[] = [];
|
|
@@ -64,5 +67,5 @@ category('Algorithms', () => {
|
|
|
64
67
|
monomerCols.push({name: col.name, rawData: col.getRawData(), cat: col.categories});
|
|
65
68
|
}
|
|
66
69
|
DG.time('MutationCliffs', () => findMutations(activityCol, monomerCols));
|
|
67
|
-
}, {
|
|
70
|
+
}, {timeout: 5000});
|
|
68
71
|
});
|
package/src/tests/core.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as grok from 'datagrok-api/grok';
|
|
2
2
|
import * as DG from 'datagrok-api/dg';
|
|
3
3
|
|
|
4
|
-
import {category, test, expect,
|
|
4
|
+
import {category, test, expect, awaitCheck} from '@datagrok-libraries/utils/src/test';
|
|
5
5
|
|
|
6
6
|
import {_package} from '../package-test';
|
|
7
7
|
import {startAnalysis} from '../widgets/peptides';
|
|
@@ -37,11 +37,28 @@ category('Core', () => {
|
|
|
37
37
|
|
|
38
38
|
model = await startAnalysis(
|
|
39
39
|
simpleActivityCol, simpleAlignedSeqCol, null, simpleTable, simpleScaledCol, C.SCALING_METHODS.MINUS_LG);
|
|
40
|
-
expect(model instanceof PeptidesModel, true);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
expect(model instanceof PeptidesModel, true, 'Model is null');
|
|
41
|
+
let overlayInit = false;
|
|
42
|
+
grok.log.debug('Waiting for overlay...');
|
|
43
|
+
model!._analysisView!.grid.onAfterDrawOverlay.subscribe(() => {
|
|
44
|
+
overlayInit = true;
|
|
45
|
+
grok.log.debug('Overlay initialized');
|
|
46
|
+
});
|
|
47
|
+
model!._analysisView!.grid.onBeforeDrawOverlay.subscribe(() => {
|
|
48
|
+
overlayInit = false;
|
|
49
|
+
grok.log.debug('Overlay is drawing');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Ensure grid finished initializing to prevent Unhandled exceptions
|
|
53
|
+
let accrodionInit = false;
|
|
54
|
+
grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
|
|
55
|
+
await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
|
|
56
|
+
await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
|
|
57
|
+
await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
|
|
58
|
+
await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
|
|
59
|
+
|
|
60
|
+
model!.mutationCliffsSelection = {'11': ['D']};
|
|
61
|
+
}, {skipReason: 'GROK-13790: Unhandled exception'});
|
|
45
62
|
|
|
46
63
|
test('Start analysis: сomplex', async () => {
|
|
47
64
|
const complexActivityColName = 'Activity';
|
|
@@ -57,11 +74,28 @@ category('Core', () => {
|
|
|
57
74
|
|
|
58
75
|
model = await startAnalysis(
|
|
59
76
|
complexActivityCol, complexAlignedSeqCol, null, complexTable, complexScaledCol, C.SCALING_METHODS.MINUS_LG);
|
|
60
|
-
expect(model instanceof PeptidesModel, true);
|
|
77
|
+
expect(model instanceof PeptidesModel, true, 'Model is null');
|
|
78
|
+
let overlayInit = false;
|
|
79
|
+
model!._analysisView!.grid.onAfterDrawOverlay.subscribe(() => {
|
|
80
|
+
overlayInit = true;
|
|
81
|
+
grok.log.debug('Overlay initialized');
|
|
82
|
+
});
|
|
83
|
+
model!._analysisView!.grid.onBeforeDrawOverlay.subscribe(() => {
|
|
84
|
+
overlayInit = false;
|
|
85
|
+
grok.log.debug('Overlay is drawing');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Ensure grid finished initializing to prevent Unhandled exceptions
|
|
89
|
+
let accrodionInit = false;
|
|
90
|
+
grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
|
|
91
|
+
await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
|
|
92
|
+
await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
|
|
93
|
+
await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
|
|
94
|
+
await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
|
|
61
95
|
|
|
62
96
|
if (model !== null)
|
|
63
|
-
model.
|
|
64
|
-
});
|
|
97
|
+
model.mutationCliffsSelection = {'13': ['-']};
|
|
98
|
+
}, {skipReason: 'GROK-13790: Unhandled exception'});
|
|
65
99
|
|
|
66
100
|
test('Save and load project', async () => {
|
|
67
101
|
const simpleActivityColName = 'IC50';
|
|
@@ -76,7 +110,19 @@ category('Core', () => {
|
|
|
76
110
|
|
|
77
111
|
model = await startAnalysis(
|
|
78
112
|
simpleActivityCol, simpleAlignedSeqCol, null, simpleTable, simpleScaledCol, C.SCALING_METHODS.MINUS_LG);
|
|
113
|
+
|
|
79
114
|
let v = grok.shell.getTableView('Peptides analysis');
|
|
115
|
+
let overlayInit = false;
|
|
116
|
+
v.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
|
|
117
|
+
|
|
118
|
+
// Ensure grid finished initializing to prevent Unhandled exceptions
|
|
119
|
+
let accrodionInit = false;
|
|
120
|
+
grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
|
|
121
|
+
await awaitCheck(() => v.table!.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
|
|
122
|
+
await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
|
|
123
|
+
await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
|
|
124
|
+
await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
|
|
125
|
+
|
|
80
126
|
const d = v.dataFrame;
|
|
81
127
|
const layout = v.saveLayout();
|
|
82
128
|
const tableInfo = d.getTableInfo();
|
|
@@ -90,18 +136,30 @@ category('Core', () => {
|
|
|
90
136
|
const sti = await grok.dapi.tables.save(tableInfo);
|
|
91
137
|
const sp = await grok.dapi.projects.save(project);
|
|
92
138
|
|
|
93
|
-
|
|
94
|
-
await
|
|
139
|
+
v.close();
|
|
140
|
+
await awaitCheck(() => typeof grok.shell.tableView('Peptides analysis') === 'undefined', 'Table never closed', 2000);
|
|
95
141
|
|
|
96
142
|
await sp.open();
|
|
97
143
|
v = grok.shell.getTableView('Peptides analysis');
|
|
144
|
+
overlayInit = false;
|
|
145
|
+
v.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
|
|
98
146
|
|
|
99
147
|
await grok.dapi.layouts.delete(sl);
|
|
100
148
|
await grok.dapi.tables.delete(sti);
|
|
101
149
|
await grok.dapi.projects.delete(sp);
|
|
150
|
+
|
|
151
|
+
// Ensure grid finished initializing to prevent Unhandled exceptions
|
|
152
|
+
accrodionInit = false;
|
|
153
|
+
grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
|
|
154
|
+
await awaitCheck(() => v.table!.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
|
|
155
|
+
await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
|
|
156
|
+
await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
|
|
102
157
|
});
|
|
103
158
|
|
|
104
159
|
test('Cluster stats - Benchmark HELM 5k', async () => {
|
|
160
|
+
if (!DG.Test.isInBenchmark)
|
|
161
|
+
return;
|
|
162
|
+
|
|
105
163
|
const df = (await _package.files.readBinaryDataFrames('tests/aligned_5k_2.d42'))[0];
|
|
106
164
|
const activityCol = df.getCol('Activity');
|
|
107
165
|
const scaledActivityCol = scaleActivity(activityCol, C.SCALING_METHODS.NONE);
|
|
@@ -112,11 +170,21 @@ category('Core', () => {
|
|
|
112
170
|
const model = await startAnalysis(
|
|
113
171
|
activityCol, sequenceCol, clustersCol, df, scaledActivityCol, C.SCALING_METHODS.NONE);
|
|
114
172
|
|
|
173
|
+
// Ensure grid finished initializing to prevent Unhandled exceptions
|
|
174
|
+
let accrodionInit = false;
|
|
175
|
+
grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
|
|
176
|
+
await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
|
|
177
|
+
await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
|
|
178
|
+
await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
|
|
179
|
+
|
|
115
180
|
for (let i = 0; i < 5; ++i)
|
|
116
181
|
DG.time('Cluster stats', () => model?.calculateClusterStatistics());
|
|
117
|
-
}, {
|
|
182
|
+
}, {timeout: 10000});
|
|
118
183
|
|
|
119
184
|
test('Monomer Position stats - Benchmark HELM 5k', async () => {
|
|
185
|
+
if (!DG.Test.isInBenchmark)
|
|
186
|
+
return;
|
|
187
|
+
|
|
120
188
|
const df = (await _package.files.readBinaryDataFrames('tests/aligned_5k.d42'))[0];
|
|
121
189
|
const activityCol = df.getCol('Activity');
|
|
122
190
|
const scaledActivityCol = scaleActivity(activityCol, C.SCALING_METHODS.NONE);
|
|
@@ -127,11 +195,21 @@ category('Core', () => {
|
|
|
127
195
|
const model = await startAnalysis(
|
|
128
196
|
activityCol, sequenceCol, clustersCol, df, scaledActivityCol, C.SCALING_METHODS.NONE);
|
|
129
197
|
|
|
198
|
+
// Ensure grid finished initializing to prevent Unhandled exceptions
|
|
199
|
+
let accrodionInit = false;
|
|
200
|
+
grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
|
|
201
|
+
await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
|
|
202
|
+
await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
|
|
203
|
+
await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
|
|
204
|
+
|
|
130
205
|
for (let i = 0; i < 5; ++i)
|
|
131
206
|
DG.time('Monomer position stats', () => model?.calculateMonomerPositionStatistics());
|
|
132
|
-
}, {
|
|
207
|
+
}, {timeout: 10000});
|
|
133
208
|
|
|
134
209
|
test('Analysis start - Benchmark HELM 5k', async () => {
|
|
210
|
+
if (!DG.Test.isInBenchmark)
|
|
211
|
+
return;
|
|
212
|
+
|
|
135
213
|
const df = (await _package.files.readBinaryDataFrames('tests/aligned_5k.d42'))[0];
|
|
136
214
|
const activityCol = df.getCol('Activity');
|
|
137
215
|
const scaledActivityCol = scaleActivity(activityCol, C.SCALING_METHODS.NONE);
|
|
@@ -144,9 +222,17 @@ category('Core', () => {
|
|
|
144
222
|
await DG.timeAsync('Analysis start', async () => {
|
|
145
223
|
const model = await startAnalysis(
|
|
146
224
|
activityCol, sequenceCol, clustersCol, df, scaledActivityCol, C.SCALING_METHODS.NONE);
|
|
225
|
+
|
|
226
|
+
// Ensure grid finished initializing to prevent Unhandled exceptions
|
|
227
|
+
let accrodionInit = false;
|
|
228
|
+
grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
|
|
229
|
+
await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
|
|
230
|
+
await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
|
|
231
|
+
await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
|
|
232
|
+
|
|
147
233
|
if (model)
|
|
148
234
|
grok.shell.closeTable(model.df);
|
|
149
235
|
});
|
|
150
236
|
}
|
|
151
|
-
}, {
|
|
237
|
+
}, {timeout: 10000});
|
|
152
238
|
});
|
package/src/tests/model.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
1
2
|
import * as DG from 'datagrok-api/dg';
|
|
2
3
|
|
|
3
|
-
import {category, test, before, expect, expectFloat,
|
|
4
|
+
import {category, test, before, expect, expectFloat, awaitCheck} from '@datagrok-libraries/utils/src/test';
|
|
4
5
|
import {_package} from '../package-test';
|
|
5
6
|
import {PeptidesModel, VIEWER_TYPE, getAggregatedColName} from '../model';
|
|
6
7
|
import {startAnalysis} from '../widgets/peptides';
|
|
@@ -34,14 +35,23 @@ category('Model: Settings', () => {
|
|
|
34
35
|
if (tempModel === null)
|
|
35
36
|
throw new Error('Model is null');
|
|
36
37
|
model = tempModel;
|
|
38
|
+
let overlayInit = false;
|
|
39
|
+
model._analysisView!.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
|
|
40
|
+
|
|
41
|
+
// Ensure grid finished initializing to prevent Unhandled exceptions
|
|
42
|
+
let accrodionInit = false;
|
|
43
|
+
grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
|
|
44
|
+
await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
|
|
45
|
+
await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
|
|
46
|
+
await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
|
|
47
|
+
await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
|
|
37
48
|
});
|
|
38
49
|
|
|
39
50
|
test('Activity scaling', async () => {
|
|
40
51
|
const getError = (row: number, method: SCALING_METHODS): string =>
|
|
41
52
|
`Activity mismatch at row ${row} for scaling method '${method}'`;
|
|
42
53
|
const tolerance = 0.0001;
|
|
43
|
-
const origActivityData =
|
|
44
|
-
model.df.getCol(model.settings.activityColumnName!).getRawData();
|
|
54
|
+
const origActivityData = model.df.getCol(model.settings.activityColumnName!).getRawData();
|
|
45
55
|
const scaledActivity = model.df.getCol(COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
46
56
|
const dfLen = model.df.rowCount;
|
|
47
57
|
|
|
@@ -113,9 +123,6 @@ category('Model: Settings', () => {
|
|
|
113
123
|
`'${Object.keys(testColumns)[0]}' with '${testColumns[columnName]}' but aggregated with ` +
|
|
114
124
|
`'${model.settings.columns![columnName]}' instead`);
|
|
115
125
|
|
|
116
|
-
expect(model.analysisView.grid.col(columnName)?.visible, true, `Expected to show column '${columnName}' but ` +
|
|
117
|
-
`it is hidden`);
|
|
118
|
-
|
|
119
126
|
const lstViewer = model.findViewer(VIEWER_TYPE.LOGO_SUMMARY_TABLE) as LogoSummaryTable;
|
|
120
127
|
const aggColName = getAggregatedColName(testColumns[columnName], columnName);
|
|
121
128
|
expect(lstViewer.viewerGrid.col(aggColName) !== null, true, `Expected to include column '${columnName}' in ` +
|
|
@@ -127,9 +134,6 @@ category('Model: Settings', () => {
|
|
|
127
134
|
`Expected to remove all column aggregations but columns {${Object.keys(model.settings.columns!).join(' & ')}} ` +
|
|
128
135
|
`are still included`);
|
|
129
136
|
|
|
130
|
-
expect(model.analysisView.grid.col(columnName)?.visible, false, `Expected to hide column '${columnName}' but ` +
|
|
131
|
-
`it is shown`);
|
|
132
|
-
|
|
133
137
|
expect(lstViewer.viewerGrid.col(aggColName) === null, true, `Expected to remove column '${columnName}' from ` +
|
|
134
138
|
`${VIEWER_TYPE.LOGO_SUMMARY_TABLE} but it is still present`);
|
|
135
139
|
});
|
|
@@ -139,10 +143,8 @@ category('Model: Settings', () => {
|
|
|
139
143
|
model.settings = {showDendrogram: true};
|
|
140
144
|
expect(model.settings.showDendrogram, true, 'Dendrogram is disabled after enabling');
|
|
141
145
|
|
|
142
|
-
await
|
|
143
|
-
|
|
144
|
-
expect(model.findViewer(VIEWER_TYPE.DENDROGRAM) !== null, true,
|
|
145
|
-
'Dendrogram is not present in the view after 5s delay');
|
|
146
|
+
await awaitCheck(() => model.findViewer(VIEWER_TYPE.DENDROGRAM) !== null,
|
|
147
|
+
'Dendrogram is not present in the view after 5s delay', 5000);
|
|
146
148
|
|
|
147
149
|
// Disable dendrogram
|
|
148
150
|
model.settings = {showDendrogram: false};
|
|
@@ -150,4 +152,4 @@ category('Model: Settings', () => {
|
|
|
150
152
|
expect(model.findViewer(VIEWER_TYPE.DENDROGRAM) === null, true,
|
|
151
153
|
'Dendrogram is present in the view after disabling');
|
|
152
154
|
}, {skipReason: 'Need to find a way to replace _package variable to call for Bio function with tests'});
|
|
153
|
-
});
|
|
155
|
+
}, {clear: false});
|
|
@@ -6,7 +6,7 @@ import {aligned1} from './test-data';
|
|
|
6
6
|
|
|
7
7
|
import * as DG from 'datagrok-api/dg';
|
|
8
8
|
import * as grok from 'datagrok-api/grok';
|
|
9
|
-
import {StringMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
|
|
9
|
+
import {DistanceMetricsSubjects, StringMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
|
|
10
10
|
|
|
11
11
|
let table: DG.DataFrame;
|
|
12
12
|
let view: DG.TableView;
|
|
@@ -25,21 +25,21 @@ category('Peptide space', async () => {
|
|
|
25
25
|
|
|
26
26
|
const alignedSequencesColumn = table.getCol('AlignedSequence');
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
category('Peptide space:test_deminsionality_reducer', async () => {
|
|
29
29
|
const columnData = cleanAlignedSequencesColumn(alignedSequencesColumn);
|
|
30
30
|
for (const method of DimensionalityReducer.availableMethods) {
|
|
31
|
-
for (const measure of DimensionalityReducer.availableMetricsByType(
|
|
32
|
-
test(
|
|
31
|
+
for (const measure of DimensionalityReducer.availableMetricsByType(DistanceMetricsSubjects.String)) {
|
|
32
|
+
test(`${method}.${measure}.is_numeric`, async () => {
|
|
33
33
|
await utils._testDimensionalityReducer(columnData, method as StringMetrics, measure);
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
category('Peptide space:test_peptide_similarity_space_viewer', async () => {
|
|
40
40
|
for (const method of DimensionalityReducer.availableMethods) {
|
|
41
|
-
for (const measure of DimensionalityReducer.availableMetricsByType(
|
|
42
|
-
test(
|
|
41
|
+
for (const measure of DimensionalityReducer.availableMetricsByType(DistanceMetricsSubjects.String)) {
|
|
42
|
+
test(`${method}.${measure}.is_proper`, async () => {
|
|
43
43
|
await utils._testPeptideSimilaritySpaceViewer(table, alignedSequencesColumn, method, measure, 100);//, view);
|
|
44
44
|
});
|
|
45
45
|
}
|
package/src/tests/table-view.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
1
2
|
import * as DG from 'datagrok-api/dg';
|
|
2
3
|
|
|
3
|
-
import {category, test, before, expect} from '@datagrok-libraries/utils/src/test';
|
|
4
|
+
import {category, test, before, expect, awaitCheck} from '@datagrok-libraries/utils/src/test';
|
|
4
5
|
import {_package} from '../package-test';
|
|
5
6
|
import {PeptidesModel} from '../model';
|
|
6
7
|
import {startAnalysis} from '../widgets/peptides';
|
|
@@ -18,8 +19,8 @@ category('Table view', () => {
|
|
|
18
19
|
let scaledActivityCol: DG.Column<number>;
|
|
19
20
|
const scaling = 'none' as SCALING_METHODS;
|
|
20
21
|
|
|
21
|
-
const
|
|
22
|
-
const
|
|
22
|
+
const firstPair = {monomer: 'Aze', position: '10', mcCount: 3, imCount: 1};
|
|
23
|
+
const secondPair = {monomer: 'meI', position: '1', mcCount: 2, imCount: 10};
|
|
23
24
|
const firstCluster = {name: '0', count: 3};
|
|
24
25
|
const secondCluster = {name: '1', count: 3};
|
|
25
26
|
|
|
@@ -35,58 +36,67 @@ category('Table view', () => {
|
|
|
35
36
|
if (tempModel === null)
|
|
36
37
|
throw new Error('Model is null');
|
|
37
38
|
model = tempModel;
|
|
39
|
+
let overlayInit = false;
|
|
40
|
+
model._analysisView!.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
|
|
41
|
+
|
|
42
|
+
// Ensure grid finished initializing to prevent Unhandled exceptions
|
|
43
|
+
let accrodionInit = false;
|
|
44
|
+
grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
|
|
45
|
+
await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
|
|
46
|
+
await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
|
|
47
|
+
await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
|
|
48
|
+
await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
|
|
38
49
|
});
|
|
39
50
|
|
|
40
51
|
test('Tooltip', async () => {
|
|
41
|
-
expect(model.showMonomerTooltip(
|
|
42
|
-
`Couldn't structure for monomer ${
|
|
52
|
+
expect(model.showMonomerTooltip(firstPair.monomer, 0, 0), true,
|
|
53
|
+
`Couldn't structure for monomer ${firstPair.monomer}`);
|
|
43
54
|
}, {skipReason: 'Need to find a way to replace _package variable to call for Bio function with tests'});
|
|
44
55
|
|
|
45
56
|
test('Visible columns', async () => {
|
|
46
57
|
const gridCols = model.analysisView.grid.columns;
|
|
47
58
|
const posCols = model.splitSeqDf.columns.names();
|
|
48
|
-
const visibleColumns = Object.keys(model.settings.columns ?? {});
|
|
49
59
|
for (let colIdx = 1; colIdx < gridCols.length; colIdx++) {
|
|
50
60
|
const col = gridCols.byIndex(colIdx)!;
|
|
51
61
|
const tableColName = col.column!.name;
|
|
52
|
-
const expectedVisibility = posCols.includes(tableColName) || (tableColName === COLUMNS_NAMES.ACTIVITY_SCALED)
|
|
53
|
-
visibleColumns.includes(tableColName);
|
|
62
|
+
const expectedVisibility = posCols.includes(tableColName) || (tableColName === COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
54
63
|
expect(col.visible, expectedVisibility, `Column ${tableColName} is visible === ${col.visible} but should be ` +
|
|
55
64
|
`${expectedVisibility}`);
|
|
56
65
|
}
|
|
57
66
|
});
|
|
58
67
|
|
|
59
|
-
|
|
68
|
+
//TODO: split into separate tests for Mutation Cliffs and Logo Summary Table
|
|
69
|
+
test('Mutation Cliffs selection', async () => {
|
|
60
70
|
const selection = model.df.selection;
|
|
61
71
|
|
|
62
|
-
for (const [position, selectedMonomers] of Object.entries(model.
|
|
72
|
+
for (const [position, selectedMonomers] of Object.entries(model.mutationCliffsSelection))
|
|
63
73
|
expect(selectedMonomers.length, 0, `Selection is not empty for position ${position} after initialization`);
|
|
64
74
|
|
|
65
75
|
// Select first monomer-position pair
|
|
66
|
-
model.modifyMonomerPositionSelection(
|
|
67
|
-
expect(model.
|
|
68
|
-
`Monomer ${
|
|
69
|
-
expect(selection.trueCount,
|
|
70
|
-
`for monomer ${
|
|
76
|
+
model.modifyMonomerPositionSelection(firstPair.monomer, firstPair.position, false);
|
|
77
|
+
expect(model.mutationCliffsSelection[firstPair.position].includes(firstPair.monomer), true,
|
|
78
|
+
`Monomer ${firstPair.monomer} is not selected at position ${firstPair.position}`);
|
|
79
|
+
expect(selection.trueCount, firstPair.mcCount, `Selection count is not equal to ${firstPair.mcCount} ` +
|
|
80
|
+
`for monomer ${firstPair.monomer} at position ${firstPair.position}`);
|
|
71
81
|
|
|
72
82
|
// Select second monomer-position pair
|
|
73
|
-
model.modifyMonomerPositionSelection(
|
|
74
|
-
expect(model.
|
|
75
|
-
`Monomer ${
|
|
76
|
-
expect(selection.trueCount,
|
|
77
|
-
`for monomer ${
|
|
83
|
+
model.modifyMonomerPositionSelection(secondPair.monomer, secondPair.position, false);
|
|
84
|
+
expect(model.mutationCliffsSelection[secondPair.position].includes(secondPair.monomer), true,
|
|
85
|
+
`Monomer ${secondPair.monomer} is not selected at position ${secondPair.position}`);
|
|
86
|
+
expect(selection.trueCount, secondPair.mcCount + firstPair.mcCount, `Selection count is not equal ` +
|
|
87
|
+
`to ${secondPair.mcCount + firstPair.mcCount} for monomer ${secondPair.monomer} at ` +
|
|
88
|
+
`position ${secondPair.position}`);
|
|
78
89
|
|
|
79
90
|
// Deselect second monomer-position pair
|
|
80
|
-
model.modifyMonomerPositionSelection(
|
|
81
|
-
expect(model.
|
|
82
|
-
`Monomer ${
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
`for monomer ${firstMonomerPair.monomer} at position ${firstMonomerPair.position}`);
|
|
91
|
+
model.modifyMonomerPositionSelection(secondPair.monomer, secondPair.position, false);
|
|
92
|
+
expect(model.mutationCliffsSelection[secondPair.position].includes(secondPair.monomer), false,
|
|
93
|
+
`Monomer ${secondPair.monomer} is still selected at position ${secondPair.position} after deselection`);
|
|
94
|
+
expect(selection.trueCount, firstPair.mcCount, `Selection count is not equal to ${firstPair.mcCount} ` +
|
|
95
|
+
`for monomer ${firstPair.monomer} at position ${firstPair.position}`);
|
|
86
96
|
|
|
87
97
|
// Clear monomer-position selection
|
|
88
|
-
model.
|
|
89
|
-
for (const [position, selectedMonomers] of Object.entries(model.
|
|
98
|
+
model.initMutationCliffsSelection({cleanInit: true});
|
|
99
|
+
for (const [position, selectedMonomers] of Object.entries(model.mutationCliffsSelection)) {
|
|
90
100
|
expect(selectedMonomers.length, 0, `Selection is not empty for position ${position} after clearing ` +
|
|
91
101
|
`monomer-position selection`);
|
|
92
102
|
}
|
|
@@ -119,43 +129,42 @@ category('Table view', () => {
|
|
|
119
129
|
expect(selection.trueCount, 0, `Selection count is not equal to 0 after clearing cluster selection`);
|
|
120
130
|
});
|
|
121
131
|
|
|
122
|
-
test('
|
|
123
|
-
const
|
|
132
|
+
test('Invariant Map selection', async () => {
|
|
133
|
+
const selection = model.df.selection;
|
|
124
134
|
|
|
125
|
-
for (const [position, filteredMonomers] of Object.entries(model.
|
|
135
|
+
for (const [position, filteredMonomers] of Object.entries(model.invariantMapSelection))
|
|
126
136
|
expect(filteredMonomers.length, 0, `Filter is not empty for position ${position} after initialization`);
|
|
127
137
|
|
|
128
|
-
//
|
|
129
|
-
model.modifyMonomerPositionSelection(
|
|
130
|
-
expect(model.
|
|
131
|
-
`Monomer ${
|
|
132
|
-
expect(
|
|
133
|
-
`for monomer ${
|
|
138
|
+
// Select by second monomer-position pair
|
|
139
|
+
model.modifyMonomerPositionSelection(secondPair.monomer, secondPair.position, true);
|
|
140
|
+
expect(model.invariantMapSelection[secondPair.position].includes(secondPair.monomer), true,
|
|
141
|
+
`Monomer ${secondPair.monomer} is not filtered at position ${secondPair.position}`);
|
|
142
|
+
expect(selection.trueCount, secondPair.imCount, `Filter count is not equal to ${secondPair.imCount} ` +
|
|
143
|
+
`for monomer ${secondPair.monomer} at position ${secondPair.position}`);
|
|
134
144
|
|
|
135
|
-
//
|
|
136
|
-
model.modifyMonomerPositionSelection(
|
|
137
|
-
expect(model.
|
|
138
|
-
`Monomer ${
|
|
139
|
-
expect(
|
|
140
|
-
`for monomer ${
|
|
145
|
+
// Select by first monomer-position pair
|
|
146
|
+
model.modifyMonomerPositionSelection(firstPair.monomer, firstPair.position, true);
|
|
147
|
+
expect(model.invariantMapSelection[firstPair.position].includes(firstPair.monomer), true,
|
|
148
|
+
`Monomer ${firstPair.monomer} is not filtered at position ${firstPair.position}`);
|
|
149
|
+
expect(selection.trueCount, secondPair.imCount, `Filter count is not equal to ${secondPair.imCount} ` +
|
|
150
|
+
`for monomer ${firstPair.monomer} at position ${firstPair.position}`);
|
|
141
151
|
|
|
142
152
|
// Deselect filter for second monomer-position pair
|
|
143
|
-
model.modifyMonomerPositionSelection(
|
|
144
|
-
expect(model.
|
|
145
|
-
`Monomer ${
|
|
153
|
+
model.modifyMonomerPositionSelection(secondPair.monomer, secondPair.position, true);
|
|
154
|
+
expect(model.invariantMapSelection[secondPair.position].includes(secondPair.monomer), false,
|
|
155
|
+
`Monomer ${secondPair.monomer} is still filtered at position ${secondPair.position} after ` +
|
|
146
156
|
`deselection`);
|
|
147
|
-
expect(
|
|
148
|
-
`for monomer ${
|
|
149
|
-
`monomer ${
|
|
157
|
+
expect(selection.trueCount, firstPair.imCount, `Filter count is not equal to ${firstPair.imCount} ` +
|
|
158
|
+
`for monomer ${firstPair.monomer} at position ${firstPair.position} after deselection of ` +
|
|
159
|
+
`monomer ${secondPair.monomer} at position ${secondPair.position}`);
|
|
150
160
|
|
|
151
161
|
// Clear selection
|
|
152
|
-
model.
|
|
153
|
-
expect(
|
|
154
|
-
`monomer-position filter`);
|
|
162
|
+
model.initInvariantMapSelection({cleanInit: true});
|
|
163
|
+
expect(selection.trueCount, 0, `Filter count is not equal to ${0} after clearing monomer-position filter`);
|
|
155
164
|
|
|
156
|
-
for (const [position, filteredMonomers] of Object.entries(model.
|
|
165
|
+
for (const [position, filteredMonomers] of Object.entries(model.invariantMapSelection)) {
|
|
157
166
|
expect(filteredMonomers.length, 0, `Filter is not empty for position ${position} after clearing ` +
|
|
158
167
|
`monomer-position filter`);
|
|
159
168
|
}
|
|
160
169
|
});
|
|
161
|
-
});
|
|
170
|
+
}, {clear: false});
|
package/src/tests/utils.ts
CHANGED
|
@@ -4,9 +4,9 @@ import {expect} from '@datagrok-libraries/utils/src/test';
|
|
|
4
4
|
import {PeptideSimilaritySpaceWidget, createPeptideSimilaritySpaceViewer} from '../utils/peptide-similarity-space';
|
|
5
5
|
import {
|
|
6
6
|
createDimensinalityReducingWorker,
|
|
7
|
-
IReduceDimensionalityResult,
|
|
8
7
|
} from '@datagrok-libraries/ml/src/workers/dimensionality-reducing-worker-creator';
|
|
9
8
|
import {StringMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
|
|
9
|
+
import {IReduceDimensionalityResult} from '@datagrok-libraries/ml/src/reduce-dimensionality';
|
|
10
10
|
|
|
11
11
|
export enum TEST_COLUMN_NAMES {
|
|
12
12
|
SEQUENCE = 'sequence',
|