higlass 1.13.5 → 1.13.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/README.md +48 -54
  2. package/app/globals.d.ts +1 -1
  3. package/app/missing-types.d.ts +4 -1
  4. package/app/scripts/AddTrackDialog.jsx +3 -3
  5. package/app/scripts/AddTrackPositionMenu.jsx +2 -2
  6. package/app/scripts/Annotations1dTrack.js +1 -1
  7. package/app/scripts/Annotations2dTrack.js +3 -5
  8. package/app/scripts/Autocomplete.jsx +14 -21
  9. package/app/scripts/AxisPixi.js +6 -10
  10. package/app/scripts/BarTrack.js +3 -3
  11. package/app/scripts/BedLikeTrack.js +12 -13
  12. package/app/scripts/Button.jsx +1 -1
  13. package/app/scripts/CNVIntervalTrack.js +1 -1
  14. package/app/scripts/CenterTrack.jsx +8 -7
  15. package/app/scripts/Chromosome2DAnnotations.js +1 -1
  16. package/app/scripts/Chromosome2DLabels.js +1 -1
  17. package/app/scripts/ChromosomeGrid.js +49 -38
  18. package/app/scripts/ChromosomeInfo.js +1 -1
  19. package/app/scripts/CombinedTrack.js +3 -1
  20. package/app/scripts/ConfigTrackMenu.jsx +1 -1
  21. package/app/scripts/ConfigViewMenu.jsx +2 -2
  22. package/app/scripts/ContextMenuContainer.jsx +1 -2
  23. package/app/scripts/ContextMenuItem.jsx +1 -0
  24. package/app/scripts/CrossRule.js +1 -1
  25. package/app/scripts/CustomTrackDialog.jsx +2 -2
  26. package/app/scripts/Dialog.jsx +2 -2
  27. package/app/scripts/DragListeningDiv.jsx +1 -1
  28. package/app/scripts/DraggableDiv.jsx +2 -3
  29. package/app/scripts/ExportLinkDialog.jsx +1 -1
  30. package/app/scripts/GalleryTracks.jsx +77 -78
  31. package/app/scripts/GenomePositionSearchBox.jsx +10 -9
  32. package/app/scripts/HeatmapOptions.jsx +4 -2
  33. package/app/scripts/HeatmapTiledPixiTrack.js +23 -32
  34. package/app/scripts/HiGlassComponent.jsx +75 -98
  35. package/app/scripts/Horizontal1dHeatmapTrack.js +1 -1
  36. package/app/scripts/Horizontal2DDomainsTrack.js +1 -1
  37. package/app/scripts/HorizontalChromosomeLabels.js +28 -22
  38. package/app/scripts/HorizontalGeneAnnotationsTrack.js +1 -1
  39. package/app/scripts/HorizontalHeatmapTrack.js +2 -2
  40. package/app/scripts/HorizontalMultivecTrack.js +6 -7
  41. package/app/scripts/HorizontalRule.js +1 -2
  42. package/app/scripts/HorizontalTiled1DPixiTrack.js +4 -4
  43. package/app/scripts/HorizontalTiledPlot.jsx +9 -9
  44. package/app/scripts/LeftTrackModifier.js +4 -0
  45. package/app/scripts/ListWrapper.jsx +1 -2
  46. package/app/scripts/MapboxTilesTrack.js +1 -2
  47. package/app/scripts/Modal.jsx +2 -2
  48. package/app/scripts/MoveableTrack.jsx +10 -12
  49. package/app/scripts/NestedContextMenu.jsx +2 -1
  50. package/app/scripts/OSMTileIdsTrack.js +1 -1
  51. package/app/scripts/OverlayTrack.js +4 -4
  52. package/app/scripts/PixiTrack.js +27 -13
  53. package/app/scripts/PlotTypeChooser.jsx +3 -4
  54. package/app/scripts/SearchField.js +5 -5
  55. package/app/scripts/SeriesListItems.jsx +3 -4
  56. package/app/scripts/SeriesListMenu.jsx +6 -11
  57. package/app/scripts/SeriesListSubmenuMixin.jsx +1 -1
  58. package/app/scripts/SketchInlinePicker.jsx +2 -2
  59. package/app/scripts/SortableList.jsx +1 -1
  60. package/app/scripts/Tiled1DPixiTrack.js +5 -1
  61. package/app/scripts/TiledPixiTrack.js +232 -99
  62. package/app/scripts/TiledPlot.jsx +33 -43
  63. package/app/scripts/TilesetFinder.jsx +12 -4
  64. package/app/scripts/Track.js +1 -1
  65. package/app/scripts/TrackArea.jsx +4 -0
  66. package/app/scripts/TrackControl.jsx +2 -2
  67. package/app/scripts/TrackRenderer.jsx +30 -31
  68. package/app/scripts/ValueIntervalTrack.js +1 -1
  69. package/app/scripts/VerticalRule.js +2 -2
  70. package/app/scripts/VerticalTiledPlot.jsx +7 -7
  71. package/app/scripts/ViewConfigEditor.jsx +1 -1
  72. package/app/scripts/ViewContextMenu.jsx +4 -4
  73. package/app/scripts/ViewHeader.jsx +6 -7
  74. package/app/scripts/ViewportTracker2D.js +1 -1
  75. package/app/scripts/api.js +5 -6
  76. package/app/scripts/configs/available-track-types.js +1 -1
  77. package/app/scripts/configs/positions-by-datatype.js +2 -2
  78. package/app/scripts/configs/themes.js +0 -1
  79. package/app/scripts/configs/tracks-info-by-type.js +11 -8
  80. package/app/scripts/configs/tracks-info.js +2 -2
  81. package/app/scripts/d3-context-menu.js +3 -4
  82. package/app/scripts/data-fetchers/DataFetcher.js +35 -36
  83. package/app/scripts/data-fetchers/genbank-fetcher.js +6 -10
  84. package/app/scripts/data-fetchers/local-tile-fetcher.js +2 -6
  85. package/app/scripts/hglib.jsx +1 -1
  86. package/app/scripts/hocs/with-modal.jsx +32 -10
  87. package/app/scripts/hocs/with-pub-sub.js +12 -3
  88. package/app/scripts/hocs/with-theme.jsx +21 -14
  89. package/app/scripts/icons.jsx +3 -2
  90. package/app/scripts/mixwith.js +2 -2
  91. package/app/scripts/plugins/get-data-fetcher.js +2 -3
  92. package/app/scripts/services/chrom-info.js +32 -4
  93. package/app/scripts/services/element-resize-listener.js +2 -2
  94. package/app/scripts/services/index.js +0 -1
  95. package/app/scripts/services/tile-proxy.js +368 -281
  96. package/app/scripts/services/worker.js +30 -28
  97. package/app/scripts/test-helpers/test-helpers.jsx +3 -3
  98. package/app/scripts/types.ts +50 -44
  99. package/app/scripts/utils/LruCache.js +3 -2
  100. package/app/scripts/utils/assert.js +19 -0
  101. package/app/scripts/utils/background-task-scheduler.js +2 -0
  102. package/app/scripts/utils/color-domain-to-rgba-array.js +13 -3
  103. package/app/scripts/utils/dict-items.js +1 -0
  104. package/app/scripts/utils/dict-keys.js +1 -0
  105. package/app/scripts/utils/dict-values.js +1 -0
  106. package/app/scripts/utils/expand-combined-tracks.js +11 -7
  107. package/app/scripts/utils/fill-in-min-widths.js +47 -21
  108. package/app/scripts/utils/flatten.js +0 -1
  109. package/app/scripts/utils/get-aggregation-function.js +1 -1
  110. package/app/scripts/utils/get-default-track-for-datatype.js +36 -10
  111. package/app/scripts/utils/get-higlass-components.js +27 -3
  112. package/app/scripts/utils/get-track-position-by-uid.js +8 -1
  113. package/app/scripts/utils/get-xylofon.js +12 -9
  114. package/app/scripts/utils/has-parent.js +5 -5
  115. package/app/scripts/utils/hex-string-to-int.js +1 -1
  116. package/app/scripts/utils/interval-tree.js +222 -177
  117. package/app/scripts/utils/load-chrom-infos.js +4 -1
  118. package/app/scripts/utils/pixi-text-to-svg.js +5 -9
  119. package/app/scripts/utils/range-query-2d.js +3 -3
  120. package/app/scripts/utils/reduce.js +12 -5
  121. package/app/scripts/utils/segments-to-rows.js +14 -11
  122. package/app/scripts/utils/show-mouse-position.js +16 -0
  123. package/app/scripts/utils/svg-line.js +7 -8
  124. package/app/scripts/utils/type-guards.js +16 -7
  125. package/app/scripts/utils/visit-positioned-tracks.js +7 -5
  126. package/app/styles/d3-context-menu.css +0 -1
  127. package/app/styles/prism.css +1 -0
  128. package/dist/hglib.js +78064 -77770
  129. package/dist/hglib.min.js +109 -109
  130. package/dist/higlass.mjs +82736 -82442
  131. package/package.json +13 -18
