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.
Files changed (100) hide show
  1. package/README.md +34 -0
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.es.js +14746 -0
  4. package/dist/index.es.js.map +1 -0
  5. package/dist/index.js +14760 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/js/CachedProperty.d.ts +10 -10
  8. package/dist/js/binarysearch.d.ts +1 -1
  9. package/dist/js/bucketsort.d.ts +16 -16
  10. package/dist/js/clustering.d.ts +14 -14
  11. package/dist/js/extractrgba.d.ts +4 -4
  12. package/dist/js/haselementsininterval.d.ts +1 -1
  13. package/dist/js/heatmapcolors.d.ts +5 -4
  14. package/dist/js/makesvgelement.d.ts +1 -1
  15. package/dist/js/modelutils.d.ts +7 -7
  16. package/dist/js/oncoprint.d.ts +168 -170
  17. package/dist/js/oncoprintheaderview.d.ts +23 -22
  18. package/dist/js/oncoprintlabelview.d.ts +79 -78
  19. package/dist/js/oncoprintlegendrenderer.d.ts +32 -31
  20. package/dist/js/oncoprintminimapview.d.ts +69 -68
  21. package/dist/js/oncoprintmodel.d.ts +403 -398
  22. package/dist/js/oncoprintruleset.d.ts +176 -177
  23. package/dist/js/oncoprintshape.d.ts +67 -67
  24. package/dist/js/oncoprintshapetosvg.d.ts +2 -2
  25. package/dist/js/oncoprintshapetovertexes.d.ts +5 -5
  26. package/dist/js/oncoprinttooltip.d.ts +23 -22
  27. package/dist/js/oncoprinttrackinfoview.d.ts +40 -39
  28. package/dist/js/oncoprinttrackoptionsview.d.ts +58 -57
  29. package/dist/js/oncoprintwebglcellview.d.ts +168 -167
  30. package/dist/js/oncoprintzoomslider.d.ts +28 -27
  31. package/dist/js/polyfill.d.ts +4 -4
  32. package/dist/js/precomputedcomparator.d.ts +13 -13
  33. package/dist/js/shaders.d.ts +2 -2
  34. package/dist/js/svgfactory.d.ts +24 -23
  35. package/dist/js/utils.d.ts +16 -16
  36. package/dist/js/workers/clustering-worker.d.ts +19 -20
  37. package/dist/test/gradientCategoricalRuleset.spec.d.ts +1 -1
  38. package/dist/test/monolith.spec.d.ts +1 -1
  39. package/jest.config.ts +2 -0
  40. package/package.json +20 -26
  41. package/rollup.config.ts +14 -0
  42. package/rules/geneticrules.ts +344 -305
  43. package/server.js +11 -0
  44. package/src/img/menudots.svg +9 -9
  45. package/src/img/zoomtofit.svg +12 -12
  46. package/src/index.tsx +13 -0
  47. package/src/js/CachedProperty.ts +6 -7
  48. package/src/js/binarysearch.ts +8 -3
  49. package/src/js/bucketsort.ts +89 -47
  50. package/src/js/clustering.ts +22 -10
  51. package/src/js/extractrgba.ts +16 -12
  52. package/src/js/haselementsininterval.ts +8 -4
  53. package/src/js/heatmapcolors.ts +515 -515
  54. package/src/js/main.js +1 -1
  55. package/src/js/makesvgelement.ts +2 -2
  56. package/src/js/modelutils.ts +11 -8
  57. package/src/js/oncoprint.ts +706 -385
  58. package/src/js/oncoprintheaderview.ts +165 -125
  59. package/src/js/oncoprintlabelview.ts +388 -170
  60. package/src/js/oncoprintlegendrenderer.ts +203 -72
  61. package/src/js/oncoprintminimapview.ts +965 -423
  62. package/src/js/oncoprintmodel.ts +905 -532
  63. package/src/js/oncoprintruleset.ts +694 -379
  64. package/src/js/oncoprintshape.ts +240 -97
  65. package/src/js/oncoprintshapetosvg.ts +77 -26
  66. package/src/js/oncoprintshapetovertexes.ts +153 -48
  67. package/src/js/oncoprinttooltip.ts +58 -27
  68. package/src/js/oncoprinttrackinfoview.ts +115 -59
  69. package/src/js/oncoprinttrackoptionsview.ts +354 -187
  70. package/src/js/oncoprintwebglcellview.ts +951 -415
  71. package/src/js/oncoprintzoomslider.ts +172 -107
  72. package/src/js/polyfill.ts +7 -3
  73. package/src/js/precomputedcomparator.ts +133 -50
  74. package/src/js/shaders.ts +2 -4
  75. package/src/js/svgfactory.ts +128 -73
  76. package/src/js/utils.ts +51 -31
  77. package/src/js/workers/clustering-worker.ts +50 -42
  78. package/src/test/gradientCategoricalRuleset.spec.ts +55 -38
  79. package/src/test/monolith.spec.ts +718 -285
  80. package/test/generate_data.py +108 -0
  81. package/test/glyphmap-data.js +1041 -0
  82. package/test/heatmap-data.js +1027 -0
  83. package/test/index.html +21 -0
  84. package/test/oncoprint-glyphmap.js +79 -0
  85. package/test/oncoprint-heatmap.js +123 -0
  86. package/tsconfig.json +4 -10
  87. package/tsconfig.test.json +11 -0
  88. package/.idea/misc.xml +0 -6
  89. package/.idea/modules.xml +0 -8
  90. package/.idea/oncoprintjs.iml +0 -12
  91. package/.idea/vcs.xml +0 -6
  92. package/.idea/workspace.xml +0 -105
  93. package/dist/.gitkeep +0 -0
  94. package/dist/js/minimaputils.d.ts +0 -0
  95. package/dist/oncoprint.bundle.js +0 -44313
  96. package/jest.config.js +0 -12
  97. package/src/js/minimaputils.ts +0 -0
  98. package/typings/custom.d.ts +0 -7
  99. package/typings/missing.d.ts +0 -7
  100. 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, {getNumWebGLVertexes} from './oncoprintshapetovertexes';
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, ColumnLabel,
11
+ ColumnId,
12
+ ColumnLabel,
10
13
  ColumnProp,
