@datagrok/sequence-translator 1.9.0 → 1.9.1
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 +4 -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/package-test.ts +1 -1
- package/src/package.ts +7 -0
- package/src/polytool/pt-combine-dialog.ts +131 -0
- package/test-console-output-1.log +1663 -0
- 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.9.
|
|
4
|
+
"version": "1.9.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Leonid Stolbov",
|
|
7
7
|
"email": "lstolbov@datagrok.ai"
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
"@datagrok-libraries/bio": "^5.50.0",
|
|
26
26
|
"@datagrok-libraries/chem-meta": "^1.2.8",
|
|
27
27
|
"@datagrok-libraries/tutorials": "^1.4.3",
|
|
28
|
-
"@datagrok-libraries/utils": "^4.
|
|
28
|
+
"@datagrok-libraries/utils": "^4.3.7",
|
|
29
29
|
"@types/react": "^18.0.15",
|
|
30
30
|
"cash-dom": "^8.1.0",
|
|
31
|
-
"datagrok-api": "^1.
|
|
31
|
+
"datagrok-api": "^1.23.0",
|
|
32
32
|
"lodash": "^4.17.21",
|
|
33
33
|
"object-hash": "^3.0.0",
|
|
34
34
|
"openchemlib": "6.0.1",
|
package/src/package-test.ts
CHANGED
|
@@ -34,5 +34,5 @@ export async function test(category: string, test: string, testContext: TestCont
|
|
|
34
34
|
|
|
35
35
|
//name: initAutoTests
|
|
36
36
|
export async function initAutoTests() {
|
|
37
|
-
await initTests(_package, _package.getModule('package-test.js'));
|
|
37
|
+
await initTests(_package as any, _package.getModule('package-test.js'));
|
|
38
38
|
}
|
package/src/package.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {CyclizedNotationProvider} from './utils/cyclized';
|
|
|
27
27
|
import {getSeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
28
28
|
import {PolyToolTags} from './consts';
|
|
29
29
|
import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
30
|
+
import { getPTCombineDialog } from './polytool/pt-combine-dialog';
|
|
30
31
|
|
|
31
32
|
export const _package: OligoToolkitPackage = new OligoToolkitPackage({debug: true}/**/);
|
|
32
33
|
|
|
@@ -302,6 +303,12 @@ export async function getPtChemEnumeratorDialog(cell?: DG.Cell) {
|
|
|
302
303
|
return polyToolEnumerateChemUI(cell);
|
|
303
304
|
}
|
|
304
305
|
|
|
306
|
+
//name: Combine Sequences
|
|
307
|
+
//top-menu: Bio | PolyTool | Combine Sequences...
|
|
308
|
+
export async function getPolyToolCombineDialog() {
|
|
309
|
+
getPTCombineDialog();
|
|
310
|
+
}
|
|
311
|
+
|
|
305
312
|
|
|
306
313
|
//name: applyNotationProviderForHarmonizedSequence
|
|
307
314
|
//input: column col
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as ui from 'datagrok-api/ui';
|
|
3
|
+
import * as DG from 'datagrok-api/dg';
|
|
4
|
+
|
|
5
|
+
export async function getPTCombineDialog() {
|
|
6
|
+
|
|
7
|
+
const createEditor = () => {
|
|
8
|
+
const editorDiv = ui.divH([]);
|
|
9
|
+
const tableEditor = ui.input.table('Table', {value: undefined, tooltipText: 'Table with sequences'});
|
|
10
|
+
const columnEditor = ui.input.choice('Column', {items: [] as string[], value: undefined, tooltipText: 'Sequence column'});
|
|
11
|
+
|
|
12
|
+
tableEditor.onChanged.subscribe(async () => {
|
|
13
|
+
const table = tableEditor.value;
|
|
14
|
+
if (!table) {
|
|
15
|
+
columnEditor.items = [];
|
|
16
|
+
columnEditor.value = null;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
await table.meta.detectSemanticTypes();
|
|
20
|
+
await grok.data.detectSemanticTypes(table);
|
|
21
|
+
const stringColumns = Array.from(table.columns.categorical);
|
|
22
|
+
const stringColumnsNames = stringColumns.map((c) => c.name);
|
|
23
|
+
columnEditor.items = stringColumnsNames;
|
|
24
|
+
columnEditor.value = stringColumns.find((c) => c.semType === DG.SEMTYPE.MACROMOLECULE)?.name ?? stringColumnsNames.find((c) => {
|
|
25
|
+
const lc = c.toLowerCase();
|
|
26
|
+
return lc.includes('seq') || lc.includes('pep');
|
|
27
|
+
}) ?? stringColumnsNames[0];
|
|
28
|
+
});
|
|
29
|
+
editorDiv.appendChild(tableEditor.root);
|
|
30
|
+
editorDiv.appendChild(columnEditor.root);
|
|
31
|
+
editorDiv.style.alignItems = 'center';
|
|
32
|
+
return {root: editorDiv, getValue: () => ({table: tableEditor.value, column: columnEditor.value})};
|
|
33
|
+
}
|
|
34
|
+
type Editor = ReturnType<typeof createEditor>;
|
|
35
|
+
|
|
36
|
+
const editors: Editor[] = [];
|
|
37
|
+
const editorsDiv = ui.divV([]);
|
|
38
|
+
|
|
39
|
+
const insertNewEditor = (index: number) => {
|
|
40
|
+
const editorDiv = createEditor();
|
|
41
|
+
const removeButton = ui.icons.delete(() => {
|
|
42
|
+
if (!editorDiv.root.parentElement || editors.length < 2)
|
|
43
|
+
return;
|
|
44
|
+
editorDiv.root.remove();
|
|
45
|
+
const editorIndex = editors.indexOf(editorDiv);
|
|
46
|
+
if (editorIndex !== -1) {
|
|
47
|
+
editors.splice(editorIndex, 1);
|
|
48
|
+
}
|
|
49
|
+
}, 'Remove');
|
|
50
|
+
const addEditor = ui.icons.add(() => {
|
|
51
|
+
let editorIndex = editors.indexOf(editorDiv);
|
|
52
|
+
if (editorIndex === -1) {
|
|
53
|
+
editorIndex = editors.length;
|
|
54
|
+
}
|
|
55
|
+
insertNewEditor(editorIndex + 1);
|
|
56
|
+
}, 'Add');
|
|
57
|
+
editorDiv.root.appendChild(removeButton);
|
|
58
|
+
editorDiv.root.appendChild(addEditor);
|
|
59
|
+
removeButton.style.marginLeft = '8px';
|
|
60
|
+
removeButton.style.marginRight = '8px';
|
|
61
|
+
removeButton.style.color = 'var(--blue-1)';
|
|
62
|
+
addEditor.style.color = 'var(--blue-1)';
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
const prevEditor = editors[index];
|
|
66
|
+
if (prevEditor) {
|
|
67
|
+
editorsDiv.insertBefore(editorDiv.root, prevEditor.root);
|
|
68
|
+
} else {
|
|
69
|
+
editorsDiv.appendChild(editorDiv.root);
|
|
70
|
+
}
|
|
71
|
+
editors.splice(index, 0, editorDiv);
|
|
72
|
+
}
|
|
73
|
+
insertNewEditor(0);
|
|
74
|
+
|
|
75
|
+
function validate() {
|
|
76
|
+
const values = editors.map((e) => e.getValue());
|
|
77
|
+
const tables = values.map((v) => v.table);
|
|
78
|
+
const columns = values.map((v) => v.column);
|
|
79
|
+
return tables.every((t) => !!t) && columns.every((c) => !!c);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const separatorInput = ui.input.string('Separator', {value: '-', tooltipText: 'Separator for sequences', nullable: false});
|
|
83
|
+
|
|
84
|
+
ui.dialog('Combine Sequences')
|
|
85
|
+
.add(editorsDiv)
|
|
86
|
+
.add(separatorInput.root)
|
|
87
|
+
.onOK(async () => {
|
|
88
|
+
if (!validate()) {
|
|
89
|
+
grok.shell.error('Please fill all the fields');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const values = editors.map((e) => e.getValue());
|
|
93
|
+
const tables = values.map((v) => v.table);
|
|
94
|
+
const columns = values.map((v) => v.column);
|
|
95
|
+
const separator = separatorInput.value;
|
|
96
|
+
const cols = columns.map((c, i) => tables[i]!.col(c!)!.toList().filter((v) => !!v));
|
|
97
|
+
// do a DFS to generate all combinations
|
|
98
|
+
let curIndex = 0;
|
|
99
|
+
const totalLength = cols.reduce((acc, c) => acc * c.length, 1);
|
|
100
|
+
if (totalLength > 10_000_000) {
|
|
101
|
+
grok.shell.error('Too many combinations. Maximum allowed is 10M');
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const result: string[] = new Array(totalLength).fill(null);
|
|
105
|
+
|
|
106
|
+
const dfs = (cur: string, depth: number) => {
|
|
107
|
+
if (depth === cols.length) {
|
|
108
|
+
result[curIndex++] = cur;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const actCur = `${cur}${cur ? separator : ''}`;
|
|
112
|
+
const col = cols[depth];
|
|
113
|
+
for (let i = 0; i < cols[depth].length; i++) {
|
|
114
|
+
dfs(actCur + col[i], depth + 1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
dfs('', 0);
|
|
118
|
+
const df = DG.DataFrame.fromColumns([DG.Column.fromStrings('Combined', result)]);
|
|
119
|
+
df.name = 'Combined Sequences';
|
|
120
|
+
await df.meta.detectSemanticTypes();
|
|
121
|
+
await grok.data.detectSemanticTypes(df);
|
|
122
|
+
grok.shell.addTableView(df);
|
|
123
|
+
})
|
|
124
|
+
.show({resizable: true});
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
}
|