Skip to content

Commit 680a93c

Browse files
committed
Fix bigBed zooms with overlapping regions
1 parent 5244c1d commit 680a93c

3 files changed

Lines changed: 33 additions & 11 deletions

File tree

bigtools/src/bbi/bbiwrite.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,7 @@ pub(crate) fn write_vals<
769769
.take(options.max_zooms as usize)
770770
.collect(),
771771
};
772+
let zoom_sizes: Vec<u32> = zoom_sizes.into_iter().filter(|z| *z != 0).collect();
772773
let zooms_map: BTreeMap<u32, ZoomValue> = zoom_sizes.iter().copied().map(make_zoom).collect();
773774

774775
let mut chrom_ids = IdMap::default();

bigtools/src/bbi/bigbedwrite.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -439,17 +439,32 @@ async fn process_val_zoom(
439439
}
440440
}
441441

442+
// At this point, if there is are any items in the list, the end of the
443+
// last item must overlap or come up to the current item start
442444
debug_assert!(overlap
443445
.get_last()
444446
.map(|o| o.end >= item_start)
445447
.unwrap_or(true));
446448

447-
if overlap.get_last().map(|o| o.end).unwrap_or(item_start) == item_start {
448-
overlap.insert_last(Value {
449-
start: item_start,
450-
end: item_end,
451-
value: 1.0,
452-
});
449+
// If the current item extends past the last item (or if there are no
450+
// previous items), we must add one
451+
match overlap.get_last() {
452+
Some(o) => {
453+
if o.end < item_end {
454+
overlap.insert_last(Value {
455+
start: o.end,
456+
end: item_end,
457+
value: 1.0,
458+
});
459+
}
460+
}
461+
None => {
462+
overlap.insert_last(Value {
463+
start: item_start,
464+
end: item_end,
465+
value: 1.0,
466+
});
467+
}
453468
}
454469

455470
let next_start = next_val.map(|v| v.start).unwrap_or(u32::max_value());

bigtools/src/utils/cli/bigbedtobed.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ pub fn write_bed_singlethreaded<R: Reopen + SeekableRead>(
114114
let chroms: Vec<ChromInfo> = if let Some(arg_chrom) = chrom {
115115
let chrom = bigbed.chroms().iter().find(|c| c.name == arg_chrom);
116116
let Some(chrom) = chrom else {
117-
eprintln!("{arg_chrom} not found in file.");
117+
eprintln!("Error: {arg_chrom} not found in file.");
118118
return Ok(());
119119
};
120120
vec![chrom.clone()]
@@ -124,13 +124,19 @@ pub fn write_bed_singlethreaded<R: Reopen + SeekableRead>(
124124
let mut writer = io::BufWriter::with_capacity(32 * 1000, out_file);
125125
let mut buf: String = String::with_capacity(50); // Estimate
126126
if let Some(zoom) = zoom {
127+
if bigbed
128+
.info()
129+
.zoom_headers
130+
.iter()
131+
.all(|z| z.reduction_level != zoom)
132+
{
133+
eprintln!("Error: Zoom level not found: {zoom}");
134+
return Ok(());
135+
}
127136
for chrom in chroms {
128137
let start = start.unwrap_or(0);
129138
let end = end.unwrap_or(chrom.length);
130-
for raw_val in bigbed
131-
.get_zoom_interval(&chrom.name, start, end, zoom)
132-
.unwrap()
133-
{
139+
for raw_val in bigbed.get_zoom_interval(&chrom.name, start, end, zoom)? {
134140
let val = raw_val?;
135141
uwrite!(
136142
&mut buf,

0 commit comments

Comments
 (0)