I am confused by a subtle difference in the cruzdb coordinates and UCSC coordinates. For those unfamiliar cruzdb is a python package for accessing the UCSC databases. Suppose I am interested in exon 3/7 for the gene TAF3. This exon extends from base pair 7963920-7965742 on chromosome 10. You can be sure of this by zooming in on the two ends of the exon in the UCSC genome browser:
However; cruzdb appears to agree with the start of the exon but is off by one base at the stop:
import cruzdb
from cruzdb import Genome
g = cruzdb.Genome('hg38')
# case 1 only picks up the cds which appears to be the exon range according to cruzdb
chromosome = 'chr10'
start = 7963920
stop = 7965741
gene = g.bin_query('refGene',chromosome,start,stop).all()
features = [x.features(start,stop) for x in gene]
print features
# case 2 also pick up the intron on the left
chromosome = 'chr10'
start = 7963919
stop = 7965741
gene = g.bin_query('refGene',chromosome,start,stop).all()
features = [x.features(start,stop) for x in gene]
print features
# case 3 also picks up the intron on the right but this is the exon range according to UCSC
chromosome = 'chr10'
start = 7963920
stop = 7965742
gene = g.bin_query('refGene',chromosome,start,stop).all()
features = [x.features(start,stop) for x in gene]
print features
I post this at the risk of looking really dumb, but I cant risk annotating hundreds of regions and be off by one base. Thanks!
2 answers
UCSC coordinates are 0-based and half-open internally (like cruzDB) but 1-based and closed in the html user interface.
I'm surprised this question has received little attention as I am quite convinced there is an inconsistency in the cruzdb coordinate system; running the following code should be convincing enough.
import cruzdb
from cruzdb import Genome
g = cruzdb.Genome('hg38')
#####################################################################
# first an example of the error on the negative strand
#####################################################################
# case 1: this query says the only features are intron
chromosome = 'chr9'
start = 35812101
stop = 35812102
gene = g.bin_query('refGene',chromosome,start,stop).all()
features = [x.features(start,stop) for x in gene]
print features
# case 2: this query says the features are intron and cds
# therefor we can conclude that 35812103 is the first base in the cds
chromosome = 'chr9'
start = 35812102
stop = 35812103
gene = g.bin_query('refGene',chromosome,start,stop).all()
features = [x.features(start,stop) for x in gene]
print features
# case 3: this query says the features are intron and cds which does
# not make since because we concluded that 35812103 was in the cds
chromosome = 'chr9'
start = 35812103
stop = 35812104
gene = g.bin_query('refGene',chromosome,start,stop).all()
features = [x.features(start,stop) for x in gene]
print features
#####################################################################
# an example of the error on the positive strand
#####################################################################
# case 1: both bases in the cds
chromosome = 'chr7'
start = 128074502
stop = 128074503
gene = g.bin_query('refGene',chromosome,start,stop).all()
features = [x.features(start,stop) for x in gene]
print features
# case 2: cds and intron - conclude 128074501 is intron
chromosome = 'chr7'
start = 128074501
stop = 128074502
gene = g.bin_query('refGene',chromosome,start,stop).all()
features = [x.features(start,stop) for x in gene]
print features
# case 3: cds and intron - inconsistent with the above
chromosome = 'chr7'
start = 128074500
stop = 128074501
gene = g.bin_query('refGene',chromosome,start,stop).all()
features = [x.features(start,stop) for x in gene]
print features
Log in to answer this question.
Update: for anyone that uses cruzdb you may want to look into this unsolved issue. I received this comment from the developer: