# How to Convert BAM to BED: Extracting Read Intervals

By the end of this guide you will be able to take an aligned BAM file and produce a clean, sorted, indexed BED file of read intervals that behaves correctly in every downstream tool you feed it to. You will also know how to compute those intervals by hand, so that when a number looks wrong you can prove where the error came from instead of guessing.

The conversion itself is one command. Almost all the difficulty sits on either side of that command: deciding which reads deserve to become intervals, and confirming that the intervals you produced actually describe the alignments you started with. A BED file is a lossy projection of a BAM file. It throws away sequence, base qualities, CIGAR strings, mate information, and mapping details. What survives is a genomic footprint, and if that footprint is computed from the wrong CIGAR operation or the wrong filter, nothing downstream will warn you.

You need three things on hand: an alignment file in BAM or CRAM format, a reference sequence if your file is CRAM, and a working installation of samtools and bedtools. Both are available as static binaries, through conda and Bioconda, and inside container images. A modern Linux or macOS machine with a few gigabytes of free disk space is enough for most BAM-to-BED jobs.

## What You Need Before You Start

Check your tool versions first. The behavior of flag filtering and BED12 block construction has been stable for years, but knowing the version makes bug reports and reproducibility notes meaningful.

```bash
samtools --version
bedtools --version
```

You should see output naming a release number for each, for example `samtools 1.20` and `bedtools v2.31.1`. If either command is missing, install them with conda:

```bash
conda install -c bioconda -c conda-forge samtools bedtools
```

Container images are the more portable option when you need the same result on a laptop and a cluster. Packaging command-line conversion tools as Conda packages and BioContainers images is now the standard way to keep cross-platform behavior identical, a pattern described for proteomics format converters and equally applicable here [1]. Toolkit authors in genomics follow the same distribution model, shipping prebuilt Linux and macOS binaries through Bioconda alongside a command-line interface [2].

Confirm you have disk space. A BAM file of roughly 10 GB can produce a BED file in the low hundreds of megabytes if you emit one interval per read, and considerably more if you split spliced reads into blocks. Compression with bgzip cuts the final size by roughly an order of magnitude for typical human data.

## BAM, BED, and the One-Base Trap

### What BAM stores

BAM is the binary form of the Sequence Alignment/Map format. Each record holds a read name, a bitwise flag, a reference name, a 1-based leftmost position, a mapping quality, a CIGAR string describing how the read aligns, the mate reference and position, an observed template length, the read sequence, per-base quality scores, and optional tags such as `NM` for edit distance. Records are stored in a compressed binary stream, and an index (`.bai` or `.csi`) allows random access to genomic regions.

The CIGAR string is the part that matters most for BED conversion. It is a run-length encoding of alignment operations. `M` means alignment match or mismatch, `I` is an insertion to the reference, `D` is a deletion from the reference, `N` is a skipped region such as an intron, `S` is a soft clip, `H` is a hard clip, `=` is a sequence match, and `X` is a sequence mismatch. Only `M`, `D`, `N`, `=`, and `X` consume reference bases. Everything else consumes read bases or nothing at all.

### What BED stores

BED is a plain-text, tab-delimited format. It has no header and no binary encoding. The first three columns are mandatory: chromosome name, start, and end. The start is 0-based and inclusive. The end is 0-based and exclusive. This "half-open" convention means an interval from 999 to 1089 covers exactly 90 reference bases, positions 1000 through 1089 in 1-based terms.

BED6 adds a name, a score, and a strand. BED12 adds thickStart, thickEnd, itemRgb, blockCount, blockSizes, and blockStarts, which is how a spliced alignment is represented as a single record with internal gaps.

Because BED is tab-delimited text, it plugs directly into the same family of tabular exchange formats used across bioinformatics for handing data to downstream tools that expect strict column layouts [3].

### The coordinate shift

The single most common source of silent error is the one-base offset between the two formats. BAM position 1000 becomes BED start 999. The end is start plus the number of reference bases consumed. `bedtools bamtobed` performs this arithmetic for you. Hand-rolled scripts frequently do not, and a BED file that is uniformly shifted by one base will still load, still sort, still intersect, and still produce plausible-looking results that are subtly wrong at every boundary.

## Where FASTA, FASTQ, BAM, and BED Fit in the File Format Landscape

