@datagrok/peptides 0.8.9 → 0.8.13
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 +2 -1
- package/dist/package-test.js +22626 -0
- package/dist/package.js +21429 -0
- package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +8840 -0
- package/jest.config.js +33 -0
- package/package.json +75 -62
- package/src/__jest__/remote.test.ts +50 -0
- package/src/__jest__/test-node.ts +96 -0
- package/src/model.ts +950 -86
- package/src/monomer-library.ts +8 -0
- package/src/package-test.ts +3 -2
- package/src/package.ts +57 -22
- package/src/peptides.ts +165 -119
- package/src/styles.css +8 -0
- package/src/tests/peptides-tests.ts +17 -78
- package/src/tests/utils.ts +1 -7
- package/src/utils/SAR-multiple-filter.ts +439 -0
- package/src/utils/SAR-multiple-selection.ts +177 -0
- package/src/utils/cell-renderer.ts +49 -50
- package/src/utils/chem-palette.ts +61 -163
- package/src/utils/constants.ts +56 -0
- package/src/utils/filtering-statistics.ts +62 -0
- package/src/utils/multiple-sequence-alignment.ts +33 -2
- package/src/utils/multivariate-analysis.ts +79 -0
- package/src/utils/peptide-similarity-space.ts +12 -31
- package/src/utils/types.ts +10 -0
- package/src/viewers/logo-viewer.ts +2 -1
- package/src/viewers/peptide-space-viewer.ts +121 -0
- package/src/viewers/sar-viewer.ts +111 -313
- package/src/viewers/stacked-barchart-viewer.ts +126 -173
- package/src/widgets/analyze-peptides.ts +39 -18
- package/src/widgets/distribution.ts +61 -0
- package/src/widgets/manual-alignment.ts +3 -3
- package/src/widgets/peptide-molecule.ts +4 -4
- package/src/widgets/subst-table.ts +30 -22
- package/test-Peptides-f8114def7953-4bf59d70.html +256 -0
- package/src/describe.ts +0 -534
- package/src/utils/split-aligned.ts +0 -72
- package/src/viewers/subst-viewer.ts +0 -320
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
import * as DG from 'datagrok-api/dg';
|
|
2
|
-
import {ChemPalette} from '../utils/chem-palette';
|
|
3
2
|
import * as rxjs from 'rxjs';
|
|
4
3
|
import * as ui from 'datagrok-api/ui';
|
|
5
|
-
|
|
4
|
+
import {MonomerLibrary} from '../monomer-library';
|
|
5
|
+
import {PeptidesController} from '../peptides';
|
|
6
|
+
|
|
7
|
+
import * as C from '../utils/constants';
|
|
8
|
+
import * as type from '../utils/types';
|
|
6
9
|
|
|
7
10
|
export function addViewerToHeader(grid: DG.Grid, barchart: StackedBarChart) {
|
|
8
11
|
if (grid.temp['containsBarchart'])
|
|
9
12
|
return;
|
|
13
|
+
|
|
14
|
+
const compareBarParts = (bar1: type.BarChart.BarPart | null, bar2: type.BarChart.BarPart | null) =>
|
|
15
|
+
bar1 && bar2 && bar1.aaName === bar2.aaName && bar1.colName === bar2.colName;
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
const eventAction = (mouseMove: MouseEvent) => {
|
|
12
18
|
const cell = grid.hitTest(mouseMove.offsetX, mouseMove.offsetY);
|
|
13
|
-
if (cell
|
|
14
|
-
barchart.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
barchart.
|
|
22
|
-
|
|
19
|
+
if (cell?.isColHeader && cell.tableColumn?.semType == C.SEM_TYPES.AMINO_ACIDS) {
|
|
20
|
+
const newBarPart = barchart.findAARandPosition(cell, mouseMove);
|
|
21
|
+
const previousClickedBarPart = barchart._previousClickedBarPart;
|
|
22
|
+
if (mouseMove.type === 'click' && compareBarParts(newBarPart, previousClickedBarPart))
|
|
23
|
+
barchart.isSameBarClicked = true;
|
|
24
|
+
else
|
|
25
|
+
barchart.currentBarPart = newBarPart;
|
|
26
|
+
barchart.requestAction(mouseMove);
|
|
27
|
+
barchart.computeData();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
23
30
|
|
|
24
31
|
// The following events makes the barchart interactive
|
|
25
32
|
rxjs.fromEvent<MouseEvent>(grid.overlay, 'mousemove').subscribe((mouseMove: MouseEvent) => eventAction(mouseMove));
|
|
@@ -32,17 +39,18 @@ export function addViewerToHeader(grid: DG.Grid, barchart: StackedBarChart) {
|
|
|
32
39
|
grid.setOptions({'colHeaderHeight': 130});
|
|
33
40
|
|
|
34
41
|
grid.onCellTooltip((cell, x, y) => {
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
if (
|
|
43
|
+
cell.tableColumn &&
|
|
44
|
+
[C.SEM_TYPES.AMINO_ACIDS, C.SEM_TYPES.ALIGNED_SEQUENCE].includes(cell.tableColumn.semType as C.SEM_TYPES)
|
|
45
|
+
) {
|
|
46
|
+
if (!cell.isColHeader) {
|
|
47
|
+
const monomerLib = cell.cell.dataFrame.temp[MonomerLibrary.id];
|
|
48
|
+
PeptidesController.chemPalette.showTooltip(cell, x, y, monomerLib);
|
|
49
|
+
} else if (barchart.currentBarPart) {
|
|
50
|
+
let elements: HTMLElement[] = [];
|
|
51
|
+
elements = elements.concat([ui.divText(barchart.currentBarPart.aaName)]);
|
|
52
|
+
ui.tooltip.show(ui.divV(elements), x, y);
|
|
44
53
|
}
|
|
45
|
-
return true;
|
|
46
54
|
}
|
|
47
55
|
return true;
|
|
48
56
|
});
|
|
@@ -67,38 +75,39 @@ export function addViewerToHeader(grid: DG.Grid, barchart: StackedBarChart) {
|
|
|
67
75
|
});
|
|
68
76
|
|
|
69
77
|
grid.temp['containsBarchart'] = true;
|
|
78
|
+
//FIXME: for some reason barchat didn't show when running analysis. This fixes it, but it's bad. Find a way to fix
|
|
79
|
+
// the problem
|
|
80
|
+
barchart.unhighlight();
|
|
70
81
|
}
|
|
71
82
|
|
|
72
|
-
type stackedBarChartDatatype = {
|
|
73
|
-
'name': string,
|
|
74
|
-
'data': {'name': string, 'count': number, 'selectedCount': number, 'fixedSelectedCount': number}[],
|
|
75
|
-
}[];
|
|
76
|
-
|
|
77
|
-
type bartStatsType = {
|
|
78
|
-
[Key: string]: {'name': string, 'count': number, 'selectedCount': number, 'fixedSelectedCount': number}[],
|
|
79
|
-
};
|
|
80
|
-
|
|
81
83
|
export class StackedBarChart extends DG.JsViewer {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
84
|
+
dataEmptyAA: string;
|
|
85
|
+
_currentBarPart: type.BarChart.BarPart | null = null;
|
|
86
|
+
tableCanvas: HTMLCanvasElement | undefined;
|
|
87
|
+
aminoColumnNames: string[] = [];
|
|
88
|
+
ord: { [Key: string]: number; } = {};
|
|
89
|
+
aminoColumnIndices: {[Key: string]: number} = {};
|
|
90
|
+
aggregatedFilterTables: type.DataFrameDict = {};
|
|
91
|
+
max = 0;
|
|
92
|
+
barStats: {[Key: string]: type.BarChart.BarStatsObject[]} = {};
|
|
93
|
+
selected: type.BarChart.BarPart[] = [];
|
|
94
|
+
aggregatedSelectedTables: type.DataFrameDict = {};
|
|
95
|
+
controller!: PeptidesController;
|
|
96
|
+
isSameBarClicked: boolean = false;
|
|
97
|
+
_previousClickedBarPart: type.BarChart.BarPart | null = null;
|
|
95
98
|
|
|
96
99
|
constructor() {
|
|
97
100
|
super();
|
|
98
101
|
this.dataEmptyAA = this.string('dataEmptyAA', '-');
|
|
99
102
|
}
|
|
100
103
|
|
|
101
|
-
|
|
104
|
+
get currentBarPart() { return this._currentBarPart; }
|
|
105
|
+
set currentBarPart(barPart: type.BarChart.BarPart | null) {
|
|
106
|
+
this._currentBarPart = barPart;
|
|
107
|
+
this.isSameBarClicked = false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
init() {
|
|
102
111
|
const groups: {[key: string]: string[]} = {
|
|
103
112
|
'yellow': ['C', 'U'],
|
|
104
113
|
'red': ['G', 'P'],
|
|
@@ -108,35 +117,38 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
108
117
|
'orange': ['S', 'T', 'N', 'Q'],
|
|
109
118
|
};
|
|
110
119
|
let i = 0;
|
|
111
|
-
|
|
112
|
-
for (const value of Object.values(groups))
|
|
120
|
+
|
|
121
|
+
for (const value of Object.values(groups)) {
|
|
113
122
|
for (const obj of value)
|
|
114
123
|
this.ord[obj] = i++;
|
|
124
|
+
}
|
|
115
125
|
|
|
116
126
|
this.aminoColumnNames = [];
|
|
117
127
|
}
|
|
118
128
|
|
|
119
129
|
// Stream subscriptions
|
|
120
|
-
onTableAttached()
|
|
130
|
+
async onTableAttached() {
|
|
121
131
|
this.init();
|
|
132
|
+
this.controller = await PeptidesController.getInstance(this.dataFrame);
|
|
133
|
+
this.controller.init(this.dataFrame);
|
|
122
134
|
if (this.dataFrame) {
|
|
123
135
|
this.subs.push(DG.debounce(this.dataFrame.selection.onChanged, 50).subscribe((_) => this.computeData()));
|
|
124
136
|
this.subs.push(DG.debounce(this.dataFrame.filter.onChanged, 50).subscribe((_) => this.computeData()));
|
|
125
|
-
this.
|
|
137
|
+
this.subs.push(DG.debounce(this.dataFrame.onValuesChanged, 50).subscribe(() => this.computeData()));
|
|
126
138
|
}
|
|
127
139
|
}
|
|
128
140
|
|
|
129
141
|
// Cancel subscriptions when the viewer is detached
|
|
130
|
-
detach()
|
|
142
|
+
detach() {
|
|
131
143
|
this.subs.forEach((sub) => sub.unsubscribe());
|
|
132
144
|
}
|
|
133
145
|
|
|
134
|
-
computeData()
|
|
146
|
+
computeData() {
|
|
135
147
|
this.aminoColumnNames = [];
|
|
136
148
|
this.aminoColumnIndices = {};
|
|
137
149
|
|
|
138
150
|
this.dataFrame!.columns.names().forEach((name: string) => {
|
|
139
|
-
if (this.dataFrame!.getCol(name).semType ===
|
|
151
|
+
if (this.dataFrame!.getCol(name).semType === C.SEM_TYPES.AMINO_ACIDS &&
|
|
140
152
|
!this.dataFrame!.getCol(name).categories.includes('COOH') &&
|
|
141
153
|
!this.dataFrame!.getCol(name).categories.includes('NH2')) {
|
|
142
154
|
this.aminoColumnIndices[name] = this.aminoColumnNames.length + 1;
|
|
@@ -144,22 +156,15 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
144
156
|
}
|
|
145
157
|
});
|
|
146
158
|
|
|
147
|
-
this.
|
|
148
|
-
this.aggregatedHighlightedTables = {};
|
|
159
|
+
this.aggregatedFilterTables = {};
|
|
149
160
|
this.aggregatedSelectedTables = {};
|
|
150
161
|
//TODO: optimize it, why store so many tables?
|
|
151
162
|
this.aminoColumnNames.forEach((name) => {
|
|
152
|
-
this.
|
|
163
|
+
this.aggregatedFilterTables[name] = this.dataFrame!
|
|
153
164
|
.groupBy([name])
|
|
154
165
|
.whereRowMask(this.dataFrame!.filter)
|
|
155
166
|
.add('count', name, `${name}_count`)
|
|
156
167
|
.aggregate();
|
|
157
|
-
|
|
158
|
-
this.aggregatedHighlightedTables[name] = this.dataFrame!
|
|
159
|
-
.groupBy([name])
|
|
160
|
-
.whereRowMask(this.highlightedMask!)
|
|
161
|
-
.add('count', name, `${name}_count`)
|
|
162
|
-
.aggregate();
|
|
163
168
|
|
|
164
169
|
this.aggregatedSelectedTables[name] = this.dataFrame!
|
|
165
170
|
.groupBy([name])
|
|
@@ -170,64 +175,41 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
170
175
|
|
|
171
176
|
this.barStats = {};
|
|
172
177
|
|
|
173
|
-
for (const [name, df] of Object.entries(this.
|
|
174
|
-
const
|
|
175
|
-
'name': string,
|
|
176
|
-
'data': { 'name': string, 'count': number, 'highlightedCount': number, 'selectedCount': number}[],
|
|
177
|
-
} = {'name': name, 'data': []};
|
|
178
|
+
for (const [name, df] of Object.entries(this.aggregatedFilterTables)) {
|
|
179
|
+
const colData: {'name': string, 'count': number, 'selectedCount': number}[] = [];
|
|
178
180
|
const aminoCol = df.getCol(name);
|
|
179
181
|
const aminoCountCol = df.getCol(`${name}_count`);
|
|
180
|
-
this.barStats[
|
|
181
|
-
|
|
182
|
+
this.barStats[name] = colData;
|
|
183
|
+
|
|
182
184
|
for (let i = 0; i < df.rowCount; i++) {
|
|
183
185
|
const amino = aminoCol.get(i);
|
|
184
186
|
const aminoCount = aminoCountCol.get(i);
|
|
185
|
-
const aminoObj = {'name': amino, 'count': aminoCount, '
|
|
186
|
-
const aggHighlightedAminoCol = this.aggregatedHighlightedTables[name].getCol(`${name}`);
|
|
187
|
-
const aggHighlightedCountCol = this.aggregatedHighlightedTables[name].getCol(`${name}_count`);
|
|
187
|
+
const aminoObj = {'name': amino, 'count': aminoCount, 'selectedCount': 0};
|
|
188
188
|
const aggSelectedAminoCol = this.aggregatedSelectedTables[name].getCol(`${name}`);
|
|
189
189
|
const aggSelectedCountCol = this.aggregatedSelectedTables[name].getCol(`${name}_count`);
|
|
190
190
|
|
|
191
191
|
if (!amino || amino === this.dataEmptyAA)
|
|
192
192
|
continue;
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
for (
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
aminoObj[col == aggHighlightedCountCol ? 'highlightedCount' : 'selectedCount'] = col.get(j);
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
194
|
+
colData.push(aminoObj);
|
|
195
|
+
|
|
196
|
+
for (let j = 0; j < aggSelectedCountCol.length; j++) {
|
|
197
|
+
const selectedAmino = aggSelectedAminoCol.get(j);
|
|
198
|
+
const curAmino = (selectedAmino);
|
|
199
|
+
if (curAmino == amino) {
|
|
200
|
+
aminoObj['selectedCount'] = aggSelectedCountCol.get(j);
|
|
201
|
+
break;
|
|
205
202
|
}
|
|
206
203
|
}
|
|
207
204
|
}
|
|
208
205
|
|
|
209
|
-
|
|
210
|
-
if (this.ord[o1['name']] > this.ord[o2['name']])
|
|
211
|
-
return -1;
|
|
212
|
-
|
|
213
|
-
if (this.ord[o1['name']] < this.ord[o2['name']])
|
|
214
|
-
return 1;
|
|
215
|
-
|
|
216
|
-
return 0;
|
|
217
|
-
});
|
|
206
|
+
colData.sort((o1, o2) => this.ord[o2['name']] - this.ord[o1['name']]);
|
|
218
207
|
}
|
|
219
208
|
|
|
220
209
|
this.max = this.dataFrame!.filter.trueCount;
|
|
221
210
|
}
|
|
222
211
|
|
|
223
|
-
renderBarToCanvas(
|
|
224
|
-
g: CanvasRenderingContext2D,
|
|
225
|
-
cell: DG.GridCell,
|
|
226
|
-
x: number,
|
|
227
|
-
y: number,
|
|
228
|
-
w: number,
|
|
229
|
-
h: number,
|
|
230
|
-
): void {
|
|
212
|
+
renderBarToCanvas(g: CanvasRenderingContext2D, cell: DG.GridCell, x: number, y: number, w: number, h: number) {
|
|
231
213
|
const name = cell.tableColumn!.name;
|
|
232
214
|
const colNameSize = g.measureText(name).width;
|
|
233
215
|
const barData = this.barStats[name];
|
|
@@ -254,7 +236,7 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
254
236
|
const sBarHeight = h * obj['count'] / this.max;
|
|
255
237
|
const gapSize = sBarHeight * innerMargin;
|
|
256
238
|
const verticalShift = (this.max - sum) / this.max;
|
|
257
|
-
const [color, aarOuter
|
|
239
|
+
const [color, aarOuter] = PeptidesController.chemPalette.getColorAAPivot(obj['name']);
|
|
258
240
|
const textSize = g.measureText(aarOuter);
|
|
259
241
|
const fontSize = 11;
|
|
260
242
|
const leftMargin = (w - (aarOuter.length > 1 ? fontSize : textSize.width - 8)) / 2;
|
|
@@ -270,11 +252,10 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
270
252
|
if (textSize.width <= subBartHeight) {
|
|
271
253
|
const origTransform = g.getTransform();
|
|
272
254
|
|
|
273
|
-
if (color !=
|
|
255
|
+
if (color != PeptidesController.chemPalette.undefinedColor) {
|
|
274
256
|
g.fillRect(x + xStart, y + yStart, barWidth, subBartHeight);
|
|
275
257
|
g.fillStyle = 'black';
|
|
276
|
-
}
|
|
277
|
-
else
|
|
258
|
+
} else
|
|
278
259
|
g.strokeRect(x + xStart + 0.5, y + yStart, barWidth - 1, subBartHeight);
|
|
279
260
|
|
|
280
261
|
g.font = `${fontSize}px monospace`;
|
|
@@ -289,9 +270,8 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
289
270
|
|
|
290
271
|
g.fillText(aarOuter, absX, absY);
|
|
291
272
|
g.setTransform(origTransform);
|
|
292
|
-
} else
|
|
273
|
+
} else
|
|
293
274
|
g.fillRect(x + xStart, y + yStart, barWidth, subBartHeight);
|
|
294
|
-
}
|
|
295
275
|
|
|
296
276
|
if (obj['selectedCount'] > eps) {
|
|
297
277
|
g.fillStyle = 'rgb(255,165,0)';
|
|
@@ -299,29 +279,20 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
299
279
|
x + xStart - w * selectLineRatio * 2,
|
|
300
280
|
y + yStart,
|
|
301
281
|
barWidth * selectLineRatio,
|
|
302
|
-
h * obj['selectedCount'] / this.max - gapSize
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
if (obj['highlightedCount'] > eps && obj['highlightedCount'] > obj['selectedCount']) {
|
|
307
|
-
g.fillStyle = 'rgb(209,242,251)';
|
|
308
|
-
g.fillRect(
|
|
309
|
-
x + xStart - w * selectLineRatio * 2,
|
|
310
|
-
y + yStart + h * obj['selectedCount'] / this.max - gapSize,
|
|
311
|
-
barWidth * selectLineRatio,
|
|
312
|
-
h * (obj['highlightedCount'] - obj['selectedCount']) / this.max - gapSize
|
|
282
|
+
h * obj['selectedCount'] / this.max - gapSize,
|
|
313
283
|
);
|
|
314
284
|
}
|
|
315
285
|
|
|
316
286
|
sum -= obj['count'];
|
|
317
287
|
});
|
|
318
|
-
return;
|
|
319
288
|
}
|
|
320
289
|
|
|
321
|
-
|
|
290
|
+
findAARandPosition(cell: DG.GridCell, mouseEvent: MouseEvent) {
|
|
322
291
|
if (!cell.tableColumn?.name || !this.aminoColumnNames.includes(cell.tableColumn.name))
|
|
323
|
-
return;
|
|
324
|
-
|
|
292
|
+
return null;
|
|
293
|
+
|
|
294
|
+
const offsetX = mouseEvent.offsetX;
|
|
295
|
+
const offsetY = mouseEvent.offsetY;
|
|
325
296
|
const colName = cell.tableColumn?.name;
|
|
326
297
|
const innerMargin = 0.02;
|
|
327
298
|
const margin = 0.2;
|
|
@@ -339,71 +310,53 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
339
310
|
sum += obj['count'];
|
|
340
311
|
});
|
|
341
312
|
|
|
342
|
-
|
|
343
|
-
|
|
313
|
+
const xStart = x + (w - barWidth) / 2;
|
|
314
|
+
for (const obj of barData) {
|
|
344
315
|
const sBarHeight = h * obj['count'] / this.max;
|
|
345
316
|
const gapSize = sBarHeight * innerMargin;
|
|
346
317
|
const verticalShift = (this.max - sum) / this.max;
|
|
347
318
|
const subBartHeight = sBarHeight - gapSize;
|
|
348
|
-
const yStart = h * verticalShift + gapSize / 2;
|
|
349
|
-
const xStart = (w - barWidth) / 2;
|
|
350
|
-
|
|
351
|
-
if (offsetX >= x + xStart &&
|
|
352
|
-
offsetY >= y + yStart &&
|
|
353
|
-
offsetX <= x + xStart + barWidth &&
|
|
354
|
-
offsetY <= y + yStart + subBartHeight) {
|
|
355
|
-
this.highlighted = {'colName': colName, 'aaName': obj['name']};
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
sum -= obj['count'];
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
if (!this.highlighted)
|
|
362
|
-
return;
|
|
319
|
+
const yStart = y + h * verticalShift + gapSize / 2;
|
|
363
320
|
|
|
364
|
-
|
|
365
|
-
|
|
321
|
+
const isIntersectingX = offsetX >= xStart && offsetX <= xStart + barWidth;
|
|
322
|
+
const isIntersectingY = offsetY >= yStart && offsetY <= yStart + subBartHeight;
|
|
366
323
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
idx = i;
|
|
324
|
+
if (isIntersectingX && isIntersectingY)
|
|
325
|
+
return {'colName': colName, 'aaName': obj['name']};
|
|
370
326
|
|
|
371
|
-
|
|
372
|
-
|
|
327
|
+
sum -= obj['count'];
|
|
328
|
+
}
|
|
373
329
|
|
|
374
|
-
|
|
375
|
-
this.selected.splice(idx, 1);
|
|
376
|
-
}
|
|
330
|
+
return null;
|
|
377
331
|
}
|
|
378
332
|
|
|
379
|
-
unhighlight()
|
|
380
|
-
|
|
381
|
-
this.highlightedMask!.setAll(false);
|
|
333
|
+
unhighlight() {
|
|
334
|
+
ui.tooltip.hide();
|
|
382
335
|
this.computeData();
|
|
383
336
|
}
|
|
384
337
|
|
|
385
|
-
|
|
386
|
-
|
|
338
|
+
/**
|
|
339
|
+
* Requests highlight/select/filter action based on currentBarPart
|
|
340
|
+
* @param event
|
|
341
|
+
* @returns
|
|
342
|
+
*/
|
|
343
|
+
requestAction(event: MouseEvent) {
|
|
344
|
+
if (!this._currentBarPart)
|
|
387
345
|
return;
|
|
388
|
-
|
|
389
|
-
this.
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
return false;
|
|
404
|
-
}, event);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
this.computeData();
|
|
346
|
+
let aar = this._currentBarPart!['aaName'];
|
|
347
|
+
let position = this._currentBarPart!['colName'];
|
|
348
|
+
if (event.type === 'click') {
|
|
349
|
+
if (this.isSameBarClicked) {
|
|
350
|
+
aar = position = C.CATEGORIES.ALL;
|
|
351
|
+
this.currentBarPart = null;
|
|
352
|
+
}
|
|
353
|
+
this.controller.setSARGridCellAt(aar, position);
|
|
354
|
+
this._previousClickedBarPart = this._currentBarPart;
|
|
355
|
+
} else {
|
|
356
|
+
ui.tooltip.showRowGroup(this.dataFrame, (i) => {
|
|
357
|
+
const currentAAR = this.dataFrame.get(position, i);
|
|
358
|
+
return currentAAR === aar;
|
|
359
|
+
}, event.offsetX, event.offsetY);
|
|
360
|
+
}
|
|
408
361
|
}
|
|
409
362
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import * as grok from 'datagrok-api/grok';
|
|
2
2
|
import * as ui from 'datagrok-api/ui';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
|
+
import {callMVA} from '../utils/multivariate-analysis';
|
|
4
5
|
import {PeptidesController} from '../peptides';
|
|
5
6
|
import '../styles.css';
|
|
6
7
|
import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
|
|
8
|
+
import * as C from '../utils/constants';
|
|
9
|
+
import {FilteringStatistics} from '../utils/filtering-statistics';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Peptide analysis widget.
|
|
@@ -15,9 +18,7 @@ import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations'
|
|
|
15
18
|
* @param {DG.DataFrame} currentDf Working table.
|
|
16
19
|
* @return {Promise<DG.Widget>} Widget containing peptide analysis.
|
|
17
20
|
*/
|
|
18
|
-
export async function analyzePeptidesWidget(
|
|
19
|
-
col: DG.Column, view: DG.TableView, tableGrid: DG.Grid, currentDf: DG.DataFrame,
|
|
20
|
-
): Promise<DG.Widget> {
|
|
21
|
+
export async function analyzePeptidesWidget(currentDf: DG.DataFrame, col: DG.Column): Promise<DG.Widget> {
|
|
21
22
|
let tempCol = null;
|
|
22
23
|
let tempDf: DG.DataFrame;
|
|
23
24
|
let newScaledColName: string;
|
|
@@ -32,13 +33,14 @@ export async function analyzePeptidesWidget(
|
|
|
32
33
|
'Scaling', 'none', ['none', 'lg', '-lg'],
|
|
33
34
|
async (currentMethod: string) => {
|
|
34
35
|
const currentActivityCol = activityColumnChoice.value.name;
|
|
36
|
+
|
|
35
37
|
|
|
36
38
|
[tempDf, newScaledColName] = await PeptidesController.scaleActivity(
|
|
37
|
-
currentMethod,
|
|
39
|
+
currentMethod, currentDf, currentActivityCol, true);
|
|
38
40
|
|
|
39
41
|
const hist = tempDf.plot.histogram({
|
|
40
42
|
filteringEnabled: false,
|
|
41
|
-
valueColumnName:
|
|
43
|
+
valueColumnName: C.COLUMNS_NAMES.ACTIVITY_SCALED,
|
|
42
44
|
legendVisibility: 'Never',
|
|
43
45
|
showXAxis: true,
|
|
44
46
|
showColumnSelector: false,
|
|
@@ -68,30 +70,49 @@ export async function analyzePeptidesWidget(
|
|
|
68
70
|
const startBtn = ui.button('Launch SAR', async () => {
|
|
69
71
|
const progress = DG.TaskBarProgressIndicator.create('Loading SAR...');
|
|
70
72
|
if (activityColumnChoice.value.type === DG.TYPE.FLOAT) {
|
|
71
|
-
const activityColumn = activityColumnChoice.value.name;
|
|
72
|
-
const activityColumnScaled = `${activityColumn}Scaled`;
|
|
73
|
-
const originalDfColumns = (currentDf.columns as DG.ColumnList).names();
|
|
73
|
+
const activityColumn: string = activityColumnChoice.value.name;
|
|
74
|
+
// const activityColumnScaled = `${activityColumn}Scaled`;
|
|
75
|
+
// const originalDfColumns = (currentDf.columns as DG.ColumnList).names();
|
|
74
76
|
const options: StringDictionary = {
|
|
75
|
-
'activityColumnName': activityColumn,
|
|
76
77
|
'scaling': activityScalingMethod.value,
|
|
77
78
|
};
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
(currentDf.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
//prepare new DF
|
|
81
|
+
const newDf = currentDf.clone(currentDf.filter, [col.name, activityColumn]);
|
|
82
|
+
newDf.getCol(activityColumn).name = C.COLUMNS_NAMES.ACTIVITY;
|
|
83
|
+
newDf.getCol(col.name).name = C.COLUMNS_NAMES.ALIGNED_SEQUENCE;
|
|
84
|
+
const activityScaledCol = tempDf.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
85
|
+
(newDf.columns as DG.ColumnList).add(activityScaledCol);
|
|
86
|
+
// newDf.temp[C.COLUMNS_NAMES.ACTIVITY] = activityColumn;
|
|
87
|
+
newDf.name = 'Peptides analysis';
|
|
88
|
+
newDf.temp[C.COLUMNS_NAMES.ACTIVITY_SCALED] = newScaledColName;
|
|
89
|
+
newDf.tags['isPeptidesAnalysis'] = 'true';
|
|
86
90
|
|
|
87
|
-
const peptides = PeptidesController.getInstance(
|
|
88
|
-
await peptides.init(
|
|
91
|
+
const peptides = await PeptidesController.getInstance(newDf);
|
|
92
|
+
await peptides.init(newDf);
|
|
89
93
|
} else
|
|
90
94
|
grok.shell.error('The activity column must be of floating point number type!');
|
|
91
95
|
progress.close();
|
|
92
96
|
});
|
|
93
97
|
startBtn.style.alignSelf = 'center';
|
|
94
98
|
|
|
99
|
+
// const startMVABtn = ui.button('Launch MVA', async () => {
|
|
100
|
+
// if (activityColumnChoice.value.type === DG.TYPE.FLOAT) {
|
|
101
|
+
// const progress = DG.TaskBarProgressIndicator.create('Loading MVA...');
|
|
102
|
+
|
|
103
|
+
// const options: {[key: string]: string} = {
|
|
104
|
+
// 'activityColumnName': activityColumnChoice.value.name,
|
|
105
|
+
// 'scaling': activityScalingMethod.value,
|
|
106
|
+
// };
|
|
107
|
+
|
|
108
|
+
// await callMVA(tableGrid, view, currentDf, options, col);
|
|
109
|
+
|
|
110
|
+
// progress.close();
|
|
111
|
+
// } else
|
|
112
|
+
// grok.shell.error('The activity column must be of floating point number type!');
|
|
113
|
+
// });
|
|
114
|
+
|
|
115
|
+
|
|
95
116
|
const viewer = await currentDf.plot.fromType('peptide-logo-viewer');
|
|
96
117
|
|
|
97
118
|
return new DG.Widget(
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as ui from 'datagrok-api/ui';
|
|
2
|
+
import * as DG from 'datagrok-api/dg';
|
|
3
|
+
|
|
4
|
+
import * as C from '../utils/constants';
|
|
5
|
+
import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
|
|
6
|
+
import {FilteringStatistics} from '../utils/filtering-statistics';
|
|
7
|
+
|
|
8
|
+
export function getDistributionPlot(df: DG.DataFrame, valueCol: string, splitCol: string) {
|
|
9
|
+
return df.plot.histogram({
|
|
10
|
+
// const hist = originalDf.plot.histogram({
|
|
11
|
+
filteringEnabled: false,
|
|
12
|
+
valueColumnName: valueCol,
|
|
13
|
+
splitColumnName: splitCol,
|
|
14
|
+
legendVisibility: 'Never',
|
|
15
|
+
showXAxis: true,
|
|
16
|
+
showColumnSelector: false,
|
|
17
|
+
showRangeSlider: false,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getDistributionWidget(table: DG.DataFrame): DG.Widget {
|
|
22
|
+
// const labelStr = this.multipleFilter.filterLabel;
|
|
23
|
+
const splitCol = table.col(C.COLUMNS_NAMES.SPLIT_COL);
|
|
24
|
+
if (!splitCol)
|
|
25
|
+
return new DG.Widget(ui.divText('No distribution'));
|
|
26
|
+
let [aarStr, otherStr] = splitCol.categories;
|
|
27
|
+
if (typeof otherStr === 'undefined')
|
|
28
|
+
[aarStr, otherStr] = [otherStr, aarStr];
|
|
29
|
+
// const currentColor = DG.Color.toHtml(DG.Color.orange);
|
|
30
|
+
// const otherColor = DG.Color.toHtml(DG.Color.blue);
|
|
31
|
+
const currentColor = DG.Color.toHtml(DG.Color.getCategoryColor(splitCol, aarStr));
|
|
32
|
+
const otherColor = DG.Color.toHtml(DG.Color.getCategoryColor(splitCol, otherStr));
|
|
33
|
+
|
|
34
|
+
const currentLabel = ui.label(aarStr, {style: {color: currentColor}});
|
|
35
|
+
const otherLabel = ui.label(otherStr, {style: {color: otherColor}});
|
|
36
|
+
const elements: (HTMLLabelElement | HTMLElement)[] = [currentLabel, otherLabel];
|
|
37
|
+
|
|
38
|
+
const getContent = () => {
|
|
39
|
+
// const processedDf =
|
|
40
|
+
// table.clone(null, [C.COLUMNS_NAMES.ACTIVITY_SCALED, C.COLUMNS_NAMES.SPLIT_COL]);
|
|
41
|
+
const hist = getDistributionPlot(table, C.COLUMNS_NAMES.ACTIVITY_SCALED, C.COLUMNS_NAMES.SPLIT_COL).root;
|
|
42
|
+
|
|
43
|
+
hist.style.width = 'auto';
|
|
44
|
+
elements.push(hist);
|
|
45
|
+
|
|
46
|
+
const stats = (table.temp[C.STATS] as FilteringStatistics).result;
|
|
47
|
+
if (stats) {
|
|
48
|
+
const tableMap: StringDictionary = {
|
|
49
|
+
'Statistics:': '',
|
|
50
|
+
'Count': stats.count.toString(),
|
|
51
|
+
'p-value': stats.pValue < 0.01 ? '<0.01' : stats.pValue.toFixed(2),
|
|
52
|
+
'Mean difference': stats.meanDifference.toFixed(2),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
elements.push(ui.tableFromMap(tableMap));
|
|
56
|
+
}
|
|
57
|
+
return ui.divV(elements);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return new DG.Widget(getContent());
|
|
61
|
+
}
|
|
@@ -33,9 +33,9 @@ export function manualAlignmentWidget(alignedSequenceCol: DG.Column, currentDf:
|
|
|
33
33
|
grok.shell.o = null;
|
|
34
34
|
grok.shell.o = temp;
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
const peptidesController = await PeptidesController.getInstance(currentDf);
|
|
37
|
+
peptidesController.init(currentDf);
|
|
38
|
+
peptidesController.updateDefault();
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
const resetBtn = ui.button(
|
|
@@ -44,16 +44,16 @@ export async function peptideMoleculeWidget(pep: string): Promise<DG.Widget> {
|
|
|
44
44
|
export function getMolecule(pep: string): string {
|
|
45
45
|
const split = pep.split('-');
|
|
46
46
|
const mols = [];
|
|
47
|
-
const chemPalette = PeptidesController.
|
|
47
|
+
const chemPalette = PeptidesController.chemPalette;
|
|
48
48
|
for (let i = 1; i < split.length - 1; i++) {
|
|
49
49
|
if (split[i] in chemPalette.AASmiles) {
|
|
50
50
|
const aar = chemPalette.AASmiles[split[i]];
|
|
51
|
-
mols[i] = aar.
|
|
51
|
+
mols[i] = aar.substring(0, aar.length - 1);
|
|
52
52
|
} else if (!split[i] || split[i] == '-')
|
|
53
53
|
mols[i] = '';
|
|
54
54
|
else
|
|
55
55
|
return '';
|
|
56
56
|
}
|
|
57
|
-
|
|
58
|
-
return
|
|
57
|
+
|
|
58
|
+
return mols.join('') + 'O';
|
|
59
59
|
}
|