@datagrok/peptides 0.4.1 → 0.6.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 +3 -3
- package/src/describe.ts +16 -23
- package/src/package.ts +21 -34
- package/src/peptides.ts +53 -29
- package/src/utils/cell-renderer.ts +126 -19
- package/src/utils/chem-palette.ts +317 -209
- package/src/utils/correlation-analysis.ts +150 -72
- package/src/utils/peptide-similarity-space.ts +22 -25
- package/src/utils/split-aligned.ts +8 -1
- package/src/viewers/logo-viewer.ts +48 -5
- package/src/viewers/model.ts +27 -0
- package/src/viewers/sar-viewer.ts +85 -24
- package/src/viewers/spiral-plot.ts +97 -0
- package/src/viewers/stacked-barchart-viewer.ts +82 -7
- package/src/viewers/subst-viewer.ts +244 -0
- package/src/widgets/analyze-peptides.ts +15 -5
- package/src/widgets/manual-alignment.ts +7 -0
- package/src/widgets/peptide-molecule.ts +7 -0
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/peptides",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@keckelt/tsne": "^1.0.2",
|
|
7
7
|
"cash-dom": "latest",
|
|
8
8
|
"d3": "latest",
|
|
9
|
-
"datagrok-api": "
|
|
9
|
+
"datagrok-api": ">=0.104.0",
|
|
10
10
|
"dayjs": "latest",
|
|
11
11
|
"jaro-winkler-typescript": "^1.0.1",
|
|
12
12
|
"jstat": "^1.9.5",
|
|
13
13
|
"logojs-react": "^2.1.1",
|
|
14
14
|
"rxjs": "^6.5.5",
|
|
15
15
|
"umap-js": "^1.3.3",
|
|
16
|
-
"@datagrok-libraries/utils": ">=0.0.
|
|
16
|
+
"@datagrok-libraries/utils": ">=0.0.13",
|
|
17
17
|
"@datagrok-libraries/statistics": ">=0.1.5",
|
|
18
18
|
"@types/d3": "^7.0.0",
|
|
19
19
|
"@types/jquery": "^3.5.6"
|
package/src/describe.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// eslint-disable-next-line no-unused-vars
|
|
2
|
-
import * as grok from 'datagrok-api/grok';
|
|
3
1
|
import * as ui from 'datagrok-api/ui';
|
|
4
2
|
import * as DG from 'datagrok-api/dg';
|
|
5
3
|
import {splitAlignedPeptides} from './utils/split-aligned';
|
|
@@ -10,7 +8,7 @@ import {setAARRenderer} from './utils/cell-renderer';
|
|
|
10
8
|
|
|
11
9
|
const cp = new ChemPalette('grok');
|
|
12
10
|
|
|
13
|
-
const aarGroups = {
|
|
11
|
+
export const aarGroups = {
|
|
14
12
|
'R': 'PC',
|
|
15
13
|
'H': 'PC',
|
|
16
14
|
'K': 'PC',
|
|
@@ -47,6 +45,15 @@ const groupDescription: {[key: string]: {'description': string, 'aminoAcids': st
|
|
|
47
45
|
'-': {'description': 'Unknown Amino Acid', 'aminoAcids': ['-']},
|
|
48
46
|
};
|
|
49
47
|
|
|
48
|
+
/*function customGridColumnHeader(cell: DG.GridCell) {
|
|
49
|
+
if (cell.isColHeader && cell.tableColumn != null) {
|
|
50
|
+
if (highlightedColumns.includes(parseInt(cell.tableColumn.name))) {
|
|
51
|
+
cell.style.backColor = 0xff1f77b4;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}*/
|
|
55
|
+
|
|
56
|
+
//TODO: decomposition!
|
|
50
57
|
export async function describe(
|
|
51
58
|
df: DG.DataFrame,
|
|
52
59
|
activityColumn: string,
|
|
@@ -62,6 +69,7 @@ export async function describe(
|
|
|
62
69
|
const col: DG.Column = df.columns.bySemType('alignedSequence');
|
|
63
70
|
[splitSeqDf, invalidIndexes] = splitAlignedPeptides(col);
|
|
64
71
|
splitSeqDf.name = 'Split sequence';
|
|
72
|
+
|
|
65
73
|
const positionColumns = splitSeqDf.columns.names();
|
|
66
74
|
const activityColumnScaled = `${activityColumn}Scaled`;
|
|
67
75
|
const renderColNames: string[] = splitSeqDf.columns.names();
|
|
@@ -240,11 +248,9 @@ export async function describe(
|
|
|
240
248
|
aarList.sort((first, second) => getWeight(second) - getWeight(first));
|
|
241
249
|
|
|
242
250
|
matrixDf.getCol(aminoAcidResidue).setCategoryOrder(aarList);
|
|
243
|
-
//const sequenceDf = segregateBestAtAllCateg(statsDf, twoColorMode);
|
|
244
251
|
|
|
245
252
|
// SAR vertical table (naive, choose best Mean difference from pVals <= 0.01)
|
|
246
253
|
// TODO: aquire ALL of the positions
|
|
247
|
-
|
|
248
254
|
let sequenceDf = statsDf.groupBy(['Mean difference', aminoAcidResidue, positionColName, 'Count', 'Ratio', 'pValue'])
|
|
249
255
|
.where('pValue <= 0.1')
|
|
250
256
|
.aggregate();
|
|
@@ -298,19 +304,6 @@ export async function describe(
|
|
|
298
304
|
return;
|
|
299
305
|
}
|
|
300
306
|
|
|
301
|
-
// if (args.cell.isColHeader) {
|
|
302
|
-
// if (args.cell.gridColumn.name != aminoAcidResidue) {
|
|
303
|
-
// const textSize = args.g.measureText(args.cell.gridColumn.name);
|
|
304
|
-
// args.g.fillStyle = '#4b4b4a';
|
|
305
|
-
// args.g.fillText(
|
|
306
|
-
// args.cell.gridColumn.name,
|
|
307
|
-
// args.bounds.x + (args.bounds.width - textSize.width) / 2,
|
|
308
|
-
// args.bounds.y + (textSize.actualBoundingBoxAscent + textSize.actualBoundingBoxDescent),
|
|
309
|
-
// );
|
|
310
|
-
// }
|
|
311
|
-
// args.preventDefault();
|
|
312
|
-
// }
|
|
313
|
-
|
|
314
307
|
if (
|
|
315
308
|
args.cell.isTableCell &&
|
|
316
309
|
args.cell.tableRowIndex !== null &&
|
|
@@ -404,10 +397,10 @@ export async function describe(
|
|
|
404
397
|
}
|
|
405
398
|
if (
|
|
406
399
|
!cell.isColHeader &&
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
400
|
+
cell.tableColumn !== null &&
|
|
401
|
+
cell.tableColumn.name == aminoAcidResidue &&
|
|
402
|
+
cell.cell.value !== null &&
|
|
403
|
+
cell.tableRowIndex !== null
|
|
411
404
|
) {
|
|
412
405
|
if (grouping) {
|
|
413
406
|
const currentGroup = groupDescription[cell.cell.value];
|
|
@@ -422,7 +415,7 @@ export async function describe(
|
|
|
422
415
|
SARgrid.onCellTooltip(onCellTooltipFunc);
|
|
423
416
|
SARVgrid.onCellTooltip(onCellTooltipFunc);
|
|
424
417
|
|
|
425
|
-
sourceGrid.onCellPrepare((cell) => {
|
|
418
|
+
sourceGrid.onCellPrepare((cell: DG.GridCell) => {
|
|
426
419
|
const currentRowIndex = cell.tableRowIndex;
|
|
427
420
|
if (currentRowIndex && invalidIndexes.includes(currentRowIndex) && !cell.isRowHeader) {
|
|
428
421
|
cell.style.backColor = DG.Color.lightLightGray;
|
package/src/package.ts
CHANGED
|
@@ -15,7 +15,8 @@ import {PeptideSimilaritySpaceWidget} from './utils/peptide-similarity-space';
|
|
|
15
15
|
import {manualAlignmentWidget} from './widgets/manual-alignment';
|
|
16
16
|
import {SARViewer, SARViewerVertical} from './viewers/sar-viewer';
|
|
17
17
|
import {peptideMoleculeWidget} from './widgets/peptide-molecule';
|
|
18
|
-
import {
|
|
18
|
+
import {SpiralPlot} from './viewers/spiral-plot';
|
|
19
|
+
import { SubstViewer } from './viewers/subst-viewer';
|
|
19
20
|
|
|
20
21
|
export const _package = new DG.Package();
|
|
21
22
|
let tableGrid: DG.Grid;
|
|
@@ -25,35 +26,13 @@ let view: DG.TableView;
|
|
|
25
26
|
|
|
26
27
|
async function main(chosenFile: string) {
|
|
27
28
|
const pi = DG.TaskBarProgressIndicator.create('Loading Peptides');
|
|
28
|
-
//let peptides =
|
|
29
|
-
// await grok.data.loadTable('https://datagrok.jnj.com/p/ejaeger.il23peptideidp5562/il-23_peptide_idp-5562');
|
|
30
29
|
const path = _package.webRoot + 'files/' + chosenFile;
|
|
31
30
|
const peptides = (await grok.data.loadTable(path));
|
|
32
31
|
peptides.name = 'Peptides';
|
|
33
32
|
peptides.setTag('dataType', 'peptides');
|
|
34
33
|
const view = grok.shell.addTableView(peptides);
|
|
35
34
|
tableGrid = view.grid;
|
|
36
|
-
// peptides.onSemanticTypeDetecting.subscribe((_: any) => {
|
|
37
|
-
// const regexp = new RegExp(/^([^-^\n]*-){2,49}(\w|\(|\))+$/);
|
|
38
|
-
// for (const col of peptides.columns) {
|
|
39
|
-
// col.semType = DG.Detector.sampleCategories(col, (s: any) => regexp.test(s.trim())) ? 'alignedSequence' : null;
|
|
40
|
-
// if (col.semType == 'alignedSequence') {
|
|
41
|
-
// expandColumn(col, tableGrid, (ent)=>{
|
|
42
|
-
// const subParts:string[] = ent.split('-');
|
|
43
|
-
// // eslint-disable-next-line no-unused-vars
|
|
44
|
-
// const [text, _] = processSequence(subParts);
|
|
45
|
-
// let textSize = 0;
|
|
46
|
-
// text.forEach((aar)=>{
|
|
47
|
-
// textSize += aar.length;
|
|
48
|
-
// });
|
|
49
|
-
// return textSize;
|
|
50
|
-
// });
|
|
51
|
-
// }
|
|
52
|
-
// }
|
|
53
|
-
// });
|
|
54
|
-
|
|
55
35
|
view.name = 'PeptidesView';
|
|
56
|
-
|
|
57
36
|
grok.shell.windows.showProperties = true;
|
|
58
37
|
|
|
59
38
|
pi.close();
|
|
@@ -67,7 +46,6 @@ export function Peptides() {
|
|
|
67
46
|
|
|
68
47
|
const appDescription = ui.info(
|
|
69
48
|
[
|
|
70
|
-
// ui.divText('\n To start the application :', {style: {'font-weight': 'bolder'}}),
|
|
71
49
|
ui.list([
|
|
72
50
|
'- automatic recognition of peptide sequences',
|
|
73
51
|
'- native integration with tons of Datagrok out-of-the box features (visualization, filtering, clustering, ' +
|
|
@@ -136,6 +114,14 @@ export function sarVertical(): SARViewerVertical {
|
|
|
136
114
|
return new SARViewerVertical();
|
|
137
115
|
}
|
|
138
116
|
|
|
117
|
+
//name: substitution-analysis-viewer
|
|
118
|
+
//description: Substitution Analysis Viewer
|
|
119
|
+
//tags: viewer
|
|
120
|
+
//output: viewer result
|
|
121
|
+
export function subst(): SubstViewer {
|
|
122
|
+
return new SubstViewer();
|
|
123
|
+
}
|
|
124
|
+
|
|
139
125
|
//name: StackedBarchart Widget
|
|
140
126
|
//tags: panel, widgets
|
|
141
127
|
//input: column col {semType: aminoAcids}
|
|
@@ -201,14 +187,15 @@ export async function peptideSpacePanel(col: DG.Column): Promise<DG.Widget> {
|
|
|
201
187
|
return await widget.draw();
|
|
202
188
|
}
|
|
203
189
|
|
|
204
|
-
//name:
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
190
|
+
//name: Spiral Plot
|
|
191
|
+
////input: dataframe table
|
|
192
|
+
////input: column activity
|
|
193
|
+
//tags: viewer, panel
|
|
194
|
+
//output: viewer result
|
|
195
|
+
export async function spiralPlot(): Promise<DG.Viewer> {//(table: DG.DataFrame, activity: DG.Column) {
|
|
196
|
+
// Read as dataframe
|
|
197
|
+
const table = await grok.data.files.openTable('Demo:TestJobs:Files:DemoFiles/bio/peptides.csv');
|
|
198
|
+
const activity = await table.columns.addNewCalculated('-log10(Activity)', '0-Log10(${Activity})');
|
|
199
|
+
view = grok.shell.addTableView(table);
|
|
200
|
+
return view.addViewer(SpiralPlot.fromTable(table, {valuesColumnName: activity.name}));
|
|
214
201
|
}
|
package/src/peptides.ts
CHANGED
|
@@ -1,23 +1,39 @@
|
|
|
1
|
-
import * as grok from 'datagrok-api/grok';
|
|
2
1
|
import * as ui from 'datagrok-api/ui';
|
|
3
2
|
import * as DG from 'datagrok-api/dg';
|
|
4
3
|
import {createPeptideSimilaritySpaceViewer} from './utils/peptide-similarity-space';
|
|
5
4
|
import {addViewerToHeader} from './viewers/stacked-barchart-viewer';
|
|
6
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Peptides controller class.
|
|
8
|
+
*
|
|
9
|
+
* @export
|
|
10
|
+
* @class Peptides
|
|
11
|
+
*/
|
|
7
12
|
export class Peptides {
|
|
13
|
+
/**
|
|
14
|
+
* Class initializer
|
|
15
|
+
*
|
|
16
|
+
* @param {DG.Grid} tableGrid Working talbe grid.
|
|
17
|
+
* @param {DG.TableView} view Working view.
|
|
18
|
+
* @param {DG.DataFrame} currentDf Working table.
|
|
19
|
+
* @param {{[key: string]: string}} options SAR viewer options
|
|
20
|
+
* @param {DG.Column} col Aligned sequences column.
|
|
21
|
+
* @param {string} activityColumnChoice Activity column name.
|
|
22
|
+
* @memberof Peptides
|
|
23
|
+
*/
|
|
8
24
|
async init(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
tableGrid: DG.Grid,
|
|
26
|
+
view: DG.TableView,
|
|
27
|
+
currentDf: DG.DataFrame,
|
|
28
|
+
options: {[key: string]: string},
|
|
29
|
+
col: DG.Column,
|
|
30
|
+
activityColumnChoice: string,
|
|
31
|
+
) {
|
|
16
32
|
for (let i = 0; i < tableGrid.columns.length; i++) {
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
33
|
+
const aarCol = tableGrid.columns.byIndex(i);
|
|
34
|
+
if (aarCol &&
|
|
35
|
+
aarCol.name &&
|
|
36
|
+
aarCol.column?.semType != 'aminoAcids'
|
|
21
37
|
) {
|
|
22
38
|
//@ts-ignore
|
|
23
39
|
tableGrid.columns.byIndex(i)?.visible = false;
|
|
@@ -26,6 +42,11 @@ export class Peptides {
|
|
|
26
42
|
|
|
27
43
|
const originalDfColumns = (currentDf.columns as DG.ColumnList).names();
|
|
28
44
|
|
|
45
|
+
const substViewer = view.addViewer(
|
|
46
|
+
'substitution-analysis-viewer', {'activityColumnName': options['activityColumnColumnName']},
|
|
47
|
+
);
|
|
48
|
+
view.dockManager.dock(substViewer, DG.DOCK_TYPE.RIGHT, null, 'Substitution Analysis');
|
|
49
|
+
|
|
29
50
|
const sarViewer = view.addViewer('peptide-sar-viewer', options);
|
|
30
51
|
const sarNode = view.dockManager.dock(sarViewer, DG.DOCK_TYPE.DOWN, null, 'SAR Viewer');
|
|
31
52
|
|
|
@@ -41,34 +62,37 @@ export class Peptides {
|
|
|
41
62
|
view,
|
|
42
63
|
`${activityColumnChoice}Scaled`,
|
|
43
64
|
);
|
|
44
|
-
|
|
65
|
+
view.dockManager.dock(peptideSpaceViewer, DG.DOCK_TYPE.LEFT, sarNode, 'Peptide Space Viewer', 0.3);
|
|
45
66
|
|
|
46
67
|
const StackedBarchartProm = currentDf.plot.fromType('StackedBarChartAA');
|
|
47
68
|
addViewerToHeader(tableGrid, StackedBarchartProm);
|
|
48
69
|
|
|
49
70
|
const hideIcon = ui.iconFA('window-close', () => { //undo?, times?
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
71
|
+
const viewers = [];
|
|
72
|
+
for (const viewer of view.viewers) {
|
|
73
|
+
if (viewer.type !== DG.VIEWER.GRID) {
|
|
74
|
+
viewers.push(viewer);
|
|
55
75
|
}
|
|
56
|
-
|
|
76
|
+
}
|
|
77
|
+
viewers.forEach((v) => v.close());
|
|
57
78
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
79
|
+
const cols = (currentDf.columns as DG.ColumnList);
|
|
80
|
+
for (const colName of cols.names()) {
|
|
81
|
+
if (!originalDfColumns.includes(colName)) {
|
|
82
|
+
cols.remove(colName);
|
|
63
83
|
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
currentDf.selection.setAll(false);
|
|
87
|
+
currentDf.filter.setAll(true);
|
|
64
88
|
|
|
65
|
-
|
|
66
|
-
|
|
89
|
+
tableGrid.setOptions({'colHeaderHeight': 20});
|
|
90
|
+
tableGrid.columns.setVisible(originalDfColumns);
|
|
67
91
|
|
|
68
|
-
|
|
92
|
+
view.setRibbonPanels(ribbonPanels);
|
|
69
93
|
}, 'Close viewers and restore dataframe');
|
|
70
|
-
|
|
94
|
+
|
|
71
95
|
const ribbonPanels = view.getRibbonPanels();
|
|
72
96
|
view.setRibbonPanels([[hideIcon]]);
|
|
73
97
|
}
|
|
74
|
-
}
|
|
98
|
+
}
|
|
@@ -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,6 +32,14 @@ export function expandColumn(col:DG.Column,
|
|
|
23
32
|
timeout);
|
|
24
33
|
}
|
|
25
34
|
|
|
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
|
+
*/
|
|
26
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');
|
|
@@ -33,17 +50,39 @@ export function setAARRenderer(col: DG.Column, grid: DG.Grid | null = null, grou
|
|
|
33
50
|
expandColumn(col, grid, (ent) => measureAAR(ent));
|
|
34
51
|
}
|
|
35
52
|
}
|
|
36
|
-
|
|
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
|
+
*/
|
|
37
60
|
export function measureAAR(s: string): number {
|
|
38
61
|
const end = s.lastIndexOf(')');
|
|
39
62
|
const beg = s.indexOf('(');
|
|
40
63
|
return end == beg ? s.length : s.length - (end - beg) + 1;
|
|
41
64
|
}
|
|
42
65
|
|
|
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(
|
|
44
82
|
x: number, y: number, w: number, h: number,
|
|
45
83
|
g: CanvasRenderingContext2D, s: string, color = ChemPalette.undefinedColor,
|
|
46
|
-
pivot: number = 0, left = false, hideMod = false
|
|
84
|
+
pivot: number = 0, left = false, hideMod = false,
|
|
85
|
+
) {
|
|
47
86
|
g.textAlign = 'start';
|
|
48
87
|
let colorPart = pivot == -1 ? s.substring(0) : s.substring(0, pivot);
|
|
49
88
|
if (colorPart.length == 1) {
|
|
@@ -100,23 +139,55 @@ function printLeftCentered(
|
|
|
100
139
|
}
|
|
101
140
|
}
|
|
102
141
|
|
|
103
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Amino acid residue cell renderer.
|
|
144
|
+
*
|
|
145
|
+
* @export
|
|
146
|
+
* @class AminoAcidsCellRenderer
|
|
147
|
+
* @extends {DG.GridCellRenderer}
|
|
148
|
+
*/
|
|
104
149
|
export class AminoAcidsCellRenderer extends DG.GridCellRenderer {
|
|
105
150
|
chemPalette: ChemPalette | null;
|
|
106
151
|
|
|
152
|
+
/**
|
|
153
|
+
* Renderer name.
|
|
154
|
+
*
|
|
155
|
+
* @readonly
|
|
156
|
+
* @memberof AminoAcidsCellRenderer
|
|
157
|
+
*/
|
|
107
158
|
get name() {
|
|
108
159
|
return 'aminoAcidsCR';
|
|
109
160
|
}
|
|
110
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Cell type.
|
|
164
|
+
*
|
|
165
|
+
* @readonly
|
|
166
|
+
* @memberof AminoAcidsCellRenderer
|
|
167
|
+
*/
|
|
111
168
|
get cellType() {
|
|
112
169
|
return 'aminoAcids';
|
|
113
170
|
}
|
|
114
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Constructor.
|
|
174
|
+
*/
|
|
115
175
|
constructor() {
|
|
116
176
|
super();
|
|
117
177
|
this.chemPalette = null;
|
|
118
178
|
}
|
|
119
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
|
+
*/
|
|
120
191
|
render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
|
|
121
192
|
gridCell: DG.GridCell, cellStyle: DG.GridCellStyle) {
|
|
122
193
|
if (this.chemPalette === null) {
|
|
@@ -130,21 +201,51 @@ export class AminoAcidsCellRenderer extends DG.GridCellRenderer {
|
|
|
130
201
|
g.textBaseline = 'top';
|
|
131
202
|
const s: string = gridCell.cell.value ? gridCell.cell.value : '-';
|
|
132
203
|
const [color, pivot] = cp.getColorPivot(s);
|
|
133
|
-
|
|
204
|
+
printLeftOrCentered(x, y, w, h, g, s, color, pivot, false, true);
|
|
134
205
|
g.restore();
|
|
135
206
|
}
|
|
136
207
|
}
|
|
137
208
|
|
|
138
|
-
|
|
209
|
+
/**
|
|
210
|
+
* Aligned sequence cell renderer.
|
|
211
|
+
*
|
|
212
|
+
* @export
|
|
213
|
+
* @class AlignedSequenceCellRenderer
|
|
214
|
+
* @extends {DG.GridCellRenderer}
|
|
215
|
+
*/
|
|
139
216
|
export class AlignedSequenceCellRenderer extends DG.GridCellRenderer {
|
|
217
|
+
/**
|
|
218
|
+
* Renderer name.
|
|
219
|
+
*
|
|
220
|
+
* @readonly
|
|
221
|
+
* @memberof AlignedSequenceCellRenderer
|
|
222
|
+
*/
|
|
140
223
|
get name() {
|
|
141
224
|
return 'alignedSequenceCR';
|
|
142
225
|
}
|
|
143
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Cell type.
|
|
229
|
+
*
|
|
230
|
+
* @readonly
|
|
231
|
+
* @memberof AlignedSequenceCellRenderer
|
|
232
|
+
*/
|
|
144
233
|
get cellType() {
|
|
145
234
|
return 'alignedSequence';
|
|
146
235
|
}
|
|
147
236
|
|
|
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
|
+
*/
|
|
148
249
|
render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
|
|
149
250
|
gridCell: DG.GridCell, cellStyle: DG.GridCellStyle ) {
|
|
150
251
|
w = Math.min(gridCell.grid.canvas.width - x, w);
|
|
@@ -169,25 +270,31 @@ export class AlignedSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
169
270
|
const gap = simplified?'':' ';
|
|
170
271
|
amino += `${amino?'':'-'}${gap}`;
|
|
171
272
|
}
|
|
172
|
-
x =
|
|
273
|
+
x = printLeftOrCentered(x, y, w, h, g, amino, color, pivot, true);
|
|
173
274
|
});
|
|
174
275
|
|
|
175
276
|
g.restore();
|
|
176
277
|
}
|
|
177
278
|
}
|
|
178
279
|
|
|
179
|
-
|
|
180
|
-
|
|
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] {
|
|
181
288
|
const simplified = !subParts.some((amino, index) =>
|
|
182
289
|
amino.length > 1 &&
|
|
183
290
|
index != 0 &&
|
|
184
291
|
index != subParts.length - 1);
|
|
185
292
|
|
|
186
|
-
const text:string[] = [];
|
|
293
|
+
const text: string[] = [];
|
|
294
|
+
const gap = simplified ? '' : ' ';
|
|
187
295
|
subParts.forEach((amino: string, index) => {
|
|
188
296
|
if (index < subParts.length) {
|
|
189
|
-
|
|
190
|
-
amino += `${amino?'':'-'}${gap}`;
|
|
297
|
+
amino += `${amino ? '' : '-'}${gap}`;
|
|
191
298
|
}
|
|
192
299
|
text.push(amino);
|
|
193
300
|
});
|