@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
@@ -0,0 +1,12 @@
1
+ Sample files of the package SequenceTranslator with samples of
2
+ additional monomer libraries and dictionaries of substituting HELM substructures into sequences.
3
+
4
+ codes-to-symbols.json: monomer codes in different formats corresponding to monomer symbols in monomer-lib.json
5
+
6
+ formats-to-helm.json: monomer codes corresponding to helm substructures
7
+
8
+ linkers.json: monomers containing phospate or phosphorothioate groups
9
+
10
+ monomer-lib.json: pseudo-helm monomer library (R-groups are dummy)
11
+
12
+ pattern-app-data.json: color maps for Pattern app
@@ -0,0 +1,34 @@
1
+ [
2
+ {
3
+ "type": "link",
4
+ "code": "1",
5
+ "monomericSubstitution": {
6
+ "firstMonomer": "C",
7
+ "secondMonomer": "C",
8
+ "firstLinkingGroup":"3",
9
+ "secondLinkingGroup":"3",
10
+ "firstSubstitution": "C",
11
+ "secondSubstitution": "C"
12
+ }
13
+ },
14
+ {
15
+ "type": "link",
16
+ "code": "2",
17
+ "monomericSubstitution": {
18
+ "firstMonomer": "NH2",
19
+ "secondMonomer": "L",
20
+ "firstLinkingGroup":"2",
21
+ "secondLinkingGroup":"3",
22
+ "firstSubstitution": "NH2",
23
+ "secondSubstitution": "L"
24
+ }
25
+ },
26
+ {
27
+ "type": "fragmentDuplication",
28
+ "code": "#3"
29
+ },
30
+ {
31
+ "type": "differentFragments",
32
+ "code": "$4"
33
+ }
34
+ ]
@@ -0,0 +1,6 @@
1
+ AxolabsSequences
2
+ (GalNAc)AfCfpGfsUfacgu
3
+ (GalNAc)UfCfpGfsUfacgu
4
+ (GalNAc)CfCfpGfsUfacgu
5
+ (GalNAc)AfCfsUfacgu
6
+ (GalNAc)AfCfGfsUfacgu
@@ -0,0 +1,2 @@
1
+ Put here .csv files with columns `<format_name>` and `Helm` to extend tests
2
+ with sequences containing your custom monomers and substitution codes.
@@ -0,0 +1,2 @@
1
+ Axolabs,Helm
2
+ AfCf,RNA1{[fR](A)p.[fR](C)}$$$$
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/sequence-translator",
3
3
  "friendlyName": "Sequence Translator",
4
- "version": "1.3.0",
4
+ "version": "1.3.2",
5
5
  "author": {
6
6
  "name": "Alexey Choposky",
7
7
  "email": "achopovsky@datagrok.ai"
@@ -12,11 +12,20 @@
12
12
  "url": "https://github.com/datagrok-ai/public.git",
13
13
  "directory": "packages/SequenceTranslator"
14
14
  },
15
+ "properties": [
16
+ {
17
+ "name": "MonomersPath",
18
+ "description": "Path to additional monomer libraries and dictionaries of substituting HELM substructures into sequences",
19
+ "propertyType": "string",
20
+ "defaultValue": "System:AppData/SequenceTranslator/monomers",
21
+ "nullable": false
22
+ }
23
+ ],
15
24
  "dependencies": {
16
25
  "@datagrok-libraries/bio": "^5.41.9",
17
- "@datagrok-libraries/chem-meta": "^1.2.3",
26
+ "@datagrok-libraries/chem-meta": "^1.2.5",
18
27
  "@datagrok-libraries/tutorials": "^1.3.12",
19
- "@datagrok-libraries/utils": "^4.1.45",
28
+ "@datagrok-libraries/utils": "^4.2.6",
20
29
  "@types/react": "^18.0.15",
21
30
  "cash-dom": "^8.1.0",
22
31
  "datagrok-api": "^1.18.6",
@@ -25,12 +34,12 @@
25
34
  "openchemlib": "6.0.1",
26
35
  "save-svg-as-png": "^1.4.17",
27
36
  "ts-loader": "^9.3.1",
28
- "typescript": "^5.4.2",
29
- "typeahead-standalone": "4.14.1"
37
+ "typeahead-standalone": "4.14.1",
38
+ "typescript": "^5.4.2"
30
39
  },
