@datagrok/sequence-translator 1.2.7 → 1.3.0

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 (107) hide show
  1. package/.eslintrc.json +5 -5
  2. package/CHANGELOG.md +14 -0
  3. package/dist/package-test.js +2 -1
  4. package/dist/package-test.js.LICENSE.txt +8 -0
  5. package/dist/package-test.js.map +1 -1
  6. package/dist/package.js +2 -1
  7. package/dist/package.js.LICENSE.txt +8 -0
  8. package/dist/package.js.map +1 -1
  9. package/files/pattern-app-data.json +80 -0
  10. package/package.json +22 -14
  11. package/src/{model → apps/common/model}/const.ts +1 -1
  12. package/src/{model/data-loading-utils → apps/common/model/data-loader}/const.ts +7 -2
  13. package/src/apps/common/model/data-loader/json-loader.ts +48 -0
  14. package/src/{model/data-loading-utils → apps/common/model/data-loader}/types.ts +13 -6
  15. package/src/{model → apps/common/model}/monomer-lib/lib-wrapper.ts +9 -12
  16. package/src/apps/common/model/oligo-toolkit-package.ts +30 -0
  17. package/src/{model → apps/common/model}/parsing-validation/format-detector.ts +5 -5
  18. package/src/{model → apps/common/model}/parsing-validation/format-handler.ts +18 -19
  19. package/src/{model → apps/common/model}/parsing-validation/sequence-validator.ts +1 -1
  20. package/src/apps/common/view/app-ui-base.ts +28 -0
  21. package/src/apps/common/view/combined-app-ui.ts +66 -0
  22. package/src/{view/utils → apps/common/view/components}/colored-input/colored-text-input.ts +1 -1
  23. package/src/{view/utils → apps/common/view/components}/draw-molecule.ts +1 -1
  24. package/src/{view/utils → apps/common/view/components}/molecule-img.ts +3 -3
  25. package/src/{view/const/ui.ts → apps/common/view/const.ts} +4 -4
  26. package/src/apps/common/view/isolated-app-ui.ts +43 -0
  27. package/src/{view/monomer-lib-viewer/viewer.ts → apps/common/view/monomer-lib-viewer.ts} +2 -2
  28. package/src/apps/common/view/utils.ts +29 -0
  29. package/src/apps/pattern/model/const.ts +121 -0
  30. package/src/apps/pattern/model/data-manager.ts +297 -0
  31. package/src/apps/pattern/model/event-bus.ts +487 -0
  32. package/src/apps/pattern/model/router.ts +46 -0
  33. package/src/apps/pattern/model/subscription-manager.ts +21 -0
  34. package/src/apps/pattern/model/translator.ts +94 -0
  35. package/src/apps/pattern/model/types.ts +52 -0
  36. package/src/apps/pattern/model/utils.ts +110 -0
  37. package/src/apps/pattern/view/components/bulk-convert/column-input.ts +79 -0
  38. package/src/apps/pattern/view/components/bulk-convert/table-controls.ts +38 -0
  39. package/src/apps/pattern/view/components/bulk-convert/table-input.ts +95 -0
  40. package/src/apps/pattern/view/components/edit-block-controls.ts +196 -0
  41. package/src/apps/pattern/view/components/left-section.ts +44 -0
  42. package/src/apps/pattern/view/components/load-block-controls.ts +200 -0
  43. package/src/apps/pattern/view/components/numeric-label-visibility-controls.ts +69 -0
  44. package/src/apps/pattern/view/components/right-section.ts +148 -0
  45. package/src/apps/pattern/view/components/strand-editor/dialog.ts +79 -0
  46. package/src/apps/pattern/view/components/strand-editor/header-controls.ts +105 -0
  47. package/src/apps/pattern/view/components/strand-editor/strand-controls.ts +159 -0
  48. package/src/apps/pattern/view/components/terminal-modification-editor.ts +127 -0
  49. package/src/apps/pattern/view/components/translation-examples-block.ts +139 -0
  50. package/src/{view/style/pattern-app.css → apps/pattern/view/style.css} +4 -0
  51. package/src/apps/pattern/view/svg-utils/const.ts +77 -0
  52. package/src/apps/pattern/view/svg-utils/legend-block.ts +92 -0
  53. package/src/apps/pattern/view/svg-utils/strands-block.ts +335 -0
  54. package/src/apps/pattern/view/svg-utils/svg-block-base.ts +37 -0
  55. package/src/apps/pattern/view/svg-utils/svg-display-manager.ts +44 -0
  56. package/src/apps/pattern/view/svg-utils/svg-element-factory.ts +94 -0
  57. package/src/apps/pattern/view/svg-utils/svg-renderer.ts +51 -0
  58. package/src/apps/pattern/view/svg-utils/text-dimensions-calculator.ts +29 -0
  59. package/src/apps/pattern/view/svg-utils/title-block.ts +53 -0
  60. package/src/apps/pattern/view/svg-utils/utils.ts +37 -0
  61. package/src/apps/pattern/view/types.ts +14 -0
  62. package/src/apps/pattern/view/ui.ts +61 -0
  63. package/src/{model/structure-app → apps/structure/model}/mol-transformations.ts +3 -3
  64. package/src/{model/structure-app → apps/structure/model}/monomer-code-parser.ts +9 -10
  65. package/src/{model/structure-app → apps/structure/model}/oligo-structure.ts +4 -4
  66. package/src/{model/structure-app → apps/structure/model}/sequence-to-molfile.ts +2 -2
  67. package/src/{view/apps/oligo-structure.ts → apps/structure/view/ui.ts} +31 -17
  68. package/src/{model/translator-app → apps/translator/model}/conversion-utils.ts +25 -7
  69. package/src/{model/translator-app → apps/translator/model}/format-converter.ts +7 -12
  70. package/src/{view/const/oligo-translator.ts → apps/translator/view/const.ts} +1 -1
  71. package/src/{view/apps/oligo-translator.ts → apps/translator/view/ui.ts} +88 -42
  72. package/src/demo/demo-st-ui.ts +12 -32
  73. package/src/package.ts +91 -55
  74. package/src/plugins/mermade.ts +9 -9
  75. package/src/polytool/const.ts +28 -0
  76. package/src/polytool/csv-to-json-monomer-lib-converter.ts +40 -0
  77. package/src/polytool/cyclized.ts +56 -0
  78. package/src/polytool/monomer-lib-handler.ts +115 -0
  79. package/src/polytool/pt-conversion.ts +307 -0
  80. package/src/polytool/pt-dialog.ts +115 -0
  81. package/src/polytool/pt-enumeration.ts +127 -0
  82. package/src/polytool/pt-rules.ts +73 -0
  83. package/src/polytool/utils.ts +27 -0
  84. package/src/tests/const.ts +5 -5
  85. package/src/tests/formats-support.ts +6 -6
  86. package/src/tests/formats-to-helm.ts +5 -5
  87. package/src/tests/helm-to-nucleotides.ts +5 -10
  88. package/tsconfig.json +3 -9
  89. package/webpack.config.js +3 -0
  90. package/files/axolabs-style.json +0 -97
  91. package/src/model/data-loading-utils/json-loader.ts +0 -38
  92. package/src/model/pattern-app/const.ts +0 -33
  93. package/src/model/pattern-app/draw-svg.ts +0 -193
  94. package/src/model/pattern-app/helpers.ts +0 -96
  95. package/src/model/pattern-app/oligo-pattern.ts +0 -111
  96. package/src/view/app-ui.ts +0 -193
  97. package/src/view/apps/oligo-pattern.ts +0 -759
  98. /package/src/{model → apps/common/model}/helpers.ts +0 -0
  99. /package/src/{model → apps/common/model}/monomer-lib/const.ts +0 -0
  100. /package/src/{view/utils → apps/common/view/components}/app-info-dialog.ts +0 -0
  101. /package/src/{view/utils → apps/common/view/components}/colored-input/input-painters.ts +0 -0
  102. /package/src/{view/style/colored-text-input.css → apps/common/view/components/colored-input/style.css} +0 -0
  103. /package/src/{view/utils → apps/common/view/components}/router.ts +0 -0
  104. /package/src/{model/structure-app → apps/structure/model}/const.ts +0 -0
  105. /package/src/{view/style/structure-app.css → apps/structure/view/style.css} +0 -0
  106. /package/src/{model/translator-app → apps/translator/model}/const.ts +0 -0
  107. /package/src/{view/style/translator-app.css → apps/translator/view/style.css} +0 -0
