@datagrok/sequence-translator 1.3.5 → 1.3.9

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 (33) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/detectors.js +32 -0
  3. package/dist/package-test.js +1 -1
  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/package.json +10 -6
  8. package/src/apps/common/view/components/colored-input/style.css +3 -2
  9. package/src/apps/pattern/model/data-manager.ts +4 -1
  10. package/src/apps/pattern/model/translator.ts +45 -8
  11. package/src/apps/pattern/view/components/bulk-convert/column-input.ts +4 -10
  12. package/src/apps/pattern/view/components/bulk-convert/table-input.ts +5 -8
  13. package/src/apps/pattern/view/components/edit-block-controls.ts +6 -15
  14. package/src/apps/pattern/view/components/load-block-controls.ts +7 -9
  15. package/src/apps/pattern/view/components/numeric-label-visibility-controls.ts +4 -5
  16. package/src/apps/pattern/view/components/strand-editor/header-controls.ts +2 -2
  17. package/src/apps/pattern/view/components/strand-editor/strand-controls.ts +2 -2
  18. package/src/apps/pattern/view/components/terminal-modification-editor.ts +1 -1
  19. package/src/apps/pattern/view/components/translation-examples-block.ts +1 -1
  20. package/src/apps/structure/view/ui.ts +5 -5
  21. package/src/apps/translator/view/ui.ts +15 -27
  22. package/src/package.ts +52 -11
  23. package/src/plugins/mermade.ts +1 -1
  24. package/src/polytool/pt-conversion.ts +2 -2
  25. package/src/polytool/pt-dialog.ts +99 -18
  26. package/src/polytool/pt-enumeration-chem.ts +105 -0
  27. package/src/polytool/pt-enumeration-helm.ts +22 -0
  28. package/src/polytool/pt-ui.ts +25 -0
  29. package/src/polytool/utils.ts +34 -3
  30. package/src/utils/context-menu.ts +57 -0
  31. package/src/utils/err-info.ts +13 -0
  32. package/webpack.config.js +2 -4
  33. package/src/polytool/pt-enumeration.ts +0 -141
@@ -3,12 +3,20 @@ 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 wu from 'wu';
7
+
8
+ import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
9
+ import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
10
+ import {HelmAtom} from '@datagrok-libraries/bio/src/helm/types';
11
+
6
12
  import {RuleInputs, RULES_PATH, RULES_STORAGE_NAME} from './pt-rules';
7
13
  import {addTransformedColumn} from './pt-conversion';
8
14
 
9
15
  import {handleError} from './utils';
10
- import {getLibrariesList, HelmInput, getEnumeration} from './pt-enumeration';
11
- import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
16
+ import {defaultErrorHandler} from '../utils/err-info';
17
+ import {getLibrariesList} from './utils';
18
+ import {getEnumerationHelm, PT_HELM_EXAMPLE} from './pt-enumeration-helm';
19
+ import {getEnumerationChem, PT_CHEM_EXAMPLE} from './pt-enumeration-chem';
12
20
 
13
21
  const PT_ERROR_DATAFRAME = 'No dataframe with macromolecule columns open';
14
22
  const PT_WARNING_COLUMN = 'No marcomolecule column chosen!';
