diff --git a/.gitignore b/.gitignore index b031ead..c08ed30 100644 --- a/.gitignore +++ b/.gitignore @@ -8,9 +8,13 @@ doc* lib/martsearch/server/public/css/martsearch-*.css lib/martsearch/server/public/js/martsearch-base-*.js lib/martsearch/server/public/js/martsearch-head-*.js +pheno_heatmap.xls +public/css/martsearch-* +public/js/martsearch-base-* +public/js/martsearch-head-* schema.xml simplecov/* test/vcr_cassettes* +tmp/*.json tmp/index_builder* tmp/pheno_abr* -pheno_heatmap.xls \ No newline at end of file diff --git a/.metrics b/.metrics new file mode 100644 index 0000000..85c7a15 --- /dev/null +++ b/.metrics @@ -0,0 +1,9 @@ +MetricFu::Configuration.run do |config| + config.metrics.delete(:flog) + config.metrics.delete(:rcov) + + config.flay = { :dirs_to_flay => ["lib","config/server/datasets"] } + config.reek = { :dirs_to_reek => ["lib","config/server/datasets"] } + config.roodi = { :dirs_to_roodi => ["lib","config/server/datasets"] } + +end diff --git a/Capfile b/Capfile index b9d229a..c8dbed8 100644 --- a/Capfile +++ b/Capfile @@ -2,6 +2,7 @@ load 'deploy' if respond_to?(:namespace) # cap2 differentiator require 'rubygems' require 'railsless-deploy' +require 'bundler/capistrano' load 'config/deploy' diff --git a/Gemfile b/Gemfile index 56b00c9..b5eba18 100644 --- a/Gemfile +++ b/Gemfile @@ -29,6 +29,9 @@ gem 'sequel', '~>3.0' gem 'mysql2' gem 'builder', '~>2.1' +# Misc +gem 'awesome_print' + group :development, :test do gem 'yard' gem 'shoulda', '>=2.11' @@ -40,8 +43,5 @@ group :development, :test do gem 'capistrano-ext' gem 'railsless-deploy' gem 'simplecov', :platforms => :ruby_19 - gem 'rcov', :platforms => :ruby_18 - gem 'metric_fu' - gem 'awesome_print', :require => 'ap' gem 'wirble' end \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 1dd3c11..291d7ac 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,16 +1,14 @@ GEM remote: http://rubygems.org/ specs: - Saikuro (1.1.0) abstract (1.0.0) - activesupport (3.0.3) + activesupport (3.0.4) addressable (2.2.3) - arrayfields (4.7.4) - awesome_print (0.3.1) - biomart (0.2.0) + awesome_print (0.3.2) + biomart (0.2.1) builder - bson (1.2.0) - bson_ext (1.2.0) + bson (1.2.1) + bson_ext (1.2.1) builder (2.1.2) capistrano (2.5.19) highline @@ -20,7 +18,7 @@ GEM net-ssh-gateway (>= 1.0.0) capistrano-ext (1.2.1) capistrano (>= 1.0.0) - capybara (0.4.0) + capybara (0.4.1.2) celerity (>= 0.7.9) culerity (>= 0.2.4) mime-types (>= 1.16) @@ -28,65 +26,30 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) selenium-webdriver (>= 0.0.27) - xpath (~> 0.1.2) - celerity (0.8.4) - childprocess (0.1.4) + xpath (~> 0.1.3) + celerity (0.8.7) + childprocess (0.1.6) ffi (~> 0.6.3) - chronic (0.2.3) - hoe (>= 1.2.1) - churn (0.0.13) - chronic (>= 0.2.3) - hirb - json_pure - main - ruby_parser (~> 2.0.4) - sexp_processor (~> 3.0.3) closure-compiler (1.0.0) - colored (1.2) crack (0.1.8) - culerity (0.2.12) + culerity (0.2.15) emk-sinatra-url-for (0.2.1) sinatra (>= 0.9.1.1) erubis (2.6.6) abstract (>= 1.0.0) - fattr (2.2.0) ffi (0.6.3) rake (>= 0.8.7) - flay (1.4.1) - ruby_parser (~> 2.0) - sexp_processor (~> 3.0) - flog (2.5.0) - ruby_parser (~> 2.0) - sexp_processor (~> 3.0) - haml (3.0.25) highline (1.6.1) - hirb (0.3.6) - hoe (2.8.0) - rake (>= 0.8.7) - hoptoad_notifier (2.4.2) + hoptoad_notifier (2.4.5) activesupport builder i18n (0.5.0) - json (1.4.6) - json_pure (1.4.6) - main (4.4.0) - arrayfields (>= 4.7.4) - fattr (>= 2.1.0) + json (1.5.1) + json_pure (1.5.1) memcache-client (1.8.5) - metric_fu (2.0.1) - Saikuro (>= 1.1.0) - activesupport (>= 2.0.0) - chronic (~> 0.2.3) - churn (>= 0.0.7) - flay (>= 1.2.1) - flog (>= 2.2.0) - rails_best_practices (>= 0.3.16) - rcov (>= 0.8.3.3) - reek (>= 1.2.6) - roodi (>= 2.1.0) mime-types (1.16) - mongo (1.2.0) - bson (>= 1.2.0) + mongo (1.2.1) + bson (>= 1.2.1) mongo_store (0.3.0) activesupport (>= 2.2) mongo (>= 1.0) @@ -106,42 +69,20 @@ GEM rack (>= 0.9.1) rack-test (0.5.7) rack (>= 1.0) - rails_best_practices (0.6.5) - activesupport - colored (~> 1.2) - erubis (~> 2.6.6) - haml (~> 3.0.18) - i18n - ruby-progressbar (~> 0.0.9) - ruby_parser (~> 2.0.4) railsless-deploy (1.0.2) rake (0.8.7) - rcov (0.9.9) - reek (1.2.8) - ruby2ruby (~> 1.2) - ruby_parser (~> 2.0) - sexp_processor (~> 3.0) - roodi (2.1.0) - ruby_parser - ruby-progressbar (0.0.9) - ruby2ruby (1.2.5) - ruby_parser (~> 2.0) - sexp_processor (~> 3.0) - ruby_parser (2.0.5) - sexp_processor (~> 3.0) rubytree (0.8.1) rubyzip (0.9.4) - selenium-webdriver (0.1.1) - childprocess (= 0.1.4) + selenium-webdriver (0.1.2) + childprocess (~> 0.1.5) ffi (~> 0.6.3) json_pure rubyzip - sequel (3.19.0) - sexp_processor (3.0.5) + sequel (3.20.0) shoulda (2.11.3) - simplecov (0.3.9) - simplecov-html (>= 0.3.7) - simplecov-html (0.3.9) + simplecov (0.4.0) + simplecov-html (~> 0.4.0) + simplecov-html (0.4.3) sinatra (1.1.2) rack (~> 1.1) tilt (~> 1.2) @@ -150,13 +91,13 @@ GEM rack (>= 1.0.0) sinatra (>= 0.9.1) tilt (1.2.2) - vcr (1.5.0) + vcr (1.6.0) webmock (1.6.2) addressable (>= 2.2.2) crack (>= 0.1.7) will_paginate (2.3.15) wirble (0.1.3) - xpath (0.1.2) + xpath (0.1.3) nokogiri (~> 1.3) yard (0.6.4) yui-compressor (0.9.3) @@ -180,7 +121,6 @@ DEPENDENCIES i18n json memcache-client (>= 1.8) - metric_fu mongo mongo_store mysql2 @@ -190,7 +130,6 @@ DEPENDENCIES rack-contrib rack-test (>= 0.5) railsless-deploy - rcov rubytree (~> 0.7) sequel (~> 3.0) shoulda (>= 2.11) diff --git a/config/deploy.rb b/config/deploy.rb index f223bb1..4409a64 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -13,6 +13,13 @@ role :web, 'etch-dev64.internal.sanger.ac.uk' role :app, 'etch-dev64.internal.sanger.ac.uk' +set :default_environment, { + 'PATH' => '/software/team87/brave_new_world/bin:/software/perl-5.8.8/bin:/usr/bin:/bin', + 'PERL5LIB' => '/software/team87/brave_new_world/lib/perl5:/software/team87/brave_new_world/lib/perl5/x86_64-linux-thread-multi' +} + +set :bundle_cmd, '/software/team87/brave_new_world/bin/htgt-env.pl --environment Ruby19 /software/team87/brave_new_world/app/ruby-1.9.2-p0/lib/ruby/gems/1.9/bin/bundle' + namespace :deploy do desc 'Restart Passenger' task :restart, :roles => :app, :except => { :no_release => true } do diff --git a/config/index.json b/config/index.json index be11120..d7f1769 100644 --- a/config/index.json +++ b/config/index.json @@ -52,6 +52,11 @@ "phenotype": { "type": "text", "indexed": true, "stored": true, "multi_valued": true }, "sanger_expression": { "type": "text", "indexed": true, "stored": false, "multi_valued": true }, "expression": { "type": "text", "indexed": true, "stored": true, "multi_valued": true }, + "ma_id": { "type": "text", "indexed": true, "stored": true, "multi_valued": true }, + "ma_term": { "type": "text", "indexed": true, "stored": true, "multi_valued": true }, + "MA": { "type": "textTight", "indexed": true, "stored": false, "multi_valued": true }, + "ma": { "type": "textTight", "indexed": true, "stored": false, "multi_valued": true }, + "ma_ontology": { "type": "text", "indexed": true, "stored": true, "multi_valued": true }, "mp_id": { "type": "text", "indexed": true, "stored": true, "multi_valued": true }, "mp_term": { "type": "text", "indexed": true, "stored": true, "multi_valued": true }, "MP": { "type": "textTight", "indexed": true, "stored": false, "multi_valued": true }, @@ -93,6 +98,8 @@ { "source": "marker_symbol", "dest": "symbol" }, { "source": "product_status", "dest": "product_status_str" }, { "source": "ikmc_project_product_status","dest": "ikmc_project_product_status_str" }, + { "source": "ma_id", "dest": "MA" }, + { "source": "ma_id", "dest": "ma" }, { "source": "mp_id", "dest": "MP" }, { "source": "mp_id", "dest": "mp" }, { "source": "go_id", "dest": "GO" }, @@ -132,6 +139,8 @@ { "source": "phenotype", "dest": "text" }, { "source": "sanger_expression", "dest": "text" }, { "source": "expression", "dest": "text" }, + { "source": "ma_id", "dest": "text" }, + { "source": "ma_term", "dest": "text" }, { "source": "mp_id", "dest": "text" }, { "source": "mp_term", "dest": "text" }, { "source": "go_id", "dest": "text" }, diff --git a/config/index_builder/datasets/wtsi-phenotyping-published_images.json b/config/index_builder/datasets/wtsi-phenotyping-published_images.json new file mode 100644 index 0000000..2805255 --- /dev/null +++ b/config/index_builder/datasets/wtsi-phenotyping-published_images.json @@ -0,0 +1,20 @@ +{ + "datasource": "wtsi-phenotyping", + "indexing": { + "allow_document_creation": false, + "days_between_downlads": 0, + "attribute_map": [ + { "attr": "published_images_colony_prefix", "idx": "colony_prefix", "use_to_map": true }, + { "attr": "published_images_annotations", "idx": "ignore_me" } + ], + "filters": {}, + "concatenated_ontology_terms": { + "attr": "published_images_annotations", + "split_on": "; ", + "ontologies": { + "^MA\\:\\d+$": { "term": "ma_id", "term_name": "ma_term", "breadcrumb": "ma_ontology" }, + "^MP\\:\\d+$": { "term": "mp_id", "term_name": "mp_term", "breadcrumb": "mp_ontology" } + } + } + } +} \ No newline at end of file diff --git a/config/index_builder/index_builder.json b/config/index_builder/index_builder.json index 02c64bf..cbca866 100644 --- a/config/index_builder/index_builder.json +++ b/config/index_builder/index_builder.json @@ -7,6 +7,7 @@ "ikmc-kermits", "wtsi-phenotyping-heatmap", "wtsi-phenotyping-adult_expression", + "wtsi-phenotyping-published_images", "eurexpress", "europhenome", "emma-strains", diff --git a/config/server/datasets/emma-strains/custom_sort.rb b/config/server/datasets/emma-strains/custom_sort.rb index 25395ac..89d3b70 100644 --- a/config/server/datasets/emma-strains/custom_sort.rb +++ b/config/server/datasets/emma-strains/custom_sort.rb @@ -5,20 +5,13 @@ def emma_strains_sort_results( results ) sorted_results = {} results.each do |result| - joined_attribute = @config[:searching][:joined_attribute].to_sym + joined_attribute = result[ @config[:searching][:joined_attribute].to_sym ] + emma_id = result[:emma_id] - unless sorted_results[ result[ joined_attribute ] ] - sorted_results[ result[ joined_attribute ] ] = {} - end - - unless sorted_results[ result[ joined_attribute ] ][ result[:emma_id] ] - sorted_results[ result[ joined_attribute ] ][ result[:emma_id] ] = { - :references => {}, - :availability => [] - } - end + sorted_results[joined_attribute] ||= {} + sorted_results[joined_attribute][emma_id] ||= { :references => {}, :availability => [] } - emma_record = sorted_results[ result[ joined_attribute ] ][ result[:emma_id] ] + emma_record = sorted_results[joined_attribute][emma_id] # Add singular info first... singles = [ @@ -42,17 +35,12 @@ def emma_strains_sort_results( results ) emma_record[:allele_name] = fix_superscript_text_in_attribute(result[:alls_form]) # References... - unless result[:pubmed_id].nil? - emma_record[:references][result[:pubmed_id]] = { - :pubmed_id => result[:pubmed_id], - :reference => result[:reference] - } - end + pubmed_id = result[:pubmed_id] + emma_record[:references][pubmed_id] = { :pubmed_id => pubmed_id, :reference => result[:reference] } unless pubmed_id.nil? # Availability... - unless result[:availability].nil? - emma_record[:availability].push(result[:availability]) - end + availability = result[:availability] + emma_record[:availability].push(availability) unless availability.nil? end return sorted_results diff --git a/config/server/datasets/ensembl-mouse-homologs/custom_sort.rb b/config/server/datasets/ensembl-mouse-homologs/custom_sort.rb index 66b781a..ca0d868 100644 --- a/config/server/datasets/ensembl-mouse-homologs/custom_sort.rb +++ b/config/server/datasets/ensembl-mouse-homologs/custom_sort.rb @@ -5,29 +5,21 @@ def ensembl_mouse_homologs_sort_results( results ) sorted_results = {} results.each do |result| - joined_attribute = @config[:searching][:joined_attribute].to_sym + joined_attribute = result[ @config[:searching][:joined_attribute].to_sym ] - if sorted_results[ result[ joined_attribute ] ].nil? - sorted_results[ result[ joined_attribute ] ] = {} - - result.keys.each do |key| - sorted_results[ result[ joined_attribute ] ][key] = [] - end - end - - result_data = sorted_results[ result[ joined_attribute ] ] + sorted_results[joined_attribute] ||= {} + result_data = sorted_results[joined_attribute] result.keys.each do |key| + result_data[key] ||= [] result_data[key].push( result[key] ) end end # Finally, ensure that the data in the arrays is unique sorted_results.each do |key,result_data| - result_data.keys.each do |field| - if result_data[field].is_a?(Array) - result_data[field].uniq! - end + result_data.keys.each do |field,field_data| + field_data.uniq! if field_data.is_a?(Array) end end diff --git a/config/server/datasets/eurexpress/custom_sort.rb b/config/server/datasets/eurexpress/custom_sort.rb index 06c484a..0024ace 100644 --- a/config/server/datasets/eurexpress/custom_sort.rb +++ b/config/server/datasets/eurexpress/custom_sort.rb @@ -6,32 +6,20 @@ def eurexpress_sort_results( results ) # chart_config = @config[:chart_config] results.each do |result| - joined_attribute = @config[:searching][:joined_attribute].to_sym + joined_attribute = result[ @config[:searching][:joined_attribute].to_sym ] + ass_assay_id_key = result[:ass_assay_id_key] - unless sorted_results[ result[ joined_attribute ] ] - sorted_results[ result[ joined_attribute ] ] = {} - end - - result_data = sorted_results[ result[ joined_attribute ] ] - - unless result_data[ result[:ass_assay_id_key] ] - result_data[ result[:ass_assay_id_key] ] = {} - # chart_config.keys.each do |field| - # result_data[ result[:ass_assay_id_key] ][:chart][field] = { - # :score => 0, - # :found_terms => [] - # } - # end - end + result_data = sorted_results[joined_attribute] ||= {} + result_data_for_assay = result_data[ass_assay_id_key] ||= {} - result_data_for_assay = result_data[ result[:ass_assay_id_key] ] - result_data_for_assay[:assay_id] = result[:ass_assay_id_key] - result_data_for_assay[:assay_image_count] = result[:assay_image_count] + # chart_config.keys.each do |field| + # result_data_for_assay[:chart][field] = { :score => 0, :found_terms => [] } + # end - unless result_data_for_assay[:annotations] - result_data_for_assay[:annotations] = {} - end + result_data_for_assay[:assay_id] = ass_assay_id_key + result_data_for_assay[:assay_image_count] = result[:assay_image_count] + result_data_for_assay[:annotations] ||= {} emap_id = result[:emap_id] emap_id = "EMAP:#{emap_id}" unless emap_id =~ /EMAP/ @@ -68,7 +56,7 @@ def eurexpress_sort_results( results ) the_results.each do |assay_id,assay_data| assays.push(assay_data) end - results_to_return[id] = assays.sort_by { |a| -1*(a[:annotations].size) } + results_to_return[id] = assays.sort_by { |elm| -1*(elm[:annotations].size) } end # Now calculate the EMAP ontology trees for the annotations and diff --git a/config/server/datasets/wtsi-phenotyping-heatmap/custom_secondary_sort.rb b/config/server/datasets/wtsi-phenotyping-heatmap/custom_secondary_sort.rb index 5bc306d..974e3f9 100644 --- a/config/server/datasets/wtsi-phenotyping-heatmap/custom_secondary_sort.rb +++ b/config/server/datasets/wtsi-phenotyping-heatmap/custom_secondary_sort.rb @@ -133,8 +133,8 @@ def wtsi_phenotyping_heatmap_secondary_sort( search_data ) if result_data[:'wtsi-phenotyping-heatmap_graphs'] mgp_graphs = result_data[:'wtsi-phenotyping-heatmap_graphs'][result[:colony_prefix].to_sym] unless mgp_graphs.nil? - mgp_graphs.each do |test_name,image_data| - if test_display_name.gsub("\(","").gsub("\)","") =~ Regexp.new(image_data[0][:heatmap_group], true) + mgp_graphs.each do |heatmap_group,image_data| + if test_display_name.gsub("\(","").gsub("\)","") =~ Regexp.new(heatmap_group.to_s, true) result["#{test}_data".to_sym] = image_data end end @@ -167,14 +167,11 @@ def wtsi_phenotyping_heatmap_secondary_sort( search_data ) if result_data[:'wtsi-phenotyping-published_images'] images = result_data[:'wtsi-phenotyping-published_images'][result[:colony_prefix].to_sym] - if images and ( images[:adult] and !images[:adult].empty? ) - result[:adult_expression_data] = {} if result[:adult_expression_data].nil? - result[:adult_expression_data][:images] = images[:adult] - end - - if images and ( images[:embryo] and !images[:embryo].empty? ) - result[:embryo_expression_data] = {} if result[:embryo_expression_data].nil? - result[:embryo_expression_data][:images] = images[:embryo] + ['adult_expression','embryo_expression','skin_screen'].each do |image_group| + if images && ( images[image_group.to_sym] && !images[image_group.to_sym].empty? ) + result["#{image_group}_data".to_sym] = {} if result["#{image_group}_data".to_sym].nil? + result["#{image_group}_data".to_sym][:images] = images[image_group.to_sym] + end end end @@ -239,7 +236,7 @@ def wtsi_phenotyping_heatmap_secondary_sort( search_data ) end end - #result_data[:'cached_pheno_data'] = cache_data + result_data[:'cached_pheno_data'] = cache_data end end diff --git a/config/server/datasets/wtsi-phenotyping-heatmap_graphs/custom_sort.rb b/config/server/datasets/wtsi-phenotyping-heatmap_graphs/custom_sort.rb index 5ebbe74..cbdcb58 100644 --- a/config/server/datasets/wtsi-phenotyping-heatmap_graphs/custom_sort.rb +++ b/config/server/datasets/wtsi-phenotyping-heatmap_graphs/custom_sort.rb @@ -11,37 +11,50 @@ def wtsi_phenotyping_heatmap_graphs_sort_results( results ) processed_result = {} result.each do |key,value| processed_result[key] = value if key == @config[:searching][:joined_attribute].to_sym - processed_result[ key.to_s.gsub(prefix,'').to_sym ] = value + processed_result[key.to_s.gsub(prefix,'').to_sym] = value end processed_results.push(processed_result) end results = processed_results results.each do |result| - joined_attribute = @config[:searching][:joined_attribute].to_sym + joined_attribute = result[ @config[:searching][:joined_attribute].to_sym ] + colony_prefix = result[:colony_prefix] + heatmap_group = result[:heatmap_group] + protocol = result[:heatmap_group_description] - unless sorted_results[ result[ joined_attribute ] ] - sorted_results[ result[ joined_attribute ] ] = {} - end + sorted_results[joined_attribute] ||= {} + sorted_results[joined_attribute][colony_prefix] ||= {} - unless sorted_results[ result[ joined_attribute ] ][result[:colony_prefix]] - sorted_results[ result[ joined_attribute ] ][result[:colony_prefix]] = {} - end + result.delete(:colony_prefix) + result.delete(:heatmap_graphs_colony_prefix) + result.delete(:heatmap_group) + result.delete(:heatmap_group_description) - unless sorted_results[result[ joined_attribute ]][result[:colony_prefix]][result[:heatmap_group]] - sorted_results[result[ joined_attribute ]][result[:colony_prefix]][result[:heatmap_group]] = [] + if protocol.nil? + # This is a PDF (or collaborator) download - they don't have descriptions in the MIG system + sorted_results[joined_attribute][colony_prefix][heatmap_group] ||= [] + sorted_results[joined_attribute][colony_prefix][heatmap_group].push(result) + else + # 'Regular' published graphs... + sorted_results[joined_attribute][colony_prefix][heatmap_group] ||= {} + sorted_results[joined_attribute][colony_prefix][heatmap_group][protocol] ||= [] + sorted_results[joined_attribute][colony_prefix][heatmap_group][:heatmap_group] = heatmap_group + + sorted_results[joined_attribute][colony_prefix][heatmap_group][protocol].push(result) end - - sorted_results[result[ joined_attribute ]][result[:colony_prefix]][result[:heatmap_group]].push(result) - end - sorted_results.each do |colony,data| - sorted_results[colony][colony].each do |test,images| - sorted_results[colony][colony][test] = images.sort{ |a,b| a[:order_by] <=> b[:order_by] } + sorted_results.keys.each do |colony_prefix| + sorted_results[colony_prefix][colony_prefix].each do |heatmap_group,heatmap_group_data| + next if heatmap_group_data.is_a? Array + heatmap_group_data.each do |protocol,protocol_data| + next if protocol == :heatmap_group + protocol_data.sort!{ |a,b| a[:order_by] <=> b[:order_by] } + end end - sorted_results[colony].recursively_symbolize_keys! + sorted_results[colony_prefix].recursively_symbolize_keys! end return sorted_results diff --git a/config/server/datasets/wtsi-phenotyping-published_images/config.json b/config/server/datasets/wtsi-phenotyping-published_images/config.json index decde56..b4571a8 100644 --- a/config/server/datasets/wtsi-phenotyping-published_images/config.json +++ b/config/server/datasets/wtsi-phenotyping-published_images/config.json @@ -28,7 +28,7 @@ "published_images_url" ], "filters": { - "published_images_image_type": "Wholemount Expression", + "published_images_image_type": ["Wholemount Expression","Confocal Skin Screen"], "published_images_genotype": ["Heterozygous","Homozygous","Hemizygous"] } } diff --git a/config/server/datasets/wtsi-phenotyping-published_images/custom_sort.rb b/config/server/datasets/wtsi-phenotyping-published_images/custom_sort.rb index a0f1b13..37bd9b2 100644 --- a/config/server/datasets/wtsi-phenotyping-published_images/custom_sort.rb +++ b/config/server/datasets/wtsi-phenotyping-published_images/custom_sort.rb @@ -26,8 +26,9 @@ def wtsi_phenotyping_published_images_sort_results( results ) unless sorted_results[ result[ joined_attribute ] ][ result[:colony_prefix].to_sym ] sorted_results[ result[ joined_attribute ] ][ result[:colony_prefix].to_sym ] = { - :adult => [], - :embryo => [] + :adult_expression => [], + :embryo_expression => [], + :skin_screen => [] } end @@ -36,14 +37,18 @@ def wtsi_phenotyping_published_images_sort_results( results ) # work out the thumbnail URL (as the one in the mart can be flakey...) result[:thumbnail_url] = result[:url].sub("\.(\w+)$","thumb.\1") - if result[:tissue].match("Embryo") - if result[:tissue].match("14.5") - result_data[:embryo].push(result) + case result[:image_type] + when 'Wholemount Expression' + if result[:tissue].match('Embryo') + if result[:tissue].match('14.5') + result_data[:embryo_expression].push(result) + end + else + result_data[:adult_expression].push(result) end - else - result_data[:adult].push(result) + when 'Confocal Skin Screen' + result_data[:skin_screen].push(result) end - end return sorted_results diff --git a/config/server/dataviews/wtsi-phenotyping/javascript_base.js b/config/server/dataviews/wtsi-phenotyping/javascript_base.js index 395ae43..518f3ba 100644 --- a/config/server/dataviews/wtsi-phenotyping/javascript_base.js +++ b/config/server/dataviews/wtsi-phenotyping/javascript_base.js @@ -4,7 +4,7 @@ jQuery(".wtsi-phenotyping table.wtsi-phenotyping_heatmap").delegate( 'td.pheno_result', 'mouseover', - function(event) { + function (event) { jQuery(this).attr( "tooltip", jQuery(this).attr("title") ); jQuery(this).attr( "title", "" ); jQuery(this).qtip({ @@ -29,3 +29,33 @@ jQuery(".wtsi-phenotyping table.wtsi-phenotyping_heatmap").delegate( event } ); + +jQuery(".wtsi-phenotyping table.wtsi-phenotyping_heatmap_legend").delegate( + "span[rel='qtip']", + 'mouseover', + function (event) { + jQuery(this).attr( "tooltip", jQuery(this).attr("title") ); + jQuery(this).attr( "title", "" ); + jQuery(this).qtip({ + content: jQuery(this).attr("tooltip"), + overwrite: false, + style: { + tip: "topMiddle", + classes: "ui-tooltip-light ui-tooltip-rounded ui-tooltip-shadow" + }, + position: { + at: "bottom center", + my: "top center", + adjust: { + screen: true + } + }, + show: { + event: event.type, + ready: true + } + }); + event + } +); + diff --git a/config/server/dataviews/wtsi-phenotyping/routes.rb b/config/server/dataviews/wtsi-phenotyping/routes.rb index fb51587..d22b627 100644 --- a/config/server/dataviews/wtsi-phenotyping/routes.rb +++ b/config/server/dataviews/wtsi-phenotyping/routes.rb @@ -74,11 +74,23 @@ class Server erubis :not_found else @page_title = "#{@data[:marker_symbol]} (#{@colony_prefix}): Embryo Expression" - # @bg_staining_imgs = @ms.dataviews_by_name[:'wtsi-phenotyping'].config[:wt_lacz_background_staining_embryo] erubis :"dataviews/wtsi-phenotyping/embryo_expression_details" end end + get "/phenotyping/:colony_prefix/skin-screen/?" do + @colony_prefix = params[:colony_prefix].upcase + @data = wtsi_phenotyping_fetch_report_data( @colony_prefix, 'skin_screen' ) + + if @data.nil? + status 404 + erubis :not_found + else + @page_title = "#{@data[:marker_symbol]} (#{@colony_prefix}): Skin Screen" + erubis :"dataviews/wtsi-phenotyping/skin_screen_details" + end + end + get "/phenotyping/:colony_prefix/homozygote-viability/?" do @colony_prefix = params[:colony_prefix].upcase @data = wtsi_phenotyping_fetch_report_data( @colony_prefix, 'homozygote_viability' ) @@ -119,9 +131,8 @@ class Server status 404 erubis :not_found else - @marker_symbol = @data[0][:marker_symbol] - @test_name = @data[0][:heatmap_group] - @test_desc = @data[0][:heatmap_group_description] + @marker_symbol = @data[:marker_symbol] + @test_name = @data[:heatmap_group] @page_title = "#{@marker_symbol} (#{@colony_prefix}): #{@test_name}" erubis :"dataviews/wtsi-phenotyping/test_details" end diff --git a/config/server/dataviews/wtsi-phenotyping/stylesheet.css b/config/server/dataviews/wtsi-phenotyping/stylesheet.css index 690d2a1..df6f1b5 100644 --- a/config/server/dataviews/wtsi-phenotyping/stylesheet.css +++ b/config/server/dataviews/wtsi-phenotyping/stylesheet.css @@ -1,3 +1,4 @@ + /* wtsi-phenotyping custom css */ .wtsi-phenotyping table td { background: #fff; } @@ -7,6 +8,7 @@ .wtsi-phenotyping table td.no_significant_difference { background-color: #6998cb; } .wtsi-phenotyping table td.not_applicable { background-color: #ccc; } .wtsi-phenotyping table td.early_indication_of_possible_phenotype { background-color: #fcfe66; } +.wtsi-phenotyping table td.test_abandoned { background: transparent url(../images/diagonal_line.png) no-repeat center center; } .wtsi-phenotyping table td.pheno_result { text-align: center; vertical-align: middle; @@ -42,6 +44,11 @@ padding-bottom: 5px; } +table.wtsi-phenotyping_heatmap_legend { + border-collapse: separate; + border-spacing: 1px; +} + /* Phenotyping details pages */ #wtsi-phenotyping-report #test-images { @@ -138,12 +145,12 @@ table.expression_ticklist td.ambiguous { text-transform: lowercase; } -.wtsi-phenotyping-expression-images { +.wtsi-phenotyping-images { margin: 0 auto; text-align: center; } -.wtsi-phenotyping-expression-image-list li { +.wtsi-phenotyping-image-list li { list-style-type: none; margin: 5px; padding: 5px; @@ -164,7 +171,7 @@ table.expression_ticklist td.ambiguous { _height: 190px; } -.wtsi-phenotyping-expression-image-list li img { +.wtsi-phenotyping-image-list li img { padding: 2px; border: 1px solid #ccc; background-color: #fff; @@ -176,20 +183,20 @@ table.expression_ticklist td.ambiguous { width: 180px; } -.wtsi-phenotyping-expression-image-list li img:hover { +.wtsi-phenotyping-image-list li img:hover { background-color: #fcf9b2; } -.wtsi-phenotyping-expression-image-list .gender { +.wtsi-phenotyping-image-list .gender { width: 16px; height: 16px; float: right; } -.wtsi-phenotyping-expression-image-list .male { +.wtsi-phenotyping-image-list .male { background-image: url(../images/silk/male.png); } -.wtsi-phenotyping-expression-image-list .female { +.wtsi-phenotyping-image-list .female { background-image: url(../images/silk/female.png); } diff --git a/config/server/dataviews/wtsi-phenotyping/views/_heatmap_legend.erubis b/config/server/dataviews/wtsi-phenotyping/views/_heatmap_legend.erubis index 967d04f..c21b35f 100644 --- a/config/server/dataviews/wtsi-phenotyping/views/_heatmap_legend.erubis +++ b/config/server/dataviews/wtsi-phenotyping/views/_heatmap_legend.erubis @@ -1,34 +1,86 @@ +<% + legend_rows_conf = [ + [ + { + :text => 'Test complete and data/resources are available', + :desc => 'Tissue blocks, images or data are available to researchers for further analysis.', + :class => 'completed_data_available' + }, + { + :text => 'Test is complete and the data are considered interesting', + :desc => 'Phenotyping is complete, genotypes have been confirmed and the data has passed the QC process. The data generated from the analysis of the mutant mice are considered interesting.', + :class => 'significant_difference' + }, + { + :text => 'Preliminary indication of an interesting phenotype', + :desc => 'Phenotyping is in progress. At least three mice have been tested and the preliminary data are considered interesting.', + :class => 'early_indication_of_possible_phenotype' + } + ], + [ + { + :text => 'Test is complete but the data are not considered interesting', + :desc => 'Phenotyping is complete, genotypes have been confirmed and the data has passed the QC process. The data generated from the analysis of the mutant mice are not considered interesting.', + :class => 'no_significant_difference' + }, + { + :text => 'Test not performed or applicable', + :desc => 'The test has not been performed. This may be the result of equipment failure, the mice being deemed unsuitable to perform the test or the inability to derive a readout (e.g. the targeting construct lacks a LacZ reporter gene resulting in absence of expression data).', + :class => 'not_applicable' + }, + { + :text => 'Test pending', + :desc => " +

Two situations fit the test pending category:

+
    +
  1. Phenotyping is in progress and less than three mice have been tested.
  2. +
  3. Phenotyping is in progress, at least three mice have been tested and the preliminary data are not considered interesting.
  4. +
+ ", + :class => 'test_pending' + } + ], + [ + { + :text => 'Test abandoned', + :desc => 'The test has been removed from our high-throughput phenotyping project and has therefore not been performed on mice bearing this mutation.', + :class => 'test_abandoned' + }, + { + :text => 'Link to a test report page', + :img_tag => image_tag( '/images/silk/chart_bar.png', :alt => 'Link to a Test Report Page' ), + }, + { + :text => 'Link to a pdf report', + :img_tag => image_tag( '/images/silk/page_white_acrobat.png', :alt => 'Link to a PDF Report' ), + } + ] + ] +%> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + <% legend_rows_conf.each do |row| %> + + <% row.each do |legend_opt| %> + + + + <% end %> + + <% end %>
Legend:Test complete and data/resources availableTest complete and considered interesting
Early indication of possible phenotypeTest complete but not considered interesting
Test not performed or applicable e.g. no lacZ reporter therefore no expressionTest pending
<%= image_tag( '/images/silk/chart_bar.png', :alt => 'Link to a Test Report Page' ) %>link to a test report page<%= image_tag( '/images/silk/page_white_acrobat.png', :alt => 'Link to a PDF Report' ) %>link to a pdf report + Legend - hover over each heading to get a more complete description +
+ <% unless legend_opt[:img_tag].nil? %> + <%= legend_opt[:img_tag] %> + <% end %> + + <% if legend_opt[:desc].nil? %> + <%= legend_opt[:text] %> + <% else %> + <%= legend_opt[:text] %> + <% end %> +
\ No newline at end of file diff --git a/config/server/dataviews/wtsi-phenotyping/views/_expression_images.erubis b/config/server/dataviews/wtsi-phenotyping/views/_images.erubis similarity index 82% rename from config/server/dataviews/wtsi-phenotyping/views/_expression_images.erubis rename to config/server/dataviews/wtsi-phenotyping/views/_images.erubis index a3c6445..681f27e 100644 --- a/config/server/dataviews/wtsi-phenotyping/views/_expression_images.erubis +++ b/config/server/dataviews/wtsi-phenotyping/views/_images.erubis @@ -8,7 +8,7 @@
{ :img => img } ) %>" + title="<%= partial( "dataviews/wtsi-phenotyping/images_legend", :locals => { :img => img } ) %>" rel="prettyPhoto[<%= gallery_name %>]" > <%= img[:tissue] %> (<%= img[:gender] %> / <%= img[:genotype] %>) diff --git a/config/server/dataviews/wtsi-phenotyping/views/_expression_image_legend.erubis b/config/server/dataviews/wtsi-phenotyping/views/_images_legend.erubis similarity index 100% rename from config/server/dataviews/wtsi-phenotyping/views/_expression_image_legend.erubis rename to config/server/dataviews/wtsi-phenotyping/views/_images_legend.erubis diff --git a/config/server/dataviews/wtsi-phenotyping/views/_skin_screen_ticklist.erubis b/config/server/dataviews/wtsi-phenotyping/views/_skin_screen_ticklist.erubis new file mode 100644 index 0000000..afe42f6 --- /dev/null +++ b/config/server/dataviews/wtsi-phenotyping/views/_skin_screen_ticklist.erubis @@ -0,0 +1 @@ +To be done... \ No newline at end of file diff --git a/config/server/dataviews/wtsi-phenotyping/views/adult_expression_details.erubis b/config/server/dataviews/wtsi-phenotyping/views/adult_expression_details.erubis index 426950c..d076d06 100644 --- a/config/server/dataviews/wtsi-phenotyping/views/adult_expression_details.erubis +++ b/config/server/dataviews/wtsi-phenotyping/views/adult_expression_details.erubis @@ -57,11 +57,11 @@
Images
-
+
<% unless @data[:images].nil? or @data[:images].empty? %> -
Background LacZ Staining in Adult
-
+

