@datagrok/peptides 1.2.0 → 1.3.0

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/src/package.ts CHANGED
@@ -8,10 +8,10 @@ import * as C from './utils/constants';
8
8
  import {analyzePeptidesWidget} from './widgets/analyze-peptides';
9
9
  import {PeptideSimilaritySpaceWidget} from './utils/peptide-similarity-space';
10
10
  import {manualAlignmentWidget} from './widgets/manual-alignment';
11
- import {SARViewer, SARViewerVertical} from './viewers/sar-viewer';
11
+ import {MutationCliffsViewer, MostPotentResiduesViewer} from './viewers/sar-viewer';
12
12
 
13
13
  import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
14
- import {InvariantMap} from './utils/invariant-map';
14
+ import {LogoSummary} from './viewers/logo-summary';
15
15
 
16
16
  export const _package = new DG.Package();
17
17
  let currentTable: DG.DataFrame;
@@ -84,16 +84,23 @@ export async function peptidesPanel(col: DG.Column): Promise<DG.Widget> {
84
84
  //description: Peptides SAR Viewer
85
85
  //tags: viewer
86
86
  //output: viewer result
87
- export function sar(): SARViewer {
88
- return new SARViewer();
87
+ export function sar(): MutationCliffsViewer {
88
+ return new MutationCliffsViewer();
89
89
  }
90
90
 
91
91
  //name: peptide-sar-viewer-vertical
92
92
  //description: Peptides Vertical SAR Viewer
93
93
  //tags: viewer
94
94
  //output: viewer result
95
- export function sarVertical(): SARViewerVertical {
96
- return new SARViewerVertical();
95
+ export function sarVertical(): MostPotentResiduesViewer {
96
+ return new MostPotentResiduesViewer();
97
+ }
98
+
99
+ //name: logo-summary-viewer
100
+ //tags: viewer
101
+ //output: viewer result
102
+ export function logoSummary(): LogoSummary {
103
+ return new LogoSummary();
97
104
  }
98
105
 
99
106
  //name: peptide-space-viewer
@@ -154,10 +161,3 @@ function getOrDefine(dataframe?: DG.DataFrame, column?: DG.Column | null): [DG.D
154
161
 
155
162
  return [dataframe, column];
156
163
  }
157
-
158
- //name: Invariant Map Filter
159
- //tags: filter
160
- //output: filter result
161
- export function invariantMapFilter() {
162
- return new InvariantMap();
163
- }
package/src/styles.css CHANGED
@@ -51,4 +51,5 @@
51
51
  font-family: 'Roboto', 'Roboto Local', sans-serif;
52
52
  color: #4D5261;
53
53
  text-align: center;
54
+ width: 100%;
54
55
  }
package/src/tests/core.ts CHANGED
@@ -37,11 +37,11 @@ category('Core', () => {
37
37
  [simpleScaledDf, simpleScaledColName] = scaleActivity('-lg', simpleTable, simpleActivityColName, true);
38
38
 
39
39
  model = await startAnalysis(
40
- simpleActivityCol, simpleAlignedSeqCol, simpleTable, simpleScaledDf, simpleScaledColName);
40
+ simpleActivityCol, simpleAlignedSeqCol, null, simpleTable, simpleScaledDf, simpleScaledColName);
41
41
  expect(model instanceof PeptidesModel, true);
42
42
 
43
43
  if (model != null) {
44
- model.currentSelection = {'11': ['D']};
44
+ model.mutationCliffsSelection = {'11': ['D']};
45
45
  grok.shell.closeTable(model.df);
46
46
  }
47
47
  });
@@ -59,11 +59,11 @@ category('Core', () => {
59
59
  [complexScaledDf, complexScaledColName] = scaleActivity('-lg', complexTable, complexActivityColName, true);
60
60
 
61
61
  model = await startAnalysis(
62
- complexActivityCol, complexAlignedSeqCol, complexTable, complexScaledDf, complexScaledColName);
62
+ complexActivityCol, complexAlignedSeqCol, null, complexTable, complexScaledDf, complexScaledColName);
63
63
  expect(model instanceof PeptidesModel, true);
64
64
 
65
65
  if (model != null) {
66
- model.currentSelection = {'13': ['-']};
66
+ model.mutationCliffsSelection = {'13': ['-']};
67
67
  grok.shell.closeTable(model.df);
68
68
  }
69
69
  });
