@datagrok/sequence-translator 1.6.0 → 1.6.2

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.6.0",
4
+ "version": "1.6.2",
5
5
  "author": {
6
6
  "name": "Leonid Stolbov",
7
7
  "email": "lstolbov@datagrok.ai"
@@ -22,7 +22,7 @@
22
22
  }
23
23
  ],
24
24
  "dependencies": {
25
- "@datagrok-libraries/bio": "^5.45.6",
25
+ "@datagrok-libraries/bio": "^5.46.0",
26
26
  "@datagrok-libraries/chem-meta": "^1.2.7",
27
27
  "@datagrok-libraries/tutorials": "^1.4.3",
28
28
  "@datagrok-libraries/utils": "^4.3.7",
@@ -41,7 +41,7 @@
41
41
  "devDependencies": {
42
42
  "@datagrok-libraries/helm-web-editor": "^1.1.13",
43
43
  "@datagrok-libraries/js-draw-lite": "^0.0.10",
44
- "@datagrok/bio": "^2.17.0",
44
+ "@datagrok/bio": "^2.17.2",
45
45
  "@datagrok/helm": "^2.5.8",
46
46
  "@datagrok/chem": "^1.12.4",
47
47
  "@types/jquery": "^3.5.14",
@@ -1,3 +1,4 @@
1
+ /* eslint-disable max-len */
1
2
  import * as grok from 'datagrok-api/grok';
2
3
  import * as ui from 'datagrok-api/ui';
3
4
  import * as DG from 'datagrok-api/dg';
@@ -76,7 +77,7 @@ export class OligoToolkitPackage extends DG.Package implements ITranslationHelpe
76
77
  if (!this.initLibDataPromise) {
77
78
  this.initLibDataPromise = (async () => {
78
79
  const packageSettings = await this.getSettings();
79
- let monomersPath: string = packageSettings['MonomersPath'];
80
+ let monomersPath: string = packageSettings instanceof Map ? packageSettings.get('MonomersPath') : packageSettings['MonomersPath'];
80
81
  if (!monomersPath || !(await grok.dapi.files.exists(monomersPath))) {
81
82
  this.logger.warning(`Monomers path '${monomersPath}' not found. ` +
82
83
  `Fallback to monomers sample path '${FALLBACK_LIB_PATH}'.`);
@@ -30,6 +30,7 @@ export async function getOverriddenLibrary(rules: Rules): Promise<IMonomerLibBas
30
30
  names = [];
31
31
  monomers = [];
32
32
  console.error(e);
33
+ grok.shell.warning(e);
33
34
  } finally {
34
35
  for (let j = 0; j < names.length; j ++)
35
36
  argLib[names[j]] = monomers[j];
@@ -52,12 +53,12 @@ export function getNewMonomers(rdkit: RDModule, mLib: IMonomerLib, rule: RuleRea
52
53
 
53
54
  const monomerNames = new Array<string>(totalLength);
54
55
  const resMonomers = new Array<Monomer>(totalLength);
55
- const rawMonomers = new Array<string>(totalLength);
56
+ const monomers = new Array<string>(totalLength);
56
57
 
57
58
  const mainRxn = getReactionSmirks(rdkit, reacSmarts);
58
59
 
59
- const reacCutFirst = `${reactants[0]}>>[C:1]`;
60
- const reacCutSecond = `${reactants[1]}>>[C:2]`;
60
+ const reacCutFirst = `${reactants[0]}>>[C:1]C`;
61
+ const reacCutSecond = `${reactants[1]}>>[C:2]C`;
61
62
 
62
63
  const rxnCutFirst = getReactionSmirks(rdkit, reacCutFirst);
63
64
  const rxnCutSecond = getReactionSmirks(rdkit, reacCutSecond);
@@ -68,7 +69,7 @@ export function getNewMonomers(rdkit: RDModule, mLib: IMonomerLib, rule: RuleRea
68
69
  if (!monomer) throw new MonomerNotFoundError('PEPTIDE', rule.firstMonomers[i]);
69
70
 
70
71
  const sMolBlock = cutReactant(rdkit, monomer.molfile, rxnCutFirst, monomer.name);
71
- rawMonomers[counter] = sMolBlock;
72
+ monomers[counter] = sMolBlock;
72
73
  monomerNames[counter] = `${monomer.symbol}_${monomerName}`;
73
74
  counter++;
74
75
  }
@@ -77,7 +78,7 @@ export function getNewMonomers(rdkit: RDModule, mLib: IMonomerLib, rule: RuleRea
77
78
  if (!monomer) throw new MonomerNotFoundError('PEPTIDE', rule.secondMonomers[i]);
78
79
 
79
80
  const sMolBlock = cutReactant(rdkit, monomer.molfile, rxnCutSecond, monomer.name);
80
- rawMonomers[counter] = sMolBlock;
81
+ monomers[counter] = sMolBlock;
81
82
  monomerNames[counter] = `${monomer.symbol}_${monomerName}`;
82
83
  counter++;
83
84
  }
@@ -97,20 +98,22 @@ export function getNewMonomers(rdkit: RDModule, mLib: IMonomerLib, rule: RuleRea
97
98
  mol?.delete();
98
99
  }
99
100
  //pMolblock = reactionMembers[1]//cutProduct(rdkit, monomer1?.molfile, monomer2?.molfile, mainRxn, monomerName);
100
- rawMonomers[counter] = pMolblock;
101
+ monomers[counter] = pMolblock;
101
102
  monomerNames[counter] = monomerName;
102
103
 
103
- //after RDKit works
104
- for (let i = 0; i < totalLength - 1; i ++)
105
- rawMonomers[i] = rawMonomers[i].replace('0.0000 C ', '0.0000 R# ').replace('M RGP 2', 'M RGP 3 1 3');
106
- rawMonomers[totalLength - 1] = modProduct(rawMonomers[totalLength - 1]);
104
+ //after RDKit works - [X:N] is first atom which is exploited
105
+ for (let i = 0; i < totalLength - 1; i ++) {
106
+ monomers[i] = monomers[i].replace(' 0.0000 0.0000 0.0000 C ', ' 0.0000 0.0000 0.0000 R# ')
107
+ .replace('M RGP 2', 'M RGP 3 2 3');
108
+ }
109
+ monomers[totalLength - 1] = modProduct(monomers[totalLength - 1]);
107
110
 
108
111
  for (let i = 0; i < totalLength; i ++) {
109
112
  const isProduct = i == totalLength - 1 ? true : false;
110
113
  const resMonomer: Monomer = {
111
114
  [REQ.SYMBOL]: monomerNames[i],
112
115
  [REQ.NAME]: monomerNames[i],
113
- [REQ.MOLFILE]: rawMonomers[i],
116
+ [REQ.MOLFILE]: monomers[i],
114
117
  [REQ.AUTHOR]: '',
115
118
  [REQ.ID]: 0,
116
119
  [REQ.RGROUPS]: getNewGroups(isProduct),
@@ -87,16 +87,33 @@ export class RulesManager {
87
87
  reactionRules: this.rules.reactionRules,
88
88
  };
89
89
 
90
- const rrrr = JSON.stringify(saveable, undefined, 2);
91
- _package.files.writeAsText(`polytool-rules/${this.fileName}`, rrrr);
90
+ const json = JSON.stringify(saveable, undefined, 2);
91
+ _package.files.writeAsText(`polytool-rules/${this.fileName}`, json);
92
92
  grok.shell.info(`Polytool rules at ${this.fileName} was updated`);
93
93
  }
94
94
 
95
- private createGridDiv(name: string, grid: DG.Grid) {
95
+ private createGridDiv(name: string, grid: DG.Grid, buttons: HTMLButtonElement[] = []) {
96
96
  const header = ui.h1(name, 'polytool-grid-header');
97
- grid.root.prepend(header);
97
+ header.style.marginTop = '10px';
98
+ header.style.marginRight = '10px';
98
99
  grid.root.style.height = '100%';
99
- return grid.root;
100
+
101
+ buttons.forEach((b) => {
102
+ b.style.marginLeft = '5px';
103
+ b.style.marginRight = '10px';
104
+ });
105
+
106
+ const gridDiv = ui.splitV([
107
+ ui.box(
108
+ ui.divH([header, ...buttons]),
109
+ {style: {maxHeight: '60px'}},
110
+ ),
111
+ grid.root,
112
+ ]);
113
+
114
+ gridDiv.style.height = '100%';
115
+
116
+ return gridDiv;
100
117
  };
101
118
 
102
119
  async getLinkExamplesGrid() {
@@ -160,69 +177,48 @@ export class RulesManager {
160
177
  async getForm() {
161
178
  inputsTabControl: DG.TabControl;
162
179
 
180
+ const saveLinksButton = ui.bigButton('Save', () => { this.save(); });
181
+ const addLinkButton = ui.button('Add rule', () => { this.linkRuleDataFrame.rows.addNew(); });
182
+ const linksGridDiv = this.createGridDiv('Rules',
183
+ this.linkRuleDataFrame.plot.grid({showAddNewRowIcon: true}), [saveLinksButton, addLinkButton]);
184
+ const linkExamples = this.createGridDiv('Examples', await this.getLinkExamplesGrid());
185
+ linksGridDiv.style.width = '50%';
186
+ linkExamples.style.width = '50%';
187
+ const links = ui.divH([linksGridDiv, linkExamples]);
188
+
189
+ const saveReactionsButton = ui.bigButton('Save', () => { this.save(); });
190
+ const addReactionButton = ui.button('Add rule', () => { this.synthRuleDataFrame.rows.addNew(); });
191
+ const reactionsGridDiv = this.createGridDiv('Rules',
192
+ this.synthRuleDataFrame.plot.grid({showAddNewRowIcon: true}), [saveReactionsButton, addReactionButton]);
193
+ const reactionExamples = this.createGridDiv('Examples', await this.getReactionExamplesGrid());
194
+ reactionsGridDiv.style.width = '50%';
195
+ reactionExamples.style.width = '50%';
196
+ const reactions = ui.divH([reactionsGridDiv, reactionExamples]);
197
+
163
198
  const dimerInputsDiv = ui.divV([
164
199
  this.homoDimerInput,
165
200
  this.heteroDimerInput,
166
201
  ]);
167
202
 
168
- const linkExamples = await this.getLinkExamplesGrid();
169
- const reactionExamples = await this.getReactionExamplesGrid();
170
-
171
203
  const inputsTabControl = ui.tabControl({
172
- 'Links': linkExamples,
173
- 'Reactions': reactionExamples,
204
+ 'Links': links,
205
+ 'Reactions': reactions,
174
206
  'Dimers': dimerInputsDiv,
175
207
  }, false);
176
208
 
177
- inputsTabControl.root.style.height = '90%';
209
+ inputsTabControl.root.style.height = '100%';
178
210
  inputsTabControl.root.style.width = '100%';
179
211
  inputsTabControl.root.classList.add('rules-manager-form-tab-control');
180
212
  inputsTabControl.header.style.marginBottom = '10px';
181
213
 
182
- const linksGridDiv = this.createGridDiv('Link rules', this.linkRuleDataFrame.plot.grid({showAddNewRowIcon: true}));
183
- const reactionsGridDiv =
184
- this.createGridDiv('Reaction rules', this.synthRuleDataFrame.plot.grid({showAddNewRowIcon: true}));
185
-
186
- linksGridDiv.style.width = '100%';
187
- reactionsGridDiv.style.width = '100%';
188
-
189
- const divs = [linksGridDiv, reactionsGridDiv, ui.div()];
190
- divs[0].style.removeProperty('display');
191
- divs[1].style.display = 'none';
192
- divs[2].style.display = 'none';
193
-
194
- inputsTabControl.onTabChanged.subscribe(() => {
195
- this.currentTab = inputsTabControl.currentPane.name;
196
-
197
- const idx = inputsTabControl.panes.findIndex((p) => p.name == this.currentTab);
198
-
199
- for (let i = 0; i < divs.length; i++) {
200
- if (i == idx)
201
- divs[i].style.removeProperty('display');
202
- else
203
- divs[i].style.display = 'none';
204
- }
205
- });
206
-
207
- const saveButton = ui.bigButton('Save changes', () => {
208
- this.save();
209
- });
210
-
211
-
212
214
  const panel = ui.divV([
213
215
  inputsTabControl.root,
214
- saveButton
215
216
  ]);
216
217
 
217
218
  panel.style.height = '100%';
218
219
  panel.style.alignItems = 'center';
219
220
 
220
- const form = ui.splitH([
221
- panel,
222
- ui.divV(divs, {style: {width: '100%'}})
223
- ], {style: {width: '100%'}}, true);
224
- form.style.height = '100%';
225
- return form;
221
+ return inputsTabControl.root;
226
222
  }
227
223
  }
228
224
 
@@ -99,8 +99,8 @@ export async function getPolyToolConvertDialog(srcCol?: DG.Column): Promise<DG.D
99
99
  const generateHelmInput = ui.input.bool(PT_UI_GET_HELM, {value: true});
100
100
  ui.tooltip.bind(generateHelmInput.root, PT_UI_ADD_HELM);
101
101
 
102
- const chiralityEngineInput = ui.input.bool(PT_UI_USE_CHIRALITY, {value: false});
103
- const highlightMonomersInput = ui.input.bool(PT_UI_HIGHLIGHT_MONOMERS, {value: false});
102
+ const chiralityEngineInput = ui.input.bool(PT_UI_USE_CHIRALITY, {value: true});
103
+ const highlightMonomersInput = ui.input.bool(PT_UI_HIGHLIGHT_MONOMERS, {value: true});
104
104
  let ruleFileList: string[];
105
105
  const ruleInputs = new RuleInputs(RULES_PATH, RULES_STORAGE_NAME, '.json', {
106
106
  onValueChanged: (value: string[]) => { ruleFileList = value; }
@@ -85,8 +85,8 @@ category('toAtomicLevel', () => {
85
85
  try {
86
86
  const molInchi = mol.get_inchi();
87
87
  const molInchiKey = rdKitModule.get_inchikey_for_inchi(molInchi);
88
- expect(mol.get_num_bonds(), 6);
89
- expect(mol.get_num_atoms(), 7);
88
+ expect(mol.get_num_bonds(), 7);
89
+ expect(mol.get_num_atoms(), 8);
90
90
  // TODO: Check inchi key for the new monomer molfile
91
91
  // expect(molInchiKey, 'V2H10N2O3S-UHFFFAOYSA-N');
92
92
  } finally {
@@ -5,20 +5,20 @@ import * as DG from 'datagrok-api/dg';
5
5
  import {MonomerPlacer} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
6
6
  import {monomerToShort} from '@datagrok-libraries/bio/src/utils/macromolecule';
7
7
  import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
8
-
9
8
  import {_package} from '../package';
10
9
 
11
10
  export class CyclizedCellRendererBack extends MonomerPlacer {
12
-
13
11
  constructor(
14
12
  gridCol: DG.GridColumn | null, tableCol: DG.Column,
15
13
  maxLengthOfMonomer: number, seqHelper: ISeqHelper
16
14
  ) {
17
15
  super(gridCol, tableCol, _package.logger, maxLengthOfMonomer, () => {
18
16
  const sh = seqHelper.getSeqHandler(tableCol);
17
+ const {font, fontWidth} = MonomerPlacer.getFontSettings(tableCol);
19
18
  return {
20
19
  seqHandler: sh,
21
- monomerCharWidth: 7,
20
+ font: font,
21
+ fontCharWidth: fontWidth,
22
22
  separatorWidth: 11,
23
23
  monomerToShort: monomerToShort,
24
24
  };
@@ -26,12 +26,12 @@ export class CyclizedCellRendererBack extends MonomerPlacer {
26
26
  }
27
27
 
28
28
  override onMouseMove(gridCell: DG.GridCell, e: MouseEvent) {
29
- const gridCellBounds: DG.Rect = gridCell.bounds;
30
- const argsX = e.offsetX - gridCell.gridColumn.left + (gridCell.gridColumn.left - gridCellBounds.x);
31
- const left: number | null = this.getPosition(gridCell.tableRowIndex!, argsX, gridCellBounds.width);
32
- if(left != null) {
29
+ // const gridCellBounds: DG.Rect = gridCell.bounds;
30
+ // const argsX = e.offsetX - gridCell.gridColumn.left + (gridCell.gridColumn.left - gridCellBounds.x);
31
+ // const left: number | null = this.getPosition(gridCell.tableRowIndex!, argsX, gridCellBounds.width);
32
+ // if(left != null) {
33
33
 
34
- }
34
+ // }
35
35
  super.onMouseMove(gridCell, e);
36
36
  }
37
37
  }