The adult wholemount LacZ expression protocol has been refined to minimize background staining however, it can still occur. We have systematically @@ -98,9 +98,9 @@ Examples of the pattern and level of background stain are presented below.

-
    +
      <% @bg_staining_imgs.each do |img| %> - <%= partial( "dataviews/wtsi-phenotyping/expression_images", :locals => { :img => img, :gallery_name => "bgstain" } ) %> + <%= partial( "dataviews/wtsi-phenotyping/images", :locals => { :img => img, :gallery_name => "bgstain" } ) %> <% end %>
diff --git a/config/server/dataviews/wtsi-phenotyping/views/embryo_expression_details.erubis b/config/server/dataviews/wtsi-phenotyping/views/embryo_expression_details.erubis index 9558d2f..598d9d6 100644 --- a/config/server/dataviews/wtsi-phenotyping/views/embryo_expression_details.erubis +++ b/config/server/dataviews/wtsi-phenotyping/views/embryo_expression_details.erubis @@ -53,11 +53,11 @@
Images
-
+
<% unless @data[:images].nil? or @data[:images].empty? %> -
    +
      <% @data[:images].each do |img| %> - <%= partial( "dataviews/wtsi-phenotyping/expression_images", :locals => { :img => img, :gallery_name => "embryoexp" } ) %> + <%= partial( "dataviews/wtsi-phenotyping/images", :locals => { :img => img, :gallery_name => "embryoexp" } ) %> <% end %>
    <% else %> @@ -66,7 +66,7 @@
