@datagrok/peptides 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package-test.js +2843 -3472
- package/dist/package.js +2643 -3294
- package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +1673 -1673
- package/package.json +7 -3
- package/src/model.ts +210 -92
- package/src/package.ts +3 -2
- package/src/tests/core.ts +8 -7
- package/src/utils/cell-renderer.ts +12 -0
- package/src/utils/constants.ts +7 -3
- package/src/utils/misc.ts +12 -17
- package/src/utils/peptide-similarity-space.ts +2 -1
- package/src/viewers/logo-summary.ts +5 -5
- package/src/viewers/peptide-space-viewer.ts +6 -4
- package/src/viewers/sar-viewer.ts +39 -6
- package/src/widgets/distribution.ts +25 -10
- package/src/widgets/mutation-cliffs.ts +2 -1
- package/src/widgets/{analyze-peptides.ts → peptides.ts} +50 -31
- package/{test-Peptides-7770371320b2-8cac318e.html → test-Peptides-916a90d7d48b-ea373bf5.html} +37 -7
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,10 +35,10 @@ 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, null, simpleTable,
|
|
41
|
+
simpleActivityCol, simpleAlignedSeqCol, null, simpleTable, scalingFormula, simpleScaledColName, '-lg', []);
|
|
41
42
|
expect(model instanceof PeptidesModel, true);
|
|
42
43
|
|
|
43
44
|
if (model != null) {
|
|
@@ -56,10 +57,10 @@ 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, null, complexTable,
|
|
63
|
+
complexActivityCol, complexAlignedSeqCol, null, complexTable, scalingFormula, complexScaledColName, '-lg', []);
|
|
63
64
|
expect(model instanceof PeptidesModel, true);
|
|
64
65
|
|
|
65
66
|
if (model != null) {
|
|
@@ -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, null, 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();
|
|
@@ -89,6 +89,18 @@ export function renderInvaraintMapCell(canvasContext: CanvasRenderingContext2D,
|
|
|
89
89
|
renderCellSelection(canvasContext, bound);
|
|
90
90
|
}
|
|
91
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);
|
|
102
|
+
}
|
|
103
|
+
|
|
92
104
|
export function renderBarchart(ctx: CanvasRenderingContext2D, col: DG.Column, monomerColStats: types.MonomerColStats,
|
|
93
105
|
bounds: DG.Rect, max: number): types.BarCoordinates {
|
|
94
106
|
let sum = col.length - (monomerColStats['-']?.count ?? 0);
|
package/src/utils/constants.ts
CHANGED
|
@@ -9,7 +9,8 @@ export enum COLUMNS_NAMES {
|
|
|
9
9
|
MEAN_DIFFERENCE = 'Mean difference',
|
|
10
10
|
COUNT = 'Count',
|
|
11
11
|
RATIO = 'Ratio',
|
|
12
|
-
CLUSTERS = '
|
|
12
|
+
CLUSTERS = 'clusters',
|
|
13
|
+
MACROMOLECULE = 'macromolecule',
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export enum CATEGORIES {
|
|
@@ -18,13 +19,16 @@ export enum CATEGORIES {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export enum TAGS {
|
|
21
|
-
|
|
22
|
-
POSITION = '
|
|
22
|
+
MONOMER = 'monomer',
|
|
23
|
+
POSITION = 'pos',
|
|
23
24
|
SEPARATOR = 'separator',
|
|
24
25
|
SELECTION = 'selection',
|
|
25
26
|
ALPHABET = 'alphabet',
|
|
26
27
|
FILTER = 'filter',
|
|
27
28
|
CLUSTERS = 'clusters',
|
|
29
|
+
SAR_MODE = 'sarMode',
|
|
30
|
+
CLUSTER_SELECTION = 'clusterSelection',
|
|
31
|
+
VISIBLE = 'visible',
|
|
28
32
|
}
|
|
29
33
|
|
|
30
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(
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import * as grok from 'datagrok-api/grok';
|
|
2
1
|
import * as ui from 'datagrok-api/ui';
|
|
3
2
|
import * as DG from 'datagrok-api/dg';
|
|
4
3
|
|
|
5
4
|
import $ from 'cash-dom';
|
|
6
|
-
import * as C from '../utils/constants';
|
|
7
5
|
import {PeptidesModel} from '../model';
|
|
8
6
|
|
|
9
7
|
export class LogoSummary extends DG.JsViewer {
|
|
8
|
+
_titleHost = ui.divText('Logo Summary Table', {id: 'pep-viewer-title'});
|
|
10
9
|
model!: PeptidesModel;
|
|
11
10
|
viewerGrid!: DG.Grid;
|
|
12
11
|
initialized: boolean = false;
|
|
@@ -19,7 +18,7 @@ export class LogoSummary extends DG.JsViewer {
|
|
|
19
18
|
super.onTableAttached();
|
|
20
19
|
|
|
21
20
|
this.model = await PeptidesModel.getInstance(this.dataFrame);
|
|
22
|
-
|
|
21
|
+
|
|
23
22
|
this.subs.push(this.model.onLogoSummaryGridChanged.subscribe((grid) => {
|
|
24
23
|
this.viewerGrid = grid;
|
|
25
24
|
this.render();
|
|
@@ -30,12 +29,13 @@ export class LogoSummary extends DG.JsViewer {
|
|
|
30
29
|
this.render();
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
detach(): void {this.subs.forEach(sub => sub.unsubscribe());}
|
|
32
|
+
detach(): void {this.subs.forEach((sub) => sub.unsubscribe());}
|
|
34
33
|
|
|
35
34
|
render(): void {
|
|
36
35
|
if (this.initialized) {
|
|
37
36
|
$(this.root).empty();
|
|
38
|
-
this.root.
|
|
37
|
+
this.viewerGrid.root.style.width = 'auto';
|
|
38
|
+
this.root.appendChild(ui.divV([this._titleHost, this.viewerGrid.root]));
|
|
39
39
|
this.viewerGrid.invalidate();
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -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(
|
|
@@ -21,6 +21,7 @@ export class SARViewerBase extends DG.JsViewer {
|
|
|
21
21
|
initialized = false;
|
|
22
22
|
isPropertyChanging: boolean = false;
|
|
23
23
|
_isVertical = false;
|
|
24
|
+
isModeChanging = false;
|
|
24
25
|
|
|
25
26
|
constructor() {
|
|
26
27
|
super();
|
|
@@ -52,20 +53,52 @@ export class SARViewerBase extends DG.JsViewer {
|
|
|
52
53
|
|
|
53
54
|
detach(): void {this.subs.forEach((sub) => sub.unsubscribe());}
|
|
54
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
|
+
|
|
55
63
|
render(refreshOnly = false): void {
|
|
56
64
|
if (!this.initialized)
|
|
57
65
|
return;
|
|
58
66
|
if (!refreshOnly) {
|
|
59
67
|
$(this.root).empty();
|
|
60
|
-
|
|
68
|
+
let switchHost = ui.div();
|
|
61
69
|
if (this.name == 'MC') {
|
|
62
|
-
const
|
|
63
|
-
this.
|
|
64
|
-
|
|
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;
|
|
65
89
|
this.viewerGrid.invalidate();
|
|
66
90
|
});
|
|
67
|
-
|
|
68
|
-
|
|
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';
|
|
69
102
|
}
|
|
70
103
|
const viewerRoot = this.viewerGrid.root;
|
|
71
104
|
viewerRoot.style.width = 'auto';
|
|
@@ -15,6 +15,10 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
15
15
|
const activityScaledCol = table.columns.bySemType(C.SEM_TYPES.ACTIVITY_SCALED)!;
|
|
16
16
|
const rowCount = activityScaledCol.length;
|
|
17
17
|
const selectionObject = model.mutationCliffsSelection;
|
|
18
|
+
let isMutationCliffsSelectionEmpty = true;
|
|
19
|
+
for (const aarList of Object.values(selectionObject))
|
|
20
|
+
isMutationCliffsSelectionEmpty &&= aarList.length === 0;
|
|
21
|
+
const clustersObject = model.logoSummarySelection;
|
|
18
22
|
const positions = Object.keys(selectionObject);
|
|
19
23
|
const positionsLen = positions.length;
|
|
20
24
|
let aarStr = allConst;
|
|
@@ -29,12 +33,16 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
29
33
|
otherStr = otherConst;
|
|
30
34
|
for (const position of positions) {
|
|
31
35
|
const posCol = table.getCol(position);
|
|
32
|
-
|
|
36
|
+
const aarList = selectionObject[position];
|
|
37
|
+
if (aarList.length === 0)
|
|
38
|
+
continue;
|
|
39
|
+
|
|
40
|
+
for (const aar of aarList) {
|
|
33
41
|
aarStr = `${position} : ${aar}`;
|
|
34
42
|
const splitCol = DG.Column.bool(C.COLUMNS_NAMES.SPLIT_COL, rowCount).init((i) => posCol.get(i) == aar);
|
|
35
43
|
|
|
36
44
|
const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
|
|
37
|
-
const currentStatsDf = model.
|
|
45
|
+
const currentStatsDf = model.monomerPositionStatsDf.rows.match({Pos: position, AAR: aar}).toDataFrame();
|
|
38
46
|
const stats: Stats = {
|
|
39
47
|
count: currentStatsDf.get(C.COLUMNS_NAMES.COUNT, 0),
|
|
40
48
|
ratio: currentStatsDf.get(C.COLUMNS_NAMES.RATIO, 0),
|
|
@@ -49,10 +57,13 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
49
57
|
}
|
|
50
58
|
} else if (splitByPosition.value) {
|
|
51
59
|
otherStr = otherConst;
|
|
52
|
-
const activityScaledData = activityScaledCol.
|
|
60
|
+
const activityScaledData = activityScaledCol.toList();
|
|
53
61
|
for (const position of positions) {
|
|
54
62
|
const posCol = table.getCol(position);
|
|
55
63
|
const aarList = selectionObject[position];
|
|
64
|
+
if (aarList.length === 0)
|
|
65
|
+
continue;
|
|
66
|
+
|
|
56
67
|
aarStr = `${position}: {${aarList.join(', ')}}`;
|
|
57
68
|
|
|
58
69
|
const mask = DG.BitSet.create(rowCount, (i) => aarList.includes(posCol.get(i)));
|
|
@@ -80,7 +91,7 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
80
91
|
}
|
|
81
92
|
|
|
82
93
|
otherStr = otherConst;
|
|
83
|
-
const activityScaledData = activityScaledCol.
|
|
94
|
+
const activityScaledData = activityScaledCol.toList();
|
|
84
95
|
for (const aar of aars) {
|
|
85
96
|
const posList = reversedSelectionObject[aar];
|
|
86
97
|
aarStr = `${aar}: {${posList.join(', ')}}`;
|
|
@@ -112,14 +123,18 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
112
123
|
otherStr = otherConst;
|
|
113
124
|
} else if (positionsLen) {
|
|
114
125
|
aarStr = '';
|
|
115
|
-
for (const position of positions)
|
|
116
|
-
|
|
117
|
-
|
|
126
|
+
for (const position of positions) {
|
|
127
|
+
const aarList = selectionObject[position];
|
|
128
|
+
if (aarList.length !== 0)
|
|
129
|
+
aarStr += `${position}: {${aarList.join(', ')}}; `;
|
|
130
|
+
}
|
|
131
|
+
if (clustersObject.length !== 0)
|
|
132
|
+
aarStr += `Clusters: ${clustersObject.join(', ')}`;
|
|
118
133
|
otherStr = otherConst;
|
|
119
134
|
}
|
|
120
135
|
|
|
121
136
|
const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
|
|
122
|
-
const stats = getStats(activityScaledCol.
|
|
137
|
+
const stats = getStats(activityScaledCol.toList(), table.selection);
|
|
123
138
|
const distributionRoot = getDistributionAndStats(distributionTable, stats, aarStr, otherStr);
|
|
124
139
|
$(distributionRoot).addClass('d4-flex-col');
|
|
125
140
|
|
|
@@ -130,9 +145,9 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
130
145
|
};
|
|
131
146
|
|
|
132
147
|
const setDefaultProperties = (input: DG.InputBase): void => {
|
|
133
|
-
input.enabled =
|
|
148
|
+
input.enabled = !isMutationCliffsSelectionEmpty;
|
|
134
149
|
$(input.root).find('.ui-input-editor').css('margin', '0px');
|
|
135
|
-
$(input.root).find('.ui-input-description').css('padding', '0px');
|
|
150
|
+
$(input.root).find('.ui-input-description').css('padding', '0px').css('padding-left', '5px');
|
|
136
151
|
};
|
|
137
152
|
|
|
138
153
|
const splitByPosition = ui.boolInput('', model.splitByPos, updateDistributionHost);
|
|
@@ -16,7 +16,8 @@ export function mutationCliffsWidget(table: DG.DataFrame, model: PeptidesModel):
|
|
|
16
16
|
const substitutionsArray: string[] = [];
|
|
17
17
|
const deltaArray: number[] = [];
|
|
18
18
|
const substitutedToArray: string[] = [];
|
|
19
|
-
const alignedSeqCol = table.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
|
|
19
|
+
// const alignedSeqCol = table.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
|
|
20
|
+
const alignedSeqCol = table.getCol(C.COLUMNS_NAMES.MACROMOLECULE);
|
|
20
21
|
const activityScaledCol = table.columns.bySemType(C.SEM_TYPES.ACTIVITY_SCALED)!;
|
|
21
22
|
const seenIndexes = new Map<number, number[]>();
|
|
22
23
|
|
|
@@ -12,10 +12,10 @@ import {scaleActivity} from '../utils/misc';
|
|
|
12
12
|
|
|
13
13
|
/** Peptide analysis widget.
|
|
14
14
|
*
|
|
15
|
-
* @param {DG.DataFrame}
|
|
15
|
+
* @param {DG.DataFrame} df Working table
|
|
16
16
|
* @param {DG.Column} col Aligned sequence column
|
|
17
17
|
* @return {Promise<DG.Widget>} Widget containing peptide analysis */
|
|
18
|
-
export async function analyzePeptidesWidget(
|
|
18
|
+
export async function analyzePeptidesWidget(df: DG.DataFrame, col: DG.Column): Promise<DG.Widget> {
|
|
19
19
|
if (!col.tags['aligned']?.includes('MSA') && col.tags[DG.TAGS.UNITS].toLowerCase() != 'helm')
|
|
20
20
|
return new DG.Widget(ui.divText('Peptides analysis only works with aligned sequences'));
|
|
21
21
|
|
|
@@ -30,19 +30,27 @@ export async function analyzePeptidesWidget(currentDf: DG.DataFrame, col: DG.Col
|
|
|
30
30
|
let tempCol = null;
|
|
31
31
|
let scaledDf: DG.DataFrame;
|
|
32
32
|
let newScaledColName: string;
|
|
33
|
+
let scalingFormula: (x: number) => number;
|
|
33
34
|
|
|
34
|
-
for (const column of
|
|
35
|
+
for (const column of df.columns.numerical)
|
|
35
36
|
tempCol = column.type === DG.TYPE.FLOAT ? column : null;
|
|
36
37
|
|
|
37
|
-
const
|
|
38
|
+
const defaultActivityColumn: DG.Column<number> | null = df.col('activity') || df.col('IC50') || tempCol;
|
|
38
39
|
const histogramHost = ui.div([], {id: 'pep-hist-host'});
|
|
39
40
|
|
|
41
|
+
const indexes: number[] = [];
|
|
42
|
+
const f = df.filter;
|
|
43
|
+
df.onFilterChanged.subscribe(() => {
|
|
44
|
+
for (let i = 0; i < f.length; ++i) {
|
|
45
|
+
if (f.get(i))
|
|
46
|
+
indexes.push(i);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
40
49
|
const activityScalingMethod = ui.choiceInput(
|
|
41
50
|
'Scaling', 'none', ['none', 'lg', '-lg'],
|
|
42
51
|
async (currentMethod: string): Promise<void> => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
[scaledDf, newScaledColName] = scaleActivity(currentMethod, currentDf, currentActivityCol, true);
|
|
52
|
+
[scaledDf, scalingFormula, newScaledColName] =
|
|
53
|
+
scaleActivity(currentMethod, activityColumnChoice.value!, indexes.length !== 0 ? indexes : undefined);
|
|
46
54
|
|
|
47
55
|
const hist = scaledDf.plot.histogram({
|
|
48
56
|
filteringEnabled: false,
|
|
@@ -60,23 +68,23 @@ export async function analyzePeptidesWidget(currentDf: DG.DataFrame, col: DG.Col
|
|
|
60
68
|
|
|
61
69
|
const activityScalingMethodState = (_: any): void => {
|
|
62
70
|
activityScalingMethod.enabled = (activityColumnChoice.value ?? false) &&
|
|
63
|
-
DG.Stats.fromColumn(activityColumnChoice.value!,
|
|
71
|
+
DG.Stats.fromColumn(activityColumnChoice.value!, df.filter).min > 0;
|
|
64
72
|
activityScalingMethod.fireChanged();
|
|
65
73
|
};
|
|
66
|
-
const activityColumnChoice = ui.columnInput('Activity',
|
|
67
|
-
const clustersColumnChoice = ui.columnInput('Clusters',
|
|
74
|
+
const activityColumnChoice = ui.columnInput('Activity', df, defaultActivityColumn, activityScalingMethodState);
|
|
75
|
+
const clustersColumnChoice = ui.columnInput('Clusters', df, null);
|
|
68
76
|
activityColumnChoice.fireChanged();
|
|
69
77
|
activityScalingMethod.fireChanged();
|
|
70
78
|
|
|
71
79
|
const inputsList = [activityColumnChoice, activityScalingMethod, clustersColumnChoice];
|
|
72
80
|
|
|
73
81
|
const startBtn = ui.button('Launch SAR', async () => {
|
|
74
|
-
await startAnalysis(
|
|
75
|
-
|
|
82
|
+
await startAnalysis(activityColumnChoice.value, col, clustersColumnChoice.value, df, scalingFormula,
|
|
83
|
+
newScaledColName, activityScalingMethod.value ?? 'none', indexes);
|
|
76
84
|
});
|
|
77
85
|
startBtn.style.alignSelf = 'center';
|
|
78
86
|
|
|
79
|
-
const viewer = await
|
|
87
|
+
const viewer = await df.plot.fromType('WebLogo') as WebLogo;
|
|
80
88
|
viewer.root.style.setProperty('height', '130px');
|
|
81
89
|
const logoHost = ui.div();
|
|
82
90
|
$(logoHost).empty().append(viewer.root);
|
|
@@ -92,26 +100,36 @@ export async function analyzePeptidesWidget(currentDf: DG.DataFrame, col: DG.Col
|
|
|
92
100
|
);
|
|
93
101
|
}
|
|
94
102
|
|
|
95
|
-
export async function startAnalysis(
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
export async function startAnalysis(activityColumn: DG.Column<number> | null, peptidesCol: DG.Column<string>,
|
|
104
|
+
clustersColumn: DG.Column | null, currentDf: DG.DataFrame, scaleNum: (x: number) => number, newScaledColName: string,
|
|
105
|
+
scaling: string, indexes: number[]): Promise<PeptidesModel | null> {
|
|
98
106
|
const progress = DG.TaskBarProgressIndicator.create('Loading SAR...');
|
|
99
107
|
let model = null;
|
|
100
108
|
if (activityColumn?.type === DG.TYPE.FLOAT) {
|
|
101
|
-
const
|
|
102
|
-
const cloneColList = [alignedSeqCol.name, activityColumnName];
|
|
103
|
-
if (clustersColumn)
|
|
104
|
-
cloneColList.push(clustersColumn.name);
|
|
105
|
-
|
|
109
|
+
const f = currentDf.filter;
|
|
106
110
|
//prepare new DF
|
|
107
|
-
const newDf =
|
|
108
|
-
const
|
|
109
|
-
activityCol.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
const newDf = DG.DataFrame.create(f.trueCount);
|
|
112
|
+
const getIndex = indexes.length !== 0 ? (i: number) : number => indexes[i] : (i: number): number => i;
|
|
113
|
+
let activityCol: DG.Column<number> | null = null;
|
|
114
|
+
for (const col of currentDf.columns.toList()) {
|
|
115
|
+
let virtualCol: DG.Column<any>;
|
|
116
|
+
if (col === activityColumn) {
|
|
117
|
+
virtualCol = newDf.columns.addNewVirtual(
|
|
118
|
+
C.COLUMNS_NAMES.ACTIVITY, (i) => activityColumn.get(getIndex(i)!), DG.TYPE.FLOAT);
|
|
119
|
+
activityCol = virtualCol;
|
|
120
|
+
} else if (col === peptidesCol) {
|
|
121
|
+
virtualCol = newDf.columns.addNewVirtual(
|
|
122
|
+
C.COLUMNS_NAMES.MACROMOLECULE, (i) => peptidesCol.get(getIndex(i)!), DG.TYPE.STRING);
|
|
123
|
+
} else
|
|
124
|
+
virtualCol = newDf.columns.addNewVirtual(col.name, (i) => col.get(getIndex(i)!), col.type as DG.TYPE);
|
|
125
|
+
virtualCol.setTag(C.TAGS.VISIBLE, '0');
|
|
126
|
+
}
|
|
127
|
+
activityCol!.semType = C.SEM_TYPES.ACTIVITY;
|
|
128
|
+
const activityScaledCol = newDf.columns.addNewVirtual(C.COLUMNS_NAMES.ACTIVITY_SCALED, (i) => {
|
|
129
|
+
const val = activityCol!.get(getIndex(i)!);
|
|
130
|
+
return val ? scaleNum(val) : val;
|
|
131
|
+
}, DG.TYPE.FLOAT);
|
|
113
132
|
activityScaledCol.semType = C.SEM_TYPES.ACTIVITY_SCALED;
|
|
114
|
-
newDf.columns.add(activityScaledCol);
|
|
115
133
|
newDf.name = 'Peptides analysis';
|
|
116
134
|
newDf.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED] = newScaledColName;
|
|
117
135
|
if (clustersColumn) {
|
|
@@ -119,13 +137,14 @@ export async function startAnalysis(
|
|
|
119
137
|
newDf.tags[C.TAGS.CLUSTERS] = C.COLUMNS_NAMES.CLUSTERS;
|
|
120
138
|
}
|
|
121
139
|
// newDf.tags[C.PEPTIDES_ANALYSIS] = 'true';
|
|
140
|
+
newDf.tags['scaling'] = scaling;
|
|
122
141
|
|
|
123
142
|
let monomerType = 'HELM_AA';
|
|
124
|
-
if (
|
|
125
|
-
const sampleSeq =
|
|
143
|
+
if (peptidesCol.getTag(DG.TAGS.UNITS).toLowerCase() == 'helm') {
|
|
144
|
+
const sampleSeq = peptidesCol.get(0)!;
|
|
126
145
|
monomerType = sampleSeq.startsWith('PEPTIDE') ? 'HELM_AA' : 'HELM_BASE';
|
|
127
146
|
} else {
|
|
128
|
-
const alphabet =
|
|
147
|
+
const alphabet = peptidesCol.tags[C.TAGS.ALPHABET];
|
|
129
148
|
monomerType = alphabet == 'DNA' || alphabet == 'RNA' ? 'HELM_BASE' : 'HELM_AA';
|
|
130
149
|
}
|
|
131
150
|
|
package/{test-Peptides-7770371320b2-8cac318e.html → test-Peptides-916a90d7d48b-ea373bf5.html}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<html><head><meta charset="utf-8"/><title>Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=
|
|
1
|
+
<html><head><meta charset="utf-8"/><title>Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=916a90d7d48b. Commit ea373bf5.</title><style type="text/css">html,
|
|
2
2
|
body {
|
|
3
3
|
font-family: Arial, Helvetica, sans-serif;
|
|
4
4
|
font-size: 1rem;
|
|
@@ -229,11 +229,14 @@ header {
|
|
|
229
229
|
font-size: 1rem;
|
|
230
230
|
padding: 0 0.5rem;
|
|
231
231
|
}
|
|
232
|
-
</style></head><body><div id="jesthtml-content"><header><h1 id="title">Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
at
|
|
232
|
+
</style></head><body><div id="jesthtml-content"><header><h1 id="title">Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=916a90d7d48b. Commit ea373bf5.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-10-13 13:02:52</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts</div><div class="suite-time warn">89.905s</div></div><div class="suite-tests"><div class="test-result failed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">failed</div><div class="test-duration">73.37s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: Test result : Failed : 501 : Peptides.Core.Start analysis: simple : Unable to get project asset "getMonomerLib"
|
|
233
|
+
Test result : Failed : 438 : Peptides.Core.Start analysis: сomplex : Unable to get project asset "getMonomerLib"
|
|
234
|
+
Test result : Failed : 431 : Peptides.Core.Save and load project : Unable to get project asset "getMonomerLib"
|
|
235
|
+
|
|
236
|
+
at /home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:68:20
|
|
237
|
+
at Generator.next (<anonymous>)
|
|
238
|
+
at fulfilled (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:31:58)
|
|
239
|
+
at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.<anonymous> (/home/runner/work/public/public/packages/Peptides/src/__jest__/test-node.ts:62:11)
|
|
237
240
|
at Generator.next (<anonymous>)
|
|
238
241
|
at fulfilled (/home/runner/work/public/public/packages/Peptides/src/__jest__/test-node.ts:28:58)
|
|
239
242
|
at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Using web root: http://localhost:8080</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:40:11
|
|
@@ -243,4 +246,31 @@ header {
|
|
|
243
246
|
at Object.<anonymous>.__awaiter (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:30:12)
|
|
244
247
|
at Object.<anonymous> (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:38:23)
|
|
245
248
|
at Promise.then.completed (/home/runner/work/public/public/packages/Peptides/node_modules/jest-circus/build/utils.js:391:28)
|
|
246
|
-
at new Promise (<anonymous>)</pre><pre class="suite-consolelog-item-message">Testing Peptides package</pre></div
|
|
249
|
+
at new Promise (<anonymous>)</pre><pre class="suite-consolelog-item-message">Testing Peptides package</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:66:11
|
|
250
|
+
at Generator.next (<anonymous>)
|
|
251
|
+
at fulfilled (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:31:58)
|
|
252
|
+
at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Test result : Success : 0 : Peptides.Peptide space.test_table.is_not_empty : OK
|
|
253
|
+
Test result : Success : 6322 : Peptides.Peptide space.PeptideSimilaritySpaceWidget.is_drawing : OK
|
|
254
|
+
Test result : Success : 2 : Peptides.Peptide space.test_deminsionality_reducer : OK
|
|
255
|
+
Test result : Success : 1 : Peptides.Peptide space.test_peptide_similarity_space_viewer : OK
|
|
256
|
+
Test result : Success : 4207 : Peptides.Peptide space.peptide_space.DimensinalityReducer.UMAP.Levenshtein.is_numeric : OK
|
|
257
|
+
Test result : Success : 2954 : Peptides.Peptide space.peptide_space.DimensinalityReducer.UMAP.Jaro-Winkler.is_numeric : OK
|
|
258
|
+
Test result : Success : 3304 : Peptides.Peptide space.peptide_space.DimensinalityReducer.t-SNE.Levenshtein.is_numeric : OK
|
|
259
|
+
Test result : Success : 3696 : Peptides.Peptide space.peptide_space.DimensinalityReducer.t-SNE.Jaro-Winkler.is_numeric : OK
|
|
260
|
+
Test result : Success : 199 : Peptides.Peptide space.peptide_space.DimensinalityReducer.SPE.Levenshtein.is_numeric : OK
|
|
261
|
+
Test result : Success : 803 : Peptides.Peptide space.peptide_space.DimensinalityReducer.SPE.Jaro-Winkler.is_numeric : OK
|
|
262
|
+
Test result : Success : 166 : Peptides.Peptide space.peptide_space.DimensinalityReducer.pSPE.Levenshtein.is_numeric : OK
|
|
263
|
+
Test result : Success : 622 : Peptides.Peptide space.peptide_space.DimensinalityReducer.pSPE.Jaro-Winkler.is_numeric : OK
|
|
264
|
+
Test result : Success : 7452 : Peptides.Peptide space.peptide_space.DimensinalityReducer.OriginalSPE.Levenshtein.is_numeric : OK
|
|
265
|
+
Test result : Success : 8496 : Peptides.Peptide space.peptide_space.DimensinalityReducer.OriginalSPE.Jaro-Winkler.is_numeric : OK
|
|
266
|
+
Test result : Success : 2071 : Peptides.Peptide space.peptide_space.PeptideSimilaritySpaceViewer.UMAP.Levenshtein.is_proper : OK
|
|
267
|
+
Test result : Success : 2746 : Peptides.Peptide space.peptide_space.PeptideSimilaritySpaceViewer.UMAP.Jaro-Winkler.is_proper : OK
|
|
268
|
+
Test result : Success : 3306 : Peptides.Peptide space.peptide_space.PeptideSimilaritySpaceViewer.t-SNE.Levenshtein.is_proper : OK
|
|
269
|
+
Test result : Success : 4189 : Peptides.Peptide space.peptide_space.PeptideSimilaritySpaceViewer.t-SNE.Jaro-Winkler.is_proper : OK
|
|
270
|
+
Test result : Success : 239 : Peptides.Peptide space.peptide_space.PeptideSimilaritySpaceViewer.SPE.Levenshtein.is_proper : OK
|
|
271
|
+
Test result : Success : 732 : Peptides.Peptide space.peptide_space.PeptideSimilaritySpaceViewer.SPE.Jaro-Winkler.is_proper : OK
|
|
272
|
+
Test result : Success : 347 : Peptides.Peptide space.peptide_space.PeptideSimilaritySpaceViewer.pSPE.Levenshtein.is_proper : OK
|
|
273
|
+
Test result : Success : 659 : Peptides.Peptide space.peptide_space.PeptideSimilaritySpaceViewer.pSPE.Jaro-Winkler.is_proper : OK
|
|
274
|
+
Test result : Success : 7587 : Peptides.Peptide space.peptide_space.PeptideSimilaritySpaceViewer.OriginalSPE.Levenshtein.is_proper : OK
|
|
275
|
+
Test result : Success : 8158 : Peptides.Peptide space.peptide_space.PeptideSimilaritySpaceViewer.OriginalSPE.Jaro-Winkler.is_proper : OK
|
|
276
|
+
</pre></div></div></div></div></body></html>
|