higlass 1.13.4 → 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 +10 -12
- 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 +4 -2
- 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 +8 -3
- package/app/scripts/HeatmapTiledPixiTrack.js +72 -53
- 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 +4 -4
- 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 +58 -17
- package/app/scripts/PlotTypeChooser.jsx +3 -4
- package/app/scripts/RasterTilesTrack.js +3 -2
- package/app/scripts/SearchField.js +5 -5
- package/app/scripts/SeriesListItems.jsx +3 -4
- package/app/scripts/SeriesListMenu.jsx +81 -11
- package/app/scripts/SeriesListSubmenuMixin.jsx +5 -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 +221 -76
- package/app/scripts/TiledPlot.jsx +35 -43
- package/app/scripts/TilesetFinder.jsx +12 -4
- package/app/scripts/Track.js +2 -2
- package/app/scripts/TrackArea.jsx +4 -0
- package/app/scripts/TrackControl.jsx +2 -2
- package/app/scripts/TrackRenderer.jsx +30 -31
- package/app/scripts/UnknownPixiTrack.js +1 -1
- 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 +107 -91
- package/app/scripts/data-fetchers/genbank-fetcher.js +6 -10
- package/app/scripts/data-fetchers/local-tile-fetcher.js +2 -6
- package/app/scripts/gosling-exports.js +29 -0
- package/app/scripts/hglib.jsx +3 -1
- package/app/scripts/hocs/with-modal.jsx +32 -10
- package/app/scripts/hocs/with-pub-sub.js +28 -0
- 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 +370 -282
- package/app/scripts/services/worker.js +36 -34
- package/app/scripts/test-helpers/test-helpers.jsx +3 -3
- package/app/scripts/types.ts +73 -38
- package/app/scripts/utils/DenseDataExtrema1D.js +1 -1
- package/app/scripts/utils/DenseDataExtrema2D.js +2 -1
- 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/color-to-hex.js +1 -1
- 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/fake-pub-sub.js +12 -0
- 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 +17 -1
- 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 +85885 -85618
- package/dist/hglib.min.js +110 -109
- package/dist/higlass.mjs +86301 -86034
- package/package.json +13 -17
- package/app/scripts/hocs/with-pub-sub.jsx +0 -28
package/README.md
CHANGED
|
@@ -7,20 +7,31 @@
|
|
|
7
7
|
|
|
8
8
|
### Introduction
|
|
9
9
|
|
|
10
|
-
HiGlass is a web-based viewer for datasets too large to view at once.
|
|
11
|
-
|
|
12
|
-
for navigation across genomic loci and resolutions. It
|
|
13
|
-
genomic (e.g., Hi-C, ChIP-seq, or bed
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
HiGlass is a web-based viewer for datasets too large to view at once. It
|
|
11
|
+
features synchronized navigation of multiple views as well as continuous
|
|
12
|
+
zooming and panning for navigation across genomic loci and resolutions. It
|
|
13
|
+
supports visual comparison of genomic (e.g., Hi-C, ChIP-seq, or bed
|
|
14
|
+
annotations) and other data (e.g., geographic maps, gigapixel images, or
|
|
15
|
+
abstract 1D and 2D sequential data) from different experimental conditions and
|
|
16
|
+
can be used to efficiently identify salient outcomes of experimental
|
|
17
|
+
perturbations, generate new hypotheses, and share the results with the
|
|
18
|
+
community.
|
|
19
|
+
|
|
20
|
+
A live instance can be found at [https://higlass.io](https://higlass.io). A
|
|
21
|
+
[Docker container](https://github.com/higlass/higlass-docker) is available for
|
|
22
|
+
running an instance locally, although we recommend using the
|
|
23
|
+
[higlass-manage](https://github.com/pkerpedjiev/higlass-manage) package to
|
|
24
|
+
start, stop and configure local instances.
|
|
25
|
+
|
|
26
|
+
For documentation about how to use and install HiGlass, please visit
|
|
27
|
+
[https://docs.higlass.io](https://docs.higlass.io).
|
|
20
28
|
|
|
21
29
|
### Citation
|
|
22
30
|
|
|
23
|
-
Kerpedjiev, P., Abdennur, N., Lekschas, F., McCallum, C., Dinkla, K., Strobelt,
|
|
31
|
+
Kerpedjiev, P., Abdennur, N., Lekschas, F., McCallum, C., Dinkla, K., Strobelt,
|
|
32
|
+
H., ... & Gehlenborg, N. *HiGlass: Web-based Visual Exploration and Analysis of
|
|
33
|
+
Genome Interaction Maps.* Genome Biology (2018): 19:125.
|
|
34
|
+
https://doi.org/10.1186/s13059-018-1486-1
|
|
24
35
|
|
|
25
36
|
### Example
|
|
26
37
|
|
|
@@ -34,7 +45,7 @@ To run higlass from its source code simply run the following:
|
|
|
34
45
|
|
|
35
46
|
```
|
|
36
47
|
npm clean-install // use --legacy-peer-deps if you get peer dependency errors
|
|
37
|
-
npm
|
|
48
|
+
npm start
|
|
38
49
|
```
|
|
39
50
|
|
|
40
51
|
This starts a server in development mode at http://localhost:5173/.
|
|
@@ -44,26 +55,16 @@ This starts a server in development mode at http://localhost:5173/.
|
|
|
44
55
|
> Once started, a list of the examples can be found at [http://localhost:8080/examples.html](http://localhost:8080/examples.html).
|
|
45
56
|
> Template viewconfs located at `/docs/examples/viewconfs` can viewed directly at urls such as [http://localhost:8080/apis/svg.html?/viewconfs/overlay-tracks.json](http://localhost:8080/apis/svg.html?/viewconfs/overlay-tracks.json).
|
|
46
57
|
|
|
47
|
-
|
|
48
58
|
### Tests
|
|
49
59
|
|
|
50
|
-
The tests for the React components and API functions are located in the `test`
|
|
51
|
-
Tests are run with [`
|
|
60
|
+
The tests for the React components and API functions are located in the `test`
|
|
61
|
+
directory. Tests are run with [`vitest`](https://vitest.dev/).
|
|
52
62
|
|
|
53
63
|
Useful commands:
|
|
54
64
|
|
|
55
|
-
- Run all tests: `npm test`
|
|
56
|
-
- Run all tests in interactive "watch" mode: `npm test -- --watch`
|
|
57
|
-
- Run a specific test or "glob" of tests: `npm test -- test/APITests.js [--watch]`
|
|
58
|
-
- Manually run individual tests in an open browser window: `npm test -- --manual`
|
|
59
|
-
|
|
60
|
-
**Troubleshooting:**
|
|
61
|
-
|
|
62
|
-
- If the installation fails due to `sharp` > `node-gyp` try installing the node packages using `python2`:
|
|
65
|
+
- Run all tests in the browser: `npm test -- --browser.headless=false`
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
npm ci --python=/usr/bin/python2 && rm -rf node_modules/node-sass && npm ci
|
|
66
|
-
```
|
|
67
|
+
See the [contributing guide](./CONTRIBUTING.md) to learn more.
|
|
67
68
|
|
|
68
69
|
### API
|
|
69
70
|
|
|
@@ -71,34 +72,27 @@ HiGlass provides an API for controlling the component from with JavaScript. Belo
|
|
|
71
72
|
|
|
72
73
|
```html
|
|
73
74
|
<!DOCTYPE html>
|
|
74
|
-
<head>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<script>
|
|
96
|
-
const hgApi = window.hglib.viewer(
|
|
97
|
-
document.body,
|
|
98
|
-
'https://higlass.io/api/v1/viewconfs/?d=default',
|
|
99
|
-
{ bounded: true },
|
|
100
|
-
);
|
|
101
|
-
</script>
|
|
75
|
+
<head>
|
|
76
|
+
<meta charset="utf-8">
|
|
77
|
+
<title>Minimal Working Example · HiGlass</title>
|
|
78
|
+
<style type="text/css">
|
|
79
|
+
html, body {
|
|
80
|
+
width: 100vw;
|
|
81
|
+
height: 100vh;
|
|
82
|
+
overflow: hidden;
|
|
83
|
+
}
|
|
84
|
+
</style>
|
|
85
|
+
</head>
|
|
86
|
+
<body></body>
|
|
87
|
+
<script type="module">
|
|
88
|
+
import * as hglib from "https://esm.sh/higlass@1.13";
|
|
89
|
+
|
|
90
|
+
const api = hglib.viewer(
|
|
91
|
+
document.body,
|
|
92
|
+
'https://higlass.io/api/v1/viewconfs/?d=default',
|
|
93
|
+
{ bounded: true },
|
|
94
|
+
);
|
|
95
|
+
</script>
|
|
102
96
|
</html>
|
|
103
97
|
```
|
|
104
98
|
|
package/app/globals.d.ts
CHANGED
package/app/missing-types.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
1
|
// https://www.npmjs.com/package/pub-sub-es
|
|
3
2
|
declare module 'pub-sub-es' {
|
|
3
|
+
// biome-ignore lint/suspicious/noExplicitAny: Inherited API
|
|
4
4
|
type EventMap = { [name: string]: any };
|
|
5
5
|
export type Subscription = {
|
|
6
6
|
event: string;
|
|
7
|
+
// biome-ignore lint/suspicious/noExplicitAny: Inherited API
|
|
7
8
|
handler: (news: any) => void;
|
|
8
9
|
};
|
|
9
10
|
type PublishOptions = {
|
|
@@ -11,7 +12,9 @@ declare module 'pub-sub-es' {
|
|
|
11
12
|
isNoGlobalBroadCast?: boolean;
|
|
12
13
|
};
|
|
13
14
|
export type PubSub = {
|
|
15
|
+
// biome-ignore lint/suspicious/noExplicitAny: Inherited API
|
|
14
16
|
publish(event: string, news?: any, options?: PublishOptions): void;
|
|
17
|
+
// biome-ignore lint/suspicious/noExplicitAny: Inherited API
|
|
15
18
|
subscribe(event: string, handler: (news: any) => void): Subscription;
|
|
16
19
|
unsubscribe(subscription: Subscription): void;
|
|
17
20
|
clear(): void;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
import React from 'react';
|
|
3
2
|
import PropTypes from 'prop-types';
|
|
3
|
+
import React from 'react';
|
|
4
4
|
|
|
5
5
|
import Dialog from './Dialog';
|
|
6
|
-
import TilesetFinder from './TilesetFinder';
|
|
7
6
|
import PlotTypeChooser from './PlotTypeChooser';
|
|
7
|
+
import TilesetFinder from './TilesetFinder';
|
|
8
8
|
|
|
9
9
|
// Configs
|
|
10
10
|
import { AVAILABLE_TRACK_TYPES } from './configs';
|
|
@@ -15,7 +15,7 @@ import { getDefaultTrackForDatatype } from './utils';
|
|
|
15
15
|
// Styles
|
|
16
16
|
import '../styles/AddTrackDialog.module.scss';
|
|
17
17
|
|
|
18
|
-
class AddTrackDialog extends React.Component {
|
|
18
|
+
export class AddTrackDialog extends React.Component {
|
|
19
19
|
constructor(props) {
|
|
20
20
|
super(props);
|
|
21
21
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
+
import clsx from 'clsx';
|
|
2
3
|
import PropTypes from 'prop-types';
|
|
3
4
|
import React from 'react';
|
|
4
|
-
import clsx from 'clsx';
|
|
5
5
|
|
|
6
|
-
import withTheme from './hocs/with-theme';
|
|
7
6
|
import { THEME_DARK } from './configs';
|
|
7
|
+
import withTheme from './hocs/with-theme';
|
|
8
8
|
|
|
9
9
|
import classes from '../styles/AddTrackPositionMenu.module.scss';
|
|
10
10
|
|
|
@@ -54,7 +54,7 @@ class Annotations1dTrack extends PixiTrack {
|
|
|
54
54
|
: 0;
|
|
55
55
|
|
|
56
56
|
let strokePos;
|
|
57
|
-
if (this.options.strokePos
|
|
57
|
+
if (this.options.strokePos?.length) {
|
|
58
58
|
strokePos = Array.isArray(this.options.strokePos)
|
|
59
59
|
? this.options.strokePos
|
|
60
60
|
: [this.options.strokePos];
|
|
@@ -41,13 +41,11 @@ class Annotations2dTrack extends TiledPixiTrack {
|
|
|
41
41
|
/* --------------------------- Getter / Setter ---------------------------- */
|
|
42
42
|
|
|
43
43
|
get minX() {
|
|
44
|
-
return this.tilesetInfo
|
|
45
|
-
? this.tilesetInfo.min_pos[0]
|
|
46
|
-
: 0;
|
|
44
|
+
return this.tilesetInfo?.min_pos ? this.tilesetInfo.min_pos[0] : 0;
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
get maxX() {
|
|
50
|
-
return this.tilesetInfo
|
|
48
|
+
return this.tilesetInfo?.max_pos
|
|
51
49
|
? this.tilesetInfo.max_pos[0]
|
|
52
50
|
: this.tilesetInfo.max_width || this.tilesetInfo.max_size;
|
|
53
51
|
}
|
|
@@ -468,7 +466,7 @@ class Annotations2dTrack extends TiledPixiTrack {
|
|
|
468
466
|
track.appendChild(output);
|
|
469
467
|
|
|
470
468
|
this.visibleAndFetchedTiles()
|
|
471
|
-
.filter((tile) => tile.tileData
|
|
469
|
+
.filter((tile) => tile.tileData?.length)
|
|
472
470
|
.map((tile) => ({ graphics: tile.graphics, td: tile.tileData }))
|
|
473
471
|
.forEach(({ td, graphics }) => {
|
|
474
472
|
const gTile = document.createElement('g');
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { findDOMNode } from 'react-dom';
|
|
2
|
+
|
|
5
3
|
import scrollIntoView from 'dom-scroll-into-view';
|
|
6
4
|
import PropTypes from 'prop-types';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { findDOMNode } from 'react-dom';
|
|
7
7
|
|
|
8
8
|
const _debugStates = [];
|
|
9
9
|
|
|
@@ -102,14 +102,12 @@ class Autocomplete extends React.Component {
|
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
// eslint-disable-next-line camelcase
|
|
106
105
|
UNSAFE_componentWillMount() {
|
|
107
106
|
this._ignoreBlur = false;
|
|
108
107
|
this._performAutoCompleteOnUpdate = false;
|
|
109
108
|
this._performAutoCompleteOnKeyUp = false;
|
|
110
109
|
}
|
|
111
110
|
|
|
112
|
-
// eslint-disable-next-line camelcase
|
|
113
111
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
114
112
|
this._performAutoCompleteOnUpdate = true;
|
|
115
113
|
// If `items` has changed we want to reset `highlightedIndex`
|
|
@@ -143,9 +141,8 @@ class Autocomplete extends React.Component {
|
|
|
143
141
|
|
|
144
142
|
maybeScrollItemIntoView() {
|
|
145
143
|
if (this.state.isOpen === true && this.state.highlightedIndex !== null) {
|
|
146
|
-
// eslint-disable-next-line react/no-string-refs
|
|
147
144
|
const itemNode = this.refs[`item-${this.state.highlightedIndex}`];
|
|
148
|
-
|
|
145
|
+
|
|
149
146
|
const menuNode = this.refs.menu;
|
|
150
147
|
if (itemNode) {
|
|
151
148
|
scrollIntoView(findDOMNode(itemNode), findDOMNode(menuNode), {
|
|
@@ -217,9 +214,9 @@ class Autocomplete extends React.Component {
|
|
|
217
214
|
const node = this.inputEl;
|
|
218
215
|
const rect = node.getBoundingClientRect();
|
|
219
216
|
const computedStyle = global.window.getComputedStyle(node);
|
|
220
|
-
const marginBottom = parseInt(computedStyle.marginBottom, 10) || 0;
|
|
221
|
-
const marginLeft = parseInt(computedStyle.marginLeft, 10) || 0;
|
|
222
|
-
const marginRight = parseInt(computedStyle.marginRight, 10) || 0;
|
|
217
|
+
const marginBottom = Number.parseInt(computedStyle.marginBottom, 10) || 0;
|
|
218
|
+
const marginLeft = Number.parseInt(computedStyle.marginLeft, 10) || 0;
|
|
219
|
+
const marginRight = Number.parseInt(computedStyle.marginRight, 10) || 0;
|
|
223
220
|
this.setState({
|
|
224
221
|
menuTop: rect.bottom + marginBottom,
|
|
225
222
|
menuLeft: rect.left + marginLeft,
|
|
@@ -354,26 +351,26 @@ class Autocomplete extends React.Component {
|
|
|
354
351
|
autoComplete="off"
|
|
355
352
|
onBlur={this.composeEventHandlers(
|
|
356
353
|
this.handleInputBlur.bind(this),
|
|
357
|
-
inputProps.onBlur
|
|
354
|
+
inputProps.onBlur?.bind(this),
|
|
358
355
|
)}
|
|
359
356
|
onChange={this.handleChange.bind(this)}
|
|
360
357
|
onClick={this.composeEventHandlers(
|
|
361
358
|
this.handleInputClick.bind(this),
|
|
362
|
-
inputProps.onClick
|
|
359
|
+
inputProps.onClick?.bind(this),
|
|
363
360
|
)}
|
|
364
361
|
onFocus={this.composeEventHandlers(
|
|
365
362
|
this.handleInputFocus.bind(this),
|
|
366
|
-
inputProps.onFocus
|
|
363
|
+
inputProps.onFocus?.bind(this),
|
|
367
364
|
)}
|
|
368
365
|
onKeyDown={this.composeEventHandlers(
|
|
369
366
|
this.handleKeyDown.bind(this),
|
|
370
|
-
inputProps.onKeyDown
|
|
367
|
+
inputProps.onKeyDown?.bind(this),
|
|
371
368
|
)}
|
|
372
369
|
onKeyUp={this.composeEventHandlers(
|
|
373
370
|
this.handleKeyUp.bind(this),
|
|
374
|
-
inputProps.onKeyUp
|
|
371
|
+
inputProps.onKeyUp?.bind(this),
|
|
375
372
|
)}
|
|
376
|
-
//
|
|
373
|
+
// biome-ignore lint/a11y/useAriaPropsForRole:
|
|
377
374
|
role="combobox"
|
|
378
375
|
value={this.props.value}
|
|
379
376
|
/>
|
|
@@ -403,11 +400,7 @@ Autocomplete.defaultProps = {
|
|
|
403
400
|
onChange() {},
|
|
404
401
|
onSelect() {},
|
|
405
402
|
renderMenu(items, value, style) {
|
|
406
|
-
return
|
|
407
|
-
/* eslint-disable react/no-this-in-sfc */
|
|
408
|
-
<div style={{ ...style, ...this.menuStyle }}>{items}</div>
|
|
409
|
-
/* eslint-enable react/no-this-in-sfc */
|
|
410
|
-
);
|
|
403
|
+
return <div style={{ ...style, ...this.menuStyle }}>{items}</div>;
|
|
411
404
|
},
|
|
412
405
|
shouldItemRender() {
|
|
413
406
|
return true;
|
package/app/scripts/AxisPixi.js
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
import { format } from 'd3-format';
|
|
3
3
|
|
|
4
4
|
// Configs
|
|
5
|
-
import
|
|
5
|
+
import GLOBALS from './configs/globals';
|
|
6
|
+
import { THEME_DARK } from './configs/themes';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
// Utils
|
|
9
|
+
import colorToHex from './utils/color-to-hex';
|
|
8
10
|
|
|
9
11
|
const TICK_HEIGHT = 40;
|
|
10
12
|
const TICK_MARGIN = 0;
|
|
@@ -136,7 +138,7 @@ class AxisPixi {
|
|
|
136
138
|
graphics.moveTo(-TICK_MARGIN, valueScale(tick));
|
|
137
139
|
graphics.lineTo(-(TICK_MARGIN + TICK_LENGTH), valueScale(tick));
|
|
138
140
|
|
|
139
|
-
if (this.track
|
|
141
|
+
if (this.track?.flipText) {
|
|
140
142
|
this.axisTexts[i].scale.x = -1;
|
|
141
143
|
}
|
|
142
144
|
}
|
|
@@ -178,7 +180,7 @@ class AxisPixi {
|
|
|
178
180
|
graphics.moveTo(TICK_MARGIN, valueScale(tick));
|
|
179
181
|
graphics.lineTo(TICK_MARGIN + TICK_LENGTH, valueScale(tick));
|
|
180
182
|
|
|
181
|
-
if (this.track
|
|
183
|
+
if (this.track?.flipText) {
|
|
182
184
|
this.axisTexts[i].scale.x = -1;
|
|
183
185
|
}
|
|
184
186
|
}
|
|
@@ -226,7 +228,7 @@ class AxisPixi {
|
|
|
226
228
|
|
|
227
229
|
let stroke = 'black';
|
|
228
230
|
|
|
229
|
-
if (this.track
|
|
231
|
+
if (this.track?.options.lineStrokeColor) {
|
|
230
232
|
stroke = this.track.options.lineStrokeColor;
|
|
231
233
|
}
|
|
232
234
|
// TODO: On the canvas, there is no vertical line beside the scale,
|
|
@@ -252,7 +254,7 @@ class AxisPixi {
|
|
|
252
254
|
// factor out the styling for axis lines
|
|
253
255
|
let stroke = 'black';
|
|
254
256
|
|
|
255
|
-
if (this.track
|
|
257
|
+
if (this.track?.options.lineStrokeColor) {
|
|
256
258
|
stroke = this.track.options.lineStrokeColor;
|
|
257
259
|
}
|
|
258
260
|
|
|
@@ -304,9 +306,7 @@ class AxisPixi {
|
|
|
304
306
|
|
|
305
307
|
tickLine.setAttribute(
|
|
306
308
|
'd',
|
|
307
|
-
`M${+TICK_MARGIN},${valueScale(tick)} L${+(
|
|
308
|
-
TICK_MARGIN + TICK_LENGTH
|
|
309
|
-
)},${valueScale(tick)}`,
|
|
309
|
+
`M${+TICK_MARGIN},${valueScale(tick)} L${+(TICK_MARGIN + TICK_LENGTH)},${valueScale(tick)}`,
|
|
310
310
|
);
|
|
311
311
|
|
|
312
312
|
const g = document.createElement('g');
|
|
@@ -350,9 +350,7 @@ class AxisPixi {
|
|
|
350
350
|
|
|
351
351
|
tickLine.setAttribute(
|
|
352
352
|
'd',
|
|
353
|
-
`M${-TICK_MARGIN},${valueScale(tick)} L${-(
|
|
354
|
-
TICK_MARGIN + TICK_LENGTH
|
|
355
|
-
)},${valueScale(tick)}`,
|
|
353
|
+
`M${-TICK_MARGIN},${valueScale(tick)} L${-(TICK_MARGIN + TICK_LENGTH)},${valueScale(tick)}`,
|
|
356
354
|
);
|
|
357
355
|
|
|
358
356
|
const g = document.createElement('g');
|
package/app/scripts/BarTrack.js
CHANGED
|
@@ -20,7 +20,7 @@ class BarTrack extends HorizontalLine1DPixiTrack {
|
|
|
20
20
|
this.pMain.addChild(this.zeroLine);
|
|
21
21
|
this.valueScaleTransform = zoomIdentity;
|
|
22
22
|
|
|
23
|
-
if (this.options
|
|
23
|
+
if (this.options?.colorRange) {
|
|
24
24
|
if (this.options.colorRangeGradient) {
|
|
25
25
|
this.setColorGradient(this.options.colorRange);
|
|
26
26
|
} else {
|
|
@@ -226,7 +226,7 @@ class BarTrack extends HorizontalLine1DPixiTrack {
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
rerender(options, force) {
|
|
229
|
-
if (options
|
|
229
|
+
if (options?.colorRange) {
|
|
230
230
|
if (options.colorRangeGradient) {
|
|
231
231
|
this.setColorGradient(options.colorRange);
|
|
232
232
|
} else {
|
|
@@ -430,7 +430,7 @@ class BarTrack extends HorizontalLine1DPixiTrack {
|
|
|
430
430
|
if (this.options.zeroLine) this.drawZeroLineSvg(output);
|
|
431
431
|
|
|
432
432
|
this.visibleAndFetchedTiles()
|
|
433
|
-
.filter((tile) => tile.svgData
|
|
433
|
+
.filter((tile) => tile.svgData?.barXValues)
|
|
434
434
|
.forEach((tile) => {
|
|
435
435
|
// const [xScale, xPos] = this.getXScaleAndOffset(tile.drawnAtScale);
|
|
436
436
|
const data = tile.svgData;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import boxIntersect from 'box-intersect';
|
|
3
3
|
import { median, range } from 'd3-array';
|
|
4
4
|
import { scaleBand, scaleLinear } from 'd3-scale';
|
|
5
|
-
import classifyPoint from 'robust-point-in-polygon';
|
|
6
5
|
import { zoomIdentity } from 'd3-zoom';
|
|
6
|
+
import classifyPoint from 'robust-point-in-polygon';
|
|
7
7
|
|
|
8
8
|
import HorizontalTiled1DPixiTrack from './HorizontalTiled1DPixiTrack';
|
|
9
9
|
import trackUtils from './track-utils';
|
|
@@ -84,7 +84,7 @@ class BedLikeTrack extends HorizontalTiled1DPixiTrack {
|
|
|
84
84
|
let plusStrandRows = [];
|
|
85
85
|
let minusStrandRows = [];
|
|
86
86
|
|
|
87
|
-
if (tile.tileData
|
|
87
|
+
if (tile.tileData?.length) {
|
|
88
88
|
tile.tileData.sort((a, b) => b.importance - a.importance);
|
|
89
89
|
// tile.tileData = tile.tileData.slice(0, MAX_TILE_ENTRIES);
|
|
90
90
|
|
|
@@ -164,9 +164,9 @@ class BedLikeTrack extends HorizontalTiled1DPixiTrack {
|
|
|
164
164
|
tile.rectGraphics.clear();
|
|
165
165
|
tile.rendered = false;
|
|
166
166
|
|
|
167
|
-
if (tile.tileData
|
|
167
|
+
if (tile.tileData?.length) {
|
|
168
168
|
tile.tileData.forEach((td, i) => {
|
|
169
|
-
if (this.drawnRects[zoomLevel]
|
|
169
|
+
if (this.drawnRects[zoomLevel]?.[td.uid]) {
|
|
170
170
|
if (this.drawnRects[zoomLevel][td.uid][2] === tile.tileId) {
|
|
171
171
|
// this was the tile that drew that rectangle
|
|
172
172
|
delete this.drawnRects[zoomLevel][td.uid];
|
|
@@ -196,7 +196,7 @@ class BedLikeTrack extends HorizontalTiled1DPixiTrack {
|
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
drawTile(tile) {
|
|
199
|
-
if (this.options
|
|
199
|
+
if (this.options?.valueColumn) {
|
|
200
200
|
// there might no be a value scale if no valueColumn was specified
|
|
201
201
|
if (this.valueScale) this.drawAxis(this.valueScale);
|
|
202
202
|
}
|
|
@@ -404,7 +404,7 @@ class BedLikeTrack extends HorizontalTiled1DPixiTrack {
|
|
|
404
404
|
setValueScale() {
|
|
405
405
|
this.valueScale = null;
|
|
406
406
|
|
|
407
|
-
if (this.options
|
|
407
|
+
if (this.options?.valueColumn) {
|
|
408
408
|
/**
|
|
409
409
|
* These intervals come with some y-value that we want to plot
|
|
410
410
|
*/
|
|
@@ -431,8 +431,7 @@ class BedLikeTrack extends HorizontalTiled1DPixiTrack {
|
|
|
431
431
|
this.colorValueScale = null;
|
|
432
432
|
|
|
433
433
|
if (
|
|
434
|
-
this.options &&
|
|
435
|
-
this.options.colorEncoding &&
|
|
434
|
+
this.options?.colorEncoding &&
|
|
436
435
|
this.options.colorEncoding !== 'itemRgb'
|
|
437
436
|
) {
|
|
438
437
|
const min = this.options.colorEncodingRange
|
|
@@ -655,7 +654,7 @@ class BedLikeTrack extends HorizontalTiled1DPixiTrack {
|
|
|
655
654
|
// this.options.colorEncoding is set
|
|
656
655
|
this.setColorValueScale();
|
|
657
656
|
|
|
658
|
-
if (tile.tileData
|
|
657
|
+
if (tile.tileData?.length) {
|
|
659
658
|
const fill =
|
|
660
659
|
this.options.plusStrandColor || this.options.fillColor || 'blue';
|
|
661
660
|
const minusStrandFill =
|
|
@@ -721,7 +720,7 @@ class BedLikeTrack extends HorizontalTiled1DPixiTrack {
|
|
|
721
720
|
null,
|
|
722
721
|
visibleAndFetchedIds
|
|
723
722
|
.map((x) => this.fetchedTiles[x])
|
|
724
|
-
.filter((x) => x.tileData
|
|
723
|
+
.filter((x) => x.tileData?.length)
|
|
725
724
|
.map((x) =>
|
|
726
725
|
Math.min.apply(
|
|
727
726
|
null,
|
|
@@ -753,7 +752,7 @@ class BedLikeTrack extends HorizontalTiled1DPixiTrack {
|
|
|
753
752
|
null,
|
|
754
753
|
visibleAndFetchedIds
|
|
755
754
|
.map((x) => this.fetchedTiles[x])
|
|
756
|
-
.filter((x) => x.tileData
|
|
755
|
+
.filter((x) => x.tileData?.length)
|
|
757
756
|
.map((x) =>
|
|
758
757
|
Math.max.apply(
|
|
759
758
|
null,
|
|
@@ -789,7 +788,7 @@ class BedLikeTrack extends HorizontalTiled1DPixiTrack {
|
|
|
789
788
|
.concat(
|
|
790
789
|
...visibleAndFetchedIds
|
|
791
790
|
.map((x) => this.fetchedTiles[x])
|
|
792
|
-
.filter((x) => x.tileData
|
|
791
|
+
.filter((x) => x.tileData?.length)
|
|
793
792
|
.map((x) =>
|
|
794
793
|
x.tileData
|
|
795
794
|
.sort((a, b) => b.importance - a.importance)
|
|
@@ -833,7 +832,7 @@ class BedLikeTrack extends HorizontalTiled1DPixiTrack {
|
|
|
833
832
|
continue;
|
|
834
833
|
}
|
|
835
834
|
|
|
836
|
-
if (tile.tileData
|
|
835
|
+
if (tile.tileData?.length) {
|
|
837
836
|
tile.tileData.forEach((td) => {
|
|
838
837
|
if (!tile.texts) {
|
|
839
838
|
// tile probably hasn't been initialized yet
|
package/app/scripts/Button.jsx
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
import
|
|
3
|
-
import React from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
4
3
|
import { brush, brushX, brushY } from 'd3-brush';
|
|
5
4
|
import { select } from 'd3-selection';
|
|
6
|
-
import
|
|
5
|
+
import PropTypes from 'prop-types';
|
|
6
|
+
import React from 'react';
|
|
7
7
|
|
|
8
8
|
import TrackControl from './TrackControl';
|
|
9
9
|
|
|
10
10
|
// Utils
|
|
11
|
-
import { or, resetD3BrushStyle
|
|
11
|
+
import { IS_TRACK_RANGE_SELECTABLE, or, resetD3BrushStyle } from './utils';
|
|
12
12
|
|
|
13
13
|
// Styles
|
|
14
|
-
import styles from '../styles/CenterTrack.module.scss';
|
|
15
|
-
import stylesTrack from '../styles/Track.module.scss';
|
|
14
|
+
import styles from '../styles/CenterTrack.module.scss';
|
|
15
|
+
import stylesTrack from '../styles/Track.module.scss';
|
|
16
16
|
|
|
17
17
|
const STYLES = {
|
|
18
18
|
pointerEvents: 'all',
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
function sourceEvent(event) {
|
|
22
|
-
return event
|
|
22
|
+
return event?.sourceEvent;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
class CenterTrack extends React.Component {
|
|
@@ -488,6 +488,7 @@ class CenterTrack extends React.Component {
|
|
|
488
488
|
}}
|
|
489
489
|
xmlns="http://www.w3.org/2000/svg"
|
|
490
490
|
>
|
|
491
|
+
<title>Range Selection Brush</title>
|
|
491
492
|
<g
|
|
492
493
|
ref={(el) => {
|
|
493
494
|
this.brushElX = select(el);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
import boxIntersect from 'box-intersect';
|
|
3
3
|
|
|
4
|
-
import PixiTrack from './PixiTrack';
|
|
5
4
|
import ChromosomeInfo from './ChromosomeInfo';
|
|
5
|
+
import PixiTrack from './PixiTrack';
|
|
6
6
|
import SearchField from './SearchField';
|
|
7
7
|
|
|
8
8
|
import { absToChr } from './utils';
|