@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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/sequence-translator",
3
3
  "friendlyName": "Sequence Translator",
4
- "version": "1.0.6",
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": "^0.1.0",
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
- let cStatus = df.columns.byName('success');
46
- let cMessage = df.columns.byName('result');
47
- let cCat = df.columns.byName('category');
48
- let cName = df.columns.byName('name');
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 {getFormat, isValidSequence} from '../structures-works/sequence-codes-tools';
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' + `> <Sequence>\nSense Strand\n\n` :
52
- sequenceToMolV3000(structureColumn.get(i), true, true, format) + '\n' + `> <Sequence>\nAnti Sense\n\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 += `> <${col.name}>\n${col.get(i)}\n\n`;
75
+ result += `> <${col.name}>\n${col.get(i)}\n\n`;
56
76
  }
57
- result += '$$$$\n\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
- async function addColumns(t: DG.DataFrame, saltsDf: DG.DataFrame) {
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
- const sequenceCol = t.getCol(COL_NAMES.SEQUENCE);
125
- const saltCol = t.getCol(COL_NAMES.SALT);
126
- const equivalentsCol = t.getCol(COL_NAMES.EQUIVALENTS);
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 > 0 && i % 2 == 0) ?
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
- const molWeightCol = saltsDf.getCol('MOLWEIGHT');
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
- const saltRowIndex = saltNamesList.indexOf(saltCol.get(i));
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
- await t.columns.addNewCalculated(COL_NAMES.BATCH_MW,
160
- '${' + COL_NAMES.CPD_MW + '} + ${' + COL_NAMES.SALT_MASS + '}', DG.COLUMN_TYPE.FLOAT, false,
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', async () => {
177
- await addColumns(table, saltsDf);
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');
@@ -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, isSet: boolean): void {
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
- if (isSet)
24
- output.synthesizer = [inputFormat];
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
- 'Input format: ', 'Janssen GCRS Codes', Object.keys(map), (format: string) => {
106
- updateTableAndMolecule(inputSequenceField.value.replace(/\s/g, ''), format, true);
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) => updateTableAndMolecule(sequence,
111
- inputFormatChoiceInput.value!, false));
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!, true);
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
- for (let i = 0; i < arr1.length; i++) {
14
- arr1[i] = arr1[i].replace('(', '\\(');
15
- arr1[i] = arr1[i].replace(')', '\\)');
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
- smilesCodes.push(stadardPhosphateLinkSmiles);
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]) ||
@@ -30,6 +30,7 @@ export const COL_NAMES = {
30
30
  EQUIVALENTS: 'Equivalents',
31
31
  PURITY: 'Purity',
32
32
  CPD_MW: 'Cpd MW',
33
+ SALT_MOL_WEIGHT: 'Salt MW',
33
34
  SALT_MASS: 'Salt mass',
34
35
  BATCH_MW: 'Batch MW',
35
36
  SOURCE: 'Source',
@@ -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 VAL=3
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\n';
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\n$$$$\n';
13
+ result = linkV3000([molSS, molAS], true, useChirality) + '\n$$$$\n';
14
14
  else {
15
15
  result =
16
16
  molSS + '\n' +
17
- `> <Sequence>\nSense Strand\n\n$$$$\n` +
17
+ `> <Sequence>\nSense Strand\n$$$$\n` +
18
18
  molAS + '\n' +
19
- `> <Sequence>\nAnti Sense\n\n$$$$\n`;
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
- return {indexOfFirstNotValidChar: 0, synthesizer: [possibleSynthesizers[3]], technology: null};
173
+ // if (possibleTechnologies.length == 0)
174
+ // return {indexOfFirstNotValidChar: 0, synthesizer: [possibleSynthesizers[3]], technology: null};
175
175
 
176
176
  outputIndex = 0;
177
177