@datagrok/sequence-translator 1.3.14 → 1.3.15

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 (31) hide show
  1. package/CHANGELOG.md +23 -1
  2. package/dist/package-test.js +1 -1
  3. package/dist/package-test.js.map +1 -1
  4. package/dist/package.js +1 -1
  5. package/dist/package.js.map +1 -1
  6. package/files/polytool-rules/rules_example.json +34 -34
  7. package/files/samples/cyclized.csv +6 -0
  8. package/package.json +9 -10
  9. package/src/apps/common/view/components/colored-input/colored-text-input.ts +2 -2
  10. package/src/apps/pattern/view/components/bulk-convert/column-input.ts +2 -2
  11. package/src/apps/pattern/view/components/bulk-convert/table-input.ts +8 -6
  12. package/src/apps/pattern/view/components/edit-block-controls.ts +5 -5
  13. package/src/apps/pattern/view/components/load-block-controls.ts +7 -3
  14. package/src/apps/pattern/view/components/numeric-label-visibility-controls.ts +1 -1
  15. package/src/apps/pattern/view/components/strand-editor/header-controls.ts +2 -2
  16. package/src/apps/pattern/view/components/strand-editor/strand-controls.ts +2 -2
  17. package/src/apps/pattern/view/components/terminal-modification-editor.ts +1 -1
  18. package/src/apps/structure/view/ui.ts +5 -5
  19. package/src/apps/translator/view/ui.ts +27 -18
  20. package/src/package-test.ts +1 -0
  21. package/src/package.ts +34 -12
  22. package/src/polytool/pt-conversion.ts +2 -33
  23. package/src/polytool/pt-convert-editor.ts +116 -0
  24. package/src/polytool/pt-dialog.ts +177 -97
  25. package/src/polytool/pt-enumeration-helm-dialog.ts +338 -282
  26. package/src/polytool/pt-enumeration-helm.ts +6 -2
  27. package/src/polytool/pt-placeholders-input.ts +1 -2
  28. package/src/polytool/utils.ts +0 -7
  29. package/src/tests/polytool-convert-tests.ts +99 -0
  30. package/src/tests/polytool-enumerate-tests.ts +21 -5
  31. package/src/utils/context-menu.ts +7 -10
@@ -13,13 +13,16 @@ import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/mon
13
13
  import {HelmType, ISeqMonomer} from '@datagrok-libraries/bio/src/helm/types';
14
14
  import {helmTypeToPolymerType} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
