@gmod/hic 1.2.1 → 1.3.0
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 +19 -14
- package/dist/bufferedFile.d.ts +2 -2
- package/dist/bufferedFile.js +5 -5
- package/dist/bufferedFile.js.map +1 -1
- package/dist/hicFile.d.ts +9 -10
- package/dist/hicFile.js +167 -174
- package/dist/hicFile.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/lru.js +0 -2
- package/dist/lru.js.map +1 -1
- package/dist/normalizationVector.d.ts +2 -2
- package/dist/normalizationVector.js +2 -2
- package/dist/normalizationVector.js.map +1 -1
- package/dist/reader.js +4 -2
- package/dist/reader.js.map +1 -1
- package/dist/types.d.ts +8 -2
- package/esm/bufferedFile.d.ts +2 -2
- package/esm/bufferedFile.js +5 -5
- package/esm/bufferedFile.js.map +1 -1
- package/esm/hicFile.d.ts +9 -10
- package/esm/hicFile.js +167 -174
- package/esm/hicFile.js.map +1 -1
- package/esm/index.d.ts +1 -1
- package/esm/lru.js +0 -2
- package/esm/lru.js.map +1 -1
- package/esm/normalizationVector.d.ts +2 -2
- package/esm/normalizationVector.js +2 -2
- package/esm/normalizationVector.js.map +1 -1
- package/esm/reader.js +4 -2
- package/esm/reader.js.map +1 -1
- package/esm/types.d.ts +8 -2
- package/package.json +11 -8
- package/src/bufferedFile.ts +10 -6
- package/src/hicFile.ts +227 -188
- package/src/index.ts +1 -0
- package/src/lru.ts +0 -2
- package/src/normalizationVector.ts +3 -3
- package/src/reader.ts +5 -3
- package/src/types.ts +13 -2
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@ Read `.hic` contact matrix files, in Node.js or the browser.
|
|
|
8
8
|
A fork of [hic-straw](https://github.com/aidenlab/hic-straw), rewritten in
|
|
9
9
|
TypeScript and retuned for a genome browser's access pattern — many region
|
|
10
10
|
pairs per fetch, arbitrary viewport windows, and contacts handed to a GPU
|
|
11
|
-
renderer. See [docs/optimizations.md](docs/optimizations.md)
|
|
12
|
-
and why.
|
|
11
|
+
renderer. See [docs/optimizations.md](docs/optimizations.md) and
|
|
12
|
+
[docs/correctness.md](docs/correctness.md) for what changed and why.
|
|
13
13
|
|
|
14
14
|
## Install
|
|
15
15
|
|
|
@@ -37,11 +37,11 @@ records.bin2 // Int32Array of bin indices along region2
|
|
|
37
37
|
records.counts // Float32Array of contact counts
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
`(current, total)` as the work lands, so a
|
|
42
|
-
rather than a spinner. The unit is the block for a
|
|
43
|
-
expected-value chunk for the normalization-index walk —
|
|
44
|
-
a pre-v9 file. See [docs/api.md](docs/api.md#progress).
|
|
40
|
+
`getNormalizationOptions()` and `getContactRecords()` both take an optional
|
|
41
|
+
trailing `{ onProgress }`, called `(current, total)` as the work lands, so a
|
|
42
|
+
loading indicator can show a bar rather than a spinner. The unit is the block for a
|
|
43
|
+
contact fetch and the expected-value chunk for the normalization-index walk —
|
|
44
|
+
the slow part of opening a pre-v9 file. See [docs/api.md](docs/api.md#progress).
|
|
45
45
|
|
|
46
46
|
```js
|
|
47
47
|
await hic.getContactRecords('KR', region, region, 'BP', 2_500_000, {
|
|
@@ -49,6 +49,9 @@ await hic.getContactRecords('KR', region, region, 'BP', 2_500_000, {
|
|
|
49
49
|
})
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
Every async method also takes an `AbortSignal` the same way, `{ signal }`, and
|
|
53
|
+
forwards it to each read; see [docs/api.md](docs/api.md#cancellation).
|
|
54
|
+
|
|
52
55
|
In the browser, or for a file over HTTP, pass a `filehandle` from
|
|
53
56
|
[`generic-filehandle2`](https://www.npmjs.com/package/generic-filehandle2)
|
|
54
57
|
instead of a `path`:
|
|
@@ -67,10 +70,10 @@ small blocks scattered through the file — a whole-genome view of the test file
|
|
|
67
70
|
issues over a thousand of them — and a browser runs about six requests per
|
|
68
71
|
origin at a time, so the request count sets the wall clock.
|
|
69
72
|
[`@gmod/range-cache-filehandle`](https://github.com/GMOD/range-cache-filehandle)
|
|
70
|
-
is a drop-in for `RemoteFile` that
|
|
71
|
-
|
|
72
|
-
whole chr1 at 5 kb: **24.0 s and 225 requests becomes 1.8 s
|
|
73
|
-
byte-identical output.
|
|
73
|
+
is a drop-in for `RemoteFile` that serves those reads out of 256 KiB chunks, so
|
|
74
|
+
neighboring blocks share a request. Measured in headless Chrome against a real
|
|
75
|
+
69 GB ENCODE file, whole chr1 at 5 kb: **24.0 s and 225 requests becomes 1.8 s
|
|
76
|
+
and 45**, for byte-identical output.
|
|
74
77
|
|
|
75
78
|
```js
|
|
76
79
|
import { RemoteFileWithRangeCache } from '@gmod/range-cache-filehandle'
|
|
@@ -97,7 +100,7 @@ See [docs/api.md](docs/api.md) for the full API reference.
|
|
|
97
100
|
requested region.
|
|
98
101
|
- A `.hic` stores only the `bin1 <= bin2` half of the matrix, so a query whose x
|
|
99
102
|
window sits right of its y window gets swapped before it goes out;
|
|
100
|
-
`transposed`
|
|
103
|
+
`transposed` marks that swap, and `bin1` then runs along `region2`.
|
|
101
104
|
- `appliedNormalization` names the normalization the file actually applied,
|
|
102
105
|
which is not always the one you asked for — a `.hic` carries normalization
|
|
103
106
|
vectors per (type, chromosome, unit, binsize), so it can offer KR at 5 kb and
|
|
@@ -113,8 +116,10 @@ See [docs/api.md](docs/api.md) for the full API reference.
|
|
|
113
116
|
- [docs/api.md](docs/api.md) — every constructor option, method and return shape
|
|
114
117
|
- [docs/dataflow.md](docs/dataflow.md) — how a fetch flows, and why the path
|
|
115
118
|
forks into two chains
|
|
116
|
-
- [docs/optimizations.md](docs/optimizations.md) —
|
|
117
|
-
|
|
119
|
+
- [docs/optimizations.md](docs/optimizations.md) — performance against
|
|
120
|
+
hic-straw, and what measured it
|
|
121
|
+
- [docs/correctness.md](docs/correctness.md) — parsing differences from
|
|
122
|
+
hic-straw
|
|
118
123
|
- [CONTRIBUTING.md](CONTRIBUTING.md) — development and release steps
|
|
119
124
|
|
|
120
125
|
## Academic use
|
package/dist/bufferedFile.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Reader } from './types.ts';
|
|
1
|
+
import type { BaseOpts, Reader } from './types.ts';
|
|
2
2
|
export default class BufferedFile {
|
|
3
3
|
private file;
|
|
4
4
|
private size;
|
|
@@ -9,5 +9,5 @@ export default class BufferedFile {
|
|
|
9
9
|
file: Reader;
|
|
10
10
|
size?: number;
|
|
11
11
|
});
|
|
12
|
-
read(position: number, length: number): Promise<ArrayBuffer>;
|
|
12
|
+
read(position: number, length: number, opts?: BaseOpts): Promise<ArrayBuffer>;
|
|
13
13
|
}
|
package/dist/bufferedFile.js
CHANGED
|
@@ -16,7 +16,7 @@ class BufferedFile {
|
|
|
16
16
|
this.file = args.file;
|
|
17
17
|
this.size = args.size ?? 64000;
|
|
18
18
|
}
|
|
19
|
-
async read(position, length) {
|
|
19
|
+
async read(position, length, opts) {
|
|
20
20
|
const start = position;
|
|
21
21
|
const end = position + length;
|
|
22
22
|
const bufferStart = this.bufferStart;
|
|
@@ -28,7 +28,7 @@ class BufferedFile {
|
|
|
28
28
|
this.buffer = undefined;
|
|
29
29
|
this.bufferStart = 0;
|
|
30
30
|
this.bufferLength = 0;
|
|
31
|
-
result = await this.file.read(position, length);
|
|
31
|
+
result = await this.file.read(position, length, opts);
|
|
32
32
|
}
|
|
33
33
|
else if (buf && start >= bufferStart && end <= bufferEnd) {
|
|
34
34
|
// Request within buffer bounds
|
|
@@ -38,7 +38,7 @@ class BufferedFile {
|
|
|
38
38
|
else if (buf && start < bufferStart && end > bufferStart) {
|
|
39
39
|
// Overlap left (unexpected in straw); we don't adjust the buffer
|
|
40
40
|
const l1 = bufferStart - start;
|
|
41
|
-
const a1 = await this.file.read(position, l1);
|
|
41
|
+
const a1 = await this.file.read(position, l1, opts);
|
|
42
42
|
const l2 = length - l1;
|
|
43
43
|
if (l2 > 0) {
|
|
44
44
|
result = concatBuffers(a1, buf.slice(0, l2));
|
|
@@ -53,7 +53,7 @@ class BufferedFile {
|
|
|
53
53
|
const a1 = buf.slice(this.bufferLength - l1, this.bufferLength);
|
|
54
54
|
const l2 = length - l1;
|
|
55
55
|
if (l2 > 0) {
|
|
56
|
-
const next = await this.file.read(bufferEnd, this.size);
|
|
56
|
+
const next = await this.file.read(bufferEnd, this.size, opts);
|
|
57
57
|
this.buffer = next;
|
|
58
58
|
this.bufferStart = bufferEnd;
|
|
59
59
|
this.bufferLength = next.byteLength;
|
|
@@ -65,7 +65,7 @@ class BufferedFile {
|
|
|
65
65
|
}
|
|
66
66
|
else {
|
|
67
67
|
// No overlap with buffer
|
|
68
|
-
const next = await this.file.read(position, this.size);
|
|
68
|
+
const next = await this.file.read(position, this.size, opts);
|
|
69
69
|
this.buffer = next;
|
|
70
70
|
this.bufferStart = position;
|
|
71
71
|
this.bufferLength = next.byteLength;
|
package/dist/bufferedFile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bufferedFile.js","sourceRoot":"","sources":["../src/bufferedFile.ts"],"names":[],"mappings":";;AAEA,SAAS,aAAa,CAAC,OAAoB,EAAE,OAAoB;IAC/D,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IACnE,GAAG,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAA;IACnC,GAAG,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;IACpD,OAAO,GAAG,CAAC,MAAM,CAAA;AACnB,CAAC;AAED,MAAqB,YAAY;IACvB,IAAI,CAAQ;IACZ,IAAI,CAAQ;IACZ,WAAW,GAAG,CAAC,CAAA;IACf,YAAY,GAAG,CAAC,CAAA;IAChB,MAAM,CAAyB;IAEvC,YAAY,IAAqC;QAC/C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,CAAA;IAChC,CAAC;IAED,KAAK,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"bufferedFile.js","sourceRoot":"","sources":["../src/bufferedFile.ts"],"names":[],"mappings":"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"}
|
package/dist/hicFile.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import Matrix from './matrix.ts';
|
|
|
2
2
|
import NormalizationVector from './normalizationVector.ts';
|
|
3
3
|
import type { ContactRecords } from './contactRecords.ts';
|
|
4
4
|
import type MatrixZoomData from './matrixZoomData.ts';
|
|
5
|
-
import type { BlockIndexEntry, HicMetadata, HicRegion, ProgressOpts, Reader } from './types.ts';
|
|
5
|
+
import type { BaseOpts, BlockIndexEntry, HicMetadata, HicRegion, ProgressOpts, Reader } from './types.ts';
|
|
6
6
|
import type { GenericFilehandle } from 'generic-filehandle2';
|
|
7
7
|
/**
|
|
8
8
|
* Prefix of the error thrown when a region pair has no matrix at the requested
|
|
@@ -39,19 +39,17 @@ interface Block {
|
|
|
39
39
|
export declare class HicFile {
|
|
40
40
|
private config;
|
|
41
41
|
private file;
|
|
42
|
+
private headerCache;
|
|
43
|
+
private normVectorIndexCache;
|
|
42
44
|
private normVectorCache;
|
|
43
|
-
private normalizationTypes;
|
|
44
45
|
private matrixCache;
|
|
45
46
|
private blockCache;
|
|
46
47
|
private normVectorIndexPosition;
|
|
47
48
|
private normVectorIndexSize;
|
|
48
|
-
private initPromise;
|
|
49
|
-
private normVectorIndexP;
|
|
50
49
|
private version;
|
|
51
50
|
private genomeId;
|
|
52
51
|
private footerPosition;
|
|
53
52
|
normExpectedValueVectorsPosition: number | undefined;
|
|
54
|
-
private normVectorIndex;
|
|
55
53
|
private chromosomes;
|
|
56
54
|
private chromosomeIndexMap;
|
|
57
55
|
private chrAliasTable;
|
|
@@ -59,11 +57,11 @@ export declare class HicFile {
|
|
|
59
57
|
private masterIndex;
|
|
60
58
|
private meta;
|
|
61
59
|
constructor(config: HicConfig);
|
|
62
|
-
init(): Promise<void>;
|
|
63
|
-
getMetaData(): Promise<HicMetadata>;
|
|
60
|
+
init(opts?: BaseOpts): Promise<void>;
|
|
61
|
+
getMetaData(opts?: BaseOpts): Promise<HicMetadata>;
|
|
64
62
|
private readHeaderAndFooter;
|
|
65
63
|
private readFooter;
|
|
66
|
-
getMatrix(chrIdx1: number, chrIdx2: number): Promise<Matrix | undefined>;
|
|
64
|
+
getMatrix(chrIdx1: number, chrIdx2: number, opts?: BaseOpts): Promise<Matrix | undefined>;
|
|
67
65
|
private readMatrix;
|
|
68
66
|
getContactRecords(normalization: string, region1: HicRegion, region2: HicRegion, units: string, binsize: number, opts?: ProgressOpts): Promise<{
|
|
69
67
|
records: ContactRecords;
|
|
@@ -72,7 +70,7 @@ export declare class HicFile {
|
|
|
72
70
|
}>;
|
|
73
71
|
private getNormVectors;
|
|
74
72
|
getBlocks(region1: HicRegion, region2: HicRegion, binSize: number, opts?: ProgressOpts): Promise<(Block | undefined)[]>;
|
|
75
|
-
readBlock(blockNumber: number, zd: MatrixZoomData): Promise<Block | undefined>;
|
|
73
|
+
readBlock(blockNumber: number, zd: MatrixZoomData, opts?: BaseOpts): Promise<Block | undefined>;
|
|
76
74
|
/**
|
|
77
75
|
* Decode one block's records straight into typed arrays.
|
|
78
76
|
*
|
|
@@ -83,9 +81,10 @@ export declare class HicFile {
|
|
|
83
81
|
* of the session, so it is worth one memcpy not to pin an oversized buffer.
|
|
84
82
|
*/
|
|
85
83
|
private parseBlockRecords;
|
|
86
|
-
getNormalizationVector(type: string, chr: string, unit: string, binSize: number): Promise<NormalizationVector | undefined>;
|
|
84
|
+
getNormalizationVector(type: string, chr: string, unit: string, binSize: number, opts?: BaseOpts): Promise<NormalizationVector | undefined>;
|
|
87
85
|
private readNormalizationVector;
|
|
88
86
|
getNormVectorIndex(opts?: ProgressOpts): Promise<Record<string, BlockIndexEntry> | undefined>;
|
|
87
|
+
private getParsedNormVectorIndex;
|
|
89
88
|
private loadNormVectorIndex;
|
|
90
89
|
getNormalizationOptions(opts?: ProgressOpts): Promise<string[]>;
|
|
91
90
|
private readNormVectorIndex;
|