@datagrok/bio 2.11.22 → 2.11.24

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.11.22",
8
+ "version": "2.11.24",
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,11 +34,12 @@
34
34
  ],
35
35
  "dependencies": {
36
36
  "@biowasm/aioli": "^3.1.0",
37
- "@datagrok-libraries/bio": "^5.39.16",
37
+ "@datagrok-libraries/bio": "^5.39.18",
38
38
  "@datagrok-libraries/chem-meta": "^1.2.1",
39
39
  "@datagrok-libraries/ml": "^6.3.68",
40
40
  "@datagrok-libraries/tutorials": "^1.3.11",
41
41
  "@datagrok-libraries/utils": "^4.1.36",
42
+ "@datagrok-libraries/math": "^1.0.7",
42
43
  "cash-dom": "^8.0.0",
43
44
  "css-loader": "^6.7.3",
44
45
  "datagrok-api": "^1.16.0",
@@ -65,7 +66,7 @@
65
66
  "webpack-bundle-analyzer": "latest",
66
67
  "webpack-cli": "^4.9.1",
67
68
  "@datagrok/chem": "^1.8.8",
68
- "@datagrok/helm": "^2.1.22",
69
+ "@datagrok/helm": "^2.1.24",
69
70
  "@datagrok/dendrogram": "^1.2.22"
70
71
  },
71
72
  "scripts": {
@@ -3,13 +3,11 @@ import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {_package} from '../package';
6
-
7
- import * as lev from 'fastest-levenshtein';
8
- import {DistanceMatrix} from '@datagrok-libraries/ml/src/distance-matrix';
9
6
  import {getTreeHelper, ITreeHelper} from '@datagrok-libraries/bio/src/trees/tree-helper';
10
7
  import {getDendrogramService, IDendrogramService} from '@datagrok-libraries/bio/src/trees/dendrogram';
11
8
  import {demoSequenceSpace, handleError} from './utils';
12
9
  import {DemoScript} from '@datagrok-libraries/tutorials/src/demo-script';
10
+ import {getClusterMatrixWorker} from '@datagrok-libraries/math';
13
11
 
14
12
  const dataFn = 'data/sample_FASTA_PT_activity.csv';
15
13
  const seqColName = 'sequence';
@@ -55,13 +53,11 @@ export async function demoBio01aUI() {
55
53
  delay: 2000,
56
54
  })
