@datagrok/peptides 0.7.1 → 0.8.7
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 +12 -2
- package/files/aligned_2.csv +1 -1
- package/package.json +21 -15
- package/setup.sh +15 -0
- package/src/describe.ts +45 -49
- package/src/model.ts +2 -1
- package/src/monomer-library.ts +187 -0
- package/src/package-test.ts +19 -0
- package/src/package.ts +79 -7
- package/src/peptides.ts +62 -21
- package/src/semantics.ts +5 -0
- package/src/tests/msa-tests.ts +27 -0
- package/src/tests/peptide-space-test.ts +77 -0
- package/src/tests/peptides-tests.ts +121 -0
- package/src/tests/test-data.ts +649 -0
- package/src/tests/utils.ts +126 -0
- package/src/utils/cell-renderer.ts +129 -26
- package/src/utils/chem-palette.ts +16 -15
- package/src/utils/molecular-measure.ts +3 -4
- package/src/utils/multiple-sequence-alignment.ts +88 -0
- package/src/utils/peptide-similarity-space.ts +39 -13
- package/src/utils/split-aligned.ts +6 -6
- package/src/viewers/logo-viewer.ts +10 -12
- package/src/viewers/sar-viewer.ts +16 -17
- package/src/viewers/stacked-barchart-viewer.ts +21 -26
- package/src/viewers/subst-viewer.ts +16 -13
- package/src/widgets/analyze-peptides.ts +6 -6
- package/src/widgets/manual-alignment.ts +5 -3
- package/src/widgets/peptide-molecule.ts +21 -13
- package/src/workers/dimensionality-reducer.ts +2 -1
- package/tsconfig.json +1 -1
- package/webpack.config.js +16 -2
|
@@ -37,12 +37,12 @@ export function splitAlignedPeptides(peptideColumn: DG.Column, filter: boolean =
|
|
|
37
37
|
currentSplitPeptide = splitPeptidesArray[i];
|
|
38
38
|
nTerminal = currentSplitPeptide.pop()!; // it is guaranteed that there will be at least one element
|
|
39
39
|
currentLength = currentSplitPeptide.length;
|
|
40
|
-
if (currentLength !== modeMonomerCount)
|
|
40
|
+
if (currentLength !== modeMonomerCount)
|
|
41
41
|
invalidIndexes.push(i);
|
|
42
|
-
|
|
43
|
-
for (let j = 0; j < modeMonomerCount; j++)
|
|
42
|
+
|
|
43
|
+
for (let j = 0; j < modeMonomerCount; j++)
|
|
44
44
|
splitColumns[j].push(j < currentLength ? currentSplitPeptide[j] : '-');
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
splitColumns[modeMonomerCount].push(nTerminal);
|
|
47
47
|
}
|
|
48
48
|
modeMonomerCount--; // minus C-terminal
|
|
@@ -56,9 +56,9 @@ export function splitAlignedPeptides(peptideColumn: DG.Column, filter: boolean =
|
|
|
56
56
|
if (filter) {
|
|
57
57
|
splitColumns = splitColumns.filter((positionArray, index) => {
|
|
58
58
|
const isRetained = new Set(positionArray).size > 1;
|
|
59
|
-
if (!isRetained)
|
|
59
|
+
if (!isRetained)
|
|
60
60
|
columnNames.splice(index, 1);
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
return isRetained;
|
|
63
63
|
});
|
|
64
64
|
}
|
|
@@ -93,9 +93,9 @@ export class Logo extends DG.JsViewer {
|
|
|
93
93
|
*/
|
|
94
94
|
onTableAttached() {
|
|
95
95
|
if (typeof this.dataFrame !== 'undefined') {
|
|
96
|
-
if (!this.initialized)
|
|
96
|
+
if (!this.initialized)
|
|
97
97
|
this.init();
|
|
98
|
-
|
|
98
|
+
|
|
99
99
|
|
|
100
100
|
this.subs.push(DG.debounce(this.dataFrame.selection.onChanged, 50).subscribe((_: any) => this.render()));
|
|
101
101
|
this.subs.push(DG.debounce(this.dataFrame.filter.onChanged, 50).subscribe((_: any) => this.render()));
|
|
@@ -141,14 +141,13 @@ export class Logo extends DG.JsViewer {
|
|
|
141
141
|
.whereRowMask(this.dataFrame!.selection)
|
|
142
142
|
.aggregate();
|
|
143
143
|
}
|
|
144
|
-
if (selected)
|
|
144
|
+
if (selected)
|
|
145
145
|
[this.splitted] = splitAlignedPeptides(this.target!.columns.bySemType(this.colSemType));
|
|
146
|
-
|
|
146
|
+
else [this.splitted] = splitAlignedPeptides(this.dataFrame!.columns.bySemType(this.colSemType));
|
|
147
147
|
$(this.root).empty();
|
|
148
148
|
|
|
149
|
-
if (typeof this.dataFrame !== 'undefined')
|
|
149
|
+
if (typeof this.dataFrame !== 'undefined')
|
|
150
150
|
this.findLogo();
|
|
151
|
-
}
|
|
152
151
|
}
|
|
153
152
|
|
|
154
153
|
/**
|
|
@@ -176,17 +175,16 @@ export class Logo extends DG.JsViewer {
|
|
|
176
175
|
for (let i = 0; i < col.length; i++) {
|
|
177
176
|
const c = col.get(i);
|
|
178
177
|
if (c != '-') {
|
|
179
|
-
if (c[1] == '(')
|
|
178
|
+
if (c[1] == '(')
|
|
180
179
|
this.ppm[index][this.PROT_NUMS[c.substr(0, 1).toUpperCase()]] += 1 / size;
|
|
181
|
-
|
|
180
|
+
else if (c.substr(0, 3) in ChemPalette.AAFullNames && (c.length == 3 || c.at(3) == '('))
|
|
182
181
|
this.ppm[index][this.PROT_NUMS[ChemPalette.AAFullNames[c.substr(0, 3)]]] += 1 / size;
|
|
183
|
-
|
|
182
|
+
else if (c.at(0)?.toLowerCase() == c.at(0) && c.substr(1, 3) in ChemPalette.AAFullNames &&
|
|
184
183
|
(c.length == 4 || c.at(4) == '(')
|
|
185
|
-
)
|
|
184
|
+
)
|
|
186
185
|
this.ppm[index][this.PROT_NUMS[ChemPalette.AAFullNames[c.substr(1, 3)]]] += 1 / size;
|
|
187
|
-
|
|
186
|
+
else
|
|
188
187
|
this.ppm[index][this.PROT_NUMS[c]] += 1 / size;
|
|
189
|
-
}
|
|
190
188
|
}
|
|
191
189
|
}
|
|
192
190
|
index++;
|
|
@@ -3,6 +3,7 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
5
|
import $ from 'cash-dom';
|
|
6
|
+
import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
|
|
6
7
|
|
|
7
8
|
import {model} from '../model';
|
|
8
9
|
|
|
@@ -28,7 +29,7 @@ export class SARViewer extends DG.JsViewer {
|
|
|
28
29
|
protected viewerVGrid: DG.Grid | null;
|
|
29
30
|
protected currentBitset: DG.BitSet | null;
|
|
30
31
|
grouping: boolean;
|
|
31
|
-
groupMapping:
|
|
32
|
+
groupMapping: StringDictionary | null;
|
|
32
33
|
// protected pValueThreshold: number;
|
|
33
34
|
// protected amountOfBestAARs: number;
|
|
34
35
|
// duplicatesHandingMethod: string;
|
|
@@ -139,9 +140,9 @@ export class SARViewer extends DG.JsViewer {
|
|
|
139
140
|
* @memberof SARViewer
|
|
140
141
|
*/
|
|
141
142
|
async render(computeData = true) {
|
|
142
|
-
if (!this.initialized)
|
|
143
|
+
if (!this.initialized)
|
|
143
144
|
return;
|
|
144
|
-
|
|
145
|
+
|
|
145
146
|
//TODO: optimize. Don't calculate everything again if only view changes
|
|
146
147
|
if (computeData) {
|
|
147
148
|
if (typeof this.dataFrame !== 'undefined' && this.activityColumnName && this.sourceGrid) {
|
|
@@ -233,9 +234,9 @@ function syncGridsFunc(
|
|
|
233
234
|
if (viewerGrid && viewerGrid.dataFrame && viewerVGrid && viewerVGrid.dataFrame) {
|
|
234
235
|
if (sourceVertical) {
|
|
235
236
|
const dfCell = viewerVGrid.dataFrame.currentCell;
|
|
236
|
-
if (dfCell.column === null || dfCell.column.name !== 'Mean difference')
|
|
237
|
+
if (dfCell.column === null || dfCell.column.name !== 'Mean difference')
|
|
237
238
|
return;
|
|
238
|
-
|
|
239
|
+
|
|
239
240
|
const otherColName: string = viewerVGrid.dataFrame.get('Position', dfCell.rowIndex);
|
|
240
241
|
const otherRowName: string = viewerVGrid.dataFrame.get(aminoAcidResidue, dfCell.rowIndex);
|
|
241
242
|
let otherRowIndex = -1;
|
|
@@ -245,14 +246,13 @@ function syncGridsFunc(
|
|
|
245
246
|
break;
|
|
246
247
|
}
|
|
247
248
|
}
|
|
248
|
-
if (otherRowIndex !== -1)
|
|
249
|
+
if (otherRowIndex !== -1)
|
|
249
250
|
viewerGrid.dataFrame.currentCell = viewerGrid.dataFrame.cell(otherRowIndex, otherColName);
|
|
250
|
-
}
|
|
251
251
|
} else {
|
|
252
252
|
const otherPos: string = viewerGrid.dataFrame.currentCol?.name;
|
|
253
|
-
if (typeof otherPos === 'undefined' && otherPos !== aminoAcidResidue)
|
|
253
|
+
if (typeof otherPos === 'undefined' && otherPos !== aminoAcidResidue)
|
|
254
254
|
return;
|
|
255
|
-
|
|
255
|
+
|
|
256
256
|
const otherAAR: string =
|
|
257
257
|
viewerGrid.dataFrame.get(aminoAcidResidue, viewerGrid.dataFrame.currentRowIdx);
|
|
258
258
|
let otherRowIndex = -1;
|
|
@@ -265,9 +265,8 @@ function syncGridsFunc(
|
|
|
265
265
|
break;
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
|
-
if (otherRowIndex !== -1)
|
|
268
|
+
if (otherRowIndex !== -1)
|
|
269
269
|
viewerVGrid.dataFrame.currentCell = viewerVGrid.dataFrame.cell(otherRowIndex, 'Mean difference');
|
|
270
|
-
}
|
|
271
270
|
}
|
|
272
271
|
}
|
|
273
272
|
}
|
|
@@ -291,7 +290,7 @@ function applyBitset(
|
|
|
291
290
|
dataFrame: DG.DataFrame,
|
|
292
291
|
viewerGrid: DG.Grid,
|
|
293
292
|
aminoAcidResidue: string,
|
|
294
|
-
groupMapping:
|
|
293
|
+
groupMapping: StringDictionary,
|
|
295
294
|
initialBitset: DG.BitSet,
|
|
296
295
|
filterMode: boolean,
|
|
297
296
|
) {
|
|
@@ -310,9 +309,9 @@ function applyBitset(
|
|
|
310
309
|
const aarLabel = `${currentAAR === '-' ? 'Empty' : currentAAR} - ${currentPosition}`;
|
|
311
310
|
|
|
312
311
|
let splitCol = dataFrame.col(splitColName);
|
|
313
|
-
if (!splitCol)
|
|
312
|
+
if (!splitCol)
|
|
314
313
|
splitCol = dataFrame.columns.addNew(splitColName, 'string');
|
|
315
|
-
|
|
314
|
+
|
|
316
315
|
|
|
317
316
|
const isChosen = (i: number) => groupMapping[dataFrame!.get(currentPosition, i)] === currentAAR;
|
|
318
317
|
splitCol!.init((i) => isChosen(i) ? aarLabel : otherLabel);
|
|
@@ -363,9 +362,9 @@ function accordionFunc(
|
|
|
363
362
|
const elements: (HTMLLabelElement | HTMLElement)[] = [currentLabel, otherLabel];
|
|
364
363
|
|
|
365
364
|
const distPane = accordion.getPane('Distribution');
|
|
366
|
-
if (distPane)
|
|
365
|
+
if (distPane)
|
|
367
366
|
accordion.removePane(distPane);
|
|
368
|
-
|
|
367
|
+
|
|
369
368
|
accordion.addPane('Distribution', () => {
|
|
370
369
|
const hist = originalDf.clone(initialBitset).plot.histogram({
|
|
371
370
|
// const hist = originalDf.plot.histogram({
|
|
@@ -380,7 +379,7 @@ function accordionFunc(
|
|
|
380
379
|
hist.style.width = 'auto';
|
|
381
380
|
elements.push(hist);
|
|
382
381
|
|
|
383
|
-
const tableMap:
|
|
382
|
+
const tableMap: StringDictionary = {'Statistics:': ''};
|
|
384
383
|
for (const colName of new Set(['Count', 'pValue', 'Mean difference'])) {
|
|
385
384
|
const query = `${aminoAcidResidue} = ${currentAAR} and Position = ${currentPosition}`;
|
|
386
385
|
const textNum = statsDf.groupBy([colName]).where(query).aggregate().get(colName, 0);
|
|
@@ -13,9 +13,8 @@ export function addViewerToHeader(grid: DG.Grid, viewer: Promise<DG.Widget>) {
|
|
|
13
13
|
rxjs.fromEvent(grid.overlay, 'mousemove').subscribe((mm:any) => {
|
|
14
14
|
mm = mm as MouseEvent;
|
|
15
15
|
const cell = grid.hitTest(mm.offsetX, mm.offsetY);
|
|
16
|
-
if (cell !== null && cell?.isColHeader && cell.tableColumn?.semType == 'aminoAcids')
|
|
16
|
+
if (cell !== null && cell?.isColHeader && cell.tableColumn?.semType == 'aminoAcids')
|
|
17
17
|
barchart.highlight(cell, mm.offsetX, mm.offsetY);
|
|
18
|
-
}
|
|
19
18
|
});
|
|
20
19
|
|
|
21
20
|
rxjs.fromEvent(grid.overlay, 'click').subscribe((mm:any) => {
|
|
@@ -118,9 +117,8 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
118
117
|
let i = 0;
|
|
119
118
|
for (const value of Object.values(groups)) {
|
|
120
119
|
i++;
|
|
121
|
-
for (const obj of value)
|
|
120
|
+
for (const obj of value)
|
|
122
121
|
this.ord[obj] = i;
|
|
123
|
-
}
|
|
124
122
|
}
|
|
125
123
|
this.yScale = scaleLinear();
|
|
126
124
|
this.xScale = scaleBand();
|
|
@@ -169,9 +167,9 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
169
167
|
const buf2 = df.filter.getBuffer();
|
|
170
168
|
const resbuf = new Int32Array(df.rowCount);
|
|
171
169
|
|
|
172
|
-
for (let i = 0; i < buf2.length; i++)
|
|
170
|
+
for (let i = 0; i < buf2.length; i++)
|
|
173
171
|
resbuf[i] = buf1[i] & buf2[i];
|
|
174
|
-
|
|
172
|
+
|
|
175
173
|
|
|
176
174
|
//TODO: optimize it, why store so many tables?
|
|
177
175
|
const mask = DG.BitSet.fromBytes(resbuf.buffer, df.rowCount);
|
|
@@ -187,9 +185,8 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
187
185
|
const buf2 = df.filter.getBuffer();
|
|
188
186
|
const resbuf = new Int32Array(df.rowCount);
|
|
189
187
|
|
|
190
|
-
for (let i = 0; i < buf2.length; i++)
|
|
188
|
+
for (let i = 0; i < buf2.length; i++)
|
|
191
189
|
resbuf[i] = buf1[i] & buf2[i];
|
|
192
|
-
}
|
|
193
190
|
|
|
194
191
|
|
|
195
192
|
// @ts-ignore
|
|
@@ -225,9 +222,9 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
225
222
|
for (let i = 0; i < df.rowCount; i++) {
|
|
226
223
|
const amino = df.getCol(name).get(i);
|
|
227
224
|
const aminoCount = df.getCol(`${name}_count`).get(i);
|
|
228
|
-
if ((!amino) || amino === this.dataEmptyAA)
|
|
225
|
+
if ((!amino) || amino === this.dataEmptyAA)
|
|
229
226
|
continue;
|
|
230
|
-
|
|
227
|
+
|
|
231
228
|
const aminoObj = {'name': amino, 'count': aminoCount, 'selectedCount': 0};
|
|
232
229
|
colObj['data'].push(aminoObj);
|
|
233
230
|
for (let j = 0; j < this.aggregatedTablesUnselected[name].rowCount; j++) {
|
|
@@ -241,12 +238,12 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
241
238
|
}
|
|
242
239
|
}
|
|
243
240
|
colObj['data'] = colObj['data'].sort((o1, o2) => {
|
|
244
|
-
if (this.ord[o1['name']] > this.ord[o2['name']])
|
|
241
|
+
if (this.ord[o1['name']] > this.ord[o2['name']])
|
|
245
242
|
return -1;
|
|
246
|
-
|
|
247
|
-
if (this.ord[o1['name']] < this.ord[o2['name']])
|
|
243
|
+
|
|
244
|
+
if (this.ord[o1['name']] < this.ord[o2['name']])
|
|
248
245
|
return 1;
|
|
249
|
-
|
|
246
|
+
|
|
250
247
|
|
|
251
248
|
return 0;
|
|
252
249
|
});
|
|
@@ -329,13 +326,12 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
329
326
|
|
|
330
327
|
render(computeData = true) {
|
|
331
328
|
const df = this.dataFrame!;
|
|
332
|
-
if (computeData)
|
|
329
|
+
if (computeData)
|
|
333
330
|
this.computeData(df);
|
|
334
|
-
|
|
331
|
+
|
|
335
332
|
if (this.tableCanvas) {
|
|
336
|
-
for (const name of this.aminoColumnNames)
|
|
333
|
+
for (const name of this.aminoColumnNames)
|
|
337
334
|
this.renderBar(name);
|
|
338
|
-
}
|
|
339
335
|
}
|
|
340
336
|
return;
|
|
341
337
|
}
|
|
@@ -350,16 +346,15 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
350
346
|
}
|
|
351
347
|
|
|
352
348
|
unregister(name: string) {
|
|
353
|
-
if (this.registered[name])
|
|
349
|
+
if (this.registered[name])
|
|
354
350
|
delete this.registered[name];
|
|
355
|
-
}
|
|
356
351
|
}
|
|
357
352
|
|
|
358
353
|
|
|
359
354
|
renderBar(name: string) {
|
|
360
|
-
if (!(this.registered[name]) || !(this.tableCanvas))
|
|
355
|
+
if (!(this.registered[name]) || !(this.tableCanvas))
|
|
361
356
|
return;
|
|
362
|
-
|
|
357
|
+
|
|
363
358
|
const cell = this.registered[name];
|
|
364
359
|
const rect = cell.bounds;
|
|
365
360
|
this.renderBarToCanvas(this.tableCanvas.getContext('2d')!, cell, rect.x, rect.y, rect.width, rect.height);
|
|
@@ -367,9 +362,9 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
367
362
|
|
|
368
363
|
highlight(cell: DG.GridCell, offsetX:number, offsetY:number) {
|
|
369
364
|
const colName = cell.tableColumn?.name;
|
|
370
|
-
if (!colName)
|
|
365
|
+
if (!colName)
|
|
371
366
|
return;
|
|
372
|
-
|
|
367
|
+
|
|
373
368
|
const margin = 0.2;
|
|
374
369
|
const bound = cell.bounds;
|
|
375
370
|
const x = bound.x + bound.width * margin;
|
|
@@ -403,9 +398,9 @@ export class StackedBarChart extends DG.JsViewer {
|
|
|
403
398
|
}
|
|
404
399
|
|
|
405
400
|
beginSelection(event:any) {
|
|
406
|
-
if (!this.highlighted || !this.dataFrame)
|
|
401
|
+
if (!this.highlighted || !this.dataFrame)
|
|
407
402
|
return;
|
|
408
|
-
|
|
403
|
+
|
|
409
404
|
this.dataFrame!.selection.handleClick((i) => {
|
|
410
405
|
// @ts-ignore
|
|
411
406
|
return this.highlighted!['aaName'] === (this.dataFrame.getCol(this.highlighted!['colName']).get(i));
|
|
@@ -1,4 +1,4 @@
|
|
|
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
4
|
|
|
@@ -6,6 +6,7 @@ import $ from 'cash-dom';
|
|
|
6
6
|
|
|
7
7
|
// import {aarGroups} from '../describe';
|
|
8
8
|
import {setAARRenderer} from '../utils/cell-renderer';
|
|
9
|
+
import { SemanticValue } from 'datagrok-api/dg';
|
|
9
10
|
|
|
10
11
|
export class SubstViewer extends DG.JsViewer {
|
|
11
12
|
viewerGrid: DG.Grid | null;
|
|
@@ -35,7 +36,7 @@ export class SubstViewer extends DG.JsViewer {
|
|
|
35
36
|
const df: DG.DataFrame = this.dataFrame!;
|
|
36
37
|
const col: DG.Column = df.columns.bySemType('alignedSequence');
|
|
37
38
|
// let values: number[] = df.columns.byName('IC50').toList();
|
|
38
|
-
const values = df.getCol(this.activityColumnName).toList()
|
|
39
|
+
const values = df.getCol(this.activityColumnName).toList();
|
|
39
40
|
// values = values;
|
|
40
41
|
const splitedMatrix = this.split(col);
|
|
41
42
|
|
|
@@ -123,6 +124,7 @@ export class SubstViewer extends DG.JsViewer {
|
|
|
123
124
|
const tableValuesKeys = Object.keys(tableValues);
|
|
124
125
|
const dfLength = tableValuesKeys.length;
|
|
125
126
|
const cols = [...nColsArray.keys()].map((v) => DG.Column.int(v.toString(), dfLength));
|
|
127
|
+
cols.forEach((col: DG.Column) => col.semType = 'Substitution');
|
|
126
128
|
const aarCol = DG.Column.string(aarColName, dfLength);
|
|
127
129
|
cols.splice(0, 1, aarCol);
|
|
128
130
|
const table = DG.DataFrame.fromColumns(cols);
|
|
@@ -160,9 +162,9 @@ export class SubstViewer extends DG.JsViewer {
|
|
|
160
162
|
},
|
|
161
163
|
);
|
|
162
164
|
|
|
163
|
-
for (const col of table.columns.names())
|
|
165
|
+
for (const col of table.columns.names())
|
|
164
166
|
this.viewerGrid.col(col)!.width = this.viewerGrid.props.rowHeight;
|
|
165
|
-
|
|
167
|
+
|
|
166
168
|
|
|
167
169
|
this.viewerGrid.onCellRender.subscribe((args) => {
|
|
168
170
|
if (args.cell.isRowHeader && args.cell.gridColumn.visible) {
|
|
@@ -200,9 +202,12 @@ export class SubstViewer extends DG.JsViewer {
|
|
|
200
202
|
|
|
201
203
|
this.casesGrid = tempDf.plot.grid();
|
|
202
204
|
this.casesGrid.props.allowEdit = false;
|
|
205
|
+
grok.shell.o = SemanticValue.fromValueType(tempDf, 'Substitution');
|
|
203
206
|
} else {
|
|
207
|
+
grok.shell.o = SemanticValue.fromValueType(null, 'Substitution');
|
|
204
208
|
this.casesGrid = null;
|
|
205
209
|
}
|
|
210
|
+
|
|
206
211
|
this.render();
|
|
207
212
|
});
|
|
208
213
|
|
|
@@ -211,9 +216,7 @@ export class SubstViewer extends DG.JsViewer {
|
|
|
211
216
|
|
|
212
217
|
render() {
|
|
213
218
|
$(this.root).empty();
|
|
214
|
-
this.root.appendChild(this.
|
|
215
|
-
this.viewerGrid!.root : ui.splitH([this.viewerGrid!.root, this.casesGrid.root]),
|
|
216
|
-
);
|
|
219
|
+
this.root.appendChild(this.viewerGrid!.root);
|
|
217
220
|
}
|
|
218
221
|
|
|
219
222
|
split(peptideColumn: DG.Column, filter: boolean = true): string[][] {
|
|
@@ -245,12 +248,12 @@ export class SubstViewer extends DG.JsViewer {
|
|
|
245
248
|
currentSplitPeptide = splitPeptidesArray[i];
|
|
246
249
|
nTerminal = currentSplitPeptide.pop()!; // it is guaranteed that there will be at least one element
|
|
247
250
|
currentLength = currentSplitPeptide.length;
|
|
248
|
-
if (currentLength !== modeMonomerCount)
|
|
251
|
+
if (currentLength !== modeMonomerCount)
|
|
249
252
|
invalidIndexes.push(i);
|
|
250
|
-
|
|
251
|
-
for (let j = 0; j < modeMonomerCount; j++)
|
|
253
|
+
|
|
254
|
+
for (let j = 0; j < modeMonomerCount; j++)
|
|
252
255
|
splitColumns[j].push(j < currentLength ? currentSplitPeptide[j] : '-');
|
|
253
|
-
|
|
256
|
+
|
|
254
257
|
splitColumns[modeMonomerCount].push(nTerminal);
|
|
255
258
|
}
|
|
256
259
|
modeMonomerCount--; // minus C-terminal
|
|
@@ -264,9 +267,9 @@ export class SubstViewer extends DG.JsViewer {
|
|
|
264
267
|
if (filter) {
|
|
265
268
|
splitColumns = splitColumns.filter((positionArray, index) => {
|
|
266
269
|
const isRetained = new Set(positionArray).size > 1;
|
|
267
|
-
if (!isRetained)
|
|
270
|
+
if (!isRetained)
|
|
268
271
|
columnNames.splice(index, 1);
|
|
269
|
-
|
|
272
|
+
|
|
270
273
|
return isRetained;
|
|
271
274
|
});
|
|
272
275
|
}
|
|
@@ -3,6 +3,7 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
import {Peptides} from '../peptides';
|
|
5
5
|
import '../styles.css';
|
|
6
|
+
import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Peptide analysis widget.
|
|
@@ -18,9 +19,9 @@ export async function analyzePeptidesWidget(
|
|
|
18
19
|
col: DG.Column, view: DG.TableView, tableGrid: DG.Grid, currentDf: DG.DataFrame,
|
|
19
20
|
): Promise<DG.Widget> {
|
|
20
21
|
let tempCol = null;
|
|
21
|
-
for (const column of currentDf.columns.numerical)
|
|
22
|
+
for (const column of currentDf.columns.numerical)
|
|
22
23
|
tempCol = column.type === DG.TYPE.FLOAT ? column : null;
|
|
23
|
-
|
|
24
|
+
|
|
24
25
|
const defaultColumn: DG.Column = currentDf.col('activity') || currentDf.col('IC50') || tempCol;
|
|
25
26
|
const histogramHost = ui.div([], {id: 'pep-hist-host'});
|
|
26
27
|
|
|
@@ -77,18 +78,17 @@ export async function analyzePeptidesWidget(
|
|
|
77
78
|
const startBtn = ui.button('Launch SAR', async () => {
|
|
78
79
|
if (activityColumnChoice.value.type === DG.TYPE.FLOAT) {
|
|
79
80
|
const progress = DG.TaskBarProgressIndicator.create('Loading SAR...');
|
|
80
|
-
const options:
|
|
81
|
+
const options: StringDictionary = {
|
|
81
82
|
'activityColumnName': activityColumnChoice.value.name,
|
|
82
83
|
'scaling': activityScalingMethod.value,
|
|
83
84
|
};
|
|
84
85
|
|
|
85
86
|
const peptides = new Peptides();
|
|
86
|
-
await peptides.init(tableGrid, view, currentDf, options, col
|
|
87
|
+
await peptides.init(tableGrid, view, currentDf, options, col);
|
|
87
88
|
|
|
88
89
|
progress.close();
|
|
89
|
-
} else
|
|
90
|
+
} else
|
|
90
91
|
grok.shell.error('The activity column must be of floating point number type!');
|
|
91
|
-
}
|
|
92
92
|
});
|
|
93
93
|
startBtn.style.alignSelf = 'center';
|
|
94
94
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as ui from 'datagrok-api/ui';
|
|
2
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
3
|
import * as DG from 'datagrok-api/dg';
|
|
3
4
|
|
|
4
5
|
import $ from 'cash-dom';
|
|
@@ -24,12 +25,13 @@ export function manualAlignmentWidget(alignedSequenceCol: DG.Column, currentDf:
|
|
|
24
25
|
|
|
25
26
|
alignedSequenceCol.set(affectedRowIndex, newSequence);
|
|
26
27
|
for (const part of splitSequence.columns) {
|
|
27
|
-
if (currentDf.col(part.name) !== null)
|
|
28
|
+
if (currentDf.col(part.name) !== null)
|
|
28
29
|
currentDf.set(part.name, affectedRowIndex, part.get(0));
|
|
29
|
-
}
|
|
30
30
|
}
|
|
31
|
+
const temp = grok.shell.o;
|
|
32
|
+
grok.shell.o = null;
|
|
33
|
+
grok.shell.o = temp;
|
|
31
34
|
|
|
32
|
-
// await model.updateDefault();
|
|
33
35
|
await Peptides.recalculate();
|
|
34
36
|
});
|
|
35
37
|
|
|
@@ -13,19 +13,11 @@ import {ChemPalette} from '../utils/chem-palette';
|
|
|
13
13
|
export async function peptideMoleculeWidget(pep: string): Promise<DG.Widget> {
|
|
14
14
|
const pi = DG.TaskBarProgressIndicator.create('Creating NGL view');
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
mols[i] = aar.substr(0, aar.length - 1);
|
|
22
|
-
} else if (!split[i] || split[i] == '-') {
|
|
23
|
-
mols[i] = '';
|
|
24
|
-
} else {
|
|
25
|
-
return new DG.Widget(ui.divH([]));
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
const smiles = mols.join('') + 'O';
|
|
16
|
+
const smiles = getMolecule(pep);
|
|
17
|
+
if (smiles == '')
|
|
18
|
+
return new DG.Widget(ui.divH([]));
|
|
19
|
+
|
|
20
|
+
|
|
29
21
|
let molfileStr = (await grok.functions.call('Peptides:SmiTo3D', {smiles}));
|
|
30
22
|
|
|
31
23
|
molfileStr = molfileStr.replaceAll('\\n', '\n'); ;
|
|
@@ -47,3 +39,19 @@ export async function peptideMoleculeWidget(pep: string): Promise<DG.Widget> {
|
|
|
47
39
|
|
|
48
40
|
return new DG.Widget(ui.div([panel, nglHost]));
|
|
49
41
|
}
|
|
42
|
+
|
|
43
|
+
export function getMolecule(pep: string): string {
|
|
44
|
+
const split = pep.split('-');
|
|
45
|
+
const mols = [];
|
|
46
|
+
for (let i = 1; i < split.length - 1; i++) {
|
|
47
|
+
if (split[i] in ChemPalette.AASmiles) {
|
|
48
|
+
const aar = ChemPalette.AASmiles[split[i]];
|
|
49
|
+
mols[i] = aar.substr(0, aar.length - 1);
|
|
50
|
+
} else if (!split[i] || split[i] == '-')
|
|
51
|
+
mols[i] = '';
|
|
52
|
+
else
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
const smiles = mols.join('') + 'O';
|
|
56
|
+
return smiles;
|
|
57
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {DimensionalityReducer, KnownMethods} from '@datagrok-libraries/ml/src/reduce-dimensionality';
|
|
2
|
+
import { KnownMetrics } from '@datagrok-libraries/ml/src/typed-metrics';
|
|
2
3
|
import {Coordinates} from '@datagrok-libraries/utils/src/type-declarations';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -10,7 +11,7 @@ import {Coordinates} from '@datagrok-libraries/utils/src/type-declarations';
|
|
|
10
11
|
* @param {number} cyclesCount Number of cycles to repeat.
|
|
11
12
|
* @return {Coordinates} Embedding.
|
|
12
13
|
*/
|
|
13
|
-
function onMessage(columnData: [], method: KnownMethods, measure:
|
|
14
|
+
function onMessage(columnData: any[], method: KnownMethods, measure: KnownMetrics, cyclesCount: number): Coordinates {
|
|
14
15
|
const reducer = new DimensionalityReducer(
|
|
15
16
|
columnData,
|
|
16
17
|
method,
|
package/tsconfig.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// "incremental": true, /* Enable incremental compilation */
|
|
7
7
|
"target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
|
|
8
8
|
"module": "es2020", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
|
9
|
-
"lib": ["es2020", "dom"], /* Specify library files to be included in the compilation. */
|
|
9
|
+
"lib": ["es2020", "dom", "ES2021.String"], /* Specify library files to be included in the compilation. */
|
|
10
10
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
|
11
11
|
// "checkJs": true, /* Report errors in .js files. */
|
|
12
12
|
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
package/webpack.config.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
+
const packageName = path.parse(require('./package.json').name).name.toLowerCase().replace(/-/g, '');
|
|
2
3
|
|
|
3
4
|
module.exports = {
|
|
4
5
|
mode: 'development',
|
|
5
6
|
entry: {
|
|
6
|
-
package: './src/package.ts',
|
|
7
|
+
package: ['./src/package.ts'],
|
|
8
|
+
test: {
|
|
9
|
+
filename: 'package-test.js',
|
|
10
|
+
library: {type: 'var', name: `${packageName}_test`},
|
|
11
|
+
import: './src/package-test.ts',
|
|
12
|
+
},
|
|
7
13
|
},
|
|
14
|
+
devServer: {
|
|
15
|
+
contentBase: './dist',
|
|
16
|
+
},
|
|
17
|
+
target: 'web',
|
|
8
18
|
module: {
|
|
9
19
|
rules: [
|
|
10
20
|
{
|
|
@@ -19,7 +29,7 @@ module.exports = {
|
|
|
19
29
|
],
|
|
20
30
|
},
|
|
21
31
|
resolve: {
|
|
22
|
-
extensions: ['.
|
|
32
|
+
extensions: ['.mjs', '.js', '.json', '.ts', '.tsx'],
|
|
23
33
|
},
|
|
24
34
|
devtool: 'inline-source-map',
|
|
25
35
|
externals: {
|
|
@@ -36,4 +46,8 @@ module.exports = {
|
|
|
36
46
|
libraryTarget: 'var',
|
|
37
47
|
path: path.resolve(__dirname, 'dist'),
|
|
38
48
|
},
|
|
49
|
+
experiments: {
|
|
50
|
+
asyncWebAssembly: true,
|
|
51
|
+
topLevelAwait: true,
|
|
52
|
+
},
|
|
39
53
|
};
|