Completed
Push — master ( 6eeaac...4c4c49 )
by Ismail
51s
created

GeoDiver.load_geo_db()   A

Complexity

Conditions 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
1
require 'yaml'
2
require 'fileutils'
3
4
require 'geodiver/config'
5
require 'geodiver/exceptions'
6
require 'geodiver/load_geo_db'
7
require 'geodiver/logger'
8
require 'geodiver/geo_analysis'
9
require 'geodiver/geo_analysis_helper'
10
require 'geodiver/routes'
11
require 'geodiver/server'
12
require 'geodiver/version'
13
14
# GeoDiver NameSpace
15
module GeoDiver
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 ssl?
30
      @config[:ssl]
31
    end
32
33
    def logger
34
      @logger ||= Logger.new(STDOUT)
35
    end
36
37
    # Setting up the environment before running the app...
38
    # We don't validate port and host settings. If GeoDiver is run
39
    # self-hosted, bind will fail on incorrect values. If GeoDiver
40
    # is run via Apache/Nginx + Passenger, we don't need to worry.
41
    def init(config = {})
42
      @config = Config.new(config)
43
      Thread.abort_on_exception = true if verbose?
44
45
      init_dirs
46
      set_up_default_user_dir
47
      check_num_threads
48
      # generate_exemplar_results
49
50
      self
51
    end
52
53
    attr_reader :config, :temp_dir, :public_dir, :users_dir, :db_dir,
54
                :exemplar_results
55
56
    # Starting the app manually
57
    def run
58
      check_host
59
      Server.run(self)
60
    rescue Errno::EADDRINUSE
61
      puts "** Could not bind to port #{config[:port]}."
62
      puts "   Is GeoDiver already accessible at #{server_url}?"
63
      puts '   No? Try running GeoDiver on another port, like so:'
64
      puts
65
      puts '       geodiver -p 4570.'
66
    rescue Errno::EACCES
67
      puts "** Need root privilege to bind to port #{config[:port]}."
68
      puts '   It is not advisable to run GeoDiver as root.'
69
      puts '   Please use Apache/Nginx to bind to a privileged port.'
70
    end
71
72
    def on_start
73
      puts '** GeoDiver is ready.'
74
      puts "   Go to #{server_url} in your browser and start analysing GEO datasets!"
75
      puts '   Press CTRL+C to quit.'
76
      open_in_browser(server_url)
77
    end
78
79
    def on_stop
80
      puts
81
      puts '** Thank you for using GeoDiver :).'
82
      # Add Citation Notice Here
83
    end
84
85
    # Rack-interface.
86
    #
87
    # Inject our logger in the env and dispatch request to our controller.
88
    def call(env)
89
      env['rack.logger'] = logger
90
      Routes.call(env)
91
    end
92
93
    private
94
95
    # Set up the directory structure in @config[:gd_serve_dir]
96
    def init_dirs
97
      default_dirs
98
      init_public_dir
99
      FileUtils.mkdir_p @users_dir unless Dir.exist? @users_dir
100
      FileUtils.mkdir_p @db_dir unless Dir.exist? @db_dir
101
    end
102
103
    def default_dirs
104
      config[:gd_serve_dir] = File.expand_path config[:gd_serve_dir]
105
      @public_dir = File.join(config[:gd_serve_dir], 'public')
106
      @users_dir = File.join(config[:gd_serve_dir], 'Users')
107
      @db_dir = File.join(config[:gd_serve_dir], 'DBs')
108
      logger.debug "GeoDiver Directory: #{config[:gd_serve_dir]}"
109
      logger.debug "@public_dir Directory: #{@public_dir}"
110
      logger.debug "@users_dir Directory: #{@users_dir}"
111
      logger.debug "@db_dir Directory: #{@db_dir}"
112
    end
113
114
    # Public Directory structure
115
    def init_public_dir
116
      FileUtils.mkdir_p @public_dir unless Dir.exist?(@public_dir)
117
      root_assets = File.join(GeoDiver.root, 'public/assets')
118
      FileUtils.rm_rf(File.join(@public_dir, 'assets'))
119
      if environment == 'development'
120
        FileUtils.ln_s(root_assets, @public_dir)
121
      else
122
        FileUtils.cp_r(root_assets, @public_dir)
123
      end
124
      init_public_gd_dir(@public_dir)
125
    end
126
127
    def init_public_gd_dir(public_dir)
128
      root_gd = File.join(GeoDiver.root, 'public/GeoDiver')
129
      public_gd = File.join(public_dir, 'GeoDiver')
130
      return if File.exist?(public_gd)
131
      FileUtils.cp_r(root_gd, public_dir)
