@datagrok/helm 2.1.29 → 2.1.31

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.
@@ -2,7 +2,7 @@ HELM,Activity
2
2
  PEPTIDE1{meI.missed2.Aca.N.T.dE.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.D-Orn.D-aThr.Phe_4Me}$$$$,5.307510973968128
3
3
  PEPTIDE1{meI.hHis.Aca.Cys_SEt.T.dK.Thr_PO3H2.Aca.Tyr_PO3H2.D-Chg.dV.Phe_ab-dehydro.N.D-Orn.D-aThr.Phe_4Me}$$$$,5.723876853431544
4
4
  PEPTIDE1{missed1.hHis.Aca.Cys_SEt.T.dK.Thr_PO3H2.Aca.Tyr_PO3H2.D-Chg.dV.Thr_PO3H2.N.D-Orn.D-aThr.Phe_4Me}$$$$,5.185811246022437
5
- PEPTIDE1{meI.hHis.Aca.m0.T.dK.Thr_PO3H2.Aca.Tyr_PO3H2.D-Chg.dV.Thr_PO3H2.N.D-Orn.D-aThr.Phe_4Me}$$$$,6.223502390804369
5
+ PEPTIDE1{meI.m0.Aca.m1.T.m2.m3.Aca.Tyr_PO3H2.D-Chg.dV.Thr_PO3H2.N.D-Orn.D-aThr.Phe_4Me}$$$$,6.223502390804369
6
6
  ,3.8459123763832412
7
7
  PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_Bn.dV.E.N.dV.Phe_4Me}$$$$,3.27920438824657
8
8
  PEPTIDE1{meI.hHis.Aca.N.T.dK.Thr_PO3H2.Aca.D-Tyr_Et.Aze.dV.E.N.dV.Phe_4Me}$$$$,2.105852152992568
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/helm",
3
3
  "friendlyName": "Helm",
4
- "version": "2.1.29",
4
+ "version": "2.1.31",
5
5
  "author": {
6
6
  "name": "Oleksandra Serhiienko",
7
7
  "email": "oserhiienko@datagrok.ai"
@@ -15,9 +15,9 @@
15
15
  "helm/JSDraw/Pistoia.HELM-uncompressed.js"
16
16
  ],
17
17
  "dependencies": {
18
- "@datagrok-libraries/bio": "^5.39.24",
19
- "@datagrok-libraries/chem-meta": "^1.2.1",
20
- "@datagrok-libraries/utils": "^4.1.42",
18
+ "@datagrok-libraries/bio": "^5.40.0",
19
+ "@datagrok-libraries/chem-meta": "^1.2.3",
20
+ "@datagrok-libraries/utils": "^4.1.45",
21
21
  "cash-dom": "^8.1.1",
22
22
  "datagrok-api": "^1.17.0",
23
23
  "dayjs": "^1.10.6",
@@ -37,7 +37,8 @@
37
37
  "@typescript-eslint/parser": "^5.11.0",
38
38
  "eslint": "^8.18.0",
39
39
  "eslint-config-google": "^0.14.0",
40
- "@datagrok/bio": "^2.11.8"
40
+ "@datagrok/bio": "^2.12.0",
41
+ "@datagrok/chem": "^1.9.0"
41
42
  },
