@datagrok/sequence-translator 1.10.11 → 1.10.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/CLAUDE.md +0 -12
- package/dist/455.js +1 -1
- package/dist/455.js.map +1 -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/package.json +5 -5
- package/src/apps/common/view/components/colored-input/style.css +3 -1
- package/src/apps/structure/view/style.css +15 -3
- package/src/apps/structure/view/ui.ts +2 -8
- package/src/apps/translator/view/ui.ts +7 -5
- package/src/package.ts +3 -1
- package/src/polytool/const.ts +3 -3
- package/src/polytool/pt-dialog.ts +9 -1
- package/src/polytool/pt-enumerate-seq-dialog.ts +42 -33
- package/test-console-output-1.log +106 -214
- package/test-record-1.mp4 +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "1.10.
|
|
4
|
+
"version": "1.10.13",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Davit Rizhinashvili",
|
|
7
7
|
"email": "drizhinashvili@datagrok.ai"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
}
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@datagrok-libraries/bio": "^5.
|
|
25
|
+
"@datagrok-libraries/bio": "^5.63.6",
|
|
26
26
|
"@datagrok-libraries/chem-meta": "^1.2.8",
|
|
27
27
|
"@datagrok-libraries/tutorials": "^1.6.1",
|
|
28
28
|
"@datagrok-libraries/utils": "^4.6.5",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@datagrok-libraries/helm-web-editor": "^1.1.16",
|
|
44
44
|
"@datagrok-libraries/js-draw-lite": "^0.0.10",
|
|
45
|
-
"@datagrok/bio": "^2.
|
|
46
|
-
"@datagrok/chem": "^1.
|
|
47
|
-
"@datagrok/helm": "^2.
|
|
45
|
+
"@datagrok/bio": "^2.26.0",
|
|
46
|
+
"@datagrok/chem": "^1.17.0",
|
|
47
|
+
"@datagrok/helm": "^2.13.0",
|
|
48
48
|
"@types/jquery": "^3.5.32",
|
|
49
49
|
"@types/js-yaml": "^4.0.5",
|
|
50
50
|
"@types/lodash": "^4.14.202",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
.st-colored-text-input > textarea {
|
|
2
2
|
width: 100%;
|
|
3
|
-
|
|
3
|
+
color: transparent !important;
|
|
4
|
+
caret-color: var(--grey-6);
|
|
5
|
+
-webkit-text-fill-color: transparent !important;
|
|
4
6
|
background-color: transparent;
|
|
5
7
|
position: relative;
|
|
6
8
|
z-index: 1;
|
|
@@ -2,11 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
.st-structure-body {
|
|
4
4
|
padding-right: 20px;
|
|
5
|
+
height: 100%;
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
5
8
|
}
|
|
6
9
|
|
|
7
10
|
.st-structure-mol-img {
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
flex: 1 1 0;
|
|
12
|
+
min-height: 100px;
|
|
13
|
+
min-width: 0;
|
|
14
|
+
transform: translateX(-50px);
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.st-structure-mol-img canvas {
|
|
19
|
+
max-width: 100% !important;
|
|
20
|
+
height: auto !important;
|
|
10
21
|
}
|
|
11
22
|
|
|
12
23
|
.st-structure-bool-button-block {
|
|
@@ -15,8 +26,9 @@
|
|
|
15
26
|
}
|
|
16
27
|
|
|
17
28
|
.st-structure-bottom {
|
|
18
|
-
flex
|
|
29
|
+
flex: 1 1 0;
|
|
19
30
|
padding-top: 20px;
|
|
31
|
+
min-height: 0;
|
|
20
32
|
}
|
|
21
33
|
|
|
22
34
|
.st-structure-clear-buttons {
|
|
@@ -52,7 +52,6 @@ class StructureAppLayout {
|
|
|
52
52
|
);
|
|
53
53
|
this.moleculeImgDiv = ui.block([]);
|
|
54
54
|
$(this.moleculeImgDiv).addClass('st-structure-mol-img');
|
|
55
|
-
|
|
56
55
|
DG.debounce<string>(this.onInput, 300).subscribe(async () => {
|
|
57
56
|
await this.updateMoleculeImg();
|
|
58
57
|
});
|
|
@@ -74,7 +73,7 @@ class StructureAppLayout {
|
|
|
74
73
|
const tableLayout = this.getTableInput(th);
|
|
75
74
|
const boolInputsAndButton = this.getBoolInputsAndButton();
|
|
76
75
|
await this.updateMoleculeImg();
|
|
77
|
-
const bottomDiv = ui.divH([
|
|
76
|
+
const bottomDiv = ui.divH([this.moleculeImgDiv, boolInputsAndButton]);
|
|
78
77
|
$(bottomDiv).addClass('st-structure-bottom');
|
|
79
78
|
|
|
80
79
|
const layout = ui.divV([tableLayout, bottomDiv]);
|
|
@@ -186,13 +185,8 @@ class StructureAppLayout {
|
|
|
186
185
|
const errStr = errorToConsole(err);
|
|
187
186
|
console.error(errStr);
|
|
188
187
|
}
|
|
189
|
-
// todo: compute relative numbers
|
|
190
|
-
const canvasWidth = 650;
|
|
191
|
-
const canvasHeight = 150;
|
|
192
188
|
const molImgObj = new MoleculeImage(molfile);
|
|
193
|
-
await molImgObj.drawMolecule(this.moleculeImgDiv,
|
|
194
|
-
// should the canvas be returned from the above function?
|
|
195
|
-
$(this.moleculeImgDiv).find('canvas').css('float', 'inherit');
|
|
189
|
+
await molImgObj.drawMolecule(this.moleculeImgDiv, 650, 150);
|
|
196
190
|
}
|
|
197
191
|
}
|
|
198
192
|
|
|
@@ -56,8 +56,6 @@ class TranslatorAppLayout {
|
|
|
56
56
|
}
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
-
$(this.formatChoiceInput.root.getElementsByTagName('select')[0]).css('width', '20%');
|
|
60
|
-
|
|
61
59
|
this.sequenceInputBase = ui.input.textArea(
|
|
62
60
|
'', {value: DEFAULT_AXOLABS_INPUT, onValueChanged: () => { this.onInput.next(); }}
|
|
63
61
|
);
|
|
@@ -235,9 +233,13 @@ class TranslatorAppLayout {
|
|
|
235
233
|
}
|
|
236
234
|
|
|
237
235
|
private saveMolfile(): void {
|
|
238
|
-
|
|
239
|
-
this.
|
|
240
|
-
|
|
236
|
+
try {
|
|
237
|
+
const result = (new SequenceToMolfileConverter(this.sequence, false,
|
|
238
|
+
this.formatChoiceInput.value!)).convert() + '\n$$$$';
|
|
239
|
+
download(this.sequence + '.sdf', encodeURIComponent(result));
|
|
240
|
+
} catch (e: any) {
|
|
241
|
+
grok.shell.warning('Unable to save SDF: ' + e.message);
|
|
242
|
+
}
|
|
241
243
|
}
|
|
242
244
|
|
|
243
245
|
private copySmiles(): void {
|
package/src/package.ts
CHANGED
|
@@ -3,7 +3,7 @@ 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 {NOTATION, NOTATION_PROVIDER_CONSTRUCTOR_ROLE} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
6
|
+
import {BioTags, NOTATION, NOTATION_PROVIDER_CONSTRUCTOR_ROLE} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
7
7
|
import {SeqTemps} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
|
|
8
8
|
|
|
9
9
|
import {OligoToolkitPackage} from './apps/common/model/oligo-toolkit-package';
|
|
@@ -397,6 +397,8 @@ export class PackageFunctions {
|
|
|
397
397
|
col.setTag('alphabet', 'UN');
|
|
398
398
|
col.setTag('.alphabetIsMultichar', 'true');
|
|
399
399
|
col.meta.units = NOTATION.CUSTOM;
|
|
400
|
+
if (separator && !col.tags[BioTags.separator])
|
|
401
|
+
col.tags[BioTags.separator] = separator;
|
|
400
402
|
col.tags[PolyToolTags.dataRole] = 'template';
|
|
401
403
|
col.temp[SeqTemps.notationProvider] = new CyclizedNotationProvider(separator, _package.helmHelper);
|
|
402
404
|
}
|
package/src/polytool/const.ts
CHANGED
|
@@ -36,9 +36,9 @@ export const PT_UI_LINEARIZE = 'Linearize';
|
|
|
36
36
|
export const PT_UI_LINEARIZE_TT = 'Make representation linear if possible';
|
|
37
37
|
export const PT_UI_USE_CHIRALITY = 'Chirality engine';
|
|
38
38
|
export const PT_UI_HIGHLIGHT_MONOMERS = 'Highlight monomers';
|
|
39
|
-
export const PT_UI_DIALOG_CONVERSION = '
|
|
40
|
-
export const PT_UI_DIALOG_UNRULE = '
|
|
41
|
-
export const PT_UI_DIALOG_ENUMERATION = '
|
|
39
|
+
export const PT_UI_DIALOG_CONVERSION = 'PolyTool Conversion';
|
|
40
|
+
export const PT_UI_DIALOG_UNRULE = 'PolyTool Unrule';
|
|
41
|
+
export const PT_UI_DIALOG_ENUMERATION = 'PolyTool Enumeration';
|
|
42
42
|
export const PT_UI_RULES_USED = 'Rules used';
|
|
43
43
|
|
|
44
44
|
export const PT_ENUM_TYPE_TOOLTIPS: Record<string, string> = {
|
|
@@ -208,7 +208,14 @@ async function getPolyToolEnumerationChemDialog(cell?: DG.Cell): Promise<DG.Dial
|
|
|
208
208
|
molInput.setMolFile(molfileValue);
|
|
209
209
|
|
|
210
210
|
//const helmInput = helmHelper.createHelmInput('Macromolecule', {value: helmValue});
|
|
211
|
-
const screenLibraryInput = ui.input.choice('Library to use', {
|
|
211
|
+
const screenLibraryInput = ui.input.choice('Library to use', {
|
|
212
|
+
value: libList.length ? libList[0] : null,
|
|
213
|
+
items: libList,
|
|
214
|
+
nullable: false,
|
|
215
|
+
onValueChanged: () => {
|
|
216
|
+
dialog.getButton('OK').disabled = screenLibraryInput.value === null;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
212
219
|
|
|
213
220
|
molInput.root.setAttribute('style', `min-width:250px!important;`);
|
|
214
221
|
molInput.root.setAttribute('style', `max-width:250px!important;`);
|
|
@@ -268,6 +275,7 @@ async function getPolyToolEnumerationChemDialog(cell?: DG.Cell): Promise<DG.Dial
|
|
|
268
275
|
molInput.setMolFile(x.mol);
|
|
269
276
|
screenLibraryInput.value = x.screenLibrary;
|
|
270
277
|
});
|
|
278
|
+
dialog.getButton('OK').disabled = screenLibraryInput.value === null;
|
|
271
279
|
return dialog;
|
|
272
280
|
} catch (err: any) {
|
|
273
281
|
destroy();
|
|
@@ -16,7 +16,6 @@ import {helmTypeToPolymerType} from '@datagrok-libraries/bio/src/monomer-works/m
|
|
|
16
16
|
import {getSeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
17
17
|
import '@datagrok-libraries/bio/src/types/input';
|
|
18
18
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
19
|
-
import {InputColumnBase} from '@datagrok-libraries/bio/src/types/input';
|
|
20
19
|
import {SeqValueBase} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
|
|
21
20
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
22
21
|
import {SeqTemps} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
|
|
@@ -60,7 +59,8 @@ type PolyToolEnumerateInputs = {
|
|
|
60
59
|
placeholders: PolyToolPlaceholdersInput;
|
|
61
60
|
placeholdersBreadth: PolyToolPlaceholdersBreadthInput;
|
|
62
61
|
enumeratorType: DG.ChoiceInput<PolyToolEnumeratorType>
|
|
63
|
-
|
|
62
|
+
trivialName: DG.InputBase<string>,
|
|
63
|
+
appendToTable: DG.InputBase<DG.DataFrame | null>,
|
|
64
64
|
keepOriginal: DG.InputBase<boolean>;
|
|
65
65
|
toAtomicLevel: DG.InputBase<boolean>;
|
|
66
66
|
generateHelm: DG.InputBase<boolean>;
|
|
@@ -75,7 +75,7 @@ type PolyToolEnumerateHelmSerialized = {
|
|
|
75
75
|
placeholders: string;
|
|
76
76
|
placeholdersBreadth: string;
|
|
77
77
|
enumeratorType: PolyToolEnumeratorType;
|
|
78
|
-
|
|
78
|
+
trivialName: string;
|
|
79
79
|
keepOriginal: boolean;
|
|
80
80
|
toAtomicLevel: boolean;
|
|
81
81
|
generateHelm: boolean;
|
|
@@ -170,7 +170,6 @@ async function getPolyToolEnumerateDialog(
|
|
|
170
170
|
const libHelper = await getMonomerLibHelper();
|
|
171
171
|
const monomerLib = libHelper.getMonomerLib();
|
|
172
172
|
const seqHelper = await getSeqHelper();
|
|
173
|
-
const emptyDf: DG.DataFrame = DG.DataFrame.fromColumns([]);
|
|
174
173
|
|
|
175
174
|
const helmHelper = await getHelmHelper();
|
|
176
175
|
const monomerLibFuncs = helmHelper.buildMonomersFuncsFromLib(monomerLib);
|
|
@@ -216,7 +215,6 @@ async function getPolyToolEnumerateDialog(
|
|
|
216
215
|
let srcId: { value: string, colName: string } | null = null;
|
|
217
216
|
let ruleFileList: string[];
|
|
218
217
|
let ruleInputs: RuleInputs;
|
|
219
|
-
const trivialNameSampleDiv = ui.divText('', {style: {marginLeft: '8px', marginTop: '2px'}});
|
|
220
218
|
const warningsTextDiv = ui.divText('', {style: {color: 'red'}});
|
|
221
219
|
const resultCountDiv = ui.divText('', {style: {
|
|
222
220
|
fontSize: '11px', color: 'var(--grey-4)', marginTop: '2px', marginLeft: '4px', whiteSpace: 'nowrap',
|
|
@@ -291,22 +289,17 @@ async function getPolyToolEnumerateDialog(
|
|
|
291
289
|
onValueChanged: (value: string[]) => { ruleFileList = value; }
|
|
292
290
|
})).getForm()
|
|
293
291
|
},
|
|
294
|
-
|
|
292
|
+
trivialName: ui.input.string(
|
|
295
293
|
'Trivial name', {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
onValueChanged: (): void => {
|
|
301
|
-
const valueCol = inputs.trivialNameCol.value;
|
|
302
|
-
let newSrcId: typeof srcId = null;
|
|
303
|
-
if (cell && valueCol) {
|
|
304
|
-
const originalId = valueCol.get(cell.rowIndex)!;
|
|
305
|
-
newSrcId = {value: originalId, colName: valueCol.name};
|
|
306
|
-
}
|
|
307
|
-
srcId = newSrcId;
|
|
308
|
-
trivialNameSampleDiv.textContent = srcId ? `Original ID: ${srcId.value}` : '';
|
|
294
|
+
value: '',
|
|
295
|
+
onValueChanged: (value: string): void => {
|
|
296
|
+
const trimmed = value?.trim();
|
|
297
|
+
srcId = trimmed ? {value: trimmed, colName: 'Trivial name'} : null;
|
|
309
298
|
},
|
|
299
|
+
}),
|
|
300
|
+
appendToTable: ui.input.table(
|
|
301
|
+
'Append to table', {
|
|
302
|
+
items: grok.shell.tables,
|
|
310
303
|
nullable: true,
|
|
311
304
|
}),
|
|
312
305
|
};
|
|
@@ -319,7 +312,22 @@ async function getPolyToolEnumerateDialog(
|
|
|
319
312
|
};
|
|
320
313
|
updateEnumTypeTooltip();
|
|
321
314
|
|
|
322
|
-
|
|
315
|
+
// Attach a "pick from column" icon button to the trivial name input
|
|
316
|
+
if (cell?.dataFrame) {
|
|
317
|
+
const colIcon = ui.iconFA('columns', (e: MouseEvent) => {
|
|
318
|
+
DG.Menu.popup()
|
|
319
|
+
.singleColumnSelector(cell.dataFrame, {
|
|
320
|
+
columnFilter: (col: DG.Column) => col.type === DG.COLUMN_TYPE.STRING && col !== cell.column,
|
|
321
|
+
onChange: (_grid, col: DG.Column, currentRowChanged: boolean) => {
|
|
322
|
+
if (currentRowChanged)
|
|
323
|
+
inputs.trivialName.value = col.get(cell.rowIndex) ?? '';
|
|
324
|
+
},
|
|
325
|
+
})
|
|
326
|
+
.show({x: e.clientX, y: e.clientY});
|
|
327
|
+
}, 'Pick trivial name from a column');
|
|
328
|
+
inputs.trivialName.addOptions(colIcon);
|
|
329
|
+
}
|
|
330
|
+
inputs.trivialName.root.style.maxWidth = '450px';
|
|
323
331
|
|
|
324
332
|
// Wire up monomer cell double-click to open selection dialog
|
|
325
333
|
inputs.placeholders.onMonomerCellEdit = async (position: number, currentMonomers: string[]) => {
|
|
@@ -634,14 +642,7 @@ async function getPolyToolEnumerateDialog(
|
|
|
634
642
|
}
|
|
635
643
|
};
|
|
636
644
|
|
|
637
|
-
const fillTrivialNameList = (
|
|
638
|
-
if (table) {
|
|
639
|
-
inputs.trivialNameCol.setColumnInputTable(table);
|
|
640
|
-
inputs.trivialNameCol.root.style.removeProperty('display');
|
|
641
|
-
} else {
|
|
642
|
-
inputs.trivialNameCol.setColumnInputTable(emptyDf);
|
|
643
|
-
inputs.trivialNameCol.root.style.setProperty('display', 'none');
|
|
644
|
-
}
|
|
645
|
+
const fillTrivialNameList = (_table?: DG.DataFrame) => {
|
|
645
646
|
if (resizeInputs)
|
|
646
647
|
resizeInputs();
|
|
647
648
|
};
|
|
@@ -711,7 +712,13 @@ async function getPolyToolEnumerateDialog(
|
|
|
711
712
|
rules: await ruleInputs.getActive()
|
|
712
713
|
} : false,
|
|
713
714
|
helmHelper);
|
|
714
|
-
|
|
715
|
+
const appendTarget = inputs.appendToTable.value;
|
|
716
|
+
if (appendTarget) {
|
|
717
|
+
appendTarget.append(enumeratorResDf, true);
|
|
718
|
+
appendTarget.meta.detectSemanticTypes();
|
|
719
|
+
} else {
|
|
720
|
+
grok.shell.addTableView(enumeratorResDf);
|
|
721
|
+
}
|
|
715
722
|
}
|
|
716
723
|
} catch (err: any) {
|
|
717
724
|
defaultErrorHandler(err);
|
|
@@ -735,8 +742,9 @@ async function getPolyToolEnumerateDialog(
|
|
|
735
742
|
{style: {width: '100%'}}))
|
|
736
743
|
.add(ui.divH([
|
|
737
744
|
ui.divV([
|
|
738
|
-
inputs.
|
|
739
|
-
inputs.keepOriginal.root
|
|
745
|
+
inputs.trivialName.root,
|
|
746
|
+
inputs.keepOriginal.root,
|
|
747
|
+
inputs.appendToTable.root],
|
|
740
748
|
{style: {width: '50%'}}),
|
|
741
749
|
ui.divV([
|
|
742
750
|
ui.divH([inputs.toAtomicLevel.root, inputs.generateHelm.root]),
|
|
@@ -767,7 +775,7 @@ async function getPolyToolEnumerateDialog(
|
|
|
767
775
|
placeholders: inputs.placeholders.stringValue,
|
|
768
776
|
enumeratorType: inputs.enumeratorType.value,
|
|
769
777
|
placeholdersBreadth: inputs.placeholdersBreadth.stringValue,
|
|
770
|
-
|
|
778
|
+
trivialName: inputs.trivialName.value,
|
|
771
779
|
keepOriginal: inputs.keepOriginal.value,
|
|
772
780
|
toAtomicLevel: inputs.toAtomicLevel.value,
|
|
773
781
|
generateHelm: inputs.generateHelm.value,
|
|
@@ -781,7 +789,8 @@ async function getPolyToolEnumerateDialog(
|
|
|
781
789
|
inputs.enumeratorType.value = x.enumeratorType ?? PolyToolEnumeratorTypes.Single;
|
|
782
790
|
inputs.placeholders.stringValue = x.placeholders;
|
|
783
791
|
inputs.placeholdersBreadth.stringValue = x.placeholdersBreadth;
|
|
784
|
-
|
|
792
|
+
if (x.trivialName)
|
|
793
|
+
inputs.trivialName.value = x.trivialName;
|
|
785
794
|
inputs.keepOriginal.value = x.keepOriginal ?? false;
|
|
786
795
|
inputs.toAtomicLevel.value = x.toAtomicLevel ?? true;
|
|
787
796
|
inputs.generateHelm.value = x.generateHelm ?? true;
|