bio-ensembl-rest 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](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
|