@datagrok/bio 2.11.30 → 2.11.33
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 +13 -0
- package/dist/36.js +1 -1
- package/dist/36.js.map +1 -1
- package/dist/42.js +1 -1
- package/dist/42.js.map +1 -1
- package/dist/590.js +2 -0
- package/dist/590.js.map +1 -0
- package/dist/709.js +1 -2
- package/dist/709.js.map +1 -1
- package/dist/79.js.map +1 -1
- package/dist/895.js +3 -0
- package/dist/895.js.map +1 -0
- package/dist/package-test.js +8 -1
- package/dist/package-test.js.LICENSE.txt +1 -0
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +8 -1
- package/dist/package.js.LICENSE.txt +1 -0
- package/dist/package.js.map +1 -1
- package/files/{data → monomer-libraries}/HELMCoreLibrary.json +594 -594
- package/files/tests/libraries/HELMmonomerSchema.json +96 -0
- package/package.json +12 -10
- package/scripts/sequence_generator.md +48 -0
- package/scripts/sequence_generator.py +515 -256
- package/src/package-test.ts +4 -0
- package/src/package.ts +26 -24
- package/src/tests/WebLogo-layout-tests.ts +37 -0
- package/src/tests/WebLogo-positions-test.ts +5 -0
- package/src/tests/WebLogo-project-tests.ts +63 -0
- package/src/tests/activity-cliffs-tests.ts +3 -2
- package/src/tests/monomer-libraries-tests.ts +7 -4
- package/src/tests/scoring.ts +3 -2
- package/src/tests/substructure-filters-tests.ts +3 -2
- package/src/tests/to-atomic-level-tests.ts +3 -2
- package/src/utils/helm-to-molfile.ts +3 -3
- package/src/utils/monomer-lib/lib-manager.ts +116 -0
- package/src/utils/monomer-lib/library-file-manager/consts.ts +1 -0
- package/src/utils/monomer-lib/library-file-manager/custom-monomer-lib-handlers.ts +80 -0
- package/src/utils/monomer-lib/library-file-manager/event-manager.ts +58 -0
- package/src/utils/monomer-lib/library-file-manager/file-manager.ts +187 -0
- package/src/utils/monomer-lib/library-file-manager/file-validator.ts +56 -0
- package/src/utils/monomer-lib/library-file-manager/style.css +8 -0
- package/src/utils/monomer-lib/library-file-manager/ui.ts +224 -0
- package/src/utils/monomer-lib/monomer-lib.ts +114 -0
- package/src/utils/poly-tool/const.ts +28 -0
- package/src/utils/poly-tool/monomer-lib-handler.ts +115 -0
- package/src/utils/poly-tool/types.ts +6 -0
- package/src/utils/poly-tool/ui.ts +2 -2
- package/src/viewers/vd-regions-viewer.ts +5 -4
- package/src/viewers/web-logo-viewer.ts +6 -5
- package/src/widgets/bio-substructure-filter.ts +4 -1
- package/files/libraries/HELMCoreLibrary.json +0 -18218
- package/src/utils/monomer-lib.ts +0 -305
- /package/dist/{709.js.LICENSE.txt → 895.js.LICENSE.txt} +0 -0
package/src/utils/monomer-lib.ts
DELETED
|
@@ -1,305 +0,0 @@
|
|
|
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
|
-
import {Observable, Subject} from 'rxjs';
|
|
6
|
-
|
|
7
|
-
import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types/index';
|
|
8
|
-
import {
|
|
9
|
-
LibSettings, getUserLibSettings, setUserLibSettings, LIB_PATH
|
|
10
|
-
} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
|
|
11
|
-
import {MolfileHandler} from '@datagrok-libraries/chem-meta/src/parsing-utils/molfile-handler';
|
|
12
|
-
import {PolyToolMonomerLibHandler} from '@datagrok-libraries/bio/src/utils/poly-tool/monomer-lib-handler';
|
|
13
|
-
import {
|
|
14
|
-
createJsonMonomerLibFromSdf,
|
|
15
|
-
IMonomerLibHelper,
|
|
16
|
-
} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
17
|
-
import {
|
|
18
|
-
HELM_REQUIRED_FIELDS as REQ, HELM_OPTIONAL_FIELDS as OPT, HELM_POLYMER_TYPE
|
|
19
|
-
} from '@datagrok-libraries/bio/src/utils/const';
|
|
20
|
-
|
|
21
|
-
import {_package} from '../package';
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export async function getLibFileNameList(): Promise<string[]> {
|
|
25
|
-
// list files recursively because permissions are available for folders only
|
|
26
|
-
const res: string[] = await Promise.all((await grok.dapi.files.list(LIB_PATH, true, ''))
|
|
27
|
-
.map(async (it) => {
|
|
28
|
-
// Get relative path (to LIB_PATH)
|
|
29
|
-
return it.fullPath.substring(LIB_PATH.length);
|
|
30
|
-
}));
|
|
31
|
-
return res;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export async function manageFiles() {
|
|
35
|
-
const a = ui.dialog({title: 'Manage files'})
|
|
36
|
-
//@ts-ignore
|
|
37
|
-
.add(ui.fileBrowser({path: 'System:AppData/Bio/libraries'}).root)
|
|
38
|
-
.addButton('OK', () => a.close())
|
|
39
|
-
.show();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export async function getLibraryPanelUI(): Promise<DG.Widget> {
|
|
43
|
-
//@ts-ignore
|
|
44
|
-
const filesButton: HTMLButtonElement = ui.button('Manage', manageFiles);
|
|
45
|
-
const inputsForm: HTMLElement = ui.inputs([]);
|
|
46
|
-
const libFileNameList: string[] = await getLibFileNameList();
|
|
47
|
-
|
|
48
|
-
const settings = await getUserLibSettings();
|
|
49
|
-
|
|
50
|
-
for (const libFileName of libFileNameList) {
|
|
51
|
-
const libInput: DG.InputBase<boolean | null> = ui.boolInput(libFileName, !settings.exclude.includes(libFileName),
|
|
52
|
-
() => {
|
|
53
|
-
if (libInput.value == true) {
|
|
54
|
-
// Checked library remove from excluded list
|
|
55
|
-
settings.exclude = settings.exclude.filter((l) => l != libFileName);
|
|
56
|
-
} else {
|
|
57
|
-
// Unchecked library add to excluded list
|
|
58
|
-
if (!settings.exclude.includes(libFileName)) settings.exclude.push(libFileName);
|
|
59
|
-
}
|
|
60
|
-
setUserLibSettings(settings).then(async () => {
|
|
61
|
-
await MonomerLibHelper.instance.loadLibraries(true); // from libraryPanel()
|
|
62
|
-
grok.shell.info('Monomer library user settings saved.');
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
inputsForm.append(libInput.root);
|
|
66
|
-
}
|
|
67
|
-
return new DG.Widget(ui.divV([inputsForm, ui.div(filesButton)]));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export class MonomerLib implements IMonomerLib {
|
|
71
|
-
public readonly error: string | undefined;
|
|
72
|
-
|
|
73
|
-
private _monomers: { [polymerType: string]: { [monomerSymbol: string]: Monomer } } = {};
|
|
74
|
-
private _onChanged = new Subject<any>();
|
|
75
|
-
|
|
76
|
-
constructor(monomers: { [polymerType: string]: { [monomerSymbol: string]: Monomer } }, error?: string) {
|
|
77
|
-
this._monomers = monomers;
|
|
78
|
-
this.error = error;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
getMonomer(polymerType: string, monomerSymbol: string): Monomer | null {
|
|
82
|
-
if (polymerType in this._monomers! && monomerSymbol in this._monomers![polymerType])
|
|
83
|
-
return this._monomers![polymerType][monomerSymbol];
|
|
84
|
-
else
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
getPolymerTypes(): string[] {
|
|
89
|
-
return Object.keys(this._monomers);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
getMonomerMolsByPolymerType(polymerType: string): { [monomerSymbol: string]: string } {
|
|
93
|
-
const res: { [monomerSymbol: string]: string } = {};
|
|
94
|
-
|
|
95
|
-
Object.keys(this._monomers[polymerType] ?? {}).forEach((monomerSymbol) => {
|
|
96
|
-
res[monomerSymbol] = this._monomers[polymerType][monomerSymbol].molfile;
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
return res;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
getMonomerSymbolsByType(polymerType: string): string[] {
|
|
103
|
-
return Object.keys(this._monomers[polymerType]);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/** Get a list of monomers with specified element attached to specified
|
|
107
|
-
* R-group
|
|
108
|
-
* WARNING: RGroup numbering starts from 1, not 0*/
|
|
109
|
-
getMonomerSymbolsByRGroup(rGroupNumber: number, polymerType: string, element?: string): string[] {
|
|
110
|
-
const monomerSymbols = this.getMonomerSymbolsByType(polymerType);
|
|
111
|
-
let monomers = monomerSymbols.map((sym) => this.getMonomer(polymerType, sym));
|
|
112
|
-
monomers = monomers.filter((el) => el !== null);
|
|
113
|
-
if (monomers.length === 0)
|
|
114
|
-
return [];
|
|
115
|
-
|
|
116
|
-
function findAllIndices<T>(arr: T[], element: T): number[] {
|
|
117
|
-
return arr.map((value, index) => (value === element ? index : -1))
|
|
118
|
-
.filter((index) => index !== -1);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
monomers = monomers.filter((monomer) => {
|
|
122
|
-
if (!monomer?.rgroups)
|
|
123
|
-
return false;
|
|
124
|
-
let criterion = monomer?.rgroups.length >= rGroupNumber;
|
|
125
|
-
const molfileHandler = MolfileHandler.getInstance(monomer.molfile);
|
|
126
|
-
const rGroupIndices = findAllIndices(molfileHandler.atomTypes, 'R#');
|
|
127
|
-
criterion &&= true;
|
|
128
|
-
return criterion;
|
|
129
|
-
});
|
|
130
|
-
return monomers.map((monomer) => monomer?.symbol!);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
get onChanged(): Observable<any> {
|
|
134
|
-
return this._onChanged;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private _updateInt(lib: IMonomerLib): void {
|
|
138
|
-
const typesNew = lib.getPolymerTypes();
|
|
139
|
-
const types = this.getPolymerTypes();
|
|
140
|
-
|
|
141
|
-
typesNew.forEach((type) => {
|
|
142
|
-
//could possibly rewrite -> TODO: check duplicated monomer symbol
|
|
143
|
-
|
|
144
|
-
if (!types.includes(type))
|
|
145
|
-
this._monomers![type] = {};
|
|
146
|
-
|
|
147
|
-
const monomers = lib.getMonomerSymbolsByType(type);
|
|
148
|
-
monomers.forEach((monomerSymbol) => {
|
|
149
|
-
this._monomers[type][monomerSymbol] = lib.getMonomer(type, monomerSymbol)!;
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
public update(lib: IMonomerLib): void {
|
|
155
|
-
this._updateInt(lib);
|
|
156
|
-
this._onChanged.next();
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
public updateLibs(libList: IMonomerLib[], reload: boolean = false): void {
|
|
160
|
-
if (reload) this._monomers = {};
|
|
161
|
-
for (const lib of libList) if (!lib.error) this._updateInt(lib);
|
|
162
|
-
this._onChanged.next();
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
public clear(): void {
|
|
166
|
-
this._monomers = {};
|
|
167
|
-
this._onChanged.next();
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
type MonomerLibWindowType = Window & { $monomerLibHelper: MonomerLibHelper };
|
|
172
|
-
declare const window: MonomerLibWindowType;
|
|
173
|
-
|
|
174
|
-
export class MonomerLibHelper implements IMonomerLibHelper {
|
|
175
|
-
private readonly _monomerLib: MonomerLib = new MonomerLib({});
|
|
176
|
-
|
|
177
|
-
/** Protect constructor to prevent multiple instantiation. */
|
|
178
|
-
protected constructor() {}
|
|
179
|
-
|
|
180
|
-
/** Singleton monomer library
|
|
181
|
-
* @return {MonomerLibHelper} MonomerLibHelper instance
|
|
182
|
-
*/
|
|
183
|
-
getBioLib(): IMonomerLib {
|
|
184
|
-
return this._monomerLib;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/** Allows syncing with managing settings/loading libraries */
|
|
188
|
-
public loadLibrariesPromise: Promise<void> = Promise.resolve();
|
|
189
|
-
|
|
190
|
-
/** Loads libraries based on settings in user storage {@link LIB_STORAGE_NAME}
|
|
191
|
-
* @param {boolean} reload Clean {@link monomerLib} before load libraries [false]
|
|
192
|
-
*/
|
|
193
|
-
async loadLibraries(reload: boolean = false): Promise<void> {
|
|
194
|
-
return this.loadLibrariesPromise = this.loadLibrariesPromise.then(async () => {
|
|
195
|
-
// This function is not allowed to throw any exception,
|
|
196
|
-
// because it will prevent further handling monomer library settings
|
|
197
|
-
// through blocking this.loadLibrariesPromise
|
|
198
|
-
try {
|
|
199
|
-
const [libFileNameList, settings]: [string[], LibSettings] = await Promise.all([
|
|
200
|
-
getLibFileNameList(),
|
|
201
|
-
getUserLibSettings(),
|
|
202
|
-
]);
|
|
203
|
-
const filteredLibFnList = libFileNameList
|
|
204
|
-
.filter((libFileName) => !settings.exclude.includes(libFileName))
|
|
205
|
-
.filter((libFileName) => settings.explicit.length > 0 ? settings.explicit.includes(libFileName) : true);
|
|
206
|
-
const libs: IMonomerLib[] = await Promise.all(filteredLibFnList
|
|
207
|
-
.map((libFileName) => {
|
|
208
|
-
//TODO handle whether files are in place
|
|
209
|
-
return this.readLibrary(LIB_PATH, libFileName).catch((err: any) => {
|
|
210
|
-
const errMsg: string = `Loading monomers from '${libFileName}' error: ` +
|
|
211
|
-
`${err instanceof Error ? err.message : err.toString()}`;
|
|
212
|
-
return new MonomerLib({}, errMsg);
|
|
213
|
-
});
|
|
214
|
-
}));
|
|
215
|
-
this._monomerLib.updateLibs(libs, reload);
|
|
216
|
-
} catch (err: any) {
|
|
217
|
-
const errMsg: string = 'Loading monomer libraries error: ' +
|
|
218
|
-
`${err instanceof Error ? err.message : err.toString()}`;
|
|
219
|
-
grok.shell.warning(errMsg);
|
|
220
|
-
|
|
221
|
-
const errStack = err instanceof Error ? err.stack : undefined;
|
|
222
|
-
_package.logger.error(errMsg, undefined, errStack);
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/** Reads library from file shares, handles .json and .sdf
|
|
228
|
-
* @param {string} path Path to library file
|
|
229
|
-
* @param {string} fileName Name of library file
|
|
230
|
-
* @return {Promise<IMonomerLib>} Promise of IMonomerLib
|
|
231
|
-
*/
|
|
232
|
-
async readLibrary(path: string, fileName: string): Promise<IMonomerLib> {
|
|
233
|
-
let rawLibData: any[] = [];
|
|
234
|
-
let file;
|
|
235
|
-
let dfSdf;
|
|
236
|
-
const fileSource = new DG.FileSource(path);
|
|
237
|
-
if (fileName.endsWith('.sdf')) {
|
|
238
|
-
const funcList: DG.Func[] = DG.Func.find({package: 'Chem', name: 'importSdf'});
|
|
239
|
-
if (funcList.length === 1) {
|
|
240
|
-
file = await fileSource.readAsBytes(fileName);
|
|
241
|
-
dfSdf = await grok.functions.call('Chem:importSdf', {bytes: file});
|
|
242
|
-
rawLibData = createJsonMonomerLibFromSdf(dfSdf[0]);
|
|
243
|
-
} else {
|
|
244
|
-
grok.shell.warning('Chem package is not installed');
|
|
245
|
-
}
|
|
246
|
-
} else if (fileName.endsWith('.json')) {
|
|
247
|
-
const file = await fileSource.readAsText(fileName);
|
|
248
|
-
rawLibData = JSON.parse(file);
|
|
249
|
-
} else if (fileName.endsWith('.csv')) {
|
|
250
|
-
// todo: replace by DataFrame's method after update of js-api
|
|
251
|
-
function toJson(df: DG.DataFrame): any[] {
|
|
252
|
-
return Array.from({length: df.rowCount}, (_, idx) =>
|
|
253
|
-
df.columns.names().reduce((entry: { [key: string]: any }, colName) => {
|
|
254
|
-
entry[colName] = df.get(colName, idx);
|
|
255
|
-
return entry;
|
|
256
|
-
}, {})
|
|
257
|
-
);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const df = await fileSource.readCsv(fileName);
|
|
261
|
-
const json = toJson(df);
|
|
262
|
-
const polyToolMonomerLib = new PolyToolMonomerLibHandler(json);
|
|
263
|
-
if (polyToolMonomerLib.isValid())
|
|
264
|
-
rawLibData = polyToolMonomerLib.getJsonMonomerLib();
|
|
265
|
-
else
|
|
266
|
-
throw new Error('Invalid format of CSV monomer lib');
|
|
267
|
-
} else {
|
|
268
|
-
throw new Error('Monomer library of unknown file format, supported formats: SDF, JSON, CSV');
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const monomers: { [polymerType: string]: { [monomerSymbol: string]: Monomer } } = {};
|
|
272
|
-
const polymerTypes: string[] = [];
|
|
273
|
-
rawLibData.forEach((monomer) => {
|
|
274
|
-
if (!polymerTypes.includes(monomer[REQ.POLYMER_TYPE])) {
|
|
275
|
-
monomers[monomer[REQ.POLYMER_TYPE]] = {};
|
|
276
|
-
polymerTypes.push(monomer[REQ.POLYMER_TYPE]);
|
|
277
|
-
}
|
|
278
|
-
monomers[monomer[REQ.POLYMER_TYPE]][monomer[REQ.SYMBOL]] = monomer as Monomer;
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
return new MonomerLib(monomers);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/** Reset user settings to the specified library. WARNING: clears user * settings */
|
|
285
|
-
public async selectSpecifiedLibraries(libFileNameList: string[]): Promise<void> {
|
|
286
|
-
const invalidNames = await this.getInvalidFileNames(libFileNameList);
|
|
287
|
-
if (invalidNames.length > 0)
|
|
288
|
-
throw new Error(`Cannot select libraries ${invalidNames}: no such library in the list`);
|
|
289
|
-
const settings = await getUserLibSettings();
|
|
290
|
-
settings.exclude = (await getLibFileNameList()).filter((fileName) => !libFileNameList.includes(fileName));
|
|
291
|
-
await setUserLibSettings(settings);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
private async getInvalidFileNames(libFileNameList: string[]): Promise<string[]> {
|
|
295
|
-
const availableFileNames = await getLibFileNameList();
|
|
296
|
-
const invalidNames = libFileNameList.filter((fileName) => !availableFileNames.includes(fileName));
|
|
297
|
-
return invalidNames;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// -- Instance singleton --
|
|
301
|
-
public static get instance(): MonomerLibHelper {
|
|
302
|
-
if (!window.$monomerLibHelper) window.$monomerLibHelper = new MonomerLibHelper();
|
|
303
|
-
return window.$monomerLibHelper;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
File without changes
|