@datagrok/peptides 1.9.3 → 1.12.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.
@@ -1,13 +1,14 @@
1
+ import * as grok from 'datagrok-api/grok';
1
2
  import * as DG from 'datagrok-api/dg';
2
3
 
3
- import {before, category, expect, test, testViewer} from '@datagrok-libraries/utils/src/test';
4
+ import {awaitCheck, before, category, expect, test, testViewer} from '@datagrok-libraries/utils/src/test';
4
5
  import {aligned1} from './test-data';
5
6
  import {PeptidesModel, VIEWER_TYPE} from '../model';
6
7
  import {_package} from '../package-test';
7
8
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
8
9
  import {scaleActivity} from '../utils/misc';
9
10
  import {startAnalysis} from '../widgets/peptides';
10
- import {MONOMER_POSITION_MODE, MonomerPosition, MostPotentResiduesViewer, showTooltip} from '../viewers/sar-viewer';
11
+ import {MONOMER_POSITION_MODE, MonomerPosition, MostPotentResidues, showTooltip} from '../viewers/sar-viewer';
11
12
  import {SCALING_METHODS} from '../utils/constants';
12
13
  import {LST_PROPERTIES, LogoSummaryTable} from '../viewers/logo-summary';
13
14
  import {PositionHeight} from '@datagrok-libraries/bio/src/viewers/web-logo';
@@ -45,7 +46,18 @@ category('Viewers: Monomer-Position', () => {
45
46
  if (tempModel === null)
46
47
  throw new Error('Model is null');
47
48
  model = tempModel;
49
+ let overlayInit = false;
50
+ model._analysisView!.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
51
+
48
52
  mpViewer = model.findViewer(VIEWER_TYPE.MONOMER_POSITION) as MonomerPosition;
53
+
54
+ // Ensure grid finished initializing to prevent Unhandled exceptions
55
+ let accrodionInit = false;
56
+ grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
57
+ await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
58
+ await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
59
+ await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
60
+ await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
49
61
  });
50
62
 
51
63
  test('Tooltip', async () => {
@@ -70,7 +82,7 @@ category('Viewers: Monomer-Position', () => {
70
82
  expect(mpViewer.mode, MONOMER_POSITION_MODE.MUTATION_CLIFFS,
71
83
  `Monomer-Position mode is not ${MONOMER_POSITION_MODE.MUTATION_CLIFFS} after switching`);
72
84
  });
73
- });
85
+ }, {clear: false});
74
86
 
