@datagrok/bio 2.0.22 → 2.0.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.0.22",
8
+ "version": "2.0.24",
9
9
  "description": "Bio is a [package](https://datagrok.ai/help/develop/develop#packages) for the [Datagrok](https://datagrok.ai) platform",
10
10
  "repository": {
11
11
  "type": "git",
@@ -14,10 +14,10 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@biowasm/aioli": "^3.1.0",
17
- "@datagrok-libraries/bio": "^5.1.1",
17
+ "@datagrok-libraries/bio": "^5.2.0",
18
18
  "@datagrok-libraries/chem-meta": "1.0.1",
19
19
  "@datagrok-libraries/ml": "^6.2.0",
20
- "@datagrok-libraries/utils": "^1.10.1",
20
+ "@datagrok-libraries/utils": "^1.11.0",
21
21
  "@deck.gl/core": "^8.7.5",
22
22
  "@deck.gl/layers": "^8.7.5",
23
23
  "@luma.gl/constants": "^8.5.10",
@@ -24,8 +24,9 @@ export {tests};
24
24
  //name: test
25
25
  //input: string category {optional: true}
26
26
  //input: string test {optional: true}
27
+ //input: bool catchUnhandled {optional: true}
27
28
  //output: dataframe result
28
- export async function test(category: string, test: string): Promise<DG.DataFrame> {
29
- const data = await runTests({category, test});
29
+ export async function test(category: string, test: string, catchUnhandled: boolean): Promise<DG.DataFrame> {
30
+ const data = await runTests({category, test, catchUnhandled});
30
31
  return DG.DataFrame.fromObjects(data)!;
31
32
  }
package/src/package.ts CHANGED
@@ -138,7 +138,7 @@ export function sequenceAlignment(alignType: string, alignTable: string, gap: nu
138
138
  //tags: viewer, panel
139
139
  //output: viewer result
140
140
  export function webLogoViewer() {
141
- return new bio.WebLogo();
141
+ return new bio.WebLogoViewer();
142
142
  }
143
143
 
144
144
  //name: VdRegions
@@ -266,14 +266,14 @@ export async function toAtomicLevel(df: DG.DataFrame, macroMolecule: DG.Column):
266
266
  //input: dataframe table
267
267
  //input: column sequence { semType: Macromolecule, units: ['fasta'], alphabet: ['DNA', 'RNA', 'PT'] }
268
268
  //output: column result
269
- export async function multipleSequenceAlignmentAny(table: DG.DataFrame, col: DG.Column): Promise<DG.Column | null> {
269
+ export async function multipleSequenceAlignmentAny(table: DG.DataFrame, sequence: DG.Column): Promise<DG.Column | null> {
270
270
  const func: DG.Func = DG.Func.find({package: 'Bio', name: 'multipleSequenceAlignmentAny'})[0];
271
271
 
272
- if (!checkInputColumnUi(col, 'MSA', ['fasta'], ['DNA', 'RNA', 'PT']))
272
+ if (!checkInputColumnUi(sequence, 'MSA', ['fasta'], ['DNA', 'RNA', 'PT']))
273
273
  return null;
274
274
 
275
- const unUsedName = table.columns.getUnusedName(`msa(${col.name})`);
276
- const msaCol = await runKalign(col, false, unUsedName);
275
+ const unUsedName = table.columns.getUnusedName(`msa(${sequence.name})`);
276
+ const msaCol = await runKalign(sequence, false, unUsedName);
277
277
  table.columns.add(msaCol);
278
278
 
279
279
  // This call is required to enable cell renderer activation
@@ -288,8 +288,8 @@ export async function multipleSequenceAlignmentAny(table: DG.DataFrame, col: DG.
288
288
  //tags: bio, panel
289
289
  //input: column sequence { semType: Macromolecule }
290
290
  //output: column result
291
- export async function panelMSA(col: DG.Column): Promise<DG.Column | null> {
292
- return multipleSequenceAlignmentAny(col.dataFrame, col);
291
+ export async function panelMSA(sequence: DG.Column): Promise<DG.Column | null> {
292
+ return multipleSequenceAlignmentAny(sequence.dataFrame, sequence);
293
293
  }
294
294
 
295
295
  //name: Composition Analysis
@@ -465,9 +465,9 @@ export function splitToMonomers(col: DG.Column<string>): void {
465
465
  }
466
466
 
467
467
  //name: Bio: getHelmMonomers
468
- //input: column col {semType: Macromolecule}
469
- export function getHelmMonomers(seqCol: DG.Column<string>): string[] {
470
- const stats = bio.getStats(seqCol, 1, bio.splitterAsHelm);
468
+ //input: column sequence {semType: Macromolecule}
469
+ export function getHelmMonomers(sequence: DG.Column<string>): string[] {
470
+ const stats = bio.getStats(sequence, 1, bio.splitterAsHelm);
471
471
  return Object.keys(stats.freq);
472
472
  }
473
473
 
@@ -8,7 +8,7 @@ import {after, before, category, test, expect, expectObject, delay} from '@datag
8
8
  category('WebLogo-positions', () => {
9
9
  let tvList: DG.TableView[];
10
10
  let dfList: DG.DataFrame[];
11
- let currentView: DG.View;
11
+ let currentView: DG.ViewBase;
12
12
 
13
13
  const csvDf1 = `seq
14
14
  ATC-G-TTGC--
@@ -21,13 +21,13 @@ ATC-G-TTGC--
21
21
  before(async () => {
22
22
  tvList = [];
23
23
  dfList = [];
24
- currentView = grok.shell.tv;
24
+ currentView = grok.shell.v;
25
25
  });
26
26
 
27
27
  after(async () => {
28
28
  dfList.forEach((df: DG.DataFrame) => { grok.shell.closeTable(df);});
29
29
  tvList.forEach((tv: DG.TableView) => tv.close());
30
- currentView = grok.shell.tv;
30
+ grok.shell.v = currentView;
31
31
  });
32
32
 
33
33
  test('allPositions', async () => {
@@ -40,7 +40,7 @@ ATC-G-TTGC--
40
40
  seqCol.setTag(bio.TAGS.alphabet, bio.ALPHABET.DNA);
41
41
  seqCol.setTag(bio.TAGS.aligned, 'SEQ.MSA');
42
42
 
43
- const wlViewer: bio.WebLogo = (await df.plot.fromType('WebLogo')) as bio.WebLogo;
43
+ const wlViewer: bio.WebLogoViewer = (await df.plot.fromType('WebLogo')) as bio.WebLogoViewer;
44
44
  tv.dockManager.dock(wlViewer.root, DG.DOCK_TYPE.DOWN);
45
45
 
46
46
  tvList.push(tv);
@@ -94,8 +94,8 @@ ATC-G-TTGC--
94
94
  return i > 2;
95
95
  });
96
96
  df.filter.fireChanged();
97
- const wlViewer: bio.WebLogo = (await df.plot.fromType('WebLogo',
98
- {'shrinkEmptyTail': true})) as bio.WebLogo;
97
+ const wlViewer: bio.WebLogoViewer = (await df.plot.fromType('WebLogo',
98
+ {'shrinkEmptyTail': true})) as bio.WebLogoViewer;
99
99
  tv.dockManager.dock(wlViewer.root, DG.DOCK_TYPE.DOWN);
100
100
 
101
101
  tvList.push(tv);
@@ -135,8 +135,8 @@ ATC-G-TTGC--
135
135
  seqCol.setTag(bio.TAGS.alphabet, bio.ALPHABET.DNA);
136
136
  seqCol.setTag(bio.TAGS.aligned, 'SEQ.MSA');
137
137
 
138
- const wlViewer: bio.WebLogo = (await df.plot.fromType('WebLogo',
139
- {'skipEmptyPositions': true})) as bio.WebLogo;
138
+ const wlViewer: bio.WebLogoViewer = (await df.plot.fromType('WebLogo',
139
+ {'skipEmptyPositions': true})) as bio.WebLogoViewer;
140
140
  tv.dockManager.dock(wlViewer.root, DG.DOCK_TYPE.DOWN);
141
141
 
142
142
  tvList.push(tv);
@@ -4,11 +4,6 @@ import * as DG from 'datagrok-api/dg';
4
4
  import * as bio from '@datagrok-libraries/bio';
5
5
 
6
6
  import {after, before, category, test, expect, expectObject} from '@datagrok-libraries/utils/src/test';
7
- import {Nucleotides, NucleotidesPalettes} from '@datagrok-libraries/bio/src/nucleotides';
8
- import {Aminoacids, AminoacidsPalettes} from '@datagrok-libraries/bio/src/aminoacids';
9
- import {WebLogo} from '@datagrok-libraries/bio/src/viewers/web-logo';
10
- import {SeqPalette} from '@datagrok-libraries/bio/src/seq-palettes';
11
- import {UnknownSeqPalette} from '@datagrok-libraries/bio/src/unknown';
12
7
 
13
8
  category('WebLogo', () => {
14
9
  const csvDfN1: string = `seq
@@ -102,7 +97,7 @@ export async function _testGetAlphabetSimilarity() {
102
97
  'T': 2048,
103
98
  '-': 1000
104
99
  };
105
- const alphabet: Set<string> = new Set(Object.keys(Nucleotides.Names));
100
+ const alphabet: Set<string> = new Set(Object.keys(bio.Nucleotides.Names));
106
101
  const res = bio.getAlphabetSimilarity(freq, alphabet);
107
102
 
108
103
  expect(res > 0.6, true);
@@ -113,7 +108,7 @@ export async function _testPickupPaletteN1(csvDfN1: string) {
113
108
  const col: DG.Column = df.col('seq')!;
114
109
  const cp = bio.pickUpPalette(col);
115
110
 
116
- expect(cp instanceof NucleotidesPalettes, true);
111
+ expect(cp instanceof bio.NucleotidesPalettes, true);
117
112
  }
118
113
 
119
114
  export async function _testPickupPaletteN1e(csvDfN1e: string) {
@@ -121,7 +116,7 @@ export async function _testPickupPaletteN1e(csvDfN1e: string) {
121
116
  const col: DG.Column = df.col('seq')!;
122
117
  const cp = bio.pickUpPalette(col);
123
118
 
124
- expect(cp instanceof NucleotidesPalettes, true);
119
+ expect(cp instanceof bio.NucleotidesPalettes, true);
125
120
  }
126
121
 
127
122
  export async function _testPickupPaletteAA1(csvDfAA1: string) {
@@ -129,7 +124,7 @@ export async function _testPickupPaletteAA1(csvDfAA1: string) {
129
124
  const col: DG.Column = df.col('seq')!;
130
125
  const cp = bio.pickUpPalette(col);
131
126
 
132
- expect(cp instanceof AminoacidsPalettes, true);
127
+ expect(cp instanceof bio.AminoacidsPalettes, true);
133
128
  }
134
129
 
135
130
  export async function _testPickupPaletteX(csvDfX: string) {
@@ -137,13 +132,13 @@ export async function _testPickupPaletteX(csvDfX: string) {
137
132
  const col: DG.Column = df.col('seq')!;
138
133
  const cp = bio.pickUpPalette(col);
139
134
 
140
- expect(cp instanceof UnknownSeqPalette, true);
135
+ expect(cp instanceof bio.UnknownSeqPalette, true);
141
136
  }
142
137
 
143
138
  export async function _testPickupPaletteAA2(dfAA2: DG.DataFrame) {
144
139
  const seqCol: DG.Column = dfAA2.col('seq')!;
145
140
  const cp = bio.pickUpPalette(seqCol);
146
141
 
147
- expect(cp instanceof AminoacidsPalettes, true);
142
+ expect(cp instanceof bio.AminoacidsPalettes, true);
148
143
  }
149
144
 
@@ -50,6 +50,7 @@ export class VdRegionsViewer extends DG.JsViewer implements bio.IVdRegionsViewer
50
50
 
51
51
  public skipEmptyPositions: boolean;
52
52
  public positionWidth: number;
53
+ public positionHeight: string;
53
54
 
54
55
 
55
56
  public get df(): DG.DataFrame {
@@ -77,6 +78,8 @@ export class VdRegionsViewer extends DG.JsViewer implements bio.IVdRegionsViewer
77
78
 
78
79
  this.skipEmptyPositions = this.bool('skipEmptyPositions', false);
79
80
  this.positionWidth = this.float('positionWidth', 16);
81
+ this.positionHeight = this.string('positionHeight', bio.PositionHeight.Entropy,
82
+ {choices: Object.keys(bio.PositionHeight)});
80
83
  }
81
84
 
82
85
  public async init() {
@@ -139,6 +142,11 @@ export class VdRegionsViewer extends DG.JsViewer implements bio.IVdRegionsViewer
139
142
  await this.destroyView();
140
143
  await this.buildView();
141
144
  break;
145
+
146
+ case 'positionHeight':
147
+ await this.destroyView();
148
+ await this.buildView();
149
+ break;
142
150
  }
143
151
  }
144
152
  }
@@ -172,7 +180,7 @@ export class VdRegionsViewer extends DG.JsViewer implements bio.IVdRegionsViewer
172
180
  //#region -- View --
173
181
  private host: HTMLElement | null = null;
174
182
  private mainLayout: HTMLTableElement | null = null;
175
- private logos: { [chain: string]: bio.WebLogo }[] = [];
183
+ private logos: { [chain: string]: bio.WebLogoViewer }[] = [];
176
184
 
177
185
  private async destroyView(): Promise<void> {
178
186
  // TODO: Unsubscribe from and remove all view elements
@@ -199,7 +207,7 @@ export class VdRegionsViewer extends DG.JsViewer implements bio.IVdRegionsViewer
199
207
  this.logos = [];
200
208
 
201
209
  for (let orderI = 0; orderI < orderList.length; orderI++) {
202
- const regionChains: { [chain: string]: bio.WebLogo } = {};
210
+ const regionChains: { [chain: string]: bio.WebLogoViewer } = {};
203
211
  for (const chain of this.chains) {
204
212
  const region: bio.VdRegion | undefined = regionsFiltered
205
213
  .find((r) => r.order == orderList[orderI] && r.chain == chain);
@@ -210,7 +218,8 @@ export class VdRegionsViewer extends DG.JsViewer implements bio.IVdRegionsViewer
210
218
  fixWidth: true,
211
219
  skipEmptyPositions: this.skipEmptyPositions,
212
220
  positionWidth: this.positionWidth,
213
- })) as unknown as bio.WebLogo;
221
+ positionHeight: this.positionHeight,
222
+ })) as unknown as bio.WebLogoViewer;
214
223
  }
215
224
  // WebLogo creation fires onRootSizeChanged event even before control being added to this.logos
216
225
  this.logos[orderI] = regionChains;
@@ -235,7 +244,7 @@ export class VdRegionsViewer extends DG.JsViewer implements bio.IVdRegionsViewer
235
244
  })] : []),
236
245
  // List with controls for regions
237
246
  ...[...Array(orderList.length).keys()].map((orderI) => {
238
- const wl: bio.WebLogo = this.logos[orderI][chain];
247
+ const wl: bio.WebLogoViewer = this.logos[orderI][chain];
239
248
  wl.root.style.height = '100%';
240
249
 
241
250
  const resDiv = ui.div([wl.root]/*`${chain} ${regionsFiltered[rI]}`*/, {
@@ -183,20 +183,18 @@ class SeparatorFilter extends FastaFilter {
183
183
 
184
184
  class HelmFilter extends BioFilterBase {
185
185
  helmEditor: any;
186
- _filterPanel = ui.div('', {style: {width: '100px', height: '100px'}});
186
+ _filterPanel = ui.div('', {style: {cursor: 'pointer'}});
187
187
  helmSubstructure = '';
188
- editDiv = ui.divText('Click to edit', {style: {cursor: 'pointer'}});
189
188
 
190
189
  constructor() {
191
190
  super();
192
191
  this.init();
193
- ui.setUpdateIndicator(this._filterPanel, true);
194
192
  }
195
193
 
196
194
  async init() {
197
195
  this.helmEditor = await grok.functions.call('HELM:helmWebEditor');
198
- updateDivInnerHTML(this._filterPanel, this.editDiv);
199
- ui.setUpdateIndicator(this._filterPanel, false);
196
+ await ui.tools.waitForElementInDom(this._filterPanel);
197
+ this.updateFilterPanel();
200
198
  this._filterPanel.addEventListener('click', (event: MouseEvent) => {
201
199
  //@ts-ignore
202
200
  ui.dialog({showHeader: false, showFooter: true})
@@ -204,14 +202,16 @@ class HelmFilter extends BioFilterBase {
204
202
  .onOK(() => {
205
203
  const helmString = this.helmEditor
206
204
  .webEditor.canvas.getHelm(true).replace(/<\/span>/g, '').replace(/<span style='background:#bbf;'>/g, '');
207
- if (helmString) {
208
- updateDivInnerHTML(this._filterPanel, this.helmEditor.host);
209
- this.helmEditor.editor.setHelm(helmString);
210
- } else { updateDivInnerHTML(this._filterPanel, this.editDiv); }
205
+ this.updateFilterPanel(helmString);
211
206
  this.helmSubstructure = helmString;
212
207
  this.onChanged.next();
213
208
  }).show({modal: true, fullScreen: true});
214
209
  });
210
+ ui.onSizeChanged(this._filterPanel).subscribe((_) => {
211
+ const helmString = this.helmEditor
212
+ .webEditor.canvas.getHelm(true).replace(/<\/span>/g, '').replace(/<span style='background:#bbf;'>/g, '');
213
+ this.updateFilterPanel(helmString);
214
+ });
215
215
  }
216
216
 
217
217
  get filterPanel() {
@@ -225,4 +225,26 @@ class HelmFilter extends BioFilterBase {
225
225
  set substructure(s: string) {
226
226
  this.helmEditor.editor.setHelm(s);
227
227
  }
228
+
229
+ updateFilterPanel(helmString?: string) {
230
+ const width = this._filterPanel.parentElement!.clientWidth < 100 ? 100 :
231
+ this._filterPanel.parentElement!.clientWidth;
232
+ const height = width / 2;
233
+ if (!helmString) {
234
+ const editDivStyle = {style: {
235
+ width: `${width}px`,
236
+ height: `${height/2}px`,
237
+ textAlign: 'center',
238
+ verticalAlign: 'middle',
239
+ lineHeight: `${height/2}px`,
240
+ border: '1px solid #dbdcdf'
241
+ }};
242
+ const editDiv = ui.divText('Click to edit', editDivStyle);
243
+ updateDivInnerHTML(this._filterPanel, editDiv);
244
+ } else {
245
+ updateDivInnerHTML(this._filterPanel, this.helmEditor.host);
246
+ this.helmEditor.editor.setHelm(helmString);
247
+ this.helmEditor.resizeEditor(width, height);
248
+ }
249
+ }
228
250
  }