@datagrok/peptides 1.2.0 → 1.3.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/dist/package-test.js +682 -613
- package/dist/package.js +779 -617
- package/package.json +5 -1
- package/src/model.ts +423 -222
- package/src/package.ts +16 -15
- package/src/styles.css +1 -0
- package/src/tests/core.ts +10 -9
- package/src/tests/peptide-space-test.ts +32 -32
- package/src/utils/cell-renderer.ts +39 -59
- package/src/utils/constants.ts +9 -2
- package/src/utils/misc.ts +12 -17
- package/src/utils/peptide-similarity-space.ts +2 -1
- package/src/utils/types.ts +1 -1
- package/src/viewers/logo-summary.ts +42 -0
- package/src/viewers/peptide-space-viewer.ts +6 -4
- package/src/viewers/sar-viewer.ts +64 -13
- package/src/widgets/distribution.ts +26 -11
- package/src/widgets/mutation-cliffs.ts +3 -2
- package/src/widgets/{analyze-peptides.ts → peptides.ts} +56 -28
- package/test-Peptides-8408d9b6ee67-ca232121.html +246 -0
- package/src/utils/invariant-map.ts +0 -163
package/src/package.ts
CHANGED
|
@@ -5,13 +5,13 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
|
|
6
6
|
import * as C from './utils/constants';
|
|
7
7
|
|
|
8
|
-
import {analyzePeptidesWidget} from './widgets/
|
|
8
|
+
import {analyzePeptidesWidget} from './widgets/peptides';
|
|
9
9
|
import {PeptideSimilaritySpaceWidget} from './utils/peptide-similarity-space';
|
|
10
10
|
import {manualAlignmentWidget} from './widgets/manual-alignment';
|
|
11
|
-
import {
|
|
11
|
+
import {MutationCliffsViewer, MostPotentResiduesViewer} from './viewers/sar-viewer';
|
|
12
12
|
|
|
13
13
|
import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
|
|
14
|
-
import {
|
|
14
|
+
import {LogoSummary} from './viewers/logo-summary';
|
|
15
15
|
|
|
16
16
|
export const _package = new DG.Package();
|
|
17
17
|
let currentTable: DG.DataFrame;
|
|
@@ -84,16 +84,23 @@ export async function peptidesPanel(col: DG.Column): Promise<DG.Widget> {
|
|
|
84
84
|
//description: Peptides SAR Viewer
|
|
85
85
|
//tags: viewer
|
|
86
86
|
//output: viewer result
|
|
87
|
-
export function sar():
|
|
88
|
-
return new
|
|
87
|
+
export function sar(): MutationCliffsViewer {
|
|
88
|
+
return new MutationCliffsViewer();
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
//name: peptide-sar-viewer-vertical
|
|
92
92
|
//description: Peptides Vertical SAR Viewer
|
|
93
93
|
//tags: viewer
|
|
94
94
|
//output: viewer result
|
|
95
|
-
export function sarVertical():
|
|
96
|
-
return new
|
|
95
|
+
export function sarVertical(): MostPotentResiduesViewer {
|
|
96
|
+
return new MostPotentResiduesViewer();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
//name: logo-summary-viewer
|
|
100
|
+
//tags: viewer
|
|
101
|
+
//output: viewer result
|
|
102
|
+
export function logoSummary(): LogoSummary {
|
|
103
|
+
return new LogoSummary();
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
//name: peptide-space-viewer
|
|
@@ -148,16 +155,10 @@ export function getPeptidesStructure(col: DG.Column): DG.Widget {
|
|
|
148
155
|
|
|
149
156
|
function getOrDefine(dataframe?: DG.DataFrame, column?: DG.Column | null): [DG.DataFrame, DG.Column] {
|
|
150
157
|
dataframe ??= grok.shell.t;
|
|
151
|
-
column ??= dataframe.columns.bySemType(C.SEM_TYPES.MACROMOLECULE);
|
|
158
|
+
// column ??= dataframe.columns.bySemType(C.SEM_TYPES.MACROMOLECULE);
|
|
159
|
+
column ??= dataframe.getCol(C.COLUMNS_NAMES.MACROMOLECULE);
|
|
152
160
|
if (column === null)
|
|
153
161
|
throw new Error('Table does not contain aligned sequence columns');
|
|
154
162
|
|
|
155
163
|
return [dataframe, column];
|
|
156
164
|
}
|
|
157
|
-
|
|
158
|
-
//name: Invariant Map Filter
|
|
159
|
-
//tags: filter
|
|
160
|
-
//output: filter result
|
|
161
|
-
export function invariantMapFilter() {
|
|
162
|
-
return new InvariantMap();
|
|
163
|
-
}
|
package/src/styles.css
CHANGED
package/src/tests/core.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
import {category, test, expect, delay} from '@datagrok-libraries/utils/src/test';
|
|
5
5
|
|
|
6
6
|
import {_package} from '../package-test';
|
|
7
|
-
import {startAnalysis} from '../widgets/
|
|
7
|
+
import {startAnalysis} from '../widgets/peptides';
|
|
8
8
|
import {PeptidesModel} from '../model';
|
|
9
9
|
import * as C from '../utils/constants';
|
|
10
10
|
import {scaleActivity} from '../utils/misc';
|
|
@@ -14,6 +14,7 @@ category('Core', () => {
|
|
|
14
14
|
let simpleActivityCol: DG.Column<number>;
|
|
15
15
|
let simpleAlignedSeqCol: DG.Column<string>;
|
|
16
16
|
let simpleScaledDf: DG.DataFrame;
|
|
17
|
+
let scalingFormula: (x: number) => number;
|
|
17
18
|
let simpleScaledColName: string;
|
|
18
19
|
|
|
19
20
|
let complexTable: DG.DataFrame;
|
|
@@ -34,14 +35,14 @@ category('Core', () => {
|
|
|
34
35
|
simpleAlignedSeqCol.tags[C.TAGS.ALPHABET] = 'PT';
|
|
35
36
|
simpleAlignedSeqCol.tags[DG.TAGS.UNITS] = 'fasta';
|
|
36
37
|
simpleAlignedSeqCol.tags['aligned'] = 'SEQ.MSA';
|
|
37
|
-
[simpleScaledDf, simpleScaledColName] = scaleActivity('-lg',
|
|
38
|
+
[simpleScaledDf, scalingFormula, simpleScaledColName] = scaleActivity('-lg', simpleActivityCol);
|
|
38
39
|
|
|
39
40
|
model = await startAnalysis(
|
|
40
|
-
simpleActivityCol, simpleAlignedSeqCol, simpleTable,
|
|
41
|
+
simpleActivityCol, simpleAlignedSeqCol, null, simpleTable, scalingFormula, simpleScaledColName, '-lg', []);
|
|
41
42
|
expect(model instanceof PeptidesModel, true);
|
|
42
43
|
|
|
43
44
|
if (model != null) {
|
|
44
|
-
model.
|
|
45
|
+
model.mutationCliffsSelection = {'11': ['D']};
|
|
45
46
|
grok.shell.closeTable(model.df);
|
|
46
47
|
}
|
|
47
48
|
});
|
|
@@ -56,14 +57,14 @@ category('Core', () => {
|
|
|
56
57
|
complexAlignedSeqCol.tags[DG.TAGS.UNITS] = 'separator';
|
|
57
58
|
complexAlignedSeqCol.tags['aligned'] = 'SEQ.MSA';
|
|
58
59
|
complexAlignedSeqCol.tags[C.TAGS.SEPARATOR] = '/';
|
|
59
|
-
[complexScaledDf, complexScaledColName] = scaleActivity('-lg',
|
|
60
|
+
[complexScaledDf, scalingFormula, complexScaledColName] = scaleActivity('-lg', complexActivityCol);
|
|
60
61
|
|
|
61
62
|
model = await startAnalysis(
|
|
62
|
-
complexActivityCol, complexAlignedSeqCol, complexTable,
|
|
63
|
+
complexActivityCol, complexAlignedSeqCol, null, complexTable, scalingFormula, complexScaledColName, '-lg', []);
|
|
63
64
|
expect(model instanceof PeptidesModel, true);
|
|
64
65
|
|
|
65
66
|
if (model != null) {
|
|
66
|
-
model.
|
|
67
|
+
model.mutationCliffsSelection = {'13': ['-']};
|
|
67
68
|
grok.shell.closeTable(model.df);
|
|
68
69
|
}
|
|
69
70
|
});
|
|
@@ -77,10 +78,10 @@ category('Core', () => {
|
|
|
77
78
|
simpleAlignedSeqCol.tags[C.TAGS.ALPHABET] = 'PT';
|
|
78
79
|
simpleAlignedSeqCol.tags[DG.TAGS.UNITS] = 'fasta';
|
|
79
80
|
simpleAlignedSeqCol.tags['aligned'] = 'SEQ.MSA';
|
|
80
|
-
[simpleScaledDf, simpleScaledColName] = scaleActivity('-lg',
|
|
81
|
+
[simpleScaledDf, scalingFormula, simpleScaledColName] = scaleActivity('-lg', simpleActivityCol);
|
|
81
82
|
|
|
82
83
|
model = await startAnalysis(
|
|
83
|
-
simpleActivityCol, simpleAlignedSeqCol, simpleTable,
|
|
84
|
+
simpleActivityCol, simpleAlignedSeqCol, null, simpleTable, scalingFormula, simpleScaledColName, '-lg', []);
|
|
84
85
|
let v = grok.shell.getTableView('Peptides analysis');
|
|
85
86
|
const d = v.dataFrame;
|
|
86
87
|
const layout = v.saveLayout();
|
|
@@ -58,40 +58,40 @@ category('Peptide space', async () => {
|
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
category('Peptide Space Performance', () => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
// category('Peptide Space Performance', () => {
|
|
62
|
+
// test('test_compute_weights_performance', async () => {
|
|
63
|
+
// const table = DG.DataFrame.fromCsv(await _package.files.readAsText('peptides_large.csv'));
|
|
64
|
+
// const results: {[key: string]: {[key: string]: {[key: string]: number}}} = {};
|
|
65
|
+
// const sliceVolumes = [1, 2, 3, 4, 5, 7, 10];
|
|
66
|
+
// const methods = DimensionalityReducer.availableMethods;
|
|
67
|
+
// const metrics = DimensionalityReducer.availableMetricsByType('String');
|
|
68
|
+
// const totalRuns = sliceVolumes.length * methods.length * metrics.length;
|
|
69
|
+
// console.log('Started Peptide Space Performance benchmark...');
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
// let run = 0;
|
|
72
|
+
// for (const slice of sliceVolumes) {
|
|
73
|
+
// const bitset = DG.BitSet.create(table.rowCount, (i) => i < slice * 1000);
|
|
74
|
+
// const tableSlice = table.clone(bitset);
|
|
75
|
+
// const col = tableSlice.getCol('sequence');
|
|
76
|
+
// const methodObj: {[key: string]: {[key: string]: number}} = {};
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
// for (const method of methods) {
|
|
79
|
+
// const measureObj: {[key: string]: number} = {};
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
// for (const metric of metrics) {
|
|
82
|
+
// console.log(`Run ${run++}/${totalRuns}`);
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
// const start = new Date();
|
|
85
|
+
// await computeWeights(tableSlice, method, metric, 100, col);
|
|
86
|
+
// const stop = new Date();
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
});
|
|
88
|
+
// measureObj[metric] = stop.getTime() - start.getTime();
|
|
89
|
+
// }
|
|
90
|
+
// methodObj[method] = measureObj;
|
|
91
|
+
// }
|
|
92
|
+
// results[`${slice}k`] = methodObj;
|
|
93
|
+
// }
|
|
94
|
+
// console.log('Peptide Space Performance benchmark finished...');
|
|
95
|
+
// console.log(results);
|
|
96
|
+
// });
|
|
97
|
+
// });
|
|
@@ -5,65 +5,24 @@ import * as C from './constants';
|
|
|
5
5
|
import {getPalleteByType} from './misc';
|
|
6
6
|
import * as types from './types';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* @param {DG.Column} col Column to expand.
|
|
13
|
-
* @param {DG.Grid} grid Grid containing colum for expansion.
|
|
14
|
-
* @param {(cellVal: string) => number} cellRenderSize An anonymous function that calculates cell value length.
|
|
15
|
-
* @param {number} [textSizeMult=10] Text size muliplier.
|
|
16
|
-
* @param {number} [minSize=30] Minimal column width.
|
|
17
|
-
* @param {number} [maxSize=650] Maximum column width.
|
|
18
|
-
* @param {number} [timeout=500] Timeout value.
|
|
19
|
-
*/
|
|
20
|
-
export function expandColumn(col: DG.Column, grid: DG.Grid, cellRenderSize: (cellVal: string) => number,
|
|
21
|
-
textSizeMult = 10, minSize = 30, maxSize = 650, timeout = 500): void {
|
|
22
|
-
let maxLen = 0;
|
|
23
|
-
col.categories.forEach((ent: string) => {
|
|
24
|
-
const len = cellRenderSize(ent);
|
|
25
|
-
if (len > maxLen)
|
|
26
|
-
maxLen = len;
|
|
27
|
-
});
|
|
28
|
-
setTimeout(() => {
|
|
29
|
-
grid.columns.byName(col.name)!.width = Math.min(Math.max(maxLen * textSizeMult, minSize), maxSize);
|
|
30
|
-
},
|
|
31
|
-
timeout);
|
|
8
|
+
function renderCellSelection(canvasContext: CanvasRenderingContext2D, bound: DG.Rect): void {
|
|
9
|
+
canvasContext.strokeStyle = '#000';
|
|
10
|
+
canvasContext.lineWidth = 1;
|
|
11
|
+
canvasContext.strokeRect(bound.x + 1, bound.y + 1, bound.width - 1, bound.height - 1);
|
|
32
12
|
}
|
|
33
13
|
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
*
|
|
37
|
-
* @export
|
|
38
|
-
* @param {DG.Column} col Column to set renderer for.
|
|
39
|
-
* @param {(DG.Grid | null)} [grid=null] Grid that contains the col column.
|
|
40
|
-
* @param {boolean} [grouping=false] Is grouping enabled.
|
|
41
|
-
*/
|
|
42
|
-
export function setAARRenderer(col: DG.Column, alphabet: string, grid?: DG.Grid): void {
|
|
14
|
+
/** A function that sets amino acid residue cell renderer to the specified column */
|
|
15
|
+
export function setAARRenderer(col: DG.Column, alphabet: string, grid: DG.Grid, timeout: number = 500): void {
|
|
43
16
|
col.semType = C.SEM_TYPES.MONOMER;
|
|
44
17
|
col.setTag('cell.renderer', C.SEM_TYPES.MONOMER);
|
|
45
18
|
col.tags[C.TAGS.ALPHABET] = alphabet;
|
|
46
|
-
|
|
47
|
-
if (grid)
|
|
48
|
-
expandColumn(col, grid, (ent) => measureAAR(ent));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* A function to measure amino acid residue
|
|
53
|
-
*
|
|
54
|
-
* @export
|
|
55
|
-
* @param {string} s Amino acid residue string.
|
|
56
|
-
* @return {number} Amino acid residue size.
|
|
57
|
-
*/
|
|
58
|
-
export function measureAAR(s: string): number {
|
|
59
|
-
const end = s.lastIndexOf(')');
|
|
60
|
-
const beg = s.indexOf('(');
|
|
61
|
-
return end == beg ? s.length : s.length - (end - beg) + 1;
|
|
19
|
+
setTimeout(() => grid.columns.byName(col.name)!.width = 60, timeout);
|
|
62
20
|
}
|
|
63
21
|
|
|
64
|
-
export function
|
|
65
|
-
statsDf: DG.DataFrame, twoColorMode: boolean, mdCol: DG.Column<number>, bound: DG.Rect,
|
|
66
|
-
|
|
22
|
+
export function renderMutationCliffCell(canvasContext: CanvasRenderingContext2D, currentAAR: string,
|
|
23
|
+
currentPosition: string, statsDf: DG.DataFrame, twoColorMode: boolean, mdCol: DG.Column<number>, bound: DG.Rect,
|
|
24
|
+
cellValue: number, mutationCliffsSelection: types.PositionToAARList, substitutionsInfo: types.SubstitutionsInfo,
|
|
25
|
+
): void {
|
|
67
26
|
const queryAAR = `${C.COLUMNS_NAMES.MONOMER} = ${currentAAR}`;
|
|
68
27
|
const query = `${queryAAR} and ${C.COLUMNS_NAMES.POSITION} = ${currentPosition}`;
|
|
69
28
|
const pVal: number = statsDf
|
|
@@ -112,13 +71,34 @@ export function renderSARCell(canvasContext: CanvasRenderingContext2D, currentAA
|
|
|
112
71
|
canvasContext.fillText(substValue.toString(), midX, midY);
|
|
113
72
|
}
|
|
114
73
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
74
|
+
const aarSelection = mutationCliffsSelection[currentPosition];
|
|
75
|
+
if (aarSelection && aarSelection.includes(currentAAR))
|
|
76
|
+
renderCellSelection(canvasContext, bound);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function renderInvaraintMapCell(canvasContext: CanvasRenderingContext2D, currentAAR: string,
|
|
80
|
+
currentPosition: string, invariantMapSelection: types.PositionToAARList, cellValue: number, bound: DG.Rect): void {
|
|
81
|
+
canvasContext.font = '13px Roboto, Roboto Local, sans-serif';
|
|
82
|
+
canvasContext.textAlign = 'center';
|
|
83
|
+
canvasContext.textBaseline = 'middle';
|
|
84
|
+
canvasContext.fillStyle = '#000';
|
|
85
|
+
canvasContext.fillText(cellValue.toString(), bound.x + (bound.width / 2), bound.y + (bound.height / 2), bound.width);
|
|
86
|
+
|
|
87
|
+
const aarSelection = invariantMapSelection[currentPosition];
|
|
88
|
+
if (aarSelection && aarSelection.includes(currentAAR))
|
|
89
|
+
renderCellSelection(canvasContext, bound);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function renderLogoSummaryCell(canvasContext: CanvasRenderingContext2D, cellValue: number,
|
|
93
|
+
clusterSelection: number[], bound: DG.Rect): void {
|
|
94
|
+
canvasContext.font = '13px Roboto, Roboto Local, sans-serif';
|
|
95
|
+
canvasContext.textAlign = 'center';
|
|
96
|
+
canvasContext.textBaseline = 'middle';
|
|
97
|
+
canvasContext.fillStyle = '#000';
|
|
98
|
+
canvasContext.fillText(cellValue.toString(), bound.x + (bound.width / 2), bound.y + (bound.height / 2), bound.width);
|
|
99
|
+
|
|
100
|
+
if (clusterSelection.includes(cellValue))
|
|
101
|
+
renderCellSelection(canvasContext, bound);
|
|
122
102
|
}
|
|
123
103
|
|
|
124
104
|
export function renderBarchart(ctx: CanvasRenderingContext2D, col: DG.Column, monomerColStats: types.MonomerColStats,
|
package/src/utils/constants.ts
CHANGED
|
@@ -9,6 +9,8 @@ export enum COLUMNS_NAMES {
|
|
|
9
9
|
MEAN_DIFFERENCE = 'Mean difference',
|
|
10
10
|
COUNT = 'Count',
|
|
11
11
|
RATIO = 'Ratio',
|
|
12
|
+
CLUSTERS = 'clusters',
|
|
13
|
+
MACROMOLECULE = 'macromolecule',
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export enum CATEGORIES {
|
|
@@ -17,11 +19,16 @@ export enum CATEGORIES {
|
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export enum TAGS {
|
|
20
|
-
|
|
21
|
-
POSITION = '
|
|
22
|
+
MONOMER = 'monomer',
|
|
23
|
+
POSITION = 'pos',
|
|
22
24
|
SEPARATOR = 'separator',
|
|
23
25
|
SELECTION = 'selection',
|
|
24
26
|
ALPHABET = 'alphabet',
|
|
27
|
+
FILTER = 'filter',
|
|
28
|
+
CLUSTERS = 'clusters',
|
|
29
|
+
SAR_MODE = 'sarMode',
|
|
30
|
+
CLUSTER_SELECTION = 'clusterSelection',
|
|
31
|
+
VISIBLE = 'visible',
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
export enum SEM_TYPES {
|
package/src/utils/misc.ts
CHANGED
|
@@ -32,38 +32,33 @@ export function getSeparator(col: DG.Column<string>): string {
|
|
|
32
32
|
return col.getTag(C.TAGS.SEPARATOR) ?? '';
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export function scaleActivity(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
let currentActivityColName = originalActivityName ?? C.COLUMNS_NAMES.ACTIVITY;
|
|
39
|
-
const flag = df.columns.names().includes(currentActivityColName) &&
|
|
40
|
-
currentActivityColName === originalActivityName;
|
|
41
|
-
currentActivityColName = flag ? currentActivityColName : C.COLUMNS_NAMES.ACTIVITY;
|
|
42
|
-
const tempDf = df.clone(cloneBitset ? df.filter : null, [currentActivityColName]);
|
|
35
|
+
export function scaleActivity(activityScaling: string, activityCol: DG.Column<number>, indexes?: number[],
|
|
36
|
+
): [DG.DataFrame, (x: number) => number, string] {
|
|
37
|
+
const tempDf = DG.DataFrame.create(activityCol.length);
|
|
43
38
|
|
|
44
|
-
let formula = (
|
|
39
|
+
let formula = (x: number): number => x;
|
|
45
40
|
let newColName = 'activity';
|
|
46
41
|
switch (activityScaling) {
|
|
47
42
|
case 'none':
|
|
48
43
|
break;
|
|
49
44
|
case 'lg':
|
|
50
|
-
formula = (
|
|
45
|
+
formula = (x: number): number => Math.log10(x);
|
|
51
46
|
newColName = `Log10(${newColName})`;
|
|
52
47
|
break;
|
|
53
48
|
case '-lg':
|
|
54
|
-
formula = (
|
|
49
|
+
formula = (x: number): number => -Math.log10(x);
|
|
55
50
|
newColName = `-Log10(${newColName})`;
|
|
56
51
|
break;
|
|
57
52
|
default:
|
|
58
53
|
throw new Error(`ScalingError: method \`${activityScaling}\` is not available.`);
|
|
59
54
|
}
|
|
55
|
+
tempDf.columns.addNewVirtual(
|
|
56
|
+
C.COLUMNS_NAMES.ACTIVITY_SCALED, (i) => {
|
|
57
|
+
const val = activityCol.get(indexes ? indexes[i] : i);
|
|
58
|
+
return val ? formula(val) : val;
|
|
59
|
+
}, DG.TYPE.FLOAT);
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
const activityCol = df.getCol(currentActivityColName);
|
|
63
|
-
asCol.init((i) => formula(activityCol.get(i)));
|
|
64
|
-
df.tags['scaling'] = activityScaling;
|
|
65
|
-
|
|
66
|
-
return [tempDf, newColName];
|
|
61
|
+
return [tempDf, formula, newColName];
|
|
67
62
|
}
|
|
68
63
|
|
|
69
64
|
export function calculateBarsData(columns: DG.Column<string>[], selection: DG.BitSet): type.MonomerDfStats {
|
|
@@ -44,7 +44,8 @@ export async function createPeptideSimilaritySpaceViewer(
|
|
|
44
44
|
const pi = DG.TaskBarProgressIndicator.create('Creating embedding...');
|
|
45
45
|
|
|
46
46
|
const axesNames = ['~X', '~Y', '~MW'];
|
|
47
|
-
col ??= table.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
|
|
47
|
+
// col ??= table.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
|
|
48
|
+
col ??= table.getCol(C.COLUMNS_NAMES.MACROMOLECULE);
|
|
48
49
|
const columnData = col.toList().map((v) => AlignedSequenceEncoder.clean(v));
|
|
49
50
|
|
|
50
51
|
const reduceDimRes: IReduceDimensionalityResult = await createDimensinalityReducingWorker(
|
package/src/utils/types.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type DataFrameDict = {[key: string]: DG.DataFrame};
|
|
|
5
5
|
export type UTypedArray = Uint8Array | Uint16Array | Uint32Array;
|
|
6
6
|
//AAR: (Position: (index: indexList))
|
|
7
7
|
export type SubstitutionsInfo = Map<string, Map<string, Map<number, number[] | UTypedArray>>>;
|
|
8
|
-
export type
|
|
8
|
+
export type PositionToAARList = {[postiton: string]: string[]};
|
|
9
9
|
|
|
10
10
|
export type HELMMonomer = {at: {[key: string]: string}, id: string, m: string, na: string, n: string, rs: number};
|
|
11
11
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as ui from 'datagrok-api/ui';
|
|
2
|
+
import * as DG from 'datagrok-api/dg';
|
|
3
|
+
|
|
4
|
+
import $ from 'cash-dom';
|
|
5
|
+
import {PeptidesModel} from '../model';
|
|
6
|
+
|
|
7
|
+
export class LogoSummary extends DG.JsViewer {
|
|
8
|
+
_titleHost = ui.divText('Logo Summary Table', {id: 'pep-viewer-title'});
|
|
9
|
+
model!: PeptidesModel;
|
|
10
|
+
viewerGrid!: DG.Grid;
|
|
11
|
+
initialized: boolean = false;
|
|
12
|
+
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async onTableAttached(): Promise<void> {
|
|
18
|
+
super.onTableAttached();
|
|
19
|
+
|
|
20
|
+
this.model = await PeptidesModel.getInstance(this.dataFrame);
|
|
21
|
+
|
|
22
|
+
this.subs.push(this.model.onLogoSummaryGridChanged.subscribe((grid) => {
|
|
23
|
+
this.viewerGrid = grid;
|
|
24
|
+
this.render();
|
|
25
|
+
}));
|
|
26
|
+
this.model.updateDefault();
|
|
27
|
+
this.viewerGrid = this.model.logoSummaryGrid;
|
|
28
|
+
this.initialized = true;
|
|
29
|
+
this.render();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
detach(): void {this.subs.forEach((sub) => sub.unsubscribe());}
|
|
33
|
+
|
|
34
|
+
render(): void {
|
|
35
|
+
if (this.initialized) {
|
|
36
|
+
$(this.root).empty();
|
|
37
|
+
this.viewerGrid.root.style.width = 'auto';
|
|
38
|
+
this.root.appendChild(ui.divV([this._titleHost, this.viewerGrid.root]));
|
|
39
|
+
this.viewerGrid.invalidate();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -61,8 +61,9 @@ export class PeptideSpaceViewer extends DG.JsViewer {
|
|
|
61
61
|
this.isEmbeddingCreating = true;
|
|
62
62
|
$(this.root).empty();
|
|
63
63
|
const viewerHost = ui.waitBox(async () => {
|
|
64
|
-
const aligendSeqCol = this.dataFrame.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
|
|
65
|
-
const
|
|
64
|
+
// const aligendSeqCol = this.dataFrame.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
|
|
65
|
+
const alignedSeqCol = this.dataFrame.getCol(C.COLUMNS_NAMES.MACROMOLECULE);
|
|
66
|
+
const edf = await computeWeights(this.dataFrame, this.method, this.measure, this.cyclesCount, alignedSeqCol);
|
|
66
67
|
this.dataFrame.temp[C.EMBEDDING_STATUS] = true;
|
|
67
68
|
this.model.edf = edf;
|
|
68
69
|
|
|
@@ -92,7 +93,7 @@ export class PeptideSpaceViewer extends DG.JsViewer {
|
|
|
92
93
|
if (idx != -1) {
|
|
93
94
|
const table = ui.tableFromMap({
|
|
94
95
|
'Activity': colorCol.get(idx),
|
|
95
|
-
'Sequence':
|
|
96
|
+
'Sequence': alignedSeqCol.get(idx),
|
|
96
97
|
'Row ID': idx,
|
|
97
98
|
});
|
|
98
99
|
ui.tooltip.show(table, ev.clientX, ev.clientY);
|
|
@@ -117,7 +118,8 @@ export async function computeWeights(
|
|
|
117
118
|
let edf: DG.DataFrame | null = null;
|
|
118
119
|
try {
|
|
119
120
|
const axesNames = ['~X', '~Y', '~MW'];
|
|
120
|
-
col ??= table.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
|
|
121
|
+
// col ??= table.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
|
|
122
|
+
col ??= table.getCol(C.COLUMNS_NAMES.MACROMOLECULE);
|
|
121
123
|
const columnData = col.toList().map((v) => AlignedSequenceEncoder.clean(v));
|
|
122
124
|
|
|
123
125
|
const reduceDimRes: IReduceDimensionalityResult = await createDimensinalityReducingWorker(
|
|
@@ -20,6 +20,8 @@ export class SARViewerBase extends DG.JsViewer {
|
|
|
20
20
|
_titleHost = ui.divText('SAR Viewer', {id: 'pep-viewer-title'});
|
|
21
21
|
initialized = false;
|
|
22
22
|
isPropertyChanging: boolean = false;
|
|
23
|
+
_isVertical = false;
|
|
24
|
+
isModeChanging = false;
|
|
23
25
|
|
|
24
26
|
constructor() {
|
|
25
27
|
super();
|
|
@@ -30,6 +32,8 @@ export class SARViewerBase extends DG.JsViewer {
|
|
|
30
32
|
this.minActivityDelta = this.float('minActivityDelta', 0);
|
|
31
33
|
}
|
|
32
34
|
|
|
35
|
+
get name(): string {return '';}
|
|
36
|
+
|
|
33
37
|
async onTableAttached(): Promise<void> {
|
|
34
38
|
super.onTableAttached();
|
|
35
39
|
this.sourceGrid = this.view?.grid ?? (grok.shell.v as DG.TableView).grid;
|
|
@@ -49,14 +53,56 @@ export class SARViewerBase extends DG.JsViewer {
|
|
|
49
53
|
|
|
50
54
|
detach(): void {this.subs.forEach((sub) => sub.unsubscribe());}
|
|
51
55
|
|
|
56
|
+
get state(): string {
|
|
57
|
+
return this.dataFrame.getTag(C.TAGS.SAR_MODE) ?? '10';
|
|
58
|
+
}
|
|
59
|
+
set state(s: string) {
|
|
60
|
+
this.dataFrame.setTag(C.TAGS.SAR_MODE, s);
|
|
61
|
+
}
|
|
62
|
+
|
|
52
63
|
render(refreshOnly = false): void {
|
|
53
64
|
if (!this.initialized)
|
|
54
65
|
return;
|
|
55
66
|
if (!refreshOnly) {
|
|
56
67
|
$(this.root).empty();
|
|
68
|
+
let switchHost = ui.div();
|
|
69
|
+
if (this.name == 'MC') {
|
|
70
|
+
const mutationCliffsMode = ui.boolInput('', this.state[0] === '1', () => {
|
|
71
|
+
if (this.isModeChanging)
|
|
72
|
+
return;
|
|
73
|
+
this.isModeChanging = true;
|
|
74
|
+
invariantMapMode.value = !invariantMapMode.value;
|
|
75
|
+
this.isModeChanging = false;
|
|
76
|
+
this._titleHost.innerText = 'Mutation Cliffs';
|
|
77
|
+
this.model.isInvariantMap = false;
|
|
78
|
+
this.viewerGrid.invalidate();
|
|
79
|
+
});
|
|
80
|
+
mutationCliffsMode.addPostfix('Mutation Cliffs');
|
|
81
|
+
const invariantMapMode = ui.boolInput('', this.state[1] === '1', () => {
|
|
82
|
+
if (this.isModeChanging)
|
|
83
|
+
return;
|
|
84
|
+
this.isModeChanging = true;
|
|
85
|
+
mutationCliffsMode.value = !mutationCliffsMode.value;
|
|
86
|
+
this.isModeChanging = false;
|
|
87
|
+
this._titleHost.innerText = 'Invariant Map';
|
|
88
|
+
this.model.isInvariantMap = true;
|
|
89
|
+
this.viewerGrid.invalidate();
|
|
90
|
+
});
|
|
91
|
+
invariantMapMode.addPostfix('Invariant Map');
|
|
92
|
+
const setDefaultProperties = (input: DG.InputBase): void => {
|
|
93
|
+
$(input.root).find('.ui-input-editor').css('margin', '0px').attr('type', 'radio');
|
|
94
|
+
$(input.root).find('.ui-input-description').css('padding', '0px').css('padding-left', '5px');
|
|
95
|
+
};
|
|
96
|
+
setDefaultProperties(mutationCliffsMode);
|
|
97
|
+
setDefaultProperties(invariantMapMode);
|
|
98
|
+
$(mutationCliffsMode.root).css('padding-right', '10px').css('padding-left', '5px');
|
|
99
|
+
|
|
100
|
+
switchHost = ui.divH([mutationCliffsMode.root, invariantMapMode.root]);
|
|
101
|
+
switchHost.style.position = 'absolute';
|
|
102
|
+
}
|
|
57
103
|
const viewerRoot = this.viewerGrid.root;
|
|
58
104
|
viewerRoot.style.width = 'auto';
|
|
59
|
-
this.root.appendChild(ui.divV([this._titleHost, viewerRoot]));
|
|
105
|
+
this.root.appendChild(ui.divV([ui.divH([switchHost, this._titleHost]), viewerRoot]));
|
|
60
106
|
}
|
|
61
107
|
this.viewerGrid?.invalidate();
|
|
62
108
|
}
|
|
@@ -88,9 +134,10 @@ export class SARViewerBase extends DG.JsViewer {
|
|
|
88
134
|
/**
|
|
89
135
|
* Structure-activity relationship viewer.
|
|
90
136
|
*/
|
|
91
|
-
export class
|
|
137
|
+
export class MutationCliffsViewer extends SARViewerBase {
|
|
92
138
|
_titleHost = ui.divText('Mutation Cliffs', {id: 'pep-viewer-title'});
|
|
93
|
-
_name = '
|
|
139
|
+
_name = 'MC';
|
|
140
|
+
_isVertical = false;
|
|
94
141
|
|
|
95
142
|
constructor() {super();}
|
|
96
143
|
|
|
@@ -98,26 +145,29 @@ export class SARViewer extends SARViewerBase {
|
|
|
98
145
|
|
|
99
146
|
async onTableAttached(): Promise<void> {
|
|
100
147
|
await super.onTableAttached();
|
|
101
|
-
this.model.
|
|
148
|
+
this.model.mutationCliffsViewer ??= this;
|
|
102
149
|
|
|
103
|
-
this.subs.push(this.model.
|
|
150
|
+
this.subs.push(this.model.onMutationCliffsGridChanged.subscribe((data) => {
|
|
104
151
|
this.viewerGrid = data;
|
|
105
152
|
this.render();
|
|
106
153
|
}));
|
|
107
154
|
|
|
108
155
|
this.model.updateDefault();
|
|
109
|
-
this.viewerGrid = this.model.
|
|
156
|
+
this.viewerGrid = this.model.mutationCliffsGrid;
|
|
110
157
|
this.initialized = true;
|
|
111
158
|
this.render();
|
|
112
159
|
}
|
|
113
160
|
|
|
114
|
-
isInitialized(): DG.Grid {return this.model?.
|
|
161
|
+
isInitialized(): DG.Grid {return this.model?.mutationCliffsGrid;}
|
|
115
162
|
|
|
116
163
|
//1. debouncing in rxjs; 2. flags?
|
|
117
164
|
onPropertyChanged(property: DG.Property): void {
|
|
118
165
|
if (!this.isInitialized() || IS_PROPERTY_CHANGING)
|
|
119
166
|
return;
|
|
120
167
|
|
|
168
|
+
if (property.name == 'invariantMap')
|
|
169
|
+
this._titleHost = ui.divText(property.get(this) ? 'Invariant Map' : 'Mutation Cliffs', {id: 'pep-viewer-title'});
|
|
170
|
+
|
|
121
171
|
super.onPropertyChanged(property);
|
|
122
172
|
IS_PROPERTY_CHANGING = true;
|
|
123
173
|
this.model.syncProperties(true);
|
|
@@ -126,9 +176,10 @@ export class SARViewer extends SARViewerBase {
|
|
|
126
176
|
}
|
|
127
177
|
|
|
128
178
|
/** Vertical structure activity relationship viewer. */
|
|
129
|
-
export class
|
|
130
|
-
_name = '
|
|
179
|
+
export class MostPotentResiduesViewer extends SARViewerBase {
|
|
180
|
+
_name = 'MPR';
|
|
131
181
|
_titleHost = ui.divText('Most Potent Residues', {id: 'pep-viewer-title'});
|
|
182
|
+
_isVertical = true;
|
|
132
183
|
|
|
133
184
|
constructor() {
|
|
134
185
|
super();
|
|
@@ -138,21 +189,21 @@ export class SARViewerVertical extends SARViewerBase {
|
|
|
138
189
|
|
|
139
190
|
async onTableAttached(): Promise<void> {
|
|
140
191
|
await super.onTableAttached();
|
|
141
|
-
this.model.
|
|
192
|
+
this.model.mostPotentResiduesViewer ??= this;
|
|
142
193
|
|
|
143
|
-
this.subs.push(this.model.
|
|
194
|
+
this.subs.push(this.model.onMostPotentResiduesGridChanged.subscribe((data) => {
|
|
144
195
|
this.viewerGrid = data;
|
|
145
196
|
this.render();
|
|
146
197
|
}));
|
|
147
198
|
|
|
148
199
|
this.model.updateDefault();
|
|
149
|
-
this.viewerGrid = this.model.
|
|
200
|
+
this.viewerGrid = this.model.mostPotentResiduesGrid;
|
|
150
201
|
|
|
151
202
|
this.initialized = true;
|
|
152
203
|
this.render();
|
|
153
204
|
}
|
|
154
205
|
|
|
155
|
-
isInitialized(): DG.Grid {return this.model?.
|
|
206
|
+
isInitialized(): DG.Grid {return this.model?.mostPotentResiduesGrid;}
|
|
156
207
|
|
|
157
208
|
onPropertyChanged(property: DG.Property): void {
|
|
158
209
|
if (!this.isInitialized() || IS_PROPERTY_CHANGING)
|