@datagrok/sequence-translator 1.0.15 → 1.0.17
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 +16 -3
- package/detectors.js +0 -28
- package/dist/package-test.js +4372 -3957
- package/dist/package.js +3875 -3460
- package/package.json +4 -2
- package/setup-unlink-clean.sh +21 -0
- package/src/apps/oligo-sd-file-app.ts +58 -0
- package/src/autostart/calculations.ts +11 -8
- package/src/autostart/constants.ts +0 -12
- package/src/autostart/registration.ts +194 -157
- package/src/{axolabs/define-pattern.ts → axolabs-tab/axolabs-tab.ts} +2 -2
- package/src/axolabs-tab/define-pattern.ts +874 -0
- package/src/{axolabs → axolabs-tab}/draw-svg.ts +1 -1
- package/src/{axolabs → axolabs-tab}/helpers.ts +2 -2
- package/src/{autostart → hardcode-to-be-eliminated}/ICDs.ts +0 -0
- package/src/{autostart → hardcode-to-be-eliminated}/IDPs.ts +0 -0
- package/src/{structures-works → hardcode-to-be-eliminated}/const.ts +0 -0
- package/src/{axolabs → hardcode-to-be-eliminated}/constants.ts +0 -0
- package/src/{structures-works → hardcode-to-be-eliminated}/converters.ts +1 -1
- package/src/{structures-works → hardcode-to-be-eliminated}/map.ts +2 -2
- package/src/{autostart → hardcode-to-be-eliminated}/salts.ts +0 -0
- package/src/{autostart → hardcode-to-be-eliminated}/sources.ts +0 -0
- package/src/{autostart → hardcode-to-be-eliminated}/users.ts +0 -0
- package/src/{main/main-view.ts → main-tab/main-tab.ts} +28 -80
- package/src/package.ts +77 -13
- package/src/sdf-tab/sdf-tab.ts +163 -0
- package/src/{structures-works → sdf-tab}/sequence-codes-tools.ts +8 -5
- package/src/tests/smiles-tests.ts +2 -2
- package/src/utils/const.ts +0 -0
- package/src/{helpers.ts → utils/helpers.ts} +3 -3
- package/src/utils/parse.ts +27 -0
- package/src/utils/sdf-add-columns.ts +118 -0
- package/src/utils/sdf-save-table.ts +56 -0
- package/src/utils/structures-works/draw-molecule.ts +84 -0
- package/src/{structures-works → utils/structures-works}/from-monomers.ts +15 -16
- package/src/{structures-works → utils/structures-works}/mol-transformations.ts +34 -52
- package/{test-SequenceTranslator-91c83d8913ff-f94596bc.html → test-SequenceTranslator-6288c2fbe346-695b7b55.html} +10 -10
- package/src/structures-works/save-sense-antisense.ts +0 -91
|
@@ -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 '../utils/helpers';
|
|
5
|
+
import {parseStrandsFromDuplexCell, parseStrandsFromTriplexOrDimerCell} from './parse';
|
|
6
|
+
import {isValidSequence} from '../sdf-tab/sequence-codes-tools';
|
|
7
|
+
import {batchMolWeight, molecularWeight, saltMass, saltMolWeigth} from '../autostart/calculations';
|
|
8
|
+
import {weightsObj} from '../hardcode-to-be-eliminated/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 '../utils/helpers';
|
|
4
|
+
import * as grok from 'datagrok-api/grok';
|
|
5
|
+
import {SYNTHESIZERS} from '../hardcode-to-be-eliminated/map';
|
|
6
|
+
import {sequenceToMolV3000} from '../utils/structures-works/from-monomers';
|
|
7
|
+
import {parseStrandsFromDuplexCell, parseStrandsFromTriplexOrDimerCell} from './parse';
|
|
8
|
+
import {linkStrandsV3000} from '../utils/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
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/* Do not change these import lines to match external modules in webpack configuration */
|
|
2
|
+
import * as grok from 'datagrok-api/grok';
|
|
3
|
+
import * as ui from 'datagrok-api/ui';
|
|
4
|
+
import * as DG from 'datagrok-api/dg';
|
|
5
|
+
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
6
|
+
|
|
7
|
+
import $ from 'cash-dom';
|
|
8
|
+
|
|
9
|
+
import {extractAtomDataV3000} from './mol-transformations';
|
|
10
|
+
|
|
11
|
+
/** Draw molecule on the canvas and append it to the specified div, with the
|
|
12
|
+
* option of zoom-in */
|
|
13
|
+
export async function drawMolecule(
|
|
14
|
+
moleculeImgDiv: HTMLDivElement,
|
|
15
|
+
canvasWidth: number, canvasHeight: number,
|
|
16
|
+
molfile: string
|
|
17
|
+
): Promise<void> {
|
|
18
|
+
// clear the div's content if any
|
|
19
|
+
async function drawMolfileOnCanvas(canvas: HTMLCanvasElement): Promise<void> {
|
|
20
|
+
await grok.functions.call('Chem:canvasMol', {
|
|
21
|
+
x: 0, y: 0, w: canvas.width, h: canvas.height, canvas: canvas,
|
|
22
|
+
molString: molfile, scaffoldMolString: '',
|
|
23
|
+
options: {normalizeDepiction: false, straightenDepiction: false}
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
async function drawZoomedInMolecule(): Promise<void> {
|
|
28
|
+
try {
|
|
29
|
+
const dialogDivStyle = {
|
|
30
|
+
overflowX: 'scroll',
|
|
31
|
+
};
|
|
32
|
+
const dialogDiv = ui.div([], {style: dialogDivStyle});
|
|
33
|
+
|
|
34
|
+
// dialogDiv size required, but now available before dialog show()
|
|
35
|
+
const atomCoordinates = extractAtomDataV3000(molfile);
|
|
36
|
+
// const cw: number = $(window).width() * 0.80; // dialogDiv.clientWidth
|
|
37
|
+
const clientHeight: number = $(window).height() * 0.70; // dialogDiv.clientHeight
|
|
38
|
+
const molWidth: number = Math.max(...atomCoordinates.x) - Math.min(...atomCoordinates.x);
|
|
39
|
+
const molHeight: number = Math.max(...atomCoordinates.y) - Math.min(...atomCoordinates.y);
|
|
40
|
+
|
|
41
|
+
// const wR: number = cw / molWidth;
|
|
42
|
+
const hR: number = clientHeight / molHeight;
|
|
43
|
+
const r: number = hR; // Math.max(wR, hR);
|
|
44
|
+
const dialogCanvasWidth = r * molWidth;
|
|
45
|
+
const dialogCanvasHeight = r * molHeight;
|
|
46
|
+
|
|
47
|
+
const dialogCanvas = ui.canvas(
|
|
48
|
+
dialogCanvasWidth * window.devicePixelRatio, dialogCanvasHeight * window.devicePixelRatio
|
|
49
|
+
);
|
|
50
|
+
dialogCanvas.style.width = `${dialogCanvasWidth}px`;
|
|
51
|
+
dialogCanvas.style.height = `${dialogCanvasHeight}px`;
|
|
52
|
+
await drawMolfileOnCanvas(dialogCanvas);
|
|
53
|
+
|
|
54
|
+
dialogDiv.appendChild(dialogCanvas);
|
|
55
|
+
ui.dialog('Molecule')
|
|
56
|
+
.add(dialogDiv)
|
|
57
|
+
.showModal(true);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
const errStr = errorToConsole(err);
|
|
60
|
+
console.error(errStr);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// clear div's content if any
|
|
65
|
+
moleculeImgDiv.innerHTML = '';
|
|
66
|
+
|
|
67
|
+
if (molfile !== '') {
|
|
68
|
+
const canvas = ui.canvas(canvasWidth * window.devicePixelRatio, canvasHeight * window.devicePixelRatio);
|
|
69
|
+
|
|
70
|
+
// Draw zoomed-out molecule
|
|
71
|
+
canvas.style.width = `${canvasWidth}px`;
|
|
72
|
+
canvas.style.height = `${canvasHeight}px`;
|
|
73
|
+
canvas.style.borderStyle = 'solid';
|
|
74
|
+
canvas.style.borderColor = 'blue';
|
|
75
|
+
drawMolfileOnCanvas(canvas);
|
|
76
|
+
|
|
77
|
+
// Dialog with zoomed-in molecule
|
|
78
|
+
$(canvas).on('click', drawZoomedInMolecule);
|
|
79
|
+
$(canvas).on('mouseover', () => $(canvas).css('cursor', 'grab')); // for some reason 'zoom-in' value wouldn't work
|
|
80
|
+
$(canvas).on('mouseout', () => $(canvas).css('cursor', 'default'));
|
|
81
|
+
|
|
82
|
+
moleculeImgDiv.append(canvas);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// import {map, SYNTHESIZERS, TECHNOLOGIES, MODIFICATIONS, DELIMITER} from './map';
|
|
2
|
-
import {map, SYNTHESIZERS, TECHNOLOGIES, DELIMITER} from '
|
|
3
|
-
import {isValidSequence} from '
|
|
2
|
+
import {map, SYNTHESIZERS, TECHNOLOGIES, DELIMITER} from '../../hardcode-to-be-eliminated/map';
|
|
3
|
+
import {isValidSequence} from '../../sdf-tab/sequence-codes-tools';
|
|
4
4
|
import {sortByStringLengthInDescendingOrder} from '../helpers';
|
|
5
|
-
import {getMonomerWorks} from '
|
|
5
|
+
import {getMonomerWorks} from '../../package';
|
|
6
6
|
import {getNucleotidesMol} from './mol-transformations';
|
|
7
7
|
|
|
8
|
-
import {standardPhosphateLinkSmiles, MODIFICATIONS} from '
|
|
9
|
-
import {getMonomerLib} from '
|
|
8
|
+
import {standardPhosphateLinkSmiles, MODIFICATIONS} from '../../hardcode-to-be-eliminated/const';
|
|
9
|
+
import {getMonomerLib} from '../../package';
|
|
10
10
|
// todo: remove
|
|
11
11
|
// const NAME = 'name';
|
|
12
12
|
const CODES = 'codes';
|
|
@@ -15,7 +15,7 @@ const MOL = 'molfile';
|
|
|
15
15
|
|
|
16
16
|
export function sequenceToMolV3000(
|
|
17
17
|
sequence: string, inverted: boolean = false, oclRender: boolean = false,
|
|
18
|
-
format: string
|
|
18
|
+
format: string
|
|
19
19
|
): string {
|
|
20
20
|
const monomerNameFromCode = getCodeToNameMap(sequence, format);
|
|
21
21
|
let codes = sortByStringLengthInDescendingOrder(Object.keys(monomerNameFromCode));
|
|
@@ -38,25 +38,24 @@ export function sequenceToMolV3000(
|
|
|
38
38
|
includesStandardLinkAlready.includes(codesList[i]) ||
|
|
39
39
|
(i < codesList.length - 1 && links.includes(codesList[i + 1]))
|
|
40
40
|
) {
|
|
41
|
-
|
|
42
|
-
if(aa !== undefined)
|
|
41
|
+
const aa = monomerNameFromCode[codesList[i]];
|
|
42
|
+
if (aa !== undefined)
|
|
43
|
+
monomers.push(aa);
|
|
44
|
+
else
|
|
45
|
+
monomers.push(codesList[i]);
|
|
46
|
+
} else {
|
|
47
|
+
const aa = monomerNameFromCode[codesList[i]];
|
|
48
|
+
if (aa !== undefined)
|
|
43
49
|
monomers.push(aa);
|
|
44
50
|
else
|
|
45
51
|
monomers.push(codesList[i]);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
let aa = monomerNameFromCode[codesList[i]];
|
|
49
|
-
if(aa !== undefined)
|
|
50
|
-
monomers.push(aa);
|
|
51
|
-
else
|
|
52
|
-
monomers.push(codesList[i]);
|
|
53
52
|
monomers.push('p linkage');
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
const lib = getMonomerLib();
|
|
58
57
|
const mols: string [] = [];
|
|
59
|
-
for(let i = 0; i < monomers.length; i++) {
|
|
58
|
+
for (let i = 0; i < monomers.length; i++) {
|
|
60
59
|
const mnmr = lib?.getMonomer('RNA', monomers[i]);
|
|
61
60
|
mols.push(mnmr?.molfile!);
|
|
62
61
|
}
|
|
@@ -1,30 +1,23 @@
|
|
|
1
1
|
export function getNucleotidesMol(codes: string[]) {
|
|
2
2
|
const molBlocks: string[] = [];
|
|
3
3
|
|
|
4
|
-
// for (let i = 0; i < smilesCodes.length - 1; i++) {
|
|
5
|
-
// smilesCodes[i] == 'OP(=O)(O)O' ? molBlocks.push(PHOSHATE) :
|
|
6
|
-
// smilesCodes[i] == 'OP(=O)(S)O' ? molBlocks.push(THIOPHOSHATE) :
|
|
7
|
-
// smilesCodes[i] == 'O[C@@H]1C[C@@H]O[C@H]1CO' ? molBlocks.push(rotateNucleotidesV3000(INVABASIC)) :
|
|
8
|
-
// smilesCodes[i] == 'OCC(O)CNC(=O)CCCC(=O)NC(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)' ? molBlocks.push(GALNAC) :
|
|
9
|
-
// smilesCodes[i] == 'C(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)(COCCC(=O)NCCCNC(=O)CCCCOC2OC(CO)C(O)C(O)C2NC(=O)C)NC(=O)CCCC(=O)NCC(O)CO' ? molBlocks.push(GALNACPRIME) :
|
|
10
|
-
// molBlocks.push(rotateNucleotidesV3000(smilesCodes[i]));
|
|
11
|
-
// }
|
|
12
|
-
|
|
13
4
|
for (let i = 0; i < codes.length - 1; i++) {
|
|
14
5
|
if (codes[i].includes('MODIFICATION')) {
|
|
15
|
-
if (i
|
|
6
|
+
if (i === 0)
|
|
16
7
|
molBlocks.push(reflect(codes[i]));
|
|
17
8
|
else
|
|
18
9
|
molBlocks.push(codes[i]);
|
|
19
|
-
}
|
|
20
|
-
else
|
|
10
|
+
} else {
|
|
21
11
|
molBlocks.push(rotateNucleotidesV3000(codes[i]));
|
|
12
|
+
}
|
|
22
13
|
}
|
|
23
14
|
|
|
24
15
|
return linkV3000(molBlocks);
|
|
25
16
|
}
|
|
26
17
|
|
|
27
|
-
export function linkStrandsV3000(
|
|
18
|
+
export function linkStrandsV3000(
|
|
19
|
+
strands: { senseStrands: string[], antiStrands: string[] }, useChirality: boolean = true
|
|
20
|
+
): string {
|
|
28
21
|
let macroMolBlock = '\nDatagrok macromolecule handler\n\n';
|
|
29
22
|
macroMolBlock += ' 0 0 0 0 0 0 999 V3000\n';
|
|
30
23
|
macroMolBlock += 'M V30 BEGIN CTAB\n';
|
|
@@ -40,22 +33,19 @@ export function linkStrandsV3000(strands: { senseStrands: string[], antiStrands:
|
|
|
40
33
|
// molBlocks[1] = invertNucleotidesV3000(molBlocks[1]);
|
|
41
34
|
|
|
42
35
|
if (strands.antiStrands.length > 0) {
|
|
43
|
-
for (let i = 0; i < strands.antiStrands.length; i++)
|
|
36
|
+
for (let i = 0; i < strands.antiStrands.length; i++)
|
|
44
37
|
strands.antiStrands[i] = invertNucleotidesV3000(strands.antiStrands[i]);
|
|
45
|
-
}
|
|
46
38
|
}
|
|
47
39
|
|
|
48
40
|
let inverted = false;
|
|
49
|
-
|
|
41
|
+
const molBlocks = strands.senseStrands.concat(strands.antiStrands);
|
|
50
42
|
|
|
51
43
|
for (let i = 0; i < molBlocks.length; i++) {
|
|
52
|
-
|
|
53
|
-
if (i >= strands.senseStrands.length && inverted == false) {
|
|
44
|
+
if (i >= strands.senseStrands.length && inverted === false) {
|
|
54
45
|
inverted = true;
|
|
55
46
|
xShift = 0;
|
|
56
47
|
}
|
|
57
48
|
|
|
58
|
-
|
|
59
49
|
molBlocks[i] = molBlocks[i].replaceAll('(-\nM V30 ', '(')
|
|
60
50
|
.replaceAll('-\nM V30 ', '').replaceAll(' )', ')');
|
|
61
51
|
const numbers = extractAtomsBondsNumbersV3000(molBlocks[i]);
|
|
@@ -63,7 +53,7 @@ export function linkStrandsV3000(strands: { senseStrands: string[], antiStrands:
|
|
|
63
53
|
|
|
64
54
|
if (inverted) {
|
|
65
55
|
const xShiftRight = Math.min(...coordinates.x) - xShift;
|
|
66
|
-
const yShift = !inverted ? Math.min(...coordinates.y) - 1 : Math.max(...coordinates.y) +
|
|
56
|
+
const yShift = !inverted ? Math.min(...coordinates.y) - 1 : Math.max(...coordinates.y) + 15;
|
|
67
57
|
for (let j = 0; j < coordinates.x.length; j++)
|
|
68
58
|
coordinates.x[j] -= xShiftRight;
|
|
69
59
|
for (let j = 0; j < coordinates.y.length; j++)
|
|
@@ -76,7 +66,7 @@ export function linkStrandsV3000(strands: { senseStrands: string[], antiStrands:
|
|
|
76
66
|
let indexEnd = indexAtoms;
|
|
77
67
|
|
|
78
68
|
for (let j = 0; j < numbers.natom; j++) {
|
|
79
|
-
// if (coordinates.atomIndex[j]
|
|
69
|
+
// if (coordinates.atomIndex[j] !== 1 || i === 0 || twoChains) {
|
|
80
70
|
//rewrite atom number
|
|
81
71
|
index = molBlocks[i].indexOf('V30', index) + 4;
|
|
82
72
|
indexEnd = molBlocks[i].indexOf(' ', index);
|
|
@@ -138,7 +128,7 @@ export function linkStrandsV3000(strands: { senseStrands: string[], antiStrands:
|
|
|
138
128
|
|
|
139
129
|
let indexCollection = molBlocks[i].indexOf('M V30 MDLV30/STEABS ATOMS=('); // V3000 index for collections
|
|
140
130
|
|
|
141
|
-
while (indexCollection
|
|
131
|
+
while (indexCollection !== -1) {
|
|
142
132
|
indexCollection += 28;
|
|
143
133
|
const collectionEnd = molBlocks[i].indexOf(')', indexCollection);
|
|
144
134
|
const collectionEntries = molBlocks[i].substring(indexCollection, collectionEnd).split(' ').slice(1);
|
|
@@ -157,25 +147,16 @@ export function linkStrandsV3000(strands: { senseStrands: string[], antiStrands:
|
|
|
157
147
|
const entries = 4;
|
|
158
148
|
const collNumber = Math.ceil(collection.length / entries);
|
|
159
149
|
|
|
160
|
-
//if (oclRender) {
|
|
161
|
-
// collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length;
|
|
162
|
-
|
|
163
|
-
// for (let j = 0; j < collection.length; j++)
|
|
164
|
-
// collectionBlock += ' ' + collection[j];
|
|
165
|
-
|
|
166
|
-
// collectionBlock += ')\n';
|
|
167
|
-
//} else {
|
|
168
150
|
collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length + ' -\n';
|
|
169
151
|
for (let i = 0; i < collNumber; i++) {
|
|
170
152
|
collectionBlock += 'M V30 ';
|
|
171
|
-
const entriesCurrent = i + 1
|
|
153
|
+
const entriesCurrent = i + 1 === collNumber ? collection.length - (collNumber - 1) * entries : entries;
|
|
172
154
|
for (let j = 0; j < entriesCurrent; j++) {
|
|
173
|
-
collectionBlock += (j + 1
|
|
174
|
-
(i
|
|
155
|
+
collectionBlock += (j + 1 === entriesCurrent) ?
|
|
156
|
+
(i === collNumber - 1 ? collection[entries * i + j] + ')\n' : collection[entries * i + j] + ' -\n') :
|
|
175
157
|
collection[entries * i + j] + ' ';
|
|
176
158
|
}
|
|
177
159
|
}
|
|
178
|
-
//}
|
|
179
160
|
|
|
180
161
|
//generate file
|
|
181
162
|
true ? natom : natom++;
|
|
@@ -190,8 +171,9 @@ export function linkStrandsV3000(strands: { senseStrands: string[], antiStrands:
|
|
|
190
171
|
macroMolBlock += 'M V30 BEGIN COLLECTION\n';
|
|
191
172
|
macroMolBlock += collectionBlock;
|
|
192
173
|
macroMolBlock += 'M V30 END COLLECTION\n';
|
|
193
|
-
} else
|
|
174
|
+
} else {
|
|
194
175
|
macroMolBlock = macroMolBlock.replace(/ CFG=\d/g, ' ');
|
|
176
|
+
}
|
|
195
177
|
|
|
196
178
|
macroMolBlock += 'M V30 END CTAB\n';
|
|
197
179
|
macroMolBlock += 'M END';
|
|
@@ -199,7 +181,7 @@ export function linkStrandsV3000(strands: { senseStrands: string[], antiStrands:
|
|
|
199
181
|
return macroMolBlock;
|
|
200
182
|
}
|
|
201
183
|
|
|
202
|
-
export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
|
|
184
|
+
export function linkV3000(molBlocks: string[], useChirality: boolean = true): string {
|
|
203
185
|
let macroMolBlock = '\nDatagrok macromolecule handler\n\n';
|
|
204
186
|
macroMolBlock += ' 0 0 0 0 0 0 999 V3000\n';
|
|
205
187
|
macroMolBlock += 'M V30 BEGIN CTAB\n';
|
|
@@ -212,7 +194,7 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
|
|
|
212
194
|
let xShift = 0;
|
|
213
195
|
|
|
214
196
|
for (let i = 0; i < molBlocks.length; i++) {
|
|
215
|
-
const isBoundary = molBlocks[i].includes('MODIFICATION') && i
|
|
197
|
+
const isBoundary = molBlocks[i].includes('MODIFICATION') && i === 0;
|
|
216
198
|
let specLength = 0;
|
|
217
199
|
if (isBoundary) {
|
|
218
200
|
const coordinates = extractAtomDataV3000(molBlocks[i]);
|
|
@@ -231,16 +213,16 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
|
|
|
231
213
|
let indexEnd = indexAtoms;
|
|
232
214
|
|
|
233
215
|
for (let j = 0; j < numbers.natom; j++) {
|
|
234
|
-
if (coordinates.atomIndex[j]
|
|
216
|
+
if (coordinates.atomIndex[j] !== 1 || i === 0) {
|
|
235
217
|
//rewrite atom number
|
|
236
218
|
index = molBlocks[i].indexOf('V30', index) + 4;
|
|
237
219
|
indexEnd = molBlocks[i].indexOf(' ', index);
|
|
238
220
|
let atomNumber = 0;
|
|
239
221
|
if (isBoundary) {
|
|
240
222
|
atomNumber = parseInt(molBlocks[i].substring(index, indexEnd))
|
|
241
|
-
if (atomNumber
|
|
223
|
+
if (atomNumber === 1)
|
|
242
224
|
atomNumber = specLength;
|
|
243
|
-
else if (atomNumber
|
|
225
|
+
else if (atomNumber === specLength)
|
|
244
226
|
atomNumber = 1;
|
|
245
227
|
atomNumber += natom;
|
|
246
228
|
} else {
|
|
@@ -294,9 +276,9 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
|
|
|
294
276
|
let atomNumber = 0;
|
|
295
277
|
if (isBoundary) {
|
|
296
278
|
atomNumber = parseInt(molBlocks[i].substring(index, indexEnd))
|
|
297
|
-
if (atomNumber
|
|
279
|
+
if (atomNumber === 1)
|
|
298
280
|
atomNumber = specLength;
|
|
299
|
-
else if (atomNumber
|
|
281
|
+
else if (atomNumber === specLength)
|
|
300
282
|
atomNumber = 1;
|
|
301
283
|
atomNumber += natom;
|
|
302
284
|
} else {
|
|
@@ -309,9 +291,9 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
|
|
|
309
291
|
atomNumber = 0;
|
|
310
292
|
if (isBoundary) {
|
|
311
293
|
atomNumber = parseInt(molBlocks[i].substring(index, indexEnd))
|
|
312
|
-
if (atomNumber
|
|
294
|
+
if (atomNumber === 1)
|
|
313
295
|
atomNumber = specLength;
|
|
314
|
-
else if (atomNumber
|
|
296
|
+
else if (atomNumber === specLength)
|
|
315
297
|
atomNumber = 1;
|
|
316
298
|
atomNumber += natom;
|
|
317
299
|
} else {
|
|
@@ -327,7 +309,7 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
|
|
|
327
309
|
|
|
328
310
|
let indexCollection = molBlocks[i].indexOf('M V30 MDLV30/STEABS ATOMS=('); // V3000 index for collections
|
|
329
311
|
|
|
330
|
-
while (indexCollection
|
|
312
|
+
while (indexCollection !== -1) {
|
|
331
313
|
indexCollection += 28;
|
|
332
314
|
const collectionEnd = molBlocks[i].indexOf(')', indexCollection);
|
|
333
315
|
const collectionEntries = molBlocks[i].substring(indexCollection, collectionEnd).split(' ').slice(1);
|
|
@@ -360,10 +342,10 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
|
|
|
360
342
|
collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length + ' -\n';
|
|
361
343
|
for (let i = 0; i < collNumber; i++) {
|
|
362
344
|
collectionBlock += 'M V30 ';
|
|
363
|
-
const entriesCurrent = i + 1
|
|
345
|
+
const entriesCurrent = i + 1 === collNumber ? collection.length - (collNumber - 1) * entries : entries;
|
|
364
346
|
for (let j = 0; j < entriesCurrent; j++) {
|
|
365
|
-
collectionBlock += (j + 1
|
|
366
|
-
(i
|
|
347
|
+
collectionBlock += (j + 1 === entriesCurrent) ?
|
|
348
|
+
(i === collNumber - 1 ? collection[entries * i + j] + ')\n' : collection[entries * i + j] + ' -\n') :
|
|
367
349
|
collection[entries * i + j] + ' ';
|
|
368
350
|
}
|
|
369
351
|
}
|
|
@@ -391,7 +373,7 @@ export function linkV3000(molBlocks: string[], useChirality: boolean = true) {
|
|
|
391
373
|
return macroMolBlock;
|
|
392
374
|
}
|
|
393
375
|
|
|
394
|
-
function rotateNucleotidesV3000(molecule: string) {
|
|
376
|
+
function rotateNucleotidesV3000(molecule: string): string {
|
|
395
377
|
// @ts-ignore
|
|
396
378
|
let molBlock = molecule.includes('M END') ? molecule : OCL.Molecule.fromSmiles(molecule).toMolfileV3();
|
|
397
379
|
const coordinates = extractAtomDataV3000(molBlock);
|
|
@@ -414,9 +396,9 @@ function rotateNucleotidesV3000(molecule: string) {
|
|
|
414
396
|
}
|
|
415
397
|
|
|
416
398
|
let angle = 0;
|
|
417
|
-
if (coordinates.x[indexFivePrime]
|
|
399
|
+
if (coordinates.x[indexFivePrime] === 0)
|
|
418
400
|
angle = coordinates.y[indexFivePrime] > coordinates.y[indexThreePrime] ? Math.PI / 2 : 3 * Math.PI / 2;
|
|
419
|
-
else if (coordinates.y[indexFivePrime]
|
|
401
|
+
else if (coordinates.y[indexFivePrime] === 0)
|
|
420
402
|
angle = coordinates.x[indexFivePrime] > coordinates.x[indexThreePrime] ? Math.PI : 0;
|
|
421
403
|
else {
|
|
422
404
|
const derivative = coordinates.y[indexFivePrime] / coordinates.x[indexFivePrime];
|
|
@@ -460,7 +442,7 @@ function rotateNucleotidesV3000(molecule: string) {
|
|
|
460
442
|
return molBlock;
|
|
461
443
|
}
|
|
462
444
|
|
|
463
|
-
function reflect(molecule: string) {
|
|
445
|
+
function reflect(molecule: string): string {
|
|
464
446
|
// @ts-ignore
|
|
465
447
|
let molBlock = molecule.includes('M END') ? molecule : OCL.Molecule.fromSmiles(molecule).toMolfileV3();
|
|
466
448
|
const coordinates = extractAtomDataV3000(molBlock);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<html><head><meta charset="utf-8"/><title>SequenceTranslator Test Report. Datagrok version datagrok/datagrok:latest SHA=
|
|
1
|
+
<html><head><meta charset="utf-8"/><title>SequenceTranslator Test Report. Datagrok version datagrok/datagrok:latest SHA=6288c2fbe346. Commit 695b7b55.</title><style type="text/css">html,
|
|
2
2
|
body {
|
|
3
3
|
font-family: Arial, Helvetica, sans-serif;
|
|
4
4
|
font-size: 1rem;
|
|
@@ -229,31 +229,31 @@ 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=
|
|
232
|
+
</style></head><body><div id="jesthtml-content"><header><h1 id="title">SequenceTranslator Test Report. Datagrok version datagrok/datagrok:latest SHA=6288c2fbe346. Commit 695b7b55.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-12-19 15:46: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">15.201s</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">4.324s</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.<anonymous> (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/test-node.ts:62:11)
|
|
233
233
|
at Generator.next (<anonymous>)
|
|
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
|
|
236
236
|
at Generator.next (<anonymous>)
|
|
237
|
-
at /home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:
|
|
237
|
+
at /home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:34:71
|
|
238
238
|
at new Promise (<anonymous>)
|
|
239
|
-
at Object.<anonymous>.__awaiter (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:
|
|
239
|
+
at Object.<anonymous>.__awaiter (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:30:12)
|
|
240
240
|
at Object.<anonymous> (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:38:23)
|
|
241
241
|
at Promise.then.completed (/home/runner/work/public/public/packages/SequenceTranslator/node_modules/jest-circus/build/utils.js:391:28)
|
|
242
242
|
at new Promise (<anonymous>)</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 (<anonymous>)
|
|
244
|
-
at fulfilled (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:
|
|
245
|
-
at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Test result : Success :
|
|
246
|
-
Test result : Success :
|
|
244
|
+
at fulfilled (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:31:58)
|
|
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
|
+
Test result : Success : 1 : SequenceTranslator.sequence-translator.usAfsusgsgsg : OK
|
|
247
247
|
Test result : Success : 1 : SequenceTranslator.sequence-translator.UfUfUfsCfsuacg : OK
|
|
248
248
|
Test result : Success : 0 : SequenceTranslator.sequence-translator.susususauasu : OK
|
|
249
249
|
Test result : Success : 1 : SequenceTranslator.sequence-translator.CfGfCfsGfsCf : OK
|
|
250
250
|
Test result : Success : 0 : SequenceTranslator.sequence-translator.acacacsacsac : OK
|
|
251
|
-
Test result : Success :
|
|
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 :
|
|
254
|
+
Test result : Success : 1 : SequenceTranslator.sequence-translator.(invabasic)usAfsucuCfuUfAfgcugUfgCfacususu : OK
|
|
255
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 (<anonymous>)
|
|
258
|
-
at fulfilled (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:
|
|
258
|
+
at fulfilled (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:31:58)
|
|
259
259
|
at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message"/></div></div></div></div></body></html>
|