@datagrok/helm 2.1.13 → 2.1.15
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-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 +71 -55
- package/src/constants.ts +20 -16
- package/src/helm-monomer-placer.ts +78 -0
- package/src/package-test.ts +1 -0
- package/src/package.ts +11 -4
- package/src/tests/findMonomers-tests.ts +3 -2
- package/src/tests/helm-tests.ts +1 -1
- package/src/tests/renderers-tests.ts +35 -0
- package/src/utils.ts +12 -12
package/src/cell-renderer.ts
CHANGED
|
@@ -2,15 +2,22 @@ import * as grok from 'datagrok-api/grok';
|
|
|
2
2
|
import * as ui from 'datagrok-api/ui';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
|
|
5
|
+
import wu from 'wu';
|
|
6
|
+
|
|
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';
|
|
11
|
+
import {HelmMonomerPlacer} from './helm-monomer-placer';
|
|
12
|
+
import {TAGS as helmTAGS} from './constants';
|
|
13
|
+
|
|
10
14
|
const enum tempTAGS {
|
|
11
15
|
helmSumMaxLengthWords = 'helm-sum-maxLengthWords',
|
|
12
16
|
helmMaxLengthWords = 'helm-maxLengthWords',
|
|
17
|
+
|
|
18
|
+
helmPlacer = 'bio-helmPlacer',
|
|
13
19
|
}
|
|
20
|
+
|
|
14
21
|
// Global flag is for replaceAll
|
|
15
22
|
const helmGapStartRe = /\{(\*\.)+/g;
|
|
16
23
|
const helmGapIntRe = /\.(\*\.)+/g;
|
|
@@ -37,52 +44,62 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
37
44
|
try { tableCol = gridCell.tableColumn; } catch { }
|
|
38
45
|
if (!tableCol) return;
|
|
39
46
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
if (!colTemp || Object.keys(colTemp).length == 0) return;
|
|
43
|
-
|
|
44
|
-
const maxLengthWordsSum: { [pos: number]: number } = colTemp[tempTAGS.helmSumMaxLengthWords];
|
|
45
|
-
const maxLengthWords: { [pos: number]: number } = colTemp[tempTAGS.helmMaxLengthWords];
|
|
47
|
+
const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
|
|
48
|
+
const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex);
|
|
46
49
|
|
|
47
|
-
const maxIndex = Object.values(
|
|
48
|
-
const argsX = e.offsetX - gridCell.
|
|
50
|
+
const maxIndex = Object.values(lengths).length - 1;
|
|
51
|
+
const argsX = e.offsetX - gridCell.bounds.x;
|
|
49
52
|
let left = 0;
|
|
50
53
|
let right = maxIndex;
|
|
51
54
|
let found = false;
|
|
52
|
-
|
|
55
|
+
let iterCount: number = 0;
|
|
56
|
+
|
|
53
57
|
let mid = 0;
|
|
54
|
-
if (argsX >
|
|
55
|
-
while (!found) {
|
|
58
|
+
if (argsX > sumLengths[0]) {
|
|
59
|
+
while (!found && iterCount < sumLengths.length) {
|
|
56
60
|
mid = Math.floor((right + left) / 2);
|
|
57
|
-
if (argsX >=
|
|
61
|
+
if (argsX >= sumLengths[mid] && argsX <= sumLengths[mid + 1]) {
|
|
58
62
|
left = mid;
|
|
59
63
|
found = true;
|
|
60
|
-
} else if (argsX <
|
|
64
|
+
} else if (argsX < sumLengths[mid]) {
|
|
61
65
|
right = mid - 1;
|
|
62
|
-
} else if (argsX >
|
|
66
|
+
} else if (argsX > sumLengths[mid + 1]) {
|
|
63
67
|
left = mid + 1;
|
|
64
68
|
}
|
|
65
69
|
if (left == right)
|
|
66
70
|
found = true;
|
|
71
|
+
|
|
72
|
+
iterCount++;
|
|
67
73
|
}
|
|
68
74
|
}
|
|
69
|
-
left = (argsX >=
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const
|
|
75
|
+
left = (argsX >= sumLengths[left]) ? left : left - 1; // correct left to between sumLengths
|
|
76
|
+
|
|
77
|
+
const seq: string = gridCell.cell.value;
|
|
78
|
+
const monomerList = parseHelm(seq);
|
|
79
|
+
const monomers = new Set<string>(monomerList);
|
|
80
|
+
const missedMonomers = findMonomers(monomerList);
|
|
81
|
+
|
|
74
82
|
const tooltipMessage: HTMLElement[] = [];
|
|
75
|
-
for (
|
|
76
|
-
if (
|
|
83
|
+
for (const [part, partI] of wu.enumerate(allParts)) {
|
|
84
|
+
if (missedMonomers.has(part)) {
|
|
77
85
|
tooltipMessage[partI] = ui.divV([
|
|
78
86
|
ui.divText(`Monomer ${allParts[partI]} not found.`),
|
|
79
87
|
ui.divText('Open the Context Panel, then expand Manage Libraries')
|
|
80
88
|
]);
|
|
89
|
+
} else if (monomers.has(part)) {
|
|
90
|
+
const elList = [ui.div(part)];
|
|
91
|
+
const monomer = helmPlacer.getMonomer(part);
|
|
92
|
+
if (monomer) {
|
|
93
|
+
const options = {autoCrop: true, autoCropMargin: 0, suppressChiralText: true};
|
|
94
|
+
const monomerSvg = grok.chem.svgMol(monomer.smiles, undefined, undefined, options);
|
|
95
|
+
elList.push(monomerSvg);
|
|
96
|
+
}
|
|
97
|
+
tooltipMessage[partI] = ui.divV(elList);
|
|
81
98
|
}
|
|
82
99
|
}
|
|
83
100
|
|
|
84
101
|
(((tooltipMessage[left]?.childNodes.length ?? 0) > 0)) ?
|
|
85
|
-
ui.tooltip.show(
|
|
102
|
+
ui.tooltip.show(tooltipMessage[left], e.x + 16, e.y + 16) :
|
|
86
103
|
ui.tooltip.hide();
|
|
87
104
|
} catch (err: any) {
|
|
88
105
|
const errMsg: string = errorToConsole(err);
|
|
@@ -93,20 +110,22 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
93
110
|
render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
|
|
94
111
|
gridCell: DG.GridCell, cellStyle: DG.GridCellStyle
|
|
95
112
|
) {
|
|
113
|
+
/* Can not do anything without tableColumn containing temp */
|
|
114
|
+
let tableCol: DG.Column | null = null;
|
|
115
|
+
try { tableCol = gridCell.tableColumn; } catch { }
|
|
116
|
+
if (!tableCol) return;
|
|
117
|
+
|
|
96
118
|
g.save();
|
|
97
119
|
try {
|
|
98
|
-
/* Can not do anything without tableColumn containing temp */
|
|
99
|
-
let tableCol: DG.Column | null = null;
|
|
100
|
-
try { tableCol = gridCell.tableColumn; } catch { }
|
|
101
|
-
if (!tableCol) return;
|
|
102
|
-
|
|
103
120
|
const grid = gridCell.gridRow !== -1 ? gridCell.grid : undefined;
|
|
104
|
-
const
|
|
105
|
-
const
|
|
121
|
+
const missedColor = 'red';
|
|
122
|
+
const monomerColor: string = '#404040';
|
|
123
|
+
const frameColor: string = '#C0C0C0';
|
|
106
124
|
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
const
|
|
125
|
+
const seq = gridCell.cell.value;
|
|
126
|
+
const monomerList: string[] = parseHelm(seq);
|
|
127
|
+
const monomers: Set<string> = new Set<string>(monomerList);
|
|
128
|
+
const missedMonomers: Set<string> = findMonomers(monomerList);
|
|
110
129
|
|
|
111
130
|
if (missedMonomers.size == 0) {
|
|
112
131
|
const host = ui.div([], {style: {width: `${w}px`, height: `${h}px`}});
|
|
@@ -122,40 +141,37 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
122
141
|
if (!grid) {
|
|
123
142
|
const r = window.devicePixelRatio;
|
|
124
143
|
h = 28;
|
|
125
|
-
g.canvas.height = h*r;
|
|
144
|
+
g.canvas.height = h * r;
|
|
126
145
|
g.canvas.style.height = `${h}px`;
|
|
127
146
|
}
|
|
128
|
-
const maxLengthWords: number[] = tableCol.temp[tempTAGS.helmMaxLengthWords] ?? [];
|
|
129
|
-
if (subParts.length > maxLengthWords.length)
|
|
130
|
-
maxLengthWords.push(...(new Array<number>(subParts.length - maxLengthWords.length).fill(-1)));
|
|
131
147
|
|
|
132
148
|
w = grid ? Math.min(grid.canvas.width - x, w) : g.canvas.width - x;
|
|
133
149
|
g.save();
|
|
134
150
|
g.beginPath();
|
|
135
151
|
g.rect(x, y, w, h);
|
|
136
152
|
g.clip();
|
|
153
|
+
g.transform(1, 0, 0, 1, x, y);
|
|
137
154
|
g.font = '12px monospace';
|
|
138
155
|
g.textBaseline = 'top';
|
|
139
|
-
|
|
140
|
-
const allParts
|
|
156
|
+
const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
|
|
157
|
+
const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRow.idx);
|
|
158
|
+
|
|
141
159
|
for (let i = 0; i < allParts.length; ++i) {
|
|
142
|
-
|
|
143
|
-
const color =
|
|
144
|
-
|
|
145
|
-
|
|
160
|
+
const part: string = allParts[i];
|
|
161
|
+
const color: string =
|
|
162
|
+
part === '.' || part.endsWith('{') || part.startsWith('}') ? frameColor :
|
|
163
|
+
missedMonomers.has(part) ? missedColor :
|
|
164
|
+
monomers.has(part) ? monomerColor :
|
|
165
|
+
frameColor;
|
|
166
|
+
g.fillStyle = color;
|
|
167
|
+
printLeftOrCentered(sumLengths[i], 0, w, h, g, allParts[i], color, 0, true, 1.0);
|
|
146
168
|
}
|
|
147
|
-
|
|
148
|
-
const maxLengthWordSum: number[] = new Array<number>(maxLengthWords.length);
|
|
149
|
-
maxLengthWordSum[0] = maxLengthWords[0];
|
|
150
|
-
for (let partI = 1; partI < allParts.length; partI++)
|
|
151
|
-
maxLengthWordSum[partI] = maxLengthWordSum[partI - 1] + maxLengthWords[partI];
|
|
152
|
-
|
|
153
|
-
tableCol.temp = {
|
|
154
|
-
[tempTAGS.helmSumMaxLengthWords]: maxLengthWordSum,
|
|
155
|
-
[tempTAGS.helmMaxLengthWords]: maxLengthWords
|
|
156
|
-
};
|
|
157
|
-
return;
|
|
158
169
|
}
|
|
170
|
+
} catch (err: any) {
|
|
171
|
+
const errMsg = err instanceof Error ? err.message : err.toString();
|
|
172
|
+
const errStack = err instanceof Error ? err.stack : undefined;
|
|
173
|
+
tableCol.setTag(helmTAGS.cellRendererRenderError, JSON.stringify({message: errMsg, stack: errStack}));
|
|
174
|
+
throw err;
|
|
159
175
|
} finally {
|
|
160
176
|
g.restore();
|
|
161
177
|
}
|
package/src/constants.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
export const jsonSdfMonomerLibDict = {
|
|
2
|
-
"monomerType": null,
|
|
3
|
-
"smiles": null,
|
|
4
|
-
"name": "MonomerName",
|
|
5
|
-
"author": null,
|
|
6
|
-
"molfile": "molecule",
|
|
7
|
-
"naturalAnalog": "MonomerNaturalAnalogCode",
|
|
2
|
+
"monomerType": null,
|
|
3
|
+
"smiles": null,
|
|
4
|
+
"name": "MonomerName",
|
|
5
|
+
"author": null,
|
|
6
|
+
"molfile": "molecule",
|
|
7
|
+
"naturalAnalog": "MonomerNaturalAnalogCode",
|
|
8
8
|
"rgroups": "MonomerCaps",
|
|
9
|
-
"createDate": null,
|
|
10
|
-
"id": null,
|
|
11
|
-
"polymerType": "MonomerType",
|
|
9
|
+
"createDate": null,
|
|
10
|
+
"id": null,
|
|
11
|
+
"polymerType": "MonomerType",
|
|
12
12
|
"symbol": "MonomerCode"
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -24,10 +24,14 @@ export type WebEditorMonomer = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
export const SMILES = 'smiles';
|
|
27
|
-
export const RGROUPS =
|
|
28
|
-
export const MONOMER_SYMBOL =
|
|
29
|
-
export const RGROUP_CAP_GROUP_SMILES =
|
|
30
|
-
export const RGROUP_ALTER_ID =
|
|
31
|
-
export const RGROUP_CAP_GROUP_NAME =
|
|
32
|
-
export const RGROUP_LABEL =
|
|
33
|
-
export const SDF_MONOMER_NAME =
|
|
27
|
+
export const RGROUPS = 'rgroups';
|
|
28
|
+
export const MONOMER_SYMBOL = 'symbol';
|
|
29
|
+
export const RGROUP_CAP_GROUP_SMILES = 'capGroupSmiles';
|
|
30
|
+
export const RGROUP_ALTER_ID = 'alternateId';
|
|
31
|
+
export const RGROUP_CAP_GROUP_NAME = 'capGroupName';
|
|
32
|
+
export const RGROUP_LABEL = 'label';
|
|
33
|
+
export const SDF_MONOMER_NAME = 'MonomerName';
|
|
34
|
+
|
|
35
|
+
export const enum TAGS {
|
|
36
|
+
cellRendererRenderError = '.cell-renderer.render.error',
|
|
37
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as ui from 'datagrok-api/ui';
|
|
3
|
+
import * as DG from 'datagrok-api/dg';
|
|
4
|
+
|
|
5
|
+
import wu from 'wu';
|
|
6
|
+
|
|
7
|
+
import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types/index';
|
|
8
|
+
|
|
9
|
+
import {getParts, parseHelm} from './utils';
|
|
10
|
+
import {getMonomerLib} from './package';
|
|
11
|
+
|
|
12
|
+
export const enum Temps {
|
|
13
|
+
helmMonomerPlacer = 'bio-helmMonomerPlacer',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class HelmMonomerPlacer {
|
|
17
|
+
private _allPartsList: string[][] = null;
|
|
18
|
+
private _lengthsList: number[][] = null;
|
|
19
|
+
|
|
20
|
+
private monomerLib: IMonomerLib;
|
|
21
|
+
|
|
22
|
+
public monomerCharWidth: number = 7;
|
|
23
|
+
public leftPadding: number = 5;
|
|
24
|
+
|
|
25
|
+
constructor(public readonly col: DG.Column<string>) {
|
|
26
|
+
this.col.dataFrame.onDataChanged.subscribe();
|
|
27
|
+
this.monomerLib = getMonomerLib();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** @param rowIdx Row index of the table {@link DG.DataFrame}, HelmMonomerPlacer is {@link DG.Column} based */
|
|
31
|
+
public getCellAllPartsLengths(rowIdx: number): [string[], number[], number[]] {
|
|
32
|
+
if (this._allPartsList === null)
|
|
33
|
+
this._allPartsList = new Array<string[]>(this.col.length).fill(null);
|
|
34
|
+
|
|
35
|
+
if (this._lengthsList === null)
|
|
36
|
+
this._lengthsList = new Array<number[]>(this.col.length).fill(null);
|
|
37
|
+
|
|
38
|
+
const [allParts, lengths] = this.getCellMonomerLengthsForSeq(rowIdx);
|
|
39
|
+
|
|
40
|
+
const sumLengths: number[] = new Array<number>(lengths.length + 1);
|
|
41
|
+
sumLengths[0] = this.leftPadding; // padding
|
|
42
|
+
for (let pos: number = 1; pos < sumLengths.length; pos++)
|
|
43
|
+
sumLengths[pos] = sumLengths[pos - 1] + lengths[pos - 1];
|
|
44
|
+
return [allParts, lengths, sumLengths];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
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;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return [allParts, lengths];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getAllParts(rowIdx: number): string[] {
|
|
60
|
+
const seq: string | null = this.col.get(rowIdx);
|
|
61
|
+
const subParts: string[] = parseHelm(seq);
|
|
62
|
+
return seq ? getParts(subParts, seq) : [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
getMonomer(monomerSymbol: any): Monomer | null {
|
|
66
|
+
let res: Monomer = null;
|
|
67
|
+
for (const polymerType of this.monomerLib.getPolymerTypes()) {
|
|
68
|
+
res = this.monomerLib.getMonomer(polymerType, monomerSymbol);
|
|
69
|
+
if (res) break;
|
|
70
|
+
}
|
|
71
|
+
return res ?? null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public static getOrCreate(col: DG.Column<string>): HelmMonomerPlacer {
|
|
75
|
+
if (!(Temps.helmMonomerPlacer in col.temp)) col.temp[Temps.helmMonomerPlacer] = new HelmMonomerPlacer(col);
|
|
76
|
+
return col.temp[Temps.helmMonomerPlacer];
|
|
77
|
+
}
|
|
78
|
+
}
|
package/src/package-test.ts
CHANGED
package/src/package.ts
CHANGED
|
@@ -17,10 +17,13 @@ let monomerLib: IMonomerLib | null = null;
|
|
|
17
17
|
|
|
18
18
|
//tags: init
|
|
19
19
|
export async function initHelm(): Promise<void> {
|
|
20
|
-
return Promise.all([
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
return Promise.all([
|
|
21
|
+
new Promise((resolve, reject) => {
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
dojo.ready(function() { resolve(null); });
|
|
24
|
+
}),
|
|
25
|
+
grok.functions.call('Bio:getBioLib'),
|
|
26
|
+
])
|
|
24
27
|
.then(([_, lib]: [void, IMonomerLib]) => {
|
|
25
28
|
monomerLib = lib;
|
|
26
29
|
rewriteLibraries(); // initHelm()
|
|
@@ -51,6 +54,10 @@ export async function initHelm(): Promise<void> {
|
|
|
51
54
|
});
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
export function getMonomerLib(): IMonomerLib {
|
|
58
|
+
return monomerLib;
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
function rewriteLibraries() {
|
|
55
62
|
org.helm.webeditor.Monomers.clear();
|
|
56
63
|
monomerLib.getPolymerTypes().forEach((polymerType) => {
|
|
@@ -4,7 +4,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
|
|
5
5
|
import {_package} from '../package-test';
|
|
6
6
|
import {after, before, category, delay, expect, expectObject, test} from '@datagrok-libraries/utils/src/test';
|
|
7
|
-
import {findMonomers} from '../utils';
|
|
7
|
+
import {findMonomers, parseHelm} from '../utils';
|
|
8
8
|
import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
9
9
|
|
|
10
10
|
const LIB_STORAGE_NAME = 'Libraries';
|
|
@@ -50,7 +50,8 @@ category('findMonomers', () => {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function _testFindMonomers(testHelmValue: string, tgtMissedSet: Set<string>): void {
|
|
53
|
-
const
|
|
53
|
+
const monomerSymbolList: string[] = parseHelm(testHelmValue);
|
|
54
|
+
const resMissedSet: Set<string> = findMonomers(monomerSymbolList);
|
|
54
55
|
expectObject(resMissedSet, tgtMissedSet);
|
|
55
56
|
}
|
|
56
57
|
});
|
package/src/tests/helm-tests.ts
CHANGED
|
@@ -2,11 +2,11 @@ import * as grok from 'datagrok-api/grok';
|
|
|
2
2
|
import * as ui from 'datagrok-api/ui';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
-
import {_package} from '../package-test';
|
|
6
5
|
import {after, before, category, delay, expect, test, expectArray} from '@datagrok-libraries/utils/src/test';
|
|
7
6
|
//import {findMonomers, helmToFasta, helmToPeptide, helmToRNA, initHelm} from '../package';
|
|
8
7
|
import {parseHelm} from '../utils';
|
|
9
8
|
|
|
9
|
+
import {_package} from '../package-test';
|
|
10
10
|
|
|
11
11
|
category('Helm', () => {
|
|
12
12
|
//These tests require webservice that is not present on test stand
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as ui from 'datagrok-api/ui';
|
|
3
|
+
import * as DG from 'datagrok-api/dg';
|
|
4
|
+
|
|
5
|
+
import $ from 'cash-dom';
|
|
6
|
+
|
|
7
|
+
import {category, expect, test, awaitCheck, delay} from '@datagrok-libraries/utils/src/test';
|
|
8
|
+
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
9
|
+
import {TAGS as helmTAGS} from '../constants';
|
|
10
|
+
|
|
11
|
+
category('renderers', () => {
|
|
12
|
+
test('missedInLib', async () => { await _testMissedInLib(); });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
async function _testMissedInLib() {
|
|
16
|
+
const df: DG.DataFrame = await grok.dapi.files.readCsv('System:AppData/Helm/tests/sample_HELM-missedInLib.csv');
|
|
17
|
+
const helmCol: DG.Column<string> = df.getCol('HELM');
|
|
18
|
+
|
|
19
|
+
const tv: DG.TableView = grok.shell.addTableView(df);
|
|
20
|
+
await awaitCheck(() => {
|
|
21
|
+
return $(tv.root).find('.d4-grid canvas').length > 0;
|
|
22
|
+
}, 'Table view canvas not found', 100);
|
|
23
|
+
|
|
24
|
+
expect(helmCol.semType, DG.SEMTYPE.MACROMOLECULE);
|
|
25
|
+
expect(helmCol.getTag(DG.TAGS.UNITS), NOTATION.HELM);
|
|
26
|
+
expect(helmCol.getTag(DG.TAGS.CELL_RENDERER), 'helm');
|
|
27
|
+
|
|
28
|
+
const cellRendererErrorJson: string = helmCol.getTag(helmTAGS.cellRendererRenderError);
|
|
29
|
+
if (!!cellRendererErrorJson) {
|
|
30
|
+
const cellRendererError: any = JSON.parse(cellRendererErrorJson);
|
|
31
|
+
const err = new Error(cellRendererError['message']);
|
|
32
|
+
err.stack = cellRendererError['stack'];
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -60,7 +60,7 @@ export function parseHelm(s: string) {
|
|
|
60
60
|
const firstPiece = monomer.substring(0, monomer.indexOf('('));
|
|
61
61
|
const thirdPiece = monomer.substring(monomer.lastIndexOf(')') + 1);
|
|
62
62
|
const secondPiece = monomer.substring(firstPiece.length + 1, monomer.length - thirdPiece.length - 1);
|
|
63
|
-
const elements =[firstPiece, secondPiece, thirdPiece];
|
|
63
|
+
const elements = [firstPiece, secondPiece, thirdPiece];
|
|
64
64
|
for (const el of elements)
|
|
65
65
|
ss.push(el);
|
|
66
66
|
} else {
|
|
@@ -94,7 +94,8 @@ export function parseHelm(s: string) {
|
|
|
94
94
|
// return new Set(helmPartList.filter((val) => !monomerNameList.includes(val)));
|
|
95
95
|
// }
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
/** Searches monomers of {@link helmString} for missed. */
|
|
98
|
+
export function findMonomers(monomerSymbolList: string[]): Set<string> {
|
|
98
99
|
//@ts-ignore
|
|
99
100
|
const types = Object.keys(org.helm.webeditor.monomerTypeList());
|
|
100
101
|
const monomers: any = [];
|
|
@@ -107,8 +108,7 @@ export function findMonomers(helmString: string) {
|
|
|
107
108
|
monomerNames.push(monomers[i][k].id);
|
|
108
109
|
});
|
|
109
110
|
}
|
|
110
|
-
|
|
111
|
-
return new Set(splitString.filter((val) => !monomerNames.includes(val)));
|
|
111
|
+
return new Set(monomerSymbolList.filter((val) => !monomerNames.includes(val)));
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
function split(s: string, sep: string) {
|
|
@@ -192,14 +192,14 @@ function unescape(s: string) {
|
|
|
192
192
|
|
|
193
193
|
return s.replace(/[\\]./g, function(m) {
|
|
194
194
|
switch (m) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
195
|
+
case '\\r':
|
|
196
|
+
return '\r';
|
|
197
|
+
case '\\n':
|
|
198
|
+
return '\n';
|
|
199
|
+
case '\\t':
|
|
200
|
+
return '\t';
|
|
201
|
+
default:
|
|
202
|
+
return m.substring(1);
|
|
203
203
|
}
|
|
204
204
|
});
|
|
205
205
|
}
|