Bioinformatics file formats fall into a small number of families, and knowing which family you are in prevents most confusion. Sequence formats hold letters. Alignment formats hold letters plus coordinates. Interval formats hold coordinates only.

| Format | Content | Coordinates | Quality scores | Typical role |
|--|--|--|--|--|
| FASTA | Sequence, no qualities | None | No | Reference genomes, protein sequences, alignments |
| FASTQ | Sequence plus per-base quality | None | Yes, Phred+33 | Raw reads from the sequencer |
| SAM | Text alignment records | 1-based | Yes | Human-readable alignment |
| BAM | Binary alignment records | 1-based | Yes | Standard aligned read storage |
| CRAM | Reference-compressed alignment | 1-based | Yes | Archival aligned read storage |
| BED | Intervals | 0-based, half-open | No | Regions, coverage tracks, overlap analysis |

The fastq versus fasta distinction trips up newcomers because both look like sequence. FASTA uses a `>` header and stores only letters. FASTQ uses an `@` header, then the sequence, then a `+` separator, then a string of characters with exactly one character per base. Each FASTQ quality character encodes a Phred score as its ASCII value minus 33. A `I` character (ASCII 73) means quality 40, which corresponds to an error probability of 0.0001. FASTA has no equivalent field, so any quality information is permanently lost the moment you convert FASTQ to FASTA.

Neither FASTA nor FASTQ can be converted to BED directly, because neither carries coordinates. You need the alignment step first. The pipeline is FASTQ to BAM through an aligner, then BAM to BED for interval work. Going backward is possible in the sense that `samtools fastq` can regenerate FASTQ from BAM (base qualities are preserved in the QUAL field), but BED to BAM is not a real conversion. A BED file has no sequences to place, so any "BED to BAM" tool is really building a synthetic alignment with placeholder bases.

## How to Convert BAM to BED Step by Step

### Step 1: Confirm the BAM Is Intact

Truncated BAM files are common on shared clusters and in downloaded datasets. A truncated file may still open and still yield records before failing partway through, which is worse than a clean failure because it produces a partial BED file with no error attached.

```bash
samtools quickcheck -v input.bam
```

A healthy file produces no output and exits with status 0. A damaged file prints its name. If quickcheck complains, re-download or re-transfer the file before doing anything else.

Next, look at the header to confirm reference names and sorting order.

```bash
samtools view -H input.bam | grep -E '^@HD|^@SQ' | head
```

Expected output resembles:

```
@HD	VN:1.6	SO:coordinate
@SQ	SN:chr1	LN:248956422
@SQ	SN:chr2	LN:242193529
```

The `SO:coordinate` tag tells you the file is coordinate-sorted, which is what most tools expect. The `SN:` values tell you whether chromosomes are named `chr1` or `1`. Write that down. A BED file that uses `chr1` will silently fail to intersect with a BED file that uses `1`, and many tools report zero overlaps rather than an error.

Get a read-level summary.

```bash
samtools flagstat input.bam
```

The output lists total reads, mapped reads, properly paired reads, duplicates, and secondary alignments as counts and percentages. Keep this output. You will compare it against your BED line count later.

### Step 2: Index the BAM

An index is not required for a full-file conversion, but it is required the moment you want to convert a region, run coverage on a window, or use `samtools view` with a genomic coordinate.

```bash
samtools index -@ 4 input.bam
```

This creates `input.bam.bai`. For references longer than about 512 Mb, use `samtools index -c` to build a CSI index instead.

If you see this message:

```
[E::idx_find_and_load] Could not retrieve index file for 'input.bam'
```

the index is missing or has a stale timestamp. Rebuild it.

If you see:

```
samtools index: "input.bam" is in a format that cannot be usefully indexed
```

the file is SAM text, not BAM binary. Convert it with `samtools view -b input.sam -o input.bam` first.

### Step 3: Filter Reads Before You Convert

This is the step people skip, and it is the step that determines whether your BED file means anything.

A raw BAM contains unmapped reads, reads that failed vendor quality checks, PCR duplicates, secondary alignments from multi-mapping reads, and supplementary alignments from chimeric or split reads. Converting all of them produces a BED file with inflated coverage, duplicated intervals, and intervals at position 0 for unmapped reads.