@@ -1,15 +1,43 @@
1
- // @ts-nocheck
2
1
  // Configs
3
2
  import { DEFAULT_TRACKS_FOR_DATATYPE } from '../configs';
4
3
 
4
+ /** @typedef {typeof DEFAULT_TRACKS_FOR_DATATYPE} DataTypeMapping */
5
+ /** @typedef {keyof DataTypeMapping} DataType */
6
+ /** @typedef {"top" | "bottom" | "left" | "right" | "center"} TrackPosition */
7
+
8
+ /**
9
+ * @template {string} D
10
+ * @template {string} P
11
+ * @typedef {D extends DataType ? P extends keyof DataTypeMapping[D] ? DataTypeMapping[D][P] : undefined : undefined} ExtractDataType
12
+ */
13
+
14
+ /**
15
+ * @template {DataType | string & {}} D
16
+ * @template {TrackPosition} P
17
+ *
18
+ * @param {D} datatype
19
+ * @param {P} position
20
+ * @returns {ExtractDataType<D, P>}
21
+ */
22
+ function findDefaultTrackType(datatype, position) {
23
+ // @ts-expect-error - ok with undefined check
24
+ return DEFAULT_TRACKS_FOR_DATATYPE[datatype] !== undefined
25
+ ? // @ts-expect-error - ok with undefined check
26
+ DEFAULT_TRACKS_FOR_DATATYPE[datatype][position]
27
+ : undefined;
28
+ }
29
+
5
30
  /**
6
31
  * Gets the default track as defined in utils/default-tracks-for-datatype.js
7
32
  *
8
- * @param {string} datatype The datatype to get the default track for
9
- * @param {string} position top, bottom, left, right, center
10
- * @param {array} availableTracks list of tracks to choose from,
11
- * typically obtained from AVAILABLE_TRACK_TYPES(...)
12
- * @return {object} an element of availableTracks or undefined
33
+ * @template {DataType | string & {}} D
34
+ * @template {TrackPosition} P
35
+ * @template {ReadonlyArray<{ type: string }>} ATracks
36
+ *
37
+ * @param {D} datatype - The datatype to get the default track for
38
+ * @param {P} position - top, bottom, left, right, center
39
+ * @param {ATracks} availableTracks - List of tracks to choose from, typically obtained from AVAILABLE_TRACK_TYPES(...)
40
+ * @return {ATracks[number] | undefined} An element of availableTracks or undefined
13
41
  */
