From 13ffab048630cc30a4af9e9113c1843ae5af0a09 Mon Sep 17 00:00:00 2001 From: gebele Date: Wed, 25 Sep 2013 00:12:04 +0200 Subject: several major changes in code, several minor changes in style; prepared for OT meeting --- application.rb | 146 ++++++++++++++++++++++---- prediction_models.csv | 0 public/images/OpenToxEuro2013.png | Bin 12922 -> 0 bytes public/images/OpenToxEuro2013_small.png | Bin 0 -> 9022 bytes public/images/favicon.ico | Bin 0 -> 1150 bytes public/stylesheets/screen.css | 2 +- public/stylesheets/screen.sass | 113 ++++++++++++++++---- unicorn.rb | 2 + views/details.haml | 21 ++-- views/layout.haml | 4 +- views/neighbors.haml | 178 ++++++++++++++++++-------------- views/predict.haml | 78 +++++++++++--- views/prediction.haml | 129 +++++++++++++++-------- views/significant_fragments.haml | 63 +++++++++++ 14 files changed, 552 insertions(+), 184 deletions(-) create mode 100644 prediction_models.csv delete mode 100644 public/images/OpenToxEuro2013.png create mode 100644 public/images/OpenToxEuro2013_small.png create mode 100644 public/images/favicon.ico create mode 100644 unicorn.rb create mode 100644 views/significant_fragments.haml diff --git a/application.rb b/application.rb index 925c208..5cd5093 100644 --- a/application.rb +++ b/application.rb @@ -8,10 +8,11 @@ require_relative 'helper.rb' require File.join(ENV["HOME"],".opentox","config","lazar-gui.rb") # until added to ot-tools helpers do - # fetch models from uri-list + # get prediction models from text file, ignore validation models + # model uris must be manually added @@models = [] - uris = `curl -Lk -X GET -H accept:text/uri-list #{$model[:uri]} `.chomp.split("\n") - uris.each{|u| m = OpenTox::Model::Lazar.find u; @@models << m} + CSV.foreach("./prediction_models.csv"){|uri| m = OpenTox::Model::Lazar.find uri[0]; @@models << m} + #$logger.debug "model uris from csv file:\t#{@@models}\n" end get '/?' do @@ -27,36 +28,126 @@ get '/jme_help/?' do File.read(File.join('views','jme_help.html')) end -# best way to get individual compound uri for details +# get individual compound details get '/prediction/:neighbor/details/?' do - @compound_uri = OpenTox::Compound.new params[:neighbor] - @smiles = @compound_uri.smiles + @compound = OpenTox::Compound.new params[:neighbor] + @smiles = @compound.smiles + task = OpenTox::Task.run("look for names.") do - names = @compound_uri.names + names = @compound.names end task.wait + case task[RDF::OT.hasStatus] when "Error" @names = "No names for this compound available." when "Completed" - @names = @compound_uri.names.join(",") + @names = @compound.names end - @inchi = @compound_uri.inchi.gsub("InChI=", "") + @inchi = @compound.inchi.gsub("InChI=", "") + haml :details, :layout => false end +# fingerprints for compound in predictions +get '/prediction/:model_uri/:type/:compound_uri/fingerprints/?' do + @type = params[:type] + model = OpenTox::Model::Lazar.find params[:model_uri] + feature_dataset = OpenTox::Dataset.find model[RDF::OT.featureDataset] + @compound = OpenTox::Compound.new params[:compound_uri] + + if @type =~ /classification/i + # collect all feature values with fingerprint + fingerprints = OpenTox::Algorithm::Descriptor.send("smarts_match", [@compound], feature_dataset.features.collect{ |f| f[RDF::DC.title]})[@compound.uri] + #$logger.debug "fingerprints:\t#{fingerprints}\n" + + # collect fingerprints with value 1 + @fingerprint_values = [] + fingerprints.each{|smarts, value| @fingerprint_values << [smarts, value] if value > 0} + + # collect all features from feature_dataset + @features = feature_dataset.features.collect{|f| f } + + # search for each fingerprint in all features and collect feature values(smarts, pValue, effect) + @significant_fragments = [] + @fingerprint_values.each{ |fi, v| @features.each{ |f| @significant_fragments << [f[RDF::OT.effect].to_i, f[RDF::OT.smarts], f[RDF::OT.pValue]] if fi == f[RDF::OT.smarts] } } + else #regression + @significant_fragments = [] + end + + haml :significant_fragments, :layout => false +end + +get '/prediction/:model_uri/:type/:neighbor/significant_fragments/?' do + @type = params[:type] + #$logger.debug "sf type:\t#{@type}" + @compound = OpenTox::Compound.new params[:neighbor] + #$logger.debug "neighbor compound uri:\t#{@compound.uri}\n" + + model = OpenTox::Model::Lazar.find params[:model_uri] + #$logger.debug "model for significant fragments:\t#{model.uri}" + + feature_dataset = OpenTox::Dataset.find model[RDF::OT.featureDataset] + $logger.debug "fd :\t#{feature_dataset.uri}" + + # load all compounds + feature_dataset.compounds + + # load all features + @features = [] + feature_dataset.features.each{|f| @features << f} + #$logger.debug "all features in fd:\t#{@features}\n" + + # find all features and values for a neighbor compound + @significant_fragments = [] + # check type first + if @type =~ /classification/i + @feat = [] + # get compound index in feature dataset + c_idx = feature_dataset.compound_indices @compound.uri + #$logger.debug "compound idx:\t#{c_idx}\n" + + # collect feature uris with value + @features.each{|f| @feat << [feature_dataset.data_entry_value(c_idx[0], f.uri), f.uri]} + #$logger.debug "collected features:\t#{@feat}\n" + + # pass feature uris if value > 0 + @feat.each do |f| + if f[0] > 0 + f = OpenTox::Feature.find f[1] + @significant_fragments << [f[RDF::OT.effect].to_i, f[RDF::OT.smarts], f[RDF::OT.pValue].to_f.round(3)] + end + end + else # regression + # find a value in feature dataset by compound and feature + @values = [] + @features.each{|f| @values << feature_dataset.values(@compound, f)} + #$logger.debug "values in fd:\t#{@values}" + + count = 0 + @features.each{|f| @significant_fragments << [f.description, @values[count]]; count +=1} + end + #$logger.debug "significant fragments:\t#{@significant_fragments}\n" + + haml :significant_fragments, :layout => false +end + post '/predict/?' do # validate identifier input task = OpenTox::Task.run("Validate SMILES string.") do # transfered input @identifier = params[:identifier] + # get compound from SMILES @compound = OpenTox::Compound.from_smiles @identifier.to_s + # validate SMILES by converting to INCHI inchi = @compound.inchi end + # necessary to wait for task task.wait + # case task fails return message smiles invalid # case task completed go ahead case task[RDF::OT.hasStatus] @@ -66,30 +157,41 @@ post '/predict/?' do when "Completed" @identifier = params[:identifier] @compound = OpenTox::Compound.from_smiles @identifier.to_s - # init - @@prediction_models = [] - @@predictions = [] + # init arrays + @prediction_models = [] + @predictions = [] # init lazar algorithm lazar = OpenTox::Algorithm::Fminer.new File.join($algorithm[:uri],"lazar") - # gather models from service and compare if selected - #TODO compare selected by uri + + # get selected models + #TODO compare if model is selected by uri not title params[:selection].each do |model| - @mselected = model[0] - @mall = @@models - @mall.each do |m| - @@prediction_models << m if m.title =~ /#{@mselected}/ + # selected model = model[0] + # compare selected with all models + @@models.each do |m| + @prediction_models << m if m.title =~ /#{model[0]}/ end end # predict with selected models - # results in prediction variable - # store prediction in array for better handling - @@prediction_models.each do |m| + # one prediction in 'pa' array = OpenTox::Dataset + # all collected predictions in '@predictions' array + # init model_type array + @model_type = [] + @prediction_models.each do |m| + # define type (classification|regression) + m.type.join =~ /classification/i ? (@model_type << "classification") : (@model_type << "regression") + + #TODO each prediction get a task; load predictions page if first task finished and load results individually + + # predict against compound @prediction_uri = m.run :compound_uri => "#{@compound.uri}" + $logger.debug "prediction dataset:\t#{@prediction_uri}\n" + prediction = OpenTox::Dataset.new @prediction_uri pa = [] pa << prediction - @@predictions << pa + @predictions << pa end haml :prediction diff --git a/prediction_models.csv b/prediction_models.csv new file mode 100644 index 0000000..e69de29 diff --git a/public/images/OpenToxEuro2013.png b/public/images/OpenToxEuro2013.png deleted file mode 100644 index 4fe1005..0000000 Binary files a/public/images/OpenToxEuro2013.png and /dev/null differ diff --git a/public/images/OpenToxEuro2013_small.png b/public/images/OpenToxEuro2013_small.png new file mode 100644 index 0000000..9613452 Binary files /dev/null and b/public/images/OpenToxEuro2013_small.png differ diff --git a/public/images/favicon.ico b/public/images/favicon.ico new file mode 100644 index 0000000..be19592 Binary files /dev/null and b/public/images/favicon.ico differ diff --git a/public/stylesheets/screen.css b/public/stylesheets/screen.css index c7cd00f..a81705c 100644 --- a/public/stylesheets/screen.css +++ b/public/stylesheets/screen.css @@ -1 +1 @@ -body{background-image:url("/images/gray_jean.png");background-color:#ccf;overflow:scroll;font-family:sans-serif}body a{text-decoration:none;font-weight:bold;color:#000}body img{border:0}.logo img{float:left;display:inline;margin-right:1em}.logo h1{display:inline;width:80%}.logo img.ote{width:100px;height:50px;display:inline;float:right}.logo hr{margin:0.5em}.content{background-image:url("/images/gray_jean.png")}.content h1{margin:0.3em;text-shadow:#fff 1px 1px 0;font-size:x-large;font-family:Verdana;display:inline}.content h2{text-shadow:#fff 1px 1px 0;font-size:x-large;color:#f55}.content .arrow{margin:5px 0px 5px 20px}.content .back{display:inline}.content #back-top{z-index:100;position:fixed;bottom:3%;margin-left:91%}.content #back-top a:hover{color:#bbb}.content fieldset#top{border:0;padding:10px;background-color:#c5c1e4;-moz-border-radius-topleft:25px;-webkit-border-top-left-radius:25px;border-top-left-radius:25px;-moz-border-radius-topright:25px;-webkit-border-top-right-radius:25px;border-top-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset}.content fieldset#top a#linkInsert{display:block;width:100%;height:2em}.content fieldset#top #appletContainer{padding:10px}.content fieldset#middle{border:0;padding:10px;background-color:#c5c1e4;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset}.content fieldset#middle a#linkModels{display:block;width:100%;height:2em}.content fieldset#middle #endpoint{padding-top:2em}.content fieldset#middle #model a{display:inline;font-weight:normal}.content fieldset#bottom{border:0;background-color:#c5c1e4;padding:10px;margin-bottom:5em;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-border-radius-bottomleft:25px;-webkit-border-bottom-left-radius:25px;border-bottom-left-radius:25px;-moz-border-radius-bottomright:25px;-webkit-border-bottom-right-radius:25px;border-bottom-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box}.content fieldset#bottom input#predict{margin-left:1em}.content .predictions{background-color:#c5c1e4;padding:10px;text-align:justify;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-border-radius-topleft:25px;-webkit-border-top-left-radius:25px;border-top-left-radius:25px;-moz-border-radius-bottomleft:25px;-webkit-border-bottom-left-radius:25px;border-bottom-left-radius:25px;-moz-border-radius-topright:25px;-webkit-border-top-right-radius:25px;border-top-right-radius:25px;-moz-border-radius-bottomright:25px;-webkit-border-bottom-right-radius:25px;border-bottom-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box}.content .overview{background-image:url("/images/gray_jean.png");padding:12px;margin-top:1em;margin-bottom:1em;text-align:left;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-border-radius-topleft:25px;-webkit-border-top-left-radius:25px;border-top-left-radius:25px;-moz-border-radius-topright:25px;-webkit-border-top-right-radius:25px;border-top-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box}.content .overview caption{text-align:left}.content .overview #overview tr td{background-color:#fff;border:1px solid #dad9c7;padding-left:1em;padding-top:0.5em}.content .overview #overview tr td #compound{width:200px}.content .overview #overview tr td b.c{color:#d42200}.content .overview #overview tr td b.n{color:#5c8533}.content .overview #overview tr td .confidence{display:inline}.content .error{background-color:#c5c1e4;padding:15px;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-border-radius-topleft:25px;-webkit-border-top-left-radius:25px;border-top-left-radius:25px;-moz-border-radius-bottomleft:25px;-webkit-border-bottom-left-radius:25px;border-bottom-left-radius:25px;-moz-border-radius-topright:25px;-webkit-border-top-right-radius:25px;border-top-right-radius:25px;-moz-border-radius-bottomright:25px;-webkit-border-bottom-right-radius:25px;border-bottom-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box}.content .error .message{margin-top:1em;padding:0.2em;border:2px solid #f55;background-color:#fff;color:#f55}.content #closebutton{margin-left:95%;padding:0;background-color:#c5c1e4;-moz-border-radius-bottomleft:5px;-webkit-border-bottom-left-radius:5px;border-bottom-left-radius:5px;-moz-border-radius-bottomright:5px;-webkit-border-bottom-right-radius:5px;border-bottom-right-radius:5px}.details{margin-bottom:2em;background-image:url("/images/gray_jean.png");-moz-border-radius-bottomleft:25px;-webkit-border-bottom-left-radius:25px;border-bottom-left-radius:25px;-moz-border-radius-bottomright:25px;-webkit-border-bottom-right-radius:25px;border-bottom-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box}.results{background-image:url("/images/gray_jean.png");overflow-x:auto;overflow-y:hidden;margin-top:2em;margin-bottom:2em;-webkit-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset}.results .tablesorter{width:100%}.results .tablesorter thead{background-color:#e6e5f3}.results .tablesorter thead tr th.header{background-image:url("/images/bg.gif");background-repeat:no-repeat;background-position:center left;cursor:pointer;padding-left:20px;border:1px solid #dad9c7;margin-left:-1px}.results .tablesorter thead tr th.headerSortDown{background-image:url("/images/desc.gif");background-color:#c5c1e4}.results .tablesorter thead tr th.headerSortUp{background-image:url("/images/asc.gif");background-color:#c5c1e4}.results .tablesorter tbody tr td{padding-left:1em;-webkit-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset}.results .tablesorter tbody .compound{width:200px}.results .tablesorter tbody .n{color:#5c8533}.results .tablesorter tbody .c{color:#d42200}input#predict{border:0px;background-color:#c5c1e4;margin:0;padding:0}.tooltip{background-color:#fff;border:2px solid #ccc;font-size:0.5em;padding:1em;display:none;z-index:50}.footer{margin:20px 0 20px 0} +body{background-image:url("/images/gray_jean.png");overflow:scroll;font-family:sans-serif}body a{text-decoration:none;font-weight:bold;color:#000}body img{border:0}body h2{padding-top:12px;text-shadow:#fff 1px 1px 0;font-size:x-large;color:#f55}.logo img{float:left;display:inline;margin-right:1em}.logo h1{display:inline;width:80%}.logo img.ote{width:100px;height:50px;display:inline;float:right}.logo hr{margin:0.5em}.content{background-image:url("/images/gray_jean.png")}.content h1{margin:0.3em;text-shadow:#fff 1px 1px 0;font-size:x-large;font-family:Verdana;display:inline}.content .arrow{margin:8px 0px 5px 20px}.content .back{display:inline}.content #back-top{z-index:100;position:fixed;bottom:3%;margin-left:91%}.content #back-top a:hover{color:#bbb}.content fieldset#top{border:0;padding:10px;background-color:#c5c1e4;-moz-border-radius-topleft:25px;-webkit-border-top-left-radius:25px;border-top-left-radius:25px;-moz-border-radius-topright:25px;-webkit-border-top-right-radius:25px;border-top-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset}.content fieldset#top a#linkInsert{display:block;width:100%;height:2em}.content fieldset#top #appletContainer{padding:10px}.content fieldset#middle{border:0;padding:10px;background-color:#c5c1e4;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset}.content fieldset#middle a#linkModels{display:block;width:100%;height:2em}.content fieldset#middle #endpoint{padding-top:2em}.content fieldset#middle #model a{display:inline;font-weight:normal}.content fieldset#middle a#linkDetailsLC50_mmol{font-size:small}.content fieldset#middle a#linkDetailsHamster{font-size:small}.content fieldset#middle a#linkDetailsRodent{font-size:small}.content fieldset#middle #details_LC50_mmol{background-color:#e6e5f3;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;padding:1em}.content fieldset#middle #details_Hamster{background-color:#e6e5f3;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;padding:1em}.content fieldset#middle #details_Rodent{background-color:#e6e5f3;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;padding:1em}.content fieldset#bottom{border:0;background-color:#c5c1e4;padding:10px;margin-bottom:5em;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-border-radius-bottomleft:25px;-webkit-border-bottom-left-radius:25px;border-bottom-left-radius:25px;-moz-border-radius-bottomright:25px;-webkit-border-bottom-right-radius:25px;border-bottom-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box}.content fieldset#bottom input#predict{margin-left:1em}.content .predictions{background-color:#c5c1e4;padding:10px;text-align:justify;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-border-radius-topleft:25px;-webkit-border-top-left-radius:25px;border-top-left-radius:25px;-moz-border-radius-bottomleft:25px;-webkit-border-bottom-left-radius:25px;border-bottom-left-radius:25px;-moz-border-radius-topright:25px;-webkit-border-top-right-radius:25px;border-top-right-radius:25px;-moz-border-radius-bottomright:25px;-webkit-border-bottom-right-radius:25px;border-bottom-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box}.content .overview{background-image:url("/images/gray_jean.png");padding:12px;margin-top:1em;margin-bottom:1em;text-align:left;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-border-radius-topleft:25px;-webkit-border-top-left-radius:25px;border-top-left-radius:25px;-moz-border-radius-topright:25px;-webkit-border-top-right-radius:25px;border-top-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box}.content .overview a:hover{color:#f55}.content .overview caption{text-align:left}.content .overview #overview tr td{background-color:#fff;border:1px solid #dad9c7;padding-left:1em;padding-top:0.5em}.content .overview #overview tr td #compound{width:200px}.content .overview #overview tr td b.c{color:#d42200}.content .overview #overview tr td b.n{color:#5c8533}.content .overview #overview tr td .confidence{display:inline}.content .error{background-color:#c5c1e4;padding:15px;-webkit-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,-1px -1px 5px rgba(0,0,0,0.3) inset;-moz-border-radius-topleft:25px;-webkit-border-top-left-radius:25px;border-top-left-radius:25px;-moz-border-radius-bottomleft:25px;-webkit-border-bottom-left-radius:25px;border-bottom-left-radius:25px;-moz-border-radius-topright:25px;-webkit-border-top-right-radius:25px;border-top-right-radius:25px;-moz-border-radius-bottomright:25px;-webkit-border-bottom-right-radius:25px;border-bottom-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box}.content .error .message{margin-top:1em;padding:1em;border:2px solid #f55;background-color:#fff;color:#f55;-moz-border-radius-topleft:25px;-webkit-border-top-left-radius:25px;border-top-left-radius:25px;-moz-border-radius-bottomleft:25px;-webkit-border-bottom-left-radius:25px;border-bottom-left-radius:25px;-moz-border-radius-topright:25px;-webkit-border-top-right-radius:25px;border-top-right-radius:25px;-moz-border-radius-bottomright:25px;-webkit-border-bottom-right-radius:25px;border-bottom-right-radius:25px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box}.content #closebutton{color:#f55;margin-left:98%;padding:0}.details{width:98%;background-color:#c5c1e4;-moz-border-radius-bottomleft:5px;-webkit-border-bottom-left-radius:5px;border-bottom-left-radius:5px;-moz-border-radius-bottomright:5px;-webkit-border-bottom-right-radius:5px;border-bottom-right-radius:5px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box;-webkit-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset}.details a:hover{color:#f55}.details img{display:inline;float:left;margin:0.5em}.significant_fragments{width:98%;margin-bottom:2em;background-color:#c5c1e4;-moz-border-radius-bottomleft:5px;-webkit-border-bottom-left-radius:5px;border-bottom-left-radius:5px;-moz-border-radius-bottomright:5px;-webkit-border-bottom-right-radius:5px;border-bottom-right-radius:5px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box;-webkit-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset}.significant_fragments img{display:inline;float:left;margin:0.5em}.significant_fragments table#sf1{text-align:left}.significant_fragments table#sf1 td{padding:0.2em}.descriptors{width:98%;margin-bottom:2em;background-color:#c5c1e4;-moz-border-radius-bottomleft:5px;-webkit-border-bottom-left-radius:5px;border-bottom-left-radius:5px;-moz-border-radius-bottomright:5px;-webkit-border-bottom-right-radius:5px;border-bottom-right-radius:5px;-webkit-background-clip:border;-moz-background-clip:border;background-clip:border-box;-webkit-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset}.descriptors img{display:inline;float:left;margin:0.5em}.descriptors table#sf2{text-align:left}.descriptors table#sf2 td{padding:0.2em}.results{background-image:url("/images/gray_jean.png");overflow-x:auto;overflow-y:hidden;margin-top:2em;margin-bottom:2em;-webkit-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset}.results a:hover{color:#f55}.results .tablesorter{width:100%;text-align:left}.results .tablesorter thead{background-color:#e6e5f3}.results .tablesorter thead tr th.header{background-image:url("/images/bg.gif");background-repeat:no-repeat;background-position:center left;cursor:pointer;padding-left:20px;border:1px solid #dad9c7;margin-left:-1px}.results .tablesorter thead tr th.headerSortDown{background-image:url("/images/desc.gif");background-color:#c5c1e4}.results .tablesorter thead tr th.headerSortUp{background-image:url("/images/asc.gif");background-color:#c5c1e4}.results .tablesorter tbody tr td{padding-left:1em;-webkit-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;-moz-box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset;box-shadow:1px 1px 1px #fff inset,0px -1px 2px rgba(0,0,0,0.3) inset}.results .tablesorter tbody .compound{width:200px;padding:0.2em}.results .tablesorter tbody .n{color:#5c8533}.results .tablesorter tbody .c{color:#d42200}input#predict{border:0px;background-color:#c5c1e4;margin:0;padding:0}.tooltip{background-color:#fff;border:2px solid #ccc;font-size:0.5em;padding:1em;display:none;z-index:50}.footer{margin:20px 0 20px 0} diff --git a/public/stylesheets/screen.sass b/public/stylesheets/screen.sass index cb6dcdf..bfbedc6 100644 --- a/public/stylesheets/screen.sass +++ b/public/stylesheets/screen.sass @@ -1,16 +1,14 @@ //@import compass/reset, compass/css3, compass/utilities, compass/layout @import compass/css3 -$bg-color: #CCCCFF +//$bg-color: #CCCCFF $ist-color: #C5C1E4 body background-image: url("/images/gray_jean.png") - background-color: $bg-color + //background-color: $bg-color overflow: scroll font-family: sans-serif - //min-width: 800px - //min-heigth: 600px a text-decoration: none font-weight: bold @@ -18,6 +16,11 @@ body //for IE img border: 0 + h2 + padding-top: 12px + text-shadow: #FFF 1px 1px 0 + font-size: x-large + color: #FF5555 .logo img @@ -43,12 +46,8 @@ body font-size: x-large font-family: Verdana display: inline - h2 - text-shadow: #FFF 1px 1px 0 - font-size: x-large - color: #FF5555 .arrow - margin: 5px 0px 5px 20px + margin: 8px 0px 5px 20px .back display: inline //.close @@ -88,6 +87,28 @@ body #model a display: inline font-weight: normal + a#linkDetailsLC50_mmol + font-size: small + a#linkDetailsHamster + font-size: small + a#linkDetailsRodent + font-size: small + #details_LC50_mmol + background-color: adjust-lightness($ist-color, 10%) + //background-image: url("/images/gray_jean.png") + +box-shadow(1px 1px 1px rgba(white, 1) inset, -1px -1px 5px rgba(black, 0.3) inset) + padding: 1em + #details_Hamster + background-color: adjust-lightness($ist-color, 10%) + //background-image: url("/images/gray_jean.png") + +box-shadow(1px 1px 1px rgba(white, 1) inset, -1px -1px 5px rgba(black, 0.3) inset) + padding: 1em + #details_Rodent + background-color: adjust-lightness($ist-color, 10%) + //background-image: url("/images/gray_jean.png") + +box-shadow(1px 1px 1px rgba(white, 1) inset, -1px -1px 5px rgba(black, 0.3) inset) + padding: 1em + fieldset#bottom border: 0 background-color: $ist-color @@ -108,6 +129,8 @@ body +border-right-radius(25px) +background-clip(border-box) .overview + a:hover + color: #FF5555 background-image: url("/images/gray_jean.png") padding: 12px margin-top: 1em @@ -141,24 +164,74 @@ body +background-clip(border-box) .message margin-top: 1em - padding: 0.2em + padding: 1em border: 2px solid #FF5555 background-color: #FFFFFF color: #FF5555 + +border-left-radius(25px) + +border-right-radius(25px) + +background-clip(border-box) // close button for iframe also in content class #closebutton - margin-left: 95% + color: #FF5555 + margin-left: 98% padding: 0 - background-color: $ist-color - +border-bottom-left-radius(5px) - +border-bottom-right-radius(5px) + //background-color: $ist-color + //+border-bottom-left-radius(5px) + //+border-bottom-right-radius(5px) .details + //height: 100% + width: 98% + background-color: $ist-color + +border-bottom-left-radius(5px) + +border-bottom-right-radius(5px) + +background-clip(border-box) + +box-shadow(1px 1px 1px rgba(white, 1) inset, 0px -1px 2px rgba(black, 0.3) inset) + a:hover + color: #FF5555 + img + display: inline + float: left + margin: 0.5em + +.significant_fragments + //height: 100% + width: 98% margin-bottom: 2em - background-image: url("/images/gray_jean.png") - +border-bottom-left-radius(25px) - +border-bottom-right-radius(25px) + background-color: $ist-color + //background-image: url("/images/gray_jean.png") + +border-bottom-left-radius(5px) + +border-bottom-right-radius(5px) + +background-clip(border-box) + +box-shadow(1px 1px 1px rgba(white, 1) inset, 0px -1px 2px rgba(black, 0.3) inset) + img + display: inline + float: left + margin: 0.5em + table#sf1 + text-align: left + td + padding: 0.2em + +.descriptors + //height: 100% + width: 98% + margin-bottom: 2em + background-color: $ist-color + //background-image: url("/images/gray_jean.png") + +border-bottom-left-radius(5px) + +border-bottom-right-radius(5px) +background-clip(border-box) + +box-shadow(1px 1px 1px rgba(white, 1) inset, 0px -1px 2px rgba(black, 0.3) inset) + img + display: inline + float: left + margin: 0.5em + table#sf2 + text-align: left + td + padding: 0.2em .results background-image: url("/images/gray_jean.png") @@ -166,9 +239,12 @@ body overflow-y: hidden margin-top: 2em margin-bottom: 2em + a:hover + color: #FF5555 +box-shadow(1px 1px 1px rgba(white, 1) inset, 0px -1px 2px rgba(black, 0.3) inset) .tablesorter width: 100% + text-align: left thead background-color: adjust-lightness($ist-color, 10%) tr @@ -191,7 +267,8 @@ body padding-left: 1em +box-shadow(1px 1px 1px rgba(white, 1) inset, 0px -1px 2px rgba(black, 0.3) inset) .compound - width: 200px + width: 200px + padding: 0.2em .n color: #5C8533 .c diff --git a/unicorn.rb b/unicorn.rb new file mode 100644 index 0000000..c0441ab --- /dev/null +++ b/unicorn.rb @@ -0,0 +1,2 @@ +worker_processes 6 +timeout 6000 diff --git a/views/details.haml b/views/details.haml index 931b0b2..5663c1f 100644 --- a/views/details.haml +++ b/views/details.haml @@ -1,15 +1,14 @@ %link{ :href=>"/stylesheets/screen.css", :media=>"screen, projection", :rel=>"stylesheet", :type=>"text/css"} .content - %button{:id=>"closebutton", :onclick=>"parent.$('#iframe').bPopup().close();parent.$('#iframe_overview').bPopup().close();"} + %button{:id=>"closebutton", :onclick=>"parent.$('#iframe_details').bPopup().close();parent.$('#iframe_overview').bPopup().close();"} X - .details - %h2{:style=>"margin-top:0px"} - Details: - %img{:src=>"#{@compound_uri.uri}/image", :alt=>"Compound image not available", :width=>"300px", :heigth=>"300px"} - %br - %br + .details{:style=>"padding:0.5em;min-height:400px;"} + %h2{:style=>"margin:0px;margin-left:8px;"} + Names and synonyms: + %img{:src=>"#{@compound.uri}/image", :alt=>"Compound image not available", :width=>"300px", :heigth=>"300px"} + %p %b="SMILES:" %p= @smiles %br @@ -17,4 +16,10 @@ %p= @inchi %br %b="Names:" - %p= @names.gsub(",", ";\t") + %p{:style=>"padding-left:0.5em;"} + = @names + %p{:style=>"padding-left:0.5em;"} + / pubchem link + %a{:href=>"http://aop.in-silico.ch/", :title=>"link opens in new tab", :alt=>"pubchem link", :target=>"_blank"} PubChem read across + %i (experimental) + diff --git a/views/layout.haml b/views/layout.haml index c7f31b6..57c654a 100644 --- a/views/layout.haml +++ b/views/layout.haml @@ -3,6 +3,7 @@ %head %meta{'http-equiv' => 'Content-Type', :content => 'text/html; charset=UTF-8'} %title Lazar Toxicity Predictions + %link{:rel=>'icon', :type=>'image/x-icon', :href=>'/images/favicon.ico'} %link{ :href=>"/stylesheets/screen.css", :media=>"screen, projection", :rel=>"stylesheet", :type=>"text/css"} %link{ :href=>"/stylesheets/jquery-ui.css", :rel=>"stylesheet"} %link{ :href=>"/jsme/jsa.css", :rel=>"stylesheet"} @@ -23,8 +24,7 @@ %img{:src=>"/images/ist_logo.png", :alt=>"logo"} %h1 Lazar Toxicity Predictions - %a{:href=> "http://www.opentox.org/news/opentoxeu2013news1"} - %img{:src=>"/images/OpenToxEuro2013.png", :alt=>"OpenToxEuro2013", :class => "ote"} + %img{:src=>"/images/OpenToxEuro2013_small.png", :alt=>"OpenToxEuro2013", :class => "ote"} %hr .content diff --git a/views/neighbors.haml b/views/neighbors.haml index 750b615..39f6272 100644 --- a/views/neighbors.haml +++ b/views/neighbors.haml @@ -10,7 +10,7 @@ #tabs %ul / each endpoint becomes a tab head ; - - @@prediction_models.each do |m| + - @prediction_models.each do |m| - count_m += 1 - m_title = m.title.split(" ").first %li @@ -18,15 +18,19 @@ = m_title - count_rs = 0 / unpack to single arrays - - @@predictions.each do |pa| + - @predictions.each do |pa| + / pass model type for significant fragments view + - @type = @model_type[count_rs] - count_rs += 1 #results{:id=>"#{count_rs}"} - pa.each do |p| / prepare dataset for neighbors table ; - / delete first array which contains input compound prediction ; - / keep the following arrays they are the neighbor predictions ; + / delete first array which contains prediction ; + / following arrays are the neighbor predictions ; + - @model_uri = p.metadata[RDF::OT.hasSource][0] - p.data_entries.shift - p.compounds.shift + / call the tablesorter plugin ; / presort by similarity ; :javascript @@ -38,81 +42,95 @@ sortList: [[2,1]] }); }); - / TODO catch table error if tbody is empty %h2= "Neighbors: " - %table{:id=>"#{count_rs}", :class=>"tablesorter", :cellspacing=>"1"} - %thead - %tr - %th - Compound - %th - %b Measured Activity - / title must be empty for tooltip - %a{:href=>"#", :title=>"", :id=>"measured_activity"} - %img{:src=>"/images/info_white.png"} - .tooltip{:style=>"font-weight: normal; font-size: 1em; text-align: left;"} - %dt - Measured Activity - %dd - Experimental result(s) from the training dataset. - %th - %b Similarity - / title must be empty for tooltip - %a{:href=>"#", :title=>"", :id=>"similarity"} - %img{:src=>"/images/info_white.png"} - .tooltip{:style=>"font-weight: normal; font-size: 1em; text-align: left;"} - %dt - Similarity - %dd - %code lazar - calculates - %em - activity specific - similarities based on the presence of statistically significant fragments. - This procedure will - %ul - %li consider only those parts of a chemical structure that are relevant - for a particular endpoint - %li ignore inert parts of the structure - %li lead to different similarities, depending on the toxic endpoint - Similarities of 1 may be encountered even for structurally dissimilar - compounds, because inert parts are ignored. - %th - Details - -#%tbody - - count = 0 - - p.compounds.each do |neighbor_compound| - / prevent conversion of nil - - c = p.data_entries[count][2] != nil ? p.data_entries[count][2] : '' - - $logger.debug "inspect c :#{c}\n" - - case c - - when /(0|false)/ - - c = "non-carcinogen" - - when /(1|true)/ - - c = "carcinogen" - - else - - c = Array.new - - c[0] = p.data_entries[count][2] - %tr - %td.compound - %img{:src=>"#{neighbor_compound.uri}/image", :alt=>"Compound image not available", :width=>"150px"} - %td{:class => c[0]} - - if c.class == String - = c - - else - = c[0] - %td{:class => c[0]} - = p.data_entries[count][3] != nil ? p.data_entries[count][3].round(3) : "Not enough similar compounds in training dataset." - %td - %a{:href => to("/prediction/#{CGI.escape(neighbor_compound.uri)}/details"), :id=>"link#{count_rs}#{count}", :target=>"details"} - %img{:src=>"/images/arrow_right_float.png", :alt=>">"} - :javascript - $(function() { - $("a#link#{count_rs}#{count}").on('click', function(e) { - $('#iframe').bPopup(); - }); - }); - - - count += 1 + - $logger.debug "neighbors compounds:\t#{p.data_entries[0]}\n" + - if p.data_entries[0][2] != nil && p.data_entries[0].size != 3 + %table{:id=>"#{count_rs}", :class=>"tablesorter", :cellspacing=>"1"} + %thead + %tr + %th + Compound + %th + %b Measured Activity + / title must be empty for tooltip + %a{:href=>"#", :title=>"", :id=>"measured_activity"} + %img{:src=>"/images/info_white.png"} + .tooltip{:style=>"font-weight: normal; font-size: 1em; text-align: left;"} + %dt + Measured Activity + %dd + Experimental result(s) from the training dataset. + %th + %b Similarity + / title must be empty for tooltip + %a{:href=>"#", :title=>"", :id=>"similarity"} + %img{:src=>"/images/info_white.png"} + .tooltip{:style=>"font-weight: normal; font-size: 1em; text-align: left;"} + %dt + Similarity + %dd + %code lazar + calculates + %em + activity specific + similarities based on the presence of statistically significant fragments. + This procedure will + %ul + %li consider only those parts of a chemical structure that are relevant + for a particular endpoint + %li ignore inert parts of the structure + %li lead to different similarities, depending on the toxic endpoint + Similarities of 1 may be encountered even for structurally dissimilar + compounds, because inert parts are ignored. + %th + Supporting information + -#%tbody + - count = 0 + - p.compounds.each do |neighbor_compound| + / prevent conversion of nil + - c = p.data_entries[count][2] != nil ? p.data_entries[count][2] : '' + - case c + - when /(0|false)/ + - c = "non-carcinogen" + - when /(1|true)/ + - c = "carcinogen" + - else + - c = Array.new + - c[0] = p.data_entries[count][2] + %tr + %td.compound + %img{:src=>"#{neighbor_compound.uri}/image", :alt=>"Compound image not available", :title=>"#{neighbor_compound.smiles}", :width=>"150px"} + %td{:class => c[0]} + - if c.class == String + = c + - else + = c[0] + %td{:class => c[0]} + = p.data_entries[count][3] != nil ? p.data_entries[count][3].round(3) : "Not enough similar compounds in training dataset." + %td + -#- if p.data_entries[count][3] != nil + %a{:href => to("/prediction/#{CGI.escape(neighbor_compound.uri)}/details"), :id=>"link#{count_rs}#{count}", :target=>"details"} Names and synonymes + %br + - if @type =~ /classification/i + - if p.data_entries[count][3] != nil + %a{:href => to("/prediction/#{CGI.escape(@model_uri)}/#{@type}/#{CGI.escape(neighbor_compound.uri)}/significant_fragments"), :id=>"link#{count_rs}#{count}sf", :target=>"details"} Significant fragments + - if @type =~ /regression/i + - if p.data_entries[count][3] != nil + %a{:href => to("/prediction/#{CGI.escape(@model_uri)}/#{@type}/#{CGI.escape(neighbor_compound.uri)}/significant_fragments"), :id=>"link#{count_rs}#{count}sf", :target=>"details"} Descriptors + :javascript + $(function() { + $("a#link#{count_rs}#{count}").on('click', function(e) { + $('#iframe_details').bPopup(); + }); + }); + $(function() { + $("a#link#{count_rs}#{count}sf").on('click', function(e) { + $('#iframe_details').bPopup(); + }); + }); + - count += 1 + - else + %h3 + Not enough similar compounds in training dataset -%iframe{:id=>"iframe", :name=>"details", :height=>"90%", :width=>"90%", :style=>"display:none;border:0px"} +%iframe{:id=>"iframe_details", :name=>"details", :height=>"95%", :width=>"95%", :style=>"display:none;border:0px"} diff --git a/views/predict.haml b/views/predict.haml index c37c61d..5641f6a 100644 --- a/views/predict.haml +++ b/views/predict.haml @@ -59,7 +59,7 @@ %fieldset#middle %a{:href => "#models", :id => "linkModels"} - %h1 2. Select one or more toxic endpoints + %h1 2. Select one or more endpoints :javascript $("a#linkModels").click(function () { @@ -68,20 +68,74 @@ }); #models - %i Please observe validation report for model details. - - // TODO order models by echa endpoint currently manually added and to find in model.type + // TODO order models by echa endpoint #endpoint - %b= "Carcinogenicity:" + %b Acute toxicity to fish (lethality): + - @models.each do |model| + - model_title = model.title.split(" ").first + - if model_title =~ /LC50/ + %div{:id => model_title} + %input{:type => "checkbox", :name => "selection[#{model_title}]", :id => "selection[#{model_title}]", :value => true, :disabled => false} + %label{:for => "selection[#{model_title}]"} + = " EPA v4b Fathead Minnow Acute Toxicity "+model_title + %a{:href=>"#details", :id => "linkDetails#{model_title}", :title=>"#{model_title} details"} + [Details] + + :javascript + $("a#linkDetails#{model_title}").click(function () { + $("#details_#{model_title}").toggle(); + //document.location = document.location + "#" + "details"; + }); + + #details{:id => "#{model_title}", :style=> "display:none;"} + %h3 Model Details: + //%p= "Training Dataset:\t#{model[RDF::OT.trainingDataset]}" + %p Algorithm: Lazar + %p Type: regression + %p Training compounds: integer + %p Descriptors: Fminer + //%p= "Training Dataset:\t#{model[RDF::OT.trainingDataset]}" + //%p= "Feature Dataset:\t#{model[RDF::OT.featureDataset]}" + %h3 Validation: + %a{:href => "#"} + Detailed report link + %p Number of predictions: integer + %p Correct predictions: % + %br + %b Carcinogenicity: - @models.each do |model| - model_title = model.title.split(" ").first - %div{:id => model_title} - %input{:type => "checkbox", :name => "selection[#{model_title}]", :id => "selection[#{model_title}]", :value => true, :disabled => false} - %label{:for => "selection[#{model_title}]"} - = "DSSTox Carcinogenic Potency DBS "+model_title - %a{:href=>"#", :title=>"#{model_title} validation"} - %i ( Validation report ) - %br + - if model_title =~ /hamster|rodent/i + %div{:id => model_title} + %input{:type => "checkbox", :name => "selection[#{model_title}]", :id => "selection[#{model_title}]", :value => true, :disabled => false} + %label{:for => "selection[#{model_title}]"} + = " DSSTox Carcinogenic Potency DBS "+model_title + %a{:href=>"#details", :id => "linkDetails#{model_title}", :title=>"#{model_title} details"} + [Details] + + :javascript + $("a#linkDetails#{model_title}").click(function () { + $("#details_#{model_title}").toggle(); + //document.location = document.location + "#" + "details"; + }); + + #details{:id=>"#{model_title}", :style=> "display:none;"} + %h3 Model Details: + //%p= "Training Dataset:\t#{model[RDF::OT.trainingDataset]}" + %p Algorithm: Lazar + %p Type: classification + %p Training compounds: integer + %p Descriptors: Fminer + //%p= "Training Dataset:\t#{model[RDF::OT.trainingDataset]}" + //%p= "Feature Dataset:\t#{model[RDF::OT.featureDataset]}" + %h3 Validation: + %a{:href => "#"} + Detailed report link + %p Number of predictions: integer + %p Correct predictions: % + %br + + %br .arrow %img{:src=>"/images/arrow_down_float.png", :alt=>"v", :class=> "arrow"} diff --git a/views/prediction.haml b/views/prediction.haml index f902504..4002cbd 100644 --- a/views/prediction.haml +++ b/views/prediction.haml @@ -4,7 +4,7 @@ %img{:src=>"/images/arrow_left_float.png", :alt=>"<"} %a{:href => to('/predict')} New Prediction - / displays all prediction results + / displays all prediction result in first table .overview %table{:width=>"100%", :cellspacing=>"1", :id=>"overview"} %thead @@ -17,9 +17,9 @@ %td{:id=>"compound"} %a{:href => to("/prediction/#{CGI.escape(@compound.uri)}/details"), :id=>"linkCompound", :target=>"details_overview"} %img{:src=>"#{@compound.uri}/image", :alt=>"Compound image not available", :width=>"150", :height=>"150"} - %br - %br - %img{:src=>"/images/arrow_up_float.png", :alt=>"^"} + %p + %a{:href => to("/prediction/#{CGI.escape(@compound.uri)}/details"), :id=>"linkCompound", :target=>"details_overview"} Names and synonyms + %p :javascript $(function() { $("a#linkCompound").on('click', function(e) { @@ -27,18 +27,18 @@ }); }); - count=0 - / var for rule to load neighbors page. - - @@neighbors_available = 1 - - @@predictions.each do |pa| - / prediction of one model + - @predictions.each do |pa| + / unpack to single array/prediction + / if p.data_entries array[0].size == 3 -> database hit + / change 'result' if database hit + / change 'confidence' if database hit - pa.each do |p| - - $logger.debug "inspect p: #{p.inspect}\n" - - $logger.debug "inspect data_entries: #{p.data_entries}\n" - / p.data_entries > 1 = neighbors available - - p.data_entries.length > 1 ? @@neighbors_available = p.data_entries.length : @@neighbors_available / prevent conversion of nil + /- $logger.debug "data entries in prediction array:\t#{p.data_entries}\n" + - database_hit = 0 + - if p.data_entries[0].size == 3 + - database_hit = 1 - c = p.data_entries[0][0] != nil ? p.data_entries[0][0] : '' - - $logger.debug "inspect c: #{c.inspect}\n" - case c - when /(0|false)/ - c = "non-carcinogen" @@ -46,15 +46,17 @@ - c = "carcinogen" - else - c = Array.new - - c[0] = (p.data_entries[0][0].class == Float) ? p.data_entries[0][0].round(3) : (p.data_entries[0][0] != nil ? p.data_entries[0][0] : "no value") + - c[0] = (p.data_entries[0][0].class == Float) ? p.data_entries[0][0].round(3) : (p.data_entries[0][0] != nil ? p.data_entries[0][0] : "no prediction") %td %b{:class => "title"} - = @@prediction_models[count].title.split(" ").first - %br - %br - / classification, regression - %b Type: - %br + = @prediction_models[count].title.split(" ").first + - @model_uri = @prediction_models[count].uri + %p + / model type (classification|regression) + %b Type: + = @model_type[count] + %p + - unless database_hit > 0 %b Result: %b{:class => c[0]} - if c.class == String @@ -76,18 +78,18 @@ %li a majority vote (weighted by compound similarity) for %em classification ( - %a{:href=>"http://www.in-silico.de/articles/modi020905.pdf"} original publication + %a{:href=>"http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract", :target=>"_blank"} original publication ) %li a local QSAR model based on neighbors for %em regression ( - %a{:href=>"http://www.in-silico.de/articles/mh_tf.pdf"} original publication + %a{:href=>"http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract", :target=>"_blank"} original publication ) Please keep in mind that predictions are based on the measured activities of neighbors. - %br + %p .confidence %b Confidence: - = p.data_entries[0][1] != nil ? p.data_entries[0][1].round(3) : "" + = p.data_entries[0][1] != nil ? p.data_entries[0][1].round(3) : "-" / title must be empty for tooltip %a{:href=>"#confidence", :title=>"", :id=>"confidence"} %img{:src=>"/images/info_white.png"} @@ -101,20 +103,65 @@ Confidence values may take any value between 0 and 1. For most models confidence > 0.025 is a sensible (hard) cutoff to distiguish between reliable and unreliable predictions. - %br - %a{:href=> "#tabs", :id=>"link#{count}"} - %img{:src=>"/images/arrow_down_float.png", :alt=>"v"} - :javascript - $("a#link#{count}").click(function () { - $(".results").show(); - document.getElementById('tabs').focus(); - $("#tabs").tabs({ active: "#{count}" }); - }); - - count+=1 - - - if @@neighbors_available > 1 - = haml :neighbors, :layout => false - - else - %h2 - no neighbors available -%iframe{:id=>"iframe_overview", :name=>"details_overview", :height=>"90%", :width=>"90%", :style=>"display:none;border:0px"} + %p + /TODO add tooltip for significant ftagments and descriptors + - if @model_type[count] =~ /classification/i + / Significant fragments: + %a{:href => to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[count]}/#{CGI.escape(@compound.uri)}/fingerprints"), :id=>"linkPredictionSf", :target=>"details_overview"}Significant fragments + :javascript + $(function() { + $("a#linkPredictionSf").on('click', function(e) { + $('#iframe_overview').bPopup(); + }); + }); + - if @model_type[count] =~ /regression/i + / Descriptors + %a{:href => to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[count]}/#{CGI.escape(@compound.uri)}/fingerprints"), :id=>"linkPredictionSf", :target=>"details_overview"} Descriptors + :javascript + $(function() { + $("a#linkPredictionSf").on('click', function(e) { + $('#iframe_overview').bPopup(); + }); + }); + / title must be empty for tooltip + -#%a{:href =>"#sfragments", :title=>"", :id=>"sfragments"} + %img{:src=>"/images/info_white.png"} + -#.tooltip{:style=>"font-weight: normal; font-size: 1em; width: 50%; text-align: left;"} + %dt + Significant fragments + %dd + Significant fragments are solely used to determine activity specific similarities of neighbors. + %p + %b Neighbors: + %a{:href=> "#tabs", :id=>"link#{count}"} + %img{:src=>"/images/arrow_down_float.png", :alt=>"v"} + :javascript + $("a#link#{count}").click(function () { + $(".results").show(); + document.getElementById('tabs').focus(); + $("#tabs").tabs({ active: "#{count}" }); + }); + %p + - count+=1 + - else # database hit + %b Database hit: + %br Compound found in training dataset + %p + %b Measured activity: + = p.data_entries[0][2] + %p + %b Neighbors: + %a{:href=> "#tabs", :id=>"link#{count}"} + %img{:src=>"/images/arrow_down_float.png", :alt=>"v"} + :javascript + $("a#link#{count}").click(function () { + $(".results").show(); + document.getElementById('tabs').focus(); + $("#tabs").tabs({ active: "#{count}" }); + }); + + - count+=1 + + / always show the neighbors table, message is given there + = haml :neighbors, :layout => false, :model_type => @model_type +%iframe{:id=>"iframe_overview", :name=>"details_overview", :height=>"95%", :width=>"95%", :style=>"display:none;border:0px"} diff --git a/views/significant_fragments.haml b/views/significant_fragments.haml new file mode 100644 index 0000000..7d342d0 --- /dev/null +++ b/views/significant_fragments.haml @@ -0,0 +1,63 @@ +%link{ :href=>"/stylesheets/screen.css", :media=>"screen, projection", :rel=>"stylesheet", :type=>"text/css"} +/TODO put smiles in div if compound image is not available, prevent overlay to table +.content + %button{:id=>"closebutton", :onclick=>"parent.$('#iframe_details').bPopup().close();parent.$('#iframe_overview').bPopup().close();"} + X +- if @type =~ /classification/i + .significant_fragments{:style=>"padding:0.5em;min-height:400px"} + %h2{:style=>"margin:0px;margin-left:8px;"} + Significant fragments: + + %img{:src=>"#{@compound.uri}/image", :alt=>"#{@compound.smiles}", :title=>"#{@compound.smiles}", :width=>"300px", :heigth=>"300px"} + - if !@significant_fragments.empty? + %table{:id => "sf1"} + %tr + %th{:style=>"border:1px solid;"} + Predominantly in compounds with activity "non-carcinogen" + %th{:style=>"border:1px solid;"} + p value + - @significant_fragments.each do |fragments| + / fragments == [1||2, smarts, pValue] + - if fragments[0] == 1 + %tr + %td + = fragments[1] + %td + = fragments[2] + %tr + %td + %br + %tr + %th{:style=>"border:1px solid;"} + Predominantly in compounds with activity "carcinogen" + %th{:style=>"border:1px solid;"} + p value + - @significant_fragments.each do |fragments| + / fragments == [1||2, smarts, pValue] + - if fragments[0] == 2 + %tr + %td + = fragments[1] + %td + = fragments[2] + +- if @type =~ /regression/i + .descriptors{:style=>"padding:0.5em;min-height:400px"} + %h2{:style=>"margin:0px;margin-left:8px;"} + Descriptors: + + %img{:src=>"#{@compound.uri}/image", :alt=>"#{@compound.smiles}", :title=>"#{@compound.smiles}", :width=>"300px", :heigth=>"300px"} + - if !@significant_fragments.empty? + %table{:id => "sf2"} + %tr + %th{:style=>"border:1px solid;"} + Descriptor + %th{:style=>"border:1px solid;"} + value + - @significant_fragments.each do |fragments| + %tr + %td + = fragments[0] + %td + = fragments[1][0].round(3) + -- cgit v1.2.3