@datagrok/bio 2.15.3 → 2.15.6

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 (69) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/detectors.js +9 -2
  3. package/dist/284.js +1 -1
  4. package/dist/284.js.map +1 -1
  5. package/dist/455.js +2 -0
  6. package/dist/455.js.map +1 -0
  7. package/dist/980.js +1 -1
  8. package/dist/980.js.map +1 -1
  9. package/dist/package-test.js +3 -3
  10. package/dist/package-test.js.map +1 -1
  11. package/dist/package.js +2 -2
  12. package/dist/package.js.map +1 -1
  13. package/files/monomer-libraries/polytool-lib.json +52 -0
  14. package/files/tests/to-atomic-level-msa-fasta-output.csv +683 -683
  15. package/files/tests/to-atomic-level-msa-separator-output.csv +104 -104
  16. package/package.json +9 -9
  17. package/src/analysis/sequence-activity-cliffs.ts +3 -1
  18. package/src/calculations/monomerLevelMols.ts +2 -1
  19. package/src/demo/bio03-atomic-level.ts +1 -1
  20. package/src/package-test.ts +2 -1
  21. package/src/package.ts +151 -38
  22. package/src/tests/WebLogo-positions-test.ts +1 -1
  23. package/src/tests/activity-cliffs-tests.ts +2 -3
  24. package/src/tests/bio-tests.ts +1 -1
  25. package/src/tests/detectors-custom-notation-tests.ts +37 -0
  26. package/src/tests/detectors-tests.ts +20 -69
  27. package/src/tests/detectors-weak-and-likely-tests.ts +2 -2
  28. package/src/tests/monomer-libraries-tests.ts +31 -6
  29. package/src/tests/pepsea-tests.ts +1 -1
  30. package/src/tests/renderers-monomer-placer-tests.ts +2 -4
  31. package/src/tests/scoring.ts +2 -3
  32. package/src/tests/seq-handler-get-helm-tests.ts +2 -4
  33. package/src/tests/seq-handler-splitted-tests.ts +6 -2
  34. package/src/tests/splitters-test.ts +6 -6
  35. package/src/tests/substructure-filters-tests.ts +2 -3
  36. package/src/tests/to-atomic-level-tests.ts +22 -17
  37. package/src/tests/to-atomic-level-ui-tests.ts +76 -38
  38. package/src/tests/types.ts +0 -2
  39. package/src/tests/utils/detectors-utils.ts +63 -0
  40. package/src/tests/utils.ts +2 -2
  41. package/src/utils/cell-renderer-custom.ts +62 -0
  42. package/src/utils/cell-renderer.ts +58 -126
  43. package/src/utils/cyclized.ts +28 -14
  44. package/src/utils/dimerized.ts +0 -2
  45. package/src/utils/helm-to-molfile/converter/converter.ts +75 -54
  46. package/src/utils/helm-to-molfile/converter/monomer-wrapper.ts +2 -2
  47. package/src/utils/helm-to-molfile/converter/polymer.ts +23 -16
  48. package/src/utils/helm-to-molfile/converter/types.ts +0 -10
  49. package/src/utils/helm-to-molfile/utils.ts +10 -7
  50. package/src/utils/monomer-lib/consts.ts +18 -0
  51. package/src/utils/monomer-lib/lib-manager.ts +13 -3
  52. package/src/utils/monomer-lib/library-file-manager/file-manager.ts +1 -2
  53. package/src/utils/monomer-lib/monomer-colors.ts +68 -0
  54. package/src/utils/monomer-lib/monomer-lib-base.ts +165 -0
  55. package/src/utils/monomer-lib/monomer-lib.ts +44 -72
  56. package/src/utils/monomer-lib/monomer-manager/monomer-manager.ts +1 -1
  57. package/src/utils/monomer-lib/web-editor-monomer-dummy.ts +121 -0
  58. package/src/utils/monomer-lib/web-editor-monomer-of-library.ts +102 -0
  59. package/src/utils/pepsea.ts +1 -1
  60. package/src/utils/save-as-fasta.ts +1 -1
  61. package/src/utils/seq-helper/seq-helper.ts +20 -49
  62. package/src/utils/sequence-to-mol.ts +24 -28
  63. package/src/viewers/web-logo-viewer.ts +2 -1
  64. package/src/widgets/composition-analysis-widget.ts +4 -3
  65. package/src/widgets/representations.ts +8 -10
  66. package/dist/248.js +0 -2
  67. package/dist/248.js.map +0 -1
  68. package/src/utils/cell-renderer-consts.ts +0 -31
  69. package/src/utils/monomer-lib/library-file-manager/consts.ts +0 -1
