@datagrok/bio 2.12.12 → 2.12.13

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.
@@ -1,367 +0,0 @@
1
- import * as grok from 'datagrok-api/grok';
2
-
3
- export async function getMacroMol(monomers: any[][]): Promise<string[]> {
4
- const result: string[] = [];
5
- const moduleRdkit = await grok.functions.call('Chem:getRdKitModule');
6
- for (let i = 0; i < monomers.length; i++) {
7
- for (let j = 0; j < monomers[i].length; j++) {
8
- const mol = moduleRdkit.get_mol(monomers[i][j]['molfile']);
9
- const a = mol.get_v3Kmolblock();
10
- const indices = getIndices(monomers[i][j], a);
11
- monomers[i][j]['indices'] = indices;
12
-
13
- monomers[i][j]['molfile'] = await rotateBackboneV3000(a, indices);
14
- mol?.delete();
15
- }
16
- result.push(linkV3000(monomers[i]));
17
- }
18
-
19
- return result;
20
- }
21
-
22
- function getIndices(monomer: any, molV3000: string): {first: number, last: number,
23
- remFirst: number, remLast: number,
24
- remBondFirst: number, remBondLast: Number} {
25
- const molfile = monomer['molfile'];
26
- let indexStart = molfile.indexOf('M RGP', 0) + 8;
27
- let indexEnd = molfile.indexOf('\n', indexStart);
28
- const indicesData = molfile.substring(indexStart, indexEnd).replaceAll(' ', ' ').replaceAll(' ', ' ');
29
- let parsedData = indicesData.split(' ');
30
- const remFirst = parsedData[2] == '1' ? parseInt(parsedData[1]) : parseInt(parsedData[3]);
31
- const remLast = parsedData[2] == '2' ? parseInt(parsedData[1]) : parseInt(parsedData[3]);
32
-
33
- const numbers = extractAtomsBondsNumbersV3000(molV3000);
34
- let indexBonds = molV3000.indexOf('M V30 BEGIN BOND'); // V3000 index for bonds
35
- indexBonds = molV3000.indexOf('\n', indexBonds);
36
- indexStart = indexBonds;
37
- indexEnd = indexBonds;
38
-
39
- let first = 0;
40
- let last = 0;
41
- let remBondFirst = 0;
42
- let remBondLast = 0;
43
-
44
- for (let j = 0; j < numbers.nbond; j++) {
45
- if (first == 0 || last == 0) {
46
- indexStart = molV3000.indexOf('V30', indexStart) + 4;
47
- indexEnd = molV3000.indexOf('\n', indexStart);
48
- const bondData = molV3000.substring(indexStart, indexEnd).replaceAll(' ', ' ').replaceAll(' ', ' ');
49
- parsedData = bondData.split(' ');
50
-
51
- if (parseInt(parsedData[2]) == remFirst) {
52
- first = parseInt(parsedData[3]);
53
- remBondFirst = parseInt(parsedData[0]);
54
- } else if (parseInt(parsedData[3]) == remFirst) {
55
- first = parseInt(parsedData[2]);
56
- remBondFirst = parseInt(parsedData[0]);
57
- } else if (parseInt(parsedData[2]) == remLast) {
58
- last = parseInt(parsedData[3]);
59
- remBondLast = parseInt(parsedData[0]);
60
- } else if (parseInt(parsedData[3]) == remLast) {
61
- last = parseInt(parsedData[2]);
62
- remBondLast = parseInt(parsedData[0]);
63
- }
64
- }
65
- }
66
-
67
- return {first, last, remFirst, remLast, remBondFirst, remBondLast};
68
- }
69
-
70
- async function rotateBackboneV3000(molBlock: string, indices:any): Promise<string> {
71
- const coordinates = extractAtomDataV3000(molBlock);
72
- const natom = coordinates.atomIndex.length;
73
- const first = indices['first'];
74
- const last = indices['last'];
75
-
76
- const xCenter = (coordinates.x[last] + coordinates.x[first]) / 2;
77
- const yCenter = (coordinates.y[last] + coordinates.y[first]) / 2;
78
-
79
- //place to center
80
- for (let i = 0; i < natom; i++) {
81
- coordinates.x[i] -= xCenter;
82
- coordinates.y[i] -= yCenter;
83
- }
84
-
85
- let angle = 0;
86
- if (coordinates.x[first] == 0) {
87
- angle = coordinates.y[first] > coordinates.y[last] ? Math.PI / 2 : 3 * Math.PI / 2;
88
- } else if (coordinates.y[first] == 0) {
89
- angle = coordinates.x[first] > coordinates.x[last] ? Math.PI : 0;
90
- } else {
91
- const derivative = coordinates.y[first] / coordinates.x[first];
92
- if (coordinates.x[first] < coordinates.x[last])
93
- angle = derivative > 0 ? Math.PI - Math.atan(derivative) : Math.atan(derivative);
94
- else
95
- angle = derivative > 0 ? Math.atan(derivative) : Math.PI - Math.atan(derivative);
96
- }
97
-
98
- const cos = Math.cos(angle);
99
- const sin = Math.sin(angle);
100
-
101
- for (let i = 0; i < natom; i++) {
102
- const xAdd = coordinates.x[i];
103
- coordinates.x[i] = xAdd * cos - coordinates.y[i] * sin;
104
- coordinates.y[i] = xAdd * sin + coordinates.y[i] * cos;
105
- }
106
-
107
- //place to right
108
- const xShift = coordinates.x[first];
109
- for (let i = 0; i < natom; i++)
110
- coordinates.x[i] -= xShift;
111
-
112
- //rewrite molBlock
113
- let index = molBlock.indexOf('M V30 BEGIN ATOM'); // V3000 index for atoms coordinates
114
- index = molBlock.indexOf('\n', index);
115
- let indexEnd = index;
116
- for (let i = 0; i < natom; i++) {
117
- index = molBlock.indexOf('V30', index) + 4;
118
- index = molBlock.indexOf(' ', index) + 1;
119
- index = molBlock.indexOf(' ', index) + 1;
120
- indexEnd = molBlock.indexOf(' ', index) + 1;
121
- indexEnd = molBlock.indexOf(' ', indexEnd);
122
-
123
- molBlock = molBlock.slice(0, index) +
124
- coordinates.x[i] + ' ' + coordinates.y[i] +
125
- molBlock.slice(indexEnd);
126
-
127
- index = molBlock.indexOf('\n', index) + 1;
128
- }
129
-
130
- return molBlock;
131
- }
132
-
133
- function extractAtomDataV3000(molBlock: string) {
134
- const numbers = extractAtomsBondsNumbersV3000(molBlock);
135
- let index = molBlock.indexOf('M V30 BEGIN ATOM'); // V3000 index for atoms coordinates
136
- index = molBlock.indexOf('\n', index);
137
- let indexEnd = index;
138
-
139
- const indexes: number[] = Array(numbers.natom);
140
- const types: string[] = Array(numbers.natom);
141
- const x: number[] = Array(numbers.natom);
142
- const y: number[] = Array(numbers.natom);
143
-
144
- for (let i = 0; i < numbers.natom; i++) {
145
- index = molBlock.indexOf('V30', index) + 4;
146
- indexEnd = molBlock.indexOf(' ', index);
147
- indexes[i] = parseInt(molBlock.substring(index, indexEnd));
148
-
149
- index = indexEnd + 1;
150
- indexEnd = molBlock.indexOf(' ', index);
151
- types[i] = molBlock.substring(index, indexEnd);
152
-
153
- index = indexEnd + 1;
154
- indexEnd = molBlock.indexOf(' ', index);
155
- x[i] = parseFloat(molBlock.substring(index, indexEnd));
156
-
157
- index = indexEnd + 1;
158
- indexEnd = molBlock.indexOf(' ', index);
159
- y[i] = parseFloat(molBlock.substring(index, indexEnd));
160
-
161
- index = molBlock.indexOf('\n', index) + 1;
162
- }
163
-
164
- return {atomIndex: indexes, atomType: types, x: x, y: y};
165
- }
166
-
167
- function linkV3000(monomers: any[]): string {
168
- let macroMolBlock = '\nDatagrok macromolecule handler\n\n';
169
- macroMolBlock += ' 0 0 0 0 0 0 999 V3000\n';
170
- macroMolBlock += 'M V30 BEGIN CTAB\n';
171
- let atomBlock = '';
172
- let bondBlock = '';
173
- let natom = 0;
174
- let nbond = 0;
175
- let xShift = 0;
176
-
177
- for (let i = 0; i < monomers.length; i++) {
178
- let molfile = monomers[i]['molfile'];
179
- const first = monomers[i]['indices']['first'];
180
- const last = monomers[i]['indices']['last'];
181
- const remFirst = monomers[i]['indices']['remFirst'];
182
- const remLast = monomers[i]['indices']['remLast'];
183
- const remBondFirst = monomers[i]['indices']['remBondFirst'];
184
- const remBondLast = monomers[i]['indices']['remBondLast'];
185
- molfile = molfile.replaceAll('(-\nM V30 ', '(')
186
- .replaceAll('-\nM V30 ', '').replaceAll(' )', ')');
187
- const numbers = extractAtomsBondsNumbersV3000(molfile);
188
- const coordinates = extractAtomDataV3000(molfile);
189
-
190
- let indexAtoms = molfile.indexOf('M V30 BEGIN ATOM'); // V3000 index for atoms coordinates
191
- indexAtoms = molfile.indexOf('\n', indexAtoms);
192
- let index = indexAtoms;
193
- let indexEnd = indexAtoms;
194
- const totalShift = xShift - coordinates.x[first - 1];
195
-
196
- for (let j = 0; j < numbers.natom; j++) {
197
- if (coordinates.atomIndex[j] != remFirst && coordinates.atomIndex[j] != remLast) { //|| i == 0) {
198
- //rewrite atom number
199
- index = molfile.indexOf('V30', index) + 4;
200
- indexEnd = molfile.indexOf(' ', index);
201
-
202
- let atomNumber = parseInt(molfile.substring(index, indexEnd));
203
- atomNumber = (atomNumber > remFirst && atomNumber > remLast) ? atomNumber - 2 :
204
- (atomNumber > remFirst || atomNumber > remLast) ? atomNumber - 1 : atomNumber;
205
- atomNumber += natom;
206
- molfile = molfile.slice(0, index) + atomNumber + molfile.slice(indexEnd);
207
-
208
- //rewrite coordinates
209
- index = molfile.indexOf(' ', index) + 1;
210
- index = molfile.indexOf(' ', index) + 1;
211
- indexEnd = molfile.indexOf(' ', index);
212
-
213
- let coordinate = Math.round(10000 * (parseFloat(molfile.substring(index, indexEnd)) + totalShift)) / 10000;
214
- molfile = molfile.slice(0, index) + coordinate + molfile.slice(indexEnd);
215
-
216
- index = molfile.indexOf(' ', index) + 1;
217
- indexEnd = molfile.indexOf(' ', index);
218
- coordinate = Math.round(10000 * (parseFloat(molfile.substring(index, indexEnd)))) / 10000;
219
- molfile = molfile.slice(0, index) + coordinate + molfile.slice(indexEnd);
220
-
221
- index = molfile.indexOf('\n', index) + 1;
222
- } else {
223
- index = molfile.indexOf('M V30', index) - 1;
224
- indexEnd = molfile.indexOf('\n', index + 1);
225
- molfile = molfile.slice(0, index) + molfile.slice(indexEnd);
226
- }
227
- }
228
-
229
- const indexAtomsEnd = molfile.indexOf('M V30 END ATOM');
230
- atomBlock += molfile.substring(indexAtoms + 1, indexAtomsEnd);
231
-
232
- let indexBonds = molfile.indexOf('M V30 BEGIN BOND'); // V3000 index for bonds
233
- indexBonds = molfile.indexOf('\n', indexBonds);
234
- index = indexBonds;
235
- indexEnd = indexBonds;
236
- let bondNumber = 0;
237
-
238
- for (let j = 0; j < numbers.nbond; j++) {
239
- //rewrite bond number
240
- index = molfile.indexOf('V30', index) + 4;
241
- indexEnd = molfile.indexOf(' ', index);
242
- bondNumber = parseInt(molfile.substring(index, indexEnd));
243
-
244
- if (bondNumber == remBondFirst || bondNumber == remBondLast) {
245
- indexEnd = molfile.indexOf('\n', index) + 1;
246
- index -= 7;
247
- molfile = molfile.slice(0, index) + molfile.slice(indexEnd);
248
- continue;
249
- }
250
-
251
- bondNumber = (bondNumber > remBondFirst && bondNumber > remBondLast) ? bondNumber - 2 :
252
- (bondNumber > remBondFirst || bondNumber > remBondLast) ? bondNumber - 1 : bondNumber;
253
- bondNumber += nbond;
254
-
255
- molfile = molfile.slice(0, index) + bondNumber + molfile.slice(indexEnd);
256
-
257
- //rewrite atom pair in bond
258
- index = molfile.indexOf(' ', index) + 1;
259
- index = molfile.indexOf(' ', index) + 1;
260
- indexEnd = molfile.indexOf(' ', index);
261
- let atomNumber = parseInt(molfile.substring(index, indexEnd));
262
- atomNumber = (atomNumber > remFirst && atomNumber > remLast) ? atomNumber - 2 :
263
- (atomNumber > remFirst || atomNumber > remLast) ? atomNumber - 1 : atomNumber;
264
- atomNumber += natom;
265
- molfile = molfile.slice(0, index) + atomNumber + molfile.slice(indexEnd);
266
- index = molfile.indexOf(' ', index) + 1;
267
- indexEnd = Math.min(molfile.indexOf('\n', index), molfile.indexOf(' ', index));
268
- atomNumber = parseInt(molfile.substring(index, indexEnd));
269
- atomNumber = (atomNumber > remFirst && atomNumber > remLast) ? atomNumber - 2 :
270
- (atomNumber > remFirst || atomNumber > remLast) ? atomNumber - 1 : atomNumber;
271
- atomNumber += natom;
272
- molfile = molfile.slice(0, index) + atomNumber + molfile.slice(indexEnd);
273
-
274
- index = molfile.indexOf('\n', index) + 1;
275
- }
276
-
277
- const indexBondEnd = molfile.indexOf('M V30 END BOND');
278
- bondBlock += molfile.substring(indexBonds + 1, indexBondEnd);
279
- //let indexCollection = molfile.indexOf('M V30 MDLV30/STEABS ATOMS=('); // V3000 index for collections
280
-
281
- // while (indexCollection != -1) {
282
- // indexCollection += 28;
283
- // const collectionEnd = molfile.indexOf(')', indexCollection);
284
- // const collectionEntries = molfile.substring(indexCollection, collectionEnd).split(' ').slice(1);
285
- // collectionEntries.forEach((e: string) => {
286
- // collection.push(parseInt(e) + natom);
287
- // });
288
- // indexCollection = collectionEnd;
289
- // indexCollection = molfile.indexOf('M V30 MDLV30/STEABS ATOMS=(', indexCollection);
290
- // }
291
-
292
- natom += numbers.natom - 2;
293
- nbond += numbers.nbond - 2;
294
- xShift += coordinates.x[last] - coordinates.x[first] + 1;
295
-
296
- if (i == monomers.length - 1) {
297
- natom++;
298
- const shift = xShift + 0.2;
299
- atomBlock += 'M V30 ' + natom + ' O ' + shift + ' 0 0.000000 0\n';
300
- }
301
- nbond++;
302
- if (i == monomers.length - 1) {
303
- const rightTerminal = (last > remFirst && last > remLast) ? last + natom - (numbers.natom - 2) - 3 :
304
- (last > remFirst || last > remLast) ? last + natom - (numbers.natom - 2) - 2 :
305
- last + natom - (numbers.natom - 2) - 1;
306
- bondBlock += 'M V30 ' + nbond + ' 1 ' + rightTerminal + ' ' + natom + '\n';
307
- } else {
308
- const rightTerminal = (last > remFirst && last > remLast) ? last + natom - (numbers.natom - 2) - 2 :
309
- (last > remFirst || last > remLast) ? last + natom - (numbers.natom - 2) - 1 :
310
- last + natom - (numbers.natom - 2);
311
-
312
- const next = monomers[i + 1]['indices'];
313
- const nextFirst = next['first'];
314
- const nextRemFirst = next['remFirst'];
315
- const nextRemLast = next['remLast'];
316
-
317
- const leftTerminal = (nextFirst > nextRemFirst && nextFirst > nextRemLast) ? nextFirst + natom - 2 :
318
- (nextFirst > nextRemFirst || nextFirst > nextRemLast) ? nextFirst + natom - 1 :
319
- nextFirst + natom;
320
-
321
- bondBlock += 'M V30 ' + nbond + ' 1 ' + rightTerminal + ' ' + leftTerminal + '\n';
322
- }
323
- }
324
-
325
- // const entries = 4;
326
- // const collNumber = Math.ceil(collection.length / entries);
327
- // collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length + ' -\n';
328
- // for (let i = 0; i < collNumber; i++) {
329
- // collectionBlock += 'M V30 ';
330
- // const entriesCurrent = i + 1 == collNumber ? collection.length - (collNumber - 1)*entries : entries;
331
- // for (let j = 0; j < entriesCurrent; j++) {
332
- // collectionBlock += (j + 1 == entriesCurrent) ?
333
- // (i == collNumber - 1 ? collection[entries*i + j] + ')\n' : collection[entries*i + j] + ' -\n') :
334
- // collection[entries*i + j] + ' ';
335
- // }
336
- // }
337
-
338
- //generate file
339
- macroMolBlock += 'M V30 COUNTS ' + natom + ' ' + nbond + ' 0 0 0\n';
340
- macroMolBlock += 'M V30 BEGIN ATOM\n';
341
- macroMolBlock += atomBlock;
342
- macroMolBlock += 'M V30 END ATOM\n';
343
- macroMolBlock += 'M V30 BEGIN BOND\n';
344
- macroMolBlock += bondBlock;
345
- macroMolBlock += 'M V30 END BOND\n';
346
- //macroMolBlock += 'M V30 BEGIN COLLECTION\n';
347
- //macroMolBlock += collectionBlock;
348
- //macroMolBlock += 'M V30 END COLLECTION\n';
349
- macroMolBlock += 'M V30 END CTAB\n';
350
- macroMolBlock += 'M END\n';
351
-
352
- return macroMolBlock;
353
- }
354
-
355
- function extractAtomsBondsNumbersV3000(molBlock: string): {natom: number, nbond: number} {
356
- molBlock = molBlock.replaceAll('\r', ''); //equalize old and new sdf standards
357
- let index = molBlock.indexOf('COUNTS') + 7; // V3000 index for atoms and bonds number
358
- let indexEnd = molBlock.indexOf(' ', index);
359
-
360
- const atomsNumber = parseInt(molBlock.substring(index, indexEnd));
361
- index = indexEnd + 1;
362
- indexEnd = molBlock.indexOf(' ', index);
363
- const bondsNumber = parseInt(molBlock.substring(index, indexEnd));
364
-
365
- return {natom: atomsNumber, nbond: bondsNumber};
366
- }
367
-