@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/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "Leonid Stolbov",
6
6
  "email": "lstolbov@datagrok.ai"
7
7
  },
8
- "version": "1.7.24",
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.3",
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
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash
2
2
 
3
- ./setup-unlink-clean
3
+ ./setup-unlink-clean.sh
4
4
 
5
5
  GREEN='\e[0;32m'
6
6
  NO_COLOR='\e[0m'
@@ -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 = 500000;
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
- }, 500000);
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: 500000});
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
  }
@@ -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
- //tags: init
31
- export async function initBio(): Promise<void> {
32
- // apparently HELMWebEditor requires dojo to be initialized first
33
- const funcList: DG.Func[] = DG.Func.find({package: 'Helm', name: 'initHelm'});
34
- console.debug(`Bio: initBio() funcList.length = ${funcList.length}`);
35
- if (funcList.length === 1)
36
- await grok.functions.call('Helm:initHelp');
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: macromoleculeSequenceCellRenderer
38
+ //name: separatorSequenceCellRenderer
51
39
  //tags: cellRenderer
52
- //meta.cellType: Macromolecule
40
+ //meta.cellType: Sequence
41
+ //meta.columnTags: units=separator
53
42
  //output: grid_cell_renderer result
54
- export function macromoleculeSequenceCellRenderer(): MacromoleculeSequenceCellRenderer {
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
- console.log(positions);
61
- expect(positions.length,resAllDf1.length);
62
- // check all positions are equal resAllDf1
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
- const df: DG.DataFrame = DG.DataFrame.fromCsv(csvDf1);
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', {'A': new PositionMonomerInfo(2), '-': new PositionMonomerInfo(3)}),
85
- new PositionInfo('2', {'T': new PositionMonomerInfo(5)}),
86
- new PositionInfo('3', {'C': new PositionMonomerInfo(5)}),
87
- new PositionInfo('4', {'-': new PositionMonomerInfo(5)}),
88
- new PositionInfo('5', {'G': new PositionMonomerInfo(5)}),
89
- new PositionInfo('6', {'-': new PositionMonomerInfo(3), 'C': new PositionMonomerInfo(2)}),
90
- new PositionInfo('7', {'T': new PositionMonomerInfo(5)}),
91
- new PositionInfo('8', {'T': new PositionMonomerInfo(5)}),
92
- new PositionInfo('9', {'G': new PositionMonomerInfo(5)}),
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
- console.log(positions);
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
- const wlViewer: WebLogo = await df.plot.fromType('WebLogo', {'skipEmptyPositions': false}) as unknown as WebLogo;
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
- console.log(positions);
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:SEQ:DNA');
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:SEQ:RNA');
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:SEQ:PT');
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:SEQ.MSA:DNA');
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:SEQ.MSA:PT');
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:SEQ:DNA', '*');
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:SEQ:RNA', '*');
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:SEQ:PT', '-');
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:SEQ:UN', '-');
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:SEQ:UN', '/');
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:SEQ.MSA:DNA', '-');
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:SEQ:PT');
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:SEQ:PT');
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:SEQ.MSA:UN', '/');
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:SEQ:PT');
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:SEQ:PT');
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:SEQ.MSA:PT');
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 'macromoleculeSequence'; }
113
+ get name(): string { return 'sequence'; }
130
114
 
131
- get cellType(): string { return C.SEM_TYPES.MACROMOLECULE; }
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
- if (tag === 'HELM') {
157
- const monomers = findMonomers(cell.value);
158
- if (monomers.size == 0) {
159
- const host = ui.div([], {style: {width: `${w}px`, height: `${h}px`}});
160
- host.setAttribute('dataformat', 'helm');
161
- host.setAttribute('data', gridCell.cell.value);
162
- gridCell.element = host;
163
- //@ts-ignore
164
- const canvas = new JSDraw2.Editor(host, {width: w, height: h, skin: 'w8', viewonly: true});
165
- const formula = canvas.getFormula(true);
166
- if (!formula) {
167
- gridCell.element = ui.divText(gridCell.cell.value, {style: {color: 'red'}});
168
- }
169
- const molWeight = Math.round(canvas.getMolWeight() * 100) / 100;
170
- const coef = Math.round(canvas.getExtinctionCoefficient(true) * 100) / 100;
171
- const molfile = canvas.getMolfile();
172
- const result = formula + ', ' + molWeight + ', ' + coef + ', ' + molfile;
173
- lru.set(gridCell.cell.value, result);
174
- return;
175
- }
176
- if (monomers.size > 0) {
177
- w = grid ? Math.min(grid.canvas.width - x, w) : g.canvas.width - x;
178
- g.save();
179
- g.beginPath();
180
- g.rect(x, y, w, h);
181
- g.clip();
182
- g.font = '12px monospace';
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
- let color = monomers.has(amino) ? 'red' : grayColor;
189
- g.fillStyle = undefinedColor;
190
- let last = index === subParts.length - 1;
191
- x1 = printLeftOrCentered(x1, y, w, h, g, amino, color, 0, true, 1.0, '/', last);
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
- const [type, subtype, paletteType] = gridCell.cell.column.getTag(DG.TAGS.UNITS).split(':');
198
- w = grid ? Math.min(grid.canvas.width - x, w) : g.canvas.width - x;
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
- const subParts: string[] = splitterFunc(cell.value);
241
- let x1 = x;
242
- let color = undefinedColor;
243
- // get max length word in subParts
244
- let tagUnits = gridCell.cell.column.getTag(DG.TAGS.UNITS);
245
- let drawStyle = 'classic';
246
- if (tagUnits.includes('MSA')) {
247
- drawStyle = 'msa';
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