The workhorse filter is the `-F` flag, which excludes reads carrying any of the specified bits. The bits that matter here:

| Flag | Hex | Meaning | Exclude for interval work? |
|--|--|--|--|
| 0x1 | 1 | Paired | No |
| 0x2 | 2 | Properly paired | No |
| 0x4 | 4 | Unmapped | Yes |
| 0x10 | 16 | Reverse strand | No |
| 0x100 | 256 | Secondary alignment | Usually yes |
| 0x200 | 512 | Failed QC | Usually yes |
| 0x400 | 1024 | PCR or optical duplicate | Usually yes |
| 0x800 | 2048 | Supplementary alignment | Usually yes |

A good general-purpose filter combines unmapped, secondary, and supplementary into `0x904`:

```bash
samtools view -b -q 20 -F 0x904 -@ 4 input.bam -o filtered.bam
```

The `-q 20` drops reads with mapping quality below 20, which removes ambiguous multi-mappers while keeping confidently placed reads. If your experiment depends on multi-mapping reads, such as certain repeat families or allele-specific analyses, lower or remove the MAPQ threshold and handle the ambiguity downstream.

If you want to keep supplementary alignments (common in long-read work where one read legitimately aligns in several pieces), use `-F 0x704` instead. That removes unmapped, secondary, QC-failed, and duplicate reads but retains supplementary records.

Record how many reads survived.

```bash
samtools view -c -F 0x904 -q 20 input.bam
```

### Step 4: Run the Conversion

With a filtered BAM in hand, the conversion is a single command.

```bash
bedtools bamtobed -i filtered.bam > reads.bed
```

Look at the first few lines.

```bash
head -3 reads.bed
```

Expected output:

```
chr1	999	1089	read_0001	60	+
chr1	1499	1549	read_0002	42	-
chr2	2999	3049	read_0003	60	+
```

Six tab-separated columns. Column 1 is the reference name, column 2 is the 0-based start, column 3 is the exclusive end, column 4 is the read name, column 5 is the mapping quality, column 6 is the strand.

You can skip the intermediate file entirely by piping:

```bash
samtools view -b -q 20 -F 0x904 -@ 4 input.bam \
  | bedtools bamtobed -i stdin \
  > reads.bed
```

This saves disk space and a write cycle, at the cost of losing the ability to re-run the conversion without repeating the filter. On a machine with enough memory and fast storage, the intermediate file is often worth keeping.

### Step 5: Sort and Compress

BED files are not required to be sorted, but almost every interval operation is faster and more predictable on sorted input. Sorting by chromosome then start is the convention.

```bash
bedtools sort -i reads.bed > reads.sorted.bed
```

Or with GNU sort, which is faster on large files:

```bash
sort -k1,1 -k2,2n reads.bed > reads.sorted.bed
```

Compress and index for random access:

```bash
bgzip -c reads.sorted.bed > reads.sorted.bed.gz
tabix -p bed reads.sorted.bed.gz
```

You now have a compressed, indexed BED file that any tool supporting tabix can query by region. The `.tbi` index file sits next to the `.gz` file.

### Step 6: Verify the Output

Verification is not optional. A BED file has no schema enforcement, so a file with negative coordinates or reversed intervals will still be accepted by many tools.

Check the line count against the filtered read count.

```bash
wc -l reads.bed
```

The BED line count should match or be slightly below the `samtools view -c` count from Step 3. It will be lower if you used `-split`, because each block of a spliced read becomes its own line. It will be lower if any reads have zero-length reference spans, which bedtools generally skips.

Check for malformed intervals.

```bash
awk 'BEGIN{bad=0} $2 < 0 || $3 <= $2 {bad++; if(bad<=5) print "BAD:", $0} END{print "total bad:", bad}' reads.bed
```

The output should end with `total bad: 0`.

Check per-chromosome counts against the BAM.

```bash
samtools idxstats filtered.bam | cut -f1,3 > bam_counts.txt
cut -f1 reads.bed | sort | uniq -c | awk '{print $2"\t"$1}' > bed_counts.txt
```

Compare the two files. Small discrepancies are normal because idxstats counts mapped reads and the BED file counts intervals. Large discrepancies on a specific chromosome usually mean a naming mismatch or a region of the BAM with unusual CIGAR operations.