132
    end
133
134
    def set_up_default_user_dir
135
      user_dir    = File.join(GeoDiver.users_dir, 'geodiver')
136
      user_public = File.join(GeoDiver.public_dir, 'GeoDiver/Users')
137
      FileUtils.mkdir(user_dir) unless Dir.exist?(user_dir)
138
      return if File.exist? File.join(user_public, 'geodiver')
139
      FileUtils.ln_s(user_dir, user_public)
140
    end
141
142
    def check_num_threads
143
      config[:num_threads] = Integer(config[:num_threads])
144
      raise NUM_THREADS_INCORRECT unless config[:num_threads] > 0
145
146
      logger.debug "Will use #{config[:num_threads]} threads to run GeoDiver."
147
      return unless config[:num_threads] > 256
148
      logger.warn "Number of threads set at #{config[:num_threads]} is" \
149
                  ' unusually high.'
150
    end
151
152
    # Check and warn user if host is 0.0.0.0 (default).
153
    def check_host
154
      return unless config[:host] == '0.0.0.0'
155
      logger.warn 'Will listen on all interfaces (0.0.0.0).' \
156
                  ' Consider using 127.0.0.1 (--host option).'
157
    end
158
159
    def server_url
160
      host = config[:host]
161
      host = 'localhost' if ['127.0.0.1', '0.0.0.0'].include? host
162
      proxy = GeoDiver.ssl? ? 'https' : 'http'
163
      "#{proxy}://#{host}:#{config[:port]}"
164
    end
165
166
    def open_in_browser(server_url)
167
      return if using_ssh? || verbose?
168
      if RUBY_PLATFORM =~ /linux/ && xdg?
169
        system "xdg-open #{server_url}"
170
      elsif RUBY_PLATFORM =~ /darwin/
171
        system "open #{server_url}"
172
      end
173
    end
174
175
    def using_ssh?
176
      true if ENV['SSH_CLIENT'] || ENV['SSH_TTY'] || ENV['SSH_CONNECTION']
177
    end
178
179
    def xdg?
180
      true if ENV['DISPLAY'] && system('which xdg-open > /dev/null 2>&1')
181
    end
182
183
    # Test if the RCore is working and also produce the exemplar results
184
    def generate_exemplar_results
185
      logger.debug 'Testing RCore and producing Exemplar Results Page'
186
      session_geodb = load_geo_db
187
      email         = 'geodiver'
188
      r = GeoAnalysis.run(default_params, email, server_url, session_geodb)
189
      assert_rcore_works(r)
190
      @exemplar_results = File.join('geodiver', r[:geo_db], r[:uniq_result_id])
191
      logger.debug "Exemplar Results page is available at: #{r[:results_url]}"
192
    end
193
194
    def load_geo_db
195
      LoadGeoData.run('geo_db' => 'GDS724')
196
      LoadGeoData.convert_geodb_into_rdata('GDS724')
197
    end
198
199
    def assert_rcore_works(r)
200
      return if r[:overview_exit_code].zero? && r[:dgea_exit_code].zero? &&
201
                r[:gage_exit_code].zero?
202
      raise RCORE_FAILURE
203
    end
204
205
    def default_params
206
      { 'geo_db' => 'GDS724', 'user' => 'Z2VvZGl2ZXI=', 'factor' => 'tissue',
207
        'groupa' => ['peripheral blood lymphocyte'], 'groupb' => ['kidney'],
208
        'dgea' => 'on', 'dgea_toptable' => 'on',
209
        'dgea_number_top_genes' => '250',
210
        'dgea_volcano_pValue_cutoff' => 'fdr', 'dgea_heatmap' => 'on',
211
        'dgea_heatmap_rows' => '100',
212
        'dgea_heatmap_distance_method' => 'euclidean',
213
        'dgea_heatmap_clustering_method' => 'complete',
214
        'dgea_cluster_by_genes' => 'true', 'dgea_cluster_by_samples' => 'true',
215
        'dgea_cluster_based_on' => 'on',
216
        'dgea_volcano' => 'on', 'gsea' => 'on', 'gsea_type' => 'ExpVsCtrl',
217
        'gsea_control_group' => 'on', 'gsea_dataset' => 'KEGG',
218
        'gsea_heatmap' => 'on', 'gsea_heatmap_rows' => '100',
219
        'gsea_heatmap_distance_method' => 'euclidean',
220
        'gsea_heatmap_clustering_method' => 'complete',
221
        'gsea_cluster_by_genes' => 'true', 'gsea_cluster_by_samples' => 'true',
222
        'gsea_cluster_based_on' => 'on' }
223
    end
224
  end
225
end
226