@datagrok/bio 2.21.12 → 2.22.1
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/detectors.js +1 -1
- package/dist/package-test.js +3 -3
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +2 -2
- package/dist/package.js.map +1 -1
- package/package.json +2 -2
- package/src/analysis/sequence-diversity-viewer.ts +1 -14
- package/src/package.ts +2 -2
- package/src/utils/monomer-lib/library-file-manager/ui.ts +9 -1
- package/src/viewers/web-logo-viewer.ts +1 -1
- package/src/widgets/composition-analysis-widget.ts +1 -38
- package/src/widgets/sequence-scrolling-widget.ts +20 -16
- package/test-console-output-1.log +302 -302
- package/test-record-1.mp4 +0 -0
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.22.1",
|
|
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",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@biowasm/aioli": "^3.1.0",
|
|
47
|
-
"@datagrok-libraries/bio": "^5.53.
|
|
47
|
+
"@datagrok-libraries/bio": "^5.53.4",
|
|
48
48
|
"@datagrok-libraries/chem-meta": "^1.2.7",
|
|
49
49
|
"@datagrok-libraries/math": "^1.2.4",
|
|
50
50
|
"@datagrok-libraries/ml": "^6.10.2",
|
|
@@ -32,8 +32,7 @@ export class SequenceDiversityViewer extends SequenceSearchBaseViewer {
|
|
|
32
32
|
return;
|
|
33
33
|
if (this.dataFrame) {
|
|
34
34
|
if (computeData && this.targetColumn) {
|
|
35
|
-
|
|
36
|
-
await (sh.isFasta() ? this.computeByMM() : this.computeByChem());
|
|
35
|
+
await this.computeByMM();
|
|
37
36
|
|
|
38
37
|
const diverseColumnName: string = this.diverseColumnLabel != null ? this.diverseColumnLabel :
|
|
39
38
|
`diverse (${this.targetColumnName})`;
|
|
@@ -57,18 +56,6 @@ export class SequenceDiversityViewer extends SequenceSearchBaseViewer {
|
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
private async computeByChem() {
|
|
61
|
-
const monomericMols = await getMonomericMols(this.targetColumn!, this.seqHelper);
|
|
62
|
-
//need to create df to calculate fingerprints
|
|
63
|
-
const _monomericMolsDf = DG.DataFrame.fromColumns([monomericMols]);
|
|
64
|
-
this.renderMolIds = await grok.functions.call('Chem:callChemDiversitySearch', {
|
|
65
|
-
col: monomericMols,
|
|
66
|
-
metricName: this.distanceMetric,
|
|
67
|
-
limit: this.limit,
|
|
68
|
-
fingerprint: this.fingerprint,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
59
|
private async computeByMM() {
|
|
73
60
|
const encodedSequences =
|
|
74
61
|
(await getEncodedSeqSpaceCol(this.targetColumn!, MmDistanceFunctionsNames.LEVENSHTEIN)).seqList;
|
package/src/package.ts
CHANGED
|
@@ -463,7 +463,7 @@ export async function activityCliffs(table: DG.DataFrame, molecules: DG.Column<s
|
|
|
463
463
|
options?: (IUMAPOptions | ITSNEOptions) & Options, demo?: boolean): Promise<DG.Viewer | undefined> {
|
|
464
464
|
//workaround for functions which add viewers to tableView (can be run only on active table view)
|
|
465
465
|
if (table.name !== grok.shell.tv.dataFrame.name) {
|
|
466
|
-
grok.shell.error(`Table ${table.name} is not
|
|
466
|
+
grok.shell.error(`Table ${table.name} is not a current table view`);
|
|
467
467
|
return;
|
|
468
468
|
}
|
|
469
469
|
if (!checkInputColumnUI(molecules, 'Activity Cliffs'))
|
|
@@ -594,7 +594,7 @@ export async function sequenceSpaceTopMenu(table: DG.DataFrame, molecules: DG.Co
|
|
|
594
594
|
): Promise<DG.ScatterPlotViewer | undefined> {
|
|
595
595
|
//workaround for functions which add viewers to tableView (can be run only on active table view)
|
|
596
596
|
if (table.name !== grok.shell.tv.dataFrame.name) {
|
|
597
|
-
grok.shell.error(`Table ${table.name} is not
|
|
597
|
+
grok.shell.error(`Table ${table.name} is not a current table view`);
|
|
598
598
|
return;
|
|
599
599
|
}
|
|
600
600
|
const tableView =
|
|
@@ -283,6 +283,14 @@ class LibManagerView {
|
|
|
283
283
|
this._duplicateManager.root],
|
|
284
284
|
{style: {width: '100%', height: '100%'}},
|
|
285
285
|
true);
|
|
286
|
+
if (this._view) {
|
|
287
|
+
try {
|
|
288
|
+
this._view.subs.forEach((s) => s.unsubscribe());
|
|
289
|
+
this._view.detach();
|
|
290
|
+
this._view.close();
|
|
291
|
+
} catch (_e) {
|
|
292
|
+
}
|
|
293
|
+
}
|
|
286
294
|
this._view = DG.View.fromRoot(v);
|
|
287
295
|
this._view.name = LibManagerView.viewName;
|
|
288
296
|
if (addView)
|
|
@@ -304,7 +312,7 @@ class LibManagerView {
|
|
|
304
312
|
this._view.subs.push(grok.events.onCurrentViewChanged.subscribe(() => {
|
|
305
313
|
try {
|
|
306
314
|
const inst = LibManagerView._instance;
|
|
307
|
-
if (inst && inst._view && 'id' in grok.shell.v && grok.shell.v.id === inst._view.id)
|
|
315
|
+
if (inst && inst._view && grok.shell.v && 'id' in grok.shell.v && grok.shell.v.id === inst._view.id)
|
|
308
316
|
inst._duplicateManager?.refresh();
|
|
309
317
|
} catch (e) {
|
|
310
318
|
console.error(e);
|
|
@@ -30,10 +30,10 @@ import {HelmType} from '@datagrok-libraries/bio/src/helm/types';
|
|
|
30
30
|
import {undefinedColor} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
|
|
31
31
|
|
|
32
32
|
import {AggFunc, getAgg} from '../utils/agg';
|
|
33
|
-
import {buildCompositionTable} from '../widgets/composition-analysis-widget';
|
|
34
33
|
|
|
35
34
|
import {_package, getMonomerLibHelper} from '../package';
|
|
36
35
|
import {numbersWithinMaxDiff} from './utils';
|
|
36
|
+
import {buildCompositionTable} from '@datagrok-libraries/bio/src/utils/composition-table';
|
|
37
37
|
|
|
38
38
|
declare global {
|
|
39
39
|
interface HTMLCanvasElement {
|
|
@@ -12,6 +12,7 @@ import {HelmTypes} from '@datagrok-libraries/bio/src/helm/consts';
|
|
|
12
12
|
|
|
13
13
|
import '../../css/composition-analysis.css';
|
|
14
14
|
import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
15
|
+
import {buildCompositionTable} from '@datagrok-libraries/bio/src/utils/composition-table';
|
|
15
16
|
|
|
16
17
|
export function getCompositionAnalysisWidget(
|
|
17
18
|
val: DG.SemanticValue, monomerLib: IMonomerLibBase, seqHelper: ISeqHelper
|
|
@@ -43,41 +44,3 @@ export function getCompositionAnalysisWidget(
|
|
|
43
44
|
return new DG.Widget(host);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
export function buildCompositionTable(
|
|
47
|
-
counts: { [m: string]: number }, biotype: HelmType, monomerLib: IMonomerLibBase
|
|
48
|
-
): HTMLTableElement {
|
|
49
|
-
let sumValue: number = 0;
|
|
50
|
-
let maxValue: number | null = null;
|
|
51
|
-
for (const value of Object.values(counts)) {
|
|
52
|
-
sumValue = sumValue + value;
|
|
53
|
-
maxValue = maxValue === null ? value : Math.max(maxValue, value);
|
|
54
|
-
}
|
|
55
|
-
const maxRatio = maxValue! / sumValue;
|
|
56
|
-
const elMap: { [m: string]: HTMLElement } = Object.assign({}, ...Array.from(Object.entries(counts))
|
|
57
|
-
.sort((a, b) => b[1] - a[1])
|
|
58
|
-
.map(([cm, value]) => {
|
|
59
|
-
const ratio = value / sumValue;
|
|
60
|
-
const wem = monomerLib.getWebEditorMonomer(biotype, cm)!;
|
|
61
|
-
const color = wem.backgroundcolor!;
|
|
62
|
-
const barDiv = ui.div('', {classes: 'macromolecule-cell-comp-analysis-bar'});
|
|
63
|
-
barDiv.style.width = `${50 * ratio / maxRatio}px`;
|
|
64
|
-
barDiv.style.backgroundColor = color;
|
|
65
|
-
if (GAP_SYMBOL === cm) {
|
|
66
|
-
barDiv.style.borderWidth = '1px';
|
|
67
|
-
barDiv.style.borderStyle = 'solid';
|
|
68
|
-
barDiv.style.borderColor = DG.Color.toHtml(DG.Color.lightGray);
|
|
69
|
-
}
|
|
70
|
-
const displayMonomer: string = GAP_SYMBOL === cm ? '-' : cm;
|
|
71
|
-
const valueDiv = ui.div(`${(100 * ratio).toFixed(2)}%`);
|
|
72
|
-
const el = ui.div([barDiv, valueDiv], {classes: 'macromolecule-cell-comp-analysis-value'});
|
|
73
|
-
return ({[displayMonomer]: el});
|
|
74
|
-
}));
|
|
75
|
-
|
|
76
|
-
const table = ui.tableFromMap(elMap);
|
|
77
|
-
Array.from(table.rows).forEach((row) => {
|
|
78
|
-
const barCol = (row.getElementsByClassName('macromolecule-cell-comp-analysis-bar')[0] as HTMLDivElement)
|
|
79
|
-
.style.backgroundColor;
|
|
80
|
-
row.cells[0].style.color = barCol;
|
|
81
|
-
});
|
|
82
|
-
return table;
|
|
83
|
-
}
|
|
@@ -14,6 +14,7 @@ import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/mon
|
|
|
14
14
|
import {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
|
|
15
15
|
import * as RxJs from 'rxjs';
|
|
16
16
|
import {filter} from 'rxjs/operators';
|
|
17
|
+
import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
|
|
17
18
|
|
|
18
19
|
// ============================================================================
|
|
19
20
|
// OPTIMIZED VIEWPORT-AWARE CACHING WITH FORCE UPDATE SUPPORT
|
|
@@ -110,7 +111,7 @@ class MSAViewportManager {
|
|
|
110
111
|
});
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
static getConservationForViewport(seqHandler:
|
|
114
|
+
static getConservationForViewport(seqHandler: ISeqHandler, viewportStart: number, viewportEnd: number, maxLength: number): number[] {
|
|
114
115
|
// Create a full-sized array filled with zeros
|
|
115
116
|
const result: number[] = new Array(maxLength).fill(0);
|
|
116
117
|
|
|
@@ -132,7 +133,7 @@ class MSAViewportManager {
|
|
|
132
133
|
return result;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
static getWebLogoForViewport(seqHandler:
|
|
136
|
+
static getWebLogoForViewport(seqHandler: ISeqHandler, viewportStart: number, viewportEnd: number, maxLength: number): Map<number, Map<string, number>> {
|
|
136
137
|
const result: Map<number, Map<string, number>> = new Map();
|
|
137
138
|
|
|
138
139
|
// Calculate which chunks we need
|
|
@@ -161,7 +162,7 @@ class MSAViewportManager {
|
|
|
161
162
|
// ============================================================================
|
|
162
163
|
|
|
163
164
|
class LazyWebLogoTrack extends WebLogoTrack {
|
|
164
|
-
private seqHandler:
|
|
165
|
+
private seqHandler: ISeqHandler;
|
|
165
166
|
private maxLength: number;
|
|
166
167
|
private lastViewportStart: number = -1;
|
|
167
168
|
private lastViewportEnd: number = -1;
|
|
@@ -169,7 +170,7 @@ class LazyWebLogoTrack extends WebLogoTrack {
|
|
|
169
170
|
private forceNextUpdate: boolean = false;
|
|
170
171
|
|
|
171
172
|
constructor(
|
|
172
|
-
seqHandler:
|
|
173
|
+
seqHandler: ISeqHandler,
|
|
173
174
|
maxLength: number,
|
|
174
175
|
height: number = 45,
|
|
175
176
|
title: string = 'WebLogo'
|
|
@@ -239,7 +240,7 @@ class LazyWebLogoTrack extends WebLogoTrack {
|
|
|
239
240
|
}
|
|
240
241
|
|
|
241
242
|
class LazyConservationTrack extends ConservationTrack {
|
|
242
|
-
private seqHandler:
|
|
243
|
+
private seqHandler: ISeqHandler;
|
|
243
244
|
private maxLength: number;
|
|
244
245
|
private lastViewportStart: number = -1;
|
|
245
246
|
private lastViewportEnd: number = -1;
|
|
@@ -247,7 +248,7 @@ class LazyConservationTrack extends ConservationTrack {
|
|
|
247
248
|
private forceNextUpdate: boolean = false;
|
|
248
249
|
|
|
249
250
|
constructor(
|
|
250
|
-
seqHandler:
|
|
251
|
+
seqHandler: ISeqHandler,
|
|
251
252
|
maxLength: number,
|
|
252
253
|
height: number = 45,
|
|
253
254
|
colorScheme: 'default' | 'rainbow' | 'heatmap' = 'default',
|
|
@@ -406,7 +407,7 @@ export function handleSequenceHeaderRendering() {
|
|
|
406
407
|
|
|
407
408
|
grid.sub(filterChangeSub);
|
|
408
409
|
|
|
409
|
-
const initializeHeaders = (monomerLib:
|
|
410
|
+
const initializeHeaders = (monomerLib: IMonomerLib) => {
|
|
410
411
|
const tracks: { id: string, track: MSAHeaderTrack, priority: number }[] = [];
|
|
411
412
|
|
|
412
413
|
// Create lazy tracks only if we have multiple sequences
|
|
@@ -433,7 +434,7 @@ export function handleSequenceHeaderRendering() {
|
|
|
433
434
|
|
|
434
435
|
if (monomerLib) {
|
|
435
436
|
webLogoTrack.setMonomerLib(monomerLib);
|
|
436
|
-
webLogoTrack.setBiotype(sh.defaultBiotype || '
|
|
437
|
+
webLogoTrack.setBiotype(sh.defaultBiotype || 'HELM_AA');
|
|
437
438
|
}
|
|
438
439
|
|
|
439
440
|
webLogoTrack.setupDefaultTooltip();
|
|
@@ -478,13 +479,15 @@ export function handleSequenceHeaderRendering() {
|
|
|
478
479
|
|
|
479
480
|
scroller.setSelectionData(df, seqCol, sh);
|
|
480
481
|
|
|
481
|
-
|
|
482
|
+
if (maxSeqLen > 50) {
|
|
483
|
+
grid.props.colHeaderHeight = initialHeaderHeight;
|
|
482
484
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
485
|
+
// Set column width
|
|
486
|
+
setTimeout(() => {
|
|
487
|
+
if (grid.isDetached) return;
|
|
488
|
+
gCol.width = 400;
|
|
489
|
+
}, 300);
|
|
490
|
+
}
|
|
488
491
|
|
|
489
492
|
// Handle cell rendering
|
|
490
493
|
grid.sub(grid.onCellRender.subscribe((e) => {
|
|
@@ -524,8 +527,9 @@ export function handleSequenceHeaderRendering() {
|
|
|
524
527
|
initializeHeaders(monomerLib);
|
|
525
528
|
})
|
|
526
529
|
.catch((error) => {
|
|
527
|
-
|
|
528
|
-
initializeHeaders();
|
|
530
|
+
grok.shell.warning(`Failed to initialize monomer library`);
|
|
531
|
+
//initializeHeaders();
|
|
532
|
+
console.error('Failed to initialize monomer library:', error);
|
|
529
533
|
});
|
|
530
534
|
}
|
|
531
535
|
}, 1000);
|