@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/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "Aleksandr Tanas",
6
6
  "email": "atanas@datagrok.ai"
7
7
  },
8
- "version": "2.12.17",
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.0",
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.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",
@@ -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.instance;
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
- _package.logger.debug('Bio: initBio(), started');
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 () => { await MonomerLibManager.instance.loadLibraries(); })(),
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 MonomerLibManager.instance.getBioLib();
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 sequenceToMolfile(table, seqCol, nonlinear);
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 libFileEventManager = MonomerLibFileEventManager.getInstance();
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: 282}, tgt: {pos: null}},
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');
@@ -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 {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
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/index';
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 {
@@ -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/index';
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, getBioLib} from '../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(grid: DG.Grid | null, g: CanvasRenderingContext2D, x: number, w: number, dpr: number): number {
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 = seqColTemp.props.monomerLib!;
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 [gridCol, _tc, temp] =
168
+ const [_gc, _tc, temp] =
174
169
  getGridCellRendererBack<string, MonomerPlacer>(gridCell);
175
- let seqColTemp: MonomerPlacer = temp['rendererBack'];
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
- const dpr = window.devicePixelRatio;
207
- const grid = gridCell.gridRow !== -1 ? gridCell.grid : null;
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 splitLimit = w / 5;
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
- for (let posIdx: number = 0; posIdx < subParts.length; ++posIdx) {
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: string = err instanceof Error ? err.message : !!err ? err.toString() : 'Error \'undefined\'';
263
- _package.logger.error(`Bio: MacromoleculeSequenceCellRenderer.render() error: ${errMsg}`);
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 {_package} from '../../../package';
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 {MonomerLibManager} from '../../monomer-lib/lib-manager';
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 monomerLib = MonomerLibManager.instance.getBioLib();
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(helmString: string, private rdKitModule: RDModule) {
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(monomerSymbol, monomerIdx, this.helm, shift, this.rdKitModule);
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 mw = new MonomerWorks(getMonomerLibHelper().getBioLib());
35
- const monomerType: string = (alphabet === ALPHABET.DNA || alphabet === ALPHABET.RNA) ? 'RNA' :
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(monomerType, monomerName);
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