Finally, spot-check a known locus. Pick a read name from the BED file and confirm the same coordinates appear in the BAM.

```bash
grep -m1 "read_0001" reads.bed
samtools view filtered.bam | grep -m1 "read_0001"
```

The BAM line will show the 1-based position in column 4 and the CIGAR in column 6. Confirm that the BED start equals the BAM position minus one, and that the BED end minus the BED start equals the reference-consuming length of the CIGAR.

## Options That Change the Output

`bedtools bamtobed` has a small set of options, and each one changes the meaning of the output rather than just its shape.

| Option | Effect | When to use |
|--|--|--|
| (none) | BED6, one line per alignment | Default interval extraction |
| `-bed12` | BED12 with block fields from CIGAR | Spliced reads kept as one record |
| `-split` | Split on `N` into separate BED6 lines | Per-exon coverage |
| `-splitD` | Split on `N` and `D` | Deletion-aware exon work |
| `-bedpe` | BEDPE, one line per read pair | Paired-end fragment analysis |
| `-mate1` | Force mate 1 first in BEDPE | Consistent pair ordering |
| `-ed` | Edit distance replaces score | Mismatch-aware filtering |
| `-cigar` | Append CIGAR as extra column | Debugging and audits |
| `-tag` | Append a BAM tag value | Carrying `NM` or `RG` forward |
| `-ubam` | Emit uncompressed BAM | Feeding another BAM-aware tool |

The `-split` and `-bed12` choice is the one that causes the most downstream confusion. A spliced read with CIGAR `50M1000N50M` at position 500 occupies a single reference span from 499 to 1599. With `-split`, it becomes two records: 499 to 549 and 1549 to 1599. With `-bed12`, it stays one record with two blocks. Neither is wrong. They answer different questions. Per-exon read counts need `-split`. Transcript-level footprint needs `-bed12`.

Downstream tools are strict about which columns they will accept and in what order. Formatting a file to match a tool's exact specification, rather than assuming the tool will be flexible, is the same discipline that applies to any structured input format conversion [4].

## Converting Without bedtools: samtools and awk

Sometimes bedtools is unavailable, or you need the interval computation embedded in a script that already streams `samtools view`. The reference end is computable directly from the CIGAR string.

```bash
samtools view -F 0x904 -q 20 filtered.bam | awk 'BEGIN{FS=OFS="\t"} {
  cigar = $6
  ref = 0
  while (match(cigar, /[0-9]+[MIDNSHP=X]/)) {
    n  = substr(cigar, RSTART, RLENGTH-1) + 0
    op = substr(cigar, RSTART+RLENGTH-1, 1)
    if (op == "M" || op == "D" || op == "N" || op == "=" || op == "X") ref += n
    cigar = substr(cigar, RSTART+RLENGTH)
  }
  strand = (int($2/16) % 2 == 1) ? "-" : "+"
  print $3, $4-1, $4-1+ref, $1, $5, strand
}' > reads_awk.bed
```

The output columns match `bamtobed` default BED6. The `$4-1` term converts the 1-based BAM position to the 0-based BED start. The `ref` accumulator adds only the operations that consume reference bases.

### A Worked Coordinate Calculation

Take a read with position 1000 and CIGAR `10S40M2D48M`. The sequence length is 98 bases.

Walk the CIGAR:

- `10S`: soft clip, 10 read bases, 0 reference bases
- `40M`: 40 reference bases
- `2D`: 2 reference bases
- `48M`: 48 reference bases

Reference span is 40 + 2 + 48 = 90. BED start is 1000 minus 1, which is 999. BED end is 999 + 90, which is 1089. The interval is `chr:999-1089`.

The naive calculation, `POS + length(SEQ) - 1`, gives 1000 + 98 - 1 = 1097. That is 8 bases too long, because the soft-clipped bases do not exist on the reference and the deletion does. A BED file built with the naive formula will overlap neighboring features that the read never touched.

### Spliced Reads

Take a read with position 500 and CIGAR `50M1000N50M`.

Reference span is 50 + 1000 + 50 = 1100. The default BED interval is 499 to 1599, which includes the intron. With `-split`, the two blocks are 499 to 549 and 1549 to 1599. Check the second block by hand: the first block ends at 1-based position 549, the `N` skips 1000 reference bases, so the next aligned base is 1-based 1550, which is 0-based 1549. The block runs for 50 bases to 0-based 1599.

