@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.
- package/CHANGELOG.md +40 -0
- package/detectors.js +9 -2
- package/dist/284.js +1 -1
- package/dist/284.js.map +1 -1
- package/dist/455.js +2 -0
- package/dist/455.js.map +1 -0
- package/dist/980.js +1 -1
- package/dist/980.js.map +1 -1
- package/dist/package-test.js +3 -3
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +2 -2
- package/dist/package.js.map +1 -1
- package/files/monomer-libraries/polytool-lib.json +52 -0
- package/files/tests/to-atomic-level-msa-fasta-output.csv +683 -683
- package/files/tests/to-atomic-level-msa-separator-output.csv +104 -104
- package/package.json +9 -9
- package/src/analysis/sequence-activity-cliffs.ts +3 -1
- package/src/calculations/monomerLevelMols.ts +2 -1
- package/src/demo/bio03-atomic-level.ts +1 -1
- package/src/package-test.ts +2 -1
- package/src/package.ts +151 -38
- package/src/tests/WebLogo-positions-test.ts +1 -1
- package/src/tests/activity-cliffs-tests.ts +2 -3
- package/src/tests/bio-tests.ts +1 -1
- package/src/tests/detectors-custom-notation-tests.ts +37 -0
- package/src/tests/detectors-tests.ts +20 -69
- package/src/tests/detectors-weak-and-likely-tests.ts +2 -2
- package/src/tests/monomer-libraries-tests.ts +31 -6
- package/src/tests/pepsea-tests.ts +1 -1
- package/src/tests/renderers-monomer-placer-tests.ts +2 -4
- package/src/tests/scoring.ts +2 -3
- package/src/tests/seq-handler-get-helm-tests.ts +2 -4
- package/src/tests/seq-handler-splitted-tests.ts +6 -2
- package/src/tests/splitters-test.ts +6 -6
- package/src/tests/substructure-filters-tests.ts +2 -3
- package/src/tests/to-atomic-level-tests.ts +22 -17
- package/src/tests/to-atomic-level-ui-tests.ts +76 -38
- package/src/tests/types.ts +0 -2
- package/src/tests/utils/detectors-utils.ts +63 -0
- package/src/tests/utils.ts +2 -2
- package/src/utils/cell-renderer-custom.ts +62 -0
- package/src/utils/cell-renderer.ts +58 -126
- package/src/utils/cyclized.ts +28 -14
- package/src/utils/dimerized.ts +0 -2
- package/src/utils/helm-to-molfile/converter/converter.ts +75 -54
- package/src/utils/helm-to-molfile/converter/monomer-wrapper.ts +2 -2
- package/src/utils/helm-to-molfile/converter/polymer.ts +23 -16
- package/src/utils/helm-to-molfile/converter/types.ts +0 -10
- package/src/utils/helm-to-molfile/utils.ts +10 -7
- package/src/utils/monomer-lib/consts.ts +18 -0
- package/src/utils/monomer-lib/lib-manager.ts +13 -3
- package/src/utils/monomer-lib/library-file-manager/file-manager.ts +1 -2
- package/src/utils/monomer-lib/monomer-colors.ts +68 -0
- package/src/utils/monomer-lib/monomer-lib-base.ts +165 -0
- package/src/utils/monomer-lib/monomer-lib.ts +44 -72
- package/src/utils/monomer-lib/monomer-manager/monomer-manager.ts +1 -1
- package/src/utils/monomer-lib/web-editor-monomer-dummy.ts +121 -0
- package/src/utils/monomer-lib/web-editor-monomer-of-library.ts +102 -0
- package/src/utils/pepsea.ts +1 -1
- package/src/utils/save-as-fasta.ts +1 -1
- package/src/utils/seq-helper/seq-helper.ts +20 -49
- package/src/utils/sequence-to-mol.ts +24 -28
- package/src/viewers/web-logo-viewer.ts +2 -1
- package/src/widgets/composition-analysis-widget.ts +4 -3
- package/src/widgets/representations.ts +8 -10
- package/dist/248.js +0 -2
- package/dist/248.js.map +0 -1
- package/src/utils/cell-renderer-consts.ts +0 -31
- 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 {
|
|
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(
|
|
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
|
-
|
|
23
|
+
helmCol: DG.Column<string>
|
|
22
24
|
): Promise<DG.Column<string>> {
|
|
23
25
|
const seqHelper = await SeqHelper.getInstance();
|
|
24
|
-
const
|
|
25
|
-
const
|
|
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,
|
|
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 =
|
|
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
|
|
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 {
|
|
11
|
-
|
|
12
|
-
|
|
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 '
|
|
21
|
+
import {MonomerLibBase, MonomerLibDataType} from './monomer-lib-base';
|
|
20
22
|
|
|
21
23
|
import {_package} from '../../package';
|
|
22
|
-
|
|
23
|
-
import
|
|
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:
|
|
41
|
+
monomers: MonomerLibDataType,
|
|
40
42
|
public readonly source: string | undefined = undefined,
|
|
41
43
|
public readonly error: string | undefined = undefined,
|
|
42
44
|
) {
|
|
43
|
-
|
|
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
|
|
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(
|
|
289
|
-
|
|
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
|
|