@datagrok/bio 2.4.44 → 2.4.46
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/dist/79.js +2 -0
- package/dist/79.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/package.json +10 -2
- package/src/function-edtiors/split-to-monomers-editor.ts +42 -0
- package/src/package-test.ts +3 -1
- package/src/package-types.ts +40 -0
- package/src/package.ts +64 -26
- package/src/tests/msa-tests.ts +0 -3
- package/src/tests/splitters-test.ts +9 -7
- package/src/utils/cell-renderer-consts.ts +27 -0
- package/src/utils/cell-renderer.ts +11 -59
- package/src/utils/monomer-cell-renderer.ts +100 -0
- package/src/utils/split-to-monomers.ts +29 -0
- package/src/widgets/package-settings-editor-widget.ts +28 -0
- package/src/widgets/representations.ts +18 -3
- /package/files/{libraries → tests/libraries}/broken-lib.sdf +0 -0
- /package/files/{libraries → tests/libraries}/group1/mock-lib-3.json +0 -0
- /package/files/{libraries → tests/libraries}/mock-lib-2.json +0 -0
package/package.json
CHANGED
|
@@ -5,16 +5,24 @@
|
|
|
5
5
|
"name": "Leonid Stolbov",
|
|
6
6
|
"email": "lstolbov@datagrok.ai"
|
|
7
7
|
},
|
|
8
|
-
"version": "2.4.
|
|
8
|
+
"version": "2.4.46",
|
|
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",
|
|
12
12
|
"url": "https://github.com/datagrok-ai/public.git",
|
|
13
13
|
"directory": "packages/Bio"
|
|
14
14
|
},
|
|
15
|
+
"properties": [
|
|
16
|
+
{
|
|
17
|
+
"name": "MaxMonomerLength",
|
|
18
|
+
"propertyType": "int",
|
|
19
|
+
"defaultValue": 3,
|
|
20
|
+
"nullable": false
|
|
21
|
+
}
|
|
22
|
+
],
|
|
15
23
|
"dependencies": {
|
|
16
24
|
"@biowasm/aioli": "^3.1.0",
|
|
17
|
-
"@datagrok-libraries/bio": "^5.32.
|
|
25
|
+
"@datagrok-libraries/bio": "^5.32.4",
|
|
18
26
|
"@datagrok-libraries/chem-meta": "^1.0.1",
|
|
19
27
|
"@datagrok-libraries/ml": "^6.3.39",
|
|
20
28
|
"@datagrok-libraries/tutorials": "^1.3.2",
|
|
@@ -0,0 +1,42 @@
|
|
|
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 class SplitToMonomersFunctionEditor {
|
|
6
|
+
tableInput: DG.InputBase;
|
|
7
|
+
seqColInput: DG.InputBase;
|
|
8
|
+
|
|
9
|
+
funcParamsDiv: HTMLDivElement;
|
|
10
|
+
|
|
11
|
+
get funcParams(): {} {
|
|
12
|
+
return {
|
|
13
|
+
table: this.tableInput.value!,
|
|
14
|
+
sequence: this.seqColInput.value!,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get paramsUI(): HTMLDivElement {
|
|
19
|
+
return this.funcParamsDiv;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
constructor() {
|
|
23
|
+
this.tableInput = ui.tableInput('Table', grok.shell.tv.dataFrame, undefined, () => {
|
|
24
|
+
this.onTableInputChanged();
|
|
25
|
+
});
|
|
26
|
+
//TODO: remove when the new version of datagrok-api is available
|
|
27
|
+
const seqColValue = this.tableInput.value!.columns.bySemType(DG.SEMTYPE.MACROMOLECULE);
|
|
28
|
+
const seqColOptions = {filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE};
|
|
29
|
+
//@ts-ignore
|
|
30
|
+
this.seqColInput = ui.columnInput('Sequence', this.tableInput.value!, seqColValue, null, seqColOptions);
|
|
31
|
+
|
|
32
|
+
this.funcParamsDiv = ui.inputs([
|
|
33
|
+
this.tableInput,
|
|
34
|
+
this.seqColInput,
|
|
35
|
+
], {style: {minWidth: '320px'}});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
onTableInputChanged(): void {
|
|
39
|
+
this.seqColInput = ui.columnInput('Sequence', this.tableInput.value!,
|
|
40
|
+
this.tableInput.value!.columns.bySemType(DG.SEMTYPE.MACROMOLECULE));
|
|
41
|
+
}
|
|
42
|
+
}
|
package/src/package-test.ts
CHANGED
|
@@ -8,7 +8,9 @@ import './tests/detectors-tests';
|
|
|
8
8
|
import './tests/detectors-weak-and-likely-tests';
|
|
9
9
|
import './tests/detectors-benchmark-tests';
|
|
10
10
|
import './tests/msa-tests';
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
import './tests/splitters-test'; //Unhandled exceptions.exceptions : Cannot read properties of null (reading 'f')
|
|
13
|
+
|
|
12
14
|
import './tests/monomer-libraries-tests';
|
|
13
15
|
import './tests/renderers-test';
|
|
14
16
|
import './tests/converters-test';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as DG from 'datagrok-api/dg';
|
|
3
|
+
import * as ui from 'datagrok-api/ui';
|
|
4
|
+
|
|
5
|
+
import {Observable, Subject} from 'rxjs';
|
|
6
|
+
import {ObjectPropertyBag} from 'datagrok-api/dg';
|
|
7
|
+
|
|
8
|
+
/** Names of package properties/settings declared in properties section of {@link './package.json'} */
|
|
9
|
+
export const enum BioPackagePropertiesNames {
|
|
10
|
+
MaxMonomerLength = 'MaxMonomerLength',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export class BioPackageProperties extends Map<string, any> {
|
|
15
|
+
|
|
16
|
+
private _onPropertyChanged: Subject<string> = new Subject<string>();
|
|
17
|
+
public get onPropertyChanged(): Observable<string> { return this._onPropertyChanged; }
|
|
18
|
+
|
|
19
|
+
/** Monomer name maximum length displayed in short mode. */
|
|
20
|
+
public get maxMonomerLength(): number {
|
|
21
|
+
return super.get(BioPackagePropertiesNames.MaxMonomerLength) as unknown as number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public set maxMonomerLength(value: number) {
|
|
25
|
+
super.set(BioPackagePropertiesNames.MaxMonomerLength, value as unknown as object);
|
|
26
|
+
this._onPropertyChanged.next(BioPackagePropertiesNames.MaxMonomerLength);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
constructor(source: any) {
|
|
30
|
+
super(Object.entries(source));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class BioPackage extends DG.Package {
|
|
35
|
+
private _properties: BioPackageProperties;
|
|
36
|
+
/** Package properties/settings declared in properties section of {@link './package.json'} */
|
|
37
|
+
public get properties(): BioPackageProperties { return this._properties; };
|
|
38
|
+
|
|
39
|
+
public set properties(value: BioPackageProperties) { this._properties = value; }
|
|
40
|
+
}
|
package/src/package.ts
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
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 {
|
|
6
|
-
MacromoleculeDifferenceCellRenderer, MacromoleculeSequenceCellRenderer,
|
|
7
|
+
MacromoleculeDifferenceCellRenderer, MacromoleculeSequenceCellRenderer,
|
|
7
8
|
} from './utils/cell-renderer';
|
|
8
9
|
import {VdRegionsViewer} from './viewers/vd-regions-viewer';
|
|
9
10
|
import {SequenceAlignment} from './seq_align';
|
|
@@ -13,13 +14,11 @@ import {
|
|
|
13
14
|
createLinesGrid, createPropPanelElement, createTooltipElement, getChemSimilaritiesMatrix,
|
|
14
15
|
} from './analysis/sequence-activity-cliffs';
|
|
15
16
|
import {convert} from './utils/convert';
|
|
16
|
-
import {
|
|
17
|
+
import {getMacromoleculeColumnPropertyPanel} from './widgets/representations';
|
|
17
18
|
import {_toAtomicLevel} from '@datagrok-libraries/bio/src/monomer-works/to-atomic-level';
|
|
18
19
|
import {FastaFileHandler} from '@datagrok-libraries/bio/src/utils/fasta-handler';
|
|
19
20
|
import {removeEmptyStringRows} from '@datagrok-libraries/utils/src/dataframe-utils';
|
|
20
21
|
|
|
21
|
-
import {splitAlignedSequences} from '@datagrok-libraries/bio/src/utils/splitter';
|
|
22
|
-
import * as C from './utils/constants';
|
|
23
22
|
import {SequenceSimilarityViewer} from './analysis/sequence-similarity-viewer';
|
|
24
23
|
import {SequenceDiversityViewer} from './analysis/sequence-diversity-viewer';
|
|
25
24
|
import {substructureSearchDialog} from './substructure-search/substructure-search';
|
|
@@ -39,6 +38,7 @@ import {getMacromoleculeColumn} from './utils/ui-utils';
|
|
|
39
38
|
import {DimReductionMethods, ITSNEOptions, IUMAPOptions} from '@datagrok-libraries/ml/src/reduce-dimensionality';
|
|
40
39
|
import {SequenceSpaceFunctionEditor} from '@datagrok-libraries/ml/src/functionEditors/seq-space-editor';
|
|
41
40
|
import {ActivityCliffsFunctionEditor} from '@datagrok-libraries/ml/src/functionEditors/activity-cliffs-editor';
|
|
41
|
+
|
|
42
42
|
import {demoBio01UI} from './demo/bio01-similarity-diversity';
|
|
43
43
|
import {demoBio01aUI} from './demo/bio01a-hierarchical-clustering-and-sequence-space';
|
|
44
44
|
import {demoBio01bUI} from './demo/bio01b-hierarchical-clustering-and-activity-cliffs';
|
|
@@ -50,8 +50,15 @@ import {MmDistanceFunctionsNames} from '@datagrok-libraries/ml/src/macromolecule
|
|
|
50
50
|
import {BitArrayMetrics, BitArrayMetricsNames} from '@datagrok-libraries/ml/src/typed-metrics';
|
|
51
51
|
import {NotationConverter} from '@datagrok-libraries/bio/src/utils/notation-converter';
|
|
52
52
|
import {WebLogoApp} from './apps/web-logo-app';
|
|
53
|
+
import {SplitToMonomersFunctionEditor} from './function-edtiors/split-to-monomers-editor';
|
|
54
|
+
import {splitToMonomersUI} from './utils/split-to-monomers';
|
|
55
|
+
import {MonomerCellRenderer} from './utils/monomer-cell-renderer';
|
|
56
|
+
import {BioPackage, BioPackageProperties} from './package-types';
|
|
57
|
+
import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
58
|
+
import {ObjectPropertyBag} from 'datagrok-api/dg';
|
|
59
|
+
import {PackageSettingsEditorWidget} from './widgets/package-settings-editor-widget';
|
|
53
60
|
|
|
54
|
-
export const _package = new
|
|
61
|
+
export const _package = new BioPackage();
|
|
55
62
|
|
|
56
63
|
// /** Avoid reassinging {@link monomerLib} because consumers subscribe to {@link IMonomerLib.onChanged} event */
|
|
57
64
|
// let monomerLib: MonomerLib | null = null;
|
|
@@ -79,11 +86,20 @@ export class SeqPaletteCustom implements SeqPalette {
|
|
|
79
86
|
|
|
80
87
|
//tags: init
|
|
81
88
|
export async function initBio() {
|
|
82
|
-
|
|
89
|
+
let module: RDModule;
|
|
90
|
+
await Promise.all([
|
|
91
|
+
(async () => { await MonomerLibHelper.instance.loadLibraries(); })(),
|
|
92
|
+
(async () => { module = await grok.functions.call('Chem:getRdKitModule'); })(),
|
|
93
|
+
(async () => {
|
|
94
|
+
const pkgProps = await _package.getProperties();
|
|
95
|
+
const bioPkgProps = new BioPackageProperties(pkgProps);
|
|
96
|
+
_package.properties = bioPkgProps;
|
|
97
|
+
})(),
|
|
98
|
+
]);
|
|
99
|
+
|
|
83
100
|
const monomerLib = MonomerLibHelper.instance.getBioLib();
|
|
84
101
|
const monomers: string[] = [];
|
|
85
102
|
const logPs: number[] = [];
|
|
86
|
-
const module = await grok.functions.call('Chem:getRdKitModule');
|
|
87
103
|
|
|
88
104
|
const series = monomerLib!.getMonomerMolsByPolymerType('PEPTIDE')!;
|
|
89
105
|
Object.keys(series).forEach((symbol) => {
|
|
@@ -170,6 +186,21 @@ export async function libraryPanel(_seqColumn: DG.Column): Promise<DG.Widget> {
|
|
|
170
186
|
return new DG.Widget(ui.divV([inputsForm, ui.div(filesButton)]));
|
|
171
187
|
}
|
|
172
188
|
|
|
189
|
+
// -- Package settings editor --
|
|
190
|
+
|
|
191
|
+
//name: packageSettingsEditor
|
|
192
|
+
//description: The database connection
|
|
193
|
+
//tags: packageSettingsEditor
|
|
194
|
+
//input: object propList
|
|
195
|
+
//output: widget result
|
|
196
|
+
export function packageSettingsEditor(propList: DG.Property[]): DG.Widget {
|
|
197
|
+
const widget = new PackageSettingsEditorWidget(propList);
|
|
198
|
+
widget.init().then(); // Ignore promise returned
|
|
199
|
+
return widget;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// -- Cell renderers --
|
|
203
|
+
|
|
173
204
|
//name: fastaSequenceCellRenderer
|
|
174
205
|
//tags: cellRenderer
|
|
175
206
|
//meta.cellType: sequence
|
|
@@ -184,7 +215,7 @@ export function fastaSequenceCellRenderer(): MacromoleculeSequenceCellRenderer {
|
|
|
184
215
|
//tags: panel
|
|
185
216
|
//output: widget result
|
|
186
217
|
export function macroMolColumnPropertyPanel(molColumn: DG.Column): DG.Widget {
|
|
187
|
-
return
|
|
218
|
+
return getMacromoleculeColumnPropertyPanel(molColumn);
|
|
188
219
|
}
|
|
189
220
|
|
|
190
221
|
//name: separatorSequenceCellRenderer
|
|
@@ -248,7 +279,7 @@ export function SeqActivityCliffsEditor(call: DG.FuncCall) {
|
|
|
248
279
|
ui.dialog({title: 'Activity Cliffs'})
|
|
249
280
|
.add(funcEditor.paramsUI)
|
|
250
281
|
.onOK(async () => {
|
|
251
|
-
call.func.prepare(funcEditor.funcParams).call(true);
|
|
282
|
+
return call.func.prepare(funcEditor.funcParams).call(true);
|
|
252
283
|
})
|
|
253
284
|
.show();
|
|
254
285
|
}
|
|
@@ -342,7 +373,7 @@ export function SequenceSpaceEditor(call: DG.FuncCall) {
|
|
|
342
373
|
ui.dialog({title: 'Sequence Space'})
|
|
343
374
|
.add(funcEditor.paramsUI)
|
|
344
375
|
.onOK(async () => {
|
|
345
|
-
call.func.prepare(funcEditor.funcParams).call(true);
|
|
376
|
+
return call.func.prepare(funcEditor.funcParams).call(true);
|
|
346
377
|
})
|
|
347
378
|
.show();
|
|
348
379
|
}
|
|
@@ -364,8 +395,7 @@ export async function sequenceSpaceTopMenu(
|
|
|
364
395
|
// Delay is required for initial function dialog to close before starting invalidating of molfiles.
|
|
365
396
|
// Otherwise, dialog is freezing
|
|
366
397
|
await delay(10);
|
|
367
|
-
if (!checkInputColumnUI(macroMolecule, 'Sequence space'))
|
|
368
|
-
return;
|
|
398
|
+
if (!checkInputColumnUI(macroMolecule, 'Sequence space')) return;
|
|
369
399
|
|
|
370
400
|
const embedColsNames = getEmbeddingColsNames(table);
|
|
371
401
|
const withoutEmptyValues = DG.DataFrame.fromColumns([macroMolecule]).clone();
|
|
@@ -586,6 +616,7 @@ export function convertDialog() {
|
|
|
586
616
|
//name: monomerCellRenderer
|
|
587
617
|
//tags: cellRenderer
|
|
588
618
|
//meta.cellType: Monomer
|
|
619
|
+
//meta.columnTags: quality=Monomer
|
|
589
620
|
//output: grid_cell_renderer result
|
|
590
621
|
export function monomerCellRenderer(): MonomerCellRenderer {
|
|
591
622
|
return new MonomerCellRenderer();
|
|
@@ -642,20 +673,27 @@ export async function testDetectMacromolecule(path: string): Promise<DG.DataFram
|
|
|
642
673
|
return resDf;
|
|
643
674
|
}
|
|
644
675
|
|
|
645
|
-
//
|
|
646
|
-
//
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
676
|
+
//name: SplitToMonomersEditor
|
|
677
|
+
//tags: editor
|
|
678
|
+
//input: funccall call
|
|
679
|
+
export function SplitToMonomersEditor(call: DG.FuncCall): void {
|
|
680
|
+
const funcEditor = new SplitToMonomersFunctionEditor();
|
|
681
|
+
ui.dialog({title: 'Split to Monomers'})
|
|
682
|
+
.add(funcEditor.paramsUI)
|
|
683
|
+
.onOK(async () => {
|
|
684
|
+
return call.func.prepare(funcEditor.funcParams).call(true);
|
|
685
|
+
})
|
|
686
|
+
.show();
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
//top-menu: Bio | Split to Monomers
|
|
690
|
+
//name: Split to Monomers
|
|
691
|
+
//input: dataframe table
|
|
692
|
+
//input: column sequence { semType: Macromolecule }
|
|
693
|
+
//output: dataframe result
|
|
694
|
+
//editor: Bio:SplitToMonomersEditor
|
|
695
|
+
export async function splitToMonomersTopMenu(table: DG.DataFrame, sequence: DG.Column): Promise<void> {
|
|
696
|
+
await splitToMonomersUI(table, sequence);
|
|
659
697
|
}
|
|
660
698
|
|
|
661
699
|
//name: Bio: getHelmMonomers
|
package/src/tests/msa-tests.ts
CHANGED
|
@@ -9,9 +9,6 @@ import {multipleSequenceAlignmentUI} from '../utils/multiple-sequence-alignment-
|
|
|
9
9
|
import {awaitContainerStart} from './utils';
|
|
10
10
|
//import * as grok from 'datagrok-api/grok';
|
|
11
11
|
|
|
12
|
-
export const _package = new DG.Package();
|
|
13
|
-
|
|
14
|
-
|
|
15
12
|
category('MSA', async () => {
|
|
16
13
|
//table = await grok.data.files.openTable('Demo:Files/bio/peptides.csv');
|
|
17
14
|
const fromCsv = `seq
|
|
@@ -6,6 +6,7 @@ import {after, before, category, test, expect, expectArray, delay} from '@datagr
|
|
|
6
6
|
import * as C from '../utils/constants';
|
|
7
7
|
import {_package, getHelmMonomers} from '../package';
|
|
8
8
|
import {TAGS as bioTAGS, splitterAsFasta, splitterAsHelm} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
9
|
+
import {splitToMonomersUI} from '../utils/split-to-monomers';
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
category('splitters', async () => {
|
|
@@ -77,14 +78,15 @@ category('splitters', async () => {
|
|
|
77
78
|
seqCol.semType = semType;
|
|
78
79
|
seqCol.setTag(bioTAGS.aligned, C.MSA);
|
|
79
80
|
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
// call to calculate 'cell.renderer' tag
|
|
83
|
-
await grok.data.detectSemanticTypes(df);
|
|
81
|
+
const newDf = await splitToMonomersUI(df, seqCol);
|
|
82
|
+
expect(newDf.columns.names().includes('17'), true);
|
|
84
83
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
// TODO: Check cell.renderer for columns of monomers
|
|
85
|
+
// const _tv: DG.TableView = grok.shell.addTableView(df);
|
|
86
|
+
// await delay(500); // needed to account for table adding
|
|
87
|
+
// // call to calculate 'cell.renderer' tag
|
|
88
|
+
// await grok.data.detectSemanticTypes(df);
|
|
89
|
+
}, {skipReason: 'GROK-13300'});
|
|
88
90
|
|
|
89
91
|
test('getHelmMonomers', async () => {
|
|
90
92
|
const df: DG.DataFrame = DG.DataFrame.fromCsv(
|
|
@@ -0,0 +1,27 @@
|
|
|
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 enum MonomerWidthMode {
|
|
6
|
+
long = 'long',
|
|
7
|
+
short = 'short',
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const enum Tags {
|
|
11
|
+
calculated = '.mm.cellRenderer.calculated',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const enum Temps {
|
|
15
|
+
monomerWidth = '.mm.cellRenderer.monomerWidth',
|
|
16
|
+
maxMonomerLength = '.mm.cellRenderer.maxMonomerLength',
|
|
17
|
+
colorCode = '.mm.cellRenderer.colorCode',
|
|
18
|
+
compareWithCurrent = '.mm.cellRenderer.compareWithCurrent',
|
|
19
|
+
highlightDifference = '.mm.cellRenderer.highlightDifference',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// export const MacromoleculeCellRendererDefaults = new class {
|
|
23
|
+
// monomerWidth: MonomerWidthMode = MonomerWidthMode.short;
|
|
24
|
+
// maxMonomerLength: number = 3;
|
|
25
|
+
// colorCode: boolean = true;
|
|
26
|
+
// compareWithCurrent: boolean = true;
|
|
27
|
+
// }();
|
|
@@ -3,9 +3,8 @@ import * as DG from 'datagrok-api/dg';
|
|
|
3
3
|
import * as ui from 'datagrok-api/ui';
|
|
4
4
|
|
|
5
5
|
import {printLeftOrCentered, DrawStyle} from '@datagrok-libraries/bio/src/utils/cell-renderer';
|
|
6
|
-
import * as C from './constants';
|
|
7
6
|
import {
|
|
8
|
-
ALIGNMENT,
|
|
7
|
+
ALIGNMENT, ALPHABET,
|
|
9
8
|
getPaletteByType,
|
|
10
9
|
getSplitter,
|
|
11
10
|
monomerToShort,
|
|
@@ -15,6 +14,11 @@ import {
|
|
|
15
14
|
} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
16
15
|
import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
|
|
17
16
|
import {UnknownSeqPalettes} from '@datagrok-libraries/bio/src/unknown';
|
|
17
|
+
import {MonomerWorks} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
|
|
18
|
+
import {Tags as mmcrTags, Temps as mmcrTemps} from '../utils/cell-renderer-consts';
|
|
19
|
+
|
|
20
|
+
import * as C from './constants';
|
|
21
|
+
import {_package} from '../package';
|
|
18
22
|
|
|
19
23
|
const enum tempTAGS {
|
|
20
24
|
referenceSequence = 'reference-sequence',
|
|
@@ -151,19 +155,19 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
151
155
|
const referenceSequence: string[] = splitterFunc(
|
|
152
156
|
((tempReferenceSequence != null) && (tempReferenceSequence != '')) ?
|
|
153
157
|
tempReferenceSequence : tempCurrentWord ?? '');
|
|
154
|
-
const monomerWidth: string =
|
|
158
|
+
const monomerWidth: string = tempMonomerWidth ?? 'short';
|
|
155
159
|
|
|
156
160
|
let gapRenderer = 5;
|
|
157
161
|
let maxIndex = 0;
|
|
158
|
-
let maxLengthOfMonomer = 8;
|
|
162
|
+
let maxLengthOfMonomer: number = 8;
|
|
159
163
|
|
|
160
164
|
if (monomerWidth === 'short') {
|
|
161
165
|
gapRenderer = 12;
|
|
162
|
-
maxLengthOfMonomer =
|
|
166
|
+
maxLengthOfMonomer = colTemp[mmcrTemps.maxMonomerLength] ?? _package.properties.maxMonomerLength;
|
|
163
167
|
}
|
|
164
168
|
|
|
165
169
|
let maxLengthWords: any = {};
|
|
166
|
-
if (gridCell.cell.column.getTag(
|
|
170
|
+
if (gridCell.cell.column.getTag(mmcrTags.calculated) !== splitLimit.toString()) {
|
|
167
171
|
let samples = 0;
|
|
168
172
|
while (samples < Math.min(gridCell.cell.column.length, 100)) {
|
|
169
173
|
const column = gridCell.cell.column.get(samples);
|
|
@@ -185,7 +189,7 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
185
189
|
colTemp[tempTAGS.bioSumMaxLengthWords] = maxLengthWordSum;
|
|
186
190
|
colTemp[tempTAGS.bioMaxIndex] = maxIndex;
|
|
187
191
|
colTemp[tempTAGS.bioMaxLengthWords] = maxLengthWords;
|
|
188
|
-
gridCell.cell.column.setTag(
|
|
192
|
+
gridCell.cell.column.setTag(mmcrTags.calculated, splitLimit.toString());
|
|
189
193
|
}
|
|
190
194
|
} else {
|
|
191
195
|
maxLengthWords = colTemp[tempTAGS.bioMaxLengthWords];
|
|
@@ -215,58 +219,6 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
215
219
|
}
|
|
216
220
|
}
|
|
217
221
|
|
|
218
|
-
export class MonomerCellRenderer extends DG.GridCellRenderer {
|
|
219
|
-
get name(): string { return C.SEM_TYPES.MONOMER; }
|
|
220
|
-
|
|
221
|
-
get cellType(): string { return C.SEM_TYPES.MONOMER; }
|
|
222
|
-
|
|
223
|
-
get defaultHeight(): number { return 15; }
|
|
224
|
-
|
|
225
|
-
get defaultWidth(): number { return 30; }
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Cell renderer function.
|
|
229
|
-
*
|
|
230
|
-
* @param {CanvasRenderingContext2D} g Canvas rendering context.
|
|
231
|
-
* @param {number} x x coordinate on the canvas.
|
|
232
|
-
* @param {number} y y coordinate on the canvas.
|
|
233
|
-
* @param {number} w width of the cell.
|
|
234
|
-
* @param {number} h height of the cell.
|
|
235
|
-
* @param {DG.GridCell} gridCell Grid cell.
|
|
236
|
-
* @param {DG.GridCellStyle} _cellStyle Cell style.
|
|
237
|
-
*/
|
|
238
|
-
render(
|
|
239
|
-
g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, gridCell: DG.GridCell,
|
|
240
|
-
_cellStyle: DG.GridCellStyle): void {
|
|
241
|
-
g.font = `12px monospace`;
|
|
242
|
-
g.textBaseline = 'middle';
|
|
243
|
-
g.textAlign = 'center';
|
|
244
|
-
|
|
245
|
-
const palette = getPaletteByType(gridCell.cell.column.getTag(bioTAGS.alphabet));
|
|
246
|
-
const s: string = gridCell.cell.value;
|
|
247
|
-
if (!s)
|
|
248
|
-
return;
|
|
249
|
-
const color = palette.get(s);
|
|
250
|
-
|
|
251
|
-
g.fillStyle = color;
|
|
252
|
-
g.fillText(monomerToShort(s, 3), x + (w / 2), y + (h / 2), w);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
svgMolOptions = {autoCrop: true, autoCropMargin: 0, suppressChiralText: true};
|
|
256
|
-
|
|
257
|
-
onMouseEnter(gridCell: DG.GridCell, e: MouseEvent) {
|
|
258
|
-
super.onMouseEnter(gridCell, e);
|
|
259
|
-
|
|
260
|
-
// TODO: Display monomer structure within tooltip
|
|
261
|
-
// const monomerName = gridCell.cell.value;
|
|
262
|
-
// const mw = getMonomerWorksInstance();
|
|
263
|
-
// // TODO: Display monomer structure in Tooltip
|
|
264
|
-
// const nameDiv = ui.div(monomerName);
|
|
265
|
-
// const molDiv = grok.chem.svgMol(monomerMol, undefined, undefined, svgMolOptions);
|
|
266
|
-
//
|
|
267
|
-
// ui.tooltip.show(ui.divV([nameDiv, molEl,]), x, y);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
222
|
|
|
271
223
|
export class MacromoleculeDifferenceCellRenderer extends DG.GridCellRenderer {
|
|
272
224
|
get name(): string { return 'MacromoleculeDifferenceCR'; }
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as DG from 'datagrok-api/dg';
|
|
3
|
+
import * as ui from 'datagrok-api/ui';
|
|
4
|
+
|
|
5
|
+
import {ALPHABET, getPaletteByType, monomerToShort} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
6
|
+
import {TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
7
|
+
import {MonomerWorks} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
|
|
8
|
+
|
|
9
|
+
import {getMonomerLibHelper} from '../package';
|
|
10
|
+
import * as C from './constants';
|
|
11
|
+
|
|
12
|
+
const Tags = new class {
|
|
13
|
+
tooltipHandlerTemp = 'tooltip-handler.Monomer';
|
|
14
|
+
}();
|
|
15
|
+
|
|
16
|
+
const svgMolOptions = {autoCrop: true, autoCropMargin: 0, suppressChiralText: true};
|
|
17
|
+
|
|
18
|
+
export class MonomerTooltipHandler {
|
|
19
|
+
private readonly grid: DG.Grid;
|
|
20
|
+
|
|
21
|
+
constructor(grid: DG.Grid) {
|
|
22
|
+
this.grid = grid;
|
|
23
|
+
this.grid.onCellTooltip(this.onCellTooltip.bind(this));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private onCellTooltip(gridCell: DG.GridCell, x: number, y: number): any {
|
|
27
|
+
if (gridCell.grid.dart != this.grid.dart || !gridCell.tableColumn || !gridCell.isTableCell ||
|
|
28
|
+
gridCell.tableColumn.semType != 'Monomer') return false;
|
|
29
|
+
|
|
30
|
+
const alphabet = gridCell.tableColumn.getTag(bioTAGS.alphabet);
|
|
31
|
+
const monomerName = gridCell.cell.value;
|
|
32
|
+
const mw = new MonomerWorks(getMonomerLibHelper().getBioLib());
|
|
33
|
+
const monomerType: string = (alphabet === ALPHABET.DNA || alphabet === ALPHABET.RNA) ? 'RNA' :
|
|
34
|
+
alphabet === ALPHABET.PT ? 'PEPTIDE' : 'PEPTIDE';
|
|
35
|
+
|
|
36
|
+
const monomerMol: string | null = mw.getCappedRotatedMonomer(monomerType, monomerName);
|
|
37
|
+
const nameDiv = ui.div(monomerName);
|
|
38
|
+
const molDiv = !monomerMol ? null :
|
|
39
|
+
grok.chem.svgMol(monomerMol, undefined, undefined, svgMolOptions);
|
|
40
|
+
|
|
41
|
+
const canvasClientRect = gridCell.grid.canvas.getBoundingClientRect();
|
|
42
|
+
const x1 = gridCell.bounds.right + canvasClientRect.left - 4;
|
|
43
|
+
const y1 = gridCell.bounds.bottom + canvasClientRect.top - 4;
|
|
44
|
+
ui.tooltip.show(ui.divV([nameDiv, ...(molDiv ? [molDiv] : [])]), x1, y1);
|
|
45
|
+
|
|
46
|
+
return true; // To prevent default tooltip behaviour
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public static getOrCreate(grid: DG.Grid): MonomerTooltipHandler {
|
|
50
|
+
const gridTemp: { [tempName: string]: any } = grid.dataFrame.temp;
|
|
51
|
+
if (!(Tags.tooltipHandlerTemp in gridTemp)) {
|
|
52
|
+
gridTemp[Tags.tooltipHandlerTemp] = new MonomerTooltipHandler(grid);
|
|
53
|
+
grid.temp = gridTemp;
|
|
54
|
+
}
|
|
55
|
+
return gridTemp[Tags.tooltipHandlerTemp];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class MonomerCellRenderer extends DG.GridCellRenderer {
|
|
60
|
+
get name(): string { return C.SEM_TYPES.MONOMER; }
|
|
61
|
+
|
|
62
|
+
get cellType(): string { return C.SEM_TYPES.MONOMER; }
|
|
63
|
+
|
|
64
|
+
get defaultHeight(): number { return 15; }
|
|
65
|
+
|
|
66
|
+
get defaultWidth(): number { return 30; }
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Cell renderer function.
|
|
70
|
+
*
|
|
71
|
+
* @param {CanvasRenderingContext2D} g Canvas rendering context.
|
|
72
|
+
* @param {number} x x coordinate on the canvas.
|
|
73
|
+
* @param {number} y y coordinate on the canvas.
|
|
74
|
+
* @param {number} w width of the cell.
|
|
75
|
+
* @param {number} h height of the cell.
|
|
76
|
+
* @param {DG.GridCell} gridCell Grid cell.
|
|
77
|
+
* @param {DG.GridCellStyle} _cellStyle Cell style.
|
|
78
|
+
*/
|
|
79
|
+
render(
|
|
80
|
+
g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, gridCell: DG.GridCell,
|
|
81
|
+
_cellStyle: DG.GridCellStyle
|
|
82
|
+
): void {
|
|
83
|
+
if (gridCell.gridRow < 0) return;
|
|
84
|
+
MonomerTooltipHandler.getOrCreate(gridCell.grid);
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
g.font = `12px monospace`;
|
|
88
|
+
g.textBaseline = 'middle';
|
|
89
|
+
g.textAlign = 'center';
|
|
90
|
+
|
|
91
|
+
const palette = getPaletteByType(gridCell.cell.column.getTag(bioTAGS.alphabet));
|
|
92
|
+
const s: string = gridCell.cell.value;
|
|
93
|
+
if (!s)
|
|
94
|
+
return;
|
|
95
|
+
const color = palette.get(s);
|
|
96
|
+
|
|
97
|
+
g.fillStyle = color;
|
|
98
|
+
g.fillText(monomerToShort(s, 3), x + (w / 2), y + (h / 2), w);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {delay} from '@datagrok-libraries/utils/src/test';
|
|
2
|
+
import {checkInputColumnUI} from './check-input-column';
|
|
3
|
+
import {splitAlignedSequences} from '@datagrok-libraries/bio/src/utils/splitter';
|
|
4
|
+
import * as C from './constants';
|
|
5
|
+
import {TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
6
|
+
import * as grok from 'datagrok-api/grok';
|
|
7
|
+
import * as DG from 'datagrok-api/dg';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export async function splitToMonomersUI(table: DG.DataFrame, seqCol: DG.Column<string>): Promise<DG.DataFrame> {
|
|
11
|
+
// Delay is required for initial function dialog to close before starting invalidating of molfiles.
|
|
12
|
+
// Otherwise, dialog is freezing
|
|
13
|
+
await delay(10);
|
|
14
|
+
if (!checkInputColumnUI(seqCol, 'Sequence space')) return table;
|
|
15
|
+
|
|
16
|
+
const tempDf = splitAlignedSequences(seqCol);
|
|
17
|
+
const originalDf = seqCol.dataFrame;
|
|
18
|
+
for (const tempCol of tempDf.columns) {
|
|
19
|
+
// TODO: GROK-11212
|
|
20
|
+
// tempCol.setTag(DG.TAGS.CELL_RENDERER, C.SEM_TYPES.MONOMER);
|
|
21
|
+
tempCol.semType = C.SEM_TYPES.MONOMER;
|
|
22
|
+
tempCol.setTag(bioTAGS.alphabet, seqCol.getTag(bioTAGS.alphabet));
|
|
23
|
+
}
|
|
24
|
+
// Create the new data frame to enable platform to setup cell renderers
|
|
25
|
+
const newDf = originalDf.join(tempDf, [], [], undefined, undefined, DG.JOIN_TYPE.LEFT, false);
|
|
26
|
+
grok.shell.addTableView(newDf);
|
|
27
|
+
|
|
28
|
+
return newDf;
|
|
29
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
import {_package} from '../package';
|
|
5
|
+
|
|
6
|
+
export class PackageSettingsEditorWidget extends DG.Widget {
|
|
7
|
+
maxMonomerLengthProp: DG.Property;
|
|
8
|
+
|
|
9
|
+
constructor(propList: DG.Property[]) {
|
|
10
|
+
super(ui.div([], {}));
|
|
11
|
+
|
|
12
|
+
const props: { [name: string]: DG.Property } =
|
|
13
|
+
Object.assign({}, ...propList.map((p) => ({[p.name]: p})));
|
|
14
|
+
|
|
15
|
+
this.maxMonomerLengthProp = props['MaxMonomerLength'];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async init(): Promise<void> {
|
|
19
|
+
const maxMonomerLengthInput = ui.intInput('Max monomer length',
|
|
20
|
+
_package.properties.maxMonomerLength,
|
|
21
|
+
(value: number) => {
|
|
22
|
+
// Handle user changed value
|
|
23
|
+
_package.properties.maxMonomerLength = value;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
this.root.appendChild(ui.form([maxMonomerLengthInput,]));
|
|
27
|
+
}
|
|
28
|
+
}
|