@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/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "Leonid Stolbov",
6
6
  "email": "lstolbov@datagrok.ai"
7
7
  },
8
- "version": "2.21.12",
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.3",
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
- const sh = this.seqHelper.getSeqHandler(this.targetColumn);
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 an current table view`);
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 an current table view`);
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: any, viewportStart: number, viewportEnd: number, maxLength: number): number[] {
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: any, viewportStart: number, viewportEnd: number, maxLength: number): Map<number, Map<string, number>> {
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: any;
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: any,
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: any;
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: any,
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: any = null) => {
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 || 'PEPTIDE');
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
- grid.props.colHeaderHeight = initialHeaderHeight;
482
+ if (maxSeqLen > 50) {
483
+ grid.props.colHeaderHeight = initialHeaderHeight;
482
484
 
483
- // Set column width
484
- setTimeout(() => {
485
- if (grid.isDetached) return;
486
- gCol.width = 400;
487
- }, 300);
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
- console.error('Error loading monomerLib:', error);
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);