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,9 +1,9 @@
1
1
  import svgfactory from './svgfactory';
2
- import $ from "jquery";
2
+ import $ from 'jquery';
3
3
  import makeSvgElement from './makesvgelement';
4
- import OncoprintModel, {TrackId, TrackProp} from "./oncoprintmodel";
5
- import OncoprintToolTip from "./oncoprinttooltip";
6
- import Oncoprint from "./oncoprint";
4
+ import OncoprintModel, { TrackId, TrackProp } from './oncoprintmodel';
5
+ import OncoprintToolTip from './oncoprinttooltip';
6
+ import Oncoprint from './oncoprint';
7
7
 
8
8
  const CIRCLE_X = 25;
9
9
 
@@ -11,38 +11,45 @@ export default class OncoprintLabelView {
11
11
  private supersampling_ratio = 2;
12
12
  private base_font_size = 14;
13
13
  // stuff from model
14
- private track_tops:TrackProp<number> = {};
15
- private cell_tops:TrackProp<number> = {};
16
- private cell_tops_view_space:TrackProp<number> = {};
17
- private cell_tops_this_space:TrackProp<number> = {};
18
- private cell_heights:TrackProp<number> = {};
19
- private cell_heights_view_space:TrackProp<number> = {};
20
- private cell_heights_this_space:TrackProp<number> = {};
21
- private label_middles_view_space:TrackProp<number> = {};
22
- private label_middles_this_space:TrackProp<number> = {};
23
- private label_left_padding:TrackProp<number> = {};
24
- private labels:TrackProp<string> = {};
25
- private sublabels:TrackProp<string> = {};
26
- private label_colors:TrackProp<string> = {};
27
- private label_circle_colors:TrackProp<string> = {};
28
- private label_font_weight:TrackProp<string> = {};
29
- private html_labels:TrackProp<string> = {};
30
- private track_link_urls:TrackProp<string> = {};
31
- private track_descriptions:TrackProp<string> = {};
14
+ private track_tops: TrackProp<number> = {};
15
+ private cell_tops: TrackProp<number> = {};
16
+ private cell_tops_view_space: TrackProp<number> = {};
17
+ private cell_tops_this_space: TrackProp<number> = {};
18
+ private cell_heights: TrackProp<number> = {};
19
+ private cell_heights_view_space: TrackProp<number> = {};
20
+ private cell_heights_this_space: TrackProp<number> = {};
21
+ private label_middles_view_space: TrackProp<number> = {};
22
+ private label_middles_this_space: TrackProp<number> = {};
23
+ private label_left_padding: TrackProp<number> = {};
24
+ private labels: TrackProp<string> = {};
25
+ private sublabels: TrackProp<string> = {};
26
+ private label_colors: TrackProp<string> = {};
27
+ private label_circle_colors: TrackProp<string> = {};
28
+ private label_font_weight: TrackProp<string> = {};
29
+ private html_labels: TrackProp<string> = {};
30
+ private track_link_urls: TrackProp<string> = {};
31
+ private track_descriptions: TrackProp<string> = {};
32
32
  private minimum_track_height = Number.POSITIVE_INFINITY;
33
33
  private maximum_label_width = Number.NEGATIVE_INFINITY;
34
- private tracks:TrackId[] = [];
35
- private show_sublabels:boolean;
34
+ private tracks: TrackId[] = [];
35
+ private show_sublabels: boolean;
36
36
 
37
37
  private rendering_suppressed = false;
38
- private highlighted_track_label_only:TrackId|null = null;
39
- private drag_callback:(target_track:TrackId, new_previous_track:TrackId)=>void;
40
- private dragged_label_track_id:TrackId|null;
41
- private drag_mouse_y:number|null;
42
- private scroll_y:number = 0;
43
- private ctx:CanvasRenderingContext2D;
44
-
45
- constructor(private $canvas:JQuery<HTMLCanvasElement>, private model:OncoprintModel, private tooltip:OncoprintToolTip) {
38
+ private highlighted_track_label_only: TrackId | null = null;
39
+ private drag_callback: (
40
+ target_track: TrackId,
41
+ new_previous_track: TrackId
42
+ ) => void;
43
+ private dragged_label_track_id: TrackId | null;
44
+ private drag_mouse_y: number | null;
45
+ private scroll_y: number = 0;
46
+ private ctx: CanvasRenderingContext2D;
47
+
48
+ constructor(
49
+ private $canvas: JQuery<HTMLCanvasElement>,
50
+ private model: OncoprintModel,
51
+ private tooltip: OncoprintToolTip
52
+ ) {
46
53
  const view = this;
47
54
  this.show_sublabels = model.getShowTrackSublabels();
48
55
 
@@ -53,11 +60,12 @@ export default class OncoprintLabelView {
53
60
  view.dragged_label_track_id = null;
54
61
  view.drag_mouse_y = null;
55
62
 
56
- view.$canvas.on("mousedown", function(evt) {
63
+ view.$canvas.on('mousedown', function(evt) {
57
64
  view.tooltip.hide();
58
65
  const track_id = view.isMouseOnLabel(evt.offsetY);
59
- if (track_id !== null &&
60
- (model.getContainingTrackGroup(track_id).length > 1) &&
66
+ if (
67
+ track_id !== null &&
68
+ model.getContainingTrackGroup(track_id).length > 1 &&
61
69
  !model.isTrackInClusteredGroup(track_id) &&
62
70
  model.getTrackMovable(track_id)
63
71
  ) {
@@ -65,43 +73,80 @@ export default class OncoprintLabelView {
65
73
  }
66
74
  });
67
75
 
68
- view.$canvas.on("mousemove", function(evt) {
76
+ view.$canvas.on('mousemove', function(evt) {
69
77
  if (view.dragged_label_track_id !== null) {
70
- const track_group = model.getContainingTrackGroup(view.dragged_label_track_id);
71
- const bottommost_track = model.getLastExpansion(track_group[track_group.length - 1]);
72
- const max_drag_y = view.track_tops[bottommost_track] + model.getTrackHeight(bottommost_track) - view.scroll_y;
73
- const min_drag_y = view.track_tops[track_group[0]] - 5 - view.scroll_y;
74
- view.drag_mouse_y = Math.min(evt.pageY - view.$canvas.offset().top, max_drag_y);
78
+ const track_group = model.getContainingTrackGroup(
79
+ view.dragged_label_track_id
80
+ );
81
+ const bottommost_track = model.getLastExpansion(
82
+ track_group[track_group.length - 1]
83
+ );
84
+ const max_drag_y =
85
+ view.track_tops[bottommost_track] +
86
+ model.getTrackHeight(bottommost_track) -
87
+ view.scroll_y;
88
+ const min_drag_y =
89
+ view.track_tops[track_group[0]] - 5 - view.scroll_y;
90
+ view.drag_mouse_y = Math.min(
91
+ evt.pageY - view.$canvas.offset().top,
92
+ max_drag_y
93
+ );
75
94
  view.drag_mouse_y = Math.max(view.drag_mouse_y, min_drag_y);
76
95
  view.renderAllLabels(model);
77
96
  } else {
78
- const hovered_track = view.isMouseOnLabel(evt.pageY - view.$canvas.offset().top);
97
+ const hovered_track = view.isMouseOnLabel(
98
+ evt.pageY - view.$canvas.offset().top
99
+ );
79
100
  if (hovered_track !== null) {
80
101
  const $tooltip_div = $('<div>');
81
102
  const offset = view.$canvas[0].getBoundingClientRect();
82
- if (view.isNecessaryToShortenLabel(view.labels[hovered_track])
83
- || view.track_link_urls[hovered_track]) {
84
- $tooltip_div.append(OncoprintLabelView.formatTooltipHeader(
85
- view.labels[hovered_track],
86
- view.html_labels[hovered_track],
87
- view.track_link_urls[hovered_track]));
103
+ if (
104
+ view.isNecessaryToShortenLabel(
105
+ view.labels[hovered_track]
106
+ ) ||
107
+ view.track_link_urls[hovered_track]
108
+ ) {
109
+ $tooltip_div.append(
110
+ OncoprintLabelView.formatTooltipHeader(
111
+ view.labels[hovered_track],
112
+ view.html_labels[hovered_track],
113
+ view.track_link_urls[hovered_track]
114
+ )
115
+ );
88
116
  }
89
- const track_description = view.track_descriptions[hovered_track];
117
+ const track_description =
118
+ view.track_descriptions[hovered_track];
90
119
  if (track_description.length > 0) {
91
- $tooltip_div.append($('<div>').text(track_description));
120
+ $tooltip_div.append(
121
+ $('<div>').text(track_description)
122
+ );
92
123
  }
93
124
  // dragging info
94
125
  if (model.getTrackMovable(hovered_track)) {
95
126
  if (model.isTrackInClusteredGroup(hovered_track)) {
96
127
  view.$canvas.css('cursor', 'not-allowed');
97
- $tooltip_div.append("<b>dragging disabled for clustered tracks</b>");
98
- } else if (model.getContainingTrackGroup(hovered_track).length > 1) {
128
+ $tooltip_div.append(
129
+ '<b>dragging disabled for clustered tracks</b>'
130
+ );
131
+ } else if (
132
+ model.getContainingTrackGroup(hovered_track)
133
+ .length > 1
134
+ ) {
99
135
  view.$canvas.css('cursor', 'move');
100
- $tooltip_div.append("<b>hold to drag</b>");
136
+ $tooltip_div.append('<b>hold to drag</b>');
101
137
  }
102
138
  }
103
139
  if ($tooltip_div.contents().length > 0) {
104
- view.tooltip.fadeIn(200, view.renderedLabelWidth(view.labels[hovered_track]) + offset.left, view.cell_tops[hovered_track] + offset.top - view.scroll_y, $tooltip_div);
140
+ view.tooltip.fadeIn(
141
+ 200,
142
+ view.renderedLabelWidth(
143
+ view.labels[hovered_track]
144
+ ) + offset.left,
145
+ view.cell_tops[hovered_track] +
146
+ offset.top -
147
+ view.scroll_y,
148
+ $tooltip_div
149
+ );
105
150
  }
106
151
  } else {
107
152
  view.$canvas.css('cursor', 'auto');
@@ -110,10 +155,16 @@ export default class OncoprintLabelView {
110
155
  }
111
156
  });
112
157
 
113
- view.$canvas.on("mouseup mouseleave", function(evt) {
158
+ view.$canvas.on('mouseup mouseleave', function(evt) {
114
159
  if (view.dragged_label_track_id !== null) {
115
- const track_group = model.getContainingTrackGroup(view.dragged_label_track_id);
116
- const previous_track_id = view.getLabelAboveMouseSpace(track_group, evt.offsetY, view.dragged_label_track_id);
160
+ const track_group = model.getContainingTrackGroup(
161
+ view.dragged_label_track_id
162
+ );
163
+ const previous_track_id = view.getLabelAboveMouseSpace(
164
+ track_group,
165
+ evt.offsetY,
166
+ view.dragged_label_track_id
167
+ );
117
168
  view.stopDragging(model, previous_track_id);
118
169
  }
119
170
  view.tooltip.hideIfNotAlreadyGoingTo(150);
@@ -122,14 +173,17 @@ export default class OncoprintLabelView {
122
173
  }
123
174
 
124
175
  private circleRadius() {
125
- return this.minimum_track_height*0.8/2;
176
+ return (this.minimum_track_height * 0.8) / 2;
126
177
  }
127
178
 
128
- private renderedLabelWidth(label:string) {
129
- return this.ctx.measureText(this.shortenLabelIfNecessary(label)).width/this.supersampling_ratio;
179
+ private renderedLabelWidth(label: string) {
180
+ return (
181
+ this.ctx.measureText(this.shortenLabelIfNecessary(label)).width /
182
+ this.supersampling_ratio
183
+ );
130
184
  }
131
-
132
- private updateFromModel(model:OncoprintModel) {
185
+
186
+ private updateFromModel(model: OncoprintModel) {
133
187
  if (this.rendering_suppressed) {
134
188
  return;
135
189
  }
@@ -142,67 +196,97 @@ export default class OncoprintLabelView {
142
196
  this.tracks = model.getTracks();
143
197
  this.track_descriptions = {};
144
198
 
145
- this.ctx.font = 'bold '+this.getFontSize()+'px Arial';
199
+ this.ctx.font = 'bold ' + this.getFontSize() + 'px Arial';
146
200
  this.minimum_track_height = Number.POSITIVE_INFINITY;
147
201
  this.maximum_label_width = 0;
148
- for (let i=0; i<this.tracks.length; i++) {
149
- this.minimum_track_height = Math.min(this.minimum_track_height, model.getTrackHeight(this.tracks[i]));
150
- const shortened_label = this.shortenLabelIfNecessary(this.labels[this.tracks[i]]);
151
- const shortened_sublabel = this.shortenLabelIfNecessary(this.sublabels[this.tracks[i]]);
152
- const measured_width = this.ctx.measureText(shortened_label).width + (this.show_sublabels ? this.ctx.measureText(shortened_sublabel).width : 0);
153
- this.maximum_label_width = Math.max(this.maximum_label_width, measured_width);
154
-
155
- this.cell_tops_this_space[this.tracks[i]] = this.cell_tops[this.tracks[i]]*this.supersampling_ratio - this.scroll_y*this.supersampling_ratio;
156
- this.track_descriptions[this.tracks[i]] = model.getTrackDescription(this.tracks[i]);
157
- this.cell_heights[this.tracks[i]] = model.getCellHeight(this.tracks[i]);
158
- this.cell_heights_this_space[this.tracks[i]] = this.cell_heights[this.tracks[i]]*this.supersampling_ratio;
159
- this.label_middles_this_space[this.tracks[i]] = this.cell_tops_this_space[this.tracks[i]] + this.cell_heights_this_space[this.tracks[i]]/2;
202
+ for (let i = 0; i < this.tracks.length; i++) {
203
+ this.minimum_track_height = Math.min(
204
+ this.minimum_track_height,
205
+ model.getTrackHeight(this.tracks[i])
206
+ );
207
+ const shortened_label = this.shortenLabelIfNecessary(
208
+ this.labels[this.tracks[i]]
209
+ );
210
+ const shortened_sublabel = this.shortenLabelIfNecessary(
211
+ this.sublabels[this.tracks[i]]
212
+ );
213
+ const measured_width =
214
+ this.ctx.measureText(shortened_label).width +
215
+ (this.show_sublabels
216
+ ? this.ctx.measureText(shortened_sublabel).width
217
+ : 0);
218
+ this.maximum_label_width = Math.max(
219
+ this.maximum_label_width,
220
+ measured_width
221
+ );
222
+
223
+ this.cell_tops_this_space[this.tracks[i]] =
224
+ this.cell_tops[this.tracks[i]] * this.supersampling_ratio -
225
+ this.scroll_y * this.supersampling_ratio;
226
+ this.track_descriptions[this.tracks[i]] = model.getTrackDescription(
227
+ this.tracks[i]
228
+ );
229
+ this.cell_heights[this.tracks[i]] = model.getCellHeight(
230
+ this.tracks[i]
231
+ );
232
+ this.cell_heights_this_space[this.tracks[i]] =
233
+ this.cell_heights[this.tracks[i]] * this.supersampling_ratio;
234
+ this.label_middles_this_space[this.tracks[i]] =
235
+ this.cell_tops_this_space[this.tracks[i]] +
236
+ this.cell_heights_this_space[this.tracks[i]] / 2;
160
237
  }
161
238
  }
162
239
  private setUpContext() {
163
240
  this.ctx = this.$canvas[0].getContext('2d');
164
- this.ctx.textAlign="start";
165
- this.ctx.textBaseline="middle";
241
+ this.ctx.textAlign = 'start';
242
+ this.ctx.textBaseline = 'middle';
166
243
  }
167
- private resizeAndClear(model:OncoprintModel, getCellViewHeight:()=>number) {
244
+ private resizeAndClear(
245
+ model: OncoprintModel,
246
+ getCellViewHeight: () => number
247
+ ) {
168
248
  if (this.rendering_suppressed) {
169
249
  return;
170
250
  }
171
251
  const visible_height = getCellViewHeight();
172
252
  const visible_width = this.getWidth();
173
- this.$canvas[0].height = this.supersampling_ratio*visible_height;
174
- this.$canvas[0].width = this.supersampling_ratio*visible_width;
253
+ this.$canvas[0].height = this.supersampling_ratio * visible_height;
254
+ this.$canvas[0].width = this.supersampling_ratio * visible_width;
175
255
  this.$canvas[0].style.height = visible_height + 'px';
176
256
  this.$canvas[0].style.width = visible_width + 'px';
177
257
  this.setUpContext();
178
258
  }
179
- private isNecessaryToShortenLabel(label:string) {
259
+ private isNecessaryToShortenLabel(label: string) {
180
260
  return label.length > this.getMaximumLabelLength();
181
261
  }
182
- private shortenLabelIfNecessary(label:string) {
262
+ private shortenLabelIfNecessary(label: string) {
183
263
  if (this.isNecessaryToShortenLabel(label)) {
184
- return label.substring(0, this.getMaximumLabelLength()-3) + '...';
264
+ return label.substring(0, this.getMaximumLabelLength() - 3) + '...';
185
265
  } else {
186
266
  return label;
187
267
  }
188
268
  }
189
- private static formatTooltipHeader(label:string, html_label:any, link_url:string) {
269
+ private static formatTooltipHeader(
270
+ label: string,
271
+ html_label: any,
272
+ link_url: string
273
+ ) {
190
274
  let header_contents;
191
275
  if (link_url) {
192
- header_contents = (
193
- $('<a target="_blank" rel="noopener noreferrer">')
194
- .attr('href', link_url));
276
+ header_contents = $(
277
+ '<a target="_blank" rel="noopener noreferrer">'
278
+ ).attr('href', link_url);
195
279
  } else {
196
280
  header_contents = $('<span>');
197
281
  }
198
282
  header_contents.append(html_label || document.createTextNode(label));
199
283
  return $('<b style="display: block;">').append(header_contents);
200
284
  }
201
- private renderAllLabels(model:OncoprintModel) {
285
+ private renderAllLabels(model: OncoprintModel) {
202
286
  if (this.rendering_suppressed) {
203
287
  return;
204
288
  }
205
- this.ctx.clearRect(0,0,this.$canvas[0].width,this.$canvas[0].height);
289
+ this.ctx.clearRect(0, 0, this.$canvas[0].width, this.$canvas[0].height);
206
290
 
207
291
  const highlightedTracks = [];
208
292
  highlightedTracks.push(...model.getHighlightedTracks());
@@ -215,90 +299,154 @@ export default class OncoprintLabelView {
215
299
  this.ctx.fillRect(
216
300
  0,
217
301
  this.cell_tops_this_space[track_id],
218
- this.getWidth()*this.supersampling_ratio,
302
+ this.getWidth() * this.supersampling_ratio,
219
303
  this.cell_heights_this_space[track_id]
220
304
  );
221
305
  }
222
306
  }
223
307
  const font_size = this.getFontSize();
224
308
  const tracks = this.tracks;
225
- const sublabelX:TrackProp<number> = {};
226
- for (let i=0; i<tracks.length; i++) {
309
+ const sublabelX: TrackProp<number> = {};
310
+ for (let i = 0; i < tracks.length; i++) {
227
311
  if (this.label_circle_colors[tracks[i]]) {
228
312
  // draw circle if specified
229
313
  this.ctx.fillStyle = this.label_circle_colors[tracks[i]];
230
314
  this.ctx.beginPath();
231
- this.ctx.arc(CIRCLE_X*this.supersampling_ratio, this.label_middles_this_space[tracks[i]], this.supersampling_ratio*this.circleRadius(), 0, 2*Math.PI);
315
+ this.ctx.arc(
316
+ CIRCLE_X * this.supersampling_ratio,
317
+ this.label_middles_this_space[tracks[i]],
318
+ this.supersampling_ratio * this.circleRadius(),
319
+ 0,
320
+ 2 * Math.PI
321
+ );
232
322
  this.ctx.fill();
233
323
  }
234
324
 
235
- this.ctx.font = (this.label_font_weight[tracks[i]] || 'bold')+' '+font_size +'px Arial';
325
+ this.ctx.font =
326
+ (this.label_font_weight[tracks[i]] || 'bold') +
327
+ ' ' +
328
+ font_size +
329
+ 'px Arial';
236
330
  this.ctx.fillStyle = 'black';
237
331
  if (this.label_colors && this.label_colors[tracks[i]]) {
238
332
  //override color, if set:
239
333
  this.ctx.fillStyle = this.label_colors[tracks[i]];
240
334
  }
241
335
  const label = this.shortenLabelIfNecessary(this.labels[tracks[i]]);
242
- this.ctx.fillText(label, this.label_left_padding[tracks[i]]*this.supersampling_ratio, this.label_middles_this_space[tracks[i]]);
336
+ this.ctx.fillText(
337
+ label,
338
+ this.label_left_padding[tracks[i]] * this.supersampling_ratio,
339
+ this.label_middles_this_space[tracks[i]]
340
+ );
243
341
  sublabelX[tracks[i]] = this.ctx.measureText(label).width;
244
342
  }
245
343
  if (this.show_sublabels) {
246
344
  // render sublabels - not bold, gray
247
- this.ctx.font = font_size+'px Arial';
248
- this.ctx.fillStyle='rgb(166,166,166)';
249
- for (let i=0; i<tracks.length; i++) {
345
+ this.ctx.font = font_size + 'px Arial';
346
+ this.ctx.fillStyle = 'rgb(166,166,166)';
347
+ for (let i = 0; i < tracks.length; i++) {
250
348
  if (this.sublabels[tracks[i]]) {
251
- this.ctx.fillText(this.shortenLabelIfNecessary(this.sublabels[tracks[i]]), sublabelX[tracks[i]], this.label_middles_this_space[tracks[i]]);
349
+ this.ctx.fillText(
350
+ this.shortenLabelIfNecessary(this.sublabels[tracks[i]]),
351
+ sublabelX[tracks[i]],
352
+ this.label_middles_this_space[tracks[i]]
353
+ );
252
354
  }
253
355
  }
254
356
  }
255
357
  if (this.dragged_label_track_id !== null) {
256
- this.ctx.font = 'bold '+font_size +'px Arial';
358
+ this.ctx.font = 'bold ' + font_size + 'px Arial';
257
359
  this.ctx.fillStyle = 'rgba(255,0,0,0.95)';
258
- this.ctx.fillText(this.shortenLabelIfNecessary(this.labels[this.dragged_label_track_id]), 0, this.supersampling_ratio*this.drag_mouse_y);
360
+ this.ctx.fillText(
361
+ this.shortenLabelIfNecessary(
362
+ this.labels[this.dragged_label_track_id]
363
+ ),
364
+ 0,
365
+ this.supersampling_ratio * this.drag_mouse_y
366
+ );
259
367
  this.ctx.fillStyle = 'rgba(0,0,0,0.15)';
260
- const group = this.model.getContainingTrackGroup(this.dragged_label_track_id);
261
- const label_above_mouse = this.model.getLastExpansion(this.getLabelAboveMouseSpace(group, this.drag_mouse_y, null));
262
- const label_below_mouse = this.getLabelBelowMouseSpace(group, this.drag_mouse_y, null);
368
+ const group = this.model.getContainingTrackGroup(
369
+ this.dragged_label_track_id
370
+ );
371
+ const label_above_mouse = this.model.getLastExpansion(
372
+ this.getLabelAboveMouseSpace(group, this.drag_mouse_y, null)
373
+ );
374
+ const label_below_mouse = this.getLabelBelowMouseSpace(
375
+ group,
376
+ this.drag_mouse_y,
377
+ null
378
+ );
263
379
  let rect_y, rect_height;
264
- if (label_above_mouse === this.dragged_label_track_id || label_below_mouse === this.dragged_label_track_id) {
380
+ if (
381
+ label_above_mouse === this.dragged_label_track_id ||
382
+ label_below_mouse === this.dragged_label_track_id
383
+ ) {
265
384
  return;
266
385
  }
267
386
  if (label_above_mouse !== null && label_below_mouse !== null) {
268
- rect_y = this.cell_tops_this_space[label_above_mouse] + this.cell_heights_this_space[label_above_mouse];
269
- rect_height = this.cell_tops_this_space[label_below_mouse] - rect_y;
387
+ rect_y =
388
+ this.cell_tops_this_space[label_above_mouse] +
389
+ this.cell_heights_this_space[label_above_mouse];
390
+ rect_height =
391
+ this.cell_tops_this_space[label_below_mouse] - rect_y;
270
392
  } else if (label_above_mouse === null) {
271
- rect_y = this.cell_tops_this_space[group[0]] - this.ctx.measureText("m").width;
272
- rect_height = this.ctx.measureText("m").width;
393
+ rect_y =
394
+ this.cell_tops_this_space[group[0]] -
395
+ this.ctx.measureText('m').width;
396
+ rect_height = this.ctx.measureText('m').width;
273
397
  } else if (label_below_mouse === null) {
274
- rect_y = this.cell_tops_this_space[label_above_mouse] + this.cell_heights_this_space[label_above_mouse];
275
- rect_height = this.ctx.measureText("m").width;
398
+ rect_y =
399
+ this.cell_tops_this_space[label_above_mouse] +
400
+ this.cell_heights_this_space[label_above_mouse];
401
+ rect_height = this.ctx.measureText('m').width;
276
402
  }
277
403
 
278
404
  const min_rect_height = 4;
279
405
  rect_height = Math.max(rect_height, min_rect_height);
280
- this.ctx.fillRect(this.label_left_padding[tracks[tracks.length-1]]*this.supersampling_ratio, rect_y, this.getWidth()*this.supersampling_ratio, rect_height);
406
+ this.ctx.fillRect(
407
+ this.label_left_padding[tracks[tracks.length - 1]] *
408
+ this.supersampling_ratio,
409
+ rect_y,
410
+ this.getWidth() * this.supersampling_ratio,
411
+ rect_height
412
+ );
281
413
  }
282
414
  }
283
415
 
284
- private isMouseOnLabel(mouse_y:number) {
285
- const candidate_track = this.getLabelAboveMouseSpace(this.tracks, mouse_y, null);
416
+ private isMouseOnLabel(mouse_y: number) {
417
+ const candidate_track = this.getLabelAboveMouseSpace(
418
+ this.tracks,
419
+ mouse_y,
420
+ null
421
+ );
286
422
  if (candidate_track === null) {
287
423
  return null;
288
424
  }
289
- if (mouse_y <= this.cell_tops[candidate_track] - this.scroll_y + this.cell_heights[candidate_track]) {
425
+ if (
426
+ mouse_y <=
427
+ this.cell_tops[candidate_track] -
428
+ this.scroll_y +
429
+ this.cell_heights[candidate_track]
430
+ ) {
290
431
  return candidate_track;
291
432
  } else {
292
433
  return null;
293
434
  }
294
435
  }
295
- private getLabelAboveMouseSpace(track_ids:TrackId[], y:number, track_to_exclude:TrackId|null) {
436
+ private getLabelAboveMouseSpace(
437
+ track_ids: TrackId[],
438
+ y: number,
439
+ track_to_exclude: TrackId | null
440
+ ) {
296
441
  if (y < this.cell_tops[track_ids[0]] - this.scroll_y) {
297
442
  return null;
298
443
  } else {
299
444
  let candidate_track = null;
300
- for (let i=0; i<track_ids.length; i++) {
301
- if (track_to_exclude !== null && track_to_exclude === track_ids[i]) {
445
+ for (let i = 0; i < track_ids.length; i++) {
446
+ if (
447
+ track_to_exclude !== null &&
448
+ track_to_exclude === track_ids[i]
449
+ ) {
302
450
  continue;
303
451
  }
304
452
  if (this.cell_tops[track_ids[i]] - this.scroll_y > y) {
@@ -310,13 +458,23 @@ export default class OncoprintLabelView {
310
458
  return candidate_track;
311
459
  }
312
460
  }
313
- private getLabelBelowMouseSpace(track_ids:TrackId[], y:number, track_to_exclude:TrackId|null) {
314
- if (y > this.cell_tops[track_ids[track_ids.length-1]] - this.scroll_y) {
461
+ private getLabelBelowMouseSpace(
462
+ track_ids: TrackId[],
463
+ y: number,
464
+ track_to_exclude: TrackId | null
465
+ ) {
466
+ if (
467
+ y >
468
+ this.cell_tops[track_ids[track_ids.length - 1]] - this.scroll_y
469
+ ) {
315
470
  return null;
316
471
  } else {
317
472
  let candidate_track = null;
318
- for (let i=track_ids.length-1; i>=0; i--) {
319
- if (track_to_exclude !== null && track_to_exclude === track_ids[i]) {
473
+ for (let i = track_ids.length - 1; i >= 0; i--) {
474
+ if (
475
+ track_to_exclude !== null &&
476
+ track_to_exclude === track_ids[i]
477
+ ) {
320
478
  continue;
321
479
  }
322
480
  if (this.cell_tops[track_ids[i]] - this.scroll_y < y) {
@@ -329,12 +487,19 @@ export default class OncoprintLabelView {
329
487
  }
330
488
  }
331
489
 
332
- private startDragging(model:OncoprintModel, track_id:TrackId, mouse_y:number) {
490
+ private startDragging(
491
+ model: OncoprintModel,
492
+ track_id: TrackId,
493
+ mouse_y: number
494
+ ) {
333
495
  this.dragged_label_track_id = track_id;
334
496
  this.drag_mouse_y = mouse_y;
335
497
  this.renderAllLabels(model);
336
498
  }
337
- private stopDragging(model:OncoprintModel, new_previous_track_id:TrackId) {
499
+ private stopDragging(
500
+ model: OncoprintModel,
501
+ new_previous_track_id: TrackId
502
+ ) {
338
503
  this.drag_callback(this.dragged_label_track_id, new_previous_track_id);
339
504
  this.dragged_label_track_id = null;
340
505
  this.renderAllLabels(model);
@@ -346,107 +511,146 @@ export default class OncoprintLabelView {
346
511
 
347
512
  public getWidth() {
348
513
  if (this.model.getShowTrackLabels()) {
349
- return Math.max(this.maximum_label_width/this.supersampling_ratio + 10, 70);
514
+ return Math.max(
515
+ this.maximum_label_width / this.supersampling_ratio + 10,
516
+ 70
517
+ );
350
518
  } else {
351
519
  return 0;
352
520
  }
353
521
  }
354
- public getFontSize(no_supersampling_adjustment?:boolean) {
355
- return (no_supersampling_adjustment ? 1 : this.supersampling_ratio) * Math.max(Math.min(this.base_font_size, this.minimum_track_height), 7);
522
+ public getFontSize(no_supersampling_adjustment?: boolean) {
523
+ return (
524
+ (no_supersampling_adjustment ? 1 : this.supersampling_ratio) *
525
+ Math.max(
526
+ Math.min(this.base_font_size, this.minimum_track_height),
527
+ 7
528
+ )
529
+ );
356
530
  }
357
- public setDragCallback(callback:OncoprintLabelView["drag_callback"]) {
531
+ public setDragCallback(callback: OncoprintLabelView['drag_callback']) {
358
532
  this.drag_callback = callback;
359
533
  }
360
- public removeTrack(model:OncoprintModel, getCellViewHeight:()=>number) {
534
+ public removeTrack(model: OncoprintModel, getCellViewHeight: () => number) {
361
535
  this.updateFromModel(model);
362
536
  this.resizeAndClear(model, getCellViewHeight);
363
537
  this.renderAllLabels(model);
364
538
  }
365
- public moveTrack(model:OncoprintModel, getCellViewHeight:()=>number) {
539
+ public moveTrack(model: OncoprintModel, getCellViewHeight: () => number) {
366
540
  this.updateFromModel(model);
367
541
  this.resizeAndClear(model, getCellViewHeight);
368
542
  this.renderAllLabels(model);
369
543
  }
370
- public setTrackGroupOrder(model:OncoprintModel, getCellViewHeight:()=>number) {
544
+ public setTrackGroupOrder(
545
+ model: OncoprintModel,
546
+ getCellViewHeight: () => number
547
+ ) {
371
548
  this.updateFromModel(model);
372
549
  this.resizeAndClear(model, getCellViewHeight);
373
550
  this.renderAllLabels(model);
374
551
  }
375
- public setShowTrackLabels(model:OncoprintModel, getCellViewHeight:()=>number) {
552
+ public setShowTrackLabels(
553
+ model: OncoprintModel,
554
+ getCellViewHeight: () => number
555
+ ) {
376
556
  this.updateFromModel(model);
377
557
  this.resizeAndClear(model, getCellViewHeight);
378
558
  this.renderAllLabels(model);
379
559
  }
380
- public addTracks(model:OncoprintModel, track_ids:TrackId[], getCellViewHeight:()=>number) {
381
- for (let i=0; i<track_ids.length; i++) {
560
+ public addTracks(
561
+ model: OncoprintModel,
562
+ track_ids: TrackId[],
563
+ getCellViewHeight: () => number
564
+ ) {
565
+ for (let i = 0; i < track_ids.length; i++) {
382
566
  this.labels[track_ids[i]] = model.getTrackLabel(track_ids[i]);
383
567
  this.sublabels[track_ids[i]] = model.getTrackSublabel(track_ids[i]);
384
- this.label_colors[track_ids[i]] = model.getTrackLabelColor(track_ids[i]);
385
- this.label_circle_colors[track_ids[i]] = model.getTrackLabelCircleColor(track_ids[i]);
386
- this.label_left_padding[track_ids[i]] = model.getTrackLabelLeftPadding(track_ids[i]);
387
- this.label_font_weight[track_ids[i]] = model.getTrackLabelFontWeight(track_ids[i]);
388
- this.html_labels[track_ids[i]] = model.getOptionalHtmlTrackLabel(track_ids[i]);
389
- this.track_link_urls[track_ids[i]] = model.getTrackLinkUrl(track_ids[i]);
568
+ this.label_colors[track_ids[i]] = model.getTrackLabelColor(
569
+ track_ids[i]
570
+ );
571
+ this.label_circle_colors[
572
+ track_ids[i]
573
+ ] = model.getTrackLabelCircleColor(track_ids[i]);
574
+ this.label_left_padding[
575
+ track_ids[i]
576
+ ] = model.getTrackLabelLeftPadding(track_ids[i]);
577
+ this.label_font_weight[
578
+ track_ids[i]
579
+ ] = model.getTrackLabelFontWeight(track_ids[i]);
580
+ this.html_labels[track_ids[i]] = model.getOptionalHtmlTrackLabel(
581
+ track_ids[i]
582
+ );
583
+ this.track_link_urls[track_ids[i]] = model.getTrackLinkUrl(
584
+ track_ids[i]
585
+ );
390
586
  }
391
587
  this.updateFromModel(model);
392
588
  this.resizeAndClear(model, getCellViewHeight);
393
589
  this.renderAllLabels(model);
394
590
  }
395
591
 
396
- public setShowTrackSublabels(model:OncoprintModel, getCellViewHeight:()=>number) {
592
+ public setShowTrackSublabels(
593
+ model: OncoprintModel,
594
+ getCellViewHeight: () => number
595
+ ) {
397
596
  this.updateFromModel(model);
398
597
  this.resizeAndClear(model, getCellViewHeight);
399
598
  this.renderAllLabels(model);
400
599
  }
401
600
 
402
- public setScroll(model:OncoprintModel, getCellViewHeight:()=>number) {
601
+ public setScroll(model: OncoprintModel, getCellViewHeight: () => number) {
403
602
  this.setVertScroll(model, getCellViewHeight);
404
603
  }
405
604
 
406
- public setHorzScroll(model:OncoprintModel) {
407
- }
605
+ public setHorzScroll(model: OncoprintModel) {}
408
606
 
409
- public setViewport(model:OncoprintModel, getCellViewHeight:()=>number) {
607
+ public setViewport(model: OncoprintModel, getCellViewHeight: () => number) {
410
608
  this.setVertScroll(model, getCellViewHeight);
411
609
  }
412
610
 
413
- public setVertScroll(model:OncoprintModel, getCellViewHeight:()=>number) {
611
+ public setVertScroll(
612
+ model: OncoprintModel,
613
+ getCellViewHeight: () => number
614
+ ) {
414
615
  this.updateFromModel(model);
415
616
  this.resizeAndClear(model, getCellViewHeight);
416
617
  this.renderAllLabels(model);
417
618
  }
418
619
 
419
- public setVertZoom(model:OncoprintModel, getCellViewHeight:()=>number) {
620
+ public setVertZoom(model: OncoprintModel, getCellViewHeight: () => number) {
420
621
  this.updateFromModel(model);
421
622
  this.resizeAndClear(model, getCellViewHeight);
422
623
  this.renderAllLabels(model);
423
624
  }
424
625
 
425
- public setZoom(model:OncoprintModel, getCellViewHeight:()=>number) {
626
+ public setZoom(model: OncoprintModel, getCellViewHeight: () => number) {
426
627
  this.setVertZoom(model, getCellViewHeight);
427
628
  }
428
629
 
429
- public highlightTrackLabelOnly(track_id:TrackId, model:OncoprintModel) {
630
+ public highlightTrackLabelOnly(track_id: TrackId, model: OncoprintModel) {
430
631
  // track_id is a track id, or null to clear highlight
431
632
  this.highlighted_track_label_only = track_id;
432
633
  this.renderAllLabels(model);
433
634
  }
434
635
 
435
- public setHighlightedTracks(model:OncoprintModel) {
636
+ public setHighlightedTracks(model: OncoprintModel) {
436
637
  this.renderAllLabels(model);
437
638
  }
438
639
 
439
- public setTrackMovable(model:OncoprintModel) {
640
+ public setTrackMovable(model: OncoprintModel) {
440
641
  this.renderAllLabels(model);
441
642
  }
442
643
 
443
- public setTrackGroupHeader(model:OncoprintModel, getCellViewHeight:()=>number) {
644
+ public setTrackGroupHeader(
645
+ model: OncoprintModel,
646
+ getCellViewHeight: () => number
647
+ ) {
444
648
  this.updateFromModel(model);
445
649
  this.resizeAndClear(model, getCellViewHeight);
446
650
  this.renderAllLabels(model);
447
651
  }
448
652
 
449
- public sort(model:OncoprintModel, getCellViewHeight:()=>number) {
653
+ public sort(model: OncoprintModel, getCellViewHeight: () => number) {
450
654
  this.updateFromModel(model);
451
655
  this.resizeAndClear(model, getCellViewHeight);
452
656
  this.renderAllLabels(model);
@@ -456,15 +660,23 @@ export default class OncoprintLabelView {
456
660
  this.rendering_suppressed = true;
457
661
  }
458
662
 
459
- public releaseRendering(model:OncoprintModel, getCellViewHeight:()=>number) {
663
+ public releaseRendering(
664
+ model: OncoprintModel,
665
+ getCellViewHeight: () => number
666
+ ) {
460
667
  this.rendering_suppressed = false;
461
668
  this.updateFromModel(model);
462
669
  this.resizeAndClear(model, getCellViewHeight);
463
670
  this.renderAllLabels(model);
464
671
  }
465
672
 
466
- public toSVGGroup(model:OncoprintModel, full_labels:boolean, offset_x:number, offset_y:number) {
467
- const root = svgfactory.group((offset_x || 0), (offset_y || 0));
673
+ public toSVGGroup(
674
+ model: OncoprintModel,
675
+ full_labels: boolean,
676
+ offset_x: number,
677
+ offset_y: number
678
+ ) {
679
+ const root = svgfactory.group(offset_x || 0, offset_y || 0);
468
680
  if (!model.getShowTrackLabels()) {
469
681
  // dont add anything if hiding track labels
470
682
  return root;
@@ -472,29 +684,35 @@ export default class OncoprintLabelView {
472
684
 
473
685
  const cell_tops = model.getCellTops() as TrackProp<number>;
474
686
  const tracks = model.getTracks();
475
- for (let i=0; i<tracks.length; i++) {
687
+ for (let i = 0; i < tracks.length; i++) {
476
688
  const track_id = tracks[i];
477
- const y = cell_tops[track_id] + model.getCellHeight(track_id)/2;
689
+ const y = cell_tops[track_id] + model.getCellHeight(track_id) / 2;
478
690
  const label = model.getTrackLabel(track_id);
479
691
  const circleColor = model.getTrackLabelCircleColor(track_id);
480
692
  if (circleColor) {
481
693
  // add circle
482
- root.appendChild(makeSvgElement("ellipse",{
483
- cx: CIRCLE_X.toString(),
484
- cy: y.toString(),
485
- rx: this.circleRadius().toString(),
486
- ry: this.circleRadius().toString(),
487
- stroke:"rgba(0,0,0,0)",
488
- fill:circleColor
489
- }));
694
+ root.appendChild(
695
+ makeSvgElement('ellipse', {
696
+ cx: CIRCLE_X.toString(),
697
+ cy: y.toString(),
698
+ rx: this.circleRadius().toString(),
699
+ ry: this.circleRadius().toString(),
700
+ stroke: 'rgba(0,0,0,0)',
701
+ fill: circleColor,
702
+ })
703
+ );
490
704
  }
491
705
  const text_elt = svgfactory.text(
492
- (full_labels ? label : this.shortenLabelIfNecessary(label)),
493
- model.getTrackLabelLeftPadding(track_id), y,
706
+ full_labels ? label : this.shortenLabelIfNecessary(label),
707
+ model.getTrackLabelLeftPadding(track_id),
708
+ y,
494
709
  this.getFontSize(true),
495
- 'Arial', model.getTrackLabelFontWeight(track_id) || 'bold', "bottom", circleColor ? "white" : "black"
710
+ 'Arial',
711
+ model.getTrackLabelFontWeight(track_id) || 'bold',
712
+ 'bottom',
713
+ circleColor ? 'white' : 'black'
496
714
  );
497
- text_elt.setAttribute("dy", "0.35em");
715
+ text_elt.setAttribute('dy', '0.35em');
498
716
  root.appendChild(text_elt);
499
717
  }
500
718
  return root;