75
87
  category('Viewers: Most Potent Residues', () => {
76
88
  let df: DG.DataFrame;
@@ -79,7 +91,7 @@ category('Viewers: Most Potent Residues', () => {
79
91
  let sequenceCol: DG.Column<string>;
80
92
  let clusterCol: DG.Column<any>;
81
93
  let scaledActivityCol: DG.Column<number>;
82
- let mprViewer: MostPotentResiduesViewer;
94
+ let mprViewer: MostPotentResidues;
83
95
 
84
96
  before(async () => {
85
97
  df = DG.DataFrame.fromCsv(await _package.files.readAsText('tests/HELM_small.csv'));
@@ -94,7 +106,18 @@ category('Viewers: Most Potent Residues', () => {
94
106
  if (tempModel === null)
95
107
  throw new Error('Model is null');
96
108
  model = tempModel;
97
- mprViewer = model.findViewer(VIEWER_TYPE.MOST_POTENT_RESIDUES) as MostPotentResiduesViewer;
109
+ let overlayInit = false;
110
+ model._analysisView!.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
111
+
112
+ mprViewer = model.findViewer(VIEWER_TYPE.MOST_POTENT_RESIDUES) as MostPotentResidues;
113
+
114
+ // Ensure grid finished initializing to prevent Unhandled exceptions
115
+ let accrodionInit = false;
116
+ grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
117
+ await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
118
+ await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
119
+ await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
120
+ await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
98
121
  });
99
122
 
100
123
  test('Tooltip', async () => {
@@ -127,7 +150,18 @@ category('Viewers: Logo Summary Table', () => {
127
150
  if (tempModel === null)
128
151
  throw new Error('Model is null');
129
152
  model = tempModel;
153
+ let overlayInit = false;
154
+ model._analysisView!.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
155
+
130
156
  lstViewer = model.findViewer(VIEWER_TYPE.LOGO_SUMMARY_TABLE) as LogoSummaryTable;
157
+
158
+ // Ensure grid finished initializing to prevent Unhandled exceptions
159
+ let accrodionInit = false;
160
+ grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
161
+ await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
162
+ await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
163
+ await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
164
+ await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
131
165
  });
132
166
 
133
167
  test('Properties', async () => {
@@ -152,4 +186,4 @@ category('Viewers: Logo Summary Table', () => {
152
186
  const tooltipElement = lstViewer.showTooltip(cluster, 0, 0);
153
187
  expect(tooltipElement !== null, true, `Tooltip is not shown for cluster '${cluster}'`);
154
188
  });
155
- });
189
+ }, {clear: false});
@@ -1,7 +1,7 @@
1
1
  import * as grok from 'datagrok-api/grok';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
 
4
- import {category, test, before, expect, delay} from '@datagrok-libraries/utils/src/test';
4
+ import {category, test, before, expect, awaitCheck} from '@datagrok-libraries/utils/src/test';
5
5
  import {_package} from '../package-test';
6
6
  import {PeptidesModel, VIEWER_TYPE} from '../model';
7
7
  import {scaleActivity} from '../utils/misc';
@@ -36,6 +36,16 @@ category('Widgets: Settings', () => {
36
36
  if (tempModel === null)
37
37
  throw new Error('Model is null');
38
38
  model = tempModel;
39
+ let overlayInit = false;
40
+ model._analysisView!.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
41
+
42
+ // Ensure grid finished initializing to prevent Unhandled exceptions
43
+ let accrodionInit = false;
44
+ grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
45
+ await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
46
+ await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
47
+ await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
48
+ await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
39
49
  });
40
50
 
41
51
  test('UI', async () => {
@@ -77,15 +87,21 @@ category('Widgets: Distribution panel', () => {
77
87
  if (tempModel === null)
78
88
  throw new Error('Model is null');
79
89
  model = tempModel;
90
+ let overlayInit = false;
91
+ model._analysisView!.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
92
+
93
+ // Ensure grid finished initializing to prevent Unhandled exceptions
94
+ let accrodionInit = false;
95
+ grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
96
+ await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
97
+ await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
98
+ await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
99
+ await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
80
100
  });
81
101
 
82
102
  test('UI', async () => {
83
103
  getDistributionWidget(model.df, model);
84
104
  });
85
-
86
- test('Split', async () => {
87
-
88
- }, {skipReason: 'Not implemented yet'});
89
105
  });
90
106
 
91
107
  category('Widgets: Mutation cliffs', () => {
@@ -109,19 +125,21 @@ category('Widgets: Mutation cliffs', () => {
109
125
  if (tempModel === null)
110
126
  throw new Error('Model is null');
111
127
  model = tempModel;
128
+ let overlayInit = false;
129
+ model._analysisView!.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
130
+
131
+ // Ensure grid finished initializing to prevent Unhandled exceptions
132
+ let accrodionInit = false;
133
+ grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
134
+ await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
135
+ await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
136
+ await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
137
+ await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
112
138
  });
113
139
 
114
140
  test('UI', async () => {
115
141
  mutationCliffsWidget(model.df, model);
116
142
  });
117
-
118
- test('General', async () => {
119
-
120
- }, {skipReason: 'Not implemented yet'});
121
-
122
- test('Filtering', async () => {
123
-
124
- }, {skipReason: 'Not implemented yet'});
125
143
  });
126
144
 
127
145
  category('Widgets: Actions', () => {
@@ -145,6 +163,16 @@ category('Widgets: Actions', () => {
145
163
  if (tempModel === null)
146
164
  throw new Error('Model is null');
147
165
  model = tempModel;
166
+ let overlayInit = false;
167
+ model._analysisView!.grid.onAfterDrawOverlay.subscribe(() => overlayInit = true);
168
+
169
+ // Ensure grid finished initializing to prevent Unhandled exceptions
170
+ let accrodionInit = false;
171
+ grok.events.onAccordionConstructed.subscribe((_) => accrodionInit = true);
172
+ await awaitCheck(() => model!.df.currentRowIdx === 0, 'Grid cell never finished initializing', 2000);
173
+ await awaitCheck(() => grok.shell.o instanceof DG.Column, 'Shell object never changed', 2000);
174
+ await awaitCheck(() => accrodionInit, 'Accordion never finished initializing', 2000);
175
+ await awaitCheck(() => overlayInit, 'Overlay never finished initializing', 2000);
148
176
  });
149
177
 
150
178
  test('New view', async () => {
@@ -164,7 +192,7 @@ category('Widgets: Actions', () => {
164
192
  expect(currentTable.getTag(C.TAGS.UUID), newViewId, 'Current table is expected to have the same UUID as new view');
165
193
  expect(currentTable.rowCount, 1, 'Current table is expected to have 1 row');
166
194
 
167
- await delay(500);
195
+ await awaitCheck(() => currentTable.currentRowIdx === 0, 'Grid never finished initializing', 2000);
168
196
 
169
197
  const currentTableModel = currentTable.temp[PeptidesModel.modelName] as PeptidesModel;
170
198
  const lstViewer = currentTableModel.findViewer(VIEWER_TYPE.LOGO_SUMMARY_TABLE);
@@ -181,13 +209,15 @@ category('Widgets: Actions', () => {
181
209
  const selection = model.df.selection;
182
210
  selection.set(0, true, false);
183
211
 
184
- const lstViewer = model.findViewer(VIEWER_TYPE.LOGO_SUMMARY_TABLE) as LogoSummaryTable;
212
+ const lstViewer = model.findViewer(VIEWER_TYPE.LOGO_SUMMARY_TABLE) as LogoSummaryTable | null;
213
+ if (lstViewer === null)
214
+ throw new Error('Logo summary table viewer is not found');
185
215
 
186
216
  // Check that custom clusters are not created yet
187
217
  expect(wu(model.customClusters).toArray().length, 0, 'Expected to have 0 custom clusters before creating one');
188
218
 
189
219
  // Create custom cluster
190
- model._newClusterSubject.next();
220
+ lstViewer.clusterFromSelection();
191
221
  const customClusterList = wu(model.customClusters).toArray();
192
222
  expect(customClusterList.length, 1, 'Expected to have 1 custom cluster');
193
223
  const clustName = customClusterList[0].name;
@@ -198,11 +228,11 @@ category('Widgets: Actions', () => {
198
228
 
199
229
  // Remove custom cluster
200
230
  model.modifyClusterSelection(clustName);
201
- model._removeClusterSubject.next();
231
+ lstViewer.removeCluster();
202
232
  expect(wu(model.customClusters).toArray().length, 0, 'Expected to have 0 custom clusters after removing one');
203
233
  expect(model.df.col(clustName) === null, true,
204
234
  'Expected to have no custom cluster column in the table');
205
235
  expect(lstViewer.viewerGrid.table.getCol(C.LST_COLUMN_NAMES.CLUSTER).categories.indexOf(clustName) === -1, true,
206
236
  'Expected to have no custom cluster in the Logo Summary Table');
207
237
  });
208
- });
238
+ }, {clear: false});
@@ -6,7 +6,7 @@ import {PositionStats, MonomerPositionStats} from '../model';
6
6
  import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
7
7
  import {monomerToShort} from '@datagrok-libraries/bio/src/utils/macromolecule';
8
8
 
9
- function renderCellSelection(canvasContext: CanvasRenderingContext2D, bound: DG.Rect): void {
9
+ export function renderCellSelection(canvasContext: CanvasRenderingContext2D, bound: DG.Rect): void {
10
10
  canvasContext.strokeStyle = '#000';
11
11
  canvasContext.lineWidth = 1;
12
12
  canvasContext.strokeRect(bound.x + 1, bound.y + 1, bound.width - 1, bound.height - 1);
@@ -22,7 +22,7 @@ export function setAARRenderer(col: DG.Column, alphabet: string): void {
22
22
  export function renderMutationCliffCell(canvasContext: CanvasRenderingContext2D, currentAAR: string,
23
23
  currentPosition: string, monomerPositionStats: MonomerPositionStats, bound: DG.Rect,
24
24
  mutationCliffsSelection: types.PositionToAARList, substitutionsInfo: types.MutationCliffs | null = null,
25
- twoColorMode: boolean = false): void {
25
+ twoColorMode: boolean = false, renderNums: boolean = true): void {
26
26
  const positionStats = monomerPositionStats[currentPosition];
27
27
  const pVal: number = positionStats[currentAAR].pValue;
28
28
  const currentMeanDiff = positionStats[currentAAR].meanDifference;
@@ -56,19 +56,27 @@ export function renderMutationCliffCell(canvasContext: CanvasRenderingContext2D,
56
56
  canvasContext.fillStyle = coef;
57
57
  canvasContext.arc(midX, midY, radius < 3 ? 3 : radius, 0, Math.PI * 2, true);
58
58
  canvasContext.closePath();
59
-
60
59
  canvasContext.fill();
61
- if (substitutionsInfo !== null && substitutionsInfo.size > 0) {
62
- canvasContext.textBaseline = 'middle';
63
- canvasContext.textAlign = 'center';
64
- canvasContext.fillStyle = DG.Color.toHtml(DG.Color.black);
65
- canvasContext.font = '13px Roboto, Roboto Local, sans-serif';
66
- canvasContext.shadowBlur = 5;
67
- canvasContext.shadowColor = DG.Color.toHtml(DG.Color.white);
68
- let substValue = 0;
69
- substitutionsInfo.get(currentAAR)?.get(currentPosition)?.forEach((idxs) => substValue += idxs.length);
70
- if (substValue && substValue !== 0)
71
- canvasContext.fillText(substValue.toString(), midX, midY);
60
+
61
+ if (renderNums) {
62
+ const substitutions = substitutionsInfo?.get(currentAAR)?.get(currentPosition)?.entries() ?? null;
63
+ if (substitutions !== null) {
64
+ canvasContext.textBaseline = 'middle';
65
+ canvasContext.textAlign = 'center';
66
+ canvasContext.fillStyle = DG.Color.toHtml(DG.Color.black);
67
+ canvasContext.font = '13px Roboto, Roboto Local, sans-serif';
68
+ canvasContext.shadowBlur = 5;
69
+ canvasContext.shadowColor = DG.Color.toHtml(DG.Color.white);
70
+ const uniqueValues = new Set<number>();
71
+
72
+ for (const [key, value] of substitutions) {
73
+ uniqueValues.add(key);
74
+ for (const val of value)
75
+ uniqueValues.add(val);
76
+ }
77
+ if (uniqueValues.size !== 0)
78
+ canvasContext.fillText(uniqueValues.size.toString(), midX, midY);
79
+ }
72
80
  }
73
81
 
74
82
  const aarSelection = mutationCliffsSelection[currentPosition];
@@ -105,18 +113,20 @@ export function renderLogoSummaryCell(canvasContext: CanvasRenderingContext2D, c
105
113
  }
106
114
 
107
115
 
108
- export function drawLogoInBounds(ctx: CanvasRenderingContext2D, bounds: DG.Rect, stats: PositionStats,
116
+ export function drawLogoInBounds(ctx: CanvasRenderingContext2D, bounds: DG.Rect, stats: PositionStats, position: string,
109
117
  sortedOrder: string[], rowCount: number, cp: SeqPalette, monomerSelectionStats: { [monomer: string]: number } = {},
110
118
  drawOptions: types.DrawOptions = {}): { [monomer: string]: DG.Rect } {
111
- drawOptions.fontStyle ??= '16px Roboto, Roboto Local, sans-serif';
119
+ const pr = window.devicePixelRatio;
120
+ drawOptions.symbolStyle ??= '16px Roboto, Roboto Local, sans-serif';
112
121
  drawOptions.upperLetterHeight ??= 12.2;
113
122
  drawOptions.upperLetterAscent ??= 0.25;
114
123
  drawOptions.marginVertical ??= 5;
115
124
  drawOptions.marginHorizontal ??= 5;
125
+ drawOptions.textHeight ??= 13;
126
+ drawOptions.headerStyle ??= `bold ${drawOptions.textHeight * pr}px Roboto, Roboto Local, sans-serif`;
116
127
 
117
- const pr = window.devicePixelRatio;
118
- const totalSpaceBetweenLetters = (sortedOrder.length - 1) * drawOptions.upperLetterAscent;
119
- const barHeight = (bounds.height - 2 * drawOptions.marginVertical - totalSpaceBetweenLetters) * pr;
128
+ const totalSpace = (sortedOrder.length - 1) * drawOptions.upperLetterAscent; // Total space between letters
129
+ const barHeight = (bounds.height - 2 * drawOptions.marginVertical - totalSpace - 1.25 * drawOptions.textHeight) * pr;
120
130
  const leftShift = drawOptions.marginHorizontal * 2;
121
131
  const barWidth = (bounds.width - leftShift * 2) * pr;
122
132
  const xStart = (bounds.x + leftShift) * pr;
@@ -143,7 +153,7 @@ export function drawLogoInBounds(ctx: CanvasRenderingContext2D, bounds: DG.Rect,
143
153
  ctx.fillStyle = cp.get(monomer) ?? cp.get('other');
144
154
  ctx.textAlign = 'left';
145
155
  ctx.textBaseline = 'top';
146
- ctx.font = drawOptions.fontStyle;
156
+ ctx.font = drawOptions.symbolStyle;
147
157
  // Hacks to scale uppercase characters to target rectangle
148
158
  const widthTransform = barWidth / mTm.width;
149
159
  const heightTransfrom = monomerHeight / drawOptions.upperLetterHeight;
@@ -153,5 +163,13 @@ export function drawLogoInBounds(ctx: CanvasRenderingContext2D, bounds: DG.Rect,
153
163
  currentY += monomerHeight + drawOptions.upperLetterAscent * pr;
154
164
  }
155
165
 
166
+ // Drawing column header
167
+ ctx.resetTransform();
168
+ ctx.fillStyle = DG.Color.toHtml(DG.Color.black);
169
+ ctx.textAlign = 'center';
170
+ ctx.textBaseline = 'top';
171
+ ctx.font = drawOptions.headerStyle;
172
+ ctx.fillText(position, (bounds.x + bounds.width / 2) * pr, (bounds.y + bounds.height - drawOptions.textHeight) * pr);
173
+
156
174
  return monomerBounds;
157
175
  }
@@ -31,6 +31,7 @@ export enum TAGS {
31
31
  SELECTION = 'selection',
32
32
  ALPHABET = 'alphabet',
33
33
  FILTER = 'filter',
34
+ INVARIANT_MAP_SELECTION = 'invariantMapSelection',
34
35
  SAR_MODE = 'sarMode',
35
36
  CLUSTER_SELECTION = 'clusterSelection',
36
37
  VISIBLE = 'visible',
@@ -39,6 +40,8 @@ export enum TAGS {
39
40
  UUID = 'pep-uuid',
40
41
  MONOMER_POSITION_MODE = 'monomerPositionMode',
41
42
  MULTIPLE_VIEWS = 'isMultipleViews',
43
+ IDENTITY_TEMPLATE = 'Identity template',
44
+ SIMILARITY_TEMPLATE = 'Similarity template',
42
45
  }
43
46
 
44
47
  export enum SEM_TYPES {
package/src/utils/misc.ts CHANGED
@@ -1,8 +1,11 @@
1
- import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
1
+ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
  import * as C from './constants';
5
5
  import * as type from './types';
6
+ import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
7
+ import {getSplitter} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
8
+ import {TAGS as bioTags} from '@datagrok-libraries/bio/src/utils/macromolecule';
6
9
 
7
10
  export function getTypedArrayConstructor(
8
11
  maxNum: number): Uint8ArrayConstructor | Uint16ArrayConstructor | Uint32ArrayConstructor {
@@ -59,11 +62,6 @@ export function calculateSelected(df: DG.DataFrame): type.MonomerSelectionStats
59
62
  return selectedObj;
60
63
  }
61
64
 
62
- // export function isGridCellInvalid(gc: DG.GridCell | null): boolean {
63
- // return !gc || !gc.cell.value || !gc.tableColumn || gc.tableRowIndex === null || gc.tableRowIndex === -1 ||
64
- // gc.cell.value === DG.INT_NULL || gc.cell.value === DG.FLOAT_NULL;
65
- // }
66
-
67
65
  export function extractColInfo(col: DG.Column<string>): type.RawColumn {
68
66
  return {
69
67
  name: col.name,
@@ -73,10 +71,33 @@ export function extractColInfo(col: DG.Column<string>): type.RawColumn {
73
71
  }
74
72
 
75
73
  export function getStatsSummary(legend: HTMLDivElement, hist: DG.Viewer<DG.IHistogramLookSettings>,
76
- statsMap: StringDictionary, isTooltip: boolean = false): HTMLDivElement {
74
+ statsMap: StringDictionary): HTMLDivElement {
77
75
  const result = ui.divV([legend, hist.root, ui.tableFromMap(statsMap)]);
78
- result.style.minWidth = '200px';
79
- if (isTooltip)
80
- hist.root.style.maxHeight = '150px';
76
+ hist.root.style.maxHeight = '75px';
81
77
  return result;
82
78
  }
79
+
80
+ export function prepareTableForHistogram(table: DG.DataFrame): DG.DataFrame {
81
+ const activityCol: DG.Column<number> = table.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
82
+ const splitCol: DG.Column<boolean> = table.getCol(C.COLUMNS_NAMES.SPLIT_COL);
83
+
84
+ const rowCount = activityCol.length;
85
+ const activityColData = activityCol.getRawData();
86
+ const expandedData: number[] = new Array(rowCount + splitCol.stats.sum);
87
+ const expandedMasks: boolean[] = new Array(expandedData.length);
88
+ for (let i = 0, j = 0; i < rowCount; ++i) {
89
+ const isSplit = splitCol.get(i)!;
90
+ expandedData[i] = activityColData[i];
91
+ expandedMasks[i] = isSplit;
92
+ if (isSplit) {
93
+ expandedData[rowCount + j] = activityColData[i];
94
+ expandedMasks[rowCount + j] = false;
95
+ ++j;
96
+ }
97
+ }
98
+
99
+ return DG.DataFrame.fromColumns([
100
+ DG.Column.fromList(DG.TYPE.FLOAT, activityCol.name, expandedData),
101
+ DG.Column.fromList(DG.TYPE.BOOL, C.COLUMNS_NAMES.SPLIT_COL, expandedMasks),
102
+ ]);
103
+ }
@@ -4,12 +4,11 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {getSequenceMolecularWeight} from './molecular-measure';
6
6
  import {AlignedSequenceEncoder} from '@datagrok-libraries/bio/src/sequence-encoder';
7
- import {DimensionalityReducer} from '@datagrok-libraries/ml/src/reduce-dimensionality';
7
+ import {DimensionalityReducer, IReduceDimensionalityResult} from '@datagrok-libraries/ml/src/reduce-dimensionality';
8
8
  import {
9
9
  createDimensinalityReducingWorker,
10
- IReduceDimensionalityResult,
11
10
  } from '@datagrok-libraries/ml/src/workers/dimensionality-reducing-worker-creator';
12
- import {Measure, StringMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
11
+ import {DistanceMetricsSubjects, Measure, StringMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
13
12
  import {Coordinates} from '@datagrok-libraries/utils/src/type-declarations';
14
13
 
15
14
  /**
@@ -115,7 +114,7 @@ export class PeptideSimilaritySpaceWidget {
115
114
  */
116
115
  constructor(alignedSequencesColumn: DG.Column, view: DG.TableView) {
117
116
  this.availableMethods = DimensionalityReducer.availableMethods;
118
- this.availableMetrics = Measure.getMetricByDataType('String');
117
+ this.availableMetrics = Measure.getMetricByDataType(DistanceMetricsSubjects.String);
119
118
  this.method = this.availableMethods[0];
120
119
  this.metrics = this.availableMetrics[0];
121
120
  const df = alignedSequencesColumn.dataFrame;
@@ -16,7 +16,7 @@ export function getStats(data: RawData | number[], bitArray: BitArray): Stats {
16
16
 
17
17
  let selectedIndex = 0;
18
18
  let restIndex = 0;
19
- for (let i = 0; i < data.length; ++i) {
19
+ for (let i = 0; i < bitArray.length; ++i) {
20
20
  if (bitArray.getBit(i))
21
21
  selected[selectedIndex++] = data[i];
22
22
  else
@@ -29,7 +29,7 @@ export function getStats(data: RawData | number[], bitArray: BitArray): Stats {
29
29
  count: selected.length,
30
30
  pValue: testResult[currentMeanDiff >= 0 ? 'p-value more' : 'p-value less'] || 0,
31
31
  meanDifference: currentMeanDiff || 0,
32
- ratio: selected.length / data.length,
32
+ ratio: selected.length / (bitArray.length),
33
33
  };
34
34
  }
35
35
 
@@ -28,7 +28,7 @@ export type PeptidesSettings = {
28
28
  };
29
29
 
30
30
  export type DrawOptions = {
31
- fontStyle?: string,
31
+ symbolStyle?: string,
32
32
  upperLetterHeight?: number,
33
33
  upperLetterAscent?: number,
34
34
  bounds?: DG.Rect,
@@ -36,6 +36,8 @@ export type DrawOptions = {
36
36
  textBaseline?: CanvasTextBaseline,
37
37
  marginVertical?: number,
38
38
  marginHorizontal?: number,
39
+ headerStyle?: string,
40
+ textHeight?: number,
39
41
  };
40
42
 
41
43
  export type StatsInfo = {