@datagrok/peptides 0.8.14 → 1.0.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.
Files changed (39) hide show
  1. package/.eslintrc.json +5 -2
  2. package/dist/package-test.js +1451 -2252
  3. package/dist/package.js +1277 -2105
  4. package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +9 -25
  5. package/package.json +10 -14
  6. package/package.png +0 -0
  7. package/src/model.ts +565 -599
  8. package/src/monomer-library.ts +31 -30
  9. package/src/package-test.ts +5 -6
  10. package/src/package.ts +52 -70
  11. package/src/tests/core.ts +67 -0
  12. package/src/tests/msa-tests.ts +3 -3
  13. package/src/tests/peptide-space-test.ts +65 -45
  14. package/src/tests/utils.ts +20 -50
  15. package/src/utils/cell-renderer.ts +86 -151
  16. package/src/utils/chem-palette.ts +3 -14
  17. package/src/utils/constants.ts +7 -0
  18. package/src/utils/filtering-statistics.ts +21 -53
  19. package/src/utils/misc.ts +29 -0
  20. package/src/utils/multiple-sequence-alignment.ts +5 -18
  21. package/src/utils/multivariate-analysis.ts +5 -8
  22. package/src/utils/peptide-similarity-space.ts +11 -8
  23. package/src/utils/types.ts +5 -2
  24. package/src/viewers/peptide-space-viewer.ts +66 -40
  25. package/src/viewers/sar-viewer.ts +35 -38
  26. package/src/viewers/stacked-barchart-viewer.ts +42 -83
  27. package/src/widgets/analyze-peptides.ts +64 -76
  28. package/src/widgets/distribution.ts +172 -47
  29. package/src/widgets/manual-alignment.ts +8 -12
  30. package/src/widgets/peptide-molecule.ts +48 -25
  31. package/src/widgets/subst-table.ts +53 -52
  32. package/src/workers/dimensionality-reducer.ts +2 -7
  33. package/{test-Peptides-2f94f62b59a8-c6d7c434.html → test-Peptides-34f75e5127b8-4210edfc.html} +2 -2
  34. package/src/peptides.ts +0 -327
  35. package/src/semantics.ts +0 -5
  36. package/src/tests/peptides-tests.ts +0 -60
  37. package/src/utils/SAR-multiple-filter.ts +0 -439
  38. package/src/utils/SAR-multiple-selection.ts +0 -177
  39. package/src/viewers/logo-viewer.ts +0 -195
@@ -1,61 +1,186 @@
1
1
  import * as ui from 'datagrok-api/ui';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
 
4
- import * as C from '../utils/constants';
5
4
  import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
