@datagrok/sequence-translator 0.0.5 → 0.0.9

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.
@@ -0,0 +1,236 @@
1
+ import {map, SYNTHESIZERS, TECHNOLOGIES, MODIFICATIONS} from './map';
2
+ import {asoGapmersNucleotidesToBioSpring, asoGapmersNucleotidesToGcrs,
3
+ asoGapmersBioSpringToNucleotides, asoGapmersBioSpringToGcrs, asoGapmersGcrsToNucleotides,
4
+ asoGapmersGcrsToBioSpring, gcrsToMermade12, siRnaNucleotideToBioSpringSenseStrand,
5
+ siRnaNucleotideToAxolabsSenseStrand, siRnaNucleotidesToGcrs, siRnaBioSpringToNucleotides,
6
+ siRnaBioSpringToAxolabs, siRnaBioSpringToGcrs, siRnaAxolabsToNucleotides,
7
+ siRnaAxolabsToBioSpring, siRnaAxolabsToGcrs, siRnaGcrsToNucleotides,
8
+ siRnaGcrsToBioSpring, siRnaGcrsToAxolabs, gcrsToNucleotides} from './converters';
9
+
10
+ const noTranslationTableAvailable = 'No translation table available';
11
+ export const undefinedInputSequence = 'Type of input sequence is undefined';
12
+
13
+ export function isValidSequence(sequence: string): {
14
+ indexOfFirstNotValidCharacter: number,
15
+ expectedSynthesizer: string | null,
16
+ expectedTechnology: string | null
17
+ } {
18
+ const possibleSynthesizers = getListOfPossibleSynthesizersByFirstMatchedCode(sequence);
19
+ if (possibleSynthesizers.length == 0)
20
+ return {indexOfFirstNotValidCharacter: 0, expectedSynthesizer: null, expectedTechnology: null};
21
+
22
+ let outputIndices = Array(possibleSynthesizers.length).fill(0);
23
+
24
+ const firstUniqueCharacters = ['r', 'd'];
25
+ const nucleotides = ['A', 'U', 'T', 'C', 'G'];
26
+
27
+ possibleSynthesizers.forEach((synthesizer, synthesizerIndex) => {
28
+ const codes = getAllCodesOfSynthesizer(synthesizer);
29
+ while (outputIndices[synthesizerIndex] < sequence.length) {
30
+ const matchedCode = codes
31
+ .find((c) => c == sequence.slice(outputIndices[synthesizerIndex], outputIndices[synthesizerIndex] + c.length));
32
+
33
+ if (matchedCode == null)
34
+ break;
35
+
36
+ if ( // for mistake pattern 'rAA'
37
+ outputIndices[synthesizerIndex] > 1 &&
38
+ nucleotides.includes(sequence[outputIndices[synthesizerIndex]]) &&
39
+ firstUniqueCharacters.includes(sequence[outputIndices[synthesizerIndex] - 2])
40
+ ) break;
41
+
42
+ if ( // for mistake pattern 'ArA'
43
+ firstUniqueCharacters.includes(sequence[outputIndices[synthesizerIndex] + 1]) &&
44
+ nucleotides.includes(sequence[outputIndices[synthesizerIndex]])
45
+ ) {
46
+ outputIndices[synthesizerIndex]++;
47
+ break;
48
+ }
49
+
50
+ outputIndices[synthesizerIndex] += matchedCode.length;
51
+ }
52
+ });
53
+
54
+ const indexOfExpectedSythesizer = Math.max(...outputIndices);
55
+ const indexOfFirstNotValidCharacter = (indexOfExpectedSythesizer == sequence.length) ? -1 : indexOfExpectedSythesizer;
56
+ const expectedSynthesizer = possibleSynthesizers[outputIndices.indexOf(indexOfExpectedSythesizer)];
57
+ if (indexOfFirstNotValidCharacter != -1) {
58
+ return {
59
+ indexOfFirstNotValidCharacter: indexOfFirstNotValidCharacter,
60
+ expectedSynthesizer: expectedSynthesizer,
61
+ expectedTechnology: null,
62
+ };
63
+ }
64
+
65
+ const possibleTechnologies = getListOfPossibleTechnologiesByFirstMatchedCode(sequence, expectedSynthesizer);
66
+ if (possibleTechnologies.length == 0)
67
+ return {indexOfFirstNotValidCharacter: 0, expectedSynthesizer: null, expectedTechnology: null};
68
+
69
+ outputIndices = Array(possibleTechnologies.length).fill(0);
70
+
71
+ possibleTechnologies.forEach((technology: string, technologyIndex: number) => {
72
+ const codes = Object.keys(map[expectedSynthesizer][technology]);
73
+ while (outputIndices[technologyIndex] < sequence.length) {
74
+ const matchedCode = codes
75
+ .find((c) => c == sequence.slice(outputIndices[technologyIndex], outputIndices[technologyIndex] + c.length));
76
+
77
+ if (matchedCode == null)
78
+ break;
79
+
80
+ if ( // for mistake pattern 'rAA'
81
+ outputIndices[technologyIndex] > 1 &&
82
+ nucleotides.includes(sequence[outputIndices[technologyIndex]]) &&
83
+ firstUniqueCharacters.includes(sequence[outputIndices[technologyIndex] - 2])
84
+ ) break;
85
+
86
+ if ( // for mistake pattern 'ArA'
87
+ firstUniqueCharacters.includes(sequence[outputIndices[technologyIndex] + 1]) &&
88
+ nucleotides.includes(sequence[outputIndices[technologyIndex]])
89
+ ) {
90
+ outputIndices[technologyIndex]++;
91
+ break;
92
+ }
93
+
94
+ outputIndices[technologyIndex] += matchedCode.length;
95
+ }
96
+ });
97
+
98
+ const indexOfExpectedTechnology = Math.max(...outputIndices);
99
+ const expectedTechnology = possibleTechnologies[outputIndices.indexOf(indexOfExpectedTechnology)];
100
+
101
+ return {
102
+ indexOfFirstNotValidCharacter: indexOfFirstNotValidCharacter,
103
+ expectedSynthesizer: expectedSynthesizer,
104
+ expectedTechnology: expectedTechnology,
105
+ };
106
+ }
107
+
108
+ function getAllCodesOfSynthesizer(synthesizer: string): string[] {
109
+ let codes: string[] = [];
110
+ for (const technology of Object.keys(map[synthesizer]))
111
+ codes = codes.concat(Object.keys(map[synthesizer][technology]));
112
+ return codes.concat(Object.keys(MODIFICATIONS));
113
+ }
114
+
115
+ function getListOfPossibleSynthesizersByFirstMatchedCode(sequence: string): string[] {
116
+ const synthesizers: string[] = [];
117
+ Object.keys(map).forEach((synthesizer: string) => {
118
+ const codes = getAllCodesOfSynthesizer(synthesizer);
119
+ //TODO: get first non-dropdown code when there are two modifications
120
+ let start = 0;
121
+ for (let i = 0; i < sequence.length; i++) {
122
+ if (sequence[i] == ')' && i != sequence.length - 1) {
123
+ start = i + 1;
124
+ break;
125
+ }
126
+ }
127
+ if (codes.some((s: string) => s == sequence.slice(start, start + s.length)))
128
+ synthesizers.push(synthesizer);
129
+ });
130
+ return synthesizers;
131
+ }
132
+
133
+ function getListOfPossibleTechnologiesByFirstMatchedCode(sequence: string, synthesizer: string): string[] {
134
+ const technologies: string[] = [];
135
+ Object.keys(map[synthesizer]).forEach((technology: string) => {
136
+ const codes = Object.keys(map[synthesizer][technology]).concat(Object.keys(MODIFICATIONS));
137
+ if (codes.some((s) => s == sequence.slice(0, s.length)))
138
+ technologies.push(technology);
139
+ });
140
+ return technologies;
141
+ }
142
+
143
+ export function convertSequence(text: string) {
144
+ text = text.replace(/\s/g, '');
145
+ const seq = text;
146
+ const output = isValidSequence(seq);
147
+ if (output.indexOfFirstNotValidCharacter != -1) {
148
+ return {
149
+ // type: '',
150
+ indexOfFirstNotValidCharacter: JSON.stringify(output),
151
+ Error: undefinedInputSequence,
152
+ };
153
+ }
154
+ if (output.expectedSynthesizer == SYNTHESIZERS.RAW_NUCLEOTIDES && output.expectedTechnology == TECHNOLOGIES.DNA) {
155
+ return {
156
+ type: SYNTHESIZERS.RAW_NUCLEOTIDES + ' ' + TECHNOLOGIES.DNA,
157
+ Nucleotides: seq,
158
+ BioSpring: asoGapmersNucleotidesToBioSpring(seq),
159
+ GCRS: asoGapmersNucleotidesToGcrs(seq),
160
+ };
161
+ }
162
+ if (output.expectedSynthesizer == SYNTHESIZERS.BIOSPRING && output.expectedTechnology == TECHNOLOGIES.ASO_GAPMERS) {
163
+ return {
164
+ type: SYNTHESIZERS.BIOSPRING + ' ' + TECHNOLOGIES.ASO_GAPMERS,
165
+ Nucleotides: asoGapmersBioSpringToNucleotides(seq),
166
+ BioSpring: seq,
167
+ GCRS: asoGapmersBioSpringToGcrs(seq),
168
+ };
169
+ }
170
+ if (output.expectedSynthesizer == SYNTHESIZERS.GCRS && output.expectedTechnology == TECHNOLOGIES.ASO_GAPMERS) {
171
+ return {
172
+ type: SYNTHESIZERS.GCRS + ' ' + TECHNOLOGIES.ASO_GAPMERS,
173
+ Nucleotides: asoGapmersGcrsToNucleotides(seq),
174
+ BioSpring: asoGapmersGcrsToBioSpring(seq),
175
+ Mermade12: gcrsToMermade12(seq),
176
+ GCRS: seq,
177
+ };
178
+ }
179
+ if (output.expectedSynthesizer == SYNTHESIZERS.RAW_NUCLEOTIDES && output.expectedTechnology == TECHNOLOGIES.RNA) {
180
+ return {
181
+ type: SYNTHESIZERS.RAW_NUCLEOTIDES + ' ' + TECHNOLOGIES.RNA,
182
+ Nucleotides: seq,
183
+ BioSpring: siRnaNucleotideToBioSpringSenseStrand(seq),
184
+ Axolabs: siRnaNucleotideToAxolabsSenseStrand(seq),
185
+ GCRS: siRnaNucleotidesToGcrs(seq),
186
+ };
187
+ }
188
+ if (output.expectedSynthesizer == SYNTHESIZERS.BIOSPRING && output.expectedTechnology == TECHNOLOGIES.SI_RNA) {
189
+ return {
190
+ type: SYNTHESIZERS.BIOSPRING + ' ' + TECHNOLOGIES.SI_RNA,
191
+ Nucleotides: siRnaBioSpringToNucleotides(seq),
192
+ BioSpring: seq,
193
+ Axolabs: siRnaBioSpringToAxolabs(seq),
194
+ GCRS: siRnaBioSpringToGcrs(seq),
195
+ };
196
+ }
197
+ if (output.expectedSynthesizer == SYNTHESIZERS.AXOLABS && output.expectedTechnology == TECHNOLOGIES.SI_RNA) {
198
+ return {
199
+ type: SYNTHESIZERS.AXOLABS + ' ' + TECHNOLOGIES.SI_RNA,
200
+ Nucleotides: siRnaAxolabsToNucleotides(seq),
201
+ BioSpring: siRnaAxolabsToBioSpring(seq),
202
+ Axolabs: seq,
203
+ GCRS: siRnaAxolabsToGcrs(seq),
204
+ };
205
+ }
206
+ if (output.expectedSynthesizer == SYNTHESIZERS.GCRS && output.expectedTechnology == TECHNOLOGIES.SI_RNA) {
207
+ return {
208
+ type: SYNTHESIZERS.GCRS + ' ' + TECHNOLOGIES.SI_RNA,
209
+ Nucleotides: siRnaGcrsToNucleotides(seq),
210
+ BioSpring: siRnaGcrsToBioSpring(seq),
211
+ Axolabs: siRnaGcrsToAxolabs(seq),
212
+ MM12: gcrsToMermade12(seq),
213
+ GCRS: seq,
214
+ };
215
+ }
216
+ if (output.expectedSynthesizer == SYNTHESIZERS.GCRS) {
217
+ return {
218
+ type: SYNTHESIZERS.GCRS,
219
+ Nucleotides: gcrsToNucleotides(seq),
220
+ GCRS: seq,
221
+ Mermade12: gcrsToMermade12(seq),
222
+ };
223
+ }
224
+ if (output.expectedSynthesizer == SYNTHESIZERS.MERMADE_12) {
225
+ return {
226
+ type: SYNTHESIZERS.MERMADE_12,
227
+ Nucleotides: noTranslationTableAvailable,
228
+ GCRS: noTranslationTableAvailable,
229
+ Mermade12: seq,
230
+ };
231
+ }
232
+ return {
233
+ type: undefinedInputSequence,
234
+ Nucleotides: undefinedInputSequence,
235
+ };
236
+ }
@@ -1,5 +1,5 @@
1
1
  import {category, expect, test} from '@datagrok-libraries/utils/src/test';