@@ -11,13 +11,3 @@ export type PositionInBonds = {
11
11
  nodeIdx: number,
12
12
  }
13
13
 
14
- export type MonomerMap = { position: number, symbol: string, atoms: number[], bonds: number[] };
15
-
16
- export class MolfileWithMap {
17
- constructor(
18
- public readonly molfile: string,
19
- public readonly monomers: MonomerMap[]
20
- ) {}
21
-
22
- static empty() { return new MolfileWithMap('', []); }
23
- }
@@ -2,27 +2,30 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
- import {_package} from '../../package';
5
+ import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types';
6
+
6
7
  import {SeqHelper} from '../seq-helper';
7
8
 
9
+ import {_package, getMonomerLib} from '../../package';
8
10
 
9
11
  /** Translate HELM column into molfile column and append to the dataframe */
10
12
  export async function getMolColumnFromHelm(
11
- df: DG.DataFrame, helmCol: DG.Column<string>, chiralityEngine: boolean = true
13
+ df: DG.DataFrame, helmCol: DG.Column<string>, chiralityEngine: boolean = true, monomerLib: IMonomerLibBase
12
14
  ): Promise<DG.Column<string>> {
13
15
  const seqHelper = await SeqHelper.getInstance();
14
- const converter = seqHelper.getHelmToMolfileConverter(df, helmCol);
15
- const molCol = converter.convertToRdKitBeautifiedMolfileColumn(chiralityEngine, _package.rdKitModule);
16
+ const converter = seqHelper.getHelmToMolfileConverter(monomerLib);
17
+ const molCol = converter.convertToRdKitBeautifiedMolfileColumn(helmCol, chiralityEngine, _package.rdKitModule, monomerLib);
16
18
  molCol.semType = DG.SEMTYPE.MOLECULE;
17
19
  return molCol;
18
20
  }
19
21
 
20
22
  export async function getSmilesColumnFromHelm(
21
- df: DG.DataFrame, helmCol: DG.Column<string>
23
+ helmCol: DG.Column<string>
22
24
  ): Promise<DG.Column<string>> {
23
25
  const seqHelper = await SeqHelper.getInstance();
24
- const converter = seqHelper.getHelmToMolfileConverter(df, helmCol);
25
- const smilesCol = converter.convertToSmiles(_package.rdKitModule);
26
+ const monomerLib = getMonomerLib();
27
+ const converter = seqHelper.getHelmToMolfileConverter(monomerLib);
28
+ const smilesCol = converter.convertToSmiles(helmCol);
26
29
  smilesCol.semType = DG.SEMTYPE.MOLECULE;
27
30
  return smilesCol;
28
31
  }
