@datagrok/sequence-translator 1.3.0 → 1.3.2
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 +1 -1
- package/CHANGELOG.md +18 -0
- package/dist/package-test.js +1 -2
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/files/monomers-sample/README.md +12 -0
- package/files/polytool-rules/rules_example.json +34 -0
- package/files/samples/bulk-translation-axolabs.csv +6 -0
- package/files/tests/README.md +2 -0
- package/files/tests/axolabs1.csv +2 -0
- package/package.json +23 -13
- package/src/apps/common/model/data-loader/const.ts +1 -2
- package/src/apps/common/model/data-loader/json-loader.ts +22 -31
- package/src/apps/common/model/monomer-lib/lib-wrapper.ts +13 -19
- package/src/apps/common/model/oligo-toolkit-package.ts +80 -13
- package/src/apps/common/model/parsing-validation/format-detector.ts +9 -6
- package/src/apps/common/model/parsing-validation/format-handler.ts +16 -13
- package/src/apps/common/model/parsing-validation/sequence-validator.ts +8 -3
- package/src/apps/common/view/combined-app-ui.ts +12 -10
- package/src/apps/common/view/components/colored-input/input-painters.ts +4 -3
- package/src/apps/common/view/monomer-lib-viewer.ts +2 -1
- package/src/apps/common/view/utils.ts +5 -4
- package/src/apps/pattern/model/data-manager.ts +9 -6
- package/src/apps/pattern/model/translator.ts +8 -10
- package/src/apps/pattern/model/utils.ts +0 -1
- package/src/apps/pattern/view/components/strand-editor/strand-controls.ts +0 -1
- package/src/apps/pattern/view/components/translation-examples-block.ts +2 -1
- package/src/apps/pattern/view/svg-utils/utils.ts +6 -4
- package/src/apps/pattern/view/ui.ts +4 -1
- package/src/apps/structure/model/monomer-code-parser.ts +15 -5
- package/src/apps/structure/model/oligo-structure.ts +17 -16
- package/src/apps/structure/model/sequence-to-molfile.ts +2 -1
- package/src/apps/structure/view/ui.ts +19 -11
- package/src/apps/translator/model/conversion-utils.ts +16 -11
- package/src/apps/translator/model/format-converter.ts +15 -5
- package/src/apps/translator/view/ui.ts +32 -20
- package/src/demo/demo-st-ui.ts +2 -2
- package/src/package-test.ts +9 -2
- package/src/package.ts +18 -17
- package/src/plugins/mermade.ts +11 -8
- package/src/polytool/pt-rules.ts +1 -1
- package/src/tests/const.ts +7 -5
- package/src/tests/files-tests.ts +75 -0
- package/src/tests/formats-support.ts +12 -11
- package/src/tests/formats-to-helm.ts +12 -19
- package/src/tests/helm-to-nucleotides.ts +12 -6
- package/src/tests/utils.ts +20 -0
- package/src/types.ts +18 -0
- package/dist/package-test.js.LICENSE.txt +0 -8
- /package/files/{codes-to-symbols.json → monomers-sample/codes-to-symbols.json} +0 -0
- /package/files/{formats-to-helm.json → monomers-sample/formats-to-helm.json} +0 -0
- /package/files/{linkers.json → monomers-sample/linkers.json} +0 -0
- /package/files/{monomer-lib.json → monomers-sample/monomer-lib.json} +0 -0
- /package/files/{pattern-app-data.json → monomers-sample/pattern-app-data.json} +0 -0
|
@@ -3,13 +3,12 @@ import * as DG from 'datagrok-api/dg';
|
|
|
3
3
|
import * as grok from 'datagrok-api/grok';
|
|
4
4
|
import * as ui from 'datagrok-api/ui';
|
|
5
5
|
|
|
6
|
+
import {Subject, BehaviorSubject, Observable} from 'rxjs';
|
|
7
|
+
|
|
6
8
|
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
7
9
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
8
10
|
|
|
9
|
-
import * as rxjs from 'rxjs';
|
|
10
|
-
|
|
11
11
|
import {DEFAULT_FORMATS} from '../../common/model/const';
|
|
12
|
-
import {CODES_TO_HELM_DICT} from '../../common/model/data-loader/json-loader';
|
|
13
12
|
import {download} from '../../common/model/helpers';
|
|
14
13
|
import {FormatDetector} from '../../common/model/parsing-validation/format-detector';
|
|
15
14
|
import {SequenceValidator} from '../../common/model/parsing-validation/sequence-validator';
|
|
@@ -22,19 +21,25 @@ import {MonomerLibViewer} from '../../common/view/monomer-lib-viewer';
|
|
|
22
21
|
import {SequenceToMolfileConverter} from '../../structure/model/sequence-to-molfile';
|
|
23
22
|
import {convert, getSupportedTargetFormats, getTranslatedSequences} from '../model/conversion-utils';
|
|
24
23
|
import {FormatConverter} from '../model/format-converter';
|
|
24
|
+
import {ITranslationHelper} from '../../../types';
|
|
25
|
+
|
|
25
26
|
import {NUCLEOTIDES_FORMAT, SEQUENCE_COPIED_MSG, SEQ_TOOLTIP_MSG} from './const';
|
|
26
27
|
import './style.css';
|
|
28
|
+
import {_package} from '../../../package';
|
|
27
29
|
|
|
28
30
|
const enum REQUIRED_COLUMN_LABEL {
|
|
29
31
|
SEQUENCE = 'Sequence',
|
|
30
32
|
}
|
|
33
|
+
|
|
31
34
|
const REQUIRED_COLUMN_LABELS = [REQUIRED_COLUMN_LABEL.SEQUENCE];
|
|
32
35
|
|
|
33
36
|
class TranslatorAppLayout {
|
|
34
37
|
private eventBus: EventBus;
|
|
35
|
-
private inputFormats = Object.keys(
|
|
38
|
+
private inputFormats = Object.keys(_package.jsonData.codesToHelmDict).concat(DEFAULT_FORMATS.HELM);
|
|
36
39
|
|
|
37
|
-
constructor(
|
|
40
|
+
constructor(
|
|
41
|
+
private readonly th: ITranslationHelper
|
|
42
|
+
) {
|
|
38
43
|
this.moleculeImgDiv = ui.div([]);
|
|
39
44
|
this.moleculeImgDiv.className = 'mol-host';
|
|
40
45
|
this.moleculeImgDiv.style.border = '1px solid var(--grey-2)';
|
|
@@ -63,7 +68,7 @@ class TranslatorAppLayout {
|
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
// todo: reduce # of state vars by further refactoring legacy code
|
|
66
|
-
private onInput = new
|
|
71
|
+
private onInput = new Subject<string>();
|
|
67
72
|
private moleculeImgDiv: HTMLDivElement;
|
|
68
73
|
private outputTableDiv: HTMLDivElement;
|
|
69
74
|
private formatChoiceInput: DG.InputBase;
|
|
@@ -105,7 +110,7 @@ class TranslatorAppLayout {
|
|
|
105
110
|
const outputFormats = ui.choiceInput(
|
|
106
111
|
'Output format',
|
|
107
112
|
NUCLEOTIDES_FORMAT,
|
|
108
|
-
getSupportedTargetFormats(),
|
|
113
|
+
getSupportedTargetFormats(this.th),
|
|
109
114
|
(value: string) => this.eventBus.selectOutputFormat(value)
|
|
110
115
|
);
|
|
111
116
|
const convertBulkButton = this.createConvertBulkButton();
|
|
@@ -156,7 +161,7 @@ class TranslatorAppLayout {
|
|
|
156
161
|
DG.TYPE.STRING,
|
|
157
162
|
newColumnName,
|
|
158
163
|
sequenceColumn.toList().map((sequence: string) => {
|
|
159
|
-
const result = convert(sequence, inputFormat, outputFormat);
|
|
164
|
+
const result = convert(sequence, inputFormat, outputFormat, this.th);
|
|
160
165
|
return result;
|
|
161
166
|
})
|
|
162
167
|
);
|
|
@@ -180,7 +185,8 @@ class TranslatorAppLayout {
|
|
|
180
185
|
}
|
|
181
186
|
|
|
182
187
|
private constructSingleSequenceControls(): HTMLDivElement {
|
|
183
|
-
const sequenceColoredInput = new ColoredTextInput(this.sequenceInputBase,
|
|
188
|
+
const sequenceColoredInput = new ColoredTextInput(this.sequenceInputBase,
|
|
189
|
+
(s: string) => { return highlightInvalidSubsequence(s, this.th); });
|
|
184
190
|
|
|
185
191
|
const downloadMolfileButton = ui.button(
|
|
186
192
|
'Get SDF',
|
|
@@ -242,8 +248,9 @@ class TranslatorAppLayout {
|
|
|
242
248
|
this.outputTableDiv.innerHTML = '';
|
|
243
249
|
// todo: does not detect correctly (U-A)(U-A)
|
|
244
250
|
const indexOfInvalidChar = (!this.format) ? 0 :
|
|
245
|
-
(
|
|
246
|
-
const translatedSequences = getTranslatedSequences(
|
|
251
|
+
this.th.createSequenceValidator(this.sequence).getInvalidCodeIndex(this.format!);
|
|
252
|
+
const translatedSequences = getTranslatedSequences(
|
|
253
|
+
this.sequence, indexOfInvalidChar, this.format!, this.th);
|
|
247
254
|
const tableRows = [];
|
|
248
255
|
|
|
249
256
|
for (const key of Object.keys(translatedSequences)) {
|
|
@@ -278,7 +285,7 @@ class TranslatorAppLayout {
|
|
|
278
285
|
private init(): void {
|
|
279
286
|
this.sequence = this.getFormattedSequence();
|
|
280
287
|
|
|
281
|
-
this.format = (
|
|
288
|
+
this.format = this.th.createFormatDetector(this.sequence).getFormat();
|
|
282
289
|
|
|
283
290
|
// warning: getMolfile relies on 'this.format', so the order is important
|
|
284
291
|
this.molfile = this.getMolfile();
|
|
@@ -292,7 +299,8 @@ class TranslatorAppLayout {
|
|
|
292
299
|
if (!this.format)
|
|
293
300
|
return '';
|
|
294
301
|
if (this.format === DEFAULT_FORMATS.HELM) {
|
|
295
|
-
const axolabs = (
|
|
302
|
+
const axolabs = this.th.createFormatConverter(this.sequence, this.format)
|
|
303
|
+
.convertTo(DEFAULT_FORMATS.AXOLABS);
|
|
296
304
|
return (new SequenceToMolfileConverter(axolabs, false, DEFAULT_FORMATS.AXOLABS).convert());
|
|
297
305
|
}
|
|
298
306
|
const molfile = (new SequenceToMolfileConverter(this.sequence, false, this.format)).convert();
|
|
@@ -473,13 +481,13 @@ class ColumnInputsManager {
|
|
|
473
481
|
export class EventBus {
|
|
474
482
|
private static _instance: EventBus;
|
|
475
483
|
|
|
476
|
-
private _tableSelection$ = new
|
|
484
|
+
private _tableSelection$ = new BehaviorSubject<DG.DataFrame | null>(null);
|
|
477
485
|
private _columnSelection = Object.fromEntries(REQUIRED_COLUMN_LABELS.map((columnLabel: string) => {
|
|
478
|
-
const columnSelection$ = new
|
|
486
|
+
const columnSelection$ = new BehaviorSubject<DG.Column<string> | null>(null);
|
|
479
487
|
return [columnLabel, columnSelection$];
|
|
480
488
|
}));
|
|
481
|
-
private _inputFormatSelection$ = new
|
|
482
|
-
private _outputFormatSelection$ = new
|
|
489
|
+
private _inputFormatSelection$ = new BehaviorSubject<string>(DEFAULT_FORMATS.AXOLABS);
|
|
490
|
+
private _outputFormatSelection$ = new BehaviorSubject<string>(NUCLEOTIDES_FORMAT);
|
|
483
491
|
|
|
484
492
|
private constructor() {}
|
|
485
493
|
|
|
@@ -489,7 +497,7 @@ export class EventBus {
|
|
|
489
497
|
return EventBus._instance;
|
|
490
498
|
}
|
|
491
499
|
|
|
492
|
-
get tableSelected$():
|
|
500
|
+
get tableSelected$(): Observable<DG.DataFrame | null> {
|
|
493
501
|
return this._tableSelection$.asObservable();
|
|
494
502
|
}
|
|
495
503
|
|
|
@@ -528,11 +536,15 @@ export class EventBus {
|
|
|
528
536
|
|
|
529
537
|
export class OligoTranslatorUI extends IsolatedAppUIBase {
|
|
530
538
|
private readonly topPanel: HTMLElement[];
|
|
531
|
-
private readonly layout
|
|
539
|
+
private readonly layout: TranslatorAppLayout;
|
|
532
540
|
|
|
533
|
-
constructor(
|
|
541
|
+
constructor(
|
|
542
|
+
private readonly th: ITranslationHelper
|
|
543
|
+
) {
|
|
534
544
|
super(APP_NAME.TRANSLATOR);
|
|
535
545
|
|
|
546
|
+
this.th = _package;
|
|
547
|
+
this.layout = new TranslatorAppLayout(this.th);
|
|
536
548
|
const viewMonomerLibIcon = ui.iconFA('book', MonomerLibViewer.view, 'View monomer library');
|
|
537
549
|
this.topPanel = [
|
|
538
550
|
viewMonomerLibIcon,
|
package/src/demo/demo-st-ui.ts
CHANGED
|
@@ -3,8 +3,7 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
5
|
import {delay} from '@datagrok-libraries/utils/src/test';
|
|
6
|
-
import {
|
|
7
|
-
import {_package, oligoTranslatorApp, oligoPatternApp, oligoStructureApp} from '../package';
|
|
6
|
+
import {oligoTranslatorApp, oligoPatternApp, oligoStructureApp} from '../package';
|
|
8
7
|
import {tryCatch} from '../apps/common/model/helpers';
|
|
9
8
|
|
|
10
9
|
export async function demoOligoTranslatorUI() {
|
|
@@ -31,6 +30,7 @@ export async function demoOligoStructureUI() {
|
|
|
31
30
|
const event = new Event('input');
|
|
32
31
|
textarea.dispatchEvent(event);
|
|
33
32
|
}
|
|
33
|
+
|
|
34
34
|
const view = await oligoStructureApp();
|
|
35
35
|
grok.shell.addView(view);
|
|
36
36
|
const inputSequences = ['Afcgacsu', 'Afcgacsu', 'Afcgacsu'];
|
package/src/package-test.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as ui from 'datagrok-api/ui';
|
|
1
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
|
+
|
|
2
5
|
import {runTests, tests, TestContext} from '@datagrok-libraries/utils/src/test';
|
|
6
|
+
|
|
3
7
|
import './tests/formats-to-helm';
|
|
4
8
|
import './tests/helm-to-nucleotides';
|
|
5
9
|
import './tests/formats-support';
|
|
10
|
+
import './tests/files-tests';
|
|
11
|
+
|
|
12
|
+
import {OligoToolkitTestPackage} from './tests/utils';
|
|
6
13
|
|
|
7
|
-
export const _package = new
|
|
14
|
+
export const _package = new OligoToolkitTestPackage();
|
|
8
15
|
export {tests};
|
|
9
16
|
|
|
10
17
|
//name: test
|
|
@@ -13,6 +20,6 @@ export {tests};
|
|
|
13
20
|
//input: object testContext {optional: true}
|
|
14
21
|
//output: dataframe result
|
|
15
22
|
export async function test(category: string, test: string, testContext: TestContext): Promise<DG.DataFrame> {
|
|
16
|
-
const data = await runTests({category, test, testContext});
|
|
23
|
+
const data = await runTests({category, test, testContext, verbose: true});
|
|
17
24
|
return DG.DataFrame.fromObjects(data)!;
|
|
18
25
|
}
|
package/src/package.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import DG from 'datagrok-api/dg';
|
|
2
2
|
import * as grok from 'datagrok-api/grok';
|
|
3
3
|
|
|
4
|
-
import {loadJsonData} from './apps/common/model/data-loader/json-loader';
|
|
5
4
|
import {MonomerLibWrapper} from './apps/common/model/monomer-lib/lib-wrapper';
|
|
6
5
|
import {OligoToolkitPackage} from './apps/common/model/oligo-toolkit-package';
|
|
7
6
|
import {FormatDetector} from './apps/common/model/parsing-validation/format-detector';
|
|
@@ -19,7 +18,7 @@ import {getExternalAppViewFactories} from './plugins/mermade';
|
|
|
19
18
|
import {getPolyToolConversionDialog, getPolyToolEnumerationDialog} from './polytool/pt-dialog';
|
|
20
19
|
import {_setPeptideColumn} from './polytool/utils';
|
|
21
20
|
import {PolyToolCsvLibHandler} from './polytool/csv-to-json-monomer-lib-converter';
|
|
22
|
-
|
|
21
|
+
import {ITranslationHelper} from './types';
|
|
23
22
|
|
|
24
23
|
export const _package: OligoToolkitPackage = new OligoToolkitPackage();
|
|
25
24
|
|
|
@@ -29,11 +28,11 @@ export const _package: OligoToolkitPackage = new OligoToolkitPackage();
|
|
|
29
28
|
//tags: app
|
|
30
29
|
//output: view v
|
|
31
30
|
export async function oligoToolkitApp(): Promise<DG.ViewBase> {
|
|
32
|
-
await
|
|
33
|
-
const externalViewFactories = await getExternalAppViewFactories();
|
|
31
|
+
await _package.initLibData();
|
|
32
|
+
const externalViewFactories = await getExternalAppViewFactories(_package);
|
|
34
33
|
if (!externalViewFactories)
|
|
35
34
|
throw new Error('External app view factories not loaded');
|
|
36
|
-
const appUI = new CombinedAppUI(externalViewFactories
|
|
35
|
+
const appUI = new CombinedAppUI(externalViewFactories!, _package);
|
|
37
36
|
const view = await appUI.getAppView();
|
|
38
37
|
return view;
|
|
39
38
|
}
|
|
@@ -68,16 +67,18 @@ export async function oligoStructureApp(): Promise<DG.ViewBase> {
|
|
|
68
67
|
return view;
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
//name:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
await _package.
|
|
70
|
+
//name: getTranslationHelper
|
|
71
|
+
//output: object result
|
|
72
|
+
export async function getTranslationHelper(): Promise<ITranslationHelper> {
|
|
73
|
+
await _package.initLibData();
|
|
74
|
+
return _package;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
//name: getCodeToWeightsMap
|
|
78
78
|
//output: object result
|
|
79
|
-
export function getCodeToWeightsMap(): {[key: string]: number} {
|
|
80
|
-
const
|
|
79
|
+
export function getCodeToWeightsMap(): { [key: string]: number } {
|
|
80
|
+
const monomerLibWrapper = _package.monomerLibWrapper;
|
|
81
|
+
const map = monomerLibWrapper.getCodesToWeightsMap();
|
|
81
82
|
return Object.fromEntries(map);
|
|
82
83
|
}
|
|
83
84
|
|
|
@@ -85,8 +86,8 @@ export function getCodeToWeightsMap(): {[key: string]: number} {
|
|
|
85
86
|
//input: string sequence
|
|
86
87
|
//output: bool result
|
|
87
88
|
export function validateSequence(sequence: string): boolean {
|
|
88
|
-
const validator =
|
|
89
|
-
const format = (
|
|
89
|
+
const validator = _package.createSequenceValidator(sequence);
|
|
90
|
+
const format = _package.createFormatDetector(sequence).getFormat();
|
|
90
91
|
return (format === null) ? false : validator.isValidSequence(format!);
|
|
91
92
|
}
|
|
92
93
|
|
|
@@ -137,13 +138,13 @@ export async function demoOligoStructure(): Promise<void> {
|
|
|
137
138
|
export async function translateOligonucleotideSequence(
|
|
138
139
|
sequence: string, sourceFormat: string, targetFormat: string
|
|
139
140
|
): Promise<string> {
|
|
140
|
-
await
|
|
141
|
-
return (
|
|
141
|
+
await _package.initLibData();
|
|
142
|
+
return _package.createFormatConverter(sequence, sourceFormat).convertTo(targetFormat);
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
async function getSpecifiedAppView(appName: string): Promise<DG.ViewBase> {
|
|
145
|
-
await
|
|
146
|
-
const appUI = getSpecifiedAppUI(appName);
|
|
146
|
+
await _package.initLibData();
|
|
147
|
+
const appUI = getSpecifiedAppUI(appName, _package);
|
|
147
148
|
const view = await appUI.getAppView();
|
|
148
149
|
return view;
|
|
149
150
|
}
|
package/src/plugins/mermade.ts
CHANGED
|
@@ -5,19 +5,22 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
|
|
6
6
|
import {ExternalPluginUI} from '../apps/common/view/utils';
|
|
7
7
|
import {ColoredTextInput} from '../apps/common/view/components/colored-input/colored-text-input';
|
|
8
|
-
import {highlightInvalidSubsequence} from '../apps/common/view/components/colored-input/input-painters';
|
|
9
|
-
import {CODES_TO_SYMBOLS_DICT} from '../apps/common/model/data-loader/json-loader';
|
|
10
8
|
import {MERMADE} from './const';
|
|
9
|
+
import {ITranslationHelper} from '../types';
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
import {_package} from '../package';
|
|
12
|
+
|
|
13
|
+
export async function getExternalAppViewFactories(
|
|
14
|
+
th: ITranslationHelper
|
|
15
|
+
): Promise<{ [name: string]: () => DG.View } | undefined> {
|
|
13
16
|
const externalPluginData = {
|
|
14
17
|
[MERMADE.FUNCTION_NAME]: {
|
|
15
18
|
tabName: MERMADE.TAB_NAME,
|
|
16
|
-
parameters: getMerMadeParameters()
|
|
19
|
+
parameters: getMerMadeParameters(th)
|
|
17
20
|
},
|
|
18
21
|
};
|
|
19
22
|
|
|
20
|
-
const result: {[tabName: string]: () => DG.View} = {};
|
|
23
|
+
const result: { [tabName: string]: () => DG.View } = {};
|
|
21
24
|
|
|
22
25
|
for (const [pluginName, data] of Object.entries(externalPluginData)) {
|
|
23
26
|
let div: HTMLDivElement;
|
|
@@ -37,12 +40,12 @@ export async function getExternalAppViewFactories(): Promise<{[name: string]: ()
|
|
|
37
40
|
return result;
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
function getMerMadeParameters(): {[name: string]: any} {
|
|
43
|
+
function getMerMadeParameters(th: ITranslationHelper): { [name: string]: any } {
|
|
41
44
|
const base = ui.textInput('', '');
|
|
42
|
-
const input = new ColoredTextInput(base, highlightInvalidSubsequence);
|
|
45
|
+
const input = new ColoredTextInput(base, th.highlightInvalidSubsequence);
|
|
43
46
|
|
|
44
47
|
return {
|
|
45
48
|
coloredInput: input,
|
|
46
|
-
codes:
|
|
49
|
+
codes: th.jsonData.codesToSymbolsDict
|
|
47
50
|
};
|
|
48
51
|
}
|
package/src/polytool/pt-rules.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
2
2
|
import * as grok from 'datagrok-api/grok';
|
|
3
3
|
import {ActiveFiles} from '@datagrok-libraries/utils/src/settings/active-files-base';
|
|
4
4
|
|
|
5
|
-
export const RULES_PATH = 'System:AppData/
|
|
5
|
+
export const RULES_PATH = 'System:AppData/SequenceTranslator/polytool-rules/';
|
|
6
6
|
export const RULES_STORAGE_NAME = 'Polytool';
|
|
7
7
|
export const RULES_TYPE_LINK = 'link';
|
|
8
8
|
export const RULES_TYPE_HOMODIMER = 'fragmentDuplication';
|
package/src/tests/const.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
type Dict = {[key: string]: string};
|
|
1
|
+
type Dict = { [key: string]: string };
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/* eslint-disable max-len*/
|
|
4
|
+
export const formatsToHelm: { [key: string]: Dict } = {
|
|
4
5
|
'Axolabs': {
|
|
5
6
|
'UfAfsCfsGfuacg': 'RNA1{[fR](U)p.[fR](A)[sp].[fR](C)[sp].[fR](G)p.[25r](U)p.[25r](A)p.[25r](C)p.[25r](G)}$$$$'
|
|
6
7
|
},
|
|
@@ -15,10 +16,11 @@ export const formatsToHelm: {[key: string]: Dict} = {
|
|
|
15
16
|
export const helmToNucleotides: Dict = {
|
|
16
17
|
'RNA1{[fR](U)p.[fR](A)[sp].[fR](C)[sp].[fR](G)p.[25r](U)p.[25r](A)p.[25r](C)p.[25r](G)}$$$$': 'UACGUACG',
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
// TODO: Handle monomer .d([m5C])
|
|
20
|
+
'RNA1{r(A)[sp].r(G)p.r(C)[sp].[fR](U)p.[fR](A)p.[fR](C)p.[fR](G)p.[25r](U)p.[25r](A)p.[25r](C)p.[25r](G)p}$$$$': 'AGCUACGUACG',
|
|
19
21
|
|
|
20
22
|
'RNA1{[25r](U)[sp].[25r](A)[sp].[25r](C)[sp].[25r](G)[sp].[fR](U)[sp].[fR](A)[sp].[fR](C)[sp].[fR](G)[sp].[fR](U)p.[fR](A)p.[fR](C)p.[fR](G)p.[25r](U)p.[25r](A)p.[25r](C)p.[25r](G)}$$$$': 'UACGUACGUACGUACG'
|
|
21
23
|
};
|
|
22
24
|
|
|
23
|
-
export const helmToMolfile: Dict = {
|
|
24
|
-
|
|
25
|
+
export const helmToMolfile: Dict = {};
|
|
26
|
+
/* eslint-enable max-len*/
|
|
@@ -0,0 +1,75 @@
|
|
|
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 {after, before, category, expect, test} from '@datagrok-libraries/utils/src/test';
|
|
6
|
+
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
7
|
+
|
|
8
|
+
import {getHelm} from './utils';
|
|
9
|
+
|
|
10
|
+
import {_package} from '../package-test';
|
|
11
|
+
import {ITranslationHelper} from '../types';
|
|
12
|
+
|
|
13
|
+
category('files', () => {
|
|
14
|
+
let th: ITranslationHelper;
|
|
15
|
+
|
|
16
|
+
before(async () => {
|
|
17
|
+
th = await _package.getTranslationHelper();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('list', async () => {
|
|
21
|
+
/** [subTest, success, format, src, res, tgt, error, stack ] */
|
|
22
|
+
let successCol: DG.Column<boolean>;
|
|
23
|
+
const resDf = DG.DataFrame.fromColumns([
|
|
24
|
+
DG.Column.string('subTest'),
|
|
25
|
+
successCol = DG.Column.bool('success'),
|
|
26
|
+
DG.Column.string('format'),
|
|
27
|
+
DG.Column.string('src'),
|
|
28
|
+
DG.Column.string('res'),
|
|
29
|
+
DG.Column.string('tgt'),
|
|
30
|
+
DG.Column.string('error'),
|
|
31
|
+
DG.Column.string('stack'),
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
const fiList = await _package.files.list('tests', true, '.csv');
|
|
35
|
+
for (const fi of fiList) {
|
|
36
|
+
const testDf = DG.DataFrame.fromCsv(await fi.readAsString());
|
|
37
|
+
const srcCol = testDf.columns.byIndex(0);
|
|
38
|
+
const format = srcCol.name;
|
|
39
|
+
const tgtCol = testDf.columns.byIndex(1);
|
|
40
|
+
const testDfRowCount = testDf.rowCount;
|
|
41
|
+
for (let rowIdx = 0; rowIdx < testDfRowCount; ++rowIdx) {
|
|
42
|
+
const row = resDf.rows.addNew();
|
|
43
|
+
row['subTest'] = `${fi.name}, row: ${rowIdx}`;
|
|
44
|
+
try {
|
|
45
|
+
const src = srcCol.get(rowIdx);
|
|
46
|
+
const tgt = tgtCol.get(rowIdx);
|
|
47
|
+
row['format'] = format;
|
|
48
|
+
row['src'] = src;
|
|
49
|
+
row['tgt'] = tgt;
|
|
50
|
+
const res = row['res'] = getHelm(src, format, th);
|
|
51
|
+
expect(res, tgt);
|
|
52
|
+
row['success'] = true;
|
|
53
|
+
} catch (err) {
|
|
54
|
+
const [errMsg, errStack] = errInfo(err);
|
|
55
|
+
row['error'] = errMsg;
|
|
56
|
+
row['stack'] = errStack;
|
|
57
|
+
row['success'] = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (resDf.rowCount == 0) {
|
|
63
|
+
const emptyRow = resDf.rows.addNew(
|
|
64
|
+
['empty', true, '', '']);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const failedTestIdx = successCol.toList().findIndex((s) => s != true);
|
|
68
|
+
if (failedTestIdx != -1) {
|
|
69
|
+
const fRow = resDf.rows.get(failedTestIdx);
|
|
70
|
+
throw new Error(`Subtest '${fRow['subTest']}' failed: ${fRow['error']}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return resDf;
|
|
74
|
+
}, {skipReason: 'Can not create test in async manner based on files in Shares.'});
|
|
75
|
+
});
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
/* Do not change these import lines to match external modules in webpack configuration */
|
|
2
1
|
import * as grok from 'datagrok-api/grok';
|
|
3
2
|
import * as ui from 'datagrok-api/ui';
|
|
4
3
|
import * as DG from 'datagrok-api/dg';
|
|
5
4
|
|
|
6
5
|
import {before, category, expect, test} from '@datagrok-libraries/utils/src/test';
|
|
7
6
|
import {DEFAULT_FORMATS} from '../apps/common/model/const';
|
|
8
|
-
import {loadJsonData} from '../apps/common/model/data-loader/json-loader';
|
|
9
|
-
import {formatsToHelm} from './const';
|
|
10
|
-
import {SequenceValidator} from '../apps/common/model/parsing-validation/sequence-validator';
|
|
11
7
|
import {getTranslatedSequences} from '../apps/translator/model/conversion-utils';
|
|
12
|
-
import {
|
|
8
|
+
import {ITranslationHelper} from '../types';
|
|
9
|
+
|
|
10
|
+
import {_package} from '../package-test';
|
|
11
|
+
import {formatsToHelm} from './const';
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
|
|
14
|
+
function getTranslationObject(sequence: string, format: string, th: ITranslationHelper): { [format: string]: string } {
|
|
15
|
+
const indexOfInvalidChar = th.createSequenceValidator(sequence).getInvalidCodeIndex(format);
|
|
16
|
+
return getTranslatedSequences(sequence, indexOfInvalidChar, format, th);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
const inputs = {
|
|
@@ -22,14 +22,15 @@ const inputs = {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
category('Formats support', () => {
|
|
25
|
+
let th: ITranslationHelper;
|
|
26
|
+
|
|
25
27
|
before(async () => {
|
|
26
|
-
await
|
|
27
|
-
await _package.initMonomerLib();
|
|
28
|
+
th = await _package.getTranslationHelper();
|
|
28
29
|
});
|
|
29
30
|
|
|
30
31
|
Object.entries(inputs).forEach(([format, sequence]) => {
|
|
31
32
|
test(`All formats for ${format}`, async () => {
|
|
32
|
-
const output = getTranslationObject(sequence, format);
|
|
33
|
+
const output = getTranslationObject(sequence, format, th);
|
|
33
34
|
const result = Object.keys(output).length;
|
|
34
35
|
// +1 due to nucleotides
|
|
35
36
|
const expected = Object.keys(formatsToHelm).length + 1;
|
|
@@ -1,34 +1,26 @@
|
|
|
1
|
-
/* Do not change these import lines to match external modules in webpack configuration */
|
|
2
1
|
import * as grok from 'datagrok-api/grok';
|
|
3
2
|
import * as ui from 'datagrok-api/ui';
|
|
4
3
|
import * as DG from 'datagrok-api/dg';
|
|
5
4
|
|
|
6
5
|
import {before, category, expect, test} from '@datagrok-libraries/utils/src/test';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {loadJsonData} from '../apps/common/model/data-loader/json-loader';
|
|
10
|
-
import {formatsToHelm} from './const';
|
|
11
|
-
import {_package} from '../package';
|
|
12
|
-
|
|
13
|
-
function getHelm(strand: string, format: string): string {
|
|
14
|
-
return (new FormatConverter(strand, format).convertTo(DEFAULT_FORMATS.HELM));
|
|
15
|
-
}
|
|
6
|
+
import {getFormat, getHelm} from './utils';
|
|
7
|
+
import {ITranslationHelper} from '../types';
|
|
16
8
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
9
|
+
import {_package} from '../package-test';
|
|
10
|
+
import {formatsToHelm} from './const';
|
|
20
11
|
|
|
21
12
|
category('Formats to HELM', () => {
|
|
13
|
+
let th: ITranslationHelper;
|
|
14
|
+
|
|
22
15
|
before(async () => {
|
|
23
|
-
await
|
|
24
|
-
await _package.initMonomerLib();
|
|
16
|
+
th = await _package.getTranslationHelper();
|
|
25
17
|
});
|
|
26
18
|
|
|
27
19
|
for (const format of Object.keys(formatsToHelm)) {
|
|
28
20
|
for (const [strand, helm] of Object.entries(formatsToHelm[format])) {
|
|
29
21
|
test(`${format} to HELM`, async () => {
|
|
30
22
|
const expected = helm;
|
|
31
|
-
const result = getHelm(strand, format);
|
|
23
|
+
const result = getHelm(strand, format, th);
|
|
32
24
|
expect(result, expected);
|
|
33
25
|
});
|
|
34
26
|
}
|
|
@@ -36,16 +28,17 @@ category('Formats to HELM', () => {
|
|
|
36
28
|
});
|
|
37
29
|
|
|
38
30
|
category('HELM to Formats', () => {
|
|
31
|
+
let th: ITranslationHelper;
|
|
32
|
+
|
|
39
33
|
before(async () => {
|
|
40
|
-
await
|
|
41
|
-
await _package.initMonomerLib();
|
|
34
|
+
th = await _package.getTranslationHelper();
|
|
42
35
|
});
|
|
43
36
|
|
|
44
37
|
for (const format of Object.keys(formatsToHelm)) {
|
|
45
38
|
for (const [strand, helm] of Object.entries(formatsToHelm[format])) {
|
|
46
39
|
test(`${format} to HELM`, async () => {
|
|
47
40
|
const expected = strand;
|
|
48
|
-
const result =
|
|
41
|
+
const result = getFormat(helm, format, th);
|
|
49
42
|
expect(result, expected);
|
|
50
43
|
});
|
|
51
44
|
}
|
|
@@ -1,20 +1,26 @@
|
|
|
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
|
+
|
|
1
5
|
import {before, category, expect, test} from '@datagrok-libraries/utils/src/test';
|
|
2
6
|
import {getNucleotidesSequence} from '../apps/translator/model/conversion-utils';
|
|
3
|
-
import {
|
|
7
|
+
import {ITranslationHelper} from '../types';
|
|
8
|
+
|
|
9
|
+
import {_package} from '../package-test';
|
|
4
10
|
import {helmToNucleotides} from './const';
|
|
5
|
-
|
|
6
|
-
import {MonomerLibWrapper} from '../apps/common/model/monomer-lib/lib-wrapper';
|
|
11
|
+
|
|
7
12
|
|
|
8
13
|
category('HELM to Nucleotides', () => {
|
|
14
|
+
let th: ITranslationHelper;
|
|
15
|
+
|
|
9
16
|
before(async () => {
|
|
10
|
-
await
|
|
11
|
-
await _package.initMonomerLib();
|
|
17
|
+
th = await _package.getTranslationHelper();
|
|
12
18
|
});
|
|
13
19
|
|
|
14
20
|
Object.entries(helmToNucleotides).forEach(([helm, nucleotide], idx) => {
|
|
15
21
|
test(`Sequence ${idx + 1} to nucleotides`, async () => {
|
|
16
22
|
const expected = nucleotide;
|
|
17
|
-
const result = getNucleotidesSequence(helm,
|
|
23
|
+
const result = getNucleotidesSequence(helm, th.monomerLibWrapper);
|
|
18
24
|
expect(result, expected);
|
|
19
25
|
});
|
|
20
26
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
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 {DEFAULT_FORMATS} from '../apps/common/model/const';
|
|
6
|
+
import {ITranslationHelper} from '../types';
|
|
7
|
+
|
|
8
|
+
export class OligoToolkitTestPackage extends DG.Package {
|
|
9
|
+
async getTranslationHelper(): Promise<ITranslationHelper> {
|
|
10
|
+
return (await grok.functions.call(`${this.name}:getTranslationHelper`)) as ITranslationHelper;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getHelm(strand: string, format: string, th: ITranslationHelper): string {
|
|
15
|
+
return th.createFormatConverter(strand, format).convertTo(DEFAULT_FORMATS.HELM);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getFormat(helm: string, format: string, th: ITranslationHelper): string {
|
|
19
|
+
return th.createFormatConverter(helm, DEFAULT_FORMATS.HELM).convertTo(format);
|
|
20
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
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 {JsonData} from './apps/common/model/data-loader/json-loader';
|
|
6
|
+
import {MonomerLibWrapper} from './apps/common/model/monomer-lib/lib-wrapper';
|
|
7
|
+
import {SequenceValidator} from './apps/common/model/parsing-validation/sequence-validator';
|
|
8
|
+
import {FormatConverter} from './apps/translator/model/format-converter';
|
|
9
|
+
import {FormatDetector} from './apps/common/model/parsing-validation/format-detector';
|
|
10
|
+
|
|
11
|
+
export interface ITranslationHelper {
|
|
12
|
+
get jsonData(): JsonData;
|
|
13
|
+
get monomerLibWrapper(): MonomerLibWrapper;
|
|
14
|
+
createSequenceValidator(sequence: string): SequenceValidator;
|
|
15
|
+
createFormatConverter(sequence: string, sourceFormat: string): FormatConverter;
|
|
16
|
+
createFormatDetector(sequence: string): FormatDetector;
|
|
17
|
+
highlightInvalidSubsequence: (sequence: string) => HTMLSpanElement[];
|
|
18
|
+
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Lodash <https://lodash.com/>
|
|
4
|
-
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
|
5
|
-
* Released under MIT license <https://lodash.com/license>
|
|
6
|
-
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
|
7
|
-
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
|
8
|
-
*/
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|