<h1>gxf2bed</h1>
<p>The fastest G{F,T}F-to-BED converter around the block!</p>
<p>translates</p>
<pre><code>chr27 gxf2bed gene 17266470 17285418 . + . gene_id &quot;ENSG00000151743&quot;;
chr27 gxf2bed transcript 17266470 17281218 . + . gene_id &quot;ENSG00000151743&quot;; transcript_id &quot;ENST00000541931.8&quot;;
chr27 gxf2bed exon 17266470 17266572 . + . gene_id &quot;ENSG00000151743&quot;; transcript_id &quot;ENST00000541931.8&quot;; exon_number &quot;1&quot;; exon_id &quot;ENST00000541931.8.1&quot;;
</code></pre>
<p>into</p>
<pre><code>chr27 17266469 17281218 ENST00000541931.8 1000 + 17266469 17281218 0,0,200 2 103,74, 0,14675,
</code></pre>
<p>before your eyes blink!</p>
<p>Converts</p>
<ul>
<li><em>Homo sapiens</em> GRCh38 GENCODE 44 (252,835 transcripts) in 3.34 seconds.</li>
<li><em>Mus musculus</em> GRCm39 GENCODE 44 (149,547 transcritps) in 2.11 seconds.</li>
<li><em>Canis lupus familiaris</em> ROS_Cfam_1.0 Ensembl 110 (55,335 transcripts) in 0.99 seconds.</li>
<li><em>Gallus galus</em> bGalGal1 Ensembl 110 (72,689 transcripts) in 1.14 seconds.</li>
</ul>
<h2>Usage</h2>
<pre class="lang-rust prettyprint-override"><code>Usage: gxf2bed[EXE] --input/-i &lt;GTF/GFF&gt; --output/-o &lt;BED&gt;
 
Arguments:
    --input/-i &lt;GTF/GFF&gt;: a .gtf/.gff file
    --output/-o &lt;BED&gt;: path to output .bed file

Options:
    --help: print help
    --version: print version
    --threads/-t: number of threads (default: max ncpus)
</code></pre>
<h2>Installation</h2>
<p>to install gxf2bed on your system follow this steps:</p>
<ol>
<li>get rust: <code>curl https://sh.rustup.rs -sSf | sh</code> on unix, or go <a href="https://www.rust-lang.org/tools/install" rel="nofollow noreferrer">here</a> for other options</li>
<li>run <code>cargo install gxf2bed</code> (make sure <code>~/.cargo/bin</code> is in your <code>$PATH</code> before running it)</li>
<li>use <code>gxf2bed</code> with the required arguments</li>
<li>enjoy!</li>
</ol>
<h2>Build</h2>
<p>to build gxf2bed from this repo, do:</p>
<ol>
<li>get rust (as described above)</li>
<li>run <code>git clone https://github.com/alejandrogzi/gxf2bed.git &amp;&amp; cd gxf2bed</code></li>
<li>run <code>cargo run --release -- -i &lt;GTF/GFF&gt; -o &lt;BED&gt;</code></li>
</ol>
<h2>Container image</h2>
<p>to build the development container image:</p>
<ol>
<li>run <code>git clone https://github.com/alejandrogzi/gxf2bed.git &amp;&amp; cd gxf2bed</code></li>
<li>initialize docker with <code>start docker</code> or <code>systemctl start docker</code></li>
<li>build the image <code>docker image build --tag gxf2bed .</code></li>
<li>run <code>docker run --rm -v &quot;[dir_where_your_gtf_is]:/dir&quot; gxf2bed -i /dir/&lt;GTF/GFF&gt; -o /dir/&lt;BED&gt;</code></li>
</ol>
<h2>Conda</h2>
<p>to use gxf2bed through Conda just:</p>
<ol>
<li><code>conda install gxf2bed -c bioconda</code> or <code>conda create -n gxf2bed -c bioconda gxf2bed</code></li>
</ol>
<h2>Benchmark + FAQ</h2>
<p><a href="https://i.sstatic.net/vzjos.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/vzjos.jpg" alt="enter image description here" /></a></p>
<p>If you google &quot;gtf to bed&quot; or &quot;gff to bed&quot; you'll find some posts about recommended tools. Part of these tools are already deprecated or too difficult to run (even in Linux), due to poor maintenance. This project was conceived to provide an easy way to convert GTF/GFF files to BED structures and finish a set of high-performance converters between gene model formats in Rust (bed2gtf, bed2gff and now gxf2bed).</p>
<p>To test the efficiency of gxf2bed, I took 4 GTF/GFF-to-BED converters and ran them with the current GRCh38 GENCODE annotation (v.44), that has ~250,000 transcripts [the values showed here are the mean of 5 consecutive runs]. Briefly, the competitors are:</p>
<ul>
<li>UCSC's utils: <code>gtfToGenePred | genePredToBed</code> &amp; <code>gffToGenePred | genePredToBed</code> (taken from <a href="https://hgdownload.soe.ucsc.edu/admin/exe/linux.x86_64/" rel="nofollow noreferrer">here</a>)</li>
<li>Signal &amp; Brown: <code>gtf2bed.py</code> &amp; <code>gff32gtf.py &amp;&amp; gtf2bed.py</code> (taken from <a href="https://github.com/signalbash/how_are_we_stranded_here/tree/master/how_are_we_stranded_here" rel="nofollow noreferrer">here</a>)</li>
<li>ea-utils: <code>gtf2bed.pl</code> &amp; <code>gff2gtf.pl | gtf2bed.pl</code> (taken from <a href="https://github.com/ExpressionAnalysis/ea-utils/tree/master/clipper" rel="nofollow noreferrer">here</a>)</li>
<li>BEDOPS: <code>gtf2bed</code> &amp;  <code>gtf2bed</code> (taken from <a href="https://github.com/bedops/bedops/tree/master/applications/bed/conversion/src/wrappers" rel="nofollow noreferrer">here</a>)</li>
</ul>
<p>Besides the easy way to make <code>gxf2bed</code> run and the GFF-GTF channel that allows centralize both in a single converter, this tool showed a significant difference in computation time against the other tools in each one of the two formats. Even using a combination of different number of threads, times were practically the same 3.5s +/- 0.4s and the differences were maintained. Is important to note that GFF3 files took a lot more time than its GTF counterpart. This could be due to the need of chaining two different programs 1) GFF-to-GTF and 2) GTF-to-BED.</p>
<p>Taken together, <code>gxf2bed</code> offers an easier and faster way to convert GTF/GFF files to BED files. This tool could save you at least x2-3 times the time you used to spend using other tools to convert GTF files and x5 times if you want to convert GFF3 files!</p>
<hr />
<p>Disclaimer: I am the author of the gxf2bed tool.</p>

