@datagrok/bio 1.8.1 → 1.9.1

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.8.1",
8
+ "version": "1.9.1",
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,16 +14,16 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@biowasm/aioli": ">=2.4.0",
17
- "@datagrok-libraries/bio": "^3.0.4",
18
- "@datagrok-libraries/ml": "^3.0.5",
19
- "@datagrok-libraries/utils": "^1.5.4",
17
+ "@datagrok-libraries/bio": "^3.3.1",
18
+ "@datagrok-libraries/ml": "^4.0.0",
19
+ "@datagrok-libraries/utils": "^1.6.2",
20
20
  "cash-dom": "latest",
21
21
  "datagrok-api": "^1.5.5",
22
22
  "dayjs": "^1.11.4",
23
23
  "openchemlib": "6.0.1",
24
24
  "rxjs": "^6.5.5",
25
- "ts-loader": "^9.2.5",
26
- "typescript": "^4.4.2"
25
+ "typescript": "^4.4.2",
26
+ "wu": "latest"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/jest": "^27.0.0",
@@ -35,6 +35,7 @@
35
35
  "jest-html-reporter": "^3.6.0",
36
36
  "puppeteer": "^13.7.0",
37
37
  "ts-jest": "^27.0.0",
38
+ "ts-loader": "^9.2.5",
38
39
  "webpack": "latest",
39
40
  "webpack-cli": "^4.10.0",
40
41
  "@types/js-yaml": "^4.0.5",
package/src/package.ts CHANGED
@@ -15,7 +15,7 @@ import {Aminoacids} from '@datagrok-libraries/bio/src/aminoacids';
15
15
  import {getEmbeddingColsNames, sequenceSpace} from './utils/sequence-space';
16
16
  import {AvailableMetrics} from '@datagrok-libraries/ml/src/typed-metrics';
17
17
  import {getActivityCliffs} from '@datagrok-libraries/ml/src/viewers/activity-cliffs';
18
- import {sequenceGetSimilarities, drawTooltip} from './utils/sequence-activity-cliffs';
18
+ import {drawSequences, sequenceGetSimilarities} from './utils/sequence-activity-cliffs';
19
19
  import {createJsonMonomerLibFromSdf, encodeMonomers, getMolfilesFromSeq, HELM_CORE_LIB_FILENAME} from './utils/utils';
20
20
  import {getMacroMol} from './utils/atomic-works';
21
21
  import {MacromoleculeSequenceCellRenderer} from './utils/cell-renderer';
@@ -23,13 +23,51 @@ import {convert} from './utils/convert';
23
23
  import {representationsWidget} from './widgets/representations';
24
24
  import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
25
25
  import {FastaFileHandler} from '@datagrok-libraries/bio/src/utils/fasta-handler';
26
- import {removeEmptyStringRows} from '@datagrok-libraries/utils/src/dataframe-utils'
27
-
26
+ import {removeEmptyStringRows} from '@datagrok-libraries/utils/src/dataframe-utils';
27
+ import {generateManySequences, generateLongSequence} from './tests/test-sequnces-generators';
28
28
 
29
29
  //tags: init
30
30
  export async function initBio() {
31
31
  }
32
32
 
33
+ //name: testManySequencesPerformance
34
+ export function testManySequencesPerformance(): void {
35
+ const startTime: number = Date.now();
36
+ const csv = generateManySequences();
37
+ const df: DG.DataFrame = DG.DataFrame.fromCsv(csv);
38
+ const col: DG.Column = df.columns.byName('MSA');
39
+ df.columns.byName('MSA').semType = DG.SEMTYPE.MACROMOLECULE;
40
+ col.setTag('units', 'separator');
41
+ col.setTag('aligned', 'SEQ.MSA');
42
+ col.setTag('alphabet', 'UN');
43
+ col.setTag('separator', '/');
44
+ grok.shell.addTableView(df);
45
+
46
+ const endTime: number = Date.now();
47
+ const elapsedTime: number = endTime - startTime;
48
+ console.log(`Elapsed time: ${elapsedTime}ms`);
49
+
50
+ }
51
+ //name: testLongSequencesPerformance
52
+ export function testLongSequencesPerformance(): void {
53
+ const startTime: number = Date.now();
54
+ const csv = generateLongSequence();
55
+ const df: DG.DataFrame = DG.DataFrame.fromCsv(csv);
56
+ const col: DG.Column = df.columns.byName('MSA');
57
+ df.columns.byName('MSA').semType = DG.SEMTYPE.MACROMOLECULE;
58
+ col.setTag('units', 'separator');
59
+ col.setTag('aligned', 'SEQ.MSA');
60
+ col.setTag('alphabet', 'UN');
61
+ col.setTag('separator', '/');
62
+ grok.shell.addTableView(df);
63
+
64
+ const endTime: number = Date.now();
65
+ const elapsedTime: number = endTime - startTime;
66
+ console.log(`Elapsed time: ${elapsedTime}ms`);
67
+
68
+ }
69
+
70
+
33
71
  //name: fastaSequenceCellRenderer
