@datagrok/bio 2.1.12 → 2.4.2
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/README.md +11 -12
- package/css/helm.css +10 -0
- package/detectors.js +83 -59
- package/dist/package-test.js +2 -13168
- package/dist/package-test.js.map +1 -0
- package/dist/package.js +2 -10560
- package/dist/package.js.map +1 -0
- package/dockerfiles/Dockerfile +86 -0
- package/files/icons/composition-analysis.svg +17 -0
- package/files/icons/sequence-diversity-viewer.svg +4 -0
- package/files/icons/sequence-similarity-viewer.svg +4 -0
- package/files/icons/vdregions-viewer.svg +22 -0
- package/files/icons/weblogo-viewer.svg +7 -0
- package/files/tests/testUrl.csv +11 -0
- package/files/tests/toAtomicLevelTest.csv +4 -0
- package/package.json +24 -25
- package/src/analysis/sequence-activity-cliffs.ts +11 -9
- package/src/analysis/sequence-search-base-viewer.ts +2 -1
- package/src/analysis/sequence-similarity-viewer.ts +3 -3
- package/src/analysis/sequence-space.ts +2 -1
- package/src/calculations/monomerLevelMols.ts +4 -4
- package/src/package-test.ts +9 -2
- package/src/package.ts +215 -131
- package/src/substructure-search/substructure-search.ts +19 -16
- package/src/tests/Palettes-test.ts +1 -1
- package/src/tests/WebLogo-positions-test.ts +113 -57
- package/src/tests/_first-tests.ts +9 -0
- package/src/tests/activity-cliffs-tests.ts +8 -7
- package/src/tests/activity-cliffs-utils.ts +17 -9
- package/src/tests/bio-tests.ts +4 -5
- package/src/tests/checkInputColumn-tests.ts +1 -1
- package/src/tests/converters-test.ts +52 -17
- package/src/tests/detectors-benchmark-tests.ts +3 -2
- package/src/tests/detectors-tests.ts +177 -172
- package/src/tests/fasta-export-tests.ts +1 -1
- package/src/tests/monomer-libraries-tests.ts +34 -0
- package/src/tests/pepsea-tests.ts +21 -0
- package/src/tests/renderers-test.ts +21 -19
- package/src/tests/sequence-space-test.ts +6 -4
- package/src/tests/similarity-diversity-tests.ts +4 -4
- package/src/tests/splitters-test.ts +4 -5
- package/src/tests/substructure-filters-tests.ts +23 -1
- package/src/tests/utils/sequences-generators.ts +1 -1
- package/src/tests/utils.ts +2 -1
- package/src/tests/viewers.ts +16 -0
- package/src/utils/cell-renderer.ts +88 -35
- package/src/utils/constants.ts +7 -6
- package/src/utils/convert.ts +8 -2
- package/src/utils/monomer-lib.ts +174 -0
- package/src/utils/multiple-sequence-alignment.ts +44 -20
- package/src/utils/pepsea.ts +78 -0
- package/src/utils/save-as-fasta.ts +2 -1
- package/src/utils/ui-utils.ts +15 -3
- package/src/viewers/vd-regions-viewer.ts +113 -72
- package/src/viewers/web-logo-viewer.ts +1031 -0
- package/src/widgets/bio-substructure-filter.ts +38 -24
- package/tsconfig.json +71 -72
- package/webpack.config.js +4 -11
- package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +0 -9039
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import * as ui from 'datagrok-api/ui';
|
|
2
|
-
import * as grok from 'datagrok-api/grok';
|
|
3
2
|
import * as DG from 'datagrok-api/dg';
|
|
4
3
|
|
|
5
|
-
import
|
|
4
|
+
import * as rxjs from 'rxjs';
|
|
5
|
+
import {FilterSources, WebLogoViewer, PROPS as wlPROPS} from '../viewers/web-logo-viewer';
|
|
6
|
+
import {
|
|
7
|
+
VdRegionsPropsDefault, VdRegionsProps, IVdRegionsViewer,
|
|
8
|
+
VdRegion, VdRegionType
|
|
9
|
+
} from '@datagrok-libraries/bio/src/viewers/vd-regions';
|
|
10
|
+
import {PositionHeight} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
11
|
+
import {Unsubscribable} from 'rxjs';
|
|
6
12
|
|
|
7
13
|
const vrt = VdRegionType;
|
|
8
14
|
|
|
@@ -36,6 +42,8 @@ const vrt = VdRegionType;
|
|
|
36
42
|
* Used to define regions of an immunoglobulin LC.
|
|
37
43
|
*/
|
|
38
44
|
export class VdRegionsViewer extends DG.JsViewer implements IVdRegionsViewer {
|
|
45
|
+
private viewed: boolean = false;
|
|
46
|
+
|
|
39
47
|
// private regionsDf: DG.DataFrame;
|
|
40
48
|
private regionsFg: DG.FilterGroup | null = null;
|
|
41
49
|
// private regionsTV: DG.TableView;
|
|
@@ -45,42 +53,28 @@ export class VdRegionsViewer extends DG.JsViewer implements IVdRegionsViewer {
|
|
|
45
53
|
private panelNode: DG.DockNode | null = null;
|
|
46
54
|
|
|
47
55
|
public regions: VdRegion[] = [];
|
|
48
|
-
public regionTypes:
|
|
56
|
+
public regionTypes: VdRegionType[];
|
|
49
57
|
public chains: string[];
|
|
50
|
-
public sequenceColumnNamePostfix: string;
|
|
58
|
+
// public sequenceColumnNamePostfix: string;
|
|
51
59
|
|
|
52
60
|
public skipEmptyPositions: boolean;
|
|
53
61
|
public positionWidth: number;
|
|
54
|
-
public positionHeight:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
public get df(): DG.DataFrame {
|
|
58
|
-
return this.dataFrame;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// TODO: .onTableAttached is not calling on dataFrame set, onPropertyChanged also not calling
|
|
62
|
-
public async setDf(value: DG.DataFrame, regions: VdRegion[]) {
|
|
63
|
-
console.debug('VdRegionsViewer.setDf()');
|
|
64
|
-
await this.destroyView();
|
|
65
|
-
this.regions = regions;
|
|
66
|
-
this.dataFrame = value;
|
|
67
|
-
await this.buildView();
|
|
68
|
-
}
|
|
62
|
+
public positionHeight: PositionHeight;
|
|
69
63
|
|
|
70
64
|
constructor() {
|
|
71
65
|
super();
|
|
72
66
|
|
|
73
67
|
// To prevent ambiguous numbering scheme in MLB
|
|
74
68
|
this.regionTypes = this.stringList('regionTypes', [vrt.CDR],
|
|
75
|
-
{choices: Object.values(vrt).filter((t) => t != vrt.Unknown)});
|
|
69
|
+
{choices: Object.values(vrt).filter((t) => t != vrt.Unknown)}) as VdRegionType[];
|
|
76
70
|
this.chains = this.stringList('chains', ['Heavy', 'Light'],
|
|
77
71
|
{choices: ['Heavy', 'Light']});
|
|
78
|
-
this.sequenceColumnNamePostfix = this.string('sequenceColumnNamePostfix', 'chain sequence');
|
|
72
|
+
// this.sequenceColumnNamePostfix = this.string('sequenceColumnNamePostfix', 'chain sequence');
|
|
79
73
|
|
|
80
74
|
this.skipEmptyPositions = this.bool('skipEmptyPositions', false);
|
|
81
75
|
this.positionWidth = this.float('positionWidth', 16);
|
|
82
76
|
this.positionHeight = this.string('positionHeight', PositionHeight.Entropy,
|
|
83
|
-
{choices: Object.keys(PositionHeight)});
|
|
77
|
+
{choices: Object.keys(PositionHeight)}) as PositionHeight;
|
|
84
78
|
}
|
|
85
79
|
|
|
86
80
|
public async init() {
|
|
@@ -108,18 +102,30 @@ export class VdRegionsViewer extends DG.JsViewer implements IVdRegionsViewer {
|
|
|
108
102
|
// this.mlbView.dockManager.dock(this.regionsFg.root, DG.DOCK_TYPE.LEFT, rootNode, 'Filter regions', 0.2);
|
|
109
103
|
|
|
110
104
|
this.subs.push(ui.onSizeChanged(this.root).subscribe(this.rootOnSizeChanged.bind(this)));
|
|
111
|
-
|
|
112
|
-
this.root.addEventListener('mousemove', this.onMouseMoveRoot.bind(this));
|
|
105
|
+
this.subs.push(rxjs.fromEvent<MouseEvent>(this.root, 'mousemove').subscribe(this.rootOnMouseMove.bind(this)));
|
|
113
106
|
|
|
114
|
-
await this.buildView();
|
|
107
|
+
// await this.buildView('init'); // init
|
|
115
108
|
}
|
|
116
109
|
|
|
117
110
|
public override async onTableAttached() {
|
|
118
|
-
|
|
111
|
+
const superOnTableAttached = super.onTableAttached.bind(this);
|
|
112
|
+
this.viewPromise = this.viewPromise.then(async () => { // onTableAttached
|
|
113
|
+
superOnTableAttached();
|
|
114
|
+
if (!this.viewed) {
|
|
115
|
+
await this.buildView('onTableAttached'); // onTableAttached
|
|
116
|
+
this.viewed = true;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
public override
|
|
121
|
+
public override onPropertyChanged(property: DG.Property | null): void {
|
|
122
122
|
super.onPropertyChanged(property);
|
|
123
|
+
|
|
124
|
+
if (!property) {
|
|
125
|
+
console.warn('Bio: VdRegionsViewer.onPropertyChanged() property is null');
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
123
129
|
if (property) {
|
|
124
130
|
switch (property.name) {
|
|
125
131
|
case 'regionTypes':
|
|
@@ -128,7 +134,6 @@ export class VdRegionsViewer extends DG.JsViewer implements IVdRegionsViewer {
|
|
|
128
134
|
break;
|
|
129
135
|
case 'sequenceColumnNamePostfix':
|
|
130
136
|
break;
|
|
131
|
-
case 'skipEmptyPositions':
|
|
132
137
|
// for (let orderI = 0; orderI < this.logos.length; orderI++) {
|
|
133
138
|
// for (let chainI = 0; chainI < this.chains.length; chainI++) {
|
|
134
139
|
// const chain: string = this.chains[chainI];
|
|
@@ -136,56 +141,72 @@ export class VdRegionsViewer extends DG.JsViewer implements IVdRegionsViewer {
|
|
|
136
141
|
// }
|
|
137
142
|
// }
|
|
138
143
|
// this.calcSize();
|
|
139
|
-
await this.destroyView();
|
|
140
|
-
await this.buildView();
|
|
141
|
-
break;
|
|
142
|
-
case 'positionWidth':
|
|
143
|
-
await this.destroyView();
|
|
144
|
-
await this.buildView();
|
|
145
|
-
break;
|
|
146
|
-
|
|
147
|
-
case 'positionHeight':
|
|
148
|
-
await this.destroyView();
|
|
149
|
-
await this.buildView();
|
|
150
|
-
break;
|
|
151
144
|
}
|
|
152
145
|
}
|
|
153
|
-
}
|
|
154
146
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (!this.isOpened) {
|
|
162
|
-
this.isOpened = true;
|
|
163
|
-
this.panelNode = mlbView.dockManager.dock(this.root, DG.DOCK_TYPE.TOP, null, 'Regions', 0.2);
|
|
147
|
+
switch (property.name) {
|
|
148
|
+
case 'skipEmptyPositions':
|
|
149
|
+
case 'positionWidth':
|
|
150
|
+
case 'positionHeight':
|
|
151
|
+
this.setData(this.dataFrame, this.regions); // onPropertyChanged
|
|
152
|
+
break;
|
|
164
153
|
}
|
|
165
154
|
}
|
|
166
155
|
|
|
167
|
-
|
|
156
|
+
// -- Data --
|
|
168
157
|
|
|
169
|
-
|
|
158
|
+
// TODO: .onTableAttached is not calling on dataFrame set, onPropertyChanged also not calling
|
|
159
|
+
public setData(mlbDf: DG.DataFrame, regions: VdRegion[]) {
|
|
160
|
+
console.debug('Bio: VdRegionsViewer.setData()');
|
|
161
|
+
this.viewPromise = this.viewPromise.then(async () => { // setData
|
|
162
|
+
if (this.viewed) {
|
|
163
|
+
await this.destroyView('setData'); // setData
|
|
164
|
+
this.viewed = false;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
170
167
|
|
|
171
|
-
|
|
168
|
+
this.regions = regions;
|
|
169
|
+
this.dataFrame = mlbDf; // causes detach and onTableAttached
|
|
172
170
|
|
|
173
|
-
|
|
171
|
+
this.viewPromise = this.viewPromise.then(async () => { // setData
|
|
172
|
+
if (!this.viewed) {
|
|
173
|
+
await this.buildView('setData'); // setData
|
|
174
|
+
this.viewed = true;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
174
178
|
|
|
175
|
-
|
|
176
|
-
|
|
179
|
+
override detach() {
|
|
180
|
+
const superDetach = super.detach.bind(this);
|
|
181
|
+
this.viewPromise = this.viewPromise.then(async () => { // detach
|
|
182
|
+
if (this.viewed) {
|
|
183
|
+
await this.destroyView('detach'); // detach
|
|
184
|
+
this.viewed = false;
|
|
185
|
+
}
|
|
186
|
+
superDetach();
|
|
187
|
+
});
|
|
177
188
|
}
|
|
178
189
|
|
|
179
|
-
//
|
|
190
|
+
// -- View --
|
|
191
|
+
|
|
192
|
+
private viewPromise: Promise<void> = Promise.resolve();
|
|
180
193
|
|
|
181
|
-
//#region -- View --
|
|
182
194
|
private host: HTMLElement | null = null;
|
|
195
|
+
private filterSourceInput: DG.InputBase<boolean | null> | null = null;
|
|
183
196
|
private mainLayout: HTMLTableElement | null = null;
|
|
184
197
|
private logos: { [chain: string]: WebLogoViewer }[] = [];
|
|
185
198
|
|
|
186
|
-
private
|
|
199
|
+
private viewSubs: Unsubscribable[] = [];
|
|
200
|
+
|
|
201
|
+
private async destroyView(purpose: string): Promise<void> {
|
|
187
202
|
// TODO: Unsubscribe from and remove all view elements
|
|
188
|
-
console.debug(`VdRegionsViewer.destroyView( mainLayout = ${!this.mainLayout ? 'none' : 'value'} )`
|
|
203
|
+
console.debug(`Bio: VdRegionsViewer.destroyView( mainLayout = ${!this.mainLayout ? 'none' : 'value'} ), ` +
|
|
204
|
+
`purpose = '${purpose}'`);
|
|
205
|
+
if (this.filterSourceInput) {
|
|
206
|
+
//
|
|
207
|
+
ui.empty(this.filterSourceInput.root);
|
|
208
|
+
}
|
|
209
|
+
|
|
189
210
|
if (this.mainLayout != null) {
|
|
190
211
|
// this.root.removeChild(this.host);
|
|
191
212
|
this.mainLayout.remove();
|
|
@@ -193,27 +214,24 @@ export class VdRegionsViewer extends DG.JsViewer implements IVdRegionsViewer {
|
|
|
193
214
|
this.host = null;
|
|
194
215
|
this.mainLayout = null;
|
|
195
216
|
}
|
|
196
|
-
}
|
|
197
217
|
|
|
198
|
-
|
|
199
|
-
|
|
218
|
+
for (const sub of this.viewSubs) sub.unsubscribe();
|
|
219
|
+
}
|
|
200
220
|
|
|
201
|
-
|
|
202
|
-
|
|
221
|
+
private async buildView(purpose: string): Promise<void> {
|
|
222
|
+
console.debug(`Bio: VdRegionsViewer.buildView() begin, ` + `purpose = '${purpose}'`);
|
|
203
223
|
|
|
204
224
|
const regionsFiltered: VdRegion[] = this.regions.filter((r: VdRegion) => this.regionTypes.includes(r.type));
|
|
205
|
-
|
|
206
225
|
const orderList: number[] = Array.from(new Set(regionsFiltered.map((r) => r.order))).sort();
|
|
207
226
|
|
|
208
227
|
this.logos = [];
|
|
209
|
-
|
|
210
228
|
for (let orderI = 0; orderI < orderList.length; orderI++) {
|
|
211
229
|
const regionChains: { [chain: string]: WebLogoViewer } = {};
|
|
212
230
|
for (const chain of this.chains) {
|
|
213
231
|
const region: VdRegion | undefined = regionsFiltered
|
|
214
232
|
.find((r) => r.order == orderList[orderI] && r.chain == chain);
|
|
215
233
|
regionChains[chain] = (await this.dataFrame.plot.fromType('WebLogo', {
|
|
216
|
-
sequenceColumnName:
|
|
234
|
+
sequenceColumnName: region!.sequenceColumnName,
|
|
217
235
|
startPositionName: region!.positionStartName,
|
|
218
236
|
endPositionName: region!.positionEndName,
|
|
219
237
|
fixWidth: true,
|
|
@@ -270,15 +288,21 @@ export class VdRegionsViewer extends DG.JsViewer implements IVdRegionsViewer {
|
|
|
270
288
|
// this.mainLayout.style.height = '100%';
|
|
271
289
|
// this.mainLayout.style.border = '1px solid black';
|
|
272
290
|
|
|
291
|
+
this.filterSourceInput = ui.boolInput('', false, this.filterSourceInputOnValueChanged.bind(this));
|
|
292
|
+
this.filterSourceInput.root.style.position = 'absolute';
|
|
293
|
+
this.filterSourceInput.root.style.left = '10px';
|
|
294
|
+
this.filterSourceInput.root.style.top = '-3px';
|
|
295
|
+
ui.tooltip.bind(this.filterSourceInput.root, 'Check to filter sequences for selected VRs');
|
|
296
|
+
|
|
273
297
|
const color: string = `#ffbb${Math.ceil(Math.random() * 255).toString(16)}`;
|
|
274
|
-
this.host = ui.
|
|
298
|
+
this.host = ui.div([this.mainLayout, this.filterSourceInput!.root],
|
|
275
299
|
{/*style: {backgroundColor: color}*/});
|
|
276
300
|
this.root.appendChild(this.host);
|
|
277
301
|
this.root.style.overflowX = 'auto';
|
|
278
302
|
|
|
279
303
|
this.calcSize();
|
|
280
304
|
|
|
281
|
-
console.debug('VdRegionsViewer.buildView() end');
|
|
305
|
+
console.debug('Bio: VdRegionsViewer.buildView() end');
|
|
282
306
|
}
|
|
283
307
|
|
|
284
308
|
private calcSize() {
|
|
@@ -297,10 +321,27 @@ export class VdRegionsViewer extends DG.JsViewer implements IVdRegionsViewer {
|
|
|
297
321
|
}
|
|
298
322
|
}
|
|
299
323
|
|
|
300
|
-
|
|
324
|
+
// -- Handle events --
|
|
301
325
|
|
|
302
|
-
private
|
|
326
|
+
private rootOnSizeChanged(args: any): void {
|
|
327
|
+
this.calcSize();
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
private rootOnMouseMove(e: MouseEvent) {
|
|
303
331
|
// ui.tooltip.show('text', e.x + 8, e.y + 8,);
|
|
304
332
|
// console.log(`onMouseMoveRoot.( x: ${e.x}, y: ${e.y} )`);
|
|
305
333
|
}
|
|
334
|
+
|
|
335
|
+
private filterSourceInputOnValueChanged(): void {
|
|
336
|
+
const filterSource: FilterSources = this.filterSourceInput!.value == true ?
|
|
337
|
+
FilterSources.Selected : FilterSources.Filtered;
|
|
338
|
+
|
|
339
|
+
for (let orderI = 0; orderI < this.logos.length; orderI++) {
|
|
340
|
+
for (let chainI = 0; chainI < this.chains.length; chainI++) {
|
|
341
|
+
const chain: string = this.chains[chainI];
|
|
342
|
+
const wl: DG.JsViewer = this.logos[orderI][chain];
|
|
343
|
+
wl.setOptions({[wlPROPS.filterSource]: filterSource});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
306
347
|
}
|