<p>To answer the question as asked,  for people googling.
For BED6, in python:</p>
<pre class="lang-py prettyprint-override"><code>#contigs.tsv contians chromosome names and lengths in two columns
for line in open(&quot;contigs.tsv&quot;):
   fields = line.strip().split(&quot;\t&quot;)
   print fields[0], &quot;.&quot;, &quot;contig&quot;,&quot;1&quot;,str(fields[1]), &quot;.&quot;, &quot;+&quot;, &quot;.&quot;, &quot;ID=%s&quot; % fields[0]

for line in open(&quot;my_bed_file.bed&quot;):
   fields = line.strip().split(&quot;\t&quot;)

   # note: BED is 0-based, half-open, GFF is 1-based, closed
   start = str(int(fields[1]) + 1)
   print fields[0], &quot;bed&quot;, &quot;interval&quot;, fields[1], fields[2], fields[4], fields[5], &quot;.&quot;, &quot;ID=%s;parent=%s&quot; % (fields[3], fields[0])
</code></pre>
<p>For bed12, in python:</p>
<pre class="lang-py prettyprint-override"><code>#contigs.tsv contians chromosome names and lengths in two columns
for line in open(&quot;contigs.tsv&quot;):
   fields = line.strip().split(&quot;\t&quot;)
   print fields[0], &quot;.&quot;, &quot;contig&quot;,&quot;1&quot;,str(fields[1]), &quot;.&quot;, &quot;+&quot;, &quot;.&quot;, &quot;ID=%s&quot; % fields[0]

for line in open(&quot;my_bed12.bed&quot;):

   fields = line.strip().split(&quot;\t&quot;)
   contig = fields[0]
   # note: BED is 0-based, half-open, GFF is 1-based, closed
   start= int(fields[1]) + 1)
   end=fields[2]
   name=fields[3]
   score=fields[4]
   strand=fields[5]
   print contig, &quot;bed&quot;, &quot;interval&quot;, str(start), end, score, strand, &quot;.&quot;, &quot;ID=%s;parent=%s&quot; % (name, contig)

   block_starts = map(int,fields[11].split(&quot;,&quot;))
   block_sizes = map(int, fields[10].split(&quot;,&quot;))
   
   for (block, (bstart, blen)) in enumerate(zip(block_starts, block_sizes)):
      bend = start + bstart + blen
      print contig, &quot;bed&quot;, &quot;block&quot;, str(start + bstart), str(bend), score, strand, &quot;.&quot;, &quot;ID=%s_%i;parent=%s&quot; %(name, block, name)
</code></pre>

CC BY-SA 4.0
2017-08-08T11:42:33.840Z
2023-10-04T14:06:44.877Z
2023-10-04T14:06:44.877Z
Ian Sudbery
<p>To convert BAM to GTF, which is the best way to get a file to compare with cuffcompare:</p>
<pre class="lang-py prettyprint-override"><code>import pysam

bamfile=pysam.AlignmentFile(&quot;my_bam_file.bam&quot;)

for alignment in bamfile.fetch():

    if alignment.is_unmapped:
        continue

    contig = bamfile.get_reference_name(alignment.reference_id)
    name = alignment.query_name
    
    if alignment.is_reverse:
        strand = &quot;-&quot;
    else: 
        strand = &quot;+&quot;

    for start, end in alignment.getblocks():
        # note: BED is 0-based, half-open, GFF is 1-based, closed
        print contig, &quot;BAM&quot;, &quot;exon&quot;, str(start + 1), str(end), &quot;0&quot;, strand, &quot;.&quot;, 'gene_id &quot;%s&quot;; transcript_id &quot;%s&quot;;' % (name, name)
</code></pre>
<p>NB, this will also work with a SAM file as long as it is headered.</p>

CC BY-SA 3.0
2017-08-10T07:21:32.023Z
As a note for future googlers, if your bam file comes from a pipeline producing unmapped BAMs, the code as it is will return error `ValueError: file header is empty (mode='rb') - is it SAM/BAM format?`. As a workaround it is necessary to add options `check_header=False`, `check_sq=False` while reading the bam. 
 
