@datagrok/sequence-translator 1.3.13 → 1.3.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/CHANGELOG.md +27 -1
- 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/polytool-rules/rules_example.json +34 -34
- package/files/samples/cyclized.csv +6 -0
- package/package.json +9 -10
- package/src/apps/common/view/components/colored-input/colored-text-input.ts +2 -2
- package/src/apps/pattern/view/components/bulk-convert/column-input.ts +2 -2
- package/src/apps/pattern/view/components/bulk-convert/table-input.ts +8 -6
- package/src/apps/pattern/view/components/edit-block-controls.ts +5 -5
- package/src/apps/pattern/view/components/load-block-controls.ts +7 -3
- package/src/apps/pattern/view/components/numeric-label-visibility-controls.ts +1 -1
- package/src/apps/pattern/view/components/strand-editor/header-controls.ts +2 -2
- package/src/apps/pattern/view/components/strand-editor/strand-controls.ts +2 -2
- package/src/apps/pattern/view/components/terminal-modification-editor.ts +1 -1
- package/src/apps/structure/view/ui.ts +5 -5
- package/src/apps/translator/view/ui.ts +27 -18
- package/src/package-test.ts +1 -0
- package/src/package.ts +34 -12
- package/src/polytool/pt-conversion.ts +2 -33
- package/src/polytool/pt-convert-editor.ts +116 -0
- package/src/polytool/pt-dialog.ts +177 -97
- package/src/polytool/pt-enumeration-helm-dialog.ts +338 -282
- package/src/polytool/pt-enumeration-helm.ts +6 -2
- package/src/polytool/pt-placeholders-input.ts +1 -2
- package/src/polytool/utils.ts +0 -7
- package/src/tests/polytool-convert-tests.ts +99 -0
- package/src/tests/polytool-enumerate-tests.ts +21 -5
- package/src/utils/context-menu.ts +7 -10
- package/src/polytool/cyclized.ts +0 -56
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
[
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
]
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"type": "link",
|
|
4
|
+
"code": "1",
|
|
5
|
+
"monomericSubstitution": {
|
|
6
|
+
"firstMonomer": "C",
|
|
7
|
+
"secondMonomer": "C",
|
|
8
|
+
"firstLinkingGroup": "3",
|
|
9
|
+
"secondLinkingGroup": "3",
|
|
10
|
+
"firstSubstitution": "C",
|
|
11
|
+
"secondSubstitution": "C"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"type": "link",
|
|
16
|
+
"code": "2",
|
|
17
|
+
"monomericSubstitution": {
|
|
18
|
+
"firstMonomer": "NH2",
|
|
19
|
+
"secondMonomer": "D",
|
|
20
|
+
"firstLinkingGroup": "2",
|
|
21
|
+
"secondLinkingGroup": "3",
|
|
22
|
+
"firstSubstitution": "NH2",
|
|
23
|
+
"secondSubstitution": "D"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"type": "fragmentDuplication",
|
|
28
|
+
"code": "#3"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"type": "differentFragments",
|
|
32
|
+
"code": "$4"
|
|
33
|
+
}
|
|
34
|
+
]
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "1.3.
|
|
4
|
+
"version": "1.3.15",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Alexey Choposky",
|
|
7
7
|
"email": "achopovsky@datagrok.ai"
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
}
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@datagrok-libraries/bio": "^5.42.
|
|
25
|
+
"@datagrok-libraries/bio": "^5.42.14",
|
|
26
26
|
"@datagrok-libraries/chem-meta": "^1.2.5",
|
|
27
|
-
"@datagrok-libraries/tutorials": "^1.
|
|
28
|
-
"@datagrok-libraries/utils": "^4.
|
|
27
|
+
"@datagrok-libraries/tutorials": "^1.4.0",
|
|
28
|
+
"@datagrok-libraries/utils": "^4.3.0",
|
|
29
29
|
"@types/react": "^18.0.15",
|
|
30
30
|
"cash-dom": "^8.1.0",
|
|
31
|
-
"datagrok-api": "^1.
|
|
31
|
+
"datagrok-api": "^1.21.1",
|
|
32
32
|
"lodash": "^4.17.21",
|
|
33
33
|
"object-hash": "^3.0.0",
|
|
34
34
|
"openchemlib": "6.0.1",
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
"wu": "latest"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@datagrok-libraries/helm-web-editor": "^1.1.
|
|
42
|
+
"@datagrok-libraries/helm-web-editor": "^1.1.11",
|
|
43
43
|
"@datagrok-libraries/js-draw-lite": "^0.0.8",
|
|
44
|
-
"@datagrok/bio": "^2.
|
|
45
|
-
"@datagrok/helm": "^2.
|
|
46
|
-
"@datagrok/chem": "^1.
|
|
44
|
+
"@datagrok/bio": "^2.15.0",
|
|
45
|
+
"@datagrok/helm": "^2.5.0",
|
|
46
|
+
"@datagrok/chem": "^1.12.0",
|
|
47
47
|
"@types/jquery": "^3.5.14",
|
|
48
48
|
"@types/js-yaml": "^4.0.5",
|
|
49
49
|
"@types/lodash": "^4.14.202",
|
|
@@ -54,7 +54,6 @@
|
|
|
54
54
|
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
|
55
55
|
"@typescript-eslint/parser": "^7.2.0",
|
|
56
56
|
"css-loader": "^6.7.3",
|
|
57
|
-
"datagrok-tools": "latest",
|
|
58
57
|
"eslint": "^8.57.0",
|
|
59
58
|
"eslint-config-google": "latest",
|
|
60
59
|
"style-loader": "^3.3.1",
|
|
@@ -22,7 +22,7 @@ export class ColoredTextInput {
|
|
|
22
22
|
$(this.root).addClass('colored-text-input');
|
|
23
23
|
if (resizeable) {
|
|
24
24
|
// make input field automatically resizeable
|
|
25
|
-
this.textInputBase.onChanged(
|
|
25
|
+
this.textInputBase.onChanged.subscribe(
|
|
26
26
|
() => {
|
|
27
27
|
// necessary for the field to be squeezable, not only expandable
|
|
28
28
|
$(this.textArea).css('height', 0);
|
|
@@ -34,7 +34,7 @@ export class ColoredTextInput {
|
|
|
34
34
|
this.root.appendChild(this.highlights);
|
|
35
35
|
this.colorize();
|
|
36
36
|
|
|
37
|
-
this.textInputBase.onChanged(() => this.colorize());
|
|
37
|
+
this.textInputBase.onChanged.subscribe(() => this.colorize());
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
private highlights: HTMLDivElement;
|
|
@@ -54,7 +54,7 @@ export class ColumnInputManager {
|
|
|
54
54
|
[];
|
|
55
55
|
const strandColumnInput = Object.fromEntries(STRANDS.map((strand) => {
|
|
56
56
|
const input = ui.input.choice(`${STRAND_LABEL[strand]} column`, {value: columns[0], items: columns,
|
|
57
|
-
onValueChanged: (
|
|
57
|
+
onValueChanged: (value) => this.eventBus.selectStrandColumn(strand, value)}
|
|
58
58
|
);
|
|
59
59
|
this.eventBus.selectStrandColumn(strand, columns[0]);
|
|
60
60
|
return [strand, input.root];
|
|
@@ -65,7 +65,7 @@ export class ColumnInputManager {
|
|
|
65
65
|
private createIdColumnInput(): HTMLElement {
|
|
66
66
|
const columns = this.selectedTable ? this.selectedTable.columns.names() : [];
|
|
67
67
|
const idColumnInput = ui.input.choice('ID column', {value: columns[0], items: columns,
|
|
68
|
-
onValueChanged: (
|
|
68
|
+
onValueChanged: (value) => this.eventBus.selectIdColumn(value)}
|
|
69
69
|
);
|
|
70
70
|
this.eventBus.selectIdColumn(columns[0]);
|
|
71
71
|
return idColumnInput.root;
|
|
@@ -28,7 +28,7 @@ export class TableInputManager {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
private getTableFromEventData(eventData: any): DG.DataFrame {
|
|
31
|
-
if (!
|
|
31
|
+
if (!eventData && eventData.args && eventData.args.dataFrame instanceof DG.DataFrame)
|
|
32
32
|
throw new Error(`EventData does not contain a dataframe`, eventData);
|
|
33
33
|
|
|
34
34
|
return eventData.args.dataFrame as DG.DataFrame;
|
|
@@ -63,13 +63,15 @@ export class TableInputManager {
|
|
|
63
63
|
private createTableInput(): DG.InputBase<DG.DataFrame | null> {
|
|
64
64
|
const currentlySelectedTable = this.eventBus.getTableSelection();
|
|
65
65
|
|
|
66
|
-
const tableInput = ui.input.table('Tables', {
|
|
67
|
-
|
|
66
|
+
const tableInput = ui.input.table('Tables', {
|
|
67
|
+
value: currentlySelectedTable!, items: this.availableTables,
|
|
68
|
+
onValueChanged: (value) => {
|
|
68
69
|
// WARNING: non-null check necessary to prevent resetting columns to
|
|
69
70
|
// null upon handling onTableAdded
|
|
70
|
-
if (
|
|
71
|
-
this.eventBus.selectTable(
|
|
72
|
-
}
|
|
71
|
+
if (value !== null)
|
|
72
|
+
this.eventBus.selectTable(value);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
73
75
|
return tableInput;
|
|
74
76
|
}
|
|
75
77
|
|
|
@@ -79,7 +79,7 @@ export class PatternEditControlsManager {
|
|
|
79
79
|
{value: this.eventBus.isAntisenseStrandActive()}
|
|
80
80
|
);
|
|
81
81
|
|
|
82
|
-
toggleAntisenseStrand.onInput(
|
|
82
|
+
toggleAntisenseStrand.onInput.subscribe(
|
|
83
83
|
() => this.eventBus.toggleAntisenseStrand(toggleAntisenseStrand.value)
|
|
84
84
|
);
|
|
85
85
|
|
|
@@ -97,7 +97,7 @@ export class PatternEditControlsManager {
|
|
|
97
97
|
const sequenceLength = this.eventBus.getNucleotideSequences()[strand].length;
|
|
98
98
|
|
|
99
99
|
const input = ui.input.int(`${STRAND_LABEL[strand]} length`, {value: sequenceLength});
|
|
100
|
-
input.onInput(() => updateStrandLengthInputs(strand, input));
|
|
100
|
+
input.onInput.subscribe(() => updateStrandLengthInputs(strand, input));
|
|
101
101
|
|
|
102
102
|
this.eventBus.nucleotideSequencesChanged$.subscribe(() => {
|
|
103
103
|
input.value = this.eventBus.getNucleotideSequences()[strand].length;
|
|
@@ -141,7 +141,7 @@ export class PatternEditControlsManager {
|
|
|
141
141
|
|
|
142
142
|
const sequenceBaseInput = ui.input.choice('Sequence basis', {value: defaultNucleotideBase, items: availableNucleoBases});
|
|
143
143
|
|
|
144
|
-
sequenceBaseInput.onInput(() => this.eventBus.replaceSequenceBase(sequenceBaseInput.value!));
|
|
144
|
+
sequenceBaseInput.onInput.subscribe(() => this.eventBus.replaceSequenceBase(sequenceBaseInput.value!));
|
|
145
145
|
|
|
146
146
|
this.eventBus.nucleotideSequencesChanged$.subscribe(() => {
|
|
147
147
|
sequenceBaseInput.value = this.eventBus.getSequenceBase();
|
|
@@ -156,7 +156,7 @@ export class PatternEditControlsManager {
|
|
|
156
156
|
|
|
157
157
|
$(patternCommentInput.root).addClass('st-pattern-text-input');
|
|
158
158
|
|
|
159
|
-
patternCommentInput.onInput(
|
|
159
|
+
patternCommentInput.onInput.subscribe(
|
|
160
160
|
() => this.eventBus.updateComment(patternCommentInput.value!)
|
|
161
161
|
);
|
|
162
162
|
|
|
@@ -172,7 +172,7 @@ export class PatternEditControlsManager {
|
|
|
172
172
|
|
|
173
173
|
$(patternNameInput.root).addClass('st-pattern-text-input');
|
|
174
174
|
|
|
175
|
-
patternNameInput.onInput(
|
|
175
|
+
patternNameInput.onInput.subscribe(
|
|
176
176
|
() => this.eventBus.updatePatternName(patternNameInput.value)
|
|
177
177
|
);
|
|
178
178
|
this.eventBus.patternLoaded$.subscribe(() => {
|
|
@@ -96,7 +96,7 @@ export class PatternLoadControlsManager {
|
|
|
96
96
|
const authorChoiceInput = ui.input.choice(
|
|
97
97
|
'Author', {value: this.eventBus.getSelectedAuthor(), items: possibleValues});
|
|
98
98
|
|
|
99
|
-
authorChoiceInput.onInput(() => {
|
|
99
|
+
authorChoiceInput.onInput.subscribe(() => {
|
|
100
100
|
this.authorSelectedByUser = true;
|
|
101
101
|
if (authorChoiceInput.value === null)
|
|
102
102
|
throw new Error('author choice must be non-null');
|
|
@@ -142,7 +142,7 @@ export class PatternLoadControlsManager {
|
|
|
142
142
|
});
|
|
143
143
|
|
|
144
144
|
this.subscriptions.add(
|
|
145
|
-
choiceInput.onInput(
|
|
145
|
+
choiceInput.onInput.subscribe(
|
|
146
146
|
() => {
|
|
147
147
|
const patternHash = this.dataManager.getPatternHash(choiceInput.value!, this.isCurrentUserSelected());
|
|
148
148
|
this.eventBus.requestPatternLoad(patternHash);
|
|
@@ -164,7 +164,11 @@ export class PatternLoadControlsManager {
|
|
|
164
164
|
|
|
165
165
|
private getPatternName(patternList: string[]): string {
|
|
166
166
|
return patternList.find(
|
|
167
|
-
(
|
|
167
|
+
(longPatternName) => {
|
|
168
|
+
// The pattern name can be followed by the author name in parenths
|
|
169
|
+
const shortPatternName = longPatternName.split(' (')[0];
|
|
170
|
+
return shortPatternName === this.eventBus.getPatternName();
|
|
171
|
+
}
|
|
168
172
|
) ?? patternList[0];
|
|
169
173
|
}
|
|
170
174
|
|
|
@@ -46,7 +46,7 @@ export class NumericLabelVisibilityControls {
|
|
|
46
46
|
const initialValue = this.eventBus.getModificationsWithNumericLabels().includes(nucleotide);
|
|
47
47
|
const input = ui.input.bool(nucleotide, {
|
|
48
48
|
value: initialValue,
|
|
49
|
-
onValueChanged: (
|
|
49
|
+
onValueChanged: (value) => this.handleNumericLabelToggle(nucleotide, value)
|
|
50
50
|
});
|
|
51
51
|
$(input.root).css('padding-right', '20px');
|
|
52
52
|
|
|
@@ -45,7 +45,7 @@ export class HeaderControls {
|
|
|
45
45
|
const initialValue = this.areAllPtoLinkagesSet(flags);
|
|
46
46
|
const allPtoActivationInput = ui.input.bool('All PTO', {value: initialValue});
|
|
47
47
|
|
|
48
|
-
allPtoActivationInput.onInput(() => {
|
|
48
|
+
allPtoActivationInput.onInput.subscribe(() => {
|
|
49
49
|
const value = allPtoActivationInput.value!;
|
|
50
50
|
this.eventBus.setAllPTOLinkages(value);
|
|
51
51
|
});
|
|
@@ -81,7 +81,7 @@ export class HeaderControls {
|
|
|
81
81
|
const initialValue = this.isFirstPtoActive(strand);
|
|
82
82
|
const firstPtoInput = ui.input.bool(`First ${strand} PTO`, {value: initialValue});
|
|
83
83
|
|
|
84
|
-
firstPtoInput.onInput(() => {
|
|
84
|
+
firstPtoInput.onInput.subscribe(() => {
|
|
85
85
|
const value = firstPtoInput.value!;
|
|
86
86
|
this.eventBus.setPhosphorothioateLinkageFlag(strand, 0, value);
|
|
87
87
|
});
|
|
@@ -79,7 +79,7 @@ export class StrandControls {
|
|
|
79
79
|
const nucleotides = this.eventBus.getNucleotideSequences()[strand];
|
|
80
80
|
const choiceInputs = nucleotides.map((nucleotide, index) => {
|
|
81
81
|
const input = ui.input.choice<string>('', {value: nucleotide, items: nucleotideBaseChoices});
|
|
82
|
-
input.onInput(() => {
|
|
82
|
+
input.onInput.subscribe(() => {
|
|
83
83
|
const newValue = input.value!;
|
|
84
84
|
this.eventBus.setNucleotide(strand, index, newValue);
|
|
85
85
|
});
|
|
@@ -93,7 +93,7 @@ export class StrandControls {
|
|
|
93
93
|
const ptoLinkageFlags = this.eventBus.getPhosphorothioateLinkageFlags()[strand].slice(1);
|
|
94
94
|
const ptoLinkageInputs = ptoLinkageFlags.map((flag, index) => {
|
|
95
95
|
const input = ui.input.bool('', {value: flag});
|
|
96
|
-
input.onInput(() => {
|
|
96
|
+
input.onInput.subscribe(() => {
|
|
97
97
|
const newValue = input.value!;
|
|
98
98
|
this.eventBus.setPhosphorothioateLinkageFlag(strand, index + 1, newValue);
|
|
99
99
|
});
|
|
@@ -109,7 +109,7 @@ class StrandTerminalModificationControls {
|
|
|
109
109
|
const input = ui.input.textArea(terminus, {value: initialValue});
|
|
110
110
|
this.applyStylingToInput(input);
|
|
111
111
|
|
|
112
|
-
input.onInput(() => {
|
|
112
|
+
input.onInput.subscribe(() => {
|
|
113
113
|
const newValue = input.value;
|
|
114
114
|
if (newValue === null)
|
|
115
115
|
return;
|
|
@@ -110,12 +110,12 @@ class StructureAppLayout {
|
|
|
110
110
|
);
|
|
111
111
|
|
|
112
112
|
STRANDS.forEach((strand, idx) => {
|
|
113
|
-
directionChoiceInput[strand].onChanged(() => {
|
|
114
|
-
let
|
|
113
|
+
directionChoiceInput[strand].onChanged.subscribe((value) => {
|
|
114
|
+
let inputValue = value === DIRECTION.INVERSE;
|
|
115
115
|
// warning: the next line is necessary
|
|
116
116
|
// until the legacy notion of direction used in the molfile generation gets fixed
|
|
117
|
-
if (idx > 0)
|
|
118
|
-
this.directionInversion[strand] =
|
|
117
|
+
if (idx > 0) inputValue = !inputValue;
|
|
118
|
+
this.directionInversion[strand] = inputValue;
|
|
119
119
|
this.onInput.next();
|
|
120
120
|
});
|
|
121
121
|
});
|
|
@@ -142,7 +142,7 @@ class StructureAppLayout {
|
|
|
142
142
|
|
|
143
143
|
const sequenseInputs = ui.form([], 'st-structure-inputs');
|
|
144
144
|
const clearButtons = ui.divV([], 'st-structure-clear-buttons');
|
|
145
|
-
const directionInputs = ui.form([], 'st-direction-inputs');
|
|
145
|
+
const directionInputs = ui.form([], 'st-direction-inputs');
|
|
146
146
|
|
|
147
147
|
for (const strand of STRANDS) {
|
|
148
148
|
sequenseInputs.append(this.inputBase[strand].root);
|
|
@@ -47,11 +47,14 @@ class TranslatorAppLayout {
|
|
|
47
47
|
this.moleculeImgDiv.style.marginTop = '12px';
|
|
48
48
|
|
|
49
49
|
this.outputTableDiv = ui.div([]);
|
|
50
|
-
this.formatChoiceInput = ui.input.choice('', {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
this.formatChoiceInput = ui.input.choice('', {
|
|
51
|
+
value: DEFAULT_FORMATS.HELM, items: this.inputFormats,
|
|
52
|
+
onValueChanged: async (value, input) => {
|
|
53
|
+
this.format = value;
|
|
54
|
+
this.updateTable();
|
|
55
|
+
await this.updateMolImg();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
55
58
|
this.sequenceInputBase = ui.input.textArea('', {value: DEFAULT_AXOLABS_INPUT, onValueChanged: () => { this.onInput.next(); }});
|
|
56
59
|
|
|
57
60
|
this.init();
|
|
@@ -99,13 +102,15 @@ class TranslatorAppLayout {
|
|
|
99
102
|
|
|
100
103
|
const tableControlsManager = new TableControlsManager(this.eventBus);
|
|
101
104
|
const tableControls = tableControlsManager.createUIComponents();
|
|
102
|
-
const inputFormats = ui.input.choice('Input format', {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
+
const inputFormats = ui.input.choice('Input format', {
|
|
106
|
+
value: DEFAULT_FORMATS.AXOLABS,
|
|
107
|
+
items: this.inputFormats, onValueChanged: (value) => this.eventBus.selectInputFormat(value)
|
|
108
|
+
});
|
|
105
109
|
|
|
106
|
-
const outputFormats = ui.input.choice('Output format', {
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
const outputFormats = ui.input.choice('Output format', {
|
|
111
|
+
value: NUCLEOTIDES_FORMAT,
|
|
112
|
+
items: getSupportedTargetFormats(this.th), onValueChanged: (value) => this.eventBus.selectOutputFormat(value)
|
|
113
|
+
});
|
|
109
114
|
const convertBulkButton = this.createConvertBulkButton();
|
|
110
115
|
|
|
111
116
|
const tableControlsContainer = ui.div([
|
|
@@ -374,13 +379,15 @@ class TableInputManager {
|
|
|
374
379
|
private createTableInput(): DG.InputBase<DG.DataFrame | null> {
|
|
375
380
|
const currentlySelectedTable = this.eventBus.getSelectedTable();
|
|
376
381
|
|
|
377
|
-
const tableInput = ui.input.table('Table', {
|
|
378
|
-
|
|
382
|
+
const tableInput = ui.input.table('Table', {
|
|
383
|
+
value: currentlySelectedTable!, items: this.availableTables,
|
|
384
|
+
onValueChanged: (value) => {
|
|
379
385
|
// WARNING: non-null check necessary to prevent resetting columns to
|
|
380
386
|
// null upon handling onTableAdded
|
|
381
|
-
if (
|
|
382
|
-
this.eventBus.selectTable(
|
|
383
|
-
}
|
|
387
|
+
if (value !== null)
|
|
388
|
+
this.eventBus.selectTable(value);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
384
391
|
return tableInput;
|
|
385
392
|
}
|
|
386
393
|
|
|
@@ -449,8 +456,10 @@ class ColumnInputsManager {
|
|
|
449
456
|
const selectedColumnName = matchingColumnName ? matchingColumnName : columnNames[0];
|
|
450
457
|
this.selectColumnIfTableNotNull(selectedTable, selectedColumnName, columnLabel);
|
|
451
458
|
|
|
452
|
-
const input = ui.input.choice(`${columnLabel}`, {
|
|
453
|
-
|
|
459
|
+
const input = ui.input.choice(`${columnLabel}`, {
|
|
460
|
+
value: selectedColumnName, items: columnNames,
|
|
461
|
+
onValueChanged: (value) => this.selectColumnIfTableNotNull(selectedTable, value, columnLabel)
|
|
462
|
+
}
|
|
454
463
|
);
|
|
455
464
|
|
|
456
465
|
return input;
|
package/src/package-test.ts
CHANGED
|
@@ -8,6 +8,7 @@ import './tests/formats-to-helm';
|
|
|
8
8
|
import './tests/helm-to-nucleotides';
|
|
9
9
|
import './tests/formats-support';
|
|
10
10
|
import './tests/files-tests';
|
|
11
|
+
import './tests/polytool-convert-tests';
|
|
11
12
|
import './tests/polytool-enumerate-tests';
|
|
12
13
|
|
|
13
14
|
import {OligoToolkitTestPackage} from './tests/utils';
|
package/src/package.ts
CHANGED
|
@@ -14,16 +14,19 @@ import {SequenceToMolfileConverter} from './apps/structure/model/sequence-to-mol
|
|
|
14
14
|
import {FormatConverter} from './apps/translator/model/format-converter';
|
|
15
15
|
import {demoOligoPatternUI, demoOligoStructureUI, demoOligoTranslatorUI} from './demo/demo-st-ui';
|
|
16
16
|
import {getExternalAppViewFactories} from './plugins/mermade';
|
|
17
|
+
import {defaultErrorHandler} from './utils/err-info';
|
|
17
18
|
|
|
18
19
|
//polytool specific
|
|
19
|
-
import {
|
|
20
|
+
import {polyToolConvert, polyToolConvertUI} from './polytool/pt-dialog';
|
|
21
|
+
import {polyToolEnumerateChemUI} from './polytool/pt-dialog';
|
|
20
22
|
import {polyToolEnumerateHelmUI} from './polytool/pt-enumeration-helm-dialog';
|
|
21
23
|
import {_setPeptideColumn} from './polytool/utils';
|
|
22
24
|
import {PolyToolCsvLibHandler} from './polytool/csv-to-json-monomer-lib-converter';
|
|
23
25
|
import {ITranslationHelper} from './types';
|
|
24
26
|
import {addContextMenuUI} from './utils/context-menu';
|
|
27
|
+
import {PolyToolConvertFuncEditor} from './polytool/pt-convert-editor';
|
|
25
28
|
|
|
26
|
-
export const _package: OligoToolkitPackage = new OligoToolkitPackage(
|
|
29
|
+
export const _package: OligoToolkitPackage = new OligoToolkitPackage({debug: true}/**/);
|
|
27
30
|
|
|
28
31
|
//name: Oligo Toolkit
|
|
29
32
|
//meta.icon: img/icons/toolkit.png
|
|
@@ -155,27 +158,46 @@ async function getSpecifiedAppView(appName: string): Promise<DG.ViewBase> {
|
|
|
155
158
|
//top-menu: Bio | PolyTool | Convert...
|
|
156
159
|
//name: polyToolConvert
|
|
157
160
|
//description: Perform cyclization of polymers
|
|
158
|
-
export async function
|
|
159
|
-
|
|
160
|
-
try {
|
|
161
|
-
dialog = await getPolyToolConversionDialog();
|
|
162
|
-
dialog.show();
|
|
163
|
-
} catch (err: any) {
|
|
164
|
-
grok.shell.warning('To run PolyTool Conversion, open a dataframe with macromolecules');
|
|
165
|
-
}
|
|
161
|
+
export async function polyToolConvertTopMenu(): Promise<void> {
|
|
162
|
+
await polyToolConvertUI();
|
|
166
163
|
}
|
|
167
164
|
|
|
165
|
+
//name: getPolyToolConvertEditor
|
|
166
|
+
//tags: editor
|
|
167
|
+
//input: funccall call
|
|
168
|
+
//output: column resCol
|
|
169
|
+
export async function getPolyToolConvertEditor(call: DG.FuncCall): Promise<DG.Column<string> | null> {
|
|
170
|
+
const funcEditor = await PolyToolConvertFuncEditor.create(call);
|
|
171
|
+
return await funcEditor.showDialog();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
//name: polyToolConvert2
|
|
175
|
+
//input: dataframe table
|
|
176
|
+
//input: column seqCol { caption: Sequence }
|
|
177
|
+
//input: bool generateHelm = true
|
|
178
|
+
//input: bool chiralityEngine = true
|
|
179
|
+
//input: object rules
|
|
180
|
+
//output: column resCol
|
|
181
|
+
//editor: SequenceTranslator:getPolyToolConvertEditor
|
|
182
|
+
export async function polyToolConvert2(table: DG.DataFrame,
|
|
183
|
+
seqCol: DG.Column, generateHelm: boolean, chiralityEngine: boolean, rules: string[]
|
|
184
|
+
): Promise<DG.Column<string>> {
|
|
185
|
+
const ptConvertRes = await polyToolConvert(seqCol, generateHelm, chiralityEngine, rules);
|
|
186
|
+
return ptConvertRes[0];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
|
|
168
190
|
//top-menu: Bio | PolyTool | Enumerate HELM...
|
|
169
191
|
//name: polyToolEnumerateHelm
|
|
170
192
|
//description: Perform cyclization of polymers
|
|
171
|
-
export async function
|
|
193
|
+
export async function polyToolEnumerateHelmTopMenu(): Promise<void> {
|
|
172
194
|
await polyToolEnumerateHelmUI(grok.shell.tv?.dataFrame.currentCell);
|
|
173
195
|
}
|
|
174
196
|
|
|
175
197
|
//top-menu: Bio | PolyTool | Enumerate Chem...
|
|
176
198
|
//name: polyToolEnumerateChem
|
|
177
199
|
//description: Perform cyclization of polymers
|
|
178
|
-
export async function
|
|
200
|
+
export async function polyToolEnumerateChemTopMenu(): Promise<void> {
|
|
179
201
|
polyToolEnumerateChemUI();
|
|
180
202
|
}
|
|
181
203
|
|
|
@@ -265,7 +265,8 @@ export class Chain {
|
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
-
|
|
268
|
+
/** The main PolyTool convert engine. Returns list of Helms. Covered with tests. */
|
|
269
|
+
export function doPolyToolConvert(sequences: string[], rules: Rules): string[] {
|
|
269
270
|
const helms = new Array<string>(sequences.length);
|
|
270
271
|
for (let i = 0; i < sequences.length; i++) {
|
|
271
272
|
if (sequences[i] === undefined)
|
|
@@ -278,35 +279,3 @@ function getHelms(sequences: string[], rules: Rules): string[] {
|
|
|
278
279
|
|
|
279
280
|
return helms;
|
|
280
281
|
}
|
|
281
|
-
|
|
282
|
-
export async function addTransformedColumn(
|
|
283
|
-
sequencesCol: DG.Column<string>, addHelm: boolean, ruleFiles: string[], chiralityEngine?: boolean
|
|
284
|
-
): Promise<void> {
|
|
285
|
-
const df = sequencesCol.dataFrame;
|
|
286
|
-
|
|
287
|
-
const rules = await getRules(ruleFiles);
|
|
288
|
-
const targetList = getHelms(sequencesCol.toList(), rules);
|
|
289
|
-
const helmColName = df.columns.getUnusedName('transformed(' + sequencesCol.name + ')');
|
|
290
|
-
const targetHelmCol = DG.Column.fromList('string', helmColName, targetList);
|
|
291
|
-
|
|
292
|
-
addCommonTags(targetHelmCol);
|
|
293
|
-
targetHelmCol.meta.units = NOTATION.HELM;
|
|
294
|
-
|
|
295
|
-
if (addHelm) {
|
|
296
|
-
targetHelmCol.setTag('cell.renderer', 'helm');
|
|
297
|
-
df.columns.add(targetHelmCol);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// toAtomicLevel
|
|
301
|
-
const molCol = await grok.functions.call('Bio:getMolFromHelm', {
|
|
302
|
-
'df': df,
|
|
303
|
-
'helmCol': targetHelmCol,
|
|
304
|
-
'chiralityEngine': chiralityEngine
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
molCol.name = df.columns.getUnusedName('molfile(' + sequencesCol.name + ')');
|
|
308
|
-
molCol.semType = DG.SEMTYPE.MOLECULE;
|
|
309
|
-
|
|
310
|
-
df.columns.add(molCol, true);
|
|
311
|
-
await grok.data.detectSemanticTypes(df);
|
|
312
|
-
}
|