higlass 1.13.5 → 1.13.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -54
- package/app/globals.d.ts +1 -1
- package/app/missing-types.d.ts +4 -1
- package/app/scripts/AddTrackDialog.jsx +3 -3
- package/app/scripts/AddTrackPositionMenu.jsx +2 -2
- package/app/scripts/Annotations1dTrack.js +1 -1
- package/app/scripts/Annotations2dTrack.js +3 -5
- package/app/scripts/Autocomplete.jsx +14 -21
- package/app/scripts/AxisPixi.js +6 -10
- package/app/scripts/BarTrack.js +3 -3
- package/app/scripts/BedLikeTrack.js +12 -13
- package/app/scripts/Button.jsx +1 -1
- package/app/scripts/CNVIntervalTrack.js +1 -1
- package/app/scripts/CenterTrack.jsx +8 -7
- package/app/scripts/Chromosome2DAnnotations.js +1 -1
- package/app/scripts/Chromosome2DLabels.js +1 -1
- package/app/scripts/ChromosomeGrid.js +49 -38
- package/app/scripts/ChromosomeInfo.js +1 -1
- package/app/scripts/CombinedTrack.js +3 -1
- package/app/scripts/ConfigTrackMenu.jsx +1 -1
- package/app/scripts/ConfigViewMenu.jsx +2 -2
- package/app/scripts/ContextMenuContainer.jsx +1 -2
- package/app/scripts/ContextMenuItem.jsx +1 -0
- package/app/scripts/CrossRule.js +1 -1
- package/app/scripts/CustomTrackDialog.jsx +2 -2
- package/app/scripts/Dialog.jsx +2 -2
- package/app/scripts/DragListeningDiv.jsx +1 -1
- package/app/scripts/DraggableDiv.jsx +2 -3
- package/app/scripts/ExportLinkDialog.jsx +1 -1
- package/app/scripts/GalleryTracks.jsx +77 -78
- package/app/scripts/GenomePositionSearchBox.jsx +10 -9
- package/app/scripts/HeatmapOptions.jsx +4 -2
- package/app/scripts/HeatmapTiledPixiTrack.js +23 -32
- package/app/scripts/HiGlassComponent.jsx +75 -98
- package/app/scripts/Horizontal1dHeatmapTrack.js +1 -1
- package/app/scripts/Horizontal2DDomainsTrack.js +1 -1
- package/app/scripts/HorizontalChromosomeLabels.js +28 -22
- package/app/scripts/HorizontalGeneAnnotationsTrack.js +1 -1
- package/app/scripts/HorizontalHeatmapTrack.js +2 -2
- package/app/scripts/HorizontalMultivecTrack.js +6 -7
- package/app/scripts/HorizontalRule.js +1 -2
- package/app/scripts/HorizontalTiled1DPixiTrack.js +4 -4
- package/app/scripts/HorizontalTiledPlot.jsx +9 -9
- package/app/scripts/LeftTrackModifier.js +4 -0
- package/app/scripts/ListWrapper.jsx +1 -2
- package/app/scripts/MapboxTilesTrack.js +1 -2
- package/app/scripts/Modal.jsx +2 -2
- package/app/scripts/MoveableTrack.jsx +10 -12
- package/app/scripts/NestedContextMenu.jsx +2 -1
- package/app/scripts/OSMTileIdsTrack.js +1 -1
- package/app/scripts/OverlayTrack.js +4 -4
- package/app/scripts/PixiTrack.js +27 -13
- package/app/scripts/PlotTypeChooser.jsx +3 -4
- package/app/scripts/SearchField.js +5 -5
- package/app/scripts/SeriesListItems.jsx +3 -4
- package/app/scripts/SeriesListMenu.jsx +6 -11
- package/app/scripts/SeriesListSubmenuMixin.jsx +1 -1
- package/app/scripts/SketchInlinePicker.jsx +2 -2
- package/app/scripts/SortableList.jsx +1 -1
- package/app/scripts/Tiled1DPixiTrack.js +5 -1
- package/app/scripts/TiledPixiTrack.js +232 -99
- package/app/scripts/TiledPlot.jsx +33 -43
- package/app/scripts/TilesetFinder.jsx +12 -4
- package/app/scripts/Track.js +1 -1
- package/app/scripts/TrackArea.jsx +4 -0
- package/app/scripts/TrackControl.jsx +2 -2
- package/app/scripts/TrackRenderer.jsx +30 -31
- package/app/scripts/ValueIntervalTrack.js +1 -1
- package/app/scripts/VerticalRule.js +2 -2
- package/app/scripts/VerticalTiledPlot.jsx +7 -7
- package/app/scripts/ViewConfigEditor.jsx +1 -1
- package/app/scripts/ViewContextMenu.jsx +4 -4
- package/app/scripts/ViewHeader.jsx +6 -7
- package/app/scripts/ViewportTracker2D.js +1 -1
- package/app/scripts/api.js +5 -6
- package/app/scripts/configs/available-track-types.js +1 -1
- package/app/scripts/configs/positions-by-datatype.js +2 -2
- package/app/scripts/configs/themes.js +0 -1
- package/app/scripts/configs/tracks-info-by-type.js +11 -8
- package/app/scripts/configs/tracks-info.js +2 -2
- package/app/scripts/d3-context-menu.js +3 -4
- package/app/scripts/data-fetchers/DataFetcher.js +35 -36
- package/app/scripts/data-fetchers/genbank-fetcher.js +6 -10
- package/app/scripts/data-fetchers/local-tile-fetcher.js +2 -6
- package/app/scripts/hglib.jsx +1 -1
- package/app/scripts/hocs/with-modal.jsx +32 -10
- package/app/scripts/hocs/with-pub-sub.js +12 -3
- package/app/scripts/hocs/with-theme.jsx +21 -14
- package/app/scripts/icons.jsx +3 -2
- package/app/scripts/mixwith.js +2 -2
- package/app/scripts/plugins/get-data-fetcher.js +2 -3
- package/app/scripts/services/chrom-info.js +32 -4
- package/app/scripts/services/element-resize-listener.js +2 -2
- package/app/scripts/services/index.js +0 -1
- package/app/scripts/services/tile-proxy.js +368 -281
- package/app/scripts/services/worker.js +30 -28
- package/app/scripts/test-helpers/test-helpers.jsx +3 -3
- package/app/scripts/types.ts +50 -44
- package/app/scripts/utils/LruCache.js +3 -2
- package/app/scripts/utils/assert.js +19 -0
- package/app/scripts/utils/background-task-scheduler.js +2 -0
- package/app/scripts/utils/color-domain-to-rgba-array.js +13 -3
- package/app/scripts/utils/dict-items.js +1 -0
- package/app/scripts/utils/dict-keys.js +1 -0
- package/app/scripts/utils/dict-values.js +1 -0
- package/app/scripts/utils/expand-combined-tracks.js +11 -7
- package/app/scripts/utils/fill-in-min-widths.js +47 -21
- package/app/scripts/utils/flatten.js +0 -1
- package/app/scripts/utils/get-aggregation-function.js +1 -1
- package/app/scripts/utils/get-default-track-for-datatype.js +36 -10
- package/app/scripts/utils/get-higlass-components.js +27 -3
- package/app/scripts/utils/get-track-position-by-uid.js +8 -1
- package/app/scripts/utils/get-xylofon.js +12 -9
- package/app/scripts/utils/has-parent.js +5 -5
- package/app/scripts/utils/hex-string-to-int.js +1 -1
- package/app/scripts/utils/interval-tree.js +222 -177
- package/app/scripts/utils/load-chrom-infos.js +4 -1
- package/app/scripts/utils/pixi-text-to-svg.js +5 -9
- package/app/scripts/utils/range-query-2d.js +3 -3
- package/app/scripts/utils/reduce.js +12 -5
- package/app/scripts/utils/segments-to-rows.js +14 -11
- package/app/scripts/utils/show-mouse-position.js +16 -0
- package/app/scripts/utils/svg-line.js +7 -8
- package/app/scripts/utils/type-guards.js +16 -7
- package/app/scripts/utils/visit-positioned-tracks.js +7 -5
- package/app/styles/d3-context-menu.css +0 -1
- package/app/styles/prism.css +1 -0
- package/dist/hglib.js +78064 -77770
- package/dist/hglib.min.js +109 -109
- package/dist/higlass.mjs +82736 -82442
- package/package.json +13 -18
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import { select, pointer } from 'd3-selection';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { ElementQueries, ResizeSensor } from 'css-element-queries';
|
|
5
4
|
import { scaleLinear } from 'd3-scale';
|
|
6
|
-
import
|
|
5
|
+
import { pointer, select } from 'd3-selection';
|
|
7
6
|
import * as PIXI from 'pixi.js';
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
import createPubSub, { globalPubSub } from 'pub-sub-es';
|
|
9
|
+
import React from 'react';
|
|
8
10
|
import ReactDOM from 'react-dom';
|
|
9
11
|
import ReactGridLayout from 'react-grid-layout';
|
|
10
|
-
import
|
|
11
|
-
import vkbeautify from 'vkbeautify';
|
|
12
|
+
import slugid from 'slugid';
|
|
12
13
|
import parse from 'url-parse';
|
|
13
|
-
import
|
|
14
|
-
import clsx from 'clsx';
|
|
14
|
+
import vkbeautify from 'vkbeautify';
|
|
15
15
|
|
|
16
|
-
import TiledPlot from './TiledPlot';
|
|
17
|
-
import GenomePositionSearchBox from './GenomePositionSearchBox';
|
|
18
|
-
import ExportLinkDialog from './ExportLinkDialog';
|
|
19
|
-
import ViewHeader from './ViewHeader';
|
|
20
16
|
import ChromosomeInfo from './ChromosomeInfo';
|
|
17
|
+
import ExportLinkDialog from './ExportLinkDialog';
|
|
18
|
+
import GenomePositionSearchBox from './GenomePositionSearchBox';
|
|
19
|
+
import TiledPlot from './TiledPlot';
|
|
21
20
|
import ViewConfigEditor from './ViewConfigEditor';
|
|
21
|
+
import ViewHeader from './ViewHeader';
|
|
22
22
|
|
|
23
|
-
import createSymbolIcon from './symbol';
|
|
24
|
-
import { all as icons } from './icons';
|
|
25
23
|
import createApi from './api';
|
|
24
|
+
import { all as icons } from './icons';
|
|
25
|
+
import createSymbolIcon from './symbol';
|
|
26
26
|
|
|
27
|
+
import { Provider as ModalProvider } from './hocs/with-modal';
|
|
27
28
|
// Higher-order components
|
|
28
29
|
import { Provider as PubSubProvider } from './hocs/with-pub-sub';
|
|
29
|
-
import { Provider as ModalProvider } from './hocs/with-modal';
|
|
30
30
|
import { Provider as ThemeProvider } from './hocs/with-theme';
|
|
31
31
|
|
|
32
32
|
// Services
|
|
33
33
|
import {
|
|
34
34
|
chromInfo,
|
|
35
35
|
createDomEvent,
|
|
36
|
+
requestsInFlight,
|
|
36
37
|
setTileProxyAuthHeader,
|
|
37
38
|
tileProxy,
|
|
38
|
-
requestsInFlight,
|
|
39
39
|
} from './services';
|
|
40
40
|
|
|
41
41
|
// Utils
|
|
@@ -64,16 +64,16 @@ import {
|
|
|
64
64
|
|
|
65
65
|
// Configs
|
|
66
66
|
import {
|
|
67
|
-
DEFAULT_SERVER,
|
|
68
67
|
DEFAULT_CONTAINER_PADDING_X,
|
|
69
68
|
DEFAULT_CONTAINER_PADDING_Y,
|
|
69
|
+
DEFAULT_SERVER,
|
|
70
70
|
DEFAULT_VIEW_MARGIN,
|
|
71
71
|
DEFAULT_VIEW_PADDING,
|
|
72
72
|
GLOBALS,
|
|
73
|
-
MOUSE_TOOL_MOVE,
|
|
74
|
-
MOUSE_TOOL_SELECT,
|
|
75
73
|
LOCATION_LISTENER_PREFIX,
|
|
76
74
|
LONG_DRAG_TIMEOUT,
|
|
75
|
+
MOUSE_TOOL_MOVE,
|
|
76
|
+
MOUSE_TOOL_SELECT,
|
|
77
77
|
SHORT_DRAG_TIMEOUT,
|
|
78
78
|
THEME_DARK,
|
|
79
79
|
THEME_LIGHT,
|
|
@@ -81,10 +81,10 @@ import {
|
|
|
81
81
|
} from './configs';
|
|
82
82
|
|
|
83
83
|
// Styles
|
|
84
|
-
import styles from '../styles/HiGlass.module.scss';
|
|
85
|
-
import stylesMTHeader from '../styles/ViewHeader.module.scss';
|
|
84
|
+
import styles from '../styles/HiGlass.module.scss';
|
|
85
|
+
import stylesMTHeader from '../styles/ViewHeader.module.scss';
|
|
86
86
|
|
|
87
|
-
import '../styles/HiGlass.scss';
|
|
87
|
+
import '../styles/HiGlass.scss';
|
|
88
88
|
|
|
89
89
|
const NUM_GRID_COLUMNS = 12;
|
|
90
90
|
const DEFAULT_NEW_VIEW_HEIGHT = 12;
|
|
@@ -116,6 +116,7 @@ class HiGlassComponent extends React.Component {
|
|
|
116
116
|
this.resizeSensor = null;
|
|
117
117
|
|
|
118
118
|
this.uid = slugid.nice();
|
|
119
|
+
/** @type {Record<string, import('./TiledPlot').TiledPlot> */
|
|
119
120
|
this.tiledPlots = {};
|
|
120
121
|
this.genomePositionSearchBoxes = {};
|
|
121
122
|
|
|
@@ -160,7 +161,7 @@ class HiGlassComponent extends React.Component {
|
|
|
160
161
|
|
|
161
162
|
// allow a different PIXI to be passed in case the
|
|
162
163
|
// caller wants to use a different version
|
|
163
|
-
GLOBALS.PIXI =
|
|
164
|
+
GLOBALS.PIXI = props.options?.PIXI || PIXI;
|
|
164
165
|
|
|
165
166
|
this.viewMarginTop =
|
|
166
167
|
+props.options.viewMarginTop >= 0
|
|
@@ -292,7 +293,7 @@ class HiGlassComponent extends React.Component {
|
|
|
292
293
|
mouseOverOverlayUid: null,
|
|
293
294
|
mouseTool,
|
|
294
295
|
isDarkTheme: false,
|
|
295
|
-
rangeSelection1dSize: [0,
|
|
296
|
+
rangeSelection1dSize: [0, Number.POSITIVE_INFINITY],
|
|
296
297
|
rangeSelectionToInt: false,
|
|
297
298
|
modal: null,
|
|
298
299
|
};
|
|
@@ -370,7 +371,6 @@ class HiGlassComponent extends React.Component {
|
|
|
370
371
|
);
|
|
371
372
|
}
|
|
372
373
|
|
|
373
|
-
// eslint-disable-next-line camelcase
|
|
374
374
|
UNSAFE_componentWillMount() {
|
|
375
375
|
this.domEvent.register('keydown', document);
|
|
376
376
|
this.domEvent.register('keyup', document);
|
|
@@ -422,7 +422,6 @@ class HiGlassComponent extends React.Component {
|
|
|
422
422
|
}
|
|
423
423
|
|
|
424
424
|
get sizeMode() {
|
|
425
|
-
// eslint-disable-next-line no-nested-ternary
|
|
426
425
|
return typeof this.props.options.sizeMode === 'undefined'
|
|
427
426
|
? this.props.options.bounded
|
|
428
427
|
? 'bounded'
|
|
@@ -514,7 +513,7 @@ class HiGlassComponent extends React.Component {
|
|
|
514
513
|
autoResize: true,
|
|
515
514
|
};
|
|
516
515
|
|
|
517
|
-
const versionNumber = parseInt(PIXI.VERSION[0], 10);
|
|
516
|
+
const versionNumber = Number.parseInt(PIXI.VERSION[0], 10);
|
|
518
517
|
|
|
519
518
|
if (versionNumber === 4) {
|
|
520
519
|
console.warn(
|
|
@@ -545,7 +544,7 @@ class HiGlassComponent extends React.Component {
|
|
|
545
544
|
|
|
546
545
|
// keep track of the width and height of this element, because it
|
|
547
546
|
// needs to be reflected in the size of our drawing surface
|
|
548
|
-
|
|
547
|
+
|
|
549
548
|
this.setState({
|
|
550
549
|
svgElement: this.svgElement,
|
|
551
550
|
canvasElement: this.canvasElement,
|
|
@@ -623,7 +622,6 @@ class HiGlassComponent extends React.Component {
|
|
|
623
622
|
return views;
|
|
624
623
|
}
|
|
625
624
|
|
|
626
|
-
// eslint-disable-next-line camelcase
|
|
627
625
|
UNSAFE_componentWillReceiveProps(newProps) {
|
|
628
626
|
const viewsByUid = this.loadIfRemoteViewConfig(newProps.viewConfig);
|
|
629
627
|
|
|
@@ -655,7 +653,6 @@ class HiGlassComponent extends React.Component {
|
|
|
655
653
|
});
|
|
656
654
|
}
|
|
657
655
|
|
|
658
|
-
// eslint-disable-next-line camelcase
|
|
659
656
|
UNSAFE_componentWillUpdate() {
|
|
660
657
|
// let width = this.element.clientWidth;
|
|
661
658
|
// let height = this.element.clientHeight;
|
|
@@ -804,10 +801,7 @@ class HiGlassComponent extends React.Component {
|
|
|
804
801
|
const trackOptions = track.options ? track.options : {};
|
|
805
802
|
|
|
806
803
|
if (this.props.options.defaultTrackOptions) {
|
|
807
|
-
if (
|
|
808
|
-
this.props.options.defaultTrackOptions.trackSpecific &&
|
|
809
|
-
this.props.options.defaultTrackOptions.trackSpecific[track.type]
|
|
810
|
-
) {
|
|
804
|
+
if (this.props.options.defaultTrackOptions.trackSpecific?.[track.type]) {
|
|
811
805
|
// track specific options take precedence over all options
|
|
812
806
|
|
|
813
807
|
const options =
|
|
@@ -834,11 +828,9 @@ class HiGlassComponent extends React.Component {
|
|
|
834
828
|
}
|
|
835
829
|
|
|
836
830
|
if (trackInfo.defaultOptions) {
|
|
837
|
-
const defaultThemeOptions =
|
|
838
|
-
trackInfo.defaultOptionsByTheme
|
|
839
|
-
|
|
840
|
-
? trackInfo.defaultOptionsByTheme[this.theme]
|
|
841
|
-
: {};
|
|
831
|
+
const defaultThemeOptions = trackInfo.defaultOptionsByTheme?.[this.theme]
|
|
832
|
+
? trackInfo.defaultOptionsByTheme[this.theme]
|
|
833
|
+
: {};
|
|
842
834
|
|
|
843
835
|
const defaultOptions = {
|
|
844
836
|
...trackInfo.defaultOptions,
|
|
@@ -1209,6 +1201,9 @@ class HiGlassComponent extends React.Component {
|
|
|
1209
1201
|
)
|
|
1210
1202
|
// filter out stale locks with non-existant tracks
|
|
1211
1203
|
.filter((track) => track)
|
|
1204
|
+
// Filter out tracks that don't have values scales (e.g. chromosome tracks).
|
|
1205
|
+
// The .originalTrack check covers LeftTrackModifier style tracks.
|
|
1206
|
+
.filter((track) => track.valueScale || track.originalTrack?.valueScale)
|
|
1212
1207
|
// if the track is a LeftTrackModifier we want the originalTrack
|
|
1213
1208
|
.map((track) =>
|
|
1214
1209
|
track.originalTrack === undefined ? track : track.originalTrack,
|
|
@@ -1234,14 +1229,16 @@ class HiGlassComponent extends React.Component {
|
|
|
1234
1229
|
|
|
1235
1230
|
if (
|
|
1236
1231
|
minValues.length === 0 ||
|
|
1237
|
-
minValues.filter((x) => x === null || x ===
|
|
1232
|
+
minValues.filter((x) => x === null || x === Number.POSITIVE_INFINITY)
|
|
1233
|
+
.length > 0
|
|
1238
1234
|
) {
|
|
1239
1235
|
return null; // Data hasn't loaded completely
|
|
1240
1236
|
}
|
|
1241
1237
|
|
|
1242
1238
|
if (
|
|
1243
1239
|
maxValues.length === 0 ||
|
|
1244
|
-
maxValues.filter((x) => x === null || x ===
|
|
1240
|
+
maxValues.filter((x) => x === null || x === Number.NEGATIVE_INFINITY)
|
|
1241
|
+
.length > 0
|
|
1245
1242
|
) {
|
|
1246
1243
|
return null; // Data hasn't loaded completely
|
|
1247
1244
|
}
|
|
@@ -1395,7 +1392,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1395
1392
|
* Event handler is called with parameters (xScale, yScale)
|
|
1396
1393
|
*/
|
|
1397
1394
|
addDraggingChangedListener(viewUid, listenerUid, eventHandler) {
|
|
1398
|
-
if (!this.draggingChangedListeners
|
|
1395
|
+
if (!(viewUid in this.draggingChangedListeners)) {
|
|
1399
1396
|
this.draggingChangedListeners[viewUid] = {};
|
|
1400
1397
|
}
|
|
1401
1398
|
|
|
@@ -1412,10 +1409,10 @@ class HiGlassComponent extends React.Component {
|
|
|
1412
1409
|
* @param listenerUid: The uid of the listener itself.
|
|
1413
1410
|
*/
|
|
1414
1411
|
removeDraggingChangedListener(viewUid, listenerUid) {
|
|
1415
|
-
if (this.draggingChangedListeners
|
|
1412
|
+
if (viewUid in this.draggingChangedListeners) {
|
|
1416
1413
|
const listeners = this.draggingChangedListeners[viewUid];
|
|
1417
1414
|
|
|
1418
|
-
if (listeners
|
|
1415
|
+
if (listenerUid in listeners) {
|
|
1419
1416
|
// make sure the listener doesn't think we're still
|
|
1420
1417
|
// dragging
|
|
1421
1418
|
listeners[listenerUid](false);
|
|
@@ -1605,7 +1602,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1605
1602
|
const lockGroup = this.zoomLocks[uid];
|
|
1606
1603
|
const lockGroupItems = dictItems(lockGroup);
|
|
1607
1604
|
|
|
1608
|
-
// eslint-disable-next-line no-unused-vars
|
|
1609
1605
|
const [centerX, centerY, k] = scalesCenterAndK(
|
|
1610
1606
|
this.xScales[uid],
|
|
1611
1607
|
this.yScales[uid],
|
|
@@ -1624,7 +1620,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1624
1620
|
continue;
|
|
1625
1621
|
}
|
|
1626
1622
|
|
|
1627
|
-
// eslint-disable-next-line no-unused-vars
|
|
1628
1623
|
const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
|
|
1629
1624
|
this.xScales[key],
|
|
1630
1625
|
this.yScales[key],
|
|
@@ -1656,7 +1651,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1656
1651
|
|
|
1657
1652
|
// notify the listeners of all locked views that the scales of
|
|
1658
1653
|
// this view have changed
|
|
1659
|
-
if (this.scalesChangedListeners
|
|
1654
|
+
if (key in this.scalesChangedListeners) {
|
|
1660
1655
|
dictValues(this.scalesChangedListeners[key]).forEach((x) => {
|
|
1661
1656
|
x(newXScale, newYScale);
|
|
1662
1657
|
});
|
|
@@ -1669,7 +1664,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1669
1664
|
const lockGroup = this.locationLocks[uid];
|
|
1670
1665
|
const lockGroupItems = dictItems(lockGroup);
|
|
1671
1666
|
|
|
1672
|
-
// eslint-disable-next-line no-unused-vars
|
|
1673
1667
|
const [centerX, centerY, k] = scalesCenterAndK(
|
|
1674
1668
|
this.xScales[uid],
|
|
1675
1669
|
this.yScales[uid],
|
|
@@ -1683,7 +1677,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1683
1677
|
continue;
|
|
1684
1678
|
}
|
|
1685
1679
|
|
|
1686
|
-
// eslint-disable-next-line no-unused-vars
|
|
1687
1680
|
const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
|
|
1688
1681
|
this.xScales[key],
|
|
1689
1682
|
this.yScales[key],
|
|
@@ -1718,7 +1711,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1718
1711
|
|
|
1719
1712
|
// notify the listeners of all locked views that the scales of
|
|
1720
1713
|
// this view have changed
|
|
1721
|
-
if (this.scalesChangedListeners
|
|
1714
|
+
if (key in this.scalesChangedListeners) {
|
|
1722
1715
|
dictValues(this.scalesChangedListeners[key]).forEach((x) => {
|
|
1723
1716
|
x(newXScale, newYScale);
|
|
1724
1717
|
});
|
|
@@ -1734,7 +1727,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1734
1727
|
// this means the x axis of this view (uid) is locked to the y axis of another view
|
|
1735
1728
|
const lockCrossAxis = this.locationLocksAxisWise.x[uid].axis !== 'x';
|
|
1736
1729
|
|
|
1737
|
-
// eslint-disable-next-line no-unused-vars
|
|
1738
1730
|
const [centerX, centerY, k] = scalesCenterAndK(
|
|
1739
1731
|
this.xScales[uid],
|
|
1740
1732
|
this.yScales[uid],
|
|
@@ -1748,7 +1740,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1748
1740
|
continue;
|
|
1749
1741
|
}
|
|
1750
1742
|
|
|
1751
|
-
// eslint-disable-next-line no-unused-vars
|
|
1752
1743
|
const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
|
|
1753
1744
|
this.xScales[key],
|
|
1754
1745
|
this.yScales[key],
|
|
@@ -1781,7 +1772,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1781
1772
|
|
|
1782
1773
|
// notify the listeners of all locked views that the scales of
|
|
1783
1774
|
// this view have changed
|
|
1784
|
-
if (this.scalesChangedListeners
|
|
1775
|
+
if (key in this.scalesChangedListeners) {
|
|
1785
1776
|
dictValues(this.scalesChangedListeners[key]).forEach((x) => {
|
|
1786
1777
|
x(newXScale, newYScale);
|
|
1787
1778
|
});
|
|
@@ -1797,7 +1788,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1797
1788
|
// this means the y axis of this view (uid) is locked to the x axis of another view
|
|
1798
1789
|
const lockCrossAxis = this.locationLocksAxisWise.y[uid].axis !== 'y';
|
|
1799
1790
|
|
|
1800
|
-
// eslint-disable-next-line no-unused-vars
|
|
1801
1791
|
const [centerX, centerY, k] = scalesCenterAndK(
|
|
1802
1792
|
this.xScales[uid],
|
|
1803
1793
|
this.yScales[uid],
|
|
@@ -1811,7 +1801,6 @@ class HiGlassComponent extends React.Component {
|
|
|
1811
1801
|
continue;
|
|
1812
1802
|
}
|
|
1813
1803
|
|
|
1814
|
-
// eslint-disable-next-line no-unused-vars
|
|
1815
1804
|
const [keyCenterX, keyCenterY, keyK] = scalesCenterAndK(
|
|
1816
1805
|
this.xScales[key],
|
|
1817
1806
|
this.yScales[key],
|
|
@@ -1844,7 +1833,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1844
1833
|
|
|
1845
1834
|
// notify the listeners of all locked views that the scales of
|
|
1846
1835
|
// this view have changed
|
|
1847
|
-
if (this.scalesChangedListeners
|
|
1836
|
+
if (key in this.scalesChangedListeners) {
|
|
1848
1837
|
dictValues(this.scalesChangedListeners[key]).forEach((x) => {
|
|
1849
1838
|
x(newXScale, newYScale);
|
|
1850
1839
|
});
|
|
@@ -2125,12 +2114,11 @@ class HiGlassComponent extends React.Component {
|
|
|
2125
2114
|
const targetXScale = this.xScales[uid1];
|
|
2126
2115
|
const targetYScale = this.yScales[uid1];
|
|
2127
2116
|
|
|
2128
|
-
// eslint-disable-next-line no-unused-vars
|
|
2129
2117
|
const [targetCenterX, targetCenterY, targetK] = scalesCenterAndK(
|
|
2130
2118
|
targetXScale,
|
|
2131
2119
|
targetYScale,
|
|
2132
2120
|
);
|
|
2133
|
-
|
|
2121
|
+
|
|
2134
2122
|
const [sourceCenterX, sourceCenterY, sourceK] = scalesCenterAndK(
|
|
2135
2123
|
sourceXScale,
|
|
2136
2124
|
sourceYScale,
|
|
@@ -2155,12 +2143,11 @@ class HiGlassComponent extends React.Component {
|
|
|
2155
2143
|
const targetXScale = this.xScales[uid1];
|
|
2156
2144
|
const targetYScale = this.yScales[uid1];
|
|
2157
2145
|
|
|
2158
|
-
// eslint-disable-next-line no-unused-vars
|
|
2159
2146
|
const [targetCenterX, targetCenterY, targetK] = scalesCenterAndK(
|
|
2160
2147
|
targetXScale,
|
|
2161
2148
|
targetYScale,
|
|
2162
2149
|
);
|
|
2163
|
-
|
|
2150
|
+
|
|
2164
2151
|
const [sourceCenterX, sourceCenterY, sourceK] = scalesCenterAndK(
|
|
2165
2152
|
sourceXScale,
|
|
2166
2153
|
sourceYScale,
|
|
@@ -2299,11 +2286,11 @@ class HiGlassComponent extends React.Component {
|
|
|
2299
2286
|
return TRACKS_INFO_BY_TYPE[trackType];
|
|
2300
2287
|
}
|
|
2301
2288
|
|
|
2302
|
-
if (this.pluginTracks
|
|
2289
|
+
if (this.pluginTracks?.[trackType]) {
|
|
2303
2290
|
return this.pluginTracks[trackType].config;
|
|
2304
2291
|
}
|
|
2305
2292
|
|
|
2306
|
-
if (window.higlassTracksByType
|
|
2293
|
+
if (window.higlassTracksByType?.[trackType]) {
|
|
2307
2294
|
return window.higlassTracksByType[trackType].config;
|
|
2308
2295
|
}
|
|
2309
2296
|
|
|
@@ -2317,7 +2304,7 @@ class HiGlassComponent extends React.Component {
|
|
|
2317
2304
|
|
|
2318
2305
|
forceRefreshView() {
|
|
2319
2306
|
// force everything to rerender
|
|
2320
|
-
this.setState(this.state);
|
|
2307
|
+
this.setState(this.state);
|
|
2321
2308
|
}
|
|
2322
2309
|
|
|
2323
2310
|
refreshView(timeout = SHORT_DRAG_TIMEOUT) {
|
|
@@ -2535,7 +2522,7 @@ class HiGlassComponent extends React.Component {
|
|
|
2535
2522
|
}
|
|
2536
2523
|
|
|
2537
2524
|
calculateZoomLimits(view, initialXDomain) {
|
|
2538
|
-
const limits = [0,
|
|
2525
|
+
const limits = [0, Number.POSITIVE_INFINITY];
|
|
2539
2526
|
|
|
2540
2527
|
// By default, highest zoom resolution is 1bp
|
|
2541
2528
|
const viewConfLimit = view.zoomLimits || [1, null];
|
|
@@ -2840,11 +2827,11 @@ class HiGlassComponent extends React.Component {
|
|
|
2840
2827
|
|
|
2841
2828
|
newTrack.width =
|
|
2842
2829
|
trackInfo.defaultWidth ||
|
|
2843
|
-
|
|
2830
|
+
trackInfo.defaultOptions?.minWidth ||
|
|
2844
2831
|
this.minVerticalWidth;
|
|
2845
2832
|
newTrack.height =
|
|
2846
2833
|
trackInfo.defaultHeight ||
|
|
2847
|
-
|
|
2834
|
+
trackInfo.defaultOptions?.minHeight ||
|
|
2848
2835
|
this.minHorizontalHeight;
|
|
2849
2836
|
|
|
2850
2837
|
const { tracks } = this.state.views[viewId];
|
|
@@ -3203,7 +3190,7 @@ class HiGlassComponent extends React.Component {
|
|
|
3203
3190
|
track.type === 'viewport-projection-center' ||
|
|
3204
3191
|
track.type === 'viewport-projection-horizontal' ||
|
|
3205
3192
|
track.type === 'viewport-projection-vertical' ||
|
|
3206
|
-
|
|
3193
|
+
trackInfo?.projection
|
|
3207
3194
|
) {
|
|
3208
3195
|
const fromView = track.fromViewUid;
|
|
3209
3196
|
|
|
@@ -3399,7 +3386,7 @@ class HiGlassComponent extends React.Component {
|
|
|
3399
3386
|
const locksByViewUid = {};
|
|
3400
3387
|
|
|
3401
3388
|
for (const viewUid of dictKeys(locks)) {
|
|
3402
|
-
let lockUid = locks[viewUid]
|
|
3389
|
+
let lockUid = locks[viewUid]?.uid;
|
|
3403
3390
|
|
|
3404
3391
|
if (!lockUid) {
|
|
3405
3392
|
// otherwise, assign this locationLock its own uid
|
|
@@ -3697,7 +3684,6 @@ class HiGlassComponent extends React.Component {
|
|
|
3697
3684
|
});
|
|
3698
3685
|
|
|
3699
3686
|
this.setState((prevState) => {
|
|
3700
|
-
// eslint-disable-next-line no-shadow
|
|
3701
3687
|
const views = JSON.parse(JSON.stringify(prevState.views));
|
|
3702
3688
|
views[newView.uid] = newView;
|
|
3703
3689
|
return { views };
|
|
@@ -4025,7 +4011,7 @@ class HiGlassComponent extends React.Component {
|
|
|
4025
4011
|
'right',
|
|
4026
4012
|
'bottom',
|
|
4027
4013
|
]) {
|
|
4028
|
-
if (v.tracks
|
|
4014
|
+
if (trackOrientation in (v.tracks ?? {})) {
|
|
4029
4015
|
// filter out invalid tracks
|
|
4030
4016
|
v.tracks[trackOrientation] = v.tracks[trackOrientation].filter((t) =>
|
|
4031
4017
|
this.isTrackValid(t, viewUidsSet),
|
|
@@ -4355,7 +4341,10 @@ class HiGlassComponent extends React.Component {
|
|
|
4355
4341
|
(listenerId) => listenerId.indexOf(LOCATION_LISTENER_PREFIX) === 0,
|
|
4356
4342
|
)
|
|
4357
4343
|
.map((listenerId) =>
|
|
4358
|
-
parseInt(
|
|
4344
|
+
Number.parseInt(
|
|
4345
|
+
listenerId.slice(LOCATION_LISTENER_PREFIX.length + 1),
|
|
4346
|
+
10,
|
|
4347
|
+
),
|
|
4359
4348
|
)
|
|
4360
4349
|
.reduce((max, value) => Math.max(max, value), 0) + 1;
|
|
4361
4350
|
}
|
|
@@ -4450,15 +4439,13 @@ class HiGlassComponent extends React.Component {
|
|
|
4450
4439
|
const evt = {
|
|
4451
4440
|
x: relPos[0],
|
|
4452
4441
|
y: relPos[1],
|
|
4453
|
-
relTrackX:
|
|
4454
|
-
|
|
4455
|
-
relTrackY:
|
|
4456
|
-
hoveredTrack && hoveredTrack.flipText ? relTrackPos[0] : relTrackPos[1],
|
|
4442
|
+
relTrackX: hoveredTrack?.flipText ? relTrackPos[1] : relTrackPos[0],
|
|
4443
|
+
relTrackY: hoveredTrack?.flipText ? relTrackPos[0] : relTrackPos[1],
|
|
4457
4444
|
dataX,
|
|
4458
4445
|
dataY,
|
|
4459
4446
|
// See below why we need these derived boolean values
|
|
4460
|
-
isFrom2dTrack: !!
|
|
4461
|
-
isFromVerticalTrack: !!
|
|
4447
|
+
isFrom2dTrack: !!hoveredTrack?.is2d,
|
|
4448
|
+
isFromVerticalTrack: !!hoveredTrack?.flipText,
|
|
4462
4449
|
track: hoveredTrack,
|
|
4463
4450
|
origEvt: e,
|
|
4464
4451
|
sourceUid: this.uid,
|
|
@@ -4536,13 +4523,12 @@ class HiGlassComponent extends React.Component {
|
|
|
4536
4523
|
showHoverMenu(evt) {
|
|
4537
4524
|
// each track should have a function that returns an HTML representation
|
|
4538
4525
|
// of the data at a give position
|
|
4539
|
-
const mouseOverHtml =
|
|
4540
|
-
evt.track
|
|
4541
|
-
|
|
4542
|
-
: '';
|
|
4526
|
+
const mouseOverHtml = evt.track?.getMouseOverHtml
|
|
4527
|
+
? evt.track.getMouseOverHtml(evt.relTrackX, evt.relTrackY)
|
|
4528
|
+
: '';
|
|
4543
4529
|
|
|
4544
4530
|
if (evt.track !== this.prevMouseHoverTrack) {
|
|
4545
|
-
if (this.prevMouseHoverTrack
|
|
4531
|
+
if (this.prevMouseHoverTrack?.stopHover) {
|
|
4546
4532
|
this.prevMouseHoverTrack.stopHover();
|
|
4547
4533
|
}
|
|
4548
4534
|
}
|
|
@@ -4551,7 +4537,7 @@ class HiGlassComponent extends React.Component {
|
|
|
4551
4537
|
|
|
4552
4538
|
if (this.zooming) return;
|
|
4553
4539
|
|
|
4554
|
-
const data = mouseOverHtml
|
|
4540
|
+
const data = mouseOverHtml?.length ? [1] : [];
|
|
4555
4541
|
|
|
4556
4542
|
// try to select the mouseover div
|
|
4557
4543
|
let mouseOverDiv = select('body')
|
|
@@ -4663,10 +4649,8 @@ class HiGlassComponent extends React.Component {
|
|
|
4663
4649
|
]
|
|
4664
4650
|
: relPos;
|
|
4665
4651
|
|
|
4666
|
-
const relTrackX =
|
|
4667
|
-
|
|
4668
|
-
const relTrackY =
|
|
4669
|
-
hoveredTrack && hoveredTrack.flipText ? relTrackPos[0] : relTrackPos[1];
|
|
4652
|
+
const relTrackX = hoveredTrack?.flipText ? relTrackPos[1] : relTrackPos[0];
|
|
4653
|
+
const relTrackY = hoveredTrack?.flipText ? relTrackPos[0] : relTrackPos[1];
|
|
4670
4654
|
|
|
4671
4655
|
for (const track of this.iterateOverTracks()) {
|
|
4672
4656
|
const trackObj = getTrackObjById(
|
|
@@ -4818,7 +4802,7 @@ class HiGlassComponent extends React.Component {
|
|
|
4818
4802
|
this.props.options.zoomFixed ||
|
|
4819
4803
|
this.state.viewConfig.zoomFixed ||
|
|
4820
4804
|
this.props.options.sizeMode === SIZE_MODE_SCROLL ||
|
|
4821
|
-
|
|
4805
|
+
view?.zoomFixed
|
|
4822
4806
|
);
|
|
4823
4807
|
}
|
|
4824
4808
|
|
|
@@ -4900,14 +4884,8 @@ class HiGlassComponent extends React.Component {
|
|
|
4900
4884
|
const evtToPublish = {
|
|
4901
4885
|
x: relPos[0],
|
|
4902
4886
|
y: relPos[1],
|
|
4903
|
-
relTrackX:
|
|
4904
|
-
|
|
4905
|
-
? relTrackPos[1]
|
|
4906
|
-
: relTrackPos[0],
|
|
4907
|
-
relTrackY:
|
|
4908
|
-
hoveredTrack && hoveredTrack.flipText
|
|
4909
|
-
? relTrackPos[0]
|
|
4910
|
-
: relTrackPos[1],
|
|
4887
|
+
relTrackX: hoveredTrack?.flipText ? relTrackPos[1] : relTrackPos[0],
|
|
4888
|
+
relTrackY: hoveredTrack?.flipText ? relTrackPos[0] : relTrackPos[1],
|
|
4911
4889
|
track: hoveredTrack,
|
|
4912
4890
|
origEvt: nativeEvent,
|
|
4913
4891
|
sourceUid: this.uid,
|
|
@@ -5152,8 +5130,7 @@ class HiGlassComponent extends React.Component {
|
|
|
5152
5130
|
}}
|
|
5153
5131
|
getGenomePositionSearchBox={getGenomePositionSearchBox}
|
|
5154
5132
|
isGenomePositionSearchBoxVisible={
|
|
5155
|
-
view.genomePositionSearchBox
|
|
5156
|
-
view.genomePositionSearchBox.visible
|
|
5133
|
+
view.genomePositionSearchBox?.visible
|
|
5157
5134
|
}
|
|
5158
5135
|
mouseTool={this.state.mouseTool}
|
|
5159
5136
|
onAddView={() => this.handleAddView(view)}
|
|
@@ -50,7 +50,7 @@ class Horizontal2DDomainsTrack extends TiledPixiTrack {
|
|
|
50
50
|
let zoomLevel = Math.max(xZoomLevel, yZoomLevel);
|
|
51
51
|
zoomLevel = Math.min(zoomLevel, this.maxZoom);
|
|
52
52
|
|
|
53
|
-
if (this.options
|
|
53
|
+
if (this.options?.maxZoom) {
|
|
54
54
|
if (this.options.maxZoom >= 0) {
|
|
55
55
|
zoomLevel = Math.min(this.options.maxZoom, zoomLevel);
|
|
56
56
|
} else {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
import boxIntersect from 'box-intersect';
|
|
3
|
+
import { format, formatPrefix, precisionPrefix } from 'd3-format';
|
|
3
4
|
import { scaleLinear } from 'd3-scale';
|
|
4
|
-
import { format, precisionPrefix, formatPrefix } from 'd3-format';
|
|
5
5
|
|
|
6
|
-
import PixiTrack from './PixiTrack';
|
|
7
6
|
import ChromosomeInfo from './ChromosomeInfo';
|
|
8
|
-
import
|
|
7
|
+
import TiledPixiTrack from './TiledPixiTrack';
|
|
9
8
|
|
|
10
9
|
import {
|
|
11
10
|
absToChr,
|
|
@@ -22,13 +21,12 @@ const TICK_HEIGHT = 6;
|
|
|
22
21
|
const TICK_TEXT_SEPARATION = 2;
|
|
23
22
|
const TICK_COLOR = 0x777777;
|
|
24
23
|
|
|
25
|
-
class HorizontalChromosomeLabels extends
|
|
24
|
+
class HorizontalChromosomeLabels extends TiledPixiTrack {
|
|
26
25
|
constructor(context, options) {
|
|
27
26
|
super(context, options);
|
|
28
27
|
const { dataConfig, animate, chromInfoPath, isShowGlobalMousePosition } =
|
|
29
28
|
context;
|
|
30
29
|
|
|
31
|
-
this.searchField = null;
|
|
32
30
|
this.chromInfo = null;
|
|
33
31
|
this.dataConfig = dataConfig;
|
|
34
32
|
|
|
@@ -80,25 +78,33 @@ class HorizontalChromosomeLabels extends PixiTrack {
|
|
|
80
78
|
);
|
|
81
79
|
}
|
|
82
80
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
/** The previous chromInfoPath approach to loading chromosome size.
|
|
82
|
+
*
|
|
83
|
+
* This is superseded by loading chromosome sizes directly from the
|
|
84
|
+
* tileset info object
|
|
85
|
+
*/
|
|
86
|
+
if (chromInfoPath) {
|
|
87
|
+
ChromosomeInfo(
|
|
88
|
+
chromInfoPath,
|
|
89
|
+
(newChromInfo) => {
|
|
90
|
+
this.chromInfo = newChromInfo;
|
|
91
|
+
|
|
92
|
+
this.tilesetInfoReceived();
|
|
93
|
+
},
|
|
94
|
+
this.pubSub,
|
|
95
|
+
);
|
|
87
96
|
}
|
|
97
|
+
}
|
|
88
98
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
this.searchField = new SearchField(this.chromInfo);
|
|
99
|
+
tilesetInfoReceived() {
|
|
100
|
+
this.rerender(this.options, true);
|
|
101
|
+
this.draw();
|
|
102
|
+
this.animate();
|
|
103
|
+
}
|
|
95
104
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
},
|
|
100
|
-
this.pubSub,
|
|
101
|
-
);
|
|
105
|
+
calculateVisibleTiles() {
|
|
106
|
+
/** This track does not use tiles so return an empty set */
|
|
107
|
+
return [];
|
|
102
108
|
}
|
|
103
109
|
|
|
104
110
|
initBoundsTicks() {
|
|
@@ -432,7 +438,7 @@ class HorizontalChromosomeLabels extends PixiTrack {
|
|
|
432
438
|
draw() {
|
|
433
439
|
this.allTexts = [];
|
|
434
440
|
|
|
435
|
-
if (!this.texts
|
|
441
|
+
if (!this.texts) return;
|
|
436
442
|
|
|
437
443
|
const x1 = absToChr(this._xScale.domain()[0], this.chromInfo);
|
|
438
444
|
const x2 = absToChr(this._xScale.domain()[1], this.chromInfo);
|
|
@@ -11,9 +11,9 @@ import HorizontalTiled1DPixiTrack from './HorizontalTiled1DPixiTrack';
|
|
|
11
11
|
// Services
|
|
12
12
|
import { tileProxy } from './services';
|
|
13
13
|
|
|
14
|
+
import trackUtils from './track-utils';
|
|
14
15
|
// Utils
|
|
15
16
|
import { colorToHex } from './utils';
|
|
16
|
-
import trackUtils from './track-utils';
|
|
17
17
|
|
|
18
18
|
// these are default values that are overwritten by the track's options
|
|
19
19
|
const FONT_SIZE = 11;
|
|
@@ -30,7 +30,7 @@ class HorizontalHeatmapTrack extends HeatmapTiledPixiTrack {
|
|
|
30
30
|
// Continuous scaling is currently not supported
|
|
31
31
|
this.continuousScaling = false;
|
|
32
32
|
|
|
33
|
-
if (options
|
|
33
|
+
if (options?.colorRange) {
|
|
34
34
|
this.colorScale = colorDomainToRgbaArray(options.colorRange);
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -89,7 +89,7 @@ class HorizontalHeatmapTrack extends HeatmapTiledPixiTrack {
|
|
|
89
89
|
zoomLevel = Math.min(zoomLevel, this.maxZoom);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
if (this.options
|
|
92
|
+
if (this.options?.maxZoom) {
|
|
93
93
|
if (this.options.maxZoom >= 0) {
|
|
94
94
|
zoomLevel = Math.min(this.options.maxZoom, zoomLevel);
|
|
95
95
|
} else {
|