summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--application.rb143
-rw-r--r--helper.rb5
-rw-r--r--model.rb12
-rw-r--r--public/external.gifbin0 -> 212 bytes
-rw-r--r--public/hamster_carcinogenicity.csv1
-rw-r--r--public/hamster_carcinogenicity.xlsbin57856 -> 11776 bytes
-rwxr-xr-xpublic/javascripts/toxcreate.js66
-rw-r--r--public/progressbar/progressbar.css23
-rw-r--r--views/ambit.haml15
-rw-r--r--views/compound_image.haml1
-rw-r--r--views/create.haml12
-rw-r--r--views/echa.haml13
-rw-r--r--views/feature.haml26
-rw-r--r--views/feature_table.haml4
-rw-r--r--views/help.haml8
-rw-r--r--views/layout.haml10
-rw-r--r--views/lazar.haml106
-rw-r--r--views/lazar_algorithm.haml4
-rw-r--r--views/lazar_description.haml4
-rw-r--r--views/login.haml26
-rw-r--r--views/model.haml25
-rw-r--r--views/model_name.haml2
-rw-r--r--views/model_name_edit.haml7
-rw-r--r--views/models.haml8
-rw-r--r--views/predict.haml13
-rw-r--r--views/regression_validation.haml6
-rw-r--r--views/significant_fragments.haml2
-rw-r--r--views/style.sass8
-rw-r--r--views/unit.haml2
29 files changed, 327 insertions, 225 deletions
diff --git a/application.rb b/application.rb
index 7bf1059..60d50cd 100644
--- a/application.rb
+++ b/application.rb
@@ -1,7 +1,7 @@
['rubygems', "haml", "sass", "rack-flash"].each do |lib|
require lib
end
-gem "opentox-ruby", "~> 1"
+gem "opentox-ruby", "~> 2"
require 'opentox-ruby'
gem 'sinatra-static-assets'
require 'sinatra/static_assets'
@@ -27,7 +27,7 @@ helpers do
private
def delete_model(model, subjectid=nil)
task = OpenTox::Task.create("Deleting model: #{model.uri}",url_for("/delete",:full)) do |task|
- begin RestClient.put(File.join(model.task_uri, 'Cancelled'),subjectid) if model.task_uri rescue LOGGER.warn "Cannot cancel task #{model.task_uri}" end
+ begin OpenTox::RestClientWrapper.put(File.join(model.task_uri, "Cancelled"), "Cancelled",{:subjectid => subjectid}) if model.task_uri rescue LOGGER.warn "Cannot cancel task #{model.task_uri}" end
task.progress(15)
delete_dependent(model.uri, subjectid) if model.uri
task.progress(30)
@@ -60,7 +60,7 @@ helpers do
end
before do
- if !logged_in and !( env['REQUEST_URI'] =~ /\/login$/ and env['REQUEST_METHOD'] == "POST" ) #or !AA_SERVER
+ if !logged_in and !( env['REQUEST_URI'] =~ /\/login$/ and env['REQUEST_METHOD'] == "POST" ) or !AA_SERVER
login("guest","guest")
end
end
@@ -179,9 +179,30 @@ get %r{/compound/(.*)} do |inchi|
OpenTox::Compound.from_inchi(inchi).to_names.join(', ')
end
+get '/echa' do
+ @endpoints = OpenTox::Ontology::Echa.endpoints
+ haml :echa
+end
+
+post '/ambit' do
+ session[:echa] = params[:endpoint]
+ @datasets = OpenTox::Ontology::Echa.datasets(params[:endpoint])
+ haml :ambit
+end
+
+post '/feature' do
+ session[:dataset] = params[:dataset]
+ @features = []
+ OpenTox::Dataset.new(params[:dataset]).load_features.each do |uri,metadata|
+ @features << OpenTox::Feature.find(uri, @subjectid) if metadata[OWL.sameAs].match(/#{session[:echa]}/)
+ end
+ haml :feature
+end
+
post '/models' do # create a new model
- unless params[:file] and params[:file][:tempfile] #params[:endpoint] and
- flash[:notice] = "Please upload a Excel or CSV file."
+
+ unless (params[:dataset] and params[:prediction_feature]) or (params[:file] and params[:file][:tempfile]) #params[:endpoint] and
+ flash[:notice] = "Please upload a Excel or CSV file or select an AMBIT dataset."
redirect url_for('/create')
end
@@ -190,75 +211,93 @@ post '/models' do # create a new model
flash[:notice] = "Please login to create a new model."
redirect url_for('/create')
end
+
subjectid = session[:subjectid] ? session[:subjectid] : nil
- @model = ToxCreateModel.create(:name => params[:file][:filename].sub(/\..*$/,""), :subjectid => subjectid)
+
+ if params[:dataset] and params[:prediction_feature]
+ @dataset = OpenTox::Dataset.new(params[:dataset],subjectid)
+ name = @dataset.load_metadata[DC.title]
+ @prediction_feature = OpenTox::Feature.find params[:prediction_feature], subjectid
+ @dataset.load_compounds
+ elsif params[:file][:filename]
+ name = params[:file][:filename].sub(/\..*$/,"")
+ end
+
+ @model = ToxCreateModel.create(:name => name, :subjectid => subjectid)
@model.update :web_uri => url_for("/model/#{@model.id}", :full), :warnings => ""
task = OpenTox::Task.create("Uploading dataset and creating lazar model",url_for("/models",:full)) do |task|
task.progress(5)
@model.update :status => "Uploading and saving dataset", :task_uri => task.uri
- begin
- @dataset = OpenTox::Dataset.create(nil, subjectid)
- # check format by extension - not all browsers provide correct content-type])
- case File.extname(params[:file][:filename])
- when ".csv"
- csv = params[:file][:tempfile].read
- @dataset.load_csv(csv, subjectid)
- when ".xls", ".xlsx"
- excel_file = params[:file][:tempfile].path + File.extname(params[:file][:filename])
- File.rename(params[:file][:tempfile].path, excel_file) # add extension, spreadsheet does not read files without extensions
- @dataset.load_spreadsheet(Excel.new excel_file, subjectid)
+
+ unless params[:dataset] and params[:prediction_feature]
+ begin
+ @dataset = OpenTox::Dataset.create(nil, subjectid)
+ # check format by extension - not all browsers provide correct content-type])
+ case File.extname(params[:file][:filename])
+ when ".csv"
+ csv = params[:file][:tempfile].read
+ @dataset.load_csv(csv, subjectid)
+ when ".xls", ".xlsx"
+ excel_file = params[:file][:tempfile].path + File.extname(params[:file][:filename])
+ File.rename(params[:file][:tempfile].path, excel_file) # add extension, spreadsheet does not read files without extensions
+ @dataset.load_spreadsheet(Excel.new excel_file, subjectid)
+ if @dataset.metadata[OT.Errors]
+ error "Incorrect file format. Please follow the instructions for #{link_to "Excel", "/help"} or #{link_to "CSV", "/help"} formats."
+ end
+ else
+ error "#{params[:file][:filename]} has a unsupported file type."
+ end
+ @dataset.save(subjectid)
+ rescue => e
+ error "Dataset creation failed with #{e.message}"
+ end
+ if @dataset.features.keys.size != 1
+ error "More than one feature in dataset #{params[:file][:filename]}. Please delete irrelvant columns and try again."
else
- error "#{params[:file][:filename]} has a unsupported file type."
+ @prediction_feature = OpenTox::Feature.find(@dataset.features.keys.first,subjectid)
end
- rescue => e
- error "Dataset creation failed with #{e.message}"
end
- @dataset.save(subjectid)
+
task.progress(10)
if @dataset.compounds.size < 10
- error "Too few compounds to create a prediction model. Did you provide compounds in SMILES format and classification activities as described in the #{link_to "instructions", "/excel_format"}? As a rule of thumb you will need at least 100 training compounds for nongeneric datasets. A lower number could be sufficient for congeneric datasets."
- end
- if @dataset.features.keys.size != 1
- error "More than one feature in dataset #{params[:file][:filename]}. Please delete irrelvant columns and try again."
- end
- if @dataset.metadata[OT.Errors]
- error "Incorrect file format. Please follow the instructions for #{link_to "Excel", "/excel_format"} or #{link_to "CSV", "/csv_format"} formats."
+ error "Too few compounds to create a prediction model. Did you provide compounds in SMILES format and classification activities as described in the #{link_to "instructions", "/help"}? As a rule of thumb you will need at least 100 training compounds for nongeneric datasets. A lower number could be sufficient for congeneric datasets."
end
@model.update :training_dataset => @dataset.uri, :nr_compounds => @dataset.compounds.size, :status => "Creating prediction model"
- @model.update :warnings => @dataset.metadata[OT.Warnings] unless @dataset.metadata[OT.Warnings].empty?
+ @model.update :warnings => @dataset.metadata[OT.Warnings] unless @dataset.metadata[OT.Warnings] and @dataset.metadata[OT.Warnings].empty?
task.progress(15)
begin
- lazar = OpenTox::Model::Lazar.create(:dataset_uri => @dataset.uri, :subjectid => subjectid)
+ lazar = OpenTox::Model::Lazar.create(:dataset_uri => @dataset.uri, :prediction_feature => @prediction_feature.uri, :subjectid => subjectid)
rescue => e
- error "Model creation failed with '#{e.message}'. Please check if the input file is in a valid #{link_to "Excel", "/excel_format"} or #{link_to "CSV", "/csv_format"} format."
+ error "Model creation failed with '#{e.message}'."# Please check if the input file is in a valid #{link_to "Excel", "/help"} or #{link_to "CSV", "/help"} format."
end
task.progress(25)
+=begin
type = "unknown"
- case lazar.metadata[OT.isA]
- when /Classification/
+ if lazar.metadata[RDF.type].grep(/Classification/)
type = "classification"
- when /Regression/
+ elsif lazar.metadata[RDF.type].grep(/Regression/)
type = "regression"
end
- @model.update :type => type, :feature_dataset => lazar.metadata[OT.featureDataset], :uri => lazar.uri
+=end
+ @model.update :type => @prediction_feature.feature_type, :feature_dataset => lazar.metadata[OT.featureDataset], :uri => lazar.uri
- unless url_for("",:full).match(/localhost/)
+ if CONFIG[:services]["opentox-validation"]
@model.update :status => "Validating model"
begin
- validation = OpenTox::Crossvalidation.create(
- {:algorithm_uri => lazar.metadata[OT.algorithm],
- :dataset_uri => lazar.parameter("dataset_uri"),
- :subjectid => subjectid,
- :prediction_feature => lazar.parameter("prediction_feature"),
- :algorithm_params => "feature_generation_uri=#{lazar.parameter("feature_generation_uri")}"},
- nil, OpenTox::SubTask.new(task,25,80))
+ validation = OpenTox::Crossvalidation.create( {
+ :algorithm_uri => lazar.metadata[OT.algorithm],
+ :dataset_uri => lazar.parameter("dataset_uri"),
+ :subjectid => subjectid,
+ :prediction_feature => lazar.parameter("prediction_feature"),
+ :algorithm_params => "feature_generation_uri=#{lazar.parameter("feature_generation_uri")}" },
+ nil, OpenTox::SubTask.new(task,25,80))
+
@model.update(:validation_uri => validation.uri)
LOGGER.debug "Validation URI: #{@model.validation_uri}"
# create summary
validation.summary(subjectid).each do |k,v|
- #LOGGER.debug "mr ::: k: #{k.inspect} - v: #{v.inspect}"
begin
eval "@model.update :#{k.to_s} => v" if v
rescue
@@ -278,17 +317,13 @@ post '/models' do # create a new model
@model.update :warnings => @model.warnings + "\nModel validation failed with #{e.message}.", :status => "Error", :error_messages => e.message
end
+ else
+ @model.update(:status => "Completed") #, :warnings => @model.warnings + "\nValidation service cannot be accessed from localhost.")
+ task.progress(100)
end
-
-
- #@model.warnings += "<p>Incorrect Smiles structures (ignored):</p>" + parser.smiles_errors.join("<br/>") unless parser.smiles_errors.empty?
- #@model.warnings += "<p>Irregular activities (ignored):</p>" + parser.activity_errors.join("<br/>") unless parser.activity_errors.empty?
- #duplicate_warnings = ''
- #parser.duplicates.each {|inchi,lines| duplicate_warnings += "<p>#{lines.join('<br/>')}</p>" if lines.size > 1 }
- #@model.warnings += "<p>Duplicated structures (all structures/activities used for model building, please make sure, that the results were obtained from <em>independent</em> experiments):</p>" + duplicate_warnings unless duplicate_warnings.empty?
lazar.uri
end
- @model.update(:task_uri => task.uri)
+ @model.update :task_uri => task.uri
flash[:notice] = "Model creation and validation started - this may last up to several hours depending on the number and size of the training compounds."
redirect url_for('/models')
@@ -325,7 +360,7 @@ post '/predict/?' do # post chemical name to model
}
else
predicted_feature = prediction_dataset.metadata[OT.dependentVariables]
- prediction = OpenTox::Feature.find(predicted_feature)
+ prediction = OpenTox::Feature.find(predicted_feature, subjectid)
if prediction.metadata[OT.error]
@predictions << {
:title => model.name,
@@ -351,7 +386,7 @@ post "/lazar/?" do # get detailed prediction
@page = params[:page].to_i if params[:page]
@model_uri = params[:model_uri]
lazar = OpenTox::Model::Lazar.new @model_uri
- prediction_dataset_uri = lazar.run(:compound_uri => params[:compound_uri], :subjectid => params[:subjectid])
+ prediction_dataset_uri = lazar.run(:compound_uri => params[:compound_uri], :subjectid => session[:subjectid])
@prediction = OpenTox::LazarPrediction.find(prediction_dataset_uri, session[:subjectid])
@compound = OpenTox::Compound.new(params[:compound_uri])
haml :lazar
diff --git a/helper.rb b/helper.rb
index 7d7a856..2fe8785 100644
--- a/helper.rb
+++ b/helper.rb
@@ -3,7 +3,7 @@ helpers do
def login(username, password)
logout
session[:subjectid] = OpenTox::Authorization.authenticate(username, password)
- LOGGER.debug "ToxCreate login user #{username} with subjectid: " + session[:subjectid].to_s
+ #LOGGER.debug "ToxCreate login user #{username} with subjectid: " + session[:subjectid].to_s
if session[:subjectid] != nil
session[:username] = username
return true
@@ -53,8 +53,7 @@ helpers do
def sort(descriptors)
features = {:activating => [], :deactivating => []}
-
- descriptors.each { |d| LOGGER.debug d.inspect; features[d[OT.effect].to_sym] << {:smarts => d[OT.smarts],:p_value => d[OT.pValue]} }
+ descriptors.each { |d| features[d[OT.effect].to_sym] << {:smarts => d[OT.smarts],:p_value => d[OT.pValue]} }
features
end
diff --git a/model.rb b/model.rb
index 5332629..5b1f4f5 100644
--- a/model.rb
+++ b/model.rb
@@ -1,13 +1,18 @@
require 'ohm'
+require 'ohm/contrib'
class ToxCreateModel < Ohm::Model
+ include Ohm::Callbacks
+ include Ohm::Typecast
+ include Ohm::Timestamping
+
attribute :name
attribute :warnings
attribute :error_messages
attribute :type
attribute :status
- attribute :created_at
+ attribute :created_at, Date
attribute :task_uri
attribute :uri
@@ -42,7 +47,7 @@ class ToxCreateModel < Ohm::Model
attr_accessor :subjectid
@subjectid = nil
- #after :save, :check_policy
+ after :save, :check_policy
def validation_status
begin
@@ -73,5 +78,4 @@ class ToxCreateModel < Ohm::Model
OpenTox::Authorization.check_policy(web_uri, subjectid)
end
-end
-
+end \ No newline at end of file
diff --git a/public/external.gif b/public/external.gif
new file mode 100644
index 0000000..6114959
--- /dev/null
+++ b/public/external.gif
Binary files differ
diff --git a/public/hamster_carcinogenicity.csv b/public/hamster_carcinogenicity.csv
index e9ca269..f087233 100644
--- a/public/hamster_carcinogenicity.csv
+++ b/public/hamster_carcinogenicity.csv
@@ -1,3 +1,4 @@
+SMILES, hamster_carcinogenicity
CC=O,1
C12C3=C(C=CC=C3)CC1=CC(=CC=2)NC(C)=O,1
O=C(N)\C(C2=CC=CO2)=C/C1=CC=C([N+]([O-])=O)O1,1
diff --git a/public/hamster_carcinogenicity.xls b/public/hamster_carcinogenicity.xls
index 0015ac6..95e8fc4 100644
--- a/public/hamster_carcinogenicity.xls
+++ b/public/hamster_carcinogenicity.xls
Binary files differ
diff --git a/public/javascripts/toxcreate.js b/public/javascripts/toxcreate.js
index 94d944d..d9946c4 100755
--- a/public/javascripts/toxcreate.js
+++ b/public/javascripts/toxcreate.js
@@ -86,8 +86,6 @@ $(function() {
});
return id;
};
-
-
loadModel = function(id, view) {
if(id == "") return -1;
@@ -111,30 +109,9 @@ $(function() {
return false;
};
- checkValidation = function() {
- var reload_id = "";
- $("input.model_validation_report").each(function(){
- if(!$(this).val().match(/Completed|Error/)) {
- reload_id = this.id.replace("model_validation_report_","");
- if(/^\d+$/.test(reload_id)) loadModel(reload_id, 'validation');
- };
- });
-//<<<<<<< HEAD
- //var validationCheck = setTimeout('checkValidation()',15000);
- //var validationCheck = setTimeout('checkValidation()',5000);
-//=======
- $("input.model_validation_qmrf").each(function(){
- if(!$(this).val().match(/Completed|Error/)) {
- reload_id = this.id.replace("model_validation_qmrf_","");
- if(/^\d+$/.test(reload_id)) loadModel(reload_id, 'model');
- };
- });
- var validationCheck = setTimeout('checkValidation()',15000);
-//>>>>>>> d1ad229730f6e6043fe6e7a150e05ffa41e3cec2
- }
});
-jQuery.fn.editModel = function(type, options) {
+jQuery.fn.editModel = function(options) {
var defaults = {
method: 'get',
action: this.attr('href'),
@@ -161,7 +138,34 @@ jQuery.fn.editModel = function(type, options) {
});
};
-jQuery.fn.saveModel = function(type, options) {
+jQuery.fn.cancelEdit = function(options) {
+ var defaults = {
+ method: 'get',
+ action: 'model/' + options.id + '/name?mode=show',
+ trigger_on: 'click'
+ };
+ var opts = $.extend(defaults, options);
+
+ this.bind(opts.trigger_on, function() {
+ $.ajax({
+ type: opts.method,
+ url: opts.action,
+ dataType: 'html',
+ data: {
+ '_method': 'get'
+ },
+ success: function(data) {
+ $("div#model_" + opts.id + "_name").html(data);
+ },
+ error: function(data) {
+ alert("model cancel error!");
+ }
+ });
+ return false;
+ });
+};
+
+jQuery.fn.saveModel = function(options) {
var defaults = {
method: 'put',
action: 'model/' + options.id,
@@ -222,3 +226,15 @@ jQuery.fn.deleteModel = function(type, options) {
return false;
});
};
+
+$(document).ready(function() {
+ $('A[rel="external"]').each(function() {
+ $(this).attr('alt', 'Link opens in new window.');
+ $(this).attr('title', 'Link opens in new window.');
+ });
+ $('A[rel="external"]').click(function() {
+ window.open($(this).attr('href'));
+ return false;
+ });
+});
+
diff --git a/public/progressbar/progressbar.css b/public/progressbar/progressbar.css
index f3b4131..d19839d 100644
--- a/public/progressbar/progressbar.css
+++ b/public/progressbar/progressbar.css
@@ -11,9 +11,7 @@
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
-/*
-.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
-*/
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px, 1px, 1px, 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
@@ -21,9 +19,8 @@
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
-/*
-.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
-*/
+
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; }
/* Interaction Cues
----------------------------------*/
@@ -84,10 +81,8 @@
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
-/*
-.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
-.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
-*/
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { background-image: none; }
/* Icons
----------------------------------*/
@@ -283,6 +278,10 @@
/* Misc visuals
----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;}/*
/* Corner radius */
/*
.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; }
@@ -300,11 +299,7 @@
/*
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
-*/
-.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; }
-.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; }
-/*
* jQuery UI Progressbar 1.8.9
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
diff --git a/views/ambit.haml b/views/ambit.haml
new file mode 100644
index 0000000..685c0dc
--- /dev/null
+++ b/views/ambit.haml
@@ -0,0 +1,15 @@
+%b Select:
+= session[:echa].split('#').last
+= "-&gt;"
+%b Dataset
+%em= "-&gt; Prediction Feature"
+
+%form{ :action => url_for('/feature'), :method => "post" }
+ %input{:type => 'hidden', :name => 'subjectid', :id => 'subjectid', :value => session[:subjectid]}
+
+ - @datasets.each do |dataset|
+ %br
+ %input{:type=>'radio', :name => "dataset", :value => dataset} #{OpenTox::Dataset.new(dataset).load_metadata[DC.title]}
+
+ %p
+ %input{:type => 'submit', :value => 'Next'}
diff --git a/views/compound_image.haml b/views/compound_image.haml
index 18944dc..25e0dbf 100644
--- a/views/compound_image.haml
+++ b/views/compound_image.haml
@@ -1,2 +1 @@
%img{:src => compound.matching_smarts_image_uri(features[:activating].collect{|f| f[:smarts]},features[:deactivating].collect{|f| f[:smarts]}), :alt => compound.to_smiles}
-
diff --git a/views/create.haml b/views/create.haml
index 5450ddf..0b299f5 100644
--- a/views/create.haml
+++ b/views/create.haml
@@ -17,18 +17,24 @@
= link_to "instructions for creating training datasets", '/help'
before submitting.
+
%form{ :action => url_for('/models'), :method => "post", :enctype => "multipart/form-data" }
%input{:type => 'hidden', :name => 'subjectid', :id => 'subjectid', :value => session[:subjectid]}
%fieldset
%label{:for => 'file'}
- Select training data in
+ Upload training data in
= link_to "Excel", '/help'
or
= link_to "CSV", '/help'
format:
%input{:type => 'file', :name => 'file', :id => 'file', :size => '41'}
%input{ :type => "submit", :value => "Create model"}
- = link_to "Cancel", '/create'
+ =# link_to "Cancel", '/create'
+
+ %p
+ or
+ %a{:href => "echa"} Select a AMBIT dataset
+ (experimental)
-# explanations
= haml :lazar_description, :layout => false
@@ -45,5 +51,5 @@
and your models can be modified or deleted by other guests. Please
= link_to "log in", "/login"
with your
- %a{:href => "www.opentox.org"} OpenTox
+ %a{:href => "http://www.opentox.org", :rel => "external"} OpenTox
account to control your model permissions.
diff --git a/views/echa.haml b/views/echa.haml
new file mode 100644
index 0000000..1cabfa0
--- /dev/null
+++ b/views/echa.haml
@@ -0,0 +1,13 @@
+%b Select:
+%b ECHA Endpoint
+%em= "-&gt; Dataset -&gt; Prediction Feature"
+
+%form{ :action => url_for('/ambit'), :method => "post" }
+ %input{:type => 'hidden', :name => 'subjectid', :id => 'subjectid', :value => session[:subjectid]}
+
+ - @endpoints.each do |endpoint|
+ %br
+ %input{:type=>'radio', :name => "endpoint", :value => endpoint} #{endpoint.split('#').last}
+
+ %p
+ %input{:type => 'submit', :value => "Next"}
diff --git a/views/feature.haml b/views/feature.haml
new file mode 100644
index 0000000..c5b8293
--- /dev/null
+++ b/views/feature.haml
@@ -0,0 +1,26 @@
+%b Select:
+= session[:echa].split('#').last
+= "-&gt;"
+= OpenTox::Dataset.new(session[:dataset]).load_metadata[DC.title]
+= "-&gt;"
+%b Prediction feature
+
+%form{ :action => url_for('/models'), :method => "post" }
+
+ %input{:type => 'hidden', :name => 'subjectid', :id => 'subjectid', :value => session[:subjectid]}
+ %input{:type => 'hidden', :name => 'dataset', :id => 'dataset', :value => session[:dataset]}
+
+ - @features.each do |feature|
+ -# type = "unknown"
+ -# if feature.metadata[RDF.type].include?(OT.NominalFeature)
+ - type = "classification"
+ -# elsif feature.metadata[RDF.type].include?(OT.NumericFeature)
+ - type = "regression"
+
+ %br
+ %input{:type=>'radio', :name => "prediction_feature", :value => feature.uri} #{feature.metadata[DC.title]} (#{feature.feature_type})
+ %br
+ =# feature.inspect
+
+ %p
+ %input{:type => 'submit', :value => "Create model"}
diff --git a/views/feature_table.haml b/views/feature_table.haml
index 4fa927c..a8a153f 100644
--- a/views/feature_table.haml
+++ b/views/feature_table.haml
@@ -4,7 +4,7 @@
%th
activating
(
- %a{:href => "http://www.daylight.com/dayhtml/doc/theory/theory.smarts.html"} SMARTS
+ %a{:href => "http://www.daylight.com/dayhtml/doc/theory/theory.smarts.html", :rel => "external"} SMARTS
)
%th p value
- if features[:activating]
@@ -17,7 +17,7 @@
%th
deactivating
(
- %a{:href => "http://www.daylight.com/dayhtml/doc/theory/theory.smarts.html"} SMARTS
+ %a{:href => "http://www.daylight.com/dayhtml/doc/theory/theory.smarts.html", :rel => "external"} SMARTS
)
%th p value
- if features[:deactivating]
diff --git a/views/help.haml b/views/help.haml
index da6495e..3d39641 100644
--- a/views/help.haml
+++ b/views/help.haml
@@ -1,7 +1,7 @@
= link_to "Back to model creation", '/create'
%p
Input files have two columns. Enter in the first column the chemical structure in
- %a{:href => "http://en.wikipedia.org/wiki/Simplified_molecular_input_line_entry_specification"} SMILES
+ %a{:href => "http://en.wikipedia.org/wiki/Simplified_molecular_input_line_entry_specification", :rel => "external"} SMILES
format, in the second column the toxic activity. The first line contains a description of the columns and is ignored.
%dl
%dt Classification datasets
@@ -12,15 +12,15 @@
%ul
%li
use
- %a{:href => "http://en.wikipedia.org/wiki/Molar_(concentration)"} molar
+ %a{:href => "http://en.wikipedia.org/wiki/Molar_(concentration)", :rel => "external"} molar
units
%li enter non-logarithmic values (logarithms are taken internally)
%li avoid 0 activities (will be ignored)
%p
Input files are accepted in
- %a{:href => "http://en.wikipedia.org/wiki/Microsoft_Excel"} Excel
+ %a{:href => "http://en.wikipedia.org/wiki/Microsoft_Excel", :rel => "external"} Excel
and
- %a{:href => "http://en.wikipedia.org/wiki/Comma-separated_values"} CSV
+ %a{:href => "http://en.wikipedia.org/wiki/Comma-separated_values", :rel => "external"} CSV
formats.
%h3 Excel example
diff --git a/views/layout.haml b/views/layout.haml
index cdabe43..174db9f 100644
--- a/views/layout.haml
+++ b/views/layout.haml
@@ -17,7 +17,7 @@
Create and evaluate models to predict toxicity
.index
%ul
- %li{:class => ("selected" if /\/create/ =~ request.path )}
+ %li{:class => ("selected" if /\/create|echa|ambit|feature/ =~ request.path )}
= link_to "Create", "/create"
%li{:class => ("selected" if /models/ =~ request.path )}
= link_to "Inspect", "/models"
@@ -37,7 +37,7 @@
- if `hostname`.match(/ot-test/)
.notice
This service is for testing purposes only - once a week all models will be deleted. Please send bug reports and feature requests to our
- %a{:href => 'http://github.com/opentox/toxcreate/issues'} issue tracker.
+ %a{:href => 'http://github.com/opentox/toxcreate/issues', :rel => "external"} issue tracker.
- if flash[:notice]
%p
@@ -48,6 +48,6 @@
.footer
&copy;
- %a{:href => 'http://www.in-silico.ch'} in silico toxicology
- 2009-2010, powered by
- %a{:href => 'http://www.opentox.org'} <span style="color:#5D308A;font-family:arial,sans-serif,helvetica;letter-spacing:-1px;">Open</span><span style="color:#000;font-family:arial,sans-serif,helvetica;font-weight:bold;letter-spacing:-1px;position:relative;">Tox</span>
+ %a{:href => 'http://www.in-silico.ch', :rel => "external"} in silico toxicology
+ 2009-2011, powered by
+ %a{:href => 'http://www.opentox.org', :rel => "external"} <span style="color:#5D308A;font-family:arial,sans-serif,helvetica;letter-spacing:-1px;">Open</span><span style="color:#000;font-family:arial,sans-serif,helvetica;font-weight:bold;letter-spacing:-1px;">Tox</span>
diff --git a/views/lazar.haml b/views/lazar.haml
index 3de7400..3f1d030 100644
--- a/views/lazar.haml
+++ b/views/lazar.haml
@@ -1,59 +1,47 @@
-%p= link_to "New prediction", "/predict"
-.lazar-predictions
-
- -# explanations
- = haml :lazar_algorithm, :layout => false
- = haml :confidence, :layout => false
- = haml :similarity, :layout => false
- = haml :significant_fragments, :layout => false
- = haml :training_data, :layout => false
-
- %a{:name => "prediction"}
- %table
- %thead
- %tr
- %th= @prediction.title
- %th= toggle_link("#lazar_algorithm","Prediction")
- %th= toggle_link("#confidence","Confidence")
- %th Supporting information
-
- %tr
- -# %td
- %img{:src => @compound.to_image_uri, :alt => @compound.to_smiles}
- %td.image= compound_image(@compound,@prediction.descriptors(@compound))
- %td= activity_markup(@prediction.value(@compound))
- %td= sprintf('%.03g', @prediction.confidence(@compound))
- -#%td= @prediction.confidence(@compound)
- %td
- %ul
- %li
- %a{:href => "#prediction", :id => "show_names"} Names and synonyms
- :javascript
- $("a#show_names").click(function () {
- $("#compound_names").load("#{File.join("/compound",@compound.inchi)}");
- $("tr#names").toggle();
- });
- %li= toggle_link("#fragments","Significant fragments")
- -# This does not work, ask nina/vedrin
- -# %li
- %a{:href => "http://ambit.uni-plovdiv.bg:8080/ambit2/query/structure/?search=#{@compound.smiles}"} Ambit data
- -# %li
- %a{:href => "http://www.ncbi.nlm.nih.gov/sites/entrez?cmd=PureSearch&db=pccompound&term=#{URI.encode('"'+@compound.inchi+'"[InChI]')}"} PubChem data
- (external)
- -# %li
- %a{:href => "http://chem.sis.nlm.nih.gov/chemidplus/direct.jsp?result=advanced&inchi=#{URI.encode @compound.inchi}"} ToxNet data
- -#http://chem.sis.nlm.nih.gov/chemidplus/direct.jsp?result=advanced&regno=000143157
-
- %tr#names{ :style => "display: none;" }
- %td{:colspan => '4'}
- %a{:name => 'names'}
- = hide_link('#names')
- #compound_names
- %tr#fragments{ :style => "display: none;" }
- %td{:colspan => '4'}
- = hide_link('#fragments')
- = haml :feature_table, :locals => {:features => sort(@prediction.descriptors(@compound))}, :layout => false
-
- %tbody#neighbors
- = haml :neighbors, :locals => {:neighbors => @prediction.neighbors(@compound), :page => @page}, :layout => false
-
+%p= link_to "New prediction", "/predict"
+.lazar-predictions
+
+ -# explanations
+ = haml :lazar_algorithm, :layout => false
+ = haml :confidence, :layout => false
+ = haml :similarity, :layout => false
+ = haml :significant_fragments, :layout => false
+ = haml :training_data, :layout => false
+
+ %a{:name => "prediction"}
+ %table
+ %thead
+ %tr
+ %th= @prediction.title
+ %th= toggle_link("#lazar_algorithm","Prediction")
+ %th= toggle_link("#confidence","Confidence")
+ %th Supporting information
+
+ %tr
+ %td.image= compound_image(@compound,@prediction.descriptors(@compound))
+ %td= activity_markup(@prediction.value(@compound))
+ %td= sprintf('%.03g', @prediction.confidence(@compound))
+ %td
+ %ul
+ %li
+ %a{:href => "#prediction", :id => "show_names"} Names and synonyms
+ :javascript
+ $("a#show_names").click(function () {
+ $("#compound_names").load("#{File.join("/compound",@compound.inchi)}");
+ $("tr#names").toggle();
+ });
+ %li= toggle_link("#fragments","Significant fragments")
+
+ %tr#names{ :style => "display: none;" }
+ %td{:colspan => '4'}
+ %a{:name => 'names'}
+ = hide_link('#names')
+ #compound_names
+ %tr#fragments{ :style => "display: none;" }
+ %td{:colspan => '4'}
+ = hide_link('#fragments')
+ = haml :feature_table, :locals => {:features => sort(@prediction.descriptors(@compound))}, :layout => false
+
+ %tbody#neighbors
+ = haml :neighbors, :locals => {:neighbors => @prediction.neighbors(@compound), :page => @page}, :layout => false
+
diff --git a/views/lazar_algorithm.haml b/views/lazar_algorithm.haml
index b83de6b..85823b5 100644
--- a/views/lazar_algorithm.haml
+++ b/views/lazar_algorithm.haml
@@ -20,13 +20,13 @@
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.in-silico.de/articles/modi020905.pdf", :rel => "external"} 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.in-silico.de/articles/mh_tf.pdf", :rel => "external"} original publication
)
%p
diff --git a/views/lazar_description.haml b/views/lazar_description.haml
index d8e995d..3eee850 100644
--- a/views/lazar_description.haml
+++ b/views/lazar_description.haml
@@ -18,11 +18,11 @@
a majority vote (weighted by compound similarity) for
%em= toggle_link("#classification","classification")
(
- %a{:href => "http://www.in-silico.de/articles/modi020905.pdf"} original publication
+ %a{:href => "http://www.in-silico.de/articles/modi020905.pdf", :rel => "external"} original publication
)
%li
a local QSAR model based on neighbors for
%em= toggle_link("#regression","regression")
(
- %a{:href => "http://www.in-silico.de/articles/mh_tf.pdf"} original publication
+ %a{:href => "http://www.in-silico.de/articles/mh_tf.pdf", :rel => "external"} original publication
)
diff --git a/views/login.haml b/views/login.haml
index 6d15bb7..e944e77 100644
--- a/views/login.haml
+++ b/views/login.haml
@@ -7,15 +7,15 @@
and your models can be modified or deleted by other guests.
To control models permissions you can
log in with your
- %a{:href => "http://www.opentox.org"} OpenTox
- username/password below. If have no
- %a{:href => "http://www.opentox.org"} OpenTox
- account yet you can
- %a{:href => "http://www.opentox.org/join_form"} register here.
+ %a{:href => "http://www.opentox.org", :rel => "external"} OpenTox
+ username/password below. If you don't have an
+ %a{:href => "http://www.opentox.org", :rel => "external"} OpenTox
+ account yet you could
+ %a{:href => "http://www.opentox.org/join_form", :rel => "external"} register here.
- else
%p
Change
- %a{:href => "http://www.opentox.org"} OpenTox
+ %a{:href => "http://www.opentox.org", :rel => "external"} OpenTox
account:
-# if !logged_in()
@@ -33,15 +33,5 @@
%form{ :action => url_for('/login'), :method => "post" }
%input{:type => 'hidden', :name => 'username', :id => 'username', :value => "guest"}
%input{:type => 'hidden', :name => 'password', :id => 'password', :value => "guest"}
- %input{ :type => "submit", :value => "Login as guest"}
- -# else
- %form{ :action => url_for('/logout'), :method => "post" }
- -#%p
- You are logged in as:
- %b= session[:username]
- -# if LOGGER.level == Logger::DEBUG
- %br
- = session[:subjectid]
- %input{ :type => "submit", :value => "Switch user"}
- = link_to "Cancel", '/login'
-
+ %input{:type => "submit", :value => "Login as guest"}
+
diff --git a/views/model.haml b/views/model.haml
index 91d7016..b4b3c59 100644
--- a/views/model.haml
+++ b/views/model.haml
@@ -18,7 +18,7 @@
- if (task = OpenTox::Task.exist?(model.task_uri))
%input{:type => 'hidden', :id => "model_#{model.id}_task", :value => "#{model.task_uri}"}
- percentage_completed = task.metadata[OT.percentageCompleted].to_i
- - js = "$('#model_#{model.id}_progress').progressbar({ value: #{percentage_completed} })";
+ - js = "$('#model_#{model.id}_progress').progressbar({ value: #{percentage_completed} });"
:javascript
$(function() {
#{js}
@@ -28,15 +28,15 @@
//= haml :model_progress, :locals=>{:percentage_completed=>percentage_completed}, :layout => false
- if is_authorized(model.web_uri, "DELETE")
%a{:href => url_for("/model/#{model.id}"), :id => "delete_#{model.id}", :class => 'delete_link'}
- - if model.status == "Completed"
+ - if model.status =~ /Completed|Error|Cancelled/
(delete)
- else
(stop)
%span
%br
- -#%dt Started:
- -#%dd= model.created_at.strftime("%m/%d/%Y - %I:%M:%S%p")
+ %dt Started:
+ %dd= Time.parse(model.created_at.to_s).strftime("%m/%d/%Y - %I:%M:%S%p") if model.created_at
- if model.nr_compounds
%dt Training compounds:
%dd= model.nr_compounds
@@ -54,16 +54,19 @@
%dd= toggle_link("##{model.type}","#{model.type}")
%dt Descriptors:
%dd
- %a{:href => 'http://www.maunz.de/libfminer2-bbrc-doc/'} Fminer backbone refinement classes
+ %a{:href => 'http://www.maunz.de/libfminer2-bbrc-doc/', :rel => "external"} Fminer backbone refinement classes
- if model.training_dataset
%dt Training dataset:
%dd
- %a{:href => "#{model.training_dataset}.xls#{subjectstring}"} Excel sheet
- ,
- -#%a{:href => "#{model.training_dataset}.rdf"} RDF/XML
- -#%em (experts) ,
- %a{:href => "#{model.training_dataset}.yaml#{subjectstring}" } YAML
- %em (experts)
+ - if model.training_dataset.match(/ambit/i)
+ %a{:href => "#{model.training_dataset}#{subjectstring}", :rel => "external"} Ambit database
+ - else
+ %a{:href => "#{model.training_dataset}.xls#{subjectstring}"} Excel sheet
+ ,
+ -#%a{:href => "#{model.training_dataset}.rdf"} RDF/XML
+ -#%em (experts) ,
+ %a{:href => "#{model.training_dataset}.yaml#{subjectstring}" } YAML
+ %em (experts)
- if model.feature_dataset
%dt Feature dataset:
%dd
diff --git a/views/model_name.haml b/views/model_name.haml
index b1f6f10..91516ce 100644
--- a/views/model_name.haml
+++ b/views/model_name.haml
@@ -1,4 +1,4 @@
-- js = "$('#edit_#{model.id}').editModel('PUT', {id: '#{model.id}', mode: 'edit'});\n "
+- js = "$('#edit_#{model.id}').editModel({id: '#{model.id}', mode: 'edit'});\n "
:javascript
$(function() {
#{js}
diff --git a/views/model_name_edit.haml b/views/model_name_edit.haml
index aec59fc..d92c68a 100644
--- a/views/model_name_edit.haml
+++ b/views/model_name_edit.haml
@@ -1,5 +1,5 @@
-- js = "$('#cancel_#{model.id}').editModel('GET', {id: '#{model.id}', mode: 'show'});\n "
-- js = "$('#save_#{model.id}').saveModel('POST', {id: '#{model.id}', mode: 'show'});\n "
+- js = "$('#cancel_#{model.id}').cancelEdit({id: '#{model.id}', mode: 'show'});\n "
+- js += "$('#save_#{model.id}').saveModel({id: '#{model.id}', mode: 'show'});\n "
:javascript
$(function() {
#{js}
@@ -10,5 +10,4 @@
%input{:type => 'hidden', :name => 'subjectid', :id => 'subjectid', :value => session[:subjectid]}
%input{ :type => "submit", :value => "Save", :id => "save_#{model.id}", :class => "edit_button"}
%span{:class => "edit_button"}
- %a{:href => url_for("/model/#{model.id}/name?mode=show"), :id => "cancel_#{model.id}"} Cancel
-
+ %a{:href => "#", :id => "cancel_#{model.id}"} Cancel
diff --git a/views/models.haml b/views/models.haml
index 67c061c..6724807 100644
--- a/views/models.haml
+++ b/views/models.haml
@@ -6,18 +6,18 @@
setTimeout('checkStati("#{stati_to_check}", "#{subjectstring}")',5000);
}
var reload_validation = true;
- //if(reload_validation) setTimeout('checkValidation()',15000);
});
-# %p Get an overview about ToxCreate models. This page is refreshed every 15 seconds to update the model status.
%p Get an overview about ToxCreate models. Parts of this page are refreshed every 5 seconds to update the model status.
-# explanations
-= haml :lazar_description, :layout => false
= haml :classification, :layout => false
+= haml :lazar_description, :layout => false
= haml :regression, :layout => false
= haml :similarity, :layout => false
= haml :significant_fragments, :layout => false
-- @models.each do |model|
- = haml :model, :locals=>{:model=>model,:subjectstring=>subjectstring}, :layout => false
+- if @models
+ - @models.each do |model|
+ = haml :model, :locals=>{:model=>model,:subjectstring=>subjectstring}, :layout => false
diff --git a/views/predict.haml b/views/predict.haml
index d8c34a2..ec667e6 100644
--- a/views/predict.haml
+++ b/views/predict.haml
@@ -18,18 +18,25 @@
%param{ :name => "options", :value => "polarnitro"}
Please enable Java and JavaScript in your browser to use the JME editor.
+ %jme_info
+ <span style="font-size:75%">&copy;
+ %a{:href => 'http://www.molinspiration.com/jme/index.html', :rel => "external"} JME Editor
+ courtesy of Peter Ertl, Novartis</span>
+ %br
%label{:for => 'identifier'} or enter a Name, InChI, Smiles, CAS, ...
%input{:type => 'text', :name => 'identifier', :id => 'identifier', :size => '60'}
+ %br
%fieldset
%legend
Choose one or more prediction models
+ %br
- @models.each do |model|
+ %input{:type => 'checkbox', :name => "selection[#{model.id}]", :value => true, :id => "model#{model.id}", :disabled => false}
%label{:for => "model#{model.id}"}
= model.name
- -#%input{:type => 'checkbox', :name => "selection[#{model.id}]", :value => true, :id => model.id, :disabled => !is_authorized(model.uri, "GET")}
- %input{:type => 'checkbox', :name => "selection[#{model.id}]", :value => true, :id => "model#{model.id}", :disabled => false}
+ -#%input{:type => 'checkbox', :name => "selection[#{model.id}]", :value => true, :id => model.id, :disabled => !is_authorized(model.uri, "GET")}
%br
-
+ %br
%input{:type => 'hidden', :name => 'subjectid', :id => 'subjectid', :value => session[:subjectid]}
%input{ :type => "submit", :value => "Predict", :onclick => "getsmiles();"}
= link_to 'Cancel', '/predict'
diff --git a/views/regression_validation.haml b/views/regression_validation.haml
index d5b3f6a..5b29d88 100644
--- a/views/regression_validation.haml
+++ b/views/regression_validation.haml
@@ -1,9 +1,9 @@
%dt
- %a{:href => "http://en.wikipedia.org/wiki/R-squared"} R-squared
+ %a{:href => "http://en.wikipedia.org/wiki/R-squared", :rel => "external"} R-squared
%dd= sprintf '%.03g', model.r_square.to_f
%dt
- %a{:href => "http://en.wikipedia.org/wiki/Root_mean_square_deviation"} Root Mean Square Error
+ %a{:href => "http://en.wikipedia.org/wiki/Root_mean_square_deviation", :rel => "external"} Root Mean Square Error
%dd= sprintf '%.03g', model.root_mean_squared_error.to_f
%dt
- %a{:href => "http://en.wikipedia.org/wiki/Mean_absolute_error"} Mean Absolute Error
+ %a{:href => "http://en.wikipedia.org/wiki/Mean_absolute_error", :rel => "external"} Mean Absolute Error
%dd= sprintf '%.03g', model.mean_absolute_error.to_f
diff --git a/views/significant_fragments.haml b/views/significant_fragments.haml
index 87cb113..bd39826 100644
--- a/views/significant_fragments.haml
+++ b/views/significant_fragments.haml
@@ -6,5 +6,5 @@
)
%dd
Substructures that occur (statistically significant) more frequently in active or inactive compounds. Substuctures can take any shape (without cycles) and are determined with the
- %a{:href => "http://www.maunz.de/libfminer2-bbrc-doc/"} fminer
+ %a{:href => "http://www.maunz.de/libfminer2-bbrc-doc/", :rel => "external"} fminer
algorithm.
diff --git a/views/style.sass b/views/style.sass
index db1f1bf..ffae6a5 100644
--- a/views/style.sass
+++ b/views/style.sass
@@ -18,6 +18,9 @@ body
color: $ot_purple
a:hover
color: black
+ a[rel="external"]
+ background: transparent url('../external.gif') center right no-repeat
+ padding-right: 15px
.headline
.logo
@@ -90,6 +93,7 @@ body
font-weight: bold
color: $fg_color
label
+ cursor: pointer
//width: 28em
//display: block
//float: left
@@ -127,7 +131,9 @@ body
padding: 0.5em
img
padding: 0
- height: 100%
+ //height: 100%
+ width: 150px
+ height: 150px
.lazar-predictions
clear: both
diff --git a/views/unit.haml b/views/unit.haml
index a352599..88433b5 100644
--- a/views/unit.haml
+++ b/views/unit.haml
@@ -6,5 +6,5 @@
)
%dd
Unit of measurement, e.g. mmol or mmol/kg-bodyweight. For optimal performance you should use
- %a{:href => "http://en.wikipedia.org/wiki/Molar_(concentration)"} molar
+ %a{:href => "http://en.wikipedia.org/wiki/Molar_(concentration)", :rel => "external"} molar
units.