Background LacZ Staining in Embryo - No background LacZ staining detected in day 14.5 embryos
-
+
No background LacZ staining detected in day 14.5 embryos
diff --git a/config/server/dataviews/wtsi-phenotyping/views/skin_screen_details.erubis b/config/server/dataviews/wtsi-phenotyping/views/skin_screen_details.erubis new file mode 100644 index 0000000..bcf841c --- /dev/null +++ b/config/server/dataviews/wtsi-phenotyping/views/skin_screen_details.erubis @@ -0,0 +1,101 @@ +
+

Skin Screen Data for <%= @data[:marker_symbol] %> (<%= @colony_prefix %>)

+ +
+

Overview

+
+

+ Skin screen collaboration (Mice were fed on Mouse Breeder Diet (5021, Labdiet) from weaning): Tails were + collected in duplicate from mutant and wild type mice of the same genetic background (≥ 14 weeks). Epidermal + whole mounts were prepared by separating the epidermis from the underlying dermis as an intact sheet following + EDTA digestion. The epidermis was fixed in 4% paraformaldehyde and permeabilised, then stained using a rapid + labelling protocol with antibodies to keratin 14 and 15 (K14, K15) that were directly conjugated with + fluorophores (Alexa 555 (red) for K14 and 488 (green) for K15). Whole mounts were counter-stained with DAPI to + reveal cell nuclei (blue). Preparations’ were imaged using a Leica SP5 Confocal microscope and Maximum Intensity + Projections produced from ~150um Z-series at 4um spacing. DAPI, Alexa 488 and Alexa555 channels were merged. + Images are x10 magnification unless otherwise indicated. +

