@datagrok/sequence-translator 0.0.4 → 0.0.5
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 +39 -0
- package/detectors.js +2 -12
- package/package.json +7 -3
- package/src/axolabsMap.ts +101 -99
- package/src/defineAxolabsPattern.ts +242 -207
- package/src/drawAxolabsPattern.ts +127 -92
- package/src/map.ts +530 -524
- package/src/package-test.ts +6 -7
- package/src/package.ts +430 -193
- package/src/save-sense-antisense.ts +36 -0
- package/src/tests/smiles-tests.ts +448 -7
package/src/package.ts
CHANGED
|
@@ -3,36 +3,38 @@ 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
5
|
import * as OCL from 'openchemlib/full.js';
|
|
6
|
-
import $ from
|
|
7
|
-
import {defineAxolabsPattern} from
|
|
8
|
-
import {
|
|
6
|
+
import $ from 'cash-dom';
|
|
7
|
+
import {defineAxolabsPattern} from './defineAxolabsPattern';
|
|
8
|
+
import {saveSenseAntiSense} from './save-sense-antisense';
|
|
9
|
+
import {map, stadardPhosphateLinkSmiles, SYNTHESIZERS, TECHNOLOGIES, MODIFICATIONS} from './map';
|
|
9
10
|
|
|
10
|
-
export
|
|
11
|
+
export const _package = new DG.Package();
|
|
11
12
|
|
|
12
|
-
const defaultInput =
|
|
13
|
-
const undefinedInputSequence =
|
|
14
|
-
const noTranslationTableAvailable =
|
|
13
|
+
const defaultInput = 'AGGTCCTCTTGACTTAGGCC';
|
|
14
|
+
const undefinedInputSequence = 'Type of input sequence is undefined';
|
|
15
|
+
const noTranslationTableAvailable = 'No translation table available';
|
|
15
16
|
const sequenceWasCopied = 'Copied';
|
|
16
17
|
const tooltipSequence = 'Copy sequence';
|
|
17
18
|
|
|
18
|
-
function getAllCodesOfSynthesizer(synthesizer: string) {
|
|
19
|
+
function getAllCodesOfSynthesizer(synthesizer: string): string[] {
|
|
19
20
|
let codes: string[] = [];
|
|
20
|
-
for (
|
|
21
|
+
for (const technology of Object.keys(map[synthesizer]))
|
|
21
22
|
codes = codes.concat(Object.keys(map[synthesizer][technology]));
|
|
22
23
|
return codes.concat(Object.keys(MODIFICATIONS));
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
function getListOfPossibleSynthesizersByFirstMatchedCode(sequence: string): string[] {
|
|
26
|
-
|
|
27
|
+
const synthesizers: string[] = [];
|
|
27
28
|
Object.keys(map).forEach((synthesizer: string) => {
|
|
28
29
|
const codes = getAllCodesOfSynthesizer(synthesizer);
|
|
29
30
|
//TODO: get first non-dropdown code when there are two modifications
|
|
30
31
|
let start = 0;
|
|
31
|
-
for (let i = 0; i < sequence.length; i++)
|
|
32
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
32
33
|
if (sequence[i] == ')') {
|
|
33
34
|
start = i + 1;
|
|
34
35
|
break;
|
|
35
36
|
}
|
|
37
|
+
}
|
|
36
38
|
if (codes.some((s: string) => s == sequence.slice(start, start + s.length)))
|
|
37
39
|
synthesizers.push(synthesizer);
|
|
38
40
|
});
|
|
@@ -40,7 +42,7 @@ function getListOfPossibleSynthesizersByFirstMatchedCode(sequence: string): stri
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
function getListOfPossibleTechnologiesByFirstMatchedCode(sequence: string, synthesizer: string): string[] {
|
|
43
|
-
|
|
45
|
+
const technologies: string[] = [];
|
|
44
46
|
Object.keys(map[synthesizer]).forEach((technology: string) => {
|
|
45
47
|
const codes = Object.keys(map[synthesizer][technology]).concat(Object.keys(MODIFICATIONS));
|
|
46
48
|
if (codes.some((s) => s == sequence.slice(0, s.length)))
|
|
@@ -49,32 +51,36 @@ function getListOfPossibleTechnologiesByFirstMatchedCode(sequence: string, synth
|
|
|
49
51
|
return technologies;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
function isValidSequence(sequence: string) {
|
|
53
|
-
|
|
54
|
+
export function isValidSequence(sequence: string): {
|
|
55
|
+
indexOfFirstNotValidCharacter: number,
|
|
56
|
+
expectedSynthesizer: string | null,
|
|
57
|
+
expectedTechnology: string | null
|
|
58
|
+
} {
|
|
59
|
+
const possibleSynthesizers = getListOfPossibleSynthesizersByFirstMatchedCode(sequence);
|
|
54
60
|
if (possibleSynthesizers.length == 0)
|
|
55
|
-
return {
|
|
61
|
+
return {indexOfFirstNotValidCharacter: 0, expectedSynthesizer: null, expectedTechnology: null};
|
|
56
62
|
|
|
57
63
|
let outputIndices = Array(possibleSynthesizers.length).fill(0);
|
|
58
64
|
|
|
59
|
-
const firstUniqueCharacters = ['r', 'd']
|
|
65
|
+
const firstUniqueCharacters = ['r', 'd'];
|
|
66
|
+
const nucleotides = ['A', 'U', 'T', 'C', 'G'];
|
|
60
67
|
|
|
61
68
|
possibleSynthesizers.forEach((synthesizer, synthesizerIndex) => {
|
|
62
|
-
|
|
69
|
+
const codes = getAllCodesOfSynthesizer(synthesizer);
|
|
63
70
|
while (outputIndices[synthesizerIndex] < sequence.length) {
|
|
64
|
-
|
|
65
|
-
let matchedCode = codes
|
|
71
|
+
const matchedCode = codes
|
|
66
72
|
.find((c) => c == sequence.slice(outputIndices[synthesizerIndex], outputIndices[synthesizerIndex] + c.length));
|
|
67
73
|
|
|
68
74
|
if (matchedCode == null)
|
|
69
75
|
break;
|
|
70
76
|
|
|
71
|
-
if (
|
|
77
|
+
if ( // for mistake pattern 'rAA'
|
|
72
78
|
outputIndices[synthesizerIndex] > 1 &&
|
|
73
79
|
nucleotides.includes(sequence[outputIndices[synthesizerIndex]]) &&
|
|
74
80
|
firstUniqueCharacters.includes(sequence[outputIndices[synthesizerIndex] - 2])
|
|
75
81
|
) break;
|
|
76
82
|
|
|
77
|
-
if (
|
|
83
|
+
if ( // for mistake pattern 'ArA'
|
|
78
84
|
firstUniqueCharacters.includes(sequence[outputIndices[synthesizerIndex] + 1]) &&
|
|
79
85
|
nucleotides.includes(sequence[outputIndices[synthesizerIndex]])
|
|
80
86
|
) {
|
|
@@ -92,16 +98,17 @@ function isValidSequence(sequence: string) {
|
|
|
92
98
|
if (indexOfFirstNotValidCharacter != -1)
|
|
93
99
|
return {
|
|
94
100
|
indexOfFirstNotValidCharacter: indexOfFirstNotValidCharacter,
|
|
95
|
-
|
|
101
|
+
expectedSynthesizer: expectedSynthesizer,
|
|
102
|
+
expectedTechnology: null
|
|
96
103
|
};
|
|
97
104
|
|
|
98
105
|
let possibleTechnologies = getListOfPossibleTechnologiesByFirstMatchedCode(sequence, expectedSynthesizer);
|
|
99
106
|
if (possibleTechnologies.length == 0)
|
|
100
|
-
return { indexOfFirstNotValidCharacter: 0,
|
|
107
|
+
return { indexOfFirstNotValidCharacter: 0, expectedSynthesizer: null, expectedTechnology: null };
|
|
101
108
|
|
|
102
109
|
outputIndices = Array(possibleTechnologies.length).fill(0);
|
|
103
110
|
|
|
104
|
-
possibleTechnologies.forEach((technology, technologyIndex) => {
|
|
111
|
+
possibleTechnologies.forEach((technology: string, technologyIndex: number) => {
|
|
105
112
|
let codes = Object.keys(map[expectedSynthesizer][technology]);
|
|
106
113
|
while (outputIndices[technologyIndex] < sequence.length) {
|
|
107
114
|
|
|
@@ -111,7 +118,7 @@ function isValidSequence(sequence: string) {
|
|
|
111
118
|
if (matchedCode == null)
|
|
112
119
|
break;
|
|
113
120
|
|
|
114
|
-
if (
|
|
121
|
+
if ( // for mistake pattern 'rAA'
|
|
115
122
|
outputIndices[technologyIndex] > 1 &&
|
|
116
123
|
nucleotides.includes(sequence[outputIndices[technologyIndex]]) &&
|
|
117
124
|
firstUniqueCharacters.includes(sequence[outputIndices[technologyIndex] - 2])
|
|
@@ -134,7 +141,8 @@ function isValidSequence(sequence: string) {
|
|
|
134
141
|
|
|
135
142
|
return {
|
|
136
143
|
indexOfFirstNotValidCharacter: indexOfFirstNotValidCharacter,
|
|
137
|
-
|
|
144
|
+
expectedSynthesizer: expectedSynthesizer,
|
|
145
|
+
expectedTechnology: expectedTechnology
|
|
138
146
|
};
|
|
139
147
|
}
|
|
140
148
|
|
|
@@ -142,39 +150,51 @@ function sortByStringLengthInDescendingOrder(array: string[]): string[] {
|
|
|
142
150
|
return array.sort(function(a: string, b: string) { return b.length - a.length; });
|
|
143
151
|
}
|
|
144
152
|
|
|
145
|
-
function getObjectWithCodesAndSmiles() {
|
|
146
|
-
|
|
147
|
-
for (
|
|
148
|
-
for (
|
|
153
|
+
function getObjectWithCodesAndSmiles(sequence: string) {
|
|
154
|
+
const obj: { [code: string]: string } = {};
|
|
155
|
+
for (const synthesizer of Object.keys(map))
|
|
156
|
+
for (const technology of Object.keys(map[synthesizer]))
|
|
149
157
|
for (let code of Object.keys(map[synthesizer][technology]))
|
|
150
158
|
obj[code] = map[synthesizer][technology][code].SMILES;
|
|
159
|
+
// TODO: create object based from synthesizer type to avoid key(codes) duplicates
|
|
160
|
+
const output = isValidSequence(sequence);
|
|
161
|
+
if (output.expectedSynthesizer == SYNTHESIZERS.MERMADE_12)
|
|
162
|
+
obj['g'] = map[SYNTHESIZERS.MERMADE_12][TECHNOLOGIES.SI_RNA]['g'].SMILES;
|
|
163
|
+
else if (output.expectedSynthesizer == SYNTHESIZERS.AXOLABS)
|
|
164
|
+
obj['g'] = map[SYNTHESIZERS.AXOLABS][TECHNOLOGIES.SI_RNA]['g'].SMILES;
|
|
151
165
|
return obj;
|
|
152
166
|
}
|
|
153
167
|
|
|
154
|
-
export function sequenceToSmiles(sequence: string) {
|
|
155
|
-
const obj = getObjectWithCodesAndSmiles();
|
|
168
|
+
export function sequenceToSmiles(sequence: string, inverted: boolean = false): string {
|
|
169
|
+
const obj = getObjectWithCodesAndSmiles(sequence);
|
|
156
170
|
let codes = sortByStringLengthInDescendingOrder(Object.keys(obj));
|
|
157
|
-
let i = 0
|
|
171
|
+
let i = 0;
|
|
172
|
+
let smiles = '';
|
|
173
|
+
const codesList = [];
|
|
158
174
|
const links = ['s', 'ps', '*'];
|
|
159
|
-
const includesStandardLinkAlready = [
|
|
175
|
+
const includesStandardLinkAlready = ['e', 'h', /*'g',*/ 'f', 'i', 'l', 'k', 'j'];
|
|
160
176
|
const dropdowns = Object.keys(MODIFICATIONS);
|
|
161
177
|
codes = codes.concat(dropdowns);
|
|
162
178
|
while (i < sequence.length) {
|
|
163
|
-
|
|
179
|
+
const code = codes.find((s: string) => s == sequence.slice(i, i + s.length))!;
|
|
164
180
|
i += code.length;
|
|
165
|
-
codesList.push(code);
|
|
181
|
+
inverted ? codesList.unshift(code) : codesList.push(code);
|
|
166
182
|
}
|
|
167
183
|
for (let i = 0; i < codesList.length; i++) {
|
|
168
184
|
if (dropdowns.includes(codesList[i])) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
185
|
+
if (i == codesList.length -1 || (i < codesList.length - 1 && links.includes(codesList[i + 1]))) {
|
|
186
|
+
smiles += (i >= codesList.length / 2) ?
|
|
187
|
+
MODIFICATIONS[codesList[i]].right:
|
|
188
|
+
MODIFICATIONS[codesList[i]].left;
|
|
189
|
+
} else if (i < codesList.length - 1) {
|
|
190
|
+
smiles += (i >= codesList.length / 2) ?
|
|
191
|
+
MODIFICATIONS[codesList[i]].right + stadardPhosphateLinkSmiles:
|
|
192
|
+
MODIFICATIONS[codesList[i]].left + stadardPhosphateLinkSmiles;
|
|
193
|
+
}
|
|
172
194
|
} else {
|
|
173
|
-
if (links.includes(codesList[i])
|
|
174
|
-
smiles = smiles.slice(0, smiles.length - stadardPhosphateLinkSmiles.length + 1);
|
|
175
|
-
else if (links.includes(codesList[i]) ||
|
|
195
|
+
if (links.includes(codesList[i]) ||
|
|
176
196
|
includesStandardLinkAlready.includes(codesList[i]) ||
|
|
177
|
-
(i < codesList.length - 1 &&
|
|
197
|
+
(i < codesList.length - 1 && links.includes(codesList[i + 1]))
|
|
178
198
|
)
|
|
179
199
|
smiles += obj[codesList[i]];
|
|
180
200
|
else
|
|
@@ -197,126 +217,221 @@ export function sequenceToSmiles(sequence: string) {
|
|
|
197
217
|
|
|
198
218
|
//name: Sequence Translator
|
|
199
219
|
//tags: app
|
|
200
|
-
export function sequenceTranslator() {
|
|
201
|
-
|
|
202
|
-
let windows = grok.shell.windows;
|
|
220
|
+
export function sequenceTranslator(): void {
|
|
221
|
+
const windows = grok.shell.windows;
|
|
203
222
|
windows.showProperties = false;
|
|
204
223
|
windows.showToolbox = false;
|
|
205
224
|
windows.showHelp = false;
|
|
206
225
|
|
|
207
|
-
function updateTableAndMolecule(sequence: string) {
|
|
208
|
-
moleculeSvgDiv.innerHTML =
|
|
209
|
-
outputTableDiv.innerHTML =
|
|
210
|
-
|
|
226
|
+
function updateTableAndMolecule(sequence: string): void {
|
|
227
|
+
moleculeSvgDiv.innerHTML = '';
|
|
228
|
+
outputTableDiv.innerHTML = '';
|
|
229
|
+
const pi = DG.TaskBarProgressIndicator.create('Rendering table and molecule...');
|
|
230
|
+
let errorsExist = false;
|
|
211
231
|
try {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
232
|
+
const outputSequenceObj = convertSequence(sequence);
|
|
233
|
+
const tableRows = [];
|
|
234
|
+
|
|
235
|
+
for (const key of Object.keys(outputSequenceObj).slice(1)) {
|
|
236
|
+
let indexOfFirstNotValidCharacter = ('indexOfFirstNotValidCharacter' in outputSequenceObj) ?
|
|
237
|
+
JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).indexOfFirstNotValidCharacter :
|
|
238
|
+
-1;
|
|
239
|
+
if ('indexOfFirstNotValidCharacter' in outputSequenceObj) {
|
|
240
|
+
let indexOfFirstNotValidCharacter = ('indexOfFirstNotValidCharacter' in outputSequenceObj) ?
|
|
241
|
+
JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).indexOfFirstNotValidCharacter :
|
|
242
|
+
-1;
|
|
243
|
+
if (indexOfFirstNotValidCharacter != -1)
|
|
244
|
+
errorsExist = true;
|
|
245
|
+
}
|
|
246
|
+
|
|
215
247
|
tableRows.push({
|
|
216
248
|
'key': key,
|
|
217
|
-
'value': (
|
|
249
|
+
'value': ('indexOfFirstNotValidCharacter' in outputSequenceObj) ?
|
|
218
250
|
ui.divH([
|
|
219
|
-
ui.divText(sequence.slice(0,
|
|
251
|
+
ui.divText(sequence.slice(0, indexOfFirstNotValidCharacter), {style: {color: 'grey'}}),
|
|
220
252
|
ui.tooltip.bind(
|
|
221
|
-
ui.divText(sequence.slice(
|
|
222
|
-
|
|
223
|
-
)
|
|
253
|
+
ui.divText(sequence.slice(indexOfFirstNotValidCharacter), {style: {color: 'red'}}),
|
|
254
|
+
'Expected format: ' + JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).expectedSynthesizer + '. See tables with valid codes on the right'
|
|
255
|
+
),
|
|
224
256
|
]) : //@ts-ignore
|
|
225
257
|
ui.link(outputSequenceObj[key], () => navigator.clipboard.writeText(outputSequenceObj[key]).then(() => grok.shell.info(sequenceWasCopied)), tooltipSequence, '')
|
|
226
|
-
})
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (errorsExist) {
|
|
262
|
+
const expectedSynthesizer = JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).expectedSynthesizer.slice(0, -6);
|
|
263
|
+
asoGapmersGrid.onCellPrepare(function (gc) {
|
|
264
|
+
gc.style.backColor = (gc.gridColumn.name == expectedSynthesizer) ? 0xFFF00000 : 0xFFFFFFFF;
|
|
265
|
+
});
|
|
266
|
+
omeAndFluoroGrid.onCellPrepare(function (gc) {
|
|
267
|
+
gc.style.backColor = (gc.gridColumn.name == expectedSynthesizer) ? 0xFFF00000 : 0xFFFFFFFF;
|
|
268
|
+
});
|
|
269
|
+
switchInput.enabled = true;
|
|
270
|
+
} else {
|
|
271
|
+
asoGapmersGrid.onCellPrepare(function (gc) {
|
|
272
|
+
gc.style.backColor = 0xFFFFFFFF;
|
|
273
|
+
});
|
|
274
|
+
omeAndFluoroGrid.onCellPrepare(function (gc) {
|
|
275
|
+
gc.style.backColor = 0xFFFFFFFF;
|
|
276
|
+
});
|
|
227
277
|
}
|
|
278
|
+
|
|
228
279
|
outputTableDiv.append(
|
|
229
|
-
ui.div([
|
|
280
|
+
ui.div([
|
|
281
|
+
DG.HtmlTable.create(tableRows, (item: { key: string; value: string; }) => [item.key, item.value], ['Code', 'Sequence']).root
|
|
282
|
+
], 'table')
|
|
230
283
|
);
|
|
231
284
|
semTypeOfInputSequence.textContent = 'Detected input type: ' + outputSequenceObj.type;
|
|
232
285
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
286
|
+
if (outputSequenceObj.type != undefinedInputSequence && outputSequenceObj.Error != undefinedInputSequence) {
|
|
287
|
+
let canvas = ui.canvas(300, 170);
|
|
288
|
+
canvas.addEventListener("click", () => {
|
|
289
|
+
let canv = ui.canvas($(window).width(), $(window).height());
|
|
290
|
+
const smiles = sequenceToSmiles(inputSequenceField.value.replace(/\s/g, ''));
|
|
291
|
+
// @ts-ignore
|
|
292
|
+
OCL.StructureView.drawMolecule(canv, OCL.Molecule.fromSmiles(smiles), { suppressChiralText: true });
|
|
293
|
+
ui.dialog('Molecule')
|
|
294
|
+
.add(canv)
|
|
295
|
+
.showModal(true);
|
|
296
|
+
});
|
|
297
|
+
$(canvas).on('mouseover', () => $(canvas).css('cursor', 'zoom-in'));
|
|
298
|
+
$(canvas).on('mouseout', () => $(canvas).css('cursor', 'default'));
|
|
299
|
+
const smiles = sequenceToSmiles(inputSequenceField.value.replace(/\s/g, ''));
|
|
300
|
+
// @ts-ignore
|
|
301
|
+
OCL.StructureView.drawMolecule(canvas, OCL.Molecule.fromSmiles(smiles), { suppressChiralText: true });
|
|
239
302
|
moleculeSvgDiv.append(canvas);
|
|
303
|
+
} else
|
|
304
|
+
moleculeSvgDiv.innerHTML = '';
|
|
240
305
|
} finally {
|
|
241
306
|
pi.close();
|
|
242
307
|
}
|
|
243
308
|
}
|
|
244
309
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
let showCodesButton = ui.button('SHOW CODES', () => ui.dialog('Codes').add(tablesWithCodes).show());
|
|
271
|
-
let copySmiles = ui.button(
|
|
272
|
-
'COPY SMILES',
|
|
273
|
-
() => navigator.clipboard.writeText(sequenceToSmiles(inputSequenceField.value.replace(/\s/g, '')))
|
|
274
|
-
.then(() => grok.shell.info(sequenceWasCopied))
|
|
310
|
+
const semTypeOfInputSequence = ui.divText('');
|
|
311
|
+
const moleculeSvgDiv = ui.block([]);
|
|
312
|
+
const outputTableDiv = ui.div([], 'table');
|
|
313
|
+
const inputSequenceField = ui.textInput('', defaultInput, (sequence: string) => updateTableAndMolecule(sequence));
|
|
314
|
+
|
|
315
|
+
const asoDf = DG.DataFrame.fromObjects([
|
|
316
|
+
{ Name: "2'MOE-5Me-rU", BioSpring: "5", "Janssen GCRS": "moeT" },
|
|
317
|
+
{ Name: "2'MOE-rA", BioSpring: "6", "Janssen GCRS": "moeA" },
|
|
318
|
+
{ Name: "2'MOE-5Me-rC", BioSpring: "7", "Janssen GCRS": "moe5mC" },
|
|
319
|
+
{ Name: "2'MOE-rG", BioSpring: "8", "Janssen GCRS": "moeG" },
|
|
320
|
+
{ Name: "5-Methyl-dC", BioSpring: "9", "Janssen GCRS": "5mC" },
|
|
321
|
+
{ Name: "ps linkage", BioSpring: "*", "Janssen GCRS": "ps" },
|
|
322
|
+
{ Name: "dA", BioSpring: "A", "Janssen GCRS": "A, dA" },
|
|
323
|
+
{ Name: "dC", BioSpring: "C", "Janssen GCRS": "C, dC" },
|
|
324
|
+
{ Name: "dG", BioSpring: "G", "Janssen GCRS": "G, dG" },
|
|
325
|
+
{ Name: "dT", BioSpring: "T", "Janssen GCRS": "T, dT" },
|
|
326
|
+
{ Name: "rA", BioSpring: "", "Janssen GCRS": "rA" },
|
|
327
|
+
{ Name: "rC", BioSpring: "", "Janssen GCRS": "rC" },
|
|
328
|
+
{ Name: "rG", BioSpring: "", "Janssen GCRS": "rG" },
|
|
329
|
+
{ Name: "rU", BioSpring: "", "Janssen GCRS": "rU" }
|
|
330
|
+
])!;
|
|
331
|
+
const asoGapmersGrid = DG.Viewer.grid(
|
|
332
|
+
asoDf, { showRowHeader: false, showCellTooltip: false }
|
|
275
333
|
);
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
let element = document.createElement('a');
|
|
280
|
-
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
|
|
281
|
-
element.setAttribute('download', inputSequenceField.value.replace(/\s/g, '') + '.mol');
|
|
282
|
-
element.click();
|
|
334
|
+
|
|
335
|
+
asoDf.onCurrentCellChanged.subscribe((_) => {
|
|
336
|
+
navigator.clipboard.writeText(asoDf.currentCell.value).then(() => grok.shell.info('Copied'))
|
|
283
337
|
});
|
|
284
338
|
|
|
339
|
+
let omeAndFluoroGrid = DG.Viewer.grid(
|
|
340
|
+
DG.DataFrame.fromObjects([
|
|
341
|
+
{ Name: "2'-fluoro-U", BioSpring: "1", Axolabs: "Uf", "Janssen GCRS": "fU" },
|
|
342
|
+
{ Name: "2'-fluoro-A", BioSpring: "2", Axolabs: "Af", "Janssen GCRS": "fA" },
|
|
343
|
+
{ Name: "2'-fluoro-C", BioSpring: "3", Axolabs: "Cf", "Janssen GCRS": "fC" },
|
|
344
|
+
{ Name: "2'-fluoro-G", BioSpring: "4", Axolabs: "Gf", "Janssen GCRS": "fG" },
|
|
345
|
+
{ Name: "2'OMe-rU", BioSpring: "5", Axolabs: "u", "Janssen GCRS": "mU" },
|
|
346
|
+
{ Name: "2'OMe-rA", BioSpring: "6", Axolabs: "a", "Janssen GCRS": "mA" },
|
|
347
|
+
{ Name: "2'OMe-rC", BioSpring: "7", Axolabs: "c", "Janssen GCRS": "mC" },
|
|
348
|
+
{ Name: "2'OMe-rG", BioSpring: "8", Axolabs: "g", "Janssen GCRS": "mG" },
|
|
349
|
+
{ Name: "ps linkage", BioSpring: "*", Axolabs: "s", "Janssen GCRS": "ps" }
|
|
350
|
+
])!, { showRowHeader: false, showCellTooltip: false }
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
const overhangModificationsGrid = DG.Viewer.grid(
|
|
354
|
+
DG.DataFrame.fromObjects([
|
|
355
|
+
{ Name: "(invabasic)" },
|
|
356
|
+
{ Name: "(GalNAc-2-JNJ)" }
|
|
357
|
+
])!, { showRowHeader: false, showCellTooltip: false }
|
|
358
|
+
);
|
|
359
|
+
updateTableAndMolecule(defaultInput);
|
|
360
|
+
|
|
285
361
|
const appMainDescription = ui.info([
|
|
286
|
-
ui.divText('
|
|
287
|
-
ui.divText(
|
|
362
|
+
ui.divText('How to convert one sequence:',{style:{'font-weight':'bolder'}}),
|
|
363
|
+
ui.divText('Paste sequence into the text field below'),
|
|
288
364
|
ui.divText('\n How to convert many sequences:',{style:{'font-weight':'bolder'}}),
|
|
289
|
-
ui.divText(
|
|
365
|
+
ui.divText('1. Drag & drop an Excel or CSV file with sequences into Datagrok. The platform will automatically detect columns with sequences'),
|
|
290
366
|
ui.divText('2. Right-click on the column header, then see the \'Convert\' menu'),
|
|
291
|
-
ui.divText(
|
|
367
|
+
ui.divText('This will add the result column to the right of the table'),
|
|
292
368
|
], 'Convert oligonucleotide sequences between Nucleotides, BioSpring, Axolabs, Mermade 12 and GCRS representations.'
|
|
293
369
|
);
|
|
294
370
|
|
|
295
|
-
|
|
296
|
-
ui.
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
371
|
+
const codesTablesDiv = ui.splitV([
|
|
372
|
+
ui.box(ui.h2('ASO Gapmers'), { style: {maxHeight: '40px'} }),
|
|
373
|
+
asoGapmersGrid.root,
|
|
374
|
+
ui.box(ui.h2("2'-OMe and 2'-F siRNA"), { style: {maxHeight: '40px'} }),
|
|
375
|
+
omeAndFluoroGrid.root,
|
|
376
|
+
ui.box(ui.h2('Overhang modifications'), { style: {maxHeight: '40px'} }),
|
|
377
|
+
overhangModificationsGrid.root
|
|
378
|
+
], { style: { maxWidth: '350px' } });
|
|
379
|
+
|
|
380
|
+
const tabControl = ui.tabControl({
|
|
381
|
+
'MAIN': ui.box(
|
|
382
|
+
ui.splitH([
|
|
383
|
+
ui.splitV([
|
|
384
|
+
ui.panel([
|
|
385
|
+
appMainDescription,
|
|
302
386
|
ui.div([
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
387
|
+
ui.h1('Input sequence'),
|
|
388
|
+
ui.div([
|
|
389
|
+
inputSequenceField.root,
|
|
390
|
+
], 'input-base'),
|
|
391
|
+
], 'sequenceInput'),
|
|
392
|
+
semTypeOfInputSequence,
|
|
393
|
+
ui.block([
|
|
394
|
+
ui.h1('Output'),
|
|
395
|
+
outputTableDiv,
|
|
396
|
+
]),
|
|
397
|
+
moleculeSvgDiv,
|
|
398
|
+
], 'sequence'),
|
|
399
|
+
]),
|
|
400
|
+
codesTablesDiv,
|
|
401
|
+
], {style: {height: '100%', width: '100%'}}),
|
|
402
|
+
),
|
|
403
|
+
'AXOLABS': defineAxolabsPattern(),
|
|
404
|
+
'SDF': saveSenseAntiSense(),
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
let v = grok.shell.newView('Sequence Translator', [tabControl]);
|
|
318
408
|
v.box = true;
|
|
319
409
|
|
|
410
|
+
const switchInput = ui.switchInput('Codes', true, (v: boolean) => (v) ?
|
|
411
|
+
$(codesTablesDiv).show() :
|
|
412
|
+
$(codesTablesDiv).hide()
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
const topPanel = [
|
|
416
|
+
ui.iconFA('download', () => {
|
|
417
|
+
const smiles = sequenceToSmiles(inputSequenceField.value.replace(/\s/g, ''));
|
|
418
|
+
const result = `${OCL.Molecule.fromSmiles(smiles).toMolfile()}\n`;
|
|
419
|
+
const element = document.createElement('a');
|
|
420
|
+
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
|
|
421
|
+
element.setAttribute('download', inputSequenceField.value.replace(/\s/g, '') + '.mol');
|
|
422
|
+
element.click();
|
|
423
|
+
}, 'Save .mol file'),
|
|
424
|
+
ui.iconFA('copy', () => {
|
|
425
|
+
navigator.clipboard.writeText(sequenceToSmiles(inputSequenceField.value.replace(/\s/g, '')))
|
|
426
|
+
.then(() => grok.shell.info(sequenceWasCopied));
|
|
427
|
+
}, 'Copy SMILES'),
|
|
428
|
+
switchInput.root,
|
|
429
|
+
];
|
|
430
|
+
|
|
431
|
+
tabControl.onTabChanged.subscribe((_) =>
|
|
432
|
+
v.setRibbonPanels([(tabControl.currentPane.name == 'MAIN') ? topPanel : []]));
|
|
433
|
+
v.setRibbonPanels([topPanel]);
|
|
434
|
+
|
|
320
435
|
$('.sequence')
|
|
321
436
|
.children().css('padding','5px 0');
|
|
322
437
|
$('.sequenceInput .input-base')
|
|
@@ -325,7 +440,7 @@ export function sequenceTranslator() {
|
|
|
325
440
|
.css('resize','none')
|
|
326
441
|
.css('min-height','50px')
|
|
327
442
|
.css('width','100%')
|
|
328
|
-
.attr(
|
|
443
|
+
.attr('spellcheck', 'false');
|
|
329
444
|
$('.sequenceInput select')
|
|
330
445
|
.css('width','100%');
|
|
331
446
|
}
|
|
@@ -336,24 +451,25 @@ function convertSequence(text: string) {
|
|
|
336
451
|
let output = isValidSequence(seq);
|
|
337
452
|
if (output.indexOfFirstNotValidCharacter != -1)
|
|
338
453
|
return {
|
|
454
|
+
// type: '',
|
|
339
455
|
indexOfFirstNotValidCharacter: JSON.stringify(output),
|
|
340
456
|
Error: undefinedInputSequence
|
|
341
457
|
};
|
|
342
|
-
if (output.
|
|
458
|
+
if (output.expectedSynthesizer == SYNTHESIZERS.RAW_NUCLEOTIDES && output.expectedTechnology == TECHNOLOGIES.DNA)
|
|
343
459
|
return {
|
|
344
460
|
type: SYNTHESIZERS.RAW_NUCLEOTIDES + ' ' + TECHNOLOGIES.DNA,
|
|
345
461
|
Nucleotides: seq,
|
|
346
462
|
BioSpring: asoGapmersNucleotidesToBioSpring(seq),
|
|
347
463
|
GCRS: asoGapmersNucleotidesToGcrs(seq)
|
|
348
464
|
};
|
|
349
|
-
if (output.
|
|
465
|
+
if (output.expectedSynthesizer == SYNTHESIZERS.BIOSPRING && output.expectedTechnology == TECHNOLOGIES.ASO_GAPMERS)
|
|
350
466
|
return {
|
|
351
467
|
type: SYNTHESIZERS.BIOSPRING + ' ' + TECHNOLOGIES.ASO_GAPMERS,
|
|
352
468
|
Nucleotides: asoGapmersBioSpringToNucleotides(seq),
|
|
353
469
|
BioSpring: seq,
|
|
354
470
|
GCRS: asoGapmersBioSpringToGcrs(seq)
|
|
355
471
|
};
|
|
356
|
-
if (output.
|
|
472
|
+
if (output.expectedSynthesizer == SYNTHESIZERS.GCRS && output.expectedTechnology == TECHNOLOGIES.ASO_GAPMERS)
|
|
357
473
|
return {
|
|
358
474
|
type: SYNTHESIZERS.GCRS + ' ' + TECHNOLOGIES.ASO_GAPMERS,
|
|
359
475
|
Nucleotides: asoGapmersGcrsToNucleotides(seq),
|
|
@@ -361,7 +477,7 @@ function convertSequence(text: string) {
|
|
|
361
477
|
Mermade12: gcrsToMermade12(seq),
|
|
362
478
|
GCRS: seq
|
|
363
479
|
};
|
|
364
|
-
if (output.
|
|
480
|
+
if (output.expectedSynthesizer == SYNTHESIZERS.RAW_NUCLEOTIDES && output.expectedTechnology == TECHNOLOGIES.RNA)
|
|
365
481
|
return {
|
|
366
482
|
type: SYNTHESIZERS.RAW_NUCLEOTIDES + ' ' + TECHNOLOGIES.RNA,
|
|
367
483
|
Nucleotides: seq,
|
|
@@ -369,7 +485,7 @@ function convertSequence(text: string) {
|
|
|
369
485
|
Axolabs: siRnaNucleotideToAxolabsSenseStrand(seq),
|
|
370
486
|
GCRS: siRnaNucleotidesToGcrs(seq)
|
|
371
487
|
};
|
|
372
|
-
if (output.
|
|
488
|
+
if (output.expectedSynthesizer == SYNTHESIZERS.BIOSPRING && output.expectedTechnology == TECHNOLOGIES.SI_RNA)
|
|
373
489
|
return {
|
|
374
490
|
type: SYNTHESIZERS.BIOSPRING + ' ' + TECHNOLOGIES.SI_RNA,
|
|
375
491
|
Nucleotides: siRnaBioSpringToNucleotides(seq),
|
|
@@ -377,7 +493,7 @@ function convertSequence(text: string) {
|
|
|
377
493
|
Axolabs: siRnaBioSpringToAxolabs(seq),
|
|
378
494
|
GCRS: siRnaBioSpringToGcrs(seq)
|
|
379
495
|
};
|
|
380
|
-
if (output.
|
|
496
|
+
if (output.expectedSynthesizer == SYNTHESIZERS.AXOLABS && output.expectedTechnology == TECHNOLOGIES.SI_RNA)
|
|
381
497
|
return {
|
|
382
498
|
type: SYNTHESIZERS.AXOLABS + ' ' + TECHNOLOGIES.SI_RNA,
|
|
383
499
|
Nucleotides: siRnaAxolabsToNucleotides(seq),
|
|
@@ -385,7 +501,7 @@ function convertSequence(text: string) {
|
|
|
385
501
|
Axolabs: seq,
|
|
386
502
|
GCRS: siRnaAxolabsToGcrs(seq)
|
|
387
503
|
};
|
|
388
|
-
if (output.
|
|
504
|
+
if (output.expectedSynthesizer == SYNTHESIZERS.GCRS && output.expectedTechnology == TECHNOLOGIES.SI_RNA)
|
|
389
505
|
return {
|
|
390
506
|
type: SYNTHESIZERS.GCRS + ' ' + TECHNOLOGIES.SI_RNA,
|
|
391
507
|
Nucleotides: siRnaGcrsToNucleotides(seq),
|
|
@@ -394,14 +510,14 @@ function convertSequence(text: string) {
|
|
|
394
510
|
MM12: gcrsToMermade12(seq),
|
|
395
511
|
GCRS: seq
|
|
396
512
|
};
|
|
397
|
-
if (output.
|
|
513
|
+
if (output.expectedSynthesizer == SYNTHESIZERS.GCRS)
|
|
398
514
|
return {
|
|
399
515
|
type: SYNTHESIZERS.GCRS,
|
|
400
516
|
Nucleotides: gcrsToNucleotides(seq),
|
|
401
517
|
GCRS: seq,
|
|
402
518
|
Mermade12: gcrsToMermade12(seq)
|
|
403
519
|
}
|
|
404
|
-
if (output.
|
|
520
|
+
if (output.expectedSynthesizer == SYNTHESIZERS.MERMADE_12)
|
|
405
521
|
return {
|
|
406
522
|
type: SYNTHESIZERS.MERMADE_12,
|
|
407
523
|
Nucleotides: noTranslationTableAvailable,
|
|
@@ -417,47 +533,47 @@ function convertSequence(text: string) {
|
|
|
417
533
|
//name: asoGapmersNucleotidesToBioSpring
|
|
418
534
|
//input: string nucleotides {semType: DNA nucleotides}
|
|
419
535
|
//output: string result {semType: BioSpring / Gapmers}
|
|
420
|
-
export function asoGapmersNucleotidesToBioSpring(nucleotides: string) {
|
|
536
|
+
export function asoGapmersNucleotidesToBioSpring(nucleotides: string): string {
|
|
421
537
|
let count: number = -1;
|
|
422
|
-
const objForEdges: {[index: string]: string} = {
|
|
423
|
-
const objForCenter: {[index: string]: string} = {
|
|
538
|
+
const objForEdges: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'T': '5*', 'A': '6*', 'C': '7*', 'G': '8*'};
|
|
539
|
+
const objForCenter: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'T': 'T*', 'A': 'A*', 'C': '9*', 'G': 'G*'};
|
|
424
540
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|T|C|G)/g, function (x: string) {
|
|
425
541
|
count++;
|
|
426
542
|
return (count > 4 && count < 15) ? objForCenter[x] : objForEdges[x];
|
|
427
|
-
}).slice(0, (nucleotides.endsWith(
|
|
543
|
+
}).slice(0, (nucleotides.endsWith('(invabasic)') || nucleotides.endsWith('(GalNAc-2-JNJ)')) ? nucleotides.length : 2 * count + 1);
|
|
428
544
|
}
|
|
429
545
|
|
|
430
546
|
//name: asoGapmersNucleotidesToGcrs
|
|
431
547
|
//input: string nucleotides {semType: DNA nucleotides}
|
|
432
548
|
//output: string result {semType: GCRS / Gapmers}
|
|
433
|
-
export function asoGapmersNucleotidesToGcrs(nucleotides: string) {
|
|
549
|
+
export function asoGapmersNucleotidesToGcrs(nucleotides: string): string {
|
|
434
550
|
let count: number = -1;
|
|
435
|
-
const objForEdges: {[index: string]: string} = {
|
|
436
|
-
const objForCenter: {[index: string]: string} = {
|
|
551
|
+
const objForEdges: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'T': 'moeUnps', 'A': 'moeAnps', 'C': 'moe5mCnps', 'G': 'moeGnps'};
|
|
552
|
+
const objForCenter: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'C': '5mCps', 'A': 'Aps', 'T': 'Tps', 'G': 'Gps'};
|
|
437
553
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|T|C|G)/g, function (x: string) {
|
|
438
554
|
count++;
|
|
439
555
|
if (count < 5) return (count == 4) ? objForEdges[x].slice(0, -3) + 'ps' : objForEdges[x];
|
|
440
556
|
if (count < 15) return (count == 14) ? objForCenter[x].slice(0, -2) + 'nps' : objForCenter[x];
|
|
441
557
|
return objForEdges[x];
|
|
442
|
-
}).slice(0, (nucleotides.endsWith(
|
|
558
|
+
}).slice(0, (nucleotides.endsWith('(invabasic)') || nucleotides.endsWith('(GalNAc-2-JNJ)')) ? nucleotides.length : -3);
|
|
443
559
|
}
|
|
444
560
|
|
|
445
561
|
//name: asoGapmersBioSpringToNucleotides
|
|
446
562
|
//input: string nucleotides {semType: BioSpring / Gapmers}
|
|
447
563
|
//output: string result {semType: DNA nucleotides}
|
|
448
|
-
export function asoGapmersBioSpringToNucleotides(nucleotides: string) {
|
|
449
|
-
const obj: {[index: string]: string} = {
|
|
564
|
+
export function asoGapmersBioSpringToNucleotides(nucleotides: string): string {
|
|
565
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', '*': '', '5': 'T', '6': 'A', '7': 'C', '8': 'G', '9': 'C'};
|
|
450
566
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|\*|5|6|7|8|9)/g, function (x: string) {return obj[x];});
|
|
451
567
|
}
|
|
452
568
|
|
|
453
569
|
//name: asoGapmersBioSpringToGcrs
|
|
454
570
|
//input: string nucleotides {semType: BioSpring / Gapmers}
|
|
455
571
|
//output: string result {semType: GCRS / Gapmers}
|
|
456
|
-
export function asoGapmersBioSpringToGcrs(nucleotides: string) {
|
|
572
|
+
export function asoGapmersBioSpringToGcrs(nucleotides: string): string {
|
|
457
573
|
let count: number = -1;
|
|
458
|
-
const obj: {[index: string]: string} = {
|
|
459
|
-
|
|
460
|
-
|
|
574
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
|
|
575
|
+
'5*': 'moeUnps', '6*': 'moeAnps', '7*': 'moe5mCnps', '8*': 'moeGnps', '9*': '5mCps', 'A*': 'Aps', 'T*': 'Tps',
|
|
576
|
+
'G*': 'Gps', 'C*': 'Cps', '5': 'moeU', '6': 'moeA', '7': 'moe5mC', '8': 'moeG'
|
|
461
577
|
};
|
|
462
578
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|5\*|6\*|7\*|8\*|9\*|A\*|T\*|G\*|C\*|5|6|7|8)/g, function (x: string) {
|
|
463
579
|
count++;
|
|
@@ -468,9 +584,9 @@ export function asoGapmersBioSpringToGcrs(nucleotides: string) {
|
|
|
468
584
|
//name: asoGapmersGcrsToBioSpring
|
|
469
585
|
//input: string nucleotides {semType: GCRS / Gapmers}
|
|
470
586
|
//output: string result {semType: BioSpring / Gapmers}
|
|
471
|
-
export function asoGapmersGcrsToBioSpring(nucleotides: string) {
|
|
472
|
-
const obj: {[index: string]: string} = {
|
|
473
|
-
|
|
587
|
+
export function asoGapmersGcrsToBioSpring(nucleotides: string): string {
|
|
588
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
|
|
589
|
+
'moeT': '5', 'moeA': '6', 'moe5mC': '7', 'moeG': '8', 'moeU': '5', '5mC': '9', 'nps': '*', 'ps': '*', 'U': 'T'
|
|
474
590
|
};
|
|
475
591
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|moeT|moeA|moe5mC|moeG|moeU|5mC|nps|ps|U)/g, function (x: string) {return obj[x];});
|
|
476
592
|
}
|
|
@@ -479,7 +595,7 @@ export function asoGapmersGcrsToBioSpring(nucleotides: string) {
|
|
|
479
595
|
//input: string nucleotides {semType: GCRS / Gapmers}
|
|
480
596
|
//output: string result {semType: DNA nucleotides}
|
|
481
597
|
export function asoGapmersGcrsToNucleotides(nucleotides: string) {
|
|
482
|
-
const obj: {[index: string]: string} = {
|
|
598
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'moe': '', '5m': '', 'n': '', 'ps': '', 'U': 'T'};
|
|
483
599
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|moe|5m|n|ps|U)/g, function (x: string) {return obj[x];});
|
|
484
600
|
}
|
|
485
601
|
|
|
@@ -487,7 +603,7 @@ export function asoGapmersGcrsToNucleotides(nucleotides: string) {
|
|
|
487
603
|
//input: string nucleotides {semType: BioSpring / siRNA}
|
|
488
604
|
//output: string result {semType: RNA nucleotides}
|
|
489
605
|
export function siRnaBioSpringToNucleotides(nucleotides: string) {
|
|
490
|
-
const obj: {[index: string]: string} = {
|
|
606
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', '1': 'U', '2': 'A', '3': 'C', '4': 'G', '5': 'U', '6': 'A', '7': 'C', '8': 'G', '*': ''};
|
|
491
607
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|1|2|3|4|5|6|7|8|\*)/g, function (x: string) {return obj[x];});
|
|
492
608
|
}
|
|
493
609
|
|
|
@@ -495,7 +611,7 @@ export function siRnaBioSpringToNucleotides(nucleotides: string) {
|
|
|
495
611
|
//input: string nucleotides {semType: BioSpring / siRNA}
|
|
496
612
|
//output: string result {semType: Axolabs / siRNA}
|
|
497
613
|
export function siRnaBioSpringToAxolabs(nucleotides: string) {
|
|
498
|
-
const obj: {[index: string]: string} = {
|
|
614
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', '1': 'Uf', '2': 'Af', '3': 'Cf', '4': 'Gf', '5': 'u', '6': 'a', '7': 'c', '8': 'g', '*': 's'};
|
|
499
615
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|1|2|3|4|5|6|7|8|\*)/g, function (x: string) {return obj[x];});
|
|
500
616
|
}
|
|
501
617
|
|
|
@@ -503,7 +619,7 @@ export function siRnaBioSpringToAxolabs(nucleotides: string) {
|
|
|
503
619
|
//input: string nucleotides {semType: BioSpring / siRNA}
|
|
504
620
|
//output: string result {semType: GCRS}
|
|
505
621
|
export function siRnaBioSpringToGcrs(nucleotides: string) {
|
|
506
|
-
const obj: {[index: string]: string} = {
|
|
622
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', '1': 'fU', '2': 'fA', '3': 'fC', '4': 'fG', '5': 'mU', '6': 'mA', '7': 'mC', '8': 'mG', '*': 'ps'};
|
|
507
623
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|1|2|3|4|5|6|7|8|\*)/g, function (x: string) {return obj[x];});
|
|
508
624
|
}
|
|
509
625
|
|
|
@@ -511,8 +627,8 @@ export function siRnaBioSpringToGcrs(nucleotides: string) {
|
|
|
511
627
|
//input: string nucleotides {semType: Axolabs / siRNA}
|
|
512
628
|
//output: string result {semType: GCRS}
|
|
513
629
|
export function siRnaAxolabsToGcrs(nucleotides: string) {
|
|
514
|
-
const obj: {[index: string]: string} = {
|
|
515
|
-
|
|
630
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
|
|
631
|
+
'Uf': 'fU', 'Af': 'fA', 'Cf': 'fC', 'Gf': 'fG', 'u': 'mU', 'a': 'mA', 'c': 'mC', 'g': 'mG', 's': 'ps'
|
|
516
632
|
};
|
|
517
633
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|Uf|Af|Cf|Gf|u|a|c|g|s)/g, function (x: string) {return obj[x];});
|
|
518
634
|
}
|
|
@@ -521,8 +637,8 @@ export function siRnaAxolabsToGcrs(nucleotides: string) {
|
|
|
521
637
|
//input: string nucleotides {semType: Axolabs / siRNA}
|
|
522
638
|
//output: string result {semType: BioSpring / siRNA}
|
|
523
639
|
export function siRnaAxolabsToBioSpring(nucleotides: string) {
|
|
524
|
-
const obj: {[index: string]: string} = {
|
|
525
|
-
|
|
640
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
|
|
641
|
+
'Uf': '1', 'Af': '2', 'Cf': '3', 'Gf': '4', 'u': '5', 'a': '6', 'c': '7', 'g': '8', 's': '*'
|
|
526
642
|
};
|
|
527
643
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|Uf|Af|Cf|Gf|u|a|c|g|s)/g, function (x: string) {return obj[x];});
|
|
528
644
|
}
|
|
@@ -531,8 +647,8 @@ export function siRnaAxolabsToBioSpring(nucleotides: string) {
|
|
|
531
647
|
//input: string nucleotides {semType: Axolabs / siRNA}
|
|
532
648
|
//output: string result {semType: RNA nucleotides}
|
|
533
649
|
export function siRnaAxolabsToNucleotides(nucleotides: string) {
|
|
534
|
-
const obj: {[index: string]: string} = {
|
|
535
|
-
|
|
650
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
|
|
651
|
+
'Uf': 'U', 'Af': 'A', 'Cf': 'C', 'Gf': 'G', 'u': 'U', 'a': 'A', 'c': 'C', 'g': 'G', 's': ''
|
|
536
652
|
};
|
|
537
653
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|Uf|Af|Cf|Gf|u|a|c|g|s)/g, function (x: string) {return obj[x];});
|
|
538
654
|
}
|
|
@@ -541,8 +657,8 @@ export function siRnaAxolabsToNucleotides(nucleotides: string) {
|
|
|
541
657
|
//input: string nucleotides {semType: GCRS}
|
|
542
658
|
//output: string result {semType: RNA nucleotides}
|
|
543
659
|
export function siRnaGcrsToNucleotides(nucleotides: string) {
|
|
544
|
-
const obj: {[index: string]: string} = {
|
|
545
|
-
|
|
660
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
|
|
661
|
+
'fU': 'U', 'fA': 'A', 'fC': 'C', 'fG': 'G', 'mU': 'U', 'mA': 'A', 'mC': 'C', 'mG': 'G', 'ps': ''
|
|
546
662
|
};
|
|
547
663
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|fU|fA|fC|fG|mU|mA|mC|mG|ps)/g, function (x: string) {return obj[x];});
|
|
548
664
|
}
|
|
@@ -551,8 +667,8 @@ export function siRnaGcrsToNucleotides(nucleotides: string) {
|
|
|
551
667
|
//input: string nucleotides {semType: GCRS}
|
|
552
668
|
//output: string result {semType: BioSpring / siRNA}
|
|
553
669
|
export function siRnaGcrsToBioSpring(nucleotides: string) {
|
|
554
|
-
const obj: {[index: string]: string} = {
|
|
555
|
-
|
|
670
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
|
|
671
|
+
'fU': '1', 'fA': '2', 'fC': '3', 'fG': '4', 'mU': '5', 'mA': '6', 'mC': '7', 'mG': '8', 'ps': '*'
|
|
556
672
|
};
|
|
557
673
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|fU|fA|fC|fG|mU|mA|mC|mG|ps)/g, function (x: string) {return obj[x];});
|
|
558
674
|
}
|
|
@@ -561,8 +677,8 @@ export function siRnaGcrsToBioSpring(nucleotides: string) {
|
|
|
561
677
|
//input: string nucleotides {semType: GCRS}
|
|
562
678
|
//output: string result {semType: Axolabs / siRNA}
|
|
563
679
|
export function siRnaGcrsToAxolabs(nucleotides: string) {
|
|
564
|
-
const obj: {[index: string]: string} = {
|
|
565
|
-
|
|
680
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
|
|
681
|
+
'fU': 'Uf', 'fA': 'Af', 'fC': 'Cf', 'fG': 'Gf', 'mU': 'u', 'mA': 'a', 'mC': 'c', 'mG': 'g', 'ps': 's'
|
|
566
682
|
};
|
|
567
683
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|fU|fA|fC|fG|mU|mA|mC|mG|ps)/g, function (x: string) {return obj[x];});
|
|
568
684
|
}
|
|
@@ -572,10 +688,10 @@ export function siRnaGcrsToAxolabs(nucleotides: string) {
|
|
|
572
688
|
//output: string result {semType: BioSpring / siRNA}
|
|
573
689
|
export function siRnaNucleotideToBioSpringSenseStrand(nucleotides: string) {
|
|
574
690
|
let count: number = -1;
|
|
575
|
-
const objForLeftEdge: {[index: string]: string} = {
|
|
576
|
-
const objForRightEdge: {[index: string]: string} = {
|
|
577
|
-
const objForOddIndices: {[index: string]: string} = {
|
|
578
|
-
const objForEvenIndices: {[index: string]: string} = {
|
|
691
|
+
const objForLeftEdge: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': '6*', 'U': '5*', 'G': '8*', 'C': '7*'};
|
|
692
|
+
const objForRightEdge: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': '*6', 'U': '*5', 'G': '*8', 'C': '*7'};
|
|
693
|
+
const objForOddIndices: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': '6', 'U': '5', 'G': '8', 'C': '7'};
|
|
694
|
+
const objForEvenIndices: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': '2', 'U': '1', 'G': '4', 'C': '3'};
|
|
579
695
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|U|G|C)/g, function (x: string) {
|
|
580
696
|
count++;
|
|
581
697
|
if (count < 2) return objForLeftEdge[x];
|
|
@@ -589,10 +705,10 @@ export function siRnaNucleotideToBioSpringSenseStrand(nucleotides: string) {
|
|
|
589
705
|
//output: string result {semType: GCRS}
|
|
590
706
|
export function siRnaNucleotidesToGcrs(nucleotides: string) {
|
|
591
707
|
let count: number = -1;
|
|
592
|
-
const objForLeftEdge: {[index: string]: string} = {
|
|
593
|
-
const objForRightEdge: {[index: string]: string} = {
|
|
594
|
-
const objForEvenIndices: {[index: string]: string} = {
|
|
595
|
-
const objForOddIndices: {[index: string]: string} = {
|
|
708
|
+
const objForLeftEdge: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'mAps', 'U': 'mUps', 'G': 'mGps', 'C': 'mCps'};
|
|
709
|
+
const objForRightEdge: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'psmA', 'U': 'psmU', 'G': 'psmG', 'C': 'psmC'};
|
|
710
|
+
const objForEvenIndices: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'fA', 'U': 'fU', 'G': 'fG', 'C': 'fC'};
|
|
711
|
+
const objForOddIndices: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'mA', 'U': 'mU', 'G': 'mG', 'C': 'mC'};
|
|
596
712
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|U|G|C)/g, function (x: string) {
|
|
597
713
|
count++;
|
|
598
714
|
if (count < 2) return objForLeftEdge[x];
|
|
@@ -606,9 +722,9 @@ export function siRnaNucleotidesToGcrs(nucleotides: string) {
|
|
|
606
722
|
//output: string result {semType: Axolabs}
|
|
607
723
|
export function siRnaNucleotideToAxolabsSenseStrand(nucleotides: string) {
|
|
608
724
|
let count: number = -1;
|
|
609
|
-
const objForLeftEdge: {[index: string]: string} = {
|
|
610
|
-
const objForSomeIndices: {[index: string]: string} = {
|
|
611
|
-
const obj: {[index: string]: string} = {
|
|
725
|
+
const objForLeftEdge: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'as', 'U': 'us', 'G': 'gs', 'C': 'cs'};
|
|
726
|
+
const objForSomeIndices: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'Af', 'U': 'Uf', 'G': 'Gf', 'C': 'Cf'};
|
|
727
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'a', 'U': 'u', 'G': 'g', 'C': 'c'};
|
|
612
728
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|U|G|C)/g, function (x: string) {
|
|
613
729
|
count++;
|
|
614
730
|
if (count < 2) return objForLeftEdge[x];
|
|
@@ -623,10 +739,10 @@ export function siRnaNucleotideToAxolabsSenseStrand(nucleotides: string) {
|
|
|
623
739
|
//output: string result {semType: Axolabs}
|
|
624
740
|
export function siRnaNucleotideToAxolabsAntisenseStrand(nucleotides: string) {
|
|
625
741
|
let count: number = -1;
|
|
626
|
-
const objForSmallLinkages: {[index: string]: string} = {
|
|
627
|
-
const objForBigLinkages: {[index: string]: string} = {
|
|
628
|
-
const objForSomeIndices: {[index: string]: string} = {
|
|
629
|
-
const obj: {[index: string]: string} = {
|
|
742
|
+
const objForSmallLinkages: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'as', 'U': 'us', 'G': 'gs', 'C': 'cs'};
|
|
743
|
+
const objForBigLinkages: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'Afs', 'U': 'Ufs', 'G': 'Gfs', 'C': 'Cfs'};
|
|
744
|
+
const objForSomeIndices: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'Af', 'U': 'Uf', 'G': 'Gf', 'C': 'Cf'};
|
|
745
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'A': 'a', 'U': 'u', 'G': 'g', 'C': 'c'};
|
|
630
746
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|U|G|C)/g, function (x: string) {
|
|
631
747
|
count++;
|
|
632
748
|
if (count > 19 && count < 22) return objForSmallLinkages[x];
|
|
@@ -640,9 +756,9 @@ export function siRnaNucleotideToAxolabsAntisenseStrand(nucleotides: string) {
|
|
|
640
756
|
//input: string nucleotides {semType: GCRS}
|
|
641
757
|
//output: string result {semType: RNA nucleotides}
|
|
642
758
|
export function gcrsToNucleotides(nucleotides: string) {
|
|
643
|
-
const obj: {[index: string]: string} = {
|
|
644
|
-
|
|
645
|
-
|
|
759
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
|
|
760
|
+
'mAps': 'A', 'mUps': 'U', 'mGps': 'G', 'mCps': 'C', 'fAps': 'A', 'fUps': 'U', 'fGps': 'G', 'fCps': 'C',
|
|
761
|
+
'fU': 'U', 'fA': 'A', 'fC': 'C', 'fG': 'G', 'mU': 'U', 'mA': 'A', 'mC': 'C', 'mG': 'G'
|
|
646
762
|
};
|
|
647
763
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|mAps|mUps|mGps|mCps|fAps|fUps|fGps|fCps|fU|fA|fC|fG|mU|mA|mC|mG)/g, function (x: string) {return obj[x];});
|
|
648
764
|
}
|
|
@@ -651,9 +767,130 @@ export function gcrsToNucleotides(nucleotides: string) {
|
|
|
651
767
|
//input: string nucleotides {semType: GCRS}
|
|
652
768
|
//output: string result {semType: Mermade 12 / siRNA}
|
|
653
769
|
export function gcrsToMermade12(nucleotides: string) {
|
|
654
|
-
const obj: {[index: string]: string} = {
|
|
655
|
-
|
|
656
|
-
|
|
770
|
+
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)',
|
|
771
|
+
'mAps': 'e', 'mUps': 'h', 'mGps': 'g', 'mCps': 'f', 'fAps': 'i', 'fUps': 'l', 'fGps': 'k', 'fCps': 'j', 'fU': 'L',
|
|
772
|
+
'fA': 'I', 'fC': 'J', 'fG': 'K', 'mU': 'H', 'mA': 'E', 'mC': 'F', 'mG': 'G'
|
|
657
773
|
};
|
|
658
774
|
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|mAps|mUps|mGps|mCps|fAps|fUps|fGps|fCps|fU|fA|fC|fG|mU|mA|mC|mG)/g, function (x: string) {return obj[x]});
|
|
659
775
|
}
|
|
776
|
+
|
|
777
|
+
async function saveTableAsSdFile(table: DG.DataFrame) {
|
|
778
|
+
if (!table.columns.contains('Compound Name'))
|
|
779
|
+
grok.shell.warning("File was saved without columns 'Compound Name', 'Compound Components', 'Cpd MW', 'Salt mass', 'Batch MW'!");
|
|
780
|
+
let structureColumn = table.columns.byName('Sequence');
|
|
781
|
+
let result = '';
|
|
782
|
+
for (let i = 0; i < table.rowCount; i++) {
|
|
783
|
+
try {
|
|
784
|
+
let smiles = sequenceToSmiles(structureColumn.get(i));
|
|
785
|
+
//@ts-ignore
|
|
786
|
+
let mol = new OCL.Molecule.fromSmiles(smiles);
|
|
787
|
+
result += `\n${mol.toMolfile()}\n`;
|
|
788
|
+
for (let col of table.columns)
|
|
789
|
+
result += `> <${col.name}>\n${col.get(i)}\n\n`;
|
|
790
|
+
result += '$$$$';
|
|
791
|
+
}
|
|
792
|
+
catch (error) {
|
|
793
|
+
console.error(error);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
let element = document.createElement('a');
|
|
797
|
+
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
|
|
798
|
+
element.setAttribute('download', table.name + '.sdf');
|
|
799
|
+
element.click();
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
function parseNumber(saltName: string) {
|
|
803
|
+
let i = saltName.length;
|
|
804
|
+
while (saltName.length > -1 && saltName[i] != '(')
|
|
805
|
+
i--;
|
|
806
|
+
return parseInt(saltName.slice(i + 2));
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
//tags: autostart
|
|
810
|
+
export function autostartOligoSdFileSubscription() {
|
|
811
|
+
grok.events.onViewAdded.subscribe((v: any) => {
|
|
812
|
+
if (v.type == 'TableView' && v.dataFrame.columns.contains('Type'))
|
|
813
|
+
oligoSdFile(v.dataFrame);
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
let weightsObj: {[code: string]: number} = {};
|
|
818
|
+
for (let synthesizer of Object.keys(map))
|
|
819
|
+
for (let technology of Object.keys(map[synthesizer]))
|
|
820
|
+
for (let code of Object.keys(map[synthesizer][technology]))
|
|
821
|
+
weightsObj[code] = map[synthesizer][technology][code].weight;
|
|
822
|
+
|
|
823
|
+
function molecularWeight(sequence: string): number {
|
|
824
|
+
const codes = sortByStringLengthInDescendingOrder(Object.keys(weightsObj));
|
|
825
|
+
let weight = 0, i = 0;
|
|
826
|
+
while (i < sequence.length) {
|
|
827
|
+
let matchedCode = codes.find((s) => s == sequence.slice(i, i + s.length))!;
|
|
828
|
+
weight += weightsObj[sequence.slice(i, i + matchedCode.length)];
|
|
829
|
+
i += matchedCode!.length;
|
|
830
|
+
}
|
|
831
|
+
return weight - 61.97;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
export function oligoSdFile(table: DG.DataFrame) {
|
|
835
|
+
|
|
836
|
+
function addColumns(t: DG.DataFrame) {
|
|
837
|
+
if (t.columns.contains('Compound Name'))
|
|
838
|
+
return grok.shell.error('Columns already exist!');
|
|
839
|
+
|
|
840
|
+
table.col('Source')?.init('Johnson and Johnson Pharma');
|
|
841
|
+
table.col('ICD')?.init('No Contract');
|
|
842
|
+
|
|
843
|
+
let sequence = t.col('Sequence')!;
|
|
844
|
+
let salt = t.col('Salt')!;
|
|
845
|
+
let equivalents = t.col('Equivalents')!;
|
|
846
|
+
|
|
847
|
+
t.columns.addNewString('Compound Name').init((i: number) => sequence.get(i));
|
|
848
|
+
t.columns.addNewString('Compound Comments').init((i: number) => (i > 0 && i % 2 == 0) ?
|
|
849
|
+
sequence.getString(i) + '; duplex of SS: ' + sequence.getString(i - 2) + ' and AS: ' + sequence.getString(i - 1) :
|
|
850
|
+
sequence.getString(i)
|
|
851
|
+
);
|
|
852
|
+
t.columns.addNewFloat('Cpd MW').init((i: number) => ((i + 1) % 3 == 0) ? DG.FLOAT_NULL : molecularWeight(sequence.get(i)));
|
|
853
|
+
t.columns.addNewFloat('Salt mass').init((i: number) => parseNumber(salt.get(i)) * equivalents.get(i));
|
|
854
|
+
t.columns.addNewCalculated('Batch MW', '${Cpd MW} + ${Salt mass}', DG.COLUMN_TYPE.FLOAT, false);
|
|
855
|
+
|
|
856
|
+
addColumnsPressed = true;
|
|
857
|
+
return newDf = t;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
const columnsOrder = ["Chemistry", "Number", "Type", "Chemistry Name", "Internal compound ID", "IDP", "Sequence", "Compound Name",
|
|
861
|
+
"Compound Comments", "Salt", "Equivalents", "Purity", "Cpd MW", "Salt mass", "Batch MW", "Source", "ICD", "Owner"];
|
|
862
|
+
let newDf: DG.DataFrame;
|
|
863
|
+
let addColumnsPressed = false;
|
|
864
|
+
|
|
865
|
+
let d = ui.div([
|
|
866
|
+
ui.icons.edit(() => {
|
|
867
|
+
d.innerHTML = '';
|
|
868
|
+
d.append(
|
|
869
|
+
ui.link('Add Columns', async () => {
|
|
870
|
+
await addColumns(table);
|
|
871
|
+
grok.shell.tableView(table.name).grid.columns.setOrder(columnsOrder);
|
|
872
|
+
}, 'Add columns: Compound Name, Compound Components, Cpd MW, Salt mass, Batch MW', ''),
|
|
873
|
+
ui.button('Save SD file', () => saveTableAsSdFile(addColumnsPressed ? newDf : table))
|
|
874
|
+
);
|
|
875
|
+
let view = grok.shell.getTableView(table.name);
|
|
876
|
+
let typeCol = view.grid.col('Type')!;
|
|
877
|
+
let saltCol = view.grid.col('Salt')!;
|
|
878
|
+
saltCol.cellType = 'html';
|
|
879
|
+
typeCol.cellType = 'html';
|
|
880
|
+
view.grid.onCellPrepare(function (gc: DG.GridCell) {
|
|
881
|
+
if (gc.isTableCell) {
|
|
882
|
+
if (gc.gridColumn.name == 'Type')
|
|
883
|
+
gc.style.element = ui.choiceInput('', gc.cell.value, ['AS', 'SS', 'Duplex']).root;
|
|
884
|
+
else if (gc.gridColumn.name == 'Salt')
|
|
885
|
+
gc.style.element = ui.choiceInput('', gc.cell.value, ['Sodium (+1)', 'Sodium (+2)']).root;
|
|
886
|
+
}
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
table.onDataChanged.subscribe((_) => {
|
|
890
|
+
if (table.currentCol.name == 'IDP' && typeof table.currentCell.value != 'number')
|
|
891
|
+
grok.shell.error('Value should be numeric');
|
|
892
|
+
});
|
|
893
|
+
})
|
|
894
|
+
]);
|
|
895
|
+
grok.shell.v.setRibbonPanels([[d]]);
|
|
896
|
+
}
|