11
14
  IdentifiedShapeList,
12
15
  TrackId,
13
16
  TrackOverlappingCells,
14
- TrackProp
15
- } from "./oncoprintmodel";
16
- import OncoprintToolTip from "./oncoprinttooltip";
17
- import {arrayFindIndex, ifndef, sgndiff} from "./utils";
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 "./oncoprint";
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 = "rgba(0,0,0,0.5)";
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<{width:number, height:number}>;
82
- public visible_area_width:number;
83
- private mouseMoveHandler:(evt:MouseMoveEvent)=>void;
84
-
85
- private ctx:OncoprintWebGLContext|null;
86
- private ext:ANGLE_instanced_arrays | null;
87
- private overlay_ctx:CanvasRenderingContext2D|null;
88
- private column_label_ctx:CanvasRenderingContext2D|null;
89
- private mvMatrix:any;
90
- private pMatrix:any;
91
- private shader_program:OncoprintShaderProgram;
92
-
93
- private scroll_x:number = 0;
94
- private scroll_y:number = 0;
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;//ColorBankIndex[],
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
- public vertex_column_array:TrackProp<Float32Array> = {}; // ColumnIdIndex[]
108
- private vertex_position_buffer:TrackProp<OncoprintVertexTrackBuffer> = {};
109
- private vertex_color_buffer:TrackProp<OncoprintVertexTrackBuffer> = {};
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 color_texture:TrackProp<{texture: WebGLTexture, size:number}> = {};
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:undefined|((left:number, right:number)=>void),
130
- cell_over_callback:CellMouseOverCallback,
131
- cell_click_callback:CellClickCallback
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({'width':$dummy_scroll_div_contents.parent()[0].clientWidth, 'height':$dummy_scroll_div_contents.parent()[0].clientHeight}, function() {
147
- return {'width':$dummy_scroll_div_contents.parent()[0].clientWidth, 'height':$dummy_scroll_div_contents.parent()[0].clientHeight};
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 = (typeof highlight_area_callback === 'undefined' ? function() {} : highlight_area_callback); // function(left, right) { ... }
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(mouseX + self.scroll_x, mouseY + self.scroll_y);
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(overlapping_cells.ids[0], overlapping_cells.track);
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(left+self.scroll_x, right+self.scroll_x);
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 (mouse_x >= offset.left && mouse_x < width + offset.left && mouse_y >= offset.top && mouse_y < height + offset.top);
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("mousemove", self.mouseMoveHandler);
211
- self.$overlay_canvas.on("mousemove", function(evt) {
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(mouseX + self.scroll_x, mouseY + self.scroll_y);
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 = (overlapping_cells === null ? null : overlapping_cells.ids.map(function(id) {
223
- return model.getTrackDatum(overlapping_cells.track, id);
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(overlapping_cells.ids[0], overlapping_cells.track);
228
-
229
- self.highlightCell(model, overlapping_cells.track, overlapping_cells.ids[0]);
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(250, model.getZoomedColumnLeft(overlapping_cells.ids[0]) + model.getCellWidth() / 2 + clientRect.left - self.scroll_x, model.getCellTops(overlapping_cells.track) + clientRect.top - self.scroll_y, model.getTrackTooltipFn(overlapping_cells.track)(overlapping_data));
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) ? 'rgba(0,0,0,0.3)' : 'rgba(0,0,0,0.2)';
244
- self.overlayFillRect(left, 0, right-left, self.getVisibleAreaHeight(model), drag_rect_fill);
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(model, overlapping_cells ? overlapping_cells.ids : []);
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("mousedown", function(evt) {
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("mouseup", function(evt) {
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("mouseleave", function(evt) {
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 = this.ctx || canvas.getContext("experimental-webgl", {alpha: false, antialias: this.antialias}) as OncoprintWebGLContext;
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(vertex_shader:WebGLShader, fragment_shader:WebGLShader) {
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(program, this.ctx.LINK_STATUS);
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 "Unable to link shader program: " + msg;
410
+ throw 'Unable to link shader program: ' + msg;
328
411
  }
329
412
 
330
413
  return program;
331
414
  }
332
415
 
333
- private createShader(source:string, type:"VERTEX_SHADER"|"FRAGMENT_SHADER") {
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(shader, this.ctx.COMPILE_STATUS);
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 "Unable to compile shader: " + msg;
431
+ throw 'Unable to compile shader: ' + msg;
343
432
  }
344
433
 
345
434
  return shader;
346
435
  }
347
436
 
348
- private overlayStrokeRect(x:number, y:number, width:number, height:number, color:string) {
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(this.supersampling_ratio*x, this.supersampling_ratio*y, this.supersampling_ratio*width, this.supersampling_ratio*height);
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(x:number, y:number, width:number, height:number, color:string) {
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(this.supersampling_ratio*x, this.supersampling_ratio*y, this.supersampling_ratio*width, this.supersampling_ratio*height);
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 = "rgba(0,0,0,0)";
363
- this.overlay_ctx.clearRect(0,0,this.$overlay_canvas[0].width, this.$overlay_canvas[0].height);
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 (model.getOncoprintHeight() + 10-this.scroll_y)*this.supersampling_ratio;
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 = (label.left_padding_percent || 0)*cell_width/100;
385
- let highlightHeight = cell_width*this.supersampling_ratio;
386
- let highlightWidth = this.overlay_ctx.measureText(label.text).width + left_padding*this.supersampling_ratio + 20;
387
- let dx = left_padding*this.supersampling_ratio;
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 = 2*this.getColumnLabelCircleSpec(model).radius*this.supersampling_ratio;
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 = (model.getZoomedColumnLeft(id) + cell_width/2 - this.scroll_x)*this.supersampling_ratio;
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 = "rgba(255,255,0,0.4)";
401
- this.overlay_ctx.fillRect(dx,-highlightHeight/2,highlightWidth, highlightHeight);
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(pMatrix, 0, self.ctx.viewportWidth, self.ctx.viewportHeight, 0, -5, 1000); // y axis inverted so that y increases down like SVG
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.getColumnIndexesAfterAGap().concat([Number.POSITIVE_INFINITY]);
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).length;
429
- const vertex_shader = this.createShader(getVertexShaderSource(columnsRightAfterGapsSize), 'VERTEX_SHADER');
430
- const fragment_shader = this.createShader(getFragmentShaderSource(), 'FRAGMENT_SHADER');
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(vertex_shader, fragment_shader) as OncoprintShaderProgram;
433
- shader_program.vertexPositionAttribute = this.ctx.getAttribLocation(shader_program, 'aPosVertex');
434
- this.ctx.enableVertexAttribArray(shader_program.vertexPositionAttribute);
435
- shader_program.vertexColorAttribute = this.ctx.getAttribLocation(shader_program, 'aColVertex');
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(shader_program, 'aVertexOncoprintColumn');
438
- this.ctx.enableVertexAttribArray(shader_program.vertexOncoprintColumnAttribute);
439
-
440
- shader_program.gapSizeUniform = this.ctx.getUniformLocation(shader_program, 'gapSize');
441
- shader_program.columnsRightAfterGapsUniform = this.ctx.getUniformLocation(shader_program, 'columnsRightAfterGaps');
442
- shader_program.samplerUniform = this.ctx.getUniformLocation(shader_program, 'uSampler');
443
- shader_program.pMatrixUniform = this.ctx.getUniformLocation(shader_program, 'uPMatrix');
444
- shader_program.mvMatrixUniform = this.ctx.getUniformLocation(shader_program, 'uMVMatrix');
445
- shader_program.columnWidthUniform = this.ctx.getUniformLocation(shader_program, 'columnWidth');
446
- shader_program.scrollXUniform = this.ctx.getUniformLocation(shader_program, 'scrollX');
447
- shader_program.scrollYUniform = this.ctx.getUniformLocation(shader_program, 'scrollY');
448
- shader_program.zoomXUniform = this.ctx.getUniformLocation(shader_program, 'zoomX');
449
- shader_program.zoomYUniform = this.ctx.getUniformLocation(shader_program, 'zoomY');
450
- shader_program.offsetYUniform = this.ctx.getUniformLocation(shader_program, 'offsetY');
451
- shader_program.supersamplingRatioUniform = this.ctx.getUniformLocation(shader_program, 'supersamplingRatio');
452
- shader_program.positionBitPackBaseUniform = this.ctx.getUniformLocation(shader_program, 'positionBitPackBase');
453
- shader_program.texSizeUniform = this.ctx.getUniformLocation(shader_program, 'texSize');
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({'min-width':total_width, 'min-height':model.getOncoprintHeight()});
464
- this.$dummy_scroll_div_contents.parent().css({'height': height + scrollbar_slack, 'width': visible_area_width + scrollbar_slack}); // add space for scrollbars
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 = this.supersampling_ratio*visible_area_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 = this.supersampling_ratio*visible_area_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(window_left);
503
- const horz_first_id_after_window_index = model.getClosestColumnIndexToLeft(window_right, false, true);
504
- horz_first_id_in_window_index = (horz_first_id_in_window_index < 1 ? 0 : horz_first_id_in_window_index - 1);
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 || horz_first_id_after_window_index === id_order.length ?
509
- null :
510
- id_order[horz_first_id_after_window_index]
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 ((cell_top / zoom_y) >= window_bottom || ((cell_top + cell_height)/zoom_y) < window_top) {
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(this.ctx.ARRAY_BUFFER, buffers.position);
539
- this.ctx.vertexAttribPointer(shader_program.vertexPositionAttribute, buffers.position.itemSize, this.ctx.FLOAT, false, 0, 0);
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(shader_program.vertexColorAttribute, buffers.color.itemSize, this.ctx.FLOAT, false, 0, 0);
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(shader_program.vertexOncoprintColumnAttribute, buffers.column.itemSize, this.ctx.FLOAT, false, 0, 0);
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(shader_program.vertexOncoprintColumnAttribute, 0);
799
+ this.ext.vertexAttribDivisorANGLE(
800
+ shader_program.vertexOncoprintColumnAttribute,
801
+ 0
802
+ );
546
803
  } else {
547
804
  // set up for drawArraysInstanced
548
- const universalShapesStart = buffers.position.specificShapesNumItems * buffers.position.itemSize;
549
- this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, buffers.position);
550
- this.ctx.vertexAttribPointer(shader_program.vertexPositionAttribute, buffers.position.itemSize, this.ctx.FLOAT, false, 0, 4*universalShapesStart);
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(shader_program.vertexColorAttribute, buffers.color.itemSize, this.ctx.FLOAT, false, 0, 4*universalShapesStart);
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(this.ctx.ARRAY_BUFFER, this.simple_count_buffer);
556
- this.ctx.vertexAttribPointer(shader_program.vertexOncoprintColumnAttribute, 1, this.ctx.FLOAT, false, 0, 4*horz_first_id_in_window_index);
557
- this.ext.vertexAttribDivisorANGLE(shader_program.vertexOncoprintColumnAttribute, 1);
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(this.ctx.TEXTURE_2D, buffers.color_tex.texture);
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(shader_program.texSizeUniform, buffers.color_tex.size);
855
+ this.ctx.uniform1f(
856
+ shader_program.texSizeUniform,
857
+ buffers.color_tex.size
858
+ );
564
859
 
565
- this.ctx.uniform1fv(shader_program.columnsRightAfterGapsUniform, this.getColumnIndexesAfterAGap(model)); // need min size of 1
566
- this.ctx.uniform1f(shader_program.gapSizeUniform, model.getGapSize());
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(shader_program.pMatrixUniform, false, this.pMatrix);
569
- this.ctx.uniformMatrix4fv(shader_program.mvMatrixUniform, false, this.mvMatrix);
570
- this.ctx.uniform1f(shader_program.columnWidthUniform, model.getCellWidth(true) + model.getCellPadding(true));
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(shader_program.supersamplingRatioUniform, this.supersampling_ratio);
577
- this.ctx.uniform1f(shader_program.positionBitPackBaseUniform, this.position_bit_pack_base);
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][horz_first_id_in_window];
580
- const first_index_out = horz_first_id_after_window === null ? buffers.position.specificShapesNumItems : this.id_to_first_vertex_index[track_id][horz_first_id_after_window];
581
- this.ctx.drawArrays(this.ctx.TRIANGLES, first_index, first_index_out - first_index);
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 * buffers.position.universalShapesNumItems,
587
- horz_first_id_after_window_index - horz_first_id_in_window_index
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(model, id_order.slice(horz_first_id_in_window_index, horz_first_id_after_window_index === -1 ? undefined : horz_first_id_after_window_index));
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(model:OncoprintModel, ctx:CanvasRenderingContext2D) {
944
+ private prepareContextForColumnLabelText(
945
+ model: OncoprintModel,
946
+ ctx: CanvasRenderingContext2D
947
+ ) {
606
948
  const font_size = OncoprintWebGLCellView.getColumnLabelsFontSize(model);
607
- const font_family = "Arial";
608
- ctx.font = (this.supersampling_ratio*font_size)+"px "+font_family;
609
- ctx.textAlign = "left";
610
- ctx.textBaseline = "middle";
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 = "rgba(0,0,0,0)";
616
- this.column_label_ctx.clearRect(0,0, this.$column_label_canvas[0].width, this.$column_label_canvas[0].height);
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 = this.column_label_ctx.measureText("m").width/this.supersampling_ratio;
983
+ let label_height =
984
+ this.column_label_ctx.measureText('m').width /
985
+ this.supersampling_ratio;
637
986
  if (label) {
638
- const origin_x = (x_map[ids[i]] + cell_width/2 - scroll_x)*this.supersampling_ratio;
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(2*circleSpec.radius, label_height);
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(0, 0, this.supersampling_ratio*circleSpec.radius, 0, 2*Math.PI);
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 = (label.left_padding_percent || 0)*cell_width/100;
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 = label.text_color || "rgba(0,0,0,1)";
657
- this.column_label_ctx.fillText(label.text, left_padding*this.supersampling_ratio, 0);
658
- const text_width = this.column_label_ctx.measureText(label.text).width/this.supersampling_ratio;
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 ifndef(label.angle_in_degrees, COLUMN_LABEL_ANGLE)*Math.PI/180
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
- const radius = 0.9*(model.getCellWidth()/2);
682
- return { radius };
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 (!this.simple_count_buffer || this.simple_count_buffer.numItems !== numColumns) {
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(this.ctx.ARRAY_BUFFER, new Float32Array(_.range(0, numColumns)), this.ctx.STATIC_DRAW);
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(model:OncoprintModel, track_id?:TrackId) {
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 = this.vertex_position_buffer[track_id] || this.ctx.createBuffer() as OncoprintVertexTrackBuffer;
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].universal_shapes_start_index;
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(this.ctx.ARRAY_BUFFER, pos_array, this.ctx.STATIC_DRAW);
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 = universal_shapes_start_index / pos_buffer.itemSize;
785
- pos_buffer.universalShapesNumItems = (pos_array.length - universal_shapes_start_index) / pos_buffer.itemSize;
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 = this.vertex_color_buffer[track_id] || this.ctx.createBuffer() as OncoprintVertexTrackBuffer;
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].universal_shapes_start_index;
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(this.ctx.ARRAY_BUFFER, col_array, this.ctx.STATIC_DRAW);
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 = universal_shapes_start_index / col_buffer.itemSize;
799
- col_buffer.universalShapesNumItems = (col_array.length - universal_shapes_start_index) / col_buffer.itemSize;
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] ? this.color_texture[track_id].texture : this.ctx.createTexture();
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(2,Math.ceil((Math as any).log2(color_bank.length / 4)));
810
- while (color_bank.length < 4*width) {
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(this.ctx.TEXTURE_2D, 0, this.ctx.RGBA, width, height, 0, this.ctx.RGBA, this.ctx.UNSIGNED_BYTE, new Uint8Array(color_bank));
815
- this.ctx.texParameteri(this.ctx.TEXTURE_2D, this.ctx.TEXTURE_MIN_FILTER, this.ctx.NEAREST);
816
- this.ctx.texParameteri(this.ctx.TEXTURE_2D, this.ctx.TEXTURE_MAG_FILTER, this.ctx.NEAREST);
817
- this.color_texture[track_id] = {'texture': tex, 'size':width};
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 = this.vertex_column_buffer[track_id] || this.ctx.createBuffer() as OncoprintTrackBuffer;
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(this.ctx.ARRAY_BUFFER, vertex_column_array, this.ctx.STATIC_DRAW);
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 = vertex_column_array.length / vertex_column_buffer.itemSize;
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 {'position':this.vertex_position_buffer[track_id],
838
- 'color': this.vertex_color_buffer[track_id],
839
- 'color_tex': this.color_texture[track_id],
840
- 'column': this.vertex_column_buffer[track_id]};
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[track_id];
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(id_to_first_vertex_index).map(function(id) {
851
- return [id, id_to_first_vertex_index[id]] as [ColumnId, number];
852
- }).sort(function(a,b) { return sgndiff(a[1], b[1]); });
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 = (i === id_and_first_vertex.length - 1 ? num_items : id_and_first_vertex[i+1][1]) - id_and_first_vertex[i][1];
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(model:OncoprintModel, track_id:TrackId) {
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(this.specific_shapes[track_id], o=>id_to_index[o.id]);
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 = _.sumBy(specific_shapes, (shapeList:IdentifiedShapeList)=>{
880
- return _.sumBy(shapeList.shape_list, getNumWebGLVertexes);
881
- }) + (universal_shapes ? _.sumBy(universal_shapes, getNumWebGLVertexes) : 0);
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:{[columnId:string]:number} = _.clone(id_to_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 position_bit_pack_base*position_bit_pack_base*posVertex[0] + position_bit_pack_base*posVertex[1] + posVertex[2];
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:{[shapeHash:string]:{position:number[], color:number[]}} = {};
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(pos:PositionVertex, col:ColorVertex) {
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 === "undefined") {
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(arr, next) { return arr.concat(next); }, []);
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(track_id, true);
973
- this.universal_shapes[track_id] = model.getTrackUniversalShapes(track_id, true);
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(model:OncoprintModel, track_id:TrackId, uid:ColumnId) {
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() + (model.getTrackHasColumnSpacing(track_id) ? 0 : model.getCellPadding()),
1471
+ model.getCellWidth() +
1472
+ (model.getTrackHasColumnSpacing(track_id)
1473
+ ? 0
1474
+ : model.getCellPadding()),
991
1475
  model.getCellHeight(track_id),
992
- "rgba(0,0,0,1)"
1476
+ 'rgba(0,0,0,1)'
993
1477
  );
994
1478
  }
995
1479
 
996
- private highlightTrack(model:OncoprintModel, track_id:TrackId) {
997
- const highlight_width = model.getCellWidth() + (model.getTrackHasColumnSpacing(track_id) ? 0 : model.getCellPadding());
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 + (model.getTrackHasColumnSpacing(tracks[i]) ? 0 : cell_padding),
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(this.scroll_x, true);
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(this.scroll_x + this.visible_area_width, true, true);
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 = model.getColumnLeft(id_order[id_order.length-1]) + model.getCellWidth(true);
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((scroll_y + this.getVisibleAreaHeight(model)) / zoom_y),
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 Math.min(model.getOncoprintHeight(), model.max_height) + this.getColumnLabelsHeight();
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(model:OncoprintModel, opt_exclude_ids?:ColumnId[]) {
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 (!opt_exclude_ids || opt_exclude_ids.indexOf(highlightedIds[i]) === -1) {
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(model:OncoprintModel, offset_x:number, offset_y:number) {
1373
- const root = svgfactory.group((offset_x || 0), (offset_y || 0));
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(track_id, false);
1382
- const identified_shape_list_list = model.getSpecificShapesForData(track_id, false);
1383
- for (let j=0; j<identified_shape_list_list.length; j++) {
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(svgfactory.fromShape(universal_shapes[h], offset_x, offset_y));
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(svgfactory.fromShape(sl[h], offset_x, offset_y));
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(makeSvgElement("ellipse",{
1425
- cx: x,
1426
- cy: column_label_y,
1427
- rx: spec.radius,
1428
- ry: spec.radius,
1429
- stroke:"rgba(0,0,0,0)",
1430
- fill:label.circle_color
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 = x + ((label.left_padding_percent || 0)/100)*cell_width;
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("text", {
1438
- x:text_x,
1439
- y:column_label_y,
1440
- fill:label.text_color || "#000000",
1441
- "font-size":font_size,
1442
- "font-family":"Arial",
1443
- "font-weight":"normal",
1444
- "text-anchor":"start",
1445
- "transform":"rotate("+angle+","+text_x+","+column_label_y+")",
1446
- "alignment-baseline":"middle"
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("mousemove", this.mouseMoveHandler);
1994
+ $(document).off('mousemove', this.mouseMoveHandler);
1459
1995
  }
1460
- }
1996
+ }