Commit a04264b1 authored by Anze Vavpetic's avatar Anze Vavpetic

Added kepner-tregoe sensitivity analysis.

parent 0e25bb73
......@@ -81,4 +81,4 @@ def build_subgroups(request, input_dict, output_dict, widget):
def kepner_tregoe(request, input_dict, output_dict, widget):
attributes = [att.name for att in input_dict['data'].domain.features]
return render(request, 'interactions/kepner_tregoe.html', {'widget':widget, 'attributes':attributes})
\ No newline at end of file
return render(request, 'interactions/kepner_tregoe.html', {'widget':widget, 'attributes':attributes})
......@@ -839,30 +839,71 @@ def load_corpus(input_dict):
return {'corpus' : response['parsedFile']}
def kepner_tregoe(input_dict):
return input_dict
def kepner_tregoe_finished(postdata,input_dict,output_dict):
attributes = [att.name for att in input_dict['data'].domain.features]
output_dict = input_dict
output_dict['model'] = None
return output_dict
class KepnerTregoe:
'''
Kepner Tregoe model.
'''
def __init__(self, data, weights, smaller_is_better=None):
self.data = data
self.weights = weights
self.smaller_is_better = smaller_is_better if smaller_is_better else set()
def __call__(self, weights=None):
import Orange
from Orange.feature import Type
if weights == None:
weights = self.weights
# Normalize the weights.
s = sum([weights[att] for att in weights.keys()])
# Normalize.
norm_weights = {}
if s > 0:
for att in weights.keys():
norm_weights[att] = float(weights[att])/s
# New normalized table
norm_data = Orange.data.Table(self.data)
newid = min(norm_data.domain.get_metas().keys()) - 1
score_attr = Orange.feature.Continuous('score')
norm_data.domain.add_meta(newid, score_attr)
norm_data.add_meta_attribute(score_attr)
# Normalize the attributes column-wise
for att in norm_data.domain:
if att.var_type == Type.Continuous:
col = [ex[att] for ex in norm_data]
col_norm = float(sum(col))
for ex in norm_data:
if att.var_type == Type.Continuous:
ex[att] = ex[att] / col_norm
# Use the inverse of an attr. value if smaller values should be treated as 'better'.
inverse = lambda x, att: 1-x if att in self.smaller_is_better else x
for ex in norm_data:
score = sum([inverse(ex[att], att.name) * norm_weights.get(att.name, 1) for att in norm_data.domain.features if att.var_type == Type.Continuous])
ex['score'] = score
return norm_data
def kepner_tregoe_finished(postdata, input_dict, output_dict):
# Fetch the data and the weights from the form.
data = input_dict['data']
attributes = [att.name for att in data.domain.features]
weights = {}
s = 0
widget_id = postdata['widget_id'][0]
smaller_is_better = set()
for att in attributes:
weights[att]=int(postdata['weight'+str(widget_id)+str(att)][0])
s = s + weights[att]
if s>0:
for att in attributes:
weights[att]=float(weights[att])/s
import Orange
new_alts = Orange.data.Table(input_dict['data'])
newid = Orange.feature.Descriptor.new_meta_id()
new_alts.domain.add_meta(newid, Orange.feature.Continuous('score'))
new_alts.add_meta_attribute('score')
for ex in new_alts:
score = sum([ex[att] * weights.get(att, 1) for att in attributes])
ex['score'] = score
if postdata.has_key('smallerIsBetter'+str(widget_id)+str(att)):
smaller_is_better.add(att)
# Instantiate a KepnerTregoe model.
kt = KepnerTregoe(data, weights, smaller_is_better=smaller_is_better)
output_dict = {}
output_dict['data'] = new_alts
output_dict['data'] = kt()
output_dict['model'] = kt
return output_dict
def sensitivity_analysis(input_dict):
return input_dict
def string_to_file(input_dict):
return {}
......@@ -439,7 +439,9 @@ class Widget(models.Model):
self.finished=False
self.save()
raise
print outputs
for o in self.outputs.all():
print o
if not self.abstract_widget is None:
o.value = outputs[o.variable]
o.save()
......
......@@ -3,10 +3,10 @@
Use the sliders to adjust the weights.<br><br>
<form>
{% for att in attributes %}
{{att}}
<br>
<br>
<input type="text" style="width:30px; margin-left:20px; float:right;" name="weight{{widget.pk}}{{att}}" id="weight{{widget.pk}}{{att}}" value="0">
<label style="font-weight:bold;">{{att}}</label>
<div style="padding-left:20px;">
<input id="smallerIsBetter{{widget.pk}}{{att}}" name="smallerIsBetter{{widget.pk}}{{att}}" type="checkbox" value="true" style="width:15px;display:inline;" /> <label for="largerIsBetter{{widget.pk}}{{att}}" style="display:inline;">smaller attr. values are better</label>
<input type="text" style="width:30px; margin-left:20px; float:right;" name="weight{{widget.pk}}{{att}}" id="weight{{widget.pk}}{{att}}" value="0"/>
<div style="width:300px;" id="slider{{widget.pk}}{{att}}"></div>
<script>
$("#slider{{widget.pk}}{{att}}").slider({
......@@ -23,12 +23,12 @@ Use the sliders to adjust the weights.<br><br>
});
</script>
</div>
<br>
<br>
{% endfor %}
<input type="hidden" name="widget_id" value="{{widget.pk}}">
<input type="hidden" name="widget_id" value="{{widget.pk}}"/>
</form>
</div>
</div>
\ No newline at end of file
<div id="widgetvisualization-{{widget.pk}}" rel="{{widget.pk}}" class="widgetvisualizationdialog" title="{{widget.name}} visualization" width="600px" height="700px">
<div style="width:580px;">
Select the attribute to perform sensitivity analysis on.<br><br>
<form>
<fieldset>
{% for att in attributes %}
<input type="radio" class="target_att" name="target{{widget.pk}}" id="target{{widget.pk}}{{att}}" value="{{att}}" {% if forloop.first %}checked="checked"{% endif %} style="display:inline;"> <label for="target{{widget.pk}}{{att}}" style="font-weight:bold; display:inline;">{{att}}</label>
<br>
<br>
{% endfor %}
</fieldset>
<input type="hidden" name="widget_id" value="{{widget.pk}}"/>
</form>
<script type="text/javascript">
$(function () {
// Load data points.
var data_points = {{ data_points|safe }};
var chart;
$(document).ready(function(){
plot("{{attributes.0}}");
});
// Handles radio button selection events.
$("form input[class=target_att]").change(function () {
var target_att = $("form input[class=target_att]:checked").val();
plot(target_att);
});
// Plots for the selected attribute.
function plot(target_att) {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'line',
marginRight: 130,
marginBottom: 25
},
title: {
text: 'Sensitivity analysis',
x: -20 //center
},
subtitle: {
text: 'Changing weight for attribute: ' + target_att,
x: -20
},
yAxis: {
title: {
text: 'score'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
this.x +': '+ this.y +'°C';
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 100,
borderWidth: 0
},
series: data_points[target_att]
});
}
});
</script>
<div id="container" style="min-width: 580px; height: 450px; margin: 0 auto"></div>
</div>
</div>
\ No newline at end of file
......@@ -51,4 +51,5 @@ urlpatterns = patterns('',
url(r'^(?P<workflow_id>[0-9]+)/$', 'workflows.views.open_workflow', name='open workflow'),
url(r'^sensitivity_analysis/', 'workflows.visualization_views.sensitivity_analysis_viewer', name='sensitivity analysis'),
)
\ No newline at end of file
from django.shortcuts import render
from django.http import Http404, HttpResponse
import nlp
import json
def odt_to_tab(request,input_dict,output_dict,widget):
import Orange
......@@ -73,13 +75,17 @@ def table_viewer(request,input_dict,output_dict,widget):
for a in data.domain.attributes:
attrs.append(a.name)
pretty_float = lambda x, a: '%.3f' % x if a.var_type == Orange.feature.Type.Continuous else x
for inst in xrange(len(data)):
inst_new = []
for a in data.domain.variables:
inst_new.append(data[inst][a.name].value)
value = data[inst][a.name].value
inst_new.append(pretty_float(value, a))
for m in data.domain.get_metas():
inst_new.append(data[inst][m].value)
value = data[inst][m].value
a = data.domain.get_meta(m)
inst_new.append(pretty_float(value, a))
data_new.append(inst_new)
output_dict = {'attrs':attrs, 'metas':metas, 'data':data_new, 'class_var':class_var}
......@@ -205,7 +211,7 @@ def term_candidate_viewer(request, input_dict, output_dict, widget):
"""
Parses the input and displays the term candidates.
@author: Anze Vavpetic, 2012
@author: Anze Vavpeltic, 2012
"""
terms = []
for line in input_dict['candidates'].split('\n'):
......@@ -219,3 +225,36 @@ def term_candidate_viewer(request, input_dict, output_dict, widget):
})
terms = sorted(terms, key = lambda x: x['score'], reverse=True)
return render(request, 'visualizations/terms.html', {'widget' : widget, 'terms' : terms})
def sensitivity_analysis_viewer(request, input_dict, output_dict, widget):
'''
Computes the sensitivity analysis graph.
@author: Anze Vavpeltic, 2012
'''
model = input_dict['model']
attributes = [att.name for att in input_dict['model'].data.domain.features]
data_points = {}
domain = range(0, 101, 10)
# Compute for each attribute
for target_att in attributes:
y, ex_data = [], {}
# For collecting scores for each example across different weights
for ex in model.data:
ex_data[ex['label'].value] = []
# Compute the scores for each weight
for w in domain:
model.weights[target_att] = w
ds = model()
for ex in ds:
ex_data[ex['label'].value].append([w, ex['score'].value])
for ex in model.data:
y.append({'name' : ex['label'].value, 'data' : ex_data[ex['label'].value]})
data_points[target_att] = y
return render(request, 'visualizations/sensitivity_analysis.html',
{'widget' : widget,
'attributes': attributes,
'data_points' : json.dumps(data_points),
'output_dict': {}
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment