@datagrok/peptides 1.23.13 → 1.23.14

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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/peptides",
3
3
  "friendlyName": "Peptides",
4
- "version": "1.23.13",
4
+ "version": "1.23.14",
5
5
  "author": {
6
6
  "name": "Davit Rizhinashvili",
7
7
  "email": "drizhinashvili@datagrok.ai"
@@ -19,9 +19,9 @@
19
19
  "@datagrok-libraries/statistics": "^1.2.12",
20
20
  "@datagrok-libraries/tutorials": "^1.6.1",
21
21
  "@datagrok-libraries/utils": "^4.5.7",
22
- "datagrok-api": "^1.23.0",
23
22
  "@webgpu/types": "^0.1.40",
24
23
  "cash-dom": "^8.1.5",
24
+ "datagrok-api": "^1.23.0",
25
25
  "file-loader": "^6.2.0",
26
26
  "rxjs": "^6.5.5",
27
27
  "uuid": "^10.0.0",
@@ -30,16 +30,17 @@
30
30
  "devDependencies": {
31
31
  "@datagrok-libraries/helm-web-editor": "^1.1.7",
32
32
  "@datagrok-libraries/js-draw-lite": "^0.0.5",
33
- "@datagrok/eda": "^1.3.1",
34
33
  "@datagrok/bio": "^2.21.11",
35
34
  "@datagrok/chem": "^1.13.0",
36
35
  "@datagrok/dendrogram": "^1.2.33",
36
+ "@datagrok/eda": "^1.3.1",
37
37
  "@datagrok/helm": "^2.7.0",
38
38
  "@types/uuid": "^10.0.0",
39
39
  "@types/wu": "^2.1.44",
40
40
  "@typescript-eslint/eslint-plugin": "^8.8.1",
41
41
  "@typescript-eslint/parser": "^8.8.1",
42
42
  "css-loader": "^7.1.2",
43
+ "datagrok-tools": "^4.14.20",
43
44
  "eslint": "^8.57.1",
44
45
  "eslint-config-google": "^0.14.0",
45
46
  "style-loader": "^4.0.0",
@@ -59,7 +60,7 @@
59
60
  "debug-peptides": "grok publish",
60
61
  "release-peptides": "grok publish --release",
61
62
  "build-peptides": "webpack",
62
- "build": "webpack",
63
+ "build": "grok api && grok check --soft && webpack",
63
64
  "debug-peptides-dev": "grok publish dev",
64
65
  "release-peptides-dev": "grok publish dev --release",
65
66
  "debug-peptides-public": "grok publish public",
@@ -0,0 +1,77 @@
1
+ /**
2
+ This file is auto-generated by the grok api command.
3
+ If you notice any changes, please push them to the repository.
4
+ Do not edit this file manually.
5
+ */
6
+ import * as grok from 'datagrok-api/grok';
7
+ import * as DG from 'datagrok-api/dg';
8
+
9
+
10
+ export namespace scripts {
11
+ export async function smiTo3D(smiles: string ): Promise<string> {
12
+ return await grok.functions.call('Peptides:SmiTo3D', { smiles });
13
+ }
14
+ }
15
+
16
+ export namespace funcs {
17
+ export async function initPeptides(): Promise<void> {
18
+ return await grok.functions.call('Peptides:InitPeptides', {});
19
+ }
20
+
21
+ export async function peptides(): Promise<DG.View> {
22
+ return await grok.functions.call('Peptides:Peptides', {});
23
+ }
24
+
25
+ export async function peptidesDialog(): Promise<void> {
26
+ return await grok.functions.call('Peptides:PeptidesDialog', {});
27
+ }
28
+
29
+ export async function testInitFunctionPeptides(v: any ): Promise<void> {
30
+ return await grok.functions.call('Peptides:TestInitFunctionPeptides', { v });
31
+ }
32
+
33
+ export async function peptidesPanel(col: DG.Column ): Promise<any> {
34
+ return await grok.functions.call('Peptides:PeptidesPanel', { col });
35
+ }
36
+
37
+ /**
38
+ Peptides Sequence Variability Map Viewer
39
+ */
40
+ export async function monomerPosition(): Promise<any> {
41
+ return await grok.functions.call('Peptides:MonomerPosition', {});
42
+ }
43
+
44
+ /**
45
+ Peptides Most Potent Residues Viewer
46
+ */
47
+ export async function mostPotentResidues(): Promise<any> {
48
+ return await grok.functions.call('Peptides:MostPotentResidues', {});
49
+ }
50
+
51
+ export async function logoSummaryTable(): Promise<any> {
52
+ return await grok.functions.call('Peptides:LogoSummaryTable', {});
53
+ }
54
+
55
+ export async function sequencePositionStatistics(): Promise<any> {
56
+ return await grok.functions.call('Peptides:SequencePositionStatistics', {});
57
+ }
58
+
59
+ export async function clusterMaxActivity(): Promise<any> {
60
+ return await grok.functions.call('Peptides:ClusterMaxActivity', {});
61
+ }
62
+
63
+ export async function manualAlignment(_monomer: string ): Promise<any> {
64
+ return await grok.functions.call('Peptides:ManualAlignment', { _monomer });
65
+ }
66
+
67
+ /**
68
+ Peptide SAR Analysis demo on peptide sequences in FASTA format
69
+ */
70
+ export async function macromoleculeSarFastaDemo(): Promise<void> {
71
+ return await grok.functions.call('Peptides:MacromoleculeSarFastaDemo', {});
72
+ }
73
+
74
+ export async function lstPiechartCellRenderer(): Promise<any> {
75
+ return await grok.functions.call('Peptides:LstPiechartCellRenderer', {});
76
+ }
77
+ }
@@ -55,6 +55,9 @@ export const enum LST_PROPERTIES {
55
55
  AGGREGATION = 'aggregation',
56
56
  ACTIVITY_SCALING = 'activityScaling',
57
57
  ACTIVITY = 'activity',
58
+
59
+ WEB_LOGO_AGGREGATION_COLUMN_NAME = 'webLogoAggregationColumnName',
60
+ WEB_LOGO_AGGREGATION_TYPE = 'webLogoAggregationType',
58
61
  }
59
62
 
60
63
  enum LST_CATEGORIES {
@@ -86,6 +89,11 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
86
89
  activityScaling: SCALING_METHODS;
87
90
  _scaledActivityColumn: DG.Column | null = null;
88
91
 
92
+ webLogoAggregationColumnName: string | null;
93
+ webLogoAggregationType: DG.AggregationType;
94
+
95
+ private _webLogoCacheGeneration: number = 0;
96
+
89
97
  /** Creates LogoSummaryTable properties. */
90
98
  constructor() {
91
99
  super();
@@ -122,6 +130,25 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
122
130
  category: LST_CATEGORIES.STYLE,
123
131
  });
124
132
 
133
+ const aggExcludeList = [DG.AGG.KEY, DG.AGG.PIVOT, DG.AGG.MISSING_VALUE_COUNT, DG.AGG.SKEW, DG.AGG.KURT,
134
+ DG.AGG.SELECTED_ROWS_COUNT];
135
+ const aggChoices = Object.values(DG.AGG).filter((agg) => !aggExcludeList.includes(agg));
136
+ this.webLogoAggregationType = this.string(LST_PROPERTIES.WEB_LOGO_AGGREGATION_TYPE, DG.AGG.TOTAL_COUNT, {
137
+ category: LST_CATEGORIES.STYLE,
138
+ choices: aggChoices,
139
+ description: 'Aggregation method for WebLogo position heights',
140
+ }) as DG.AggregationType;
141
+
142
+
143
+ this.webLogoAggregationColumnName = this.column(LST_PROPERTIES.WEB_LOGO_AGGREGATION_COLUMN_NAME, {
144
+ defaultValue: null,
145
+ category: LST_CATEGORIES.STYLE,
146
+ nullable: true,
147
+ columnTypeFilter: DG.TYPE.NUMERICAL,
148
+ description: `Column with values to aggregate for WebLogo position heights.
149
+ Used if aggregation type is not '${DG.AGG.TOTAL_COUNT}'.`,
150
+ });
151
+
125
152
  this.columns = this.columnList(LST_PROPERTIES.COLUMNS, [], {category: LST_CATEGORIES.AGGREGATION});
126
153
  this.aggregation = this.string(LST_PROPERTIES.AGGREGATION, DG.AGG.AVG,
127
154
  {
@@ -251,9 +278,7 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
251
278
  * @return - iterable over custom clusters columns.
252
279
  */
253
280
  get customClusters(): wu.WuIterable<DG.Column<boolean>> {
254
- const query: {
255
- [key: string]: string
256
- } = {};
281
+ const query: {[key: string]: string} = {};
257
282
  query[C.TAGS.CUSTOM_CLUSTER] = '1';
258
283
  return wu(this.dataFrame.columns.byTags(query));
259
284
  }
@@ -293,10 +318,13 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
293
318
  onTableAttached(): void {
294
319
  super.onTableAttached();
295
320
  if (isApplicableDataframe(this.dataFrame)) {
321
+ const activityColName = wu(this.dataFrame.columns.numerical).next().value.name;
296
322
  this.getProperty(`${LST_PROPERTIES.SEQUENCE}${COLUMN_NAME}`)
297
323
  ?.set(this, this.dataFrame.columns.bySemType(DG.SEMTYPE.MACROMOLECULE)!.name);
298
324
  this.getProperty(`${LST_PROPERTIES.ACTIVITY}${COLUMN_NAME}`)
299
- ?.set(this, wu(this.dataFrame.columns.numerical).next().value.name);
325
+ ?.set(this, activityColName);
326
+ this.getProperty(`${LST_PROPERTIES.WEB_LOGO_AGGREGATION_COLUMN_NAME}`)?.set(this, activityColName);
327
+
300
328
  this.getProperty(`${LST_PROPERTIES.CLUSTERS}${COLUMN_NAME}`)
301
329
  ?.set(this, wu(this.dataFrame.columns.categorical).next().value.name);
302
330
  } else {
@@ -376,7 +404,11 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
376
404
  doRender = true;
377
405
  break;
378
406
  case `${LST_PROPERTIES.ACTIVITY}${COLUMN_NAME}`:
407
+ this.webLogoAggregationColumnName = this.activityColumnName;
379
408
  case LST_PROPERTIES.ACTIVITY_SCALING:
409
+ case `${LST_PROPERTIES.WEB_LOGO_AGGREGATION_COLUMN_NAME}${COLUMN_NAME}`:
410
+ case LST_PROPERTIES.WEB_LOGO_AGGREGATION_TYPE:
411
+ this._webLogoCacheGeneration++; // Increment to invalidate cache
380
412
  this._scaledActivityColumn = null;
381
413
  this._viewerGrid = null;
382
414
  this._clusterStats = null;
@@ -402,9 +434,7 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
402
434
  * @param options.notify - flag that indicates if bitset changed event should fire.
403
435
  * @return - cluster selection.
404
436
  */
405
- initClusterSelection(options: {
406
- notify?: boolean
407
- } = {}): type.Selection {
437
+ initClusterSelection(options: {notify?: boolean} = {}): type.Selection {
408
438
  options.notify ??= true;
409
439
 
410
440
  const newClusterSelection = {} as type.Selection;
@@ -438,7 +468,13 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
438
468
  */
439
469
  getNeededDfClone(): DG.DataFrame {
440
470
  // gather all needed columns. for string columns we need to remove 'dist(' and ')' from the name
441
- const neededCols = [this.clustersColumnName, this.sequenceColumnName, this.activityColumnName, ...(this.getTotalViewerAggColumns() ?? []).map(([cn, _]) => cn), ...(this.getStringAggregatedColumns() ?? []).map((cn) => cn.substring(5, cn.length - 1))];
471
+ const neededCols = [this.clustersColumnName, this.sequenceColumnName, this.activityColumnName,
472
+ ...(this.getTotalViewerAggColumns() ?? []).map(([cn, _]) => cn),
473
+ ...(this.getStringAggregatedColumns() ?? []).map((cn) => cn.substring(5, cn.length - 1))];
474
+ if (this.webLogoAggregationColumnName)
475
+ neededCols.push(this.webLogoAggregationColumnName);
476
+
477
+
442
478
  const colsSet = Array.from(new Set(neededCols)).filter((colName) => this.dataFrame.columns.contains(colName));
443
479
  return this.dataFrame.clone(this.dataFrame.filter, colsSet);
444
480
  }
@@ -459,9 +495,7 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
459
495
  const filteredDfClustColData = filteredDfClustCol.getRawData();
460
496
  const filteredDfClustColCat = filteredDfClustCol.categories;
461
497
 
462
- const query: {
463
- [key: string]: string
464
- } = {};
498
+ const query: {[key: string]: string} = {};
465
499
  query[C.TAGS.CUSTOM_CLUSTER] = '1';
466
500
  const customClustColList: DG.Column<boolean>[] = wu(filteredDfCols.byTags(query))
467
501
  .filter((c) => c.max > 0).toArray();
@@ -614,8 +648,8 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
614
648
  grid.columns.rowHeader!.visible = false;
615
649
  grid.props.rowHeight = 55;
616
650
 
617
- const webLogoCache = new DG.LruCache<number, DG.Viewer & IWebLogoViewer>();
618
- const webLogoPromiseCache = new Map<number, boolean>();// this map will keep the promises for weblogo creation
651
+ const webLogoCache = new DG.LruCache<string, DG.Viewer & IWebLogoViewer>();
652
+ const webLogoPromiseCache = new Map<string, boolean>(); // this map will keep promises for weblogo creation
619
653
 
620
654
  let invalidateTimeout: any = null;
621
655
 
@@ -655,14 +689,17 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
655
689
  CR.renderLogoSummaryCell(canvasContext, gridCell.cell.value, this.clusterSelection, bound);
656
690
  gridCellArgs.preventDefault();
657
691
  } else if (gridCell.tableColumn?.name === C.LST_COLUMN_NAMES.WEB_LOGO) {
692
+ const cacheKey = `${currentRowIdx}_${this.webLogoAggregationColumnName || 'count'}_${this.webLogoAggregationType}_${this._webLogoCacheGeneration}`;
693
+ const viewer = webLogoCache.get(cacheKey);
694
+
658
695
  // if current weblogo is being created, prevent the creation of another one
659
- if (webLogoPromiseCache.get(currentRowIdx) === true) {
696
+
697
+ if (webLogoPromiseCache.get(cacheKey) === true) {
660
698
  gridCellArgs.preventDefault();
661
699
  return;
662
700
  }
663
701
  const positionWidth = Math.floor((gridCell.bounds.width - 2 - (4 * (maxSequenceLen - 1))) / maxSequenceLen);
664
702
 
665
- const viewer = webLogoCache.get(currentRowIdx);
666
703
  if (viewer !== undefined) {
667
704
  const viewerProps = viewer.getProperties();
668
705
 
@@ -680,19 +717,30 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
680
717
  gridCell.element = viewer.root;
681
718
  gridCellArgs.preventDefault();
682
719
  } else {
683
- const webLogoTable = this.createWebLogoDf(pepCol, clusterBitSet);
684
- webLogoPromiseCache.set(currentRowIdx, true);
720
+ const columnsToInclude = [pepCol];
721
+ if (this.webLogoAggregationType !== DG.AGG.TOTAL_COUNT && this.webLogoAggregationColumnName) {
722
+ const aggCol = this.dataFrame.columns.byName(this.webLogoAggregationColumnName);
723
+ if (aggCol)
724
+ columnsToInclude.push(aggCol);
725
+ }
726
+ const webLogoTable = DG.DataFrame.fromColumns(columnsToInclude);
727
+ webLogoTable.filter.copyFrom(clusterBitSet);
728
+
729
+ webLogoPromiseCache.set(cacheKey, true);
685
730
  webLogoTable.plot
686
731
  .fromType('WebLogo', {
732
+ valueColumnName: this.webLogoAggregationColumnName,
733
+ valueAggrType: this.webLogoAggregationType,
687
734
  positionHeight: this.webLogoMode,
688
735
  horizontalAlignment: HorizontalAlignments.LEFT,
689
736
  maxHeight: 1000,
690
737
  minHeight: height,
691
738
  positionWidth: positionWidth,
692
739
  showPositionLabels: false,
693
- }).then((v) => {
694
- webLogoCache.set(currentRowIdx, v);
695
- webLogoPromiseCache.delete(currentRowIdx);
740
+ })
741
+ .then((v) => {
742
+ webLogoCache.set(cacheKey, v);
743
+ webLogoPromiseCache.delete(cacheKey);
696
744
  debouncedInvalidate();
697
745
  });
698
746
  gridCellArgs.preventDefault();
@@ -875,12 +923,8 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
875
923
  this.bitsets.push(currentSelection.clone());
876
924
 
877
925
  const newClusterName = this.dataFrame.columns.getUnusedName('New Cluster');
878
- const aggregatedValues: {
879
- [colName: string]: number
880
- } = {};
881
- const stringAggregatedValues: {
882
- [colName: string]: string
883
- } = {};
926
+ const aggregatedValues: {[colName: string]: number} = {};
927
+ const stringAggregatedValues: {[colName: string]: string} = {};
884
928
  const aggColsEntries = this.getTotalViewerAggColumns();
885
929
  const aggStringColNames = this.getStringAggregatedColumns();
886
930
  for (const [colName, aggFn] of aggColsEntries) {
@@ -1021,9 +1065,7 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
1021
1065
  filterDf: true,
1022
1066
  mask: mask,
1023
1067
  });
1024
- const resultMap: {
1025
- [key: string]: any
1026
- } = {...tableMap, ...aggregatedColMap};
1068
+ const resultMap: {[key: string]: any} = {...tableMap, ...aggregatedColMap};
1027
1069
  const tooltip = getDistributionPanel(hist, resultMap);
1028
1070
 
1029
1071
  ui.tooltip.show(tooltip, x, y);
@@ -1032,10 +1074,9 @@ export class LogoSummaryTable extends DG.JsViewer implements ILogoSummaryTable {
1032
1074
  }
1033
1075
 
1034
1076
  /**
1035
- * Creates a dataframe for WebLogo viewer.
1036
1077
  * @param pepCol - column with peptides.
1037
1078
  * @param mask - bitset to filter dataframe with.
1038
- * @return - dataframe for WebLogo viewer.
1079
+ * @deprecated The logic is now handled directly in createLogoSummaryTableGrid
1039
1080
  */
1040
1081
  createWebLogoDf(pepCol: DG.Column<string>, mask: DG.BitSet): DG.DataFrame {
1041
1082
  const newDf = DG.DataFrame.fromColumns([pepCol]);
@@ -44,14 +44,8 @@ export function analyzePeptidesUI(df: DG.DataFrame, col?: DG.Column<string>): Di
44
44
  }));
45
45
  if (value.stats.missingValueCount !== 0)
46
46
  grok.shell.info('Sequences column contains missing values. They will be ignored during analysis');
47
- }, filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE});
47
+ }, filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE, nullable: false});
48
48
  seqColInput.setTooltip('Macromolecule column in FASTA, HELM or separated format');
49
- } else if (!(col.getTag(bioTAGS.aligned) === ALIGNMENT.SEQ_MSA) &&
50
- col.getTag(DG.TAGS.UNITS) !== NOTATION.HELM) {
51
- return {
52
- host: ui.label('Peptides analysis only works with aligned sequences'),
53
- callback: async (): Promise<boolean> => false,
54
- };
55
49
  }
