genomer 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +45 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +23 -0
- data/Rakefile +23 -0
- data/bin/genomer +18 -0
- data/cucumber.yml +2 -0
- data/features/api/annotation_ids.feature +152 -0
- data/features/api/annotation_location.feature +269 -0
- data/features/api/scaffold.feature +38 -0
- data/features/cli/create.feature +19 -0
- data/features/cli/error.feature +17 -0
- data/features/cli/help.feature +48 -0
- data/features/cli/man.feature +71 -0
- data/features/cli/plugins.feature +34 -0
- data/features/step_definitions/genomer_steps.rb +10 -0
- data/features/support/env.rb +13 -0
- data/genomer-plugin-simple/genomer-plugin-simple.gemspec +18 -0
- data/genomer-plugin-simple/lib/genomer-plugin-simple.rb +19 -0
- data/genomer-plugin-simple/man/genomer-simple-subcommand.ronn +6 -0
- data/genomer-plugin-simple/man/genomer-simple.ronn +6 -0
- data/genomer.gemspec +39 -0
- data/lib/genomer.rb +6 -0
- data/lib/genomer/error.rb +4 -0
- data/lib/genomer/plugin.rb +126 -0
- data/lib/genomer/runtime.rb +101 -0
- data/lib/genomer/version.rb +3 -0
- data/man/genomer-init.1.ronn +20 -0
- data/spec/genomer/plugin_spec.rb +341 -0
- data/spec/genomer/runtime_spec.rb +262 -0
- data/spec/spec_helper.rb +45 -0
- metadata +290 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
Feature: Plugins accessing the scaffold in a genomer project
|
2
|
+
In order to access the scaffold in a genomer plugin
|
3
|
+
A plugin developer can access the scaffold using the #scaffold method
|
4
|
+
So that the scaffold can be used
|
5
|
+
|
6
|
+
@disable-bundler
|
7
|
+
Scenario: Plugin accessing the scaffold
|
8
|
+
Given I run the genomer command with the arguments "init project"
|
9
|
+
And I cd to "project"
|
10
|
+
And I append to "Gemfile" with:
|
11
|
+
"""
|
12
|
+
gem 'genomer', :path => '../../../'
|
13
|
+
gem 'genomer-plugin-simple', :path => '../../../genomer-plugin-simple'
|
14
|
+
"""
|
15
|
+
And I append to "assembly/scaffold.yml" with:
|
16
|
+
"""
|
17
|
+
---
|
18
|
+
-
|
19
|
+
sequence:
|
20
|
+
source: contig1
|
21
|
+
-
|
22
|
+
sequence:
|
23
|
+
source: contig2
|
24
|
+
|
25
|
+
"""
|
26
|
+
And I append to "assembly/sequence.fna" with:
|
27
|
+
"""
|
28
|
+
>contig1
|
29
|
+
ATGC
|
30
|
+
>contig2
|
31
|
+
ATGC
|
32
|
+
"""
|
33
|
+
When I run the genomer command with the arguments "simple describe"
|
34
|
+
Then the exit status should be 0
|
35
|
+
And the output should contain:
|
36
|
+
"""
|
37
|
+
The scaffold contains 2 entries
|
38
|
+
"""
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: Creating a new genomer project
|
2
|
+
In order to build a genome
|
3
|
+
A user can create a new genomer project
|
4
|
+
So that they can use the genomer commands and organise their data
|
5
|
+
|
6
|
+
Scenario: Creating a new project
|
7
|
+
When I run the genomer command with the arguments "init project"
|
8
|
+
Then the exit status should be 0
|
9
|
+
And a directory named "project" should exist
|
10
|
+
And a directory named "project/assembly" should exist
|
11
|
+
|
12
|
+
Scenario: Creating a new project where the directory already exists
|
13
|
+
Given a directory named "project"
|
14
|
+
When I run the genomer command with the arguments "init project"
|
15
|
+
Then the exit status should be 1
|
16
|
+
And the stderr should contain:
|
17
|
+
"""
|
18
|
+
Error. Directory 'project' already exists.
|
19
|
+
"""
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Feature: Reporting genomer errors
|
2
|
+
In order to use genomer correctly
|
3
|
+
A user can see descriptive genomer error messages
|
4
|
+
And understand how to correct the errors
|
5
|
+
|
6
|
+
Scenario: Calling a non-specified genomer plugin
|
7
|
+
Given I run the genomer command with the arguments "init project"
|
8
|
+
And I cd to "project"
|
9
|
+
And I append to "Gemfile" with ""
|
10
|
+
When I run the genomer command with the arguments "simple"
|
11
|
+
Then the exit status should be 1
|
12
|
+
And the output should contain:
|
13
|
+
"""
|
14
|
+
Error. Unknown command or plugin 'simple.'
|
15
|
+
run `genomer help` for a list of available commands
|
16
|
+
|
17
|
+
"""
|
@@ -0,0 +1,48 @@
|
|
1
|
+
Feature: Listing available commands
|
2
|
+
In order to know which commands are available
|
3
|
+
A user can use the help command
|
4
|
+
To list the available options to the console
|
5
|
+
|
6
|
+
Scenario: Running genomer with no commands
|
7
|
+
When I run the genomer command with no arguments
|
8
|
+
Then the exit status should be 0
|
9
|
+
And the output should contain:
|
10
|
+
"""
|
11
|
+
genomer COMMAND [options]
|
12
|
+
run `genomer help` for a list of available commands
|
13
|
+
|
14
|
+
"""
|
15
|
+
|
16
|
+
Scenario: Running genomer with the help command
|
17
|
+
When I run the genomer command with the arguments "help"
|
18
|
+
Then the exit status should be 0
|
19
|
+
And the output should contain:
|
20
|
+
"""
|
21
|
+
genomer COMMAND [options]
|
22
|
+
|
23
|
+
Available commands:
|
24
|
+
"""
|
25
|
+
And the output should contain:
|
26
|
+
"""
|
27
|
+
init Create a new genomer project
|
28
|
+
"""
|
29
|
+
And the output should contain:
|
30
|
+
"""
|
31
|
+
man View man page for the specified plugin
|
32
|
+
"""
|
33
|
+
|
34
|
+
@disable-bundler
|
35
|
+
Scenario: Running help with a single genomer plugins specified
|
36
|
+
Given I run the genomer command with the arguments "init project"
|
37
|
+
And I cd to "project"
|
38
|
+
And I append to "Gemfile" with:
|
39
|
+
"""
|
40
|
+
gem 'genomer-plugin-simple', :path => '../../../genomer-plugin-simple'
|
41
|
+
"""
|
42
|
+
When I run the genomer command with the arguments "help"
|
43
|
+
Then the exit status should be 0
|
44
|
+
And the output should contain:
|
45
|
+
"""
|
46
|
+
simple Simple genomer plugin for testing purposes
|
47
|
+
"""
|
48
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
Feature: Showing man pages for available commands
|
2
|
+
In order to know which how to use genomer plugins
|
3
|
+
A user can use the man command
|
4
|
+
To show the man page for specified plugin
|
5
|
+
|
6
|
+
Scenario: Running genomer man with no commands
|
7
|
+
When I run the genomer command with the arguments "man"
|
8
|
+
Then the exit status should be 0
|
9
|
+
And the output should contain:
|
10
|
+
"""
|
11
|
+
genomer man COMMAND
|
12
|
+
run `genomer help` for a list of available commands
|
13
|
+
|
14
|
+
"""
|
15
|
+
|
16
|
+
@disable-bundler
|
17
|
+
Scenario: Getting the man page for a plugin
|
18
|
+
Given I run the genomer command with the arguments "init project"
|
19
|
+
And I cd to "project"
|
20
|
+
And I append to "Gemfile" with:
|
21
|
+
"""
|
22
|
+
gem 'genomer-plugin-simple', :path => '../../../genomer-plugin-simple'
|
23
|
+
"""
|
24
|
+
When I run the genomer command with the arguments "man simple"
|
25
|
+
Then the exit status should be 0
|
26
|
+
And the output should contain "GENOMER-SIMPLE(1)"
|
27
|
+
|
28
|
+
@disable-bundler
|
29
|
+
Scenario: Getting the man page for a plugin subcommand
|
30
|
+
Given I run the genomer command with the arguments "init project"
|
31
|
+
And I cd to "project"
|
32
|
+
And I append to "Gemfile" with:
|
33
|
+
"""
|
34
|
+
gem 'genomer-plugin-simple', :path => '../../../genomer-plugin-simple'
|
35
|
+
"""
|
36
|
+
When I run the genomer command with the arguments "man simple subcommand"
|
37
|
+
Then the exit status should be 0
|
38
|
+
And the output should contain "GENOMER-SIMPLE-SUBCOMMAND(1)"
|
39
|
+
|
40
|
+
@disable-bundler
|
41
|
+
Scenario: Trying to get a man page for an unknown plugin
|
42
|
+
Given I run the genomer command with the arguments "init project"
|
43
|
+
And I cd to "project"
|
44
|
+
And I append to "Gemfile" with:
|
45
|
+
"""
|
46
|
+
gem 'genomer-plugin-simple', :path => '../../../genomer-plugin-simple'
|
47
|
+
"""
|
48
|
+
When I run the genomer command with the arguments "man unknown"
|
49
|
+
Then the exit status should be 1
|
50
|
+
And the output should contain:
|
51
|
+
"""
|
52
|
+
Error. Unknown command or plugin 'unknown.'
|
53
|
+
run `genomer help` for a list of available commands
|
54
|
+
|
55
|
+
"""
|
56
|
+
|
57
|
+
@disable-bundler
|
58
|
+
Scenario: Trying to get a man page for an unknown subcommand
|
59
|
+
Given I run the genomer command with the arguments "init project"
|
60
|
+
And I cd to "project"
|
61
|
+
And I append to "Gemfile" with:
|
62
|
+
"""
|
63
|
+
gem 'genomer-plugin-simple', :path => '../../../genomer-plugin-simple'
|
64
|
+
"""
|
65
|
+
When I run the genomer command with the arguments "man simple unknown"
|
66
|
+
Then the exit status should be 1
|
67
|
+
And the output should contain:
|
68
|
+
"""
|
69
|
+
Error. No manual entry for command 'simple unknown'
|
70
|
+
|
71
|
+
"""
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Feature: Calling genomer plugins in a genomer project
|
2
|
+
In order to use third-party genomer plugins
|
3
|
+
A user can specify genomer plugins in a Gemfile
|
4
|
+
And call these plugins on the command line
|
5
|
+
|
6
|
+
@disable-bundler
|
7
|
+
Scenario: Calling a genomer plugin with no command
|
8
|
+
Given I run the genomer command with the arguments "init project"
|
9
|
+
And I cd to "project"
|
10
|
+
And I append to "Gemfile" with:
|
11
|
+
"""
|
12
|
+
gem 'genomer-plugin-simple', :path => '../../../genomer-plugin-simple'
|
13
|
+
"""
|
14
|
+
When I run the genomer command with the arguments "simple"
|
15
|
+
Then the exit status should be 0
|
16
|
+
And the output should contain:
|
17
|
+
"""
|
18
|
+
Plugin "simple" called
|
19
|
+
"""
|
20
|
+
|
21
|
+
@disable-bundler
|
22
|
+
Scenario: Calling a genomer plugin with a command
|
23
|
+
Given I run the genomer command with the arguments "init project"
|
24
|
+
And I cd to "project"
|
25
|
+
And I append to "Gemfile" with:
|
26
|
+
"""
|
27
|
+
gem 'genomer-plugin-simple', :path => '../../../genomer-plugin-simple'
|
28
|
+
"""
|
29
|
+
When I run the genomer command with the arguments "simple echo some words"
|
30
|
+
Then the exit status should be 0
|
31
|
+
And the output should contain:
|
32
|
+
"""
|
33
|
+
Echo: some words
|
34
|
+
"""
|
@@ -0,0 +1,10 @@
|
|
1
|
+
GENOMER = File.join %W|#{File.dirname(__FILE__)} .. .. bin genomer|
|
2
|
+
|
3
|
+
Given /^I run the genomer command with the arguments "([^"]*)"$/ do |args|
|
4
|
+
step "I run `#{GENOMER} #{args}`"
|
5
|
+
end
|
6
|
+
|
7
|
+
Given /^I run the genomer command with no arguments/ do
|
8
|
+
step 'I run the genomer command with the arguments ""'
|
9
|
+
end
|
10
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
begin
|
3
|
+
Bundler.setup(:default, :development)
|
4
|
+
rescue Bundler::BundlerError => e
|
5
|
+
$stderr.puts e.message
|
6
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
7
|
+
exit e.status_code
|
8
|
+
end
|
9
|
+
|
10
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
|
11
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../spec')
|
12
|
+
|
13
|
+
require 'aruba/cucumber'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "genomer-plugin-simple"
|
3
|
+
s.version = "0.0.0"
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.authors = ["Michael Barton"]
|
6
|
+
s.email = ["mail@michaelbarton.me.uk"]
|
7
|
+
s.homepage = "http://next.gs"
|
8
|
+
s.summary = "Simple genomer plugin for testing purposes"
|
9
|
+
s.description = "Empty"
|
10
|
+
|
11
|
+
s.required_rubygems_version = ">= 1.8"
|
12
|
+
|
13
|
+
# required for validation
|
14
|
+
s.rubyforge_project = "genomer-plugin-simple"
|
15
|
+
|
16
|
+
s.files = Dir["{lib}/**/*.rb"]
|
17
|
+
s.require_path = 'lib'
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class GenomerPluginSimple < Genomer::Plugin
|
2
|
+
|
3
|
+
def run
|
4
|
+
case arguments.shift
|
5
|
+
when nil then 'Plugin "simple" called'
|
6
|
+
when 'echo' then "Echo: #{arguments.join(' ')}"
|
7
|
+
when 'describe' then "The scaffold contains #{scaffold.length} entries"
|
8
|
+
when 'annotations' then annotations
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def annotations
|
13
|
+
args = Hash.new
|
14
|
+
args[:prefix] = flags[:prefix] if flags[:prefix]
|
15
|
+
args[:reset] = flags[:reset_locus_numbering] if flags[:reset_locus_numbering]
|
16
|
+
super(args).inject("##gff-version 3\n"){|s, a| s << a.to_s}
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/genomer.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/genomer/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "genomer"
|
6
|
+
s.version = Genomer::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Michael Barton"]
|
9
|
+
s.email = ["mail@michaelbarton.me.uk"]
|
10
|
+
s.homepage = "http://github.com/michaelbarton/genomer"
|
11
|
+
s.summary = %Q{Build genome output files}
|
12
|
+
s.description = %Q{Turns scaffolded contigs and annotations into a genome.}
|
13
|
+
s.license = "MIT"
|
14
|
+
|
15
|
+
s.required_rubygems_version = ">= 1.8.0"
|
16
|
+
s.rubyforge_project = "genomer"
|
17
|
+
|
18
|
+
s.add_dependency "rake", "~> 0.9.0"
|
19
|
+
s.add_dependency "bundler", "~> 1.1.0"
|
20
|
+
s.add_dependency "configliere", "~> 0.4.8"
|
21
|
+
s.add_dependency "scaffolder", "~> 0.4.0"
|
22
|
+
s.add_dependency "scaffolder-annotation-locator", ">= 0.1.2"
|
23
|
+
s.add_dependency "unindent", "~> 1.0.0"
|
24
|
+
s.add_dependency "ronn", "~> 0.7.3"
|
25
|
+
|
26
|
+
# Specs
|
27
|
+
s.add_development_dependency "rspec", "~> 2.7.0"
|
28
|
+
s.add_development_dependency "fakefs", "~> 0.4.0"
|
29
|
+
s.add_development_dependency "rr", "~> 1.0.4"
|
30
|
+
s.add_development_dependency "scaffolder-test-helpers", "~> 0.4.0"
|
31
|
+
|
32
|
+
# Features
|
33
|
+
s.add_development_dependency "cucumber", "~> 1.1.4"
|
34
|
+
s.add_development_dependency "aruba", "~> 0.4.11"
|
35
|
+
|
36
|
+
s.files = `git ls-files`.split("\n")
|
37
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
38
|
+
s.require_path = 'lib'
|
39
|
+
end
|
data/lib/genomer.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'scaffolder'
|
2
|
+
require 'scaffolder/annotation_locator'
|
3
|
+
|
4
|
+
# Superclass for genomer plugins which us the genomer plugin. This class
|
5
|
+
# implements the common API which plugins should use to interact with the
|
6
|
+
# genomer system
|
7
|
+
class Genomer::Plugin
|
8
|
+
|
9
|
+
# Return the corresponding class for this plugin name.
|
10
|
+
#
|
11
|
+
# This method calls {Kernel#require} for the requested plugin by searching
|
12
|
+
# the available plugins for genomer-plugin-NAME. Where name is the passed
|
13
|
+
# string. The class for this plugin is then returned.
|
14
|
+
#
|
15
|
+
# @param [String] name The name of plugin without the 'genomer-plugin-' prefix.
|
16
|
+
# @return [Class] The class for this genomer plugin.
|
17
|
+
def self.[](plugin)
|
18
|
+
name = fetch(plugin).name
|
19
|
+
require name
|
20
|
+
Kernel.const_get(to_class_name(name))
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.fetch(name)
|
24
|
+
plugin = plugins.detect{|i| i.name == "genomer-plugin-#{name}" }
|
25
|
+
unless plugin
|
26
|
+
error = "Unknown command or plugin '#{name}.'\n"
|
27
|
+
error << "run `genomer help` for a list of available commands\n"
|
28
|
+
raise Genomer::Error, error
|
29
|
+
end
|
30
|
+
plugin
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# All the avaiable gems with a matching genomer-plugin- prefix.
|
36
|
+
#
|
37
|
+
# @return [Array] An array of genomer plugin gems
|
38
|
+
def self.plugins
|
39
|
+
require 'bundler'
|
40
|
+
Bundler.setup.gems.select{|gem| gem.name =~ /genomer-plugin-.+/ }
|
41
|
+
end
|
42
|
+
|
43
|
+
# Convert hyphen separated list of words to camel case
|
44
|
+
#
|
45
|
+
# @param [String] Hyphen separate string
|
46
|
+
# @return [String] Camel case string
|
47
|
+
def self.to_class_name(string)
|
48
|
+
string.split('-').map{|i| i.capitalize}.join
|
49
|
+
end
|
50
|
+
|
51
|
+
public
|
52
|
+
|
53
|
+
# @return [Array] List of command line arguments
|
54
|
+
attr :arguments
|
55
|
+
|
56
|
+
# @return [Hash] Command line flags as where --flag=value is :flag => value
|
57
|
+
attr :flags
|
58
|
+
|
59
|
+
attr :sequence_file
|
60
|
+
attr :scaffold_file
|
61
|
+
attr :annotation_file
|
62
|
+
|
63
|
+
# Initialize plugin with passed command line parameters.
|
64
|
+
#
|
65
|
+
# This create a plugin instance with the command line arguments and instance set as
|
66
|
+
# instance variables. These command line arguments are passed by the
|
67
|
+
# Genomer::Runtime.
|
68
|
+
#
|
69
|
+
# @param [Array] arguments List of command arguments
|
70
|
+
# @param [Hash] settings Command line flags as :flag => value
|
71
|
+
def initialize(arguments,flags)
|
72
|
+
@arguments = arguments
|
73
|
+
@flags = flags
|
74
|
+
|
75
|
+
assembly = Pathname.new('assembly')
|
76
|
+
@sequence_file = assembly + 'sequence.fna'
|
77
|
+
@scaffold_file = assembly + 'scaffold.yml'
|
78
|
+
@annotation_file = assembly + 'annotations.gff'
|
79
|
+
end
|
80
|
+
|
81
|
+
# The genome scaffold constructed from the files in the "ROOT/assembly/" directory.
|
82
|
+
#
|
83
|
+
# @return [Array] An array of Scaffolder::Region instances
|
84
|
+
def scaffold
|
85
|
+
YAML::ENGINE.yamler = 'syck'
|
86
|
+
Scaffolder.new(YAML.load(File.read(scaffold_file)),sequence_file)
|
87
|
+
end
|
88
|
+
|
89
|
+
def annotations(options = {})
|
90
|
+
attns = Scaffolder::AnnotationLocator.new(
|
91
|
+
scaffold_file,sequence_file,annotation_file)
|
92
|
+
|
93
|
+
attns.sort_by! do |attn|
|
94
|
+
[attn.start,attn.end]
|
95
|
+
end
|
96
|
+
|
97
|
+
if value = options[:reset]
|
98
|
+
start = value.to_s =~ /^[-+]?[0-9]+$/ ? value.to_i : 1
|
99
|
+
|
100
|
+
genes = attns.select{|i| i.feature == 'gene'}
|
101
|
+
genes.each_with_index do |annotation,count|
|
102
|
+
annotation.id.replace sprintf("%06d",count + start)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
if prefix = options[:prefix]
|
107
|
+
genes = attns.select{|i| i.feature == 'gene'}
|
108
|
+
genes.each{|attn| attn.id.insert(0,prefix) }
|
109
|
+
end
|
110
|
+
|
111
|
+
attns
|
112
|
+
end
|
113
|
+
|
114
|
+
# This method should be overriden to perform this plugin's operation.
|
115
|
+
#
|
116
|
+
# The run method is called on the plugin by Genomer::Runtime. This should be
|
117
|
+
# overridden in subclasses to perform the intended function. If an error is
|
118
|
+
# encountered raise a Genomer::Error with a description. This will be caught
|
119
|
+
# and the error message printed to the standard out.
|
120
|
+
#
|
121
|
+
# @return [String] The string output of this plugin. This is
|
122
|
+
# subsequently output to the command line
|
123
|
+
def run
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|