@datagrok/bio 2.12.17 → 2.12.18
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 +9 -2
- package/dist/79.js.map +1 -1
- package/dist/package-test.js +5 -5
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +3 -3
- package/dist/package.js.map +1 -1
- package/package.json +3 -3
- package/src/package-test.ts +1 -1
- package/src/package.ts +23 -7
- package/src/tests/monomer-libraries-tests.ts +1 -4
- package/src/tests/renderers-monomer-placer-tests.ts +8 -7
- package/src/tests/renderers-test.ts +1 -1
- package/src/tests/scoring.ts +2 -2
- package/src/tests/substructure-filters-tests.ts +4 -2
- package/src/tests/to-atomic-level-tests.ts +1 -1
- package/src/tests/utils.ts +15 -0
- package/src/utils/cell-renderer.ts +39 -46
- package/src/utils/helm-to-molfile/converter/converter.ts +10 -5
- package/src/utils/helm-to-molfile/converter/monomer-wrapper.ts +9 -9
- package/src/utils/helm-to-molfile/converter/polymer.ts +10 -3
- package/src/utils/monomer-cell-renderer.ts +18 -8
- package/src/utils/monomer-lib/lib-manager.ts +56 -18
- package/src/utils/monomer-lib/library-file-manager/event-manager.ts +15 -9
- package/src/utils/monomer-lib/library-file-manager/file-manager.ts +78 -59
- package/src/utils/monomer-lib/library-file-manager/file-validator.ts +3 -1
- package/src/utils/monomer-lib/library-file-manager/ui.ts +52 -47
- package/src/utils/monomer-lib/monomer-lib.ts +78 -9
- package/src/utils/sequence-to-mol.ts +7 -7
- package/src/widgets/bio-substructure-filter.ts +2 -2
- package/webpack.config.js +1 -0
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "Aleksandr Tanas",
|
|
6
6
|
"email": "atanas@datagrok.ai"
|
|
7
7
|
},
|
|
8
|
-
"version": "2.12.
|
|
8
|
+
"version": "2.12.18",
|
|
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",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@biowasm/aioli": "^3.1.0",
|
|
37
|
-
"@datagrok-libraries/bio": "^5.41.
|
|
37
|
+
"@datagrok-libraries/bio": "^5.41.2",
|
|
38
38
|
"@datagrok-libraries/chem-meta": "^1.2.5",
|
|
39
39
|
"@datagrok-libraries/math": "^1.1.5",
|
|
40
40
|
"@datagrok-libraries/ml": "^6.6.5",
|
|
41
41
|
"@datagrok-libraries/tutorials": "^1.3.12",
|
|
42
|
-
"@datagrok-libraries/utils": "^4.2.
|
|
42
|
+
"@datagrok-libraries/utils": "^4.2.5",
|
|
43
43
|
"@webgpu/types": "^0.1.40",
|
|
44
44
|
"ajv": "^8.12.0",
|
|
45
45
|
"ajv-errors": "^3.0.0",
|
package/src/package-test.ts
CHANGED
|
@@ -23,7 +23,7 @@ import './tests/WebLogo-project-tests';
|
|
|
23
23
|
import './tests/WebLogo-layout-tests';
|
|
24
24
|
import './tests/checkInputColumn-tests';
|
|
25
25
|
import './tests/similarity-diversity-tests';
|
|
26
|
-
import './tests/substructure-filters-tests';
|
|
26
|
+
// import './tests/substructure-filters-tests';
|
|
27
27
|
import './tests/pepsea-tests';
|
|
28
28
|
import './tests/viewers';
|
|
29
29
|
import './tests/seq-handler-tests';
|
package/src/package.ts
CHANGED
|
@@ -86,8 +86,8 @@ export const _package = new BioPackage();
|
|
|
86
86
|
//name: getMonomerLibHelper
|
|
87
87
|
//description:
|
|
88
88
|
//output: object result
|
|
89
|
-
export function getMonomerLibHelper(): IMonomerLibHelper {
|
|
90
|
-
return MonomerLibManager.
|
|
89
|
+
export async function getMonomerLibHelper(): Promise<IMonomerLibHelper> {
|
|
90
|
+
return await MonomerLibManager.getInstance();
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
export let hydrophobPalette: SeqPaletteCustom | null = null;
|
|
@@ -104,12 +104,20 @@ export class SeqPaletteCustom implements SeqPalette {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
let monomerLib: IMonomerLib | null = null;
|
|
108
|
+
|
|
107
109
|
//tags: init
|
|
108
110
|
export async function initBio() {
|
|
109
|
-
|
|
111
|
+
const logPrefix = 'Bio: initBio()';
|
|
112
|
+
_package.logger.debug(`${logPrefix}, start`);
|
|
110
113
|
const module = await grok.functions.call('Chem:getRdKitModule');
|
|
114
|
+
const t1: number = window.performance.now();
|
|
111
115
|
await Promise.all([
|
|
112
|
-
(async () => {
|
|
116
|
+
(async () => {
|
|
117
|
+
const monomerLibManager = await MonomerLibManager.getInstance();
|
|
118
|
+
await monomerLibManager.loadLibraries();
|
|
119
|
+
monomerLib = monomerLibManager.getBioLib();
|
|
120
|
+
})(),
|
|
113
121
|
(async () => {
|
|
114
122
|
const pkgProps = await _package.getProperties();
|
|
115
123
|
const bioPkgProps = new BioPackageProperties(pkgProps);
|
|
@@ -117,9 +125,10 @@ export async function initBio() {
|
|
|
117
125
|
})(),
|
|
118
126
|
]).finally(() => {
|
|
119
127
|
_package.completeInit();
|
|
128
|
+
const t2: number = window.performance.now();
|
|
129
|
+
_package.logger.debug(`${logPrefix}, loading ET: ${t2 - t1} ms`);
|
|
120
130
|
});
|
|
121
131
|
|
|
122
|
-
const monomerLib = MonomerLibManager.instance.getBioLib();
|
|
123
132
|
const monomers: string[] = [];
|
|
124
133
|
const logPs: number[] = [];
|
|
125
134
|
|
|
@@ -159,10 +168,16 @@ export function sequenceTooltip(col: DG.Column): DG.Widget<any> {
|
|
|
159
168
|
return resWidget;
|
|
160
169
|
}
|
|
161
170
|
|
|
171
|
+
// Keep for backward compatibility
|
|
162
172
|
//name: getBioLib
|
|
163
173
|
//output: object monomerLib
|
|
164
174
|
export function getBioLib(): IMonomerLib {
|
|
165
|
-
return
|
|
175
|
+
return monomerLib!;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// For sync internal use, on initialized package
|
|
179
|
+
export function getMonomerLib(): IMonomerLib | null {
|
|
180
|
+
return monomerLib!;
|
|
166
181
|
}
|
|
167
182
|
|
|
168
183
|
//name: getSeqHandler
|
|
@@ -571,7 +586,8 @@ export async function sequenceSpaceTopMenu(table: DG.DataFrame, molecules: DG.Co
|
|
|
571
586
|
export async function toAtomicLevel(table: DG.DataFrame, seqCol: DG.Column, nonlinear: boolean): Promise<void> {
|
|
572
587
|
const pi = DG.TaskBarProgressIndicator.create('Converting to atomic level ...');
|
|
573
588
|
try {
|
|
574
|
-
await
|
|
589
|
+
const monomerLib = (await getMonomerLibHelper()).getBioLib();
|
|
590
|
+
await sequenceToMolfile(table, seqCol, nonlinear, monomerLib);
|
|
575
591
|
} finally {
|
|
576
592
|
pi.close();
|
|
577
593
|
}
|
|
@@ -8,8 +8,6 @@ import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/sr
|
|
|
8
8
|
import {
|
|
9
9
|
getUserLibSettings, setUserLibSettings, setUserLibSettingsForTests
|
|
10
10
|
} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
|
|
11
|
-
import {MonomerLibFileManager} from '../utils/monomer-lib/library-file-manager/file-manager';
|
|
12
|
-
import {MonomerLibFileEventManager} from '../utils/monomer-lib/library-file-manager/event-manager';
|
|
13
11
|
|
|
14
12
|
|
|
15
13
|
category('monomerLibraries', () => {
|
|
@@ -51,8 +49,7 @@ category('monomerLibraries', () => {
|
|
|
51
49
|
test('empty', async () => {
|
|
52
50
|
// exclude all monomer libraries for empty set
|
|
53
51
|
const libSettings = await getUserLibSettings();
|
|
54
|
-
const
|
|
55
|
-
const libFileManager = await MonomerLibFileManager.getInstance(libFileEventManager);
|
|
52
|
+
const libFileManager = await monomerLibHelper.getFileManager();
|
|
56
53
|
|
|
57
54
|
let libFnList = libFileManager.getValidLibraryPaths();
|
|
58
55
|
if (libFnList.length === 0)
|
|
@@ -8,8 +8,7 @@ import {category, test} from '@datagrok-libraries/utils/src/test';
|
|
|
8
8
|
import {MonomerPlacer} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
|
|
9
9
|
import {monomerToShort} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
10
10
|
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
11
|
-
|
|
12
|
-
import {MonomerLibManager} from '../utils/monomer-lib/lib-manager';
|
|
11
|
+
import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
13
12
|
|
|
14
13
|
import {_package} from '../package-test';
|
|
15
14
|
|
|
@@ -45,7 +44,7 @@ category('renderers: monomerPlacer', () => {
|
|
|
45
44
|
'id1,m1-M-m3-mon4-mon5-N-T-MON8-N9\n' +
|
|
46
45
|
'id2,m1-mon2-m3-mon4-mon5-Num--MON8-N9\n' +
|
|
47
46
|
'id3,\n' + // empty
|
|
48
|
-
'id4,mon1-M-mon3-mon4-mon5---MON8-N9\n',
|
|
47
|
+
'id4,mon1-M-mon3-mon4-mon5---MON8-N9\n', // [ 5, 38, 71, 104, 137, 170, 203, 236, 269, 295 ]
|
|
49
48
|
testList: [
|
|
50
49
|
{src: {row: 0, x: -1}, tgt: {pos: null}},
|
|
51
50
|
{src: {row: 1, x: 0}, tgt: {pos: null}},
|
|
@@ -59,7 +58,7 @@ category('renderers: monomerPlacer', () => {
|
|
|
59
58
|
{src: {row: 2, x: 20}, tgt: {pos: null}}, // empty value
|
|
60
59
|
{src: {row: 3, x: 170}, tgt: {pos: 4}},
|
|
61
60
|
{src: {row: 3, x: 200}, tgt: {pos: 5}},
|
|
62
|
-
{src: {row: 3, x:
|
|
61
|
+
{src: {row: 3, x: 297}, tgt: {pos: null}},
|
|
63
62
|
]
|
|
64
63
|
},
|
|
65
64
|
fastaMsa: {
|
|
@@ -88,6 +87,8 @@ id3,QHIRE--LT
|
|
|
88
87
|
|
|
89
88
|
for (const [testName, testData] of Object.entries(tests)) {
|
|
90
89
|
test(`getPosition-${testName}`, async () => {
|
|
90
|
+
const libHelper = await getMonomerLibHelper();
|
|
91
|
+
const monomerLib = libHelper.getBioLib();
|
|
91
92
|
const df: DG.DataFrame = DG.DataFrame.fromCsv(testData.csv);
|
|
92
93
|
await grok.data.detectSemanticTypes(df);
|
|
93
94
|
const seqCol: DG.Column = df.getCol('seq');
|
|
@@ -103,18 +104,18 @@ id3,QHIRE--LT
|
|
|
103
104
|
separatorWidth: sepWidth,
|
|
104
105
|
monomerToShort: monomerToShort,
|
|
105
106
|
monomerLengthLimit: monLength,
|
|
106
|
-
monomerLib: MonomerLibManager.instance.getBioLib(),
|
|
107
107
|
};
|
|
108
108
|
});
|
|
109
109
|
|
|
110
|
+
const width: number = 10000;
|
|
110
111
|
const testList = testData.testList;
|
|
111
112
|
// simulate rendering
|
|
112
113
|
for (let rowI: number = 0; rowI < seqCol.length; ++rowI)
|
|
113
|
-
colTemp.getCellMonomerLengths(rowI);
|
|
114
|
+
colTemp.getCellMonomerLengths(rowI, 10000);
|
|
114
115
|
|
|
115
116
|
const errorList: string[] = [];
|
|
116
117
|
for (const [test, _testI] of wu.enumerate(testList)) {
|
|
117
|
-
const res = {pos: colTemp.getPosition(test.src.row, test.src.x)};
|
|
118
|
+
const res = {pos: colTemp.getPosition(test.src.row, test.src.x, width)};
|
|
118
119
|
if (test.tgt.pos != res.pos) {
|
|
119
120
|
errorList.push(`Test src ${JSON.stringify(test.src)} expected tgt ${JSON.stringify(test.tgt)},` +
|
|
120
121
|
` but get ${JSON.stringify({res})}`);
|
|
@@ -56,7 +56,7 @@ category('renderers', () => {
|
|
|
56
56
|
|
|
57
57
|
test('scatterPlotTooltip', async () => {
|
|
58
58
|
await _testScatterPlotTooltip();
|
|
59
|
-
});
|
|
59
|
+
}, {skipReason: 'GROK-15679'});
|
|
60
60
|
|
|
61
61
|
async function _rendererMacromoleculeFasta() {
|
|
62
62
|
const csv: string = await grok.dapi.files.readAsText('System:AppData/Bio/samples/FASTA.csv');
|
package/src/tests/scoring.ts
CHANGED
|
@@ -4,9 +4,9 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
|
|
5
5
|
import {category, test, expectFloat, before, after} from '@datagrok-libraries/utils/src/test';
|
|
6
6
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
7
|
-
import {
|
|
7
|
+
import {IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
8
8
|
|
|
9
|
-
import {sequenceIdentityScoring, sequenceSimilarityScoring} from '../package';
|
|
9
|
+
import {getMonomerLibHelper, sequenceIdentityScoring, sequenceSimilarityScoring} from '../package';
|
|
10
10
|
import {
|
|
11
11
|
getUserLibSettings, setUserLibSettings, setUserLibSettingsForTests
|
|
12
12
|
} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
|
|
@@ -185,7 +185,8 @@ category('bio-substructure-filters', async () => {
|
|
|
185
185
|
dlg.close();
|
|
186
186
|
}
|
|
187
187
|
await filter.awaitRendered();
|
|
188
|
-
|
|
188
|
+
await delay(3000); //TODO: await for grid.onLookChanged
|
|
189
|
+
}, {skipReason: 'GROK-15678'});
|
|
189
190
|
|
|
190
191
|
// Generates unhandled exception accessing isFiltering before bioFilter created
|
|
191
192
|
test('helm-view', async () => {
|
|
@@ -308,7 +309,8 @@ category('bio-substructure-filters', async () => {
|
|
|
308
309
|
}
|
|
309
310
|
await Promise.all([f1.awaitRendered(), f2.awaitRendered()]);
|
|
310
311
|
await awaitGrid(view.grid);
|
|
311
|
-
|
|
312
|
+
await delay(3000); //TODO: await for grid.onLookChanged
|
|
313
|
+
}, {skipReason: 'GROK-15678'});
|
|
312
314
|
|
|
313
315
|
// two seq columns
|
|
314
316
|
|
|
@@ -7,7 +7,7 @@ import wu from 'wu';
|
|
|
7
7
|
|
|
8
8
|
import {before, after, category, test, expectArray, expect} from '@datagrok-libraries/utils/src/test';
|
|
9
9
|
import {_toAtomicLevel} from '@datagrok-libraries/bio/src/monomer-works/to-atomic-level';
|
|
10
|
-
import {IMonomerLib} from '@datagrok-libraries/bio/src/types
|
|
10
|
+
import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
|
|
11
11
|
import {ALPHABET, NOTATION, TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
12
12
|
import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
13
13
|
import {
|
package/src/tests/utils.ts
CHANGED
|
@@ -2,10 +2,12 @@ import * as DG from 'datagrok-api/dg';
|
|
|
2
2
|
import * as grok from 'datagrok-api/grok';
|
|
3
3
|
|
|
4
4
|
import {delay, expect, testEvent} from '@datagrok-libraries/utils/src/test';
|
|
5
|
+
import {asRenderer, IRenderer, isRenderer} from '@datagrok-libraries/bio/src/types/renderer';
|
|
5
6
|
|
|
6
7
|
import {startDockerContainer} from '../utils/docker';
|
|
7
8
|
|
|
8
9
|
import {_package} from '../package-test';
|
|
10
|
+
import {CellRendererBackBase, getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
9
11
|
|
|
10
12
|
export async function loadFileAsText(name: string): Promise<string> {
|
|
11
13
|
return await _package.files.readAsText(name);
|
|
@@ -38,4 +40,17 @@ export async function awaitGrid(grid: DG.Grid, timeout: number = 5000): Promise<
|
|
|
38
40
|
await delay(0);
|
|
39
41
|
await testEvent(grid.onAfterDrawContent, () => {},
|
|
40
42
|
() => { grid.invalidate(); }, timeout);
|
|
43
|
+
|
|
44
|
+
const colCount = grid.columns.length;
|
|
45
|
+
for (let colI = 0; colI < colCount; ++colI) {
|
|
46
|
+
const gridCol = grid.columns.byIndex(colI);
|
|
47
|
+
if (gridCol) {
|
|
48
|
+
const gridCell = grid.cell(gridCol.name, 0);
|
|
49
|
+
const [_gridCol, _tableCol, temp] =
|
|
50
|
+
getGridCellRendererBack<void, CellRendererBackBase<void>>(gridCell);
|
|
51
|
+
|
|
52
|
+
const renderer = asRenderer(temp.rendererBack);
|
|
53
|
+
if (renderer) await renderer.awaitRendered();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
41
56
|
}
|
|
@@ -3,7 +3,6 @@ import * as DG from 'datagrok-api/dg';
|
|
|
3
3
|
import * as ui from 'datagrok-api/ui';
|
|
4
4
|
|
|
5
5
|
import wu from 'wu';
|
|
6
|
-
import {Unsubscribable} from 'rxjs';
|
|
7
6
|
|
|
8
7
|
import {printLeftOrCentered, DrawStyle, TAGS as mmcrTAGS} from '@datagrok-libraries/bio/src/utils/cell-renderer';
|
|
9
8
|
import {MonomerPlacer} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
|
|
@@ -22,7 +21,7 @@ import {GapOriginals, SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-ha
|
|
|
22
21
|
import {ISeqSplitted, SeqSplittedBase} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
23
22
|
import {getSplitter} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
|
|
24
23
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
25
|
-
import {alphabetPolymerTypes, IMonomerLib} from '@datagrok-libraries/bio/src/types
|
|
24
|
+
import {alphabetPolymerTypes, IMonomerLib} from '@datagrok-libraries/bio/src/types';
|
|
26
25
|
import {getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
27
26
|
|
|
28
27
|
import {
|
|
@@ -31,14 +30,16 @@ import {
|
|
|
31
30
|
} from '../utils/cell-renderer-consts';
|
|
32
31
|
import * as C from './constants';
|
|
33
32
|
|
|
34
|
-
import {_package,
|
|
33
|
+
import {_package, getMonomerLib} from '../package';
|
|
35
34
|
|
|
36
35
|
type TempType = { [tagName: string]: any };
|
|
37
36
|
|
|
38
37
|
const undefinedColor = 'rgb(100,100,100)';
|
|
39
38
|
const monomerToShortFunction: MonomerToShortFunc = monomerToShort;
|
|
40
39
|
|
|
41
|
-
function getUpdatedWidth(
|
|
40
|
+
function getUpdatedWidth(
|
|
41
|
+
grid: DG.Grid | null | undefined, g: CanvasRenderingContext2D, x: number, w: number, dpr: number
|
|
42
|
+
): number {
|
|
42
43
|
return !!grid ? Math.max(Math.min(grid.canvas.width / dpr - x, w)) : Math.max(g.canvas.width / dpr - x, 0);
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -99,7 +100,7 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
99
100
|
// maxLengthWordsSum[posI] = maxLengthWordsSum[posI - 1] + maxLengthWords[posI];
|
|
100
101
|
// const maxIndex = maxLengthWords.length;
|
|
101
102
|
const argsX = e.offsetX - gridCell.gridColumn.left + (gridCell.gridColumn.left - gridCellBounds.x);
|
|
102
|
-
const left: number | null = seqColTemp.getPosition(gridCell.tableRowIndex!, argsX);
|
|
103
|
+
const left: number | null = seqColTemp.getPosition(gridCell.tableRowIndex!, argsX, gridCellBounds.width);
|
|
103
104
|
|
|
104
105
|
const seqCList: SeqSplittedBase = SeqHandler.forColumn(tableCol)
|
|
105
106
|
.getSplitted(gridCell.tableRowIndex!).canonicals;
|
|
@@ -113,8 +114,8 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
113
114
|
const alphabet = sh.alphabet ?? ALPHABET.UN;
|
|
114
115
|
const polymerType = alphabetPolymerTypes[alphabet as ALPHABET];
|
|
115
116
|
|
|
116
|
-
const lib: IMonomerLib =
|
|
117
|
-
return lib.getTooltip(polymerType, monomerSymbol);
|
|
117
|
+
const lib: IMonomerLib | null = getMonomerLib();
|
|
118
|
+
return lib ? lib.getTooltip(polymerType, monomerSymbol) : ui.divText('Monomer library is not available');
|
|
118
119
|
})();
|
|
119
120
|
}
|
|
120
121
|
tooltipElements.push(monomerDiv);
|
|
@@ -142,23 +143,17 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
142
143
|
_cellStyle: DG.GridCellStyle
|
|
143
144
|
): void {
|
|
144
145
|
const logPrefix: string = 'MacromoleculeSequenceCellRenderer.render()';
|
|
146
|
+
|
|
147
|
+
const dpr = window.devicePixelRatio;
|
|
148
|
+
const [gridCol, tableCol, _temp] =
|
|
149
|
+
getGridCellRendererBack<string, MonomerPlacer>(gridCell);
|
|
150
|
+
if (!tableCol) return;
|
|
151
|
+
const tableColTemp: TempType = tableCol.temp;
|
|
152
|
+
|
|
145
153
|
let gapLength = 0;
|
|
146
154
|
const msaGapLength = 8;
|
|
147
155
|
let maxLengthOfMonomer = 50; // in case of long monomer representation, do not limit max length
|
|
148
156
|
|
|
149
|
-
// TODO: Store temp data to GridColumn
|
|
150
|
-
// Now the renderer requires data frame table Column underlying GridColumn
|
|
151
|
-
let grid: DG.Grid | undefined = undefined;
|
|
152
|
-
try { grid = gridCell.grid; } catch (err: any) {
|
|
153
|
-
grid = undefined;
|
|
154
|
-
const [errMsg, errStack] = errInfo(err);
|
|
155
|
-
_package.logger.error(errMsg, undefined, errStack);
|
|
156
|
-
}
|
|
157
|
-
const tableCol: DG.Column = gridCell.cell.column;
|
|
158
|
-
if (!grid || !tableCol) return;
|
|
159
|
-
|
|
160
|
-
const tableColTemp: TempType = tableCol.temp;
|
|
161
|
-
|
|
162
157
|
// Cell renderer settings
|
|
163
158
|
const tempMonomerWidth: string | null = tableColTemp[tempTAGS.monomerWidth];
|
|
164
159
|
const monomerWidth: string = (tempMonomerWidth != null) ? tempMonomerWidth : 'short';
|
|
@@ -170,46 +165,41 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
170
165
|
(!isNaN(tagMaxMonomerLength) ? tagMaxMonomerLength : _package.properties?.MaxMonomerLength) ?? 4;
|
|
171
166
|
}
|
|
172
167
|
|
|
173
|
-
const [
|
|
168
|
+
const [_gc, _tc, temp] =
|
|
174
169
|
getGridCellRendererBack<string, MonomerPlacer>(gridCell);
|
|
175
|
-
let seqColTemp: MonomerPlacer = temp
|
|
170
|
+
let seqColTemp: MonomerPlacer = temp.rendererBack;
|
|
176
171
|
if (!seqColTemp) {
|
|
177
|
-
seqColTemp = new MonomerPlacer(gridCol, tableCol, _package.logger,
|
|
172
|
+
seqColTemp = temp.rendererBack = new MonomerPlacer(gridCol, tableCol, _package.logger,
|
|
178
173
|
() => {
|
|
179
174
|
const sh = SeqHandler.forColumn(tableCol);
|
|
180
175
|
return {
|
|
181
176
|
seqHandler: sh,
|
|
182
177
|
monomerCharWidth: 7, separatorWidth: !sh.isMsa() ? gapLength : msaGapLength,
|
|
183
178
|
monomerToShort: monomerToShortFunction, monomerLengthLimit: maxLengthOfMonomer,
|
|
184
|
-
monomerLib: getBioLib()
|
|
185
179
|
};
|
|
186
180
|
});
|
|
187
181
|
}
|
|
188
182
|
|
|
189
|
-
if (tableCol.tags[mmcrTags.RendererSettingsChanged] === rendererSettingsChangedState.true) {
|
|
190
|
-
gapLength = tableColTemp[mmcrTemps.gapLength] as number ?? gapLength;
|
|
191
|
-
// this event means that the mm renderer settings have changed, particularly monomer representation and max width.
|
|
192
|
-
seqColTemp.setMonomerLengthLimit(maxLengthOfMonomer);
|
|
193
|
-
seqColTemp.setSeparatorWidth(seqColTemp.isMsa() ? msaGapLength : gapLength);
|
|
194
|
-
tableCol.setTag(mmcrTags.RendererSettingsChanged, rendererSettingsChangedState.false);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const [maxLengthWords, maxLengthWordsSum]: [number[], number[]] =
|
|
198
|
-
seqColTemp.getCellMonomerLengths(gridCell.tableRowIndex!);
|
|
199
|
-
const _maxIndex = maxLengthWords.length;
|
|
200
|
-
|
|
201
|
-
// Store updated seqColTemp to the col temp
|
|
202
|
-
if (seqColTemp.updated) temp['rendererBack'] = seqColTemp;
|
|
203
|
-
|
|
204
183
|
g.save();
|
|
205
184
|
try {
|
|
206
|
-
|
|
207
|
-
|
|
185
|
+
if (tableCol.tags[mmcrTags.RendererSettingsChanged] === rendererSettingsChangedState.true) {
|
|
186
|
+
gapLength = tableColTemp[mmcrTemps.gapLength] as number ?? gapLength;
|
|
187
|
+
// this event means that the mm renderer settings have changed,
|
|
188
|
+
// particularly monomer representation and max width.
|
|
189
|
+
seqColTemp.setMonomerLengthLimit(maxLengthOfMonomer);
|
|
190
|
+
seqColTemp.setSeparatorWidth(seqColTemp.isMsa() ? msaGapLength : gapLength);
|
|
191
|
+
tableCol.setTag(mmcrTags.RendererSettingsChanged, rendererSettingsChangedState.false);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const [maxLengthWords, maxLengthWordsSum]: [number[], number[]] =
|
|
195
|
+
seqColTemp.getCellMonomerLengths(gridCell.tableRowIndex!, w);
|
|
196
|
+
const _maxIndex = maxLengthWords.length;
|
|
197
|
+
|
|
208
198
|
const value: any = gridCell.cell.value;
|
|
209
199
|
const rowIdx = gridCell.cell.rowIndex;
|
|
210
200
|
const paletteType = tableCol.getTag(bioTAGS.alphabet);
|
|
211
201
|
const minDistanceRenderer = 50;
|
|
212
|
-
w = getUpdatedWidth(grid, g, x, w, dpr);
|
|
202
|
+
w = getUpdatedWidth(gridCol?.grid, g, x, w, dpr);
|
|
213
203
|
g.beginPath();
|
|
214
204
|
g.rect(x + this.padding, y + this.padding, w - this.padding - 1, h - this.padding * 2);
|
|
215
205
|
g.clip();
|
|
@@ -223,7 +213,8 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
223
213
|
const palette = getPaletteByType(paletteType);
|
|
224
214
|
|
|
225
215
|
const separator = tableCol.getTag(bioTAGS.separator) ?? '';
|
|
226
|
-
const
|
|
216
|
+
const minMonWidth = seqColTemp.props.separatorWidth + 1 * seqColTemp.props.monomerCharWidth;
|
|
217
|
+
const splitLimit = w / minMonWidth;
|
|
227
218
|
const sh = SeqHandler.forColumn(tableCol);
|
|
228
219
|
|
|
229
220
|
const tempReferenceSequence: string | null = tableColTemp[tempTAGS.referenceSequence];
|
|
@@ -247,7 +238,8 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
247
238
|
if (aligned && aligned.includes('MSA') && units == NOTATION.SEPARATOR)
|
|
248
239
|
drawStyle = DrawStyle.MSA;
|
|
249
240
|
|
|
250
|
-
|
|
241
|
+
const visibleSeqLength = Math.min(subParts.length, splitLimit);
|
|
242
|
+
for (let posIdx: number = 0; posIdx < visibleSeqLength; ++posIdx) {
|
|
251
243
|
const amino: string = subParts.getOriginal(posIdx);
|
|
252
244
|
color = palette.get(amino);
|
|
253
245
|
g.fillStyle = undefinedColor;
|
|
@@ -259,8 +251,9 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
259
251
|
if (minDistanceRenderer > w) break;
|
|
260
252
|
}
|
|
261
253
|
} catch (err: any) {
|
|
262
|
-
const errMsg
|
|
263
|
-
|
|
254
|
+
const [errMsg, errStack] = errInfo(err);
|
|
255
|
+
seqColTemp.logger.error(errMsg, undefined, errStack);
|
|
256
|
+
seqColTemp.errors.push(err);
|
|
264
257
|
//throw err; // Do not throw to prevent disabling renderer
|
|
265
258
|
} finally {
|
|
266
259
|
g.restore();
|
|
@@ -5,10 +5,13 @@ import * as OCL from 'openchemlib/full';
|
|
|
5
5
|
|
|
6
6
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
7
7
|
import {RDModule, RDMol} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
8
|
-
import {
|
|
8
|
+
import {IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
|
|
9
|
+
|
|
9
10
|
import {Polymer} from './polymer';
|
|
10
11
|
import {GlobalMonomerPositionHandler} from './position-handler';
|
|
11
12
|
|
|
13
|
+
import {_package, getMonomerLibHelper} from '../../../package';
|
|
14
|
+
|
|
12
15
|
export class HelmToMolfileConverter {
|
|
13
16
|
constructor(private helmColumn: DG.Column<string>, private df: DG.DataFrame) {
|
|
14
17
|
this.helmColumn = helmColumn;
|
|
@@ -54,7 +57,7 @@ export class HelmToMolfileConverter {
|
|
|
54
57
|
async convertToRdKitBeautifiedMolfileColumn(chiralityEngine?: boolean): Promise<DG.Column<string>> {
|
|
55
58
|
const molfilesV3K = (await this.convertToMolfileV3KColumn()).toList();
|
|
56
59
|
const rdKitModule: RDModule = await grok.functions.call('Chem:getRdKitModule');
|
|
57
|
-
const beautifiedMols = molfilesV3K.map((item) =>{
|
|
60
|
+
const beautifiedMols = molfilesV3K.map((item) => {
|
|
58
61
|
if (item === '')
|
|
59
62
|
return null;
|
|
60
63
|
const mol = rdKitModule.get_mol(item);
|
|
@@ -81,6 +84,7 @@ export class HelmToMolfileConverter {
|
|
|
81
84
|
private async convertToMolfileV3KColumn(): Promise<DG.Column<string>> {
|
|
82
85
|
const polymerGraphColumn: DG.Column<string> = await this.getPolymerGraphColumn();
|
|
83
86
|
const rdKitModule = await grok.functions.call('Chem:getRdKitModule');
|
|
87
|
+
const monomerLib: IMonomerLib = (await getMonomerLibHelper()).getBioLib();
|
|
84
88
|
const molfileList = polymerGraphColumn.toList().map(
|
|
85
89
|
(pseudoMolfile: string, idx: number) => {
|
|
86
90
|
const helm = this.helmColumn.get(idx);
|
|
@@ -88,7 +92,7 @@ export class HelmToMolfileConverter {
|
|
|
88
92
|
return '';
|
|
89
93
|
let result = '';
|
|
90
94
|
try {
|
|
91
|
-
result = this.getPolymerMolfile(helm, pseudoMolfile, rdKitModule);
|
|
95
|
+
result = this.getPolymerMolfile(helm, pseudoMolfile, rdKitModule, monomerLib);
|
|
92
96
|
} catch (err: any) {
|
|
93
97
|
const [errMsg, errStack] = errInfo(err);
|
|
94
98
|
_package.logger.error(errMsg, undefined, errStack);
|
|
@@ -110,10 +114,11 @@ export class HelmToMolfileConverter {
|
|
|
110
114
|
private getPolymerMolfile(
|
|
111
115
|
helm: string,
|
|
112
116
|
polymerGraph: string,
|
|
113
|
-
rdKitModule: RDModule
|
|
117
|
+
rdKitModule: RDModule,
|
|
118
|
+
monomerLib: IMonomerLib
|
|
114
119
|
): string {
|
|
115
120
|
const globalPositionHandler = new GlobalMonomerPositionHandler(polymerGraph);
|
|
116
|
-
const polymer = new Polymer(helm, rdKitModule);
|
|
121
|
+
const polymer = new Polymer(helm, rdKitModule, monomerLib);
|
|
117
122
|
globalPositionHandler.monomerSymbols.forEach((monomerSymbol: string, monomerIdx: number) => {
|
|
118
123
|
const shift = globalPositionHandler.getMonomerShifts(monomerIdx);
|
|
119
124
|
polymer.addMonomer(monomerSymbol, monomerIdx, shift);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {Monomer} from '@datagrok-libraries/bio/src/types';
|
|
1
|
+
import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
|
|
2
2
|
import {HELM_RGROUP_FIELDS} from '@datagrok-libraries/bio/src/utils/const';
|
|
3
3
|
import {RDModule, RDMol} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
4
|
-
import {
|
|
4
|
+
import {MolfileHandler} from '@datagrok-libraries/chem-meta/src/parsing-utils/molfile-handler';
|
|
5
|
+
|
|
5
6
|
import {Helm} from './helm';
|
|
6
7
|
import {MolfileWrapper} from './mol-wrapper';
|
|
7
8
|
import {MolfileWrapperFactory} from './mol-wrapper-factory';
|
|
8
|
-
import {MolfileHandler} from '@datagrok-libraries/chem-meta/src/parsing-utils/molfile-handler';
|
|
9
9
|
|
|
10
10
|
export class MonomerWrapper {
|
|
11
11
|
private molfileWrapper: MolfileWrapper;
|
|
@@ -15,8 +15,9 @@ export class MonomerWrapper {
|
|
|
15
15
|
private monomerSymbol: string,
|
|
16
16
|
private monomerIdx: number,
|
|
17
17
|
private helm: Helm,
|
|
18
|
-
shift: {x: number, y: number},
|
|
19
|
-
rdKitModule: RDModule
|
|
18
|
+
shift: { x: number, y: number },
|
|
19
|
+
rdKitModule: RDModule,
|
|
20
|
+
private readonly monomerLib: IMonomerLib
|
|
20
21
|
) {
|
|
21
22
|
const libraryMonomerObject = this.getLibraryMonomerObject();
|
|
22
23
|
|
|
@@ -37,7 +38,7 @@ export class MonomerWrapper {
|
|
|
37
38
|
private convertMolfileToV3KFormat(molfileV2K: string, monomerSymbol: string, rdKitModule: RDModule): string {
|
|
38
39
|
let mol: RDMol | null = null;
|
|
39
40
|
try {
|
|
40
|
-
mol = rdKitModule.get_mol(molfileV2K, JSON.stringify({mergeQueryHs: true}))
|
|
41
|
+
mol = rdKitModule.get_mol(molfileV2K, JSON.stringify({mergeQueryHs: true}));
|
|
41
42
|
if (mol)
|
|
42
43
|
return mol.get_v3Kmolblock();
|
|
43
44
|
else
|
|
@@ -49,8 +50,7 @@ export class MonomerWrapper {
|
|
|
49
50
|
|
|
50
51
|
private getLibraryMonomerObject(): Monomer {
|
|
51
52
|
const polymerType = this.helm.getPolymerTypeByMonomerIdx(this.monomerIdx);
|
|
52
|
-
const
|
|
53
|
-
const monomer = monomerLib.getMonomer(polymerType, this.monomerSymbol);
|
|
53
|
+
const monomer = this.monomerLib.getMonomer(polymerType, this.monomerSymbol);
|
|
54
54
|
if (!monomer)
|
|
55
55
|
throw new Error(`Monomer ${this.monomerSymbol} is not found in the library`);
|
|
56
56
|
return monomer;
|
|
@@ -72,7 +72,7 @@ export class MonomerWrapper {
|
|
|
72
72
|
return result;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
private shiftCoordinates(shift: {x: number, y: number}): void {
|
|
75
|
+
private shiftCoordinates(shift: { x: number, y: number }): void {
|
|
76
76
|
this.molfileWrapper.shiftCoordinates(shift);
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
2
2
|
import {V3K_CONST} from '@datagrok-libraries/chem-meta/src/formats/molfile-const';
|
|
3
|
+
import {IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
|
|
4
|
+
|
|
3
5
|
import {Helm} from './helm';
|
|
4
6
|
import {MonomerWrapper} from './monomer-wrapper';
|
|
5
7
|
|
|
6
8
|
export class Polymer {
|
|
7
|
-
constructor(
|
|
9
|
+
constructor(
|
|
10
|
+
helmString: string,
|
|
11
|
+
private readonly rdKitModule: RDModule,
|
|
12
|
+
private readonly monomerLib: IMonomerLib
|
|
13
|
+
) {
|
|
8
14
|
this.helm = new Helm(helmString);
|
|
9
15
|
}
|
|
10
16
|
|
|
@@ -14,9 +20,10 @@ export class Polymer {
|
|
|
14
20
|
addMonomer(
|
|
15
21
|
monomerSymbol: string,
|
|
16
22
|
monomerIdx: number,
|
|
17
|
-
shift: {x: number, y: number},
|
|
23
|
+
shift: { x: number, y: number },
|
|
18
24
|
): void {
|
|
19
|
-
const monomerWrapper = new MonomerWrapper(
|
|
25
|
+
const monomerWrapper = new MonomerWrapper(
|
|
26
|
+
monomerSymbol, monomerIdx, this.helm, shift, this.rdKitModule, this.monomerLib);
|
|
20
27
|
|
|
21
28
|
this.monomerWrappers.push(monomerWrapper);
|
|
22
29
|
}
|
|
@@ -5,9 +5,10 @@ import * as ui from 'datagrok-api/ui';
|
|
|
5
5
|
import {ALPHABET, getPaletteByType, monomerToShort} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
6
6
|
import {TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
7
7
|
import {MonomerWorks} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
|
|
8
|
+
import {PolymerType} from '@datagrok-libraries/bio/src/types';
|
|
8
9
|
|
|
9
|
-
import {getMonomerLibHelper} from '../package';
|
|
10
10
|
import * as C from './constants';
|
|
11
|
+
import {getMonomerLib} from '../package';
|
|
11
12
|
|
|
12
13
|
const Tags = new class {
|
|
13
14
|
tooltipHandlerTemp = 'tooltip-handler.Monomer';
|
|
@@ -29,20 +30,29 @@ export class MonomerTooltipHandler {
|
|
|
29
30
|
!gridCell.tableColumn || !gridCell.isTableCell
|
|
30
31
|
) return false;
|
|
31
32
|
|
|
32
|
-
const alphabet = gridCell.tableColumn.getTag(bioTAGS.alphabet);
|
|
33
|
+
const alphabet = gridCell.tableColumn.getTag(bioTAGS.alphabet) as ALPHABET;
|
|
33
34
|
const monomerName = gridCell.cell.value;
|
|
34
|
-
const
|
|
35
|
-
const
|
|
35
|
+
const canvasClientRect = gridCell.grid.canvas.getBoundingClientRect();
|
|
36
|
+
const x1 = gridCell.bounds.right + canvasClientRect.left - 4;
|
|
37
|
+
const y1 = gridCell.bounds.bottom + canvasClientRect.top - 4;
|
|
38
|
+
|
|
39
|
+
const monomerLib = getMonomerLib();
|
|
40
|
+
if (!monomerLib) {
|
|
41
|
+
ui.tooltip.show(ui.divText('Monomer library is not available.'), x1, y1);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const mw = new MonomerWorks(monomerLib);
|
|
46
|
+
const polymerType: PolymerType = (alphabet === ALPHABET.DNA || alphabet === ALPHABET.RNA) ? 'RNA' :
|
|
36
47
|
alphabet === ALPHABET.PT ? 'PEPTIDE' : 'PEPTIDE';
|
|
48
|
+
// const biotype: HelmType = [ALPHABET.RNA, ALPHABET.DNA].includes(alphabet) ? HelmTypes.NUCLEOTIDE :
|
|
49
|
+
// [ALPHABET.PT].includes(alphabet) ? HelmTypes.AA : HelmTypes.AA;
|
|
37
50
|
|
|
38
|
-
const monomerMol: string | null = mw.getCappedRotatedMonomer(
|
|
51
|
+
const monomerMol: string | null = mw.getCappedRotatedMonomer(polymerType, monomerName);
|
|
39
52
|
const nameDiv = ui.div(monomerName);
|
|
40
53
|
const molDiv = !monomerMol ? null :
|
|
41
54
|
grok.chem.svgMol(monomerMol, undefined, undefined, svgMolOptions);
|
|
42
55
|
|
|
43
|
-
const canvasClientRect = gridCell.grid.canvas.getBoundingClientRect();
|
|
44
|
-
const x1 = gridCell.bounds.right + canvasClientRect.left - 4;
|
|
45
|
-
const y1 = gridCell.bounds.bottom + canvasClientRect.top - 4;
|
|
46
56
|
ui.tooltip.show(ui.divV([nameDiv, ...(molDiv ? [molDiv] : [])]), x1, y1);
|
|
47
57
|
|
|
48
58
|
return true; // To prevent default tooltip behaviour
|