genomer 0.0.5
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.
- 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
|