@datagrok/helm 2.1.16 → 2.1.17

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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/helm",
3
3
  "friendlyName": "Helm",
4
- "version": "2.1.16",
4
+ "version": "2.1.17",
5
5
  "author": {
6
6
  "name": "Oleksandra Serhiienko",
7
7
  "email": "oserhiienko@datagrok.ai"
@@ -15,7 +15,7 @@
15
15
  "helm/JSDraw/Pistoia.HELM-uncompressed.js"
16
16
  ],
17
17
  "dependencies": {
18
- "@datagrok-libraries/bio": "^5.33.2",
18
+ "@datagrok-libraries/bio": "^5.38.0",
19
19
  "@datagrok-libraries/utils": "^4.0.17",
20
20
  "cash-dom": "^8.1.1",
21
21
  "datagrok-api": "^1.10.2",
@@ -60,11 +60,11 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
60
60
  if (argsX >= sumLengths[mid] && argsX <= sumLengths[mid + 1]) {
61
61
  left = mid;
62
62
  found = true;
63
- } else if (argsX < sumLengths[mid]) {
63
+ } else if (argsX < sumLengths[mid])
64
64
  right = mid - 1;
65
- } else if (argsX > sumLengths[mid + 1]) {
65
+ else if (argsX > sumLengths[mid + 1])
66
66
  left = mid + 1;
67
- }
67
+
68
68
  if (left == right)
69
69
  found = true;
70
70
 
@@ -73,7 +73,9 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
73
73
  }
74
74
  left = (argsX >= sumLengths[left]) ? left : left - 1; // correct left to between sumLengths
75
75
 
76
- const seq: string = gridCell.cell.value;
76
+ const seq: string = !gridCell.cell.value ? '' : gridCell.cell.value
77
+ .replaceAll(helmGapStartRe, '{').replaceAll(helmGapIntRe, '.').replaceAll(helmGapEndRe, '}')
78
+ .replace('{*}', '{}');
77
79
  const monomerList = parseHelm(seq);
78
80
  const monomers = new Set<string>(monomerList);
79
81
  const missedMonomers = findMonomers(monomerList);
@@ -121,15 +123,19 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
121
123
  const monomerColor: string = '#404040';
122
124
  const frameColor: string = '#C0C0C0';
123
125
 
124
- const seq = gridCell.cell.value;
126
+ const seq: string = !gridCell.cell.value ? '' : gridCell.cell.value
127
+ .replaceAll(helmGapStartRe, '{').replaceAll(helmGapIntRe, '.').replaceAll(helmGapEndRe, '}')
128
+ .replace('{*}', '{}');
125
129
  const monomerList = parseHelm(seq);
126
130
  const monomers: Set<string> = new Set<string>(monomerList);
127
131
  const missedMonomers: Set<string> = findMonomers(monomerList);
132
+ const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
128
133
 
