bio-ensembl-rest 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +10 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +20 -0
- data/README.md +51 -0
- data/Rakefile +45 -0
- data/lib/bio-ensembl-rest.rb +19 -0
- data/lib/bio-ensembl-rest/comparative-genomics.rb +117 -0
- data/lib/bio-ensembl-rest/cross-reference.rb +55 -0
- data/lib/bio-ensembl-rest/ensembl-rest-main.rb +108 -0
- data/lib/bio-ensembl-rest/features.rb +46 -0
- data/lib/bio-ensembl-rest/information.rb +133 -0
- data/lib/bio-ensembl-rest/lookup.rb +20 -0
- data/lib/bio-ensembl-rest/mapping.rb +55 -0
- data/lib/bio-ensembl-rest/ontologies.rb +68 -0
- data/lib/bio-ensembl-rest/sequence.rb +37 -0
- data/lib/bio-ensembl-rest/taxonomy.rb +30 -0
- data/lib/bio-ensembl-rest/variation.rb +37 -0
- data/test/helper.rb +20 -0
- data/test/test-comparative-genomics.rb +159 -0
- data/test/test-cross-reference.rb +81 -0
- data/test/test-features.rb +76 -0
- data/test/test-information.rb +131 -0
- data/test/test-lookup.rb +45 -0
- data/test/test-mapping.rb +105 -0
- data/test/test-ontologies.rb +116 -0
- data/test/test-sequence.rb +110 -0
- data/test/test-taxonomy.rb +58 -0
- data/test/test-variation.rb +62 -0
- metadata +157 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e112aedd2a2a78c4f241301731d39e2a3f094942
|
4
|
+
data.tar.gz: 483b616adf1743cac1b35088b59fa4d68e85e915
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7fa0521d7923a7b9aafe1427258037a27b3794c736f36b9c0bec00d2b68b051b22195abbb3bec34307735a8274fcd9e58bfbb55b02ca2db745f76748f19dd90c
|
7
|
+
data.tar.gz: f91ecf17d9f0a267851e936efa1d4522160d54b56ba892ef1c2ad7f659f8fcdd1e1ed0a1301cc464f519566eedaf1c5894292791acc31144116dc68caf4cb07f
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
gem "bio", ">= 1.4.3"
|
7
|
+
gem "libxml-ruby", ">= 2" if RUBY_PLATFORM != 'java'
|
8
|
+
|
9
|
+
# Add dependencies to develop your gem here.
|
10
|
+
# Include everything needed to run rake, tests, features, etc.
|
11
|
+
group :development do
|
12
|
+
gem "shoulda", ">= 0"
|
13
|
+
gem "rdoc", "~> 3.12"
|
14
|
+
gem "bundler", "~> 1.3.5"
|
15
|
+
gem "jeweler", "~> 1.8.4"
|
16
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Alberto Donizetti
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
Ensembl Rest
|
2
|
+
================
|
3
|
+
|
4
|
+
A Ruby library for the RESTful Ensembl API.
|
5
|
+
|
6
|
+
[![Build Status](https://api.travis-ci.org/ALTree/ensembl-rest.png)](https://travis-ci.org/ALTree/ensembl-rest)
|
7
|
+
|
8
|
+
Obtaining
|
9
|
+
---------
|
10
|
+
|
11
|
+
```sh
|
12
|
+
gem install ensembl-rest
|
13
|
+
```
|
14
|
+
for the repository:
|
15
|
+
```sh
|
16
|
+
git clone git://github.com/ALTree/bio-ensembl-rest
|
17
|
+
```
|
18
|
+
|
19
|
+
Usage
|
20
|
+
-----
|
21
|
+
|
22
|
+
Each of the endpoint group listed in the Ensembl REST [documentation](http://beta.rest.ensembl.org/) has its own ruby module with the same name (except for Ontologies and Taxonomy, wich is split in two modules).
|
23
|
+
|
24
|
+
**A full list of modules and methods, with documentation, is available [here](https://github.com/ALTree/bio-ensembl-rest/wiki/modules-and-methods-list)**.
|
25
|
+
|
26
|
+
To make a request to an endpoint, use the appropriate method in the relative module. For example, to access the `sequence/region/:species/:region ` endpoint in the Sequence group, use the `sequence_region` method in the `Sequence` module:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require 'bio-ensembl-rest'
|
30
|
+
include EnsemblRest
|
31
|
+
|
32
|
+
EnsemblRest.connect_db # connect to database
|
33
|
+
puts Sequence.sequence_region 'Homo sapiens', 'X:1000000..1000025:1'
|
34
|
+
|
35
|
+
# GAAACAGCTACTTGGAAGGCTGAAGC
|
36
|
+
```
|
37
|
+
|
38
|
+
Documentation
|
39
|
+
-----------
|
40
|
+
See the [ensembl-rest wiki page](https://github.com/ALTree/bio-ensembl-rest/wiki).
|
41
|
+
|
42
|
+
## Known issues
|
43
|
+
|
44
|
+
### version-specific issues
|
45
|
+
|
46
|
+
* On jruby-1.7, methods in the ComparativeGenomics module fail if called with `response: ruby`,
|
47
|
+
due to a C dependency in the 'bio' gem.
|
48
|
+
|
49
|
+
* On rubinius, methods in the ComparativeGenomics module fail if called with `response: ruby`,
|
50
|
+
due to a C dependency in the 'bio' gem.
|
51
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
gem.name = "bio-ensembl-rest"
|
17
|
+
gem.version = '0.1.0'
|
18
|
+
gem.homepage = "http://github.com/ALTree/bio-ensembl-rest"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = "Ruby Ensembl REST api"
|
21
|
+
gem.description = "A Ruby library for the RESTful Ensembl API."
|
22
|
+
gem.email = "alb.donizetti@gmail.com"
|
23
|
+
gem.authors = ["Alberto Donizetti"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.test_files = FileList['test/test-*.rb']
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
task :default => :test
|
36
|
+
|
37
|
+
require 'rdoc/task'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "ensembl-rest #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Please require your code below, respecting the naming conventions in the
|
2
|
+
# bioruby directory tree.
|
3
|
+
#
|
4
|
+
# For example, say you have a plugin named bio-plugin, the only uncommented
|
5
|
+
# line in this file would be
|
6
|
+
#
|
7
|
+
# require 'bio/bio-plugin/plugin'
|
8
|
+
#
|
9
|
+
# In this file only require other files. Avoid other source code.
|
10
|
+
|
11
|
+
require 'bio'
|
12
|
+
require 'net/http'
|
13
|
+
require 'open-uri'
|
14
|
+
require 'json'
|
15
|
+
|
16
|
+
Dir[File.dirname(__FILE__) + '/bio-ensembl-rest/*.rb'].each do |file|
|
17
|
+
require file
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module EnsemblRest
|
2
|
+
module ComparativeGenomics
|
3
|
+
|
4
|
+
##
|
5
|
+
# Retrieves Gene Tree dumps for a given Gene Tree stable identifier
|
6
|
+
def self.genetree_id(id, opts = {})
|
7
|
+
return _genetree_generic id, 'id', opts
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Retrieves the Gene Tree that contains the given stable identifier
|
12
|
+
def self.genetree_member_id(id, opts = {})
|
13
|
+
return _genetree_generic id, 'member', opts
|
14
|
+
end
|
15
|
+
|
16
|
+
# generic method used by genetree_id and genetree_member_id
|
17
|
+
def self._genetree_generic(id, type, opts = {}) # :nodoc:
|
18
|
+
opts = EnsemblRest.parse_options opts
|
19
|
+
url = type == 'id' ? "/genetree/id/#{id}" : "/genetree/member/id/#{id}"
|
20
|
+
path = EnsemblRest.build_path url, opts
|
21
|
+
|
22
|
+
if opts['content-type'] == 'ruby'
|
23
|
+
plain_opts = opts.clone
|
24
|
+
plain_opts['content-type'] = 'text/x-phyloxml+xml'
|
25
|
+
return Bio::PhyloXML::Parser.new _genetree_generic id, type, plain_opts
|
26
|
+
end
|
27
|
+
|
28
|
+
return EnsemblRest.fetch_data path, opts, 'compara'
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
##
|
33
|
+
# Retrieves a Gene Tree containing the Gene identified by the given symbol
|
34
|
+
def self.genetree_member_symbol(species, symbol, opts = {})
|
35
|
+
opts = EnsemblRest.parse_options opts
|
36
|
+
path = EnsemblRest.build_path "/genetree/member/symbol/#{species}/#{symbol}", opts
|
37
|
+
|
38
|
+
if opts['content-type'] == 'ruby'
|
39
|
+
plain_opts = opts.clone
|
40
|
+
plain_opts['content-type'] = 'text/x-phyloxml+xml'
|
41
|
+
return Bio::PhyloXML::Parser.new genetree_member_symbol(species, symbol, plain_opts)
|
42
|
+
end
|
43
|
+
|
44
|
+
return EnsemblRest.fetch_data path, opts, 'compara'
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
##
|
49
|
+
# Retrieves homology information by ensembl gene id
|
50
|
+
def self.homology_id(id, opts = {})
|
51
|
+
opts = EnsemblRest.parse_options opts
|
52
|
+
path = EnsemblRest.build_path "/homology/id/#{id}", opts
|
53
|
+
|
54
|
+
if opts['content-type'] == 'ruby'
|
55
|
+
plain_opts = opts.clone
|
56
|
+
plain_opts['content-type'] = 'application/json'
|
57
|
+
data = JSON.parse ComparativeGenomics.homology_id id, plain_opts
|
58
|
+
return build_homology_class data
|
59
|
+
end
|
60
|
+
|
61
|
+
return EnsemblRest.fetch_data path, opts, 'compara'
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
##
|
66
|
+
# Retrieves homology information by symbol
|
67
|
+
def self.homology_symbol(species, symbol, opts = {})
|
68
|
+
opts = EnsemblRest.parse_options opts
|
69
|
+
path = EnsemblRest.build_path "/homology/symbol/#{species}/#{symbol}", opts
|
70
|
+
|
71
|
+
if opts['content-type'] == 'ruby'
|
72
|
+
plain_opts = opts.clone
|
73
|
+
plain_opts['content-type'] = 'application/json'
|
74
|
+
data = JSON.parse ComparativeGenomics.homology_symbol species, symbol, plain_opts
|
75
|
+
return build_homology_class data
|
76
|
+
end
|
77
|
+
|
78
|
+
return EnsemblRest.fetch_data path, opts, 'compara'
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# here we define the Homology class
|
84
|
+
Object.const_set("Homology", Class.new)
|
85
|
+
|
86
|
+
def self.build_homology_class(json_data) # :nodoc:
|
87
|
+
# extract the homologies list (homology = ruby hash obj)
|
88
|
+
homologies_data = json_data['data'][0]['homologies'] # this is a list of hashes
|
89
|
+
|
90
|
+
# retrieve homology keys to make a list of methods
|
91
|
+
homology_methods = []
|
92
|
+
homologies_data.first.each { |k, _| homology_methods << k.to_sym }
|
93
|
+
|
94
|
+
# we define an attr_accessor for each symbol in homology_methods
|
95
|
+
# and a 'bio_methods' attribute with all the newly defined methods
|
96
|
+
homology_methods.each { |k, _| Homology.class_eval "attr_accessor :#{k}" }
|
97
|
+
Homology.class_eval "attr_accessor :bio_methods"
|
98
|
+
|
99
|
+
# we will return a list of homology objects
|
100
|
+
homologies = []
|
101
|
+
|
102
|
+
# let's build the list
|
103
|
+
homologies_data.each do |hom| # cycle over the homologies we were given
|
104
|
+
h = Homology.new # we instantiate an Homology obj
|
105
|
+
hom.each do |k, v| # for each key,value in the homology hash
|
106
|
+
h.send "#{k}=".to_sym, v # we use the 'key=' method to set 'value'
|
107
|
+
end
|
108
|
+
h.send :bio_methods=, homology_methods # set the bio_methods param
|
109
|
+
homologies << h # add the obj to the list to be returned
|
110
|
+
end
|
111
|
+
|
112
|
+
return homologies
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module EnsemblRest
|
2
|
+
module CrossReference
|
3
|
+
|
4
|
+
##
|
5
|
+
# Perform lookups of Ensembl Identifiers and retrieve their external cross
|
6
|
+
# references in other databases
|
7
|
+
def self.xrefs_id(id, opts = {})
|
8
|
+
opts = EnsemblRest.parse_options opts
|
9
|
+
path = EnsemblRest.build_path "/xrefs/id/#{id}", opts
|
10
|
+
|
11
|
+
if opts['content-type'] == 'ruby'
|
12
|
+
plain_opts = opts.clone
|
13
|
+
plain_opts['content-type'] = 'application/json'
|
14
|
+
return JSON.parse xrefs_id id, plain_opts
|
15
|
+
end
|
16
|
+
|
17
|
+
return EnsemblRest.fetch_data path, opts, 'crossreference'
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
##
|
22
|
+
# Performs a lookup based upon the primary accession or display label of
|
23
|
+
# an external reference and returning the information we hold about the entry
|
24
|
+
def self.xrefs_name(species, name, opts = {})
|
25
|
+
opts = EnsemblRest.parse_options opts
|
26
|
+
path = EnsemblRest.build_path "/xrefs/name/#{species}/#{name}", opts
|
27
|
+
|
28
|
+
if opts['content-type'] == 'ruby'
|
29
|
+
plain_opts = opts.clone
|
30
|
+
plain_opts['content-type'] = 'application/json'
|
31
|
+
return JSON.parse xrefs_name species, name, plain_opts
|
32
|
+
end
|
33
|
+
|
34
|
+
return EnsemblRest.fetch_data path, opts, 'crossreference'
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
##
|
39
|
+
# Looks up an external symbol and returns all Ensembl objects linked to it
|
40
|
+
def self.xrefs_symbol(species, symbol, opts = {})
|
41
|
+
opts = EnsemblRest.parse_options opts
|
42
|
+
path = EnsemblRest.build_path "/xrefs/symbol/#{species}/#{symbol}", opts
|
43
|
+
|
44
|
+
if opts['content-type'] == 'ruby'
|
45
|
+
plain_opts = opts.clone
|
46
|
+
plain_opts['content-type'] = 'application/json'
|
47
|
+
return JSON.parse xrefs_symbol species, symbol, plain_opts
|
48
|
+
end
|
49
|
+
|
50
|
+
return EnsemblRest.fetch_data path, opts, 'crossreference'
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module EnsemblRest
|
2
|
+
## start HTTP database connection ##
|
3
|
+
|
4
|
+
def self.connect_db
|
5
|
+
$SERVER = URI.parse 'http://beta.rest.ensembl.org'
|
6
|
+
$HTTP_CONNECTION = Net::HTTP.new($SERVER.host, $SERVER.port)
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
## parse options stuff ##
|
11
|
+
def self.parse_options(opts) # :nodoc:
|
12
|
+
parsed_opts = {}
|
13
|
+
opts.each {|k, v| parsed_opts[k.to_s] = v}
|
14
|
+
|
15
|
+
parse_format parsed_opts
|
16
|
+
parse_true_false parsed_opts
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.parse_true_false(opts) # :nodoc:
|
20
|
+
opts.each do |k, v|
|
21
|
+
if v.instance_of?(TrueClass)
|
22
|
+
opts[k] = 1
|
23
|
+
elsif v.instance_of?(FalseClass)
|
24
|
+
opts[k] = 0
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.parse_format(opts) # :nodoc:
|
30
|
+
supported_formats = {
|
31
|
+
'text' => 'text/plain',
|
32
|
+
'fasta' => 'text/x-fasta',
|
33
|
+
'gff3' => 'ext/x-gff3',
|
34
|
+
'json' => 'application/json',
|
35
|
+
'msgpack' => 'application/x-msgpack',
|
36
|
+
'nh' => 'text/x-nh',
|
37
|
+
'seqxml' => 'text/x-seqxml+xml',
|
38
|
+
'sereal' => 'application/x-sereal',
|
39
|
+
'phyloxml' => 'text/x-phyloxml+xml',
|
40
|
+
'xml' => 'text/xml',
|
41
|
+
'yaml' => 'text/x-yaml'
|
42
|
+
}
|
43
|
+
if opts.has_key?('response')
|
44
|
+
req = opts['response']
|
45
|
+
if supported_formats[req]
|
46
|
+
opts['content-type'] = supported_formats[req]
|
47
|
+
else
|
48
|
+
opts['content-type'] = req
|
49
|
+
end
|
50
|
+
opts.delete 'response'
|
51
|
+
end
|
52
|
+
opts
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
## HTTP request stuff ##
|
57
|
+
|
58
|
+
def self.build_path(home, opts) # :nodoc:
|
59
|
+
path = home + '?'
|
60
|
+
opts.each { |k,v| path << "#{k}=#{v};" if k != 'content-type' }
|
61
|
+
path[-1] = '' if not opts
|
62
|
+
URI::encode path
|
63
|
+
end
|
64
|
+
|
65
|
+
# TODO: add tests to check if this default stuff is ok
|
66
|
+
def self.fetch_data(path, opts, mod) # :nodoc:
|
67
|
+
# what we should set as content-type in the header
|
68
|
+
# to keep ensembl happy when the the user does not
|
69
|
+
# use the format parameter to set the return type
|
70
|
+
default_types = {
|
71
|
+
'sequence' => 'text/plain',
|
72
|
+
'compara' => 'text/xml',
|
73
|
+
'crossreference' => 'application/json',
|
74
|
+
'features' => 'application/json',
|
75
|
+
'information' => 'application/json',
|
76
|
+
'lookup' => 'application/json',
|
77
|
+
'mapping' => 'application/json',
|
78
|
+
'ontologies' => 'application/json',
|
79
|
+
'taxonomy' => 'application/json',
|
80
|
+
'variation' => 'application/json'
|
81
|
+
}
|
82
|
+
request = Net::HTTP::Get.new path
|
83
|
+
request.content_type = opts['content-type'] || default_types[mod]
|
84
|
+
response = $HTTP_CONNECTION.request request
|
85
|
+
return check_response response
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.check_response(response) # :nodoc:
|
89
|
+
case response.code
|
90
|
+
when '200'
|
91
|
+
return response.body
|
92
|
+
when '400'
|
93
|
+
raise 'Bad request: ' + response.body
|
94
|
+
when '404'
|
95
|
+
raise 'Not Found'
|
96
|
+
when '415'
|
97
|
+
raise 'Unsupported Media Type'
|
98
|
+
when '429'
|
99
|
+
raise 'Too many requests'
|
100
|
+
when '503'
|
101
|
+
raise 'Service Unavailable'
|
102
|
+
else
|
103
|
+
raise "Bad response code: #{response.code}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
end
|