@datagrok/peptides 1.0.1 → 1.0.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 (34) hide show
  1. package/dist/package-test.js +8275 -3759
  2. package/dist/package.js +19735 -14773
  3. package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +306 -215
  4. package/files/aligned.csv +648 -648
  5. package/files/aligned_2.csv +541 -10275
  6. package/files/aligned_3.csv +335 -0
  7. package/helm/JSDraw/Pistoia.HELM.js +27 -0
  8. package/package.json +17 -12
  9. package/src/__jest__/remote.test.ts +31 -13
  10. package/src/model.ts +321 -342
  11. package/src/package-test.ts +0 -1
  12. package/src/package.ts +13 -109
  13. package/src/tests/core.ts +48 -16
  14. package/src/tests/utils.ts +0 -11
  15. package/src/utils/cell-renderer.ts +92 -275
  16. package/src/utils/constants.ts +5 -4
  17. package/src/utils/misc.ts +103 -16
  18. package/src/utils/multiple-sequence-alignment.ts +1 -1
  19. package/src/utils/peptide-similarity-space.ts +1 -1
  20. package/src/utils/types.ts +7 -5
  21. package/src/viewers/peptide-space-viewer.ts +3 -3
  22. package/src/viewers/sar-viewer.ts +34 -23
  23. package/src/widgets/analyze-peptides.ts +23 -17
  24. package/src/widgets/distribution.ts +0 -1
  25. package/src/widgets/manual-alignment.ts +4 -4
  26. package/src/widgets/subst-table.ts +5 -2
  27. package/{test-Peptides-34f75e5127b8-4210edfc.html → test-Peptides-4f0c8bae6479-74cbfe68.html} +8 -8
  28. package/detectors.js +0 -9
  29. package/src/monomer-library.ts +0 -193
  30. package/src/tests/msa-tests.ts +0 -27
  31. package/src/utils/chem-palette.ts +0 -280
  32. package/src/viewers/stacked-barchart-viewer.ts +0 -321
  33. package/src/widgets/multiple-sequence-alignment.ts +0 -9
  34. package/src/widgets/peptide-molecule.ts +0 -82