56
50
 
57
51
  let funcs = DG.Func.find({package: 'Bio', name: 'webLogoViewer'});
@@ -96,7 +90,7 @@ export function analyzePeptidesUI(df: DG.DataFrame, col?: DG.Column<string>): Di
96
90
  if (activityColumnChoice.value!.stats.missingValueCount !== 0)
97
91
  grok.shell.info('Activity column contains missing values. They will be ignored during analysis');
98
92
  };
99
- const activityColumnChoice = ui.input.column('Activity', {table: df, value: defaultActivityColumn!,
93
+ const activityColumnChoice = ui.input.column('Activity', {table: df, value: defaultActivityColumn!, nullable: false,
100
94
  onValueChanged: activityScalingMethodState, filter: (col: DG.Column) => col.type === DG.TYPE.INT || col.type === DG.TYPE.FLOAT || col.type === DG.TYPE.QNUM});
101
95
  activityColumnChoice.setTooltip('Numerical activity column');
102
96
  const clustersColumnChoice = ui.input.column('Clusters', {table: df, onValueChanged: (value) => {
@@ -355,6 +349,15 @@ export async function startAnalysis(activityColumn: DG.Column<number>, peptidesC
355
349
  }
356
350
  }
357
351
 
352
+ const selectionGrid = model.df.plot.grid({
353
+ rowSource: DG.RowSet.Selected,
354
+ selectedRowsColor: DG.Color.fromHtml('#ffffff'),
355
+ title: 'Selection',
356
+ });
357
+
358
+ const logoViewerNode = (model?.findViewerNode(VIEWER_TYPE.LOGO_SUMMARY_TABLE));
359
+ if (logoViewerNode)
360
+ model.analysisView.dockManager.dock(selectionGrid, DG.DOCK_TYPE.DOWN, logoViewerNode, 'Selection', 0.4);
358
361
 
359
362
  progress.close();
360
363
  return model;