CC BY-SA 4.0
2024-02-06T22:54:54.287Z
How do you deal with regular GTFs that have a variable number of key-value pairs in the ninth column?
Ram RS
CC BY-SA 4.0
2024-02-06T23:17:43.330Z
It does not matter how many number of key-value pairs are in the ninth column. The only thing this tool assumes is that at least "gene_id" and "transcript_id" should be present in each line. This is nothing crazy to ask since is very common practice.
Alejandro Gonzales-Irribarren
CC BY-SA 4.0
2024-02-07T10:12:33.617Z
So what options did you use to make the conversion you show here? Why were the gene and exon lines ignored and only the transcript kept?
terdon
CC BY-SA 4.0
2024-02-07T15:26:07.557Z
Exactly what @terdon says - there doesn't seem to be any way to pick the features to extract. Is your tool faster than a simple `awk` in that case? And are you sure you're comparing apples to apples when your tool makes these assumptions?
Ram RS
CC BY-SA 4.0
2024-02-07T23:08:30.720Z
Exon lines are not ignored. The tool basically parses a gtf and extracts only the needed features to build a BED12 (which is basically a transcript-based annotation file). The results of gxf2bed are exactly the same obtained by UCSC's binaries and the other tools as well. gxf2bed even goes a step further sorting the BED12 by chr and pos, which does not seem to be accurate for some of the tools evaluated.

