@datagrok/bio 2.22.4 → 2.22.5

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": "Davit Rizhinashvili",
6
6
  "email": "drizhinashvili@datagrok.ai"
7
7
  },
8
- "version": "2.22.4",
8
+ "version": "2.22.5",
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.54.4",
47
+ "@datagrok-libraries/bio": "^5.54.5",
48
48
  "@datagrok-libraries/chem-meta": "^1.2.7",
49
49
  "@datagrok-libraries/math": "^1.2.4",
50
50
  "@datagrok-libraries/ml": "^6.10.4",
@@ -3,7 +3,7 @@ import * as DG from 'datagrok-api/dg';
3
3
  import {GridCell} from 'datagrok-api/dg';
4
4
  import * as ui from 'datagrok-api/ui';
5
5
  import {ALPHABET, monomerToShort} from '@datagrok-libraries/bio/src/utils/macromolecule';
6
- import {GAP_SYMBOL, TAGS as bioTAGS,} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
6
+ import {GAP_SYMBOL, MONOMER_MOTIF_SPLITTER, TAGS as bioTAGS,} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
7
7
  import {MONOMER_RENDERER_TAGS} from '@datagrok-libraries/bio/src/utils/cell-renderer';
8
8
  import {getGridCellColTemp} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
9
9
 
@@ -16,6 +16,8 @@ const Tags = new class {
16
16
  tooltipHandlerTemp = 'tooltip-handler.Monomer';
17
17
  }();
18
18
 
