@datagrok/sequence-translator 1.10.18 → 1.10.20
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/CHANGELOG.md +4 -0
- package/detectors.js +4 -4
- 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/files/enumeration/chem_enum_cores.csv +5 -0
- package/files/enumeration/chem_enum_rgroups.csv +5 -0
- package/package.json +1 -1
- package/src/oligo-renderer/canvas-renderer.ts +4 -3
- package/src/oligo-renderer/cell-renderer.ts +19 -20
- package/src/package-api.ts +2 -9
- package/src/package.g.ts +6 -13
- package/src/package.ts +9 -16
- package/src/polytool/pt-chem-enum-dialog.ts +366 -55
- package/test-console-output-1.log +154 -154
- package/test-record-1.mp4 +0 -0
package/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable max-params */
|
|
1
2
|
/**
|
|
2
3
|
* Canvas drawing for the OligoNucleotide cell renderer.
|
|
3
4
|
*
|
|
@@ -41,7 +42,7 @@ export interface RenderOpts {
|
|
|
41
42
|
scheme?: string;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
const DEFAULT_OPTS: RenderOpts = {showLetters: true, pairAlign: true};
|
|
45
|
+
export const DEFAULT_OPTS: RenderOpts = {showLetters: true, pairAlign: true};
|
|
45
46
|
|
|
46
47
|
/* Visual tuning. */
|
|
47
48
|
const ASPECT_H_OVER_W = 1.25;
|
|
@@ -329,11 +330,11 @@ function fitsInBudget(widths: number[], leadW: number, chipGap: number, budget:
|
|
|
329
330
|
export function drawDuplex(
|
|
330
331
|
g: CanvasRenderingContext2D, cellX: number, cellY: number,
|
|
331
332
|
cellW: number, cellH: number, model: ParsedDuplex,
|
|
332
|
-
opts: Partial<RenderOpts> = {},
|
|
333
|
+
opts: Partial<RenderOpts> = {}, skipDrawing = false,
|
|
333
334
|
): DuplexLayout {
|
|
334
335
|
const o: RenderOpts = {...DEFAULT_OPTS, ...opts};
|
|
335
336
|
const layout = computeLayout(cellW, cellH, model, o);
|
|
336
|
-
|
|
337
|
+
if (skipDrawing) return layout;
|
|
337
338
|
g.save();
|
|
338
339
|
g.beginPath();
|
|
339
340
|
g.rect(cellX, cellY, cellW, cellH);
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import * as DG from 'datagrok-api/dg';
|
|
15
15
|
import * as ui from 'datagrok-api/ui';
|
|
16
16
|
|
|
17
|
-
import {drawDuplex, hitTest, DuplexLayout} from './canvas-renderer';
|
|
17
|
+
import {drawDuplex, hitTest, DuplexLayout, RenderOpts, DEFAULT_OPTS} from './canvas-renderer';
|
|
18
18
|
import {looksLikeHelm, parseHelmDuplex} from './helm-parser';
|
|
19
19
|
import {ParsedDuplex} from './types';
|
|
20
20
|
import {showMonomerTooltip} from './tooltip';
|
|
@@ -23,9 +23,9 @@ const CELL_TYPE = 'OligoNucleotide';
|
|
|
23
23
|
|
|
24
24
|
export class OligoNucleotideCellRenderer extends DG.GridCellRenderer {
|
|
25
25
|
/** WeakMap-by-value cache of parsed HELM. Avoids reparsing on redraw. */
|
|
26
|
-
private modelCache = new
|
|
26
|
+
private modelCache = new DG.LruCache<string, ParsedDuplex>();
|
|
27
27
|
/** Last-rendered layout per cell key, for hit-testing on subsequent moves. */
|
|
28
|
-
private layoutCache = new
|
|
28
|
+
private layoutCache = new DG.LruCache<string, DuplexLayout>();
|
|
29
29
|
|
|
30
30
|
get name(): string { return CELL_TYPE; }
|
|
31
31
|
get cellType(): string { return CELL_TYPE; }
|
|
@@ -54,11 +54,16 @@ export class OligoNucleotideCellRenderer extends DG.GridCellRenderer {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
const model = this.getOrParse(value);
|
|
57
|
+
if (!gridCell.cell?.dart || !gridCell.cell.column) {
|
|
58
|
+
w = g.canvas.width;
|
|
59
|
+
h = g.canvas.height;
|
|
60
|
+
x = 0;
|
|
61
|
+
y = 0;
|
|
62
|
+
// this happens in forms....
|
|
63
|
+
}
|
|
57
64
|
const layout = drawDuplex(g, x, y, w, h, model);
|
|
58
65
|
// Cache for hit-test on subsequent mouse moves over the same cell.
|
|
59
|
-
this.layoutCache.set(this.cellKey(
|
|
60
|
-
// Avoid unbounded growth on big tables.
|
|
61
|
-
if (this.layoutCache.size > 5000) this.layoutCache.clear();
|
|
66
|
+
this.layoutCache.set(this.cellKey(value, w, h, DEFAULT_OPTS), layout);
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
override onMouseMove(gridCell: DG.GridCell, e: MouseEvent): void {
|
|
@@ -68,7 +73,11 @@ export class OligoNucleotideCellRenderer extends DG.GridCellRenderer {
|
|
|
68
73
|
return;
|
|
69
74
|
}
|
|
70
75
|
const model = this.getOrParse(value);
|
|
71
|
-
const layout = this.layoutCache.
|
|
76
|
+
const layout = this.layoutCache.getOrCreate(
|
|
77
|
+
this.cellKey(value, gridCell.bounds.width, gridCell.bounds.height, DEFAULT_OPTS), (v) => drawDuplex(
|
|
78
|
+
null as unknown as CanvasRenderingContext2D, 0, 0, gridCell.bounds.width, gridCell.bounds.height,
|
|
79
|
+
model, DEFAULT_OPTS, true,
|
|
80
|
+
));
|
|
72
81
|
if (!layout) return;
|
|
73
82
|
|
|
74
83
|
const bounds = gridCell.bounds;
|
|
@@ -88,24 +97,14 @@ export class OligoNucleotideCellRenderer extends DG.GridCellRenderer {
|
|
|
88
97
|
}
|
|
89
98
|
|
|
90
99
|
private getOrParse(helm: string): ParsedDuplex {
|
|
91
|
-
|
|
92
|
-
if (!m) {
|
|
93
|
-
m = parseHelmDuplex(helm);
|
|
94
|
-
// Cap cache to avoid unbounded growth on huge tables.
|
|
95
|
-
if (this.modelCache.size > 5000) this.modelCache.clear();
|
|
96
|
-
this.modelCache.set(helm, m);
|
|
97
|
-
}
|
|
98
|
-
return m;
|
|
100
|
+
return this.modelCache.getOrCreate(helm, (h) => parseHelmDuplex(h));
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
/** Cache key for a cell's layout. Includes the column's `version` so any
|
|
102
104
|
* edit to the column (which bumps version) orphans previous cache entries
|
|
103
105
|
* — preventing onMouseMove from hit-testing a stale layout that was cached
|
|
104
106
|
* before the edit and not yet replaced by a fresh render(). */
|
|
105
|
-
private cellKey(
|
|
106
|
-
|
|
107
|
-
const colName = col?.name ?? gridCell.gridColumn?.name ?? '?';
|
|
108
|
-
const ver = col?.version ?? 0;
|
|
109
|
-
return `${colName}@${ver}::${gridCell.tableRowIndex ?? -1}`;
|
|
107
|
+
private cellKey(value: string, width: number, height: number, opts: RenderOpts): string {
|
|
108
|
+
return `${value}::${Math.floor(width)}x${Math.floor(height)}::${JSON.stringify(opts)}`;
|
|
110
109
|
}
|
|
111
110
|
}
|
package/src/package-api.ts
CHANGED
|
@@ -95,18 +95,11 @@ export namespace funcs {
|
|
|
95
95
|
return await grok.functions.call('SequenceTranslator:PolyToolEnumerateHelmTopMenu', {});
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
/**
|
|
99
|
-
Perform enumeration of a molecule using different fragments at specified positions
|
|
100
|
-
*/
|
|
101
|
-
export async function polyToolEnumerateChemTopMenu(): Promise<void> {
|
|
102
|
-
return await grok.functions.call('SequenceTranslator:PolyToolEnumerateChemTopMenu', {});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
98
|
/**
|
|
106
99
|
Enumerate cores and R-group lists into a molecule table (Zip or Cartesian)
|
|
107
100
|
*/
|
|
108
|
-
export async function
|
|
109
|
-
return await grok.functions.call('SequenceTranslator:
|
|
101
|
+
export async function chemEnumerateMarkushTopMenu(): Promise<void> {
|
|
102
|
+
return await grok.functions.call('SequenceTranslator:ChemEnumerateMarkushTopMenu', {});
|
|
110
103
|
}
|
|
111
104
|
|
|
112
105
|
export async function polyToolColumnChoice(df: DG.DataFrame , macroMolecule: DG.Column ): Promise<void> {
|
package/src/package.g.ts
CHANGED
|
@@ -141,18 +141,11 @@ export async function polyToolEnumerateHelmTopMenu() : Promise<void> {
|
|
|
141
141
|
await PackageFunctions.polyToolEnumerateHelmTopMenu();
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
//name:
|
|
145
|
-
//description: Perform enumeration of a molecule using different fragments at specified positions
|
|
146
|
-
//top-menu: Bio | PolyTool | Enumerate Chem...
|
|
147
|
-
export async function polyToolEnumerateChemTopMenu() : Promise<void> {
|
|
148
|
-
await PackageFunctions.polyToolEnumerateChemTopMenu();
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
//name: chemEnumerateReactions
|
|
144
|
+
//name: Markush Enumerator
|
|
152
145
|
//description: Enumerate cores and R-group lists into a molecule table (Zip or Cartesian)
|
|
153
|
-
//top-menu: Chem | Transform |
|
|
154
|
-
export async function
|
|
155
|
-
await PackageFunctions.
|
|
146
|
+
//top-menu: Chem | Transform | Markush Enumeration...
|
|
147
|
+
export async function chemEnumerateMarkushTopMenu() : Promise<void> {
|
|
148
|
+
await PackageFunctions.chemEnumerateMarkushTopMenu();
|
|
156
149
|
}
|
|
157
150
|
|
|
158
151
|
//input: dataframe df { description: Input data table }
|
|
@@ -175,11 +168,11 @@ export async function ptEnumeratorHelmApp() : Promise<void> {
|
|
|
175
168
|
await PackageFunctions.ptEnumeratorHelmApp();
|
|
176
169
|
}
|
|
177
170
|
|
|
178
|
-
//name:
|
|
171
|
+
//name: Markush Enumerator
|
|
179
172
|
//tags: app
|
|
180
173
|
//output: view result
|
|
181
174
|
//meta.icon: img/icons/structure.png
|
|
182
|
-
//meta.browsePath: Chem
|
|
175
|
+
//meta.browsePath: Chem
|
|
183
176
|
//meta.role: app
|
|
184
177
|
export async function ptEnumeratorChemApp() {
|
|
185
178
|
return await PackageFunctions.ptEnumeratorChemApp();
|
package/src/package.ts
CHANGED
|
@@ -274,22 +274,15 @@ export class PackageFunctions {
|
|
|
274
274
|
|
|
275
275
|
|
|
276
276
|
@grok.decorators.func({
|
|
277
|
-
'top-menu': '
|
|
278
|
-
'name': '
|
|
279
|
-
'description': 'Perform enumeration of a molecule using different fragments at specified positions'
|
|
280
|
-
})
|
|
281
|
-
static async polyToolEnumerateChemTopMenu(): Promise<void> {
|
|
282
|
-
polyToolEnumerateChemUI();
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
@grok.decorators.func({
|
|
287
|
-
'top-menu': 'Chem | Transform | Reactions | Enumerate...',
|
|
288
|
-
'name': 'chemEnumerateReactions',
|
|
277
|
+
'top-menu': 'Chem | Transform | Markush Enumeration...',
|
|
278
|
+
'name': 'Markush Enumerator',
|
|
289
279
|
'description': 'Enumerate cores and R-group lists into a molecule table (Zip or Cartesian)'
|
|
290
280
|
})
|
|
291
|
-
static async
|
|
292
|
-
|
|
281
|
+
static async chemEnumerateMarkushTopMenu(): Promise<void> {
|
|
282
|
+
let cell: DG.Cell | undefined = undefined;
|
|
283
|
+
if (grok.shell.tv?.dataFrame && grok.shell.tv.dataFrame.currentCell && grok.shell.tv.dataFrame.currentCell.column.semType === DG.SEMTYPE.MOLECULE)
|
|
284
|
+
cell = grok.shell.tv.dataFrame.currentCell;
|
|
285
|
+
polyToolEnumerateChemUI(cell);
|
|
293
286
|
}
|
|
294
287
|
|
|
295
288
|
|
|
@@ -331,10 +324,10 @@ export class PackageFunctions {
|
|
|
331
324
|
@grok.decorators.func({
|
|
332
325
|
meta: {
|
|
333
326
|
icon: 'img/icons/structure.png',
|
|
334
|
-
browsePath: 'Chem
|
|
327
|
+
browsePath: 'Chem',
|
|
335
328
|
role: 'app'
|
|
336
329
|
},
|
|
337
|
-
name: '
|
|
330
|
+
name: 'Markush Enumerator',
|
|
338
331
|
tags: ['app'],
|
|
339
332
|
outputs: [{type: 'view', name: 'result'}]
|
|
340
333
|
})
|