@@ -80,7 +80,7 @@ category('Core', () => {
80
80
  [simpleScaledDf, simpleScaledColName] = scaleActivity('-lg', simpleTable, simpleActivityColName, true);
81
81
 
82
82
  model = await startAnalysis(
83
- simpleActivityCol, simpleAlignedSeqCol, simpleTable, simpleScaledDf, simpleScaledColName);
83
+ simpleActivityCol, simpleAlignedSeqCol, null, simpleTable, simpleScaledDf, simpleScaledColName);
84
84
  let v = grok.shell.getTableView('Peptides analysis');
85
85
  const d = v.dataFrame;
86
86
  const layout = v.saveLayout();
@@ -58,40 +58,40 @@ category('Peptide space', async () => {
58
58
  });
59
59
  });
60
60
 
61
- category('Peptide Space Performance', () => {
62
- test('test_compute_weights_performance', async () => {
63
- const table = DG.DataFrame.fromCsv(await _package.files.readAsText('peptides_large.csv'));
64
- const results: {[key: string]: {[key: string]: {[key: string]: number}}} = {};
65
- const sliceVolumes = [1, 2, 3, 4, 5, 7, 10];
66
- const methods = DimensionalityReducer.availableMethods;
67
- const metrics = DimensionalityReducer.availableMetricsByType('String');
68
- const totalRuns = sliceVolumes.length * methods.length * metrics.length;
69
- console.log('Started Peptide Space Performance benchmark...');
61
+ // category('Peptide Space Performance', () => {
62
+ // test('test_compute_weights_performance', async () => {
63
+ // const table = DG.DataFrame.fromCsv(await _package.files.readAsText('peptides_large.csv'));
64
+ // const results: {[key: string]: {[key: string]: {[key: string]: number}}} = {};
65
+ // const sliceVolumes = [1, 2, 3, 4, 5, 7, 10];
66
+ // const methods = DimensionalityReducer.availableMethods;
67
+ // const metrics = DimensionalityReducer.availableMetricsByType('String');
68
+ // const totalRuns = sliceVolumes.length * methods.length * metrics.length;
69
+ // console.log('Started Peptide Space Performance benchmark...');
70
70
 
71
- let run = 0;
72
- for (const slice of sliceVolumes) {
73
- const bitset = DG.BitSet.create(table.rowCount, (i) => i < slice * 1000);
74
- const tableSlice = table.clone(bitset);
75
- const col = tableSlice.getCol('sequence');
76
- const methodObj: {[key: string]: {[key: string]: number}} = {};
71
+ // let run = 0;
72
+ // for (const slice of sliceVolumes) {
73
+ // const bitset = DG.BitSet.create(table.rowCount, (i) => i < slice * 1000);
74
+ // const tableSlice = table.clone(bitset);
75
+ // const col = tableSlice.getCol('sequence');
76
+ // const methodObj: {[key: string]: {[key: string]: number}} = {};
77
77
 
78
- for (const method of methods) {
79
- const measureObj: {[key: string]: number} = {};
78
+ // for (const method of methods) {
79
+ // const measureObj: {[key: string]: number} = {};
80
80
 
81
- for (const metric of metrics) {
82
- console.log(`Run ${run++}/${totalRuns}`);
81
+ // for (const metric of metrics) {
82
+ // console.log(`Run ${run++}/${totalRuns}`);
83
83
 
84
- const start = new Date();
85
- await computeWeights(tableSlice, method, metric, 100, col);
86
- const stop = new Date();
84
+ // const start = new Date();
85
+ // await computeWeights(tableSlice, method, metric, 100, col);
86
+ // const stop = new Date();
87
87
 
88
- measureObj[metric] = stop.getTime() - start.getTime();
89
- }
90
- methodObj[method] = measureObj;
91
- }
92
- results[`${slice}k`] = methodObj;
93
- }
94
- console.log('Peptide Space Performance benchmark finished...');
95
- console.log(results);
96
- });
97
- });
88
+ // measureObj[metric] = stop.getTime() - start.getTime();
89
+ // }
90
+ // methodObj[method] = measureObj;
91
+ // }
92
+ // results[`${slice}k`] = methodObj;
93
+ // }
94
+ // console.log('Peptide Space Performance benchmark finished...');
95
+ // console.log(results);
96
+ // });
97
+ // });
@@ -5,65 +5,24 @@ import * as C from './constants';
5
5
  import {getPalleteByType} from './misc';
