@datagrok/sequence-translator 1.3.11 → 1.3.13

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/sequence-translator",
3
3
  "friendlyName": "Sequence Translator",
4
- "version": "1.3.11",
4
+ "version": "1.3.13",
5
5
  "author": {
6
6
  "name": "Alexey Choposky",
7
7
  "email": "achopovsky@datagrok.ai"
@@ -22,10 +22,10 @@
22
22
  }
23
23
  ],
24
24
  "dependencies": {
25
- "@datagrok-libraries/bio": "5.42.5",
25
+ "@datagrok-libraries/bio": "^5.42.11",
26
26
  "@datagrok-libraries/chem-meta": "^1.2.5",
27
- "@datagrok-libraries/tutorials": "^1.3.12",
28
- "@datagrok-libraries/utils": "^4.2.13",
27
+ "@datagrok-libraries/tutorials": "^1.3.13",
28
+ "@datagrok-libraries/utils": "^4.2.29",
29
29
  "@types/react": "^18.0.15",
30
30
  "cash-dom": "^8.1.0",
31
31
  "datagrok-api": "^1.20.0",
@@ -39,10 +39,11 @@
39
39
  "wu": "latest"
40
40
  },
41
41
  "devDependencies": {
42
- "@datagrok-libraries/helm-web-editor": "^1.1.6",
43
- "@datagrok-libraries/js-draw-lite": "^0.0.4",
44
- "@datagrok/bio": "^2.13.3",
45
- "@datagrok/chem": "1.9.2",
42
+ "@datagrok-libraries/helm-web-editor": "^1.1.10",
43
+ "@datagrok-libraries/js-draw-lite": "^0.0.8",
44
+ "@datagrok/bio": "^2.14.2",
45
+ "@datagrok/helm": "^2.4.4",
46
+ "@datagrok/chem": "^1.11.3",
46
47
  "@types/jquery": "^3.5.14",
47
48
  "@types/js-yaml": "^4.0.5",
48
49
  "@types/lodash": "^4.14.202",
@@ -4,6 +4,7 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
6
6
  import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types';
7
+ import {LoggerWrapper} from '@datagrok-libraries/bio/src/utils/logger';
7
8
 
8
9
  import {APP_NAME} from '../view/const';
9
10
  import {DEFAULT_LIB_FILENAME, FALLBACK_LIB_PATH} from './data-loader/const';
@@ -12,7 +13,6 @@ import {ITranslationHelper} from '../../../types';
12
13
  import {SequenceValidator} from './parsing-validation/sequence-validator';
13
14
  import {JsonData, loadJsonData} from './data-loader/json-loader';
14
15
  import {MonomerLibWrapper} from './monomer-lib/lib-wrapper';
15
- import {_package} from '../../../package';
16
16
  import {FormatConverter} from '../../translator/model/format-converter';
17
17
  import {FormatDetector} from './parsing-validation/format-detector';
18
18
  import {highlightInvalidSubsequence} from '../view/components/colored-input/input-painters';
@@ -39,8 +39,10 @@ export class OligoToolkitPackage extends DG.Package implements ITranslationHelpe
39
39
  return this._monomerLibWrapper;
40
40
  }
41
41
 
42
- constructor() {
42
+ constructor(opts: { debug: boolean } = {debug: false}) {
43
43
  super();
44
+ // @ts-ignore
45
+ super._logger = new LoggerWrapper(super.logger, opts.debug);
44
46
  }
45
47
 
46
48
  private initPromise?: Promise<void>;
@@ -51,7 +53,7 @@ export class OligoToolkitPackage extends DG.Package implements ITranslationHelpe
51
53
  const packageSettings = await this.getSettings();
52
54
  let monomersPath: string = packageSettings['MonomersPath'];
53
55
  if (!monomersPath || !(await grok.dapi.files.exists(monomersPath))) {
54
- _package.logger.warning(`Monomers path '${monomersPath}' not found. ` +
56
+ this.logger.warning(`Monomers path '${monomersPath}' not found. ` +
55
57
  `Fallback to monomers sample path '${FALLBACK_LIB_PATH}'.`);
56
58
  monomersPath = FALLBACK_LIB_PATH;
57
59
  }
@@ -25,4 +25,5 @@
25
25
  color: transparent;
26
26
  white-space: pre-wrap;
27
27
  word-wrap: break-word;
28
+ padding-left: 35px;
28
29
  }
@@ -4,25 +4,6 @@
4
4
  padding-right: 20px;
5
5
  }