This is exactly the calculation a genome browser performs when it draws a spliced read as a line with a gap. Getting it wrong produces coverage piled up in introns, which is a classic symptom of an unsplit conversion applied to RNA-seq data.

## Coverage BED Files Are a Different Product

A read-interval BED and a coverage BED answer different questions, and mixing them up is a frequent source of confusion. `bamtobed` gives you one line per alignment. Coverage tools give you one line per run of constant depth.

```bash
bedtools genomecov -ibam filtered.bam -bg > coverage.bedgraph
```

The output has four columns: chromosome, start, end, and depth. Adjacent positions with equal depth are merged into runs. This is a bedGraph file, not a BED6 file, and tools that expect read intervals will misinterpret it.

To include zero-coverage regions:

```bash
bedtools genomecov -ibam filtered.bam -bga > coverage_with_zeros.bedgraph
```

For per-base depth from samtools, which produces 1-based positions:

```bash
samtools depth -a -q 20 filtered.bam > depth.txt
```

The three columns are reference name, 1-based position, and depth. Note the coordinate system changes here. If you mix `samtools depth` output with BED files in the same script without converting, every position is off by one.

To measure coverage over a set of target regions:

```bash
bedtools coverage -a targets.bed -b filtered.bam > target_coverage.txt
```

This appends counts of overlapping features, bases covered, region length, and fractional coverage to each target interval.

## Common Mistakes and Limitations

**Forgetting the coordinate shift.** BAM is 1-based, BED is 0-based. Scripts that copy column 4 directly into the BED start column produce a file that is shifted by one base everywhere. The error is invisible in aggregate statistics and fatal in boundary-sensitive analyses such as splice site definition or transcription start site mapping.

**Using sequence length instead of reference span.** The formula `POS + length(SEQ)` overestimates the interval for any read with soft clips and underestimates it for any read with deletions. Use the CIGAR, or use a tool that does.

**Converting unmapped reads.** Unmapped reads have no meaningful position. Some carry the mate's coordinate in the POS field, which produces intervals at loci the read never came from. Always filter with `-F 0x4` or the larger `-F 0x904` mask.

**Leaving duplicates in.** PCR duplicates inflate coverage in a way that is not random. For any quantitative work, filter `0x400` unless you have a specific reason not to.

**Mixing chromosome naming conventions.** A BAM using `chr1` converted to BED and then intersected against a BED using `1` yields zero overlaps with no error message. Check `samtools view -H` and normalize with `sed 's/^chr//'` or the reverse before intersecting.

**Assuming BED is lossless.** BED discards sequence, base quality, CIGAR, mate coordinates, insert size, and every optional tag. Anything you need from those fields must be extracted before or during conversion. Summary representations always lose information relative to the full record, a tradeoff that shows up across every domain where compact exchange formats replace rich primary data [5]. Conversions between formats with proprietary or non-standard extensions are especially prone to losing fields the converter does not know about [6].

**Sorting by string instead of numerically.** `sort -k2` sorts `100` before `99`. Use `sort -k1,1 -k2,2n` or `bedtools sort`.

**Zero-length intervals.** Some alignments produce start equal to end. Many tools reject these or treat them inconsistently. Filter them out with `awk '$3 > $2'` if your downstream tool is strict.

**Forgetting that `-bedpe` needs name sorting.** Paired-end BEDPE output requires the BAM to be queryname-sorted. Run `samtools sort -n` first, and expect bedtools to refuse the file otherwise.

**Using a truncated BAM.** A partially downloaded BAM can produce a partial BED file with no error until the exact byte where the stream ends. Run `samtools quickcheck` before every conversion in an automated pipeline.

**Ignoring the strand column.** BED6 column 6 is strand, and it is computed from flag bit `0x10`. A script that hardcodes `+` breaks every antisense transcript and every reverse-strand feature annotation.

**Overwriting the input.** `bedtools bamtobed -i reads.bam > reads.bam` truncates the BAM before bedtools reads it. Shell redirection happens first. Use distinct filenames.

**Expecting a header.** BED has no header line. If you add one for readability, most tools will treat it as a malformed record. Use a separate metadata file or a comment character only if the specific tool documents support for it.

