@datagrok/sequence-translator 1.9.9 → 1.9.11
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/.eslintrc.json +0 -1
- 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/files/polytool-rules/rules_example.json +4 -4
- package/package.json +4 -4
- package/src/demo/demo-st-ui.ts +4 -4
- package/src/package-api.ts +4 -4
- package/src/package.g.ts +195 -0
- package/src/package.ts +345 -273
- package/src/polytool/conversion/pt-rule-cards.ts +76 -47
- package/src/polytool/conversion/pt-rules.ts +39 -12
- package/src/polytool/conversion/rule-manager.ts +65 -12
- package/src/polytool/conversion/style.css +2 -2
- package/src/polytool/pt-enumerate-seq-dialog.ts +3 -3
- package/src/tests/polytool-convert-tests.ts +2 -2
- package/test-console-output-1.log +139 -138
- package/test-record-1.mp4 +0 -0
- package/tsconfig.json +2 -2
- package/webpack.config.js +5 -1
|
@@ -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';
|
|
@@ -13,6 +14,7 @@ import {getSeqHelper, ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-he
|
|
|
13
14
|
import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
14
15
|
import {getOverriddenLibrary} from './pt-synthetic';
|
|
15
16
|
import {helmToMol} from './pt-atomic';
|
|
17
|
+
import {execMonomerHoverLinks} from '@datagrok-libraries/bio/src/monomer-works/monomer-hover';
|
|
16
18
|
|
|
17
19
|
class MonomerCard {
|
|
18
20
|
root: HTMLElement = ui.divV([], {classes: 'monomer-card-rule-root'});
|
|
@@ -24,11 +26,12 @@ class MonomerCard {
|
|
|
24
26
|
this.root.style.border = value ? '2px solid var(--green-2)' : '2px solid var(--grey-2)';
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
constructor(public monomer: Monomer | null) {}
|
|
29
|
+
constructor(public monomer: Monomer | null, public monomerSymbol: string) {}
|
|
28
30
|
|
|
29
31
|
render() {
|
|
32
|
+
ui.empty(this.root);
|
|
33
|
+
this.root.appendChild(ui.h2(this.monomerSymbol, {style: {textAlign: 'center'}}));
|
|
30
34
|
if (this.monomer) {
|
|
31
|
-
ui.empty(this.root);
|
|
32
35
|
const monomerMolSvg = this.monomer.smiles && grok.chem.checkSmiles(this.monomer.smiles) ?
|
|
33
36
|
grok.chem.drawMolecule(this.monomer.smiles, 150, 120) :
|
|
34
37
|
grok.chem.drawMolecule(this.monomer.molfile ?? '', 150, 120);
|
|
@@ -52,6 +55,9 @@ class MonomerCard {
|
|
|
52
55
|
ui.tooltip.bind(monomerType, this.monomer.polymerType);
|
|
53
56
|
|
|
54
57
|
ui.tooltip.bind(this.root, 'Select Monomer');
|
|
58
|
+
} else {
|
|
59
|
+
this.root.appendChild(ui.divV([`Monomer ${this.monomerSymbol} not found in libraries`],
|
|
60
|
+
{style: {textAlign: 'center', height: '100%'}}));
|
|
55
61
|
}
|
|
56
62
|
}
|
|
57
63
|
}
|
|
@@ -59,7 +65,6 @@ class MonomerCard {
|
|
|
59
65
|
export class RuleCards {
|
|
60
66
|
root: HTMLElement = ui.divH([],
|
|
61
67
|
{style: {
|
|
62
|
-
alignItems: 'center',
|
|
63
68
|
width: '100%',
|
|
64
69
|
overflow: 'hidden',
|
|
65
70
|
visibility: 'visible',
|
|
@@ -74,47 +79,53 @@ export class RuleCards {
|
|
|
74
79
|
|
|
75
80
|
constructor(public firstMonomers: string[], public secondMonomers: string[],
|
|
76
81
|
lib: IMonomerLib, public code: number, public rules: Rules) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
this.
|
|
82
|
-
|
|
83
|
-
this.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
82
|
+
const emptyFirst = !firstMonomers?.length;
|
|
83
|
+
const emptySecond = !secondMonomers?.length;
|
|
84
|
+
// if one of the lists is empty, it means that the rule is active for all monomers
|
|
85
|
+
if (emptyFirst)
|
|
86
|
+
this.firstMonomers = firstMonomers = ['C', 'D', 'E', 'F', 'G'];
|
|
87
|
+
if (emptySecond)
|
|
88
|
+
this.secondMonomers = secondMonomers = ['D', 'C', 'E', 'F', 'G'];
|
|
89
|
+
this.actionable = true;
|
|
90
|
+
const monomerGalleryFirst = ui.divH([], {style: {overflowX: 'auto', width: '100%'}});
|
|
91
|
+
const monomerGallerySecond = ui.divH([], {style: {overflowX: 'auto', width: '100%'}});
|
|
92
|
+
|
|
93
|
+
this.resulting = ui.divH([], {style: {overflowX: 'auto', width: '100%', minHeight: '150px'}});
|
|
94
|
+
const headerFirst = ui.h2('First Monomer' + (!emptyFirst ? '' : ' (Applied to all monomers, example list shown)'),
|
|
95
|
+
{style: {width: '100%'}});
|
|
96
|
+
const headerSecond = ui.h2('Second Monomer' + (!emptySecond ? '' : ' (Applied to all monomers, example list shown)'),
|
|
97
|
+
{style: {width: '100%'}});
|
|
98
|
+
const galleries = ui.divV([headerFirst, monomerGalleryFirst, headerSecond, monomerGallerySecond, this.resulting]);
|
|
99
|
+
this.cardsFirst = firstMonomers.map((symbol) => new MonomerCard(lib.getMonomer('PEPTIDE', symbol), symbol));
|
|
100
|
+
this.cardsSecond = secondMonomers.map((symbol) => new MonomerCard(lib.getMonomer('PEPTIDE', symbol), symbol));
|
|
101
|
+
|
|
102
|
+
this.cardsFirst.forEach((card) => {
|
|
103
|
+
card.root.onclick = () => {
|
|
104
|
+
this.cardsFirst.forEach((c) => c.selected = false);
|
|
105
|
+
card.selected = true;
|
|
106
|
+
this.firstCard = card;
|
|
107
|
+
this.reset();
|
|
108
|
+
//onMonomerSelected(card.monomer);
|
|
109
|
+
};
|
|
110
|
+
monomerGalleryFirst.appendChild(card.root);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
this.cardsSecond.forEach((card) => {
|
|
114
|
+
card.root.onclick = () => {
|
|
115
|
+
this.cardsSecond.forEach((c) => c.selected = false);
|
|
116
|
+
card.selected = true;
|
|
117
|
+
this.secondCard = card;
|
|
118
|
+
this.reset();
|
|
119
|
+
//onMonomerSelected(card.monomer);
|
|
120
|
+
};
|
|
121
|
+
monomerGallerySecond.appendChild(card.root);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
this.cardsFirst[0].selected = true;
|
|
125
|
+
this.cardsSecond[0].selected = true;
|
|
126
|
+
this.firstCard = this.cardsFirst[0];
|
|
127
|
+
this.secondCard = this.cardsSecond[0];
|
|
128
|
+
this.root.appendChild(galleries);
|
|
118
129
|
}
|
|
119
130
|
|
|
120
131
|
async reset() {
|
|
@@ -122,6 +133,7 @@ export class RuleCards {
|
|
|
122
133
|
const seqs: string[] = [
|
|
123
134
|
`${this.firstCard.monomer?.symbol}(${this.code})-A-A-A-A-${this.secondCard.monomer?.symbol}(${this.code})`
|
|
124
135
|
];
|
|
136
|
+
'PEPTIDE1{[NH2].A.A.A.A.D}$PEPTIDE1,PEPTIDE1,1:R2-6:R3$$$V2.0';
|
|
125
137
|
|
|
126
138
|
const helmHelper = await getHelmHelper();
|
|
127
139
|
const [helms, isLinear, positionMaps] = doPolyToolConvert(seqs, this.rules, helmHelper);
|
|
@@ -143,11 +155,28 @@ export class RuleCards {
|
|
|
143
155
|
|
|
144
156
|
const mol = resMolCol.get(0);
|
|
145
157
|
const monomerMolSvg = mol && grok.chem.checkSmiles(mol) ?
|
|
146
|
-
grok.chem.drawMolecule(mol,
|
|
147
|
-
grok.chem.drawMolecule(mol ?? '',
|
|
158
|
+
grok.chem.drawMolecule(mol, 200, 200) :
|
|
159
|
+
grok.chem.drawMolecule(mol ?? '', 200, 200);
|
|
160
|
+
|
|
161
|
+
if (mol) {
|
|
162
|
+
monomerMolSvg.style.cursor = 'pointer';
|
|
163
|
+
monomerMolSvg.onclick = () => {
|
|
164
|
+
const width = window.innerWidth - 200;
|
|
165
|
+
const height = window.innerHeight - 200;
|
|
166
|
+
const bigMol = grok.chem.checkSmiles(mol) ?
|
|
167
|
+
grok.chem.drawMolecule(mol, width, height) :
|
|
168
|
+
grok.chem.drawMolecule(mol ?? '', width, height);
|
|
169
|
+
ui.dialog({title: 'Molecule'}).add(bigMol).showModal(true);
|
|
170
|
+
};
|
|
171
|
+
ui.tooltip.bind(monomerMolSvg, 'Click to expand');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const exampleDiv = ui.divV([
|
|
175
|
+
ui.h2('Example Result:'), ui.h2(seqs[0])
|
|
176
|
+
], {style: {width: '200px'}});
|
|
148
177
|
|
|
149
178
|
ui.empty(this.resulting);
|
|
150
|
-
this.resulting.append(ui.divH([monomerMolSvg], {style: {overflowX: 'auto', width: '100%', minHeight: '150px'}}));
|
|
179
|
+
this.resulting.append(ui.divH([exampleDiv, monomerMolSvg], {style: {overflowX: 'auto', width: '100%', minHeight: '150px'}}));
|
|
151
180
|
}
|
|
152
181
|
}
|
|
153
182
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
1
2
|
import * as DG from 'datagrok-api/dg';
|
|
2
3
|
import * as grok from 'datagrok-api/grok';
|
|
3
4
|
import * as ui from 'datagrok-api/ui';
|
|
@@ -5,7 +6,9 @@ import {ActiveFiles} from '@datagrok-libraries/utils/src/settings/active-files-b
|
|
|
5
6
|
import {RulesManager} from './rule-manager';
|
|
6
7
|
import {RuleCards} from './pt-rule-cards';
|
|
7
8
|
import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
8
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
PackageFunctions} from '../../package';
|
|
11
|
+
import {MmcrTemps} from '@datagrok-libraries/bio/src/utils/cell-renderer-consts';
|
|
9
12
|
|
|
10
13
|
export const RULES_PATH = 'System:AppData/SequenceTranslator/polytool-rules/';
|
|
11
14
|
export const RULES_STORAGE_NAME = 'Polytool';
|
|
@@ -62,6 +65,15 @@ export type RuleReaction = {
|
|
|
62
65
|
name: string
|
|
63
66
|
}
|
|
64
67
|
|
|
68
|
+
export type LinkRuleRowArgs = {
|
|
69
|
+
row?: number,
|
|
70
|
+
code: number,
|
|
71
|
+
firstMonomers: string,
|
|
72
|
+
secondMonomers: string,
|
|
73
|
+
firstLinkingGroup: number,
|
|
74
|
+
secondLinkingGroup: number
|
|
75
|
+
}
|
|
76
|
+
|
|
65
77
|
export class Rules {
|
|
66
78
|
homodimerCode: string | null;
|
|
67
79
|
heterodimerCode: string | null;
|
|
@@ -94,39 +106,54 @@ export class Rules {
|
|
|
94
106
|
this.reactionRules.push(rules[j]);
|
|
95
107
|
}
|
|
96
108
|
|
|
97
|
-
getLinkRulesDf()
|
|
109
|
+
getLinkRulesDf() {
|
|
98
110
|
const length = this.linkRules.length;
|
|
99
111
|
const codeCol = DG.Column.int(NAME_CODE, length);
|
|
100
112
|
codeCol.setTag('friendlyName', 'Code');
|
|
101
113
|
//ui.tooltip.bind(codeCol.root, 'Click to zoom');
|
|
102
114
|
const firstMonomerCol = DG.Column.string(NAME_FIRST_MONOMERS, length);
|
|
115
|
+
firstMonomerCol.temp[MmcrTemps.fontSize] = 16;
|
|
103
116
|
firstMonomerCol.setTag('friendlyName', 'First monomers');
|
|
104
117
|
firstMonomerCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
105
|
-
applyNotationProviderForCyclized(firstMonomerCol, ',');
|
|
118
|
+
PackageFunctions.applyNotationProviderForCyclized(firstMonomerCol, ',');
|
|
106
119
|
|
|
107
120
|
const secondMonomerCol = DG.Column.string(NAME_SECOND_MONOMERS, length);
|
|
108
121
|
secondMonomerCol.setTag('friendlyName', 'Second monomers');
|
|
122
|
+
secondMonomerCol.temp[MmcrTemps.fontSize] = 16;
|
|
109
123
|
secondMonomerCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
110
|
-
applyNotationProviderForCyclized(secondMonomerCol, ',');
|
|
124
|
+
PackageFunctions.applyNotationProviderForCyclized(secondMonomerCol, ',');
|
|
111
125
|
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
126
|
+
const firstLinkingGroupCol = DG.Column.int(NAME_FIRST_LINK, length);
|
|
127
|
+
firstLinkingGroupCol.setTag('friendlyName', 'First group');
|
|
128
|
+
const secondLinkingGroupCol = DG.Column.int(NAME_SECOND_LINK, length);
|
|
129
|
+
secondLinkingGroupCol.setTag('friendlyName', 'Second group');
|
|
116
130
|
|
|
117
131
|
for (let i = 0; i < length; i++) {
|
|
118
132
|
codeCol.set(i, this.linkRules[i].code);
|
|
119
133
|
firstMonomerCol.set(i, this.linkRules[i].firstMonomers.toString());
|
|
120
134
|
secondMonomerCol.set(i, this.linkRules[i].secondMonomers.toString());
|
|
121
|
-
|
|
122
|
-
|
|
135
|
+
firstLinkingGroupCol.set(i, this.linkRules[i].firstLinkingGroup);
|
|
136
|
+
secondLinkingGroupCol.set(i, this.linkRules[i].secondLinkingGroup);
|
|
123
137
|
}
|
|
124
138
|
|
|
125
139
|
const res = DG.DataFrame.fromColumns([
|
|
126
|
-
codeCol, firstMonomerCol, secondMonomerCol,
|
|
140
|
+
codeCol, firstMonomerCol, secondMonomerCol, firstLinkingGroupCol, secondLinkingGroupCol
|
|
127
141
|
]);
|
|
128
142
|
|
|
129
|
-
|
|
143
|
+
const addNewRow = (rowObj: LinkRuleRowArgs) => {
|
|
144
|
+
if (rowObj.row != undefined && rowObj.row < res.rowCount && rowObj.row >= 0) {
|
|
145
|
+
codeCol.set(rowObj.row, rowObj.code);
|
|
146
|
+
firstMonomerCol.set(rowObj.row, rowObj.firstMonomers);
|
|
147
|
+
secondMonomerCol.set(rowObj.row, rowObj.secondMonomers);
|
|
148
|
+
firstLinkingGroupCol.set(rowObj.row, rowObj.firstLinkingGroup);
|
|
149
|
+
secondLinkingGroupCol.set(rowObj.row, rowObj.secondLinkingGroup);
|
|
150
|
+
} else {
|
|
151
|
+
const {code, firstMonomers, secondMonomers, firstLinkingGroup, secondLinkingGroup} = rowObj;
|
|
152
|
+
res.rows.addNew([code, firstMonomers ?? '', secondMonomers ?? '', firstLinkingGroup ?? 1, secondLinkingGroup ?? 2]);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return {res, addNewRow};
|
|
130
157
|
}
|
|
131
158
|
|
|
132
159
|
async getLinkCards(): Promise<RuleCards[]> {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
/* eslint-disable max-len */
|
|
1
2
|
import * as DG from 'datagrok-api/dg';
|
|
2
3
|
import * as grok from 'datagrok-api/grok';
|
|
3
4
|
import * as ui from 'datagrok-api/ui';
|
|
4
|
-
import {getMonomerPairs, getRules, Rules} from './pt-rules';
|
|
5
|
-
import {_package,
|
|
5
|
+
import {getMonomerPairs, getRules, LinkRuleRowArgs, Rules} from './pt-rules';
|
|
6
|
+
import {_package, PackageFunctions} from '../../package';
|
|
6
7
|
import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
7
8
|
import {doPolyToolConvert} from './pt-conversion';
|
|
8
9
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
@@ -24,13 +25,16 @@ export class RulesManager {
|
|
|
24
25
|
heteroDimerInput: DG.InputBase;
|
|
25
26
|
|
|
26
27
|
linkCards: RuleCards[];
|
|
28
|
+
addLinkRulesFunc: (rowObj: LinkRuleRowArgs) => void;
|
|
27
29
|
|
|
28
30
|
// every rule set will have its editor instance
|
|
29
31
|
private static instances: Record<string, RulesManager> = {};
|
|
30
32
|
|
|
31
33
|
protected constructor(rules: Rules, fileName: string) {
|
|
32
34
|
this.rules = rules;
|
|
33
|
-
|
|
35
|
+
const linksRes = this.rules.getLinkRulesDf();
|
|
36
|
+
this.linkRuleDataFrame = linksRes.res;
|
|
37
|
+
this.addLinkRulesFunc = linksRes.addNewRow;
|
|
34
38
|
|
|
35
39
|
this.synthRuleDataFrame = this.rules.getSynthesisRulesDf();
|
|
36
40
|
this.fileName = fileName;
|
|
@@ -138,7 +142,7 @@ export class RulesManager {
|
|
|
138
142
|
const initCol = DG.Column.fromStrings('Monomers', seqs);
|
|
139
143
|
const helmCol = DG.Column.fromStrings('Helm', helms);
|
|
140
144
|
|
|
141
|
-
applyNotationProviderForCyclized(initCol, '-');
|
|
145
|
+
PackageFunctions.applyNotationProviderForCyclized(initCol, '-');
|
|
142
146
|
initCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
143
147
|
|
|
144
148
|
helmCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
@@ -168,7 +172,7 @@ export class RulesManager {
|
|
|
168
172
|
const helmCol = DG.Column.fromStrings('Helm', helms);
|
|
169
173
|
|
|
170
174
|
initCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
171
|
-
applyNotationProviderForCyclized(initCol, '-');
|
|
175
|
+
PackageFunctions.applyNotationProviderForCyclized(initCol, '-');
|
|
172
176
|
|
|
173
177
|
helmCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
174
178
|
helmCol.meta.units = NOTATION.HELM;
|
|
@@ -179,10 +183,26 @@ export class RulesManager {
|
|
|
179
183
|
}
|
|
180
184
|
|
|
181
185
|
async getForm() {
|
|
182
|
-
|
|
186
|
+
const gridOptions: Partial<DG.IGridSettings> = {showAddNewRowIcon: false, allowEdit: false, rowHeight: 60};
|
|
187
|
+
|
|
188
|
+
const linksGrid = this.linkRuleDataFrame.plot.grid(gridOptions);
|
|
189
|
+
linksGrid.onCellDoubleClick.subscribe(() => {
|
|
190
|
+
if (!linksGrid.dataFrame || linksGrid.dataFrame.currentRowIdx == -1 || linksGrid.dataFrame.currentRowIdx == undefined)
|
|
191
|
+
return;
|
|
192
|
+
const idx = linksGrid.dataFrame.currentRowIdx;
|
|
193
|
+
const editArgs: LinkRuleRowArgs = {
|
|
194
|
+
row: idx,
|
|
195
|
+
code: this.linkRuleDataFrame.get('code', idx),
|
|
196
|
+
firstMonomers: this.linkRuleDataFrame.get('firstMonomers', idx),
|
|
197
|
+
secondMonomers: this.linkRuleDataFrame.get('secondMonomers', idx),
|
|
198
|
+
firstLinkingGroup: this.linkRuleDataFrame.get('firstLinkingGroup', idx),
|
|
199
|
+
secondLinkingGroup: this.linkRuleDataFrame.get('secondLinkingGroup', idx),
|
|
200
|
+
};
|
|
201
|
+
this.getAddNewLinkRuleDialog(editArgs);
|
|
202
|
+
});
|
|
183
203
|
|
|
184
204
|
const linksGridDiv = this.createGridDiv('Rules',
|
|
185
|
-
|
|
205
|
+
linksGrid,
|
|
186
206
|
'specification for monomers to link and linking positions');
|
|
187
207
|
const linkExamples = this.createGridDiv('Examples', await this.getLinkExamplesGrid(),
|
|
188
208
|
'specification for monomers to link and linking positions');
|
|
@@ -205,7 +225,7 @@ export class RulesManager {
|
|
|
205
225
|
this.linkRuleDataFrame.currentRowIdx = 0;
|
|
206
226
|
this.linkRuleDataFrame.onCurrentRowChanged.subscribe(async () => {
|
|
207
227
|
const idx = this.linkRuleDataFrame.currentRowIdx;
|
|
208
|
-
if (idx !== -1) {
|
|
228
|
+
if (idx !== -1 && idx != undefined) {
|
|
209
229
|
ui.empty(gridDiv);
|
|
210
230
|
gridDiv.append(ui.splitV([
|
|
211
231
|
ui.box(
|
|
@@ -214,10 +234,9 @@ export class RulesManager {
|
|
|
214
234
|
),
|
|
215
235
|
this.linkCards[idx].root,
|
|
216
236
|
]));
|
|
237
|
+
this.linkCards[idx].render();
|
|
238
|
+
await this.linkCards[idx].reset();
|
|
217
239
|
}
|
|
218
|
-
|
|
219
|
-
this.linkCards[idx].render();
|
|
220
|
-
await this.linkCards[idx].reset();
|
|
221
240
|
});
|
|
222
241
|
|
|
223
242
|
const links = ui.splitH([linksGridDiv, gridDiv], null, true);
|
|
@@ -260,7 +279,7 @@ export class RulesManager {
|
|
|
260
279
|
const addButton = ui.button('Add rule', () => {
|
|
261
280
|
const currentTab = inputsTabControl.currentPane.name;
|
|
262
281
|
if (currentTab == TAB_LINKS)
|
|
263
|
-
this.
|
|
282
|
+
this.getAddNewLinkRuleDialog();
|
|
264
283
|
else if (currentTab == TAB_REACTIONS)
|
|
265
284
|
this.synthRuleDataFrame.rows.addNew();
|
|
266
285
|
});
|
|
@@ -272,5 +291,39 @@ export class RulesManager {
|
|
|
272
291
|
|
|
273
292
|
return inputsTabControl.root;
|
|
274
293
|
}
|
|
294
|
+
|
|
295
|
+
getAddNewLinkRuleDialog(preset?: Partial<LinkRuleRowArgs>): void {
|
|
296
|
+
const codeInput = ui.input.int('Code', {nullable: false, value: preset?.code});
|
|
297
|
+
const firstMonomersInput = ui.input.string('First monomers', {placeholder: 'E.g. C,D,E', value: preset?.firstMonomers,
|
|
298
|
+
tooltipText: 'Comma separated list of first monomers applicable for the rule. If left empty, all monomers will be considered', nullable: true});
|
|
299
|
+
const secondMonomersInput = ui.input.string('Second monomers', {placeholder: 'E.g. C,D,E', value: preset?.secondMonomers,
|
|
300
|
+
tooltipText: 'Comma separated list of second monomers applicable for the rule. If left empty, all monomers will be considered', nullable: true});
|
|
301
|
+
const firstLinkingGroup = preset?.firstLinkingGroup ? `R${preset.firstLinkingGroup}` : 'R3';
|
|
302
|
+
const secondLinkingGroup = preset?.secondLinkingGroup ? `R${preset.secondLinkingGroup}` : 'R3';
|
|
303
|
+
const firstLinkingGroupInput = ui.input.choice('First linking group', {value: firstLinkingGroup, items: ['R1', 'R2', 'R3', 'R4'],
|
|
304
|
+
tooltipText: 'Specifies which R-group of the first monomer will be used for linking', nullable: false});
|
|
305
|
+
const secondLinkingGroupInput = ui.input.choice('Second linking group', {value: secondLinkingGroup, items: ['R1', 'R2', 'R3', 'R4'],
|
|
306
|
+
tooltipText: 'Specifies which R-group of the second monomer will be used for linking', nullable: false});
|
|
307
|
+
ui.dialog('Add new link rule')
|
|
308
|
+
.add(codeInput)
|
|
309
|
+
.add(firstMonomersInput)
|
|
310
|
+
.add(secondMonomersInput)
|
|
311
|
+
.add(firstLinkingGroupInput)
|
|
312
|
+
.add(secondLinkingGroupInput)
|
|
313
|
+
.onOK(async () => {
|
|
314
|
+
// we rely on validation of inputs by DG inputs
|
|
315
|
+
const code = codeInput.value!;
|
|
316
|
+
const firstMonomers = (firstMonomersInput.value ?? '').split(',').map((s) => s.trim()).filter((s) => s).join(',');
|
|
317
|
+
const secondMonomers = (secondMonomersInput.value ?? '').split(',').map((s) => s.trim()).filter((s) => s).join(',');
|
|
318
|
+
const firstLinkingGroup = parseInt(firstLinkingGroupInput.value!.substring(1));
|
|
319
|
+
const secondLinkingGroup = parseInt(secondLinkingGroupInput.value!.substring(1));
|
|
320
|
+
this.addLinkRulesFunc({code, firstMonomers: firstMonomers ?? '', secondMonomers: secondMonomers ?? '',
|
|
321
|
+
firstLinkingGroup, secondLinkingGroup, row: preset?.row});
|
|
322
|
+
|
|
323
|
+
this.rules.setLinkRules(this.linkRuleDataFrame);
|
|
324
|
+
this.linkCards = await this.rules.getLinkCards();
|
|
325
|
+
this.save();
|
|
326
|
+
}).show();
|
|
327
|
+
}
|
|
275
328
|
}
|
|
276
329
|
|
|
@@ -32,7 +32,7 @@ import {RuleInputs, RULES_PATH, RULES_STORAGE_NAME} from './conversion/pt-rules'
|
|
|
32
32
|
import {Chain} from './conversion/pt-chain';
|
|
33
33
|
import {polyToolConvert} from './pt-dialog';
|
|
34
34
|
|
|
35
|
-
import {_package,
|
|
35
|
+
import {_package, PackageFunctions} from '../package';
|
|
36
36
|
import {buildMonomerHoverLink} from '@datagrok-libraries/bio/src/monomer-works/monomer-hover';
|
|
37
37
|
import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
|
|
38
38
|
|
|
@@ -723,14 +723,14 @@ async function polyToolEnumerateSeq(
|
|
|
723
723
|
enumCol = DG.Column.fromList(DG.COLUMN_TYPE.STRING, 'Enumerated', templateList);
|
|
724
724
|
enumCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
725
725
|
enumCol.setTag(PolyToolTags.dataRole, PolyToolDataRole.template);
|
|
726
|
-
applyNotationProviderForCyclized(enumCol, '-');
|
|
726
|
+
PackageFunctions.applyNotationProviderForCyclized(enumCol, '-');
|
|
727
727
|
break;
|
|
728
728
|
}
|
|
729
729
|
}
|
|
730
730
|
const enumeratorResDf = DG.DataFrame.fromColumns([enumCol]);
|
|
731
731
|
await grok.data.detectSemanticTypes(enumeratorResDf);
|
|
732
732
|
if (dataRole == PolyToolDataRole.template)
|
|
733
|
-
applyNotationProviderForCyclized(enumCol, '-');
|
|
733
|
+
PackageFunctions.applyNotationProviderForCyclized(enumCol, '-');
|
|
734
734
|
|
|
735
735
|
|
|
736
736
|
if (toAtomicLevel) {
|
|
@@ -76,14 +76,14 @@ category('PolyTool: Convert', () => {
|
|
|
76
76
|
'cyclized-D(2)-NH2(2)-3-0': {
|
|
77
77
|
src: {seq: 'R-F-D(2)-T-G-H-F-Y-P-NH2(2)'},
|
|
78
78
|
tgt: {
|
|
79
|
-
helm: 'PEPTIDE1{R.F.D.T.G.H.F.Y.P.[NH2]}$PEPTIDE1,PEPTIDE1,10:R2
|
|
79
|
+
helm: 'PEPTIDE1{R.F.D.T.G.H.F.Y.P.[NH2]}$PEPTIDE1,PEPTIDE1,3:R3-10:R2$$$V2.0',
|
|
80
80
|
mol: {atomCount: 81, bondCount: 86, inchiKey: 'CBMGNYKOZWNVNK-AHGCAHLCSA-N'},
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
83
|
'cyclized-D(2)-NH2(2)-0-0': {
|
|
84
84
|
src: {seq: 'D(2)-T-G-H-F-Y-P-NH2(2)'},
|
|
85
85
|
tgt: {
|
|
86
|
-
helm: 'PEPTIDE1{D.T.G.H.F.Y.P.[NH2]}$PEPTIDE1,PEPTIDE1,8:R2
|
|
86
|
+
helm: 'PEPTIDE1{D.T.G.H.F.Y.P.[NH2]}$PEPTIDE1,PEPTIDE1,1:R3-8:R2$$$V2.0',
|
|
87
87
|
mol: {atomCount: 59, bondCount: 63, inchiKey: 'HGRHAUQBJXFERJ-MUFWPYSASA-N'},
|
|
88
88
|
}
|
|
89
89
|
},
|