@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.
Files changed (59) hide show
  1. package/README.md +11 -12
  2. package/css/helm.css +10 -0
  3. package/detectors.js +83 -59
  4. package/dist/package-test.js +2 -13168
  5. package/dist/package-test.js.map +1 -0
  6. package/dist/package.js +2 -10560
  7. package/dist/package.js.map +1 -0
  8. package/dockerfiles/Dockerfile +86 -0
  9. package/files/icons/composition-analysis.svg +17 -0
  10. package/files/icons/sequence-diversity-viewer.svg +4 -0
  11. package/files/icons/sequence-similarity-viewer.svg +4 -0
  12. package/files/icons/vdregions-viewer.svg +22 -0
  13. package/files/icons/weblogo-viewer.svg +7 -0
  14. package/files/tests/testUrl.csv +11 -0
  15. package/files/tests/toAtomicLevelTest.csv +4 -0
  16. package/package.json +24 -25
  17. package/src/analysis/sequence-activity-cliffs.ts +11 -9
  18. package/src/analysis/sequence-search-base-viewer.ts +2 -1
  19. package/src/analysis/sequence-similarity-viewer.ts +3 -3
  20. package/src/analysis/sequence-space.ts +2 -1
  21. package/src/calculations/monomerLevelMols.ts +4 -4
  22. package/src/package-test.ts +9 -2
  23. package/src/package.ts +215 -131
  24. package/src/substructure-search/substructure-search.ts +19 -16
  25. package/src/tests/Palettes-test.ts +1 -1
  26. package/src/tests/WebLogo-positions-test.ts +113 -57
  27. package/src/tests/_first-tests.ts +9 -0
  28. package/src/tests/activity-cliffs-tests.ts +8 -7
  29. package/src/tests/activity-cliffs-utils.ts +17 -9
  30. package/src/tests/bio-tests.ts +4 -5
  31. package/src/tests/checkInputColumn-tests.ts +1 -1
  32. package/src/tests/converters-test.ts +52 -17
  33. package/src/tests/detectors-benchmark-tests.ts +3 -2
  34. package/src/tests/detectors-tests.ts +177 -172
  35. package/src/tests/fasta-export-tests.ts +1 -1
  36. package/src/tests/monomer-libraries-tests.ts +34 -0
  37. package/src/tests/pepsea-tests.ts +21 -0
  38. package/src/tests/renderers-test.ts +21 -19
  39. package/src/tests/sequence-space-test.ts +6 -4
  40. package/src/tests/similarity-diversity-tests.ts +4 -4
  41. package/src/tests/splitters-test.ts +4 -5
  42. package/src/tests/substructure-filters-tests.ts +23 -1
  43. package/src/tests/utils/sequences-generators.ts +1 -1
  44. package/src/tests/utils.ts +2 -1
  45. package/src/tests/viewers.ts +16 -0
  46. package/src/utils/cell-renderer.ts +88 -35
  47. package/src/utils/constants.ts +7 -6
  48. package/src/utils/convert.ts +8 -2
  49. package/src/utils/monomer-lib.ts +174 -0
  50. package/src/utils/multiple-sequence-alignment.ts +44 -20
  51. package/src/utils/pepsea.ts +78 -0
  52. package/src/utils/save-as-fasta.ts +2 -1
  53. package/src/utils/ui-utils.ts +15 -3
  54. package/src/viewers/vd-regions-viewer.ts +113 -72
  55. package/src/viewers/web-logo-viewer.ts +1031 -0
  56. package/src/widgets/bio-substructure-filter.ts +38 -24
  57. package/tsconfig.json +71 -72
  58. package/webpack.config.js +4 -11
  59. 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 {IVdRegionsViewer, PositionHeight, VdRegion, VdRegionType, WebLogoViewer} from '@datagrok-libraries/bio';
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: string[];
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: string;
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
- // rxjs.fromEvent(this.root, 'mousemove').subscribe(this.onMouseMoveRoot.bind(this));
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
- await this.init();
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 async onPropertyChanged(property: DG.Property | null) {
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
- public async reset() {
157
-
158
- }
159
-
160
- public async open(mlbView: DG.TableView) {
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
- public async show(mlbView: DG.TableView) {
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
- // #region -- Handle controls' events --
168
+ this.regions = regions;
169
+ this.dataFrame = mlbDf; // causes detach and onTableAttached
172
170
 
173
- private resizing: boolean = false;
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
- private rootOnSizeChanged(args: any): void {
176
- this.calcSize();
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
- // #endregion
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 async destroyView(): Promise<void> {
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
- private async buildView(): Promise<void> {
199
- console.debug('VdRegionsViewer.buildView() start');
218
+ for (const sub of this.viewSubs) sub.unsubscribe();
219
+ }
200
220
 
201
- const colNames: { [chain: string]: string } = Object.assign({},
202
- ...this.chains.map((chain) => ({[chain]: `${chain} ${this.sequenceColumnNamePostfix}`})));
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: colNames[chain],
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.box(this.mainLayout,
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
- //#endregion -- View --
324
+ // -- Handle events --
301
325
 
302
- private onMouseMoveRoot(e: MouseEvent) {
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
  }