**Treating BED as a sequence format.** A BED file cannot be converted back to BAM in any meaningful sense. There are no bases to place. Tools that claim to do this build synthetic records with placeholder sequence, and the result is useful only for testing parsers.

**Skipping validation on large files.** A conversion that works on a 10,000-read test file can still fail at scale because of a single malformed CIGAR deep in the file. Run the `awk` validity check from Step 6 on the full output, not just the head.

## Tips for Reproducible Conversion

Write the filter into the command, not into your memory. A conversion script that says `bedtools bamtobed -i input.bam` is not reproducible, because the filtering decisions are invisible. A script that says `samtools view -b -q 20 -F 0x904 input.bam | bedtools bamtobed -i stdin` documents its own assumptions.

Record tool versions in the output directory.

```bash
{
  echo "# samtools: $(samtools --version | head -1)"
  echo "# bedtools: $(bedtools --version)"
  echo "# date: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
  echo "# filter: -q 20 -F 0x904"
} > reads.bed.provenance.txt
```

Keep the intermediate filtered BAM. Regenerating a BED file from a filtered BAM takes seconds. Regenerating the filtered BAM from a 200 GB original takes hours.

Capture per-file audit information for every output. Workflow systems built for bioinformatics pipelines treat an audit trace per output file as a first-class feature, precisely because reconstruction after the fact is unreliable [7]. Even a simple sidecar text file gets you most of the benefit.

Test the round trip. Convert a small region of the BAM to BED, then verify that every interval in the BED corresponds to a record in the BAM with matching coordinates. Round-trip testing between formats written by different code paths is how interoperability libraries catch silent corruption, and the same discipline applies to a two-command conversion [8]. Parse the source into a well-defined in-memory representation, write the target format, and confirm the fields you care about survive the trip [9].

Use region-restricted conversion for spot checks rather than converting the whole file.

```bash
samtools view -b filtered.bam chr1:1000000-1100000 \
  | bedtools bamtobed -i stdin \
  > region_check.bed
```

This requires the index from Step 2 and runs in seconds regardless of file size.

Decide between file-based and streaming conversion deliberately. A file-based approach materializes the intermediate BAM and is easier to debug, while a streaming approach avoids disk pressure and is easier to schedule on constrained nodes. Both are legitimate, and the choice should be documented rather than accidental [10].

Pin your container image by digest, not by tag. `latest` is not a version.

## Frequently Asked Questions

### Can I convert BAM to BED without bedtools?

Yes. `samtools view` piped into an awk script that walks the CIGAR string produces identical BED6 output. The awk approach is slower and easier to get wrong, but it removes a dependency and gives you full control over the columns.

### Does bamtobed include unmapped reads?

No, unmapped reads are skipped because they have no reference span to report. Reads that are flagged unmapped but carry a mate coordinate can still cause trouble in hand-rolled scripts, so filter with `-F 0x4` explicitly rather than relying on the tool's behavior.

### Why is my BED start one base off from the BAM position?

BAM uses 1-based coordinates and BED uses 0-based coordinates. Subtract one from the BAM position to get the BED start. Every field derived from the position needs the same adjustment.

### Should I use -split or -bed12 for RNA-seq?

Use `-split` when you need per-exon counts and `-bed12` when you need one record per transcript footprint. Splitting inflates the line count but makes exon-level overlap arithmetic straightforward. Keeping BED12 preserves the read as a single unit with internal gaps.

### How do I convert only a specific genomic region?

Index the BAM, then use `samtools view -b input.bam chr1:1000000-1100000` and pipe the result into `bedtools bamtobed -i stdin`. The region syntax is 1-based and inclusive, matching the BAM coordinate system.

### What is the difference between BED and BEDPE?

BED holds one interval per line. BEDPE holds two intervals per line, one for each mate of a read pair, plus the read name and pair-level fields such as insert size. BEDPE requires a queryname-sorted BAM as input.

### Can I convert BED back to BAM?

Not in any meaningful way. BED contains coordinates but no sequence, no quality scores, and no CIGAR string. Any tool that claims to do this produces synthetic records with placeholder bases and is useful only for testing software, not for analysis.

### How do I handle chr1 versus 1 naming mismatches?

