@datagrok/bio 2.23.2 → 2.25.0

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.
Files changed (63) hide show
  1. package/.eslintrc.json +0 -2
  2. package/CHANGELOG.md +9 -0
  3. package/README.md +1 -1
  4. package/dist/455.js.map +1 -1
  5. package/dist/package-test.js +3 -3
  6. package/dist/package-test.js.map +1 -1
  7. package/dist/package.js +2 -2
  8. package/dist/package.js.map +1 -1
  9. package/files/samples/HELM_CHEMS.csv +11 -0
  10. package/package.json +2 -2
  11. package/src/analysis/sequence-space.ts +1 -1
  12. package/src/demo/bio03-atomic-level.ts +1 -1
  13. package/src/package-types.ts +2 -2
  14. package/src/package.ts +10 -4
  15. package/src/tests/activity-cliffs-tests.ts +2 -2
  16. package/src/tests/monomer-libraries-tests.ts +9 -7
  17. package/src/tests/renderers-monomer-placer-tests.ts +1 -1
  18. package/src/tests/scoring.ts +1 -1
  19. package/src/tests/seq-handler-get-helm-tests.ts +1 -1
  20. package/src/tests/splitters-test.ts +2 -2
  21. package/src/tests/substructure-filters-tests.ts +11 -11
  22. package/src/tests/to-atomic-level-tests.ts +2 -2
  23. package/src/tests/to-atomic-level-ui-tests.ts +13 -14
  24. package/src/utils/cell-renderer.ts +1 -1
  25. package/src/utils/get-region.ts +2 -2
  26. package/src/utils/helm-to-molfile/converter/const.ts +0 -1
  27. package/src/utils/helm-to-molfile/converter/converter.ts +4 -4
  28. package/src/utils/helm-to-molfile/converter/helm.ts +14 -6
  29. package/src/utils/helm-to-molfile/converter/mol-bonds.ts +2 -2
  30. package/src/utils/helm-to-molfile/converter/mol-wrapper.ts +2 -2
  31. package/src/utils/helm-to-molfile/converter/monomer-wrapper.ts +1 -1
  32. package/src/utils/helm-to-molfile/converter/polymer.ts +1 -1
  33. package/src/utils/helm-to-molfile/converter/r-group-handler.ts +2 -2
  34. package/src/utils/helm-to-molfile/utils.ts +3 -2
  35. package/src/utils/monomer-cell-renderer-base.ts +1 -2
  36. package/src/utils/monomer-lib/consts.ts +1 -6
  37. package/src/utils/monomer-lib/lib-manager.ts +239 -112
  38. package/src/utils/monomer-lib/library-file-manager/file-validator.ts +1 -1
  39. package/src/utils/monomer-lib/library-file-manager/monomers-lib-provider.ts +378 -0
  40. package/src/utils/monomer-lib/library-file-manager/ui.ts +120 -81
  41. package/src/utils/monomer-lib/monomer-colors.ts +37 -39
  42. package/src/utils/monomer-lib/monomer-lib-base.ts +34 -7
  43. package/src/utils/monomer-lib/monomer-lib.ts +7 -33
  44. package/src/utils/monomer-lib/monomer-manager/duplicate-monomer-manager.ts +3 -3
  45. package/src/utils/monomer-lib/monomer-manager/monomer-manager.ts +91 -82
  46. package/src/utils/monomer-lib/smiles2Monomer.ts +128 -0
  47. package/src/utils/monomer-lib/web-editor-monomer-dummy.ts +15 -1
  48. package/src/utils/monomer-lib/web-editor-monomer-of-library.ts +2 -1
  49. package/src/utils/multiple-sequence-alignment-ui.ts +1 -1
  50. package/src/utils/multiple-sequence-alignment.ts +1 -1
  51. package/src/utils/seq-helper/seq-handler.ts +26 -13
  52. package/src/utils/seq-helper/seq-helper.ts +1 -2
  53. package/src/utils/sequence-to-mol.ts +1 -1
  54. package/src/utils/ui-utils.ts +1 -1
  55. package/src/viewers/web-logo-viewer.ts +20 -9
  56. package/src/widgets/composition-analysis-widget.ts +1 -1
  57. package/src/widgets/sequence-scrolling-widget.ts +1 -2
  58. package/test-console-output-1.log +670 -721
  59. package/test-record-1.mp4 +0 -0
  60. package/src/utils/monomer-lib/library-file-manager/custom-monomer-lib-handlers.ts +0 -41
  61. package/src/utils/monomer-lib/library-file-manager/event-manager.ts +0 -93
  62. package/src/utils/monomer-lib/library-file-manager/file-manager.ts +0 -317
  63. package/src/utils/monomer-lib/monomer-set.ts +0 -61
