@gmod/bam 1.1.13 → 1.1.16
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/CHANGELOG.md +16 -1
- package/dist/bamFile.d.ts +3 -2
- package/dist/bamFile.js +209 -224
- package/dist/bamFile.js.map +1 -1
- package/dist/csi.js +5 -1
- package/dist/csi.js.map +1 -1
- package/dist/htsget.js +5 -1
- package/dist/htsget.js.map +1 -1
- package/dist/record.js +20 -19
- package/dist/record.js.map +1 -1
- package/esm/bamFile.d.ts +3 -2
- package/esm/bamFile.js +76 -87
- package/esm/bamFile.js.map +1 -1
- package/esm/record.js +19 -18
- package/esm/record.js.map +1 -1
- package/package.json +12 -8
- package/src/bai.ts +227 -0
- package/src/bamFile.ts +546 -0
- package/src/chunk.ts +52 -0
- package/src/constants.ts +26 -0
- package/src/csi.ts +246 -0
- package/src/declare.d.ts +2 -0
- package/src/errors.ts +22 -0
- package/src/htsget.ts +138 -0
- package/src/index.ts +7 -0
- package/src/indexFile.ts +63 -0
- package/src/record.ts +610 -0
- package/src/sam.ts +15 -0
- package/src/util.ts +116 -0
- package/src/virtualOffset.ts +47 -0
package/src/util.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import Chunk from './chunk'
|
|
2
|
+
import VirtualOffset from './virtualOffset'
|
|
3
|
+
|
|
4
|
+
export function timeout(ms: number) {
|
|
5
|
+
return new Promise(resolve => setTimeout(resolve, ms))
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function longToNumber(long: Long) {
|
|
9
|
+
if (
|
|
10
|
+
long.greaterThan(Number.MAX_SAFE_INTEGER) ||
|
|
11
|
+
long.lessThan(Number.MIN_SAFE_INTEGER)
|
|
12
|
+
) {
|
|
13
|
+
throw new Error('integer overflow')
|
|
14
|
+
}
|
|
15
|
+
return long.toNumber()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Properly check if the given AbortSignal is aborted.
|
|
20
|
+
* Per the standard, if the signal reads as aborted,
|
|
21
|
+
* this function throws either a DOMException AbortError, or a regular error
|
|
22
|
+
* with a `code` attribute set to `ERR_ABORTED`.
|
|
23
|
+
*
|
|
24
|
+
* For convenience, passing `undefined` is a no-op
|
|
25
|
+
*
|
|
26
|
+
* @param {AbortSignal} [signal] an AbortSignal, or anything with an `aborted` attribute
|
|
27
|
+
* @returns nothing
|
|
28
|
+
*/
|
|
29
|
+
export function checkAbortSignal(signal?: AbortSignal) {
|
|
30
|
+
if (!signal) {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (signal.aborted) {
|
|
35
|
+
// console.log('bam aborted!')
|
|
36
|
+
if (typeof DOMException !== 'undefined') {
|
|
37
|
+
throw new DOMException('aborted', 'AbortError')
|
|
38
|
+
} else {
|
|
39
|
+
const e = new Error('aborted')
|
|
40
|
+
//@ts-ignore
|
|
41
|
+
e.code = 'ERR_ABORTED'
|
|
42
|
+
throw e
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Skips to the next tick, then runs `checkAbortSignal`.
|
|
49
|
+
* Await this to inside an otherwise synchronous loop to
|
|
50
|
+
* provide a place to break when an abort signal is received.
|
|
51
|
+
* @param {AbortSignal} signal
|
|
52
|
+
*/
|
|
53
|
+
export async function abortBreakPoint(signal?: AbortSignal) {
|
|
54
|
+
await Promise.resolve()
|
|
55
|
+
checkAbortSignal(signal)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function canMergeBlocks(chunk1: Chunk, chunk2: Chunk) {
|
|
59
|
+
return (
|
|
60
|
+
chunk2.minv.blockPosition - chunk1.maxv.blockPosition < 65000 &&
|
|
61
|
+
chunk2.maxv.blockPosition - chunk1.minv.blockPosition < 5000000
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface BamOpts {
|
|
66
|
+
viewAsPairs?: boolean
|
|
67
|
+
pairAcrossChr?: boolean
|
|
68
|
+
maxInsertSize?: number
|
|
69
|
+
signal?: AbortSignal
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface BaseOpts {
|
|
73
|
+
signal?: AbortSignal
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function makeOpts(obj: AbortSignal | BaseOpts = {}): BaseOpts {
|
|
77
|
+
return 'aborted' in obj ? ({ signal: obj } as BaseOpts) : (obj as BaseOpts)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function optimizeChunks(chunks: Chunk[], lowest: VirtualOffset) {
|
|
81
|
+
const mergedChunks: Chunk[] = []
|
|
82
|
+
let lastChunk: Chunk | null = null
|
|
83
|
+
|
|
84
|
+
if (chunks.length === 0) {
|
|
85
|
+
return chunks
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
chunks.sort((c0, c1) => {
|
|
89
|
+
const dif = c0.minv.blockPosition - c1.minv.blockPosition
|
|
90
|
+
if (dif !== 0) {
|
|
91
|
+
return dif
|
|
92
|
+
} else {
|
|
93
|
+
return c0.minv.dataPosition - c1.minv.dataPosition
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
chunks.forEach(chunk => {
|
|
98
|
+
if (!lowest || chunk.maxv.compareTo(lowest) > 0) {
|
|
99
|
+
if (lastChunk === null) {
|
|
100
|
+
mergedChunks.push(chunk)
|
|
101
|
+
lastChunk = chunk
|
|
102
|
+
} else {
|
|
103
|
+
if (canMergeBlocks(lastChunk, chunk)) {
|
|
104
|
+
if (chunk.maxv.compareTo(lastChunk.maxv) > 0) {
|
|
105
|
+
lastChunk.maxv = chunk.maxv
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
mergedChunks.push(chunk)
|
|
109
|
+
lastChunk = chunk
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
return mergedChunks
|
|
116
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export default class VirtualOffset {
|
|
2
|
+
public blockPosition: number
|
|
3
|
+
public dataPosition: number
|
|
4
|
+
constructor(blockPosition: number, dataPosition: number) {
|
|
5
|
+
this.blockPosition = blockPosition // < offset of the compressed data block
|
|
6
|
+
this.dataPosition = dataPosition // < offset into the uncompressed data
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
toString() {
|
|
10
|
+
return `${this.blockPosition}:${this.dataPosition}`
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
compareTo(b: VirtualOffset) {
|
|
14
|
+
return (
|
|
15
|
+
this.blockPosition - b.blockPosition || this.dataPosition - b.dataPosition
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static min(...args: VirtualOffset[]) {
|
|
20
|
+
let min
|
|
21
|
+
let i = 0
|
|
22
|
+
for (; !min; i += 1) {
|
|
23
|
+
min = args[i]
|
|
24
|
+
}
|
|
25
|
+
for (; i < args.length; i += 1) {
|
|
26
|
+
if (min.compareTo(args[i]) > 0) {
|
|
27
|
+
min = args[i]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return min
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function fromBytes(bytes: Buffer, offset = 0, bigendian = false) {
|
|
34
|
+
if (bigendian) {
|
|
35
|
+
throw new Error('big-endian virtual file offsets not implemented')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return new VirtualOffset(
|
|
39
|
+
bytes[offset + 7] * 0x10000000000 +
|
|
40
|
+
bytes[offset + 6] * 0x100000000 +
|
|
41
|
+
bytes[offset + 5] * 0x1000000 +
|
|
42
|
+
bytes[offset + 4] * 0x10000 +
|
|
43
|
+
bytes[offset + 3] * 0x100 +
|
|
44
|
+
bytes[offset + 2],
|
|
45
|
+
(bytes[offset + 1] << 8) | bytes[offset],
|
|
46
|
+
)
|
|
47
|
+
}
|