oncoprintjs 5.0.3 → 6.0.1
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/README.md +34 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.es.js +14746 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.js +14760 -0
- package/dist/index.js.map +1 -0
- package/dist/js/CachedProperty.d.ts +10 -10
- package/dist/js/binarysearch.d.ts +1 -1
- package/dist/js/bucketsort.d.ts +16 -16
- package/dist/js/clustering.d.ts +14 -14
- package/dist/js/extractrgba.d.ts +4 -4
- package/dist/js/haselementsininterval.d.ts +1 -1
- package/dist/js/heatmapcolors.d.ts +5 -4
- package/dist/js/makesvgelement.d.ts +1 -1
- package/dist/js/modelutils.d.ts +7 -7
- package/dist/js/oncoprint.d.ts +168 -170
- package/dist/js/oncoprintheaderview.d.ts +23 -22
- package/dist/js/oncoprintlabelview.d.ts +79 -78
- package/dist/js/oncoprintlegendrenderer.d.ts +32 -31
- package/dist/js/oncoprintminimapview.d.ts +69 -68
- package/dist/js/oncoprintmodel.d.ts +403 -398
- package/dist/js/oncoprintruleset.d.ts +176 -177
- package/dist/js/oncoprintshape.d.ts +67 -67
- package/dist/js/oncoprintshapetosvg.d.ts +2 -2
- package/dist/js/oncoprintshapetovertexes.d.ts +5 -5
- package/dist/js/oncoprinttooltip.d.ts +23 -22
- package/dist/js/oncoprinttrackinfoview.d.ts +40 -39
- package/dist/js/oncoprinttrackoptionsview.d.ts +58 -57
- package/dist/js/oncoprintwebglcellview.d.ts +168 -167
- package/dist/js/oncoprintzoomslider.d.ts +28 -27
- package/dist/js/polyfill.d.ts +4 -4
- package/dist/js/precomputedcomparator.d.ts +13 -13
- package/dist/js/shaders.d.ts +2 -2
- package/dist/js/svgfactory.d.ts +24 -23
- package/dist/js/utils.d.ts +16 -16
- package/dist/js/workers/clustering-worker.d.ts +19 -20
- package/dist/test/gradientCategoricalRuleset.spec.d.ts +1 -1
- package/dist/test/monolith.spec.d.ts +1 -1
- package/jest.config.ts +2 -0
- package/package.json +20 -26
- package/rollup.config.ts +14 -0
- package/rules/geneticrules.ts +344 -305
- package/server.js +11 -0
- package/src/img/menudots.svg +9 -9
- package/src/img/zoomtofit.svg +12 -12
- package/src/index.tsx +13 -0
- package/src/js/CachedProperty.ts +6 -7
- package/src/js/binarysearch.ts +8 -3
- package/src/js/bucketsort.ts +89 -47
- package/src/js/clustering.ts +22 -10
- package/src/js/extractrgba.ts +16 -12
- package/src/js/haselementsininterval.ts +8 -4
- package/src/js/heatmapcolors.ts +515 -515
- package/src/js/main.js +1 -1
- package/src/js/makesvgelement.ts +2 -2
- package/src/js/modelutils.ts +11 -8
- package/src/js/oncoprint.ts +706 -385
- package/src/js/oncoprintheaderview.ts +165 -125
- package/src/js/oncoprintlabelview.ts +388 -170
- package/src/js/oncoprintlegendrenderer.ts +203 -72
- package/src/js/oncoprintminimapview.ts +965 -423
- package/src/js/oncoprintmodel.ts +905 -532
- package/src/js/oncoprintruleset.ts +694 -379
- package/src/js/oncoprintshape.ts +240 -97
- package/src/js/oncoprintshapetosvg.ts +77 -26
- package/src/js/oncoprintshapetovertexes.ts +153 -48
- package/src/js/oncoprinttooltip.ts +58 -27
- package/src/js/oncoprinttrackinfoview.ts +115 -59
- package/src/js/oncoprinttrackoptionsview.ts +354 -187
- package/src/js/oncoprintwebglcellview.ts +951 -415
- package/src/js/oncoprintzoomslider.ts +172 -107
- package/src/js/polyfill.ts +7 -3
- package/src/js/precomputedcomparator.ts +133 -50
- package/src/js/shaders.ts +2 -4
- package/src/js/svgfactory.ts +128 -73
- package/src/js/utils.ts +51 -31
- package/src/js/workers/clustering-worker.ts +50 -42
- package/src/test/gradientCategoricalRuleset.spec.ts +55 -38
- package/src/test/monolith.spec.ts +718 -285
- package/test/generate_data.py +108 -0
- package/test/glyphmap-data.js +1041 -0
- package/test/heatmap-data.js +1027 -0
- package/test/index.html +21 -0
- package/test/oncoprint-glyphmap.js +79 -0
- package/test/oncoprint-heatmap.js +123 -0
- package/tsconfig.json +4 -10
- package/tsconfig.test.json +11 -0
- package/.idea/misc.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/oncoprintjs.iml +0 -12
- package/.idea/vcs.xml +0 -6
- package/.idea/workspace.xml +0 -105
- package/dist/.gitkeep +0 -0
- package/dist/js/minimaputils.d.ts +0 -0
- package/dist/oncoprint.bundle.js +0 -44313
- package/jest.config.js +0 -12
- package/src/js/minimaputils.ts +0 -0
- package/typings/custom.d.ts +0 -7
- package/typings/missing.d.ts +0 -7
- package/webpack.config.js +0 -43
|
@@ -1,76 +1,77 @@
|
|
|
1
1
|
import gl_matrix from 'gl-matrix';
|
|
2
2
|
import svgfactory from './svgfactory';
|
|
3
3
|
import makeSvgElement from './makesvgelement';
|
|
4
|
-
import shapeToVertexes, {
|
|
4
|
+
import shapeToVertexes, {
|
|
5
|
+
getNumWebGLVertexes,
|
|
6
|
+
} from './oncoprintshapetovertexes';
|
|
5
7
|
import CachedProperty from './CachedProperty';
|
|
6
|
-
import {ComputedShapeParams, Shape} from './oncoprintshape';
|
|
8
|
+
import { ComputedShapeParams, Shape } from './oncoprintshape';
|
|
7
9
|
import $ from 'jquery';
|
|
8
10
|
import OncoprintModel, {
|
|
9
|
-
ColumnId,
|
|
11
|
+
ColumnId,
|
|
12
|
+
ColumnLabel,
|
|
10
13
|
ColumnProp,
|
|
11
14
|
IdentifiedShapeList,
|
|
12
15
|
TrackId,
|
|
13
16
|
TrackOverlappingCells,
|
|
14
|
-
TrackProp
|
|
15
|
-
} from
|
|
16
|
-
import OncoprintToolTip from
|
|
17
|
-
import {arrayFindIndex, ifndef, sgndiff} from
|
|
17
|
+
TrackProp,
|
|
18
|
+
} from './oncoprintmodel';
|
|
19
|
+
import OncoprintToolTip from './oncoprinttooltip';
|
|
20
|
+
import { arrayFindIndex, ifndef, sgndiff } from './utils';
|
|
18
21
|
import MouseUpEvent = JQuery.MouseUpEvent;
|
|
19
22
|
import MouseMoveEvent = JQuery.MouseMoveEvent;
|
|
20
|
-
import {CellClickCallback, CellMouseOverCallback} from
|
|
21
|
-
import {
|
|
22
|
-
getFragmentShaderSource, getVertexShaderSource
|
|
23
|
-
} from "./shaders";
|
|
23
|
+
import { CellClickCallback, CellMouseOverCallback } from './oncoprint';
|
|
24
|
+
import { getFragmentShaderSource, getVertexShaderSource } from './shaders';
|
|
24
25
|
import _ from 'lodash';
|
|
25
26
|
|
|
26
27
|
type ColorBankIndex = number; // index into vertex bank (e.g. 0, 4, 8, ...)
|
|
27
28
|
type ColorBank = number[]; // flat list of color: [c0,c0,c0,c0,v1,v1,v1,c1,c1,c1,c1,...]
|
|
28
29
|
type ColumnIdIndex = number;
|
|
29
|
-
type PositionVertex = [number,number,number];
|
|
30
|
-
type ColorVertex = [number,number,number,number];
|
|
30
|
+
type PositionVertex = [number, number, number];
|
|
31
|
+
type ColorVertex = [number, number, number, number];
|
|
31
32
|
|
|
32
33
|
export type OncoprintWebGLContext = WebGLRenderingContext & {
|
|
33
|
-
viewportWidth:number
|
|
34
|
-
viewportHeight:number
|
|
34
|
+
viewportWidth: number;
|
|
35
|
+
viewportHeight: number;
|
|
35
36
|
}; // TODO: handle this differently, considered an anti-pattern https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
|
|
36
37
|
|
|
37
38
|
export type OncoprintShaderProgram = WebGLProgram & {
|
|
38
|
-
vertexPositionAttribute:any;
|
|
39
|
-
vertexColorAttribute:any;
|
|
40
|
-
vertexOncoprintColumnAttribute:any;
|
|
41
|
-
|
|
42
|
-
gapSizeUniform:WebGLUniformLocation;
|
|
43
|
-
columnsRightAfterGapsUniform:WebGLUniformLocation;
|
|
44
|
-
|
|
45
|
-
samplerUniform:WebGLUniformLocation;
|
|
46
|
-
pMatrixUniform:WebGLUniformLocation;
|
|
47
|
-
mvMatrixUniform:WebGLUniformLocation;
|
|
48
|
-
columnWidthUniform:WebGLUniformLocation;
|
|
49
|
-
scrollXUniform:WebGLUniformLocation;
|
|
50
|
-
scrollYUniform:WebGLUniformLocation;
|
|
51
|
-
zoomXUniform:WebGLUniformLocation;
|
|
52
|
-
zoomYUniform:WebGLUniformLocation;
|
|
53
|
-
offsetYUniform:WebGLUniformLocation;
|
|
54
|
-
supersamplingRatioUniform:WebGLUniformLocation;
|
|
55
|
-
positionBitPackBaseUniform:WebGLUniformLocation;
|
|
56
|
-
texSizeUniform:WebGLUniformLocation;
|
|
39
|
+
vertexPositionAttribute: any;
|
|
40
|
+
vertexColorAttribute: any;
|
|
41
|
+
vertexOncoprintColumnAttribute: any;
|
|
42
|
+
|
|
43
|
+
gapSizeUniform: WebGLUniformLocation;
|
|
44
|
+
columnsRightAfterGapsUniform: WebGLUniformLocation;
|
|
45
|
+
|
|
46
|
+
samplerUniform: WebGLUniformLocation;
|
|
47
|
+
pMatrixUniform: WebGLUniformLocation;
|
|
48
|
+
mvMatrixUniform: WebGLUniformLocation;
|
|
49
|
+
columnWidthUniform: WebGLUniformLocation;
|
|
50
|
+
scrollXUniform: WebGLUniformLocation;
|
|
51
|
+
scrollYUniform: WebGLUniformLocation;
|
|
52
|
+
zoomXUniform: WebGLUniformLocation;
|
|
53
|
+
zoomYUniform: WebGLUniformLocation;
|
|
54
|
+
offsetYUniform: WebGLUniformLocation;
|
|
55
|
+
supersamplingRatioUniform: WebGLUniformLocation;
|
|
56
|
+
positionBitPackBaseUniform: WebGLUniformLocation;
|
|
57
|
+
texSizeUniform: WebGLUniformLocation;
|
|
57
58
|
}; // TODO: handle this differently, considered an anti-pattern https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
|
|
58
59
|
|
|
59
60
|
export type OncoprintTrackBuffer = WebGLBuffer & {
|
|
60
|
-
itemSize:number;
|
|
61
|
-
numItems:number;
|
|
61
|
+
itemSize: number;
|
|
62
|
+
numItems: number;
|
|
62
63
|
}; // TODO: handle this differently, considered an anti-pattern https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
|
|
63
64
|
|
|
64
65
|
export type OncoprintVertexTrackBuffer = OncoprintTrackBuffer & {
|
|
65
66
|
// the universal shapes vertexes start at index itemSize*numItems, and go on for itemSize*universalShapesNumItems indexes
|
|
66
|
-
specificShapesNumItems:number;
|
|
67
|
-
universalShapesNumItems:number;
|
|
68
|
-
}
|
|
67
|
+
specificShapesNumItems: number;
|
|
68
|
+
universalShapesNumItems: number;
|
|
69
|
+
};
|
|
69
70
|
|
|
70
71
|
const COLUMN_LABEL_ANGLE = 65;
|
|
71
72
|
const COLUMN_LABEL_MARGIN = 30;
|
|
72
73
|
|
|
73
|
-
const CELL_HIGHLIGHT_STROKE =
|
|
74
|
+
const CELL_HIGHLIGHT_STROKE = 'rgba(0,0,0,0.5)';
|
|
74
75
|
|
|
75
76
|
export default class OncoprintWebGLCellView {
|
|
76
77
|
public readonly position_bit_pack_base = 128;
|
|
@@ -78,60 +79,66 @@ export default class OncoprintWebGLCellView {
|
|
|
78
79
|
private readonly antialias_on_cell_width_thresh = 5;
|
|
79
80
|
private antialias = true;
|
|
80
81
|
|
|
81
|
-
private dummy_scroll_div_client_size:CachedProperty<{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
private
|
|
87
|
-
|
|
88
|
-
private
|
|
89
|
-
private
|
|
90
|
-
private
|
|
91
|
-
private
|
|
92
|
-
|
|
93
|
-
private
|
|
94
|
-
private
|
|
82
|
+
private dummy_scroll_div_client_size: CachedProperty<{
|
|
83
|
+
width: number;
|
|
84
|
+
height: number;
|
|
85
|
+
}>;
|
|
86
|
+
public visible_area_width: number;
|
|
87
|
+
private mouseMoveHandler: (evt: MouseMoveEvent) => void;
|
|
88
|
+
|
|
89
|
+
private ctx: OncoprintWebGLContext | null;
|
|
90
|
+
private ext: ANGLE_instanced_arrays | null;
|
|
91
|
+
private overlay_ctx: CanvasRenderingContext2D | null;
|
|
92
|
+
private column_label_ctx: CanvasRenderingContext2D | null;
|
|
93
|
+
private mvMatrix: any;
|
|
94
|
+
private pMatrix: any;
|
|
95
|
+
private shader_program: OncoprintShaderProgram;
|
|
96
|
+
|
|
97
|
+
private scroll_x: number = 0;
|
|
98
|
+
private scroll_y: number = 0;
|
|
95
99
|
private maximum_column_label_width = 0;
|
|
96
100
|
private maximum_column_label_height = 0;
|
|
97
101
|
private rendering_suppressed = false;
|
|
98
102
|
|
|
99
|
-
private specific_shapes:TrackProp<IdentifiedShapeList[]> = {};
|
|
100
|
-
private universal_shapes:TrackProp<ComputedShapeParams[]> = {};
|
|
101
|
-
public vertex_data:TrackProp<{
|
|
102
|
-
pos_array:Float32Array;
|
|
103
|
-
col_array:Float32Array
|
|
104
|
-
col_bank:ColorBank
|
|
105
|
-
universal_shapes_start_index:number
|
|
103
|
+
private specific_shapes: TrackProp<IdentifiedShapeList[]> = {};
|
|
104
|
+
private universal_shapes: TrackProp<ComputedShapeParams[]> = {};
|
|
105
|
+
public vertex_data: TrackProp<{
|
|
106
|
+
pos_array: Float32Array;
|
|
107
|
+
col_array: Float32Array; //ColorBankIndex[],
|
|
108
|
+
col_bank: ColorBank;
|
|
109
|
+
universal_shapes_start_index: number;
|
|
110
|
+
}> = {};
|
|
111
|
+
public vertex_column_array: TrackProp<Float32Array> = {}; // ColumnIdIndex[]
|
|
112
|
+
private vertex_position_buffer: TrackProp<OncoprintVertexTrackBuffer> = {};
|
|
113
|
+
private vertex_color_buffer: TrackProp<OncoprintVertexTrackBuffer> = {};
|
|
114
|
+
private vertex_column_buffer: TrackProp<OncoprintTrackBuffer> = {};
|
|
115
|
+
private simple_count_buffer: OncoprintTrackBuffer | null = null;
|
|
116
|
+
private is_buffer_empty: TrackProp<{
|
|
117
|
+
position: boolean;
|
|
118
|
+
color: boolean;
|
|
119
|
+
column: boolean;
|
|
120
|
+
color_texture: boolean;
|
|
106
121
|
}> = {};
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
private vertex_column_buffer:TrackProp<OncoprintTrackBuffer> = {};
|
|
111
|
-
private simple_count_buffer:OncoprintTrackBuffer | null = null;
|
|
112
|
-
private is_buffer_empty:TrackProp<{
|
|
113
|
-
position:boolean;
|
|
114
|
-
color:boolean;
|
|
115
|
-
column:boolean;
|
|
116
|
-
color_texture:boolean;
|
|
122
|
+
private color_texture: TrackProp<{
|
|
123
|
+
texture: WebGLTexture;
|
|
124
|
+
size: number;
|
|
117
125
|
}> = {};
|
|
118
|
-
private
|
|
119
|
-
private id_to_first_vertex_index:TrackProp<ColumnProp<number>> = {}; // index of first vertex corresponding to given id for given track, e.g. 0, 3, 6, ...
|
|
126
|
+
private id_to_first_vertex_index: TrackProp<ColumnProp<number>> = {}; // index of first vertex corresponding to given id for given track, e.g. 0, 3, 6, ...
|
|
120
127
|
|
|
121
128
|
constructor(
|
|
122
|
-
private $container:JQuery,
|
|
123
|
-
private $canvas:JQuery<HTMLCanvasElement>,
|
|
124
|
-
private $overlay_canvas:JQuery<HTMLCanvasElement>,
|
|
125
|
-
private $column_label_canvas:JQuery<HTMLCanvasElement>,
|
|
126
|
-
private $dummy_scroll_div_contents:JQuery,
|
|
127
|
-
model:OncoprintModel,
|
|
128
|
-
private tooltip:OncoprintToolTip,
|
|
129
|
-
private highlight_area_callback:
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
private $container: JQuery,
|
|
130
|
+
private $canvas: JQuery<HTMLCanvasElement>,
|
|
131
|
+
private $overlay_canvas: JQuery<HTMLCanvasElement>,
|
|
132
|
+
private $column_label_canvas: JQuery<HTMLCanvasElement>,
|
|
133
|
+
private $dummy_scroll_div_contents: JQuery,
|
|
134
|
+
model: OncoprintModel,
|
|
135
|
+
private tooltip: OncoprintToolTip,
|
|
136
|
+
private highlight_area_callback:
|
|
137
|
+
| undefined
|
|
138
|
+
| ((left: number, right: number) => void),
|
|
139
|
+
cell_over_callback: CellMouseOverCallback,
|
|
140
|
+
cell_click_callback: CellClickCallback
|
|
132
141
|
) {
|
|
133
|
-
|
|
134
|
-
|
|
135
142
|
this.getWebGLContextAndSetUpMatrices();
|
|
136
143
|
this.setUpShaders(model);
|
|
137
144
|
this.getOverlayContextAndClear();
|
|
@@ -143,25 +150,36 @@ export default class OncoprintWebGLCellView {
|
|
|
143
150
|
|
|
144
151
|
this.scroll_x = 0;
|
|
145
152
|
this.scroll_y = 0;
|
|
146
|
-
this.dummy_scroll_div_client_size = new CachedProperty(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
153
|
+
this.dummy_scroll_div_client_size = new CachedProperty(
|
|
154
|
+
{
|
|
155
|
+
width: $dummy_scroll_div_contents.parent()[0].clientWidth,
|
|
156
|
+
height: $dummy_scroll_div_contents.parent()[0].clientHeight,
|
|
157
|
+
},
|
|
158
|
+
function() {
|
|
159
|
+
return {
|
|
160
|
+
width: $dummy_scroll_div_contents.parent()[0].clientWidth,
|
|
161
|
+
height: $dummy_scroll_div_contents.parent()[0].clientHeight,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
);
|
|
150
165
|
|
|
151
|
-
this.highlight_area_callback =
|
|
166
|
+
this.highlight_area_callback =
|
|
167
|
+
typeof highlight_area_callback === 'undefined'
|
|
168
|
+
? function() {}
|
|
169
|
+
: highlight_area_callback; // function(left, right) { ... }
|
|
152
170
|
|
|
153
171
|
(function initializeOverlayEvents(self) {
|
|
154
172
|
let dragging = false;
|
|
155
173
|
let drag_diff_minimum = 10;
|
|
156
|
-
let drag_start_x:number;
|
|
157
|
-
let drag_end_x:number;
|
|
158
|
-
let last_cell_over:TrackOverlappingCells|null = null;
|
|
174
|
+
let drag_start_x: number;
|
|
175
|
+
let drag_end_x: number;
|
|
176
|
+
let last_cell_over: TrackOverlappingCells | null = null;
|
|
159
177
|
|
|
160
|
-
function dragIsValid(drag_start_x:number, drag_end_x:number) {
|
|
178
|
+
function dragIsValid(drag_start_x: number, drag_end_x: number) {
|
|
161
179
|
return Math.abs(drag_start_x - drag_end_x) >= drag_diff_minimum;
|
|
162
180
|
}
|
|
163
181
|
|
|
164
|
-
function executeDragOrClick(mouse_up_evt?:MouseUpEvent) {
|
|
182
|
+
function executeDragOrClick(mouse_up_evt?: MouseUpEvent) {
|
|
165
183
|
if (!dragging) {
|
|
166
184
|
return;
|
|
167
185
|
}
|
|
@@ -173,25 +191,39 @@ export default class OncoprintWebGLCellView {
|
|
|
173
191
|
const offset = self.$overlay_canvas.offset();
|
|
174
192
|
const mouseX = mouse_up_evt.pageX - offset.left;
|
|
175
193
|
const mouseY = mouse_up_evt.pageY - offset.top;
|
|
176
|
-
const overlapping_cells = model.getOverlappingCells(
|
|
194
|
+
const overlapping_cells = model.getOverlappingCells(
|
|
195
|
+
mouseX + self.scroll_x,
|
|
196
|
+
mouseY + self.scroll_y
|
|
197
|
+
);
|
|
177
198
|
if (overlapping_cells === null) {
|
|
178
199
|
cell_click_callback(null);
|
|
179
200
|
} else {
|
|
180
|
-
cell_click_callback(
|
|
201
|
+
cell_click_callback(
|
|
202
|
+
overlapping_cells.ids[0],
|
|
203
|
+
overlapping_cells.track
|
|
204
|
+
);
|
|
181
205
|
}
|
|
182
206
|
}
|
|
183
207
|
return;
|
|
184
208
|
}
|
|
185
209
|
const left = Math.min(drag_start_x, drag_end_x);
|
|
186
210
|
const right = Math.max(drag_start_x, drag_end_x);
|
|
187
|
-
self.highlight_area_callback(
|
|
211
|
+
self.highlight_area_callback(
|
|
212
|
+
left + self.scroll_x,
|
|
213
|
+
right + self.scroll_x
|
|
214
|
+
);
|
|
188
215
|
}
|
|
189
216
|
|
|
190
|
-
function mouseInOverlayCanvas(mouse_x:number, mouse_y:number) {
|
|
217
|
+
function mouseInOverlayCanvas(mouse_x: number, mouse_y: number) {
|
|
191
218
|
const offset = self.$overlay_canvas.offset();
|
|
192
219
|
const width = self.$overlay_canvas.width();
|
|
193
220
|
const height = self.$overlay_canvas.height();
|
|
194
|
-
return (
|
|
221
|
+
return (
|
|
222
|
+
mouse_x >= offset.left &&
|
|
223
|
+
mouse_x < width + offset.left &&
|
|
224
|
+
mouse_y >= offset.top &&
|
|
225
|
+
mouse_y < height + offset.top
|
|
226
|
+
);
|
|
195
227
|
}
|
|
196
228
|
|
|
197
229
|
self.mouseMoveHandler = function(evt) {
|
|
@@ -206,9 +238,9 @@ export default class OncoprintWebGLCellView {
|
|
|
206
238
|
}
|
|
207
239
|
}
|
|
208
240
|
};
|
|
209
|
-
|
|
210
|
-
$(document).on(
|
|
211
|
-
self.$overlay_canvas.on(
|
|
241
|
+
|
|
242
|
+
$(document).on('mousemove', self.mouseMoveHandler);
|
|
243
|
+
self.$overlay_canvas.on('mousemove', function(evt) {
|
|
212
244
|
if (self.rendering_suppressed) {
|
|
213
245
|
return;
|
|
214
246
|
}
|
|
@@ -217,20 +249,50 @@ export default class OncoprintWebGLCellView {
|
|
|
217
249
|
const offset = self.$overlay_canvas.offset();
|
|
218
250
|
const mouseX = evt.pageX - offset.left;
|
|
219
251
|
const mouseY = evt.pageY - offset.top;
|
|
220
|
-
let overlapping_cells = model.getOverlappingCells(
|
|
252
|
+
let overlapping_cells = model.getOverlappingCells(
|
|
253
|
+
mouseX + self.scroll_x,
|
|
254
|
+
mouseY + self.scroll_y
|
|
255
|
+
);
|
|
221
256
|
if (!dragging) {
|
|
222
|
-
const overlapping_data =
|
|
223
|
-
|
|
224
|
-
|
|
257
|
+
const overlapping_data =
|
|
258
|
+
overlapping_cells === null
|
|
259
|
+
? null
|
|
260
|
+
: overlapping_cells.ids.map(function(id) {
|
|
261
|
+
return model.getTrackDatum(
|
|
262
|
+
overlapping_cells.track,
|
|
263
|
+
id
|
|
264
|
+
);
|
|
265
|
+
});
|
|
225
266
|
if (overlapping_data !== null) {
|
|
226
267
|
last_cell_over = overlapping_cells;
|
|
227
|
-
cell_over_callback(
|
|
228
|
-
|
|
229
|
-
|
|
268
|
+
cell_over_callback(
|
|
269
|
+
overlapping_cells.ids[0],
|
|
270
|
+
overlapping_cells.track
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
self.highlightCell(
|
|
274
|
+
model,
|
|
275
|
+
overlapping_cells.track,
|
|
276
|
+
overlapping_cells.ids[0]
|
|
277
|
+
);
|
|
230
278
|
self.highlightColumn(model, overlapping_cells.ids[0]);
|
|
231
279
|
|
|
232
280
|
const clientRect = self.$overlay_canvas[0].getBoundingClientRect();
|
|
233
|
-
tooltip.show(
|
|
281
|
+
tooltip.show(
|
|
282
|
+
250,
|
|
283
|
+
model.getZoomedColumnLeft(
|
|
284
|
+
overlapping_cells.ids[0]
|
|
285
|
+
) +
|
|
286
|
+
model.getCellWidth() / 2 +
|
|
287
|
+
clientRect.left -
|
|
288
|
+
self.scroll_x,
|
|
289
|
+
model.getCellTops(overlapping_cells.track) +
|
|
290
|
+
clientRect.top -
|
|
291
|
+
self.scroll_y,
|
|
292
|
+
model.getTrackTooltipFn(overlapping_cells.track)(
|
|
293
|
+
overlapping_data
|
|
294
|
+
)
|
|
295
|
+
);
|
|
234
296
|
} else {
|
|
235
297
|
tooltip.hideIfNotAlreadyGoingTo(150);
|
|
236
298
|
overlapping_cells = null;
|
|
@@ -240,19 +302,30 @@ export default class OncoprintWebGLCellView {
|
|
|
240
302
|
drag_end_x = mouseX;
|
|
241
303
|
const left = Math.min(mouseX, drag_start_x);
|
|
242
304
|
const right = Math.max(mouseX, drag_start_x);
|
|
243
|
-
const drag_rect_fill = dragIsValid(drag_start_x, drag_end_x)
|
|
244
|
-
|
|
305
|
+
const drag_rect_fill = dragIsValid(drag_start_x, drag_end_x)
|
|
306
|
+
? 'rgba(0,0,0,0.3)'
|
|
307
|
+
: 'rgba(0,0,0,0.2)';
|
|
308
|
+
self.overlayFillRect(
|
|
309
|
+
left,
|
|
310
|
+
0,
|
|
311
|
+
right - left,
|
|
312
|
+
self.getVisibleAreaHeight(model),
|
|
313
|
+
drag_rect_fill
|
|
314
|
+
);
|
|
245
315
|
}
|
|
246
316
|
if (overlapping_cells === null) {
|
|
247
317
|
last_cell_over = null;
|
|
248
318
|
cell_over_callback(null);
|
|
249
319
|
}
|
|
250
320
|
|
|
251
|
-
self.highlightHighlightedIds(
|
|
321
|
+
self.highlightHighlightedIds(
|
|
322
|
+
model,
|
|
323
|
+
overlapping_cells ? overlapping_cells.ids : []
|
|
324
|
+
);
|
|
252
325
|
self.highlightHighlightedTracks(model);
|
|
253
326
|
});
|
|
254
327
|
|
|
255
|
-
self.$overlay_canvas.on(
|
|
328
|
+
self.$overlay_canvas.on('mousedown', function(evt) {
|
|
256
329
|
if (!mouseInOverlayCanvas(evt.pageX, evt.pageY)) {
|
|
257
330
|
return;
|
|
258
331
|
}
|
|
@@ -262,16 +335,15 @@ export default class OncoprintWebGLCellView {
|
|
|
262
335
|
|
|
263
336
|
tooltip.hide();
|
|
264
337
|
});
|
|
265
|
-
self.$overlay_canvas.on(
|
|
338
|
+
self.$overlay_canvas.on('mouseup', function(evt) {
|
|
266
339
|
if (!mouseInOverlayCanvas(evt.pageX, evt.pageY)) {
|
|
267
340
|
return;
|
|
268
341
|
}
|
|
269
342
|
executeDragOrClick(evt);
|
|
270
343
|
});
|
|
271
|
-
self.$overlay_canvas.on(
|
|
344
|
+
self.$overlay_canvas.on('mouseleave', function(evt) {
|
|
272
345
|
executeDragOrClick();
|
|
273
346
|
});
|
|
274
|
-
|
|
275
347
|
})(this);
|
|
276
348
|
|
|
277
349
|
$dummy_scroll_div_contents.parent().scroll(function() {
|
|
@@ -295,7 +367,12 @@ export default class OncoprintWebGLCellView {
|
|
|
295
367
|
private getWebGLCanvasContext() {
|
|
296
368
|
try {
|
|
297
369
|
const canvas = this.$canvas[0];
|
|
298
|
-
const ctx =
|
|
370
|
+
const ctx =
|
|
371
|
+
this.ctx ||
|
|
372
|
+
(canvas.getContext('experimental-webgl', {
|
|
373
|
+
alpha: false,
|
|
374
|
+
antialias: this.antialias,
|
|
375
|
+
}) as OncoprintWebGLContext);
|
|
299
376
|
ctx.clearColor(1.0, 1.0, 1.0, 1.0);
|
|
300
377
|
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT);
|
|
301
378
|
ctx.viewportWidth = canvas.width;
|
|
@@ -313,54 +390,93 @@ export default class OncoprintWebGLCellView {
|
|
|
313
390
|
}
|
|
314
391
|
}
|
|
315
392
|
|
|
316
|
-
private createShaderProgram(
|
|
393
|
+
private createShaderProgram(
|
|
394
|
+
vertex_shader: WebGLShader,
|
|
395
|
+
fragment_shader: WebGLShader
|
|
396
|
+
) {
|
|
317
397
|
const program = this.ctx.createProgram();
|
|
318
398
|
this.ctx.attachShader(program, vertex_shader);
|
|
319
399
|
this.ctx.attachShader(program, fragment_shader);
|
|
320
400
|
|
|
321
401
|
this.ctx.linkProgram(program);
|
|
322
402
|
|
|
323
|
-
const success = this.ctx.getProgramParameter(
|
|
403
|
+
const success = this.ctx.getProgramParameter(
|
|
404
|
+
program,
|
|
405
|
+
this.ctx.LINK_STATUS
|
|
406
|
+
);
|
|
324
407
|
if (!success) {
|
|
325
408
|
const msg = this.ctx.getProgramInfoLog(program);
|
|
326
409
|
this.ctx.deleteProgram(program);
|
|
327
|
-
throw
|
|
410
|
+
throw 'Unable to link shader program: ' + msg;
|
|
328
411
|
}
|
|
329
412
|
|
|
330
413
|
return program;
|
|
331
414
|
}
|
|
332
415
|
|
|
333
|
-
private createShader(
|
|
416
|
+
private createShader(
|
|
417
|
+
source: string,
|
|
418
|
+
type: 'VERTEX_SHADER' | 'FRAGMENT_SHADER'
|
|
419
|
+
) {
|
|
334
420
|
const shader = this.ctx.createShader(this.ctx[type]);
|
|
335
421
|
this.ctx.shaderSource(shader, source);
|
|
336
422
|
this.ctx.compileShader(shader);
|
|
337
423
|
|
|
338
|
-
const success = this.ctx.getShaderParameter(
|
|
424
|
+
const success = this.ctx.getShaderParameter(
|
|
425
|
+
shader,
|
|
426
|
+
this.ctx.COMPILE_STATUS
|
|
427
|
+
);
|
|
339
428
|
if (!success) {
|
|
340
429
|
const msg = this.ctx.getShaderInfoLog(shader);
|
|
341
430
|
this.ctx.deleteShader(shader);
|
|
342
|
-
throw
|
|
431
|
+
throw 'Unable to compile shader: ' + msg;
|
|
343
432
|
}
|
|
344
433
|
|
|
345
434
|
return shader;
|
|
346
435
|
}
|
|
347
436
|
|
|
348
|
-
private overlayStrokeRect(
|
|
437
|
+
private overlayStrokeRect(
|
|
438
|
+
x: number,
|
|
439
|
+
y: number,
|
|
440
|
+
width: number,
|
|
441
|
+
height: number,
|
|
442
|
+
color: string
|
|
443
|
+
) {
|
|
349
444
|
const ctx = this.overlay_ctx;
|
|
350
445
|
ctx.strokeStyle = color;
|
|
351
446
|
(ctx as any).strokeWidth = 10;
|
|
352
|
-
ctx.strokeRect(
|
|
447
|
+
ctx.strokeRect(
|
|
448
|
+
this.supersampling_ratio * x,
|
|
449
|
+
this.supersampling_ratio * y,
|
|
450
|
+
this.supersampling_ratio * width,
|
|
451
|
+
this.supersampling_ratio * height
|
|
452
|
+
);
|
|
353
453
|
}
|
|
354
454
|
|
|
355
|
-
private overlayFillRect(
|
|
455
|
+
private overlayFillRect(
|
|
456
|
+
x: number,
|
|
457
|
+
y: number,
|
|
458
|
+
width: number,
|
|
459
|
+
height: number,
|
|
460
|
+
color: string
|
|
461
|
+
) {
|
|
356
462
|
const ctx = this.overlay_ctx;
|
|
357
463
|
ctx.fillStyle = color;
|
|
358
|
-
ctx.fillRect(
|
|
464
|
+
ctx.fillRect(
|
|
465
|
+
this.supersampling_ratio * x,
|
|
466
|
+
this.supersampling_ratio * y,
|
|
467
|
+
this.supersampling_ratio * width,
|
|
468
|
+
this.supersampling_ratio * height
|
|
469
|
+
);
|
|
359
470
|
}
|
|
360
471
|
|
|
361
472
|
public clearOverlay() {
|
|
362
|
-
this.overlay_ctx.fillStyle =
|
|
363
|
-
this.overlay_ctx.clearRect(
|
|
473
|
+
this.overlay_ctx.fillStyle = 'rgba(0,0,0,0)';
|
|
474
|
+
this.overlay_ctx.clearRect(
|
|
475
|
+
0,
|
|
476
|
+
0,
|
|
477
|
+
this.$overlay_canvas[0].width,
|
|
478
|
+
this.$overlay_canvas[0].height
|
|
479
|
+
);
|
|
364
480
|
}
|
|
365
481
|
|
|
366
482
|
private getOverlayContextAndClear() {
|
|
@@ -372,33 +488,52 @@ export default class OncoprintWebGLCellView {
|
|
|
372
488
|
this.column_label_ctx = this.$column_label_canvas[0].getContext('2d');
|
|
373
489
|
}
|
|
374
490
|
|
|
375
|
-
private getColumnLabelY(model:OncoprintModel) {
|
|
376
|
-
return (
|
|
491
|
+
private getColumnLabelY(model: OncoprintModel) {
|
|
492
|
+
return (
|
|
493
|
+
(model.getOncoprintHeight() + 10 - this.scroll_y) *
|
|
494
|
+
this.supersampling_ratio
|
|
495
|
+
);
|
|
377
496
|
}
|
|
378
497
|
|
|
379
|
-
private overlayColumnLabelHighlight(model:OncoprintModel, id:ColumnId) {
|
|
498
|
+
private overlayColumnLabelHighlight(model: OncoprintModel, id: ColumnId) {
|
|
380
499
|
const label = model.getColumnLabels()[id];
|
|
381
500
|
if (label) {
|
|
382
501
|
this.prepareContextForColumnLabelText(model, this.overlay_ctx);
|
|
383
502
|
const cell_width = model.getCellWidth();
|
|
384
|
-
const left_padding =
|
|
385
|
-
|
|
386
|
-
let
|
|
387
|
-
let
|
|
503
|
+
const left_padding =
|
|
504
|
+
((label.left_padding_percent || 0) * cell_width) / 100;
|
|
505
|
+
let highlightHeight = cell_width * this.supersampling_ratio;
|
|
506
|
+
let highlightWidth =
|
|
507
|
+
this.overlay_ctx.measureText(label.text).width +
|
|
508
|
+
left_padding * this.supersampling_ratio +
|
|
509
|
+
20;
|
|
510
|
+
let dx = left_padding * this.supersampling_ratio;
|
|
388
511
|
if (label.circle_color) {
|
|
389
|
-
const circleDiameter =
|
|
512
|
+
const circleDiameter =
|
|
513
|
+
2 *
|
|
514
|
+
this.getColumnLabelCircleSpec(model).radius *
|
|
515
|
+
this.supersampling_ratio;
|
|
390
516
|
highlightHeight = Math.max(highlightHeight, circleDiameter);
|
|
391
517
|
highlightWidth = Math.max(highlightWidth, circleDiameter);
|
|
392
|
-
dx = Math.min(dx, -circleDiameter/2);
|
|
518
|
+
dx = Math.min(dx, -circleDiameter / 2);
|
|
393
519
|
}
|
|
394
|
-
const origin_x =
|
|
520
|
+
const origin_x =
|
|
521
|
+
(model.getZoomedColumnLeft(id) +
|
|
522
|
+
cell_width / 2 -
|
|
523
|
+
this.scroll_x) *
|
|
524
|
+
this.supersampling_ratio;
|
|
395
525
|
const origin_y = this.getColumnLabelY(model);
|
|
396
526
|
this.overlay_ctx.save();
|
|
397
527
|
this.overlay_ctx.translate(origin_x, origin_y);
|
|
398
528
|
const angle = this.getColumnLabelAngleRadians(label);
|
|
399
529
|
this.overlay_ctx.rotate(angle);
|
|
400
|
-
this.overlay_ctx.fillStyle =
|
|
401
|
-
this.overlay_ctx.fillRect(
|
|
530
|
+
this.overlay_ctx.fillStyle = 'rgba(255,255,0,0.4)';
|
|
531
|
+
this.overlay_ctx.fillRect(
|
|
532
|
+
dx,
|
|
533
|
+
-highlightHeight / 2,
|
|
534
|
+
highlightWidth,
|
|
535
|
+
highlightHeight
|
|
536
|
+
);
|
|
402
537
|
this.overlay_ctx.restore();
|
|
403
538
|
}
|
|
404
539
|
}
|
|
@@ -414,66 +549,149 @@ export default class OncoprintWebGLCellView {
|
|
|
414
549
|
self.mvMatrix = mvMatrix;
|
|
415
550
|
|
|
416
551
|
const pMatrix = gl_matrix.mat4.create();
|
|
417
|
-
gl_matrix.mat4.ortho(
|
|
552
|
+
gl_matrix.mat4.ortho(
|
|
553
|
+
pMatrix,
|
|
554
|
+
0,
|
|
555
|
+
self.ctx.viewportWidth,
|
|
556
|
+
self.ctx.viewportHeight,
|
|
557
|
+
0,
|
|
558
|
+
-5,
|
|
559
|
+
1000
|
|
560
|
+
); // y axis inverted so that y increases down like SVG
|
|
418
561
|
self.pMatrix = pMatrix;
|
|
419
562
|
})(this);
|
|
420
563
|
}
|
|
421
564
|
|
|
422
|
-
private getColumnIndexesAfterAGap(model:OncoprintModel) {
|
|
565
|
+
private getColumnIndexesAfterAGap(model: OncoprintModel) {
|
|
423
566
|
// uniform length is minimum 1
|
|
424
|
-
return model
|
|
567
|
+
return model
|
|
568
|
+
.getColumnIndexesAfterAGap()
|
|
569
|
+
.concat([Number.POSITIVE_INFINITY]);
|
|
425
570
|
}
|
|
426
571
|
|
|
427
|
-
private setUpShaders(model:OncoprintModel) {
|
|
428
|
-
const columnsRightAfterGapsSize = this.getColumnIndexesAfterAGap(model)
|
|
429
|
-
|
|
430
|
-
const
|
|
572
|
+
private setUpShaders(model: OncoprintModel) {
|
|
573
|
+
const columnsRightAfterGapsSize = this.getColumnIndexesAfterAGap(model)
|
|
574
|
+
.length;
|
|
575
|
+
const vertex_shader = this.createShader(
|
|
576
|
+
getVertexShaderSource(columnsRightAfterGapsSize),
|
|
577
|
+
'VERTEX_SHADER'
|
|
578
|
+
);
|
|
579
|
+
const fragment_shader = this.createShader(
|
|
580
|
+
getFragmentShaderSource(),
|
|
581
|
+
'FRAGMENT_SHADER'
|
|
582
|
+
);
|
|
431
583
|
|
|
432
|
-
const shader_program = this.createShaderProgram(
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
584
|
+
const shader_program = this.createShaderProgram(
|
|
585
|
+
vertex_shader,
|
|
586
|
+
fragment_shader
|
|
587
|
+
) as OncoprintShaderProgram;
|
|
588
|
+
shader_program.vertexPositionAttribute = this.ctx.getAttribLocation(
|
|
589
|
+
shader_program,
|
|
590
|
+
'aPosVertex'
|
|
591
|
+
);
|
|
592
|
+
this.ctx.enableVertexAttribArray(
|
|
593
|
+
shader_program.vertexPositionAttribute
|
|
594
|
+
);
|
|
595
|
+
shader_program.vertexColorAttribute = this.ctx.getAttribLocation(
|
|
596
|
+
shader_program,
|
|
597
|
+
'aColVertex'
|
|
598
|
+
);
|
|
436
599
|
this.ctx.enableVertexAttribArray(shader_program.vertexColorAttribute);
|
|
437
|
-
shader_program.vertexOncoprintColumnAttribute = this.ctx.getAttribLocation(
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
shader_program.
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
shader_program.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
shader_program.
|
|
600
|
+
shader_program.vertexOncoprintColumnAttribute = this.ctx.getAttribLocation(
|
|
601
|
+
shader_program,
|
|
602
|
+
'aVertexOncoprintColumn'
|
|
603
|
+
);
|
|
604
|
+
this.ctx.enableVertexAttribArray(
|
|
605
|
+
shader_program.vertexOncoprintColumnAttribute
|
|
606
|
+
);
|
|
607
|
+
|
|
608
|
+
shader_program.gapSizeUniform = this.ctx.getUniformLocation(
|
|
609
|
+
shader_program,
|
|
610
|
+
'gapSize'
|
|
611
|
+
);
|
|
612
|
+
shader_program.columnsRightAfterGapsUniform = this.ctx.getUniformLocation(
|
|
613
|
+
shader_program,
|
|
614
|
+
'columnsRightAfterGaps'
|
|
615
|
+
);
|
|
616
|
+
shader_program.samplerUniform = this.ctx.getUniformLocation(
|
|
617
|
+
shader_program,
|
|
618
|
+
'uSampler'
|
|
619
|
+
);
|
|
620
|
+
shader_program.pMatrixUniform = this.ctx.getUniformLocation(
|
|
621
|
+
shader_program,
|
|
622
|
+
'uPMatrix'
|
|
623
|
+
);
|
|
624
|
+
shader_program.mvMatrixUniform = this.ctx.getUniformLocation(
|
|
625
|
+
shader_program,
|
|
626
|
+
'uMVMatrix'
|
|
627
|
+
);
|
|
628
|
+
shader_program.columnWidthUniform = this.ctx.getUniformLocation(
|
|
629
|
+
shader_program,
|
|
630
|
+
'columnWidth'
|
|
631
|
+
);
|
|
632
|
+
shader_program.scrollXUniform = this.ctx.getUniformLocation(
|
|
633
|
+
shader_program,
|
|
634
|
+
'scrollX'
|
|
635
|
+
);
|
|
636
|
+
shader_program.scrollYUniform = this.ctx.getUniformLocation(
|
|
637
|
+
shader_program,
|
|
638
|
+
'scrollY'
|
|
639
|
+
);
|
|
640
|
+
shader_program.zoomXUniform = this.ctx.getUniformLocation(
|
|
641
|
+
shader_program,
|
|
642
|
+
'zoomX'
|
|
643
|
+
);
|
|
644
|
+
shader_program.zoomYUniform = this.ctx.getUniformLocation(
|
|
645
|
+
shader_program,
|
|
646
|
+
'zoomY'
|
|
647
|
+
);
|
|
648
|
+
shader_program.offsetYUniform = this.ctx.getUniformLocation(
|
|
649
|
+
shader_program,
|
|
650
|
+
'offsetY'
|
|
651
|
+
);
|
|
652
|
+
shader_program.supersamplingRatioUniform = this.ctx.getUniformLocation(
|
|
653
|
+
shader_program,
|
|
654
|
+
'supersamplingRatio'
|
|
655
|
+
);
|
|
656
|
+
shader_program.positionBitPackBaseUniform = this.ctx.getUniformLocation(
|
|
657
|
+
shader_program,
|
|
658
|
+
'positionBitPackBase'
|
|
659
|
+
);
|
|
660
|
+
shader_program.texSizeUniform = this.ctx.getUniformLocation(
|
|
661
|
+
shader_program,
|
|
662
|
+
'texSize'
|
|
663
|
+
);
|
|
454
664
|
|
|
455
665
|
this.shader_program = shader_program;
|
|
456
666
|
}
|
|
457
667
|
|
|
458
|
-
private resizeAndClear(model:OncoprintModel) {
|
|
668
|
+
private resizeAndClear(model: OncoprintModel) {
|
|
459
669
|
const height = this.getVisibleAreaHeight(model);
|
|
460
670
|
const total_width = this.getTotalWidth(model);
|
|
461
671
|
const visible_area_width = this.visible_area_width;
|
|
462
672
|
const scrollbar_slack = 20;
|
|
463
|
-
this.$dummy_scroll_div_contents.css({
|
|
464
|
-
|
|
673
|
+
this.$dummy_scroll_div_contents.css({
|
|
674
|
+
'min-width': total_width,
|
|
675
|
+
'min-height': model.getOncoprintHeight(),
|
|
676
|
+
});
|
|
677
|
+
this.$dummy_scroll_div_contents.parent().css({
|
|
678
|
+
height: height + scrollbar_slack,
|
|
679
|
+
width: visible_area_width + scrollbar_slack,
|
|
680
|
+
}); // add space for scrollbars
|
|
465
681
|
this.dummy_scroll_div_client_size.update();
|
|
466
|
-
this.$canvas[0].height = this.supersampling_ratio*height;
|
|
682
|
+
this.$canvas[0].height = this.supersampling_ratio * height;
|
|
467
683
|
this.$canvas[0].style.height = height + 'px';
|
|
468
|
-
this.$overlay_canvas[0].height = this.supersampling_ratio*height;
|
|
684
|
+
this.$overlay_canvas[0].height = this.supersampling_ratio * height;
|
|
469
685
|
this.$overlay_canvas[0].style.height = height + 'px';
|
|
470
|
-
this.$column_label_canvas[0].height = this.supersampling_ratio*height;
|
|
686
|
+
this.$column_label_canvas[0].height = this.supersampling_ratio * height;
|
|
471
687
|
this.$column_label_canvas[0].style.height = height + 'px';
|
|
472
|
-
this.$canvas[0].width = this.supersampling_ratio*visible_area_width;
|
|
688
|
+
this.$canvas[0].width = this.supersampling_ratio * visible_area_width;
|
|
473
689
|
this.$canvas[0].style.width = visible_area_width + 'px';
|
|
474
|
-
this.$overlay_canvas[0].width =
|
|
690
|
+
this.$overlay_canvas[0].width =
|
|
691
|
+
this.supersampling_ratio * visible_area_width;
|
|
475
692
|
this.$overlay_canvas[0].style.width = visible_area_width + 'px';
|
|
476
|
-
this.$column_label_canvas[0].width =
|
|
693
|
+
this.$column_label_canvas[0].width =
|
|
694
|
+
this.supersampling_ratio * visible_area_width;
|
|
477
695
|
this.$column_label_canvas[0].style.width = visible_area_width + 'px';
|
|
478
696
|
this.$container.css('height', height);
|
|
479
697
|
this.$container.css('width', visible_area_width);
|
|
@@ -483,7 +701,7 @@ export default class OncoprintWebGLCellView {
|
|
|
483
701
|
this.getColumnLabelsContext();
|
|
484
702
|
}
|
|
485
703
|
|
|
486
|
-
private renderAllTracks(model:OncoprintModel, dont_resize?:boolean) {
|
|
704
|
+
private renderAllTracks(model: OncoprintModel, dont_resize?: boolean) {
|
|
487
705
|
if (this.rendering_suppressed) {
|
|
488
706
|
return;
|
|
489
707
|
}
|
|
@@ -499,21 +717,30 @@ export default class OncoprintWebGLCellView {
|
|
|
499
717
|
const window_top = viewport.top;
|
|
500
718
|
const window_bottom = viewport.bottom;
|
|
501
719
|
const id_order = model.getIdOrder();
|
|
502
|
-
let horz_first_id_in_window_index = model.getClosestColumnIndexToLeft(
|
|
503
|
-
|
|
504
|
-
|
|
720
|
+
let horz_first_id_in_window_index = model.getClosestColumnIndexToLeft(
|
|
721
|
+
window_left
|
|
722
|
+
);
|
|
723
|
+
const horz_first_id_after_window_index = model.getClosestColumnIndexToLeft(
|
|
724
|
+
window_right,
|
|
725
|
+
false,
|
|
726
|
+
true
|
|
727
|
+
);
|
|
728
|
+
horz_first_id_in_window_index =
|
|
729
|
+
horz_first_id_in_window_index < 1
|
|
730
|
+
? 0
|
|
731
|
+
: horz_first_id_in_window_index - 1;
|
|
505
732
|
|
|
506
733
|
const horz_first_id_in_window = id_order[horz_first_id_in_window_index];
|
|
507
|
-
const horz_first_id_after_window =
|
|
508
|
-
horz_first_id_after_window_index === -1 ||
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
734
|
+
const horz_first_id_after_window =
|
|
735
|
+
horz_first_id_after_window_index === -1 ||
|
|
736
|
+
horz_first_id_after_window_index === id_order.length
|
|
737
|
+
? null
|
|
738
|
+
: id_order[horz_first_id_after_window_index];
|
|
512
739
|
|
|
513
740
|
if (!dont_resize) {
|
|
514
741
|
this.resizeAndClear(model);
|
|
515
742
|
}
|
|
516
|
-
this.ctx.clearColor(1.0,1.0,1.0,1.0);
|
|
743
|
+
this.ctx.clearColor(1.0, 1.0, 1.0, 1.0);
|
|
517
744
|
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
|
|
518
745
|
|
|
519
746
|
const tracks = model.getTracks();
|
|
@@ -521,7 +748,10 @@ export default class OncoprintWebGLCellView {
|
|
|
521
748
|
const track_id = tracks[i];
|
|
522
749
|
const cell_top = model.getCellTops(track_id);
|
|
523
750
|
const cell_height = model.getCellHeight(track_id);
|
|
524
|
-
if (
|
|
751
|
+
if (
|
|
752
|
+
cell_top / zoom_y >= window_bottom ||
|
|
753
|
+
(cell_top + cell_height) / zoom_y < window_top
|
|
754
|
+
) {
|
|
525
755
|
// vertical clipping
|
|
526
756
|
continue;
|
|
527
757
|
}
|
|
@@ -530,90 +760,207 @@ export default class OncoprintWebGLCellView {
|
|
|
530
760
|
continue;
|
|
531
761
|
}
|
|
532
762
|
|
|
533
|
-
for (const forSpecificShapes of [false,true]) {
|
|
763
|
+
for (const forSpecificShapes of [false, true]) {
|
|
534
764
|
const shader_program = this.shader_program;
|
|
535
765
|
this.ctx.useProgram(shader_program);
|
|
536
766
|
|
|
537
767
|
if (forSpecificShapes) {
|
|
538
|
-
this.ctx.bindBuffer(
|
|
539
|
-
|
|
768
|
+
this.ctx.bindBuffer(
|
|
769
|
+
this.ctx.ARRAY_BUFFER,
|
|
770
|
+
buffers.position
|
|
771
|
+
);
|
|
772
|
+
this.ctx.vertexAttribPointer(
|
|
773
|
+
shader_program.vertexPositionAttribute,
|
|
774
|
+
buffers.position.itemSize,
|
|
775
|
+
this.ctx.FLOAT,
|
|
776
|
+
false,
|
|
777
|
+
0,
|
|
778
|
+
0
|
|
779
|
+
);
|
|
540
780
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, buffers.color);
|
|
541
|
-
this.ctx.vertexAttribPointer(
|
|
781
|
+
this.ctx.vertexAttribPointer(
|
|
782
|
+
shader_program.vertexColorAttribute,
|
|
783
|
+
buffers.color.itemSize,
|
|
784
|
+
this.ctx.FLOAT,
|
|
785
|
+
false,
|
|
786
|
+
0,
|
|
787
|
+
0
|
|
788
|
+
);
|
|
542
789
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, buffers.column);
|
|
543
|
-
this.ctx.vertexAttribPointer(
|
|
790
|
+
this.ctx.vertexAttribPointer(
|
|
791
|
+
shader_program.vertexOncoprintColumnAttribute,
|
|
792
|
+
buffers.column.itemSize,
|
|
793
|
+
this.ctx.FLOAT,
|
|
794
|
+
false,
|
|
795
|
+
0,
|
|
796
|
+
0
|
|
797
|
+
);
|
|
544
798
|
// make sure to set divisor 0, otherwise the track will only use the first item in the column buffer
|
|
545
|
-
this.ext.vertexAttribDivisorANGLE(
|
|
799
|
+
this.ext.vertexAttribDivisorANGLE(
|
|
800
|
+
shader_program.vertexOncoprintColumnAttribute,
|
|
801
|
+
0
|
|
802
|
+
);
|
|
546
803
|
} else {
|
|
547
804
|
// set up for drawArraysInstanced
|
|
548
|
-
const universalShapesStart =
|
|
549
|
-
|
|
550
|
-
|
|
805
|
+
const universalShapesStart =
|
|
806
|
+
buffers.position.specificShapesNumItems *
|
|
807
|
+
buffers.position.itemSize;
|
|
808
|
+
this.ctx.bindBuffer(
|
|
809
|
+
this.ctx.ARRAY_BUFFER,
|
|
810
|
+
buffers.position
|
|
811
|
+
);
|
|
812
|
+
this.ctx.vertexAttribPointer(
|
|
813
|
+
shader_program.vertexPositionAttribute,
|
|
814
|
+
buffers.position.itemSize,
|
|
815
|
+
this.ctx.FLOAT,
|
|
816
|
+
false,
|
|
817
|
+
0,
|
|
818
|
+
4 * universalShapesStart
|
|
819
|
+
);
|
|
551
820
|
|
|
552
821
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, buffers.color);
|
|
553
|
-
this.ctx.vertexAttribPointer(
|
|
822
|
+
this.ctx.vertexAttribPointer(
|
|
823
|
+
shader_program.vertexColorAttribute,
|
|
824
|
+
buffers.color.itemSize,
|
|
825
|
+
this.ctx.FLOAT,
|
|
826
|
+
false,
|
|
827
|
+
0,
|
|
828
|
+
4 * universalShapesStart
|
|
829
|
+
);
|
|
554
830
|
|
|
555
|
-
this.ctx.bindBuffer(
|
|
556
|
-
|
|
557
|
-
|
|
831
|
+
this.ctx.bindBuffer(
|
|
832
|
+
this.ctx.ARRAY_BUFFER,
|
|
833
|
+
this.simple_count_buffer
|
|
834
|
+
);
|
|
835
|
+
this.ctx.vertexAttribPointer(
|
|
836
|
+
shader_program.vertexOncoprintColumnAttribute,
|
|
837
|
+
1,
|
|
838
|
+
this.ctx.FLOAT,
|
|
839
|
+
false,
|
|
840
|
+
0,
|
|
841
|
+
4 * horz_first_id_in_window_index
|
|
842
|
+
);
|
|
843
|
+
this.ext.vertexAttribDivisorANGLE(
|
|
844
|
+
shader_program.vertexOncoprintColumnAttribute,
|
|
845
|
+
1
|
|
846
|
+
);
|
|
558
847
|
}
|
|
559
848
|
|
|
560
849
|
this.ctx.activeTexture(this.ctx.TEXTURE0);
|
|
561
|
-
this.ctx.bindTexture(
|
|
850
|
+
this.ctx.bindTexture(
|
|
851
|
+
this.ctx.TEXTURE_2D,
|
|
852
|
+
buffers.color_tex.texture
|
|
853
|
+
);
|
|
562
854
|
this.ctx.uniform1i(shader_program.samplerUniform, 0);
|
|
563
|
-
this.ctx.uniform1f(
|
|
855
|
+
this.ctx.uniform1f(
|
|
856
|
+
shader_program.texSizeUniform,
|
|
857
|
+
buffers.color_tex.size
|
|
858
|
+
);
|
|
564
859
|
|
|
565
|
-
this.ctx.uniform1fv(
|
|
566
|
-
|
|
860
|
+
this.ctx.uniform1fv(
|
|
861
|
+
shader_program.columnsRightAfterGapsUniform,
|
|
862
|
+
this.getColumnIndexesAfterAGap(model)
|
|
863
|
+
); // need min size of 1
|
|
864
|
+
this.ctx.uniform1f(
|
|
865
|
+
shader_program.gapSizeUniform,
|
|
866
|
+
model.getGapSize()
|
|
867
|
+
);
|
|
567
868
|
|
|
568
|
-
this.ctx.uniformMatrix4fv(
|
|
569
|
-
|
|
570
|
-
|
|
869
|
+
this.ctx.uniformMatrix4fv(
|
|
870
|
+
shader_program.pMatrixUniform,
|
|
871
|
+
false,
|
|
872
|
+
this.pMatrix
|
|
873
|
+
);
|
|
874
|
+
this.ctx.uniformMatrix4fv(
|
|
875
|
+
shader_program.mvMatrixUniform,
|
|
876
|
+
false,
|
|
877
|
+
this.mvMatrix
|
|
878
|
+
);
|
|
879
|
+
this.ctx.uniform1f(
|
|
880
|
+
shader_program.columnWidthUniform,
|
|
881
|
+
model.getCellWidth(true) + model.getCellPadding(true)
|
|
882
|
+
);
|
|
571
883
|
this.ctx.uniform1f(shader_program.scrollXUniform, scroll_x);
|
|
572
884
|
this.ctx.uniform1f(shader_program.scrollYUniform, scroll_y);
|
|
573
885
|
this.ctx.uniform1f(shader_program.zoomXUniform, zoom_x);
|
|
574
886
|
this.ctx.uniform1f(shader_program.zoomYUniform, zoom_y);
|
|
575
887
|
this.ctx.uniform1f(shader_program.offsetYUniform, cell_top);
|
|
576
|
-
this.ctx.uniform1f(
|
|
577
|
-
|
|
888
|
+
this.ctx.uniform1f(
|
|
889
|
+
shader_program.supersamplingRatioUniform,
|
|
890
|
+
this.supersampling_ratio
|
|
891
|
+
);
|
|
892
|
+
this.ctx.uniform1f(
|
|
893
|
+
shader_program.positionBitPackBaseUniform,
|
|
894
|
+
this.position_bit_pack_base
|
|
895
|
+
);
|
|
578
896
|
if (forSpecificShapes) {
|
|
579
|
-
const first_index = this.id_to_first_vertex_index[track_id][
|
|
580
|
-
|
|
581
|
-
|
|
897
|
+
const first_index = this.id_to_first_vertex_index[track_id][
|
|
898
|
+
horz_first_id_in_window
|
|
899
|
+
];
|
|
900
|
+
const first_index_out =
|
|
901
|
+
horz_first_id_after_window === null
|
|
902
|
+
? buffers.position.specificShapesNumItems
|
|
903
|
+
: this.id_to_first_vertex_index[track_id][
|
|
904
|
+
horz_first_id_after_window
|
|
905
|
+
];
|
|
906
|
+
this.ctx.drawArrays(
|
|
907
|
+
this.ctx.TRIANGLES,
|
|
908
|
+
first_index,
|
|
909
|
+
first_index_out - first_index
|
|
910
|
+
);
|
|
582
911
|
} else {
|
|
583
912
|
this.ext.drawArraysInstancedANGLE(
|
|
584
913
|
this.ctx.TRIANGLES,
|
|
585
914
|
0,
|
|
586
|
-
buffers.position.itemSize *
|
|
587
|
-
|
|
915
|
+
buffers.position.itemSize *
|
|
916
|
+
buffers.position.universalShapesNumItems,
|
|
917
|
+
horz_first_id_after_window_index -
|
|
918
|
+
horz_first_id_in_window_index
|
|
588
919
|
);
|
|
589
920
|
}
|
|
590
921
|
}
|
|
591
922
|
}
|
|
592
923
|
this.ctx.flush();
|
|
593
|
-
this.renderColumnLabels(
|
|
924
|
+
this.renderColumnLabels(
|
|
925
|
+
model,
|
|
926
|
+
id_order.slice(
|
|
927
|
+
horz_first_id_in_window_index,
|
|
928
|
+
horz_first_id_after_window_index === -1
|
|
929
|
+
? undefined
|
|
930
|
+
: horz_first_id_after_window_index
|
|
931
|
+
)
|
|
932
|
+
);
|
|
594
933
|
|
|
595
934
|
// finally, refresh overlay (highlights)
|
|
596
935
|
this.clearOverlay();
|
|
597
936
|
this.highlightHighlightedIds(model);
|
|
598
937
|
this.highlightHighlightedTracks(model);
|
|
599
|
-
}
|
|
938
|
+
}
|
|
600
939
|
|
|
601
|
-
private static getColumnLabelsFontSize(model:OncoprintModel) {
|
|
602
|
-
return model.getCellWidth()/2 + 2;
|
|
940
|
+
private static getColumnLabelsFontSize(model: OncoprintModel) {
|
|
941
|
+
return model.getCellWidth() / 2 + 2;
|
|
603
942
|
}
|
|
604
943
|
|
|
605
|
-
private prepareContextForColumnLabelText(
|
|
944
|
+
private prepareContextForColumnLabelText(
|
|
945
|
+
model: OncoprintModel,
|
|
946
|
+
ctx: CanvasRenderingContext2D
|
|
947
|
+
) {
|
|
606
948
|
const font_size = OncoprintWebGLCellView.getColumnLabelsFontSize(model);
|
|
607
|
-
const font_family =
|
|
608
|
-
ctx.font =
|
|
609
|
-
ctx.textAlign =
|
|
610
|
-
ctx.textBaseline =
|
|
949
|
+
const font_family = 'Arial';
|
|
950
|
+
ctx.font = this.supersampling_ratio * font_size + 'px ' + font_family;
|
|
951
|
+
ctx.textAlign = 'left';
|
|
952
|
+
ctx.textBaseline = 'middle';
|
|
611
953
|
}
|
|
612
954
|
|
|
613
|
-
private renderColumnLabels(model:OncoprintModel, ids:ColumnId[]) {
|
|
955
|
+
private renderColumnLabels(model: OncoprintModel, ids: ColumnId[]) {
|
|
614
956
|
// first clear
|
|
615
|
-
this.column_label_ctx.fillStyle =
|
|
616
|
-
this.column_label_ctx.clearRect(
|
|
957
|
+
this.column_label_ctx.fillStyle = 'rgba(0,0,0,0)';
|
|
958
|
+
this.column_label_ctx.clearRect(
|
|
959
|
+
0,
|
|
960
|
+
0,
|
|
961
|
+
this.$column_label_canvas[0].width,
|
|
962
|
+
this.$column_label_canvas[0].height
|
|
963
|
+
);
|
|
617
964
|
this.maximum_column_label_width = 0;
|
|
618
965
|
this.maximum_column_label_height = 0;
|
|
619
966
|
|
|
@@ -631,40 +978,61 @@ export default class OncoprintWebGLCellView {
|
|
|
631
978
|
const cell_width = model.getCellWidth();
|
|
632
979
|
|
|
633
980
|
this.prepareContextForColumnLabelText(model, this.column_label_ctx);
|
|
634
|
-
for (let i=0; i<ids.length; i++) {
|
|
981
|
+
for (let i = 0; i < ids.length; i++) {
|
|
635
982
|
const label = labels[ids[i]];
|
|
636
|
-
let label_height =
|
|
983
|
+
let label_height =
|
|
984
|
+
this.column_label_ctx.measureText('m').width /
|
|
985
|
+
this.supersampling_ratio;
|
|
637
986
|
if (label) {
|
|
638
|
-
const origin_x =
|
|
987
|
+
const origin_x =
|
|
988
|
+
(x_map[ids[i]] + cell_width / 2 - scroll_x) *
|
|
989
|
+
this.supersampling_ratio;
|
|
639
990
|
if (label.circle_color) {
|
|
640
991
|
// draw circle if specified
|
|
641
992
|
this.column_label_ctx.save();
|
|
642
993
|
const circleSpec = this.getColumnLabelCircleSpec(model);
|
|
643
|
-
label_height = Math.max(
|
|
994
|
+
label_height = Math.max(
|
|
995
|
+
2 * circleSpec.radius,
|
|
996
|
+
label_height
|
|
997
|
+
);
|
|
644
998
|
this.column_label_ctx.translate(origin_x, origin_y);
|
|
645
999
|
this.column_label_ctx.fillStyle = label.circle_color;
|
|
646
1000
|
this.column_label_ctx.beginPath();
|
|
647
|
-
this.column_label_ctx.arc(
|
|
1001
|
+
this.column_label_ctx.arc(
|
|
1002
|
+
0,
|
|
1003
|
+
0,
|
|
1004
|
+
this.supersampling_ratio * circleSpec.radius,
|
|
1005
|
+
0,
|
|
1006
|
+
2 * Math.PI
|
|
1007
|
+
);
|
|
648
1008
|
this.column_label_ctx.fill();
|
|
649
1009
|
this.column_label_ctx.restore();
|
|
650
1010
|
}
|
|
651
1011
|
this.column_label_ctx.save();
|
|
652
1012
|
const text_angle = this.getColumnLabelAngleRadians(label);
|
|
653
|
-
const left_padding =
|
|
1013
|
+
const left_padding =
|
|
1014
|
+
((label.left_padding_percent || 0) * cell_width) / 100;
|
|
654
1015
|
this.column_label_ctx.translate(origin_x, origin_y);
|
|
655
1016
|
this.column_label_ctx.rotate(text_angle);
|
|
656
|
-
this.column_label_ctx.fillStyle =
|
|
657
|
-
|
|
658
|
-
|
|
1017
|
+
this.column_label_ctx.fillStyle =
|
|
1018
|
+
label.text_color || 'rgba(0,0,0,1)';
|
|
1019
|
+
this.column_label_ctx.fillText(
|
|
1020
|
+
label.text,
|
|
1021
|
+
left_padding * this.supersampling_ratio,
|
|
1022
|
+
0
|
|
1023
|
+
);
|
|
1024
|
+
const text_width =
|
|
1025
|
+
this.column_label_ctx.measureText(label.text).width /
|
|
1026
|
+
this.supersampling_ratio;
|
|
659
1027
|
|
|
660
1028
|
this.maximum_column_label_width = Math.max(
|
|
661
1029
|
this.maximum_column_label_width,
|
|
662
|
-
Math.cos(text_angle)*text_width
|
|
1030
|
+
Math.cos(text_angle) * text_width
|
|
663
1031
|
);
|
|
664
1032
|
|
|
665
1033
|
this.maximum_column_label_height = Math.max(
|
|
666
1034
|
this.maximum_column_label_height,
|
|
667
|
-
Math.sin(text_angle)*text_width,
|
|
1035
|
+
Math.sin(text_angle) * text_width,
|
|
668
1036
|
label_height
|
|
669
1037
|
);
|
|
670
1038
|
|
|
@@ -673,35 +1041,47 @@ export default class OncoprintWebGLCellView {
|
|
|
673
1041
|
}
|
|
674
1042
|
}
|
|
675
1043
|
|
|
676
|
-
private getColumnLabelAngleRadians(label:ColumnLabel) {
|
|
677
|
-
return
|
|
1044
|
+
private getColumnLabelAngleRadians(label: ColumnLabel) {
|
|
1045
|
+
return (
|
|
1046
|
+
(ifndef(label.angle_in_degrees, COLUMN_LABEL_ANGLE) * Math.PI) / 180
|
|
1047
|
+
);
|
|
678
1048
|
}
|
|
679
1049
|
|
|
680
|
-
private getColumnLabelCircleSpec(model:OncoprintModel) {
|
|
681
|
-
|
|
682
|
-
|
|
1050
|
+
private getColumnLabelCircleSpec(model: OncoprintModel) {
|
|
1051
|
+
const radius = 0.9 * (model.getCellWidth() / 2);
|
|
1052
|
+
return { radius };
|
|
683
1053
|
}
|
|
684
1054
|
|
|
685
|
-
private ensureSimpleCountBuffer(model:OncoprintModel) {
|
|
1055
|
+
private ensureSimpleCountBuffer(model: OncoprintModel) {
|
|
686
1056
|
const numColumns = model.getIdOrder().length;
|
|
687
|
-
if (
|
|
1057
|
+
if (
|
|
1058
|
+
!this.simple_count_buffer ||
|
|
1059
|
+
this.simple_count_buffer.numItems !== numColumns
|
|
1060
|
+
) {
|
|
688
1061
|
const buffer = this.ctx.createBuffer() as OncoprintTrackBuffer;
|
|
689
1062
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, buffer);
|
|
690
|
-
this.ctx.bufferData(
|
|
1063
|
+
this.ctx.bufferData(
|
|
1064
|
+
this.ctx.ARRAY_BUFFER,
|
|
1065
|
+
new Float32Array(_.range(0, numColumns)),
|
|
1066
|
+
this.ctx.STATIC_DRAW
|
|
1067
|
+
);
|
|
691
1068
|
buffer.itemSize = 1;
|
|
692
1069
|
buffer.numItems = numColumns;
|
|
693
1070
|
this.simple_count_buffer = buffer;
|
|
694
1071
|
}
|
|
695
1072
|
}
|
|
696
1073
|
|
|
697
|
-
private clearTrackPositionAndColorBuffers(
|
|
1074
|
+
private clearTrackPositionAndColorBuffers(
|
|
1075
|
+
model: OncoprintModel,
|
|
1076
|
+
track_id?: TrackId
|
|
1077
|
+
) {
|
|
698
1078
|
let tracks_to_clear;
|
|
699
1079
|
if (typeof track_id === 'undefined') {
|
|
700
1080
|
tracks_to_clear = model.getTracks();
|
|
701
1081
|
} else {
|
|
702
1082
|
tracks_to_clear = [track_id];
|
|
703
1083
|
}
|
|
704
|
-
for (let i=0; i<tracks_to_clear.length; i++) {
|
|
1084
|
+
for (let i = 0; i < tracks_to_clear.length; i++) {
|
|
705
1085
|
if (this.is_buffer_empty[tracks_to_clear[i]]) {
|
|
706
1086
|
this.is_buffer_empty[tracks_to_clear[i]].position = true;
|
|
707
1087
|
this.is_buffer_empty[tracks_to_clear[i]].color = true;
|
|
@@ -710,28 +1090,28 @@ export default class OncoprintWebGLCellView {
|
|
|
710
1090
|
}
|
|
711
1091
|
}
|
|
712
1092
|
|
|
713
|
-
private clearTrackColumnBuffers(model:OncoprintModel, track_id?:TrackId) {
|
|
1093
|
+
private clearTrackColumnBuffers(model: OncoprintModel, track_id?: TrackId) {
|
|
714
1094
|
let tracks_to_clear;
|
|
715
1095
|
if (typeof track_id === 'undefined') {
|
|
716
1096
|
tracks_to_clear = model.getTracks();
|
|
717
1097
|
} else {
|
|
718
1098
|
tracks_to_clear = [track_id];
|
|
719
1099
|
}
|
|
720
|
-
for (let i=0; i<tracks_to_clear.length; i++) {
|
|
1100
|
+
for (let i = 0; i < tracks_to_clear.length; i++) {
|
|
721
1101
|
if (this.is_buffer_empty[tracks_to_clear[i]]) {
|
|
722
1102
|
this.is_buffer_empty[tracks_to_clear[i]].column = true;
|
|
723
1103
|
}
|
|
724
1104
|
}
|
|
725
|
-
}
|
|
1105
|
+
}
|
|
726
1106
|
|
|
727
|
-
private deleteBuffers(model: OncoprintModel, track_id?:TrackId) {
|
|
1107
|
+
private deleteBuffers(model: OncoprintModel, track_id?: TrackId) {
|
|
728
1108
|
let tracks_to_clear;
|
|
729
1109
|
if (typeof track_id === 'undefined') {
|
|
730
1110
|
tracks_to_clear = model.getTracks();
|
|
731
1111
|
} else {
|
|
732
1112
|
tracks_to_clear = [track_id];
|
|
733
1113
|
}
|
|
734
|
-
for (let i=0; i<tracks_to_clear.length; i++) {
|
|
1114
|
+
for (let i = 0; i < tracks_to_clear.length; i++) {
|
|
735
1115
|
const track_id = tracks_to_clear[i];
|
|
736
1116
|
if (this.vertex_position_buffer[track_id]) {
|
|
737
1117
|
this.ctx.deleteBuffer(this.vertex_position_buffer[track_id]);
|
|
@@ -752,78 +1132,128 @@ export default class OncoprintWebGLCellView {
|
|
|
752
1132
|
this.is_buffer_empty[track_id] = {
|
|
753
1133
|
position: true,
|
|
754
1134
|
color: true,
|
|
755
|
-
color_texture:true,
|
|
756
|
-
column: true
|
|
1135
|
+
color_texture: true,
|
|
1136
|
+
column: true,
|
|
757
1137
|
};
|
|
758
1138
|
}
|
|
759
1139
|
}
|
|
760
1140
|
|
|
761
|
-
private deleteSimpleCountBuffer(model:OncoprintModel) {
|
|
1141
|
+
private deleteSimpleCountBuffer(model: OncoprintModel) {
|
|
762
1142
|
if (this.simple_count_buffer) {
|
|
763
1143
|
this.ctx.deleteBuffer(this.simple_count_buffer);
|
|
764
1144
|
this.simple_count_buffer = null;
|
|
765
1145
|
}
|
|
766
1146
|
}
|
|
767
1147
|
|
|
768
|
-
private getTrackBuffers(track_id:TrackId) {
|
|
1148
|
+
private getTrackBuffers(track_id: TrackId) {
|
|
769
1149
|
this.is_buffer_empty[track_id] = this.is_buffer_empty[track_id] || {
|
|
770
1150
|
position: true,
|
|
771
1151
|
color: true,
|
|
772
1152
|
color_texture: true,
|
|
773
|
-
column: true
|
|
1153
|
+
column: true,
|
|
774
1154
|
};
|
|
775
1155
|
|
|
776
1156
|
if (this.is_buffer_empty[track_id].position) {
|
|
777
|
-
const pos_buffer =
|
|
1157
|
+
const pos_buffer =
|
|
1158
|
+
this.vertex_position_buffer[track_id] ||
|
|
1159
|
+
(this.ctx.createBuffer() as OncoprintVertexTrackBuffer);
|
|
778
1160
|
const pos_array = this.vertex_data[track_id].pos_array;
|
|
779
|
-
const universal_shapes_start_index = this.vertex_data[track_id]
|
|
1161
|
+
const universal_shapes_start_index = this.vertex_data[track_id]
|
|
1162
|
+
.universal_shapes_start_index;
|
|
780
1163
|
|
|
781
1164
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, pos_buffer);
|
|
782
|
-
this.ctx.bufferData(
|
|
1165
|
+
this.ctx.bufferData(
|
|
1166
|
+
this.ctx.ARRAY_BUFFER,
|
|
1167
|
+
pos_array,
|
|
1168
|
+
this.ctx.STATIC_DRAW
|
|
1169
|
+
);
|
|
783
1170
|
pos_buffer.itemSize = 1;
|
|
784
|
-
pos_buffer.specificShapesNumItems =
|
|
785
|
-
|
|
1171
|
+
pos_buffer.specificShapesNumItems =
|
|
1172
|
+
universal_shapes_start_index / pos_buffer.itemSize;
|
|
1173
|
+
pos_buffer.universalShapesNumItems =
|
|
1174
|
+
(pos_array.length - universal_shapes_start_index) /
|
|
1175
|
+
pos_buffer.itemSize;
|
|
786
1176
|
|
|
787
1177
|
this.vertex_position_buffer[track_id] = pos_buffer;
|
|
788
1178
|
}
|
|
789
1179
|
|
|
790
1180
|
if (this.is_buffer_empty[track_id].color) {
|
|
791
|
-
const col_buffer =
|
|
1181
|
+
const col_buffer =
|
|
1182
|
+
this.vertex_color_buffer[track_id] ||
|
|
1183
|
+
(this.ctx.createBuffer() as OncoprintVertexTrackBuffer);
|
|
792
1184
|
const col_array = this.vertex_data[track_id].col_array;
|
|
793
|
-
const universal_shapes_start_index = this.vertex_data[track_id]
|
|
1185
|
+
const universal_shapes_start_index = this.vertex_data[track_id]
|
|
1186
|
+
.universal_shapes_start_index;
|
|
794
1187
|
|
|
795
1188
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, col_buffer);
|
|
796
|
-
this.ctx.bufferData(
|
|
1189
|
+
this.ctx.bufferData(
|
|
1190
|
+
this.ctx.ARRAY_BUFFER,
|
|
1191
|
+
col_array,
|
|
1192
|
+
this.ctx.STATIC_DRAW
|
|
1193
|
+
);
|
|
797
1194
|
col_buffer.itemSize = 1;
|
|
798
|
-
col_buffer.specificShapesNumItems =
|
|
799
|
-
|
|
1195
|
+
col_buffer.specificShapesNumItems =
|
|
1196
|
+
universal_shapes_start_index / col_buffer.itemSize;
|
|
1197
|
+
col_buffer.universalShapesNumItems =
|
|
1198
|
+
(col_array.length - universal_shapes_start_index) /
|
|
1199
|
+
col_buffer.itemSize;
|
|
800
1200
|
|
|
801
1201
|
this.vertex_color_buffer[track_id] = col_buffer;
|
|
802
1202
|
}
|
|
803
1203
|
|
|
804
1204
|
if (this.is_buffer_empty[track_id].color_texture) {
|
|
805
|
-
const tex = this.color_texture[track_id]
|
|
1205
|
+
const tex = this.color_texture[track_id]
|
|
1206
|
+
? this.color_texture[track_id].texture
|
|
1207
|
+
: this.ctx.createTexture();
|
|
806
1208
|
this.ctx.bindTexture(this.ctx.TEXTURE_2D, tex);
|
|
807
1209
|
|
|
808
1210
|
const color_bank = this.vertex_data[track_id].col_bank;
|
|
809
|
-
const width = Math.pow(
|
|
810
|
-
|
|
1211
|
+
const width = Math.pow(
|
|
1212
|
+
2,
|
|
1213
|
+
Math.ceil((Math as any).log2(color_bank.length / 4))
|
|
1214
|
+
);
|
|
1215
|
+
while (color_bank.length < 4 * width) {
|
|
811
1216
|
color_bank.push(0);
|
|
812
1217
|
}
|
|
813
1218
|
const height = 1;
|
|
814
|
-
this.ctx.texImage2D(
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
1219
|
+
this.ctx.texImage2D(
|
|
1220
|
+
this.ctx.TEXTURE_2D,
|
|
1221
|
+
0,
|
|
1222
|
+
this.ctx.RGBA,
|
|
1223
|
+
width,
|
|
1224
|
+
height,
|
|
1225
|
+
0,
|
|
1226
|
+
this.ctx.RGBA,
|
|
1227
|
+
this.ctx.UNSIGNED_BYTE,
|
|
1228
|
+
new Uint8Array(color_bank)
|
|
1229
|
+
);
|
|
1230
|
+
this.ctx.texParameteri(
|
|
1231
|
+
this.ctx.TEXTURE_2D,
|
|
1232
|
+
this.ctx.TEXTURE_MIN_FILTER,
|
|
1233
|
+
this.ctx.NEAREST
|
|
1234
|
+
);
|
|
1235
|
+
this.ctx.texParameteri(
|
|
1236
|
+
this.ctx.TEXTURE_2D,
|
|
1237
|
+
this.ctx.TEXTURE_MAG_FILTER,
|
|
1238
|
+
this.ctx.NEAREST
|
|
1239
|
+
);
|
|
1240
|
+
this.color_texture[track_id] = { texture: tex, size: width };
|
|
818
1241
|
}
|
|
819
1242
|
|
|
820
1243
|
if (this.is_buffer_empty[track_id].column) {
|
|
821
|
-
const vertex_column_buffer =
|
|
1244
|
+
const vertex_column_buffer =
|
|
1245
|
+
this.vertex_column_buffer[track_id] ||
|
|
1246
|
+
(this.ctx.createBuffer() as OncoprintTrackBuffer);
|
|
822
1247
|
const vertex_column_array = this.vertex_column_array[track_id];
|
|
823
1248
|
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, vertex_column_buffer);
|
|
824
|
-
this.ctx.bufferData(
|
|
1249
|
+
this.ctx.bufferData(
|
|
1250
|
+
this.ctx.ARRAY_BUFFER,
|
|
1251
|
+
vertex_column_array,
|
|
1252
|
+
this.ctx.STATIC_DRAW
|
|
1253
|
+
);
|
|
825
1254
|
vertex_column_buffer.itemSize = 1;
|
|
826
|
-
vertex_column_buffer.numItems =
|
|
1255
|
+
vertex_column_buffer.numItems =
|
|
1256
|
+
vertex_column_array.length / vertex_column_buffer.itemSize;
|
|
827
1257
|
|
|
828
1258
|
this.vertex_column_buffer[track_id] = vertex_column_buffer;
|
|
829
1259
|
}
|
|
@@ -831,31 +1261,45 @@ export default class OncoprintWebGLCellView {
|
|
|
831
1261
|
position: false,
|
|
832
1262
|
color: false,
|
|
833
1263
|
column: false,
|
|
834
|
-
color_texture: false
|
|
1264
|
+
color_texture: false,
|
|
835
1265
|
};
|
|
836
1266
|
|
|
837
|
-
return {
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
1267
|
+
return {
|
|
1268
|
+
position: this.vertex_position_buffer[track_id],
|
|
1269
|
+
color: this.vertex_color_buffer[track_id],
|
|
1270
|
+
color_tex: this.color_texture[track_id],
|
|
1271
|
+
column: this.vertex_column_buffer[track_id],
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
842
1274
|
|
|
843
|
-
private computeVertexColumns(model:OncoprintModel, track_id:TrackId) {
|
|
1275
|
+
private computeVertexColumns(model: OncoprintModel, track_id: TrackId) {
|
|
844
1276
|
if (this.rendering_suppressed) {
|
|
845
1277
|
return;
|
|
846
1278
|
}
|
|
847
1279
|
const num_items = this.vertex_data[track_id].pos_array.length;
|
|
848
|
-
const id_to_first_vertex_index = this.id_to_first_vertex_index[
|
|
1280
|
+
const id_to_first_vertex_index = this.id_to_first_vertex_index[
|
|
1281
|
+
track_id
|
|
1282
|
+
];
|
|
849
1283
|
const id_to_index = model.getVisibleIdToIndexMap();
|
|
850
|
-
const id_and_first_vertex:[ColumnId, number][] = Object.keys(
|
|
851
|
-
|
|
852
|
-
|
|
1284
|
+
const id_and_first_vertex: [ColumnId, number][] = Object.keys(
|
|
1285
|
+
id_to_first_vertex_index
|
|
1286
|
+
)
|
|
1287
|
+
.map(function(id) {
|
|
1288
|
+
return [id, id_to_first_vertex_index[id]] as [ColumnId, number];
|
|
1289
|
+
})
|
|
1290
|
+
.sort(function(a, b) {
|
|
1291
|
+
return sgndiff(a[1], b[1]);
|
|
1292
|
+
});
|
|
853
1293
|
const vertex_column_array = new Float32Array(num_items);
|
|
854
1294
|
let vertex_index = 0;
|
|
855
|
-
for (let i=0; i<id_and_first_vertex.length; i++) {
|
|
856
|
-
const num_to_add =
|
|
1295
|
+
for (let i = 0; i < id_and_first_vertex.length; i++) {
|
|
1296
|
+
const num_to_add =
|
|
1297
|
+
(i === id_and_first_vertex.length - 1
|
|
1298
|
+
? num_items
|
|
1299
|
+
: id_and_first_vertex[i + 1][1]) -
|
|
1300
|
+
id_and_first_vertex[i][1];
|
|
857
1301
|
const column = id_to_index[id_and_first_vertex[i][0]];
|
|
858
|
-
for (let j=0; j<num_to_add; j++) {
|
|
1302
|
+
for (let j = 0; j < num_to_add; j++) {
|
|
859
1303
|
vertex_column_array[vertex_index] = column;
|
|
860
1304
|
vertex_index += 1;
|
|
861
1305
|
}
|
|
@@ -864,7 +1308,10 @@ export default class OncoprintWebGLCellView {
|
|
|
864
1308
|
this.clearTrackColumnBuffers(model, track_id);
|
|
865
1309
|
}
|
|
866
1310
|
|
|
867
|
-
private computeVertexPositionsAndVertexColors(
|
|
1311
|
+
private computeVertexPositionsAndVertexColors(
|
|
1312
|
+
model: OncoprintModel,
|
|
1313
|
+
track_id: TrackId
|
|
1314
|
+
) {
|
|
868
1315
|
if (this.rendering_suppressed) {
|
|
869
1316
|
return;
|
|
870
1317
|
}
|
|
@@ -874,44 +1321,62 @@ export default class OncoprintWebGLCellView {
|
|
|
874
1321
|
|
|
875
1322
|
const universal_shapes = this.universal_shapes[track_id];
|
|
876
1323
|
const id_to_index = model.getIdToIndexMap();
|
|
877
|
-
const specific_shapes = _.sortBy(
|
|
1324
|
+
const specific_shapes = _.sortBy(
|
|
1325
|
+
this.specific_shapes[track_id],
|
|
1326
|
+
o => id_to_index[o.id]
|
|
1327
|
+
);
|
|
878
1328
|
// Compute vertex array
|
|
879
|
-
const num_vertexes =
|
|
880
|
-
|
|
881
|
-
|
|
1329
|
+
const num_vertexes =
|
|
1330
|
+
_.sumBy(specific_shapes, (shapeList: IdentifiedShapeList) => {
|
|
1331
|
+
return _.sumBy(shapeList.shape_list, getNumWebGLVertexes);
|
|
1332
|
+
}) +
|
|
1333
|
+
(universal_shapes
|
|
1334
|
+
? _.sumBy(universal_shapes, getNumWebGLVertexes)
|
|
1335
|
+
: 0);
|
|
882
1336
|
const vertex_pos_array = new Float32Array(num_vertexes);
|
|
883
1337
|
const vertex_col_array = new Float32Array(num_vertexes);
|
|
884
1338
|
|
|
885
1339
|
// original values dont mean anything but its faster to create an object with all the keys
|
|
886
1340
|
// already in it than to slowly grow it
|
|
887
|
-
const id_to_first_vertex_index:{
|
|
1341
|
+
const id_to_first_vertex_index: {
|
|
1342
|
+
[columnId: string]: number;
|
|
1343
|
+
} = _.clone(id_to_index);
|
|
888
1344
|
|
|
889
|
-
const color_vertexes:ColorVertex[] = [];
|
|
890
|
-
const color_bank_index:{[colorHash:string]:ColorBankIndex} = {};
|
|
1345
|
+
const color_vertexes: ColorVertex[] = [];
|
|
1346
|
+
const color_bank_index: { [colorHash: string]: ColorBankIndex } = {};
|
|
891
1347
|
|
|
892
1348
|
const position_bit_pack_base = this.position_bit_pack_base;
|
|
893
|
-
function packPos(posVertex:number[]) {
|
|
1349
|
+
function packPos(posVertex: number[]) {
|
|
894
1350
|
// values must be in [0,255] (integer)
|
|
895
|
-
return
|
|
1351
|
+
return (
|
|
1352
|
+
position_bit_pack_base * position_bit_pack_base * posVertex[0] +
|
|
1353
|
+
position_bit_pack_base * posVertex[1] +
|
|
1354
|
+
posVertex[2]
|
|
1355
|
+
);
|
|
896
1356
|
}
|
|
897
1357
|
|
|
898
|
-
const vertexifiedShapes:
|
|
1358
|
+
const vertexifiedShapes: {
|
|
1359
|
+
[shapeHash: string]: { position: number[]; color: number[] };
|
|
1360
|
+
} = {};
|
|
899
1361
|
let vertex_array_index = 0;
|
|
900
1362
|
|
|
901
|
-
function addShapeVertexes(_shape:ComputedShapeParams, zindex:number) {
|
|
1363
|
+
function addShapeVertexes(_shape: ComputedShapeParams, zindex: number) {
|
|
902
1364
|
const hash = Shape.hashComputedShape(_shape, zindex);
|
|
903
1365
|
if (!(hash in vertexifiedShapes)) {
|
|
904
|
-
vertexifiedShapes[hash] = {position:[], color:[]};
|
|
1366
|
+
vertexifiedShapes[hash] = { position: [], color: [] };
|
|
905
1367
|
const position = vertexifiedShapes[hash].position;
|
|
906
1368
|
const color = vertexifiedShapes[hash].color;
|
|
907
|
-
shapeToVertexes(_shape, zindex, function(
|
|
1369
|
+
shapeToVertexes(_shape, zindex, function(
|
|
1370
|
+
pos: PositionVertex,
|
|
1371
|
+
col: ColorVertex
|
|
1372
|
+
) {
|
|
908
1373
|
pos = pos.map(Math.round) as PositionVertex;
|
|
909
1374
|
|
|
910
1375
|
position.push(packPos(pos));
|
|
911
1376
|
|
|
912
1377
|
const col_hash = `${col[0]},${col[1]},${col[2]},${col[3]}`;
|
|
913
1378
|
let col_index = color_bank_index[col_hash];
|
|
914
|
-
if (typeof col_index ===
|
|
1379
|
+
if (typeof col_index === 'undefined') {
|
|
915
1380
|
col_index = color_vertexes.length;
|
|
916
1381
|
color_vertexes.push(col);
|
|
917
1382
|
color_bank_index[col_hash] = col_index;
|
|
@@ -921,7 +1386,7 @@ export default class OncoprintWebGLCellView {
|
|
|
921
1386
|
}
|
|
922
1387
|
const positionVertexes = vertexifiedShapes[hash].position;
|
|
923
1388
|
const colorVertexes = vertexifiedShapes[hash].color;
|
|
924
|
-
for (let i=0; i<positionVertexes.length; i++) {
|
|
1389
|
+
for (let i = 0; i < positionVertexes.length; i++) {
|
|
925
1390
|
vertex_pos_array[vertex_array_index] = positionVertexes[i];
|
|
926
1391
|
vertex_col_array[vertex_array_index] = colorVertexes[i];
|
|
927
1392
|
vertex_array_index += 1;
|
|
@@ -949,31 +1414,43 @@ export default class OncoprintWebGLCellView {
|
|
|
949
1414
|
}
|
|
950
1415
|
}
|
|
951
1416
|
|
|
952
|
-
const color_bank:ColorBank = color_vertexes.reduce(function(
|
|
1417
|
+
const color_bank: ColorBank = color_vertexes.reduce(function(
|
|
1418
|
+
arr,
|
|
1419
|
+
next
|
|
1420
|
+
) {
|
|
1421
|
+
return arr.concat(next);
|
|
1422
|
+
},
|
|
1423
|
+
[]);
|
|
953
1424
|
// minimum color bank to avoid webGL texture errors
|
|
954
1425
|
if (color_bank.length === 0) {
|
|
955
|
-
color_bank.push(0,0,0,0);
|
|
1426
|
+
color_bank.push(0, 0, 0, 0);
|
|
956
1427
|
}
|
|
957
1428
|
this.vertex_data[track_id] = {
|
|
958
1429
|
pos_array: vertex_pos_array,
|
|
959
1430
|
col_array: vertex_col_array,
|
|
960
1431
|
col_bank: color_bank,
|
|
961
|
-
universal_shapes_start_index
|
|
1432
|
+
universal_shapes_start_index,
|
|
962
1433
|
};
|
|
963
1434
|
this.id_to_first_vertex_index[track_id] = id_to_first_vertex_index;
|
|
964
1435
|
|
|
965
1436
|
this.clearTrackPositionAndColorBuffers(model, track_id);
|
|
966
1437
|
}
|
|
967
1438
|
|
|
968
|
-
private getShapes(model:OncoprintModel, track_id:TrackId) {
|
|
1439
|
+
private getShapes(model: OncoprintModel, track_id: TrackId) {
|
|
969
1440
|
if (this.rendering_suppressed) {
|
|
970
1441
|
return;
|
|
971
1442
|
}
|
|
972
|
-
this.specific_shapes[track_id] = model.getSpecificShapesForData(
|
|
973
|
-
|
|
1443
|
+
this.specific_shapes[track_id] = model.getSpecificShapesForData(
|
|
1444
|
+
track_id,
|
|
1445
|
+
true
|
|
1446
|
+
);
|
|
1447
|
+
this.universal_shapes[track_id] = model.getTrackUniversalShapes(
|
|
1448
|
+
track_id,
|
|
1449
|
+
true
|
|
1450
|
+
);
|
|
974
1451
|
}
|
|
975
1452
|
|
|
976
|
-
private refreshCanvas(model:OncoprintModel) {
|
|
1453
|
+
private refreshCanvas(model: OncoprintModel) {
|
|
977
1454
|
// whenever you get a new context, you have to get new buffers
|
|
978
1455
|
this.deleteBuffers(model);
|
|
979
1456
|
this.deleteSimpleCountBuffer(model);
|
|
@@ -983,28 +1460,36 @@ export default class OncoprintWebGLCellView {
|
|
|
983
1460
|
this.ensureSimpleCountBuffer(model);
|
|
984
1461
|
}
|
|
985
1462
|
|
|
986
|
-
private highlightCell(
|
|
1463
|
+
private highlightCell(
|
|
1464
|
+
model: OncoprintModel,
|
|
1465
|
+
track_id: TrackId,
|
|
1466
|
+
uid: ColumnId
|
|
1467
|
+
) {
|
|
987
1468
|
this.overlayStrokeRect(
|
|
988
1469
|
model.getZoomedColumnLeft(uid) - this.scroll_x,
|
|
989
1470
|
model.getCellTops(track_id) - this.scroll_y,
|
|
990
|
-
model.getCellWidth() +
|
|
1471
|
+
model.getCellWidth() +
|
|
1472
|
+
(model.getTrackHasColumnSpacing(track_id)
|
|
1473
|
+
? 0
|
|
1474
|
+
: model.getCellPadding()),
|
|
991
1475
|
model.getCellHeight(track_id),
|
|
992
|
-
|
|
1476
|
+
'rgba(0,0,0,1)'
|
|
993
1477
|
);
|
|
994
1478
|
}
|
|
995
1479
|
|
|
996
|
-
private highlightTrack(model:OncoprintModel, track_id:TrackId) {
|
|
997
|
-
const highlight_width =
|
|
1480
|
+
private highlightTrack(model: OncoprintModel, track_id: TrackId) {
|
|
1481
|
+
const highlight_width =
|
|
1482
|
+
model.getCellWidth() +
|
|
1483
|
+
(model.getTrackHasColumnSpacing(track_id)
|
|
1484
|
+
? 0
|
|
1485
|
+
: model.getCellPadding());
|
|
998
1486
|
const cell_height = model.getCellHeight(track_id);
|
|
999
1487
|
const uids = model.getIdOrder();
|
|
1000
1488
|
const left = model.getZoomedColumnLeft();
|
|
1001
1489
|
const top = model.getCellTops(track_id) - this.scroll_y;
|
|
1002
1490
|
|
|
1003
1491
|
for (const uid of uids) {
|
|
1004
|
-
if (
|
|
1005
|
-
model.getTrackDatum(track_id, uid) !== null &&
|
|
1006
|
-
(uid in left)
|
|
1007
|
-
) {
|
|
1492
|
+
if (model.getTrackDatum(track_id, uid) !== null && uid in left) {
|
|
1008
1493
|
this.overlayStrokeRect(
|
|
1009
1494
|
left[uid] - this.scroll_x,
|
|
1010
1495
|
top,
|
|
@@ -1016,17 +1501,20 @@ export default class OncoprintWebGLCellView {
|
|
|
1016
1501
|
}
|
|
1017
1502
|
}
|
|
1018
1503
|
|
|
1019
|
-
private highlightColumn(model:OncoprintModel, uid:ColumnId) {
|
|
1504
|
+
private highlightColumn(model: OncoprintModel, uid: ColumnId) {
|
|
1020
1505
|
const left = model.getZoomedColumnLeft(uid) - this.scroll_x;
|
|
1021
1506
|
const cell_padding = model.getCellPadding();
|
|
1022
1507
|
const cell_width = model.getCellWidth();
|
|
1023
1508
|
const tracks = model.getTracks();
|
|
1024
|
-
for (let i=0; i<tracks.length; i++) {
|
|
1509
|
+
for (let i = 0; i < tracks.length; i++) {
|
|
1025
1510
|
if (model.getTrackDatum(tracks[i], uid) !== null) {
|
|
1026
1511
|
this.overlayStrokeRect(
|
|
1027
1512
|
left,
|
|
1028
1513
|
model.getCellTops(tracks[i]) - this.scroll_y,
|
|
1029
|
-
cell_width +
|
|
1514
|
+
cell_width +
|
|
1515
|
+
(model.getTrackHasColumnSpacing(tracks[i])
|
|
1516
|
+
? 0
|
|
1517
|
+
: cell_padding),
|
|
1030
1518
|
model.getCellHeight(tracks[i]),
|
|
1031
1519
|
CELL_HIGHLIGHT_STROKE
|
|
1032
1520
|
);
|
|
@@ -1035,28 +1523,39 @@ export default class OncoprintWebGLCellView {
|
|
|
1035
1523
|
this.overlayColumnLabelHighlight(model, uid);
|
|
1036
1524
|
}
|
|
1037
1525
|
|
|
1038
|
-
public getViewportOncoprintSpace(model:OncoprintModel) {
|
|
1526
|
+
public getViewportOncoprintSpace(model: OncoprintModel) {
|
|
1039
1527
|
const scroll_y = this.scroll_y;
|
|
1040
1528
|
const zoom_y = model.getVertZoom();
|
|
1041
1529
|
|
|
1042
1530
|
const id_order = model.getIdOrder();
|
|
1043
|
-
const left_index = model.getClosestColumnIndexToLeft(
|
|
1531
|
+
const left_index = model.getClosestColumnIndexToLeft(
|
|
1532
|
+
this.scroll_x,
|
|
1533
|
+
true
|
|
1534
|
+
);
|
|
1044
1535
|
const left_id = id_order[left_index];
|
|
1045
|
-
const right_index = model.getClosestColumnIndexToLeft(
|
|
1536
|
+
const right_index = model.getClosestColumnIndexToLeft(
|
|
1537
|
+
this.scroll_x + this.visible_area_width,
|
|
1538
|
+
true,
|
|
1539
|
+
true
|
|
1540
|
+
);
|
|
1046
1541
|
|
|
1047
1542
|
let right;
|
|
1048
1543
|
if (right_index < id_order.length) {
|
|
1049
1544
|
right = model.getColumnLeft(id_order[right_index]);
|
|
1050
1545
|
} else {
|
|
1051
|
-
right =
|
|
1546
|
+
right =
|
|
1547
|
+
model.getColumnLeft(id_order[id_order.length - 1]) +
|
|
1548
|
+
model.getCellWidth(true);
|
|
1052
1549
|
}
|
|
1053
1550
|
|
|
1054
1551
|
return {
|
|
1055
1552
|
top: Math.round(scroll_y / zoom_y),
|
|
1056
|
-
bottom: Math.round(
|
|
1553
|
+
bottom: Math.round(
|
|
1554
|
+
(scroll_y + this.getVisibleAreaHeight(model)) / zoom_y
|
|
1555
|
+
),
|
|
1057
1556
|
left: model.getColumnLeft(left_id),
|
|
1058
1557
|
right,
|
|
1059
|
-
center_col_index: Math.floor((right_index + left_index) / 2)
|
|
1558
|
+
center_col_index: Math.floor((right_index + left_index) / 2),
|
|
1060
1559
|
};
|
|
1061
1560
|
}
|
|
1062
1561
|
|
|
@@ -1064,7 +1563,7 @@ export default class OncoprintWebGLCellView {
|
|
|
1064
1563
|
return this.ctx !== null;
|
|
1065
1564
|
}
|
|
1066
1565
|
|
|
1067
|
-
public removeTrack(model:OncoprintModel, track_id:TrackId) {
|
|
1566
|
+
public removeTrack(model: OncoprintModel, track_id: TrackId) {
|
|
1068
1567
|
this.deleteBuffers(model, track_id);
|
|
1069
1568
|
|
|
1070
1569
|
delete this.specific_shapes[track_id];
|
|
@@ -1079,19 +1578,19 @@ export default class OncoprintWebGLCellView {
|
|
|
1079
1578
|
}
|
|
1080
1579
|
}
|
|
1081
1580
|
|
|
1082
|
-
public moveTrack(model:OncoprintModel) {
|
|
1581
|
+
public moveTrack(model: OncoprintModel) {
|
|
1083
1582
|
if (!this.rendering_suppressed) {
|
|
1084
1583
|
this.renderAllTracks(model);
|
|
1085
1584
|
}
|
|
1086
1585
|
}
|
|
1087
1586
|
|
|
1088
|
-
public setTrackGroupOrder(model:OncoprintModel) {
|
|
1587
|
+
public setTrackGroupOrder(model: OncoprintModel) {
|
|
1089
1588
|
if (!this.rendering_suppressed) {
|
|
1090
1589
|
this.renderAllTracks(model);
|
|
1091
1590
|
}
|
|
1092
1591
|
}
|
|
1093
1592
|
|
|
1094
|
-
public setTrackShowGaps(model:OncoprintModel) {
|
|
1593
|
+
public setTrackShowGaps(model: OncoprintModel) {
|
|
1095
1594
|
if (!this.rendering_suppressed) {
|
|
1096
1595
|
// shader depends on gaps
|
|
1097
1596
|
this.setUpShaders(model);
|
|
@@ -1099,45 +1598,45 @@ export default class OncoprintWebGLCellView {
|
|
|
1099
1598
|
}
|
|
1100
1599
|
}
|
|
1101
1600
|
|
|
1102
|
-
public setColumnLabels(model:OncoprintModel) {
|
|
1601
|
+
public setColumnLabels(model: OncoprintModel) {
|
|
1103
1602
|
if (!this.rendering_suppressed) {
|
|
1104
1603
|
this.renderAllTracks(model);
|
|
1105
1604
|
}
|
|
1106
1605
|
}
|
|
1107
1606
|
|
|
1108
|
-
public addTracks(model:OncoprintModel, track_ids:TrackId[]) {
|
|
1607
|
+
public addTracks(model: OncoprintModel, track_ids: TrackId[]) {
|
|
1109
1608
|
if (this.rendering_suppressed) {
|
|
1110
1609
|
return;
|
|
1111
1610
|
}
|
|
1112
|
-
for (let i=0; i<track_ids.length; i++) {
|
|
1611
|
+
for (let i = 0; i < track_ids.length; i++) {
|
|
1113
1612
|
this.getShapes(model, track_ids[i]);
|
|
1114
1613
|
this.computeVertexPositionsAndVertexColors(model, track_ids[i]);
|
|
1115
1614
|
this.computeVertexColumns(model, track_ids[i]);
|
|
1116
1615
|
}
|
|
1117
1616
|
this.renderAllTracks(model);
|
|
1118
1617
|
}
|
|
1119
|
-
public setIdOrder(model:OncoprintModel, ids:ColumnId[]) {
|
|
1618
|
+
public setIdOrder(model: OncoprintModel, ids: ColumnId[]) {
|
|
1120
1619
|
if (this.rendering_suppressed) {
|
|
1121
1620
|
return;
|
|
1122
1621
|
}
|
|
1123
1622
|
const track_ids = model.getTracks();
|
|
1124
|
-
for (let i=0; i<track_ids.length; i++) {
|
|
1623
|
+
for (let i = 0; i < track_ids.length; i++) {
|
|
1125
1624
|
this.computeVertexColumns(model, track_ids[i]);
|
|
1126
1625
|
}
|
|
1127
1626
|
this.renderAllTracks(model);
|
|
1128
1627
|
}
|
|
1129
|
-
public setTrackGroupSortPriority(model:OncoprintModel) {
|
|
1628
|
+
public setTrackGroupSortPriority(model: OncoprintModel) {
|
|
1130
1629
|
if (this.rendering_suppressed) {
|
|
1131
1630
|
return;
|
|
1132
1631
|
}
|
|
1133
1632
|
this.renderAllTracks(model);
|
|
1134
1633
|
}
|
|
1135
|
-
public sort(model:OncoprintModel) {
|
|
1634
|
+
public sort(model: OncoprintModel) {
|
|
1136
1635
|
if (this.rendering_suppressed) {
|
|
1137
1636
|
return;
|
|
1138
1637
|
}
|
|
1139
1638
|
const track_ids = model.getTracks();
|
|
1140
|
-
for (let i=0; i<track_ids.length; i++) {
|
|
1639
|
+
for (let i = 0; i < track_ids.length; i++) {
|
|
1141
1640
|
this.computeVertexPositionsAndVertexColors(model, track_ids[i]); // need to recompute because the vertexes are in sorted order for clipping
|
|
1142
1641
|
this.computeVertexColumns(model, track_ids[i]);
|
|
1143
1642
|
}
|
|
@@ -1146,11 +1645,11 @@ export default class OncoprintWebGLCellView {
|
|
|
1146
1645
|
public suppressRendering() {
|
|
1147
1646
|
this.rendering_suppressed = true;
|
|
1148
1647
|
}
|
|
1149
|
-
public releaseRendering(model:OncoprintModel) {
|
|
1648
|
+
public releaseRendering(model: OncoprintModel) {
|
|
1150
1649
|
this.rendering_suppressed = false;
|
|
1151
1650
|
this.updateAntialiasSetting(model);
|
|
1152
1651
|
const track_ids = model.getTracks();
|
|
1153
|
-
for (let i=0; i<track_ids.length; i++) {
|
|
1652
|
+
for (let i = 0; i < track_ids.length; i++) {
|
|
1154
1653
|
this.getShapes(model, track_ids[i]);
|
|
1155
1654
|
this.computeVertexPositionsAndVertexColors(model, track_ids[i]);
|
|
1156
1655
|
this.computeVertexColumns(model, track_ids[i]);
|
|
@@ -1158,17 +1657,17 @@ export default class OncoprintWebGLCellView {
|
|
|
1158
1657
|
this.setUpShaders(model); // due to possible changes in gaps
|
|
1159
1658
|
this.renderAllTracks(model);
|
|
1160
1659
|
}
|
|
1161
|
-
public hideIds(model:OncoprintModel) {
|
|
1660
|
+
public hideIds(model: OncoprintModel) {
|
|
1162
1661
|
if (this.rendering_suppressed) {
|
|
1163
1662
|
return;
|
|
1164
1663
|
}
|
|
1165
1664
|
const track_ids = model.getTracks();
|
|
1166
|
-
for (let i=0; i<track_ids.length; i++) {
|
|
1665
|
+
for (let i = 0; i < track_ids.length; i++) {
|
|
1167
1666
|
this.computeVertexColumns(model, track_ids[i]);
|
|
1168
1667
|
}
|
|
1169
1668
|
this.renderAllTracks(model);
|
|
1170
1669
|
}
|
|
1171
|
-
public setTrackImportantIds(model:OncoprintModel, track_id:TrackId) {
|
|
1670
|
+
public setTrackImportantIds(model: OncoprintModel, track_id: TrackId) {
|
|
1172
1671
|
if (this.rendering_suppressed) {
|
|
1173
1672
|
return;
|
|
1174
1673
|
}
|
|
@@ -1177,7 +1676,7 @@ export default class OncoprintWebGLCellView {
|
|
|
1177
1676
|
this.computeVertexColumns(model, track_id);
|
|
1178
1677
|
this.renderAllTracks(model);
|
|
1179
1678
|
}
|
|
1180
|
-
public setTrackData(model:OncoprintModel, track_id:TrackId) {
|
|
1679
|
+
public setTrackData(model: OncoprintModel, track_id: TrackId) {
|
|
1181
1680
|
if (this.rendering_suppressed) {
|
|
1182
1681
|
return;
|
|
1183
1682
|
}
|
|
@@ -1186,7 +1685,7 @@ export default class OncoprintWebGLCellView {
|
|
|
1186
1685
|
this.computeVertexColumns(model, track_id);
|
|
1187
1686
|
this.renderAllTracks(model);
|
|
1188
1687
|
}
|
|
1189
|
-
public setRuleSet(model:OncoprintModel, target_track_id:TrackId) {
|
|
1688
|
+
public setRuleSet(model: OncoprintModel, target_track_id: TrackId) {
|
|
1190
1689
|
if (this.rendering_suppressed) {
|
|
1191
1690
|
return;
|
|
1192
1691
|
}
|
|
@@ -1194,7 +1693,7 @@ export default class OncoprintWebGLCellView {
|
|
|
1194
1693
|
this.computeVertexPositionsAndVertexColors(model, target_track_id);
|
|
1195
1694
|
this.renderAllTracks(model);
|
|
1196
1695
|
}
|
|
1197
|
-
public shareRuleSet(model:OncoprintModel, target_track_id:TrackId) {
|
|
1696
|
+
public shareRuleSet(model: OncoprintModel, target_track_id: TrackId) {
|
|
1198
1697
|
if (this.rendering_suppressed) {
|
|
1199
1698
|
return;
|
|
1200
1699
|
}
|
|
@@ -1202,22 +1701,22 @@ export default class OncoprintWebGLCellView {
|
|
|
1202
1701
|
this.computeVertexPositionsAndVertexColors(model, target_track_id);
|
|
1203
1702
|
this.renderAllTracks(model);
|
|
1204
1703
|
}
|
|
1205
|
-
public setSortConfig(model:OncoprintModel) {
|
|
1704
|
+
public setSortConfig(model: OncoprintModel) {
|
|
1206
1705
|
if (this.rendering_suppressed) {
|
|
1207
1706
|
return;
|
|
1208
1707
|
}
|
|
1209
1708
|
this.sort(model);
|
|
1210
1709
|
}
|
|
1211
1710
|
|
|
1212
|
-
public setHorzScroll(model:OncoprintModel) {
|
|
1711
|
+
public setHorzScroll(model: OncoprintModel) {
|
|
1213
1712
|
this.setScroll(model);
|
|
1214
1713
|
}
|
|
1215
1714
|
|
|
1216
|
-
public setVertScroll(model:OncoprintModel) {
|
|
1715
|
+
public setVertScroll(model: OncoprintModel) {
|
|
1217
1716
|
this.setScroll(model);
|
|
1218
1717
|
}
|
|
1219
1718
|
|
|
1220
|
-
public setScroll(model:OncoprintModel) {
|
|
1719
|
+
public setScroll(model: OncoprintModel) {
|
|
1221
1720
|
this.scroll_x = model.getHorzScroll();
|
|
1222
1721
|
this.scroll_y = model.getVertScroll();
|
|
1223
1722
|
if (!this.rendering_suppressed) {
|
|
@@ -1225,7 +1724,7 @@ export default class OncoprintWebGLCellView {
|
|
|
1225
1724
|
}
|
|
1226
1725
|
}
|
|
1227
1726
|
|
|
1228
|
-
private updateAntialiasSetting(model:OncoprintModel) {
|
|
1727
|
+
private updateAntialiasSetting(model: OncoprintModel) {
|
|
1229
1728
|
const cell_width = model.getCellWidth();
|
|
1230
1729
|
if (cell_width < this.antialias_on_cell_width_thresh) {
|
|
1231
1730
|
if (!this.antialias) {
|
|
@@ -1238,37 +1737,37 @@ export default class OncoprintWebGLCellView {
|
|
|
1238
1737
|
this.refreshCanvas(model);
|
|
1239
1738
|
}
|
|
1240
1739
|
}
|
|
1241
|
-
}
|
|
1740
|
+
}
|
|
1242
1741
|
|
|
1243
|
-
public setZoom(model:OncoprintModel) {
|
|
1742
|
+
public setZoom(model: OncoprintModel) {
|
|
1244
1743
|
if (!this.rendering_suppressed) {
|
|
1245
1744
|
this.updateAntialiasSetting(model);
|
|
1246
1745
|
this.renderAllTracks(model);
|
|
1247
1746
|
}
|
|
1248
1747
|
}
|
|
1249
1748
|
|
|
1250
|
-
public setHorzZoom(model:OncoprintModel) {
|
|
1749
|
+
public setHorzZoom(model: OncoprintModel) {
|
|
1251
1750
|
if (!this.rendering_suppressed) {
|
|
1252
1751
|
this.updateAntialiasSetting(model);
|
|
1253
1752
|
this.renderAllTracks(model);
|
|
1254
1753
|
}
|
|
1255
1754
|
}
|
|
1256
1755
|
|
|
1257
|
-
public setVertZoom(model:OncoprintModel) {
|
|
1756
|
+
public setVertZoom(model: OncoprintModel) {
|
|
1258
1757
|
if (this.rendering_suppressed) {
|
|
1259
1758
|
return;
|
|
1260
1759
|
}
|
|
1261
1760
|
this.renderAllTracks(model);
|
|
1262
1761
|
}
|
|
1263
1762
|
|
|
1264
|
-
public setTrackGroupHeader(model:OncoprintModel) {
|
|
1763
|
+
public setTrackGroupHeader(model: OncoprintModel) {
|
|
1265
1764
|
if (this.rendering_suppressed) {
|
|
1266
1765
|
return;
|
|
1267
1766
|
}
|
|
1268
1767
|
this.renderAllTracks(model);
|
|
1269
1768
|
}
|
|
1270
1769
|
|
|
1271
|
-
public setViewport(model:OncoprintModel) {
|
|
1770
|
+
public setViewport(model: OncoprintModel) {
|
|
1272
1771
|
this.scroll_x = model.getHorzScroll();
|
|
1273
1772
|
this.scroll_y = model.getVertScroll();
|
|
1274
1773
|
if (!this.rendering_suppressed) {
|
|
@@ -1277,7 +1776,7 @@ export default class OncoprintWebGLCellView {
|
|
|
1277
1776
|
}
|
|
1278
1777
|
}
|
|
1279
1778
|
|
|
1280
|
-
public getTotalWidth(model:OncoprintModel, base?:boolean) {
|
|
1779
|
+
public getTotalWidth(model: OncoprintModel, base?: boolean) {
|
|
1281
1780
|
let width = model.getOncoprintWidth(base);
|
|
1282
1781
|
|
|
1283
1782
|
if (this.maximum_column_label_width > 0) {
|
|
@@ -1291,7 +1790,7 @@ export default class OncoprintWebGLCellView {
|
|
|
1291
1790
|
return this.visible_area_width;
|
|
1292
1791
|
}
|
|
1293
1792
|
|
|
1294
|
-
public setWidth(w:number, model:OncoprintModel) {
|
|
1793
|
+
public setWidth(w: number, model: OncoprintModel) {
|
|
1295
1794
|
this.visible_area_width = w;
|
|
1296
1795
|
if (this.rendering_suppressed) {
|
|
1297
1796
|
return;
|
|
@@ -1308,22 +1807,25 @@ export default class OncoprintWebGLCellView {
|
|
|
1308
1807
|
}
|
|
1309
1808
|
|
|
1310
1809
|
return height;
|
|
1311
|
-
}
|
|
1810
|
+
}
|
|
1312
1811
|
|
|
1313
|
-
public getTotalHeight(model:OncoprintModel) {
|
|
1812
|
+
public getTotalHeight(model: OncoprintModel) {
|
|
1314
1813
|
return model.getOncoprintHeight() + this.getColumnLabelsHeight();
|
|
1315
1814
|
}
|
|
1316
1815
|
|
|
1317
|
-
public getVisibleAreaHeight(model:OncoprintModel) {
|
|
1318
|
-
return
|
|
1816
|
+
public getVisibleAreaHeight(model: OncoprintModel) {
|
|
1817
|
+
return (
|
|
1818
|
+
Math.min(model.getOncoprintHeight(), model.max_height) +
|
|
1819
|
+
this.getColumnLabelsHeight()
|
|
1820
|
+
);
|
|
1319
1821
|
}
|
|
1320
1822
|
|
|
1321
|
-
public setCellPaddingOn(model:OncoprintModel) {
|
|
1823
|
+
public setCellPaddingOn(model: OncoprintModel) {
|
|
1322
1824
|
if (this.rendering_suppressed) {
|
|
1323
1825
|
return;
|
|
1324
1826
|
}
|
|
1325
1827
|
const track_ids = model.getTracks();
|
|
1326
|
-
for (let i=0; i<track_ids.length; i++) {
|
|
1828
|
+
for (let i = 0; i < track_ids.length; i++) {
|
|
1327
1829
|
if (!model.getTrackHasColumnSpacing(track_ids[i])) {
|
|
1328
1830
|
// We need to recompute shapes for tracks that don't have column spacing,
|
|
1329
1831
|
// because for those we're redefining the base width for shape generation.
|
|
@@ -1335,32 +1837,38 @@ export default class OncoprintWebGLCellView {
|
|
|
1335
1837
|
this.renderAllTracks(model);
|
|
1336
1838
|
}
|
|
1337
1839
|
|
|
1338
|
-
public setHighlightedIds(model:OncoprintModel) {
|
|
1840
|
+
public setHighlightedIds(model: OncoprintModel) {
|
|
1339
1841
|
this.clearOverlay();
|
|
1340
1842
|
this.highlightHighlightedIds(model);
|
|
1341
1843
|
this.highlightHighlightedTracks(model);
|
|
1342
1844
|
}
|
|
1343
1845
|
|
|
1344
|
-
public setHighlightedTracks(model:OncoprintModel) {
|
|
1846
|
+
public setHighlightedTracks(model: OncoprintModel) {
|
|
1345
1847
|
this.clearOverlay();
|
|
1346
1848
|
this.highlightHighlightedIds(model);
|
|
1347
1849
|
this.highlightHighlightedTracks(model);
|
|
1348
1850
|
}
|
|
1349
1851
|
|
|
1350
|
-
public highlightHighlightedIds(
|
|
1852
|
+
public highlightHighlightedIds(
|
|
1853
|
+
model: OncoprintModel,
|
|
1854
|
+
opt_exclude_ids?: ColumnId[]
|
|
1855
|
+
) {
|
|
1351
1856
|
// Highlight highlighted ids
|
|
1352
1857
|
const highlightedIds = model.getVisibleHighlightedIds();
|
|
1353
|
-
for (let i=0; i<highlightedIds.length; i++) {
|
|
1354
|
-
if (
|
|
1858
|
+
for (let i = 0; i < highlightedIds.length; i++) {
|
|
1859
|
+
if (
|
|
1860
|
+
!opt_exclude_ids ||
|
|
1861
|
+
opt_exclude_ids.indexOf(highlightedIds[i]) === -1
|
|
1862
|
+
) {
|
|
1355
1863
|
this.highlightColumn(model, highlightedIds[i]);
|
|
1356
1864
|
}
|
|
1357
1865
|
}
|
|
1358
1866
|
}
|
|
1359
1867
|
|
|
1360
|
-
public highlightHighlightedTracks(model:OncoprintModel) {
|
|
1868
|
+
public highlightHighlightedTracks(model: OncoprintModel) {
|
|
1361
1869
|
// Highlight highlighted ids
|
|
1362
1870
|
const highlightedTracks = model.getHighlightedTracks();
|
|
1363
|
-
for (let i=0; i<highlightedTracks.length; i++) {
|
|
1871
|
+
for (let i = 0; i < highlightedTracks.length; i++) {
|
|
1364
1872
|
this.highlightTrack(model, highlightedTracks[i]);
|
|
1365
1873
|
}
|
|
1366
1874
|
}
|
|
@@ -1369,18 +1877,28 @@ export default class OncoprintWebGLCellView {
|
|
|
1369
1877
|
return this.dummy_scroll_div_client_size.get();
|
|
1370
1878
|
}
|
|
1371
1879
|
|
|
1372
|
-
public toSVGGroup(
|
|
1373
|
-
|
|
1880
|
+
public toSVGGroup(
|
|
1881
|
+
model: OncoprintModel,
|
|
1882
|
+
offset_x: number,
|
|
1883
|
+
offset_y: number
|
|
1884
|
+
) {
|
|
1885
|
+
const root = svgfactory.group(offset_x || 0, offset_y || 0);
|
|
1374
1886
|
const cell_tops = model.getCellTops();
|
|
1375
1887
|
const tracks = model.getTracks();
|
|
1376
1888
|
const zoomedColumnLeft = model.getZoomedColumnLeft();
|
|
1377
1889
|
// add cell shapes
|
|
1378
|
-
for (let i=0; i<tracks.length; i++) {
|
|
1890
|
+
for (let i = 0; i < tracks.length; i++) {
|
|
1379
1891
|
const track_id = tracks[i];
|
|
1380
1892
|
const offset_y = cell_tops[track_id];
|
|
1381
|
-
const universal_shapes = model.getTrackUniversalShapes(
|
|
1382
|
-
|
|
1383
|
-
|
|
1893
|
+
const universal_shapes = model.getTrackUniversalShapes(
|
|
1894
|
+
track_id,
|
|
1895
|
+
false
|
|
1896
|
+
);
|
|
1897
|
+
const identified_shape_list_list = model.getSpecificShapesForData(
|
|
1898
|
+
track_id,
|
|
1899
|
+
false
|
|
1900
|
+
);
|
|
1901
|
+
for (let j = 0; j < identified_shape_list_list.length; j++) {
|
|
1384
1902
|
const id_sl = identified_shape_list_list[j];
|
|
1385
1903
|
const id = id_sl.id;
|
|
1386
1904
|
const sl = id_sl.shape_list;
|
|
@@ -1391,12 +1909,20 @@ export default class OncoprintWebGLCellView {
|
|
|
1391
1909
|
}
|
|
1392
1910
|
|
|
1393
1911
|
// draw universal shapes first
|
|
1394
|
-
for (let h=0; h<universal_shapes.length; h++) {
|
|
1395
|
-
root.appendChild(
|
|
1912
|
+
for (let h = 0; h < universal_shapes.length; h++) {
|
|
1913
|
+
root.appendChild(
|
|
1914
|
+
svgfactory.fromShape(
|
|
1915
|
+
universal_shapes[h],
|
|
1916
|
+
offset_x,
|
|
1917
|
+
offset_y
|
|
1918
|
+
)
|
|
1919
|
+
);
|
|
1396
1920
|
}
|
|
1397
1921
|
// next draw specific shapes
|
|
1398
|
-
for (let h=0; h<sl.length; h++) {
|
|
1399
|
-
root.appendChild(
|
|
1922
|
+
for (let h = 0; h < sl.length; h++) {
|
|
1923
|
+
root.appendChild(
|
|
1924
|
+
svgfactory.fromShape(sl[h], offset_x, offset_y)
|
|
1925
|
+
);
|
|
1400
1926
|
}
|
|
1401
1927
|
}
|
|
1402
1928
|
}
|
|
@@ -1407,7 +1933,7 @@ export default class OncoprintWebGLCellView {
|
|
|
1407
1933
|
const column_label_y = model.getOncoprintHeight() + 10;
|
|
1408
1934
|
const font_size = OncoprintWebGLCellView.getColumnLabelsFontSize(model);
|
|
1409
1935
|
const cell_width = model.getCellWidth();
|
|
1410
|
-
for (let i=0; i<ids_with_labels.length; i++) {
|
|
1936
|
+
for (let i = 0; i < ids_with_labels.length; i++) {
|
|
1411
1937
|
const id = ids_with_labels[i];
|
|
1412
1938
|
|
|
1413
1939
|
if (!(id in left)) {
|
|
@@ -1417,33 +1943,43 @@ export default class OncoprintWebGLCellView {
|
|
|
1417
1943
|
|
|
1418
1944
|
const label = labels[id];
|
|
1419
1945
|
|
|
1420
|
-
const x = left[id] + cell_width/2;
|
|
1946
|
+
const x = left[id] + cell_width / 2;
|
|
1421
1947
|
if (label.circle_color) {
|
|
1422
1948
|
// add circle
|
|
1423
1949
|
const spec = this.getColumnLabelCircleSpec(model);
|
|
1424
|
-
root.appendChild(
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1950
|
+
root.appendChild(
|
|
1951
|
+
makeSvgElement('ellipse', {
|
|
1952
|
+
cx: x,
|
|
1953
|
+
cy: column_label_y,
|
|
1954
|
+
rx: spec.radius,
|
|
1955
|
+
ry: spec.radius,
|
|
1956
|
+
stroke: 'rgba(0,0,0,0)',
|
|
1957
|
+
fill: label.circle_color,
|
|
1958
|
+
})
|
|
1959
|
+
);
|
|
1432
1960
|
}
|
|
1433
1961
|
|
|
1434
|
-
const text_x =
|
|
1962
|
+
const text_x =
|
|
1963
|
+
x + ((label.left_padding_percent || 0) / 100) * cell_width;
|
|
1435
1964
|
|
|
1436
1965
|
const angle = ifndef(label.angle_in_degrees, COLUMN_LABEL_ANGLE);
|
|
1437
|
-
const textElt = makeSvgElement(
|
|
1438
|
-
x:text_x,
|
|
1439
|
-
y:column_label_y,
|
|
1440
|
-
fill:label.text_color ||
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1966
|
+
const textElt = makeSvgElement('text', {
|
|
1967
|
+
x: text_x,
|
|
1968
|
+
y: column_label_y,
|
|
1969
|
+
fill: label.text_color || '#000000',
|
|
1970
|
+
'font-size': font_size,
|
|
1971
|
+
'font-family': 'Arial',
|
|
1972
|
+
'font-weight': 'normal',
|
|
1973
|
+
'text-anchor': 'start',
|
|
1974
|
+
transform:
|
|
1975
|
+
'rotate(' +
|
|
1976
|
+
angle +
|
|
1977
|
+
',' +
|
|
1978
|
+
text_x +
|
|
1979
|
+
',' +
|
|
1980
|
+
column_label_y +
|
|
1981
|
+
')',
|
|
1982
|
+
'alignment-baseline': 'middle',
|
|
1447
1983
|
});
|
|
1448
1984
|
|
|
1449
1985
|
textElt.textContent = label.text;
|
|
@@ -1455,6 +1991,6 @@ export default class OncoprintWebGLCellView {
|
|
|
1455
1991
|
|
|
1456
1992
|
public destroy() {
|
|
1457
1993
|
this.$overlay_canvas.off(); // clear all handlers so that it can be garbage collected
|
|
1458
|
-
$(document).off(
|
|
1994
|
+
$(document).off('mousemove', this.mouseMoveHandler);
|
|
1459
1995
|
}
|
|
1460
|
-
}
|
|
1996
|
+
}
|