1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
OBMOL_METHODS = {
"NumAtoms" => "Number of atoms",
"NumBonds" => "Number of bonds",
"NumHvyAtoms" => "Number of heavy atoms",
"NumResidues" => "Number of residues",
"NumRotors" => "Number of rotatable bonds",
"GetEnergy" => "Heat of formation for this molecule (in kcal/mol)",
"GetMolWt" => "Standard molar mass given by IUPAC atomic masses (amu)",
"GetExactMass" => "Mass given by isotopes (or most abundant isotope, if not specified)",
"GetTotalCharge" => "Total charge",
}
OBDESCRIPTOR_METHODS = {
"HBA1" => "Number of hydrogen bond acceptors 1 (JoelLib)",
"HBA2" => "Number of hydrogen bond acceptors 2 (JoelLib)",
"HBD" => "Number of hydrogen bond donors (JoelLib)",
"L5" => "Lipinski rule of five",
"logP" => "Octanol/water partition coefficient",
"MR" => "Molar refractivity",
"MW" => "Molecular weight",
"nF" => "Number of fluorine atoms",
"nHal" => "Number of halogen atoms",
"spinMult" => "Total spin multiplicity",
"TPSA" => "Topological polar surface area",
}
# Get a list of OpenBabel algorithms
# @return [text/uri-list] URIs of OpenBabel algorithms
get '/openbabel' do
algorithms = OBMOL_METHODS.collect{|name,description| url_for("/openbabel/#{name}",:full)}
algorithms << OBDESCRIPTOR_METHODS.collect{|name,description| url_for("/openbabel/#{name}",:full)}
response['Content-Type'] = 'text/uri-list'
algorithms.join("\n")
end
# Get RDF/XML representation of OpenBabel algorithm
# @return [application/rdf+xml] OWL-DL representation of OpenBabel algorithm
get '/openbabel/:property' do
description = OBMOL_METHODS[params[:property]] if OBMOL_METHODS.include? params[:property]
description = OBDESCRIPTOR_METHODS[params[:property]] if OBDESCRIPTOR_METHODS.include? params[:property]
if description
algorithm = OpenTox::Algorithm::Generic.new(url_for("/openbabel/#{params[:property]}",:full))
algorithm.metadata = {
DC.title => params[:property],
DC.creator => "helma@in-silico.ch",
DC.description => description,
RDF.type => [OTA.DescriptorCalculation],
}
response['Content-Type'] = 'application/rdf+xml'
algorithm.to_rdfxml
else
raise OpenTox::NotFoundError.new "Unknown OpenBabel descriptor #{params[:property]}."
end
end
# Calculate OpenBabel descriptors
# Supports the following OpenBabel methods (see OpenBabel API http://openbabel.org/api/2.2.0/)
# - NumAtoms Number of atoms
# - NumBonds Number of bonds
# - NumHvyAtoms Number of heavy atoms
# - NumResidues Number of residues
# - NumRotors Number of rotatable bonds
# - GetEnergy Heat of formation for this molecule (in kcal/mol)
# - GetMolWt Standard molar mass given by IUPAC atomic masses (amu)
# - GetExactMass Mass given by isotopes (or most abundant isotope, if not specified)
# - GetTotalCharge Total charge
# - HBA1 Number of hydrogen bond acceptors 1 (JoelLib)
# - HBA2 Number of hydrogen bond acceptors 2 (JoelLib)
# - HBD Number of hydrogen bond donors (JoelLib)
# - L5 Lipinski rule of five
# - logP Octanol/water partition coefficient
# - MR Molar refractivity
# - MW Molecular weight
# - nF Number of fluorine atoms
# - nHal Number of halogen atoms
# - spinMult Total spin multiplicity
# - TPSA Topological polar surface area
# @param [String] compound_uri Compound URI
# @return [String] descriptor value
post '/openbabel/:property' do
obconversion = OpenBabel::OBConversion.new
obmol = OpenBabel::OBMol.new
compound = OpenTox::Compound.new params[:compound_uri]
obconversion.set_in_and_out_formats 'inchi', 'can'
obconversion.read_string obmol, compound.to_inchi
if OBMOL_METHODS.keys.include? params[:property]
eval("obmol.#{params[:property].underscore}").to_s
elsif OBDESCRIPTOR_METHODS.keys.include? params[:property]
descriptor = OpenBabel::OBDescriptor.find_type(params[:property])
descriptor.predict(obmol).to_s
else
raise OpenTox::NotFoundError.new "Cannot calculate property #{params[:property]} with OpenBabel"
end
end
# Calculate all OpenBabel descriptors for a dataset
# @param [String] dataset_uri Dataset URI
# @return [text/uri-list] Task URI
post '/openbabel' do
task = OpenTox::Task.create("Calculating OpenBabel descriptors for #{params[:dataset_uri]}", url_for('/openbabel',:full)) do
dataset = OpenTox::Dataset.find(params[:dataset_uri])
result_dataset = OpenTox::Dataset.create
result_dataset.add_metadata({
DC.title => "OpenBabel descriptors for " + dataset.metadata[DC.title].to_s,
DC.creator => url_for('/openbabel',:full),
OT.hasSource => url_for('/openbabel', :full),
OT.parameters => [
{ DC.title => "dataset_uri", OT.paramValue => params[:dataset_uri] },
]
})
obconversion = OpenBabel::OBConversion.new
obmol = OpenBabel::OBMol.new
obconversion.set_in_and_out_formats 'inchi', 'can'
OBMOL_METHODS.merge(OBDESCRIPTOR_METHODS).each do |name,description|
feature_uri = File.join result_dataset.uri, "feature", "openbabel", name
metadata = {
OT.hasSource => url_for("/openbabel/#{name}", :full),
DC.description => description,
DC.title => name,
}
result_dataset.add_feature feature_uri, metadata
end
dataset.compounds.each do |compound_uri|
compound = OpenTox::Compound.new(compound_uri)
obconversion.read_string obmol, compound.to_inchi
#result_dataset.add_compound compound_uri
OBMOL_METHODS.keys.each do |name|
feature_uri = File.join result_dataset.uri, "feature", "openbabel", name
value = eval("obmol.#{name.underscore}").to_f
result_dataset.add compound_uri, feature_uri, value
end
OBDESCRIPTOR_METHODS.keys.each do |name|
feature_uri = File.join result_dataset.uri, "feature", "openbabel", name
value = OpenBabel::OBDescriptor.find_type(params[:property]).predict(obmol).to_f
result_dataset.add compound_uri, feature_uri, value
end
end
result_dataset.save
result_dataset.uri
end
response['Content-Type'] = 'text/uri-list'
raise OpenTox::ServiceUnavailableError.newtask.uri+"\n" if task.status == "Cancelled"
halt 202,task.uri.to_s+"\n"
end
|