@datagrok/peptides 1.5.1 → 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.
@@ -4,6 +4,7 @@ import {runTests, tests, TestContext} from '@datagrok-libraries/utils/src/test';
4
4
  import './tests/core';
5
5
  import './tests/peptide-space-test';
6
6
  import './tests/algorithms';
7
+ import './tests/viewers';
7
8
 
8
9
  export const _package = new DG.Package();
9
10
  export {tests};
package/src/package.ts CHANGED
@@ -10,19 +10,23 @@ import {MonomerPosition, MostPotentResiduesViewer} from './viewers/sar-viewer';
10
10
 
11
11
  import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
12
12
  import {LogoSummary} from './viewers/logo-summary';
13
- import {MonomerWorks} from '@datagrok-libraries/bio';
13
+ import {MonomerWorks} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
14
+ import {PeptidesModel} from './model';
14
15
 
15
- export let monomerWorks: MonomerWorks | null;
16
+ let monomerWorks: MonomerWorks | null = null;
16
17
 
17
18
  export const _package = new DG.Package();
18
- let currentTable: DG.DataFrame;
19
- let alignedSequenceColumn: DG.Column;
20
19
 
21
20
  export function getMonomerWorks(): MonomerWorks | null {
22
21
  return monomerWorks;
23
- };
22
+ }
23
+
24
+ //tags: init
25
+ export async function initPeptides(): Promise<void> {
26
+ monomerWorks ??= new MonomerWorks(await grok.functions.call('Bio:getBioLib'));
27
+ }
24
28
 
