@datagrok/sequence-translator 1.0.3 → 1.0.4
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/detectors.js +24 -0
- package/dist/package-test.js +5 -16
- package/dist/package.js +159 -125
- package/package.json +8 -8
- package/src/__jest__/remote.test.ts +33 -14
- package/src/defineAxolabsPattern.ts +48 -24
- package/src/package.ts +33 -13
- package/src/structures-works/mol-transformations.ts +2 -2
- package/test-SequenceTranslator-4f0c8bae6479-18ff1615.html +276 -0
- package/vendors/openchemlib-full.js +293 -0
- package/webpack.config.js +1 -1
- package/test-SequenceTranslator-46784acc64a5-c67dd897.html +0 -245
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.4",
|
|
5
5
|
"description": "SequenceTranslator is a [package](https://datagrok.ai/help/develop/develop#packages) for the [Datagrok](https://datagrok.ai) platform, used to translate [oligonucleotide](https://en.wikipedia.org/wiki/Oligonucleotide) sequences between [different representations](https://github.com/datagrok-ai/public/tree/master/packages/SequenceTranslator#sequence-representations).",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -21,21 +21,21 @@
|
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
23
|
"link-api": "npm link datagrok-api",
|
|
24
|
-
"debug-sequencetranslator": "grok publish
|
|
25
|
-
"release-sequencetranslator": "grok publish
|
|
24
|
+
"debug-sequencetranslator": "grok publish",
|
|
25
|
+
"release-sequencetranslator": "grok publish localhost --release",
|
|
26
26
|
"build-sequencetranslator": "webpack",
|
|
27
27
|
"build": "webpack",
|
|
28
|
-
"debug-sequencetranslator-public": "grok publish public
|
|
29
|
-
"release-sequencetranslator-public": "grok publish public --
|
|
30
|
-
"debug-sequencetranslator-local": "grok publish local
|
|
31
|
-
"release-sequencetranslator-local": "grok publish local --
|
|
28
|
+
"debug-sequencetranslator-public": "grok publish public",
|
|
29
|
+
"release-sequencetranslator-public": "grok publish public --release",
|
|
30
|
+
"debug-sequencetranslator-local": "grok publish local",
|
|
31
|
+
"release-sequencetranslator-local": "grok publish local --release",
|
|
32
32
|
"test": "set HOST=dev && jest",
|
|
33
33
|
"test-dev": "set HOST=dev && jest",
|
|
34
34
|
"test-local": "set HOST=localhost && jest"
|
|
35
35
|
},
|
|
36
36
|
"sources": [
|
|
37
37
|
"css/style.css",
|
|
38
|
-
"
|
|
38
|
+
"vendors/openchemlib-full.js"
|
|
39
39
|
],
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@typescript-eslint/eslint-plugin": "^4.29.1",
|
|
@@ -16,34 +16,53 @@ beforeAll(async () => {
|
|
|
16
16
|
}, P_START_TIMEOUT);
|
|
17
17
|
|
|
18
18
|
afterAll(async () => {
|
|
19
|
-
await browser
|
|
19
|
+
await browser?.close();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
expect.extend({
|
|
23
|
+
checkOutput(received, expected, context) {
|
|
24
|
+
if (received === expected) {
|
|
25
|
+
return {
|
|
26
|
+
message: () => context,
|
|
27
|
+
pass: true
|
|
28
|
+
};
|
|
29
|
+
} else {
|
|
30
|
+
return {
|
|
31
|
+
message: () => context,
|
|
32
|
+
pass: false
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
20
36
|
});
|
|
21
37
|
|
|
22
38
|
it('TEST', async () => {
|
|
23
|
-
const
|
|
24
|
-
console.log(`Testing ${
|
|
39
|
+
const targetPackage:string = process.env.TARGET_PACKAGE ?? 'SequenceTranslator';
|
|
40
|
+
console.log(`Testing ${targetPackage} package`);
|
|
25
41
|
|
|
26
|
-
|
|
27
|
-
let r = await page.evaluate((target_package):Promise<object> => {
|
|
42
|
+
let r = await page.evaluate((targetPackage):Promise<object> => {
|
|
28
43
|
return new Promise<object>((resolve, reject) => {
|
|
29
|
-
(<any>window).grok.functions.eval(
|
|
44
|
+
(<any>window).grok.functions.eval(targetPackage + ':test()').then((df: any) => {
|
|
30
45
|
let cStatus = df.columns.byName('success');
|
|
31
46
|
let cMessage = df.columns.byName('result');
|
|
32
47
|
let cCat = df.columns.byName('category');
|
|
33
48
|
let cName = df.columns.byName('name');
|
|
34
49
|
let failed = false;
|
|
35
|
-
let
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
50
|
+
let passReport = '';
|
|
51
|
+
let failReport = '';
|
|
52
|
+
for (let i = 0; i < df.rowCount; i++) {
|
|
53
|
+
if (cStatus.get(i)) {
|
|
54
|
+
passReport += `Test result : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
55
|
+
} else {
|
|
39
56
|
failed = true;
|
|
57
|
+
failReport += `Test result : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
40
58
|
}
|
|
41
|
-
|
|
59
|
+
}
|
|
60
|
+
resolve({failReport, passReport, failed});
|
|
42
61
|
}).catch((e: any) => reject(e));
|
|
43
62
|
});
|
|
44
|
-
},
|
|
63
|
+
}, targetPackage);
|
|
45
64
|
// @ts-ignore
|
|
46
|
-
console.log(r.
|
|
65
|
+
console.log(r.passReport);
|
|
47
66
|
// @ts-ignore
|
|
48
|
-
expect(r.failed).
|
|
67
|
+
expect(r.failed).checkOutput(false, r.failReport);
|
|
49
68
|
}, 100000);
|
|
@@ -82,7 +82,9 @@ function addColumnWithIds(tableName: string, columnName: string, patternName: st
|
|
|
82
82
|
if (columns.contains(nameOfNewColumn))
|
|
83
83
|
columns.remove(nameOfNewColumn);
|
|
84
84
|
const columnWithIds = columns.byName(columnName);
|
|
85
|
-
return columns.addNewString(nameOfNewColumn).init((i: number) =>
|
|
85
|
+
return columns.addNewString(nameOfNewColumn).init((i: number) => {
|
|
86
|
+
return (columnWithIds.getString(i) == '') ? '' : columnWithIds.get(i) + '_' + patternName;
|
|
87
|
+
});
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
function addColumnWithTranslatedSequences(
|
|
@@ -99,8 +101,10 @@ function addColumnWithTranslatedSequences(
|
|
|
99
101
|
columns.remove(nameOfNewColumn);
|
|
100
102
|
const columnWithInputSequences = columns.byName(columnName);
|
|
101
103
|
return columns.addNewString(nameOfNewColumn).init((i: number) => {
|
|
102
|
-
return
|
|
103
|
-
|
|
104
|
+
return columnWithInputSequences.getString(i) == '' ?
|
|
105
|
+
'' :
|
|
106
|
+
translateSequence(columnWithInputSequences.getString(i), bases, ptoLinkages, startModification, endModification,
|
|
107
|
+
firstPtoExist);
|
|
104
108
|
});
|
|
105
109
|
}
|
|
106
110
|
|
|
@@ -332,7 +336,7 @@ export function defineAxolabsPattern() {
|
|
|
332
336
|
const col = tables.value!.columns.byName(colName);
|
|
333
337
|
let allLengthsAreTheSame = true;
|
|
334
338
|
for (let i = 1; i < col.length; i++) {
|
|
335
|
-
if (col.get(i - 1).length != col.get(i).length) {
|
|
339
|
+
if (col.get(i - 1).length != col.get(i).length && col.get(i).length != 0) {
|
|
336
340
|
allLengthsAreTheSame = false;
|
|
337
341
|
break;
|
|
338
342
|
}
|
|
@@ -361,12 +365,13 @@ export function defineAxolabsPattern() {
|
|
|
361
365
|
}
|
|
362
366
|
|
|
363
367
|
async function postPatternToUserStorage() {
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
saveAs.value
|
|
368
|
+
const currUserName = await getCurrentUserName();
|
|
369
|
+
saveAs.value = (saveAs.stringValue.includes('(created by ')) ?
|
|
370
|
+
getShortName(saveAs.value) + currUserName :
|
|
371
|
+
saveAs.stringValue + currUserName;
|
|
367
372
|
return grok.dapi.userDataStorage.postValue(
|
|
368
373
|
userStorageKey,
|
|
369
|
-
saveAs.
|
|
374
|
+
saveAs.value,
|
|
370
375
|
JSON.stringify({
|
|
371
376
|
'ssBases': ssBases.slice(0, ssLength.value!).map((e) => e.value),
|
|
372
377
|
'asBases': asBases.slice(0, asLength.value!).map((e) => e.value),
|
|
@@ -387,11 +392,12 @@ export function defineAxolabsPattern() {
|
|
|
387
392
|
const lstMy: string[] = [];
|
|
388
393
|
const lstOthers: string[] = [];
|
|
389
394
|
|
|
395
|
+
// TODO: display short name, but use long for querying userdataStorage
|
|
390
396
|
for (const ent of Object.keys(entities)) {
|
|
391
397
|
if (await isCurrentUserCreatedThisPattern(ent))
|
|
392
398
|
lstOthers.push(ent);
|
|
393
399
|
else
|
|
394
|
-
lstMy.push(getShortName(ent));
|
|
400
|
+
lstMy.push(ent);//getShortName(ent));
|
|
395
401
|
}
|
|
396
402
|
|
|
397
403
|
let loadPattern = ui.choiceInput('Load Pattern', '', lstMy, (v: string) => parsePatternAndUpdateUi(v));
|
|
@@ -526,7 +532,7 @@ export function defineAxolabsPattern() {
|
|
|
526
532
|
const col = tables.value!.columns.byName(colName);
|
|
527
533
|
if (col.type != DG.TYPE.INT)
|
|
528
534
|
grok.shell.error('Column should contain integers only');
|
|
529
|
-
else if (col.categories.length < col.length) {
|
|
535
|
+
else if (col.categories.filter((e) => e != '').length < col.toList().filter((e) => e != '').length) {
|
|
530
536
|
const duplicates = findDuplicates(col.getRawData());
|
|
531
537
|
ui.dialog('Non-unique IDs')
|
|
532
538
|
.add(ui.divText('Press \'OK\' to select rows with non-unique values'))
|
|
@@ -541,25 +547,43 @@ export function defineAxolabsPattern() {
|
|
|
541
547
|
}
|
|
542
548
|
|
|
543
549
|
const tables = ui.tableInput('Tables', grok.shell.tables[0], grok.shell.tables, (t: DG.DataFrame) => {
|
|
544
|
-
const inputSsColumn =
|
|
545
|
-
|
|
550
|
+
const inputSsColumn = ui.choiceInput('SS Column', '', t.columns.names(), (colName: string) => {
|
|
551
|
+
validateSsColumn(colName);
|
|
552
|
+
ssVar = colName;
|
|
553
|
+
});
|
|
546
554
|
inputSsColumnDiv.innerHTML = '';
|
|
547
555
|
inputSsColumnDiv.append(inputSsColumn.root);
|
|
548
|
-
const inputAsColumn =
|
|
549
|
-
|
|
556
|
+
const inputAsColumn = ui.choiceInput('AS Column', '', t.columns.names(), (colName: string) => {
|
|
557
|
+
validateAsColumn(colName);
|
|
558
|
+
asVar = colName;
|
|
559
|
+
});
|
|
550
560
|
inputAsColumnDiv.innerHTML = '';
|
|
551
561
|
inputAsColumnDiv.append(inputAsColumn.root);
|
|
552
|
-
const inputIdColumn =
|
|
553
|
-
|
|
562
|
+
const inputIdColumn = ui.choiceInput('ID Column', '', t.columns.names(), (colName: string) => {
|
|
563
|
+
validateIdsColumn(colName);
|
|
564
|
+
idVar = colName;
|
|
565
|
+
});
|
|
554
566
|
inputIdColumnDiv.innerHTML = '';
|
|
555
567
|
inputIdColumnDiv.append(inputIdColumn.root);
|
|
556
568
|
});
|
|
557
569
|
|
|
558
|
-
|
|
570
|
+
let ssVar = '';
|
|
571
|
+
const inputSsColumn = ui.choiceInput('SS Column', '', [], (colName: string) => {
|
|
572
|
+
validateSsColumn(colName);
|
|
573
|
+
ssVar = colName;
|
|
574
|
+
});
|
|
559
575
|
inputSsColumnDiv.append(inputSsColumn.root);
|
|
560
|
-
|
|
576
|
+
let asVar = '';
|
|
577
|
+
const inputAsColumn = ui.choiceInput('AS Column', '', [], (colName: string) => {
|
|
578
|
+
validateAsColumn(colName);
|
|
579
|
+
asVar = colName;
|
|
580
|
+
});
|
|
561
581
|
inputAsColumnDiv.append(inputAsColumn.root);
|
|
562
|
-
|
|
582
|
+
let idVar = '';
|
|
583
|
+
const inputIdColumn = ui.choiceInput('ID Column', '', [], (colName: string) => {
|
|
584
|
+
validateIdsColumn(colName);
|
|
585
|
+
idVar = colName;
|
|
586
|
+
});
|
|
563
587
|
inputIdColumnDiv.append(inputIdColumn.root);
|
|
564
588
|
|
|
565
589
|
updatePatternsList();
|
|
@@ -638,7 +662,7 @@ export function defineAxolabsPattern() {
|
|
|
638
662
|
});
|
|
639
663
|
|
|
640
664
|
const convertSequenceButton = ui.button('Convert Sequences', () => {
|
|
641
|
-
if (
|
|
665
|
+
if (ssVar == '' || (createAsStrand.value && asVar == ''))
|
|
642
666
|
grok.shell.info('Please select table and columns on which to apply pattern');
|
|
643
667
|
else if (ssLength.value != ssInputExample.value.length || asLength.value != asInputExample.value.length) {
|
|
644
668
|
const dialog = ui.dialog('Length Mismatch');
|
|
@@ -652,14 +676,14 @@ export function defineAxolabsPattern() {
|
|
|
652
676
|
})
|
|
653
677
|
.show();
|
|
654
678
|
} else {
|
|
655
|
-
if (
|
|
656
|
-
addColumnWithIds(tables.value!.name,
|
|
679
|
+
if (idVar != '')
|
|
680
|
+
addColumnWithIds(tables.value!.name, idVar, getShortName(saveAs.value));
|
|
657
681
|
addColumnWithTranslatedSequences(
|
|
658
|
-
tables.value!.name,
|
|
682
|
+
tables.value!.name, ssVar, ssBases, ssPtoLinkages,
|
|
659
683
|
ssFiveModification, ssThreeModification, firstSsPto.value!);
|
|
660
684
|
if (createAsStrand.value) {
|
|
661
685
|
addColumnWithTranslatedSequences(
|
|
662
|
-
tables.value!.name,
|
|
686
|
+
tables.value!.name, asVar, asBases, asPtoLinkages,
|
|
663
687
|
asFiveModification, asThreeModification, firstAsPto.value!);
|
|
664
688
|
}
|
|
665
689
|
grok.shell.v = grok.shell.getTableView(tables.value!.name);
|
package/src/package.ts
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import * as grok from 'datagrok-api/grok';
|
|
3
3
|
import * as ui from 'datagrok-api/ui';
|
|
4
4
|
import * as DG from 'datagrok-api/dg';
|
|
5
|
-
import * as OCL from 'openchemlib/full.js';
|
|
6
5
|
import $ from 'cash-dom';
|
|
7
6
|
import {defineAxolabsPattern} from './defineAxolabsPattern';
|
|
8
7
|
import {saveSenseAntiSense} from './structures-works/save-sense-antisense';
|
|
@@ -10,7 +9,8 @@ import {sequenceToSmiles, sequenceToMolV3000} from './structures-works/from-mono
|
|
|
10
9
|
import {convertSequence, undefinedInputSequence, isValidSequence, getFormat} from
|
|
11
10
|
'./structures-works/sequence-codes-tools';
|
|
12
11
|
import {map, COL_NAMES, MODIFICATIONS} from './structures-works/map';
|
|
13
|
-
import {siRnaAxolabsToGcrs
|
|
12
|
+
import {siRnaAxolabsToGcrs, gcrsToNucleotides, asoGapmersBioSpringToGcrs, gcrsToMermade12,
|
|
13
|
+
} from './structures-works/converters';
|
|
14
14
|
import {SALTS_CSV} from './salts';
|
|
15
15
|
import {USERS_CSV} from './users';
|
|
16
16
|
import {ICDS} from './ICDs';
|
|
@@ -309,23 +309,43 @@ function molecularWeight(sequence: string, weightsObj: {[index: string]: number}
|
|
|
309
309
|
|
|
310
310
|
//tags: autostart
|
|
311
311
|
export function autostartOligoSdFileSubscription() {
|
|
312
|
-
let alreadyAdded = false;
|
|
313
312
|
grok.events.onViewAdded.subscribe((v: any) => {
|
|
314
313
|
if (v.type == 'TableView') {
|
|
315
314
|
if (v.dataFrame.columns.contains(COL_NAMES.TYPE))
|
|
316
315
|
oligoSdFile(v.dataFrame);
|
|
317
316
|
grok.events.onContextMenu.subscribe((args) => {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
args.args.
|
|
322
|
-
|
|
323
|
-
args.args.context.table.columns.addNewString(seqCol.name + ' to GCRS').init((i: number) => {
|
|
324
|
-
return siRnaAxolabsToGcrs(seqCol.get(i));
|
|
325
|
-
});
|
|
317
|
+
const seqCol = args.args.context.table.currentCol;
|
|
318
|
+
if (DG.Detector.sampleCategories(seqCol, (s) => /^[fsACGUacgu]{6,}$/.test(s))) {
|
|
319
|
+
args.args.menu.item('Convert Axolabs to GCRS', () => {
|
|
320
|
+
args.args.context.table.columns.addNewString(seqCol.name + ' to GCRS').init((i: number) => {
|
|
321
|
+
return siRnaAxolabsToGcrs(seqCol.get(i));
|
|
326
322
|
});
|
|
327
|
-
|
|
328
|
-
|
|
323
|
+
});
|
|
324
|
+
} else if (DG.Detector.sampleCategories(seqCol, (s) => /^[fmpsACGU]{6,}$/.test(s)) ||
|
|
325
|
+
DG.Detector.sampleCategories(seqCol, (s) => /^(?=.*moe)(?=.*5mC)(?=.*ps){6,}/.test(s))) {
|
|
326
|
+
args.args.menu.item('Convert GCRS to raw', () => {
|
|
327
|
+
args.args.context.table.columns.addNewString(seqCol.name + ' to raw').init((i: number) => {
|
|
328
|
+
return gcrsToNucleotides(seqCol.get(i));
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
args.args.menu.item('Convert GCRS to MM12', () => {
|
|
332
|
+
args.args.context.table.columns.addNewString(seqCol.name + ' to MM12').init((i: number) => {
|
|
333
|
+
return gcrsToMermade12(seqCol.get(i));
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
} else if (DG.Detector.sampleCategories(seqCol, (s) => /^[*56789ATGC]{6,}$/.test(s))) {
|
|
337
|
+
args.args.menu.item('Convert Biospring to GCRS', () => {
|
|
338
|
+
const seqCol = args.args.context.table.currentCol;
|
|
339
|
+
args.args.context.table.columns.addNewString(seqCol.name + ' to GCRS').init((i: number) => {
|
|
340
|
+
return asoGapmersBioSpringToGcrs(seqCol.get(i));
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
} else if (DG.Detector.sampleCategories(seqCol, (s) => /^[*1-8]{6,}$/.test(s))) {
|
|
344
|
+
args.args.menu.item('Convert Biospring to GCRS', () => {
|
|
345
|
+
args.args.context.table.columns.addNewString(seqCol.name + ' to GCRS').init((i: number) => {
|
|
346
|
+
return siRnaAxolabsToGcrs(seqCol.get(i));
|
|
347
|
+
});
|
|
348
|
+
});
|
|
329
349
|
}
|
|
330
350
|
});
|
|
331
351
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import * as OCL from 'openchemlib/full.js';
|
|
2
|
-
|
|
3
1
|
const PHOSHATE = `
|
|
4
2
|
Datagrok monomer library Nucleotides
|
|
5
3
|
|
|
@@ -254,6 +252,7 @@ export function linkV3000(molBlocks: string[], twoChains: boolean = false, oclRe
|
|
|
254
252
|
}
|
|
255
253
|
|
|
256
254
|
function rotateNucleotidesV3000(molecule: string) {
|
|
255
|
+
// @ts-ignore
|
|
257
256
|
let molBlock = molecule.includes('M END') ? molecule : OCL.Molecule.fromSmiles(molecule).toMolfileV3();
|
|
258
257
|
const coordinates = extractAtomDataV3000(molBlock);
|
|
259
258
|
const natom = coordinates.atomIndex.length;
|
|
@@ -320,6 +319,7 @@ function rotateNucleotidesV3000(molecule: string) {
|
|
|
320
319
|
}
|
|
321
320
|
|
|
322
321
|
function invertNucleotidesV3000(molecule: string) {
|
|
322
|
+
// @ts-ignore
|
|
323
323
|
let molBlock = molecule.includes('M END') ? molecule : OCL.Molecule.fromSmiles(molecule).toMolfileV3();
|
|
324
324
|
const coordinates = extractAtomDataV3000(molBlock);
|
|
325
325
|
const natom = coordinates.atomIndex.length;
|