@datagrok/bio 1.7.24 → 1.7.25
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/detectors.js +6 -3
- package/dist/package-test.js +162 -191
- package/dist/package.js +104 -152
- package/package.json +7 -3
- package/{setup-unlink-clean → setup-unlink-clean.sh} +0 -0
- package/{setup → setup.sh} +1 -1
- package/src/__jest__/remote.test.ts +2 -2
- package/src/__jest__/test-node.ts +3 -2
- package/src/package-test.ts +0 -1
- package/src/package.ts +11 -22
- package/src/tests/WebLogo-positions-test.ts +43 -21
- package/src/tests/detectors-test.ts +21 -18
- package/src/tests/renderers-test.ts +6 -2
- package/src/utils/cell-renderer.ts +59 -117
- package/src/utils/convert.ts +12 -2
- package/{test-Bio-4f0c8bae6479-367602e1.html → test-Bio-4f0c8bae6479-17115d45.html} +4 -4
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "Leonid Stolbov",
|
|
6
6
|
"email": "lstolbov@datagrok.ai"
|
|
7
7
|
},
|
|
8
|
-
"version": "1.7.
|
|
8
|
+
"version": "1.7.25",
|
|
9
9
|
"description": "Bio is a [package](https://datagrok.ai/help/develop/develop#packages) for the [Datagrok](https://datagrok.ai) platform",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@biowasm/aioli": ">=2.4.0",
|
|
17
|
-
"@datagrok-libraries/bio": "^3.0.
|
|
17
|
+
"@datagrok-libraries/bio": "^3.0.4",
|
|
18
18
|
"@datagrok-libraries/ml": "^3.0.3",
|
|
19
19
|
"@datagrok-libraries/utils": "^1.5.4",
|
|
20
20
|
"cash-dom": "latest",
|
|
@@ -36,7 +36,11 @@
|
|
|
36
36
|
"puppeteer": "^13.7.0",
|
|
37
37
|
"ts-jest": "^27.0.0",
|
|
38
38
|
"webpack": "latest",
|
|
39
|
-
"webpack-cli": "^4.10.0"
|
|
39
|
+
"webpack-cli": "^4.10.0",
|
|
40
|
+
"@types/js-yaml": "^4.0.5",
|
|
41
|
+
"js-yaml": "^4.1.0",
|
|
42
|
+
"@types/node-fetch": "^2.6.2",
|
|
43
|
+
"node-fetch": "^2.6.7"
|
|
40
44
|
},
|
|
41
45
|
"scripts": {
|
|
42
46
|
"link-api": "npm link datagrok-api",
|
|
File without changes
|
package/{setup → setup.sh}
RENAMED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as utils from './test-node';
|
|
6
6
|
import puppeteer from 'puppeteer';
|
|
7
7
|
|
|
8
|
-
const P_START_TIMEOUT: number =
|
|
8
|
+
const P_START_TIMEOUT: number = 3600000;
|
|
9
9
|
let browser: puppeteer.Browser;
|
|
10
10
|
let page: puppeteer.Page;
|
|
11
11
|
|
|
@@ -65,4 +65,4 @@ it('TEST', async () => {
|
|
|
65
65
|
console.log(r.passReport);
|
|
66
66
|
// @ts-ignore
|
|
67
67
|
expect(r.failed).checkOutput(false, r.failReport);
|
|
68
|
-
},
|
|
68
|
+
}, 3600000);
|
|
@@ -68,6 +68,7 @@ export async function getBrowserPage(puppeteer: any): Promise<{ browser: any, pa
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
const page = await browser.newPage();
|
|
71
|
+
await page.setDefaultNavigationTimeout(0);
|
|
71
72
|
await page.goto(`${url}/oauth/`);
|
|
72
73
|
await page.setCookie({name: 'auth', value: token});
|
|
73
74
|
await page.evaluate((token: any) => {
|
|
@@ -75,8 +76,8 @@ export async function getBrowserPage(puppeteer: any): Promise<{ browser: any, pa
|
|
|
75
76
|
}, token);
|
|
76
77
|
await page.goto(url);
|
|
77
78
|
try {
|
|
78
|
-
await page.waitForSelector('.grok-preloader');
|
|
79
|
-
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout:
|
|
79
|
+
await page.waitForSelector('.grok-preloader', { timeout: 1800000 });
|
|
80
|
+
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout: 3600000});
|
|
80
81
|
} catch (error) {
|
|
81
82
|
throw error;
|
|
82
83
|
}
|
package/src/package-test.ts
CHANGED
|
@@ -22,7 +22,6 @@ export {tests};
|
|
|
22
22
|
//input: string category {optional: true}
|
|
23
23
|
//input: string test {optional: true}
|
|
24
24
|
//output: dataframe result
|
|
25
|
-
//top-menu: Tools | Dev | JS API Tests
|
|
26
25
|
export async function test(category: string, test: string): Promise<DG.DataFrame> {
|
|
27
26
|
const data = await runTests({category, test});
|
|
28
27
|
return DG.DataFrame.fromObjects(data)!;
|
package/src/package.ts
CHANGED
|
@@ -20,38 +20,27 @@ import {createJsonMonomerLibFromSdf, encodeMonomers, getMolfilesFromSeq, HELM_CO
|
|
|
20
20
|
import {getMacroMol} from './utils/atomic-works';
|
|
21
21
|
import {MacromoleculeSequenceCellRenderer} from './utils/cell-renderer';
|
|
22
22
|
import {convert} from './utils/convert';
|
|
23
|
-
import {lru} from './utils/cell-renderer';
|
|
24
23
|
import {representationsWidget} from './widgets/representations';
|
|
25
24
|
import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
|
|
26
25
|
import {FastaFileHandler} from '@datagrok-libraries/bio/src/utils/fasta-handler';
|
|
27
26
|
import {removeEmptyStringRows} from '@datagrok-libraries/utils/src/dataframe-utils'
|
|
28
27
|
|
|
29
28
|
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return new Promise((resolve, reject) => {
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
dojo.ready(function() { resolve(null); });
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
//name: Lru
|
|
45
|
-
//output: object lruCache
|
|
46
|
-
export function Lru() {
|
|
47
|
-
return lru;
|
|
29
|
+
//name: fastaSequenceCellRenderer
|
|
30
|
+
//tags: cellRenderer
|
|
31
|
+
//meta.cellType: Sequence
|
|
32
|
+
//meta.columnTags: units=fasta
|
|
33
|
+
//output: grid_cell_renderer result
|
|
34
|
+
export function fastaSequenceCellRenderer(): MacromoleculeSequenceCellRenderer {
|
|
35
|
+
return new MacromoleculeSequenceCellRenderer();
|
|
48
36
|
}
|
|
49
37
|
|
|
50
|
-
//name:
|
|
38
|
+
//name: separatorSequenceCellRenderer
|
|
51
39
|
//tags: cellRenderer
|
|
52
|
-
//meta.cellType:
|
|
40
|
+
//meta.cellType: Sequence
|
|
41
|
+
//meta.columnTags: units=separator
|
|
53
42
|
//output: grid_cell_renderer result
|
|
54
|
-
export function
|
|
43
|
+
export function separatorSequenceCellRenderer(): MacromoleculeSequenceCellRenderer {
|
|
55
44
|
return new MacromoleculeSequenceCellRenderer();
|
|
56
45
|
}
|
|
57
46
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
2
1
|
import {after, before, category, test, expect, expectObject} from '@datagrok-libraries/utils/src/test';
|
|
3
2
|
|
|
4
3
|
import * as grok from 'datagrok-api/grok';
|
|
5
4
|
import * as ui from 'datagrok-api/ui';
|
|
6
5
|
import * as DG from 'datagrok-api/dg';
|
|
7
6
|
import {PositionInfo, PositionMonomerInfo, WebLogo} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
7
|
+
import {Column} from 'datagrok-api/dg';
|
|
8
|
+
|
|
8
9
|
category('WebLogo-positions', () => {
|
|
9
10
|
let tvList: DG.TableView[];
|
|
10
11
|
let dfList: DG.DataFrame[];
|
|
@@ -18,8 +19,6 @@ category('WebLogo-positions', () => {
|
|
|
18
19
|
-TC-GCTTGC--`;
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
const resShrinkEmptyTailDf1: PositionInfo[] = [];
|
|
22
|
-
|
|
23
22
|
before(async () => {
|
|
24
23
|
tvList = [];
|
|
25
24
|
dfList = [];
|
|
@@ -35,6 +34,9 @@ category('WebLogo-positions', () => {
|
|
|
35
34
|
const df: DG.DataFrame = DG.DataFrame.fromCsv(csvDf1);
|
|
36
35
|
const tv: DG.TableView = grok.shell.addTableView(df);
|
|
37
36
|
|
|
37
|
+
df.getCol('seq').semType = 'Macromolecule';
|
|
38
|
+
df.getCol('seq').setTag('units', 'fasta:SEQ.MSA:DNA');
|
|
39
|
+
|
|
38
40
|
const wlViewer: WebLogo = await df.plot.fromType('WebLogo') as unknown as WebLogo;
|
|
39
41
|
tv.dockManager.dock(wlViewer.root, DG.DOCK_TYPE.DOWN);
|
|
40
42
|
|
|
@@ -57,9 +59,9 @@ category('WebLogo-positions', () => {
|
|
|
57
59
|
new PositionInfo('11', {'-': new PositionMonomerInfo(5)}),
|
|
58
60
|
new PositionInfo('12', {'-': new PositionMonomerInfo(5)})
|
|
59
61
|
];
|
|
60
|
-
|
|
61
|
-
expect(positions.length,resAllDf1.length);
|
|
62
|
-
|
|
62
|
+
|
|
63
|
+
expect(positions.length, resAllDf1.length);
|
|
64
|
+
|
|
63
65
|
for (let i = 0; i < positions.length; i++) {
|
|
64
66
|
expect(positions[i].name, resAllDf1[i].name);
|
|
65
67
|
for (const key in positions[i].freq) {
|
|
@@ -68,11 +70,27 @@ category('WebLogo-positions', () => {
|
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
});
|
|
71
|
-
test('positions with shrinkEmptyTail option', async () => {
|
|
72
|
-
|
|
73
|
+
test('positions with shrinkEmptyTail option true (filterd)', async () => {
|
|
74
|
+
let csvDf2 = `seq
|
|
75
|
+
-TC-G-TTGC--
|
|
76
|
+
-TC-GCTTGC--
|
|
77
|
+
-T--C-GT-
|
|
78
|
+
-T--C-GT-
|
|
79
|
+
-T--C-GT-
|
|
80
|
+
-T--CCGT-`;
|
|
81
|
+
const df: DG.DataFrame = DG.DataFrame.fromCsv(csvDf2);
|
|
73
82
|
const tv: DG.TableView = grok.shell.addTableView(df);
|
|
74
83
|
|
|
84
|
+
df.getCol('seq').semType = 'Macromolecule';
|
|
85
|
+
df.getCol('seq').setTag('units', 'fasta:SEQ.MSA:DNA');
|
|
86
|
+
|
|
87
|
+
let seq: Column = df.getCol('seq');
|
|
88
|
+
df.filter.init((i) => {
|
|
89
|
+
return i > 2;
|
|
90
|
+
});
|
|
91
|
+
df.filter.fireChanged();
|
|
75
92
|
const wlViewer: WebLogo = await df.plot.fromType('WebLogo', {'shrinkEmptyTail': true}) as unknown as WebLogo;
|
|
93
|
+
|
|
76
94
|
tv.dockManager.dock(wlViewer.root, DG.DOCK_TYPE.DOWN);
|
|
77
95
|
|
|
78
96
|
tvList.push(tv);
|
|
@@ -81,19 +99,19 @@ category('WebLogo-positions', () => {
|
|
|
81
99
|
const positions: PositionInfo[] = wlViewer['positions'];
|
|
82
100
|
|
|
83
101
|
const resAllDf1: PositionInfo[] = [
|
|
84
|
-
new PositionInfo('1', {'
|
|
85
|
-
new PositionInfo('2', {'T': new PositionMonomerInfo(
|
|
86
|
-
new PositionInfo('3', {'
|
|
87
|
-
new PositionInfo('4', {'-': new PositionMonomerInfo(
|
|
88
|
-
new PositionInfo('5', {'
|
|
89
|
-
new PositionInfo('6', {'-': new PositionMonomerInfo(
|
|
90
|
-
new PositionInfo('7', {'
|
|
91
|
-
new PositionInfo('8', {'T': new PositionMonomerInfo(
|
|
92
|
-
new PositionInfo('9', {'
|
|
93
|
-
new PositionInfo('10', {'C': new PositionMonomerInfo(5)})
|
|
102
|
+
new PositionInfo('1', {'-': new PositionMonomerInfo(3)}),
|
|
103
|
+
new PositionInfo('2', {'T': new PositionMonomerInfo(3)}),
|
|
104
|
+
new PositionInfo('3', {'-': new PositionMonomerInfo(3)}),
|
|
105
|
+
new PositionInfo('4', {'-': new PositionMonomerInfo(3)}),
|
|
106
|
+
new PositionInfo('5', {'C': new PositionMonomerInfo(3)}),
|
|
107
|
+
new PositionInfo('6', {'-': new PositionMonomerInfo(2), 'C': new PositionMonomerInfo(1)}),
|
|
108
|
+
new PositionInfo('7', {'G': new PositionMonomerInfo(3)}),
|
|
109
|
+
new PositionInfo('8', {'T': new PositionMonomerInfo(3)}),
|
|
110
|
+
new PositionInfo('9', {'-': new PositionMonomerInfo(3)}),
|
|
94
111
|
];
|
|
95
112
|
|
|
96
|
-
|
|
113
|
+
expect(positions.length, resAllDf1.length);
|
|
114
|
+
|
|
97
115
|
for (let i = 0; i < positions.length; i++) {
|
|
98
116
|
expect(positions[i].name, resAllDf1[i].name);
|
|
99
117
|
for (const key in positions[i].freq) {
|
|
@@ -107,7 +125,10 @@ category('WebLogo-positions', () => {
|
|
|
107
125
|
const df: DG.DataFrame = DG.DataFrame.fromCsv(csvDf1);
|
|
108
126
|
const tv: DG.TableView = grok.shell.addTableView(df);
|
|
109
127
|
|
|
110
|
-
|
|
128
|
+
df.getCol('seq').semType = 'Macromolecule';
|
|
129
|
+
df.getCol('seq').setTag('units', 'fasta:SEQ.MSA:DNA');
|
|
130
|
+
|
|
131
|
+
const wlViewer: WebLogo = await df.plot.fromType('WebLogo', {'skipEmptyPositions': true}) as unknown as WebLogo;
|
|
111
132
|
tv.dockManager.dock(wlViewer.root, DG.DOCK_TYPE.DOWN);
|
|
112
133
|
|
|
113
134
|
tvList.push(tv);
|
|
@@ -126,7 +147,8 @@ category('WebLogo-positions', () => {
|
|
|
126
147
|
new PositionInfo('9', {'G': new PositionMonomerInfo(5)}),
|
|
127
148
|
new PositionInfo('10', {'C': new PositionMonomerInfo(5)})
|
|
128
149
|
];
|
|
129
|
-
|
|
150
|
+
|
|
151
|
+
expect(positions.length, resAllDf1.length);
|
|
130
152
|
|
|
131
153
|
for (let i = 0; i < positions.length; i++) {
|
|
132
154
|
expect(positions[i].name, resAllDf1[i].name);
|
|
@@ -190,6 +190,7 @@ MWRSWY-CKHP
|
|
|
190
190
|
};
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
+
|
|
193
194
|
test('NegativeEmpty', async () => { await _testNeg(readCsv('csvDfEmpty', csvDfEmpty), 'col1'); });
|
|
194
195
|
test('Negative1', async () => { await _testNeg(readCsv('csvDf1', csvDf1), 'col1'); });
|
|
195
196
|
test('Negative2', async () => { await _testNeg(readCsv('csvDf2', csvDf2), 'col1'); });
|
|
@@ -197,44 +198,44 @@ MWRSWY-CKHP
|
|
|
197
198
|
test('NegativeSmiles', async () => { await _testNeg(readCsv('csvDfSmiles', csvDfSmiles), 'col1'); });
|
|
198
199
|
|
|
199
200
|
test('Dna1', async () => {
|
|
200
|
-
await _testPos(readCsv('csvDfDna1', csvDfDna1), 'seq', 'fasta
|
|
201
|
+
await _testPos(readCsv('csvDfDna1', csvDfDna1), 'seq', 'fasta', 'SEQ', 'DNA');
|
|
201
202
|
});
|
|
202
203
|
test('Rna1', async () => {
|
|
203
|
-
await _testPos(readCsv('csvDfRna1', csvDfRna1), 'seq', 'fasta
|
|
204
|
+
await _testPos(readCsv('csvDfRna1', csvDfRna1), 'seq', 'fasta', 'SEQ', 'RNA');
|
|
204
205
|
});
|
|
205
206
|
test('AA1', async () => {
|
|
206
|
-
await _testPos(readCsv('csvDfPt1', csvDfPt1), 'seq', 'fasta
|
|
207
|
+
await _testPos(readCsv('csvDfPt1', csvDfPt1), 'seq', 'fasta', 'SEQ', 'PT');
|
|
207
208
|
});
|
|
208
209
|
test('MsaDna1', async () => {
|
|
209
|
-
await _testPos(readCsv('csvDfMsaDna1', csvDfMsaDna1), 'seq', 'fasta
|
|
210
|
+
await _testPos(readCsv('csvDfMsaDna1', csvDfMsaDna1), 'seq', 'fasta', 'SEQ.MSA', 'DNA');
|
|
210
211
|
});
|
|
211
212
|
|
|
212
213
|
test('MsaAA1', async () => {
|
|
213
|
-
await _testPos(readCsv('csvDfMsaPt1', csvDfMsaPt1), 'seq', 'fasta
|
|
214
|
+
await _testPos(readCsv('csvDfMsaPt1', csvDfMsaPt1), 'seq', 'fasta', 'SEQ.MSA', 'PT');
|
|
214
215
|
});
|
|
215
216
|
|
|
216
217
|
test('SepDna', async () => {
|
|
217
|
-
await _testPos(readCsv('csvDfSepDna', csvDfSepDna), 'seq', 'separator
|
|
218
|
+
await _testPos(readCsv('csvDfSepDna', csvDfSepDna), 'seq', 'separator', 'SEQ', 'DNA', '*');
|
|
218
219
|
});
|
|
219
220
|
test('SepRna', async () => {
|
|
220
|
-
await _testPos(readCsv('csvDfSepRna', csvDfSepRna), 'seq', 'separator
|
|
221
|
+
await _testPos(readCsv('csvDfSepRna', csvDfSepRna), 'seq', 'separator', 'SEQ', 'RNA', '*');
|
|
221
222
|
});
|
|
222
223
|
test('SepPt', async () => {
|
|
223
|
-
await _testPos(readCsv('csvDfSepPt', csvDfSepPt), 'seq', 'separator
|
|
224
|
+
await _testPos(readCsv('csvDfSepPt', csvDfSepPt), 'seq', 'separator', 'SEQ', 'PT', '-');
|
|
224
225
|
});
|
|
225
226
|
test('SepUn1', async () => {
|
|
226
|
-
await _testPos(readCsv('csvDfSepUn1', csvDfSepUn1), 'seq', 'separator
|
|
227
|
+
await _testPos(readCsv('csvDfSepUn1', csvDfSepUn1), 'seq', 'separator', 'SEQ', 'UN', '-');
|
|
227
228
|
});
|
|
228
229
|
test('SepUn2', async () => {
|
|
229
|
-
await _testPos(readCsv('csvDfSepUn2', csvDfSepUn2), 'seq', 'separator
|
|
230
|
+
await _testPos(readCsv('csvDfSepUn2', csvDfSepUn2), 'seq', 'separator', 'SEQ', 'UN', '/');
|
|
230
231
|
});
|
|
231
232
|
|
|
232
233
|
test('SepMsaN1', async () => {
|
|
233
|
-
await _testPos(readCsv('csvDfSepMsaDna1', csvDfSepMsaDna1), 'seq', 'separator
|
|
234
|
+
await _testPos(readCsv('csvDfSepMsaDna1', csvDfSepMsaDna1), 'seq', 'separator', 'SEQ.MSA', 'DNA', '-');
|
|
234
235
|
});
|
|
235
236
|
|
|
236
237
|
test('SamplesFastaCsvPt', async () => {
|
|
237
|
-
await _testPos(readSamples(Samples.fastaCsv), 'sequence', 'fasta
|
|
238
|
+
await _testPos(readSamples(Samples.fastaCsv), 'sequence', 'fasta', 'SEQ', 'PT');
|
|
238
239
|
});
|
|
239
240
|
test('SamplesFastaCsvNegativeEntry', async () => {
|
|
240
241
|
await _testNeg(readSamples(Samples.fastaCsv), 'Entry');
|
|
@@ -247,7 +248,7 @@ MWRSWY-CKHP
|
|
|
247
248
|
});
|
|
248
249
|
|
|
249
250
|
test('SamplesFastaFastaPt', async () => {
|
|
250
|
-
await _testPos(readSamples(Samples.fastaFasta, readFileFasta), 'sequence', 'fasta
|
|
251
|
+
await _testPos(readSamples(Samples.fastaFasta, readFileFasta), 'sequence', 'fasta', 'SEQ', 'PT');
|
|
251
252
|
});
|
|
252
253
|
|
|
253
254
|
// peptidesComplex contains monomers with spaces in AlignedSequence columns, which are forbidden
|
|
@@ -265,7 +266,7 @@ MWRSWY-CKHP
|
|
|
265
266
|
});
|
|
266
267
|
|
|
267
268
|
test('samplesMsaComplexUn', async () => {
|
|
268
|
-
await _testPos(readSamples(Samples.msaComplex), 'MSA', 'separator
|
|
269
|
+
await _testPos(readSamples(Samples.msaComplex), 'MSA', 'separator', 'SEQ.MSA', 'UN', '/');
|
|
269
270
|
});
|
|
270
271
|
test('samplesMsaComplexNegativeActivity', async () => {
|
|
271
272
|
await _testNeg(readSamples(Samples.msaComplex), 'Activity');
|
|
@@ -280,7 +281,7 @@ MWRSWY-CKHP
|
|
|
280
281
|
});
|
|
281
282
|
|
|
282
283
|
test('samplesHelmCsvHELM', async () => {
|
|
283
|
-
await _testPos(readSamples(Samples.helmCsv), 'HELM', 'HELM', null);
|
|
284
|
+
await _testPos(readSamples(Samples.helmCsv), 'HELM', 'HELM', null, null, null);
|
|
284
285
|
});
|
|
285
286
|
|
|
286
287
|
test('samplesHelmCsvNegativeActivity', async () => {
|
|
@@ -296,7 +297,7 @@ MWRSWY-CKHP
|
|
|
296
297
|
await _testNeg(readSamples(Samples.testHelmCsv), 'Test type');
|
|
297
298
|
});
|
|
298
299
|
test('samplesTestHelmPositiveHelmString', async () => {
|
|
299
|
-
await _testPos(readSamples(Samples.testHelmCsv), 'HELM string', 'HELM');
|
|
300
|
+
await _testPos(readSamples(Samples.testHelmCsv), 'HELM string', 'HELM', null, null, null);
|
|
300
301
|
});
|
|
301
302
|
test('samplesTestHelmNegativeValid', async () => {
|
|
302
303
|
await _testNeg(readSamples(Samples.testHelmCsv), 'Valid?');
|
|
@@ -328,7 +329,7 @@ MWRSWY-CKHP
|
|
|
328
329
|
});
|
|
329
330
|
|
|
330
331
|
test('samplesFastaPtPosSequence', async () => {
|
|
331
|
-
await _testPos(readSamples(Samples.fastaPtCsv), 'sequence', 'fasta
|
|
332
|
+
await _testPos(readSamples(Samples.fastaPtCsv), 'sequence', 'fasta', 'SEQ', 'PT');
|
|
332
333
|
});
|
|
333
334
|
|
|
334
335
|
test('samplesTestCerealNegativeCerealName', async () => {
|
|
@@ -383,7 +384,7 @@ export async function _testNeg(readDf: DfReaderFunc, colName: string) {
|
|
|
383
384
|
}
|
|
384
385
|
}
|
|
385
386
|
|
|
386
|
-
export async function _testPos(readDf: DfReaderFunc, colName: string, units: string, separator: string | null = null) {
|
|
387
|
+
export async function _testPos(readDf: DfReaderFunc, colName: string, units: string, aligned: string | null, alphabet: string | null, separator: string | null = null) {
|
|
387
388
|
const df: DG.DataFrame = await readDf();
|
|
388
389
|
const col: DG.Column = df.col(colName)!;
|
|
389
390
|
const semType: string = await grok.functions.call('Bio:detectMacromolecule', {col: col});
|
|
@@ -392,6 +393,8 @@ export async function _testPos(readDf: DfReaderFunc, colName: string, units: str
|
|
|
392
393
|
|
|
393
394
|
expect(col.semType === DG.SEMTYPE.MACROMOLECULE, true);
|
|
394
395
|
expect(col.getTag(DG.TAGS.UNITS), units);
|
|
396
|
+
expect(col.getTag('aligned'), aligned);
|
|
397
|
+
expect(col.getTag('alphabet'), alphabet);
|
|
395
398
|
if (separator)
|
|
396
399
|
expect(col.getTag('separator'), separator);
|
|
397
400
|
}
|
|
@@ -43,14 +43,18 @@ category('renderers', () => {
|
|
|
43
43
|
`semType="${srcSeqCol!.semType}", units="${srcSeqCol!.getTag(DG.TAGS.UNITS)}", ` +
|
|
44
44
|
`cell.renderer="${srcSeqCol!.getTag('cell.renderer')}"`);
|
|
45
45
|
expect(srcSeqCol!.semType, DG.SEMTYPE.MACROMOLECULE);
|
|
46
|
-
expect(srcSeqCol!.getTag(DG.TAGS.UNITS), 'fasta
|
|
46
|
+
expect(srcSeqCol!.getTag(DG.TAGS.UNITS), 'fasta');
|
|
47
|
+
expect(srcSeqCol!.getTag('aligned'), 'SEQ');
|
|
48
|
+
expect(srcSeqCol!.getTag('alphabet'), 'PT');
|
|
47
49
|
expect(srcSeqCol!.getTag('cell.renderer'), 'Macromolecule');
|
|
48
50
|
|
|
49
51
|
const msaSeqCol: DG.Column | null = await multipleSequenceAlignmentAny(df, srcSeqCol!);
|
|
50
52
|
tv.grid.invalidate();
|
|
51
53
|
|
|
52
54
|
expect(msaSeqCol!.semType, DG.SEMTYPE.MACROMOLECULE);
|
|
53
|
-
expect(msaSeqCol!.getTag(DG.TAGS.UNITS), 'fasta
|
|
55
|
+
expect(msaSeqCol!.getTag(DG.TAGS.UNITS), 'fasta');
|
|
56
|
+
expect(msaSeqCol!.getTag('aligned'), 'SEQ.MSA');
|
|
57
|
+
expect(msaSeqCol!.getTag('alphabet'), 'PT');
|
|
54
58
|
expect(msaSeqCol!.getTag('cell.renderer'), 'Macromolecule');
|
|
55
59
|
|
|
56
60
|
dfList.push(df);
|
|
@@ -7,7 +7,6 @@ import {SplitterFunc, WebLogo} from '@datagrok-libraries/bio/src/viewers/web-log
|
|
|
7
7
|
import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
|
|
8
8
|
import * as ui from 'datagrok-api/ui';
|
|
9
9
|
|
|
10
|
-
export const lru = new DG.LruCache<any, any>();
|
|
11
10
|
const undefinedColor = 'rgb(100,100,100)';
|
|
12
11
|
const grayColor = '#808080';
|
|
13
12
|
|
|
@@ -62,7 +61,7 @@ export function processSequence(subParts: string[]): [string[], boolean] {
|
|
|
62
61
|
* @param {boolean} [last=false] Is checker if element last or not.
|
|
63
62
|
* @return {number} x coordinate to start printing at.
|
|
64
63
|
*/
|
|
65
|
-
function printLeftOrCentered(
|
|
64
|
+
export function printLeftOrCentered(
|
|
66
65
|
x: number, y: number, w: number, h: number,
|
|
67
66
|
g: CanvasRenderingContext2D, s: string, color = undefinedColor,
|
|
68
67
|
pivot: number = 0, left = false, transparencyRate: number = 1.0,
|
|
@@ -71,7 +70,7 @@ function printLeftOrCentered(
|
|
|
71
70
|
const colorPart = s.substring(0);
|
|
72
71
|
let grayPart = last ? '' : separator;
|
|
73
72
|
if (drawStyle === 'msa') {
|
|
74
|
-
grayPart = '
|
|
73
|
+
grayPart = '';
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
let textSize: any = g.measureText(colorPart + grayPart);
|
|
@@ -109,26 +108,11 @@ function printLeftOrCentered(
|
|
|
109
108
|
}
|
|
110
109
|
}
|
|
111
110
|
|
|
112
|
-
function findMonomers(helmString: string) {
|
|
113
|
-
//@ts-ignore
|
|
114
|
-
const types = Object.keys(org.helm.webeditor.monomerTypeList());
|
|
115
|
-
const monomers: any = [];
|
|
116
|
-
const monomer_names: any = [];
|
|
117
|
-
for (var i = 0; i < types.length; i++) {
|
|
118
|
-
//@ts-ignore
|
|
119
|
-
monomers.push(new scil.helm.Monomers.getMonomerSet(types[i]));
|
|
120
|
-
Object.keys(monomers[i]).forEach(k => {
|
|
121
|
-
monomer_names.push(monomers[i][k].id);
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
const split_string = WebLogo.splitterAsHelm(helmString);
|
|
125
|
-
return new Set(split_string.filter(val => !monomer_names.includes(val)));
|
|
126
|
-
}
|
|
127
111
|
|
|
128
112
|
export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
129
|
-
get name(): string { return '
|
|
113
|
+
get name(): string { return 'sequence'; }
|
|
130
114
|
|
|
131
|
-
get cellType(): string { return
|
|
115
|
+
get cellType(): string { return 'sequence'; }
|
|
132
116
|
|
|
133
117
|
get defaultHeight(): number { return 30; }
|
|
134
118
|
|
|
@@ -153,109 +137,67 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
153
137
|
const grid = gridCell.gridRow !== -1 ? gridCell.grid : undefined;
|
|
154
138
|
const cell = gridCell.cell;
|
|
155
139
|
const tag = gridCell.cell.column.getTag(DG.TAGS.UNITS);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
g.textBaseline = 'top';
|
|
184
|
-
let x1 = x;
|
|
185
|
-
const s: string = cell.value ?? '';
|
|
186
|
-
let subParts: string[] = WebLogo.splitterAsHelm(s);
|
|
140
|
+
const [type, subtype, paletteType] = gridCell.cell.column.getTag(DG.TAGS.UNITS).split(':');
|
|
141
|
+
w = grid ? Math.min(grid.canvas.width - x, w) : g.canvas.width - x;
|
|
142
|
+
g.save();
|
|
143
|
+
g.beginPath();
|
|
144
|
+
g.rect(x, y, w, h);
|
|
145
|
+
g.clip();
|
|
146
|
+
g.font = '12px monospace';
|
|
147
|
+
g.textBaseline = 'top';
|
|
148
|
+
const s: string = cell.value ?? '';
|
|
149
|
+
|
|
150
|
+
//TODO: can this be replaced/merged with splitSequence?
|
|
151
|
+
const units = gridCell.cell.column.getTag(DG.TAGS.UNITS);
|
|
152
|
+
|
|
153
|
+
const palette = getPalleteByType(paletteType);
|
|
154
|
+
|
|
155
|
+
const separator = gridCell.cell.column.getTag('separator') ?? '';
|
|
156
|
+
const splitterFunc: SplitterFunc = WebLogo.getSplitter(units, gridCell.cell.column.getTag('separator'));
|
|
157
|
+
|
|
158
|
+
const columns = gridCell.cell.column.categories;
|
|
159
|
+
let monomerToShortFunction: (amino: string, maxLengthOfMonomer: number) => string = WebLogo.monomerToShort;
|
|
160
|
+
let maxLengthOfMonomer = 8;
|
|
161
|
+
|
|
162
|
+
let maxLengthWords = {};
|
|
163
|
+
// check if gridCell.cell.column.temp is array
|
|
164
|
+
if (gridCell.cell.column.getTag('.calculatedCellRender') !== 'exist') {
|
|
165
|
+
for (let i = 0; i < columns.length; i++) {
|
|
166
|
+
let subParts: string[] = splitterFunc(columns[i]);
|
|
187
167
|
subParts.forEach((amino, index) => {
|
|
188
|
-
|
|
189
|
-
g.
|
|
190
|
-
|
|
191
|
-
|
|
168
|
+
//@ts-ignore
|
|
169
|
+
let textSizeWidth = g.measureText(monomerToShortFunction(amino, maxLengthOfMonomer));
|
|
170
|
+
//@ts-ignore
|
|
171
|
+
if (textSizeWidth.width > (maxLengthWords[index] ?? 0)) {
|
|
172
|
+
//@ts-ignore
|
|
173
|
+
maxLengthWords[index] = textSizeWidth.width;
|
|
174
|
+
}
|
|
192
175
|
});
|
|
193
|
-
g.restore();
|
|
194
|
-
return;
|
|
195
176
|
}
|
|
177
|
+
gridCell.cell.column.temp = maxLengthWords;
|
|
178
|
+
gridCell.cell.column.setTag('.calculatedCellRender', 'exist');
|
|
196
179
|
} else {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
g.save();
|
|
200
|
-
g.beginPath();
|
|
201
|
-
g.rect(x, y, w, h);
|
|
202
|
-
g.clip();
|
|
203
|
-
g.font = '12px monospace';
|
|
204
|
-
g.textBaseline = 'top';
|
|
205
|
-
const s: string = cell.value ?? '';
|
|
206
|
-
|
|
207
|
-
//TODO: can this be replaced/merged with splitSequence?
|
|
208
|
-
const units = gridCell.cell.column.getTag(DG.TAGS.UNITS);
|
|
209
|
-
|
|
210
|
-
const palette = getPalleteByType(paletteType);
|
|
211
|
-
|
|
212
|
-
const separator = gridCell.cell.column.getTag('separator') ?? '';
|
|
213
|
-
const splitterFunc: SplitterFunc = WebLogo.getSplitter(units, gridCell.cell.column.getTag('separator'));
|
|
214
|
-
|
|
215
|
-
const columns = gridCell.cell.column.categories;
|
|
216
|
-
let monomerToShortFunction: (amino: string, maxLengthOfMonomer: number) => string = WebLogo.monomerToShort;
|
|
217
|
-
let maxLengthOfMonomer = 8;
|
|
218
|
-
|
|
219
|
-
let maxLengthWords = {};
|
|
220
|
-
// check if gridCell.cell.column.temp is array
|
|
221
|
-
if (gridCell.cell.column.getTag('.calculatedCellRender') !== 'exist') {
|
|
222
|
-
for (let i = 0; i < columns.length; i++) {
|
|
223
|
-
let subParts: string[] = splitterFunc(columns[i]);
|
|
224
|
-
subParts.forEach((amino, index) => {
|
|
225
|
-
//@ts-ignore
|
|
226
|
-
let textSizeWidth = g.measureText(monomerToShortFunction(amino, maxLengthOfMonomer));
|
|
227
|
-
//@ts-ignore
|
|
228
|
-
if (textSizeWidth.width > (maxLengthWords[index] ?? 0)) {
|
|
229
|
-
//@ts-ignore
|
|
230
|
-
maxLengthWords[index] = textSizeWidth.width;
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
gridCell.cell.column.temp = maxLengthWords;
|
|
235
|
-
gridCell.cell.column.setTag('.calculatedCellRender', 'exist');
|
|
236
|
-
} else {
|
|
237
|
-
maxLengthWords = gridCell.cell.column.temp;
|
|
238
|
-
}
|
|
180
|
+
maxLengthWords = gridCell.cell.column.temp;
|
|
181
|
+
}
|
|
239
182
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
subParts.forEach((amino, index) => {
|
|
250
|
-
color = palette.get(amino);
|
|
251
|
-
g.fillStyle = undefinedColor;
|
|
252
|
-
let last = index === subParts.length - 1;
|
|
253
|
-
x1 = printLeftOrCentered(x1, y, w, h, g, monomerToShortFunction(amino, maxLengthOfMonomer), color, 0, true, 1.0, separator, last, drawStyle, maxLengthWords, index, gridCell);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
g.restore();
|
|
257
|
-
return;
|
|
183
|
+
const subParts: string[] = splitterFunc(cell.value);
|
|
184
|
+
let x1 = x;
|
|
185
|
+
let color = undefinedColor;
|
|
186
|
+
// get max length word in subParts
|
|
187
|
+
let tagUnits = gridCell.cell.column.getTag(DG.TAGS.UNITS);
|
|
188
|
+
let drawStyle = 'classic';
|
|
189
|
+
if (tagUnits.includes('MSA')) {
|
|
190
|
+
drawStyle = 'msa';
|
|
258
191
|
}
|
|
192
|
+
subParts.forEach((amino, index) => {
|
|
193
|
+
color = palette.get(amino);
|
|
194
|
+
g.fillStyle = undefinedColor;
|
|
195
|
+
let last = index === subParts.length - 1;
|
|
196
|
+
x1 = printLeftOrCentered(x1, y, w, h, g, monomerToShortFunction(amino, maxLengthOfMonomer), color, 0, true, 1.0, separator, last, drawStyle, maxLengthWords, index, gridCell);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
g.restore();
|
|
200
|
+
return;
|
|
259
201
|
}
|
|
260
202
|
}
|
|
261
203
|
|