2
- import {sequenceToSmiles} from '../package';
2
+ import {sequenceToSmiles} from '../structures-works/from-monomers';
3
3
 
4
4
  category('sequence-translator', () => {
5
5
  test('AGGTCCTCTTGACTTAGGCC', async () => {
package/src/users.ts ADDED
@@ -0,0 +1,3 @@
1
+ export const USERS_CSV = `DISPLAY
2
+ NO DATA
3
+ `;
@@ -0,0 +1,245 @@
1
+ <html><head><meta charset="utf-8"/><title>SequenceTranslator Test Report. Datagrok version datagrok/datagrok:latest SHA=2e08c8e54bde. Commit 1367d435.</title><style type="text/css">html,
2
+ body {
3
+ font-family: Arial, Helvetica, sans-serif;
4
+ font-size: 1rem;
5
+ margin: 0;
6
+ padding: 0;
7
+ color: #333;
8
+ }
9
+ body {
10
+ padding: 2rem 1rem;
11
+ font-size: 0.85rem;
12
+ }
13
+ #jesthtml-content {
14
+ margin: 0 auto;
15
+ max-width: 70rem;
16
+ }
17
+ header {
18
+ display: flex;
19
+ align-items: center;
20
+ }
21
+ #title {
22
+ margin: 0;
23
+ flex-grow: 1;
24
+ }
25
+ #logo {
26
+ height: 4rem;
27
+ }
28
+ #timestamp {
29
+ color: #777;
30
+ margin-top: 0.5rem;
31
+ }
32
+
33
+ /** SUMMARY */
34
+ #summary {
35
+ color: #333;
36
+ margin: 2rem 0;
37
+ display: flex;
38
+ font-family: monospace;
39
+ font-size: 1rem;
40
+ }
41
+ #summary > div {
42
+ margin-right: 2rem;
43
+ background: #eee;
44
+ padding: 1rem;
45
+ min-width: 15rem;
46
+ }
47
+ #summary > div:last-child {
48
+ margin-right: 0;
49
+ }
50
+ @media only screen and (max-width: 720px) {
51
+ #summary {
52
+ flex-direction: column;
53
+ }
54
+ #summary > div {
55
+ margin-right: 0;
56
+ margin-top: 2rem;
57
+ }
58
+ #summary > div:first-child {
59
+ margin-top: 0;
60
+ }
61
+ }
62
+
63
+ .summary-total {
64
+ font-weight: bold;
65
+ margin-bottom: 0.5rem;
66
+ }
67
+ .summary-passed {
68
+ color: #4f8a10;
69
+ border-left: 0.4rem solid #4f8a10;
70
+ padding-left: 0.5rem;
71
+ }
72
+ .summary-failed,
73
+ .summary-obsolete-snapshots {
74
+ color: #d8000c;
75
+ border-left: 0.4rem solid #d8000c;
76
+ padding-left: 0.5rem;
77
+ }
78
+ .summary-pending {
79
+ color: #9f6000;
80
+ border-left: 0.4rem solid #9f6000;
81
+ padding-left: 0.5rem;
82
+ }
83
+ .summary-empty {
84
+ color: #999;
85
+ border-left: 0.4rem solid #999;
86
+ }
87
+
88
+ .test-result {
89
+ padding: 1rem;
90
+ margin-bottom: 0.25rem;
91
+ }
92
+ .test-result:last-child {
93
+ border: 0;
94
+ }
95
+ .test-result.passed {
96
+ background-color: #dff2bf;
97
+ color: #4f8a10;
98
+ }
99
+ .test-result.failed {
100
+ background-color: #ffbaba;
101
+ color: #d8000c;
102
+ }
103
+ .test-result.pending {
104
+ background-color: #ffdf61;
105
+ color: #9f6000;
106
+ }
107
+
108
+ .test-info {
109
+ display: flex;
110
+ justify-content: space-between;
111
+ }
112
+ .test-suitename {
113
+ width: 20%;
114
+ text-align: left;
115
+ font-weight: bold;
116
+ word-break: break-word;
117
+ }
118
+ .test-title {
119
+ width: 40%;
120
+ text-align: left;
121
+ font-style: italic;
122
+ }
123
+ .test-status {
124
+ width: 20%;
125
+ text-align: right;
126
+ }
127
+ .test-duration {
128
+ width: 10%;
129
+ text-align: right;
130
+ font-size: 0.75rem;
131
+ }
132
+
133
+ .failureMessages {
134
+ padding: 0 1rem;
135
+ margin-top: 1rem;
136
+ border-top: 1px dashed #d8000c;
137
+ }
138
+ .failureMessages.suiteFailure {
139
+ border-top: none;
140
+ }
141
+ .failureMsg {
142
+ white-space: pre-wrap;
143
+ white-space: -moz-pre-wrap;
144
+ white-space: -pre-wrap;
145
+ white-space: -o-pre-wrap;
146
+ word-wrap: break-word;
147
+ }
148
+
149
+ .suite-container {
150
+ margin-bottom: 2rem;
151
+ }
152
+ .suite-info {
153
+ padding: 1rem;
154
+ background-color: #eee;
155
+ color: #777;
156
+ display: flex;
157
+ align-items: center;
158
+ margin-bottom: 0.25rem;
159
+ }
160
+ .suite-info .suite-path {
161
+ word-break: break-all;
162
+ flex-grow: 1;
163
+ font-family: monospace;
164
+ font-size: 1rem;
165
+ }
166
+ .suite-info .suite-time {
167
+ margin-left: 0.5rem;
168
+ padding: 0.2rem 0.3rem;
169
+ font-size: 0.75rem;
170
+ }
171
+ .suite-info .suite-time.warn {
172
+ background-color: #d8000c;
173
+ color: #fff;
174
+ }
175
+
176
+ /* CONSOLE LOGS */
177
+ .suite-consolelog {
178
+ margin-bottom: 0.25rem;
179
+ padding: 1rem;
180
+ background-color: #efefef;
181
+ }
182
+ .suite-consolelog-header {
183
+ font-weight: bold;
184
+ }
185
+ .suite-consolelog-item {
186
+ padding: 0.5rem;
187
+ }
188
+ .suite-consolelog-item pre {
189
+ margin: 0.5rem 0;
190
+ white-space: pre-wrap;
191
+ white-space: -moz-pre-wrap;
192
+ white-space: -pre-wrap;
193
+ white-space: -o-pre-wrap;
194
+ word-wrap: break-word;
195
+ }
196
+ .suite-consolelog-item-origin {
197
+ color: #777;
198
+ font-weight: bold;
199
+ }
200
+ .suite-consolelog-item-message {
201
+ color: #000;
202
+ font-size: 1rem;
203
+ padding: 0 0.5rem;
204
+ }
205
+
206
+ /* OBSOLETE SNAPSHOTS */
207
+ .suite-obsolete-snapshots {
208
+ margin-bottom: 0.25rem;
209
+ padding: 1rem;
210
+ background-color: #ffbaba;
211
+ color: #d8000c;
212
+ }
213
+ .suite-obsolete-snapshots-header {
214
+ font-weight: bold;
215
+ }
216
+ .suite-obsolete-snapshots-item {
217
+ padding: 0.5rem;
218
+ }
219
+ .suite-obsolete-snapshots-item pre {
220
+ margin: 0.5rem 0;
221
+ white-space: pre-wrap;
222
+ white-space: -moz-pre-wrap;
223
+ white-space: -pre-wrap;
224
+ white-space: -o-pre-wrap;
225
+ word-wrap: break-word;
226
+ }
227
+ .suite-obsolete-snapshots-item-message {
228
+ color: #000;
229
+ font-size: 1rem;
230
+ padding: 0 0.5rem;
231
+ }
232
+ </style></head><body><div id="jesthtml-content"><header><h1 id="title">SequenceTranslator Test Report. Datagrok version datagrok/datagrok:latest SHA=2e08c8e54bde. Commit 1367d435.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-04-20 13:02:23</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts</div><div class="suite-time warn">18.061s</div></div><div class="suite-tests"><div class="test-result failed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">failed</div><div class="test-duration">0.524s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: Evaluation failed: Unable to find JS function "test"
233
+ at ExecutionContext._evaluateInternal (/home/runner/work/public/public/packages/SequenceTranslator/node_modules/puppeteer/src/common/ExecutionContext.ts:273:13)
234
+ at processTicksAndRejections (internal/process/task_queues.js:97:5)
235
+ at ExecutionContext.evaluate (/home/runner/work/public/public/packages/SequenceTranslator/node_modules/puppeteer/src/common/ExecutionContext.ts:140:12)</pre></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/test-node.ts:62:11)
236
+ at Generator.next (&lt;anonymous&gt;)
237
+ at fulfilled (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/test-node.ts:24:58)
238
+ at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Using web root: http://localhost:8080</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:24:11
239
+ at Generator.next (&lt;anonymous&gt;)
240
+ at /home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:27:71
241
+ at new Promise (&lt;anonymous&gt;)
242
+ at Object.&lt;anonymous&gt;.__awaiter (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:23:12)
243
+ at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/SequenceTranslator/src/__jest__/remote.test.ts:22:23)
244
+ at Promise.then.completed (/home/runner/work/public/public/packages/SequenceTranslator/node_modules/jest-circus/build/utils.js:391:28)
245
+ at new Promise (&lt;anonymous&gt;)</pre><pre class="suite-consolelog-item-message">Testing SequenceTranslator package</pre></div></div></div></div></body></html>
package/tsconfig.json CHANGED
@@ -10,7 +10,8 @@
10
10
  /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
