@datagrok/bio 1.1.0 → 1.2.0

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
@@ -2,7 +2,7 @@
2
2
  "name": "@datagrok/bio",
3
3
  "beta": false,
4
4
  "friendlyName": "Bio",
5
- "version": "1.1.0",
5
+ "version": "1.2.0",
6
6
  "description": "Bio is a [package](https://datagrok.ai/help/develop/develop#packages) for the [Datagrok](https://datagrok.ai) platform",
7
7
  "repository": {
8
8
  "type": "git",
@@ -0,0 +1,274 @@
1
+ import * as ui from 'datagrok-api/ui';
2
+ import * as grok from 'datagrok-api/grok';
3
+ import * as DG from 'datagrok-api/dg';
4
+
5
+ import {VdRegionType, VdRegion} from '@datagrok-libraries/bio/src/vd-regions';
6
+ import {WebLogo} from '@datagrok-libraries/bio/src/viewers/web-logo';
7
+
8
+ const vrt = VdRegionType;
9
+
10
+ // Positions of regions for numbering schemes
11
+ // http://www.bioinf.org.uk/abs/info.html
12
+
13
+ // const imgtRegions: VdRegion[] = [
14
+ // new VdRegion(vrt.FR, 'FR1', 'Light', 1, '1', '26'),
15
+ // new VdRegion(vrt.FR, 'FR1', 'Heavy', 1, '1', '26'),
16
+ //
17
+ // new VdRegion(vrt.CDR, 'CDR1', 'Light', 2, '27', '38'), // 27-32
18
+ // new VdRegion(vrt.CDR, 'CDR1', 'Heavy', 2, '27', '38'), // 27-32
19
+ //
20
+ // new VdRegion(vrt.FR, 'FR2', 'Light', 3, '39', '55'),
21
+ // new VdRegion(vrt.FR, 'FR2', 'Heavy', 3, '39', '55'),
22
+ //
23
+ // new VdRegion(vrt.CDR, 'CDR2', 'Light', 4, '56', '65'),
24
+ // new VdRegion(vrt.CDR, 'CDR2', 'Heavy', 4, '56', '65'),
25
+ //
26
+ // new VdRegion(vrt.FR, 'FR3', 'Light', 5, '66', '104'),
27
+ // new VdRegion(vrt.FR, 'FR3', 'Heavy', 5, '66', '104'),
28
+ //
29
+ // new VdRegion(vrt.CDR, 'CDR3', 'Light', 6, '105', '117'),
30
+ // new VdRegion(vrt.CDR, 'CDR3', 'Heavy', 6, '105', '117'),
31
+ //
32
+ // new VdRegion(vrt.FR, 'FR4', 'Light', 7, '118', null/*127*/),
33
+ // new VdRegion(vrt.FR, 'FR4', 'Heavy', 7, '118', null/*128*/),
34
+ // ];
35
+
36
+ /** Viewer with tabs based on description of chain regions.
37
+ * Used to define regions of an immunoglobulin LC.
38
+ */
39
+ export class VdRegionsViewer extends DG.JsViewer {
40
+ // private regionsDf: DG.DataFrame;
41
+ private regionsFg: DG.FilterGroup | null = null;
42
+ // private regionsTV: DG.TableView;
43
+ private regionsRoot: HTMLElement | null = null;
44
+
45
+ private isOpened: boolean = false;
46
+ private panelNode: DG.DockNode | null = null;
47
+
48
+ public regions: VdRegion[] = [];
49
+ public regionTypes: string[];
50
+ public chains: string[];
51
+ public sequenceColumnNamePostfix: string;
52
+
53
+ public get df(): DG.DataFrame {
54
+ return this.dataFrame;
55
+ }
56
+
57
+ // TODO: .onTableAttached is not calling on dataFrame set, onPropertyChanged also not calling
58
+ public async setDf(value: DG.DataFrame, regions: VdRegion[]) {
59
+ console.debug('VdRegionsViewer.setDf()');
60
+ await this.destroyView();
61
+ this.regions = regions;
62
+ this.dataFrame = value;
63
+ await this.buildView();
64
+ }
65
+
66
+ constructor() {
67
+ super();
68
+
69
+ // To prevent ambiguous numbering scheme in MLB
70
+ this.regionTypes = this.stringList('regionTypes', [vrt.CDR],
71
+ {choices: Object.values(vrt).filter((t) => t != vrt.Unknown)});
72
+ this.chains = this.stringList('chains', ['Heavy', 'Light'],
73
+ {choices: ['Heavy', 'Light']});
74
+ this.sequenceColumnNamePostfix = this.string('sequenceColumnNamePostfix', 'chain sequence');
75
+ }
76
+
77
+ public async init() {
78
+ //#region regionsDF with filter
79
+ // this.regionsDf = DG.DataFrame.fromObjects(this.regions);
80
+ // this.regionsDf.rows.filter((row) => row.name == 'CDR1');
81
+ // // To available options /
82
+ // this.regionsFg = (await this.regionsDf.plot.fromType(DG.VIEWER.FILTERS, {
83
+ // // columnNames: ['name',],
84
+ // showFilterCountsIndication: false,
85
+ // showHeader: false,
86
+ // showSearchBox: false,
87
+ // filters: [
88
+ // {type: DG.FILTER_TYPE.CATEGORICAL, column: 'type', label: 'Region name', showHistogram: false},
89
+ // {type: DG.FILTER_TYPE.CATEGORICAL, column: 'name', label: 'Region type', showHistogram: false},
90
+ // ],
91
+ // title: 'Regions filter',
92
+ // showTitle: true,
93
+ // description: 'Filter for regions of multiple alignment by IMGT nomenclature',
94
+ // someProperty: 'Hello',
95
+ // })) as DG.FilterGroup;
96
+
97
+ //#endregion regionsDF with filter
98
+
99
+ // this.mlbView.dockManager.dock(this.regionsFg.root, DG.DOCK_TYPE.LEFT, rootNode, 'Filter regions', 0.2);
100
+
101
+ this.subs.push(ui.onSizeChanged(this.root).subscribe(this.rootOnSizeChanged.bind(this)));
102
+ // rxjs.fromEvent(this.root, 'mousemove').subscribe(this.onMouseMoveRoot.bind(this));
103
+ this.root.addEventListener('mousemove', this.onMouseMoveRoot.bind(this));
104
+
105
+ await this.buildView();
106
+ }
107
+
108
+ public override async onTableAttached() {
109
+ await this.init();
110
+ }
111
+
112
+ public override async onPropertyChanged(property: DG.Property | null) {
113
+ super.onPropertyChanged(property);
114
+ if (property) {
115
+ switch (property.name) {
116
+ case 'regionTypes':
117
+ break;
118
+ case 'chains':
119
+ break;
120
+ case 'sequenceColumnNamePostfix':
121
+ break;
122
+ }
123
+ }
124
+ }
125
+
126
+
127
+ public async reset() {
128
+
129
+ }
130
+
131
+ public async open(mlbView: DG.TableView) {
132
+ if (!this.isOpened) {
133
+ this.isOpened = true;
134
+ this.panelNode = mlbView.dockManager.dock(this.root, DG.DOCK_TYPE.TOP, null, 'Regions', 0.2);
135
+ }
136
+ }
137
+
138
+ public async show(mlbView: DG.TableView) {
139
+
140
+ }
141
+
142
+ // #region -- Handle controls' events --
143
+
144
+ private resizing: boolean = false;
145
+
146
+ private rootOnSizeChanged(args: any): void {
147
+ this.calcSize();
148
+ }
149
+
150
+ // #endregion
151
+
152
+ //#region -- View --
153
+ private host: HTMLElement | null = null;
154
+ private mainLayout: HTMLTableElement | null = null;
155
+ private logos: { [chain: string]: WebLogo }[] = [];
156
+
157
+ private async destroyView(): Promise<void> {
158
+ // TODO: Unsubscribe from and remove all view elements
159
+ console.debug(`VdRegionsViewer.destroyView( mainLayout = ${!this.mainLayout ? 'none' : 'value'} )`);
160
+ if (this.mainLayout != null) {
161
+ // this.root.removeChild(this.host);
162
+ this.mainLayout.remove();
163
+ this.host!.remove();
164
+ this.host = null;
165
+ this.mainLayout = null;
166
+ }
167
+ }
168
+
169
+ private async buildView(): Promise<void> {
170
+ console.debug('VdRegionsViewer.buildView() start');
171
+
172
+ const colNames: { [chain: string]: string } = Object.assign({},
173
+ ...this.chains.map((chain) => ({[chain]: `${chain} ${this.sequenceColumnNamePostfix}`})));
174
+
175
+ const regionsFiltered: VdRegion[] = this.regions.filter((r: VdRegion) => this.regionTypes.includes(r.type));
176
+
177
+ const orderList: number[] = Array.from(new Set(regionsFiltered.map((r) => r.order))).sort();
178
+
179
+ this.logos = [];
180
+
181
+ for (let orderI = 0; orderI < orderList.length; orderI++) {
182
+ const regionChains: { [chain: string]: WebLogo } = {};
183
+ for (const chain of this.chains) {
184
+ const region: VdRegion | undefined = regionsFiltered
185
+ .find((r) => r.order == orderList[orderI] && r.chain == chain);
186
+ regionChains[chain] = (await this.dataFrame.plot.fromType('WebLogo', {
187
+ sequenceColumnName: colNames[chain],
188
+ startPositionName: region!.positionStartName,
189
+ endPositionName: region!.positionEndName,
190
+ fixWidth: true,
191
+ })) as unknown as WebLogo;
192
+ }
193
+ // WebLogo creation fires onRootSizeChanged event even before control being added to this.logos
194
+ this.logos[orderI] = regionChains;
195
+ }
196
+
197
+ // ui.tableFromMap()
198
+ // DG.HtmlTable.create()
199
+ this.mainLayout = ui.table(
200
+ this.chains,
201
+ (chain) => {
202
+ const elements = [
203
+ // This is chain label
204
+ ...(orderList.length > 0 ? [ui.div(chain, {
205
+ style: {
206
+ transform: 'rotate(-90deg)',
207
+ font: '12px Roboto, Roboto Local, sans-serif',
208
+ textAlign: 'center',
209
+ width: '16px',
210
+ marginTop: '24px',
211
+ marginLeft: '6px',
212
+ }
213
+ })] : []),
214
+ // List with controls for regions
215
+ ...[...Array(orderList.length).keys()].map((orderI) => {
216
+ const wl: WebLogo = this.logos[orderI][chain];
217
+ wl.root.style.height = '100%';
218
+
219
+ const resDiv = ui.div([wl.root]/*`${chain} ${regionsFiltered[rI]}`*/, {
220
+ style: {
221
+ // height: '100%',
222
+ marginTop: '4px',
223
+ marginBottom: '4px',
224
+ }
225
+ });
226
+
227
+ return resDiv;
228
+ })];
229
+ return elements;
230
+ },
231
+ ['', ...[...Array(orderList.length).keys()].map(
232
+ (orderI: number) => regionsFiltered.find(
233
+ (r: VdRegion) => r.order == orderList[orderI] && r.chain == this.chains[0]
234
+ )!.name || 'Name')]
235
+ );
236
+ this.mainLayout.className = 'mlb-vd-regions-viewer-table2';
237
+ // this.mainLayout.style.background = '#EEEEFF';
238
+ // this.mainLayout.style.height = '100%';
239
+ // this.mainLayout.style.border = '1px solid black';
240
+
241
+ const color: string = `#ffbb${Math.ceil(Math.random() * 255).toString(16)}`;
242
+ this.host = ui.box(this.mainLayout,
243
+ {/*style: {backgroundColor: color}*/});
244
+ this.root.appendChild(this.host);
245
+ this.root.style.overflowX = 'auto';
246
+
247
+ this.calcSize();
248
+
249
+ console.debug('VdRegionsViewer.buildView() end');
250
+ }
251
+
252
+ private calcSize() {
253
+ const logoHeight = (this.root.clientHeight - 54) / this.chains.length;
254
+
255
+ const maxHeight: number = Math.min(logoHeight,
256
+ Math.max(...this.logos.map((wlDict) =>
257
+ Math.max(...Object.values(wlDict).map((wl) => wl.maxHeight))))
258
+ );
259
+
260
+ for (let orderI = 0; orderI < this.logos.length; orderI++) {
261
+ for (let chainI = 0; chainI < this.chains.length; chainI++) {
262
+ const chain: string = this.chains[chainI];
263
+ this.logos[orderI][chain].root.style.height = `${maxHeight}px`;
264
+ }
265
+ }
266
+ }
267
+
268
+ //#endregion -- View --
269
+
270
+ private onMouseMoveRoot(e: MouseEvent) {
271
+ // ui.tooltip.show('text', e.x + 8, e.y + 8,);
272
+ // console.log(`onMouseMoveRoot.( x: ${e.x}, y: ${e.y} )`);
273
+ }
274
+ }
@@ -1,4 +1,4 @@
1
- <html><head><meta charset="utf-8"/><title>Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=3109311545e4. Commit 04060aee.</title><style type="text/css">html,
1
+ <html><head><meta charset="utf-8"/><title>Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=3109311545e4. Commit fcd6a7f5.</title><style type="text/css">html,
2
2
  body {
3
3
  font-family: Arial, Helvetica, sans-serif;
4
4
  font-size: 1rem;
@@ -229,7 +229,7 @@ header {
229
229
  font-size: 1rem;
230
230
  padding: 0 0.5rem;
231
231
  }
232
- </style></head><body><div id="jesthtml-content"><header><h1 id="title">Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=3109311545e4. Commit 04060aee.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-06-22 13:34:16</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts</div><div class="suite-time warn">17.821s</div></div><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">passed</div><div class="test-duration">6.52s</div></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/Bio/src/__jest__/test-node.ts:63:11)
232
+ </style></head><body><div id="jesthtml-content"><header><h1 id="title">Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=3109311545e4. Commit fcd6a7f5.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-06-23 09:07:04</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed">1 passed</div><div class="summary-failed summary-empty">0 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts</div><div class="suite-time warn">20.235s</div></div><div class="suite-tests"><div class="test-result passed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">passed</div><div class="test-duration">6.845s</div></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/Bio/src/__jest__/test-node.ts:63:11)
233
233
  at Generator.next (&lt;anonymous&gt;)
234
234
  at fulfilled (/home/runner/work/public/public/packages/Bio/src/__jest__/test-node.ts:28:58)
235
235
  at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Using web root: http://localhost:8080</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts:24:11