@datagrok/peptides 0.8.15 → 1.0.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datagrok/peptides",
3
- "version": "0.8.15",
3
+ "version": "1.0.0",
4
4
  "description": "Provides advanced tools for analyzing collections of peptides.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,7 +34,7 @@
34
34
  "jest": "^27.0.0",
35
35
  "@types/jest": "^27.0.0",
36
36
  "ts-jest": "^27.0.0",
37
- "puppeteer": "latest"
37
+ "puppeteer": "^13.7.0"
38
38
  },
39
39
  "sources": [
40
40
  "common/ngl_viewer/ngl.js"
@@ -68,5 +68,6 @@
68
68
  ],
69
69
  "canView": [
70
70
  "All users"
71
- ]
71
+ ],
72
+ "category": "Cheminformatics"
72
73
  }
package/package.png CHANGED
Binary file
package/src/model.ts CHANGED
@@ -16,6 +16,8 @@ import {_package} from './package';
16
16
  import {SARViewer, SARViewerVertical} from './viewers/sar-viewer';
17
17
  import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
18
18
  import {setAARRenderer} from './utils/cell-renderer';
19
+ import {substitutionsWidget} from './widgets/subst-table';
20
+ import {getDistributionWidget} from './widgets/distribution';
19
21
 
20
22
  export class PeptidesModel {
21
23
  static _modelName = 'peptidesModel';
@@ -28,6 +30,7 @@ export class PeptidesModel {
28
30
  _isUpdating: boolean = false;
29
31
  _isSubstInitialized = false;
30
32
  isBitsetChangedInitialized = false;
33
+ isCellChanging = false;
31
34
 
32
35
  //viewer properties
33
36
  _filterMode!: boolean;
@@ -41,17 +44,20 @@ export class PeptidesModel {
41
44
  _sarVGrid!: DG.Grid;
42
45
  _sourceGrid!: DG.Grid;
43
46
  _dataFrame: DG.DataFrame;
44
- splitCol!: DG.Column;
47
+ splitCol!: DG.Column<boolean>;
45
48
  stackedBarchart!: StackedBarChart;
49
+ edf: DG.DataFrame | null = null;
46
50
 
47
51
  substitutionsInfo: type.SubstitutionsInfo = new Map();
48
52
  isInitialized: boolean = false;
49
53
  currentView!: DG.TableView;
50
54
 
55
+ _currentSelection!: type.SelectionObject;
56
+ isPeptideSpaceChangingBitset: boolean = false;
57
+ isChangingEdfBitset: boolean = false;
58
+
51
59
  private constructor(dataFrame: DG.DataFrame) {
52
60
  this._dataFrame = dataFrame;
53
- this._dataFrame.temp[C.PEPTIDES_ANALYSIS] = true;
54
-
55
61
  this.updateProperties();
56
62
  }
57
63
 
@@ -67,6 +73,8 @@ export class PeptidesModel {
67
73
 
68
74
  static get modelName(): string {return PeptidesModel._modelName;}
69
75
 
76
+ static get chemPalette(): typeof ChemPalette {return ChemPalette;}
77
+
70
78
  get onStatsDataFrameChanged(): Observable<DG.DataFrame> {return this._statsDataFrameSubject.asObservable();}
71
79
 
72
80
  get onSARGridChanged(): Observable<DG.Grid> {return this._sarGridSubject.asObservable();}
@@ -75,6 +83,31 @@ export class PeptidesModel {
75
83
 
76
84
  get onSubstTableChanged(): Observable<type.SubstitutionsInfo> {return this._substitutionTableSubject.asObservable();}
77
85
 
86
+ get currentSelection(): type.SelectionObject {
87
+ this._currentSelection ??= JSON.parse(this._dataFrame.tags[C.TAGS.SELECTION] || '{}');
88
+ return this._currentSelection;
89
+ }
90
+ set currentSelection(selection: type.SelectionObject) {
91
+ this._currentSelection = selection;
92
+ this._dataFrame.tags[C.TAGS.SELECTION] = JSON.stringify(selection);
93
+ this.invalidateSelection();
94
+ }
95
+
96
+ invalidateSelection(): void {
97
+ this.fireBitsetChanged();
98
+ this.invalidateGrids();
99
+ }
100
+
101
+ createAccordion() {
102
+ const acc = ui.accordion('Selection info');
103
+ acc.root.style.width = '100%';
104
+ acc.addTitle(ui.h1('Selection info'));
105
+ acc.addPane('Substitutions', () => substitutionsWidget(this._dataFrame, this).root, true);
106
+ acc.addPane('Distribtution', () => getDistributionWidget(this._dataFrame).root, true);
107
+
108
+ return acc;
109
+ }
110
+
78
111
  updateProperties(): void {
79
112
  this._activityScaling = this._dataFrame.tags['scaling'];
80
113
  this._filterMode = stringToBool(this._dataFrame.tags['filterMode']);
@@ -136,7 +169,7 @@ export class PeptidesModel {
136
169
  }
137
170
  }
138
171
  await this.updateBarchart();
139
- this.invalidateGrids();
172
+ this.invalidateSelection();
140
173
 
141
174
  this._isUpdating = false;
142
175
  }
@@ -221,28 +254,10 @@ export class PeptidesModel {
221
254
 
222
255
  this.setInteractionCallback();
223
256
 
224
- this.modifyOrCreateSplitCol(C.CATEGORIES.ALL, C.CATEGORIES.ALL);
225
-
226
257
  this.setBitsetCallback();
227
258
 
228
259
  this.postProcessGrids(this._sourceGrid, invalidIndexes, sarGrid, sarVGrid);
229
260
 
230
- const currentAAR = this._dataFrame.tags[C.TAGS.AAR];
231
- const currentPos = this._dataFrame.tags[C.TAGS.POSITION];
232
- if (currentAAR !== currentPos) {
233
- const sarDf = sarGrid.dataFrame;
234
- const rowCount = sarDf.rowCount;
235
- let index = -1;
236
- const aarCol = sarDf.getCol(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE);
237
- for (let i = 0; i < rowCount; i++) {
238
- if (aarCol.get(i) === currentAAR) {
239
- index = i;
240
- break;
241
- }
242
- }
243
- sarDf.currentCell = sarDf.cell(index, currentPos);
244
- }
245
-
246
261
  //TODO: return class instead
247
262
  return [sarGrid, sarVGrid, statsDf];
248
263
  }
@@ -369,7 +384,7 @@ export class PeptidesModel {
369
384
  activityScaling: string, df: DG.DataFrame, sourceGrid: DG.Grid, splitSeqDf: DG.DataFrame,
370
385
  ): Promise<void> {
371
386
  const [scaledDf, newColName] = await PeptidesModel.scaleActivity(
372
- activityScaling, df, df.temp[C.COLUMNS_NAMES.ACTIVITY]);
387
+ activityScaling, df, df.tags[C.COLUMNS_NAMES.ACTIVITY]);
373
388
  //TODO: make another func
374
389
  const scaledCol = scaledDf.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED);
375
390
  scaledCol.semType = C.SEM_TYPES.ACTIVITY_SCALED;
@@ -379,7 +394,7 @@ export class PeptidesModel {
379
394
  const gridCol = sourceGrid.col(C.COLUMNS_NAMES.ACTIVITY_SCALED);
380
395
  if (gridCol !== null) {
381
396
  gridCol.name = newColName;
382
- df.temp[C.COLUMNS_NAMES.ACTIVITY_SCALED] = newColName;
397
+ df.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED] = newColName;
383
398
  }
384
399
 
385
400
  sourceGrid.columns.setOrder([newColName]);
@@ -488,8 +503,8 @@ export class PeptidesModel {
488
503
  const sarVGrid = sequenceDf.plot.grid();
489
504
  sarVGrid.sort([C.COLUMNS_NAMES.POSITION]);
490
505
  const pValGridCol = sarVGrid.col(C.COLUMNS_NAMES.P_VALUE)!;
491
- pValGridCol.format = 'four digits after comma';
492
- pValGridCol.name = 'P-Value';
506
+ pValGridCol.format = '#.000';
507
+ pValGridCol.name = 'P-value';
493
508
 
494
509
  let tempCol = matrixDf.getCol(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE);
495
510
  if (tempCol)
@@ -532,9 +547,9 @@ export class PeptidesModel {
532
547
 
533
548
  if (cell.isTableCell && tableColName && tableRowIndex !== null && renderColNames.indexOf(tableColName) !== -1) {
534
549
  const gridTable = cell.grid.table;
535
- const currentPosition = tableColName !== C.COLUMNS_NAMES.MEAN_DIFFERENCE ?
550
+ const currentPosition: string = tableColName !== C.COLUMNS_NAMES.MEAN_DIFFERENCE ?
536
551
  tableColName : gridTable.get(C.COLUMNS_NAMES.POSITION, tableRowIndex);
537
- const currentAAR = gridTable.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, tableRowIndex);
552
+ const currentAAR: string = gridTable.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, tableRowIndex);
538
553
 
539
554
  const queryAAR = `${C.COLUMNS_NAMES.AMINO_ACID_RESIDUE} = ${currentAAR}`;
540
555
  if (cellValue) {
@@ -582,6 +597,14 @@ export class PeptidesModel {
582
597
  if (substValue && substValue != 0)
583
598
  canvasContext.fillText(substValue.toString(), midX, midY);
584
599
  }
600
+
601
+ //TODO: frame based on currentSelection
602
+ const aarSelection = this.currentSelection[currentPosition];
603
+ if (aarSelection && aarSelection.includes(currentAAR)) {
604
+ canvasContext.strokeStyle = '#000';
605
+ canvasContext.lineWidth = 1;
606
+ canvasContext.strokeRect(bound.x + 1, bound.y + 1, bound.width - 1, bound.height - 1);
607
+ }
585
608
  }
586
609
  args.preventDefault();
587
610
  }
@@ -640,46 +663,63 @@ export class PeptidesModel {
640
663
  const sarDf = this._sarGrid.dataFrame;
641
664
  const sarVDf = this._sarVGrid.dataFrame;
642
665
 
643
- //rework, it doesn't even get into isVertical clause
644
- const getAARandPosition = (isVertical = false): [string, string] => {
645
- let aar : string;
646
- let position: string;
647
- if (isVertical) {
648
- const currentRowIdx = sarVDf.currentRowIdx;
649
- aar = sarVDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, currentRowIdx);
650
- position = sarVDf.get(C.COLUMNS_NAMES.POSITION, currentRowIdx);
651
- } else {
652
- aar = sarDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, sarDf.currentRowIdx);
653
- position = sarDf.currentCol.name;
654
- }
655
- return [aar, position];
666
+ const chooseAction = (aar: string, position: string, isShiftPressed: boolean) => {
667
+ isShiftPressed ? this.modifyCurrentSelection(aar, position) : this.initCurrentSelection(aar, position);
656
668
  };
657
669
 
658
- this._sarGrid.onCurrentCellChanged.subscribe((gc) => {
659
- const isNegativeRowIndex = sarDf.currentRowIdx === -1;
660
- if (!sarDf.currentCol || (!sarDf.currentCell.value && !isNegativeRowIndex))
670
+ const gridCellValidation = (gc: DG.GridCell | null) => !gc || !gc.cell.value || !gc.tableColumn ||
671
+ gc.tableRowIndex == null || gc.tableRowIndex == -1;
672
+ this._sarGrid.root.addEventListener('click', (ev) => {
673
+ const gridCell = this._sarGrid.hitTest(ev.offsetX, ev.offsetY);
674
+ if (gridCellValidation(gridCell) || gridCell!.tableColumn!.name == C.COLUMNS_NAMES.AMINO_ACID_RESIDUE)
661
675
  return;
662
- this.syncGrids(false, sarDf, sarVDf);
663
- let aar: string = C.CATEGORIES.ALL;
664
- let position: string = C.CATEGORIES.ALL;
665
- if (!isNegativeRowIndex) {
666
- [aar, position] = getAARandPosition();
667
- this._dataFrame.tags[C.TAGS.AAR] = aar;
668
- this._dataFrame.tags[C.TAGS.POSITION] = position;
669
- } else
670
- this._dataFrame.tags[C.TAGS.AAR] = this._dataFrame.tags[C.TAGS.POSITION] = '';
671
-
672
- this.modifyOrCreateSplitCol(aar, position);
673
- this.fireBitsetChanged();
674
- this.invalidateGrids();
675
- grok.shell.o = this._dataFrame;
676
+
677
+ const position = gridCell!.tableColumn!.name;
678
+ const aar = sarDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, gridCell!.tableRowIndex!);
679
+ chooseAction(aar, position, ev.shiftKey);
676
680
  });
677
681
 
678
- this._sarVGrid.onCurrentCellChanged.subscribe((gc) => {
679
- if (!sarVDf.currentCol || sarVDf.currentRowIdx === -1)
682
+ this._sarVGrid.root.addEventListener('click', (ev) => {
683
+ const gridCell = this._sarVGrid.hitTest(ev.offsetX, ev.offsetY);
684
+ if (gridCellValidation(gridCell) || gridCell!.tableColumn!.name != C.COLUMNS_NAMES.MEAN_DIFFERENCE)
680
685
  return;
681
- this.syncGrids(true, sarDf, sarVDf);
686
+
687
+ const tableRowIdx = gridCell!.tableRowIndex!;
688
+ const position = sarVDf.get(C.COLUMNS_NAMES.POSITION, tableRowIdx);
689
+ const aar = sarVDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, tableRowIdx);
690
+ chooseAction(aar, position, ev.shiftKey);
682
691
  });
692
+
693
+ const cellChanged = (table: DG.DataFrame) => {
694
+ if (this.isCellChanging)
695
+ return;
696
+ this.isCellChanging = true;
697
+ table.currentRowIdx = -1;
698
+ this.isCellChanging = false;
699
+ };
700
+ this._sarGrid.onCurrentCellChanged.subscribe((_gc) => cellChanged(sarDf));
701
+ this._sarVGrid.onCurrentCellChanged.subscribe((_gc) => cellChanged(sarVDf));
702
+ }
703
+
704
+ modifyCurrentSelection(aar: string, position: string): void {
705
+ const tempSelection = this.currentSelection;
706
+ if (!tempSelection.hasOwnProperty(position))
707
+ tempSelection[position] = [aar];
708
+ else {
709
+ const tempSelectionAt = tempSelection[position];
710
+ const aarIndex = tempSelectionAt.indexOf(aar);
711
+ aarIndex == -1 ? tempSelectionAt.push(aar) :
712
+ tempSelectionAt.length == 1 ? delete tempSelection[position] :
713
+ tempSelectionAt.splice(aarIndex, 1);
714
+ }
715
+
716
+ this.currentSelection = tempSelection;
717
+ }
718
+
719
+ initCurrentSelection(aar: string, position: string): void {
720
+ const tempSelection: type.SelectionObject = {};
721
+ tempSelection[position] = [aar];
722
+ this.currentSelection = tempSelection;
683
723
  }
684
724
 
685
725
  invalidateGrids(): void {
@@ -698,10 +738,41 @@ export class PeptidesModel {
698
738
 
699
739
  const changeBitset = (currentBitset: DG.BitSet, previousBitset: DG.BitSet): void => {
700
740
  previousBitset.setAll(!this._filterMode, false);
701
- currentBitset.init((i) => {
702
- const currentCategory = this.splitCol.get(i);
703
- return currentCategory !== C.CATEGORIES.OTHER && currentCategory !== C.CATEGORIES.ALL;
704
- }, false);
741
+
742
+ const edfSelection = this.edf?.selection;
743
+ if (this.isPeptideSpaceChangingBitset) {
744
+ if (edfSelection == null)
745
+ return;
746
+
747
+ currentBitset.init((i) => edfSelection.get(i) ?? false, false);
748
+ return;
749
+ }
750
+
751
+ const updateEdfSelection = () => {
752
+ this.isChangingEdfBitset = true;
753
+ edfSelection?.copyFrom(currentBitset);
754
+ this.isChangingEdfBitset = false;
755
+ };
756
+
757
+ const positionList = Object.keys(this.currentSelection);
758
+ if (positionList.length == 0) {
759
+ currentBitset.init(() => false, false);
760
+ updateEdfSelection();
761
+ return;
762
+ }
763
+
764
+ //TODO: move out
765
+ const getBitAt = (i: number) => {
766
+ for (const position of positionList) {
767
+ const positionCol: DG.Column<string> = this._dataFrame.getCol(position);
768
+ if (this._currentSelection[position].includes(positionCol.get(i)))
769
+ return true;
770
+ }
771
+ return false;
772
+ };
773
+ currentBitset.init(getBitAt, false);
774
+
775
+ updateEdfSelection();
705
776
  };
706
777
 
707
778
  const recalculateStatistics =
@@ -718,7 +789,15 @@ export class PeptidesModel {
718
789
  this.isBitsetChangedInitialized = true;
719
790
  }
720
791
 
721
- fireBitsetChanged(): void {(this._filterMode ? this._dataFrame.filter : this._dataFrame.selection).fireChanged();}
792
+ fireBitsetChanged(isPeptideSpaceSource: boolean = false): void {
793
+ this.isPeptideSpaceChangingBitset = isPeptideSpaceSource;
794
+ this.getBiteset().fireChanged();
795
+ this.isPeptideSpaceChangingBitset = false;
796
+ this.modifyOrCreateSplitCol();
797
+ grok.shell.o = this.createAccordion().root;
798
+ }
799
+
800
+ getBiteset(): DG.BitSet {return this._filterMode ? this._dataFrame.filter : this._dataFrame.selection;}
722
801
 
723
802
  //TODO: move out
724
803
  postProcessGrids(sourceGrid: DG.Grid, invalidIndexes: number[], sarGrid: DG.Grid, sarVGrid: DG.Grid): void {
@@ -732,70 +811,28 @@ export class PeptidesModel {
732
811
  mdCol.name = 'Diff';
733
812
 
734
813
  for (const grid of [sarGrid, sarVGrid]) {
735
- grid.props.rowHeight = 20;
736
- grid.columns.rowHeader!.width = 20;
737
- for (let i = 0; i < grid.columns.length; ++i) {
738
- const col = grid.columns.byIndex(i)!;
739
- if (grid == sarVGrid && col.name !== 'Diff' && col.name !== C.COLUMNS_NAMES.AMINO_ACID_RESIDUE)
740
- col.width = 45;
814
+ const gridProps = grid.props;
815
+ gridProps.rowHeight = 20;
816
+ const girdCols = grid.columns;
817
+ const colNum = girdCols.length;
818
+ for (let i = 0; i < colNum; ++i) {
819
+ const col = girdCols.byIndex(i)!;
820
+ const colName = col.name;
821
+ if (grid == sarVGrid && colName !== 'Diff' && colName !== C.COLUMNS_NAMES.AMINO_ACID_RESIDUE)
822
+ col.width = 50;
741
823
  else
742
- col.width = grid.props.rowHeight;
824
+ col.width = gridProps.rowHeight + 10;
743
825
  }
744
826
  }
745
827
 
746
- sarGrid.props.allowEdit = false;
747
- sarVGrid.props.allowEdit = false;
748
- }
749
-
750
- //TODO: refactor, use this.sarDf and accept aar & position as parameters
751
- syncGrids(sourceVertical: boolean, sarDf: DG.DataFrame, sarVDf: DG.DataFrame): void {
752
- let otherColName: string;
753
- let otherRowIndex: number;
754
- const otherDf = sourceVertical ? sarDf : sarVDf;
755
-
756
- if (otherDf.temp[C.FLAGS.CELL_CHANGING])
757
- return;
758
-
759
- //on vertical SAR viewer click
760
- if (sourceVertical) {
761
- const currentRowIdx = sarVDf.currentRowIdx;
762
- const currentColName = sarVDf.currentCol.name;
763
- if (currentColName !== C.COLUMNS_NAMES.MEAN_DIFFERENCE)
764
- return;
765
-
766
- otherColName = sarVDf.get(C.COLUMNS_NAMES.POSITION, currentRowIdx);
767
- const otherRowName: string = sarVDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, currentRowIdx);
768
- otherRowIndex = -1;
769
- const rows = otherDf.rowCount;
770
- for (let i = 0; i < rows; i++) {
771
- if (otherDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, i) === otherRowName) {
772
- otherRowIndex = i;
773
- break;
774
- }
775
- }
776
- //on SAR viewer click
777
- } else {
778
- otherColName = C.COLUMNS_NAMES.MEAN_DIFFERENCE;
779
- const otherPos: string = sarDf.currentCol.name;
780
- if (otherPos === C.COLUMNS_NAMES.AMINO_ACID_RESIDUE)
781
- return;
828
+ const setViewerGridProps = (grid: DG.Grid) => {
829
+ grid.props.allowEdit = false;
830
+ grid.props.allowRowSelection = false;
831
+ grid.props.allowBlockSelection = false;
832
+ };
782
833
 
783
- const otherAAR: string =
784
- sarDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, sarDf.currentRowIdx);
785
- otherRowIndex = -1;
786
- for (let i = 0; i < sarVDf.rowCount; i++) {
787
- if (
788
- sarVDf.get(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE, i) === otherAAR &&
789
- sarVDf.get(C.COLUMNS_NAMES.POSITION, i) === otherPos
790
- ) {
791
- otherRowIndex = i;
792
- break;
793
- }
794
- }
795
- }
796
- otherDf.temp[C.FLAGS.CELL_CHANGING] = true;
797
- otherDf.currentCell = otherDf.cell(otherRowIndex, otherColName);
798
- otherDf.temp[C.FLAGS.CELL_CHANGING] = false;
834
+ setViewerGridProps(sarGrid);
835
+ setViewerGridProps(sarVGrid);
799
836
  }
800
837
 
801
838
  getSplitColValueAt(index: number, aar: string, position: string, aarLabel: string): string {
@@ -803,26 +840,12 @@ export class PeptidesModel {
803
840
  return currentAAR === aar ? aarLabel : C.CATEGORIES.OTHER;
804
841
  }
805
842
 
806
- modifyOrCreateSplitCol(aar: string, position: string): void {
807
- const df = this._dataFrame;
808
- this.splitCol = df.col(C.COLUMNS_NAMES.SPLIT_COL) ?? df.columns.addNew(C.COLUMNS_NAMES.SPLIT_COL, 'string');
809
-
810
- if (aar === C.CATEGORIES.ALL && position === C.CATEGORIES.ALL) {
811
- this.splitCol.init(() => C.CATEGORIES.ALL);
812
- return;
813
- }
814
-
815
- const aarLabel = `${aar === '-' ? 'Gap' : aar} : ${position}`;
816
- this.splitCol.init((i) => this.getSplitColValueAt(i, aar, position, aarLabel));
817
-
818
- this.splitCol.setCategoryOrder([aarLabel]);
843
+ modifyOrCreateSplitCol(): void {
844
+ const bs = this.getBiteset();
845
+ this.splitCol = this._dataFrame.col(C.COLUMNS_NAMES.SPLIT_COL) ??
846
+ this._dataFrame.columns.addNewBool(C.COLUMNS_NAMES.SPLIT_COL);
847
+ this.splitCol.init((i) => bs.get(i));
819
848
  this.splitCol.compact();
820
-
821
- const colorMap: {[index: string]: string | number} = {};
822
-
823
- colorMap[C.CATEGORIES.OTHER] = DG.Color.blue;
824
- colorMap[aarLabel] = DG.Color.orange;
825
- this.splitCol.colors.setCategorical(colorMap);
826
849
  }
827
850
 
828
851
  static async scaleActivity(
@@ -835,7 +858,7 @@ export class PeptidesModel {
835
858
  const tempDf = df.clone(cloneBitset ? df.filter : null, [currentActivityColName]);
836
859
 
837
860
  let formula = '${' + currentActivityColName + '}';
838
- let newColName = 'activity'; //originalActivityName ?? df.temp[C.COLUMNS_NAMES.ACTIVITY] ?? currentActivityColName;
861
+ let newColName = 'activity';
839
862
  switch (activityScaling) {
840
863
  case 'none':
841
864
  break;
@@ -921,13 +944,9 @@ export class PeptidesModel {
921
944
  ];
922
945
  }
923
946
 
924
- getCurrentAARandPos(): {aar: string, pos: string} {
925
- return {aar: this._dataFrame.getTag(C.TAGS.AAR) ?? 'All', pos: this._dataFrame.getTag(C.TAGS.POSITION) ?? 'All'};
926
- }
927
-
928
947
  syncProperties(isSourceSAR = true): void {
929
- const sarViewer = this._dataFrame.temp['sarViewer'];
930
- const sarViewerVertical = this._dataFrame.temp['sarViewerVertical'];
948
+ const sarViewer: SARViewer = this._dataFrame.temp['sarViewer'];
949
+ const sarViewerVertical: SARViewerVertical = this._dataFrame.temp['sarViewerVertical'];
931
950
  const sourceViewer = isSourceSAR ? sarViewer : sarViewerVertical;
932
951
  const targetViewer = isSourceSAR ? sarViewerVertical : sarViewer;
933
952
  const properties = sourceViewer.props.getProperties();
@@ -935,24 +954,6 @@ export class PeptidesModel {
935
954
  targetViewer.props.set(property.name, property.get(sourceViewer));
936
955
  }
937
956
 
938
- //TODO: move to viewer
939
- setSARGridCellAt(aar: string, position: string): void {
940
- const sarDf = this._sarGrid.dataFrame;
941
- const aarCol = sarDf.getCol(C.COLUMNS_NAMES.AMINO_ACID_RESIDUE);
942
- const aarColLen = aarCol.length;
943
- let index = -1;
944
- for (let i = 0; i < aarColLen; i++) {
945
- if (aarCol.get(i) === aar) {
946
- index = i;
947
- break;
948
- }
949
- }
950
- position = position === C.CATEGORIES.ALL ? C.COLUMNS_NAMES.AMINO_ACID_RESIDUE : position;
951
- sarDf.currentCell = sarDf.cell(index, position);
952
- }
953
-
954
- static get chemPalette(): typeof ChemPalette {return ChemPalette;}
955
-
956
957
  /** Class initializer */
957
958
  async init(): Promise<void> {
958
959
  if (this.isInitialized)
@@ -965,10 +966,16 @@ export class PeptidesModel {
965
966
  stats.setMask(this._dataFrame.selection);
966
967
  this._dataFrame.temp[C.STATS] = stats;
967
968
 
968
- this.currentView = grok.shell.addTableView(this._dataFrame);
969
+ this.currentView = this._dataFrame.tags[C.PEPTIDES_ANALYSIS] == 'true' ? grok.shell.v as DG.TableView :
970
+ grok.shell.addTableView(this._dataFrame);
969
971
  const sourceGrid = this.currentView.grid;
970
- sourceGrid.col(C.COLUMNS_NAMES.ACTIVITY_SCALED)!.name = this._dataFrame.temp[C.COLUMNS_NAMES.ACTIVITY_SCALED];
971
- sourceGrid.columns.setOrder([this._dataFrame.temp[C.COLUMNS_NAMES.ACTIVITY_SCALED]]);
972
+ if (this._dataFrame.tags[C.PEPTIDES_ANALYSIS] == 'true')
973
+ return;
974
+
975
+ this._dataFrame.tags[C.PEPTIDES_ANALYSIS] = 'true';
976
+ sourceGrid.col(C.COLUMNS_NAMES.ACTIVITY_SCALED)!.name = this._dataFrame.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED];
977
+ sourceGrid.columns.setOrder([this._dataFrame.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED]]);
978
+
972
979
 
973
980
  this._dataFrame.temp[C.EMBEDDING_STATUS] = false;
974
981
  const adjustCellSize = (grid: DG.Grid): void => {
@@ -983,9 +990,8 @@ export class PeptidesModel {
983
990
  for (let i = 0; i < sourceGrid.columns.length; i++) {
984
991
  const aarCol = sourceGrid.columns.byIndex(i);
985
992
  if (aarCol && aarCol.name && aarCol.column?.semType !== C.SEM_TYPES.AMINO_ACIDS &&
986
- aarCol.name !== this._dataFrame.temp[C.COLUMNS_NAMES.ACTIVITY_SCALED]
987
- )
988
- sourceGrid.columns.byIndex(i)!.visible = false;
993
+ aarCol.name !== this._dataFrame.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED])
994
+ aarCol.visible = false;
989
995
  }
990
996
 
991
997
  const options = {scaling: this._dataFrame.tags['scaling']};
@@ -993,20 +999,19 @@ export class PeptidesModel {
993
999
 
994
1000
  const dockManager = this.currentView.dockManager;
995
1001
 
996
- const sarViewer =
997
- await this._dataFrame.plot.fromType('peptide-sar-viewer', options) as SARViewer;
998
- this._dataFrame.temp['sarViewer'] = sarViewer;
1002
+ const sarViewer = await this._dataFrame.plot.fromType('peptide-sar-viewer', options) as SARViewer;
999
1003
 
1000
1004
  const sarViewerVertical =
1001
1005
  await this._dataFrame.plot.fromType('peptide-sar-viewer-vertical', options) as SARViewerVertical;
1002
- this._dataFrame.temp['sarViewerVertical'] = sarViewer;
1003
1006
 
1004
1007
  const sarViewersGroup: viewerTypes[] = [sarViewer, sarViewerVertical];
1005
1008
 
1006
- const peptideSpaceViewerOptions = {method: 't-SNE', measure: 'Levenshtein', cyclesCount: 100};
1007
- const peptideSpaceViewer =
1008
- await this._dataFrame.plot.fromType('peptide-space-viewer', peptideSpaceViewerOptions) as PeptideSpaceViewer;
1009
- dockManager.dock(peptideSpaceViewer, DG.DOCK_TYPE.RIGHT, null, 'Peptide Space Viewer');
1009
+ if (this._dataFrame.rowCount <= 10000) {
1010
+ const peptideSpaceViewerOptions = {method: 'UMAP', measure: 'Levenshtein', cyclesCount: 100};
1011
+ const peptideSpaceViewer =
1012
+ await this._dataFrame.plot.fromType('peptide-space-viewer', peptideSpaceViewerOptions) as PeptideSpaceViewer;
1013
+ dockManager.dock(peptideSpaceViewer, DG.DOCK_TYPE.RIGHT, null, 'Peptide Space Viewer');
1014
+ }
1010
1015
 
1011
1016
  dockViewers(sarViewersGroup, DG.DOCK_TYPE.RIGHT, dockManager, DG.DOCK_TYPE.DOWN);
1012
1017
 
@@ -10,10 +10,10 @@ export {tests};
10
10
 
11
11
  //name: test
12
12
  //input: string category {optional: true}
13
- //input: string t {optional: true}
13
+ //input: string test {optional: true}
14
14
  //output: dataframe result
15
15
  //top-menu: Tools | Dev | JS API Tests
16
- export async function test(category: string, t: string): Promise<DG.DataFrame> {
17
- const data = await runTests({category, test: t});
16
+ export async function test(category: string, test: string): Promise<DG.DataFrame> {
17
+ const data = await runTests({category, test: test});
18
18
  return DG.DataFrame.fromObjects(data)!;
19
19
  }
package/src/package.ts CHANGED
@@ -18,9 +18,7 @@ import {manualAlignmentWidget} from './widgets/manual-alignment';
18
18
  import {SARViewer, SARViewerVertical} from './viewers/sar-viewer';
19
19
  import {peptideMoleculeWidget, getMolecule} from './widgets/peptide-molecule';
20
20
  import {runKalign, testMSAEnoughMemory} from './utils/multiple-sequence-alignment';
21
- import {substitutionsWidget} from './widgets/subst-table';
22
21
  import {msaWidget} from './widgets/multiple-sequence-alignment';
23
- import {getDistributionWidget} from './widgets/distribution';
24
22
  import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
25
23
 
26
24
  export const _package = new DG.Package();
@@ -236,26 +234,6 @@ export async function runTestMSAEnoughMemory(_table: DG.DataFrame, col: DG.Colum
236
234
  return col;
237
235
  }
238
236
 
239
- //name: Substitution
240
- //tags: panel, widgets
241
- //input: dataframe table {semType: Substitution}
242
- //output: widget result
243
- export async function peptideSubstitution(table: DG.DataFrame): Promise<DG.Widget> {
244
- if (!table.temp[C.PEPTIDES_ANALYSIS])
245
- return new DG.Widget(ui.divText('This widget is only applicable for peptides analysis'));
246
- return substitutionsWidget(table);
247
- }
248
-
249
- //name: Distribution
250
- //tags: panel, widgets
251
- //input: dataframe table {semType: viewerTable}
252
- //output: widget result
253
- export function peptideDistribution(table: DG.DataFrame): DG.Widget {
254
- if (!table.temp[C.PEPTIDES_ANALYSIS])
255
- return new DG.Widget(ui.divText('This widget is only applicable for peptides analysis'));
256
- return getDistributionWidget(table);
257
- }
258
-
259
237
  //name: Get Peptides Structure
260
238
  //tags: panel, widgets
261
239
  //input: column col {semType: alignedSequence}
package/src/tests/core.ts CHANGED
@@ -36,9 +36,11 @@ category('Core', () => {
36
36
  model = await startAnalysis(
37
37
  simpleActivityCol, simpleAlignedSeqCol, simpleTable, simpleScaledDf, simpleScaledColName, _package);
38
38
  expect(model instanceof PeptidesModel, true);
39
- model?.setSARGridCellAt('D', '11');
40
- if (model != null)
39
+
40
+ if (model != null) {
41
+ model.currentSelection = {'11': ['D']};
41
42
  grok.shell.closeTable(model._dataFrame);
43
+ }
42
44
  });
43
45
 
44
46
  test('Start analysis: сomplex', async () => {
@@ -56,8 +58,10 @@ category('Core', () => {
56
58
  model = await startAnalysis(
57
59
  complexActivityCol, complexAlignedSeqCol, complexTable, complexScaledDf, complexScaledColName, _package);
58
60
  expect(model instanceof PeptidesModel, true);
59
- model?.setSARGridCellAt('-', '13');
60
- if (model != null)
61
+
62
+ if (model != null) {
63
+ model.currentSelection = {'13': ['-']};
61
64
  grok.shell.closeTable(model._dataFrame);
65
+ }
62
66
  });
63
67
  });