chemspider 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/chem_spider.rb +456 -0
- data/lib/chem_spider/services/in_ch_i.rb +79 -0
- data/lib/chem_spider/services/mass_spec_a_p_i.rb +128 -0
- data/lib/chem_spider/services/open_babel.rb +7 -0
- data/lib/chem_spider/services/search.rb +150 -0
- data/lib/chem_spider/services/spectra.rb +79 -0
- data/lib/chem_spider/version.rb +22 -0
- data/lib/chemspider.rb +1 -0
- metadata +73 -0
data/lib/chem_spider.rb
ADDED
@@ -0,0 +1,456 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require 'net/http'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
module ChemSpider
|
8
|
+
class << self
|
9
|
+
##
|
10
|
+
# Returns the result of calling the specified ChemSpider Web service using the HTTP/1.1 "GET" method.
|
11
|
+
#
|
12
|
+
# @example Convert an InChIKey into a ChemSpider ID.
|
13
|
+
# ##
|
14
|
+
# # http://www.chemspider.com/InChI.asmx/InChIKeyToCSID?inchi_key=BSYNRYMUTXBXSQ-UHFFFAOYSA-N
|
15
|
+
# # => <string xmlns="http://www.chemspider.com/">2157</string>
|
16
|
+
# #
|
17
|
+
# ChemSpider.get!(:InChI, :InChIKeyToCSID, { :inchi_key => 'BSYNRYMUTXBXSQ-UHFFFAOYSA-N' }, {}, {
|
18
|
+
# :selector => 'string',
|
19
|
+
# :datatype => Integer,
|
20
|
+
# :first_child => true,
|
21
|
+
# })
|
22
|
+
# #=> 2157
|
23
|
+
#
|
24
|
+
# @example Convert an InChIKey into a ChemSpider ID using a proxy server.
|
25
|
+
# ##
|
26
|
+
# # https://www.example.com:443/chemspider/InChI/InChIKeyToCSID?inchi_key=BSYNRYMUTXBXSQ-UHFFFAOYSA-N
|
27
|
+
# # => <string xmlns="http://www.chemspider.com/">2157</string>
|
28
|
+
# #
|
29
|
+
# ChemSpider.get!(:InChI, :InChIKeyToCSID, { :inchi_key => 'BSYNRYMUTXBXSQ-UHFFFAOYSA-N' }, {
|
30
|
+
# :scheme => :https,
|
31
|
+
# :host => 'www.example.com',
|
32
|
+
# :port => 443,
|
33
|
+
# :path_format => '/chemspider/%s/%s',
|
34
|
+
# }, {
|
35
|
+
# :selector => 'string',
|
36
|
+
# :datatype => Integer,
|
37
|
+
# :first_child => true,
|
38
|
+
# })
|
39
|
+
# #=> 2157
|
40
|
+
#
|
41
|
+
# @param [#to_s] service_name
|
42
|
+
# @param [#to_s] operation_name
|
43
|
+
# @param [Hash] params (Hash.new)
|
44
|
+
# @option uri_options [#to_s] :scheme ('http')
|
45
|
+
# @option uri_options [#to_s] :host ('www.chemspider.com')
|
46
|
+
# @option uri_options [#to_s] :port (80)
|
47
|
+
# @option uri_options [#to_s] :path (nil)
|
48
|
+
# @option uri_options [#to_s] :path_format ('/%s.asmx/%s')
|
49
|
+
# @option uri_options [#to_s] :query (nil)
|
50
|
+
# @option uri_options [#to_s] :fragment (nil)
|
51
|
+
# @option options [#to_s] :selector (nil)
|
52
|
+
# @option options [Hash, Class, #__attributes__, #new] :datatype (Hash.new)
|
53
|
+
# @option options [Boolean] :first_child (false)
|
54
|
+
#
|
55
|
+
# @return [Object]
|
56
|
+
#
|
57
|
+
# @see ChemSpider#css
|
58
|
+
# @see ChemSpider#uri_for
|
59
|
+
#
|
60
|
+
def get!(service_name, operation_name, params = {}, uri_options = {}, options = {})
|
61
|
+
# construct the URI...
|
62
|
+
uri = uri_for(service_name, operation_name, params, uri_options)
|
63
|
+
|
64
|
+
# dereference the URI...
|
65
|
+
response = Net::HTTP.get_response(uri)
|
66
|
+
|
67
|
+
# parse the response...
|
68
|
+
doc = Nokogiri::XML(response.body)
|
69
|
+
|
70
|
+
# process the result...
|
71
|
+
css(doc, options)
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Returns the result of calling the specified ChemSpider Web service using the HTTP/1.1 "POST" method.
|
76
|
+
#
|
77
|
+
# @example Convert an InChIKey into a ChemSpider ID.
|
78
|
+
# ##
|
79
|
+
# # http://www.chemspider.com/InChI.asmx/InChIKeyToCSID?inchi_key=BSYNRYMUTXBXSQ-UHFFFAOYSA-N
|
80
|
+
# # => <string xmlns="http://www.chemspider.com/">2157</string>
|
81
|
+
# #
|
82
|
+
# ChemSpider.post!(:InChI, :InChIKeyToCSID, { :inchi_key => 'BSYNRYMUTXBXSQ-UHFFFAOYSA-N' }, {}, {
|
83
|
+
# :selector => 'string',
|
84
|
+
# :datatype => Integer,
|
85
|
+
# :first_child => true,
|
86
|
+
# })
|
87
|
+
# #=> 2157
|
88
|
+
#
|
89
|
+
# @example Convert an InChIKey into a ChemSpider ID using a proxy server.
|
90
|
+
# ##
|
91
|
+
# # https://www.example.com:443/chemspider/InChI/InChIKeyToCSID?inchi_key=BSYNRYMUTXBXSQ-UHFFFAOYSA-N
|
92
|
+
# # => <string xmlns="http://www.chemspider.com/">2157</string>
|
93
|
+
# #
|
94
|
+
# ChemSpider.post!(:InChI, :InChIKeyToCSID, { :inchi_key => 'BSYNRYMUTXBXSQ-UHFFFAOYSA-N' }, {
|
95
|
+
# :scheme => :https,
|
96
|
+
# :host => 'www.example.com',
|
97
|
+
# :port => 443,
|
98
|
+
# :path_format => '/chemspider/%s/%s',
|
99
|
+
# }, {
|
100
|
+
# :selector => 'string',
|
101
|
+
# :datatype => Integer,
|
102
|
+
# :first_child => true,
|
103
|
+
# })
|
104
|
+
# #=> 2157
|
105
|
+
#
|
106
|
+
# @param [#to_s] service_name
|
107
|
+
# @param [#to_s] operation_name
|
108
|
+
# @param [Hash] params (Hash.new)
|
109
|
+
# @option uri_options [#to_s] :scheme ('http')
|
110
|
+
# @option uri_options [#to_s] :host ('www.chemspider.com')
|
111
|
+
# @option uri_options [#to_s] :port (80)
|
112
|
+
# @option uri_options [#to_s] :path (nil)
|
113
|
+
# @option uri_options [#to_s] :path_format ('/%s.asmx/%s')
|
114
|
+
# @option uri_options [#to_s] :query (nil)
|
115
|
+
# @option uri_options [#to_s] :fragment (nil)
|
116
|
+
# @option options [#to_s] :selector (nil)
|
117
|
+
# @option options [Hash, Class, #__attributes__, #new] :datatype (Hash.new)
|
118
|
+
# @option options [Boolean] :first_child (false)
|
119
|
+
#
|
120
|
+
# @return [Object]
|
121
|
+
#
|
122
|
+
# @see ChemSpider#css
|
123
|
+
# @see ChemSpider#uri_for
|
124
|
+
#
|
125
|
+
def post!(service_name, operation_name, params = {}, uri_options = {}, options = {})
|
126
|
+
# construct the URI...
|
127
|
+
uri = uri_for(service_name, operation_name, nil, uri_options)
|
128
|
+
|
129
|
+
# dereference the URI...
|
130
|
+
response = Net::HTTP.post_form(uri, params)
|
131
|
+
|
132
|
+
# parse the response...
|
133
|
+
doc = Nokogiri::XML(response.body)
|
134
|
+
|
135
|
+
# process the result...
|
136
|
+
css(doc, options)
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
##
|
142
|
+
# Macro to define the Ruby modules and methods for a ChemSpider Web service.
|
143
|
+
#
|
144
|
+
# @example
|
145
|
+
# m = ChemSpider.REST(:InChI, :InChIKeyToCSID, %w{inchi_key}, {
|
146
|
+
# :selector => 'string',
|
147
|
+
# :datatype => Integer,
|
148
|
+
# :first_child => true,
|
149
|
+
# })
|
150
|
+
# m.get!('BSYNRYMUTXBXSQ-UHFFFAOYSA-N')
|
151
|
+
# #=> 2157
|
152
|
+
# m.get!(:inchi_key => 'BSYNRYMUTXBXSQ-UHFFFAOYSA-N')
|
153
|
+
# #=> 2157
|
154
|
+
# m.post!('BSYNRYMUTXBXSQ-UHFFFAOYSA-N')
|
155
|
+
# #=> 2157
|
156
|
+
# m.post!(:inchi_key => 'BSYNRYMUTXBXSQ-UHFFFAOYSA-N')
|
157
|
+
# #=> 2157
|
158
|
+
#
|
159
|
+
# @param [#to_s] service_name
|
160
|
+
# @param [#to_s] operation_name
|
161
|
+
# @param [Array<String>] param_names
|
162
|
+
# @option options [#to_s] :selector (nil)
|
163
|
+
# @option options [Hash, Class, #__attributes__, #new] :datatype (Hash.new)
|
164
|
+
# @option options [Boolean] :first_child (false)
|
165
|
+
#
|
166
|
+
# @return [Module]
|
167
|
+
#
|
168
|
+
# @see ChemSpider#get!
|
169
|
+
# @see ChemSpider#post!
|
170
|
+
#
|
171
|
+
def REST(service_name, operation_name, param_names = [], options = {})
|
172
|
+
# find/create the specified module...
|
173
|
+
# #=> "ChemSpider::#{service_name}::#{operation_name}"
|
174
|
+
mod = [service_name, operation_name].inject(self) { |acc, s|
|
175
|
+
begin
|
176
|
+
acc.send(:const_get, s.to_sym)
|
177
|
+
rescue NameError
|
178
|
+
acc.send(:const_set, s.to_sym, Module.new)
|
179
|
+
end
|
180
|
+
}
|
181
|
+
|
182
|
+
# [re]define the methods...
|
183
|
+
%w{get! post!}.each do |method_name|
|
184
|
+
##
|
185
|
+
# @see ChemSpider#get!
|
186
|
+
# @see ChemSpider#post!
|
187
|
+
mod.send(:define_method, method_name.to_sym) do |*args|
|
188
|
+
# the default `uri_options` argument is an empty Hash
|
189
|
+
uri_options = {}
|
190
|
+
|
191
|
+
args_as_hash = nil
|
192
|
+
|
193
|
+
# minimal implementation of the ActiveSupport `Module#extract_options!` method...
|
194
|
+
case args.length
|
195
|
+
when 2
|
196
|
+
uri_options = args.pop if args.last.is_a?(Hash)
|
197
|
+
|
198
|
+
args_as_hash = args.pop if args.last.is_a?(Hash)
|
199
|
+
when 1
|
200
|
+
args_as_hash = args.pop if args.last.is_a?(Hash)
|
201
|
+
else
|
202
|
+
uri_options = args.pop if args.last.is_a?(Hash)
|
203
|
+
end
|
204
|
+
|
205
|
+
params = nil
|
206
|
+
|
207
|
+
if args_as_hash.nil?
|
208
|
+
params = {}
|
209
|
+
|
210
|
+
# treat `args' as an ordered list with a 1-1 correspondence
|
211
|
+
# between each element and the list of parameter names...
|
212
|
+
param_names.each_with_index do |param_name, idx|
|
213
|
+
params[param_name] = args[idx]
|
214
|
+
end
|
215
|
+
else
|
216
|
+
# treat `args' as a "HashWithIndifferentAccess" (in Ruby on Rails parlance)...
|
217
|
+
params = param_names.inject({}) { |acc, param_name|
|
218
|
+
if args_as_hash.key?(param_name)
|
219
|
+
acc[param_name] = args_as_hash[param_name]
|
220
|
+
elsif args_as_hash.key?(param_name.to_s)
|
221
|
+
acc[param_name] = args_as_hash[param_name.to_s]
|
222
|
+
elsif args_as_hash.key?(param_name.to_sym)
|
223
|
+
acc[param_name] = args_as_hash[param_name.to_sym]
|
224
|
+
end
|
225
|
+
|
226
|
+
acc
|
227
|
+
}
|
228
|
+
end
|
229
|
+
|
230
|
+
ChemSpider.send(method_name.to_sym, service_name, operation_name, params, uri_options, options)
|
231
|
+
end
|
232
|
+
|
233
|
+
# make the method a "module function"...
|
234
|
+
mod.send(:module_function, method_name.to_sym)
|
235
|
+
end
|
236
|
+
|
237
|
+
##
|
238
|
+
# @return [String]
|
239
|
+
mod.send(:define_method, :chem_spider_service_name) do ||
|
240
|
+
service_name.to_s
|
241
|
+
end
|
242
|
+
|
243
|
+
##
|
244
|
+
# @return [String]
|
245
|
+
mod.send(:define_method, :chem_spider_operation_name) do ||
|
246
|
+
operation_name.to_s
|
247
|
+
end
|
248
|
+
|
249
|
+
##
|
250
|
+
# @return [Array<String>]
|
251
|
+
mod.send(:define_method, :chem_spider_param_names) do ||
|
252
|
+
param_names.collect(&:to_s)
|
253
|
+
end
|
254
|
+
|
255
|
+
##
|
256
|
+
# @return [Hash]
|
257
|
+
mod.send(:define_method, :chem_spider_options) do ||
|
258
|
+
options.dup
|
259
|
+
end
|
260
|
+
|
261
|
+
mod.send(:module_function, :chem_spider_service_name, :chem_spider_operation_name, :chem_spider_param_names, :chem_spider_options)
|
262
|
+
|
263
|
+
# done!
|
264
|
+
return mod
|
265
|
+
end
|
266
|
+
|
267
|
+
##
|
268
|
+
# Returns a unary callable that casts the argument to the specified `Class`.
|
269
|
+
#
|
270
|
+
# @param [Class] klass
|
271
|
+
#
|
272
|
+
# @return [#call]
|
273
|
+
#
|
274
|
+
def cast_for(klass)
|
275
|
+
# lazily construct the set of callables...
|
276
|
+
@casts ||= {
|
277
|
+
TrueClass => Proc.new { |s| s.downcase == 'true' },
|
278
|
+
DateTime => Proc.new { |s| DateTime.parse(s) },
|
279
|
+
Float => Proc.new { |s| s.to_f },
|
280
|
+
Integer => Proc.new { |s| s.to_i },
|
281
|
+
String => Proc.new { |s| s },
|
282
|
+
URI => Proc.new { |s| URI.parse(s) },
|
283
|
+
}.freeze
|
284
|
+
|
285
|
+
# raise an exception if no callable is available for the specified `Class`...
|
286
|
+
raise "Unsupported cast: #{klass}" unless @casts.key?(klass)
|
287
|
+
|
288
|
+
# return the match...
|
289
|
+
@casts[klass]
|
290
|
+
end
|
291
|
+
|
292
|
+
##
|
293
|
+
# Extracts nodes specified by a CSS selector, and casts the result.
|
294
|
+
#
|
295
|
+
# @param [Nokogiri::XML::Node] doc
|
296
|
+
# @option options [#to_s] :selector (nil)
|
297
|
+
# @option options [Class, Hash, #__attributes__, #new] :datatype (Hash.new)
|
298
|
+
# @option options [Boolean] :first_child (false)
|
299
|
+
#
|
300
|
+
# @return [Object]
|
301
|
+
#
|
302
|
+
# @see ChemSpider#cast_for
|
303
|
+
#
|
304
|
+
def css(doc, options = {})
|
305
|
+
# evaluate the CSS selector...
|
306
|
+
nodes = doc.css(options[:selector].to_s)
|
307
|
+
|
308
|
+
# lazily initialize the datatype to `Hash.new`...
|
309
|
+
if !(datatype = (options[:datatype] || {})).nil?
|
310
|
+
# the set of attributes...
|
311
|
+
attributes = nil
|
312
|
+
|
313
|
+
# specifies whether or not we should reify the result (by passing it to a constructor)...
|
314
|
+
responds_to_new = nil
|
315
|
+
|
316
|
+
# test if the datatype responds to the duck typing method...
|
317
|
+
if datatype.respond_to?(:__attributes__)
|
318
|
+
# extract the set of attributes from the datatype...
|
319
|
+
attributes = datatype.send(:__attributes__)
|
320
|
+
|
321
|
+
# test if we should reify the result, i.e., does the datatype have a constructor?
|
322
|
+
responds_to_new = datatype.respond_to?(:new)
|
323
|
+
elsif datatype.is_a?(Hash)
|
324
|
+
# the datatype "is" the set of attributes...
|
325
|
+
attributes = datatype
|
326
|
+
|
327
|
+
# do not reify the result...
|
328
|
+
responds_to_new = false
|
329
|
+
end
|
330
|
+
|
331
|
+
# test if the set of attributes is valid...
|
332
|
+
if attributes.is_a?(Hash)
|
333
|
+
# recursively extract each node...
|
334
|
+
nodes = nodes.map { |node|
|
335
|
+
attributes.inject({}) { |acc, pair|
|
336
|
+
acc[pair.first] = css(node, pair.last)
|
337
|
+
acc
|
338
|
+
}
|
339
|
+
}
|
340
|
+
|
341
|
+
# reify the extracted results (if needed)...
|
342
|
+
nodes = nodes.map { |*args| datatype.send(:new, *args) } if responds_to_new
|
343
|
+
else
|
344
|
+
# extract the content of each node, and cast the result...
|
345
|
+
nodes = nodes.map { |node| node.content.to_s }.map(&cast_for(datatype))
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
# return either the first result, or all of the results...
|
350
|
+
!!options[:first_child] ? nodes.first : nodes
|
351
|
+
end
|
352
|
+
|
353
|
+
##
|
354
|
+
# Constructs the query string of an URL using the specified key-value pairs.
|
355
|
+
#
|
356
|
+
# @example Construct a query string with univalued parameters.
|
357
|
+
# ChemSpider.query_for(:foo => 'bar', :alice => 'bob') #=> 'foo=bar&alice=bob'
|
358
|
+
#
|
359
|
+
# @example Construct a query string with multivalued parameters.
|
360
|
+
# ChemSpider.query_for(:letters => %w{a b c}) #=> 'letters=a&letters=b&letters=c'
|
361
|
+
#
|
362
|
+
# @param [Array, Hash] pairs
|
363
|
+
#
|
364
|
+
# @return [#to_s]
|
365
|
+
#
|
366
|
+
def query_for(pairs)
|
367
|
+
return nil if pairs.nil? || pairs.empty?
|
368
|
+
|
369
|
+
pairs.map { |pair|
|
370
|
+
# if the "key" is multi-valued, i.e., if the "value" is an Array...
|
371
|
+
if pair.last.is_a?(Array)
|
372
|
+
# recur...
|
373
|
+
query_for(pair.last.map { |value| [pair.first, value] })
|
374
|
+
else
|
375
|
+
# ensure that the components are encoded...
|
376
|
+
pair.map { |s| URI.encode(s.to_s) }.join('=')
|
377
|
+
end
|
378
|
+
}.join('&')
|
379
|
+
end
|
380
|
+
|
381
|
+
##
|
382
|
+
# Constructs the URI for a request to a ChemSpider Web service.
|
383
|
+
#
|
384
|
+
# @example Construct a URI.
|
385
|
+
# ChemSpider.uri_for(:InChI, :InChIKeyToCSID, :inchi_key => 'BSYNRYMUTXBXSQ-UHFFFAOYSA-N')
|
386
|
+
# #=> #<URI::HTTP:0x1003d2308 URL:http://www.chemspider.com/InChI.asmx/InChIKeyToCSID?inchi_key=BSYNRYMUTXBXSQ-UHFFFAOYSA-N>
|
387
|
+
#
|
388
|
+
# @example Construct a URI for a proxy server.
|
389
|
+
# ChemSpider.uri_for(:InChI, :InChIKeyToCSID, { :inchi_key => 'BSYNRYMUTXBXSQ-UHFFFAOYSA-N' }, {
|
390
|
+
# :scheme => :https,
|
391
|
+
# :host => 'www.example.com',
|
392
|
+
# :port => 443,
|
393
|
+
# :path_format => '/chemspider/%s/%s',
|
394
|
+
# })
|
395
|
+
# #=> #<URI::HTTP:0x101990e88 URL:http://www.example.com:443/chemspider/InChI/InChIKeyToCSID?inchi_key=BSYNRYMUTXBXSQ-UHFFFAOYSA-N>
|
396
|
+
#
|
397
|
+
# @param [#to_s] service_name
|
398
|
+
# @param [#to_s] operation_name
|
399
|
+
# @param [Hash] params (Hash.new)
|
400
|
+
# @option options [#to_s] :scheme ('http')
|
401
|
+
# @option options [#to_s] :host ('www.chemspider.com')
|
402
|
+
# @option options [#to_s] :port (80)
|
403
|
+
# @option options [#to_s] :path (nil)
|
404
|
+
# @option options [#to_s] :path_format ('/%s.asmx/%s')
|
405
|
+
# @option options [#to_s] :query (nil)
|
406
|
+
# @option options [#to_s] :fragment (nil)
|
407
|
+
#
|
408
|
+
# @return [URI]
|
409
|
+
#
|
410
|
+
# @see ChemSpider#query_for
|
411
|
+
#
|
412
|
+
def uri_for(service_name, operation_name, params = {}, options = {})
|
413
|
+
# initialize the format string for the base URI "scheme://host:port"...
|
414
|
+
format = '%s://%s:%s'
|
415
|
+
format_args = [
|
416
|
+
options[:scheme] || :http,
|
417
|
+
options[:host] || 'www.chemspider.com',
|
418
|
+
options[:port] || 80,
|
419
|
+
]
|
420
|
+
|
421
|
+
if path = options[:path]
|
422
|
+
# use the custom path (if specified)...
|
423
|
+
format += '%s'
|
424
|
+
format_args << path
|
425
|
+
elsif path_format = (options[:path_format] || '/%s.asmx/%s')
|
426
|
+
# otherwise, format the path...
|
427
|
+
format += path_format
|
428
|
+
format_args << service_name
|
429
|
+
format_args << operation_name
|
430
|
+
end
|
431
|
+
|
432
|
+
# concatinate the constructed and specified query strings (`params` and `options[:query]`)...
|
433
|
+
if !(query = [options[:query], query_for(params)].compact.map(&:to_s).map(&:strip).reject(&:empty?)).empty?
|
434
|
+
format += '?%s'
|
435
|
+
format_args << query.join('&')
|
436
|
+
end
|
437
|
+
|
438
|
+
if fragment = options[:fragment]
|
439
|
+
# use the custom fragment (if specified...)
|
440
|
+
format += '#%s'
|
441
|
+
format_args << fragment
|
442
|
+
end
|
443
|
+
|
444
|
+
# evaluate the format string for the given arguments, and parse the result...
|
445
|
+
URI.parse(format % format_args)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
require 'chem_spider/version'
|
451
|
+
|
452
|
+
require 'chem_spider/services/in_ch_i'
|
453
|
+
require 'chem_spider/services/mass_spec_a_p_i'
|
454
|
+
require 'chem_spider/services/open_babel'
|
455
|
+
require 'chem_spider/services/search'
|
456
|
+
require 'chem_spider/services/spectra'
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module ChemSpider
|
2
|
+
REST(:InChI, :CSIDToMol, %w{csid token}, {
|
3
|
+
:selector => 'string',
|
4
|
+
:datatype => String,
|
5
|
+
:first_child => true,
|
6
|
+
})
|
7
|
+
|
8
|
+
REST(:InChI, :InChIKeyToCSID, %w{inchi_key}, {
|
9
|
+
:selector => 'string',
|
10
|
+
:datatype => Integer,
|
11
|
+
:first_child => true,
|
12
|
+
})
|
13
|
+
|
14
|
+
REST(:InChI, :InChIKeyToInChI, %w{inchi_key}, {
|
15
|
+
:selector => 'string',
|
16
|
+
:datatype => String,
|
17
|
+
:first_child => true,
|
18
|
+
})
|
19
|
+
|
20
|
+
REST(:InChI, :InChIKeyToMol, %w{inchi_key}, {
|
21
|
+
:selector => 'string',
|
22
|
+
:datatype => String,
|
23
|
+
:first_child => true,
|
24
|
+
})
|
25
|
+
|
26
|
+
REST(:InChI, :InChIToCSID, %w{inchi}, {
|
27
|
+
:selector => 'string',
|
28
|
+
:datatype => Integer,
|
29
|
+
:first_child => true,
|
30
|
+
})
|
31
|
+
|
32
|
+
REST(:InChI, :InChIToInChIKey, %{inchi}, {
|
33
|
+
:selector => 'string',
|
34
|
+
:datatype => String,
|
35
|
+
:first_child => true,
|
36
|
+
})
|
37
|
+
|
38
|
+
REST(:InChI, :InChIToMol, %w{inchi}, {
|
39
|
+
:selector => 'string',
|
40
|
+
:datatype => String,
|
41
|
+
:first_child => true,
|
42
|
+
})
|
43
|
+
|
44
|
+
REST(:InChI, :InChIToSMILES, %w{inchi}, {
|
45
|
+
:selector => 'string',
|
46
|
+
:datatype => String,
|
47
|
+
:first_child => true,
|
48
|
+
})
|
49
|
+
|
50
|
+
REST(:InChI, :IsValidInChIKey, %w{inchi_key}, {
|
51
|
+
:selector => 'boolean',
|
52
|
+
:datatype => TrueClass,
|
53
|
+
:first_child => true,
|
54
|
+
})
|
55
|
+
|
56
|
+
REST(:InChI, :MolToInChI, %w{mol}, {
|
57
|
+
:selector => 'string',
|
58
|
+
:datatype => String,
|
59
|
+
:first_child => true,
|
60
|
+
})
|
61
|
+
|
62
|
+
REST(:InChI, :MolToInChIKey, %w{mol}, {
|
63
|
+
:selector => 'string',
|
64
|
+
:datatype => String,
|
65
|
+
:first_child => true,
|
66
|
+
})
|
67
|
+
|
68
|
+
REST(:InChI, :ResolveInChIKey, %w{inchi_key out_format}, {
|
69
|
+
:selector => 'ArrayOfString string',
|
70
|
+
:datatype => String,
|
71
|
+
:first_child => false,
|
72
|
+
})
|
73
|
+
|
74
|
+
REST(:InChI, :SMILESToInChI, %w{smiles}, {
|
75
|
+
:selector => 'string',
|
76
|
+
:datatype => String,
|
77
|
+
:first_child => true,
|
78
|
+
})
|
79
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module ChemSpider
|
2
|
+
class ExtendedCompoundInfo
|
3
|
+
ATTRIBUTES = {
|
4
|
+
:csid => {
|
5
|
+
:selector => 'CSID',
|
6
|
+
:datatype => Integer,
|
7
|
+
:first_child => true,
|
8
|
+
},
|
9
|
+
:molecular_formula => {
|
10
|
+
:selector => 'MF',
|
11
|
+
:datatype => String,
|
12
|
+
:first_child => true,
|
13
|
+
},
|
14
|
+
:smiles => {
|
15
|
+
:selector => 'SMILES',
|
16
|
+
:datatype => String,
|
17
|
+
:first_child => true,
|
18
|
+
},
|
19
|
+
:inchi => {
|
20
|
+
:selector => 'InChI',
|
21
|
+
:datatype => String,
|
22
|
+
:first_child => true,
|
23
|
+
},
|
24
|
+
:inchi_key => {
|
25
|
+
:selector => 'InChIKey',
|
26
|
+
:datatype => String,
|
27
|
+
:first_child => true,
|
28
|
+
},
|
29
|
+
:average_mass => {
|
30
|
+
:selector => 'AverageMass',
|
31
|
+
:datatype => Float,
|
32
|
+
:first_child => true,
|
33
|
+
},
|
34
|
+
:molecular_weight => {
|
35
|
+
:selector => 'MolecularWeight',
|
36
|
+
:datatype => Float,
|
37
|
+
:first_child => true,
|
38
|
+
},
|
39
|
+
:monoisotopic_mass => {
|
40
|
+
:selector => 'MonoisotopicMass',
|
41
|
+
:datatype => Float,
|
42
|
+
:first_child => true,
|
43
|
+
},
|
44
|
+
:nominal_mass => {
|
45
|
+
:selector => 'NominalMass',
|
46
|
+
:datatype => Float,
|
47
|
+
:first_child => true,
|
48
|
+
},
|
49
|
+
:a_log_p => {
|
50
|
+
:selector => 'ALogP',
|
51
|
+
:datatype => Float,
|
52
|
+
:first_child => true,
|
53
|
+
},
|
54
|
+
:x_log_p => {
|
55
|
+
:selector => 'XLogP',
|
56
|
+
:datatype => Float,
|
57
|
+
:first_child => true,
|
58
|
+
},
|
59
|
+
:common_name => {
|
60
|
+
:selector => 'CommonName',
|
61
|
+
:datatype => String,
|
62
|
+
:first_child => true,
|
63
|
+
},
|
64
|
+
}.freeze
|
65
|
+
|
66
|
+
class << self
|
67
|
+
def __attributes__
|
68
|
+
ATTRIBUTES
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
attr_reader *ATTRIBUTES.keys
|
73
|
+
|
74
|
+
def initialize(attributes = {})
|
75
|
+
ATTRIBUTES.keys.each do |attr_name|
|
76
|
+
instance_variable_set(:"@#{attr_name}", attributes[attr_name])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
REST(:MassSpecAPI, :GetCompressedRecordsSdf, %w{rid token eComp}, {
|
82
|
+
:selector => 'base64Binary',
|
83
|
+
:datatype => String,
|
84
|
+
:first_child => true,
|
85
|
+
})
|
86
|
+
|
87
|
+
REST(:MassSpecAPI, :GetDatabases, %w{}, {
|
88
|
+
:selector => 'ArrayOfString string',
|
89
|
+
:datatype => String,
|
90
|
+
:first_child => false,
|
91
|
+
})
|
92
|
+
|
93
|
+
REST(:MassSpecAPI, :GetExtendedCompoundInfo, %w{CSID token}, {
|
94
|
+
:selector => 'ExtendedCompoundInfo',
|
95
|
+
:datatype => ChemSpider::ExtendedCompoundInfo,
|
96
|
+
:first_child => true,
|
97
|
+
})
|
98
|
+
|
99
|
+
REST(:MassSpecAPI, :GetExtendedCompoundInfoArray, %w{CSIDs token}, {
|
100
|
+
:selector => 'ArrayOfExtendedCompoundInfo ExtendedCompoundInfo',
|
101
|
+
:datatype => ChemSpider::ExtendedCompoundInfo,
|
102
|
+
:first_child => false,
|
103
|
+
})
|
104
|
+
|
105
|
+
REST(:MassSpecAPI, :GetRecordMol, %w{csid calc3d token}, {
|
106
|
+
:selector => 'string',
|
107
|
+
:datatype => String,
|
108
|
+
:first_child => true,
|
109
|
+
})
|
110
|
+
|
111
|
+
REST(:MassSpecAPI, :GetRecordsSdf, %w{rid token}, {
|
112
|
+
:selector => 'string',
|
113
|
+
:datatype => String,
|
114
|
+
:first_child => true,
|
115
|
+
})
|
116
|
+
|
117
|
+
REST(:MassSpecAPI, :SearchByFormula2, %w{formula}, {
|
118
|
+
:selector => 'ArrayOfString string',
|
119
|
+
:datatype => String,
|
120
|
+
:first_child => false,
|
121
|
+
})
|
122
|
+
|
123
|
+
REST(:MassSpecAPI, :SearchByMass2, %w{mass range}, {
|
124
|
+
:selector => 'ArrayOfString string',
|
125
|
+
:datatype => String,
|
126
|
+
:first_child => false,
|
127
|
+
})
|
128
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
module ChemSpider
|
2
|
+
class CompoundInfo
|
3
|
+
ATTRIBUTES = {
|
4
|
+
:csid => {
|
5
|
+
:selector => 'CSID',
|
6
|
+
:datatype => Integer,
|
7
|
+
:first_child => true,
|
8
|
+
},
|
9
|
+
:inchi => {
|
10
|
+
:selector => 'InChI',
|
11
|
+
:datatype => String,
|
12
|
+
:first_child => true,
|
13
|
+
},
|
14
|
+
:inchi_key => {
|
15
|
+
:selector => 'InChIKey',
|
16
|
+
:datatype => String,
|
17
|
+
:first_child => true,
|
18
|
+
},
|
19
|
+
:smiles => {
|
20
|
+
:selector => 'SMILES',
|
21
|
+
:datatype => String,
|
22
|
+
:first_child => true,
|
23
|
+
},
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def __attributes__
|
28
|
+
ATTRIBUTES
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader *ATTRIBUTES.keys
|
33
|
+
|
34
|
+
def initialize(attributes = {})
|
35
|
+
ATTRIBUTES.keys.each do |attr_name|
|
36
|
+
instance_variable_set(:"@#{attr_name}", attributes[attr_name])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class ExtRef
|
42
|
+
ATTRIBUTES = {
|
43
|
+
:csid => {
|
44
|
+
:selector => 'CSID',
|
45
|
+
:datatype => Integer,
|
46
|
+
:first_child => true,
|
47
|
+
},
|
48
|
+
:ds_name => {
|
49
|
+
:selector => 'ds_name',
|
50
|
+
:datatype => String,
|
51
|
+
:first_child => true,
|
52
|
+
},
|
53
|
+
:ds_url => {
|
54
|
+
:selector => 'ds_url',
|
55
|
+
:datatype => URI,
|
56
|
+
:first_child => true,
|
57
|
+
},
|
58
|
+
:ext_id => {
|
59
|
+
:selector => 'ext_id',
|
60
|
+
:datatype => String,
|
61
|
+
:first_child => true,
|
62
|
+
},
|
63
|
+
:ext_url => {
|
64
|
+
:selector => 'ext_url',
|
65
|
+
:datatype => URI,
|
66
|
+
:first_child => true,
|
67
|
+
},
|
68
|
+
}.freeze
|
69
|
+
|
70
|
+
class << self
|
71
|
+
def __attributes__
|
72
|
+
ATTRIBUTES
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
attr_reader *ATTRIBUTES.keys
|
77
|
+
|
78
|
+
def initialize(attributes = {})
|
79
|
+
ATTRIBUTES.keys.each do |attr_name|
|
80
|
+
instance_variable_set(:"@#{attr_name}", attributes[attr_name])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
REST(:Search, :AsyncSimpleSearch, %w{query token}, {
|
86
|
+
:selector => 'string',
|
87
|
+
:datatype => String,
|
88
|
+
:first_child => true,
|
89
|
+
})
|
90
|
+
|
91
|
+
REST(:Search, :CSID2ExtRefs, %w{CSID datasources token}, {
|
92
|
+
:selector => 'ArrayOfExtRef ExtRef',
|
93
|
+
:datatype => ChemSpider::ExtRef,
|
94
|
+
:first_child => false,
|
95
|
+
})
|
96
|
+
|
97
|
+
REST(:Search, :GetAsyncSearchResult, %w{rid token}, {
|
98
|
+
:selector => 'ArrayOfInt int',
|
99
|
+
:datatype => Integer,
|
100
|
+
:first_child => false,
|
101
|
+
})
|
102
|
+
|
103
|
+
REST(:Search, :GetAsyncSearchResultPart, %w{rid token start count}, {
|
104
|
+
:selector => 'ArrayOfInt int',
|
105
|
+
:datatype => Integer,
|
106
|
+
:first_child => false,
|
107
|
+
})
|
108
|
+
|
109
|
+
REST(:Search, :GetAsyncSearchStatus, %w{rid token}, {
|
110
|
+
:selector => 'ERequestStatus',
|
111
|
+
:datatype => String,
|
112
|
+
:first_child => true,
|
113
|
+
})
|
114
|
+
|
115
|
+
REST(:Search, :GetCompoundInfo, %w{CSID token}, {
|
116
|
+
:selector => 'CompoundInfo',
|
117
|
+
:datatype => ChemSpider::CompoundInfo,
|
118
|
+
:first_child => true,
|
119
|
+
})
|
120
|
+
|
121
|
+
REST(:Search, :GetCompoundThumbnail, %w{id token}, {
|
122
|
+
:selector => 'base64Binary',
|
123
|
+
:datatype => String,
|
124
|
+
:first_child => true,
|
125
|
+
})
|
126
|
+
|
127
|
+
REST(:Search, :GetDataSliceCompounds, %w{name token}, {
|
128
|
+
:selector => 'ArrayOfInt int',
|
129
|
+
:datatype => Integer,
|
130
|
+
:first_child => false,
|
131
|
+
})
|
132
|
+
|
133
|
+
REST(:Search, :Mol2CSID, %w{mol options token}, {
|
134
|
+
:selector => 'ArrayOfInt int',
|
135
|
+
:datatype => Integer,
|
136
|
+
:first_child => false,
|
137
|
+
})
|
138
|
+
|
139
|
+
REST(:Search, :MolAndDS2CSID, %w{mol options datasources token}, {
|
140
|
+
:selector => 'ArrayOfInt int',
|
141
|
+
:datatype => Integer,
|
142
|
+
:first_child => false,
|
143
|
+
})
|
144
|
+
|
145
|
+
REST(:Search, :SimpleSearch, %w{query token}, {
|
146
|
+
:selector => 'ArrayOfInt int',
|
147
|
+
:datatype => Integer,
|
148
|
+
:first_child => false,
|
149
|
+
})
|
150
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module ChemSpider
|
2
|
+
class SpectrumInfo
|
3
|
+
ATTRIBUTES = {
|
4
|
+
:spc_id => {
|
5
|
+
:selector => 'spc_id',
|
6
|
+
:datatype => Integer,
|
7
|
+
:first_child => true,
|
8
|
+
},
|
9
|
+
:spc_type => {
|
10
|
+
:selector => 'spc_type',
|
11
|
+
:datatype => String,
|
12
|
+
:first_child => true,
|
13
|
+
},
|
14
|
+
:csid => {
|
15
|
+
:selector => 'csid',
|
16
|
+
:datatype => Integer,
|
17
|
+
:first_child => true,
|
18
|
+
},
|
19
|
+
:file_name => {
|
20
|
+
:selector => 'file_name',
|
21
|
+
:datatype => String,
|
22
|
+
:first_child => true,
|
23
|
+
},
|
24
|
+
:comments => {
|
25
|
+
:selector => 'comments',
|
26
|
+
:datatype => String,
|
27
|
+
:first_child => true,
|
28
|
+
},
|
29
|
+
:original_url => {
|
30
|
+
:selector => 'original_url',
|
31
|
+
:datatype => URI,
|
32
|
+
:first_child => true,
|
33
|
+
},
|
34
|
+
:submitted_date => {
|
35
|
+
:selector => 'submitted_date',
|
36
|
+
:datatype => DateTime,
|
37
|
+
:first_child => true,
|
38
|
+
},
|
39
|
+
}.freeze
|
40
|
+
|
41
|
+
class << self
|
42
|
+
def __attributes__
|
43
|
+
ATTRIBUTES
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
attr_reader *ATTRIBUTES.keys
|
48
|
+
|
49
|
+
def initialize(attributes = {})
|
50
|
+
ATTRIBUTES.keys.each do |attr_name|
|
51
|
+
instance_variable_set(:"@#{attr_name}", attributes[attr_name])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
REST(:Spectra, :GetAllSpectraInfo, %w{token}, {
|
57
|
+
:selector => 'ArrayOfCSSpectrumInfo CSSpectrumInfo',
|
58
|
+
:datatype => ChemSpider::SpectrumInfo,
|
59
|
+
:first_child => false,
|
60
|
+
})
|
61
|
+
|
62
|
+
REST(:Spectra, :GetCompoundSpectraInfo, %w{csid token}, {
|
63
|
+
:selector => 'ArrayOfCSSpectrumInfo CSSpectrumInfo',
|
64
|
+
:datatype => ChemSpider::SpectrumInfo,
|
65
|
+
:first_child => false,
|
66
|
+
})
|
67
|
+
|
68
|
+
REST(:Spectra, :GetSpectraInfoArray, %w{CSIDs token}, {
|
69
|
+
:selector => 'ArrayOfCSSpectrumInfo CSSpectrumInfo',
|
70
|
+
:datatype => ChemSpider::SpectrumInfo,
|
71
|
+
:first_child => false,
|
72
|
+
})
|
73
|
+
|
74
|
+
REST(:Spectra, :GetSpectrumInfo, %w{spc_id token}, {
|
75
|
+
:selector => 'CSSpectrumInfo',
|
76
|
+
:datatype => ChemSpider::SpectrumInfo,
|
77
|
+
:first_child => true,
|
78
|
+
})
|
79
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ChemSpider
|
2
|
+
module VERSION
|
3
|
+
MAJOR = 0
|
4
|
+
MINOR = 0
|
5
|
+
TINY = 1
|
6
|
+
EXTRA = nil
|
7
|
+
|
8
|
+
STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
|
9
|
+
|
10
|
+
##
|
11
|
+
# @return [String]
|
12
|
+
def self.to_s() STRING end
|
13
|
+
|
14
|
+
##
|
15
|
+
# @return [String]
|
16
|
+
def self.to_str() STRING end
|
17
|
+
|
18
|
+
##
|
19
|
+
# @return [Array(Integer, Integer, Integer)]
|
20
|
+
def self.to_a() [MAJOR, MINOR, TINY] end
|
21
|
+
end
|
22
|
+
end
|
data/lib/chemspider.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'chem_spider'
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chemspider
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Mark Borkum
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-10-15 00:00:00 Z
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: The ChemSpider API (REST interface) wrapped up with a Ruby bow
|
22
|
+
email: m.i.borkum@soton.ac.uk
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- lib/chemspider.rb
|
31
|
+
- lib/chem_spider.rb
|
32
|
+
- lib/chem_spider/version.rb
|
33
|
+
- lib/chem_spider/services/in_ch_i.rb
|
34
|
+
- lib/chem_spider/services/mass_spec_a_p_i.rb
|
35
|
+
- lib/chem_spider/services/open_babel.rb
|
36
|
+
- lib/chem_spider/services/search.rb
|
37
|
+
- lib/chem_spider/services/spectra.rb
|
38
|
+
homepage: https://github.com/markborkum/chemspider
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
hash: 3
|
52
|
+
segments:
|
53
|
+
- 0
|
54
|
+
version: "0"
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
requirements:
|
65
|
+
- nokogiri
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.8.4
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: ChemSpider API
|
71
|
+
test_files: []
|
72
|
+
|
73
|
+
has_rdoc:
|