@datagrok/sequence-translator 0.0.9 → 1.0.1

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,14 +1,19 @@
1
1
  {
2
2
  "name": "@datagrok/sequence-translator",
3
3
  "friendlyName": "Sequence Translator",
4
- "version": "0.0.9",
5
- "description": "",
4
+ "version": "1.0.1",
5
+ "description": "SequenceTranslator is a [package](https://datagrok.ai/help/develop/develop#packages) for the [Datagrok](https://datagrok.ai) platform, used to translate [oligonucleotide](https://en.wikipedia.org/wiki/Oligonucleotide) sequences between [different representations](https://github.com/datagrok-ai/public/tree/master/packages/SequenceTranslator#sequence-representations).",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/datagrok-ai/public.git",
9
+ "directory": "packages/SequenceTranslator"
10
+ },
6
11
  "dependencies": {
7
12
  "@datagrok-libraries/utils": "^0.1.0",
8
13
  "@types/react": "latest",
9
- "datagrok-api": ">0.94.10",
14
+ "datagrok-api": "^1.1.7",
10
15
  "datagrok-tools": "^4.1.2",
11
- "npm": "^7.11.2",
16
+ "npm": "^8.11.0",
12
17
  "save-svg-as-png": "^1.4.17",
13
18
  "ts-loader": "latest",
14
19
  "typescript": "latest",
@@ -28,6 +33,9 @@
28
33
  "test-dev": "set HOST=dev && jest",
29
34
  "test-local": "set HOST=localhost && jest"
30
35
  },
36
+ "sources": [
37
+ "css/style.css"
38
+ ],
31
39
  "devDependencies": {
32
40
  "@typescript-eslint/eslint-plugin": "^4.29.1",
33
41
  "@typescript-eslint/parser": "^4.29.1",
@@ -36,10 +44,11 @@
36
44
  "eslint-config-google": "^0.14.0",
37
45
  "webpack": "^5.31.0",
38
46
  "webpack-cli": "^4.6.0",
39
- "@types/jest": "latest",
40
- "jest": "latest",
41
- "jest-html-reporter": "latest",
42
- "puppeteer": "^13.1.2",
43
- "ts-jest": "^27.1.2"
44
- }
47
+ "jest-html-reporter": "^3.5.0",
48
+ "jest": "^27.0.0",
49
+ "@types/jest": "^27.0.0",
50
+ "ts-jest": "^27.0.0",
51
+ "puppeteer": "^13.7.0"
52
+ },
53
+ "category": "Bioinformatics"
45
54
  }
