@datagrok/sequence-translator 1.4.1 → 1.4.3
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 +20 -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/files/polytool-rules/rules_example.json +10 -0
- package/files/samples/cyclized.csv +2 -1
- package/files/tests/polytool-reaction-lib.json +40 -0
- package/package.json +7 -7
- package/src/package-test.ts +9 -1
- package/src/package.ts +8 -0
- package/src/polytool/const.ts +1 -0
- package/src/polytool/pt-conversion.ts +147 -43
- package/src/polytool/pt-dialog.ts +86 -24
- package/src/polytool/pt-enumeration-helm-dialog.ts +35 -20
- package/src/polytool/pt-enumeration-helm.ts +46 -26
- package/src/polytool/pt-placeholders-breadth-input.ts +111 -0
- package/src/polytool/pt-placeholders-input.ts +13 -20
- package/src/polytool/pt-rules.ts +24 -4
- package/src/polytool/pt-unrule-dialog.ts +106 -0
- package/src/polytool/pt-unrule.ts +37 -0
- package/src/polytool/types.ts +5 -2
- package/src/tests/polytool-convert-tests.ts +8 -9
- package/src/tests/polytool-enumerate-breadth-tests.ts +116 -0
- package/src/tests/polytool-enumerate-tests.ts +40 -41
- package/src/tests/polytool-unrule-tests.ts +10 -0
- package/src/tests/toAtomicLevel-tests.ts +72 -0
|
@@ -23,6 +23,16 @@
|
|
|
23
23
|
"secondSubstitution": "D"
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
|
+
{
|
|
27
|
+
"type": "reaction",
|
|
28
|
+
"code": "3",
|
|
29
|
+
"monomericSubstitution": {
|
|
30
|
+
"firstMonomer": "aG",
|
|
31
|
+
"secondMonomer": "azG",
|
|
32
|
+
"reaction": "[H:1]NC(C([OH:2])=O)c1cn(C(N[H:3])C([OH:4])=O)nn1",
|
|
33
|
+
"name": "GGaz"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
26
36
|
{
|
|
27
37
|
"type": "fragmentDuplication",
|
|
28
38
|
"code": "#3"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"monomerType": "Backbone",
|
|
4
|
+
"smiles": "[H:1]NC(C([OH:2])=O)c1cn(C(N[H:3])C([OH:4])=O)nn1",
|
|
5
|
+
"name": "GGaz",
|
|
6
|
+
"author": "Datagrok",
|
|
7
|
+
"molfile": "\n MJ201900 \n\n 17 17 0 0 0 0 0 0 0 0999 V2000\n 18.8168 -12.6760 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0\n 19.5312 -13.0885 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 20.2457 -12.6760 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 20.9602 -13.0885 0.0000 R# 0 0 0 0 0 0 0 0 0 0 0 0\n 20.2457 -11.8510 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 19.1403 -15.8019 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0\n 19.8547 -16.2144 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 20.5692 -15.8019 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 21.2837 -16.2144 0.0000 R# 0 0 0 0 0 0 0 0 0 0 0 0\n 20.5692 -14.9769 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 19.5083 -13.8885 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0\n 18.8409 -14.3735 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0\n 19.0958 -15.1581 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0\n 19.9208 -15.1581 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 20.1757 -14.3735 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 18.4258 -16.2144 0.0000 R# 0 0 0 0 0 0 0 0 0 0 0 0\n 18.1023 -13.0885 0.0000 R# 0 0 0 0 0 0 0 0 0 0 0 0\n 2 3 1 0 0 0 0\n 3 5 2 0 0 0 0\n 7 8 1 0 0 0 0\n 8 10 2 0 0 0 0\n 3 4 1 0 0 0 0\n 8 9 1 0 0 0 0\n 14 15 2 0 0 0 0\n 11 15 1 0 0 0 0\n 11 12 1 0 0 0 0\n 13 14 1 0 0 0 0\n 12 13 2 0 0 0 0\n 2 11 1 0 0 0 0\n 7 14 1 0 0 0 0\n 1 2 1 0 0 0 0\n 1 17 1 0 0 0 0\n 6 7 1 0 0 0 0\n 6 16 1 0 0 0 0\nM RGP 4 4 2 9 4 16 3 17 1\nM END\n",
|
|
8
|
+
"naturalAnalog": "G",
|
|
9
|
+
"rgroups": [
|
|
10
|
+
{
|
|
11
|
+
"capGroupSMILES": "[*:1][H]",
|
|
12
|
+
"alternateId": "R1-H",
|
|
13
|
+
"capGroupName": "H",
|
|
14
|
+
"label": "R1"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"capGroupSMILES": "O[*:2]",
|
|
18
|
+
"alternateId": "R2-OH",
|
|
19
|
+
"capGroupName": "OH",
|
|
20
|
+
"label": "R2"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"capGroupSMILES": "[*:3][H]",
|
|
24
|
+
"alternateId": "R3-H",
|
|
25
|
+
"capGroupName": "H",
|
|
26
|
+
"label": "R3"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"capGroupSMILES": "O[*:4]",
|
|
30
|
+
"alternateId": "R4-OH",
|
|
31
|
+
"capGroupName": "OH",
|
|
32
|
+
"label": "R4"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"createDate": null,
|
|
36
|
+
"id": 0,
|
|
37
|
+
"polymerType": "PEPTIDE",
|
|
38
|
+
"symbol": "GGaz"
|
|
39
|
+
}
|
|
40
|
+
]
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.3",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Alexey Choposky",
|
|
7
7
|
"email": "achopovsky@datagrok.ai"
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
}
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@datagrok-libraries/bio": "^5.
|
|
26
|
-
"@datagrok-libraries/chem-meta": "^1.2.
|
|
25
|
+
"@datagrok-libraries/bio": "^5.44.2",
|
|
26
|
+
"@datagrok-libraries/chem-meta": "^1.2.7",
|
|
27
27
|
"@datagrok-libraries/tutorials": "^1.4.0",
|
|
28
|
-
"@datagrok-libraries/utils": "^4.3.
|
|
28
|
+
"@datagrok-libraries/utils": "^4.3.5",
|
|
29
29
|
"@types/react": "^18.0.15",
|
|
30
30
|
"cash-dom": "^8.1.0",
|
|
31
31
|
"datagrok-api": "^1.21.1",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@datagrok-libraries/helm-web-editor": "^1.1.11",
|
|
43
43
|
"@datagrok-libraries/js-draw-lite": "^0.0.8",
|
|
44
|
-
"@datagrok/bio": "^2.15.
|
|
45
|
-
"@datagrok/helm": "^2.5.
|
|
46
|
-
"@datagrok/chem": "^1.12.
|
|
44
|
+
"@datagrok/bio": "^2.15.6",
|
|
45
|
+
"@datagrok/helm": "^2.5.3",
|
|
46
|
+
"@datagrok/chem": "^1.12.1",
|
|
47
47
|
"@types/jquery": "^3.5.14",
|
|
48
48
|
"@types/js-yaml": "^4.0.5",
|
|
49
49
|
"@types/lodash": "^4.14.202",
|
package/src/package-test.ts
CHANGED
|
@@ -2,14 +2,17 @@ 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 {runTests, tests, TestContext} from '@datagrok-libraries/utils/src/test';
|
|
5
|
+
import {runTests, tests, TestContext, initAutoTests as initTests} from '@datagrok-libraries/utils/src/test';
|
|
6
6
|
|
|
7
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
11
|
import './tests/polytool-convert-tests';
|
|
12
|
+
import './tests/polytool-unrule-tests';
|
|
12
13
|
import './tests/polytool-enumerate-tests';
|
|
14
|
+
import './tests/polytool-enumerate-breadth-tests';
|
|
15
|
+
import './tests/toAtomicLevel-tests';
|
|
13
16
|
|
|
14
17
|
import {OligoToolkitTestPackage} from './tests/utils';
|
|
15
18
|
|
|
@@ -25,3 +28,8 @@ export async function test(category: string, test: string, testContext: TestCont
|
|
|
25
28
|
const data = await runTests({category, test, testContext, verbose: true});
|
|
26
29
|
return DG.DataFrame.fromObjects(data)!;
|
|
27
30
|
}
|
|
31
|
+
|
|
32
|
+
//name: initAutoTests
|
|
33
|
+
export async function initAutoTests() {
|
|
34
|
+
await initTests(_package, _package.getModule('package-test.js'));
|
|
35
|
+
}
|
package/src/package.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {PolyToolCsvLibHandler} from './polytool/csv-to-json-monomer-lib-converte
|
|
|
25
25
|
import {ITranslationHelper} from './types';
|
|
26
26
|
import {addContextMenuUI} from './utils/context-menu';
|
|
27
27
|
import {PolyToolConvertFuncEditor} from './polytool/pt-convert-editor';
|
|
28
|
+
import {polyToolUnruleUI} from './polytool/pt-unrule';
|
|
28
29
|
|
|
29
30
|
export const _package: OligoToolkitPackage = new OligoToolkitPackage({debug: true}/**/);
|
|
30
31
|
|
|
@@ -162,6 +163,13 @@ export async function polyToolConvertTopMenu(): Promise<void> {
|
|
|
162
163
|
await polyToolConvertUI();
|
|
163
164
|
}
|
|
164
165
|
|
|
166
|
+
// //top-menu: Bio | PolyTool | Unrule...
|
|
167
|
+
// //name: polyToolUnrule
|
|
168
|
+
// //description: Perform uncyclization of polymers by rules
|
|
169
|
+
// export async function polyToolUnruleTopMenu(): Promise<void> {
|
|
170
|
+
// await polyToolUnruleUI();
|
|
171
|
+
// }
|
|
172
|
+
|
|
165
173
|
//name: getPolyToolConvertEditor
|
|
166
174
|
//tags: editor
|
|
167
175
|
//input: funccall call
|
package/src/polytool/const.ts
CHANGED
|
@@ -34,5 +34,6 @@ export const PT_UI_GET_HELM = 'Get HELM';
|
|
|
34
34
|
export const PT_UI_ADD_HELM = 'Add HELM column';
|
|
35
35
|
export const PT_UI_USE_CHIRALITY = 'Chirality engine';
|
|
36
36
|
export const PT_UI_DIALOG_CONVERSION = 'Poly Tool Conversion';
|
|
37
|
+
export const PT_UI_DIALOG_UNRULE = 'Poly Tool Unrule';
|
|
37
38
|
export const PT_UI_DIALOG_ENUMERATION = 'Poly Tool Enumeration';
|
|
38
39
|
export const PT_UI_RULES_USED = 'Rules used';
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import * as grok from 'datagrok-api/grok';
|
|
2
|
-
import * as DG from 'datagrok-api/dg';
|
|
1
|
+
// import * as grok from 'datagrok-api/grok';
|
|
2
|
+
// import * as DG from 'datagrok-api/dg';
|
|
3
3
|
|
|
4
|
-
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
5
|
-
import {ALIGNMENT, ALPHABET} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
6
4
|
|
|
7
|
-
import {
|
|
5
|
+
//import {ALIGNMENT, ALPHABET} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
6
|
+
|
|
7
|
+
import {Rules, RuleLink, RuleReaction} from './pt-rules';
|
|
8
8
|
|
|
9
9
|
export const RULES_DIMER = '(#2)';
|
|
10
10
|
export const RULES_HETERODIMER = '($2)';
|
|
11
11
|
|
|
12
|
-
function addCommonTags(col: DG.Column): void {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
12
|
+
// function addCommonTags(col: DG.Column): void {
|
|
13
|
+
// col.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
14
|
+
// col.setTag('aligned', ALIGNMENT.SEQ);
|
|
15
|
+
// col.setTag('alphabet', ALPHABET.PT);
|
|
16
|
+
// }
|
|
17
17
|
|
|
18
18
|
export class Chain {
|
|
19
|
-
linkages: {fChain: number, sChain: number, fMonomer:number, sMonomer:number, fR:number, sR:number}[];
|
|
19
|
+
linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[];
|
|
20
20
|
monomers: string[][];
|
|
21
21
|
|
|
22
22
|
constructor(
|
|
23
23
|
monomers: string[][],
|
|
24
|
-
linkages: {fChain: number, sChain: number, fMonomer:number, sMonomer:number, fR:number, sR:number}[]) {
|
|
24
|
+
linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[]) {
|
|
25
25
|
this.linkages = linkages;
|
|
26
26
|
this.monomers = monomers;
|
|
27
27
|
}
|
|
@@ -32,7 +32,7 @@ export class Chain {
|
|
|
32
32
|
const rawLinkages = fragmentation[1].split('|');
|
|
33
33
|
|
|
34
34
|
const monomers = new Array<Array<string>>(rawFragments.length);
|
|
35
|
-
const linkages: {fChain: number, sChain: number, fMonomer:number, sMonomer:number, fR:number, sR:number}[] = [];
|
|
35
|
+
const linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[] = [];
|
|
36
36
|
|
|
37
37
|
//HELM parsing
|
|
38
38
|
for (let i = 0; i < rawFragments.length; i++) {
|
|
@@ -66,15 +66,15 @@ export class Chain {
|
|
|
66
66
|
return new Chain(monomers, linkages);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
static fromNotation(sequence: string, rules: Rules) {
|
|
69
|
+
static fromNotation(sequence: string, rules: Rules): Chain {
|
|
70
70
|
const heterodimerCode = rules.heterodimerCode;
|
|
71
71
|
const homodimerCode = rules.homodimerCode;
|
|
72
72
|
const mainFragments: string[] = [];
|
|
73
73
|
|
|
74
|
-
const linkages: {fChain: number, sChain: number, fMonomer:number, sMonomer:number, fR:number, sR:number}[] = [];
|
|
74
|
+
const linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[] = [];
|
|
75
75
|
|
|
76
76
|
//NOTICE: this works only with simple single heterodimers
|
|
77
|
-
const heterodimeric = heterodimerCode !== null? sequence.split(`(${rules.heterodimerCode!})`) : '';
|
|
77
|
+
const heterodimeric = heterodimerCode !== null ? sequence.split(`(${rules.heterodimerCode!})`) : '';
|
|
78
78
|
if (heterodimerCode !== null && heterodimeric.length > 1) {
|
|
79
79
|
linkages.push({fChain: 0, sChain: 1, fMonomer: 1, sMonomer: 1, fR: 1, sR: 1});
|
|
80
80
|
mainFragments.push(heterodimeric[1].replaceAll('{', '').replaceAll('}', ''));
|
|
@@ -99,17 +99,32 @@ export class Chain {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
for (let i = 0; i < mainFragments.length; i++) {
|
|
103
|
+
if (homodimerCode !== null && mainFragments[i].includes(`(${homodimerCode!})`)) {
|
|
104
|
+
const idxSequence = mainFragments.length;
|
|
105
|
+
|
|
106
|
+
linkages.push({fChain: i, sChain: idxSequence, fMonomer: 1, sMonomer: 1, fR: 1, sR: 1});
|
|
107
|
+
const rawDimer = mainFragments[i].replace(`(${homodimerCode!})`, '');
|
|
108
|
+
const idx = rawDimer.indexOf('{');
|
|
109
|
+
const linker = rawDimer.slice(0, idx);
|
|
110
|
+
const body = rawDimer.replace(linker, '').replaceAll('{', '').replaceAll('}', '');
|
|
111
|
+
|
|
112
|
+
mainFragments[i] = linker + body;
|
|
113
|
+
mainFragments.push(body);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
102
117
|
const monomers = new Array<Array<string>>(mainFragments.length);
|
|
103
118
|
|
|
104
119
|
for (let i = 0; i < mainFragments.length; i++) {
|
|
105
120
|
const rawMonomers = mainFragments[i].split('-');
|
|
106
121
|
const linkedPositions = this.getLinkedPositions(rawMonomers, rules.linkRules);
|
|
107
122
|
const [monomersCycled, allPos1, allPos2, allAttaches1, allAttaches2] =
|
|
108
|
-
|
|
123
|
+
this.getAllCycles(rules.linkRules, rawMonomers, linkedPositions);
|
|
109
124
|
|
|
110
125
|
const monomersReady = new Array<string>(monomersCycled.length);
|
|
111
|
-
for (let j = 0; j < monomersCycled.length; j++)
|
|
112
|
-
|
|
126
|
+
// for (let j = 0; j < monomersCycled.length; j++)
|
|
127
|
+
// monomersReady[j] = `[${monomersCycled[j]}]`;
|
|
113
128
|
|
|
114
129
|
for (let j = 0; j < allPos1.length; j++) {
|
|
115
130
|
linkages.push({
|
|
@@ -122,10 +137,72 @@ export class Chain {
|
|
|
122
137
|
});
|
|
123
138
|
}
|
|
124
139
|
|
|
125
|
-
monomers[i] =
|
|
140
|
+
monomers[i] = monomersCycled;
|
|
126
141
|
}
|
|
127
142
|
|
|
128
|
-
|
|
143
|
+
const monomersAll: string[][] = [];
|
|
144
|
+
|
|
145
|
+
for (let i = 0; i < monomers.length; i++) {
|
|
146
|
+
const linkedPositions = this.getLinkedPositions(monomers[i], rules.reactionRules);
|
|
147
|
+
const [monomersCycled, allPos1, allPos2, ruleN] =
|
|
148
|
+
this.getAllReactants(rules.reactionRules, monomers[i], linkedPositions);
|
|
149
|
+
|
|
150
|
+
if (allPos1.length >= 1) {
|
|
151
|
+
const ch1 = new Array<string>(allPos2[0] - 1);
|
|
152
|
+
const ch2 = new Array<string>(monomersCycled.length - allPos2[0]);
|
|
153
|
+
for (let j = 0; j < allPos2[0] - 1; j++)
|
|
154
|
+
ch1[j] = monomersCycled[j];
|
|
155
|
+
|
|
156
|
+
for (let j = allPos2[0]; j < monomersCycled.length; j++)
|
|
157
|
+
ch2[j - allPos2[0]] = monomersCycled[j];
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
ch1[allPos1[0] - 1] = rules.reactionRules[ruleN[0]].name;
|
|
161
|
+
|
|
162
|
+
for (let j = 0; j < linkages.length; j++) {
|
|
163
|
+
if (linkages[j].fMonomer > allPos2[0]) {
|
|
164
|
+
linkages[j].fMonomer -= allPos2[0];
|
|
165
|
+
linkages[j].fChain++;
|
|
166
|
+
}
|
|
167
|
+
if (linkages[j].sMonomer > allPos2[0]) {
|
|
168
|
+
linkages[j].sMonomer -= allPos2[0];
|
|
169
|
+
linkages[j].sChain++;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
linkages.push({
|
|
173
|
+
fChain: 0,
|
|
174
|
+
sChain: 0,
|
|
175
|
+
fMonomer: allPos1[0],
|
|
176
|
+
sMonomer: allPos2[0] - 1,
|
|
177
|
+
fR: 3,
|
|
178
|
+
sR: 2,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
linkages.push({
|
|
182
|
+
fChain: 0,
|
|
183
|
+
sChain: 1,
|
|
184
|
+
fMonomer: allPos1[0],
|
|
185
|
+
sMonomer: 1,
|
|
186
|
+
fR: 4,
|
|
187
|
+
sR: 1,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const monomersReady1 = new Array<string>(ch1.length);
|
|
191
|
+
for (let j = 0; j < ch1.length; j++)
|
|
192
|
+
monomersReady1[j] = `[${ch1[j]}]`;
|
|
193
|
+
const monomersReady2 = new Array<string>(ch2.length);
|
|
194
|
+
for (let j = 0; j < ch2.length; j++)
|
|
195
|
+
monomersReady2[j] = `[${ch2[j]}]`;
|
|
196
|
+
|
|
197
|
+
monomersAll.push(ch1);
|
|
198
|
+
monomersAll.push(ch2);
|
|
199
|
+
} else {
|
|
200
|
+
monomersAll.push(monomers[i]);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const chain = new Chain(monomersAll, linkages);
|
|
205
|
+
return chain;
|
|
129
206
|
}
|
|
130
207
|
|
|
131
208
|
getHelmChanged(changeNumber: number, monomer: string): string {
|
|
@@ -134,17 +211,17 @@ export class Chain {
|
|
|
134
211
|
let idx1 = 0;
|
|
135
212
|
let idx2 = 0;
|
|
136
213
|
loop1:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
214
|
+
for (let i = 0; i < this.monomers.length; i++) {
|
|
215
|
+
loop2:
|
|
216
|
+
for (let j = 0; j < this.monomers[i].length; j++) {
|
|
217
|
+
if (counter == changeNumber) {
|
|
218
|
+
idx1 = i;
|
|
219
|
+
idx2 = j;
|
|
220
|
+
break loop1;
|
|
221
|
+
}
|
|
222
|
+
counter++;
|
|
223
|
+
}
|
|
146
224
|
}
|
|
147
|
-
}
|
|
148
225
|
|
|
149
226
|
const previous = this.monomers[idx1][idx2];
|
|
150
227
|
|
|
@@ -166,7 +243,8 @@ export class Chain {
|
|
|
166
243
|
for (let j = 0; j < this.monomers[i].length; j++) {
|
|
167
244
|
if (j > 0)
|
|
168
245
|
helm += '.';
|
|
169
|
-
|
|
246
|
+
const symbol = this.monomers[i][j];
|
|
247
|
+
helm += symbol.length > 1 ? `[${symbol}]` : symbol;
|
|
170
248
|
}
|
|
171
249
|
helm += `}`;
|
|
172
250
|
}
|
|
@@ -185,8 +263,13 @@ export class Chain {
|
|
|
185
263
|
return helm;
|
|
186
264
|
}
|
|
187
265
|
|
|
188
|
-
|
|
189
|
-
|
|
266
|
+
getNotation(rules: Rules): string {
|
|
267
|
+
return 'not implemented';
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
protected static getLinkedPositions(monomers: string[], rules: RuleLink[] | RuleReaction []):
|
|
271
|
+
[number, number, number][] {
|
|
272
|
+
const result: [number, number, number][] = new Array<[number, number, number]>(rules.length);
|
|
190
273
|
|
|
191
274
|
for (let i = 0; i < rules.length; i++) {
|
|
192
275
|
let firstFound = false;
|
|
@@ -226,19 +309,18 @@ export class Chain {
|
|
|
226
309
|
}
|
|
227
310
|
|
|
228
311
|
if (!(firstFound && secondFound))
|
|
229
|
-
result[i] = [-1, -1];
|
|
312
|
+
result[i] = [-1, -1, -1];
|
|
230
313
|
else if (firstIsFirst)
|
|
231
|
-
result[i] = [firstEntryIndex, secondEntryIndex];
|
|
314
|
+
result[i] = [firstEntryIndex, secondEntryIndex, i];
|
|
232
315
|
else
|
|
233
|
-
result[i] = [secondEntryIndex, firstEntryIndex];
|
|
316
|
+
result[i] = [secondEntryIndex, firstEntryIndex, i];
|
|
234
317
|
}
|
|
235
318
|
|
|
236
|
-
|
|
237
319
|
return result;
|
|
238
320
|
}
|
|
239
321
|
|
|
240
|
-
protected static getAllCycles(rules: RuleLink[], monomers: string [], positions: [number, number][])
|
|
241
|
-
|
|
322
|
+
protected static getAllCycles(rules: RuleLink[], monomers: string [], positions: [number, number, number][]):
|
|
323
|
+
[string [], number [], number [], number [], number []] {
|
|
242
324
|
const allPos1: number [] = [];
|
|
243
325
|
const allPos2: number [] = [];
|
|
244
326
|
const allAttaches1: number [] = [];
|
|
@@ -251,7 +333,6 @@ export class Chain {
|
|
|
251
333
|
|
|
252
334
|
const firstMonomer = monomers[positions[i][0]];
|
|
253
335
|
const secondMonomer = monomers[positions[i][1]];
|
|
254
|
-
|
|
255
336
|
monomers[positions[i][0]] = monomers[positions[i][0]].replace(firstMonomer, rules[i].firstSubstitution);
|
|
256
337
|
monomers[positions[i][1]] = monomers[positions[i][1]].replace(secondMonomer, rules[i].secondSubstitution);
|
|
257
338
|
|
|
@@ -263,17 +344,40 @@ export class Chain {
|
|
|
263
344
|
|
|
264
345
|
return [monomers, allPos1, allPos2, allAttaches1, allAttaches2];
|
|
265
346
|
}
|
|
347
|
+
|
|
348
|
+
protected static getAllReactants(rules: RuleReaction[], monomers: string [], positions: [number, number, number][]):
|
|
349
|
+
[string [], number [], number [], number []] {
|
|
350
|
+
const allPos1: number [] = [];
|
|
351
|
+
const allPos2: number [] = [];
|
|
352
|
+
const rule: number [] = [];
|
|
353
|
+
const ruleCount = rules.length;
|
|
354
|
+
|
|
355
|
+
for (let i = 0; i < ruleCount; i++) {
|
|
356
|
+
if (positions[i][0] == -1)
|
|
357
|
+
continue;
|
|
358
|
+
|
|
359
|
+
const firstMonomer = monomers[positions[i][0]];
|
|
360
|
+
const secondMonomer = monomers[positions[i][1]];
|
|
361
|
+
monomers[positions[i][0]] = monomers[positions[i][0]].replace(firstMonomer, rules[i].firstMonomer);
|
|
362
|
+
monomers[positions[i][1]] = monomers[positions[i][1]].replace(secondMonomer, rules[i].secondMonomer);
|
|
363
|
+
|
|
364
|
+
allPos1.push(positions[i][0] + 1);
|
|
365
|
+
allPos2.push(positions[i][1] + 1);
|
|
366
|
+
rule.push(positions[i][2]);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return [monomers, allPos1, allPos2, rule];
|
|
370
|
+
}
|
|
266
371
|
}
|
|
267
372
|
|
|
268
373
|
/** The main PolyTool convert engine. Returns list of Helms. Covered with tests. */
|
|
269
374
|
export function doPolyToolConvert(sequences: string[], rules: Rules): string[] {
|
|
270
375
|
const helms = new Array<string>(sequences.length);
|
|
271
376
|
for (let i = 0; i < sequences.length; i++) {
|
|
272
|
-
if (sequences[i]
|
|
377
|
+
if (sequences[i] == null) { helms[i] = ''; } else {
|
|
273
378
|
const chain = Chain.fromNotation(sequences[i], rules);
|
|
274
379
|
helms[i] = chain.getHelm();
|
|
275
380
|
}
|
|
276
381
|
}
|
|
277
|
-
|
|
278
382
|
return helms;
|
|
279
383
|
}
|
|
@@ -9,6 +9,7 @@ import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
|
9
9
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
10
10
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
11
11
|
import {getSeqHelper, ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
12
|
+
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
12
13
|
|
|
13
14
|
import {getRules, RuleInputs, RULES_PATH, RULES_STORAGE_NAME} from './pt-rules';
|
|
14
15
|
import {doPolyToolConvert} from './pt-conversion';
|
|
@@ -23,6 +24,17 @@ import {
|
|
|
23
24
|
|
|
24
25
|
import {_package} from '../package';
|
|
25
26
|
|
|
27
|
+
type PolyToolConvertSerialized = {
|
|
28
|
+
generateHelm: boolean;
|
|
29
|
+
chiralityEngine: boolean;
|
|
30
|
+
rules: string[];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type PolyToolEnumerateChemSerialized = {
|
|
34
|
+
mol: string;
|
|
35
|
+
screenLibrary: string | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
26
38
|
export function polyToolEnumerateChemUI(cell?: DG.Cell): void {
|
|
27
39
|
getPolyToolEnumerationChemDialog(cell)
|
|
28
40
|
.then((dialog) => {
|
|
@@ -45,45 +57,52 @@ export async function polyToolConvertUI(): Promise<void> {
|
|
|
45
57
|
}
|
|
46
58
|
}
|
|
47
59
|
|
|
48
|
-
export async function getPolyToolConvertDialog(
|
|
60
|
+
export async function getPolyToolConvertDialog(srcCol?: DG.Column): Promise<DG.Dialog> {
|
|
49
61
|
const subs: Unsubscribable[] = [];
|
|
50
62
|
const destroy = () => {
|
|
51
63
|
for (const sub of subs) sub.unsubscribe();
|
|
52
64
|
};
|
|
53
65
|
try {
|
|
54
|
-
|
|
55
|
-
if (!
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
let srcColVal: DG.Column<string> | undefined = srcCol;
|
|
67
|
+
if (!srcColVal) {
|
|
68
|
+
const srcColList = grok.shell.t.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);
|
|
69
|
+
if (srcColList.length < 1)
|
|
70
|
+
throw new Error(PT_ERROR_DATAFRAME);
|
|
71
|
+
srcColVal = srcColList[0];
|
|
72
|
+
}
|
|
73
|
+
const srcColInput = ui.input.column('Column', {
|
|
74
|
+
table: srcColVal.dataFrame, value: srcColVal,
|
|
75
|
+
filter: (col: DG.Column) => {
|
|
76
|
+
if (col.semType !== DG.SEMTYPE.MACROMOLECULE) return false;
|
|
77
|
+
const sh = SeqHandler.forColumn(col);
|
|
78
|
+
return sh.notation === NOTATION.CUSTOM;
|
|
79
|
+
}
|
|
61
80
|
});
|
|
62
81
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const generateHelmChoiceInput = ui.input.bool(PT_UI_GET_HELM, {value: true});
|
|
66
|
-
ui.tooltip.bind(generateHelmChoiceInput.root, PT_UI_ADD_HELM);
|
|
82
|
+
const generateHelmInput = ui.input.bool(PT_UI_GET_HELM, {value: true});
|
|
83
|
+
ui.tooltip.bind(generateHelmInput.root, PT_UI_ADD_HELM);
|
|
67
84
|
|
|
68
85
|
const chiralityEngineInput = ui.input.bool(PT_UI_USE_CHIRALITY, {value: false});
|
|
69
|
-
|
|
86
|
+
let ruleFileList: string[];
|
|
87
|
+
const ruleInputs = new RuleInputs(RULES_PATH, RULES_STORAGE_NAME, '.json', {
|
|
88
|
+
onValueChanged: (value: string[]) => { ruleFileList = value;}
|
|
89
|
+
});
|
|
70
90
|
const rulesHeader = ui.inlineText([PT_UI_RULES_USED]);
|
|
71
91
|
ui.tooltip.bind(rulesHeader, 'Add or specify rules to use');
|
|
72
92
|
const rulesForm = await ruleInputs.getForm();
|
|
73
93
|
|
|
74
|
-
const div = ui.
|
|
75
|
-
|
|
76
|
-
|
|
94
|
+
const div = ui.divV([
|
|
95
|
+
srcColInput,
|
|
96
|
+
generateHelmInput,
|
|
77
97
|
chiralityEngineInput,
|
|
78
98
|
rulesHeader,
|
|
79
99
|
rulesForm
|
|
80
100
|
]);
|
|
81
101
|
|
|
82
|
-
|
|
83
102
|
const exec = async (): Promise<void> => {
|
|
84
103
|
try {
|
|
85
104
|
const ruleFileList = await ruleInputs.getActive();
|
|
86
|
-
await polyToolConvert(
|
|
105
|
+
await polyToolConvert(srcColInput.value!, generateHelmInput.value!, chiralityEngineInput.value!, ruleFileList);
|
|
87
106
|
} catch (err: any) {
|
|
88
107
|
defaultErrorHandler(err);
|
|
89
108
|
}
|
|
@@ -95,7 +114,19 @@ export async function getPolyToolConvertDialog(targetCol?: DG.Column): Promise<D
|
|
|
95
114
|
subs.push(dialog.onClose.subscribe(() => {
|
|
96
115
|
destroy();
|
|
97
116
|
}));
|
|
98
|
-
|
|
117
|
+
dialog.history(
|
|
118
|
+
/* getInput */ (): PolyToolConvertSerialized => {
|
|
119
|
+
return {
|
|
120
|
+
generateHelm: generateHelmInput.value,
|
|
121
|
+
chiralityEngine: chiralityEngineInput.value,
|
|
122
|
+
rules: ruleFileList,
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
/* applyInput */ (x: PolyToolConvertSerialized): void => {
|
|
126
|
+
generateHelmInput.value = x.generateHelm;
|
|
127
|
+
chiralityEngineInput.value = x.chiralityEngine;
|
|
128
|
+
ruleInputs.setActive(ruleFileList);
|
|
129
|
+
});
|
|
99
130
|
return dialog;
|
|
100
131
|
} catch (err: any) {
|
|
101
132
|
destroy(); // on failing to build a dialog
|
|
@@ -133,15 +164,15 @@ async function getPolyToolEnumerationChemDialog(cell?: DG.Cell): Promise<DG.Dial
|
|
|
133
164
|
molInput.setMolFile(molfileValue);
|
|
134
165
|
|
|
135
166
|
//const helmInput = helmHelper.createHelmInput('Macromolecule', {value: helmValue});
|
|
136
|
-
const
|
|
167
|
+
const screenLibraryInput = ui.input.choice('Library to use', {value: null, items: libList});
|
|
137
168
|
|
|
138
169
|
molInput.root.setAttribute('style', `min-width:250px!important;`);
|
|
139
170
|
molInput.root.setAttribute('style', `max-width:250px!important;`);
|
|
140
|
-
|
|
171
|
+
screenLibraryInput.input.setAttribute('style', `min-width:250px!important;`);
|
|
141
172
|
|
|
142
173
|
const div = ui.div([
|
|
143
174
|
molInput.root,
|
|
144
|
-
|
|
175
|
+
screenLibraryInput.root
|
|
145
176
|
]);
|
|
146
177
|
|
|
147
178
|
subs.push(grok.events.onCurrentCellChanged.subscribe(() => {
|
|
@@ -160,7 +191,7 @@ async function getPolyToolEnumerationChemDialog(cell?: DG.Cell): Promise<DG.Dial
|
|
|
160
191
|
} else if (!molString.includes('R#')) {
|
|
161
192
|
grok.shell.warning('PolyTool: no R group was provided');
|
|
162
193
|
} else {
|
|
163
|
-
const molecules = await getEnumerationChem(molString,
|
|
194
|
+
const molecules = await getEnumerationChem(molString, screenLibraryInput.value!);
|
|
164
195
|
const molCol = DG.Column.fromStrings('Enumerated', molecules);
|
|
165
196
|
const df = DG.DataFrame.fromColumns([molCol]);
|
|
166
197
|
grok.shell.addTableView(df);
|
|
@@ -182,6 +213,17 @@ async function getPolyToolEnumerationChemDialog(cell?: DG.Cell): Promise<DG.Dial
|
|
|
182
213
|
subs.push(dialog.onClose.subscribe(() => {
|
|
183
214
|
destroy();
|
|
184
215
|
}));
|
|
216
|
+
dialog.history(
|
|
217
|
+
/* getInput */ (): PolyToolEnumerateChemSerialized => {
|
|
218
|
+
return {
|
|
219
|
+
mol: molInput.getMolFile(),
|
|
220
|
+
screenLibrary: screenLibraryInput.value,
|
|
221
|
+
};
|
|
222
|
+
},
|
|
223
|
+
/* applyInput */ (x: PolyToolEnumerateChemSerialized): void => {
|
|
224
|
+
molInput.setMolFile(x.mol);
|
|
225
|
+
screenLibraryInput.value = x.screenLibrary;
|
|
226
|
+
});
|
|
185
227
|
return dialog;
|
|
186
228
|
} catch (err: any) {
|
|
187
229
|
destroy();
|
|
@@ -215,7 +257,27 @@ export async function polyToolConvert(
|
|
|
215
257
|
|
|
216
258
|
const seqHelper: ISeqHelper = await getSeqHelper();
|
|
217
259
|
const toAtomicLevelRes = await seqHelper.helmToAtomicLevel(resHelmCol, chiralityEngine, /* highlight */ generateHelm);
|
|
218
|
-
const resMolCol = toAtomicLevelRes.molCol
|
|
260
|
+
const resMolCol = toAtomicLevelRes.molCol!;
|
|
261
|
+
|
|
262
|
+
// const rdkit = await grok.functions.call('Chem:getRdKitModule');
|
|
263
|
+
// for (let i = 0; i < rules.reactionRules.length; i++) {
|
|
264
|
+
// const reacSmarts = rules.reactionRules[i].reaction;
|
|
265
|
+
// const rxn = rdkit.get_rxn(reacSmarts);
|
|
266
|
+
|
|
267
|
+
// for (let j = 0; j < resMolCol.length; j++) {
|
|
268
|
+
// const mols = new rdkit.MolList();
|
|
269
|
+
// const mol = rdkit.get_mol(resMolCol.get(j));
|
|
270
|
+
// mols.append(mol!);
|
|
271
|
+
// const rctns = rxn.run_reactants(mols, 1);
|
|
272
|
+
// const size = rctns.size();
|
|
273
|
+
// const element = rctns.get(0);
|
|
274
|
+
// let molP: RDMol | null = null;
|
|
275
|
+
// molP = element.next();
|
|
276
|
+
// const molBlock = molP?.get_v3Kmolblock();
|
|
277
|
+
// resMolCol.set(j, molBlock!);
|
|
278
|
+
// }
|
|
279
|
+
// }
|
|
280
|
+
|
|
219
281
|
resMolCol.name = getUnusedName(table, `molfile(${seqCol.name})`);
|
|
220
282
|
resMolCol.semType = DG.SEMTYPE.MOLECULE;
|
|
221
283
|
if (table) {
|