@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.
@@ -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
- if (firstMonomers.length > 0) {
78
- this.actionable = true;
79
- const monomerGalleryFirst = ui.divH([], {style: {overflowX: 'auto', width: '100%'}});
80
- const monomerGallerySecond = ui.divH([], {style: {overflowX: 'auto', width: '100%'}});
81
- this.resulting = ui.divH([], {style: {overflowX: 'auto', width: '100%', minHeight: '150px'}});
82
- const galleries = ui.divV([monomerGalleryFirst, monomerGallerySecond, this.resulting]);
83
- this.cardsFirst = firstMonomers.map((symbol) => new MonomerCard(lib.getMonomer('PEPTIDE', symbol)));
84
- this.cardsSecond = secondMonomers.map((symbol) => new MonomerCard(lib.getMonomer('PEPTIDE', symbol)));
85
-
86
- this.cardsFirst.forEach((card) => {
87
- card.root.onclick = () => {
88
- this.cardsFirst.forEach((c) => c.selected = false);
89
- card.selected = true;
90
- this.firstCard = card;
91
- this.reset();
92
- //onMonomerSelected(card.monomer);
93
- };
94
- monomerGalleryFirst.appendChild(card.root);
95
- });
96
-
97
- this.cardsSecond.forEach((card) => {
98
- card.root.onclick = () => {
99
- this.cardsSecond.forEach((c) => c.selected = false);
100
- card.selected = true;
101
- this.secondCard = card;
102
- this.reset();
103
- //onMonomerSelected(card.monomer);
104
- };
105
- monomerGallerySecond.appendChild(card.root);
106
- });
107
-
108
- this.cardsFirst[0].selected = true;
109
- this.cardsSecond[0].selected = true;
110
- this.firstCard = this.cardsFirst[0];
111
- this.secondCard = this.cardsSecond[0];
112
- this.root.appendChild(galleries);
113
- } else {
114
- const es = ui.divV(['Rule is active for all monomers, no examples to show']);
115
- this.root.appendChild(es);
116
- this.actionable = false;
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, 150, 120) :
147
- grok.chem.drawMolecule(mol ?? '', 150, 120);
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 {applyNotationProviderForCyclized} from '../../package';
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(): DG.DataFrame {
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 firstLinkingGroup = DG.Column.int(NAME_FIRST_LINK, length);
113
- firstLinkingGroup.setTag('friendlyName', 'First group');
114
- const secondLinkingGroup = DG.Column.int(NAME_SECOND_LINK, length);
115
- secondLinkingGroup.setTag('friendlyName', 'Second group');
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
- firstLinkingGroup.set(i, this.linkRules[i].firstLinkingGroup);
122
- secondLinkingGroup.set(i, this.linkRules[i].secondLinkingGroup);
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, firstLinkingGroup, secondLinkingGroup
140
+ codeCol, firstMonomerCol, secondMonomerCol, firstLinkingGroupCol, secondLinkingGroupCol
127
141
  ]);
128
142
 
129
- return res;
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, applyNotationProviderForCyclized} from '../../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
- this.linkRuleDataFrame = this.rules.getLinkRulesDf();
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
- inputsTabControl: DG.TabControl;
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
- this.linkRuleDataFrame.plot.grid({showAddNewRowIcon: true}),
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.linkRuleDataFrame.rows.addNew();
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
 
@@ -7,9 +7,9 @@
7
7
  align-items: center;
8
8
  cursor: pointer;
9
9
  width: 200px;
10
- height: 210px;
10
+ height: 240px;
11
11
  min-width: 200px;
12
- min-height: 210px;
12
+ min-height: 240px;
13
13
  }
14
14
 
15
15
  .monomer-card-info-rules {
@@ -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, applyNotationProviderForCyclized} from '../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-3:R3$$$V2.0',
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-1:R3$$$V2.0',
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
  },