42
43
  "scripts": {
43
44
  "link-all": "npm link @datagrok-libraries/chem-meta datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
@@ -7,7 +7,7 @@ import wu from 'wu';
7
7
  import {printLeftOrCentered} from '@datagrok-libraries/bio/src/utils/cell-renderer';
8
8
  import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
9
9
 
10
- import {findMonomers, parseHelm} from './utils';
10
+ import {findMonomers, parseHelm, removeGapsFromHelm} from './utils';
11
11
  import {IEditor, HelmMonomerPlacer, IEditorMolAtom, ISeqMonomer} from './helm-monomer-placer';
12
12
  import {IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
13
13
 
@@ -20,11 +20,6 @@ const enum tempTAGS {
20
20
  helmPlacer = 'bio-helmPlacer',
21
21
  }
22
22
 
23
- // Global flag is for replaceAll
24
- const helmGapStartRe = /\{(\*\.)+/g;
25
- const helmGapIntRe = /\.(\*\.)+/g;
26
- const helmGapEndRe = /(\.\*)+\}/g;
27
-
28
23
  function getSeqMonomerFromHelm(
29
24
  helmPrefix: string, symbol: string, monomerLib: IMonomerLib
30
25
  ): ISeqMonomer {
@@ -42,16 +37,16 @@ function getSeqMonomerFromHelmAtom(atom: IEditorMolAtom): ISeqMonomer {
42
37
  let polymerType: string | undefined = undefined;
43
38
  // @ts-ignore
44
39
  switch (atom.bio.type) {
45
- case 'HELM_BASE':
46
- case 'HELM_SUGAR': // r - ribose, d - deoxyribose
47
- case 'HELM_LINKER': // p - phosphate
48
- polymerType = 'RNA';
49
- break;
50
- case 'HELM_AA':
51
- polymerType = 'PEPTIDE';
52
- break;
53
- default:
54
- polymerType = 'PEPTIDE';
40
+ case 'HELM_BASE':
41
+ case 'HELM_SUGAR': // r - ribose, d - deoxyribose
42
+ case 'HELM_LINKER': // p - phosphate
43
+ polymerType = 'RNA';
44
+ break;
45
+ case 'HELM_AA':
46
+ polymerType = 'PEPTIDE';
47
+ break;
48
+ default:
49
+ polymerType = 'PEPTIDE';
55
50
  }
56
51
  return {symbol: atom.elem, polymerType: polymerType};
57
52
  }
@@ -163,63 +158,63 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
163
158
  try { tableCol = gridCell.tableColumn; } catch { }
164
159
  if (!tableCol) return;
165
160
 
166
- const argsX = e.offsetX - gridCell.bounds.x;
167
- const argsY = e.offsetY - gridCell.bounds.y;
161
+ /** {@link gridCell}.bounds */ const gcb = gridCell.bounds;
162
+ const argsX = e.offsetX - gcb.x;
163
+ const argsY = e.offsetY - gcb.y;
168
164
 
169
165
  const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
170
166
  const editor: IEditor | null = helmPlacer.getEditor(gridCell.tableRowIndex!);
171
- const seqMonomer: ISeqMonomer | null = editor ? getHoveredMonomerFromEditor(argsX, argsY, gridCell, editor) :
172
- getHoveredMonomerFallback(argsX, argsY, gridCell, helmPlacer);
173
- if (!seqMonomer) {
174
- ui.tooltip.hide();
175
- return;
167
+ let seqMonomer: ISeqMonomer | null;
168
+ let missedMonomers: Set<string> = new Set<string>(); // of .size = 0
169
+ if (editor)
170
+ seqMonomer = getHoveredMonomerFromEditor(argsX, argsY, gridCell, editor);
171
+ else {
172
+ const seq: string = !gridCell.cell.value ? '' : removeGapsFromHelm(gridCell.cell.value as string);
173
+ const monomerList = parseHelm(seq);
174
+ missedMonomers = findMonomers(monomerList);
175
+ const parsedMonomers = new Set<string>(monomerList);
176
+ seqMonomer = getHoveredMonomerFallback(argsX, argsY, gridCell, helmPlacer);
177
+ if (seqMonomer && !parsedMonomers.has(seqMonomer.symbol)) seqMonomer = null;
178
+ if (seqMonomer) {
179
+ const textSize = helmPlacer.monomerTextSizeMap[seqMonomer.symbol];
180
+ if (textSize) {
181
+ const textBaseLine = gcb.height / 2 -
182
+ (textSize.fontBoundingBoxAscent + textSize.fontBoundingBoxDescent) / 2 + 1;
183
+ const textTop = textBaseLine - textSize.fontBoundingBoxAscent;
184
+ const textBottom = textBaseLine + textSize.fontBoundingBoxDescent;
185
+ if (argsY < textTop || textBottom < argsY) seqMonomer = null;
186
+ }
187
+ }
176
188
  }
177
189
 
178
- const seq: string = !gridCell.cell.value ? '' : gridCell.cell.value
179
- .replaceAll(helmGapStartRe, '{').replaceAll(helmGapIntRe, '.').replaceAll(helmGapEndRe, '}')
180
- .replace('{*}', '{}');
181
- const monomerList = parseHelm(seq);
182
- const missedMonomers = findMonomers(monomerList);
183
-
184
- if (missedMonomers.has(seqMonomer.symbol)) {
185
- ui.tooltip.show(ui.divV([
186
- ui.divText(`Monomer ${seqMonomer.symbol} not found.`),
187
- ui.divText('Open the Context Panel, then expand Manage Libraries'),
188
- ]), e.x + 16, e.y + 16);
189
- } else {
190
- const monomer = helmPlacer.getMonomer(seqMonomer);
191
- if (monomer) {
192
- const options = {autoCrop: true, autoCropMargin: 0, suppressChiralText: true};
193
- const monomerSvg = grok.chem.svgMol(monomer.smiles, undefined, undefined, options);
190
+ if (seqMonomer) {
191
+ if (!missedMonomers.has(seqMonomer.symbol)) {
192
+ const monomer = helmPlacer.getMonomer(seqMonomer);
193
+ if (monomer) {
194
+ const options = {autoCrop: true, autoCropMargin: 0, suppressChiralText: true};
195
+ const monomerSvg = grok.chem.svgMol(monomer.smiles, undefined, undefined, options);
196
+ ui.tooltip.show(ui.divV([
197
+ ui.divText(seqMonomer.symbol),
198
+ monomerSvg,
199
+ ]), e.x + 16, e.y + 16);
200
+ }
201
+ } else {
194
202
  ui.tooltip.show(ui.divV([
195
- ui.divText(seqMonomer.symbol),
196
- monomerSvg,
203
+ ui.divText(`Monomer '${seqMonomer.symbol}' not found.`),
204
+ ui.divText('Open the Context Panel, then expand Manage Libraries'),
197
205
  ]), e.x + 16, e.y + 16);
198
206
  }
207
+ } else if (missedMonomers.size == 0) {
208
+ ui.tooltip.hide();
209
+ return;
210
+ } else { // seqMonomer == null && missedMonomers.size > 0
211
+ const mmStrList = wu(missedMonomers.keys()).toArray().sort()
212
+ .filter((_, i) => i < 3);
213
+ const missedMonomersStr = mmStrList.join(', ') + (missedMonomers.size > 3 ? ', ...' : '');
214
+ ui.tooltip.show(ui.divV([ui.divText('Monomers missed in monomer libraries:'),
215
+ ui.divText(missedMonomersStr)
216
+ ]), e.x + 16, e.y + 16);
199
217
  }
200
-
201
- // const tooltipMessage: HTMLElement[] = [];
202
- // for (const [part, partI] of wu.enumerate(allParts)) {
203
- // if (missedMonomers.has(part)) {
204
- // tooltipMessage[partI] = ui.divV([
205
- // ui.divText(`Monomer ${allParts[partI]} not found.`),
206
- // ui.divText('Open the Context Panel, then expand Manage Libraries')
207
- // ]);
208
- // } else if (monomers.has(part)) {
209
- // const elList = [ui.div(part)];
210
- // const monomer = helmPlacer.getMonomer(part);
211
- // if (monomer) {
212
- // const options = {autoCrop: true, autoCropMargin: 0, suppressChiralText: true};
213
- // const monomerSvg = grok.chem.svgMol(monomer.smiles, undefined, undefined, options);
214
- // elList.push(monomerSvg);
215
- // }
216
- // tooltipMessage[partI] = ui.divV(elList);
217
- // }
218
- // }
219
- //
220
- // (((tooltipMessage[left]?.childNodes.length ?? 0) > 0)) ?
221
- // ui.tooltip.show(tooltipMessage[left], e.x + 16, e.y + 16) :
222
- // ui.tooltip.hide();
223
218
  } catch (err: any) {
224
219
  const errMsg: string = errorToConsole(err);
225
220
  console.error('Helm: HelmCellRenderer.onMouseMove() error:\n' + errMsg);
@@ -245,9 +240,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
245
240
  const monomerColor: string = '#404040';
246
241
  const frameColor: string = '#C0C0C0';
247
242
 
248
- const seq: string = !gridCell.cell.value ? '' : gridCell.cell.value
249
- .replaceAll(helmGapStartRe, '{').replaceAll(helmGapIntRe, '.').replaceAll(helmGapEndRe, '}')
250
- .replace('{*}', '{}');
243
+ const seq: string = !gridCell.cell.value ? '' : removeGapsFromHelm(gridCell.cell.value);
251
244
  const monomerList = parseHelm(seq);
252
245
  const monomers: Set<string> = new Set<string>(monomerList);
253
246
  const missedMonomers: Set<string> = findMonomers(monomerList);
@@ -289,7 +282,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
289
282
  g.transform(1, 0, 0, 1, x, y);
290
283
  g.font = '12px monospace';
291
284
  g.textBaseline = 'top';
292
- const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
285
+ const [allParts, _lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
293
286
 
294
287
  for (let i = 0; i < allParts.length; ++i) {
295
288
  const part: string = allParts[i];
@@ -299,7 +292,9 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
299
292
  monomers.has(part) ? monomerColor :
300
293
  frameColor;
301
294
  g.fillStyle = color;
302
- printLeftOrCentered(sumLengths[i], 0, w, h, g, allParts[i], color, 0, true, 1.0);
295
+ printLeftOrCentered(sumLengths[i], 0, w, h, g, allParts[i], color, 0, true, 1.0,
296
+ undefined, undefined, undefined, undefined, undefined,
297
+ undefined, undefined, undefined, helmPlacer.monomerTextSizeMap);
303
298
  }
304
299
  }
305
300
  } finally {
@@ -49,6 +49,7 @@ export class HelmMonomerPlacer {
49
49
 
50
50
  public monomerCharWidth: number = 7;
51
51
  public leftPadding: number = 5;
52
+ public monomerTextSizeMap: { [p: string]: TextMetrics } = {};
52
53
 
53
54
  constructor(public readonly col: DG.Column<string>) {
54
55
  this.col.dataFrame.onDataChanged.subscribe();
package/src/package.ts CHANGED
@@ -7,7 +7,7 @@ import $ from 'cash-dom';
7
7
 
8
8
  import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
9
9
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
10
- import {GapSymbols, UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
10
+ import {GapOriginals, SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
11
11
  import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
12
12
  import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
13
13
 
@@ -156,17 +156,17 @@ export function helmCellRenderer(): HelmCellRenderer {
156
156
  return new HelmCellRenderer();
157
157
  }
158
158
 
159
- function checkMonomersAndOpenWebEditor(cell?: DG.Cell, value?: string, units?: string) {
159
+ function checkMonomersAndOpenWebEditor(cell: DG.Cell, value?: string, units?: string) {
160
160
  const cellValue: string = !!cell && units === undefined ? cell.value : value;
161
161
  const monomerList: string[] = parseHelm(cellValue);
162
- const monomers = findMonomers(monomerList);
163
- if (monomers.size === 0)
162
+ const missedMonomerSet = findMonomers(monomerList);
163
+ if (missedMonomerSet.size === 0)
164
164
  webEditor(cell, value, units);
165
- else if (monomers.size === 1 && monomers.has(GapSymbols[NOTATION.HELM]))
166
- grok.shell.warning(`WebEditor doesn't support Helm with gaps '${GapSymbols[NOTATION.HELM]}'.`);
165
+ else if (missedMonomerSet.size === 1 && missedMonomerSet.has(GapOriginals[NOTATION.HELM]))
166
+ grok.shell.warning(`WebEditor doesn't support Helm with gaps '${GapOriginals[NOTATION.HELM]}'.`);
167
167
  else {
168
168
  grok.shell.warning(
169
- `Monomers ${Array.from(monomers).map((m) => `'${m}'`).join(', ')} are absent! <br/>` +
169
+ `Monomers ${Array.from(missedMonomerSet).map((m) => `'${m}'`).join(', ')} are absent! <br/>` +
170
170
  `Please, upload the monomer library! <br/>` +
171
171
  `<a href="https://datagrok.ai/help/domains/bio/macromolecules" target="_blank">Learn more</a>`);
172
172
  }
@@ -187,11 +187,11 @@ export function editMoleculeCell(cell: DG.GridCell): void {
187
187
  export function openEditor(mol: string): void {
188
188
  const df = grok.shell.tv.grid.dataFrame;
189
189
  const col = df.columns.bySemType('Macromolecule')!;
190
- const colUh = UnitsHandler.getOrCreate(col);
190
+ const colSh = SeqHandler.forColumn(col);
191
191
  const colUnits = col.getTag(DG.TAGS.UNITS);
192
192
  if (colUnits === NOTATION.HELM)
193
193
  checkMonomersAndOpenWebEditor(df.currentCell, undefined, undefined);
194
- const convert = colUh.getConverter(NOTATION.HELM);
194
+ const convert = colSh.getConverter(NOTATION.HELM);
195
195
  const helmMol = convert(mol);
196
196
  checkMonomersAndOpenWebEditor(df.currentCell, helmMol, col.getTag(DG.TAGS.UNITS));
197
197
  }
@@ -204,11 +204,13 @@ export function propertiesWidget(sequence: DG.SemanticValue): DG.Widget {
204
204
  return getPropertiesWidget(sequence);
205
205
  }
206
206
 
207
- function webEditor(cell?: DG.Cell, value?: string, units?: string) {
207
+ function webEditor(cell: DG.Cell, value?: string, units?: string) {
208
208
  const view = ui.div();
209
- const df = grok.shell.tv.grid.dataFrame;
210
- const col = df.columns.bySemType('Macromolecule')!;
211
- const uh = UnitsHandler.getOrCreate(col);
209
+ // const df = grok.shell.tv.grid.dataFrame;
210
+ // const col = df.columns.bySemType('Macromolecule')!;
211
+ const col = cell.column;
212
+ const sh = SeqHandler.forColumn(col);
213
+ const rowIdx = cell.rowIndex;
212
214
  // @ts-ignore
213
215
  org.helm.webeditor.MolViewer.molscale = 0.8;
214
216
  // @ts-ignore
@@ -244,13 +246,13 @@ function webEditor(cell?: DG.Cell, value?: string, units?: string) {
244
246
  ui.dialog({showHeader: false, showFooter: true})
245
247
  .add(view)
246
248
  .onOK(() => {
247
- const helmValue = app.canvas.getHelm(true).replace(/<\/span>/g, '')
249
+ const helmValue: string = app.canvas.getHelm(true).replace(/<\/span>/g, '')
248
250
  .replace(/<span style='background:#bbf;'>/g, '');
249
251
  if (!!cell) {
250
252
  if (units === undefined)
251
253
  cell.value = helmValue;
252
254
  else {
253
- const convertedRes = uh.convertHelmToFastaSeparator(helmValue, units!);
255
+ const convertedRes = sh.convertHelmToFastaSeparator(helmValue, units!, sh.separator);
254
256
  cell.value = convertedRes;
255
257
  }
256
258
  }
@@ -3,9 +3,10 @@ import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {after, before, category, delay, expect, expectObject, test} from '@datagrok-libraries/utils/src/test';
6
+ import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
6
7
  import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
7
8
  import {
8
- getUserLibSettings, LibSettings, setUserLibSettings, setUserLibSettingsForTests
9
+ getUserLibSettings, setUserLibSettings, setUserLibSettingsForTests
9
10
  } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
10
11
 
11
12
  import {findMonomers, parseHelm} from '../utils';
@@ -15,7 +16,7 @@ import {findMonomers, parseHelm} from '../utils';
15
16
  category('findMonomers', () => {
16
17
  let monomerLibHelper: IMonomerLibHelper;
17
18
  /** Backup actual user's monomer libraries settings */
18
- let userLibSettings: LibSettings;
19
+ let userLibSettings: UserLibSettings;
19
20
 
20
21
  before(async () => {
21
22
  monomerLibHelper = await getMonomerLibHelper();
@@ -4,8 +4,9 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {after, before, category, delay, expect, test, expectArray, testEvent} from '@datagrok-libraries/utils/src/test';
6
6
  import {
7
- getUserLibSettings, LibSettings, setUserLibSettings, setUserLibSettingsForTests
7
+ getUserLibSettings, setUserLibSettings, setUserLibSettingsForTests
8
8
  } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
9
+ import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
9
10
  import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
10
11
  import {MolfileHandler} from '@datagrok-libraries/chem-meta/src/parsing-utils/molfile-handler';
11
12
  import {MolfileHandlerBase} from '@datagrok-libraries/chem-meta/src/parsing-utils/molfile-handler-base';
@@ -16,7 +17,7 @@ import {_package} from '../package-test';
16
17
 
17
18
  category('getMolfiles', () => {
18
19
  let monomerLibHelper: IMonomerLibHelper;
19
- let userLibSettings: LibSettings;
20
+ let userLibSettings: UserLibSettings;
20
21
 
21
22
  before(async () => {
22
23
  monomerLibHelper = await getMonomerLibHelper();
@@ -4,7 +4,7 @@ import * as grok from 'datagrok-api/grok';
4
4
 
5
5
  import {category, expect, expectObject, test} from '@datagrok-libraries/utils/src/test';
6
6
  import {ALPHABET, NOTATION, TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
7
- import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
7
+ import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
8
8
 
9
9
  import {getPropertiesDict} from '../widgets/properties-widget';
10
10
 
@@ -75,7 +75,7 @@ function testPropertiesDict(
75
75
  col.setTag(DG.TAGS.UNITS, units);
76
76
  if (separator) col.setTag(bioTAGS.separator, separator);
77
77
  if (alphabet) col.setTag(bioTAGS.alphabet, alphabet);
78
- const uh = UnitsHandler.getOrCreate(col);
78
+ const uh = SeqHandler.forColumn(col);
79
79
  const actPropDict = getPropertiesDict(seq, uh);
80
80
  expectObject(actPropDict, expPropDict);
81
81
  }
@@ -11,6 +11,16 @@ import {
11
11
  SDF_MONOMER_NAME
12
12
  } from '../constants';
13
13
 
14
+ // Global flag is for replaceAll
15
+ const helmGapStartRe = /\{(\*\.)+/g;
16
+ const helmGapIntRe = /\.(\*\.)+/g;
17
+ const helmGapEndRe = /(\.\*)+\}/g;
18
+
19
+ export function removeGapsFromHelm(srcHelm: string): string {
20
+ return srcHelm.replaceAll(helmGapStartRe, '{').replaceAll(helmGapIntRe, '.')
21
+ .replaceAll(helmGapEndRe, '}').replace('{*}', '{}');
22
+ }
23
+
14
24
  export function getParts(subParts: string[], s: string): string[] {
15
25
  const j = 0;
16
26
  const allParts: string[] = [];
@@ -226,14 +236,14 @@ function unescape(s: string) {
226
236
 
227
237
  return s.replace(/[\\]./g, function(m) {
228
238
  switch (m) {
229
- case '\\r':
230
- return '\r';
231
- case '\\n':
232
- return '\n';
233
- case '\\t':
234
- return '\t';
235
- default:
236
- return m.substring(1);
239
+ case '\\r':
240
+ return '\r';
241
+ case '\\n':
242
+ return '\n';
243
+ case '\\t':
244
+ return '\t';
245
+ default:
246
+ return m.substring(1);
237
247
  }
238
248
  });
239
249
  }
@@ -4,14 +4,15 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import $ from 'cash-dom';
6
6
 
7
- import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
7
+ import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
8
8
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
9
9
 
10
- export function getPropertiesDict(seq: string, uh: UnitsHandler): {} {
11
- const helmString = uh.isHelm() ? seq : uh.getConverter(NOTATION.HELM)(seq);
10
+ import {removeGapsFromHelm} from '../utils';
11
+
12
+ export function getPropertiesDict(seq: string, sh: SeqHandler): {} {
13
+ const helmString = sh.isHelm() ? seq : sh.getConverter(NOTATION.HELM)(seq);
12
14
  // Remove gap symbols for compatibility with WebEditor
13
- const helmString2 = helmString.replaceAll(/\.(\*\.)+/g, '.')
14
- .replaceAll(/\{(\*\.)+/g, '{').replaceAll(/(\.\*)+}/g, '}');
15
+ const helmString2 = removeGapsFromHelm(helmString);
15
16
 
16
17
  const host = ui.div([], {style: {width: '0', height: '0'}});
17
18
  document.documentElement.appendChild(host);
@@ -35,8 +36,8 @@ export function getPropertiesDict(seq: string, uh: UnitsHandler): {} {
35
36
 
36
37
 
37
38
  export function getPropertiesWidget(value: DG.SemanticValue): DG.Widget {
38
- const uh = UnitsHandler.getOrCreate(value.cell.column);
39
- const propDict = getPropertiesDict(value.value, uh);
39
+ const sh = SeqHandler.forColumn(value.cell.column);
40
+ const propDict = getPropertiesDict(value.value, sh);
40
41
  return new DG.Widget(
41
42
  ui.tableFromMap(propDict)
42
43
  );