neurohmmerapp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +81 -0
  5. data/LICENSE.txt +661 -0
  6. data/README.md +96 -0
  7. data/Rakefile +21 -0
  8. data/bin/neurohmmerapp +166 -0
  9. data/config.ru +3 -0
  10. data/lib/neurohmmerapp/config.rb +87 -0
  11. data/lib/neurohmmerapp/exceptions.rb +77 -0
  12. data/lib/neurohmmerapp/logger.rb +24 -0
  13. data/lib/neurohmmerapp/neurohmmer.rb +158 -0
  14. data/lib/neurohmmerapp/routes.rb +79 -0
  15. data/lib/neurohmmerapp/server.rb +63 -0
  16. data/lib/neurohmmerapp/version.rb +3 -0
  17. data/lib/neurohmmerapp.rb +207 -0
  18. data/neurohmmerapp.gemspec +50 -0
  19. data/public/NeuroHmmer/loading.html +12 -0
  20. data/public/src/css/bootstrap1.min.css +7 -0
  21. data/public/src/css/custom.css +189 -0
  22. data/public/src/css/custom.min.css +1 -0
  23. data/public/src/css/font-awesome.min.css +4 -0
  24. data/public/src/js/bionode-seq.min.js +1 -0
  25. data/public/src/js/bootstrap.min.js +6 -0
  26. data/public/src/js/jquery.cookie.min.js +1 -0
  27. data/public/src/js/jquery.min.js +4 -0
  28. data/public/src/js/jquery.validate.min.js +4 -0
  29. data/public/src/js/neurohmmer.js +228 -0
  30. data/public/src/js/neurohmmer.min.js +1 -0
  31. data/public/web_files/css/nh_compiled_css.min.css +14 -0
  32. data/public/web_files/fonts/FontAwesome.otf +0 -0
  33. data/public/web_files/fonts/fontawesome-webfont.eot +0 -0
  34. data/public/web_files/fonts/fontawesome-webfont.svg +504 -0
  35. data/public/web_files/fonts/fontawesome-webfont.ttf +0 -0
  36. data/public/web_files/fonts/fontawesome-webfont.woff +0 -0
  37. data/public/web_files/js/nh_compiled_js.min.js +20 -0
  38. data/spec/empty_config.yml +0 -0
  39. data/spec/route_spec.rb +72 -0
  40. data/views/500.slim +5 -0
  41. data/views/index.slim +38 -0
  42. data/views/layout.slim +74 -0
  43. data/views/results.slim +9 -0
  44. metadata +281 -0
