@gmod/bbi 4.0.3 → 4.0.5
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 +12 -4
- package/README.md +3 -2
- package/dist/bbi.d.ts +3 -6
- package/dist/bbi.js +7 -8
- package/dist/bbi.js.map +1 -1
- package/dist/bigbed.js +13 -13
- package/dist/bigbed.js.map +1 -1
- package/dist/bigwig.d.ts +3 -1
- package/dist/bigwig.js +3 -1
- package/dist/bigwig.js.map +1 -1
- package/dist/block-view.js +13 -8
- package/dist/block-view.js.map +1 -1
- package/dist/range.d.ts +8 -7
- package/dist/range.js +30 -89
- package/dist/range.js.map +1 -1
- package/esm/bbi.d.ts +3 -6
- package/esm/bbi.js +5 -6
- package/esm/bbi.js.map +1 -1
- package/esm/bigbed.js +9 -9
- package/esm/bigbed.js.map +1 -1
- package/esm/bigwig.d.ts +3 -1
- package/esm/bigwig.js +3 -1
- package/esm/bigwig.js.map +1 -1
- package/esm/block-view.js +14 -6
- package/esm/block-view.js.map +1 -1
- package/esm/range.d.ts +8 -7
- package/esm/range.js +29 -88
- package/esm/range.js.map +1 -1
- package/package.json +11 -11
- package/src/bbi.ts +13 -12
- package/src/bigbed.ts +9 -9
- package/src/bigwig.ts +3 -1
- package/src/block-view.ts +14 -6
- package/src/range.ts +35 -101
package/src/bigbed.ts
CHANGED
|
@@ -174,18 +174,17 @@ export class BigBed extends BBI {
|
|
|
174
174
|
const node = bpt.parse(buffer)
|
|
175
175
|
if (node.leafkeys) {
|
|
176
176
|
let lastOffset
|
|
177
|
-
for (
|
|
178
|
-
const { key } = node.leafkeys[i]
|
|
177
|
+
for (const { key, offset } of node.leafkeys) {
|
|
179
178
|
if (name.localeCompare(key) < 0 && lastOffset) {
|
|
180
179
|
return bptReadNode(lastOffset)
|
|
181
180
|
}
|
|
182
|
-
lastOffset =
|
|
181
|
+
lastOffset = offset
|
|
183
182
|
}
|
|
184
183
|
return bptReadNode(lastOffset)
|
|
185
184
|
}
|
|
186
|
-
for (
|
|
187
|
-
if (
|
|
188
|
-
return { ...
|
|
185
|
+
for (const n of node.keys) {
|
|
186
|
+
if (n.key === name) {
|
|
187
|
+
return { ...n, field }
|
|
189
188
|
}
|
|
190
189
|
}
|
|
191
190
|
|
|
@@ -198,8 +197,9 @@ export class BigBed extends BBI {
|
|
|
198
197
|
}
|
|
199
198
|
|
|
200
199
|
/*
|
|
201
|
-
* retrieve the features from the bigbed data that were found through the
|
|
202
|
-
* note that there can be multiple extraIndex, see
|
|
200
|
+
* retrieve the features from the bigbed data that were found through the
|
|
201
|
+
* lookup of the extraIndex note that there can be multiple extraIndex, see
|
|
202
|
+
* the BigBed specification and the -extraIndex argument to bedToBigBed
|
|
203
203
|
*
|
|
204
204
|
* @param name - the name to search for
|
|
205
205
|
* @param opts - a SearchOptions argument with optional signal
|
|
@@ -213,7 +213,7 @@ export class BigBed extends BBI {
|
|
|
213
213
|
const view = await this.getUnzoomedView(opts)
|
|
214
214
|
const res = blocks.map(block => {
|
|
215
215
|
return new Observable<Feature[]>(observer => {
|
|
216
|
-
view.readFeatures(observer, [block], opts)
|
|
216
|
+
view.readFeatures(observer, [block], opts).catch(e => observer.error(e))
|
|
217
217
|
}).pipe(
|
|
218
218
|
reduce((acc, curr) => acc.concat(curr)),
|
|
219
219
|
map(x => {
|
package/src/bigwig.ts
CHANGED
|
@@ -6,7 +6,9 @@ export class BigWig extends BBI {
|
|
|
6
6
|
* Retrieves a BlockView of a specific zoomLevel
|
|
7
7
|
*
|
|
8
8
|
* @param scale - number
|
|
9
|
-
*
|
|
9
|
+
*
|
|
10
|
+
* @param opts - An object containing basesPerSpan (e.g. pixels per basepair)
|
|
11
|
+
* or scale used to infer the zoomLevel to use
|
|
10
12
|
*/
|
|
11
13
|
protected async getView(scale: number, opts: RequestOptions) {
|
|
12
14
|
const { zoomLevels, refsByName, fileSize, isBigEndian, uncompressBufSize } =
|
package/src/block-view.ts
CHANGED
|
@@ -235,7 +235,7 @@ export class BlockView {
|
|
|
235
235
|
blocksToFetch = blocksToFetch.concat(
|
|
236
236
|
p.blocksToFetch
|
|
237
237
|
.filter(f => filterFeats(f))
|
|
238
|
-
.map(
|
|
238
|
+
.map(l => ({
|
|
239
239
|
offset: l.blockOffset,
|
|
240
240
|
length: l.blockSize,
|
|
241
241
|
})),
|
|
@@ -268,8 +268,8 @@ export class BlockView {
|
|
|
268
268
|
level: number,
|
|
269
269
|
) => {
|
|
270
270
|
try {
|
|
271
|
-
const length = fr.max
|
|
272
|
-
const offset = fr.min
|
|
271
|
+
const length = fr.max - fr.min
|
|
272
|
+
const offset = fr.min
|
|
273
273
|
const resultBuffer: Buffer = await this.featureCache.get(
|
|
274
274
|
`${length}_${offset}`,
|
|
275
275
|
{ length, offset },
|
|
@@ -280,7 +280,10 @@ export class BlockView {
|
|
|
280
280
|
cirFobRecur2(resultBuffer, element - offset, level)
|
|
281
281
|
outstanding -= 1
|
|
282
282
|
if (outstanding === 0) {
|
|
283
|
-
this.readFeatures(observer, blocksToFetch, {
|
|
283
|
+
this.readFeatures(observer, blocksToFetch, {
|
|
284
|
+
...opts,
|
|
285
|
+
request,
|
|
286
|
+
}).catch(e => observer.error(e))
|
|
284
287
|
}
|
|
285
288
|
}
|
|
286
289
|
}
|
|
@@ -294,11 +297,16 @@ export class BlockView {
|
|
|
294
297
|
|
|
295
298
|
// Upper bound on size, based on a completely full leaf node.
|
|
296
299
|
const maxCirBlockSpan = 4 + Number(cirBlockSize) * 32
|
|
297
|
-
let spans = new Range(
|
|
300
|
+
let spans = new Range([
|
|
301
|
+
{ min: offset[0], max: offset[0] + maxCirBlockSpan },
|
|
302
|
+
])
|
|
298
303
|
for (let i = 1; i < offset.length; i += 1) {
|
|
299
|
-
const blockSpan = new Range(
|
|
304
|
+
const blockSpan = new Range([
|
|
305
|
+
{ min: offset[i], max: offset[i] + maxCirBlockSpan },
|
|
306
|
+
])
|
|
300
307
|
spans = spans.union(blockSpan)
|
|
301
308
|
}
|
|
309
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
302
310
|
spans.getRanges().map(fr => cirFobStartFetch(offset, fr, level))
|
|
303
311
|
} catch (e) {
|
|
304
312
|
observer.error(e)
|
package/src/range.ts
CHANGED
|
@@ -1,32 +1,29 @@
|
|
|
1
|
-
/* eslint prefer-rest-params:0, no-nested-ternary:0 */
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Adapted from a combination of Range and _Compound in the
|
|
5
3
|
* Dalliance Genome Explorer, (c) Thomas Down 2006-2010.
|
|
6
4
|
*/
|
|
5
|
+
|
|
6
|
+
export interface IRange {
|
|
7
|
+
min: number
|
|
8
|
+
max: number
|
|
9
|
+
}
|
|
7
10
|
export default class Range {
|
|
8
|
-
public ranges:
|
|
11
|
+
public ranges: IRange[]
|
|
9
12
|
|
|
10
|
-
public constructor(arg1:
|
|
11
|
-
this.ranges =
|
|
12
|
-
arguments.length === 2
|
|
13
|
-
? [{ min: arg1, max: arg2 }]
|
|
14
|
-
: 0 in arg1
|
|
15
|
-
? Object.assign({}, arg1)
|
|
16
|
-
: [arg1]
|
|
13
|
+
public constructor(arg1: IRange[]) {
|
|
14
|
+
this.ranges = arg1
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
get min() {
|
|
20
18
|
return this.ranges[0].min
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
get max() {
|
|
24
22
|
return this.ranges[this.ranges.length - 1].max
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
public contains(pos: number)
|
|
28
|
-
for (
|
|
29
|
-
const r = this.ranges[s]
|
|
25
|
+
public contains(pos: number) {
|
|
26
|
+
for (const r of this.ranges) {
|
|
30
27
|
if (r.min <= pos && r.max >= pos) {
|
|
31
28
|
return true
|
|
32
29
|
}
|
|
@@ -38,104 +35,41 @@ export default class Range {
|
|
|
38
35
|
return this.ranges.length > 1
|
|
39
36
|
}
|
|
40
37
|
|
|
41
|
-
public getRanges()
|
|
42
|
-
return this.ranges.map(
|
|
38
|
+
public getRanges() {
|
|
39
|
+
return this.ranges.map(r => new Range([{ min: r.min, max: r.max }]))
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
public toString(): string {
|
|
46
|
-
return this.ranges.map(
|
|
43
|
+
return this.ranges.map(r => `[${r.min}-${r.max}]`).join(',')
|
|
47
44
|
}
|
|
48
45
|
|
|
49
|
-
public union(s1: Range)
|
|
50
|
-
const ranges = this.getRanges()
|
|
51
|
-
|
|
46
|
+
public union(s1: Range) {
|
|
47
|
+
const ranges = [...this.getRanges(), ...s1.getRanges()].sort((a, b) => {
|
|
48
|
+
if (a.min < b.min) {
|
|
49
|
+
return -1
|
|
50
|
+
} else if (a.min > b.min) {
|
|
51
|
+
return 1
|
|
52
|
+
} else if (a.max < b.max) {
|
|
53
|
+
return -1
|
|
54
|
+
} else if (b.max > a.max) {
|
|
55
|
+
return 1
|
|
56
|
+
} else {
|
|
57
|
+
return 0
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
const oranges = [] as Range[]
|
|
52
61
|
let current = ranges[0]
|
|
53
62
|
|
|
54
|
-
for (
|
|
55
|
-
|
|
56
|
-
if (nxt.min() > current.max() + 1) {
|
|
63
|
+
for (const nxt of ranges) {
|
|
64
|
+
if (nxt.min > current.max + 1) {
|
|
57
65
|
oranges.push(current)
|
|
58
66
|
current = nxt
|
|
59
|
-
} else if (nxt.max
|
|
60
|
-
current = new Range(current.min
|
|
67
|
+
} else if (nxt.max > current.max) {
|
|
68
|
+
current = new Range([{ min: current.min, max: nxt.max }])
|
|
61
69
|
}
|
|
62
70
|
}
|
|
63
71
|
oranges.push(current)
|
|
64
72
|
|
|
65
|
-
|
|
66
|
-
return oranges[0]
|
|
67
|
-
}
|
|
68
|
-
return new Range(oranges)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
public intersection(arg: Range): Range {
|
|
72
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias,unicorn/no-this-assignment
|
|
73
|
-
let s0 = this
|
|
74
|
-
let s1 = arg
|
|
75
|
-
const r0 = this.ranges()
|
|
76
|
-
const r1 = s1.ranges()
|
|
77
|
-
const l0 = r0.length
|
|
78
|
-
|
|
79
|
-
const l1 = r1.length
|
|
80
|
-
let i0 = 0
|
|
81
|
-
|
|
82
|
-
let i1 = 0
|
|
83
|
-
const or = []
|
|
84
|
-
|
|
85
|
-
while (i0 < l0 && i1 < l1) {
|
|
86
|
-
s0 = r0[i0]
|
|
87
|
-
s1 = r1[i1]
|
|
88
|
-
const lapMin = Math.max(s0.min(), s1.min())
|
|
89
|
-
const lapMax = Math.min(s0.max(), s1.max())
|
|
90
|
-
if (lapMax >= lapMin) {
|
|
91
|
-
or.push(new Range(lapMin, lapMax))
|
|
92
|
-
}
|
|
93
|
-
if (s0.max() > s1.max()) {
|
|
94
|
-
i1 += 1
|
|
95
|
-
} else {
|
|
96
|
-
i0 += 1
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (or.length === 0) {
|
|
101
|
-
throw new Error('found range of length 0')
|
|
102
|
-
}
|
|
103
|
-
if (or.length === 1) {
|
|
104
|
-
return or[0]
|
|
105
|
-
}
|
|
106
|
-
return new Range(or)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
public coverage(): number {
|
|
110
|
-
let tot = 0
|
|
111
|
-
const rl = this.ranges()
|
|
112
|
-
for (const r of rl) {
|
|
113
|
-
tot += r.max() - r.min() + 1
|
|
114
|
-
}
|
|
115
|
-
return tot
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
public rangeOrder(tmpa: Range, tmpb: Range): number {
|
|
119
|
-
let a = tmpa
|
|
120
|
-
let b = tmpb
|
|
121
|
-
if (arguments.length < 2) {
|
|
122
|
-
b = a
|
|
123
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias,unicorn/no-this-assignment
|
|
124
|
-
a = this
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (a.min() < b.min()) {
|
|
128
|
-
return -1
|
|
129
|
-
}
|
|
130
|
-
if (a.min() > b.min()) {
|
|
131
|
-
return 1
|
|
132
|
-
}
|
|
133
|
-
if (a.max() < b.max()) {
|
|
134
|
-
return -1
|
|
135
|
-
}
|
|
136
|
-
if (b.max() > a.max()) {
|
|
137
|
-
return 1
|
|
138
|
-
}
|
|
139
|
-
return 0
|
|
73
|
+
return oranges.length === 1 ? oranges[0] : new Range(oranges)
|
|
140
74
|
}
|
|
141
75
|
}
|