@datagrok/sequence-translator 0.0.9 → 0.0.12
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/css/style.css +18 -0
- package/dist/package-test.js +2387 -0
- package/dist/package.js +5151 -0
- package/package.json +15 -7
- package/src/package.ts +27 -35
- package/src/salts.ts +2 -2
- package/src/structures-works/from-monomers.ts +2 -2
- package/src/structures-works/mol-transformations.ts +11 -7
- package/src/structures-works/sequence-codes-tools.ts +110 -94
- package/{test-SequenceTranslator-2e08c8e54bde-1367d435.html → test-SequenceTranslator-c2bbc2b235db-afc0e1c5.html} +2 -2
package/package.json
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.12",
|
|
5
5
|
"description": "",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/datagrok-ai/public.git",
|
|
9
|
+
"directory": "packages/SequenceTranslator"
|
|
10
|
+
},
|
|
6
11
|
"dependencies": {
|
|
7
12
|
"@datagrok-libraries/utils": "^0.1.0",
|
|
8
13
|
"@types/react": "latest",
|
|
9
|
-
"datagrok-api": "
|
|
14
|
+
"datagrok-api": "^0.151.0",
|
|
10
15
|
"datagrok-tools": "^4.1.2",
|
|
11
16
|
"npm": "^7.11.2",
|
|
12
17
|
"save-svg-as-png": "^1.4.17",
|
|
@@ -28,6 +33,9 @@
|
|
|
28
33
|
"test-dev": "set HOST=dev && jest",
|
|
29
34
|
"test-local": "set HOST=localhost && jest"
|
|
30
35
|
},
|
|
36
|
+
"sources": [
|
|
37
|
+
"css/style.css"
|
|
38
|
+
],
|
|
31
39
|
"devDependencies": {
|
|
32
40
|
"@typescript-eslint/eslint-plugin": "^4.29.1",
|
|
33
41
|
"@typescript-eslint/parser": "^4.29.1",
|
|
@@ -36,10 +44,10 @@
|
|
|
36
44
|
"eslint-config-google": "^0.14.0",
|
|
37
45
|
"webpack": "^5.31.0",
|
|
38
46
|
"webpack-cli": "^4.6.0",
|
|
39
|
-
"
|
|
40
|
-
"jest": "
|
|
41
|
-
"jest
|
|
42
|
-
"
|
|
43
|
-
"
|
|
47
|
+
"jest-html-reporter": "^3.5.0",
|
|
48
|
+
"jest": "^27.0.0",
|
|
49
|
+
"@types/jest": "^27.0.0",
|
|
50
|
+
"ts-jest": "^27.0.0",
|
|
51
|
+
"puppeteer": "latest"
|
|
44
52
|
}
|
|
45
53
|
}
|
package/src/package.ts
CHANGED
|
@@ -7,7 +7,7 @@ import $ from 'cash-dom';
|
|
|
7
7
|
import {defineAxolabsPattern} from './defineAxolabsPattern';
|
|
8
8
|
import {saveSenseAntiSense} from './structures-works/save-sense-antisense';
|
|
9
9
|
import {sequenceToSmiles, sequenceToMolV3000} from './structures-works/from-monomers';
|
|
10
|
-
import {convertSequence, undefinedInputSequence} from './structures-works/sequence-codes-tools';
|
|
10
|
+
import {convertSequence, undefinedInputSequence, isValidSequence} from './structures-works/sequence-codes-tools';
|
|
11
11
|
import {map, COL_NAMES, MODIFICATIONS} from './structures-works/map';
|
|
12
12
|
import {SALTS_CSV} from './salts';
|
|
13
13
|
import {USERS_CSV} from './users';
|
|
@@ -17,7 +17,7 @@ import {IDPS} from './IDPs';
|
|
|
17
17
|
|
|
18
18
|
export const _package = new DG.Package();
|
|
19
19
|
|
|
20
|
-
const defaultInput = '
|
|
20
|
+
const defaultInput = 'fAmCmGmAmCpsmU';
|
|
21
21
|
const sequenceWasCopied = 'Copied';
|
|
22
22
|
const tooltipSequence = 'Copy sequence';
|
|
23
23
|
|
|
@@ -35,29 +35,31 @@ export function sequenceTranslator(): void {
|
|
|
35
35
|
const pi = DG.TaskBarProgressIndicator.create('Rendering table and molecule...');
|
|
36
36
|
let errorsExist = false;
|
|
37
37
|
try {
|
|
38
|
-
|
|
38
|
+
sequence = sequence.replace(/\s/g, '');
|
|
39
|
+
const output = isValidSequence(sequence);
|
|
40
|
+
const outputSequenceObj = convertSequence(sequence, output);
|
|
39
41
|
const tableRows = [];
|
|
40
42
|
|
|
41
43
|
for (const key of Object.keys(outputSequenceObj).slice(1)) {
|
|
42
|
-
const
|
|
43
|
-
JSON.parse(outputSequenceObj.
|
|
44
|
+
const indexOfFirstNotValidChar = ('indexOfFirstNotValidChar' in outputSequenceObj) ?
|
|
45
|
+
JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).indexOfFirstNotValidChar :
|
|
44
46
|
-1;
|
|
45
|
-
if ('
|
|
46
|
-
const
|
|
47
|
-
JSON.parse(outputSequenceObj.
|
|
47
|
+
if ('indexOfFirstNotValidChar' in outputSequenceObj) {
|
|
48
|
+
const indexOfFirstNotValidChar = ('indexOfFirstNotValidChar' in outputSequenceObj) ?
|
|
49
|
+
JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).indexOfFirstNotValidChar :
|
|
48
50
|
-1;
|
|
49
|
-
if (
|
|
51
|
+
if (indexOfFirstNotValidChar != -1)
|
|
50
52
|
errorsExist = true;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
tableRows.push({
|
|
54
56
|
'key': key,
|
|
55
|
-
'value': ('
|
|
57
|
+
'value': ('indexOfFirstNotValidChar' in outputSequenceObj) ?
|
|
56
58
|
ui.divH([
|
|
57
|
-
ui.divText(sequence.slice(0,
|
|
59
|
+
ui.divText(sequence.slice(0, indexOfFirstNotValidChar), {style: {color: 'grey'}}),
|
|
58
60
|
ui.tooltip.bind(
|
|
59
|
-
ui.divText(sequence.slice(
|
|
60
|
-
'Expected format: ' + JSON.parse(outputSequenceObj.
|
|
61
|
+
ui.divText(sequence.slice(indexOfFirstNotValidChar), {style: {color: 'red'}}),
|
|
62
|
+
'Expected format: ' + JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).synthesizer +
|
|
61
63
|
'. See tables with valid codes on the right',
|
|
62
64
|
),
|
|
63
65
|
]) : //@ts-ignore
|
|
@@ -67,13 +69,12 @@ export function sequenceTranslator(): void {
|
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
if (errorsExist) {
|
|
70
|
-
const
|
|
71
|
-
.expectedSynthesizer.slice(0, -6);
|
|
72
|
+
const synthesizer = JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).synthesizer.slice(0, -6);
|
|
72
73
|
asoGapmersGrid.onCellPrepare(function(gc) {
|
|
73
|
-
gc.style.backColor = (gc.gridColumn.name ==
|
|
74
|
+
gc.style.backColor = (gc.gridColumn.name == synthesizer) ? 0xFFF00000 : 0xFFFFFFFF;
|
|
74
75
|
});
|
|
75
76
|
omeAndFluoroGrid.onCellPrepare(function(gc) {
|
|
76
|
-
gc.style.backColor = (gc.gridColumn.name ==
|
|
77
|
+
gc.style.backColor = (gc.gridColumn.name == synthesizer) ? 0xFFF00000 : 0xFFFFFFFF;
|
|
77
78
|
});
|
|
78
79
|
switchInput.enabled = true;
|
|
79
80
|
} else {
|
|
@@ -85,7 +86,7 @@ export function sequenceTranslator(): void {
|
|
|
85
86
|
ui.div([
|
|
86
87
|
DG.HtmlTable.create(tableRows, (item: { key: string; value: string; }) =>
|
|
87
88
|
[item.key, item.value], ['Code', 'Sequence']).root,
|
|
88
|
-
]
|
|
89
|
+
]),
|
|
89
90
|
);
|
|
90
91
|
semTypeOfInputSequence.textContent = 'Detected input type: ' + outputSequenceObj.type;
|
|
91
92
|
|
|
@@ -115,7 +116,7 @@ export function sequenceTranslator(): void {
|
|
|
115
116
|
|
|
116
117
|
const semTypeOfInputSequence = ui.divText('');
|
|
117
118
|
const moleculeSvgDiv = ui.block([]);
|
|
118
|
-
const outputTableDiv = ui.div([]
|
|
119
|
+
const outputTableDiv = ui.div([]);
|
|
119
120
|
const inputSequenceField = ui.textInput('', defaultInput, (sequence: string) => updateTableAndMolecule(sequence));
|
|
120
121
|
|
|
121
122
|
const asoDf = DG.DataFrame.fromObjects([
|
|
@@ -191,7 +192,7 @@ export function sequenceTranslator(): void {
|
|
|
191
192
|
ui.div([
|
|
192
193
|
inputSequenceField.root,
|
|
193
194
|
], 'input-base'),
|
|
194
|
-
], '
|
|
195
|
+
], 'inputSequence'),
|
|
195
196
|
semTypeOfInputSequence,
|
|
196
197
|
ui.block([
|
|
197
198
|
ui.h1('Output'),
|
|
@@ -233,18 +234,6 @@ export function sequenceTranslator(): void {
|
|
|
233
234
|
tabControl.onTabChanged.subscribe((_) =>
|
|
234
235
|
v.setRibbonPanels([(tabControl.currentPane.name == 'MAIN') ? topPanel : []]));
|
|
235
236
|
v.setRibbonPanels([topPanel]);
|
|
236
|
-
|
|
237
|
-
$('.sequence')
|
|
238
|
-
.children().css('padding', '5px 0');
|
|
239
|
-
$('.sequenceInput .input-base')
|
|
240
|
-
.css('margin', '0');
|
|
241
|
-
$('.sequenceInput textarea')
|
|
242
|
-
.css('resize', 'none')
|
|
243
|
-
.css('min-height', '50px')
|
|
244
|
-
.css('width', '100%')
|
|
245
|
-
.attr('spellcheck', 'false');
|
|
246
|
-
$('.sequenceInput select')
|
|
247
|
-
.css('width', '100%');
|
|
248
237
|
}
|
|
249
238
|
|
|
250
239
|
async function saveTableAsSdFile(table: DG.DataFrame) {
|
|
@@ -324,6 +313,7 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
324
313
|
return grok.shell.error('Columns already exist!');
|
|
325
314
|
|
|
326
315
|
const sequence = t.col(COL_NAMES.SEQUENCE)!;
|
|
316
|
+
const salt = t.col(COL_NAMES.SALT)!;
|
|
327
317
|
const equivalents = t.col(COL_NAMES.EQUIVALENTS)!;
|
|
328
318
|
|
|
329
319
|
t.columns.addNewString(COL_NAMES.COMPOUND_NAME).init((i: number) => sequence.get(i));
|
|
@@ -331,11 +321,13 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
331
321
|
sequence.getString(i) + '; duplex of SS: ' + sequence.getString(i - 2) + ' and AS: ' + sequence.getString(i - 1) :
|
|
332
322
|
sequence.getString(i),
|
|
333
323
|
);
|
|
324
|
+
const molWeightCol = saltsDf.col('MOLWEIGHT')!;
|
|
325
|
+
const saltNamesList = saltsDf.col('DISPLAY')!.toList();
|
|
334
326
|
t.columns.addNewFloat(COL_NAMES.CPD_MW)
|
|
335
327
|
.init((i: number) => molecularWeight(sequence.get(i), weightsObj));
|
|
336
|
-
const mwCol = t.col(COL_NAMES.CPD_MW)!;
|
|
337
328
|
t.columns.addNewFloat(COL_NAMES.SALT_MASS).init((i: number) => {
|
|
338
|
-
const
|
|
329
|
+
const saltRowIndex = saltNamesList.indexOf(salt.get(i));
|
|
330
|
+
const mw = molWeightCol.get(saltRowIndex);
|
|
339
331
|
return mw * equivalents.get(i);
|
|
340
332
|
});
|
|
341
333
|
t.columns.addNewCalculated(COL_NAMES.BATCH_MW,
|
|
@@ -367,7 +359,7 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
367
359
|
|
|
368
360
|
view.table!.col(COL_NAMES.TYPE)!.setTag(DG.TAGS.CHOICES, '["AS", "SS", "Duplex"]');
|
|
369
361
|
view.table!.col(COL_NAMES.OWNER)!.setTag(DG.TAGS.CHOICES, stringifyItems(usersDf.columns.byIndex(0).toList()));
|
|
370
|
-
view.table!.col(COL_NAMES.SALT)!.setTag(DG.TAGS.CHOICES, stringifyItems(saltsDf.columns.byIndex(
|
|
362
|
+
view.table!.col(COL_NAMES.SALT)!.setTag(DG.TAGS.CHOICES, stringifyItems(saltsDf.columns.byIndex(0).toList()));
|
|
371
363
|
view.table!.col(COL_NAMES.SOURCE)!.setTag(DG.TAGS.CHOICES, stringifyItems(sourcesDf.columns.byIndex(0).toList()));
|
|
372
364
|
view.table!.col(COL_NAMES.ICD)!.setTag(DG.TAGS.CHOICES, stringifyItems(icdsDf.columns.byIndex(0).toList()));
|
|
373
365
|
view.table!.col(COL_NAMES.IDP)!.setTag(DG.TAGS.CHOICES, stringifyItems(idpsDf.columns.byIndex(0).toList()));
|
package/src/salts.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const SALTS_CSV = `
|
|
2
|
-
|
|
1
|
+
export const SALTS_CSV = `DISPLAY,MOLWEIGHT
|
|
2
|
+
no Data Added,100`;
|
|
@@ -92,9 +92,9 @@ function getObjectWithCodesAndSmiles(sequence: string) {
|
|
|
92
92
|
}
|
|
93
93
|
// TODO: create object based from synthesizer type to avoid key(codes) duplicates
|
|
94
94
|
const output = isValidSequence(sequence);
|
|
95
|
-
if (output.
|
|
95
|
+
if (output.synthesizer == SYNTHESIZERS.MERMADE_12)
|
|
96
96
|
obj['g'] = map[SYNTHESIZERS.MERMADE_12][TECHNOLOGIES.SI_RNA]['g'].SMILES;
|
|
97
|
-
else if (output.
|
|
97
|
+
else if (output.synthesizer == SYNTHESIZERS.AXOLABS)
|
|
98
98
|
obj['g'] = map[SYNTHESIZERS.AXOLABS][TECHNOLOGIES.SI_RNA]['g'].SMILES;
|
|
99
99
|
return obj;
|
|
100
100
|
}
|
|
@@ -95,7 +95,7 @@ export function getNucleotidesMol(smilesCodes: string[], oclRender: boolean = fa
|
|
|
95
95
|
|
|
96
96
|
export function linkV3000(molBlocks: string[], twoMolecules: boolean = false, oclRender: boolean = false) {
|
|
97
97
|
let macroMolBlock = '\nDatagrok macromolecule handler\n\n';
|
|
98
|
-
macroMolBlock += ' 0 0 0 0 0 0
|
|
98
|
+
macroMolBlock += ' 0 0 0 0 0 0 999 V3000\n';
|
|
99
99
|
macroMolBlock += 'M V30 BEGIN CTAB\n';
|
|
100
100
|
let atomBlock = '';
|
|
101
101
|
let bondBlock = '';
|
|
@@ -110,6 +110,8 @@ export function linkV3000(molBlocks: string[], twoMolecules: boolean = false, oc
|
|
|
110
110
|
molBlocks[1] = invertNucleotidesV3000(molBlocks[1]);
|
|
111
111
|
|
|
112
112
|
for (let i = 0; i < molBlocks.length; i++) {
|
|
113
|
+
molBlocks[i] = molBlocks[i].replaceAll('(-\nM V30 ', '(')
|
|
114
|
+
.replaceAll('-\nM V30 ', '').replaceAll(' )', ')');
|
|
113
115
|
const numbers = extractAtomsBondsNumbersV3000(molBlocks[i]);
|
|
114
116
|
const coordinates = extractAtomDataV3000(molBlocks[i]);
|
|
115
117
|
let indexAtoms = molBlocks[i].indexOf('M V30 BEGIN ATOM'); // V3000 index for atoms coordinates
|
|
@@ -184,7 +186,7 @@ export function linkV3000(molBlocks: string[], twoMolecules: boolean = false, oc
|
|
|
184
186
|
while (indexCollection != -1) {
|
|
185
187
|
indexCollection += 28;
|
|
186
188
|
const collectionEnd = molBlocks[i].indexOf(')', indexCollection);
|
|
187
|
-
const collectionEntries = molBlocks[i].substring(indexCollection, collectionEnd).split(' ');
|
|
189
|
+
const collectionEntries = molBlocks[i].substring(indexCollection, collectionEnd).split(' ').slice(1);
|
|
188
190
|
collectionEntries.forEach((e) => {
|
|
189
191
|
collection.push(parseInt(e) + natom);
|
|
190
192
|
});
|
|
@@ -209,13 +211,15 @@ export function linkV3000(molBlocks: string[], twoMolecules: boolean = false, oc
|
|
|
209
211
|
|
|
210
212
|
collectionBlock += ')\n';
|
|
211
213
|
} else {
|
|
214
|
+
collectionBlock += 'M V30 MDLV30/STEABS ATOMS=(' + collection.length + ' -\n';
|
|
212
215
|
for (let i = 0; i < collNumber; i++) {
|
|
213
|
-
collectionBlock += 'M V30
|
|
216
|
+
collectionBlock += 'M V30 ';
|
|
214
217
|
const entriesCurrent = i + 1 == collNumber ? collection.length - (collNumber - 1)*entries : entries;
|
|
215
|
-
for (let j = 0; j < entriesCurrent; j++)
|
|
216
|
-
collectionBlock += (j + 1 == entriesCurrent) ?
|
|
217
|
-
|
|
218
|
-
|
|
218
|
+
for (let j = 0; j < entriesCurrent; j++) {
|
|
219
|
+
collectionBlock += (j + 1 == entriesCurrent) ?
|
|
220
|
+
(i == collNumber - 1 ? collection[entries*i + j] + ')\n' : collection[entries*i + j] + ' -\n') :
|
|
221
|
+
collection[entries*i + j] + ' ';
|
|
222
|
+
}
|
|
219
223
|
}
|
|
220
224
|
}
|
|
221
225
|
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as ui from 'datagrok-api/ui';
|
|
3
|
+
// import * as DG from 'datagrok-api/dg';
|
|
1
4
|
import {map, SYNTHESIZERS, TECHNOLOGIES, MODIFICATIONS} from './map';
|
|
2
5
|
import {asoGapmersNucleotidesToBioSpring, asoGapmersNucleotidesToGcrs,
|
|
3
6
|
asoGapmersBioSpringToNucleotides, asoGapmersBioSpringToGcrs, asoGapmersGcrsToNucleotides,
|
|
@@ -11,97 +14,112 @@ const noTranslationTableAvailable = 'No translation table available';
|
|
|
11
14
|
export const undefinedInputSequence = 'Type of input sequence is undefined';
|
|
12
15
|
|
|
13
16
|
export function isValidSequence(sequence: string): {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
indexOfFirstNotValidChar: number,
|
|
18
|
+
synthesizer: string | null,
|
|
19
|
+
technology: string | null
|
|
17
20
|
} {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
let possibleSynthesizers = getListOfPossibleSynthesizersByFirstMatchedCode(sequence);
|
|
22
|
+
|
|
23
|
+
if (possibleSynthesizers.length > 1) {
|
|
24
|
+
const synthesizer = ui.choiceInput('Choose synthesizer from list: ', possibleSynthesizers[0], possibleSynthesizers);
|
|
25
|
+
ui.dialog('Choose Synthesizer')
|
|
26
|
+
.add(ui.panel([synthesizer.root], {style: {fontWeight: 'bold'}}))
|
|
27
|
+
.onOK(() => possibleSynthesizers = [synthesizer.value])
|
|
28
|
+
.onCancel(() => {
|
|
29
|
+
possibleSynthesizers = [possibleSynthesizers[0]];
|
|
30
|
+
grok.shell.warning('Input sequence is expected to be in format ' + possibleSynthesizers[0]);
|
|
31
|
+
})
|
|
32
|
+
.show();
|
|
33
|
+
} else if (possibleSynthesizers.length == 0)
|
|
34
|
+
return {indexOfFirstNotValidChar: 0, synthesizer: null, technology: null};
|
|
35
|
+
|
|
36
|
+
let outputIndex = 0;
|
|
23
37
|
|
|
24
38
|
const firstUniqueCharacters = ['r', 'd'];
|
|
25
39
|
const nucleotides = ['A', 'U', 'T', 'C', 'G'];
|
|
26
40
|
|
|
27
|
-
possibleSynthesizers.forEach((synthesizer
|
|
41
|
+
possibleSynthesizers.forEach((synthesizer) => {
|
|
28
42
|
const codes = getAllCodesOfSynthesizer(synthesizer);
|
|
29
|
-
while (
|
|
30
|
-
const matchedCode = codes
|
|
31
|
-
.find((c) => c == sequence.slice(outputIndices[synthesizerIndex], outputIndices[synthesizerIndex] + c.length));
|
|
43
|
+
while (outputIndex < sequence.length) {
|
|
44
|
+
const matchedCode = codes.find((c) => c == sequence.slice(outputIndex, outputIndex + c.length));
|
|
32
45
|
|
|
33
46
|
if (matchedCode == null)
|
|
34
47
|
break;
|
|
35
48
|
|
|
36
49
|
if ( // for mistake pattern 'rAA'
|
|
37
|
-
|
|
38
|
-
nucleotides.includes(sequence[
|
|
39
|
-
firstUniqueCharacters.includes(sequence[
|
|
50
|
+
outputIndex > 1 &&
|
|
51
|
+
nucleotides.includes(sequence[outputIndex]) &&
|
|
52
|
+
firstUniqueCharacters.includes(sequence[outputIndex - 2])
|
|
40
53
|
) break;
|
|
41
54
|
|
|
42
55
|
if ( // for mistake pattern 'ArA'
|
|
43
|
-
firstUniqueCharacters.includes(sequence[
|
|
44
|
-
nucleotides.includes(sequence[
|
|
56
|
+
firstUniqueCharacters.includes(sequence[outputIndex + 1]) &&
|
|
57
|
+
nucleotides.includes(sequence[outputIndex])
|
|
45
58
|
) {
|
|
46
|
-
|
|
59
|
+
outputIndex++;
|
|
47
60
|
break;
|
|
48
61
|
}
|
|
49
62
|
|
|
50
|
-
|
|
63
|
+
outputIndex += matchedCode.length;
|
|
51
64
|
}
|
|
52
65
|
});
|
|
53
66
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
const expectedSynthesizer = possibleSynthesizers[outputIndices.indexOf(indexOfExpectedSythesizer)];
|
|
57
|
-
if (indexOfFirstNotValidCharacter != -1) {
|
|
67
|
+
const indexOfFirstNotValidChar = (outputIndex == sequence.length) ? -1 : outputIndex;
|
|
68
|
+
if (indexOfFirstNotValidChar != -1) {
|
|
58
69
|
return {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
indexOfFirstNotValidChar: indexOfFirstNotValidChar,
|
|
71
|
+
synthesizer: possibleSynthesizers[0],
|
|
72
|
+
technology: null,
|
|
62
73
|
};
|
|
63
74
|
}
|
|
64
75
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
76
|
+
let possibleTechnologies = getListOfPossibleTechnologiesByFirstMatchedCode(sequence, possibleSynthesizers[0]);
|
|
77
|
+
|
|
78
|
+
if (possibleTechnologies.length > 1) {
|
|
79
|
+
const technology = ui.choiceInput('Choose technology from list: ', possibleTechnologies[0], possibleTechnologies);
|
|
80
|
+
ui.dialog('Choose Technology')
|
|
81
|
+
.add(ui.panel([technology.root], {style: {fontWeight: 'bold'}}))
|
|
82
|
+
.onOK(() => possibleTechnologies = [technology.value])
|
|
83
|
+
.onCancel(() => {
|
|
84
|
+
possibleTechnologies = [possibleTechnologies[0]];
|
|
85
|
+
grok.shell.warning('Input sequence is expected to be in format ' + possibleTechnologies[0]);
|
|
86
|
+
})
|
|
87
|
+
.show();
|
|
88
|
+
} else if (possibleTechnologies.length == 0)
|
|
89
|
+
return {indexOfFirstNotValidChar: 0, synthesizer: null, technology: null};
|
|
68
90
|
|
|
69
|
-
|
|
91
|
+
outputIndex = 0;
|
|
70
92
|
|
|
71
|
-
possibleTechnologies.forEach((technology: string
|
|
72
|
-
const codes = Object.keys(map[
|
|
73
|
-
while (
|
|
74
|
-
const matchedCode = codes
|
|
75
|
-
.find((c) => c == sequence.slice(outputIndices[technologyIndex], outputIndices[technologyIndex] + c.length));
|
|
93
|
+
possibleTechnologies.forEach((technology: string) => {
|
|
94
|
+
const codes = Object.keys(map[possibleSynthesizers[0]][technology]);
|
|
95
|
+
while (outputIndex < sequence.length) {
|
|
96
|
+
const matchedCode = codes.find((c) => c == sequence.slice(outputIndex, outputIndex + c.length));
|
|
76
97
|
|
|
77
98
|
if (matchedCode == null)
|
|
78
99
|
break;
|
|
79
100
|
|
|
80
101
|
if ( // for mistake pattern 'rAA'
|
|
81
|
-
|
|
82
|
-
nucleotides.includes(sequence[
|
|
83
|
-
firstUniqueCharacters.includes(sequence[
|
|
102
|
+
outputIndex > 1 &&
|
|
103
|
+
nucleotides.includes(sequence[outputIndex]) &&
|
|
104
|
+
firstUniqueCharacters.includes(sequence[outputIndex - 2])
|
|
84
105
|
) break;
|
|
85
106
|
|
|
86
107
|
if ( // for mistake pattern 'ArA'
|
|
87
|
-
firstUniqueCharacters.includes(sequence[
|
|
88
|
-
nucleotides.includes(sequence[
|
|
108
|
+
firstUniqueCharacters.includes(sequence[outputIndex + 1]) &&
|
|
109
|
+
nucleotides.includes(sequence[outputIndex])
|
|
89
110
|
) {
|
|
90
|
-
|
|
111
|
+
outputIndex++;
|
|
91
112
|
break;
|
|
92
113
|
}
|
|
93
114
|
|
|
94
|
-
|
|
115
|
+
outputIndex += matchedCode.length;
|
|
95
116
|
}
|
|
96
117
|
});
|
|
97
118
|
|
|
98
|
-
const indexOfExpectedTechnology = Math.max(...outputIndices);
|
|
99
|
-
const expectedTechnology = possibleTechnologies[outputIndices.indexOf(indexOfExpectedTechnology)];
|
|
100
|
-
|
|
101
119
|
return {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
120
|
+
indexOfFirstNotValidChar: indexOfFirstNotValidChar,
|
|
121
|
+
synthesizer: possibleSynthesizers[0],
|
|
122
|
+
technology: possibleTechnologies[outputIndex],
|
|
105
123
|
};
|
|
106
124
|
}
|
|
107
125
|
|
|
@@ -140,93 +158,91 @@ function getListOfPossibleTechnologiesByFirstMatchedCode(sequence: string, synth
|
|
|
140
158
|
return technologies;
|
|
141
159
|
}
|
|
142
160
|
|
|
143
|
-
export function convertSequence(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const output = isValidSequence(seq);
|
|
147
|
-
if (output.indexOfFirstNotValidCharacter != -1) {
|
|
161
|
+
export function convertSequence(sequence: string, output: {
|
|
162
|
+
indexOfFirstNotValidChar: number, synthesizer: string | null, technology: string | null}) {
|
|
163
|
+
if (output.indexOfFirstNotValidChar != -1) {
|
|
148
164
|
return {
|
|
149
165
|
// type: '',
|
|
150
|
-
|
|
166
|
+
indexOfFirstNotValidChar: JSON.stringify(output),
|
|
151
167
|
Error: undefinedInputSequence,
|
|
152
168
|
};
|
|
153
169
|
}
|
|
154
|
-
if (output.
|
|
170
|
+
if (output.synthesizer == SYNTHESIZERS.RAW_NUCLEOTIDES && output.technology == TECHNOLOGIES.DNA) {
|
|
155
171
|
return {
|
|
156
172
|
type: SYNTHESIZERS.RAW_NUCLEOTIDES + ' ' + TECHNOLOGIES.DNA,
|
|
157
|
-
Nucleotides:
|
|
158
|
-
BioSpring: asoGapmersNucleotidesToBioSpring(
|
|
159
|
-
GCRS: asoGapmersNucleotidesToGcrs(
|
|
173
|
+
Nucleotides: sequence,
|
|
174
|
+
BioSpring: asoGapmersNucleotidesToBioSpring(sequence),
|
|
175
|
+
GCRS: asoGapmersNucleotidesToGcrs(sequence),
|
|
160
176
|
};
|
|
161
177
|
}
|
|
162
|
-
if (output.
|
|
178
|
+
if (output.synthesizer == SYNTHESIZERS.BIOSPRING && output.technology == TECHNOLOGIES.ASO_GAPMERS) {
|
|
163
179
|
return {
|
|
164
180
|
type: SYNTHESIZERS.BIOSPRING + ' ' + TECHNOLOGIES.ASO_GAPMERS,
|
|
165
|
-
Nucleotides: asoGapmersBioSpringToNucleotides(
|
|
166
|
-
BioSpring:
|
|
167
|
-
GCRS: asoGapmersBioSpringToGcrs(
|
|
181
|
+
Nucleotides: asoGapmersBioSpringToNucleotides(sequence),
|
|
182
|
+
BioSpring: sequence,
|
|
183
|
+
GCRS: asoGapmersBioSpringToGcrs(sequence),
|
|
168
184
|
};
|
|
169
185
|
}
|
|
170
|
-
if (output.
|
|
186
|
+
if (output.synthesizer == SYNTHESIZERS.GCRS && output.technology == TECHNOLOGIES.ASO_GAPMERS) {
|
|
171
187
|
return {
|
|
172
188
|
type: SYNTHESIZERS.GCRS + ' ' + TECHNOLOGIES.ASO_GAPMERS,
|
|
173
|
-
Nucleotides: asoGapmersGcrsToNucleotides(
|
|
174
|
-
BioSpring: asoGapmersGcrsToBioSpring(
|
|
175
|
-
Mermade12: gcrsToMermade12(
|
|
176
|
-
GCRS:
|
|
189
|
+
Nucleotides: asoGapmersGcrsToNucleotides(sequence),
|
|
190
|
+
BioSpring: asoGapmersGcrsToBioSpring(sequence),
|
|
191
|
+
Mermade12: gcrsToMermade12(sequence),
|
|
192
|
+
GCRS: sequence,
|
|
177
193
|
};
|
|
178
194
|
}
|
|
179
|
-
if (output.
|
|
195
|
+
if (output.synthesizer == SYNTHESIZERS.RAW_NUCLEOTIDES && output.technology == TECHNOLOGIES.RNA) {
|
|
180
196
|
return {
|
|
181
197
|
type: SYNTHESIZERS.RAW_NUCLEOTIDES + ' ' + TECHNOLOGIES.RNA,
|
|
182
|
-
Nucleotides:
|
|
183
|
-
BioSpring: siRnaNucleotideToBioSpringSenseStrand(
|
|
184
|
-
Axolabs: siRnaNucleotideToAxolabsSenseStrand(
|
|
185
|
-
GCRS: siRnaNucleotidesToGcrs(
|
|
198
|
+
Nucleotides: sequence,
|
|
199
|
+
BioSpring: siRnaNucleotideToBioSpringSenseStrand(sequence),
|
|
200
|
+
Axolabs: siRnaNucleotideToAxolabsSenseStrand(sequence),
|
|
201
|
+
GCRS: siRnaNucleotidesToGcrs(sequence),
|
|
186
202
|
};
|
|
187
203
|
}
|
|
188
|
-
if (output.
|
|
204
|
+
if (output.synthesizer == SYNTHESIZERS.BIOSPRING && output.technology == TECHNOLOGIES.SI_RNA) {
|
|
189
205
|
return {
|
|
190
206
|
type: SYNTHESIZERS.BIOSPRING + ' ' + TECHNOLOGIES.SI_RNA,
|
|
191
|
-
Nucleotides: siRnaBioSpringToNucleotides(
|
|
192
|
-
BioSpring:
|
|
193
|
-
Axolabs: siRnaBioSpringToAxolabs(
|
|
194
|
-
GCRS: siRnaBioSpringToGcrs(
|
|
207
|
+
Nucleotides: siRnaBioSpringToNucleotides(sequence),
|
|
208
|
+
BioSpring: sequence,
|
|
209
|
+
Axolabs: siRnaBioSpringToAxolabs(sequence),
|
|
210
|
+
GCRS: siRnaBioSpringToGcrs(sequence),
|
|
195
211
|
};
|
|
196
212
|
}
|
|
197
|
-
if (output.
|
|
213
|
+
if (output.synthesizer == SYNTHESIZERS.AXOLABS && output.technology == TECHNOLOGIES.SI_RNA) {
|
|
198
214
|
return {
|
|
199
215
|
type: SYNTHESIZERS.AXOLABS + ' ' + TECHNOLOGIES.SI_RNA,
|
|
200
|
-
Nucleotides: siRnaAxolabsToNucleotides(
|
|
201
|
-
BioSpring: siRnaAxolabsToBioSpring(
|
|
202
|
-
Axolabs:
|
|
203
|
-
GCRS: siRnaAxolabsToGcrs(
|
|
216
|
+
Nucleotides: siRnaAxolabsToNucleotides(sequence),
|
|
217
|
+
BioSpring: siRnaAxolabsToBioSpring(sequence),
|
|
218
|
+
Axolabs: sequence,
|
|
219
|
+
GCRS: siRnaAxolabsToGcrs(sequence),
|
|
204
220
|
};
|
|
205
221
|
}
|
|
206
|
-
if (output.
|
|
222
|
+
if (output.synthesizer == SYNTHESIZERS.GCRS && output.technology == TECHNOLOGIES.SI_RNA) {
|
|
207
223
|
return {
|
|
208
224
|
type: SYNTHESIZERS.GCRS + ' ' + TECHNOLOGIES.SI_RNA,
|
|
209
|
-
Nucleotides: siRnaGcrsToNucleotides(
|
|
210
|
-
BioSpring: siRnaGcrsToBioSpring(
|
|
211
|
-
Axolabs: siRnaGcrsToAxolabs(
|
|
212
|
-
MM12: gcrsToMermade12(
|
|
213
|
-
GCRS:
|
|
225
|
+
Nucleotides: siRnaGcrsToNucleotides(sequence),
|
|
226
|
+
BioSpring: siRnaGcrsToBioSpring(sequence),
|
|
227
|
+
Axolabs: siRnaGcrsToAxolabs(sequence),
|
|
228
|
+
MM12: gcrsToMermade12(sequence),
|
|
229
|
+
GCRS: sequence,
|
|
214
230
|
};
|
|
215
231
|
}
|
|
216
|
-
if (output.
|
|
232
|
+
if (output.synthesizer == SYNTHESIZERS.GCRS) {
|
|
217
233
|
return {
|
|
218
234
|
type: SYNTHESIZERS.GCRS,
|
|
219
|
-
Nucleotides: gcrsToNucleotides(
|
|
220
|
-
GCRS:
|
|
221
|
-
Mermade12: gcrsToMermade12(
|
|
235
|
+
Nucleotides: gcrsToNucleotides(sequence),
|
|
236
|
+
GCRS: sequence,
|
|
237
|
+
Mermade12: gcrsToMermade12(sequence),
|
|
222
238
|
};
|
|
223
239
|
}
|
|
224
|
-
if (output.
|
|
240
|
+
if (output.synthesizer == SYNTHESIZERS.MERMADE_12) {
|
|
225
241
|
return {
|
|
226
242
|
type: SYNTHESIZERS.MERMADE_12,
|
|
227
243
|
Nucleotides: noTranslationTableAvailable,
|
|
228
244
|
GCRS: noTranslationTableAvailable,
|
|
229
|
-
Mermade12:
|
|
245
|
+
Mermade12: sequence,
|
|
230
246
|
};
|
|
231
247
|
}
|
|
232
248
|
return {
|
|
@@ -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=c2bbc2b235db. Commit afc0e1c5.</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=
|
|
232
|
+
</style></head><body><div id="jesthtml-content"><header><h1 id="title">SequenceTranslator Test Report. Datagrok version datagrok/datagrok:latest SHA=c2bbc2b235db. Commit afc0e1c5.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-05-13 15:45:08</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 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 summary-empty">0 passed</div><div class="summary-failed">1 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">26.07s</div></div><div class="suite-tests"><div class="test-result failed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">failed</div><div class="test-duration">2.12s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: Evaluation failed: Unable to find JS function "test"
|
|
233
233
|
at ExecutionContext._evaluateInternal (/home/runner/work/public/public/packages/SequenceTranslator/node_modules/puppeteer/src/common/ExecutionContext.ts:273:13)
|
|
234
234
|
at processTicksAndRejections (internal/process/task_queues.js:97:5)
|
|
235
235
|
at ExecutionContext.evaluate (/home/runner/work/public/public/packages/SequenceTranslator/node_modules/puppeteer/src/common/ExecutionContext.ts:140:12)</pre></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)
|