If you are confident that an awk command could build a correct BED12, wonderful! This tool provides another opportunity to perform this conversion in less time that the available tools now.
Alejandro Gonzales-Irribarren
CC BY-SA 4.0
2024-02-07T23:14:23.747Z
If you are skeptical about how the results of gxf2bed, you can try it, though. Just run the command as explained in this post and compare the results yourself. To elaborate a little bit more on the last lines of the past comment: re-writting this functionality in Rust now allows 1) a more straightforward installation, 2) faster times, 3) easy pipeline implementation, 4) better performance. All this is open source, so feel free to review the code if you still do not feel that comfortable! :)
Alejandro Gonzales-Irribarren
CC BY-SA 4.0
2024-02-08T15:11:19.480Z
"a BED12 (which is basically a transcript-based annotation file)" Please show your source for this information. BED files are lists of contigs+positions with optional annotations, they could be genes, transcripts or even random nucleotides. You are assuming the transcript part.
Ram RS
CC BY-SA 4.0
2024-02-08T15:17:41.207Z
gtf2bed, for example, accepts an `attribute_key` and is thus flexible. gtf2genePred does assume gene as the feature and it does provide some flexibility as to the identifier within that constraint, but it calls itself genePred, not featurePred. Sure, `gtf2bed.pl` seems to default to `transcript_id` but that's the only tool you can compare to. I appreciate your rust-based contributions to the field but please be more mindful with your claims.
Ram RS
CC BY-SA 4.0
2024-02-06T22:09:42.633Z
2024-02-07T10:10:26.480Z
2024-02-07T10:10:26.480Z
Alejandro Gonzales-Irribarren
<p>Given a GTF/GFF3 annotation file, what is the fastest way to convert it into a BED file?</p>

CC BY-SA 4.0
2024-02-06T23:50:48.927Z
Hi @AlejandroGonzalesIrribarren. Thanks for your response. For future reference please provide some context to this question, e.g. the genome (humans), computer resources and what have your tried? Again thanks for posting back. Conda is cool for getting stuff working quickly, but not necessarily performant .... Easybuild is much better in this particularly question, i.e. fastest.
M__
CC BY-SA 4.0
2024-02-07T10:06:45.140Z
Yes, please at least provide example input and expected output so the question can be clear.
terdon
<bed><format-conversion><gtf><gff>
Fastest way to convert GTF or GFF file to a BED file?
# Fastest way to convert GTF or GFF file to a BED file?

(Asked by: username_0 on 2024-02-06)

Given a GTF/GFF3 annotation file, what is the fastest way to convert it into a BED file?

**Tags:** bed, format-conversion, gtf, gff
> **Comments:**
> **username_1**: Hi @AlejandroGonzalesIrribarren. Thanks for your response. For future reference please provide some context to this question, e.g. the genome (humans), computer resources and what have your tried? Again thanks for posting back. Conda is cool for getting stuff working quickly, but not necessarily performant .... Easybuild is much better in this particularly question, i.e. fastest.  
> **username_2**: Yes, please at least provide example input and expected output so the question can be clear.  

---

## 1 answers

### Answer by username_0 on 2024-02-06. Score: 3 | Accepted answer

gxf2bed
The fastest G{F,T}F-to-BED converter around the block!
translates
chr27 gxf2bed gene 17266470 17285418 . + . gene_id "ENSG00000151743";
chr27 gxf2bed transcript 17266470 17281218 . + . gene_id "ENSG00000151743"; transcript_id "ENST00000541931.8";
chr27 gxf2bed exon 17266470 17266572 . + . gene_id "ENSG00000151743"; transcript_id "ENST00000541931.8"; exon_number "1"; exon_id "ENST00000541931.8.1";

into
chr27 17266469 17281218 ENST00000541931.8 1000 + 17266469 17281218 0,0,200 2 103,74, 0,14675,

before your eyes blink!
Converts

Homo sapiens GRCh38 GENCODE 44 (252,835 transcripts) in 3.34 seconds.
Mus musculus GRCm39 GENCODE 44 (149,547 transcritps) in 2.11 seconds.
Canis lupus familiaris ROS_Cfam_1.0 Ensembl 110 (55,335 transcripts) in 0.99 seconds.
Gallus galus bGalGal1 Ensembl 110 (72,689 transcripts) in 1.14 seconds.

Usage
Usage: gxf2bed[EXE] --input/-i  --output/-o 
 
Arguments:
    --input/-i : a .gtf/.gff file
    --output/-o : path to output .bed file

Options:
    --help: print help
    --version: print version
    --threads/-t: number of threads (default: max ncpus)

Installation
to install gxf2bed on your system follow this steps:

get rust: curl https://sh.rustup.rs -sSf | sh on unix, or go here for other options
run cargo install gxf2bed (make sure ~/.cargo/bin is in your $PATH before running it)
use gxf2bed with the required arguments
enjoy!

Build
to build gxf2bed from this repo, do:

get rust (as described above)
run git clone https://github.com/alejandrogzi/gxf2bed.git && cd gxf2bed
run cargo run --release -- -i  -o 

Container image
to build the development container image:

