@datagrok/peptides 0.8.12 → 0.8.15

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 (36) hide show
  1. package/.eslintrc.json +5 -2
  2. package/dist/package-test.js +1060 -1557
  3. package/dist/package.js +958 -1492
  4. package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +120 -62
  5. package/package.json +16 -16
  6. package/src/model.ts +438 -387
  7. package/src/monomer-library.ts +31 -30
  8. package/src/package-test.ts +2 -3
  9. package/src/package.ts +56 -52
  10. package/src/tests/core.ts +63 -0
  11. package/src/tests/utils.ts +10 -7
  12. package/src/utils/cell-renderer.ts +25 -151
  13. package/src/utils/chem-palette.ts +3 -14
  14. package/src/utils/constants.ts +4 -0
  15. package/src/utils/filtering-statistics.ts +2 -2
  16. package/src/utils/misc.ts +29 -0
  17. package/src/utils/multiple-sequence-alignment.ts +5 -18
  18. package/src/utils/multivariate-analysis.ts +5 -8
  19. package/src/utils/peptide-similarity-space.ts +12 -9
  20. package/src/utils/types.ts +4 -0
  21. package/src/viewers/peptide-space-viewer.ts +18 -19
  22. package/src/viewers/sar-viewer.ts +32 -37
  23. package/src/viewers/stacked-barchart-viewer.ts +34 -34
  24. package/src/widgets/analyze-peptides.ts +53 -75
  25. package/src/widgets/distribution.ts +4 -9
  26. package/src/widgets/manual-alignment.ts +8 -12
  27. package/src/widgets/peptide-molecule.ts +48 -25
  28. package/src/widgets/subst-table.ts +43 -58
  29. package/src/workers/dimensionality-reducer.ts +8 -8
  30. package/{test-Peptides-414a1874a71a-2f1c6575.html → test-Peptides-e702a345ac13-2a8c8b59.html} +15 -17
  31. package/src/peptides.ts +0 -327
  32. package/src/semantics.ts +0 -5
  33. package/src/tests/peptides-tests.ts +0 -60
  34. package/src/utils/SAR-multiple-filter.ts +0 -439
  35. package/src/utils/SAR-multiple-selection.ts +0 -177
  36. package/src/viewers/logo-viewer.ts +0 -195
@@ -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,58 @@
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
7
  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();
8
+ const model = await PeptidesModel.getInstance(table);
9
+ const substInfo = model.substitutionsInfo;
10
+ const currentCell = model.getCurrentAARandPos();
9
11
 
10
- if (!substTable)
12
+ if (currentCell.aar === currentCell.pos)
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');
21
-
22
- initialCol.semType = 'alignedSequenceDifference';
23
- initialCol.name = 'Substitution';
24
- // substTable.columns.remove('Substituted');
25
- // const substCol = table.getCol('Substitution');
26
-
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('-');
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])}`;
15
+ const substitutionsMap =
16
+ substInfo.get(currentCell.aar)?.get(currentCell.pos) as Map<number, type.UTypedArray> | undefined;
17
+ if (typeof substitutionsMap === 'undefined')
18
+ return new DG.Widget(ui.label('No substitution table generated'));
37
19
 
38
- if (!(idx in fromToMap))
39
- fromToMap[idx] = DG.BitSet.create(dfRowCount);
40
- fromToMap[idx].set(i, true);
41
- }
20
+ const substitutionsArray: string[] = [];
21
+ const deltaArray: number[] = [];
22
+ const substitutedToArray: string[] = [];
23
+ // const alignedSeqCol = table.getCol(C.COLUMNS_NAMES.ALIGNED_SEQUENCE);
24
+ // const activityScaledCol = table.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
25
+ const alignedSeqCol = table.columns.bySemType(C.SEM_TYPES.ALIGNED_SEQUENCE)!;
26
+ const activityScaledCol = table.columns.bySemType(C.SEM_TYPES.ACTIVITY_SCALED)!;
27
+ const posCol = table.getCol(currentCell.pos);
28
+ for (const [referenceIdx, indexArray] of substitutionsMap.entries()) {
29
+ const baseSequence = alignedSeqCol.get(referenceIdx);
30
+ const baseActivity = activityScaledCol.get(referenceIdx);
31
+ for (const subIdx of indexArray) {
32
+ substitutionsArray.push(`${baseSequence}#${alignedSeqCol.get(subIdx)}`);
33
+ deltaArray.push(baseActivity - activityScaledCol.get(subIdx));
34
+ substitutedToArray.push(posCol.get(subIdx));
42
35
  }
