higlass 1.13.5 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) 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 +11 -4
  5. package/app/scripts/AddTrackPositionMenu.jsx +28 -7
  6. package/app/scripts/Annotations1dTrack.js +90 -251
  7. package/app/scripts/Annotations2dTrack.js +12 -7
  8. package/app/scripts/Autocomplete.jsx +13 -28
  9. package/app/scripts/AxisPixi.js +6 -10
  10. package/app/scripts/BarTrack.js +3 -3
  11. package/app/scripts/BedLikeTrack.js +556 -449
  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 +4 -2
  23. package/app/scripts/ContextMenuItem.jsx +14 -2
  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/FilledLine.js +349 -0
  31. package/app/scripts/GalleryTracks.jsx +77 -78
  32. package/app/scripts/GenomePositionSearchBox.jsx +184 -482
  33. package/app/scripts/HeatmapOptions.jsx +4 -2
  34. package/app/scripts/HeatmapTiledPixiTrack.js +23 -32
  35. package/app/scripts/HiGlassComponent.jsx +515 -444
  36. package/app/scripts/HiGlassComponentContext.js +5 -0
  37. package/app/scripts/Horizontal1dHeatmapTrack.js +1 -1
  38. package/app/scripts/Horizontal2DDomainsTrack.js +1 -1
  39. package/app/scripts/HorizontalChromosomeLabels.js +28 -22
  40. package/app/scripts/HorizontalGeneAnnotationsTrack.js +1 -1
  41. package/app/scripts/HorizontalHeatmapTrack.js +2 -2
  42. package/app/scripts/HorizontalMultivecTrack.js +6 -7
  43. package/app/scripts/HorizontalRule.js +1 -2
  44. package/app/scripts/HorizontalTiled1DPixiTrack.js +4 -4
  45. package/app/scripts/HorizontalTiledPlot.jsx +9 -9
  46. package/app/scripts/LeftTrackModifier.js +4 -0
  47. package/app/scripts/ListWrapper.jsx +1 -2
  48. package/app/scripts/MapboxTilesTrack.js +1 -2
  49. package/app/scripts/Modal.jsx +2 -2
  50. package/app/scripts/MoveableTrack.jsx +10 -12
  51. package/app/scripts/NestedContextMenu.jsx +2 -1
  52. package/app/scripts/OSMTileIdsTrack.js +1 -1
  53. package/app/scripts/OverlayTrack.js +4 -4
  54. package/app/scripts/PixiTrack.js +27 -13
  55. package/app/scripts/PlotTypeChooser.jsx +3 -4
  56. package/app/scripts/SearchField.js +5 -5
  57. package/app/scripts/SeriesListItems.jsx +3 -4
  58. package/app/scripts/SeriesListMenu.jsx +95 -53
  59. package/app/scripts/SeriesListSubmenuMixin.jsx +2 -1
  60. package/app/scripts/SketchInlinePicker.jsx +2 -2
  61. package/app/scripts/SortableList.jsx +1 -1
  62. package/app/scripts/Tiled1DPixiTrack.js +4 -1
  63. package/app/scripts/TiledPixiTrack.js +244 -102
  64. package/app/scripts/TiledPlot.jsx +565 -118
  65. package/app/scripts/TilesetFinder.jsx +12 -4
  66. package/app/scripts/Track.js +1 -1
  67. package/app/scripts/TrackArea.jsx +4 -0
  68. package/app/scripts/TrackControl.jsx +2 -2
  69. package/app/scripts/TrackRenderer.jsx +32 -33
  70. package/app/scripts/ValueIntervalTrack.js +1 -1
  71. package/app/scripts/VerticalRule.js +2 -2
  72. package/app/scripts/VerticalTiledPlot.jsx +7 -7
  73. package/app/scripts/ViewConfigEditor.jsx +1 -1
  74. package/app/scripts/ViewContextMenu.jsx +53 -5
  75. package/app/scripts/ViewHeader.jsx +9 -9
  76. package/app/scripts/ViewportTracker2D.js +1 -1
  77. package/app/scripts/api.js +92 -12
  78. package/app/scripts/configs/available-track-types.js +1 -1
  79. package/app/scripts/configs/index.js +6 -1
  80. package/app/scripts/configs/positions-by-datatype.js +2 -2
  81. package/app/scripts/configs/primitives.js +2 -0
  82. package/app/scripts/configs/themes.js +0 -1
  83. package/app/scripts/configs/tracks-info-by-type.js +11 -8
  84. package/app/scripts/configs/tracks-info.js +3 -2
  85. package/app/scripts/d3-context-menu.js +3 -4
  86. package/app/scripts/data-fetchers/DataFetcher.js +35 -36
  87. package/app/scripts/data-fetchers/genbank-fetcher.js +13 -22
  88. package/app/scripts/data-fetchers/local-tile-fetcher.js +10 -8
  89. package/app/scripts/hglib.jsx +62 -71
  90. package/app/scripts/hocs/with-modal.jsx +32 -10
  91. package/app/scripts/hocs/with-pub-sub.js +12 -3
  92. package/app/scripts/hocs/with-theme.jsx +21 -14
  93. package/app/scripts/icons.jsx +3 -2
  94. package/app/scripts/mixwith.js +2 -2
  95. package/app/scripts/options-info.js +49 -11
  96. package/app/scripts/plugins/get-data-fetcher.js +2 -3
  97. package/app/scripts/services/chrom-info.js +32 -4
  98. package/app/scripts/services/element-resize-listener.js +2 -2
  99. package/app/scripts/services/index.js +0 -1
  100. package/app/scripts/services/tile-proxy.js +368 -285
  101. package/app/scripts/services/worker.js +31 -28
  102. package/app/scripts/test-helpers/index.js +2 -1
  103. package/app/scripts/test-helpers/test-helpers.jsx +157 -69
  104. package/app/scripts/types.ts +118 -47
  105. package/app/scripts/utils/LruCache.js +3 -2
  106. package/app/scripts/utils/assert.js +19 -0
  107. package/app/scripts/utils/background-task-scheduler.js +2 -0
  108. package/app/scripts/utils/color-domain-to-rgba-array.js +13 -3
  109. package/app/scripts/utils/copy-text-to-clipboard.js +36 -0
  110. package/app/scripts/utils/decompress.js +33 -0
  111. package/app/scripts/utils/default-tracks.js +46 -0
  112. package/app/scripts/utils/dict-items.js +1 -0
  113. package/app/scripts/utils/dict-keys.js +1 -0
  114. package/app/scripts/utils/dict-values.js +1 -0
  115. package/app/scripts/utils/expand-combined-tracks.js +11 -7
  116. package/app/scripts/utils/fill-in-min-widths.js +47 -21
  117. package/app/scripts/utils/flatten.js +0 -1
  118. package/app/scripts/utils/get-aggregation-function.js +1 -1
  119. package/app/scripts/utils/get-default-track-for-datatype.js +37 -10
  120. package/app/scripts/utils/get-default-tracks-for-datatype.ts +46 -0
  121. package/app/scripts/utils/get-higlass-components.js +27 -3
  122. package/app/scripts/utils/get-track-position-by-uid.js +8 -1
  123. package/app/scripts/utils/get-xylofon.js +12 -9
  124. package/app/scripts/utils/has-parent.js +5 -5
  125. package/app/scripts/utils/hex-string-to-int.js +1 -1
  126. package/app/scripts/utils/index.js +1 -0
  127. package/app/scripts/utils/interval-tree.js +222 -177
  128. package/app/scripts/utils/load-chrom-infos.js +4 -1
  129. package/app/scripts/utils/pixi-text-to-svg.js +5 -9
  130. package/app/scripts/utils/positioned-tracks-to-all-tracks.js +55 -0
  131. package/app/scripts/utils/range-query-2d.js +3 -3
  132. package/app/scripts/utils/reduce.js +12 -5
  133. package/app/scripts/utils/segments-to-rows.js +14 -11
  134. package/app/scripts/utils/svg-line.js +7 -8
  135. package/app/scripts/utils/type-guards.js +16 -7
  136. package/app/scripts/utils/visit-positioned-tracks.js +9 -4
  137. package/app/styles/AddTrackPositionMenu.module.scss +37 -0
  138. package/app/styles/HiGlass.module.scss +3 -1
  139. package/app/styles/d3-context-menu.css +0 -1
  140. package/app/styles/prism.css +1 -0
  141. package/dist/app/schema.json +525 -0
  142. package/dist/app/scripts/AddTrackDialog.d.ts +64 -0
  143. package/dist/app/scripts/AddTrackPositionMenu.d.ts +5 -0
  144. package/dist/app/scripts/Annotations1dTrack.d.ts +15 -0
  145. package/dist/app/scripts/Annotations2dTrack.d.ts +95 -0
  146. package/dist/app/scripts/ArrowheadDomainsTrack.d.ts +36 -0
  147. package/dist/app/scripts/Autocomplete.d.ts +102 -0
  148. package/dist/app/scripts/AxisPixi.d.ts +25 -0
  149. package/dist/app/scripts/BarTrack.d.ts +28 -0
  150. package/dist/app/scripts/BedLikeTrack.d.ts +84 -0
  151. package/dist/app/scripts/Button.d.ts +3 -0
  152. package/dist/app/scripts/CNVIntervalTrack.d.ts +12 -0
  153. package/dist/app/scripts/CenterTiledPlot.d.ts +3 -0
  154. package/dist/app/scripts/CenterTrack.d.ts +92 -0
  155. package/dist/app/scripts/Chromosome2DAnnotations.d.ts +10 -0
  156. package/dist/app/scripts/Chromosome2DLabels.d.ts +13 -0
  157. package/dist/app/scripts/ChromosomeGrid.d.ts +24 -0
  158. package/dist/app/scripts/ChromosomeInfo.d.ts +14 -0
  159. package/dist/app/scripts/CloseTrackMenu.d.ts +10 -0
  160. package/dist/app/scripts/CombinedTrack.d.ts +32 -0
  161. package/dist/app/scripts/ConfigTrackMenu.d.ts +10 -0
  162. package/dist/app/scripts/ConfigViewMenu.d.ts +34 -0
  163. package/dist/app/scripts/ConfigureSeriesMenu.d.ts +3 -0
  164. package/dist/app/scripts/ContextMenuContainer.d.ts +36 -0
  165. package/dist/app/scripts/ContextMenuItem.d.ts +34 -0
  166. package/dist/app/scripts/Cross.d.ts +3 -0
  167. package/dist/app/scripts/CrossRule.d.ts +24 -0
  168. package/dist/app/scripts/CustomTrackDialog.d.ts +17 -0
  169. package/dist/app/scripts/Dialog.d.ts +5 -0
  170. package/dist/app/scripts/DivergentBarTrack.d.ts +4 -0
  171. package/dist/app/scripts/DragListeningDiv.d.ts +32 -0
  172. package/dist/app/scripts/DraggableDiv.d.ts +63 -0
  173. package/dist/app/scripts/ExportLinkDialog.d.ts +21 -0
  174. package/dist/app/scripts/FilledLine.d.ts +5 -0
  175. package/dist/app/scripts/FixedTrack.d.ts +5 -0
  176. package/dist/app/scripts/GalleryTracks.d.ts +20 -0
  177. package/dist/app/scripts/GenomePositionSearchBox.d.ts +95 -0
  178. package/dist/app/scripts/HeatmapOptions.d.ts +30 -0
  179. package/dist/app/scripts/HeatmapTiledPixiTrack.d.ts +184 -0
  180. package/dist/app/scripts/HiGlassComponent.d.ts +762 -0
  181. package/dist/app/scripts/HiGlassComponentContext.d.ts +3 -0
  182. package/dist/app/scripts/HiGlassTrackComponent.d.ts +37 -0
  183. package/dist/app/scripts/Horizontal1dHeatmapTrack.d.ts +9 -0
  184. package/dist/app/scripts/Horizontal2DDomainsTrack.d.ts +21 -0
  185. package/dist/app/scripts/HorizontalChromosomeLabels.d.ts +47 -0
  186. package/dist/app/scripts/HorizontalGeneAnnotationsTrack.d.ts +25 -0
  187. package/dist/app/scripts/HorizontalHeatmapTrack.d.ts +12 -0
  188. package/dist/app/scripts/HorizontalItem.d.ts +3 -0
  189. package/dist/app/scripts/HorizontalLine1DPixiTrack.d.ts +23 -0
  190. package/dist/app/scripts/HorizontalMultivecTrack.d.ts +50 -0
  191. package/dist/app/scripts/HorizontalPoint1DPixiTrack.d.ts +5 -0
  192. package/dist/app/scripts/HorizontalRule.d.ts +22 -0
  193. package/dist/app/scripts/HorizontalTiled1DPixiTrack.d.ts +26 -0
  194. package/dist/app/scripts/HorizontalTiledPlot.d.ts +49 -0
  195. package/dist/app/scripts/HorizontalTrack.d.ts +6 -0
  196. package/dist/app/scripts/Id2DTiledPixiTrack.d.ts +10 -0
  197. package/dist/app/scripts/IdHorizontal1DTiledPixiTrack.d.ts +6 -0
  198. package/dist/app/scripts/IdVertical1DTiledPixiTrack.d.ts +7 -0
  199. package/dist/app/scripts/LeftAxisTrack.d.ts +9 -0
  200. package/dist/app/scripts/LeftTrackModifier.d.ts +29 -0
  201. package/dist/app/scripts/ListWrapper.d.ts +64 -0
  202. package/dist/app/scripts/MapboxTilesTrack.d.ts +9 -0
  203. package/dist/app/scripts/Modal.d.ts +5 -0
  204. package/dist/app/scripts/MoveableTrack.d.ts +18 -0
  205. package/dist/app/scripts/NestedContextMenu.d.ts +7 -0
  206. package/dist/app/scripts/OSMTileIdsTrack.d.ts +5 -0
  207. package/dist/app/scripts/OSMTilesTrack.d.ts +129 -0
  208. package/dist/app/scripts/OverlayTrack.d.ts +13 -0
  209. package/dist/app/scripts/PixiTrack.d.ts +174 -0
  210. package/dist/app/scripts/PlotTypeChooser.d.ts +25 -0
  211. package/dist/app/scripts/PopupMenu.d.ts +28 -0
  212. package/dist/app/scripts/RasterTilesTrack.d.ts +9 -0
  213. package/dist/app/scripts/RuleMixin.d.ts +2 -0
  214. package/dist/app/scripts/SVGTrack.d.ts +15 -0
  215. package/dist/app/scripts/SearchField.d.ts +13 -0
  216. package/dist/app/scripts/SeriesListItems.d.ts +2 -0
  217. package/dist/app/scripts/SeriesListMenu.d.ts +51 -0
  218. package/dist/app/scripts/SeriesListSubmenuMixin.d.ts +2 -0
  219. package/dist/app/scripts/SketchInlinePicker.d.ts +25 -0
  220. package/dist/app/scripts/SortableList.d.ts +22 -0
  221. package/dist/app/scripts/SquareMarkersTrack.d.ts +22 -0
  222. package/dist/app/scripts/Tiled1DPixiTrack.d.ts +60 -0
  223. package/dist/app/scripts/TiledPixiTrack.d.ts +369 -0
  224. package/dist/app/scripts/TiledPlot.d.ts +313 -0
  225. package/dist/app/scripts/TilesetFinder.d.ts +65 -0
  226. package/dist/app/scripts/TopAxisTrack.d.ts +9 -0
  227. package/dist/app/scripts/Track.d.ts +196 -0
  228. package/dist/app/scripts/TrackArea.d.ts +26 -0
  229. package/dist/app/scripts/TrackControl.d.ts +5 -0
  230. package/dist/app/scripts/TrackRenderer.d.ts +724 -0
  231. package/dist/app/scripts/UnknownPixiTrack.d.ts +7 -0
  232. package/dist/app/scripts/ValueIntervalTrack.d.ts +6 -0
  233. package/dist/app/scripts/VerticalItem.d.ts +3 -0
  234. package/dist/app/scripts/VerticalRule.d.ts +21 -0
  235. package/dist/app/scripts/VerticalTiled1DPixiTrack.d.ts +6 -0
  236. package/dist/app/scripts/VerticalTiledPlot.d.ts +50 -0
  237. package/dist/app/scripts/VerticalTrack.d.ts +6 -0
  238. package/dist/app/scripts/ViewConfigEditor.d.ts +53 -0
  239. package/dist/app/scripts/ViewContextMenu.d.ts +17 -0
  240. package/dist/app/scripts/ViewHeader.d.ts +75 -0
  241. package/dist/app/scripts/ViewportTracker2D.d.ts +17 -0
  242. package/dist/app/scripts/ViewportTracker2DPixi.d.ts +11 -0
  243. package/dist/app/scripts/ViewportTrackerHorizontal.d.ts +17 -0
  244. package/dist/app/scripts/ViewportTrackerVertical.d.ts +17 -0
  245. package/dist/app/scripts/api.d.ts +640 -0
  246. package/dist/app/scripts/configs/available-track-types.d.ts +2 -0
  247. package/dist/app/scripts/configs/colormaps.d.ts +2 -0
  248. package/dist/app/scripts/configs/datatype-to-track-type.d.ts +4 -0
  249. package/dist/app/scripts/configs/default-tracks-for-datatype.d.ts +38 -0
  250. package/dist/app/scripts/configs/dense-data-extrema-config.d.ts +2 -0
  251. package/dist/app/scripts/configs/globals.d.ts +5 -0
  252. package/dist/app/scripts/configs/index.d.ts +16 -0
  253. package/dist/app/scripts/configs/positions-by-datatype.d.ts +2 -0
  254. package/dist/app/scripts/configs/primitives.d.ts +20 -0
  255. package/dist/app/scripts/configs/themes.d.ts +3 -0
  256. package/dist/app/scripts/configs/tracks-info-by-type.d.ts +4 -0
  257. package/dist/app/scripts/configs/tracks-info.d.ts +24 -0
  258. package/dist/app/scripts/d3-context-menu.d.ts +2 -0
  259. package/dist/app/scripts/data-fetchers/DataFetcher.d.ts +151 -0
  260. package/dist/app/scripts/data-fetchers/genbank-fetcher.d.ts +86 -0
  261. package/dist/app/scripts/data-fetchers/index.d.ts +3 -0
  262. package/dist/app/scripts/data-fetchers/local-tile-fetcher.d.ts +47 -0
  263. package/dist/app/scripts/gosling-exports.d.ts +17 -0
  264. package/dist/app/scripts/hglib.d.ts +24 -0
  265. package/dist/app/scripts/hocs/with-modal.d.ts +19 -0
  266. package/dist/app/scripts/hocs/with-pub-sub.d.ts +22 -0
  267. package/dist/app/scripts/hocs/with-theme.d.ts +13 -0
  268. package/dist/app/scripts/icons.d.ts +161 -0
  269. package/dist/app/scripts/mixwith.d.ts +27 -0
  270. package/dist/app/scripts/options-info.d.ts +1355 -0
  271. package/dist/app/scripts/plugins/available-for-plugins.d.ts +2338 -0
  272. package/dist/app/scripts/plugins/get-data-fetcher.d.ts +2 -0
  273. package/dist/app/scripts/plugins/index.d.ts +2 -0
  274. package/dist/app/scripts/services/chrom-info.d.ts +10 -0
  275. package/dist/app/scripts/services/dom-event.d.ts +7 -0
  276. package/dist/app/scripts/services/element-resize-listener.d.ts +5 -0
  277. package/dist/app/scripts/services/index.d.ts +5 -0
  278. package/dist/app/scripts/services/tile-proxy.d.ts +180 -0
  279. package/dist/app/scripts/services/worker.d.ts +157 -0
  280. package/dist/app/scripts/symbol.d.ts +13 -0
  281. package/dist/app/scripts/test-helpers/index.d.ts +1 -0
  282. package/dist/app/scripts/test-helpers/test-helpers.d.ts +33 -0
  283. package/dist/app/scripts/track-utils.d.ts +73 -0
  284. package/dist/app/scripts/types.d.ts +199 -0
  285. package/dist/app/scripts/utils/DenseDataExtrema1D.d.ts +88 -0
  286. package/dist/app/scripts/utils/DenseDataExtrema2D.d.ts +97 -0
  287. package/dist/app/scripts/utils/LruCache.d.ts +44 -0
  288. package/dist/app/scripts/utils/abs-to-chr.d.ts +14 -0
  289. package/dist/app/scripts/utils/accessor-transposition.d.ts +14 -0
  290. package/dist/app/scripts/utils/add-arrays.d.ts +18 -0
  291. package/dist/app/scripts/utils/add-class.d.ts +8 -0
  292. package/dist/app/scripts/utils/add-event-listener-once.d.ts +11 -0
  293. package/dist/app/scripts/utils/assert.d.ts +17 -0
  294. package/dist/app/scripts/utils/background-task-scheduler.d.ts +47 -0
  295. package/dist/app/scripts/utils/base64-to-canvas.d.ts +9 -0
  296. package/dist/app/scripts/utils/chr-to-abs.d.ts +10 -0
  297. package/dist/app/scripts/utils/chrom-info-bisector.d.ts +4 -0
  298. package/dist/app/scripts/utils/clone-event.d.ts +12 -0
  299. package/dist/app/scripts/utils/color-domain-to-rgba-array.d.ts +13 -0
  300. package/dist/app/scripts/utils/color-to-hex.d.ts +9 -0
  301. package/dist/app/scripts/utils/color-to-rgba.d.ts +9 -0
  302. package/dist/app/scripts/utils/copy-text-to-clipboard.d.ts +2 -0
  303. package/dist/app/scripts/utils/data-to-genomic-loci.d.ts +11 -0
  304. package/dist/app/scripts/utils/debounce.d.ts +5 -0
  305. package/dist/app/scripts/utils/dec-to-hex-str.d.ts +8 -0
  306. package/dist/app/scripts/utils/decompress.d.ts +27 -0
  307. package/dist/app/scripts/utils/default-tracks.d.ts +3 -0
  308. package/dist/app/scripts/utils/dict-from-tuples.d.ts +11 -0
  309. package/dist/app/scripts/utils/dict-items.d.ts +18 -0
  310. package/dist/app/scripts/utils/dict-keys.d.ts +10 -0
  311. package/dist/app/scripts/utils/dict-values.d.ts +8 -0
  312. package/dist/app/scripts/utils/download.d.ts +7 -0
  313. package/dist/app/scripts/utils/expand-combined-tracks.d.ts +11 -0
  314. package/dist/app/scripts/utils/fake-pub-sub.d.ts +11 -0
  315. package/dist/app/scripts/utils/fill-in-min-widths.d.ts +44 -0
  316. package/dist/app/scripts/utils/flatten.d.ts +9 -0
  317. package/dist/app/scripts/utils/for-each.d.ts +9 -0
  318. package/dist/app/scripts/utils/forward-event.d.ts +7 -0
  319. package/dist/app/scripts/utils/genome-loci-to-pixels.d.ts +9 -0
  320. package/dist/app/scripts/utils/genomic-range-to-chromosome-chunks.d.ts +21 -0
  321. package/dist/app/scripts/utils/get-aggregation-function.d.ts +10 -0
  322. package/dist/app/scripts/utils/get-default-track-for-datatype.d.ts +21 -0
  323. package/dist/app/scripts/utils/get-default-tracks-for-datatype.d.ts +3 -0
  324. package/dist/app/scripts/utils/get-element-dim.d.ts +7 -0
  325. package/dist/app/scripts/utils/get-higlass-components.d.ts +7 -0
  326. package/dist/app/scripts/utils/get-track-by-uid.d.ts +7 -0
  327. package/dist/app/scripts/utils/get-track-conf-from-hgc.d.ts +10 -0
  328. package/dist/app/scripts/utils/get-track-obj-by-id.d.ts +2 -0
  329. package/dist/app/scripts/utils/get-track-position-by-uid.d.ts +13 -0
  330. package/dist/app/scripts/utils/get-xylofon.d.ts +2 -0
  331. package/dist/app/scripts/utils/gradient.d.ts +14 -0
  332. package/dist/app/scripts/utils/has-class.d.ts +8 -0
  333. package/dist/app/scripts/utils/has-parent.d.ts +9 -0
  334. package/dist/app/scripts/utils/hex-string-to-int.d.ts +14 -0
  335. package/dist/app/scripts/utils/index.d.ts +89 -0
  336. package/dist/app/scripts/utils/interval-tree.d.ts +109 -0
  337. package/dist/app/scripts/utils/into-the-void.d.ts +6 -0
  338. package/dist/app/scripts/utils/is-track-or-child-track.d.ts +7 -0
  339. package/dist/app/scripts/utils/is-track-range-selectable.d.ts +2 -0
  340. package/dist/app/scripts/utils/is-within.d.ts +12 -0
  341. package/dist/app/scripts/utils/lat-to-y.d.ts +9 -0
  342. package/dist/app/scripts/utils/lng-to-x.d.ts +8 -0
  343. package/dist/app/scripts/utils/load-chrom-infos.d.ts +8 -0
  344. package/dist/app/scripts/utils/map.d.ts +13 -0
  345. package/dist/app/scripts/utils/max-non-zero.d.ts +6 -0
  346. package/dist/app/scripts/utils/max.d.ts +10 -0
  347. package/dist/app/scripts/utils/min-non-zero.d.ts +6 -0
  348. package/dist/app/scripts/utils/min.d.ts +10 -0
  349. package/dist/app/scripts/utils/mod.d.ts +9 -0
  350. package/dist/app/scripts/utils/ndarray-assign.d.ts +2 -0
  351. package/dist/app/scripts/utils/ndarray-flatten.d.ts +2 -0
  352. package/dist/app/scripts/utils/ndarray-to-list.d.ts +2 -0
  353. package/dist/app/scripts/utils/numericify-version.d.ts +6 -0
  354. package/dist/app/scripts/utils/obj-vals.d.ts +8 -0
  355. package/dist/app/scripts/utils/or.d.ts +8 -0
  356. package/dist/app/scripts/utils/parse-chromsizes-rows.d.ts +34 -0
  357. package/dist/app/scripts/utils/pixi-text-to-svg.d.ts +2 -0
  358. package/dist/app/scripts/utils/positioned-tracks-to-all-tracks.d.ts +26 -0
  359. package/dist/app/scripts/utils/q.d.ts +18 -0
  360. package/dist/app/scripts/utils/rad-to-deg.d.ts +7 -0
  361. package/dist/app/scripts/utils/range-query-2d.d.ts +17 -0
  362. package/dist/app/scripts/utils/reduce.d.ts +14 -0
  363. package/dist/app/scripts/utils/rel-to-abs-chrom-pos.d.ts +10 -0
  364. package/dist/app/scripts/utils/remove-class.d.ts +7 -0
  365. package/dist/app/scripts/utils/reset-d3-brush-style.d.ts +10 -0
  366. package/dist/app/scripts/utils/rgb-to-hex.d.ts +8 -0
  367. package/dist/app/scripts/utils/scales-center-and-k.d.ts +12 -0
  368. package/dist/app/scripts/utils/scales-to-genome-loci.d.ts +3 -0
  369. package/dist/app/scripts/utils/segments-to-rows.d.ts +15 -0
  370. package/dist/app/scripts/utils/selected-items-to-cum-weights.d.ts +12 -0
  371. package/dist/app/scripts/utils/selected-items-to-size.d.ts +13 -0
  372. package/dist/app/scripts/utils/show-mouse-position.d.ts +54 -0
  373. package/dist/app/scripts/utils/some.d.ts +10 -0
  374. package/dist/app/scripts/utils/sum.d.ts +8 -0
  375. package/dist/app/scripts/utils/svg-line.d.ts +2 -0
  376. package/dist/app/scripts/utils/throttle-and-debounce.d.ts +33 -0
  377. package/dist/app/scripts/utils/tile-to-canvas.d.ts +9 -0
  378. package/dist/app/scripts/utils/timeout.d.ts +3 -0
  379. package/dist/app/scripts/utils/to-void.d.ts +3 -0
  380. package/dist/app/scripts/utils/total-track-pixel-height.d.ts +27 -0
  381. package/dist/app/scripts/utils/trim-trailing-slash.d.ts +7 -0
  382. package/dist/app/scripts/utils/type-guards.d.ts +36 -0
  383. package/dist/app/scripts/utils/value-to-color.d.ts +12 -0
  384. package/dist/app/scripts/utils/visit-positioned-tracks.d.ts +18 -0
  385. package/dist/app/scripts/utils/visit-tracks.d.ts +9 -0
  386. package/dist/esm.html +1 -3
  387. package/dist/hglib.js +86315 -100592
  388. package/dist/hglib.min.js +123 -131
  389. package/dist/higlass.mjs +88861 -103138
  390. package/dist/index.html +1 -3
  391. package/dist/package.json +134 -0
  392. package/package.json +25 -27