6
6
 
7
- .st-structure-input-form {
8
- text-align: right;
9
- vertical-align: top;
10
- min-width: 95px;
11
- }
12
-
13
- .st-structure-direction-choice label {
14
- min-width: 100px;
15
- float: right;
16
- }
17
-
18
- .st-structure-direction-choice div {
19
- justify-content: right;
20
- }
21
-
22
- .st-structure-text-input-td { /* Style for td containing textarea */
23
- width: 100%;
24
- }
25
-
26
7
  .st-structure-mol-img {
27
8
  margin-right: 30px;
28
9
  float: right;
@@ -37,3 +18,17 @@
37
18
  flex-direction: row-reverse;
38
19
  padding-top: 20px;
39
20
  }
21
+
22
+ .st-structure-clear-buttons {
23
+ justify-content: space-between;
24
+ padding: 13px 10px 13px 10px;
25
+ }
26
+
27
+ .st-direction-inputs {
28
+ align-items: end;
29
+ }
30
+
31
+ .st-structure-inputs {
32
+ flex-grow: 2;
33
+ padding-left: 10px;
34
+ }
@@ -33,7 +33,7 @@ class StructureAppLayout {
33
33
  this.onInvalidInput = new rxjs.Subject<string>();
34
34
  this.inputBase = Object.fromEntries(
35
35
  STRANDS.map(
36
- (key) => [key, ui.input.textArea('', {value: '', onValueChanged: () => { this.onInput.next(); }})]
36
+ (key) => [key, ui.input.textArea(key.toUpperCase(), {value: '', onValueChanged: () => { this.onInput.next(); }})]
37
37
  )
38
38
  );
39
39
  this.useChiralInput = ui.input.bool('Use chiral', {value: true});
@@ -91,7 +91,7 @@ class StructureAppLayout {
91
91
  return boolInputsAndButton;
92
92
  }
93
93
 
94
- private getTableInput(th: ITranslationHelper): HTMLTableElement {
94
+ private getTableInput(th: ITranslationHelper): HTMLElement {
95
95
  const coloredInput = Object.fromEntries(
96
96
  STRANDS.map(
97
97
  (key) => [key, new ColoredTextInput(this.inputBase[key], th.highlightInvalidSubsequence)]
@@ -140,32 +140,16 @@ class StructureAppLayout {
140
140
  }
141
141
  ));
142
142
 
143
- const tableRows = STRANDS.map((strand) => {
144
- return {
145
- label: label[strand],
146
- textInput: coloredInput[strand].root,
147
- clear: clearBlock[strand],
148
- choiceInput: directionChoiceInput[strand].root,
149
- };
150
- });
151
- const tableLayout = ui.table(
152
- tableRows, (item) => [item.label, item.textInput, item.clear, item.choiceInput]);
153
- $(tableLayout).css('margin-top', '10px');
143
+ const sequenseInputs = ui.form([], 'st-structure-inputs');
144
+ const clearButtons = ui.divV([], 'st-structure-clear-buttons');
145
+ const directionInputs = ui.form([], 'st-direction-inputs');
154
146
 
155
147
  for (const strand of STRANDS) {
156
- let element = label[strand].parentElement!;
157
- element.classList.add('st-structure-input-form');
158
- // the following line is necessary because otherwise overridden by
159
- // d4-item-table class
160
- $(element).css('padding-top', '3px');
161
-
162
- element = directionChoiceInput[strand].root.parentElement!;
163
- element.classList.add('st-structure-input-form', 'st-structure-direction-choice');
164
-
165
- element = this.inputBase[strand].root.parentElement!;
166
- element.classList.add('st-structure-text-input-td');
148
+ sequenseInputs.append(this.inputBase[strand].root);
149
+ clearButtons.append(clearBlock[strand]);
150
+ directionInputs.append(directionChoiceInput[strand].root);
167
151
  }
168
- return tableLayout;
152
+ return ui.divH([sequenseInputs, clearButtons, directionInputs]);
169
153
  }
170
154
 
171
155
  private getStrandData() {
@@ -8,6 +8,7 @@ import './tests/formats-to-helm';
8
8
  import './tests/helm-to-nucleotides';
9
9
  import './tests/formats-support';
10
10
  import './tests/files-tests';
11
+ import './tests/polytool-enumerate-tests';
11
12
 
12
13
  import {OligoToolkitTestPackage} from './tests/utils';
13
14
 
package/src/package.ts CHANGED
@@ -16,14 +16,14 @@ import {demoOligoPatternUI, demoOligoStructureUI, demoOligoTranslatorUI} from '.
16
16
  import {getExternalAppViewFactories} from './plugins/mermade';
17
17
 
18
18
  //polytool specific
19
- import {getPolyToolConversionDialog, polyToolEnumerateHelmUI, polyToolEnumerateChemUI} from './polytool/pt-dialog';
19
+ import {getPolyToolConversionDialog, polyToolEnumerateChemUI} from './polytool/pt-dialog';
20
+ import {polyToolEnumerateHelmUI} from './polytool/pt-enumeration-helm-dialog';
20
21
  import {_setPeptideColumn} from './polytool/utils';
21
22
  import {PolyToolCsvLibHandler} from './polytool/csv-to-json-monomer-lib-converter';
22
23
  import {ITranslationHelper} from './types';
23
24
  import {addContextMenuUI} from './utils/context-menu';
24
- import { NOTATION } from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
25
25
 
26
- export const _package: OligoToolkitPackage = new OligoToolkitPackage();
26
+ export const _package: OligoToolkitPackage = new OligoToolkitPackage(/*{debug: true}/**/);
27
27
 
28
28
  //name: Oligo Toolkit
29
29
  //meta.icon: img/icons/toolkit.png
@@ -152,7 +152,7 @@ async function getSpecifiedAppView(appName: string): Promise<DG.ViewBase> {
152
152
  return view;
153
153
  }
154
154
 
155
- //top-menu: Bio | Convert | PolyTool-Convert
155
+ //top-menu: Bio | PolyTool | Convert...
156
156
  //name: polyToolConvert
157
157
  //description: Perform cyclization of polymers
158
158
  export async function polyToolConvert(): Promise<void> {
@@ -165,14 +165,14 @@ export async function polyToolConvert(): Promise<void> {
165
165
  }
166
166
  }
167
167
 
168
- //top-menu: Bio | Convert | PolyTool-Enumerate HELM
168
+ //top-menu: Bio | PolyTool | Enumerate HELM...
169
169
  //name: polyToolEnumerateHelm
170
170
  //description: Perform cyclization of polymers
171
171
  export async function polyToolEnumerateHelm(): Promise<void> {
172
- polyToolEnumerateHelmUI();
172
+ await polyToolEnumerateHelmUI(grok.shell.tv?.dataFrame.currentCell);
173
173
  }
174
174
 
175
- //top-menu: Bio | Convert | PolyTool-Enumerate Chem
175
+ //top-menu: Bio | PolyTool | Enumerate Chem...
176
176
  //name: polyToolEnumerateChem
177
177
  //description: Perform cyclization of polymers
178
178
  export async function polyToolEnumerateChem(): Promise<void> {
@@ -213,7 +213,7 @@ export function addContextMenu(event: DG.EventData): void {
213
213
  // export async function ptConverterApp(): Promise<void> {
214
214
  // const view = grok.shell.v as DG.TableView;
215
215
  // const table = view.dataFrame;
216
- // const colNames = table.columns.names();
216
+ // const colNames = table.columns.names();
217
217
  // let covertableName = '';
218
218
 
219
219
  // for (let i = 0; i < colNames.length; i++) {
@@ -229,7 +229,7 @@ export function addContextMenu(event: DG.EventData): void {
229
229
  // else {
230
230
  // const dialog = await getPolyToolConversionDialog();
231
231
  // dialog.show();
232
- // }
232
+ // }
233
233
  // }
234
234
 
235
235
  //name: PolyTool Enumerator Helm
@@ -237,7 +237,7 @@ export function addContextMenu(event: DG.EventData): void {
237
237
  //meta.browsePath: PolyTool
238
238
  //tags: app
239
239
  export async function ptEnumeratorHelmApp(): Promise<void> {
240
- polyToolEnumerateHelmUI();
240
+ await polyToolEnumerateHelmUI();
241
241
  }
242
242
 
243
243
  //name: PolyTool Enumerator Chem
@@ -246,4 +246,4 @@ export async function ptEnumeratorHelmApp(): Promise<void> {
246
246
  //tags: app
247
247
  export async function ptEnumeratorChemApp(): Promise<void> {
248
248
  polyToolEnumerateChemUI();
249
- }
249
+ }
@@ -26,3 +26,13 @@ export const R_GROUP_BLOCK_DUMMY = [
26
26
  'label': 'R3'
27
27
  }
28
28
  ];
29
+
30
+ export const PT_ERROR_DATAFRAME = 'No dataframe with macromolecule columns open';
31
+ export const PT_WARNING_COLUMN = 'No marcomolecule column chosen!';
32
+
33
+ export const PT_UI_GET_HELM = 'Get HELM';
34
+ export const PT_UI_ADD_HELM = 'Add HELM column';
35
+ export const PT_UI_USE_CHIRALITY = 'Chirality engine';
36
+ export const PT_UI_DIALOG_CONVERSION = 'Poly Tool Conversion';
37
+ export const PT_UI_DIALOG_ENUMERATION = 'Poly Tool Enumeration';
38
+ export const PT_UI_RULES_USED = 'Rules used';
@@ -297,6 +297,7 @@ export async function addTransformedColumn(
297
297
  df.columns.add(targetHelmCol);
298
298
  }
299
299
 
300
+ // toAtomicLevel
300
301
  const molCol = await grok.functions.call('Bio:getMolFromHelm', {
301
302
  'df': df,
302
303
  'helmCol': targetHelmCol,
@@ -3,11 +3,9 @@ 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';
6
+ import $ from 'cash-dom';
7
7
 
8
- import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
9
8
  import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
10
- import {HelmAtom} from '@datagrok-libraries/bio/src/helm/types';
11
9
 
12
10
  import {RuleInputs, RULES_PATH, RULES_STORAGE_NAME} from './pt-rules';
13
11
  import {addTransformedColumn} from './pt-conversion';
@@ -15,28 +13,13 @@ import {addTransformedColumn} from './pt-conversion';
15
13
  import {handleError} from './utils';
16
14
  import {defaultErrorHandler} from '../utils/err-info';
17
15
  import {getLibrariesList} from './utils';
18
- import {getEnumerationHelm, PT_HELM_EXAMPLE} from './pt-enumeration-helm';
19
16
  import {getEnumerationChem, PT_CHEM_EXAMPLE} from './pt-enumeration-chem';
17
+ import {
18
+ PT_ERROR_DATAFRAME, PT_UI_ADD_HELM, PT_UI_DIALOG_CONVERSION, PT_UI_DIALOG_ENUMERATION,
19
+ PT_UI_GET_HELM, PT_UI_RULES_USED, PT_UI_USE_CHIRALITY, PT_WARNING_COLUMN
20
+ } from './const';
20
21
 
21
- const PT_ERROR_DATAFRAME = 'No dataframe with macromolecule columns open';
22
- const PT_WARNING_COLUMN = 'No marcomolecule column chosen!';
23
-
24
- const PT_UI_GET_HELM = 'Get HELM';
25
- const PT_UI_ADD_HELM = 'Add HELM column';
26
- const PT_UI_USE_CHIRALITY = 'Chirality engine';
27
- const PT_UI_DIALOG_CONVERSION = 'Poly Tool Conversion';
28
- const PT_UI_DIALOG_ENUMERATION = 'Poly Tool Enumeration';
29
- const PT_UI_RULES_USED = 'Rules used';
30
-
31
- export function polyToolEnumerateHelmUI(cell?: DG.Cell): void {
32
- getPolyToolEnumerationHelmDialog(cell)
33
- .then((dialog) => {
34
- dialog.show({resizable: true});
35
- })
36
- .catch((_err: any) => {
37
- grok.shell.warning('To run PolyTool Enumeration, sketch the macromolecule and select monomers to vary');
38
- });
39
- }
22
+ import {_package} from '../package';
40
23
 
41
24
  export function polyToolEnumerateChemUI(cell?: DG.Cell): void {
42
25
  getPolyToolEnumerationChemDialog(cell)
@@ -104,61 +87,6 @@ export async function getPolyToolConversionDialog(targetCol?: DG.Column): Promis
104
87
  return dialog;
105
88
  }
106
89
 
107
- async function getPolyToolEnumerationHelmDialog(cell?: DG.Cell): Promise<DG.Dialog> {
108
- const [libList, helmHelper] = await Promise.all([
109
- getLibrariesList(), getHelmHelper()]);
110
-
111
- const helmValue = cell ? cell.value : PT_HELM_EXAMPLE;
112
-
113
- const helmInput = helmHelper.createHelmInput('Macromolecule', {value: helmValue});
114
- const screenLibrary = ui.input.choice('Library to use', {value: null, items: libList});
115
-
116
- helmInput.input.setAttribute('style', `min-width:250px!important;`);
117
- screenLibrary.input.setAttribute('style', `min-width:250px!important;`);
118
-
119
- const div = ui.div([
120
- helmInput.root,
121
- screenLibrary.root
122
- ]);
123
-
124
- // Displays the molecule from a current cell (monitors changes)
125
- const cccSubs = grok.events.onCurrentCellChanged.subscribe(() => {
126
- const cell = grok.shell.tv.dataFrame.currentCell;
127
-
128
- if (cell.column.semType === DG.SEMTYPE.MACROMOLECULE && cell.column.meta.units === NOTATION.HELM)
129
- helmInput.stringValue = cell.value;
130
- });
131
-
132
- const dialog = ui.dialog(PT_UI_DIALOG_ENUMERATION)
133
- .add(div)
134
- .onOK(async () => {
135
- try {
136
- const helmString = helmInput.stringValue;
137
- const helmSelections: number[] = wu.enumerate<HelmAtom>(helmInput.value.atoms)
138
- .filter(([a, aI]) => a.highlighted)
139
- .map(([a, aI]) => aI).toArray();
140
- if (helmString === undefined || helmString === '') {
141
- grok.shell.warning('PolyTool: no molecule was provided');
142
- } else if (helmSelections === undefined || helmSelections.length < 1) {
143
- grok.shell.warning('PolyTool: no selection was provided');
144
- } else {
145
- const molecules = await getEnumerationHelm(helmString, helmSelections, screenLibrary.value!);
146
- const molCol = DG.Column.fromStrings('Enumerated', molecules);
147
- const df = DG.DataFrame.fromColumns([molCol]);
148
- grok.shell.addTableView(df);
149
- }
150
- } catch (err: any) {
151
- defaultErrorHandler(err);
152
- } finally {
153
- cccSubs.unsubscribe();
154
- }
155
- }).onCancel(() => {
156
- cccSubs.unsubscribe();
157
- });
158
-
159
- return dialog;
160
- }
161
-
162
90
  async function getPolyToolEnumerationChemDialog(cell?: DG.Cell): Promise<DG.Dialog> {
163
91
  const [libList, helmHelper] = await Promise.all([
164
92
  getLibrariesList(), getHelmHelper()]);
@@ -87,23 +87,8 @@ export async function getEnumerationChem(molString: string, screenLibrary: strin
87
87
  //TODO: use RDKit linking function when exposed
88
88
  const smiResRaw = `${smiScaffold}.${smilesSubsts[i]}`.replaceAll('[1*]C', 'C([1*])').replaceAll('[1*]c', 'c([1*])').replaceAll('[1*]O', 'O([1*])').replaceAll('[1*]N', 'N([1*])');
89
89
  const smiRes = `${smiResRaw}`.replaceAll('([1*])', '9').replaceAll('[1*]', '9');
90
- molRes = rdkitModule.get_mol(smiRes);
90
+ molRes = rdkitModule.get_mol(smiRes, JSON.stringify({mappedDummiesAreRGroups: true}))
91
91
  let molV3 = molRes.get_v3Kmolblock();
92
-
93
-
94
- //TODO: use RDKit when MASS problem is solved
95
- while(molV3.includes('MASS')) {
96
-
97
- //MASS=2 VAL=1
98
- //RGROUPS=(1 2)
99
- const idx = molV3.indexOf('MASS');
100
- const rNum = parseInt(molV3.slice(idx + 5, idx + 6));
101
- const replace = `RGROUPS=(1 ${rNum})`;
102
- molV3 = molV3.substring(0, idx) + replace + molV3.substring(idx + 12);
103
- }
104
-
105
- molV3 = molV3.replaceAll('R ', 'R# ')
106
-
107
92
  enumerations[i] = molV3;
108
93
  }
109
94
  catch(err:any) {