@datagrok/peptides 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/detectors.js +1 -1
- package/package.json +11 -8
- package/src/describe.ts +184 -83
- package/src/{viewers/model.ts → model.ts} +1 -1
- package/src/package.ts +0 -14
- package/src/peptides.ts +27 -37
- package/src/styles.css +9 -0
- package/src/utils/peptide-similarity-space.ts +7 -33
- package/src/viewers/sar-viewer.ts +191 -180
- package/src/viewers/stacked-barchart-viewer.ts +0 -69
- package/src/widgets/analyze-peptides.ts +12 -2
- package/src/widgets/manual-alignment.ts +3 -2
- package/src/workers/dimensionality-reducer.ts +2 -2
- package/webpack.config.js +1 -1
- package/src/utils/correlation-analysis.ts +0 -204
- package/src/viewers/spiral-plot.ts +0 -97
package/detectors.js
CHANGED
|
@@ -3,7 +3,7 @@ class PeptidesPackageDetectors extends DG.Package {
|
|
|
3
3
|
//input: column col
|
|
4
4
|
//output: string semType
|
|
5
5
|
detectAligned(col) {
|
|
6
|
-
const regexp = new RegExp(/^([
|
|
6
|
+
const regexp = new RegExp(/^([^\-\n]*-){7,49}(\w|\(|\))+$/);
|
|
7
7
|
return DG.Detector.sampleCategories(col, (s) => regexp.test(s.trim())) ? 'alignedSequence' : null;
|
|
8
8
|
}
|
|
9
9
|
}
|
package/package.json
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/peptides",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@keckelt/tsne": "^1.0.2",
|
|
7
6
|
"cash-dom": "latest",
|
|
8
7
|
"d3": "latest",
|
|
9
8
|
"datagrok-api": ">=0.104.0",
|
|
10
9
|
"dayjs": "latest",
|
|
11
|
-
"jaro-winkler-typescript": "^1.0.1",
|
|
12
10
|
"jstat": "^1.9.5",
|
|
13
11
|
"logojs-react": "^2.1.1",
|
|
14
12
|
"rxjs": "^6.5.5",
|
|
15
|
-
"umap-js": "^1.3.3",
|
|
16
13
|
"@datagrok-libraries/utils": ">=0.0.13",
|
|
17
14
|
"@datagrok-libraries/statistics": ">=0.1.5",
|
|
15
|
+
"@datagrok-libraries/ml": ">=0.0.1",
|
|
16
|
+
"@datagrok-libraries/bio": ">=0.0.4",
|
|
18
17
|
"@types/d3": "^7.0.0",
|
|
19
18
|
"@types/jquery": "^3.5.6"
|
|
20
19
|
},
|
|
@@ -36,10 +35,12 @@
|
|
|
36
35
|
"common/ngl_viewer/ngl.js"
|
|
37
36
|
],
|
|
38
37
|
"scripts": {
|
|
38
|
+
"link-api": "npm link datagrok-api",
|
|
39
39
|
"link-utils": "npm link @datagrok-libraries/utils",
|
|
40
40
|
"link-statistics": "npm link @datagrok-libraries/statistics",
|
|
41
|
-
"link-
|
|
42
|
-
"link-
|
|
41
|
+
"link-ml": "npm link @datagrok-libraries/ml",
|
|
42
|
+
"link-bio": "npm link @datagrok-libraries/bio",
|
|
43
|
+
"link-all": "npm link datagrok-api @datagrok-libraries/utils @datagrok-libraries/statistics link @datagrok-libraries/ml @datagrok-libraries/bio",
|
|
43
44
|
"install-dependencies": "npm install",
|
|
44
45
|
"debug-peptides": "grok publish --rebuild",
|
|
45
46
|
"release-peptides": "grok publish --rebuild --release",
|
|
@@ -53,5 +54,7 @@
|
|
|
53
54
|
"release-peptides-local": "grok publish local --rebuild --release",
|
|
54
55
|
"lint": "eslint \"./src/**/*.ts\"",
|
|
55
56
|
"lint-fix": "eslint \"./src/**/*.ts\" --fix"
|
|
56
|
-
}
|
|
57
|
-
|
|
57
|
+
},
|
|
58
|
+
"canEdit": [ "Developers" ],
|
|
59
|
+
"canView": [ "All users" ]
|
|
60
|
+
}
|
package/src/describe.ts
CHANGED
|
@@ -53,29 +53,13 @@ const groupDescription: {[key: string]: {'description': string, 'aminoAcids': st
|
|
|
53
53
|
}
|
|
54
54
|
}*/
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
function joinDataFrames(
|
|
57
|
+
activityColumnScaled: string,
|
|
58
58
|
df: DG.DataFrame,
|
|
59
|
+
positionColumns: string[],
|
|
60
|
+
splitSeqDf: DG.DataFrame,
|
|
59
61
|
activityColumn: string,
|
|
60
|
-
|
|
61
|
-
sourceGrid: DG.Grid,
|
|
62
|
-
twoColorMode: boolean,
|
|
63
|
-
initialBitset: DG.BitSet | null,
|
|
64
|
-
grouping: boolean,
|
|
65
|
-
): Promise<[DG.Grid, DG.Grid, DG.DataFrame, {[key: string]: string}]> {
|
|
66
|
-
//Split the aligned sequence into separate AARs
|
|
67
|
-
let splitSeqDf: DG.DataFrame | undefined;
|
|
68
|
-
let invalidIndexes: number[];
|
|
69
|
-
const col: DG.Column = df.columns.bySemType('alignedSequence');
|
|
70
|
-
[splitSeqDf, invalidIndexes] = splitAlignedPeptides(col);
|
|
71
|
-
splitSeqDf.name = 'Split sequence';
|
|
72
|
-
|
|
73
|
-
const positionColumns = splitSeqDf.columns.names();
|
|
74
|
-
const activityColumnScaled = `${activityColumn}Scaled`;
|
|
75
|
-
const renderColNames: string[] = splitSeqDf.columns.names();
|
|
76
|
-
|
|
77
|
-
splitSeqDf.columns.add(df.getCol(activityColumn));
|
|
78
|
-
|
|
62
|
+
) {
|
|
79
63
|
if (df.col(activityColumnScaled)) {
|
|
80
64
|
df.columns.remove(activityColumnScaled);
|
|
81
65
|
}
|
|
@@ -90,13 +74,9 @@ export async function describe(
|
|
|
90
74
|
if (!positionColumns.every((col: string) => dfColsSet.has(col))) {
|
|
91
75
|
df.join(splitSeqDf, [activityColumn], [activityColumn], df.columns.names(), positionColumns, 'inner', true);
|
|
92
76
|
}
|
|
77
|
+
}
|
|
93
78
|
|
|
94
|
-
|
|
95
|
-
if (splitSeqDf.col(col.name) && col.name != activityColumn) {
|
|
96
|
-
setAARRenderer(col, sourceGrid);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
79
|
+
function sortSourceGrid(sourceGrid: DG.Grid) {
|
|
100
80
|
if (sourceGrid) {
|
|
101
81
|
const colNames:string[] = [];
|
|
102
82
|
for (let i = 0; i < sourceGrid.columns.length; i++) {
|
|
@@ -116,8 +96,16 @@ export async function describe(
|
|
|
116
96
|
});
|
|
117
97
|
sourceGrid?.columns.setOrder(colNames);
|
|
118
98
|
}
|
|
99
|
+
}
|
|
119
100
|
|
|
120
|
-
|
|
101
|
+
async function scaleActivity(
|
|
102
|
+
activityScaling: string,
|
|
103
|
+
activityColumn: string,
|
|
104
|
+
activityColumnScaled: string,
|
|
105
|
+
sourceGrid: DG.Grid,
|
|
106
|
+
splitSeqDf: DG.DataFrame,
|
|
107
|
+
) {
|
|
108
|
+
const df = sourceGrid.dataFrame!;
|
|
121
109
|
switch (activityScaling) {
|
|
122
110
|
case 'lg':
|
|
123
111
|
await df.columns.addNewCalculated(activityColumnScaled, 'Log10(${' + activityColumn + '})');
|
|
@@ -138,32 +126,17 @@ export async function describe(
|
|
|
138
126
|
sourceGrid.columns.setOrder([`${activityColumn}`]);
|
|
139
127
|
break;
|
|
140
128
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const positionColName = 'Position';
|
|
144
|
-
const aminoAcidResidue = 'AAR';
|
|
145
|
-
|
|
146
|
-
//unpivot a table and handle duplicates
|
|
147
|
-
splitSeqDf = splitSeqDf.groupBy(positionColumns)
|
|
148
|
-
.add('med', activityColumnScaled, activityColumnScaled)
|
|
149
|
-
.aggregate();
|
|
150
|
-
|
|
151
|
-
const peptidesCount = splitSeqDf.getCol(activityColumnScaled).length;
|
|
152
|
-
|
|
153
|
-
let matrixDf = splitSeqDf.unpivot([activityColumnScaled], positionColumns, positionColName, aminoAcidResidue);
|
|
154
|
-
|
|
155
|
-
//TODO: move to chem palette
|
|
156
|
-
let groupMapping: {[key: string]: string} = {};
|
|
157
|
-
if (grouping) {
|
|
158
|
-
groupMapping = aarGroups;
|
|
159
|
-
const aarCol = matrixDf.getCol(aminoAcidResidue);
|
|
160
|
-
aarCol.init((index) => groupMapping[aarCol.get(index)[0]] ?? '-');
|
|
161
|
-
aarCol.compact();
|
|
162
|
-
} else {
|
|
163
|
-
Object.keys(aarGroups).forEach((value) => groupMapping[value] = value);
|
|
164
|
-
}
|
|
129
|
+
}
|
|
165
130
|
|
|
166
|
-
|
|
131
|
+
async function calculateStatistics(
|
|
132
|
+
matrixDf: DG.DataFrame,
|
|
133
|
+
positionColName: string,
|
|
134
|
+
aminoAcidResidue: string,
|
|
135
|
+
activityColumnScaled: string,
|
|
136
|
+
peptidesCount: number,
|
|
137
|
+
splitSeqDf: DG.DataFrame,
|
|
138
|
+
groupMapping: {[key: string]: string},
|
|
139
|
+
) {
|
|
167
140
|
matrixDf = matrixDf.groupBy([positionColName, aminoAcidResidue])
|
|
168
141
|
.add('count', activityColumnScaled, 'Count')
|
|
169
142
|
.aggregate();
|
|
@@ -177,39 +150,31 @@ export async function describe(
|
|
|
177
150
|
await matrixDf.columns.addNewCalculated('Ratio', '${count}/'.concat(`${peptidesCount}`));
|
|
178
151
|
|
|
179
152
|
//calculate p-values based on t-test
|
|
180
|
-
let position: string;
|
|
181
|
-
let aar: string;
|
|
182
|
-
let currentActivity: number[];
|
|
183
|
-
let otherActivity: number[];
|
|
184
|
-
let testResult;
|
|
185
|
-
let currentMeanDiff: number;
|
|
186
153
|
let pvalues: Float32Array = new Float32Array(matrixDf.rowCount).fill(1);
|
|
187
|
-
let pvalue = 1.;
|
|
188
|
-
|
|
189
154
|
const mdCol: DG.Column = matrixDf.columns.addNewFloat('Mean difference');
|
|
190
155
|
const pValCol: DG.Column = matrixDf.columns.addNewFloat('pValue');
|
|
191
156
|
for (let i = 0; i < matrixDf.rowCount; i++) {
|
|
192
|
-
position = matrixDf.get(positionColName, i);
|
|
193
|
-
aar = matrixDf.get(aminoAcidResidue, i);
|
|
157
|
+
const position = matrixDf.get(positionColName, i);
|
|
158
|
+
const aar = matrixDf.get(aminoAcidResidue, i);
|
|
194
159
|
|
|
195
160
|
//@ts-ignore
|
|
196
161
|
splitSeqDf.rows.select((row) => groupMapping[row[position]] === aar);
|
|
197
|
-
currentActivity = splitSeqDf
|
|
162
|
+
const currentActivity: number[] = splitSeqDf
|
|
198
163
|
.clone(splitSeqDf.selection, [activityColumnScaled])
|
|
199
164
|
.getCol(activityColumnScaled)
|
|
200
165
|
.toList();
|
|
201
166
|
|
|
202
167
|
//@ts-ignore
|
|
203
168
|
splitSeqDf.rows.select((row) => groupMapping[row[position]] !== aar);
|
|
204
|
-
otherActivity = splitSeqDf
|
|
169
|
+
const otherActivity: number[] = splitSeqDf
|
|
205
170
|
.clone(splitSeqDf.selection, [activityColumnScaled])
|
|
206
171
|
.getCol(activityColumnScaled)
|
|
207
172
|
.toList();
|
|
208
173
|
|
|
209
|
-
testResult = tTest(currentActivity, otherActivity);
|
|
174
|
+
const testResult = tTest(currentActivity, otherActivity);
|
|
210
175
|
// testResult = uTest(currentActivity, otherActivity);
|
|
211
|
-
currentMeanDiff = testResult['Mean difference']!;
|
|
212
|
-
pvalue = testResult[currentMeanDiff >= 0 ? 'p-value more' : 'p-value less'];
|
|
176
|
+
const currentMeanDiff = testResult['Mean difference']!;
|
|
177
|
+
const pvalue = testResult[currentMeanDiff >= 0 ? 'p-value more' : 'p-value less'];
|
|
213
178
|
|
|
214
179
|
mdCol.set(i, currentMeanDiff);
|
|
215
180
|
pvalues[i] = pvalue;
|
|
@@ -223,17 +188,12 @@ export async function describe(
|
|
|
223
188
|
pValCol.set(i, pvalues[i]);
|
|
224
189
|
}
|
|
225
190
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
// SAR matrix table
|
|
229
|
-
//pivot a table to make it matrix-like
|
|
230
|
-
matrixDf = matrixDf.groupBy([aminoAcidResidue])
|
|
231
|
-
.pivot(positionColName)
|
|
232
|
-
.add('first', 'Mean difference', '')
|
|
233
|
-
.aggregate();
|
|
234
|
-
matrixDf.name = 'SAR';
|
|
191
|
+
return matrixDf.clone();
|
|
192
|
+
}
|
|
235
193
|
|
|
236
|
-
|
|
194
|
+
async function setCategoryOrder(
|
|
195
|
+
twoColorMode: boolean, statsDf: DG.DataFrame, aminoAcidResidue: string, matrixDf: DG.DataFrame,
|
|
196
|
+
) {
|
|
237
197
|
const sortArgument = twoColorMode ? 'Absolute Mean difference' : 'Mean difference';
|
|
238
198
|
if (twoColorMode) {
|
|
239
199
|
await statsDf.columns.addNewCalculated('Absolute Mean difference', 'Abs(${Mean difference})');
|
|
@@ -248,8 +208,14 @@ export async function describe(
|
|
|
248
208
|
aarList.sort((first, second) => getWeight(second) - getWeight(first));
|
|
249
209
|
|
|
250
210
|
matrixDf.getCol(aminoAcidResidue).setCategoryOrder(aarList);
|
|
211
|
+
}
|
|
251
212
|
|
|
252
|
-
|
|
213
|
+
function createVerticalTable(
|
|
214
|
+
statsDf: DG.DataFrame,
|
|
215
|
+
aminoAcidResidue: string,
|
|
216
|
+
positionColName: string,
|
|
217
|
+
twoColorMode: boolean,
|
|
218
|
+
) {
|
|
253
219
|
// TODO: aquire ALL of the positions
|
|
254
220
|
let sequenceDf = statsDf.groupBy(['Mean difference', aminoAcidResidue, positionColName, 'Count', 'Ratio', 'pValue'])
|
|
255
221
|
.where('pValue <= 0.1')
|
|
@@ -268,9 +234,18 @@ export async function describe(
|
|
|
268
234
|
sequenceDf = sequenceDf.clone(DG.BitSet.create(sequenceDf.rowCount, (i) => {
|
|
269
235
|
return sequenceDf.get('Mean difference', i) === maxAtPos[sequenceDf.get(positionColName, i)];
|
|
270
236
|
}));
|
|
271
|
-
renderColNames.push('Mean difference');
|
|
272
237
|
|
|
273
|
-
|
|
238
|
+
return sequenceDf;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function createGrids(
|
|
242
|
+
matrixDf: DG.DataFrame,
|
|
243
|
+
aminoAcidResidue: string,
|
|
244
|
+
positionColumns: string[],
|
|
245
|
+
sequenceDf: DG.DataFrame,
|
|
246
|
+
positionColName: string,
|
|
247
|
+
grouping: boolean,
|
|
248
|
+
) {
|
|
274
249
|
const sarGrid = matrixDf.plot.grid();
|
|
275
250
|
sarGrid.sort([aminoAcidResidue]);
|
|
276
251
|
sarGrid.columns.setOrder([aminoAcidResidue].concat(positionColumns));
|
|
@@ -291,7 +266,19 @@ export async function describe(
|
|
|
291
266
|
}
|
|
292
267
|
}
|
|
293
268
|
|
|
294
|
-
|
|
269
|
+
return [sarGrid, sarVGrid];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function setCellRendererFunc(
|
|
273
|
+
renderColNames: string[],
|
|
274
|
+
positionColName: string,
|
|
275
|
+
aminoAcidResidue: string,
|
|
276
|
+
statsDf: DG.DataFrame,
|
|
277
|
+
twoColorMode: boolean,
|
|
278
|
+
sarGrid: DG.Grid,
|
|
279
|
+
sarVGrid: DG.Grid,
|
|
280
|
+
) {
|
|
281
|
+
const mdCol = statsDf.getCol('Mean difference');
|
|
295
282
|
const cellRendererFunc = function(args: DG.GridCellRenderArgs) {
|
|
296
283
|
args.g.save();
|
|
297
284
|
args.g.beginPath();
|
|
@@ -360,8 +347,18 @@ export async function describe(
|
|
|
360
347
|
};
|
|
361
348
|
sarGrid.onCellRender.subscribe(cellRendererFunc);
|
|
362
349
|
sarVGrid.onCellRender.subscribe(cellRendererFunc);
|
|
350
|
+
}
|
|
363
351
|
|
|
364
|
-
|
|
352
|
+
function setTooltipFunc(
|
|
353
|
+
renderColNames: string[],
|
|
354
|
+
statsDf: DG.DataFrame,
|
|
355
|
+
aminoAcidResidue: string,
|
|
356
|
+
positionColName: string,
|
|
357
|
+
peptidesCount: number,
|
|
358
|
+
grouping: boolean,
|
|
359
|
+
sarGrid: DG.Grid,
|
|
360
|
+
sarVGrid: DG.Grid,
|
|
361
|
+
) {
|
|
365
362
|
const onCellTooltipFunc = function(cell: DG.GridCell, x: number, y: number) {
|
|
366
363
|
if (
|
|
367
364
|
!cell.isRowHeader &&
|
|
@@ -414,7 +411,17 @@ export async function describe(
|
|
|
414
411
|
};
|
|
415
412
|
sarGrid.onCellTooltip(onCellTooltipFunc);
|
|
416
413
|
sarVGrid.onCellTooltip(onCellTooltipFunc);
|
|
414
|
+
}
|
|
417
415
|
|
|
416
|
+
function postProcessGrids(
|
|
417
|
+
sourceGrid: DG.Grid,
|
|
418
|
+
invalidIndexes: number[],
|
|
419
|
+
matrixDf: DG.DataFrame,
|
|
420
|
+
grouping: boolean,
|
|
421
|
+
aminoAcidResidue: string,
|
|
422
|
+
sarGrid: DG.Grid,
|
|
423
|
+
sarVGrid: DG.Grid,
|
|
424
|
+
) {
|
|
418
425
|
sourceGrid.onCellPrepare((cell: DG.GridCell) => {
|
|
419
426
|
const currentRowIndex = cell.tableRowIndex;
|
|
420
427
|
if (currentRowIndex && invalidIndexes.includes(currentRowIndex) && !cell.isRowHeader) {
|
|
@@ -433,6 +440,100 @@ export async function describe(
|
|
|
433
440
|
|
|
434
441
|
sarGrid.props.allowEdit = false;
|
|
435
442
|
sarVGrid.props.allowEdit = false;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export async function describe(
|
|
446
|
+
df: DG.DataFrame,
|
|
447
|
+
activityColumn: string,
|
|
448
|
+
activityScaling: string,
|
|
449
|
+
sourceGrid: DG.Grid,
|
|
450
|
+
twoColorMode: boolean,
|
|
451
|
+
initialBitset: DG.BitSet | null,
|
|
452
|
+
grouping: boolean,
|
|
453
|
+
): Promise<[DG.Grid, DG.Grid, DG.DataFrame, {[key: string]: string}]> {
|
|
454
|
+
//Split the aligned sequence into separate AARs
|
|
455
|
+
let splitSeqDf: DG.DataFrame | undefined;
|
|
456
|
+
let invalidIndexes: number[];
|
|
457
|
+
const col: DG.Column = df.columns.bySemType('alignedSequence');
|
|
458
|
+
[splitSeqDf, invalidIndexes] = splitAlignedPeptides(col);
|
|
459
|
+
splitSeqDf.name = 'Split sequence';
|
|
460
|
+
|
|
461
|
+
const positionColumns = splitSeqDf.columns.names();
|
|
462
|
+
const activityColumnScaled = `${activityColumn}Scaled`;
|
|
463
|
+
const renderColNames: string[] = splitSeqDf.columns.names();
|
|
464
|
+
const positionColName = 'Position';
|
|
465
|
+
const aminoAcidResidue = 'AAR';
|
|
466
|
+
|
|
467
|
+
splitSeqDf.columns.add(df.getCol(activityColumn));
|
|
468
|
+
|
|
469
|
+
joinDataFrames(activityColumnScaled, df, positionColumns, splitSeqDf, activityColumn);
|
|
470
|
+
|
|
471
|
+
for (const col of df.columns) {
|
|
472
|
+
if (splitSeqDf.col(col.name) && col.name != activityColumn) {
|
|
473
|
+
setAARRenderer(col, sourceGrid);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
sortSourceGrid(sourceGrid);
|
|
478
|
+
|
|
479
|
+
await scaleActivity(activityScaling, activityColumn, activityColumnScaled, sourceGrid, splitSeqDf);
|
|
480
|
+
splitSeqDf = splitSeqDf.clone(initialBitset);
|
|
481
|
+
|
|
482
|
+
//unpivot a table and handle duplicates
|
|
483
|
+
splitSeqDf = splitSeqDf.groupBy(positionColumns)
|
|
484
|
+
.add('med', activityColumnScaled, activityColumnScaled)
|
|
485
|
+
.aggregate();
|
|
486
|
+
|
|
487
|
+
const peptidesCount = splitSeqDf.getCol(activityColumnScaled).length;
|
|
488
|
+
|
|
489
|
+
let matrixDf = splitSeqDf.unpivot([activityColumnScaled], positionColumns, positionColName, aminoAcidResidue);
|
|
490
|
+
|
|
491
|
+
//TODO: move to chem palette
|
|
492
|
+
let groupMapping: {[key: string]: string} = {};
|
|
493
|
+
if (grouping) {
|
|
494
|
+
groupMapping = aarGroups;
|
|
495
|
+
const aarCol = matrixDf.getCol(aminoAcidResidue);
|
|
496
|
+
aarCol.init((index) => groupMapping[aarCol.get(index)[0]] ?? '-');
|
|
497
|
+
aarCol.compact();
|
|
498
|
+
} else {
|
|
499
|
+
Object.keys(aarGroups).forEach((value) => groupMapping[value] = value);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
//statistics for specific AAR at a specific position
|
|
503
|
+
const statsDf = await calculateStatistics(
|
|
504
|
+
matrixDf, positionColName, aminoAcidResidue, activityColumnScaled, peptidesCount, splitSeqDf, groupMapping,
|
|
505
|
+
);
|
|
506
|
+
|
|
507
|
+
// SAR matrix table
|
|
508
|
+
//pivot a table to make it matrix-like
|
|
509
|
+
matrixDf = statsDf.groupBy([aminoAcidResidue])
|
|
510
|
+
.pivot(positionColName)
|
|
511
|
+
.add('first', 'Mean difference', '')
|
|
512
|
+
.aggregate();
|
|
513
|
+
matrixDf.name = 'SAR';
|
|
514
|
+
|
|
515
|
+
// Setting category order
|
|
516
|
+
await setCategoryOrder(twoColorMode, statsDf, aminoAcidResidue, matrixDf);
|
|
517
|
+
|
|
518
|
+
// SAR vertical table (naive, choose best Mean difference from pVals <= 0.01)
|
|
519
|
+
const sequenceDf = createVerticalTable(statsDf, aminoAcidResidue, positionColName, twoColorMode);
|
|
520
|
+
renderColNames.push('Mean difference');
|
|
521
|
+
|
|
522
|
+
const [sarGrid, sarVGrid] = createGrids(
|
|
523
|
+
matrixDf, aminoAcidResidue, positionColumns, sequenceDf, positionColName, grouping,
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
setCellRendererFunc(
|
|
527
|
+
renderColNames, positionColName, aminoAcidResidue, statsDf, twoColorMode, sarGrid, sarVGrid,
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
// show all the statistics in a tooltip over cell
|
|
531
|
+
setTooltipFunc(
|
|
532
|
+
renderColNames, statsDf, aminoAcidResidue, positionColName, peptidesCount, grouping, sarGrid, sarVGrid,
|
|
533
|
+
);
|
|
534
|
+
|
|
535
|
+
postProcessGrids(sourceGrid, invalidIndexes, matrixDf, grouping, aminoAcidResidue, sarGrid, sarVGrid);
|
|
436
536
|
|
|
537
|
+
//TODO: return class instead
|
|
437
538
|
return [sarGrid, sarVGrid, statsDf, groupMapping];
|
|
438
539
|
}
|
package/src/package.ts
CHANGED
|
@@ -15,7 +15,6 @@ import {PeptideSimilaritySpaceWidget} from './utils/peptide-similarity-space';
|
|
|
15
15
|
import {manualAlignmentWidget} from './widgets/manual-alignment';
|
|
16
16
|
import {SARViewer, SARViewerVertical} from './viewers/sar-viewer';
|
|
17
17
|
import {peptideMoleculeWidget} from './widgets/peptide-molecule';
|
|
18
|
-
import {SpiralPlot} from './viewers/spiral-plot';
|
|
19
18
|
import {SubstViewer} from './viewers/subst-viewer';
|
|
20
19
|
|
|
21
20
|
export const _package = new DG.Package();
|
|
@@ -182,16 +181,3 @@ export async function peptideSpacePanel(col: DG.Column): Promise<DG.Widget> {
|
|
|
182
181
|
const widget = new PeptideSimilaritySpaceWidget(col, view ?? grok.shell.v);
|
|
183
182
|
return await widget.draw();
|
|
184
183
|
}
|
|
185
|
-
|
|
186
|
-
//name: Spiral Plot
|
|
187
|
-
////input: dataframe table
|
|
188
|
-
////input: column activity
|
|
189
|
-
//tags: viewer, panel
|
|
190
|
-
//output: viewer result
|
|
191
|
-
export async function spiralPlot(): Promise<DG.Viewer> {//(table: DG.DataFrame, activity: DG.Column) {
|
|
192
|
-
// Read as dataframe
|
|
193
|
-
const table = await grok.data.files.openTable('Demo:TestJobs:Files:DemoFiles/bio/peptides.csv');
|
|
194
|
-
const activity = await table.columns.addNewCalculated('-log10(Activity)', '0-Log10(${Activity})');
|
|
195
|
-
view = grok.shell.addTableView(table);
|
|
196
|
-
return view.addViewer(SpiralPlot.fromTable(table, {valuesColumnName: activity.name}));
|
|
197
|
-
}
|
package/src/peptides.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as ui from 'datagrok-api/ui';
|
|
|
2
2
|
import * as DG from 'datagrok-api/dg';
|
|
3
3
|
import {createPeptideSimilaritySpaceViewer} from './utils/peptide-similarity-space';
|
|
4
4
|
import {addViewerToHeader} from './viewers/stacked-barchart-viewer';
|
|
5
|
+
import {model} from './model';
|
|
5
6
|
// import $ from 'cash-dom';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -11,6 +12,12 @@ import {addViewerToHeader} from './viewers/stacked-barchart-viewer';
|
|
|
11
12
|
* @class Peptides
|
|
12
13
|
*/
|
|
13
14
|
export class Peptides {
|
|
15
|
+
private static _model = model;
|
|
16
|
+
|
|
17
|
+
static async recalculate() {
|
|
18
|
+
await Peptides._model.updateDefault();
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
/**
|
|
15
22
|
* Class initializer
|
|
16
23
|
*
|
|
@@ -47,7 +54,10 @@ export class Peptides {
|
|
|
47
54
|
const substViewer = view.addViewer(
|
|
48
55
|
'substitution-analysis-viewer', {'activityColumnName': options['activityColumnName']},
|
|
49
56
|
);
|
|
50
|
-
view.dockManager.dock(substViewer, DG.DOCK_TYPE.RIGHT, null, 'Substitution Analysis');
|
|
57
|
+
const substNode = view.dockManager.dock(substViewer, DG.DOCK_TYPE.RIGHT, null, 'Substitution Analysis');
|
|
58
|
+
|
|
59
|
+
const layout1 = view.saveLayout();
|
|
60
|
+
view.dockManager.close(substNode);
|
|
51
61
|
|
|
52
62
|
const sarViewer = view.addViewer('peptide-sar-viewer', options);
|
|
53
63
|
const sarNode = view.dockManager.dock(sarViewer, DG.DOCK_TYPE.DOWN, null, 'SAR Viewer');
|
|
@@ -65,8 +75,8 @@ export class Peptides {
|
|
|
65
75
|
`${activityColumnChoice}Scaled`,
|
|
66
76
|
);
|
|
67
77
|
const psNode = view.dockManager.dock(peptideSpaceViewer, DG.DOCK_TYPE.LEFT, sarNode, 'Peptide Space Viewer', 0.3);
|
|
68
|
-
|
|
69
|
-
|
|
78
|
+
|
|
79
|
+
const layout2 = view.saveLayout();
|
|
70
80
|
|
|
71
81
|
const StackedBarchartProm = currentDf.plot.fromType('StackedBarChartAA');
|
|
72
82
|
addViewerToHeader(tableGrid, StackedBarchartProm);
|
|
@@ -99,42 +109,22 @@ export class Peptides {
|
|
|
99
109
|
view.setRibbonPanels(ribbonPanels);
|
|
100
110
|
}, 'Close viewers and restore dataframe');
|
|
101
111
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// $(switchViewers).removeClass('fa-toggle-off');
|
|
116
|
-
// $(switchViewers).addClass('fa-toggle-on');
|
|
117
|
-
// } else {
|
|
118
|
-
// viewLayout1 = view.saveLayout();
|
|
119
|
-
// // sarDockNodes.forEach((node) => view.dockManager.close(node));
|
|
120
|
-
// sarViewers.forEach((v) => v.close());
|
|
121
|
-
|
|
122
|
-
// if (viewLayout2 === null) {
|
|
123
|
-
// substViewer = view.addViewer(
|
|
124
|
-
// 'substitution-analysis-viewer', {'activityColumnName': options['activityColumnName']},
|
|
125
|
-
// );
|
|
126
|
-
// substNode = view.dockManager.dock(substViewer, DG.DOCK_TYPE.DOWN, null, 'Substitution Analysis');
|
|
127
|
-
// } else {
|
|
128
|
-
// view.loadLayout(viewLayout2);
|
|
129
|
-
// }
|
|
130
|
-
|
|
131
|
-
// $(switchViewers).removeClass('fa-toggle-on');
|
|
132
|
-
// $(switchViewers).addClass('fa-toggle-off');
|
|
133
|
-
// }
|
|
134
|
-
// isSA = !isSA;
|
|
135
|
-
// });
|
|
112
|
+
let isSA = false;
|
|
113
|
+
const switchViewers = ui.iconFA('toggle-on', () => {
|
|
114
|
+
if (isSA) {
|
|
115
|
+
view.loadLayout(layout1);
|
|
116
|
+
$(switchViewers).removeClass('fa-toggle-off');
|
|
117
|
+
$(switchViewers).addClass('fa-toggle-on');
|
|
118
|
+
} else {
|
|
119
|
+
view.loadLayout(layout2);
|
|
120
|
+
$(switchViewers).removeClass('fa-toggle-on');
|
|
121
|
+
$(switchViewers).addClass('fa-toggle-off');
|
|
122
|
+
}
|
|
123
|
+
isSA = !isSA;
|
|
124
|
+
});
|
|
136
125
|
|
|
137
126
|
const ribbonPanels = view.getRibbonPanels();
|
|
127
|
+
// view.setRibbonPanels([[hideIcon, switchViewers]]);
|
|
138
128
|
view.setRibbonPanels([[hideIcon]]);
|
|
139
129
|
}
|
|
140
130
|
}
|
package/src/styles.css
CHANGED
|
@@ -3,40 +3,14 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
5
|
import {getSequenceMolecularWeight} from './molecular-measure';
|
|
6
|
-
import {AlignedSequenceEncoder} from '@datagrok-libraries/
|
|
7
|
-
import {DimensionalityReducer} from '@datagrok-libraries/
|
|
8
|
-
import {
|
|
6
|
+
import {AlignedSequenceEncoder} from '@datagrok-libraries/bio/src/sequence-encoder';
|
|
7
|
+
import {DimensionalityReducer} from '@datagrok-libraries/ml/src/reduce-dimensionality';
|
|
8
|
+
import {
|
|
9
|
+
createDimensinalityReducingWorker,
|
|
10
|
+
} from '@datagrok-libraries/ml/src/workers/dimensionality-reducing-worker-creator';
|
|
11
|
+
import {StringMeasure} from '@datagrok-libraries/ml/src/string-measure';
|
|
9
12
|
import {Coordinates} from '@datagrok-libraries/utils/src/type-declarations';
|
|
10
13
|
|
|
11
|
-
/**
|
|
12
|
-
* A worker to perform dimensionality reduction.
|
|
13
|
-
*
|
|
14
|
-
* @param {any[]} columnData The data to process.
|
|
15
|
-
* @param {string} method A method of dimensionality reduction.
|
|
16
|
-
* @param {string} measure A distance metrics.
|
|
17
|
-
* @param {number} cyclesCount Number of iterations to run.
|
|
18
|
-
* @return {Promise<unknown>} Resulting embedding.
|
|
19
|
-
*/
|
|
20
|
-
function createDimensinalityReducingWorker(
|
|
21
|
-
columnData: any[],
|
|
22
|
-
method: string,
|
|
23
|
-
measure: string,
|
|
24
|
-
cyclesCount: number,
|
|
25
|
-
): Promise<unknown> {
|
|
26
|
-
return new Promise(function(resolve) {
|
|
27
|
-
const worker = new Worker(new URL('../workers/dimensionality-reducer.ts', import.meta.url));
|
|
28
|
-
worker.postMessage({
|
|
29
|
-
columnData: columnData,
|
|
30
|
-
method: method,
|
|
31
|
-
measure: measure,
|
|
32
|
-
cyclesCount: cyclesCount,
|
|
33
|
-
});
|
|
34
|
-
worker.onmessage = ({data: {embedding}}) => {
|
|
35
|
-
resolve(embedding);
|
|
36
|
-
};
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
14
|
/**
|
|
41
15
|
* Finds a column with an activity.
|
|
42
16
|
*
|
|
@@ -157,7 +131,7 @@ export class PeptideSimilaritySpaceWidget {
|
|
|
157
131
|
*/
|
|
158
132
|
constructor(alignedSequencesColumn: DG.Column, view: DG.TableView) {
|
|
159
133
|
this.availableMethods = DimensionalityReducer.availableMethods;
|
|
160
|
-
this.availableMetrics =
|
|
134
|
+
this.availableMetrics = StringMeasure.availableMeasures;
|
|
161
135
|
this.method = this.availableMethods[0];
|
|
162
136
|
this.metrics = this.availableMetrics[0];
|
|
163
137
|
this.currentDf = alignedSequencesColumn.dataFrame;
|