@datagrok/helm 2.1.9 → 2.1.11
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/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +2 -2
- package/src/cell-renderer.ts +11 -5
- package/src/package.ts +47 -46
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/helm",
|
|
3
3
|
"friendlyName": "Helm",
|
|
4
|
-
"version": "2.1.
|
|
4
|
+
"version": "2.1.11",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Oleksandra Serhiienko",
|
|
7
7
|
"email": "oserhiienko@datagrok.ai"
|
|
8
8
|
},
|
|
9
9
|
"description": "Provides support for HELM notation (importing, detecting, rendering, conversion).",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@datagrok-libraries/bio": "^5.
|
|
11
|
+
"@datagrok-libraries/bio": "^5.32.3",
|
|
12
12
|
"@datagrok-libraries/utils": "^1.19.1",
|
|
13
13
|
"cash-dom": "^8.1.1",
|
|
14
14
|
"datagrok-api": "^1.10.2",
|
package/src/cell-renderer.ts
CHANGED
|
@@ -6,6 +6,10 @@ import {findMonomers, parseHelm, getParts} from './utils';
|
|
|
6
6
|
import {printLeftOrCentered} from '@datagrok-libraries/bio/src/utils/cell-renderer';
|
|
7
7
|
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
8
8
|
|
|
9
|
+
// Global flag is for replaceAll
|
|
10
|
+
const helmGapStartRe = /\{(\*\.)+/g;
|
|
11
|
+
const helmGapIntRe = /\.(\*\.)+/g;
|
|
12
|
+
const helmGapEndRe = /(\.\*)+\}/g;
|
|
9
13
|
|
|
10
14
|
export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
11
15
|
get name() { return 'helm'; }
|
|
@@ -50,7 +54,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
50
54
|
for (let i = 0; i < allParts.length; ++i) {
|
|
51
55
|
if (monomers.has(allParts[i])) {
|
|
52
56
|
tooltipMessage[i] = ui.divV([
|
|
53
|
-
ui.divText(`Monomer ${allParts[i]} not found.`),
|
|
57
|
+
ui.divText(`Monomer '${allParts[i]}' not found.`),
|
|
54
58
|
ui.divText('Open the Context Panel, then expand Manage Libraries')
|
|
55
59
|
]);
|
|
56
60
|
}
|
|
@@ -70,13 +74,15 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
70
74
|
const grid = gridCell.gridRow !== -1 ? gridCell.grid : undefined;
|
|
71
75
|
const undefinedColor = 'rgb(100,100,100)';
|
|
72
76
|
const grayColor = '#808080';
|
|
73
|
-
|
|
74
|
-
const s: string = gridCell.cell.value
|
|
77
|
+
|
|
78
|
+
const s: string = !gridCell.cell.value ? '' : gridCell.cell.value
|
|
79
|
+
.replaceAll(helmGapStartRe, '{').replaceAll(helmGapIntRe, '.').replaceAll(helmGapEndRe, '}');
|
|
80
|
+
const monomers = findMonomers(s);
|
|
75
81
|
const subParts: string[] = parseHelm(s);
|
|
76
82
|
if (monomers.size == 0 && grid) {
|
|
77
83
|
const host = ui.div([], {style: {width: `${w}px`, height: `${h}px`}});
|
|
78
84
|
host.setAttribute('dataformat', 'helm');
|
|
79
|
-
host.setAttribute('data',
|
|
85
|
+
host.setAttribute('data', s);
|
|
80
86
|
gridCell.element = host;
|
|
81
87
|
//@ts-ignore
|
|
82
88
|
const canvas = new JSDraw2.Editor(host, {width: w, height: h, skin: 'w8', viewonly: true});
|
|
@@ -85,7 +91,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
85
91
|
if (!grid) {
|
|
86
92
|
const r = window.devicePixelRatio;
|
|
87
93
|
h = 28;
|
|
88
|
-
g.canvas.height = h*r;
|
|
94
|
+
g.canvas.height = h * r;
|
|
89
95
|
g.canvas.style.height = `${h}px`;
|
|
90
96
|
}
|
|
91
97
|
w = grid ? Math.min(grid.canvas.width - x, w) : g.canvas.width - x;
|
package/src/package.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
|
|
|
10
10
|
import {NotationConverter} from '@datagrok-libraries/bio/src/utils/notation-converter';
|
|
11
11
|
import {findMonomers} from './utils';
|
|
12
12
|
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
13
|
-
import {
|
|
13
|
+
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
14
14
|
|
|
15
15
|
export const _package = new DG.Package();
|
|
16
16
|
let monomerLib: IMonomerLib | null = null;
|
|
@@ -27,10 +27,10 @@ export async function initHelm(): Promise<void> {
|
|
|
27
27
|
try {
|
|
28
28
|
rewriteLibraries(); // initHelm()
|
|
29
29
|
|
|
30
|
-
const
|
|
30
|
+
const polymerTypeList: string[] = monomerLib.getPolymerTypes();
|
|
31
31
|
const msgStr: string = 'Monomer lib updated:<br />' + (
|
|
32
|
-
|
|
33
|
-
return `${
|
|
32
|
+
polymerTypeList.length == 0 ? 'empty' : polymerTypeList.map((polymerType) => {
|
|
33
|
+
return `${polymerType} ${monomerLib.getMonomerSymbolsByType(polymerType).length}`;
|
|
34
34
|
}).join('<br />'));
|
|
35
35
|
|
|
36
36
|
grok.shell.info(msgStr);
|
|
@@ -45,13 +45,13 @@ export async function initHelm(): Promise<void> {
|
|
|
45
45
|
|
|
46
46
|
function rewriteLibraries() {
|
|
47
47
|
org.helm.webeditor.Monomers.clear();
|
|
48
|
-
monomerLib.
|
|
49
|
-
const
|
|
50
|
-
|
|
48
|
+
monomerLib.getPolymerTypes().forEach((polymerType) => {
|
|
49
|
+
const monomerSymbols = monomerLib.getMonomerSymbolsByType(polymerType);
|
|
50
|
+
monomerSymbols.forEach((monomerSymbol) => {
|
|
51
51
|
let isBroken = false;
|
|
52
|
-
const monomer: Monomer = monomerLib.getMonomer(
|
|
52
|
+
const monomer: Monomer = monomerLib.getMonomer(polymerType, monomerSymbol);
|
|
53
53
|
const webEditorMonomer: WebEditorMonomer = {
|
|
54
|
-
id:
|
|
54
|
+
id: monomerSymbol,
|
|
55
55
|
m: monomer.molfile,
|
|
56
56
|
n: monomer.name,
|
|
57
57
|
na: monomer.naturalAnalog,
|
|
@@ -64,13 +64,13 @@ function rewriteLibraries() {
|
|
|
64
64
|
if (monomer.rgroups.length > 0) {
|
|
65
65
|
webEditorMonomer.rs = monomer.rgroups.length;
|
|
66
66
|
const at = {};
|
|
67
|
-
monomer.rgroups.forEach(it => {
|
|
67
|
+
monomer.rgroups.forEach((it) => {
|
|
68
68
|
at[it[RGROUP_LABEL]] = it[RGROUP_CAP_GROUP_NAME];
|
|
69
69
|
});
|
|
70
70
|
webEditorMonomer.at = at;
|
|
71
|
-
} else if (monomer
|
|
72
|
-
webEditorMonomer.rs = Object.keys(getRS(monomer
|
|
73
|
-
webEditorMonomer.at = getRS(monomer
|
|
71
|
+
} else if (monomer[SMILES] != null) {
|
|
72
|
+
webEditorMonomer.rs = Object.keys(getRS(monomer[SMILES].toString())).length;
|
|
73
|
+
webEditorMonomer.at = getRS(monomer[SMILES].toString());
|
|
74
74
|
} else {
|
|
75
75
|
isBroken = true;
|
|
76
76
|
}
|
|
@@ -81,7 +81,7 @@ function rewriteLibraries() {
|
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
// Obsolete
|
|
84
|
-
|
|
84
|
+
const grid: DG.Grid = grok.shell.tv.grid;
|
|
85
85
|
if (grid) grid.invalidate();
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -97,16 +97,17 @@ export function helmCellRenderer(): HelmCellRenderer {
|
|
|
97
97
|
function checkMonomersAndOpenWebEditor(cell?: DG.Cell, value?: string, units?: string) {
|
|
98
98
|
const cellValue = typeof units === 'undefined' ? cell.value : value;
|
|
99
99
|
const monomers = findMonomers(cellValue);
|
|
100
|
-
if (monomers.size == 0)
|
|
100
|
+
if (monomers.size == 0) {
|
|
101
101
|
webEditor(cell, value, units);
|
|
102
|
-
else
|
|
102
|
+
} else {
|
|
103
103
|
grok.shell.warning(`Monomers ${Array.from(monomers).join(', ')} are absent! <br/>` +
|
|
104
104
|
`Please, upload the monomer library! <br/>` +
|
|
105
105
|
`<a href="https://datagrok.ai/help/domains/bio/macromolecules" target="_blank">Learn more</a>`);
|
|
106
|
+
}
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
//tags: cellEditor
|
|
109
|
-
//description: Macromolecule
|
|
110
|
+
//description: Macromolecule
|
|
110
111
|
//input: grid_cell cell
|
|
111
112
|
//meta.columnTags: quality=Macromolecule, units=helm
|
|
112
113
|
export function editMoleculeCell(cell: DG.GridCell): void {
|
|
@@ -118,13 +119,13 @@ export function editMoleculeCell(cell: DG.GridCell): void {
|
|
|
118
119
|
//meta.action: Open Helm Web Editor
|
|
119
120
|
//input: string mol { semType: Macromolecule }
|
|
120
121
|
export function openEditor(mol: string): void {
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
const df = grok.shell.tv.grid.dataFrame;
|
|
123
|
+
const col = df.columns.bySemType('Macromolecule');
|
|
123
124
|
const colUnits = col.getTag(DG.TAGS.UNITS);
|
|
124
|
-
if (colUnits === NOTATION.HELM)
|
|
125
|
+
if (colUnits === NOTATION.HELM)
|
|
125
126
|
checkMonomersAndOpenWebEditor(df.currentCell, undefined, undefined);
|
|
126
|
-
|
|
127
|
-
const resStr = converter.convertStringToHelm(mol, '/');
|
|
127
|
+
const converter = new NotationConverter(col);
|
|
128
|
+
const resStr = converter.convertStringToHelm(mol, '/');
|
|
128
129
|
checkMonomersAndOpenWebEditor(df.currentCell, resStr, col.getTag(DG.TAGS.UNITS));
|
|
129
130
|
}
|
|
130
131
|
|
|
@@ -133,17 +134,17 @@ export function openEditor(mol: string): void {
|
|
|
133
134
|
//input: string helmString {semType: Macromolecule}
|
|
134
135
|
//output: widget result
|
|
135
136
|
export async function propertiesPanel(helmString: string) {
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
const grid = grok.shell.tv.grid;
|
|
138
|
+
const parent = grid.root.parentElement;
|
|
138
139
|
const host = ui.div([]);
|
|
139
140
|
parent.appendChild(host);
|
|
140
|
-
|
|
141
|
+
const editor = new JSDraw2.Editor(host, {viewonly: true});
|
|
141
142
|
host.style.width = '0px';
|
|
142
143
|
host.style.height = '0px';
|
|
143
144
|
editor.setHelm(helmString);
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
const formula = editor.getFormula(true);
|
|
146
|
+
const molWeight = Math.round(editor.getMolWeight() * 100) / 100;
|
|
147
|
+
const coef = Math.round(editor.getExtinctionCoefficient(true) * 100) / 100;
|
|
147
148
|
parent.lastChild.remove();
|
|
148
149
|
return new DG.Widget(
|
|
149
150
|
ui.tableFromMap({
|
|
@@ -155,11 +156,11 @@ export async function propertiesPanel(helmString: string) {
|
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
function webEditor(cell?: DG.Cell, value?: string, units?: string) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
const view = ui.div();
|
|
160
|
+
const df = grok.shell.tv.grid.dataFrame;
|
|
161
|
+
const converter = new NotationConverter(df.columns.bySemType('Macromolecule'));
|
|
161
162
|
org.helm.webeditor.MolViewer.molscale = 0.8;
|
|
162
|
-
|
|
163
|
+
const app = new scil.helm.App(view, {
|
|
163
164
|
showabout: false,
|
|
164
165
|
mexfontsize: '90%',
|
|
165
166
|
mexrnapinontab: true,
|
|
@@ -169,9 +170,9 @@ function webEditor(cell?: DG.Cell, value?: string, units?: string) {
|
|
|
169
170
|
mexfavoritefirst: true,
|
|
170
171
|
mexfilter: true
|
|
171
172
|
});
|
|
172
|
-
|
|
173
|
+
const sizes = app.calculateSizes();
|
|
173
174
|
app.canvas.resize(sizes.rightwidth - 100, sizes.topheight - 210);
|
|
174
|
-
|
|
175
|
+
let s = {width: sizes.rightwidth - 100 + 'px', height: sizes.bottomheight + 'px'};
|
|
175
176
|
//@ts-ignore
|
|
176
177
|
scil.apply(app.sequence.style, s);
|
|
177
178
|
//@ts-ignore
|
|
@@ -181,22 +182,22 @@ function webEditor(cell?: DG.Cell, value?: string, units?: string) {
|
|
|
181
182
|
scil.apply(app.properties.parent.style, s);
|
|
182
183
|
app.structureview.resize(sizes.rightwidth, sizes.bottomheight + app.toolbarheight);
|
|
183
184
|
app.mex.resize(sizes.topheight - 80);
|
|
184
|
-
setTimeout(
|
|
185
|
-
if (typeof units === 'undefined')
|
|
185
|
+
setTimeout(() => {
|
|
186
|
+
if (typeof units === 'undefined')
|
|
186
187
|
app.canvas.helm.setSequence(cell.value, 'HELM');
|
|
187
|
-
|
|
188
|
+
else
|
|
188
189
|
app.canvas.helm.setSequence(value, 'HELM');
|
|
189
|
-
}
|
|
190
190
|
}, 200);
|
|
191
191
|
//@ts-ignore
|
|
192
192
|
ui.dialog({showHeader: false, showFooter: true})
|
|
193
193
|
.add(view)
|
|
194
194
|
.onOK(() => {
|
|
195
|
-
|
|
195
|
+
const helmValue = app.canvas.getHelm(true).replace(/<\/span>/g, '')
|
|
196
|
+
.replace(/<span style='background:#bbf;'>/g, '');
|
|
196
197
|
if (typeof units === 'undefined') {
|
|
197
198
|
cell.value = helmValue;
|
|
198
199
|
} else {
|
|
199
|
-
|
|
200
|
+
const convertedRes = converter.convertHelmToFastaSeparator(helmValue, units);
|
|
200
201
|
cell.value = convertedRes;
|
|
201
202
|
}
|
|
202
203
|
}).show({modal: true, fullScreen: true});
|
|
@@ -226,19 +227,19 @@ function getRS(smiles: string) {
|
|
|
226
227
|
|
|
227
228
|
//name: getMolfiles
|
|
228
229
|
//input: column col {semType: Macromolecule}
|
|
229
|
-
//output: column res
|
|
230
|
+
//output: column res
|
|
230
231
|
export function getMolfiles(col: DG.Column): DG.Column {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
232
|
+
const grid = grok.shell.tv.grid;
|
|
233
|
+
const parent = grid.root.parentElement;
|
|
234
|
+
const res = DG.Column.string('mols', col.length);
|
|
234
235
|
const host = ui.div([]);
|
|
235
236
|
parent.appendChild(host);
|
|
236
|
-
|
|
237
|
+
const editor = new JSDraw2.Editor(host, {viewonly: true});
|
|
237
238
|
host.style.width = '0px';
|
|
238
239
|
host.style.height = '0px';
|
|
239
240
|
res.init((i) => {
|
|
240
241
|
editor.setHelm(col.get(i));
|
|
241
|
-
|
|
242
|
+
const mol = editor.getMolfile();
|
|
242
243
|
return mol;
|
|
243
244
|
});
|
|
244
245
|
parent.lastChild.remove();
|