@IanSudbery  might be useful to add it as a comment to your code
aechchiki
CC BY-SA 3.0
2017-08-10T13:38:21.163Z
@Amina Echchiki, this error is not because your BAM contains unmapped reads, but because your BAM has no header. BAMs without headers are not valid BAM files. I am surprised fetching the contig name worked if the file has no header, even if you set `check_header=False, check_sq=False` because it uses the header to do so.
Ian Sudbery
CC BY-SA 4.0
2017-08-08T12:00:46.733Z
2023-10-04T14:06:07.443Z
2023-10-04T14:06:07.443Z
Ian Sudbery
<p>Bioconductor makes this so easy. It does the coordinate conversion on import.</p>
<pre class="lang-r prettyprint-override"><code>library(rtracklayer)

## import the bed file
bed.ranges &lt;- import.bed('regions.bed')

## export as a gff3 file
export.gff3(bed.ranges,'regions.gff3')
</code></pre>
<p>And people wonder why R is so popular for bioinformatics...</p>
<p>Also if needed, you could go straight from <strong>BAM</strong> file to <strong>gff3</strong> in R as well.</p>

CC BY-SA 3.0
2017-08-09T17:21:31.797Z
As long as you have enough memory to hold the whole bed in memory at once (not a given if it comes from a BAM) this is indeed an easy option.
Ian Sudbery
CC BY-SA 4.0
2017-08-09T15:56:32.420Z
2023-10-04T14:05:44.133Z
2023-10-04T14:05:44.133Z
story
<p>I recently developed <a href="https://github.com/alejandrogzi/bed2gff" rel="nofollow noreferrer">bed2gff</a> to quickly convert .bed files to a gff3 format, a tool written in Rust. Could be of help here!</p>

CC BY-SA 4.0
2023-10-03T23:49:10.090Z
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer).
Community
CC BY-SA 4.0
2023-10-03T23:45:15.427Z
2023-10-03T23:45:15.427Z
Alejandro Gonzales-Irribarren
<p>If anybody needs a simple bed to gff converter, simple in the sense that only takes a bed with a single type of feature, lets say peaks and translate it to GFF I recently wrote this, is Bash and as far as I know all the tools it uses should be present in most Linux / Mac operating systems.</p>
<p><a href="https://github.com/UBMI-IFC/bed2gff/tree/main" rel="nofollow noreferrer">https://github.com/UBMI-IFC/bed2gff/tree/main</a></p>
<p>It cannot deal, however with multi featured Bed files as it ignores everything from the 7th column and beyond.</p>

CC BY-SA 4.0
2023-10-25T17:05:10.397Z
2023-10-25T17:07:17.143Z
2023-10-25T17:07:17.143Z
Carlos  Peralta
<p>You could also use <code>agat_convert_bed2gff</code>. <code>agat</code> is generally a very useful tool when needing to convert from / to / between gff formats. See here how to use it to convert from bed to gff. <a href="https://agat.readthedocs.io/en/latest/tools/agat_convert_bed2gff.html" rel="nofollow noreferrer">https://agat.readthedocs.io/en/latest/tools/agat_convert_bed2gff.html</a></p>

CC BY-SA 4.0
2023-10-26T12:38:25.933Z
2023-10-26T12:38:25.933Z
Niklas
<p>Galaxy has API and API-consuming libraries (such as BioBlend) that will allow you to interactively script against it without opening the graphical interface at all.</p>

<p>However you can also take almost any tool out of Galaxy and use it independently since everything is open source. The converter you mentioned is available as a Python script <a href="https://github.com/galaxyproject/galaxy/blob/dev/tools/filters/bed_to_gff_converter.py" rel="noreferrer">here</a> and the tool 'wrapper' which you can use to understand how to invoke the python script is <a href="https://github.com/galaxyproject/galaxy/blob/dev/tools/filters/bed2gff.xml" rel="noreferrer">next to it</a>.</p>

CC BY-SA 3.0
2017-08-08T20:27:37.457Z
2017-08-08T20:27:37.457Z
Severian
<p>I would like to convert a <a href="https://genome.ucsc.edu/FAQ/FAQformat#format1" rel="noreferrer"><code>BED</code></a> format to <a href="http://www.ensembl.org/info/website/upload/gff3.html" rel="noreferrer"><code>GFF3</code></a>.</p>

