@datagrok/peptides 1.4.0 → 1.5.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 +1480 -1006
- package/dist/package.js +1252 -921
- package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +3 -3
- package/files/tests/aligned_5k.d42 +0 -0
- package/package.json +2 -2
- package/src/__jest__/remote.test.ts +12 -5
- package/src/__jest__/test-node.ts +1 -1
- package/src/model.ts +432 -479
- package/src/package-test.ts +1 -0
- package/src/package.ts +15 -14
- package/src/tests/algorithms.ts +29 -20
- package/src/tests/core.ts +3 -6
- package/src/tests/utils.ts +4 -4
- package/src/utils/algorithms.ts +25 -22
- package/src/utils/cell-renderer.ts +22 -16
- package/src/utils/constants.ts +3 -36
- package/src/utils/misc.ts +14 -15
- package/src/utils/peptide-similarity-space.ts +4 -7
- package/src/utils/statistics.ts +18 -9
- package/src/utils/types.ts +6 -0
- package/src/viewers/logo-summary.ts +108 -39
- package/src/viewers/peptide-space-viewer.ts +5 -5
- package/src/viewers/sar-viewer.ts +229 -56
- package/src/widgets/distribution.ts +35 -10
- package/src/widgets/manual-alignment.ts +1 -1
- package/src/widgets/mutation-cliffs.ts +2 -3
- package/src/widgets/peptides.ts +67 -36
- package/src/widgets/settings.ts +20 -16
- package/{test-Peptides-62cc009524f3-d4fc804f.html → test-Peptides-4775b69ad08a-1bc1a2b4.html} +33 -32
- package/tsconfig.json +3 -3
package/src/model.ts
CHANGED
|
@@ -9,8 +9,8 @@ import * as rxjs from 'rxjs';
|
|
|
9
9
|
|
|
10
10
|
import * as C from './utils/constants';
|
|
11
11
|
import * as type from './utils/types';
|
|
12
|
-
import {calculateSelected,
|
|
13
|
-
import {
|
|
12
|
+
import {calculateSelected, extractMonomerInfo, scaleActivity} from './utils/misc';
|
|
13
|
+
import {MonomerPosition, MostPotentResiduesViewer} from './viewers/sar-viewer';
|
|
14
14
|
import * as CR from './utils/cell-renderer';
|
|
15
15
|
import {mutationCliffsWidget} from './widgets/mutation-cliffs';
|
|
16
16
|
import {getDistributionAndStats, getDistributionWidget} from './widgets/distribution';
|
|
@@ -24,30 +24,24 @@ import {findMutations} from './utils/algorithms';
|
|
|
24
24
|
export class PeptidesModel {
|
|
25
25
|
static modelName = 'peptidesModel';
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
logoSummaryGridSubject = new rxjs.Subject<DG.Grid>();
|
|
30
|
-
settingsSubject = new rxjs.Subject();
|
|
27
|
+
settingsSubject: rxjs.Subject<type.PeptidesSettings> = new rxjs.Subject();
|
|
28
|
+
_mutatinCliffsSelectionSubject: rxjs.Subject<undefined> = new rxjs.Subject();
|
|
31
29
|
|
|
32
30
|
_isUpdating: boolean = false;
|
|
33
31
|
isBitsetChangedInitialized = false;
|
|
34
32
|
isCellChanging = false;
|
|
35
33
|
|
|
36
|
-
mutationCliffsGrid!: DG.Grid;
|
|
37
|
-
mostPotentResiduesGrid!: DG.Grid;
|
|
38
|
-
// logoSummaryGrid!: DG.Grid;
|
|
39
|
-
sourceGrid!: DG.Grid;
|
|
40
34
|
df: DG.DataFrame;
|
|
41
35
|
splitCol!: DG.Column<boolean>;
|
|
42
36
|
edf: DG.DataFrame | null = null;
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
_monomerPositionStatsDf?: DG.DataFrame;
|
|
38
|
+
_clusterStatsDf?: DG.DataFrame;
|
|
45
39
|
_mutationCliffsSelection!: type.PositionToAARList;
|
|
46
40
|
_invariantMapSelection!: type.PositionToAARList;
|
|
47
41
|
_logoSummarySelection!: number[];
|
|
48
|
-
|
|
42
|
+
_substitutionsInfo?: type.SubstitutionsInfo;
|
|
49
43
|
isInitialized = false;
|
|
50
|
-
|
|
44
|
+
_analysisView?: DG.TableView;
|
|
51
45
|
|
|
52
46
|
isPeptideSpaceChangingBitset = false;
|
|
53
47
|
isChangingEdfBitset = false;
|
|
@@ -59,38 +53,122 @@ export class PeptidesModel {
|
|
|
59
53
|
_settings!: type.PeptidesSettings;
|
|
60
54
|
isRibbonSet = false;
|
|
61
55
|
|
|
62
|
-
|
|
56
|
+
_cp?: bio.SeqPalette;
|
|
63
57
|
initBitset: DG.BitSet;
|
|
64
58
|
isInvariantMapTrigger: boolean = false;
|
|
65
59
|
headerSelectedMonomers: type.MonomerSelectionStats = {};
|
|
66
60
|
webLogoBounds: {[positon: string]: {[monomer: string]: DG.Rect}} = {};
|
|
67
61
|
cachedWebLogoTooltip: {bar: string; tooltip: HTMLDivElement | null;} = {bar: '', tooltip: null};
|
|
62
|
+
_monomerPositionDf?: DG.DataFrame;
|
|
63
|
+
_alphabet?: string;
|
|
64
|
+
_mostPotentResiduesDf?: DG.DataFrame;
|
|
65
|
+
_matrixDf?: DG.DataFrame;
|
|
66
|
+
_splitSeqDf?: DG.DataFrame;
|
|
68
67
|
|
|
69
68
|
private constructor(dataFrame: DG.DataFrame) {
|
|
70
69
|
this.df = dataFrame;
|
|
71
70
|
this.initBitset = this.df.filter.clone();
|
|
72
|
-
this.cp = bio.pickUpPalette(this.df.getCol(C.COLUMNS_NAMES.MACROMOLECULE));
|
|
73
71
|
}
|
|
74
72
|
|
|
75
|
-
static
|
|
73
|
+
static getInstance(dataFrame: DG.DataFrame): PeptidesModel {
|
|
76
74
|
dataFrame.temp[PeptidesModel.modelName] ??= new PeptidesModel(dataFrame);
|
|
77
|
-
|
|
75
|
+
(dataFrame.temp[PeptidesModel.modelName] as PeptidesModel).init();
|
|
78
76
|
return dataFrame.temp[PeptidesModel.modelName] as PeptidesModel;
|
|
79
77
|
}
|
|
80
78
|
|
|
81
|
-
get
|
|
82
|
-
|
|
79
|
+
get monomerPositionDf(): DG.DataFrame {
|
|
80
|
+
this._monomerPositionDf ??= this.createMonomerPositionDf();
|
|
81
|
+
return this._monomerPositionDf;
|
|
82
|
+
}
|
|
83
|
+
set monomerPositionDf(df: DG.DataFrame) {
|
|
84
|
+
this._monomerPositionDf = df;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get monomerPositionStatsDf(): DG.DataFrame {
|
|
88
|
+
this._monomerPositionStatsDf ??= this.calculateMonomerPositionStatistics();
|
|
89
|
+
return this._monomerPositionStatsDf;
|
|
90
|
+
}
|
|
91
|
+
set monomerPositionStatsDf(df: DG.DataFrame) {
|
|
92
|
+
this._monomerPositionStatsDf = df;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get matrixDf(): DG.DataFrame {
|
|
96
|
+
this._matrixDf ??= this.buildMatrixDf();
|
|
97
|
+
return this._matrixDf;
|
|
98
|
+
}
|
|
99
|
+
set matrixDf(df: DG.DataFrame) {
|
|
100
|
+
this._matrixDf = df;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
get splitSeqDf(): DG.DataFrame {
|
|
104
|
+
this._splitSeqDf ??= this.buildSplitSeqDf();
|
|
105
|
+
return this._splitSeqDf;
|
|
106
|
+
}
|
|
107
|
+
set splitSeqDf(df: DG.DataFrame) {
|
|
108
|
+
this._splitSeqDf = df;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
get mostPotentResiduesDf(): DG.DataFrame {
|
|
112
|
+
this._mostPotentResiduesDf ??= this.createMostPotentResiduesDf();
|
|
113
|
+
return this._mostPotentResiduesDf;
|
|
114
|
+
}
|
|
115
|
+
set mostPotentResiduesDf(df: DG.DataFrame) {
|
|
116
|
+
this._mostPotentResiduesDf = df;
|
|
83
117
|
}
|
|
84
118
|
|
|
85
|
-
get
|
|
86
|
-
|
|
119
|
+
get alphabet(): string {
|
|
120
|
+
const col = this.settings.sequenceColumnName ? this.df.getCol(this.settings.sequenceColumnName) :
|
|
121
|
+
this.df.columns.bySemType(DG.SEMTYPE.MACROMOLECULE)!;
|
|
122
|
+
return col.getTag(bio.TAGS.alphabet);
|
|
87
123
|
}
|
|
88
124
|
|
|
89
|
-
get
|
|
90
|
-
|
|
125
|
+
get substitutionsInfo(): type.SubstitutionsInfo {
|
|
126
|
+
if (this._substitutionsInfo)
|
|
127
|
+
return this._substitutionsInfo;
|
|
128
|
+
|
|
129
|
+
const scaledActivityCol: DG.Column<number> = this.df.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
130
|
+
//TODO: set categories ordering the same to share compare indexes instead of strings
|
|
131
|
+
const monomerColumns: type.RawColumn[] = this.df.columns.bySemTypeAll(C.SEM_TYPES.MONOMER).map(extractMonomerInfo);
|
|
132
|
+
this._substitutionsInfo = findMutations(scaledActivityCol.getRawData(), monomerColumns, this.settings);
|
|
133
|
+
return this._substitutionsInfo;
|
|
134
|
+
}
|
|
135
|
+
set substitutionsInfo(si: type.SubstitutionsInfo) {
|
|
136
|
+
this._substitutionsInfo = si;
|
|
91
137
|
}
|
|
92
138
|
|
|
93
|
-
get
|
|
139
|
+
get clusterStatsDf(): DG.DataFrame {
|
|
140
|
+
this._clusterStatsDf ??= this.calculateClusterStatistics();
|
|
141
|
+
return this._clusterStatsDf;
|
|
142
|
+
}
|
|
143
|
+
set clusterStatsDf(df: DG.DataFrame) {
|
|
144
|
+
this._clusterStatsDf = df;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
get cp(): bio.SeqPalette {
|
|
148
|
+
this._cp ??= bio.pickUpPalette(this.df.getCol(this.settings.sequenceColumnName!));
|
|
149
|
+
return this._cp;
|
|
150
|
+
}
|
|
151
|
+
set cp(_cp: bio.SeqPalette) {
|
|
152
|
+
this._cp = _cp;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
get analysisView(): DG.TableView {
|
|
156
|
+
const shell = grok.shell;
|
|
157
|
+
if (this.df.getTag('newAnalysis') !== '1') {
|
|
158
|
+
this._analysisView = wu(shell.tableViews).find(({dataFrame}) => dataFrame.tags[C.PEPTIDES_ANALYSIS] === '1')!;
|
|
159
|
+
grok.shell.v = this._analysisView;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this._analysisView ??= shell.addTableView(this.df);
|
|
163
|
+
this.df.setTag('newAnalysis', '');
|
|
164
|
+
return this._analysisView;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
get onMutationCliffsSelectionChanged(): rxjs.Observable<undefined> {
|
|
168
|
+
return this._mutatinCliffsSelectionSubject.asObservable();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
get onSettingsChanged(): rxjs.Observable<type.PeptidesSettings> {
|
|
94
172
|
return this.settingsSubject.asObservable();
|
|
95
173
|
}
|
|
96
174
|
|
|
@@ -103,7 +181,7 @@ export class PeptidesModel {
|
|
|
103
181
|
this._mutationCliffsSelection = selection;
|
|
104
182
|
this.df.tags[C.TAGS.SELECTION] = JSON.stringify(selection);
|
|
105
183
|
this.fireBitsetChanged();
|
|
106
|
-
this.
|
|
184
|
+
this._mutatinCliffsSelectionSubject.next();
|
|
107
185
|
}
|
|
108
186
|
|
|
109
187
|
get invariantMapSelection(): type.PositionToAARList {
|
|
@@ -117,7 +195,7 @@ export class PeptidesModel {
|
|
|
117
195
|
this.isInvariantMapTrigger = true;
|
|
118
196
|
this.df.filter.fireChanged();
|
|
119
197
|
this.isInvariantMapTrigger = false;
|
|
120
|
-
this.
|
|
198
|
+
this.analysisView.grid.invalidate();
|
|
121
199
|
}
|
|
122
200
|
|
|
123
201
|
get logoSummarySelection(): number[] {
|
|
@@ -129,7 +207,7 @@ export class PeptidesModel {
|
|
|
129
207
|
this._logoSummarySelection = selection;
|
|
130
208
|
this.df.tags[C.TAGS.CLUSTER_SELECTION] = JSON.stringify(selection);
|
|
131
209
|
this.fireBitsetChanged();
|
|
132
|
-
this.
|
|
210
|
+
this.analysisView.grid.invalidate();
|
|
133
211
|
}
|
|
134
212
|
|
|
135
213
|
get splitByPos(): boolean {
|
|
@@ -177,122 +255,132 @@ export class PeptidesModel {
|
|
|
177
255
|
return this._settings;
|
|
178
256
|
}
|
|
179
257
|
set settings(s: type.PeptidesSettings) {
|
|
180
|
-
|
|
258
|
+
const newSettingsEntries = Object.entries(s);
|
|
259
|
+
const updateVars: Set<string> = new Set();
|
|
260
|
+
for (const [key, value] of newSettingsEntries) {
|
|
181
261
|
this._settings[key as keyof type.PeptidesSettings] = value as any;
|
|
262
|
+
switch (key) {
|
|
263
|
+
case 'scaling':
|
|
264
|
+
updateVars.add('activity');
|
|
265
|
+
updateVars.add('mutationCliffs');
|
|
266
|
+
updateVars.add('stats');
|
|
267
|
+
break;
|
|
268
|
+
// case 'columns':
|
|
269
|
+
// updateVars.add('grid');
|
|
270
|
+
// break;
|
|
271
|
+
case 'maxMutations':
|
|
272
|
+
case 'minActivityDelta':
|
|
273
|
+
updateVars.add('mutationCliffs');
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
182
277
|
this.df.setTag('settings', JSON.stringify(this._settings));
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
|
|
278
|
+
// this.updateDefault();
|
|
279
|
+
for (const variable of updateVars) {
|
|
280
|
+
switch (variable) {
|
|
281
|
+
case 'activity':
|
|
282
|
+
this.createScaledCol();
|
|
283
|
+
break;
|
|
284
|
+
case 'mutationCliffs':
|
|
285
|
+
const scaledActivityCol: DG.Column<number> = this.df.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
286
|
+
//TODO: set categories ordering the same to share compare indexes instead of strings
|
|
287
|
+
const monomerColumns: type.RawColumn[] = this.df.columns.bySemTypeAll(C.SEM_TYPES.MONOMER).map(extractMonomerInfo);
|
|
288
|
+
this.substitutionsInfo = findMutations(scaledActivityCol.getRawData(), monomerColumns, this.settings);
|
|
289
|
+
break;
|
|
290
|
+
case 'stats':
|
|
291
|
+
this.monomerPositionStatsDf = this.calculateMonomerPositionStatistics();
|
|
292
|
+
this.monomerPositionDf = this.createMonomerPositionDf();
|
|
293
|
+
this.mostPotentResiduesDf = this.createMostPotentResiduesDf();
|
|
294
|
+
this.clusterStatsDf = this.calculateClusterStatistics();
|
|
295
|
+
break;
|
|
296
|
+
case 'grid':
|
|
297
|
+
this.updateGrid();
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
//TODO: handle settings change
|
|
303
|
+
this.settingsSubject.next(this.settings);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
createMonomerPositionDf(): DG.DataFrame {
|
|
307
|
+
const matrixDf = this.monomerPositionStatsDf.groupBy([C.COLUMNS_NAMES.MONOMER])
|
|
308
|
+
.pivot(C.COLUMNS_NAMES.POSITION)
|
|
309
|
+
.add('first', C.COLUMNS_NAMES.MEAN_DIFFERENCE, '')
|
|
310
|
+
.aggregate();
|
|
311
|
+
const monomerCol = matrixDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
312
|
+
for (let i = 0; i < monomerCol.length; ++i) {
|
|
313
|
+
if (monomerCol.get(i) == '') {
|
|
314
|
+
matrixDf.rows.removeAt(i);
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
matrixDf.name = 'SAR';
|
|
319
|
+
|
|
320
|
+
return matrixDf;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
buildMatrixDf(): DG.DataFrame {
|
|
324
|
+
const splitSeqDfColumns = this.splitSeqDf.columns;
|
|
325
|
+
const positionColumns = splitSeqDfColumns.names();
|
|
326
|
+
return this.splitSeqDf
|
|
327
|
+
.groupBy(positionColumns)
|
|
328
|
+
.aggregate()
|
|
329
|
+
.unpivot([], positionColumns, C.COLUMNS_NAMES.POSITION, C.COLUMNS_NAMES.MONOMER);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
buildSplitSeqDf(): DG.DataFrame {
|
|
333
|
+
const sequenceCol = this.df.getCol(this.settings.sequenceColumnName!);
|
|
334
|
+
const splitSeqDf = splitAlignedSequences(sequenceCol);
|
|
335
|
+
|
|
336
|
+
return splitSeqDf;
|
|
186
337
|
}
|
|
187
338
|
|
|
188
339
|
createAccordion(): DG.Accordion {
|
|
189
340
|
const acc = ui.accordion();
|
|
190
341
|
acc.root.style.width = '100%';
|
|
191
342
|
acc.addTitle(ui.h1(`${this.df.selection.trueCount} selected rows`));
|
|
192
|
-
acc.addPane('Mutation Cliff pairs', () => mutationCliffsWidget(this.df, this).root
|
|
193
|
-
acc.addPane('Distribution', () => getDistributionWidget(this.df, this).root
|
|
343
|
+
acc.addPane('Mutation Cliff pairs', () => mutationCliffsWidget(this.df, this).root);
|
|
344
|
+
acc.addPane('Distribution', () => getDistributionWidget(this.df, this).root);
|
|
194
345
|
|
|
195
346
|
return acc;
|
|
196
347
|
}
|
|
197
348
|
|
|
198
349
|
updateDefault(): void {
|
|
199
|
-
if (
|
|
200
|
-
// this.isInitialized = true;
|
|
350
|
+
if (!this._isUpdating || !this.isInitialized) {
|
|
201
351
|
this._isUpdating = true;
|
|
202
|
-
this.
|
|
203
|
-
|
|
204
|
-
this.
|
|
205
|
-
this.mostPotentResiduesGridSubject.next(this.mostPotentResiduesGrid);
|
|
206
|
-
// if (this.df.getTag(C.TAGS.CLUSTERS))
|
|
207
|
-
// this.logoSummaryGridSubject.next(this.logoSummaryGrid);
|
|
208
|
-
|
|
209
|
-
this.fireBitsetChanged();
|
|
210
|
-
this.invalidateGrids();
|
|
352
|
+
this.updateGrid();
|
|
353
|
+
|
|
354
|
+
this.analysisView.grid.invalidate();
|
|
211
355
|
this._isUpdating = false;
|
|
212
356
|
}
|
|
213
357
|
}
|
|
214
358
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
throw new Error(`Source grid is not initialized`);
|
|
218
|
-
|
|
219
|
-
//Split the aligned sequence into separate AARs
|
|
220
|
-
const col = this.df.getCol(C.COLUMNS_NAMES.MACROMOLECULE);
|
|
221
|
-
const alphabet = col.tags['alphabet'];
|
|
222
|
-
const splitSeqDf = splitAlignedSequences(col);
|
|
223
|
-
for (const col of splitSeqDf.columns)
|
|
224
|
-
col.name = `p${col.name}`;
|
|
225
|
-
|
|
226
|
-
const positionColumns = splitSeqDf.columns.names();
|
|
227
|
-
|
|
228
|
-
const activityCol = this.df.columns.bySemType(C.SEM_TYPES.ACTIVITY)!;
|
|
229
|
-
splitSeqDf.columns.add(activityCol);
|
|
230
|
-
|
|
231
|
-
this.joinDataFrames(positionColumns, splitSeqDf, alphabet);
|
|
359
|
+
updateGrid(): void {
|
|
360
|
+
this.joinDataFrames();
|
|
232
361
|
|
|
233
362
|
this.sortSourceGrid();
|
|
234
363
|
|
|
235
|
-
this.createScaledCol(
|
|
236
|
-
|
|
237
|
-
//unpivot a table and handle duplicates
|
|
238
|
-
let matrixDf = splitSeqDf.groupBy(positionColumns).aggregate();
|
|
239
|
-
|
|
240
|
-
matrixDf = matrixDf.unpivot([], positionColumns, C.COLUMNS_NAMES.POSITION, C.COLUMNS_NAMES.MONOMER);
|
|
241
|
-
|
|
242
|
-
//statistics for specific AAR at a specific position
|
|
243
|
-
this.monomerPositionStatsDf = this.calculateMonomerPositionStatistics(matrixDf);
|
|
244
|
-
|
|
245
|
-
// SAR matrix table
|
|
246
|
-
//pivot a table to make it matrix-like
|
|
247
|
-
const monomerCol = matrixDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
248
|
-
matrixDf = matrixDf.clone(DG.BitSet.create(matrixDf.rowCount, (i) => monomerCol.get(i) ? true : false));
|
|
249
|
-
matrixDf = this.monomerPositionStatsDf.groupBy([C.COLUMNS_NAMES.MONOMER])
|
|
250
|
-
.pivot(C.COLUMNS_NAMES.POSITION)
|
|
251
|
-
.add('first', C.COLUMNS_NAMES.MEAN_DIFFERENCE, '')
|
|
252
|
-
.aggregate();
|
|
253
|
-
matrixDf.name = 'SAR';
|
|
254
|
-
|
|
255
|
-
// Setting category order
|
|
256
|
-
// this.setCategoryOrder(matrixDf);
|
|
364
|
+
this.createScaledCol();
|
|
257
365
|
|
|
258
|
-
|
|
259
|
-
const sequenceDf = this.createVerticalTable();
|
|
260
|
-
|
|
261
|
-
const scaledActivityCol = this.df.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
262
|
-
const monomerColumns = this.df.columns.bySemTypeAll(C.SEM_TYPES.MONOMER);
|
|
263
|
-
this.substitutionsInfo = findMutations(scaledActivityCol, monomerColumns, this.settings);
|
|
264
|
-
|
|
265
|
-
[this.mutationCliffsGrid, this.mostPotentResiduesGrid] =
|
|
266
|
-
this.createGrids(matrixDf, sequenceDf, positionColumns, alphabet);
|
|
267
|
-
|
|
268
|
-
if (this.df.getTag(C.TAGS.CLUSTERS)) {
|
|
269
|
-
this.clusterStatsDf = this.calculateClusterStatistics();
|
|
270
|
-
// this.logoSummaryGrid = this.createLogoSummaryGrid();
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// init invariant map & mutation cliffs selections
|
|
274
|
-
this.initSelections(positionColumns);
|
|
275
|
-
|
|
276
|
-
// positionColumns.push(C.COLUMNS_NAMES.MEAN_DIFFERENCE);
|
|
366
|
+
this.initSelections();
|
|
277
367
|
|
|
278
368
|
this.setWebLogoInteraction();
|
|
279
369
|
this.webLogoBounds = {};
|
|
280
370
|
|
|
281
|
-
this.setCellRenderers(
|
|
371
|
+
this.setCellRenderers();
|
|
282
372
|
|
|
283
|
-
|
|
284
|
-
this.setTooltips([...positionColumns, C.COLUMNS_NAMES.MEAN_DIFFERENCE]);
|
|
285
|
-
|
|
286
|
-
this.setInteractionCallback();
|
|
373
|
+
this.setTooltips();
|
|
287
374
|
|
|
288
375
|
this.setBitsetCallback();
|
|
289
376
|
|
|
290
|
-
this.postProcessGrids(
|
|
377
|
+
this.postProcessGrids();
|
|
291
378
|
}
|
|
292
379
|
|
|
293
|
-
initSelections(
|
|
380
|
+
initSelections(): void {
|
|
294
381
|
const tempInvariantMapSelection: type.PositionToAARList = this.invariantMapSelection;
|
|
295
382
|
const mutationCliffsSelection: type.PositionToAARList = this.mutationCliffsSelection;
|
|
383
|
+
const positionColumns = this.splitSeqDf.columns.names();
|
|
296
384
|
for (const pos of positionColumns) {
|
|
297
385
|
tempInvariantMapSelection[pos] ??= [];
|
|
298
386
|
mutationCliffsSelection[pos] ??= [];
|
|
@@ -301,29 +389,31 @@ export class PeptidesModel {
|
|
|
301
389
|
this.mutationCliffsSelection = mutationCliffsSelection;
|
|
302
390
|
}
|
|
303
391
|
|
|
304
|
-
joinDataFrames(
|
|
392
|
+
joinDataFrames(): void {
|
|
305
393
|
// append splitSeqDf columns to source table and make sure columns are not added more than once
|
|
306
394
|
const name = this.df.name;
|
|
307
395
|
const cols = this.df.columns;
|
|
396
|
+
const positionColumns = this.splitSeqDf.columns.names();
|
|
308
397
|
for (const colName of positionColumns) {
|
|
309
398
|
const col = this.df.col(colName);
|
|
310
|
-
const newCol = splitSeqDf.getCol(colName);
|
|
399
|
+
const newCol = this.splitSeqDf.getCol(colName);
|
|
311
400
|
if (col === null)
|
|
312
401
|
cols.add(newCol);
|
|
313
402
|
else {
|
|
314
403
|
cols.remove(colName);
|
|
315
404
|
cols.add(newCol);
|
|
316
405
|
}
|
|
317
|
-
CR.setAARRenderer(newCol,
|
|
406
|
+
CR.setAARRenderer(newCol, this.alphabet);
|
|
318
407
|
}
|
|
319
408
|
this.df.name = name;
|
|
320
|
-
this.currentView.name = name;
|
|
321
409
|
}
|
|
322
410
|
|
|
323
411
|
sortSourceGrid(): void {
|
|
324
412
|
const colNames: DG.GridColumn[] = [];
|
|
325
|
-
|
|
326
|
-
|
|
413
|
+
const sourceGridCols = this.analysisView.grid.columns;
|
|
414
|
+
const sourceGridColsCount = sourceGridCols.length;
|
|
415
|
+
for (let i = 1; i < sourceGridColsCount; i++)
|
|
416
|
+
colNames.push(sourceGridCols.byIndex(i)!);
|
|
327
417
|
|
|
328
418
|
colNames.sort((a, b) => {
|
|
329
419
|
if (a.column!.semType == C.SEM_TYPES.MONOMER) {
|
|
@@ -335,99 +425,133 @@ export class PeptidesModel {
|
|
|
335
425
|
return 1;
|
|
336
426
|
return 0;
|
|
337
427
|
});
|
|
338
|
-
|
|
428
|
+
sourceGridCols.setOrder(colNames.map((v) => v.name));
|
|
339
429
|
}
|
|
340
430
|
|
|
341
|
-
createScaledCol(
|
|
342
|
-
const
|
|
431
|
+
createScaledCol(): void {
|
|
432
|
+
const sourceGrid = this.analysisView.grid;
|
|
433
|
+
const scaledCol = scaleActivity(this.df.getCol(this.settings.activityColumnName!), this.settings.scaling);
|
|
343
434
|
//TODO: make another func
|
|
344
|
-
splitSeqDf.columns.add(scaledCol);
|
|
345
435
|
this.df.columns.replace(C.COLUMNS_NAMES.ACTIVITY_SCALED, scaledCol);
|
|
346
|
-
const gridCol =
|
|
347
|
-
if (gridCol)
|
|
348
|
-
|
|
436
|
+
// const gridCol = sourceGrid.col(C.COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
437
|
+
// if (gridCol)
|
|
438
|
+
// gridCol.name = scaledCol.getTag('gridName');
|
|
349
439
|
|
|
350
|
-
|
|
440
|
+
sourceGrid.columns.setOrder([scaledCol.name]);
|
|
351
441
|
}
|
|
352
442
|
|
|
353
|
-
calculateMonomerPositionStatistics(
|
|
354
|
-
matrixDf = matrixDf.groupBy([C.COLUMNS_NAMES.POSITION, C.COLUMNS_NAMES.MONOMER]).aggregate();
|
|
443
|
+
calculateMonomerPositionStatistics(): DG.DataFrame {
|
|
444
|
+
const matrixDf = this.matrixDf.groupBy([C.COLUMNS_NAMES.POSITION, C.COLUMNS_NAMES.MONOMER]).aggregate();
|
|
445
|
+
const matrixLen = matrixDf.rowCount;
|
|
446
|
+
|
|
447
|
+
const posRawColumns: type.RawColumn[] = [];
|
|
355
448
|
|
|
356
|
-
|
|
357
|
-
|
|
449
|
+
const posCol: DG.Column<string> = matrixDf.getCol(C.COLUMNS_NAMES.POSITION);
|
|
450
|
+
const posColData = posCol.getRawData();
|
|
451
|
+
const posColCategories = posCol.categories;
|
|
452
|
+
for (const position of posColCategories) {
|
|
453
|
+
const currentCol = this.df.getCol(position);
|
|
454
|
+
posRawColumns.push({
|
|
455
|
+
name: position,
|
|
456
|
+
rawData: currentCol.getRawData(),
|
|
457
|
+
cat: currentCol.categories,
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const monomerCol: DG.Column<string> = matrixDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
462
|
+
const monomerColData = monomerCol.getRawData();
|
|
463
|
+
const monomerColCategories = monomerCol.categories;
|
|
358
464
|
|
|
359
465
|
//calculate p-values based on t-test
|
|
360
466
|
const matrixCols = matrixDf.columns;
|
|
361
|
-
const
|
|
362
|
-
const
|
|
363
|
-
const
|
|
364
|
-
const
|
|
365
|
-
const
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
const
|
|
372
|
-
const mask =
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
467
|
+
const mdColData = matrixCols.addNewFloat(C.COLUMNS_NAMES.MEAN_DIFFERENCE).init(0).getRawData();
|
|
468
|
+
const pValColData = matrixCols.addNewFloat(C.COLUMNS_NAMES.P_VALUE).init(0).getRawData();
|
|
469
|
+
const countColData = matrixCols.addNewInt(C.COLUMNS_NAMES.COUNT).init(0).getRawData();
|
|
470
|
+
const ratioColData = matrixCols.addNewFloat(C.COLUMNS_NAMES.RATIO).init(0).getRawData();
|
|
471
|
+
const activityColData = this.df.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED).getRawData();
|
|
472
|
+
const sourceDfLen = activityColData.length;
|
|
473
|
+
|
|
474
|
+
for (let i = 0; i < matrixLen; i++) {
|
|
475
|
+
const positionRawIdx = posColData[i];
|
|
476
|
+
const currentPosRawCol = posRawColumns[positionRawIdx];
|
|
477
|
+
const monomerRawIdx = monomerColData[i];
|
|
478
|
+
const mask: boolean[] = new Array(sourceDfLen);
|
|
479
|
+
const monomer = monomerColCategories[monomerRawIdx];
|
|
480
|
+
if (monomer == '')
|
|
481
|
+
continue;
|
|
482
|
+
|
|
483
|
+
let trueCount = 0;
|
|
484
|
+
for (let j = 0; j < sourceDfLen; ++j) {
|
|
485
|
+
mask[j] = currentPosRawCol.cat![currentPosRawCol.rawData[j]] == monomer;
|
|
486
|
+
|
|
487
|
+
if (mask[j])
|
|
488
|
+
++trueCount;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const maskInfo = {
|
|
492
|
+
trueCount: trueCount,
|
|
493
|
+
falseCount: sourceDfLen - trueCount,
|
|
494
|
+
mask: mask,
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
const stats = getStats(activityColData, maskInfo);
|
|
498
|
+
|
|
499
|
+
mdColData[i] = stats.meanDifference;
|
|
500
|
+
pValColData[i] = stats.pValue;
|
|
501
|
+
countColData[i] = stats.count;
|
|
502
|
+
ratioColData[i] = stats.ratio;
|
|
379
503
|
}
|
|
504
|
+
matrixDf.fireValuesChanged();
|
|
380
505
|
|
|
381
506
|
return matrixDf as DG.DataFrame;
|
|
382
507
|
}
|
|
383
508
|
|
|
384
509
|
calculateClusterStatistics(): DG.DataFrame {
|
|
385
|
-
const originalClustersCol = this.df.getCol(
|
|
386
|
-
const
|
|
387
|
-
const
|
|
510
|
+
const originalClustersCol = this.df.getCol(this.settings.clustersColumnName!);
|
|
511
|
+
const originalClustersColData = originalClustersCol.getRawData();
|
|
512
|
+
const originalClustersColCategories = originalClustersCol.categories;
|
|
513
|
+
|
|
514
|
+
const statsDf = this.df.groupBy([this.settings.clustersColumnName!]).aggregate();
|
|
515
|
+
const clustersCol = statsDf.getCol(this.settings.clustersColumnName!);
|
|
516
|
+
clustersCol.setCategoryOrder(originalClustersColCategories);
|
|
517
|
+
const clustersColData = clustersCol.getRawData();
|
|
518
|
+
|
|
388
519
|
const statsDfCols = statsDf.columns;
|
|
389
|
-
const
|
|
390
|
-
const
|
|
391
|
-
const
|
|
392
|
-
const
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
const
|
|
398
|
-
const
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
520
|
+
const mdColData = statsDfCols.addNewFloat(C.COLUMNS_NAMES.MEAN_DIFFERENCE).getRawData();
|
|
521
|
+
const pValColData = statsDfCols.addNewFloat(C.COLUMNS_NAMES.P_VALUE).getRawData();
|
|
522
|
+
const countColData = statsDfCols.addNewInt(C.COLUMNS_NAMES.COUNT).getRawData();
|
|
523
|
+
const ratioColData = statsDfCols.addNewFloat(C.COLUMNS_NAMES.RATIO).getRawData();
|
|
524
|
+
const activityColData: type.RawData = this.df.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED).getRawData();
|
|
525
|
+
const activityColLen = activityColData.length;
|
|
526
|
+
|
|
527
|
+
for (let rowIdx = 0; rowIdx < clustersColData.length; ++rowIdx) {
|
|
528
|
+
const clusterIdx = clustersColData[rowIdx];
|
|
529
|
+
const mask = new Array(activityColLen);
|
|
530
|
+
let trueCount = 0;
|
|
531
|
+
for (let maskIdx = 0; maskIdx < activityColLen; ++maskIdx) {
|
|
532
|
+
mask[maskIdx] = clusterIdx == originalClustersColData[maskIdx];
|
|
533
|
+
|
|
534
|
+
if (mask[maskIdx])
|
|
535
|
+
++trueCount;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const maskInfo = {
|
|
539
|
+
trueCount: trueCount,
|
|
540
|
+
falseCount: activityColLen - trueCount,
|
|
541
|
+
mask: mask,
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
const stats = getStats(activityColData, maskInfo);
|
|
545
|
+
|
|
546
|
+
mdColData[rowIdx] = stats.meanDifference;
|
|
547
|
+
pValColData[rowIdx] = stats.pValue;
|
|
548
|
+
countColData[rowIdx] = stats.count;
|
|
549
|
+
ratioColData[rowIdx] = stats.ratio;
|
|
404
550
|
}
|
|
405
551
|
return statsDf;
|
|
406
552
|
}
|
|
407
553
|
|
|
408
|
-
|
|
409
|
-
// let sortArgument: string = C.COLUMNS_NAMES.MEAN_DIFFERENCE;
|
|
410
|
-
// if (this.settings.isBidirectional) {
|
|
411
|
-
// const mdCol = this.monomerPositionStatsDf.getCol(sortArgument);
|
|
412
|
-
// sortArgument = 'Absolute Mean difference';
|
|
413
|
-
// const absMDCol = this.monomerPositionStatsDf.columns.addNewFloat(sortArgument);
|
|
414
|
-
// absMDCol.init((i) => Math.abs(mdCol.get(i)));
|
|
415
|
-
// }
|
|
416
|
-
|
|
417
|
-
// const aarWeightsDf = this.monomerPositionStatsDf.groupBy([C.COLUMNS_NAMES.MONOMER]).sum(sortArgument, 'weight')
|
|
418
|
-
// .aggregate();
|
|
419
|
-
// const aarList = aarWeightsDf.getCol(C.COLUMNS_NAMES.MONOMER).toList();
|
|
420
|
-
// const getWeight = (aar: string): number => aarWeightsDf
|
|
421
|
-
// .groupBy(['weight'])
|
|
422
|
-
// .where(`${C.COLUMNS_NAMES.MONOMER} = ${aar}`)
|
|
423
|
-
// .aggregate()
|
|
424
|
-
// .get('weight', 0) as number;
|
|
425
|
-
// aarList.sort((first, second) => getWeight(second) - getWeight(first));
|
|
426
|
-
|
|
427
|
-
// matrixDf.getCol(C.COLUMNS_NAMES.MONOMER).setCategoryOrder(aarList);
|
|
428
|
-
// }
|
|
429
|
-
|
|
430
|
-
createVerticalTable(): DG.DataFrame {
|
|
554
|
+
createMostPotentResiduesDf(): DG.DataFrame {
|
|
431
555
|
// TODO: aquire ALL of the positions
|
|
432
556
|
const columns = [C.COLUMNS_NAMES.MEAN_DIFFERENCE, C.COLUMNS_NAMES.MONOMER, C.COLUMNS_NAMES.POSITION,
|
|
433
557
|
'Count', 'Ratio', C.COLUMNS_NAMES.P_VALUE];
|
|
@@ -440,6 +564,7 @@ export class PeptidesModel {
|
|
|
440
564
|
const posColCategories = sequenceDf.getCol(C.COLUMNS_NAMES.POSITION).categories;
|
|
441
565
|
const mdCol = sequenceDf.getCol(C.COLUMNS_NAMES.MEAN_DIFFERENCE);
|
|
442
566
|
const posCol = sequenceDf.getCol(C.COLUMNS_NAMES.POSITION);
|
|
567
|
+
const monomerCol = sequenceDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
443
568
|
const rowCount = sequenceDf.rowCount;
|
|
444
569
|
for (const pos of posColCategories) {
|
|
445
570
|
tempStats = DG.Stats.fromColumn(mdCol, DG.BitSet.create(rowCount, (i) => posCol.get(i) === pos));
|
|
@@ -447,32 +572,12 @@ export class PeptidesModel {
|
|
|
447
572
|
(tempStats.max > Math.abs(tempStats.min) ? tempStats.max : tempStats.min) :
|
|
448
573
|
tempStats.max;
|
|
449
574
|
}
|
|
450
|
-
sequenceDf = sequenceDf.clone(DG.BitSet.create(rowCount,
|
|
575
|
+
sequenceDf = sequenceDf.clone(DG.BitSet.create(rowCount,
|
|
576
|
+
(i) => monomerCol.get(i) !== '' && maxAtPos[posCol.get(i)] != 0 && mdCol.get(i) === maxAtPos[posCol.get(i)]));
|
|
451
577
|
|
|
452
578
|
return sequenceDf;
|
|
453
579
|
}
|
|
454
580
|
|
|
455
|
-
createGrids(mutationCliffsDf: DG.DataFrame, mostPotentResiduesDf: DG.DataFrame, positionColumns: string[],
|
|
456
|
-
alphabet: string): [DG.Grid, DG.Grid] {
|
|
457
|
-
// Creating Mutation Cliffs grid and sorting columns
|
|
458
|
-
const mutationCliffsGrid = mutationCliffsDf.plot.grid();
|
|
459
|
-
mutationCliffsGrid.sort([C.COLUMNS_NAMES.MONOMER]);
|
|
460
|
-
mutationCliffsGrid.columns.setOrder([C.COLUMNS_NAMES.MONOMER].concat(positionColumns as C.COLUMNS_NAMES[]));
|
|
461
|
-
|
|
462
|
-
// Creating Monomer-Position grid, sorting and setting column format
|
|
463
|
-
const mostPotentResiduesGrid = mostPotentResiduesDf.plot.grid();
|
|
464
|
-
mostPotentResiduesGrid.sort([C.COLUMNS_NAMES.POSITION]);
|
|
465
|
-
const pValGridCol = mostPotentResiduesGrid.col(C.COLUMNS_NAMES.P_VALUE)!;
|
|
466
|
-
pValGridCol.format = '#.000';
|
|
467
|
-
pValGridCol.name = 'P-value';
|
|
468
|
-
|
|
469
|
-
// Setting Monomer column renderer
|
|
470
|
-
CR.setAARRenderer(mutationCliffsDf.getCol(C.COLUMNS_NAMES.MONOMER), alphabet, mutationCliffsGrid);
|
|
471
|
-
CR.setAARRenderer(mostPotentResiduesDf.getCol(C.COLUMNS_NAMES.MONOMER), alphabet, mostPotentResiduesGrid);
|
|
472
|
-
|
|
473
|
-
return [mutationCliffsGrid, mostPotentResiduesGrid];
|
|
474
|
-
}
|
|
475
|
-
|
|
476
581
|
modifyClusterSelection(cluster: number): void {
|
|
477
582
|
const tempSelection = this.logoSummarySelection;
|
|
478
583
|
const idx = tempSelection.indexOf(cluster);
|
|
@@ -489,8 +594,9 @@ export class PeptidesModel {
|
|
|
489
594
|
}
|
|
490
595
|
|
|
491
596
|
setWebLogoInteraction(): void {
|
|
597
|
+
const sourceView = this.analysisView.grid;
|
|
492
598
|
const eventAction = (ev: MouseEvent): void => {
|
|
493
|
-
const cell =
|
|
599
|
+
const cell = sourceView.hitTest(ev.offsetX, ev.offsetY);
|
|
494
600
|
if (cell?.isColHeader && cell.tableColumn?.semType == C.SEM_TYPES.MONOMER) {
|
|
495
601
|
const newBarPart = this.findAARandPosition(cell, ev);
|
|
496
602
|
this.requestBarchartAction(ev, newBarPart);
|
|
@@ -498,9 +604,9 @@ export class PeptidesModel {
|
|
|
498
604
|
};
|
|
499
605
|
|
|
500
606
|
// The following events makes the barchart interactive
|
|
501
|
-
rxjs.fromEvent<MouseEvent>(
|
|
607
|
+
rxjs.fromEvent<MouseEvent>(sourceView.overlay, 'mousemove')
|
|
502
608
|
.subscribe((mouseMove: MouseEvent) => eventAction(mouseMove));
|
|
503
|
-
rxjs.fromEvent<MouseEvent>(
|
|
609
|
+
rxjs.fromEvent<MouseEvent>(sourceView.overlay, 'click')
|
|
504
610
|
.subscribe((mouseMove: MouseEvent) => eventAction(mouseMove));
|
|
505
611
|
}
|
|
506
612
|
|
|
@@ -531,126 +637,58 @@ export class PeptidesModel {
|
|
|
531
637
|
else
|
|
532
638
|
this.cachedWebLogoTooltip = {bar: bar, tooltip: this.showTooltipAt(monomer, position, ev.clientX, ev.clientY)};
|
|
533
639
|
|
|
534
|
-
|
|
640
|
+
//TODO: how to unghighlight?
|
|
535
641
|
// this.df.rows.match(bar).highlight();
|
|
536
642
|
}
|
|
537
643
|
}
|
|
538
644
|
|
|
539
|
-
setCellRenderers(
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
const canvasContext = args.g;
|
|
544
|
-
const bound = args.bounds;
|
|
545
|
-
|
|
546
|
-
canvasContext.save();
|
|
547
|
-
canvasContext.beginPath();
|
|
548
|
-
canvasContext.rect(bound.x, bound.y, bound.width, bound.height);
|
|
549
|
-
canvasContext.clip();
|
|
550
|
-
|
|
551
|
-
// Hide row column
|
|
552
|
-
const cell = args.cell;
|
|
553
|
-
if (cell.isRowHeader && cell.gridColumn.visible) {
|
|
554
|
-
cell.gridColumn.visible = false;
|
|
555
|
-
args.preventDefault();
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
const tableColName = cell.tableColumn?.name;
|
|
560
|
-
const tableRowIndex = cell.tableRowIndex!;
|
|
561
|
-
if (cell.isTableCell && tableColName && tableRowIndex !== null && renderColNames.indexOf(tableColName) !== -1) {
|
|
562
|
-
const cellValue: number | null = cell.cell.value;
|
|
563
|
-
|
|
564
|
-
if (cellValue && cellValue !== DG.INT_NULL && cellValue !== DG.FLOAT_NULL) {
|
|
565
|
-
const gridTable = cell.grid.table;
|
|
566
|
-
const currentPosition: string = tableColName !== C.COLUMNS_NAMES.MEAN_DIFFERENCE ?
|
|
567
|
-
tableColName : gridTable.get(C.COLUMNS_NAMES.POSITION, tableRowIndex);
|
|
568
|
-
const currentAAR: string = gridTable.get(C.COLUMNS_NAMES.MONOMER, tableRowIndex);
|
|
569
|
-
|
|
570
|
-
if (this.isInvariantMap) {
|
|
571
|
-
const value: number = this.monomerPositionStatsDf
|
|
572
|
-
.groupBy([C.COLUMNS_NAMES.POSITION, C.COLUMNS_NAMES.MONOMER, C.COLUMNS_NAMES.COUNT])
|
|
573
|
-
.where(`${C.COLUMNS_NAMES.POSITION} = ${currentPosition} and ${C.COLUMNS_NAMES.MONOMER} = ${currentAAR}`)
|
|
574
|
-
.aggregate().get(C.COLUMNS_NAMES.COUNT, 0);
|
|
575
|
-
CR.renderInvaraintMapCell(
|
|
576
|
-
canvasContext, currentAAR, currentPosition, this.invariantMapSelection, value, bound);
|
|
577
|
-
} else {
|
|
578
|
-
CR.renderMutationCliffCell(canvasContext, currentAAR, currentPosition, this.monomerPositionStatsDf,
|
|
579
|
-
mdCol, bound, cellValue, this.mutationCliffsSelection, this.substitutionsInfo,
|
|
580
|
-
this.settings.isBidirectional);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
args.preventDefault();
|
|
584
|
-
}
|
|
585
|
-
canvasContext.restore();
|
|
586
|
-
};
|
|
587
|
-
this.mutationCliffsGrid.onCellRender.subscribe(renderCell);
|
|
588
|
-
this.mostPotentResiduesGrid.onCellRender.subscribe(renderCell);
|
|
589
|
-
|
|
590
|
-
this.sourceGrid.setOptions({'colHeaderHeight': 130});
|
|
591
|
-
this.sourceGrid.onCellRender.subscribe((gcArgs) => {
|
|
645
|
+
setCellRenderers(): void {
|
|
646
|
+
const sourceGrid = this.analysisView.grid;
|
|
647
|
+
sourceGrid.setOptions({'colHeaderHeight': 130});
|
|
648
|
+
sourceGrid.onCellRender.subscribe((gcArgs) => {
|
|
592
649
|
const ctx = gcArgs.g;
|
|
593
650
|
const bounds = gcArgs.bounds;
|
|
594
651
|
const col = gcArgs.cell.tableColumn;
|
|
595
652
|
|
|
596
653
|
ctx.save();
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
654
|
+
try {
|
|
655
|
+
// ctx.beginPath();
|
|
656
|
+
// ctx.rect(bounds.x, bounds.y, bounds.width, bounds.height);
|
|
657
|
+
// ctx.clip();
|
|
658
|
+
|
|
659
|
+
//TODO: optimize
|
|
660
|
+
if (gcArgs.cell.isColHeader && col?.semType == C.SEM_TYPES.MONOMER) {
|
|
661
|
+
const monomerStatsCol: DG.Column<string> = this.monomerPositionStatsDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
662
|
+
const positionStatsCol: DG.Column<string> = this.monomerPositionStatsDf.getCol(C.COLUMNS_NAMES.POSITION);
|
|
663
|
+
const rowMask = DG.BitSet.create(this.monomerPositionStatsDf.rowCount,
|
|
664
|
+
(i) => positionStatsCol.get(i) === col.name);
|
|
665
|
+
//TODO: precalc on stats creation
|
|
666
|
+
const sortedStatsOrder = this.monomerPositionStatsDf.getSortedOrder([C.COLUMNS_NAMES.COUNT], [false], rowMask)
|
|
667
|
+
.sort((a, b) => {
|
|
668
|
+
if (monomerStatsCol.get(a) === '-' || monomerStatsCol.get(a) === '')
|
|
669
|
+
return -1;
|
|
670
|
+
else if (monomerStatsCol.get(b) === '-' || monomerStatsCol.get(b) === '')
|
|
671
|
+
return +1;
|
|
672
|
+
return 0;
|
|
673
|
+
});
|
|
674
|
+
const statsInfo: type.StatsInfo = {
|
|
675
|
+
countCol: this.monomerPositionStatsDf.getCol(C.COLUMNS_NAMES.COUNT),
|
|
676
|
+
monomerCol: monomerStatsCol,
|
|
677
|
+
orderedIndexes: sortedStatsOrder,
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
this.webLogoBounds[col.name] =
|
|
681
|
+
CR.drawLogoInBounds(ctx, bounds, statsInfo, this.df.rowCount, this.cp, this.headerSelectedMonomers[col.name]);
|
|
682
|
+
gcArgs.preventDefault();
|
|
683
|
+
}
|
|
684
|
+
} finally {
|
|
685
|
+
ctx.restore();
|
|
623
686
|
}
|
|
624
|
-
|
|
625
|
-
ctx.restore();
|
|
626
687
|
});
|
|
627
688
|
}
|
|
628
689
|
|
|
629
|
-
setTooltips(
|
|
630
|
-
|
|
631
|
-
const tableCol = cell.tableColumn;
|
|
632
|
-
const tableColName = tableCol?.name;
|
|
633
|
-
const tableRowIndex = cell.tableRowIndex;
|
|
634
|
-
|
|
635
|
-
if (!cell.isRowHeader && !cell.isColHeader && tableCol && tableRowIndex != null) {
|
|
636
|
-
const table = cell.grid.table;
|
|
637
|
-
const currentAAR = table.get(C.COLUMNS_NAMES.MONOMER, tableRowIndex);
|
|
638
|
-
|
|
639
|
-
if (tableCol.semType == C.SEM_TYPES.MONOMER)
|
|
640
|
-
this.showMonomerTooltip(currentAAR, x, y);
|
|
641
|
-
else if (cell.cell.value && renderColNames.includes(tableColName!)) {
|
|
642
|
-
const currentPosition = tableColName !== C.COLUMNS_NAMES.MEAN_DIFFERENCE ? tableColName :
|
|
643
|
-
table.get(C.COLUMNS_NAMES.POSITION, tableRowIndex);
|
|
644
|
-
|
|
645
|
-
this.showTooltipAt(currentAAR, currentPosition, x, y);
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
return true;
|
|
649
|
-
};
|
|
650
|
-
|
|
651
|
-
this.mutationCliffsGrid.onCellTooltip(showTooltip);
|
|
652
|
-
this.mostPotentResiduesGrid.onCellTooltip(showTooltip);
|
|
653
|
-
this.sourceGrid.onCellTooltip((cell, x, y) => {
|
|
690
|
+
setTooltips(): void {
|
|
691
|
+
this.analysisView.grid.onCellTooltip((cell, x, y) => {
|
|
654
692
|
const col = cell.tableColumn;
|
|
655
693
|
const cellValue = cell.cell.value;
|
|
656
694
|
if (cellValue && col && col.semType === C.SEM_TYPES.MONOMER)
|
|
@@ -663,8 +701,8 @@ export class PeptidesModel {
|
|
|
663
701
|
const tooltipElements: HTMLDivElement[] = [];
|
|
664
702
|
const monomerName = aar.toLowerCase();
|
|
665
703
|
|
|
666
|
-
|
|
667
|
-
|
|
704
|
+
const mw = getMonomerWorks();
|
|
705
|
+
const mol = mw?.getCappedRotatedMonomer('PEPTIDE', aar);
|
|
668
706
|
|
|
669
707
|
if (mol) {
|
|
670
708
|
tooltipElements.push(ui.div(monomerName));
|
|
@@ -676,13 +714,30 @@ export class PeptidesModel {
|
|
|
676
714
|
ui.tooltip.show(ui.divV(tooltipElements), x, y);
|
|
677
715
|
}
|
|
678
716
|
|
|
717
|
+
//TODO: move out to viewer code
|
|
679
718
|
showTooltipAt(aar: string, position: string, x: number, y: number): HTMLDivElement | null {
|
|
680
719
|
const currentStatsDf = this.monomerPositionStatsDf.rows.match({Pos: position, AAR: aar}).toDataFrame();
|
|
681
|
-
const activityCol = this.df.
|
|
720
|
+
const activityCol = this.df.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
682
721
|
//TODO: use bitset instead of splitCol
|
|
683
722
|
const splitCol = DG.Column.bool(C.COLUMNS_NAMES.SPLIT_COL, activityCol.length);
|
|
684
723
|
const currentPosCol = this.df.getCol(position);
|
|
685
|
-
|
|
724
|
+
const indexes: number[] = [];
|
|
725
|
+
splitCol.init((i) => {
|
|
726
|
+
const sameMonomer = currentPosCol.get(i) == aar;
|
|
727
|
+
if (sameMonomer)
|
|
728
|
+
indexes.push(i);
|
|
729
|
+
|
|
730
|
+
return sameMonomer;
|
|
731
|
+
});
|
|
732
|
+
const colResults: {[colName: string]: number} = {};
|
|
733
|
+
for (const [col, agg] of Object.entries(this.settings.columns ?? {})) {
|
|
734
|
+
const currentCol = this.df.getCol(col);
|
|
735
|
+
const currentColData = currentCol.getRawData();
|
|
736
|
+
const tempCol = DG.Column.float('', indexes.length);
|
|
737
|
+
tempCol.init((i) => currentColData[indexes[i]]);
|
|
738
|
+
colResults[`${agg}(${col})`] = tempCol.stats[agg as keyof DG.Stats] as number;
|
|
739
|
+
}
|
|
740
|
+
|
|
686
741
|
const distributionTable = DG.DataFrame.fromColumns([activityCol, splitCol]);
|
|
687
742
|
const stats: Stats = {
|
|
688
743
|
count: currentStatsDf.get(C.COLUMNS_NAMES.COUNT, 0),
|
|
@@ -693,19 +748,21 @@ export class PeptidesModel {
|
|
|
693
748
|
if (!stats.count)
|
|
694
749
|
return null;
|
|
695
750
|
|
|
696
|
-
const
|
|
751
|
+
const distroStatsElem = getDistributionAndStats(distributionTable, stats, `${position} : ${aar}`, 'Other', true);
|
|
697
752
|
|
|
698
|
-
ui.tooltip.show(
|
|
753
|
+
ui.tooltip.show(ui.divV([distroStatsElem, ui.tableFromMap(colResults)]), x, y);
|
|
699
754
|
|
|
700
|
-
return
|
|
755
|
+
return distroStatsElem;
|
|
701
756
|
}
|
|
702
757
|
|
|
703
758
|
showTooltipCluster(cluster: number, x: number, y: number): HTMLDivElement | null {
|
|
704
|
-
const
|
|
705
|
-
|
|
759
|
+
const matcher: {[key: string]: number} = {};
|
|
760
|
+
matcher[this.settings.clustersColumnName!] = cluster;
|
|
761
|
+
const currentStatsDf = this.clusterStatsDf.rows.match(matcher).toDataFrame();
|
|
762
|
+
const activityCol = this.df.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
|
|
706
763
|
//TODO: use bitset instead of splitCol
|
|
707
764
|
const splitCol = DG.Column.bool(C.COLUMNS_NAMES.SPLIT_COL, activityCol.length);
|
|
708
|
-
const currentClusterCol = this.df.getCol(
|
|
765
|
+
const currentClusterCol = this.df.getCol(this.settings.clustersColumnName!);
|
|
709
766
|
splitCol.init((i) => currentClusterCol.get(i) == cluster);
|
|
710
767
|
const distributionTable = DG.DataFrame.fromColumns([activityCol, splitCol]);
|
|
711
768
|
const stats: Stats = {
|
|
@@ -724,48 +781,6 @@ export class PeptidesModel {
|
|
|
724
781
|
return tooltip;
|
|
725
782
|
}
|
|
726
783
|
|
|
727
|
-
setInteractionCallback(): void {
|
|
728
|
-
const mutationCliffsDf = this.mutationCliffsGrid.dataFrame;
|
|
729
|
-
const mostPotentResiduesDf = this.mostPotentResiduesGrid.dataFrame;
|
|
730
|
-
|
|
731
|
-
const chooseAction =
|
|
732
|
-
(aar: string, position: string, isShiftPressed: boolean, isInvariantMapSelection: boolean = true): void => {
|
|
733
|
-
isShiftPressed ? this.modifyMonomerPositionSelection(aar, position, isInvariantMapSelection) :
|
|
734
|
-
this.initMonomerPositionSelection(aar, position, isInvariantMapSelection);
|
|
735
|
-
};
|
|
736
|
-
|
|
737
|
-
this.mutationCliffsGrid.root.addEventListener('click', (ev) => {
|
|
738
|
-
const gridCell = this.mutationCliffsGrid.hitTest(ev.offsetX, ev.offsetY);
|
|
739
|
-
if (isGridCellInvalid(gridCell) || gridCell!.tableColumn!.name == C.COLUMNS_NAMES.MONOMER)
|
|
740
|
-
return;
|
|
741
|
-
|
|
742
|
-
const position = gridCell!.tableColumn!.name;
|
|
743
|
-
const aar = mutationCliffsDf.get(C.COLUMNS_NAMES.MONOMER, gridCell!.tableRowIndex!);
|
|
744
|
-
chooseAction(aar, position, ev.shiftKey, this.isInvariantMap);
|
|
745
|
-
});
|
|
746
|
-
|
|
747
|
-
this.mostPotentResiduesGrid.root.addEventListener('click', (ev) => {
|
|
748
|
-
const gridCell = this.mostPotentResiduesGrid.hitTest(ev.offsetX, ev.offsetY);
|
|
749
|
-
if (isGridCellInvalid(gridCell) || gridCell!.tableColumn!.name != C.COLUMNS_NAMES.MEAN_DIFFERENCE)
|
|
750
|
-
return;
|
|
751
|
-
|
|
752
|
-
const tableRowIdx = gridCell!.tableRowIndex!;
|
|
753
|
-
const position = mostPotentResiduesDf.get(C.COLUMNS_NAMES.POSITION, tableRowIdx);
|
|
754
|
-
const aar = mostPotentResiduesDf.get(C.COLUMNS_NAMES.MONOMER, tableRowIdx);
|
|
755
|
-
chooseAction(aar, position, ev.shiftKey, false);
|
|
756
|
-
});
|
|
757
|
-
|
|
758
|
-
const cellChanged = (table: DG.DataFrame): void => {
|
|
759
|
-
if (this.isCellChanging)
|
|
760
|
-
return;
|
|
761
|
-
this.isCellChanging = true;
|
|
762
|
-
table.currentRowIdx = -1;
|
|
763
|
-
this.isCellChanging = false;
|
|
764
|
-
};
|
|
765
|
-
this.mutationCliffsGrid.onCurrentCellChanged.subscribe((_gc) => cellChanged(mutationCliffsDf));
|
|
766
|
-
this.mostPotentResiduesGrid.onCurrentCellChanged.subscribe((_gc) => cellChanged(mostPotentResiduesDf));
|
|
767
|
-
}
|
|
768
|
-
|
|
769
784
|
modifyMonomerPositionSelection(aar: string, position: string, isInvariantMapSelection: boolean): void {
|
|
770
785
|
const tempSelection = isInvariantMapSelection ? this.invariantMapSelection : this.mutationCliffsSelection;
|
|
771
786
|
const tempSelectionAt = tempSelection[position];
|
|
@@ -793,19 +808,13 @@ export class PeptidesModel {
|
|
|
793
808
|
this.mutationCliffsSelection = tempSelection;
|
|
794
809
|
}
|
|
795
810
|
|
|
796
|
-
invalidateGrids(): void {
|
|
797
|
-
this.mutationCliffsGrid.invalidate();
|
|
798
|
-
this.mostPotentResiduesGrid.invalidate();
|
|
799
|
-
// this.logoSummaryGrid?.invalidate();
|
|
800
|
-
this.sourceGrid?.invalidate();
|
|
801
|
-
}
|
|
802
|
-
|
|
803
811
|
setBitsetCallback(): void {
|
|
804
812
|
if (this.isBitsetChangedInitialized)
|
|
805
813
|
return;
|
|
806
814
|
const selection = this.df.selection;
|
|
807
815
|
const filter = this.df.filter;
|
|
808
|
-
const clusterCol = this.df.col(
|
|
816
|
+
const clusterCol = this.df.col(this.settings.clustersColumnName!);
|
|
817
|
+
const clusterColData = clusterCol?.getRawData();
|
|
809
818
|
|
|
810
819
|
const changeSelectionBitset = (currentBitset: DG.BitSet): void => {
|
|
811
820
|
const edfSelection = this.edf?.selection;
|
|
@@ -832,7 +841,7 @@ export class PeptidesModel {
|
|
|
832
841
|
if (this.mutationCliffsSelection[position].includes(positionCol.get(i)!))
|
|
833
842
|
return true;
|
|
834
843
|
}
|
|
835
|
-
if (this.logoSummarySelection.includes(
|
|
844
|
+
if (clusterColData && this.logoSummarySelection.includes(clusterColData[i]))
|
|
836
845
|
return true;
|
|
837
846
|
return false;
|
|
838
847
|
};
|
|
@@ -842,7 +851,7 @@ export class PeptidesModel {
|
|
|
842
851
|
};
|
|
843
852
|
|
|
844
853
|
selection.onChanged.subscribe(() => changeSelectionBitset(selection));
|
|
845
|
-
|
|
854
|
+
|
|
846
855
|
filter.onChanged.subscribe(() => {
|
|
847
856
|
const positionList = Object.keys(this.invariantMapSelection);
|
|
848
857
|
const invariantMapBitset = DG.BitSet.create(filter.length, (index) => {
|
|
@@ -859,7 +868,6 @@ export class PeptidesModel {
|
|
|
859
868
|
if (!this.isInvariantMapTrigger)
|
|
860
869
|
this.initBitset = filter.clone();
|
|
861
870
|
|
|
862
|
-
// filter.copyFrom(invariantMapBitset.and(this.initBitset), false);
|
|
863
871
|
const temp = invariantMapBitset.and(this.initBitset);
|
|
864
872
|
filter.init((i) => temp.get(i), false);
|
|
865
873
|
});
|
|
@@ -871,54 +879,35 @@ export class PeptidesModel {
|
|
|
871
879
|
this.df.selection.fireChanged();
|
|
872
880
|
this.modifyOrCreateSplitCol();
|
|
873
881
|
this.headerSelectedMonomers = calculateSelected(this.df);
|
|
874
|
-
|
|
882
|
+
const acc = this.createAccordion();
|
|
883
|
+
grok.shell.o = acc.root;
|
|
884
|
+
for (const pane of acc.panes)
|
|
885
|
+
pane.expanded = true;
|
|
875
886
|
this.isPeptideSpaceChangingBitset = false;
|
|
876
887
|
}
|
|
877
888
|
|
|
878
|
-
postProcessGrids(
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
const setViewerGridProps = (grid: DG.Grid): void => {
|
|
897
|
-
const gridProps = grid.props;
|
|
898
|
-
gridProps.allowEdit = false;
|
|
899
|
-
gridProps.allowRowSelection = false;
|
|
900
|
-
gridProps.allowBlockSelection = false;
|
|
901
|
-
gridProps.allowColSelection = false;
|
|
902
|
-
};
|
|
903
|
-
|
|
904
|
-
setViewerGridProps(this.mutationCliffsGrid);
|
|
905
|
-
setViewerGridProps(this.mostPotentResiduesGrid);
|
|
906
|
-
// if (this.df.getTag(C.TAGS.CLUSTERS))
|
|
907
|
-
// setViewerGridProps(this.logoSummaryGrid);
|
|
908
|
-
|
|
909
|
-
for (let gcIndex = 0; gcIndex < this.sourceGrid.columns.length; ++gcIndex) {
|
|
910
|
-
const col = this.sourceGrid.columns.byIndex(gcIndex)!;
|
|
911
|
-
if (!col.column)
|
|
912
|
-
continue;
|
|
913
|
-
|
|
914
|
-
if (posCols.includes(col.name))
|
|
915
|
-
col.name = col.name.substring(1);
|
|
916
|
-
|
|
917
|
-
col.visible =
|
|
918
|
-
col.column?.semType === C.SEM_TYPES.MONOMER ||
|
|
919
|
-
col.column.name === C.COLUMNS_NAMES.ACTIVITY_SCALED ||
|
|
920
|
-
Object.keys(this.settings.columns ?? {}).includes(col.column.name ?? '');
|
|
889
|
+
postProcessGrids(): void {
|
|
890
|
+
const posCols = this.splitSeqDf.columns.names();
|
|
891
|
+
const sourceGrid = this.analysisView.grid;
|
|
892
|
+
const sourceGridCols = sourceGrid.columns;
|
|
893
|
+
const sourceGridColsLen = sourceGridCols.length;
|
|
894
|
+
const visibleColumns = Object.keys(this.settings.columns ?? {});
|
|
895
|
+
const sourceGridProps = sourceGrid.props;
|
|
896
|
+
sourceGridProps.allowColSelection = false;
|
|
897
|
+
sourceGridProps.allowEdit = false;
|
|
898
|
+
sourceGridProps.allowRowResizing = false;
|
|
899
|
+
sourceGridProps.showCurrentRowIndicator = false;
|
|
900
|
+
this.df.temp[C.EMBEDDING_STATUS] = false;
|
|
901
|
+
for (let colIdx = 1; colIdx < sourceGridColsLen; ++colIdx) {
|
|
902
|
+
const gridCol = sourceGridCols.byIndex(colIdx)!;
|
|
903
|
+
const tableColName = gridCol.column!.name;
|
|
904
|
+
gridCol.visible = posCols.includes(tableColName) || (tableColName === C.COLUMNS_NAMES.ACTIVITY_SCALED) ||
|
|
905
|
+
visibleColumns.includes(tableColName);
|
|
906
|
+
gridCol.width = 60;
|
|
921
907
|
}
|
|
908
|
+
setTimeout(() => {
|
|
909
|
+
sourceGridProps.rowHeight = 20;
|
|
910
|
+
}, 500);
|
|
922
911
|
}
|
|
923
912
|
|
|
924
913
|
getSplitColValueAt(index: number, aar: string, position: string, aarLabel: string): string {
|
|
@@ -935,77 +924,41 @@ export class PeptidesModel {
|
|
|
935
924
|
}
|
|
936
925
|
|
|
937
926
|
/** Class initializer */
|
|
938
|
-
|
|
927
|
+
init(): void {
|
|
939
928
|
if (this.isInitialized)
|
|
940
929
|
return;
|
|
941
930
|
this.isInitialized = true;
|
|
942
931
|
|
|
943
|
-
// Don't find the dataset if the analysis started from button
|
|
944
|
-
if (this.df.getTag('newAnalysis') !== '1')
|
|
945
|
-
this.currentView = wu(grok.shell.tableViews).find(({dataFrame}) => dataFrame.tags[C.PEPTIDES_ANALYSIS] === '1')!;
|
|
946
|
-
|
|
947
|
-
this.currentView ??= grok.shell.addTableView(this.df);
|
|
948
|
-
|
|
949
|
-
this.df.setTag('newAnalysis', '');
|
|
950
932
|
if (!this.isRibbonSet) {
|
|
951
933
|
//TODO: don't pass model, pass parameters instead
|
|
952
934
|
const settingsButton = ui.bigButton('Settings', () => getSettingsDialog(this), 'Peptides analysis settings');
|
|
953
|
-
this.
|
|
935
|
+
this.analysisView.setRibbonPanels([[settingsButton]], false);
|
|
954
936
|
this.isRibbonSet = true;
|
|
955
937
|
}
|
|
956
|
-
grok.shell.v = this.currentView;
|
|
957
|
-
this.sourceGrid = this.currentView.grid;
|
|
958
|
-
if (this.df.tags[C.PEPTIDES_ANALYSIS] === '1')
|
|
959
|
-
return;
|
|
960
938
|
|
|
961
939
|
this.df.tags[C.PEPTIDES_ANALYSIS] = '1';
|
|
962
|
-
const scaledGridCol = this.sourceGrid.col(C.COLUMNS_NAMES.ACTIVITY_SCALED)!;
|
|
963
|
-
scaledGridCol.name = scaledGridCol.column!.getTag('gridName');
|
|
964
|
-
scaledGridCol.format = '#.000';
|
|
965
|
-
this.sourceGrid.columns.setOrder([scaledGridCol.name]);
|
|
966
|
-
this.sourceGrid.props.allowColSelection = false;
|
|
967
940
|
|
|
968
|
-
this.
|
|
969
|
-
const adjustCellSize = (grid: DG.Grid): void => {
|
|
970
|
-
const colNum = grid.columns.length;
|
|
971
|
-
for (let i = 0; i < colNum; ++i) {
|
|
972
|
-
const iCol = grid.columns.byIndex(i)!;
|
|
973
|
-
iCol.width = isNaN(parseInt(iCol.name)) ? 50 : 40;
|
|
974
|
-
}
|
|
975
|
-
grid.props.rowHeight = 20;
|
|
976
|
-
};
|
|
977
|
-
|
|
978
|
-
for (let i = 0; i < this.sourceGrid.columns.length; i++) {
|
|
979
|
-
const currentCol = this.sourceGrid.columns.byIndex(i);
|
|
980
|
-
if (currentCol?.column?.getTag(C.TAGS.VISIBLE) === '0')
|
|
981
|
-
currentCol.visible = false;
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
const options = {scaling: this.df.tags['scaling']};
|
|
985
|
-
|
|
986
|
-
const dockManager = this.currentView.dockManager;
|
|
987
|
-
|
|
988
|
-
const mutationCliffsViewer = await this.df.plot.fromType('peptide-sar-viewer', options) as MutationCliffsViewer;
|
|
941
|
+
this.updateDefault();
|
|
989
942
|
|
|
990
|
-
|
|
991
|
-
|
|
943
|
+
this.analysisView.grid.invalidate();
|
|
944
|
+
}
|
|
992
945
|
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
}
|
|
946
|
+
async addViewers(): Promise<void> {
|
|
947
|
+
const dockManager = this.analysisView.dockManager;
|
|
948
|
+
const dfPlt = this.df.plot;
|
|
997
949
|
|
|
998
|
-
|
|
950
|
+
const mutationCliffsViewer = await dfPlt.fromType('peptide-sar-viewer') as MonomerPosition;
|
|
951
|
+
const mostPotentResiduesViewer = await dfPlt.fromType('peptide-sar-viewer-vertical') as MostPotentResiduesViewer;
|
|
952
|
+
if (this.settings.clustersColumnName)
|
|
953
|
+
await this.addLogoSummaryTableViewer();
|
|
999
954
|
|
|
1000
|
-
const mcNode =
|
|
1001
|
-
dockManager.dock(mutationCliffsViewer, DG.DOCK_TYPE.DOWN, null, mutationCliffsViewer.name);
|
|
955
|
+
const mcNode = dockManager.dock(mutationCliffsViewer, DG.DOCK_TYPE.DOWN, null, mutationCliffsViewer.name);
|
|
1002
956
|
|
|
1003
957
|
dockManager.dock(mostPotentResiduesViewer, DG.DOCK_TYPE.RIGHT, mcNode, mostPotentResiduesViewer.name, 0.3);
|
|
958
|
+
}
|
|
1004
959
|
|
|
1005
|
-
|
|
1006
|
-
this.
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
this.invalidateGrids();
|
|
960
|
+
async addLogoSummaryTableViewer(): Promise<void> {
|
|
961
|
+
const logoSummary = await this.df.plot.fromType('logo-summary-viewer') as LogoSummary;
|
|
962
|
+
this.analysisView.dockManager.dock(logoSummary, DG.DOCK_TYPE.RIGHT, null, 'Logo Summary Table');
|
|
1010
963
|
}
|
|
1011
964
|
}
|