43
36
  }
44
-
45
- for (let i = 0; i < initialCol.length; ++i) {
46
- const sequenceDifference = `${initialCol.get(i)}#${substitutedCol.get(i)}`;
47
- initialCol.set(i, sequenceDifference);
48
- }
49
-
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
- });
56
-
57
- aminoInputTo.onInput(() => {
58
- aminoTo = getAmino(aminoInputTo.value);
59
- const toKey = `${aminoFrom}#${aminoTo}`;
60
- if (toKey in fromToMap)
61
- substTable.selection.copyFrom(fromToMap[toKey]);
37
+ const substCol = DG.Column.fromStrings('Substiutions', substitutionsArray);
38
+ substCol.semType = C.SEM_TYPES.ALIGNED_SEQUENCE_DIFFERENCE;
39
+ const toColName = '~to';
40
+ const hiddenSubstToAarCol = DG.Column.fromStrings(toColName, substitutedToArray);
41
+ const substTable =
42
+ DG.DataFrame.fromColumns([substCol, DG.Column.fromList('double', 'Delta', deltaArray), hiddenSubstToAarCol]);
43
+
44
+ const aminoToInput = ui.stringInput('Substituted to:', '', () => {
45
+ const substitutedToAar = aminoToInput.stringValue;
46
+ if (substitutedToAar != '')
47
+ substTable.filter.init((idx) => hiddenSubstToAarCol.get(idx) === substitutedToAar);
48
+ else
49
+ substTable.filter.setAll(true);
62
50
  });
63
51
 
64
52
  const grid = substTable.plot.grid();
65
53
  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;
54
+ const gridRoot = grid.root;
55
+ gridRoot.style.width = 'auto';
56
+ gridRoot.style.height = '150px';
57
+ return new DG.Widget(ui.divV([aminoToInput.root, gridRoot]));
73
58
  }
@@ -1,6 +1,5 @@
1
1
  import {DimensionalityReducer, KnownMethods} from '@datagrok-libraries/ml/src/reduce-dimensionality';
2
2
  import {KnownMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
3
- import {Coordinates} from '@datagrok-libraries/utils/src/type-declarations';
4
3
 
5
4
  /**
6
5
  * Worker thread receiving data function.
@@ -8,23 +7,24 @@ import {Coordinates} from '@datagrok-libraries/utils/src/type-declarations';
8
7
  * @param {any[]} columnData Samples to process.
9
8
  * @param {string} method Embedding method.
10
9
  * @param {string} measure Distance metric.
11
- * @param {number} cyclesCount Number of cycles to repeat.
12
- * @return {Coordinates} Embedding.
10
+ * @param {any} options Options to pass to algorithm.
11
+ * @return {any} Embedding (and distance matrix where applicable).
13
12
  */
14
- function onMessage(columnData: any[], method: KnownMethods, measure: KnownMetrics, cyclesCount: number): Coordinates {
13
+ function onMessage(columnData: any[], method: KnownMethods, measure: KnownMetrics, options: any): any {
15
14
  const reducer = new DimensionalityReducer(
16
15
  columnData,
17
16
  method,
18
17
  measure,
19
- {cycles: cyclesCount},
18
+ options,
20
19
  );
21
20
  return reducer.transform(true);
22
21
  }
23
22
 
24
- self.onmessage = ({data: {columnData, method, measure, cyclesCount}}) => {
25
- const embedding = onMessage(columnData, method, measure, cyclesCount);
23
+ self.onmessage = ({data: {columnData, method, measure, options}}): void => {
24
+ const embedding = onMessage(columnData, method, measure, options);
26
25
  self.postMessage({
27
- embedding: embedding,
26
+ distance: embedding.distance,
27
+ embedding: embedding.embedding,
28
28
  });
29
29
  };
30
30
 
@@ -1,4 +1,4 @@
1
- <html><head><meta charset="utf-8"/><title>Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=414a1874a71a. Commit 2f1c6575.</title><style type="text/css">html,
1
+ <html><head><meta charset="utf-8"/><title>Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=e702a345ac13. Commit 2a8c8b59.</title><style type="text/css">html,
2
2
  body {
3
3
  font-family: Arial, Helvetica, sans-serif;
4
4
  font-size: 1rem;
@@ -229,21 +229,14 @@ 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=414a1874a71a. Commit 2f1c6575.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-04-29 11:32:43</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">119.379s</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.001s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: thrown: "Exceeded timeout of 100000 ms for a test.
233
- Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
234
- at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:22:1)
235
- at Runtime._execModule (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runtime/build/index.js:1646:24)
236
- at Runtime._loadModule (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runtime/build/index.js:1185:12)
237
- at Runtime.requireModule (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runtime/build/index.js:1009:12)
238
- at jestAdapter (/home/runner/work/public/public/packages/Peptides/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:13)
239
- at runTestInternal (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runner/build/runTest.js:389:16)
240
- at runTest (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runner/build/runTest.js:475:34)
241
- at TestRunner.runTests (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runner/build/index.js:101:12)
242
- at TestScheduler.scheduleTests (/home/runner/work/public/public/packages/Peptides/node_modules/@jest/core/build/TestScheduler.js:333:13)
243
- at runJest (/home/runner/work/public/public/packages/Peptides/node_modules/@jest/core/build/runJest.js:404:19)
244
- at _run10000 (/home/runner/work/public/public/packages/Peptides/node_modules/@jest/core/build/cli/index.js:320:7)
245
- at runCLI (/home/runner/work/public/public/packages/Peptides/node_modules/@jest/core/build/cli/index.js:173:3)
246
- at Object.run (/home/runner/work/public/public/packages/Peptides/node_modules/jest-cli/build/cli/index.js:155:37)</pre></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/Peptides/src/__jest__/test-node.ts:62:11)
232
+ </style></head><body><div id="jesthtml-content"><header><h1 id="title">Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=e702a345ac13. Commit 2a8c8b59.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-06-06 21:05:18</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">105.848s</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">95.396s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: expect(received).toBe(expected) // Object.is equality
233
+
234
+ Expected: false
235
+ Received: true
236
+ at /home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:49:20
237
+ at Generator.next (&lt;anonymous&gt;)
238
+ at fulfilled (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:24:58)
239
+ at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/Peptides/src/__jest__/test-node.ts:62:11)
247
240
  at Generator.next (&lt;anonymous&gt;)
248
241
  at fulfilled (/home/runner/work/public/public/packages/Peptides/src/__jest__/test-node.ts:24:58)
249
242
  at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Using web root: http://localhost:8080</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:24:11
@@ -253,4 +246,9 @@ Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long
253
246
  at Object.&lt;anonymous&gt;.__awaiter (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:23:12)
254
247
  at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:22:23)
255
248
  at Promise.then.completed (/home/runner/work/public/public/packages/Peptides/node_modules/jest-circus/build/utils.js:391:28)
256
- at new Promise (&lt;anonymous&gt;)</pre><pre class="suite-consolelog-item-message">Testing Peptides package</pre></div></div></div></div></body></html>
249
+ at new Promise (&lt;anonymous&gt;)</pre><pre class="suite-consolelog-item-message">Testing Peptides package</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:47:11
250
+ at Generator.next (&lt;anonymous&gt;)
251
+ at fulfilled (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:24:58)
252
+ at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Core.Start analysis: simple: Operation caused an exception (FileSystemException: Cannot open file, path = '/home/grok/data/prod/packages/data/Peptides/HELMMonomers_June10.sdf' (OS Error: No such file or directory, errno = 2))
253
+ Core.Start analysis: сomplex: Operation caused an exception (FileSystemException: Cannot open file, path = '/home/grok/data/prod/packages/data/Peptides/HELMMonomers_June10.sdf' (OS Error: No such file or directory, errno = 2))
254
+ </pre></div></div></div></div></body></html>
package/src/peptides.ts DELETED
@@ -1,327 +0,0 @@
1
- import * as grok from 'datagrok-api/grok';
2
- import * as DG from 'datagrok-api/dg';
3
- import {PeptidesModel} from './model';
4
- import {SARViewer, SARViewerVertical} from './viewers/sar-viewer';
5
- import {ChemPalette} from './utils/chem-palette';
6
- import {Observable} from 'rxjs';
7
- import {MonomerLibrary} from './monomer-library';
8
- import {_package} from './package';
9
- import {setAARRenderer} from './utils/cell-renderer';
10
- import * as C from './utils/constants';
11
- import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
12
- import { FilteringStatistics } from './utils/filtering-statistics';
13
-
14
- type viewerTypes = SARViewer | SARViewerVertical;
15
- export class PeptidesController {
16
- private static _controllerName: string = 'peptidesController';
17
- private helpUrl = '/help/domains/bio/peptides.md';
18
-
19
- private _model: PeptidesModel;
20
- sarViewer!: SARViewer;
21
- sarViewerVertical!: SARViewerVertical;
22
- isInitialized = false;
23
-
24
- private constructor(dataFrame: DG.DataFrame) {
25
- this._model = PeptidesModel.getInstance(dataFrame);
26
- }
27
-
28
- static async getInstance(dataFrame: DG.DataFrame): Promise<PeptidesController> {
29
- dataFrame.temp[PeptidesController.controllerName] ??= new PeptidesController(dataFrame);
30
- if (dataFrame.temp[MonomerLibrary.id] === null) {
31
- const sdf = await _package.files.readAsText('HELMMonomers_June10.sdf');
32
- dataFrame.temp[MonomerLibrary.id] ??= new MonomerLibrary(sdf);
33
- }
34
- return dataFrame.temp[PeptidesController.controllerName];
35
- }
36
-
37
- static get controllerName() {return PeptidesController._controllerName;}
38
-
39
- get dataFrame() {return this._model.dataFrame;}
40
-
41
- static setAARRenderer(col: DG.Column, grid: DG.Grid) {
42
- return setAARRenderer(col, grid);
43
- }
44
-
45
- get onStatsDataFrameChanged(): Observable<DG.DataFrame> {return this._model.onStatsDataFrameChanged;}
46
-
47
- get onSARGridChanged(): Observable<DG.Grid> {return this._model.onSARGridChanged;}
48
-
49
- get onSARVGridChanged(): Observable<DG.Grid> {return this._model.onSARVGridChanged;}
50
-
51
- // get onGroupMappingChanged(): Observable<StringDictionary> {return this._model.onGroupMappingChanged;}
52
-
53
- get onSubstTableChanged(): Observable<DG.DataFrame> {return this._model.onSubstTableChanged;}
54
-
55
- async updateDefault() {await this._model.updateDefault();}
56
-
57
- get sarGrid() {return this._model._sarGrid;}
58
-
59
- get sarVGrid() {return this._model._sarVGrid;}
60
-
61
- get sourceGrid() {return this._model._sourceGrid!; }
62
-
63
- async updateData(
64
- activityScaling?: string, sourceGrid?: DG.Grid, twoColorMode?: boolean, activityLimit?: number,
65
- maxSubstitutions?: number, isSubstitutionOn?: boolean, filterMode?: boolean,
66
- ) {
67
- filterMode ??= false;
68
- await this._model.updateData(
69
- activityScaling, sourceGrid, twoColorMode, activityLimit, maxSubstitutions, isSubstitutionOn, filterMode);
70
- }
71
-
72
- getSubstitutions() {
73
- return this._model.getSubstitutionTable();
74
- }
75
-
76
- static async scaleActivity(
77
- activityScaling: string, df: DG.DataFrame, originalActivityName?: string, cloneBitset = false,
78
- ): Promise<[DG.DataFrame, string]> {
79
- // const df = sourceGrid.dataFrame!;
80
- let currentActivityColName = originalActivityName ?? C.COLUMNS_NAMES.ACTIVITY;
81
- const flag = (df.columns as DG.ColumnList).names().includes(currentActivityColName) &&
82
- currentActivityColName === originalActivityName;
83
- currentActivityColName = flag ? currentActivityColName : C.COLUMNS_NAMES.ACTIVITY;
84
- const tempDf = df.clone(cloneBitset ? df.filter : null, [currentActivityColName]);
85
-
86
- let formula = '${' + currentActivityColName + '}';
87
- let newColName = 'activity'; //originalActivityName ?? df.temp[C.COLUMNS_NAMES.ACTIVITY] ?? currentActivityColName;
88
- switch (activityScaling) {
89
- case 'none':
90
- break;
91
- case 'lg':
92
- formula = `Log10(${formula})`;
93
- newColName = `Log10(${newColName})`;
94
- break;
95
- case '-lg':
96
- formula = `-1*Log10(${formula})`;
97
- newColName = `-Log10(${newColName})`;
98
- break;
99
- default:
100
- throw new Error(`ScalingError: method \`${activityScaling}\` is not available.`);
101
- }
102
-
103
- await (tempDf.columns as DG.ColumnList).addNewCalculated(C.COLUMNS_NAMES.ACTIVITY_SCALED, formula);
104
- df.tags['scaling'] = activityScaling;
105
-
106
- return [tempDf, newColName];
107
- }
108
-
109
- get originalActivityColumnName(): string {return this.dataFrame.temp[C.COLUMNS_NAMES.ACTIVITY];}
110
-
111
- get substTooltipData() {return this._model.substTooltipData;}
112
-
113
- static splitAlignedPeptides(peptideColumn: DG.Column, filter: boolean = true): [DG.DataFrame, number[]] {
114
- const splitPeptidesArray: string[][] = [];
115
- let currentSplitPeptide: string[];
116
- let modeMonomerCount = 0;
117
- let currentLength;
118
- const colLength = peptideColumn.length;
119
-
120
- // splitting data
121
- const monomerLengths: {[index: string]: number} = {};
122
- for (let i = 0; i < colLength; i++) {
123
- currentSplitPeptide = peptideColumn.get(i).split('-').map((value: string) => value ? value : '-');
124
- splitPeptidesArray.push(currentSplitPeptide);
125
- currentLength = currentSplitPeptide.length;
126
- monomerLengths[currentLength + ''] =
127
- monomerLengths[currentLength + ''] ? monomerLengths[currentLength + ''] + 1 : 1;
128
- }
129
- //@ts-ignore: what I do here is converting string to number the most effective way I could find. parseInt is slow
130
- modeMonomerCount = 1 * Object.keys(monomerLengths).reduce((a, b) => monomerLengths[a] > monomerLengths[b] ? a : b);
131
-
132
- // making sure all of the sequences are of the same size
133
- // and marking invalid sequences
134
- let nTerminal: string;
135
- const invalidIndexes: number[] = [];
136
- let splitColumns: string[][] = Array.from({length: modeMonomerCount}, (_) => []);
137
- modeMonomerCount--; // minus N-terminal
138
- for (let i = 0; i < colLength; i++) {
139
- currentSplitPeptide = splitPeptidesArray[i];
140
- nTerminal = currentSplitPeptide.pop()!; // it is guaranteed that there will be at least one element
141
- currentLength = currentSplitPeptide.length;
142
- if (currentLength !== modeMonomerCount)
143
- invalidIndexes.push(i);
144
-
145
- for (let j = 0; j < modeMonomerCount; j++)
146
- splitColumns[j].push(j < currentLength ? currentSplitPeptide[j] : '-');
147
-
148
- splitColumns[modeMonomerCount].push(nTerminal);
149
- }
150
- modeMonomerCount--; // minus C-terminal
151
-
152
- //create column names list
153
- const columnNames = Array.from({length: modeMonomerCount}, (_, index) => `${index + 1 < 10 ? 0 : ''}${index + 1 }`);
154
- columnNames.splice(0, 0, 'Nterminal');
155
- columnNames.push('Cterminal');
156
-
157
- // filter out the columns with the same values
158
- if (filter) {
159
- splitColumns = splitColumns.filter((positionArray, index) => {
160
- const isRetained = new Set(positionArray).size > 1;
161
- if (!isRetained)
162
- columnNames.splice(index, 1);
163
-
164
- return isRetained;
165
- });
166
- }
167
-
168
- return [
169
- DG.DataFrame.fromColumns(splitColumns.map((positionArray, index) => {
170
- return DG.Column.fromList('string', columnNames[index], positionArray);
171
- })),
172
- invalidIndexes,
173
- ];
174
- }
175
-
176
- static get chemPalette() { return ChemPalette; }
177
-
178
- assertVar(variable: string, init = false): boolean {
179
- //@ts-ignore
180
- let foundVariable: any = this[variable];
181
- if (!foundVariable && init) {
182
- //@ts-ignore
183
- this[variable] = foundVariable = this.dataFrame.temp[variable];
184
- }
185
-
186
- const assertionResult = foundVariable ? true : false
187
- if (init && !assertionResult)
188
- throw new Error(`Variable assertion error: variable '${variable}' is not found in dataFrame`);
189
-
190
- return assertionResult;
191
- }
192
-
193
- assertVariables(variables: string[], init = false) {
194
- let result = true;
195
- for (const variable of variables)
196
- result &&= this.assertVar(variable, init);
197
-
198
- return result;
199
- }
200
-
201
- syncProperties(isSourceSAR = true) {
202
- this.assertVariables(['sarViewer', 'sarViewerVertical'], true);
203
- const sourceViewer = isSourceSAR ? this.sarViewer : this.sarViewerVertical;
204
- const targetViewer = isSourceSAR ? this.sarViewerVertical : this.sarViewer;
205
- const properties = sourceViewer.props.getProperties();
206
- for (const property of properties)
207
- targetViewer.props.set(property.name, property.get(sourceViewer));
208
- }
209
-
210
- modifyOrCreateSplitCol(aar: string, position: string, notify: boolean = true) {
211
- this._model.modifyOrCreateSplitCol(aar, position);
212
- if (notify)
213
- this._model.fireBitsetChanged();
214
- }
215
-
216
- setSARGridCellAt(aar: string, position: string) {
217
- const sarDf = this.sarGrid.dataFrame;
218
- const aarCol = sarDf.getCol(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE);
219
- const aarColLen = aarCol.length;
220
- let index = -1;
221
- for (let i = 0; i < aarColLen; i++) {
222
- if (aarCol.get(i) === aar) {
223
- index = i;
224
- break;
225
- }
226
- }
227
- position = position === C.CATEGORIES.ALL ? C.COLUMNS_NAMES.AMINO_ACID_RESIDUE : position;
228
- sarDf.currentCell = sarDf.cell(index, position);
229
- }
230
-
231
- /**
232
- * Class initializer
233
- *
234
- * @param {DG.Grid} sourceGrid Working talbe grid.
235
- * @param {DG.TableView} currentView Working view.
236
- * @param {DG.DataFrame} currentDf Working table.
237
- * @param {StringDictionary} options SAR viewer options
238
- * @param {DG.Column} col Aligned sequences column.
239
- * @memberof Peptides
240
- */
241
- async init(table: DG.DataFrame) {
242
- if (this.isInitialized)
243
- return;
244
- this.isInitialized = true;
245
- //calculate initial stats
246
- const stats = new FilteringStatistics();
247
- const activityScaledCol = table.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
248
- stats.setData(activityScaledCol.getRawData() as Float32Array);
249
- stats.setMask(table.selection);
250
- table.temp[C.STATS] = stats;
251
-
252
- //set up views
253
- let currentView = grok.shell.v as DG.TableView ;
254
- if (currentView.dataFrame.tags['isPeptidesAnalysis'] !== 'true')
255
- currentView = grok.shell.addTableView(table);
256
- const sourceGrid = currentView.grid;
257
- sourceGrid.col(C.COLUMNS_NAMES.ACTIVITY_SCALED)!.name = table.temp[C.COLUMNS_NAMES.ACTIVITY_SCALED];
258
- sourceGrid.columns.setOrder([table.temp[C.COLUMNS_NAMES.ACTIVITY_SCALED]]);
259
-
260
- this.dataFrame.temp[C.EMBEDDING_STATUS] = false;
261
- function adjustCellSize(grid: DG.Grid) {
262
- const colNum = grid.columns.length;
263
- for (let i = 0; i < colNum; ++i) {
264
- const iCol = grid.columns.byIndex(i)!;
265
- iCol.width = isNaN(parseInt(iCol.name)) ? 50 : 40;
266
- }
267
- grid.props.rowHeight = 20;
268
- }
269
-
270
- for (let i = 0; i < sourceGrid.columns.length; i++) {
271
- const aarCol = sourceGrid.columns.byIndex(i);
272
- if (aarCol && aarCol.name && aarCol.column?.semType !== C.SEM_TYPES.AMINO_ACIDS &&
273
- aarCol.name !== this.dataFrame.temp[C.COLUMNS_NAMES.ACTIVITY_SCALED]
274
- )
275
- sourceGrid.columns.byIndex(i)!.visible = false;
276
- }
277
-
278
- const options = {scaling: table.tags['scaling']};
279
- await this.updateData(table.tags['scaling'], sourceGrid, false, 1, 2, false, false);
280
-
281
- const dockManager = currentView.dockManager;
282
-
283
- this.dataFrame.temp['sarViewer'] = this.sarViewer =
284
- await this.dataFrame.plot.fromType('peptide-sar-viewer', options) as SARViewer;
285
- this.sarViewer.helpUrl = this.helpUrl;
286
-
287
- this.dataFrame.temp['sarViewerVertical'] = this.sarViewerVertical =
288
- await this.dataFrame.plot.fromType('peptide-sar-viewer-vertical', options) as SARViewerVertical;
289
- this.sarViewerVertical.helpUrl = this.helpUrl;
290
-
291
- const sarViewersGroup: viewerTypes[] = [this.sarViewer, this.sarViewerVertical];
292
-
293
- const peptideSpaceViewerOptions = {method: 't-SNE', measure: 'Levenshtein', cyclesCount: 100};
294
- const peptideSpaceViewer =
295
- await this.dataFrame.plot.fromType('peptide-space-viewer', peptideSpaceViewerOptions) as PeptideSpaceViewer;
296
- dockManager.dock(peptideSpaceViewer, DG.DOCK_TYPE.RIGHT, null, 'Peptide Space Viewer');
297
-
298
- dockViewers(sarViewersGroup, DG.DOCK_TYPE.RIGHT, dockManager, DG.DOCK_TYPE.DOWN);
299
-
300
- sourceGrid.props.allowEdit = false;
301
- adjustCellSize(sourceGrid);
302
-
303
- // this._model._sarGrid.invalidate();
304
- // this._model._sarVGrid.invalidate();
305
- this._model.invalidateGrids();
306
- }
307
-
308
- invalidateSourceGrid() { this.sourceGrid.invalidate(); }
309
- }
310
-
311
- function dockViewers(
312
- viewerList: viewerTypes[], attachDirection: DG.DockType, dockManager: DG.DockManager,
313
- initialAttachDirection?: DG.DockType): DG.DockNode[] | null {
314
- const viewerListLength = viewerList.length;
315
- if (viewerListLength === 0)
316
- return null;
317
-
318
- let currentViewer = viewerList[0];
319
- const nodeList = [dockManager.dock(currentViewer, initialAttachDirection, null, currentViewer.name ?? '')];
320
- const ratio = 1 / viewerListLength;
321
-
322
- for (let i = 1; i < viewerListLength; i++) {
323
- currentViewer = viewerList[i];
324
- nodeList.push(dockManager.dock(currentViewer, attachDirection, nodeList[i - 1], currentViewer.name ?? '', ratio));
325
- }
326
- return nodeList;
327
- }
package/src/semantics.ts DELETED
@@ -1,5 +0,0 @@
1
- export const SEMTYPE = {
2
- ALIGNED: 'alignedSequence',
3
- };
4
-
5
-