@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.
Files changed (55) hide show
  1. package/.eslintrc.json +1 -1
  2. package/CHANGELOG.md +18 -0
  3. package/dist/package-test.js +1 -2
  4. package/dist/package-test.js.map +1 -1
  5. package/dist/package.js +1 -1
  6. package/dist/package.js.map +1 -1
  7. package/files/monomers-sample/README.md +12 -0
  8. package/files/polytool-rules/rules_example.json +34 -0
  9. package/files/samples/bulk-translation-axolabs.csv +6 -0
  10. package/files/tests/README.md +2 -0
  11. package/files/tests/axolabs1.csv +2 -0
  12. package/package.json +23 -13
  13. package/src/apps/common/model/data-loader/const.ts +1 -2
  14. package/src/apps/common/model/data-loader/json-loader.ts +22 -31
  15. package/src/apps/common/model/monomer-lib/lib-wrapper.ts +13 -19
  16. package/src/apps/common/model/oligo-toolkit-package.ts +80 -13
  17. package/src/apps/common/model/parsing-validation/format-detector.ts +9 -6
  18. package/src/apps/common/model/parsing-validation/format-handler.ts +16 -13
  19. package/src/apps/common/model/parsing-validation/sequence-validator.ts +8 -3
  20. package/src/apps/common/view/combined-app-ui.ts +12 -10
  21. package/src/apps/common/view/components/colored-input/input-painters.ts +4 -3
  22. package/src/apps/common/view/monomer-lib-viewer.ts +2 -1
  23. package/src/apps/common/view/utils.ts +5 -4
  24. package/src/apps/pattern/model/data-manager.ts +9 -6
  25. package/src/apps/pattern/model/translator.ts +8 -10
  26. package/src/apps/pattern/model/utils.ts +0 -1
  27. package/src/apps/pattern/view/components/strand-editor/strand-controls.ts +0 -1
  28. package/src/apps/pattern/view/components/translation-examples-block.ts +2 -1
  29. package/src/apps/pattern/view/svg-utils/utils.ts +6 -4
  30. package/src/apps/pattern/view/ui.ts +4 -1
  31. package/src/apps/structure/model/monomer-code-parser.ts +15 -5
  32. package/src/apps/structure/model/oligo-structure.ts +17 -16
  33. package/src/apps/structure/model/sequence-to-molfile.ts +2 -1
  34. package/src/apps/structure/view/ui.ts +19 -11
  35. package/src/apps/translator/model/conversion-utils.ts +16 -11
  36. package/src/apps/translator/model/format-converter.ts +15 -5
  37. package/src/apps/translator/view/ui.ts +32 -20
  38. package/src/demo/demo-st-ui.ts +2 -2
  39. package/src/package-test.ts +9 -2
  40. package/src/package.ts +18 -17
  41. package/src/plugins/mermade.ts +11 -8
  42. package/src/polytool/pt-rules.ts +1 -1
  43. package/src/tests/const.ts +7 -5
  44. package/src/tests/files-tests.ts +75 -0
  45. package/src/tests/formats-support.ts +12 -11
  46. package/src/tests/formats-to-helm.ts +12 -19
  47. package/src/tests/helm-to-nucleotides.ts +12 -6
  48. package/src/tests/utils.ts +20 -0
  49. package/src/types.ts +18 -0
  50. package/dist/package-test.js.LICENSE.txt +0 -8
  51. /package/files/{codes-to-symbols.json → monomers-sample/codes-to-symbols.json} +0 -0
  52. /package/files/{formats-to-helm.json → monomers-sample/formats-to-helm.json} +0 -0
  53. /package/files/{linkers.json → monomers-sample/linkers.json} +0 -0
  54. /package/files/{monomer-lib.json → monomers-sample/monomer-lib.json} +0 -0
  55. /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(CODES_TO_HELM_DICT).concat(DEFAULT_FORMATS.HELM);
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 rxjs.Subject<string>();
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, highlightInvalidSubsequence);
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
- (new SequenceValidator(this.sequence)).getInvalidCodeIndex(this.format!);
246
- const translatedSequences = getTranslatedSequences(this.sequence, indexOfInvalidChar, this.format!);
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 = (new FormatDetector(this.sequence)).getFormat();
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 = (new FormatConverter(this.sequence, this.format).convertTo(DEFAULT_FORMATS.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 rxjs.BehaviorSubject<DG.DataFrame | null>(null);
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 rxjs.BehaviorSubject<DG.Column<string> | null>(null);
486
+ const columnSelection$ = new BehaviorSubject<DG.Column<string> | null>(null);
479
487
  return [columnLabel, columnSelection$];
480
488
  }));
481
- private _inputFormatSelection$ = new rxjs.BehaviorSubject<string>(DEFAULT_FORMATS.AXOLABS);
482
- private _outputFormatSelection$ = new rxjs.BehaviorSubject<string>(NUCLEOTIDES_FORMAT);
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$(): rxjs.Observable<DG.DataFrame | null> {
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 = new TranslatorAppLayout();
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,
@@ -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 {loadJsonData} from '../apps/common/model/data-loader/json-loader';
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'];
@@ -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 DG.Package();
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 initSequenceTranslatorLibData();
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: initSequenceTranslatorLibData
72
- export async function initSequenceTranslatorLibData(): Promise<void> {
73
- await loadJsonData();
74
- await _package.initMonomerLib();
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 map = MonomerLibWrapper.getInstance().getCodesToWeightsMap();
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 = new SequenceValidator(sequence);
89
- const format = (new FormatDetector(sequence).getFormat());
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 initSequenceTranslatorLibData();
141
- return (new FormatConverter(sequence, sourceFormat)).convertTo(targetFormat);
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 initSequenceTranslatorLibData();
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
  }
@@ -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
- export async function getExternalAppViewFactories(): Promise<{[name: string]: () => DG.View} | undefined> {
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: CODES_TO_SYMBOLS_DICT
49
+ codes: th.jsonData.codesToSymbolsDict
47
50
  };
48
51
  }
@@ -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/Bio/polytool-rules/';
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';
@@ -1,6 +1,7 @@
1
- type Dict = {[key: string]: string};
1
+ type Dict = { [key: string]: string };
2
2
 
3
- export const formatsToHelm: {[key: string]: Dict} = {
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
- '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.d([m5C])}$$$$': 'AGCUACGUACGC',
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 {_package} from '../package';
8
+ import {ITranslationHelper} from '../types';
9
+
10
+ import {_package} from '../package-test';
11
+ import {formatsToHelm} from './const';
13
12
 
14
- function getTranslationObject(sequence: string, format: string): {[format: string]: string} {
15
- const indexOfInvalidChar = (new SequenceValidator(sequence)).getInvalidCodeIndex(format);
16
- return getTranslatedSequences(sequence, indexOfInvalidChar, format);
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 loadJsonData();
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 {DEFAULT_FORMATS} from '../apps/common/model/const';
8
- import {FormatConverter} from '../apps/translator/model/format-converter';
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
- function getFromat(helm: string, format: string): string {
18
- return (new FormatConverter(helm, DEFAULT_FORMATS.HELM).convertTo(format));
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 loadJsonData();
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 loadJsonData();
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 = getFromat(helm, format);
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 {loadJsonData} from '../apps/common/model/data-loader/json-loader';
7
+ import {ITranslationHelper} from '../types';
8
+
9
+ import {_package} from '../package-test';
4
10
  import {helmToNucleotides} from './const';
5
- import {_package} from '../package';
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 loadJsonData();
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, MonomerLibWrapper.getInstance());
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
- */