<p>The only useful tool that I could find via a <a href="https://www.google.ch/search?q=bed%20to%20gff3" rel="noreferrer">google search</a> seems to be <a href="https://galaxy.inf.ethz.ch/" rel="noreferrer">Galaxy</a>, and I do not feel very comfortable with online tools, plus the webserver is currenlty under maintenance. </p>

<p>Does anyone knows about a command-line tool that can handle this conversion?</p>

<p>Edit: here are some lines of my BED file: </p>

<pre><code>$ head -4 last_minion-r7_sort.bed
211000022278137 175 211 8e5d0959-7cdb-49cf-9298-94ed3b2aedb5_Basecall_2D_000_2d 42  +
211000022279134 0   503 e8a9c6b8-bad2-4a7e-97d8-ca4acb34ff70_Basecall_2D_000_2d 69  -
211000022279134 24  353 e258783d-95a3-41f5-9ad5-bb12311dbaf4_Basecall_2D_000_2d 45  -
211000022279134 114 429 26601afb-581a-41df-b42b-b366148ea06f_Basecall_2D_000_2d 100 -
</code></pre>

<p>The bed file thus has 6 columns as for now: chromosome, start coordinate, end coordinate, read name, score, strand. This file was obtained from conversion of <code>MAF</code> format (as output of alignment of RNA-seq reads to reference genome, using <a href="http://last.cbrc.jp/" rel="noreferrer"><code>LAST</code></a>) converted to <code>SAM</code> using <a href="http://last.cbrc.jp/doc/maf-convert.html" rel="noreferrer"><code>maf-convert</code></a>, then to <code>BAM</code> using <a href="http://samtools.sourceforge.net/" rel="noreferrer"><code>samtools</code></a>, finally to <code>BED</code> using <a href="http://bedtools.readthedocs.io/en/latest/content/bedtools-suite.html" rel="noreferrer"><code>bedtools</code></a>. </p>

<p>The aim of my conversion is basically to convert <code>SAM</code> -> <code>GTF</code>, for <a href="https://bioinformatics.stackexchange.com/questions/2036/tools-to-reconcile-experimental-transcripts-with-reference-annotation">post-processing</a>. Since there is no straightforward way to do this, I am going through steps, the only way to do this in my knowledge is : <code>SAM</code> -> <code>BAM</code> -> <code>BED</code> -> <code>GFF3</code> -> <code>GTF</code> but for now I am stuck in the <code>BED</code> -> <code>GFF3</code> part. </p>

CC BY-SA 3.0
2017-08-08T10:00:43.817Z
There isn't necessarily a very meaningful way to do that. Can you post a few lines from your BED file? Also, what's the end goal?
Devon Ryan
CC BY-SA 3.0
2017-08-08T10:47:59.323Z
Yes, it would be helpful to see some of the BED. Is it BED12 or BED6, what does it represent? In GFF3 who have to say what your intervals represent.  No reason it can't be done though. Oh, and are you happy with code?
Ian Sudbery
CC BY-SA 3.0
2017-08-08T11:09:59.113Z
@DevonRyan I have edited the question, hopefully answers your comments.
aechchiki
CC BY-SA 3.0
2017-08-08T11:15:56.197Z
@AminaEchchiki While I could provide code (or you could just use the tool in Galaxy), I don't think the information from the SAM file is being accurately transmitted to BED in a way that's needed to produce a useful GFF3 or GTF file. I strongly recommend you write a tool to directly produce a GTF/GFF from either SAM or MAF (presuming none exist).
Devon Ryan
CC BY-SA 3.0
2017-08-08T11:29:15.323Z
if this is an organism that has splicing, your convsion to bed is unlikely to be accurate. I will post BAM -> GTF code and BED to GFF3, but let me know if your reads are spliced/
Ian Sudbery
CC BY-SA 3.0
2017-08-08T11:30:53.727Z
@IanSudbery yes my reads are spliced (D. melanogaster)
aechchiki
CC BY-SA 3.0
2017-08-08T11:35:11.413Z
Right, in which case you should generate your bed files with `bamtobed --bed12`, but really you should go direct from BAM to GFF/GTF.
Ian Sudbery
CC BY-SA 3.0
2017-08-08T11:36:09.087Z
@IanSudbery thanks for the tip, will do that
aechchiki
<software-recommendation><bed><format-conversion><gff3>
How to convert BED to GFF3
# How to convert BED to GFF3

