@datagrok/peptides 1.4.0 → 1.7.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.
@@ -1,11 +1,16 @@
1
1
  import * as ui from 'datagrok-api/ui';
2
+ import * as grok from 'datagrok-api/grok';
2
3
  import * as DG from 'datagrok-api/dg';
3
4
 
4
5
  import $ from 'cash-dom';
5
6
  import {PeptidesModel} from '../model';
6
7
  import * as C from '../utils/constants';
7
8
  import * as CR from '../utils/cell-renderer';
8
- import * as bio from '@datagrok-libraries/bio';
9
+ import {TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
10
+ import {PositionHeight} from '@datagrok-libraries/bio/src/viewers/web-logo';
11
+ import {getStats, MaskInfo, Stats} from '../utils/statistics';
12
+ import wu from 'wu';
13
+ import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
9
14
 
10
15
  export class LogoSummary extends DG.JsViewer {
11
16
  _titleHost = ui.divText('Logo Summary Table', {id: 'pep-viewer-title'});
@@ -13,29 +18,35 @@ export class LogoSummary extends DG.JsViewer {
13
18
  viewerGrid!: DG.Grid;
14
19
  initialized: boolean = false;
15
20
  webLogoMode: string;
16
- importanceThreshold: number;
21
+ membersRatioThreshold: number;
22
+ newClusterName: string;
23
+ webLogoDfPlot: DG.DataFramePlotHelper[] = [];
24
+ distributionDfPlot: DG.DataFramePlotHelper[] = [];
17
25
 
18
26
  constructor() {
19
27
  super();
20
28
 
21
- this.webLogoMode = this.string('webLogoMode', bio.PositionHeight.full, {choices: [bio.PositionHeight.full, bio.PositionHeight.Entropy]});
22
- this.importanceThreshold = this.float('importanceThreshold', 0.7);
29
+ this.webLogoMode = this.string('webLogoMode', PositionHeight.full,
30
+ {choices: [PositionHeight.full, PositionHeight.Entropy]});
31
+ this.membersRatioThreshold = this.float('membersRatioThreshold', 0.7, {min: 0, max: 1.0});
32
+ this.newClusterName = this.string('newClusterName', 'New cluster');
23
33
  }
24
34
 
25
- async onTableAttached(): Promise<void> {
35
+ onTableAttached(): void {
26
36
  super.onTableAttached();
27
37
 
28
- this.model = await PeptidesModel.getInstance(this.dataFrame);
38
+ this.model = PeptidesModel.getInstance(this.dataFrame);
29
39
  this.subs.push(this.model.onSettingsChanged.subscribe(() => {
30
40
  this.createLogoSummaryGrid();
31
41
  this.render();
32
42
  }));
33
- // this.subs.push(this.model.onLogoSummaryGridChanged.subscribe((grid) => {
34
- // this.viewerGrid = grid;
35
- // this.render();
36
- // }));
37
- // this.model.updateDefault();
38
- // this.viewerGrid = this.model.logoSummaryGrid;
43
+ this.subs.push(this.model.onNewCluster.subscribe(() => this.clusterFromSelection()));
44
+ this.subs.push(this.model.onRemoveCluster.subscribe(() => this.removeCluster()));
45
+ this.subs.push(this.model.onFilterChanged.subscribe(() => {
46
+ this.createLogoSummaryGrid();
47
+ this.render();
48
+ }));
49
+
39
50
  this.createLogoSummaryGrid();
40
51
  this.initialized = true;
41
52
  this.render();
@@ -46,83 +57,213 @@ export class LogoSummary extends DG.JsViewer {
46
57
  render(): void {
47
58
  if (this.initialized) {
48
59
  $(this.root).empty();
60
+ const df = this.viewerGrid.dataFrame;
61
+ if (!df.filter.anyTrue) {
62
+ const emptyDf = ui.divText('No clusters to satisfy the threshold. ' +
63
+ 'Please, lower the threshold in viewer proeperties to include clusters');
64
+ this.root.appendChild(ui.divV([this._titleHost, emptyDf]));
65
+ return;
66
+ }
49
67
  this.viewerGrid.root.style.width = 'auto';
50
68
  this.root.appendChild(ui.divV([this._titleHost, this.viewerGrid.root]));
51
69
  this.viewerGrid.invalidate();
52
70
  }
53
71
  }
54
72
 
55
- onPropertyChanged(): void {
56
- this.createLogoSummaryGrid();
73
+ onPropertyChanged(property: DG.Property): void {
74
+ super.onPropertyChanged(property);
75
+ if (property.name == 'membersRatioThreshold')
76
+ this.updateFilter();
57
77
  this.render();
58
78
  }
59
79
 
60
80
  createLogoSummaryGrid(): DG.Grid {
61
- let summaryTableBuilder = this.dataFrame.groupBy([C.COLUMNS_NAMES.CLUSTERS]);
62
- for (const [colName, aggregationFunc] of Object.entries(this.model.settings.columns ?? {}))
63
- summaryTableBuilder = summaryTableBuilder.add(aggregationFunc as any, colName, `${aggregationFunc}(${colName})`);
64
-
65
- const summaryTable = summaryTableBuilder.aggregate();
66
- const summaryTableLength = summaryTable.rowCount;
67
- const clustersCol: DG.Column<number> = summaryTable.getCol(C.COLUMNS_NAMES.CLUSTERS);
68
- const membersCol: DG.Column<number> = summaryTable.columns.addNewInt('Members');
69
- const webLogoCol: DG.Column<string> = summaryTable.columns.addNew('WebLogo', DG.COLUMN_TYPE.STRING);
70
- const tempDfList: DG.DataFrame[] = new Array(summaryTableLength);
71
- const originalClustersCol = this.dataFrame.getCol(C.COLUMNS_NAMES.CLUSTERS);
72
- const peptideCol: DG.Column<string> = this.dataFrame.getCol(C.COLUMNS_NAMES.MACROMOLECULE);
73
-
74
- for (let index = 0; index < summaryTableLength; ++index) {
75
- const indexes: number[] = [];
76
- for (let j = 0; j < originalClustersCol.length; ++j) {
77
- if (originalClustersCol.get(j) === clustersCol.get(index))
78
- indexes.push(j);
81
+ const clustersColName = this.model.settings.clustersColumnName!;
82
+ const isDfFiltered = this.dataFrame.filter.anyFalse;
83
+ const filteredDf = isDfFiltered ? this.dataFrame.clone(this.dataFrame.filter) : this.dataFrame;
84
+ const filteredDfCols = filteredDf.columns;
85
+ const activityCol = filteredDf.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
86
+ const activityColData = activityCol.getRawData();
87
+
88
+ const filteredDfClustersCol = filteredDf.getCol(clustersColName);
89
+ const filteredDfClustersColData = filteredDfClustersCol.getRawData();
90
+ const filteredDfClustersColCategories = filteredDfClustersCol.categories;
91
+ const filteredDfClustersColLength = filteredDfClustersColData.length;
92
+
93
+ // const customClustersColumnsList = wu(this.model.customClusters).toArray();
94
+ const query: { [key: string]: string } = {};
95
+ query[C.TAGS.CUSTOM_CLUSTER] = '1';
96
+ const customClustersColumnsList = wu(filteredDfCols.byTags(query)).filter(c => c.max > 0).toArray();
97
+ const getAggregatedColName = (aggF: string, colName: string) => `${aggF}(${colName})`;
98
+ const isCustomCluster = (cluster: string) => filteredDfCols.contains(cluster);
99
+
100
+ let summaryTableBuilder = filteredDf.groupBy([clustersColName]);
101
+ const aggregateColumnsEntries = Object.entries(this.model.settings.columns ?? {});
102
+ for (const [colName, aggregationFunc] of aggregateColumnsEntries) {
103
+ summaryTableBuilder = summaryTableBuilder.add(
104
+ aggregationFunc as any, colName, getAggregatedColName(aggregationFunc, colName));
105
+ }
106
+
107
+ const tempSummaryTable = summaryTableBuilder.aggregate();
108
+ const tempSummaryTableLength = tempSummaryTable.rowCount;
109
+ const tempClustersCol: DG.Column<string> = tempSummaryTable.getCol(clustersColName);
110
+ const summaryTableLength = tempSummaryTableLength + customClustersColumnsList.length;
111
+ const summaryTable = DG.DataFrame.create(summaryTableLength);
112
+ const summaryTableCols = summaryTable.columns;
113
+
114
+ const clustersCol = summaryTableCols.addNewString(clustersColName);
115
+ for (let i = 0; i < summaryTableLength; ++i) {
116
+ clustersCol.set(i, i < tempSummaryTableLength ? tempClustersCol.get(i) :
117
+ customClustersColumnsList[i - tempSummaryTableLength].name);
118
+ }
119
+ const clustersColData = clustersCol.getRawData();
120
+ const clustersColCategories = clustersCol.categories;
121
+
122
+ const peptideCol: DG.Column<string> = filteredDf.getCol(this.model.settings.sequenceColumnName!);
123
+ const peptideColData = peptideCol.getRawData();
124
+ const peptideColCategories = peptideCol.categories;
125
+ const peptideColTags = peptideCol.tags;
126
+
127
+ const membersColData = summaryTableCols.addNewInt(C.LST_COLUMN_NAMES.MEMBERS).getRawData();
128
+ const webLogoCol = summaryTableCols.addNewString(C.LST_COLUMN_NAMES.WEB_LOGO);
129
+ const distributionCol = summaryTableCols.addNewString(C.LST_COLUMN_NAMES.DISTRIBUTION);
130
+ const meanDifferenceColData = summaryTableCols.addNewFloat(C.LST_COLUMN_NAMES.MEAN_DIFFERENCE).getRawData();
131
+ const pValColData = summaryTableCols.addNewFloat(C.LST_COLUMN_NAMES.P_VALUE).getRawData();
132
+ const ratioColData = summaryTableCols.addNewFloat(C.LST_COLUMN_NAMES.RATIO).getRawData();
133
+
134
+ for (const [colName, aggregationFunc] of aggregateColumnsEntries) {
135
+ const tempSummaryTableCol = tempSummaryTable.getCol(getAggregatedColName(aggregationFunc, colName));
136
+ const summaryTableCol = summaryTableCols.addNew(tempSummaryTableCol.name, tempSummaryTableCol.type);
137
+ summaryTableCol.init((i) => i < tempSummaryTableLength ? tempSummaryTableCol.get(i) : null);
138
+ }
139
+
140
+ this.webLogoDfPlot = new Array(summaryTableLength);
141
+ this.distributionDfPlot = new Array(summaryTableLength);
142
+
143
+ for (let summaryTableRowIndex = 0; summaryTableRowIndex < summaryTableLength; ++summaryTableRowIndex) {
144
+ const isOriginalCluster = summaryTableRowIndex < tempSummaryTableLength;
145
+ const currentClusterCategoryIndex = clustersColData[summaryTableRowIndex];
146
+ const currentCluster = clustersColCategories[currentClusterCategoryIndex]; // Cluster name
147
+ const customClusterColData = customClustersColumnsList.find((col) => col.name == currentCluster)?.toList();
148
+
149
+ const isValidIndex = isOriginalCluster ?
150
+ (j: number) => filteredDfClustersColCategories[filteredDfClustersColData[j]] == currentCluster :
151
+ (j: number) => customClusterColData![j];
152
+
153
+
154
+ //TODO: use bitset instead of splitCol
155
+ const splitCol = DG.Column.bool(C.COLUMNS_NAMES.SPLIT_COL, activityCol.length);
156
+ const getSplitColValueAt = isOriginalCluster ?
157
+ (splitColIndex: number) => filteredDfClustersColData[splitColIndex] == currentClusterCategoryIndex :
158
+ (splitColIndex: number) => customClusterColData![splitColIndex];
159
+ splitCol.init((i) => getSplitColValueAt(i));
160
+
161
+ let stats: Stats;
162
+ if (isDfFiltered) {
163
+ const trueCount = splitCol.stats.sum;
164
+ const maskInfo = {
165
+ trueCount: trueCount,
166
+ falseCount: activityColData.length - trueCount,
167
+ mask: splitCol.toList() as boolean[],
168
+ };
169
+ stats = getStats(activityColData, maskInfo);
170
+ } else
171
+ stats = this.model.clusterStats[currentCluster];
172
+
173
+ const tCol = DG.Column.string('peptides', stats.count);
174
+ let tColIdx = 0;
175
+ for (let j = 0; j < filteredDfClustersColLength; ++j) {
176
+ if (isValidIndex(j))
177
+ tCol.set(tColIdx++, peptideColCategories[peptideColData[j]]);
79
178
  }
80
- const tCol = DG.Column.string('peptides', indexes.length);
81
- tCol.init((i) => peptideCol.get(indexes[i]));
82
179
 
83
- for (const tag of peptideCol.tags)
180
+ for (const tag of peptideColTags)
84
181
  tCol.setTag(tag[0], tag[1]);
85
182
 
86
- const uh = new bio.UnitsHandler(tCol);
87
- tCol.setTag(bio.TAGS.alphabetSize, uh.getAlphabetSize().toString());
183
+ const uh = new UnitsHandler(tCol);
184
+ tCol.setTag(bioTAGS.alphabetSize, uh.getAlphabetSize().toString());
185
+
88
186
 
187
+ const distributionTable = DG.DataFrame.fromColumns([activityCol, splitCol]);
89
188
  const dfSlice = DG.DataFrame.fromColumns([tCol]);
90
- tempDfList[index] = dfSlice;
91
- webLogoCol.set(index, index.toString());
92
- membersCol.set(index, dfSlice.rowCount);
93
- //TODO: user should be able to choose threshold
94
- if (dfSlice.rowCount <= Math.ceil(this.model.clusterStatsDf.getCol(C.COLUMNS_NAMES.COUNT).stats.max * this.importanceThreshold))
95
- summaryTable.filter.set(index, false, false);
189
+
190
+ this.webLogoDfPlot[summaryTableRowIndex] = dfSlice.plot;
191
+ this.distributionDfPlot[summaryTableRowIndex] = distributionTable.plot;
192
+
193
+ membersColData[summaryTableRowIndex] = stats.count;
194
+ meanDifferenceColData[summaryTableRowIndex] = stats.meanDifference;
195
+ pValColData[summaryTableRowIndex] = stats.pValue;
196
+ ratioColData[summaryTableRowIndex] = stats.ratio;
197
+
198
+ //Setting aggregated col values
199
+ if (!isOriginalCluster) {
200
+ for (const [colName, aggregationFunc] of aggregateColumnsEntries) {
201
+ const arrayBuffer = filteredDf.getCol(colName).getRawData();
202
+ const clusterMask = DG.BitSet.fromBytes(arrayBuffer.buffer, arrayBuffer.byteLength / 4);
203
+ const subDf = filteredDf.clone(clusterMask, [colName]);
204
+ const newColName = getAggregatedColName(aggregationFunc, colName);
205
+ const aggregatedDf = subDf.groupBy()
206
+ .add(aggregationFunc as any, colName, newColName)
207
+ .aggregate();
208
+ const value = aggregatedDf.get(newColName, 0);
209
+ summaryTable.set(newColName, summaryTableRowIndex, value);
210
+ }
211
+ }
96
212
  }
97
213
  webLogoCol.setTag(DG.TAGS.CELL_RENDERER, 'html');
214
+ distributionCol.setTag(DG.TAGS.CELL_RENDERER, 'html');
98
215
 
99
216
  this.viewerGrid = summaryTable.plot.grid();
100
- const gridClustersCol = this.viewerGrid.col(C.COLUMNS_NAMES.CLUSTERS)!;
217
+ this.updateFilter();
218
+ const gridClustersCol = this.viewerGrid.col(clustersColName)!;
101
219
  gridClustersCol.name = 'Clusters';
102
220
  gridClustersCol.visible = true;
103
221
  this.viewerGrid.columns.rowHeader!.visible = false;
104
222
  this.viewerGrid.props.rowHeight = 55;
105
223
  this.viewerGrid.onCellPrepare((cell) => {
106
- if (cell.isTableCell && cell.tableColumn?.name === 'WebLogo') {
107
- tempDfList[parseInt(cell.cell.value)].plot.fromType('WebLogo', {maxHeight: 50, positionHeight: this.webLogoMode})
224
+ const currentRowIdx = cell.tableRowIndex;
225
+ if (!cell.isTableCell || currentRowIdx == null || currentRowIdx == -1)
226
+ return;
227
+
228
+ if (cell.tableColumn?.name == 'WebLogo') {
229
+ this.webLogoDfPlot[currentRowIdx]
230
+ .fromType('WebLogo', {maxHeight: cell.grid.props.rowHeight - 5, positionHeight: this.webLogoMode,
231
+ horizontalAlignment: 'left'})
108
232
  .then((viewer) => cell.element = viewer.root);
233
+ } else if (cell.tableColumn?.name == 'Distribution') {
234
+ const viewerRoot = this.distributionDfPlot[currentRowIdx].histogram({
235
+ filteringEnabled: false,
236
+ valueColumnName: C.COLUMNS_NAMES.ACTIVITY_SCALED,
237
+ splitColumnName: C.COLUMNS_NAMES.SPLIT_COL,
238
+ legendVisibility: 'Never',
239
+ showXAxis: true,
240
+ showColumnSelector: false,
241
+ showRangeSlider: false,
242
+ showBinSelector: false,
243
+ backColor: '#fffff',
244
+ }).root;
245
+
246
+ viewerRoot.style.width = 'auto';
247
+ const height = (cell.grid.props.rowHeight - 5) / 2 * 3;
248
+ viewerRoot.style.height = `${height}px`;
249
+ cell.element = viewerRoot;
109
250
  }
110
251
  });
111
252
  this.viewerGrid.root.addEventListener('click', (ev) => {
112
253
  const cell = this.viewerGrid.hitTest(ev.offsetX, ev.offsetY);
113
- if (!cell || !cell.isTableCell)
254
+ if (!cell || !cell.isTableCell || cell.tableColumn?.name != clustersColName)
114
255
  return;
115
256
 
116
- const cluster = clustersCol.get(cell.tableRowIndex!)!;
117
257
  summaryTable.currentRowIdx = -1;
118
258
  if (ev.shiftKey)
119
- this.model.modifyClusterSelection(cluster);
259
+ this.model.modifyClusterSelection(cell.cell.value);
120
260
  else
121
- this.model.initClusterSelection(cluster);
261
+ this.model.initClusterSelection(cell.cell.value);
262
+ this.viewerGrid.invalidate();
122
263
  });
123
264
  this.viewerGrid.onCellRender.subscribe((gridCellArgs) => {
124
265
  const gc = gridCellArgs.cell;
125
- if (gc.tableColumn?.name !== C.COLUMNS_NAMES.CLUSTERS || gc.isColHeader)
266
+ if (gc.tableColumn?.name !== clustersColName || gc.isColHeader)
126
267
  return;
127
268
  const canvasContext = gridCellArgs.g;
128
269
  const bound = gridCellArgs.bounds;
@@ -135,8 +276,8 @@ export class LogoSummary extends DG.JsViewer {
135
276
  canvasContext.restore();
136
277
  });
137
278
  this.viewerGrid.onCellTooltip((cell, x, y) => {
138
- if (!cell.isColHeader && cell.tableColumn?.name === C.COLUMNS_NAMES.CLUSTERS)
139
- this.model.showTooltipCluster(cell.cell.value, x, y);
279
+ if (!cell.isColHeader && cell.tableColumn?.name === clustersColName)
280
+ this.model.showTooltipCluster(cell.cell.rowIndex, x, y, cell.cell.value);
140
281
  return true;
141
282
  });
142
283
  const webLogoGridCol = this.viewerGrid.columns.byName('WebLogo')!;
@@ -151,4 +292,97 @@ export class LogoSummary extends DG.JsViewer {
151
292
 
152
293
  return this.viewerGrid;
153
294
  }
295
+
296
+ updateFilter(): void {
297
+ const table = this.viewerGrid.table;
298
+ const memberstCol = table.getCol(C.LST_COLUMN_NAMES.MEMBERS);
299
+ const membersColData = memberstCol.getRawData();
300
+ const maxCount = memberstCol.stats.max;
301
+ const minMembers = Math.ceil(maxCount * this.membersRatioThreshold);
302
+ table.filter.init((i) => membersColData[i] > minMembers);
303
+ }
304
+
305
+ clusterFromSelection(): void {
306
+ const filteredDf = this.dataFrame.filter.anyFalse ? this.dataFrame.clone(this.dataFrame.filter, null, true) :
307
+ this.dataFrame;
308
+ const selection = filteredDf.selection;
309
+ const viewerDf = this.viewerGrid.dataFrame;
310
+ const viewerDfCols = viewerDf.columns;
311
+ const viewerDfColsLength = viewerDfCols.length;
312
+ const newClusterVals = new Array(viewerDfCols.length);
313
+
314
+ const activityScaledCol = filteredDf.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
315
+ const maskInfo: MaskInfo = {
316
+ mask: selection.getBuffer(),
317
+ trueCount: selection.trueCount,
318
+ falseCount: selection.falseCount,
319
+ };
320
+ const stats = getStats(activityScaledCol.getRawData(), maskInfo);
321
+ const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, filteredDf.getCol(this.model.splitCol.name)]);
322
+
323
+ const peptideCol: DG.Column<string> = filteredDf.getCol(this.model.settings.sequenceColumnName!);
324
+ const peptideColData = peptideCol.getRawData();
325
+ const peptideColCategories = peptideCol.categories;
326
+ const peptideColTags = peptideCol.tags;
327
+ const selectedIndexes = selection.getSelectedIndexes();
328
+ const tCol = DG.Column.string('peptides', selectedIndexes.length);
329
+
330
+ for (let i = 0; i < selectedIndexes.length; ++i)
331
+ tCol.set(i, peptideColCategories[peptideColData[selectedIndexes[i]]]);
332
+ for (const tag of peptideColTags)
333
+ tCol.setTag(tag[0], tag[1]);
334
+
335
+ const uh = new UnitsHandler(tCol);
336
+ tCol.setTag(bioTAGS.alphabetSize, uh.getAlphabetSize().toString());
337
+
338
+ const webLogoTable = DG.DataFrame.fromColumns([tCol]);
339
+ this.webLogoDfPlot.push(webLogoTable.plot);
340
+ this.distributionDfPlot.push(distributionTable.plot);
341
+
342
+ const colCategories = viewerDfCols.byName(this.model.settings.clustersColumnName!).categories;
343
+ let newClusterName = this.newClusterName;
344
+ let clusterNum = 1;
345
+ const getString = !isNaN(parseInt(newClusterName)) ? () => `${parseInt(newClusterName) + 1}` :
346
+ newClusterName == '' ? () => `${clusterNum++}` :
347
+ () => `${this.newClusterName} ${clusterNum++}`;
348
+ while (colCategories.includes(newClusterName))
349
+ newClusterName = getString();
350
+
351
+ this.getProperty('newClusterName')?.set(this, getString());
352
+
353
+ for (let i = 0; i < viewerDfColsLength; ++i) {
354
+ const col = viewerDfCols.byIndex(i);
355
+ newClusterVals[i] = col.name == this.model.settings.clustersColumnName! ? newClusterName :
356
+ col.name == C.LST_COLUMN_NAMES.MEMBERS ? maskInfo.trueCount :
357
+ col.name == C.LST_COLUMN_NAMES.WEB_LOGO ? null :
358
+ col.name == C.LST_COLUMN_NAMES.DISTRIBUTION ? null :
359
+ col.name == C.LST_COLUMN_NAMES.MEAN_DIFFERENCE ? stats.meanDifference:
360
+ col.name == C.LST_COLUMN_NAMES.P_VALUE ? stats.pValue:
361
+ col.name == C.LST_COLUMN_NAMES.RATIO ? stats.ratio:
362
+ console.warn(`PeptidesLSTWarn: value for column ${col.name} is undefined`)! || null;
363
+ }
364
+ viewerDf.rows.addNew(newClusterVals);
365
+
366
+ this.model.clusterStats[newClusterName] = stats;
367
+ this.model.addNewCluster(newClusterName);
368
+ }
369
+
370
+ removeCluster(): void {
371
+ const lss = this.model.logoSummarySelection;
372
+ const dfCols = this.dataFrame.columns;
373
+
374
+ const removeClusterIndexesList = lss.filter((cluster) => dfCols.contains(cluster));
375
+ if (removeClusterIndexesList.length == 0)
376
+ return grok.shell.info('Nothing removed. Please select a created cluster to remove');
377
+
378
+ for (const cluster of removeClusterIndexesList) {
379
+ lss.splice(lss.indexOf(cluster), 1);
380
+ dfCols.remove(cluster);
381
+ }
382
+
383
+ this.model.logoSummarySelection = lss;
384
+ this.model.clusterStats = this.model.calculateClusterStatistics();
385
+ this.createLogoSummaryGrid();
386
+ this.render();
387
+ }
154
388
  }
@@ -40,7 +40,7 @@ export class PeptideSpaceViewer extends DG.JsViewer {
40
40
  async onTableAttached(): Promise<void> {
41
41
  super.onTableAttached();
42
42
 
43
- this.model = await PeptidesModel.getInstance(this.dataFrame);
43
+ this.model = PeptidesModel.getInstance(this.dataFrame);
44
44
 
45
45
  await this.render(!this.dataFrame.temp[C.EMBEDDING_STATUS]);
46
46
  }
@@ -62,7 +62,7 @@ export class PeptideSpaceViewer extends DG.JsViewer {
62
62
  $(this.root).empty();
63
63
  const viewerHost = ui.waitBox(async () => {
64
64
  // const aligendSeqCol = this.dataFrame.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
65
- const alignedSeqCol = this.dataFrame.getCol(C.COLUMNS_NAMES.MACROMOLECULE);
65
+ const alignedSeqCol = this.dataFrame.getCol(this.model.settings.sequenceColumnName!);
66
66
  const edf = await computeWeights(this.dataFrame, this.method, this.measure, this.cyclesCount, alignedSeqCol);
67
67
  this.dataFrame.temp[C.EMBEDDING_STATUS] = true;
68
68
  this.model.edf = edf;
@@ -77,7 +77,7 @@ export class PeptideSpaceViewer extends DG.JsViewer {
77
77
  this.model.fireBitsetChanged(true);
78
78
  });
79
79
 
80
- const colorCol = this.dataFrame.columns.bySemType(C.SEM_TYPES.ACTIVITY_SCALED)!;
80
+ const colorCol = this.dataFrame.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
81
81
  edf.columns.add(colorCol);
82
82
 
83
83
  const viewerOptions = {
@@ -112,14 +112,14 @@ export class PeptideSpaceViewer extends DG.JsViewer {
112
112
 
113
113
  //Do not accept table, only column
114
114
  export async function computeWeights(
115
- table: DG.DataFrame, method: string, measure: string, cyclesCount: number, col?: DG.Column,
115
+ table: DG.DataFrame, method: string, measure: string, cyclesCount: number, col: DG.Column,
116
116
  ): Promise<DG.DataFrame | null> {
117
117
  const pi = DG.TaskBarProgressIndicator.create('Creating embedding...');
118
118
  let edf: DG.DataFrame | null = null;
119
119
  try {
120
120
  const axesNames = ['~X', '~Y', '~MW'];
121
121
  // col ??= table.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
122
- col ??= table.getCol(C.COLUMNS_NAMES.MACROMOLECULE);
122
+ // col ??= table.getCol(this.model.settings.sequenceColumnName!);
123
123
  const columnData = col.toList().map((v) => AlignedSequenceEncoder.clean(v));
124
124
 
125
125
  const reduceDimRes: IReduceDimensionalityResult = await createDimensinalityReducingWorker(