summaryrefslogtreecommitdiff
path: root/reach_reports
diff options
context:
space:
mode:
authormguetlein <martin.guetlein@gmail.com>2010-08-11 10:58:59 +0200
committermguetlein <martin.guetlein@gmail.com>2010-08-11 10:58:59 +0200
commit566786bdd7e253880b7fe6c00cb40fbc46f771a2 (patch)
tree69cf68c7b479b8f99b9248d92ae91a4f7f24cd34 /reach_reports
parent148e4eaccf2e406586914150cf2f953fa5f12ece (diff)
move to wrapper 1.6.2, remove report-dir-check, initial commit of reach reporting stuff
Diffstat (limited to 'reach_reports')
-rw-r--r--reach_reports/reach_application.rb69
-rw-r--r--reach_reports/reach_persistance.rb47
-rw-r--r--reach_reports/reach_properties.rb158
-rw-r--r--reach_reports/reach_service.rb125
-rw-r--r--reach_reports/reach_test.rb62
-rw-r--r--reach_reports/reach_to_xml.rb60
6 files changed, 521 insertions, 0 deletions
diff --git a/reach_reports/reach_application.rb b/reach_reports/reach_application.rb
new file mode 100644
index 0000000..96b6b37
--- /dev/null
+++ b/reach_reports/reach_application.rb
@@ -0,0 +1,69 @@
+
+[ 'rubygems', 'sinatra', 'sinatra/url_for', 'active_record', 'ar-extensions', 'opentox-ruby-api-wrapper' ].each do |lib|
+ require lib
+end
+
+require 'reach_reports/reach_properties.rb'
+require 'reach_reports/reach_persistance.rb'
+require 'reach_reports/reach_service.rb'
+require 'reach_reports/reach_to_xml.rb'
+
+
+require "lib/format_util.rb"
+
+def extract_type(params)
+ halt 400, "illegal type, neither QMRF nor QPRF: "+params[:type] unless params[:type] && params[:type] =~ /(?i)Q(M|P)RF/
+ params.delete("type")
+end
+
+get '/reach_report/:type' do
+ content_type "text/uri-list"
+ type = extract_type(params)
+ LOGGER.info "list all "+type+" reports"
+ ReachReports.list_reports(type)
+end
+
+post '/reach_report/:type' do
+ content_type "text/uri-list"
+ type = extract_type(params)
+ LOGGER.info "creating "+type+" report "+params.inspect
+ ReachReports.create_report(type,params)
+end
+
+get '/reach_report/:type/:id' do
+
+ type = extract_type(params)
+ LOGGER.info "get "+type+" report with id "+params[:id].to_s+"' "+request.env['HTTP_ACCEPT'].to_s+"'"
+ rep = ReachReports.get_report(type, params[:id])
+
+ case request.env['HTTP_ACCEPT'].to_s
+ when "application/rdf+xml"
+ owl = OpenTox::Owl.create(rep.type+"Report",rep.report_uri)
+ owl.set_data( rep.get_content.keys_to_rdf_format )
+ result = owl.rdf
+ when "application/qmrf-xml"
+ content_type "application/qmrf-xml"
+ result = ReachReports.reach_report_to_xml(rep)
+ when /application\/x-yaml|\*\/\*|^$/ # matches 'application/x-yaml', '*/*', ''
+ content_type "application/x-yaml"
+ result = rep.get_content.to_yaml
+ else
+ halt 400, "MIME type '"+request.env['HTTP_ACCEPT'].to_s+"' not supported, valid Accept-Headers are \"application/rdf+xml\", \"application/x-yaml\", \"application/qmrf-xml\"."
+ end
+ result
+end
+
+get '/reach_report/:type/:id/:section' do
+
+ type = extract_type(params)
+ LOGGER.info "get "+type+" report section '"+params[:section].to_s+"', with id "+params[:id].to_s+"' "+request.env['HTTP_ACCEPT'].to_s+"'"
+ ReachReports.get_report(type, params[:id], params[:section]).to_yaml
+end
+
+get '/reach_report/:type/:id/:section/:subsection' do
+
+ type = extract_type(params)
+ LOGGER.info "get "+type+" report subsection '"+params[:subsection].to_s+"', section '"+params[:section].to_s+"', with id "+params[:id].to_s+"' "+request.env['HTTP_ACCEPT'].to_s+"'"
+ ReachReports.get_report(type, params[:id], params[:section], params[:subsection]).to_yaml
+end
+
diff --git a/reach_reports/reach_persistance.rb b/reach_reports/reach_persistance.rb
new file mode 100644
index 0000000..786c48f
--- /dev/null
+++ b/reach_reports/reach_persistance.rb
@@ -0,0 +1,47 @@
+
+module ReachReports
+
+ def self.get_uri( report )
+ raise "internal error, id not set "+to_yaml if report.id==nil
+ return $sinatra.url_for("/"+File.join(report.type,report.id.to_s), :full).to_s
+ end
+
+ class QmrfReport < ActiveRecord::Base
+
+ alias_attribute :date, :created_at
+
+ QmrfProperties.serialized_properties.each do |p|
+ serialize p
+ end
+
+ def type
+ "QMRF"
+ end
+
+ def report_uri
+ ReachReports.get_uri(self)
+ end
+
+ def get_content
+ hash = {}
+ [ :model_uri, :date ].each{ |p| hash[p] = self.send(p) }
+ QmrfProperties.properties.each{ |p| hash[p] = self.send(p) }
+ return hash
+ end
+ end
+
+
+ class QprfReport < ActiveRecord::Base
+
+ alias_attribute :date, :created_at
+
+ def report_uri
+ ReachReports.get_uri(self)
+ end
+
+ def type
+ "QPRF"
+ end
+ end
+
+end \ No newline at end of file
diff --git a/reach_reports/reach_properties.rb b/reach_reports/reach_properties.rb
new file mode 100644
index 0000000..5397206
--- /dev/null
+++ b/reach_reports/reach_properties.rb
@@ -0,0 +1,158 @@
+
+module ReachReports
+
+ class QmrfProperties
+
+ private
+ PROPS = {
+ "QSAR_title" => "1.1", "QSAR_models" => "1.2", "QSAR_software" => "1.3",
+ "QMRF_date" => "2.1", "QMRF_authors" => "2.2", "QMRF_date_revision" => "2.3", "QMRF_revision" => "2.4",
+ "model_authors" => "2.5", "model_date" => "2.6", "references" => "2.7", "info_availability" => "2.8",
+ "related_models" => "2.9",
+ "model_species" => "3.1", "model_endpoint" => "3.2", "endpoint_comments" => "3.3", "endpoint_units" => "3.4",
+ "endpoint_variable" => "3.5", "endpoint_protocol" => "3.6", "endpoint_data_quality" => "3.7",
+ "algorithm_type" => "4.1", "algorithm_explicit" => "4.2", "algorithms_descriptors" => "4.3",
+ "descriptors_selection" => "4.4", "descriptors_generation" => "4.5", "descriptors_generation_software" => "4.6",
+ "descriptors_chemicals_ratio" => "4.7",
+ "app_domain_description" => "5.1", "app_domain_method" => "5.2", "app_domain_software" => "5.3",
+ "applicability_limits" => "5.4",
+ "training_set_availability" => "6.1", "training_set_data" => "6.2","training_set_descriptors" => "6.3",
+ "dependent_var_availability" => "6.4", "other_info" => "6.5", "preprocessing" => "6.6", "goodness_of_fit" => "6.7",
+ "loo" => "6.8", "lmo" => "6.9", "yscrambling" => "6.10", "bootstrap" => "6.11", "other_statistics" => "6.12",
+ "validation_set_availability" => "7.1", "validation_set_data" => "7.2", "validation_set_descriptors" => "7.3",
+ "validation_dependent_var_availability" => "7.4", "validation_other_info" => "7.5", "experimental_design" => "7.6",
+ "validation_predictivity" => "7.7", "validation_assessment" => "7.8", "validation_comments" => "7.9",
+ "mechanistic_basis" => "8.1", "mechanistic_basis_comments" => "8.2", "mechanistic_basis_info" => "8.3",
+ "comments" => "9.1", "bibliography" => "9.2", "attachments" => "9.3",
+ "QMRF_number" => "10.1", "date_publication" => "10.2", "keywords" => "10.3", "summary_comments" => "10.4",
+ }
+
+ CHAPTER = {
+ "QSAR_identifier" => 1,
+ "QSAR_General_information" => 2,
+ "QSAR_Endpoint" => 3,
+ "QSAR_Algorithm" => 4,
+ "QSAR_Applicability_domain" => 5,
+ "QSAR_Robustness" => 6,
+ "QSAR_Predictivity" => 7,
+ "QSAR_Interpretation" => 8,
+ "QSAR_Miscelaneous" => 9,
+ "QMRF_Summary" => 10 }
+
+ CATALOGS = {
+ "software_catalog" =>
+ { :element => "software",
+ :fields => ["contact", "description", "name", "number", "url"] },
+ "authors_catalog" => {
+ :element => "author",
+ :fields => ["affiliation", "contact", "email", "name", "number", "url"]},
+ "algorithms_catalog" => {
+ :element => "algorithm",
+ :fields => ["definition", "description", "publication_ref"] },
+ "descriptors_catalog" => {
+ :element => "descriptor",
+ :fields => [ "description", "name", "publication_ref", "units"] },
+ "endpoints_catalog" => {
+ :element => "endpoint",
+ :fields => [ "group", "name", "subgroup" ]},
+ "publications_catalog" => {
+ :element => "publication",
+ :fields => [ "title", "url"]},
+ }
+
+ CATALOG_REFERENCES = {
+ "QSAR_software" => "software_catalog",
+ "references" => "publications_catalog",
+ "QMRF_authors" => "authors_catalog",
+ "algorithm_explicit" => "algorithms_catalog",
+ "descriptors_generation_software" => "descriptors_catalog",
+ "model_endpoint" => "endpoints_catalog",
+ "bibliography" => "publications_catalog",
+ }
+
+ SUBSUBSECTIONS = {
+ "algorithm_explicit" => [ "equation" ]
+ }
+
+ #"attachment_training_data", "attachment_validation_data, "attachment_documents",
+
+ public
+ def self.serialized_properties
+ return CATALOG_REFERENCES.keys | SUBSUBSECTIONS.keys
+ end
+
+ def self.properties
+ return PROPS.keys
+ end
+
+ def self.chapter_number( chapter )
+ CHAPTER[chapter]
+ end
+
+ def self.chapter_properties( chapter )
+ chapter_number = CHAPTER[chapter]
+ unsorted_chapter_props = []
+ PROPS.each do |k,v|
+ chapter_nr = v.split(".")[0].to_i
+ next unless chapter_number == chapter_nr
+ unsorted_chapter_props << [ k, v.split(".")[1].to_i ]
+ end
+ unsorted_chapter_props.sort{|a,b| a[1]<=>b[1]}.collect{ |a| a[0] }
+ end
+
+ def self.chapters()
+ #h = { "a" => 20, "b" => 30, "c" => 10 }
+ # h.sort {|a,b| a[1]<=>b[1]} #=> [["c", 10], ["a", 20], ["b", 30]]
+ CHAPTER.sort{|a,b| a[1]<=>b[1]}.collect{ |a| a[0] }
+ end
+
+ def self.to_xml(property, content, catalogs_node)
+ node = REXML::Element.new(property)
+ node.add_attribute "chapter",PROPS[property]
+
+ return node unless content
+
+ unless serialized_properties.include?(property)
+ node.text = content
+ else
+ if content[:text]
+ node.text = content.text
+ end
+ if SUBSUBSECTIONS.has_key?(property)
+ SUBSUBSECTIONS[property].each do |p|
+ subsubsection_node = REXML::Element.new(p)
+ subsubsection_node.text = content[p]
+ node << subsubsection_node
+ end
+ end
+ if CATALOG_REFERENCES.has_key?(property) and content[CATALOG_REFERENCES[property]]
+ catalog_prop = CATALOG_REFERENCES[property]
+ catalog_content = content[catalog_prop]
+ catalog_attributes = CATALOGS[catalog_prop]
+ catalog_node = REXML::Element.new(catalog_prop)
+
+ catalog_content.each do |element|
+ ref_node = REXML::Element.new(catalog_attributes[:element]+"_ref")
+ id = catalog_attributes[:element]+"_"+(catalog_content.index(element)+1).to_s
+ ref_node.add_attribute "idref",id
+ ref_node.add_attribute "catalog",catalog_prop
+ node << ref_node
+ element_node = REXML::Element.new(catalog_attributes[:element])
+ element_node.add_attribute "id",id
+ catalog_attributes[:fields].each do |k|
+ element_node.add_attribute k,element[k.to_sym]
+ end
+ catalog_node << element_node
+ end
+ catalogs_node << catalog_node
+ end
+ end
+
+ node
+ end
+ end
+
+end
+
+
+
diff --git a/reach_reports/reach_service.rb b/reach_reports/reach_service.rb
new file mode 100644
index 0000000..cdc0f9c
--- /dev/null
+++ b/reach_reports/reach_service.rb
@@ -0,0 +1,125 @@
+module ReachReports
+
+ def self.list_reports(type)
+ case type
+ when /(?i)QMRF/
+ ReachReports::QmrfReport.all.collect{ |r| r.report_uri }.join("\n")
+ when /(?i)QPRF/
+ ReachReports::QprfReport.all.collect{ |r| r.report_uri }.join("\n")
+ end
+ end
+
+ def self.create_report( type, params )
+
+ #content_type "text/uri-list"
+ #task_uri = OpenTox::Task.as_task do |task|
+
+ case type
+ when /(?i)QMRF/
+ if params[:model_uri]
+ report = ReachReports::QmrfReport.new :model_uri => params[:model_uri]
+ build_qmrf_report(report)
+ else
+ $sinatra.halt 400, "illegal parameters for qmrf-report, use either\n"+
+ "* model_uri\n"+
+ "params given: "+params.inspect
+ end
+ when /(?i)QPRF/
+ if params[:compound_uri]
+ report = ReachReports::QprfReport.new :compound_uri => params[:compound_uri]
+ else
+ $sinatra.halt 400, "illegal parameters for qprf-report, use either\n"+
+ "* compound-uri\n"+
+ "params given: "+params.inspect
+ end
+ end
+
+ report.report_uri
+
+ #end
+ #halt 202,task_uri
+ end
+
+ def self.build_qmrf_report(r)
+
+ model = OpenTox::Model::Generic.find(r.model_uri)
+
+ # chapter 1
+ r.QSAR_title = model.title
+ # TODO
+ # QSAR_models -> sparql same endpoint
+ software = []
+ software << { :url => model.uri, :name => model.title, :contact => model.creator }
+ algorithm = OpenTox::Algorithm::Generic.find(model.algorithm) if model.algorithm
+ software << { :url => algorithm.uri, :name => algorithm.title }
+ r.QSAR_software = {"software_catalog" => software}
+ #chpater 2
+ r.QMRF_date = DateTime.now.to_s
+ # EMPTY: QMRF_authors, QMRF_date_revision, QMRF_revision
+ # TODO: model_authors ?
+ r.model_date = model.date.to_s
+ # TODO: references?
+ # EMPTY: info_availablity
+ # TODO: related_models = find qmrf reports for QSAR_models
+
+ # chapter 3
+ # TODO "model_species" ?
+ endpoints = []
+ model.predictedVariables.each do |p|
+ endpoints << { :name => p } # TODO :group, :subgroup ?
+ end
+ r.model_endpoint = { "endpoints_catalog" => endpoints }
+ # TODO "endpoint_comments" => "3.3", "endpoint_units" => "3.4",
+ r.endpoint_variable = model.dependentVariables
+ # TODO "endpoint_protocol" => "3.6", "endpoint_data_quality" => "3.7",
+
+ # chapter 4
+ # TODO algorithm_type (='type of model')
+ # TODO algorithm_explicit.equation
+ # TODO algorithm_explicit.algorithms_catalog
+ # TODO algorithms_descriptors, descriptors_selection, descriptors_generation, descriptors_generation_software, descriptors_chemicals_ratio
+
+ # chapter 5
+ # TODO app_domain_description, app_domain_method, app_domain_software, applicability_limits
+
+ # chapter 6
+ # "training_set_availability" => "6.1", "training_set_data" => "6.2","training_set_descriptors" => "6.3",
+ # "dependent_var_availability" => "6.4", "other_info" => "6.5", "preprocessing" => "6.6", "goodness_of_fit" => "6.7",
+ # "loo" => "6.8", "lmo" => "6.9", "yscrambling" => "6.10", "bootstrap" => "6.11", "other_statistics" => "6.12",
+
+ # chapter 7
+ # "validation_set_availability" => "7.1", "validation_set_data" => "7.2", "validation_set_descriptors" => "7.3",
+ # "validation_dependent_var_availability" => "7.4", "validation_other_info" => "7.5", "experimental_design" => "7.6",
+ # "validation_predictivity" => "7.7", "validation_assessment" => "7.8", "validation_comments" => "7.9",
+
+ # chapter 8
+ # "mechanistic_basis" => "8.1", "mechanistic_basis_comments" => "8.2", "mechanistic_basis_info" => "8.3",
+
+ # chapter 9
+ # "comments" => "9.1", "bibliography" => "9.2", "attachments" => "9.3",
+
+ r.save!
+ end
+
+ def self.get_report_content(type, id, *keys)
+
+ report_content = get_report(type, id).get_content
+ keys.each do |k|
+ $sinatra.halt 400, type+" unknown report property '#{key}'" unless report_content.is_a?(Hash) and report_content.has_key?(k)
+ report_content = report_content[k]
+ end
+ report_content
+ end
+
+ def self.get_report(type, id)
+
+ case type
+ when /(?i)QMRF/
+ report = ReachReports::QmrfReport.find(id)
+ when /(?i)QPRF/
+ report = ReachReports::QprfReport.find(id)
+ end
+ $sinatra.halt 404, type+" report with id '#{id}' not found." unless report
+ return report
+ end
+end \ No newline at end of file
diff --git a/reach_reports/reach_test.rb b/reach_reports/reach_test.rb
new file mode 100644
index 0000000..c96340a
--- /dev/null
+++ b/reach_reports/reach_test.rb
@@ -0,0 +1,62 @@
+require "uri"
+require "yaml"
+ENV['RACK_ENV'] = 'test'
+require 'application.rb'
+require 'test/unit'
+require 'rack/test'
+require 'lib/test_util.rb'
+require 'test/test_examples.rb'
+
+LOGGER = MyLogger.new(STDOUT)
+LOGGER.datetime_format = "%Y-%m-%d %H:%M:%S "
+LOGGER.formatter = Logger::Formatter.new
+
+
+class ReachTest < Test::Unit::TestCase
+ include Rack::Test::Methods
+ include Lib::TestUtil
+
+
+ def app
+ Sinatra::Application
+ end
+
+ def test_it
+ #$test_case = self
+
+ post '/reach_report/qmrf',:model_uri=>"http://localhost/model/16"
+ ##post '/reach_report/qprf',:compound_uri=>"http://localhost/compound/XYZ"
+ uri = last_response.body
+ id = uri.split("/")[-1]
+ puts uri
+
+ #get '/reach_report/qmrf'
+ #puts last_response.body
+
+ get '/reach_report/qmrf/'+id.to_s,nil,'HTTP_ACCEPT'=>"application/x-yaml"
+ puts "YAML"
+ puts last_response.body
+
+# get '/reach_report/qmrf/'+id.to_s,nil,'HTTP_ACCEPT'=>"application/rdf+xml"
+# puts "RDF"
+# puts last_response.body
+
+ get '/reach_report/qmrf/'+id,nil,'HTTP_ACCEPT' => "application/qmrf-xml"
+ puts "XML"
+ puts last_response.body
+
+
+ end
+end
+
+
+# query = <<EOF
+#PREFIX ot:<http://www.opentox.org/api/1.1#>
+#PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+#select ?model
+#where {
+#?model rdf:type ot:Model
+#}
+#EOF
+# puts OpenTox::RestClientWrapper.post("http://apps.ideaconsult.net:8080/ontology/",{:accept => "application/rdf+xml", :query => query})
+# exit \ No newline at end of file
diff --git a/reach_reports/reach_to_xml.rb b/reach_reports/reach_to_xml.rb
new file mode 100644
index 0000000..311f59f
--- /dev/null
+++ b/reach_reports/reach_to_xml.rb
@@ -0,0 +1,60 @@
+
+module ReachReports include REXML
+
+ def self.reach_report_to_xml( report )
+
+ @@info = {}
+ if report.type=="QMRF"
+ @@info[:type ] = "QMRF"
+ @@info[:dtd_full ] = "http://ambit.sourceforge.net/qmrf/jws/qmrf.dtd"
+ @@info[:dtd ] = "qmrf.dtd"
+ @@info[:version ] = 1.2
+ @@info[:schema_version] = 0.9
+ @@info[:name ] = "(Q)SAR Model Reporting Format"
+ elsif report.type=="QPRF"
+ @@info[:type ] = "QPRF"
+ @@info[:dtd_full ] = "not-yet-defined/qprf.dtd"
+ @@info[:dtd ] = "qprf.dtd"
+ @@info[:version ] = 0.1
+ @@info[:schema_version] = 0.1
+ @@info[:name ] = "(Q)SAR Prediction Reporting Format"
+ end
+ @@info[:author] ="Joint Research Centre, European Commission"
+ @@info[:contact] ="Joint Research Centre, European Commission"
+ @@info[:date ] = Time.new.to_s
+ @@info[:email] ="qsardb@jrc.it"
+ @@info[:schema_version] ="0.9"
+ @@info[:url ] = "http://ecb.jrc.ec.europa.eu/qsar/"
+
+ doc = Document.new
+ decl = XMLDecl.new
+ doc << decl
+ type = DocType.new(@@info[:type]+' PUBLIC "'+@@info[:dtd_full]+'" "'+@@info[:dtd]+'"')
+ doc << type
+
+ main = Element.new(@@info[:type])
+ main.add_attributes( Hash[*[:version, :schema_version, :name, :author, :contact,
+ :date, :email, :schema_version, :url].collect { |v| [v.to_s, @@info[v]]}.flatten] )
+
+ catalogs = Element.new("Catalogs")
+ chapters = Element.new(@@info[:type]+"_chapters")
+
+ QmrfProperties.chapters.each do |c|
+ chapter = Element.new(c)
+ chapter.add_attribute("chapter",QmrfProperties.chapter_number(c))
+ QmrfProperties.chapter_properties(c).each do |p|
+ chapter << QmrfProperties.to_xml(p, report.send(p), catalogs)
+ end
+ chapters << chapter
+ end
+
+ main << chapters
+ main << catalogs
+ doc << main
+
+ s = ""
+ doc.write(s, 2, false, false)
+ return s
+ end
+
+end \ No newline at end of file