(Asked by: username_0 on 2017-08-08)

I would like to convert a BED format to GFF3.
The only useful tool that I could find via a google search seems to be Galaxy, and I do not feel very comfortable with online tools, plus the webserver is currenlty under maintenance. 
Does anyone knows about a command-line tool that can handle this conversion?
Edit: here are some lines of my BED file: 
$ head -4 last_minion-r7_sort.bed
211000022278137 175 211 8e5d0959-7cdb-49cf-9298-94ed3b2aedb5_Basecall_2D_000_2d 42  +
211000022279134 0   503 e8a9c6b8-bad2-4a7e-97d8-ca4acb34ff70_Basecall_2D_000_2d 69  -
211000022279134 24  353 e258783d-95a3-41f5-9ad5-bb12311dbaf4_Basecall_2D_000_2d 45  -
211000022279134 114 429 26601afb-581a-41df-b42b-b366148ea06f_Basecall_2D_000_2d 100 -

The bed file thus has 6 columns as for now: chromosome, start coordinate, end coordinate, read name, score, strand. This file was obtained from conversion of MAF format (as output of alignment of RNA-seq reads to reference genome, using LAST) converted to SAM using maf-convert, then to BAM using samtools, finally to BED using bedtools. 
The aim of my conversion is basically to convert SAM -> GTF, for post-processing. Since there is no straightforward way to do this, I am going through steps, the only way to do this in my knowledge is : SAM -> BAM -> BED -> GFF3 -> GTF but for now I am stuck in the BED -> GFF3 part.

**Tags:** software-recommendation, bed, format-conversion, gff3
> **Comments:**
> **username_1**: There isn't necessarily a very meaningful way to do that. Can you post a few lines from your BED file? Also, what's the end goal?  
> **username_2**: Yes, it would be helpful to see some of the BED. Is it BED12 or BED6, what does it represent? In GFF3 who have to say what your intervals represent.  No reason it can't be done though. Oh, and are you happy with code?  
> **username_0**: @DevonRyan I have edited the question, hopefully answers your comments.  
> **username_1**: @AminaEchchiki While I could provide code (or you could just use the tool in Galaxy), I don't think the information from the SAM file is being accurately transmitted to BED in a way that's needed to produce a useful GFF3 or GTF file. I strongly recommend you write a tool to directly produce a GTF/GFF from either SAM or MAF (presuming none exist).  
> **username_2**: if this is an organism that has splicing, your convsion to bed is unlikely to be accurate. I will post BAM -> GTF code and BED to GFF3, but let me know if your reads are spliced/  
> **username_0**: @IanSudbery yes my reads are spliced (D. melanogaster)  
> **username_2**: Right, in which case you should generate your bed files with `bamtobed --bed12`, but really you should go direct from BAM to GFF/GTF.  
> **username_0**: @IanSudbery thanks for the tip, will do that  

---

## 7 answers

### Answer by username_8 on 2017-08-08. Score: 8 | Accepted answer

Galaxy has API and API-consuming libraries (such as BioBlend) that will allow you to interactively script against it without opening the graphical interface at all.