@@ -3,43 +3,22 @@ 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 {getJsonData} from '../model/data-loading-utils/json-loader';
6
+ import {loadJsonData} from '../apps/common/model/data-loader/json-loader';
7
7
  import {_package, oligoTranslatorApp, oligoPatternApp, oligoStructureApp} from '../package';
8
- import {tryCatch} from '../model/helpers';
8
+ import {tryCatch} from '../apps/common/model/helpers';
9
9
 
10
10
  export async function demoOligoTranslatorUI() {
11
- await tryCatch(async () => oligoTranslatorApp());
11
+ await tryCatch(async () => {
12
+ const view = await oligoTranslatorApp();
13
+ grok.shell.addView(view);
14
+ });
12
15
  }
13
16
 
14
17
  export async function demoOligoPatternUI() {
15
18
  await tryCatch(async () => {
16
- async function emulateUserInput(value: string, idx: number, idxUpdate: (idx: number) => number): Promise<void> {
17
- await delay(3000);
18
-
19
- // warning: this redefinition is necessary because
20
- // the ids of the elements can dynamically change
21
- const choiceInputs: NodeListOf<HTMLSelectElement> = document.querySelectorAll('.st-pattern-choice-input > select');
22
- len = choiceInputs.length;
23
- const selectElement = choiceInputs[idxUpdate(idx)];
24
- selectElement.value = value;
25
- const event = new Event('input');
26
- selectElement.dispatchEvent(event);
27
- }
28
-
29
- await oligoPatternApp();
30
-
31
- let len: number;
32
-
33
- const ssNewValues = ['DNA', 'invAb', 'Z-New'];
34
- ssNewValues.forEach(async (value, idx) => {
35
- emulateUserInput(value, idx, (i) => 2 * i);
36
- });
37
-
38
- const asNewValues = ['2\'-O-Methyl', '2\'-Fluoro', '2\'-O-MOE'];
39
- asNewValues.forEach(async (value, idx) => {
40
- emulateUserInput(value, idx, (i) => (len - 2 - 2 * i));
41
- });
42
- })
19
+ const view = await oligoPatternApp();
20
+ grok.shell.addView(view);
21
+ });
43
22
  }
