@gmod/bam 5.0.4 → 5.0.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/CHANGELOG.md +4 -8
- package/dist/bai.d.ts +17 -16
- package/dist/bai.js +67 -16
- package/dist/bai.js.map +1 -1
- package/dist/bamFile.d.ts +3 -8
- package/dist/bamFile.js +7 -31
- package/dist/bamFile.js.map +1 -1
- package/dist/chunk.d.ts +4 -4
- package/dist/chunk.js.map +1 -1
- package/dist/csi.d.ts +9 -9
- package/dist/csi.js +52 -45
- package/dist/csi.js.map +1 -1
- package/dist/htsget.d.ts +1 -1
- package/dist/htsget.js +2 -2
- package/dist/htsget.js.map +1 -1
- package/dist/indexFile.d.ts +2 -2
- package/dist/indexFile.js +1 -1
- package/dist/indexFile.js.map +1 -1
- package/dist/long.d.ts +3 -0
- package/dist/long.js +18 -0
- package/dist/long.js.map +1 -0
- package/dist/nullFilehandle.d.ts +6 -0
- package/dist/nullFilehandle.js +18 -0
- package/dist/nullFilehandle.js.map +1 -0
- package/dist/record.js +2 -3
- package/dist/record.js.map +1 -1
- package/dist/util.d.ts +3 -2
- package/dist/util.js +11 -3
- package/dist/util.js.map +1 -1
- package/dist/virtualOffset.d.ts +7 -2
- package/dist/virtualOffset.js +2 -14
- package/dist/virtualOffset.js.map +1 -1
- package/esm/bai.d.ts +17 -16
- package/esm/bai.js +67 -16
- package/esm/bai.js.map +1 -1
- package/esm/bamFile.d.ts +3 -8
- package/esm/bamFile.js +6 -30
- package/esm/bamFile.js.map +1 -1
- package/esm/chunk.d.ts +4 -4
- package/esm/chunk.js.map +1 -1
- package/esm/csi.d.ts +9 -9
- package/esm/csi.js +51 -11
- package/esm/csi.js.map +1 -1
- package/esm/htsget.d.ts +1 -1
- package/esm/htsget.js +2 -2
- package/esm/htsget.js.map +1 -1
- package/esm/indexFile.d.ts +2 -2
- package/esm/indexFile.js +1 -1
- package/esm/indexFile.js.map +1 -1
- package/esm/long.d.ts +3 -0
- package/esm/long.js +14 -0
- package/esm/long.js.map +1 -0
- package/esm/nullFilehandle.d.ts +6 -0
- package/esm/nullFilehandle.js +15 -0
- package/esm/nullFilehandle.js.map +1 -0
- package/esm/record.js +2 -3
- package/esm/record.js.map +1 -1
- package/esm/util.d.ts +3 -2
- package/esm/util.js +10 -3
- package/esm/util.js.map +1 -1
- package/esm/virtualOffset.d.ts +7 -2
- package/esm/virtualOffset.js +1 -14
- package/esm/virtualOffset.js.map +1 -1
- package/package.json +4 -4
- package/src/bai.ts +83 -30
- package/src/bamFile.ts +21 -41
- package/src/chunk.ts +3 -3
- package/src/csi.ts +58 -21
- package/src/htsget.ts +3 -2
- package/src/indexFile.ts +3 -2
- package/src/long.ts +16 -0
- package/src/nullFilehandle.ts +16 -0
- package/src/record.ts +14 -12
- package/src/util.ts +14 -6
- package/src/virtualOffset.ts +15 -22
- package/dist/errors.d.ts +0 -23
- package/dist/errors.js +0 -33
- package/dist/errors.js.map +0 -1
- package/esm/errors.d.ts +0 -23
- package/esm/errors.js +0 -24
- package/esm/errors.js.map +0 -1
- package/src/errors.ts +0 -22
package/src/bamFile.ts
CHANGED
|
@@ -1,50 +1,34 @@
|
|
|
1
|
-
import crc32 from 'crc/calculators/crc32'
|
|
2
|
-
import { unzip, unzipChunkSlice } from '@gmod/bgzf-filehandle'
|
|
3
|
-
import { LocalFile, RemoteFile, GenericFilehandle } from 'generic-filehandle2'
|
|
4
1
|
import AbortablePromiseCache from '@gmod/abortable-promise-cache'
|
|
2
|
+
import { unzip, unzipChunkSlice } from '@gmod/bgzf-filehandle'
|
|
3
|
+
import crc32 from 'crc/calculators/crc32'
|
|
4
|
+
import { LocalFile, RemoteFile } from 'generic-filehandle2'
|
|
5
5
|
import QuickLRU from 'quick-lru'
|
|
6
6
|
|
|
7
|
-
// locals
|
|
8
7
|
import BAI from './bai'
|
|
9
|
-
import CSI from './csi'
|
|
10
8
|
import Chunk from './chunk'
|
|
9
|
+
import CSI from './csi'
|
|
10
|
+
import NullFilehandle from './nullFilehandle'
|
|
11
11
|
import BAMFeature from './record'
|
|
12
12
|
import { parseHeaderText } from './sam'
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
BamOpts,
|
|
15
|
+
BaseOpts,
|
|
16
|
+
checkAbortSignal,
|
|
17
|
+
gen2array,
|
|
18
|
+
makeOpts,
|
|
19
|
+
timeout,
|
|
20
|
+
} from './util'
|
|
21
|
+
|
|
22
|
+
import type { GenericFilehandle } from 'generic-filehandle2'
|
|
14
23
|
|
|
15
24
|
export const BAM_MAGIC = 21840194
|
|
16
25
|
|
|
17
26
|
const blockLen = 1 << 16
|
|
18
|
-
|
|
19
|
-
async function gen2array<T>(gen: AsyncIterable<T[]>): Promise<T[]> {
|
|
20
|
-
let out: T[] = []
|
|
21
|
-
for await (const x of gen) {
|
|
22
|
-
out = out.concat(x)
|
|
23
|
-
}
|
|
24
|
-
return out
|
|
25
|
-
}
|
|
26
|
-
|
|
27
27
|
interface Args {
|
|
28
28
|
chunk: Chunk
|
|
29
29
|
opts: BaseOpts
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
class NullFilehandle {
|
|
33
|
-
public read(): Promise<any> {
|
|
34
|
-
throw new Error('never called')
|
|
35
|
-
}
|
|
36
|
-
public stat(): Promise<any> {
|
|
37
|
-
throw new Error('never called')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
public readFile(): Promise<any> {
|
|
41
|
-
throw new Error('never called')
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
public close(): Promise<any> {
|
|
45
|
-
throw new Error('never called')
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
32
|
export default class BamFile {
|
|
49
33
|
public renameRefSeq: (a: string) => string
|
|
50
34
|
public bam: GenericFilehandle
|
|
@@ -375,14 +359,10 @@ export default class BamFile {
|
|
|
375
359
|
return mateFeatPromises.flat()
|
|
376
360
|
}
|
|
377
361
|
|
|
378
|
-
async _readRegion(position: number, size: number, opts: BaseOpts = {}) {
|
|
379
|
-
return this.bam.read(size, position, opts)
|
|
380
|
-
}
|
|
381
|
-
|
|
382
362
|
async _readChunk({ chunk, opts }: { chunk: Chunk; opts: BaseOpts }) {
|
|
383
|
-
const
|
|
384
|
-
chunk.minv.blockPosition,
|
|
363
|
+
const buf = await this.bam.read(
|
|
385
364
|
chunk.fetchedSize(),
|
|
365
|
+
chunk.minv.blockPosition,
|
|
386
366
|
opts,
|
|
387
367
|
)
|
|
388
368
|
|
|
@@ -390,7 +370,7 @@ export default class BamFile {
|
|
|
390
370
|
buffer: data,
|
|
391
371
|
cpositions,
|
|
392
372
|
dpositions,
|
|
393
|
-
} = await unzipChunkSlice(
|
|
373
|
+
} = await unzipChunkSlice(buf, chunk)
|
|
394
374
|
return { data, cpositions, dpositions, chunk }
|
|
395
375
|
}
|
|
396
376
|
|
|
@@ -413,7 +393,7 @@ export default class BamFile {
|
|
|
413
393
|
// increment position to the current decompressed status
|
|
414
394
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
415
395
|
if (dpositions) {
|
|
416
|
-
while (blockStart + chunk.minv.dataPosition >= dpositions[pos++]) {}
|
|
396
|
+
while (blockStart + chunk.minv.dataPosition >= dpositions[pos++]!) {}
|
|
417
397
|
pos--
|
|
418
398
|
}
|
|
419
399
|
|
|
@@ -447,8 +427,8 @@ export default class BamFile {
|
|
|
447
427
|
// realistically happen
|
|
448
428
|
fileOffset:
|
|
449
429
|
cpositions.length > 0
|
|
450
|
-
? cpositions[pos] * (1 << 8) +
|
|
451
|
-
(blockStart - dpositions[pos]) +
|
|
430
|
+
? cpositions[pos]! * (1 << 8) +
|
|
431
|
+
(blockStart - dpositions[pos]!) +
|
|
452
432
|
chunk.minv.dataPosition +
|
|
453
433
|
1
|
|
454
434
|
: // this shift >>> 0 is equivalent to crc32(b).unsigned but uses the
|
package/src/chunk.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Offset } from './virtualOffset'
|
|
2
2
|
|
|
3
3
|
// little class representing a chunk in the index
|
|
4
4
|
export default class Chunk {
|
|
5
5
|
public buffer?: Uint8Array
|
|
6
6
|
|
|
7
7
|
constructor(
|
|
8
|
-
public minv:
|
|
9
|
-
public maxv:
|
|
8
|
+
public minv: Offset,
|
|
9
|
+
public maxv: Offset,
|
|
10
10
|
public bin: number,
|
|
11
11
|
public _fetchedSize?: number,
|
|
12
12
|
) {}
|
package/src/csi.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { unzip } from '@gmod/bgzf-filehandle'
|
|
2
|
-
import
|
|
2
|
+
import QuickLRU from 'quick-lru'
|
|
3
|
+
|
|
3
4
|
import Chunk from './chunk'
|
|
5
|
+
import IndexFile from './indexFile'
|
|
4
6
|
import {
|
|
5
|
-
|
|
7
|
+
BaseOpts,
|
|
6
8
|
findFirstData,
|
|
7
|
-
|
|
9
|
+
optimizeChunks,
|
|
8
10
|
parseNameBytes,
|
|
9
|
-
|
|
11
|
+
parsePseudoBin,
|
|
10
12
|
} from './util'
|
|
11
|
-
|
|
12
|
-
import IndexFile from './indexFile'
|
|
13
|
+
import { VirtualOffset, fromBytes } from './virtualOffset'
|
|
13
14
|
|
|
14
15
|
const CSI1_MAGIC = 21582659 // CSI\1
|
|
15
16
|
const CSI2_MAGIC = 38359875 // CSI\2
|
|
@@ -30,7 +31,7 @@ export default class CSI extends IndexFile {
|
|
|
30
31
|
|
|
31
32
|
async lineCount(refId: number, opts?: BaseOpts) {
|
|
32
33
|
const indexData = await this.parse(opts)
|
|
33
|
-
return indexData.indices
|
|
34
|
+
return indexData.indices(refId)?.stats?.lineCount || 0
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
async indexCov() {
|
|
@@ -94,20 +95,45 @@ export default class CSI extends IndexFile {
|
|
|
94
95
|
this.minShift = dataView.getInt32(4, true)
|
|
95
96
|
this.depth = dataView.getInt32(8, true)
|
|
96
97
|
this.maxBinNumber = ((1 << ((this.depth + 1) * 3)) - 1) / 7
|
|
98
|
+
const maxBinNumber = this.maxBinNumber
|
|
97
99
|
const auxLength = dataView.getInt32(12, true)
|
|
98
100
|
const aux = auxLength >= 30 ? this.parseAuxData(bytes, 16) : undefined
|
|
99
101
|
const refCount = dataView.getInt32(16 + auxLength, true)
|
|
100
102
|
|
|
101
|
-
type BinIndex = Record<string, Chunk[]>
|
|
102
|
-
|
|
103
103
|
// read the indexes for each reference sequence
|
|
104
104
|
let curr = 16 + auxLength + 4
|
|
105
105
|
let firstDataLine: VirtualOffset | undefined
|
|
106
|
-
const
|
|
107
|
-
binIndex: BinIndex
|
|
108
|
-
stats?: { lineCount: number }
|
|
109
|
-
}>(refCount)
|
|
106
|
+
const offsets = [] as number[]
|
|
110
107
|
for (let i = 0; i < refCount; i++) {
|
|
108
|
+
offsets.push(curr)
|
|
109
|
+
const binCount = dataView.getInt32(curr, true)
|
|
110
|
+
curr += 4
|
|
111
|
+
for (let j = 0; j < binCount; j++) {
|
|
112
|
+
const bin = dataView.getUint32(curr, true)
|
|
113
|
+
curr += 4
|
|
114
|
+
if (bin > this.maxBinNumber) {
|
|
115
|
+
curr += 28 + 16
|
|
116
|
+
} else {
|
|
117
|
+
curr += 8
|
|
118
|
+
const chunkCount = dataView.getInt32(curr, true)
|
|
119
|
+
curr += 4
|
|
120
|
+
for (let k = 0; k < chunkCount; k += 1) {
|
|
121
|
+
curr += 8
|
|
122
|
+
curr += 8
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const indicesCache = new QuickLRU<number, ReturnType<typeof getIndices>>({
|
|
129
|
+
maxSize: 5,
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
function getIndices(refId: number) {
|
|
133
|
+
let curr = offsets[refId]
|
|
134
|
+
if (curr === undefined) {
|
|
135
|
+
return undefined
|
|
136
|
+
}
|
|
111
137
|
// the binning index
|
|
112
138
|
const binCount = dataView.getInt32(curr, true)
|
|
113
139
|
curr += 4
|
|
@@ -116,7 +142,7 @@ export default class CSI extends IndexFile {
|
|
|
116
142
|
for (let j = 0; j < binCount; j++) {
|
|
117
143
|
const bin = dataView.getUint32(curr, true)
|
|
118
144
|
curr += 4
|
|
119
|
-
if (bin >
|
|
145
|
+
if (bin > maxBinNumber) {
|
|
120
146
|
stats = parsePseudoBin(bytes, curr + 28)
|
|
121
147
|
curr += 28 + 16
|
|
122
148
|
} else {
|
|
@@ -137,13 +163,25 @@ export default class CSI extends IndexFile {
|
|
|
137
163
|
}
|
|
138
164
|
}
|
|
139
165
|
|
|
140
|
-
|
|
166
|
+
return {
|
|
167
|
+
binIndex,
|
|
168
|
+
stats,
|
|
169
|
+
}
|
|
141
170
|
}
|
|
142
171
|
|
|
143
172
|
return {
|
|
144
173
|
csiVersion,
|
|
145
174
|
firstDataLine,
|
|
146
|
-
indices
|
|
175
|
+
indices: (refId: number) => {
|
|
176
|
+
if (!indicesCache.has(refId)) {
|
|
177
|
+
const result = getIndices(refId)
|
|
178
|
+
if (result) {
|
|
179
|
+
indicesCache.set(refId, result)
|
|
180
|
+
}
|
|
181
|
+
return result
|
|
182
|
+
}
|
|
183
|
+
return indicesCache.get(refId)
|
|
184
|
+
},
|
|
147
185
|
refCount,
|
|
148
186
|
csi: true,
|
|
149
187
|
maxBlockSize: 1 << 16,
|
|
@@ -162,8 +200,8 @@ export default class CSI extends IndexFile {
|
|
|
162
200
|
}
|
|
163
201
|
|
|
164
202
|
const indexData = await this.parse(opts)
|
|
165
|
-
const ba = indexData.indices
|
|
166
|
-
|
|
203
|
+
const ba = indexData.indices(refId)
|
|
204
|
+
|
|
167
205
|
if (!ba) {
|
|
168
206
|
return []
|
|
169
207
|
}
|
|
@@ -177,9 +215,8 @@ export default class CSI extends IndexFile {
|
|
|
177
215
|
// Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned
|
|
178
216
|
for (const [start, end] of overlappingBins) {
|
|
179
217
|
for (let bin = start; bin <= end; bin++) {
|
|
180
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
181
218
|
if (ba.binIndex[bin]) {
|
|
182
|
-
const binChunks = ba.binIndex[bin]
|
|
219
|
+
const binChunks = ba.binIndex[bin]!
|
|
183
220
|
for (const c of binChunks) {
|
|
184
221
|
chunks.push(c)
|
|
185
222
|
}
|
|
@@ -232,6 +269,6 @@ export default class CSI extends IndexFile {
|
|
|
232
269
|
|
|
233
270
|
async hasRefSeq(seqId: number, opts: BaseOpts = {}) {
|
|
234
271
|
const header = await this.parse(opts)
|
|
235
|
-
return !!header.indices
|
|
272
|
+
return !!header.indices(seqId)?.binIndex
|
|
236
273
|
}
|
|
237
274
|
}
|
package/src/htsget.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { unzip } from '@gmod/bgzf-filehandle'
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import BamFile, { BAM_MAGIC } from './bamFile'
|
|
4
4
|
import Chunk from './chunk'
|
|
5
5
|
import { parseHeaderText } from './sam'
|
|
6
|
+
import { BamOpts, BaseOpts, concatUint8Array } from './util'
|
|
6
7
|
|
|
7
8
|
interface HtsgetChunk {
|
|
8
9
|
url: string
|
|
@@ -22,7 +23,7 @@ async function concat(arr: HtsgetChunk[], opts?: Record<string, any>) {
|
|
|
22
23
|
const ret = await res.arrayBuffer()
|
|
23
24
|
return new Uint8Array(ret)
|
|
24
25
|
} else {
|
|
25
|
-
//remove referer header, it is not even allowed to be specified
|
|
26
|
+
// remove referer header, it is not even allowed to be specified
|
|
26
27
|
// @ts-expect-error
|
|
27
28
|
|
|
28
29
|
const { referer, ...rest } = headers
|
package/src/indexFile.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { GenericFilehandle } from 'generic-filehandle2'
|
|
2
1
|
import Chunk from './chunk'
|
|
3
2
|
import { BaseOpts } from './util'
|
|
4
3
|
|
|
4
|
+
import type { GenericFilehandle } from 'generic-filehandle2'
|
|
5
|
+
|
|
5
6
|
export default abstract class IndexFile {
|
|
6
7
|
public filehandle: GenericFilehandle
|
|
7
8
|
public renameRefSeq: (s: string) => string
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* @param {filehandle} filehandle
|
|
11
|
-
* @param {function}
|
|
12
|
+
* @param {function} renameRefSeqs
|
|
12
13
|
*/
|
|
13
14
|
constructor({
|
|
14
15
|
filehandle,
|
package/src/long.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const TWO_PWR_16_DBL = 1 << 16
|
|
2
|
+
export const TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL
|
|
3
|
+
|
|
4
|
+
export function longFromBytesToUnsigned(source: Uint8Array, i = 0) {
|
|
5
|
+
const low =
|
|
6
|
+
source[i]! |
|
|
7
|
+
(source[i + 1]! << 8) |
|
|
8
|
+
(source[i + 2]! << 16) |
|
|
9
|
+
(source[i + 3]! << 24)
|
|
10
|
+
const high =
|
|
11
|
+
source[i + 4]! |
|
|
12
|
+
(source[i + 5]! << 8) |
|
|
13
|
+
(source[i + 6]! << 16) |
|
|
14
|
+
(source[i + 7]! << 24)
|
|
15
|
+
return (high >>> 0) * TWO_PWR_32_DBL + (low >>> 0)
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export default class NullFilehandle {
|
|
2
|
+
public read(): Promise<any> {
|
|
3
|
+
throw new Error('never called')
|
|
4
|
+
}
|
|
5
|
+
public stat(): Promise<any> {
|
|
6
|
+
throw new Error('never called')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
public readFile(): Promise<any> {
|
|
10
|
+
throw new Error('never called')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public close(): Promise<any> {
|
|
14
|
+
throw new Error('never called')
|
|
15
|
+
}
|
|
16
|
+
}
|
package/src/record.ts
CHANGED
|
@@ -77,7 +77,7 @@ export default class BamRecord {
|
|
|
77
77
|
get name() {
|
|
78
78
|
let str = ''
|
|
79
79
|
for (let i = 0; i < this.read_name_length - 1; i++) {
|
|
80
|
-
str += String.fromCharCode(this.byteArray[this.b0 + i])
|
|
80
|
+
str += String.fromCharCode(this.byteArray[this.b0 + i]!)
|
|
81
81
|
}
|
|
82
82
|
return str
|
|
83
83
|
}
|
|
@@ -93,12 +93,15 @@ export default class BamRecord {
|
|
|
93
93
|
const blockEnd = this.bytes.end
|
|
94
94
|
const tags = {} as Record<string, unknown>
|
|
95
95
|
while (p < blockEnd) {
|
|
96
|
-
const tag = String.fromCharCode(
|
|
97
|
-
|
|
96
|
+
const tag = String.fromCharCode(
|
|
97
|
+
this.byteArray[p]!,
|
|
98
|
+
this.byteArray[p + 1]!,
|
|
99
|
+
)
|
|
100
|
+
const type = String.fromCharCode(this.byteArray[p + 2]!)
|
|
98
101
|
p += 3
|
|
99
102
|
|
|
100
103
|
if (type === 'A') {
|
|
101
|
-
tags[tag] = String.fromCharCode(this.byteArray[p])
|
|
104
|
+
tags[tag] = String.fromCharCode(this.byteArray[p]!)
|
|
102
105
|
p += 1
|
|
103
106
|
} else if (type === 'i') {
|
|
104
107
|
tags[tag] = this.#dataView.getInt32(p, true)
|
|
@@ -124,7 +127,7 @@ export default class BamRecord {
|
|
|
124
127
|
} else if (type === 'Z' || type === 'H') {
|
|
125
128
|
const value = []
|
|
126
129
|
while (p <= blockEnd) {
|
|
127
|
-
const cc = this.byteArray[p++]
|
|
130
|
+
const cc = this.byteArray[p++]!
|
|
128
131
|
if (cc !== 0) {
|
|
129
132
|
value.push(String.fromCharCode(cc))
|
|
130
133
|
} else {
|
|
@@ -133,7 +136,7 @@ export default class BamRecord {
|
|
|
133
136
|
}
|
|
134
137
|
tags[tag] = value.join('')
|
|
135
138
|
} else if (type === 'B') {
|
|
136
|
-
const cc = this.byteArray[p++]
|
|
139
|
+
const cc = this.byteArray[p++]!
|
|
137
140
|
const Btype = String.fromCharCode(cc)
|
|
138
141
|
const limit = this.#dataView.getInt32(p, true)
|
|
139
142
|
p += 4
|
|
@@ -143,7 +146,7 @@ export default class BamRecord {
|
|
|
143
146
|
for (let k = 0; k < limit; k++) {
|
|
144
147
|
const cigop = this.#dataView.getInt32(p, true)
|
|
145
148
|
const lop = cigop >> 4
|
|
146
|
-
const op = CIGAR_DECODER[cigop & 0xf]
|
|
149
|
+
const op = CIGAR_DECODER[cigop & 0xf]!
|
|
147
150
|
value.push(lop + op)
|
|
148
151
|
p += 4
|
|
149
152
|
}
|
|
@@ -162,7 +165,7 @@ export default class BamRecord {
|
|
|
162
165
|
for (let k = 0; k < limit; k++) {
|
|
163
166
|
const cigop = this.#dataView.getUint32(p, true)
|
|
164
167
|
const lop = cigop >> 4
|
|
165
|
-
const op = CIGAR_DECODER[cigop & 0xf]
|
|
168
|
+
const op = CIGAR_DECODER[cigop & 0xf]!
|
|
166
169
|
value.push(lop + op)
|
|
167
170
|
p += 4
|
|
168
171
|
}
|
|
@@ -318,7 +321,7 @@ export default class BamRecord {
|
|
|
318
321
|
for (let c = 0; c < numCigarOps; ++c) {
|
|
319
322
|
cigop = this.#dataView.getInt32(p, true)
|
|
320
323
|
lop = cigop >> 4
|
|
321
|
-
op = CIGAR_DECODER[cigop & 0xf]
|
|
324
|
+
op = CIGAR_DECODER[cigop & 0xf]!
|
|
322
325
|
CIGAR.push(lop + op)
|
|
323
326
|
// soft clip, hard clip, and insertion don't count toward the length on
|
|
324
327
|
// the reference
|
|
@@ -357,14 +360,13 @@ export default class BamRecord {
|
|
|
357
360
|
}
|
|
358
361
|
|
|
359
362
|
get seq() {
|
|
360
|
-
const { byteArray } = this.bytes
|
|
361
363
|
const p = this.b0 + this.read_name_length + this.num_cigar_ops * 4
|
|
362
364
|
const seqBytes = this.num_seq_bytes
|
|
363
365
|
const len = this.seq_length
|
|
364
366
|
const buf = []
|
|
365
367
|
let i = 0
|
|
366
368
|
for (let j = 0; j < seqBytes; ++j) {
|
|
367
|
-
const sb = byteArray[p + j]
|
|
369
|
+
const sb = this.byteArray[p + j]!
|
|
368
370
|
buf.push(SEQRET_DECODER[(sb & 0xf0) >> 4])
|
|
369
371
|
i++
|
|
370
372
|
if (i < len) {
|
|
@@ -442,7 +444,7 @@ export default class BamRecord {
|
|
|
442
444
|
if (k.startsWith('_') || k === 'bytes') {
|
|
443
445
|
continue
|
|
444
446
|
}
|
|
445
|
-
|
|
447
|
+
// @ts-ignore
|
|
446
448
|
data[k] = this[k]
|
|
447
449
|
}
|
|
448
450
|
|
package/src/util.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { fromBytesLE, toNumber } from 'longfn'
|
|
2
1
|
import Chunk from './chunk'
|
|
3
|
-
import
|
|
2
|
+
import { longFromBytesToUnsigned } from './long'
|
|
3
|
+
import { Offset, VirtualOffset } from './virtualOffset'
|
|
4
4
|
|
|
5
5
|
export function timeout(ms: number) {
|
|
6
6
|
return new Promise(resolve => setTimeout(resolve, ms))
|
|
@@ -27,7 +27,7 @@ export function checkAbortSignal(signal?: AbortSignal) {
|
|
|
27
27
|
// console.log('bam aborted!')
|
|
28
28
|
if (typeof DOMException === 'undefined') {
|
|
29
29
|
const e = new Error('aborted')
|
|
30
|
-
|
|
30
|
+
// @ts-ignore
|
|
31
31
|
e.code = 'ERR_ABORTED'
|
|
32
32
|
throw e
|
|
33
33
|
} else {
|
|
@@ -69,7 +69,7 @@ export function makeOpts(obj: AbortSignal | BaseOpts = {}): BaseOpts {
|
|
|
69
69
|
return 'aborted' in obj ? ({ signal: obj } as BaseOpts) : obj
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
export function optimizeChunks(chunks: Chunk[], lowest?:
|
|
72
|
+
export function optimizeChunks(chunks: Chunk[], lowest?: Offset) {
|
|
73
73
|
const mergedChunks: Chunk[] = []
|
|
74
74
|
let lastChunk: Chunk | undefined
|
|
75
75
|
|
|
@@ -105,7 +105,7 @@ export function optimizeChunks(chunks: Chunk[], lowest?: VirtualOffset) {
|
|
|
105
105
|
|
|
106
106
|
export function parsePseudoBin(bytes: Uint8Array, offset: number) {
|
|
107
107
|
return {
|
|
108
|
-
lineCount:
|
|
108
|
+
lineCount: longFromBytesToUnsigned(bytes, offset),
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
@@ -133,7 +133,7 @@ export function parseNameBytes(
|
|
|
133
133
|
if (currNameStart < i) {
|
|
134
134
|
let refName = ''
|
|
135
135
|
for (let j = currNameStart; j < i; j++) {
|
|
136
|
-
refName += String.fromCharCode(namesBytes[j])
|
|
136
|
+
refName += String.fromCharCode(namesBytes[j]!)
|
|
137
137
|
}
|
|
138
138
|
refName = renameRefSeq(refName)
|
|
139
139
|
refIdToName[currRefId] = refName
|
|
@@ -162,3 +162,11 @@ export function concatUint8Array(args: Uint8Array[]) {
|
|
|
162
162
|
}
|
|
163
163
|
return mergedArray
|
|
164
164
|
}
|
|
165
|
+
|
|
166
|
+
export async function gen2array<T>(gen: AsyncIterable<T[]>): Promise<T[]> {
|
|
167
|
+
let out: T[] = []
|
|
168
|
+
for await (const x of gen) {
|
|
169
|
+
out = out.concat(x)
|
|
170
|
+
}
|
|
171
|
+
return out
|
|
172
|
+
}
|
package/src/virtualOffset.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface Offset {
|
|
2
|
+
blockPosition: number
|
|
3
|
+
dataPosition: number
|
|
4
|
+
toString(): string
|
|
5
|
+
compareTo(arg: Offset): number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class VirtualOffset {
|
|
2
9
|
public blockPosition: number
|
|
3
10
|
public dataPosition: number
|
|
4
11
|
constructor(blockPosition: number, dataPosition: number) {
|
|
@@ -15,20 +22,6 @@ export default class VirtualOffset {
|
|
|
15
22
|
this.blockPosition - b.blockPosition || this.dataPosition - b.dataPosition
|
|
16
23
|
)
|
|
17
24
|
}
|
|
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
25
|
}
|
|
33
26
|
export function fromBytes(bytes: Uint8Array, offset = 0, bigendian = false) {
|
|
34
27
|
if (bigendian) {
|
|
@@ -36,12 +29,12 @@ export function fromBytes(bytes: Uint8Array, offset = 0, bigendian = false) {
|
|
|
36
29
|
}
|
|
37
30
|
|
|
38
31
|
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]
|
|
32
|
+
bytes[offset + 7]! * 0x10000000000 +
|
|
33
|
+
bytes[offset + 6]! * 0x100000000 +
|
|
34
|
+
bytes[offset + 5]! * 0x1000000 +
|
|
35
|
+
bytes[offset + 4]! * 0x10000 +
|
|
36
|
+
bytes[offset + 3]! * 0x100 +
|
|
37
|
+
bytes[offset + 2]!,
|
|
38
|
+
(bytes[offset + 1]! << 8) | bytes[offset]!,
|
|
46
39
|
)
|
|
47
40
|
}
|
package/dist/errors.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export declare class BamError extends Error {
|
|
2
|
-
}
|
|
3
|
-
/** Error caused by encountering a part of the BAM spec that has not yet been implemented */
|
|
4
|
-
export declare class BamUnimplementedError extends Error {
|
|
5
|
-
}
|
|
6
|
-
/** An error caused by malformed data. */
|
|
7
|
-
export declare class BamMalformedError extends BamError {
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* An error caused by attempting to read beyond the end of the defined data.
|
|
11
|
-
*/
|
|
12
|
-
export declare class BamBufferOverrunError extends BamMalformedError {
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* An error caused by data being too big, exceeding a size limit.
|
|
16
|
-
*/
|
|
17
|
-
export declare class BamSizeLimitError extends BamError {
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* An invalid argument was supplied to a bam-js method or object.
|
|
21
|
-
*/
|
|
22
|
-
export declare class BamArgumentError extends BamError {
|
|
23
|
-
}
|
package/dist/errors.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BamArgumentError = exports.BamSizeLimitError = exports.BamBufferOverrunError = exports.BamMalformedError = exports.BamUnimplementedError = exports.BamError = void 0;
|
|
4
|
-
class BamError extends Error {
|
|
5
|
-
}
|
|
6
|
-
exports.BamError = BamError;
|
|
7
|
-
/** Error caused by encountering a part of the BAM spec that has not yet been implemented */
|
|
8
|
-
class BamUnimplementedError extends Error {
|
|
9
|
-
}
|
|
10
|
-
exports.BamUnimplementedError = BamUnimplementedError;
|
|
11
|
-
/** An error caused by malformed data. */
|
|
12
|
-
class BamMalformedError extends BamError {
|
|
13
|
-
}
|
|
14
|
-
exports.BamMalformedError = BamMalformedError;
|
|
15
|
-
/**
|
|
16
|
-
* An error caused by attempting to read beyond the end of the defined data.
|
|
17
|
-
*/
|
|
18
|
-
class BamBufferOverrunError extends BamMalformedError {
|
|
19
|
-
}
|
|
20
|
-
exports.BamBufferOverrunError = BamBufferOverrunError;
|
|
21
|
-
/**
|
|
22
|
-
* An error caused by data being too big, exceeding a size limit.
|
|
23
|
-
*/
|
|
24
|
-
class BamSizeLimitError extends BamError {
|
|
25
|
-
}
|
|
26
|
-
exports.BamSizeLimitError = BamSizeLimitError;
|
|
27
|
-
/**
|
|
28
|
-
* An invalid argument was supplied to a bam-js method or object.
|
|
29
|
-
*/
|
|
30
|
-
class BamArgumentError extends BamError {
|
|
31
|
-
}
|
|
32
|
-
exports.BamArgumentError = BamArgumentError;
|
|
33
|
-
//# sourceMappingURL=errors.js.map
|
package/dist/errors.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA,MAAa,QAAS,SAAQ,KAAK;CAAG;AAAtC,4BAAsC;AAEtC,4FAA4F;AAC5F,MAAa,qBAAsB,SAAQ,KAAK;CAAG;AAAnD,sDAAmD;AAEnD,0CAA0C;AAC1C,MAAa,iBAAkB,SAAQ,QAAQ;CAAG;AAAlD,8CAAkD;AAElD;;GAEG;AACH,MAAa,qBAAsB,SAAQ,iBAAiB;CAAG;AAA/D,sDAA+D;AAE/D;;GAEG;AACH,MAAa,iBAAkB,SAAQ,QAAQ;CAAG;AAAlD,8CAAkD;AAElD;;GAEG;AACH,MAAa,gBAAiB,SAAQ,QAAQ;CAAG;AAAjD,4CAAiD"}
|
package/esm/errors.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export declare class BamError extends Error {
|
|
2
|
-
}
|
|
3
|
-
/** Error caused by encountering a part of the BAM spec that has not yet been implemented */
|
|
4
|
-
export declare class BamUnimplementedError extends Error {
|
|
5
|
-
}
|
|
6
|
-
/** An error caused by malformed data. */
|
|
7
|
-
export declare class BamMalformedError extends BamError {
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* An error caused by attempting to read beyond the end of the defined data.
|
|
11
|
-
*/
|
|
12
|
-
export declare class BamBufferOverrunError extends BamMalformedError {
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* An error caused by data being too big, exceeding a size limit.
|
|
16
|
-
*/
|
|
17
|
-
export declare class BamSizeLimitError extends BamError {
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* An invalid argument was supplied to a bam-js method or object.
|
|
21
|
-
*/
|
|
22
|
-
export declare class BamArgumentError extends BamError {
|
|
23
|
-
}
|
package/esm/errors.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export class BamError extends Error {
|
|
2
|
-
}
|
|
3
|
-
/** Error caused by encountering a part of the BAM spec that has not yet been implemented */
|
|
4
|
-
export class BamUnimplementedError extends Error {
|
|
5
|
-
}
|
|
6
|
-
/** An error caused by malformed data. */
|
|
7
|
-
export class BamMalformedError extends BamError {
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* An error caused by attempting to read beyond the end of the defined data.
|
|
11
|
-
*/
|
|
12
|
-
export class BamBufferOverrunError extends BamMalformedError {
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* An error caused by data being too big, exceeding a size limit.
|
|
16
|
-
*/
|
|
17
|
-
export class BamSizeLimitError extends BamError {
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* An invalid argument was supplied to a bam-js method or object.
|
|
21
|
-
*/
|
|
22
|
-
export class BamArgumentError extends BamError {
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=errors.js.map
|
package/esm/errors.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAS,SAAQ,KAAK;CAAG;AAEtC,4FAA4F;AAC5F,MAAM,OAAO,qBAAsB,SAAQ,KAAK;CAAG;AAEnD,0CAA0C;AAC1C,MAAM,OAAO,iBAAkB,SAAQ,QAAQ;CAAG;AAElD;;GAEG;AACH,MAAM,OAAO,qBAAsB,SAAQ,iBAAiB;CAAG;AAE/D;;GAEG;AACH,MAAM,OAAO,iBAAkB,SAAQ,QAAQ;CAAG;AAElD;;GAEG;AACH,MAAM,OAAO,gBAAiB,SAAQ,QAAQ;CAAG"}
|