run git clone https://github.com/alejandrogzi/gxf2bed.git && cd gxf2bed
initialize docker with start docker or systemctl start docker
build the image docker image build --tag gxf2bed .
run docker run --rm -v "[dir_where_your_gtf_is]:/dir" gxf2bed -i /dir/ -o /dir/

Conda
to use gxf2bed through Conda just:

conda install gxf2bed -c bioconda or conda create -n gxf2bed -c bioconda gxf2bed

Benchmark + FAQ

If you google "gtf to bed" or "gff to bed" you'll find some posts about recommended tools. Part of these tools are already deprecated or too difficult to run (even in Linux), due to poor maintenance. This project was conceived to provide an easy way to convert GTF/GFF files to BED structures and finish a set of high-performance converters between gene model formats in Rust (bed2gtf, bed2gff and now gxf2bed).
To test the efficiency of gxf2bed, I took 4 GTF/GFF-to-BED converters and ran them with the current GRCh38 GENCODE annotation (v.44), that has ~250,000 transcripts [the values showed here are the mean of 5 consecutive runs]. Briefly, the competitors are:

UCSC's utils: gtfToGenePred | genePredToBed & gffToGenePred | genePredToBed (taken from here)
Signal & Brown: gtf2bed.py & gff32gtf.py && gtf2bed.py (taken from here)
ea-utils: gtf2bed.pl & gff2gtf.pl | gtf2bed.pl (taken from here)
BEDOPS: gtf2bed &  gtf2bed (taken from here)

Besides the easy way to make gxf2bed run and the GFF-GTF channel that allows centralize both in a single converter, this tool showed a significant difference in computation time against the other tools in each one of the two formats. Even using a combination of different number of threads, times were practically the same 3.5s +/- 0.4s and the differences were maintained. Is important to note that GFF3 files took a lot more time than its GTF counterpart. This could be due to the need of chaining two different programs 1) GFF-to-GTF and 2) GTF-to-BED.
Taken together, gxf2bed offers an easier and faster way to convert GTF/GFF files to BED files. This tool could save you at least x2-3 times the time you used to spend using other tools to convert GTF files and x5 times if you want to convert GFF3 files!

Disclaimer: I am the author of the gxf2bed tool.

> **Comments:**
> **username_3**: How do you deal with regular GTFs that have a variable number of key-value pairs in the ninth column?  
> **username_0**: It does not matter how many number of key-value pairs are in the ninth column. The only thing this tool assumes is that at least "gene_id" and "transcript_id" should be present in each line. This is nothing crazy to ask since is very common practice.  
> **username_2**: So what options did you use to make the conversion you show here? Why were the gene and exon lines ignored and only the transcript kept?  
> **username_3**: Exactly what @terdon says - there doesn't seem to be any way to pick the features to extract. Is your tool faster than a simple `awk` in that case? And are you sure you're comparing apples to apples when your tool makes these assumptions?  
> **username_0**: Exon lines are not ignored. The tool basically parses a gtf and extracts only the needed features to build a BED12 (which is basically a transcript-based annotation file). The results of gxf2bed are exactly the same obtained by UCSC's binaries and the other tools as well. gxf2bed even goes a step further sorting the BED12 by chr and pos, which does not seem to be accurate for some of the tools evaluated.  If you are confident that an awk command could build a correct BED12, wonderful! This tool provides another opportunity to perform this conversion in less time that the available tools now.  
> **username_0**: If you are skeptical about how the results of gxf2bed, you can try it, though. Just run the command as explained in this post and compare the results yourself. To elaborate a little bit more on the last lines of the past comment: re-writting this functionality in Rust now allows 1) a more straightforward installation, 2) faster times, 3) easy pipeline implementation, 4) better performance. All this is open source, so feel free to review the code if you still do not feel that comfortable! :)  
> **username_3**: "a BED12 (which is basically a transcript-based annotation file)" Please show your source for this information. BED files are lists of contigs+positions with optional annotations, they could be genes, transcripts or even random nucleotides. You are assuming the transcript part.  
> **username_3**: gtf2bed, for example, accepts an `attribute_key` and is thus flexible. gtf2genePred does assume gene as the feature and it does provide some flexibility as to the identifier within that constraint, but it calls itself genePred, not featurePred. Sure, `gtf2bed.pl` seems to default to `transcript_id` but that's the only tool you can compare to. I appreciate your rust-based contributions to the field but please be more mindful with your claims.  

---