+
+
+ +
+

Evaluation of Phenotype

+
+

+ A tick-list was used to record the presence (red cross) or absence (green tick) of a phenotype in the epidermis. +

+

+ K14 is expressed in basal layer epidermal cells in the interfollicular epidermis (IFE), sebaceous gland (SG) and + hair follicles (HF). DAPI staining provides an indication of cell density and K15 is most highly expressed in the HF + bulge, which is a stem cell reservoir. +

+

+ In tail epidermis melanocytes reside in the HF and also in the IFE immediately adjacent to the HF (parakeratotic + scale). In some mutant mice pigmentation in the IFE is altered and this is recorded in bright-field images. +

+

+ In the tick-list, abnormal K14 expression would indicate loss of expression. Abnormal K15 expression indicates + either abnormal bulge morphology or altered K15 expression (for example, reduced in the bulge or up-regulated + outside the bulge). In tail epidermis the HF are normally arranged in groups of three (triplets) and in + staggered rows; abnormalities in HF patterning include changes in number of HF per group and distance between + rows. The hair growth cycle in tail epidermis is less highly synchronised than in the back and the mice analysed + are not closely age-matched. Therefore, detailed evaluation of the hair cycle has not been performed; + nevertheless, obvious disturbance, such as all HF being in catagen, is recorded. The SG are K14-positive + sack-like structures that lie above the bulge; changes in SG size, number or morphology are recorded as + abnormal. Changes in the IFE include hyperproliferation (detected as increased basal layer density and + enveloping of the junction with the HF), hypocellularity and altered pigmentation. +

+

+ If information or images that you are interested in are not presented, please send + details to MGPenquiries@sanger.ac.uk + and, on a limited, first come first served basis, we will process your request. +

+
+
+ +
+
Tick-List
+
+ <%= partial( "dataviews/wtsi-phenotyping/skin_screen_ticklist" ) %> +
+ +
Images
+
+ <% unless @data[:images].nil? or @data[:images].empty? %> +
    + <% @data[:images].each do |img| %> + <%= partial( "dataviews/wtsi-phenotyping/images", :locals => { :img => img, :gallery_name => "skinscreen" } ) %> + <% end %> +
+ <% else %> +
no data reported
+ <% end %> +
+ +
Reference Wildtype Images
+
+ To be done... +
+ +
Collaborator Information
+
+

+ The screen is being performed by Emma Heath in the laboratory of Fiona Watt, assisted by Elizabeth MacRae and + Kifayathullah Liakath Ali. Our website is: http://www.bio.cam.ac.uk/~wattlab/. We gratefully acknowledge the financial support of + Cancer Research UK, the Medical Research Council, the Wellcome Trust and the European Union. The references + below are the original description of the whole mount tail epidermal preparation (Braun et al., 2003) and a + review on different epidermal stem cell populations (Watt and Jensen, 2009). +

+

+ Braun, K.M., Niemann,C., Jensen, U.B., Sundberg, J.P., Silva-Vargas, V. and Watt, F.M. (2003) + Manipulation of stem cell proliferation and lineage commitment: visualisation of label-retaining cells in + wholemounts of mouse epidermis. Development 130:5241-5255. +