@@ -0,0 +1,79 @@
1
+ require 'sinatra/base'
2
+ require 'sinatra/cross_origin'
3
+ require 'neurohmmer/version'
4
+ require 'neurohmmerapp/version'
5
+ require 'slim'
6
+
7
+ module NeuroHmmerApp
8
+ # The Sinatra Routes
9
+ class Routes < Sinatra::Base
10
+ register Sinatra::CrossOrigin
11
+
12
+ configure do
13
+ # We don't need Rack::MethodOverride. Let's avoid the overhead.
14
+ disable :method_override
15
+
16
+ # Ensure exceptions never leak out of the app. Exceptions raised within
17
+ # the app must be handled by the app. We do this by attaching error
18
+ # blocks to exceptions we know how to handle and attaching to Exception
19
+ # as fallback.
20
+ disable :show_exceptions, :raise_errors
21
+
22
+ # Make it a policy to dump to 'rack.errors' any exception raised by the
23
+ # app so that error handlers don't have to do it themselves. But for it
24
+ # to always work, Exceptions defined by us should not respond to `code`
25
+ # or http_status` methods. Error blocks errors must explicitly set http
26
+ # status, if needed, by calling `status` method.
27
+ enable :dump_errors
28
+
29
+ # We don't want Sinatra do setup any loggers for us. We will use our own.
30
+ set :logging, nil
31
+
32
+ # This is the app root...
33
+ set :root, lambda { NeuroHmmerApp.root }
34
+
35
+ # This is the full path to the public folder...
36
+ set :public_folder, lambda { NeuroHmmerApp.public_dir }
37
+ end
38
+
39
+ # Set up global variables for the templates...
40
+ before '/' do
41
+ @max_characters = NeuroHmmerApp.config[:max_characters]
42
+ @current_neurohmmer_version = '0.1'
43
+ end
44
+
45
+ get '/' do
46
+ slim :index
47
+ end
48
+
49
+ post '/' do
50
+ cross_origin # Required for the API to work...
51
+ RunNeuroHmmer.init(request.url, params)
52
+ @neurohmmer_results = RunNeuroHmmer.run
53
+ slim :results, layout: false
54
+ end
55
+
56
+ # This error block will only ever be hit if the user gives us a funny
57
+ # sequence or incorrect advanced parameter. Well, we could hit this block
58
+ # if someone is playing around with our HTTP API too.
59
+ error RunNeuroHmmer::ArgumentError do
60
+ status 400
61
+ slim :"500", layout: false
62
+ end
63
+
64
+ # This will catch any unhandled error and some very special errors. Ideally
65
+ # we will never hit this block. If we do, there's a bug in NeuroHmmerApp
66
+ # or something really weird going on.
67
+ # TODO: If we hit this error block we show the stacktrace to the user
68
+ # requesting them to post the same to our Google Group.
69
+ error Exception, RunNeuroHmmer::RuntimeError do
70
+ status 500
71
+ slim :"500", layout: false
72
+ end
73
+
74
+ not_found do
75
+ status 404
76
+ slim :"500" # TODO: Create another Template
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,63 @@
1
+ require 'rack/handler/webrick'
2
+
3
+ module NeuroHmmerApp
4
+ # Simple wrapper around WEBrick and Rack::Handler::WEBrick to host
5
+ # NeuroHmmerApp standalone.
6
+ class Server
7
+ class << self
8
+ def run(*args)
9
+ new(*args).start
10
+ end
11
+ end
12
+
13
+ def initialize(app)
14
+ @app = app
15
+ end
16
+
17
+ attr_reader :app
18
+
19
+ # Start server. Raises Errno::EADDRINUSE if port is in use by another
20
+ # process. Raises Errno::EACCES if binding to the port requires root
21
+ # privilege.
22
+ def start
23
+ setup_signal_handlers
24
+ @server = WEBrick::HTTPServer.new(options)
25
+ @server.mount '/', Rack::Handler::WEBrick, app
26
+ @server.start
27
+ end
28
+
29
+ # Stop server.
30
+ def stop
31
+ @server.shutdown
32
+ end
33
+
34
+ # Options Hash passed to WEBrick::HTTPServer.
35
+ # rubocop:disable Metrics/AbcSize
36
+ def options
37
+ @options ||= {
38
+ :BindAddress => app.config[:host],
39
+ :Port => app.config[:port],
40
+ :StartCallback => proc { app.on_start },
41
+ :StopCallback => proc { app.on_stop },
42
+ :OutputBufferSize => 5,
43
+ :AccessLog => [[logdev, WEBrick::AccessLog::COMMON_LOG_FORMAT]],
44
+ :Logger => WEBrick::Log.new(logdev)
45
+ }
46
+ end
47
+ # rubocop:enable Metrics/AbcSize
48
+
49
+ private
50
+
51
+ def setup_signal_handlers
52
+ [:INT, :TERM].each do |sig|
53
+ trap sig do
54
+ stop
55
+ end
56
+ end
57
+ end
58
+
59
+ def logdev
60
+ @logdev ||= app.verbose? ? STDERR : '/dev/null'
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ module NeuroHmmerApp
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,207 @@
1
+ require 'yaml'
2
+ require 'fileutils'
3
+
4
+ require 'neurohmmerapp/config'
5
+ require 'neurohmmerapp/exceptions'
6
+ require 'neurohmmerapp/neurohmmer'
7
+ require 'neurohmmerapp/logger'
8
+ require 'neurohmmerapp/routes'
9
+ require 'neurohmmerapp/server'
10
+ require 'neurohmmerapp/version'
11
+
12
+ module NeuroHmmerApp
13
+ # Use a fixed minimum version of BLAST+
14
+ MINIMUM_HMMER_VERSION = '3.0.0'
15
+
16
+ class << self
17
+ def environment
18
+ ENV['RACK_ENV']
19
+ end
20
+
21
+ def verbose?
22
+ @verbose ||= (environment == 'development')
23
+ end
24
+
25
+ def root
26
+ File.dirname(File.dirname(__FILE__))
27
+ end
28
+
29
+ def logger
30
+ @logger ||= Logger.new(STDERR, verbose?)
31
+ end
32
+
33
+ # Setting up the environment before running the app...
34
+ def init(config = {})
35
+ @config = Config.new(config)
36
+
37
+ init_binaries
38
+ init_dirs
39
+
40
+ load_extension
41
+ check_num_threads
42
+ check_max_characters
43
+ self
44
+ end
45
+
46
+ attr_reader :config, :temp_dir, :public_dir
47
+
48
+ # Starting the app manually
49
+ def run
50
+ check_host
51
+ Server.run(self)
52
+ rescue Errno::EADDRINUSE
53
+ puts "** Could not bind to port #{config[:port]}."
54
+ puts " Is NeuroHmmer already accessible at #{server_url}?"
55
+ puts ' No? Try running NeuroHmmer on another port, like so:'
56
+ puts
57
+ puts ' neurohmmerapp -p 4570.'
58
+ rescue Errno::EACCES
59
+ puts "** Need root privilege to bind to port #{config[:port]}."
60
+ puts ' It is not advisable to run NeuroHmmer as root.'
61
+ puts ' Please use Apache/Nginx to bind to a privileged port.'
62
+ end
63
+
64
+ def on_start
65
+ puts '** NeuroHmmer is ready.'
66
+ puts " Go to #{server_url} in your browser and start analysing genes!"
67
+ puts ' Press CTRL+C to quit.'
68
+ open_in_browser(server_url)
69
+ end
70
+
71
+ def on_stop
72
+ puts
73
+ puts '** Thank you for using NeuroHmmerApp :).'
74
+ puts ' Please cite: '
75
+ puts ' Moghul M.I., Elphick M & Wurm Y (in prep).'
76
+ puts ' NeuroHmmer: identify Neuropeptide Precursors.'
77
+ end
78
+
79
+ # Rack-interface.
80
+ #
81
+ # Inject our logger in the env and dispatch request to our controller.
82
+ def call(env)
83
+ env['rack.logger'] = logger
84
+ Routes.call(env)
85
+ end
86
+
87
+ private
88
+
89
+ def init_dirs
90
+ config[:public_dir] = File.expand_path(config[:public_dir])
91
+ unique_start_id = 'NH_' + "#{Time.now.strftime('%Y%m%d-%H-%M-%S')}"
92
+ @public_dir = File.join(config[:public_dir], unique_start_id)
93
+ init_public_dir
94
+ end
95
+
96
+ # Create the Public Dir and copy files from gem root - this public dir
97
+ # is served by the app is accessible at URL/...
98
+ def init_public_dir
99
+ FileUtils.mkdir_p(File.join(@public_dir, 'NeuroHmmer'))
100
+ root_web_files = File.join(NeuroHmmerApp.root, 'public/web_files')
101
+ root_gv = File.join(NeuroHmmerApp.root, 'public/NeuroHmmer')
102
+ FileUtils.cp_r(root_web_files, @public_dir)
103
+ FileUtils.cp_r(root_gv, @public_dir)
104
+ end
105
+
106
+ def init_binaries
107
+ config[:bin] = init_bins if config[:bin]
108
+ assert_blast_installed_and_compatible
109
+ assert_mafft_installed
110
+ end
111
+
112
+ def load_extension
113
+ return unless config[:require]
114
+ config[:require] = File.expand_path config[:require]
115
+ unless File.exist?(config[:require]) && File.file?(config[:require])
116
+ fail EXTENSION_FILE_NOT_FOUND, config[:require]
117
+ end
118
+
119
+ logger.debug("Loading extension: #{config[:require]}")
120
+ require config[:require]
121
+ end
122
+
123
+ def check_num_threads
124
+ num_threads = Integer(config[:num_threads])
125
+ fail NUM_THREADS_INCORRECT unless num_threads > 0
126
+
127
+ logger.debug "Will use #{num_threads} threads to run BLAST."
128
+ if num_threads > 256
129
+ logger.warn "Number of threads set at #{num_threads} is unusually high."
130
+ end
131
+ rescue
132
+ raise NUM_THREADS_INCORRECT
133
+ end
134
+
135
+ def check_max_characters
136
+ if config[:max_characters] != 'undefined'
137
+ config[:max_characters] = Integer(config[:max_characters])
138
+ end
139
+ rescue
140
+ raise MAX_CHARACTERS_INCORRECT
141
+ end
142
+
143
+ def init_bins
144
+ bins = []
145
+ config[:bin].each do |bin|
146
+ bins << File.expand_path(bin)
147
+ unless File.exist?(bin) && File.directory?(bin)
148
+ fail BIN_DIR_NOT_FOUND, config[:bin]
149
+ end
150
+ export_bin_dir(bin)
151
+ end
152
+ bins
153
+ end
154
+
155
+ ## Checks if dir is in $PATH and if not, it adds the dir to the $PATH.
156
+ def export_bin_dir(bin_dir)
157
+ return unless bin_dir
158
+ return if ENV['PATH'].split(':').include?(bin_dir)
159
+ ENV['PATH'] = "#{bin_dir}:#{ENV['PATH']}"
160
+ end
161
+
162
+ def assert_blast_installed_and_compatible
163
+ fail HMMER_NOT_INSTALLED unless command? 'hmmscan'
164
+ # version = `hmmscan -version`.split[1]
165
+ # fail HMMER_NOT_COMPATIBLE, version unless version >= MINIMUM_HMMER_VERSION
166
+ end
167
+
168
+ def assert_mafft_installed
169
+ fail MAFFT_NOT_INSTALLED unless command? 'mafft'
170
+ end
171
+
172
+ # Check and warn user if host is 0.0.0.0 (default).
173
+ def check_host
174
+ return unless config[:host] == '0.0.0.0'
175
+ logger.warn 'Will listen on all interfaces (0.0.0.0).' \
176
+ ' Consider using 127.0.0.1 (--host option).'
177
+ end
178
+
179
+ def server_url
180
+ host = config[:host]
181
+ host = 'localhost' if host == '127.0.0.1' || host == '0.0.0.0'
182
+ "http://#{host}:#{config[:port]}"
183
+ end
184
+
185
+ def open_in_browser(server_url)
186
+ return if using_ssh? || verbose?
187
+ if RUBY_PLATFORM =~ /linux/ && xdg?
188
+ system "xdg-open #{server_url}system"
189
+ elsif RUBY_PLATFORM =~ /darwin/
190
+ system "open #{server_url}system"
191
+ end
192
+ end
193
+
194
+ def using_ssh?
195
+ true if ENV['SSH_CLIENT'] || ENV['SSH_TTY'] || ENV['SSH_CONNECTION']
196
+ end
197
+
198
+ def xdg?
199
+ true if ENV['DISPLAY'] && command?('xdg-open')
200
+ end
201
+
202
+ # Return `true` if the given command exists and is executable.
203
+ def command?(command)
204
+ system("which #{command} > /dev/null 2>&1")
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,50 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'neurohmmerapp/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'neurohmmerapp'
8
+ spec.version = NeuroHmmerApp::VERSION
9
+ spec.authors = ['Ismail Moghul', 'Yannick Wurm']
10
+ spec.email = 'y.wurm@qmul.ac.uk'
11
+ spec.summary = 'A Web App wrapper for NeuroHmmer.'
12
+ spec.description = 'A Web App wrapper for NeuroHmmer, a program for' \
13
+ ' validating gene predictions.'
14
+ spec.homepage = 'https://github.com/wurmlab/neurohmmerapp'
15
+ spec.license = 'AGPL'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.required_ruby_version = '>= 2.0.0'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.6'
25
+ spec.add_development_dependency 'rake', '~>10.3'
26
+ spec.add_development_dependency('rspec', '~> 2.8', '>= 2.8.0')
27
+ spec.add_development_dependency 'rack-test', '~> 0.6'
28
+ spec.add_development_dependency('capybara', '~> 2.4', '>= 2.4.4')
29
+ spec.add_development_dependency 'w3c_validators', '~>1.1'
30
+
31
+ spec.add_dependency 'neurohmmer', '~>0.1'
32
+ spec.add_dependency 'bio', '~>1.4'
33
+ spec.add_dependency 'sinatra', '~>1.4'
34
+ spec.add_dependency 'sinatra-cross_origin', '~> 0.3'
35
+ spec.add_dependency 'slim', '~>3.0'
36
+ spec.add_dependency 'slop', '~>3.6'
37
+ spec.post_install_message = <<INFO
38
+
39
+ ------------------------------------------------------------------------
40
+ Thank you for Installing the NeuroHmmer App!
41
+
42
+ To launch NeuroHmmerApp execute 'neurohmmerapp' from command line.
43
+
44
+ $ neurohmmerapp [options]
45
+
46
+ Visit https://github.com/wurmlab/neurohmmerapp for more information.
47
+ ------------------------------------------------------------------------
48
+
49
+ INFO
50
+ end
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html><html><head><title>NeuroHmmer: Identify Neuropeptide Precursors</title><meta content="text/html; charset=utf-8" http-equiv="Content-Type"><link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.5/flatly/bootstrap.min.css"><link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
2
+ <style type="text/css">html{position:relative;min-height:100%;}body{margin:0 0 100px;background-color:#F5F5F5}footer{bottom:0;width:100%;margin:0 auto;position:absolute;height:100px;overflow:hidden;border-top:2px solid #DBDBDB;padding-top:10px;color:#b4bcc2}
3
+ </style></head>
4
+ <body>
5
+ <div class="container text-center">
6
+ <h1 style="font-size: 78px">NeuroHmmer</h1>
7
+ <h4 style="margin-bottom:3em">Identify Neuropeptide Precursors</h4>
8
+ <i class="fa fa-spinner fa-spin" style="font-size: 10em"></i>
9
+ <h2> Calculating...</h2>
10
+ <p class="results_link"> This may take some time. Please leave this page open.</p>
11
+ </div>
12
+ <footer><div class="container center-block"><p class="text-muted text-center">Please cite: "Moghul MI, Elphick M &amp; Wurm Y <em>(in prep)</em> NeuroHmmer: Identify Neuropeptide Precursors"<br/> Developed at <a href="https://wurmlab.github.io" target="_blank">Wurm Lab</a>, <a href="http://www.sbcs.qmul.ac.uk" target="_blank">QMUL</a> with funding by <a href="http://www.bbsrc.ac.uk/home/home.aspx" target="_blank">BBSRC</a><br/>This page was created by <a href="https://github.com/wurmlab/neurohmmer" target="_blank" >NeuroHmmer</a> v0.01</p></div></footer></body></html>