44
23
 
45
24
  export async function demoOligoStructureUI() {
@@ -52,10 +31,11 @@ export async function demoOligoStructureUI() {
52
31
  const event = new Event('input');
53
32
  textarea.dispatchEvent(event);
54
33
  }
55
- await oligoStructureApp();
34
+ const view = await oligoStructureApp();
35
+ grok.shell.addView(view);
56
36
  const inputSequences = ['Afcgacsu', 'Afcgacsu', 'Afcgacsu'];
57
37
  inputSequences.forEach(async (sequence, idx) => {
58
38
  await setInputValue(idx, sequence);
59
- })
39
+ });
60
40
  });
61
41
  }
package/src/package.ts CHANGED
@@ -1,94 +1,76 @@
1
+ import DG from 'datagrok-api/dg';
1
2
  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 {AppUIFactory, CombinedAppUI} from './view/app-ui';
6
- import {tryCatch} from './model/helpers';
7
- import {LIB_PATH, DEFAULT_LIB_FILENAME} from './model/data-loading-utils/const';
8
- import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
9
- import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
10
- import {getJsonData} from './model/data-loading-utils/json-loader';
11
- import {SequenceToMolfileConverter} from './model/structure-app/sequence-to-molfile';
12
- import {linkStrandsV3000} from './model/structure-app/mol-transformations';
13
- import {MonomerLibWrapper} from './model/monomer-lib/lib-wrapper';
14
- import {FormatDetector} from './model/parsing-validation/format-detector';
15
- import {SequenceValidator} from './model/parsing-validation/sequence-validator';
16
- import {demoOligoTranslatorUI, demoOligoPatternUI, demoOligoStructureUI} from './demo/demo-st-ui';
17
- import {FormatConverter} from './model/translator-app/format-converter';
18
- import {APP} from './view/const/ui';
19
- import {getExternalAppViewFactories} from './plugins/mermade';
20
-
21
- class StPackage extends DG.Package {
22
- private _monomerLib?: IMonomerLib;
23
-
24
- get monomerLib(): IMonomerLib {
25
- if (!this._monomerLib)
26
- throw new Error ('Monomer lib not loaded')
27
- return this._monomerLib!;
28
- }
29
-
30
- public async initMonomerLib(): Promise<void> {
31
- if (this._monomerLib !== undefined)
32
- return;
33
3
 
34
- const pi: DG.TaskBarProgressIndicator = DG.TaskBarProgressIndicator.create(
35
- `Initializing ${APP.COMBINED} monomer library ...`);
36
- await tryCatch(async () => {
37
- const libHelper: IMonomerLibHelper = await getMonomerLibHelper();
38
- this._monomerLib = await libHelper.readLibrary(LIB_PATH, DEFAULT_LIB_FILENAME);
39
- }, () => pi.close());
40
- }
41
- }
4
+ import {loadJsonData} from './apps/common/model/data-loader/json-loader';
5
+ import {MonomerLibWrapper} from './apps/common/model/monomer-lib/lib-wrapper';
6
+ import {OligoToolkitPackage} from './apps/common/model/oligo-toolkit-package';
7
+ import {FormatDetector} from './apps/common/model/parsing-validation/format-detector';
8
+ import {SequenceValidator} from './apps/common/model/parsing-validation/sequence-validator';
9
+ import {APP_NAME} from './apps/common/view/const';
10
+ import {getSpecifiedAppUI} from './apps/common/view/utils';
11
+ import {CombinedAppUI} from './apps/common/view/combined-app-ui';
12
+ import {linkStrandsV3000} from './apps/structure/model/mol-transformations';
13
+ import {SequenceToMolfileConverter} from './apps/structure/model/sequence-to-molfile';
14
+ import {FormatConverter} from './apps/translator/model/format-converter';
15
+ import {demoOligoPatternUI, demoOligoStructureUI, demoOligoTranslatorUI} from './demo/demo-st-ui';
16
+ import {getExternalAppViewFactories} from './plugins/mermade';
42
17
 
