@datagrok/peptides 0.8.8 → 0.8.9

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.
@@ -4,8 +4,9 @@ import * as DG from 'datagrok-api/dg';
4
4
  import $ from 'cash-dom';
5
5
 
6
6
  import * as logojs from 'logojs-react';
7
- import {splitAlignedPeptides} from '../utils/split-aligned';
7
+ // import {splitAlignedPeptides} from '../utils/split-aligned';
8
8
  import {ChemPalette} from '../utils/chem-palette';
9
+ import {PeptidesController} from '../peptides';
9
10
 
10
11
  /**
11
12
  * Logo viewer.
@@ -80,7 +81,7 @@ export class Logo extends DG.JsViewer {
80
81
  this.initialized = true;
81
82
  console.log('INIT');
82
83
  this.target = this.dataFrame;
83
- [this.splitted] = splitAlignedPeptides(this.dataFrame!.columns.bySemType(this.colSemType));
84
+ [this.splitted] = PeptidesController.splitAlignedPeptides(this.dataFrame!.columns.bySemType(this.colSemType));
84
85
  this.root.style.width = 'auto';
85
86
  this.root.style.height = 'auto';
86
87
  this.root.style.maxHeight = '200px';
@@ -142,8 +143,8 @@ export class Logo extends DG.JsViewer {
142
143
  .aggregate();
143
144
  }
144
145
  if (selected)
145
- [this.splitted] = splitAlignedPeptides(this.target!.columns.bySemType(this.colSemType));
146
- else [this.splitted] = splitAlignedPeptides(this.dataFrame!.columns.bySemType(this.colSemType));
146
+ [this.splitted] = PeptidesController.splitAlignedPeptides(this.target!.columns.bySemType(this.colSemType));
147
+ else [this.splitted] = PeptidesController.splitAlignedPeptides(this.dataFrame!.columns.bySemType(this.colSemType));
147
148
  $(this.root).empty();
148
149
 
149
150
  if (typeof this.dataFrame !== 'undefined')
@@ -4,8 +4,8 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import $ from 'cash-dom';
6
6
  import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
7
-
8
- import {model} from '../model';
7
+ import {PeptidesController} from '../peptides';
8
+ // import {PeptidesModel} from '../model';
9
9
 
10
10
  /**
11
11
  * Structure-activity relationship viewer.
@@ -28,8 +28,11 @@ export class SARViewer extends DG.JsViewer {
28
28
  protected _initialBitset: DG.BitSet | null;
29
29
  protected viewerVGrid: DG.Grid | null;
30
30
  protected currentBitset: DG.BitSet | null;
31
- grouping: boolean;
32
- groupMapping: StringDictionary | null;
31
+ protected grouping: boolean;
32
+ protected groupMapping: StringDictionary | null;
33
+ // model: PeptidesModel | null;
34
+ protected _name: string = 'Monomer-Positions';
35
+ protected controller: PeptidesController | null;
33
36
  // protected pValueThreshold: number;
34
37
  // protected amountOfBestAARs: number;
35
38
  // duplicatesHandingMethod: string;
@@ -51,6 +54,8 @@ export class SARViewer extends DG.JsViewer {
51
54
  this._initialBitset = null;
52
55
  this.viewGridInitialized = false;
53
56
  this.currentBitset = null;
57
+ // this.model = null;
58
+ this.controller = null;
54
59
 
55
60
  //TODO: find a way to restrict activityColumnName to accept only numerical columns (double even better)
56
61
  this.activityColumnName = this.string('activityColumnName');
@@ -58,47 +63,38 @@ export class SARViewer extends DG.JsViewer {
58
63
  this.filterMode = this.bool('filterMode', false);
59
64
  this.bidirectionalAnalysis = this.bool('bidirectionalAnalysis', false);
60
65
  this.grouping = this.bool('grouping', false);
61
- // this.pValueThreshold = this.float('pValueThreshold', 0.1);
62
- // this.amountOfBestAARs = this.int('amountOfBestAAR', 1);
63
- // this.duplicatesHandingMethod = this.string('duplicatesHandlingMethod', 'median', {choices: ['median']});
64
66
 
65
67
  this.sourceGrid = null;
66
68
  }
67
69
 
68
- /**
69
- * Initializes SARViewer.
70
- *
71
- * @memberof SARViewer
72
- */
70
+ get name() {
71
+ return this._name;
72
+ }
73
+
73
74
  init() {
74
75
  this._initialBitset = this.dataFrame!.filter.clone();
75
76
  this.currentBitset = this._initialBitset.clone();
76
77
  this.initialized = true;
77
- this.subs.push(model.statsDf$.subscribe((data) => this.statsDf = data));
78
- this.subs.push(model.viewerGrid$.subscribe((data) => {
78
+ }
79
+
80
+ async onTableAttached() {
81
+ this.sourceGrid = this.view?.grid ?? (grok.shell.v as DG.TableView).grid;
82
+ this.dataFrame?.setTag('dataType', 'peptides');
83
+ this.controller = PeptidesController.getInstance(this.dataFrame!);
84
+ // this.model = PeptidesModel.getOrInit(this.dataFrame!);
85
+ // this.model = this.controller.getOrInitModel();
86
+
87
+ this.subs.push(this.controller.onStatsDataFrameChanged.subscribe((data) => this.statsDf = data));
88
+ this.subs.push(this.controller.onSARGridChanged.subscribe((data) => {
79
89
  this.viewerGrid = data;
80
- this.render();
90
+ this.render(false);
81
91
  }));
82
- this.subs.push(model.viewerVGrid$.subscribe((data) => this.viewerVGrid = data));
83
- this.subs.push(model.groupMapping$.subscribe((data) => this.groupMapping = data));
84
- }
92
+ this.subs.push(this.controller.onSARVGridChanged.subscribe((data) => this.viewerVGrid = data));
93
+ this.subs.push(this.controller.onGroupMappingChanged.subscribe((data) => this.groupMapping = data));
85
94
 
86
- /**
87
- * Function that is executed when the table is attached.
88
- *
89
- * @memberof SARViewer
90
- */
91
- onTableAttached() {
92
- this.sourceGrid = this.view.grid;
93
- this.sourceGrid?.dataFrame?.setTag('dataType', 'peptides');
94
- this.render();
95
+ await this.render();
95
96
  }
96
97
 
97
- /**
98
- * Function that is executed when the viewer is detached from the table.
99
- *
100
- * @memberof SARViewer
101
- */
102
98
  detach() {
103
99
  this.subs.forEach((sub) => sub.unsubscribe());
104
100
  }
@@ -109,7 +105,7 @@ export class SARViewer extends DG.JsViewer {
109
105
  * @param {DG.Property} property New property.
110
106
  * @memberof SARViewer
111
107
  */
112
- onPropertyChanged(property: DG.Property) {
108
+ async onPropertyChanged(property: DG.Property) {
113
109
  super.onPropertyChanged(property);
114
110
 
115
111
  if (!this.initialized) {
@@ -130,7 +126,7 @@ export class SARViewer extends DG.JsViewer {
130
126
  }
131
127
  }
132
128
 
133
- this.render();
129
+ await this.render();
134
130
  }
135
131
 
136
132
  /**
@@ -144,41 +140,37 @@ export class SARViewer extends DG.JsViewer {
144
140
  return;
145
141
 
146
142
  //TODO: optimize. Don't calculate everything again if only view changes
147
- if (computeData) {
148
- if (typeof this.dataFrame !== 'undefined' && this.activityColumnName && this.sourceGrid) {
149
- await model?.updateData(
150
- this.dataFrame!,
151
- this.activityColumnName,
152
- this.scaling,
153
- this.sourceGrid,
154
- this.bidirectionalAnalysis,
155
- this._initialBitset,
156
- this.grouping,
157
- );
158
-
159
- if (this.viewerGrid !== null && this.viewerVGrid !== null) {
160
- $(this.root).empty();
161
- this.root.appendChild(this.viewerGrid.root);
162
- this.viewerGrid.dataFrame!.onCurrentCellChanged.subscribe((_) => {
163
- this.currentBitset = applyBitset(
164
- this.dataFrame!, this.viewerGrid!, this.aminoAcidResidue,
165
- this.groupMapping!, this._initialBitset!, this.filterMode,
166
- ) ?? this.currentBitset;
167
- syncGridsFunc(false, this.viewerGrid!, this.viewerVGrid!, this.aminoAcidResidue);
168
- });
169
- this.viewerVGrid.dataFrame!.onCurrentCellChanged.subscribe((_) => {
170
- syncGridsFunc(true, this.viewerGrid!, this.viewerVGrid!, this.aminoAcidResidue);
171
- });
172
- this.dataFrame!.onRowsFiltering.subscribe((_) => {
173
- sourceFilteringFunc(this.filterMode, this.dataFrame!, this.currentBitset!, this._initialBitset!);
174
- });
175
- grok.events.onAccordionConstructed.subscribe((accordion: DG.Accordion) => {
176
- accordionFunc(
177
- accordion, this.viewerGrid!, this.aminoAcidResidue,
178
- this._initialBitset!, this.activityColumnName, this.statsDf!,
179
- );
180
- });
181
- }
143
+ if (typeof this.dataFrame !== 'undefined' && this.activityColumnName && this.sourceGrid) {
144
+ if (computeData) {
145
+ await this.controller!.updateData(this.dataFrame, this.activityColumnName, this.scaling, this.sourceGrid,
146
+ this.bidirectionalAnalysis, this._initialBitset, this.grouping);
147
+ }
148
+
149
+ if (this.viewerGrid !== null && this.viewerVGrid !== null) {
150
+ $(this.root).empty();
151
+ const title = ui.h1(this._name, {style: {'align-self': 'center'}});
152
+ const gridRoot = this.viewerGrid.root;
153
+ gridRoot.style.width = 'auto';
154
+ this.root.appendChild(ui.divV([title, gridRoot]));
155
+ this.viewerGrid.dataFrame!.onCurrentCellChanged.subscribe((_) => {
156
+ this.currentBitset = applyBitset(
157
+ this.dataFrame!, this.viewerGrid!, this.aminoAcidResidue,
158
+ this.groupMapping!, this._initialBitset!, this.filterMode,
159
+ ) ?? this.currentBitset;
160
+ syncGridsFunc(false, this.viewerGrid!, this.viewerVGrid!, this.aminoAcidResidue);
161
+ });
162
+ this.viewerVGrid.dataFrame!.onCurrentCellChanged.subscribe((_) => {
163
+ syncGridsFunc(true, this.viewerGrid!, this.viewerVGrid!, this.aminoAcidResidue);
164
+ });
165
+ this.dataFrame.onRowsFiltering.subscribe((_) => {
166
+ sourceFilteringFunc(this.filterMode, this.dataFrame!, this.currentBitset!, this._initialBitset!);
167
+ });
168
+ grok.events.onAccordionConstructed.subscribe((accordion: DG.Accordion) => {
169
+ accordionFunc(
170
+ accordion, this.viewerGrid!, this.aminoAcidResidue,
171
+ this._initialBitset!, this.activityColumnName, this.statsDf!,
172
+ );
173
+ });
182
174
  }
183
175
  }
184
176
  //fixes viewers not rendering immediately after analyze.
@@ -195,27 +187,31 @@ export class SARViewer extends DG.JsViewer {
195
187
  */
196
188
  export class SARViewerVertical extends DG.JsViewer {
197
189
  viewerVGrid: DG.Grid | null;
190
+ // model: PeptidesModel | null;
191
+ protected _name = 'Sequence-Activity relationship';
192
+ controller: PeptidesController | null;
198
193
 
199
- /**
200
- * Creates an instance of SARViewerVertical.
201
- *
202
- * @memberof SARViewerVertical
203
- */
204
194
  constructor() {
205
195
  super();
206
196
 
207
197
  this.viewerVGrid = null;
208
- this.subs.push(model.viewerVGrid$.subscribe((data) => {
198
+ this.controller = null;
199
+ }
200
+
201
+ get name() {
202
+ return this._name;
203
+ }
204
+
205
+ onTableAttached(): void {
206
+ // this.model = PeptidesModel.getOrInit(this.dataFrame!);
207
+ this.controller = PeptidesController.getInstance(this.dataFrame!);
208
+
209
+ this.subs.push(this.controller.onSARVGridChanged.subscribe((data) => {
209
210
  this.viewerVGrid = data;
210
211
  this.render();
211
212
  }));
212
213
  }
213
214
 
214
- /**
215
- * Viewer render function.
216
- *
217
- * @memberof SARViewerVertical
218
- */
219
215
  render() {
220
216
  if (this.viewerVGrid) {
221
217
  $(this.root).empty();
@@ -225,19 +221,15 @@ export class SARViewerVertical extends DG.JsViewer {
225
221
  }
226
222
  }
227
223
 
228
- function syncGridsFunc(
229
- sourceVertical: boolean,
230
- viewerGrid: DG.Grid,
231
- viewerVGrid: DG.Grid,
232
- aminoAcidResidue: string,
233
- ) { //TODO: refactor, move
224
+ //TODO: refactor, move
225
+ function syncGridsFunc(sourceVertical: boolean, viewerGrid: DG.Grid, viewerVGrid: DG.Grid, aminoAcidResidue: string) {
234
226
  if (viewerGrid && viewerGrid.dataFrame && viewerVGrid && viewerVGrid.dataFrame) {
235
227
  if (sourceVertical) {
236
228
  const dfCell = viewerVGrid.dataFrame.currentCell;
237
- if (dfCell.column === null || dfCell.column.name !== 'Mean difference')
229
+ if (dfCell.column === null || dfCell.column.name !== 'Diff')
238
230
  return;
239
231
 
240
- const otherColName: string = viewerVGrid.dataFrame.get('Position', dfCell.rowIndex);
232
+ const otherColName: string = viewerVGrid.dataFrame.get('Pos', dfCell.rowIndex);
241
233
  const otherRowName: string = viewerVGrid.dataFrame.get(aminoAcidResidue, dfCell.rowIndex);
242
234
  let otherRowIndex = -1;
243
235
  for (let i = 0; i < viewerGrid.dataFrame.rowCount; i++) {
@@ -259,24 +251,20 @@ function syncGridsFunc(
259
251
  for (let i = 0; i < viewerVGrid.dataFrame.rowCount; i++) {
260
252
  if (
261
253
  viewerVGrid.dataFrame.get(aminoAcidResidue, i) === otherAAR &&
262
- viewerVGrid.dataFrame.get('Position', i) === otherPos
254
+ viewerVGrid.dataFrame.get('Pos', i) === otherPos
263
255
  ) {
264
256
  otherRowIndex = i;
265
257
  break;
266
258
  }
267
259
  }
268
260
  if (otherRowIndex !== -1)
269
- viewerVGrid.dataFrame.currentCell = viewerVGrid.dataFrame.cell(otherRowIndex, 'Mean difference');
261
+ viewerVGrid.dataFrame.currentCell = viewerVGrid.dataFrame.cell(otherRowIndex, 'Diff');
270
262
  }
271
263
  }
272
264
  }
273
265
 
274
266
  function sourceFilteringFunc(
275
- filterMode: boolean,
276
- dataFrame: DG.DataFrame,
277
- currentBitset: DG.BitSet,
278
- initialBitset: DG.BitSet,
279
- ) {
267
+ filterMode: boolean, dataFrame: DG.DataFrame, currentBitset: DG.BitSet, initialBitset: DG.BitSet) {
280
268
  if (filterMode) {
281
269
  dataFrame.selection.setAll(false, false);
282
270
  dataFrame.filter.copyFrom(currentBitset);
@@ -287,13 +275,8 @@ function sourceFilteringFunc(
287
275
  }
288
276
 
289
277
  function applyBitset(
290
- dataFrame: DG.DataFrame,
291
- viewerGrid: DG.Grid,
292
- aminoAcidResidue: string,
293
- groupMapping: StringDictionary,
294
- initialBitset: DG.BitSet,
295
- filterMode: boolean,
296
- ) {
278
+ dataFrame: DG.DataFrame, viewerGrid: DG.Grid, aminoAcidResidue: string, groupMapping: StringDictionary,
279
+ initialBitset: DG.BitSet, filterMode: boolean) {
297
280
  let currentBitset = null;
298
281
  if (
299
282
  viewerGrid.dataFrame &&
@@ -330,13 +313,8 @@ function applyBitset(
330
313
  }
331
314
 
332
315
  function accordionFunc(
333
- accordion: DG.Accordion,
334
- viewerGrid: DG.Grid,
335
- aminoAcidResidue: string,
336
- initialBitset: DG.BitSet,
337
- activityColumnName: string,
338
- statsDf: DG.DataFrame,
339
- ) {
316
+ accordion: DG.Accordion, viewerGrid: DG.Grid, aminoAcidResidue: string, initialBitset: DG.BitSet,
317
+ activityColumnName: string, statsDf: DG.DataFrame) {
340
318
  if (accordion.context instanceof DG.RowGroup) {
341
319
  const originalDf: DG.DataFrame = DG.toJs(accordion.context.dataFrame);
342
320
  const viewerDf = viewerGrid.dataFrame;
@@ -381,7 +359,7 @@ function accordionFunc(
381
359
 
382
360
  const tableMap: StringDictionary = {'Statistics:': ''};
383
361
  for (const colName of new Set(['Count', 'pValue', 'Mean difference'])) {
384
- const query = `${aminoAcidResidue} = ${currentAAR} and Position = ${currentPosition}`;
362
+ const query = `${aminoAcidResidue} = ${currentAAR} and Pos = ${currentPosition}`;
385
363
  const textNum = statsDf.groupBy([colName]).where(query).aggregate().get(colName, 0);
386
364
  // const text = textNum === 0 ? '<0.01' : `${colName === 'Count' ? textNum : textNum.toFixed(2)}`;
387
365
  const text = colName === 'Count' ? `${textNum}` : textNum < 0.01 ? '<0.01' : textNum.toFixed(2);