@datagrok/sequence-translator 1.2.7 → 1.3.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.
- package/.eslintrc.json +5 -5
- package/CHANGELOG.md +14 -0
- package/dist/package-test.js +2 -1
- package/dist/package-test.js.LICENSE.txt +8 -0
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +2 -1
- package/dist/package.js.LICENSE.txt +8 -0
- package/dist/package.js.map +1 -1
- package/files/pattern-app-data.json +80 -0
- package/package.json +22 -14
- package/src/{model → apps/common/model}/const.ts +1 -1
- package/src/{model/data-loading-utils → apps/common/model/data-loader}/const.ts +7 -2
- package/src/apps/common/model/data-loader/json-loader.ts +48 -0
- package/src/{model/data-loading-utils → apps/common/model/data-loader}/types.ts +13 -6
- package/src/{model → apps/common/model}/monomer-lib/lib-wrapper.ts +9 -12
- package/src/apps/common/model/oligo-toolkit-package.ts +30 -0
- package/src/{model → apps/common/model}/parsing-validation/format-detector.ts +5 -5
- package/src/{model → apps/common/model}/parsing-validation/format-handler.ts +18 -19
- package/src/{model → apps/common/model}/parsing-validation/sequence-validator.ts +1 -1
- package/src/apps/common/view/app-ui-base.ts +28 -0
- package/src/apps/common/view/combined-app-ui.ts +66 -0
- package/src/{view/utils → apps/common/view/components}/colored-input/colored-text-input.ts +1 -1
- package/src/{view/utils → apps/common/view/components}/draw-molecule.ts +1 -1
- package/src/{view/utils → apps/common/view/components}/molecule-img.ts +3 -3
- package/src/{view/const/ui.ts → apps/common/view/const.ts} +4 -4
- package/src/apps/common/view/isolated-app-ui.ts +43 -0
- package/src/{view/monomer-lib-viewer/viewer.ts → apps/common/view/monomer-lib-viewer.ts} +2 -2
- package/src/apps/common/view/utils.ts +29 -0
- package/src/apps/pattern/model/const.ts +121 -0
- package/src/apps/pattern/model/data-manager.ts +297 -0
- package/src/apps/pattern/model/event-bus.ts +487 -0
- package/src/apps/pattern/model/router.ts +46 -0
- package/src/apps/pattern/model/subscription-manager.ts +21 -0
- package/src/apps/pattern/model/translator.ts +94 -0
- package/src/apps/pattern/model/types.ts +52 -0
- package/src/apps/pattern/model/utils.ts +110 -0
- package/src/apps/pattern/view/components/bulk-convert/column-input.ts +79 -0
- package/src/apps/pattern/view/components/bulk-convert/table-controls.ts +38 -0
- package/src/apps/pattern/view/components/bulk-convert/table-input.ts +95 -0
- package/src/apps/pattern/view/components/edit-block-controls.ts +196 -0
- package/src/apps/pattern/view/components/left-section.ts +44 -0
- package/src/apps/pattern/view/components/load-block-controls.ts +200 -0
- package/src/apps/pattern/view/components/numeric-label-visibility-controls.ts +69 -0
- package/src/apps/pattern/view/components/right-section.ts +148 -0
- package/src/apps/pattern/view/components/strand-editor/dialog.ts +79 -0
- package/src/apps/pattern/view/components/strand-editor/header-controls.ts +105 -0
- package/src/apps/pattern/view/components/strand-editor/strand-controls.ts +159 -0
- package/src/apps/pattern/view/components/terminal-modification-editor.ts +127 -0
- package/src/apps/pattern/view/components/translation-examples-block.ts +139 -0
- package/src/{view/style/pattern-app.css → apps/pattern/view/style.css} +4 -0
- package/src/apps/pattern/view/svg-utils/const.ts +77 -0
- package/src/apps/pattern/view/svg-utils/legend-block.ts +92 -0
- package/src/apps/pattern/view/svg-utils/strands-block.ts +335 -0
- package/src/apps/pattern/view/svg-utils/svg-block-base.ts +37 -0
- package/src/apps/pattern/view/svg-utils/svg-display-manager.ts +44 -0
- package/src/apps/pattern/view/svg-utils/svg-element-factory.ts +94 -0
- package/src/apps/pattern/view/svg-utils/svg-renderer.ts +51 -0
- package/src/apps/pattern/view/svg-utils/text-dimensions-calculator.ts +29 -0
- package/src/apps/pattern/view/svg-utils/title-block.ts +53 -0
- package/src/apps/pattern/view/svg-utils/utils.ts +37 -0
- package/src/apps/pattern/view/types.ts +14 -0
- package/src/apps/pattern/view/ui.ts +61 -0
- package/src/{model/structure-app → apps/structure/model}/mol-transformations.ts +3 -3
- package/src/{model/structure-app → apps/structure/model}/monomer-code-parser.ts +9 -10
- package/src/{model/structure-app → apps/structure/model}/oligo-structure.ts +4 -4
- package/src/{model/structure-app → apps/structure/model}/sequence-to-molfile.ts +2 -2
- package/src/{view/apps/oligo-structure.ts → apps/structure/view/ui.ts} +31 -17
- package/src/{model/translator-app → apps/translator/model}/conversion-utils.ts +25 -7
- package/src/{model/translator-app → apps/translator/model}/format-converter.ts +7 -12
- package/src/{view/const/oligo-translator.ts → apps/translator/view/const.ts} +1 -1
- package/src/{view/apps/oligo-translator.ts → apps/translator/view/ui.ts} +88 -42
- package/src/demo/demo-st-ui.ts +12 -32
- package/src/package.ts +91 -55
- package/src/plugins/mermade.ts +9 -9
- package/src/polytool/const.ts +28 -0
- package/src/polytool/csv-to-json-monomer-lib-converter.ts +40 -0
- package/src/polytool/cyclized.ts +56 -0
- package/src/polytool/monomer-lib-handler.ts +115 -0
- package/src/polytool/pt-conversion.ts +307 -0
- package/src/polytool/pt-dialog.ts +115 -0
- package/src/polytool/pt-enumeration.ts +127 -0
- package/src/polytool/pt-rules.ts +73 -0
- package/src/polytool/utils.ts +27 -0
- package/src/tests/const.ts +5 -5
- package/src/tests/formats-support.ts +6 -6
- package/src/tests/formats-to-helm.ts +5 -5
- package/src/tests/helm-to-nucleotides.ts +5 -10
- package/tsconfig.json +3 -9
- package/webpack.config.js +3 -0
- package/files/axolabs-style.json +0 -97
- package/src/model/data-loading-utils/json-loader.ts +0 -38
- package/src/model/pattern-app/const.ts +0 -33
- package/src/model/pattern-app/draw-svg.ts +0 -193
- package/src/model/pattern-app/helpers.ts +0 -96
- package/src/model/pattern-app/oligo-pattern.ts +0 -111
- package/src/view/app-ui.ts +0 -193
- package/src/view/apps/oligo-pattern.ts +0 -759
- /package/src/{model → apps/common/model}/helpers.ts +0 -0
- /package/src/{model → apps/common/model}/monomer-lib/const.ts +0 -0
- /package/src/{view/utils → apps/common/view/components}/app-info-dialog.ts +0 -0
- /package/src/{view/utils → apps/common/view/components}/colored-input/input-painters.ts +0 -0
- /package/src/{view/style/colored-text-input.css → apps/common/view/components/colored-input/style.css} +0 -0
- /package/src/{view/utils → apps/common/view/components}/router.ts +0 -0
- /package/src/{model/structure-app → apps/structure/model}/const.ts +0 -0
- /package/src/{view/style/structure-app.css → apps/structure/view/style.css} +0 -0
- /package/src/{model/translator-app → apps/translator/model}/const.ts +0 -0
- /package/src/{view/style/translator-app.css → apps/translator/view/style.css} +0 -0
package/src/demo/demo-st-ui.ts
CHANGED
|
@@ -3,43 +3,22 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
5
|
import {delay} from '@datagrok-libraries/utils/src/test';
|
|
6
|
-
import {
|
|
6
|
+
import {loadJsonData} from '../apps/common/model/data-loader/json-loader';
|
|
7
7
|
import {_package, oligoTranslatorApp, oligoPatternApp, oligoStructureApp} from '../package';
|
|
8
|
-
import {tryCatch} from '../model/helpers';
|
|
8
|
+
import {tryCatch} from '../apps/common/model/helpers';
|
|
9
9
|
|
|
10
10
|
export async function demoOligoTranslatorUI() {
|
|
11
|
-
await tryCatch(async () =>
|
|
11
|
+
await tryCatch(async () => {
|
|
12
|
+
const view = await oligoTranslatorApp();
|
|
13
|
+
grok.shell.addView(view);
|
|
14
|
+
});
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
export async function demoOligoPatternUI() {
|
|
15
18
|
await tryCatch(async () => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// warning: this redefinition is necessary because
|
|
20
|
-
// the ids of the elements can dynamically change
|
|
21
|
-
const choiceInputs: NodeListOf<HTMLSelectElement> = document.querySelectorAll('.st-pattern-choice-input > select');
|
|
22
|
-
len = choiceInputs.length;
|
|
23
|
-
const selectElement = choiceInputs[idxUpdate(idx)];
|
|
24
|
-
selectElement.value = value;
|
|
25
|
-
const event = new Event('input');
|
|
26
|
-
selectElement.dispatchEvent(event);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
await oligoPatternApp();
|
|
30
|
-
|
|
31
|
-
let len: number;
|
|
32
|
-
|
|
33
|
-
const ssNewValues = ['DNA', 'invAb', 'Z-New'];
|
|
34
|
-
ssNewValues.forEach(async (value, idx) => {
|
|
35
|
-
emulateUserInput(value, idx, (i) => 2 * i);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const asNewValues = ['2\'-O-Methyl', '2\'-Fluoro', '2\'-O-MOE'];
|
|
39
|
-
asNewValues.forEach(async (value, idx) => {
|
|
40
|
-
emulateUserInput(value, idx, (i) => (len - 2 - 2 * i));
|
|
41
|
-
});
|
|
42
|
-
})
|
|
19
|
+
const view = await oligoPatternApp();
|
|
20
|
+
grok.shell.addView(view);
|
|
21
|
+
});
|
|
43
22
|
}
|
|
44
23
|
|
|
45
24
|
export async function demoOligoStructureUI() {
|
|
@@ -52,10 +31,11 @@ export async function demoOligoStructureUI() {
|
|
|
52
31
|
const event = new Event('input');
|
|
53
32
|
textarea.dispatchEvent(event);
|
|
54
33
|
}
|
|
55
|
-
await oligoStructureApp();
|
|
34
|
+
const view = await oligoStructureApp();
|
|
35
|
+
grok.shell.addView(view);
|
|
56
36
|
const inputSequences = ['Afcgacsu', 'Afcgacsu', 'Afcgacsu'];
|
|
57
37
|
inputSequences.forEach(async (sequence, idx) => {
|
|
58
38
|
await setInputValue(idx, sequence);
|
|
59
|
-
})
|
|
39
|
+
});
|
|
60
40
|
});
|
|
61
41
|
}
|
package/src/package.ts
CHANGED
|
@@ -1,94 +1,76 @@
|
|
|
1
|
+
import DG from 'datagrok-api/dg';
|
|
1
2
|
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 {AppUIFactory, CombinedAppUI} from './view/app-ui';
|
|
6
|
-
import {tryCatch} from './model/helpers';
|
|
7
|
-
import {LIB_PATH, DEFAULT_LIB_FILENAME} from './model/data-loading-utils/const';
|
|
8
|
-
import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
|
|
9
|
-
import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
10
|
-
import {getJsonData} from './model/data-loading-utils/json-loader';
|
|
11
|
-
import {SequenceToMolfileConverter} from './model/structure-app/sequence-to-molfile';
|
|
12
|
-
import {linkStrandsV3000} from './model/structure-app/mol-transformations';
|
|
13
|
-
import {MonomerLibWrapper} from './model/monomer-lib/lib-wrapper';
|
|
14
|
-
import {FormatDetector} from './model/parsing-validation/format-detector';
|
|
15
|
-
import {SequenceValidator} from './model/parsing-validation/sequence-validator';
|
|
16
|
-
import {demoOligoTranslatorUI, demoOligoPatternUI, demoOligoStructureUI} from './demo/demo-st-ui';
|
|
17
|
-
import {FormatConverter} from './model/translator-app/format-converter';
|
|
18
|
-
import {APP} from './view/const/ui';
|
|
19
|
-
import {getExternalAppViewFactories} from './plugins/mermade';
|
|
20
|
-
|
|
21
|
-
class StPackage extends DG.Package {
|
|
22
|
-
private _monomerLib?: IMonomerLib;
|
|
23
|
-
|
|
24
|
-
get monomerLib(): IMonomerLib {
|
|
25
|
-
if (!this._monomerLib)
|
|
26
|
-
throw new Error ('Monomer lib not loaded')
|
|
27
|
-
return this._monomerLib!;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public async initMonomerLib(): Promise<void> {
|
|
31
|
-
if (this._monomerLib !== undefined)
|
|
32
|
-
return;
|
|
33
3
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
4
|
+
import {loadJsonData} from './apps/common/model/data-loader/json-loader';
|
|
5
|
+
import {MonomerLibWrapper} from './apps/common/model/monomer-lib/lib-wrapper';
|
|
6
|
+
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
|
+
import {APP_NAME} from './apps/common/view/const';
|
|
10
|
+
import {getSpecifiedAppUI} from './apps/common/view/utils';
|
|
11
|
+
import {CombinedAppUI} from './apps/common/view/combined-app-ui';
|
|
12
|
+
import {linkStrandsV3000} from './apps/structure/model/mol-transformations';
|
|
13
|
+
import {SequenceToMolfileConverter} from './apps/structure/model/sequence-to-molfile';
|
|
14
|
+
import {FormatConverter} from './apps/translator/model/format-converter';
|
|
15
|
+
import {demoOligoPatternUI, demoOligoStructureUI, demoOligoTranslatorUI} from './demo/demo-st-ui';
|
|
16
|
+
import {getExternalAppViewFactories} from './plugins/mermade';
|
|
42
17
|
|
|
43
|
-
|
|
18
|
+
//polytool specific
|
|
19
|
+
import {getPolyToolConversionDialog, getPolyToolEnumerationDialog} from './polytool/pt-dialog';
|
|
20
|
+
import {_setPeptideColumn} from './polytool/utils';
|
|
21
|
+
import {PolyToolCsvLibHandler} from './polytool/csv-to-json-monomer-lib-converter';
|
|
44
22
|
|
|
45
|
-
async function buildLayout(appName: string): Promise<void> {
|
|
46
|
-
await initSequenceTranslatorLibData();
|
|
47
|
-
const appUI = AppUIFactory.getUI(appName);
|
|
48
|
-
await appUI.createAppLayout();
|
|
49
|
-
}
|
|
50
23
|
|
|
24
|
+
export const _package: OligoToolkitPackage = new OligoToolkitPackage();
|
|
51
25
|
|
|
52
26
|
//name: Oligo Toolkit
|
|
53
27
|
//meta.icon: img/icons/toolkit.png
|
|
54
28
|
//meta.browsePath: Oligo
|
|
55
29
|
//tags: app
|
|
56
|
-
|
|
30
|
+
//output: view v
|
|
31
|
+
export async function oligoToolkitApp(): Promise<DG.ViewBase> {
|
|
57
32
|
await initSequenceTranslatorLibData();
|
|
58
33
|
const externalViewFactories = await getExternalAppViewFactories();
|
|
59
34
|
if (!externalViewFactories)
|
|
60
35
|
throw new Error('External app view factories not loaded');
|
|
61
36
|
const appUI = new CombinedAppUI(externalViewFactories!);
|
|
62
|
-
await appUI.
|
|
37
|
+
const view = await appUI.getAppView();
|
|
38
|
+
return view;
|
|
63
39
|
}
|
|
64
40
|
|
|
65
41
|
//name: Oligo Translator
|
|
66
42
|
//meta.icon: img/icons/translator.png
|
|
67
43
|
//meta.browsePath: Oligo
|
|
68
44
|
//tags: app
|
|
69
|
-
|
|
70
|
-
|
|
45
|
+
//output: view v
|
|
46
|
+
export async function oligoTranslatorApp(): Promise<DG.ViewBase> {
|
|
47
|
+
const view = await getSpecifiedAppView(APP_NAME.TRANSLATOR);
|
|
48
|
+
return view;
|
|
71
49
|
}
|
|
72
50
|
|
|
73
51
|
//name: Oligo Pattern
|
|
74
52
|
//meta.icon: img/icons/pattern.png
|
|
75
53
|
//meta.browsePath: Oligo
|
|
76
54
|
//tags: app
|
|
77
|
-
|
|
78
|
-
|
|
55
|
+
//output: view v
|
|
56
|
+
export async function oligoPatternApp(): Promise<DG.ViewBase> {
|
|
57
|
+
const view = await getSpecifiedAppView(APP_NAME.PATTERN);
|
|
58
|
+
return view;
|
|
79
59
|
}
|
|
80
60
|
|
|
81
61
|
//name: Oligo Structure
|
|
82
62
|
//meta.icon: img/icons/structure.png
|
|
83
63
|
//meta.browsePath: Oligo
|
|
84
64
|
//tags: app
|
|
85
|
-
|
|
86
|
-
|
|
65
|
+
//output: view v
|
|
66
|
+
export async function oligoStructureApp(): Promise<DG.ViewBase> {
|
|
67
|
+
const view = await getSpecifiedAppView(APP_NAME.STRUCTURE);
|
|
68
|
+
return view;
|
|
87
69
|
}
|
|
88
70
|
|
|
89
71
|
//name: initSequenceTranslatorLibData
|
|
90
72
|
export async function initSequenceTranslatorLibData(): Promise<void> {
|
|
91
|
-
await
|
|
73
|
+
await loadJsonData();
|
|
92
74
|
await _package.initMonomerLib();
|
|
93
75
|
}
|
|
94
76
|
|
|
@@ -152,7 +134,61 @@ export async function demoOligoStructure(): Promise<void> {
|
|
|
152
134
|
//input: string sourceFormat
|
|
153
135
|
//input: string targetFormat
|
|
154
136
|
//output: string result
|
|
155
|
-
export async function translateOligonucleotideSequence(
|
|
137
|
+
export async function translateOligonucleotideSequence(
|
|
138
|
+
sequence: string, sourceFormat: string, targetFormat: string
|
|
139
|
+
): Promise<string> {
|
|
156
140
|
await initSequenceTranslatorLibData();
|
|
157
141
|
return (new FormatConverter(sequence, sourceFormat)).convertTo(targetFormat);
|
|
158
142
|
}
|
|
143
|
+
|
|
144
|
+
async function getSpecifiedAppView(appName: string): Promise<DG.ViewBase> {
|
|
145
|
+
await initSequenceTranslatorLibData();
|
|
146
|
+
const appUI = getSpecifiedAppUI(appName);
|
|
147
|
+
const view = await appUI.getAppView();
|
|
148
|
+
return view;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
//top-menu: Bio | Convert | PolyTool-Convert
|
|
152
|
+
//name: polyToolConvert
|
|
153
|
+
//description: Perform cyclization of polymers
|
|
154
|
+
export async function polyToolConvert(): Promise<void> {
|
|
155
|
+
let dialog: DG.Dialog;
|
|
156
|
+
try {
|
|
157
|
+
dialog = await getPolyToolConversionDialog();
|
|
158
|
+
dialog.show();
|
|
159
|
+
} catch (err: any) {
|
|
160
|
+
grok.shell.warning('To run PolyTool Conversion, open a dataframe with macromolecules');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
//top-menu: Bio | Convert | PolyTool-Enumerate
|
|
165
|
+
//name: polyToolEnumerate
|
|
166
|
+
//description: Perform cyclization of polymers
|
|
167
|
+
export async function polyToolEnumerate(): Promise<void> {
|
|
168
|
+
let dialog: DG.Dialog;
|
|
169
|
+
try {
|
|
170
|
+
dialog = await getPolyToolEnumerationDialog();
|
|
171
|
+
dialog.show();
|
|
172
|
+
} catch (err: any) {
|
|
173
|
+
grok.shell.warning('To run PolyTool Enumeration, sketch the macromolecule and select monomers to vary');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
//name: polyToolColumnChoice
|
|
178
|
+
//input: dataframe df [Input data table]
|
|
179
|
+
//input: column macroMolecule
|
|
180
|
+
export async function polyToolColumnChoice(df: DG.DataFrame, macroMolecule: DG.Column): Promise<void> {
|
|
181
|
+
_setPeptideColumn(macroMolecule);
|
|
182
|
+
await grok.data.detectSemanticTypes(df);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
//name: createMonomerLibraryForPolyTool
|
|
186
|
+
//input: file file
|
|
187
|
+
export async function createMonomerLibraryForPolyTool(file: DG.FileInfo) {
|
|
188
|
+
const fileContent = await file.readAsString();
|
|
189
|
+
const libHandler = new PolyToolCsvLibHandler(file.fileName, fileContent);
|
|
190
|
+
const libObject = await libHandler.getJson();
|
|
191
|
+
const jsonFileName = file.fileName.replace(/\.csv$/, '.json');
|
|
192
|
+
const jsonFileContent = JSON.stringify(libObject, null, 2);
|
|
193
|
+
DG.Utils.download(jsonFileName, jsonFileContent);
|
|
194
|
+
}
|
package/src/plugins/mermade.ts
CHANGED
|
@@ -3,19 +3,19 @@ import * as grok from 'datagrok-api/grok';
|
|
|
3
3
|
import * as ui from 'datagrok-api/ui';
|
|
4
4
|
import * as DG from 'datagrok-api/dg';
|
|
5
5
|
|
|
6
|
-
import {ExternalPluginUI} from '../view/
|
|
7
|
-
import {ColoredTextInput} from '../view/
|
|
8
|
-
import {highlightInvalidSubsequence} from '../view/
|
|
9
|
-
import {
|
|
6
|
+
import {ExternalPluginUI} from '../apps/common/view/utils';
|
|
7
|
+
import {ColoredTextInput} from '../apps/common/view/components/colored-input/colored-text-input';
|
|
8
|
+
import {highlightInvalidSubsequence} from '../apps/common/view/components/colored-input/input-painters';
|
|
9
|
+
import {CODES_TO_SYMBOLS_DICT} from '../apps/common/model/data-loader/json-loader';
|
|
10
10
|
import {MERMADE} from './const';
|
|
11
11
|
|
|
12
12
|
export async function getExternalAppViewFactories(): Promise<{[name: string]: () => DG.View} | undefined> {
|
|
13
13
|
const externalPluginData = {
|
|
14
|
-
|
|
14
|
+
[MERMADE.FUNCTION_NAME]: {
|
|
15
15
|
tabName: MERMADE.TAB_NAME,
|
|
16
16
|
parameters: getMerMadeParameters()
|
|
17
17
|
},
|
|
18
|
-
}
|
|
18
|
+
};
|
|
19
19
|
|
|
20
20
|
const result: {[tabName: string]: () => DG.View} = {};
|
|
21
21
|
|
|
@@ -30,7 +30,7 @@ export async function getExternalAppViewFactories(): Promise<{[name: string]: ()
|
|
|
30
30
|
|
|
31
31
|
result[data.tabName] = () => pluginUI.getView();
|
|
32
32
|
} catch (err) {
|
|
33
|
-
console.warn(`Plugin ${pluginName} not loaded, reason:`, err)
|
|
33
|
+
console.warn(`Plugin ${pluginName} not loaded, reason:`, err);
|
|
34
34
|
continue;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -43,6 +43,6 @@ function getMerMadeParameters(): {[name: string]: any} {
|
|
|
43
43
|
|
|
44
44
|
return {
|
|
45
45
|
coloredInput: input,
|
|
46
|
-
codes:
|
|
47
|
-
}
|
|
46
|
+
codes: CODES_TO_SYMBOLS_DICT
|
|
47
|
+
};
|
|
48
48
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {HELM_REQUIRED_FIELD} from '@datagrok-libraries/bio/src/utils/const';
|
|
2
|
+
|
|
3
|
+
export const helmFieldsToPolyToolInputFields = {
|
|
4
|
+
[HELM_REQUIRED_FIELD.SYMBOL]: 'Short Name',
|
|
5
|
+
[HELM_REQUIRED_FIELD.NAME]: 'Medium Name',
|
|
6
|
+
[HELM_REQUIRED_FIELD.SMILES]: 'SMILES',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const R_GROUP_BLOCK_DUMMY = [
|
|
10
|
+
{
|
|
11
|
+
'capGroupSmiles': '[*:1][H]',
|
|
12
|
+
'alternateId': 'R1-H',
|
|
13
|
+
'capGroupName': 'H',
|
|
14
|
+
'label': 'R1'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
'capGroupSmiles': 'O[*:2]',
|
|
18
|
+
'alternateId': 'R2-OH',
|
|
19
|
+
'capGroupName': 'OH',
|
|
20
|
+
'label': 'R2'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
'capGroupSmiles': '[*:3][H]',
|
|
24
|
+
'alternateId': 'R3-H',
|
|
25
|
+
'capGroupName': 'H',
|
|
26
|
+
'label': 'R3'
|
|
27
|
+
}
|
|
28
|
+
];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as DG from 'datagrok-api/dg';
|
|
2
|
+
|
|
3
|
+
import {PolyToolMonomerLibHandler} from './monomer-lib-handler';
|
|
4
|
+
|
|
5
|
+
/** Handler of custom monomer libs for PolyTool */
|
|
6
|
+
export class PolyToolCsvLibHandler {
|
|
7
|
+
constructor(private fileName: string, private fileContent: string) {
|
|
8
|
+
this.validateFileType();
|
|
9
|
+
const df = DG.DataFrame.fromCsv(this.fileContent);
|
|
10
|
+
const json = this.toJson(df);
|
|
11
|
+
this.polyToolMonomerLib = new PolyToolMonomerLibHandler(json);
|
|
12
|
+
this.validateContent();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private polyToolMonomerLib: PolyToolMonomerLibHandler;
|
|
16
|
+
|
|
17
|
+
async getJson(): Promise<any> {
|
|
18
|
+
const rawLibData = this.polyToolMonomerLib.getJsonMonomerLib();
|
|
19
|
+
return rawLibData;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private toJson(df: DG.DataFrame): any[] {
|
|
23
|
+
return Array.from({length: df.rowCount}, (_, idx) =>
|
|
24
|
+
df.columns.names().reduce((entry: { [key: string]: any }, colName) => {
|
|
25
|
+
entry[colName] = df.get(colName, idx);
|
|
26
|
+
return entry;
|
|
27
|
+
}, {})
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private validateFileType(): void {
|
|
32
|
+
if (!this.fileName.endsWith('.csv'))
|
|
33
|
+
throw new Error(`File ${this.fileName} is not an CSV file`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private validateContent(): void {
|
|
37
|
+
if (!this.polyToolMonomerLib.isValid())
|
|
38
|
+
throw new Error('Invalid format of CSV monomer lib');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {GAP_SYMBOL, INotationProvider, ISeqSplitted, SeqSplittedBase, SplitterFunc}
|
|
2
|
+
from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
3
|
+
import {getSplitterWithSeparator, StringListSeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
|
|
4
|
+
import {GapOriginals} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
5
|
+
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
6
|
+
|
|
7
|
+
export class CyclizedNotationProvider implements INotationProvider {
|
|
8
|
+
private readonly separatorSplitter: SplitterFunc;
|
|
9
|
+
public readonly splitter: SplitterFunc;
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
public readonly separator: string
|
|
13
|
+
) {
|
|
14
|
+
this.separatorSplitter = getSplitterWithSeparator(this.separator);
|
|
15
|
+
this.splitter = this._splitter.bind(this);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private _splitter(seq: string): ISeqSplitted {
|
|
19
|
+
const baseSS: ISeqSplitted = this.separatorSplitter(seq);
|
|
20
|
+
return new CyclizedSeqSplitted(baseSS.originals, GapOriginals[NOTATION.SEPARATOR]);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Gets canonical monomers for original ones with cyclization marks */
|
|
25
|
+
export class CyclizedSeqSplitted extends StringListSeqSplitted {
|
|
26
|
+
private readonly seqCList: (string | null)[];
|
|
27
|
+
|
|
28
|
+
private _canonicals: string[] | null = null;
|
|
29
|
+
override get canonicals(): SeqSplittedBase {
|
|
30
|
+
if (!this._canonicals) {
|
|
31
|
+
const len = this.length;
|
|
32
|
+
this._canonicals = new Array<string>(len);
|
|
33
|
+
for (let posIdx = 0; posIdx < len; ++posIdx)
|
|
34
|
+
this._canonicals[posIdx] = this.getCanonical(posIdx);
|
|
35
|
+
}
|
|
36
|
+
return this._canonicals;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override getCanonical(posIdx: number): string {
|
|
40
|
+
if (this.isGap(posIdx)) return GAP_SYMBOL;
|
|
41
|
+
|
|
42
|
+
let cmRes: string | null = this.seqCList[posIdx];
|
|
43
|
+
if (cmRes === null) {
|
|
44
|
+
const om = this.getOriginal(posIdx);
|
|
45
|
+
cmRes = om;
|
|
46
|
+
if (om[om.length - 1] === ')')
|
|
47
|
+
cmRes = this.seqCList[posIdx] = om.replace(/\(\d+\)$/, '');
|
|
48
|
+
}
|
|
49
|
+
return cmRes;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
constructor(seqOList: SeqSplittedBase, gapOriginalMonomer: string) {
|
|
53
|
+
super(seqOList, gapOriginalMonomer);
|
|
54
|
+
this.seqCList = new Array<string | null>(this.length).fill(null);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
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 {HELM_FIELDS, DUMMY_MONOMER} from '@datagrok-libraries/bio/src/utils/const';
|
|
7
|
+
import {
|
|
8
|
+
helmFieldsToPolyToolInputFields, R_GROUP_BLOCK_DUMMY
|
|
9
|
+
} from './const';
|
|
10
|
+
import {Monomer, RGroup} from '@datagrok-libraries/bio/src/types/index';
|
|
11
|
+
|
|
12
|
+
export class PolyToolMonomerLibHandler {
|
|
13
|
+
constructor(private rawLib: any[]) { }
|
|
14
|
+
|
|
15
|
+
isValid(): boolean {
|
|
16
|
+
return this.rawLib.every((entry) => {
|
|
17
|
+
return typeof entry === 'object' &&
|
|
18
|
+
Object.values(helmFieldsToPolyToolInputFields).every((field) => {
|
|
19
|
+
return field in entry &&
|
|
20
|
+
typeof entry[field] === 'string';
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getJsonMonomerLib(): any {
|
|
26
|
+
const resultLib: any[] = [];
|
|
27
|
+
this.rawLib.forEach((rawMonomer) => {
|
|
28
|
+
const monomer = this.prepareMonomer(rawMonomer);
|
|
29
|
+
resultLib.push(monomer);
|
|
30
|
+
});
|
|
31
|
+
return resultLib;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private prepareMonomer(rawMonomer: any): Monomer {
|
|
35
|
+
const monomer: Monomer = {...DUMMY_MONOMER};
|
|
36
|
+
|
|
37
|
+
Object.entries(helmFieldsToPolyToolInputFields).forEach(([key, value]) => {
|
|
38
|
+
const monomerSymbol = rawMonomer[value] as string;
|
|
39
|
+
//@ts-ignore
|
|
40
|
+
monomer[key] = monomerSymbol;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
let key = HELM_FIELDS.SMILES;
|
|
44
|
+
const rawSmiles = rawMonomer[helmFieldsToPolyToolInputFields[key]];
|
|
45
|
+
const smilesHandler = new SmilesHandler(rawSmiles);
|
|
46
|
+
const smiles = smilesHandler.getCappedSmiles();
|
|
47
|
+
monomer[key] = smiles;
|
|
48
|
+
|
|
49
|
+
key = HELM_FIELDS.RGROUPS;
|
|
50
|
+
monomer[key] = RGroupHandler.getRGroups(smilesHandler.getNumberOfRGroups());
|
|
51
|
+
|
|
52
|
+
key = HELM_FIELDS.MOLFILE;
|
|
53
|
+
monomer[key] = new MolBlockHandler(smilesHandler.getSmilesWithRGroups()).getMolfile();
|
|
54
|
+
|
|
55
|
+
return monomer;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
class SmilesHandler {
|
|
60
|
+
constructor(rawSmiles: string) {
|
|
61
|
+
const regex = /\[R(\d+)\]/g;
|
|
62
|
+
let i = 0;
|
|
63
|
+
this.smilesWithRGroups = rawSmiles.replace(regex, (_, capturedDigit) => { ++i; return `[${capturedDigit}*]`; });
|
|
64
|
+
this.numberOfRGroups = i;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private numberOfRGroups: number;
|
|
68
|
+
private smilesWithRGroups: string;
|
|
69
|
+
|
|
70
|
+
getSmilesWithRGroups(): string {
|
|
71
|
+
return this.smilesWithRGroups;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
getCappedSmiles(): string {
|
|
75
|
+
const smiles = this.capRGroups();
|
|
76
|
+
return smiles;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
getNumberOfRGroups(): number {
|
|
80
|
+
return this.numberOfRGroups;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private capRGroups(): string {
|
|
84
|
+
let result = this.smilesWithRGroups.replace('[1*]', '[H:1]');
|
|
85
|
+
result = result.replace('[2*]', '[OH:2]');
|
|
86
|
+
return result.replace('[3*]', '[H:3]');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
class RGroupHandler {
|
|
91
|
+
private constructor() {};
|
|
92
|
+
|
|
93
|
+
static getRGroups(numberOfRGroups: number): RGroup[] {
|
|
94
|
+
return R_GROUP_BLOCK_DUMMY.slice(0, numberOfRGroups);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
class MolBlockHandler {
|
|
99
|
+
constructor(private smilesWithRGroups: string) { }
|
|
100
|
+
|
|
101
|
+
getMolfile(): string {
|
|
102
|
+
let molfile = DG.chem.convert(this.smilesWithRGroups, DG.chem.Notation.Smiles, DG.chem.Notation.MolBlock);
|
|
103
|
+
molfile = this.restoreRGPLine(molfile);
|
|
104
|
+
molfile = this.fixRGroupSymbols(molfile);
|
|
105
|
+
return molfile;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private restoreRGPLine(rawMolfile: string): string {
|
|
109
|
+
return rawMolfile.replace('M ISO', 'M RGP');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private fixRGroupSymbols(molfile: string): string {
|
|
113
|
+
return molfile.replace(/\bR\b/g, 'R#');
|
|
114
|
+
}
|
|
115
|
+
}
|