@datagrok/sequence-translator 1.0.6 → 1.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/dist/package-test.js +435 -322
- package/dist/package.js +144 -80
- package/package.json +2 -2
- package/src/__jest__/remote.test.ts +7 -6
- package/src/__jest__/test-node.ts +1 -1
- package/src/autostart/registration.ts +66 -23
- package/src/axolabs/define-pattern.ts +10 -0
- package/src/main/main-view.ts +11 -12
- package/src/structures-works/converters.ts +15 -6
- package/src/structures-works/from-monomers.ts +2 -1
- package/src/structures-works/map.ts +1 -0
- package/src/structures-works/mol-transformations.ts +2 -2
- package/src/structures-works/save-sense-antisense.ts +3 -3
- package/src/structures-works/sequence-codes-tools.ts +2 -2
- package/src/tests/smiles-tests.ts +279 -279
- package/test-SequenceTranslator-7770371320b2-ca4b554d.html +256 -0
- package/test-SequenceTranslator-d3cbf13cf137-2cb8277f.html +0 -276
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.8",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Vadym Kovadlo",
|
|
7
7
|
"email": "vkovadlo@datagrok.ai"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"directory": "packages/SequenceTranslator"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@datagrok-libraries/utils": "^
|
|
16
|
+
"@datagrok-libraries/utils": "^1.9.2",
|
|
17
17
|
"@types/react": "^18.0.15",
|
|
18
18
|
"datagrok-api": "^1.6.0",
|
|
19
19
|
"datagrok-tools": "^4.1.2",
|
|
@@ -42,19 +42,20 @@ it('TEST', async () => {
|
|
|
42
42
|
let r = await page.evaluate((targetPackage):Promise<object> => {
|
|
43
43
|
return new Promise<object>((resolve, reject) => {
|
|
44
44
|
(<any>window).grok.functions.eval(targetPackage + ':test()').then((df: any) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
const cStatus = df.columns.byName('success');
|
|
46
|
+
const cMessage = df.columns.byName('result');
|
|
47
|
+
const cCat = df.columns.byName('category');
|
|
48
|
+
const cName = df.columns.byName('name');
|
|
49
|
+
const cTime = df.columns.byName('ms');
|
|
49
50
|
let failed = false;
|
|
50
51
|
let passReport = '';
|
|
51
52
|
let failReport = '';
|
|
52
53
|
for (let i = 0; i < df.rowCount; i++) {
|
|
53
54
|
if (cStatus.get(i)) {
|
|
54
|
-
passReport += `Test result : Success : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
55
|
+
passReport += `Test result : Success : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
55
56
|
} else {
|
|
56
57
|
failed = true;
|
|
57
|
-
failReport += `Test result : Failed : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
58
|
+
failReport += `Test result : Failed : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
resolve({failReport, passReport, failed});
|
|
@@ -75,7 +75,7 @@ export async function getBrowserPage(puppeteer: any): Promise<{browser: any, pag
|
|
|
75
75
|
}, token);
|
|
76
76
|
await page.goto(url);
|
|
77
77
|
try {
|
|
78
|
-
await page.waitForSelector('.grok-preloader', { timeout: 1800000 });
|
|
78
|
+
// await page.waitForSelector('.grok-preloader', { timeout: 1800000 });
|
|
79
79
|
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout: 3600000});
|
|
80
80
|
} catch (error) {
|
|
81
81
|
throw error;
|
|
@@ -4,7 +4,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
import {siRnaAxolabsToGcrs, gcrsToNucleotides, asoGapmersBioSpringToGcrs, gcrsToMermade12,
|
|
5
5
|
} from '../structures-works/converters';
|
|
6
6
|
import {map, COL_NAMES, MODIFICATIONS} from '../structures-works/map';
|
|
7
|
-
import {
|
|
7
|
+
import {isValidSequence} from '../structures-works/sequence-codes-tools';
|
|
8
8
|
import {sequenceToMolV3000} from '../structures-works/from-monomers';
|
|
9
9
|
|
|
10
10
|
import {SALTS_CSV} from '../salts';
|
|
@@ -22,6 +22,26 @@ function stringify(items: string[]): string {
|
|
|
22
22
|
return '["' + items.join('", "') + '"]';
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
function saltMass(saltNames: string[], molWeightCol: DG.Column, equivalentsCol: DG.Column, i: number,
|
|
26
|
+
saltCol: DG.Column) {
|
|
27
|
+
const saltRowIndex = saltNames.indexOf(saltCol.get(i));
|
|
28
|
+
return (
|
|
29
|
+
saltRowIndex == -1 || molWeightCol.get(saltRowIndex) == DG.FLOAT_NULL || equivalentsCol.get(i) == DG.INT_NULL) ?
|
|
30
|
+
DG.FLOAT_NULL :
|
|
31
|
+
molWeightCol.get(saltRowIndex) * equivalentsCol.get(i);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function saltMolWeigth(saltNamesList: string[], saltCol: DG.Column, molWeightCol: DG.Column, i: number) {
|
|
35
|
+
const saltRowIndex = saltNamesList.indexOf(saltCol.get(i));
|
|
36
|
+
return (saltRowIndex == -1) ? DG.FLOAT_NULL : molWeightCol.get(saltRowIndex);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function batchMolWeight(compoundMolWeightCol: DG.Column, saltMassCol: DG.Column, i: number) {
|
|
40
|
+
return (compoundMolWeightCol.getString(i) == '' || saltMassCol.getString(i) == '') ?
|
|
41
|
+
DG.FLOAT_NULL :
|
|
42
|
+
compoundMolWeightCol.get(i) + saltMassCol.get(i);
|
|
43
|
+
}
|
|
44
|
+
|
|
25
45
|
function molecularWeight(sequence: string, weightsObj: {[index: string]: number}): number {
|
|
26
46
|
const codes = sortByStringLengthInDescendingOrder(Object.keys(weightsObj)).concat(Object.keys(MODIFICATIONS));
|
|
27
47
|
let weight = 0;
|
|
@@ -48,13 +68,13 @@ async function saveTableAsSdFile(table: DG.DataFrame) {
|
|
|
48
68
|
for (let i = 0; i < table.rowCount; i++) {
|
|
49
69
|
const format = 'Janssen GCRS Codes'; //getFormat(structureColumn.get(i))!;
|
|
50
70
|
result += (typeColumn.get(i) == 'SS') ?
|
|
51
|
-
sequenceToMolV3000(structureColumn.get(i), false, true, format) + '\n' + `>
|
|
52
|
-
sequenceToMolV3000(structureColumn.get(i), true, true, format) + '\n' + `>
|
|
71
|
+
sequenceToMolV3000(structureColumn.get(i), false, true, format) + '\n' + `> <Sequence>\nSense Strand\n\n` :
|
|
72
|
+
sequenceToMolV3000(structureColumn.get(i), true, true, format) + '\n' + `> <Sequence>\nAnti Sense\n\n`;
|
|
53
73
|
for (const col of table.columns) {
|
|
54
74
|
if (col.name != COL_NAMES.SEQUENCE)
|
|
55
|
-
result += `>
|
|
75
|
+
result += `> <${col.name}>\n${col.get(i)}\n\n`;
|
|
56
76
|
}
|
|
57
|
-
result += '$$$$\n
|
|
77
|
+
result += '$$$$\n';
|
|
58
78
|
}
|
|
59
79
|
const element = document.createElement('a');
|
|
60
80
|
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
|
|
@@ -117,22 +137,30 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
117
137
|
const icdsDf = DG.DataFrame.fromCsv(ICDS);
|
|
118
138
|
const idpsDf = DG.DataFrame.fromCsv(IDPS);
|
|
119
139
|
|
|
120
|
-
|
|
140
|
+
const sequenceCol = table.getCol(COL_NAMES.SEQUENCE);
|
|
141
|
+
const saltCol = table.getCol(COL_NAMES.SALT);
|
|
142
|
+
const equivalentsCol = table.getCol(COL_NAMES.EQUIVALENTS);
|
|
143
|
+
const typeColumn = table.getCol(COL_NAMES.TYPE);
|
|
144
|
+
|
|
145
|
+
const molWeightCol = saltsDf.getCol('MOLWEIGHT');
|
|
146
|
+
const saltNamesList = saltsDf.getCol('DISPLAY').toList();
|
|
147
|
+
|
|
148
|
+
function addColumns(t: DG.DataFrame) {
|
|
121
149
|
if (t.columns.contains(COL_NAMES.COMPOUND_NAME))
|
|
122
150
|
return grok.shell.error('Columns already exist');
|
|
123
151
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
152
|
+
for (let i = t.rowCount - 1; i > -1; i--) {
|
|
153
|
+
if (sequenceCol.get(i) == '')
|
|
154
|
+
t.rows.removeAt(i, 1, false);
|
|
155
|
+
}
|
|
127
156
|
|
|
128
157
|
t.columns.addNewString(COL_NAMES.COMPOUND_NAME).init((i: number) => sequenceCol.get(i));
|
|
129
158
|
|
|
130
|
-
t.columns.addNewString(COL_NAMES.COMPOUND_COMMENTS).init((i: number) => (i >
|
|
159
|
+
t.columns.addNewString(COL_NAMES.COMPOUND_COMMENTS).init((i: number) => (i > 2 && typeColumn.get(i) == 'Duplex') ?
|
|
131
160
|
sequenceCol.get(i) + '; duplex of SS: ' + sequenceCol.get(i - 2) + ' and AS: ' + sequenceCol.get(i - 1) :
|
|
132
161
|
sequenceCol.get(i),
|
|
133
162
|
);
|
|
134
|
-
|
|
135
|
-
const saltNamesList = saltsDf.getCol('DISPLAY').toList();
|
|
163
|
+
|
|
136
164
|
const weightsObj: {[code: string]: number} = {};
|
|
137
165
|
for (const synthesizer of Object.keys(map)) {
|
|
138
166
|
for (const technology of Object.keys(map[synthesizer])) {
|
|
@@ -149,16 +177,14 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
149
177
|
DG.FLOAT_NULL;
|
|
150
178
|
});
|
|
151
179
|
|
|
152
|
-
t.columns.addNewFloat(COL_NAMES.SALT_MASS).init((i: number) =>
|
|
153
|
-
|
|
154
|
-
return (saltRowIndex == -1) ?
|
|
155
|
-
DG.FLOAT_NULL :
|
|
156
|
-
molWeightCol.get(saltRowIndex) * equivalentsCol.get(i);
|
|
157
|
-
});
|
|
180
|
+
t.columns.addNewFloat(COL_NAMES.SALT_MASS).init((i: number) =>
|
|
181
|
+
saltMass(saltNamesList, molWeightCol, equivalentsCol, i, saltCol));
|
|
158
182
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
183
|
+
t.columns.addNewFloat(COL_NAMES.SALT_MOL_WEIGHT).init((i: number) =>
|
|
184
|
+
saltMolWeigth(saltNamesList, saltCol, molWeightCol, i));
|
|
185
|
+
|
|
186
|
+
t.columns.addNewFloat(COL_NAMES.BATCH_MW).init((i: number) =>
|
|
187
|
+
batchMolWeight(t.getCol(COL_NAMES.CPD_MW), t.getCol(COL_NAMES.SALT_MASS), i));
|
|
162
188
|
|
|
163
189
|
addColumnsPressed = true;
|
|
164
190
|
return newDf = t;
|
|
@@ -173,8 +199,8 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
173
199
|
if (table.getCol(COL_NAMES.IDP).type != DG.COLUMN_TYPE.STRING)
|
|
174
200
|
table.changeColumnType(COL_NAMES.IDP, DG.COLUMN_TYPE.STRING);
|
|
175
201
|
d.append(
|
|
176
|
-
ui.link('Add Columns',
|
|
177
|
-
|
|
202
|
+
ui.link('Add Columns', () => {
|
|
203
|
+
addColumns(table);
|
|
178
204
|
view.grid.columns.setOrder(Object.values(COL_NAMES));
|
|
179
205
|
}, 'Add columns: \'' + [COL_NAMES.COMPOUND_NAME, COL_NAMES.COMPOUND_COMMENTS, COL_NAMES.CPD_MW,
|
|
180
206
|
COL_NAMES.SALT_MASS, COL_NAMES.BATCH_MW].join('\', \''), '',
|
|
@@ -197,9 +223,26 @@ export function oligoSdFile(table: DG.DataFrame) {
|
|
|
197
223
|
args.args.menu.item('Fill Column With Value', () => {
|
|
198
224
|
const v = args.args.context.table.currentCell.value;
|
|
199
225
|
args.args.context.table.currentCell.column.init(v);
|
|
226
|
+
for (let i = 0; i < view.dataFrame.rowCount; i++)
|
|
227
|
+
updateCalculatedColumns(view.dataFrame, i);
|
|
200
228
|
});
|
|
201
229
|
}
|
|
202
230
|
});
|
|
231
|
+
|
|
232
|
+
view.dataFrame.onDataChanged.subscribe(() => {
|
|
233
|
+
const colName = view.dataFrame.currentCol.name;
|
|
234
|
+
if ([COL_NAMES.SALT, COL_NAMES.EQUIVALENTS, COL_NAMES.SALT_MOL_WEIGHT].includes(colName))
|
|
235
|
+
updateCalculatedColumns(view.dataFrame, view.dataFrame.currentRowIdx);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
function updateCalculatedColumns(t: DG.DataFrame, i: number): void {
|
|
239
|
+
const smValue = saltMass(saltNamesList, molWeightCol, equivalentsCol, i, saltCol);
|
|
240
|
+
t.getCol(COL_NAMES.SALT_MASS).set(i, smValue, false);
|
|
241
|
+
const smwValue = saltMolWeigth(saltNamesList, saltCol, molWeightCol, i);
|
|
242
|
+
t.getCol(COL_NAMES.SALT_MOL_WEIGHT).set(i, smwValue, false);
|
|
243
|
+
const bmw = batchMolWeight(t.getCol(COL_NAMES.CPD_MW), t.getCol(COL_NAMES.SALT_MASS), i);
|
|
244
|
+
t.getCol(COL_NAMES.BATCH_MW).set(i, bmw, false);
|
|
245
|
+
}
|
|
203
246
|
}),
|
|
204
247
|
]);
|
|
205
248
|
grok.shell.v.setRibbonPanels([[d]]);
|
|
@@ -361,6 +361,11 @@ export function defineAxolabsPattern() {
|
|
|
361
361
|
})
|
|
362
362
|
.show();
|
|
363
363
|
}
|
|
364
|
+
if (col.get(0) != ssLength.value) {
|
|
365
|
+
const d = ui.dialog('Length was updated by value to from imported file');
|
|
366
|
+
d.add(ui.divText('Latest modifications may not take effect during translation'))
|
|
367
|
+
.onOK(() => grok.shell.info('Lengths changed')).show();
|
|
368
|
+
}
|
|
364
369
|
return allLengthsAreTheSame;
|
|
365
370
|
}
|
|
366
371
|
|
|
@@ -513,7 +518,9 @@ export function defineAxolabsPattern() {
|
|
|
513
518
|
let asPtoLinkages = Array(defaultSequenceLength).fill(ui.boolInput('', defaultPto));
|
|
514
519
|
|
|
515
520
|
const ssLength = ui.intInput('SS Length', defaultSequenceLength, () => updateUiForNewSequenceLength());
|
|
521
|
+
ssLength.setTooltip('Length of sense strand, including overhangs');
|
|
516
522
|
const asLength = ui.intInput('AS Length', defaultSequenceLength, () => updateUiForNewSequenceLength());
|
|
523
|
+
asLength.setTooltip('Length of sense strand, including overhangs');
|
|
517
524
|
const asLengthDiv = ui.div([asLength.root]);
|
|
518
525
|
|
|
519
526
|
function validateSsColumn(colName: string): void {
|
|
@@ -605,7 +612,9 @@ export function defineAxolabsPattern() {
|
|
|
605
612
|
});
|
|
606
613
|
|
|
607
614
|
const firstSsPto = ui.boolInput('First SS PTO', fullyPto.value!, () => updateSvgScheme());
|
|
615
|
+
firstSsPto.setTooltip('ps linkage before first nucleotide of sense strand');
|
|
608
616
|
const firstAsPto = ui.boolInput('First AS PTO', fullyPto.value!, () => updateSvgScheme());
|
|
617
|
+
firstAsPto.setTooltip('ps linkage before first nucleotide of antisense strand');
|
|
609
618
|
firstAsPtoDiv.append(firstAsPto.root);
|
|
610
619
|
|
|
611
620
|
const createAsStrand = ui.boolInput('Create AS Strand', true, (v: boolean) => {
|
|
@@ -617,6 +626,7 @@ export function defineAxolabsPattern() {
|
|
|
617
626
|
firstAsPtoDiv.hidden = (!v);
|
|
618
627
|
updateSvgScheme();
|
|
619
628
|
});
|
|
629
|
+
createAsStrand.setTooltip('Create antisense strand sections on SVG and table to the right');
|
|
620
630
|
|
|
621
631
|
const saveAs = ui.textInput('Save As', 'Pattern Name', () => updateSvgScheme());
|
|
622
632
|
saveAs.setTooltip('Name Of New Pattern');
|
package/src/main/main-view.ts
CHANGED
|
@@ -4,7 +4,6 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
import {convertSequence, undefinedInputSequence, isValidSequence} from '../structures-works/sequence-codes-tools';
|
|
5
5
|
import {map, MODIFICATIONS} from '../structures-works/map';
|
|
6
6
|
import {sequenceToSmiles, sequenceToMolV3000} from '../structures-works/from-monomers';
|
|
7
|
-
|
|
8
7
|
import $ from 'cash-dom';
|
|
9
8
|
|
|
10
9
|
const defaultInput = 'fAmCmGmAmCpsmU';
|
|
@@ -12,7 +11,7 @@ const sequenceWasCopied = 'Copied';
|
|
|
12
11
|
const tooltipSequence = 'Copy sequence';
|
|
13
12
|
|
|
14
13
|
export function mainView() {
|
|
15
|
-
function updateTableAndMolecule(sequence: string, inputFormat: string
|
|
14
|
+
function updateTableAndMolecule(sequence: string, inputFormat: string): void {
|
|
16
15
|
moleculeSvgDiv.innerHTML = '';
|
|
17
16
|
outputTableDiv.innerHTML = '';
|
|
18
17
|
const pi = DG.TaskBarProgressIndicator.create('Rendering table and molecule...');
|
|
@@ -20,9 +19,8 @@ export function mainView() {
|
|
|
20
19
|
try {
|
|
21
20
|
sequence = sequence.replace(/\s/g, '');
|
|
22
21
|
const output = isValidSequence(sequence, null);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
inputFormatChoiceInput.value = output.synthesizer![0];
|
|
22
|
+
output.synthesizer = [inputFormat];
|
|
23
|
+
// inputFormatChoiceInput.value = output.synthesizer![0];
|
|
26
24
|
const outputSequenceObj = convertSequence(sequence, output);
|
|
27
25
|
const tableRows = [];
|
|
28
26
|
|
|
@@ -101,14 +99,15 @@ export function mainView() {
|
|
|
101
99
|
}
|
|
102
100
|
}
|
|
103
101
|
|
|
104
|
-
const inputFormatChoiceInput = ui.choiceInput(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
102
|
+
const inputFormatChoiceInput = ui.choiceInput('Input format: ', 'Janssen GCRS Codes', Object.keys(map));
|
|
103
|
+
inputFormatChoiceInput.onInput((format: string) => {
|
|
104
|
+
updateTableAndMolecule(inputSequenceField.value.replace(/\s/g, ''), format);
|
|
105
|
+
});
|
|
108
106
|
const moleculeSvgDiv = ui.block([]);
|
|
109
107
|
const outputTableDiv = ui.div([]);
|
|
110
|
-
const inputSequenceField = ui.textInput('', defaultInput, (sequence: string) =>
|
|
111
|
-
|
|
108
|
+
const inputSequenceField = ui.textInput('', defaultInput, (sequence: string) => {
|
|
109
|
+
updateTableAndMolecule(sequence, inputFormatChoiceInput.value!);
|
|
110
|
+
});
|
|
112
111
|
|
|
113
112
|
const asoDf = DG.DataFrame.fromObjects([
|
|
114
113
|
{'Name': '2\'MOE-5Me-rU', 'BioSpring': '5', 'Janssen GCRS': 'moeT'},
|
|
@@ -151,7 +150,7 @@ export function mainView() {
|
|
|
151
150
|
DG.Column.fromStrings('Name', Object.keys(MODIFICATIONS)),
|
|
152
151
|
])!, {showRowHeader: false, showCellTooltip: false},
|
|
153
152
|
);
|
|
154
|
-
updateTableAndMolecule(defaultInput, inputFormatChoiceInput.value
|
|
153
|
+
updateTableAndMolecule(defaultInput, inputFormatChoiceInput.value!);
|
|
155
154
|
|
|
156
155
|
const codesTablesDiv = ui.splitV([
|
|
157
156
|
ui.box(ui.h2('ASO Gapmers'), {style: {maxHeight: '40px'}}),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {lcmsToGcrs} from './map';
|
|
2
2
|
import * as DG from 'datagrok-api/dg';
|
|
3
|
-
|
|
3
|
+
import {delimiter} from './map';
|
|
4
4
|
//name: gcrsToLcms
|
|
5
5
|
//input: string nucleotides {semType: GCRS}
|
|
6
6
|
//output: string result {semType: LCMS}
|
|
@@ -10,12 +10,21 @@ export function gcrsToLcms(sequence: string): string {
|
|
|
10
10
|
const arr2 = df.getCol('LCMS').toList();
|
|
11
11
|
const obj: {[i: string]: string} = {};
|
|
12
12
|
arr1.forEach((element, index) => obj[element] = arr2[index]);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
obj[delimiter] = delimiter;
|
|
14
|
+
// for (let i = 0; i < arr1.length; i++) {
|
|
15
|
+
// arr1[i] = arr1[i].replace('(', '\\(');
|
|
16
|
+
// arr1[i] = arr1[i].replace(')', '\\)');
|
|
17
|
+
// }
|
|
18
|
+
// const regExp = new RegExp('(' + arr1.join('|') + ')', 'g');
|
|
19
|
+
// let r1 = sequence.replace(regExp, function(code) {return obj[code];});
|
|
20
|
+
const codes = arr1.concat(delimiter).sort(function(a, b) {return b.length - a.length;});
|
|
21
|
+
let i = 0;
|
|
22
|
+
let r1 = '';
|
|
23
|
+
while (i < sequence.length) {
|
|
24
|
+
const matchedCode = codes.find((c) => c == sequence.slice(i, i + c.length));
|
|
25
|
+
r1 += obj[sequence.slice(i, i + matchedCode.length)];
|
|
26
|
+
i += matchedCode.length;
|
|
16
27
|
}
|
|
17
|
-
const regExp = new RegExp('(' + arr1.join('|') + ')', 'g');
|
|
18
|
-
let r1 = sequence.replace(regExp, function(code) {return obj[code];});
|
|
19
28
|
while (r1.indexOf('//') != -1)
|
|
20
29
|
r1 = r1.replace('//', '/');
|
|
21
30
|
return r1;
|
|
@@ -22,7 +22,8 @@ export function sequenceToMolV3000(sequence: string, inverted: boolean = false,
|
|
|
22
22
|
if (dropdowns.includes(codesList[i])) {
|
|
23
23
|
smilesCodes.push((i >= codesList.length / 2) ?
|
|
24
24
|
MODIFICATIONS[codesList[i]].right : MODIFICATIONS[codesList[i]].left);
|
|
25
|
-
|
|
25
|
+
if (!(i < codesList.length - 1 && links.includes(codesList[i + 1])))
|
|
26
|
+
smilesCodes.push(stadardPhosphateLinkSmiles);
|
|
26
27
|
} else {
|
|
27
28
|
if (links.includes(codesList[i]) ||
|
|
28
29
|
includesStandardLinkAlready.includes(codesList[i]) ||
|
|
@@ -56,7 +56,7 @@ M V30 BEGIN ATOM
|
|
|
56
56
|
M V30 1 O 1.0934 -2.1636 0 0
|
|
57
57
|
M V30 2 C 1.8365 -1.4945 0 0 CFG=2
|
|
58
58
|
M V30 3 C 2.8147 -1.7024 0 0
|
|
59
|
-
M V30 4 C 3.3147 -0.8364 0 0
|
|
59
|
+
M V30 4 C 3.3147 -0.8364 0 0
|
|
60
60
|
M V30 5 O 2.6455 -0.0932 0 0
|
|
61
61
|
M V30 6 C 1.732 -0.5 0 0 CFG=1
|
|
62
62
|
M V30 7 C 0.866 0 0 0
|
|
@@ -250,7 +250,7 @@ export function linkV3000(molBlocks: string[], twoChains: boolean = false, useCh
|
|
|
250
250
|
macroMolBlock = macroMolBlock.replace(/ CFG=\d/g, ' ');
|
|
251
251
|
|
|
252
252
|
macroMolBlock += 'M V30 END CTAB\n';
|
|
253
|
-
macroMolBlock += 'M END
|
|
253
|
+
macroMolBlock += 'M END';
|
|
254
254
|
|
|
255
255
|
return macroMolBlock;
|
|
256
256
|
}
|
|
@@ -10,13 +10,13 @@ export function saveSdf(as: string, ss: string, oneEntity: boolean, useChirality
|
|
|
10
10
|
const molAS = sequenceToMolV3000(as, invertAS, false, formatAs!);
|
|
11
11
|
let result: string;
|
|
12
12
|
if (oneEntity)
|
|
13
|
-
result = linkV3000([molSS, molAS], true, useChirality) + '\n
|
|
13
|
+
result = linkV3000([molSS, molAS], true, useChirality) + '\n$$$$\n';
|
|
14
14
|
else {
|
|
15
15
|
result =
|
|
16
16
|
molSS + '\n' +
|
|
17
|
-
`>
|
|
17
|
+
`> <Sequence>\nSense Strand\n$$$$\n` +
|
|
18
18
|
molAS + '\n' +
|
|
19
|
-
`>
|
|
19
|
+
`> <Sequence>\nAnti Sense\n$$$$\n`;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const element = document.createElement('a');
|
|
@@ -170,8 +170,8 @@ export function isValidSequence(sequence: string, format: string | null): {
|
|
|
170
170
|
// })
|
|
171
171
|
// .show();
|
|
172
172
|
// } else if (possibleTechnologies.length == 0)
|
|
173
|
-
if (possibleTechnologies.length == 0)
|
|
174
|
-
|
|
173
|
+
// if (possibleTechnologies.length == 0)
|
|
174
|
+
// return {indexOfFirstNotValidChar: 0, synthesizer: [possibleSynthesizers[3]], technology: null};
|
|
175
175
|
|
|
176
176
|
outputIndex = 0;
|
|
177
177
|
|