6
- import {FilteringStatistics} from '../utils/filtering-statistics';
5
+ import $ from 'cash-dom';
6
+
7
+ import * as C from '../utils/constants';
8
+ import {getStats, Stats} from '../utils/filtering-statistics';
9
+ import {PeptidesModel} from '../model';
10
+
11
+ const allConst = 'All';
12
+ const otherConst = 'Other';
13
+
14
+ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel): DG.Widget {
15
+ const activityScaledCol = table.columns.bySemType(C.SEM_TYPES.ACTIVITY_SCALED)!;
16
+ const rowCount = activityScaledCol.length;
17
+ const selectionObject = model.currentSelection;
18
+ const positions = Object.keys(selectionObject);
19
+ const positionsLen = positions.length;
20
+ let aarStr = allConst;
21
+ let otherStr = '';
22
+ const useSelectedStr = model.isPeptideSpaceChangingBitset;
23
+
24
+ const updateDistributionHost = () => {
25
+ model.splitByPos = splitByPosition.value!;
26
+ model.splitByAAR = splitByAAR.value!;
27
+ const res: HTMLDivElement[] = [];
28
+ if (splitByPosition.value && splitByAAR.value) {
29
+ otherStr = otherConst;
30
+ for (const position of positions) {
31
+ const posCol = table.getCol(position);
32
+ for (const aar of selectionObject[position]) {
33
+ aarStr = `${position} : ${aar}`;
34
+ const splitCol = DG.Column.bool(C.COLUMNS_NAMES.SPLIT_COL, rowCount).init((i) => posCol.get(i) == aar);
35
+
36
+ const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
37
+ const currentStatsDf = model.statsDf.rows.match({Pos: position, AAR: aar}).toDataFrame();
38
+ const stats: Stats = {
39
+ count: currentStatsDf.get(C.COLUMNS_NAMES.COUNT, 0),
40
+ ratio: currentStatsDf.get(C.COLUMNS_NAMES.RATIO, 0),
41
+ pValue: currentStatsDf.get(C.COLUMNS_NAMES.P_VALUE, 0),
42
+ meanDifference: currentStatsDf.get(C.COLUMNS_NAMES.MEAN_DIFFERENCE, 0),
43
+ };
44
+ const distributionRoot = getDistributionAndStats(distributionTable, stats, aarStr, otherStr, true);
45
+ $(distributionRoot).addClass('d4-flex-col');
46
+
47
+ res.push(distributionRoot);
48
+ }
49
+ }
50
+ } else if (splitByPosition.value) {
51
+ otherStr = otherConst;
52
+ const activityScaledData = activityScaledCol.getRawData();
53
+ for (const position of positions) {
54
+ const posCol = table.getCol(position);
55
+ const aarList = selectionObject[position];
56
+ aarStr = `${position}: {${aarList.join(', ')}}`;
57
+
58
+ const mask = DG.BitSet.create(rowCount, (i) => aarList.includes(posCol.get(i)));
59
+ const stats = getStats(activityScaledData, mask);
60
+ const splitCol = DG.Column.fromBitSet(C.COLUMNS_NAMES.SPLIT_COL, mask);
61
+ const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
62
+ const distributionRoot = getDistributionAndStats(distributionTable, stats, aarStr, otherStr, true);
63
+ $(distributionRoot).addClass('d4-flex-col');
64
+
65
+ res.push(distributionRoot);
66
+ }
67
+ } else if (splitByAAR.value) {
68
+ const reversedSelectionObject: {[aar: string]: string[]} = {};
69
+ const aars = [];
70
+ for (const position of positions) {
71
+ for (const aar of selectionObject[position]) {
72
+ if (!reversedSelectionObject.hasOwnProperty(aar)) {
73
+ reversedSelectionObject[aar] = [position];
74
+ aars.push(aar);
75
+ continue;
76
+ }
77
+ if (!reversedSelectionObject[aar].includes(position))
78
+ reversedSelectionObject[aar].push(position);
79
+ }
80
+ }
81
+
82
+ otherStr = otherConst;
83
+ const activityScaledData = activityScaledCol.getRawData();
84
+ for (const aar of aars) {
85
+ const posList = reversedSelectionObject[aar];
86
+ aarStr = `${aar}: {${posList.join(', ')}}`;
87
+
88
+ const mask = DG.BitSet.create(rowCount, (i) => {
89
+ const currentRow = table.row(i);
90
+ for (const position of posList) {
91
+ if (currentRow.get(position) == aar)
92
+ return true;
93
+ }
94
+ return false;
95
+ });
96
+ const stats = getStats(activityScaledData, mask);
97
+ const splitCol = DG.Column.fromBitSet(C.COLUMNS_NAMES.SPLIT_COL, mask);
98
+ const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
99
+ const distributionRoot = getDistributionAndStats(distributionTable, stats, aarStr, otherStr, true);
100
+ $(distributionRoot).addClass('d4-flex-col');
101
+
102
+ res.push(distributionRoot);
103
+ }
104
+ } else {
105
+ const splitCol = table.col(C.COLUMNS_NAMES.SPLIT_COL);
106
+ if (!splitCol)
107
+ return new DG.Widget(ui.divText('No distribution'));
108
+
109
+ otherStr = '';
110
+ if (useSelectedStr) {
111
+ aarStr = 'Selected';
112
+ otherStr = otherConst;
113
+ } else if (positionsLen) {
114
+ aarStr = '';
115
+ for (const position of positions)
116
+ aarStr += `${position}: {${selectionObject[position].join(', ')}}; `;
117
+ aarStr = aarStr.slice(0, aarStr.length - 2);
118
+ otherStr = otherConst;
119
+ }
7
120
 
8
- export function getDistributionPlot(df: DG.DataFrame, valueCol: string, splitCol: string) {
9
- return df.plot.histogram({
10
- // const hist = originalDf.plot.histogram({
121
+ const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
122
+ const stats = getStats(activityScaledCol.getRawData(), table.selection);
123
+ const distributionRoot = getDistributionAndStats(distributionTable, stats, aarStr, otherStr);
124
+ $(distributionRoot).addClass('d4-flex-col');
125
+
126
+ res.push(distributionRoot);
127
+ }
128
+ $(distributionHost).empty().append(res);
129
+ };
130
+
131
+ const setDefaultProperties = (input: DG.InputBase) => {
132
+ input.enabled = positionsLen != 0;
133
+ $(input.root).find('.ui-input-editor').css('margin', '0px');
134
+ $(input.root).find('.ui-input-bool-deco').css('left', '-35px').css('margin-right', '-35px');
135
+ $(input.root).find('.ui-input-description').css('padding', '0px');
136
+ };
137
+
138
+ const splitByPosition = ui.boolInput('', model.splitByPos, updateDistributionHost);
139
+ splitByPosition.addPostfix('Split by position');
140
+ setDefaultProperties(splitByPosition);
141
+ $(splitByPosition.root).css('margin-right', '10px');
142
+ const splitByAAR = ui.boolInput('', model.splitByAAR, updateDistributionHost);
143
+ splitByAAR.addPostfix('Split by monomer');
144
+ setDefaultProperties(splitByAAR);
145
+
146
+ const controlsHost = ui.divH([splitByPosition.root, splitByAAR.root]);
147
+ const distributionHost = ui.div([], 'd4-flex-wrap');
148
+ splitByAAR.fireChanged();
149
+
150
+ return new DG.Widget(ui.divV([controlsHost, distributionHost]));
151
+ }
152
+
153
+ export function getDistributionAndStats(
154
+ table: DG.DataFrame, stats: Stats, thisLabel: string, otherLabel: string = '', isTooltip: boolean = false,
155
+ ): HTMLDivElement {
156
+ const labels = ui.divV([
157
+ ui.label(thisLabel, {style: {color: DG.Color.toHtml(otherLabel == '' ? DG.Color.blue : DG.Color.orange)}}),
158
+ ui.label(otherLabel, {style: {color: DG.Color.toHtml(DG.Color.blue)}})]);
159
+
160
+ const histRoot = table.plot.histogram({
11
161
  filteringEnabled: false,
12
- valueColumnName: valueCol,
13
- splitColumnName: splitCol,
162
+ valueColumnName: table.columns.bySemType(C.SEM_TYPES.ACTIVITY_SCALED)?.name,
163
+ splitColumnName: C.COLUMNS_NAMES.SPLIT_COL,
14
164
  legendVisibility: 'Never',
15
165
  showXAxis: true,
16
166
  showColumnSelector: false,
17
167
  showRangeSlider: false,
18
- });
19
- }
168
+ showBinSelector: !isTooltip,
169
+ backColor: isTooltip ? '#fdffe5' : '#fffff',
170
+ }).root;
171
+ histRoot.style.width = 'auto';
20
172
 
21
- export function getDistributionWidget(table: DG.DataFrame): DG.Widget {
22
- // const labelStr = this.multipleFilter.filterLabel;
23
- const splitCol = table.col(C.COLUMNS_NAMES.SPLIT_COL);
24
- if (!splitCol)
25
- return new DG.Widget(ui.divText('No distribution'));
26
- let [aarStr, otherStr] = splitCol.categories;
27
- if (typeof otherStr === 'undefined')
28
- [aarStr, otherStr] = [otherStr, aarStr];
29
- // const currentColor = DG.Color.toHtml(DG.Color.orange);
30
- // const otherColor = DG.Color.toHtml(DG.Color.blue);
31
- const currentColor = DG.Color.toHtml(DG.Color.getCategoryColor(splitCol, aarStr));
32
- const otherColor = DG.Color.toHtml(DG.Color.getCategoryColor(splitCol, otherStr));
33
-
34
- const currentLabel = ui.label(aarStr, {style: {color: currentColor}});
35
- const otherLabel = ui.label(otherStr, {style: {color: otherColor}});
36
- const elements: (HTMLLabelElement | HTMLElement)[] = [currentLabel, otherLabel];
37
-
38
- const getContent = () => {
39
- // const processedDf =
40
- // table.clone(null, [C.COLUMNS_NAMES.ACTIVITY_SCALED, C.COLUMNS_NAMES.SPLIT_COL]);
41
- const hist = getDistributionPlot(table, C.COLUMNS_NAMES.ACTIVITY_SCALED, C.COLUMNS_NAMES.SPLIT_COL).root;
42
-
43
- hist.style.width = 'auto';
44
- elements.push(hist);
45
-
46
- const stats = (table.temp[C.STATS] as FilteringStatistics).result;
47
- if (stats) {
48
- const tableMap: StringDictionary = {
49
- 'Statistics:': '',
50
- 'Count': stats.count.toString(),
51
- 'p-value': stats.pValue < 0.01 ? '<0.01' : stats.pValue.toFixed(2),
52
- 'Mean difference': stats.meanDifference.toFixed(2),
53
- };
54
-
55
- elements.push(ui.tableFromMap(tableMap));
56
- }
57
- return ui.divV(elements);
173
+ const tableMap: StringDictionary = {
174
+ 'Statistics:': '',
175
+ 'Count': stats.count.toString(),
176
+ 'Ratio': stats.ratio.toFixed(2),
177
+ 'p-value': stats.pValue < 0.01 ? '<0.01' : stats.pValue.toFixed(2),
178
+ 'Mean difference': stats.meanDifference.toFixed(2),
58
179
  };
59
180
 
60
- return new DG.Widget(getContent());
181
+ const result = ui.divV([labels, histRoot, ui.tableFromMap(tableMap)]);
182
+ result.style.minWidth = '200px';
183
+ if (isTooltip)
184
+ histRoot.style.maxHeight = '150px';
185
+ return result;
61
186
  }
@@ -3,25 +3,22 @@ import * as grok from 'datagrok-api/grok';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import $ from 'cash-dom';
6
- // import {splitAlignedPeptides} from '../utils/split-aligned';
7
6
  import '../styles.css';
8
- import {PeptidesController} from '../peptides';
7
+ import {PeptidesModel} from '../model';
9
8
 
10
- /**
11
- * Manual sequence alignment widget.
9
+ /** Manual sequence alignment widget.
12
10
  *
13
- * @param {DG.Column} alignedSequenceCol Aligned sequence column.
14
- * @param {DG.DataFrame} currentDf Working table.
15
- * @return {DG.Widget} Widget for manual sequence alignment.
16
- */
17
- export function manualAlignmentWidget(alignedSequenceCol: DG.Column, currentDf: DG.DataFrame) {
11
+ * @param {DG.Column} alignedSequenceCol Aligned sequence column
12
+ * @param {DG.DataFrame} currentDf Working table
13
+ * @return {DG.Widget} Widget for manual sequence alignment */
14
+ export function manualAlignmentWidget(alignedSequenceCol: DG.Column<string>, currentDf: DG.DataFrame): DG.Widget {
18
15
  const sequenceInput = ui.textInput('', alignedSequenceCol.get(currentDf.currentRowIdx));
19
16
  $(sequenceInput.root).addClass('pep-textinput');
20
17
 
21
18
  const applyChangesBtn = ui.button('Apply', async () => {
22
19
  const newSequence = sequenceInput.value;
23
20
  const affectedRowIndex = currentDf.currentRowIdx;
24
- const [splitSequence] = PeptidesController.splitAlignedPeptides(
21
+ const [splitSequence] = PeptidesModel.splitAlignedPeptides(
25
22
  DG.Column.fromStrings('splitSequence', [newSequence]), false);
26
23
 
27
24
  alignedSequenceCol.set(affectedRowIndex, newSequence);
@@ -33,8 +30,7 @@ export function manualAlignmentWidget(alignedSequenceCol: DG.Column, currentDf:
33
30
  grok.shell.o = null;
34
31
  grok.shell.o = temp;
35
32
 
36
- const peptidesController = await PeptidesController.getInstance(currentDf);
37
- peptidesController.init(currentDf);
33
+ const peptidesController = await PeptidesModel.getInstance(currentDf);
38
34
  peptidesController.updateDefault();
39
35
  });
40
36
 
@@ -1,8 +1,8 @@
1
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
- // import {ChemPalette} from '../utils/chem-palette';
5
- import {PeptidesController} from '../peptides';
4
+ import * as C from '../utils/constants';
5
+ import {PeptidesModel} from '../model';
6
6
 
7
7
  /**
8
8
  * 3D representation widget of peptide molecule.
@@ -11,40 +11,63 @@ import {PeptidesController} from '../peptides';
11
11
  * @param {string} pep Peptide string.
12
12
  * @return {Promise<DG.Widget>} Widget.
13
13
  */
14
- export async function peptideMoleculeWidget(pep: string): Promise<DG.Widget> {
14
+ export async function peptideMoleculeWidget(pep: string, currentTable: DG.DataFrame): Promise<DG.Widget> {
15
15
  const pi = DG.TaskBarProgressIndicator.create('Creating NGL view');
16
+ const separator = currentTable.columns.bySemType(C.SEM_TYPES.ALIGNED_SEQUENCE)!.tags[C.TAGS.SEPARATOR];
16
17
 
17
- const smiles = getMolecule(pep);
18
- if (smiles == '')
19
- return new DG.Widget(ui.divH([]));
18
+ let widgetHost;
19
+ let smiles = '';
20
+ let molfileStr = '';
21
+ try {
22
+ try {
23
+ const params = {table: currentTable};
24
+ const result = await grok.functions.call('Customerextensions:getPeptideStructure', params) as string[];
25
+ if (result.length !== 0) {
26
+ smiles = result[0];
27
+ molfileStr = result[1];
28
+ throw new Error(`Found structure in DB`);
29
+ }
20
30
 
31
+ smiles = getMolecule(pep, separator);
32
+ if (smiles == '')
33
+ throw new Error('Couldn\'t get smiles');
21
34
 
22
- let molfileStr = (await grok.functions.call('Peptides:SmiTo3D', {smiles}));
35
+ molfileStr = (await grok.functions.call('Peptides:SmiTo3D', {smiles})) as string;
36
+ } catch (e) {
37
+ console.warn(e);
38
+ }
23
39
 
24
- molfileStr = molfileStr.replaceAll('\\n', '\n'); ;
25
- const stringBlob = new Blob([molfileStr], {type: 'text/plain'});
26
- const nglHost = ui.div([], {classes: 'd4-ngl-viewer', id: 'ngl-3d-host'});
40
+ try {
41
+ molfileStr = molfileStr.replaceAll('\\n', '\n');
42
+ const stringBlob = new Blob([molfileStr], {type: 'text/plain'});
43
+ const nglHost = ui.div([], {classes: 'd4-ngl-viewer', id: 'ngl-3d-host'});
27
44
 
28
- //@ts-ignore
29
- const stage = new NGL.Stage(nglHost, {backgroundColor: 'white'});
30
- //@ts-ignore
31
- stage.loadFile(stringBlob, {ext: 'sdf'}).then(function(comp: NGL.StructureComponent) {
32
- stage.setSize(300, 300);
33
- comp.addRepresentation('ball+stick');
34
- comp.autoView();
35
- });
36
- const sketch = grok.chem.svgMol(smiles);
37
- const panel = ui.divH([sketch]);
45
+ //@ts-ignore
46
+ const stage = new NGL.Stage(nglHost, {backgroundColor: 'white'});
47
+ //@ts-ignore
48
+ stage.loadFile(stringBlob, {ext: 'sdf'}).then(function(comp: NGL.StructureComponent) {
49
+ stage.setSize(300, 300);
50
+ comp.addRepresentation('ball+stick');
51
+ comp.autoView();
52
+ });
53
+ const sketch = grok.chem.svgMol(molfileStr);
54
+ const panel = ui.divH([sketch]);
38
55
 
56
+ widgetHost = ui.div([panel, nglHost]);
57
+ } catch (e) {
58
+ widgetHost = ui.divText('Couldn\'t get peptide structure');
59
+ }
60
+ } catch (e) {
61
+ widgetHost = ui.divText('Couldn\'t get peptide structure');
62
+ }
39
63
  pi.close();
40
-
41
- return new DG.Widget(ui.div([panel, nglHost]));
64
+ return new DG.Widget(widgetHost);
42
65
  }
43
66
 
44
- export function getMolecule(pep: string): string {
45
- const split = pep.split('-');
67
+ export function getMolecule(pep: string, separator: string): string {
68
+ const split = pep.split(separator);
46
69
  const mols = [];
47
- const chemPalette = PeptidesController.chemPalette;
70
+ const chemPalette = PeptidesModel.chemPalette;
48
71
  for (let i = 1; i < split.length - 1; i++) {
49
72
  if (split[i] in chemPalette.AASmiles) {
50
73
  const aar = chemPalette.AASmiles[split[i]];
@@ -1,73 +1,74 @@
1
1
  import * as ui from 'datagrok-api/ui';
2
2
  import * as DG from 'datagrok-api/dg';
3
- import { PeptidesController } from '../peptides';
3
+ import * as C from '../utils/constants';
4
+ import * as type from '../utils/types';
5
+ import {PeptidesModel} from '../model';
4
6
 
5
- export async function substitutionsWidget(table: DG.DataFrame): Promise<DG.Widget> {
6
- const controller = await PeptidesController.getInstance(table);
7
- controller.init(table);
8
- const substTable = controller.getSubstitutions();
7
+ export function substitutionsWidget(table: DG.DataFrame, model: PeptidesModel): DG.Widget {
8
+ const substInfo = model.substitutionsInfo;
9
+ const currentCell = model.currentSelection;
10
+ const positions = Object.keys(currentCell);
9
11
 
10
- if (!substTable)
12
+ if (!positions.length)
11
13
  return new DG.Widget(ui.label('No substitution table generated'));
12
14
 
13
- const dfRowCount = substTable.rowCount;
14
- const aminoInputFrom = ui.stringInput('from', '');
15
- const aminoInputTo = ui.stringInput('to', '');
16
- const fromToMap: {[key: string]: DG.BitSet} = {};
17
- let aminoFrom = '';
18
- let aminoTo = '';
19
- const initialCol: DG.Column = substTable.getCol('Initial');
20
- const substitutedCol: DG.Column = substTable.getCol('Substituted');
15
+ const substitutionsArray: string[] = [];
16
+ const deltaArray: number[] = [];
17
+ const substitutedToArray: string[] = [];
18
+ const alignedSeqCol = table.columns.bySemType(C.SEM_TYPES.ALIGNED_SEQUENCE)!;
19
+ const activityScaledCol = table.columns.bySemType(C.SEM_TYPES.ACTIVITY_SCALED)!;
20
+ const seenIndexes = new Map<number, number[]>();
21
21
 
22
- initialCol.semType = 'alignedSequenceDifference';
23
- initialCol.name = 'Substitution';
24
- // substTable.columns.remove('Substituted');
25
- // const substCol = table.getCol('Substitution');
22
+ for (const pos of positions) {
23
+ for (const aar of currentCell[pos]) {
24
+ const substitutionsMap = substInfo.get(aar)?.get(pos) as Map<number, type.UTypedArray> | undefined;
25
+ if (typeof substitutionsMap === 'undefined')
26
+ continue;
26
27
 
27
- for (let i = 0; i < dfRowCount; ++i) {
28
- // const [from, to] = substCol!.get(i).split('#');
29
- const from = initialCol.get(i);
30
- const to = substitutedCol.get(i);
31
- const aminosFrom: [] = from.split('-');
32
- const aminosTo: [] = to.split('-');
28
+ const posCol = table.getCol(pos);
29
+ for (const [referenceIdx, indexArray] of substitutionsMap.entries()) {
30
+ const forbiddentIndexes = seenIndexes.has(referenceIdx) ? seenIndexes.get(referenceIdx)! : [];
31
+ const baseSequence = alignedSeqCol.get(referenceIdx);
32
+ const baseActivity = activityScaledCol.get(referenceIdx);
33
33
 
34
- for (let j = 0; j < aminosFrom.length; ++j) {
35
- if (aminosFrom[j] != aminosTo[j]) {
36
- const idx = `${getAmino(aminosFrom[j])}#${getAmino(aminosTo[j])}`;
34
+ for (const subIdx of indexArray) {
35
+ if (forbiddentIndexes.includes(subIdx))
36
+ continue;
37
37
 
38
- if (!(idx in fromToMap))
39
- fromToMap[idx] = DG.BitSet.create(dfRowCount);
40
- fromToMap[idx].set(i, true);
38
+ if (!seenIndexes.has(subIdx))
39
+ seenIndexes.set(subIdx, []);
40
+
41
+ seenIndexes.get(subIdx)!.push(referenceIdx);
42
+ substitutionsArray.push(`${baseSequence}#${alignedSeqCol.get(subIdx)}`);
43
+ deltaArray.push(baseActivity - activityScaledCol.get(subIdx));
44
+ substitutedToArray.push(posCol.get(subIdx));
45
+ }
41
46
  }
42
47
  }
43
48
  }
44
49
 
45
- for (let i = 0; i < initialCol.length; ++i) {
46
- const sequenceDifference = `${initialCol.get(i)}#${substitutedCol.get(i)}`;
47
- initialCol.set(i, sequenceDifference);
48
- }
50
+ if (!substitutionsArray.length)
51
+ return new DG.Widget(ui.label('No substitution table generated'));
49
52
 
50
- aminoInputFrom.onInput(() => {
51
- aminoFrom = getAmino(aminoInputFrom.value);
52
- const fromKey = `${aminoFrom}#${aminoTo}`;
53
- if (fromKey in fromToMap)
54
- substTable.selection.copyFrom(fromToMap[fromKey]);
55
- });
53
+ const substCol = DG.Column.fromStrings('Substiutions', substitutionsArray);
54
+ substCol.semType = C.SEM_TYPES.ALIGNED_SEQUENCE_DIFFERENCE;
55
+ const toColName = '~to';
56
+ const hiddenSubstToAarCol = DG.Column.fromStrings(toColName, substitutedToArray);
57
+ const substTable =
58
+ DG.DataFrame.fromColumns([substCol, DG.Column.fromList('double', 'Delta', deltaArray), hiddenSubstToAarCol]);
56
59
 
57
- aminoInputTo.onInput(() => {
58
- aminoTo = getAmino(aminoInputTo.value);
59
- const toKey = `${aminoFrom}#${aminoTo}`;
60
- if (toKey in fromToMap)
61
- substTable.selection.copyFrom(fromToMap[toKey]);
60
+ const aminoToInput = ui.stringInput('Substituted to:', '', () => {
61
+ const substitutedToAar = aminoToInput.stringValue;
62
+ if (substitutedToAar != '')
63
+ substTable.filter.init((idx) => hiddenSubstToAarCol.get(idx) === substitutedToAar);
64
+ else
65
+ substTable.filter.setAll(true);
62
66
  });
63
67
 
64
68
  const grid = substTable.plot.grid();
65
69
  grid.props.allowEdit = false;
66
- grid.root.style.width = 'auto';
67
- grid.root.style.height = '150px';
68
- return new DG.Widget(ui.divV([aminoInputFrom.root, aminoInputTo.root, grid.root]));
69
- }
70
-
71
- function getAmino(amino: string): string {
72
- return amino === '' ? '-' : amino;
70
+ const gridRoot = grid.root;
71
+ gridRoot.style.width = 'auto';
72
+ gridRoot.style.height = '150px';
73
+ return new DG.Widget(ui.divV([aminoToInput.root, gridRoot]));
73
74
  }
@@ -11,16 +11,11 @@ import {KnownMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
11
11
  * @return {any} Embedding (and distance matrix where applicable).
12
12
  */
13
13
  function onMessage(columnData: any[], method: KnownMethods, measure: KnownMetrics, options: any): any {
14
- const reducer = new DimensionalityReducer(
15
- columnData,
16
- method,
17
- measure,
18
- options,
19
- );
14
+ const reducer = new DimensionalityReducer(columnData, method, measure, options);
20
15
  return reducer.transform(true);
21
16
  }
22
17
 
23
- self.onmessage = ({data: {columnData, method, measure, options}}) => {
18
+ self.onmessage = ({data: {columnData, method, measure, options}}): void => {
24
19
  const embedding = onMessage(columnData, method, measure, options);
25
20
  self.postMessage({
26
21
  distance: embedding.distance,
@@ -1,4 +1,4 @@
1
- <html><head><meta charset="utf-8"/><title>Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=2f94f62b59a8. Commit c6d7c434.</title><style type="text/css">html,
1
+ <html><head><meta charset="utf-8"/><title>Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=34f75e5127b8. Commit 4210edfc.</title><style type="text/css">html,
2
2
  body {
3
3
  font-family: Arial, Helvetica, sans-serif;
4
4
  font-size: 1rem;
@@ -229,7 +229,7 @@ header {
229
229
  font-size: 1rem;
230
230
  padding: 0 0.5rem;
231
231
  }
232
- </style></head><body><div id="jesthtml-content"><header><h1 id="title">Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=2f94f62b59a8. Commit c6d7c434.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-05-09 13:23:40</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts</div><div class="suite-time warn">117.439s</div></div><div class="suite-tests"><div class="test-result failed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">failed</div><div class="test-duration">100.002s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: thrown: "Exceeded timeout of 100000 ms for a test.
232
+ </style></head><body><div id="jesthtml-content"><header><h1 id="title">Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=34f75e5127b8. Commit 4210edfc.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-07-08 12:49:24</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts</div><div class="suite-time warn">113.293s</div></div><div class="suite-tests"><div class="test-result failed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">failed</div><div class="test-duration">100.003s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: thrown: "Exceeded timeout of 100000 ms for a test.
233
233
  Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
234
234
  at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:22:1)
235
235
  at Runtime._execModule (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runtime/build/index.js:1646:24)