@@ -25,15 +33,15 @@ export async function getPolyToolConversionDialog(): Promise<DG.Dialog> {
25
33
  if (!targetColumns)
26
34
  throw new Error(PT_ERROR_DATAFRAME);
27
35
 
28
- const targetColumnInput = ui.columnInput(
29
- 'Column', grok.shell.t, targetColumns[0], null,
30
- {filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE}
31
- );
36
+ const targetColumnInput = ui.input.column('Column', {
37
+ table: grok.shell.t, value: targetColumns[0],
38
+ filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE
39
+ });
32
40
 
33
- const generateHelmChoiceInput = ui.boolInput(PT_UI_GET_HELM, true);
41
+ const generateHelmChoiceInput = ui.input.bool(PT_UI_GET_HELM, {value: true});
34
42
  ui.tooltip.bind(generateHelmChoiceInput.root, PT_UI_ADD_HELM);
35
43
 
36
- const chiralityEngineInput = ui.boolInput(PT_UI_USE_CHIRALITY, false);
44
+ const chiralityEngineInput = ui.input.bool(PT_UI_USE_CHIRALITY, {value: false});
37
45
  const ruleInputs = new RuleInputs(RULES_PATH, RULES_STORAGE_NAME, '.json');
38
46
  const rulesHeader = ui.inlineText([PT_UI_RULES_USED]);
39
47
  ui.tooltip.bind(rulesHeader, 'Add or specify rules to use');
@@ -74,44 +82,117 @@ export async function getPolyToolConversionDialog(): Promise<DG.Dialog> {
74
82
  return dialog;
75
83
  }
76
84
 
77
- export async function getPolyToolEnumerationDialog(): Promise<DG.Dialog> {
78
- const helmInput = await HelmInput.init();
85
+ export async function getPolyToolEnumerationHelmDialog(cell?: DG.Cell): Promise<DG.Dialog> {
86
+ const [libList, helmHelper] = await Promise.all([
87
+ getLibrariesList(), getHelmHelper()]);
88
+
89
+ const helmValue = cell ? cell.value : PT_HELM_EXAMPLE;
79
90
 
80
- const libList = await getLibrariesList();
81
- const screenLibrary = ui.choiceInput('Library to use', null, libList);
91
+ const helmInput = helmHelper.createHelmInput('Macromolecule', {value: helmValue});
92
+ const screenLibrary = ui.input.choice('Library to use', {value: null, items: libList});
82
93
 
94
+ helmInput.input.setAttribute('style', `min-width:250px!important;`);
83
95
  screenLibrary.input.setAttribute('style', `min-width:250px!important;`);
84
96
 
85
97
  const div = ui.div([
86
- helmInput.getDiv(),
98
+ helmInput.root,
87
99
  screenLibrary.root
88
100
  ]);
89
101
 
102
+ // Displays the molecule from a current cell (monitors changes)
90
103
  const cccSubs = grok.events.onCurrentCellChanged.subscribe(() => {
91
104
  const cell = grok.shell.tv.dataFrame.currentCell;
92
105
 
93
- if (cell.column.semType === DG.SEMTYPE.MACROMOLECULE && cell.column.tags[DG.TAGS.UNITS] === NOTATION.HELM)
94
- helmInput.setHelmString(cell.value);
106
+ if (cell.column.semType === DG.SEMTYPE.MACROMOLECULE && cell.column.meta.units === NOTATION.HELM)
107
+ helmInput.stringValue = cell.value;
95
108
  });
96
109
 
97
110
  const dialog = ui.dialog(PT_UI_DIALOG_ENUMERATION)
98
111
  .add(div)
99
112
  .onOK(async () => {
100
113
  try {
101
- const helmString = helmInput.getHelmString();
102
- const helmSelections = helmInput.getHelmSelections();
114
+ const helmString = helmInput.stringValue;
115
+ const helmSelections: number[] = wu.enumerate<HelmAtom>(helmInput.value.atoms)
116
+ .filter(([a, aI]) => a.highlighted)
117
+ .map(([a, aI]) => aI).toArray();
103
118
  if (helmString === undefined || helmString === '') {
104
119
  grok.shell.warning('PolyTool: no molecule was provided');
105
120
  } else if (helmSelections === undefined || helmSelections.length < 1) {
106
121
  grok.shell.warning('PolyTool: no selection was provided');
107
122
  } else {
108
- const molecules = await getEnumeration(helmString, helmSelections, screenLibrary.value!);
123
+ const molecules = await getEnumerationHelm(helmString, helmSelections, screenLibrary.value!);
109
124
  const molCol = DG.Column.fromStrings('Enumerated', molecules);
110
125
  const df = DG.DataFrame.fromColumns([molCol]);
111
126
  grok.shell.addTableView(df);
112
127
  }
113
128
  } catch (err: any) {
129
+ defaultErrorHandler(err);
130
+ } finally {
131
+ cccSubs.unsubscribe();
132
+ }
133
+ }).onCancel(() => {
134
+ cccSubs.unsubscribe();
135
+ });
136
+
137
+ return dialog;
138
+ }
139
+
140
+ export async function getPolyToolEnumerationChemDialog(cell?: DG.Cell): Promise<DG.Dialog> {
141
+ const [libList, helmHelper] = await Promise.all([
142
+ getLibrariesList(), getHelmHelper()]);
143
+
144
+ let molValue = PT_CHEM_EXAMPLE;//cell ? cell.value : PT_CHEM_EXAMPLE;
145
+ const molInput = new DG.chem.Sketcher(DG.chem.SKETCHER_MODE.EXTERNAL);
146
+ molInput.syncCurrentObject = false;
147
+ // sketcher.setMolFile(col.tags[ALIGN_BY_SCAFFOLD_TAG]);
148
+ molInput.onChanged.subscribe((_: any) => {
149
+ molValue = molInput.getMolFile();
150
+ // col.tags[ALIGN_BY_SCAFFOLD_TAG] = molFile;
151
+ // col.temp[ALIGN_BY_SCAFFOLD_TAG] = molFile;
152
+ // col.dataFrame?.fireValuesChanged();
153
+ });
154
+ molInput.root.classList.add('ui-input-editor');
155
+ molInput.root.style.marginTop = '3px';
156
+ molInput.setMolFile(molValue);
157
+
158
+ //const helmInput = helmHelper.createHelmInput('Macromolecule', {value: helmValue});
159
+ const screenLibrary = ui.input.choice('Library to use', {value: null, items: libList});
114
160
 
161
+ molInput.root.setAttribute('style', `min-width:250px!important;`);
162
+ molInput.root.setAttribute('style', `max-width:250px!important;`);
163
+ screenLibrary.input.setAttribute('style', `min-width:250px!important;`);
164
+
165
+ const div = ui.div([
166
+ molInput.root,
167
+ screenLibrary.root
168
+ ]);
169
+
170
+ const cccSubs = grok.events.onCurrentCellChanged.subscribe(() => {
171
+ const cell = grok.shell.tv.dataFrame.currentCell;
172
+
173
+ if (cell.column.semType === DG.SEMTYPE.MOLECULE)
174
+ molInput.setValue(cell.value);
175
+ });
176
+
177
+ // Displays the molecule from a current cell (monitors changes)
178
+ const dialog = ui.dialog(PT_UI_DIALOG_ENUMERATION)
179
+ .add(div)
180
+ .onOK(async () => {
181
+ try {
182
+ const molString = molInput.getMolFile();
183
+
184
+ if (molString === undefined || molString === '') {
185
+ grok.shell.warning('PolyTool: no molecule was provided');
186
+ } else if (!molString.includes('R#')) {
187
+ grok.shell.warning('PolyTool: no R group was provided');
188
+ } else {
189
+ const molecules = await getEnumerationChem(molString, screenLibrary.value!);
190
+ const molCol = DG.Column.fromStrings('Enumerated', molecules);
191
+ const df = DG.DataFrame.fromColumns([molCol]);
192
+ grok.shell.addTableView(df);
193
+ }
194
+ } catch (err: any) {
195
+ defaultErrorHandler(err);
115
196
  } finally {
116
197
  cccSubs.unsubscribe();
117
198
  }
@@ -0,0 +1,105 @@
1
+ import * as ui from 'datagrok-api/ui';
2
+ import * as grok from 'datagrok-api/grok';
3
+ import * as DG from 'datagrok-api/dg';
4
+
5
+ import {getAvailableMonomers, getAvailableMonomerMols} from './utils';
6
+ import {RDModule, RDMol} from '@datagrok-libraries/chem-meta/src/rdkit-api';
7
+
8
+ export const PT_CHEM_EXAMPLE = `
9
+
10
+
11
+ 22 24 0 0 0 0 0 0 0 0999 V2000
12
+ 0.3128 -0.7509 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
13
+ 0.3128 0.0740 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
14
+ -0.4054 -1.1623 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
15
+ -1.1081 -0.7509 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
16
+ -0.4054 0.4877 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
17
+ -1.1081 0.0740 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
18
+ -1.8175 -1.1623 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
19
+ 1.0222 0.4877 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
20
+ -1.8175 0.4877 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
21
+ -2.5292 -0.7509 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
22
+ 1.0222 1.3127 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
23
+ 1.7227 1.7263 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
24
+ -0.4054 -1.9896 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
25
+ -2.5292 0.0740 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
26
+ 2.4544 1.3127 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
27
+ 1.7406 0.0740 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
28
+ 1.0222 -1.1623 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
29
+ 2.4544 0.4877 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
30
+ -1.8175 -1.9896 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
31
+ -3.2453 0.4877 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
32
+ 3.1670 1.7285 0.0000 R# 0 0 0 0 0 0 0 0 0 0 0 0
33
+ 1.7149 2.5513 0.0000 R# 0 0 0 0 0 0 0 0 0 0 0 0
34
+ 2 1 2 0 0 0 0
35
+ 3 1 1 0 0 0 0
36
+ 4 3 1 0 0 0 0
37
+ 5 2 1 0 0 0 0
38
+ 6 5 1 0 0 0 0
39
+ 7 4 1 0 0 0 0
40
+ 8 2 1 0 0 0 0
41
+ 9 6 1 0 0 0 0
42
+ 10 7 2 0 0 0 0
43
+ 11 8 2 0 0 0 0
44
+ 12 11 1 0 0 0 0
45
+ 13 3 2 0 0 0 0
46
+ 14 9 2 0 0 0 0
47
+ 15 18 1 0 0 0 0
48
+ 16 8 1 0 0 0 0
49
+ 17 1 1 0 0 0 0
50
+ 18 16 2 0 0 0 0
51
+ 19 7 1 0 0 0 0
52
+ 20 14 1 0 0 0 0
53
+ 6 4 2 0 0 0 0
54
+ 15 12 2 0 0 0 0
55
+ 14 10 1 0 0 0 0
56
+ 15 21 1 0 0 0 0
57
+ 12 22 1 0 0 0 0
58
+ M RGP 2 21 1 22 2
59
+ M END`;
60
+
61
+ export async function getEnumerationChem(molString: string, screenLibrary: string):
62
+ Promise<string[]> {
63
+ const variableMonomers = await getAvailableMonomers(screenLibrary);
64
+ const variableMols = await getAvailableMonomerMols(screenLibrary);
65
+
66
+ const idx = molString.indexOf('M RGP');
67
+ const rCount = parseInt(molString.slice(idx + 6, idx + 9)); //extracting from molfile positions
68
+ const size = 1 * variableMonomers.length;
69
+ const enumerations = new Array<string>(size);
70
+
71
+ const rdkitModule: RDModule = await grok.functions.call('Chem:getRdKitModule');
72
+ const molScaffold: RDMol = rdkitModule.get_mol(molString);
73
+ const smiScaffold = molScaffold.get_smiles();
74
+ molScaffold.delete();
75
+
76
+ const smilesSubsts = new Array<string>(variableMonomers.length);
77
+
78
+ for (let i = 0; i < variableMonomers.length; i++) {
79
+
80
+ const name = variableMonomers[i];
81
+ const molBlock = variableMols[name];
82
+ const molSubst: RDMol = rdkitModule.get_mol(molBlock);
83
+ smilesSubsts[i] = molSubst.get_smiles();
84
+ molSubst.delete();
85
+ }
86
+
87
+ //TODO: get for all R groups
88
+ for (let i = 0; i < 1; i++) {
89
+ for (let j = 0; j < variableMonomers.length; j++) {
90
+ try {
91
+ const smiResRaw = `${smiScaffold}.${smilesSubsts[j]}`.replaceAll('[1*]C', 'C([1*])').replaceAll('[1*]c', 'c([1*])').replaceAll('[1*]O', 'O([1*])').replaceAll('[1*]N', 'N([1*])');
92
+ const smiRes = `${smiResRaw}`.replaceAll('([1*])', '9').replaceAll('[1*]', '9');
93
+ const molRes: RDMol = rdkitModule.get_mol(smiRes);
94
+
95
+ enumerations[i * variableMonomers.length + j] = molRes.get_v3Kmolblock();
96
+ molRes.delete();
97
+ }
98
+ catch(err:any) {
99
+ enumerations[i * variableMonomers.length + j] = '';
100
+ }
101
+ }
102
+ }
103
+
104
+ return enumerations;
105
+ }
@@ -0,0 +1,22 @@
1
+ import * as ui from 'datagrok-api/ui';
2
+ import * as grok from 'datagrok-api/grok';
3
+ import * as DG from 'datagrok-api/dg';
4
+ import {Chain} from './pt-conversion';
5
+ import {getAvailableMonomers} from './utils'
6
+
7
+ export const PT_HELM_EXAMPLE = 'PEPTIDE1{[R].[F].[T].[G].[H].[F].[G].[A].[A].[Y].[P].[E].[NH2]}$$$$';
8
+
9
+ export async function getEnumerationHelm(helmString: string, helmSelections: number[], screenLibrary: string):
10
+ Promise<string[]> {
11
+ const variableMonomers = await getAvailableMonomers(screenLibrary);
12
+ const chain: Chain = Chain.fromHelm(helmString);
13
+ const size = helmSelections.length * variableMonomers.length;
14
+ const enumerations = new Array<string>(size);
15
+
16
+ for (let i = 0; i < helmSelections.length; i++) {
17
+ for (let j = 0; j < variableMonomers.length; j++)
18
+ enumerations[i * variableMonomers.length + j] = chain.getHelmChanged(helmSelections[i], variableMonomers[j]);
19
+ }
20
+
21
+ return enumerations;
22
+ }
@@ -0,0 +1,25 @@
1
+ import * as grok from 'datagrok-api/grok';
2
+ import * as DG from 'datagrok-api/dg';
3
+ import * as ui from 'datagrok-api/ui';
4
+
5
+ import {getPolyToolEnumerationHelmDialog, getPolyToolEnumerationChemDialog} from './pt-dialog';
6
+
7
+ export function polyToolEnumerateHelmUI(cell?: DG.Cell): void {
8
+ getPolyToolEnumerationHelmDialog(cell)
9
+ .then((dialog) => {
10
+ dialog.show({resizable: true});
11
+ })
12
+ .catch((_err: any) => {
13
+ grok.shell.warning('To run PolyTool Enumeration, sketch the macromolecule and select monomers to vary');
14
+ });
15
+ }
16
+
17
+ export function polyToolEnumerateChemUI(cell?: DG.Cell): void {
18
+ getPolyToolEnumerationChemDialog(cell)
19
+ .then((dialog) => {
20
+ dialog.show({resizable: true});
21
+ })
22
+ .catch((_err: any) => {
23
+ grok.shell.warning('To run PolyTool Enumeration, sketch the molecule and specify the R group to vary');
24
+ });
25
+ }
@@ -2,19 +2,27 @@
2
2
  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
- import {_package} from '../package';
6
5
 
6
+ import {_package} from '../package';
7
7
  import {ALPHABET, ALIGNMENT, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
8
+ import {OrgType} from '@datagrok-libraries/bio/src/helm/types';
9
+
10
+ import {
11
+ IMonomerLibFileManager, IMonomerLibHelper
12
+ } from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
13
+
14
+ declare const org: OrgType;
15
+ const LIB_PATH = 'System:AppData/Bio/monomer-libraries/';
8
16
 
9
17
  export function _setPeptideColumn(col: DG.Column): void {
10
18
  addCommonTags(col);
11
- col.setTag('units', NOTATION.SEPARATOR);
19
+ col.meta.units = NOTATION.SEPARATOR;
12
20
  col.setTag('separator', '-');
13
21
  // col.setTag('cell.renderer', 'sequence');
14
22
  }
15
23
 
16
24
  function addCommonTags(col: DG.Column<any>) {
17
- col.setTag('quality', DG.SEMTYPE.MACROMOLECULE);
25
+ col.semType = DG.SEMTYPE.MACROMOLECULE;
18
26
  col.setTag('aligned', ALIGNMENT.SEQ);
19
27
  col.setTag('alphabet', ALPHABET.PT);
20
28
  }
@@ -25,3 +33,26 @@ export function handleError(err: any): void {
25
33
  grok.shell.error(errMsg);
26
34
  _package.logger.error(err.message, undefined, stack);
27
35
  }
36
+
37
+ export async function getAvailableMonomers(screenLibrary: string): Promise<string[]> {
38
+ const monomerLibHelper: IMonomerLibHelper = await grok.functions.call('Bio:getMonomerLibHelper', {});
39
+ const monomerLib = await monomerLibHelper.readLibrary(LIB_PATH, screenLibrary);
40
+ //NOTICE: works with Peptides only
41
+ return monomerLib.getMonomerSymbolsByType('PEPTIDE');
42
+ }
43
+
44
+ export async function getAvailableMonomerMols(screenLibrary: string): Promise<{[monomerSymbol: string]: string}> {
45
+ const monomerLibHelper: IMonomerLibHelper = await grok.functions.call('Bio:getMonomerLibHelper', {});
46
+ const monomerLib = await monomerLibHelper.readLibrary(LIB_PATH, screenLibrary);
47
+ const monomers = monomerLib.getMonomerSymbolsByType('PEPTIDE');
48
+ const mols = new Array<string>(monomers.length);
49
+
50
+ //NOTICE: works with Peptides only
51
+ return monomerLib.getMonomerMolsByPolymerType('PEPTIDE')!;
52
+ }
53
+
54
+ export async function getLibrariesList(): Promise<string[]> {
55
+ const monomerLibHelper: IMonomerLibHelper = await grok.functions.call('Bio:getMonomerLibHelper', {});
56
+ const monomerFileManager: IMonomerLibFileManager = await monomerLibHelper.getFileManager();
57
+ return monomerFileManager.getValidLibraryPaths();
58
+ }
@@ -0,0 +1,57 @@
1
+ import * as grok from 'datagrok-api/grok';
2
+ import * as DG from 'datagrok-api/dg';
3
+ import * as ui from 'datagrok-api/ui';
4
+
5
+ import {defaultErrorHandler} from './err-info';
6
+ import {_package, addContextMenu} from '../package';
7
+ import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
8
+ import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
9
+ import {polyToolEnumerateHelmUI} from '../polytool/pt-ui';
10
+
11
+ export type SequenceTranslatorWindowType = Window & {
12
+ $sequenceTranslator?: {
13
+ contextMenuError?: any
14
+ },
15
+ };
16
+ declare const window: SequenceTranslatorWindowType;
17
+
18
+ export function addContextMenuUI(event: DG.EventData): void {
19
+ try {
20
+ const item = event.args.item;
21
+ if (item) {
22
+ const menu: DG.Menu = event.args.menu;
23
+ if (item instanceof DG.GridCell || item.constructor.name == 'GridCell') {
24
+ const gridCell: DG.GridCell = item;
25
+ if (addContextMenuForCell(gridCell, menu))
26
+ event.preventDefault();
27
+ }
28
+ }
29
+ } catch (err: any) {
30
+ defaultErrorHandler(err);
31
+ if (!window.$sequenceTranslator) window.$sequenceTranslator = {};
32
+ window.$sequenceTranslator.contextMenuError = err;
33
+ }
34
+ }
35
+
36
+ function addContextMenuForCell(gridCell: DG.GridCell, menu: DG.Menu): boolean {
37
+ const logPrefix: string = `ST: addContextMenuForCell()`;
38
+ _package.logger.debug(`${logPrefix}, start`);
39
+
40
+ const polyToolEnumerate = () => {
41
+ polyToolEnumerateHelmUI(gridCell.cell);
42
+ };
43
+
44
+ if (gridCell && gridCell.tableColumn) {
45
+ switch (gridCell.tableColumn.semType) {
46
+ case DG.SEMTYPE.MACROMOLECULE: {
47
+ const sh = SeqHandler.forColumn(gridCell.tableColumn);
48
+ if (sh.notation === NOTATION.HELM) {
49
+ menu
50
+ .item('PolyTool-Enumerate', polyToolEnumerate);
51
+ true;
52
+ }
53
+ }
54
+ }
55
+ }
56
+ return false;
57
+ }
@@ -0,0 +1,13 @@
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 {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
6
+
7
+ import {_package} from '../package';
8
+
9
+ export function defaultErrorHandler(err: any): void {
10
+ const [errMsg, errStack] = errInfo(err);
11
+ _package.logger.error(errMsg, undefined, errStack);
12
+ grok.shell.error(errMsg);
13
+ }
package/webpack.config.js CHANGED
@@ -2,9 +2,7 @@ const path = require('path');
2
2
  const packageName = path.parse(require('./package.json').name).name.toLowerCase().replace(/-/g, '');
3
3
 
4
4
  module.exports = {
5
- cache: {
6
- type: 'filesystem',
7
- },
5
+ cache: {type: 'filesystem'},
8
6
  mode: 'development',
9
7
  entry: {
10
8
  package: ['./src/package.ts'],
@@ -12,7 +10,7 @@ module.exports = {
12
10
  filename: 'package-test.js',
13
11
  library: {type: 'var', name: `${packageName}_test`},
14
12
  import: './src/package-test.ts',
15
- }
13
+ },
16
14
  },
17
15
  resolve: {
18
16
  extensions: ['.ts', '.tsx', '.wasm', '.mjs', '.js', '.json'],
@@ -1,141 +0,0 @@
1
- import * as ui from 'datagrok-api/ui';
2
- import * as grok from 'datagrok-api/grok';
3
- import * as DG from 'datagrok-api/dg';
4
-
5
- import {IHelmHelper, getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
6
- import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
7
- import '@datagrok-libraries/bio/src/types/helm';
8
- import '@datagrok-libraries/bio/src/types/jsdraw2';
9
- import * as org from 'org';
10
- import $ from 'cash-dom';
11
- import {Unsubscribable, fromEvent} from 'rxjs';
12
- import {IMonomerLibFileManager, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
13
- import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
14
-
15
- import {Chain} from './pt-conversion';
16
-
17
- const LIB_PATH = 'System:AppData/Bio/monomer-libraries/';
18
- const PT_HELM_EXAMPLE = 'PEPTIDE1{[R].[F].[T].[G].[H].[F].[G].[A].[A].[Y].[P].[E].[NH2]}$$$$';
19
-
20
- export async function getLibrariesList(): Promise<string[]> {
21
- const monomerLibHelper: IMonomerLibHelper = await grok.functions.call('Bio:getMonomerLibHelper', {});
22
- const monomerFileManager: IMonomerLibFileManager = await monomerLibHelper.getFileManager();
23
- return monomerFileManager.getValidLibraryPaths();
24
- }
25
-
26
- export async function getEnumeration(helmString: string, helmSelections: number[], screenLibrary: string):
27
- Promise<string[]> {
28
- const variableMonomers = await getAvaialableMonomers(screenLibrary);
29
- const chain: Chain = Chain.fromHelm(helmString);
30
- const size = helmSelections.length*variableMonomers.length;
31
- const enumerations = new Array<string>(size);
32
-
33
- for (let i = 0; i < helmSelections.length; i++) {
34
- for (let j = 0; j < variableMonomers.length; j++)
35
- enumerations[i*variableMonomers.length + j] = chain.getHelmChanged(helmSelections[i], variableMonomers[j]);
36
- }
37
-
38
- return enumerations;
39
- }
40
-
41
- export class HelmInput {
42
- webEditorHost: HTMLDivElement | null;
43
- webEditorApp: org.helm.IWebEditorApp | null;
44
- helmHelper: IHelmHelper;
45
- editor: IHelmWebEditor;
46
- subs: Unsubscribable[];
47
-
48
- helmString: string = PT_HELM_EXAMPLE;
49
- helmSelection: number[];
50
-
51
- constructor(
52
- helmHelper: IHelmHelper, editor: IHelmWebEditor) {
53
- this.helmHelper = helmHelper;
54
- this.editor = editor;
55
-
56
- this.webEditorHost = null;
57
- this.webEditorApp = null;
58
- const subs: Unsubscribable[] = [];
59
-
60
- subs.push(fromEvent<MouseEvent>(editor.host, 'click').subscribe(() => {
61
- this.webEditorHost = ui.div();
62
- //TODO: use not hh, but anything from editor.getHelm(true)
63
- this.webEditorApp = helmHelper.createWebEditorApp(this.webEditorHost, this.getHelmString());
64
- const dlg = ui.dialog({showHeader: false, showFooter: true})
65
- .add(this.webEditorHost!)
66
- .onOK(() => {
67
- try {
68
- const webEditorValue = this.webEditorApp!.canvas.getHelm(true)
69
- .replace(/<\/span>/g, '').replace(/<span style='background:#bbf;'>/g, '');
70
- editor.editor.setHelm(webEditorValue);
71
- this.helmString = webEditorValue;
72
- this.helmSelection = [];
73
-
74
- //@ts-ignore
75
- const selection = this.webEditorApp?.canvas.helm.jsd.m.atoms;
76
- for (let i = 0; i < selection.length; i++) {
77
- if (selection[i].selected)
78
- this.helmSelection.push(i);
79
- }
80
- } catch (err: any) {
81
- //this.logger.error(err);
82
- } finally {
83
- $(this.webEditorHost).empty();
84
- this.webEditorHost = null;
85
- this.webEditorApp = null;
86
- }
87
- })
88
- .onCancel(() => {
89
- $(this.webEditorHost).empty();
90
- this.webEditorHost = null;
91
- this.webEditorApp = null;
92
- })
93
- .show({modal: true, fullScreen: true});
94
- }));
95
- }
96
-
97
- static async init() {
98
- const helmHelper = await getHelmHelper();
99
-
100
- const editor = helmHelper.createHelmWebEditor();
101
- editor.host.style.width = '200px';
102
- editor.host.style.height = '100px';
103
- editor.host.style.paddingLeft = '40px';
104
-
105
- const cell = grok.shell.tv.dataFrame.currentCell;
106
-
107
- if (cell.column.semType === DG.SEMTYPE.MACROMOLECULE && cell.column.tags[DG.TAGS.UNITS] === NOTATION.HELM)
108
- editor.editor.setHelm(cell.value);
109
- else
110
- editor.editor.setHelm(PT_HELM_EXAMPLE);
111
-
112
- return new HelmInput(helmHelper, editor);
113
- }
114
-
115
- getHelmString(): string {
116
- return this.helmString;
117
- }
118
-
119
- getHelmSelections() {
120
- return this.helmSelection;
121
- }
122
-
123
- setHelmString(helm: string): void {
124
- this.helmString = helm;
125
- this.editor.editor.setHelm(helm);
126
- this.helmSelection = [];
127
- }
128
-
129
- getDiv(): HTMLDivElement {
130
- const title = ui.divText('Macromolecule', {style: {paddingTop: '43px', color: 'var(--grey-4)'}});
131
-
132
- return ui.divH([title, this.editor.host], {style: {paddingLeft: '48px'}});
133
- }
134
- }
135
-
136
- async function getAvaialableMonomers(screenLibrary: string): Promise<string[]> {
137
- const monomerLibHelper: IMonomerLibHelper = await grok.functions.call('Bio:getMonomerLibHelper', {});
138
- const monomerLib = await monomerLibHelper.readLibrary(LIB_PATH, screenLibrary);
139
- //NOTICE: works with Peptides only
140
- return monomerLib.getMonomerSymbolsByType('PEPTIDE');
141
- }