@datagrok/sequence-translator 1.0.14 → 1.0.16

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.
@@ -11,8 +11,8 @@ export function getNucleotidesMol(codes: string[]) {
11
11
  // }
12
12
 
13
13
  for (let i = 0; i < codes.length - 1; i++) {
14
- if(codes[i].includes('MODIFICATION')) {
15
- if(i == 0)
14
+ if (codes[i].includes('MODIFICATION')) {
15
+ if (i == 0)
16
16
  molBlocks.push(reflect(codes[i]));
17
17
  else
18
18
  molBlocks.push(codes[i]);
@@ -24,7 +24,7 @@ export function getNucleotidesMol(codes: string[]) {
24
24
  return linkV3000(molBlocks);
25
25
  }
26
26
 
27
- export function linkStrandsV3000(strands:{senseStrands: string[], antiStrands: string[]}, useChirality: boolean = true) {
27
+ export function linkStrandsV3000(strands: { senseStrands: string[], antiStrands: string[] }, useChirality: boolean = true) {
28
28
  let macroMolBlock = '\nDatagrok macromolecule handler\n\n';
29
29
  macroMolBlock += ' 0 0 0 0 0 0 999 V3000\n';
30
30
  macroMolBlock += 'M V30 BEGIN CTAB\n';
@@ -40,7 +40,7 @@ export function linkStrandsV3000(strands:{senseStrands: string[], antiStrands: s
40
40
  // molBlocks[1] = invertNucleotidesV3000(molBlocks[1]);
41
41
 
42
42
  if (strands.antiStrands.length > 0) {
43
- for(let i = 0; i < strands.antiStrands.length; i++) {
43
+ for (let i = 0; i < strands.antiStrands.length; i++) {
44
44
  strands.antiStrands[i] = invertNucleotidesV3000(strands.antiStrands[i]);
45
45
  }
46
46
  }
@@ -90,15 +90,15 @@ export function linkStrandsV3000(strands:{senseStrands: string[], antiStrands: s
90
90
 
91
91
  const totalShift = true ? 0 : xShift - coordinates.x[0];
92
92
  let coordinate = true ?
93
- Math.round(10000*coordinates.x[j])/10000 :
94
- Math.round(10000*(parseFloat(molBlocks[i].substring(index, indexEnd)) + totalShift))/10000;
93
+ Math.round(10000 * coordinates.x[j]) / 10000 :
94
+ Math.round(10000 * (parseFloat(molBlocks[i].substring(index, indexEnd)) + totalShift)) / 10000;
95
95
  molBlocks[i] = molBlocks[i].slice(0, index) + coordinate + molBlocks[i].slice(indexEnd);
96
96
 
97
97
  index = molBlocks[i].indexOf(' ', index) + 1;
98
98
  indexEnd = molBlocks[i].indexOf(' ', index);
99
99
  coordinate = true ?
100
- Math.round(10000*coordinates.y[j])/10000 :
101
- Math.round(10000*(parseFloat(molBlocks[i].substring(index, indexEnd))))/10000;
100
+ Math.round(10000 * coordinates.y[j]) / 10000 :
101
+ Math.round(10000 * (parseFloat(molBlocks[i].substring(index, indexEnd)))) / 10000;
102
102
  molBlocks[i] = molBlocks[i].slice(0, index) + coordinate + molBlocks[i].slice(indexEnd);
103
103
 
104
104
  index = molBlocks[i].indexOf('\n', index) + 1;
@@ -158,27 +158,27 @@ export function linkStrandsV3000(strands:{senseStrands: string[], antiStrands: s
158
158
  const collNumber = Math.ceil(collection.length / entries);
159
159
 
160
160
  //if (oclRender) {
161
- // collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length;
161
+ // collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length;
162
162
 
163
- // for (let j = 0; j < collection.length; j++)
164
- // collectionBlock += ' ' + collection[j];
163
+ // for (let j = 0; j < collection.length; j++)
164
+ // collectionBlock += ' ' + collection[j];
165
165
 
166
- // collectionBlock += ')\n';
166
+ // collectionBlock += ')\n';
167
167
  //} else {
168
- collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length + ' -\n';
169
- for (let i = 0; i < collNumber; i++) {
170
- collectionBlock += 'M V30 ';
171
- const entriesCurrent = i + 1 == collNumber ? collection.length - (collNumber - 1)*entries : entries;
172
- for (let j = 0; j < entriesCurrent; j++) {
173
- collectionBlock += (j + 1 == entriesCurrent) ?
174
- (i == collNumber - 1 ? collection[entries*i + j] + ')\n' : collection[entries*i + j] + ' -\n') :
175
- collection[entries*i + j] + ' ';
176
- }
168
+ collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length + ' -\n';
169
+ for (let i = 0; i < collNumber; i++) {
170
+ collectionBlock += 'M V30 ';
171
+ const entriesCurrent = i + 1 == collNumber ? collection.length - (collNumber - 1) * entries : entries;
172
+ for (let j = 0; j < entriesCurrent; j++) {
173
+ collectionBlock += (j + 1 == entriesCurrent) ?
174
+ (i == collNumber - 1 ? collection[entries * i + j] + ')\n' : collection[entries * i + j] + ' -\n') :
175
+ collection[entries * i + j] + ' ';
177
176
  }
177
+ }
178
178
  //}
179
179
 
180
180
  //generate file
181
- true? natom : natom++;
181
+ true ? natom : natom++;
182
182
  macroMolBlock += 'M V30 COUNTS ' + natom + ' ' + nbond + ' 0 0 0\n';
183
183
  macroMolBlock += 'M V30 BEGIN ATOM\n';
184
184
  macroMolBlock += atomBlock;
@@ -186,7 +186,7 @@ export function linkStrandsV3000(strands:{senseStrands: string[], antiStrands: s
186
186
  macroMolBlock += 'M V30 BEGIN BOND\n';
187
187
  macroMolBlock += bondBlock;
188
188
  macroMolBlock += 'M V30 END BOND\n';
189
- if(useChirality){
189
+ if (useChirality) {
190
190
  macroMolBlock += 'M V30 BEGIN COLLECTION\n';
191
191
  macroMolBlock += collectionBlock;
192
192
  macroMolBlock += 'M V30 END COLLECTION\n';
@@ -218,7 +218,7 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
218
218
  const coordinates = extractAtomDataV3000(molBlocks[i]);
219
219
  specLength = coordinates.atomIndex.length;
220
220
  }
221
-
221
+
222
222
 
223
223
  molBlocks[i] = molBlocks[i].replaceAll('(-\nM V30 ', '(')
224
224
  .replaceAll('-\nM V30 ', '').replaceAll(' )', ')');
@@ -236,11 +236,11 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
236
236
  index = molBlocks[i].indexOf('V30', index) + 4;
237
237
  indexEnd = molBlocks[i].indexOf(' ', index);
238
238
  let atomNumber = 0;
239
- if(isBoundary) {
239
+ if (isBoundary) {
240
240
  atomNumber = parseInt(molBlocks[i].substring(index, indexEnd))
241
- if(atomNumber == 1)
241
+ if (atomNumber == 1)
242
242
  atomNumber = specLength;
243
- else if(atomNumber == specLength)
243
+ else if (atomNumber == specLength)
244
244
  atomNumber = 1;
245
245
  atomNumber += natom;
246
246
  } else {
@@ -254,14 +254,14 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
254
254
  indexEnd = molBlocks[i].indexOf(' ', index);
255
255
 
256
256
  const totalShift = xShift - coordinates.x[0];
257
- let coordinate =
258
- Math.round(10000*(parseFloat(molBlocks[i].substring(index, indexEnd)) + totalShift))/10000;
257
+ let coordinate =
258
+ Math.round(10000 * (parseFloat(molBlocks[i].substring(index, indexEnd)) + totalShift)) / 10000;
259
259
  molBlocks[i] = molBlocks[i].slice(0, index) + coordinate + molBlocks[i].slice(indexEnd);
260
260
 
261
261
  index = molBlocks[i].indexOf(' ', index) + 1;
262
262
  indexEnd = molBlocks[i].indexOf(' ', index);
263
- coordinate =
264
- Math.round(10000*(parseFloat(molBlocks[i].substring(index, indexEnd))))/10000;
263
+ coordinate =
264
+ Math.round(10000 * (parseFloat(molBlocks[i].substring(index, indexEnd)))) / 10000;
265
265
  molBlocks[i] = molBlocks[i].slice(0, index) + coordinate + molBlocks[i].slice(indexEnd);
266
266
 
267
267
  index = molBlocks[i].indexOf('\n', index) + 1;
@@ -292,11 +292,11 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
292
292
  index = molBlocks[i].indexOf(' ', index) + 1;
293
293
  indexEnd = molBlocks[i].indexOf(' ', index);
294
294
  let atomNumber = 0;
295
- if(isBoundary) {
295
+ if (isBoundary) {
296
296
  atomNumber = parseInt(molBlocks[i].substring(index, indexEnd))
297
- if(atomNumber == 1)
297
+ if (atomNumber == 1)
298
298
  atomNumber = specLength;
299
- else if(atomNumber == specLength)
299
+ else if (atomNumber == specLength)
300
300
  atomNumber = 1;
301
301
  atomNumber += natom;
302
302
  } else {
@@ -307,11 +307,11 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
307
307
  index = molBlocks[i].indexOf(' ', index) + 1;
308
308
  indexEnd = Math.min(molBlocks[i].indexOf('\n', index), molBlocks[i].indexOf(' ', index));
309
309
  atomNumber = 0;
310
- if(isBoundary) {
310
+ if (isBoundary) {
311
311
  atomNumber = parseInt(molBlocks[i].substring(index, indexEnd))
312
- if(atomNumber == 1)
312
+ if (atomNumber == 1)
313
313
  atomNumber = specLength;
314
- else if(atomNumber == specLength)
314
+ else if (atomNumber == specLength)
315
315
  atomNumber = 1;
316
316
  atomNumber += natom;
317
317
  } else {
@@ -340,7 +340,7 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
340
340
 
341
341
  natom += numbers.natom - 1;
342
342
  nbond += numbers.nbond;
343
- if(isBoundary)
343
+ if (isBoundary)
344
344
  xShift += Math.max(...coordinates.x);
345
345
  else
346
346
  xShift += coordinates.x[numbers.natom - 1] - coordinates.x[0];
@@ -350,23 +350,23 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
350
350
  const collNumber = Math.ceil(collection.length / entries);
351
351
 
352
352
  //if (oclRender) {
353
- // collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length;
353
+ // collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length;
354
354
 
355
- // for (let j = 0; j < collection.length; j++)
356
- // collectionBlock += ' ' + collection[j];
355
+ // for (let j = 0; j < collection.length; j++)
356
+ // collectionBlock += ' ' + collection[j];
357
357
 
358
- // collectionBlock += ')\n';
358
+ // collectionBlock += ')\n';
359
359
  //} else {
360
- collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length + ' -\n';
361
- for (let i = 0; i < collNumber; i++) {
362
- collectionBlock += 'M V30 ';
363
- const entriesCurrent = i + 1 == collNumber ? collection.length - (collNumber - 1)*entries : entries;
364
- for (let j = 0; j < entriesCurrent; j++) {
365
- collectionBlock += (j + 1 == entriesCurrent) ?
366
- (i == collNumber - 1 ? collection[entries*i + j] + ')\n' : collection[entries*i + j] + ' -\n') :
367
- collection[entries*i + j] + ' ';
368
- }
360
+ collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length + ' -\n';
361
+ for (let i = 0; i < collNumber; i++) {
362
+ collectionBlock += 'M V30 ';
363
+ const entriesCurrent = i + 1 == collNumber ? collection.length - (collNumber - 1) * entries : entries;
364
+ for (let j = 0; j < entriesCurrent; j++) {
365
+ collectionBlock += (j + 1 == entriesCurrent) ?
366
+ (i == collNumber - 1 ? collection[entries * i + j] + ')\n' : collection[entries * i + j] + ' -\n') :
367
+ collection[entries * i + j] + ' ';
369
368
  }
369
+ }
370
370
  //}
371
371
 
372
372
  //generate file
@@ -378,7 +378,7 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
378
378
  macroMolBlock += 'M V30 BEGIN BOND\n';
379
379
  macroMolBlock += bondBlock;
380
380
  macroMolBlock += 'M V30 END BOND\n';
381
- if(useChirality){
381
+ if (useChirality) {
382
382
  macroMolBlock += 'M V30 BEGIN COLLECTION\n';
383
383
  macroMolBlock += collectionBlock;
384
384
  macroMolBlock += 'M V30 END COLLECTION\n';
@@ -404,8 +404,8 @@ function rotateNucleotidesV3000(molecule: string) {
404
404
  if (natom > 8)
405
405
  fix5Prime(coordinates, indexFivePrime, indexThreePrime);
406
406
 
407
- const xCenter = (coordinates.x[indexThreePrime] + coordinates.x[indexFivePrime])/2;
408
- const yCenter = (coordinates.y[indexThreePrime] + coordinates.y[indexFivePrime])/2;
407
+ const xCenter = (coordinates.x[indexThreePrime] + coordinates.x[indexFivePrime]) / 2;
408
+ const yCenter = (coordinates.y[indexThreePrime] + coordinates.y[indexFivePrime]) / 2;
409
409
 
410
410
  //place to center
411
411
  for (let i = 0; i < natom; i++) {
@@ -415,16 +415,14 @@ function rotateNucleotidesV3000(molecule: string) {
415
415
 
416
416
  let angle = 0;
417
417
  if (coordinates.x[indexFivePrime] == 0)
418
- angle = coordinates.y[indexFivePrime] > coordinates.y[indexThreePrime] ? Math.PI/2 : 3*Math.PI/2;
418
+ angle = coordinates.y[indexFivePrime] > coordinates.y[indexThreePrime] ? Math.PI / 2 : 3 * Math.PI / 2;
419
419
  else if (coordinates.y[indexFivePrime] == 0)
420
420
  angle = coordinates.x[indexFivePrime] > coordinates.x[indexThreePrime] ? Math.PI : 0;
421
421
  else {
422
- const derivative = coordinates.y[indexFivePrime]/coordinates.x[indexFivePrime];
423
- angle = derivative > 0 ? Math.PI - Math.atan(derivative) :
424
- (coordinates.x[indexFivePrime] < 0 ?
425
- Math.atan(derivative) :
426
- - Math.PI - Math.atan(derivative)
427
- );
422
+ const derivative = coordinates.y[indexFivePrime] / coordinates.x[indexFivePrime];
423
+ angle = derivative > 0
424
+ ? (coordinates.x[indexFivePrime] > 0 ? Math.PI - Math.atan(derivative) : Math.PI * 2 - Math.atan(derivative))
425
+ : (coordinates.x[indexFivePrime] > 0 ? -Math.PI - Math.atan(derivative) : Math.atan(derivative));
428
426
  }
429
427
 
430
428
  const cos = Math.cos(angle);
@@ -432,8 +430,8 @@ function rotateNucleotidesV3000(molecule: string) {
432
430
 
433
431
  for (let i = 0; i < natom; i++) {
434
432
  const xAdd = coordinates.x[i];
435
- coordinates.x[i] = xAdd*cos - coordinates.y[i]*sin;
436
- coordinates.y[i] = xAdd*sin + coordinates.y[i]*cos;
433
+ coordinates.x[i] = xAdd * cos - coordinates.y[i] * sin;
434
+ coordinates.y[i] = xAdd * sin + coordinates.y[i] * cos;
437
435
  }
438
436
 
439
437
  //place to right
@@ -471,8 +469,8 @@ function reflect(molecule: string) {
471
469
  const indexFivePrime = coordinates.atomIndex.indexOf(1);
472
470
  const indexThreePrime = coordinates.atomIndex.indexOf(natom);
473
471
 
474
- const xCenter = (coordinates.x[indexThreePrime] + coordinates.x[indexFivePrime])/2;
475
- const yCenter = (coordinates.y[indexThreePrime] + coordinates.y[indexFivePrime])/2;
472
+ const xCenter = (coordinates.x[indexThreePrime] + coordinates.x[indexFivePrime]) / 2;
473
+ const yCenter = (coordinates.y[indexThreePrime] + coordinates.y[indexFivePrime]) / 2;
476
474
 
477
475
  //place to center
478
476
  for (let i = 0; i < natom; i++) {
@@ -517,8 +515,8 @@ function invertNucleotidesV3000(molecule: string) {
517
515
  const coordinates = extractAtomDataV3000(molBlock);
518
516
  const natom = coordinates.atomIndex.length;
519
517
 
520
- const xCenter = (Math.max(...coordinates.x) + Math.min(...coordinates.x))/2;
521
- const yCenter = (Math.max(...coordinates.y) + Math.min(...coordinates.y))/2;
518
+ const xCenter = (Math.max(...coordinates.x) + Math.min(...coordinates.x)) / 2;
519
+ const yCenter = (Math.max(...coordinates.y) + Math.min(...coordinates.y)) / 2;
522
520
 
523
521
  //place to center
524
522
  for (let i = 0; i < natom; i++) {
@@ -533,8 +531,8 @@ function invertNucleotidesV3000(molecule: string) {
533
531
 
534
532
  for (let i = 0; i < natom; i++) {
535
533
  const xAdd = coordinates.x[i];
536
- coordinates.x[i] = xAdd*cos - coordinates.y[i]*sin;
537
- coordinates.y[i] = xAdd*sin + coordinates.y[i]*cos;
534
+ coordinates.x[i] = xAdd * cos - coordinates.y[i] * sin;
535
+ coordinates.y[i] = xAdd * sin + coordinates.y[i] * cos;
538
536
  }
539
537
 
540
538
  //place back
@@ -565,7 +563,7 @@ function invertNucleotidesV3000(molecule: string) {
565
563
  return molBlock;
566
564
  }
567
565
 
568
- function fix5Prime(coordinates: {atomIndex: number[], atomType: string[], x: number[], y: number[]},
566
+ function fix5Prime(coordinates: { atomIndex: number[], atomType: string[], x: number[], y: number[] },
569
567
  indexFivePrime: number, indexThreePrime: number) {
570
568
  const indexFivePrimeNeighbour = indexFivePrime + 1;
571
569
  const xShift = coordinates.x[indexFivePrimeNeighbour];
@@ -575,21 +573,21 @@ function fix5Prime(coordinates: {atomIndex: number[], atomType: string[], x: num
575
573
  const base5PrimeX = coordinates.x[indexFivePrime] - xShift;
576
574
  const base5PrimeY = coordinates.y[indexFivePrime] - yShift;
577
575
 
578
- const rotated5PrimeX = base5PrimeX*Math.cos(Math.PI*2/3) - base5PrimeY*Math.sin(Math.PI*2/3);
579
- const rotated5PrimeY = base5PrimeX*Math.sin(Math.PI*2/3) + base5PrimeY*Math.cos(Math.PI*2/3);
576
+ const rotated5PrimeX = base5PrimeX * Math.cos(Math.PI * 2 / 3) - base5PrimeY * Math.sin(Math.PI * 2 / 3);
577
+ const rotated5PrimeY = base5PrimeX * Math.sin(Math.PI * 2 / 3) + base5PrimeY * Math.cos(Math.PI * 2 / 3);
580
578
 
581
579
  const dx = base5PrimeX - base3PrimeX;
582
580
  const dy = base5PrimeY - base3PrimeY;
583
581
  const dxRotated = rotated5PrimeX - base3PrimeX;
584
582
  const dyRotated = rotated5PrimeY - base3PrimeY;
585
583
 
586
- if (Math.sqrt(dyRotated*dyRotated + dxRotated*dxRotated) >= Math.sqrt(dy*dy + dx*dx)) {
584
+ if (Math.sqrt(dyRotated * dyRotated + dxRotated * dxRotated) >= Math.sqrt(dy * dy + dx * dx)) {
587
585
  coordinates.x[indexFivePrime] = rotated5PrimeX + xShift;
588
586
  coordinates.y[indexFivePrime] = rotated5PrimeY + yShift;
589
587
  }
590
588
  }
591
589
 
592
- function extractAtomsBondsNumbersV3000(molBlock: string): {natom: number, nbond: number} {
590
+ function extractAtomsBondsNumbersV3000(molBlock: string): { natom: number, nbond: number } {
593
591
  molBlock = molBlock.replaceAll('\r', ''); //equalize old and new sdf standards
594
592
  let index = molBlock.indexOf('COUNTS') + 7; // V3000 index for atoms and bonds number
595
593
  let indexEnd = molBlock.indexOf(' ', index);
@@ -602,7 +600,7 @@ function extractAtomsBondsNumbersV3000(molBlock: string): {natom: number, nbond:
602
600
  return {natom: atomsNumber, nbond: bondsNumber};
603
601
  }
604
602
 
605
- function extractAtomDataV3000(molBlock: string) {
603
+ export function extractAtomDataV3000(molBlock: string) {
606
604
  const numbers = extractAtomsBondsNumbersV3000(molBlock);
607
605
  let index = molBlock.indexOf('M V30 BEGIN ATOM'); // V3000 index for atoms coordinates
608
606
  index = molBlock.indexOf('\n', index);
@@ -0,0 +1,27 @@
1
+ export const CELL_STRUCTURE = {
2
+ DUPLEX: {
3
+ BEFORE_SS: 'SS ',
4
+ BEFORE_AS: '\r\nAS ',
5
+ },
6
+ TRIPLEX_OR_DIMER: {
7
+ BEFORE_SS: 'SS ',
8
+ BEFORE_AS1: '\r\nAS1 ',
9
+ BEFORE_AS2: '\r\nAS2 ',
10
+ },
11
+ };
12
+
13
+ export function parseStrandsFromDuplexCell(s: string): { SS: string, AS: string } {
14
+ const arr = s
15
+ .slice(CELL_STRUCTURE.DUPLEX.BEFORE_SS.length)
16
+ .split(CELL_STRUCTURE.DUPLEX.BEFORE_AS);
17
+ return {SS: arr[0], AS: arr[1]};
18
+ }
19
+
20
+ export function parseStrandsFromTriplexOrDimerCell(s: string): { SS: string, AS1: string, AS2: string } {
21
+ const arr1 = s
22
+ .slice(CELL_STRUCTURE.TRIPLEX_OR_DIMER.BEFORE_SS.length)
23
+ .split(CELL_STRUCTURE.TRIPLEX_OR_DIMER.BEFORE_AS1);
24
+ const arr2 = arr1[1]
25
+ .split(CELL_STRUCTURE.TRIPLEX_OR_DIMER.BEFORE_AS2);
26
+ return {SS: arr1[0], AS1: arr2[0], AS2: arr2[1]};
27
+ }
@@ -0,0 +1,118 @@
1
+ import * as DG from 'datagrok-api/dg';
2
+ import {COL_NAMES, GENERATED_COL_NAMES, SEQUENCE_TYPES} from '../autostart/constants';
3
+ import * as grok from 'datagrok-api/grok';
4
+ import {removeEmptyRows} from '../helpers';
5
+ import {parseStrandsFromDuplexCell, parseStrandsFromTriplexOrDimerCell} from './parse';
6
+ import {isValidSequence} from '../structures-works/sequence-codes-tools';
7
+ import {batchMolWeight, molecularWeight, saltMass, saltMolWeigth} from '../autostart/calculations';
8
+ import {weightsObj} from '../structures-works/map';
9
+
10
+ export class SdfColumnsExistsError extends Error {
11
+ constructor(message: string) {
12
+ super();
13
+ }
14
+ }
15
+
16
+ export function sdfAddColumns(
17
+ df: DG.DataFrame, saltNamesList: string[], saltsMolWeightList: number[], onError: (rowI: number, err: any) => void
18
+ ): DG.DataFrame {
19
+ const sequenceCol = df.getCol(COL_NAMES.SEQUENCE);
20
+ const saltCol = df.getCol(COL_NAMES.SALT);
21
+ const equivalentsCol = df.getCol(COL_NAMES.EQUIVALENTS);
22
+ const typeCol = df.getCol(COL_NAMES.TYPE);
23
+ const chemistryNameCol = df.getCol(COL_NAMES.CHEMISTRY_NAME);
24
+
25
+ if (GENERATED_COL_NAMES.some((colName) => df.columns.contains(colName)))
26
+ throw new SdfColumnsExistsError('Columns already exist');
27
+
28
+ df = removeEmptyRows(df, sequenceCol);
29
+
30
+ df.columns.addNewString(COL_NAMES.COMPOUND_NAME).init((i: number) => {
31
+ let res: string = '';
32
+ try {
33
+ res = ([SEQUENCE_TYPES.DUPLEX, SEQUENCE_TYPES.DIMER, SEQUENCE_TYPES.TRIPLEX].includes(typeCol.get(i))) ?
34
+ chemistryNameCol.get(i) :
35
+ sequenceCol.get(i);
36
+ } catch (err) {
37
+ onError(i, err);
38
+ }
39
+ return res;
40
+ });
41
+
42
+ df.columns.addNewString(COL_NAMES.COMPOUND_COMMENTS).init((i: number) => {
43
+ let res: string = '';
44
+ try {
45
+ if ([SEQUENCE_TYPES.SENSE_STRAND, SEQUENCE_TYPES.ANTISENSE_STRAND].includes(typeCol.get(i))) {
46
+ res = sequenceCol.get(i);
47
+ } else if (typeCol.get(i) == SEQUENCE_TYPES.DUPLEX) {
48
+ const obj = parseStrandsFromDuplexCell(sequenceCol.get(i));
49
+ res = `${chemistryNameCol.get(i)}; duplex of SS: ${obj.SS} and AS: ${obj.AS}`;
50
+ } else if ([SEQUENCE_TYPES.DIMER, SEQUENCE_TYPES.TRIPLEX].includes(typeCol.get(i))) {
51
+ const obj = parseStrandsFromTriplexOrDimerCell(sequenceCol.get(i));
52
+ res = `${chemistryNameCol.get(i)}; duplex of SS: ${obj.SS} and AS1: ${obj.AS1} and AS2: ${obj.AS2}`;
53
+ }
54
+ } catch (err) {
55
+ onError(i, err);
56
+ }
57
+ return res;
58
+ });
59
+
60
+ df.columns.addNewFloat(COL_NAMES.COMPOUND_MOL_WEIGHT).init((i: number) => {
61
+ let res: number = Number.NaN;
62
+ try {
63
+ if ([SEQUENCE_TYPES.SENSE_STRAND, SEQUENCE_TYPES.ANTISENSE_STRAND].includes(typeCol.get(i))) {
64
+ res = (isValidSequence(sequenceCol.get(i), null).indexOfFirstNotValidChar == -1) ?
65
+ molecularWeight(sequenceCol.get(i), weightsObj) :
66
+ DG.FLOAT_NULL;
67
+ } else if (typeCol.get(i) == SEQUENCE_TYPES.DUPLEX) {
68
+ const obj = parseStrandsFromDuplexCell(sequenceCol.get(i));
69
+ res = (Object.values(obj).every((seq) => isValidSequence(seq, null).indexOfFirstNotValidChar == -1)) ?
70
+ molecularWeight(obj.SS, weightsObj) + molecularWeight(obj.AS, weightsObj) :
71
+ DG.FLOAT_NULL;
72
+ } else if ([SEQUENCE_TYPES.DIMER, SEQUENCE_TYPES.TRIPLEX].includes(typeCol.get(i))) {
73
+ const obj = parseStrandsFromTriplexOrDimerCell(sequenceCol.get(i));
74
+ res = (Object.values(obj).every((seq) => isValidSequence(seq, null).indexOfFirstNotValidChar == -1)) ?
75
+ molecularWeight(obj.SS, weightsObj) + molecularWeight(obj.AS1, weightsObj) +
76
+ molecularWeight(obj.AS2, weightsObj) :
77
+ DG.FLOAT_NULL;
78
+ }
79
+ } catch (err) {
80
+ onError(i, err);
81
+ }
82
+ return res;
83
+ });
84
+
85
+ df.columns.addNewFloat(COL_NAMES.SALT_MASS).init((i: number) => {
86
+ let res: number = Number.NaN;
87
+ try {
88
+ res = saltMass(saltNamesList, saltsMolWeightList, equivalentsCol, i, saltCol);
89
+ } catch (err) {
90
+ onError(i, err);
91
+ }
92
+ return res;
93
+ });
94
+
95
+ df.columns.addNewFloat(COL_NAMES.SALT_MOL_WEIGHT).init((i: number) => {
96
+ let res: number = Number.NaN;
97
+ try {
98
+ res = saltMolWeigth(saltNamesList, saltCol, saltsMolWeightList, i);
99
+ } catch (err) {
100
+ onError(i, err);
101
+ }
102
+ return res;
103
+ });
104
+
105
+ const compoundMolWeightCol = df.getCol(COL_NAMES.COMPOUND_MOL_WEIGHT);
106
+ const saltMassCol = df.getCol(COL_NAMES.SALT_MASS);
107
+ df.columns.addNewFloat(COL_NAMES.BATCH_MOL_WEIGHT).init((i: number) => {
108
+ let res: number = Number.NaN;
109
+ try {
110
+ res = batchMolWeight(compoundMolWeightCol, saltMassCol, i);
111
+ } catch (err) {
112
+ onError(i, err);
113
+ }
114
+ return res;
115
+ });
116
+
117
+ return df;
118
+ }
@@ -0,0 +1,56 @@
1
+ import * as DG from 'datagrok-api/dg';
2
+ import {COL_NAMES, GENERATED_COL_NAMES, SEQUENCE_TYPES} from '../autostart/constants';
3
+ import {differenceOfTwoArrays, download} from '../helpers';
4
+ import * as grok from 'datagrok-api/grok';
5
+ import {SYNTHESIZERS} from '../structures-works/map';
6
+ import {sequenceToMolV3000} from '../structures-works/from-monomers';
7
+ import {parseStrandsFromDuplexCell, parseStrandsFromTriplexOrDimerCell} from './parse';
8
+ import {linkStrandsV3000} from '../structures-works/mol-transformations';
9
+
10
+ export async function sdfSaveTable(table: DG.DataFrame, onError: (rowI: number, err: any) => void) {
11
+ if (GENERATED_COL_NAMES.some((colName) => !table.columns.contains(colName))) {
12
+ const absentColNames = differenceOfTwoArrays(GENERATED_COL_NAMES, table.columns.names()).join(`', '`);
13
+ grok.shell.warning(`File saved without columns '${absentColNames}'`);
14
+ }
15
+
16
+ const sequenceCol = table.getCol(COL_NAMES.SEQUENCE);
17
+ const typeCol = table.getCol(COL_NAMES.TYPE);
18
+
19
+ let resultStr = '';
20
+ const rowCount = table.rowCount;
21
+ for (let i = 0; i < rowCount; i++) {
22
+ try {
23
+ let rowStr = '';
24
+ const format = SYNTHESIZERS.GCRS; //getFormat(sequenceCol.get(i))!;
25
+ if (typeCol.get(i) == SEQUENCE_TYPES.SENSE_STRAND) {
26
+ rowStr += `${sequenceToMolV3000(sequenceCol.get(i), false, true, format)}\n> <Sequence>\nSense Strand\n\n`;
27
+ } else if (typeCol.get(i) == SEQUENCE_TYPES.ANTISENSE_STRAND) {
28
+ rowStr += `${sequenceToMolV3000(sequenceCol.get(i), true, true, format)}\n> <Sequence>\nAnti Sense\n\n`;
29
+ } else if (typeCol.get(i) == SEQUENCE_TYPES.DUPLEX) {
30
+ const obj = parseStrandsFromDuplexCell(sequenceCol.get(i));
31
+ const as = `${sequenceToMolV3000(obj.AS, true, true, format)}\n> <Sequence>\nAnti Sense\n\n`;
32
+ const ss = `${sequenceToMolV3000(obj.SS, false, true, format)}\n> <Sequence>\nSense Strand\n\n`;
33
+ rowStr += `${linkStrandsV3000({senseStrands: [ss], antiStrands: [as]}, true)}\n\n`;
34
+ } else if ([SEQUENCE_TYPES.TRIPLEX, SEQUENCE_TYPES.DIMER].includes(typeCol.get(i))) {
35
+ const obj = parseStrandsFromTriplexOrDimerCell(sequenceCol.get(i));
36
+ const as1 = `${sequenceToMolV3000(obj.AS1, true, true, format)}\n> <Sequence>\nAnti Sense\n\n`;
37
+ const as2 = `${sequenceToMolV3000(obj.AS2, true, true, format)}\n> <Sequence>\nAnti Sense\n\n`;
38
+ const ss = `${sequenceToMolV3000(obj.SS, false, true, format)}\n> <Sequence>\nSense Strand\n\n`;
39
+ rowStr += `${linkStrandsV3000({senseStrands: [ss], antiStrands: [as1, as2]}, true)}\n\n`;
40
+ }
41
+
42
+ for (const col of table.columns) {
43
+ if (col.name != COL_NAMES.SEQUENCE)
44
+ rowStr += `> <${col.name}>\n${col.get(i)}\n\n`;
45
+ }
46
+
47
+ rowStr += '$$$$\n';
48
+
49
+ resultStr += rowStr;
50
+ } catch (err: any) {
51
+ onError(i, err);
52
+ }
53
+ }
54
+
55
+ download(`${table.name}.sdf`, encodeURIComponent(resultStr));
56
+ }
@@ -1,4 +1,4 @@
1
- <html><head><meta charset="utf-8"/><title>SequenceTranslator Test Report. Datagrok version datagrok/datagrok:latest SHA=e8c06047b7e7. Commit eb4db608.</title><style type="text/css">html,
1
+ <html><head><meta charset="utf-8"/><title>SequenceTranslator Test Report. Datagrok version datagrok/datagrok:latest SHA=6288c2fbe346. Commit cce4ac1d.</title><style type="text/css">html,
2
2
  body {
3
3
  font-family: Arial, Helvetica, sans-serif;
4
4
  font-size: 1rem;
@@ -229,7 +229,7 @@ header {
229
229
  font-size: 1rem;
230
230
  padding: 0 0.5rem;
231
231
  }
232
- </style></head><body><div id="jesthtml-content"><header><h1 id="title">SequenceTranslator Test Report. Datagrok version datagrok/datagrok:latest SHA=e8c06047b7e7. Commit eb4db608.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-11-22 12:28:58</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts</div><div class="suite-time warn">15.587s</div></div><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">passed</div><div class="test-duration">3.952s</div></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/test-node.ts:62:11)
232
+ </style></head><body><div id="jesthtml-content"><header><h1 id="title">SequenceTranslator Test Report. Datagrok version datagrok/datagrok:latest SHA=6288c2fbe346. Commit cce4ac1d.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-12-12 14:55:37</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts</div><div class="suite-time warn">21.067s</div></div><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">passed</div><div class="test-duration">6.276s</div></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/test-node.ts:62:11)
233
233
  at Generator.next (&lt;anonymous&gt;)
234
234
  at fulfilled (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/test-node.ts:28:58)
235
235
  at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Using web root: http://localhost:8080</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:40:11
@@ -242,17 +242,17 @@ header {
242
242
  at new Promise (&lt;anonymous&gt;)</pre><pre class="suite-consolelog-item-message">Testing SequenceTranslator package</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:72:11
243
243
  at Generator.next (&lt;anonymous&gt;)
244
244
  at fulfilled (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:28:58)
245
- at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Test result : Success : 1 : SequenceTranslator.sequence-translator.usCfCfUfGfAf : OK
245
+ at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Test result : Success : 2 : SequenceTranslator.sequence-translator.usCfCfUfGfAf : OK
246
246
  Test result : Success : 0 : SequenceTranslator.sequence-translator.usAfsusgsgsg : OK
247
- Test result : Success : 1 : SequenceTranslator.sequence-translator.UfUfUfsCfsuacg : OK
247
+ Test result : Success : 0 : SequenceTranslator.sequence-translator.UfUfUfsCfsuacg : OK
248
248
  Test result : Success : 0 : SequenceTranslator.sequence-translator.susususauasu : OK
249
249
  Test result : Success : 0 : SequenceTranslator.sequence-translator.CfGfCfsGfsCf : OK
250
250
  Test result : Success : 1 : SequenceTranslator.sequence-translator.acacacsacsac : OK
251
251
  Test result : Success : 0 : SequenceTranslator.sequence-translator.cccgggusug : OK
252
252
  Test result : Success : 0 : SequenceTranslator.sequence-translator.UfAfCfGfGfCfAfUf : OK
253
253
  Test result : Success : 1 : SequenceTranslator.sequence-translator.(invabasic)cuCfuUfsc : OK
254
- Test result : Success : 0 : SequenceTranslator.sequence-translator.(invabasic)usAfsucuCfuUfAfgcugUfgCfacususu : OK
255
- Test result : Success : 0 : SequenceTranslator.sequence-translator.(invabasic)asacgGfuGfCfAfacucuauuca : OK
254
+ Test result : Success : 1 : SequenceTranslator.sequence-translator.(invabasic)usAfsucuCfuUfAfgcugUfgCfacususu : OK
255
+ Test result : Success : 1 : SequenceTranslator.sequence-translator.(invabasic)asacgGfuGfCfAfacucuauuca : OK
256
256
  </pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:74:11
257
257
  at Generator.next (&lt;anonymous&gt;)
258
258
  at fulfilled (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:28:58)