31
40
  "devDependencies": {
32
- "@datagrok/bio": "^2.12.0",
33
- "@datagrok/chem": "1.9.0",
41
+ "@datagrok/bio": "^2.12.23",
42
+ "@datagrok/chem": "1.9.2",
34
43
  "@types/jquery": "^3.5.14",
35
44
  "@types/js-yaml": "^4.0.5",
36
45
  "@types/lodash": "^4.14.202",
@@ -40,6 +49,7 @@
40
49
  "@typescript-eslint/eslint-plugin": "^7.2.0",
41
50
  "@typescript-eslint/parser": "^7.2.0",
42
51
  "css-loader": "^6.7.3",
52
+ "datagrok-tools": "latest",
43
53
  "eslint": "^8.57.0",
44
54
  "eslint-config-google": "latest",
45
55
  "style-loader": "^3.3.1",
@@ -53,14 +63,14 @@
53
63
  "link-api": "npm link datagrok-api",
54
64
  "link-bio": "npm link @datagrok-libraries/bio",
55
65
  "link-all": "npm link @datagrok-libraries/chem-meta datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio @datagrok-libraries/tutorials",
56
- "debug-sequencetranslator": "grok publish",
57
- "release-sequencetranslator": "grok publish localhost --release",
66
+ "debug-sequencetranslator": "webpack && grok publish",
67
+ "release-sequencetranslator": "webpack && grok publish --release",
58
68
  "build-sequencetranslator": "webpack",
59
69
  "build": "webpack",
60
- "debug-sequencetranslator-public": "grok publish public",
61
- "release-sequencetranslator-public": "grok publish public --release",
62
- "debug-sequencetranslator-local": "grok publish local",
63
- "release-sequencetranslator-local": "grok publish local --release",
70
+ "debug-sequencetranslator-public": "webpack && grok publish public",
71
+ "release-sequencetranslator-public": "webpack && grok publish public --release",
72
+ "debug-sequencetranslator-local": "webpack && grok publish local",
73
+ "release-sequencetranslator-local": "webpack && grok publish local --release",
64
74
  "lint": "eslint \"./src/**/*.ts\"",
65
75
  "lint-fix": "eslint \"./src/**/*.ts\" --fix",
66
76
  "test": "grok test",
@@ -1,7 +1,6 @@
1
- export const LIB_PATH = 'System:AppData/SequenceTranslator';
1
+ export const FALLBACK_LIB_PATH = 'System:AppData/SequenceTranslator/monomers-sample';
2
2
  export const DEFAULT_LIB_FILENAME = 'monomer-lib.json';
3
3
 
4
- export const APP_PATH = 'System:AppData/SequenceTranslator';
5
4
  export const PATTERN_APP_DATA_FILENAME = 'pattern-app-data.json';
6
5
  export const CODES_TO_HELM_DICT_FILENAME = 'formats-to-helm.json';
7
6
  export const CODES_TO_SYMBOLS_FILENAME = 'codes-to-symbols.json';
@@ -1,48 +1,39 @@
1
1
  /* Do not change these import lines to match external modules in webpack configuration */
2
+ import * as grok from 'datagrok-api/grok';
3
+ import * as ui from 'datagrok-api/ui';
2
4
  import * as DG from 'datagrok-api/dg';
3
5
 
4
6
  import {
5
- APP_PATH, PATTERN_APP_DATA_FILENAME, CODES_TO_HELM_DICT_FILENAME,
7
+ PATTERN_APP_DATA_FILENAME, CODES_TO_HELM_DICT_FILENAME,
6
8
  CODES_TO_SYMBOLS_FILENAME, MONOMERS_WITH_PHOSPHATE_FILENAME
7
9
  } from './const';
8
10
  import {PatternAppData, CodeToSymbol, FormatToHELMDict} from './types';
9
11
 
10
- const fileSource = new DG.FileSource(APP_PATH);
11
-
12
- export let PATTERN_APP_DATA: PatternAppData;
13
- export let CODES_TO_HELM_DICT: FormatToHELMDict;
14
- export let CODES_TO_SYMBOLS_DICT: CodeToSymbol;
15
- export let MONOMERS_WITH_PHOSPHATE: {[key: string]: string[]};
16
-
17
- export async function loadJsonData(): Promise<void> {
18
- if (isAllJsonDataLoaded())
19
- return;
20
-
21
- const jsonFileNames = [
22
- PATTERN_APP_DATA_FILENAME, CODES_TO_HELM_DICT_FILENAME, CODES_TO_SYMBOLS_FILENAME, MONOMERS_WITH_PHOSPHATE_FILENAME
23
- ];
12
+ export class JsonData {
13
+ constructor(
14
+ public readonly patternAppData: PatternAppData,
15
+ public readonly codesToHelmDict: FormatToHELMDict,
16
+ public readonly codesToSymbolsDict: CodeToSymbol,
17
+ public readonly monomersWithPhosphate: { [key: string]: string[] }
18
+ ) {};
19
+ }
24
20
 
25
- [
26
- PATTERN_APP_DATA,
27
- CODES_TO_HELM_DICT,
28
- CODES_TO_SYMBOLS_DICT,
29
- MONOMERS_WITH_PHOSPHATE
30
- ] = await Promise.all(
31
- jsonFileNames.map((fileName) => loadAndParseJson(fileName))
21
+ export async function loadJsonData(monomersPath: string): Promise<JsonData> {
22
+ const data = await Promise.all(
23
+ [
24
+ PATTERN_APP_DATA_FILENAME, CODES_TO_HELM_DICT_FILENAME,
25
+ CODES_TO_SYMBOLS_FILENAME, MONOMERS_WITH_PHOSPHATE_FILENAME
26
+ ].map((fileName) => loadAndParseJson(monomersPath, fileName))
32
27
  );
28
+ return new JsonData(data[0], data[1], data[2], data[3]);
33
29
  }
34
30
 
35
- async function loadAndParseJson(filePath: string): Promise<any> {
31
+ async function loadAndParseJson(path: string, fileName: string): Promise<any> {
32
+ const filePath = path.endsWith('/') ? `${path}${fileName}` : `${path}/${fileName}`;
36
33
  try {
37
- const content = await fileSource.readAsText(filePath);
34
+ const content = await grok.dapi.files.readAsText(filePath);
38
35
  return JSON.parse(content);
39
36
  } catch (err) {
40
- console.error(`Error loading json from ${filePath}:`, err);
37
+ console.error(`Error loading json from '${filePath}':`, err);
41
38
  }
42
39
  }
43
-
44
- function isAllJsonDataLoaded(): boolean {
45
- const data = [PATTERN_APP_DATA, CODES_TO_HELM_DICT, CODES_TO_SYMBOLS_DICT, MONOMERS_WITH_PHOSPHATE];
46
-
47
- return data.every((item) => item !== undefined);
48
- }
@@ -7,23 +7,23 @@ import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
7
7
  import {HELM_REQUIRED_FIELD as REQ, HELM_OPTIONAL_FIELDS as OPT} from '@datagrok-libraries/bio/src/utils/const';
8
8
 
9
9
  import {META_FIELDS as MET} from './const';
10
- import {CODES_TO_SYMBOLS_DICT} from '../data-loader/json-loader';
10
+ import {JsonData} from '../data-loader/json-loader';
11
11
 
12
12
  export class MonomerLibWrapper {
13
- private constructor() {
14
- const lib = _package.monomerLib;
15
- if (lib === null)
13
+ public constructor(
14
+ private readonly lib: IMonomerLib,
15
+ private readonly jsonData: JsonData
16
+ ) {
17
+ if (this.lib === null)
16
18
  throw new Error('SequenceTranslator: monomer library is null');
17
- this.lib = lib!;
18
19
  this.allMonomers = this.getAllMonomers();
19
20
  }
20
21
 
21
- private lib: IMonomerLib;
22
22
  private static instance?: MonomerLibWrapper;
23
23
  private allMonomers: Monomer[];
24
24
 
25
- private formatMonomerForViewer(sourceObj: Monomer): {[key: string]: string} {
26
- const formattedObject: {[key: string]: string} = {};
25
+ private formatMonomerForViewer(sourceObj: Monomer): { [key: string]: string } {
26
+ const formattedObject: { [key: string]: string } = {};
27
27
  formattedObject[REQ.NAME] = sourceObj[REQ.SYMBOL];
28
28
  formattedObject[REQ.SYMBOL] = sourceObj[REQ.SYMBOL];
29
29
  formattedObject[REQ.MOLFILE] = sourceObj[REQ.MOLFILE];
@@ -31,7 +31,7 @@ export class MonomerLibWrapper {
31
31
  formats.forEach((format) => {
32
32
  if (format === DEFAULT_FORMATS.HELM)
33
33
  return;
34
- const map = CODES_TO_SYMBOLS_DICT[format];
34
+ const map = this.jsonData.codesToSymbolsDict[format];
35
35
  const codes = Object.keys(map).filter((code) => map[code] === sourceObj.symbol);
36
36
  formattedObject[format] = codes.join(', ');
37
37
  });
@@ -59,12 +59,6 @@ export class MonomerLibWrapper {
59
59
  return monomer!;
60
60
  }
61
61
 
62
- static getInstance(): MonomerLibWrapper {
63
- if (MonomerLibWrapper.instance === undefined)
64
- MonomerLibWrapper.instance = new MonomerLibWrapper();
65
- return MonomerLibWrapper.instance!;
66
- }
67
-
68
62
  getMolfileBySymbol(monomerSymbol: string): string {
69
63
  const monomer = this.getMonomer(monomerSymbol);
70
64
  return monomer.molfile;
@@ -85,15 +79,15 @@ export class MonomerLibWrapper {
85
79
  }
86
80
 
87
81
  getCodeToSymbolMap(format: string): Map<string, string> {
88
- return new Map<string, string>(Object.entries(CODES_TO_SYMBOLS_DICT[format]));
82
+ return new Map<string, string>(Object.entries(this.jsonData.codesToSymbolsDict[format]));
89
83
  }
90
84
 
91
85
  getCodesByFormat(format: string): string[] {
92
- return Object.keys(CODES_TO_SYMBOLS_DICT[format]);
86
+ return Object.keys(this.jsonData.codesToSymbolsDict[format]);
93
87
  }
94
88
 
95
89
  getAllFormats(): string[] {
96
- return Object.keys(CODES_TO_SYMBOLS_DICT);
90
+ return Object.keys(this.jsonData.codesToSymbolsDict);
97
91
  }
98
92
 
99
93
  getTableForViewer(): DG.DataFrame {
@@ -104,7 +98,7 @@ export class MonomerLibWrapper {
104
98
 
105
99
  getCodesToWeightsMap(): Map<string, number> {
106
100
  const codesToWeightsMap = new Map<string, number>();
107
- Object.entries(CODES_TO_SYMBOLS_DICT).forEach(([_, dict]) => {
101
+ Object.entries(this.jsonData.codesToSymbolsDict).forEach(([_, dict]) => {
108
102
  Object.entries(dict).forEach(([code, monomerSymbol]) => {
109
103
  const monomer = this.getMonomer(monomerSymbol);
110
104
  const weight = monomer[OPT.META]?.[MET.MOLWEIGHT];
@@ -1,30 +1,97 @@
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';
2
4
 
3
5
  import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
4
- import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
6
+ import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
5
7
 
6
8
  import {APP_NAME} from '../view/const';
7
- import {DEFAULT_LIB_FILENAME, LIB_PATH} from './data-loader/const';
9
+ import {DEFAULT_LIB_FILENAME, FALLBACK_LIB_PATH} from './data-loader/const';
8
10
  import {tryCatch} from './helpers';
11
+ import {ITranslationHelper} from '../../../types';
12
+ import {SequenceValidator} from './parsing-validation/sequence-validator';
13
+ import {JsonData, loadJsonData} from './data-loader/json-loader';
14
+ import {MonomerLibWrapper} from './monomer-lib/lib-wrapper';
15
+ import {_package} from '../../../package';
16
+ import {FormatConverter} from '../../translator/model/format-converter';
17
+ import {FormatDetector} from './parsing-validation/format-detector';
18
+ import {highlightInvalidSubsequence} from '../view/components/colored-input/input-painters';
9
19
 
10
- export class OligoToolkitPackage extends DG.Package {
20
+ export class OligoToolkitPackage extends DG.Package implements ITranslationHelper {
11
21
  private _monomerLib?: IMonomerLib;
12
-
13
22
  get monomerLib(): IMonomerLib {
14
23
  if (!this._monomerLib)
15
24
  throw new Error('Monomer lib not loaded');
16
25
  return this._monomerLib!;
17
26
  }
18
27
 
19
- async initMonomerLib(): Promise<void> {
20
- if (this._monomerLib !== undefined)
21
- return;
28
+ private _jsonData: JsonData;
29
+ get jsonData(): JsonData {
30
+ if (!this._jsonData)
31
+ throw new Error('Json data not loaded');
32
+ return this._jsonData;
33
+ }
34
+
35
+ private _monomerLibWrapper: MonomerLibWrapper;
36
+ get monomerLibWrapper(): MonomerLibWrapper {
37
+ if (!this._monomerLibWrapper)
38
+ throw new Error('Monomer lib wrapper not loaded');
39
+ return this._monomerLibWrapper;
40
+ }
41
+
42
+ constructor() {
43
+ super();
44
+ }
45
+
46
+ private initPromise?: Promise<void>;
47
+
48
+ async initLibData(): Promise<void> {
49
+ if (!this.initPromise) {
50
+ this.initPromise = (async () => {
51
+ const packageSettings = await this.getSettings();
52
+ let monomersPath: string = packageSettings['MonomersPath'];
53
+ if (!monomersPath || !(await grok.dapi.files.exists(monomersPath))) {
54
+ _package.logger.warning(`Monomers path '${monomersPath}' not found. ` +
55
+ `Fallback to monomers sample path '${FALLBACK_LIB_PATH}'.`);
56
+ monomersPath = FALLBACK_LIB_PATH;
57
+ }
58
+ [this._jsonData, this._monomerLib] = await Promise.all([
59
+ loadJsonData(monomersPath),
60
+ loadMonomerLib(monomersPath)
61
+ ]);
62
+ this._monomerLibWrapper = new MonomerLibWrapper(this.monomerLib, this.jsonData);
63
+ })();
64
+ }
65
+ return this.initPromise;
66
+ }
67
+
68
+ async getTranslationHelper(): Promise<ITranslationHelper> {
69
+ return (await grok.functions.call(`${this.name}:getTranslationHelper`)) as ITranslationHelper;
70
+ }
22
71
 
23
- const pi: DG.TaskBarProgressIndicator = DG.TaskBarProgressIndicator.create(
24
- `Initializing ${APP_NAME.COMBINED} monomer library ...`);
25
- await tryCatch(async () => {
26
- const libHelper: IMonomerLibHelper = await getMonomerLibHelper();
27
- this._monomerLib = await libHelper.readLibrary(LIB_PATH, DEFAULT_LIB_FILENAME);
28
- }, () => pi.close());
72
+ createSequenceValidator(sequence: string): SequenceValidator {
73
+ return new SequenceValidator(sequence, this);
29
74
  }
75
+
76
+ createFormatConverter(sequence: string, sourceFormat: string): FormatConverter {
77
+ return new FormatConverter(sequence, sourceFormat, this);
78
+ }
79
+
80
+ createFormatDetector(sequence: string): FormatDetector {
81
+ return new FormatDetector(sequence, this);
82
+ }
83
+
84
+ highlightInvalidSubsequence = (input: string): HTMLSpanElement[] => {
85
+ return highlightInvalidSubsequence(input, this);
86
+ };
87
+ }
88
+
89
+ async function loadMonomerLib(monomersPath: string): Promise<IMonomerLib> {
90
+ const pi: DG.TaskBarProgressIndicator = DG.TaskBarProgressIndicator.create(
91
+ `Initializing ${APP_NAME.COMBINED} monomer library ...`);
92
+ try {
93
+ const libHelper = await getMonomerLibHelper();
94
+ const res = await libHelper.readLibrary(monomersPath, DEFAULT_LIB_FILENAME);
95
+ return res;
96
+ } finally { pi.close(); }
30
97
  }
@@ -6,13 +6,16 @@ import * as DG from 'datagrok-api/dg';
6
6
  import {sortByReverseLength} from '../helpers';
7
7
  import {DEFAULT_FORMATS} from '../const';
8
8
  import {MonomerLibWrapper} from '../monomer-lib/lib-wrapper';
9
- import {CODES_TO_HELM_DICT} from '../data-loader/json-loader';
10
- import {SequenceValidator} from './sequence-validator';
9
+
10
+ import {ITranslationHelper} from '../../../../types';
11
11
 
12
12
  export class FormatDetector {
13
- constructor(private sequence: string) {
14
- this.libWrapper = MonomerLibWrapper.getInstance();
15
- this.formats = Object.keys(CODES_TO_HELM_DICT);
13
+ constructor(
14
+ private sequence: string,
15
+ private readonly th: ITranslationHelper,
16
+ ) {
17
+ this.libWrapper = this.th.monomerLibWrapper;
18
+ this.formats = Object.keys(this.th.jsonData.codesToHelmDict);
16
19
  };
17
20
 
18
21
  private libWrapper: MonomerLibWrapper;
@@ -26,7 +29,7 @@ export class FormatDetector {
26
29
  if (possibleFormats.length === 0)
27
30
  return null;
28
31
 
29
- const validator = new SequenceValidator(this.sequence);
32
+ const validator = this.th.createSequenceValidator(this.sequence);
30
33
  const outputIndices = Array(possibleFormats.length).fill(0);
31
34
  for (let i = 0; i < possibleFormats.length; ++i) {
32
35
  const format = possibleFormats[i];
@@ -3,15 +3,17 @@ import * as grok from 'datagrok-api/grok';
3
3
  import * as ui from 'datagrok-api/ui';
4
4
  import * as DG from 'datagrok-api/dg';
5
5
 
6
- import {CODES_TO_HELM_DICT} from '../data-loader/json-loader';
7
6
  import {CodesInfo} from '../data-loader/types';
8
7
  import {DEFAULT_FORMATS} from '../const';
8
+ import {ITranslationHelper} from '../../../../types';
9
9
  import {GROUP_TYPE, PHOSPHATE_SYMBOL} from '../../../translator/model/const';
10
10
 
11
11
  const inverseLengthComparator = (a: string, b: string) => b.length - a.length;
12
12
 
13
13
  export class FormatHandler {
14
- constructor() {
14
+ constructor(
15
+ private readonly th: ITranslationHelper,
16
+ ) {
15
17
  this.formats = this.getFormats();
16
18
  }
17
19
 
@@ -31,19 +33,19 @@ export class FormatHandler {
31
33
  return this.getFormatCodes(format);
32
34
  }
33
35
 
34
- getHelmToFormatDict(format: string): {[key: string]: string} {
36
+ getHelmToFormatDict(format: string): { [key: string]: string } {
35
37
  this.validateFormat(format);
36
38
 
37
- const codesInfoObject = CODES_TO_HELM_DICT[format] as CodesInfo;
39
+ const codesInfoObject = this.th.jsonData.codesToHelmDict[format] as CodesInfo;
38
40
  const dict = getHelmToCodeDict(codesInfoObject);
39
41
  return dict;
40
42
  }
41
43
 
42
- getFormatToHelmDict(format: string): {[key: string]: string} {
44
+ getFormatToHelmDict(format: string): { [key: string]: string } {
43
45
  this.validateFormat(format);
44
46
 
45
- const codesInfoObject = CODES_TO_HELM_DICT[format] as CodesInfo;
46
- const dict = Object.assign({}, ...Object.values(codesInfoObject)) as {[code: string]: string};
47
+ const codesInfoObject = this.th.jsonData.codesToHelmDict[format] as CodesInfo;
48
+ const dict = Object.assign({}, ...Object.values(codesInfoObject)) as { [code: string]: string };
47
49
  return dict;
48
50
  }
49
51
 
@@ -75,7 +77,7 @@ export class FormatHandler {
75
77
  getPhosphateHelmCodesRegExp(format: string): RegExp {
76
78
  this.validateFormat(format);
77
79
 
78
- const codesInfoObject = CODES_TO_HELM_DICT[format] as CodesInfo;
80
+ const codesInfoObject = this.th.jsonData.codesToHelmDict[format] as CodesInfo;
79
81
  const phosphateHELMCodes = Array.from(
80
82
  new Set(Object.values(codesInfoObject[GROUP_TYPE.LINKAGE]))
81
83
  ).sort(inverseLengthComparator);
@@ -89,7 +91,7 @@ export class FormatHandler {
89
91
  }
90
92
 
91
93
  private getFormats(): string[] {
92
- return Object.keys(CODES_TO_HELM_DICT);
94
+ return Object.keys(this.th.jsonData.codesToHelmDict);
93
95
  }
94
96
 
95
97
  private validateFormat(format: string) {
@@ -109,7 +111,8 @@ export class FormatHandler {
109
111
 
110
112
  private getNonHelmFormatRegExp(format: string): RegExp {
111
113
  const formatCodes = this.getCodesByFormat(format);
112
- const formatRegExp = new RegExp(getRegExpPattern(formatCodes) + '|\\([^()]*\\)|.', 'g'); // the added group before '|.' is to avoid mismatch inside parenths
114
+ // the added group before '|.' is to avoid mismatch inside parenthesis
115
+ const formatRegExp = new RegExp(getRegExpPattern(formatCodes) + '|\\([^()]*\\)|.', 'g');
113
116
  return formatRegExp;
114
117
  }
115
118
  }
@@ -128,8 +131,8 @@ export function getRegExpPattern(arr: string[]): string {
128
131
  }
129
132
 
130
133
  function getHelmToCodeDict(infoObj: CodesInfo) {
131
- const result: {[key: string]: string | string[]} = {};
132
- Object.values(infoObj).forEach((obj: {[code: string]: string}) => {
134
+ const result: { [key: string]: string | string[] } = {};
135
+ Object.values(infoObj).forEach((obj: { [code: string]: string }) => {
133
136
  Object.entries(obj).forEach(([code, helm]) => {
134
137
  const key = helm.replace(/\)p/g, ')').replace(/\]p/g, ']');
135
138
  if (result[key] === undefined)
@@ -142,5 +145,5 @@ function getHelmToCodeDict(infoObj: CodesInfo) {
142
145
  const sorted = (value as string[]).sort(inverseLengthComparator);
143
146
  result[key] = sorted[0] as string;
144
147
  });
145
- return result as {[key: string]: string};
148
+ return result as { [key: string]: string };
146
149
  }
@@ -2,13 +2,18 @@ import {NUCLEOTIDES} from '../const';
2
2
  import {MonomerLibWrapper} from '../monomer-lib/lib-wrapper';
3
3
  import {sortByReverseLength} from '../helpers';
4
4
  import {DEFAULT_FORMATS} from '../const';
5
+ import {ITranslationHelper} from '../../../../types';
5
6
 
6
7
  export class SequenceValidator {
7
- constructor(private sequence: string) {
8
- this.libWrapper = MonomerLibWrapper.getInstance();
9
- };
10
8
  private libWrapper: MonomerLibWrapper;
11
9
 
10
+ constructor(
11
+ private readonly sequence: string,
12
+ private readonly th: ITranslationHelper,
13
+ ) {
14
+ this.libWrapper = this.th.monomerLibWrapper;
15
+ };
16
+
12
17
  getInvalidCodeIndex(format: string): number {
13
18
  if (format === DEFAULT_FORMATS.HELM)
14
19
  return this.sequence.length;
@@ -9,32 +9,34 @@ import {OligoTranslatorUI} from '../../translator/view/ui';
9
9
  import {AppUIBase} from './app-ui-base';
10
10
  import {IsolatedAppUIBase} from './isolated-app-ui';
11
11
  import {APP_NAME, TAB_NAME} from './const';
12
+ import {ITranslationHelper} from '../../../types';
12
13
 
13
- type ViewFactories = {[name: string]: () => DG.View};
14
+ type ViewFactories = { [name: string]: () => DG.View };
14
15
 
15
16
  export class CombinedAppUI extends AppUIBase {
16
- constructor(externalViewFactories: ViewFactories) {
17
+ constructor(
18
+ private readonly externalViewFactories: ViewFactories,
19
+ private readonly th: ITranslationHelper
20
+ ) {
17
21
  super(APP_NAME.COMBINED);
18
- this.externalViewFactories = externalViewFactories;
19
- const factories = this.getViewFactories();
22
+
23
+ const factories = this.getViewFactories(this.th);
20
24
  this.multiView = new DG.MultiView({viewFactories: factories});
21
25
  }
22
26
 
23
27
  private multiView: DG.MultiView;
24
- private externalViewFactories?: ViewFactories;
25
-
26
28
 
27
- private getViewFactories(): ViewFactories {
28
- function viewFactory(UiConstructor: new (view: DG.View) => IsolatedAppUIBase): () => DG.View {
29
+ private getViewFactories(th: ITranslationHelper): ViewFactories {
30
+ function viewFactory(UiConstructor: new (th: ITranslationHelper) => IsolatedAppUIBase): () => DG.View {
29
31
  const view = DG.View.create();
30
- const translateUI = new UiConstructor(view);
32
+ const translateUI = new UiConstructor(th);
31
33
  translateUI.initView().catch(
32
34
  (e) => console.error(`Failed to initialize ${UiConstructor.name}: ${e}`)
33
35
  );
34
36
  return () => translateUI.getView();
35
37
  }
36
38
 
37
- let result: {[key: string]: () => DG.View } = {
39
+ let result: { [key: string]: () => DG.View } = {
38
40
  [TAB_NAME.TRANSLATOR]: viewFactory(OligoTranslatorUI),
39
41
  [TAB_NAME.PATTERN]: viewFactory(OligoPatternUI),
40
42
  [TAB_NAME.STRUCTURE]: viewFactory(OligoStructureUI),
@@ -7,6 +7,7 @@ import {SequenceValidator} from '../../../model/parsing-validation/sequence-vali
7
7
  import {FormatDetector} from '../../../model/parsing-validation/format-detector';
8
8
 
9
9
  import $ from 'cash-dom';
10
+ import {ITranslationHelper} from '../../../../../types';
10
11
 
11
12
  /** Set different colors for letters, can be upgraded to color various monomers */
12
13
  export function demoPainter(input: string): HTMLSpanElement[] {
@@ -24,12 +25,12 @@ export function demoPainter(input: string): HTMLSpanElement[] {
24
25
  }
25
26
 
26
27
  // todo: port to another place
27
- export function highlightInvalidSubsequence(input: string): HTMLSpanElement[] {
28
+ export function highlightInvalidSubsequence(input: string, th: ITranslationHelper): HTMLSpanElement[] {
28
29
  // validate sequence
29
30
  let cutoff = 0;
30
- const format = (new FormatDetector(input)).getFormat();
31
+ const format = th.createFormatDetector(input).getFormat();
31
32
  if (format !== null)
32
- cutoff = (new SequenceValidator(input)).getInvalidCodeIndex(format!);
33
+ cutoff = (new SequenceValidator(input, th)).getInvalidCodeIndex(format!);
33
34
  const isValid = cutoff < 0 || input === '';
34
35
  const greyTextSpan = ui.span([]);
35
36
  $(greyTextSpan).css('-webkit-text-fill-color', 'var(--grey-6)');
@@ -5,10 +5,11 @@ import * as DG from 'datagrok-api/dg';
5
5
 
6
6
  import {drawZoomedInMolecule} from './components/draw-molecule';
7
7
  import {MonomerLibWrapper} from '../model/monomer-lib/lib-wrapper';
8
+ import {_package} from '../../../package';
8
9
 
9
10
  export class MonomerLibViewer {
10
11
  static async view(): Promise<void> {
11
- const table = MonomerLibWrapper.getInstance().getTableForViewer();
12
+ const table = _package.monomerLibWrapper.getTableForViewer();
12
13
  table.name = 'Monomer Library';
13
14
  const view = grok.shell.addTableView(table);
14
15
  view.grid.props.allowEdit = false;