34
72
  //tags: cellRenderer
35
73
  //meta.cellType: Sequence
@@ -51,7 +89,7 @@ export function separatorSequenceCellRenderer(): MacromoleculeSequenceCellRender
51
89
  function checkInputColumn(col: DG.Column, name: string,
52
90
  allowedNotations: string[] = [], allowedAlphabets: string[] = []): boolean {
53
91
  const notation: string = col.getTag(DG.TAGS.UNITS);
54
- const alphabet: string = col.getTag('alphabet')
92
+ const alphabet: string = col.getTag('alphabet');
55
93
  if (col.semType !== DG.SEMTYPE.MACROMOLECULE) {
56
94
  grok.shell.warning(name + ' analysis is allowed for Macromolecules semantic type');
57
95
  return false;
@@ -127,7 +165,7 @@ export async function activityCliffs(df: DG.DataFrame, macroMolecule: DG.Column,
127
165
  'aligned': macroMolecule.tags['aligned'],
128
166
  'separator': macroMolecule.tags['separator'],
129
167
  'alphabet': macroMolecule.tags['alphabet'],
130
- }
168
+ };
131
169
  const sp = await getActivityCliffs(
132
170
  df,
133
171
  macroMolecule,
@@ -142,9 +180,9 @@ export async function activityCliffs(df: DG.DataFrame, macroMolecule: DG.Column,
142
180
  tags,
143
181
  sequenceSpace,
144
182
  sequenceGetSimilarities,
145
- drawTooltip,
183
+ drawSequences,
146
184
  (options as any)[methodName]);
147
- return sp;
185
+ return sp;
148
186
  }
149
187
 
150
188
  //top-menu: Bio | Sequence Space...
@@ -155,7 +193,7 @@ export async function activityCliffs(df: DG.DataFrame, macroMolecule: DG.Column,
155
193
  //input: string similarityMetric { choices:["Levenshtein", "Tanimoto"] }
156
194
  //input: bool plotEmbeddings = true
157
195
  export async function sequenceSpaceTopMenu(table: DG.DataFrame, macroMolecule: DG.Column, methodName: string,
158
- similarityMetric: string = 'Levenshtein', plotEmbeddings: boolean): Promise<DG.Viewer|undefined> {
196
+ similarityMetric: string = 'Levenshtein', plotEmbeddings: boolean): Promise<DG.Viewer | undefined> {
159
197
  if (!checkInputColumn(macroMolecule, 'Activity Cliffs'))
160
198
  return;
161
199
  const encodedCol = encodeMonomers(macroMolecule);
@@ -174,11 +212,11 @@ export async function sequenceSpaceTopMenu(table: DG.DataFrame, macroMolecule: D
174
212
  const sequenceSpaceRes = await sequenceSpace(chemSpaceParams);
175
213
  const embeddings = sequenceSpaceRes.coordinates;
176
214
  for (const col of embeddings) {
177
- const listValues = col.toList();
178
- emptyValsIdxs.forEach((ind: number) => listValues.splice(ind, 0, null));
179
- table.columns.add(DG.Column.fromList('double', col.name, listValues));
215
+ const listValues = col.toList();
216
+ emptyValsIdxs.forEach((ind: number) => listValues.splice(ind, 0, null));
217
+ table.columns.add(DG.Column.fromList('double', col.name, listValues));
180
218
  }
181
- let sp;
219
+ let sp;
182
220
  if (plotEmbeddings) {
183
221
  for (const v of grok.shell.views) {
184
222
  if (v.name === table.name)
@@ -12,11 +12,11 @@ category('WebLogo-positions', () => {
12
12
  let currentView: DG.View;
13
13
 
14
14
  const csvDf1 = `seq
15
- ATC-G-TTGC--
16
- ATC-G-TTGC--
17
- -TC-G-TTGC--
18
- -TC-GCTTGC--
19
- -TC-GCTTGC--`;
15
+ ATC-G-TTGC--
16
+ ATC-G-TTGC--
17
+ -TC-G-TTGC--
18
+ -TC-GCTTGC--
19
+ -TC-GCTTGC--`;
20
20
 
21
21
 
22
22
  before(async () => {
@@ -34,8 +34,10 @@ category('WebLogo-positions', () => {
34
34
  const df: DG.DataFrame = DG.DataFrame.fromCsv(csvDf1);
35
35
  const tv: DG.TableView = grok.shell.addTableView(df);
36
36
 
37
- df.getCol('seq').semType = 'Macromolecule';
38
- df.getCol('seq').setTag('units', 'fasta:SEQ.MSA:DNA');
37
+ const seqCol: DG.Column = df.getCol('seq');
38
+ seqCol.semType = 'Macromolecule';
39
+ seqCol.setTag('units', 'fasta');
40
+ seqCol.setTag('alphabet', 'DNA');
39
41
 
40
42
  const wlViewer: WebLogo = await df.plot.fromType('WebLogo') as unknown as WebLogo;
41
43
  tv.dockManager.dock(wlViewer.root, DG.DOCK_TYPE.DOWN);
@@ -81,10 +83,11 @@ category('WebLogo-positions', () => {
81
83
  const df: DG.DataFrame = DG.DataFrame.fromCsv(csvDf2);
82
84
  const tv: DG.TableView = grok.shell.addTableView(df);
83
85
 
84
- df.getCol('seq').semType = 'Macromolecule';
85
- df.getCol('seq').setTag('units', 'fasta:SEQ.MSA:DNA');
86
+ const seqCol: DG.Column = df.getCol('seq');
87
+ seqCol.semType = 'Macromolecule';
88
+ seqCol.setTag('units', 'fasta');
89
+ seqCol.setTag('alphabet', 'DNA');
86
90
 
87
- let seq: Column = df.getCol('seq');
88
91
  df.filter.init((i) => {
89
92
  return i > 2;
90
93
  });
@@ -125,8 +128,10 @@ category('WebLogo-positions', () => {
125
128
  const df: DG.DataFrame = DG.DataFrame.fromCsv(csvDf1);
126
129
  const tv: DG.TableView = grok.shell.addTableView(df);
127
130
 
128
- df.getCol('seq').semType = 'Macromolecule';
129
- df.getCol('seq').setTag('units', 'fasta:SEQ.MSA:DNA');
131
+ const seqCol: DG.Column = df.getCol('seq');
132
+ seqCol.semType = 'Macromolecule';
133
+ seqCol.setTag('units', 'fasta');
134
+ seqCol.setTag('alphabet', 'DNA');
130
135
 
131
136
  const wlViewer: WebLogo = await df.plot.fromType('WebLogo', {'skipEmptyPositions': true}) as unknown as WebLogo;
132
137
  tv.dockManager.dock(wlViewer.root, DG.DOCK_TYPE.DOWN);
@@ -156,7 +161,6 @@ category('WebLogo-positions', () => {
156
161
  expect(positions[i].freq[key].count, resAllDf1[i].freq[key].count);
157
162
  }
158
163
  }
159
-
160
164
  });
161
165
 
162
166
  });
@@ -5,6 +5,7 @@ import * as ui from 'datagrok-api/ui';
5
5
  import * as DG from 'datagrok-api/dg';
6
6
 
7
7
  import {importFasta} from '../package';
8
+ import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
8
9
 
9
10
  type DfReaderFunc = () => Promise<DG.DataFrame>;
10
11
 
@@ -281,7 +282,7 @@ MWRSWY-CKHP
281
282
  });
282
283
 
283
284
  test('samplesHelmCsvHELM', async () => {
284
- await _testPos(readSamples(Samples.helmCsv), 'HELM', 'HELM', null, null, null);
285
+ await _testPos(readSamples(Samples.helmCsv), 'HELM', 'helm', null, null, null);
285
286
  });
286
287
 
287
288
  test('samplesHelmCsvNegativeActivity', async () => {
@@ -297,7 +298,7 @@ MWRSWY-CKHP
297
298
  await _testNeg(readSamples(Samples.testHelmCsv), 'Test type');
298
299
  });
299
300
  test('samplesTestHelmPositiveHelmString', async () => {
300
- await _testPos(readSamples(Samples.testHelmCsv), 'HELM string', 'HELM', null, null, null);
301
+ await _testPos(readSamples(Samples.testHelmCsv), 'HELM string', 'helm', null, null, null);
301
302
  });
302
303
  test('samplesTestHelmNegativeValid', async () => {
303
304
  await _testNeg(readSamples(Samples.testHelmCsv), 'Valid?');
@@ -371,7 +372,8 @@ MWRSWY-CKHP
371
372
  export async function _testNeg(readDf: DfReaderFunc, colName: string) {
372
373
  const df: DG.DataFrame = await readDf();
373
374
  const col: DG.Column = df.col(colName)!;
374
- const semType: string = await grok.functions.call('Bio:detectMacromolecule', {col: col});
375
+ const semType: string = await grok.functions
376
+ .call('Bio:detectMacromolecule', {col: col}) as unknown as string;
375
377
  if (semType)
376
378
  col.semType = semType;
377
379
 
@@ -384,10 +386,14 @@ export async function _testNeg(readDf: DfReaderFunc, colName: string) {
384
386
  }
385
387
  }
386
388
 
387
- export async function _testPos(readDf: DfReaderFunc, colName: string, units: string, aligned: string | null, alphabet: string | null, separator: string | null = null) {
389
+ export async function _testPos(
390
+ readDf: DfReaderFunc, colName: string, units: string,
391
+ aligned: string | null, alphabet: string | null, separator: string | null = null
392
+ ) {
388
393
  const df: DG.DataFrame = await readDf();
389
394
  const col: DG.Column = df.col(colName)!;
390
- const semType: string = await grok.functions.call('Bio:detectMacromolecule', {col: col});
395
+ const semType: string = await grok.functions
396
+ .call('Bio:detectMacromolecule', {col: col}) as unknown as string;
391
397
  if (semType)
392
398
  col.semType = semType;
393
399
 
@@ -397,5 +403,11 @@ export async function _testPos(readDf: DfReaderFunc, colName: string, units: str
397
403
  expect(col.getTag('alphabet'), alphabet);
398
404
  if (separator)
399
405
  expect(col.getTag('separator'), separator);
406
+
407
+ const uh = new UnitsHandler(col);
408
+ if (!uh.isHelm()) {
409
+ expect(uh.aligned, aligned);
410
+ expect(uh.alphabet, alphabet);
411
+ }
400
412
  }
401
413
 
@@ -49,7 +49,8 @@ async function _testMsaIsCorrect(srcCsv: string, tgtCsv: string): Promise<void>
49
49
  const tgtDf: DG.DataFrame = DG.DataFrame.fromCsv(tgtCsv);
50
50
 
51
51
  const srcCol: DG.Column = srcDf.getCol('seq')!;
52
- const semType: string = await grok.functions.call('Bio:detectMacromolecule', {col: srcCol});
52
+ const semType: string = await grok.functions
53
+ .call('Bio:detectMacromolecule', {col: srcCol}) as unknown as string;
53
54
  if (semType)
54
55
  srcCol.semType = semType;
55
56
 
@@ -0,0 +1,22 @@
1
+ export function generateManySequences(): string {
2
+ let csvData = `MSA,Activity
3
+ meI/hHis/Aca/N/T/dE/Thr_PO3H2/Aca/D-Tyr_Et/Tyr_ab-dehydroMe/dV/E/N/D-Orn/D-aThr//Phe_4Me,5.30751`;
4
+ for (let i = 0; i < 10 ** 6; i++) {
5
+ csvData += `\n meI/hHis/Aca/N/T/dE/Thr_PO3H2/Aca/D-Tyr_Et/Tyr_ab-dehydroMe/dV/E/N/D-Orn/D-aThr//Phe_4Me,5.30751`;
6
+ }
7
+ return csvData;
8
+ }
9
+
10
+ export function generateLongSequence(): string {
11
+ let longSequence = `meI/hHis/Aca/N/T/dE/Thr_PO3H2/Aca/D-Tyr_Et/Tyr_ab-dehydroMe/dV/E/N/D-Orn/D-aThr`;
12
+ for (let i = 0; i < 10 ** 6; i++) {
13
+ longSequence += `/Aca/N/T/dE/Thr_PO3H2/Aca/D-Tyr_Et/Tyr_ab-dehydroMe/dV/dv`;
14
+ }
15
+ longSequence += `//Phe_4Me,5.30751`;
16
+ let csvData = `MSA,Activity
17
+ \n ${longSequence}`;
18
+ for (let i = 0; i <= 10 ** 2; i++) {
19
+ csvData += `\n ${longSequence}`;
20
+ }
21
+ return csvData;
22
+ }
@@ -1,6 +1,8 @@
1
1
  import * as OCL from 'openchemlib/full.js';
2
2
  import * as grok from 'datagrok-api/grok';
3
3
 
4
+ import {RDModule} from '@datagrok-libraries/bio/src/rdkit-api';
5
+
4
6
  export async function getMacroMol(monomers: any[][]): Promise<string[]> {
5
7
  let result: string[] = [];
6
8
  const moduleRdkit = await grok.functions.call('Chem:getRdKitModule');
@@ -6,9 +6,11 @@ import {UnknownSeqPalette, UnknownSeqPalettes} from '@datagrok-libraries/bio/src
6
6
  import {SplitterFunc, WebLogo} from '@datagrok-libraries/bio/src/viewers/web-logo';
7
7
  import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
8
8
  import * as ui from 'datagrok-api/ui';
9
+ import {printLeftOrCentered} from '@datagrok-libraries/bio/src/utils/cell-renderer';
9
10
 
10
11
  const undefinedColor = 'rgb(100,100,100)';
11
- const grayColor = '#808080';
12
+ const monomerToShortFunction: (amino: string, maxLengthOfMonomer: number) => string = WebLogo.monomerToShort;
13
+ const gapRenderer = 5;
12
14
 
13
15
  function getPalleteByType(paletteType: string): SeqPalette {
14
16
  switch (paletteType) {
@@ -44,81 +46,6 @@ export function processSequence(subParts: string[]): [string[], boolean] {
44
46
  }
45
47
 
46
48
 
47
- /**
48
- * A function that prints a string aligned to left or centered.
49
- *
50
- * @param {number} x x coordinate.
51
- * @param {number} y y coordinate.
52
- * @param {number} w Width.
53
- * @param {number} h Height.
54
- * @param {CanvasRenderingContext2D} g Canvas rendering context.
55
- * @param {string} s String to print.
56
- * @param {string} [color=undefinedColor] String color.
57
- * @param {number} [pivot=0] Pirvot.
58
- * @param {boolean} [left=false] Is left aligned.
59
- * @param {number} [transparencyRate=0.0] Transparency rate where 1.0 is fully transparent
60
- * @param {string} [separator=''] Is separator for sequence.
61
- * @param {boolean} [last=false] Is checker if element last or not.
62
- * @return {number} x coordinate to start printing at.
63
- */
64
- export function printLeftOrCentered(
65
- x: number, y: number, w: number, h: number,
66
- g: CanvasRenderingContext2D, s: string, color = undefinedColor,
67
- pivot: number = 0, left = false, transparencyRate: number = 1.0,
68
- separator: string = '', last: boolean = false, drawStyle: string = 'classic', maxWord: any = {}, maxWordIdx: number = 0, gridCell: any = {}): number {
69
- g.textAlign = 'start';
70
- const colorPart = s.substring(0);
71
- let grayPart = last ? '' : separator;
72
- if (drawStyle === 'msa') {
73
- grayPart = '';
74
- }
75
-
76
- let textSize: any = g.measureText(colorPart + grayPart);
77
- const indent = 5;
78
-
79
- let maxColorTextSize = g.measureText(colorPart).width;
80
- let colorTextSize = g.measureText(colorPart).width;
81
- const dy = (textSize.fontBoundingBoxAscent + textSize.fontBoundingBoxDescent) / 2;
82
- textSize = textSize.width;
83
- if (drawStyle === 'msa') {
84
- maxColorTextSize = maxWord[maxWordIdx];
85
- textSize = maxWord[maxWordIdx];
86
- if (maxColorTextSize > maxWord) {
87
- maxWord[maxWordIdx] = maxColorTextSize;
88
- gridCell.cell.column.temp = maxWord;
89
- }
90
- if (maxWordIdx > (maxWord['bio-maxIndex'] ?? 0)) {
91
- maxWord['bio-maxIndex'] = maxWordIdx;
92
- gridCell.cell.column.temp = maxWord;
93
- }
94
- }
95
-
96
- function draw(dx1: number, dx2: number): void {
97
- g.fillStyle = color;
98
- g.globalAlpha = transparencyRate;
99
- if (drawStyle === 'classic') {
100
- g.fillText(colorPart, x + dx1, y + dy);
101
- g.fillStyle = grayColor;
102
- g.fillText(grayPart, x + dx2, y + dy);
103
- }
104
- if (drawStyle === 'msa') {
105
- g.fillStyle = color;
106
- g.fillText(colorPart, x + dx1 + ((maxWord[maxWordIdx] - colorTextSize) / 2), y + dy);
107
- }
108
- }
109
-
110
- if (left || textSize > w) {
111
- draw(indent, indent + maxColorTextSize);
112
- return x + maxColorTextSize + g.measureText(grayPart).width;
113
-
114
- } else {
115
- const dx = (w - textSize) / 2;
116
- draw(dx, dx + maxColorTextSize);
117
- return x + dx + maxColorTextSize;
118
- }
119
- }
120
-
121
-
122
49
  export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
123
50
  get name(): string { return 'sequence'; }
124
51
 
@@ -133,12 +60,9 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
133
60
  return;
134
61
  }
135
62
  const maxLengthWordsSum = gridCell.cell.column.temp['bio-sum-maxLengthWords'];
136
- if (maxLengthWordsSum == null) {
137
- gridCell.cell.column.setTag('.calculatedCellRender', 'unexist');
138
- }
139
63
  const maxIndex = gridCell.cell.column.temp['bio-maxIndex'];
140
64
  //@ts-ignore
141
- const argsX = e.layerX - gridCell.gridColumn.left - ((gridCell.bounds.x<0) ? gridCell.bounds.x : 0);
65
+ const argsX = e.layerX - gridCell.gridColumn.left - ((gridCell.bounds.x < 0) ? gridCell.bounds.x : 0);
142
66
  let left = 0;
143
67
  let right = maxIndex;
144
68
  let found = false;
@@ -203,23 +127,31 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
203
127
  const separator = gridCell.cell.column.getTag('separator') ?? '';
204
128
  const splitterFunc: SplitterFunc = WebLogo.getSplitter(units, separator);
205
129
 
206
- const columns = gridCell.cell.column.categories;
207
- let monomerToShortFunction: (amino: string, maxLengthOfMonomer: number) => string = WebLogo.monomerToShort;
208
- let maxLengthOfMonomer = 8;
130
+
131
+ const maxLengthOfMonomer = 8;
209
132
 
210
133
  let maxLengthWords: any = {};
211
134
  if (gridCell.cell.column.getTag('.calculatedCellRender') !== 'exist') {
212
- for (let i = 0; i < columns.length; i++) {
213
- let subParts: string[] = splitterFunc(columns[i]);
135
+ let samples = 0;
136
+ while (samples < Math.max(Math.min(gridCell.cell.column.length, 100), gridCell.cell.column.length / 100)) {
137
+ let column = gridCell.cell.column.get(samples);
138
+ let subParts: string[] = splitterFunc(column);
214
139
  subParts.forEach((amino, index) => {
215
- let textSizeWidth = g.measureText(monomerToShortFunction(amino, maxLengthOfMonomer));
216
- if (textSizeWidth.width > (maxLengthWords[index] ?? 0)) {
217
- maxLengthWords[index] = textSizeWidth.width;
140
+ let textSize = monomerToShortFunction(amino, maxLengthOfMonomer).length * 7 + gapRenderer;
141
+ if (textSize > (maxLengthWords[index] ?? 0)) {
142
+ maxLengthWords[index] = textSize;
218
143
  }
219
144
  if (index > (maxLengthWords['bio-maxIndex'] ?? 0)) {
220
145
  maxLengthWords['bio-maxIndex'] = index;
221
146
  }
222
147
  });
148
+ samples += 1;
149
+ }
150
+ let minLength = 3 * 7;
151
+ for (let i = 0; i <= maxLengthWords['bio-maxIndex']; i++) {
152
+ if (maxLengthWords[i] < minLength) {
153
+ maxLengthWords[i] = minLength;
154
+ }
223
155
  }
224
156
  let maxLengthWordSum: any = {};
225
157
  maxLengthWordSum[0] = maxLengthWords[0];
@@ -1,4 +1,4 @@
1
- import {IDrawTooltipParams} from '@datagrok-libraries/ml/src/viewers/activity-cliffs';
1
+ import {ITooltipAndPanelParams} from '@datagrok-libraries/ml/src/viewers/activity-cliffs';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
  import * as ui from 'datagrok-api/ui';
4
4
  import {getSimilarityFromDistance} from '@datagrok-libraries/utils/src/similarity-metrics';
@@ -12,25 +12,9 @@ export async function sequenceGetSimilarities(col: DG.Column, seq: string): Prom
12
12
  return DG.Column.fromList(DG.COLUMN_TYPE.FLOAT, 'distances', distances);
13
13
  }
14
14
 
15
- export function drawTooltip(params: IDrawTooltipParams) {
16
- params.tooltips[params.line.id] = ui.divH([]);
17
- const columnNames = ui.divV([
18
- ui.divText('sequense'),
19
- ui.divText(params.activity.name),
20
- ]);
21
- columnNames.style.fontWeight = 'bold';
22
- columnNames.style.display = 'flex';
23
- columnNames.style.justifyContent = 'space-between';
24
- params.tooltips[params.line.id].append(columnNames);
25
- params.line.mols.forEach((mol: number) => {
26
- const seq = ui.divText(params.df.get(params.seqCol.name, mol));
27
- const activity = ui.divText(params.df.get(params.activity.name, mol).toFixed(2));
28
- activity.style.display = 'flex';
29
- activity.style.justifyContent = 'left';
30
- activity.style.paddingLeft = '30px';
31
- params.tooltips[params.line.id].append(ui.divV([
32
- seq,
33
- activity,
34
- ], {style: {paddingLeft: '5px'}}));
15
+ export function drawSequences(params: ITooltipAndPanelParams) {
16
+ params.line.mols.forEach((mol: number, index: number) => {
17
+ ui.empty(params.hosts[index]);
18
+ params.hosts[index].append(ui.divText(params.seqCol.get(mol)));
35
19
  });
36
20
  }
@@ -22,7 +22,7 @@ export async function representationsWidget(macroMolecule: DG.Cell, monomersLibO
22
22
  const atomicCodes = getMolfilesFromSingleSeq(macroMolecule, monomersLibObject);
23
23
  const result = await getMacroMol(atomicCodes!);
24
24
  const molBlock2D = result[0];
25
- molBlock3D = (await grok.functions.call('Bio:Embed', {molBlock2D})) as string;
25
+ molBlock3D = (await grok.functions.call('Bio:Embed', {molBlock2D})) as unknown as string;
26
26
  } catch (e) {
27
27
  console.warn(e);
28
28
  }
@@ -1,4 +1,4 @@
1
- <html><head><meta charset="utf-8"/><title>Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=dc07f068a0b2. Commit cdad4cfb.</title><style type="text/css">html,
1
+ <html><head><meta charset="utf-8"/><title>Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=fe2f9610d4ed. Commit cdfe422f.</title><style type="text/css">html,
2
2
  body {
3
3
  font-family: Arial, Helvetica, sans-serif;
4
4
  font-size: 1rem;
@@ -229,13 +229,7 @@ header {
229
229
  font-size: 1rem;
230
230
  padding: 0 0.5rem;
231
231
  }
232
- </style></head><body><div id="jesthtml-content"><header><h1 id="title">Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=dc07f068a0b2. Commit cdad4cfb.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-08-22 08:54:42</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts</div><div class="suite-time warn">251.573s</div></div><div class="suite-tests"><div class="test-result failed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">failed</div><div class="test-duration">237.85s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: Test result : Failed : Bio.detectors.samplesHelmCsvHELM : Error: Expected "HELM", got "helm"
233
- Test result : Failed : Bio.detectors.samplesTestHelmPositiveHelmString : Error: Expected "HELM", got "helm"
234
-
235
- at /home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts:67:20
236
- at Generator.next (&lt;anonymous&gt;)
237
- at fulfilled (/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts:31:58)
238
- at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/Bio/src/__jest__/test-node.ts:63:11)
232
+ </style></head><body><div id="jesthtml-content"><header><h1 id="title">Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=fe2f9610d4ed. Commit cdfe422f.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-09-01 07:04:31</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts</div><div class="suite-time warn">46.104s</div></div><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">passed</div><div class="test-duration">27.903s</div></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/Bio/src/__jest__/test-node.ts:63:11)
239
233
  at Generator.next (&lt;anonymous&gt;)
240
234
  at fulfilled (/home/runner/work/public/public/packages/Bio/src/__jest__/test-node.ts:28:58)
241
235
  at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Using web root: http://localhost:8080</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts:40:11
@@ -248,6 +242,7 @@ Test result : Failed : Bio.detectors.samplesTestHelmPositiveHelmString : Error:
248
242
  at new Promise (&lt;anonymous&gt;)</pre><pre class="suite-consolelog-item-message">Testing Bio package</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts:65:11
249
243
  at Generator.next (&lt;anonymous&gt;)
250
244
  at fulfilled (/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts:31:58)
245
+ at runMicrotasks (&lt;anonymous&gt;)
251
246
  at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Test result : Success : Bio.WebLogo.testGetStats : OK
252
247
  Test result : Success : Bio.WebLogo.testGetAlphabetSimilarity : OK
253
248
  Test result : Success : Bio.WebLogo.testPickupPaletteN1 : OK
@@ -289,9 +284,11 @@ Test result : Success : Bio.detectors.samplesMsaComplexUn : OK
289
284
  Test result : Success : Bio.detectors.samplesMsaComplexNegativeActivity : OK
290
285
  Test result : Success : Bio.detectors.samplesIdCsvNegativeID : OK
291
286
  Test result : Success : Bio.detectors.samplesSarSmallCsvNegativeSmiles : OK
287
+ Test result : Success : Bio.detectors.samplesHelmCsvHELM : OK
292
288
  Test result : Success : Bio.detectors.samplesHelmCsvNegativeActivity : OK
293
289
  Test result : Success : Bio.detectors.samplesTestHelmNegativeID : OK
294
290
  Test result : Success : Bio.detectors.samplesTestHelmNegativeTestType : OK
291
+ Test result : Success : Bio.detectors.samplesTestHelmPositiveHelmString : OK
295
292
  Test result : Success : Bio.detectors.samplesTestHelmNegativeValid : OK
296
293
  Test result : Success : Bio.detectors.samplesTestHelmNegativeMolWeight : OK
297
294
  Test result : Success : Bio.detectors.samplesTestHelmNegativeMolFormula : OK
package/webpack.config.js CHANGED
@@ -39,6 +39,7 @@ module.exports = {
39
39
  'rxjs/operators': 'rxjs.operators',
40
40
  'cash-dom': '$',
41
41
  'dayjs': 'dayjs',
42
+ 'wu': 'wu',
42
43
  },
43
44
  output: {
44
45
  filename: '[name].js',