19
+ const DASH_GAP_SYMBOL = '-';
20
+
19
21
  export class MonomerCellRendererBack extends CellRendererWithMonomerLibBackBase {
20
22
  constructor(gridCol: DG.GridColumn | null, tableCol: DG.Column) {
21
23
  super(gridCol, tableCol);
@@ -25,39 +27,51 @@ export class MonomerCellRendererBack extends CellRendererWithMonomerLibBackBase
25
27
  x: number, y: number, w: number, h: number, gridCell: DG.GridCell, cellStyle: DG.GridCellStyle
26
28
  ): void {
27
29
  g.save();
30
+ // clip the cell
31
+ g.beginPath();
32
+ g.rect(x, y, w, h);
33
+ g.clip();
28
34
  try {
29
35
  if (!gridCell.isTableCell) return;
30
36
  const applyToBackground = gridCell.cell?.column && gridCell.cell.column?.dart && gridCell.cell.column.getTag(MONOMER_RENDERER_TAGS.applyToBackground) === 'true';
31
37
 
32
38
  g.font = `12px monospace`;
33
39
  g.textBaseline = 'middle';
34
- g.textAlign = 'center';
35
-
36
- const symbol: string = gridCell.cell.value;
37
- if (!symbol || symbol == GAP_SYMBOL) return;
38
-
39
- let textcolor = undefinedColor;
40
- let backgroundcolor = 'rgb(255, 255, 255)';
41
- if (this.monomerLib) {
42
- const alphabet = this.tableCol.getTag(bioTAGS.alphabet);
43
- const biotype = alphabet === ALPHABET.RNA || alphabet === ALPHABET.DNA ? HelmTypes.NUCLEOTIDE : HelmTypes.AA;
44
- if (applyToBackground) {
45
- const colors = this.monomerLib.getMonomerColors(biotype, symbol);
46
- textcolor = colors?.textcolor ?? textcolor;
47
- backgroundcolor = colors?.backgroundcolor ?? backgroundcolor;
48
- } else
49
- textcolor = this.monomerLib.getMonomerTextColor(biotype, symbol);
50
- }
40
+ g.textAlign = 'left';
51
41
 
42
+ let value: string = gridCell.cell.value;
43
+ if (!value || value === GAP_SYMBOL)
44
+ value = DASH_GAP_SYMBOL;
45
+ const symbols = value.split(MONOMER_MOTIF_SPLITTER).map((s) => !s || s === GAP_SYMBOL ? DASH_GAP_SYMBOL : s.trim());
52
46
  //cell width of monomer should dictate how many characters can be displayed
53
47
  // for width 40, 6 characters can be displayed (0.15 is 6 / 40)
54
- const maxChars = Math.max(2, Math.floor(w * 0.15));
55
- if (applyToBackground) {
56
- g.fillStyle = backgroundcolor;
57
- g.fillRect(x, y, w, h);
48
+ const shortSymbols = symbols.map((s) => monomerToShort(s, Math.max(2, Math.floor(w * 0.15 / symbols.length))));
49
+ const symbolWidths = shortSymbols.map((s) => g.measureText(s).width);
50
+ const totalWidth = symbolWidths.reduce((a, b) => a + b, 0);
51
+ const xOffset = (w - totalWidth) / 2;
52
+ let xPos = x + xOffset;
53
+ const alphabet = this.tableCol.getTag(bioTAGS.alphabet);
54
+ const biotype = alphabet === ALPHABET.RNA || alphabet === ALPHABET.DNA ? HelmTypes.NUCLEOTIDE : HelmTypes.AA;
55
+ for (let i = 0; i < shortSymbols.length; i++) {
56
+ const symbol: string = symbols[i];
57
+ let textcolor = undefinedColor;
58
+ let backgroundcolor = 'rgb(255, 255, 255)';
59
+ if (this.monomerLib) {
60
+ if (applyToBackground) {
61
+ const colors = this.monomerLib.getMonomerColors(biotype, symbol);
62
+ textcolor = colors?.textcolor ?? textcolor;
63
+ backgroundcolor = colors?.backgroundcolor ?? backgroundcolor;
64
+ } else
65
+ textcolor = this.monomerLib.getMonomerTextColor(biotype, symbol);
66
+ }
67
+ if (applyToBackground && symbols.length == 1) {
68
+ g.fillStyle = backgroundcolor;
69
+ g.fillRect(x, y, w, h);
70
+ }
71
+ g.fillStyle = textcolor;
72
+ g.fillText(shortSymbols[i], xPos, y + (h / 2), w);
73
+ xPos += symbolWidths[i];
58
74
  }
59
- g.fillStyle = textcolor;
60
- g.fillText(monomerToShort(symbol, maxChars), x + (w / 2), y + (h / 2), w);
61
75
  } finally {
62
76
  g.restore();
63
77
  }
@@ -70,12 +84,12 @@ export class MonomerCellRendererBack extends CellRendererWithMonomerLibBackBase
70
84
  ) return false;
71
85
 
72
86
  const alphabet = gridCell.tableColumn.getTag(bioTAGS.alphabet) as ALPHABET;
73
- const monomerName = gridCell.cell.value;
87
+ const monomerName: string = gridCell.cell.value;
74
88
  const canvasClientRect = gridCell.grid.canvas.getBoundingClientRect();
75
89
  const x1 = gridCell.bounds.right + canvasClientRect.left - 4;
76
90
  const y1 = gridCell.bounds.bottom + canvasClientRect.top - 4;
77
91
 
78
- if (monomerName == GAP_SYMBOL) {
92
+ if (!monomerName || monomerName == GAP_SYMBOL || monomerName == DASH_GAP_SYMBOL) {
79
93
  ui.tooltip.show(ui.divText('gap'), x1, y1);
80
94
  return true;
81
95
  }
@@ -86,7 +100,18 @@ export class MonomerCellRendererBack extends CellRendererWithMonomerLibBackBase
86
100
  }
87
101
 
88
102
  const biotype = alphabet === ALPHABET.RNA || alphabet === ALPHABET.DNA ? HelmTypes.NUCLEOTIDE : HelmTypes.AA;
89
- const tooltipEl = this.monomerLib.getTooltip(biotype, monomerName);
103
+ const tooltipEls = monomerName.split(MONOMER_MOTIF_SPLITTER)
104
+ .map((s) => !s || s === GAP_SYMBOL || s === DASH_GAP_SYMBOL ? ui.divText('gap') : this.monomerLib!.getTooltip(biotype, s));
105
+ const tooltipEl = ui.divH(tooltipEls, {style: {alignItems: 'top'}});
106
+ // tooltip max width is 600px, so we need to shrink the canvases a bit if needed. by default, it is 250px
107
+ const canvases = Array.from(tooltipEl.querySelectorAll('canvas'));
108
+ if (canvases.length > 2) {
109
+ const side = Math.floor(550 / canvases.length);
110
+ canvases.forEach((c) => {
111
+ c.style.setProperty('max-width', `${side}px`, 'important');
112
+ c.style.setProperty('max-height', `${side}px`, 'important');
113
+ });
114
+ }
90
115
  ui.tooltip.show(tooltipEl, x1, y1);
91
116
 
92
117
  return true; // To prevent default tooltip behaviour