@datagrok/peptides 0.3.0 → 0.5.6
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/.eslintrc.json +29 -0
- package/package.json +4 -4
- package/src/describe.ts +92 -41
- package/src/package.ts +13 -35
- package/src/peptides.ts +93 -0
- package/src/utils/cell-renderer.ts +185 -60
- package/src/utils/chem-palette.ts +316 -208
- package/src/utils/correlation-analysis.ts +165 -70
- package/src/utils/peptide-similarity-space.ts +29 -25
- package/src/utils/split-aligned.ts +8 -1
- package/src/viewers/logo-viewer.ts +48 -5
- package/src/viewers/model.ts +56 -16
- package/src/viewers/sar-viewer.ts +100 -33
- package/src/viewers/spiral-plot.ts +97 -0
- package/src/viewers/stacked-barchart-viewer.ts +84 -9
- package/src/widgets/analyze-peptides.ts +18 -34
- package/src/widgets/manual-alignment.ts +12 -4
- package/src/widgets/peptide-molecule.ts +8 -1
- package/src/workers/dimensionality-reducer.ts +1 -1
|
@@ -3,13 +3,22 @@ import * as DG from 'datagrok-api/dg';
|
|
|
3
3
|
|
|
4
4
|
const cp = new ChemPalette('grok');
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
/**
|
|
7
|
+
* A function to expand column size based on its contents.
|
|
8
|
+
*
|
|
9
|
+
* @export
|
|
10
|
+
* @param {DG.Column} col Column to expand.
|
|
11
|
+
* @param {DG.Grid} grid Grid containing colum for expansion.
|
|
12
|
+
* @param {(cellVal: string) => number} cellRenderSize An anonymous function that calculates cell value length.
|
|
13
|
+
* @param {number} [textSizeMult=10] Text size muliplier.
|
|
14
|
+
* @param {number} [minSize=30] Minimal column width.
|
|
15
|
+
* @param {number} [maxSize=650] Maximum column width.
|
|
16
|
+
* @param {number} [timeout=500] Timeout value.
|
|
17
|
+
*/
|
|
18
|
+
export function expandColumn(
|
|
19
|
+
col: DG.Column, grid: DG.Grid, cellRenderSize: (cellVal: string) => number,
|
|
20
|
+
textSizeMult = 10, minSize = 30, maxSize = 650, timeout = 500,
|
|
21
|
+
) {
|
|
13
22
|
let maxLen = 0;
|
|
14
23
|
col.categories.forEach((ent: string) => {
|
|
15
24
|
const len = cellRenderSize(ent);
|
|
@@ -23,24 +32,57 @@ export function expandColumn(col:DG.Column,
|
|
|
23
32
|
timeout);
|
|
24
33
|
}
|
|
25
34
|
|
|
26
|
-
|
|
35
|
+
/**
|
|
36
|
+
* A function that sets amino acid residue to the specified column.
|
|
37
|
+
*
|
|
38
|
+
* @export
|
|
39
|
+
* @param {DG.Column} col Column to set renderer for.
|
|
40
|
+
* @param {(DG.Grid | null)} [grid=null] Grid that contains the col column.
|
|
41
|
+
* @param {boolean} [grouping=false] Is grouping enabled.
|
|
42
|
+
*/
|
|
43
|
+
export function setAARRenderer(col: DG.Column, grid: DG.Grid | null = null, grouping = false) {
|
|
27
44
|
col.semType = 'aminoAcids';
|
|
28
45
|
col.setTag('cell.renderer', 'aminoAcids');
|
|
29
|
-
if (
|
|
46
|
+
if (grouping) {
|
|
47
|
+
col.setTag('groups', `${grouping}`);
|
|
48
|
+
}
|
|
49
|
+
if (grid) {
|
|
30
50
|
expandColumn(col, grid, (ent) => measureAAR(ent));
|
|
51
|
+
}
|
|
31
52
|
}
|
|
32
|
-
|
|
53
|
+
/**
|
|
54
|
+
* A function to measure amino acid residue
|
|
55
|
+
*
|
|
56
|
+
* @export
|
|
57
|
+
* @param {string} s Amino acid residue string.
|
|
58
|
+
* @return {number} Amino acid residue size.
|
|
59
|
+
*/
|
|
33
60
|
export function measureAAR(s: string): number {
|
|
34
61
|
const end = s.lastIndexOf(')');
|
|
35
62
|
const beg = s.indexOf('(');
|
|
36
|
-
return end == beg ? s.length:s.length - (end-beg)+1;
|
|
63
|
+
return end == beg ? s.length : s.length - (end - beg) + 1;
|
|
37
64
|
}
|
|
38
65
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
66
|
+
/**
|
|
67
|
+
* A function that prints a string aligned to left or centered.
|
|
68
|
+
*
|
|
69
|
+
* @param {number} x x coordinate.
|
|
70
|
+
* @param {number} y y coordinate.
|
|
71
|
+
* @param {number} w Width.
|
|
72
|
+
* @param {number} h Height.
|
|
73
|
+
* @param {CanvasRenderingContext2D} g Canvas rendering context.
|
|
74
|
+
* @param {string} s String to print.
|
|
75
|
+
* @param {string} [color=ChemPalette.undefinedColor] String color.
|
|
76
|
+
* @param {number} [pivot=0] Pirvot.
|
|
77
|
+
* @param {boolean} [left=false] Is left aligned.
|
|
78
|
+
* @param {boolean} [hideMod=false] Hide amino acid redidue modifications.
|
|
79
|
+
* @return {number} x coordinate to start printing at.
|
|
80
|
+
*/
|
|
81
|
+
function printLeftOrCentered(
|
|
82
|
+
x: number, y: number, w: number, h: number,
|
|
83
|
+
g: CanvasRenderingContext2D, s: string, color = ChemPalette.undefinedColor,
|
|
84
|
+
pivot: number = 0, left = false, hideMod = false,
|
|
85
|
+
) {
|
|
44
86
|
g.textAlign = 'start';
|
|
45
87
|
let colorPart = pivot == -1 ? s.substring(0) : s.substring(0, pivot);
|
|
46
88
|
if (colorPart.length == 1) {
|
|
@@ -91,22 +133,66 @@ function printLeftCentered(
|
|
|
91
133
|
if (left || textSize.width > w) {
|
|
92
134
|
draw(indent, indent + colorTextSize.width);
|
|
93
135
|
return x + colorTextSize.width + g.measureText(grayPart).width;
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
136
|
+
} else {
|
|
96
137
|
draw((w - textSize.width) / 2, (w - textSize.width) / 2 + colorTextSize.width);
|
|
97
138
|
return x + (w - textSize.width) / 2 + colorTextSize.width;
|
|
98
139
|
}
|
|
99
140
|
}
|
|
100
141
|
|
|
101
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Amino acid residue cell renderer.
|
|
144
|
+
*
|
|
145
|
+
* @export
|
|
146
|
+
* @class AminoAcidsCellRenderer
|
|
147
|
+
* @extends {DG.GridCellRenderer}
|
|
148
|
+
*/
|
|
102
149
|
export class AminoAcidsCellRenderer extends DG.GridCellRenderer {
|
|
150
|
+
chemPalette: ChemPalette | null;
|
|
103
151
|
|
|
104
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Renderer name.
|
|
154
|
+
*
|
|
155
|
+
* @readonly
|
|
156
|
+
* @memberof AminoAcidsCellRenderer
|
|
157
|
+
*/
|
|
158
|
+
get name() {
|
|
159
|
+
return 'aminoAcidsCR';
|
|
160
|
+
}
|
|
105
161
|
|
|
106
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Cell type.
|
|
164
|
+
*
|
|
165
|
+
* @readonly
|
|
166
|
+
* @memberof AminoAcidsCellRenderer
|
|
167
|
+
*/
|
|
168
|
+
get cellType() {
|
|
169
|
+
return 'aminoAcids';
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Constructor.
|
|
174
|
+
*/
|
|
175
|
+
constructor() {
|
|
176
|
+
super();
|
|
177
|
+
this.chemPalette = null;
|
|
178
|
+
}
|
|
107
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Cell renderer function.
|
|
182
|
+
*
|
|
183
|
+
* @param {CanvasRenderingContext2D} g Canvas rendering context.
|
|
184
|
+
* @param {number} x x coordinate on the canvas.
|
|
185
|
+
* @param {number} y y coordinate on the canvas.
|
|
186
|
+
* @param {number} w width of the cell.
|
|
187
|
+
* @param {number} h height of the cell.
|
|
188
|
+
* @param {DG.GridCell} gridCell Grid cell.
|
|
189
|
+
* @param {DG.GridCellStyle} cellStyle Cell style.
|
|
190
|
+
*/
|
|
108
191
|
render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
|
|
109
|
-
|
|
192
|
+
gridCell: DG.GridCell, cellStyle: DG.GridCellStyle) {
|
|
193
|
+
if (this.chemPalette === null) {
|
|
194
|
+
this.chemPalette = new ChemPalette('grok', gridCell.tableColumn?.getTag('groups') ? true : false);
|
|
195
|
+
}
|
|
110
196
|
g.save();
|
|
111
197
|
g.beginPath();
|
|
112
198
|
g.rect(x, y, w, h);
|
|
@@ -115,63 +201,102 @@ export class AminoAcidsCellRenderer extends DG.GridCellRenderer {
|
|
|
115
201
|
g.textBaseline = 'top';
|
|
116
202
|
const s: string = gridCell.cell.value ? gridCell.cell.value : '-';
|
|
117
203
|
const [color, pivot] = cp.getColorPivot(s);
|
|
118
|
-
|
|
204
|
+
printLeftOrCentered(x, y, w, h, g, s, color, pivot, false, true);
|
|
119
205
|
g.restore();
|
|
120
206
|
}
|
|
121
207
|
}
|
|
122
208
|
|
|
123
|
-
|
|
209
|
+
/**
|
|
210
|
+
* Aligned sequence cell renderer.
|
|
211
|
+
*
|
|
212
|
+
* @export
|
|
213
|
+
* @class AlignedSequenceCellRenderer
|
|
214
|
+
* @extends {DG.GridCellRenderer}
|
|
215
|
+
*/
|
|
124
216
|
export class AlignedSequenceCellRenderer extends DG.GridCellRenderer {
|
|
217
|
+
/**
|
|
218
|
+
* Renderer name.
|
|
219
|
+
*
|
|
220
|
+
* @readonly
|
|
221
|
+
* @memberof AlignedSequenceCellRenderer
|
|
222
|
+
*/
|
|
223
|
+
get name() {
|
|
224
|
+
return 'alignedSequenceCR';
|
|
225
|
+
}
|
|
125
226
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Cell type.
|
|
229
|
+
*
|
|
230
|
+
* @readonly
|
|
231
|
+
* @memberof AlignedSequenceCellRenderer
|
|
232
|
+
*/
|
|
233
|
+
get cellType() {
|
|
234
|
+
return 'alignedSequence';
|
|
235
|
+
}
|
|
129
236
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
x = printLeftCentered(x, y, w, h, g, amino, color, pivot, true);
|
|
154
|
-
});
|
|
237
|
+
/**
|
|
238
|
+
* Cell renderer function.
|
|
239
|
+
*
|
|
240
|
+
* @param {CanvasRenderingContext2D} g Canvas rendering context.
|
|
241
|
+
* @param {number} x x coordinate on the canvas.
|
|
242
|
+
* @param {number} y y coordinate on the canvas.
|
|
243
|
+
* @param {number} w width of the cell.
|
|
244
|
+
* @param {number} h height of the cell.
|
|
245
|
+
* @param {DG.GridCell} gridCell Grid cell.
|
|
246
|
+
* @param {DG.GridCellStyle} cellStyle Cell style.
|
|
247
|
+
* @memberof AlignedSequenceCellRenderer
|
|
248
|
+
*/
|
|
249
|
+
render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
|
|
250
|
+
gridCell: DG.GridCell, cellStyle: DG.GridCellStyle ) {
|
|
251
|
+
w = Math.min(gridCell.grid.canvas.width - x, w);
|
|
252
|
+
g.save();
|
|
253
|
+
g.beginPath();
|
|
254
|
+
g.rect(x, y, w, h);
|
|
255
|
+
g.clip();
|
|
256
|
+
g.font = '14px monospace';
|
|
257
|
+
g.textBaseline = 'top';
|
|
258
|
+
const s: string = gridCell.cell.value ?? '';
|
|
155
259
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
260
|
+
//TODO: can this be replaced/merged with splitSequence?
|
|
261
|
+
const subParts = s.split('-');
|
|
262
|
+
const [text, simplified] = processSequence(subParts);
|
|
263
|
+
const textSize = g.measureText(text.join(''));
|
|
264
|
+
x = Math.max(x, x + (w - textSize.width) / 2);
|
|
159
265
|
|
|
266
|
+
subParts.forEach((amino: string, index) => {
|
|
267
|
+
const [color, pivot] = cp.getColorPivot(amino);
|
|
268
|
+
g.fillStyle = ChemPalette.undefinedColor;
|
|
269
|
+
if (index + 1 < subParts.length) {
|
|
270
|
+
const gap = simplified?'':' ';
|
|
271
|
+
amino += `${amino?'':'-'}${gap}`;
|
|
272
|
+
}
|
|
273
|
+
x = printLeftOrCentered(x, y, w, h, g, amino, color, pivot, true);
|
|
274
|
+
});
|
|
160
275
|
|
|
161
|
-
|
|
276
|
+
g.restore();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
162
279
|
|
|
280
|
+
/**
|
|
281
|
+
* Function for sequence processing.
|
|
282
|
+
*
|
|
283
|
+
* @export
|
|
284
|
+
* @param {string[]} subParts Sequence subparts.
|
|
285
|
+
* @return {[string[], boolean]}
|
|
286
|
+
*/
|
|
287
|
+
export function processSequence(subParts: string[]): [string[], boolean] {
|
|
163
288
|
const simplified = !subParts.some((amino, index) =>
|
|
164
289
|
amino.length > 1 &&
|
|
165
290
|
index != 0 &&
|
|
166
291
|
index != subParts.length - 1);
|
|
167
292
|
|
|
168
|
-
const text:string[] = [];
|
|
293
|
+
const text: string[] = [];
|
|
294
|
+
const gap = simplified ? '' : ' ';
|
|
169
295
|
subParts.forEach((amino: string, index) => {
|
|
170
296
|
if (index < subParts.length) {
|
|
171
|
-
|
|
172
|
-
amino += `${amino?'':'-'}${gap}`;
|
|
297
|
+
amino += `${amino ? '' : '-'}${gap}`;
|
|
173
298
|
}
|
|
174
299
|
text.push(amino);
|
|
175
300
|
});
|
|
176
301
|
return [text, simplified];
|
|
177
|
-
}
|
|
302
|
+
}
|