@datagrok/sequence-translator 1.0.17 → 1.1.4
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/.eslintrc.json +4 -3
- package/CHANGELOG.md +36 -0
- package/detectors.js +8 -0
- package/dist/package-test.js +2 -73079
- package/dist/package-test.js.map +1 -0
- package/dist/package.js +2 -72284
- package/dist/package.js.map +1 -0
- package/files/axolabs-style.json +97 -0
- package/files/codes-to-symbols.json +67 -0
- package/files/formats-to-helm.json +63 -0
- package/files/linkers.json +22 -0
- package/files/monomer-lib.json +1142 -0
- package/link-bio +7 -0
- package/package.json +30 -31
- package/scripts/build-monomer-lib.py +391 -122
- package/src/demo/demo-st-ui.ts +71 -0
- package/src/demo/handle-error.ts +12 -0
- package/src/model/axolabs/axolabs-tab.ts +111 -0
- package/src/model/axolabs/const.ts +33 -0
- package/src/{axolabs-tab → model/axolabs}/draw-svg.ts +1 -1
- package/src/{axolabs-tab → model/axolabs}/helpers.ts +7 -5
- package/src/model/const.ts +18 -0
- package/src/model/data-loading-utils/const.ts +8 -0
- package/src/model/data-loading-utils/json-loader.ts +38 -0
- package/src/model/data-loading-utils/types.ts +30 -0
- package/src/model/format-translation/const.ts +8 -0
- package/src/model/format-translation/conversion-utils.ts +49 -0
- package/src/model/format-translation/format-converter.ts +109 -0
- package/src/model/helpers.ts +12 -0
- package/src/model/monomer-lib/const.ts +3 -0
- package/src/model/monomer-lib/lib-wrapper.ts +119 -0
- package/src/model/parsing-validation/format-detector.ts +57 -0
- package/src/model/parsing-validation/sequence-validator.ts +52 -0
- package/src/model/sequence-to-structure-utils/const.ts +1 -0
- package/src/{utils/structures-works → model/sequence-to-structure-utils}/mol-transformations.ts +33 -41
- package/src/model/sequence-to-structure-utils/monomer-code-parser.ts +92 -0
- package/src/model/sequence-to-structure-utils/sdf-tab.ts +97 -0
- package/src/model/sequence-to-structure-utils/sequence-to-molfile.ts +409 -0
- package/src/package-test.ts +3 -1
- package/src/package.ts +113 -91
- package/src/tests/const.ts +24 -0
- package/src/tests/formats-support.ts +40 -0
- package/src/tests/formats-to-helm.ts +53 -0
- package/src/tests/helm-to-nucleotides.ts +28 -0
- package/src/view/const/main-tab.ts +3 -0
- package/src/view/const/view.ts +10 -0
- package/src/view/css/axolabs-tab.css +1 -0
- package/src/view/css/colored-text-input.css +27 -0
- package/src/view/css/main-tab.css +46 -0
- package/src/view/css/sdf-tab.css +39 -0
- package/src/view/monomer-lib-viewer/viewer.ts +22 -0
- package/src/view/tabs/axolabs.ts +719 -0
- package/src/view/tabs/main.ts +174 -0
- package/src/view/tabs/sdf.ts +193 -0
- package/src/view/utils/app-info-dialog.ts +18 -0
- package/src/view/utils/colored-input/colored-text-input.ts +56 -0
- package/src/view/utils/colored-input/input-painters.ts +44 -0
- package/src/view/utils/draw-molecule.ts +86 -0
- package/src/view/utils/molecule-img.ts +106 -0
- package/src/view/view.ts +127 -0
- package/tsconfig.json +12 -18
- package/webpack.config.js +17 -4
- package/README.md +0 -84
- package/css/style.css +0 -18
- package/img/Sequence Translator Axolabs.png +0 -0
- package/jest.config.js +0 -33
- package/setup-unlink-clean.cmd +0 -14
- package/setup-unlink-clean.sh +0 -21
- package/setup.cmd +0 -14
- package/setup.sh +0 -37
- package/src/__jest__/remote.test.ts +0 -77
- package/src/__jest__/test-node.ts +0 -97
- package/src/apps/oligo-sd-file-app.ts +0 -58
- package/src/autostart/calculations.ts +0 -40
- package/src/autostart/constants.ts +0 -37
- package/src/autostart/registration.ts +0 -306
- package/src/axolabs-tab/axolabs-tab.ts +0 -873
- package/src/axolabs-tab/define-pattern.ts +0 -874
- package/src/hardcode-to-be-eliminated/ICDs.ts +0 -3
- package/src/hardcode-to-be-eliminated/IDPs.ts +0 -3
- package/src/hardcode-to-be-eliminated/const.ts +0 -5
- package/src/hardcode-to-be-eliminated/constants.ts +0 -101
- package/src/hardcode-to-be-eliminated/converters.ts +0 -323
- package/src/hardcode-to-be-eliminated/map.ts +0 -720
- package/src/hardcode-to-be-eliminated/salts.ts +0 -2
- package/src/hardcode-to-be-eliminated/sources.ts +0 -3
- package/src/hardcode-to-be-eliminated/users.ts +0 -3
- package/src/main-tab/main-tab.ts +0 -210
- package/src/sdf-tab/sdf-tab.ts +0 -163
- package/src/sdf-tab/sequence-codes-tools.ts +0 -347
- package/src/tests/smiles-tests.ts +0 -458
- package/src/utils/const.ts +0 -0
- package/src/utils/helpers.ts +0 -28
- package/src/utils/parse.ts +0 -27
- package/src/utils/sdf-add-columns.ts +0 -118
- package/src/utils/sdf-save-table.ts +0 -56
- package/src/utils/structures-works/draw-molecule.ts +0 -84
- package/src/utils/structures-works/from-monomers.ts +0 -266
- package/test-SequenceTranslator-6288c2fbe346-695b7b55.html +0 -259
- package/vendors/openchemlib-full.js +0 -293
package/src/main-tab/main-tab.ts
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import * as grok from 'datagrok-api/grok';
|
|
2
|
-
import * as ui from 'datagrok-api/ui';
|
|
3
|
-
import * as DG from 'datagrok-api/dg';
|
|
4
|
-
|
|
5
|
-
import * as rxjs from 'rxjs';
|
|
6
|
-
import $ from 'cash-dom';
|
|
7
|
-
|
|
8
|
-
import {convertSequence, undefinedInputSequence, isValidSequence} from '../sdf-tab/sequence-codes-tools';
|
|
9
|
-
|
|
10
|
-
// todo: elminate completely
|
|
11
|
-
import {map} from '../hardcode-to-be-eliminated/map';
|
|
12
|
-
import {MODIFICATIONS} from '../hardcode-to-be-eliminated/const';
|
|
13
|
-
|
|
14
|
-
// todo: unify with lib bio monomers works
|
|
15
|
-
import {sequenceToSmiles, sequenceToMolV3000} from '../utils/structures-works/from-monomers';
|
|
16
|
-
import {drawMolecule} from '../utils/structures-works/draw-molecule';
|
|
17
|
-
|
|
18
|
-
import {download} from '../utils/helpers';
|
|
19
|
-
|
|
20
|
-
const defaultInput = 'fAmCmGmAmCpsmU'; // todo: capitalize constants
|
|
21
|
-
const sequenceWasCopied = 'Copied'; // todo: wrap hardcoded literals into constants
|
|
22
|
-
const tooltipSequence = 'Copy sequence';
|
|
23
|
-
|
|
24
|
-
export async function getMainTab(onSequenceChanged: (seq: string) => void): Promise<HTMLDivElement> {
|
|
25
|
-
const onInput: rxjs.Subject<string> = new rxjs.Subject<string>();
|
|
26
|
-
|
|
27
|
-
async function updateTableAndMolecule(sequence: string, inputFormat: string): Promise<void> {
|
|
28
|
-
moleculeImgDiv.innerHTML = '';
|
|
29
|
-
outputTableDiv.innerHTML = '';
|
|
30
|
-
const pi = DG.TaskBarProgressIndicator.create('Rendering table and molecule...');
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
sequence = sequence.replace(/\s/g, '');
|
|
34
|
-
const output = isValidSequence(sequence, null);
|
|
35
|
-
inputFormatChoiceInput.value = output.synthesizer![0];
|
|
36
|
-
const outputSequenceObj = convertSequence(sequence, output);
|
|
37
|
-
const tableRows = [];
|
|
38
|
-
|
|
39
|
-
for (const key of Object.keys(outputSequenceObj).slice(1)) {
|
|
40
|
-
const indexOfFirstNotValidChar = ('indexOfFirstNotValidChar' in outputSequenceObj) ?
|
|
41
|
-
JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).indexOfFirstNotValidChar :
|
|
42
|
-
-1;
|
|
43
|
-
|
|
44
|
-
tableRows.push({
|
|
45
|
-
'key': key,
|
|
46
|
-
'value': ('indexOfFirstNotValidChar' in outputSequenceObj) ?
|
|
47
|
-
ui.divH([
|
|
48
|
-
ui.divText(sequence.slice(0, indexOfFirstNotValidChar), {style: {color: 'grey'}}),
|
|
49
|
-
ui.tooltip.bind(
|
|
50
|
-
ui.divText(sequence.slice(indexOfFirstNotValidChar), {style: {color: 'red'}}),
|
|
51
|
-
'Expected format: ' + JSON.parse(outputSequenceObj.indexOfFirstNotValidChar!).synthesizer +
|
|
52
|
-
'. See tables with valid codes on the right',
|
|
53
|
-
),
|
|
54
|
-
]) : //@ts-ignore
|
|
55
|
-
ui.link(outputSequenceObj[key], () => navigator.clipboard.writeText(outputSequenceObj[key])
|
|
56
|
-
.then(() => grok.shell.info(sequenceWasCopied)), tooltipSequence, ''),
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
outputTableDiv.append(
|
|
61
|
-
ui.div([
|
|
62
|
-
DG.HtmlTable.create(tableRows, (item: { key: string; value: string; }) =>
|
|
63
|
-
[item.key, item.value], ['Code', 'Sequence']).root,
|
|
64
|
-
])
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
if (outputSequenceObj.type !== undefinedInputSequence && outputSequenceObj.Error !== undefinedInputSequence) {
|
|
68
|
-
const formCanvasWidth = 500;
|
|
69
|
-
const formCanvasHeight = 170;
|
|
70
|
-
const molfile = sequenceToMolV3000(
|
|
71
|
-
inputSequenceField.value.replace(/\s/g, ''), false, true,
|
|
72
|
-
output.synthesizer![0]
|
|
73
|
-
);
|
|
74
|
-
await drawMolecule(moleculeImgDiv, formCanvasWidth, formCanvasHeight, molfile);
|
|
75
|
-
} else {
|
|
76
|
-
moleculeImgDiv.innerHTML = '';
|
|
77
|
-
}
|
|
78
|
-
} finally {
|
|
79
|
-
pi.close();
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const inputFormatChoiceInput = ui.choiceInput('Input format: ', 'Janssen GCRS Codes', Object.keys(map));
|
|
84
|
-
inputFormatChoiceInput.onInput((format: string) => {
|
|
85
|
-
updateTableAndMolecule(inputSequenceField.value.replace(/\s/g, ''), format);
|
|
86
|
-
});
|
|
87
|
-
const moleculeImgDiv = ui.block([]);
|
|
88
|
-
const outputTableDiv = ui.div([]);
|
|
89
|
-
const inputSequenceField = ui.textInput('', defaultInput, (sequence: string) => {
|
|
90
|
-
// Send event to DG.debounce()
|
|
91
|
-
onInput.next(sequence);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
DG.debounce<string>(onInput, 300).subscribe((sequence) => {
|
|
95
|
-
updateTableAndMolecule(sequence, inputFormatChoiceInput.value!);
|
|
96
|
-
onSequenceChanged(sequence);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
const asoGapmersGrid = DG.Viewer.grid(
|
|
100
|
-
DG.DataFrame.fromObjects([
|
|
101
|
-
{'Name': '2\'MOE-5Me-rU', 'BioSpring': '5', 'Janssen GCRS': 'moeT'},
|
|
102
|
-
{'Name': '2\'MOE-rA', 'BioSpring': '6', 'Janssen GCRS': 'moeA'},
|
|
103
|
-
{'Name': '2\'MOE-5Me-rC', 'BioSpring': '7', 'Janssen GCRS': 'moe5mC'},
|
|
104
|
-
{'Name': '2\'MOE-rG', 'BioSpring': '8', 'Janssen GCRS': 'moeG'},
|
|
105
|
-
{'Name': '5-Methyl-dC', 'BioSpring': '9', 'Janssen GCRS': '5mC'},
|
|
106
|
-
{'Name': 'ps linkage', 'BioSpring': '*', 'Janssen GCRS': 'ps'},
|
|
107
|
-
{'Name': 'dA', 'BioSpring': 'A', 'Janssen GCRS': 'A, dA'},
|
|
108
|
-
{'Name': 'dC', 'BioSpring': 'C', 'Janssen GCRS': 'C, dC'},
|
|
109
|
-
{'Name': 'dG', 'BioSpring': 'G', 'Janssen GCRS': 'G, dG'},
|
|
110
|
-
{'Name': 'dT', 'BioSpring': 'T', 'Janssen GCRS': 'T, dT'},
|
|
111
|
-
{'Name': 'rA', 'BioSpring': '', 'Janssen GCRS': 'rA'},
|
|
112
|
-
{'Name': 'rC', 'BioSpring': '', 'Janssen GCRS': 'rC'},
|
|
113
|
-
{'Name': 'rG', 'BioSpring': '', 'Janssen GCRS': 'rG'},
|
|
114
|
-
{'Name': 'rU', 'BioSpring': '', 'Janssen GCRS': 'rU'},
|
|
115
|
-
])!, {showRowHeader: false, showCellTooltip: false, allowEdit: false},
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
const omeAndFluoroGrid = DG.Viewer.grid(
|
|
119
|
-
DG.DataFrame.fromObjects([
|
|
120
|
-
{'Name': '2\'-fluoro-U', 'BioSpring': '1', 'Axolabs': 'Uf', 'Janssen GCRS': 'fU'},
|
|
121
|
-
{'Name': '2\'-fluoro-A', 'BioSpring': '2', 'Axolabs': 'Af', 'Janssen GCRS': 'fA'},
|
|
122
|
-
{'Name': '2\'-fluoro-C', 'BioSpring': '3', 'Axolabs': 'Cf', 'Janssen GCRS': 'fC'},
|
|
123
|
-
{'Name': '2\'-fluoro-G', 'BioSpring': '4', 'Axolabs': 'Gf', 'Janssen GCRS': 'fG'},
|
|
124
|
-
{'Name': '2\'OMe-rU', 'BioSpring': '5', 'Axolabs': 'u', 'Janssen GCRS': 'mU'},
|
|
125
|
-
{'Name': '2\'OMe-rA', 'BioSpring': '6', 'Axolabs': 'a', 'Janssen GCRS': 'mA'},
|
|
126
|
-
{'Name': '2\'OMe-rC', 'BioSpring': '7', 'Axolabs': 'c', 'Janssen GCRS': 'mC'},
|
|
127
|
-
{'Name': '2\'OMe-rG', 'BioSpring': '8', 'Axolabs': 'g', 'Janssen GCRS': 'mG'},
|
|
128
|
-
{'Name': 'ps linkage', 'BioSpring': '*', 'Axolabs': 's', 'Janssen GCRS': 'ps'},
|
|
129
|
-
])!, {showRowHeader: false, showCellTooltip: false, allowEdit: false},
|
|
130
|
-
);
|
|
131
|
-
|
|
132
|
-
const overhangModificationsGrid = DG.Viewer.grid(
|
|
133
|
-
DG.DataFrame.fromColumns([
|
|
134
|
-
DG.Column.fromStrings('Name', Object.keys(MODIFICATIONS)),
|
|
135
|
-
])!, {showRowHeader: false, showCellTooltip: false, allowEdit: false},
|
|
136
|
-
);
|
|
137
|
-
updateTableAndMolecule(defaultInput, inputFormatChoiceInput.value!);
|
|
138
|
-
|
|
139
|
-
const codesTablesDiv = ui.splitV([
|
|
140
|
-
ui.box(ui.h2('ASO Gapmers'), {style: {maxHeight: '40px'}}),
|
|
141
|
-
asoGapmersGrid.root,
|
|
142
|
-
ui.box(ui.h2('2\'-OMe and 2\'-F siRNA'), {style: {maxHeight: '40px'}}),
|
|
143
|
-
omeAndFluoroGrid.root,
|
|
144
|
-
ui.box(ui.h2('Overhang modifications'), {style: {maxHeight: '40px'}}),
|
|
145
|
-
overhangModificationsGrid.root,
|
|
146
|
-
], {style: {maxWidth: '350px'}});
|
|
147
|
-
|
|
148
|
-
const appMainDescription = ui.info([
|
|
149
|
-
ui.divText('How to convert one sequence:', {style: {'font-weight': 'bolder'}}),
|
|
150
|
-
ui.divText('Paste sequence into the text field below'),
|
|
151
|
-
ui.divText('\n How to convert many sequences:', {style: {'font-weight': 'bolder'}}),
|
|
152
|
-
ui.divText('1. Drag & drop an Excel or CSV file with sequences into Datagrok'),
|
|
153
|
-
ui.divText('2. Right-click on the column header, then see the \'Convert\' menu'),
|
|
154
|
-
ui.divText('This will add the result column to the right of the table'),
|
|
155
|
-
], 'Convert oligonucleotide sequences between Nucleotides, BioSpring, Axolabs, Mermade 12 and GCRS representations.');
|
|
156
|
-
|
|
157
|
-
$(codesTablesDiv).hide();
|
|
158
|
-
const switchInput = ui.switchInput('Codes', false, (v: boolean) => (v) ?
|
|
159
|
-
$(codesTablesDiv).show() :
|
|
160
|
-
$(codesTablesDiv).hide(),
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
const downloadMolFileIcon = ui.iconFA('download', async () => {
|
|
164
|
-
const clearSequence = inputSequenceField.value.replace(/\s/g, '');
|
|
165
|
-
const result = sequenceToMolV3000(inputSequenceField.value.replace(/\s/g, ''), false, false,
|
|
166
|
-
inputFormatChoiceInput.value!);
|
|
167
|
-
download(clearSequence + '.mol', encodeURIComponent(result));
|
|
168
|
-
}, 'Save .mol file');
|
|
169
|
-
|
|
170
|
-
const copySmilesIcon = ui.iconFA('copy', () => {
|
|
171
|
-
navigator.clipboard.writeText(
|
|
172
|
-
sequenceToSmiles(inputSequenceField.value.replace(/\s/g, ''), false, inputFormatChoiceInput.value!),
|
|
173
|
-
).then(() => grok.shell.info(sequenceWasCopied));
|
|
174
|
-
}, 'Copy SMILES');
|
|
175
|
-
|
|
176
|
-
const topPanel = [
|
|
177
|
-
downloadMolFileIcon,
|
|
178
|
-
copySmilesIcon,
|
|
179
|
-
switchInput.root, // todo: remove from top panel
|
|
180
|
-
];
|
|
181
|
-
|
|
182
|
-
const v = grok.shell.v;
|
|
183
|
-
const tabControl = grok.shell.sidebar;
|
|
184
|
-
tabControl.onTabChanged.subscribe((_) => {
|
|
185
|
-
v.setRibbonPanels([(tabControl.currentPane.name == 'MAIN') ? topPanel : []]);
|
|
186
|
-
});
|
|
187
|
-
v.setRibbonPanels([topPanel]);
|
|
188
|
-
|
|
189
|
-
return ui.box(
|
|
190
|
-
ui.splitH([
|
|
191
|
-
ui.splitV([
|
|
192
|
-
ui.panel([
|
|
193
|
-
appMainDescription,
|
|
194
|
-
ui.div([
|
|
195
|
-
ui.h1('Input sequence'),
|
|
196
|
-
ui.div([], 'input-base'),
|
|
197
|
-
inputSequenceField.root,
|
|
198
|
-
], 'inputSequence'),
|
|
199
|
-
ui.div([inputFormatChoiceInput], {style: {padding: '5px 0'}}),
|
|
200
|
-
ui.block([
|
|
201
|
-
ui.h1('Output'),
|
|
202
|
-
outputTableDiv,
|
|
203
|
-
]),
|
|
204
|
-
moleculeImgDiv,
|
|
205
|
-
], 'sequence'),
|
|
206
|
-
]),
|
|
207
|
-
codesTablesDiv,
|
|
208
|
-
], {style: {height: '100%', width: '100%'}}),
|
|
209
|
-
);
|
|
210
|
-
}
|
package/src/sdf-tab/sdf-tab.ts
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import * as grok from 'datagrok-api/grok';
|
|
2
|
-
import * as ui from 'datagrok-api/ui';
|
|
3
|
-
import * as DG from 'datagrok-api/dg';
|
|
4
|
-
import * as rxjs from 'rxjs';
|
|
5
|
-
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
6
|
-
|
|
7
|
-
import $ from 'cash-dom';
|
|
8
|
-
|
|
9
|
-
import {download} from '../utils/helpers';
|
|
10
|
-
|
|
11
|
-
import {sequenceToMolV3000} from '../utils/structures-works/from-monomers';
|
|
12
|
-
import {linkStrandsV3000} from '../utils/structures-works/mol-transformations';
|
|
13
|
-
import {getFormat} from './sequence-codes-tools';
|
|
14
|
-
|
|
15
|
-
import {drawMolecule} from '../utils/structures-works/draw-molecule';
|
|
16
|
-
|
|
17
|
-
function getMolfileForImg(
|
|
18
|
-
ss: string, as: string,
|
|
19
|
-
as2: string | null = null,
|
|
20
|
-
invertSS: boolean, invertAS: boolean, invertAS2: boolean,
|
|
21
|
-
useChiral: boolean
|
|
22
|
-
): string {
|
|
23
|
-
const formatAs = getFormat(as);
|
|
24
|
-
const formatSs = getFormat(ss);
|
|
25
|
-
let formatAs2: string | null = null;
|
|
26
|
-
let molAS2: string | null = null;
|
|
27
|
-
|
|
28
|
-
let molSS = '';
|
|
29
|
-
let molAS = '';
|
|
30
|
-
try {
|
|
31
|
-
// a workaround to get the SS depicted in case AS is empty
|
|
32
|
-
molSS = sequenceToMolV3000(ss, invertSS, false, formatSs!);
|
|
33
|
-
molAS = sequenceToMolV3000(as, invertAS, false, formatAs!);
|
|
34
|
-
} catch (err) {
|
|
35
|
-
const errStr = errorToConsole(err);
|
|
36
|
-
console.error(errStr);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (as2 !== null && as2 !== '') {
|
|
40
|
-
formatAs2 = getFormat(as2!);
|
|
41
|
-
molAS2 = sequenceToMolV3000(as2, invertAS2!, false, formatAs2!);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const antiStrands = molAS2 === null ? [molAS] : [molAS, molAS2];
|
|
45
|
-
const resultingMolfile = linkStrandsV3000({senseStrands: [molSS], antiStrands: antiStrands}, useChiral);
|
|
46
|
-
return resultingMolfile;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function saveSdf(as: string, ss: string,
|
|
50
|
-
oneEntity: boolean, useChiral: boolean,
|
|
51
|
-
invertSS: boolean, invertAS: boolean,
|
|
52
|
-
as2: string | null = null, invertAS2: boolean | null
|
|
53
|
-
): void {
|
|
54
|
-
const formatAs = getFormat(as);
|
|
55
|
-
const formatSs = getFormat(ss);
|
|
56
|
-
let formatAs2: string | null = null;
|
|
57
|
-
let molAS2: string | null = null;
|
|
58
|
-
|
|
59
|
-
const molSS = sequenceToMolV3000(ss, invertSS, false, formatSs!);
|
|
60
|
-
const molAS = sequenceToMolV3000(as, invertAS, false, formatAs!);
|
|
61
|
-
|
|
62
|
-
if (as2 !== null && as2 !== '') {
|
|
63
|
-
formatAs2 = getFormat(as2!);
|
|
64
|
-
molAS2 = sequenceToMolV3000(as2, invertAS2!, false, formatAs2!);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
let result: string;
|
|
68
|
-
if (oneEntity) {
|
|
69
|
-
const antiStrands = molAS2 === null ? [molAS] : [molAS, molAS2];
|
|
70
|
-
result = linkStrandsV3000({senseStrands: [molSS], antiStrands: antiStrands}, useChiral) + '\n$$$$\n';
|
|
71
|
-
} else {
|
|
72
|
-
result =
|
|
73
|
-
molSS + '\n' +
|
|
74
|
-
`> <Sequence>\nSense Strand\n$$$$\n` +
|
|
75
|
-
molAS + '\n' +
|
|
76
|
-
`> <Sequence>\nAnti Sense\n$$$$\n`;
|
|
77
|
-
|
|
78
|
-
if (molAS2) {
|
|
79
|
-
result += molAS2+ '\n' +
|
|
80
|
-
`> <Sequence>\nAnti Sense 2\n$$$$\n`;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// construct date-time in the form yyyy-mm-dd_hh-mm-ss
|
|
85
|
-
const date = new Date();
|
|
86
|
-
function pad(x: number): string {
|
|
87
|
-
return (x >= 10) ? x.toString() : '0' + x.toString();
|
|
88
|
-
}
|
|
89
|
-
const dateString: string = date.getFullYear() + '-' + pad(date.getMonth() + 1) +
|
|
90
|
-
'-' + pad(date.getDate()) + '_' + pad(date.getHours()) + '-' +
|
|
91
|
-
pad(date.getMinutes()) + '-' + pad(date.getSeconds());
|
|
92
|
-
|
|
93
|
-
download(`SequenceTranslator-${dateString}.sdf`, encodeURIComponent(result));
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/** UI of the SDF tab on the application's view */
|
|
97
|
-
export function getSdfTab(): HTMLDivElement {
|
|
98
|
-
const onInput: rxjs.Subject<string> = new rxjs.Subject<string>();
|
|
99
|
-
|
|
100
|
-
// inputs
|
|
101
|
-
const inputColHeader = ui.h1('Sequences');
|
|
102
|
-
const ssInput = ui.textInput('Sense Strand', '', () => { onInput.next(); });
|
|
103
|
-
ssInput.root.style.color = 'red';
|
|
104
|
-
const asInput = ui.textInput('Anti Sense', '', () => { onInput.next(); });
|
|
105
|
-
const as2Input = ui.textInput('Anti Sense 2', '', () => { onInput.next(); });
|
|
106
|
-
const saveEntity = ui.boolInput('Save as one entity', true);
|
|
107
|
-
const useChiralInput = ui.boolInput('Use chiral', true);
|
|
108
|
-
|
|
109
|
-
// default values
|
|
110
|
-
const straight = '5 prime -> 3 prime';
|
|
111
|
-
const inverse = '3 prime -> 5 prime';
|
|
112
|
-
let invertSS = false;
|
|
113
|
-
let invertAS = false;
|
|
114
|
-
const invertAS2 = false;
|
|
115
|
-
|
|
116
|
-
// choice inputs
|
|
117
|
-
const ssDirection = ui.choiceInput('SS direction', straight, [straight, inverse]);
|
|
118
|
-
ssDirection.onChanged(() => { invertSS = ssDirection.value === inverse; });
|
|
119
|
-
const asDirection = ui.choiceInput('AS direction', straight, [straight, inverse]);
|
|
120
|
-
asDirection.onChanged(() => { invertAS = asDirection.value === inverse; });
|
|
121
|
-
const as2Direction = ui.choiceInput('AS 2 direction', straight, [straight, inverse]);
|
|
122
|
-
as2Direction.onChanged(() => { invertAS = asDirection.value === inverse; });
|
|
123
|
-
|
|
124
|
-
// molecule image
|
|
125
|
-
const moleculeImgDiv = ui.block([]);
|
|
126
|
-
DG.debounce<string>(onInput, 300).subscribe(async () => {
|
|
127
|
-
let molfile = '';
|
|
128
|
-
try {
|
|
129
|
-
molfile = getMolfileForImg(
|
|
130
|
-
ssInput.value, asInput.value, as2Input.value, invertSS, invertAS, invertAS2, useChiralInput.value!
|
|
131
|
-
);
|
|
132
|
-
} catch (err) {
|
|
133
|
-
const errStr = errorToConsole(err);
|
|
134
|
-
console.error(errStr);
|
|
135
|
-
}
|
|
136
|
-
// todo: calculate relative numbers
|
|
137
|
-
const canvasWidth = 500;
|
|
138
|
-
const canvasHeight = 170;
|
|
139
|
-
// todo: remove div with image if molfile empty
|
|
140
|
-
await drawMolecule(moleculeImgDiv, canvasWidth, canvasHeight, molfile);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
const saveButton = ui.buttonsInput([
|
|
144
|
-
ui.bigButton('Save SDF', () =>
|
|
145
|
-
saveSdf(
|
|
146
|
-
asInput.value, ssInput.value, saveEntity.value!,
|
|
147
|
-
useChiralInput.value!, invertSS, invertAS, as2Input.value, invertAS2)
|
|
148
|
-
)
|
|
149
|
-
]);
|
|
150
|
-
//@ts-ignore
|
|
151
|
-
// the above line is recommended by Dmitry because saveButton has wrong return
|
|
152
|
-
// type
|
|
153
|
-
const form1 = ui.form([inputColHeader, ssInput, asInput, as2Input, saveButton]);
|
|
154
|
-
form1.className = 'ui-form ui-form-wide';
|
|
155
|
-
const form2 = ui.form([ssDirection, asDirection, as2Direction, saveEntity, useChiralInput]);
|
|
156
|
-
form2.className = 'ui-form ui-form-wide';
|
|
157
|
-
|
|
158
|
-
const body = ui.divV([ui.divH([ui.block([form1]), form2]), moleculeImgDiv]);
|
|
159
|
-
$(form1).find('textarea').css('flex-grow', '1');
|
|
160
|
-
$(form1).find('label').css('max-width', '140px');
|
|
161
|
-
|
|
162
|
-
return body;
|
|
163
|
-
}
|