@datagrok/sequence-translator 1.3.4 → 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 +33 -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 +106 -17
  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 -127
@@ -3,11 +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';
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';
11
20
 
12
21
  const PT_ERROR_DATAFRAME = 'No dataframe with macromolecule columns open';
13
22
  const PT_WARNING_COLUMN = 'No marcomolecule column chosen!';
@@ -24,15 +33,15 @@ export async function getPolyToolConversionDialog(): Promise<DG.Dialog> {
24
33
  if (!targetColumns)
25
34
  throw new Error(PT_ERROR_DATAFRAME);
26
35
 
27
- const targetColumnInput = ui.columnInput(
28
- 'Column', grok.shell.t, targetColumns[0], null,
29
- {filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE}
30
- );
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
+ });
31
40
 
32
- const generateHelmChoiceInput = ui.boolInput(PT_UI_GET_HELM, true);
41
+ const generateHelmChoiceInput = ui.input.bool(PT_UI_GET_HELM, {value: true});
33
42
  ui.tooltip.bind(generateHelmChoiceInput.root, PT_UI_ADD_HELM);
34
43
 
35
- const chiralityEngineInput = ui.boolInput(PT_UI_USE_CHIRALITY, false);
44
+ const chiralityEngineInput = ui.input.bool(PT_UI_USE_CHIRALITY, {value: false});
36
45
  const ruleInputs = new RuleInputs(RULES_PATH, RULES_STORAGE_NAME, '.json');
37
46
  const rulesHeader = ui.inlineText([PT_UI_RULES_USED]);
38
47
  ui.tooltip.bind(rulesHeader, 'Add or specify rules to use');
@@ -73,42 +82,122 @@ export async function getPolyToolConversionDialog(): Promise<DG.Dialog> {
73
82
  return dialog;
74
83
  }
75
84
 
76
- export async function getPolyToolEnumerationDialog(): Promise<DG.Dialog> {
77
- 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;
78
90
 
79
- const libList = await getLibrariesList();
80
- 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});
81
93
 
94
+ helmInput.input.setAttribute('style', `min-width:250px!important;`);
82
95
  screenLibrary.input.setAttribute('style', `min-width:250px!important;`);
83
96
 
84
97
  const div = ui.div([
85
- helmInput.getDiv(),
98
+ helmInput.root,
86
99
  screenLibrary.root
87
100
  ]);
88
101
 
102
+ // Displays the molecule from a current cell (monitors changes)
103
+ const cccSubs = grok.events.onCurrentCellChanged.subscribe(() => {
104
+ const cell = grok.shell.tv.dataFrame.currentCell;
105
+
106
+ if (cell.column.semType === DG.SEMTYPE.MACROMOLECULE && cell.column.meta.units === NOTATION.HELM)
107
+ helmInput.stringValue = cell.value;
108
+ });
109
+
89
110
  const dialog = ui.dialog(PT_UI_DIALOG_ENUMERATION)
90
111
  .add(div)
91
112
  .onOK(async () => {
92
113
  try {
93
- const helmString = helmInput.getHelmString();
94
- 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();
95
118
  if (helmString === undefined || helmString === '') {
96
119
  grok.shell.warning('PolyTool: no molecule was provided');
97
120
  } else if (helmSelections === undefined || helmSelections.length < 1) {
98
121
  grok.shell.warning('PolyTool: no selection was provided');
99
122
  } else {
100
- const molecules = await getEnumeration(helmString, helmSelections, screenLibrary.value!);
123
+ const molecules = await getEnumerationHelm(helmString, helmSelections, screenLibrary.value!);
101
124
  const molCol = DG.Column.fromStrings('Enumerated', molecules);
102
125
  const df = DG.DataFrame.fromColumns([molCol]);
103
126
  grok.shell.addTableView(df);
104
127
  }
105
128
  } catch (err: any) {
106
-
129
+ defaultErrorHandler(err);
107
130
  } finally {
108
-
131
+ cccSubs.unsubscribe();
109
132
  }
110
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});
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
+ ]);
111
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);
196
+ } finally {
197
+ cccSubs.unsubscribe();
198
+ }
199
+ }).onCancel(() => {
200
+ cccSubs.unsubscribe();
112
201
  });
113
202
 
114
203
  return dialog;
