@datagrok/sequence-translator 1.4.4 → 1.4.5
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 +11 -0
- package/detectors.js +24 -0
- package/dist/455.js +2 -0
- package/dist/455.js.map +1 -0
- package/dist/package-test.js +1 -1
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/files/polytool-rules/rules_example.json +1 -1
- package/files/samples/cyclized.csv +3 -3
- package/package.json +13 -13
- package/src/apps/common/model/oligo-toolkit-package.ts +12 -0
- package/src/apps/common/view/components/molecule-img.ts +2 -2
- package/src/apps/pattern/model/data-manager.ts +9 -9
- package/src/apps/translator/view/ui.ts +8 -8
- package/src/package-test.ts +2 -0
- package/src/package.ts +30 -4
- package/src/polytool/pt-conversion.ts +199 -37
- package/src/polytool/pt-dialog.ts +12 -2
- package/src/polytool/pt-enumeration-helm-dialog.ts +18 -11
- package/src/polytool/pt-enumeration-helm.ts +3 -2
- package/src/polytool/pt-unrule-dialog.ts +2 -2
- package/src/polytool/pt-unrule.ts +1 -1
- package/src/tests/polytool-chain-parse-notation-tests.ts +59 -0
- package/src/tests/polytool-detectors-custom-notation-test.ts +43 -0
- package/src/tests/toAtomicLevel-tests.ts +1 -1
- package/src/tests/utils/detect-macromolecule-utils.ts +64 -0
- package/src/tests/{utils.ts → utils/index.ts} +2 -2
- package/src/utils/context-menu.ts +0 -3
- package/src/utils/cyclized.ts +90 -0
- package/src/utils/dimerized.ts +10 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
n,seqs
|
|
2
2
|
1,R-F-C(1)-T-G-H-F-Y-G-H-F-Y-G-H-F-Y-P-C(1)-meI
|
|
3
|
-
2,C(1)-T-G-
|
|
3
|
+
2,C(1)-T-G-Aca-F-Y-P-C(1)-meI
|
|
4
4
|
3,R-F-C(1)-T-G-H-F-Y-P-C(1)
|
|
5
5
|
4,C(1)-T-G-H-F-H-P-C(1)
|
|
6
6
|
5,R-F-D(2)-T-G-H-F-Y-P-NH2(2)
|
|
7
|
-
6,R-F-azG(
|
|
8
|
-
7,R-F-aG(
|
|
7
|
+
6,R-F-azG(4)-T-G-H-F-Y-P-aG(4)-meI
|
|
8
|
+
7,R-F-aG(4)-T-G-H-F-Y-P-azG(4)-meI
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/sequence-translator",
|
|
3
3
|
"friendlyName": "Sequence Translator",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.5",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Alexey Chopovsky",
|
|
7
7
|
"email": "achopovsky@datagrok.ai"
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
}
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@datagrok-libraries/bio": "^5.
|
|
25
|
+
"@datagrok-libraries/bio": "^5.45.2",
|
|
26
26
|
"@datagrok-libraries/chem-meta": "^1.2.7",
|
|
27
|
-
"@datagrok-libraries/tutorials": "^1.4.
|
|
28
|
-
"@datagrok-libraries/utils": "^4.3.
|
|
27
|
+
"@datagrok-libraries/tutorials": "^1.4.3",
|
|
28
|
+
"@datagrok-libraries/utils": "^4.3.6",
|
|
29
29
|
"@types/react": "^18.0.15",
|
|
30
30
|
"cash-dom": "^8.1.0",
|
|
31
31
|
"datagrok-api": "^1.21.1",
|
|
@@ -36,32 +36,32 @@
|
|
|
36
36
|
"ts-loader": "^9.3.1",
|
|
37
37
|
"typeahead-standalone": "4.14.1",
|
|
38
38
|
"typescript": "^5.4.2",
|
|
39
|
-
"wu": "
|
|
39
|
+
"wu": "^2.1.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@datagrok-libraries/helm-web-editor": "^1.1.
|
|
43
|
-
"@datagrok-libraries/js-draw-lite": "^0.0.
|
|
44
|
-
"@datagrok/bio": "^2.
|
|
45
|
-
"@datagrok/helm": "^2.5.
|
|
46
|
-
"@datagrok/chem": "^1.12.
|
|
42
|
+
"@datagrok-libraries/helm-web-editor": "^1.1.12",
|
|
43
|
+
"@datagrok-libraries/js-draw-lite": "^0.0.9",
|
|
44
|
+
"@datagrok/bio": "^2.16.2",
|
|
45
|
+
"@datagrok/helm": "^2.5.4",
|
|
46
|
+
"@datagrok/chem": "^1.12.3",
|
|
47
47
|
"@types/jquery": "^3.5.14",
|
|
48
48
|
"@types/js-yaml": "^4.0.5",
|
|
49
49
|
"@types/lodash": "^4.14.202",
|
|
50
50
|
"@types/node-fetch": "^2.6.2",
|
|
51
51
|
"@types/object-hash": "^3.0.6",
|
|
52
52
|
"@types/react": "^18.0.15",
|
|
53
|
-
"@types/wu": "
|
|
53
|
+
"@types/wu": "^2.1.44",
|
|
54
54
|
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
|
55
55
|
"@typescript-eslint/parser": "^7.2.0",
|
|
56
56
|
"css-loader": "^6.7.3",
|
|
57
57
|
"eslint": "^8.57.0",
|
|
58
|
-
"eslint-config-google": "
|
|
58
|
+
"eslint-config-google": "^0.14.0",
|
|
59
59
|
"style-loader": "^3.3.1",
|
|
60
60
|
"ts-loader": "^9.3.1",
|
|
61
61
|
"typescript": "^4.7.4",
|
|
62
62
|
"typescript-eslint": "^7.2.0",
|
|
63
63
|
"webpack": "^5.75.0",
|
|
64
|
-
"webpack-cli": "
|
|
64
|
+
"webpack-cli": "^5.1.4"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"link-api": "npm link datagrok-api",
|
|
@@ -16,8 +16,16 @@ import {MonomerLibWrapper} from './monomer-lib/lib-wrapper';
|
|
|
16
16
|
import {FormatConverter} from '../../translator/model/format-converter';
|
|
17
17
|
import {FormatDetector} from './parsing-validation/format-detector';
|
|
18
18
|
import {highlightInvalidSubsequence} from '../view/components/colored-input/input-painters';
|
|
19
|
+
import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
19
20
|
|
|
20
21
|
export class OligoToolkitPackage extends DG.Package implements ITranslationHelper {
|
|
22
|
+
private _seqHelper: ISeqHelper;
|
|
23
|
+
public get seqHelper(): ISeqHelper {
|
|
24
|
+
if (!this._seqHelper)
|
|
25
|
+
throw new Error('Package SequenceTranslator .seqHelper is not initialized');
|
|
26
|
+
return this._seqHelper;
|
|
27
|
+
}
|
|
28
|
+
|
|
21
29
|
private _monomerLib?: IMonomerLib;
|
|
22
30
|
get monomerLib(): IMonomerLib {
|
|
23
31
|
if (!this._monomerLib)
|
|
@@ -47,6 +55,10 @@ export class OligoToolkitPackage extends DG.Package implements ITranslationHelpe
|
|
|
47
55
|
|
|
48
56
|
private initPromise?: Promise<void>;
|
|
49
57
|
|
|
58
|
+
completeInit(seqHelper: ISeqHelper): void {
|
|
59
|
+
this._seqHelper = seqHelper;
|
|
60
|
+
}
|
|
61
|
+
|
|
50
62
|
async initLibData(): Promise<void> {
|
|
51
63
|
if (!this.initPromise) {
|
|
52
64
|
this.initPromise = (async () => {
|
|
@@ -17,8 +17,8 @@ export class MoleculeImage {
|
|
|
17
17
|
this.molblock = molblok;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
private _validMolBlock
|
|
21
|
-
get molblock(): string { return this._validMolBlock
|
|
20
|
+
private _validMolBlock!: string;
|
|
21
|
+
get molblock(): string { return this._validMolBlock!; }
|
|
22
22
|
|
|
23
23
|
set molblock(value: string) {
|
|
24
24
|
if (value === '') {
|
|
@@ -33,7 +33,7 @@ export class DataManager {
|
|
|
33
33
|
instance.currentUserName = await instance.fetchCurrentUserName();
|
|
34
34
|
instance.currentUserId = await instance.fetchCurrentUserId();
|
|
35
35
|
|
|
36
|
-
const patternRecords =
|
|
36
|
+
const patternRecords = instance.fetchPatterns();
|
|
37
37
|
await instance.initializePatternMaps(patternRecords);
|
|
38
38
|
|
|
39
39
|
return instance;
|
|
@@ -81,7 +81,7 @@ export class DataManager {
|
|
|
81
81
|
if (hash === null || hash === '')
|
|
82
82
|
return null;
|
|
83
83
|
try {
|
|
84
|
-
const patternConfig =
|
|
84
|
+
const patternConfig = grok.userSettings.getValue(STORAGE_NAME, hash, false) ?? 'null';
|
|
85
85
|
const config = JSON.parse(patternConfig) as PatternConfigRecord;
|
|
86
86
|
return config;
|
|
87
87
|
} catch {
|
|
@@ -181,7 +181,7 @@ export class DataManager {
|
|
|
181
181
|
[D.MODIFY]: timestamp,
|
|
182
182
|
};
|
|
183
183
|
const record = JSON.stringify(recordObj);
|
|
184
|
-
|
|
184
|
+
grok.userSettings.add(STORAGE_NAME, hash, record, false);
|
|
185
185
|
this.currentUserPatternNameToHash.set(patternName, hash);
|
|
186
186
|
|
|
187
187
|
eventBus.selectAuthor(this.getCurrentUserAuthorshipCategory());
|
|
@@ -212,14 +212,14 @@ export class DataManager {
|
|
|
212
212
|
newRecordObj[R.DATE] = {
|
|
213
213
|
[D.MODIFY]: timestamp,
|
|
214
214
|
};
|
|
215
|
-
const oldPattern =
|
|
215
|
+
const oldPattern = grok.userSettings.getValue(STORAGE_NAME, oldHash, false) ?? 'null';
|
|
216
216
|
const oldPatternsRecord = JSON.parse(oldPattern) as PatternConfigRecord;
|
|
217
217
|
if (oldPatternsRecord[R.DATE] !== undefined && oldPatternsRecord[R.DATE][D.CREATE] != undefined)
|
|
218
218
|
newRecordObj[R.DATE][D.CREATE] = oldPatternsRecord[R.DATE][D.CREATE];
|
|
219
219
|
|
|
220
220
|
const newRecord = JSON.stringify(newRecordObj);
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
grok.userSettings.add(STORAGE_NAME, newHash, newRecord, false);
|
|
222
|
+
grok.userSettings.delete(STORAGE_NAME, oldHash, false);
|
|
223
223
|
|
|
224
224
|
this.currentUserPatternNameToHash.set(patternName, newHash);
|
|
225
225
|
eventBus.requestPatternLoad(newHash);
|
|
@@ -237,7 +237,7 @@ export class DataManager {
|
|
|
237
237
|
}
|
|
238
238
|
if (hash === undefined)
|
|
239
239
|
throw new Error(`Pattern with name ${patternName} not found`);
|
|
240
|
-
|
|
240
|
+
grok.userSettings.delete(STORAGE_NAME, hash, false);
|
|
241
241
|
this.currentUserPatternNameToHash.delete(patternName);
|
|
242
242
|
eventBus.updatePatternList();
|
|
243
243
|
|
|
@@ -264,8 +264,8 @@ export class DataManager {
|
|
|
264
264
|
return (await grok.dapi.users.current()).id;
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
private
|
|
268
|
-
const patternsRecord =
|
|
267
|
+
private fetchPatterns(): RawPatternRecords {
|
|
268
|
+
const patternsRecord = (grok.userSettings.get(STORAGE_NAME, false) ?? {}) as RawPatternRecords;
|
|
269
269
|
return patternsRecord;
|
|
270
270
|
}
|
|
271
271
|
|
|
@@ -3,9 +3,10 @@ import * as DG from 'datagrok-api/dg';
|
|
|
3
3
|
import * as grok from 'datagrok-api/grok';
|
|
4
4
|
import * as ui from 'datagrok-api/ui';
|
|
5
5
|
|
|
6
|
+
import $ from 'cash-dom';
|
|
6
7
|
import {Subject, BehaviorSubject, Observable} from 'rxjs';
|
|
7
8
|
|
|
8
|
-
import {
|
|
9
|
+
import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
9
10
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
10
11
|
|
|
11
12
|
import {DEFAULT_FORMATS} from '../../common/model/const';
|
|
@@ -22,7 +23,6 @@ import {ITranslationHelper} from '../../../types';
|
|
|
22
23
|
|
|
23
24
|
import {NUCLEOTIDES_FORMAT, SEQUENCE_COPIED_MSG, SEQ_TOOLTIP_MSG} from './const';
|
|
24
25
|
import './style.css';
|
|
25
|
-
import $ from 'cash-dom';
|
|
26
26
|
import {_package} from '../../../package';
|
|
27
27
|
|
|
28
28
|
const enum REQUIRED_COLUMN_LABEL {
|
|
@@ -34,9 +34,10 @@ const REQUIRED_COLUMN_LABELS = [REQUIRED_COLUMN_LABEL.SEQUENCE];
|
|
|
34
34
|
class TranslatorAppLayout {
|
|
35
35
|
private eventBus: EventBus;
|
|
36
36
|
private inputFormats = Object.keys(_package.jsonData.codesToHelmDict).concat(DEFAULT_FORMATS.HELM);
|
|
37
|
+
private readonly seqHelper: ISeqHelper = _package.seqHelper;
|
|
37
38
|
|
|
38
39
|
constructor(
|
|
39
|
-
private readonly th: ITranslationHelper
|
|
40
|
+
private readonly th: ITranslationHelper,
|
|
40
41
|
) {
|
|
41
42
|
this.moleculeImgDiv = ui.div([]);
|
|
42
43
|
this.moleculeImgDiv.className = 'mol-host';
|
|
@@ -171,9 +172,9 @@ class TranslatorAppLayout {
|
|
|
171
172
|
translatedColumn.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
172
173
|
const units = outputFormat == NUCLEOTIDES_FORMAT ? NOTATION.FASTA : NOTATION.HELM;
|
|
173
174
|
translatedColumn.meta.units = units;
|
|
174
|
-
const seqHandler =
|
|
175
|
-
const setUnits = outputFormat == NUCLEOTIDES_FORMAT ?
|
|
176
|
-
|
|
175
|
+
const seqHandler = this.seqHelper.getSeqHandler(translatedColumn as DG.Column<string>);
|
|
176
|
+
const setUnits = outputFormat == NUCLEOTIDES_FORMAT ? this.seqHelper.setUnitsToFastaColumn :
|
|
177
|
+
this.seqHelper.setUnitsToHelmColumn;
|
|
177
178
|
setUnits(seqHandler);
|
|
178
179
|
}
|
|
179
180
|
|
|
@@ -462,8 +463,7 @@ class ColumnInputsManager {
|
|
|
462
463
|
const input = ui.input.choice(`${columnLabel}`, {
|
|
463
464
|
value: selectedColumnName, items: columnNames,
|
|
464
465
|
onValueChanged: (value) => this.selectColumnIfTableNotNull(selectedTable, value, columnLabel)
|
|
465
|
-
}
|
|
466
|
-
);
|
|
466
|
+
});
|
|
467
467
|
|
|
468
468
|
return input;
|
|
469
469
|
}
|
package/src/package-test.ts
CHANGED
|
@@ -8,10 +8,12 @@ import './tests/formats-to-helm';
|
|
|
8
8
|
import './tests/helm-to-nucleotides';
|
|
9
9
|
import './tests/formats-support';
|
|
10
10
|
import './tests/files-tests';
|
|
11
|
+
import './tests/polytool-detectors-custom-notation-test';
|
|
11
12
|
import './tests/polytool-convert-tests';
|
|
12
13
|
import './tests/polytool-unrule-tests';
|
|
13
14
|
import './tests/polytool-enumerate-tests';
|
|
14
15
|
import './tests/polytool-enumerate-breadth-tests';
|
|
16
|
+
import './tests/polytool-chain-parse-notation-tests';
|
|
15
17
|
import './tests/toAtomicLevel-tests';
|
|
16
18
|
|
|
17
19
|
import {OligoToolkitTestPackage} from './tests/utils';
|
package/src/package.ts
CHANGED
|
@@ -2,16 +2,15 @@ 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 {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
6
|
+
import {SeqTemps} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
|
|
7
|
+
|
|
6
8
|
import {OligoToolkitPackage} from './apps/common/model/oligo-toolkit-package';
|
|
7
|
-
import {FormatDetector} from './apps/common/model/parsing-validation/format-detector';
|
|
8
|
-
import {SequenceValidator} from './apps/common/model/parsing-validation/sequence-validator';
|
|
9
9
|
import {APP_NAME} from './apps/common/view/const';
|
|
10
10
|
import {getSpecifiedAppUI} from './apps/common/view/utils';
|
|
11
11
|
import {CombinedAppUI} from './apps/common/view/combined-app-ui';
|
|
12
12
|
import {linkStrandsV3000} from './apps/structure/model/mol-transformations';
|
|
13
13
|
import {SequenceToMolfileConverter} from './apps/structure/model/sequence-to-molfile';
|
|
14
|
-
import {FormatConverter} from './apps/translator/model/format-converter';
|
|
15
14
|
import {demoOligoPatternUI, demoOligoStructureUI, demoOligoTranslatorUI} from './demo/demo-st-ui';
|
|
16
15
|
import {getExternalAppViewFactories} from './plugins/mermade';
|
|
17
16
|
import {defaultErrorHandler} from './utils/err-info';
|
|
@@ -26,9 +25,27 @@ import {ITranslationHelper} from './types';
|
|
|
26
25
|
import {addContextMenuUI} from './utils/context-menu';
|
|
27
26
|
import {PolyToolConvertFuncEditor} from './polytool/pt-convert-editor';
|
|
28
27
|
import {polyToolUnruleUI} from './polytool/pt-unrule';
|
|
28
|
+
import {CyclizedNotationProvider} from './utils/cyclized';
|
|
29
|
+
import {getSeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
29
30
|
|
|
30
31
|
export const _package: OligoToolkitPackage = new OligoToolkitPackage({debug: true}/**/);
|
|
31
32
|
|
|
33
|
+
let initSequenceTranslatorPromise: Promise<void> | null = null;
|
|
34
|
+
|
|
35
|
+
//tags: init
|
|
36
|
+
export async function init(): Promise<void> {
|
|
37
|
+
if (initSequenceTranslatorPromise === null)
|
|
38
|
+
initSequenceTranslatorPromise = initSequenceTranslatorInt();
|
|
39
|
+
return initSequenceTranslatorPromise;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function initSequenceTranslatorInt(): Promise<void> {
|
|
43
|
+
const [seqHelper] = await Promise.all([
|
|
44
|
+
getSeqHelper(),
|
|
45
|
+
]);
|
|
46
|
+
_package.completeInit(seqHelper);
|
|
47
|
+
}
|
|
48
|
+
|
|
32
49
|
//name: Oligo Toolkit
|
|
33
50
|
//meta.icon: img/icons/toolkit.png
|
|
34
51
|
//meta.browsePath: Oligo
|
|
@@ -277,3 +294,12 @@ export async function ptEnumeratorHelmApp(): Promise<void> {
|
|
|
277
294
|
export async function ptEnumeratorChemApp(): Promise<void> {
|
|
278
295
|
polyToolEnumerateChemUI();
|
|
279
296
|
}
|
|
297
|
+
|
|
298
|
+
//name: applyNotationProviderForHarmonizedSequence
|
|
299
|
+
//input: column col
|
|
300
|
+
//input: string separator
|
|
301
|
+
export function applyNotationProviderForCyclized(col: DG.Column<string>, separator: string) {
|
|
302
|
+
col.meta.units = NOTATION.CUSTOM;
|
|
303
|
+
col.tags['pt-role'] = 'template';
|
|
304
|
+
col.temp[SeqTemps.notationProvider] = new CyclizedNotationProvider(separator, _package.seqHelper);
|
|
305
|
+
}
|
|
@@ -2,36 +2,39 @@ 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
|
|
6
|
-
|
|
5
|
+
import wu from 'wu';
|
|
6
|
+
|
|
7
|
+
import {HelmTypes, PolymerTypes} from '@datagrok-libraries/bio/src/helm/consts';
|
|
8
|
+
import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
7
9
|
import {IMonomerLib, IMonomerLibBase, Monomer, MonomerLibData, RGroup} from '@datagrok-libraries/bio/src/types';
|
|
8
10
|
import {RDModule, RDMol, RDReaction, MolList, RDReactionResult} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
9
|
-
import {HELM_REQUIRED_FIELD, HELM_RGROUP_FIELDS} from '@datagrok-libraries/bio/src/utils/const';
|
|
11
|
+
import {HELM_REQUIRED_FIELD as REQ, HELM_OPTIONAL_FIELDS as OPT, HELM_RGROUP_FIELDS, HELM_OPTIONAL_FIELDS} from '@datagrok-libraries/bio/src/utils/const';
|
|
10
12
|
import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
|
|
13
|
+
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
14
|
+
import {HelmMol, HelmType, JSDraw2ModuleType, OrgType} from '@datagrok-libraries/bio/src/helm/types';
|
|
15
|
+
import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
11
16
|
|
|
12
17
|
import {Rules, RuleLink, RuleReaction} from './pt-rules';
|
|
13
18
|
import {InvalidReactionError, MonomerNotFoundError} from './types';
|
|
14
|
-
|
|
19
|
+
|
|
15
20
|
import {_package} from '../package';
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
declare const JSDraw2: JSDraw2ModuleType;
|
|
23
|
+
declare const org: OrgType;
|
|
19
24
|
|
|
20
|
-
// function addCommonTags(col: DG.Column): void {
|
|
21
|
-
// col.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
22
|
-
// col.setTag('aligned', ALIGNMENT.SEQ);
|
|
23
|
-
// col.setTag('alphabet', ALPHABET.PT);
|
|
24
|
-
// }
|
|
25
25
|
|
|
26
26
|
export class Chain {
|
|
27
27
|
linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[];
|
|
28
28
|
monomers: string[][];
|
|
29
|
+
mol: HelmMol | null;
|
|
29
30
|
|
|
30
31
|
constructor(
|
|
31
32
|
monomers: string[][],
|
|
32
|
-
linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[]
|
|
33
|
+
linkages: { fChain: number, sChain: number, fMonomer: number, sMonomer: number, fR: number, sR: number }[],
|
|
34
|
+
mol: HelmMol | null) {
|
|
33
35
|
this.linkages = linkages;
|
|
34
36
|
this.monomers = monomers;
|
|
37
|
+
this.mol = mol;
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
static fromHelm(helm: string) {
|
|
@@ -78,7 +81,7 @@ export class Chain {
|
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
83
|
|
|
81
|
-
return new Chain(monomers, linkages);
|
|
84
|
+
return new Chain(monomers, linkages, null);
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
static fromNotation(sequence: string, rules: Rules): Chain {
|
|
@@ -223,7 +226,97 @@ export class Chain {
|
|
|
223
226
|
}
|
|
224
227
|
}
|
|
225
228
|
|
|
226
|
-
const chain = new Chain(monomersAll, linkages);
|
|
229
|
+
const chain = new Chain(monomersAll, linkages, null);
|
|
230
|
+
return chain;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
static async parseNotation(sequence: string): Promise<Chain> {
|
|
234
|
+
const mainFragments: string[][] = [];
|
|
235
|
+
|
|
236
|
+
const linkages: {
|
|
237
|
+
fChain: number,
|
|
238
|
+
sChain: number,
|
|
239
|
+
fMonomer: number,
|
|
240
|
+
sMonomer: number,
|
|
241
|
+
fR: number,
|
|
242
|
+
sR: number
|
|
243
|
+
}[] = [];
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
const hh = await getHelmHelper();
|
|
247
|
+
// const sampleHwe = hh.createHelmWebEditor();
|
|
248
|
+
// sampleHwe.editor.setHelm('PEPTIDE1{R.P.D.[meI]}$$$$');
|
|
249
|
+
|
|
250
|
+
const resHwe = hh.createHelmWebEditor();
|
|
251
|
+
const resMol = resHwe.editor.m;
|
|
252
|
+
|
|
253
|
+
const rxp = /(\(.\d+\))?\{[^\}]*\}/g;
|
|
254
|
+
const seqs: string [] = [];
|
|
255
|
+
seqs.push(sequence.replaceAll(rxp, ''));
|
|
256
|
+
|
|
257
|
+
//const l = (rxpRes?.length) ?? -1;
|
|
258
|
+
|
|
259
|
+
const matches = sequence.matchAll(rxp);
|
|
260
|
+
//const rxpRes = rxp.exec(sequence);
|
|
261
|
+
for (const m of matches) {
|
|
262
|
+
const str = m![0];
|
|
263
|
+
if (str)
|
|
264
|
+
seqs.push(str);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
let counter = 0;
|
|
268
|
+
for (let i = 0; i < seqs.length; i++) {
|
|
269
|
+
const splMonomers = seqs[i].split('-');
|
|
270
|
+
const monomers: string [] = new Array<string>(splMonomers.length);
|
|
271
|
+
for (let j = 0; j < splMonomers.length; j++) {
|
|
272
|
+
const monomer = splMonomers[j].replace('{', '').replace('}', '');
|
|
273
|
+
if (monomer !== '') {
|
|
274
|
+
monomers[j] = monomer;
|
|
275
|
+
counter++;
|
|
276
|
+
} else {
|
|
277
|
+
linkages.push({fChain: i, sChain: i + 1, fMonomer: counter, sMonomer: counter + 1, fR: 1, sR: 1});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
mainFragments.push(monomers);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
counter = 0;
|
|
285
|
+
const p = new JSDraw2.Point(0, 0);
|
|
286
|
+
for (let i = 0; i < mainFragments.length; i++) {
|
|
287
|
+
for (let j = 0; j < mainFragments[i].length; j++) {
|
|
288
|
+
if (!!mainFragments[i][j]) {
|
|
289
|
+
const elem = mainFragments[i][j];
|
|
290
|
+
const bio = {type: HelmTypes.AA, i: i, j: j};
|
|
291
|
+
const atom = new JSDraw2.Atom<HelmType>(p, elem, bio);
|
|
292
|
+
resMol.addAtom(atom);
|
|
293
|
+
|
|
294
|
+
if (j !== 0) {
|
|
295
|
+
const atom1 = resMol.atoms[counter - 1];
|
|
296
|
+
const atom2 = resMol.atoms[counter];
|
|
297
|
+
const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
|
|
298
|
+
bond.r1 = 2;
|
|
299
|
+
bond.r2 = 1;
|
|
300
|
+
resMol.addBond(bond);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
counter++;
|
|
304
|
+
p.x += JSDraw2.Editor.BONDLENGTH; // Inspired by HELMWebEditor
|
|
305
|
+
}
|
|
306
|
+
p.y += 4 * JSDraw2.Editor.BONDLENGTH; // Inspired by HELMWebEditor
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
for (let i = 0; i < linkages.length; i++) {
|
|
311
|
+
const atom1 = resMol.atoms[linkages[i].fMonomer - 1];
|
|
312
|
+
const atom2 = resMol.atoms[linkages[i].sMonomer - 1];
|
|
313
|
+
const bond = new JSDraw2.Bond<HelmType>(atom1, atom2);
|
|
314
|
+
bond.r1 = linkages[i].fR;
|
|
315
|
+
bond.r2 = linkages[i].sR;
|
|
316
|
+
resMol.addBond(bond);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const chain = new Chain(mainFragments, linkages, resMol);
|
|
227
320
|
return chain;
|
|
228
321
|
}
|
|
229
322
|
|
|
@@ -233,17 +326,17 @@ export class Chain {
|
|
|
233
326
|
let idx1 = 0;
|
|
234
327
|
let idx2 = 0;
|
|
235
328
|
loop1:
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
329
|
+
for (let i = 0; i < this.monomers.length; i++) {
|
|
330
|
+
loop2:
|
|
331
|
+
for (let j = 0; j < this.monomers[i].length; j++) {
|
|
332
|
+
if (counter == changeNumber) {
|
|
333
|
+
idx1 = i;
|
|
334
|
+
idx2 = j;
|
|
335
|
+
break loop1;
|
|
336
|
+
}
|
|
337
|
+
counter++;
|
|
246
338
|
}
|
|
339
|
+
}
|
|
247
340
|
|
|
248
341
|
const previous = this.monomers[idx1][idx2];
|
|
249
342
|
|
|
@@ -254,6 +347,10 @@ export class Chain {
|
|
|
254
347
|
return res;
|
|
255
348
|
}
|
|
256
349
|
|
|
350
|
+
getNotationHelm(): string {
|
|
351
|
+
return this.getHelm();
|
|
352
|
+
}
|
|
353
|
+
|
|
257
354
|
getHelm(): string {
|
|
258
355
|
let helm = '';
|
|
259
356
|
for (let i = 0; i < this.monomers.length; i++) {
|
|
@@ -285,8 +382,66 @@ export class Chain {
|
|
|
285
382
|
return helm;
|
|
286
383
|
}
|
|
287
384
|
|
|
288
|
-
getNotation(
|
|
289
|
-
|
|
385
|
+
getNotation(): string {
|
|
386
|
+
const atoms = this.mol!.atoms;
|
|
387
|
+
const bonds = this.mol!.bonds;
|
|
388
|
+
const chains: number[] = [];
|
|
389
|
+
const specialBonds: number[] = [];
|
|
390
|
+
for (let i = 0; i < bonds.length!; i++) {
|
|
391
|
+
//@ts-ignore
|
|
392
|
+
if (bonds[i].a1.bio.i !== bonds[i].a2.bio.i)
|
|
393
|
+
specialBonds.push(i);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
for (let i = 0; i < atoms.length!; i++) {
|
|
397
|
+
//@ts-ignore
|
|
398
|
+
const atomChain = atoms[i].bio?.i;
|
|
399
|
+
if (atomChain + 1 > chains.length)
|
|
400
|
+
chains.push(1);
|
|
401
|
+
else
|
|
402
|
+
chains[atomChain]++;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const simpleChains: string[][] = new Array(chains.length);
|
|
406
|
+
let counter = 0;
|
|
407
|
+
for (let i = 0; i < chains.length!; i++) {
|
|
408
|
+
const simpleChain: string[] = new Array(chains[i]);
|
|
409
|
+
for (let j = 0; j < chains[i]; j++) {
|
|
410
|
+
simpleChain[j] = atoms[counter].elem;
|
|
411
|
+
counter++;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
simpleChains[i] = simpleChain;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
let res = '';
|
|
418
|
+
for (let i = 0; i < simpleChains.length; i++) {
|
|
419
|
+
let chainAdd = '';
|
|
420
|
+
|
|
421
|
+
for (let j = 0; j < simpleChains[i].length; j++)
|
|
422
|
+
chainAdd += `${j == 0 ? '' : '-'}${simpleChains[i][j]}`;
|
|
423
|
+
|
|
424
|
+
if (i !== 0) {
|
|
425
|
+
const rxp = /(\(.\d+\))/;
|
|
426
|
+
const match = chainAdd.match(rxp);
|
|
427
|
+
chainAdd = chainAdd.replace(match?.[0]!, '');
|
|
428
|
+
const group = match ? match?.[0]! : '';
|
|
429
|
+
chainAdd = `${group}{${chainAdd}}`;
|
|
430
|
+
} else {
|
|
431
|
+
if (simpleChains.length > 1) {
|
|
432
|
+
//@ts-ignore
|
|
433
|
+
const firstAtomLinks = bonds[specialBonds[0]].a1.bio.i == 0 && bonds[specialBonds[0]].a1.bio.j == 0;
|
|
434
|
+
//@ts-ignore
|
|
435
|
+
const secondAtomLinks = bonds[specialBonds[0]].a2.bio.i == 1 && bonds[specialBonds[0]].a1.bio.j == 0;
|
|
436
|
+
if (firstAtomLinks && secondAtomLinks)
|
|
437
|
+
chainAdd += '-';
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
res += chainAdd;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return res;
|
|
290
445
|
}
|
|
291
446
|
|
|
292
447
|
protected static getLinkedPositions(monomers: string[], rules: RuleLink[] | RuleReaction []):
|
|
@@ -517,18 +672,24 @@ export function getNewMonomer(rdkit: RDModule, mLib: IMonomerLib, rule: RuleReac
|
|
|
517
672
|
const groups: RGroup[] = getNewGroups(monomer1!, monomer2!);
|
|
518
673
|
|
|
519
674
|
const resMonomer: Monomer = {
|
|
520
|
-
[
|
|
521
|
-
[
|
|
522
|
-
[
|
|
523
|
-
[
|
|
524
|
-
[
|
|
525
|
-
[
|
|
526
|
-
[
|
|
527
|
-
[
|
|
528
|
-
[
|
|
529
|
-
[
|
|
675
|
+
[REQ.SYMBOL]: monomerName,
|
|
676
|
+
[REQ.NAME]: monomerName,
|
|
677
|
+
[REQ.MOLFILE]: molBlock,
|
|
678
|
+
[REQ.AUTHOR]: '',
|
|
679
|
+
[REQ.ID]: 0,
|
|
680
|
+
[REQ.RGROUPS]: groups,
|
|
681
|
+
[REQ.SMILES]: '',
|
|
682
|
+
[REQ.POLYMER_TYPE]: 'PEPTIDE',
|
|
683
|
+
[REQ.MONOMER_TYPE]: 'Backbone',
|
|
684
|
+
[REQ.CREATE_DATE]: null,
|
|
685
|
+
|
|
686
|
+
// // @ts-ignore
|
|
687
|
+
// lib: {source: 'Reaction'},
|
|
530
688
|
};
|
|
531
689
|
|
|
690
|
+
resMonomer[OPT.META] = Object.assign(resMonomer[OPT.META] ?? {},
|
|
691
|
+
{'colors': {'default': {line: '#2083D5', text: '#2083D5', background: '#F2F2F5'}}});
|
|
692
|
+
|
|
532
693
|
return [monomerName, resMonomer];
|
|
533
694
|
}
|
|
534
695
|
|
|
@@ -545,6 +706,7 @@ export async function getOverriddenLibrary(rules: Rules): Promise<IMonomerLibBas
|
|
|
545
706
|
}
|
|
546
707
|
|
|
547
708
|
const overrideMonomerLibData: MonomerLibData = {[PolymerTypes.PEPTIDE]: argLib};
|
|
548
|
-
const overriddenMonomerLib = systemMonomerLib.override(overrideMonomerLibData
|
|
709
|
+
const overriddenMonomerLib = systemMonomerLib.override(overrideMonomerLibData,
|
|
710
|
+
'ST-PT-reactions.' + wu.repeat(1).map(() => Math.floor((Math.random() * 36)).toString(36)).take(4).toArray().join(''));
|
|
549
711
|
return overriddenMonomerLib;
|
|
550
712
|
}
|
|
@@ -9,7 +9,10 @@ import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
|
9
9
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
10
10
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
11
11
|
import {getSeqHelper, ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
12
|
-
import {
|
|
12
|
+
import {MmcrTemps} from '@datagrok-libraries/bio/src/utils/cell-renderer-consts';
|
|
13
|
+
import {buildMonomerHoverLink} from '@datagrok-libraries/bio/src/monomer-works/monomer-hover';
|
|
14
|
+
import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
|
|
15
|
+
import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
13
16
|
|
|
14
17
|
import {getRules, RuleInputs, Rules, RULES_PATH, RULES_STORAGE_NAME} from './pt-rules';
|
|
15
18
|
import {doPolyToolConvert, getOverriddenLibrary} from './pt-conversion';
|
|
@@ -74,7 +77,7 @@ export async function getPolyToolConvertDialog(srcCol?: DG.Column): Promise<DG.D
|
|
|
74
77
|
table: srcColVal.dataFrame, value: srcColVal,
|
|
75
78
|
filter: (col: DG.Column) => {
|
|
76
79
|
if (col.semType !== DG.SEMTYPE.MACROMOLECULE) return false;
|
|
77
|
-
const sh =
|
|
80
|
+
const sh = _package.seqHelper.getSeqHandler(col);
|
|
78
81
|
return sh.notation === NOTATION.CUSTOM;
|
|
79
82
|
}
|
|
80
83
|
});
|
|
@@ -256,7 +259,11 @@ export async function polyToolConvert(
|
|
|
256
259
|
if (generateHelm && table) table.columns.add(resHelmCol, true);
|
|
257
260
|
|
|
258
261
|
const seqHelper: ISeqHelper = await getSeqHelper();
|
|
262
|
+
const rdKitModule: RDModule = await getRdKitModule();
|
|
259
263
|
const lib = await getOverriddenLibrary(rules);
|
|
264
|
+
const resHelmColTemp = resHelmCol.temp;
|
|
265
|
+
resHelmColTemp[MmcrTemps.overriddenLibrary] = lib;
|
|
266
|
+
resHelmCol.temp = resHelmColTemp;
|
|
260
267
|
const toAtomicLevelRes =
|
|
261
268
|
await seqHelper.helmToAtomicLevel(resHelmCol, chiralityEngine, /* highlight */ generateHelm, lib);
|
|
262
269
|
const resMolCol = toAtomicLevelRes.molCol!;
|
|
@@ -267,6 +274,9 @@ export async function polyToolConvert(
|
|
|
267
274
|
table.columns.add(resMolCol, true);
|
|
268
275
|
await grok.data.detectSemanticTypes(table);
|
|
269
276
|
}
|
|
277
|
+
|
|
278
|
+
buildMonomerHoverLink(resHelmCol, resMolCol, lib, seqHelper, rdKitModule);
|
|
279
|
+
|
|
270
280
|
return [resHelmCol, resMolCol];
|
|
271
281
|
} finally {
|
|
272
282
|
pi.close();
|