@datagrok/sequence-translator 1.3.5 → 1.3.10

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 (38) hide show
  1. package/CHANGELOG.md +37 -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/const.ts +8 -5
  10. package/src/apps/pattern/model/data-manager.ts +44 -16
  11. package/src/apps/pattern/model/event-bus.ts +2 -0
  12. package/src/apps/pattern/model/translator.ts +45 -8
  13. package/src/apps/pattern/model/types.ts +8 -6
  14. package/src/apps/pattern/view/components/bulk-convert/column-input.ts +4 -10
  15. package/src/apps/pattern/view/components/bulk-convert/table-input.ts +5 -8
  16. package/src/apps/pattern/view/components/edit-block-controls.ts +6 -15
  17. package/src/apps/pattern/view/components/load-block-controls.ts +11 -10
  18. package/src/apps/pattern/view/components/numeric-label-visibility-controls.ts +4 -5
  19. package/src/apps/pattern/view/components/right-section.ts +50 -1
  20. package/src/apps/pattern/view/components/strand-editor/header-controls.ts +2 -2
  21. package/src/apps/pattern/view/components/strand-editor/strand-controls.ts +2 -2
  22. package/src/apps/pattern/view/components/terminal-modification-editor.ts +1 -1
  23. package/src/apps/pattern/view/components/translation-examples-block.ts +1 -1
  24. package/src/apps/pattern/view/ui.ts +1 -1
  25. package/src/apps/structure/view/ui.ts +5 -5
  26. package/src/apps/translator/view/ui.ts +15 -27
  27. package/src/package.ts +52 -11
  28. package/src/plugins/mermade.ts +1 -1
  29. package/src/polytool/pt-conversion.ts +2 -2
  30. package/src/polytool/pt-dialog.ts +99 -18
  31. package/src/polytool/pt-enumeration-chem.ts +105 -0
  32. package/src/polytool/pt-enumeration-helm.ts +22 -0
  33. package/src/polytool/pt-ui.ts +25 -0
  34. package/src/polytool/utils.ts +34 -3
  35. package/src/utils/context-menu.ts +57 -0
  36. package/src/utils/err-info.ts +13 -0
  37. package/webpack.config.js +2 -4
  38. package/src/polytool/pt-enumeration.ts +0 -141
