@datagrok/peptides 1.8.0 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +4 -3
- package/dist/478.js +2 -0
- package/dist/563.js +2 -2
- package/dist/802.js +2 -2
- package/dist/96.js +2 -2
- package/dist/package-test.js +2 -2
- package/dist/package.js +2 -2
- package/files/tests/HELM_small.csv +12 -0
- package/package.json +5 -4
- package/src/demo/fasta.ts +47 -0
- package/src/model.ts +170 -180
- package/src/package-test.ts +3 -0
- package/src/package.ts +10 -1
- package/src/tests/algorithms.ts +1 -1
- package/src/tests/core.ts +13 -8
- package/src/tests/model.ts +152 -0
- package/src/tests/table-view.ts +160 -0
- package/src/tests/viewers.ts +142 -2
- package/src/tests/widgets.ts +135 -0
- package/src/utils/algorithms.ts +2 -2
- package/src/utils/cell-renderer.ts +1 -1
- package/src/utils/constants.ts +8 -0
- package/src/utils/misc.ts +4 -4
- package/src/utils/peptide-similarity-space.ts +1 -1
- package/src/utils/statistics.ts +5 -10
- package/src/utils/types.ts +3 -3
- package/src/viewers/logo-summary.ts +91 -111
- package/src/viewers/sar-viewer.ts +106 -108
- package/src/widgets/distribution.ts +92 -122
- package/src/widgets/mutation-cliffs.ts +2 -2
- package/src/widgets/peptides.ts +7 -2
- package/src/widgets/settings.ts +67 -23
- package/tsconfig.json +1 -1
- package/dist/611.js +0 -2
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as grok from 'datagrok-api/grok';
|
|
2
1
|
import * as ui from 'datagrok-api/ui';
|
|
3
2
|
import * as DG from 'datagrok-api/dg';
|
|
4
3
|
|
|
@@ -7,70 +6,111 @@ import * as C from '../utils/constants';
|
|
|
7
6
|
import * as CR from '../utils/cell-renderer';
|
|
8
7
|
import {PeptidesModel, VIEWER_TYPE} from '../model';
|
|
9
8
|
|
|
10
|
-
export
|
|
11
|
-
|
|
9
|
+
export enum MONOMER_POSITION_MODE {
|
|
10
|
+
MUTATION_CLIFFS = 'Mutation Cliffs',
|
|
11
|
+
INVARIANT_MAP = 'Invariant Map',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Structure-activity relationship viewer */
|
|
15
|
+
export class MonomerPosition extends DG.JsViewer {
|
|
16
|
+
_titleHost = ui.divText('Mutation Cliffs', {id: 'pep-viewer-title'});
|
|
12
17
|
_viewerGrid!: DG.Grid;
|
|
13
|
-
sourceGrid!: DG.Grid;
|
|
14
18
|
_model!: PeptidesModel;
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
colorColumnName: string;
|
|
20
|
+
aggregation: string;
|
|
17
21
|
|
|
18
22
|
constructor() {
|
|
19
23
|
super();
|
|
24
|
+
this.colorColumnName = this.string('colorColumnName', C.COLUMNS_NAMES.ACTIVITY_SCALED, {category: 'Invariant Map'});
|
|
25
|
+
this.aggregation = this.string('aggregation', 'avg', {category: 'Invariant Map', choices: Object.values(DG.AGG)});
|
|
20
26
|
}
|
|
21
27
|
|
|
22
|
-
get name(): string {return
|
|
28
|
+
get name(): string {return VIEWER_TYPE.MONOMER_POSITION;}
|
|
23
29
|
|
|
24
30
|
get viewerGrid(): DG.Grid {
|
|
31
|
+
if (!this._viewerGrid)
|
|
32
|
+
this.createMonomerPositionGrid();
|
|
25
33
|
return this._viewerGrid;
|
|
26
34
|
}
|
|
27
35
|
set viewerGrid(grid: DG.Grid) {
|
|
28
36
|
this._viewerGrid = grid;
|
|
29
37
|
}
|
|
30
38
|
|
|
39
|
+
get mode(): MONOMER_POSITION_MODE {
|
|
40
|
+
return this.dataFrame.getTag(C.TAGS.MONOMER_POSITION_MODE) as MONOMER_POSITION_MODE ??
|
|
41
|
+
MONOMER_POSITION_MODE.MUTATION_CLIFFS;
|
|
42
|
+
}
|
|
43
|
+
set mode(mode: MONOMER_POSITION_MODE) {
|
|
44
|
+
this.dataFrame.setTag(C.TAGS.MONOMER_POSITION_MODE, mode);
|
|
45
|
+
this.viewerGrid.invalidate();
|
|
46
|
+
}
|
|
47
|
+
|
|
31
48
|
get model(): PeptidesModel {
|
|
32
49
|
this._model ??= PeptidesModel.getInstance(this.dataFrame);
|
|
33
50
|
return this._model;
|
|
34
51
|
}
|
|
35
52
|
|
|
53
|
+
detach(): void {this.subs.forEach((sub) => sub.unsubscribe());}
|
|
54
|
+
|
|
36
55
|
onTableAttached(): void {
|
|
37
56
|
super.onTableAttached();
|
|
38
|
-
this.
|
|
39
|
-
// this.model = PeptidesModel.getInstance(this.dataFrame);
|
|
40
|
-
this.subs.push(this.model.onMutationCliffsSelectionChanged.subscribe(() => this.viewerGrid.invalidate()));
|
|
57
|
+
this.subs.push(this.model.onMonomerPositionSelectionChanged.subscribe(() => this.viewerGrid.invalidate()));
|
|
41
58
|
this.helpUrl = '/help/domains/bio/peptides.md';
|
|
59
|
+
this.subs.push(this.model.onSettingsChanged.subscribe(() => {
|
|
60
|
+
this.createMonomerPositionGrid();
|
|
61
|
+
this.render();
|
|
62
|
+
}));
|
|
63
|
+
this.render();
|
|
42
64
|
}
|
|
43
65
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return this.dataFrame.getTag(C.TAGS.SAR_MODE) ?? '1';
|
|
66
|
+
onPropertyChanged(property: DG.Property): void {
|
|
67
|
+
super.onPropertyChanged(property);
|
|
68
|
+
this.render();
|
|
48
69
|
}
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
|
|
71
|
+
createMonomerPositionGrid(): void {
|
|
72
|
+
this.viewerGrid = this.model.monomerPositionDf.plot.grid();
|
|
73
|
+
this.viewerGrid.sort([C.COLUMNS_NAMES.MONOMER]);
|
|
74
|
+
this.viewerGrid.columns.setOrder([C.COLUMNS_NAMES.MONOMER, ...this.model.splitSeqDf.columns.names()]);
|
|
75
|
+
const monomerCol = this.model.monomerPositionDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
76
|
+
CR.setAARRenderer(monomerCol, this.model.alphabet);
|
|
77
|
+
this.viewerGrid.onCellRender.subscribe((args: DG.GridCellRenderArgs) => renderCell(args, this.model,
|
|
78
|
+
this.mode === MONOMER_POSITION_MODE.INVARIANT_MAP, this.dataFrame.getCol(this.colorColumnName),
|
|
79
|
+
this.aggregation as DG.AggregationType));
|
|
80
|
+
this.viewerGrid.onCellTooltip((cell: DG.GridCell, x: number, y: number) => showTooltip(cell, x, y, this.model));
|
|
81
|
+
this.viewerGrid.root.addEventListener('click', (ev) => {
|
|
82
|
+
const gridCell = this.viewerGrid.hitTest(ev.offsetX, ev.offsetY);
|
|
83
|
+
if (!gridCell?.isTableCell || gridCell?.tableColumn?.name == C.COLUMNS_NAMES.MONOMER)
|
|
84
|
+
return;
|
|
85
|
+
|
|
86
|
+
const position = gridCell!.tableColumn!.name;
|
|
87
|
+
const aar = monomerCol.get(gridCell!.tableRowIndex!);
|
|
88
|
+
chooseAction(aar, position, ev.shiftKey, this.mode === MONOMER_POSITION_MODE.INVARIANT_MAP, this.model);
|
|
89
|
+
this.viewerGrid.invalidate();
|
|
90
|
+
// this.model.fireBitsetChanged();
|
|
91
|
+
});
|
|
92
|
+
this.viewerGrid.onCurrentCellChanged.subscribe((_gc) => cellChanged(this.model.monomerPositionDf, this.model));
|
|
93
|
+
|
|
94
|
+
setViewerGridProps(this.viewerGrid, false);
|
|
51
95
|
}
|
|
52
96
|
|
|
53
97
|
render(refreshOnly = false): void {
|
|
54
98
|
if (!refreshOnly) {
|
|
55
99
|
$(this.root).empty();
|
|
56
100
|
let switchHost = ui.divText(VIEWER_TYPE.MOST_POTENT_RESIDUES, {id: 'pep-viewer-title'});
|
|
57
|
-
if (this.name ==
|
|
58
|
-
const mutationCliffsMode = ui.boolInput('', this.
|
|
101
|
+
if (this.name == VIEWER_TYPE.MONOMER_POSITION) {
|
|
102
|
+
const mutationCliffsMode = ui.boolInput('', this.mode === MONOMER_POSITION_MODE.MUTATION_CLIFFS);
|
|
59
103
|
mutationCliffsMode.root.addEventListener('click', () => {
|
|
60
104
|
invariantMapMode.value = false;
|
|
61
105
|
mutationCliffsMode.value = true;
|
|
62
|
-
this.
|
|
63
|
-
this.model.isInvariantMap = false;
|
|
64
|
-
this.viewerGrid.invalidate();
|
|
106
|
+
this.mode = MONOMER_POSITION_MODE.MUTATION_CLIFFS;
|
|
65
107
|
});
|
|
66
108
|
mutationCliffsMode.addPostfix('Mutation Cliffs');
|
|
67
|
-
const invariantMapMode = ui.boolInput('', this.
|
|
109
|
+
const invariantMapMode = ui.boolInput('', this.mode === MONOMER_POSITION_MODE.INVARIANT_MAP);
|
|
68
110
|
invariantMapMode.root.addEventListener('click', () => {
|
|
69
111
|
mutationCliffsMode.value = false;
|
|
70
112
|
invariantMapMode.value = true;
|
|
71
|
-
this.
|
|
72
|
-
this.model.isInvariantMap = true;
|
|
73
|
-
this.viewerGrid.invalidate();
|
|
113
|
+
this.mode = MONOMER_POSITION_MODE.INVARIANT_MAP;
|
|
74
114
|
});
|
|
75
115
|
invariantMapMode.addPostfix('Invariant Map');
|
|
76
116
|
const setDefaultProperties = (input: DG.InputBase): void => {
|
|
@@ -97,89 +137,19 @@ export class SARViewerBase extends DG.JsViewer {
|
|
|
97
137
|
}
|
|
98
138
|
this.viewerGrid?.invalidate();
|
|
99
139
|
}
|
|
100
|
-
|
|
101
|
-
onPropertyChanged(property: DG.Property): void {
|
|
102
|
-
super.onPropertyChanged(property);
|
|
103
|
-
|
|
104
|
-
this.render(true);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** Structure-activity relationship viewer */
|
|
109
|
-
export class MonomerPosition extends SARViewerBase {
|
|
110
|
-
_titleHost = ui.divText('Mutation Cliffs', {id: 'pep-viewer-title'});
|
|
111
|
-
_name = 'MC';
|
|
112
|
-
_isVertical = false;
|
|
113
|
-
colorColumnName: string;
|
|
114
|
-
aggregation: string;
|
|
115
|
-
|
|
116
|
-
constructor() {
|
|
117
|
-
super();
|
|
118
|
-
this.colorColumnName = this.string('colorColumnName', C.COLUMNS_NAMES.ACTIVITY_SCALED, {category: 'Invariant Map'});
|
|
119
|
-
this.aggregation = this.string('aggregation', 'avg', {category: 'Invariant Map', choices: Object.values(DG.AGG)});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
get name(): string {return this._name;}
|
|
123
|
-
|
|
124
|
-
get viewerGrid(): DG.Grid {
|
|
125
|
-
if (!this._viewerGrid)
|
|
126
|
-
this.createMonomerPositionGrid();
|
|
127
|
-
return this._viewerGrid;
|
|
128
|
-
}
|
|
129
|
-
set viewerGrid(grid: DG.Grid) {
|
|
130
|
-
this._viewerGrid = grid;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
onTableAttached(): void {
|
|
134
|
-
super.onTableAttached();
|
|
135
|
-
this.subs.push(this.model.onSettingsChanged.subscribe(() => {
|
|
136
|
-
this.createMonomerPositionGrid();
|
|
137
|
-
this.render();
|
|
138
|
-
}));
|
|
139
|
-
this.render();
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
onPropertyChanged(property: DG.Property): void {
|
|
143
|
-
super.onPropertyChanged(property);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
createMonomerPositionGrid(): void {
|
|
147
|
-
this.viewerGrid = this.model.monomerPositionDf.plot.grid();
|
|
148
|
-
this.viewerGrid.sort([C.COLUMNS_NAMES.MONOMER]);
|
|
149
|
-
this.viewerGrid.columns.setOrder([C.COLUMNS_NAMES.MONOMER, ...this.model.splitSeqDf.columns.names()]);
|
|
150
|
-
const monomerCol = this.model.monomerPositionDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
151
|
-
CR.setAARRenderer(monomerCol, this.model.alphabet);
|
|
152
|
-
this.viewerGrid.onCellRender.subscribe((args: DG.GridCellRenderArgs) => renderCell(args, this.model,
|
|
153
|
-
this.model.isInvariantMap, this.dataFrame.getCol(this.colorColumnName), this.aggregation as DG.AggregationType));
|
|
154
|
-
this.viewerGrid.onCellTooltip((cell: DG.GridCell, x: number, y: number) => showTooltip(cell, x, y, this.model));
|
|
155
|
-
this.viewerGrid.root.addEventListener('click', (ev) => {
|
|
156
|
-
const gridCell = this.viewerGrid.hitTest(ev.offsetX, ev.offsetY);
|
|
157
|
-
if (!gridCell?.isTableCell || gridCell?.tableColumn?.name == C.COLUMNS_NAMES.MONOMER)
|
|
158
|
-
return;
|
|
159
|
-
|
|
160
|
-
const position = gridCell!.tableColumn!.name;
|
|
161
|
-
const aar = monomerCol.get(gridCell!.tableRowIndex!);
|
|
162
|
-
chooseAction(aar, position, ev.shiftKey, this.model.isInvariantMap, this.model);
|
|
163
|
-
this.viewerGrid.invalidate();
|
|
164
|
-
this.model.fireBitsetChanged();
|
|
165
|
-
});
|
|
166
|
-
this.viewerGrid.onCurrentCellChanged.subscribe((_gc) => cellChanged(this.model.monomerPositionDf, this.model));
|
|
167
|
-
|
|
168
|
-
setViewerGridProps(this.viewerGrid, false);
|
|
169
|
-
}
|
|
170
140
|
}
|
|
171
141
|
|
|
172
142
|
/** Vertical structure activity relationship viewer */
|
|
173
|
-
export class MostPotentResiduesViewer extends
|
|
174
|
-
_name = 'MPR';
|
|
143
|
+
export class MostPotentResiduesViewer extends DG.JsViewer {
|
|
175
144
|
_titleHost = ui.divText(VIEWER_TYPE.MOST_POTENT_RESIDUES, {id: 'pep-viewer-title'});
|
|
176
|
-
|
|
145
|
+
_viewerGrid!: DG.Grid;
|
|
146
|
+
_model!: PeptidesModel;
|
|
177
147
|
|
|
178
148
|
constructor() {
|
|
179
149
|
super();
|
|
180
150
|
}
|
|
181
151
|
|
|
182
|
-
get name(): string {return
|
|
152
|
+
get name(): string {return VIEWER_TYPE.MOST_POTENT_RESIDUES;}
|
|
183
153
|
|
|
184
154
|
get viewerGrid(): DG.Grid {
|
|
185
155
|
if (!this._viewerGrid)
|
|
@@ -190,8 +160,17 @@ export class MostPotentResiduesViewer extends SARViewerBase {
|
|
|
190
160
|
this._viewerGrid = grid;
|
|
191
161
|
}
|
|
192
162
|
|
|
163
|
+
get model(): PeptidesModel {
|
|
164
|
+
this._model ??= PeptidesModel.getInstance(this.dataFrame);
|
|
165
|
+
return this._model;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
detach(): void {this.subs.forEach((sub) => sub.unsubscribe());}
|
|
169
|
+
|
|
193
170
|
onTableAttached(): void {
|
|
194
171
|
super.onTableAttached();
|
|
172
|
+
this.subs.push(this.model.onMonomerPositionSelectionChanged.subscribe(() => this.viewerGrid.invalidate()));
|
|
173
|
+
this.helpUrl = '/help/domains/bio/peptides.md';
|
|
195
174
|
this.subs.push(this.model.onSettingsChanged.subscribe(() => {
|
|
196
175
|
this.createMostPotentResiduesGrid();
|
|
197
176
|
this.render();
|
|
@@ -201,6 +180,7 @@ export class MostPotentResiduesViewer extends SARViewerBase {
|
|
|
201
180
|
|
|
202
181
|
onPropertyChanged(property: DG.Property): void {
|
|
203
182
|
super.onPropertyChanged(property);
|
|
183
|
+
this.render();
|
|
204
184
|
}
|
|
205
185
|
|
|
206
186
|
createMostPotentResiduesGrid(): void {
|
|
@@ -226,13 +206,31 @@ export class MostPotentResiduesViewer extends SARViewerBase {
|
|
|
226
206
|
const aar = monomerCol.get(tableRowIdx);
|
|
227
207
|
chooseAction(aar, position!.toFixed(), ev.shiftKey, false, this.model);
|
|
228
208
|
this.viewerGrid.invalidate();
|
|
229
|
-
this.model.fireBitsetChanged();
|
|
209
|
+
// this.model.fireBitsetChanged();
|
|
230
210
|
});
|
|
231
211
|
this.viewerGrid.onCurrentCellChanged.subscribe((_gc) => cellChanged(this.model.mostPotentResiduesDf, this.model));
|
|
232
212
|
const mdCol: DG.GridColumn = this.viewerGrid.col(C.COLUMNS_NAMES.MEAN_DIFFERENCE)!;
|
|
233
213
|
mdCol.name = 'Diff';
|
|
234
214
|
setViewerGridProps(this.viewerGrid, true);
|
|
235
215
|
}
|
|
216
|
+
|
|
217
|
+
render(refreshOnly = false): void {
|
|
218
|
+
if (!refreshOnly) {
|
|
219
|
+
$(this.root).empty();
|
|
220
|
+
const switchHost = ui.divText(VIEWER_TYPE.MOST_POTENT_RESIDUES, {id: 'pep-viewer-title'});
|
|
221
|
+
const tips: HTMLElement = ui.iconFA('question');
|
|
222
|
+
ui.tooltip.bind(tips,
|
|
223
|
+
() => ui.divV([ui.divText('Color intensity - p-value'), ui.divText('Circle size - Mean difference')]));
|
|
224
|
+
|
|
225
|
+
$(tips).addClass('pep-help-icon');
|
|
226
|
+
|
|
227
|
+
const viewerRoot = this.viewerGrid.root;
|
|
228
|
+
viewerRoot.style.width = 'auto';
|
|
229
|
+
const header = ui.divH([switchHost, tips], {style: {alignSelf: 'center', lineHeight: 'normal'}});
|
|
230
|
+
this.root.appendChild(ui.divV([header, viewerRoot]));
|
|
231
|
+
}
|
|
232
|
+
this.viewerGrid?.invalidate();
|
|
233
|
+
}
|
|
236
234
|
}
|
|
237
235
|
|
|
238
236
|
function renderCell(args: DG.GridCellRenderArgs, model: PeptidesModel, isInvariantMap?: boolean,
|
|
@@ -292,16 +290,16 @@ function renderCell(args: DG.GridCellRenderArgs, model: PeptidesModel, isInvaria
|
|
|
292
290
|
|
|
293
291
|
const color = DG.Color.scaleColor(cellColorDataCol.aggregate(colorAgg!), colorColStats.min, colorColStats.max);
|
|
294
292
|
CR.renderInvaraintMapCell(
|
|
295
|
-
canvasContext, currentMonomer, currentPosition, model.
|
|
293
|
+
canvasContext, currentMonomer, currentPosition, model.monomerPositionFilter, value, bound, color);
|
|
296
294
|
} else {
|
|
297
295
|
CR.renderMutationCliffCell(canvasContext, currentMonomer, currentPosition, model.monomerPositionStats, bound,
|
|
298
|
-
model.
|
|
296
|
+
model.monomerPositionSelection, model.mutationCliffs, model.settings.isBidirectional);
|
|
299
297
|
}
|
|
300
298
|
args.preventDefault();
|
|
301
299
|
canvasContext.restore();
|
|
302
300
|
}
|
|
303
301
|
|
|
304
|
-
function showTooltip(cell: DG.GridCell, x: number, y: number, model: PeptidesModel): boolean {
|
|
302
|
+
export function showTooltip(cell: DG.GridCell, x: number, y: number, model: PeptidesModel): boolean {
|
|
305
303
|
const renderColNames = [...model.splitSeqDf.columns.names(), C.COLUMNS_NAMES.MEAN_DIFFERENCE];
|
|
306
304
|
const tableCol = cell.tableColumn;
|
|
307
305
|
const tableColName = tableCol?.name;
|
|
@@ -323,12 +321,12 @@ function showTooltip(cell: DG.GridCell, x: number, y: number, model: PeptidesMod
|
|
|
323
321
|
return true;
|
|
324
322
|
}
|
|
325
323
|
|
|
326
|
-
function chooseAction(aar: string, position: string, isShiftPressed: boolean,
|
|
324
|
+
function chooseAction(aar: string, position: string, isShiftPressed: boolean, isFilter: boolean,
|
|
327
325
|
model: PeptidesModel): void {
|
|
328
|
-
if (isShiftPressed)
|
|
329
|
-
model.
|
|
330
|
-
|
|
331
|
-
|
|
326
|
+
if (!isShiftPressed)
|
|
327
|
+
model.initMonomerPositionSelection({cleanInit: true, notify: false});
|
|
328
|
+
|
|
329
|
+
model.modifyMonomerPositionSelection(aar, position, isFilter);
|
|
332
330
|
}
|
|
333
331
|
|
|
334
332
|
function cellChanged(table: DG.DataFrame, model: PeptidesModel): void {
|
|
@@ -5,27 +5,27 @@ import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations'
|
|
|
5
5
|
import $ from 'cash-dom';
|
|
6
6
|
|
|
7
7
|
import * as C from '../utils/constants';
|
|
8
|
-
import {
|
|
8
|
+
import {getStats, Stats} from '../utils/statistics';
|
|
9
9
|
import {PeptidesModel} from '../model';
|
|
10
|
-
import {
|
|
10
|
+
import {getStatsSummary} from '../utils/misc';
|
|
11
|
+
import BitArray from '@datagrok-libraries/utils/src/bit-array';
|
|
11
12
|
|
|
12
13
|
const allConst = 'All';
|
|
13
14
|
const otherConst = 'Other';
|
|
14
15
|
|
|
15
16
|
export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel): DG.Widget {
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
17
|
+
const activityCol = table.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
18
|
+
const activityColData = activityCol.getRawData();
|
|
19
|
+
const rowCount = activityCol.length;
|
|
20
|
+
const selectionObject = model.monomerPositionSelection;
|
|
19
21
|
const clustersColName = model.settings.clustersColumnName;
|
|
20
22
|
let clustersProcessedObject: string[] = [];
|
|
21
23
|
if (clustersColName)
|
|
22
|
-
clustersProcessedObject = model.
|
|
24
|
+
clustersProcessedObject = model.clusterSelection;
|
|
23
25
|
|
|
24
26
|
const positions = Object.keys(selectionObject);
|
|
25
|
-
const positionsLen = positions.length;
|
|
26
27
|
let aarStr = allConst;
|
|
27
28
|
let otherStr = '';
|
|
28
|
-
// const useSelectedStr = model.isPeptideSpaceChangingBitset;
|
|
29
29
|
|
|
30
30
|
const updateDistributionHost = (): void => {
|
|
31
31
|
model.splitByPos = splitByPosition.value!;
|
|
@@ -34,34 +34,30 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
34
34
|
if (splitByPosition.value && splitByAAR.value) {
|
|
35
35
|
otherStr = otherConst;
|
|
36
36
|
for (const position of positions) {
|
|
37
|
-
const posCol = table.getCol(position);
|
|
38
37
|
const aarList = selectionObject[position];
|
|
39
38
|
if (aarList.length === 0)
|
|
40
39
|
continue;
|
|
41
40
|
|
|
41
|
+
const posCol = table.getCol(position);
|
|
42
|
+
const posColCategories = posCol.categories;
|
|
43
|
+
const posColData = posCol.getRawData();
|
|
44
|
+
|
|
42
45
|
for (const aar of aarList) {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
|
|
51
|
-
|
|
52
|
-
const colResults: {[colName: string]: number} = {};
|
|
53
|
-
for (const [col, agg] of Object.entries(model.settings.columns || {})) {
|
|
54
|
-
const currentCol = table.getCol(col);
|
|
55
|
-
const currentColData = currentCol.getRawData();
|
|
56
|
-
const tempCol = DG.Column.float('', indexes.length);
|
|
57
|
-
tempCol.init((i) => currentColData[indexes[i]]);
|
|
58
|
-
colResults[`${agg}(${col})`] = tempCol.stats[agg as keyof DG.Stats] as number;
|
|
59
|
-
}
|
|
46
|
+
const labels = getDistributionLegend(`${position} : ${aar}`, otherStr);
|
|
47
|
+
|
|
48
|
+
const aarCategoryIndex = posColCategories.indexOf(aar);
|
|
49
|
+
const mask = DG.BitSet.create(rowCount, (i) => posColData[i] === aarCategoryIndex);
|
|
50
|
+
const distributionTable = DG.DataFrame.fromColumns(
|
|
51
|
+
[activityCol, DG.Column.fromBitSet(C.COLUMNS_NAMES.SPLIT_COL, mask)]);
|
|
52
|
+
const hist = getActivityDistribution(distributionTable);
|
|
60
53
|
|
|
61
54
|
const stats = model.monomerPositionStats[position][aar];
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
const
|
|
55
|
+
const tableMap = getStatsTableMap(stats, {fractionDigits: 2});
|
|
56
|
+
|
|
57
|
+
const aggregatedColMap = model.getAggregatedColumnValues({filterDf: true, mask, fractionDigits: 2});
|
|
58
|
+
|
|
59
|
+
const resultMap = {...tableMap, ...aggregatedColMap};
|
|
60
|
+
const distributionRoot = getStatsSummary(labels, hist, resultMap);
|
|
65
61
|
$(distributionRoot).addClass('d4-flex-col');
|
|
66
62
|
|
|
67
63
|
res.push(distributionRoot);
|
|
@@ -69,40 +65,32 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
69
65
|
}
|
|
70
66
|
} else if (splitByPosition.value) {
|
|
71
67
|
otherStr = otherConst;
|
|
72
|
-
const activityScaledData = activityScaledCol.toList();
|
|
73
68
|
for (const position of positions) {
|
|
74
|
-
const posCol = table.getCol(position);
|
|
75
69
|
const aarList = selectionObject[position];
|
|
76
70
|
if (aarList.length === 0)
|
|
77
71
|
continue;
|
|
78
72
|
|
|
79
73
|
aarStr = `${position}: {${aarList.join(', ')}}`;
|
|
74
|
+
const labels = getDistributionLegend(aarStr, otherStr);
|
|
80
75
|
|
|
81
|
-
|
|
82
|
-
const
|
|
76
|
+
const posCol = table.getCol(position);
|
|
77
|
+
const posColCategories = posCol.categories;
|
|
78
|
+
const posColData = posCol.getRawData();
|
|
79
|
+
const aarIndexesList = aarList.map((aar) => posColCategories.indexOf(aar));
|
|
80
|
+
const mask = DG.BitSet.create(rowCount, (i) => aarIndexesList.includes(posColData[i]));
|
|
83
81
|
const splitCol = DG.Column.fromBitSet(C.COLUMNS_NAMES.SPLIT_COL, mask);
|
|
84
82
|
|
|
85
|
-
const
|
|
86
|
-
mask: splitCol.toList() as boolean[],
|
|
87
|
-
trueCount: mask.trueCount,
|
|
88
|
-
falseCount: mask.falseCount,
|
|
89
|
-
};
|
|
90
|
-
const stats = getStats(activityScaledData, maskInfo);
|
|
91
|
-
const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
|
|
92
|
-
|
|
93
|
-
const indexes = mask.getSelectedIndexes();
|
|
94
|
-
const colResults: {[colName: string]: number} = {};
|
|
95
|
-
for (const [col, agg] of Object.entries(model.settings.columns || {})) {
|
|
96
|
-
const currentCol = table.getCol(col);
|
|
97
|
-
const currentColData = currentCol.getRawData();
|
|
98
|
-
const tempCol = DG.Column.float('', indexes.length);
|
|
99
|
-
tempCol.init((i) => currentColData[indexes[i]]);
|
|
100
|
-
colResults[`${agg}(${col})`] = tempCol.stats[agg as keyof DG.Stats] as number;
|
|
101
|
-
}
|
|
83
|
+
const aggregatedColMap = model.getAggregatedColumnValues({filterDf: true, mask, fractionDigits: 2});
|
|
102
84
|
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
|
|
85
|
+
const distributionTable = DG.DataFrame.fromColumns([activityCol, splitCol]);
|
|
86
|
+
const hist = getActivityDistribution(distributionTable);
|
|
87
|
+
|
|
88
|
+
const bitArray = BitArray.fromUint32Array(rowCount, splitCol.getRawData() as Uint32Array);
|
|
89
|
+
const stats = getStats(activityColData, bitArray);
|
|
90
|
+
const tableMap = getStatsTableMap(stats, {fractionDigits: 2});
|
|
91
|
+
|
|
92
|
+
const resultMap = {...tableMap, ...aggregatedColMap};
|
|
93
|
+
const distributionRoot = getStatsSummary(labels, hist, resultMap);
|
|
106
94
|
$(distributionRoot).addClass('d4-flex-col');
|
|
107
95
|
|
|
108
96
|
res.push(distributionRoot);
|
|
@@ -123,43 +111,30 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
123
111
|
}
|
|
124
112
|
|
|
125
113
|
otherStr = otherConst;
|
|
126
|
-
const activityScaledData = activityScaledCol.getRawData();
|
|
127
114
|
for (const aar of aars) {
|
|
128
115
|
const posList = reversedSelectionObject[aar];
|
|
116
|
+
const posColList = posList.map((pos) => table.getCol(pos));
|
|
117
|
+
const posColCategoriesList = posColList.map((posCol) => posCol.categories);
|
|
118
|
+
const posColDataList = posColList.map((posCol) => posCol.getRawData());
|
|
119
|
+
const aarCategoryIndexList = posColCategoriesList.map((posColCategories) => posColCategories.indexOf(aar));
|
|
120
|
+
|
|
129
121
|
aarStr = `${aar}: {${posList.join(', ')}}`;
|
|
122
|
+
const labels = getDistributionLegend(aarStr, otherStr);
|
|
123
|
+
|
|
124
|
+
const mask = DG.BitSet.create(rowCount,
|
|
125
|
+
(i) => posColDataList.some((posColData, j) => posColData[i] === aarCategoryIndexList[j]));
|
|
126
|
+
const aggregatedColMap = model.getAggregatedColumnValues({filterDf: true, mask, fractionDigits: 2});
|
|
130
127
|
|
|
131
|
-
//OPTIMIZE: don't create Bitset, use bool[]
|
|
132
|
-
const mask = DG.BitSet.create(rowCount, (i) => {
|
|
133
|
-
const currentRow = table.row(i);
|
|
134
|
-
for (const position of posList) {
|
|
135
|
-
if (currentRow.get(position) == aar)
|
|
136
|
-
return true;
|
|
137
|
-
}
|
|
138
|
-
return false;
|
|
139
|
-
});
|
|
140
128
|
const splitCol = DG.Column.fromBitSet(C.COLUMNS_NAMES.SPLIT_COL, mask);
|
|
129
|
+
const distributionTable = DG.DataFrame.fromColumns([activityCol, splitCol]);
|
|
130
|
+
const hist = getActivityDistribution(distributionTable);
|
|
141
131
|
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
falseCount: mask.falseCount,
|
|
146
|
-
};
|
|
147
|
-
const stats = getStats(activityScaledData, maskInfo);
|
|
148
|
-
const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
|
|
149
|
-
|
|
150
|
-
const indexes = mask.getSelectedIndexes();
|
|
151
|
-
const colResults: {[colName: string]: number} = {};
|
|
152
|
-
for (const [col, agg] of Object.entries(model.settings.columns || {})) {
|
|
153
|
-
const currentCol = table.getCol(col);
|
|
154
|
-
const currentColData = currentCol.getRawData();
|
|
155
|
-
const tempCol = DG.Column.float('', indexes.length);
|
|
156
|
-
tempCol.init((i) => currentColData[indexes[i]]);
|
|
157
|
-
colResults[`${agg}(${col})`] = tempCol.stats[agg as keyof DG.Stats] as number;
|
|
158
|
-
}
|
|
132
|
+
const bitArray = BitArray.fromUint32Array(rowCount, splitCol.getRawData() as Uint32Array);
|
|
133
|
+
const stats = getStats(activityColData, bitArray);
|
|
134
|
+
const tableMap = getStatsTableMap(stats, {fractionDigits: 2});
|
|
159
135
|
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
const distributionRoot = wrapDistroAndStatsDefault(das.labels, das.histRoot, resultMap);
|
|
136
|
+
const resultMap: {[key: string]: any} = {...tableMap, ...aggregatedColMap};
|
|
137
|
+
const distributionRoot = getStatsSummary(labels, hist, resultMap);
|
|
163
138
|
$(distributionRoot).addClass('d4-flex-col');
|
|
164
139
|
|
|
165
140
|
res.push(distributionRoot);
|
|
@@ -170,10 +145,8 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
170
145
|
res.push(ui.divText('No distribution'));
|
|
171
146
|
else {
|
|
172
147
|
otherStr = '';
|
|
173
|
-
if (
|
|
174
|
-
|
|
175
|
-
otherStr = otherConst;
|
|
176
|
-
} else if (positionsLen) {
|
|
148
|
+
if (Object.values(selectionObject).some((selectedAar) => selectedAar.length !== 0) ||
|
|
149
|
+
clustersProcessedObject.length !== 0) {
|
|
177
150
|
aarStr = '';
|
|
178
151
|
for (const position of positions) {
|
|
179
152
|
const aarList = selectionObject[position];
|
|
@@ -184,25 +157,20 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
184
157
|
aarStr += `Clusters: ${clustersProcessedObject.join(', ')}`;
|
|
185
158
|
otherStr = otherConst;
|
|
186
159
|
}
|
|
160
|
+
const labels = getDistributionLegend(aarStr, otherStr);
|
|
187
161
|
|
|
188
|
-
const distributionTable = DG.DataFrame.fromColumns([
|
|
162
|
+
const distributionTable = DG.DataFrame.fromColumns([activityCol, splitCol]);
|
|
163
|
+
const hist = getActivityDistribution(distributionTable);
|
|
189
164
|
|
|
190
|
-
const
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
165
|
+
const bitArray = BitArray.fromUint32Array(rowCount, splitCol.getRawData() as Uint32Array);
|
|
166
|
+
const mask = DG.BitSet.create(rowCount, (i) => bitArray.getBit(i));
|
|
167
|
+
const aggregatedColMap = model.getAggregatedColumnValues({filterDf: true, mask, fractionDigits: 2});
|
|
168
|
+
|
|
169
|
+
const stats = getStats(activityColData, bitArray);
|
|
170
|
+
const tableMap = getStatsTableMap(stats, {fractionDigits: 2});
|
|
196
171
|
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
trueCount: compoundBs.trueCount,
|
|
200
|
-
falseCount: compoundBs.falseCount,
|
|
201
|
-
};
|
|
202
|
-
const stats = getStats(activityScaledCol.getRawData(), maskInfo);
|
|
203
|
-
const das = getDistributionAndStats(distributionTable, stats, aarStr, otherStr);
|
|
204
|
-
const resultMap: {[key: string]: any} = {...das.tableMap, ...colResults};
|
|
205
|
-
const distributionRoot = wrapDistroAndStatsDefault(das.labels, das.histRoot, resultMap);
|
|
172
|
+
const resultMap: {[key: string]: any} = {...tableMap, ...aggregatedColMap};
|
|
173
|
+
const distributionRoot = getStatsSummary(labels, hist, resultMap);
|
|
206
174
|
$(distributionRoot).addClass('d4-flex-col');
|
|
207
175
|
|
|
208
176
|
res.push(distributionRoot);
|
|
@@ -212,14 +180,14 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
212
180
|
};
|
|
213
181
|
|
|
214
182
|
const setDefaultProperties = (input: DG.InputBase): void => {
|
|
215
|
-
input.enabled = !model.
|
|
183
|
+
input.enabled = !model.isMonomerPositionSelectionEmpty;
|
|
216
184
|
$(input.root).find('.ui-input-editor').css('margin', '0px');
|
|
217
185
|
$(input.root).find('.ui-input-description').css('padding', '0px').css('padding-left', '5px');
|
|
218
186
|
};
|
|
219
187
|
|
|
220
188
|
let defaultValuePos = model.splitByPos;
|
|
221
189
|
let defaultValueAAR = model.splitByAAR;
|
|
222
|
-
if (!model.
|
|
190
|
+
if (!model.isClusterSelectionEmpty && model.isMonomerPositionSelectionEmpty) {
|
|
223
191
|
defaultValuePos = false;
|
|
224
192
|
defaultValueAAR = false;
|
|
225
193
|
}
|
|
@@ -239,34 +207,36 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
239
207
|
return new DG.Widget(ui.divV([controlsHost, distributionHost]));
|
|
240
208
|
}
|
|
241
209
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
isTooltip: boolean = false, splitColName?: string): DistroAndStats {
|
|
246
|
-
const labels = ui.divV([
|
|
247
|
-
ui.label(thisLabel, {style: {color: DG.Color.toHtml(otherLabel == '' ? DG.Color.blue : DG.Color.orange)}}),
|
|
248
|
-
ui.label(otherLabel, {style: {color: DG.Color.toHtml(DG.Color.blue)}})]);
|
|
249
|
-
|
|
250
|
-
const histRoot = table.plot.histogram({
|
|
210
|
+
export function getActivityDistribution(table: DG.DataFrame, isTooltip: boolean = false,
|
|
211
|
+
): DG.Viewer<DG.IHistogramLookSettings> {
|
|
212
|
+
const hist = table.plot.histogram({
|
|
251
213
|
filteringEnabled: false,
|
|
252
214
|
valueColumnName: C.COLUMNS_NAMES.ACTIVITY_SCALED,
|
|
253
|
-
splitColumnName:
|
|
215
|
+
splitColumnName: C.COLUMNS_NAMES.SPLIT_COL,
|
|
254
216
|
legendVisibility: 'Never',
|
|
255
217
|
showXAxis: true,
|
|
256
218
|
showColumnSelector: false,
|
|
257
219
|
showRangeSlider: false,
|
|
258
220
|
showBinSelector: !isTooltip,
|
|
259
221
|
backColor: isTooltip ? '#fdffe5' : '#fffff',
|
|
260
|
-
}).
|
|
261
|
-
|
|
222
|
+
}) as DG.Viewer<DG.IHistogramLookSettings>;
|
|
223
|
+
hist.root.style.width = 'auto';
|
|
224
|
+
return hist;
|
|
225
|
+
}
|
|
262
226
|
|
|
263
|
-
|
|
227
|
+
export function getStatsTableMap(stats: Stats, options: {fractionDigits?: number} = {}): StringDictionary {
|
|
228
|
+
const tableMap = {
|
|
264
229
|
'Statistics:': '',
|
|
265
230
|
'Count': stats.count.toString(),
|
|
266
|
-
'Ratio': stats.ratio.toFixed(
|
|
267
|
-
'p-value': stats.pValue < 0.01 ? '<0.01' : stats.pValue.toFixed(
|
|
268
|
-
'Mean difference': stats.meanDifference.toFixed(
|
|
231
|
+
'Ratio': stats.ratio.toFixed(options.fractionDigits),
|
|
232
|
+
'p-value': stats.pValue < 0.01 ? '<0.01' : stats.pValue.toFixed(options.fractionDigits),
|
|
233
|
+
'Mean difference': stats.meanDifference.toFixed(options.fractionDigits),
|
|
269
234
|
};
|
|
235
|
+
return tableMap;
|
|
236
|
+
}
|
|
270
237
|
|
|
271
|
-
|
|
238
|
+
export function getDistributionLegend(thisLabel: string, otherLabel: string = ''): HTMLDivElement {
|
|
239
|
+
return ui.divV([
|
|
240
|
+
ui.label(thisLabel, {style: {color: DG.Color.toHtml(otherLabel.length === 0 ? DG.Color.blue : DG.Color.orange)}}),
|
|
241
|
+
ui.label(otherLabel, {style: {color: DG.Color.toHtml(DG.Color.blue)}})]);
|
|
272
242
|
}
|
|
@@ -7,8 +7,8 @@ import {getSeparator} from '../utils/misc';
|
|
|
7
7
|
|
|
8
8
|
export function mutationCliffsWidget(table: DG.DataFrame, model: PeptidesModel): DG.Widget {
|
|
9
9
|
const currentFilter = table.filter.getSelectedIndexes();
|
|
10
|
-
const substInfo = model.
|
|
11
|
-
const currentCell = model.
|
|
10
|
+
const substInfo = model.mutationCliffs;
|
|
11
|
+
const currentCell = model.monomerPositionSelection;
|
|
12
12
|
const positions = Object.keys(currentCell);
|
|
13
13
|
|
|
14
14
|
if (!positions.length)
|