@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/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "Leonid Stolbov",
6
6
  "email": "lstolbov@datagrok.ai"
7
7
  },
8
- "version": "2.11.34",
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
- (await getEncodedSeqSpaceCol(this.moleculeColumn!, MmDistanceFunctionsNames.LEVENSHTEIN)).seqList;
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
- const libFnList = libFileManager.getValidLibraryPaths();
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
- expect(currentMonomerLib.getPolymerTypes().length === 0, true);
64
- const monomerOfTypesList = currentMonomerLib.getMonomerMolsByPolymerType('PEPTIDE');
65
- }, {skipReason: '#2690'});
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');
@@ -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((_value) => {
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
- const filteredLibFnList = libFileNameList
60
- .filter((libFileName) => !settings.exclude.includes(libFileName))
61
- .filter((libFileName) => settings.explicit.length > 0 ? settings.explicit.includes(libFileName) : true);
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 instance: MonomerLibFileManager | undefined;
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.instance === undefined) {
37
- const helmSchemaRaw = await grok.dapi.files.readAsText(HELM_JSON_SCHEMA_PATH);
38
- const helmSchema = JSON.parse(helmSchemaRaw) as JSONSchemaType<any>;
39
-
40
- const fileValidator = new MonomerLibFileValidator(helmSchema);
41
- MonomerLibFileManager.instance = new MonomerLibFileManager(fileValidator, libraryEventManager);
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.instance;
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('Manage monomer libraries');
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
+ }