@@ -47,13 +47,12 @@ class TranslatorAppLayout {
47
47
  this.moleculeImgDiv.style.marginTop = '12px';
48
48
 
49
49
  this.outputTableDiv = ui.div([]);
50
- this.formatChoiceInput = ui.choiceInput('', DEFAULT_FORMATS.HELM, this.inputFormats, async () => {
50
+ this.formatChoiceInput = ui.input.choice('', {value: DEFAULT_FORMATS.HELM, items: this.inputFormats, onValueChanged: async () => {
51
51
  this.format = this.formatChoiceInput.value;
52
52
  this.updateTable();
53
53
  await this.updateMolImg();
54
- });
55
- this.sequenceInputBase = ui.textInput('', DEFAULT_AXOLABS_INPUT,
56
- () => { this.onInput.next(); });
54
+ }});
55
+ this.sequenceInputBase = ui.input.textArea('', {value: DEFAULT_AXOLABS_INPUT, onValueChanged: () => { this.onInput.next(); }});
57
56
 
58
57
  this.init();
59
58
 
@@ -100,18 +99,12 @@ class TranslatorAppLayout {
100
99
 
101
100
  const tableControlsManager = new TableControlsManager(this.eventBus);
102
101
  const tableControls = tableControlsManager.createUIComponents();
103
- const inputFormats = ui.choiceInput(
104
- 'Input format',
105
- DEFAULT_FORMATS.AXOLABS,
106
- this.inputFormats,
107
- (value: string) => this.eventBus.selectInputFormat(value)
102
+ const inputFormats = ui.input.choice('Input format', {value: DEFAULT_FORMATS.AXOLABS,
103
+ items: this.inputFormats, onValueChanged: (input) => this.eventBus.selectInputFormat(input.value)}
108
104
  );
109
105
 
110
- const outputFormats = ui.choiceInput(
111
- 'Output format',
112
- NUCLEOTIDES_FORMAT,
113
- getSupportedTargetFormats(this.th),
114
- (value: string) => this.eventBus.selectOutputFormat(value)
106
+ const outputFormats = ui.input.choice('Output format', {value: NUCLEOTIDES_FORMAT,
107
+ items: getSupportedTargetFormats(this.th), onValueChanged: (input) => this.eventBus.selectOutputFormat(input.value)}
115
108
  );
116
109
  const convertBulkButton = this.createConvertBulkButton();
117
110
 
@@ -169,7 +162,7 @@ class TranslatorAppLayout {
169
162
  if (outputFormat === NUCLEOTIDES_FORMAT || outputFormat === DEFAULT_FORMATS.HELM) {
170
163
  translatedColumn.semType = DG.SEMTYPE.MACROMOLECULE;
171
164
  const units = outputFormat == NUCLEOTIDES_FORMAT ? NOTATION.FASTA : NOTATION.HELM;
172
- translatedColumn.setTag(DG.TAGS.UNITS, units);
165
+ translatedColumn.meta.units = units;
173
166
  const seqHandler = SeqHandler.forColumn(translatedColumn as DG.Column<string>);
174
167
  const setUnits = outputFormat == NUCLEOTIDES_FORMAT ? SeqHandler.setUnitsToFastaColumn :
175
168
  SeqHandler.setUnitsToHelmColumn;
@@ -381,16 +374,13 @@ class TableInputManager {
381
374
  private createTableInput(): DG.InputBase<DG.DataFrame | null> {
382
375
  const currentlySelectedTable = this.eventBus.getSelectedTable();
383
376
 
384
- const tableInput = ui.tableInput(
385
- 'Table',
386
- currentlySelectedTable,
387
- this.availableTables,
388
- (table: DG.DataFrame) => {
377
+ const tableInput = ui.input.table('Table', {value: currentlySelectedTable!, items: this.availableTables,
378
+ onValueChanged: (input) => {
389
379
  // WARNING: non-null check necessary to prevent resetting columns to
390
380
  // null upon handling onTableAdded
391
- if (table !== null && table instanceof DG.DataFrame)
392
- this.eventBus.selectTable(table);
393
- });
381
+ if (input.value !== null)
382
+ this.eventBus.selectTable(input.value);
383
+ }});
394
384
  return tableInput;
395
385
  }
396
386
 
@@ -459,10 +449,8 @@ class ColumnInputsManager {
459
449
  const selectedColumnName = matchingColumnName ? matchingColumnName : columnNames[0];
460
450
  this.selectColumnIfTableNotNull(selectedTable, selectedColumnName, columnLabel);
461
451
 
462
- const input = ui.choiceInput(
463
- `${columnLabel}`,
464
- selectedColumnName, columnNames,
465
- (colName: string) => this.selectColumnIfTableNotNull(selectedTable, colName, columnLabel)
452
+ const input = ui.input.choice(`${columnLabel}`, {value: selectedColumnName, items: columnNames,
453
+ onValueChanged: (input) => this.selectColumnIfTableNotNull(selectedTable, input.value, columnLabel)}
466
454
  );
467
455
 
468
456
  return input;
package/src/package.ts CHANGED
@@ -16,10 +16,12 @@ import {demoOligoPatternUI, demoOligoStructureUI, demoOligoTranslatorUI} from '.
16
16
  import {getExternalAppViewFactories} from './plugins/mermade';
17
17
 
18
18
  //polytool specific
19
- import {getPolyToolConversionDialog, getPolyToolEnumerationDialog} from './polytool/pt-dialog';
19
+ import {getPolyToolConversionDialog} from './polytool/pt-dialog';
20
20
  import {_setPeptideColumn} from './polytool/utils';
21
21
  import {PolyToolCsvLibHandler} from './polytool/csv-to-json-monomer-lib-converter';
22
22
  import {ITranslationHelper} from './types';
23
+ import {polyToolEnumerateHelmUI, polyToolEnumerateChemUI} from './polytool/pt-ui';
24
+ import {addContextMenuUI} from './utils/context-menu';
23
25
 
24
26
  export const _package: OligoToolkitPackage = new OligoToolkitPackage();
25
27
 
@@ -163,19 +165,20 @@ export async function polyToolConvert(): Promise<void> {
163
165
  }
164
166
  }
165
167
 
166
- //top-menu: Bio | Convert | PolyTool-Enumerate
167
- //name: polyToolEnumerate
168
+ //top-menu: Bio | Convert | PolyTool-Enumerate HELM
169
+ //name: polyToolEnumerateHelm
168
170
  //description: Perform cyclization of polymers
169
- export async function polyToolEnumerate(): Promise<void> {
170
- let dialog: DG.Dialog;
171
- try {
172
- dialog = await getPolyToolEnumerationDialog();
173
- dialog.show();
174
- } catch (err: any) {
175
- grok.shell.warning('To run PolyTool Enumeration, sketch the macromolecule and select monomers to vary');
176
- }
171
+ export async function polyToolEnumerateHelm(): Promise<void> {
172
+ polyToolEnumerateHelmUI();
177
173
  }
178
174
 
175
+ // //top-menu: Bio | Convert | PolyTool-Enumerate Chem
176
+ // //name: polyToolEnumerateChem
177
+ // //description: Perform cyclization of polymers
178
+ // export async function polyToolEnumerateChem(): Promise<void> {
179
+ // polyToolEnumerateChemUI();
180
+ // }
181
+
179
182
  //name: polyToolColumnChoice
180
183
  //input: dataframe df [Input data table]
181
184
  //input: column macroMolecule
@@ -194,3 +197,41 @@ export async function createMonomerLibraryForPolyTool(file: DG.FileInfo) {
194
197
  const jsonFileContent = JSON.stringify(libObject, null, 2);
195
198
  DG.Utils.download(jsonFileName, jsonFileContent);
196
199
  }
200
+
201
+ // -- Handle context menu --
202
+
203
+ //name: addContextMenu
204
+ //input: object event
205
+ export function addContextMenu(event: DG.EventData): void {
206
+ addContextMenuUI(event);
207
+ }
208
+
209
+ // //name: PolyTool Converter
210
+ // //meta.icon: img/icons/structure.png
211
+ // //meta.browsePath: PolyTool
212
+ // //tags: app
213
+ // //output: view v
214
+ // export async function ptConverterApp(): Promise<DG.ViewBase> {
215
+ // const view = await getSpecifiedAppView(APP_NAME.STRUCTURE);
216
+ // return view;
217
+ // }
218
+
219
+ // //name: PolyTool Enumerator Helm
220
+ // //meta.icon: img/icons/structure.png
221
+ // //meta.browsePath: PolyTool
222
+ // //tags: app
223
+ // //output: view v
224
+ // export async function ptEnumeratorHelmApp(): Promise<DG.ViewBase> {
225
+ // const view = await getSpecifiedAppView(APP_NAME.STRUCTURE);
226
+ // return view;
227
+ // }
228
+
229
+ // //name: PolyTool Enumerator Chem
230
+ // //meta.icon: img/icons/structure.png
231
+ // //meta.browsePath: PolyTool
232
+ // //tags: app
233
+ // //output: view v
234
+ // export async function ptEnumeratorChemApp(): Promise<DG.ViewBase> {
235
+ // const view = await getSpecifiedAppView(APP_NAME.STRUCTURE);
236
+ // return view;
237
+ // }
@@ -41,7 +41,7 @@ export async function getExternalAppViewFactories(
41
41
  }
42
42
 
43
43
  function getMerMadeParameters(th: ITranslationHelper): { [name: string]: any } {
44
- const base = ui.textInput('', '');
44
+ const base = ui.input.textArea('', {value: ''});
45
45
  const input = new ColoredTextInput(base, th.highlightInvalidSubsequence);
46
46
 
47
47
  return {
@@ -10,7 +10,7 @@ export const RULES_DIMER = '(#2)';
10
10
  export const RULES_HETERODIMER = '($2)';
11
11
 
12
12
  function addCommonTags(col: DG.Column): void {
13
- col.setTag('quality', DG.SEMTYPE.MACROMOLECULE);
13
+ col.semType = DG.SEMTYPE.MACROMOLECULE;
14
14
  col.setTag('aligned', ALIGNMENT.SEQ);
15
15
  col.setTag('alphabet', ALPHABET.PT);
16
16
  }
@@ -290,7 +290,7 @@ export async function addTransformedColumn(
290
290
  const targetHelmCol = DG.Column.fromList('string', helmColName, targetList);
291
291
 
292
292
  addCommonTags(targetHelmCol);
293
- targetHelmCol.setTag('units', NOTATION.HELM);
293
+ targetHelmCol.meta.units = NOTATION.HELM;
294
294
 
295
295
  if (addHelm) {
296
296
  targetHelmCol.setTag('cell.renderer', 'helm');
@@ -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
+ }