However you can also take almost any tool out of Galaxy and use it independently since everything is open source. The converter you mentioned is available as a Python script [here](https://github.com/galaxyproject/galaxy/blob/dev/tools/filters/bed_to_gff_converter.py) and the tool 'wrapper' which you can use to understand how to invoke the python script is [next to it](https://github.com/galaxyproject/galaxy/blob/dev/tools/filters/bed2gff.xml).


---

### Answer by username_2 on 2017-08-08. Score: 8

To answer the question as asked,  for people googling.
For BED6, in python:
#contigs.tsv contians chromosome names and lengths in two columns
for line in open("contigs.tsv"):
   fields = line.strip().split("\t")
   print fields[0], ".", "contig","1",str(fields[1]), ".", "+", ".", "ID=%s" % fields[0]

for line in open("my_bed_file.bed"):
   fields = line.strip().split("\t")

   # note: BED is 0-based, half-open, GFF is 1-based, closed
   start = str(int(fields[1]) + 1)
   print fields[0], "bed", "interval", fields[1], fields[2], fields[4], fields[5], ".", "ID=%s;parent=%s" % (fields[3], fields[0])

For bed12, in python:
#contigs.tsv contians chromosome names and lengths in two columns
for line in open("contigs.tsv"):
   fields = line.strip().split("\t")
   print fields[0], ".", "contig","1",str(fields[1]), ".", "+", ".", "ID=%s" % fields[0]

for line in open("my_bed12.bed"):

   fields = line.strip().split("\t")
   contig = fields[0]
   # note: BED is 0-based, half-open, GFF is 1-based, closed
   start= int(fields[1]) + 1)
   end=fields[2]
   name=fields[3]
   score=fields[4]
   strand=fields[5]
   print contig, "bed", "interval", str(start), end, score, strand, ".", "ID=%s;parent=%s" % (name, contig)

   block_starts = map(int,fields[11].split(","))
   block_sizes = map(int, fields[10].split(","))
   
   for (block, (bstart, blen)) in enumerate(zip(block_starts, block_sizes)):
      bend = start + bstart + blen
      print contig, "bed", "block", str(start + bstart), str(bend), score, strand, ".", "ID=%s_%i;parent=%s" %(name, block, name)


---

### Answer by username_2 on 2017-08-08. Score: 5

To convert BAM to GTF, which is the best way to get a file to compare with cuffcompare:
import pysam

bamfile=pysam.AlignmentFile("my_bam_file.bam")

for alignment in bamfile.fetch():

    if alignment.is_unmapped:
        continue

    contig = bamfile.get_reference_name(alignment.reference_id)
    name = alignment.query_name
    
    if alignment.is_reverse:
        strand = "-"
    else: 
        strand = "+"

    for start, end in alignment.getblocks():
        # note: BED is 0-based, half-open, GFF is 1-based, closed
        print contig, "BAM", "exon", str(start + 1), str(end), "0", strand, ".", 'gene_id "%s"; transcript_id "%s";' % (name, name)

NB, this will also work with a SAM file as long as it is headered.

> **Comments:**
> **username_0**: As a note for future googlers, if your bam file comes from a pipeline producing unmapped BAMs, the code as it is will return error `ValueError: file header is empty (mode='rb') - is it SAM/BAM format?`. As a workaround it is necessary to add options `check_header=False`, `check_sq=False` while reading the bam.    @IanSudbery  might be useful to add it as a comment to your code  
> **username_2**: @Amina Echchiki, this error is not because your BAM contains unmapped reads, but because your BAM has no header. BAMs without headers are not valid BAM files. I am surprised fetching the contig name worked if the file has no header, even if you set `check_header=False, check_sq=False` because it uses the header to do so.  

---

### Answer by username_3 on 2017-08-09. Score: 4

Bioconductor makes this so easy. It does the coordinate conversion on import.
library(rtracklayer)

## import the bed file
bed.ranges <- import.bed('regions.bed')

## export as a gff3 file
export.gff3(bed.ranges,'regions.gff3')

And people wonder why R is so popular for bioinformatics...
Also if needed, you could go straight from BAM file to gff3 in R as well.

> **Comments:**
> **username_2**: As long as you have enough memory to hold the whole bed in memory at once (not a given if it comes from a BAM) this is indeed an easy option.  

---

### Answer by username_4 on 2023-10-03. Score: 3

I recently developed [bed2gff](https://github.com/alejandrogzi/bed2gff) to quickly convert .bed files to a gff3 format, a tool written in Rust. Could be of help here!

> **Comments:**
> **username_5**: Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer).  

---

### Answer by username_6 on 2023-10-25. Score: 2

If anybody needs a simple bed to gff converter, simple in the sense that only takes a bed with a single type of feature, lets say peaks and translate it to GFF I recently wrote this, is Bash and as far as I know all the tools it uses should be present in most Linux / Mac operating systems.

<https://github.com/UBMI-IFC/bed2gff/tree/main>

It cannot deal, however with multi featured Bed files as it ignores everything from the 7th column and beyond.


---

### Answer by username_7 on 2023-10-26. Score: 0

You could also use `agat_convert_bed2gff`. `agat` is generally a very useful tool when needing to convert from / to / between gff formats. See here how to use it to convert from bed to gff. <https://agat.readthedocs.io/en/latest/tools/agat_convert_bed2gff.html>


---