@@ -1,111 +1,104 @@
1
- // @ts-nocheck
2
1
  import { range } from 'd3-array';
3
2
  import slugid from 'slugid';
4
3
 
5
- import { workerGetTiles, workerSetPix } from './worker';
4
+ import { workerFetchTiles, workerSetPix } from './worker';
6
5
 
7
- import tts from '../utils/trim-trailing-slash';
8
6
  import sleep from '../utils/timeout';
7
+ import tts from '../utils/trim-trailing-slash';
8
+ import {
9
+ isLegacyTilesetInfo,
10
+ isResolutionsTilesetInfo,
11
+ } from '../utils/type-guards';
9
12
 
10
13
  // Config
11
14
  import { TILE_FETCH_DEBOUNCE } from '../configs/primitives';
12
15
 
16
+ /** @import { PubSub } from 'pub-sub-es' */
17
+ /** @import { Scale, TilesetInfo, TilesRequest } from '../types' */
18
+ /** @import { CompletedTileData, TileResponse, SelectedRowsOptions } from './worker' */
19
+
20
+ /** @type {number} */
13
21
  const MAX_FETCH_TILES = 15;
14
22
 
15
- /*
16
- const str = document.currentScript.src
17
- const pathName = str.substring(0, str.lastIndexOf("/"));
18
- const workerPath = `${pathName}/worker.js`;
19
-
20
- const setPixPool = new Pool(1);
21
-
22
- setPixPool.run(function(params, done) {
23
- try {
24
- const array = new Float32Array(params.data);
25
- const pixData = worker.workerSetPix(
26
- params.size,
27
- array,
28
- params.valueScaleType,
29
- params.valueScaleDomain,
30
- params.pseudocount,
31
- params.colorScale,
32
- );
23
+ /** @type {string} */
24
+ const sessionId = import.meta.env.DEV ? 'dev' : slugid.nice();
25
+ /** @type {number} */
26
+ export let requestsInFlight = 0;
27
+ /** @type {string | null} */
28
+ export let authHeader = null;
33
29
 
