@datagrok/bio 2.10.28 → 2.11.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/CHANGELOG.md +4 -2
- 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/package.json +2 -2
- package/src/apps/web-logo-app.ts +7 -3
- package/src/package.ts +29 -10
- package/src/tests/WebLogo-positions-test.ts +3 -3
- package/src/utils/agg.ts +29 -0
- package/src/utils/poly-tool/const.ts +16 -0
- package/src/utils/{enumerator-tools.ts → poly-tool/enumerator-tools.ts} +36 -54
- package/src/utils/poly-tool/types.ts +14 -0
- package/src/utils/poly-tool/utils.ts +20 -0
- package/src/viewers/web-logo-viewer.ts +235 -119
- package/src/widgets/composition-analysis-widget.ts +35 -23
- package/webpack.config.js +1 -1
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "Leonid Stolbov",
|
|
6
6
|
"email": "lstolbov@datagrok.ai"
|
|
7
7
|
},
|
|
8
|
-
"version": "2.
|
|
8
|
+
"version": "2.11.0",
|
|
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,7 +34,7 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@biowasm/aioli": "^3.1.0",
|
|
37
|
-
"@datagrok-libraries/bio": "^5.
|
|
37
|
+
"@datagrok-libraries/bio": "^5.39.0",
|
|
38
38
|
"@datagrok-libraries/chem-meta": "^1.0.1",
|
|
39
39
|
"@datagrok-libraries/ml": "^6.3.50",
|
|
40
40
|
"@datagrok-libraries/tutorials": "^1.3.6",
|
package/src/apps/web-logo-app.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
4
4
|
|
|
5
5
|
import wu from 'wu';
|
|
6
6
|
|
|
7
|
-
import {IWebLogoViewer} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
7
|
+
import {IWebLogoViewer, WebLogoProps} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
8
8
|
|
|
9
9
|
import {PROPS as wlPROPS} from '../viewers/web-logo-viewer';
|
|
10
10
|
|
|
@@ -14,7 +14,11 @@ export class WebLogoApp {
|
|
|
14
14
|
df: DG.DataFrame;
|
|
15
15
|
view: DG.TableView;
|
|
16
16
|
|
|
17
|
-
constructor(
|
|
17
|
+
constructor(
|
|
18
|
+
private readonly urlParams: URLSearchParams,
|
|
19
|
+
private readonly funcName: string,
|
|
20
|
+
private readonly options: Partial<WebLogoProps> = {}
|
|
21
|
+
) {}
|
|
18
22
|
|
|
19
23
|
async init(df: DG.DataFrame): Promise<void> {
|
|
20
24
|
this.df = df;
|
|
@@ -32,7 +36,7 @@ export class WebLogoApp {
|
|
|
32
36
|
this.view = grok.shell.addTableView(this.df);
|
|
33
37
|
this.view.path = this.view.basePath = `func/${_package.name}.${this.funcName}?${urlParamsTxt}`;
|
|
34
38
|
|
|
35
|
-
const options: { [p: string]: any } = {sequenceColumnName: 'sequence'};
|
|
39
|
+
const options: { [p: string]: any } = {...this.options, ...{sequenceColumnName: 'sequence'}};
|
|
36
40
|
for (const [optName, optValue] of this.urlParams.entries()) {
|
|
37
41
|
switch (optName) {
|
|
38
42
|
// boolean
|
package/src/package.ts
CHANGED
|
@@ -65,7 +65,8 @@ import {PackageSettingsEditorWidget} from './widgets/package-settings-editor-wid
|
|
|
65
65
|
import {getCompositionAnalysisWidget} from './widgets/composition-analysis-widget';
|
|
66
66
|
import {MacromoleculeColumnWidget} from './utils/macromolecule-column-widget';
|
|
67
67
|
import {addCopyMenuUI} from './utils/context-menu';
|
|
68
|
-
import {
|
|
68
|
+
import {getPolyToolDialog} from './utils/poly-tool/enumerator-tools';
|
|
69
|
+
import {_setPeptideColumn} from './utils/poly-tool/utils';
|
|
69
70
|
import {getRegionDo} from './utils/get-region';
|
|
70
71
|
import {GetRegionApp} from './apps/get-region-app';
|
|
71
72
|
import {GetRegionFuncEditor} from './utils/get-region-func-editor';
|
|
@@ -763,6 +764,19 @@ export function convertDialog() {
|
|
|
763
764
|
convert(col);
|
|
764
765
|
}
|
|
765
766
|
|
|
767
|
+
//top-menu: Bio | Convert | PolyTool
|
|
768
|
+
//name: polyTool
|
|
769
|
+
//description: Perform cyclization of polymers
|
|
770
|
+
export function polyTool(): void {
|
|
771
|
+
let dialog: DG.Dialog;
|
|
772
|
+
try {
|
|
773
|
+
dialog = getPolyToolDialog();
|
|
774
|
+
dialog.show();
|
|
775
|
+
} catch (err: any) {
|
|
776
|
+
grok.shell.warning('To run PolyTool, open a dataframe with macromolecules');
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
766
780
|
//name: monomerCellRenderer
|
|
767
781
|
//tags: cellRenderer
|
|
768
782
|
//meta.cellType: Monomer
|
|
@@ -962,6 +976,20 @@ export async function webLogoLargeApp(): Promise<void> {
|
|
|
962
976
|
}
|
|
963
977
|
}
|
|
964
978
|
|
|
979
|
+
//name: webLogoAggApp
|
|
980
|
+
export async function webLogoAggApp(): Promise<void> {
|
|
981
|
+
const pi = DG.TaskBarProgressIndicator.create('WebLogo ...');
|
|
982
|
+
try {
|
|
983
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
984
|
+
const app = new WebLogoApp(urlParams, 'webLogoAggApp');
|
|
985
|
+
const df: DG.DataFrame = await _package.files.readCsv('data/sample_FASTA_PT_activity.csv');
|
|
986
|
+
await grok.data.detectSemanticTypes(df);
|
|
987
|
+
await app.init(df);
|
|
988
|
+
} finally {
|
|
989
|
+
pi.close();
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
965
993
|
//name: getRegionApp
|
|
966
994
|
export async function getRegionApp(): Promise<void> {
|
|
967
995
|
const pi = DG.TaskBarProgressIndicator.create('getRegion ...');
|
|
@@ -1056,15 +1084,6 @@ export async function enumeratorColumnChoice(df: DG.DataFrame, macroMolecule: DG
|
|
|
1056
1084
|
await grok.data.detectSemanticTypes(df);
|
|
1057
1085
|
}
|
|
1058
1086
|
|
|
1059
|
-
//name: PolyTool
|
|
1060
|
-
//input: column molColumn {semType: Macromolecule}
|
|
1061
|
-
//tags: panel, exclude-actions-panel
|
|
1062
|
-
//output: widget result
|
|
1063
|
-
export function getEnumeratorWidget(molColumn: DG.Column): DG.Widget {
|
|
1064
|
-
return _getEnumeratorWidget(molColumn);
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
1087
|
//top-menu: Bio | Convert | SDF to JSON Library...
|
|
1069
1088
|
//name: SDF to JSON Library
|
|
1070
1089
|
//input: dataframe table
|
|
@@ -55,7 +55,7 @@ ATC-G-TTGC--
|
|
|
55
55
|
for (let i = 0; i < positions.length; i++) {
|
|
56
56
|
expect(positions[i].name, resAllDf1[i].name);
|
|
57
57
|
for (const m of positions[i].getMonomers())
|
|
58
|
-
expect(positions[i].getFreq(m).
|
|
58
|
+
expect(positions[i].getFreq(m).rowCount, resAllDf1[i].getFreq(m).rowCount);
|
|
59
59
|
}
|
|
60
60
|
});
|
|
61
61
|
|
|
@@ -104,7 +104,7 @@ ATC-G-TTGC--
|
|
|
104
104
|
for (let i = 0; i < positions.length; i++) {
|
|
105
105
|
expect(positions[i].name, resAllDf1[i].name);
|
|
106
106
|
for (const m of positions[i].getMonomers())
|
|
107
|
-
expect(positions[i].getFreq(m).
|
|
107
|
+
expect(positions[i].getFreq(m).rowCount, resAllDf1[i].getFreq(m).rowCount);
|
|
108
108
|
}
|
|
109
109
|
});
|
|
110
110
|
|
|
@@ -204,7 +204,7 @@ function expectPositionInfo(actualPos: PI, expectedPos: PI): void {
|
|
|
204
204
|
expectArray(actualPos.getMonomers(), expectedPos.getMonomers());
|
|
205
205
|
for (const key of actualPos.getMonomers()) {
|
|
206
206
|
//
|
|
207
|
-
expect(actualPos.getFreq(key).
|
|
207
|
+
expect(actualPos.getFreq(key).rowCount, expectedPos.getFreq(key).rowCount);
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
|
package/src/utils/agg.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
export type AggValueListType = (number | null)[] | Float32Array | Int32Array;
|
|
6
|
+
export type AggFunc = (valueList: AggValueListType) => number | null;
|
|
7
|
+
|
|
8
|
+
export function getAgg(agg: DG.AggregationType): AggFunc {
|
|
9
|
+
let res: AggFunc;
|
|
10
|
+
|
|
11
|
+
function buildCol(valueList: AggValueListType): DG.Column<number> {
|
|
12
|
+
let resCol: DG.Column<number>;
|
|
13
|
+
const resColName = `agg`;
|
|
14
|
+
if (valueList instanceof Float32Array)
|
|
15
|
+
resCol = DG.Column.fromFloat32Array(resColName, valueList as Float32Array);
|
|
16
|
+
else if (valueList instanceof Int32Array)
|
|
17
|
+
resCol = DG.Column.fromInt32Array(resColName, valueList as Int32Array);
|
|
18
|
+
else
|
|
19
|
+
resCol = DG.Column.fromList(DG.COLUMN_TYPE.FLOAT, resColName, valueList as (number | null)[]);
|
|
20
|
+
|
|
21
|
+
return resCol;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return (valueList: AggValueListType): number | null => {
|
|
25
|
+
const aggCol = buildCol(valueList);
|
|
26
|
+
const res = aggCol.aggregate(agg);
|
|
27
|
+
return res;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const enum HELM_WRAPPER {
|
|
2
|
+
LEFT = 'PEPTIDE1{',
|
|
3
|
+
RIGHT = '}$$$$',
|
|
4
|
+
}
|
|
5
|
+
export const ALL_MONOMERS = '<All>';
|
|
6
|
+
|
|
7
|
+
export const enum TRANSFORMATION_TYPE {
|
|
8
|
+
CYCLIZATION = 'Cyclization',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const enum CYCLIZATION_TYPE {
|
|
12
|
+
NO = 'N-O',
|
|
13
|
+
NCys = 'N-Cys',
|
|
14
|
+
R3 = 'R3-R3',
|
|
15
|
+
}
|
|
16
|
+
|
|
@@ -3,51 +3,15 @@ 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 {NOTATION
|
|
6
|
+
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
7
7
|
import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
|
|
8
8
|
import {HELM_POLYMER_TYPE} from '@datagrok-libraries/bio/src/utils/const';
|
|
9
|
-
import {MonomerLibHelper} from '
|
|
10
|
-
import {_package} from '
|
|
9
|
+
import {MonomerLibHelper} from '../../utils/monomer-lib';
|
|
10
|
+
import {_package} from '../../package';
|
|
11
|
+
import {addCommonTags} from './utils';
|
|
11
12
|
import * as rxjs from 'rxjs';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const RIGHT_HELM_WRAPPER = '}$$$$';
|
|
15
|
-
const ALL_MONOMERS = '<All>';
|
|
16
|
-
|
|
17
|
-
type MetaData = {
|
|
18
|
-
leftTerminal: string,
|
|
19
|
-
rightTerminal: string,
|
|
20
|
-
transformationType: TRANSFORMATION_TYPE,
|
|
21
|
-
cyclizationType: CYCLIZATION_TYPE,
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
type ConnectionData = {
|
|
25
|
-
monomerPosition: number,
|
|
26
|
-
attachmentPoint: number,
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const enum TRANSFORMATION_TYPE {
|
|
30
|
-
CYCLIZATION = 'Cyclization',
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const enum CYCLIZATION_TYPE {
|
|
34
|
-
NO = 'N-O',
|
|
35
|
-
NCys = 'N-Cys',
|
|
36
|
-
R3 = 'R3-R3',
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function addCommonTags(col: DG.Column):void {
|
|
40
|
-
col.setTag('quality', DG.SEMTYPE.MACROMOLECULE);
|
|
41
|
-
col.setTag('aligned', ALIGNMENT.SEQ);
|
|
42
|
-
col.setTag('alphabet', ALPHABET.PT);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function _setPeptideColumn(col: DG.Column): void {
|
|
46
|
-
addCommonTags(col);
|
|
47
|
-
col.setTag('units', NOTATION.SEPARATOR);
|
|
48
|
-
col.setTag('separator', '-');
|
|
49
|
-
// col.setTag('cell.renderer', 'sequence');
|
|
50
|
-
}
|
|
13
|
+
import {HELM_WRAPPER, ALL_MONOMERS, CYCLIZATION_TYPE, TRANSFORMATION_TYPE} from './const';
|
|
14
|
+
import {MetaData, ConnectionData} from './types';
|
|
51
15
|
|
|
52
16
|
abstract class TransformationBase {
|
|
53
17
|
constructor(helmColumn: DG.Column<string>, meta: MetaData) {
|
|
@@ -80,11 +44,11 @@ class TransformationNCys extends TransformationBase {
|
|
|
80
44
|
}
|
|
81
45
|
|
|
82
46
|
protected hasTerminals(helm: string): boolean {
|
|
83
|
-
if (! helm.includes(this.rightTerminal +
|
|
47
|
+
if (! helm.includes(this.rightTerminal + HELM_WRAPPER.RIGHT))
|
|
84
48
|
return false;
|
|
85
49
|
if (this.leftTerminal === ALL_MONOMERS)
|
|
86
50
|
return true;
|
|
87
|
-
return helm.includes(
|
|
51
|
+
return helm.includes(HELM_WRAPPER.LEFT + this.leftTerminal);
|
|
88
52
|
}
|
|
89
53
|
|
|
90
54
|
protected getLinkedPositions(helm: string): [number, number] {
|
|
@@ -107,8 +71,8 @@ class TransformationNO extends TransformationBase {
|
|
|
107
71
|
protected hasTerminals(helm: string): boolean {
|
|
108
72
|
if (this.leftTerminal === ALL_MONOMERS || this.rightTerminal === ALL_MONOMERS)
|
|
109
73
|
return true;
|
|
110
|
-
return helm.includes(
|
|
111
|
-
helm.includes(this.rightTerminal +
|
|
74
|
+
return helm.includes(HELM_WRAPPER.LEFT + this.leftTerminal) &&
|
|
75
|
+
helm.includes(this.rightTerminal + HELM_WRAPPER.RIGHT);
|
|
112
76
|
}
|
|
113
77
|
|
|
114
78
|
protected getLinkedPositions(helm: string): [number, number] {
|
|
@@ -136,7 +100,7 @@ class TransformationR3 extends TransformationBase {
|
|
|
136
100
|
}
|
|
137
101
|
|
|
138
102
|
protected getLinkedPositions(helm: string): [number, number] {
|
|
139
|
-
const seq = helm.replace(
|
|
103
|
+
const seq = helm.replace(HELM_WRAPPER.LEFT, '').replace(HELM_WRAPPER.RIGHT, '');
|
|
140
104
|
const monomers = seq.split('.');
|
|
141
105
|
const start = monomers.findIndex((el) => el === this.leftTerminal);
|
|
142
106
|
const end = monomers.findIndex((el, idx) => el === this.rightTerminal && idx > start);
|
|
@@ -163,12 +127,12 @@ class PolymerTransformation {
|
|
|
163
127
|
}
|
|
164
128
|
|
|
165
129
|
function getNumberOfMonomers(helm: string): number {
|
|
166
|
-
const seq = helm.replace(
|
|
130
|
+
const seq = helm.replace(HELM_WRAPPER.LEFT, '').replace(HELM_WRAPPER.RIGHT, '');
|
|
167
131
|
return seq.split('.').length;
|
|
168
132
|
}
|
|
169
133
|
|
|
170
134
|
function getHelmCycle(helm: string, source: ConnectionData, target: ConnectionData): string {
|
|
171
|
-
return helm.replace(
|
|
135
|
+
return helm.replace(HELM_WRAPPER.RIGHT,
|
|
172
136
|
`}$PEPTIDE1,PEPTIDE1,${
|
|
173
137
|
source.monomerPosition
|
|
174
138
|
}:R${
|
|
@@ -200,7 +164,7 @@ async function addTransformedColumn(
|
|
|
200
164
|
await grok.data.detectSemanticTypes(df);
|
|
201
165
|
}
|
|
202
166
|
|
|
203
|
-
export function
|
|
167
|
+
export function getPolyToolDialog(): DG.Dialog {
|
|
204
168
|
function getMonomerList(cyclizationType: CYCLIZATION_TYPE): string[] {
|
|
205
169
|
if (cyclizationType === cyclizationTypes[0]) {
|
|
206
170
|
return [ALL_MONOMERS].concat(
|
|
@@ -280,16 +244,34 @@ export function _getEnumeratorWidget(molColumn: DG.Column): DG.Widget {
|
|
|
280
244
|
|
|
281
245
|
updateMeta();
|
|
282
246
|
|
|
283
|
-
const
|
|
284
|
-
|
|
247
|
+
const targetColumns = grok.shell.t.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);
|
|
248
|
+
if (!targetColumns)
|
|
249
|
+
throw new Error('No dataframe with maceomolecule columns open');
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
const targetColumnInput = ui.columnInput(
|
|
253
|
+
'Column', grok.shell.t, targetColumns[0], null,
|
|
254
|
+
{filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE}
|
|
285
255
|
);
|
|
286
256
|
|
|
287
257
|
const div = ui.div([
|
|
258
|
+
targetColumnInput,
|
|
288
259
|
transformationChoice,
|
|
289
260
|
cyclizationTypeChoice,
|
|
290
261
|
terminalControls,
|
|
291
|
-
btn
|
|
292
262
|
]);
|
|
293
263
|
|
|
294
|
-
|
|
264
|
+
const dialog = ui.dialog('Poly Tool')
|
|
265
|
+
.add(div)
|
|
266
|
+
.onOK(async () => {
|
|
267
|
+
const molCol = targetColumnInput.value;
|
|
268
|
+
if (!molCol) {
|
|
269
|
+
grok.shell.warning('No marcomolecule column chosen!');
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
addTransformedColumn(molCol!, meta);
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
return dialog;
|
|
295
277
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {TRANSFORMATION_TYPE, CYCLIZATION_TYPE} from './const';
|
|
2
|
+
|
|
3
|
+
export type MetaData = {
|
|
4
|
+
leftTerminal: string,
|
|
5
|
+
rightTerminal: string,
|
|
6
|
+
transformationType: TRANSFORMATION_TYPE,
|
|
7
|
+
cyclizationType: CYCLIZATION_TYPE,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type ConnectionData = {
|
|
11
|
+
monomerPosition: number,
|
|
12
|
+
attachmentPoint: number,
|
|
13
|
+
}
|
|
14
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
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 {NOTATION, ALIGNMENT, ALPHABET} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
7
|
+
|
|
8
|
+
export function addCommonTags(col: DG.Column):void {
|
|
9
|
+
col.setTag('quality', DG.SEMTYPE.MACROMOLECULE);
|
|
10
|
+
col.setTag('aligned', ALIGNMENT.SEQ);
|
|
11
|
+
col.setTag('alphabet', ALPHABET.PT);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function _setPeptideColumn(col: DG.Column): void {
|
|
15
|
+
addCommonTags(col);
|
|
16
|
+
col.setTag('units', NOTATION.SEPARATOR);
|
|
17
|
+
col.setTag('separator', '-');
|
|
18
|
+
// col.setTag('cell.renderer', 'sequence');
|
|
19
|
+
}
|
|
20
|
+
|