diff options
-rw-r--r-- | application.rb | 2 | ||||
-rw-r--r-- | views/details.haml | 13 | ||||
-rw-r--r-- | views/layout.haml | 8 | ||||
-rw-r--r-- | views/neighbors.haml | 197 | ||||
-rw-r--r-- | views/predict.haml | 5 | ||||
-rw-r--r-- | views/prediction.haml | 34 | ||||
-rw-r--r-- | views/significant_fragments.haml | 10 |
7 files changed, 127 insertions, 142 deletions
diff --git a/application.rb b/application.rb index 3f3d5f0..cff08a2 100644 --- a/application.rb +++ b/application.rb @@ -195,7 +195,7 @@ get '/predict/:dataset/?' do t = Tempfile.new("tempfile.rdf") t << `curl -k -H accept:application/rdf+xml #{params[:dataset]}` send_file t.path, - :filename => params[:dataset].split("_").last+".rdf" + :filename => params[:dataset].split("/").last+".rdf" t.close t.unlink end diff --git a/views/details.haml b/views/details.haml index 00d8f61..8a57440 100644 --- a/views/details.haml +++ b/views/details.haml @@ -1,15 +1,8 @@ -:javascript - $(document).ready(function(){ - $("#details").on('hidden.bs.modal', function() { - $(this).removeData('bs.modal'); - }); - }); - %div.modal-body{:style=>"padding:10px;"} %button.close{ :type=>" button", data: { dismiss:"modal"}} × - %h2 + %h3 Names and synonyms: - %img{:src=>"#{@compound.uri}/image", :alt=>"Compound image not available", :width=>"300px", :heigth=>"300px", :style=>"float:left;"} + %img.img-responsive{:src=>"#{@compound.uri}/image", :alt=>"Compound image not available", :width=>"300px", :heigth=>"300px", :style=>"float:left;"} %p %b="SMILES:" %p= @smiles @@ -28,4 +21,4 @@ / pubchem link %a.btn.btn-primary{:href=>"http://aop.in-silico.ch/", :title=>"Link opens in new window.", :alt=>"pubchem read across", :target=>"_blank"} PubChem read across %i (experimental) - + %br diff --git a/views/layout.haml b/views/layout.haml index 8703042..d0c77b7 100644 --- a/views/layout.haml +++ b/views/layout.haml @@ -10,10 +10,8 @@ %link{:rel=>'stylesheet', :href=>"#{'/css/theme.default.min.css'}"} %link{:rel=>'stylesheet', :href=>"#{'/css/theme.bootstrap.min.css'}"} %link{ :href=>"/stylesheets/jquery-ui.css", :rel=>"stylesheet"} - %link{ :href=>"/jsme/jsa.css", :rel=>"stylesheet"} %script{:src=>"/javascripts/jquery-1.11.2.min.js"} %script{:src=>"/javascripts/bootstrap.min.js"} - %script{:src=>"/javascripts/jquery-ui-1.10.3.custom.min.js"} %script{:src=>"/javascripts/jquery.tablesorter.min.js"} %script{:src=>"/javascripts/jquery.tablesorter.widgets.js"} %script{ :src=>"/javascripts/lazar-gui.js"} @@ -25,11 +23,11 @@ %div.row %div.col-md-2 %a{:href=> to("/predict")} - %img.media-object{:src=>"/images/ist_logo.png", :alt=>"logo", :style=>"margin-left:3em;margin-right:1em;"} + %img.media-object{:src=>"/images/ist_logo.png", :alt=>"logo", :style=>"margin:0 3em 0 2em;"} %div.col-md-8 - %h1.media-heading Lazar Toxicity Predictions + %h1.media-heading{:style=>"margin: 0 0 0 1em;"} Lazar Toxicity Predictions - %div.container + %div.container-fluid :javascript $(document).ready(function(){ $("#back-top").hide(); diff --git a/views/neighbors.haml b/views/neighbors.haml index db32c88..22dff56 100644 --- a/views/neighbors.haml +++ b/views/neighbors.haml @@ -1,11 +1,3 @@ -:javascript - $(function() { - $("#deatils.modal").on('show.bs.modal', function() { - alert("alert"); - //$(this).removeData('bs.modal'); - }); - }); - / unpacks multi prediction array ; / prepare it for neighbors ; / align single prediction to endpoint ; @@ -13,110 +5,109 @@ %div.results{:style=>"display:none"} - count_m = 0 - / tabs div ; + %h3 Neighbors: + / tabs div #tabs - %ul + %ul.nav.nav-tabs.nav-justified{:id=>"neighborTabs", :role=>"tablist"} / each model a tab head ; - @prediction_models.each do |m| - count_m += 1 - m_title = m.title.split("_").last(2)[0] %li - %a{:href => "#results_#{count_m}", :id => "link#{m_title}"} + %a{:href => "#results_#{count_m}", :id => "linkTab#{count_m}", data: {toggle:"tab"}} = m_title - count_rs = 0 - / unpack to single arrays - - @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 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 - $(document).ready(function(){ - $("table##{count_rs}").tablesorter({ - debug: false, - table: 'ui-widget ui-widget-content ui-corner-all', - header: 'ui-widget-header ui-corner-all ui-state-default', - theme: "bootstrap", - widthFixed: true, - hover: 'ui-state-hover', - even: 'ui-widget-content', - odd: 'ui-state-default', - headerTemplate: '{content} {icon}', - widgets: ['zebra', 'columns', 'uitheme'], - headers: {0: {sorter: false}, 3: {sorter: false}}, - sortList: [[2,1]] + %div.tab-content + / unpack to single arrays + - @predictions.each do |pa| + / pass model type for significant fragments view + - @type = @model_type[count_rs] + - count_rs += 1 + #results.tab-pane.fade{:id=>"#{count_rs}"} + - pa.each do |p| + / prepare dataset for neighbors table ; + / 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 + $(document).ready(function(){ + $("table##{count_rs}").tablesorter({ + debug: false, + //table: 'ui-widget ui-widget-content ui-corner-all', + //header: 'ui-widget-header ui-corner-all ui-state-default', + theme: "bootstrap", + //widthFixed: true, + //hover: 'ui-state-hover', + //even: 'ui-widget-content', + //odd: 'ui-state-default', + headerTemplate: '{content} {icon}', + widgets: ['zebra', 'columns', 'uitheme'], + headers: {0: {sorter: false}, 3: {sorter: false}}, + sortList: [[2,1]] + }); }); - }); - - $logger.debug "neighbors compounds:\t#{p.data_entries[0]}\n" - - if p.data_entries[0][2] != nil && p.data_entries[0].size != 3 - %h2= "Neighbors: " - - %div.table-responsive - %table.tablesorter{:id=>"#{count_rs}", :style=>"border-style: solid;"} - %thead - %tr - %th{:style =>"vertical-align:middle;"} - Compound - %th{:style =>"vertical-align:middle;"} - Measured Activity - -#%a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Measured Activity", data: {toggle:"popover", placement:"auto", trigger:"focus", html:"true", content:"Experimental result(s) from the training dataset."}, :style=>"z-index:auto+10;"} - %th{:style =>"vertical-align:middle;"} - Similarity - -#%a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Similarity", data: {toggle:"popover", placement:"auto", trigger:"focus", html:"true", content:"LAZAR calculates 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><li>ignore inert parts of the structure</li><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.</li></ul>"}, :style=>"z-index:auto+10;"} - %th{:style =>"vertical-align:middle;"} - Supporting Information - %info - %tr - %td - %td{:style=>"font-size:x-small;padding:0px;"} - %a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Measured Activity", data: {toggle:"popover", placement:"auto", trigger:"focus", html:"true", content:"Experimental result(s) from the training dataset."}, :style=>"z-index:auto+10;"} - %td{:style=>"font-size:x-small;padding:0px;"} - %a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Similarity", data: {toggle:"popover", placement:"auto", trigger:"focus", html:"true", content:"LAZAR calculates 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><li>ignore inert parts of the structure</li><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.</li></ul>"}, :style=>"z-index:auto+10;"} - %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 /(false|true|inactive|active)/i - - c = c - - else - /- c = Array.new - - c = p.data_entries[count][2].to_f.round(3) - %tr - %td{:style =>"vertical-align:middle;padding-left:1em;"} - %a.btn.btn-link{:href => to("/prediction/#{CGI.escape(neighbor_compound.uri)}/details"), :id=>"link#{count_rs}#{count}", data: { toggle: "modal", target:"#details"}} - %img.blind{:src=>"#{neighbor_compound.uri}/image", :alt=>"no image", :onError=>"this.onerror=null;", :title=>"#{neighbor_compound.smiles}", :width=>"150px"} - %td{:style =>"vertical-align:middle;padding-left:1em;"} - - if c.class == String - = c + - $logger.debug "neighbors compounds:\t#{p.data_entries[0]}\n" + - if p.data_entries[0][2] != nil && p.data_entries[0].size != 3 + -#%h2= "Neighbors: " + + %div.table-responsive + %table.tablesorter{:id=>"#{count_rs}", :style=>"border-style: solid;"} + %thead + %tr + %th{:style =>"vertical-align:middle;"} + Compound + %th{:style =>"vertical-align:middle;"} + Measured Activity + %th{:style =>"vertical-align:middle;"} + Similarity + %th{:style =>"vertical-align:middle;"} + Supporting Information + %info + %tr + %td + %td{:style=>"font-size:x-small;padding:0px;"} + %a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Measured Activity", data: {toggle:"popover", placement:"auto", html:"true", content:"Experimental result(s) from the training dataset."}, :style=>"z-index:auto+10;"} + %td{:style=>"font-size:x-small;padding:0px;"} + %a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Similarity", data: {toggle:"popover", placement:"auto", html:"true", content:"LAZAR calculates 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><li>ignore inert parts of the structure</li><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.</li></ul>"}, :style=>"z-index:auto+10;"} + %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 /(false|true|inactive|active)/i + - c = c - else - = c - %td{:style =>"vertical-align:middle;padding-left:1em;"} - = p.data_entries[count][3] != nil ? p.data_entries[count][3].round(3) : "Not enough similar compounds in training dataset." - %td{:style =>"vertical-align:middle;padding-left:1em;"} - - if @type =~ /classification/i - - if p.data_entries[count][3] != nil - %a.btn.btn-primary{:href => to("/prediction/#{CGI.escape(@model_uri)}/#{@type}/#{CGI.escape(neighbor_compound.uri)}/significant_fragments"), :id=>"link#{count_rs}#{count}sf", data: { toggle: "modal", target:"#details"}} Significant fragments - - if @type =~ /regression/i - - if p.data_entries[count][3] != nil - %a.btn.btn-primary{:href => to("/prediction/#{CGI.escape(@model_uri)}/#{@type}/#{CGI.escape(neighbor_compound.uri)}/significant_fragments"), :id=>"link#{count_rs}#{count}sf", data: { toggle: "modal", target:"#details"}} Descriptors - - count += 1 - -#- else - %h3 - Not enough similar compounds in training dataset + /- c = Array.new + - c = p.data_entries[count][2].to_f.round(3) + %tr + %td{:style =>"vertical-align:middle;padding-left:1em;"} + %a.btn.btn-link{:href => "#details#{count_rs}", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(neighbor_compound.uri)}/details"), :id=>"link#{count_rs}#{count}"}} + %img.blind{:src=>"#{neighbor_compound.uri}/image", :alt=>"no image", :onError=>"this.onerror=null;", :title=>"#{neighbor_compound.smiles}", :width=>"150px"} + %td{:style =>"vertical-align:middle;padding-left:1em;"} + - if c.class == String + = c + - else + = c + %td{:style =>"vertical-align:middle;padding-left:1em;"} + = p.data_entries[count][3] != nil ? p.data_entries[count][3].round(3) : "Not enough similar compounds in training dataset." + %td{:style =>"vertical-align:middle;padding-left:1em;"} + - if @type =~ /classification/i + - if p.data_entries[count][3] != nil + %a.btn.btn-default{:href => "#details#{count_rs}", :id=>"link#{count_rs}#{count}sf", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@type}/#{CGI.escape(neighbor_compound.uri)}/significant_fragments")}} Significant Fragments + - if @type =~ /regression/i + - if p.data_entries[count][3] != nil + %a.btn.btn-default{:href => "#details#{count_rs}", :id=>"link#{count_rs}#{count}sf", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@type}/#{CGI.escape(neighbor_compound.uri)}/significant_fragments")}} Descriptors + - count += 1 + - else + %span.btn.btn-default.disabled Not enough similar compounds in training dataset -%div.modal.fade{:id=>"details", :role=>"dialog"} - %div.modal-dialog.modal-lg - %div.modal-content + %div.modal.fade{:id=>"details#{count_rs}", :role=>"dialog"} + %div.modal-dialog.modal-lg + %div.modal-content diff --git a/views/predict.haml b/views/predict.haml index 0ff25e8..bd430a6 100644 --- a/views/predict.haml +++ b/views/predict.haml @@ -1,3 +1,4 @@ +%link{ :href=>"/jsme/jsa.css", :rel=>"stylesheet"} %script{:src=>"/jsme/jsme.nocache.js"} :javascript function callTask(url) { @@ -178,9 +179,9 @@ %h2 3. Predict %div.col-md-10 - %input.btn.btn-warning.h2{ :type => "submit", :id => "submit", :value=>">>", :onclick => "(progress($('.progress-bar'),'#{task_uri}') & getsmiles() & checkboxes())"} + %input.btn.btn-warning.h2{ :type => "submit", :id => "submit", :value=>">>", :onclick => "(progress($('.progress-bar'),'#{task_uri}') & getsmiles())"} %input{:type => "hidden", :name => "task_uri", :value => "#{task_uri}"} %div.row %div.col-md-12 %div.progress - %div.progress-bar.progress-bar-striped.active{:role=>"progressbar", aria: { valuemin: 0, valuemax: 100}, :style=>"width:0%;"} + %div.progress-bar.progress-bar-striped.active{:role=>"progressbar", aria: { valuemin: 0, valuemax: 100}, :style=>"width:0;"} diff --git a/views/prediction.haml b/views/prediction.haml index 8d9e235..dfc11fc 100644 --- a/views/prediction.haml +++ b/views/prediction.haml @@ -1,25 +1,25 @@ :javascript $(document).ready(function(){ $('[data-toggle="popover"]').popover(); - $(".modal").on('hidden.bs.modal', function() { + $('.modal').on('hidden.bs.modal', function () { $(this).removeData('bs.modal'); }); }); %div.well - %a.btn.btn-primary{:href => to('/predict')} New Prediction + %a.btn.btn-warning{:href => to('/predict')} New Prediction / displays all prediction result in first table %div.table-responsive - %table.table.table-bordered{:id=>"overview"} + %table.table.table-bordered{:id=>"overview", :style=>"background-color:white;"} %thead %tr - %h2 Prediction Results: + %h3 Prediction Results: %tbody %tr %td{:id=>"compound", :style=>"vertical-align:top;"} - %a.btn.btn-link{:href => to("/prediction/#{CGI.escape(@compound.uri)}/details"), :id=>"linkCompound", data: { toggle: "modal", target:"#detailsTop"}} - %img{:src=>"#{@compound.uri}/image", :alt=>"no image", :title=>"#{@compound.smiles}", :width=>"150", :height=>"150"} + %a.btn.btn-link{:href => "#detailsTop", :id=>"linkCompound", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@compound.uri)}/details")}} + %img.img-responsive{:src=>"#{@compound.uri}/image", :alt=>"no image", :title=>"#{@compound.smiles}", :width=>"150", :height=>"150"} - count=0 - @predictions.each do |pa| / unpack to single array/prediction @@ -58,7 +58,7 @@ - result = (c != '' ? c.round(3) : "No prediction result.") = result - confidence = (p.data_entries[0][1] != nil && p.data_entries[0][1] != 0.0) ? p.data_entries[0][1].round(2) : "--" - %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Result", data: {toggle:"popover", placement:"left", trigger:"focus", html:"true", content:"LAZAR calculates searches the training dataset for similar compounds (neighbors) and calculates the prediction from their measured activities. LAZAR calculates predictions using <ul><li>a majority vote (weighted by compound similarity) for<br /><b>classification</b> (<a href='http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract', target='_blank'>original publication</a>) </li><li>a local QSAR model based on neighbors for<br /><b>regression</b> (<a href='http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract', target='_blank'</h>original publication</a>) </li></ul>Please keep in mind that predictions are based on the measured activities of neighbors."}} + %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Result", data: {toggle:"popover", placement:"left", html:"true", content:"LAZAR calculates searches the training dataset for similar compounds (neighbors) and calculates the prediction from their measured activities. LAZAR calculates predictions using <ul><li>a majority vote (weighted by compound similarity) for<br /><b>classification</b> (<a href='http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract', target='_blank'>original publication</a>) </li><li>a local QSAR model based on neighbors for<br /><b>regression</b> (<a href='http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract', target='_blank'</h>original publication</a>) </li></ul>Please keep in mind that predictions are based on the measured activities of neighbors."}} - @cv = OpenTox::Validation.find @prediction_models[count].metadata[RDF::OT.crossValidation][0]+"/statistics" #unless @prediction_models[count].title.include?("Mutagenicity") - unless @model_type[count] == "regression" %br @@ -70,24 +70,25 @@ %p %b Confidence: = confidence - %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Confidence", data: {toggle:"popover", placement:"left", trigger:"focus", html:"true", content:"Indicates the applicability domain of a model. Predictions with a high confidence can be expected to be more reliable than predictions with low confidence. Confidence values may take any value between 0 and 1. For most models confidence > 0.025 is a sensible (hard) cutoff to distinguish between reliable and unreliable predictions."}} + %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Confidence", data: {toggle:"popover", placement:"left", html:"true", content:"Indicates the applicability domain of a model. Predictions with a high confidence can be expected to be more reliable than predictions with low confidence. Confidence values may take any value between 0 and 1. For most models confidence > 0.025 is a sensible (hard) cutoff to distinguish between reliable and unreliable predictions."}} %p /TODO add tooltip for significant ftagments and descriptors - if @model_type[count] =~ /classification/i && (p.data_entries[0][1] != nil && p.data_entries[0][1] != 0.0) / Significant fragments: - %a.btn.btn-primary.btn-sm{:id=>"linkSigFragments", :href => to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[count]}/#{CGI.escape(@compound.uri)}/fingerprints"), data: { toggle: "modal", target:"#detailsTop"}} Significant fragments + %a.btn.btn-default.btn-sm{:id=>"linkSigFragments", :href => "#detailsTop", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[count]}/#{CGI.escape(@compound.uri)}/fingerprints")}} Significant fragments - if @model_type[count] =~ /regression/i && (p.data_entries[0][1] != nil && p.data_entries[0][1] != 0.0) / Descriptors - %a.btn.btn-primary.btn-sm{:id=>"linkDescriptors", :href => to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[count]}/#{CGI.escape(@compound.uri)}/fingerprints"), data: { toggle: "modal", target:"#detailsTop"}} Descriptors + %a.btn.btn-default.btn-sm{:id=>"linkDescriptors", :href => "#detailsTop", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[count]}/#{CGI.escape(@compound.uri)}/fingerprints")}} Descriptors %p - if c != '' - %a.btn.btn-warning.btn-sm{:href=> "#tabs", :id=>"link#{count}"} + %a.btn.btn-default.btn-sm{:href=> "#tabs", :id=>"link#{count}"} Neighbors :javascript $("a#link#{count}").click(function () { $(".results").show(); - document.getElementById('tabs').focus(); - $("#tabs").tabs({ active: "#{count}" }); + //document.getElementById('tabs').focus(); + $('#neighborTabs a[href="#results_#{count+1}"]').tab('show'); + //$("#tabs").tabs({ active: "#{count}" }); }); %p - count+=1 @@ -103,6 +104,7 @@ / always show the neighbors table, message is given there = haml :neighbors, :layout => false, :model_type => @model_type -%div.modal.fade{:id=>"detailsTop", :role=>"dialog"} - %div.modal-dialog.modal-lg - %div.modal-content + %div.modal.fade{:id=>"detailsTop", :role=>"dialog"} + %div.modal-dialog.modal-lg + %div.modal-content + diff --git a/views/significant_fragments.haml b/views/significant_fragments.haml index e441a9a..bd3598d 100644 --- a/views/significant_fragments.haml +++ b/views/significant_fragments.haml @@ -3,7 +3,7 @@ - if @type =~ /classification/i %div.row %div.col-md-4 - %h2{:style=>"margin-left:8px;"} + %h3{:style=>"margin-left:8px;"} Significant fragments: %img{:src=>"#{@compound.uri}/image", :alt=>"#{@compound.smiles}", :title=>"#{@compound.smiles}", :width=>"300px", :heigth=>"300px"} - if !@significant_fragments.empty? @@ -38,15 +38,15 @@ - if fragments[0] == @value_map.index("active") %tr %td - %img{:src => "http://smartsview.de/smartsview/auto/png/1/both/#{CGI.escape(fragments[1])}", :class => "smarts"} + -#%img{:src => "http://smartsview.de/smartsview/auto/png/1/both/#{CGI.escape(fragments[1])}", :class => "smarts"} = fragments[1] %td = fragments[2] - + %br - if @type =~ /regression/i %div.row %div.col-md-4 - %h2 + %h3 Descriptors: %img{:src=>"#{@compound.uri}/image", :alt=>"#{@compound.smiles}", :title=>"#{@compound.smiles}", :width=>"300px", :heigth=>"300px"} - if !@significant_fragments.empty? @@ -63,4 +63,4 @@ = fragments[0] %td = fragments[1][0].round(3) - + %br |