@@ -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,127 +0,0 @@
1
- import * as ui from 'datagrok-api/ui';
2
- import * as grok from 'datagrok-api/grok';
3
-
4
- import {IHelmHelper, getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
5
- import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
6
- import '@datagrok-libraries/bio/src/types/helm';
7
- import '@datagrok-libraries/bio/src/types/jsdraw2';
8
- import * as org from 'org';
9
- import $ from 'cash-dom';
10
- import {Unsubscribable, fromEvent} from 'rxjs';
11
- import {IMonomerLibFileManager, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
12
-
13
- import {Chain} from './pt-conversion';
14
-
15
- const LIB_PATH = 'System:AppData/Bio/monomer-libraries/';
16
- const PT_HELM_EXAMPLE = 'PEPTIDE1{[R].[F].[T].[G].[H].[F].[G].[A].[A].[Y].[P].[E].[NH2]}$$$$';
17
-
18
- export async function getLibrariesList(): Promise<string[]> {
19
- const monomerLibHelper: IMonomerLibHelper = await grok.functions.call('Bio:getMonomerLibHelper', {});
20
- const monomerFileManager: IMonomerLibFileManager = await monomerLibHelper.getFileManager();
21
- return monomerFileManager.getValidLibraryPaths();
22
- }
23
-
24
- export async function getEnumeration(helmString: string, helmSelections: number[], screenLibrary: string):
25
- Promise<string[]> {
26
- const variableMonomers = await getAvaialableMonomers(screenLibrary);
27
- const chain: Chain = Chain.fromHelm(helmString);
28
- const size = helmSelections.length*variableMonomers.length;
29
- const enumerations = new Array<string>(size);
30
-
31
- for (let i = 0; i < helmSelections.length; i++) {
32
- for (let j = 0; j < variableMonomers.length; j++)
33
- enumerations[i*variableMonomers.length + j] = chain.getHelmChanged(helmSelections[i], variableMonomers[j]);
34
- }
35
-
36
- return enumerations;
37
- }
38
-
39
- export class HelmInput {
40
- webEditorHost: HTMLDivElement | null;
41
- webEditorApp: org.helm.IWebEditorApp | null;
42
- helmHelper: IHelmHelper;
43
- editor: IHelmWebEditor;
44
- subs: Unsubscribable[];
45
-
46
- helmString: string = PT_HELM_EXAMPLE;
47
- helmSelection: number[];
48
-
49
- constructor(
50
- helmHelper: IHelmHelper, editor: IHelmWebEditor) {
51
- this.helmHelper = helmHelper;
52
- this.editor = editor;
53
-
54
- this.webEditorHost = null;
55
- this.webEditorApp = null;
56
- const subs: Unsubscribable[] = [];
57
-
58
- subs.push(fromEvent<MouseEvent>(editor.host, 'click').subscribe(() => {
59
- this.webEditorHost = ui.div();
60
- //TODO: use not hh, but anything from editor.getHelm(true)
61
- this.webEditorApp = helmHelper.createWebEditorApp(this.webEditorHost, this.getHelmString());
62
- const dlg = ui.dialog({showHeader: false, showFooter: true})
63
- .add(this.webEditorHost!)
64
- .onOK(() => {
65
- try {
66
- const webEditorValue = this.webEditorApp!.canvas.getHelm(true)
67
- .replace(/<\/span>/g, '').replace(/<span style='background:#bbf;'>/g, '');
68
- editor.editor.setHelm(webEditorValue);
69
- this.helmString = webEditorValue;
70
- this.helmSelection = [];
71
-
72
- //@ts-ignore
73
- const selection = this.webEditorApp?.canvas.helm.jsd.m.atoms;
74
- for (let i = 0; i < selection.length; i++) {
75
- if (selection[i].selected)
76
- this.helmSelection.push(i);
77
- }
78
- } catch (err: any) {
79
- //this.logger.error(err);
80
- } finally {
81
- $(this.webEditorHost).empty();
82
- this.webEditorHost = null;
83
- this.webEditorApp = null;
84
- }
85
- })
86
- .onCancel(() => {
87
- $(this.webEditorHost).empty();
88
- this.webEditorHost = null;
89
- this.webEditorApp = null;
90
- })
91
- .show({modal: true, fullScreen: true});
92
- }));
93
- }
94
-
95
- static async init() {
96
- const helmHelper = await getHelmHelper();
97
-
98
- const editor = helmHelper.createHelmWebEditor();
99
- editor.host.style.width = '200px';
100
- editor.host.style.height = '100px';
101
- editor.host.style.paddingLeft = '40px';
102
- editor.editor.setHelm(PT_HELM_EXAMPLE);
103
-
104
- return new HelmInput(helmHelper, editor);
105
- }
106
-
107
- getHelmString(): string {
108
- return this.helmString;
109
- }
110
-
111
- getHelmSelections() {
112
- return this.helmSelection;
113
- }
114
-
115
- getDiv(): HTMLDivElement {
116
- const title = ui.divText('Macromolecule', {style: {paddingTop: '43px', color: 'var(--grey-4)'}});
117
-
118
- return ui.divH([title, this.editor.host], {style: {paddingLeft: '48px'}});
119
- }
120
- }
121
-
122
- async function getAvaialableMonomers(screenLibrary: string): Promise<string[]> {
123
- const monomerLibHelper: IMonomerLibHelper = await grok.functions.call('Bio:getMonomerLibHelper', {});
124
- const monomerLib = await monomerLibHelper.readLibrary(LIB_PATH, screenLibrary);
125
- //NOTICE: works with Peptides only
126
- return monomerLib.getMonomerSymbolsByType('PEPTIDE');
127
- }