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.
- package/README.md +0 -2
- package/app/globals.d.ts +4 -4
- package/app/missing-types.d.ts +3 -3
- package/app/scripts/AddTrackDialog.jsx +1 -0
- package/app/scripts/AddTrackPositionMenu.jsx +17 -4
- package/app/scripts/Annotations1dTrack.js +1 -0
- package/app/scripts/Annotations2dTrack.js +1 -0
- package/app/scripts/ArrowheadDomainsTrack.js +1 -0
- package/app/scripts/Autocomplete.jsx +1 -0
- package/app/scripts/AxisPixi.js +1 -0
- package/app/scripts/BarTrack.js +1 -0
- package/app/scripts/BedLikeTrack.js +1 -0
- package/app/scripts/Button.jsx +1 -0
- package/app/scripts/CNVIntervalTrack.js +1 -0
- package/app/scripts/CenterTiledPlot.jsx +1 -0
- package/app/scripts/CenterTrack.jsx +1 -0
- package/app/scripts/Chromosome2DAnnotations.js +1 -0
- package/app/scripts/Chromosome2DLabels.js +1 -0
- package/app/scripts/ChromosomeGrid.js +1 -0
- package/app/scripts/ChromosomeInfo.js +1 -0
- package/app/scripts/CloseTrackMenu.jsx +1 -0
- package/app/scripts/CombinedTrack.js +1 -0
- package/app/scripts/ConfigTrackMenu.jsx +1 -0
- package/app/scripts/ConfigViewMenu.jsx +1 -0
- package/app/scripts/ConfigureSeriesMenu.jsx +1 -0
- package/app/scripts/ContextMenuContainer.jsx +1 -0
- package/app/scripts/ContextMenuItem.jsx +1 -0
- package/app/scripts/Cross.jsx +1 -0
- package/app/scripts/CrossRule.js +1 -0
- package/app/scripts/CustomTrackDialog.jsx +1 -0
- package/app/scripts/Dialog.jsx +1 -0
- package/app/scripts/DivergentBarTrack.js +1 -0
- package/app/scripts/DragListeningDiv.jsx +1 -0
- package/app/scripts/DraggableDiv.jsx +1 -0
- package/app/scripts/ExportLinkDialog.jsx +1 -0
- package/app/scripts/FixedTrack.jsx +1 -0
- package/app/scripts/GalleryTracks.jsx +1 -0
- package/app/scripts/GenomePositionSearchBox.jsx +1 -0
- package/app/scripts/HeatmapOptions.jsx +1 -0
- package/app/scripts/HeatmapTiledPixiTrack.js +1 -0
- package/app/scripts/HiGlassComponent.jsx +1 -0
- package/app/scripts/HiGlassTrackComponent.jsx +1 -0
- package/app/scripts/Horizontal1dHeatmapTrack.js +1 -0
- package/app/scripts/Horizontal2DDomainsTrack.js +1 -0
- package/app/scripts/HorizontalChromosomeLabels.js +1 -0
- package/app/scripts/HorizontalGeneAnnotationsTrack.js +1 -0
- package/app/scripts/HorizontalHeatmapTrack.js +1 -0
- package/app/scripts/HorizontalItem.jsx +1 -0
- package/app/scripts/HorizontalLine1DPixiTrack.js +1 -0
- package/app/scripts/HorizontalMultivecTrack.js +1 -0
- package/app/scripts/HorizontalPoint1DPixiTrack.js +1 -0
- package/app/scripts/HorizontalRule.js +1 -0
- package/app/scripts/HorizontalTiled1DPixiTrack.js +1 -0
- package/app/scripts/HorizontalTiledPlot.jsx +1 -0
- package/app/scripts/HorizontalTrack.jsx +1 -0
- package/app/scripts/Id2DTiledPixiTrack.js +1 -0
- package/app/scripts/IdHorizontal1DTiledPixiTrack.js +1 -0
- package/app/scripts/IdVertical1DTiledPixiTrack.js +1 -0
- package/app/scripts/LeftAxisTrack.js +1 -0
- package/app/scripts/LeftTrackModifier.js +1 -0
- package/app/scripts/ListWrapper.jsx +1 -0
- package/app/scripts/MapboxTilesTrack.js +1 -0
- package/app/scripts/Modal.jsx +1 -0
- package/app/scripts/MoveableTrack.jsx +1 -0
- package/app/scripts/NestedContextMenu.jsx +1 -0
- package/app/scripts/OSMTileIdsTrack.js +1 -0
- package/app/scripts/OSMTilesTrack.js +1 -0
- package/app/scripts/OverlayTrack.js +1 -0
- package/app/scripts/PixiTrack.js +0 -1
- package/app/scripts/PlotTypeChooser.jsx +1 -0
- package/app/scripts/PopupMenu.jsx +1 -0
- package/app/scripts/RasterTilesTrack.js +1 -0
- package/app/scripts/RuleMixin.js +1 -0
- package/app/scripts/SVGTrack.js +1 -0
- package/app/scripts/SearchField.js +1 -0
- package/app/scripts/SeriesListItems.jsx +1 -0
- package/app/scripts/SeriesListMenu.jsx +1 -0
- package/app/scripts/SeriesListSubmenuMixin.jsx +1 -0
- package/app/scripts/SketchInlinePicker.jsx +1 -0
- package/app/scripts/SortableList.jsx +1 -0
- package/app/scripts/SquareMarkersTrack.js +1 -0
- package/app/scripts/Tiled1DPixiTrack.js +1 -0
- package/app/scripts/TiledPixiTrack.js +1 -0
- package/app/scripts/TiledPlot.jsx +1 -0
- package/app/scripts/TilesetFinder.jsx +1 -0
- package/app/scripts/TopAxisTrack.js +1 -0
- package/app/scripts/Track.js +0 -1
- package/app/scripts/TrackArea.jsx +1 -0
- package/app/scripts/TrackControl.jsx +1 -0
- package/app/scripts/TrackRenderer.jsx +0 -1
- package/app/scripts/UnknownPixiTrack.js +1 -0
- package/app/scripts/ValueIntervalTrack.js +1 -0
- package/app/scripts/VerticalItem.jsx +1 -0
- package/app/scripts/VerticalRule.js +1 -0
- package/app/scripts/VerticalTiled1DPixiTrack.js +1 -0
- package/app/scripts/VerticalTiledPlot.jsx +1 -0
- package/app/scripts/VerticalTrack.jsx +1 -0
- package/app/scripts/ViewConfigEditor.jsx +1 -0
- package/app/scripts/ViewContextMenu.jsx +1 -0
- package/app/scripts/ViewHeader.jsx +1 -0
- package/app/scripts/ViewportTracker2D.js +1 -0
- package/app/scripts/ViewportTracker2DPixi.js +1 -0
- package/app/scripts/ViewportTrackerHorizontal.js +1 -0
- package/app/scripts/ViewportTrackerVertical.js +1 -0
- package/app/scripts/api.js +1 -0
- package/app/scripts/configs/available-track-types.js +1 -0
- package/app/scripts/configs/colormaps.js +1 -0
- package/app/scripts/configs/datatype-to-track-type.js +1 -0
- package/app/scripts/configs/default-tracks-for-datatype.js +0 -1
- package/app/scripts/configs/dense-data-extrema-config.js +1 -0
- package/app/scripts/configs/globals.js +1 -0
- package/app/scripts/configs/index.js +1 -0
- package/app/scripts/configs/positions-by-datatype.js +1 -0
- package/app/scripts/configs/primitives.js +0 -1
- package/app/scripts/configs/themes.js +1 -0
- package/app/scripts/configs/tracks-info-by-type.js +0 -1
- package/app/scripts/configs/tracks-info.js +0 -1
- package/app/scripts/d3-context-menu.js +1 -0
- package/app/scripts/data-fetchers/DataFetcher.js +193 -153
- package/app/scripts/data-fetchers/genbank-fetcher.js +205 -87
- package/app/scripts/data-fetchers/index.js +1 -0
- package/app/scripts/data-fetchers/local-tile-fetcher.js +37 -4
- package/app/scripts/hglib.jsx +1 -0
- package/app/scripts/hocs/with-modal.jsx +1 -0
- package/app/scripts/hocs/with-pub-sub.jsx +1 -0
- package/app/scripts/hocs/with-theme.jsx +1 -0
- package/app/scripts/icons.jsx +1 -0
- package/app/scripts/mixwith.js +1 -0
- package/app/scripts/options-info.js +1 -0
- package/app/scripts/plugins/available-for-plugins.js +1 -0
- package/app/scripts/plugins/get-data-fetcher.js +1 -0
- package/app/scripts/plugins/index.js +1 -0
- package/app/scripts/services/chrom-info.js +1 -0
- package/app/scripts/services/dom-event.js +1 -0
- package/app/scripts/services/element-resize-listener.js +1 -0
- package/app/scripts/services/index.js +1 -0
- package/app/scripts/services/tile-proxy.js +14 -10
- package/app/scripts/services/worker.js +161 -84
- package/app/scripts/symbol.js +1 -0
- package/app/scripts/test-helpers/index.js +1 -0
- package/app/scripts/test-helpers/test-helpers.jsx +1 -0
- package/app/scripts/track-utils.js +1 -0
- package/app/scripts/types.ts +59 -22
- package/app/scripts/utils/DenseDataExtrema1D.js +32 -19
- package/app/scripts/utils/DenseDataExtrema2D.js +51 -31
- package/app/scripts/utils/LruCache.js +1 -0
- package/app/scripts/utils/abs-to-chr.js +0 -1
- package/app/scripts/utils/accessor-transposition.js +0 -2
- package/app/scripts/utils/add-arrays.js +0 -2
- package/app/scripts/utils/add-class.js +0 -1
- package/app/scripts/utils/add-event-listener-once.js +0 -2
- package/app/scripts/utils/background-task-scheduler.js +0 -2
- package/app/scripts/utils/base64-to-canvas.js +0 -2
- package/app/scripts/utils/chr-to-abs.js +0 -2
- package/app/scripts/utils/chrom-info-bisector.js +0 -1
- package/app/scripts/utils/clone-event.js +0 -2
- package/app/scripts/utils/color-domain-to-rgba-array.js +1 -0
- package/app/scripts/utils/color-to-hex.js +0 -1
- package/app/scripts/utils/color-to-rgba.js +0 -1
- package/app/scripts/utils/data-to-genomic-loci.js +0 -1
- package/app/scripts/utils/debounce.js +0 -2
- package/app/scripts/utils/dec-to-hex-str.js +0 -1
- package/app/scripts/utils/dict-from-tuples.js +0 -2
- package/app/scripts/utils/dict-items.js +0 -2
- package/app/scripts/utils/dict-keys.js +0 -2
- package/app/scripts/utils/dict-values.js +0 -2
- package/app/scripts/utils/download.js +0 -2
- package/app/scripts/utils/expand-combined-tracks.js +1 -0
- package/app/scripts/utils/fill-in-min-widths.js +1 -0
- package/app/scripts/utils/flatten.js +1 -0
- package/app/scripts/utils/for-each.js +0 -1
- package/app/scripts/utils/forward-event.js +0 -1
- package/app/scripts/utils/genome-loci-to-pixels.js +0 -1
- package/app/scripts/utils/genomic-range-to-chromosome-chunks.js +0 -2
- package/app/scripts/utils/get-aggregation-function.js +6 -12
- package/app/scripts/utils/get-default-track-for-datatype.js +1 -0
- package/app/scripts/utils/get-element-dim.js +0 -1
- package/app/scripts/utils/get-higlass-components.js +1 -0
- package/app/scripts/utils/get-track-by-uid.js +1 -0
- package/app/scripts/utils/get-track-conf-from-hgc.js +1 -0
- package/app/scripts/utils/get-track-obj-by-id.js +1 -0
- package/app/scripts/utils/get-track-position-by-uid.js +1 -0
- package/app/scripts/utils/get-xylofon.js +1 -0
- package/app/scripts/utils/gradient.js +0 -2
- package/app/scripts/utils/has-class.js +0 -2
- package/app/scripts/utils/has-parent.js +1 -0
- package/app/scripts/utils/hex-string-to-int.js +0 -1
- package/app/scripts/utils/index.js +0 -1
- package/app/scripts/utils/interval-tree.js +1 -0
- package/app/scripts/utils/into-the-void.js +0 -1
- package/app/scripts/utils/is-track-or-child-track.js +0 -1
- package/app/scripts/utils/is-track-range-selectable.js +0 -1
- package/app/scripts/utils/is-within.js +0 -2
- package/app/scripts/utils/lat-to-y.js +0 -2
- package/app/scripts/utils/lng-to-x.js +0 -1
- package/app/scripts/utils/load-chrom-infos.js +1 -0
- package/app/scripts/utils/map.js +0 -1
- package/app/scripts/utils/max-non-zero.js +0 -1
- package/app/scripts/utils/max.js +0 -1
- package/app/scripts/utils/min-non-zero.js +0 -1
- package/app/scripts/utils/min.js +0 -1
- package/app/scripts/utils/mod.js +0 -1
- package/app/scripts/utils/ndarray-assign.js +1 -0
- package/app/scripts/utils/ndarray-flatten.js +1 -0
- package/app/scripts/utils/ndarray-to-list.js +1 -0
- package/app/scripts/utils/numericify-version.js +0 -1
- package/app/scripts/utils/obj-vals.js +1 -0
- package/app/scripts/utils/or.js +0 -1
- package/app/scripts/utils/parse-chromsizes-rows.js +0 -2
- package/app/scripts/utils/pixi-text-to-svg.js +1 -0
- package/app/scripts/utils/q.js +1 -0
- package/app/scripts/utils/rad-to-deg.js +0 -1
- package/app/scripts/utils/range-query-2d.js +1 -0
- package/app/scripts/utils/reduce.js +1 -0
- package/app/scripts/utils/rel-to-abs-chrom-pos.js +0 -2
- package/app/scripts/utils/remove-class.js +0 -1
- package/app/scripts/utils/reset-d3-brush-style.js +0 -2
- package/app/scripts/utils/rgb-to-hex.js +0 -2
- package/app/scripts/utils/scales-center-and-k.js +0 -2
- package/app/scripts/utils/scales-to-genome-loci.js +0 -1
- package/app/scripts/utils/segments-to-rows.js +1 -0
- package/app/scripts/utils/selected-items-to-cum-weights.js +0 -1
- package/app/scripts/utils/selected-items-to-size.js +0 -1
- package/app/scripts/utils/show-mouse-position.js +0 -1
- package/app/scripts/utils/some.js +0 -1
- package/app/scripts/utils/sum.js +0 -1
- package/app/scripts/utils/svg-line.js +1 -0
- package/app/scripts/utils/throttle-and-debounce.js +0 -1
- package/app/scripts/utils/tile-to-canvas.js +0 -1
- package/app/scripts/utils/timeout.js +0 -1
- package/app/scripts/utils/to-void.js +0 -1
- package/app/scripts/utils/total-track-pixel-height.js +0 -1
- package/app/scripts/utils/trim-trailing-slash.js +0 -1
- package/app/scripts/utils/type-guards.js +0 -2
- package/app/scripts/utils/value-to-color.js +0 -1
- package/app/scripts/utils/visit-positioned-tracks.js +0 -1
- package/app/scripts/utils/visit-tracks.js +0 -1
- package/dist/esm.html +13 -14
- package/dist/hglib.css +1 -1724
- package/dist/hglib.js +122661 -28
- package/dist/hglib.min.js +116 -119
- package/dist/higlass.mjs +122643 -28
- package/dist/index.html +5 -6
- 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
|
-
* @
|
|
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
|
-
|
|
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
|
|
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
|
-
/**
|
|
119
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
-
|
|
166
|
-
.then(() => {
|
|
266
|
+
return this.gbDataPromise
|
|
267
|
+
.then((gbData) => {
|
|
167
268
|
this.tilesetInfoLoading = false;
|
|
168
269
|
|
|
169
270
|
const TILE_SIZE = 1024;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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(
|
|
276
|
+
Math.log(gbData.json[0].size / TILE_SIZE) / Math.log(2),
|
|
176
277
|
),
|
|
177
|
-
max_width:
|
|
278
|
+
max_width: gbData.json[0].size,
|
|
178
279
|
min_pos: [0],
|
|
179
|
-
max_pos: [
|
|
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
|
-
|
|
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)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
-
|
|
227
|
-
});
|
|
228
|
-
// tiles = tileResponseToData(tiles, null, tileIds);
|
|
335
|
+
receivedTiles(tiles);
|
|
229
336
|
return tiles;
|
|
230
337
|
}
|
|
231
338
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
266
|
-
|
|
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
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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,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
|
-
|
|
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
|
|
package/app/scripts/hglib.jsx
CHANGED
package/app/scripts/icons.jsx
CHANGED
package/app/scripts/mixwith.js
CHANGED
|
@@ -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
|
|
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
|
|
411
|
-
* @param minX
|
|
412
|
-
* @param maxX
|
|
413
|
-
* @param maxZoom
|
|
414
|
-
* @param maxDim
|
|
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
|
|
466
|
-
* @param scale
|
|
467
|
-
* @param minX
|
|
468
|
-
* @param maxX
|
|
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,
|