package/test-record-1.mp4 CHANGED
Binary file
@@ -1,41 +0,0 @@
1
- /* Do not change these import lines to match external modules in webpack configuration */
2
- import * as grok from 'datagrok-api/grok';
3
- import * as ui from 'datagrok-api/ui';
4
- import * as DG from 'datagrok-api/dg';
5
-
6
- import {createJsonMonomerLibFromSdf} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
7
-
8
- interface CustomMonomerLibHandler {
9
- getHelmLibContent(): Promise<string>;
10
- }
11
-
12
- /** Casts specific SDF files as HELM-standard monomer libraries */
13
- export class SdfMonomerLibHandler implements CustomMonomerLibHandler {
14
- constructor(private fileName: string, private fileContent: string) {
15
- this.validateChemInstallation();
16
- this.validate();
17
- }
18
-
19
- async getHelmLibContent(): Promise<string> {
20
- const bytes = this.transformToBytes();
21
- const dfSdf = await grok.functions.call('Chem:importSdf', {bytes});
22
- const jsonContent = createJsonMonomerLibFromSdf(dfSdf[0]);
23
- return JSON.stringify(jsonContent);
24
- }
25
-
26
- private transformToBytes(): Uint8Array {
27
- return new TextEncoder().encode(this.fileContent);
28
- }
29
-
30
- private validateChemInstallation(): void {
31
- const funcList: DG.Func[] = DG.Func.find({package: 'Chem', name: 'importSdf'});
32
- if (funcList.length === 1)
33
- return;
34
- throw new Error('MonomerLibFileManager: Chem package is not installed, cannot convert SDF to JSON');
35
- }
36
-
37
- private validate(): void {
38
- if (!this.fileName.endsWith('.sdf'))
39
- throw new Error(`File ${this.fileName} is not an SDF file`);
40
- }
41
- }
@@ -1,93 +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 {BehaviorSubject, Observable, Subject} from 'rxjs';
6
- import {debounceTime, tap, skip} from 'rxjs/operators';
7
-
8
- import {IMonomerLibFileEventManager} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
9
-
10
- export class MonomerLibFileEventManager implements IMonomerLibFileEventManager {
11
- // WARNING: this must be a singleton because it manages the unique state
12
- private constructor() {}
13
-
14
- private static _instance: MonomerLibFileEventManager;
15
-
16
- static getInstance(): MonomerLibFileEventManager {
17
- if (!MonomerLibFileEventManager._instance)
18
- MonomerLibFileEventManager._instance = new MonomerLibFileEventManager();
19
-
20
- return MonomerLibFileEventManager._instance;
21
- }
22
-
23
- private _libFilesUpdateSubject$ = new BehaviorSubject<string[]>([]);
24
- private _setFilesUpdateSubject$ = new BehaviorSubject<string[]>([]);
25
-
26
- private _addLibraryFilesSubject$ = new Subject<void>();
27
- private _librarySelectionSubject$ = new Subject<[string, boolean]>();
28
-
29
- getValidLibPathList(): string[] {
30
- return this._libFilesUpdateSubject$.getValue();
31
- }
32
-
33
- getValidSetPathList(): string[] {
34
- return this._setFilesUpdateSubject$.getValue();
35
- }
36
-
37
- // TODO: remove after adding init from user data storage
38
- // WARNING: a temporary solution
39
- async getValidLibraryPathsAsynchronously(): Promise<string[]> {
40
- return new Promise((resolve) => {
41
- const sub = this._libFilesUpdateSubject$.pipe<string[]>(
42
- skip(1)
43
- ).subscribe((fileNames) => {
44
- resolve(fileNames);
45
- sub.unsubscribe();
46
- });
47
- });
48
- }
49
-
50
- changeValidLibPathList(newLibPathList: string[]): void {
51
- this._libFilesUpdateSubject$.next(newLibPathList);
52
- }
53
-
54
- changeValidSetPathList(newSetPathList: string[]): void {
55
- this._setFilesUpdateSubject$.next(newSetPathList);
56
- }
57
-
58
- get updateUIControlsRequested$(): Observable<string[]> {
59
- return this._libFilesUpdateSubject$.pipe(
60
- // debounceTime(1000)
61
- );
62
- }
63
-
64
- get updateValidLibraryFileListRequested$(): Observable<string[]> {
65
- return this._libFilesUpdateSubject$.pipe(
66
- // debounceTime(3000)
67
- );
68
- }
69
-
70
- get updateValidSetFileListRequested$(): Observable<string[]> {
71
- return this._setFilesUpdateSubject$.pipe(
72
- // debounceTime(1000)
73
- );
74
- }
75
-
76
- get addLibraryFileRequested$(): Observable<void> {
77
- return this._addLibraryFilesSubject$.pipe(
78
- // debounceTime(1000)
79
- );
80
- }
81
-
82
- addLibraryFile(): void {
83
- this._addLibraryFilesSubject$.next();
84
- }
85
-
86
- get librarySelectionRequested$(): Observable<[string, boolean]> {
87
- return this._librarySelectionSubject$;
88
- }
89
-
90
- updateLibrarySelectionStatus(fileName: string, isSelected: boolean): void {
91
- this._librarySelectionSubject$.next([fileName, isSelected]);
92
- }
93
- }
@@ -1,317 +0,0 @@
1
- /* Do not change these import lines to match external modules in webpack configuration */
2
- import * as grok from 'datagrok-api/grok';
3
- import * as ui from 'datagrok-api/ui';
4
- import * as DG from 'datagrok-api/dg';
5
-
6
- import {JSONSchemaType} from 'ajv';
7
-
8
- import {MonomerType, PolymerType} from '@datagrok-libraries/bio/src/helm/types';
9
- import {IMonomerLib, IMonomerLinkData, IMonomerSet, Monomer} from '@datagrok-libraries/bio/src/types';
10
- import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
11
- import {
12
- HELM_REQUIRED_FIELD as REQ,
13
- } from '@datagrok-libraries/bio/src/utils/const';
14
- import {
15
- IMonomerLibHelper, IMonomerLibFileManager
16
- } from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
17
-
18
- import {MonomerLib} from '../monomer-lib';
19
- import {MonomerLibFileEventManager} from './event-manager';
20
- import {MonomerLibFileValidator} from './file-validator';
21
- import {MonomerSet, MonomerSetPlaceholder} from '../monomer-set';
22
- import {HELM_JSON_SCHEMA_PATH, LIB_PATH, SETS_PATH} from '../consts';
23
-
24
- import {_package} from '../../../package';
25
-
26
-
27
- /** Singleton for adding, validation and reading of monomer library files.
28
- * All files **must** be aligned to the HELM standard before adding. */
29
- export class MonomerLibFileManager implements IMonomerLibFileManager {
30
- public filesPromise: Promise<void> = Promise.resolve();
31
- public initializedPromise: Promise<void> = Promise.resolve();
32
-
33
- private constructor(
34
- private readonly fileValidator: MonomerLibFileValidator,
35
- private readonly libHelper: IMonomerLibHelper,
36
- public readonly eventManager: MonomerLibFileEventManager,
37
- private readonly logger: ILogger,
38
- ) {
39
- // these both are behavioral subjects, i.e. they emit their value when subscribed.
40
- // initial creation/request from bio package on awaiting files promise makes no sense,
41
- // until the subscription fires first time
42
- let resolveFilesPromise: () => void;
43
- let initialized = false;
44
- this.initializedPromise =
45
- Promise.race([DG.delay(1000), new Promise<void>((resolve) => resolveFilesPromise = resolve)]);
46
- const _libSub = this.eventManager.updateValidLibraryFileListRequested$.subscribe(() => {
47
- this.updateValidLibList().then(() => {});
48
- if (!initialized) {
49
- initialized = true;
50
- resolveFilesPromise();
51
- }
52
- });
53
- const _setSub = this.eventManager.updateValidSetFileListRequested$.subscribe(() => {
54
- this.updateValidSetList().then(() => {});
55
- });
56
- }
57
-
58
- private static objCounter: number = -1;
59
- private readonly objId: number = ++MonomerLibFileManager.objCounter;
60
-
61
- protected toLog(): string {
62
- return `MonomerLibFileManager<${this.objId}>`;
63
- }
64
-
65
- /** For internal use only, get {@link IMonomerLibHelper.getFileManager} */
66
- public static async create(
67
- libHelper: IMonomerLibHelper, eventManager: MonomerLibFileEventManager, logger: ILogger,
68
- ): Promise<MonomerLibFileManager> {
69
- const helmSchemaRaw = await grok.dapi.files.readAsText(HELM_JSON_SCHEMA_PATH);
70
- const helmSchema = JSON.parse(helmSchemaRaw) as JSONSchemaType<any>;
71
-
72
- const fileValidator = new MonomerLibFileValidator(helmSchema);
73
- return new MonomerLibFileManager(fileValidator, libHelper, eventManager, logger);
74
- }
75
-
76
- /** Add standard .json monomer library */
77
- async addLibraryFile(fileContent: string, fileName: string, reload = true): Promise<void> {
78
- try {
79
- const alreadyFileExists = await grok.dapi.files.exists(LIB_PATH + `${fileName}`);
80
- if (alreadyFileExists) {
81
- grok.shell.error(`File ${fileName} already exists`);
82
- return;
83
- }
84
-
85
- await this.validateAgainstHELM(fileContent, fileName);
86
- await grok.dapi.files.writeAsText(LIB_PATH + `${fileName}`, fileContent);
87
- await this.updateValidLibList();
88
- const fileExists = await grok.dapi.files.exists(LIB_PATH + `${fileName}`);
89
- if (!fileExists)
90
- grok.shell.error(`Failed to add ${fileName} library`);
91
- else
92
- grok.shell.info(`Added ${fileName} HELM library`);
93
- } catch (e) {
94
- console.error(e);
95
- grok.shell.error(`Failed to add ${fileName} library`);
96
- }
97
- }
98
-
99
- async deleteLibraryFile(fileName: string): Promise<void> {
100
- try {
101
- await grok.dapi.files.delete(LIB_PATH + `${fileName}`);
102
- await this.updateValidLibList();
103
- grok.shell.info(`Deleted ${fileName} library`);
104
- } catch (e) {
105
- console.error(e);
106
- const fileExists = await grok.dapi.files.exists(LIB_PATH + `${fileName}`);
107
- if (fileExists)
108
- grok.shell.error(`Failed to delete ${fileName} library`);
109
- else
110
- grok.shell.warning(`File ${fileName} already deleted, refresh the list`);
111
- }
112
- }
113
-
114
- async loadLibraryFromFile(path: string, fileName: string): Promise<IMonomerLib> {
115
- let rawLibData: any[] = [];
116
- const fileSource = new DG.FileSource(path);
117
- const file = await fileSource.readAsText(fileName);
118
- rawLibData = JSON.parse(file);
119
- const monomers: { [polymerType: string]: { [monomerSymbol: string]: Monomer } } = {};
120
- const polymerTypes: string[] = [];
121
- rawLibData.forEach((monomer) => {
122
- const polymerType = monomer[REQ.POLYMER_TYPE];
123
- const monomerSymbol = monomer[REQ.SYMBOL];
124
- if (!polymerTypes.includes(polymerType)) {
125
- monomers[polymerType] = {};
126
- polymerTypes.push(polymerType);
127
- }
128
- monomers[polymerType][monomerSymbol] = monomer as Monomer;
129
- });
130
-
131
- return new MonomerLib(monomers, fileName);
132
- }
133
-
134
- async loadSetFromFile(monomerLib: IMonomerLib, path: string, fileName: string): Promise<IMonomerSet> {
135
- let raw: any = {};
136
- const fileSource = new DG.FileSource(path);
137
- const content = await fileSource.readAsText(fileName);
138
- raw = JSON.parse(content);
139
-
140
- const description = raw['description'];
141
- const placeholders = Object.entries(raw['placeholders']).map(([k, v]: [string, any]) => {
142
- const placeholderSymbol = k;
143
- const polymerType = v['polymerType'] as PolymerType;
144
- const monomerType = v['monomerType'] as MonomerType;
145
- const monomerLinks = v['set'] as IMonomerLinkData[];
146
-
147
- return new MonomerSetPlaceholder(monomerLib, placeholderSymbol, polymerType, monomerType, monomerLinks);
148
- });
149
-
150
- return new MonomerSet(description, placeholders);
151
- }
152
-
153
- getValidLibraryPaths(): string[] {
154
- return this.eventManager.getValidLibPathList();
155
- }
156
-
157
- getValidSetPaths(): string[] {
158
- return this.eventManager.getValidSetPathList();
159
- }
160
-
161
- // TODO: remove after adding init from user data storage
162
- // WARNING: a temporary solution
163
- async getValidLibraryPathsAsynchronously(): Promise<string[]> {
164
- return await this.eventManager.getValidLibraryPathsAsynchronously();
165
- }
166
-
167
- private async updateValidLibList(): Promise<void> {
168
- const logPrefix: string = `${this.toLog()}.updateValidLibList()`;
169
- this.logger.debug(`${logPrefix}, start`);
170
- this.filesPromise = this.filesPromise.then(async () => {
171
- this.logger.debug(`${logPrefix}, IN`);
172
- const invalidFiles = [] as string[];
173
- // console.log(`files before validation:`, this.libraryEventManager.getValidFilesPathList());
174
- const libPathList = await this.getLibFileListAtLocation();
175
-
176
- if (!this.libListHasChanged(libPathList)) {
177
- this.logger.debug(`${logPrefix}, end, not changed`);
178
- return;
179
- }
180
-
181
- for (const path of libPathList) {
182
- if (!path.endsWith('.json')) {
183
- invalidFiles.push(path);
184
- continue;
185
- }
186
-
187
- const fileContent = await grok.dapi.files.readAsText(LIB_PATH + `${path}`);
188
- if (!this.isValidHELMLibrary(fileContent, path))
189
- invalidFiles.push(path);
190
- }
191
-
192
- const validLibPathList = libPathList.filter((path) => !invalidFiles.includes(path));
193
-
194
- if (this.libListHasChanged(validLibPathList)) {
195
- this.eventManager.changeValidLibPathList(validLibPathList);
196
- await this.libHelper.loadMonomerLib(true);
197
- }
198
- // console.log(`files after validation:`, this.libraryEventManager.getValidFilesPathList());
199
-
200
- if (validLibPathList.some((el) => !el.endsWith('.json')))
201
- this.logger.warning(`Wrong validation: ${validLibPathList}`);
202
-
203
- if (invalidFiles.length > 0) {
204
- const message = `Invalid monomer library files in ${LIB_PATH}` +
205
- `, consider fixing or removing them: ${invalidFiles.join(', ')}`;
206
-
207
- this.logger.warning(message);
208
- // grok.shell.warning(message);
209
- }
210
- this.logger.debug(`${logPrefix}, OUT`);
211
- });
212
- this.logger.debug(`${logPrefix}, end`);
213
- return this.filesPromise;
214
- }
215
-
216
- private async updateValidSetList(): Promise<void> {
217
- const logPrefix: string = `${this.toLog()}.updateValidSetList()`;
218
- _package.logger.debug(`${logPrefix}, start`);
219
- this.filesPromise = this.filesPromise.then(async () => {
220
- _package.logger.debug(`${logPrefix}, IN`);
221
- const invalidFiles = [] as string[];
222
- const setPathList: string[] = await this.getSetFileListAtLocation();
223
-
224
- if (!this.setListHasChanged(setPathList)) {
225
- _package.logger.debug(`${logPrefix}, end, not changed`);
226
- return;
227
- }
228
-
229
- for (const path of setPathList) {
230
- if (!path.endsWith('.json')) {
231
- invalidFiles.push(path);
232
- continue;
233
- }
234
-
235
- const fileContent = await grok.dapi.files.readAsText(SETS_PATH + `${path}`);
236
- // TODO: Validate monomer set
237
- // if (!this.isValidMonomerSet(fileContent, path))
238
- // invalidFiles.push(path);
239
- }
240
-
241
- const validSetPathList = setPathList.filter((path) => !invalidFiles.includes(path));
242
- if (this.setListHasChanged(validSetPathList)) {
243
- this.eventManager.changeValidSetPathList(validSetPathList);
244
- this.libHelper.loadMonomerSets(true);
245
- }
246
-
247
- _package.logger.debug(`${logPrefix}, OUT`);
248
- });
249
- _package.logger.debug(`${logPrefix}, end`);
250
- return this.filesPromise;
251
- }
252
-
253
- private libListHasChanged(newList: string[]): boolean {
254
- const currentList = this.eventManager.getValidLibPathList();
255
- return newList.length !== currentList.length || newList.some((el, i) => el !== currentList[i]);
256
- }
257
-
258
- private setListHasChanged(newList: string[]): boolean {
259
- const currentList = this.eventManager.getValidSetPathList();
260
- return newList.length !== currentList.length || newList.some((el, i) => el !== currentList[i]);
261
- }
262
-
263
- private async validateAgainstHELM(fileContent: string, fileName: string): Promise<void> {
264
- const isValid = this.isValidHELMLibrary(fileContent, fileName);
265
- if (!isValid)
266
- throw new Error(`File ${fileName} does not satisfy HELM standard`);
267
- }
268
-
269
- private isValidHELMLibrary(fileContent: string, fileName: string): boolean {
270
- return this.fileValidator.validateFile(fileContent, fileName);
271
- }
272
-
273
- /** Get relative paths for files in LIB_PATH, SET_PATH */
274
- private async getLibFileListAtLocation(): Promise<string[]> {
275
- const logPrefix = `${this.toLog()}.getLibFileListAtLocation()`;
276
- this.logger.debug(`${logPrefix}, start`);
277
-
278
- const libPaths = await grok.dapi.files.list(LIB_PATH)
279
- .then((l) => l.filter((f) => f.isFile).map((fi) => fi.fullPath));
280
-
281
- const checkForUi = false;
282
- const existingLibPaths: string[] = [];
283
- if (checkForUi) {
284
- // WARNING: an extra sanity check,
285
- // caused by unexpected behavior of grok.dapi.files.list() when it returns non-existent paths
286
- for (const path of libPaths) {
287
- const exists = await grok.dapi.files.exists(path);
288
- if (exists)
289
- existingLibPaths.push(path);
290
- }
291
- } else
292
- existingLibPaths.push(...libPaths);
293
-
294
- return existingLibPaths.map((p) => /* relative to LIB_PATH */ p.substring(LIB_PATH.length));
295
- }
296
-
297
- private async getSetFileListAtLocation(): Promise<string[]> {
298
- const logPrefix = `${this.toLog()}.getSetFileListAtLocation()`;
299
- this.logger.debug(`${logPrefix}, start`);
300
-
301
- const setPaths = await grok.dapi.files.list(SETS_PATH)
302
- .then((l) => l.map((fi) => fi.fullPath));
303
-
304
- const checkForUi = false;
305
- const existingSetPaths: string[] = [];
306
- if (checkForUi) {
307
- for (const path of setPaths) {
308
- const exists = await grok.dapi.files.exists(path);
309
- if (exists)
310
- existingSetPaths.push(path);
311
- }
312
- } else
313
- existingSetPaths.push(...setPaths);
314
-
315
- return existingSetPaths.map((p) => /* relative to SET_PATH */ p.substring(SETS_PATH.length));
316
- }
317
- }
@@ -1,61 +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 type {MonomerType, PolymerType} from '@datagrok-libraries/bio/src/helm/types';
6
- import {
7
- IMonomerLib, IMonomerLinkData, IMonomerSet, IMonomerSetPlaceholder, Monomer
8
- } from '@datagrok-libraries/bio/src/types';
9
- import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
10
-
11
- export class MonomerSetPlaceholder implements IMonomerSetPlaceholder {
12
- public readonly monomers: Monomer[];
13
-
14
- public readonly error: string | null = null;
15
-
16
- constructor(
17
- private readonly monomerLib: IMonomerLib,
18
- public symbol: string,
19
- public readonly polymerType: PolymerType,
20
- public readonly monomerType: MonomerType,
21
- public readonly monomerLinks: IMonomerLinkData[],
22
- ) {
23
- try {
24
- this.monomers = this.monomerLinks.map((mLink) => {
25
- const resM = this.monomerLib.getMonomer(this.polymerType, mLink.symbol);
26
- if (!resM)
27
- throw new Error('Monomer not found: ');
28
- if (resM.lib?.source != mLink.source)
29
- throw new Error(`Monomer '${symbol}' found in different library.`);
30
- return resM;
31
- });
32
- } catch (err: any) {
33
- const [errMsg, errStack] = errInfo(err);
34
- this.error = errMsg;
35
- this.monomers = [];
36
- }
37
- }
38
- }
39
-
40
- export class MonomerSet implements IMonomerSet {
41
- public constructor(
42
- public readonly description: string,
43
- public placeholders: IMonomerSetPlaceholder[],
44
- public readonly source: string | undefined = undefined,
45
- public readonly error: string | undefined = undefined,
46
- ) {}
47
-
48
- updateSets(setList: IMonomerSet[], reload: boolean = false): void {
49
- if (reload)
50
- this.placeholders = [];
51
- for (const _set of setList)
52
- if (!_set.error) this._updateSetInt(_set);
53
-
54
- // TODO: File onChanged
55
- }
56
-
57
- private _updateSetInt(set: IMonomerSet): void {
58
- for (const setPh of set.placeholders)
59
- this.placeholders.push(setPh);
60
- }
61
- }