@datagrok/bio 2.11.34 → 2.11.36
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 +12 -0
- package/dist/package-test.js +3 -3
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +6 -6
- package/dist/package.js.map +1 -1
- package/package.json +1 -1
- package/src/analysis/sequence-diversity-viewer.ts +2 -2
- package/src/analysis/sequence-similarity-viewer.ts +1 -1
- package/src/package.ts +12 -0
- package/src/tests/monomer-libraries-tests.ts +8 -4
- package/src/tests/similarity-diversity-tests.ts +2 -2
- package/src/utils/convert.ts +1 -1
- package/src/utils/monomer-lib/lib-manager.ts +8 -3
- package/src/utils/monomer-lib/library-file-manager/custom-monomer-lib-handlers.ts +0 -39
- package/src/utils/monomer-lib/library-file-manager/event-manager.ts +13 -1
- package/src/utils/monomer-lib/library-file-manager/file-manager.ts +18 -9
- package/src/utils/monomer-lib/library-file-manager/file-validator.ts +1 -1
- package/src/utils/monomer-lib/library-file-manager/ui.ts +6 -1
- package/src/utils/poly-tool/csv-to-json-monomer-lib-converter.ts +40 -0
- package/src/utils/poly-tool/transformation.ts +201 -121
- package/src/utils/poly-tool/ui.ts +21 -84
- package/src/utils/poly-tool/utils.ts +7 -7
- package/src/widgets/bio-substructure-filter-helm.ts +2 -2
- package/webpack.config.js +3 -0
- package/src/utils/poly-tool/types.ts +0 -20
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "Leonid Stolbov",
|
|
6
6
|
"email": "lstolbov@datagrok.ai"
|
|
7
7
|
},
|
|
8
|
-
"version": "2.11.
|
|
8
|
+
"version": "2.11.36",
|
|
9
9
|
"description": "Bioinformatics support (import/export of sequences, conversion, visualization, analysis). [See more](https://github.com/datagrok-ai/public/blob/master/packages/Bio/README.md) for details.",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
@@ -40,7 +40,7 @@ export class SequenceDiversityViewer extends SequenceSearchBaseViewer {
|
|
|
40
40
|
this.tags.forEach((tag) => resCol.setTag(tag, this.moleculeColumn!.getTag(tag)));
|
|
41
41
|
const resDf = DG.DataFrame.fromColumns([resCol]);
|
|
42
42
|
resDf.onCurrentRowChanged.subscribe(
|
|
43
|
-
(_) => { this.dataFrame.currentRowIdx = this.renderMolIds![resDf.currentRowIdx]; });
|
|
43
|
+
(_: any) => { this.dataFrame.currentRowIdx = this.renderMolIds![resDf.currentRowIdx]; });
|
|
44
44
|
updateDivInnerHTML(this.root, resDf.plot.grid().root);
|
|
45
45
|
this.computeCompleted.next(true);
|
|
46
46
|
}
|
|
@@ -61,7 +61,7 @@ export class SequenceDiversityViewer extends SequenceSearchBaseViewer {
|
|
|
61
61
|
|
|
62
62
|
private async computeByMM() {
|
|
63
63
|
const encodedSequences =
|
|
64
|
-
|
|
64
|
+
(await getEncodedSeqSpaceCol(this.moleculeColumn!, MmDistanceFunctionsNames.LEVENSHTEIN)).seqList;
|
|
65
65
|
const distanceMatrixService = new DistanceMatrixService(true, false);
|
|
66
66
|
const distanceMatrixData = await distanceMatrixService.calc(encodedSequences, MmDistanceFunctionsNames.LEVENSHTEIN);
|
|
67
67
|
distanceMatrixService.terminate();
|
|
@@ -60,7 +60,7 @@ export class SequenceSimilarityViewer extends SequenceSearchBaseViewer {
|
|
|
60
60
|
this.molCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
61
61
|
this.tags.forEach((tag) => this.molCol!.setTag(tag, this.moleculeColumn!.getTag(tag)));
|
|
62
62
|
const resDf = DG.DataFrame.fromColumns([this.idxs!, this.molCol!, this.scores!]);
|
|
63
|
-
resDf.onCurrentRowChanged.subscribe((_) => {
|
|
63
|
+
resDf.onCurrentRowChanged.subscribe((_: any) => {
|
|
64
64
|
this.dataFrame.currentRowIdx = resDf.col('indexes')!.get(resDf.currentRowIdx);
|
|
65
65
|
setTimeout(() => { this.createPropertyPanel(resDf); }, 1000);
|
|
66
66
|
this.gridSelect = true;
|
package/src/package.ts
CHANGED
|
@@ -60,6 +60,7 @@ import {getCompositionAnalysisWidget} from './widgets/composition-analysis-widge
|
|
|
60
60
|
import {MacromoleculeColumnWidget} from './utils/macromolecule-column-widget';
|
|
61
61
|
import {addCopyMenuUI} from './utils/context-menu';
|
|
62
62
|
import {getPolyToolDialog} from './utils/poly-tool/ui';
|
|
63
|
+
import {PolyToolCsvLibHandler} from './utils/poly-tool/csv-to-json-monomer-lib-converter';
|
|
63
64
|
import {_setPeptideColumn} from './utils/poly-tool/utils';
|
|
64
65
|
import {getRegionDo} from './utils/get-region';
|
|
65
66
|
import {GetRegionApp} from './apps/get-region-app';
|
|
@@ -1018,6 +1019,17 @@ export async function polyToolColumnChoice(df: DG.DataFrame, macroMolecule: DG.C
|
|
|
1018
1019
|
await grok.data.detectSemanticTypes(df);
|
|
1019
1020
|
}
|
|
1020
1021
|
|
|
1022
|
+
//name: createMonomerLibraryForPolyTool
|
|
1023
|
+
//input: file file
|
|
1024
|
+
export async function createMonomerLibraryForPolyTool(file: DG.FileInfo) {
|
|
1025
|
+
const fileContent = await file.readAsString();
|
|
1026
|
+
const libHandler = new PolyToolCsvLibHandler(file.fileName, fileContent);
|
|
1027
|
+
const libObject = await libHandler.getJson();
|
|
1028
|
+
const jsonFileName = file.fileName.replace(/\.csv$/, '.json');
|
|
1029
|
+
const jsonFileContent = JSON.stringify(libObject, null, 2);
|
|
1030
|
+
DG.Utils.download(jsonFileName, jsonFileContent);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1021
1033
|
//name: SDF to JSON Library
|
|
1022
1034
|
//input: dataframe table
|
|
1023
1035
|
export async function sdfToJsonLib(table: DG.DataFrame) {
|
|
@@ -53,14 +53,18 @@ category('monomerLibraries', () => {
|
|
|
53
53
|
const libSettings = await getUserLibSettings();
|
|
54
54
|
const libFileEventManager = MonomerLibFileEventManager.getInstance();
|
|
55
55
|
const libFileManager = await MonomerLibFileManager.getInstance(libFileEventManager);
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
let libFnList = libFileManager.getValidLibraryPaths();
|
|
58
|
+
if (libFnList.length === 0)
|
|
59
|
+
libFnList = await libFileManager.getValidLibraryPathsAsynchronously();
|
|
60
|
+
|
|
57
61
|
libSettings.exclude = libFnList;
|
|
58
62
|
libSettings.explicit = [];
|
|
59
63
|
await setUserLibSettings(libSettings);
|
|
60
64
|
|
|
61
65
|
await monomerLibHelper.loadLibraries(true);
|
|
62
66
|
const currentMonomerLib = monomerLibHelper.getBioLib();
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
67
|
+
const polymerTypes = currentMonomerLib.getPolymerTypes();
|
|
68
|
+
expect(polymerTypes.length === 0, true);
|
|
69
|
+
});
|
|
66
70
|
});
|
|
@@ -28,7 +28,7 @@ async function _testSimilaritySearchViewer() {
|
|
|
28
28
|
const viewer: SequenceSimilarityViewer = (await moleculesView.dataFrame.plot
|
|
29
29
|
.fromType('Sequence Similarity Search')) as SequenceSimilarityViewer;
|
|
30
30
|
let computeCompleted: boolean = false;
|
|
31
|
-
viewer.computeCompleted.subscribe((value) => {
|
|
31
|
+
viewer.computeCompleted.subscribe((value: any) => {
|
|
32
32
|
if (value) computeCompleted = true;
|
|
33
33
|
});
|
|
34
34
|
moleculesView.dockManager.dock(viewer, DG.DOCK_TYPE.RIGHT, null, 'Similarity');
|
|
@@ -78,7 +78,7 @@ async function _testDiversitySearchViewer() {
|
|
|
78
78
|
const viewer: SequenceDiversityViewer = (await moleculesView.dataFrame.plot
|
|
79
79
|
.fromType('Sequence Diversity Search')) as SequenceDiversityViewer;
|
|
80
80
|
let computeCompleted: boolean = false;
|
|
81
|
-
viewer.computeCompleted.subscribe((value) => {
|
|
81
|
+
viewer.computeCompleted.subscribe((value: boolean) => {
|
|
82
82
|
if (value) computeCompleted = true;
|
|
83
83
|
});
|
|
84
84
|
moleculesView.dockManager.dock(viewer, DG.DOCK_TYPE.DOWN, null, 'Diversity');
|
package/src/utils/convert.ts
CHANGED
|
@@ -102,7 +102,7 @@ export function convert(col?: DG.Column): void {
|
|
|
102
102
|
})
|
|
103
103
|
.show({x: 350, y: 100});
|
|
104
104
|
|
|
105
|
-
convertDialogSubs.push(convertDialog.onClose.subscribe((
|
|
105
|
+
convertDialogSubs.push(convertDialog.onClose.subscribe((_: any) => {
|
|
106
106
|
convertDialogSubs.forEach((s) => { s.unsubscribe(); });
|
|
107
107
|
convertDialogSubs = [];
|
|
108
108
|
convertDialog = null;
|
|
@@ -56,9 +56,14 @@ export class MonomerLibManager implements IMonomerLibHelper {
|
|
|
56
56
|
getLibFileNameList(),
|
|
57
57
|
getUserLibSettings(),
|
|
58
58
|
]);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
|
|
60
|
+
const filteredLibFnList = libFileNameList.filter((libFileName) => {
|
|
61
|
+
const isFileIncluded = !settings.exclude.includes(libFileName);
|
|
62
|
+
const isExplicit = settings.explicit.length === 0 || settings.explicit.includes(libFileName);
|
|
63
|
+
|
|
64
|
+
return isFileIncluded && isExplicit;
|
|
65
|
+
});
|
|
66
|
+
|
|
62
67
|
const libs: IMonomerLib[] = await Promise.all(filteredLibFnList
|
|
63
68
|
.map((libFileName) => {
|
|
64
69
|
//TODO handle whether files are in place
|
|
@@ -4,7 +4,6 @@ import * as ui from 'datagrok-api/ui';
|
|
|
4
4
|
import * as DG from 'datagrok-api/dg';
|
|
5
5
|
|
|
6
6
|
import {createJsonMonomerLibFromSdf} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
7
|
-
import {PolyToolMonomerLibHandler} from '../../poly-tool/monomer-lib-handler';
|
|
8
7
|
|
|
9
8
|
interface CustomMonomerLibHandler {
|
|
10
9
|
getHelmLibContent(): Promise<string>;
|
|
@@ -40,41 +39,3 @@ export class SdfMonomerLibHandler implements CustomMonomerLibHandler {
|
|
|
40
39
|
throw new Error(`File ${this.fileName} is not an SDF file`);
|
|
41
40
|
}
|
|
42
41
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
/** Handler of custom monomer libs for PolyTool */
|
|
46
|
-
export class PolyToolCsvLibHandler implements CustomMonomerLibHandler {
|
|
47
|
-
constructor(private fileName: string, private fileContent: string) {
|
|
48
|
-
this.validateFileType();
|
|
49
|
-
const df = DG.DataFrame.fromCsv(this.fileContent);
|
|
50
|
-
const json = this.toJson(df);
|
|
51
|
-
this.polyToolMonomerLib = new PolyToolMonomerLibHandler(json);
|
|
52
|
-
this.validateContent();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private polyToolMonomerLib: PolyToolMonomerLibHandler;
|
|
56
|
-
|
|
57
|
-
async getHelmLibContent(): Promise<string> {
|
|
58
|
-
const rawLibData = this.polyToolMonomerLib.getJsonMonomerLib();
|
|
59
|
-
return JSON.stringify(rawLibData);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
private toJson(df: DG.DataFrame): any[] {
|
|
63
|
-
return Array.from({length: df.rowCount}, (_, idx) =>
|
|
64
|
-
df.columns.names().reduce((entry: { [key: string]: any }, colName) => {
|
|
65
|
-
entry[colName] = df.get(colName, idx);
|
|
66
|
-
return entry;
|
|
67
|
-
}, {})
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
private validateFileType(): void {
|
|
72
|
-
if (!this.fileName.endsWith('.csv'))
|
|
73
|
-
throw new Error(`File ${this.fileName} is not an CSV file`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
private validateContent(): void {
|
|
77
|
-
if (!this.polyToolMonomerLib.isValid())
|
|
78
|
-
throw new Error('Invalid format of CSV monomer lib');
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as rxjs from 'rxjs';
|
|
2
|
-
import {debounceTime, tap} from 'rxjs/operators';
|
|
2
|
+
import {debounceTime, tap, skip} from 'rxjs/operators';
|
|
3
3
|
|
|
4
4
|
export class MonomerLibFileEventManager {
|
|
5
5
|
// WARNING: this must be a singleton because it manages the unique state
|
|
@@ -22,6 +22,18 @@ export class MonomerLibFileEventManager {
|
|
|
22
22
|
return this._libraryFilesUpdateSubject$.getValue();
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
// TODO: remove after adding init from user data storage
|
|
26
|
+
// WARNING: a temporary solution
|
|
27
|
+
async getValidLibraryPathsAsynchronously(): Promise<string[]> {
|
|
28
|
+
return new Promise((resolve) => {
|
|
29
|
+
this._libraryFilesUpdateSubject$.pipe(
|
|
30
|
+
skip(1)
|
|
31
|
+
).subscribe((fileNames) => {
|
|
32
|
+
resolve(fileNames);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
25
37
|
changeValidFilesPathList(newList: string[]): void {
|
|
26
38
|
this._libraryFilesUpdateSubject$.next(newList);
|
|
27
39
|
}
|
|
@@ -28,20 +28,22 @@ export class MonomerLibFileManager {
|
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
private static
|
|
31
|
+
private static instancePromise: Promise<MonomerLibFileManager> | undefined;
|
|
32
32
|
|
|
33
33
|
static async getInstance(
|
|
34
34
|
libraryEventManager: MonomerLibFileEventManager,
|
|
35
35
|
): Promise<MonomerLibFileManager> {
|
|
36
|
-
if (MonomerLibFileManager.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
if (!MonomerLibFileManager.instancePromise) {
|
|
37
|
+
MonomerLibFileManager.instancePromise = (async () => {
|
|
38
|
+
const helmSchemaRaw = await grok.dapi.files.readAsText(HELM_JSON_SCHEMA_PATH);
|
|
39
|
+
const helmSchema = JSON.parse(helmSchemaRaw) as JSONSchemaType<any>;
|
|
40
|
+
|
|
41
|
+
const fileValidator = new MonomerLibFileValidator(helmSchema);
|
|
42
|
+
return new MonomerLibFileManager(fileValidator, libraryEventManager);
|
|
43
|
+
})();
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
return MonomerLibFileManager.
|
|
46
|
+
return MonomerLibFileManager.instancePromise;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
/** Add standard .json monomer library */
|
|
@@ -103,6 +105,13 @@ export class MonomerLibFileManager {
|
|
|
103
105
|
return this.libraryEventManager.getValidFilesPathList();
|
|
104
106
|
}
|
|
105
107
|
|
|
108
|
+
// TODO: remove after adding init from user data storage
|
|
109
|
+
// WARNING: a temporary solution
|
|
110
|
+
async getValidLibraryPathsAsynchronously(): Promise<string[]> {
|
|
111
|
+
return await this.libraryEventManager.getValidLibraryPathsAsynchronously();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
106
115
|
private async libraryFileExists(fileName: string): Promise<boolean> {
|
|
107
116
|
return await grok.dapi.files.exists(LIB_PATH + `${fileName}`);
|
|
108
117
|
}
|
|
@@ -142,7 +151,7 @@ export class MonomerLibFileManager {
|
|
|
142
151
|
`, consider fixing or removing them: ${invalidFiles.join(', ')}`;
|
|
143
152
|
|
|
144
153
|
console.warn(message);
|
|
145
|
-
grok.shell.warning(message);
|
|
154
|
+
// grok.shell.warning(message);
|
|
146
155
|
}
|
|
147
156
|
}
|
|
148
157
|
|
|
@@ -41,7 +41,7 @@ export class MonomerLibFileValidator {
|
|
|
41
41
|
isValid = this.validateMonomerSchema(monomer);
|
|
42
42
|
if (!isValid) {
|
|
43
43
|
console.warn(
|
|
44
|
-
`Bio: Monomer Library File Validator:\nfile${fileName}\n monomer violating JSON schema:`,
|
|
44
|
+
`Bio: Monomer Library File Validator:\nfile ${fileName}\n monomer violating JSON schema:`,
|
|
45
45
|
monomer,
|
|
46
46
|
'\nError reason: ',
|
|
47
47
|
this.validateMonomerSchema.errors,
|
|
@@ -208,7 +208,12 @@ class DialogWrapper {
|
|
|
208
208
|
private async getDialog(): Promise<DG.Dialog> {
|
|
209
209
|
const eventManager = MonomerLibFileEventManager.getInstance();
|
|
210
210
|
const widget = await MonomerLibraryManagerWidget.getContent(eventManager);
|
|
211
|
-
const dialog = ui.dialog(
|
|
211
|
+
const dialog = ui.dialog(
|
|
212
|
+
{
|
|
213
|
+
title: 'Manage monomer libraries',
|
|
214
|
+
helpUrl: '/help/datagrok/solutions/domains/bio/bio.md#manage-monomer-libraries'
|
|
215
|
+
}
|
|
216
|
+
);
|
|
212
217
|
$(dialog.root).css('width', '350px');
|
|
213
218
|
dialog.clear();
|
|
214
219
|
dialog.addButton(
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as DG from 'datagrok-api/dg';
|
|
2
|
+
|
|
3
|
+
import {PolyToolMonomerLibHandler} from './monomer-lib-handler';
|
|
4
|
+
|
|
5
|
+
/** Handler of custom monomer libs for PolyTool */
|
|
6
|
+
export class PolyToolCsvLibHandler {
|
|
7
|
+
constructor(private fileName: string, private fileContent: string) {
|
|
8
|
+
this.validateFileType();
|
|
9
|
+
const df = DG.DataFrame.fromCsv(this.fileContent);
|
|
10
|
+
const json = this.toJson(df);
|
|
11
|
+
this.polyToolMonomerLib = new PolyToolMonomerLibHandler(json);
|
|
12
|
+
this.validateContent();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private polyToolMonomerLib: PolyToolMonomerLibHandler;
|
|
16
|
+
|
|
17
|
+
async getJson(): Promise<any> {
|
|
18
|
+
const rawLibData = this.polyToolMonomerLib.getJsonMonomerLib();
|
|
19
|
+
return rawLibData;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private toJson(df: DG.DataFrame): any[] {
|
|
23
|
+
return Array.from({length: df.rowCount}, (_, idx) =>
|
|
24
|
+
df.columns.names().reduce((entry: { [key: string]: any }, colName) => {
|
|
25
|
+
entry[colName] = df.get(colName, idx);
|
|
26
|
+
return entry;
|
|
27
|
+
}, {})
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private validateFileType(): void {
|
|
32
|
+
if (!this.fileName.endsWith('.csv'))
|
|
33
|
+
throw new Error(`File ${this.fileName} is not an CSV file`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private validateContent(): void {
|
|
37
|
+
if (!this.polyToolMonomerLib.isValid())
|
|
38
|
+
throw new Error('Invalid format of CSV monomer lib');
|
|
39
|
+
}
|
|
40
|
+
}
|