15
15
  import {getSeqHelper, ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
16
+ import '@datagrok-libraries/bio/src/types/input';
16
17
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
18
+ import {InputColumnBase} from '@datagrok-libraries/bio/src/types/input';
19
+ import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
17
20
 
18
21
  import {
19
22
  PolyToolEnumeratorParams, PolyToolEnumeratorType, PolyToolEnumeratorTypes
20
23
  } from './types';
21
24
  import {getLibrariesList} from './utils';
22
- import {getPtEnumeratorHelm, PT_HELM_EXAMPLE} from './pt-enumeration-helm';
25
+ import {doPolyToolEnumerateHelm, PT_HELM_EXAMPLE} from './pt-enumeration-helm';
23
26
  import {PolyToolPlaceholdersInput} from './pt-placeholders-input';
24
27
  import {defaultErrorHandler} from '../utils/err-info';
25
28
  import {PT_UI_DIALOG_ENUMERATION} from './const';
@@ -27,12 +30,21 @@ import {PT_UI_DIALOG_ENUMERATION} from './const';
27
30
  import {_package} from '../package';
28
31
 
29
32
  type PolyToolEnumerateInputs = {
30
- enumeratorType: DG.ChoiceInput<PolyToolEnumeratorType>
31
33
  macromolecule: HelmInputBase;
32
34
  placeholders: PolyToolPlaceholdersInput;
35
+ enumeratorType: DG.ChoiceInput<PolyToolEnumeratorType>
36
+ trivialNameCol: InputColumnBase,
33
37
  toAtomicLevel: DG.InputBase<boolean>;
34
38
  keepOriginal: DG.InputBase<boolean>;
35
- /** Trivial names source column */ trivialNameCol: DG.InputBase<DG.Column<string> | null>,
39
+ };
40
+
41
+ type PolyToolEnumerateSerialized = {
42
+ macromolecule: string;
43
+ placeholders: string;
44
+ enumeratorType: PolyToolEnumeratorType;
45
+ trivialNameCol: string;
46
+ toAtomicLevel: boolean;
47
+ keepOriginal: boolean;
36
48
  };
37
49
 
38
50
  export async function polyToolEnumerateHelmUI(cell?: DG.Cell): Promise<void> {
@@ -40,7 +52,10 @@ export async function polyToolEnumerateHelmUI(cell?: DG.Cell): Promise<void> {
40
52
  const maxHeight = window.innerHeight;
41
53
 
42
54
  try {
55
+ let dialog: DG.Dialog;
43
56
  const resizeInputs = () => {
57
+ if (dialog == null) return;
58
+
44
59
  const dialogContentEl = $(dialog.root).find('div.d4-dialog-contents').get(0)! as HTMLElement;
45
60
  const contentHeight = dialogContentEl.clientHeight;
46
61
 
@@ -60,7 +75,7 @@ export async function polyToolEnumerateHelmUI(cell?: DG.Cell): Promise<void> {
60
75
  }
61
76
  });
62
77
  };
63
- const [dialog, inputs] = await getPolyToolEnumerateDialog(cell, resizeInputs);
78
+ dialog = await getPolyToolEnumerateDialog(cell, resizeInputs);
64
79
 
65
80
  let isFirstShow = true;
66
81
  ui.onSizeChanged(dialog.root).subscribe(() => {
@@ -87,329 +102,370 @@ export async function polyToolEnumerateHelmUI(cell?: DG.Cell): Promise<void> {
87
102
 
88
103
  resizeInputs();
89
104
  });
105
+ resizeInputs();
90
106
 
91
107
  _package.logger.debug('PolyToolEnumerateHelmUI: dialog before show');
92
108
  const res = dialog.show({width: Math.max(350, maxWidth * 0.7), /* center: true,*/ resizable: true});
93
109
  _package.logger.debug('PolyToolEnumerateHelmUI: dialog after show');
94
- const k = 42;
95
- } catch (_err: any) {
110
+ } catch (err: any) {
111
+ const [errMsg, errStack] = errInfo(err);
96
112
  grok.shell.warning('To run PolyTool Enumeration, sketch the macromolecule and select monomers to vary');
113
+ _package.logger.error(errMsg, undefined, errStack);
97
114
  }
98
115
  }
99
116
 
100
117
 
101
118
  async function getPolyToolEnumerateDialog(
102
119
  cell?: DG.Cell, resizeInputs?: () => void
103
- ): Promise<[DG.Dialog, PolyToolEnumerateInputs]> {
120
+ ): Promise<DG.Dialog> {
104
121
  const logPrefix = `ST: PT: HelmDialog()`;
105
- const monomerLib = (await getMonomerLibHelper()).getMonomerLib();
106
- const seqHelper = await getSeqHelper();
107
-
108
- const [libList, helmHelper] = await Promise.all([getLibrariesList(), getHelmHelper()]);
109
-
110
- const helmValue = (cell && cell.rowIndex >= 0) ? cell.value : PT_HELM_EXAMPLE;
111
-
112
- const macromoleculeInput = helmHelper.createHelmInput(
113
- 'Macromolecule', {value: helmValue, editable: false});
114
-
115
- const createTrivialNameColInput = (cell?: DG.Cell): DG.InputBase<DG.Column<string> | null> => {
116
- return ui.input.column(
117
- 'Trivial name', {
118
- table: cell?.dataFrame,
119
- filter: (col: DG.Column): boolean => {
120
- return col.type === DG.COLUMN_TYPE.STRING && col != cell?.column; /* id */
121
- },
122
- onValueChanged: (): void => {
123
- const valueCol = inputs.trivialNameCol.value;
124
- let newSrcId: typeof srcId = null;
125
- if (cell && valueCol) {
126
- const originalId = valueCol.get(cell.rowIndex)!;
127
- newSrcId = {value: originalId, colName: valueCol.name};
128
- }
129
- srcId = newSrcId;
130
- trivialNameSampleDiv.textContent = srcId ? `Original ID: ${srcId.value}` : '';
131
- },
132
- });
133
- };
134
-
135
- let srcId: { value: string, colName: string } | null = null;
136
- const trivialNameSampleDiv = ui.divText('', {style: {marginLeft: '8px', marginTop: '2px'}});
137
- const warningsTextDiv = ui.divText('', {style: {color: 'red'}});
138
- const inputs: PolyToolEnumerateInputs = {
139
- enumeratorType: ui.input.choice<PolyToolEnumeratorType>(
140
- 'Enumerator type', {
141
- value: PolyToolEnumeratorTypes.Single,
142
- items: Object.values(PolyToolEnumeratorTypes)
143
- }) as DG.ChoiceInput<PolyToolEnumeratorType>,
144
- macromolecule: macromoleculeInput,
145
-
146
- placeholders: await PolyToolPlaceholdersInput.create(
147
- 'Placeholders', {
148
- showAddNewRowIcon: true,
149
- showRemoveRowIcon: true,
150
- showRowHeader: false,
151
- showCellTooltip: false,
152
- }/*, 2/**/),
153
- toAtomicLevel: ui.input.bool(
154
- 'To atomic level', {value: false}),
155
- keepOriginal: ui.input.bool(
156
- 'Keep original', {value: false}),
157
- trivialNameCol: createTrivialNameColInput(cell),
158
- // warnings: ui.input.textArea('' +
159
- // 'Warnings', {value: ''}),
160
- };
161
- const elementList = [
162
- inputs.toAtomicLevel,
163
- inputs.placeholders
164
- ];
165
-
166
- inputs.trivialNameCol.addOptions(trivialNameSampleDiv);
167
- // inputs.warnings.readOnly = true;
168
-
169
- let placeholdersValidity: string | null = null;
170
- inputs.placeholders.addValidator((value: string): string | null => {
171
- try {
172
- const missedMonomerList: ISeqMonomer[] = [];
173
- for (const [posVal, monomerSymbolList] of Object.entries(inputs.placeholders.placeholdersValue)) {
174
- const pos = parseInt(posVal);
175
- const a = inputs.macromolecule.molValue.atoms[pos];
176
- const helmType: HelmType = a.biotype()!;
177
- const polymerType = helmTypeToPolymerType(helmType);
178
- for (const symbol of monomerSymbolList) {
179
- const substituteMonomer = monomerLib.getMonomer(polymerType, symbol)!;
180
- // TODO: Check substitution monomer is presented in the library
181
- if (!substituteMonomer || !substituteMonomer.lib)
182
- missedMonomerList.push({polymerType, symbol});
183
- }
184
- }
185
-
186
- const byType: { [polymerType: string]: string[] } = {};
187
- for (const sm of missedMonomerList) {
188
- let byTypeList = byType[sm.polymerType];
189
- if (!byTypeList) byTypeList = byType[sm.polymerType] = [];
190
- byTypeList.push(sm.symbol);
191
- }
192
- const byTypeStr: string = Object.entries(byType)
193
- .map(([polymerType, symbolList]) => `${polymerType}: ${symbolList.join(', ')}`)
194
- .join('\n');
195
- placeholdersValidity = Object.keys(byTypeStr).length > 0 ?
196
- `Placeholders contain missed monomers: ${byTypeStr}` : null;
197
- } catch (err: any) {
198
- const [errMsg, errStack] = defaultErrorHandler(err, false);
199
- placeholdersValidity = errMsg;
200
- }
201
- setTimeout(() => { updateWarnings(); }, 0);
202
- return placeholdersValidity;
203
- });
204
-
122
+ let inputs: PolyToolEnumerateInputs;
205
123
  const subs: Unsubscribable[] = [];
206
124
  const destroy = () => {
207
- inputs.placeholders.detach();
208
125
  for (const sub of subs) sub.unsubscribe();
126
+ inputs.placeholders.detach();
209
127
  };
128
+ try {
129
+ const monomerLib = (await getMonomerLibHelper()).getMonomerLib();
130
+ const seqHelper = await getSeqHelper();
131
+ const emptyDf: DG.DataFrame = DG.DataFrame.fromColumns([]);
132
+
133
+ const [libList, helmHelper] = await Promise.all([getLibrariesList(), getHelmHelper()]);
134
+
135
+ let srcId: { value: string, colName: string } | null = null;
136
+ const trivialNameSampleDiv = ui.divText('', {style: {marginLeft: '8px', marginTop: '2px'}});
137
+ const warningsTextDiv = ui.divText('', {style: {color: 'red'}});
138
+ inputs = {
139
+ enumeratorType: ui.input.choice<PolyToolEnumeratorType>(
140
+ 'Enumerator type', {
141
+ value: PolyToolEnumeratorTypes.Single,
142
+ items: Object.values(PolyToolEnumeratorTypes)
143
+ }) as DG.ChoiceInput<PolyToolEnumeratorType>,
144
+ macromolecule: helmHelper.createHelmInput(
145
+ 'Macromolecule', {editable: false}),
146
+ placeholders: await PolyToolPlaceholdersInput.create(
147
+ 'Placeholders', {
148
+ showAddNewRowIcon: true,
149
+ showRemoveRowIcon: true,
150
+ showRowHeader: false,
151
+ showCellTooltip: false,
152
+ }/*, 2/**/),
153
+ toAtomicLevel: ui.input.bool(
154
+ 'To atomic level', {value: false}),
155
+ keepOriginal: ui.input.bool(
156
+ 'Keep original', {value: false}),
157
+ trivialNameCol: ui.input.column2(
158
+ 'Trivial name', {
159
+ table: cell?.dataFrame,
160
+ filter: (col: DG.Column): boolean => {
161
+ return col.type === DG.COLUMN_TYPE.STRING && col != cell?.column; /* id */
162
+ },
163
+ onValueChanged: (): void => {
164
+ const valueCol = inputs.trivialNameCol.value;
165
+ let newSrcId: typeof srcId = null;
166
+ if (cell && valueCol) {
167
+ const originalId = valueCol.get(cell.rowIndex)!;
168
+ newSrcId = {value: originalId, colName: valueCol.name};
169
+ }
170
+ srcId = newSrcId;
171
+ trivialNameSampleDiv.textContent = srcId ? `Original ID: ${srcId.value}` : '';
172
+ },
173
+ nullable: true,
174
+ }),
175
+ };
210
176
 
211
- subs.push(inputs.macromolecule.onMouseMove.subscribe((e: MouseEvent) => {
212
- try {
213
- _package.logger.debug(`${logPrefix}, placeholdersInput.onMouseMove()`);
177
+ inputs.trivialNameCol.addOptions(trivialNameSampleDiv);
178
+
179
+ let placeholdersValidity: string | null = null;
180
+ inputs.placeholders.addValidator((value: string): string | null => {
181
+ const errors: string[] = [];
182
+ try {
183
+ const missedMonomerList: ISeqMonomer[] = [];
184
+ for (const [posVal, monomerSymbolList] of Object.entries(inputs.placeholders.placeholdersValue)) {
185
+ const pos = parseInt(posVal);
186
+ if (pos >= inputs.macromolecule.molValue.atoms.length) {
187
+ errors.push(`There is no monomer at position ${pos + 1}.`);
188
+ continue;
189
+ }
190
+ const a = inputs.macromolecule.molValue.atoms[pos];
191
+ const helmType: HelmType = a.biotype()!;
192
+ const polymerType = helmTypeToPolymerType(helmType);
193
+ for (const symbol of monomerSymbolList) {
194
+ const substituteMonomer = monomerLib.getMonomer(polymerType, symbol)!;
195
+ // TODO: Check substitution monomer is presented in the library
196
+ if (!substituteMonomer || !substituteMonomer.lib)
197
+ missedMonomerList.push({polymerType, symbol});
198
+ }
199
+ }
214
200
 
215
- const argsX = e.offsetX;
216
- const argsY = e.offsetY;
217
- const mol = inputs.macromolecule.molValue;
218
- const hoveredAtom = helmHelper.getHoveredAtom(argsX, argsY, mol, inputs.macromolecule.root.clientHeight);
219
- if (hoveredAtom) {
220
- const hoveredAtomContIdx = hoveredAtom._parent.atoms.indexOf(hoveredAtom);
221
- const hoveredAtomContIdxStr = (hoveredAtomContIdx + 1).toString();
222
- const substitutingMonomers = inputs.placeholders.placeholdersValue[hoveredAtomContIdx];
223
-
224
- if (substitutingMonomers) {
225
- const cnt = ui.divText(substitutingMonomers.join(', '));
226
- inputs.macromolecule.showTooltip(cnt, hoveredAtom);
227
- e.preventDefault();
228
- e.stopPropagation();
201
+ const byType: { [polymerType: string]: string[] } = {};
202
+ for (const sm of missedMonomerList) {
203
+ let byTypeList = byType[sm.polymerType];
204
+ if (!byTypeList) byTypeList = byType[sm.polymerType] = [];
205
+ byTypeList.push(sm.symbol);
229
206
  }
207
+ const byTypeStr: string = Object.entries(byType)
208
+ .map(([polymerType, symbolList]) => `${polymerType}: ${symbolList.join(', ')}`)
209
+ .join('\n');
210
+ if (Object.keys(byTypeStr).length > 0)
211
+ errors.push(`Placeholders contain missed monomers: ${byTypeStr}`);
212
+ placeholdersValidity = errors.length > 0 ? errors.join('\n') : null;
213
+ } catch (err: any) {
214
+ const [errMsg, errStack] = defaultErrorHandler(err, false);
215
+ placeholdersValidity = errMsg;
230
216
  }
231
- } catch (err: any) {
232
- defaultErrorHandler(err, false);
233
- }
234
- }));
235
- subs.push(inputs.macromolecule.onClick.subscribe((e: MouseEvent) => {
236
- try {
237
- _package.logger.debug(`${logPrefix}, placeholdersInput.onClick()`);
217
+ setTimeout(() => { updateWarnings(); }, 0);
218
+ return placeholdersValidity;
219
+ });
238
220
 
239
- const argsX = e.offsetX;
240
- const argsY = e.offsetY;
241
- const mol = inputs.macromolecule.molValue;
242
- const clickedAtom = helmHelper.getHoveredAtom(argsX, argsY, mol, inputs.macromolecule.root.clientHeight);
243
- if (clickedAtom) {
244
- const clickedAtomContIdx = clickedAtom._parent.atoms.indexOf(clickedAtom);
245
- const clickedAtomContIdxStr = (clickedAtomContIdx + 1).toString();
246
-
247
- const phDf = inputs.placeholders.grid.dataFrame;
248
- const posList = phDf.columns.byName('Position').toList();
249
- let rowIdx = posList.indexOf(clickedAtomContIdxStr);
250
- if (rowIdx === -1) {
251
- rowIdx = posList.findIndex((v) => isNaN(v));
221
+ subs.push(inputs.macromolecule.onMouseMove.subscribe((e: MouseEvent) => {
222
+ try {
223
+ _package.logger.debug(`${logPrefix}, placeholdersInput.onMouseMove()`);
224
+
225
+ const argsX = e.offsetX;
226
+ const argsY = e.offsetY;
227
+ const mol = inputs.macromolecule.molValue;
228
+ const hoveredAtom = helmHelper.getHoveredAtom(argsX, argsY, mol, inputs.macromolecule.root.clientHeight);
229
+ if (hoveredAtom) {
230
+ const hoveredAtomContIdx = hoveredAtom._parent.atoms.indexOf(hoveredAtom);
231
+ const hoveredAtomContIdxStr = (hoveredAtomContIdx + 1).toString();
232
+ const substitutingMonomers = inputs.placeholders.placeholdersValue[hoveredAtomContIdx];
233
+
234
+ if (substitutingMonomers) {
235
+ const cnt = ui.divText(substitutingMonomers.join(', '));
236
+ inputs.macromolecule.showTooltip(cnt, hoveredAtom);
237
+ e.preventDefault();
238
+ e.stopPropagation();
239
+ }
240
+ }
241
+ } catch (err: any) {
242
+ defaultErrorHandler(err, false);
243
+ }
244
+ }));
245
+ subs.push(inputs.macromolecule.onClick.subscribe((e: MouseEvent) => {
246
+ try {
247
+ _package.logger.debug(`${logPrefix}, placeholdersInput.onClick()`);
248
+
249
+ const argsX = e.offsetX;
250
+ const argsY = e.offsetY;
251
+ const mol = inputs.macromolecule.molValue;
252
+ const clickedAtom = helmHelper.getHoveredAtom(argsX, argsY, mol, inputs.macromolecule.root.clientHeight);
253
+ if (clickedAtom) {
254
+ const clickedAtomContIdx = clickedAtom._parent.atoms.indexOf(clickedAtom);
255
+ const clickedAtomContIdxStr = (clickedAtomContIdx + 1).toString();
256
+
257
+ const phDf = inputs.placeholders.grid.dataFrame;
258
+ const posList = phDf.columns.byName('Position').toList();
259
+ let rowIdx = posList.indexOf(clickedAtomContIdxStr);
252
260
  if (rowIdx === -1) {
253
- rowIdx = phDf.rows.addNew([clickedAtomContIdxStr, '']).idx;
261
+ rowIdx = posList.findIndex((v) => isNaN(v));
262
+ if (rowIdx === -1) {
263
+ rowIdx = phDf.rows.addNew([clickedAtomContIdxStr, '']).idx;
264
+ }
265
+ phDf.set('Position', rowIdx, clickedAtomContIdxStr);
266
+ // const tgtCell = inputs.placeholders.grid.cell('Monomers', rowIdx);
254
267
  }
255
- phDf.set('Position', rowIdx, clickedAtomContIdxStr);
256
- // const tgtCell = inputs.placeholders.grid.cell('Monomers', rowIdx);
268
+ phDf.currentCell = phDf.cell(rowIdx, 'Monomers');
269
+ //const gridRowIdx = inputs.placeholders.grid.tableRowToGrid(rowIdx);
270
+ //const monomersGCell = inputs.placeholders.grid.cell('Monomers', gridRowIdx);
271
+ const k = 42;
257
272
  }
258
- phDf.currentCell = phDf.cell(rowIdx, 'Monomers');
259
- //const gridRowIdx = inputs.placeholders.grid.tableRowToGrid(rowIdx);
260
- //const monomersGCell = inputs.placeholders.grid.cell('Monomers', gridRowIdx);
261
- const k = 42;
273
+ } catch (err: any) {
274
+ defaultErrorHandler(err);
262
275
  }
263
- } catch (err: any) {
264
- defaultErrorHandler(err);
265
- }
266
- }));
267
- subs.push(inputs.placeholders.grid.dataFrame.onDataChanged.subscribe(() => {
268
- updateMolView();
269
- }));
270
- subs.push(fromEvent<KeyboardEvent>(inputs.placeholders.grid.root, 'keydown')
271
- .subscribe((e: KeyboardEvent) => {
272
- if (e.key === 'Enter') e.stopPropagation();
276
+ }));
277
+ subs.push(inputs.placeholders.grid.dataFrame.onDataChanged.subscribe(() => {
278
+ updateMolView();
279
+ }));
280
+ subs.push(fromEvent<KeyboardEvent>(inputs.placeholders.grid.root, 'keydown')
281
+ .subscribe((e: KeyboardEvent) => {
282
+ if (e.key === 'Enter') e.stopPropagation();
283
+ }));
284
+
285
+ // TODO: suspect
286
+ subs.push(ui.onSizeChanged(inputs.placeholders.root).subscribe(() => {
287
+ if (resizeInputs) resizeInputs();
273
288
  }));
274
289
 
275
- // TODO: suspect
276
- subs.push(ui.onSizeChanged(inputs.placeholders.root).subscribe(() => {
277
- if (resizeInputs) resizeInputs();
278
- }));
290
+ // Displays the molecule from a current cell (monitors changes)
291
+ subs.push(grok.events.onCurrentCellChanged.subscribe(() => {
292
+ const cell = grok.shell.tv.dataFrame.currentCell;
293
+ if (cell.column.semType !== DG.SEMTYPE.MACROMOLECULE) return;
279
294
 
280
- // Displays the molecule from a current cell (monitors changes)
281
- subs.push(grok.events.onCurrentCellChanged.subscribe(() => {
282
- const cell = grok.shell.tv.dataFrame.currentCell;
295
+ fillForCurrentCell(cell);
296
+ }));
283
297
 
284
- if (cell.column.semType === DG.SEMTYPE.MACROMOLECULE && cell.column.meta.units === NOTATION.HELM)
285
- inputs.macromolecule.stringValue = cell.value;
298
+ inputs.macromolecule.root.style.setProperty('min-width', '250px', 'important');
299
+ // inputs.macromolecule.root.style.setProperty('max-height', '300px', 'important');
286
300
 
287
- fillTrivialNameList(cell);
288
- }));
301
+ const updateMolView = () => {
302
+ const mol = inputs.macromolecule.molValue;
303
+ for (let aI = 0; aI < mol.atoms.length; aI++) {
304
+ const a = mol.atoms[aI];
305
+ a.highlighted = aI in inputs.placeholders.placeholdersValue;
306
+ }
307
+ inputs.macromolecule.redraw();
308
+ };
289
309
 
290
- inputs.macromolecule.root.style.setProperty('min-width', '250px', 'important');
291
- // inputs.macromolecule.root.style.setProperty('max-height', '300px', 'important');
310
+ const updateWarnings = () => {
311
+ const warnings = placeholdersValidity;
312
+ // const iw = inputs.warnings;
313
+ const w = warningsTextDiv;
314
+ if (!!warnings) {
315
+ // iw.value = warnings; // <- breaks dialog resize
316
+ // iw.enabled = true;
317
+ // iw.root.style.removeProperty('display');
318
+
319
+ w.innerText = warnings;
320
+ w.style.removeProperty('display');
321
+ } else {
322
+ // iw.value = ''; // <- breaks dialog resize
323
+ // iw.enabled = false;
324
+ // iw.root.style.setProperty('display', 'none');
325
+
326
+ w.innerText = '';
327
+ w.style.setProperty('display', 'none');
328
+ }
329
+ //resizeInputs();
330
+ };
292
331
 
293
- const updateMolView = () => {
294
- const mol = inputs.macromolecule.molValue;
295
- for (let aI = 0; aI < mol.atoms.length; aI++) {
296
- const a = mol.atoms[aI];
297
- a.highlighted = aI in inputs.placeholders.placeholdersValue;
298
- }
299
- inputs.macromolecule.redraw();
300
- };
332
+ const fillTrivialNameList = (table?: DG.DataFrame) => {
333
+ // const colList: DG.Column[] = [];
334
+ // const colCount: number = cell.dataFrame.columns.length;
335
+ //
336
+ // // TODO: by semType?
337
+ // for (let colI: number = 0; colI < colCount; ++colI) {
338
+ // const col = cell.dataFrame.columns.byIndex(colI);
339
+ // if (col.type === DG.COLUMN_TYPE.STRING) colList.push(col);
340
+ // }
341
+
342
+ if (table) {
343
+ inputs.trivialNameCol.setColumnInputTable(table);
344
+ inputs.trivialNameCol.root.style.removeProperty('display');
345
+ } else {
346
+ inputs.trivialNameCol.setColumnInputTable(emptyDf);
347
+ inputs.trivialNameCol.root.style.setProperty('display', 'none');
348
+ }
349
+ if (resizeInputs) resizeInputs();
350
+ };
301
351
 
302
- const updateWarnings = () => {
303
- const warnings = placeholdersValidity;
304
- // const iw = inputs.warnings;
305
- const w = warningsTextDiv;
306
- if (!!warnings) {
307
- // iw.value = warnings; // <- breaks dialog resize
308
- // iw.enabled = true;
309
- // iw.root.style.removeProperty('display');
310
-
311
- w.innerText = warnings;
312
- w.style.removeProperty('display');
313
- } else {
314
- // iw.value = ''; // <- breaks dialog resize
315
- // iw.enabled = false;
316
- // iw.root.style.setProperty('display', 'none');
317
-
318
- w.innerText = '';
319
- w.style.setProperty('display', 'none');
320
- }
321
- //resizeInputs();
322
- };
352
+ const fillForCurrentCell = async (cell?: DG.Cell): Promise<void> => {
353
+ let helmValue: string;
354
+ let table: DG.DataFrame | undefined = undefined;
355
+ if (cell && cell.rowIndex >= 0 && cell?.column.semType == DG.SEMTYPE.MACROMOLECULE) {
356
+ const sh = SeqHandler.forColumn(cell.column);
357
+ helmValue = await sh.getHelm(cell.rowIndex);
358
+ table = cell.dataFrame;
359
+ } else {
360
+ helmValue = PT_HELM_EXAMPLE;
361
+ }
323
362
 
324
- const fillTrivialNameList = (cell: DG.Cell) => {
325
- // const colList: DG.Column[] = [];
326
- // const colCount: number = cell.dataFrame.columns.length;
327
- //
328
- // // TODO: by semType?
329
- // for (let colI: number = 0; colI < colCount; ++colI) {
330
- // const col = cell.dataFrame.columns.byIndex(colI);
331
- // if (col.type === DG.COLUMN_TYPE.STRING) colList.push(col);
332
- // }
333
-
334
- // TODO: Change table column items in inputs.trivialName
335
- inputs.trivialNameCol = createTrivialNameColInput(cell);
336
- };
363
+ inputs.macromolecule.stringValue = helmValue;
364
+ fillTrivialNameList(table);
365
+ };
337
366
 
338
- const execDialog = async (): Promise<void> => {
339
- try {
340
- const srcHelm = inputs.macromolecule.stringValue;
341
- const helmSelections: number[] = wu.enumerate<HelmAtom>(inputs.macromolecule.molValue.atoms)
342
- .filter(([a, aI]) => a.highlighted)
343
- .map(([a, aI]) => aI).toArray();
344
- if (srcHelm === undefined || srcHelm === '') {
345
- grok.shell.warning('PolyTool: no molecule was provided');
346
- } else /* if (helmSelections === undefined || helmSelections.length < 1) {
367
+ await fillForCurrentCell(cell);
368
+
369
+ const exec = async (): Promise<void> => {
370
+ try {
371
+ const srcHelm = inputs.macromolecule.stringValue;
372
+ const helmSelections: number[] = wu.enumerate<HelmAtom>(inputs.macromolecule.molValue.atoms)
373
+ .filter(([a, aI]) => a.highlighted)
374
+ .map(([a, aI]) => aI).toArray();
375
+ if (srcHelm === undefined || srcHelm === '') {
376
+ grok.shell.warning('PolyTool: no molecule was provided');
377
+ } else /* if (helmSelections === undefined || helmSelections.length < 1) {
347
378
  grok.shell.warning('PolyTool: no selection was provided');
348
379
  } else /**/ {
349
- if (Object.keys(inputs.placeholders.placeholdersValue).length === 0) {
350
- grok.shell.warning(`${PT_UI_DIALOG_ENUMERATION}: placeholders are empty`);
351
- return;
380
+ if (Object.keys(inputs.placeholders.placeholdersValue).length === 0) {
381
+ grok.shell.warning(`${PT_UI_DIALOG_ENUMERATION}: placeholders are empty`);
382
+ return;
383
+ }
384
+ await getHelmHelper(); // initializes JSDraw and org
385
+ const params: PolyToolEnumeratorParams = {
386
+ type: inputs.enumeratorType.value!,
387
+ placeholders: inputs.placeholders.placeholdersValue,
388
+ keepOriginal: inputs.keepOriginal.value,
389
+ };
390
+ const enumeratorResDf = await polyToolEnumerateHelm(srcHelm, srcId, params, inputs.toAtomicLevel.value, seqHelper);
391
+ grok.shell.addTableView(enumeratorResDf);
352
392
  }
353
- await getHelmHelper(); // initializes JSDraw and org
354
- const params: PolyToolEnumeratorParams = {
355
- type: inputs.enumeratorType.value!,
356
- placeholders: inputs.placeholders.placeholdersValue,
357
- keepOriginal: inputs.keepOriginal.value,
358
- };
359
- const enumeratorResDf = await enumerateHelm(srcHelm, srcId, params, inputs.toAtomicLevel.value, seqHelper);
360
- grok.shell.addTableView(enumeratorResDf);
393
+ } catch (err: any) {
394
+ defaultErrorHandler(err);
361
395
  }
362
- } catch (err: any) {
363
- defaultErrorHandler(err);
364
- } finally {
365
- destroy();
366
- }
367
- };
396
+ };
368
397
 
369
- const dialog = ui.dialog({title: PT_UI_DIALOG_ENUMERATION, showFooter: true})
370
- .add(inputs.macromolecule)
371
- .add(inputs.placeholders)
372
- .add(inputs.enumeratorType)
373
- .add(inputs.trivialNameCol)
374
- .add(inputs.toAtomicLevel)
375
- .add(inputs.keepOriginal)
376
- .add(warningsTextDiv)
377
- // .addButton('Enumerate', () => {
378
- // execDialog()
379
- // .then(() => {});
380
- // }, 0, 'Keeps the dialog open')
381
- .onOK(() => {
382
- execDialog()
383
- .then(() => {destroy();});
384
- })
385
- .onCancel(() => { destroy(); });
386
- return [dialog, inputs];
398
+ const dialog = ui.dialog({title: PT_UI_DIALOG_ENUMERATION, showFooter: true})
399
+ .add(inputs.macromolecule)
400
+ .add(inputs.placeholders)
401
+ .add(inputs.enumeratorType)
402
+ .add(inputs.trivialNameCol)
403
+ .add(inputs.toAtomicLevel)
404
+ .add(inputs.keepOriginal)
405
+ .add(warningsTextDiv)
406
+ // .addButton('Enumerate', () => {
407
+ // execDialog()
408
+ // .then(() => {});
409
+ // }, 0, 'Keeps the dialog open')
410
+ .onOK(() => { exec(); });
411
+ subs.push(dialog.onClose.subscribe(() => {
412
+ destroy();
413
+ }));
414
+ dialog.history(
415
+ /* getInput */ (): PolyToolEnumerateSerialized => {
416
+ return {
417
+ macromolecule: inputs.macromolecule.stringValue,
418
+ placeholders: inputs.placeholders.stringValue,
419
+ enumeratorType: inputs.enumeratorType.value,
420
+ trivialNameCol: inputs.trivialNameCol.stringValue,
421
+ toAtomicLevel: inputs.toAtomicLevel.value,
422
+ keepOriginal: inputs.keepOriginal.value,
423
+ };
424
+ },
425
+ /* applyInput */ (x: PolyToolEnumerateSerialized): void => {
426
+ inputs.macromolecule.stringValue = x.macromolecule;
427
+ inputs.placeholders.stringValue = x.placeholders;
428
+ inputs.enumeratorType.value = x.enumeratorType;
429
+ inputs.trivialNameCol.stringValue = x.trivialNameCol;
430
+ inputs.toAtomicLevel.value = x.toAtomicLevel;
431
+ inputs.keepOriginal.value = x.keepOriginal;
432
+ });
433
+ return dialog;
434
+ } catch (err: any) {
435
+ destroy(); // on failing to build a dialog
436
+ throw err;
437
+ }
387
438
  }
388
439
 
389
- async function enumerateHelm(
440
+ async function polyToolEnumerateHelm(
390
441
  srcHelm: string, srcId: { value: string, colName: string } | null, params: PolyToolEnumeratorParams,
391
442
  toAtomicLevel: boolean, seqHelper: ISeqHelper,
392
443
  ): Promise<DG.DataFrame> {
393
- await getHelmHelper(); // initializes JSDraw and org
394
-
395
- const resList = getPtEnumeratorHelm(srcHelm, srcId?.value ?? '', params);
396
- const enumHelmCol = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'Enumerated', resList.length)
397
- .init((rowIdx: number) => resList[rowIdx][0]);
398
- const enumeratorResDf = DG.DataFrame.fromColumns([enumHelmCol]);
399
-
400
- if (toAtomicLevel) {
401
- const seqHelper: ISeqHelper = await getSeqHelper();
402
- const toAtomicLevelRes = await seqHelper.helmToAtomicLevel(enumHelmCol, true, true);
403
- toAtomicLevelRes.molCol.semType = DG.SEMTYPE.MOLECULE;
404
- enumeratorResDf.columns.add(toAtomicLevelRes.molCol, false);
405
- enumeratorResDf.columns.add(toAtomicLevelRes.molHighlightCol, false);
406
- }
444
+ const pi = DG.TaskBarProgressIndicator.create('PolyTool enumerating...');
445
+ try {
446
+ await getHelmHelper(); // initializes JSDraw and org
447
+
448
+ const resList = doPolyToolEnumerateHelm(srcHelm, srcId?.value ?? '', params);
449
+ const enumHelmCol = DG.Column.fromType(DG.COLUMN_TYPE.STRING, 'Enumerated', resList.length)
450
+ .init((rowIdx: number) => resList[rowIdx][0]);
451
+ const enumeratorResDf = DG.DataFrame.fromColumns([enumHelmCol]);
452
+
453
+ if (toAtomicLevel) {
454
+ const seqHelper: ISeqHelper = await getSeqHelper();
455
+ const toAtomicLevelRes = await seqHelper.helmToAtomicLevel(enumHelmCol, true, true);
456
+ toAtomicLevelRes.molCol.semType = DG.SEMTYPE.MOLECULE;
457
+ enumeratorResDf.columns.add(toAtomicLevelRes.molCol, false);
458
+ enumeratorResDf.columns.add(toAtomicLevelRes.molHighlightCol, false);
459
+ }
407
460
 
408
- if (srcId) {
409
- const enumIdCol = DG.Column.fromType(DG.COLUMN_TYPE.STRING, srcId.colName, resList.length)
410
- .init((rowIdx: number) => resList[rowIdx][1]);
411
- enumeratorResDf.columns.add(enumIdCol);
412
- }
461
+ if (srcId) {
462
+ const enumIdCol = DG.Column.fromType(DG.COLUMN_TYPE.STRING, srcId.colName, resList.length)
463
+ .init((rowIdx: number) => resList[rowIdx][1]);
464
+ enumeratorResDf.columns.add(enumIdCol);
465
+ }
413
466
 
414
- return enumeratorResDf;
467
+ return enumeratorResDf;
468
+ } finally {
469
+ pi.close();
470
+ }
415
471
  }