6
6
  import * as types from './types';
7
7
 
8
- /**
9
- * A function to expand column size based on its contents.
10
- *
11
- * @export
12
- * @param {DG.Column} col Column to expand.
13
- * @param {DG.Grid} grid Grid containing colum for expansion.
14
- * @param {(cellVal: string) => number} cellRenderSize An anonymous function that calculates cell value length.
15
- * @param {number} [textSizeMult=10] Text size muliplier.
16
- * @param {number} [minSize=30] Minimal column width.
17
- * @param {number} [maxSize=650] Maximum column width.
18
- * @param {number} [timeout=500] Timeout value.
19
- */
20
- export function expandColumn(col: DG.Column, grid: DG.Grid, cellRenderSize: (cellVal: string) => number,
21
- textSizeMult = 10, minSize = 30, maxSize = 650, timeout = 500): void {
22
- let maxLen = 0;
23
- col.categories.forEach((ent: string) => {
24
- const len = cellRenderSize(ent);
25
- if (len > maxLen)
26
- maxLen = len;
27
- });
28
- setTimeout(() => {
29
- grid.columns.byName(col.name)!.width = Math.min(Math.max(maxLen * textSizeMult, minSize), maxSize);
30
- },
31
- timeout);
8
+ function renderCellSelection(canvasContext: CanvasRenderingContext2D, bound: DG.Rect): void {
9
+ canvasContext.strokeStyle = '#000';
10
+ canvasContext.lineWidth = 1;
11
+ canvasContext.strokeRect(bound.x + 1, bound.y + 1, bound.width - 1, bound.height - 1);
32
12
  }
33
13
 
34
- /**
35
- * A function that sets amino acid residue to the specified column.
36
- *
37
- * @export
38
- * @param {DG.Column} col Column to set renderer for.
39
- * @param {(DG.Grid | null)} [grid=null] Grid that contains the col column.
40
- * @param {boolean} [grouping=false] Is grouping enabled.
41
- */
42
- export function setAARRenderer(col: DG.Column, alphabet: string, grid?: DG.Grid): void {
14
+ /** A function that sets amino acid residue cell renderer to the specified column */
15
+ export function setAARRenderer(col: DG.Column, alphabet: string, grid: DG.Grid, timeout: number = 500): void {
43
16
  col.semType = C.SEM_TYPES.MONOMER;
44
17
  col.setTag('cell.renderer', C.SEM_TYPES.MONOMER);
45
18
  col.tags[C.TAGS.ALPHABET] = alphabet;
46
-
47
- if (grid)
48
- expandColumn(col, grid, (ent) => measureAAR(ent));
49
- }
50
-
51
- /**
52
- * A function to measure amino acid residue
53
- *
54
- * @export
55
- * @param {string} s Amino acid residue string.
56
- * @return {number} Amino acid residue size.
57
- */
58
- export function measureAAR(s: string): number {
59
- const end = s.lastIndexOf(')');
60
- const beg = s.indexOf('(');
61
- return end == beg ? s.length : s.length - (end - beg) + 1;
19
+ setTimeout(() => grid.columns.byName(col.name)!.width = 60, timeout);
62
20
  }
63
21
 
64
- export function renderSARCell(canvasContext: CanvasRenderingContext2D, currentAAR: string, currentPosition: string,
65
- statsDf: DG.DataFrame, twoColorMode: boolean, mdCol: DG.Column<number>, bound: DG.Rect, cellValue: number,
66
- currentSelection: types.SelectionObject, substitutionsInfo: types.SubstitutionsInfo): void {
22
+ export function renderMutationCliffCell(canvasContext: CanvasRenderingContext2D, currentAAR: string,
23
+ currentPosition: string, statsDf: DG.DataFrame, twoColorMode: boolean, mdCol: DG.Column<number>, bound: DG.Rect,
24
+ cellValue: number, mutationCliffsSelection: types.PositionToAARList, substitutionsInfo: types.SubstitutionsInfo,
25
+ ): void {
67
26
  const queryAAR = `${C.COLUMNS_NAMES.MONOMER} = ${currentAAR}`;
68
27
  const query = `${queryAAR} and ${C.COLUMNS_NAMES.POSITION} = ${currentPosition}`;
69
28
  const pVal: number = statsDf
@@ -112,13 +71,22 @@ export function renderSARCell(canvasContext: CanvasRenderingContext2D, currentAA
112
71
  canvasContext.fillText(substValue.toString(), midX, midY);
113
72
  }
114
73
 
115
- //TODO: frame based on currentSelection
116
- const aarSelection = currentSelection[currentPosition];
117
- if (aarSelection && aarSelection.includes(currentAAR)) {
118
- canvasContext.strokeStyle = '#000';
119
- canvasContext.lineWidth = 1;
120
- canvasContext.strokeRect(bound.x + 1, bound.y + 1, bound.width - 1, bound.height - 1);
121
- }
74
+ const aarSelection = mutationCliffsSelection[currentPosition];
75
+ if (aarSelection && aarSelection.includes(currentAAR))
76
+ renderCellSelection(canvasContext, bound);
77
+ }
78
+
79
+ export function renderInvaraintMapCell(canvasContext: CanvasRenderingContext2D, currentAAR: string,
80
+ currentPosition: string, invariantMapSelection: types.PositionToAARList, cellValue: number, bound: DG.Rect): void {
81
+ canvasContext.font = '13px Roboto, Roboto Local, sans-serif';
82
+ canvasContext.textAlign = 'center';
83
+ canvasContext.textBaseline = 'middle';
84
+ canvasContext.fillStyle = '#000';
85
+ canvasContext.fillText(cellValue.toString(), bound.x + (bound.width / 2), bound.y + (bound.height / 2), bound.width);
86
+
87
+ const aarSelection = invariantMapSelection[currentPosition];
88
+ if (aarSelection && aarSelection.includes(currentAAR))
89
+ renderCellSelection(canvasContext, bound);
122
90
  }
123
91
 
124
92
  export function renderBarchart(ctx: CanvasRenderingContext2D, col: DG.Column, monomerColStats: types.MonomerColStats,
@@ -9,6 +9,7 @@ export enum COLUMNS_NAMES {
9
9
  MEAN_DIFFERENCE = 'Mean difference',
10
10
  COUNT = 'Count',
11
11
  RATIO = 'Ratio',
12
+ CLUSTERS = '~clusters',
12
13
  }
13
14
 
14
15
  export enum CATEGORIES {
@@ -22,6 +23,8 @@ export enum TAGS {
22
23
  SEPARATOR = 'separator',
23
24
  SELECTION = 'selection',
24
25
  ALPHABET = 'alphabet',
26
+ FILTER = 'filter',
27
+ CLUSTERS = 'clusters',
25
28
  }
26
29
 
27
30
  export enum SEM_TYPES {
@@ -5,7 +5,7 @@ export type DataFrameDict = {[key: string]: DG.DataFrame};
5
5
  export type UTypedArray = Uint8Array | Uint16Array | Uint32Array;
6
6
  //AAR: (Position: (index: indexList))
7
7
  export type SubstitutionsInfo = Map<string, Map<string, Map<number, number[] | UTypedArray>>>;
8
- export type SelectionObject = {[postiton: string]: string[]};
8
+ export type PositionToAARList = {[postiton: string]: string[]};
9
9
 
10
10
  export type HELMMonomer = {at: {[key: string]: string}, id: string, m: string, na: string, n: string, rs: number};
11
11
 
@@ -0,0 +1,42 @@
1
+ import * as grok from 'datagrok-api/grok';
2
+ import * as ui from 'datagrok-api/ui';
3
+ import * as DG from 'datagrok-api/dg';
4
+
5
+ import $ from 'cash-dom';
6
+ import * as C from '../utils/constants';
7
+ import {PeptidesModel} from '../model';
8
+
9
+ export class LogoSummary extends DG.JsViewer {
10
+ model!: PeptidesModel;
11
+ viewerGrid!: DG.Grid;
12
+ initialized: boolean = false;
13
+
14
+ constructor() {
15
+ super();
16
+ }
17
+
18
+ async onTableAttached(): Promise<void> {
19
+ super.onTableAttached();
20
+
21
+ this.model = await PeptidesModel.getInstance(this.dataFrame);
22
+
23
+ this.subs.push(this.model.onLogoSummaryGridChanged.subscribe((grid) => {
24
+ this.viewerGrid = grid;
25
+ this.render();
26
+ }));
27
+ this.model.updateDefault();
28
+ this.viewerGrid = this.model.logoSummaryGrid;
29
+ this.initialized = true;
30
+ this.render();
31
+ }
32
+
33
+ detach(): void {this.subs.forEach(sub => sub.unsubscribe());}
34
+
35
+ render(): void {
36
+ if (this.initialized) {
37
+ $(this.root).empty();
38
+ this.root.appendChild(this.viewerGrid.root);
39
+ this.viewerGrid.invalidate();
40
+ }
41
+ }
42
+ }
@@ -20,6 +20,7 @@ export class SARViewerBase extends DG.JsViewer {
20
20
  _titleHost = ui.divText('SAR Viewer', {id: 'pep-viewer-title'});
21
21
  initialized = false;
22
22
  isPropertyChanging: boolean = false;
23
+ _isVertical = false;
23
24
 
24
25
  constructor() {
25
26
  super();
@@ -30,6 +31,8 @@ export class SARViewerBase extends DG.JsViewer {
30
31
  this.minActivityDelta = this.float('minActivityDelta', 0);
31
32
  }
32
33
 
34
+ get name(): string {return '';}
35
+
33
36
  async onTableAttached(): Promise<void> {
34
37
  super.onTableAttached();
35
38
  this.sourceGrid = this.view?.grid ?? (grok.shell.v as DG.TableView).grid;
@@ -54,9 +57,19 @@ export class SARViewerBase extends DG.JsViewer {
54
57
  return;
55
58
  if (!refreshOnly) {
56
59
  $(this.root).empty();
60
+ const switchHost = ui.div();
61
+ if (this.name == 'MC') {
62
+ const modeSwitch = ui.switchInput('Invariant Map', this.model.isInvariantMap, () => {
63
+ this.model.isInvariantMap = modeSwitch.value;
64
+ this._titleHost.innerText = modeSwitch.value ? 'Invariant Map' : 'Mutation Cliffs';
65
+ this.viewerGrid.invalidate();
66
+ });
67
+ modeSwitch.root.style.position = 'absolute';
68
+ switchHost.appendChild(modeSwitch.root);
69
+ }
57
70
  const viewerRoot = this.viewerGrid.root;
58
71
  viewerRoot.style.width = 'auto';
59
- this.root.appendChild(ui.divV([this._titleHost, viewerRoot]));
72
+ this.root.appendChild(ui.divV([ui.divH([switchHost, this._titleHost]), viewerRoot]));
60
73
  }
61
74
  this.viewerGrid?.invalidate();
62
75
  }
@@ -88,9 +101,10 @@ export class SARViewerBase extends DG.JsViewer {
88
101
  /**
89
102
  * Structure-activity relationship viewer.
90
103
  */
91
- export class SARViewer extends SARViewerBase {
104
+ export class MutationCliffsViewer extends SARViewerBase {
92
105
  _titleHost = ui.divText('Mutation Cliffs', {id: 'pep-viewer-title'});
93
- _name = 'Structure-Activity Relationship';
106
+ _name = 'MC';
107
+ _isVertical = false;
94
108
 
95
109
  constructor() {super();}
96
110
 
@@ -98,26 +112,29 @@ export class SARViewer extends SARViewerBase {
98
112
 
99
113
  async onTableAttached(): Promise<void> {
100
114
  await super.onTableAttached();
101
- this.model.sarViewer ??= this;
115
+ this.model.mutationCliffsViewer ??= this;
102
116
 
103
- this.subs.push(this.model.onSARGridChanged.subscribe((data) => {
117
+ this.subs.push(this.model.onMutationCliffsGridChanged.subscribe((data) => {
104
118
  this.viewerGrid = data;
105
119
  this.render();
106
120
  }));
107
121
 
108
122
  this.model.updateDefault();
109
- this.viewerGrid = this.model._sarGrid;
123
+ this.viewerGrid = this.model.mutationCliffsGrid;
110
124
  this.initialized = true;
111
125
  this.render();
112
126
  }
113
127
 
114
- isInitialized(): DG.Grid {return this.model?._sarGrid;}
128
+ isInitialized(): DG.Grid {return this.model?.mutationCliffsGrid;}
115
129
 
116
130
  //1. debouncing in rxjs; 2. flags?
117
131
  onPropertyChanged(property: DG.Property): void {
118
132
  if (!this.isInitialized() || IS_PROPERTY_CHANGING)
119
133
  return;
120
134
 
135
+ if (property.name == 'invariantMap')
136
+ this._titleHost = ui.divText(property.get(this) ? 'Invariant Map' : 'Mutation Cliffs', {id: 'pep-viewer-title'});
137
+
121
138
  super.onPropertyChanged(property);
122
139
  IS_PROPERTY_CHANGING = true;
123
140
  this.model.syncProperties(true);
@@ -126,9 +143,10 @@ export class SARViewer extends SARViewerBase {
126
143
  }
127
144
 
128
145
  /** Vertical structure activity relationship viewer. */
129
- export class SARViewerVertical extends SARViewerBase {
130
- _name = 'Sequence-Activity relationship';
146
+ export class MostPotentResiduesViewer extends SARViewerBase {
147
+ _name = 'MPR';
131
148
  _titleHost = ui.divText('Most Potent Residues', {id: 'pep-viewer-title'});
149
+ _isVertical = true;
132
150
 
133
151
  constructor() {
134
152
  super();
@@ -138,21 +156,21 @@ export class SARViewerVertical extends SARViewerBase {
138
156
 
139
157
  async onTableAttached(): Promise<void> {
140
158
  await super.onTableAttached();
141
- this.model.sarViewerVertical ??= this;
159
+ this.model.mostPotentResiduesViewer ??= this;
142
160
 
143
- this.subs.push(this.model.onSARVGridChanged.subscribe((data) => {
161
+ this.subs.push(this.model.onMostPotentResiduesGridChanged.subscribe((data) => {
144
162
  this.viewerGrid = data;
145
163
  this.render();
146
164
  }));
147
165
 
148
166
  this.model.updateDefault();
149
- this.viewerGrid = this.model._sarVGrid;
167
+ this.viewerGrid = this.model.mostPotentResiduesGrid;
150
168
 
151
169
  this.initialized = true;
152
170
  this.render();
153
171
  }
154
172
 
155
- isInitialized(): DG.Grid {return this.model?._sarVGrid;}
173
+ isInitialized(): DG.Grid {return this.model?.mostPotentResiduesGrid;}
156
174
 
157
175
  onPropertyChanged(property: DG.Property): void {
158
176
  if (!this.isInitialized() || IS_PROPERTY_CHANGING)
@@ -64,13 +64,15 @@ export async function analyzePeptidesWidget(currentDf: DG.DataFrame, col: DG.Col
64
64
  activityScalingMethod.fireChanged();
65
65
  };
66
66
  const activityColumnChoice = ui.columnInput('Activity', currentDf, defaultColumn, activityScalingMethodState);
67
+ const clustersColumnChoice = ui.columnInput('Clusters', currentDf, null);
67
68
  activityColumnChoice.fireChanged();
68
69
  activityScalingMethod.fireChanged();
69
70
 
70
- const inputsList = [activityColumnChoice, activityScalingMethod];
71
+ const inputsList = [activityColumnChoice, activityScalingMethod, clustersColumnChoice];
71
72
 
72
73
  const startBtn = ui.button('Launch SAR', async () => {
73
- await startAnalysis(activityColumnChoice.value, col, currentDf, scaledDf, newScaledColName);
74
+ await startAnalysis(
75
+ activityColumnChoice.value, col, clustersColumnChoice.value, currentDf, scaledDf, newScaledColName);
74
76
  });
75
77
  startBtn.style.alignSelf = 'center';
76
78
 
@@ -85,21 +87,24 @@ export async function analyzePeptidesWidget(currentDf: DG.DataFrame, col: DG.Col
85
87
  ui.splitH([
86
88
  ui.splitV([ui.inputs(inputsList), startBtn]),
87
89
  histogramHost,
88
- ], {style: {height: 'unset'}}),
90
+ ], {style: {height: '215px'}}),
89
91
  ]),
90
92
  );
91
93
  }
92
94
 
93
95
  export async function startAnalysis(
94
- activityColumn: DG.Column<number> | null, alignedSeqCol: DG.Column<string>, currentDf: DG.DataFrame,
95
- scaledDf: DG.DataFrame, newScaledColName: string): Promise<PeptidesModel | null> {
96
+ activityColumn: DG.Column<number> | null, alignedSeqCol: DG.Column<string>, clustersColumn: DG.Column | null,
97
+ currentDf: DG.DataFrame, scaledDf: DG.DataFrame, newScaledColName: string): Promise<PeptidesModel | null> {
96
98
  const progress = DG.TaskBarProgressIndicator.create('Loading SAR...');
97
99
  let model = null;
98
100
  if (activityColumn?.type === DG.TYPE.FLOAT) {
99
101
  const activityColumnName: string = activityColumn.name;
102
+ const cloneColList = [alignedSeqCol.name, activityColumnName];
103
+ if (clustersColumn)
104
+ cloneColList.push(clustersColumn.name);
100
105
 
101
106
  //prepare new DF
102
- const newDf = currentDf.clone(currentDf.filter, [alignedSeqCol.name, activityColumnName]);
107
+ const newDf = currentDf.clone(currentDf.filter, cloneColList);
103
108
  const activityCol = newDf.getCol(activityColumnName);
104
109
  activityCol.name = C.COLUMNS_NAMES.ACTIVITY;
105
110
  activityCol.semType = C.SEM_TYPES.ACTIVITY;
@@ -109,6 +114,10 @@ export async function startAnalysis(
109
114
  newDf.columns.add(activityScaledCol);
110
115
  newDf.name = 'Peptides analysis';
111
116
  newDf.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED] = newScaledColName;
117
+ if (clustersColumn) {
118
+ newDf.getCol(clustersColumn.name).name = C.COLUMNS_NAMES.CLUSTERS;
119
+ newDf.tags[C.TAGS.CLUSTERS] = C.COLUMNS_NAMES.CLUSTERS;
120
+ }
112
121
  // newDf.tags[C.PEPTIDES_ANALYSIS] = 'true';
113
122
 
114
123
  let monomerType = 'HELM_AA';
@@ -14,7 +14,7 @@ const otherConst = 'Other';
14
14
  export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel): DG.Widget {
15
15
  const activityScaledCol = table.columns.bySemType(C.SEM_TYPES.ACTIVITY_SCALED)!;
16
16
  const rowCount = activityScaledCol.length;
17
- const selectionObject = model.currentSelection;
17
+ const selectionObject = model.mutationCliffsSelection;
18
18
  const positions = Object.keys(selectionObject);
19
19
  const positionsLen = positions.length;
20
20
  let aarStr = allConst;
@@ -7,7 +7,7 @@ import {getSeparator} from '../utils/misc';
7
7
 
8
8
  export function mutationCliffsWidget(table: DG.DataFrame, model: PeptidesModel): DG.Widget {
9
9
  const substInfo = model.substitutionsInfo;
10
- const currentCell = model.currentSelection;
10
+ const currentCell = model.mutationCliffsSelection;
11
11
  const positions = Object.keys(currentCell);
12
12
 
13
13
  if (!positions.length)