higlass 1.13.2 → 1.13.3

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 (244) hide show
  1. package/README.md +0 -2
  2. package/app/globals.d.ts +4 -4
  3. package/app/missing-types.d.ts +3 -3
  4. package/app/scripts/AddTrackDialog.jsx +1 -0
  5. package/app/scripts/AddTrackPositionMenu.jsx +17 -4
  6. package/app/scripts/Annotations1dTrack.js +1 -0
  7. package/app/scripts/Annotations2dTrack.js +1 -0
  8. package/app/scripts/ArrowheadDomainsTrack.js +1 -0
  9. package/app/scripts/Autocomplete.jsx +1 -0
  10. package/app/scripts/AxisPixi.js +1 -0
  11. package/app/scripts/BarTrack.js +1 -0
  12. package/app/scripts/BedLikeTrack.js +1 -0
  13. package/app/scripts/Button.jsx +1 -0
  14. package/app/scripts/CNVIntervalTrack.js +1 -0
  15. package/app/scripts/CenterTiledPlot.jsx +1 -0
  16. package/app/scripts/CenterTrack.jsx +1 -0
  17. package/app/scripts/Chromosome2DAnnotations.js +1 -0
  18. package/app/scripts/Chromosome2DLabels.js +1 -0
  19. package/app/scripts/ChromosomeGrid.js +1 -0
  20. package/app/scripts/ChromosomeInfo.js +1 -0
  21. package/app/scripts/CloseTrackMenu.jsx +1 -0
  22. package/app/scripts/CombinedTrack.js +1 -0
  23. package/app/scripts/ConfigTrackMenu.jsx +1 -0
  24. package/app/scripts/ConfigViewMenu.jsx +1 -0
  25. package/app/scripts/ConfigureSeriesMenu.jsx +1 -0
  26. package/app/scripts/ContextMenuContainer.jsx +1 -0
  27. package/app/scripts/ContextMenuItem.jsx +1 -0
  28. package/app/scripts/Cross.jsx +1 -0
  29. package/app/scripts/CrossRule.js +1 -0
  30. package/app/scripts/CustomTrackDialog.jsx +1 -0
  31. package/app/scripts/Dialog.jsx +1 -0
  32. package/app/scripts/DivergentBarTrack.js +1 -0
  33. package/app/scripts/DragListeningDiv.jsx +1 -0
  34. package/app/scripts/DraggableDiv.jsx +1 -0
  35. package/app/scripts/ExportLinkDialog.jsx +1 -0
  36. package/app/scripts/FixedTrack.jsx +1 -0
  37. package/app/scripts/GalleryTracks.jsx +1 -0
  38. package/app/scripts/GenomePositionSearchBox.jsx +1 -0
  39. package/app/scripts/HeatmapOptions.jsx +1 -0
  40. package/app/scripts/HeatmapTiledPixiTrack.js +1 -0
  41. package/app/scripts/HiGlassComponent.jsx +1 -0
  42. package/app/scripts/HiGlassTrackComponent.jsx +1 -0
  43. package/app/scripts/Horizontal1dHeatmapTrack.js +1 -0
  44. package/app/scripts/Horizontal2DDomainsTrack.js +1 -0
  45. package/app/scripts/HorizontalChromosomeLabels.js +1 -0
  46. package/app/scripts/HorizontalGeneAnnotationsTrack.js +1 -0
  47. package/app/scripts/HorizontalHeatmapTrack.js +1 -0
  48. package/app/scripts/HorizontalItem.jsx +1 -0
  49. package/app/scripts/HorizontalLine1DPixiTrack.js +1 -0
  50. package/app/scripts/HorizontalMultivecTrack.js +1 -0
  51. package/app/scripts/HorizontalPoint1DPixiTrack.js +1 -0
  52. package/app/scripts/HorizontalRule.js +1 -0
  53. package/app/scripts/HorizontalTiled1DPixiTrack.js +1 -0
  54. package/app/scripts/HorizontalTiledPlot.jsx +1 -0
  55. package/app/scripts/HorizontalTrack.jsx +1 -0
  56. package/app/scripts/Id2DTiledPixiTrack.js +1 -0
  57. package/app/scripts/IdHorizontal1DTiledPixiTrack.js +1 -0
  58. package/app/scripts/IdVertical1DTiledPixiTrack.js +1 -0
  59. package/app/scripts/LeftAxisTrack.js +1 -0
  60. package/app/scripts/LeftTrackModifier.js +1 -0
  61. package/app/scripts/ListWrapper.jsx +1 -0
  62. package/app/scripts/MapboxTilesTrack.js +1 -0
  63. package/app/scripts/Modal.jsx +1 -0
  64. package/app/scripts/MoveableTrack.jsx +1 -0
  65. package/app/scripts/NestedContextMenu.jsx +1 -0
  66. package/app/scripts/OSMTileIdsTrack.js +1 -0
  67. package/app/scripts/OSMTilesTrack.js +1 -0
  68. package/app/scripts/OverlayTrack.js +1 -0
  69. package/app/scripts/PixiTrack.js +0 -1
  70. package/app/scripts/PlotTypeChooser.jsx +1 -0
  71. package/app/scripts/PopupMenu.jsx +1 -0
  72. package/app/scripts/RasterTilesTrack.js +1 -0
  73. package/app/scripts/RuleMixin.js +1 -0
  74. package/app/scripts/SVGTrack.js +1 -0
  75. package/app/scripts/SearchField.js +1 -0
  76. package/app/scripts/SeriesListItems.jsx +1 -0
  77. package/app/scripts/SeriesListMenu.jsx +1 -0
  78. package/app/scripts/SeriesListSubmenuMixin.jsx +1 -0
  79. package/app/scripts/SketchInlinePicker.jsx +1 -0
  80. package/app/scripts/SortableList.jsx +1 -0
  81. package/app/scripts/SquareMarkersTrack.js +1 -0
  82. package/app/scripts/Tiled1DPixiTrack.js +1 -0
  83. package/app/scripts/TiledPixiTrack.js +1 -0
  84. package/app/scripts/TiledPlot.jsx +1 -0
  85. package/app/scripts/TilesetFinder.jsx +1 -0
  86. package/app/scripts/TopAxisTrack.js +1 -0
  87. package/app/scripts/Track.js +0 -1
  88. package/app/scripts/TrackArea.jsx +1 -0
  89. package/app/scripts/TrackControl.jsx +1 -0
  90. package/app/scripts/TrackRenderer.jsx +0 -1
  91. package/app/scripts/UnknownPixiTrack.js +1 -0
  92. package/app/scripts/ValueIntervalTrack.js +1 -0
  93. package/app/scripts/VerticalItem.jsx +1 -0
  94. package/app/scripts/VerticalRule.js +1 -0
  95. package/app/scripts/VerticalTiled1DPixiTrack.js +1 -0
  96. package/app/scripts/VerticalTiledPlot.jsx +1 -0
  97. package/app/scripts/VerticalTrack.jsx +1 -0
  98. package/app/scripts/ViewConfigEditor.jsx +1 -0
  99. package/app/scripts/ViewContextMenu.jsx +1 -0
  100. package/app/scripts/ViewHeader.jsx +1 -0
  101. package/app/scripts/ViewportTracker2D.js +1 -0
  102. package/app/scripts/ViewportTracker2DPixi.js +1 -0
  103. package/app/scripts/ViewportTrackerHorizontal.js +1 -0
  104. package/app/scripts/ViewportTrackerVertical.js +1 -0
  105. package/app/scripts/api.js +1 -0
  106. package/app/scripts/configs/available-track-types.js +1 -0
  107. package/app/scripts/configs/colormaps.js +1 -0
  108. package/app/scripts/configs/datatype-to-track-type.js +1 -0
  109. package/app/scripts/configs/default-tracks-for-datatype.js +0 -1
  110. package/app/scripts/configs/dense-data-extrema-config.js +1 -0
  111. package/app/scripts/configs/globals.js +1 -0
  112. package/app/scripts/configs/index.js +1 -0
  113. package/app/scripts/configs/positions-by-datatype.js +1 -0
  114. package/app/scripts/configs/primitives.js +0 -1
  115. package/app/scripts/configs/themes.js +1 -0
  116. package/app/scripts/configs/tracks-info-by-type.js +0 -1
  117. package/app/scripts/configs/tracks-info.js +0 -1
  118. package/app/scripts/d3-context-menu.js +1 -0
  119. package/app/scripts/data-fetchers/DataFetcher.js +193 -153
  120. package/app/scripts/data-fetchers/genbank-fetcher.js +205 -87
  121. package/app/scripts/data-fetchers/index.js +1 -0
  122. package/app/scripts/data-fetchers/local-tile-fetcher.js +37 -4
  123. package/app/scripts/hglib.jsx +1 -0
  124. package/app/scripts/hocs/with-modal.jsx +1 -0
  125. package/app/scripts/hocs/with-pub-sub.jsx +1 -0
  126. package/app/scripts/hocs/with-theme.jsx +1 -0
  127. package/app/scripts/icons.jsx +1 -0
  128. package/app/scripts/mixwith.js +1 -0
  129. package/app/scripts/options-info.js +1 -0
  130. package/app/scripts/plugins/available-for-plugins.js +1 -0
  131. package/app/scripts/plugins/get-data-fetcher.js +1 -0
  132. package/app/scripts/plugins/index.js +1 -0
  133. package/app/scripts/services/chrom-info.js +1 -0
  134. package/app/scripts/services/dom-event.js +1 -0
  135. package/app/scripts/services/element-resize-listener.js +1 -0
  136. package/app/scripts/services/index.js +1 -0
  137. package/app/scripts/services/tile-proxy.js +14 -10
  138. package/app/scripts/services/worker.js +161 -84
  139. package/app/scripts/symbol.js +1 -0
  140. package/app/scripts/test-helpers/index.js +1 -0
  141. package/app/scripts/test-helpers/test-helpers.jsx +1 -0
  142. package/app/scripts/track-utils.js +1 -0
  143. package/app/scripts/types.ts +59 -22
  144. package/app/scripts/utils/DenseDataExtrema1D.js +32 -19
  145. package/app/scripts/utils/DenseDataExtrema2D.js +51 -31
  146. package/app/scripts/utils/LruCache.js +1 -0
  147. package/app/scripts/utils/abs-to-chr.js +0 -1
  148. package/app/scripts/utils/accessor-transposition.js +0 -2
  149. package/app/scripts/utils/add-arrays.js +0 -2
  150. package/app/scripts/utils/add-class.js +0 -1
  151. package/app/scripts/utils/add-event-listener-once.js +0 -2
  152. package/app/scripts/utils/background-task-scheduler.js +0 -2
  153. package/app/scripts/utils/base64-to-canvas.js +0 -2
  154. package/app/scripts/utils/chr-to-abs.js +0 -2
  155. package/app/scripts/utils/chrom-info-bisector.js +0 -1
  156. package/app/scripts/utils/clone-event.js +0 -2
  157. package/app/scripts/utils/color-domain-to-rgba-array.js +1 -0
  158. package/app/scripts/utils/color-to-hex.js +0 -1
  159. package/app/scripts/utils/color-to-rgba.js +0 -1
  160. package/app/scripts/utils/data-to-genomic-loci.js +0 -1
  161. package/app/scripts/utils/debounce.js +0 -2
  162. package/app/scripts/utils/dec-to-hex-str.js +0 -1
  163. package/app/scripts/utils/dict-from-tuples.js +0 -2
  164. package/app/scripts/utils/dict-items.js +0 -2
  165. package/app/scripts/utils/dict-keys.js +0 -2
  166. package/app/scripts/utils/dict-values.js +0 -2
  167. package/app/scripts/utils/download.js +0 -2
  168. package/app/scripts/utils/expand-combined-tracks.js +1 -0
  169. package/app/scripts/utils/fill-in-min-widths.js +1 -0
  170. package/app/scripts/utils/flatten.js +1 -0
  171. package/app/scripts/utils/for-each.js +0 -1
  172. package/app/scripts/utils/forward-event.js +0 -1
  173. package/app/scripts/utils/genome-loci-to-pixels.js +0 -1
  174. package/app/scripts/utils/genomic-range-to-chromosome-chunks.js +0 -2
  175. package/app/scripts/utils/get-aggregation-function.js +6 -12
  176. package/app/scripts/utils/get-default-track-for-datatype.js +1 -0
  177. package/app/scripts/utils/get-element-dim.js +0 -1
  178. package/app/scripts/utils/get-higlass-components.js +1 -0
  179. package/app/scripts/utils/get-track-by-uid.js +1 -0
  180. package/app/scripts/utils/get-track-conf-from-hgc.js +1 -0
  181. package/app/scripts/utils/get-track-obj-by-id.js +1 -0
  182. package/app/scripts/utils/get-track-position-by-uid.js +1 -0
  183. package/app/scripts/utils/get-xylofon.js +1 -0
  184. package/app/scripts/utils/gradient.js +0 -2
  185. package/app/scripts/utils/has-class.js +0 -2
  186. package/app/scripts/utils/has-parent.js +1 -0
  187. package/app/scripts/utils/hex-string-to-int.js +0 -1
  188. package/app/scripts/utils/index.js +0 -1
  189. package/app/scripts/utils/interval-tree.js +1 -0
  190. package/app/scripts/utils/into-the-void.js +0 -1
  191. package/app/scripts/utils/is-track-or-child-track.js +0 -1
  192. package/app/scripts/utils/is-track-range-selectable.js +0 -1
  193. package/app/scripts/utils/is-within.js +0 -2
  194. package/app/scripts/utils/lat-to-y.js +0 -2
  195. package/app/scripts/utils/lng-to-x.js +0 -1
  196. package/app/scripts/utils/load-chrom-infos.js +1 -0
  197. package/app/scripts/utils/map.js +0 -1
  198. package/app/scripts/utils/max-non-zero.js +0 -1
  199. package/app/scripts/utils/max.js +0 -1
  200. package/app/scripts/utils/min-non-zero.js +0 -1
  201. package/app/scripts/utils/min.js +0 -1
  202. package/app/scripts/utils/mod.js +0 -1
  203. package/app/scripts/utils/ndarray-assign.js +1 -0
  204. package/app/scripts/utils/ndarray-flatten.js +1 -0
  205. package/app/scripts/utils/ndarray-to-list.js +1 -0
  206. package/app/scripts/utils/numericify-version.js +0 -1
  207. package/app/scripts/utils/obj-vals.js +1 -0
  208. package/app/scripts/utils/or.js +0 -1
  209. package/app/scripts/utils/parse-chromsizes-rows.js +0 -2
  210. package/app/scripts/utils/pixi-text-to-svg.js +1 -0
  211. package/app/scripts/utils/q.js +1 -0
  212. package/app/scripts/utils/rad-to-deg.js +0 -1
  213. package/app/scripts/utils/range-query-2d.js +1 -0
  214. package/app/scripts/utils/reduce.js +1 -0
  215. package/app/scripts/utils/rel-to-abs-chrom-pos.js +0 -2
  216. package/app/scripts/utils/remove-class.js +0 -1
  217. package/app/scripts/utils/reset-d3-brush-style.js +0 -2
  218. package/app/scripts/utils/rgb-to-hex.js +0 -2
  219. package/app/scripts/utils/scales-center-and-k.js +0 -2
  220. package/app/scripts/utils/scales-to-genome-loci.js +0 -1
  221. package/app/scripts/utils/segments-to-rows.js +1 -0
  222. package/app/scripts/utils/selected-items-to-cum-weights.js +0 -1
  223. package/app/scripts/utils/selected-items-to-size.js +0 -1
  224. package/app/scripts/utils/show-mouse-position.js +0 -1
  225. package/app/scripts/utils/some.js +0 -1
  226. package/app/scripts/utils/sum.js +0 -1
  227. package/app/scripts/utils/svg-line.js +1 -0
  228. package/app/scripts/utils/throttle-and-debounce.js +0 -1
  229. package/app/scripts/utils/tile-to-canvas.js +0 -1
  230. package/app/scripts/utils/timeout.js +0 -1
  231. package/app/scripts/utils/to-void.js +0 -1
  232. package/app/scripts/utils/total-track-pixel-height.js +0 -1
  233. package/app/scripts/utils/trim-trailing-slash.js +0 -1
  234. package/app/scripts/utils/type-guards.js +0 -2
  235. package/app/scripts/utils/value-to-color.js +0 -1
  236. package/app/scripts/utils/visit-positioned-tracks.js +0 -1
  237. package/app/scripts/utils/visit-tracks.js +0 -1
  238. package/dist/esm.html +13 -14
  239. package/dist/hglib.css +1 -1724
  240. package/dist/hglib.js +122661 -28
  241. package/dist/hglib.min.js +116 -119
  242. package/dist/higlass.mjs +122643 -28
  243. package/dist/index.html +5 -6
  244. package/package.json +23 -16
