@datagrok/peptides 1.9.0 → 1.9.1
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/dist/package-test.js +2 -2
- package/dist/package.js +2 -2
- package/package.json +1 -1
- package/src/model.ts +42 -31
- package/src/tests/core.ts +2 -2
- package/src/tests/model.ts +4 -3
- package/src/tests/table-view.ts +5 -4
- package/src/tests/utils.ts +6 -0
- package/src/tests/viewers.ts +10 -10
- package/src/tests/widgets.ts +96 -23
- package/src/utils/algorithms.ts +3 -3
- package/src/utils/cell-renderer.ts +1 -1
- package/src/utils/constants.ts +1 -2
- package/src/utils/misc.ts +2 -2
- package/src/utils/peptide-similarity-space.ts +2 -2
- package/src/viewers/logo-summary.ts +24 -20
- package/src/viewers/peptide-space-viewer.ts +2 -2
- package/src/viewers/sar-viewer.ts +6 -6
- package/src/widgets/mutation-cliffs.ts +1 -1
- package/src/widgets/peptides.ts +8 -8
- package/src/widgets/settings.ts +2 -2
package/package.json
CHANGED
package/src/model.ts
CHANGED
|
@@ -115,6 +115,14 @@ export class PeptidesModel {
|
|
|
115
115
|
return dataFrame.temp[PeptidesModel.modelName] as PeptidesModel;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
get id(): string {
|
|
119
|
+
const id = this.df.getTag(C.TAGS.UUID);
|
|
120
|
+
if (id === null || id === '')
|
|
121
|
+
throw new Error('PeptidesError: UUID is not defined');
|
|
122
|
+
|
|
123
|
+
return id;
|
|
124
|
+
}
|
|
125
|
+
|
|
118
126
|
get treeHelper(): ITreeHelper {
|
|
119
127
|
this._treeHelper ??= getTreeHelperInstance();
|
|
120
128
|
return this._treeHelper;
|
|
@@ -202,9 +210,9 @@ export class PeptidesModel {
|
|
|
202
210
|
|
|
203
211
|
get analysisView(): DG.TableView {
|
|
204
212
|
this._analysisView ??=
|
|
205
|
-
wu(grok.shell.tableViews).find(({dataFrame}) => dataFrame.getTag(C.TAGS.UUID)
|
|
213
|
+
wu(grok.shell.tableViews).find(({dataFrame}) => dataFrame.getTag(C.TAGS.UUID) === this.id) ??
|
|
206
214
|
grok.shell.addTableView(this.df);
|
|
207
|
-
if (this.df.getTag(C.MULTIPLE_VIEWS)
|
|
215
|
+
if (this.df.getTag(C.TAGS.MULTIPLE_VIEWS) !== '1')
|
|
208
216
|
grok.shell.v = this._analysisView;
|
|
209
217
|
|
|
210
218
|
return this._analysisView;
|
|
@@ -271,7 +279,7 @@ export class PeptidesModel {
|
|
|
271
279
|
|
|
272
280
|
get splitByPos(): boolean {
|
|
273
281
|
const splitByPosFlag = (this.df.tags['distributionSplit'] || '00')[0];
|
|
274
|
-
return splitByPosFlag
|
|
282
|
+
return splitByPosFlag === '1' ? true : false;
|
|
275
283
|
}
|
|
276
284
|
|
|
277
285
|
set splitByPos(flag: boolean) {
|
|
@@ -281,7 +289,7 @@ export class PeptidesModel {
|
|
|
281
289
|
|
|
282
290
|
get splitByAAR(): boolean {
|
|
283
291
|
const splitByPosFlag = (this.df.tags['distributionSplit'] || '00')[1];
|
|
284
|
-
return splitByPosFlag
|
|
292
|
+
return splitByPosFlag === '1' ? true : false;
|
|
285
293
|
}
|
|
286
294
|
|
|
287
295
|
set splitByAAR(flag: boolean) {
|
|
@@ -410,7 +418,7 @@ export class PeptidesModel {
|
|
|
410
418
|
|
|
411
419
|
const monomerCol = matrixDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
412
420
|
for (let i = 0; i < monomerCol.length; ++i) {
|
|
413
|
-
if (monomerCol.get(i)
|
|
421
|
+
if (monomerCol.get(i) === '') {
|
|
414
422
|
matrixDf.rows.removeAt(i);
|
|
415
423
|
break;
|
|
416
424
|
}
|
|
@@ -555,12 +563,12 @@ export class PeptidesModel {
|
|
|
555
563
|
colNames.push(sourceGridCols.byIndex(i)!);
|
|
556
564
|
|
|
557
565
|
colNames.sort((a, b) => {
|
|
558
|
-
if (a.column!.semType
|
|
559
|
-
if (b.column!.semType
|
|
566
|
+
if (a.column!.semType === C.SEM_TYPES.MONOMER) {
|
|
567
|
+
if (b.column!.semType === C.SEM_TYPES.MONOMER)
|
|
560
568
|
return 0;
|
|
561
569
|
return -1;
|
|
562
570
|
}
|
|
563
|
-
if (b.column!.semType
|
|
571
|
+
if (b.column!.semType === C.SEM_TYPES.MONOMER)
|
|
564
572
|
return 1;
|
|
565
573
|
return 0;
|
|
566
574
|
});
|
|
@@ -589,7 +597,7 @@ export class PeptidesModel {
|
|
|
589
597
|
|
|
590
598
|
for (let categoryIndex = 0; categoryIndex < posColCateogries.length; ++categoryIndex) {
|
|
591
599
|
const monomer = posColCateogries[categoryIndex];
|
|
592
|
-
if (monomer
|
|
600
|
+
if (monomer === '')
|
|
593
601
|
continue;
|
|
594
602
|
|
|
595
603
|
const bitArray = BitArray.fromSeq(sourceDfLen, (i: number) => posColData[i] === categoryIndex);
|
|
@@ -604,7 +612,7 @@ export class PeptidesModel {
|
|
|
604
612
|
}
|
|
605
613
|
|
|
606
614
|
getSummaryStats(genObj: SummaryStats, stats: Stats | null = null, summaryStats: SummaryStats | null = null): void {
|
|
607
|
-
if (stats
|
|
615
|
+
if (stats === null && summaryStats === null)
|
|
608
616
|
throw new Error(`MonomerPositionStatsError: either stats or summaryStats must be present`);
|
|
609
617
|
|
|
610
618
|
const possibleMaxCount = stats?.count ?? summaryStats!.maxCount;
|
|
@@ -671,9 +679,9 @@ export class PeptidesModel {
|
|
|
671
679
|
const customClustStats: ClusterStats = {};
|
|
672
680
|
|
|
673
681
|
for (let clustType = 0; clustType < 2; ++clustType) {
|
|
674
|
-
const masks = clustType
|
|
675
|
-
const clustNames = clustType
|
|
676
|
-
const resultStats = clustType
|
|
682
|
+
const masks = clustType === 0 ? origClustMasks : customClustMasks;
|
|
683
|
+
const clustNames = clustType === 0 ? origClustColCat : customClustColNamesList;
|
|
684
|
+
const resultStats = clustType === 0 ? origClustStats : customClustStats;
|
|
677
685
|
for (let maskIdx = 0; maskIdx < masks.length; ++maskIdx) {
|
|
678
686
|
const mask = masks[maskIdx];
|
|
679
687
|
const stats = getStats(activityColData, mask);
|
|
@@ -706,15 +714,15 @@ export class PeptidesModel {
|
|
|
706
714
|
|
|
707
715
|
const filteredMonomerStats = Object.entries(positionStats).filter((v) => {
|
|
708
716
|
const key = v[0];
|
|
709
|
-
if (key
|
|
717
|
+
if (key === 'general')
|
|
710
718
|
return false;
|
|
711
719
|
|
|
712
|
-
return (v[1] as Stats).pValue
|
|
720
|
+
return (v[1] as Stats).pValue === generalPositionStats.minPValue;
|
|
713
721
|
}) as [string, Stats][];
|
|
714
722
|
|
|
715
723
|
let maxEntry: [string, Stats];
|
|
716
724
|
for (const [monomer, monomerStats] of filteredMonomerStats) {
|
|
717
|
-
if (typeof maxEntry!
|
|
725
|
+
if (typeof maxEntry! === 'undefined' || maxEntry[1].meanDifference < monomerStats.meanDifference)
|
|
718
726
|
maxEntry = [monomer, monomerStats];
|
|
719
727
|
}
|
|
720
728
|
|
|
@@ -753,7 +761,7 @@ export class PeptidesModel {
|
|
|
753
761
|
const sourceView = this.analysisView.grid;
|
|
754
762
|
const eventAction = (ev: MouseEvent): void => {
|
|
755
763
|
const cell = sourceView.hitTest(ev.offsetX, ev.offsetY);
|
|
756
|
-
if (cell?.isColHeader && cell.tableColumn?.semType
|
|
764
|
+
if (cell?.isColHeader && cell.tableColumn?.semType === C.SEM_TYPES.MONOMER) {
|
|
757
765
|
const newBarPart = this.findAARandPosition(cell, ev);
|
|
758
766
|
this.requestBarchartAction(ev, newBarPart);
|
|
759
767
|
}
|
|
@@ -790,7 +798,7 @@ export class PeptidesModel {
|
|
|
790
798
|
this.modifyMonomerPositionSelection(monomer, position, false);
|
|
791
799
|
} else {
|
|
792
800
|
const bar = `${position} = ${monomer}`;
|
|
793
|
-
if (this.cachedWebLogoTooltip.bar
|
|
801
|
+
if (this.cachedWebLogoTooltip.bar === bar)
|
|
794
802
|
ui.tooltip.show(this.cachedWebLogoTooltip.tooltip!, ev.clientX, ev.clientY);
|
|
795
803
|
else
|
|
796
804
|
this.cachedWebLogoTooltip = {bar: bar, tooltip: this.showTooltipAt(monomer, position, ev.clientX, ev.clientY)};
|
|
@@ -815,16 +823,16 @@ export class PeptidesModel {
|
|
|
815
823
|
ctx.clip();
|
|
816
824
|
|
|
817
825
|
//TODO: optimize
|
|
818
|
-
if (gcArgs.cell.isColHeader && col?.semType
|
|
826
|
+
if (gcArgs.cell.isColHeader && col?.semType === C.SEM_TYPES.MONOMER) {
|
|
819
827
|
const stats = this.monomerPositionStats[col.name];
|
|
820
828
|
//TODO: precalc on stats creation
|
|
821
829
|
const sortedStatsOrder = Object.keys(stats).sort((a, b) => {
|
|
822
|
-
if (a
|
|
830
|
+
if (a === '' || a === '-')
|
|
823
831
|
return -1;
|
|
824
|
-
else if (b
|
|
832
|
+
else if (b === '' || b === '-')
|
|
825
833
|
return +1;
|
|
826
834
|
return 0;
|
|
827
|
-
}).filter((v) => v
|
|
835
|
+
}).filter((v) => v !== 'general');
|
|
828
836
|
|
|
829
837
|
this.webLogoBounds[col.name] = CR.drawLogoInBounds(ctx, bounds, stats, sortedStatsOrder, this.df.rowCount,
|
|
830
838
|
this.cp, this.headerSelectedMonomers[col.name]);
|
|
@@ -1011,7 +1019,7 @@ export class PeptidesModel {
|
|
|
1011
1019
|
this.headerSelectedMonomers = calculateSelected(this.df);
|
|
1012
1020
|
|
|
1013
1021
|
const acc = this.createAccordion();
|
|
1014
|
-
if (acc
|
|
1022
|
+
if (acc !== null) {
|
|
1015
1023
|
grok.shell.o = acc.root;
|
|
1016
1024
|
for (const pane of acc.panes)
|
|
1017
1025
|
pane.expanded = true;
|
|
@@ -1092,7 +1100,7 @@ export class PeptidesModel {
|
|
|
1092
1100
|
return;
|
|
1093
1101
|
this.isInitialized = true;
|
|
1094
1102
|
|
|
1095
|
-
if (!this.isRibbonSet && this.df.getTag(C.MULTIPLE_VIEWS)
|
|
1103
|
+
if (!this.isRibbonSet && this.df.getTag(C.TAGS.MULTIPLE_VIEWS) !== '1') {
|
|
1096
1104
|
//TODO: don't pass model, pass parameters instead
|
|
1097
1105
|
const settingsButton = ui.iconFA('wrench', () => getSettingsDialog(this), 'Peptides analysis settings');
|
|
1098
1106
|
this.analysisView.setRibbonPanels([[settingsButton]], false);
|
|
@@ -1158,18 +1166,21 @@ export class PeptidesModel {
|
|
|
1158
1166
|
this.analysisView.grid.col(newClusterCol.name)!.visible = false;
|
|
1159
1167
|
}
|
|
1160
1168
|
|
|
1161
|
-
createNewView():
|
|
1169
|
+
createNewView(): string {
|
|
1162
1170
|
const rowMask = this.getCompoundBitset();
|
|
1163
|
-
|
|
1164
|
-
return grok.shell.warning('Cannot create a new view, there are no visible selected rows in your dataset');
|
|
1171
|
+
const newDfId = uuid.v4();
|
|
1165
1172
|
|
|
1166
1173
|
const newDf = this.df.clone(rowMask);
|
|
1167
1174
|
for (const [tag, value] of newDf.tags)
|
|
1168
|
-
newDf.setTag(tag, tag
|
|
1175
|
+
newDf.setTag(tag, tag === C.TAGS.SETTINGS ? value : '');
|
|
1176
|
+
|
|
1169
1177
|
newDf.name = 'Peptides Multiple Views';
|
|
1170
|
-
newDf.setTag(C.MULTIPLE_VIEWS, '1');
|
|
1171
|
-
newDf.setTag(C.TAGS.UUID,
|
|
1178
|
+
newDf.setTag(C.TAGS.MULTIPLE_VIEWS, '1');
|
|
1179
|
+
newDf.setTag(C.TAGS.UUID, newDfId);
|
|
1180
|
+
|
|
1172
1181
|
const view = grok.shell.addTableView(newDf);
|
|
1173
|
-
view.addViewer(
|
|
1182
|
+
view.addViewer(VIEWER_TYPE.LOGO_SUMMARY_TABLE);
|
|
1183
|
+
|
|
1184
|
+
return newDfId;
|
|
1174
1185
|
}
|
|
1175
1186
|
}
|
package/src/tests/core.ts
CHANGED
|
@@ -39,7 +39,7 @@ category('Core', () => {
|
|
|
39
39
|
simpleActivityCol, simpleAlignedSeqCol, null, simpleTable, simpleScaledCol, C.SCALING_METHODS.MINUS_LG);
|
|
40
40
|
expect(model instanceof PeptidesModel, true);
|
|
41
41
|
|
|
42
|
-
if (model
|
|
42
|
+
if (model !== null)
|
|
43
43
|
model.monomerPositionSelection = {'11': ['D']};
|
|
44
44
|
});
|
|
45
45
|
|
|
@@ -59,7 +59,7 @@ category('Core', () => {
|
|
|
59
59
|
complexActivityCol, complexAlignedSeqCol, null, complexTable, complexScaledCol, C.SCALING_METHODS.MINUS_LG);
|
|
60
60
|
expect(model instanceof PeptidesModel, true);
|
|
61
61
|
|
|
62
|
-
if (model
|
|
62
|
+
if (model !== null)
|
|
63
63
|
model.monomerPositionSelection = {'13': ['-']};
|
|
64
64
|
});
|
|
65
65
|
|
package/src/tests/model.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {scaleActivity} from '../utils/misc';
|
|
|
8
8
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
9
9
|
import {COLUMNS_NAMES, SCALING_METHODS} from '../utils/constants';
|
|
10
10
|
import {LogoSummaryTable} from '../viewers/logo-summary';
|
|
11
|
+
import {TEST_COLUMN_NAMES} from './utils';
|
|
11
12
|
|
|
12
13
|
category('Model: Settings', () => {
|
|
13
14
|
let df: DG.DataFrame;
|
|
@@ -22,12 +23,12 @@ category('Model: Settings', () => {
|
|
|
22
23
|
|
|
23
24
|
before(async () => {
|
|
24
25
|
df = DG.DataFrame.fromCsv(await _package.files.readAsText('tests/HELM_small.csv'));
|
|
25
|
-
activityCol = df.getCol(
|
|
26
|
-
sequenceCol = df.getCol(
|
|
26
|
+
activityCol = df.getCol(TEST_COLUMN_NAMES.ACTIVITY);
|
|
27
|
+
sequenceCol = df.getCol(TEST_COLUMN_NAMES.SEQUENCE);
|
|
27
28
|
sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
28
29
|
sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
29
30
|
scaledActivityCol = scaleActivity(activityCol, SCALING_METHODS.NONE);
|
|
30
|
-
clusterCol = df.getCol(
|
|
31
|
+
clusterCol = df.getCol(TEST_COLUMN_NAMES.CLUSTER);
|
|
31
32
|
const tempModel = await startAnalysis(activityCol, sequenceCol, clusterCol, df, scaledActivityCol,
|
|
32
33
|
SCALING_METHODS.NONE);
|
|
33
34
|
if (tempModel === null)
|
package/src/tests/table-view.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {startAnalysis} from '../widgets/peptides';
|
|
|
7
7
|
import {scaleActivity} from '../utils/misc';
|
|
8
8
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
9
9
|
import {COLUMNS_NAMES, SCALING_METHODS} from '../utils/constants';
|
|
10
|
+
import {TEST_COLUMN_NAMES} from './utils';
|
|
10
11
|
|
|
11
12
|
category('Table view', () => {
|
|
12
13
|
let df: DG.DataFrame;
|
|
@@ -24,12 +25,12 @@ category('Table view', () => {
|
|
|
24
25
|
|
|
25
26
|
before(async () => {
|
|
26
27
|
df = DG.DataFrame.fromCsv(await _package.files.readAsText('tests/HELM_small.csv'));
|
|
27
|
-
activityCol = df.getCol(
|
|
28
|
-
sequenceCol = df.getCol(
|
|
28
|
+
activityCol = df.getCol(TEST_COLUMN_NAMES.ACTIVITY);
|
|
29
|
+
sequenceCol = df.getCol(TEST_COLUMN_NAMES.SEQUENCE);
|
|
29
30
|
sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
30
31
|
sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
31
32
|
scaledActivityCol = scaleActivity(activityCol, scaling);
|
|
32
|
-
clusterCol = df.getCol(
|
|
33
|
+
clusterCol = df.getCol(TEST_COLUMN_NAMES.CLUSTER);
|
|
33
34
|
const tempModel = await startAnalysis(activityCol, sequenceCol, clusterCol, df, scaledActivityCol, scaling);
|
|
34
35
|
if (tempModel === null)
|
|
35
36
|
throw new Error('Model is null');
|
|
@@ -50,7 +51,7 @@ category('Table view', () => {
|
|
|
50
51
|
const tableColName = col.column!.name;
|
|
51
52
|
const expectedVisibility = posCols.includes(tableColName) || (tableColName === COLUMNS_NAMES.ACTIVITY_SCALED) ||
|
|
52
53
|
visibleColumns.includes(tableColName);
|
|
53
|
-
expect(col.visible, expectedVisibility, `Column ${tableColName} is visible
|
|
54
|
+
expect(col.visible, expectedVisibility, `Column ${tableColName} is visible === ${col.visible} but should be ` +
|
|
54
55
|
`${expectedVisibility}`);
|
|
55
56
|
}
|
|
56
57
|
});
|
package/src/tests/utils.ts
CHANGED
|
@@ -8,6 +8,12 @@ import {
|
|
|
8
8
|
} from '@datagrok-libraries/ml/src/workers/dimensionality-reducing-worker-creator';
|
|
9
9
|
import {StringMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
|
|
10
10
|
|
|
11
|
+
export enum TEST_COLUMN_NAMES {
|
|
12
|
+
SEQUENCE = 'sequence',
|
|
13
|
+
ACTIVITY = 'activity',
|
|
14
|
+
CLUSTER = 'cluster',
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
/**
|
|
12
18
|
* Tests if a table has non zero rows and columns.
|
|
13
19
|
*
|
package/src/tests/viewers.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {MONOMER_POSITION_MODE, MonomerPosition, MostPotentResiduesViewer, showTo
|
|
|
11
11
|
import {SCALING_METHODS} from '../utils/constants';
|
|
12
12
|
import {LST_PROPERTIES, LogoSummaryTable} from '../viewers/logo-summary';
|
|
13
13
|
import {PositionHeight} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
14
|
-
|
|
14
|
+
import {TEST_COLUMN_NAMES} from './utils';
|
|
15
15
|
|
|
16
16
|
category('Viewers: Basic', () => {
|
|
17
17
|
const df = DG.DataFrame.fromCsv(aligned1);
|
|
@@ -34,12 +34,12 @@ category('Viewers: Monomer-Position', () => {
|
|
|
34
34
|
|
|
35
35
|
before(async () => {
|
|
36
36
|
df = DG.DataFrame.fromCsv(await _package.files.readAsText('tests/HELM_small.csv'));
|
|
37
|
-
activityCol = df.getCol(
|
|
38
|
-
sequenceCol = df.getCol(
|
|
37
|
+
activityCol = df.getCol(TEST_COLUMN_NAMES.ACTIVITY);
|
|
38
|
+
sequenceCol = df.getCol(TEST_COLUMN_NAMES.SEQUENCE);
|
|
39
39
|
sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
40
40
|
sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
41
41
|
scaledActivityCol = scaleActivity(activityCol, SCALING_METHODS.NONE);
|
|
42
|
-
clusterCol = df.getCol(
|
|
42
|
+
clusterCol = df.getCol(TEST_COLUMN_NAMES.CLUSTER);
|
|
43
43
|
const tempModel = await startAnalysis(
|
|
44
44
|
activityCol, sequenceCol, clusterCol, df, scaledActivityCol, SCALING_METHODS.NONE);
|
|
45
45
|
if (tempModel === null)
|
|
@@ -83,12 +83,12 @@ category('Viewers: Most Potent Residues', () => {
|
|
|
83
83
|
|
|
84
84
|
before(async () => {
|
|
85
85
|
df = DG.DataFrame.fromCsv(await _package.files.readAsText('tests/HELM_small.csv'));
|
|
86
|
-
activityCol = df.getCol(
|
|
87
|
-
sequenceCol = df.getCol(
|
|
86
|
+
activityCol = df.getCol(TEST_COLUMN_NAMES.ACTIVITY);
|
|
87
|
+
sequenceCol = df.getCol(TEST_COLUMN_NAMES.SEQUENCE);
|
|
88
88
|
sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
89
89
|
sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
90
90
|
scaledActivityCol = scaleActivity(activityCol, SCALING_METHODS.NONE);
|
|
91
|
-
clusterCol = df.getCol(
|
|
91
|
+
clusterCol = df.getCol(TEST_COLUMN_NAMES.CLUSTER);
|
|
92
92
|
const tempModel = await startAnalysis(
|
|
93
93
|
activityCol, sequenceCol, clusterCol, df, scaledActivityCol, SCALING_METHODS.NONE);
|
|
94
94
|
if (tempModel === null)
|
|
@@ -116,12 +116,12 @@ category('Viewers: Logo Summary Table', () => {
|
|
|
116
116
|
|
|
117
117
|
before(async () => {
|
|
118
118
|
df = DG.DataFrame.fromCsv(await _package.files.readAsText('tests/HELM_small.csv'));
|
|
119
|
-
activityCol = df.getCol(
|
|
120
|
-
sequenceCol = df.getCol(
|
|
119
|
+
activityCol = df.getCol(TEST_COLUMN_NAMES.ACTIVITY);
|
|
120
|
+
sequenceCol = df.getCol(TEST_COLUMN_NAMES.SEQUENCE);
|
|
121
121
|
sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
122
122
|
sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
123
123
|
scaledActivityCol = scaleActivity(activityCol, SCALING_METHODS.NONE);
|
|
124
|
-
clusterCol = df.getCol(
|
|
124
|
+
clusterCol = df.getCol(TEST_COLUMN_NAMES.CLUSTER);
|
|
125
125
|
const tempModel = await startAnalysis(
|
|
126
126
|
activityCol, sequenceCol, clusterCol, df, scaledActivityCol, SCALING_METHODS.NONE);
|
|
127
127
|
if (tempModel === null)
|
package/src/tests/widgets.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
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, delay} from '@datagrok-libraries/utils/src/test';
|
|
4
5
|
import {_package} from '../package-test';
|
|
5
|
-
import {PeptidesModel} from '../model';
|
|
6
|
+
import {PeptidesModel, VIEWER_TYPE} from '../model';
|
|
6
7
|
import {scaleActivity} from '../utils/misc';
|
|
7
8
|
import {startAnalysis} from '../widgets/peptides';
|
|
8
9
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
9
|
-
import
|
|
10
|
+
import * as C from '../utils/constants';
|
|
10
11
|
import {PANES_INPUTS, SETTINGS_PANES, getSettingsDialog} from '../widgets/settings';
|
|
11
12
|
import {getDistributionWidget} from '../widgets/distribution';
|
|
12
13
|
import {mutationCliffsWidget} from '../widgets/mutation-cliffs';
|
|
14
|
+
import {TEST_COLUMN_NAMES} from './utils';
|
|
15
|
+
import wu from 'wu';
|
|
16
|
+
import {LogoSummaryTable} from '../viewers/logo-summary';
|
|
13
17
|
|
|
14
18
|
category('Widgets: Settings', () => {
|
|
15
19
|
let df: DG.DataFrame;
|
|
@@ -21,14 +25,14 @@ category('Widgets: Settings', () => {
|
|
|
21
25
|
|
|
22
26
|
before(async () => {
|
|
23
27
|
df = DG.DataFrame.fromCsv(await _package.files.readAsText('tests/HELM_small.csv'));
|
|
24
|
-
activityCol = df.getCol(
|
|
25
|
-
sequenceCol = df.getCol(
|
|
28
|
+
activityCol = df.getCol(TEST_COLUMN_NAMES.ACTIVITY);
|
|
29
|
+
sequenceCol = df.getCol(TEST_COLUMN_NAMES.SEQUENCE);
|
|
26
30
|
sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
27
31
|
sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
28
|
-
scaledActivityCol = scaleActivity(activityCol, SCALING_METHODS.NONE);
|
|
29
|
-
clusterCol = df.getCol(
|
|
32
|
+
scaledActivityCol = scaleActivity(activityCol, C.SCALING_METHODS.NONE);
|
|
33
|
+
clusterCol = df.getCol(TEST_COLUMN_NAMES.CLUSTER);
|
|
30
34
|
const tempModel = await startAnalysis(activityCol, sequenceCol, clusterCol, df, scaledActivityCol,
|
|
31
|
-
SCALING_METHODS.NONE);
|
|
35
|
+
C.SCALING_METHODS.NONE);
|
|
32
36
|
if (tempModel === null)
|
|
33
37
|
throw new Error('Model is null');
|
|
34
38
|
model = tempModel;
|
|
@@ -62,14 +66,14 @@ category('Widgets: Distribution panel', () => {
|
|
|
62
66
|
|
|
63
67
|
before(async () => {
|
|
64
68
|
df = DG.DataFrame.fromCsv(await _package.files.readAsText('tests/HELM_small.csv'));
|
|
65
|
-
activityCol = df.getCol(
|
|
66
|
-
sequenceCol = df.getCol(
|
|
69
|
+
activityCol = df.getCol(TEST_COLUMN_NAMES.ACTIVITY);
|
|
70
|
+
sequenceCol = df.getCol(TEST_COLUMN_NAMES.SEQUENCE);
|
|
67
71
|
sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
68
72
|
sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
69
|
-
scaledActivityCol = scaleActivity(activityCol, SCALING_METHODS.NONE);
|
|
70
|
-
clusterCol = df.getCol(
|
|
73
|
+
scaledActivityCol = scaleActivity(activityCol, C.SCALING_METHODS.NONE);
|
|
74
|
+
clusterCol = df.getCol(TEST_COLUMN_NAMES.CLUSTER);
|
|
71
75
|
const tempModel = await startAnalysis(activityCol, sequenceCol, clusterCol, df, scaledActivityCol,
|
|
72
|
-
SCALING_METHODS.NONE);
|
|
76
|
+
C.SCALING_METHODS.NONE);
|
|
73
77
|
if (tempModel === null)
|
|
74
78
|
throw new Error('Model is null');
|
|
75
79
|
model = tempModel;
|
|
@@ -94,14 +98,14 @@ category('Widgets: Mutation cliffs', () => {
|
|
|
94
98
|
|
|
95
99
|
before(async () => {
|
|
96
100
|
df = DG.DataFrame.fromCsv(await _package.files.readAsText('tests/HELM_small.csv'));
|
|
97
|
-
activityCol = df.getCol(
|
|
98
|
-
sequenceCol = df.getCol(
|
|
101
|
+
activityCol = df.getCol(TEST_COLUMN_NAMES.ACTIVITY);
|
|
102
|
+
sequenceCol = df.getCol(TEST_COLUMN_NAMES.SEQUENCE);
|
|
99
103
|
sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
100
104
|
sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
101
|
-
scaledActivityCol = scaleActivity(activityCol, SCALING_METHODS.NONE);
|
|
102
|
-
clusterCol = df.getCol(
|
|
105
|
+
scaledActivityCol = scaleActivity(activityCol, C.SCALING_METHODS.NONE);
|
|
106
|
+
clusterCol = df.getCol(TEST_COLUMN_NAMES.CLUSTER);
|
|
103
107
|
const tempModel = await startAnalysis(activityCol, sequenceCol, clusterCol, df, scaledActivityCol,
|
|
104
|
-
SCALING_METHODS.NONE);
|
|
108
|
+
C.SCALING_METHODS.NONE);
|
|
105
109
|
if (tempModel === null)
|
|
106
110
|
throw new Error('Model is null');
|
|
107
111
|
model = tempModel;
|
|
@@ -121,15 +125,84 @@ category('Widgets: Mutation cliffs', () => {
|
|
|
121
125
|
});
|
|
122
126
|
|
|
123
127
|
category('Widgets: Actions', () => {
|
|
128
|
+
let df: DG.DataFrame;
|
|
129
|
+
let model: PeptidesModel;
|
|
130
|
+
let activityCol: DG.Column<number>;
|
|
131
|
+
let sequenceCol: DG.Column<string>;
|
|
132
|
+
let clusterCol: DG.Column<any>;
|
|
133
|
+
let scaledActivityCol: DG.Column<number>;
|
|
134
|
+
|
|
135
|
+
before(async () => {
|
|
136
|
+
df = DG.DataFrame.fromCsv(await _package.files.readAsText('tests/HELM_small.csv'));
|
|
137
|
+
activityCol = df.getCol(TEST_COLUMN_NAMES.ACTIVITY);
|
|
138
|
+
sequenceCol = df.getCol(TEST_COLUMN_NAMES.SEQUENCE);
|
|
139
|
+
sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
140
|
+
sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
141
|
+
scaledActivityCol = scaleActivity(activityCol, C.SCALING_METHODS.NONE);
|
|
142
|
+
clusterCol = df.getCol(TEST_COLUMN_NAMES.CLUSTER);
|
|
143
|
+
const tempModel = await startAnalysis(activityCol, sequenceCol, clusterCol, df, scaledActivityCol,
|
|
144
|
+
C.SCALING_METHODS.NONE);
|
|
145
|
+
if (tempModel === null)
|
|
146
|
+
throw new Error('Model is null');
|
|
147
|
+
model = tempModel;
|
|
148
|
+
});
|
|
149
|
+
|
|
124
150
|
test('New view', async () => {
|
|
151
|
+
// Set compound bitset: filter out 2 rows and select 1 among them
|
|
152
|
+
const filter = model.df.filter;
|
|
153
|
+
filter.setAll(false, false);
|
|
154
|
+
filter.set(0, true, false);
|
|
155
|
+
filter.set(1, true, false);
|
|
125
156
|
|
|
126
|
-
|
|
157
|
+
const selection = model.df.selection;
|
|
158
|
+
selection.set(0, true, false);
|
|
127
159
|
|
|
128
|
-
|
|
160
|
+
const newViewId = model.createNewView();
|
|
161
|
+
const currentTable = grok.shell.t;
|
|
129
162
|
|
|
130
|
-
|
|
163
|
+
expect(currentTable.getTag(C.TAGS.MULTIPLE_VIEWS), '1', 'Current table is expected to have multiple views tag');
|
|
164
|
+
expect(currentTable.getTag(C.TAGS.UUID), newViewId, 'Current table is expected to have the same UUID as new view');
|
|
165
|
+
expect(currentTable.rowCount, 1, 'Current table is expected to have 1 row');
|
|
131
166
|
|
|
132
|
-
|
|
167
|
+
await delay(500);
|
|
133
168
|
|
|
134
|
-
|
|
169
|
+
const currentTableModel = currentTable.temp[PeptidesModel.modelName] as PeptidesModel;
|
|
170
|
+
const lstViewer = currentTableModel.findViewer(VIEWER_TYPE.LOGO_SUMMARY_TABLE);
|
|
171
|
+
expect(lstViewer !== null, true, 'New view is expected to have Logo Summary Table viewer attached');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test('Custom clusters', async () => {
|
|
175
|
+
// Set compound bitset: filter out 2 rows and select 1 among them
|
|
176
|
+
const filter = model.df.filter;
|
|
177
|
+
filter.setAll(false, false);
|
|
178
|
+
filter.set(0, true, false);
|
|
179
|
+
filter.set(1, true, false);
|
|
180
|
+
|
|
181
|
+
const selection = model.df.selection;
|
|
182
|
+
selection.set(0, true, false);
|
|
183
|
+
|
|
184
|
+
const lstViewer = model.findViewer(VIEWER_TYPE.LOGO_SUMMARY_TABLE) as LogoSummaryTable;
|
|
185
|
+
|
|
186
|
+
// Check that custom clusters are not created yet
|
|
187
|
+
expect(wu(model.customClusters).toArray().length, 0, 'Expected to have 0 custom clusters before creating one');
|
|
188
|
+
|
|
189
|
+
// Create custom cluster
|
|
190
|
+
model._newClusterSubject.next();
|
|
191
|
+
const customClusterList = wu(model.customClusters).toArray();
|
|
192
|
+
expect(customClusterList.length, 1, 'Expected to have 1 custom cluster');
|
|
193
|
+
const clustName = customClusterList[0].name;
|
|
194
|
+
expect(model.df.col(clustName) !== null, true,
|
|
195
|
+
'Expected to have custom cluster column in the table');
|
|
196
|
+
expect(lstViewer.viewerGrid.table.getCol(C.LST_COLUMN_NAMES.CLUSTER).categories.indexOf(clustName) !== -1, true,
|
|
197
|
+
'Expected to have custom cluster in the Logo Summary Table');
|
|
198
|
+
|
|
199
|
+
// Remove custom cluster
|
|
200
|
+
model.modifyClusterSelection(clustName);
|
|
201
|
+
model._removeClusterSubject.next();
|
|
202
|
+
expect(wu(model.customClusters).toArray().length, 0, 'Expected to have 0 custom clusters after removing one');
|
|
203
|
+
expect(model.df.col(clustName) === null, true,
|
|
204
|
+
'Expected to have no custom cluster column in the table');
|
|
205
|
+
expect(lstViewer.viewerGrid.table.getCol(C.LST_COLUMN_NAMES.CLUSTER).categories.indexOf(clustName) === -1, true,
|
|
206
|
+
'Expected to have no custom cluster in the Logo Summary Table');
|
|
207
|
+
});
|
|
135
208
|
});
|
package/src/utils/algorithms.ts
CHANGED
|
@@ -8,7 +8,7 @@ export function findMutations(activityArray: type.RawData, monomerInfoArray: typ
|
|
|
8
8
|
settings: type.PeptidesSettings = {},
|
|
9
9
|
targetOptions: {targetCol?: type.RawColumn | null, currentTarget?: string | null} = {}): type.MutationCliffs {
|
|
10
10
|
const nCols = monomerInfoArray.length;
|
|
11
|
-
if (nCols
|
|
11
|
+
if (nCols === 0)
|
|
12
12
|
throw new Error(`PepAlgorithmError: Couldn't find any column of semType '${C.SEM_TYPES.MONOMER}'`);
|
|
13
13
|
|
|
14
14
|
settings.minActivityDelta ??= 0;
|
|
@@ -37,7 +37,7 @@ export function findMutations(activityArray: type.RawData, monomerInfoArray: typ
|
|
|
37
37
|
for (const monomerInfo of monomerInfoArray) {
|
|
38
38
|
const seq1category = monomerInfo.rawData[seq1Idx];
|
|
39
39
|
const seq2category = monomerInfo.rawData[seq2Idx];
|
|
40
|
-
if (seq1category
|
|
40
|
+
if (seq1category === seq2category)
|
|
41
41
|
continue;
|
|
42
42
|
|
|
43
43
|
substCounter++;
|
|
@@ -54,7 +54,7 @@ export function findMutations(activityArray: type.RawData, monomerInfoArray: typ
|
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
if (substCounterFlag || substCounter
|
|
57
|
+
if (substCounterFlag || substCounter === 0)
|
|
58
58
|
continue;
|
|
59
59
|
|
|
60
60
|
for (const tempDataElement of tempData) {
|
|
@@ -67,7 +67,7 @@ export function renderMutationCliffCell(canvasContext: CanvasRenderingContext2D,
|
|
|
67
67
|
canvasContext.shadowColor = DG.Color.toHtml(DG.Color.white);
|
|
68
68
|
let substValue = 0;
|
|
69
69
|
substitutionsInfo.get(currentAAR)?.get(currentPosition)?.forEach((idxs) => substValue += idxs.length);
|
|
70
|
-
if (substValue && substValue
|
|
70
|
+
if (substValue && substValue !== 0)
|
|
71
71
|
canvasContext.fillText(substValue.toString(), midX, midY);
|
|
72
72
|
}
|
|
73
73
|
|
package/src/utils/constants.ts
CHANGED
|
@@ -38,6 +38,7 @@ export enum TAGS {
|
|
|
38
38
|
CUSTOM_CLUSTER = 'customCluster',
|
|
39
39
|
UUID = 'pep-uuid',
|
|
40
40
|
MONOMER_POSITION_MODE = 'monomerPositionMode',
|
|
41
|
+
MULTIPLE_VIEWS = 'isMultipleViews',
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
export enum SEM_TYPES {
|
|
@@ -47,8 +48,6 @@ export enum SEM_TYPES {
|
|
|
47
48
|
|
|
48
49
|
export const EMBEDDING_STATUS = 'embeddingStatus';
|
|
49
50
|
|
|
50
|
-
export const MULTIPLE_VIEWS = 'isMultipleViews';
|
|
51
|
-
|
|
52
51
|
export enum SCALING_METHODS {
|
|
53
52
|
NONE = 'none',
|
|
54
53
|
LG = 'lg',
|
package/src/utils/misc.ts
CHANGED
|
@@ -59,8 +59,8 @@ export function calculateSelected(df: DG.DataFrame): type.MonomerSelectionStats
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// export function isGridCellInvalid(gc: DG.GridCell | null): boolean {
|
|
62
|
-
// return !gc || !gc.cell.value || !gc.tableColumn || gc.tableRowIndex
|
|
63
|
-
// gc.cell.value
|
|
62
|
+
// return !gc || !gc.cell.value || !gc.tableColumn || gc.tableRowIndex === null || gc.tableRowIndex === -1 ||
|
|
63
|
+
// gc.cell.value === DG.INT_NULL || gc.cell.value === DG.FLOAT_NULL;
|
|
64
64
|
// }
|
|
65
65
|
|
|
66
66
|
export function extractColInfo(col: DG.Column<string>): type.RawColumn {
|
|
@@ -68,7 +68,7 @@ export async function createPeptideSimilaritySpaceViewer(table: DG.DataFrame, me
|
|
|
68
68
|
const axisCol = table.col(axis);
|
|
69
69
|
const newCol = edf.getCol(axis);
|
|
70
70
|
|
|
71
|
-
if (axisCol
|
|
71
|
+
if (axisCol !== null) {
|
|
72
72
|
for (let i = 0; i < newCol.length; ++i) {
|
|
73
73
|
const v = newCol.get(i);
|
|
74
74
|
table.set(axis, i, v);
|
|
@@ -204,7 +204,7 @@ export class PeptideSimilaritySpaceWidget {
|
|
|
204
204
|
for (const v of this.view.viewers) {
|
|
205
205
|
const opts = v.getOptions() as {[name: string]: any};
|
|
206
206
|
|
|
207
|
-
if (opts.type
|
|
207
|
+
if (opts.type === 'Scatter plot' && opts.look.xColumnName === '~X' && opts.look.yColumnName === '~Y')
|
|
208
208
|
found = true;
|
|
209
209
|
}
|
|
210
210
|
|