| name | bio-genome-intervals-interval-arithmetic |
| description | Core interval arithmetic operations including intersect, subtract, merge, complement, map, and groupby using bedtools and pybedtools. Use when finding overlapping regions, removing overlaps, combining adjacent intervals, or transferring annotations between interval files. |
| tool_type | mixed |
| primary_tool | bedtools |
Interval Arithmetic
Core set operations on genomic intervals using bedtools (CLI) and pybedtools (Python).
Intersect - Find Overlapping Regions
CLI
bedtools intersect -a peaks.bed -b genes.bed > overlapping.bed
bedtools intersect -a peaks.bed -b genes.bed > peaks_in_genes.bed
bedtools intersect -a peaks.bed -b genes.bed > overlap_regions.bed
bedtools intersect -a peaks.bed -b genes.bed -wa -wb > with_gene_info.bed
bedtools intersect -a peaks.bed -b genes.bed -u > peaks_overlapping_genes.bed
bedtools intersect -a peaks.bed -b genes.bed -v > peaks_not_in_genes.bed
bedtools intersect -a peaks.bed -b genes.bed -f 0.5 > min_50pct.bed
bedtools intersect -a peaks.bed -b genes.bed -f 0.5 -r > reciprocal_50pct.bed
bedtools intersect -a peaks.bed -b genes.bed -c > with_counts.bed
bedtools intersect -a peaks.bed -b genes.bed promoters.bed enhancers.bed -names genes promoters enhancers > multi.bed
Python
import pybedtools
a = pybedtools.BedTool('peaks.bed')
b = pybedtools.BedTool('genes.bed')
result = a.intersect(b)
result = a.intersect(b, u=True)
result = a.intersect(b, wa=True, wb=True)
result = a.intersect(b, v=True)
result = a.intersect(b, f=0.5)
result = a.intersect(b, f=0.5, r=True)
result = a.intersect(b, c=True)
result.saveas('output.bed')
Subtract - Remove Overlapping Regions
CLI
bedtools subtract -a regions.bed -b exclude.bed > remaining.bed
bedtools subtract -a regions.bed -b exclude.bed -A > non_overlapping.bed
bedtools subtract -a regions.bed -b exclude.bed -f 0.5 > subtract_50pct.bed
Python
import pybedtools
a = pybedtools.BedTool('regions.bed')
b = pybedtools.BedTool('exclude.bed')
result = a.subtract(b)
result = a.subtract(b, A=True)
result = a.subtract(b, f=0.5)
result.saveas('remaining.bed')
Merge - Combine Overlapping/Adjacent Intervals
CLI
bedtools sort -i peaks.bed | bedtools merge > merged.bed
bedtools sort -i peaks.bed | bedtools merge -d 100 > merged_100bp.bed
bedtools sort -i peaks.bed | bedtools merge -c 1 -o count > merged_counts.bed
bedtools sort -i peaks.bed | bedtools merge -c 4,5 -o collapse,sum > merged_agg.bed
bedtools sort -i peaks.bed | bedtools merge -c 5 -o max > merged_max.bed
bedtools sort -i peaks.bed | bedtools merge -s > merged_stranded.bed
Python
import pybedtools
bed = pybedtools.BedTool('peaks.bed')
merged = bed.sort().merge()
merged = bed.sort().merge(d=100)
merged = bed.sort().merge(c=1, o='count')
merged = bed.sort().merge(c='4,5', o='collapse,sum')
merged = bed.sort().merge(s=True)
merged.saveas('merged.bed')
Complement - Get Uncovered Regions
CLI
bedtools complement -i covered.bed -g genome.txt > uncovered.bed
Python
import pybedtools
bed = pybedtools.BedTool('covered.bed')
genome = 'genome.txt'
uncovered = bed.complement(g=genome)
uncovered.saveas('uncovered.bed')
genome_dict = pybedtools.chromsizes('hg38')
uncovered = bed.complement(genome=genome_dict)
Cluster - Group Overlapping Intervals
CLI
bedtools sort -i peaks.bed | bedtools cluster > clustered.bed
bedtools sort -i peaks.bed | bedtools cluster -d 100 > clustered_100bp.bed
Python
import pybedtools
bed = pybedtools.BedTool('peaks.bed')
clustered = bed.sort().cluster()
clustered.saveas('clustered.bed')
Multiinter - Find Multi-way Overlaps
CLI
bedtools multiinter -i sample1.bed sample2.bed sample3.bed > multi_overlap.bed
bedtools multiinter -i sample1.bed sample2.bed sample3.bed \
-names s1 s2 s3 > multi_overlap.bed
bedtools multiinter -i sample1.bed sample2.bed sample3.bed -header > multi_overlap.bed
Python
import pybedtools
beds = [pybedtools.BedTool(f) for f in ['s1.bed', 's2.bed', 's3.bed']]
result = pybedtools.BedTool().multi_intersect(i=[b.fn for b in beds])
Jaccard - Similarity Metric
CLI
bedtools jaccard -a sample1.bed -b sample2.bed
Python
import pybedtools
a = pybedtools.BedTool('sample1.bed')
b = pybedtools.BedTool('sample2.bed')
result = a.jaccard(b)
print(f"Jaccard index: {result['jaccard']}")
print(f"Intersection: {result['intersection']} bp")
print(f"Union: {result['union']} bp")
Fisher's Exact Test
CLI
bedtools fisher -a peaks.bed -b genes.bed -g genome.txt
Python
import pybedtools
a = pybedtools.BedTool('peaks.bed')
b = pybedtools.BedTool('genes.bed')
result = a.fisher(b, genome='genome.txt')
print(result)
Shuffle - Random Permutation
CLI
bedtools shuffle -i peaks.bed -g genome.txt > shuffled.bed
bedtools shuffle -i peaks.bed -g genome.txt -excl blacklist.bed > shuffled.bed
bedtools shuffle -i peaks.bed -g genome.txt -chrom > shuffled.bed
Python
import pybedtools
bed = pybedtools.BedTool('peaks.bed')
shuffled = bed.shuffle(g='genome.txt')
shuffled.saveas('shuffled.bed')
Map - Transfer Values Between Files
Map overlapping B values onto A intervals with aggregation.
CLI
bedtools map -a genes.bed -b scores.bedGraph -c 4 -o mean > genes_with_scores.bed
bedtools map -a regions.bed -b data.bed -c 5,5,5 -o mean,min,max > multi_stats.bed
bedtools map -a genes.bed -b peaks.bed -c 1 -o count > genes_with_peak_counts.bed
bedtools map -a genes.bed -b peaks.bed -c 4 -o collapse > genes_with_peak_names.bed
bedtools map -a genes.bed -b annotations.bed -c 4 -o distinct > unique_annotations.bed
Python
import pybedtools
a = pybedtools.BedTool('genes.bed')
b = pybedtools.BedTool('scores.bedGraph')
result = a.map(b, c=4, o='mean')
result = a.map(b, c='5,5,5', o='mean,min,max')
result.saveas('mapped.bed')
Map Operations
| Operation | Description |
|---|
| sum | Sum of values |
| count | Number of overlapping features |
| count_distinct | Number of distinct values |
| min, max | Minimum/maximum value |
| mean, median | Average values |
| collapse | Comma-separated list |
| distinct | Unique values only |
| first, last | First/last overlapping value |
Groupby - Aggregate by Columns
Group intervals and compute summary statistics.
CLI
bedtools groupby -i sorted.bed -g 4 -c 5 -o sum > gene_totals.bed
bedtools groupby -i sorted.bed -g 1 -c 2,3 -o min,max > chr_ranges.bed
bedtools groupby -i sorted.bed -g 1,4 -c 5 -o mean > by_chr_gene.bed
bedtools groupby -i sorted.bed -g 1,2,3 -c 4 -o collapse > merged_names.bed
bedtools groupby -i sorted.bed -g 1 -c 1 -o count > features_per_chr.bed
bedtools groupby -i sorted.bed -g 1-3 -c 5 -o sum > grouped.bed
Python
import pybedtools
bed = pybedtools.BedTool('sorted.bed')
result = bed.groupby(g=4, c=5, o='sum')
result = bed.groupby(g=[1, 4], c=[5, 5], o=['mean', 'count'])
result.saveas('grouped.bed')
Note: Input must be sorted by grouping columns.
Common Patterns
Find Peaks in Promoters
import pybedtools
peaks = pybedtools.BedTool('peaks.bed')
promoters = pybedtools.BedTool('promoters.bed')
peaks_in_promoters = peaks.intersect(promoters, u=True)
print(f'{peaks_in_promoters.count()} peaks in promoters')
Find Unique Regions in Sample
import pybedtools
sample_a = pybedtools.BedTool('sample_a.bed')
sample_b = pybedtools.BedTool('sample_b.bed')
unique_a = sample_a.intersect(sample_b, v=True)
unique_a.saveas('unique_to_a.bed')
Merge Replicates
cat rep1.bed rep2.bed rep3.bed | bedtools sort | bedtools merge -d 100 > consensus.bed
Key Parameters
| Operation | Key Flags | Description |
|---|
| intersect -u | Unique | Report A once if overlap |
| intersect -v | Inverse | A that don't overlap B |
| intersect -f | Fraction | Minimum overlap fraction |
| intersect -r | Reciprocal | Both must meet -f threshold |
| intersect -c | Count | Count overlapping B features |
| subtract -A | All | Remove entire A if any overlap |
| merge -d | Distance | Merge within N bp |
| merge -c -o | Columns/Ops | Aggregate columns |
Related Skills
- bed-file-basics - BED format and creation
- proximity-operations - closest, window, flank, slop
- coverage-analysis - coverage calculations
- chip-seq/peak-calling - peak file operations