Check the reference names with `samtools view -H` and normalize one side of every comparison. Either strip the prefix with `sed 's/^chr//'` or add it, then verify that the per-chromosome counts match before running any intersection.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Can I convert BAM to BED without bedtools?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes. samtools view piped into an awk script that walks the CIGAR string produces identical BED6 output. The awk approach is slower and easier to get wrong, but it removes a dependency and gives you full control over the columns."
      }
    },
    {
      "@type": "Question",
      "name": "Does bamtobed include unmapped reads?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "No, unmapped reads are skipped because they have no reference span to report. Reads that are flagged unmapped but carry a mate coordinate can still cause trouble in hand-rolled scripts, so filter with -F 0x4 explicitly rather than relying on the tool's behavior."
      }
    },
    {
      "@type": "Question",
      "name": "Why is my BED start one base off from the BAM position?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "BAM uses 1-based coordinates and BED uses 0-based coordinates. Subtract one from the BAM position to get the BED start. Every field derived from the position needs the same adjustment."
      }
    },
    {
      "@type": "Question",
      "name": "Should I use -split or -bed12 for RNA-seq?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Use -split when you need per-exon counts and -bed12 when you need one record per transcript footprint. Splitting inflates the line count but makes exon-level overlap arithmetic straightforward. Keeping BED12 preserves the read as a single unit with internal gaps."
      }
    },
    {
      "@type": "Question",
      "name": "How do I convert only a specific genomic region?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Index the BAM, then use samtools view -b input.bam chr1:1000000-1100000 and pipe the result into bedtools bamtobed -i stdin. The region syntax is 1-based and inclusive, matching the BAM coordinate system."
      }
    },
    {
      "@type": "Question",
      "name": "What is the difference between BED and BEDPE?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "BED holds one interval per line. BEDPE holds two intervals per line, one for each mate of a read pair, plus the read name and pair-level fields such as insert size. BEDPE requires a queryname-sorted BAM as input."
      }
    },
    {
      "@type": "Question",
      "name": "Can I convert BED back to BAM?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Not in any meaningful way. BED contains coordinates but no sequence, no quality scores, and no CIGAR string. Any tool that claims to do this produces synthetic records with placeholder bases and is useful only for testing software, not for analysis."
      }
    },
    {
      "@type": "Question",
      "name": "How do I handle chr1 versus 1 naming mismatches?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Check the reference names with samtools view -H and normalize one side of every comparison. Either strip the prefix with sed 's/^chr//' or add it, then verify that the per-chromosome counts match before running any intersection."
      }
    }
  ]
}
</script>

## Sources

1. [ThermoRawFileParser: Modular, Scalable, and Cross-Platform RAW File Conversion.](https://pubmed.ncbi.nlm.nih.gov/31755270/)
2. [hictk: blazing fast toolkit to work with .hic and .cool files.](https://pubmed.ncbi.nlm.nih.gov/38913844/)
3. [EMBL2checklists: A Python package to facilitate the user-friendly submission of plant and fungal DNA barcoding sequences to ENA.](https://pubmed.ncbi.nlm.nih.gov/30629718/)
4. [Fasta2Structure: a user-friendly tool for converting multiple aligned FASTA files to STRUCTURE format.](https://pubmed.ncbi.nlm.nih.gov/38365590/)
5. [HXMS: a standardized file format for HX-MS data.](https://pubmed.ncbi.nlm.nih.gov/41803064/)
6. [cd2sbgnml: bidirectional conversion between CellDesigner and SBGN formats.](https://pubmed.ncbi.nlm.nih.gov/31904823/)
7. [SciPipe: A workflow library for agile development of complex and dynamic bioinformatics pipelines.](https://pubmed.ncbi.nlm.nih.gov/31029061/)
8. [anndataR improves interoperability between R and Python in single-cell transcriptomics.](https://pubmed.ncbi.nlm.nih.gov/42108549/)
9. [IOData: A python library for reading, writing, and converting computational chemistry file formats and generating input files.](https://pubmed.ncbi.nlm.nih.gov/33368350/)
10. [Enhancing semantic interoperability in precision medicine: converting OMOP CDM to Beacon v2 in the Spanish IMPaCT-Data project.](https://pubmed.ncbi.nlm.nih.gov/42420997/)