+

+ Watt, F.M. and Jensen, K.B. (2009). Epidermal stem cell diversity and quiescence. EMBO + Molecular Medicine 1:260-267. +

+
+
+
diff --git a/config/server/dataviews/wtsi-phenotyping/views/test_details.erubis b/config/server/dataviews/wtsi-phenotyping/views/test_details.erubis index cc6d4b5..ead2979 100644 --- a/config/server/dataviews/wtsi-phenotyping/views/test_details.erubis +++ b/config/server/dataviews/wtsi-phenotyping/views/test_details.erubis @@ -1,16 +1,19 @@

<%= @test_name %> Data for <%= @marker_symbol %> (<%= @colony_prefix %>)

-
-

Overview

-
- <%= @test_desc %> + <% @data.each do |protocol_desc,images| %> + <% next if [:marker_symbol,:heatmap_group].include?(protocol_desc) %> +
+

Overview

+
+ <%= protocol_desc %> +
-
- -
- <% @data.each do |img| %> - <%= img[:test] %> - <% end %> -
+ +
+ <% images.each do |img| %> + <%= img[:test] %> + <% end %> +
+ <% end %>
diff --git a/lib/martsearch.rb b/lib/martsearch.rb index 65420fd..a28b25b 100644 --- a/lib/martsearch.rb +++ b/lib/martsearch.rb @@ -1,10 +1,10 @@ +require 'rubygems' +require 'bundler/setup' + require 'singleton' require 'logger' require 'date' -require 'rubygems' -require 'bundler/setup' - require 'biomart' require 'sinatra/base' require 'erubis' @@ -23,7 +23,7 @@ require 'mongo' require 'mongo_store' -require 'ap' +require 'awesome_print' MARTSEARCH_PATH = "#{File.expand_path(File.dirname(__FILE__))}/.." @@ -42,6 +42,9 @@ module MartSearch # Error class raised when there is an error with the supplied configuration files. class InvalidConfigError < StandardError; end + # MongoDB based cache class. This is entirely ActiveSupport::Cache::MongoStore, but + # we have to ovveride it here as we're not running in a Rails environment, and we + # need to include some Rails3 mixins for it to work correctly. class MongoCache < ActiveSupport::Cache::MongoStore include ::MongoStore::Cache::Rails3 end @@ -59,11 +62,12 @@ class MongoCache < ActiveSupport::Cache::MongoStore require "#{MARTSEARCH_PATH}/lib/martsearch/controller_utils" require "#{MARTSEARCH_PATH}/lib/martsearch/controller" require "#{MARTSEARCH_PATH}/lib/martsearch/ontology_term" +require "#{MARTSEARCH_PATH}/lib/martsearch/ontology_term_cache" require "#{MARTSEARCH_PATH}/lib/martsearch/index_builder_utils" require "#{MARTSEARCH_PATH}/lib/martsearch/index_builder" -require "#{MARTSEARCH_PATH}/lib/martsearch/project_utils" require "#{MARTSEARCH_PATH}/lib/martsearch/server_utils" require "#{MARTSEARCH_PATH}/lib/martsearch/server_view_helpers" +require "#{MARTSEARCH_PATH}/lib/martsearch/project_utils" require "#{MARTSEARCH_PATH}/lib/martsearch/server" diff --git a/lib/martsearch/array.rb b/lib/martsearch/array.rb index d9a285b..82b60fb 100644 --- a/lib/martsearch/array.rb +++ b/lib/martsearch/array.rb @@ -12,7 +12,7 @@ class Array # "[1,2,3,4,5,6,7,8,9,10,11,12].chunk(5)" => "[[1,2,3,4,5],[6,7,8,9,10],[11,12]]" def chunk( length ) chunks = [] - each_with_index do |element,index| + self.each_with_index do |element,index| chunks << [] if index % length == 0 chunks.last << element end @@ -23,11 +23,7 @@ def chunk( length ) # @see http://snippets.dzone.com/posts/show/12019 def recursively_symbolize_keys! self.each do |item| - if item.is_a?(Hash) - item.recursively_symbolize_keys! - elsif item.is_a? Array - item.recursively_symbolize_keys! - end + item.recursively_symbolize_keys! if item.respond_to?(:recursively_symbolize_keys!) end end @@ -35,11 +31,7 @@ def recursively_symbolize_keys! # @see http://snippets.dzone.com/posts/show/12019 def recursively_stringify_keys! self.each do |item| - if item.is_a?(Hash) - item.recursively_stringify_keys! - elsif item.is_a? Array - item.recursively_stringify_keys! - end + item.recursively_stringify_keys! if item.respond_to?(:recursively_stringify_keys!) end end @@ -56,7 +48,7 @@ def randomly_pick( number ) sort_by{ rand }.slice( 0...number ) end - # Helper function for {Hash#clean_hashes} - this just call .clean_hashes + # Helper function for {Hash#clean_hashes} - just call .clean_hashes # if one of the elements of the array is an instance of Hash (or one of its children). def clean_hashes self.map do |item| diff --git a/lib/martsearch/index_builder.rb b/lib/martsearch/index_builder.rb index caed44d..322b7aa 100644 --- a/lib/martsearch/index_builder.rb +++ b/lib/martsearch/index_builder.rb @@ -298,6 +298,11 @@ def process_dataset( ds ) if ds_index_conf[:ontology_terms] index_ontology_terms( ds_index_conf[:ontology_terms], doc, data_row_obj, map_data, @ontology_cache ) end + + # Any concatenated ontology term fields... + if ds_index_conf[:concatenated_ontology_terms] + index_concatenated_ontology_terms( ds_index_conf[:concatenated_ontology_terms], doc, data_row_obj, map_data, @ontology_cache ) + end # Finally - save the document to the cache doc_primary_key = doc[@index_config[:schema][:unique_key].to_sym][0] diff --git a/lib/martsearch/index_builder_utils.rb b/lib/martsearch/index_builder_utils.rb index e5e6498..f3ed13e 100644 --- a/lib/martsearch/index_builder_utils.rb +++ b/lib/martsearch/index_builder_utils.rb @@ -213,8 +213,8 @@ def index_ontology_terms( ontology_term_conf, doc, data_row_obj, map_data, cache ontology_term_conf.each do |term_conf| attribute = term_conf[:attr] value_to_index = extract_value_to_index( attribute, map_data[:attribute_map], { attribute => data_row_obj[attribute] } ) - - if value_to_index and !value_to_index.gsub(" ","").empty? + + if value_to_index && !value_to_index.gsub(" ","").empty? cached_data = cache[value_to_index] if cached_data != nil index_ontology_terms_from_cache( doc, term_conf, cached_data ) @@ -225,6 +225,40 @@ def index_ontology_terms( ontology_term_conf, doc, data_row_obj, map_data, cache end end + + def index_concatenated_ontology_terms( concat_ont_term_conf, doc, data_row_obj, map_data, cache ) + attribute = concat_ont_term_conf[:attr] + split_delimiter = concat_ont_term_conf[:split_on] || ", " + value_to_index = extract_value_to_index( attribute, map_data[:attribute_map], { attribute => data_row_obj[attribute] } ) + + if value_to_index && !value_to_index.gsub(" ","").empty? + terms_to_test = value_to_index.split(split_delimiter) + terms_to_test.each do |test_term| + concat_ont_term_conf[:ontologies].each do |ontology_matcher,ontology_conf| + regexp = Regexp.new(ontology_matcher.to_s) + + unless test_term.match(regexp).nil? + cached_data = cache[test_term] + term_conf = { + :attr => attribute, + :idx => { + :term => ontology_conf[:term], + :term_name => ontology_conf[:term_name], + :breadcrumb => ontology_conf[:breadcrumb] + } + } + + if cached_data != nil + index_ontology_terms_from_cache( doc, term_conf, cached_data ) + else + index_ontology_terms_from_fresh( doc, term_conf, test_term, cache ) + end + end + end + end + end + end + # Utility function to create the actual XML markup for a collection # of solr document constructs. # diff --git a/lib/martsearch/ontology_term.rb b/lib/martsearch/ontology_term.rb index 0ce1052..90a7575 100644 --- a/lib/martsearch/ontology_term.rb +++ b/lib/martsearch/ontology_term.rb @@ -340,7 +340,7 @@ def get_term_details @leaf_node = true if subject[:is_leaf].to_i == 1 end end - + # Helper function to try to find an ontology term via a synonym. def get_term_from_synonym sql = <<-SQL @@ -366,7 +366,7 @@ def get_term_from_synonym @root_term = true if subject[:is_root_term].to_i == 1 @leaf_node = true if subject[:is_leaf].to_i == 1 end - + # Helper function to produce the flat lists of all the child # terms and names. def get_all_child_lists @@ -390,161 +390,4 @@ def get_all_child_lists end - class OntologyTermCache - - def initialize() - create_table = <<-SQL - CREATE TABLE martsearch_cache ( - term varchar(255) NOT NULL PRIMARY KEY, - compressed_json longblob NOT NULL - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 - SQL - - unless MartSearch::OLS_DB.table_exists?( :martsearch_cache ) - MartSearch::OLS_DB.run create_table - end - - @dataset = MartSearch::OLS_DB[:martsearch_cache] - end - - # Looks up a given term in the cache. If not found, it creates it - # before saving it. - # - # @param [String] term The ontology term (id) i.e. GO:00032 - # @return [OntologyTerm] The OntologyTerm object - def fetch( term ) - obj = nil - select_obj = @dataset.first( :term => term ) - select_par = @dataset.first( :term => "#{term}-parents" ) - - if select_obj.nil? - obj = MartSearch::OntologyTerm.new(term) - else - obj = JSON.parse( Zlib::Inflate.inflate(select_obj[:compressed_json]), :max_nesting => false ) - - unless select_par.nil? - parents = JSON.parse( Zlib::Inflate.inflate(select_par[:compressed_json]), :max_nesting => false ) - obj.already_fetched_parents = true - - target = obj - parent = parents.pop - while parent - parent.already_fetched_parents = true - target.parent = parent - target = parent - parent = parents.pop - end - end - end - - return obj - end - - # Builds an OntologyTerm object for the given term and appeneds the - # parent terms to it from the cache. - useful if you're not interested in - # the children of a given term. - # - # @param [String] term The ontology term (id) i.e. GO:00032 - # @return [OntologyTerm] The OntologyTerm object - def fetch_just_parents( term ) - obj = MartSearch::OntologyTerm.new(term) - select_par = @dataset.first( :term => "#{term}-parents" ) - - unless select_par.nil? - parents = JSON.parse( Zlib::Inflate.inflate(select_par[:compressed_json]), :max_nesting => false ) - obj.already_fetched_parents = true - - target = obj - parent = parents.pop - while parent - parent.already_fetched_parents = true - target.parent = parent - target = parent - parent = parents.pop - end - else - obj.get_parents - end - - return obj - end - - # Save a cache entry for a given term. First creates the OntologyTerm - # object, then saves it to the cache. - # - # @param [String] term The ontology term (id) i.e. GO:00032 - # @param [Boolean] build Build the full OntologyTerm tree before save - # @return [OntologyTerm] The OntologyTerm object - def cache_term( term, build=false ) - obj = MartSearch::OntologyTerm.new(term) - - if build - obj.build_tree - obj.all_child_terms - else - obj.get_parents - obj.get_children - end - - cache_obj( obj ) - return obj - end - - # Save an existing OntologyTerm object into the cache. - # - # @param [OntologyTerm] obj The OntologyTerm object to be stored - # @return [OntologyTerm] The OntologyTerm object - def cache_obj( obj ) - MartSearch::OLS_DB.transaction do - @dataset.filter( :term => obj.term ).delete - @dataset.filter( :term => "#{obj.term}-parents" ).delete - - @dataset.insert( - :term => obj.term, - :compressed_json => Zlib::Deflate.deflate( JSON.generate( obj, :max_nesting => false ) ) - ) - - if obj.parentage and !obj.parentage.empty? - @dataset.insert( - :term => "#{obj.term}-parents", - :compressed_json => Zlib::Deflate.deflate( JSON.generate( obj.parentage, :max_nesting => false ) ) - ) - end - end - - return obj - end - - # Helper function to cache all the possible entries of an ontology tree. - # - # @param [String] term The ROOT ontology term (id) - i.e. EMAP:0 - # @param [Boolean] cache_full_tree Whether to build and store the full ontology tree (good for small ontologies - not so good for big ones) - def prepare_full_cache( term, cache_full_tree=true ) - obj = cache_term( term, cache_full_tree ) - puts " - caching #{obj.term}" - recursively_cache_children( obj, cache_full_tree ) - end - - private - - # Helper function to recursively cache the children of an OntologyTerm. - # - # @param [OntologyTerm] obj The OntologyTerm object to be processed - # @param [Boolean] cache_full_tree Whether to build and store the full ontology tree of the child terms (good for small ontologies - not so good for big ones) - def recursively_cache_children( obj, cache_full_tree=true ) - obj.children.each do |child| - if cache_full_tree - child.all_child_terms - else - child.get_children - end - - cache_obj( child ) - puts " - caching #{child.term}" - recursively_cache_children( child, cache_full_tree ) if child.has_children? - end - end - - end - end diff --git a/lib/martsearch/ontology_term_cache.rb b/lib/martsearch/ontology_term_cache.rb new file mode 100644 index 0000000..3314a8c --- /dev/null +++ b/lib/martsearch/ontology_term_cache.rb @@ -0,0 +1,162 @@ +module MartSearch + + # Class for handling the caching of MartSearch::OntologyTerm objects. + # Creates a small cache table within the OLS database schema and handles + # all of the serialisation/de-serialisation to store and fetch the objects. + # + # @author Darren Oakley + class OntologyTermCache + + def initialize() + unless MartSearch::OLS_DB.table_exists?( :martsearch_cache ) + MartSearch::OLS_DB.run <<-SQL + CREATE TABLE martsearch_cache ( + term varchar(255) NOT NULL PRIMARY KEY, + compressed_json longblob NOT NULL + ) ENGINE=MyISAM DEFAULT CHARSET=utf8 + SQL + end + + @dataset = MartSearch::OLS_DB[:martsearch_cache] + end + + # Looks up a given term in the cache. If not found, it creates it. + # + # @param [String] term The ontology term (id) i.e. GO:00032 + # @return [OntologyTerm] The OntologyTerm object + def fetch( term ) + obj = nil + select_obj = @dataset.first( :term => term ) + select_par = @dataset.first( :term => "#{term}-parents" ) + + if select_obj.nil? + obj = MartSearch::OntologyTerm.new(term) + else + obj = JSON.parse( Zlib::Inflate.inflate(select_obj[:compressed_json]), :max_nesting => false ) + + unless select_par.nil? + parents = JSON.parse( Zlib::Inflate.inflate(select_par[:compressed_json]), :max_nesting => false ) + obj.already_fetched_parents = true + + target = obj + parent = parents.pop + while parent + parent.already_fetched_parents = true + target.parent = parent + target = parent + parent = parents.pop + end + end + end + + return obj + end + + # Builds an OntologyTerm object for the given term and appeneds the + # parent terms to it from the cache. - useful if you're not interested in + # the children of a given term. + # + # @param [String] term The ontology term (id) i.e. GO:00032 + # @return [OntologyTerm] The OntologyTerm object + def fetch_just_parents( term ) + obj = MartSearch::OntologyTerm.new(term) + select_par = @dataset.first( :term => "#{term}-parents" ) + + unless select_par.nil? + parents = JSON.parse( Zlib::Inflate.inflate(select_par[:compressed_json]), :max_nesting => false ) + obj.already_fetched_parents = true + + target = obj + parent = parents.pop + while parent + parent.already_fetched_parents = true + target.parent = parent + target = parent + parent = parents.pop + end + else + obj.get_parents + end + + return obj + end + + # Save a cache entry for a given term. First creates the OntologyTerm + # object, then saves it to the cache. + # + # @param [String] term The ontology term (id) i.e. GO:00032 + # @param [Boolean] build Build the full OntologyTerm tree before save + # @return [OntologyTerm] The OntologyTerm object + def cache_term( term, build=false ) + obj = MartSearch::OntologyTerm.new(term) + + if build + obj.build_tree + obj.all_child_terms + else + obj.get_parents + obj.get_children + end + + cache_obj( obj ) + return obj + end + + # Save an existing OntologyTerm object into the cache. + # + # @param [OntologyTerm] obj The OntologyTerm object to be stored + # @return [OntologyTerm] The OntologyTerm object + def cache_obj( obj ) + MartSearch::OLS_DB.transaction do + @dataset.filter( :term => obj.term ).delete + @dataset.filter( :term => "#{obj.term}-parents" ).delete + + @dataset.insert( + :term => obj.term, + :compressed_json => Zlib::Deflate.deflate( JSON.generate( obj, :max_nesting => false ) ) + ) + + if obj.parentage and !obj.parentage.empty? + @dataset.insert( + :term => "#{obj.term}-parents", + :compressed_json => Zlib::Deflate.deflate( JSON.generate( obj.parentage, :max_nesting => false ) ) + ) + end + end + + return obj + end + + # Helper function to cache all the possible entries of an ontology tree. + # + # @param [String] term The ROOT ontology term (id) - i.e. EMAP:0 + # @param [Boolean] cache_full_tree Whether to build and store the full ontology tree (good for small ontologies - not so good for big ones) + def prepare_full_cache( term, cache_full_tree=true ) + obj = cache_term( term, cache_full_tree ) + puts " - caching #{obj.term}" + recursively_cache_children( obj, cache_full_tree ) + end + + private + + # Helper function to recursively cache the children of an OntologyTerm. + # + # @param [OntologyTerm] obj The OntologyTerm object to be processed + # @param [Boolean] cache_full_tree Whether to build and store the full ontology tree of the child terms (good for small ontologies - not so good for big ones) + def recursively_cache_children( obj, cache_full_tree=true ) + obj.children.each do |child| + if cache_full_tree + child.all_child_terms + else + child.get_children + end + + cache_obj( child ) + puts " - caching #{child.term}" + recursively_cache_children( child, cache_full_tree ) if child.has_children? + end + end + + end + +end \ No newline at end of file diff --git a/lib/martsearch/project_utils.rb b/lib/martsearch/project_utils.rb index d396717..a4361b7 100644 --- a/lib/martsearch/project_utils.rb +++ b/lib/martsearch/project_utils.rb @@ -9,6 +9,7 @@ module MartSearch module ProjectUtils include MartSearch::Utils + include MartSearch::ServerViewHelpers # Wrapper function to collate all of the data for a given IKMC project. # @@ -44,19 +45,19 @@ def get_ikmc_project_page_data( project_id ) [ :"targeted non-conditional", :conditional ].each do |symbol| es_cell_names.push( data[:es_cells][symbol][:cells] ) unless data[:es_cells][symbol].nil? end - es_cell_names.flatten! - es_cell_names.map! { |es_cell| es_cell[:name] } + + es_cell_names.flatten!.map! { |es_cell| es_cell[:name] } unless es_cell_names.empty? mice = get_mice( datasources, es_cell_names ) data.merge!( mice[:data] ) unless mice[:data].empty? errors.push( mice[:error] ) unless mice[:error].empty? end - - mouse_data = nil - mouse_data = data[:mice][:genotype_confirmed] if data[:mice] and data[:mice][:genotype_confirmed] # Ammend the es cells data to say which cells have been made into a mouse, then sort the cells as # we do in the current code (by mice, followed by qc count). + mouse_data = nil + mouse_data = data[:mice][:genotype_confirmed] if data[:mice] and data[:mice][:genotype_confirmed] + unless mouse_data.nil? mouse_data.each do |mouse| [ :"targeted non-conditional", :conditional ].each do |symbol| @@ -79,21 +80,56 @@ def get_ikmc_project_page_data( project_id ) end # Add the mutagenesis predictions - mutagenesis_predictions = get_mutagenesis_predictions( project_id ) - data[:mutagenesis_predictions] = mutagenesis_predictions[:data] - unless mutagenesis_predictions[:error].empty? - errors.push( mutagenesis_predictions[:error] ) + unless ['KOMP-Regeneron','mirKO'].include?(data[:ikmc_project]) + mutagenesis_predictions = get_mutagenesis_predictions( project_id ) + data[:mutagenesis_predictions] = mutagenesis_predictions[:data] + errors.push( mutagenesis_predictions[:error] ) unless mutagenesis_predictions[:error].empty? end + # Add the conf for the floxed exon display + data.merge!( floxed_exon_display_conf( data ) ) + # Finally, categorize the stage of the pipeline that we are in data.merge!( get_pipeline_stage( data[:status]) ) if data[:status] end - + return { :data => data, :errors => errors } end - + private - + + # Helper function to setup links to the floxed/deleted exons and all the config + # needed for these activities in the templates. + # + # @param [Hash] data The current project page data hash + # @return [Hash] The additional data required for the floxed exon display + def floxed_exon_display_conf( data ) + new_data = {} + + # Calculate the links to the Floxed/Deleted exons... + exon_links = [] + unless data[:floxed_start_exon].nil? + url = ensembl_link_url_from_exon( :mouse, data[:floxed_start_exon] ) + url = vega_link_url_from_exon( :mouse, data[:floxed_start_exon] ) if data[:floxed_start_exon] =~ /OTT/ + exon_links.push( ''+data[:floxed_start_exon]+'' ) + end + + if !data[:floxed_end_exon].nil? && ( data[:floxed_start_exon] != data[:floxed_end_exon] ) + url = ensembl_link_url_from_exon( :mouse, data[:floxed_end_exon] ) + url = vega_link_url_from_exon( :mouse, data[:floxed_end_exon] ) if data[:floxed_end_exon] =~ /OTT/ + exon_links.push( ''+data[:floxed_end_exon]+'' ) + end + + new_data[:floxed_exon_count] = exon_links.size + new_data[:floxed_exon_link] = exon_links.join(" - ") + + # Also, extablish id these are "Floxed" or "Deleted" exons... + new_data[:deletion] = false + new_data[:deletion] = true if data[:design_type].include?('Deletion') + + return new_data + end + # Wrapper function to handle Biomart::BiomartErrors # # @param [String] data_source - the biomart data source name @@ -461,6 +497,8 @@ def get_pipeline_stage( status ) "Regeneron Selected" => { :stage => "pre", :stage_type => "normal" }, "Design Finished/Oligos Ordered" => { :stage => "designs", :stage_type => "normal" }, "Parental BAC Obtained" => { :stage => "vectors", :stage_type => "normal" }, + "BAC QC Failure" => { :stage => "vectors", :stage_type => "error" }, + "Targeting Vector Unsuccessful" => { :stage => "vectors", :stage_type => "error" }, "Targeting Vector QC Completed" => { :stage => "vectors", :stage_type => "normal" }, "Vector Electroporated into ES Cells" => { :stage => "vectors", :stage_type => "normal" }, "ES cell colonies picked" => { :stage => "cells", :stage_type => "normal" }, diff --git a/lib/martsearch/server/views/project_report.erubis b/lib/martsearch/server/views/project_report.erubis index 9c80442..f7d7a4a 100644 --- a/lib/martsearch/server/views/project_report.erubis +++ b/lib/martsearch/server/views/project_report.erubis @@ -57,29 +57,6 @@ <% end %> <% end %> - <% - # Calculate the links to the Floxed/Deleted exons... - exon_links = [] - unless @data[:floxed_start_exon].nil? - url = ensembl_link_url_from_exon( :mouse, @data[:floxed_start_exon] ) - url = vega_link_url_from_exon( :mouse, @data[:floxed_start_exon] ) if @data[:floxed_start_exon] =~ /OTT/ - exon_links.push( ''+@data[:floxed_start_exon]+'' ) - end - - if !@data[:floxed_end_exon].nil? && @data[:floxed_start_exon] != @data[:floxed_end_exon] - url = ensembl_link_url_from_exon( :mouse, @data[:floxed_end_exon] ) - url = vega_link_url_from_exon( :mouse, @data[:floxed_end_exon] ) if @data[:floxed_end_exon] =~ /OTT/ - exon_links.push( ''+@data[:floxed_end_exon]+'' ) - end - - @data[:floxed_exon_count] = exon_links.size - @data[:floxed_exon_link] = exon_links.join(" - ") - - # Also, extablish id these are "Floxed" or "Deleted" exons... - @data[:deletion] = false - @data[:deletion] = true if @data[:design_type].include?('Deletion') - -%> - <% unless @data[:es_cells].nil? %> <% unless @data[:es_cells][:conditional][:cells].empty? %> diff --git a/public/css/screen.css b/public/css/screen.css index 9252156..69cc415 100644 --- a/public/css/screen.css +++ b/public/css/screen.css @@ -469,7 +469,7 @@ tr.odd td { background: none !important; } -.noborder, .noborder th, .noborder td { +.noborder, .noborder th, .noborder td, td.noborder { border: none !important; } @@ -478,7 +478,7 @@ tr.odd td { padding-bottom: 2px; } -.border, .border th, .border td { +.border, .border th, .border td, td.border { border: 1px solid #999 !important; } diff --git a/public/images/diagonal_line.png b/public/images/diagonal_line.png new file mode 100644 index 0000000..67620f5 Binary files /dev/null and b/public/images/diagonal_line.png differ diff --git a/public/js/martsearch-base.js b/public/js/martsearch-base.js index d85b7ce..0b5b20d 100644 --- a/public/js/martsearch-base.js +++ b/public/js/martsearch-base.js @@ -19,7 +19,7 @@ jQuery(document).ready(function() { overwrite: false, style: { tip: "topRight", - classes: "ui-tooltip-light ui-tooltip-shadow" + classes: "ui-tooltip-light ui-tooltip-rounded ui-tooltip-shadow" }, position: { at: "bottom left", diff --git a/script/wtsi_phenotyping_spreadsheet.pl b/script/wtsi_phenotyping_spreadsheet.pl index 484d0ca..1a2baa5 100644 --- a/script/wtsi_phenotyping_spreadsheet.pl +++ b/script/wtsi_phenotyping_spreadsheet.pl @@ -121,20 +121,19 @@ sub _xls_setup_result_formats { my $xls_formats = { completed_data_available => { bg => 'navy', col => 'white' }, significant_difference => { bg => 'red' }, - no_significant_difference => { bg => 44 }, # light blue early_indication => { bg => 'yellow' }, + no_significant_difference => { bg => 44 }, # light blue not_applicable => { bg => 'silver' }, - test_pending => { bg => 'white' } + test_pending => { bg => 'white' }, + test_abandoned => { bg => 'white', fg => 'silver', pattern => 14 } }; foreach my $result ( keys %{$xls_formats} ) { my $format = $workbook->add_format( %{$default_props} ); - if ( defined $xls_formats->{$result}->{bg} ) { - $format->set_bg_color( $xls_formats->{$result}->{bg} ); - } - if ( defined $xls_formats->{$result}->{col} ) { - $format->set_color( $xls_formats->{$result}->{col} ); - } + if ( defined $xls_formats->{$result}->{bg} ) { $format->set_bg_color( $xls_formats->{$result}->{bg} ); } + if ( defined $xls_formats->{$result}->{fg} ) { $format->set_fg_color( $xls_formats->{$result}->{fg} ); } + if ( defined $xls_formats->{$result}->{pattern} ) { $format->set_pattern( $xls_formats->{$result}->{pattern} ); } + if ( defined $xls_formats->{$result}->{col} ) { $format->set_color( $xls_formats->{$result}->{col} ); } $xls_formats->{$result} = $format; } @@ -153,6 +152,7 @@ sub _xls_test_result_format { elsif ( $result eq "Test complete but not considered interesting" ) { $form = $tf->{no_significant_difference}; } elsif ( $result eq "Early indication of possible phenotype" ) { $form = $tf->{early_indication}; } elsif ( $result =~ /^Test not performed or applicable/i ) { $form = $tf->{not_applicable}; } + elsif ( $result eq "Test abandoned" ) { $form = $tf->{test_abandoned}; } else { $form = $tf->{test_pending}; } return $form; @@ -163,10 +163,11 @@ sub sorted_results_test_codes { my $test_mapping = { completed_data_available => 1, significant_difference => 2, - no_significant_difference => 3, - early_indication => 4, + early_indication => 3, + no_significant_difference => 4, not_applicable => 5, - test_pending => 6 + test_abandoned => 6, + test_pending => 7 }; return $test_mapping; } @@ -179,20 +180,22 @@ sub write_unsorted_legend { my $linked_formats = $formats->{linked_tests}; $worksheet->write( 2, $number_of_columns+2, "LEGEND" ); - $worksheet->write( 4, $number_of_columns+3, "Test complete and data/resources available" ); + $worksheet->write( 4, $number_of_columns+3, "Test complete and data/resources are available" ); $worksheet->write( 4, $number_of_columns+2, "", $unlinked_formats->{completed_data_available} ); - $worksheet->write( 5, $number_of_columns+3, "Test complete and considered interesting" ); + $worksheet->write( 5, $number_of_columns+3, "Test is complete and the data are considered interesting" ); $worksheet->write( 5, $number_of_columns+2, "", $unlinked_formats->{significant_difference} ); - $worksheet->write( 6, $number_of_columns+3, "Test complete but not considered interesting" ); - $worksheet->write( 6, $number_of_columns+2, "", $unlinked_formats->{no_significant_difference} ); - $worksheet->write( 7, $number_of_columns+3, "Early indication of possible phenotype" ); - $worksheet->write( 7, $number_of_columns+2, "", $unlinked_formats->{early_indication} ); + $worksheet->write( 6, $number_of_columns+3, "Preliminary indication of an interesting phenotype" ); + $worksheet->write( 6, $number_of_columns+2, "", $unlinked_formats->{early_indication} ); + $worksheet->write( 7, $number_of_columns+3, "Test is complete but the data are not considered interesting" ); + $worksheet->write( 7, $number_of_columns+2, "", $unlinked_formats->{no_significant_difference} ); $worksheet->write( 8, $number_of_columns+3, "Test not performed or applicable e.g. no lacZ reporter therefore no expression" ); $worksheet->write( 8, $number_of_columns+2, "", $unlinked_formats->{not_applicable} ); $worksheet->write( 9, $number_of_columns+3, "Test pending" ); $worksheet->write( 9, $number_of_columns+2, "", $unlinked_formats->{test_pending} ); - $worksheet->write( 10, $number_of_columns+3, "Link to a phenotyping test report page" ); - $worksheet->write( 10, $number_of_columns+2, ">", $linked_formats->{test_pending} ); + $worksheet->write( 10, $number_of_columns+3, "Test abandoned" ); + $worksheet->write( 10, $number_of_columns+2, "", $unlinked_formats->{test_abandoned} ); + $worksheet->write( 11, $number_of_columns+3, "Link to a phenotyping test report page" ); + $worksheet->write( 11, $number_of_columns+2, ">", $linked_formats->{test_pending} ); } # Helper function to write the cells for the sortable heatmap. @@ -204,20 +207,22 @@ sub write_sorted_legend { my $test_code = sorted_results_test_codes(); $worksheet->write( 2, $number_of_columns+2, "LEGEND" ); - $worksheet->write( 4, $number_of_columns+3, "Test complete and data/resources available" ); + $worksheet->write( 4, $number_of_columns+3, "Test complete and data/resources are available" ); $worksheet->write( 4, $number_of_columns+2, $test_code->{completed_data_available}, $test_formats->{completed_data_available} ); - $worksheet->write( 5, $number_of_columns+3, "Test complete and considered interesting" ); + $worksheet->write( 5, $number_of_columns+3, "Test is complete and the data are considered interesting" ); $worksheet->write( 5, $number_of_columns+2, $test_code->{significant_difference}, $test_formats->{significant_difference} ); - $worksheet->write( 6, $number_of_columns+3, "Test complete but not considered interesting" ); - $worksheet->write( 6, $number_of_columns+2, $test_code->{no_significant_difference}, $test_formats->{no_significant_difference} ); - $worksheet->write( 7, $number_of_columns+3, "Early indication of possible phenotype" ); - $worksheet->write( 7, $number_of_columns+2, $test_code->{early_indication}, $test_formats->{early_indication} ); + $worksheet->write( 6, $number_of_columns+3, "Preliminary indication of an interesting phenotype" ); + $worksheet->write( 6, $number_of_columns+2, $test_code->{early_indication}, $test_formats->{early_indication} ); + $worksheet->write( 7, $number_of_columns+3, "Test is complete but the data are not considered interesting" ); + $worksheet->write( 7, $number_of_columns+2, $test_code->{no_significant_difference}, $test_formats->{no_significant_difference} ); $worksheet->write( 8, $number_of_columns+3, "Test not performed or applicable e.g. no lacZ reporter therefore no expression" ); $worksheet->write( 8, $number_of_columns+2, $test_code->{not_applicable}, $test_formats->{not_applicable} ); $worksheet->write( 9, $number_of_columns+3, "Test pending" ); $worksheet->write( 9, $number_of_columns+2, $test_code->{test_pending}, $test_formats->{test_pending} ); - $worksheet->write( 10, $number_of_columns+3, "Link to a phenotyping test report page" ); - $worksheet->write( 10, $number_of_columns+2, "x", $linked_formats->{test_pending} ); + $worksheet->write( 10, $number_of_columns+3, "Test pending" ); + $worksheet->write( 10, $number_of_columns+2, $test_code->{test_abandoned}, $test_formats->{test_abandoned} ); + $worksheet->write( 11, $number_of_columns+3, "Link to a phenotyping test report page" ); + $worksheet->write( 11, $number_of_columns+2, ">", $linked_formats->{test_pending} ); } @@ -268,7 +273,7 @@ sub write_test_results { if ( $worksheet->get_name() =~ /Sort/ ) { $worksheet->write_url( $row, $col, $pheno_details_url, _xls_test_result_format( $sorted_test_mapping, $result ), _xls_test_result_format( $formats->{linked_tests}, $result ) ); } else { - $worksheet->write_url( $row, $col, $pheno_details_url, "x", _xls_test_result_format( $formats->{linked_tests}, $result ) ); + $worksheet->write_url( $row, $col, $pheno_details_url, ">", _xls_test_result_format( $formats->{linked_tests}, $result ) ); } } else { diff --git a/tasks/metric_fu.task b/tasks/metric_fu.task deleted file mode 100644 index b4d576d..0000000 --- a/tasks/metric_fu.task +++ /dev/null @@ -1,21 +0,0 @@ -begin - require 'rubygems' - require 'metric_fu' - - unless Object.respond_to?(:to_json!) - # Rails 3 fixes - require 'active_support/core_ext/object/to_json' - require 'active_support/core_ext/object/blank' - end - - MetricFu::Configuration.run do |config| - config.metrics = [:churn, :saikuro, :flog, :flay, :reek, :roodi] - config.graphs = [:flog, :flay, :reek, :roodi] - config.flog = { :dirs_to_flog => ['lib'] } - config.flay = { :dirs_to_flay => ['lib'] } - config.reek = { :dirs_to_reek => ['lib'] } - config.roodi = { :dirs_to_roodi => ['lib'] } - end -rescue LoadError - puts "[ERROR] Unable to load 'metric_fu' tasks - please run 'bundle install'" -end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index 995ce5f..d3b7a9f 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,3 +1,6 @@ +# Add the lib directory to the search path +$:.unshift( "#{File.expand_path(File.dirname(__FILE__))}/../lib" ) + require 'rubygems' # Set-up SimpleCov (code coverage tool for Ruby 1.9) @@ -15,14 +18,10 @@ end end -# Add the lib directory to the search path -$:.unshift( "#{File.expand_path(File.dirname(__FILE__))}/../lib" ) - -require 'ap' +require 'martsearch' require 'test/unit' require 'vcr' require 'shoulda' -require 'martsearch' # Set-up VCR for mocking up web requests. VCR.config do |c| diff --git a/test/test_index_builder_utils.rb b/test/test_index_builder_utils.rb index d3e0184..b25a9d0 100644 --- a/test/test_index_builder_utils.rb +++ b/test/test_index_builder_utils.rb @@ -248,4 +248,75 @@ def test_index_ontology_terms assert( doc3[:mp_ontology].empty? ) end + def test_concatenated_ontology_terms + ontology_cache = {} + doc = new_document() + attr_map = [ + { :attr => 'colony_prefix', :idx => 'colony_prefix', :use_to_map => true }, + { :attr => 'annotations', :idx => 'ignore_me' } + ] + concatenated_ontology_term_conf = { + :attr => 'annotations', + :split_on => '; ', + :ontologies => { + :"^MA\\:\\d+$" => { :term => 'ma_id', :term_name => 'ma_term', :breadcrumb => 'ma_ontology' }, + :"^MP\\:\\d+$" => { :term => 'mp_id', :term_name => 'mp_term', :breadcrumb => 'mp_ontology' } + } + } + data_row_obj = { + 'colony_prefix' => 'MAMM', + 'annotations' => 'MA:0000053; MP:0003866' + } + + # Perform the search from fresh... + index_concatenated_ontology_terms( concatenated_ontology_term_conf, doc, data_row_obj, process_attribute_map(attr_map), ontology_cache ) + + assert_equal( 6, doc[:ma_id].size ) + assert_equal( 5, doc[:ma_term].size ) + assert( doc[:ma_id].include?('MA:0000005') ) + assert( doc[:ma_id].include?('MA:0000001') ) + assert( doc[:ma_term].include?('body cavity or lining') ) + assert( doc[:ma_term].include?('adult mouse') ) + assert( doc[:ma_ontology].include?('MA:0000001 | MA:0002405 | MA:0002433 | MA:0000005 | MA:0002447 | MA:0000053') ) + + assert_equal( 4, doc[:mp_id].size ) + assert_equal( 3, doc[:mp_term].size ) + assert( doc[:mp_id].include?('MP:0001663') ) + assert( doc[:mp_id].include?('MP:0000001') ) + assert( doc[:mp_term].include?('abnormal defecation') ) + assert( doc[:mp_term].include?('digestive/alimentary phenotype') ) + assert( doc[:mp_ontology].include?('MP:0000001 | MP:0005381 | MP:0001663 | MP:0003866') ) + + # Perform the search from cache... + doc2 = new_document() + + index_concatenated_ontology_terms( concatenated_ontology_term_conf, doc2, data_row_obj, process_attribute_map(attr_map), ontology_cache ) + + assert_equal( 6, doc2[:ma_id].size ) + assert_equal( 5, doc2[:ma_term].size ) + assert( doc2[:ma_id].include?('MA:0000005') ) + assert( doc2[:ma_id].include?('MA:0000001') ) + + assert_equal( 4, doc2[:mp_id].size ) + assert_equal( 3, doc2[:mp_term].size ) + assert( doc2[:mp_id].include?('MP:0001663') ) + assert( doc2[:mp_id].include?('MP:0000001') ) + + # Make sure a bad ontology term doesn't blow stuff up... + doc3 = new_document() + data_row_obj2 = { + 'colony_prefix' => 'MAMM', + 'annotations' => 'FLIBBLE:5', + } + + index_concatenated_ontology_terms( concatenated_ontology_term_conf, doc3, data_row_obj2, process_attribute_map(attr_map), ontology_cache ) + + assert( doc3[:ma_id].empty? ) + assert( doc3[:ma_term].empty? ) + assert( doc3[:ma_ontology].empty? ) + assert( doc3[:mp_id].empty? ) + assert( doc3[:mp_term].empty? ) + assert( doc3[:mp_ontology].empty? ) + end + end \ No newline at end of file diff --git a/test/test_project_utils.rb b/test/test_project_utils.rb index 234f1cc..03d6fe5 100644 --- a/test/test_project_utils.rb +++ b/test/test_project_utils.rb @@ -1,5 +1,4 @@ require "test_helper" -require "json" class TestMartSearchProjectUtils < Test::Unit::TestCase include MartSearch::ProjectUtils @@ -910,9 +909,11 @@ class TestMartSearchProjectUtils < Test::Unit::TestCase end should "not throw any exceptions with no mice" do - assert_nothing_raised do - get_ikmc_project_page_data( 42474 ) - end + project_id = 42474 + data = nil + assert_nothing_raised { data = get_ikmc_project_page_data( project_id ) } + assert( !data.nil? ) + assert( data[:mice].nil?, "We're trying to test for exception handling for projects with no mice - but this project 'project_id' has mouse data!") end should "return the correct data with more than one mouse" do diff --git a/test/test_server.rb b/test/test_server.rb index 73dcbd6..239f1ea 100644 --- a/test/test_server.rb +++ b/test/test_server.rb @@ -100,8 +100,8 @@ def setup should "render IKMC project pages" do VCR.use_cassette('test_server_project_page') do - project_ids_to_test = ['35505','27042','42474','82403','23242'] - + project_ids_to_test = ['35505','27042','42474','82403','23242','VG12252','VG11490'] + project_ids_to_test.each do |project_id| visit "/project/#{project_id}" assert_equal( "/project/#{project_id}", current_path ) @@ -145,11 +145,13 @@ def setup when 'embryo-expression' then 'Embryo Expression' when 'homozygote-viability' then 'Homozygote Viability' when 'fertility' then 'Fertility' + when 'skin-screen' then 'Skin Screen' else - test_data[0][:heatmap_group] + test_data[:heatmap_group] end urls_to_hit.push({ + :test => test_url, :url => "/phenotyping/#{colony_prefix}/#{test_url}/", :title => test_title }) @@ -162,6 +164,13 @@ def setup visit test_conf[:url] assert_equal( "#{test_conf[:url]}", current_path, "WTSI Phenotyping - can't visit '#{test_conf[:url]}'!" ) assert( page.has_content?(test_conf[:title]) ) + + if test_conf[:test] == 'abr' + assert( page.has_css?('#abr-thresholds') ) + href = page.first(:css, "#abr-thresholds a[rel='prettyPhoto']")[:href] + visit "#{test_conf[:url]}#{href}" + visit "#{test_conf[:url]}foobarweewar.png" + end end end end @@ -225,15 +234,15 @@ def setup should 'render IKMC project pages as JSON...' do VCR.use_cassette('test_server_project_page') do - project_ids_to_test = ['35505','27042','42474','82403','23242'] - + project_ids_to_test = ['35505','27042','42474','82403','23242','VG12252','VG11490'] + project_ids_to_test.each do |project_id| @browser.get "/project/#{project_id}?wt=json" assert( @browser.last_response.ok?, "A request to '/project/#{project_id}?wt=json' failed!" ) json = JSON.parse( @browser.last_response.body ) assert( json.is_a?(Hash) ) end - + @browser.get "/project/foobar" assert_equal( 404, @browser.last_response.status ) end @@ -300,7 +309,7 @@ def setup skip("Skipping WTSI Phenotyping report tests as the DataView is not active.") else VCR.use_cassette('test_server_wtsi_phenotyping_report_pages') do - tests_to_test = ['abr','homozygote-viability','fertility','adult-expression','embryo-expression','dexa','hot-plate'] + tests_to_test = ['abr','homozygote-viability','fertility','adult-expression','embryo-expression','dexa','hot-plate','skin-screen'] colonies_to_test = ['FOOO','BAAR','BAAZ','ARRR'] colonies_to_test.each do |colony_prefix|