From 6a2c3f2100d030c30b7d8ac8c95dcece7edb040c Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Tue, 8 Sep 2009 16:04:23 +0200 Subject: api separated into individual components, adapted for new webservice versions --- lib/compound.rb | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 lib/compound.rb (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb new file mode 100644 index 0000000..4652770 --- /dev/null +++ b/lib/compound.rb @@ -0,0 +1,67 @@ +module OpenTox + + # uri: /compound/:inchi + class Compound < OpenTox + + attr_reader :inchi + + # Initialize with :uri => uri, :smiles => smiles or :name => name (name can be also an InChI/InChiKey, CAS number, etc) + def initialize(params) + @@cactus_uri="http://cactus.nci.nih.gov/chemical/structure/" + if params[:smiles] + @inchi = smiles2inchi(params[:smiles]) + @uri = File.join(@@config[:services]["opentox-dataset"],"compound",@inchi) + elsif params[:inchi] + @inchi = inchi + @uri = File.join(@@config[:services]["opentox-dataset"],"compound",@inchi) + elsif params[:name] + @inchi = RestClient.get "#{@@cactus_uri}#{params[:name]}/stdinchi" + @uri = File.join(@@config[:services]["opentox-dataset"],"compound",@inchi) + elsif params[:uri] + @inchi = params[:uri].sub(/^.*InChI/, 'InChI') + @uri = params[:uri] + end + end + + # Get the (canonical) smiles + def smiles + obconversion(@inchi,'inchi','can') + end + + def sdf + obconversion(@inchi,'inchi','sdf') + end + + # Matchs a smarts string + def match?(smarts) + obconversion = OpenBabel::OBConversion.new + obmol = OpenBabel::OBMol.new + obconversion.set_in_format('inchi') + obconversion.read_string(obmol,@inchi) + smarts_pattern = OpenBabel::OBSmartsPattern.new + smarts_pattern.init(smarts) + smarts_pattern.match(obmol) + end + + # Match an array of smarts features, returns matching features + def match(smarts_features) + smarts_features.all_features.collect{ |smarts| smarts if self.match?(smarts.name) }.compact + end + + def smiles2inchi(smiles) + obconversion(smiles,'smi','inchi') + end + + def smiles2cansmi(smiles) + obconversion(smiles,'smi','can') + end + + def obconversion(identifier,input_format,output_format) + obconversion = OpenBabel::OBConversion.new + obmol = OpenBabel::OBMol.new + obconversion.set_in_and_out_formats input_format, output_format + obconversion.read_string obmol, identifier + obconversion.write_string(obmol).gsub(/\s/,'').chomp + end + end +end -- cgit v1.2.3 From 59249a0febc2f90cd1643ddb7e3baa68e3f49065 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 10 Sep 2009 15:21:09 +0200 Subject: initial wrapper for new webservices --- lib/compound.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 4652770..67c8004 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -44,8 +44,8 @@ module OpenTox end # Match an array of smarts features, returns matching features - def match(smarts_features) - smarts_features.all_features.collect{ |smarts| smarts if self.match?(smarts.name) }.compact + def match(smarts_dataset) + smarts_dataset.all_features.collect{ |uri| uri if self.match?(Feature.new(:uri => uri).name) }.compact end def smiles2inchi(smiles) -- cgit v1.2.3 From 5d5688fbe43806af8523e5481715b5969feeab60 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Tue, 6 Oct 2009 10:39:43 +0200 Subject: Passes tests in opentox-test --- lib/compound.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 67c8004..c4ba8d9 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -10,13 +10,13 @@ module OpenTox @@cactus_uri="http://cactus.nci.nih.gov/chemical/structure/" if params[:smiles] @inchi = smiles2inchi(params[:smiles]) - @uri = File.join(@@config[:services]["opentox-dataset"],"compound",@inchi) + @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:inchi] - @inchi = inchi - @uri = File.join(@@config[:services]["opentox-dataset"],"compound",@inchi) + @inchi = params[:inchi] + @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:name] @inchi = RestClient.get "#{@@cactus_uri}#{params[:name]}/stdinchi" - @uri = File.join(@@config[:services]["opentox-dataset"],"compound",@inchi) + @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:uri] @inchi = params[:uri].sub(/^.*InChI/, 'InChI') @uri = params[:uri] -- cgit v1.2.3 From adfcc9d572a2122b1b030dc04b3abf46007fb3f7 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Mon, 23 Nov 2009 18:17:37 +0100 Subject: RDF support added --- lib/compound.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index c4ba8d9..416acab 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -15,7 +15,7 @@ module OpenTox @inchi = params[:inchi] @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:name] - @inchi = RestClient.get "#{@@cactus_uri}#{params[:name]}/stdinchi" + @inchi = RestClient.get("#{@@cactus_uri}#{params[:name]}/stdinchi").chomp @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:uri] @inchi = params[:uri].sub(/^.*InChI/, 'InChI') @@ -44,8 +44,8 @@ module OpenTox end # Match an array of smarts features, returns matching features - def match(smarts_dataset) - smarts_dataset.all_features.collect{ |uri| uri if self.match?(Feature.new(:uri => uri).name) }.compact + def match(smarts_array) + smarts_array.collect{|s| s if match?(s)}.compact end def smiles2inchi(smiles) -- cgit v1.2.3 From fc3bda0095ca7e6968edf01bec034a243d294af4 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Mon, 14 Dec 2009 09:41:59 +0100 Subject: Initial adaptation to RDF/OWL --- lib/compound.rb | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 416acab..9e1cee7 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -1,9 +1,8 @@ module OpenTox - # uri: /compound/:inchi - class Compound < OpenTox + class Compound #< OpenTox - attr_reader :inchi + attr_reader :inchi, :uri # Initialize with :uri => uri, :smiles => smiles or :name => name (name can be also an InChI/InChiKey, CAS number, etc) def initialize(params) @@ -14,6 +13,9 @@ module OpenTox elsif params[:inchi] @inchi = params[:inchi] @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) + elsif params[:sdf] + @inchi = sdf2inchi(params[:sdf]) + @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:name] @inchi = RestClient.get("#{@@cactus_uri}#{params[:name]}/stdinchi").chomp @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) @@ -48,6 +50,10 @@ module OpenTox smarts_array.collect{|s| s if match?(s)}.compact end + def sdf2inchi(sdf) + obconversion(sdf,'sdf','inchi') + end + def smiles2inchi(smiles) obconversion(smiles,'smi','inchi') end @@ -61,7 +67,12 @@ module OpenTox obmol = OpenBabel::OBMol.new obconversion.set_in_and_out_formats input_format, output_format obconversion.read_string obmol, identifier - obconversion.write_string(obmol).gsub(/\s/,'').chomp + case output_format + when /smi|can|inchi/ + obconversion.write_string(obmol).gsub(/\s/,'').chomp + else + obconversion.write_string(obmol) + end end end end -- cgit v1.2.3 From 09974c5a920bbb07475d8e48a725ef3780e60dbe Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Fri, 22 Jan 2010 11:16:13 +0100 Subject: central config.ru, generic compound API --- lib/compound.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 4385a7d..0a90663 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -20,14 +20,19 @@ module OpenTox @inchi = RestClient.get("#{@@cactus_uri}#{params[:name]}/stdinchi").chomp @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:uri] - @inchi = params[:uri].sub(/^.*InChI/, 'InChI') + if params[:uri].match(/InChI/) # shortcut for IST services + @inchi = params[:uri].sub(/^.*InChI/, 'InChI') + else + @inchi = RestClient.get @uri, :accept => 'chemical/x-inchi' + end @uri = params[:uri] end end # Get the (canonical) smiles def smiles - obconversion(@inchi,'inchi','can') + RestClient.get(@uri, :accept => 'chemical/x-daylight-smiles').split(/\s+/).first # fix ambit output + #obconversion(@inchi,'inchi','can') end def sdf -- cgit v1.2.3 From c9d820e767a6baf6ae6fba2bb6b2e3641253b5c4 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Sun, 31 Jan 2010 19:09:16 +0100 Subject: Upload facilities added, Ambit disabled --- lib/compound.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 0a90663..562baaa 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -20,19 +20,22 @@ module OpenTox @inchi = RestClient.get("#{@@cactus_uri}#{params[:name]}/stdinchi").chomp @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:uri] + @uri = params[:uri] if params[:uri].match(/InChI/) # shortcut for IST services @inchi = params[:uri].sub(/^.*InChI/, 'InChI') else @inchi = RestClient.get @uri, :accept => 'chemical/x-inchi' + # AMBIT does not provide InChIs + #smiles = RestClient.get(@uri, :accept => 'chemical/x-daylight-smiles').split(/\s+/).first # fix ambit output + #@inchi = obconversion(smiles,'smi','inchi') end - @uri = params[:uri] end end # Get the (canonical) smiles def smiles - RestClient.get(@uri, :accept => 'chemical/x-daylight-smiles').split(/\s+/).first # fix ambit output - #obconversion(@inchi,'inchi','can') + #RestClient.get(@uri, :accept => 'chemical/x-daylight-smiles').split(/\s+/).first # fix ambit output + obconversion(@inchi,'inchi','can') end def sdf -- cgit v1.2.3 From 3d65a42cf68bd5128666d810ec3c29673624ee5d Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Tue, 2 Feb 2010 17:00:48 +0100 Subject: centralized database configuration --- lib/compound.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 562baaa..56646c0 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -21,20 +21,20 @@ module OpenTox @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:uri] @uri = params[:uri] - if params[:uri].match(/InChI/) # shortcut for IST services + case params[:uri] + when /ambit/ # Ambit does not deliver InChIs reliably + smiles = RestClient.get @uri, :accept => 'chemical/x-daylight-smiles' + @inchi = obconversion(smiles,'smi','inchi') + when /InChI/ # shortcut for IST services @inchi = params[:uri].sub(/^.*InChI/, 'InChI') else @inchi = RestClient.get @uri, :accept => 'chemical/x-inchi' - # AMBIT does not provide InChIs - #smiles = RestClient.get(@uri, :accept => 'chemical/x-daylight-smiles').split(/\s+/).first # fix ambit output - #@inchi = obconversion(smiles,'smi','inchi') end end end # Get the (canonical) smiles def smiles - #RestClient.get(@uri, :accept => 'chemical/x-daylight-smiles').split(/\s+/).first # fix ambit output obconversion(@inchi,'inchi','can') end -- cgit v1.2.3 From 7b59d1f07bf8cf0e23f3070f97f940af3bfad843 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Tue, 23 Feb 2010 17:49:02 +0100 Subject: some test issues resolved --- lib/compound.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 56646c0..0ee853d 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -17,7 +17,8 @@ module OpenTox @inchi = sdf2inchi(params[:sdf]) @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:name] - @inchi = RestClient.get("#{@@cactus_uri}#{params[:name]}/stdinchi").chomp + # paranoid URI encoding to keep SMILES charges and brackets + @inchi = RestClient.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").chomp @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:uri] @uri = params[:uri] -- cgit v1.2.3 From 9e356d0d94ea4fe210ea7cefce5d4c1179cb63cd Mon Sep 17 00:00:00 2001 From: mguetlein Date: Thu, 6 May 2010 11:32:05 +0200 Subject: major change: using literal datatypes in owl --- lib/compound.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 0ee853d..cc29fc5 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -18,18 +18,18 @@ module OpenTox @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:name] # paranoid URI encoding to keep SMILES charges and brackets - @inchi = RestClient.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").chomp + @inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").chomp @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:uri] @uri = params[:uri] case params[:uri] when /ambit/ # Ambit does not deliver InChIs reliably - smiles = RestClient.get @uri, :accept => 'chemical/x-daylight-smiles' + smiles = RestClientWrapper.get @uri, :accept => 'chemical/x-daylight-smiles' @inchi = obconversion(smiles,'smi','inchi') when /InChI/ # shortcut for IST services @inchi = params[:uri].sub(/^.*InChI/, 'InChI') else - @inchi = RestClient.get @uri, :accept => 'chemical/x-inchi' + @inchi = RestClientWrapper.get @uri, :accept => 'chemical/x-inchi' end end end @@ -44,7 +44,7 @@ module OpenTox end def image - RestClient.get("#{@@cactus_uri}#{@inchi}/image") + RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/image") end def image_uri -- cgit v1.2.3 From d5eea102ff343804dde1ccd254bc570596341a89 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Fri, 21 May 2010 15:55:17 +0200 Subject: dynamic From: address from mailer --- lib/compound.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index cc29fc5..6ab78e0 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -18,7 +18,9 @@ module OpenTox @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:name] # paranoid URI encoding to keep SMILES charges and brackets - @inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").chomp + @inchi = RestClient.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").body.chomp + # this was too hard for me to debug and leads to additional errors (ch) + #@inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").chomp @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:uri] @uri = params[:uri] -- cgit v1.2.3 From 4902d7d4c2d45ef98d20d5a6269e0dbf3bd01cc4 Mon Sep 17 00:00:00 2001 From: ist Date: Fri, 11 Jun 2010 17:35:10 +0200 Subject: Added occurrence function 'match_all' --- lib/compound.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 6ab78e0..7c7c3d8 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -69,6 +69,12 @@ module OpenTox smarts_array.collect{|s| s if match?(s)}.compact end + # AM + # Match an array of smarts features, returns (0)1 for (non)matching features at each pos + def match_all(smarts_array) + smarts_array.collect{|s| match?(s) ? 1 : 0 } + end + def sdf2inchi(sdf) obconversion(sdf,'sdf','inchi') end -- cgit v1.2.3 From 3fe0e8c735abd2cacc138f075b5a4af0c6359724 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 14 Jul 2010 13:56:50 +0200 Subject: model creation working, validation report generation fails for large datasets --- lib/compound.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 7c7c3d8..a293df0 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -1,3 +1,6 @@ +@@cactus_uri="http://cactus.nci.nih.gov/chemical/structure/" +@@ambit_uri="http://ambit.uni-plovdiv.bg:8080/ambit2/depict/cdk?search=" + module OpenTox class Compound #< OpenTox @@ -6,7 +9,6 @@ module OpenTox # Initialize with :uri => uri, :smiles => smiles or :name => name (name can be also an InChI/InChiKey, CAS number, etc) def initialize(params) - @@cactus_uri="http://cactus.nci.nih.gov/chemical/structure/" if params[:smiles] @inchi = smiles2inchi(params[:smiles]) @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) @@ -45,12 +47,17 @@ module OpenTox obconversion(@inchi,'inchi','sdf') end - def image + def gif RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/image") end + def png + RestClientWrapper.get("#{@@ambit_uri}#{smiles}") + end + def image_uri - "#{@@cactus_uri}#{@inchi}/image" + "#{@@ambit_uri}#{smiles}" + #"#{@@cactus_uri}#{@inchi}/image" end # Matchs a smarts string -- cgit v1.2.3 From 05084b1127f0d2498240472cca8a475f48f1fcc4 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 22 Jul 2010 10:23:53 +0200 Subject: modifications from first code review meeting --- lib/compound.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index a293df0..45b96b8 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -11,19 +11,19 @@ module OpenTox def initialize(params) if params[:smiles] @inchi = smiles2inchi(params[:smiles]) - @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) + @uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:inchi] @inchi = params[:inchi] - @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) + @uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:sdf] @inchi = sdf2inchi(params[:sdf]) - @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) + @uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:name] # paranoid URI encoding to keep SMILES charges and brackets @inchi = RestClient.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").body.chomp # this was too hard for me to debug and leads to additional errors (ch) #@inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").chomp - @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) + @uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:uri] @uri = params[:uri] case params[:uri] -- cgit v1.2.3 From 34a7b50fb278fc37c937f2fe170b86332eb054c5 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 22 Jul 2010 17:12:51 +0200 Subject: CONFIG reverted to @@config --- lib/compound.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 45b96b8..9366db4 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -11,19 +11,19 @@ module OpenTox def initialize(params) if params[:smiles] @inchi = smiles2inchi(params[:smiles]) - @uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(@inchi)) + @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:inchi] @inchi = params[:inchi] - @uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(@inchi)) + @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:sdf] @inchi = sdf2inchi(params[:sdf]) - @uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(@inchi)) + @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:name] # paranoid URI encoding to keep SMILES charges and brackets @inchi = RestClient.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").body.chomp # this was too hard for me to debug and leads to additional errors (ch) #@inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").chomp - @uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(@inchi)) + @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) elsif params[:uri] @uri = params[:uri] case params[:uri] @@ -56,7 +56,8 @@ module OpenTox end def image_uri - "#{@@ambit_uri}#{smiles}" + File.join @uri, "image" + #"#{@@ambit_uri}#{smiles}" #"#{@@cactus_uri}#{@inchi}/image" end -- cgit v1.2.3 From d6811507c1c1339cc4fe7cdb429b9b34b97dc422 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Fri, 22 Oct 2010 17:45:19 +0200 Subject: new API with support for external services (initial version) --- lib/compound.rb | 184 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 117 insertions(+), 67 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 49c166f..699e4c1 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -3,82 +3,120 @@ module OpenTox - class Compound #< OpenTox - - attr_reader :inchi, :uri - - # Initialize with :uri => uri, :smiles => smiles or :name => name (name can be also an InChI/InChiKey, CAS number, etc) - def initialize(params) - if params[:smiles] - @inchi = smiles2inchi(params[:smiles]) - @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) - elsif params[:inchi] - @inchi = params[:inchi] - @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) - elsif params[:sdf] - @inchi = sdf2inchi(params[:sdf]) - @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) - elsif params[:name] - # paranoid URI encoding to keep SMILES charges and brackets - @inchi = RestClient.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").body.chomp - # this was too hard for me to debug and leads to additional errors (ch) - #@inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").chomp - @uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi)) - elsif params[:uri] - @uri = params[:uri] - case params[:uri] - when /ambit/ # Ambit does not deliver InChIs reliably - smiles = RestClientWrapper.get @uri, :accept => 'chemical/x-daylight-smiles' - @inchi = obconversion(smiles,'smi','inchi') - when /InChI/ # shortcut for IST services - @inchi = params[:uri].sub(/^.*InChI/, 'InChI') - else - @inchi = RestClientWrapper.get @uri, :accept => 'chemical/x-inchi' - end - end - end + # Ruby wrapper for OpenTox Compound Webservices (http://opentox.org/dev/apis/api-1.2/structure). + # + # Examples: + # require "opentox-ruby-api-wrapper" + # + # # Creating compounds + # + # # from smiles string + # compound = OpenTox::Compound.from_smiles("c1ccccc1") + # # from name + # compound = OpenTox::Compound.from_name("Benzene") + # # from uri + # compound = OpenTox::Compound.new("http://webservices.in-silico.ch/compound/InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H"") + # + # # Getting compound representations + # + # # get InChI + # inchi = compound.inchi + # # get all compound names + # names = compound.names + # # get png image + # image = compound.png + # # get uri + # uri = compound.uri + # + # # SMARTS matching + # + # # match a smarts string + # compound.match?("cN") # returns false + # # match an array of smarts strings + # compound.match(['cc','cN']) # returns ['cc'] + class Compound + + attr_accessor :inchi, :uri + + # Create compound with optional uri + def initialize(uri=nil) + @uri = uri + case @uri + when /InChI/ # shortcut for IST services + @inchi = @uri.sub(/^.*InChI/, 'InChI') + else + @inchi = RestClientWrapper.get(@uri, :accept => 'chemical/x-inchi').to_s.chomp if @uri + end + end - # Get the (canonical) smiles + # Create a compound from smiles string + def self.from_smiles(smiles) + c = Compound.new + c.inchi = Compound.smiles2inchi(smiles) + c.uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(c.inchi)) + c + end + + # Create a compound from inchi string + def self.from_inchi(inchi) + c = Compound.new + c.inchi = inchi + c.uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(c.inchi)) + c + end + + # Create a compound from sdf string + def self.from_sdf(sdf) + c = Compound.new + c.inchi = Compound.sdf2inchi(sdf) + c.uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(c.inchi)) + c + end + + # Create a compound from name (name can be also an InChI/InChiKey, CAS number, etc) + def self.from_name(name) + c = Compound.new + # paranoid URI encoding to keep SMILES charges and brackets + c.inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(name, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").to_s.chomp + c.uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(c.inchi)) + c + end + + # Get (canonical) smiles def smiles - obconversion(@inchi,'inchi','can') + Compound.obconversion(@inchi,'inchi','can') end + # Get sdf def sdf - obconversion(@inchi,'inchi','sdf') + Compound.obconversion(@inchi,'inchi','sdf') end + # Get gif image def gif RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/image") end + # Get png image def png RestClientWrapper.get(File.join @uri, "image") end + # Get URI of compound image + def image_uri + File.join @uri, "image" + end + + # Get all known compound names def names begin - RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/names") + RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/names").split("\n") rescue "not available" end end - def display_smarts_uri(activating, deactivating, highlight = nil) - LOGGER.debug activating.to_yaml unless activating.nil? - activating_smarts = URI.encode "\"#{activating.join("\"/\"")}\"" - deactivating_smarts = URI.encode "\"#{deactivating.join("\"/\"")}\"" - if highlight.nil? - File.join @@config[:services]["opentox-compound"], "smiles", URI.encode(smiles), "smarts/activating", URI.encode(activating_smarts),"deactivating", URI.encode(deactivating_smarts) - else - File.join @@config[:services]["opentox-compound"], "smiles", URI.encode(smiles), "smarts/activating", URI.encode(activating_smarts),"deactivating", URI.encode(deactivating_smarts), "highlight", URI.encode(highlight) - end - end - - def image_uri - File.join @uri, "image" - end - - # Matchs a smarts string + # Match a smarts string def match?(smarts) obconversion = OpenBabel::OBConversion.new obmol = OpenBabel::OBMol.new @@ -89,30 +127,42 @@ module OpenTox smarts_pattern.match(obmol) end - # Match an array of smarts features, returns matching features + # Match an array of smarts strings, returns array with matching smarts def match(smarts_array) smarts_array.collect{|s| s if match?(s)}.compact end - # AM - # Match an array of smarts features, returns (0)1 for (non)matching features at each pos - def match_all(smarts_array) - smarts_array.collect{|s| match?(s) ? 1 : 0 } - end + # Get URI of compound image with highlighted fragments + def matching_smarts_image_uri(activating, deactivating, highlight = nil) + activating_smarts = URI.encode "\"#{activating.join("\"/\"")}\"" + deactivating_smarts = URI.encode "\"#{deactivating.join("\"/\"")}\"" + if highlight.nil? + File.join CONFIG[:services]["opentox-compound"], "smiles", URI.encode(smiles), "smarts/activating", URI.encode(activating_smarts),"deactivating", URI.encode(deactivating_smarts) + else + File.join CONFIG[:services]["opentox-compound"], "smiles", URI.encode(smiles), "smarts/activating", URI.encode(activating_smarts),"deactivating", URI.encode(deactivating_smarts), "highlight", URI.encode(highlight) + end + end + + + private - def sdf2inchi(sdf) - obconversion(sdf,'sdf','inchi') + # Convert sdf to inchi + def self.sdf2inchi(sdf) + Compound.obconversion(sdf,'sdf','inchi') end - def smiles2inchi(smiles) - obconversion(smiles,'smi','inchi') + # Convert smiles to inchi + def self.smiles2inchi(smiles) + Compound.obconversion(smiles,'smi','inchi') end - def smiles2cansmi(smiles) - obconversion(smiles,'smi','can') + # Convert smiles to canonical smiles + def self.smiles2cansmi(smiles) + Compound.obconversion(smiles,'smi','can') end - def obconversion(identifier,input_format,output_format) + # Convert identifier from OpenBabel input_format to OpenBabel output_format + def self.obconversion(identifier,input_format,output_format) obconversion = OpenBabel::OBConversion.new obmol = OpenBabel::OBMol.new obconversion.set_in_and_out_formats input_format, output_format -- cgit v1.2.3 From b93002b4ea50ff7e357da08abd10577347ce2d5f Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 11 Nov 2010 09:31:27 +0100 Subject: first steps towards version 2.0, yard documentation started, passes compound, dataset, feature, algorithm, fminer tests --- lib/compound.rb | 105 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 45 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 699e4c1..6834860 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -4,41 +4,15 @@ module OpenTox # Ruby wrapper for OpenTox Compound Webservices (http://opentox.org/dev/apis/api-1.2/structure). - # - # Examples: - # require "opentox-ruby-api-wrapper" - # - # # Creating compounds - # - # # from smiles string - # compound = OpenTox::Compound.from_smiles("c1ccccc1") - # # from name - # compound = OpenTox::Compound.from_name("Benzene") - # # from uri - # compound = OpenTox::Compound.new("http://webservices.in-silico.ch/compound/InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H"") - # - # # Getting compound representations - # - # # get InChI - # inchi = compound.inchi - # # get all compound names - # names = compound.names - # # get png image - # image = compound.png - # # get uri - # uri = compound.uri - # - # # SMARTS matching - # - # # match a smarts string - # compound.match?("cN") # returns false - # # match an array of smarts strings - # compound.match(['cc','cN']) # returns ['cc'] class Compound attr_accessor :inchi, :uri # Create compound with optional uri + # @example + # compound = OpenTox::Compound.new("http://webservices.in-silico.ch/compound/InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H"") + # @param [optional, String] uri Compound URI + # @return [OpenTox::Compound] Compound def initialize(uri=nil) @uri = uri case @uri @@ -50,6 +24,10 @@ module OpenTox end # Create a compound from smiles string + # @example + # compound = OpenTox::Compound.from_smiles("c1ccccc1") + # @param [String] smiles Smiles string + # @return [OpenTox::Compound] Compound def self.from_smiles(smiles) c = Compound.new c.inchi = Compound.smiles2inchi(smiles) @@ -58,6 +36,8 @@ module OpenTox end # Create a compound from inchi string + # @param [String] smiles InChI string + # @return [OpenTox::Compound] Compound def self.from_inchi(inchi) c = Compound.new c.inchi = inchi @@ -66,6 +46,8 @@ module OpenTox end # Create a compound from sdf string + # @param [String] smiles SDF string + # @return [OpenTox::Compound] Compound def self.from_sdf(sdf) c = Compound.new c.inchi = Compound.sdf2inchi(sdf) @@ -73,7 +55,11 @@ module OpenTox c end - # Create a compound from name (name can be also an InChI/InChiKey, CAS number, etc) + # Create a compound from name. Relies on an external service for name lookups. + # @example + # compound = OpenTox::Compound.from_name("Benzene") + # @param [String] name name can be also an InChI/InChiKey, CAS number, etc + # @return [OpenTox::Compound] Compound def self.from_name(name) c = Compound.new # paranoid URI encoding to keep SMILES charges and brackets @@ -83,32 +69,42 @@ module OpenTox end # Get (canonical) smiles - def smiles + # @return [String] Smiles string + def to_smiles Compound.obconversion(@inchi,'inchi','can') end # Get sdf - def sdf + # @return [String] SDF string + def to_sdf Compound.obconversion(@inchi,'inchi','sdf') end # Get gif image - def gif + # @return [image/gif] Image data + def to_gif RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/image") end # Get png image - def png + # @example + # image = compound.to_png + # @return [image/png] Image data + def to_png RestClientWrapper.get(File.join @uri, "image") end # Get URI of compound image - def image_uri + # @return [String] Compound image URI + def to_image_uri File.join @uri, "image" end - # Get all known compound names - def names + # Get all known compound names. Relies on an external service for name lookups. + # @example + # names = compound.to_names + # @return [String] Compound names + def to_names begin RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/names").split("\n") rescue @@ -117,6 +113,10 @@ module OpenTox end # Match a smarts string + # @example + # compound = OpenTox::Compound.from_name("Benzene") + # compound.match?("cN") # returns false + # @param [String] smarts Smarts string def match?(smarts) obconversion = OpenBabel::OBConversion.new obmol = OpenBabel::OBMol.new @@ -128,19 +128,34 @@ module OpenTox end # Match an array of smarts strings, returns array with matching smarts + # @example + # compound = OpenTox::Compound.from_name("Benzene") + # compound.match(['cc','cN']) # returns ['cc'] + # @param [Array] smarts_array Array with Smarts strings + # @return [Array] Array with matching Smarts strings def match(smarts_array) - smarts_array.collect{|s| s if match?(s)}.compact + # avoid recreation of OpenBabel objects + obconversion = OpenBabel::OBConversion.new + obmol = OpenBabel::OBMol.new + obconversion.set_in_format('inchi') + obconversion.read_string(obmol,@inchi) + smarts_pattern = OpenBabel::OBSmartsPattern.new + smarts_array.collect do |smarts| + smarts_pattern.init(smarts) + smarts if smarts_pattern.match(obmol) + end.compact + #smarts_array.collect { |s| s if match?(s)}.compact end # Get URI of compound image with highlighted fragments - def matching_smarts_image_uri(activating, deactivating, highlight = nil) + # + # @param [Array] activating Array with activating Smarts strings + # @param [Array] deactivating Array with deactivating Smarts strings + # @return [String] URI for compound image with highlighted fragments + def matching_smarts_image_uri(activating, deactivating) activating_smarts = URI.encode "\"#{activating.join("\"/\"")}\"" deactivating_smarts = URI.encode "\"#{deactivating.join("\"/\"")}\"" - if highlight.nil? - File.join CONFIG[:services]["opentox-compound"], "smiles", URI.encode(smiles), "smarts/activating", URI.encode(activating_smarts),"deactivating", URI.encode(deactivating_smarts) - else - File.join CONFIG[:services]["opentox-compound"], "smiles", URI.encode(smiles), "smarts/activating", URI.encode(activating_smarts),"deactivating", URI.encode(deactivating_smarts), "highlight", URI.encode(highlight) - end + File.join @uri, "smarts/activating", URI.encode(activating_smarts),"deactivating", URI.encode(deactivating_smarts) end -- cgit v1.2.3 From 64e5d2890f42cef112fbe768f6bfd54b746686de Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Fri, 3 Dec 2010 14:37:09 +0100 Subject: underscore method added to String class --- lib/compound.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 6834860..a85507b 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -68,6 +68,12 @@ module OpenTox c end + # Get InChI + # @return [String] InChI string + def to_inchi + @inchi + end + # Get (canonical) smiles # @return [String] Smiles string def to_smiles -- cgit v1.2.3 From 64354959e04fcac11bcf70e75099691b74573033 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Tue, 16 Aug 2011 14:46:31 +0200 Subject: initial minimal version --- lib/compound.rb | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index a85507b..189db7b 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -29,30 +29,21 @@ module OpenTox # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound def self.from_smiles(smiles) - c = Compound.new - c.inchi = Compound.smiles2inchi(smiles) - c.uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(c.inchi)) - c + Compound.new RestClientWrapper.post(CONFIG[:services]["opentox-compound"], smiles, :content_type => 'chemical/x-daylight-smiles').to_s.chomp end # Create a compound from inchi string # @param [String] smiles InChI string # @return [OpenTox::Compound] Compound def self.from_inchi(inchi) - c = Compound.new - c.inchi = inchi - c.uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(c.inchi)) - c + Compound.new RestClientWrapper.post(CONFIG[:services]["opentox-compound"], inchi, :content_type => 'chemical/x-inchi').to_s.chomp end # Create a compound from sdf string # @param [String] smiles SDF string # @return [OpenTox::Compound] Compound def self.from_sdf(sdf) - c = Compound.new - c.inchi = Compound.sdf2inchi(sdf) - c.uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(c.inchi)) - c + Compound.new RestClientWrapper.post(CONFIG[:services]["opentox-compound"], sdf, :content_type => 'chemical/x-mdl-sdfile').to_s.chomp end # Create a compound from name. Relies on an external service for name lookups. @@ -77,13 +68,13 @@ module OpenTox # Get (canonical) smiles # @return [String] Smiles string def to_smiles - Compound.obconversion(@inchi,'inchi','can') + RestClientWrapper.get(@uri, :accept => 'chemical/x-daylight-smiles').chomp end # Get sdf # @return [String] SDF string def to_sdf - Compound.obconversion(@inchi,'inchi','sdf') + RestClientWrapper.get(@uri, :accept => 'chemical/x-mdl-sdfile').chomp end # Get gif image @@ -118,6 +109,7 @@ module OpenTox end end +=begin # Match a smarts string # @example # compound = OpenTox::Compound.from_name("Benzene") @@ -195,5 +187,6 @@ module OpenTox obconversion.write_string(obmol) end end +=end end end -- cgit v1.2.3 From ac54997dccc571471a0cdf62939e2fcbc42e06e2 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Fri, 13 Jan 2012 12:49:09 +0100 Subject: compound added --- lib/compound.rb | 39 ++++++++++----------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 189db7b..974e46e 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -6,44 +6,27 @@ module OpenTox # Ruby wrapper for OpenTox Compound Webservices (http://opentox.org/dev/apis/api-1.2/structure). class Compound - attr_accessor :inchi, :uri - - # Create compound with optional uri - # @example - # compound = OpenTox::Compound.new("http://webservices.in-silico.ch/compound/InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H"") - # @param [optional, String] uri Compound URI - # @return [OpenTox::Compound] Compound - def initialize(uri=nil) - @uri = uri - case @uri - when /InChI/ # shortcut for IST services - @inchi = @uri.sub(/^.*InChI/, 'InChI') - else - @inchi = RestClientWrapper.get(@uri, :accept => 'chemical/x-inchi').to_s.chomp if @uri - end - end - # Create a compound from smiles string # @example # compound = OpenTox::Compound.from_smiles("c1ccccc1") # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound - def self.from_smiles(smiles) - Compound.new RestClientWrapper.post(CONFIG[:services]["opentox-compound"], smiles, :content_type => 'chemical/x-daylight-smiles').to_s.chomp + def self.from_smiles service_uri, smiles, subjectid=nil + Compound.new RestClientWrapper.post(service_uri, smiles, :content_type => 'chemical/x-daylight-smiles').to_s.chomp end # Create a compound from inchi string # @param [String] smiles InChI string # @return [OpenTox::Compound] Compound - def self.from_inchi(inchi) - Compound.new RestClientWrapper.post(CONFIG[:services]["opentox-compound"], inchi, :content_type => 'chemical/x-inchi').to_s.chomp + def self.from_inchi(service_uri, inchi) + Compound.new RestClientWrapper.post(service_uri, inchi, :content_type => 'chemical/x-inchi').to_s.chomp end # Create a compound from sdf string # @param [String] smiles SDF string # @return [OpenTox::Compound] Compound - def self.from_sdf(sdf) - Compound.new RestClientWrapper.post(CONFIG[:services]["opentox-compound"], sdf, :content_type => 'chemical/x-mdl-sdfile').to_s.chomp + def self.from_sdf(service_uri, sdf) + Compound.new RestClientWrapper.post(service_uri, sdf, :content_type => 'chemical/x-mdl-sdfile').to_s.chomp end # Create a compound from name. Relies on an external service for name lookups. @@ -51,18 +34,16 @@ module OpenTox # compound = OpenTox::Compound.from_name("Benzene") # @param [String] name name can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound - def self.from_name(name) - c = Compound.new + def self.from_name(service_uri, name) # paranoid URI encoding to keep SMILES charges and brackets - c.inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(name, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").to_s.chomp - c.uri = File.join(CONFIG[:services]["opentox-compound"],URI.escape(c.inchi)) - c + inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(name, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").to_s.chomp + Compound.new File.join(service_uri,URI.escape(inchi)) end # Get InChI # @return [String] InChI string def to_inchi - @inchi + RestClientWrapper.get(@uri, :accept => 'chemical/x-inchi').to_s.chomp if @uri end # Get (canonical) smiles -- cgit v1.2.3 From 354aaa649e9eeed5d81793e09d9714b45063c147 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 8 Feb 2012 13:14:11 +0100 Subject: toxbank-investigation compatible version --- lib/compound.rb | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 974e46e..8761d50 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -1,5 +1,4 @@ -@@cactus_uri="http://cactus.nci.nih.gov/chemical/structure/" -@@ambit_uri="http://ambit.uni-plovdiv.bg:8080/ambit2/depict/cdk?search=" +CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/" module OpenTox @@ -12,21 +11,21 @@ module OpenTox # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound def self.from_smiles service_uri, smiles, subjectid=nil - Compound.new RestClientWrapper.post(service_uri, smiles, :content_type => 'chemical/x-daylight-smiles').to_s.chomp + Compound.new RestClient.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles', :subjectid => subjectid}) end # Create a compound from inchi string # @param [String] smiles InChI string # @return [OpenTox::Compound] Compound - def self.from_inchi(service_uri, inchi) - Compound.new RestClientWrapper.post(service_uri, inchi, :content_type => 'chemical/x-inchi').to_s.chomp + def self.from_inchi service_uri, inchi, subjectid=nil + Compound.new RestClient.post(service_uri, inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) end # Create a compound from sdf string # @param [String] smiles SDF string # @return [OpenTox::Compound] Compound - def self.from_sdf(service_uri, sdf) - Compound.new RestClientWrapper.post(service_uri, sdf, :content_type => 'chemical/x-mdl-sdfile').to_s.chomp + def self.from_sdf service_uri, sdf, subjectid=nil + Compound.new RestClient.post(service_uri, sdf, {:content_type => 'chemical/x-mdl-sdfile', :subjectid => subjectid}) end # Create a compound from name. Relies on an external service for name lookups. @@ -34,34 +33,32 @@ module OpenTox # compound = OpenTox::Compound.from_name("Benzene") # @param [String] name name can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound - def self.from_name(service_uri, name) - # paranoid URI encoding to keep SMILES charges and brackets - inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(name, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").to_s.chomp - Compound.new File.join(service_uri,URI.escape(inchi)) + def self.from_name service_uri, name, subjectid=nil + Compound.new RestClient.post(service_uri, name, {:content_type => 'text/plain', :subjectid => subjectid}) end # Get InChI # @return [String] InChI string def to_inchi - RestClientWrapper.get(@uri, :accept => 'chemical/x-inchi').to_s.chomp if @uri + get(:accept => 'chemical/x-inchi').to_s.chomp if @uri end # Get (canonical) smiles # @return [String] Smiles string def to_smiles - RestClientWrapper.get(@uri, :accept => 'chemical/x-daylight-smiles').chomp + get(:accept => 'chemical/x-daylight-smiles').chomp end # Get sdf # @return [String] SDF string def to_sdf - RestClientWrapper.get(@uri, :accept => 'chemical/x-mdl-sdfile').chomp + get(:accept => 'chemical/x-mdl-sdfile').chomp end # Get gif image # @return [image/gif] Image data def to_gif - RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/image") + get("#{CACTUS_URI}#{to_inchi}/image") end # Get png image @@ -69,7 +66,7 @@ module OpenTox # image = compound.to_png # @return [image/png] Image data def to_png - RestClientWrapper.get(File.join @uri, "image") + get(File.join @uri, "image") end # Get URI of compound image @@ -84,7 +81,7 @@ module OpenTox # @return [String] Compound names def to_names begin - RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/names").split("\n") + get("#{CACTUS_URI}#{to_inchi}/names").split("\n") rescue "not available" end -- cgit v1.2.3 From fa9069e13fb6b1c8bb4ebcdf82f1cf1c04ad71ca Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 23 Feb 2012 17:56:46 +0000 Subject: (partially) switched back to RestClientWrapper --- lib/compound.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 8761d50..ce0fdbf 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -11,21 +11,21 @@ module OpenTox # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound def self.from_smiles service_uri, smiles, subjectid=nil - Compound.new RestClient.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles', :subjectid => subjectid}) + Compound.new RestClientWrapper.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles', :subjectid => subjectid}) end # Create a compound from inchi string # @param [String] smiles InChI string # @return [OpenTox::Compound] Compound def self.from_inchi service_uri, inchi, subjectid=nil - Compound.new RestClient.post(service_uri, inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) + Compound.new RestClientWrapper.post(service_uri, inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) end # Create a compound from sdf string # @param [String] smiles SDF string # @return [OpenTox::Compound] Compound def self.from_sdf service_uri, sdf, subjectid=nil - Compound.new RestClient.post(service_uri, sdf, {:content_type => 'chemical/x-mdl-sdfile', :subjectid => subjectid}) + Compound.new RestClientWrapper.post(service_uri, sdf, {:content_type => 'chemical/x-mdl-sdfile', :subjectid => subjectid}) end # Create a compound from name. Relies on an external service for name lookups. @@ -34,7 +34,7 @@ module OpenTox # @param [String] name name can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound def self.from_name service_uri, name, subjectid=nil - Compound.new RestClient.post(service_uri, name, {:content_type => 'text/plain', :subjectid => subjectid}) + Compound.new RestClientWrapper.post(service_uri, name, {:content_type => 'text/plain', :subjectid => subjectid}) end # Get InChI -- cgit v1.2.3 From bf6834445feb6f93f0a20359462dbd1e7e89f4b8 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 12 Jul 2012 16:38:03 +0200 Subject: all opentox-client tests pass --- lib/compound.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index ce0fdbf..5992ee3 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -40,25 +40,25 @@ module OpenTox # Get InChI # @return [String] InChI string def to_inchi - get(:accept => 'chemical/x-inchi').to_s.chomp if @uri + RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-inchi'}).chomp end # Get (canonical) smiles # @return [String] Smiles string def to_smiles - get(:accept => 'chemical/x-daylight-smiles').chomp + RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-daylight-smiles'}).chomp end # Get sdf # @return [String] SDF string def to_sdf - get(:accept => 'chemical/x-mdl-sdfile').chomp + RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-mdl-sdfile'}).chomp end # Get gif image # @return [image/gif] Image data def to_gif - get("#{CACTUS_URI}#{to_inchi}/image") + RestClientWrapper.get("#{CACTUS_URI}#{to_inchi}/image") end # Get png image @@ -66,7 +66,7 @@ module OpenTox # image = compound.to_png # @return [image/png] Image data def to_png - get(File.join @uri, "image") + RestClientWrapper.get(File.join @uri, "image") end # Get URI of compound image @@ -81,7 +81,7 @@ module OpenTox # @return [String] Compound names def to_names begin - get("#{CACTUS_URI}#{to_inchi}/names").split("\n") + RestClientWrapper.get("#{CACTUS_URI}#{to_inchi}/names").split("\n") rescue "not available" end -- cgit v1.2.3 From 32ad3c8f6e1e16cfe9fd59a47df6b560ffb13ddd Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 1 Aug 2012 14:56:08 +0200 Subject: task error handling improved --- lib/compound.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 5992ee3..7d84a3c 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -83,7 +83,7 @@ module OpenTox begin RestClientWrapper.get("#{CACTUS_URI}#{to_inchi}/names").split("\n") rescue - "not available" + "CACTVS service not responding." end end -- cgit v1.2.3 From fdad1b78a4ec89c160bff710f0374614c22cda56 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Mon, 20 Aug 2012 14:36:39 +0200 Subject: cached compound representations, initial pubchem and chembl methods --- lib/compound.rb | 56 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 18 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 7d84a3c..127a6ee 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -11,6 +11,7 @@ module OpenTox # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound def self.from_smiles service_uri, smiles, subjectid=nil + @smiles = smiles Compound.new RestClientWrapper.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles', :subjectid => subjectid}) end @@ -18,6 +19,7 @@ module OpenTox # @param [String] smiles InChI string # @return [OpenTox::Compound] Compound def self.from_inchi service_uri, inchi, subjectid=nil + @inchi = inchi Compound.new RestClientWrapper.post(service_uri, inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) end @@ -33,60 +35,78 @@ module OpenTox # compound = OpenTox::Compound.from_name("Benzene") # @param [String] name name can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound + # def self.from_name service_uri, name, subjectid=nil - Compound.new RestClientWrapper.post(service_uri, name, {:content_type => 'text/plain', :subjectid => subjectid}) + @inchi = RestClientWrapper.get File.join(CACTUS_URI,URI.escape(name),"stdinchi") + Compound.new RestClientWrapper.post(service_uri, @inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) end # Get InChI # @return [String] InChI string - def to_inchi - RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-inchi'}).chomp + def inchi + @inchi ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-inchi'}).chomp + end + + # Get InChIKey + # @return [String] InChI string + def inchikey + @inchikey ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-inchikey'}).chomp end # Get (canonical) smiles # @return [String] Smiles string - def to_smiles - RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-daylight-smiles'}).chomp + def smiles + @smiles ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-daylight-smiles'}).chomp end # Get sdf # @return [String] SDF string - def to_sdf + def sdf RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-mdl-sdfile'}).chomp end # Get gif image # @return [image/gif] Image data - def to_gif - RestClientWrapper.get("#{CACTUS_URI}#{to_inchi}/image") + def gif + RestClientWrapper.get File.join(CACTUS_URI,inchi,"image") end # Get png image # @example - # image = compound.to_png + # image = compound.png # @return [image/png] Image data - def to_png + def png RestClientWrapper.get(File.join @uri, "image") end # Get URI of compound image # @return [String] Compound image URI - def to_image_uri + def image_uri File.join @uri, "image" end # Get all known compound names. Relies on an external service for name lookups. # @example - # names = compound.to_names + # names = compound.names # @return [String] Compound names - def to_names - begin - RestClientWrapper.get("#{CACTUS_URI}#{to_inchi}/names").split("\n") - rescue - "CACTVS service not responding." - end + def names + RestClientWrapper.get("#{CACTUS_URI}#{inchi}/names").split("\n") end + def cid + pug_uri = "http://pubchem.ncbi.nlm.nih.gov/rest/pug/" + @cid ||= RestClientWrapper.post(File.join(pug_uri, "compound", "inchi", "cids", "TXT"),{:inchi => inchi}).strip + end + + def chebi + end + + def chemblid + # https://www.ebi.ac.uk/chembldb/ws#individualCompoundByInChiKey + uri = "http://www.ebi.ac.uk/chemblws/compounds/smiles/#{smiles}.json" + @chemblid = JSON.parse(RestClientWrapper.get(uri))["compounds"].first["chemblId"] + end + =begin # Match a smarts string # @example -- cgit v1.2.3 From 781e7f714130dcd054d5d437f9c9f95c02cf9f7f Mon Sep 17 00:00:00 2001 From: Andreas Maunz Date: Thu, 6 Sep 2012 16:59:57 +0200 Subject: Added match routines --- lib/compound.rb | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 127a6ee..19d00fb 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -186,5 +186,44 @@ module OpenTox end end =end + + # Match an array of smarts strings, returns array with matching smarts + # @example + # compound = Compound.from_name("Benzene") + # compound.match(['cc','cN']) # returns ['cc'] + # @param [Array] smarts_array Array with Smarts strings + # @return [Array] Array with matching Smarts strings + def match(smarts_array) + obconversion = OpenBabel::OBConversion.new + obmol = OpenBabel::OBMol.new + obconversion.set_in_format('inchi') + obconversion.read_string(obmol,inchi) + smarts_pattern = OpenBabel::OBSmartsPattern.new + smarts_array.collect { |smarts| + smarts_pattern.init(smarts) + smarts if smarts_pattern.match(obmol) + }.compact + end + + # Match an array of smarts strings, returns hash with matching smarts as key and number of non-unique hits as value + # @param [Array] smarts_array Array with Smarts strings + # @return [Hash] Hash with matching smarts as key and number of non-unique hits as value + def match_hits(smarts_array) + obconversion = OpenBabel::OBConversion.new + obmol = OpenBabel::OBMol.new + obconversion.set_in_format('inchi') + obconversion.read_string(obmol,inchi) + smarts_pattern = OpenBabel::OBSmartsPattern.new + smarts_hits = {} + smarts_array.collect do |smarts| + smarts_pattern.init(smarts) + if smarts_pattern.match(obmol) + hits = smarts_pattern.get_map_list + smarts_hits[smarts] = hits.to_a.size + end + end + return smarts_hits + end + end end -- cgit v1.2.3 From fcb0574da3d9e52ad68669b7c84e0a8e029ad240 Mon Sep 17 00:00:00 2001 From: Andreas Maunz Date: Tue, 11 Sep 2012 12:57:00 +0200 Subject: Updated match routines --- lib/compound.rb | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 19d00fb..da16c85 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -187,28 +187,18 @@ module OpenTox end =end - # Match an array of smarts strings, returns array with matching smarts - # @example - # compound = Compound.from_name("Benzene") - # compound.match(['cc','cN']) # returns ['cc'] - # @param [Array] smarts_array Array with Smarts strings - # @return [Array] Array with matching Smarts strings - def match(smarts_array) - obconversion = OpenBabel::OBConversion.new - obmol = OpenBabel::OBMol.new - obconversion.set_in_format('inchi') - obconversion.read_string(obmol,inchi) - smarts_pattern = OpenBabel::OBSmartsPattern.new - smarts_array.collect { |smarts| - smarts_pattern.init(smarts) - smarts if smarts_pattern.match(obmol) - }.compact - end - # Match an array of smarts strings, returns hash with matching smarts as key and number of non-unique hits as value + + # Match an array of smarts strings, returns hash + # Keys: matching smarts, values: number of non-unique hits, or 1 # @param [Array] smarts_array Array with Smarts strings - # @return [Hash] Hash with matching smarts as key and number of non-unique hits as value - def match_hits(smarts_array) + # @param [Boolean] Whether non-unique hits or 1 should be produced + # @return [Array] Array with matching Smarts strings + # @example { + # compound = Compound.from_name("Benzene") + # compound.match(['cc','cN']) # returns { 'cc' => 12, 'cN' => 0 } + # } + def match_hits(smarts_array, use_hits=true) obconversion = OpenBabel::OBConversion.new obmol = OpenBabel::OBMol.new obconversion.set_in_format('inchi') @@ -218,12 +208,21 @@ module OpenTox smarts_array.collect do |smarts| smarts_pattern.init(smarts) if smarts_pattern.match(obmol) - hits = smarts_pattern.get_map_list - smarts_hits[smarts] = hits.to_a.size + if use_hits + hits = smarts_pattern.get_map_list + smarts_hits[smarts] = hits.to_a.size + else + smarts_hits[smarts] = 1 + end end end return smarts_hits end + # Provided for backward compatibility + def match(smarts_array) + match_hits(smarts_array,false) + end + end end -- cgit v1.2.3 From 147e1b7351975f19697e1e6ff4a6106fd38174ae Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 23 Jan 2013 12:53:43 +0100 Subject: url_for removed auto insertion of RDF::DC.modified --- lib/compound.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index da16c85..a0d6ec7 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -11,7 +11,7 @@ module OpenTox # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound def self.from_smiles service_uri, smiles, subjectid=nil - @smiles = smiles + #@smiles = smiles Compound.new RestClientWrapper.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles', :subjectid => subjectid}) end @@ -19,7 +19,7 @@ module OpenTox # @param [String] smiles InChI string # @return [OpenTox::Compound] Compound def self.from_inchi service_uri, inchi, subjectid=nil - @inchi = inchi + #@inchi = inchi Compound.new RestClientWrapper.post(service_uri, inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) end -- cgit v1.2.3 From a54db46684680d98311631804eca367cc949a715 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Tue, 26 Mar 2013 10:56:04 +0100 Subject: code cleanup and refactoring. --- lib/compound.rb | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index a0d6ec7..5d77dec 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -10,23 +10,21 @@ module OpenTox # compound = OpenTox::Compound.from_smiles("c1ccccc1") # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound - def self.from_smiles service_uri, smiles, subjectid=nil - #@smiles = smiles + def self.from_smiles smiles, subjectid=nil Compound.new RestClientWrapper.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles', :subjectid => subjectid}) end # Create a compound from inchi string # @param [String] smiles InChI string # @return [OpenTox::Compound] Compound - def self.from_inchi service_uri, inchi, subjectid=nil - #@inchi = inchi + def self.from_inchi inchi, subjectid=nil Compound.new RestClientWrapper.post(service_uri, inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) end # Create a compound from sdf string # @param [String] smiles SDF string # @return [OpenTox::Compound] Compound - def self.from_sdf service_uri, sdf, subjectid=nil + def self.from_sdf sdf, subjectid=nil Compound.new RestClientWrapper.post(service_uri, sdf, {:content_type => 'chemical/x-mdl-sdfile', :subjectid => subjectid}) end @@ -36,7 +34,7 @@ module OpenTox # @param [String] name name can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound # - def self.from_name service_uri, name, subjectid=nil + def self.from_name name, subjectid=nil @inchi = RestClientWrapper.get File.join(CACTUS_URI,URI.escape(name),"stdinchi") Compound.new RestClientWrapper.post(service_uri, @inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) end @@ -216,7 +214,7 @@ module OpenTox end end end - return smarts_hits + smarts_hits end # Provided for backward compatibility -- cgit v1.2.3 From 7def60bb82474c5e12bbc0362476752524e25d53 Mon Sep 17 00:00:00 2001 From: gebele Date: Wed, 15 May 2013 13:43:20 +0200 Subject: require openbabel --- lib/compound.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 5d77dec..294aa90 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -1,3 +1,4 @@ +require "openbabel" CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/" module OpenTox -- cgit v1.2.3 From 0df97a547ad623cff5d714076addbaa3cc73c53b Mon Sep 17 00:00:00 2001 From: davor Date: Tue, 28 May 2013 12:15:36 +0200 Subject: Replacing tab with two spaces. --- lib/compound.rb | 126 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 63 insertions(+), 63 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 294aa90..2eccdcd 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -4,7 +4,7 @@ CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/" module OpenTox # Ruby wrapper for OpenTox Compound Webservices (http://opentox.org/dev/apis/api-1.2/structure). - class Compound + class Compound # Create a compound from smiles string # @example @@ -40,57 +40,57 @@ module OpenTox Compound.new RestClientWrapper.post(service_uri, @inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) end - # Get InChI + # Get InChI # @return [String] InChI string - def inchi + def inchi @inchi ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-inchi'}).chomp - end + end - # Get InChIKey + # Get InChIKey # @return [String] InChI string - def inchikey + def inchikey @inchikey ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-inchikey'}).chomp - end + end - # Get (canonical) smiles + # Get (canonical) smiles # @return [String] Smiles string - def smiles + def smiles @smiles ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-daylight-smiles'}).chomp - end + end # Get sdf # @return [String] SDF string - def sdf + def sdf RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-mdl-sdfile'}).chomp - end + end # Get gif image # @return [image/gif] Image data - def gif + def gif RestClientWrapper.get File.join(CACTUS_URI,inchi,"image") - end + end # Get png image # @example # image = compound.png # @return [image/png] Image data - def png + def png RestClientWrapper.get(File.join @uri, "image") - end + end # Get URI of compound image # @return [String] Compound image URI - def image_uri + def image_uri File.join @uri, "image" - end + end # Get all known compound names. Relies on an external service for name lookups. # @example # names = compound.names # @return [String] Compound names - def names + def names RestClientWrapper.get("#{CACTUS_URI}#{inchi}/names").split("\n") - end + end def cid pug_uri = "http://pubchem.ncbi.nlm.nih.gov/rest/pug/" @@ -107,40 +107,40 @@ module OpenTox end =begin - # Match a smarts string + # Match a smarts string # @example # compound = OpenTox::Compound.from_name("Benzene") # compound.match?("cN") # returns false # @param [String] smarts Smarts string - def match?(smarts) - obconversion = OpenBabel::OBConversion.new - obmol = OpenBabel::OBMol.new - obconversion.set_in_format('inchi') - obconversion.read_string(obmol,@inchi) - smarts_pattern = OpenBabel::OBSmartsPattern.new - smarts_pattern.init(smarts) - smarts_pattern.match(obmol) - end - - # Match an array of smarts strings, returns array with matching smarts + def match?(smarts) + obconversion = OpenBabel::OBConversion.new + obmol = OpenBabel::OBMol.new + obconversion.set_in_format('inchi') + obconversion.read_string(obmol,@inchi) + smarts_pattern = OpenBabel::OBSmartsPattern.new + smarts_pattern.init(smarts) + smarts_pattern.match(obmol) + end + + # Match an array of smarts strings, returns array with matching smarts # @example # compound = OpenTox::Compound.from_name("Benzene") # compound.match(['cc','cN']) # returns ['cc'] # @param [Array] smarts_array Array with Smarts strings # @return [Array] Array with matching Smarts strings - def match(smarts_array) + def match(smarts_array) # avoid recreation of OpenBabel objects - obconversion = OpenBabel::OBConversion.new - obmol = OpenBabel::OBMol.new - obconversion.set_in_format('inchi') - obconversion.read_string(obmol,@inchi) - smarts_pattern = OpenBabel::OBSmartsPattern.new - smarts_array.collect do |smarts| + obconversion = OpenBabel::OBConversion.new + obmol = OpenBabel::OBMol.new + obconversion.set_in_format('inchi') + obconversion.read_string(obmol,@inchi) + smarts_pattern = OpenBabel::OBSmartsPattern.new + smarts_array.collect do |smarts| smarts_pattern.init(smarts) smarts if smarts_pattern.match(obmol) end.compact #smarts_array.collect { |s| s if match?(s)}.compact - end + end # Get URI of compound image with highlighted fragments # @@ -157,33 +157,33 @@ module OpenTox private # Convert sdf to inchi - def self.sdf2inchi(sdf) - Compound.obconversion(sdf,'sdf','inchi') - end + def self.sdf2inchi(sdf) + Compound.obconversion(sdf,'sdf','inchi') + end # Convert smiles to inchi - def self.smiles2inchi(smiles) - Compound.obconversion(smiles,'smi','inchi') - end + def self.smiles2inchi(smiles) + Compound.obconversion(smiles,'smi','inchi') + end # Convert smiles to canonical smiles - def self.smiles2cansmi(smiles) - Compound.obconversion(smiles,'smi','can') - end + def self.smiles2cansmi(smiles) + Compound.obconversion(smiles,'smi','can') + end # Convert identifier from OpenBabel input_format to OpenBabel output_format - def self.obconversion(identifier,input_format,output_format) - obconversion = OpenBabel::OBConversion.new - obmol = OpenBabel::OBMol.new - obconversion.set_in_and_out_formats input_format, output_format - obconversion.read_string obmol, identifier - case output_format - when /smi|can|inchi/ - obconversion.write_string(obmol).gsub(/\s/,'').chomp - else - obconversion.write_string(obmol) - end - end + def self.obconversion(identifier,input_format,output_format) + obconversion = OpenBabel::OBConversion.new + obmol = OpenBabel::OBMol.new + obconversion.set_in_and_out_formats input_format, output_format + obconversion.read_string obmol, identifier + case output_format + when /smi|can|inchi/ + obconversion.write_string(obmol).gsub(/\s/,'').chomp + else + obconversion.write_string(obmol) + end + end =end @@ -207,7 +207,7 @@ module OpenTox smarts_array.collect do |smarts| smarts_pattern.init(smarts) if smarts_pattern.match(obmol) - if use_hits + if use_hits hits = smarts_pattern.get_map_list smarts_hits[smarts] = hits.to_a.size else @@ -223,5 +223,5 @@ module OpenTox match_hits(smarts_array,false) end - end + end end -- cgit v1.2.3 From 0f770837cbfe17fe17fc86aa0d360c55e281c7f7 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 29 May 2013 15:10:46 +0200 Subject: modification date inserted at client to improve performance --- lib/compound.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 5d77dec..2bef69e 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -183,7 +183,6 @@ module OpenTox obconversion.write_string(obmol) end end -=end @@ -221,6 +220,7 @@ module OpenTox def match(smarts_array) match_hits(smarts_array,false) end +=end end end -- cgit v1.2.3 From 962773d59d94f8d16dae11b6290fdf30aaf09d7b Mon Sep 17 00:00:00 2001 From: rautenberg Date: Mon, 3 Jun 2013 15:25:33 +0200 Subject: make yard documentation full yard 0.8.6.1 compatible --- lib/compound.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 2eccdcd..a278244 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -16,14 +16,14 @@ module OpenTox end # Create a compound from inchi string - # @param [String] smiles InChI string + # @param inchi [String] smiles InChI string # @return [OpenTox::Compound] Compound def self.from_inchi inchi, subjectid=nil Compound.new RestClientWrapper.post(service_uri, inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) end # Create a compound from sdf string - # @param [String] smiles SDF string + # @param sdf [String] smiles SDF string # @return [OpenTox::Compound] Compound def self.from_sdf sdf, subjectid=nil Compound.new RestClientWrapper.post(service_uri, sdf, {:content_type => 'chemical/x-mdl-sdfile', :subjectid => subjectid}) @@ -32,9 +32,8 @@ module OpenTox # Create a compound from name. Relies on an external service for name lookups. # @example # compound = OpenTox::Compound.from_name("Benzene") - # @param [String] name name can be also an InChI/InChiKey, CAS number, etc + # @param name [String] can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound - # def self.from_name name, subjectid=nil @inchi = RestClientWrapper.get File.join(CACTUS_URI,URI.escape(name),"stdinchi") Compound.new RestClientWrapper.post(service_uri, @inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) @@ -191,7 +190,7 @@ module OpenTox # Match an array of smarts strings, returns hash # Keys: matching smarts, values: number of non-unique hits, or 1 # @param [Array] smarts_array Array with Smarts strings - # @param [Boolean] Whether non-unique hits or 1 should be produced + # @param use_hits [Boolean] Whether non-unique hits or 1 should be produced # @return [Array] Array with matching Smarts strings # @example { # compound = Compound.from_name("Benzene") -- cgit v1.2.3 From 498ec077e6b8290cf5efee08aaa6af7759ddccc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20G=C3=BCtlein?= Date: Thu, 6 Jun 2013 12:58:26 +0200 Subject: commenting cid, chemblid, and match_hits --- lib/compound.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index a278244..51ef96d 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -91,14 +91,18 @@ module OpenTox RestClientWrapper.get("#{CACTUS_URI}#{inchi}/names").split("\n") end + # @return [String] PubChem Compound Identifier (CID), derieved via restcall to pubchem def cid pug_uri = "http://pubchem.ncbi.nlm.nih.gov/rest/pug/" @cid ||= RestClientWrapper.post(File.join(pug_uri, "compound", "inchi", "cids", "TXT"),{:inchi => inchi}).strip end + # @todo def chebi + raise_internal_error "not yet implemented" end + # @return [String] ChEMBL database compound id, derieved via restcall to chembl def chemblid # https://www.ebi.ac.uk/chembldb/ws#individualCompoundByInChiKey uri = "http://www.ebi.ac.uk/chemblws/compounds/smiles/#{smiles}.json" @@ -191,11 +195,11 @@ module OpenTox # Keys: matching smarts, values: number of non-unique hits, or 1 # @param [Array] smarts_array Array with Smarts strings # @param use_hits [Boolean] Whether non-unique hits or 1 should be produced - # @return [Array] Array with matching Smarts strings - # @example { + # @return [Hash] Hash with matching Smarts as keys, nr-of-hits/1 as values + # @example # compound = Compound.from_name("Benzene") - # compound.match(['cc','cN']) # returns { 'cc' => 12, 'cN' => 0 } - # } + # compound.match(['cc','cN'],true) # returns { 'cc' => 12 }, 'cN' is not included because it does not match + # compound.match(['cc','cN'],false) # returns { 'cc' => 1 } def match_hits(smarts_array, use_hits=true) obconversion = OpenBabel::OBConversion.new obmol = OpenBabel::OBMol.new -- cgit v1.2.3 From bc9d5b9266e18d39ab5fd83db272bffde98c4161 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 19 Jun 2013 16:29:43 +0200 Subject: openbabel requirement removed. initial descriptor classes. --- lib/compound.rb | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 89bf840..daeabb9 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -1,4 +1,4 @@ -require "openbabel" +#require "openbabel" CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/" module OpenTox @@ -110,6 +110,27 @@ module OpenTox end =begin + # Match a smarts string + # @example + # compound = OpenTox::Compound.from_name("Benzene") + # compound.match?("cN") # returns false + # @param [String] smarts Smarts string + def match?(smarts) + matcher = Algorithm.new File.join($algorithm[:uri],"descriptor","smarts") + matcher.run :compound_uri => @uri, :smarts => smarts, :count => false + end + + # Match an array of smarts strings, returns array with matching smarts + # @example + # compound = OpenTox::Compound.from_name("Benzene") + # compound.match(['cc','cN']) # returns ['cc'] + # @param [Array] smarts_array Array with Smarts strings + # @return [Array] Array with matching Smarts strings + def match(smarts_array) + matcher = Algorithm.new File.join($algorithm[:uri],"descriptor","smarts") + matcher.run :compound_uri => @uri, :smarts => smarts_array, :count => false + end + # Match a smarts string # @example # compound = OpenTox::Compound.from_name("Benzene") -- cgit v1.2.3 From 6c35e3f8369ba96cb251eac487424bd949fdcf6c Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Tue, 2 Jul 2013 19:23:01 +0200 Subject: Algorithms and Models are modules instead of classes. --- lib/compound.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index daeabb9..9bd2066 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -6,6 +6,10 @@ module OpenTox # Ruby wrapper for OpenTox Compound Webservices (http://opentox.org/dev/apis/api-1.2/structure). class Compound + def ==(c) + @uri == c.uri + end + # Create a compound from smiles string # @example # compound = OpenTox::Compound.from_smiles("c1ccccc1") -- cgit v1.2.3 From 3262e3cf2ed1ce896dcd11d9c1bde5222ea720ce Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 4 Jul 2013 18:17:56 +0200 Subject: Algorithm::Generic and Model::Generic classes. --- lib/compound.rb | 139 -------------------------------------------------------- 1 file changed, 139 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 9bd2066..82f0d73 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -112,144 +112,5 @@ module OpenTox uri = "http://www.ebi.ac.uk/chemblws/compounds/smiles/#{smiles}.json" @chemblid = JSON.parse(RestClientWrapper.get(uri))["compounds"].first["chemblId"] end - -=begin - # Match a smarts string - # @example - # compound = OpenTox::Compound.from_name("Benzene") - # compound.match?("cN") # returns false - # @param [String] smarts Smarts string - def match?(smarts) - matcher = Algorithm.new File.join($algorithm[:uri],"descriptor","smarts") - matcher.run :compound_uri => @uri, :smarts => smarts, :count => false - end - - # Match an array of smarts strings, returns array with matching smarts - # @example - # compound = OpenTox::Compound.from_name("Benzene") - # compound.match(['cc','cN']) # returns ['cc'] - # @param [Array] smarts_array Array with Smarts strings - # @return [Array] Array with matching Smarts strings - def match(smarts_array) - matcher = Algorithm.new File.join($algorithm[:uri],"descriptor","smarts") - matcher.run :compound_uri => @uri, :smarts => smarts_array, :count => false - end - - # Match a smarts string - # @example - # compound = OpenTox::Compound.from_name("Benzene") - # compound.match?("cN") # returns false - # @param [String] smarts Smarts string - def match?(smarts) - obconversion = OpenBabel::OBConversion.new - obmol = OpenBabel::OBMol.new - obconversion.set_in_format('inchi') - obconversion.read_string(obmol,@inchi) - smarts_pattern = OpenBabel::OBSmartsPattern.new - smarts_pattern.init(smarts) - smarts_pattern.match(obmol) - end - - # Match an array of smarts strings, returns array with matching smarts - # @example - # compound = OpenTox::Compound.from_name("Benzene") - # compound.match(['cc','cN']) # returns ['cc'] - # @param [Array] smarts_array Array with Smarts strings - # @return [Array] Array with matching Smarts strings - def match(smarts_array) - # avoid recreation of OpenBabel objects - obconversion = OpenBabel::OBConversion.new - obmol = OpenBabel::OBMol.new - obconversion.set_in_format('inchi') - obconversion.read_string(obmol,@inchi) - smarts_pattern = OpenBabel::OBSmartsPattern.new - smarts_array.collect do |smarts| - smarts_pattern.init(smarts) - smarts if smarts_pattern.match(obmol) - end.compact - #smarts_array.collect { |s| s if match?(s)}.compact - end - - # Get URI of compound image with highlighted fragments - # - # @param [Array] activating Array with activating Smarts strings - # @param [Array] deactivating Array with deactivating Smarts strings - # @return [String] URI for compound image with highlighted fragments - def matching_smarts_image_uri(activating, deactivating) - activating_smarts = URI.encode "\"#{activating.join("\"/\"")}\"" - deactivating_smarts = URI.encode "\"#{deactivating.join("\"/\"")}\"" - File.join @uri, "smarts/activating", URI.encode(activating_smarts),"deactivating", URI.encode(deactivating_smarts) - end - - - private - - # Convert sdf to inchi - def self.sdf2inchi(sdf) - Compound.obconversion(sdf,'sdf','inchi') - end - - # Convert smiles to inchi - def self.smiles2inchi(smiles) - Compound.obconversion(smiles,'smi','inchi') - end - - # Convert smiles to canonical smiles - def self.smiles2cansmi(smiles) - Compound.obconversion(smiles,'smi','can') - end - - # Convert identifier from OpenBabel input_format to OpenBabel output_format - def self.obconversion(identifier,input_format,output_format) - obconversion = OpenBabel::OBConversion.new - obmol = OpenBabel::OBMol.new - obconversion.set_in_and_out_formats input_format, output_format - obconversion.read_string obmol, identifier - case output_format - when /smi|can|inchi/ - obconversion.write_string(obmol).gsub(/\s/,'').chomp - else - obconversion.write_string(obmol) - end - end - - - - # Match an array of smarts strings, returns hash - # Keys: matching smarts, values: number of non-unique hits, or 1 - # @param [Array] smarts_array Array with Smarts strings - # @param use_hits [Boolean] Whether non-unique hits or 1 should be produced - # @return [Hash] Hash with matching Smarts as keys, nr-of-hits/1 as values - # @example - # compound = Compound.from_name("Benzene") - # compound.match(['cc','cN'],true) # returns { 'cc' => 12 }, 'cN' is not included because it does not match - # compound.match(['cc','cN'],false) # returns { 'cc' => 1 } - def match_hits(smarts_array, use_hits=true) - obconversion = OpenBabel::OBConversion.new - obmol = OpenBabel::OBMol.new - obconversion.set_in_format('inchi') - obconversion.read_string(obmol,inchi) - smarts_pattern = OpenBabel::OBSmartsPattern.new - smarts_hits = {} - smarts_array.collect do |smarts| - smarts_pattern.init(smarts) - if smarts_pattern.match(obmol) - if use_hits - hits = smarts_pattern.get_map_list - smarts_hits[smarts] = hits.to_a.size - else - smarts_hits[smarts] = 1 - end - end - end - smarts_hits - end - - # Provided for backward compatibility - def match(smarts_array) - match_hits(smarts_array,false) - end -=end - end end -- cgit v1.2.3 From ddb83b4302e8628b333402d24e3e05fc90b3faef Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 10 Jul 2013 14:36:39 +0200 Subject: subjectids partially removed --- lib/compound.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 82f0d73..9d99ae9 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -1,4 +1,3 @@ -#require "openbabel" CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/" module OpenTox @@ -15,22 +14,22 @@ module OpenTox # compound = OpenTox::Compound.from_smiles("c1ccccc1") # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound - def self.from_smiles smiles, subjectid=nil - Compound.new RestClientWrapper.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles', :subjectid => subjectid}) + def self.from_smiles smiles + Compound.new RestClientWrapper.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles'}) end # Create a compound from inchi string # @param inchi [String] smiles InChI string # @return [OpenTox::Compound] Compound - def self.from_inchi inchi, subjectid=nil - Compound.new RestClientWrapper.post(service_uri, inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) + def self.from_inchi inchi + Compound.new RestClientWrapper.post(service_uri, inchi, {:content_type => 'chemical/x-inchi'}) end # Create a compound from sdf string # @param sdf [String] smiles SDF string # @return [OpenTox::Compound] Compound - def self.from_sdf sdf, subjectid=nil - Compound.new RestClientWrapper.post(service_uri, sdf, {:content_type => 'chemical/x-mdl-sdfile', :subjectid => subjectid}) + def self.from_sdf sdf + Compound.new RestClientWrapper.post(service_uri, sdf, {:content_type => 'chemical/x-mdl-sdfile'}) end # Create a compound from name. Relies on an external service for name lookups. @@ -38,9 +37,9 @@ module OpenTox # compound = OpenTox::Compound.from_name("Benzene") # @param name [String] can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound - def self.from_name name, subjectid=nil + def self.from_name name @inchi = RestClientWrapper.get File.join(CACTUS_URI,URI.escape(name),"stdinchi") - Compound.new RestClientWrapper.post(service_uri, @inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid}) + Compound.new RestClientWrapper.post(service_uri, @inchi, {:content_type => 'chemical/x-inchi'}) end # Get InChI -- cgit v1.2.3 From 0172f39bf3638919735d0bcd2b6597c5885a05d7 Mon Sep 17 00:00:00 2001 From: mguetlein Date: Fri, 10 Oct 2014 12:35:50 +0200 Subject: fix error msg --- lib/compound.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 9d99ae9..f63e127 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -102,7 +102,7 @@ module OpenTox # @todo def chebi - raise_internal_error "not yet implemented" + internal_server_error "not yet implemented" end # @return [String] ChEMBL database compound id, derieved via restcall to chembl -- cgit v1.2.3 From f850712765a67bf31b1327401e3eddf59e3e6f50 Mon Sep 17 00:00:00 2001 From: ch Date: Sun, 12 Jul 2015 12:14:13 +0200 Subject: initial dataset tests --- lib/compound.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index f63e127..82ea94e 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -5,8 +5,13 @@ module OpenTox # Ruby wrapper for OpenTox Compound Webservices (http://opentox.org/dev/apis/api-1.2/structure). class Compound + def initialize uri + @data = {} + @data["uri"] = uri + end + def ==(c) - @uri == c.uri + @data["uri"] == c.uri end # Create a compound from smiles string @@ -45,25 +50,25 @@ module OpenTox # Get InChI # @return [String] InChI string def inchi - @inchi ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-inchi'}).chomp + @inchi ||= RestClientWrapper.get(@data["uri"],{},{:accept => 'chemical/x-inchi'}).chomp end # Get InChIKey # @return [String] InChI string def inchikey - @inchikey ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-inchikey'}).chomp + @inchikey ||= RestClientWrapper.get(@data["uri"],{},{:accept => 'chemical/x-inchikey'}).chomp end # Get (canonical) smiles # @return [String] Smiles string def smiles - @smiles ||= RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-daylight-smiles'}).chomp + @smiles ||= RestClientWrapper.get(@data["uri"],{},{:accept => 'chemical/x-daylight-smiles'}).chomp end # Get sdf # @return [String] SDF string def sdf - RestClientWrapper.get(@uri,{},{:accept => 'chemical/x-mdl-sdfile'}).chomp + RestClientWrapper.get(@data["uri"],{},{:accept => 'chemical/x-mdl-sdfile'}).chomp end # Get gif image @@ -77,13 +82,13 @@ module OpenTox # image = compound.png # @return [image/png] Image data def png - RestClientWrapper.get(File.join @uri, "image") + RestClientWrapper.get(File.join @data["uri"], "image") end # Get URI of compound image # @return [String] Compound image URI def image_uri - File.join @uri, "image" + File.join @data["uri"], "image" end # Get all known compound names. Relies on an external service for name lookups. -- cgit v1.2.3 From 1c74a684b8b2992d7e6fce5f1a4677d397ec4dd6 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Sat, 18 Jul 2015 08:52:39 +0200 Subject: dataset tests pass --- lib/compound.rb | 55 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 21 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 82ea94e..b588c75 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -1,17 +1,15 @@ CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/" +require 'openbabel' module OpenTox # Ruby wrapper for OpenTox Compound Webservices (http://opentox.org/dev/apis/api-1.2/structure). class Compound - def initialize uri - @data = {} - @data["uri"] = uri - end + attr_reader :inchi - def ==(c) - @data["uri"] == c.uri + def initialize inchi + @inchi = inchi end # Create a compound from smiles string @@ -20,21 +18,21 @@ module OpenTox # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound def self.from_smiles smiles - Compound.new RestClientWrapper.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles'}) + OpenTox::Compound.new obconversion(smiles,"smi","inchi") end # Create a compound from inchi string # @param inchi [String] smiles InChI string # @return [OpenTox::Compound] Compound def self.from_inchi inchi - Compound.new RestClientWrapper.post(service_uri, inchi, {:content_type => 'chemical/x-inchi'}) + OpenTox::Compound.new inchi end # Create a compound from sdf string # @param sdf [String] smiles SDF string # @return [OpenTox::Compound] Compound def self.from_sdf sdf - Compound.new RestClientWrapper.post(service_uri, sdf, {:content_type => 'chemical/x-mdl-sdfile'}) + OpenTox::Compound.new obconversion(sdf,"sdf","inchi") end # Create a compound from name. Relies on an external service for name lookups. @@ -43,32 +41,25 @@ module OpenTox # @param name [String] can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound def self.from_name name - @inchi = RestClientWrapper.get File.join(CACTUS_URI,URI.escape(name),"stdinchi") - Compound.new RestClientWrapper.post(service_uri, @inchi, {:content_type => 'chemical/x-inchi'}) - end - - # Get InChI - # @return [String] InChI string - def inchi - @inchi ||= RestClientWrapper.get(@data["uri"],{},{:accept => 'chemical/x-inchi'}).chomp + OpenTox::Compound.new RestClientWrapper.get File.join(CACTUS_URI,URI.escape(name),"stdinchi") end # Get InChIKey # @return [String] InChI string def inchikey - @inchikey ||= RestClientWrapper.get(@data["uri"],{},{:accept => 'chemical/x-inchikey'}).chomp + obconversion(@inchi,"inchi","inchikey") end # Get (canonical) smiles # @return [String] Smiles string def smiles - @smiles ||= RestClientWrapper.get(@data["uri"],{},{:accept => 'chemical/x-daylight-smiles'}).chomp + obconversion(@inchi,"inchi","smi") # "can" gives nonn-canonical smiles?? end # Get sdf # @return [String] SDF string def sdf - RestClientWrapper.get(@data["uri"],{},{:accept => 'chemical/x-mdl-sdfile'}).chomp + obconversion(@inchi,"inchi","sdf") end # Get gif image @@ -82,14 +73,16 @@ module OpenTox # image = compound.png # @return [image/png] Image data def png - RestClientWrapper.get(File.join @data["uri"], "image") + obconversion(@inchi,"inchi","_png2") end +=begin # Get URI of compound image # @return [String] Compound image URI def image_uri File.join @data["uri"], "image" end +=end # Get all known compound names. Relies on an external service for name lookups. # @example @@ -116,5 +109,25 @@ module OpenTox uri = "http://www.ebi.ac.uk/chemblws/compounds/smiles/#{smiles}.json" @chemblid = JSON.parse(RestClientWrapper.get(uri))["compounds"].first["chemblId"] end + + private + + def self.obconversion(identifier,input_format,output_format,option=nil) + obconversion = OpenBabel::OBConversion.new + obconversion.set_options(option, OpenBabel::OBConversion::OUTOPTIONS) if option + obmol = OpenBabel::OBMol.new + obconversion.set_in_and_out_formats input_format, output_format + obconversion.read_string obmol, identifier + case output_format + when /smi|can|inchi/ + obconversion.write_string(obmol).gsub(/\s/,'').chomp + else + obconversion.write_string(obmol) + end + end + + def obconversion(identifier,input_format,output_format,option=nil) + self.class.obconversion(identifier,input_format,output_format,option=nil) + end end end -- cgit v1.2.3 From 51e7a29c8aac568ff8ef04de5b15d2f6db8f66da Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Sun, 19 Jul 2015 21:26:03 +0200 Subject: lazar predictions working in principle --- lib/compound.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index b588c75..6cc4707 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -12,6 +12,10 @@ module OpenTox @inchi = inchi end + def == compound + self.inchi == compound.inchi + end + # Create a compound from smiles string # @example # compound = OpenTox::Compound.from_smiles("c1ccccc1") -- cgit v1.2.3 From cd1cba67830505cd2d23ec83e64c0beed42a9f28 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 22 Jul 2015 20:08:12 +0200 Subject: mongo batch import workaround --- lib/compound.rb | 86 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 35 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 6cc4707..4a8089b 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -1,16 +1,20 @@ CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/" require 'openbabel' +require "base64" module OpenTox - # Ruby wrapper for OpenTox Compound Webservices (http://opentox.org/dev/apis/api-1.2/structure). class Compound - attr_reader :inchi - - def initialize inchi - @inchi = inchi - end + field :inchi, type: String + attr_readonly :inchi + field :smiles, type: String + field :inchikey, type: String + field :names, type: Array + field :cid, type: String + field :chemblid, type: String + field :image_id, type: BSON::ObjectId + field :sdf_id, type: BSON::ObjectId def == compound self.inchi == compound.inchi @@ -22,21 +26,23 @@ module OpenTox # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound def self.from_smiles smiles - OpenTox::Compound.new obconversion(smiles,"smi","inchi") + # do not store smiles because it might be noncanonical + Compound.find_or_create_by :inchi => obconversion(smiles,"smi","inchi") end # Create a compound from inchi string # @param inchi [String] smiles InChI string # @return [OpenTox::Compound] Compound def self.from_inchi inchi - OpenTox::Compound.new inchi + Compound.find_or_create_by :inchi => inchi end # Create a compound from sdf string # @param sdf [String] smiles SDF string # @return [OpenTox::Compound] Compound def self.from_sdf sdf - OpenTox::Compound.new obconversion(sdf,"sdf","inchi") + # do not store sdf because it might be 2D + Compound.find_or_create_by :inchi => obconversion(sdf,"sdf","inchi") end # Create a compound from name. Relies on an external service for name lookups. @@ -45,31 +51,32 @@ module OpenTox # @param name [String] can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound def self.from_name name - OpenTox::Compound.new RestClientWrapper.get File.join(CACTUS_URI,URI.escape(name),"stdinchi") + Compound.find_or_create_by :inchi => RestClientWrapper.get(File.join(CACTUS_URI,URI.escape(name),"stdinchi")) end # Get InChIKey # @return [String] InChI string def inchikey - obconversion(@inchi,"inchi","inchikey") + update(:inchikey => obconversion(inchi,"inchi","inchikey")) unless self["inchikey"] + self["inchikey"] end # Get (canonical) smiles # @return [String] Smiles string def smiles - obconversion(@inchi,"inchi","smi") # "can" gives nonn-canonical smiles?? + update(:smiles => obconversion(inchi,"inchi","smi")) unless self["smiles"] # should give canonical smiles, "can" seems to give incorrect results + self["smiles"] end # Get sdf # @return [String] SDF string def sdf - obconversion(@inchi,"inchi","sdf") - end - - # Get gif image - # @return [image/gif] Image data - def gif - RestClientWrapper.get File.join(CACTUS_URI,inchi,"image") + if sdf_id.nil? + sdf = obconversion(inchi,"inchi","sdf") + file = Mongo::Grid::File.new(sdf, :filename => "#{id}.sdf",:content_type => "chemical/x-mdl-sdfile") + sdf_id = $gridfs.insert_one file + end + $gridfs.find_one(_id: sdf_id).data end # Get png image @@ -77,41 +84,37 @@ module OpenTox # image = compound.png # @return [image/png] Image data def png - obconversion(@inchi,"inchi","_png2") - end + if image_id.nil? + png = obconversion(inchi,"inchi","_png2") + file = Mongo::Grid::File.new(Base64.encode64(png), :filename => "#{id}.png", :content_type => "image/png") + update(:image_id => $gridfs.insert_one(file)) + end + Base64.decode64($gridfs.find_one(_id: image_id).data) -=begin - # Get URI of compound image - # @return [String] Compound image URI - def image_uri - File.join @data["uri"], "image" end -=end # Get all known compound names. Relies on an external service for name lookups. # @example # names = compound.names # @return [String] Compound names def names - RestClientWrapper.get("#{CACTUS_URI}#{inchi}/names").split("\n") + update(:names => RestClientWrapper.get("#{CACTUS_URI}#{inchi}/names").split("\n")) unless self["names"] + self["names"] end # @return [String] PubChem Compound Identifier (CID), derieved via restcall to pubchem def cid pug_uri = "http://pubchem.ncbi.nlm.nih.gov/rest/pug/" - @cid ||= RestClientWrapper.post(File.join(pug_uri, "compound", "inchi", "cids", "TXT"),{:inchi => inchi}).strip - end - - # @todo - def chebi - internal_server_error "not yet implemented" + update(:cid => RestClientWrapper.post(File.join(pug_uri, "compound", "inchi", "cids", "TXT"),{:inchi => inchi}).strip) unless self["cid"] + self["cid"] end # @return [String] ChEMBL database compound id, derieved via restcall to chembl def chemblid # https://www.ebi.ac.uk/chembldb/ws#individualCompoundByInChiKey uri = "http://www.ebi.ac.uk/chemblws/compounds/smiles/#{smiles}.json" - @chemblid = JSON.parse(RestClientWrapper.get(uri))["compounds"].first["chemblId"] + update(:chemblid => JSON.parse(RestClientWrapper.get(uri))["compounds"].first["chemblId"]) unless self["chemblid"] + self["chemblid"] end private @@ -125,6 +128,19 @@ module OpenTox case output_format when /smi|can|inchi/ obconversion.write_string(obmol).gsub(/\s/,'').chomp + when /sdf/ + OpenBabel::OBOp.find_type("Gen3D").do(obmol) + sdf = obconversion.write_string(obmol) + if sdf.match(/.nan/) + $logger.warn "3D generation failed for compound #{compound.inchi}, trying to calculate 2D structure" + OpenBabel::OBOp.find_type("Gen2D").do(obmol) + sdf = obconversion.write_string(obmol) + if sdf.match(/.nan/) + $logger.warn "2D generation failed for compound #{compound.inchi}" + sdf = nil + end + end + sdf else obconversion.write_string(obmol) end -- cgit v1.2.3 From 3cea6abe3606ea586b733e943737f77d58f215f9 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Mon, 27 Jul 2015 20:51:25 +0200 Subject: reasonable query performace for data_entries --- lib/compound.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 4a8089b..93f609f 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -15,10 +15,12 @@ module OpenTox field :chemblid, type: String field :image_id, type: BSON::ObjectId field :sdf_id, type: BSON::ObjectId + #belongs_to :dataset + #belongs_to :data_entry - def == compound - self.inchi == compound.inchi - end + #def == compound + #self.inchi == compound.inchi + #end # Create a compound from smiles string # @example -- cgit v1.2.3 From e68c69f90036bb7c47c57acb1ee3652b73c835c1 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Fri, 31 Jul 2015 10:59:53 +0200 Subject: descriptor tests working --- lib/compound.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 93f609f..4d36915 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -73,12 +73,13 @@ module OpenTox # Get sdf # @return [String] SDF string def sdf - if sdf_id.nil? + if self.sdf_id.nil? sdf = obconversion(inchi,"inchi","sdf") file = Mongo::Grid::File.new(sdf, :filename => "#{id}.sdf",:content_type => "chemical/x-mdl-sdfile") sdf_id = $gridfs.insert_one file + update :sdf_id => sdf_id end - $gridfs.find_one(_id: sdf_id).data + $gridfs.find_one(_id: self.sdf_id).data end # Get png image @@ -86,12 +87,12 @@ module OpenTox # image = compound.png # @return [image/png] Image data def png - if image_id.nil? + if self.image_id.nil? png = obconversion(inchi,"inchi","_png2") file = Mongo::Grid::File.new(Base64.encode64(png), :filename => "#{id}.png", :content_type => "image/png") update(:image_id => $gridfs.insert_one(file)) end - Base64.decode64($gridfs.find_one(_id: image_id).data) + Base64.decode64($gridfs.find_one(_id: self.image_id).data) end @@ -134,11 +135,11 @@ module OpenTox OpenBabel::OBOp.find_type("Gen3D").do(obmol) sdf = obconversion.write_string(obmol) if sdf.match(/.nan/) - $logger.warn "3D generation failed for compound #{compound.inchi}, trying to calculate 2D structure" + $logger.warn "3D generation failed for compound #{identifier}, trying to calculate 2D structure" OpenBabel::OBOp.find_type("Gen2D").do(obmol) sdf = obconversion.write_string(obmol) if sdf.match(/.nan/) - $logger.warn "2D generation failed for compound #{compound.inchi}" + $logger.warn "2D generation failed for compound #{identifier}" sdf = nil end end -- cgit v1.2.3 From f93333d7f5df30875eae9135f4b5e65a98d923b6 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Fri, 31 Jul 2015 19:25:13 +0200 Subject: intermediary commit --- lib/compound.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 4d36915..0c27553 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -1,3 +1,7 @@ +# TODO: check +# *** Open Babel Error in ParseFile +# Could not find contribution data file. +# 3d creation?? CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/" require 'openbabel' require "base64" -- cgit v1.2.3 From 04af01b8135ea147e9ce253e5526e3ee3adcc675 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Fri, 7 Aug 2015 19:50:09 +0200 Subject: initial k-nn weighted average implementation --- lib/compound.rb | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 0c27553..4d292f1 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -1,7 +1,7 @@ # TODO: check # *** Open Babel Error in ParseFile # Could not find contribution data file. -# 3d creation?? + CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/" require 'openbabel' require "base64" @@ -9,6 +9,34 @@ require "base64" module OpenTox class Compound + include OpenTox + +# OpenBabel FP4 fingerprints +# OpenBabel http://open-babel.readthedocs.org/en/latest/Fingerprints/intro.html +# TODO store in DB +fp4 = FingerprintSmarts.find +unless fp4 + fp4 = [] + File.open(File.join(File.dirname(__FILE__),"SMARTS_InteLigand.txt")).each do |l| + l.strip! + unless l.empty? or l.match /^#/ + name,smarts = l.split(': ') + fp4 << OpenTox::FingerprintSmarts.find_or_create_by(:name => name, :smarts => smarts) unless smarts.nil? + end + end +end +FP4 = fp4 + +# TODO investigate other types of fingerprints (MACCS) +# OpenBabel http://open-babel.readthedocs.org/en/latest/Fingerprints/intro.html +# http://www.dalkescientific.com/writings/diary/archive/2008/06/26/fingerprint_background.html +# OpenBabel MNA http://openbabel.org/docs/dev/FileFormats/Multilevel_Neighborhoods_of_Atoms_(MNA).html#multilevel-neighborhoods-of-atoms-mna +# Morgan ECFP, FCFP +# http://cdk.github.io/cdk/1.5/docs/api/org/openscience/cdk/fingerprint/CircularFingerprinter.html +# http://www.rdkit.org/docs/GettingStartedInPython.html +# Chemfp +# https://chemfp.readthedocs.org/en/latest/using-tools.html +# CACTVS/PubChem field :inchi, type: String attr_readonly :inchi @@ -19,6 +47,8 @@ module OpenTox field :chemblid, type: String field :image_id, type: BSON::ObjectId field :sdf_id, type: BSON::ObjectId + field :fp4, type: Array + field :fp4_size, type: Integer #belongs_to :dataset #belongs_to :data_entry @@ -26,6 +56,22 @@ module OpenTox #self.inchi == compound.inchi #end + def self.find_or_create_by params + compound = self.find_or_initialize_by params + unless compound.fp4 + compound.fp4_size = 0 + compound.fp4 = [] + Algorithm::Descriptor.smarts_match(compound, FP4.collect{|f| f.smarts}).each_with_index do |m,i| + if m > 0 + compound.fp4 << FP4[i].id + compound.fp4_size += 1 + end + end + end + compound.save + compound + end + # Create a compound from smiles string # @example # compound = OpenTox::Compound.from_smiles("c1ccccc1") @@ -124,6 +170,29 @@ module OpenTox self["chemblid"] end + def neighbors threshold=0.3 + # from http://blog.matt-swain.com/post/87093745652/chemical-similarity-search-in-mongodb + qn = fp4.size + qmin = qn * threshold + qmax = qn / threshold + #not sure if it is worth the effort of keeping feature counts up to date (compound deletions, additions, ...) + #reqbits = [count['_id'] for count in db.mfp_counts.find({'_id': {'$in': qfp}}).sort('count', 1).limit(qn - qmin + 1)] + aggregate = [ + #{'$match': {'mfp.count': {'$gte': qmin, '$lte': qmax}, 'mfp.bits': {'$in': reqbits}}}, + {'$project': { + 'tanimoto': {'$let': { + 'vars': {'common': {'$size': {'$setIntersection': ['$fp4', fp4]}}}, + 'in': {'$divide': ['$$common', {'$subtract': [{'$add': [qn, '$fp4_size']}, '$$common']}]} + }}, + '_id': 1 + }}, + {'$match': {'tanimoto': {'$gte': threshold}}}, + {'$sort': {'tanimoto': -1}} + ] + + $mongo["compounds"].aggregate(aggregate).collect { |r| [Compound.find(r["_id"]), r["tanimoto"]]} + end + private def self.obconversion(identifier,input_format,output_format,option=nil) -- cgit v1.2.3 From ef76c077fd39d31fc795b842c32575f6afb9fdb2 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Sun, 9 Aug 2015 13:42:54 +0200 Subject: customized prediction algorithms implemented --- lib/compound.rb | 59 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 4d292f1..4e29938 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -11,32 +11,31 @@ module OpenTox class Compound include OpenTox -# OpenBabel FP4 fingerprints -# OpenBabel http://open-babel.readthedocs.org/en/latest/Fingerprints/intro.html -# TODO store in DB -fp4 = FingerprintSmarts.find -unless fp4 - fp4 = [] - File.open(File.join(File.dirname(__FILE__),"SMARTS_InteLigand.txt")).each do |l| - l.strip! - unless l.empty? or l.match /^#/ - name,smarts = l.split(': ') - fp4 << OpenTox::FingerprintSmarts.find_or_create_by(:name => name, :smarts => smarts) unless smarts.nil? + # OpenBabel FP4 fingerprints + # OpenBabel http://open-babel.readthedocs.org/en/latest/Fingerprints/intro.html + fp4 = FingerprintSmarts.all + unless fp4 + fp4 = [] + File.open(File.join(File.dirname(__FILE__),"SMARTS_InteLigand.txt")).each do |l| + l.strip! + unless l.empty? or l.match /^#/ + name,smarts = l.split(': ') + fp4 << OpenTox::FingerprintSmarts.find_or_create_by(:name => name, :smarts => smarts) unless smarts.nil? + end + end end - end -end -FP4 = fp4 - -# TODO investigate other types of fingerprints (MACCS) -# OpenBabel http://open-babel.readthedocs.org/en/latest/Fingerprints/intro.html -# http://www.dalkescientific.com/writings/diary/archive/2008/06/26/fingerprint_background.html -# OpenBabel MNA http://openbabel.org/docs/dev/FileFormats/Multilevel_Neighborhoods_of_Atoms_(MNA).html#multilevel-neighborhoods-of-atoms-mna -# Morgan ECFP, FCFP -# http://cdk.github.io/cdk/1.5/docs/api/org/openscience/cdk/fingerprint/CircularFingerprinter.html -# http://www.rdkit.org/docs/GettingStartedInPython.html -# Chemfp -# https://chemfp.readthedocs.org/en/latest/using-tools.html -# CACTVS/PubChem + FP4 = fp4 + + # TODO investigate other types of fingerprints (MACCS) + # OpenBabel http://open-babel.readthedocs.org/en/latest/Fingerprints/intro.html + # http://www.dalkescientific.com/writings/diary/archive/2008/06/26/fingerprint_background.html + # OpenBabel MNA http://openbabel.org/docs/dev/FileFormats/Multilevel_Neighborhoods_of_Atoms_(MNA).html#multilevel-neighborhoods-of-atoms-mna + # Morgan ECFP, FCFP + # http://cdk.github.io/cdk/1.5/docs/api/org/openscience/cdk/fingerprint/CircularFingerprinter.html + # http://www.rdkit.org/docs/GettingStartedInPython.html + # Chemfp + # https://chemfp.readthedocs.org/en/latest/using-tools.html + # CACTVS/PubChem field :inchi, type: String attr_readonly :inchi @@ -170,15 +169,16 @@ FP4 = fp4 self["chemblid"] end - def neighbors threshold=0.3 + def neighbors threshold=0.7 # from http://blog.matt-swain.com/post/87093745652/chemical-similarity-search-in-mongodb qn = fp4.size - qmin = qn * threshold - qmax = qn / threshold + #qmin = qn * threshold + #qmax = qn / threshold #not sure if it is worth the effort of keeping feature counts up to date (compound deletions, additions, ...) #reqbits = [count['_id'] for count in db.mfp_counts.find({'_id': {'$in': qfp}}).sort('count', 1).limit(qn - qmin + 1)] aggregate = [ #{'$match': {'mfp.count': {'$gte': qmin, '$lte': qmax}, 'mfp.bits': {'$in': reqbits}}}, + {'$match': {'_id': {'$ne': self.id}}}, # remove self {'$project': { 'tanimoto': {'$let': { 'vars': {'common': {'$size': {'$setIntersection': ['$fp4', fp4]}}}, @@ -190,7 +190,8 @@ FP4 = fp4 {'$sort': {'tanimoto': -1}} ] - $mongo["compounds"].aggregate(aggregate).collect { |r| [Compound.find(r["_id"]), r["tanimoto"]]} + $mongo["compounds"].aggregate(aggregate).collect{ |r| [r["_id"], r["tanimoto"]] } + end private -- cgit v1.2.3 From 23ecfc6fa5ae4913e5cd17b7d58432d1f88d780c Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Mon, 10 Aug 2015 09:48:57 +0200 Subject: transfer to new git project started --- lib/compound.rb | 40 +++++----------------------------------- 1 file changed, 5 insertions(+), 35 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 4e29938..3ba1670 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -11,32 +11,6 @@ module OpenTox class Compound include OpenTox - # OpenBabel FP4 fingerprints - # OpenBabel http://open-babel.readthedocs.org/en/latest/Fingerprints/intro.html - fp4 = FingerprintSmarts.all - unless fp4 - fp4 = [] - File.open(File.join(File.dirname(__FILE__),"SMARTS_InteLigand.txt")).each do |l| - l.strip! - unless l.empty? or l.match /^#/ - name,smarts = l.split(': ') - fp4 << OpenTox::FingerprintSmarts.find_or_create_by(:name => name, :smarts => smarts) unless smarts.nil? - end - end - end - FP4 = fp4 - - # TODO investigate other types of fingerprints (MACCS) - # OpenBabel http://open-babel.readthedocs.org/en/latest/Fingerprints/intro.html - # http://www.dalkescientific.com/writings/diary/archive/2008/06/26/fingerprint_background.html - # OpenBabel MNA http://openbabel.org/docs/dev/FileFormats/Multilevel_Neighborhoods_of_Atoms_(MNA).html#multilevel-neighborhoods-of-atoms-mna - # Morgan ECFP, FCFP - # http://cdk.github.io/cdk/1.5/docs/api/org/openscience/cdk/fingerprint/CircularFingerprinter.html - # http://www.rdkit.org/docs/GettingStartedInPython.html - # Chemfp - # https://chemfp.readthedocs.org/en/latest/using-tools.html - # CACTVS/PubChem - field :inchi, type: String attr_readonly :inchi field :smiles, type: String @@ -48,21 +22,17 @@ module OpenTox field :sdf_id, type: BSON::ObjectId field :fp4, type: Array field :fp4_size, type: Integer - #belongs_to :dataset - #belongs_to :data_entry - - #def == compound - #self.inchi == compound.inchi - #end + # Overwrites standard Mongoid method to create fingerprints before database insertion def self.find_or_create_by params compound = self.find_or_initialize_by params - unless compound.fp4 + unless compound.fp4 and !compound.fp4.empty? compound.fp4_size = 0 compound.fp4 = [] - Algorithm::Descriptor.smarts_match(compound, FP4.collect{|f| f.smarts}).each_with_index do |m,i| + fingerprint = FingerprintSmarts.fingerprint + Algorithm::Descriptor.smarts_match(compound, fingerprint).each_with_index do |m,i| if m > 0 - compound.fp4 << FP4[i].id + compound.fp4 << fingerprint[i].id compound.fp4_size += 1 end end -- cgit v1.2.3 From b7cd3ebbb858a8891c35c45896f1bdd525f3534e Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Mon, 10 Aug 2015 13:26:06 +0200 Subject: algorithm libraries added, fminer tests pass --- lib/compound.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 3ba1670..3418fcc 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -3,8 +3,6 @@ # Could not find contribution data file. CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/" -require 'openbabel' -require "base64" module OpenTox -- cgit v1.2.3 From 6ab86c253ba0eb79b9e6a20effa2d18626accf2b Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 13 Aug 2015 11:56:40 +0200 Subject: OpenBabel can (canonical smiles) instead of inchi as internal identifier to avoid OpenBabel InChi bug. --- lib/compound.rb | 54 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 14 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 3418fcc..5343aa0 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -10,13 +10,13 @@ module OpenTox include OpenTox field :inchi, type: String - attr_readonly :inchi field :smiles, type: String field :inchikey, type: String field :names, type: Array field :cid, type: String field :chemblid, type: String - field :image_id, type: BSON::ObjectId + field :png_id, type: BSON::ObjectId + field :svg_id, type: BSON::ObjectId field :sdf_id, type: BSON::ObjectId field :fp4, type: Array field :fp4_size, type: Integer @@ -46,14 +46,18 @@ module OpenTox # @return [OpenTox::Compound] Compound def self.from_smiles smiles # do not store smiles because it might be noncanonical - Compound.find_or_create_by :inchi => obconversion(smiles,"smi","inchi") + Compound.find_or_create_by :smiles => obconversion(smiles,"smi","can") end # Create a compound from inchi string # @param inchi [String] smiles InChI string # @return [OpenTox::Compound] Compound def self.from_inchi inchi - Compound.find_or_create_by :inchi => inchi + # Temporary workaround for OpenBabels Inchi bug + # http://sourceforge.net/p/openbabel/bugs/957/ + # bug has not been fixed in latest git/development version + smiles = `echo "#{inchi}" | babel -iinchi - -ocan`.chomp.strip + smiles.empty? ? nil : Compound.find_or_create_by(:smiles => smiles, :inchi => inchi) end # Create a compound from sdf string @@ -61,7 +65,7 @@ module OpenTox # @return [OpenTox::Compound] Compound def self.from_sdf sdf # do not store sdf because it might be 2D - Compound.find_or_create_by :inchi => obconversion(sdf,"sdf","inchi") + Compound.find_or_create_by :smiles => obconversion(sdf,"sdf","can") end # Create a compound from name. Relies on an external service for name lookups. @@ -70,20 +74,30 @@ module OpenTox # @param name [String] can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound def self.from_name name - Compound.find_or_create_by :inchi => RestClientWrapper.get(File.join(CACTUS_URI,URI.escape(name),"stdinchi")) + Compound.find_or_create_by :smiles => RestClientWrapper.get(File.join(CACTUS_URI,URI.escape(name),"smiles")) end - # Get InChIKey + # Get InChI # @return [String] InChI string + def inchi + unless self["inchi"] + result = `echo "#{self.smiles}" | babel -ismi - -oinchi`.chomp + update(:inchi => result.chomp) unless result.empty? + end + self["inchi"] + end + + # Get InChIKey + # @return [String] InChIKey string def inchikey - update(:inchikey => obconversion(inchi,"inchi","inchikey")) unless self["inchikey"] + update(:inchikey => obconversion(smiles,"smi","inchikey")) unless self["inchikey"] self["inchikey"] end # Get (canonical) smiles # @return [String] Smiles string def smiles - update(:smiles => obconversion(inchi,"inchi","smi")) unless self["smiles"] # should give canonical smiles, "can" seems to give incorrect results + update(:smiles => obconversion(self["smiles"],"smi","can")) #unless self["smiles"] # should give canonical smiles, "can" seems to give incorrect results self["smiles"] end @@ -91,7 +105,7 @@ module OpenTox # @return [String] SDF string def sdf if self.sdf_id.nil? - sdf = obconversion(inchi,"inchi","sdf") + sdf = obconversion(smiles,"smi","sdf") file = Mongo::Grid::File.new(sdf, :filename => "#{id}.sdf",:content_type => "chemical/x-mdl-sdfile") sdf_id = $gridfs.insert_one file update :sdf_id => sdf_id @@ -99,17 +113,29 @@ module OpenTox $gridfs.find_one(_id: self.sdf_id).data end + # Get SVG image + # @return [image/svg] Image data + def svg + if self.svg_id.nil? + svg = obconversion(smiles,"smi","svg") + file = Mongo::Grid::File.new(svg, :filename => "#{id}.svg", :content_type => "image/svg") + update(:image_id => $gridfs.insert_one(file)) + end + $gridfs.find_one(_id: self.svg_id).data + + end + # Get png image # @example # image = compound.png # @return [image/png] Image data def png - if self.image_id.nil? - png = obconversion(inchi,"inchi","_png2") + if self.png_id.nil? + png = obconversion(smiles,"smi","_png2") file = Mongo::Grid::File.new(Base64.encode64(png), :filename => "#{id}.png", :content_type => "image/png") - update(:image_id => $gridfs.insert_one(file)) + update(:png_id => $gridfs.insert_one(file)) end - Base64.decode64($gridfs.find_one(_id: self.image_id).data) + Base64.decode64($gridfs.find_one(_id: self.png_id).data) end -- cgit v1.2.3 From d0850e2983a219da214a67190fe881c7650f532f Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 13 Aug 2015 18:57:11 +0200 Subject: majority of tests working --- lib/compound.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 5343aa0..10deabc 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -13,6 +13,7 @@ module OpenTox field :smiles, type: String field :inchikey, type: String field :names, type: Array + field :warning, type: String field :cid, type: String field :chemblid, type: String field :png_id, type: BSON::ObjectId @@ -46,7 +47,12 @@ module OpenTox # @return [OpenTox::Compound] Compound def self.from_smiles smiles # do not store smiles because it might be noncanonical - Compound.find_or_create_by :smiles => obconversion(smiles,"smi","can") + smiles = obconversion(smiles,"smi","can") + if smiles.empty? + Compound.find_or_create_by(:warning => "SMILES parsing failed for '#{smiles}', this may be caused by an incorrect SMILES string.") + else + Compound.find_or_create_by :smiles => obconversion(smiles,"smi","can") + end end # Create a compound from inchi string @@ -57,7 +63,11 @@ module OpenTox # http://sourceforge.net/p/openbabel/bugs/957/ # bug has not been fixed in latest git/development version smiles = `echo "#{inchi}" | babel -iinchi - -ocan`.chomp.strip - smiles.empty? ? nil : Compound.find_or_create_by(:smiles => smiles, :inchi => inchi) + if smiles.empty? + Compound.find_or_create_by(:warning => "InChi parsing failed for #{inchi}, this may be caused by an incorrect InChi string or a bug in OpenBabel libraries.") + else + Compound.find_or_create_by(:smiles => smiles, :inchi => inchi) + end end # Create a compound from sdf string -- cgit v1.2.3 From 4067d78c78c1f503b5f21d043ece8042260a3d78 Mon Sep 17 00:00:00 2001 From: ch Date: Tue, 18 Aug 2015 16:37:09 +0200 Subject: initial installation fixes, installs on Debian 3.16.7 --- lib/compound.rb | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 10deabc..e51e9ad 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -62,7 +62,7 @@ module OpenTox # Temporary workaround for OpenBabels Inchi bug # http://sourceforge.net/p/openbabel/bugs/957/ # bug has not been fixed in latest git/development version - smiles = `echo "#{inchi}" | babel -iinchi - -ocan`.chomp.strip + smiles = `echo "#{inchi}" | "#{File.join(File.dirname(__FILE__),"..","openbabel","bin","babel")}" -iinchi - -ocan`.chomp.strip if smiles.empty? Compound.find_or_create_by(:warning => "InChi parsing failed for #{inchi}, this may be caused by an incorrect InChi string or a bug in OpenBabel libraries.") else @@ -91,7 +91,8 @@ module OpenTox # @return [String] InChI string def inchi unless self["inchi"] - result = `echo "#{self.smiles}" | babel -ismi - -oinchi`.chomp + + result = `echo "#{self.smiles}" | "#{File.join(File.dirname(__FILE__),"..","openbabel","bin","babel")}" -ismi - -oinchi`.chomp update(:inchi => result.chomp) unless result.empty? end self["inchi"] @@ -182,21 +183,23 @@ module OpenTox #reqbits = [count['_id'] for count in db.mfp_counts.find({'_id': {'$in': qfp}}).sort('count', 1).limit(qn - qmin + 1)] aggregate = [ #{'$match': {'mfp.count': {'$gte': qmin, '$lte': qmax}, 'mfp.bits': {'$in': reqbits}}}, - {'$match': {'_id': {'$ne': self.id}}}, # remove self - {'$project': { - 'tanimoto': {'$let': { - 'vars': {'common': {'$size': {'$setIntersection': ['$fp4', fp4]}}}, - 'in': {'$divide': ['$$common', {'$subtract': [{'$add': [qn, '$fp4_size']}, '$$common']}]} + {'$match' => {'_id' => {'$ne' => self.id}}}, # remove self + {'$project' => { + 'tanimoto' => {'$let' => { + 'vars' => {'common' => {'$size' => {'$setIntersection' => ['$fp4', fp4]}}}, + 'in' => {'$divide' => ['$$common', {'$subtract' => [{'$add' => [qn, '$fp4_size']}, '$$common']}]} }}, - '_id': 1 + '_id' => 1 }}, - {'$match': {'tanimoto': {'$gte': threshold}}}, - {'$sort': {'tanimoto': -1}} + {'$match' => {'tanimoto' => {'$gte' => threshold}}}, + {'$sort' => {'tanimoto' => -1}} ] $mongo["compounds"].aggregate(aggregate).collect{ |r| [r["_id"], r["tanimoto"]] } end +=begin +=end private @@ -210,11 +213,12 @@ module OpenTox when /smi|can|inchi/ obconversion.write_string(obmol).gsub(/\s/,'').chomp when /sdf/ - OpenBabel::OBOp.find_type("Gen3D").do(obmol) +# TODO set 3D + #OpenBabel::OBOp.find_type("Gen3D").do(obmol) sdf = obconversion.write_string(obmol) if sdf.match(/.nan/) $logger.warn "3D generation failed for compound #{identifier}, trying to calculate 2D structure" - OpenBabel::OBOp.find_type("Gen2D").do(obmol) + #OpenBabel::OBOp.find_type("Gen2D").do(obmol) sdf = obconversion.write_string(obmol) if sdf.match(/.nan/) $logger.warn "2D generation failed for compound #{identifier}" -- cgit v1.2.3 From 36e10aa98a3d19a78a1889857262abe338a05eef Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 19 Aug 2015 12:57:23 +0200 Subject: libfminer rpath fixed, installation instructions --- lib/compound.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index e51e9ad..fdec019 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -213,11 +213,22 @@ module OpenTox when /smi|can|inchi/ obconversion.write_string(obmol).gsub(/\s/,'').chomp when /sdf/ -# TODO set 3D +p "SDF conversion" + # has no effect + #obconversion.add_option("gen3D", OpenBabel::OBConversion::GENOPTIONS) + # segfaults with openbabel git master #OpenBabel::OBOp.find_type("Gen3D").do(obmol) + + builder = OpenBabel::OBBuilder.new + builder.build(obmol); + sdf = obconversion.write_string(obmol) +print sdf if sdf.match(/.nan/) + +# TODO: fix or eliminate 2d generation $logger.warn "3D generation failed for compound #{identifier}, trying to calculate 2D structure" + obconversion.set_options("gen2D", OpenBabel::OBConversion::GENOPTIONS) #OpenBabel::OBOp.find_type("Gen2D").do(obmol) sdf = obconversion.write_string(obmol) if sdf.match(/.nan/) -- cgit v1.2.3 From 57bb9c2c691d350dce8c30b862030973043818cc Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 19 Aug 2015 14:00:55 +0200 Subject: hydrogens added for 3d generation --- lib/compound.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index fdec019..6d755da 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -46,7 +46,6 @@ module OpenTox # @param [String] smiles Smiles string # @return [OpenTox::Compound] Compound def self.from_smiles smiles - # do not store smiles because it might be noncanonical smiles = obconversion(smiles,"smi","can") if smiles.empty? Compound.find_or_create_by(:warning => "SMILES parsing failed for '#{smiles}', this may be caused by an incorrect SMILES string.") @@ -62,7 +61,8 @@ module OpenTox # Temporary workaround for OpenBabels Inchi bug # http://sourceforge.net/p/openbabel/bugs/957/ # bug has not been fixed in latest git/development version - smiles = `echo "#{inchi}" | "#{File.join(File.dirname(__FILE__),"..","openbabel","bin","babel")}" -iinchi - -ocan`.chomp.strip + #smiles = `echo "#{inchi}" | "#{File.join(File.dirname(__FILE__),"..","openbabel","bin","babel")}" -iinchi - -ocan`.chomp.strip + smiles = obconversion(inchi,"inchi","can") if smiles.empty? Compound.find_or_create_by(:warning => "InChi parsing failed for #{inchi}, this may be caused by an incorrect InChi string or a bug in OpenBabel libraries.") else @@ -92,7 +92,8 @@ module OpenTox def inchi unless self["inchi"] - result = `echo "#{self.smiles}" | "#{File.join(File.dirname(__FILE__),"..","openbabel","bin","babel")}" -ismi - -oinchi`.chomp + result = obconversion(smiles,"smi","inchi") + #result = `echo "#{self.smiles}" | "#{File.join(File.dirname(__FILE__),"..","openbabel","bin","babel")}" -ismi - -oinchi`.chomp update(:inchi => result.chomp) unless result.empty? end self["inchi"] @@ -108,7 +109,7 @@ module OpenTox # Get (canonical) smiles # @return [String] Smiles string def smiles - update(:smiles => obconversion(self["smiles"],"smi","can")) #unless self["smiles"] # should give canonical smiles, "can" seems to give incorrect results + update(:smiles => obconversion(self["smiles"],"smi","can")) unless self["smiles"] self["smiles"] end @@ -219,8 +220,12 @@ p "SDF conversion" # segfaults with openbabel git master #OpenBabel::OBOp.find_type("Gen3D").do(obmol) + # TODO: find disconnected structures + # strip_salts + # separate + obmol.add_hydrogens builder = OpenBabel::OBBuilder.new - builder.build(obmol); + builder.build(obmol) sdf = obconversion.write_string(obmol) print sdf -- cgit v1.2.3 From 4fb010f4c0f30e5b23d39e191ce36587827f8f4e Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 19 Aug 2015 14:17:44 +0200 Subject: name conversion fixed --- lib/compound.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 6d755da..c0d6536 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -75,7 +75,7 @@ module OpenTox # @return [OpenTox::Compound] Compound def self.from_sdf sdf # do not store sdf because it might be 2D - Compound.find_or_create_by :smiles => obconversion(sdf,"sdf","can") + Compound.from_smiles obconversion(sdf,"sdf","can") end # Create a compound from name. Relies on an external service for name lookups. @@ -84,7 +84,7 @@ module OpenTox # @param name [String] can be also an InChI/InChiKey, CAS number, etc # @return [OpenTox::Compound] Compound def self.from_name name - Compound.find_or_create_by :smiles => RestClientWrapper.get(File.join(CACTUS_URI,URI.escape(name),"smiles")) + Compound.from_smiles RestClientWrapper.get(File.join(CACTUS_URI,URI.escape(name),"smiles")) end # Get InChI -- cgit v1.2.3 From 8c6c59980bc82dc2177147f2fe34adf8bfbc1539 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Mon, 24 Aug 2015 12:17:07 +0200 Subject: Model::Prediction with tests, initial indexes --- lib/compound.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index c0d6536..fa57aff 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -22,6 +22,8 @@ module OpenTox field :fp4, type: Array field :fp4_size, type: Integer + index({smiles: 1}, {unique: true}) + # Overwrites standard Mongoid method to create fingerprints before database insertion def self.find_or_create_by params compound = self.find_or_initialize_by params -- cgit v1.2.3 From f8faf510b4574df1a00fa61a9f0a1681fc2f4857 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Tue, 25 Aug 2015 17:20:55 +0200 Subject: Experiments added --- lib/compound.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index fa57aff..a819f56 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -178,6 +178,7 @@ module OpenTox end def neighbors threshold=0.7 + # TODO restrict to dataset # from http://blog.matt-swain.com/post/87093745652/chemical-similarity-search-in-mongodb qn = fp4.size #qmin = qn * threshold -- cgit v1.2.3 From 66c34e4682965272060a121b6e362af67ed4be5f Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 27 Aug 2015 20:28:25 +0200 Subject: Initial GUI for Nestec models --- lib/compound.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index a819f56..8f393f5 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -133,7 +133,7 @@ module OpenTox if self.svg_id.nil? svg = obconversion(smiles,"smi","svg") file = Mongo::Grid::File.new(svg, :filename => "#{id}.svg", :content_type => "image/svg") - update(:image_id => $gridfs.insert_one(file)) + update(:svg_id => $gridfs.insert_one(file)) end $gridfs.find_one(_id: self.svg_id).data -- cgit v1.2.3 From 96a476a2331daa4d1d6b5ac444bbdbd2ac221a5f Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 10 Sep 2015 12:54:18 +0200 Subject: tests fixed (crossvalidations may fail due to memory constraints) --- lib/compound.rb | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 8f393f5..6adf3c0 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -218,11 +218,6 @@ module OpenTox obconversion.write_string(obmol).gsub(/\s/,'').chomp when /sdf/ p "SDF conversion" - # has no effect - #obconversion.add_option("gen3D", OpenBabel::OBConversion::GENOPTIONS) - # segfaults with openbabel git master - #OpenBabel::OBOp.find_type("Gen3D").do(obmol) - # TODO: find disconnected structures # strip_salts # separate @@ -234,14 +229,13 @@ p "SDF conversion" print sdf if sdf.match(/.nan/) -# TODO: fix or eliminate 2d generation $logger.warn "3D generation failed for compound #{identifier}, trying to calculate 2D structure" obconversion.set_options("gen2D", OpenBabel::OBConversion::GENOPTIONS) - #OpenBabel::OBOp.find_type("Gen2D").do(obmol) sdf = obconversion.write_string(obmol) if sdf.match(/.nan/) - $logger.warn "2D generation failed for compound #{identifier}" - sdf = nil + $logger.warn "2D generation failed for compound #{identifier}, rendering without coordinates." + obconversion.remove_option("gen2D", OpenBabel::OBConversion::GENOPTIONS) + sdf = obconversion.write_string(obmol) end end sdf -- cgit v1.2.3 From 2fdecbed76c4db8dfe3f10f825fed9772e653197 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 16 Sep 2015 16:52:18 +0200 Subject: generic openbabel fingerprints --- lib/compound.rb | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 6adf3c0..7f175ca 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -42,6 +42,35 @@ module OpenTox compound end + def openbabel_fingerprint type="FP2" + fp = OpenBabel::OBFingerprint.find_fingerprint(type) + obmol = OpenBabel::OBMol.new + obconversion = OpenBabel::OBConversion.new + obconversion.set_in_format "smi" + obconversion.read_string obmol, smiles + result = OpenBabel::VectorUnsignedInt.new + fp.get_fingerprint(obmol,result) + # TODO: %ignore *::DescribeBits @ line 163 openbabel/scripts/openbabel-ruby.i + #p OpenBabel::OBFingerprint.describe_bits(result) + result = result.to_a + # convert result to a list of the bits that are set + # from openbabel/scripts/python/pybel.py line 830 + # see also http://openbabel.org/docs/dev/UseTheLibrary/Python_Pybel.html#fingerprints + bitsperint = OpenBabel::OBFingerprint.getbitsperint() + bits_set = [] + start = 1 + result.each do |x| + i = start + while x > 0 do + bits_set << i if (x % 2) == 1 + x >>= 1 + i += 1 + end + start += bitsperint + end + bits_set + end + # Create a compound from smiles string # @example # compound = OpenTox::Compound.from_smiles("c1ccccc1") @@ -202,8 +231,6 @@ module OpenTox $mongo["compounds"].aggregate(aggregate).collect{ |r| [r["_id"], r["tanimoto"]] } end -=begin -=end private -- cgit v1.2.3 From 6ac119c32cef094d4f1c2fb5c2daa4e274401f70 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 17 Sep 2015 14:56:25 +0200 Subject: neighbor calculation moved to Compound class --- lib/compound.rb | 84 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 24 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 7f175ca..7abd913 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -19,8 +19,11 @@ module OpenTox field :png_id, type: BSON::ObjectId field :svg_id, type: BSON::ObjectId field :sdf_id, type: BSON::ObjectId + field :fp2, type: Array + field :fp3, type: Array field :fp4, type: Array field :fp4_size, type: Integer + field :maccs, type: Array index({smiles: 1}, {unique: true}) @@ -43,32 +46,35 @@ module OpenTox end def openbabel_fingerprint type="FP2" - fp = OpenBabel::OBFingerprint.find_fingerprint(type) - obmol = OpenBabel::OBMol.new - obconversion = OpenBabel::OBConversion.new - obconversion.set_in_format "smi" - obconversion.read_string obmol, smiles - result = OpenBabel::VectorUnsignedInt.new - fp.get_fingerprint(obmol,result) - # TODO: %ignore *::DescribeBits @ line 163 openbabel/scripts/openbabel-ruby.i - #p OpenBabel::OBFingerprint.describe_bits(result) - result = result.to_a - # convert result to a list of the bits that are set - # from openbabel/scripts/python/pybel.py line 830 - # see also http://openbabel.org/docs/dev/UseTheLibrary/Python_Pybel.html#fingerprints - bitsperint = OpenBabel::OBFingerprint.getbitsperint() - bits_set = [] - start = 1 - result.each do |x| - i = start - while x > 0 do - bits_set << i if (x % 2) == 1 - x >>= 1 - i += 1 + unless self.send(type.downcase.to_sym) # stored fingerprint + fp = OpenBabel::OBFingerprint.find_fingerprint(type) + obmol = OpenBabel::OBMol.new + obconversion = OpenBabel::OBConversion.new + obconversion.set_in_format "smi" + obconversion.read_string obmol, smiles + result = OpenBabel::VectorUnsignedInt.new + fp.get_fingerprint(obmol,result) + # TODO: %ignore *::DescribeBits @ line 163 openbabel/scripts/openbabel-ruby.i + #p OpenBabel::OBFingerprint.describe_bits(result) + # convert result to a list of the bits that are set + # from openbabel/scripts/python/pybel.py line 830 + # see also http://openbabel.org/docs/dev/UseTheLibrary/Python_Pybel.html#fingerprints + result = result.to_a + bitsperint = OpenBabel::OBFingerprint.getbitsperint() + bits_set = [] + start = 1 + result.each do |x| + i = start + while x > 0 do + bits_set << i if (x % 2) == 1 + x >>= 1 + i += 1 + end + start += bitsperint end - start += bitsperint + update type.downcase.to_sym, bits_set end - bits_set + self.send(type.downcase.to_sym) end # Create a compound from smiles string @@ -206,6 +212,36 @@ module OpenTox self["chemblid"] end + def fingerprint_neighbors params + bad_request_error "Incorrect parameters '#{params}' for Compound#fingerprint_neighbors. Please provide :type, :training_dataset_id, :min_sim." unless params[:type] and params[:training_dataset_id] and params[:min_sim] + neighbors = [] + query_fingerprint = self.openbabel_fingerprint params[:type] + training_dataset = Dataset.find(params[:training_dataset_id]).compounds.each do |compound| + unless self == compound + fingerprint = compound.openbabel_fingerprint params[:type] + sim = (query_fingerprint & fingerprint).size/(query_fingerprint | fingerprint).size.to_f + neighbors << [compound.id, sim] if sim >= params[:min_sim] + end + end + neighbors.sort{|a,b| b.last <=> a.last} + end + + def fminer_neighbors params + bad_request_error "Incorrect parameters for Compound#fminer_neighbors. Please provide :feature_dataset_id, :min_sim." unless params[:feature_dataset_id] and params[:min_sim] + feature_dataset = Dataset.find params[:feature_dataset_id] + query_fingerprint = Algorithm::Descriptor.smarts_match(self, feature_dataset.features) + neighbors = [] + + # find neighbors + feature_dataset.data_entries.each_with_index do |fingerprint, i| + sim = Algorithm::Similarity.tanimoto fingerprint, query_fingerprint + if sim >= params[:min_sim] + neighbors << [feature_dataset.compound_ids[i],sim] # use compound_ids, instantiation of Compounds is too time consuming + end + end + neighbors + end + def neighbors threshold=0.7 # TODO restrict to dataset # from http://blog.matt-swain.com/post/87093745652/chemical-similarity-search-in-mongodb -- cgit v1.2.3 From d5bf97c2cb999539c56bf59aa1d7d3286745be84 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 23 Sep 2015 14:51:41 +0200 Subject: validations fixed (all models were executed with default parameters) --- lib/compound.rb | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index 7abd913..d3df125 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -44,6 +44,21 @@ module OpenTox compound.save compound end + + #http://openbabel.org/docs/dev/FileFormats/MolPrint2D_format.html#molprint2d-format + def mpd + smarts = obconversion(smiles,"smi","mpd").strip.split("\t") + smarts.shift # remove Title + smarts + + end + + #http://openbabel.org/docs/dev/FileFormats/Multilevel_Neighborhoods_of_Atoms_(MNA).html + def mna level=2 + smarts = obconversion(smiles,"smi","mna","xL\"#{level}\"").split("\n") + smarts.shift # remove Title + smarts + end def openbabel_fingerprint type="FP2" unless self.send(type.downcase.to_sym) # stored fingerprint @@ -72,7 +87,7 @@ module OpenTox end start += bitsperint end - update type.downcase.to_sym, bits_set + update_attribute type.downcase.to_sym, bits_set end self.send(type.downcase.to_sym) end @@ -242,6 +257,28 @@ module OpenTox neighbors end + def physchem_neighbors params + feature_dataset = Dataset.find params[:feature_dataset_id] + query_fingerprint = Algorithm.run params[:feature_calculation_algorithm], self, params[:descriptors] + neighbors = [] + feature_dataset.data_entries.each_with_index do |fingerprint, i| + # TODO implement pearson and cosine similarity separatly + R.assign "x", query_fingerprint + R.assign "y", fingerprint + # pearson r + #sim = R.eval("cor(x,y,use='complete.obs',method='pearson')").to_ruby + #p "pearson" + #p sim + #p "cosine" + sim = R.eval("x %*% y / sqrt(x%*%x * y%*%y)").to_ruby.first + #p sim + if sim >= params[:min_sim] + neighbors << [feature_dataset.compound_ids[i],sim] # use compound_ids, instantiation of Compounds is too time consuming + end + end + neighbors + end + def neighbors threshold=0.7 # TODO restrict to dataset # from http://blog.matt-swain.com/post/87093745652/chemical-similarity-search-in-mongodb @@ -308,7 +345,7 @@ print sdf end def obconversion(identifier,input_format,output_format,option=nil) - self.class.obconversion(identifier,input_format,output_format,option=nil) + self.class.obconversion(identifier,input_format,output_format,option) end end end -- cgit v1.2.3 From 8d2f1c8a0f6cc9f7a481d1117bf8b3351130b1ea Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Wed, 7 Oct 2015 12:34:02 +0200 Subject: generalised fingerprints --- lib/compound.rb | 171 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 95 insertions(+), 76 deletions(-) (limited to 'lib/compound.rb') diff --git a/lib/compound.rb b/lib/compound.rb index d3df125..7a3dc5c 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -9,6 +9,8 @@ module OpenTox class Compound include OpenTox + DEFAULT_FINGERPRINT = "MP2D" + field :inchi, type: String field :smiles, type: String field :inchikey, type: String @@ -19,77 +21,64 @@ module OpenTox field :png_id, type: BSON::ObjectId field :svg_id, type: BSON::ObjectId field :sdf_id, type: BSON::ObjectId - field :fp2, type: Array - field :fp3, type: Array - field :fp4, type: Array - field :fp4_size, type: Integer - field :maccs, type: Array + field :fingerprints, type: Hash, default: {} + field :default_fingerprint_size, type: Integer index({smiles: 1}, {unique: true}) # Overwrites standard Mongoid method to create fingerprints before database insertion def self.find_or_create_by params compound = self.find_or_initialize_by params - unless compound.fp4 and !compound.fp4.empty? - compound.fp4_size = 0 - compound.fp4 = [] - fingerprint = FingerprintSmarts.fingerprint - Algorithm::Descriptor.smarts_match(compound, fingerprint).each_with_index do |m,i| - if m > 0 - compound.fp4 << fingerprint[i].id - compound.fp4_size += 1 - end - end - end + compound.default_fingerprint_size = compound.fingerprint(DEFAULT_FINGERPRINT) compound.save compound end - - #http://openbabel.org/docs/dev/FileFormats/MolPrint2D_format.html#molprint2d-format - def mpd - smarts = obconversion(smiles,"smi","mpd").strip.split("\t") - smarts.shift # remove Title - smarts - - end - - #http://openbabel.org/docs/dev/FileFormats/Multilevel_Neighborhoods_of_Atoms_(MNA).html - def mna level=2 - smarts = obconversion(smiles,"smi","mna","xL\"#{level}\"").split("\n") - smarts.shift # remove Title - smarts - end - def openbabel_fingerprint type="FP2" - unless self.send(type.downcase.to_sym) # stored fingerprint - fp = OpenBabel::OBFingerprint.find_fingerprint(type) - obmol = OpenBabel::OBMol.new - obconversion = OpenBabel::OBConversion.new - obconversion.set_in_format "smi" - obconversion.read_string obmol, smiles - result = OpenBabel::VectorUnsignedInt.new - fp.get_fingerprint(obmol,result) - # TODO: %ignore *::DescribeBits @ line 163 openbabel/scripts/openbabel-ruby.i - #p OpenBabel::OBFingerprint.describe_bits(result) - # convert result to a list of the bits that are set - # from openbabel/scripts/python/pybel.py line 830 - # see also http://openbabel.org/docs/dev/UseTheLibrary/Python_Pybel.html#fingerprints - result = result.to_a - bitsperint = OpenBabel::OBFingerprint.getbitsperint() - bits_set = [] - start = 1 - result.each do |x| - i = start - while x > 0 do - bits_set << i if (x % 2) == 1 - x >>= 1 - i += 1 + def fingerprint type="MP2D" + unless fingerprints[type] + return [] unless self.smiles + #http://openbabel.org/docs/dev/FileFormats/MolPrint2D_format.html#molprint2d-format + if type == "MP2D" + fp = obconversion(smiles,"smi","mpd").strip.split("\t") + name = fp.shift # remove Title + fingerprints[type] = fp + #http://openbabel.org/docs/dev/FileFormats/Multilevel_Neighborhoods_of_Atoms_(MNA).html + elsif type== "MNA" + level = 2 # TODO: level as parameter, evaluate level 1, see paper + fp = obconversion(smiles,"smi","mna","xL\"#{level}\"").split("\n") + fp.shift # remove Title + fingerprints[type] = fp + else # standard fingerprints + fp = OpenBabel::OBFingerprint.find_fingerprint(type) + obmol = OpenBabel::OBMol.new + obconversion = OpenBabel::OBConversion.new + obconversion.set_in_format "smi" + obconversion.read_string obmol, self.smiles + result = OpenBabel::VectorUnsignedInt.new + fp.get_fingerprint(obmol,result) + # TODO: %ignore *::DescribeBits @ line 163 openbabel/scripts/openbabel-ruby.i + #p OpenBabel::OBFingerprint.describe_bits(result) + # convert result to a list of the bits that are set + # from openbabel/scripts/python/pybel.py line 830 + # see also http://openbabel.org/docs/dev/UseTheLibrary/Python_Pybel.html#fingerprints + result = result.to_a + bitsperint = OpenBabel::OBFingerprint.getbitsperint() + bits_set = [] + start = 1 + result.each do |x| + i = start + while x > 0 do + bits_set << i if (x % 2) == 1 + x >>= 1 + i += 1 + end + start += bitsperint end - start += bitsperint + fingerprints[type] = bits_set end - update_attribute type.downcase.to_sym, bits_set + save end - self.send(type.downcase.to_sym) + fingerprints[type] end # Create a compound from smiles string @@ -100,7 +89,8 @@ module OpenTox def self.from_smiles smiles smiles = obconversion(smiles,"smi","can") if smiles.empty? - Compound.find_or_create_by(:warning => "SMILES parsing failed for '#{smiles}', this may be caused by an incorrect SMILES string.") + return nil + #Compound.find_or_create_by(:warning => "SMILES parsing failed for '#{smiles}', this may be caused by an incorrect SMILES string.") else Compound.find_or_create_by :smiles => obconversion(smiles,"smi","can") end @@ -146,7 +136,7 @@ module OpenTox result = obconversion(smiles,"smi","inchi") #result = `echo "#{self.smiles}" | "#{File.join(File.dirname(__FILE__),"..","openbabel","bin","babel")}" -ismi - -oinchi`.chomp - update(:inchi => result.chomp) unless result.empty? + update(:inchi => result.chomp) if result and !result.empty? end self["inchi"] end @@ -227,20 +217,47 @@ module OpenTox self["chemblid"] end - def fingerprint_neighbors params - bad_request_error "Incorrect parameters '#{params}' for Compound#fingerprint_neighbors. Please provide :type, :training_dataset_id, :min_sim." unless params[:type] and params[:training_dataset_id] and params[:min_sim] + def fingerprint_count_neighbors params + # TODO fix neighbors = [] - query_fingerprint = self.openbabel_fingerprint params[:type] + query_fingerprint = self.fingerprint params[:type] training_dataset = Dataset.find(params[:training_dataset_id]).compounds.each do |compound| unless self == compound - fingerprint = compound.openbabel_fingerprint params[:type] - sim = (query_fingerprint & fingerprint).size/(query_fingerprint | fingerprint).size.to_f - neighbors << [compound.id, sim] if sim >= params[:min_sim] + candidate_fingerprint = compound.fingerprint params[:type] + features = (query_fingerprint + candidate_fingerprint).uniq + min_sum = 0 + max_sum = 0 + features.each do |f| + min,max = [query_fingerprint.count(f),candidate_fingerprint.count(f)].minmax + min_sum += min + max_sum += max + end + max_sum == 0 ? sim = 0 : sim = min_sum/max_sum.to_f + neighbors << [compound.id, sim] if sim and sim >= params[:min_sim] end end neighbors.sort{|a,b| b.last <=> a.last} end + def fingerprint_neighbors params + bad_request_error "Incorrect parameters '#{params}' for Compound#fingerprint_neighbors. Please provide :type, :training_dataset_id, :min_sim." unless params[:type] and params[:training_dataset_id] and params[:min_sim] + neighbors = [] + #if params[:type] == DEFAULT_FINGERPRINT + #neighbors = db_neighbors params + #p neighbors + #else + query_fingerprint = self.fingerprint params[:type] + training_dataset = Dataset.find(params[:training_dataset_id]).compounds.each do |compound| + unless self == compound + candidate_fingerprint = compound.fingerprint params[:type] + sim = (query_fingerprint & candidate_fingerprint).size/(query_fingerprint | candidate_fingerprint).size.to_f + neighbors << [compound.id, sim] if sim >= params[:min_sim] + end + end + #end + neighbors.sort{|a,b| b.last <=> a.last} + end + def fminer_neighbors params bad_request_error "Incorrect parameters for Compound#fminer_neighbors. Please provide :feature_dataset_id, :min_sim." unless params[:feature_dataset_id] and params[:min_sim] feature_dataset = Dataset.find params[:feature_dataset_id] @@ -248,8 +265,8 @@ module OpenTox neighbors = [] # find neighbors - feature_dataset.data_entries.each_with_index do |fingerprint, i| - sim = Algorithm::Similarity.tanimoto fingerprint, query_fingerprint + feature_dataset.data_entries.each_with_index do |candidate_fingerprint, i| + sim = Algorithm::Similarity.tanimoto candidate_fingerprint, query_fingerprint if sim >= params[:min_sim] neighbors << [feature_dataset.compound_ids[i],sim] # use compound_ids, instantiation of Compounds is too time consuming end @@ -261,10 +278,10 @@ module OpenTox feature_dataset = Dataset.find params[:feature_dataset_id] query_fingerprint = Algorithm.run params[:feature_calculation_algorithm], self, params[:descriptors] neighbors = [] - feature_dataset.data_entries.each_with_index do |fingerprint, i| + feature_dataset.data_entries.each_with_index do |candidate_fingerprint, i| # TODO implement pearson and cosine similarity separatly R.assign "x", query_fingerprint - R.assign "y", fingerprint + R.assign "y", candidate_fingerprint # pearson r #sim = R.eval("cor(x,y,use='complete.obs',method='pearson')").to_ruby #p "pearson" @@ -279,10 +296,12 @@ module OpenTox neighbors end - def neighbors threshold=0.7 + def db_neighbors params + p "DB NEIGHBORS" + p params # TODO restrict to dataset # from http://blog.matt-swain.com/post/87093745652/chemical-similarity-search-in-mongodb - qn = fp4.size + qn = fingerprint(params[:type]).size #qmin = qn * threshold #qmax = qn / threshold #not sure if it is worth the effort of keeping feature counts up to date (compound deletions, additions, ...) @@ -292,12 +311,12 @@ module OpenTox {'$match' => {'_id' => {'$ne' => self.id}}}, # remove self {'$project' => { 'tanimoto' => {'$let' => { - 'vars' => {'common' => {'$size' => {'$setIntersection' => ['$fp4', fp4]}}}, - 'in' => {'$divide' => ['$$common', {'$subtract' => [{'$add' => [qn, '$fp4_size']}, '$$common']}]} + 'vars' => {'common' => {'$size' => {'$setIntersection' => ["'$#{DEFAULT_FINGERPRINT}'", DEFAULT_FINGERPRINT]}}}, + 'in' => {'$divide' => ['$$common', {'$subtract' => [{'$add' => [qn, '$default_fingerprint_size']}, '$$common']}]} }}, '_id' => 1 }}, - {'$match' => {'tanimoto' => {'$gte' => threshold}}}, + {'$match' => {'tanimoto' => {'$gte' => params[:min_sim]}}}, {'$sort' => {'tanimoto' => -1}} ] @@ -312,12 +331,12 @@ module OpenTox obconversion.set_options(option, OpenBabel::OBConversion::OUTOPTIONS) if option obmol = OpenBabel::OBMol.new obconversion.set_in_and_out_formats input_format, output_format + return nil if identifier.nil? obconversion.read_string obmol, identifier case output_format when /smi|can|inchi/ obconversion.write_string(obmol).gsub(/\s/,'').chomp when /sdf/ -p "SDF conversion" # TODO: find disconnected structures # strip_salts # separate -- cgit v1.2.3