57
55
  .step('Cluster sequences', async () => {
58
- const seqCol: DG.Column<string> = df.getCol(seqColName);
59
- const seqList = seqCol.toList();
60
- const distance: DistanceMatrix = DistanceMatrix.calc(seqList, (aSeq: string, bSeq: string) => {
61
- const levDistance = lev.distance(aSeq, bSeq);
62
- return levDistance / ((aSeq.length + bSeq.length) / 2);
63
- });
64
- const treeRoot = await treeHelper.hierarchicalClusteringByDistance(distance, 'ward');
56
+ const distance = await treeHelper.calcDistanceMatrix(df, [seqColName]);
57
+ const clusterMatrix = await getClusterMatrixWorker(
58
+ distance!.data, df.rowCount, 1,
59
+ );
60
+ const treeRoot = treeHelper.parseClusterMatrix(clusterMatrix);
65
61
  dendrogramSvc.injectTreeForGrid(view.grid, treeRoot, undefined, 150, undefined);
66
62
  }, {
67
63
  description: `Perform hierarchical clustering to reveal relationships between sequences.`,
@@ -6,14 +6,13 @@ import {_package, activityCliffs} from '../package';
6
6
  import $ from 'cash-dom';
7
7
 
8
8
  import {TEMPS as acTEMPS} from '@datagrok-libraries/ml/src/viewers/activity-cliffs';
9
- import * as lev from 'fastest-levenshtein';
10
- import {DistanceMatrix} from '@datagrok-libraries/ml/src/distance-matrix';
11
9
  import {getTreeHelper, ITreeHelper} from '@datagrok-libraries/bio/src/trees/tree-helper';
12
10
  import {getDendrogramService, IDendrogramService} from '@datagrok-libraries/bio/src/trees/dendrogram';
13
11
  import {handleError} from './utils';
14
12
  import {DemoScript} from '@datagrok-libraries/tutorials/src/demo-script';
15
13
  import {DimReductionMethods} from '@datagrok-libraries/ml/src/reduce-dimensionality';
16
14
  import {MmDistanceFunctionsNames} from '@datagrok-libraries/ml/src/macromolecule-distance-functions';
15
+ import {getClusterMatrixWorker} from '@datagrok-libraries/math';
17
16
 
18
17
  const dataFn: string = 'data/sample_FASTA_PT_activity.csv';
19
18
 
@@ -67,13 +66,12 @@ export async function demoBio01bUI() {
67
66
  })
68
67
  .step('Cluster sequences', async () => {
69
68
  const progressBar = DG.TaskBarProgressIndicator.create(`Running sequence clustering...`);
70
- const seqCol: DG.Column<string> = df.getCol('sequence');
71
- const seqList = seqCol.toList();
72
- const distance: DistanceMatrix = DistanceMatrix.calc(seqList, (aSeq: string, bSeq: string) => {
73
- const levDistance = lev.distance(aSeq, bSeq);
74
- return levDistance / ((aSeq.length + bSeq.length) / 2);
75
- });
76
- const treeRoot = await treeHelper.hierarchicalClusteringByDistance(distance, 'ward');
69
+
70
+ const distance = await treeHelper.calcDistanceMatrix(df, ['sequence']);
71
+ const clusterMatrix = await getClusterMatrixWorker(
72
+ distance!.data, df.rowCount, 1,
73
+ );
74
+ const treeRoot = treeHelper.parseClusterMatrix(clusterMatrix);
77
75
  progressBar.close();
78
76
  dendrogramSvc.injectTreeForGrid(view.grid, treeRoot, undefined, 150, undefined);
79
77
 
@@ -294,6 +294,10 @@ enum WlRenderLevel {
294
294
  Freqs = 2,
295
295
  }
296
296
 
297
+ export const Debounces = new class {
298
+ render: number = 20;
299
+ }();
300
+
297
301
  const POSITION_LABELS_HEIGHT: number = 12;
298
302
 
299
303
  export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
@@ -507,7 +511,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
507
511
  const dataFrameTxt: string = this.dataFrame ? 'data' : 'null';
508
512
  _package.logger.debug(`Bio: WebLogoViewer<${this.viewerId}>.buildView( dataFrame = ${dataFrameTxt} ) start`);
509
513
  const dpr = window.devicePixelRatio;
510
- this.viewSubs.push(DG.debounce(this.renderRequest)
514
+ this.viewSubs.push(DG.debounce(this.renderRequest, Debounces.render)
511
515
  .subscribe(this.renderRequestOnDebounce.bind(this)));
512
516
 
513
517
  this.helpUrl = '/help/visualize/viewers/web-logo.md';
@@ -6,17 +6,21 @@
6
6
 
7
7
  import * as ui from 'datagrok-api/ui';
8
8
  import * as DG from 'datagrok-api/dg';
9
-
10
9
  import * as grok from 'datagrok-api/grok';
10
+
11
11
  import wu from 'wu';
12
- import {helmSubstructureSearch, linearSubstructureSearch} from '../substructure-search/substructure-search';
13
- import {Subject, Subscription} from 'rxjs';
14
- import {updateDivInnerHTML} from '../utils/ui-utils';
12
+ import {fromEvent, Subject, Subscription, Unsubscribable} from 'rxjs';
13
+ import {debounceTime} from 'rxjs/operators';
14
+
15
15
  import {TAGS as bioTAGS, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
16
+ import {errInfo, errStack} from '@datagrok-libraries/bio/src/utils/err-info';
16
17
  import {delay} from '@datagrok-libraries/utils/src/test';
17
- import {debounceTime} from 'rxjs/operators';
18
+ import {IHelmWebEditor} from '@datagrok-libraries/bio/src/types/editor';
18
19
 
19
- import {_package} from '../package-test';
20
+ import {helmSubstructureSearch, linearSubstructureSearch} from '../substructure-search/substructure-search';
21
+ import {updateDivInnerHTML} from '../utils/ui-utils';
22
+
23
+ import {_package} from '../package';
20
24
 
21
25
  export class BioSubstructureFilter extends DG.Filter {
22
26
  bioFilter: BioFilterBase | null = null;
@@ -84,6 +88,7 @@ export class BioSubstructureFilter extends DG.Filter {
84
88
  }
85
89
 
86
90
  detach() {
91
+ if (this.bioFilter) this.bioFilter.detach();
87
92
  super.detach();
88
93
  }
89
94
 
@@ -147,18 +152,16 @@ abstract class BioFilterBase {
147
152
  return new HTMLElement();
148
153
  }
149
154
 
150
- get substructure() {
151
- return '';
152
- }
153
-
154
- set substructure(s: string) {
155
- }
155
+ abstract get substructure(): string;
156
+ abstract set substructure(s: string);
156
157
 
157
158
  async substructureSearch(_column: DG.Column): Promise<DG.BitSet | null> {
158
159
  return null;
159
160
  }
160
161
 
161
162
  abstract resetFilter(): void;
163
+
164
+ abstract detach(): void;
162
165
  }
163
166
 
164
167
  class FastaFilter extends BioFilterBase {
@@ -191,6 +194,8 @@ class FastaFilter extends BioFilterBase {
191
194
  resetFilter(): void {
192
195
  this.substructureInput.value = '';
193
196
  }
197
+
198
+ detach(): void { }
194
199
  }
195
200
 
196
201
  export class SeparatorFilter extends FastaFilter {
@@ -227,10 +232,12 @@ export class SeparatorFilter extends FastaFilter {
227
232
  async substructureSearch(column: DG.Column): Promise<DG.BitSet | null> {
228
233
  return linearSubstructureSearch(this.substructure, column, this.colSeparator);
229
234
  }
235
+
236
+ detach(): void { }
230
237
  }
231
238
 
232
239
  export class HelmFilter extends BioFilterBase {
233
- helmEditor: any;
240
+ helmEditor: IHelmWebEditor;
234
241
  _filterPanel = ui.div('', {style: {cursor: 'pointer'}});
235
242
  helmSubstructure = '';
236
243
 
@@ -239,14 +246,18 @@ export class HelmFilter extends BioFilterBase {
239
246
  this.init();
240
247
  }
241
248
 
249
+ viewSubs: Unsubscribable[] = [];
250
+
242
251
  async init() {
243
- this.helmEditor = await grok.functions.call('HELM:helmWebEditor');
252
+ this.helmEditor = await grok.functions.call('Helm:helmWebEditor');
244
253
  await ui.tools.waitForElementInDom(this._filterPanel);
245
254
  this.updateFilterPanel();
246
- this._filterPanel.addEventListener('click', (_event: MouseEvent) => {
247
- const {editorDiv, webEditor} = this.helmEditor.createWebEditor(this.helmSubstructure);
248
- //@ts-ignore
249
- ui.dialog({showHeader: false, showFooter: true})
255
+ let editorDiv: HTMLDivElement | undefined;
256
+ let webEditor: any | undefined;
257
+ // TODO: Unsubscribe 'click' and 'sizeChanged'
258
+ this.viewSubs.push(fromEvent(this._filterPanel, 'click').subscribe(() => {
259
+ ({editorDiv, webEditor} = this.helmEditor.createWebEditor(this.helmSubstructure));
260
+ const dlg = ui.dialog({showHeader: false, showFooter: true})
250
261
  .add(editorDiv)
251
262
  .onOK(() => {
252
263
  const helmString = webEditor.canvas.getHelm(true)
@@ -255,12 +266,24 @@ export class HelmFilter extends BioFilterBase {
255
266
  this.updateFilterPanel(this.substructure);
256
267
  setTimeout(() => { this.onChanged.next(); }, 10);
257
268
  }).show({modal: true, fullScreen: true});
258
- });
259
- ui.onSizeChanged(this._filterPanel).subscribe((_) => {
260
- const helmString = this.helmEditor
261
- .webEditor.canvas.getHelm(true).replace(/<\/span>/g, '').replace(/<span style='background:#bbf;'>/g, '');
262
- this.updateFilterPanel(helmString);
263
- });
269
+ const onCloseSub = dlg.onClose.subscribe(() => {
270
+ onCloseSub.unsubscribe();
271
+ editorDiv = undefined;
272
+ webEditor = undefined;
273
+ });
274
+ }));
275
+ this.viewSubs.push(ui.onSizeChanged(this._filterPanel).subscribe((_) => {
276
+ try {
277
+ if (!!webEditor) {
278
+ const helmString = webEditor.canvas.getHelm(true)
279
+ .replace(/<\/span>/g, '').replace(/<span style='background:#bbf;'>/g, '');
280
+ this.updateFilterPanel(helmString);
281
+ }
282
+ } catch (err: any) {
283
+ const [errMsg, errStack] = errInfo(err);
284
+ _package.logger.error(errMsg, undefined, errStack);
285
+ }
286
+ }));
264
287
  }
265
288
 
266
289
  get filterPanel() {
@@ -302,4 +325,8 @@ export class HelmFilter extends BioFilterBase {
302
325
  this.helmSubstructure = '';
303
326
  this.updateFilterPanel(this.substructure);
304
327
  }
328
+
329
+ detach(): void {
330
+ for (const sub of this.viewSubs) sub.unsubscribe();
331
+ }
305
332
  }