@@ -1,280 +0,0 @@
1
- import * as grok from 'datagrok-api/grok';
2
- import * as ui from 'datagrok-api/ui';
3
- import * as DG from 'datagrok-api/dg';
4
-
5
- import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
6
- import {MonomerLibrary} from '../monomer-library';
7
-
8
-
9
- export class ChemPalette {
10
- cp: StringDictionary = {};
11
- isInit: boolean = false;
12
- monomerLib: MonomerLibrary | null = null;
13
-
14
- /**
15
- * Creates an instance of ChemPalette.
16
- *
17
- * @param {string} scheme Color scheme to use.
18
- * @param {boolean} [grouping=false] Is grouping enabled.
19
- * @memberof ChemPalette
20
- */
21
- private constructor(scheme: string, grouping = false) {
22
- if (scheme == 'grok')
23
- this.cp = ChemPalette.getDatagrok(grouping);
24
- }
25
-
26
- /**
27
- * Renders 2D representation of a amino acid residue in a tooltip.
28
- *
29
- * @param {DG.GridCell} cell Grid cell to show tooltip over.
30
- * @param {number} x x coordinate of the mouse pointer.
31
- * @param {number} y y coordinate of the mouse pointer.
32
- * @param {MonomerLibrary} monomerLib Monomer Library instance
33
- */
34
- static showTooltip(cell: DG.GridCell, x: number, y: number, monomerLib: MonomerLibrary): void {
35
- const s = cell.cell.value as string;
36
- let toDisplay = [ui.divText(s)];
37
- const [, aarOuter, aarInner] = ChemPalette.getColorAAPivot(s);
38
- for (const aar of [aarOuter, aarInner]) {
39
- if (monomerLib.monomerNames.includes(aar)) {
40
- if (aar in ChemPalette.AANames)
41
- toDisplay = [ui.divText(ChemPalette.AANames[aar])];
42
-
43
- if (aar in ChemPalette.AAFullNames)
44
- toDisplay = [ui.divText(ChemPalette.AANames[ChemPalette.AAFullNames[aar]])];
45
-
46
- const options = {
47
- autoCrop: true,
48
- autoCropMargin: 0,
49
- suppressChiralText: true,
50
- };
51
- const sketch = grok.chem.svgMol(monomerLib.getMonomerMol(aar), undefined, undefined, options);
52
- if (toDisplay.length == 2)
53
- toDisplay.push(ui.divText('Modified'));
54
-
55
- toDisplay.push(sketch);
56
- }
57
- }
58
- ui.tooltip.show(ui.divV(toDisplay), x, y);
59
- }
60
-
61
- /**
62
- * Retursn divided amino with its content in the bracket, if the conetent is number, then its omitted
63
- *
64
- * @param {string} c raw amino
65
- * @return {[string, string]} outer and inner content
66
- */
67
- static getInnerOuter(c: string): [string, string] {
68
- let isInner = 0;
69
- let inner = '';
70
- let outer = '';
71
-
72
- for (const char of c) {
73
- if (char == '(')
74
- isInner++;
75
- else if (char == ')')
76
- isInner--;
77
- else if (isInner)
78
- inner += char;
79
- else
80
- outer += char;
81
- }
82
-
83
- return !isNaN(parseInt(inner)) ? [outer, ''] : [outer, inner];
84
- }
85
-
86
- static getColorAAPivot(monomer: string = '', scheme: 'grok' = 'grok'): [string, string, string, number] {
87
- const chemPaletteInstance = ChemPalette.getPalette(scheme);
88
- let [outerMonomer, innerMonomer] = ChemPalette.getInnerOuter(monomer);
89
- outerMonomer = (outerMonomer.length > 6 ? `${outerMonomer.slice(0, 3)}...` : outerMonomer);
90
- innerMonomer = (innerMonomer.length > 6 ? `${innerMonomer.slice(0, 3)}...` : innerMonomer);
91
-
92
- if (monomer.length == 1 || monomer[1] == '(') {
93
- const amino = monomer[0]?.toUpperCase()!;
94
- return amino in chemPaletteInstance ?
95
- [chemPaletteInstance[amino], amino, innerMonomer, 1]:
96
- [ChemPalette.undefinedColor, outerMonomer, innerMonomer, 1];
97
- }
98
-
99
- if (monomer[0] == 'd' && monomer[1]! in chemPaletteInstance) {
100
- if (monomer.length == 2 || monomer[2] == '(') {
101
- const amino = monomer[1]?.toUpperCase()!;
102
- return amino in chemPaletteInstance ?
103
- [chemPaletteInstance[amino], amino, innerMonomer, 2]:
104
- [ChemPalette.undefinedColor, outerMonomer, innerMonomer, 2];
105
- }
106
- }
107
-
108
- if (monomer.substring(0, 3) in ChemPalette.AAFullNames) {
109
- if (monomer.length == 3 || monomer[3] == '(') {
110
- const amino = ChemPalette.AAFullNames[monomer.substring(0, 3)];
111
- return amino in chemPaletteInstance ?
112
- [chemPaletteInstance[amino], amino, innerMonomer, 3]:
113
- [ChemPalette.undefinedColor, outerMonomer, innerMonomer, 3];
114
- }
115
- }
116
-
117
- if (monomer[0]?.toLowerCase() == monomer[0]) {
118
- if (monomer.substring(1, 3) in ChemPalette.AAFullNames) {
119
- if (monomer.length == 4 || monomer[4] == '(') {
120
- const amino = ChemPalette.AAFullNames[monomer.substring(1, 3)];
121
- return amino in chemPaletteInstance ?
122
- [chemPaletteInstance[amino], amino, innerMonomer, 4]:
123
- [ChemPalette.undefinedColor, outerMonomer, innerMonomer, 4];
124
- }
125
- }
126
- }
127
-
128
- return [ChemPalette.undefinedColor, outerMonomer, innerMonomer, 0];
129
- }
130
-
131
- static colourPalette: {[key: string]: string[]} = {
132
- 'orange': ['rgb(255,187,120)', 'rgb(245,167,100)', 'rgb(235,137,70)', 'rgb(205, 111, 71)'],
133
- 'all_green': ['rgb(44,160,44)', 'rgb(74,160,74)', 'rgb(23,103,57)', 'rgb(30,110,96)', 'rgb(60,131,95)',
134
- 'rgb(24,110,79)', 'rgb(152,223,138)', 'rgb(182, 223, 138)', 'rgb(152, 193, 138)'],
135
- 'all_blue': ['rgb(31,119,180)', 'rgb(23,190,207)', 'rgb(122, 102, 189)', 'rgb(158,218,229)', 'rgb(141, 124, 217)',
136
- 'rgb(31, 120, 150)'],
137
- 'magenta': ['rgb(162,106,192)', 'rgb(197,165,224)', 'rgb(208,113,218)'],
138
- 'red': ['rgb(214,39,40)', 'rgb(255,152,150)'],
139
- 'st_blue': ['rgb(23,190,207)', 'rgb(158,218,229)', 'rgb(31,119,180)'],
140
- 'dark_blue': ['rgb(31,119,180)', 'rgb(31, 120, 150)'],
141
- 'light_blue': ['rgb(23,190,207)', 'rgb(158,218,229)', 'rgb(108, 218, 229)', 'rgb(23,190,227)'],
142
- 'lilac_blue': ['rgb(124,102,211)', 'rgb(149,134,217)', 'rgb(97, 81, 150)'],
143
- 'dark_green': ['rgb(23,103,57)', 'rgb(30,110,96)', 'rgb(60,131,95)', 'rgb(24,110,79)'],
144
- 'green': ['rgb(44,160,44)', 'rgb(74,160,74)'],
145
- 'light_green': ['rgb(152,223,138)', 'rgb(182, 223, 138)', 'rgb(152, 193, 138)'],
146
- 'st_green': ['rgb(44,160,44)', 'rgb(152,223,138)', 'rgb(39, 174, 96)', 'rgb(74,160,74)'],
147
- 'pink': ['rgb(247,182,210)'],
148
- 'brown': ['rgb(140,86,75)', 'rgb(102, 62, 54)'],
149
- 'gray': ['rgb(127,127,127)', 'rgb(199,199,199)', 'rgb(196,156,148)', 'rgb(222, 222, 180)'],
150
- 'yellow': ['rgb(188,189,34)'],
151
- 'white': ['rgb(230,230,230)'],
152
- };
153
-
154
- static grokGroups: {[key: string]: string[]} = {
155
- 'yellow': ['C', 'U'],
156
- 'red': ['G', 'P'],
157
- 'all_green': ['A', 'V', 'I', 'L', 'M', 'F', 'Y', 'W'],
158
- 'light_blue': ['R', 'H', 'K'],
159
- 'dark_blue': ['D', 'E'],
160
- 'orange': ['S', 'T', 'N', 'Q'],
161
- };
162
-
163
- static undefinedColor = 'rgb(100,100,100)';
164
-
165
- static makePalette(dt: {[key: string]: string[]}, simplified = false, grouping = false): StringDictionary {
166
- const palette: { [key: string]: string } = {};
167
- const groups = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
168
- let currentGroup = 0;
169
- for (const [color, monomers] of Object.entries(dt)) {
170
- monomers.forEach((monomer, index) => {
171
- palette[grouping ? groups[currentGroup] : monomer] = ChemPalette.colourPalette[color][simplified ? 0 : index];
172
- });
173
- currentGroup++;
174
- }
175
- return palette;
176
- }
177
-
178
- static AANames: StringDictionary = {
179
- 'G': 'Glycine',
180
- 'L': 'Leucine',
181
- 'Y': 'Tyrosine',
182
- 'S': 'Serine',
183
- 'E': 'Glutamic acid',
184
- 'Q': 'Glutamine',
185
- 'D': 'Aspartic acid',
186
- 'N': 'Asparagine',
187
- 'F': 'Phenylalanine',
188
- 'A': 'Alanine',
189
- 'K': 'Lysine',
190
- 'R': 'Arginine',
191
- 'H': 'Histidine',
192
- 'C': 'Cysteine',
193
- 'V': 'Valine',
194
- 'P': 'Proline',
195
- 'W': 'Tryptophan',
196
- 'I': 'Isoleucine',
197
- 'M': 'Methionine',
198
- 'T': 'Threonine',
199
- };
200
-
201
- static AASmiles: StringDictionary = {
202
- 'G': 'NCC(=O)O',
203
- 'L': 'N[C@H](CC(C)C)C(=O)O',
204
- 'Y': 'NC(CC1=CC=C(O)C=C1)C(=O)O',
205
- 'S': 'NC(CO)C(=O)O',
206
- 'E': 'N[C@@H](CCC(O)=O)C(=O)O',
207
- 'Q': 'N[C@@H](CCC(N)=O)C(=O)O',
208
- 'D': 'N[C@@H](CC(O)=O)C(=O)O',
209
- 'N': 'N[C@@H](CC(N)=O)C(=O)O',
210
- 'F': 'NC(CC1=CC=CC=C1)C(=O)O',
211
- 'A': 'N[C@H](C)C(=O)O',
212
- 'K': 'NC(CCCCN)C(=O)O',
213
- 'R': 'N[C@H](CCCNC(=N)C)C(=O)O',
214
- 'H': 'NC(CC1=CN=C[N]1)C(=O)O',
215
- 'C': 'N[C@@H](CS)C(=O)O',
216
- 'V': 'NC(C(C)C)C(=O)O',
217
- 'P': 'N(CCC1)C1C(=O)O',
218
- 'W': 'N[C@@H](Cc1c2ccccc2n([H])c1)C(=O)O',
219
- 'I': 'N[C@H]([C@H](C)CC)C(=O)O',
220
- 'M': 'NC(CCSC)C(=O)O',
221
- 'T': 'NC(C(O)C)C(=O)O',
222
- };
223
-
224
- static AASmilesTruncated: StringDictionary = {
225
- 'G': '*C*',
226
- 'L': 'CC(C)C[C@H](*)*',
227
- 'Y': 'C1=CC(=CC=C1CC(*)*)O',
228
- 'S': 'OCC(*)C*',
229
- 'E': '*[C@@H](CCC(O)=O)*',
230
- 'Q': '*N[C@@H](CCC(N)=O)*',
231
- 'D': '*[C@@H](CC(O)=O)*',
232
- 'N': '*[C@@H](CC(N)=O)*',
233
- 'F': 'C1=CC=C(C=C1)CC(*)*',
234
- 'A': 'C[C@H](*)*',
235
- 'K': 'C(CCN)CC(*)*',
236
- 'R': '*[C@H](CCCNC(=N)C)*',
237
- 'H': 'C1=C(NC=N1)CC(*)*',
238
- 'C': 'C([C@@H](*)*)S',
239
- 'V': 'CC(C)C(*)*',
240
- 'P': 'C1CCN(*)C1*',
241
- 'W': '*[C@@H](Cc1c2ccccc2n([H])c1)*',
242
- 'I': 'CC[C@H](C)[C@H](*)*',
243
- 'M': 'CSCCC(*)*',
244
- 'T': 'CC(O)C(*)*',
245
- };
246
-
247
- static AAFullNames: StringDictionary = {
248
- 'Ala': 'A',
249
- 'Arg': 'R',
250
- 'Asn': 'N',
251
- 'Asp': 'D',
252
- 'Cys': 'C',
253
- 'Gln': 'Q',
254
- 'Glu': 'E',
255
- 'Gly': 'G',
256
- 'His': 'H',
257
- 'Ile': 'I',
258
- 'Leu': 'L',
259
- 'Lys': 'K',
260
- 'Met': 'M',
261
- 'Phe': 'F',
262
- 'Pro': 'P',
263
- 'Ser': 'S',
264
- 'Thr': 'T',
265
- 'Trp': 'W',
266
- 'Tyr': 'Y',
267
- 'Val': 'V',
268
- };
269
-
270
- static getDatagrok(grouping = false): StringDictionary {
271
- return ChemPalette.makePalette(ChemPalette.grokGroups, false, grouping);
272
- }
273
-
274
- static getPalette(scheme: 'grok'): StringDictionary {
275
- if (scheme == 'grok')
276
- return ChemPalette.getDatagrok();
277
- else
278
- throw new Error(`ChemPalette: scheme \`${scheme}\` does not exist`);
279
- }
280
- }
@@ -1,321 +0,0 @@
1
- import * as DG from 'datagrok-api/dg';
2
- import * as rxjs from 'rxjs';
3
- import {MonomerLibrary} from '../monomer-library';
4
-
5
- import * as C from '../utils/constants';
6
- import * as type from '../utils/types';
7
- import {PeptidesModel} from '../model';
8
-
9
- export function addViewerToHeader(grid: DG.Grid, barchart: StackedBarChart): void {
10
- if (grid.temp['containsBarchart'])
11
- return;
12
-
13
- const eventAction = (ev: MouseEvent): void => {
14
- const cell = grid.hitTest(ev.offsetX, ev.offsetY);
15
- if (cell?.isColHeader && cell.tableColumn?.semType == C.SEM_TYPES.AMINO_ACIDS) {
16
- const newBarPart = barchart.findAARandPosition(cell, ev);
17
- // barchart._currentBarPart = newBarPart;
18
- barchart.requestAction(ev, newBarPart);
19
- barchart.computeData();
20
- }
21
- };
22
-
23
- // The following events makes the barchart interactive
24
- rxjs.fromEvent<MouseEvent>(grid.overlay, 'mousemove').subscribe((mouseMove: MouseEvent) => eventAction(mouseMove));
25
- rxjs.fromEvent<MouseEvent>(grid.overlay, 'click').subscribe((mouseMove: MouseEvent) => eventAction(mouseMove));
26
- rxjs.fromEvent<MouseEvent>(grid.overlay, 'mouseout').subscribe(() => barchart.computeData());
27
-
28
- barchart.tableCanvas = grid.canvas;
29
-
30
- //Setting grid options
31
- grid.setOptions({'colHeaderHeight': 130});
32
-
33
- grid.onCellTooltip((cell, x, y) => {
34
- const colSemType = cell.tableColumn?.semType as C.SEM_TYPES;
35
- if (colSemType == C.SEM_TYPES.ALIGNED_SEQUENCE || colSemType == C.SEM_TYPES.AMINO_ACIDS) {
36
- if (!cell.isColHeader) {
37
- const monomerLib = cell.cell.dataFrame.temp[MonomerLibrary.id];
38
- PeptidesModel.chemPalette.showTooltip(cell, x, y, monomerLib);
39
- }
40
- }
41
- return true;
42
- });
43
-
44
- grid.onCellRender.subscribe((args) => {
45
- const context = args.g;
46
- const boundX = args.bounds.x;
47
- const boundY = args.bounds.y;
48
- const boundWidth = args.bounds.width;
49
- const boundHeight = args.bounds.height;
50
- const cell = args.cell;
51
- context.save();
52
- context.beginPath();
53
- context.rect(boundX, boundY, boundWidth, boundHeight);
54
- context.clip();
55
-
56
- if (cell.isColHeader && barchart.aminoColumnNames.includes(cell.gridColumn.name)) {
57
- barchart.renderBarToCanvas(context, cell, boundX, boundY, boundWidth, boundHeight);
58
- args.preventDefault();
59
- }
60
- context.restore();
61
- });
62
-
63
- grid.temp['containsBarchart'] = true;
64
- }
65
-
66
- export class StackedBarChart extends DG.JsViewer {
67
- dataEmptyAA: string;
68
- tableCanvas: HTMLCanvasElement | undefined;
69
- aminoColumnNames: string[] = [];
70
- ord: { [Key: string]: number; } = {};
71
- aminoColumnIndices: {[Key: string]: number} = {};
72
- aggregatedFilterTables: type.DataFrameDict = {};
73
- max = 0;
74
- barStats: {[Key: string]: type.BarChart.BarStatsObject[]} = {};
75
- selected: type.BarChart.BarPart[] = [];
76
- aggregatedSelectedTables: type.DataFrameDict = {};
77
- model!: PeptidesModel;
78
-
79
- constructor() {
80
- super();
81
- this.dataEmptyAA = this.string('dataEmptyAA', '-');
82
- }
83
-
84
- init(): void {
85
- const groups: {[key: string]: string[]} = {
86
- 'yellow': ['C', 'U'],
87
- 'red': ['G', 'P'],
88
- 'all_green': ['A', 'V', 'I', 'L', 'M', 'F', 'Y', 'W'],
89
- 'light_blue': ['R', 'H', 'K'],
90
- 'dark_blue': ['D', 'E'],
91
- 'orange': ['S', 'T', 'N', 'Q'],
92
- };
93
- let i = 0;
94
-
95
- for (const value of Object.values(groups)) {
96
- for (const obj of value)
97
- this.ord[obj] = i++;
98
- }
99
-
100
- this.aminoColumnNames = [];
101
- }
102
-
103
- // Stream subscriptions
104
- async onTableAttached(): Promise<void> {
105
- this.init();
106
- this.model = await PeptidesModel.getInstance(this.dataFrame);
107
- // this.controller.init(this.dataFrame);
108
- if (this.dataFrame) {
109
- this.subs.push(DG.debounce(this.dataFrame.selection.onChanged, 50).subscribe((_) => this.computeData()));
110
- this.subs.push(DG.debounce(this.dataFrame.filter.onChanged, 50).subscribe((_) => this.computeData()));
111
- this.subs.push(DG.debounce(this.dataFrame.onValuesChanged, 50).subscribe(() => this.computeData()));
112
- }
113
- this.computeData();
114
- }
115
-
116
- // Cancel subscriptions when the viewer is detached
117
- detach(): void {
118
- this.subs.forEach((sub) => sub.unsubscribe());
119
- }
120
-
121
- computeData(): void {
122
- this.aminoColumnNames = [];
123
- this.aminoColumnIndices = {};
124
-
125
- this.dataFrame.columns.names().forEach((name: string) => {
126
- if (this.dataFrame.getCol(name).semType === C.SEM_TYPES.AMINO_ACIDS &&
127
- !this.dataFrame.getCol(name).categories.includes('COOH') &&
128
- !this.dataFrame.getCol(name).categories.includes('NH2')) {
129
- this.aminoColumnIndices[name] = this.aminoColumnNames.length + 1;
130
- this.aminoColumnNames.push(name);
131
- }
132
- });
133
-
134
- this.aggregatedFilterTables = {};
135
- this.aggregatedSelectedTables = {};
136
- //TODO: optimize it, why store so many tables?
137
- this.aminoColumnNames.forEach((name) => {
138
- this.aggregatedFilterTables[name] = this.dataFrame
139
- .groupBy([name])
140
- .whereRowMask(this.dataFrame.filter)
141
- .add('count', name, `${name}_count`)
142
- .aggregate();
143
-
144
- this.aggregatedSelectedTables[name] = this.dataFrame
145
- .groupBy([name])
146
- .whereRowMask(this.dataFrame.selection)
147
- .add('count', name, `${name}_count`)
148
- .aggregate();
149
- });
150
-
151
- this.barStats = {};
152
-
153
- for (const [name, df] of Object.entries(this.aggregatedFilterTables)) {
154
- const colData: {'name': string, 'count': number, 'selectedCount': number}[] = [];
155
- const aminoCol = df.getCol(name);
156
- const aminoCountCol = df.getCol(`${name}_count`);
157
- this.barStats[name] = colData;
158
-
159
- for (let i = 0; i < df.rowCount; i++) {
160
- const amino = aminoCol.get(i);
161
- const aminoCount = aminoCountCol.get(i);
162
- const aminoObj = {'name': amino, 'count': aminoCount, 'selectedCount': 0};
163
- const aggSelectedAminoCol = this.aggregatedSelectedTables[name].getCol(`${name}`);
164
- const aggSelectedCountCol = this.aggregatedSelectedTables[name].getCol(`${name}_count`);
165
-
166
- if (!amino || amino === this.dataEmptyAA)
167
- continue;
168
-
169
- colData.push(aminoObj);
170
-
171
- for (let j = 0; j < aggSelectedCountCol.length; j++) {
172
- const selectedAmino = aggSelectedAminoCol.get(j);
173
- const curAmino = (selectedAmino);
174
- if (curAmino == amino) {
175
- aminoObj['selectedCount'] = aggSelectedCountCol.get(j);
176
- break;
177
- }
178
- }
179
- }
180
-
181
- colData.sort((o1, o2) => this.ord[o2['name']] - this.ord[o1['name']]);
182
- }
183
-
184
- this.max = this.dataFrame.filter.trueCount;
185
- }
186
-
187
- renderBarToCanvas(g: CanvasRenderingContext2D, cell: DG.GridCell, x: number, y: number, w: number, h: number): void {
188
- const name = cell.tableColumn!.name;
189
- const colNameSize = g.measureText(name).width;
190
- const barData = this.barStats[name];
191
- const margin = 0.2;
192
- const innerMargin = 0.02;
193
- const selectLineRatio = 0.1;
194
- let sum = 0;
195
-
196
- barData.forEach((obj) => {
197
- sum += obj['count'];
198
- });
199
-
200
- x = x + w * margin;
201
- y = y + h * margin / 4;
202
- w = w - w * margin * 2;
203
- h = h - h * margin;
204
- const barWidth = w - 10;
205
- g.fillStyle = 'black';
206
- g.textBaseline = 'top';
207
- g.font = `${h * margin / 2}px`;
208
- g.fillText(name, x + (w - colNameSize) / 2, y + h + h * margin / 4);
209
-
210
- barData.forEach((obj) => {
211
- const sBarHeight = h * obj['count'] / this.max;
212
- const gapSize = sBarHeight * innerMargin;
213
- const verticalShift = (this.max - sum) / this.max;
214
- const [color, aarOuter] = PeptidesModel.chemPalette.getColorAAPivot(obj['name']);
215
- const textSize = g.measureText(aarOuter);
216
- const fontSize = 11;
217
- const leftMargin = (w - (aarOuter.length > 1 ? fontSize : textSize.width - 8)) / 2;
218
- const subBartHeight = sBarHeight - gapSize;
219
- const yStart = h * verticalShift + gapSize / 2;
220
- const xStart = (w - barWidth) / 2;
221
- const absX = x + leftMargin;
222
- const absY = y + yStart + subBartHeight / 2 + (aarOuter.length == 1 ? + 4 : 0);
223
- const eps = 0.1;
224
-
225
- g.strokeStyle = color;
226
- g.fillStyle = color;
227
- if (textSize.width <= subBartHeight) {
228
- const origTransform = g.getTransform();
229
-
230
- if (color != PeptidesModel.chemPalette.undefinedColor) {
231
- g.fillRect(x + xStart, y + yStart, barWidth, subBartHeight);
232
- g.fillStyle = 'black';
233
- } else
234
- g.strokeRect(x + xStart + 0.5, y + yStart, barWidth - 1, subBartHeight);
235
-
236
- g.font = `${fontSize}px monospace`;
237
- g.textAlign = 'center';
238
- g.textBaseline = 'bottom';
239
-
240
- if (aarOuter.length > 1) {
241
- g.translate(absX, absY);
242
- g.rotate(Math.PI / 2);
243
- g.translate(-absX, -absY);
244
- }
245
-
246
- g.fillText(aarOuter, absX, absY);
247
- g.setTransform(origTransform);
248
- } else
249
- g.fillRect(x + xStart, y + yStart, barWidth, subBartHeight);
250
-
251
- if (obj['selectedCount'] > eps) {
252
- g.fillStyle = 'rgb(255,165,0)';
253
- g.fillRect(
254
- x + xStart - w * selectLineRatio * 2,
255
- y + yStart,
256
- barWidth * selectLineRatio,
257
- h * obj['selectedCount'] / this.max - gapSize,
258
- );
259
- }
260
-
261
- sum -= obj['count'];
262
- });
263
- }
264
-
265
- //TODO: refactor and simplify it
266
- findAARandPosition(cell: DG.GridCell, mouseEvent: MouseEvent): {colName: string, aaName: string} | null {
267
- if (!cell.tableColumn?.name || !this.aminoColumnNames.includes(cell.tableColumn.name))
268
- return null;
269
-
270
- const offsetX = mouseEvent.offsetX;
271
- const offsetY = mouseEvent.offsetY;
272
- const colName = cell.tableColumn?.name;
273
- const innerMargin = 0.02;
274
- const margin = 0.2;
275
- const bound = cell.bounds;
276
- const height = 130;
277
- const x = bound.x + bound.width * margin;
278
- const y = height * margin / 4;
279
- const w = bound.width - bound.width * margin * 2;
280
- const h = height - height * margin;
281
- const barData = this.barStats[colName];
282
- const barWidth = w - 10;
283
- let sum = 0;
284
-
285
- barData.forEach((obj) => {
286
- sum += obj['count'];
287
- });
288
-
289
- const xStart = x + (w - barWidth) / 2;
290
- for (const obj of barData) {
291
- const sBarHeight = h * obj['count'] / this.max;
292
- const gapSize = sBarHeight * innerMargin;
293
- const verticalShift = (this.max - sum) / this.max;
294
- const subBartHeight = sBarHeight - gapSize;
295
- const yStart = y + h * verticalShift + gapSize / 2;
296
-
297
- const isIntersectingX = offsetX >= xStart && offsetX <= xStart + barWidth;
298
- const isIntersectingY = offsetY >= yStart && offsetY <= yStart + subBartHeight;
299
-
300
- if (isIntersectingX && isIntersectingY)
301
- return {'colName': colName, 'aaName': obj['name']};
302
-
303
- sum -= obj['count'];
304
- }
305
-
306
- return null;
307
- }
308
-
309
- /** Requests highlight/select/filter action based on currentBarPart */
310
- requestAction(event: MouseEvent, barPart: {colName: string, aaName: string} | null): void {
311
- if (!barPart)
312
- return;
313
- const aar = barPart['aaName'];
314
- const position = barPart['colName'];
315
- if (event.type === 'click') {
316
- event.shiftKey ? this.model.modifyCurrentSelection(aar, position) :
317
- this.model.initCurrentSelection(aar, position);
318
- } else
319
- this.model.showTooltip(aar, position, event.clientX, event.clientY);
320
- }
321
- }
@@ -1,9 +0,0 @@
1
- import * as DG from 'datagrok-api/dg';
2
- import {runKalign} from '../utils/multiple-sequence-alignment';
3
-
4
- export async function msaWidget(col: DG.Column): Promise<DG.DataFrame> {
5
- const msaCol = await runKalign(col, true);
6
- const table = col.dataFrame;
7
- table.columns.add(msaCol);
8
- return table;
9
- }
@@ -1,82 +0,0 @@
1
- import * as grok from 'datagrok-api/grok';
2
- import * as ui from 'datagrok-api/ui';
3
- import * as DG from 'datagrok-api/dg';
4
- import * as C from '../utils/constants';
5
- import {PeptidesModel} from '../model';
6
-
7
- /**
8
- * 3D representation widget of peptide molecule.
9
- *
10
- * @export
11
- * @param {string} pep Peptide string.
12
- * @return {Promise<DG.Widget>} Widget.
13
- */
14
- export async function peptideMoleculeWidget(pep: string, currentTable: DG.DataFrame): Promise<DG.Widget> {
15
- const pi = DG.TaskBarProgressIndicator.create('Creating NGL view');
16
- const separator = currentTable.columns.bySemType(C.SEM_TYPES.ALIGNED_SEQUENCE)!.tags[C.TAGS.SEPARATOR];
17
-
18
- let widgetHost;
19
- let smiles = '';
20
- let molfileStr = '';
21
- try {
22
- try {
23
- const params = {table: currentTable};
24
- const result = await grok.functions.call('Customerextensions:getPeptideStructure', params) as string[];
25
- if (result.length !== 0) {
26
- smiles = result[0];
27
- molfileStr = result[1];
28
- throw new Error(`Found structure in DB`);
29
- }
30
-
31
- smiles = getMolecule(pep, separator);
32
- if (smiles == '')
33
- throw new Error('Couldn\'t get smiles');
34
-
35
- molfileStr = (await grok.functions.call('Peptides:SmiTo3D', {smiles})) as string;
36
- } catch (e) {
37
- console.warn(e);
38
- }
39
-
40
- try {
41
- molfileStr = molfileStr.replaceAll('\\n', '\n');
42
- const stringBlob = new Blob([molfileStr], {type: 'text/plain'});
43
- const nglHost = ui.div([], {classes: 'd4-ngl-viewer', id: 'ngl-3d-host'});
44
-
45
- //@ts-ignore
46
- const stage = new NGL.Stage(nglHost, {backgroundColor: 'white'});
47
- //@ts-ignore
48
- stage.loadFile(stringBlob, {ext: 'sdf'}).then(function(comp: NGL.StructureComponent) {
49
- stage.setSize(300, 300);
50
- comp.addRepresentation('ball+stick');
51
- comp.autoView();
52
- });
53
- const sketch = grok.chem.svgMol(molfileStr);
54
- const panel = ui.divH([sketch]);
55
-
56
- widgetHost = ui.div([panel, nglHost]);
57
- } catch (e) {
58
- widgetHost = ui.divText('Couldn\'t get peptide structure');
59
- }
60
- } catch (e) {
61
- widgetHost = ui.divText('Couldn\'t get peptide structure');
62
- }
63
- pi.close();
64
- return new DG.Widget(widgetHost);
65
- }
66
-
67
- export function getMolecule(pep: string, separator: string): string {
68
- const split = pep.split(separator);
69
- const mols = [];
70
- const chemPalette = PeptidesModel.chemPalette;
71
- for (let i = 1; i < split.length - 1; i++) {
72
- if (split[i] in chemPalette.AASmiles) {
73
- const aar = chemPalette.AASmiles[split[i]];
74
- mols[i] = aar.substring(0, aar.length - 1);
75
- } else if (!split[i] || split[i] == '-')
76
- mols[i] = '';
77
- else
78
- return '';
79
- }
80
-
81
- return mols.join('') + 'O';
82
- }