@datagrok/bio 2.12.16 → 2.12.17
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/dist/package-test.js +2 -2
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +3 -3
- package/dist/package.js.map +1 -1
- package/package.json +6 -6
- package/src/package.ts +15 -37
- package/src/tests/renderers-monomer-placer-tests.ts +1 -1
- package/src/utils/cell-renderer.ts +10 -28
- package/src/utils/{poly-tool/cyclized.ts → cyclized.ts} +3 -7
- package/src/utils/monomer-lib/monomer-lib.ts +14 -2
- package/src/widgets/bio-substructure-filter-helm.ts +5 -4
- package/src/widgets/bio-substructure-filter.ts +0 -1
- package/webpack.config.js +2 -0
- package/src/utils/poly-tool/const.ts +0 -40
- package/src/utils/poly-tool/csv-to-json-monomer-lib-converter.ts +0 -40
- package/src/utils/poly-tool/monomer-lib-handler.ts +0 -115
- package/src/utils/poly-tool/transformation.ts +0 -320
- package/src/utils/poly-tool/ui.ts +0 -59
- package/src/utils/poly-tool/utils.ts +0 -20
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "Aleksandr Tanas",
|
|
6
6
|
"email": "atanas@datagrok.ai"
|
|
7
7
|
},
|
|
8
|
-
"version": "2.12.
|
|
8
|
+
"version": "2.12.17",
|
|
9
9
|
"description": "Bioinformatics support (import/export of sequences, conversion, visualization, analysis). [See more](https://github.com/datagrok-ai/public/blob/master/packages/Bio/README.md) for details.",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@biowasm/aioli": "^3.1.0",
|
|
37
|
-
"@datagrok-libraries/bio": "^5.
|
|
37
|
+
"@datagrok-libraries/bio": "^5.41.0",
|
|
38
38
|
"@datagrok-libraries/chem-meta": "^1.2.5",
|
|
39
39
|
"@datagrok-libraries/math": "^1.1.5",
|
|
40
40
|
"@datagrok-libraries/ml": "^6.6.5",
|
|
41
41
|
"@datagrok-libraries/tutorials": "^1.3.12",
|
|
42
|
-
"@datagrok-libraries/utils": "^4.2.
|
|
42
|
+
"@datagrok-libraries/utils": "^4.2.2",
|
|
43
43
|
"@webgpu/types": "^0.1.40",
|
|
44
44
|
"ajv": "^8.12.0",
|
|
45
45
|
"ajv-errors": "^3.0.0",
|
|
@@ -55,9 +55,9 @@
|
|
|
55
55
|
"wu": "latest"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@datagrok/chem": "^1.9.
|
|
59
|
-
"@datagrok/dendrogram": "^1.2.
|
|
60
|
-
"@datagrok/helm": "^2.1.
|
|
58
|
+
"@datagrok/chem": "^1.9.2",
|
|
59
|
+
"@datagrok/dendrogram": "^1.2.29",
|
|
60
|
+
"@datagrok/helm": "^2.1.34",
|
|
61
61
|
"@types/node": "^17.0.24",
|
|
62
62
|
"@types/wu": "latest",
|
|
63
63
|
"@typescript-eslint/eslint-plugin": "latest",
|
package/src/package.ts
CHANGED
|
@@ -3,6 +3,8 @@ 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 '@datagrok-libraries/bio/src/types/helm';
|
|
7
|
+
|
|
6
8
|
import {Options} from '@datagrok-libraries/utils/src/type-declarations';
|
|
7
9
|
import {DimReductionBaseEditor, PreprocessFunctionReturnType}
|
|
8
10
|
from '@datagrok-libraries/ml/src/functionEditors/dimensionality-reduction-editor';
|
|
@@ -55,13 +57,9 @@ import {SplitToMonomersFunctionEditor} from './function-edtiors/split-to-monomer
|
|
|
55
57
|
import {splitToMonomersUI} from './utils/split-to-monomers';
|
|
56
58
|
import {MonomerCellRenderer} from './utils/monomer-cell-renderer';
|
|
57
59
|
import {BioPackage, BioPackageProperties} from './package-types';
|
|
58
|
-
// import {PackageSettingsEditorWidget} from './widgets/package-settings-editor-widget';
|
|
59
60
|
import {getCompositionAnalysisWidget} from './widgets/composition-analysis-widget';
|
|
60
61
|
import {MacromoleculeColumnWidget} from './utils/macromolecule-column-widget';
|
|
61
62
|
import {addCopyMenuUI} from './utils/context-menu';
|
|
62
|
-
import {getPolyToolDialog} from './utils/poly-tool/ui';
|
|
63
|
-
import {PolyToolCsvLibHandler} from './utils/poly-tool/csv-to-json-monomer-lib-converter';
|
|
64
|
-
import {_setPeptideColumn} from './utils/poly-tool/utils';
|
|
65
63
|
import {getRegionDo} from './utils/get-region';
|
|
66
64
|
import {GetRegionApp} from './apps/get-region-app';
|
|
67
65
|
import {GetRegionFuncEditor} from './utils/get-region-func-editor';
|
|
@@ -77,7 +75,8 @@ import {DimReductionMethods} from '@datagrok-libraries/ml/src/multi-column-dimen
|
|
|
77
75
|
import {
|
|
78
76
|
ITSNEOptions, IUMAPOptions
|
|
79
77
|
} from '@datagrok-libraries/ml/src/multi-column-dimensionality-reduction/multi-column-dim-reducer';
|
|
80
|
-
import {CyclizedNotationProvider} from './utils/
|
|
78
|
+
import {CyclizedNotationProvider} from './utils/cyclized';
|
|
79
|
+
import {getMolColumnFromHelm} from './utils/helm-to-molfile/utils';
|
|
81
80
|
|
|
82
81
|
export const _package = new BioPackage();
|
|
83
82
|
|
|
@@ -685,19 +684,6 @@ export function convertDialog() {
|
|
|
685
684
|
convert(col);
|
|
686
685
|
}
|
|
687
686
|
|
|
688
|
-
//top-menu: Bio | Convert | PolyTool
|
|
689
|
-
//name: polyTool
|
|
690
|
-
//description: Perform cyclization of polymers
|
|
691
|
-
export async function polyTool(): Promise<void> {
|
|
692
|
-
let dialog: DG.Dialog;
|
|
693
|
-
try {
|
|
694
|
-
dialog = await getPolyToolDialog();
|
|
695
|
-
dialog.show();
|
|
696
|
-
} catch (err: any) {
|
|
697
|
-
grok.shell.warning('To run PolyTool, open a dataframe with macromolecules');
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
|
|
701
687
|
//name: monomerCellRenderer
|
|
702
688
|
//tags: cellRenderer
|
|
703
689
|
//meta.cellType: Monomer
|
|
@@ -1010,25 +996,6 @@ export async function demoBioHelmMsaSequenceSpace(): Promise<void> {
|
|
|
1010
996
|
await demoBio05UI();
|
|
1011
997
|
}
|
|
1012
998
|
|
|
1013
|
-
//name: polyToolColumnChoice
|
|
1014
|
-
//input: dataframe df [Input data table]
|
|
1015
|
-
//input: column macroMolecule
|
|
1016
|
-
export async function polyToolColumnChoice(df: DG.DataFrame, macroMolecule: DG.Column): Promise<void> {
|
|
1017
|
-
_setPeptideColumn(macroMolecule);
|
|
1018
|
-
await grok.data.detectSemanticTypes(df);
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
//name: createMonomerLibraryForPolyTool
|
|
1022
|
-
//input: file file
|
|
1023
|
-
export async function createMonomerLibraryForPolyTool(file: DG.FileInfo) {
|
|
1024
|
-
const fileContent = await file.readAsString();
|
|
1025
|
-
const libHandler = new PolyToolCsvLibHandler(file.fileName, fileContent);
|
|
1026
|
-
const libObject = await libHandler.getJson();
|
|
1027
|
-
const jsonFileName = file.fileName.replace(/\.csv$/, '.json');
|
|
1028
|
-
const jsonFileContent = JSON.stringify(libObject, null, 2);
|
|
1029
|
-
DG.Utils.download(jsonFileName, jsonFileContent);
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
999
|
//name: SDF to JSON Library
|
|
1033
1000
|
//input: dataframe table
|
|
1034
1001
|
export async function sdfToJsonLib(table: DG.DataFrame) {
|
|
@@ -1048,6 +1015,17 @@ export async function detectMacromoleculeProbe(file: DG.FileInfo, colName: strin
|
|
|
1048
1015
|
await detectMacromoleculeProbeDo(csv, colName, probeCount);
|
|
1049
1016
|
}
|
|
1050
1017
|
|
|
1018
|
+
//name: getMolFromHelm
|
|
1019
|
+
//input: dataframe df
|
|
1020
|
+
//input: column helmCol
|
|
1021
|
+
//input: bool chiralityEngine
|
|
1022
|
+
//output: column result
|
|
1023
|
+
export async function getMolFromHelm(
|
|
1024
|
+
df: DG.DataFrame, helmCol: DG.Column<string>, chiralityEngine?: boolean
|
|
1025
|
+
): Promise<DG.Column<string>> {
|
|
1026
|
+
return getMolColumnFromHelm(df, helmCol, chiralityEngine);
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1051
1029
|
// -- Custom notation providers --
|
|
1052
1030
|
|
|
1053
1031
|
//name: applyNotationProviderForCyclized
|
|
@@ -95,7 +95,7 @@ id3,QHIRE--LT
|
|
|
95
95
|
const monLength: number = 3;
|
|
96
96
|
const charWidth: number = 7;
|
|
97
97
|
const sepWidth: number = 12;
|
|
98
|
-
const colTemp: MonomerPlacer = new MonomerPlacer(null, seqCol, () => {
|
|
98
|
+
const colTemp: MonomerPlacer = new MonomerPlacer(null, seqCol, _package.logger, () => {
|
|
99
99
|
const sh = SeqHandler.forColumn(seqCol);
|
|
100
100
|
return {
|
|
101
101
|
seqHandler: sh,
|
|
@@ -23,6 +23,7 @@ import {ISeqSplitted, SeqSplittedBase} from '@datagrok-libraries/bio/src/utils/m
|
|
|
23
23
|
import {getSplitter} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
|
|
24
24
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
25
25
|
import {alphabetPolymerTypes, IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
|
|
26
|
+
import {getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
26
27
|
|
|
27
28
|
import {
|
|
28
29
|
Temps as mmcrTemps, Tags as mmcrTags,
|
|
@@ -63,27 +64,6 @@ type RendererGridCellTemp = {
|
|
|
63
64
|
[mmcrTemps.monomerPlacer]: MonomerPlacer
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
function getRendererFridCellTempTemp(gridCell: DG.GridCell): RendererGridCellTemp {
|
|
67
|
-
/** Primarily store/get MonomerPlacer at GridColumn, fallback at (Table) Column for scatter plot tooltip */
|
|
68
|
-
let temp: RendererGridCellTemp | null = null;
|
|
69
|
-
|
|
70
|
-
let gridCol: DG.GridColumn | null = null;
|
|
71
|
-
try { gridCol = gridCell.gridColumn; } catch { gridCol = null; }
|
|
72
|
-
temp = gridCol && gridCol.dart ? gridCol.temp as RendererGridCellTemp : null;
|
|
73
|
-
|
|
74
|
-
if (!temp) {
|
|
75
|
-
let tableCol: DG.Column | null = null;
|
|
76
|
-
try { tableCol = gridCell.cell.column; } catch { tableCol = null; }
|
|
77
|
-
if (!tableCol) {
|
|
78
|
-
const k = 42;
|
|
79
|
-
}
|
|
80
|
-
temp = tableCol ? tableCol.temp as RendererGridCellTemp : null;
|
|
81
|
-
}
|
|
82
|
-
if (temp === null)
|
|
83
|
-
throw new Error(`Monomer placer store (GridColumn or Column) not found.`);
|
|
84
|
-
return temp;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
67
|
export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
88
68
|
private padding: number = 5;
|
|
89
69
|
|
|
@@ -105,9 +85,9 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
105
85
|
// if (gridCell.cell.column.getTag(bioTAGS.aligned) !== ALIGNMENT.SEQ_MSA)
|
|
106
86
|
// return;
|
|
107
87
|
|
|
108
|
-
const tableCol
|
|
109
|
-
|
|
110
|
-
const seqColTemp: MonomerPlacer =
|
|
88
|
+
const [_gridCol, tableCol, temp] =
|
|
89
|
+
getGridCellRendererBack<string, MonomerPlacer>(gridCell);
|
|
90
|
+
const seqColTemp: MonomerPlacer = temp['rendererBack'];
|
|
111
91
|
if (!seqColTemp) return; // Can do nothing without precalculated data
|
|
112
92
|
|
|
113
93
|
const gridCellBounds: DG.Rect = gridCell.bounds;
|
|
@@ -121,7 +101,7 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
121
101
|
const argsX = e.offsetX - gridCell.gridColumn.left + (gridCell.gridColumn.left - gridCellBounds.x);
|
|
122
102
|
const left: number | null = seqColTemp.getPosition(gridCell.tableRowIndex!, argsX);
|
|
123
103
|
|
|
124
|
-
const seqCList: SeqSplittedBase = SeqHandler.forColumn(
|
|
104
|
+
const seqCList: SeqSplittedBase = SeqHandler.forColumn(tableCol)
|
|
125
105
|
.getSplitted(gridCell.tableRowIndex!).canonicals;
|
|
126
106
|
if (left !== null && left < seqCList.length) {
|
|
127
107
|
const monomerSymbol: string = seqCList[left];
|
|
@@ -190,9 +170,11 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
190
170
|
(!isNaN(tagMaxMonomerLength) ? tagMaxMonomerLength : _package.properties?.MaxMonomerLength) ?? 4;
|
|
191
171
|
}
|
|
192
172
|
|
|
193
|
-
|
|
173
|
+
const [gridCol, _tc, temp] =
|
|
174
|
+
getGridCellRendererBack<string, MonomerPlacer>(gridCell);
|
|
175
|
+
let seqColTemp: MonomerPlacer = temp['rendererBack'];
|
|
194
176
|
if (!seqColTemp) {
|
|
195
|
-
seqColTemp = new MonomerPlacer(
|
|
177
|
+
seqColTemp = new MonomerPlacer(gridCol, tableCol, _package.logger,
|
|
196
178
|
() => {
|
|
197
179
|
const sh = SeqHandler.forColumn(tableCol);
|
|
198
180
|
return {
|
|
@@ -217,7 +199,7 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
217
199
|
const _maxIndex = maxLengthWords.length;
|
|
218
200
|
|
|
219
201
|
// Store updated seqColTemp to the col temp
|
|
220
|
-
if (seqColTemp.updated)
|
|
202
|
+
if (seqColTemp.updated) temp['rendererBack'] = seqColTemp;
|
|
221
203
|
|
|
222
204
|
g.save();
|
|
223
205
|
try {
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import * as DG from 'datagrok-api/dg';
|
|
4
|
-
|
|
5
|
-
import {GAP_SYMBOL, INotationProvider, ISeqSplitted, SeqSplittedBase, SplitterFunc} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
1
|
+
import {GAP_SYMBOL, INotationProvider, ISeqSplitted, SeqSplittedBase, SplitterFunc}
|
|
2
|
+
from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
6
3
|
import {getSplitterWithSeparator, StringListSeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
|
|
7
4
|
import {GapOriginals} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
8
5
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
@@ -33,9 +30,8 @@ export class CyclizedSeqSplitted extends StringListSeqSplitted {
|
|
|
33
30
|
if (!this._canonicals) {
|
|
34
31
|
const len = this.length;
|
|
35
32
|
this._canonicals = new Array<string>(len);
|
|
36
|
-
for (let posIdx = 0; posIdx < len; ++posIdx)
|
|
33
|
+
for (let posIdx = 0; posIdx < len; ++posIdx)
|
|
37
34
|
this._canonicals[posIdx] = this.getCanonical(posIdx);
|
|
38
|
-
}
|
|
39
35
|
}
|
|
40
36
|
return this._canonicals;
|
|
41
37
|
}
|
|
@@ -116,6 +116,14 @@ export class MonomerLib implements IMonomerLib {
|
|
|
116
116
|
this._onChanged.next();
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
getSummary(): string {
|
|
120
|
+
const monTypeList: string[] = this.getPolymerTypes();
|
|
121
|
+
const resStr: string = monTypeList.length == 0 ? 'empty' : monTypeList.map((monType) => {
|
|
122
|
+
return `${monType} ${this.getMonomerSymbolsByType(monType).length}`;
|
|
123
|
+
}).join('\n');
|
|
124
|
+
return resStr;
|
|
125
|
+
}
|
|
126
|
+
|
|
119
127
|
getTooltip(polymerType: string, monomerSymbol: string): HTMLElement {
|
|
120
128
|
// getTooltip(monomer: Monomer): HTMLElement;
|
|
121
129
|
// getTooltip(monomerOrPolymerType: string | Monomer, symbol?: string): HTMLElement {
|
|
@@ -163,8 +171,12 @@ export class MonomerLib implements IMonomerLib {
|
|
|
163
171
|
label('Source'),
|
|
164
172
|
ui.divText(monomer.lib?.source ?? 'unknown', {classes: 'ui-input-text'}),
|
|
165
173
|
], {classes: 'ui-input-root'}));
|
|
166
|
-
} else
|
|
167
|
-
res.append(ui.
|
|
174
|
+
} else {
|
|
175
|
+
res.append(ui.divV([
|
|
176
|
+
ui.divText(`Monomer '${monomerSymbol}' of type '${polymerType}' not found.`),
|
|
177
|
+
ui.divText('Open the Context Panel, then expand Manage Libraries'),
|
|
178
|
+
]));
|
|
179
|
+
}
|
|
168
180
|
return res;
|
|
169
181
|
}
|
|
170
182
|
}
|
|
@@ -2,14 +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 * as org from 'org';
|
|
5
6
|
import $ from 'cash-dom';
|
|
6
|
-
import {fromEvent,
|
|
7
|
+
import {fromEvent, Unsubscribable} from 'rxjs';
|
|
7
8
|
|
|
8
|
-
import {IHelmWebEditor
|
|
9
|
+
import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
|
|
9
10
|
import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
10
11
|
import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
|
|
11
12
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
12
|
-
import {delay
|
|
13
|
+
import {delay} from '@datagrok-libraries/utils/src/test';
|
|
13
14
|
|
|
14
15
|
import {updateDivInnerHTML} from '../utils/ui-utils';
|
|
15
16
|
import {helmSubstructureSearch} from '../substructure-search/substructure-search';
|
|
@@ -54,7 +55,7 @@ export class HelmBioFilter extends BioFilterBase<BioFilterProps> /* implements I
|
|
|
54
55
|
this.logger.warning('TEST: HelmBioFilter.init().sync() waitForElementInDom ready');
|
|
55
56
|
this.updateFilterPanel();
|
|
56
57
|
let webEditorHost: HTMLDivElement | null;
|
|
57
|
-
let webEditorApp: IWebEditorApp | null;
|
|
58
|
+
let webEditorApp: org.helm.IWebEditorApp | null;
|
|
58
59
|
// TODO: Unsubscribe 'click' and 'sizeChanged'
|
|
59
60
|
this.viewSubs.push(fromEvent(this._filterPanel, 'click').subscribe(() => {
|
|
60
61
|
webEditorHost = ui.div();
|
|
@@ -16,7 +16,6 @@ import {TAGS as bioTAGS, NOTATION} from '@datagrok-libraries/bio/src/utils/macro
|
|
|
16
16
|
import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
|
|
17
17
|
import {delay, testEvent} from '@datagrok-libraries/utils/src/test';
|
|
18
18
|
import {getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
19
|
-
import {IHelmWebEditor, IWebEditorApp} from '@datagrok-libraries/bio/src/helm/types';
|
|
20
19
|
import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
|
|
21
20
|
import {IRenderer} from '@datagrok-libraries/bio/src/types/renderer';
|
|
22
21
|
import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
|
package/webpack.config.js
CHANGED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import {HELM_REQUIRED_FIELD} from '@datagrok-libraries/bio/src/utils/const';
|
|
2
|
-
|
|
3
|
-
export const ALL_MONOMERS = '<All>';
|
|
4
|
-
|
|
5
|
-
export const enum TRANSFORMATION_TYPE {
|
|
6
|
-
CYCLIZATION = 'Cyclization',
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const enum CYCLIZATION_TYPE {
|
|
10
|
-
NO = 'N-O',
|
|
11
|
-
NCys = 'N-Cys',
|
|
12
|
-
R3 = 'R3-R3',
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const helmFieldsToPolyToolInputFields = {
|
|
16
|
-
[HELM_REQUIRED_FIELD.SYMBOL]: 'Short Name',
|
|
17
|
-
[HELM_REQUIRED_FIELD.NAME]: 'Medium Name',
|
|
18
|
-
[HELM_REQUIRED_FIELD.SMILES]: 'SMILES',
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const R_GROUP_BLOCK_DUMMY = [
|
|
22
|
-
{
|
|
23
|
-
'capGroupSMILES': '[*:1][H]',
|
|
24
|
-
'alternateId': 'R1-H',
|
|
25
|
-
'capGroupName': 'H',
|
|
26
|
-
'label': 'R1'
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
'capGroupSMILES': 'O[*:2]',
|
|
30
|
-
'alternateId': 'R2-OH',
|
|
31
|
-
'capGroupName': 'OH',
|
|
32
|
-
'label': 'R2'
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
'capGroupSMILES': '[*:3][H]',
|
|
36
|
-
'alternateId': 'R3-H',
|
|
37
|
-
'capGroupName': 'H',
|
|
38
|
-
'label': 'R3'
|
|
39
|
-
}
|
|
40
|
-
];
|
|
@@ -1,40 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
/* Do not change these import lines to match external modules in webpack configuration */
|
|
2
|
-
import * as grok from 'datagrok-api/grok';
|
|
3
|
-
import * as ui from 'datagrok-api/ui';
|
|
4
|
-
import * as DG from 'datagrok-api/dg';
|
|
5
|
-
|
|
6
|
-
import {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
|
-
}
|