@datagrok/bio 2.15.7 → 2.15.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/284.js +1 -1
- package/dist/284.js.map +1 -1
- package/dist/package-test.js +3 -3
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +3 -3
- package/dist/package.js.map +1 -1
- package/files/monomer-libraries/sample-lib-Aca-colored.json +2 -2
- package/package.json +8 -8
- package/src/analysis/sequence-activity-cliffs.ts +10 -5
- package/src/analysis/sequence-similarity-viewer.ts +1 -1
- package/src/package.ts +1 -1
- package/src/tests/WebLogo-positions-test.ts +1 -1
- package/src/tests/splitters-test.ts +23 -6
- package/src/utils/cell-renderer-custom.ts +10 -2
- package/src/utils/cell-renderer.ts +102 -128
- package/src/utils/monomer-cell-renderer-base.ts +30 -0
- package/src/utils/monomer-cell-renderer.ts +73 -54
- package/src/utils/monomer-lib/lib-manager.ts +1 -1
- package/src/utils/monomer-lib/monomer-colors.ts +33 -30
- package/src/utils/monomer-lib/monomer-lib-base.ts +151 -13
- package/src/utils/monomer-lib/monomer-lib.ts +7 -50
- package/src/utils/monomer-lib/monomer-manager/monomer-manager.ts +94 -5
- package/src/utils/monomer-lib/web-editor-monomer-dummy.ts +11 -4
- package/src/utils/monomer-lib/web-editor-monomer-of-library.ts +5 -37
- package/src/viewers/web-logo-viewer.ts +40 -27
- package/src/widgets/composition-analysis-widget.ts +12 -17
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "Aleksandr Tanas",
|
|
6
6
|
"email": "atanas@datagrok.ai"
|
|
7
7
|
},
|
|
8
|
-
"version": "2.15.
|
|
8
|
+
"version": "2.15.9",
|
|
9
9
|
"description": "Bioinformatics support (import/export of sequences, conversion, visualization, analysis). [See more](https://github.com/datagrok-ai/public/blob/master/packages/Bio/README.md) for details.",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@biowasm/aioli": "^3.1.0",
|
|
40
|
-
"@datagrok-libraries/bio": "^5.44.
|
|
40
|
+
"@datagrok-libraries/bio": "^5.44.5",
|
|
41
41
|
"@datagrok-libraries/chem-meta": "^1.2.7",
|
|
42
|
-
"@datagrok-libraries/math": "^1.2.
|
|
43
|
-
"@datagrok-libraries/ml": "^6.7.
|
|
44
|
-
"@datagrok-libraries/tutorials": "^1.4.
|
|
45
|
-
"@datagrok-libraries/utils": "^4.3.
|
|
42
|
+
"@datagrok-libraries/math": "^1.2.1",
|
|
43
|
+
"@datagrok-libraries/ml": "^6.7.3",
|
|
44
|
+
"@datagrok-libraries/tutorials": "^1.4.3",
|
|
45
|
+
"@datagrok-libraries/utils": "^4.3.6",
|
|
46
46
|
"@webgpu/types": "^0.1.40",
|
|
47
47
|
"ajv": "^8.12.0",
|
|
48
48
|
"ajv-errors": "^3.0.0",
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@datagrok-libraries/helm-web-editor": "^1.1.11",
|
|
62
62
|
"@datagrok-libraries/js-draw-lite": "^0.0.8",
|
|
63
|
-
"@datagrok/chem": "^1.12.
|
|
63
|
+
"@datagrok/chem": "^1.12.3",
|
|
64
64
|
"@datagrok/dendrogram": "^1.2.33",
|
|
65
|
-
"@datagrok/helm": "^2.5.
|
|
65
|
+
"@datagrok/helm": "^2.5.3",
|
|
66
66
|
"@types/node": "^17.0.24",
|
|
67
67
|
"@types/wu": "latest",
|
|
68
68
|
"@typescript-eslint/eslint-plugin": "latest",
|
|
@@ -12,6 +12,9 @@ import {invalidateMols, MONOMERIC_COL_TAGS} from '../substructure-search/substru
|
|
|
12
12
|
import {TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
13
13
|
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
14
14
|
import {ISeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
15
|
+
import {HelmType} from '@datagrok-libraries/bio/src/helm/types';
|
|
16
|
+
|
|
17
|
+
import {getMonomerLib} from '../package';
|
|
15
18
|
|
|
16
19
|
export async function getDistances(col: DG.Column, seq: string): Promise<Array<number>> {
|
|
17
20
|
const stringArray = col.toList();
|
|
@@ -106,9 +109,10 @@ export function createPropPanelElement(params: ITooltipAndPanelParams): HTMLDivE
|
|
|
106
109
|
|
|
107
110
|
const molDifferences: { [key: number]: HTMLCanvasElement } = {};
|
|
108
111
|
const sh = SeqHandler.forColumn(params.seqCol);
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
+
const biotype = sh.defaultBiotype;
|
|
113
|
+
const subParts1 = sh.getSplitted(params.points[0]);
|
|
114
|
+
const subParts2 = sh.getSplitted(params.points[1]);
|
|
115
|
+
const canvas = createDifferenceCanvas(subParts1, subParts2, biotype, molDifferences);
|
|
112
116
|
propPanel.append(ui.div(canvas, {style: {width: '300px', overflow: 'scroll'}}));
|
|
113
117
|
|
|
114
118
|
propPanel.append(createDifferencesWithPositions(molDifferences));
|
|
@@ -129,15 +133,16 @@ function createPropPanelField(name: string, value: number): HTMLDivElement {
|
|
|
129
133
|
export function createDifferenceCanvas(
|
|
130
134
|
subParts1: ISeqSplitted,
|
|
131
135
|
subParts2: ISeqSplitted,
|
|
132
|
-
|
|
136
|
+
biotype: HelmType,
|
|
133
137
|
molDifferences: { [key: number]: HTMLCanvasElement }): HTMLCanvasElement {
|
|
134
138
|
const canvas = document.createElement('canvas');
|
|
135
139
|
const context = canvas.getContext('2d');
|
|
136
140
|
canvas.height = 30;
|
|
141
|
+
const monomerLib = getMonomerLib();
|
|
137
142
|
drawMoleculeDifferenceOnCanvas(context!, 0, 0, 0, 30,
|
|
138
143
|
wu.count(0).take(subParts1.length).map((posIdx) => subParts1.getCanonical(posIdx)).toArray(),
|
|
139
144
|
wu.count(0).take(subParts2.length).map((posIdx) => subParts2.getCanonical(posIdx)).toArray(),
|
|
140
|
-
|
|
145
|
+
biotype, monomerLib, true, molDifferences);
|
|
141
146
|
return canvas;
|
|
142
147
|
}
|
|
143
148
|
|
|
@@ -130,7 +130,7 @@ export class SequenceSimilarityViewer extends SequenceSearchBaseViewer {
|
|
|
130
130
|
const subParts1 = molColSh.getSplitted(this.targetMoleculeIdx);
|
|
131
131
|
const subParts2 = resSh.getSplitted(resDf.currentRowIdx);
|
|
132
132
|
const alignment = alignSequencePair(subParts1, subParts2);
|
|
133
|
-
const canvas = createDifferenceCanvas(alignment.seq1Splitted, alignment.seq2Splitted, resSh.
|
|
133
|
+
const canvas = createDifferenceCanvas(alignment.seq1Splitted, alignment.seq2Splitted, resSh.defaultBiotype, molDifferences);
|
|
134
134
|
propPanel.append(ui.div(canvas, {style: {width: '300px', overflow: 'scroll'}}));
|
|
135
135
|
if (subParts1.length !== subParts2.length) {
|
|
136
136
|
propPanel.append(ui.divV([
|
package/src/package.ts
CHANGED
|
@@ -364,7 +364,7 @@ export function macroMolColumnPropertyPanel(molColumn: DG.Column): DG.Widget {
|
|
|
364
364
|
//input: semantic_value sequence { semType: Macromolecule }
|
|
365
365
|
//output: widget result
|
|
366
366
|
export function compositionAnalysisWidget(sequence: DG.SemanticValue): DG.Widget {
|
|
367
|
-
return getCompositionAnalysisWidget(sequence);
|
|
367
|
+
return getCompositionAnalysisWidget(sequence, monomerLib!);
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
//name: MacromoleculeDifferenceCellRenderer
|
|
@@ -36,7 +36,7 @@ ATC-G-TTGC--
|
|
|
36
36
|
const wlViewer: WebLogoViewer = (await df.plot.fromType('WebLogo')) as WebLogoViewer;
|
|
37
37
|
await testEvent(wlViewer.onLayoutCalculated, () => {}, () => {
|
|
38
38
|
tv.dockManager.dock(wlViewer.root, DG.DOCK_TYPE.DOWN);
|
|
39
|
-
}, 500);
|
|
39
|
+
}, 500, 'Layout calculate timeout');
|
|
40
40
|
const positions: PI[] = wlViewer['positions'];
|
|
41
41
|
|
|
42
42
|
const resAllDf1: PI[] = [
|
|
@@ -4,20 +4,21 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
|
|
5
5
|
import wu from 'wu';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
after, before, category, test, expect, expectArray
|
|
9
|
-
} from '@datagrok-libraries/utils/src/test';
|
|
7
|
+
import {after, before, category, test, expect, expectArray} from '@datagrok-libraries/utils/src/test';
|
|
10
8
|
import {TAGS as bioTAGS, splitterAsFasta} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
9
|
+
import {splitterAsHelm} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
|
|
10
|
+
import {ISeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
11
|
+
import {IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
12
|
+
import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
|
|
13
|
+
import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
11
14
|
|
|
12
15
|
import {splitToMonomersUI} from '../utils/split-to-monomers';
|
|
13
16
|
import {awaitGrid} from './utils';
|
|
14
17
|
import * as C from '../utils/constants';
|
|
15
18
|
import {getHelmMonomers} from '../package';
|
|
16
19
|
|
|
17
|
-
import {splitterAsHelm} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
|
|
18
|
-
import {ISeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
19
|
-
|
|
20
20
|
import {_package} from '../package-test';
|
|
21
|
+
import {getUserLibSettings, setUserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
|
|
21
22
|
|
|
22
23
|
category('splitters', async () => {
|
|
23
24
|
before(async () => {
|
|
@@ -85,7 +86,23 @@ category('splitters', async () => {
|
|
|
85
86
|
test('testHelm1', async () => { await _testHelmSplitter(data.testHelm1[0], data.testHelm1[1]); });
|
|
86
87
|
test('testHelm2', async () => { await _testHelmSplitter(data.testHelm2[0], data.testHelm2[1]); });
|
|
87
88
|
test('testHelm3', async () => { await _testHelmSplitter(data.testHelm3[0], data.testHelm3[1]); });
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
category('splitters', () => {
|
|
92
|
+
let monomerLibHelper: IMonomerLibHelper;
|
|
93
|
+
let userLibSettings: UserLibSettings;
|
|
88
94
|
|
|
95
|
+
before(async () => {
|
|
96
|
+
monomerLibHelper = await getMonomerLibHelper();
|
|
97
|
+
userLibSettings = await getUserLibSettings();
|
|
98
|
+
|
|
99
|
+
await monomerLibHelper.loadMonomerLibForTests();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
after(async () => {
|
|
103
|
+
await setUserLibSettings(userLibSettings);
|
|
104
|
+
await monomerLibHelper.loadMonomerLib(true);
|
|
105
|
+
});
|
|
89
106
|
|
|
90
107
|
test('splitToMonomers', async () => {
|
|
91
108
|
const df: DG.DataFrame = await grok.dapi.files.readCsv('System:AppData/Bio/samples/MSA.csv');
|
|
@@ -5,6 +5,7 @@ import * as ui from 'datagrok-api/ui';
|
|
|
5
5
|
import {getGridCellColTemp, CellRendererBackBase} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
6
6
|
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
7
7
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
8
|
+
import {GridCell} from 'datagrok-api/dg';
|
|
8
9
|
|
|
9
10
|
export class MacromoleculeCustomCellRenderer extends DG.GridCellRenderer {
|
|
10
11
|
get name(): string { return 'sequence'; }
|
|
@@ -24,9 +25,16 @@ export class MacromoleculeCustomCellRenderer extends DG.GridCellRenderer {
|
|
|
24
25
|
return back;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
override
|
|
28
|
+
override onMouseEnter(gridCell: GridCell, e: MouseEvent) {
|
|
28
29
|
const back = this.getRendererBack(gridCell);
|
|
29
|
-
back.
|
|
30
|
+
back.onMouseEnter(gridCell, e);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override onMouseLeave(gridCell: DG.GridCell, e: MouseEvent) {
|
|
34
|
+
// TODO: We get gridCell from another column here, so we can not get back object from the column rendered.
|
|
35
|
+
ui.tooltip.hide();
|
|
36
|
+
// const back = this.getRendererBack(gridCell);
|
|
37
|
+
// back.onMouseLeave(gridCell, e);
|
|
30
38
|
}
|
|
31
39
|
|
|
32
40
|
override onMouseMove(gridCell: DG.GridCell, e: MouseEvent) {
|
|
@@ -7,34 +7,31 @@ import * as ui from 'datagrok-api/ui';
|
|
|
7
7
|
|
|
8
8
|
import wu from 'wu';
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import {HelmType} from '@datagrok-libraries/bio/src/helm/types';
|
|
11
|
+
import {printLeftOrCentered, TAGS as mmcrTAGS} from '@datagrok-libraries/bio/src/utils/cell-renderer';
|
|
12
|
+
import {getUpdatedWidth, MonomerPlacer, undefinedColor} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
|
|
12
13
|
import {
|
|
13
|
-
getPaletteByType,
|
|
14
14
|
monomerToShort,
|
|
15
15
|
MonomerToShortFunc,
|
|
16
16
|
NOTATION,
|
|
17
|
-
SplitterFunc,
|
|
18
17
|
TAGS as bioTAGS,
|
|
19
18
|
ALPHABET,
|
|
20
19
|
} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
21
|
-
import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
|
|
22
|
-
import {UnknownSeqPalettes} from '@datagrok-libraries/bio/src/unknown';
|
|
23
20
|
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
24
|
-
import {ISeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
25
21
|
import {getSplitter} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
|
|
26
|
-
import {
|
|
27
|
-
import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
|
|
22
|
+
import {IMonomerLib, IMonomerLibBase} from '@datagrok-libraries/bio/src/types';
|
|
28
23
|
import {GapOriginals} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
29
24
|
import {ISeqMonomer} from '@datagrok-libraries/bio/src/helm/types';
|
|
30
25
|
import {execMonomerHoverLinks} from '@datagrok-libraries/bio/src/monomer-works/monomer-hover';
|
|
31
|
-
import {getGridCellColTemp} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
26
|
+
import {CellRendererBackBase, getGridCellColTemp} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
32
27
|
import {HelmTypes} from '@datagrok-libraries/bio/src/helm/consts';
|
|
33
28
|
import {MmcrTemps, rendererSettingsChangedState, tempTAGS} from '@datagrok-libraries/bio/src/utils/cell-renderer-consts';
|
|
29
|
+
import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
34
30
|
import * as C from './constants';
|
|
35
31
|
|
|
36
|
-
import {_package
|
|
37
|
-
import {
|
|
32
|
+
import {_package} from '../package';
|
|
33
|
+
import {CellRendererWithMonomerLibBackBase} from './monomer-cell-renderer-base';
|
|
34
|
+
import {timeout} from 'rxjs/operators';
|
|
38
35
|
|
|
39
36
|
type TempType = { [tagName: string]: any };
|
|
40
37
|
|
|
@@ -78,54 +75,9 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
78
75
|
}
|
|
79
76
|
|
|
80
77
|
override onMouseMove(gridCell: DG.GridCell, e: MouseEvent): void {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
// return;
|
|
85
|
-
|
|
86
|
-
const [_gridCol, tableCol, temp] =
|
|
87
|
-
getGridCellColTemp<string, MonomerPlacer>(gridCell);
|
|
88
|
-
const seqColTemp: MonomerPlacer = temp.rendererBack;
|
|
89
|
-
if (!seqColTemp) return; // Can do nothing without precalculated data
|
|
90
|
-
|
|
91
|
-
const gridCellBounds: DG.Rect = gridCell.bounds;
|
|
92
|
-
// const value: any = gridCell.cell.value;
|
|
93
|
-
//
|
|
94
|
-
// const maxLengthWords: number[] = seqColTemp.getCellMonomerLengths(gridCell.tableRowIndex!);
|
|
95
|
-
// const maxLengthWordsSum: number[] = new Array<number>(maxLengthWords.length).fill(0);
|
|
96
|
-
// for (let posI: number = 1; posI < maxLengthWords.length; posI++)
|
|
97
|
-
// maxLengthWordsSum[posI] = maxLengthWordsSum[posI - 1] + maxLengthWords[posI];
|
|
98
|
-
// const maxIndex = maxLengthWords.length;
|
|
99
|
-
const argsX = e.offsetX - gridCell.gridColumn.left + (gridCell.gridColumn.left - gridCellBounds.x);
|
|
100
|
-
const left: number | null = seqColTemp.getPosition(gridCell.tableRowIndex!, argsX, gridCellBounds.width);
|
|
101
|
-
|
|
102
|
-
const seqSS = SeqHandler.forColumn(tableCol)
|
|
103
|
-
.getSplitted(gridCell.tableRowIndex!);
|
|
104
|
-
if (left !== null && left < seqSS.length) {
|
|
105
|
-
const sh = SeqHandler.forColumn(tableCol);
|
|
106
|
-
const alphabet = sh.alphabet ?? ALPHABET.UN;
|
|
107
|
-
const seqMonomer = {
|
|
108
|
-
position: left,
|
|
109
|
-
biotype: alphabet === ALPHABET.RNA || alphabet === ALPHABET.DNA ? HelmTypes.NUCLEOTIDE : HelmTypes.AA,
|
|
110
|
-
symbol: seqSS.getCanonical(left),
|
|
111
|
-
} as ISeqMonomer;
|
|
112
|
-
const tooltipElements: HTMLElement[] = [];
|
|
113
|
-
let monomerDiv = seqColTemp._monomerStructureMap[seqMonomer.symbol];
|
|
114
|
-
if (!monomerDiv || true) {
|
|
115
|
-
monomerDiv = seqColTemp._monomerStructureMap[seqMonomer.symbol] = (() => {
|
|
116
|
-
const lib: IMonomerLib | null = getMonomerLib();
|
|
117
|
-
return lib ? lib.getTooltip(seqMonomer.biotype, seqMonomer.symbol) : ui.divText('Monomer library is not available');
|
|
118
|
-
})();
|
|
119
|
-
}
|
|
120
|
-
tooltipElements.push(monomerDiv);
|
|
121
|
-
ui.tooltip.show(ui.divV(tooltipElements), e.x + 16, e.y + 16);
|
|
122
|
-
|
|
123
|
-
execMonomerHoverLinks(gridCell, seqMonomer);
|
|
124
|
-
} else {
|
|
125
|
-
//
|
|
126
|
-
ui.tooltip.hide();
|
|
127
|
-
execMonomerHoverLinks(gridCell, null);
|
|
128
|
-
}
|
|
78
|
+
const [gridCol, tableCol, temp] = getGridCellColTemp<string, MonomerPlacer>(gridCell);
|
|
79
|
+
const back = temp.rendererBack;
|
|
80
|
+
back.onMouseMove(gridCell, e);
|
|
129
81
|
}
|
|
130
82
|
|
|
131
83
|
override onMouseLeave(gridCell: DG.GridCell, e: MouseEvent) {
|
|
@@ -150,10 +102,11 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
150
102
|
): void {
|
|
151
103
|
const logPrefix: string = 'MacromoleculeSequenceCellRenderer.render()';
|
|
152
104
|
|
|
153
|
-
const [gridCol, tableCol,
|
|
105
|
+
const [gridCol, tableCol, temp] =
|
|
154
106
|
getGridCellColTemp<string, MonomerPlacer>(gridCell);
|
|
155
107
|
if (!tableCol) return;
|
|
156
108
|
const tableColTemp: TempType = tableCol.temp;
|
|
109
|
+
const sh = SeqHandler.forColumn(tableCol);
|
|
157
110
|
|
|
158
111
|
let gapLength = 0;
|
|
159
112
|
const msaGapLength = 8;
|
|
@@ -169,37 +122,65 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
169
122
|
maxLengthOfMonomer = !isNaN(v) && v ? v : 50;
|
|
170
123
|
}
|
|
171
124
|
|
|
172
|
-
const [_gc, _tc, temp] =
|
|
173
|
-
getGridCellColTemp<string, MonomerPlacer>(gridCell);
|
|
174
125
|
let seqColTemp: MonomerPlacer = temp.rendererBack;
|
|
175
126
|
if (!seqColTemp) {
|
|
176
127
|
seqColTemp = temp.rendererBack = new MonomerPlacer(gridCol, tableCol, _package.logger, maxLengthOfMonomer,
|
|
177
128
|
() => {
|
|
178
|
-
const sh = SeqHandler.forColumn(tableCol);
|
|
179
129
|
return {
|
|
180
|
-
seqHandler: sh,
|
|
181
130
|
monomerCharWidth: 7, separatorWidth: !sh.isMsa() ? gapLength : msaGapLength,
|
|
182
131
|
monomerToShort: monomerToShortFunction,
|
|
183
132
|
};
|
|
184
133
|
});
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (
|
|
188
|
-
tableCol.temp[MmcrTemps.rendererSettingsChanged] === rendererSettingsChangedState.true ||
|
|
189
|
-
seqColTemp.monomerLengthLimit != maxLengthOfMonomer
|
|
190
|
-
) {
|
|
191
|
-
gapLength = tableColTemp[MmcrTemps.gapLength] as number ?? gapLength;
|
|
192
|
-
// this event means that the mm renderer settings have changed,
|
|
193
|
-
// particularly monomer representation and max width.
|
|
194
|
-
seqColTemp.setMonomerLengthLimit(maxLengthOfMonomer);
|
|
195
|
-
seqColTemp.setSeparatorWidth(seqColTemp.isMsa() ? msaGapLength : gapLength);
|
|
196
|
-
tableCol.temp[MmcrTemps.rendererSettingsChanged] = rendererSettingsChangedState.false;
|
|
134
|
+
tableCol.temp[MmcrTemps.rendererSettingsChanged] === rendererSettingsChangedState.true;
|
|
197
135
|
}
|
|
198
136
|
|
|
199
137
|
seqColTemp.render(g, x, y, w, h, gridCell, _cellStyle);
|
|
200
138
|
}
|
|
201
139
|
}
|
|
202
140
|
|
|
141
|
+
export class MacromoleculeDifferenceCellRendererBack extends CellRendererWithMonomerLibBackBase {
|
|
142
|
+
constructor(
|
|
143
|
+
gridCol: DG.GridColumn | null,
|
|
144
|
+
tableCol: DG.Column<string>,
|
|
145
|
+
) {
|
|
146
|
+
super(gridCol, tableCol);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
render(g: CanvasRenderingContext2D,
|
|
150
|
+
x: number, y: number, w: number, h: number, gridCell: DG.GridCell, cellStyle: DG.GridCellStyle
|
|
151
|
+
): void {
|
|
152
|
+
const dpr = window.devicePixelRatio;
|
|
153
|
+
const grid = gridCell.grid;
|
|
154
|
+
const cell = gridCell.cell;
|
|
155
|
+
const s: string = cell.value ?? '';
|
|
156
|
+
const separator = this.tableCol.tags[bioTAGS.separator];
|
|
157
|
+
const units: string = this.tableCol.meta.units!;
|
|
158
|
+
w = getUpdatedWidth(grid, g, x, w, dpr);
|
|
159
|
+
//TODO: can this be replaced/merged with splitSequence?
|
|
160
|
+
const [s1, s2] = s.split('#');
|
|
161
|
+
const splitter = getSplitter(units, separator);
|
|
162
|
+
const s1SS = splitter(s1);
|
|
163
|
+
const s2SS = splitter(s2);
|
|
164
|
+
const subParts1 = wu.count(0).take(s1SS.length).map((posIdx) => s1SS.getCanonical(posIdx)).toArray();
|
|
165
|
+
const subParts2 = wu.count(0).take(s2SS.length).map((posIdx) => s2SS.getCanonical(posIdx)).toArray();
|
|
166
|
+
const alphabet = this.tableCol.getTag(bioTAGS.alphabet);
|
|
167
|
+
const biotype = alphabet === ALPHABET.RNA || alphabet === ALPHABET.DNA ? HelmTypes.NUCLEOTIDE : HelmTypes.AA;
|
|
168
|
+
drawMoleculeDifferenceOnCanvas(g, x, y, w, h, subParts1, subParts2, biotype, this.monomerLib, undefined, undefined);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async awaitRendered(timeout: number = 10000, reason: string = `${timeout} timeout`): Promise<void> {
|
|
172
|
+
return Promise.resolve();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
static getOrCreate(gridCell: DG.GridCell): MacromoleculeDifferenceCellRendererBack {
|
|
176
|
+
const [gridCol, tableCol, temp] =
|
|
177
|
+
getGridCellColTemp<string, MacromoleculeDifferenceCellRendererBack>(gridCell);
|
|
178
|
+
|
|
179
|
+
let res: MacromoleculeDifferenceCellRendererBack = temp.rendererBack;
|
|
180
|
+
if (!res) res = temp.rendererBack = new MacromoleculeDifferenceCellRendererBack(gridCol, tableCol);
|
|
181
|
+
return res;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
203
184
|
|
|
204
185
|
export class MacromoleculeDifferenceCellRenderer extends DG.GridCellRenderer {
|
|
205
186
|
get name(): string { return 'MacromoleculeDifferenceCR'; }
|
|
@@ -222,25 +203,11 @@ export class MacromoleculeDifferenceCellRenderer extends DG.GridCellRenderer {
|
|
|
222
203
|
* @param {DG.GridCellStyle} _cellStyle Cell style.
|
|
223
204
|
* @memberof AlignedSequenceDifferenceCellRenderer
|
|
224
205
|
*/
|
|
225
|
-
render(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
const cell = gridCell.cell;
|
|
231
|
-
const tableCol = gridCell.tableColumn as DG.Column<string>;
|
|
232
|
-
const s: string = cell.value ?? '';
|
|
233
|
-
const separator = tableCol.tags[bioTAGS.separator];
|
|
234
|
-
const units: string = tableCol.meta.units!;
|
|
235
|
-
w = getUpdatedWidth(grid, g, x, w, dpr);
|
|
236
|
-
//TODO: can this be replaced/merged with splitSequence?
|
|
237
|
-
const [s1, s2] = s.split('#');
|
|
238
|
-
const splitter = getSplitter(units, separator);
|
|
239
|
-
const s1SS = splitter(s1);
|
|
240
|
-
const s2SS = splitter(s2);
|
|
241
|
-
const subParts1 = wu.count(0).take(s1SS.length).map((posIdx) => s1SS.getCanonical(posIdx)).toArray();
|
|
242
|
-
const subParts2 = wu.count(0).take(s2SS.length).map((posIdx) => s2SS.getCanonical(posIdx)).toArray();
|
|
243
|
-
drawMoleculeDifferenceOnCanvas(g, x, y, w, h, subParts1, subParts2, units);
|
|
206
|
+
render(g: CanvasRenderingContext2D,
|
|
207
|
+
x: number, y: number, w: number, h: number, gridCell: DG.GridCell, _cellStyle: DG.GridCellStyle
|
|
208
|
+
): void {
|
|
209
|
+
const back = MacromoleculeDifferenceCellRendererBack.getOrCreate(gridCell);
|
|
210
|
+
back.render(g, x, y, w, h, gridCell, _cellStyle);
|
|
244
211
|
}
|
|
245
212
|
}
|
|
246
213
|
|
|
@@ -252,7 +219,8 @@ export function drawMoleculeDifferenceOnCanvas(
|
|
|
252
219
|
h: number,
|
|
253
220
|
subParts1: string[],
|
|
254
221
|
subParts2: string[],
|
|
255
|
-
|
|
222
|
+
biotype: HelmType,
|
|
223
|
+
monomerLib: IMonomerLibBase | null,
|
|
256
224
|
fullStringLength?: boolean,
|
|
257
225
|
molDifferences?: { [key: number]: HTMLCanvasElement },
|
|
258
226
|
): void {
|
|
@@ -273,39 +241,45 @@ export function drawMoleculeDifferenceOnCanvas(
|
|
|
273
241
|
const updatedY = Math.max(y, y + (h - 28) / 2);
|
|
274
242
|
|
|
275
243
|
g.save();
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
244
|
+
try {
|
|
245
|
+
g.beginPath();
|
|
246
|
+
g.rect(x, y, fullStringLength ? textWidth + subParts1.length * 4 : w, h);
|
|
247
|
+
g.clip();
|
|
248
|
+
g.font = '12px monospace';
|
|
249
|
+
g.textBaseline = 'top';
|
|
250
|
+
|
|
251
|
+
const vShift = 7;
|
|
252
|
+
for (let i = 0; i < subParts1.length; i++) {
|
|
253
|
+
const amino1 = subParts1[i];
|
|
254
|
+
const amino2 = subParts2[i];
|
|
255
|
+
|
|
256
|
+
let color1 = undefinedColor;
|
|
257
|
+
if (monomerLib) {
|
|
258
|
+
color1 = monomerLib.getMonomerTextColor(biotype, amino1);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (amino1 != amino2) {
|
|
262
|
+
let color2 = undefinedColor;
|
|
263
|
+
if (monomerLib) {
|
|
264
|
+
color2 = monomerLib.getMonomerTextColor(biotype, amino2);
|
|
265
|
+
}
|
|
266
|
+
const subX0 = printLeftOrCentered(g, amino1, updatedX, updatedY - vShift, w, h,
|
|
267
|
+
{color: color1, pivot: 0, left: true});
|
|
268
|
+
const subX1 = printLeftOrCentered(g, amino2, updatedX, updatedY + vShift, w, h,
|
|
269
|
+
{color: color2, pivot: 0, left: true});
|
|
270
|
+
updatedX = Math.max(subX1, subX0);
|
|
271
|
+
if (molDifferences)
|
|
272
|
+
molDifferences[i] = createDifferenceCanvas(amino1, amino2, color1, color2, updatedY, vShift, h);
|
|
273
|
+
} else {
|
|
274
|
+
//
|
|
275
|
+
updatedX = printLeftOrCentered(g, amino1, updatedX, updatedY, w, h,
|
|
276
|
+
{color: color1, pivot: 0, left: true, transparencyRate: 0.5});
|
|
277
|
+
}
|
|
278
|
+
updatedX += 4;
|
|
305
279
|
}
|
|
306
|
-
|
|
280
|
+
} finally {
|
|
281
|
+
g.restore();
|
|
307
282
|
}
|
|
308
|
-
g.restore();
|
|
309
283
|
}
|
|
310
284
|
|
|
311
285
|
interface IComparedSequences {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as DG from 'datagrok-api/dg';
|
|
3
|
+
import * as ui from 'datagrok-api/ui';
|
|
4
|
+
|
|
5
|
+
import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
6
|
+
import {CellRendererBackBase} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
7
|
+
import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types/index';
|
|
8
|
+
|
|
9
|
+
import {_package} from '../package';
|
|
10
|
+
|
|
11
|
+
export abstract class CellRendererWithMonomerLibBackBase extends CellRendererBackBase<string> {
|
|
12
|
+
protected monomerLib: IMonomerLibBase | null = null;
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
gridCol: DG.GridColumn | null,
|
|
16
|
+
tableCol: DG.Column<string>,
|
|
17
|
+
) {
|
|
18
|
+
super(gridCol, tableCol, _package.logger);
|
|
19
|
+
|
|
20
|
+
getMonomerLibHelper().then((libHelper) => {
|
|
21
|
+
this.monomerLib = libHelper.getMonomerLib();
|
|
22
|
+
this.dirty = true;
|
|
23
|
+
this.gridCol?.grid?.invalidate();
|
|
24
|
+
this.subs.push(this.monomerLib.onChanged.subscribe(() => {
|
|
25
|
+
this.dirty = true;
|
|
26
|
+
this.gridCol?.grid?.invalidate();
|
|
27
|
+
}));
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|