34
- done.transfer({
35
- pixData: pixData
36
- }, [pixData.buffer]);
37
- } catch (err) {
38
- console.log('err:', err);
30
+ /**
31
+ * Iterator helper to chunk an array into smaller arrays of a fixed size.
32
+ *
33
+ * @template T
34
+ * @param {Iterable<T>} iterable
35
+ * @param {number} size
36
+ * @returns {Generator<Array<T>, void, unknown>}
37
+ */
38
+ function* chunkIterable(iterable, size) {
39
+ let chunk = [];
40
+ for (const item of iterable) {
41
+ chunk.push(item);
42
+ if (chunk.length === size) {
43
+ yield chunk;
44
+ chunk = [];
45
+ }
39
46
  }
40
- }, [workerPath]);
41
-
42
-
43
- const fetchTilesPool = new Pool(10);
44
- fetchTilesPool.run(function(params, done) {
45
- try {
46
- worker.workerGetTiles(params.outUrl, params.server, params.theseTileIds,
47
- params.authHeader, done);
48
- // done.transfer({
49
- // pixData: pixData
50
- // }, [pixData.buffer]);
51
- } catch (err) {
52
- console.log('err:', err);
47
+ if (chunk.length) {
48
+ yield chunk;
53
49
  }
54
- }, [workerPath]);
55
- */
50
+ }
56
51
 
