higlass 1.12.4 → 1.13.1
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 +3 -3
- package/app/globals.d.ts +11 -0
- package/app/missing-types.d.ts +21 -0
- package/app/scripts/CenterTrack.jsx +0 -1
- package/app/scripts/DraggableDiv.jsx +0 -1
- package/app/scripts/GenomePositionSearchBox.jsx +0 -1
- package/app/scripts/PixiTrack.js +106 -42
- package/app/scripts/Track.js +153 -45
- package/app/scripts/TrackRenderer.jsx +452 -135
- package/app/scripts/VerticalTiledPlot.jsx +0 -1
- package/app/scripts/configs/default-tracks-for-datatype.js +3 -2
- package/app/scripts/configs/primitives.js +3 -2
- package/app/scripts/configs/tracks-info-by-type.js +4 -1
- package/app/scripts/configs/tracks-info.js +25 -1
- package/app/scripts/hocs/with-pub-sub.jsx +3 -1
- package/app/scripts/types.ts +105 -0
- package/app/scripts/utils/abs-to-chr.js +16 -1
- package/app/scripts/utils/accessor-transposition.js +5 -4
- package/app/scripts/utils/add-arrays.js +9 -7
- package/app/scripts/utils/add-class.js +4 -2
- package/app/scripts/utils/add-event-listener-once.js +9 -3
- package/app/scripts/utils/background-task-scheduler.js +58 -2
- package/app/scripts/utils/base64-to-canvas.js +12 -5
- package/app/scripts/utils/chr-to-abs.js +10 -0
- package/app/scripts/utils/chrom-info-bisector.js +4 -1
- package/app/scripts/utils/clone-event.js +11 -4
- package/app/scripts/utils/color-to-hex.js +8 -0
- package/app/scripts/utils/color-to-rgba.js +8 -0
- package/app/scripts/utils/data-to-genomic-loci.js +13 -1
- package/app/scripts/utils/debounce.js +16 -11
- package/app/scripts/utils/dec-to-hex-str.js +7 -0
- package/app/scripts/utils/dict-from-tuples.js +11 -3
- package/app/scripts/utils/dict-items.js +15 -0
- package/app/scripts/utils/dict-keys.js +11 -1
- package/app/scripts/utils/dict-values.js +7 -0
- package/app/scripts/utils/download.js +14 -11
- package/app/scripts/utils/flatten.js +5 -2
- package/app/scripts/utils/for-each.js +7 -5
- package/app/scripts/utils/forward-event.js +3 -2
- package/app/scripts/utils/genome-loci-to-pixels.js +8 -0
- package/app/scripts/utils/genomic-range-to-chromosome-chunks.js +13 -6
- package/app/scripts/utils/get-aggregation-function.js +10 -2
- package/app/scripts/utils/get-element-dim.js +6 -0
- package/app/scripts/utils/gradient.js +14 -0
- package/app/scripts/utils/has-class.js +6 -4
- package/app/scripts/utils/hex-string-to-int.js +11 -4
- package/app/scripts/utils/index.js +1 -0
- package/app/scripts/utils/into-the-void.js +2 -1
- package/app/scripts/utils/is-track-or-child-track.js +6 -0
- package/app/scripts/utils/is-track-range-selectable.js +10 -1
- package/app/scripts/utils/is-within.js +9 -7
- package/app/scripts/utils/lat-to-y.js +6 -3
- package/app/scripts/utils/lng-to-x.js +4 -3
- package/app/scripts/utils/map.js +5 -2
- package/app/scripts/utils/max-non-zero.js +6 -0
- package/app/scripts/utils/max.js +4 -3
- package/app/scripts/utils/min-non-zero.js +6 -0
- package/app/scripts/utils/min.js +4 -3
- package/app/scripts/utils/mod.js +4 -3
- package/app/scripts/utils/numericify-version.js +5 -0
- package/app/scripts/utils/obj-vals.js +3 -2
- package/app/scripts/utils/or.js +4 -3
- package/app/scripts/utils/parse-chromsizes-rows.js +26 -5
- package/app/scripts/utils/q.js +3 -2
- package/app/scripts/utils/rad-to-deg.js +3 -2
- package/app/scripts/utils/reduce.js +2 -2
- package/app/scripts/utils/rel-to-abs-chrom-pos.js +10 -0
- package/app/scripts/utils/remove-class.js +3 -2
- package/app/scripts/utils/reset-d3-brush-style.js +7 -2
- package/app/scripts/utils/rgb-to-hex.js +9 -0
- package/app/scripts/utils/scales-center-and-k.js +5 -3
- package/app/scripts/utils/scales-to-genome-loci.js +10 -0
- package/app/scripts/utils/selected-items-to-cum-weights.js +12 -4
- package/app/scripts/utils/selected-items-to-size.js +5 -2
- package/app/scripts/utils/show-mouse-position.js +62 -19
- package/app/scripts/utils/some.js +6 -4
- package/app/scripts/utils/sum.js +4 -3
- package/app/scripts/utils/throttle-and-debounce.js +15 -6
- package/app/scripts/utils/tile-to-canvas.js +8 -4
- package/app/scripts/utils/timeout.js +2 -0
- package/app/scripts/utils/to-void.js +2 -0
- package/app/scripts/utils/total-track-pixel-height.js +11 -12
- package/app/scripts/utils/trim-trailing-slash.js +3 -2
- package/app/scripts/utils/type-guards.js +41 -0
- package/app/scripts/utils/value-to-color.js +7 -6
- package/app/scripts/utils/visit-positioned-tracks.js +16 -11
- package/app/scripts/utils/visit-tracks.js +12 -13
- package/dist/esm.html +283 -0
- package/dist/hglib.js +42 -82804
- package/dist/hglib.min.js +86 -105
- package/dist/higlass.mjs +207 -0
- package/dist/index.html +6 -6
- package/package.json +23 -5
|
@@ -1,8 +1,23 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @template T
|
|
5
|
+
* @typedef {Array<{ [Key in keyof T]: [Key, T[Key]] }[keyof T]>} DictItems
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
/**
|
|
2
9
|
* Return an array of (key,value) pairs that are present in this
|
|
3
10
|
* dictionary
|
|
11
|
+
*
|
|
12
|
+
* TODO(Trevor): Replace with `Object.entries`?
|
|
13
|
+
*
|
|
14
|
+
* @template {object} T
|
|
15
|
+
* @param {T} dictionary
|
|
16
|
+
*
|
|
17
|
+
* @returns {DictItems<T>}
|
|
4
18
|
*/
|
|
5
19
|
const dictItems = (dictionary) => {
|
|
20
|
+
/** @type {DictItems<T>} */
|
|
6
21
|
const keyValues = [];
|
|
7
22
|
|
|
8
23
|
for (const key in dictionary) {
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
* Return an array of
|
|
4
|
+
* Return an array of keys that are present in this dictionary
|
|
5
|
+
*
|
|
6
|
+
* TODO(Trevor): Replace with `Object.keys`?
|
|
7
|
+
*
|
|
8
|
+
* @template T
|
|
9
|
+
* @param {T} dictionary
|
|
10
|
+
* @returns {Array<keyof T>}
|
|
3
11
|
*/
|
|
4
12
|
export default function dictKeys(dictionary) {
|
|
13
|
+
/** @type {Array<keyof T>} */
|
|
5
14
|
const keys = [];
|
|
6
15
|
|
|
7
16
|
for (const key in dictionary) {
|
|
17
|
+
// @ts-expect-error - TS inference not good enough to infer the correct type
|
|
8
18
|
if (dictionary.hasOwnProperty(key)) {
|
|
9
19
|
keys.push(key);
|
|
10
20
|
}
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Return an array of values that are present in this dictionary
|
|
5
|
+
*
|
|
6
|
+
* @template {object} T
|
|
7
|
+
* @param {T} dictionary
|
|
8
|
+
* @returns {Array<T[keyof T]>}
|
|
3
9
|
*/
|
|
4
10
|
export default function dictValues(dictionary) {
|
|
11
|
+
/** @type {Array<T[keyof T]>} */
|
|
5
12
|
const values = [];
|
|
6
13
|
|
|
7
14
|
for (const key in dictionary) {
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Download a file to the user's computer.
|
|
5
|
+
* @param {string} filename - Name of the file to download
|
|
6
|
+
* @param {string | Blob} stringOrBlob - Contents of the file to download
|
|
7
|
+
*/
|
|
1
8
|
export function download(filename, stringOrBlob) {
|
|
2
9
|
// yanked from here
|
|
3
10
|
// https://stackoverflow.com/questions/3665115/create-a-file-in-memory-for-user-to-download-not-through-server
|
|
@@ -6,17 +13,13 @@ export function download(filename, stringOrBlob) {
|
|
|
6
13
|
typeof stringOrBlob === 'string'
|
|
7
14
|
? new Blob([stringOrBlob], { type: 'application/octet-stream' })
|
|
8
15
|
: stringOrBlob;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
elem.click();
|
|
17
|
-
document.body.removeChild(elem);
|
|
18
|
-
URL.revokeObjectURL(elem.href);
|
|
19
|
-
}
|
|
16
|
+
const elem = window.document.createElement('a');
|
|
17
|
+
elem.href = window.URL.createObjectURL(blob);
|
|
18
|
+
elem.download = filename;
|
|
19
|
+
document.body.appendChild(elem);
|
|
20
|
+
elem.click();
|
|
21
|
+
document.body.removeChild(elem);
|
|
22
|
+
URL.revokeObjectURL(elem.href);
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
export default download;
|
|
@@ -2,9 +2,12 @@ import reduce from './reduce';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Function for flattening a nested array. It returns a curried reducer.
|
|
5
|
-
*
|
|
6
|
-
* @
|
|
5
|
+
*
|
|
6
|
+
* @template T
|
|
7
|
+
* @param {Array<Array<T>>} Nested array
|
|
8
|
+
* @return {Array<T>} Flat array
|
|
7
9
|
*/
|
|
8
10
|
const flatten = reduce((a, b) => a.concat(b), []);
|
|
9
11
|
|
|
12
|
+
// TODO(Trevor): Not referenced anywhere. Remove?
|
|
10
13
|
export default flatten;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/**
|
|
2
|
-
* Functional version of `Array.forEach`. More flexible and applicable to
|
|
3
|
-
*
|
|
4
|
-
* @
|
|
5
|
-
*
|
|
6
|
-
* @return
|
|
3
|
+
* Functional version of `Array.forEach`. More flexible and applicable to other array-like data types.
|
|
4
|
+
*
|
|
5
|
+
* @template T
|
|
6
|
+
* @param {<T>(item: T) => void} f - Modifier function applied on every item of the array.
|
|
7
|
+
* @return {(arr: ArrayLike<T>) => void} Modified array-like variable.
|
|
7
8
|
*/
|
|
8
9
|
const forEach = (f) => (x) => Array.prototype.forEach.call(x, f);
|
|
9
10
|
|
|
11
|
+
// TODO(Trevor): Not referenced anywhere. Remove?
|
|
10
12
|
export default forEach;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import cloneEvent from './clone-event';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Forward an event by cloning and dispatching it.
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
6
|
+
* @param {Event} event - Event to be forwarded.
|
|
7
|
+
* @param {HTMLElement} target - Target HTML element for the event.
|
|
7
8
|
*/
|
|
8
9
|
const forwardEvent = (event, target) => {
|
|
9
10
|
target.dispatchEvent(cloneEvent(event));
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import chrToAbs from './chr-to-abs';
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Convert a genome locus to an absolute genome position.
|
|
6
|
+
* @template {string} Name
|
|
7
|
+
* @param {[Name, number, Name, number]} genomeLoci - Genome locus
|
|
8
|
+
* @param {import('../types').ChromInfo<Name>} chromInfo - Chromosome info object
|
|
9
|
+
* @return {[start: number, end: number]} The absolute genome position.
|
|
10
|
+
*/
|
|
3
11
|
const genomeLociToPixels = (genomeLoci, chromInfo) => [
|
|
4
12
|
chrToAbs(genomeLoci[0], genomeLoci[1], chromInfo),
|
|
5
13
|
chrToAbs(genomeLoci[2], genomeLoci[3], chromInfo),
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Using the [genomicStart, genomicEnd] range, get an array of "chromosome chunks",
|
|
3
5
|
* where each chunk range starts and ends with the same chromosome.
|
|
4
6
|
* Start a new chromosome chunk at each chromosome boundary.
|
|
5
|
-
*
|
|
6
|
-
* @
|
|
7
|
-
* @param {
|
|
8
|
-
* @param {number}
|
|
9
|
-
* @param {number}
|
|
10
|
-
* @
|
|
7
|
+
*
|
|
8
|
+
* @template {string} Name
|
|
9
|
+
* @param {Array<[charName: Name, chrLen: number]>} chromSizes - Array of [chrName, chrLen] tuples.
|
|
10
|
+
* @param {{ chr: Name, pos: number }} genomicStart - A genomic position object returned from abs2genomic { chr, pos }.
|
|
11
|
+
* @param {{ chr: Name, pos: number }} genomicEnd - A genomic position object returned from abs2genomic { chr, pos }.
|
|
12
|
+
* @param {number} binSize - The resolution / bin size.
|
|
13
|
+
* @param {number} tileSize - The tile size (probably 256).
|
|
14
|
+
* @returns {Array<[chrName: Name, zStart: number, zEnd: number]>} Returns array of [chrName, zStart, zEnd] tuples.
|
|
11
15
|
*/
|
|
12
16
|
function genomicRangeToChromosomeChunks(
|
|
13
17
|
chromSizes,
|
|
@@ -19,6 +23,7 @@ function genomicRangeToChromosomeChunks(
|
|
|
19
23
|
const { chr: chrStart, pos: chrStartPos } = genomicStart;
|
|
20
24
|
const { chr: chrEnd, pos: chrEndPos } = genomicEnd;
|
|
21
25
|
|
|
26
|
+
/** @type {Array<[chrName: Name, zStart: number, zEnd: number]>} */
|
|
22
27
|
const chrChunks = [];
|
|
23
28
|
if (chrStart === chrEnd) {
|
|
24
29
|
// This tile does _not_ cross a chromosome boundary.
|
|
@@ -37,7 +42,9 @@ function genomicRangeToChromosomeChunks(
|
|
|
37
42
|
|
|
38
43
|
// Create a separate chunk for each chromosome that lies within the range.
|
|
39
44
|
for (let chrIndex = chrStartIndex; chrIndex <= chrEndIndex; chrIndex++) {
|
|
45
|
+
/** @type {number} */
|
|
40
46
|
let chrChunkStart;
|
|
47
|
+
/** @type {number} */
|
|
41
48
|
let chrChunkEnd;
|
|
42
49
|
|
|
43
50
|
const [currChrName, currChrLen] = chromSizes[chrIndex];
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import { mean, sum, variance, deviation } from 'd3-array';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Get an aggregation function from a function name.
|
|
5
|
-
* @
|
|
6
|
+
* @template {'mean' | 'sum' | 'variance' | 'deviation'} Type
|
|
7
|
+
* @param {Type} name - The name of an aggregation function
|
|
6
8
|
* ('mean', 'sum', 'variance', 'deviation'). If an unknown string is passed,
|
|
7
9
|
* the mean function will be used, and a console warning will be thrown.
|
|
8
|
-
* @returns {
|
|
10
|
+
* @returns {{
|
|
11
|
+
* mean: typeof mean,
|
|
12
|
+
* sum: typeof sum,
|
|
13
|
+
* variance: typeof variance,
|
|
14
|
+
* deviation: typeof deviation,
|
|
15
|
+
* }[Type]} The function of interest as determined by the string,
|
|
9
16
|
*/
|
|
10
17
|
const getAggregationFunction = (name) => {
|
|
11
18
|
let aggFunc;
|
|
@@ -29,6 +36,7 @@ const getAggregationFunction = (name) => {
|
|
|
29
36
|
'Encountered an unsupported selectedRowsAggregationMode option.',
|
|
30
37
|
);
|
|
31
38
|
}
|
|
39
|
+
// @ts-expect-error - TS can't infer type-mapping
|
|
32
40
|
return aggFunc;
|
|
33
41
|
};
|
|
34
42
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import { ElementResizeListener } from '../services';
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Get the dimensions of an element
|
|
6
|
+
* @param {HTMLElement} element - DOM element to get dimensions of.
|
|
7
|
+
* @return {[width: number, height: number]} The width and height of the element.
|
|
8
|
+
*/
|
|
3
9
|
const getElementDim = (element) => {
|
|
4
10
|
ElementResizeListener.listen();
|
|
5
11
|
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {{ from: number, color: string }[]} steps
|
|
5
|
+
* @param {number} width
|
|
6
|
+
* @param {number} height
|
|
7
|
+
* @param {number} fromX
|
|
8
|
+
* @param {number} fromY
|
|
9
|
+
* @param {number} toX
|
|
10
|
+
* @param {number} toY
|
|
11
|
+
*/
|
|
1
12
|
const gradient = (
|
|
2
13
|
steps,
|
|
3
14
|
width = 1,
|
|
@@ -12,6 +23,9 @@ const gradient = (
|
|
|
12
23
|
canvas.height = height;
|
|
13
24
|
|
|
14
25
|
const ctx = canvas.getContext('2d');
|
|
26
|
+
if (!ctx) {
|
|
27
|
+
throw new Error('Could not get canvas context');
|
|
28
|
+
}
|
|
15
29
|
const grd = ctx.createLinearGradient(fromX, fromY, toX, toY);
|
|
16
30
|
|
|
17
31
|
steps.forEach((step) => {
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
const XMLNS = 'http://www.w3.org/2000/svg';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Check if an HTML or SVG element has a certain class
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
7
|
-
* @return
|
|
7
|
+
* @param {Element} el - HTML or SVG element to be checked.
|
|
8
|
+
* @param {string} className - Class name to be checked for.
|
|
9
|
+
* @return {boolean} If `true` `el` has the class name.
|
|
8
10
|
*/
|
|
9
11
|
const hasClass = (el, className) => {
|
|
10
12
|
if (el.namespaceURI === XMLNS) {
|
|
11
13
|
const _class = el.getAttribute('class');
|
|
12
|
-
return _class && !!_class.match(new RegExp(`(\\s|^)${className}(\\s|$)`));
|
|
14
|
+
return !!_class && !!_class.match(new RegExp(`(\\s|^)${className}(\\s|$)`));
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
if (el.classList) return el.classList.contains(className);
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/**
|
|
2
|
-
* Convert a HEX string into a HEX integer.
|
|
3
|
-
*
|
|
4
|
-
* @
|
|
5
|
-
*
|
|
3
|
+
* Convert a HEX string into a HEX integer.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```js
|
|
7
|
+
* // returns 16711680
|
|
8
|
+
* hexStrToInt("#FF0000");
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @param {string} str - HEX string
|
|
12
|
+
* @return {number} An (integer) HEX number
|
|
6
13
|
*/
|
|
7
14
|
const hexStrToInt = (str) => parseInt(str.replace(/^#/, ''), 16);
|
|
8
15
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import CombinedTrack from '../CombinedTrack';
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @param {import('../types').TrackObject} testTrack
|
|
6
|
+
* @param {import('../types').TrackObject} track
|
|
7
|
+
* @returns {boolean}
|
|
8
|
+
*/
|
|
3
9
|
const isTrackOrChildTrack = (testTrack, track) => {
|
|
4
10
|
if (track === testTrack) return true;
|
|
5
11
|
if (track instanceof CombinedTrack) {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import or from './or';
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Return true if this track is selectable by range.
|
|
6
|
+
* @param {import('../types').TrackConfig} track
|
|
7
|
+
* @returns {boolean}
|
|
8
|
+
*/
|
|
3
9
|
export const IS_TRACK_RANGE_SELECTABLE = (track) => {
|
|
4
10
|
switch (track.type) {
|
|
5
11
|
case 'heatmap':
|
|
@@ -24,7 +30,10 @@ export const IS_TRACK_RANGE_SELECTABLE = (track) => {
|
|
|
24
30
|
return true;
|
|
25
31
|
|
|
26
32
|
case 'combined': {
|
|
27
|
-
|
|
33
|
+
/** @type {import('../types').TrackConfig[]} */
|
|
34
|
+
// @ts-expect-error - TS should be able to narrow the type but isn't smart enough
|
|
35
|
+
const contents = track.contents;
|
|
36
|
+
return contents
|
|
28
37
|
.map((t) => IS_TRACK_RANGE_SELECTABLE(t))
|
|
29
38
|
.reduce(or, false);
|
|
30
39
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Check if a 2D or 1D point is within a rectangle or range
|
|
3
|
-
* @param
|
|
4
|
-
* @param
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
7
|
-
* @param
|
|
8
|
-
* @param
|
|
9
|
-
* @return
|
|
5
|
+
* @param {number} x - The point's X coordinate.
|
|
6
|
+
* @param {number} y - The point's Y coordinate.
|
|
7
|
+
* @param {number} minX - The rectangle's start X coordinate.
|
|
8
|
+
* @param {number} maxX - The rectangle's start X coordinate.
|
|
9
|
+
* @param {number} minY - The rectangle's start X coordinate.
|
|
10
|
+
* @param {number} maxY - The rectangle's start X coordinate.
|
|
11
|
+
* @return {boolean} If `true` the [x,y] point is in the rectangle.
|
|
10
12
|
*/
|
|
11
13
|
const isWithin = (x, y, minX, maxX, minY, maxY, is1d = false) =>
|
|
12
14
|
is1d
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/** @param {number} y */
|
|
1
4
|
export const invGudermannian = (y) => Math.log(Math.tan((y + Math.PI / 2) / 2));
|
|
2
5
|
|
|
3
6
|
/**
|
|
4
7
|
* Translate latitude to Y in the Mercator projection
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
7
|
-
* @return
|
|
8
|
+
* @param {number} lat - Latitude.
|
|
9
|
+
* @param {number} zoom - Zoom level
|
|
10
|
+
* @return {number} Y coordinate in the Mercator projection.
|
|
8
11
|
*/
|
|
9
12
|
const latToY = (lat, zoom) => {
|
|
10
13
|
let latRad = (lat * Math.PI) / 180.0;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/**
|
|
2
3
|
* Convert longitude to the X coordinate in the Mercator projection.
|
|
3
|
-
* @param
|
|
4
|
-
* @param
|
|
5
|
-
* @return
|
|
4
|
+
* @param {number} lng - Longitude
|
|
5
|
+
* @param {number} zoom - Zoom level
|
|
6
|
+
* @return {number} X coordinate in the Mercator projection.
|
|
6
7
|
*/
|
|
7
8
|
const lngToX = (lng, zoom) => (2 ** zoom * (lng + 180.0)) / 360.0;
|
|
8
9
|
|
package/app/scripts/utils/map.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/**
|
|
2
3
|
* Exposed map function. You can do cool stuff with that!
|
|
3
4
|
*
|
|
@@ -5,9 +6,11 @@
|
|
|
5
6
|
* The pure map function is more powerful because it can be used on data types
|
|
6
7
|
* other than Array too.
|
|
7
8
|
*
|
|
8
|
-
* @
|
|
9
|
-
* @
|
|
9
|
+
* @template T, B
|
|
10
|
+
* @param {(item: T, idx?: number) => B} f - Mapping function.
|
|
11
|
+
* @return {(x: Array<T>) => Array<B>} Mapped array.
|
|
10
12
|
*/
|
|
13
|
+
// @ts-expect-error - TS can't infer the type of the returned function.
|
|
11
14
|
const map = (f) => (x) => Array.prototype.map.call(x, f);
|
|
12
15
|
|
|
13
16
|
export default map;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
const epsilon = 0.0000001;
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Calculate the maximum non-zero value in the data
|
|
6
|
+
* @param {ArrayLike<number>} data - An array of values
|
|
7
|
+
* @returns {number} The maximum non-zero value in the array
|
|
8
|
+
*/
|
|
3
9
|
export default function maxNonZero(data) {
|
|
4
10
|
/**
|
|
5
11
|
* Calculate the minimum non-zero value in the data
|
package/app/scripts/utils/max.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/**
|
|
2
3
|
* Fast version of `Math.max`. Based on
|
|
3
4
|
* https://jsperf.com/math-min-max-vs-ternary-vs-if/24 `Math.max` is not
|
|
4
5
|
* very fast
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
7
|
-
* @return
|
|
6
|
+
* @param {number} a - Value A
|
|
7
|
+
* @param {number} b - Value B
|
|
8
|
+
* @return {number} If `true` A is greater than B.
|
|
8
9
|
*/
|
|
9
10
|
const max = (a, b) => (a > b ? a : b);
|
|
10
11
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
const epsilon = 0.0000001;
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Calculate the minimum non-zero value in the data
|
|
6
|
+
* @param {ArrayLike<number>} data - An array of values
|
|
7
|
+
* @returns {number} The minimum non-zero value in the array
|
|
8
|
+
*/
|
|
3
9
|
export default function minNonZero(data) {
|
|
4
10
|
/**
|
|
5
11
|
* Calculate the minimum non-zero value in the data
|
package/app/scripts/utils/min.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/**
|
|
2
3
|
* Fast version of `Math.min`. Based on
|
|
3
4
|
* https://jsperf.com/math-min-max-vs-ternary-vs-if/24 `Math.max` is not
|
|
4
5
|
* very fast
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
7
|
-
* @return
|
|
6
|
+
* @param {number} a - Value A
|
|
7
|
+
* @param {number} b - Value B
|
|
8
|
+
* @return {number} If `true` A is smaller than B.
|
|
8
9
|
*/
|
|
9
10
|
const min = (a, b) => (a < b ? a : b);
|
|
10
11
|
|
package/app/scripts/utils/mod.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/**
|
|
2
3
|
* Non-negative modulo function. E.g., `mod(-1, 5) === 4` while `-1 % 5 === -1`.
|
|
3
4
|
*
|
|
4
|
-
* @param
|
|
5
|
-
* @param
|
|
6
|
-
* @return
|
|
5
|
+
* @param {number} n - Dividend (integer)
|
|
6
|
+
* @param {number} m - Divisor (integer)
|
|
7
|
+
* @return {number} Remainder (integer)
|
|
7
8
|
*/
|
|
8
9
|
const mod = (n, m) => ((n % m) + m) % m;
|
|
9
10
|
|
|
@@ -3,9 +3,10 @@ import map from './map';
|
|
|
3
3
|
/**
|
|
4
4
|
* Convert an object into array which entries are the prop values of the object
|
|
5
5
|
*
|
|
6
|
-
* @param {Object}
|
|
7
|
-
* @return {Array}
|
|
6
|
+
* @param {Object} obj - Object to be arrayified
|
|
7
|
+
* @return {Array} Array of the object.
|
|
8
8
|
*/
|
|
9
9
|
const objVals = (obj) => map((key) => obj[key])(Object.keys(obj));
|
|
10
10
|
|
|
11
|
+
// TODO(Trevor): We already have dictValues and `Object.values`? Can we get rid of this?
|
|
11
12
|
export default objVals;
|
package/app/scripts/utils/or.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
/**
|
|
2
3
|
* Logical or operator for convenience.
|
|
3
|
-
* @param
|
|
4
|
-
* @param
|
|
5
|
-
* @return
|
|
4
|
+
* @param {boolean} a - Value A
|
|
5
|
+
* @param {boolean} b - Value B
|
|
6
|
+
* @return {boolean} If `true` one of the two or both values are truthy.
|
|
6
7
|
*/
|
|
7
8
|
const or = (a, b) => a || b;
|
|
8
9
|
|
|
@@ -1,13 +1,34 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/** @typedef {[string, number]} ChromsizeRow */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef CumulativeChromsizeEntry
|
|
7
|
+
* @property {number} id
|
|
8
|
+
* @property {string} chr
|
|
9
|
+
* @property {number} pos
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef ParsedChromsizes
|
|
14
|
+
* @property {CumulativeChromsizeEntry[]} cumPositions
|
|
15
|
+
* @property {Record<string, CumulativeChromsizeEntry>} chrPositions
|
|
16
|
+
* @property {number} totalLength
|
|
17
|
+
* @property {Record<string, number>} chromLengths
|
|
18
|
+
*/
|
|
19
|
+
|
|
1
20
|
/**
|
|
2
|
-
* Parse an array of chromsizes, for example that result
|
|
3
|
-
*
|
|
4
|
-
* @param {
|
|
5
|
-
* @returns {
|
|
6
|
-
* { cumPositions, chrPositions, totalLength, chromLengths }.
|
|
21
|
+
* Parse an array of chromsizes, for example that result from reading rows of a chromsizes CSV file.
|
|
22
|
+
*
|
|
23
|
+
* @param {ArrayLike<ChromsizeRow>} data - Array of [chrName, chrLen] "tuples".
|
|
24
|
+
* @returns {ParsedChromsizes}
|
|
7
25
|
*/
|
|
8
26
|
function parseChromsizesRows(data) {
|
|
27
|
+
/** @type {Array<CumulativeChromsizeEntry>} */
|
|
9
28
|
const cumValues = [];
|
|
29
|
+
/** @type {Record<string, number>} */
|
|
10
30
|
const chromLengths = {};
|
|
31
|
+
/** @type {Record<string, CumulativeChromsizeEntry>} */
|
|
11
32
|
const chrPositions = {};
|
|
12
33
|
|
|
13
34
|
let totalLength = 0;
|
package/app/scripts/utils/q.js
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* console.log(myFancyQuery(myFancyObj)) ==> 'Sweet!'
|
|
12
12
|
* console.log(myFancyQuery(myNotSoFancyObj)) ==> undefined
|
|
13
13
|
* ```
|
|
14
|
-
* @param
|
|
15
|
-
* @return
|
|
14
|
+
* @param {string} queryStr - dot-notation query string
|
|
15
|
+
* @return {unknown}
|
|
16
16
|
*/
|
|
17
17
|
const q = (queryStr) => {
|
|
18
18
|
try {
|
|
@@ -29,4 +29,5 @@ const q = (queryStr) => {
|
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
// TODO(Trevor): This is not referenced anywhere in the codebase, but it is exported. Remove?
|
|
32
33
|
export default q;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pure functional reducer. Can be used for currying stuff. Check out
|
|
3
|
-
* `flatten.js`.
|
|
2
|
+
* Pure functional reducer. Can be used for currying stuff. Check out `flatten.js`.
|
|
4
3
|
* @param {function} f Reducer function.
|
|
5
4
|
* @return {array} Curried function that accepts an array to be reduced.
|
|
6
5
|
*/
|
|
7
6
|
const reduce = (f) => (x) => Array.prototype.reduce.call(x, f);
|
|
8
7
|
|
|
8
|
+
// TODO(Trevor): Not referenced anywhere. Remove?
|
|
9
9
|
export default reduce;
|