@datagrok/sequence-translator 1.4.7 → 1.4.10
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 -1
- package/CHANGELOG.md +25 -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 +9 -9
- package/src/apps/common/model/oligo-toolkit-package.ts +13 -7
- package/src/package.ts +8 -7
- package/src/polytool/const.ts +1 -0
- package/src/polytool/{pt-conversion.ts → conversion/pt-chain.ts} +37 -241
- package/src/polytool/conversion/pt-conversion.ts +27 -0
- package/src/polytool/conversion/pt-misc.ts +183 -0
- package/src/polytool/pt-dialog.ts +135 -6
- package/src/polytool/{pt-enumeration-helm-dialog.ts → pt-enumerate-seq-dialog.ts} +241 -112
- package/src/polytool/pt-enumeration-helm.ts +2 -2
- package/src/polytool/pt-placeholders-breadth-input.ts +80 -39
- package/src/polytool/pt-placeholders-input.ts +96 -35
- package/src/polytool/pt-unrule.ts +1 -1
- package/src/polytool/types.ts +5 -1
- package/src/tests/polytool-chain-from-notation-tests.ts +3 -4
- package/src/tests/polytool-chain-parse-notation-tests.ts +2 -1
- package/src/tests/polytool-convert-tests.ts +2 -1
- package/src/tests/toAtomicLevel-tests.ts +1 -2
- package/src/utils/cell-renderer-cyclized.ts +37 -0
- package/src/utils/context-menu.ts +1 -1
- package/src/utils/cyclized.ts +23 -26
|
@@ -2,9 +2,10 @@ import * as ui from 'datagrok-api/ui';
|
|
|
2
2
|
import * as grok from 'datagrok-api/grok';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
-
import {Unsubscribable} from 'rxjs';
|
|
5
|
+
import {fromEvent, Unsubscribable} from 'rxjs';
|
|
6
6
|
import {PolyToolBreadthPlaceholder} from './types';
|
|
7
7
|
import {parseMonomerSymbolList} from './pt-placeholders-input';
|
|
8
|
+
import {GridCellRenderArgs} from 'datagrok-api/dg';
|
|
8
9
|
|
|
9
10
|
export class PolyToolPlaceholdersBreadthInput extends DG.JsInputBase<DG.DataFrame> {
|
|
10
11
|
get inputType(): string { return 'Breadth'; }
|
|
@@ -15,71 +16,110 @@ export class PolyToolPlaceholdersBreadthInput extends DG.JsInputBase<DG.DataFram
|
|
|
15
16
|
|
|
16
17
|
getValue(): DG.DataFrame { return this.grid.dataFrame; }
|
|
17
18
|
|
|
18
|
-
setValue(value: DG.DataFrame): void {
|
|
19
|
+
setValue(value: DG.DataFrame): void {
|
|
20
|
+
this.setDataFrame(value);
|
|
21
|
+
}
|
|
19
22
|
|
|
20
23
|
getStringValue(): string { return this.grid.dataFrame.toCsv(); }
|
|
21
24
|
|
|
22
|
-
setStringValue(str: string): void {
|
|
25
|
+
setStringValue(str: string): void {
|
|
26
|
+
this.setDataFrame(DG.DataFrame.fromCsv(str));
|
|
27
|
+
}
|
|
23
28
|
|
|
24
29
|
get placeholdersBreadthValue(): PolyToolBreadthPlaceholder[] {
|
|
25
30
|
return dfToPlaceholdersBreadth(this.grid.dataFrame);
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
private readonly gridHost: HTMLDivElement;
|
|
29
|
-
public
|
|
34
|
+
public grid: DG.Grid;
|
|
30
35
|
|
|
31
36
|
private subs: Unsubscribable[] = [];
|
|
32
37
|
|
|
33
|
-
protected constructor(
|
|
38
|
+
protected constructor(
|
|
39
|
+
private readonly name: string | undefined,
|
|
40
|
+
heightRowCount?: number, options?: {}
|
|
41
|
+
) {
|
|
34
42
|
super();
|
|
35
43
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
this.gridHost = ui.div([], {
|
|
44
|
+
this.caption = name ?? '';
|
|
45
|
+
this.root.classList.add('ui-input-polytool-pos-grid');
|
|
46
|
+
this.root.append(this.gridHost = ui.div([], {
|
|
39
47
|
classes: 'ui-input-editor',
|
|
40
48
|
style: {width: '100%', height: '100%', marginTop: '-8px', marginBottom: '8px', paddingBottom: '4px'},
|
|
49
|
+
}));
|
|
50
|
+
this.render(heightRowCount, options).then(() => {});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
detach(): void {
|
|
54
|
+
for (const sub of this.subs) sub.unsubscribe();
|
|
55
|
+
for (const sub of this.dataFrameSubs) sub.unsubscribe();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async render(heightRowCount?: number, options?: {}): Promise<void> {
|
|
59
|
+
let removeCol: DG.Column<boolean>;
|
|
60
|
+
const df: DG.DataFrame = DG.DataFrame.fromColumns([
|
|
61
|
+
removeCol = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'Remove', 0),
|
|
62
|
+
DG.Column.fromType(DG.COLUMN_TYPE.INT, 'Start', 0),
|
|
63
|
+
DG.Column.fromType(DG.COLUMN_TYPE.INT, 'End', 0),
|
|
64
|
+
DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'Monomers', 0),
|
|
65
|
+
])!;
|
|
66
|
+
removeCol.setTag(DG.TAGS.FRIENDLY_NAME, '');
|
|
67
|
+
this.grid = (await df.plot.fromType(DG.VIEWER.GRID, options)) as DG.Grid;
|
|
68
|
+
this.grid.sort(['Start', 'End']);
|
|
69
|
+
this.grid.columns.byIndex(1)!.width = this.grid.props.rowHeight + 2;
|
|
70
|
+
|
|
71
|
+
this.grid.onCellRender.subscribe((eventArgs: GridCellRenderArgs) => {
|
|
72
|
+
const gridCell = eventArgs.cell;
|
|
73
|
+
if (gridCell.tableColumn?.name == removeCol.name && (gridCell?.tableRowIndex ?? -1) >= 0) {
|
|
74
|
+
gridCell.element = ui.div(ui.icons.delete(() => {
|
|
75
|
+
this.grid.dataFrame.rows.removeAt(gridCell.tableRowIndex!);
|
|
76
|
+
}, 'Delete'), {
|
|
77
|
+
style: {
|
|
78
|
+
height: `${gridCell.grid.props.rowHeight}px`, color: 'var(--grey-6)',
|
|
79
|
+
display: 'flex', flexDirection: 'row', justifyContent: 'center'
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
41
83
|
});
|
|
42
84
|
|
|
43
|
-
this.grid
|
|
44
|
-
this.
|
|
85
|
+
this.updateGridHeight(heightRowCount ?? this.grid.dataFrame.rowCount + 0.7);
|
|
86
|
+
this.subs.push(ui.onSizeChanged(this.grid.root)
|
|
87
|
+
.subscribe(this.gridRootOnSizeChanged.bind(this)));
|
|
88
|
+
this.subs.push(fromEvent<KeyboardEvent>(this.grid.root, 'keydown')
|
|
89
|
+
.subscribe((e: KeyboardEvent) => {
|
|
90
|
+
if (e.key === 'Enter') e.stopPropagation();
|
|
91
|
+
}));
|
|
92
|
+
this.setDataFrame(df);
|
|
45
93
|
|
|
46
|
-
if (heightRowCount != null) {
|
|
47
|
-
this.updateGridHeight(heightRowCount + 0.7);
|
|
48
|
-
} else {
|
|
49
|
-
this.updateGridHeight(this.grid.dataFrame.rowCount + 0.6);
|
|
50
|
-
this.subs.push(this.grid.dataFrame.onRowsAdded
|
|
51
|
-
.subscribe(() => { this.updateGridHeight(this.grid.dataFrame.rowCount + 0.6); }));
|
|
52
|
-
}
|
|
53
94
|
this.grid.root.style.width = `100%`;
|
|
95
|
+
this.gridHost.append(this.grid.root);
|
|
96
|
+
}
|
|
54
97
|
|
|
55
|
-
|
|
56
|
-
this.fireChanged();
|
|
57
|
-
}));
|
|
98
|
+
private dataFrameSubs: Unsubscribable[] = [];
|
|
58
99
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}));
|
|
100
|
+
private setDataFrame(dataFrame: DG.DataFrame): void {
|
|
101
|
+
for (const sub of this.dataFrameSubs) sub.unsubscribe();
|
|
102
|
+
this.grid.dataFrame = dataFrame;
|
|
63
103
|
|
|
64
|
-
this.
|
|
65
|
-
|
|
66
|
-
|
|
104
|
+
this.dataFrameSubs.push(this.grid.dataFrame.onRowsRemoved
|
|
105
|
+
.subscribe(() => {
|
|
106
|
+
this.updateGridHeight(this.grid.dataFrame.rowCount + 0.7);
|
|
107
|
+
this.fireChanged();
|
|
108
|
+
}));
|
|
109
|
+
this.dataFrameSubs.push(this.grid.dataFrame.onRowsAdded
|
|
110
|
+
.subscribe(() => { this.updateGridHeight(this.grid.dataFrame.rowCount + 0.7); }));
|
|
111
|
+
this.dataFrameSubs.push(this.grid.dataFrame.onDataChanged.subscribe(() => {
|
|
112
|
+
this.fireChanged();
|
|
113
|
+
}));
|
|
67
114
|
|
|
68
|
-
|
|
69
|
-
|
|
115
|
+
this.updateGridHeight(this.grid.dataFrame.rowCount + 0.7);
|
|
116
|
+
this.fireChanged();
|
|
70
117
|
}
|
|
71
118
|
|
|
72
119
|
public static async create(
|
|
73
120
|
name?: string, options?: {}, heightRowCount?: number
|
|
74
121
|
): Promise<PolyToolPlaceholdersBreadthInput> {
|
|
75
|
-
|
|
76
|
-
DG.Column.fromType(DG.COLUMN_TYPE.INT, 'Start', 0),
|
|
77
|
-
DG.Column.fromType(DG.COLUMN_TYPE.INT, 'End', 0),
|
|
78
|
-
DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'Monomers', 0),
|
|
79
|
-
])!;
|
|
80
|
-
const grid = (await df.plot.fromType(DG.VIEWER.GRID, options)) as DG.Grid;
|
|
81
|
-
grid.sort(['Start', 'End']);
|
|
82
|
-
return new PolyToolPlaceholdersBreadthInput(name, grid, heightRowCount);
|
|
122
|
+
return new PolyToolPlaceholdersBreadthInput(name, heightRowCount, options);
|
|
83
123
|
}
|
|
84
124
|
|
|
85
125
|
// -- Update view --
|
|
@@ -92,8 +132,9 @@ export class PolyToolPlaceholdersBreadthInput extends DG.JsInputBase<DG.DataFram
|
|
|
92
132
|
// -- Handle events --
|
|
93
133
|
|
|
94
134
|
private gridRootOnSizeChanged(): void {
|
|
95
|
-
this.grid.columns.byIndex(
|
|
96
|
-
this.grid.columns.byIndex(0)!.width - this.grid.columns.byIndex(1)!.width -
|
|
135
|
+
this.grid.columns.byIndex(4)!.width = this.grid.root.clientWidth - this.grid.horzScroll.root.offsetWidth -
|
|
136
|
+
this.grid.columns.byIndex(0)!.width - this.grid.columns.byIndex(1)!.width -
|
|
137
|
+
this.grid.columns.byIndex(2)!.width - this.grid.columns.byIndex(3)!.width - 10;
|
|
97
138
|
}
|
|
98
139
|
}
|
|
99
140
|
|
|
@@ -2,9 +2,10 @@ import * as ui from 'datagrok-api/ui';
|
|
|
2
2
|
import * as grok from 'datagrok-api/grok';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
-
import {Unsubscribable} from 'rxjs';
|
|
5
|
+
import {fromEvent, Unsubscribable} from 'rxjs';
|
|
6
6
|
|
|
7
7
|
import {PolyToolPlaceholder} from './types';
|
|
8
|
+
import {GridCellRenderArgs} from 'datagrok-api/dg';
|
|
8
9
|
|
|
9
10
|
export class PolyToolPlaceholdersInput extends DG.JsInputBase<DG.DataFrame> {
|
|
10
11
|
get inputType(): string { return 'Positions'; }
|
|
@@ -15,69 +16,126 @@ export class PolyToolPlaceholdersInput extends DG.JsInputBase<DG.DataFrame> {
|
|
|
15
16
|
|
|
16
17
|
getValue(): DG.DataFrame { return this.grid.dataFrame; }
|
|
17
18
|
|
|
18
|
-
setValue(value: DG.DataFrame): void {
|
|
19
|
+
setValue(value: DG.DataFrame): void {
|
|
20
|
+
this.setDataFrame(value);
|
|
21
|
+
}
|
|
19
22
|
|
|
20
23
|
getStringValue(): string { return this.grid.dataFrame.toCsv(); }
|
|
21
24
|
|
|
22
|
-
setStringValue(str: string): void {
|
|
25
|
+
setStringValue(str: string): void {
|
|
26
|
+
this.setDataFrame(DG.DataFrame.fromCsv(str));
|
|
27
|
+
}
|
|
23
28
|
|
|
24
29
|
get placeholdersValue(): PolyToolPlaceholder[] {
|
|
25
30
|
return dfToPlaceholders(this.grid.dataFrame);
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
private readonly gridHost: HTMLDivElement;
|
|
29
|
-
|
|
34
|
+
private grid!: DG.Grid;
|
|
30
35
|
|
|
31
36
|
private subs: Unsubscribable[] = [];
|
|
32
37
|
|
|
33
|
-
protected constructor(
|
|
38
|
+
protected constructor(
|
|
39
|
+
private readonly name: string | undefined,
|
|
40
|
+
heightRowCount?: number, options?: {},
|
|
41
|
+
) {
|
|
34
42
|
super();
|
|
35
43
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
this.gridHost = ui.div([], {
|
|
44
|
+
this.caption = name ?? '';
|
|
45
|
+
this.root.classList.add('ui-input-polytool-pos-grid');
|
|
46
|
+
this.root.append(this.gridHost = ui.div([], {
|
|
39
47
|
classes: 'ui-input-editor',
|
|
40
48
|
style: {width: '100%', height: '100%', marginTop: '-8px', marginBottom: '8px', paddingBottom: '4px'},
|
|
49
|
+
}));
|
|
50
|
+
this.render(heightRowCount, options).then(() => {});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
detach(): void {
|
|
54
|
+
for (const sub of this.subs) sub.unsubscribe();
|
|
55
|
+
for (const sub of this.dataFrameSubs) sub.unsubscribe();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async render(heightRowCount?: number, options?: {}): Promise<void> {
|
|
59
|
+
// this.captionLabel.appendChild(ui.divH([ui.divText(this.name ?? this.caption), ui.icons.add(() => {}, 'Add')]));
|
|
60
|
+
let removeCol: DG.Column<boolean>;
|
|
61
|
+
const df: DG.DataFrame = DG.DataFrame.fromColumns([
|
|
62
|
+
removeCol = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'Remove', 0),
|
|
63
|
+
DG.Column.fromType(DG.COLUMN_TYPE.INT, 'Position', 0),
|
|
64
|
+
DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'Monomers', 0),])!;
|
|
65
|
+
removeCol.setTag(DG.TAGS.FRIENDLY_NAME, '');
|
|
66
|
+
this.grid = (await df.plot.fromType(DG.VIEWER.GRID, options)) as DG.Grid;
|
|
67
|
+
this.grid.sort(['Position']);
|
|
68
|
+
this.grid.columns.byIndex(1)!.width = this.grid.props.rowHeight + 2;
|
|
69
|
+
|
|
70
|
+
this.grid.onCellRender.subscribe((eventArgs: GridCellRenderArgs) => {
|
|
71
|
+
const gridCell = eventArgs.cell;
|
|
72
|
+
if (gridCell.tableColumn?.name == removeCol.name && (gridCell?.tableRowIndex ?? -1) >= 0) {
|
|
73
|
+
gridCell.element = ui.div(ui.icons.delete(() => {
|
|
74
|
+
this.grid.dataFrame.rows.removeAt(gridCell.tableRowIndex!);
|
|
75
|
+
}, 'Delete'), {
|
|
76
|
+
style: {
|
|
77
|
+
height: `${gridCell.grid.props.rowHeight}px`, color: 'var(--grey-6)',
|
|
78
|
+
display: 'flex', flexDirection: 'row', justifyContent: 'center'
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
41
82
|
});
|
|
42
83
|
|
|
43
|
-
this.grid
|
|
44
|
-
this.
|
|
84
|
+
this.updateGridHeight(heightRowCount ?? this.grid.dataFrame.rowCount + 0.7);
|
|
85
|
+
this.subs.push(ui.onSizeChanged(this.grid.root)
|
|
86
|
+
.subscribe(this.gridRootOnSizeChanged.bind(this)));
|
|
87
|
+
this.subs.push(fromEvent<KeyboardEvent>(this.grid.root, 'keydown')
|
|
88
|
+
.subscribe((e: KeyboardEvent) => {
|
|
89
|
+
if (e.key === 'Enter') e.stopPropagation();
|
|
90
|
+
}));
|
|
91
|
+
this.setDataFrame(df);
|
|
45
92
|
|
|
46
|
-
if (heightRowCount != null) {
|
|
47
|
-
this.updateGridHeight(heightRowCount + 0.7);
|
|
48
|
-
} else {
|
|
49
|
-
this.updateGridHeight(this.grid.dataFrame.rowCount + 0.6);
|
|
50
|
-
this.subs.push(this.grid.dataFrame.onRowsAdded
|
|
51
|
-
.subscribe(() => { this.updateGridHeight(this.grid.dataFrame.rowCount + 0.6); }));
|
|
52
|
-
}
|
|
53
93
|
this.grid.root.style.width = `100%`;
|
|
94
|
+
this.gridHost.append(this.grid.root);
|
|
95
|
+
}
|
|
54
96
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
97
|
+
private dataFrameSubs: Unsubscribable[] = [];
|
|
98
|
+
|
|
99
|
+
private setDataFrame(dataFrame: DG.DataFrame): void {
|
|
100
|
+
for (const sub of this.dataFrameSubs) sub.unsubscribe();
|
|
101
|
+
this.grid.dataFrame = dataFrame;
|
|
58
102
|
|
|
59
|
-
this.
|
|
60
|
-
|
|
61
|
-
this.
|
|
103
|
+
this.dataFrameSubs.push(this.grid.dataFrame.onRowsRemoved
|
|
104
|
+
.subscribe(() => {
|
|
105
|
+
this.updateGridHeight(this.grid.dataFrame.rowCount + 0.7);
|
|
106
|
+
this.fireChanged();
|
|
107
|
+
}));
|
|
108
|
+
this.dataFrameSubs.push(this.grid.dataFrame.onRowsAdded
|
|
109
|
+
.subscribe(() => { this.updateGridHeight(this.grid.dataFrame.rowCount + 0.7); }));
|
|
110
|
+
this.dataFrameSubs.push(this.grid.dataFrame.onDataChanged.subscribe(() => {
|
|
111
|
+
this.fireChanged();
|
|
62
112
|
}));
|
|
63
113
|
|
|
64
|
-
this.
|
|
65
|
-
this.
|
|
114
|
+
this.updateGridHeight(this.grid.dataFrame.rowCount + 0.7);
|
|
115
|
+
this.fireChanged();
|
|
66
116
|
}
|
|
67
117
|
|
|
68
|
-
|
|
69
|
-
|
|
118
|
+
/** @param {number} posOutIdx continuous (outer) position index, 0-based */
|
|
119
|
+
addPosition(posOutIdx: number): void {
|
|
120
|
+
const phDf = this.grid.dataFrame;
|
|
121
|
+
const posList = phDf.columns.byName('Position').toList();
|
|
122
|
+
let rowIdx = posList.indexOf(posOutIdx + 1);
|
|
123
|
+
if (rowIdx === -1) {
|
|
124
|
+
rowIdx = posList.findIndex((v) => isNaN(v));
|
|
125
|
+
if (rowIdx === -1)
|
|
126
|
+
rowIdx = phDf.rows.addNew(['', posOutIdx + 1, '']).idx;
|
|
127
|
+
const tgtCell = this.grid.cell('Monomers', rowIdx);
|
|
128
|
+
}
|
|
129
|
+
phDf.currentCell = phDf.cell(rowIdx, 'Monomers');
|
|
130
|
+
//const gridRowIdx = inputs.placeholders.grid.tableRowToGrid(rowIdx);
|
|
131
|
+
//const monomersGCell = inputs.placeholders.grid.cell('Monomers', gridRowIdx);
|
|
132
|
+
const k = 42;
|
|
70
133
|
}
|
|
71
134
|
|
|
72
135
|
public static async create(
|
|
73
136
|
name?: string, options?: {}, heightRowCount?: number
|
|
74
137
|
): Promise<PolyToolPlaceholdersInput> {
|
|
75
|
-
|
|
76
|
-
DG.Column.fromType(DG.COLUMN_TYPE.INT, 'Position', 0),
|
|
77
|
-
DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'Monomers', 0),])!;
|
|
78
|
-
const grid = (await df.plot.fromType(DG.VIEWER.GRID, options)) as DG.Grid;
|
|
79
|
-
grid.sort(['Position']);
|
|
80
|
-
return new PolyToolPlaceholdersInput(name, grid, heightRowCount);
|
|
138
|
+
return new PolyToolPlaceholdersInput(name, heightRowCount, options);
|
|
81
139
|
}
|
|
82
140
|
|
|
83
141
|
// -- Update view --
|
|
@@ -90,8 +148,9 @@ export class PolyToolPlaceholdersInput extends DG.JsInputBase<DG.DataFrame> {
|
|
|
90
148
|
// -- Handle events --
|
|
91
149
|
|
|
92
150
|
private gridRootOnSizeChanged(): void {
|
|
93
|
-
this.grid.columns.byIndex(
|
|
94
|
-
this.grid.columns.byIndex(0)!.width - this.grid.columns.byIndex(1)!.width -
|
|
151
|
+
this.grid.columns.byIndex(3)!.width = this.grid.root.clientWidth - this.grid.horzScroll.root.offsetWidth -
|
|
152
|
+
this.grid.columns.byIndex(0)!.width - this.grid.columns.byIndex(1)!.width -
|
|
153
|
+
this.grid.columns.byIndex(2)!.width - 10;
|
|
95
154
|
}
|
|
96
155
|
}
|
|
97
156
|
|
|
@@ -111,6 +170,8 @@ export function getPlaceholdersFromText(src: string): PolyToolPlaceholder[] {
|
|
|
111
170
|
export function dfToPlaceholders(df: DG.DataFrame): PolyToolPlaceholder[] {
|
|
112
171
|
const res: PolyToolPlaceholder[] = [];
|
|
113
172
|
for (let rowI = 0; rowI < df.rowCount; rowI++) {
|
|
173
|
+
if (df.getCol('Position').isNone(rowI))
|
|
174
|
+
continue;
|
|
114
175
|
const pos = parseInt(df.get('Position', rowI)) - 1;
|
|
115
176
|
if (!isNaN(pos)) {
|
|
116
177
|
const monomerSymbolList = parseMonomerSymbolList(df.get('Monomers', rowI));
|
|
@@ -4,7 +4,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
|
|
5
5
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
6
6
|
|
|
7
|
-
import {Chain} from './pt-
|
|
7
|
+
import {Chain} from './conversion/pt-chain';
|
|
8
8
|
import {getPolyToolUnruleDialog} from './pt-unrule-dialog';
|
|
9
9
|
import {Rules} from './pt-rules';
|
|
10
10
|
|
package/src/polytool/types.ts
CHANGED
|
@@ -13,7 +13,11 @@ export type PolyToolEnumeratorType = typeof PolyToolEnumeratorTypes[keyof typeof
|
|
|
13
13
|
|
|
14
14
|
export type PolyToolPlaceholder = { position: number, monomers: string[] };
|
|
15
15
|
|
|
16
|
-
export type PolyToolBreadthPlaceholder = {
|
|
16
|
+
export type PolyToolBreadthPlaceholder = {
|
|
17
|
+
/** 0-based monomer position index */ start: number,
|
|
18
|
+
/** 0-based monomer position index */ end: number,
|
|
19
|
+
monomers: string[]
|
|
20
|
+
};
|
|
17
21
|
|
|
18
22
|
export type PolyToolEnumeratorParams = {
|
|
19
23
|
type: PolyToolEnumeratorType;
|
|
@@ -3,7 +3,7 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
5
|
import {before, after, category, expect, test, expectArray, testEvent, delay} from '@datagrok-libraries/utils/src/test';
|
|
6
|
-
import {Chain} from '../polytool/pt-
|
|
6
|
+
import {Chain} from '../polytool/conversion/pt-chain';
|
|
7
7
|
import {getRules} from '../polytool/pt-rules';
|
|
8
8
|
import {getHelmHelper, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
9
9
|
|
|
@@ -23,7 +23,7 @@ category('PolyTool: Chain', () => {
|
|
|
23
23
|
},
|
|
24
24
|
tgt: {
|
|
25
25
|
templateChain: {monomerCount: [11], linkageCount: 0},
|
|
26
|
-
mmChain: {monomerCount: [11], linkageCount: 1
|
|
26
|
+
mmChain: {monomerCount: [11], linkageCount: 1}
|
|
27
27
|
},
|
|
28
28
|
},
|
|
29
29
|
'reaction1': {
|
|
@@ -124,12 +124,11 @@ category('PolyTool: Chain', () => {
|
|
|
124
124
|
test(`applyRules-${testName}`, async () => {
|
|
125
125
|
const rules = await getRules(['rules_example.json']);
|
|
126
126
|
const resTemplateChain = Chain.parseNotation(data.templateSeq, helmHelper);
|
|
127
|
-
const resMmChain = resTemplateChain.applyRules(rules);
|
|
127
|
+
const resMmChain = await resTemplateChain.applyRules(rules);
|
|
128
128
|
resMmChain.check(true);
|
|
129
129
|
expectArray(resMmChain.monomers.map((mL) => mL.length), tgt.mmChain.monomerCount);
|
|
130
130
|
expect(resMmChain.linkages.length, tgt.mmChain.linkageCount);
|
|
131
131
|
expect(resMmChain.getHelm(), data.mmHelm);
|
|
132
132
|
}, {skipReason: 'applyRules is not implemented'});
|
|
133
133
|
}
|
|
134
|
-
|
|
135
134
|
});
|
|
@@ -3,7 +3,8 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
5
|
import {before, after, category, expect, test, expectArray, testEvent, delay} from '@datagrok-libraries/utils/src/test';
|
|
6
|
-
import {Chain
|
|
6
|
+
import {Chain} from '../polytool/conversion/pt-chain';
|
|
7
|
+
import {getInnerIdx, getOuterIdx} from '../polytool/conversion/pt-misc';
|
|
7
8
|
import {getRules} from '../polytool/pt-rules';
|
|
8
9
|
import {getHelmHelper, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
9
10
|
|
|
@@ -14,7 +14,8 @@ import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
|
|
|
14
14
|
import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
15
15
|
import {getHelmHelper, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
16
16
|
|
|
17
|
-
import {doPolyToolConvert
|
|
17
|
+
import {doPolyToolConvert} from '../polytool/conversion/pt-conversion';
|
|
18
|
+
import {getOverriddenLibrary} from '../polytool/conversion/pt-misc';
|
|
18
19
|
import {getRules} from '../polytool/pt-rules';
|
|
19
20
|
|
|
20
21
|
|
|
@@ -15,7 +15,7 @@ import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
|
|
|
15
15
|
import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
16
16
|
|
|
17
17
|
import {_package} from '../package-test';
|
|
18
|
-
import {getNewMonomer} from '../polytool/pt-
|
|
18
|
+
import {getNewMonomer} from '../polytool/conversion/pt-misc';
|
|
19
19
|
import {getRules, RuleReaction} from '../polytool/pt-rules';
|
|
20
20
|
|
|
21
21
|
category('toAtomicLevel', () => {
|
|
@@ -24,7 +24,6 @@ category('toAtomicLevel', () => {
|
|
|
24
24
|
let rdKitModule: RDModule;
|
|
25
25
|
|
|
26
26
|
before(async () => {
|
|
27
|
-
|
|
28
27
|
monomerLibHelper = await getMonomerLibHelper();
|
|
29
28
|
userLibSettings = await getUserLibSettings();
|
|
30
29
|
rdKitModule = await getRdKitModule();
|
|
@@ -0,0 +1,37 @@
|
|
|
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 {MonomerPlacer} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
|
|
6
|
+
import {monomerToShort} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
7
|
+
import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
8
|
+
|
|
9
|
+
import {_package} from '../package';
|
|
10
|
+
|
|
11
|
+
export class CyclizedCellRendererBack extends MonomerPlacer {
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
gridCol: DG.GridColumn | null, tableCol: DG.Column,
|
|
15
|
+
maxLengthOfMonomer: number, seqHelper: ISeqHelper
|
|
16
|
+
) {
|
|
17
|
+
super(gridCol, tableCol, _package.logger, maxLengthOfMonomer, () => {
|
|
18
|
+
const sh = seqHelper.getSeqHandler(tableCol);
|
|
19
|
+
return {
|
|
20
|
+
seqHandler: sh,
|
|
21
|
+
monomerCharWidth: 7,
|
|
22
|
+
separatorWidth: 11,
|
|
23
|
+
monomerToShort: monomerToShort,
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override onMouseMove(gridCell: DG.GridCell, e: MouseEvent) {
|
|
29
|
+
const gridCellBounds: DG.Rect = gridCell.bounds;
|
|
30
|
+
const argsX = e.offsetX - gridCell.gridColumn.left + (gridCell.gridColumn.left - gridCellBounds.x);
|
|
31
|
+
const left: number | null = this.getPosition(gridCell.tableRowIndex!, argsX, gridCellBounds.width);
|
|
32
|
+
if(left != null) {
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
super.onMouseMove(gridCell, e);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -3,7 +3,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
3
3
|
import * as ui from 'datagrok-api/ui';
|
|
4
4
|
|
|
5
5
|
import {defaultErrorHandler} from './err-info';
|
|
6
|
-
import {polyToolEnumerateHelmUI} from '../polytool/pt-
|
|
6
|
+
import {polyToolEnumerateHelmUI} from '../polytool/pt-enumerate-seq-dialog';
|
|
7
7
|
import {polyToolEnumerateChemUI} from '../polytool/pt-dialog';
|
|
8
8
|
|
|
9
9
|
import {_package} from '../package';
|
package/src/utils/cyclized.ts
CHANGED
|
@@ -13,11 +13,12 @@ import {CellRendererBackBase} from '@datagrok-libraries/bio/src/utils/cell-rende
|
|
|
13
13
|
import {MonomerPlacer} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
|
|
14
14
|
import {monomerToShort, StringListSeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
|
|
15
15
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
16
|
-
import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
16
|
+
import {getHelmHelper, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
17
17
|
|
|
18
|
-
import {Chain} from '../polytool/pt-
|
|
18
|
+
import {Chain} from '../polytool/conversion/pt-chain';
|
|
19
19
|
|
|
20
20
|
import {_package} from '../package';
|
|
21
|
+
import {CyclizedCellRendererBack} from './cell-renderer-cyclized';
|
|
21
22
|
|
|
22
23
|
/* eslint-enable max-len */
|
|
23
24
|
|
|
@@ -25,14 +26,18 @@ export class CyclizedNotationProvider implements INotationProvider {
|
|
|
25
26
|
private readonly separatorSplitter: SplitterFunc;
|
|
26
27
|
public readonly splitter: SplitterFunc;
|
|
27
28
|
|
|
29
|
+
get defaultGapOriginal(): string { return ''; }
|
|
30
|
+
|
|
28
31
|
constructor(
|
|
29
32
|
public readonly separator: string,
|
|
30
|
-
protected readonly
|
|
33
|
+
protected readonly helmHelper: IHelmHelper
|
|
31
34
|
) {
|
|
32
35
|
this.separatorSplitter = getSplitterWithSeparator(this.separator);
|
|
33
36
|
this.splitter = this._splitter.bind(this);
|
|
34
37
|
}
|
|
35
38
|
|
|
39
|
+
setUnits(): void {}
|
|
40
|
+
|
|
36
41
|
private _splitter(seq: string): ISeqSplitted {
|
|
37
42
|
const baseSS: ISeqSplitted = this.separatorSplitter(seq);
|
|
38
43
|
return new CyclizedSeqSplitted(
|
|
@@ -40,25 +45,17 @@ export class CyclizedNotationProvider implements INotationProvider {
|
|
|
40
45
|
GapOriginals[NOTATION.SEPARATOR]);
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
public
|
|
44
|
-
const
|
|
45
|
-
const seqChain = await Chain.parseNotation(seq, helmHelper);
|
|
48
|
+
public getHelm(seq: string, options?: any): string {
|
|
49
|
+
const seqChain = Chain.parseNotation(seq, this.helmHelper);
|
|
46
50
|
const resPseudoHelm = seqChain.getNotationHelm();
|
|
47
51
|
return resPseudoHelm;
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
public createCellRendererBack(gridCol: DG.GridColumn | null, tableCol: DG.Column<string>): CellRendererBackBase<string> {
|
|
51
55
|
let maxLengthOfMonomer: number = 4; // (_package.bioProperties ? _package.bioProperties.maxMonomerLength : 4) ?? 50;
|
|
52
|
-
const back = new
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
seqHandler: sh,
|
|
57
|
-
monomerCharWidth: 7,
|
|
58
|
-
separatorWidth: 11,
|
|
59
|
-
monomerToShort: monomerToShort,
|
|
60
|
-
};
|
|
61
|
-
});
|
|
56
|
+
const back = new CyclizedCellRendererBack(gridCol, tableCol,
|
|
57
|
+
maxLengthOfMonomer, this.helmHelper.seqHelper);
|
|
58
|
+
|
|
62
59
|
back.init().then(() => {});
|
|
63
60
|
return back;
|
|
64
61
|
}
|
|
@@ -66,23 +63,23 @@ export class CyclizedNotationProvider implements INotationProvider {
|
|
|
66
63
|
|
|
67
64
|
/** Gets canonical monomers for original ones with cyclization marks */
|
|
68
65
|
export class CyclizedSeqSplitted extends StringListSeqSplitted {
|
|
69
|
-
private readonly seqCList: (string | null)[];
|
|
70
|
-
|
|
71
66
|
override getCanonical(posIdx: number): string {
|
|
72
67
|
if (this.isGap(posIdx)) return GAP_SYMBOL;
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
cmRes = om;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
const om = this.getOriginal(posIdx);
|
|
70
|
+
let cmRes = om;
|
|
71
|
+
if (om.startsWith('{'))
|
|
72
|
+
cmRes = om.slice(1);
|
|
73
|
+
else if (om.endsWith('}'))
|
|
74
|
+
cmRes = om.slice(0, -1);
|
|
75
|
+
else if (om.startsWith('('))
|
|
76
|
+
cmRes = om.replace(/^\(.\d+\)/, '');
|
|
77
|
+
else if (om.endsWith(')'))
|
|
78
|
+
cmRes = om.replace(/\(\d+\)$/, '');
|
|
81
79
|
return cmRes;
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
constructor(seqOList: SeqSplittedBase, gapOriginalMonomer: string) {
|
|
85
83
|
super(seqOList, gapOriginalMonomer);
|
|
86
|
-
this.seqCList = new Array<string | null>(this.length).fill(null);
|
|
87
84
|
}
|
|
88
85
|
}
|