@datagrok/sequence-translator 0.0.6 → 0.0.8
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/package.json +1 -1
- package/src/defineAxolabsPattern.ts +2 -8
- package/src/package.ts +116 -656
- package/src/salts.ts +2 -0
- package/src/structures-works/converters.ts +288 -0
- package/src/structures-works/from-monomers.ts +73 -0
- package/src/{map.ts → structures-works/map.ts} +0 -0
- package/src/{save-sense-antisense.ts → structures-works/save-sense-antisense.ts} +5 -5
- package/src/structures-works/sequence-codes-tools.ts +236 -0
- package/src/tests/smiles-tests.ts +1 -1
package/src/package.ts
CHANGED
|
@@ -5,216 +5,17 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
import * as OCL from 'openchemlib/full.js';
|
|
6
6
|
import $ from 'cash-dom';
|
|
7
7
|
import {defineAxolabsPattern} from './defineAxolabsPattern';
|
|
8
|
-
import {saveSenseAntiSense} from './save-sense-antisense';
|
|
9
|
-
import {
|
|
8
|
+
import {saveSenseAntiSense} from './structures-works/save-sense-antisense';
|
|
9
|
+
import {sequenceToSmiles} from './structures-works/from-monomers';
|
|
10
|
+
import {convertSequence, undefinedInputSequence} from './structures-works/sequence-codes-tools';
|
|
11
|
+
import {SALTS_CSV} from './salts';
|
|
10
12
|
|
|
11
13
|
export const _package = new DG.Package();
|
|
12
14
|
|
|
13
15
|
const defaultInput = 'AGGTCCTCTTGACTTAGGCC';
|
|
14
|
-
const undefinedInputSequence = 'Type of input sequence is undefined';
|
|
15
|
-
const noTranslationTableAvailable = 'No translation table available';
|
|
16
16
|
const sequenceWasCopied = 'Copied';
|
|
17
17
|
const tooltipSequence = 'Copy sequence';
|
|
18
18
|
|
|
19
|
-
function getAllCodesOfSynthesizer(synthesizer: string): string[] {
|
|
20
|
-
let codes: string[] = [];
|
|
21
|
-
for (const technology of Object.keys(map[synthesizer]))
|
|
22
|
-
codes = codes.concat(Object.keys(map[synthesizer][technology]));
|
|
23
|
-
return codes.concat(Object.keys(MODIFICATIONS));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function getListOfPossibleSynthesizersByFirstMatchedCode(sequence: string): string[] {
|
|
27
|
-
const synthesizers: string[] = [];
|
|
28
|
-
Object.keys(map).forEach((synthesizer: string) => {
|
|
29
|
-
const codes = getAllCodesOfSynthesizer(synthesizer);
|
|
30
|
-
//TODO: get first non-dropdown code when there are two modifications
|
|
31
|
-
let start = 0;
|
|
32
|
-
for (let i = 0; i < sequence.length; i++) {
|
|
33
|
-
if (sequence[i] == ')') {
|
|
34
|
-
start = i + 1;
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
if (codes.some((s: string) => s == sequence.slice(start, start + s.length)))
|
|
39
|
-
synthesizers.push(synthesizer);
|
|
40
|
-
});
|
|
41
|
-
return synthesizers;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function getListOfPossibleTechnologiesByFirstMatchedCode(sequence: string, synthesizer: string): string[] {
|
|
45
|
-
const technologies: string[] = [];
|
|
46
|
-
Object.keys(map[synthesizer]).forEach((technology: string) => {
|
|
47
|
-
const codes = Object.keys(map[synthesizer][technology]).concat(Object.keys(MODIFICATIONS));
|
|
48
|
-
if (codes.some((s) => s == sequence.slice(0, s.length)))
|
|
49
|
-
technologies.push(technology);
|
|
50
|
-
});
|
|
51
|
-
return technologies;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function isValidSequence(sequence: string): {
|
|
55
|
-
indexOfFirstNotValidCharacter: number,
|
|
56
|
-
expectedSynthesizer: string | null,
|
|
57
|
-
expectedTechnology: string | null
|
|
58
|
-
} {
|
|
59
|
-
const possibleSynthesizers = getListOfPossibleSynthesizersByFirstMatchedCode(sequence);
|
|
60
|
-
if (possibleSynthesizers.length == 0)
|
|
61
|
-
return {indexOfFirstNotValidCharacter: 0, expectedSynthesizer: null, expectedTechnology: null};
|
|
62
|
-
|
|
63
|
-
let outputIndices = Array(possibleSynthesizers.length).fill(0);
|
|
64
|
-
|
|
65
|
-
const firstUniqueCharacters = ['r', 'd'];
|
|
66
|
-
const nucleotides = ['A', 'U', 'T', 'C', 'G'];
|
|
67
|
-
|
|
68
|
-
possibleSynthesizers.forEach((synthesizer, synthesizerIndex) => {
|
|
69
|
-
const codes = getAllCodesOfSynthesizer(synthesizer);
|
|
70
|
-
while (outputIndices[synthesizerIndex] < sequence.length) {
|
|
71
|
-
const matchedCode = codes
|
|
72
|
-
.find((c) => c == sequence.slice(outputIndices[synthesizerIndex], outputIndices[synthesizerIndex] + c.length));
|
|
73
|
-
|
|
74
|
-
if (matchedCode == null)
|
|
75
|
-
break;
|
|
76
|
-
|
|
77
|
-
if ( // for mistake pattern 'rAA'
|
|
78
|
-
outputIndices[synthesizerIndex] > 1 &&
|
|
79
|
-
nucleotides.includes(sequence[outputIndices[synthesizerIndex]]) &&
|
|
80
|
-
firstUniqueCharacters.includes(sequence[outputIndices[synthesizerIndex] - 2])
|
|
81
|
-
) break;
|
|
82
|
-
|
|
83
|
-
if ( // for mistake pattern 'ArA'
|
|
84
|
-
firstUniqueCharacters.includes(sequence[outputIndices[synthesizerIndex] + 1]) &&
|
|
85
|
-
nucleotides.includes(sequence[outputIndices[synthesizerIndex]])
|
|
86
|
-
) {
|
|
87
|
-
outputIndices[synthesizerIndex]++;
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
outputIndices[synthesizerIndex] += matchedCode.length;
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
const indexOfExpectedSythesizer = Math.max.apply(Math, outputIndices);
|
|
96
|
-
const indexOfFirstNotValidCharacter = (indexOfExpectedSythesizer == sequence.length) ? -1 : indexOfExpectedSythesizer;
|
|
97
|
-
const expectedSynthesizer = possibleSynthesizers[outputIndices.indexOf(indexOfExpectedSythesizer)];
|
|
98
|
-
if (indexOfFirstNotValidCharacter != -1)
|
|
99
|
-
return {
|
|
100
|
-
indexOfFirstNotValidCharacter: indexOfFirstNotValidCharacter,
|
|
101
|
-
expectedSynthesizer: expectedSynthesizer,
|
|
102
|
-
expectedTechnology: null
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
let possibleTechnologies = getListOfPossibleTechnologiesByFirstMatchedCode(sequence, expectedSynthesizer);
|
|
106
|
-
if (possibleTechnologies.length == 0)
|
|
107
|
-
return { indexOfFirstNotValidCharacter: 0, expectedSynthesizer: null, expectedTechnology: null };
|
|
108
|
-
|
|
109
|
-
outputIndices = Array(possibleTechnologies.length).fill(0);
|
|
110
|
-
|
|
111
|
-
possibleTechnologies.forEach((technology: string, technologyIndex: number) => {
|
|
112
|
-
let codes = Object.keys(map[expectedSynthesizer][technology]);
|
|
113
|
-
while (outputIndices[technologyIndex] < sequence.length) {
|
|
114
|
-
|
|
115
|
-
let matchedCode = codes
|
|
116
|
-
.find((c) => c == sequence.slice(outputIndices[technologyIndex], outputIndices[technologyIndex] + c.length));
|
|
117
|
-
|
|
118
|
-
if (matchedCode == null)
|
|
119
|
-
break;
|
|
120
|
-
|
|
121
|
-
if ( // for mistake pattern 'rAA'
|
|
122
|
-
outputIndices[technologyIndex] > 1 &&
|
|
123
|
-
nucleotides.includes(sequence[outputIndices[technologyIndex]]) &&
|
|
124
|
-
firstUniqueCharacters.includes(sequence[outputIndices[technologyIndex] - 2])
|
|
125
|
-
) break;
|
|
126
|
-
|
|
127
|
-
if ( // for mistake pattern 'ArA'
|
|
128
|
-
firstUniqueCharacters.includes(sequence[outputIndices[technologyIndex] + 1]) &&
|
|
129
|
-
nucleotides.includes(sequence[outputIndices[technologyIndex]])
|
|
130
|
-
) {
|
|
131
|
-
outputIndices[technologyIndex]++;
|
|
132
|
-
break;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
outputIndices[technologyIndex] += matchedCode.length;
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
const indexOfExpectedTechnology = Math.max.apply(Math, outputIndices);
|
|
140
|
-
const expectedTechnology = possibleTechnologies[outputIndices.indexOf(indexOfExpectedTechnology)];
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
indexOfFirstNotValidCharacter: indexOfFirstNotValidCharacter,
|
|
144
|
-
expectedSynthesizer: expectedSynthesizer,
|
|
145
|
-
expectedTechnology: expectedTechnology
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function sortByStringLengthInDescendingOrder(array: string[]): string[] {
|
|
150
|
-
return array.sort(function(a: string, b: string) { return b.length - a.length; });
|
|
151
|
-
}
|
|
152
|
-
|
|
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]))
|
|
157
|
-
for (let code of Object.keys(map[synthesizer][technology]))
|
|
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;
|
|
165
|
-
return obj;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export function sequenceToSmiles(sequence: string, inverted: boolean = false): string {
|
|
169
|
-
const obj = getObjectWithCodesAndSmiles(sequence);
|
|
170
|
-
let codes = sortByStringLengthInDescendingOrder(Object.keys(obj));
|
|
171
|
-
let i = 0;
|
|
172
|
-
let smiles = '';
|
|
173
|
-
const codesList = [];
|
|
174
|
-
const links = ['s', 'ps', '*'];
|
|
175
|
-
const includesStandardLinkAlready = ['e', 'h', /*'g',*/ 'f', 'i', 'l', 'k', 'j'];
|
|
176
|
-
const dropdowns = Object.keys(MODIFICATIONS);
|
|
177
|
-
codes = codes.concat(dropdowns);
|
|
178
|
-
while (i < sequence.length) {
|
|
179
|
-
const code = codes.find((s: string) => s == sequence.slice(i, i + s.length))!;
|
|
180
|
-
i += code.length;
|
|
181
|
-
inverted ? codesList.unshift(code) : codesList.push(code);
|
|
182
|
-
}
|
|
183
|
-
for (let i = 0; i < codesList.length; i++) {
|
|
184
|
-
if (dropdowns.includes(codesList[i])) {
|
|
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
|
-
}
|
|
194
|
-
} else {
|
|
195
|
-
if (links.includes(codesList[i]) ||
|
|
196
|
-
includesStandardLinkAlready.includes(codesList[i]) ||
|
|
197
|
-
(i < codesList.length - 1 && links.includes(codesList[i + 1]))
|
|
198
|
-
)
|
|
199
|
-
smiles += obj[codesList[i]];
|
|
200
|
-
else
|
|
201
|
-
smiles += obj[codesList[i]] + stadardPhosphateLinkSmiles;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
smiles = smiles.replace(/OO/g, 'O');
|
|
205
|
-
return (
|
|
206
|
-
(
|
|
207
|
-
links.includes(codesList[codesList.length - 1]) &&
|
|
208
|
-
codesList.length > 1 &&
|
|
209
|
-
!includesStandardLinkAlready.includes(codesList[codesList.length - 2])
|
|
210
|
-
) ||
|
|
211
|
-
dropdowns.includes(codesList[codesList.length - 1]) ||
|
|
212
|
-
includesStandardLinkAlready.includes(codesList[codesList.length - 1])
|
|
213
|
-
) ?
|
|
214
|
-
smiles :
|
|
215
|
-
smiles.slice(0, smiles.length - stadardPhosphateLinkSmiles.length + 1);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
19
|
//name: Sequence Translator
|
|
219
20
|
//tags: app
|
|
220
21
|
export function sequenceTranslator(): void {
|
|
@@ -233,11 +34,11 @@ export function sequenceTranslator(): void {
|
|
|
233
34
|
const tableRows = [];
|
|
234
35
|
|
|
235
36
|
for (const key of Object.keys(outputSequenceObj).slice(1)) {
|
|
236
|
-
|
|
37
|
+
const indexOfFirstNotValidCharacter = ('indexOfFirstNotValidCharacter' in outputSequenceObj) ?
|
|
237
38
|
JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).indexOfFirstNotValidCharacter :
|
|
238
39
|
-1;
|
|
239
40
|
if ('indexOfFirstNotValidCharacter' in outputSequenceObj) {
|
|
240
|
-
|
|
41
|
+
const indexOfFirstNotValidCharacter = ('indexOfFirstNotValidCharacter' in outputSequenceObj) ?
|
|
241
42
|
JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).indexOfFirstNotValidCharacter :
|
|
242
43
|
-1;
|
|
243
44
|
if (indexOfFirstNotValidCharacter != -1)
|
|
@@ -251,46 +52,50 @@ export function sequenceTranslator(): void {
|
|
|
251
52
|
ui.divText(sequence.slice(0, indexOfFirstNotValidCharacter), {style: {color: 'grey'}}),
|
|
252
53
|
ui.tooltip.bind(
|
|
253
54
|
ui.divText(sequence.slice(indexOfFirstNotValidCharacter), {style: {color: 'red'}}),
|
|
254
|
-
'Expected format: ' + JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).expectedSynthesizer +
|
|
55
|
+
'Expected format: ' + JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).expectedSynthesizer +
|
|
56
|
+
'. See tables with valid codes on the right',
|
|
255
57
|
),
|
|
256
58
|
]) : //@ts-ignore
|
|
257
|
-
ui.link(outputSequenceObj[key], () => navigator.clipboard.writeText(outputSequenceObj[key])
|
|
59
|
+
ui.link(outputSequenceObj[key], () => navigator.clipboard.writeText(outputSequenceObj[key])
|
|
60
|
+
.then(() => grok.shell.info(sequenceWasCopied)), tooltipSequence, ''),
|
|
258
61
|
});
|
|
259
62
|
}
|
|
260
63
|
|
|
261
64
|
if (errorsExist) {
|
|
262
|
-
const expectedSynthesizer = JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!)
|
|
263
|
-
|
|
65
|
+
const expectedSynthesizer = JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!)
|
|
66
|
+
.expectedSynthesizer.slice(0, -6);
|
|
67
|
+
asoGapmersGrid.onCellPrepare(function(gc) {
|
|
264
68
|
gc.style.backColor = (gc.gridColumn.name == expectedSynthesizer) ? 0xFFF00000 : 0xFFFFFFFF;
|
|
265
69
|
});
|
|
266
|
-
omeAndFluoroGrid.onCellPrepare(function
|
|
70
|
+
omeAndFluoroGrid.onCellPrepare(function(gc) {
|
|
267
71
|
gc.style.backColor = (gc.gridColumn.name == expectedSynthesizer) ? 0xFFF00000 : 0xFFFFFFFF;
|
|
268
72
|
});
|
|
269
73
|
switchInput.enabled = true;
|
|
270
74
|
} else {
|
|
271
|
-
asoGapmersGrid.onCellPrepare(function
|
|
75
|
+
asoGapmersGrid.onCellPrepare(function(gc) {
|
|
272
76
|
gc.style.backColor = 0xFFFFFFFF;
|
|
273
77
|
});
|
|
274
|
-
omeAndFluoroGrid.onCellPrepare(function
|
|
78
|
+
omeAndFluoroGrid.onCellPrepare(function(gc) {
|
|
275
79
|
gc.style.backColor = 0xFFFFFFFF;
|
|
276
80
|
});
|
|
277
81
|
}
|
|
278
82
|
|
|
279
83
|
outputTableDiv.append(
|
|
280
84
|
ui.div([
|
|
281
|
-
DG.HtmlTable.create(tableRows, (item: { key: string; value: string; }) =>
|
|
282
|
-
|
|
85
|
+
DG.HtmlTable.create(tableRows, (item: { key: string; value: string; }) =>
|
|
86
|
+
[item.key, item.value], ['Code', 'Sequence']).root,
|
|
87
|
+
], 'table'),
|
|
283
88
|
);
|
|
284
89
|
semTypeOfInputSequence.textContent = 'Detected input type: ' + outputSequenceObj.type;
|
|
285
90
|
|
|
286
91
|
if (outputSequenceObj.type != undefinedInputSequence && outputSequenceObj.Error != undefinedInputSequence) {
|
|
287
|
-
|
|
288
|
-
canvas.addEventListener(
|
|
289
|
-
|
|
92
|
+
const canvas = ui.canvas(300, 170);
|
|
93
|
+
canvas.addEventListener('click', () => {
|
|
94
|
+
const canv = ui.canvas($(window).width(), $(window).height());
|
|
290
95
|
const smiles = sequenceToSmiles(inputSequenceField.value.replace(/\s/g, ''));
|
|
291
96
|
// @ts-ignore
|
|
292
|
-
OCL.StructureView.drawMolecule(canv, OCL.Molecule.fromSmiles(smiles), {
|
|
293
|
-
ui.dialog('Molecule')
|
|
97
|
+
OCL.StructureView.drawMolecule(canv, OCL.Molecule.fromSmiles(smiles), {suppressChiralText: true});
|
|
98
|
+
ui.dialog('Molecule: ' + inputSequenceField.value)
|
|
294
99
|
.add(canv)
|
|
295
100
|
.showModal(true);
|
|
296
101
|
});
|
|
@@ -298,7 +103,7 @@ export function sequenceTranslator(): void {
|
|
|
298
103
|
$(canvas).on('mouseout', () => $(canvas).css('cursor', 'default'));
|
|
299
104
|
const smiles = sequenceToSmiles(inputSequenceField.value.replace(/\s/g, ''));
|
|
300
105
|
// @ts-ignore
|
|
301
|
-
OCL.StructureView.drawMolecule(canvas, OCL.Molecule.fromSmiles(smiles), {
|
|
106
|
+
OCL.StructureView.drawMolecule(canvas, OCL.Molecule.fromSmiles(smiles), {suppressChiralText: true});
|
|
302
107
|
moleculeSvgDiv.append(canvas);
|
|
303
108
|
} else
|
|
304
109
|
moleculeSvgDiv.innerHTML = '';
|
|
@@ -313,69 +118,66 @@ export function sequenceTranslator(): void {
|
|
|
313
118
|
const inputSequenceField = ui.textInput('', defaultInput, (sequence: string) => updateTableAndMolecule(sequence));
|
|
314
119
|
|
|
315
120
|
const asoDf = DG.DataFrame.fromObjects([
|
|
316
|
-
{
|
|
317
|
-
{
|
|
318
|
-
{
|
|
319
|
-
{
|
|
320
|
-
{
|
|
321
|
-
{
|
|
322
|
-
{
|
|
323
|
-
{
|
|
324
|
-
{
|
|
325
|
-
{
|
|
326
|
-
{
|
|
327
|
-
{
|
|
328
|
-
{
|
|
329
|
-
{
|
|
121
|
+
{'Name': '2\'MOE-5Me-rU', 'BioSpring': '5', 'Janssen GCRS': 'moeT'},
|
|
122
|
+
{'Name': '2\'MOE-rA', 'BioSpring': '6', 'Janssen GCRS': 'moeA'},
|
|
123
|
+
{'Name': '2\'MOE-5Me-rC', 'BioSpring': '7', 'Janssen GCRS': 'moe5mC'},
|
|
124
|
+
{'Name': '2\'MOE-rG', 'BioSpring': '8', 'Janssen GCRS': 'moeG'},
|
|
125
|
+
{'Name': '5-Methyl-dC', 'BioSpring': '9', 'Janssen GCRS': '5mC'},
|
|
126
|
+
{'Name': 'ps linkage', 'BioSpring': '*', 'Janssen GCRS': 'ps'},
|
|
127
|
+
{'Name': 'dA', 'BioSpring': 'A', 'Janssen GCRS': 'A, dA'},
|
|
128
|
+
{'Name': 'dC', 'BioSpring': 'C', 'Janssen GCRS': 'C, dC'},
|
|
129
|
+
{'Name': 'dG', 'BioSpring': 'G', 'Janssen GCRS': 'G, dG'},
|
|
130
|
+
{'Name': 'dT', 'BioSpring': 'T', 'Janssen GCRS': 'T, dT'},
|
|
131
|
+
{'Name': 'rA', 'BioSpring': '', 'Janssen GCRS': 'rA'},
|
|
132
|
+
{'Name': 'rC', 'BioSpring': '', 'Janssen GCRS': 'rC'},
|
|
133
|
+
{'Name': 'rG', 'BioSpring': '', 'Janssen GCRS': 'rG'},
|
|
134
|
+
{'Name': 'rU', 'BioSpring': '', 'Janssen GCRS': 'rU'},
|
|
330
135
|
])!;
|
|
331
|
-
const asoGapmersGrid = DG.Viewer.grid(
|
|
332
|
-
asoDf, { showRowHeader: false, showCellTooltip: false }
|
|
333
|
-
);
|
|
136
|
+
const asoGapmersGrid = DG.Viewer.grid(asoDf, {showRowHeader: false, showCellTooltip: false});
|
|
334
137
|
|
|
335
138
|
asoDf.onCurrentCellChanged.subscribe((_) => {
|
|
336
|
-
navigator.clipboard.writeText(asoDf.currentCell.value).then(() => grok.shell.info('Copied'))
|
|
139
|
+
navigator.clipboard.writeText(asoDf.currentCell.value).then(() => grok.shell.info('Copied'));
|
|
337
140
|
});
|
|
338
141
|
|
|
339
|
-
|
|
142
|
+
const omeAndFluoroGrid = DG.Viewer.grid(
|
|
340
143
|
DG.DataFrame.fromObjects([
|
|
341
|
-
{
|
|
342
|
-
{
|
|
343
|
-
{
|
|
344
|
-
{
|
|
345
|
-
{
|
|
346
|
-
{
|
|
347
|
-
{
|
|
348
|
-
{
|
|
349
|
-
{
|
|
350
|
-
])!, {
|
|
144
|
+
{'Name': '2\'-fluoro-U', 'BioSpring': '1', 'Axolabs': 'Uf', 'Janssen GCRS': 'fU'},
|
|
145
|
+
{'Name': '2\'-fluoro-A', 'BioSpring': '2', 'Axolabs': 'Af', 'Janssen GCRS': 'fA'},
|
|
146
|
+
{'Name': '2\'-fluoro-C', 'BioSpring': '3', 'Axolabs': 'Cf', 'Janssen GCRS': 'fC'},
|
|
147
|
+
{'Name': '2\'-fluoro-G', 'BioSpring': '4', 'Axolabs': 'Gf', 'Janssen GCRS': 'fG'},
|
|
148
|
+
{'Name': '2\'OMe-rU', 'BioSpring': '5', 'Axolabs': 'u', 'Janssen GCRS': 'mU'},
|
|
149
|
+
{'Name': '2\'OMe-rA', 'BioSpring': '6', 'Axolabs': 'a', 'Janssen GCRS': 'mA'},
|
|
150
|
+
{'Name': '2\'OMe-rC', 'BioSpring': '7', 'Axolabs': 'c', 'Janssen GCRS': 'mC'},
|
|
151
|
+
{'Name': '2\'OMe-rG', 'BioSpring': '8', 'Axolabs': 'g', 'Janssen GCRS': 'mG'},
|
|
152
|
+
{'Name': 'ps linkage', 'BioSpring': '*', 'Axolabs': 's', 'Janssen GCRS': 'ps'},
|
|
153
|
+
])!, {showRowHeader: false, showCellTooltip: false},
|
|
351
154
|
);
|
|
352
155
|
|
|
353
156
|
const overhangModificationsGrid = DG.Viewer.grid(
|
|
354
157
|
DG.DataFrame.fromObjects([
|
|
355
|
-
{
|
|
356
|
-
{
|
|
357
|
-
])!, {
|
|
158
|
+
{'Name': '(invabasic)'},
|
|
159
|
+
{'Name': '(GalNAc-2-JNJ)'},
|
|
160
|
+
])!, {showRowHeader: false, showCellTooltip: false},
|
|
358
161
|
);
|
|
359
162
|
updateTableAndMolecule(defaultInput);
|
|
360
163
|
|
|
361
164
|
const appMainDescription = ui.info([
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
);
|
|
165
|
+
ui.divText('How to convert one sequence:', {style: {'font-weight': 'bolder'}}),
|
|
166
|
+
ui.divText('Paste sequence into the text field below'),
|
|
167
|
+
ui.divText('\n How to convert many sequences:', {style: {'font-weight': 'bolder'}}),
|
|
168
|
+
ui.divText('1. Drag & drop an Excel or CSV file with sequences into Datagrok'),
|
|
169
|
+
ui.divText('2. Right-click on the column header, then see the \'Convert\' menu'),
|
|
170
|
+
ui.divText('This will add the result column to the right of the table'),
|
|
171
|
+
], 'Convert oligonucleotide sequences between Nucleotides, BioSpring, Axolabs, Mermade 12 and GCRS representations.');
|
|
370
172
|
|
|
371
173
|
const codesTablesDiv = ui.splitV([
|
|
372
|
-
ui.box(ui.h2('ASO Gapmers'), {
|
|
174
|
+
ui.box(ui.h2('ASO Gapmers'), {style: {maxHeight: '40px'}}),
|
|
373
175
|
asoGapmersGrid.root,
|
|
374
|
-
ui.box(ui.h2(
|
|
176
|
+
ui.box(ui.h2('2\'-OMe and 2\'-F siRNA'), {style: {maxHeight: '40px'}}),
|
|
375
177
|
omeAndFluoroGrid.root,
|
|
376
|
-
ui.box(ui.h2('Overhang modifications'), {
|
|
377
|
-
overhangModificationsGrid.root
|
|
378
|
-
], {
|
|
178
|
+
ui.box(ui.h2('Overhang modifications'), {style: {maxHeight: '40px'}}),
|
|
179
|
+
overhangModificationsGrid.root,
|
|
180
|
+
], {style: {maxWidth: '350px'}});
|
|
379
181
|
|
|
380
182
|
const tabControl = ui.tabControl({
|
|
381
183
|
'MAIN': ui.box(
|
|
@@ -404,12 +206,12 @@ export function sequenceTranslator(): void {
|
|
|
404
206
|
'SDF': saveSenseAntiSense(),
|
|
405
207
|
});
|
|
406
208
|
|
|
407
|
-
|
|
209
|
+
const v = grok.shell.newView('Sequence Translator', [tabControl]);
|
|
408
210
|
v.box = true;
|
|
409
211
|
|
|
410
212
|
const switchInput = ui.switchInput('Codes', true, (v: boolean) => (v) ?
|
|
411
213
|
$(codesTablesDiv).show() :
|
|
412
|
-
$(codesTablesDiv).hide()
|
|
214
|
+
$(codesTablesDiv).hide(),
|
|
413
215
|
);
|
|
414
216
|
|
|
415
217
|
const topPanel = [
|
|
@@ -433,379 +235,43 @@ export function sequenceTranslator(): void {
|
|
|
433
235
|
v.setRibbonPanels([topPanel]);
|
|
434
236
|
|
|
435
237
|
$('.sequence')
|
|
436
|
-
.children().css('padding','5px 0');
|
|
238
|
+
.children().css('padding', '5px 0');
|
|
437
239
|
$('.sequenceInput .input-base')
|
|
438
|
-
.css('margin','0');
|
|
240
|
+
.css('margin', '0');
|
|
439
241
|
$('.sequenceInput textarea')
|
|
440
|
-
.css('resize','none')
|
|
441
|
-
.css('min-height','50px')
|
|
442
|
-
.css('width','100%')
|
|
242
|
+
.css('resize', 'none')
|
|
243
|
+
.css('min-height', '50px')
|
|
244
|
+
.css('width', '100%')
|
|
443
245
|
.attr('spellcheck', 'false');
|
|
444
246
|
$('.sequenceInput select')
|
|
445
|
-
.css('width','100%');
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
function convertSequence(text: string) {
|
|
449
|
-
text = text.replace(/\s/g, '');
|
|
450
|
-
let seq = text;
|
|
451
|
-
let output = isValidSequence(seq);
|
|
452
|
-
if (output.indexOfFirstNotValidCharacter != -1)
|
|
453
|
-
return {
|
|
454
|
-
// type: '',
|
|
455
|
-
indexOfFirstNotValidCharacter: JSON.stringify(output),
|
|
456
|
-
Error: undefinedInputSequence
|
|
457
|
-
};
|
|
458
|
-
if (output.expectedSynthesizer == SYNTHESIZERS.RAW_NUCLEOTIDES && output.expectedTechnology == TECHNOLOGIES.DNA)
|
|
459
|
-
return {
|
|
460
|
-
type: SYNTHESIZERS.RAW_NUCLEOTIDES + ' ' + TECHNOLOGIES.DNA,
|
|
461
|
-
Nucleotides: seq,
|
|
462
|
-
BioSpring: asoGapmersNucleotidesToBioSpring(seq),
|
|
463
|
-
GCRS: asoGapmersNucleotidesToGcrs(seq)
|
|
464
|
-
};
|
|
465
|
-
if (output.expectedSynthesizer == SYNTHESIZERS.BIOSPRING && output.expectedTechnology == TECHNOLOGIES.ASO_GAPMERS)
|
|
466
|
-
return {
|
|
467
|
-
type: SYNTHESIZERS.BIOSPRING + ' ' + TECHNOLOGIES.ASO_GAPMERS,
|
|
468
|
-
Nucleotides: asoGapmersBioSpringToNucleotides(seq),
|
|
469
|
-
BioSpring: seq,
|
|
470
|
-
GCRS: asoGapmersBioSpringToGcrs(seq)
|
|
471
|
-
};
|
|
472
|
-
if (output.expectedSynthesizer == SYNTHESIZERS.GCRS && output.expectedTechnology == TECHNOLOGIES.ASO_GAPMERS)
|
|
473
|
-
return {
|
|
474
|
-
type: SYNTHESIZERS.GCRS + ' ' + TECHNOLOGIES.ASO_GAPMERS,
|
|
475
|
-
Nucleotides: asoGapmersGcrsToNucleotides(seq),
|
|
476
|
-
BioSpring: asoGapmersGcrsToBioSpring(seq),
|
|
477
|
-
Mermade12: gcrsToMermade12(seq),
|
|
478
|
-
GCRS: seq
|
|
479
|
-
};
|
|
480
|
-
if (output.expectedSynthesizer == SYNTHESIZERS.RAW_NUCLEOTIDES && output.expectedTechnology == TECHNOLOGIES.RNA)
|
|
481
|
-
return {
|
|
482
|
-
type: SYNTHESIZERS.RAW_NUCLEOTIDES + ' ' + TECHNOLOGIES.RNA,
|
|
483
|
-
Nucleotides: seq,
|
|
484
|
-
BioSpring: siRnaNucleotideToBioSpringSenseStrand(seq),
|
|
485
|
-
Axolabs: siRnaNucleotideToAxolabsSenseStrand(seq),
|
|
486
|
-
GCRS: siRnaNucleotidesToGcrs(seq)
|
|
487
|
-
};
|
|
488
|
-
if (output.expectedSynthesizer == SYNTHESIZERS.BIOSPRING && output.expectedTechnology == TECHNOLOGIES.SI_RNA)
|
|
489
|
-
return {
|
|
490
|
-
type: SYNTHESIZERS.BIOSPRING + ' ' + TECHNOLOGIES.SI_RNA,
|
|
491
|
-
Nucleotides: siRnaBioSpringToNucleotides(seq),
|
|
492
|
-
BioSpring: seq,
|
|
493
|
-
Axolabs: siRnaBioSpringToAxolabs(seq),
|
|
494
|
-
GCRS: siRnaBioSpringToGcrs(seq)
|
|
495
|
-
};
|
|
496
|
-
if (output.expectedSynthesizer == SYNTHESIZERS.AXOLABS && output.expectedTechnology == TECHNOLOGIES.SI_RNA)
|
|
497
|
-
return {
|
|
498
|
-
type: SYNTHESIZERS.AXOLABS + ' ' + TECHNOLOGIES.SI_RNA,
|
|
499
|
-
Nucleotides: siRnaAxolabsToNucleotides(seq),
|
|
500
|
-
BioSpring: siRnaAxolabsToBioSpring(seq),
|
|
501
|
-
Axolabs: seq,
|
|
502
|
-
GCRS: siRnaAxolabsToGcrs(seq)
|
|
503
|
-
};
|
|
504
|
-
if (output.expectedSynthesizer == SYNTHESIZERS.GCRS && output.expectedTechnology == TECHNOLOGIES.SI_RNA)
|
|
505
|
-
return {
|
|
506
|
-
type: SYNTHESIZERS.GCRS + ' ' + TECHNOLOGIES.SI_RNA,
|
|
507
|
-
Nucleotides: siRnaGcrsToNucleotides(seq),
|
|
508
|
-
BioSpring: siRnaGcrsToBioSpring(seq),
|
|
509
|
-
Axolabs: siRnaGcrsToAxolabs(seq),
|
|
510
|
-
MM12: gcrsToMermade12(seq),
|
|
511
|
-
GCRS: seq
|
|
512
|
-
};
|
|
513
|
-
if (output.expectedSynthesizer == SYNTHESIZERS.GCRS)
|
|
514
|
-
return {
|
|
515
|
-
type: SYNTHESIZERS.GCRS,
|
|
516
|
-
Nucleotides: gcrsToNucleotides(seq),
|
|
517
|
-
GCRS: seq,
|
|
518
|
-
Mermade12: gcrsToMermade12(seq)
|
|
519
|
-
}
|
|
520
|
-
if (output.expectedSynthesizer == SYNTHESIZERS.MERMADE_12)
|
|
521
|
-
return {
|
|
522
|
-
type: SYNTHESIZERS.MERMADE_12,
|
|
523
|
-
Nucleotides: noTranslationTableAvailable,
|
|
524
|
-
GCRS: noTranslationTableAvailable,
|
|
525
|
-
Mermade12: seq
|
|
526
|
-
};
|
|
527
|
-
return {
|
|
528
|
-
type: undefinedInputSequence,
|
|
529
|
-
Nucleotides: undefinedInputSequence
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
//name: asoGapmersNucleotidesToBioSpring
|
|
534
|
-
//input: string nucleotides {semType: DNA nucleotides}
|
|
535
|
-
//output: string result {semType: BioSpring / Gapmers}
|
|
536
|
-
export function asoGapmersNucleotidesToBioSpring(nucleotides: string): string {
|
|
537
|
-
let count: number = -1;
|
|
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*'};
|
|
540
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|T|C|G)/g, function (x: string) {
|
|
541
|
-
count++;
|
|
542
|
-
return (count > 4 && count < 15) ? objForCenter[x] : objForEdges[x];
|
|
543
|
-
}).slice(0, (nucleotides.endsWith('(invabasic)') || nucleotides.endsWith('(GalNAc-2-JNJ)')) ? nucleotides.length : 2 * count + 1);
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
//name: asoGapmersNucleotidesToGcrs
|
|
547
|
-
//input: string nucleotides {semType: DNA nucleotides}
|
|
548
|
-
//output: string result {semType: GCRS / Gapmers}
|
|
549
|
-
export function asoGapmersNucleotidesToGcrs(nucleotides: string): string {
|
|
550
|
-
let count: number = -1;
|
|
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'};
|
|
553
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|T|C|G)/g, function (x: string) {
|
|
554
|
-
count++;
|
|
555
|
-
if (count < 5) return (count == 4) ? objForEdges[x].slice(0, -3) + 'ps' : objForEdges[x];
|
|
556
|
-
if (count < 15) return (count == 14) ? objForCenter[x].slice(0, -2) + 'nps' : objForCenter[x];
|
|
557
|
-
return objForEdges[x];
|
|
558
|
-
}).slice(0, (nucleotides.endsWith('(invabasic)') || nucleotides.endsWith('(GalNAc-2-JNJ)')) ? nucleotides.length : -3);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
//name: asoGapmersBioSpringToNucleotides
|
|
562
|
-
//input: string nucleotides {semType: BioSpring / Gapmers}
|
|
563
|
-
//output: string result {semType: DNA nucleotides}
|
|
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'};
|
|
566
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|\*|5|6|7|8|9)/g, function (x: string) {return obj[x];});
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
//name: asoGapmersBioSpringToGcrs
|
|
570
|
-
//input: string nucleotides {semType: BioSpring / Gapmers}
|
|
571
|
-
//output: string result {semType: GCRS / Gapmers}
|
|
572
|
-
export function asoGapmersBioSpringToGcrs(nucleotides: string): string {
|
|
573
|
-
let count: number = -1;
|
|
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'
|
|
577
|
-
};
|
|
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) {
|
|
579
|
-
count++;
|
|
580
|
-
return (count == 4) ? obj[x].slice(0, -3) + 'ps' : (count == 14) ? obj[x].slice(0, -2) + 'nps' : obj[x];
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
//name: asoGapmersGcrsToBioSpring
|
|
585
|
-
//input: string nucleotides {semType: GCRS / Gapmers}
|
|
586
|
-
//output: string result {semType: BioSpring / Gapmers}
|
|
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'
|
|
590
|
-
};
|
|
591
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|moeT|moeA|moe5mC|moeG|moeU|5mC|nps|ps|U)/g, function (x: string) {return obj[x];});
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
//name: asoGapmersGcrsToNucleotides
|
|
595
|
-
//input: string nucleotides {semType: GCRS / Gapmers}
|
|
596
|
-
//output: string result {semType: DNA nucleotides}
|
|
597
|
-
export function asoGapmersGcrsToNucleotides(nucleotides: string) {
|
|
598
|
-
const obj: {[index: string]: string} = {'(invabasic)': '(invabasic)', '(GalNAc-2-JNJ)': '(GalNAc-2-JNJ)', 'moe': '', '5m': '', 'n': '', 'ps': '', 'U': 'T'};
|
|
599
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|moe|5m|n|ps|U)/g, function (x: string) {return obj[x];});
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
//name: siRnaBioSpringToNucleotides
|
|
603
|
-
//input: string nucleotides {semType: BioSpring / siRNA}
|
|
604
|
-
//output: string result {semType: RNA nucleotides}
|
|
605
|
-
export function siRnaBioSpringToNucleotides(nucleotides: 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', '*': ''};
|
|
607
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|1|2|3|4|5|6|7|8|\*)/g, function (x: string) {return obj[x];});
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
//name: siRnaBioSpringToAxolabs
|
|
611
|
-
//input: string nucleotides {semType: BioSpring / siRNA}
|
|
612
|
-
//output: string result {semType: Axolabs / siRNA}
|
|
613
|
-
export function siRnaBioSpringToAxolabs(nucleotides: 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'};
|
|
615
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|1|2|3|4|5|6|7|8|\*)/g, function (x: string) {return obj[x];});
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
//name: siRnaBioSpringToGcrs
|
|
619
|
-
//input: string nucleotides {semType: BioSpring / siRNA}
|
|
620
|
-
//output: string result {semType: GCRS}
|
|
621
|
-
export function siRnaBioSpringToGcrs(nucleotides: 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'};
|
|
623
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|1|2|3|4|5|6|7|8|\*)/g, function (x: string) {return obj[x];});
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
//name: siRnaAxolabsToGcrs
|
|
627
|
-
//input: string nucleotides {semType: Axolabs / siRNA}
|
|
628
|
-
//output: string result {semType: GCRS}
|
|
629
|
-
export function siRnaAxolabsToGcrs(nucleotides: string) {
|
|
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'
|
|
632
|
-
};
|
|
633
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|Uf|Af|Cf|Gf|u|a|c|g|s)/g, function (x: string) {return obj[x];});
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
//name: siRnaAxolabsToBioSpring
|
|
637
|
-
//input: string nucleotides {semType: Axolabs / siRNA}
|
|
638
|
-
//output: string result {semType: BioSpring / siRNA}
|
|
639
|
-
export function siRnaAxolabsToBioSpring(nucleotides: string) {
|
|
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': '*'
|
|
642
|
-
};
|
|
643
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|Uf|Af|Cf|Gf|u|a|c|g|s)/g, function (x: string) {return obj[x];});
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
//name: siRnaAxolabsToNucleotides
|
|
647
|
-
//input: string nucleotides {semType: Axolabs / siRNA}
|
|
648
|
-
//output: string result {semType: RNA nucleotides}
|
|
649
|
-
export function siRnaAxolabsToNucleotides(nucleotides: string) {
|
|
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': ''
|
|
652
|
-
};
|
|
653
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|Uf|Af|Cf|Gf|u|a|c|g|s)/g, function (x: string) {return obj[x];});
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
//name: siRnaGcrsToNucleotides
|
|
657
|
-
//input: string nucleotides {semType: GCRS}
|
|
658
|
-
//output: string result {semType: RNA nucleotides}
|
|
659
|
-
export function siRnaGcrsToNucleotides(nucleotides: string) {
|
|
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': ''
|
|
662
|
-
};
|
|
663
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|fU|fA|fC|fG|mU|mA|mC|mG|ps)/g, function (x: string) {return obj[x];});
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
//name: siRnaGcrsToBioSpring
|
|
667
|
-
//input: string nucleotides {semType: GCRS}
|
|
668
|
-
//output: string result {semType: BioSpring / siRNA}
|
|
669
|
-
export function siRnaGcrsToBioSpring(nucleotides: string) {
|
|
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': '*'
|
|
672
|
-
};
|
|
673
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|fU|fA|fC|fG|mU|mA|mC|mG|ps)/g, function (x: string) {return obj[x];});
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
//name: siRnaGcrsToAxolabs
|
|
677
|
-
//input: string nucleotides {semType: GCRS}
|
|
678
|
-
//output: string result {semType: Axolabs / siRNA}
|
|
679
|
-
export function siRnaGcrsToAxolabs(nucleotides: string) {
|
|
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'
|
|
682
|
-
};
|
|
683
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|fU|fA|fC|fG|mU|mA|mC|mG|ps)/g, function (x: string) {return obj[x];});
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
//name: siRnaNucleotideToBioSpringSenseStrand
|
|
687
|
-
//input: string nucleotides {semType: RNA nucleotides}
|
|
688
|
-
//output: string result {semType: BioSpring / siRNA}
|
|
689
|
-
export function siRnaNucleotideToBioSpringSenseStrand(nucleotides: string) {
|
|
690
|
-
let count: number = -1;
|
|
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'};
|
|
695
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|U|G|C)/g, function (x: string) {
|
|
696
|
-
count++;
|
|
697
|
-
if (count < 2) return objForLeftEdge[x];
|
|
698
|
-
if (count > nucleotides.length - 3) return objForRightEdge[x];
|
|
699
|
-
return (count % 2 == 0) ? objForEvenIndices[x] : objForOddIndices[x];
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
//name: siRnaNucleotidesToGcrs
|
|
704
|
-
//input: string nucleotides {semType: RNA nucleotides}
|
|
705
|
-
//output: string result {semType: GCRS}
|
|
706
|
-
export function siRnaNucleotidesToGcrs(nucleotides: string) {
|
|
707
|
-
let count: number = -1;
|
|
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'};
|
|
712
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|U|G|C)/g, function (x: string) {
|
|
713
|
-
count++;
|
|
714
|
-
if (count < 2) return objForLeftEdge[x];
|
|
715
|
-
if (count > nucleotides.length - 3) return objForRightEdge[x];
|
|
716
|
-
return (count % 2 == 0) ? objForEvenIndices[x] : objForOddIndices[x];
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
//name: siRnaNucleotideToAxolabsSenseStrand
|
|
721
|
-
//input: string nucleotides {semType: RNA nucleotides}
|
|
722
|
-
//output: string result {semType: Axolabs}
|
|
723
|
-
export function siRnaNucleotideToAxolabsSenseStrand(nucleotides: string) {
|
|
724
|
-
let count: number = -1;
|
|
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'};
|
|
728
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|U|G|C)/g, function (x: string) {
|
|
729
|
-
count++;
|
|
730
|
-
if (count < 2) return objForLeftEdge[x];
|
|
731
|
-
if (count == 6 || (count > 7 && count < 11)) return objForSomeIndices[x]
|
|
732
|
-
if (count == nucleotides.length - 1) return 'a';
|
|
733
|
-
return obj[x];
|
|
734
|
-
});
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
//name: siRnaNucleotideToAxolabsAntisenseStrand
|
|
738
|
-
//input: string nucleotides {semType: RNA nucleotides}
|
|
739
|
-
//output: string result {semType: Axolabs}
|
|
740
|
-
export function siRnaNucleotideToAxolabsAntisenseStrand(nucleotides: string) {
|
|
741
|
-
let count: number = -1;
|
|
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'};
|
|
746
|
-
return nucleotides.replace(/(\(invabasic\)|\(GalNAc-2-JNJ\)|A|U|G|C)/g, function (x: string) {
|
|
747
|
-
count++;
|
|
748
|
-
if (count > 19 && count < 22) return objForSmallLinkages[x];
|
|
749
|
-
if (count == 0) return 'us';
|
|
750
|
-
if (count == 1) return objForBigLinkages[x];
|
|
751
|
-
return (count == 5 || count == 7 || count == 8 || count == 13 || count == 15) ? objForSomeIndices[x] : obj[x];
|
|
752
|
-
});
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
//name: gcrsToNucleotides
|
|
756
|
-
//input: string nucleotides {semType: GCRS}
|
|
757
|
-
//output: string result {semType: RNA nucleotides}
|
|
758
|
-
export function gcrsToNucleotides(nucleotides: string) {
|
|
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'
|
|
762
|
-
};
|
|
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];});
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
//name: gcrsToMermade12
|
|
767
|
-
//input: string nucleotides {semType: GCRS}
|
|
768
|
-
//output: string result {semType: Mermade 12 / siRNA}
|
|
769
|
-
export function gcrsToMermade12(nucleotides: string) {
|
|
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'
|
|
773
|
-
};
|
|
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]});
|
|
247
|
+
.css('width', '100%');
|
|
775
248
|
}
|
|
776
249
|
|
|
777
250
|
async function saveTableAsSdFile(table: DG.DataFrame) {
|
|
778
|
-
if (!table.columns.contains('Compound Name'))
|
|
779
|
-
grok.shell.warning(
|
|
780
|
-
|
|
251
|
+
if (!table.columns.contains('Compound Name')) {
|
|
252
|
+
grok.shell.warning(
|
|
253
|
+
'File saved without columns \'Compound Name\', \'Compound Components\', \'Cpd MW\', \'Salt mass\', \'Batch MW\'');
|
|
254
|
+
}
|
|
255
|
+
const structureColumn = table.columns.byName('Sequence');
|
|
781
256
|
let result = '';
|
|
782
257
|
for (let i = 0; i < table.rowCount; i++) {
|
|
783
258
|
try {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
let mol = new OCL.Molecule.fromSmiles(smiles);
|
|
259
|
+
const smiles = sequenceToSmiles(structureColumn.get(i));
|
|
260
|
+
const mol = OCL.Molecule.fromSmiles(smiles);
|
|
787
261
|
result += `\n${mol.toMolfile()}\n`;
|
|
788
|
-
for (
|
|
262
|
+
for (const col of table.columns)
|
|
789
263
|
result += `> <${col.name}>\n${col.get(i)}\n\n`;
|
|
790
264
|
result += '$$$$';
|
|
791
|
-
}
|
|
792
|
-
catch (error) {
|
|
265
|
+
} catch (error) {
|
|
793
266
|
console.error(error);
|
|
794
267
|
}
|
|
795
268
|
}
|
|
796
|
-
|
|
269
|
+
const element = document.createElement('a');
|
|
797
270
|
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
|
|
798
271
|
element.setAttribute('download', table.name + '.sdf');
|
|
799
272
|
element.click();
|
|
800
273
|
}
|
|
801
274
|
|
|
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
275
|
//tags: autostart
|
|
810
276
|
export function autostartOligoSdFileSubscription() {
|
|
811
277
|
grok.events.onViewAdded.subscribe((v: any) => {
|
|
@@ -814,75 +280,69 @@ export function autostartOligoSdFileSubscription() {
|
|
|
814
280
|
});
|
|
815
281
|
}
|
|
816
282
|
|
|
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
283
|
export function oligoSdFile(table: DG.DataFrame) {
|
|
835
|
-
|
|
836
|
-
function addColumns(t: DG.DataFrame) {
|
|
284
|
+
const saltsDf = DG.DataFrame.fromCsv(SALTS_CSV);
|
|
285
|
+
function addColumns(t: DG.DataFrame, saltsDf: DG.DataFrame) {
|
|
837
286
|
if (t.columns.contains('Compound Name'))
|
|
838
287
|
return grok.shell.error('Columns already exist!');
|
|
839
288
|
|
|
840
289
|
table.col('Source')?.init('Johnson and Johnson Pharma');
|
|
841
290
|
table.col('ICD')?.init('No Contract');
|
|
842
291
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
292
|
+
const sequence = t.col('Sequence')!;
|
|
293
|
+
const salt = t.col('Salt')!;
|
|
294
|
+
const equivalents = t.col('Equivalents')!;
|
|
846
295
|
|
|
847
296
|
t.columns.addNewString('Compound Name').init((i: number) => sequence.get(i));
|
|
848
297
|
t.columns.addNewString('Compound Comments').init((i: number) => (i > 0 && i % 2 == 0) ?
|
|
849
298
|
sequence.getString(i) + '; duplex of SS: ' + sequence.getString(i - 2) + ' and AS: ' + sequence.getString(i - 1) :
|
|
850
|
-
sequence.getString(i)
|
|
299
|
+
sequence.getString(i),
|
|
851
300
|
);
|
|
852
|
-
|
|
853
|
-
|
|
301
|
+
const chargeCol = saltsDf.col('CHARGE')!.toList();
|
|
302
|
+
const saltNames = saltsDf.col('DISPLAY')!.toList();
|
|
303
|
+
const molWeight = saltsDf.col('MOLWEIGHT')!.toList();
|
|
304
|
+
t.columns.addNewFloat('Cpd MW').init((i: number) => ((i + 1) % 3 == 0) ? DG.FLOAT_NULL : molWeight[i]);
|
|
305
|
+
t.columns.addNewFloat('Salt mass').init((i: number) => {
|
|
306
|
+
const v = chargeCol[saltNames.indexOf(salt.get(i))];
|
|
307
|
+
const n = (v == null) ? 0 : chargeCol[saltNames.indexOf(salt.get(i))];
|
|
308
|
+
return n * equivalents.get(i);
|
|
309
|
+
});
|
|
854
310
|
t.columns.addNewCalculated('Batch MW', '${Cpd MW} + ${Salt mass}', DG.COLUMN_TYPE.FLOAT, false);
|
|
855
311
|
|
|
856
312
|
addColumnsPressed = true;
|
|
857
313
|
return newDf = t;
|
|
858
314
|
}
|
|
859
315
|
|
|
860
|
-
const columnsOrder = [
|
|
861
|
-
|
|
316
|
+
const columnsOrder = ['Chemistry', 'Number', 'Type', 'Chemistry Name', 'Internal compound ID',
|
|
317
|
+
'IDP', 'Sequence', 'Compound Name', 'Compound Comments', 'Salt', 'Equivalents', 'Purity', 'Cpd MW', 'Salt mass',
|
|
318
|
+
'Batch MW', 'Source', 'ICD', 'Owner'];
|
|
862
319
|
let newDf: DG.DataFrame;
|
|
863
320
|
let addColumnsPressed = false;
|
|
864
321
|
|
|
865
|
-
|
|
322
|
+
const d = ui.div([
|
|
866
323
|
ui.icons.edit(() => {
|
|
867
324
|
d.innerHTML = '';
|
|
868
325
|
d.append(
|
|
869
326
|
ui.link('Add Columns', async () => {
|
|
870
|
-
await addColumns(table);
|
|
327
|
+
await addColumns(table, saltsDf);
|
|
871
328
|
grok.shell.tableView(table.name).grid.columns.setOrder(columnsOrder);
|
|
872
329
|
}, 'Add columns: Compound Name, Compound Components, Cpd MW, Salt mass, Batch MW', ''),
|
|
873
|
-
ui.button('Save SD file', () => saveTableAsSdFile(addColumnsPressed ? newDf : table))
|
|
330
|
+
ui.button('Save SD file', () => saveTableAsSdFile(addColumnsPressed ? newDf : table)),
|
|
874
331
|
);
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
332
|
+
const view = grok.shell.getTableView(table.name);
|
|
333
|
+
const typeCol = view.grid.col('Type')!;
|
|
334
|
+
const saltCol = view.grid.col('Salt')!;
|
|
878
335
|
saltCol.cellType = 'html';
|
|
879
336
|
typeCol.cellType = 'html';
|
|
880
|
-
view.grid.onCellPrepare(function
|
|
337
|
+
view.grid.onCellPrepare(function(gc: DG.GridCell) {
|
|
881
338
|
if (gc.isTableCell) {
|
|
882
339
|
if (gc.gridColumn.name == 'Type')
|
|
883
340
|
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,
|
|
341
|
+
else if (gc.gridColumn.name == 'Salt') {
|
|
342
|
+
gc.style.element = ui.choiceInput('', gc.cell.value, saltsDf.columns.byIndex(1).toList(), () => {
|
|
343
|
+
view.dataFrame.col('Salt')!.set(gc.gridRow, '');
|
|
344
|
+
}).root;
|
|
345
|
+
}
|
|
886
346
|
}
|
|
887
347
|
});
|
|
888
348
|
|
|
@@ -890,7 +350,7 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
890
350
|
if (table.currentCol.name == 'IDP' && typeof table.currentCell.value != 'number')
|
|
891
351
|
grok.shell.error('Value should be numeric');
|
|
892
352
|
});
|
|
893
|
-
})
|
|
353
|
+
}),
|
|
894
354
|
]);
|
|
895
355
|
grok.shell.v.setRibbonPanels([[d]]);
|
|
896
356
|
}
|