@datagrok/peptides 0.8.8 → 0.8.12
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 +2 -1
- package/dist/package-test.js +22626 -0
- package/dist/package.js +21429 -0
- package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +8840 -0
- package/jest.config.js +33 -0
- package/package.json +70 -62
- package/src/__jest__/remote.test.ts +50 -0
- package/src/__jest__/test-node.ts +96 -0
- package/src/model.ts +977 -92
- package/src/monomer-library.ts +18 -12
- package/src/package-test.ts +6 -5
- package/src/package.ts +83 -68
- package/src/peptides.ts +298 -142
- package/src/styles.css +8 -0
- package/src/tests/peptide-space-test.ts +1 -1
- package/src/tests/peptides-tests.ts +20 -81
- package/src/tests/utils.ts +4 -9
- package/src/utils/SAR-multiple-filter.ts +439 -0
- package/src/utils/SAR-multiple-selection.ts +177 -0
- package/src/utils/cell-renderer.ts +124 -97
- package/src/utils/chem-palette.ts +98 -166
- package/src/utils/constants.ts +56 -0
- package/src/utils/filtering-statistics.ts +62 -0
- package/src/utils/multiple-sequence-alignment.ts +33 -2
- package/src/utils/multivariate-analysis.ts +79 -0
- package/src/utils/peptide-similarity-space.ts +24 -53
- package/src/utils/types.ts +10 -0
- package/src/viewers/logo-viewer.ts +7 -5
- package/src/viewers/peptide-space-viewer.ts +121 -0
- package/src/viewers/sar-viewer.ts +118 -342
- package/src/viewers/stacked-barchart-viewer.ts +322 -369
- package/src/widgets/analyze-peptides.ts +50 -29
- package/src/widgets/distribution.ts +61 -0
- package/src/widgets/manual-alignment.ts +7 -4
- package/src/widgets/multiple-sequence-alignment.ts +9 -0
- package/src/widgets/peptide-molecule.ts +8 -6
- package/src/widgets/subst-table.ts +73 -0
- package/src/workers/dimensionality-reducer.ts +1 -1
- package/test-Peptides-414a1874a71a-2f1c6575.html +256 -0
- package/src/describe.ts +0 -535
- package/src/utils/split-aligned.ts +0 -72
- package/src/viewers/subst-viewer.ts +0 -285
|
@@ -3,394 +3,170 @@ 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 {
|
|
6
|
+
import {PeptidesController} from '../peptides';
|
|
7
|
+
import * as C from '../utils/constants';
|
|
8
|
+
|
|
9
|
+
let IS_PROPERTY_CHANGING = false;
|
|
10
|
+
|
|
11
|
+
export class SARViewerBase extends DG.JsViewer {
|
|
12
|
+
tempName!: string;
|
|
13
|
+
viewerGrid!: DG.Grid;
|
|
14
|
+
sourceGrid!: DG.Grid;
|
|
15
|
+
controller!: PeptidesController;
|
|
16
|
+
scaling: string;
|
|
17
|
+
// filterMode: boolean;
|
|
18
|
+
bidirectionalAnalysis: boolean;
|
|
19
|
+
// grouping: boolean;
|
|
20
|
+
showSubstitution: boolean;
|
|
21
|
+
maxSubstitutions: number;
|
|
22
|
+
activityLimit: number;
|
|
23
|
+
_titleHost = ui.divText('SAR Viewer', {id: 'pep-viewer-title'});
|
|
24
|
+
initialized = false;
|
|
25
|
+
isPropertyChanging: boolean = false;
|
|
7
26
|
|
|
8
|
-
import {model} from '../model';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Structure-activity relationship viewer.
|
|
12
|
-
*
|
|
13
|
-
* @export
|
|
14
|
-
* @class SARViewer
|
|
15
|
-
* @extends {DG.JsViewer}
|
|
16
|
-
*/
|
|
17
|
-
export class SARViewer extends DG.JsViewer {
|
|
18
|
-
protected viewerGrid: DG.Grid | null;
|
|
19
|
-
protected sourceGrid: DG.Grid | null;
|
|
20
|
-
protected activityColumnName: string;
|
|
21
|
-
protected scaling: string;
|
|
22
|
-
protected bidirectionalAnalysis: boolean;
|
|
23
|
-
protected filterMode: boolean;
|
|
24
|
-
protected statsDf: DG.DataFrame | null;
|
|
25
|
-
protected initialized: boolean;
|
|
26
|
-
protected viewGridInitialized: boolean;
|
|
27
|
-
protected aminoAcidResidue;
|
|
28
|
-
protected _initialBitset: DG.BitSet | null;
|
|
29
|
-
protected viewerVGrid: DG.Grid | null;
|
|
30
|
-
protected currentBitset: DG.BitSet | null;
|
|
31
|
-
grouping: boolean;
|
|
32
|
-
groupMapping: StringDictionary | null;
|
|
33
|
-
// protected pValueThreshold: number;
|
|
34
|
-
// protected amountOfBestAARs: number;
|
|
35
|
-
// duplicatesHandingMethod: string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Creates an instance of SARViewer.
|
|
39
|
-
*
|
|
40
|
-
* @memberof SARViewer
|
|
41
|
-
*/
|
|
42
27
|
constructor() {
|
|
43
28
|
super();
|
|
44
29
|
|
|
45
|
-
this.viewerGrid = null;
|
|
46
|
-
this.viewerVGrid = null;
|
|
47
|
-
this.statsDf = null;
|
|
48
|
-
this.groupMapping = null;
|
|
49
|
-
this.initialized = false;
|
|
50
|
-
this.aminoAcidResidue = 'AAR';
|
|
51
|
-
this._initialBitset = null;
|
|
52
|
-
this.viewGridInitialized = false;
|
|
53
|
-
this.currentBitset = null;
|
|
54
|
-
|
|
55
|
-
//TODO: find a way to restrict activityColumnName to accept only numerical columns (double even better)
|
|
56
|
-
this.activityColumnName = this.string('activityColumnName');
|
|
57
30
|
this.scaling = this.string('scaling', 'none', {choices: ['none', 'lg', '-lg']});
|
|
58
|
-
this.filterMode = this.bool('filterMode', false);
|
|
31
|
+
// this.filterMode = this.bool('filterMode', false);
|
|
59
32
|
this.bidirectionalAnalysis = this.bool('bidirectionalAnalysis', false);
|
|
60
|
-
this.grouping = this.bool('grouping', false);
|
|
61
|
-
// this.pValueThreshold = this.float('pValueThreshold', 0.1);
|
|
62
|
-
// this.amountOfBestAARs = this.int('amountOfBestAAR', 1);
|
|
63
|
-
// this.duplicatesHandingMethod = this.string('duplicatesHandlingMethod', 'median', {choices: ['median']});
|
|
33
|
+
// this.grouping = this.bool('grouping', false);
|
|
64
34
|
|
|
65
|
-
this.
|
|
35
|
+
this.showSubstitution = this.bool('showSubstitution', false);
|
|
36
|
+
this.maxSubstitutions = this.int('maxSubstitutions', 1);
|
|
37
|
+
this.activityLimit = this.float('activityLimit', 2);
|
|
66
38
|
}
|
|
67
39
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
this.
|
|
77
|
-
this.subs.push(model.statsDf$.subscribe((data) => this.statsDf = data));
|
|
78
|
-
this.subs.push(model.viewerGrid$.subscribe((data) => {
|
|
79
|
-
this.viewerGrid = data;
|
|
80
|
-
this.render();
|
|
81
|
-
}));
|
|
82
|
-
this.subs.push(model.viewerVGrid$.subscribe((data) => this.viewerVGrid = data));
|
|
83
|
-
this.subs.push(model.groupMapping$.subscribe((data) => this.groupMapping = data));
|
|
40
|
+
async onTableAttached() {
|
|
41
|
+
super.onTableAttached();
|
|
42
|
+
this.dataFrame.temp[this.tempName] ??= this;
|
|
43
|
+
this.sourceGrid = this.view?.grid ?? (grok.shell.v as DG.TableView).grid;
|
|
44
|
+
this.controller = await PeptidesController.getInstance(this.dataFrame);
|
|
45
|
+
this.controller.init(this.dataFrame);
|
|
46
|
+
await this.requestDataUpdate();
|
|
47
|
+
|
|
48
|
+
// this.subs.push(this.controller.onGroupMappingChanged.subscribe(() => {this.render(true);}));
|
|
84
49
|
}
|
|
85
50
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
51
|
+
detach() {this.subs.forEach((sub) => sub.unsubscribe());}
|
|
52
|
+
|
|
53
|
+
render(refreshOnly = false) {
|
|
54
|
+
if (!this.initialized)
|
|
55
|
+
return;
|
|
56
|
+
if (!refreshOnly) {
|
|
57
|
+
$(this.root).empty();
|
|
58
|
+
const viewerRoot = this.viewerGrid.root;
|
|
59
|
+
viewerRoot.style.width = 'auto';
|
|
60
|
+
this.root.appendChild(ui.divV([this._titleHost, viewerRoot]));
|
|
61
|
+
}
|
|
62
|
+
this.viewerGrid?.invalidate();
|
|
95
63
|
}
|
|
96
64
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
* @memberof SARViewer
|
|
101
|
-
*/
|
|
102
|
-
detach() {
|
|
103
|
-
this.subs.forEach((sub) => sub.unsubscribe());
|
|
65
|
+
async requestDataUpdate() {
|
|
66
|
+
await this.controller.updateData(this.scaling, this.sourceGrid, this.bidirectionalAnalysis,
|
|
67
|
+
this.activityLimit, this.maxSubstitutions, this.showSubstitution);
|
|
104
68
|
}
|
|
105
69
|
|
|
106
|
-
|
|
107
|
-
* Function that is executed when the property is changed.
|
|
108
|
-
*
|
|
109
|
-
* @param {DG.Property} property New property.
|
|
110
|
-
* @memberof SARViewer
|
|
111
|
-
*/
|
|
112
|
-
onPropertyChanged(property: DG.Property) {
|
|
70
|
+
async onPropertyChanged(property: DG.Property) {
|
|
113
71
|
super.onPropertyChanged(property);
|
|
114
|
-
|
|
115
|
-
if (!this.initialized)
|
|
116
|
-
this.init();
|
|
72
|
+
this.dataFrame.tags[property.name] = `${property.get(this)}`;
|
|
73
|
+
if (!this.initialized || IS_PROPERTY_CHANGING)
|
|
117
74
|
return;
|
|
118
|
-
|
|
75
|
+
|
|
76
|
+
const propName = property.name;
|
|
119
77
|
|
|
120
|
-
if (
|
|
121
|
-
const minActivity =
|
|
122
|
-
this.dataFrame!.col(this.activityColumnName)!,
|
|
123
|
-
this._initialBitset,
|
|
124
|
-
).min;
|
|
78
|
+
if (propName === 'scaling' && typeof this.dataFrame !== 'undefined') {
|
|
79
|
+
const minActivity = this.dataFrame.getCol(C.COLUMNS_NAMES.ACTIVITY).stats.min;
|
|
125
80
|
if (minActivity && minActivity <= 0 && this.scaling !== 'none') {
|
|
126
81
|
grok.shell.warning(`Could not apply ${this.scaling}: ` +
|
|
127
|
-
`activity column ${
|
|
82
|
+
`activity column ${C.COLUMNS_NAMES.ACTIVITY} contains zero or negative values, falling back to 'none'.`);
|
|
128
83
|
property.set(this, 'none');
|
|
129
84
|
return;
|
|
130
85
|
}
|
|
131
86
|
}
|
|
132
87
|
|
|
133
|
-
this.
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Viewer render function.
|
|
138
|
-
*
|
|
139
|
-
* @param {boolean} [computeData=true] Recalculate data.
|
|
140
|
-
* @memberof SARViewer
|
|
141
|
-
*/
|
|
142
|
-
async render(computeData = true) {
|
|
143
|
-
if (!this.initialized)
|
|
88
|
+
if (!this.showSubstitution && ['maxSubstitutions', 'activityLimit'].includes(propName))
|
|
144
89
|
return;
|
|
145
90
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (typeof this.dataFrame !== 'undefined' && this.activityColumnName && this.sourceGrid) {
|
|
149
|
-
await model?.updateData(
|
|
150
|
-
this.dataFrame!,
|
|
151
|
-
this.activityColumnName,
|
|
152
|
-
this.scaling,
|
|
153
|
-
this.sourceGrid,
|
|
154
|
-
this.bidirectionalAnalysis,
|
|
155
|
-
this._initialBitset,
|
|
156
|
-
this.grouping,
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
if (this.viewerGrid !== null && this.viewerVGrid !== null) {
|
|
160
|
-
$(this.root).empty();
|
|
161
|
-
this.root.appendChild(this.viewerGrid.root);
|
|
162
|
-
this.viewerGrid.dataFrame!.onCurrentCellChanged.subscribe((_) => {
|
|
163
|
-
this.currentBitset = applyBitset(
|
|
164
|
-
this.dataFrame!, this.viewerGrid!, this.aminoAcidResidue,
|
|
165
|
-
this.groupMapping!, this._initialBitset!, this.filterMode,
|
|
166
|
-
) ?? this.currentBitset;
|
|
167
|
-
syncGridsFunc(false, this.viewerGrid!, this.viewerVGrid!, this.aminoAcidResidue);
|
|
168
|
-
});
|
|
169
|
-
this.viewerVGrid.dataFrame!.onCurrentCellChanged.subscribe((_) => {
|
|
170
|
-
syncGridsFunc(true, this.viewerGrid!, this.viewerVGrid!, this.aminoAcidResidue);
|
|
171
|
-
});
|
|
172
|
-
this.dataFrame!.onRowsFiltering.subscribe((_) => {
|
|
173
|
-
sourceFilteringFunc(this.filterMode, this.dataFrame!, this.currentBitset!, this._initialBitset!);
|
|
174
|
-
});
|
|
175
|
-
grok.events.onAccordionConstructed.subscribe((accordion: DG.Accordion) => {
|
|
176
|
-
accordionFunc(
|
|
177
|
-
accordion, this.viewerGrid!, this.aminoAcidResidue,
|
|
178
|
-
this._initialBitset!, this.activityColumnName, this.statsDf!,
|
|
179
|
-
);
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
//fixes viewers not rendering immediately after analyze.
|
|
185
|
-
this.viewerGrid?.invalidate();
|
|
91
|
+
await this.requestDataUpdate();
|
|
92
|
+
this.render(true);
|
|
186
93
|
}
|
|
187
94
|
}
|
|
188
95
|
|
|
189
96
|
/**
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
* @export
|
|
193
|
-
* @class SARViewerVertical
|
|
194
|
-
* @extends {DG.JsViewer}
|
|
97
|
+
* Structure-activity relationship viewer.
|
|
195
98
|
*/
|
|
196
|
-
export class
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
* Creates an instance of SARViewerVertical.
|
|
201
|
-
*
|
|
202
|
-
* @memberof SARViewerVertical
|
|
203
|
-
*/
|
|
204
|
-
constructor() {
|
|
205
|
-
super();
|
|
99
|
+
export class SARViewer extends SARViewerBase {
|
|
100
|
+
_titleHost = ui.divText('Monomer-Positions', {id: 'pep-viewer-title'});
|
|
101
|
+
_name = 'Structure-Activity Relationship';
|
|
102
|
+
tempName = 'sarViewer';
|
|
206
103
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
104
|
+
constructor() { super(); }
|
|
105
|
+
|
|
106
|
+
get name() {return this._name;}
|
|
107
|
+
|
|
108
|
+
async onTableAttached() {
|
|
109
|
+
await super.onTableAttached();
|
|
110
|
+
this.viewerGrid = this.controller.sarGrid;
|
|
111
|
+
|
|
112
|
+
this.subs.push(this.controller.onSARGridChanged.subscribe((data) => {
|
|
113
|
+
this.viewerGrid = data;
|
|
210
114
|
this.render();
|
|
211
115
|
}));
|
|
212
|
-
}
|
|
213
116
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
*
|
|
217
|
-
* @memberof SARViewerVertical
|
|
218
|
-
*/
|
|
219
|
-
render() {
|
|
220
|
-
if (this.viewerVGrid) {
|
|
221
|
-
$(this.root).empty();
|
|
222
|
-
this.root.appendChild(this.viewerVGrid.root);
|
|
223
|
-
}
|
|
224
|
-
this.viewerVGrid?.invalidate();
|
|
117
|
+
this.initialized = true;
|
|
118
|
+
this.render();
|
|
225
119
|
}
|
|
226
|
-
}
|
|
227
120
|
|
|
228
|
-
|
|
229
|
-
sourceVertical: boolean,
|
|
230
|
-
viewerGrid: DG.Grid,
|
|
231
|
-
viewerVGrid: DG.Grid,
|
|
232
|
-
aminoAcidResidue: string,
|
|
233
|
-
) { //TODO: refactor, move
|
|
234
|
-
if (viewerGrid && viewerGrid.dataFrame && viewerVGrid && viewerVGrid.dataFrame) {
|
|
235
|
-
if (sourceVertical) {
|
|
236
|
-
const dfCell = viewerVGrid.dataFrame.currentCell;
|
|
237
|
-
if (dfCell.column === null || dfCell.column.name !== 'Mean difference')
|
|
238
|
-
return;
|
|
121
|
+
isInitialized() { return this.controller?.sarGrid ?? false; }
|
|
239
122
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
for (let i = 0; i < viewerGrid.dataFrame.rowCount; i++) {
|
|
244
|
-
if (viewerGrid.dataFrame.get(aminoAcidResidue, i) === otherRowName) {
|
|
245
|
-
otherRowIndex = i;
|
|
246
|
-
break;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
if (otherRowIndex !== -1)
|
|
250
|
-
viewerGrid.dataFrame.currentCell = viewerGrid.dataFrame.cell(otherRowIndex, otherColName);
|
|
251
|
-
} else {
|
|
252
|
-
const otherPos: string = viewerGrid.dataFrame.currentCol?.name;
|
|
253
|
-
if (typeof otherPos === 'undefined' && otherPos !== aminoAcidResidue)
|
|
254
|
-
return;
|
|
123
|
+
async onPropertyChanged(property: DG.Property): Promise<void> {
|
|
124
|
+
if (!this.isInitialized() || IS_PROPERTY_CHANGING)
|
|
125
|
+
return;
|
|
255
126
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if (
|
|
261
|
-
viewerVGrid.dataFrame.get(aminoAcidResidue, i) === otherAAR &&
|
|
262
|
-
viewerVGrid.dataFrame.get('Position', i) === otherPos
|
|
263
|
-
) {
|
|
264
|
-
otherRowIndex = i;
|
|
265
|
-
break;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
if (otherRowIndex !== -1)
|
|
269
|
-
viewerVGrid.dataFrame.currentCell = viewerVGrid.dataFrame.cell(otherRowIndex, 'Mean difference');
|
|
270
|
-
}
|
|
127
|
+
await super.onPropertyChanged(property);
|
|
128
|
+
IS_PROPERTY_CHANGING = true;
|
|
129
|
+
this.controller.syncProperties(true);
|
|
130
|
+
IS_PROPERTY_CHANGING = false;
|
|
271
131
|
}
|
|
272
132
|
}
|
|
273
133
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
dataFrame.filter.copyFrom(initialBitset);
|
|
285
|
-
dataFrame.selection.copyFrom(currentBitset);
|
|
134
|
+
/**
|
|
135
|
+
* Vertical structure activity relationship viewer.
|
|
136
|
+
*/
|
|
137
|
+
export class SARViewerVertical extends SARViewerBase {
|
|
138
|
+
_name = 'Sequence-Activity relationship';
|
|
139
|
+
_titleHost = ui.divText('Most Potent Residues', {id: 'pep-viewer-title'});
|
|
140
|
+
tempName = 'sarViewerVertical';
|
|
141
|
+
|
|
142
|
+
constructor() {
|
|
143
|
+
super();
|
|
286
144
|
}
|
|
287
|
-
}
|
|
288
145
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
) {
|
|
303
|
-
const currentAAR: string =
|
|
304
|
-
viewerGrid.dataFrame.get(aminoAcidResidue, viewerGrid.dataFrame.currentRowIdx);
|
|
305
|
-
const currentPosition = viewerGrid.dataFrame.currentCol.name;
|
|
306
|
-
|
|
307
|
-
const splitColName = '~splitCol';
|
|
308
|
-
const otherLabel = 'Other';
|
|
309
|
-
const aarLabel = `${currentAAR === '-' ? 'Empty' : currentAAR} - ${currentPosition}`;
|
|
310
|
-
|
|
311
|
-
let splitCol = dataFrame.col(splitColName);
|
|
312
|
-
if (!splitCol)
|
|
313
|
-
splitCol = dataFrame.columns.addNew(splitColName, 'string');
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const isChosen = (i: number) => groupMapping[dataFrame!.get(currentPosition, i)] === currentAAR;
|
|
317
|
-
splitCol!.init((i) => isChosen(i) ? aarLabel : otherLabel);
|
|
318
|
-
|
|
319
|
-
//TODO: use column.compact
|
|
320
|
-
currentBitset = DG.BitSet.create(dataFrame.rowCount, isChosen).and(initialBitset);
|
|
321
|
-
sourceFilteringFunc(filterMode, dataFrame, currentBitset, initialBitset);
|
|
322
|
-
|
|
323
|
-
const colorMap: {[index: string]: string | number} = {};
|
|
324
|
-
colorMap[otherLabel] = DG.Color.blue;
|
|
325
|
-
colorMap[aarLabel] = DG.Color.orange;
|
|
326
|
-
// colorMap[currentAAR] = cp.getColor(currentAAR);
|
|
327
|
-
dataFrame.getCol(splitColName).colors.setCategorical(colorMap);
|
|
146
|
+
get name() {return this._name;}
|
|
147
|
+
|
|
148
|
+
async onTableAttached() {
|
|
149
|
+
await super.onTableAttached();
|
|
150
|
+
this.viewerGrid = this.controller.sarVGrid;
|
|
151
|
+
|
|
152
|
+
this.subs.push(this.controller.onSARVGridChanged.subscribe((data) => {
|
|
153
|
+
this.viewerGrid = data;
|
|
154
|
+
this.render();
|
|
155
|
+
}));
|
|
156
|
+
|
|
157
|
+
this.initialized = true;
|
|
158
|
+
this.render();
|
|
328
159
|
}
|
|
329
|
-
return currentBitset;
|
|
330
|
-
}
|
|
331
160
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const viewerDf = viewerGrid.dataFrame;
|
|
343
|
-
|
|
344
|
-
if (
|
|
345
|
-
originalDf.getTag('dataType') === 'peptides' &&
|
|
346
|
-
originalDf.col('~splitCol') &&
|
|
347
|
-
viewerDf &&
|
|
348
|
-
viewerDf.currentCol !== null
|
|
349
|
-
) {
|
|
350
|
-
const currentAAR: string = viewerDf.get(
|
|
351
|
-
aminoAcidResidue,
|
|
352
|
-
viewerDf.currentRowIdx,
|
|
353
|
-
);
|
|
354
|
-
const currentPosition = viewerDf.currentCol.name;
|
|
355
|
-
|
|
356
|
-
const labelStr = `${currentAAR === '-' ? 'Empty' : currentAAR} - ${currentPosition}`;
|
|
357
|
-
const currentColor = DG.Color.toHtml(DG.Color.orange);
|
|
358
|
-
const otherColor = DG.Color.toHtml(DG.Color.blue);
|
|
359
|
-
const currentLabel = ui.label(labelStr, {style: {color: currentColor}});
|
|
360
|
-
const otherLabel = ui.label('Other', {style: {color: otherColor}});
|
|
361
|
-
|
|
362
|
-
const elements: (HTMLLabelElement | HTMLElement)[] = [currentLabel, otherLabel];
|
|
363
|
-
|
|
364
|
-
const distPane = accordion.getPane('Distribution');
|
|
365
|
-
if (distPane)
|
|
366
|
-
accordion.removePane(distPane);
|
|
367
|
-
|
|
368
|
-
accordion.addPane('Distribution', () => {
|
|
369
|
-
const hist = originalDf.clone(initialBitset).plot.histogram({
|
|
370
|
-
// const hist = originalDf.plot.histogram({
|
|
371
|
-
filteringEnabled: false,
|
|
372
|
-
valueColumnName: `${activityColumnName}Scaled`,
|
|
373
|
-
splitColumnName: '~splitCol',
|
|
374
|
-
legendVisibility: 'Never',
|
|
375
|
-
showXAxis: true,
|
|
376
|
-
showColumnSelector: false,
|
|
377
|
-
showRangeSlider: false,
|
|
378
|
-
}).root;
|
|
379
|
-
hist.style.width = 'auto';
|
|
380
|
-
elements.push(hist);
|
|
381
|
-
|
|
382
|
-
const tableMap: StringDictionary = {'Statistics:': ''};
|
|
383
|
-
for (const colName of new Set(['Count', 'pValue', 'Mean difference'])) {
|
|
384
|
-
const query = `${aminoAcidResidue} = ${currentAAR} and Position = ${currentPosition}`;
|
|
385
|
-
const textNum = statsDf.groupBy([colName]).where(query).aggregate().get(colName, 0);
|
|
386
|
-
// const text = textNum === 0 ? '<0.01' : `${colName === 'Count' ? textNum : textNum.toFixed(2)}`;
|
|
387
|
-
const text = colName === 'Count' ? `${textNum}` : textNum < 0.01 ? '<0.01' : textNum.toFixed(2);
|
|
388
|
-
tableMap[colName === 'pValue' ? 'p-value' : colName] = text;
|
|
389
|
-
}
|
|
390
|
-
elements.push(ui.tableFromMap(tableMap));
|
|
391
|
-
|
|
392
|
-
return ui.divV(elements);
|
|
393
|
-
}, true);
|
|
394
|
-
}
|
|
161
|
+
isInitialized() { return this.controller?.sarVGrid ?? false; }
|
|
162
|
+
|
|
163
|
+
async onPropertyChanged(property: DG.Property): Promise<void> {
|
|
164
|
+
if (!this.isInitialized() || IS_PROPERTY_CHANGING)
|
|
165
|
+
return;
|
|
166
|
+
|
|
167
|
+
await super.onPropertyChanged(property);
|
|
168
|
+
IS_PROPERTY_CHANGING = true;
|
|
169
|
+
this.controller.syncProperties(false);
|
|
170
|
+
IS_PROPERTY_CHANGING = false;
|
|
395
171
|
}
|
|
396
172
|
}
|