57
- const sessionId = import.meta.env.DEV ? 'dev' : slugid.nice();
58
- export let requestsInFlight = 0; // eslint-disable-line import/no-mutable-exports
59
- export let authHeader = null; // eslint-disable-line import/no-mutable-exports
52
+ /**
53
+ * @template T
54
+ * @template U
55
+ * @typedef {{ value: T, resolve: (value: U) => void, reject: (err: unknown) => void }} WithResolvers
56
+ */
60
57
 
61
- const throttleAndDebounce = (func, interval, finalWait) => {
62
- let timeout;
63
- let bundledRequest = [];
64
- let requestMapper = {};
58
+ /**
59
+ * Create a function that batches calls at intervals, with a final debounce.
60
+ *
61
+ * The returned function collects individual items and executes `processBatch` at the specified interval.
62
+ * If additional calls occur after the last batch, a final debounce ensures they are included.
63
+ *
64
+ * @template T
65
+ * @template U
66
+ * @template {Array<unknown>} Args
67
+ *
68
+ * @param {Object} options
69
+ * @param {(items: Array<WithResolvers<T, U>>, ...args: Args) => void} options.processBatch
70
+ * @param {number} options.interval
71
+ * @param {number} options.finalWait
72
+ */
73
+ function createBatchedExecutor({ processBatch, interval, finalWait }) {
74
+ /** @type {ReturnType<typeof setTimeout> | undefined} */
75
+ let timeout = undefined;
76
+ /** @type {Array<WithResolvers<T, U>>} */
77
+ let pending = [];
78
+ /** @type {number} */
65
79
  let blockedCalls = 0;
66
80
 
67
- const bundleRequests = (request) => {
68
- const requestId = requestMapper[request.id];
69
-
70
- if (requestId && bundledRequest[requestId]) {
71
- bundledRequest[requestId].ids = bundledRequest[requestId].ids.concat(
72
- request.ids,
73
- );
74
- } else {
75
- requestMapper[request.id] = bundledRequest.length;
76
- bundledRequest.push(request);
77
- }
78
- };
79
-
80
81
  const reset = () => {
81
- timeout = null;
82
- bundledRequest = [];
83
- requestMapper = {};
82
+ timeout = undefined;
83
+ pending = [];
84
84
  };
85
85
 
86
- // In a normal situation we would just call `func(...args)` but since we
87
- // modify the first argument and always trigger `reset()` afterwards I created
88
- // this helper function to avoid code duplication. Think of this function
89
- // as the actual function call that is being throttled and debounced.
90
- const callFunc = (request, ...args) => {
91
- func(
92
- {
93
- sessionId,
94
- requests: bundledRequest,
95
- },
96
- ...args,
97
- );
86
+ /** @param {Args} args */
87
+ const callFunc = (...args) => {
88
+ // Flush the "bundle" (of collected items) to the processor
89
+ processBatch(pending, ...args);
98
90
  reset();
99
91
  };
100
92
 
101
- const debounced = (request, ...args) => {
93
+ /** @param {Args} args */
94
+ const debounced = (...args) => {
102
95
  const later = () => {
103
96
  // Since we throttle and debounce we should check whether there were
104
97
  // actually multiple attempts to call this function after the most recent
105
98
  // throttled call. If there were no more calls we don't have to call
106
99
  // the function again.
107
100
  if (blockedCalls > 0) {
108
- callFunc(request, ...args);
101
+ callFunc(...args);
109
102
  blockedCalls = 0;
110
103
  }
111
104
  };
@@ -114,25 +107,20 @@ const throttleAndDebounce = (func, interval, finalWait) => {
114
107
  timeout = setTimeout(later, finalWait);
115
108
  };
116
109
 
117
- debounced.cancel = () => {
118
- clearTimeout(timeout);
119
- reset();
120
- };
121
-
122
- debounced.immediate = () => {
123
- func({
124
- sessionId,
125
- requests: bundledRequest,
126
- });
127
- };
128
-
129
110
  let wait = false;
130
- const throttled = (request, ...args) => {
131
- bundleRequests(request);
111
+ /**
112
+ * @param {T} value
113
+ * @param {Args} args
114
+ * @returns {Promise<U>}
115
+ */
116
+ const throttled = (value, ...args) => {
117
+ // Collect items into the current queue any time the caller makes a request
118
+ const { promise, resolve, reject } = Promise.withResolvers();
119
+ pending.push({ value, resolve, reject });
132
120
 
133
121
  if (!wait) {
134
- callFunc(request, ...args);
135
- debounced(request, ...args);
122
+ callFunc(...args);
123
+ debounced(...args);
136
124
  wait = true;
137
125
  blockedCalls = 0;
138
126
  setTimeout(() => {
@@ -141,152 +129,247 @@ const throttleAndDebounce = (func, interval, finalWait) => {
141
129
  } else {
142
130
  blockedCalls++;
143
131
  }
132
+
133
+ return promise;
144
134
  };
145
135
 
146
136
  return throttled;
147
- };
137
+ }
148
138
 
139
+ /** @param {string} newHeader */
149
140
  export const setTileProxyAuthHeader = (newHeader) => {
150
141
  authHeader = newHeader;
151
142
  };
152
143
 
144
+ /** @returns {string | null} */
153
145
  export const getTileProxyAuthHeader = () => authHeader;
154
146
 
155
- // Fritz: is this function used anywhere?
156
- export function fetchMultiRequestTiles(req, pubSub) {
157
- const requests = req.requests;
147
+ /**
148
+ * Merges an array of request objects by combining requests
149
+ * that share the same `id`, reducing the total number of requests.
150
+ *
151
+ * If multiple requests have the same `id`, their `tileIds` arrays are merged
152
+ * into a single request entry in the output array.
153
+ *
154
+ * @example
155
+ * ```js
156
+ * const requests = [
157
+ * { id: "A", tileIds: ["1", "2"] },
158
+ * { id: "B", tileIds: ["3"] },
159
+ * { id: "A", tileids: ["4", "5"] },
160
+ * ];
161
+ *
162
+ * const bundled = bundleRequests(requests);
163
+ * console.log(bundled);
164
+ * // [
165
+ * // { id: "A", tileIds: ["1", "2", "4", "5"] },
166
+ * // { id: "B", tileIds: ["3"] },
167
+ * // ]
168
+ * ```
169
+ *
170
+ * @template {{ id: string, tileIds: ReadonlyArray<string> }} T
171
+ * @param {Array<T>} requests - The list of requests to bundle
172
+ * @returns {Array<T>} - A new array with merged requests
173
+ */
174
+ export function bundleRequestsById(requests) {
175
+ /** @type {Array<T>} */
176
+ const bundledRequests = [];
177
+ /** @type {Record<string, number>} */
178
+ const mapper = {};
179
+
180
+ for (const request of requests) {
181
+ if (mapper[request.id] === undefined) {
182
+ mapper[request.id] = bundledRequests.length;
183
+ bundledRequests.push({ ...request, tileIds: [] });
184
+ }
185
+ const bundle = bundledRequests[mapper[request.id]];
186
+ bundle.tileIds = bundle.tileIds.concat(request.tileIds);
187
+ }
158
188
 
159
- const fetchPromises = [];
189
+ return bundledRequests;
190
+ }
160
191
 
161
- const requestsByServer = {};
162
- const requestBodyByServer = {};
192
+ /**
193
+ * Groups request objects by `server`, merging their `tileIds` and structuring tileset-related
194
+ * data into `body`.
195
+ *
196
+ * **Note:** The first request for each `server` sets the `options` for all grouped requests.
197
+ * Each tileset in `body` also inherits these `options`. A tileset is only added to `body`
198
+ * if the request includes `options`.
199
+ *
200
+ * Trevor (2025-02-20): This follows the original "server bundling" logic. It’s unclear if `body` is
201
+ * actually used in practice. Omitting requests without `options` might be an unintended
202
+ * behavior, but we're maintaining it for now.
203
+ *
204
+ * @example
205
+ * ```js
206
+ * const requests = [
207
+ * { server: "A", tileIds: ["tileset1.1", "tileset2.2"], options: { foo: "bar" } },
208
+ * { server: "B", tileIds: ["tileset3.3"], options: { baz: "qux" } },
209
+ * { server: "A", tileIds: ["tileset1.4"] },
210
+ * ];
211
+ *
212
+ * const bundled = bundleRequestsByServer(requests);
213
+ * console.log(bundled);
214
+ * // [
215
+ * // {
216
+ * // server: "A",
217
+ * // tileIds: ["tileset1.1", "tileset2.2", "tileset1.4"],
218
+ * // options: { foo: "bar" },
219
+ * // body: [
220
+ * // { tilesetUid: "tileset1", tileIds: ["1"], options: { foo: "bar" } },
221
+ * // { tilesetUid: "tileset2", tileIds: ["2"], options: { foo: "bar" } }
222
+ * // ]
223
+ * // },
224
+ * // {
225
+ * // server: "B",
226
+ * // tileIds: ["tileset3.3"],
227
+ * // options: { baz: "qux" },
228
+ * // body: [
229
+ * // { tilesetUid: "tileset3", tileIds: ["3"], options: { baz: "qux" } }
230
+ * // ]
231
+ * // }
232
+ * // ]
233
+ * ```
234
+ *
235
+ * @template {{ tileIds: ReadonlyArray<string>, server: string, options?: Record<string, any> }} T
236
+ * @param {Array<T>} requests - The list of requests to bundle
237
+ * @returns {Array<T & { body: ReadonlyArray<ServerTilesetBody> }> }>} - A new array with merged requests per server
238
+ */
239
+ export function bundleRequestsByServer(requests) {
240
+ /** @typedef {{ tilesetUid: string, tileIds: Array<string>, options: Record<string, any> }} ServerTilesetBody */
241
+ /** @type {Array<T & { body: Array<ServerTilesetBody> }>} */
242
+ const bundle = [];
243
+ /** @type {Record<string, number>} */
244
+ const mapper = {};
163
245
 
164
246
  // We're converting the array of IDs into an object in order to filter out duplicated requests.
165
247
  // In case different instances request the same data it won't be loaded twice.
166
248
  for (const request of requests) {
167
- if (!requestsByServer[request.server]) {
168
- requestsByServer[request.server] = {};
169
- requestBodyByServer[request.server] = [];
249
+ if (mapper[request.server] === undefined) {
250
+ mapper[request.server] = bundle.length;
251
+ bundle.push({ ...request, tileIds: [], body: [] });
170
252
  }
171
- for (const id of request.ids) {
172
- requestsByServer[request.server][id] = true;
173
-
253
+ const server = bundle[mapper[request.server]];
254
+ server.tileIds = server.tileIds.concat(request.tileIds);
255
+ for (const id of request.tileIds) {
174
256
  if (request.options) {
175
257
  const firstSepIndex = id.indexOf('.');
176
- const tilesetUuid = id.substring(0, firstSepIndex);
258
+ const tilesetUid = id.substring(0, firstSepIndex);
177
259
  const tileId = id.substring(firstSepIndex + 1);
178
- const tilesetObject = requestBodyByServer[request.server].find(
179
- (t) => t.tilesetUid === tilesetUuid,
260
+ let tilesetObject = server.body.find(
261
+ (t) => t.tilesetUid === tilesetUid,
180
262
  );
181
- if (tilesetObject) {
182
- tilesetObject.tileIds.push(tileId);
183
- } else {
184
- requestBodyByServer[request.server].push({
185
- tilesetUid: tilesetUuid,
186
- tileIds: [tileId],
263
+ if (!tilesetObject) {
264
+ tilesetObject = {
265
+ tilesetUid: tilesetUid,
266
+ tileIds: [],
187
267
  options: request.options,
188
- });
268
+ };
269
+ server.body.push(tilesetObject);
189
270
  }
271
+ tilesetObject.tileIds.push(tileId);
190
272
  }
191
273
  }
192
274
  }
193
275
 
194
- const servers = Object.keys(requestsByServer);
195
-
196
- for (const server of servers) {
197
- const ids = Object.keys(requestsByServer[server]);
198
- // console.log('ids:', ids);
199
-
200
- const requestBody = requestBodyByServer[server];
201
-
202
- // if we request too many tiles, then the URL can get too long and fail
203
- // so we'll break up the requests into smaller subsets
204
- for (let i = 0; i < ids.length; i += MAX_FETCH_TILES) {
205
- const theseTileIds = ids.slice(
206
- i,
207
- i + Math.min(ids.length - i, MAX_FETCH_TILES),
208
- );
209
-
210
- const renderParams = theseTileIds.map((x) => `d=${x}`).join('&');
211
- const outUrl = `${server}/tiles/?${renderParams}&s=${sessionId}`;
212
-
213
- /* eslint-disable no-loop-func */
214
- /* eslint-disable no-unused-vars */
215
- const p = new Promise((resolve, reject) => {
216
- pubSub.publish('requestSent', outUrl);
217
- const params = {};
218
-
219
- params.outUrl = outUrl;
220
- params.server = server;
221
- params.theseTileIds = theseTileIds;
222
- params.authHeader = authHeader;
223
-
224
- workerGetTiles(
225
- params.outUrl,
226
- params.server,
227
- params.theseTileIds,
228
- params.authHeader,
229
- resolve,
230
- requestBody,
231
- );
276
+ return bundle;
277
+ }
232
278
 
233
- /*
234
- fetchTilesPool.send(params)
235
- .promise()
236
- .then(ret => {
237
- resolve(ret);
238
- });
239
- */
240
- pubSub.publish('requestReceived', outUrl);
241
- });
242
-
243
- fetchPromises.push(p);
279
+ /**
280
+ * Consolidates requests into a (potentially) smaller, optimized set
281
+ *
282
+ * Requests are first bundled to merge duplicates, then grouped by `server` to
283
+ * consolidate requests targeting the same endpoint. The resulting set is split
284
+ * into smaller batches based on `maxSize`.
285
+ *
286
+ * @template {TilesRequest} T
287
+ * @param {Array<T>} requests - The list of requests to optimize.
288
+ * @param {{ maxSize?: number }} [options] - Configuration options.
289
+ */
290
+ function* optimizeRequests(requests, { maxSize = MAX_FETCH_TILES } = {}) {
291
+ const byRequestId = bundleRequestsById(requests);
292
+ const byServer = bundleRequestsByServer(byRequestId);
293
+ for (const request of byServer) {
294
+ for (const tileIds of chunkIterable(new Set(request.tileIds), maxSize)) {
295
+ yield { ...request, tileIds };
244
296
  }
245
297
  }
298
+ }
246
299
 
247
- Promise.all(fetchPromises).then((datas) => {
248
- const tiles = {};
249
-
250
- // merge back all the tile requests
251
- for (const data of datas) {
252
- const tileIds = Object.keys(data);
300
+ /** @typedef {CompletedTileData<TileResponse>} TileData */
253
301
 
254
- for (const tileId of tileIds) {
255
- tiles[`${data[tileId].server}/${tileId}`] = data[tileId];
256
- }
302
+ /**
303
+ * Collects independent tile responses into a shared index.
304
+ *
305
+ * Allows requests to retrieve associated tiles by server and tile IDs.
306
+ *
307
+ * @param {Array<Record<string, TileData> | void>} responses
308
+ */
309
+ function indexTiles(responses) {
310
+ /** @type {Record<string, TileData>} */
311
+ const tileMap = {};
312
+ /** @type {(server: string, tileId: string) => string} */
313
+ const keyFor = (server, tileId) => `${server}/${tileId}`;
314
+
315
+ // merge back all the tile requests
316
+ for (const response of responses) {
317
+ if (!response) continue;
318
+ for (const [tileId, tileData] of Object.entries(response)) {
319
+ tileMap[keyFor(tileData.server, tileId)] = response[tileId];
257
320
  }
321
+ }
258
322
 
259
- // trigger the callback for every request
260
- for (const request of requests) {
261
- const reqDate = {};
262
- const { server } = request;
263
-
264
- // pull together the data per request
265
- for (const id of request.ids) {
266
- reqDate[id] = tiles[`${server}/${id}`];
323
+ return {
324
+ /**
325
+ * Retrieve data for a specific request from the shared index.
326
+ *
327
+ * @param {{ server: string, tileIds: Array<string> }} request
328
+ */
329
+ resolveTileDataForRequest(request) {
330
+ /** @type {Record<string, TileData>} */
331
+ const response = {};
332
+ for (const tileId of request.tileIds) {
333
+ const entry = tileMap[keyFor(request.server, tileId)];
334
+ if (entry) response[tileId] = entry;
267
335
  }
268
-
269
- request.done(reqDate);
270
- }
271
- });
336
+ return response;
337
+ },
338
+ };
272
339
  }
273
340
 
274
341
  /**
275
- * Retrieve a set of tiles from the server
276
- *
277
- * Plenty of room for optimization and caching here.
342
+ * Retrieve a set of tiles from the server.
278
343
  *
279
- * @param server: A string with the server's url (e.g. "http://127.0.0.1")
280
- * @param tileIds: The ids of the tiles to fetch (e.g. asdf-sdfs-sdfs.0.0.0)
344
+ * @type {(request: TilesRequest, pubSub: PubSub) => Promise<Record<string, TileData>>}
281
345
  */
282
- export const fetchTilesDebounced = throttleAndDebounce(
283
- fetchMultiRequestTiles,
284
- TILE_FETCH_DEBOUNCE,
285
- TILE_FETCH_DEBOUNCE,
286
- );
346
+ export const fetchTilesDebounced = createBatchedExecutor({
347
+ /**
348
+ * Fetch and process a batch of tile requests.
349
+ *
350
+ * @param {Array<WithResolvers<TilesRequest, Record<string, TileData>>>} requests
351
+ * @param {PubSub} pubSub
352
+ */
353
+ processBatch: async (requests, pubSub) => {
354
+ const promises = Array.from(
355
+ optimizeRequests(requests.map((r) => r.value)),
356
+ (request) => workerFetchTiles(request, { authHeader, sessionId, pubSub }),
357
+ );
358
+ const index = indexTiles(await Promise.all(promises));
359
+ for (const request of requests) {
360
+ request.resolve(index.resolveTileDataForRequest(request.value));
361
+ }
362
+ },
363
+ interval: TILE_FETCH_DEBOUNCE,
364
+ finalWait: TILE_FETCH_DEBOUNCE,
365
+ });
287
366
 
288
367
  /**
289
368
  * Calculate the zoom level from a list of available resolutions
369
+ *
370
+ * @param {Array<string>} resolutions
371
+ * @param {Scale} scale
372
+ * @returns {number}
290
373
  */
291
374
  export const calculateZoomLevelFromResolutions = (resolutions, scale) => {
292
375
  const sortedResolutions = resolutions.map((x) => +x).sort((a, b) => b - a);
@@ -309,8 +392,13 @@ export const calculateZoomLevelFromResolutions = (resolutions, scale) => {
309
392
  );
310
393
  };
311
394
 
395
+ /**
396
+ * @param {TilesetInfo} tilesetInfo
397
+ * @param {number} zoomLevel
398
+ * @returns {number}
399
+ */
312
400
  export const calculateResolution = (tilesetInfo, zoomLevel) => {
313
- if (tilesetInfo.resolutions) {
401
+ if (isResolutionsTilesetInfo(tilesetInfo)) {
314
402
  const sortedResolutions = tilesetInfo.resolutions
315
403
  .map((x) => +x)
316
404
  .sort((a, b) => b - a);
@@ -320,7 +408,7 @@ export const calculateResolution = (tilesetInfo, zoomLevel) => {
320
408
  }
321
409
 
322
410
  const maxWidth = tilesetInfo.max_width;
323
- const binsPerDimension = +tilesetInfo.bins_per_dimension;
411
+ const binsPerDimension = +(tilesetInfo?.bins_per_dimension ?? 256);
324
412
  const resolution = maxWidth / (2 ** zoomLevel * binsPerDimension);
325
413
 
326
414
  return resolution;
@@ -328,6 +416,12 @@ export const calculateResolution = (tilesetInfo, zoomLevel) => {
328
416
 
329
417
  /**
330
418
  * Calculate the current zoom level.
419
+ *
420
+ * @param {Scale} scale
421
+ * @param {number} minX
422
+ * @param {number} maxX
423
+ * @param {number} binsPerTile
424
+ * @returns {number}
331
425
  */
332
426
  export const calculateZoomLevel = (scale, minX, maxX, binsPerTile) => {
333
427
  const rangeWidth = scale.range()[1] - scale.range()[0];
@@ -367,13 +461,13 @@ export const calculateZoomLevel = (scale, minX, maxX, binsPerTile) => {
367
461
  * Returns the tile position and position within the tile for
368
462
  * the given element.
369
463
  *
370
- * @param {object} tilesetInfo: The information about this tileset
371
- * @param {Number} maxDim: The maximum width of the dataset (only used for
372
- * tilesets without resolutions)
373
- * @param {Number} dataStartPos: The position where the data begins
374
- * @param {int} zoomLevel: The current zoomLevel
375
- * @param {Number} position: The position (in absolute coordinates) to caculate
376
- * the tile and position in tile for
464
+ * @param {TilesetInfo} tilesetInfo - The information about this tileset
465
+ * @param {number} maxDim - The maximum width of the dataset (only used for tilesets without resolutions)
466
+ * @param {number} dataStartPos - The position where the data begins
467
+ * @param {number} zoomLevel - The (integer) current zoomLevel
468
+ * @param {number} position -The position (in absolute coordinates) to caculate the tile and position in tile for
469
+ *
470
+ * @returns {Array<number>}
377
471
  */
378
472
  export function calculateTileAndPosInTile(
379
473
  tilesetInfo,
@@ -383,17 +477,20 @@ export function calculateTileAndPosInTile(
383
477
  position,
384
478
  ) {
385
479
  let tileWidth = null;
386
- const PIXELS_PER_TILE = tilesetInfo.bins_per_dimension || 256;
387
480
 
388
- if (tilesetInfo.resolutions) {
389
- tileWidth = tilesetInfo.resolutions[zoomLevel] * PIXELS_PER_TILE;
481
+ const pixelsPerTile = isLegacyTilesetInfo(tilesetInfo)
482
+ ? (tilesetInfo.bins_per_dimension ?? 256)
483
+ : 256;
484
+
485
+ if (!isLegacyTilesetInfo(tilesetInfo)) {
486
+ tileWidth = tilesetInfo.resolutions[zoomLevel] * pixelsPerTile;
390
487
  } else {
391
488
  tileWidth = maxDim / 2 ** zoomLevel;
392
489
  }
393
490
 
394
491
  const tilePos = Math.floor((position - dataStartPos) / tileWidth);
395
492
  const posInTile = Math.floor(
396
- (PIXELS_PER_TILE * (position - tilePos * tileWidth)) / tileWidth,
493
+ (pixelsPerTile * (position - tilePos * tileWidth)) / tileWidth,
397
494
  );
398
495
 
399
496
  return [tilePos, posInTile];
@@ -409,19 +506,19 @@ export function calculateTileAndPosInTile(
409
506
  * @param {number} zoomLevel - The zoom level at which to find the tiles (can be
410
507
  * calculated using this.calcaulteZoomLevel, but needs to synchronized across
411
508
  * both x and y scales so should be calculated externally)
412
- * @param {import('../type').Scale} scale - A d3 scale mapping data domain to visible values
509
+ * @param {Scale} scale - A d3 scale mapping data domain to visible values
413
510
  * @param {number} minX - The minimum possible value in the dataset
414
- * @param {number} maxX - The maximum possible value in the dataset
511
+ * @param {number} _maxX - The maximum possible value in the dataset
415
512
  * @param {number} maxZoom - The maximum zoom value in this dataset
416
513
  * @param {number} maxDim - The largest dimension of the tileset (e.g., width or height)
417
514
  * (roughlty equal to 2 ** maxZoom * tileSize * tileResolution)
418
- * @returns {number[]} The indices of the tiles that should be visible
515
+ * @returns {Array<number>} The indices of the tiles that should be visible
419
516
  */
420
517
  export const calculateTiles = (
421
518
  zoomLevel,
422
519
  scale,
423
520
  minX,
424
- maxX,
521
+ _maxX,
425
522
  maxZoom,
426
523
  maxDim,
427
524
  ) => {
@@ -432,16 +529,8 @@ export const calculateTiles = (
432
529
  // be calculated according to cumulative width
433
530
 
434
531
  const tileWidth = maxDim / 2 ** zoomLevelFinal;
435
- // console.log('maxDim:', maxDim);
436
-
437
532
  const epsilon = 0.0000001;
438
533
 
439
- /*
440
- console.log('minX:', minX, 'zoomLevel:', zoomLevel);
441
- console.log('domain:', scale.domain(), scale.domain()[0] - minX,
442
- ((scale.domain()[0] - minX) / tileWidth))
443
- */
444
-
445
534
  return range(
446
535
  Math.max(0, Math.floor((scale.domain()[0] - minX) / tileWidth)),
447
536
  Math.min(
@@ -451,8 +540,13 @@ export const calculateTiles = (
451
540
  );
452
541
  };
453
542
 
543
+ /**
544
+ * @param {TilesetInfo} tilesetInfo
545
+ * @param {number} zoomLevel
546
+ * @param {number} binsPerTile
547
+ */
454
548
  export const calculateTileWidth = (tilesetInfo, zoomLevel, binsPerTile) => {
455
- if (tilesetInfo.resolutions) {
549
+ if (!isLegacyTilesetInfo(tilesetInfo)) {
456
550
  const sortedResolutions = tilesetInfo.resolutions
457
551
  .map((x) => +x)
458
552
  .sort((a, b) => b - a);
@@ -466,7 +560,7 @@ export const calculateTileWidth = (tilesetInfo, zoomLevel, binsPerTile) => {
466
560
  * the minX and maxX values for the region
467
561
  *
468
562
  * @param {number} resolution - The number of base pairs per bin
469
- * @param {import('../type').Scale} scale - The scale to use to calculate the currently visible tiles
563
+ * @param {Scale} scale - The scale to use to calculate the currently visible tiles
470
564
  * @param {number} minX - The minimum x position of the tileset
471
565
  * @param {number} maxX - The maximum x position of the tileset
472
566
  * @param {number=} pixelsPerTile - The number of pixels per tile
@@ -486,7 +580,7 @@ export const calculateTilesFromResolution = (
486
580
  // console.log('PIXELS_PER_TILE:', PIXELS_PER_TILE);
487
581
 
488
582
  if (!maxX) {
489
- maxX = Number.MAX_VALUE; // eslint-disable-line no-param-reassign
583
+ maxX = Number.MAX_VALUE;
490
584
  }
491
585
 
492
586
  const lowerBound = Math.max(
@@ -514,21 +608,16 @@ export const calculateTilesFromResolution = (
514
608
  * Render 2D tile data. Convert the raw values to an array of
515
609
  * color values
516
610
  *
517
- * @param finished: A callback to let the caller know that the worker thread
518
- * has converted tileData to pixData
519
- * @param minVisibleValue: The minimum visible value (used for setting the color
520
- * scale)
521
- * @param maxVisibleValue: The maximum visible value
522
- * @param valueScaleType: Either 'log' or 'linear'
523
- * @param valueScaleDomain: The domain of the scale (the range is always [254,0])
524
- * @param colorScale: a 255 x 4 rgba array used as a color scale
525
- * @param synchronous: Render this tile synchronously or pass it on to the threadpool (which doesn't exist yet).
526
- * @param ignoreUpperRight: If this is a tile along the diagonal and there will
527
- * be mirrored tiles present ignore the upper right values
528
- * @param ignoreLowerLeft: If this is a tile along the diagonal and there will be
529
- * mirrored tiles present ignore the lower left values
530
- * @param {array} zeroValueColor: The color to use for rendering zero data values, [r, g, b, a].
531
- * @param {object} selectedRowsOptions Rendering options when using a `selectRows` track option.
611
+ * @param {{ mirrored?: boolean, isMirrored?: boolean, tileData: { dense: Float32Array, tilePos: readonly [a: number, b?: number], shape: readonly [number, number] }}} tile
612
+ * @param {"log" | "linear"} valueScaleType - Either 'log' or 'linear'
613
+ * @param {[min: number, max: number]} valueScaleDomain - The domain of the scale (the range is always [254,0])
614
+ * @param {number} pseudocount
615
+ * @param {ReadonlyArray<readonly [r: number, g: number, b: number, a: number]>} colorScale - a 255 x 4 rgba array used as a color scale
616
+ * @param {(x: null | { pixData: Uint8ClampedArray }) => void} finished
617
+ * @param {boolean | undefined} ignoreUpperRight - If this is a tile along the diagonal and there will be mirrored tiles present ignore the upper right values
618
+ * @param {boolean | undefined} ignoreLowerLeft - If this is a tile along the diagonal and there will be mirrored tiles present ignore the lower left values
619
+ * @param {[r: number, g:number, b: number, a: number]} zeroValueColor - The color to use for rendering zero data values
620
+ * @param {Partial<SelectedRowsOptions>} selectedRowsOptions Rendering options when using a `selectRows` track option.
532
621
  */
533
622
  export const tileDataToPixData = (
534
623
  tile,
@@ -573,19 +662,13 @@ export const tileDataToPixData = (
573
662
  if (ignoreLowerLeft) {
574
663
  for (let row = 0; row < tileWidth; row++) {
575
664
  for (let col = 0; col < row; col++) {
576
- tile.tileData.dense[row * tileWidth + col] = NaN;
665
+ tile.tileData.dense[row * tileWidth + col] = Number.NaN;
577
666
  }
578
667
  }
579
668
  }
580
669
  tile.isMirrored = true;
581
670
  }
582
671
 
583
- // console.log('tile', tile);
584
- // clone the tileData so that the original array doesn't get neutered
585
- // when being passed to the worker script
586
- // const newTileData = tileData.dense;
587
-
588
- // comment this and uncomment the code afterwards to enable threading
589
672
  const pixData = workerSetPix(
590
673
  tileData.dense.length,
591
674
  tileData.dense,
@@ -601,31 +684,35 @@ export const tileDataToPixData = (
601
684
  );
602
685
 
603
686
  finished({ pixData });
687
+ };
604
688
 
605
- // const newTileData = new Float32Array(tileData.dense.length);
606
- // newTileData.set(tileData.dense);
607
- /*
608
- var params = {
609
- size: newTileData.length,
610
- data: newTileData,
611
- valueScaleType: valueScaleType,
612
- valueScaleDomain: valueScaleDomain,
613
- pseudocount: pseudocount,
614
- colorScale: colorScale
615
- };
689
+ /**
690
+ * @template T
691
+ * @overload
692
+ * @param {string | URL} url
693
+ * @param {(err: Error | undefined, value: T | undefined) => void} callback
694
+ * @param {"json"} textOrJson
695
+ * @param {import("pub-sub-es").PubSub} pubSub
696
+ * @returns {Promise<T>}
697
+ */
616
698
 
617
- setPixPool.send(params, [ newTileData.buffer ])
618
- .promise()
619
- .then(returned => {
620
- finished(returned);
621
- })
622
- .catch(reason => {
623
- finished(null);
624
- });
625
- ;
626
- */
627
- };
699
+ /**
700
+ * @overload
701
+ * @param {string | URL} url
702
+ * @param {(err: Error | undefined, value: string | undefined) => void} callback
703
+ * @param {"text"} textOrJson
704
+ * @param {import("pub-sub-es").PubSub} pubSub
705
+ * @returns {Promise<string>}
706
+ */
628
707
 
708
+ /**
709
+ * @template T
710
+ * @param {string | URL} url
711
+ * @param {(err: Error | undefined, value: T | undefined) => void} callback
712
+ * @param {"text" | "json"} textOrJson
713
+ * @param {import("pub-sub-es").PubSub} pubSub
714
+ * @returns {Promise<T>}
715
+ */
629
716
  function fetchEither(url, callback, textOrJson, pubSub) {
630
717
  requestsInFlight += 1;
631
718
  pubSub.publish('requestSent', url);
@@ -638,6 +725,7 @@ function fetchEither(url, callback, textOrJson, pubSub) {
638
725
  } else {
639
726
  throw new Error(`fetch either "text" or "json", not "${textOrJson}"`);
640
727
  }
728
+ /** @type {Record<string, string>} */
641
729
  const headers = {};
642
730
 
643
731
  if (mime) {
@@ -672,8 +760,9 @@ function fetchEither(url, callback, textOrJson, pubSub) {
672
760
  /**
673
761
  * Send a text request and mark it so that we can tell how many are in flight
674
762
  *
675
- * @param url: URL to fetch
676
- * @param callback: Callback to execute with content from fetch
763
+ * @param {string | URL} url
764
+ * @param {(err: Error | undefined, value: string | undefined) => void} callback
765
+ * @param {import("pub-sub-es").PubSub} pubSub
677
766
  */
678
767
  function text(url, callback, pubSub) {
679
768
  return fetchEither(url, callback, 'text', pubSub);
@@ -682,15 +771,12 @@ function text(url, callback, pubSub) {
682
771
  /**
683
772
  * Send a JSON request and mark it so that we can tell how many are in flight
684
773
  *
685
- * @param url: URL to fetch
686
- * @param callback: Callback to execute with content from fetch
774
+ * @template T
775
+ * @param {string} url
776
+ * @param {(err: Error | undefined, value: T | undefined) => void} callback
777
+ * @param {import("pub-sub-es").PubSub} pubSub
687
778
  */
688
779
  async function json(url, callback, pubSub) {
689
- // Fritz: What is going on here? Can someone explain?
690
- if (url.indexOf('hg19') >= 0) {
691
- await sleep(1);
692
- }
693
- // console.log('url:', url);
694
780
  return fetchEither(url, callback, 'json', pubSub);
695
781
  }
696
782
 
@@ -699,8 +785,10 @@ async function json(url, callback, pubSub) {
699
785
  *
700
786
  * @param {string} server: The server where the data resides
701
787
  * @param {string} tilesetUid: The identifier for the dataset
702
- * @param {func} doneCb: A callback that gets called when the data is retrieved
703
- * @param {func} errorCb: A callback that gets called when there is an error
788
+ * @param {(info: Record<string, TilesetInfo>) => void} doneCb: A callback that gets called when the data is retrieved
789
+ * @param {(error: string) => void} errorCb: A callback that gets called when there is an error
790
+ * @param {import("pub-sub-es").PubSub} pubSub
791
+ * @returns {void}
704
792
  */
705
793
  export const trackInfo = (server, tilesetUid, doneCb, errorCb, pubSub) => {
706
794
  const url = `${tts(server)}/tileset_info/?d=${tilesetUid}&s=${sessionId}`;
@@ -709,19 +797,14 @@ export const trackInfo = (server, tilesetUid, doneCb, errorCb, pubSub) => {
709
797
  json(
710
798
  url,
711
799
  (error, data) => {
712
- // eslint-disable-line
713
800
  pubSub.publish('requestReceived', url);
714
801
  if (error) {
715
- // console.log('error:', error);
716
- // don't do anything
717
- // no tileset info just means we can't do anything with this file...
718
802
  if (errorCb) {
719
803
  errorCb(`Error retrieving tilesetInfo from: ${server}`);
720
804
  } else {
721
805
  console.warn('Error retrieving: ', url);
722
806
  }
723
807
  } else {
724
- // console.log('got data', data);
725
808
  doneCb(data);
726
809
  }
727
810
  },