@@ -0,0 +1,18 @@
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 {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
6
+ import {MonomerLibSummaryType} from '@datagrok-libraries/bio/src/types/index';
7
+
8
+ export const LIB_PATH = 'System:AppData/Bio/monomer-libraries/';
9
+ export const SETS_PATH: string = 'System:AppData/Bio/monomer-sets/';
10
+
11
+ export const HELM_JSON_SCHEMA_PATH = 'System:AppData/Bio/tests/libraries/HELMmonomerSchema.json';
12
+
13
+ export const LIB_SETTINGS_FOR_TESTS: UserLibSettings =
14
+ {explicit: ['HELMCoreLibrary.json', 'polytool-lib.json'], exclude: [], duplicateMonomerPreferences: {}};
15
+
16
+ /** Summary for settings {@link LIB_SETTINGS_FOR_TESTS} */
17
+ export const monomerLibForTestsSummary: MonomerLibSummaryType = {'PEPTIDE': 326, 'RNA': 383, 'CHEM': 0};
18
+
@@ -7,7 +7,7 @@ import {delay} from '@datagrok-libraries/utils/src/test';
7
7
  import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
8
8
  import {IMonomerLib, IMonomerSet} from '@datagrok-libraries/bio/src/types';
9
9
  import {
10
- getUserLibSettings, setUserLibSettings, LIB_PATH, SETS_PATH
10
+ getUserLibSettings, setUserLibSettings,
11
11
  } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
12
12
  import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
13
13
  import {
@@ -18,6 +18,7 @@ import {MonomerLib} from './monomer-lib';
18
18
  import {MonomerSet} from './monomer-set';
19
19
  import {MonomerLibFileManager} from './library-file-manager/file-manager';
20
20
  import {MonomerLibFileEventManager} from './library-file-manager/event-manager';
21
+ import {LIB_PATH, LIB_SETTINGS_FOR_TESTS, SETS_PATH} from './consts';
21
22
 
22
23
  import {_package} from '../../package';
23
24
 
@@ -34,7 +35,7 @@ export class MonomerLibManager implements IMonomerLibHelper {
34
35
 
35
36
  public get eventManager(): IMonomerLibFileEventManager { return this._eventManager; }
36
37
 
37
- public async awaitLoaded(timeout: number = 3000): Promise<void> {
38
+ public async awaitLoaded(timeout: number = 5000): Promise<void> {
38
39
  return await Promise.race([
39
40
  (async () => {
40
41
  const fileManager = await this.getFileManager();
@@ -47,7 +48,7 @@ export class MonomerLibManager implements IMonomerLibHelper {
47
48
  })(),
48
49
  ]).then((res) => {
49
50
  if (!res)
50
- throw new Error(`Loading monomer libraries is timeout ${timeout} ms.`);
51
+ throw new Error(`Loading monomer libraries timeout ${timeout} ms.`);
51
52
  });
52
53
  }
53
54
 
@@ -267,6 +268,15 @@ export class MonomerLibManager implements IMonomerLibHelper {
267
268
  return invalidNames;
268
269
  }
269
270
 
271
+ // -- Settings --
272
+
273
+ /** Changes userLibSettings set only HELMCoreLibrary.json, polytool-lib.json */
274
+ async loadMonomerLibForTests(): Promise<void> {
275
+ await setUserLibSettings(LIB_SETTINGS_FOR_TESTS);
276
+ await this.awaitLoaded();
277
+ await this.loadMonomerLib(true); // load default libraries
278
+ }
279
+
270
280
  // -- Instance singleton --
271
281
  public static async getInstance(): Promise<MonomerLibManager> {
272
282
  let res = window.$monomerLibHelperPromise;
@@ -8,7 +8,6 @@ import {JSONSchemaType} from 'ajv';
8
8
  import {MonomerType, PolymerType} from '@datagrok-libraries/bio/src/helm/types';
9
9
  import {IMonomerLib, IMonomerLinkData, IMonomerSet, Monomer} from '@datagrok-libraries/bio/src/types';
10
10
  import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
11
- import {LIB_PATH, SETS_PATH} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
12
11
  import {
13
12
  HELM_REQUIRED_FIELD as REQ,
14
13
  } from '@datagrok-libraries/bio/src/utils/const';
@@ -17,10 +16,10 @@ import {
17
16
  } from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
18
17
 
19
18
  import {MonomerLib} from '../monomer-lib';
20
- import {HELM_JSON_SCHEMA_PATH} from './consts';
21
19
  import {MonomerLibFileEventManager} from './event-manager';
22
20
  import {MonomerLibFileValidator} from './file-validator';
23
21
  import {MonomerSet, MonomerSetPlaceholder} from '../monomer-set';
22
+ import {HELM_JSON_SCHEMA_PATH, LIB_PATH, SETS_PATH} from '../consts';
24
23
 
25
24
  import {_package} from '../../../package';
26
25
 
@@ -0,0 +1,68 @@
1
+ import {HelmTypes} from '@datagrok-libraries/bio/src/helm/consts';
2
+ import {Helm} from '../helm-to-molfile/converter/helm';
3
+ import {HelmType} from '@datagrok-libraries/bio/src/helm/types';
4
+
5
+ /**
6
+ * MonomerColors class from HelmWebEditor for natural monomers
7
+ */
8
+ export const naturalMonomerColors = {
9
+ [HelmTypes.BASE]: {
10
+ A: "#A0A0FF",
11
+ G: "#FF7070",
12
+ T: "#A0FFA0",
13
+ C: "#FF8C4B",
14
+ U: "#FF8080"
15
+ },
16
+
17
+ [HelmTypes.NUCLEOTIDE]: {
18
+ A: "#A0A0FF",
19
+ G: "#FF7070",
20
+ T: "#A0FFA0",
21
+ C: "#FF8C4B",
22
+ U: "#FF8080"
23
+ },
24
+
25
+ [HelmTypes.LINKER]: {
26
+ P: "#9aa5e1",
27
+ p: "#9aa5e1"
28
+ },
29
+
30
+ [HelmTypes.SUGAR]: {
31
+ R: "#7a85c1",
32
+ r: "#7a85c1",
33
+ // TODO: deoxyribose
34
+ },
35
+
36
+ [HelmTypes.AA]: {
37
+ A: "#C8C8C8",
38
+ R: "#145AFF",
39
+ N: "#00DCDC",
40
+ D: "#E60A0A",
41
+ C: "#E6E600",
42
+ E: "#00DCDC",
43
+ Q: "#E60A0A",
44
+ G: "#EBEBEB",
45
+ H: "#8282D2",
46
+ I: "#0F820F",
47
+ L: "#0F820F",
48
+ K: "#145AFF",
49
+ M: "#E6E600",
50
+ F: "#3232AA",
51
+ P: "#DC9682",
52
+ S: "#FA9600",
53
+ T: "#FA9600",
54
+ W: "#B45AB4",
55
+ Y: "#3232AA",
56
+ V: "#0F820F"
57
+ },
58
+
59
+ [HelmTypes.CHEM]: {
60
+ R: "#eeeeee",
61
+ },
62
+
63
+ [HelmTypes.BLOB]: {
64
+ B: "#999999",
65
+ G: "#e2e2e2"
66
+ }
67
+ };
68
+
@@ -0,0 +1,165 @@
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 wu from 'wu';
6
+
7
+ import {IMonomerLibBase, Monomer, RGroup} from '@datagrok-libraries/bio/src/types/index';
8
+ import {HelmAtom, HelmType, IWebEditorMonomer, MonomerType, PolymerType} from '@datagrok-libraries/bio/src/helm/types';
9
+ import {getMonomerHandleArgs} from '@datagrok-libraries/bio/src/helm/helm-helper';
10
+ import {helmTypeToPolymerType} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
11
+ import {HelmTypes, PolymerTypes} from '@datagrok-libraries/bio/src/helm/consts';
12
+ import {HELM_REQUIRED_FIELD as REQ, HELM_RGROUP_FIELDS as RGP} from '@datagrok-libraries/bio/src/utils/const';
13
+ import {GapOriginals, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
14
+
15
+ import {AmbiguousWebEditorMonomer, GapWebEditorMonomer, MissingWebEditorMonomer} from './web-editor-monomer-dummy';
16
+ import {LibraryWebEditorMonomer} from './web-editor-monomer-of-library';
17
+
18
+ import {_package} from '../../package';
19
+ import {Observable, Subject} from 'rxjs';
20
+
21
+ const monomerRe = /[\w()]+/;
22
+ //** Do not mess with monomer symbol with parenthesis enclosed in square brackets */
23
+ const ambMonomerRe = RegExp(String.raw`\(${monomerRe}(,${monomerRe})+\)`);
24
+
25
+ export type MonomerLibDataType = { [polymerType: string]: { [monomerSymbol: string]: Monomer } };
26
+
27
+ export class MonomerLibBase implements IMonomerLibBase {
28
+ protected _onChanged = new Subject<any>();
29
+
30
+ get onChanged(): Observable<any> { return this._onChanged; }
31
+
32
+ constructor(
33
+ protected _monomers: MonomerLibDataType,
34
+ ) {}
35
+
36
+ /** Creates missing {@link Monomer} */
37
+ addMissingMonomer(polymerType: PolymerType, monomerSymbol: string): Monomer {
38
+ let mSet = this._monomers[polymerType];
39
+ if (!mSet)
40
+ mSet = this._monomers[polymerType] = {};
41
+
42
+ let monomerName: string = monomerSymbol;
43
+ if (monomerSymbol === GapOriginals[NOTATION.HELM])
44
+ monomerName = 'Gap';
45
+ else if (polymerType === PolymerTypes.PEPTIDE && monomerSymbol === 'X')
46
+ monomerName = 'Any';
47
+ else if (polymerType === PolymerTypes.RNA && monomerSymbol === 'N')
48
+ monomerName = 'Any';
49
+
50
+ const m = mSet[monomerSymbol] = {
51
+ [REQ.SYMBOL]: monomerSymbol,
52
+ [REQ.NAME]: monomerName,
53
+ [REQ.MOLFILE]: '',
54
+ [REQ.AUTHOR]: 'MISSING',
55
+ [REQ.ID]: -1,
56
+ [REQ.RGROUPS]:
57
+ wu.count(1).take(9).map((i) => {
58
+ return {
59
+ /* eslint-disable no-multi-spaces */
60
+ // Samples // PEPTIDE RNA
61
+ [RGP.CAP_GROUP_SMILES]: '', // '[*:1][H]' '[*:1][H]'
62
+ [RGP.ALTERNATE_ID]: '', // 'R1-H' 'R1-H'
63
+ [RGP.CAP_GROUP_NAME]: '', // 'H' 'H'
64
+ [RGP.LABEL]: `R${i.toString()}`, // 'R1' 'R1'
65
+ /* eslint-enable no-multi-spaces */
66
+ } as RGroup;
67
+ }).toArray(),
68
+ [REQ.SMILES]: '',
69
+ [REQ.POLYMER_TYPE]: polymerType,
70
+ [REQ.MONOMER_TYPE]: undefined as unknown as MonomerType, // TODO: Can we get monomerType from atom of POM
71
+ [REQ.CREATE_DATE]: null,
72
+ } as Monomer;
73
+ return m;
74
+ }
75
+
76
+ getMonomer(polymerType: PolymerType | null, argMonomerSymbol: string): Monomer | null {
77
+ const logPrefix = `Bio: MonomerLib.getMonomer()`;
78
+ // Adjust RNA's 'R' for ribose to 'r' and 'P' for phosphate to 'p' for case-sensitive monomer names.
79
+ // There are uppercase 'R' and 'P' at RNA samples in test data 'helm2.csv' but lowercase in HELMCoreLibrary.json
80
+ let monomerSymbol = argMonomerSymbol;
81
+ if (polymerType == 'RNA' && monomerSymbol == 'R')
82
+ monomerSymbol = 'r';
83
+ if (polymerType == 'RNA' && monomerSymbol == 'P')
84
+ monomerSymbol = 'p';
85
+
86
+ let res: Monomer | null = null;
87
+
88
+ if (!polymerType) {
89
+ _package.logger.warning(`${logPrefix} symbol '${argMonomerSymbol}', polymerType not specified.`);
90
+ // Assume any polymer type
91
+ for (const [_polymerType, dict] of Object.entries(this._monomers)) {
92
+ res = dict[monomerSymbol];
93
+ if (res) break;
94
+ }
95
+ } else {
96
+ const dict = this._monomers[polymerType];
97
+ res = dict ? dict[monomerSymbol] : null;
98
+ }
99
+ return res;
100
+ }
101
+
102
+ /** Substitutes {@link org.helm.webeditor.Monomers.getMonomer()} */
103
+ getWebEditorMonomer(a: HelmAtom | HelmType, argName?: string): IWebEditorMonomer | null {
104
+ const [biotype, elem] = getMonomerHandleArgs(a, argName);
105
+ const pt = helmTypeToPolymerType(biotype);
106
+
107
+ /** Get or create {@link Monomer} object (in case it is missing in monomer library current config) */
108
+ let m: Monomer | null = this.getMonomer(pt, elem);
109
+ if (m && biotype == HelmTypes.LINKER && m[REQ.RGROUPS].length != 2) {
110
+ // Web Editor expects null
111
+ return null;
112
+ }
113
+ if (m && biotype == HelmTypes.SUGAR && m[REQ.RGROUPS].length != 3) {
114
+ // Web Editor expects null
115
+ return null;
116
+ }
117
+ if (!m /* && biotype != HelmTypes.LINKER*/)
118
+ m = this.addMissingMonomer(pt, elem);
119
+
120
+ /** Get or create {@link org,helm.WebEditorMonomer} */
121
+ let resWem: IWebEditorMonomer | null = m.wem ?? null;
122
+ if (!resWem) {
123
+ if (elem === '*')
124
+ resWem = m.wem = new GapWebEditorMonomer(biotype, elem);
125
+ else if (
126
+ (biotype === 'HELM_NUCLETIDE' && elem === 'N') ||
127
+ (biotype === 'HELM_AA' && elem === 'X') ||
128
+ (biotype === 'HELM_CHEM' && false) || // TODO: Ambiguous monomer for CHEM
129
+ ambMonomerRe.test(elem) // e.g. (A,R,_)
130
+ )
131
+ resWem = m.wem = new AmbiguousWebEditorMonomer(biotype, elem);
132
+ else if (!m.lib)
133
+ resWem = m.wem = new MissingWebEditorMonomer(biotype, elem);
134
+
135
+ if (!resWem)
136
+ resWem = m.wem = LibraryWebEditorMonomer.fromMonomer(biotype, m, this);
137
+ }
138
+
139
+ return resWem!;
140
+ }
141
+
142
+ getRS(smiles: string): { [r: string]: string } {
143
+ const newS = smiles.match(/(?<=\[)[^\][]*(?=])/gm);
144
+ const res: { [name: string]: string } = {};
145
+ let el = '';
146
+ let digit;
147
+ if (!!newS) {
148
+ for (let i = 0; i < newS.length; i++) {
149
+ if (newS[i] != null) {
150
+ if (/\d/.test(newS[i])) {
151
+ digit = newS[i][newS[i].length - 1];
152
+ newS[i] = newS[i].replace(/[0-9]/g, '');
153
+ for (let j = 0; j < newS[i].length; j++) {
154
+ if (newS[i][j] != ':')
155
+ el += newS[i][j];
156
+ }
157
+ res['R' + digit] = el;
158
+ el = '';
159
+ }
160
+ }
161
+ }
162
+ }
163
+ return res;
164
+ }
165
+ }
@@ -7,40 +7,42 @@ import * as DG from 'datagrok-api/dg';
7
7
  import wu from 'wu';
8
8
  import {Observable, Subject} from 'rxjs';
9
9
 
10
- import {HelmType, MonomerSetType, MonomerType, PolymerType} from '@datagrok-libraries/bio/src/helm/types';
11
- import {IMonomerLib, IMonomerSet, Monomer, MonomerLibSummaryType, RGroup} from '@datagrok-libraries/bio/src/types';
12
- import {HELM_REQUIRED_FIELD as REQ, HELM_RGROUP_FIELDS as RGP} from '@datagrok-libraries/bio/src/utils/const';
10
+ import {
11
+ HelmType, HelmAtom,
12
+ MonomerSetType, MonomerType, PolymerType, IWebEditorMonomer,
13
+ } from '@datagrok-libraries/bio/src/helm/types';
14
+ import {IMonomerLibBase, IMonomerLib, IMonomerSet, Monomer, MonomerLibData, MonomerLibSummaryType, RGroup} from '@datagrok-libraries/bio/src/types';
15
+ import {HELM_OPTIONAL_FIELDS as OPT, HELM_REQUIRED_FIELD as REQ, HELM_RGROUP_FIELDS as RGP} from '@datagrok-libraries/bio/src/utils/const';
13
16
  import {MolfileHandler} from '@datagrok-libraries/chem-meta/src/parsing-utils/molfile-handler';
14
- import {GapOriginals} from '@datagrok-libraries/bio/src/utils/seq-handler';
15
- import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
16
- import {PolymerTypes} from '@datagrok-libraries/bio/src/helm/consts';
17
17
  import {helmTypeToPolymerType} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
18
+ import {getUserLibSettings, setUserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
19
+ import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
18
20
 
19
- import '../../../css/cell-renderer.css';
21
+ import {MonomerLibBase, MonomerLibDataType} from './monomer-lib-base';
20
22
 
21
23
  import {_package} from '../../package';
22
- import {getUserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
23
- import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
24
+
25
+ import '../../../css/cell-renderer.css';
24
26
 
25
27
  /** Wrapper for monomers obtained from different sources. For managing monomere
26
28
  * libraries, use MolfileHandler class instead */
27
- export class MonomerLib implements IMonomerLib {
28
- private _monomers: { [polymerType: string]: { [monomerSymbol: string]: Monomer } } = {};
29
- private _onChanged = new Subject<any>();
29
+ export class MonomerLib extends MonomerLibBase implements IMonomerLib {
30
30
  private _duplicateMonomers: { [polymerType: string]: { [monomerSymbol: string]: Monomer[] } } = {};
31
31
  public get duplicateMonomers(): { [polymerType: string]: { [monomerSymbol: string]: Monomer[] } } {
32
32
  return this._duplicateMonomers;
33
33
  }
34
+
34
35
  private _duplicatesHandled = true;
35
36
  public get duplicatesHandled() { return this._duplicatesHandled; }
37
+
36
38
  private duplicatesNotified: boolean = false;
37
39
 
38
40
  constructor(
39
- monomers: { [polymerType: string]: { [monomerSymbol: string]: Monomer } },
41
+ monomers: MonomerLibDataType,
40
42
  public readonly source: string | undefined = undefined,
41
43
  public readonly error: string | undefined = undefined,
42
44
  ) {
43
- this._monomers = monomers;
45
+ super(monomers);
44
46
  for (const [_monomerType, monomersOfType] of Object.entries(this._monomers)) {
45
47
  for (const [_monomerSymbol, monomer] of Object.entries(monomersOfType))
46
48
  monomer.lib = this;
@@ -56,46 +58,6 @@ export class MonomerLib implements IMonomerLib {
56
58
  return resJSON;
57
59
  }
58
60
 
59
- /** Creates missing {@link Monomer} */
60
- addMissingMonomer(polymerType: PolymerType, monomerSymbol: string): Monomer {
61
- let mSet = this._monomers[polymerType];
62
- if (!mSet)
63
- mSet = this._monomers[polymerType] = {};
64
-
65
- let monomerName: string = monomerSymbol;
66
- if (monomerSymbol === GapOriginals[NOTATION.HELM])
67
- monomerName = 'Gap';
68
- else if (polymerType === PolymerTypes.PEPTIDE && monomerSymbol === 'X')
69
- monomerName = 'Any';
70
- else if (polymerType === PolymerTypes.RNA && monomerSymbol === 'N')
71
- monomerName = 'Any';
72
-
73
- const m = mSet[monomerSymbol] = {
74
- [REQ.SYMBOL]: monomerSymbol,
75
- [REQ.NAME]: monomerName,
76
- [REQ.MOLFILE]: '',
77
- [REQ.AUTHOR]: 'MISSING',
78
- [REQ.ID]: -1,
79
- [REQ.RGROUPS]:
80
- wu.count(1).take(9).map((i) => {
81
- return {
82
- /* eslint-disable no-multi-spaces */
83
- // Samples // PEPTIDE RNA
84
- [RGP.CAP_GROUP_SMILES]: '', // '[*:1][H]' '[*:1][H]'
85
- [RGP.ALTERNATE_ID]: '', // 'R1-H' 'R1-H'
86
- [RGP.CAP_GROUP_NAME]: '', // 'H' 'H'
87
- [RGP.LABEL]: `R${i.toString()}`, // 'R1' 'R1'
88
- /* eslint-enable no-multi-spaces */
89
- } as RGroup;
90
- }).toArray(),
91
- [REQ.SMILES]: '',
92
- [REQ.POLYMER_TYPE]: polymerType,
93
- [REQ.MONOMER_TYPE]: undefined as unknown as MonomerType, // TODO: Can we get monomerType from atom of POM
94
- [REQ.CREATE_DATE]: null,
95
- } as Monomer;
96
- return m;
97
- }
98
-
99
61
  getMonomer(polymerType: PolymerType | null, argMonomerSymbol: string): Monomer | null {
100
62
  const logPrefix = `Bio: MonomerLib.getMonomer()`;
101
63
  // Adjust RNA's 'R' for ribose to 'r' and 'P' for phosphate to 'p' for case-sensitive monomer names.
@@ -117,7 +79,7 @@ export class MonomerLib implements IMonomerLib {
117
79
  }
118
80
  } else {
119
81
  const dict = this._monomers[polymerType];
120
- res = dict ? dict[monomerSymbol] : null;
82
+ res = dict?.[monomerSymbol] ?? null;
121
83
  }
122
84
  return res;
123
85
  }
@@ -181,10 +143,6 @@ export class MonomerLib implements IMonomerLib {
181
143
  return monomers.map((monomer) => monomer?.symbol!);
182
144
  }
183
145
 
184
- get onChanged(): Observable<any> {
185
- return this._onChanged;
186
- }
187
-
188
146
  private _updateLibInt(lib: IMonomerLib): void {
189
147
  const typesNew = lib.getPolymerTypes();
190
148
  const types = this.getPolymerTypes();
@@ -285,19 +243,8 @@ export class MonomerLib implements IMonomerLib {
285
243
  return resStr;
286
244
  }
287
245
 
288
- getTooltip(polymerType: PolymerType, monomerSymbol: string): HTMLElement {
289
- // getTooltip(monomer: Monomer): HTMLElement;
290
- // getTooltip(monomerOrPolymerType: string | Monomer, symbol?: string): HTMLElement {
291
- // let polymerType: string;
292
- // let monomerSymbol: string;
293
- // if (typeof monomerOrPolymerType === 'string' || monomerOrPolymerType instanceof String) {
294
- // polymerType = monomerOrPolymerType as string;
295
- // monomerSymbol = symbol!;
296
- // } else {
297
- // const m = monomerOrPolymerType as Monomer;
298
- // polymerType = m[HELM_REQUIRED_FIELD.POLYMER_TYPE];
299
- // monomerSymbol = m[HELM_REQUIRED_FIELD.SYMBOL];
300
- // }
246
+ getTooltip(biotype: HelmType, monomerSymbol: string): HTMLElement {
247
+ const polymerType = helmTypeToPolymerType(biotype);
301
248
  const res = ui.div([], {classes: 'ui-form ui-tooltip'});
302
249
  const monomer = this.getMonomer(polymerType, monomerSymbol);
303
250
  if (monomer) {
@@ -336,4 +283,29 @@ export class MonomerLib implements IMonomerLib {
336
283
  }
337
284
  return res;
338
285
  }
286
+
287
+ override(data: MonomerLibData): IMonomerLibBase {
288
+ return new OverriddenMonomerLib(data, this);
289
+ }
290
+ }
291
+
292
+ class OverriddenMonomerLib extends MonomerLibBase {
293
+ constructor(
294
+ private readonly data: MonomerLibData,
295
+ private readonly base: MonomerLibBase
296
+ ) {
297
+ super(data);
298
+ }
299
+
300
+ get onChanged(): Observable<any> { return this.base.onChanged; }
301
+
302
+ addMissingMonomer(polymerType: PolymerType, monomerSymbol: string): Monomer {
303
+ return this.base.addMissingMonomer(polymerType, monomerSymbol);
304
+ }
305
+
306
+ getMonomer(polymerType: PolymerType | null, monomerSymbol: string): Monomer | null {
307
+ const dataMonomer = this.data[polymerType as string]?.[monomerSymbol];
308
+ const resMonomer = dataMonomer ?? this.base.getMonomer(polymerType, monomerSymbol);
309
+ return resMonomer;
310
+ }
339
311
  }
@@ -8,12 +8,12 @@ import * as DG from 'datagrok-api/dg';
8
8
  import {IMonomerManager, INewMonomerForm} from '@datagrok-libraries/bio/src/utils/monomer-ui';
9
9
  import {IMonomerLib, Monomer, RGroup} from '@datagrok-libraries/bio/src/types';
10
10
  import {DUMMY_MONOMER, HELM_RGROUP_FIELDS} from '@datagrok-libraries/bio/src/utils/const';
11
- import {LIB_PATH} from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
12
11
  import {ItemsGrid} from '@datagrok-libraries/utils/src/items-grid';
13
12
  import {mostSimilarNaturalAnalog} from '@datagrok-libraries/bio/src/utils/macromolecule/monomers';
14
13
  import {PolymerType, MonomerType} from '@datagrok-libraries/bio/src/helm/types';
15
14
 
16
15
  import {MonomerLibManager} from '../lib-manager';
16
+ import {LIB_PATH} from '../consts';
17
17
 
18
18
  import '../../../../css/monomer-manager.css';
19
19