@@ -114,7 +114,7 @@ export function defineAxolabsPattern() {
114
114
  asPtoLinkages = asPtoLinkages.concat(Array(maximalAsLength - asBases.length).fill(fullyPto));
115
115
  asBases = asBases.concat(Array(maximalAsLength - asBases.length).fill(sequenceBase));
116
116
  let nucleotideCounter = 0;
117
- for (let i = 0; i < asLength.value; i++) {
117
+ for (let i = 0; i < asLength.value!; i++) {
118
118
  asPtoLinkages[i] = ui.boolInput('', asPtoLinkages[i].value, () => {
119
119
  updateSvgScheme();
120
120
  updateOutputExamples();
@@ -157,7 +157,7 @@ export function defineAxolabsPattern() {
157
157
  ssPtoLinkages = ssPtoLinkages.concat(Array(maximalSsLength - ssBases.length).fill(fullyPto));
158
158
  ssBases = ssBases.concat(Array(maximalSsLength - ssBases.length).fill(sequenceBase));
159
159
  let nucleotideCounter = 0;
160
- for (let i = 0; i < ssLength.value; i++) {
160
+ for (let i = 0; i < ssLength.value!; i++) {
161
161
  ssPtoLinkages[i] = ui.boolInput('', ssPtoLinkages[i].value, () => {
162
162
  updateSvgScheme();
163
163
  updateOutputExamples();
@@ -196,11 +196,11 @@ export function defineAxolabsPattern() {
196
196
  }
197
197
 
198
198
  function updateUiForNewSequenceLength() {
199
- if (ssLength.value < maximalValidSequenceLength && asLength.value < maximalValidSequenceLength) {
200
- if (ssLength.value > maximalSsLength)
201
- maximalSsLength = ssLength.value;
202
- if (asLength.value > maximalAsLength)
203
- maximalAsLength = asLength.value;
199
+ if (ssLength.value! < maximalValidSequenceLength && asLength.value! < maximalValidSequenceLength) {
200
+ if (ssLength.value! > maximalSsLength)
201
+ maximalSsLength = ssLength.value!;
202
+ if (asLength.value! > maximalAsLength)
203
+ maximalAsLength = asLength.value!;
204
204
  updateSsModification();
205
205
  updateAsModification();
206
206
  updateSvgScheme();
@@ -236,17 +236,17 @@ export function defineAxolabsPattern() {
236
236
  }
237
237
 
238
238
  function updateInputExamples() {
239
- ssInputExample.value = generateExample(ssLength.value, sequenceBase.value);
239
+ ssInputExample.value = generateExample(ssLength.value!, sequenceBase.value!);
240
240
  if (createAsStrand.value)
241
- asInputExample.value = generateExample(asLength.value, sequenceBase.value);
241
+ asInputExample.value = generateExample(asLength.value!, sequenceBase.value!);
242
242
  }
243
243
 
244
244
  function updateOutputExamples() {
245
245
  ssOutputExample.value = translateSequence(
246
- ssInputExample.value, ssBases, ssPtoLinkages, ssFiveModification, ssThreeModification, firstSsPto.value);
246
+ ssInputExample.value, ssBases, ssPtoLinkages, ssFiveModification, ssThreeModification, firstSsPto.value!);
247
247
  if (createAsStrand.value) {
248
248
  asOutputExample.value = translateSequence(
249
- asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstAsPto.value);
249
+ asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstAsPto.value!);
250
250
  }
251
251
  }
252
252
 
@@ -256,11 +256,11 @@ export function defineAxolabsPattern() {
256
256
  ui.span([
257
257
  drawAxolabsPattern(
258
258
  getShortName(saveAs.value),
259
- createAsStrand.value,
260
- ssBases.slice(0, ssLength.value).map((e) => e.value),
261
- asBases.slice(0, asLength.value).map((e) => e.value),
262
- [firstSsPto.value].concat(ssPtoLinkages.slice(0, ssLength.value).map((e) => e.value)),
263
- [firstAsPto.value].concat(asPtoLinkages.slice(0, asLength.value).map((e) => e.value)),
259
+ createAsStrand.value!,
260
+ ssBases.slice(0, ssLength.value!).map((e) => e.value),
261
+ asBases.slice(0, asLength.value!).map((e) => e.value),
262
+ [firstSsPto.value!].concat(ssPtoLinkages.slice(0, ssLength.value!).map((e) => e.value)),
263
+ [firstAsPto.value!].concat(asPtoLinkages.slice(0, asLength.value!).map((e) => e.value)),
264
264
  ssThreeModification.value,
265
265
  ssFiveModification.value,
266
266
  asThreeModification.value,
@@ -329,7 +329,7 @@ export function defineAxolabsPattern() {
329
329
  }
330
330
 
331
331
  function checkWhetherAllValuesInColumnHaveTheSameLength(colName: string): boolean {
332
- const col = tables.value.columns.byName(colName);
332
+ const col = tables.value!.columns.byName(colName);
333
333
  let allLengthsAreTheSame = true;
334
334
  for (let i = 1; i < col.length; i++) {
335
335
  if (col.get(i - 1).length != col.get(i).length) {
@@ -344,10 +344,10 @@ export function defineAxolabsPattern() {
344
344
  .add(ui.divText('The sequence length should match the number of Raw sequences in the input file'))
345
345
  .add(ui.divText('\'ADD COLUMN\' to see sequences lengths'))
346
346
  .addButton('ADD COLUMN', () => {
347
- tables.value.columns.addNewInt('Sequences lengths in ' + colName).init((j: number) => col.get(j).length);
348
- grok.shell.info('Column with lengths added to \'' + tables.value.name + '\'');
347
+ tables.value!.columns.addNewInt('Sequences lengths in ' + colName).init((j: number) => col.get(j).length);
348
+ grok.shell.info('Column with lengths added to \'' + tables.value!.name + '\'');
349
349
  dialog.close();
350
- grok.shell.v = grok.shell.getTableView(tables.value.name);
350
+ grok.shell.v = grok.shell.getTableView(tables.value!.name);
351
351
  })
352
352
  .show();
353
353
  }
@@ -368,10 +368,10 @@ export function defineAxolabsPattern() {
368
368
  userStorageKey,
369
369
  saveAs.stringValue,
370
370
  JSON.stringify({
371
- 'ssBases': ssBases.slice(0, ssLength.value).map((e) => e.value),
372
- 'asBases': asBases.slice(0, asLength.value).map((e) => e.value),
373
- 'ssPtoLinkages': [firstSsPto.value].concat(ssPtoLinkages.slice(0, ssLength.value).map((e) => e.value)),
374
- 'asPtoLinkages': [firstAsPto.value].concat(asPtoLinkages.slice(0, asLength.value).map((e) => e.value)),
371
+ 'ssBases': ssBases.slice(0, ssLength.value!).map((e) => e.value),
372
+ 'asBases': asBases.slice(0, asLength.value!).map((e) => e.value),
373
+ 'ssPtoLinkages': [firstSsPto.value].concat(ssPtoLinkages.slice(0, ssLength.value!).map((e) => e.value)),
374
+ 'asPtoLinkages': [firstAsPto.value].concat(asPtoLinkages.slice(0, asLength.value!).map((e) => e.value)),
375
375
  'ssThreeModification': ssThreeModification.value,
376
376
  'ssFiveModification': ssFiveModification.value,
377
377
  'asThreeModification': asThreeModification.value,
@@ -506,24 +506,24 @@ export function defineAxolabsPattern() {
506
506
 
507
507
  function validateSsColumn(colName: string) {
508
508
  const allLengthsAreTheSame: boolean = checkWhetherAllValuesInColumnHaveTheSameLength(colName);
509
- const firstSequence = tables.value.columns.byName(colName).get(0);
509
+ const firstSequence = tables.value!.columns.byName(colName).get(0);
510
510
  if (allLengthsAreTheSame && firstSequence.length != ssLength.value)
511
- ssLength.value = tables.value.columns.byName(colName).get(0).length;
511
+ ssLength.value = tables.value!.columns.byName(colName).get(0).length;
512
512
  ssInputExample.value = firstSequence;
513
513
  }
514
514
 
515
515
  function validateAsColumn(colName: string) {
516
516
  const allLengthsAreTheSame: boolean = checkWhetherAllValuesInColumnHaveTheSameLength(colName);
517
- const firstSequence = tables.value.columns.byName(colName).get(0);
517
+ const firstSequence = tables.value!.columns.byName(colName).get(0);
518
518
  if (allLengthsAreTheSame && firstSequence.length != asLength.value)
519
- asLength.value = tables.value.columns.byName(colName).get(0).length;
519
+ asLength.value = tables.value!.columns.byName(colName).get(0).length;
520
520
  asLengthDiv.innerHTML = '';
521
521
  asLengthDiv.append(asLength.root);
522
522
  asInputExample.value = firstSequence;
523
523
  }
524
524
 
525
525
  function validateIdsColumn(colName: string) {
526
- const col = tables.value.columns.byName(colName);
526
+ const col = tables.value!.columns.byName(colName);
527
527
  if (col.type != DG.TYPE.INT)
528
528
  grok.shell.error('Column should contain integers only');
529
529
  else if (col.categories.length < col.length) {
@@ -531,32 +531,35 @@ export function defineAxolabsPattern() {
531
531
  ui.dialog('Non-unique IDs')
532
532
  .add(ui.divText('Press \'OK\' to select rows with non-unique values'))
533
533
  .onOK(() => {
534
- const selection = tables.value.selection;
534
+ const selection = tables.value!.selection;
535
535
  selection.init((i: number) => duplicates.indexOf(col.get(i)) > -1);
536
- grok.shell.v = grok.shell.getTableView(tables.value.name);
537
- grok.shell.info('Rows are selected in table \'' + tables.value.name + '\'');
536
+ grok.shell.v = grok.shell.getTableView(tables.value!.name);
537
+ grok.shell.info('Rows are selected in table \'' + tables.value!.name + '\'');
538
538
  })
539
539
  .show();
540
540
  }
541
541
  }
542
542
 
543
543
  const tables = ui.tableInput('Tables', grok.shell.tables[0], grok.shell.tables, (t: DG.DataFrame) => {
544
- inputSsColumn = ui.choiceInput('SS Column', '', t.columns.names(), (colName: string) => validateSsColumn(colName));
544
+ const inputSsColumn =
545
+ ui.choiceInput('SS Column', '', t.columns.names(), (colName: string) => validateSsColumn(colName));
545
546
  inputSsColumnDiv.innerHTML = '';
546
547
  inputSsColumnDiv.append(inputSsColumn.root);
547
- inputAsColumn = ui.choiceInput('AS Column', '', t.columns.names(), (colName: string) => validateAsColumn(colName));
548
+ const inputAsColumn =
549
+ ui.choiceInput('AS Column', '', t.columns.names(), (colName: string) => validateAsColumn(colName));
548
550
  inputAsColumnDiv.innerHTML = '';
549
551
  inputAsColumnDiv.append(inputAsColumn.root);
550
- inputIdColumn = ui.choiceInput('ID Column', '', t.columns.names(), (colName: string) => validateIdsColumn(colName));
552
+ const inputIdColumn =
553
+ ui.choiceInput('ID Column', '', t.columns.names(), (colName: string) => validateIdsColumn(colName));
551
554
  inputIdColumnDiv.innerHTML = '';
552
555
  inputIdColumnDiv.append(inputIdColumn.root);
553
556
  });
554
557
 
555
- let inputSsColumn = ui.choiceInput('SS Column', '', []);
558
+ const inputSsColumn = ui.choiceInput('SS Column', '', []);
556
559
  inputSsColumnDiv.append(inputSsColumn.root);
557
- let inputAsColumn = ui.choiceInput('AS Column', '', []);
560
+ const inputAsColumn = ui.choiceInput('AS Column', '', []);
558
561
  inputAsColumnDiv.append(inputAsColumn.root);
559
- let inputIdColumn = ui.choiceInput('ID Column', '', []);
562
+ const inputIdColumn = ui.choiceInput('ID Column', '', []);
560
563
  inputIdColumnDiv.append(inputIdColumn.root);
561
564
 
562
565
  updatePatternsList();
@@ -573,8 +576,8 @@ export function defineAxolabsPattern() {
573
576
  updateOutputExamples();
574
577
  });
575
578
 
576
- const firstSsPto = ui.boolInput('First SS PTO', fullyPto.value, () => updateSvgScheme());
577
- const firstAsPto = ui.boolInput('First AS PTO', fullyPto.value, () => updateSvgScheme());
579
+ const firstSsPto = ui.boolInput('First SS PTO', fullyPto.value!, () => updateSvgScheme());
580
+ const firstAsPto = ui.boolInput('First AS PTO', fullyPto.value!, () => updateSvgScheme());
578
581
  firstAsPtoDiv.append(firstAsPto.root);
579
582
 
580
583
  const createAsStrand = ui.boolInput('Create AS Strand', true, (v: boolean) => {
@@ -643,34 +646,34 @@ export function defineAxolabsPattern() {
643
646
  dialog
644
647
  .add(ui.divText('Length of sequences in columns doesn\'t match entered length. Update length value?'))
645
648
  .addButton('YES', () => {
646
- ssLength.value = tables.value.columns.byName(inputSsColumn.value).getString(0).length;
647
- asLength.value = tables.value.columns.byName(inputAsColumn.value).getString(0).length;
649
+ ssLength.value = tables.value!.columns.byName(inputSsColumn.value!).getString(0).length;
650
+ asLength.value = tables.value!.columns.byName(inputAsColumn.value!).getString(0).length;
648
651
  dialog.close();
649
652
  })
650
653
  .show();
651
654
  } else {
652
655
  if (inputIdColumn.value != null)
653
- addColumnWithIds(tables.value.name, inputIdColumn.value, getShortName(saveAs.value));
656
+ addColumnWithIds(tables.value!.name, inputIdColumn.value, getShortName(saveAs.value));
654
657
  addColumnWithTranslatedSequences(
655
- tables.value.name, inputSsColumn.value, ssBases, ssPtoLinkages,
656
- ssFiveModification, ssThreeModification, firstSsPto.value);
658
+ tables.value!.name, inputSsColumn.value, ssBases, ssPtoLinkages,
659
+ ssFiveModification, ssThreeModification, firstSsPto.value!);
657
660
  if (createAsStrand.value) {
658
661
  addColumnWithTranslatedSequences(
659
- tables.value.name, inputAsColumn.value, asBases, asPtoLinkages,
660
- asFiveModification, asThreeModification, firstAsPto.value);
662
+ tables.value!.name, inputAsColumn.value!, asBases, asPtoLinkages,
663
+ asFiveModification, asThreeModification, firstAsPto.value!);
661
664
  }
662
- grok.shell.v = grok.shell.getTableView(tables.value.name);
665
+ grok.shell.v = grok.shell.getTableView(tables.value!.name);
663
666
  grok.shell.info(((createAsStrand.value) ? 'Columns were' : 'Column was') +
664
- ' added to table \'' + tables.value.name + '\'');
667
+ ' added to table \'' + tables.value!.name + '\'');
665
668
  }
666
669
  });
667
670
 
668
- const ssInputExample = ui.textInput('Sense Strand', generateExample(ssLength.value, sequenceBase.value), () => {
671
+ const ssInputExample = ui.textInput('Sense Strand', generateExample(ssLength.value!, sequenceBase.value!), () => {
669
672
  ssOutputExample.value = translateSequence(ssInputExample.value, ssBases, ssPtoLinkages,
670
- ssFiveModification, ssThreeModification, firstSsPto.value);
673
+ ssFiveModification, ssThreeModification, firstSsPto.value!);
671
674
  });
672
675
  const ssOutputExample = ui.textInput(' ', translateSequence(
673
- ssInputExample.value, ssBases, ssPtoLinkages, ssThreeModification, ssFiveModification, firstSsPto.value));
676
+ ssInputExample.value, ssBases, ssPtoLinkages, ssThreeModification, ssFiveModification, firstSsPto.value!));
674
677
  (ssInputExample.input as HTMLElement).style.resize = 'none';
675
678
  (ssInputExample.input as HTMLElement).style.minWidth = exampleMinWidth;
676
679
  (ssOutputExample.input as HTMLElement).style.resize = 'none';
@@ -686,12 +689,12 @@ export function defineAxolabsPattern() {
686
689
  ], 'ui-input-options'),
687
690
  );
688
691
 
689
- const asInputExample = ui.textInput('Antisense Strand', generateExample(asLength.value, sequenceBase.value), () => {
692
+ const asInputExample = ui.textInput('Antisense Strand', generateExample(asLength.value!, sequenceBase.value!), () => {
690
693
  asOutputExample.value = translateSequence(
691
- asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value);
694
+ asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value!);
692
695
  });
693
696
  const asOutputExample = ui.textInput(' ', translateSequence(
694
- asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value));
697
+ asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value!));
695
698
  (asInputExample.input as HTMLElement).style.resize = 'none';
696
699
  (asInputExample.input as HTMLElement).style.minWidth = exampleMinWidth;
697
700
  (asOutputExample.input as HTMLElement).style.resize = 'none';
@@ -3,7 +3,7 @@ import {runTests, tests} from '@datagrok-libraries/utils/src/test';
3
3
  import './tests/smiles-tests';
4
4
 
5
5
  export const _package = new DG.Package();
6
- export {tests}
6
+ export {tests};
7
7
 
8
8
  //name: test
9
9
  //output: dataframe result
package/src/package.ts CHANGED
@@ -7,7 +7,8 @@ import $ from 'cash-dom';
7
7
  import {defineAxolabsPattern} from './defineAxolabsPattern';
8
8
  import {saveSenseAntiSense} from './structures-works/save-sense-antisense';
9
9
  import {sequenceToSmiles, sequenceToMolV3000} from './structures-works/from-monomers';
10
- import {convertSequence, undefinedInputSequence} from './structures-works/sequence-codes-tools';
10
+ import {convertSequence, undefinedInputSequence, isValidSequence, getFormat} from
11
+ './structures-works/sequence-codes-tools';
11
12
  import {map, COL_NAMES, MODIFICATIONS} from './structures-works/map';
12
13
  import {SALTS_CSV} from './salts';
13
14
  import {USERS_CSV} from './users';
@@ -17,7 +18,7 @@ import {IDPS} from './IDPs';
17
18
 
18
19
  export const _package = new DG.Package();
19
20
 
20
- const defaultInput = 'AGGTCCTCTTGACTTAGGCC';
21
+ const defaultInput = 'fAmCmGmAmCpsmU';
21
22
  const sequenceWasCopied = 'Copied';
22
23
  const tooltipSequence = 'Copy sequence';
23
24
 
@@ -29,35 +30,40 @@ export function sequenceTranslator(): void {
29
30
  windows.showToolbox = false;
30
31
  windows.showHelp = false;
31
32
 
32
- function updateTableAndMolecule(sequence: string): void {
33
+ function updateTableAndMolecule(sequence: string, inputFormat: string, isSet: boolean): void {
33
34
  moleculeSvgDiv.innerHTML = '';
34
35
  outputTableDiv.innerHTML = '';
35
36
  const pi = DG.TaskBarProgressIndicator.create('Rendering table and molecule...');
36
37
  let errorsExist = false;
37
38
  try {
38
- const outputSequenceObj = convertSequence(sequence);
39
+ sequence = sequence.replace(/\s/g, '');
40
+ const output = isValidSequence(sequence, null);
41
+ if (isSet)
42
+ output.synthesizer = [inputFormat];
43
+ inputFormatChoiceInput.value = output.synthesizer![0];
44
+ const outputSequenceObj = convertSequence(sequence, output);
39
45
  const tableRows = [];
40
46
 
41
47
  for (const key of Object.keys(outputSequenceObj).slice(1)) {
42
- const indexOfFirstNotValidCharacter = ('indexOfFirstNotValidCharacter' in outputSequenceObj) ?
43
- JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).indexOfFirstNotValidCharacter :
48
+ const indexOfFirstNotValidChar = ('indexOfFirstNotValidChar' in outputSequenceObj) ?
49
+ JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).indexOfFirstNotValidChar :
44
50
  -1;
45
- if ('indexOfFirstNotValidCharacter' in outputSequenceObj) {
46
- const indexOfFirstNotValidCharacter = ('indexOfFirstNotValidCharacter' in outputSequenceObj) ?
47
- JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).indexOfFirstNotValidCharacter :
51
+ if ('indexOfFirstNotValidChar' in outputSequenceObj) {
52
+ const indexOfFirstNotValidChar = ('indexOfFirstNotValidChar' in outputSequenceObj) ?
53
+ JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).indexOfFirstNotValidChar :
48
54
  -1;
49
- if (indexOfFirstNotValidCharacter != -1)
55
+ if (indexOfFirstNotValidChar != -1)
50
56
  errorsExist = true;
51
57
  }
52
58
 
53
59
  tableRows.push({
54
60
  'key': key,
55
- 'value': ('indexOfFirstNotValidCharacter' in outputSequenceObj) ?
61
+ 'value': ('indexOfFirstNotValidChar' in outputSequenceObj) ?
56
62
  ui.divH([
57
- ui.divText(sequence.slice(0, indexOfFirstNotValidCharacter), {style: {color: 'grey'}}),
63
+ ui.divText(sequence.slice(0, indexOfFirstNotValidChar), {style: {color: 'grey'}}),
58
64
  ui.tooltip.bind(
59
- ui.divText(sequence.slice(indexOfFirstNotValidCharacter), {style: {color: 'red'}}),
60
- 'Expected format: ' + JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!).expectedSynthesizer +
65
+ ui.divText(sequence.slice(indexOfFirstNotValidChar), {style: {color: 'red'}}),
66
+ 'Expected format: ' + JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).synthesizer +
61
67
  '. See tables with valid codes on the right',
62
68
  ),
63
69
  ]) : //@ts-ignore
@@ -67,13 +73,12 @@ export function sequenceTranslator(): void {
67
73
  }
68
74
 
69
75
  if (errorsExist) {
70
- const expectedSynthesizer = JSON.parse(outputSequenceObj.indexOfFirstNotValidCharacter!)
71
- .expectedSynthesizer.slice(0, -6);
76
+ const synthesizer = JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).synthesizer.slice(0, -6);
72
77
  asoGapmersGrid.onCellPrepare(function(gc) {
73
- gc.style.backColor = (gc.gridColumn.name == expectedSynthesizer) ? 0xFFF00000 : 0xFFFFFFFF;
78
+ gc.style.backColor = (gc.gridColumn.name == synthesizer) ? 0xFFF00000 : 0xFFFFFFFF;
74
79
  });
75
80
  omeAndFluoroGrid.onCellPrepare(function(gc) {
76
- gc.style.backColor = (gc.gridColumn.name == expectedSynthesizer) ? 0xFFF00000 : 0xFFFFFFFF;
81
+ gc.style.backColor = (gc.gridColumn.name == synthesizer) ? 0xFFF00000 : 0xFFFFFFFF;
77
82
  });
78
83
  switchInput.enabled = true;
79
84
  } else {
@@ -85,15 +90,15 @@ export function sequenceTranslator(): void {
85
90
  ui.div([
86
91
  DG.HtmlTable.create(tableRows, (item: { key: string; value: string; }) =>
87
92
  [item.key, item.value], ['Code', 'Sequence']).root,
88
- ], 'table'),
93
+ ]),
89
94
  );
90
- semTypeOfInputSequence.textContent = 'Detected input type: ' + outputSequenceObj.type;
91
95
 
92
96
  if (outputSequenceObj.type != undefinedInputSequence && outputSequenceObj.Error != undefinedInputSequence) {
93
97
  const canvas = ui.canvas(300, 170);
94
98
  canvas.addEventListener('click', () => {
95
99
  const canv = ui.canvas($(window).width(), $(window).height());
96
- const mol = sequenceToMolV3000(inputSequenceField.value.replace(/\s/g, ''), false, true);
100
+ const mol = sequenceToMolV3000(inputSequenceField.value.replace(/\s/g, ''), false, true,
101
+ output.synthesizer![0]);
97
102
  // @ts-ignore
98
103
  OCL.StructureView.drawMolecule(canv, OCL.Molecule.fromMolfile(mol), {suppressChiralText: true});
99
104
  ui.dialog('Molecule: ' + inputSequenceField.value)
@@ -102,7 +107,8 @@ export function sequenceTranslator(): void {
102
107
  });
103
108
  $(canvas).on('mouseover', () => $(canvas).css('cursor', 'zoom-in'));
104
109
  $(canvas).on('mouseout', () => $(canvas).css('cursor', 'default'));
105
- const mol = sequenceToMolV3000(inputSequenceField.value.replace(/\s/g, ''), false, true);
110
+ const mol = sequenceToMolV3000(inputSequenceField.value.replace(/\s/g, ''), false, true,
111
+ output.synthesizer![0]);
106
112
  // @ts-ignore
107
113
  OCL.StructureView.drawMolecule(canvas, OCL.Molecule.fromMolfile(mol), {suppressChiralText: true});
108
114
  moleculeSvgDiv.append(canvas);
@@ -113,10 +119,14 @@ export function sequenceTranslator(): void {
113
119
  }
114
120
  }
115
121
 
116
- const semTypeOfInputSequence = ui.divText('');
122
+ const inputFormatChoiceInput = ui.choiceInput(
123
+ 'Input format: ', 'Janssen GCRS Codes', Object.keys(map), (format: string) => {
124
+ updateTableAndMolecule(inputSequenceField.value.replace(/\s/g, ''), format, true);
125
+ });
117
126
  const moleculeSvgDiv = ui.block([]);
118
- const outputTableDiv = ui.div([], 'table');
119
- const inputSequenceField = ui.textInput('', defaultInput, (sequence: string) => updateTableAndMolecule(sequence));
127
+ const outputTableDiv = ui.div([]);
128
+ const inputSequenceField = ui.textInput('', defaultInput, (sequence: string) => updateTableAndMolecule(sequence,
129
+ inputFormatChoiceInput.value!, false));
120
130
 
121
131
  const asoDf = DG.DataFrame.fromObjects([
122
132
  {'Name': '2\'MOE-5Me-rU', 'BioSpring': '5', 'Janssen GCRS': 'moeT'},
@@ -155,12 +165,11 @@ export function sequenceTranslator(): void {
155
165
  );
156
166
 
157
167
  const overhangModificationsGrid = DG.Viewer.grid(
158
- DG.DataFrame.fromObjects([
159
- {'Name': '(invabasic)'},
160
- {'Name': '(GalNAc-2-JNJ)'},
168
+ DG.DataFrame.fromColumns([
169
+ DG.Column.fromStrings('Name', Object.keys(MODIFICATIONS)),
161
170
  ])!, {showRowHeader: false, showCellTooltip: false},
162
171
  );
163
- updateTableAndMolecule(defaultInput);
172
+ updateTableAndMolecule(defaultInput, inputFormatChoiceInput.value!, true);
164
173
 
165
174
  const appMainDescription = ui.info([
166
175
  ui.divText('How to convert one sequence:', {style: {'font-weight': 'bolder'}}),
@@ -191,8 +200,8 @@ export function sequenceTranslator(): void {
191
200
  ui.div([
192
201
  inputSequenceField.root,
193
202
  ], 'input-base'),
194
- ], 'sequenceInput'),
195
- semTypeOfInputSequence,
203
+ ], 'inputSequence'),
204
+ ui.div([inputFormatChoiceInput], {style: {padding: '5px 0'}}),
196
205
  ui.block([
197
206
  ui.h1('Output'),
198
207
  outputTableDiv,
@@ -217,14 +226,16 @@ export function sequenceTranslator(): void {
217
226
 
218
227
  const topPanel = [
219
228
  ui.iconFA('download', () => {
220
- const result = sequenceToMolV3000(inputSequenceField.value.replace(/\s/g, ''));
229
+ const result = sequenceToMolV3000(inputSequenceField.value.replace(/\s/g, ''), false, false,
230
+ inputFormatChoiceInput.value!);
221
231
  const element = document.createElement('a');
222
232
  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
223
233
  element.setAttribute('download', inputSequenceField.value.replace(/\s/g, '') + '.mol');
224
234
  element.click();
225
235
  }, 'Save .mol file'),
226
236
  ui.iconFA('copy', () => {
227
- navigator.clipboard.writeText(sequenceToSmiles(inputSequenceField.value.replace(/\s/g, '')))
237
+ navigator.clipboard.writeText(
238
+ sequenceToSmiles(inputSequenceField.value.replace(/\s/g, ''), false, inputFormatChoiceInput.value!))
228
239
  .then(() => grok.shell.info(sequenceWasCopied));
229
240
  }, 'Copy SMILES'),
230
241
  switchInput.root,
@@ -233,18 +244,6 @@ export function sequenceTranslator(): void {
233
244
  tabControl.onTabChanged.subscribe((_) =>
234
245
  v.setRibbonPanels([(tabControl.currentPane.name == 'MAIN') ? topPanel : []]));
235
246
  v.setRibbonPanels([topPanel]);
236
-
237
- $('.sequence')
238
- .children().css('padding', '5px 0');
239
- $('.sequenceInput .input-base')
240
- .css('margin', '0');
241
- $('.sequenceInput textarea')
242
- .css('resize', 'none')
243
- .css('min-height', '50px')
244
- .css('width', '100%')
245
- .attr('spellcheck', 'false');
246
- $('.sequenceInput select')
247
- .css('width', '100%');
248
247
  }
249
248
 
250
249
  async function saveTableAsSdFile(table: DG.DataFrame) {
@@ -259,9 +258,10 @@ async function saveTableAsSdFile(table: DG.DataFrame) {
259
258
  const typeColumn = table.col(COL_NAMES.TYPE)!;
260
259
  let result = '';
261
260
  for (let i = 0; i < table.rowCount; i++) {
261
+ const format = getFormat(structureColumn.get(i));
262
262
  result += (typeColumn.get(i) == 'SS') ?
263
- sequenceToMolV3000(structureColumn.get(i), false, true) + '\n' + `> <Sequence>\nSense Strand\n\n` :
264
- sequenceToMolV3000(structureColumn.get(i), true, true) + '\n' + `> <Sequence>\nAnti Sense\n\n`;
263
+ sequenceToMolV3000(structureColumn.get(i), false, true, format!) + '\n' + `> <Sequence>\nSense Strand\n\n` :
264
+ sequenceToMolV3000(structureColumn.get(i), true, true, format!) + '\n' + `> <Sequence>\nAnti Sense\n\n`;
265
265
  for (const col of table.columns) {
266
266
  if (col.name != COL_NAMES.SEQUENCE)
267
267
  result += `> <${col.name}>\n${col.get(i)}\n\n`;
@@ -324,6 +324,7 @@ export function oligoSdFile(table: DG.DataFrame) {
324
324
  return grok.shell.error('Columns already exist!');
325
325
 
326
326
  const sequence = t.col(COL_NAMES.SEQUENCE)!;
327
+ const salt = t.col(COL_NAMES.SALT)!;
327
328
  const equivalents = t.col(COL_NAMES.EQUIVALENTS)!;
328
329
 
329
330
  t.columns.addNewString(COL_NAMES.COMPOUND_NAME).init((i: number) => sequence.get(i));
@@ -331,11 +332,13 @@ export function oligoSdFile(table: DG.DataFrame) {
331
332
  sequence.getString(i) + '; duplex of SS: ' + sequence.getString(i - 2) + ' and AS: ' + sequence.getString(i - 1) :
332
333
  sequence.getString(i),
333
334
  );
335
+ const molWeightCol = saltsDf.col('MOLWEIGHT')!;
336
+ const saltNamesList = saltsDf.col('DISPLAY')!.toList();
334
337
  t.columns.addNewFloat(COL_NAMES.CPD_MW)
335
338
  .init((i: number) => molecularWeight(sequence.get(i), weightsObj));
336
- const mwCol = t.col(COL_NAMES.CPD_MW)!;
337
339
  t.columns.addNewFloat(COL_NAMES.SALT_MASS).init((i: number) => {
338
- const mw = mwCol.get(i);
340
+ const saltRowIndex = saltNamesList.indexOf(salt.get(i));
341
+ const mw = molWeightCol.get(saltRowIndex);
339
342
  return mw * equivalents.get(i);
340
343
  });
341
344
  t.columns.addNewCalculated(COL_NAMES.BATCH_MW,
@@ -367,7 +370,7 @@ export function oligoSdFile(table: DG.DataFrame) {
367
370
 
368
371
  view.table!.col(COL_NAMES.TYPE)!.setTag(DG.TAGS.CHOICES, '["AS", "SS", "Duplex"]');
369
372
  view.table!.col(COL_NAMES.OWNER)!.setTag(DG.TAGS.CHOICES, stringifyItems(usersDf.columns.byIndex(0).toList()));
370
- view.table!.col(COL_NAMES.SALT)!.setTag(DG.TAGS.CHOICES, stringifyItems(saltsDf.columns.byIndex(1).toList()));
373
+ view.table!.col(COL_NAMES.SALT)!.setTag(DG.TAGS.CHOICES, stringifyItems(saltsDf.columns.byIndex(0).toList()));
371
374
  view.table!.col(COL_NAMES.SOURCE)!.setTag(DG.TAGS.CHOICES, stringifyItems(sourcesDf.columns.byIndex(0).toList()));
372
375
  view.table!.col(COL_NAMES.ICD)!.setTag(DG.TAGS.CHOICES, stringifyItems(icdsDf.columns.byIndex(0).toList()));
373
376
  view.table!.col(COL_NAMES.IDP)!.setTag(DG.TAGS.CHOICES, stringifyItems(idpsDf.columns.byIndex(0).toList()));
package/src/salts.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const SALTS_CSV = `CHARGE,DISPLAY,MOLWEIGHT
2
- ,no Data Added,100`;
1
+ export const SALTS_CSV = `DISPLAY,MOLWEIGHT
2
+ no Data Added,100`;
@@ -2,8 +2,9 @@ import {map, stadardPhosphateLinkSmiles, SYNTHESIZERS, TECHNOLOGIES, MODIFICATIO
2
2
  import {isValidSequence} from './sequence-codes-tools';
3
3
  import {getNucleotidesMol} from './mol-transformations';
4
4
 
5
- export function sequenceToMolV3000(sequence: string, inverted: boolean = false, oclRender: boolean = false): string {
6
- const obj = getObjectWithCodesAndSmiles(sequence);
5
+ export function sequenceToMolV3000(sequence: string, inverted: boolean = false, oclRender: boolean = false,
6
+ format: string): string {
7
+ const obj = getObjectWithCodesAndSmiles(sequence, format);
7
8
  let codes = sortByStringLengthInDescendingOrder(Object.keys(obj));
8
9
  let i = 0;
9
10
  const smilesCodes:string[] = [];
@@ -38,8 +39,8 @@ export function sequenceToMolV3000(sequence: string, inverted: boolean = false,
38
39
  return getNucleotidesMol(smilesCodes, oclRender);
39
40
  }
40
41
 
41
- export function sequenceToSmiles(sequence: string, inverted: boolean = false): string {
42
- const obj = getObjectWithCodesAndSmiles(sequence);
42
+ export function sequenceToSmiles(sequence: string, inverted: boolean = false, format: string): string {
43
+ const obj = getObjectWithCodesAndSmiles(sequence, format);
43
44
  let codes = sortByStringLengthInDescendingOrder(Object.keys(obj));
44
45
  let i = 0;
45
46
  let smiles = '';
@@ -82,19 +83,26 @@ export function sequenceToSmiles(sequence: string, inverted: boolean = false): s
82
83
  smiles.slice(0, smiles.length - stadardPhosphateLinkSmiles.length + 1);
83
84
  }
84
85
 
85
- function getObjectWithCodesAndSmiles(sequence: string) {
86
+ function getObjectWithCodesAndSmiles(sequence: string, format: string) {
86
87
  const obj: { [code: string]: string } = {};
87
- for (const synthesizer of Object.keys(map)) {
88
- for (const technology of Object.keys(map[synthesizer])) {
89
- for (const code of Object.keys(map[synthesizer][technology]))
90
- obj[code] = map[synthesizer][technology][code].SMILES;
88
+ if (format == null) {
89
+ for (const synthesizer of Object.keys(map)) {
90
+ for (const technology of Object.keys(map[synthesizer])) {
91
+ for (const code of Object.keys(map[synthesizer][technology]))
92
+ obj[code] = map[synthesizer][technology][code].SMILES;
93
+ }
94
+ }
95
+ } else {
96
+ for (const technology of Object.keys(map[format])) {
97
+ for (const code of Object.keys(map[format][technology]))
98
+ obj[code] = map[format][technology][code].SMILES;
91
99
  }
92
100
  }
93
101
  // TODO: create object based from synthesizer type to avoid key(codes) duplicates
94
- const output = isValidSequence(sequence);
95
- if (output.expectedSynthesizer == SYNTHESIZERS.MERMADE_12)
102
+ const output = isValidSequence(sequence, format);
103
+ if (output.synthesizer!.includes(SYNTHESIZERS.MERMADE_12))
96
104
  obj['g'] = map[SYNTHESIZERS.MERMADE_12][TECHNOLOGIES.SI_RNA]['g'].SMILES;
97
- else if (output.expectedSynthesizer == SYNTHESIZERS.AXOLABS)
105
+ else if (output.synthesizer!.includes(SYNTHESIZERS.AXOLABS))
98
106
  obj['g'] = map[SYNTHESIZERS.AXOLABS][TECHNOLOGIES.SI_RNA]['g'].SMILES;
99
107
  return obj;
100
108
  }