43
- export const _package: StPackage = new StPackage();
18
+ //polytool specific
19
+ import {getPolyToolConversionDialog, getPolyToolEnumerationDialog} from './polytool/pt-dialog';
20
+ import {_setPeptideColumn} from './polytool/utils';
21
+ import {PolyToolCsvLibHandler} from './polytool/csv-to-json-monomer-lib-converter';
44
22
 
45
- async function buildLayout(appName: string): Promise<void> {
46
- await initSequenceTranslatorLibData();
47
- const appUI = AppUIFactory.getUI(appName);
48
- await appUI.createAppLayout();
49
- }
50
23
 
24
+ export const _package: OligoToolkitPackage = new OligoToolkitPackage();
51
25
 
52
26
  //name: Oligo Toolkit
53
27
  //meta.icon: img/icons/toolkit.png
54
28
  //meta.browsePath: Oligo
55
29
  //tags: app
56
- export async function oligoToolkitApp(): Promise<void> {
30
+ //output: view v
31
+ export async function oligoToolkitApp(): Promise<DG.ViewBase> {
57
32
  await initSequenceTranslatorLibData();
58
33
  const externalViewFactories = await getExternalAppViewFactories();
59
34
  if (!externalViewFactories)
60
35
  throw new Error('External app view factories not loaded');
61
36
  const appUI = new CombinedAppUI(externalViewFactories!);
62
- await appUI.createAppLayout();
37
+ const view = await appUI.getAppView();
38
+ return view;
63
39
  }
64
40
 
65
41
  //name: Oligo Translator
66
42
  //meta.icon: img/icons/translator.png
67
43
  //meta.browsePath: Oligo
68
44
  //tags: app
69
- export async function oligoTranslatorApp(): Promise<void> {
70
- await buildLayout(APP.TRANSLATOR);
45
+ //output: view v
46
+ export async function oligoTranslatorApp(): Promise<DG.ViewBase> {
47
+ const view = await getSpecifiedAppView(APP_NAME.TRANSLATOR);
48
+ return view;
71
49
  }
72
50
 
73
51
  //name: Oligo Pattern
74
52
  //meta.icon: img/icons/pattern.png
75
53
  //meta.browsePath: Oligo
76
54
  //tags: app
77
- export async function oligoPatternApp(): Promise<void> {
78
- await buildLayout(APP.PATTERN);
55
+ //output: view v
56
+ export async function oligoPatternApp(): Promise<DG.ViewBase> {
57
+ const view = await getSpecifiedAppView(APP_NAME.PATTERN);
58
+ return view;
79
59
  }
80
60
 
81
61
  //name: Oligo Structure
82
62
  //meta.icon: img/icons/structure.png
83
63
  //meta.browsePath: Oligo
84
64
  //tags: app
85
- export async function oligoStructureApp(): Promise<void> {
86
- await buildLayout(APP.STRUCTRE);
65
+ //output: view v
66
+ export async function oligoStructureApp(): Promise<DG.ViewBase> {
67
+ const view = await getSpecifiedAppView(APP_NAME.STRUCTURE);
68
+ return view;
87
69
  }
88
70
 
89
71
  //name: initSequenceTranslatorLibData
90
72
  export async function initSequenceTranslatorLibData(): Promise<void> {
91
- await getJsonData();
73
+ await loadJsonData();
92
74
  await _package.initMonomerLib();
93
75
  }
94
76
 
@@ -152,7 +134,61 @@ export async function demoOligoStructure(): Promise<void> {
152
134
  //input: string sourceFormat
153
135
  //input: string targetFormat
154
136
  //output: string result
155
- export async function translateOligonucleotideSequence(sequence: string, sourceFormat: string, targetFormat: string): Promise<string> {
137
+ export async function translateOligonucleotideSequence(
138
+ sequence: string, sourceFormat: string, targetFormat: string
139
+ ): Promise<string> {
156
140
  await initSequenceTranslatorLibData();
157
141
  return (new FormatConverter(sequence, sourceFormat)).convertTo(targetFormat);
158
142
  }
143
+
144
+ async function getSpecifiedAppView(appName: string): Promise<DG.ViewBase> {
145
+ await initSequenceTranslatorLibData();
146
+ const appUI = getSpecifiedAppUI(appName);
147
+ const view = await appUI.getAppView();
148
+ return view;
149
+ }
150
+
151
+ //top-menu: Bio | Convert | PolyTool-Convert
152
+ //name: polyToolConvert
153
+ //description: Perform cyclization of polymers
154
+ export async function polyToolConvert(): Promise<void> {
155
+ let dialog: DG.Dialog;
156
+ try {
157
+ dialog = await getPolyToolConversionDialog();
158
+ dialog.show();
159
+ } catch (err: any) {
160
+ grok.shell.warning('To run PolyTool Conversion, open a dataframe with macromolecules');
161
+ }
162
+ }
163
+
164
+ //top-menu: Bio | Convert | PolyTool-Enumerate
165
+ //name: polyToolEnumerate
166
+ //description: Perform cyclization of polymers
167
+ export async function polyToolEnumerate(): Promise<void> {
168
+ let dialog: DG.Dialog;
169
+ try {
170
+ dialog = await getPolyToolEnumerationDialog();
171
+ dialog.show();
172
+ } catch (err: any) {
173
+ grok.shell.warning('To run PolyTool Enumeration, sketch the macromolecule and select monomers to vary');
174
+ }
175
+ }
176
+
177
+ //name: polyToolColumnChoice
178
+ //input: dataframe df [Input data table]
179
+ //input: column macroMolecule
180
+ export async function polyToolColumnChoice(df: DG.DataFrame, macroMolecule: DG.Column): Promise<void> {
181
+ _setPeptideColumn(macroMolecule);
182
+ await grok.data.detectSemanticTypes(df);
183
+ }
184
+
185
+ //name: createMonomerLibraryForPolyTool
186
+ //input: file file
187
+ export async function createMonomerLibraryForPolyTool(file: DG.FileInfo) {
188
+ const fileContent = await file.readAsString();
189
+ const libHandler = new PolyToolCsvLibHandler(file.fileName, fileContent);
190
+ const libObject = await libHandler.getJson();
191
+ const jsonFileName = file.fileName.replace(/\.csv$/, '.json');
192
+ const jsonFileContent = JSON.stringify(libObject, null, 2);
193
+ DG.Utils.download(jsonFileName, jsonFileContent);
194
+ }
@@ -3,19 +3,19 @@ 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 {ExternalPluginUI} from '../view/app-ui';
7
- import {ColoredTextInput} from '../view/utils/colored-input/colored-text-input';
8
- import {highlightInvalidSubsequence} from '../view/utils/colored-input/input-painters';
9
- import {codesToSymbolsDictionary} from '../model/data-loading-utils/json-loader';
6
+ import {ExternalPluginUI} from '../apps/common/view/utils';
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
10
  import {MERMADE} from './const';
11
11
 
12
12
  export async function getExternalAppViewFactories(): Promise<{[name: string]: () => DG.View} | undefined> {
13
13
  const externalPluginData = {
14
- [MERMADE.FUNCTION_NAME]: {
14
+ [MERMADE.FUNCTION_NAME]: {
15
15
  tabName: MERMADE.TAB_NAME,
16
16
  parameters: getMerMadeParameters()
17
17
  },
18
- }
18
+ };
19
19
 
20
20
  const result: {[tabName: string]: () => DG.View} = {};
21
21
 
@@ -30,7 +30,7 @@ export async function getExternalAppViewFactories(): Promise<{[name: string]: ()
30
30
 
31
31
  result[data.tabName] = () => pluginUI.getView();
32
32
  } catch (err) {
33
- console.warn(`Plugin ${pluginName} not loaded, reason:`, err)
33
+ console.warn(`Plugin ${pluginName} not loaded, reason:`, err);
34
34
  continue;
35
35
  }
36
36
  }
@@ -43,6 +43,6 @@ function getMerMadeParameters(): {[name: string]: any} {
43
43
 
44
44
  return {
45
45
  coloredInput: input,
46
- codes: codesToSymbolsDictionary
47
- }
46
+ codes: CODES_TO_SYMBOLS_DICT
47
+ };
48
48
  }
@@ -0,0 +1,28 @@
1
+ import {HELM_REQUIRED_FIELD} from '@datagrok-libraries/bio/src/utils/const';
2
+
3
+ export const helmFieldsToPolyToolInputFields = {
4
+ [HELM_REQUIRED_FIELD.SYMBOL]: 'Short Name',
5
+ [HELM_REQUIRED_FIELD.NAME]: 'Medium Name',
6
+ [HELM_REQUIRED_FIELD.SMILES]: 'SMILES',
7
+ };
8
+
9
+ export const R_GROUP_BLOCK_DUMMY = [
10
+ {
11
+ 'capGroupSmiles': '[*:1][H]',
12
+ 'alternateId': 'R1-H',
13
+ 'capGroupName': 'H',
14
+ 'label': 'R1'
15
+ },
16
+ {
17
+ 'capGroupSmiles': 'O[*:2]',
18
+ 'alternateId': 'R2-OH',
19
+ 'capGroupName': 'OH',
20
+ 'label': 'R2'
21
+ },
22
+ {
23
+ 'capGroupSmiles': '[*:3][H]',
24
+ 'alternateId': 'R3-H',
25
+ 'capGroupName': 'H',
26
+ 'label': 'R3'
27
+ }
28
+ ];
@@ -0,0 +1,40 @@
1
+ import * as DG from 'datagrok-api/dg';
2
+
3
+ import {PolyToolMonomerLibHandler} from './monomer-lib-handler';
4
+
5
+ /** Handler of custom monomer libs for PolyTool */
6
+ export class PolyToolCsvLibHandler {
7
+ constructor(private fileName: string, private fileContent: string) {
8
+ this.validateFileType();
9
+ const df = DG.DataFrame.fromCsv(this.fileContent);
10
+ const json = this.toJson(df);
11
+ this.polyToolMonomerLib = new PolyToolMonomerLibHandler(json);
12
+ this.validateContent();
13
+ }
14
+
15
+ private polyToolMonomerLib: PolyToolMonomerLibHandler;
16
+
17
+ async getJson(): Promise<any> {
18
+ const rawLibData = this.polyToolMonomerLib.getJsonMonomerLib();
19
+ return rawLibData;
20
+ }
21
+
22
+ private toJson(df: DG.DataFrame): any[] {
23
+ return Array.from({length: df.rowCount}, (_, idx) =>
24
+ df.columns.names().reduce((entry: { [key: string]: any }, colName) => {
25
+ entry[colName] = df.get(colName, idx);
26
+ return entry;
27
+ }, {})
28
+ );
29
+ }
30
+
31
+ private validateFileType(): void {
32
+ if (!this.fileName.endsWith('.csv'))
33
+ throw new Error(`File ${this.fileName} is not an CSV file`);
34
+ }
35
+
36
+ private validateContent(): void {
37
+ if (!this.polyToolMonomerLib.isValid())
38
+ throw new Error('Invalid format of CSV monomer lib');
39
+ }
40
+ }
@@ -0,0 +1,56 @@
1
+ import {GAP_SYMBOL, INotationProvider, ISeqSplitted, SeqSplittedBase, SplitterFunc}
2
+ from '@datagrok-libraries/bio/src/utils/macromolecule/types';
3
+ import {getSplitterWithSeparator, StringListSeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
4
+ import {GapOriginals} from '@datagrok-libraries/bio/src/utils/seq-handler';
5
+ import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
6
+
7
+ export class CyclizedNotationProvider implements INotationProvider {
8
+ private readonly separatorSplitter: SplitterFunc;
9
+ public readonly splitter: SplitterFunc;
10
+
11
+ constructor(
12
+ public readonly separator: string
13
+ ) {
14
+ this.separatorSplitter = getSplitterWithSeparator(this.separator);
15
+ this.splitter = this._splitter.bind(this);
16
+ }
17
+
18
+ private _splitter(seq: string): ISeqSplitted {
19
+ const baseSS: ISeqSplitted = this.separatorSplitter(seq);
20
+ return new CyclizedSeqSplitted(baseSS.originals, GapOriginals[NOTATION.SEPARATOR]);
21
+ };
22
+ }
23
+
24
+ /** Gets canonical monomers for original ones with cyclization marks */
25
+ export class CyclizedSeqSplitted extends StringListSeqSplitted {
26
+ private readonly seqCList: (string | null)[];
27
+
28
+ private _canonicals: string[] | null = null;
29
+ override get canonicals(): SeqSplittedBase {
30
+ if (!this._canonicals) {
31
+ const len = this.length;
32
+ this._canonicals = new Array<string>(len);
33
+ for (let posIdx = 0; posIdx < len; ++posIdx)
34
+ this._canonicals[posIdx] = this.getCanonical(posIdx);
35
+ }
36
+ return this._canonicals;
37
+ }
38
+
39
+ override getCanonical(posIdx: number): string {
40
+ if (this.isGap(posIdx)) return GAP_SYMBOL;
41
+
42
+ let cmRes: string | null = this.seqCList[posIdx];
43
+ if (cmRes === null) {
44
+ const om = this.getOriginal(posIdx);
45
+ cmRes = om;
46
+ if (om[om.length - 1] === ')')
47
+ cmRes = this.seqCList[posIdx] = om.replace(/\(\d+\)$/, '');
48
+ }
49
+ return cmRes;
50
+ }
51
+
52
+ constructor(seqOList: SeqSplittedBase, gapOriginalMonomer: string) {
53
+ super(seqOList, gapOriginalMonomer);
54
+ this.seqCList = new Array<string | null>(this.length).fill(null);
55
+ }
56
+ }
@@ -0,0 +1,115 @@
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';
4
+ import * as DG from 'datagrok-api/dg';
5
+
6
+ import {HELM_FIELDS, DUMMY_MONOMER} from '@datagrok-libraries/bio/src/utils/const';
7
+ import {
8
+ helmFieldsToPolyToolInputFields, R_GROUP_BLOCK_DUMMY
9
+ } from './const';
10
+ import {Monomer, RGroup} from '@datagrok-libraries/bio/src/types/index';
11
+
12
+ export class PolyToolMonomerLibHandler {
13
+ constructor(private rawLib: any[]) { }
14
+
15
+ isValid(): boolean {
16
+ return this.rawLib.every((entry) => {
17
+ return typeof entry === 'object' &&
18
+ Object.values(helmFieldsToPolyToolInputFields).every((field) => {
19
+ return field in entry &&
20
+ typeof entry[field] === 'string';
21
+ });
22
+ });
23
+ }
24
+
25
+ getJsonMonomerLib(): any {
26
+ const resultLib: any[] = [];
27
+ this.rawLib.forEach((rawMonomer) => {
28
+ const monomer = this.prepareMonomer(rawMonomer);
29
+ resultLib.push(monomer);
30
+ });
31
+ return resultLib;
32
+ }
33
+
34
+ private prepareMonomer(rawMonomer: any): Monomer {
35
+ const monomer: Monomer = {...DUMMY_MONOMER};
36
+
37
+ Object.entries(helmFieldsToPolyToolInputFields).forEach(([key, value]) => {
38
+ const monomerSymbol = rawMonomer[value] as string;
39
+ //@ts-ignore
40
+ monomer[key] = monomerSymbol;
41
+ });
42
+
43
+ let key = HELM_FIELDS.SMILES;
44
+ const rawSmiles = rawMonomer[helmFieldsToPolyToolInputFields[key]];
45
+ const smilesHandler = new SmilesHandler(rawSmiles);
46
+ const smiles = smilesHandler.getCappedSmiles();
47
+ monomer[key] = smiles;
48
+
49
+ key = HELM_FIELDS.RGROUPS;
50
+ monomer[key] = RGroupHandler.getRGroups(smilesHandler.getNumberOfRGroups());
51
+
52
+ key = HELM_FIELDS.MOLFILE;
53
+ monomer[key] = new MolBlockHandler(smilesHandler.getSmilesWithRGroups()).getMolfile();
54
+
55
+ return monomer;
56
+ }
57
+ }
58
+
59
+ class SmilesHandler {
60
+ constructor(rawSmiles: string) {
61
+ const regex = /\[R(\d+)\]/g;
62
+ let i = 0;
63
+ this.smilesWithRGroups = rawSmiles.replace(regex, (_, capturedDigit) => { ++i; return `[${capturedDigit}*]`; });
64
+ this.numberOfRGroups = i;
65
+ }
66
+
67
+ private numberOfRGroups: number;
68
+ private smilesWithRGroups: string;
69
+
70
+ getSmilesWithRGroups(): string {
71
+ return this.smilesWithRGroups;
72
+ }
73
+
74
+ getCappedSmiles(): string {
75
+ const smiles = this.capRGroups();
76
+ return smiles;
77
+ }
78
+
79
+ getNumberOfRGroups(): number {
80
+ return this.numberOfRGroups;
81
+ }
82
+
83
+ private capRGroups(): string {
84
+ let result = this.smilesWithRGroups.replace('[1*]', '[H:1]');
85
+ result = result.replace('[2*]', '[OH:2]');
86
+ return result.replace('[3*]', '[H:3]');
87
+ }
88
+ }
89
+
90
+ class RGroupHandler {
91
+ private constructor() {};
92
+
93
+ static getRGroups(numberOfRGroups: number): RGroup[] {
94
+ return R_GROUP_BLOCK_DUMMY.slice(0, numberOfRGroups);
95
+ }
96
+ }
97
+
98
+ class MolBlockHandler {
99
+ constructor(private smilesWithRGroups: string) { }
100
+
101
+ getMolfile(): string {
102
+ let molfile = DG.chem.convert(this.smilesWithRGroups, DG.chem.Notation.Smiles, DG.chem.Notation.MolBlock);
103
+ molfile = this.restoreRGPLine(molfile);
104
+ molfile = this.fixRGroupSymbols(molfile);
105
+ return molfile;
106
+ }
107
+
108
+ private restoreRGPLine(rawMolfile: string): string {
109
+ return rawMolfile.replace('M ISO', 'M RGP');
110
+ }
111
+
112
+ private fixRGroupSymbols(molfile: string): string {
113
+ return molfile.replace(/\bR\b/g, 'R#');
114
+ }
115
+ }