14
42
  const getDefaultTrackForDatatype = (datatype, position, availableTracks) => {
15
43
  if (availableTracks.length === 0) {
@@ -21,10 +49,8 @@ const getDefaultTrackForDatatype = (datatype, position, availableTracks) => {
21
49
  }
22
50
 
23
51
  let usedTrack = availableTracks[0];
24
- const defaultTrackType =
25
- DEFAULT_TRACKS_FOR_DATATYPE[datatype] !== undefined
26
- ? DEFAULT_TRACKS_FOR_DATATYPE[datatype][position]
27
- : undefined;
52
+
53
+ const defaultTrackType = findDefaultTrackType(datatype, position);
28
54
 
29
55
  if (defaultTrackType !== undefined) {
30
56
  // If we found a default track type for this datatype,
@@ -1,19 +1,43 @@
1
- // @ts-nocheck
1
+ /** @import * as t from '../types' */
2
+ /** @import HiGlassComponent from '../HiGlassComponent' */
3
+ /** @import { TrackRenderer } from '../TrackRenderer' */
4
+ /** @import { TiledPlot } from '../TiledPlot' */
5
+
6
+ /**
7
+ * @param {HiGlassComponent} hgc
8
+ * @param {string} viewUid
9
+ * @param {string | undefined} trackUid
10
+ * @returns {t.TrackObject | undefined}
11
+ */
2
12
  export const getTrackObjectFromHGC = (hgc, viewUid, trackUid) => {
13
+ /** @type {string} */
3
14
  let newViewUid = viewUid;
4
- let newTrackUid = trackUid;
15
+ /** @type {string} */
16
+ let newTrackUid;
5
17
 
6
18
  if (!trackUid) {
7
19
  // didn't specify a trackUid so use the viewUid as the trackUid
8
20
  // and use the first plot
9
21
  newTrackUid = viewUid;
10
22
  newViewUid = Object.values(hgc.state.views)[0].uid;
23
+ } else {
24
+ newTrackUid = trackUid;
11
25
  }
12
26
 
13
- return hgc.tiledPlots[newViewUid].trackRenderer.getTrackObject(newTrackUid);
27
+ return hgc.tiledPlots[newViewUid].trackRenderer?.getTrackObject(newTrackUid);
14
28
  };
15
29
 
30
+ /**
31
+ * @param {HiGlassComponent} hgc
32
+ * @param {string} viewUid
33
+ * @returns {TrackRenderer | null}
34
+ */
16
35
  export const getTrackRenderer = (hgc, viewUid) =>
17
36
  hgc.tiledPlots[viewUid].trackRenderer;
18
37
 
38
+ /**
39
+ * @param {HiGlassComponent} hgc
40
+ * @param {string} viewUid
41
+ * @returns {TiledPlot}
42
+ */
19
43
  export const getTiledPlot = (hgc, viewUid) => hgc.tiledPlots[viewUid];
@@ -1,10 +1,17 @@
1
- // @ts-nocheck
2
1
  import visitPositionedTracks from './visit-positioned-tracks';
3
2
 
3
+ /** @import { TrackPosition } from '../types' */
4
+ /** @import { PositionedTracks } from './visit-positioned-tracks' */
5
+
4
6
  /**
5
7
  * Get a track's orientation by its UID.
8
+ *
9
+ * @param {PositionedTracks} positionedTracks
10
+ * @param {string} uid
11
+ * @returns {TrackPosition | null}
6
12
  */
7
13
  const getTrackPositionByUid = (positionedTracks, uid) => {
14
+ /** @type {TrackPosition | null} */
8
15
  let position = null;
9
16
 
10
17
  visitPositionedTracks(positionedTracks, (track, trackPosition) => {
@@ -1,13 +1,16 @@
1
- // @ts-nocheck
2
- /* global XYLOPHON:false */
3
-
4
1
  import map from './map';
5
2
 
6
- const getXylofon = () => [
7
- window,
8
- map((c) => c.charCodeAt(0))(XYLOPHON)
9
- .map((number) => (number <= 999 ? `00${number}`.slice(-3) : number))
10
- .join(''),
11
- ];
3
+ // Trevor(2025-02-18): Really not sure what the purpose of this module is.
4
+
5
+ const getXylofon = () =>
6
+ /** @type {const} */ ([
7
+ window,
8
+ map((c) => c.charCodeAt(0))(
9
+ // @ts-expect-error - A global added by `vite.config.js`.
10
+ XYLOPHON,
11
+ )
12
+ .map((number) => (number <= 999 ? `00${number}`.slice(-3) : number))
13
+ .join(''),
14
+ ]);
12
15
 
13
16
  export default getXylofon;
@@ -1,16 +1,16 @@
1
- // @ts-nocheck
2
1
  /**
3
2
  * Test whether a DOM element is the parent of another DOM element.
4
3
  *
5
- * @param {object} el - Potential child element.
6
- * @param {object} target - Target parent element which is tested to have `el`
7
- * as a child.
8
- * @return {Boolean} If `true` `el` has `target` as a parent.
4
+ * @param {HTMLElement} el - Potential child element.
5
+ * @param {HTMLElement} target - Target parent element which is tested to have `el` as a child.
6
+ * @return {boolean} If `true` `el` has `target` as a parent.
9
7
  */
10
8
  const hasParent = (el, target) => {
9
+ /** @type {HTMLElement | null} */
11
10
  let _el = el;
12
11
 
13
12
  while (_el && _el !== target && _el.tagName !== 'HTML') {
13
+ // @ts-expect-error - we know ParentElement is also DOM or null
14
14
  _el = _el.parentNode;
15
15
  }
16
16
 
@@ -10,6 +10,6 @@
10
10
  * @param {string} str - HEX string
11
11
  * @return {number} An (integer) HEX number
12
12
  */
13
- const hexStrToInt = (str) => parseInt(str.replace(/^#/, ''), 16);
13
+ const hexStrToInt = (str) => Number.parseInt(str.replace(/^#/, ''), 16);
14
14
 
15
15
  export default hexStrToInt;
@@ -1,47 +1,221 @@
1
- // @ts-nocheck
2
- function IntervalTreeNode(start, end, left, right) {
1
+ /** @typedef {[start: number, end: number]} Interval */
2
+
3
+ class IntervalTreeNode {
3
4
  /**
4
- * Node interval.
5
- * @member {Array}
5
+ * @param {number} start
6
+ * @param {number} end
7
+ * @param {IntervalTreeNode} [left]
8
+ * @param {IntervalTreeNode} [right]
6
9
  */
7
- this.interval = [start, end];
10
+ constructor(start, end, left, right) {
11
+ /**
12
+ * Node interval.
13
+ * @type {Interval}
14
+ */
15
+ this.interval = [start, end];
16
+ /**
17
+ * Max endpoint in subtree which starts from this node.
18
+ * @type {number}
19
+ */
20
+ this.max = Number.NEGATIVE_INFINITY;
21
+ /**
22
+ * Parent node.
23
+ * @type {IntervalTreeNode | null}
24
+ */
25
+ this.parentNode = null;
26
+ /**
27
+ * Left child node.
28
+ * @type {IntervalTreeNode | null}
29
+ */
30
+ this.left = left ?? null;
31
+ /**
32
+ * Right child node.
33
+ * @type {IntervalTreeNode | null}
34
+ */
35
+ this.right = right ?? null;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Interval tree.
41
+ *
42
+ * @public
43
+ * @constructor
44
+ */
45
+ export class IntervalTree {
46
+ constructor() {
47
+ /**
48
+ * Root node of the tree.
49
+ * @type {IntervalTreeNode | null}
50
+ */
51
+ this.root = null;
52
+ }
8
53
  /**
9
- * Max endpoint in subtree which starts from this node.
10
- * @member {Number}
54
+ * Add new interval to the tree.
55
+ *
56
+ * @public
57
+ * @param {Interval} interval - Array with start and end points of the interval.
11
58
  */
12
- this.max = -Infinity;
59
+ add(interval) {
60
+ if (!this.root) {
61
+ this.root = new IntervalTreeNode(interval[0], interval[1]);
62
+ this.root.max = interval[1];
63
+ return;
64
+ }
65
+ addHelper(this.root, interval);
66
+ }
13
67
  /**
14
- * Parent node.
15
- * @member {IntervalTreeNode}
68
+ * Checks or point belongs to at least one intarval from the tree.<br><br>
69
+ * Complexity: O(log N).
70
+ *
71
+ * @public
72
+ * @method
73
+ * @param {Number} point Point which should be checked.
74
+ * @return {Boolean} True if point belongs to one of the intervals.
16
75
  */
17
- this.parentNode = null;
76
+ contains(point) {
77
+ return contains(point, this.root);
78
+ }
18
79
  /**
19
- * Left child node.
20
- * @member {IntervalTreeNode}
80
+ * Checks or interval belongs to at least one intarval from the tree.<br><br>
81
+ * Complexity: O(log N).
82
+ *
83
+ * @public
84
+ * @method
85
+ * @param {Interval} interval Interval which should be checked.
86
+ * @return {boolean} True if interval intersects with one of the intervals.
21
87
  */
22
- this.left = left;
88
+ intersects(interval) {
89
+ return intersectsHelper(interval, this.root);
90
+ }
23
91
  /**
24
- * Right child node.
25
- * @member {IntervalTreeNode}
92
+ * Returns height of the tree.
93
+ *
94
+ * @public
95
+ * @method
96
+ * @return {Number} Height of the tree.
26
97
  */
27
- this.right = right;
28
- }
98
+ height() {
99
+ return heightHelper(this.root);
100
+ }
101
+ /**
102
+ * Returns node with the max endpoint in subtree.
103
+ *
104
+ * @public
105
+ * @method
106
+ * @param {IntervalTreeNode} node Root node of subtree.
107
+ * @return {IntervalTreeNode | null} IntervalTreeNode with the largest endpoint.
108
+ */
109
+ findMax(node) {
110
+ const stack = [node];
111
+ let current;
112
+ let max = Number.NEGATIVE_INFINITY;
113
+ let maxNode;
114
+ while (stack.length) {
115
+ current = stack.pop();
116
+ if (current?.left) {
117
+ stack.push(current.left);
118
+ }
119
+ if (current?.right) {
120
+ stack.push(current.right);
121
+ }
122
+ // @ts-expect-error - ok assertion
123
+ if (current?.interval[1] > max) {
124
+ // @ts-expect-error - only ok if above assertion succeeds
125
+ max = current.interval[1];
126
+ maxNode = current;
127
+ }
128
+ }
129
+ return maxNode ?? null;
130
+ }
29
131
 
30
- /**
31
- * Interval tree.
32
- *
33
- * @public
34
- * @constructor
35
- */
36
- export default function IntervalTree() {
37
132
  /**
38
- * Root node of the tree.
39
- * @member {IntervalTreeNode}
133
+ * Adjust the max value.
134
+ *
135
+ * @param {Interval} interval
136
+ * @param {IntervalTreeNode | null} node
40
137
  */
41
- this.root = null;
138
+ _removeHelper(interval, node) {
139
+ if (!node) {
140
+ return;
141
+ }
142
+ if (node.interval[0] === interval[0] && node.interval[1] === interval[1]) {
143
+ // When left and right children exists
144
+ if (node.left && node.right) {
145
+ let replacement = node.left;
146
+ while (replacement.left) {
147
+ replacement = replacement.left;
148
+ }
149
+ const temp = replacement.interval;
150
+ replacement.interval = node.interval;
151
+ node.interval = temp;
152
+ this._removeHelper(replacement.interval, node);
153
+ } else {
154
+ // When only left or right child exists
155
+ /** @type {"left" | "right"} */
156
+ let side = 'left';
157
+ if (node.right) {
158
+ side = 'right';
159
+ }
160
+ const parentNode = node.parentNode;
161
+ if (parentNode) {
162
+ if (parentNode.left === node) {
163
+ parentNode.left = node[side];
164
+ } else {
165
+ parentNode.right = node[side];
166
+ }
167
+ if (node[side]) {
168
+ // @ts-expect-error - ok to set to a node
169
+ node[side].parentNode = parentNode;
170
+ }
171
+ } else {
172
+ this.root = node[side];
173
+ // last node removed
174
+ if (this.root) {
175
+ this.root.parentNode = null;
176
+ }
177
+ }
178
+ }
179
+ // Adjust the max value
180
+ const p = node.parentNode;
181
+ if (p) {
182
+ let maxNode = this.findMax(p);
183
+ const max = maxNode?.interval[1] ?? Number.NEGATIVE_INFINITY;
184
+ while (maxNode) {
185
+ if (maxNode.max === node.interval[1]) {
186
+ maxNode.max = max;
187
+ maxNode = maxNode.parentNode;
188
+ } else {
189
+ maxNode = null;
190
+ }
191
+ }
192
+ }
193
+ } else {
194
+ // could be optimized
195
+ this._removeHelper(interval, node.left);
196
+ this._removeHelper(interval, node.right);
197
+ }
198
+ }
199
+ /**
200
+ * Remove interval from the tree.
201
+ *
202
+ * @public
203
+ * @method
204
+ * @param {Interval} interval - Array with start and end of the interval.
205
+ */
206
+ remove(interval) {
207
+ return this._removeHelper(interval, this.root);
208
+ }
42
209
  }
43
210
 
211
+ /**
212
+ * @param {IntervalTreeNode} node
213
+ * @param {"left"| "right"} side
214
+ * @param {Interval} interval
215
+ * @returns {void}
216
+ */
44
217
  function addNode(node, side, interval) {
218
+ /** @type {IntervalTreeNode | null} */
45
219
  let child = new IntervalTreeNode(interval[0], interval[1]);
46
220
  child.max = interval[1];
47
221
  child.parentNode = node;
@@ -56,6 +230,11 @@ function addNode(node, side, interval) {
56
230
  }
57
231
  }
58
232
 
233
+ /**
234
+ * @param {IntervalTreeNode} node
235
+ * @param {Interval} interval
236
+ * @returns {void}
237
+ */
59
238
  function addHelper(node, interval) {
60
239
  if (node.interval[0] > interval[0]) {
61
240
  if (node.left) {
@@ -71,20 +250,10 @@ function addHelper(node, interval) {
71
250
  }
72
251
 
73
252
  /**
74
- * Add new interval to the tree.
75
- *
76
- * @public
77
- * @param {Array} intreval Array with start and end points of the interval.
253
+ * @param {number} point
254
+ * @param {IntervalTreeNode | null} node
255
+ * @returns {boolean}
78
256
  */
79
- IntervalTree.prototype.add = function add(interval) {
80
- if (!this.root) {
81
- this.root = new IntervalTreeNode(interval[0], interval[1]);
82
- this.root.max = interval[1];
83
- return;
84
- }
85
- addHelper(this.root, interval);
86
- };
87
-
88
257
  function contains(point, node) {
89
258
  if (!node) {
90
259
  return false;
@@ -94,7 +263,7 @@ function contains(point, node) {
94
263
  }
95
264
  let result = false;
96
265
  let temp;
97
- ['left', 'right'].forEach((key) => {
266
+ /** @type {const} */ (['left', 'right']).forEach((key) => {
98
267
  temp = node[key];
99
268
  if (temp) {
100
269
  if (temp.max > point) {
@@ -106,18 +275,10 @@ function contains(point, node) {
106
275
  }
107
276
 
108
277
  /**
109
- * Checks or point belongs to at least one intarval from the tree.<br><br>
110
- * Complexity: O(log N).
111
- *
112
- * @public
113
- * @method
114
- * @param {Number} point Point which should be checked.
115
- * @return {Boolean} True if point belongs to one of the intervals.
278
+ * @param {Interval} a
279
+ * @param {Interval} b
280
+ * @returns {boolean}
116
281
  */
117
- IntervalTree.prototype.contains = function _contains(point) {
118
- return contains(point, this.root);
119
- };
120
-
121
282
  function intersects(a, b) {
122
283
  return (
123
284
  // The first case checks for completely overlapping
@@ -132,6 +293,11 @@ function intersects(a, b) {
132
293
  );
133
294
  }
134
295
 
296
+ /**
297
+ * @param {Interval} interval
298
+ * @param {IntervalTreeNode | null} node
299
+ * @returns {boolean}
300
+ */
135
301
  function intersectsHelper(interval, node) {
136
302
  if (!node) {
137
303
  return false;
@@ -141,7 +307,7 @@ function intersectsHelper(interval, node) {
141
307
  }
142
308
  let result = false;
143
309
  let temp;
144
- ['left', 'right'].forEach((side) => {
310
+ /** @type {const} */ (['left', 'right']).forEach((side) => {
145
311
  temp = node[side];
146
312
  if (temp && temp.max >= interval[0]) {
147
313
  result = result || intersectsHelper(interval, temp);
@@ -151,133 +317,12 @@ function intersectsHelper(interval, node) {
151
317
  }
152
318
 
153
319
  /**
154
- * Checks or interval belongs to at least one intarval from the tree.<br><br>
155
- * Complexity: O(log N).
156
- *
157
- * @public
158
- * @method
159
- * @param {Array} interval Interval which should be checked.
160
- * @return {Boolean} True if interval intersects with one of the intervals.
320
+ * @param {IntervalTreeNode | null} node
321
+ * @returns {number}
161
322
  */
162
- IntervalTree.prototype.intersects = function _intersects(interval) {
163
- return intersectsHelper(interval, this.root);
164
- };
165
-
166
323
  function heightHelper(node) {
167
324
  if (!node) {
168
325
  return 0;
169
326
  }
170
327
  return 1 + Math.max(heightHelper(node.left), heightHelper(node.right));
171
328
  }
172
-
173
- /**
174
- * Returns height of the tree.
175
- *
176
- * @public
177
- * @method
178
- * @return {Number} Height of the tree.
179
- */
180
- IntervalTree.prototype.height = function height() {
181
- return heightHelper(this.root);
182
- };
183
-
184
- /**
185
- * Returns node with the max endpoint in subtree.
186
- *
187
- * @public
188
- * @method
189
- * @param {IntervalTreeNode} node Root node of subtree.
190
- * @return {IntervalTreeNode} IntervalTreeNode with the largest endpoint.
191
- */
192
- IntervalTree.prototype.findMax = function findMax(node) {
193
- const stack = [node];
194
- let current;
195
- let max = -Infinity;
196
- let maxNode;
197
- while (stack.length) {
198
- current = stack.pop();
199
- if (current.left) {
200
- stack.push(current.left);
201
- }
202
- if (current.right) {
203
- stack.push(current.right);
204
- }
205
- if (current.interval[1] > max) {
206
- max = current.interval[1];
207
- maxNode = current;
208
- }
209
- }
210
- return maxNode;
211
- };
212
-
213
- // adjust the max value
214
- IntervalTree.prototype._removeHelper = function _removeHelper(interval, node) {
215
- if (!node) {
216
- return;
217
- }
218
- if (node.interval[0] === interval[0] && node.interval[1] === interval[1]) {
219
- // When left and right children exists
220
- if (node.left && node.right) {
221
- let replacement = node.left;
222
- while (replacement.left) {
223
- replacement = replacement.left;
224
- }
225
- const temp = replacement.interval;
226
- replacement.interval = node.interval;
227
- node.interval = temp;
228
- this._removeHelper(replacement.interval, node);
229
- } else {
230
- // When only left or right child exists
231
- let side = 'left';
232
- if (node.right) {
233
- side = 'right';
234
- }
235
- const parentNode = node.parentNode;
236
- if (parentNode) {
237
- if (parentNode.left === node) {
238
- parentNode.left = node[side];
239
- } else {
240
- parentNode.right = node[side];
241
- }
242
- if (node[side]) {
243
- node[side].parentNode = parentNode;
244
- }
245
- } else {
246
- this.root = node[side];
247
- // last node removed
248
- if (this.root) {
249
- this.root.parentNode = null;
250
- }
251
- }
252
- }
253
- // Adjust the max value
254
- const p = node.parentNode;
255
- if (p) {
256
- let maxNode = this.findMax(p);
257
- const max = maxNode.interval[1];
258
- while (maxNode) {
259
- if (maxNode.max === node.interval[1]) {
260
- maxNode.max = max;
261
- maxNode = maxNode.parentNode;
262
- } else {
263
- maxNode = false;
264
- }
265
- }
266
- }
267
- } else {
268
- // could be optimized
269
- this._removeHelper(interval, node.left);
270
- this._removeHelper(interval, node.right);
271
- }
272
- };
273
-
274
- /**
275
- * Remove interval from the tree.
276
- *
277
- * @public
278
- * @method
279
- * @param {Array} intreval Array with start and end of the interval.
280
- */
281
- IntervalTree.prototype.remove = function remove(interval) {
282
- return this._removeHelper(interval, this.root);
283
- };
@@ -1,8 +1,11 @@
1
- // @ts-nocheck
2
1
  import { chromInfo } from '../services';
3
2
 
4
3
  import objVals from './obj-vals';
5
4
 
5
+ /**
6
+ * @param {Record<string, { chromInfoPath: string }>} views
7
+ * @returns {void}
8
+ */
6
9
  const loadChromInfos = (views) =>
7
10
  objVals(views)
8
11
  .map((view) => view.chromInfoPath)