@datagrok/helm 2.1.30 → 2.1.32
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 +18 -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 +5 -5
- package/src/cell-renderer.ts +7 -12
- package/src/helm-monomer-placer.ts +55 -24
- package/src/package-test.ts +1 -0
- package/src/package.ts +17 -15
- package/src/tests/get-all-parts-tests.ts +34 -0
- package/src/tests/properties-widget-tests.ts +21 -3
- package/src/widgets/properties-widget.ts +5 -5
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.32",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Oleksandra Serhiienko",
|
|
7
7
|
"email": "oserhiienko@datagrok.ai"
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"helm/JSDraw/Pistoia.HELM-uncompressed.js"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@datagrok-libraries/bio": "^5.
|
|
19
|
-
"@datagrok-libraries/chem-meta": "^1.2.
|
|
18
|
+
"@datagrok-libraries/bio": "^5.40.7",
|
|
19
|
+
"@datagrok-libraries/chem-meta": "^1.2.3",
|
|
20
20
|
"@datagrok-libraries/utils": "^4.1.45",
|
|
21
21
|
"cash-dom": "^8.1.1",
|
|
22
22
|
"datagrok-api": "^1.17.0",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"@typescript-eslint/parser": "^5.11.0",
|
|
38
38
|
"eslint": "^8.18.0",
|
|
39
39
|
"eslint-config-google": "^0.14.0",
|
|
40
|
-
"@datagrok/bio": "^2.11
|
|
41
|
-
"@datagrok/chem": "^1.
|
|
40
|
+
"@datagrok/bio": "^2.12.11",
|
|
41
|
+
"@datagrok/chem": "^1.9.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"link-all": "npm link @datagrok-libraries/chem-meta datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
|
package/src/cell-renderer.ts
CHANGED
|
@@ -29,7 +29,7 @@ function getSeqMonomerFromHelm(
|
|
|
29
29
|
resSeqMonomer = {symbol: symbol, polymerType: polymerType};
|
|
30
30
|
}
|
|
31
31
|
if (!resSeqMonomer)
|
|
32
|
-
|
|
32
|
+
throw new Error(`Monomer not found for symbol = '${symbol}' and helmPrefix = '${helmPrefix}'.`);
|
|
33
33
|
return resSeqMonomer;
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -162,7 +162,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
162
162
|
const argsX = e.offsetX - gcb.x;
|
|
163
163
|
const argsY = e.offsetY - gcb.y;
|
|
164
164
|
|
|
165
|
-
const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
|
|
165
|
+
const helmPlacer = HelmMonomerPlacer.getOrCreate(gridCell.gridColumn, tableCol);
|
|
166
166
|
const editor: IEditor | null = helmPlacer.getEditor(gridCell.tableRowIndex!);
|
|
167
167
|
let seqMonomer: ISeqMonomer | null;
|
|
168
168
|
let missedMonomers: Set<string> = new Set<string>(); // of .size = 0
|
|
@@ -189,15 +189,10 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
189
189
|
|
|
190
190
|
if (seqMonomer) {
|
|
191
191
|
if (!missedMonomers.has(seqMonomer.symbol)) {
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
ui.tooltip.show(ui.divV([
|
|
197
|
-
ui.divText(seqMonomer.symbol),
|
|
198
|
-
monomerSvg,
|
|
199
|
-
]), e.x + 16, e.y + 16);
|
|
200
|
-
}
|
|
192
|
+
const tooltipElements: HTMLElement[] = [ui.div(seqMonomer.symbol)];
|
|
193
|
+
const monomerDiv = helmPlacer.monomerLib.getTooltip(seqMonomer.polymerType, seqMonomer.symbol);
|
|
194
|
+
tooltipElements.push(monomerDiv);
|
|
195
|
+
ui.tooltip.show(ui.divV(tooltipElements), e.x + 16, e.y + 16);
|
|
201
196
|
} else {
|
|
202
197
|
ui.tooltip.show(ui.divV([
|
|
203
198
|
ui.divText(`Monomer '${seqMonomer.symbol}' not found.`),
|
|
@@ -244,7 +239,7 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
244
239
|
const monomerList = parseHelm(seq);
|
|
245
240
|
const monomers: Set<string> = new Set<string>(monomerList);
|
|
246
241
|
const missedMonomers: Set<string> = findMonomers(monomerList);
|
|
247
|
-
const helmPlacer = HelmMonomerPlacer.getOrCreate(tableCol);
|
|
242
|
+
const helmPlacer = HelmMonomerPlacer.getOrCreate(gridCell.gridColumn, tableCol);
|
|
248
243
|
|
|
249
244
|
if (missedMonomers.size == 0) {
|
|
250
245
|
// Recreate host to avoid hanging in window.dojox.gfx.svg.Text.prototype.getTextWidth
|
|
@@ -3,11 +3,13 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
5
|
import wu from 'wu';
|
|
6
|
+
import {Unsubscribable} from 'rxjs';
|
|
6
7
|
|
|
7
8
|
import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types/index';
|
|
8
9
|
|
|
9
10
|
import {getParts, parseHelm} from './utils';
|
|
10
|
-
|
|
11
|
+
|
|
12
|
+
import {_package, getMonomerLib} from './package';
|
|
11
13
|
|
|
12
14
|
export const enum Temps {
|
|
13
15
|
helmMonomerPlacer = 'bio-helmMonomerPlacer',
|
|
@@ -36,31 +38,60 @@ export interface IEditorPoint {
|
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export interface ISeqMonomer {
|
|
41
|
+
polymerType: string
|
|
39
42
|
symbol: string,
|
|
40
|
-
polymerType?: string
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
export class HelmMonomerPlacer {
|
|
44
|
-
private readonly
|
|
45
|
-
private readonly _lengthsList: (number[] | null)[];
|
|
46
|
-
private readonly _editorList: (IEditor | null)[];
|
|
47
|
-
|
|
46
|
+
private readonly grid: DG.Grid;
|
|
48
47
|
public readonly monomerLib: IMonomerLib;
|
|
49
48
|
|
|
49
|
+
private _allPartsList: (string[] | null)[];
|
|
50
|
+
private _lengthsList: (number[] | null)[];
|
|
51
|
+
private _editorList: (IEditor | null)[];
|
|
52
|
+
|
|
50
53
|
public monomerCharWidth: number = 7;
|
|
51
54
|
public leftPadding: number = 5;
|
|
52
55
|
public monomerTextSizeMap: { [p: string]: TextMetrics } = {};
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
private subs: Unsubscribable[] = [];
|
|
58
|
+
|
|
59
|
+
protected constructor(
|
|
60
|
+
public readonly gridCol: DG.GridColumn,
|
|
61
|
+
public readonly col: DG.Column<string>
|
|
62
|
+
) {
|
|
63
|
+
this.grid = this.gridCol.grid;
|
|
64
|
+
this.reset();
|
|
65
|
+
if (this.grid) {
|
|
66
|
+
this.subs.push(this.col.dataFrame.onDataChanged.subscribe(() => {
|
|
67
|
+
try {
|
|
68
|
+
this.reset();
|
|
69
|
+
} catch (err: any) {
|
|
70
|
+
console.error(err);
|
|
71
|
+
}
|
|
72
|
+
}));
|
|
73
|
+
this.subs.push(grok.events.onViewRemoved.subscribe((view: DG.View) => {
|
|
74
|
+
try {
|
|
75
|
+
if (this.gridCol.grid.view?.id === view.id) this.destroy();
|
|
76
|
+
} catch (err: any) {
|
|
77
|
+
console.error(err);
|
|
78
|
+
}
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
56
81
|
this.monomerLib = getMonomerLib();
|
|
57
|
-
this.monomerLib.onChanged.subscribe(this.monomerLibOnChanged.bind(this));
|
|
82
|
+
this.subs.push(this.monomerLib.onChanged.subscribe(this.monomerLibOnChanged.bind(this)));
|
|
83
|
+
}
|
|
58
84
|
|
|
85
|
+
private reset(): void {
|
|
59
86
|
this._allPartsList = new Array<string[] | null>(this.col.length).fill(null);
|
|
60
87
|
this._lengthsList = new Array<number[] | null>(this.col.length).fill(null);
|
|
61
88
|
this._editorList = new Array<IEditor | null>(this.col.length).fill(null);
|
|
62
89
|
}
|
|
63
90
|
|
|
91
|
+
private destroy(): void {
|
|
92
|
+
for (const sub of this.subs) sub.unsubscribe();
|
|
93
|
+
}
|
|
94
|
+
|
|
64
95
|
/** Skips cell for the fallback rendering */
|
|
65
96
|
public skipCell(rowIdx: number): void {
|
|
66
97
|
this._allPartsList[rowIdx] = [];
|
|
@@ -80,8 +111,10 @@ export class HelmMonomerPlacer {
|
|
|
80
111
|
|
|
81
112
|
private getCellMonomerLengthsForSeq(rowIdx: number): [string[], number[]] {
|
|
82
113
|
let allParts: string[] | null = this._allPartsList![rowIdx];
|
|
83
|
-
if (allParts === null)
|
|
84
|
-
|
|
114
|
+
if (allParts === null) {
|
|
115
|
+
const seq = this.col.get(rowIdx);
|
|
116
|
+
allParts = this._allPartsList![rowIdx] = getAllParts(seq);
|
|
117
|
+
}
|
|
85
118
|
|
|
86
119
|
let lengths: number[] | null = this._lengthsList![rowIdx];
|
|
87
120
|
if (lengths === null) {
|
|
@@ -95,12 +128,6 @@ export class HelmMonomerPlacer {
|
|
|
95
128
|
return [allParts, lengths];
|
|
96
129
|
}
|
|
97
130
|
|
|
98
|
-
getAllParts(rowIdx: number): string[] {
|
|
99
|
-
const seq: string | null = this.col.get(rowIdx);
|
|
100
|
-
const monomerList: string[] = seq ? parseHelm(seq) : [];
|
|
101
|
-
return seq ? getParts(monomerList, seq) : [];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
131
|
getMonomer(monomer: ISeqMonomer): Monomer | null {
|
|
105
132
|
let res: Monomer | null = null;
|
|
106
133
|
if (monomer.polymerType)
|
|
@@ -117,15 +144,14 @@ export class HelmMonomerPlacer {
|
|
|
117
144
|
// -- Handle events --
|
|
118
145
|
|
|
119
146
|
private monomerLibOnChanged(_value: any): void {
|
|
120
|
-
this.
|
|
121
|
-
this.
|
|
122
|
-
this._editorList.fill(null);
|
|
123
|
-
// TODO: Invalidate all grids of this.col.dataFrame
|
|
147
|
+
this.reset();
|
|
148
|
+
if (this.grid) this.grid.invalidate();
|
|
124
149
|
}
|
|
125
150
|
|
|
126
|
-
public static getOrCreate(col: DG.Column<string>): HelmMonomerPlacer {
|
|
127
|
-
|
|
128
|
-
|
|
151
|
+
public static getOrCreate(gridCol: DG.GridColumn, col: DG.Column<string>): HelmMonomerPlacer {
|
|
152
|
+
let res: HelmMonomerPlacer = gridCol.temp[Temps.helmMonomerPlacer];
|
|
153
|
+
if (!res) res = gridCol.temp[Temps.helmMonomerPlacer] = new HelmMonomerPlacer(gridCol, col);
|
|
154
|
+
return res;
|
|
129
155
|
}
|
|
130
156
|
|
|
131
157
|
public setEditor(tableRowIndex: number, editor: IEditor) {
|
|
@@ -136,3 +162,8 @@ export class HelmMonomerPlacer {
|
|
|
136
162
|
return this._editorList![tableRowIndex];
|
|
137
163
|
}
|
|
138
164
|
}
|
|
165
|
+
|
|
166
|
+
export function getAllParts(seq: string | null): string[] {
|
|
167
|
+
const monomerList: string[] = seq ? parseHelm(seq) : [];
|
|
168
|
+
return seq ? getParts(monomerList, seq) : [];
|
|
169
|
+
}
|
package/src/package-test.ts
CHANGED
package/src/package.ts
CHANGED
|
@@ -7,7 +7,7 @@ import $ from 'cash-dom';
|
|
|
7
7
|
|
|
8
8
|
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
9
9
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
10
|
-
import {
|
|
10
|
+
import {GapOriginals, SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
11
11
|
import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
|
|
12
12
|
import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
13
13
|
|
|
@@ -156,17 +156,17 @@ export function helmCellRenderer(): HelmCellRenderer {
|
|
|
156
156
|
return new HelmCellRenderer();
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
function checkMonomersAndOpenWebEditor(cell
|
|
159
|
+
function checkMonomersAndOpenWebEditor(cell: DG.Cell, value?: string, units?: string) {
|
|
160
160
|
const cellValue: string = !!cell && units === undefined ? cell.value : value;
|
|
161
161
|
const monomerList: string[] = parseHelm(cellValue);
|
|
162
|
-
const
|
|
163
|
-
if (
|
|
162
|
+
const missedMonomerSet = findMonomers(monomerList);
|
|
163
|
+
if (missedMonomerSet.size === 0)
|
|
164
164
|
webEditor(cell, value, units);
|
|
165
|
-
else if (
|
|
166
|
-
grok.shell.warning(`WebEditor doesn't support Helm with gaps '${
|
|
165
|
+
else if (missedMonomerSet.size === 1 && missedMonomerSet.has(GapOriginals[NOTATION.HELM]))
|
|
166
|
+
grok.shell.warning(`WebEditor doesn't support Helm with gaps '${GapOriginals[NOTATION.HELM]}'.`);
|
|
167
167
|
else {
|
|
168
168
|
grok.shell.warning(
|
|
169
|
-
`Monomers ${Array.from(
|
|
169
|
+
`Monomers ${Array.from(missedMonomerSet).map((m) => `'${m}'`).join(', ')} are absent! <br/>` +
|
|
170
170
|
`Please, upload the monomer library! <br/>` +
|
|
171
171
|
`<a href="https://datagrok.ai/help/domains/bio/macromolecules" target="_blank">Learn more</a>`);
|
|
172
172
|
}
|
|
@@ -187,11 +187,11 @@ export function editMoleculeCell(cell: DG.GridCell): void {
|
|
|
187
187
|
export function openEditor(mol: string): void {
|
|
188
188
|
const df = grok.shell.tv.grid.dataFrame;
|
|
189
189
|
const col = df.columns.bySemType('Macromolecule')!;
|
|
190
|
-
const
|
|
190
|
+
const colSh = SeqHandler.forColumn(col);
|
|
191
191
|
const colUnits = col.getTag(DG.TAGS.UNITS);
|
|
192
192
|
if (colUnits === NOTATION.HELM)
|
|
193
193
|
checkMonomersAndOpenWebEditor(df.currentCell, undefined, undefined);
|
|
194
|
-
const convert =
|
|
194
|
+
const convert = colSh.getConverter(NOTATION.HELM);
|
|
195
195
|
const helmMol = convert(mol);
|
|
196
196
|
checkMonomersAndOpenWebEditor(df.currentCell, helmMol, col.getTag(DG.TAGS.UNITS));
|
|
197
197
|
}
|
|
@@ -204,11 +204,13 @@ export function propertiesWidget(sequence: DG.SemanticValue): DG.Widget {
|
|
|
204
204
|
return getPropertiesWidget(sequence);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
function webEditor(cell
|
|
207
|
+
function webEditor(cell: DG.Cell, value?: string, units?: string) {
|
|
208
208
|
const view = ui.div();
|
|
209
|
-
const df = grok.shell.tv.grid.dataFrame;
|
|
210
|
-
const col = df.columns.bySemType('Macromolecule')!;
|
|
211
|
-
const
|
|
209
|
+
// const df = grok.shell.tv.grid.dataFrame;
|
|
210
|
+
// const col = df.columns.bySemType('Macromolecule')!;
|
|
211
|
+
const col = cell.column;
|
|
212
|
+
const sh = SeqHandler.forColumn(col);
|
|
213
|
+
const rowIdx = cell.rowIndex;
|
|
212
214
|
// @ts-ignore
|
|
213
215
|
org.helm.webeditor.MolViewer.molscale = 0.8;
|
|
214
216
|
// @ts-ignore
|
|
@@ -244,13 +246,13 @@ function webEditor(cell?: DG.Cell, value?: string, units?: string) {
|
|
|
244
246
|
ui.dialog({showHeader: false, showFooter: true})
|
|
245
247
|
.add(view)
|
|
246
248
|
.onOK(() => {
|
|
247
|
-
const helmValue = app.canvas.getHelm(true).replace(/<\/span>/g, '')
|
|
249
|
+
const helmValue: string = app.canvas.getHelm(true).replace(/<\/span>/g, '')
|
|
248
250
|
.replace(/<span style='background:#bbf;'>/g, '');
|
|
249
251
|
if (!!cell) {
|
|
250
252
|
if (units === undefined)
|
|
251
253
|
cell.value = helmValue;
|
|
252
254
|
else {
|
|
253
|
-
const convertedRes =
|
|
255
|
+
const convertedRes = sh.convertHelmToFastaSeparator(helmValue, units!, sh.separator);
|
|
254
256
|
cell.value = convertedRes;
|
|
255
257
|
}
|
|
256
258
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
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 {after, before, category, delay, expect, test, expectArray} from '@datagrok-libraries/utils/src/test';
|
|
6
|
+
|
|
7
|
+
import {getAllParts} from '../helm-monomer-placer';
|
|
8
|
+
|
|
9
|
+
category('getAllParts', () => {
|
|
10
|
+
/** All parts of Helm string are required for fallback rendering. */
|
|
11
|
+
|
|
12
|
+
const tests: { [testName: string]: { tgt: string[]; seq: string } } = {
|
|
13
|
+
'peptideSimpleSingleChar': {
|
|
14
|
+
seq: 'PEPTIDE1{L.V.A}$$$$',
|
|
15
|
+
tgt: ['PEPTIDE1{', 'L', '.', 'V', '.', 'A', '}$$$$'],
|
|
16
|
+
},
|
|
17
|
+
'peptideSimpleMultiChar': {
|
|
18
|
+
seq: 'PEPTIDE1{[Ac].V.A}$$$$',
|
|
19
|
+
/* doubt joining square brackets to separator or notation is correct */
|
|
20
|
+
tgt: ['PEPTIDE1{[', 'Ac', '].', 'V', '.', 'A', '}$$$$'],
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
for (const [testName, testData] of Object.entries(tests)) {
|
|
25
|
+
test(`${testName}`, async () => {
|
|
26
|
+
await _testAllParts(testData.seq, testData.tgt);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
async function _testAllParts(seq: string | null, tgt: string[]): Promise<void> {
|
|
32
|
+
const res: string[] = getAllParts(seq);
|
|
33
|
+
expectArray(res, tgt);
|
|
34
|
+
}
|
|
@@ -2,9 +2,11 @@ import * as ui from 'datagrok-api/ui';
|
|
|
2
2
|
import * as DG from 'datagrok-api/dg';
|
|
3
3
|
import * as grok from 'datagrok-api/grok';
|
|
4
4
|
|
|
5
|
-
import {category, expect, expectObject, test} from '@datagrok-libraries/utils/src/test';
|
|
5
|
+
import {after, before, category, expect, expectObject, test} from '@datagrok-libraries/utils/src/test';
|
|
6
6
|
import {ALPHABET, NOTATION, TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
7
|
-
import {
|
|
7
|
+
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
8
|
+
import {getUserLibSettings, setUserLibSettings, setUserLibSettingsForTests} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
|
|
9
|
+
import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
8
10
|
|
|
9
11
|
import {getPropertiesDict} from '../widgets/properties-widget';
|
|
10
12
|
|
|
@@ -60,6 +62,22 @@ const TestsData: {
|
|
|
60
62
|
};
|
|
61
63
|
|
|
62
64
|
category('properties-widget', () => {
|
|
65
|
+
let monomerLibHelper: IMonomerLibHelper;
|
|
66
|
+
/** Backup actual user's monomer libraries settings */
|
|
67
|
+
let userLibSettings: any = null;
|
|
68
|
+
|
|
69
|
+
before(async () => {
|
|
70
|
+
monomerLibHelper = await getMonomerLibHelper();
|
|
71
|
+
userLibSettings = getUserLibSettings();
|
|
72
|
+
await setUserLibSettingsForTests();
|
|
73
|
+
await monomerLibHelper.loadLibraries(true); // load default libraries
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
after(async () => {
|
|
77
|
+
await setUserLibSettings(userLibSettings);
|
|
78
|
+
await monomerLibHelper.loadLibraries(true); // load user settings libraries
|
|
79
|
+
});
|
|
80
|
+
|
|
63
81
|
for (const [testName, testData] of Object.entries(TestsData)) {
|
|
64
82
|
test(testName, async () => {
|
|
65
83
|
testPropertiesDict(testData.seq, testData.units, testData.separator, testData.alphabet, testData.res);
|
|
@@ -75,7 +93,7 @@ function testPropertiesDict(
|
|
|
75
93
|
col.setTag(DG.TAGS.UNITS, units);
|
|
76
94
|
if (separator) col.setTag(bioTAGS.separator, separator);
|
|
77
95
|
if (alphabet) col.setTag(bioTAGS.alphabet, alphabet);
|
|
78
|
-
const uh =
|
|
96
|
+
const uh = SeqHandler.forColumn(col);
|
|
79
97
|
const actPropDict = getPropertiesDict(seq, uh);
|
|
80
98
|
expectObject(actPropDict, expPropDict);
|
|
81
99
|
}
|
|
@@ -4,13 +4,13 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
|
|
5
5
|
import $ from 'cash-dom';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
8
8
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
9
9
|
|
|
10
10
|
import {removeGapsFromHelm} from '../utils';
|
|
11
11
|
|
|
12
|
-
export function getPropertiesDict(seq: string,
|
|
13
|
-
const helmString =
|
|
12
|
+
export function getPropertiesDict(seq: string, sh: SeqHandler): {} {
|
|
13
|
+
const helmString = sh.isHelm() ? seq : sh.getConverter(NOTATION.HELM)(seq);
|
|
14
14
|
// Remove gap symbols for compatibility with WebEditor
|
|
15
15
|
const helmString2 = removeGapsFromHelm(helmString);
|
|
16
16
|
|
|
@@ -36,8 +36,8 @@ export function getPropertiesDict(seq: string, uh: UnitsHandler): {} {
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
export function getPropertiesWidget(value: DG.SemanticValue): DG.Widget {
|
|
39
|
-
const
|
|
40
|
-
const propDict = getPropertiesDict(value.value,
|
|
39
|
+
const sh = SeqHandler.forColumn(value.cell.column);
|
|
40
|
+
const propDict = getPropertiesDict(value.value, sh);
|
|
41
41
|
return new DG.Widget(
|
|
42
42
|
ui.tableFromMap(propDict)
|
|
43
43
|
);
|