@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.
@@ -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"
@@ -1,6 +1,7 @@
1
1
  n,seqs
2
- 1,R-F-C(1)-T-G-H-F-Y-P-C(1)-meI
2
+ 1,R-F-C(1)-T-G-H-F-Y-G-H-F-Y-G-H-F-Y-P-C(1)-meI
3
3
  2,C(1)-T-G-H-F-Y-P-C(1)-meI
4
4
  3,R-F-C(1)-T-G-H-F-Y-P-C(1)
5
5
  4,C(1)-T-G-H-F-H-P-C(1)
6
6
  5,R-F-D(2)-T-G-H-F-Y-P-NH2(2)
7
+ 6,R-F-aG(3)-T-G-H-F-Y-P-azG(3)-meI
@@ -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.1",
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.42.15",
26
- "@datagrok-libraries/chem-meta": "^1.2.5",
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.0",
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.1",
45
- "@datagrok/helm": "^2.5.0",
46
- "@datagrok/chem": "^1.12.0",
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",
@@ -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
@@ -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 {Rules, RuleLink, getRules} from './pt-rules';
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
- col.semType = DG.SEMTYPE.MACROMOLECULE;
14
- col.setTag('aligned', ALIGNMENT.SEQ);
15
- col.setTag('alphabet', ALPHABET.PT);
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
- this.getAllCycles(rules.linkRules, rawMonomers, linkedPositions);
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
- monomersReady[j] = `[${monomersCycled[j]}]`;
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] = monomersReady;
140
+ monomers[i] = monomersCycled;
126
141
  }
127
142
 
128
- return new Chain(monomers, linkages);
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
- for (let i = 0; i < this.monomers.length; i++) {
138
- loop2:
139
- for (let j = 0; j < this.monomers[i].length; j++) {
140
- if (counter == changeNumber) {
141
- idx1 = i;
142
- idx2 = j;
143
- break loop1;
144
- }
145
- counter++;
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
- helm += this.monomers[i][j];
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
- protected static getLinkedPositions(monomers: string[], rules: RuleLink[]): [number, number][] {
189
- const result: [number, number][] = new Array<[number, number]>(rules.length);
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
- [string [], number [], number [], number [], number []] {
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] === undefined) { helms[i] = ''; } else {
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(targetCol?: DG.Column): Promise<DG.Dialog> {
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
- const targetColumns = grok.shell.t.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);
55
- if (!targetColumns)
56
- throw new Error(PT_ERROR_DATAFRAME);
57
-
58
- const targetColumnInput = ui.input.column('Column', {
59
- table: grok.shell.t, value: targetColumns[0],
60
- filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE
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
- targetColumnInput.value = targetCol ? targetCol : targetColumnInput.value;
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
- const ruleInputs = new RuleInputs(RULES_PATH, RULES_STORAGE_NAME, '.json');
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.div([
75
- targetColumnInput,
76
- generateHelmChoiceInput,
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(targetColumnInput.value!, generateHelmChoiceInput.value!, chiralityEngineInput.value!, ruleFileList);
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 screenLibrary = ui.input.choice('Library to use', {value: null, items: libList});
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
- screenLibrary.input.setAttribute('style', `min-width:250px!important;`);
171
+ screenLibraryInput.input.setAttribute('style', `min-width:250px!important;`);
141
172
 
142
173
  const div = ui.div([
143
174
  molInput.root,
144
- screenLibrary.root
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, screenLibrary.value!);
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) {