@@ -2,6 +2,13 @@ import slugid from 'slugid';
2
2
  import pako from 'pako';
3
3
  import genbankParser from 'genbank-parser';
4
4
 
5
+ /**
6
+ * @template T
7
+ * @typedef {import('../types').AbstractDataFetcher<T>} AbstractDataFetcher
8
+ */
9
+
10
+ /** @typedef {{ start: number, end: number, type: 'filler', strand: "+" | "-" }} FillerSegment */
11
+
5
12
  /**
6
13
  * Take a list of genes, which can be any list with elements containing
7
14
  * { start, end } fields and return another list of { start, end }
@@ -10,8 +17,14 @@ import genbankParser from 'genbank-parser';
10
17
  * The segments should be sorted by their start coordinate.
11
18
  *
12
19
  * The scale parameter is the number of base pairs per pixels
20
+ *
21
+ * @param {ArrayLike<{ start: number, end: number }>} segments
22
+ * @param {number} scale
23
+ * @param {"+" | "-"} strand
24
+ * @returns {Array<FillerSegment>}
13
25
  */
14
- function collapse(segments, scale) {
26
+ function collapse(segments, scale, strand) {
27
+ /** @type {Array<FillerSegment>} */
15
28
  const collapsed = [];
16
29
 
17
30
  // the maximum distance we allow between segments before collapsing them
@@ -38,6 +51,7 @@ function collapse(segments, scale) {
38
51
  type: 'filler',
39
52
  start: currStart,
40
53
  end: currEnd,
54
+ strand,
41
55
  });
42
56
 
43
57
  // start a new collapsed segment
@@ -51,6 +65,7 @@ function collapse(segments, scale) {
51
65
  start: currStart,
52
66
  end: currEnd,
53
67
  type: 'filler',
68
+ strand,
54
69
  });
