@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/CHANGELOG.md +14 -0
- package/dist/package-test.js +1 -1
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +3 -3
- package/src/apps/common/model/oligo-toolkit-package.ts +2 -1
- package/src/polytool/conversion/pt-synthetic.ts +14 -11
- package/src/polytool/conversion/rule-manager.ts +44 -48
- package/src/polytool/pt-dialog.ts +2 -2
- package/src/tests/toAtomicLevel-tests.ts +2 -2
- package/src/utils/cell-renderer-cyclized.ts +8 -8
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
106
|
-
|
|
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]:
|
|
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
|
|
91
|
-
_package.files.writeAsText(`polytool-rules/${this.fileName}`,
|
|
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
|
-
|
|
97
|
+
header.style.marginTop = '10px';
|
|
98
|
+
header.style.marginRight = '10px';
|
|
98
99
|
grid.root.style.height = '100%';
|
|
99
|
-
|
|
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':
|
|
173
|
-
'Reactions':
|
|
204
|
+
'Links': links,
|
|
205
|
+
'Reactions': reactions,
|
|
174
206
|
'Dimers': dimerInputsDiv,
|
|
175
207
|
}, false);
|
|
176
208
|
|
|
177
|
-
inputsTabControl.root.style.height = '
|
|
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
|
-
|
|
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:
|
|
103
|
-
const highlightMonomersInput = ui.input.bool(PT_UI_HIGHLIGHT_MONOMERS, {value:
|
|
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(),
|
|
89
|
-
expect(mol.get_num_atoms(),
|
|
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
|
-
|
|
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
|
}
|