@datagrok/sequence-translator 1.0.3 → 1.0.6
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 +26 -0
- package/dist/package-test.js +79 -67
- package/dist/package.js +768 -631
- package/package.json +28 -19
- package/src/__jest__/remote.test.ts +35 -16
- package/src/__jest__/test-node.ts +3 -2
- package/src/autostart/registration.ts +206 -0
- package/src/{axolabsMap.ts → axolabs/constants.ts} +1 -1
- package/src/{defineAxolabsPattern.ts → axolabs/define-pattern.ts} +87 -62
- package/src/{drawAxolabsPattern.ts → axolabs/draw-svg.ts} +1 -1
- package/src/main/main-view.ts +225 -0
- package/src/package.ts +11 -390
- package/src/structures-works/converters.ts +4 -1
- package/src/structures-works/from-monomers.ts +5 -4
- package/src/structures-works/map.ts +7 -0
- package/src/structures-works/mol-transformations.ts +19 -15
- package/src/structures-works/save-sense-antisense.ts +24 -11
- package/src/structures-works/sequence-codes-tools.ts +35 -27
- package/test-SequenceTranslator-d3cbf13cf137-2cb8277f.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,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.6",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Vadym Kovadlo",
|
|
7
|
+
"email": "vkovadlo@datagrok.ai"
|
|
8
|
+
},
|
|
5
9
|
"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
10
|
"repository": {
|
|
7
11
|
"type": "git",
|
|
@@ -10,46 +14,51 @@
|
|
|
10
14
|
},
|
|
11
15
|
"dependencies": {
|
|
12
16
|
"@datagrok-libraries/utils": "^0.1.0",
|
|
13
|
-
"@types/react": "
|
|
14
|
-
"datagrok-api": "^1.
|
|
17
|
+
"@types/react": "^18.0.15",
|
|
18
|
+
"datagrok-api": "^1.6.0",
|
|
15
19
|
"datagrok-tools": "^4.1.2",
|
|
16
20
|
"npm": "^8.11.0",
|
|
21
|
+
"openchemlib": "6.0.1",
|
|
17
22
|
"save-svg-as-png": "^1.4.17",
|
|
18
|
-
"ts-loader": "
|
|
19
|
-
"typescript": "
|
|
20
|
-
"openchemlib": "6.0.1"
|
|
23
|
+
"ts-loader": "^9.3.1",
|
|
24
|
+
"typescript": "^4.7.4"
|
|
21
25
|
},
|
|
22
26
|
"scripts": {
|
|
23
27
|
"link-api": "npm link datagrok-api",
|
|
24
|
-
"debug-sequencetranslator": "grok publish
|
|
25
|
-
"release-sequencetranslator": "grok publish
|
|
28
|
+
"debug-sequencetranslator": "grok publish",
|
|
29
|
+
"release-sequencetranslator": "grok publish localhost --release",
|
|
26
30
|
"build-sequencetranslator": "webpack",
|
|
27
31
|
"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 --
|
|
32
|
-
"test": "
|
|
32
|
+
"debug-sequencetranslator-public": "grok publish public",
|
|
33
|
+
"release-sequencetranslator-public": "grok publish public --release",
|
|
34
|
+
"debug-sequencetranslator-local": "grok publish local",
|
|
35
|
+
"release-sequencetranslator-local": "grok publish local --release",
|
|
36
|
+
"test": "jest",
|
|
33
37
|
"test-dev": "set HOST=dev && jest",
|
|
34
38
|
"test-local": "set HOST=localhost && jest"
|
|
35
39
|
},
|
|
36
40
|
"sources": [
|
|
37
41
|
"css/style.css",
|
|
38
|
-
"
|
|
42
|
+
"vendors/openchemlib-full.js"
|
|
39
43
|
],
|
|
40
44
|
"devDependencies": {
|
|
45
|
+
"@types/jest": "^27.0.0",
|
|
46
|
+
"@types/jquery": "^3.5.14",
|
|
41
47
|
"@typescript-eslint/eslint-plugin": "^4.29.1",
|
|
42
48
|
"@typescript-eslint/parser": "^4.29.1",
|
|
43
49
|
"cash-dom": "^8.1.0",
|
|
44
50
|
"eslint": "^7.32.0",
|
|
45
51
|
"eslint-config-google": "^0.14.0",
|
|
46
|
-
"webpack": "^5.31.0",
|
|
47
|
-
"webpack-cli": "^4.6.0",
|
|
48
|
-
"jest-html-reporter": "^3.5.0",
|
|
49
52
|
"jest": "^27.0.0",
|
|
50
|
-
"
|
|
53
|
+
"jest-html-reporter": "^3.5.0",
|
|
54
|
+
"puppeteer": "^13.7.0",
|
|
51
55
|
"ts-jest": "^27.0.0",
|
|
52
|
-
"
|
|
56
|
+
"webpack": "^5.31.0",
|
|
57
|
+
"webpack-cli": "^4.6.0",
|
|
58
|
+
"@types/js-yaml": "^4.0.5",
|
|
59
|
+
"js-yaml": "^4.1.0",
|
|
60
|
+
"@types/node-fetch": "^2.6.2",
|
|
61
|
+
"node-fetch": "^2.6.7"
|
|
53
62
|
},
|
|
54
63
|
"category": "Bioinformatics"
|
|
55
64
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as utils from './test-node';
|
|
6
6
|
import puppeteer from 'puppeteer';
|
|
7
7
|
|
|
8
|
-
const P_START_TIMEOUT: number =
|
|
8
|
+
const P_START_TIMEOUT: number = 3600000;
|
|
9
9
|
let browser: puppeteer.Browser;
|
|
10
10
|
let page: puppeteer.Page;
|
|
11
11
|
|
|
@@ -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 : Success : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
55
|
+
} else {
|
|
39
56
|
failed = true;
|
|
57
|
+
failReport += `Test result : Failed : ${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).
|
|
49
|
-
},
|
|
67
|
+
expect(r.failed).checkOutput(false, r.failReport);
|
|
68
|
+
}, 3600000);
|
|
@@ -67,6 +67,7 @@ export async function getBrowserPage(puppeteer: any): Promise<{browser: any, pag
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
let page = await browser.newPage();
|
|
70
|
+
await page.setDefaultNavigationTimeout(0);
|
|
70
71
|
await page.goto(`${url}/oauth/`);
|
|
71
72
|
await page.setCookie({name: 'auth', value: token});
|
|
72
73
|
await page.evaluate((token: any) => {
|
|
@@ -74,8 +75,8 @@ export async function getBrowserPage(puppeteer: any): Promise<{browser: any, pag
|
|
|
74
75
|
}, token);
|
|
75
76
|
await page.goto(url);
|
|
76
77
|
try {
|
|
77
|
-
await page.waitForSelector('.grok-preloader');
|
|
78
|
-
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout:
|
|
78
|
+
await page.waitForSelector('.grok-preloader', { timeout: 1800000 });
|
|
79
|
+
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout: 3600000});
|
|
79
80
|
} catch (error) {
|
|
80
81
|
throw error;
|
|
81
82
|
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as ui from 'datagrok-api/ui';
|
|
3
|
+
import * as DG from 'datagrok-api/dg';
|
|
4
|
+
import {siRnaAxolabsToGcrs, gcrsToNucleotides, asoGapmersBioSpringToGcrs, gcrsToMermade12,
|
|
5
|
+
} from '../structures-works/converters';
|
|
6
|
+
import {map, COL_NAMES, MODIFICATIONS} from '../structures-works/map';
|
|
7
|
+
import {getFormat, isValidSequence} from '../structures-works/sequence-codes-tools';
|
|
8
|
+
import {sequenceToMolV3000} from '../structures-works/from-monomers';
|
|
9
|
+
|
|
10
|
+
import {SALTS_CSV} from '../salts';
|
|
11
|
+
import {USERS_CSV} from '../users';
|
|
12
|
+
import {ICDS} from '../ICDs';
|
|
13
|
+
import {SOURCES} from '../sources';
|
|
14
|
+
import {IDPS} from '../IDPs';
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
function sortByStringLengthInDescendingOrder(array: string[]): string[] {
|
|
18
|
+
return array.sort(function(a, b) {return b.length - a.length;});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function stringify(items: string[]): string {
|
|
22
|
+
return '["' + items.join('", "') + '"]';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function molecularWeight(sequence: string, weightsObj: {[index: string]: number}): number {
|
|
26
|
+
const codes = sortByStringLengthInDescendingOrder(Object.keys(weightsObj)).concat(Object.keys(MODIFICATIONS));
|
|
27
|
+
let weight = 0;
|
|
28
|
+
let i = 0;
|
|
29
|
+
while (i < sequence.length) {
|
|
30
|
+
const matchedCode = codes.find((s) => s == sequence.slice(i, i + s.length))!;
|
|
31
|
+
weight += weightsObj[sequence.slice(i, i + matchedCode.length)];
|
|
32
|
+
i += matchedCode.length;
|
|
33
|
+
}
|
|
34
|
+
return weight - 61.97;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function saveTableAsSdFile(table: DG.DataFrame) {
|
|
38
|
+
if (!table.columns.contains('Compound Name')) {
|
|
39
|
+
grok.shell.warning(
|
|
40
|
+
'File saved without columns \'' +
|
|
41
|
+
[COL_NAMES.COMPOUND_NAME, COL_NAMES.COMPOUND_COMMENTS, COL_NAMES.CPD_MW,
|
|
42
|
+
COL_NAMES.SALT_MASS, COL_NAMES.BATCH_MW].join('\', \''),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
const structureColumn = table.getCol(COL_NAMES.SEQUENCE);
|
|
46
|
+
const typeColumn = table.getCol(COL_NAMES.TYPE);
|
|
47
|
+
let result = '';
|
|
48
|
+
for (let i = 0; i < table.rowCount; i++) {
|
|
49
|
+
const format = 'Janssen GCRS Codes'; //getFormat(structureColumn.get(i))!;
|
|
50
|
+
result += (typeColumn.get(i) == 'SS') ?
|
|
51
|
+
sequenceToMolV3000(structureColumn.get(i), false, true, format) + '\n' + `> <Sequence>\nSense Strand\n\n` :
|
|
52
|
+
sequenceToMolV3000(structureColumn.get(i), true, true, format) + '\n' + `> <Sequence>\nAnti Sense\n\n`;
|
|
53
|
+
for (const col of table.columns) {
|
|
54
|
+
if (col.name != COL_NAMES.SEQUENCE)
|
|
55
|
+
result += `> <${col.name}>\n${col.get(i)}\n\n`;
|
|
56
|
+
}
|
|
57
|
+
result += '$$$$\n\n';
|
|
58
|
+
}
|
|
59
|
+
const element = document.createElement('a');
|
|
60
|
+
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
|
|
61
|
+
element.setAttribute('download', table.name + '.sdf');
|
|
62
|
+
element.click();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function autostartOligoSdFileSubscription() {
|
|
66
|
+
grok.events.onViewAdded.subscribe((v: any) => {
|
|
67
|
+
if (v.type == 'TableView') {
|
|
68
|
+
if (v.dataFrame.columns.contains(COL_NAMES.TYPE))
|
|
69
|
+
oligoSdFile(v.dataFrame);
|
|
70
|
+
grok.events.onContextMenu.subscribe((args) => {
|
|
71
|
+
const seqCol = args.args.context.table.currentCol; // /^[fsACGUacgu]{6,}$/
|
|
72
|
+
if (DG.Detector.sampleCategories(seqCol,
|
|
73
|
+
(s) => /(\(invabasic\)|\(GalNAc-2-JNJ\)|f|s|A|C|G|U|a|c|g|u){6,}$/.test(s))) {
|
|
74
|
+
args.args.menu.item('Convert Axolabs to GCRS', () => {
|
|
75
|
+
args.args.context.table.columns.addNewString(seqCol.name + ' to GCRS').init((i: number) => {
|
|
76
|
+
return siRnaAxolabsToGcrs(seqCol.get(i));
|
|
77
|
+
});
|
|
78
|
+
}); // /^[fmpsACGU]{6,}$/
|
|
79
|
+
} else if (DG.Detector.sampleCategories(seqCol,
|
|
80
|
+
(s) => /(\(invabasic\)|\(GalNAc-2-JNJ\)|f|m|ps|A|C|G|U){6,}$/.test(s)) ||
|
|
81
|
+
DG.Detector.sampleCategories(seqCol, (s) => /^(?=.*moe)(?=.*5mC)(?=.*ps){6,}/.test(s))) {
|
|
82
|
+
args.args.menu.item('Convert GCRS to raw', () => {
|
|
83
|
+
args.args.context.table.columns.addNewString(seqCol.name + ' to raw').init((i: number) => {
|
|
84
|
+
return gcrsToNucleotides(seqCol.get(i));
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
args.args.menu.item('Convert GCRS to MM12', () => {
|
|
88
|
+
args.args.context.table.columns.addNewString(seqCol.name + ' to MM12').init((i: number) => {
|
|
89
|
+
return gcrsToMermade12(seqCol.get(i));
|
|
90
|
+
});
|
|
91
|
+
}); // /^[*56789ATGC]{6,}$/
|
|
92
|
+
} else if (DG.Detector.sampleCategories(seqCol,
|
|
93
|
+
(s) => /(\(invabasic\)|\(GalNAc-2-JNJ\)|\*|5|6|7|8|9|A|T|G|C){6,}$/.test(s))) {
|
|
94
|
+
args.args.menu.item('Convert Biospring to GCRS', () => {
|
|
95
|
+
const seqCol = args.args.context.table.currentCol;
|
|
96
|
+
args.args.context.table.columns.addNewString(seqCol.name + ' to GCRS').init((i: number) => {
|
|
97
|
+
return asoGapmersBioSpringToGcrs(seqCol.get(i));
|
|
98
|
+
});
|
|
99
|
+
}); // /^[*1-8]{6,}$/
|
|
100
|
+
} else if (DG.Detector.sampleCategories(seqCol,
|
|
101
|
+
(s) => /(\(invabasic\)|\(GalNAc-2-JNJ\)|\*|1|2|3|4|5|6|7|8){6,}$/.test(s))) {
|
|
102
|
+
args.args.menu.item('Convert Biospring to GCRS', () => {
|
|
103
|
+
args.args.context.table.columns.addNewString(seqCol.name + ' to GCRS').init((i: number) => {
|
|
104
|
+
return siRnaAxolabsToGcrs(seqCol.get(i));
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function oligoSdFile(table: DG.DataFrame) {
|
|
114
|
+
const saltsDf = DG.DataFrame.fromCsv(SALTS_CSV);
|
|
115
|
+
const usersDf = DG.DataFrame.fromCsv(USERS_CSV);
|
|
116
|
+
const sourcesDf = DG.DataFrame.fromCsv(SOURCES);
|
|
117
|
+
const icdsDf = DG.DataFrame.fromCsv(ICDS);
|
|
118
|
+
const idpsDf = DG.DataFrame.fromCsv(IDPS);
|
|
119
|
+
|
|
120
|
+
async function addColumns(t: DG.DataFrame, saltsDf: DG.DataFrame) {
|
|
121
|
+
if (t.columns.contains(COL_NAMES.COMPOUND_NAME))
|
|
122
|
+
return grok.shell.error('Columns already exist');
|
|
123
|
+
|
|
124
|
+
const sequenceCol = t.getCol(COL_NAMES.SEQUENCE);
|
|
125
|
+
const saltCol = t.getCol(COL_NAMES.SALT);
|
|
126
|
+
const equivalentsCol = t.getCol(COL_NAMES.EQUIVALENTS);
|
|
127
|
+
|
|
128
|
+
t.columns.addNewString(COL_NAMES.COMPOUND_NAME).init((i: number) => sequenceCol.get(i));
|
|
129
|
+
|
|
130
|
+
t.columns.addNewString(COL_NAMES.COMPOUND_COMMENTS).init((i: number) => (i > 0 && i % 2 == 0) ?
|
|
131
|
+
sequenceCol.get(i) + '; duplex of SS: ' + sequenceCol.get(i - 2) + ' and AS: ' + sequenceCol.get(i - 1) :
|
|
132
|
+
sequenceCol.get(i),
|
|
133
|
+
);
|
|
134
|
+
const molWeightCol = saltsDf.getCol('MOLWEIGHT');
|
|
135
|
+
const saltNamesList = saltsDf.getCol('DISPLAY').toList();
|
|
136
|
+
const weightsObj: {[code: string]: number} = {};
|
|
137
|
+
for (const synthesizer of Object.keys(map)) {
|
|
138
|
+
for (const technology of Object.keys(map[synthesizer])) {
|
|
139
|
+
for (const code of Object.keys(map[synthesizer][technology]))
|
|
140
|
+
weightsObj[code] = map[synthesizer][technology][code].weight!;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
for (const [key, value] of Object.entries(MODIFICATIONS))
|
|
144
|
+
weightsObj[key] = value.molecularWeight;
|
|
145
|
+
|
|
146
|
+
t.columns.addNewFloat(COL_NAMES.CPD_MW).init((i: number) => {
|
|
147
|
+
return (isValidSequence(sequenceCol.get(i), null).indexOfFirstNotValidChar == -1) ?
|
|
148
|
+
molecularWeight(sequenceCol.get(i), weightsObj) :
|
|
149
|
+
DG.FLOAT_NULL;
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
t.columns.addNewFloat(COL_NAMES.SALT_MASS).init((i: number) => {
|
|
153
|
+
const saltRowIndex = saltNamesList.indexOf(saltCol.get(i));
|
|
154
|
+
return (saltRowIndex == -1) ?
|
|
155
|
+
DG.FLOAT_NULL :
|
|
156
|
+
molWeightCol.get(saltRowIndex) * equivalentsCol.get(i);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
await t.columns.addNewCalculated(COL_NAMES.BATCH_MW,
|
|
160
|
+
'${' + COL_NAMES.CPD_MW + '} + ${' + COL_NAMES.SALT_MASS + '}', DG.COLUMN_TYPE.FLOAT, false,
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
addColumnsPressed = true;
|
|
164
|
+
return newDf = t;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
let newDf: DG.DataFrame;
|
|
168
|
+
let addColumnsPressed = false;
|
|
169
|
+
|
|
170
|
+
const d = ui.div([
|
|
171
|
+
ui.icons.edit(() => {
|
|
172
|
+
d.innerHTML = '';
|
|
173
|
+
if (table.getCol(COL_NAMES.IDP).type != DG.COLUMN_TYPE.STRING)
|
|
174
|
+
table.changeColumnType(COL_NAMES.IDP, DG.COLUMN_TYPE.STRING);
|
|
175
|
+
d.append(
|
|
176
|
+
ui.link('Add Columns', async () => {
|
|
177
|
+
await addColumns(table, saltsDf);
|
|
178
|
+
view.grid.columns.setOrder(Object.values(COL_NAMES));
|
|
179
|
+
}, 'Add columns: \'' + [COL_NAMES.COMPOUND_NAME, COL_NAMES.COMPOUND_COMMENTS, COL_NAMES.CPD_MW,
|
|
180
|
+
COL_NAMES.SALT_MASS, COL_NAMES.BATCH_MW].join('\', \''), '',
|
|
181
|
+
),
|
|
182
|
+
ui.button('Save SD file', () => saveTableAsSdFile(addColumnsPressed ? newDf : table)),
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const view = grok.shell.getTableView(table.name);
|
|
186
|
+
|
|
187
|
+
view.dataFrame.getCol(COL_NAMES.TYPE).setTag(DG.TAGS.CHOICES, '["AS", "SS", "Duplex"]');
|
|
188
|
+
view.dataFrame.getCol(COL_NAMES.OWNER).setTag(DG.TAGS.CHOICES, stringify(usersDf.columns.byIndex(0).toList()));
|
|
189
|
+
view.dataFrame.getCol(COL_NAMES.SALT).setTag(DG.TAGS.CHOICES, stringify(saltsDf.columns.byIndex(0).toList()));
|
|
190
|
+
view.dataFrame.getCol(COL_NAMES.SOURCE).setTag(DG.TAGS.CHOICES, stringify(sourcesDf.columns.byIndex(0).toList()));
|
|
191
|
+
view.dataFrame.getCol(COL_NAMES.ICD).setTag(DG.TAGS.CHOICES, stringify(icdsDf.columns.byIndex(0).toList()));
|
|
192
|
+
view.dataFrame.getCol(COL_NAMES.IDP).setTag(DG.TAGS.CHOICES, stringify(idpsDf.columns.byIndex(0).toList()));
|
|
193
|
+
|
|
194
|
+
grok.events.onContextMenu.subscribe((args) => {
|
|
195
|
+
if ([COL_NAMES.TYPE, COL_NAMES.OWNER, COL_NAMES.SALT, COL_NAMES.SOURCE, COL_NAMES.ICD, COL_NAMES.IDP]
|
|
196
|
+
.includes(args.args.context.table.currentCol.name)) {
|
|
197
|
+
args.args.menu.item('Fill Column With Value', () => {
|
|
198
|
+
const v = args.args.context.table.currentCell.value;
|
|
199
|
+
args.args.context.table.currentCell.column.init(v);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}),
|
|
204
|
+
]);
|
|
205
|
+
grok.shell.v.setRibbonPanels([[d]]);
|
|
206
|
+
}
|
|
@@ -94,7 +94,7 @@ export const axolabsMap:
|
|
|
94
94
|
color: invAbasicColor,
|
|
95
95
|
},
|
|
96
96
|
'2\'-OMe-U(o)': {
|
|
97
|
-
fullName: 'Nucleotide Uridine with 2
|
|
97
|
+
fullName: 'Nucleotide Uridine with 2\'O-Methyl protection (overhang)',
|
|
98
98
|
symbols: ['mU', 'mU', 'mU', 'mU'],
|
|
99
99
|
color: 'rgb(65,233,80)',
|
|
100
100
|
},
|