55
70
 
56
71
  return collapsed;
@@ -58,7 +73,9 @@ function collapse(segments, scale) {
58
73
 
59
74
  /**
60
75
  * Shuffles array in place.
61
- * @param {Array} a items An array containing the items.
76
+ * @template T
77
+ * @param {Array<T>} a items An array containing the items.
78
+ * @returns {Array<T>} The (mutated) shuffled array
62
79
  */
63
80
  function shuffle(a) {
64
81
  for (let i = a.length - 1; i > 0; i--) {
@@ -70,12 +87,67 @@ function shuffle(a) {
70
87
  return a;
71
88
  }
72
89
 
73
- function gbToHgGene(gb) {
90
+ /** @typedef {import('genbank-parser').ParsedGenbank["features"][number]} GenbankFeature */
91
+
92
+ /**
93
+ * @typedef FillerGeneAnnotation
94
+ * @prop {number} xStart
95
+ * @prop {number} xEnd
96
+ * @prop {'+' | '-'} strand
97
+ * @prop {string} uid
98
+ * @prop {'filler'} type
99
+ * @prop {[]} fields
100
+ */
101
+
102
+ /**
103
+ * @typedef CompleteGeneAnnotation
104
+ * @prop {number} xStart
105
+ * @prop {number} xEnd
106
+ * @prop {'+' | '-'} strand
107
+ * @prop {number} chrOffset
108
+ * @prop {number} importance
109
+ * @prop {string} uid
110
+ * @prop {string=} type
111
+ * @prop {[
112
+ * chr: 'chrom',
113
+ * start: number,
114
+ * end: number,
115
+ * name: string,
116
+ * importance: number,
117
+ * strand: '+' | '-',
118
+ * _unknown0: string,
119
+ * _unknown1: string,
120
+ * type: string,
121
+ * name: string,
122
+ * start: string,
123
+ * end: string,
124
+ * start: string,
125
+ * end: string,
126
+ * ]} fields
127
+ */
128
+
129
+ /** @typedef {CompleteGeneAnnotation | FillerGeneAnnotation} GeneAnnotation */
130
+
131
+ /**
132
+ * @param {GenbankFeature | FillerSegment} x
133
+ * @returns {x is FillerSegment}
134
+ */
135
+ function isFillerSegment(x) {
136
+ return x.type === 'filler';
137
+ }
138
+
139
+ /**
140
+ * Convert a genbank feature to a higlass gene annotation
141
+ *
142
+ * @param {GenbankFeature | FillerSegment} gb
143
+ * @returns {GeneAnnotation}
144
+ */
145
+ function genbankFeatureToHiGlassGeneAnnotation(gb) {
74
146
  const importance = gb.end - gb.start;
75
147
  const strand = gb.strand === 1 ? '+' : '-';
76
148
  const uid = slugid.nice();
77
149
 
78
- if (gb.type === 'filler') {
150
+ if (isFillerSegment(gb)) {
79
151
  // this is annotation that was generated by collapsing genes and is
80
152
  // only meant to show that there is something there.
81
153
  return {
@@ -115,68 +187,97 @@ function gbToHgGene(gb) {
115
187
  };
116
188
  }
117
189
 
118
- /** Convert genbank text to a JSON representation and extract features * */
119
- const gbToJsonAndFeatures = (gbText) => {
190
+ /**
191
+ * Convert genbank text to a JSON representation and extract features
192
+ * @param {string} gbText
193
+ * @returns {{
194
+ * json: import('genbank-parser').ParsedGenbank[],
195
+ * features: GenbankFeature[],
196
+ * }}
197
+ */
198
+ function gbToJsonAndFeatures(gbText) {
120
199
  const gbJson = genbankParser(gbText);
121
200
  const features = shuffle(
122
201
  gbJson[0].features
123
202
  .filter((f) => f.type !== 'source')
124
203
  .sort((a, b) => a.start - b.start),
125
204
  );
205
+ return { json: gbJson, features };
206
+ }
207
+
208
+ /**
209
+ * Extract the response from a fetch request
210
+ * @param {Response} response
211
+ * @param {{ gzipped: boolean }} options
212
+ * @returns {Promise<string>}
213
+ */
214
+ async function extractResponse(response, { gzipped }) {
215
+ if (!gzipped) return response.text();
216
+ const buffer = await response.arrayBuffer();
217
+ return pako.inflate(buffer, { to: 'string' });
218
+ }
126
219
 
127
- return [gbJson, features];
128
- };
220
+ /**
221
+ * @typedef GenbankDataConfig
222
+ * @prop {string=} url
223
+ * @prop {string=} text
224
+ */
129
225
 
226
+ /**
227
+ * @typedef {Array<GeneAnnotation> & { tilePositionId?: string }} GenbankTile
228
+ */
229
+
230
+ /** @implements {AbstractDataFetcher<GenbankTile>} */
130
231
  class GBKDataFetcher {
232
+ /** @param {GenbankDataConfig} dataConfig */
131
233
  constructor(dataConfig) {
234
+ /** @type {GenbankDataConfig} */
132
235
  this.dataConfig = dataConfig;
236
+ /** @type {string} */
133
237
  this.trackUid = slugid.nice();
238
+ /** @type {string} */
239
+ this.errorTxt = '';
240
+
241
+ /** @type {Promise<string>} */
242
+ let textPromise;
134
243
 
135
244
  if (dataConfig.url) {
136
245
  const extension = dataConfig.url.slice(dataConfig.url.length - 3);
137
- const gzipped = extension === '.gz';
138
- this.errorTxt = '';
139
-
140
- this.dataPromise = fetch(dataConfig.url, {
246
+ textPromise = fetch(dataConfig.url, {
141
247
  mode: 'cors',
142
248
  redirect: 'follow',
143
249
  method: 'GET',
144
- })
145
- .then((response) =>
146
- gzipped ? response.arrayBuffer() : response.text(),
147
- )
148
- .then((buffer) => {
149
- const gffText = gzipped
150
- ? pako.inflate(buffer, { to: 'string' })
151
- : buffer;
152
- [this.gbJson, this.cdss] = gbToJsonAndFeatures(gffText);
153
- });
250
+ }).then((r) => extractResponse(r, { gzipped: extension === '.gz' }));
154
251
  } else if (dataConfig.text) {
155
- this.dataPromise = new Promise((resolve, reject) => {
156
- [this.gbJson, this.cdss] = gbToJsonAndFeatures(dataConfig.text);
157
- resolve();
158
- });
252
+ textPromise = Promise.resolve(dataConfig.text);
253
+ } else {
254
+ throw new Error('No data or URL specified');
159
255
  }
256
+ /** @type {Promise<ReturnType<typeof gbToJsonAndFeatures>>} */
257
+ this.gbDataPromise = textPromise.then((text) => gbToJsonAndFeatures(text));
160
258
  }
161
259
 
260
+ /**
261
+ * @param {import('../types').HandleTilesetInfoFinished} [callback]
262
+ * @returns {Promise<import('../types').LegacyTilesetInfo | undefined>}
263
+ */
162
264
  tilesetInfo(callback) {
163
265
  this.tilesetInfoLoading = true;
164
-
165
- return this.dataPromise
166
- .then(() => {
266
+ return this.gbDataPromise
267
+ .then((gbData) => {
167
268
  this.tilesetInfoLoading = false;
168
269
 
169
270
  const TILE_SIZE = 1024;
170
- let retVal = {};
171
- // retVal[this.trackUid] = {
172
- retVal = {
271
+ /** @satisfies {import('../types').LegacyTilesetInfo} */
272
+ const retVal = {
273
+ name: `genbank-${this.trackUid}`,
173
274
  tile_size: TILE_SIZE,
174
275
  max_zoom: Math.ceil(
175
- Math.log(this.gbJson[0].size / TILE_SIZE) / Math.log(2),
276
+ Math.log(gbData.json[0].size / TILE_SIZE) / Math.log(2),
176
277
  ),
177
- max_width: this.gbJson[0].size,
278
+ max_width: gbData.json[0].size,
178
279
  min_pos: [0],
179
- max_pos: [this.gbJson[0].size],
280
+ max_pos: [gbData.json[0].size],
180
281
  };
181
282
 
182
283
  if (callback) {
@@ -193,13 +294,21 @@ class GBKDataFetcher {
193
294
  error: `Error parsing genbank: ${err}`,
194
295
  });
195
296
  }
297
+ return undefined;
196
298
  });
197
299
  }
198
300
 
199
- fetchTilesDebounced(receivedTiles, tileIds) {
301
+ /**
302
+ * @param {(tiles: Record<string, GenbankTile>) => void} receivedTiles
303
+ * @param {string[]} tileIds
304
+ * @returns {Promise<Record<string, GenbankTile>>}
305
+ */
306
+ async fetchTilesDebounced(receivedTiles, tileIds) {
307
+ /** @type {Record<string, GenbankTile>} */
200
308
  const tiles = {};
201
-
309
+ /** @type {string[]} */
202
310
  const validTileIds = [];
311
+ /** @type {Promise<GeneAnnotation[]>[]} */
203
312
  const tilePromises = [];
204
313
 
205
314
  for (const tileId of tileIds) {
@@ -216,62 +325,71 @@ class GBKDataFetcher {
216
325
  tilePromises.push(this.tile(z, x));
217
326
  }
218
327
 
219
- Promise.all(tilePromises).then((values) => {
220
- for (let i = 0; i < values.length; i++) {
221
- const validTileId = validTileIds[i];
222
- tiles[validTileId] = values[i];
223
- tiles[validTileId].tilePositionId = validTileId;
224
- }
328
+ const values = await Promise.all(tilePromises);
329
+ for (let i = 0; i < values.length; i++) {
330
+ const validTileId = validTileIds[i];
331
+ tiles[validTileId] = values[i];
332
+ tiles[validTileId].tilePositionId = validTileId;
333
+ }
225
334
 
226
- receivedTiles(tiles);
227
- });
228
- // tiles = tileResponseToData(tiles, null, tileIds);
335
+ receivedTiles(tiles);
229
336
  return tiles;
230
337
  }
231
338
 
232
- tile(z, x) {
233
- return this.tilesetInfo().then((tsInfo) => {
234
- const tileWidth = +tsInfo.max_width / 2 ** +z;
235
-
236
- // get the bounds of the tile
237
- const minX = tsInfo.min_pos[0] + x * tileWidth;
238
- const maxX = tsInfo.min_pos[0] + (x + 1) * tileWidth;
239
-
240
- const filtered = this.cdss.filter((v) => v.end > minX && v.start < maxX);
241
- const scaleFactor = 1024 / 2 ** (tsInfo.max_zoom - z);
242
-
243
- const collapsedPlus = collapse(
244
- filtered.filter((v) => v.strand === 1),
245
- scaleFactor,
246
- );
247
- const collapsedMinus = collapse(
248
- filtered.filter((v) => v.strand !== 1),
249
- scaleFactor,
250
- );
251
-
252
- collapsedPlus.forEach((v) => {
253
- v.strand = '+';
254
- });
255
- collapsedMinus.forEach((v) => {
256
- v.strand = '-';
257
- });
258
-
259
- let values = [];
260
- const TILE_CAPACITY = 20;
261
- // fill the tile with entries that are within it
262
- for (let i = 0; i < this.cdss.length; i++) {
263
- if (values.length >= TILE_CAPACITY) break;
339
+ /**
340
+ * @param {number} z
341
+ * @param {number} x
342
+ * @returns {Promise<GeneAnnotation[]>}
343
+ */
344
+ async tile(z, x) {
345
+ const [tsInfo, gbData] = await Promise.all([
346
+ this.tilesetInfo(),
347
+ this.gbDataPromise,
348
+ ]);
349
+ if (!tsInfo) {
350
+ throw new Error('No tileset info');
351
+ }
264
352
 
265
- if (this.cdss[i].end >= minX && this.cdss[i].start <= maxX) {
266
- values.push(this.cdss[i]);
267
- }
353
+ const tileWidth = +tsInfo.max_width / 2 ** +z;
354
+
355
+ // get the bounds of the tile
356
+ const minX = tsInfo.min_pos[0] + x * tileWidth;
357
+ const maxX = tsInfo.min_pos[0] + (x + 1) * tileWidth;
358
+
359
+ const filtered = gbData.features.filter(
360
+ (v) => v.end > minX && v.start < maxX,
361
+ );
362
+ const scaleFactor = 1024 / 2 ** (tsInfo.max_zoom - z);
363
+
364
+ /** @type {Array<FillerSegment>} */
365
+ const collapsedPlus = collapse(
366
+ filtered.filter((v) => v.strand === 1),
367
+ scaleFactor,
368
+ '+',
369
+ );
370
+
371
+ /** @type {Array<FillerSegment>} */
372
+ const collapsedMinus = collapse(
373
+ filtered.filter((v) => v.strand !== 1),
374
+ scaleFactor,
375
+ '-',
376
+ );
377
+
378
+ /** @type {Array<GenbankFeature | FillerSegment>} */
379
+ const values = [];
380
+ const TILE_CAPACITY = 20;
381
+ // fill the tile with entries that are within it
382
+ for (let i = 0; i < gbData.features.length; i++) {
383
+ if (values.length >= TILE_CAPACITY) {
384
+ break;
268
385
  }
269
-
270
- values = [...values, ...collapsedPlus, ...collapsedMinus];
271
- // values = values.concat(collapsedPlus).concat(collapsedMinus);
272
- // we're not going to take into account importance
273
- return values.map((v) => gbToHgGene(v));
274
- });
386
+ if (gbData.features[i].end >= minX && gbData.features[i].start <= maxX) {
387
+ values.push(gbData.features[i]);
388
+ }
389
+ }
390
+ return [values, collapsedPlus, collapsedMinus].flatMap((v) =>
391
+ v.map(genbankFeatureToHiGlassGeneAnnotation),
392
+ );
275
393
  }
276
394
  }
277
395
 
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  export { default as DataFetcher } from './DataFetcher';
2
3
  export { default as GBKDataFetcher } from './genbank-fetcher';
3
4
  export { default as LocalDataFetcher } from './local-tile-fetcher';
@@ -1,24 +1,50 @@
1
1
  import { tileResponseToData } from '../services';
2
2
 
3
+ /** @typedef {import('../types').TilesetInfo} TilesetInfo */
4
+ /**
5
+ * @template T
6
+ * @typedef {import('../types').AbstractDataFetcher<T>} AbstractDataFetcher
7
+ */
8
+
9
+ // TODO: Add type for LocalTile
10
+ /** @typedef {{}} LocalTile */
11
+
12
+ /**
13
+ * @typedef LocalTileDataConfig
14
+ * @property {Record<string, LocalTile>} tiles
15
+ * @property {Record<string, TilesetInfo>} tilesetInfo
16
+ */
17
+
18
+ /** @implements {AbstractDataFetcher<LocalTile>} */
3
19
  class LocalTileDataFetcher {
20
+ /** @param {LocalTileDataConfig} dataConfig */
4
21
  constructor(dataConfig) {
22
+ /** @type {LocalTileDataConfig} */
5
23
  this.dataConfig = dataConfig;
6
-
24
+ /** @type {TilesetInfo} */
7
25
  this.tilesetInfoData = Object.values(this.dataConfig.tilesetInfo)[0];
26
+ /** @type {Record<string, LocalTile>} */
27
+ this.tilesData = {};
28
+ /** @type {boolean} */
29
+ this.tilesetInfoLoading = true;
8
30
  }
9
31
 
10
- tilesetInfo(callback) {
32
+ /** @param {import('../types').HandleTilesetInfoFinished} callback */
33
+ async tilesetInfo(callback) {
11
34
  this.tilesetInfoLoading = false;
12
-
13
35
  callback(this.tilesetInfoData);
36
+ return this.tilesetInfoData;
14
37
  }
15
38
 
16
39
  /** We expect there to be a tilesetUid in the provided tilesetInfo
17
40
  * and tiles data since tileResponseToData needs it
18
41
  *
19
42
  * It is also easier for users to paste in request responses for debugging.
43
+ *
44
+ * @param {(tiles: Record<string, LocalTile>) => void} receivedTiles
45
+ * @param {string[]} tileIds
20
46
  */
21
- fetchTilesDebounced(receivedTiles, tileIds) {
47
+ async fetchTilesDebounced(receivedTiles, tileIds) {
22
48
  this.tilesData = {};
23
49
 
24
50
  for (const key of Object.keys(this.dataConfig.tiles)) {
@@ -27,6 +53,7 @@ class LocalTileDataFetcher {
27
53
  this.tilesData[newKey] = this.dataConfig.tiles[key];
28
54
  }
29
55
 
56
+ /** @type {Record<string, LocalTile>} */
30
57
  const ret = {};
31
58
 
32
59
  const newTileIds = tileIds.map((x) => `localtile.${x}`);
@@ -36,8 +63,14 @@ class LocalTileDataFetcher {
36
63
  ret[tileId] = this.tilesData[`localtile.${tileId}`];
37
64
  }
38
65
  receivedTiles(ret);
66
+ return ret;
39
67
  }
40
68
 
69
+ /**
70
+ * @param {number} z
71
+ * @param {number} x
72
+ * @returns {void}
73
+ */
41
74
  tile(z, x) {}
42
75
  }
43
76
 
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import React from 'react';
2
3
  import ReactDOM from 'react-dom';
3
4
  import HiGlassComponent from './HiGlassComponent';
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  /* eslint-disable react/jsx-props-no-spreading */
2
3
  import React from 'react';
3
4
 
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  /* eslint-disable react/jsx-props-no-spreading */
2
3
  import React from 'react';
3
4
 
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  /* eslint-disable react/jsx-props-no-spreading */
2
3
  import React from 'react';
3
4
 
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import React from 'react';
2
3
  import PropTypes from 'prop-types';
3
4
  import { select } from 'd3-selection';
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  /* eslint-disable max-classes-per-file */
2
3
 
3
4
  // used by apply() and isApplicationOf()
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  // A better position of this file would be under \configs,
2
3
  // but this file imports HeatmapOptions that contains React
3
4
  // components, so having this file near track implementations
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  /**
2
3
  * Code that is available to plugin tracks.
3
4
  */
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import {
2
3
  DataFetcher,
3
4
  GBKDataFetcher,
@@ -1,2 +1,3 @@
1
+ // @ts-nocheck
1
2
  export { default as getDataFetcher } from './get-data-fetcher';
2
3
  export { default as AVAILABLE_FOR_PLUGINS } from './available-for-plugins';
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import { tsvParseRows } from 'd3-dsv';
2
3
  import { parseChromsizesRows } from '../utils';
3
4
 
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  class DomEvent {
2
3
  constructor(pubSub) {
3
4
  /**
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import { getXylofon } from '../utils';
2
3
 
3
4
  let isInit = false;
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  export { default as chromInfo } from './chrom-info';
2
3
  export { default as createDomEvent } from './dom-event';
3
4
  export { default as ElementResizeListener } from './element-resize-listener';
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import { range } from 'd3-array';
2
3
  import slugid from 'slugid';
3
4
 
@@ -404,15 +405,16 @@ export function calculateTileAndPosInTile(
404
405
  * All the parameters except the first should be present in the
405
406
  * tileset_info returned by the server.
406
407
  *
407
- * @param zoomLevel: The zoom level at which to find the tiles (can be
408
+ * @param {number} zoomLevel - The zoom level at which to find the tiles (can be
408
409
  * calculated using this.calcaulteZoomLevel, but needs to synchronized across
409
410
  * both x and y scales so should be calculated externally)
410
- * @param scale: A d3 scale mapping data domain to visible values
411
- * @param minX: The minimum possible value in the dataset
412
- * @param maxX: The maximum possible value in the dataset
413
- * @param maxZoom: The maximum zoom value in this dataset
414
- * @param maxDim: The largest dimension of the tileset (e.g., width or height)
411
+ * @param {import('../type').Scale} scale - A d3 scale mapping data domain to visible values
412
+ * @param {number} minX - The minimum possible value in the dataset
413
+ * @param {number} maxX - The maximum possible value in the dataset
414
+ * @param {number} maxZoom - The maximum zoom value in this dataset
415
+ * @param {number} maxDim - The largest dimension of the tileset (e.g., width or height)
415
416
  * (roughlty equal to 2 ** maxZoom * tileSize * tileResolution)
417
+ * @returns {number[]} The indices of the tiles that should be visible
416
418
  */
417
419
  export const calculateTiles = (
418
420
  zoomLevel,
@@ -462,10 +464,12 @@ export const calculateTileWidth = (tilesetInfo, zoomLevel, binsPerTile) => {
462
464
  * Calculate the tiles that sould be visisble given the resolution and
463
465
  * the minX and maxX values for the region
464
466
  *
465
- * @param resolution: The number of base pairs per bin
466
- * @param scale: The scale to use to calculate the currently visible tiles
467
- * @param minX: The minimum x position of the tileset
468
- * @param maxX: The maximum x position of the tileset
467
+ * @param {number} resolution - The number of base pairs per bin
468
+ * @param {import('../type').Scale} scale - The scale to use to calculate the currently visible tiles
469
+ * @param {number} minX - The minimum x position of the tileset
470
+ * @param {number} maxX - The maximum x position of the tileset
471
+ * @param {number=} pixelsPerTile - The number of pixels per tile
472
+ * @returns {number[]} The indices of the tiles that should be visible
469
473
  */
470
474
  export const calculateTilesFromResolution = (
471
475
  resolution,