25
- async function main(chosenFile: string): Promise<void> {
29
+ async function openDemoData(chosenFile: string): Promise<void> {
26
30
  const pi = DG.TaskBarProgressIndicator.create('Loading Peptides');
27
31
  const path = _package.webRoot + 'files/' + chosenFile;
28
32
  const peptides = await grok.data.loadTable(path);
@@ -36,13 +40,10 @@ async function main(chosenFile: string): Promise<void> {
36
40
 
37
41
  //name: Peptides
38
42
  //tags: app
39
- export async function Peptides(): Promise<void> {
43
+ export function Peptides(): void {
40
44
  const wikiLink = ui.link('wiki', 'https://github.com/datagrok-ai/public/blob/master/help/domains/bio/peptides.md');
41
45
  const textLink = ui.inlineText(['For more details, see our ', wikiLink, '.']);
42
- if (monomerWorks == null) {
43
- const lib = await grok.functions.call('Bio:getBioLib');
44
- monomerWorks = new MonomerWorks(lib);
45
- }
46
+
46
47
  const appDescription = ui.info(
47
48
  [
48
49
  ui.list([
@@ -72,9 +73,9 @@ export async function Peptides(): Promise<void> {
72
73
  appDescription,
73
74
  ui.info([textLink]),
74
75
  ui.divH([
75
- ui.button('Simple demo', () => main('aligned.csv'), ''),
76
- ui.button('Complex demo', () => main('aligned_2.csv'), ''),
77
- ui.button('HELM demo', () => main('aligned_3.csv'), ''),
76
+ ui.button('Simple demo', () => openDemoData('aligned.csv'), ''),
77
+ ui.button('Complex demo', () => openDemoData('aligned_2.csv'), ''),
78
+ ui.button('HELM demo', () => openDemoData('aligned_3.csv'), ''),
78
79
  ]),
79
80
  ]);
80
81
  }
@@ -96,8 +97,7 @@ export function peptidesDialog(): DG.Dialog {
96
97
  //input: column col {semType: Macromolecule}
97
98
  //output: widget result
98
99
  export function peptidesPanel(col: DG.Column): DG.Widget {
99
- [currentTable, alignedSequenceColumn] = getOrDefine(col.dataFrame, col);
100
- const analyzeObject = analyzePeptidesUI(currentTable, alignedSequenceColumn);
100
+ const analyzeObject = analyzePeptidesUI(col.dataFrame, col);
101
101
  return new DG.Widget(analyzeObject.host);
102
102
  }
103
103
 
@@ -137,9 +137,14 @@ export function peptideSpace(): PeptideSpaceViewer {
137
137
  //input: string _monomer {semType: Monomer}
138
138
  //output: widget result
139
139
  export function manualAlignment(_monomer: string): DG.Widget {
140
- [currentTable, alignedSequenceColumn] = getOrDefine();
141
140
  //TODO: recalculate Molfile and Molecule panels on sequence update
142
- return manualAlignmentWidget(alignedSequenceColumn, currentTable);
141
+ const df = grok.shell.t;
142
+ const model: PeptidesModel | null = df?.temp[PeptidesModel.modelName];
143
+ if (!model)
144
+ return new DG.Widget(ui.divText('Manual alignment works with peptides analysis'));
145
+
146
+ const col = df.getCol(model.settings.sequenceColumnName!);
147
+ return manualAlignmentWidget(col, df);
143
148
  }
144
149
 
145
150
  //name: Peptide Space
@@ -147,38 +152,6 @@ export function manualAlignment(_monomer: string): DG.Widget {
147
152
  //input: column col {semType: Macromolecule}
148
153
  //output: widget result
149
154
  export async function peptideSpacePanel(col: DG.Column): Promise<DG.Widget> {
150
- [currentTable, alignedSequenceColumn] = getOrDefine(col.dataFrame, col);
151
155
  const widget = new PeptideSimilaritySpaceWidget(col, grok.shell.v as DG.TableView);
152
156
  return widget.draw();
153
157
  }
154
-
155
- //name: Get Peptides Structure
156
- //tags: panel, widgets
157
- //input: column col {semType: Macromolecule}
158
- //output: widget result
159
- export function getPeptidesStructure(col: DG.Column): DG.Widget {
160
- const getButtonTooltip = 'Retrieves peptides structure from customer database by special id column';
161
- const getButton = ui.button('Get structure', async () => {
162
- const progress = DG.TaskBarProgressIndicator.create('Getting structure...');
163
- try {
164
- const params = {peptidesTable: col.dataFrame};
165
- const result = await grok.functions.call('Customerextensions:getPeptidesStructure', params);
166
- const text = result ? 'Structure retreived' : 'Structure retreivial is not possible';
167
- grok.shell.info(text);
168
- } catch (e) {
169
- console.warn(e);
170
- } finally {
171
- progress.close();
172
- }
173
- }, getButtonTooltip);
174
- return new DG.Widget(getButton);
175
- }
176
-
177
- function getOrDefine(dataframe?: DG.DataFrame, column?: DG.Column | null): [DG.DataFrame, DG.Column] {
178
- dataframe ??= grok.shell.t;
179
- column ??= dataframe.columns.bySemType(DG.SEMTYPE.MACROMOLECULE)!;
180
- if (column === null)
181
- throw new Error('Table does not contain aligned sequence columns');
182
-
183
- return [dataframe, column];
184
- }
package/src/styles.css CHANGED
@@ -52,4 +52,11 @@
52
52
  color: #4D5261;
53
53
  text-align: center;
54
54
  width: 100%;
55
+ align-self: end;
56
+ }
57
+
58
+ .pep-help-icon {
59
+ position: absolute;
60
+ left: 5px;
61
+ top: 1px;
55
62
  }
package/src/tests/core.ts CHANGED
@@ -8,7 +8,7 @@ import {startAnalysis} from '../widgets/peptides';
8
8
  import {PeptidesModel} from '../model';
9
9
  import * as C from '../utils/constants';
10
10
  import {scaleActivity} from '../utils/misc';
11
- import {ALPHABET, TAGS, NOTATION, ALIGNMENT} from '@datagrok-libraries/bio';
11
+ import {ALIGNMENT, ALPHABET, NOTATION, TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
12
12
 
13
13
  category('Core', () => {
14
14
  let simpleTable: DG.DataFrame;
@@ -32,16 +32,14 @@ category('Core', () => {
32
32
  simpleAlignedSeqCol.semType = DG.SEMTYPE.MACROMOLECULE;
33
33
  simpleAlignedSeqCol.setTag(C.TAGS.ALPHABET, ALPHABET.PT);
34
34
  simpleAlignedSeqCol.setTag(DG.TAGS.UNITS, NOTATION.FASTA);
35
- simpleAlignedSeqCol.setTag(TAGS.aligned, ALIGNMENT.SEQ_MSA);
35
+ simpleAlignedSeqCol.setTag(bioTAGS.aligned, ALIGNMENT.SEQ_MSA);
36
36
  simpleScaledCol = scaleActivity(simpleActivityCol, '-lg');
37
37
 
38
38
  model = await startAnalysis(simpleActivityCol, simpleAlignedSeqCol, null, simpleTable, simpleScaledCol, '-lg');
39
39
  expect(model instanceof PeptidesModel, true);
40
40
 
41
- if (model != null) {
41
+ if (model != null)
42
42
  model.mutationCliffsSelection = {'11': ['D']};
43
- grok.shell.closeTable(model.df);
44
- }
45
43
  });
46
44
 
47
45
  test('Start analysis: сomplex', async () => {
@@ -52,18 +50,16 @@ category('Core', () => {
52
50
  complexAlignedSeqCol.semType = DG.SEMTYPE.MACROMOLECULE;
53
51
  complexAlignedSeqCol.setTag(C.TAGS.ALPHABET, ALPHABET.UN);
54
52
  complexAlignedSeqCol.setTag(DG.TAGS.UNITS, NOTATION.SEPARATOR);
55
- complexAlignedSeqCol.setTag(TAGS.aligned, ALIGNMENT.SEQ_MSA);
56
- complexAlignedSeqCol.tags[C.TAGS.SEPARATOR] = '/';
53
+ complexAlignedSeqCol.setTag(bioTAGS.aligned, ALIGNMENT.SEQ_MSA);
54
+ complexAlignedSeqCol.setTag(C.TAGS.SEPARATOR, '/');
57
55
  complexScaledCol = scaleActivity(complexActivityCol, '-lg');
58
56
 
59
57
  model = await startAnalysis(
60
58
  complexActivityCol, complexAlignedSeqCol, null, complexTable, complexScaledCol, '-lg');
61
59
  expect(model instanceof PeptidesModel, true);
62
60
 
63
- if (model != null) {
61
+ if (model != null)
64
62
  model.mutationCliffsSelection = {'13': ['-']};
65
- grok.shell.closeTable(model.df);
66
- }
67
63
  });
68
64
 
69
65
  test('Save and load project', async () => {
@@ -74,7 +70,7 @@ category('Core', () => {
74
70
  simpleAlignedSeqCol.semType = DG.SEMTYPE.MACROMOLECULE;
75
71
  simpleAlignedSeqCol.setTag(C.TAGS.ALPHABET, ALPHABET.PT);
76
72
  simpleAlignedSeqCol.setTag(DG.TAGS.UNITS, NOTATION.FASTA);
77
- simpleAlignedSeqCol.setTag(TAGS.aligned, ALIGNMENT.SEQ_MSA);
73
+ simpleAlignedSeqCol.setTag(bioTAGS.aligned, ALIGNMENT.SEQ_MSA);
78
74
  simpleScaledCol = scaleActivity(simpleActivityCol, '-lg');
79
75
 
80
76
  model = await startAnalysis(simpleActivityCol, simpleAlignedSeqCol, null, simpleTable, simpleScaledCol, '-lg');
@@ -95,12 +91,57 @@ category('Core', () => {
95
91
  grok.shell.closeTable(d);
96
92
  await delay(500);
97
93
 
98
- await grok.dapi.projects.open('Peptides project unique test');
94
+ await sp.open();
99
95
  v = grok.shell.getTableView('Peptides analysis');
100
- grok.shell.closeTable(v.dataFrame);
101
96
 
102
97
  await grok.dapi.layouts.delete(sl);
103
98
  await grok.dapi.tables.delete(sti);
104
99
  await grok.dapi.projects.delete(sp);
105
100
  });
101
+
102
+ test('Cluster stats - Benchmark HELM 5k', async () => {
103
+ const df = (await _package.files.readBinaryDataFrames('tests/aligned_5k_2.d42'))[0];
104
+ const activityCol = df.getCol('Activity');
105
+ const scaledActivityCol = scaleActivity(activityCol, 'none');
106
+ const clustersCol = df.getCol('Cluster');
107
+ const sequenceCol = df.getCol('HELM');
108
+ sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
109
+ sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
110
+ const model = await startAnalysis(activityCol, sequenceCol, clustersCol, df, scaledActivityCol, 'none');
111
+
112
+ for (let i = 0; i < 5; ++i)
113
+ DG.time('Cluster stats', () => model?.calculateClusterStatistics());
114
+ }, {skipReason: 'Benchmark'});
115
+
116
+ test('Monomer Position stats - Benchmark HELM 5k', async () => {
117
+ const df = (await _package.files.readBinaryDataFrames('tests/aligned_5k.d42'))[0];
118
+ const activityCol = df.getCol('Activity');
119
+ const scaledActivityCol = scaleActivity(activityCol, 'none');
120
+ const clustersCol = df.getCol('Cluster');
121
+ const sequenceCol = df.getCol('HELM');
122
+ sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
123
+ sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
124
+ const model = await startAnalysis(activityCol, sequenceCol, clustersCol, df, scaledActivityCol, 'none');
125
+
126
+ for (let i = 0; i < 5; ++i)
127
+ DG.time('Monomer position stats', () => model?.calculateMonomerPositionStatistics());
128
+ }, {skipReason: 'Benchmark'});
129
+
130
+ test('Analysis start - Benchmark HELM 5k', async () => {
131
+ const df = (await _package.files.readBinaryDataFrames('tests/aligned_5k.d42'))[0];
132
+ const activityCol = df.getCol('Activity');
133
+ const scaledActivityCol = scaleActivity(activityCol, 'none');
134
+ const clustersCol = df.getCol('Cluster');
135
+ const sequenceCol = df.getCol('HELM');
136
+ sequenceCol.semType = DG.SEMTYPE.MACROMOLECULE;
137
+ sequenceCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
138
+
139
+ for (let i = 0; i < 5; ++i) {
140
+ await DG.timeAsync('Analysis start', async () => {
141
+ const model = await startAnalysis(activityCol, sequenceCol, clustersCol, df, scaledActivityCol, 'none');
142
+ if (model)
143
+ grok.shell.closeTable(model.df);
144
+ });
145
+ }
146
+ }, {skipReason: 'Benchmark'});
106
147
  });
@@ -1,10 +1,5 @@
1
1
  import {/*before, after, */after, category, test} from '@datagrok-libraries/utils/src/test';
2
- import {
3
- _testViewerIsDrawing,
4
- _testDimensionalityReducer,
5
- _testPeptideSimilaritySpaceViewer,
6
- _testTableIsNotEmpty,
7
- } from './utils';
2
+ import * as utils from './utils';
8
3
  import {DimensionalityReducer} from '@datagrok-libraries/ml/src/reduce-dimensionality';
9
4
  import {cleanAlignedSequencesColumn} from '../utils/peptide-similarity-space';
10
5
  import {aligned1} from './test-data';
@@ -12,7 +7,6 @@ import {aligned1} from './test-data';
12
7
  import * as DG from 'datagrok-api/dg';
13
8
  import * as grok from 'datagrok-api/grok';
14
9
  import {StringMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
15
- import {computeWeights} from '../viewers/peptide-space-viewer';
16
10
  import {_package} from '../package-test';
17
11
 
18
12
  let table: DG.DataFrame;
@@ -22,12 +16,12 @@ category('Peptide space', async () => {
22
16
  table = DG.DataFrame.fromCsv(aligned1);
23
17
 
24
18
  test('test_table.is_not_empty', async () => {
25
- _testTableIsNotEmpty(table);
19
+ utils._testTableIsNotEmpty(table);
26
20
  });
27
21
 
28
22
  test('PeptideSimilaritySpaceWidget.is_drawing', async () => {
29
23
  view = grok.shell.addTableView(table);
30
- await _testViewerIsDrawing(table, view);
24
+ await utils._testViewerIsDrawing(table, view);
31
25
  });
32
26
 
33
27
  const alignedSequencesColumn = table.getCol('AlignedSequence');
@@ -37,7 +31,7 @@ category('Peptide space', async () => {
37
31
  for (const method of DimensionalityReducer.availableMethods) {
38
32
  for (const measure of DimensionalityReducer.availableMetricsByType('String')) {
39
33
  test(`peptide_space.DimensinalityReducer.${method}.${measure}.is_numeric`, async () => {
40
- await _testDimensionalityReducer(columnData, method as StringMetrics, measure);
34
+ await utils._testDimensionalityReducer(columnData, method as StringMetrics, measure);
41
35
  });
42
36
  }
43
37
  }
@@ -47,51 +41,9 @@ category('Peptide space', async () => {
47
41
  for (const method of DimensionalityReducer.availableMethods) {
48
42
  for (const measure of DimensionalityReducer.availableMetricsByType('String')) {
49
43
  test(`peptide_space.PeptideSimilaritySpaceViewer.${method}.${measure}.is_proper`, async () => {
50
- await _testPeptideSimilaritySpaceViewer(table, alignedSequencesColumn, method, measure, 100);//, view);
44
+ await utils._testPeptideSimilaritySpaceViewer(table, alignedSequencesColumn, method, measure, 100);//, view);
51
45
  });
52
46
  }
53
47
  }
54
48
  });
55
-
56
- after(async () => {
57
- view?.close();
58
- });
59
49
  });
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...');
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}} = {};
77
-
78
- // for (const method of methods) {
79
- // const measureObj: {[key: string]: number} = {};
80
-
81
- // for (const metric of metrics) {
82
- // console.log(`Run ${run++}/${totalRuns}`);
83
-
84
- // const start = new Date();
85
- // await computeWeights(tableSlice, method, metric, 100, col);
86
- // const stop = new Date();
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
- // });
@@ -0,0 +1,17 @@
1
+ import * as DG from 'datagrok-api/dg';
2
+ import * as grok from 'datagrok-api/grok';
3
+ //import * as ui from 'datagrok-api/ui';
4
+
5
+ import {category, test, testViewer} from '@datagrok-libraries/utils/src/test';
6
+ import {aligned1} from './test-data';
7
+
8
+
9
+ category('Viewers', () => {
10
+ const df = DG.DataFrame.fromCsv(aligned1);
11
+ const viewers = DG.Func.find({package: 'Peptides', tags: ['viewer']}).map((f) => f.friendlyName);
12
+ for (const v of viewers) {
13
+ test(v, async () => {
14
+ await testViewer(v, df.clone(), true);
15
+ }, {skipReason: 'GROK-11534'});
16
+ }
17
+ });
@@ -2,7 +2,9 @@ import * as DG from 'datagrok-api/dg';
2
2
 
3
3
  import * as C from './constants';
4
4
  import * as types from './types';
5
- import * as bio from '@datagrok-libraries/bio';
5
+ import {PositionStats, SummaryStats, MonomerPositionStats} from '../model';
6
+ import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
7
+ import {monomerToShort} from '@datagrok-libraries/bio/src/utils/macromolecule';
6
8
 
7
9
  function renderCellSelection(canvasContext: CanvasRenderingContext2D, bound: DG.Rect): void {
8
10
  canvasContext.strokeStyle = '#000';
@@ -18,34 +20,32 @@ export function setAARRenderer(col: DG.Column, alphabet: string): void {
18
20
  }
19
21
 
20
22
  export function renderMutationCliffCell(canvasContext: CanvasRenderingContext2D, currentAAR: string,
21
- currentPosition: string, statsDf: DG.DataFrame, mdCol: DG.Column<number>, bound: DG.Rect, cellValue: number,
23
+ currentPosition: string, monomerPositionStats: MonomerPositionStats, bound: DG.Rect,
22
24
  mutationCliffsSelection: types.PositionToAARList, substitutionsInfo: types.SubstitutionsInfo,
23
25
  twoColorMode: boolean = false): void {
24
- const queryAAR = `${C.COLUMNS_NAMES.MONOMER} = ${currentAAR}`;
25
- const query = `${queryAAR} and ${C.COLUMNS_NAMES.POSITION} = ${currentPosition}`;
26
- const pVal: number = statsDf
27
- .groupBy([C.COLUMNS_NAMES.P_VALUE])
28
- .where(query)
29
- .aggregate()
30
- .get(C.COLUMNS_NAMES.P_VALUE, 0);
26
+ const positionStats = monomerPositionStats[currentPosition];
27
+ const pVal: number = positionStats[currentAAR].pValue;
28
+ const currentMeanDiff = positionStats[currentAAR].meanDifference;
31
29
 
32
30
  let coef: string;
33
- const variant = cellValue < 0;
31
+ const isMeanDeltaNegative = currentMeanDiff < 0;
34
32
  if (pVal < 0.01)
35
- coef = variant && twoColorMode ? '#FF7900' : '#299617';
33
+ coef = isMeanDeltaNegative && twoColorMode ? '#FF7900' : '#299617';
36
34
  else if (pVal < 0.05)
37
- coef = variant && twoColorMode ? '#FFA500' : '#32CD32';
35
+ coef = isMeanDeltaNegative && twoColorMode ? '#FFA500' : '#32CD32';
38
36
  else if (pVal < 0.1)
39
- coef = variant && twoColorMode ? '#FBCEB1' : '#98FF98';
37
+ coef = isMeanDeltaNegative && twoColorMode ? '#FBCEB1' : '#98FF98';
40
38
  else
41
39
  coef = DG.Color.toHtml(DG.Color.lightLightGray);
42
40
 
43
41
 
44
- const chooseMin = (): number => twoColorMode ? 0 : mdCol.min;
45
- const chooseMax = (): number => twoColorMode ? Math.max(Math.abs(mdCol.min), mdCol.max) : mdCol.max;
46
- const chooseCurrent = (): any => twoColorMode ? Math.abs(cellValue) : cellValue;
42
+ const minMeanDifference = twoColorMode ? 0 : monomerPositionStats.general.minMeanDifference;
43
+ const maxMeanDifference = twoColorMode ?
44
+ Math.max(Math.abs(monomerPositionStats.general.minMeanDifference), monomerPositionStats.general.maxMeanDifference) :
45
+ monomerPositionStats.general.maxMeanDifference;
46
+ const currentMeanDifference = twoColorMode ? Math.abs(currentMeanDiff) : currentMeanDiff;
47
47
 
48
- const rCoef = (chooseCurrent() - chooseMin()) / (chooseMax() - chooseMin());
48
+ const rCoef = (currentMeanDifference - minMeanDifference) / (maxMeanDifference - minMeanDifference);
49
49
 
50
50
  const maxRadius = 0.9 * (bound.width > bound.height ? bound.height : bound.width) / 2;
51
51
  const radius = Math.floor(maxRadius * rCoef);
@@ -92,22 +92,22 @@ export function renderInvaraintMapCell(canvasContext: CanvasRenderingContext2D,
92
92
  renderCellSelection(canvasContext, bound);
93
93
  }
94
94
 
95
- export function renderLogoSummaryCell(canvasContext: CanvasRenderingContext2D, cellValue: string, cellRawData: number,
96
- clusterSelection: number[], bound: DG.Rect): void {
95
+ export function renderLogoSummaryCell(canvasContext: CanvasRenderingContext2D, cellValue: string,
96
+ clusterSelection: string[], bound: DG.Rect): void {
97
97
  canvasContext.font = '13px Roboto, Roboto Local, sans-serif';
98
98
  canvasContext.textAlign = 'center';
99
99
  canvasContext.textBaseline = 'middle';
100
100
  canvasContext.fillStyle = '#000';
101
101
  canvasContext.fillText(cellValue.toString(), bound.x + (bound.width / 2), bound.y + (bound.height / 2), bound.width);
102
102
 
103
- if (clusterSelection.includes(cellRawData))
103
+ if (clusterSelection.includes(cellValue))
104
104
  renderCellSelection(canvasContext, bound);
105
105
  }
106
106
 
107
107
 
108
- export function drawLogoInBounds(ctx: CanvasRenderingContext2D, bounds: DG.Rect, statsInfo: types.StatsInfo,
109
- rowCount: number, cp: bio.SeqPalette, monomerSelectionStats: {[monomer: string]: number} = {},
110
- drawOptions: types.DrawOptions = {}): {[monomer: string]: DG.Rect} {
108
+ export function drawLogoInBounds(ctx: CanvasRenderingContext2D, bounds: DG.Rect, stats: PositionStats,
109
+ sortedOrder: string[], rowCount: number, cp: SeqPalette, monomerSelectionStats: { [monomer: string]: number } = {},
110
+ drawOptions: types.DrawOptions = {}): { [monomer: string]: DG.Rect } {
111
111
  drawOptions.fontStyle ??= '16px Roboto, Roboto Local, sans-serif';
112
112
  drawOptions.upperLetterHeight ??= 12.2;
113
113
  drawOptions.upperLetterAscent ??= 0.25;
@@ -115,7 +115,7 @@ export function drawLogoInBounds(ctx: CanvasRenderingContext2D, bounds: DG.Rect,
115
115
  drawOptions.marginHorizontal ??= 5;
116
116
 
117
117
  const pr = window.devicePixelRatio;
118
- const totalSpaceBetweenLetters = (statsInfo.orderedIndexes.length - 1) * drawOptions.upperLetterAscent;
118
+ const totalSpaceBetweenLetters = (sortedOrder.length - 1) * drawOptions.upperLetterAscent;
119
119
  const barHeight = (bounds.height - 2 * drawOptions.marginVertical - totalSpaceBetweenLetters) * pr;
120
120
  const leftShift = drawOptions.marginHorizontal * 2;
121
121
  const barWidth = (bounds.width - leftShift * 2) * pr;
@@ -124,17 +124,16 @@ export function drawLogoInBounds(ctx: CanvasRenderingContext2D, bounds: DG.Rect,
124
124
  const xSelection = (bounds.x + 3) * pr;
125
125
  let currentY = (bounds.y + drawOptions.marginVertical) * pr;
126
126
 
127
- const monomerBounds: {[monomer: string]: DG.Rect} = {};
128
- for (const index of statsInfo.orderedIndexes) {
129
- const monomer = statsInfo.monomerCol.get(index)!;
130
- const monomerHeight = barHeight * (statsInfo.countCol.get(index)! / rowCount);
127
+ const monomerBounds: { [monomer: string]: DG.Rect } = {};
128
+ for (const monomer of sortedOrder) {
129
+ const monomerHeight = barHeight * (stats[monomer].count / rowCount);
131
130
  const selectionHeight = barHeight * ((monomerSelectionStats[monomer] ?? 0) / rowCount);
132
131
  const currentBound = new DG.Rect(xStart / pr, currentY / pr, barWidth / pr, monomerHeight / pr);
133
132
  monomerBounds[monomer] = currentBound;
134
133
 
135
134
  ctx.resetTransform();
136
135
  if (monomer !== '-' && monomer !== '') {
137
- const monomerTxt = bio.monomerToShort(monomer, 5);
136
+ const monomerTxt = monomerToShort(monomer, 5);
138
137
  const mTm: TextMetrics = ctx.measureText(monomerTxt);
139
138
 
140
139
  // Filling selection
@@ -7,7 +7,15 @@ export enum COLUMNS_NAMES {
7
7
  MEAN_DIFFERENCE = 'Mean difference',
8
8
  COUNT = 'Count',
9
9
  RATIO = 'Ratio',
10
+ }
11
+
12
+ export enum LST_COLUMN_NAMES {
10
13
  MEMBERS = 'Members',
14
+ WEB_LOGO = 'WebLogo',
15
+ DISTRIBUTION = 'Distribution',
16
+ MEAN_DIFFERENCE = 'Mean difference',
17
+ P_VALUE = 'P-Value',
18
+ RATIO = 'Ratio',
11
19
  }
12
20
 
13
21
  export enum CATEGORIES {
@@ -26,6 +34,8 @@ export enum TAGS {
26
34
  CLUSTER_SELECTION = 'clusterSelection',
27
35
  VISIBLE = 'visible',
28
36
  SETTINGS = 'settings',
37
+ CUSTOM_CLUSTER = 'customCluster',
38
+ UUID = 'pep-uuid',
29
39
  }
30
40
 
31
41
  export enum SEM_TYPES {
@@ -35,4 +45,4 @@ export enum SEM_TYPES {
35
45
 
36
46
  export const EMBEDDING_STATUS = 'embeddingStatus';
37
47
 
38
- export const PEPTIDES_ANALYSIS = 'isPeptidesAnalysis';
48
+ export const MULTIPLE_VIEWS = 'isMultipleViews';
package/src/utils/misc.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
2
+ import * as ui from 'datagrok-api/ui';
1
3
  import * as DG from 'datagrok-api/dg';
2
4
  import * as C from './constants';
3
5
  import * as type from './types';
@@ -36,6 +38,7 @@ export function scaleActivity(activityCol: DG.Column<number>, scaling: string =
36
38
  return scaledCol;
37
39
  }
38
40
 
41
+ //TODO: optimize
39
42
  export function calculateSelected(df: DG.DataFrame): type.MonomerSelectionStats {
40
43
  const monomerColumns: DG.Column<string>[] = df.columns.bySemTypeAll(C.SEM_TYPES.MONOMER);
41
44
  const selectedObj: type.MonomerSelectionStats = {};
@@ -54,10 +57,10 @@ export function calculateSelected(df: DG.DataFrame): type.MonomerSelectionStats
54
57
  return selectedObj;
55
58
  }
56
59
 
57
- export function isGridCellInvalid(gc: DG.GridCell | null): boolean {
58
- return !gc || !gc.cell.value || !gc.tableColumn || gc.tableRowIndex == null || gc.tableRowIndex == -1 ||
59
- gc.cell.value == DG.INT_NULL || gc.cell.value == DG.FLOAT_NULL;
60
- }
60
+ // export function isGridCellInvalid(gc: DG.GridCell | null): boolean {
61
+ // return !gc || !gc.cell.value || !gc.tableColumn || gc.tableRowIndex == null || gc.tableRowIndex == -1 ||
62
+ // gc.cell.value == DG.INT_NULL || gc.cell.value == DG.FLOAT_NULL;
63
+ // }
61
64
 
62
65
  export function extractMonomerInfo(col: DG.Column<string>): type.RawColumn {
63
66
  return {
@@ -66,3 +69,12 @@ export function extractMonomerInfo(col: DG.Column<string>): type.RawColumn {
66
69
  rawData: col.getRawData(),
67
70
  };
68
71
  }
72
+
73
+ export function wrapDistroAndStatsDefault(labels: HTMLDivElement, histRoot: HTMLElement, tableMap: StringDictionary,
74
+ isTooltip: boolean = false): HTMLDivElement {
75
+ const result = ui.divV([labels, histRoot, ui.tableFromMap(tableMap)]);
76
+ result.style.minWidth = '200px';
77
+ if (isTooltip)
78
+ histRoot.style.maxHeight = '150px';
79
+ return result;
80
+ }
@@ -188,7 +188,7 @@ export class PeptideSimilaritySpaceWidget {
188
188
  }
189
189
 
190
190
  /**
191
- * Draws a viewer on property panel.
191
+ * Draws a viewer on context panel.
192
192
  *
193
193
  * @return {Promise<DG.Widget>} The corresponding widget.
194
194
  * @memberof PeptideSimilaritySpaceWidget
@@ -40,3 +40,5 @@ export type StatsInfo = {
40
40
  }
41
41
 
42
42
  export type RawColumn = {name: string, rawData: RawData, cat?: string[]};
43
+
44
+ export type CustomClusters = {[clusterName: string]: number[] | Int32Array};