@datagrok/peptides 1.3.7 → 1.3.8
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 +1162 -362
- package/dist/package.js +745 -587
- package/package.json +2 -2
- package/src/model.ts +44 -97
- package/src/package.ts +23 -4
- package/src/tests/core.ts +3 -3
- package/src/utils/cell-renderer.ts +3 -3
- package/src/utils/misc.ts +1 -1
- package/src/utils/types.ts +4 -0
- package/src/viewers/sar-viewer.ts +7 -55
- package/src/widgets/distribution.ts +1 -1
- package/src/widgets/peptides.ts +49 -26
- package/src/widgets/settings.ts +37 -0
package/src/widgets/peptides.ts
CHANGED
|
@@ -14,28 +14,40 @@ import {scaleActivity} from '../utils/misc';
|
|
|
14
14
|
* @param {DG.DataFrame} df Working table
|
|
15
15
|
* @param {DG.Column} col Aligned sequence column
|
|
16
16
|
* @return {Promise<DG.Widget>} Widget containing peptide analysis */
|
|
17
|
-
export async function
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
export async function analyzePeptidesUI(df: DG.DataFrame, col?: DG.Column<string>):
|
|
18
|
+
Promise<{host: HTMLElement, callback: () => Promise<void>}> {
|
|
19
|
+
let seqColInput: DG.InputBase | null = null;
|
|
20
|
+
if (typeof col === 'undefined') {
|
|
21
|
+
const sequenceColumns = df.columns.toList().filter((dfCol) => dfCol.semType === DG.SEMTYPE.MACROMOLECULE);
|
|
22
|
+
let potentialCol = DG.Utils.firstOrNull(sequenceColumns);
|
|
23
|
+
if (potentialCol === null)
|
|
24
|
+
throw new Error('Peptides Error: table doesn\'t contain sequence columns');
|
|
25
|
+
seqColInput = ui.columnInput('Sequence', df, potentialCol, () => {
|
|
26
|
+
const seqCol = seqColInput!.value;
|
|
27
|
+
if (!seqCol.tags['aligned']?.includes('MSA') && seqCol.tags[DG.TAGS.UNITS].toLowerCase() !== 'helm')
|
|
28
|
+
grok.shell.warning('Peptides analysis only works with aligned sequences');
|
|
29
|
+
});
|
|
30
|
+
} else if (!col.tags['aligned']?.includes('MSA') && col.tags[DG.TAGS.UNITS].toLowerCase() !== 'helm')
|
|
31
|
+
return {host: ui.label('Peptides analysis only works with aligned sequences'), callback: async () => {}};
|
|
20
32
|
|
|
21
33
|
let funcs = DG.Func.find({package: 'Bio', name: 'webLogoViewer'});
|
|
22
34
|
if (funcs.length == 0)
|
|
23
|
-
return
|
|
35
|
+
return {host: ui.label('Bio package is missing or out of date. Please install the latest version.'), callback: async () => {}};
|
|
24
36
|
|
|
25
|
-
funcs = DG.Func.find({package: '
|
|
37
|
+
funcs = DG.Func.find({package: 'Bio', name: 'getBioLib'});
|
|
26
38
|
if (funcs.length == 0)
|
|
27
|
-
return
|
|
39
|
+
return {host: ui.label('Bio package is missing or out of date. Please install the latest version.'), callback: async () => {}};
|
|
28
40
|
|
|
29
41
|
let scaledCol: DG.Column<number>;
|
|
30
42
|
|
|
31
43
|
const defaultActivityColumn: DG.Column<number> | null =
|
|
32
|
-
df.col('activity') || df.col('IC50') || DG.Utils.firstOrNull(df.columns.numerical)
|
|
44
|
+
df.col('activity') || df.col('IC50') || DG.Utils.firstOrNull(df.columns.numerical); ;
|
|
33
45
|
const histogramHost = ui.div([], {id: 'pep-hist-host'});
|
|
34
46
|
|
|
35
47
|
const activityScalingMethod = ui.choiceInput(
|
|
36
48
|
'Scaling', 'none', ['none', 'lg', '-lg'],
|
|
37
49
|
async (currentMethod: string): Promise<void> => {
|
|
38
|
-
scaledCol = scaleActivity(
|
|
50
|
+
scaledCol = scaleActivity(activityColumnChoice.value!, currentMethod);
|
|
39
51
|
|
|
40
52
|
const hist = DG.DataFrame.fromColumns([scaledCol]).plot.histogram({
|
|
41
53
|
filteringEnabled: false,
|
|
@@ -62,37 +74,48 @@ export async function analyzePeptidesWidget(df: DG.DataFrame, col: DG.Column): P
|
|
|
62
74
|
activityScalingMethod.fireChanged();
|
|
63
75
|
|
|
64
76
|
const inputsList = [activityColumnChoice, activityScalingMethod, clustersColumnChoice];
|
|
77
|
+
if (seqColInput !== null)
|
|
78
|
+
inputsList.splice(0, 0, seqColInput);
|
|
65
79
|
|
|
66
80
|
const bitsetChanged = df.filter.onChanged.subscribe(() => {
|
|
67
81
|
activityScalingMethodState();
|
|
68
|
-
})
|
|
82
|
+
});
|
|
69
83
|
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
84
|
+
const startAnalysisCallback = async () => {
|
|
85
|
+
const sequencesCol = col ?? seqColInput!.value;
|
|
86
|
+
if (sequencesCol)
|
|
87
|
+
await startAnalysis(activityColumnChoice.value!, sequencesCol, clustersColumnChoice.value, df, scaledCol,
|
|
88
|
+
activityScalingMethod.value ?? 'none');
|
|
73
89
|
bitsetChanged.unsubscribe();
|
|
74
|
-
}
|
|
75
|
-
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const inputElements: HTMLElement[] = [ui.inputs(inputsList)];
|
|
93
|
+
$(inputElements[0]).find('label').css('width', 'unset');
|
|
94
|
+
if (typeof col !== 'undefined') {
|
|
95
|
+
const startBtn = ui.button('Launch SAR', startAnalysisCallback);
|
|
96
|
+
startBtn.style.alignSelf = 'center';
|
|
97
|
+
inputElements.push(startBtn);
|
|
98
|
+
}
|
|
76
99
|
|
|
77
100
|
const viewer = await df.plot.fromType('WebLogo') as bio.WebLogoViewer;
|
|
78
101
|
viewer.root.style.setProperty('height', '130px');
|
|
79
102
|
const logoHost = ui.div();
|
|
80
103
|
$(logoHost).empty().append(viewer.root);
|
|
81
104
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
ui.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
105
|
+
const mainHost = ui.divV([
|
|
106
|
+
logoHost,
|
|
107
|
+
ui.splitH([
|
|
108
|
+
ui.splitV(inputElements),
|
|
109
|
+
histogramHost,
|
|
110
|
+
], {style: {height: '215px'}}),
|
|
111
|
+
]);
|
|
112
|
+
mainHost.style.maxWidth = '400px';
|
|
113
|
+
return {host: mainHost, callback: startAnalysisCallback};
|
|
91
114
|
}
|
|
92
115
|
|
|
93
116
|
export async function startAnalysis(activityColumn: DG.Column<number>, peptidesCol: DG.Column<string>,
|
|
94
117
|
clustersColumn: DG.Column | null, currentDf: DG.DataFrame, scaledCol: DG.Column<number>, scaling: string,
|
|
95
|
-
|
|
118
|
+
): Promise<PeptidesModel | null> {
|
|
96
119
|
const progress = DG.TaskBarProgressIndicator.create('Loading SAR...');
|
|
97
120
|
let model = null;
|
|
98
121
|
if (activityColumn.type === DG.TYPE.FLOAT || activityColumn.type === DG.TYPE.INT) {
|
|
@@ -112,9 +135,9 @@ export async function startAnalysis(activityColumn: DG.Column<number>, peptidesC
|
|
|
112
135
|
newDf.name = 'Peptides analysis';
|
|
113
136
|
if (clustersColumn) {
|
|
114
137
|
newDf.getCol(clustersColumn.name).name = C.COLUMNS_NAMES.CLUSTERS;
|
|
115
|
-
newDf.
|
|
138
|
+
newDf.setTag(C.TAGS.CLUSTERS, C.COLUMNS_NAMES.CLUSTERS);
|
|
116
139
|
}
|
|
117
|
-
newDf.
|
|
140
|
+
newDf.setTag('settings', JSON.stringify({scaling: scaling}));
|
|
118
141
|
|
|
119
142
|
let monomerType = 'HELM_AA';
|
|
120
143
|
if (peptidesCol.getTag(DG.TAGS.UNITS).toLowerCase() == 'helm') {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as ui from 'datagrok-api/ui';
|
|
2
|
+
import * as grok from 'datagrok-api/grok';
|
|
3
|
+
import * as DG from 'datagrok-api/dg';
|
|
4
|
+
|
|
5
|
+
import * as type from '../utils/types';
|
|
6
|
+
import {PeptidesModel} from '../model';
|
|
7
|
+
|
|
8
|
+
//TODO: show sliderInput values
|
|
9
|
+
export function getSettingsDialog(model: PeptidesModel): DG.Dialog {
|
|
10
|
+
const settings = model.settings;
|
|
11
|
+
const result: type.PeptidesSettings = {};
|
|
12
|
+
const activityScaling = ui.choiceInput('Activity scaling', settings.scaling ?? 'none', ['none', 'lg', '-lg'],
|
|
13
|
+
() => result.scaling = activityScaling.value! as type.ScalingMethods);
|
|
14
|
+
const bidirectionalAnalysis = ui.boolInput('Bidirectional analysis', settings.isBidirectional ?? false,
|
|
15
|
+
() => result.isBidirectional = bidirectionalAnalysis.value!);
|
|
16
|
+
const maxMutations = ui.sliderInput('Max mutations', settings.maxMutations ?? 1, 0, 50, () => {
|
|
17
|
+
const val = Math.round(maxMutations.value!);
|
|
18
|
+
result.maxMutations = val;
|
|
19
|
+
});
|
|
20
|
+
const minActivityDelta = ui.sliderInput('Min activity delta', settings.minActivityDelta ?? 0, 0, 100, () => {
|
|
21
|
+
const val = Math.round(minActivityDelta.value!);
|
|
22
|
+
result.minActivityDelta = val;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const accordion = ui.accordion();
|
|
26
|
+
accordion.addPane('General', () => ui.inputs([activityScaling, bidirectionalAnalysis]), true);
|
|
27
|
+
accordion.addPane('Mutation Cliffs', () => ui.inputs([maxMutations, minActivityDelta]), true);
|
|
28
|
+
|
|
29
|
+
const dialog = ui.dialog('Peptides settings').add(accordion);
|
|
30
|
+
dialog.root.style.width = '400px';
|
|
31
|
+
dialog.onOK(() => model.settings = result);
|
|
32
|
+
dialog.show();
|
|
33
|
+
|
|
34
|
+
return dialog.show();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|