11
11
  "lib": [
12
12
  "es2020",
13
- "dom"
13
+ "dom",
14
+ "ES2021.String"
14
15
  ],
15
16
  /* Specify library files to be included in the compilation. */
16
17
  // "allowJs": true, /* Allow javascript files to be compiled. */
@@ -1,36 +0,0 @@
1
- import * as ui from 'datagrok-api/ui';
2
- import {sequenceToSmiles} from './package';
3
- import * as OCL from 'openchemlib/full.js';
4
-
5
- export function saveSenseAntiSense() {
6
- const ssInput = ui.textInput('Sense Strand 5\' ->3\'', '');
7
- const asInput = ui.textInput('Anti Sense 3\' ->5\'', '');
8
- const saveBtn = ui.button('Save SDF', () => {
9
- const smiSS = sequenceToSmiles(ssInput.value);
10
- const smiAS = sequenceToSmiles(asInput.value, true);
11
- const result =
12
- `${OCL.Molecule.fromSmiles(smiSS).toMolfile()}\n` +
13
- `> <Sequence>\nSense Strand\n\n$$$$\n` +
14
- `${OCL.Molecule.fromSmiles(smiAS).toMolfile()}\n` +
15
- `> <Sequence>\nAnti Sense\n\n$$$$\n`;
16
- const element = document.createElement('a');
17
- element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
18
- element.setAttribute('download', ssInput.value.replace(/\s/g, '') + '.sdf');
19
- element.click();
20
- });
21
-
22
- const saveSection = ui.panel([
23
- ui.div([
24
- ui.div([
25
- ui.divH([ui.h1('Inputs')]),
26
- ui.divV([
27
- ui.div([ssInput.root]),
28
- ui.div([asInput.root]),
29
- ui.buttonsInput([saveBtn]),
30
- ], 'ui-form'),
31
- ], 'ui-form'),
32
- ], 'ui-form'),
33
- ]);
34
-
35
- return saveSection;
36
- }