@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/.eslintrc.json +1 -2
- package/CHANGELOG.md +22 -0
- package/dist/package-test.js +1 -1
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +2 -2
- package/src/cell-renderer.ts +12 -7
- package/src/helm-monomer-placer.ts +30 -7
- package/src/package.ts +20 -13
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/helm",
|
|
3
3
|
"friendlyName": "Helm",
|
|
4
|
-
"version": "2.1.
|
|
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.
|
|
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",
|
package/src/cell-renderer.ts
CHANGED
|
@@ -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
|
-
|
|
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',
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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 {
|
|
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
|
|
120
|
-
|
|
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
|
|
145
|
-
const
|
|
146
|
-
checkMonomersAndOpenWebEditor(df.currentCell,
|
|
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
|
|
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
|
-
|
|
220
|
-
const convertedRes =
|
|
226
|
+
else {
|
|
227
|
+
const convertedRes = uh.convertHelmToFastaSeparator(helmValue, units!);
|
|
221
228
|
cell.value = convertedRes;
|
|
222
229
|
}
|
|
223
230
|
}
|