129
134
  if (missedMonomers.size == 0) {
135
+ helmPlacer.skipCell(gridCell.tableRowIndex!);
130
136
  const host = ui.div([], {style: {width: `${w}px`, height: `${h}px`}});
131
137
  host.setAttribute('dataformat', 'helm');
132
- host.setAttribute('data', gridCell.cell.value);
138
+ host.setAttribute('data', seq /* gaps skipped */);
133
139
  gridCell.element = host;
134
140
  //@ts-ignore
135
141
  const canvas = new JSDraw2.Editor(host, {width: w, height: h, skin: 'w8', viewonly: true});
@@ -152,7 +158,6 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
152
158
  g.transform(1, 0, 0, 1, x, y);
153
159
  g.font = '12px monospace';
154
160
  g.textBaseline = 'top';
155
- const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
156
161
  const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
157
162
 
158
163
  for (let i = 0; i < allParts.length; ++i) {
@@ -25,13 +25,23 @@ export class HelmMonomerPlacer {
25
25
  constructor(public readonly col: DG.Column<string>) {
26
26
  this.col.dataFrame.onDataChanged.subscribe();
27
27
  this.monomerLib = getMonomerLib();
28
+ this.monomerLib.onChanged.subscribe(this.monomerLibOnChanged.bind(this));
29
+ }
30
+
31
+ public skipCell(rowIdx: number): void {
32
+ if (this._allPartsList === null)
33
+ this._allPartsList = new Array<string[] | null>(this.col.length).fill(null);
34
+ if (this._lengthsList === null)
35
+ this._lengthsList = new Array<number[] | null>(this.col.length).fill(null);
36
+
37
+ this._allPartsList[rowIdx] = [];
38
+ this._lengthsList[rowIdx] = [];
28
39
  }
29
40
 
30
41
  /** @param rowIdx Row index of the table {@link DG.DataFrame}, HelmMonomerPlacer is {@link DG.Column} based */
31
42
  public getCellAllPartsLengths(rowIdx: number): [string[], number[], number[]] {
32
43
  if (this._allPartsList === null)
33
44
  this._allPartsList = new Array<string[] | null>(this.col.length).fill(null);
34
-
35
45
  if (this._lengthsList === null)
36
46
  this._lengthsList = new Array<number[] | null>(this.col.length).fill(null);
37
47
 
@@ -45,12 +55,17 @@ export class HelmMonomerPlacer {
45
55
  }
46
56
 
47
57
  private getCellMonomerLengthsForSeq(rowIdx: number): [string[], number[]] {
48
- const allParts: string[] = this._allPartsList![rowIdx] = this.getAllParts(rowIdx);
49
- const lengths: number[] = this._lengthsList![rowIdx] = new Array<number>(allParts.length);
50
-
51
- for (const [part, partI] of wu.enumerate(allParts)) {
52
- const partWidth: number = part.length * this.monomerCharWidth;
53
- lengths[partI] = partWidth;
58
+ let allParts: string[] | null = this._allPartsList![rowIdx];
59
+ if (allParts === null)
60
+ allParts = this._allPartsList![rowIdx] = this.getAllParts(rowIdx);
61
+
62
+ let lengths: number[] | null = this._lengthsList![rowIdx];
63
+ if (lengths === null) {
64
+ lengths = this._lengthsList![rowIdx] = new Array<number>(allParts.length);
65
+ for (const [part, partI] of wu.enumerate(allParts)) {
66
+ const partWidth: number = part.length * this.monomerCharWidth;
67
+ lengths[partI] = partWidth;
68
+ }
54
69
  }
55
70
 
56
71
  return [allParts, lengths];
@@ -71,6 +86,14 @@ export class HelmMonomerPlacer {
71
86
  return res;
72
87
  }
73
88
 
89
+ // -- Handle events --
90
+
91
+ private monomerLibOnChanged(_value: any): void {
92
+ this._lengthsList = null;
93
+ this._allPartsList = null;
94
+ // TODO: Invalidate all grids of this.col.dataFrame
95
+ }
96
+
74
97
  public static getOrCreate(col: DG.Column<string>): HelmMonomerPlacer {
75
98
  if (!(Temps.helmMonomerPlacer in col.temp)) col.temp[Temps.helmMonomerPlacer] = new HelmMonomerPlacer(col);
76
99
  return col.temp[Temps.helmMonomerPlacer];
package/src/package.ts CHANGED
@@ -7,14 +7,15 @@ import {WebEditorMonomer, RGROUP_CAP_GROUP_NAME, RGROUP_LABEL, SMILES} from './c
7
7
  import {HelmWebEditor} from './helm-web-editor';
8
8
  import {HelmCellRenderer} from './cell-renderer';
9
9
  import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
10
- import {NotationConverter} from '@datagrok-libraries/bio/src/utils/notation-converter';
10
+ import {GapSymbols, UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
11
11
  import {findMonomers, parseHelm} from './utils';
12
12
  import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
13
13
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
14
14
 
15
- export const _package = new DG.Package();
16
15
  let monomerLib: IMonomerLib | null = null;
17
16
 
17
+ export const _package = new DG.Package();
18
+
18
19
  //tags: init
19
20
  export async function initHelm(): Promise<void> {
20
21
  return Promise.all([
@@ -87,9 +88,8 @@ function rewriteLibraries() {
87
88
  } else if (monomer[SMILES] != null) {
88
89
  webEditorMonomer.rs = Object.keys(getRS(monomer[SMILES].toString())).length;
89
90
  webEditorMonomer.at = getRS(monomer[SMILES].toString());
90
- } else {
91
+ } else
91
92
  isBroken = true;
92
- }
93
93
 
94
94
  if (!isBroken) {
95
95
  // @ts-ignore
@@ -116,8 +116,13 @@ function checkMonomersAndOpenWebEditor(cell?: DG.Cell, value?: string, units?: s
116
116
  const cellValue: string = !!cell && units === undefined ? cell.value : value;
117
117
  const monomerList: string[] = parseHelm(cellValue);
118
118
  const monomers = findMonomers(monomerList);
119
- if (monomers.size == 0) { webEditor(cell, value, units); } else {
120
- grok.shell.warning(`Monomers ${Array.from(monomers).join(', ')} are absent! <br/>` +
119
+ if (monomers.size === 0)
120
+ webEditor(cell, value, units);
121
+ else if (monomers.size === 1 && monomers.has(GapSymbols[NOTATION.HELM]))
122
+ grok.shell.warning(`WebEditor doesn't support Helm with gaps '${GapSymbols[NOTATION.HELM]}'.`);
123
+ else {
124
+ grok.shell.warning(
125
+ `Monomers ${Array.from(monomers).map((m) => `'${m}'`).join(', ')} are absent! <br/>` +
121
126
  `Please, upload the monomer library! <br/>` +
122
127
  `<a href="https://datagrok.ai/help/domains/bio/macromolecules" target="_blank">Learn more</a>`);
123
128
  }
@@ -138,12 +143,13 @@ export function editMoleculeCell(cell: DG.GridCell): void {
138
143
  export function openEditor(mol: string): void {
139
144
  const df = grok.shell.tv.grid.dataFrame;
140
145
  const col = df.columns.bySemType('Macromolecule')!;
146
+ const colUh = UnitsHandler.getOrCreate(col);
141
147
  const colUnits = col.getTag(DG.TAGS.UNITS);
142
148
  if (colUnits === NOTATION.HELM)
143
149
  checkMonomersAndOpenWebEditor(df.currentCell, undefined, undefined);
144
- const converter = new NotationConverter(col);
145
- const resStr = converter.convertStringToHelm(mol, '/');
146
- checkMonomersAndOpenWebEditor(df.currentCell, resStr, col.getTag(DG.TAGS.UNITS));
150
+ const convert = colUh.getConverter(NOTATION.HELM);
151
+ const helmMol = convert(mol);
152
+ checkMonomersAndOpenWebEditor(df.currentCell, helmMol, col.getTag(DG.TAGS.UNITS));
147
153
  }
148
154
 
149
155
  //name: Properties
@@ -175,7 +181,8 @@ export async function propertiesPanel(helmString: string) {
175
181
  function webEditor(cell?: DG.Cell, value?: string, units?: string) {
176
182
  const view = ui.div();
177
183
  const df = grok.shell.tv.grid.dataFrame;
178
- const converter = new NotationConverter(df.columns.bySemType('Macromolecule')!);
184
+ const col = df.columns.bySemType('Macromolecule')!;
185
+ const uh = UnitsHandler.getOrCreate(col);
179
186
  // @ts-ignore
180
187
  org.helm.webeditor.MolViewer.molscale = 0.8;
181
188
  // @ts-ignore
@@ -214,10 +221,10 @@ function webEditor(cell?: DG.Cell, value?: string, units?: string) {
214
221
  const helmValue = app.canvas.getHelm(true).replace(/<\/span>/g, '')
215
222
  .replace(/<span style='background:#bbf;'>/g, '');
216
223
  if (!!cell) {
217
- if (units === undefined) {
224
+ if (units === undefined)
218
225
  cell.value = helmValue;
219
- } else {
220
- const convertedRes = converter.convertHelmToFastaSeparator(helmValue, units!);
226
+ else {
227
+ const convertedRes = uh.convertHelmToFastaSeparator(helmValue, units!);
221
228
  cell.value = convertedRes;
222
229
  }
223
230
  }