@datagrok/peptides 0.8.15 → 1.0.0
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 +384 -385
- package/dist/package.js +297 -288
- package/package.json +4 -3
- package/package.png +0 -0
- package/src/model.ts +188 -183
- package/src/package-test.ts +3 -3
- package/src/package.ts +0 -22
- package/src/tests/core.ts +8 -4
- package/src/tests/msa-tests.ts +3 -3
- package/src/tests/peptide-space-test.ts +65 -45
- package/src/tests/utils.ts +15 -48
- package/src/utils/constants.ts +1 -0
- package/src/utils/peptide-similarity-space.ts +1 -1
- package/src/utils/types.ts +1 -2
- package/src/viewers/peptide-space-viewer.ts +61 -32
- package/src/viewers/sar-viewer.ts +2 -0
- package/src/viewers/stacked-barchart-viewer.ts +16 -39
- package/src/widgets/analyze-peptides.ts +2 -2
- package/src/widgets/distribution.ts +30 -9
- package/src/widgets/subst-table.ts +35 -19
- package/src/workers/dimensionality-reducer.ts +1 -6
- package/{test-Peptides-e702a345ac13-2a8c8b59.html → test-Peptides-69a4761f6044-40ac3a0c.html} +17 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/peptides",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Provides advanced tools for analyzing collections of peptides.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"jest": "^27.0.0",
|
|
35
35
|
"@types/jest": "^27.0.0",
|
|
36
36
|
"ts-jest": "^27.0.0",
|
|
37
|
-
"puppeteer": "
|
|
37
|
+
"puppeteer": "^13.7.0"
|
|
38
38
|
},
|
|
39
39
|
"sources": [
|
|
40
40
|
"common/ngl_viewer/ngl.js"
|
|
@@ -68,5 +68,6 @@
|
|
|
68
68
|
],
|
|
69
69
|
"canView": [
|
|
70
70
|
"All users"
|
|
71
|
-
]
|
|
71
|
+
],
|
|
72
|
+
"category": "Cheminformatics"
|
|
72
73
|
}
|
package/package.png
CHANGED
|
Binary file
|
package/src/model.ts
CHANGED
|
@@ -16,6 +16,8 @@ import {_package} from './package';
|
|
|
16
16
|
import {SARViewer, SARViewerVertical} from './viewers/sar-viewer';
|
|
17
17
|
import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
|
|
18
18
|
import {setAARRenderer} from './utils/cell-renderer';
|
|
19
|
+
import {substitutionsWidget} from './widgets/subst-table';
|
|
20
|
+
import {getDistributionWidget} from './widgets/distribution';
|
|
19
21
|
|
|
20
22
|
export class PeptidesModel {
|
|
21
23
|
static _modelName = 'peptidesModel';
|
|
@@ -28,6 +30,7 @@ export class PeptidesModel {
|
|
|
28
30
|
_isUpdating: boolean = false;
|
|
29
31
|
_isSubstInitialized = false;
|
|
30
32
|
isBitsetChangedInitialized = false;
|
|
33
|
+
isCellChanging = false;
|
|
31
34
|
|
|
32
35
|
//viewer properties
|
|
33
36
|
_filterMode!: boolean;
|
|
@@ -41,17 +44,20 @@ export class PeptidesModel {
|
|
|
41
44
|
_sarVGrid!: DG.Grid;
|
|
42
45
|
_sourceGrid!: DG.Grid;
|
|
43
46
|
_dataFrame: DG.DataFrame;
|
|
44
|
-
splitCol!: DG.Column
|
|
47
|
+
splitCol!: DG.Column<boolean>;
|
|
45
48
|
stackedBarchart!: StackedBarChart;
|
|
49
|
+
edf: DG.DataFrame | null = null;
|
|
46
50
|
|
|
47
51
|
substitutionsInfo: type.SubstitutionsInfo = new Map();
|
|
48
52
|
isInitialized: boolean = false;
|
|
49
53
|
currentView!: DG.TableView;
|
|
50
54
|
|
|
55
|
+
_currentSelection!: type.SelectionObject;
|
|
56
|
+
isPeptideSpaceChangingBitset: boolean = false;
|
|
57
|
+
isChangingEdfBitset: boolean = false;
|
|
58
|
+
|
|
51
59
|
private constructor(dataFrame: DG.DataFrame) {
|
|
52
60
|
this._dataFrame = dataFrame;
|
|
53
|
-
this._dataFrame.temp[C.PEPTIDES_ANALYSIS] = true;
|
|
54
|
-
|
|
55
61
|
this.updateProperties();
|
|
56
62
|
}
|
|
57
63
|
|
|
@@ -67,6 +73,8 @@ export class PeptidesModel {
|
|
|
67
73
|
|
|
68
74
|
static get modelName(): string {return PeptidesModel._modelName;}
|
|
69
75
|
|
|
76
|
+
static get chemPalette(): typeof ChemPalette {return ChemPalette;}
|
|
77
|
+
|
|
70
78
|
get onStatsDataFrameChanged(): Observable<DG.DataFrame> {return this._statsDataFrameSubject.asObservable();}
|
|
71
79
|
|
|
72
80
|
get onSARGridChanged(): Observable<DG.Grid> {return this._sarGridSubject.asObservable();}
|
|
@@ -75,6 +83,31 @@ export class PeptidesModel {
|
|
|
75
83
|
|
|
76
84
|
get onSubstTableChanged(): Observable<type.SubstitutionsInfo> {return this._substitutionTableSubject.asObservable();}
|
|
77
85
|
|
|
86
|
+
get currentSelection(): type.SelectionObject {
|
|
87
|
+
this._currentSelection ??= JSON.parse(this._dataFrame.tags[C.TAGS.SELECTION] || '{}');
|
|
88
|
+
return this._currentSelection;
|
|
89
|
+
}
|
|
90
|
+
set currentSelection(selection: type.SelectionObject) {
|
|
91
|
+
this._currentSelection = selection;
|
|
92
|
+
this._dataFrame.tags[C.TAGS.SELECTION] = JSON.stringify(selection);
|
|
93
|
+
this.invalidateSelection();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
invalidateSelection(): void {
|
|
97
|
+
this.fireBitsetChanged();
|
|
98
|
+
this.invalidateGrids();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
createAccordion() {
|
|
102
|
+
const acc = ui.accordion('Selection info');
|
|
103
|
+
acc.root.style.width = '100%';
|
|
104
|
+
acc.addTitle(ui.h1('Selection info'));
|
|
105
|
+
acc.addPane('Substitutions', () => substitutionsWidget(this._dataFrame, this).root, true);
|
|
106
|
+
acc.addPane('Distribtution', () => getDistributionWidget(this._dataFrame).root, true);
|
|
107
|
+
|
|
108
|
+
return acc;
|
|
109
|
+
}
|
|
110
|
+
|
|
78
111
|
updateProperties(): void {
|
|
79
112
|
this._activityScaling = this._dataFrame.tags['scaling'];
|
|
80
113
|
this._filterMode = stringToBool(this._dataFrame.tags['filterMode']);
|
|
@@ -136,7 +169,7 @@ export class PeptidesModel {
|
|
|
136
169
|
}
|
|
137
170
|
}
|
|
138
171
|
await this.updateBarchart();
|
|
139
|
-
this.
|
|
172
|
+
this.invalidateSelection();
|
|
140
173
|
|
|
141
174
|
this._isUpdating = false;
|
|
142
175
|
}
|
|
@@ -221,28 +254,10 @@ export class PeptidesModel {
|
|
|
221
254
|
|
|
222
255
|
this.setInteractionCallback();
|
|
223
256
|
|
|
224
|
-
this.modifyOrCreateSplitCol(C.CATEGORIES.ALL, C.CATEGORIES.ALL);
|
|
225
|
-
|
|
226
257
|
this.setBitsetCallback();
|
|
227
258
|
|
|
228
259
|
this.postProcessGrids(this._sourceGrid, invalidIndexes, sarGrid, sarVGrid);
|
|
229
260
|
|
|
230
|
-
const currentAAR = this._dataFrame.tags[C.TAGS.AAR];
|
|
231
|
-
const currentPos = this._dataFrame.tags[C.TAGS.POSITION];
|
|
232
|
-
if (currentAAR !== currentPos) {
|
|
233
|
-
const sarDf = sarGrid.dataFrame;
|
|
234
|
-
const rowCount = sarDf.rowCount;
|
|
235
|
-
let index = -1;
|
|
236
|
-
const aarCol = sarDf.getCol(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE);
|
|
237
|
-
for (let i = 0; i < rowCount; i++) {
|
|
238
|
-
if (aarCol.get(i) === currentAAR) {
|
|
239
|
-
index = i;
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
sarDf.currentCell = sarDf.cell(index, currentPos);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
261
|
//TODO: return class instead
|
|
247
262
|
return [sarGrid, sarVGrid, statsDf];
|
|
248
263
|
}
|
|
@@ -369,7 +384,7 @@ export class PeptidesModel {
|
|
|
369
384
|
activityScaling: string, df: DG.DataFrame, sourceGrid: DG.Grid, splitSeqDf: DG.DataFrame,
|
|
370
385
|
): Promise<void> {
|
|
371
386
|
const [scaledDf, newColName] = await PeptidesModel.scaleActivity(
|
|
372
|
-
activityScaling, df, df.
|
|
387
|
+
activityScaling, df, df.tags[C.COLUMNS_NAMES.ACTIVITY]);
|
|
373
388
|
//TODO: make another func
|
|
374
389
|
const scaledCol = scaledDf.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
375
390
|
scaledCol.semType = C.SEM_TYPES.ACTIVITY_SCALED;
|
|
@@ -379,7 +394,7 @@ export class PeptidesModel {
|
|
|
379
394
|
const gridCol = sourceGrid.col(C.COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
380
395
|
if (gridCol !== null) {
|
|
381
396
|
gridCol.name = newColName;
|
|
382
|
-
df.
|
|
397
|
+
df.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED] = newColName;
|
|
383
398
|
}
|
|
384
399
|
|
|
385
400
|
sourceGrid.columns.setOrder([newColName]);
|
|
@@ -488,8 +503,8 @@ export class PeptidesModel {
|
|
|
488
503
|
const sarVGrid = sequenceDf.plot.grid();
|
|
489
504
|
sarVGrid.sort([C.COLUMNS_NAMES.POSITION]);
|
|
490
505
|
const pValGridCol = sarVGrid.col(C.COLUMNS_NAMES.P_VALUE)!;
|
|
491
|
-
pValGridCol.format = '
|
|
492
|
-
pValGridCol.name = 'P-
|
|
506
|
+
pValGridCol.format = '#.000';
|
|
507
|
+
pValGridCol.name = 'P-value';
|
|
493
508
|
|
|
494
509
|
let tempCol = matrixDf.getCol(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE);
|
|
495
510
|
if (tempCol)
|
|
@@ -532,9 +547,9 @@ export class PeptidesModel {
|
|
|
532
547
|
|
|
533
548
|
if (cell.isTableCell && tableColName && tableRowIndex !== null && renderColNames.indexOf(tableColName) !== -1) {
|
|
534
549
|
const gridTable = cell.grid.table;
|
|
535
|
-
const currentPosition = tableColName !== C.COLUMNS_NAMES.MEAN_DIFFERENCE ?
|
|
550
|
+
const currentPosition: string = tableColName !== C.COLUMNS_NAMES.MEAN_DIFFERENCE ?
|
|
536
551
|
tableColName : gridTable.get(C.COLUMNS_NAMES.POSITION, tableRowIndex);
|
|
537
|
-
const currentAAR = gridTable.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, tableRowIndex);
|
|
552
|
+
const currentAAR: string = gridTable.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, tableRowIndex);
|
|
538
553
|
|
|
539
554
|
const queryAAR = `${C.COLUMNS_NAMES.AMINO_ACID_RESIDUE} = ${currentAAR}`;
|
|
540
555
|
if (cellValue) {
|
|
@@ -582,6 +597,14 @@ export class PeptidesModel {
|
|
|
582
597
|
if (substValue && substValue != 0)
|
|
583
598
|
canvasContext.fillText(substValue.toString(), midX, midY);
|
|
584
599
|
}
|
|
600
|
+
|
|
601
|
+
//TODO: frame based on currentSelection
|
|
602
|
+
const aarSelection = this.currentSelection[currentPosition];
|
|
603
|
+
if (aarSelection && aarSelection.includes(currentAAR)) {
|
|
604
|
+
canvasContext.strokeStyle = '#000';
|
|
605
|
+
canvasContext.lineWidth = 1;
|
|
606
|
+
canvasContext.strokeRect(bound.x + 1, bound.y + 1, bound.width - 1, bound.height - 1);
|
|
607
|
+
}
|
|
585
608
|
}
|
|
586
609
|
args.preventDefault();
|
|
587
610
|
}
|
|
@@ -640,46 +663,63 @@ export class PeptidesModel {
|
|
|
640
663
|
const sarDf = this._sarGrid.dataFrame;
|
|
641
664
|
const sarVDf = this._sarVGrid.dataFrame;
|
|
642
665
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
let aar : string;
|
|
646
|
-
let position: string;
|
|
647
|
-
if (isVertical) {
|
|
648
|
-
const currentRowIdx = sarVDf.currentRowIdx;
|
|
649
|
-
aar = sarVDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, currentRowIdx);
|
|
650
|
-
position = sarVDf.get(C.COLUMNS_NAMES.POSITION, currentRowIdx);
|
|
651
|
-
} else {
|
|
652
|
-
aar = sarDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, sarDf.currentRowIdx);
|
|
653
|
-
position = sarDf.currentCol.name;
|
|
654
|
-
}
|
|
655
|
-
return [aar, position];
|
|
666
|
+
const chooseAction = (aar: string, position: string, isShiftPressed: boolean) => {
|
|
667
|
+
isShiftPressed ? this.modifyCurrentSelection(aar, position) : this.initCurrentSelection(aar, position);
|
|
656
668
|
};
|
|
657
669
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
670
|
+
const gridCellValidation = (gc: DG.GridCell | null) => !gc || !gc.cell.value || !gc.tableColumn ||
|
|
671
|
+
gc.tableRowIndex == null || gc.tableRowIndex == -1;
|
|
672
|
+
this._sarGrid.root.addEventListener('click', (ev) => {
|
|
673
|
+
const gridCell = this._sarGrid.hitTest(ev.offsetX, ev.offsetY);
|
|
674
|
+
if (gridCellValidation(gridCell) || gridCell!.tableColumn!.name == C.COLUMNS_NAMES.AMINO_ACID_RESIDUE)
|
|
661
675
|
return;
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
[aar, position] = getAARandPosition();
|
|
667
|
-
this._dataFrame.tags[C.TAGS.AAR] = aar;
|
|
668
|
-
this._dataFrame.tags[C.TAGS.POSITION] = position;
|
|
669
|
-
} else
|
|
670
|
-
this._dataFrame.tags[C.TAGS.AAR] = this._dataFrame.tags[C.TAGS.POSITION] = '';
|
|
671
|
-
|
|
672
|
-
this.modifyOrCreateSplitCol(aar, position);
|
|
673
|
-
this.fireBitsetChanged();
|
|
674
|
-
this.invalidateGrids();
|
|
675
|
-
grok.shell.o = this._dataFrame;
|
|
676
|
+
|
|
677
|
+
const position = gridCell!.tableColumn!.name;
|
|
678
|
+
const aar = sarDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, gridCell!.tableRowIndex!);
|
|
679
|
+
chooseAction(aar, position, ev.shiftKey);
|
|
676
680
|
});
|
|
677
681
|
|
|
678
|
-
this._sarVGrid.
|
|
679
|
-
|
|
682
|
+
this._sarVGrid.root.addEventListener('click', (ev) => {
|
|
683
|
+
const gridCell = this._sarVGrid.hitTest(ev.offsetX, ev.offsetY);
|
|
684
|
+
if (gridCellValidation(gridCell) || gridCell!.tableColumn!.name != C.COLUMNS_NAMES.MEAN_DIFFERENCE)
|
|
680
685
|
return;
|
|
681
|
-
|
|
686
|
+
|
|
687
|
+
const tableRowIdx = gridCell!.tableRowIndex!;
|
|
688
|
+
const position = sarVDf.get(C.COLUMNS_NAMES.POSITION, tableRowIdx);
|
|
689
|
+
const aar = sarVDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, tableRowIdx);
|
|
690
|
+
chooseAction(aar, position, ev.shiftKey);
|
|
682
691
|
});
|
|
692
|
+
|
|
693
|
+
const cellChanged = (table: DG.DataFrame) => {
|
|
694
|
+
if (this.isCellChanging)
|
|
695
|
+
return;
|
|
696
|
+
this.isCellChanging = true;
|
|
697
|
+
table.currentRowIdx = -1;
|
|
698
|
+
this.isCellChanging = false;
|
|
699
|
+
};
|
|
700
|
+
this._sarGrid.onCurrentCellChanged.subscribe((_gc) => cellChanged(sarDf));
|
|
701
|
+
this._sarVGrid.onCurrentCellChanged.subscribe((_gc) => cellChanged(sarVDf));
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
modifyCurrentSelection(aar: string, position: string): void {
|
|
705
|
+
const tempSelection = this.currentSelection;
|
|
706
|
+
if (!tempSelection.hasOwnProperty(position))
|
|
707
|
+
tempSelection[position] = [aar];
|
|
708
|
+
else {
|
|
709
|
+
const tempSelectionAt = tempSelection[position];
|
|
710
|
+
const aarIndex = tempSelectionAt.indexOf(aar);
|
|
711
|
+
aarIndex == -1 ? tempSelectionAt.push(aar) :
|
|
712
|
+
tempSelectionAt.length == 1 ? delete tempSelection[position] :
|
|
713
|
+
tempSelectionAt.splice(aarIndex, 1);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
this.currentSelection = tempSelection;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
initCurrentSelection(aar: string, position: string): void {
|
|
720
|
+
const tempSelection: type.SelectionObject = {};
|
|
721
|
+
tempSelection[position] = [aar];
|
|
722
|
+
this.currentSelection = tempSelection;
|
|
683
723
|
}
|
|
684
724
|
|
|
685
725
|
invalidateGrids(): void {
|
|
@@ -698,10 +738,41 @@ export class PeptidesModel {
|
|
|
698
738
|
|
|
699
739
|
const changeBitset = (currentBitset: DG.BitSet, previousBitset: DG.BitSet): void => {
|
|
700
740
|
previousBitset.setAll(!this._filterMode, false);
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
741
|
+
|
|
742
|
+
const edfSelection = this.edf?.selection;
|
|
743
|
+
if (this.isPeptideSpaceChangingBitset) {
|
|
744
|
+
if (edfSelection == null)
|
|
745
|
+
return;
|
|
746
|
+
|
|
747
|
+
currentBitset.init((i) => edfSelection.get(i) ?? false, false);
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
const updateEdfSelection = () => {
|
|
752
|
+
this.isChangingEdfBitset = true;
|
|
753
|
+
edfSelection?.copyFrom(currentBitset);
|
|
754
|
+
this.isChangingEdfBitset = false;
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
const positionList = Object.keys(this.currentSelection);
|
|
758
|
+
if (positionList.length == 0) {
|
|
759
|
+
currentBitset.init(() => false, false);
|
|
760
|
+
updateEdfSelection();
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
//TODO: move out
|
|
765
|
+
const getBitAt = (i: number) => {
|
|
766
|
+
for (const position of positionList) {
|
|
767
|
+
const positionCol: DG.Column<string> = this._dataFrame.getCol(position);
|
|
768
|
+
if (this._currentSelection[position].includes(positionCol.get(i)))
|
|
769
|
+
return true;
|
|
770
|
+
}
|
|
771
|
+
return false;
|
|
772
|
+
};
|
|
773
|
+
currentBitset.init(getBitAt, false);
|
|
774
|
+
|
|
775
|
+
updateEdfSelection();
|
|
705
776
|
};
|
|
706
777
|
|
|
707
778
|
const recalculateStatistics =
|
|
@@ -718,7 +789,15 @@ export class PeptidesModel {
|
|
|
718
789
|
this.isBitsetChangedInitialized = true;
|
|
719
790
|
}
|
|
720
791
|
|
|
721
|
-
fireBitsetChanged(): void {
|
|
792
|
+
fireBitsetChanged(isPeptideSpaceSource: boolean = false): void {
|
|
793
|
+
this.isPeptideSpaceChangingBitset = isPeptideSpaceSource;
|
|
794
|
+
this.getBiteset().fireChanged();
|
|
795
|
+
this.isPeptideSpaceChangingBitset = false;
|
|
796
|
+
this.modifyOrCreateSplitCol();
|
|
797
|
+
grok.shell.o = this.createAccordion().root;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
getBiteset(): DG.BitSet {return this._filterMode ? this._dataFrame.filter : this._dataFrame.selection;}
|
|
722
801
|
|
|
723
802
|
//TODO: move out
|
|
724
803
|
postProcessGrids(sourceGrid: DG.Grid, invalidIndexes: number[], sarGrid: DG.Grid, sarVGrid: DG.Grid): void {
|
|
@@ -732,70 +811,28 @@ export class PeptidesModel {
|
|
|
732
811
|
mdCol.name = 'Diff';
|
|
733
812
|
|
|
734
813
|
for (const grid of [sarGrid, sarVGrid]) {
|
|
735
|
-
grid.props
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
814
|
+
const gridProps = grid.props;
|
|
815
|
+
gridProps.rowHeight = 20;
|
|
816
|
+
const girdCols = grid.columns;
|
|
817
|
+
const colNum = girdCols.length;
|
|
818
|
+
for (let i = 0; i < colNum; ++i) {
|
|
819
|
+
const col = girdCols.byIndex(i)!;
|
|
820
|
+
const colName = col.name;
|
|
821
|
+
if (grid == sarVGrid && colName !== 'Diff' && colName !== C.COLUMNS_NAMES.AMINO_ACID_RESIDUE)
|
|
822
|
+
col.width = 50;
|
|
741
823
|
else
|
|
742
|
-
col.width =
|
|
824
|
+
col.width = gridProps.rowHeight + 10;
|
|
743
825
|
}
|
|
744
826
|
}
|
|
745
827
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
syncGrids(sourceVertical: boolean, sarDf: DG.DataFrame, sarVDf: DG.DataFrame): void {
|
|
752
|
-
let otherColName: string;
|
|
753
|
-
let otherRowIndex: number;
|
|
754
|
-
const otherDf = sourceVertical ? sarDf : sarVDf;
|
|
755
|
-
|
|
756
|
-
if (otherDf.temp[C.FLAGS.CELL_CHANGING])
|
|
757
|
-
return;
|
|
758
|
-
|
|
759
|
-
//on vertical SAR viewer click
|
|
760
|
-
if (sourceVertical) {
|
|
761
|
-
const currentRowIdx = sarVDf.currentRowIdx;
|
|
762
|
-
const currentColName = sarVDf.currentCol.name;
|
|
763
|
-
if (currentColName !== C.COLUMNS_NAMES.MEAN_DIFFERENCE)
|
|
764
|
-
return;
|
|
765
|
-
|
|
766
|
-
otherColName = sarVDf.get(C.COLUMNS_NAMES.POSITION, currentRowIdx);
|
|
767
|
-
const otherRowName: string = sarVDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, currentRowIdx);
|
|
768
|
-
otherRowIndex = -1;
|
|
769
|
-
const rows = otherDf.rowCount;
|
|
770
|
-
for (let i = 0; i < rows; i++) {
|
|
771
|
-
if (otherDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, i) === otherRowName) {
|
|
772
|
-
otherRowIndex = i;
|
|
773
|
-
break;
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
//on SAR viewer click
|
|
777
|
-
} else {
|
|
778
|
-
otherColName = C.COLUMNS_NAMES.MEAN_DIFFERENCE;
|
|
779
|
-
const otherPos: string = sarDf.currentCol.name;
|
|
780
|
-
if (otherPos === C.COLUMNS_NAMES.AMINO_ACID_RESIDUE)
|
|
781
|
-
return;
|
|
828
|
+
const setViewerGridProps = (grid: DG.Grid) => {
|
|
829
|
+
grid.props.allowEdit = false;
|
|
830
|
+
grid.props.allowRowSelection = false;
|
|
831
|
+
grid.props.allowBlockSelection = false;
|
|
832
|
+
};
|
|
782
833
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
otherRowIndex = -1;
|
|
786
|
-
for (let i = 0; i < sarVDf.rowCount; i++) {
|
|
787
|
-
if (
|
|
788
|
-
sarVDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, i) === otherAAR &&
|
|
789
|
-
sarVDf.get(C.COLUMNS_NAMES.POSITION, i) === otherPos
|
|
790
|
-
) {
|
|
791
|
-
otherRowIndex = i;
|
|
792
|
-
break;
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
otherDf.temp[C.FLAGS.CELL_CHANGING] = true;
|
|
797
|
-
otherDf.currentCell = otherDf.cell(otherRowIndex, otherColName);
|
|
798
|
-
otherDf.temp[C.FLAGS.CELL_CHANGING] = false;
|
|
834
|
+
setViewerGridProps(sarGrid);
|
|
835
|
+
setViewerGridProps(sarVGrid);
|
|
799
836
|
}
|
|
800
837
|
|
|
801
838
|
getSplitColValueAt(index: number, aar: string, position: string, aarLabel: string): string {
|
|
@@ -803,26 +840,12 @@ export class PeptidesModel {
|
|
|
803
840
|
return currentAAR === aar ? aarLabel : C.CATEGORIES.OTHER;
|
|
804
841
|
}
|
|
805
842
|
|
|
806
|
-
modifyOrCreateSplitCol(
|
|
807
|
-
const
|
|
808
|
-
this.splitCol =
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
this.splitCol.init(() => C.CATEGORIES.ALL);
|
|
812
|
-
return;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
const aarLabel = `${aar === '-' ? 'Gap' : aar} : ${position}`;
|
|
816
|
-
this.splitCol.init((i) => this.getSplitColValueAt(i, aar, position, aarLabel));
|
|
817
|
-
|
|
818
|
-
this.splitCol.setCategoryOrder([aarLabel]);
|
|
843
|
+
modifyOrCreateSplitCol(): void {
|
|
844
|
+
const bs = this.getBiteset();
|
|
845
|
+
this.splitCol = this._dataFrame.col(C.COLUMNS_NAMES.SPLIT_COL) ??
|
|
846
|
+
this._dataFrame.columns.addNewBool(C.COLUMNS_NAMES.SPLIT_COL);
|
|
847
|
+
this.splitCol.init((i) => bs.get(i));
|
|
819
848
|
this.splitCol.compact();
|
|
820
|
-
|
|
821
|
-
const colorMap: {[index: string]: string | number} = {};
|
|
822
|
-
|
|
823
|
-
colorMap[C.CATEGORIES.OTHER] = DG.Color.blue;
|
|
824
|
-
colorMap[aarLabel] = DG.Color.orange;
|
|
825
|
-
this.splitCol.colors.setCategorical(colorMap);
|
|
826
849
|
}
|
|
827
850
|
|
|
828
851
|
static async scaleActivity(
|
|
@@ -835,7 +858,7 @@ export class PeptidesModel {
|
|
|
835
858
|
const tempDf = df.clone(cloneBitset ? df.filter : null, [currentActivityColName]);
|
|
836
859
|
|
|
837
860
|
let formula = '${' + currentActivityColName + '}';
|
|
838
|
-
let newColName = 'activity';
|
|
861
|
+
let newColName = 'activity';
|
|
839
862
|
switch (activityScaling) {
|
|
840
863
|
case 'none':
|
|
841
864
|
break;
|
|
@@ -921,13 +944,9 @@ export class PeptidesModel {
|
|
|
921
944
|
];
|
|
922
945
|
}
|
|
923
946
|
|
|
924
|
-
getCurrentAARandPos(): {aar: string, pos: string} {
|
|
925
|
-
return {aar: this._dataFrame.getTag(C.TAGS.AAR) ?? 'All', pos: this._dataFrame.getTag(C.TAGS.POSITION) ?? 'All'};
|
|
926
|
-
}
|
|
927
|
-
|
|
928
947
|
syncProperties(isSourceSAR = true): void {
|
|
929
|
-
const sarViewer = this._dataFrame.temp['sarViewer'];
|
|
930
|
-
const sarViewerVertical = this._dataFrame.temp['sarViewerVertical'];
|
|
948
|
+
const sarViewer: SARViewer = this._dataFrame.temp['sarViewer'];
|
|
949
|
+
const sarViewerVertical: SARViewerVertical = this._dataFrame.temp['sarViewerVertical'];
|
|
931
950
|
const sourceViewer = isSourceSAR ? sarViewer : sarViewerVertical;
|
|
932
951
|
const targetViewer = isSourceSAR ? sarViewerVertical : sarViewer;
|
|
933
952
|
const properties = sourceViewer.props.getProperties();
|
|
@@ -935,24 +954,6 @@ export class PeptidesModel {
|
|
|
935
954
|
targetViewer.props.set(property.name, property.get(sourceViewer));
|
|
936
955
|
}
|
|
937
956
|
|
|
938
|
-
//TODO: move to viewer
|
|
939
|
-
setSARGridCellAt(aar: string, position: string): void {
|
|
940
|
-
const sarDf = this._sarGrid.dataFrame;
|
|
941
|
-
const aarCol = sarDf.getCol(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE);
|
|
942
|
-
const aarColLen = aarCol.length;
|
|
943
|
-
let index = -1;
|
|
944
|
-
for (let i = 0; i < aarColLen; i++) {
|
|
945
|
-
if (aarCol.get(i) === aar) {
|
|
946
|
-
index = i;
|
|
947
|
-
break;
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
position = position === C.CATEGORIES.ALL ? C.COLUMNS_NAMES.AMINO_ACID_RESIDUE : position;
|
|
951
|
-
sarDf.currentCell = sarDf.cell(index, position);
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
static get chemPalette(): typeof ChemPalette {return ChemPalette;}
|
|
955
|
-
|
|
956
957
|
/** Class initializer */
|
|
957
958
|
async init(): Promise<void> {
|
|
958
959
|
if (this.isInitialized)
|
|
@@ -965,10 +966,16 @@ export class PeptidesModel {
|
|
|
965
966
|
stats.setMask(this._dataFrame.selection);
|
|
966
967
|
this._dataFrame.temp[C.STATS] = stats;
|
|
967
968
|
|
|
968
|
-
this.currentView = grok.shell.
|
|
969
|
+
this.currentView = this._dataFrame.tags[C.PEPTIDES_ANALYSIS] == 'true' ? grok.shell.v as DG.TableView :
|
|
970
|
+
grok.shell.addTableView(this._dataFrame);
|
|
969
971
|
const sourceGrid = this.currentView.grid;
|
|
970
|
-
|
|
971
|
-
|
|
972
|
+
if (this._dataFrame.tags[C.PEPTIDES_ANALYSIS] == 'true')
|
|
973
|
+
return;
|
|
974
|
+
|
|
975
|
+
this._dataFrame.tags[C.PEPTIDES_ANALYSIS] = 'true';
|
|
976
|
+
sourceGrid.col(C.COLUMNS_NAMES.ACTIVITY_SCALED)!.name = this._dataFrame.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED];
|
|
977
|
+
sourceGrid.columns.setOrder([this._dataFrame.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED]]);
|
|
978
|
+
|
|
972
979
|
|
|
973
980
|
this._dataFrame.temp[C.EMBEDDING_STATUS] = false;
|
|
974
981
|
const adjustCellSize = (grid: DG.Grid): void => {
|
|
@@ -983,9 +990,8 @@ export class PeptidesModel {
|
|
|
983
990
|
for (let i = 0; i < sourceGrid.columns.length; i++) {
|
|
984
991
|
const aarCol = sourceGrid.columns.byIndex(i);
|
|
985
992
|
if (aarCol && aarCol.name && aarCol.column?.semType !== C.SEM_TYPES.AMINO_ACIDS &&
|
|
986
|
-
aarCol.name !== this._dataFrame.
|
|
987
|
-
|
|
988
|
-
sourceGrid.columns.byIndex(i)!.visible = false;
|
|
993
|
+
aarCol.name !== this._dataFrame.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED])
|
|
994
|
+
aarCol.visible = false;
|
|
989
995
|
}
|
|
990
996
|
|
|
991
997
|
const options = {scaling: this._dataFrame.tags['scaling']};
|
|
@@ -993,20 +999,19 @@ export class PeptidesModel {
|
|
|
993
999
|
|
|
994
1000
|
const dockManager = this.currentView.dockManager;
|
|
995
1001
|
|
|
996
|
-
const sarViewer =
|
|
997
|
-
await this._dataFrame.plot.fromType('peptide-sar-viewer', options) as SARViewer;
|
|
998
|
-
this._dataFrame.temp['sarViewer'] = sarViewer;
|
|
1002
|
+
const sarViewer = await this._dataFrame.plot.fromType('peptide-sar-viewer', options) as SARViewer;
|
|
999
1003
|
|
|
1000
1004
|
const sarViewerVertical =
|
|
1001
1005
|
await this._dataFrame.plot.fromType('peptide-sar-viewer-vertical', options) as SARViewerVertical;
|
|
1002
|
-
this._dataFrame.temp['sarViewerVertical'] = sarViewer;
|
|
1003
1006
|
|
|
1004
1007
|
const sarViewersGroup: viewerTypes[] = [sarViewer, sarViewerVertical];
|
|
1005
1008
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1009
|
+
if (this._dataFrame.rowCount <= 10000) {
|
|
1010
|
+
const peptideSpaceViewerOptions = {method: 'UMAP', measure: 'Levenshtein', cyclesCount: 100};
|
|
1011
|
+
const peptideSpaceViewer =
|
|
1012
|
+
await this._dataFrame.plot.fromType('peptide-space-viewer', peptideSpaceViewerOptions) as PeptideSpaceViewer;
|
|
1013
|
+
dockManager.dock(peptideSpaceViewer, DG.DOCK_TYPE.RIGHT, null, 'Peptide Space Viewer');
|
|
1014
|
+
}
|
|
1010
1015
|
|
|
1011
1016
|
dockViewers(sarViewersGroup, DG.DOCK_TYPE.RIGHT, dockManager, DG.DOCK_TYPE.DOWN);
|
|
1012
1017
|
|
package/src/package-test.ts
CHANGED
|
@@ -10,10 +10,10 @@ export {tests};
|
|
|
10
10
|
|
|
11
11
|
//name: test
|
|
12
12
|
//input: string category {optional: true}
|
|
13
|
-
//input: string
|
|
13
|
+
//input: string test {optional: true}
|
|
14
14
|
//output: dataframe result
|
|
15
15
|
//top-menu: Tools | Dev | JS API Tests
|
|
16
|
-
export async function test(category: string,
|
|
17
|
-
const data = await runTests({category, test:
|
|
16
|
+
export async function test(category: string, test: string): Promise<DG.DataFrame> {
|
|
17
|
+
const data = await runTests({category, test: test});
|
|
18
18
|
return DG.DataFrame.fromObjects(data)!;
|
|
19
19
|
}
|
package/src/package.ts
CHANGED
|
@@ -18,9 +18,7 @@ import {manualAlignmentWidget} from './widgets/manual-alignment';
|
|
|
18
18
|
import {SARViewer, SARViewerVertical} from './viewers/sar-viewer';
|
|
19
19
|
import {peptideMoleculeWidget, getMolecule} from './widgets/peptide-molecule';
|
|
20
20
|
import {runKalign, testMSAEnoughMemory} from './utils/multiple-sequence-alignment';
|
|
21
|
-
import {substitutionsWidget} from './widgets/subst-table';
|
|
22
21
|
import {msaWidget} from './widgets/multiple-sequence-alignment';
|
|
23
|
-
import {getDistributionWidget} from './widgets/distribution';
|
|
24
22
|
import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
|
|
25
23
|
|
|
26
24
|
export const _package = new DG.Package();
|
|
@@ -236,26 +234,6 @@ export async function runTestMSAEnoughMemory(_table: DG.DataFrame, col: DG.Colum
|
|
|
236
234
|
return col;
|
|
237
235
|
}
|
|
238
236
|
|
|
239
|
-
//name: Substitution
|
|
240
|
-
//tags: panel, widgets
|
|
241
|
-
//input: dataframe table {semType: Substitution}
|
|
242
|
-
//output: widget result
|
|
243
|
-
export async function peptideSubstitution(table: DG.DataFrame): Promise<DG.Widget> {
|
|
244
|
-
if (!table.temp[C.PEPTIDES_ANALYSIS])
|
|
245
|
-
return new DG.Widget(ui.divText('This widget is only applicable for peptides analysis'));
|
|
246
|
-
return substitutionsWidget(table);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
//name: Distribution
|
|
250
|
-
//tags: panel, widgets
|
|
251
|
-
//input: dataframe table {semType: viewerTable}
|
|
252
|
-
//output: widget result
|
|
253
|
-
export function peptideDistribution(table: DG.DataFrame): DG.Widget {
|
|
254
|
-
if (!table.temp[C.PEPTIDES_ANALYSIS])
|
|
255
|
-
return new DG.Widget(ui.divText('This widget is only applicable for peptides analysis'));
|
|
256
|
-
return getDistributionWidget(table);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
237
|
//name: Get Peptides Structure
|
|
260
238
|
//tags: panel, widgets
|
|
261
239
|
//input: column col {semType: alignedSequence}
|
package/src/tests/core.ts
CHANGED
|
@@ -36,9 +36,11 @@ category('Core', () => {
|
|
|
36
36
|
model = await startAnalysis(
|
|
37
37
|
simpleActivityCol, simpleAlignedSeqCol, simpleTable, simpleScaledDf, simpleScaledColName, _package);
|
|
38
38
|
expect(model instanceof PeptidesModel, true);
|
|
39
|
-
|
|
40
|
-
if (model != null)
|
|
39
|
+
|
|
40
|
+
if (model != null) {
|
|
41
|
+
model.currentSelection = {'11': ['D']};
|
|
41
42
|
grok.shell.closeTable(model._dataFrame);
|
|
43
|
+
}
|
|
42
44
|
});
|
|
43
45
|
|
|
44
46
|
test('Start analysis: сomplex', async () => {
|
|
@@ -56,8 +58,10 @@ category('Core', () => {
|
|
|
56
58
|
model = await startAnalysis(
|
|
57
59
|
complexActivityCol, complexAlignedSeqCol, complexTable, complexScaledDf, complexScaledColName, _package);
|
|
58
60
|
expect(model instanceof PeptidesModel, true);
|
|
59
|
-
|
|
60
|
-
if (model != null)
|
|
61
|
+
|
|
62
|
+
if (model != null) {
|
|
63
|
+
model.currentSelection = {'13': ['-']};
|
|
61
64
|
grok.shell.closeTable(model._dataFrame);
|
|
65
|
+
}
|
|
62
66
|
});
|
|
63
67
|
});
|