summaryrefslogtreecommitdiff
path: root/lazar.rb
blob: 5275602d4d7c530682acc0194c22807b5af16b0a (plain)
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
get '/?' do # get index of models
	Dir["models/*"].collect{|model|  url_for("/", :full) + File.basename(model,".yaml")}.sort.join("\n")
end

get '/:id/?' do

	path = File.join("models",params[:id] + ".yaml")
	halt 404, "Model #{params[:id]} does not exist." unless File.exists? path
	uri = url_for("/lazar/#{params[:id]}", :full)

	accept = request.env['HTTP_ACCEPT']
	accept = "application/rdf+xml" if accept == '*/*' or accept == '' or accept.nil?
	case accept
	when "application/rdf+xml"
		lazar = OpenTox::Model::Lazar.new
		lazar.read_yaml(params[:id],File.read(path))
		lazar.rdf
	when /yaml/
		send_file path
	else
		status 400
		"Unsupported MIME type '#{request.content_type}'"
	end
end

delete '/:id/?' do
	path = File.join("models",params[:id] + ".yaml")
	if File.exists? path
		File.delete path
		"Model #{params[:id]} deleted."
	else
		status 404
		"Model #{params[:id]} does not exist."
	end
end

post '/?' do # create model

	case request.content_type
	when /yaml/
		input =	request.env["rack.input"].read
		id = Dir["models/*"].collect{|model|  File.basename(model,".yaml").to_i}.sort.last
		if id.nil?
			id = 1
		else
			id += 1
		end
		File.open(File.join("models",id.to_s + ".yaml"),"w+") { |f| f.write input }
		url_for("/#{id}", :full)
	else
		halt 400, "MIME type \"#{request.content_type}\" not supported."
	end

	url_for("/#{id}", :full)

end

# PREDICTIONS
post '/:id/?' do # create prediction

	path = File.join("models",params[:id] + ".yaml")
	halt 404, "Model #{params[:id]} does not exist." unless File.exists? path
	halt 404, "No compound_uri." unless compound_uri = params[:compound_uri]
	lazar = YAML.load_file path
	dataset = OpenTox::Dataset.new

	# find database activities
	if lazar[:activities][compound_uri]
		c = dataset.find_or_create_compound(compound_uri)
		f = dataset.find_or_create_feature(lazar[:endpoint])
		v = dataset.find_or_create_value lazar[:activities][compound_uri].join(',')
		dataset.add_data_entry c,f,v
	else
		#puts compound_uri
		compound = OpenTox::Compound.new(:uri => compound_uri)
		#puts compound.smiles
		#puts compound.inchi
		compound_matches = compound.match lazar[:features]

		conf = 0.0
		neighbors = []
		classification = nil

		lazar[:fingerprints].each do |uri,matches|

			sim = weighted_tanimoto(compound_matches,matches,lazar[:p_values])
			if sim > 0.3
				neighbors << uri
				lazar[:activities][uri].each do |act|
					case act.to_s
					when 'true'
						conf += OpenTox::Utils.gauss(sim)
					when 'false'
						conf -= OpenTox::Utils.gauss(sim)
					end
				end
			end
		end

		conf = conf/neighbors.size
		if conf > 0.0
			classification = true
		elsif conf < 0.0
			classification = false
		end

		c = dataset.find_or_create_compound(compound_uri)
		f = dataset.find_or_create_feature(lazar[:endpoint] + " lazar prediction")
		v = dataset.find_or_create_value classification
		dataset.add_data_entry c,f,v
	
	end

	if /yaml/ =~ params[:type] 
		{ :classification => classification,
			:confidence => conf,
			:neighbors => neighbors,
			:features => compound_matches
		}.to_yaml
	else
		dataset.rdf
	end

end

def weighted_tanimoto(fp_a,fp_b,p)
	common_features = fp_a & fp_b
	all_features = fp_a + fp_b
	common_p_sum = 0.0
	if common_features.size > 0
		common_features.each{|f| common_p_sum += p[f]}
		all_p_sum = 0.0
		all_features.each{|f| all_p_sum += p[f]}
		common_p_sum/all_p_sum
	else
		0.0
	end
end