Commit 22fe453f authored by Anze Vavpetic's avatar Anze Vavpetic
Browse files

merged fixes for bogdans widgets

parent 778c5142
......@@ -21,8 +21,7 @@ def select_attrs(request, input_dict, output_dict, widget):
import orange, Orange
data = Orange.data.Table(input_dict['data'])
d = data.domain
classes = d.class_var.name
classes = d.class_var.name if d.class_var else None
metas = []
for m in d.getmetas().values():
......@@ -38,38 +37,30 @@ def select_attrs(request, input_dict, output_dict, widget):
return render(request, 'interactions/select_attrs.html',{'widget':widget, 'input_dict':input_dict})
def select_data(request, input_dict, output_dict, widget):
import Orange
data = Orange.data.Table(input_dict['data'])
attrs = {}
for att in data.domain.variables:
values = att.values if hasattr(att, 'values') else []
attrs[att.name] = {'feature' : 1, 'type' : str(att.var_type),
'values' : list(values)}
for a in data.domain.variables:
values = []
try:
for v in a.values:
values.append(v)
except:
pass
attrs[a.name] = {'feature':1, 'type':str(a.var_type), 'values':values}
for a in data.domain.get_metas():
meta = data.domain.get_meta(a)
values = []
try:
for v in meta.values:
values.append(v)
except:
pass
for att in data.domain.get_metas():
meta = data.domain.get_meta(att)
values = meta.values if hasattr(meta, 'values') else []
attrs[meta.name] = {'feature' : 0, 'type' : str(meta.var_type),
'values' : list(values)}
attrs[meta.name] = {'feature':0, 'type':str(meta.var_type), 'values':values}
cls = data.domain.class_var
if cls:
values = cls.values if hasattr(cls, 'values') else []
attrs[cls.name] = {'feature' : 1, 'type':str(cls.var_type),
'values': list(values)}
sorted_attrs = sorted(attrs.items())
input_dict = {'data': data, 'attrs':attrs, 'sorted_attrs':sorted_attrs}
return render(request, 'interactions/select_data.html',{'widget':widget, 'input_dict':input_dict})
return render(request, 'interactions/select_data_2.html',
{'widget' : widget, 'attrs' : sorted_attrs})
def alter_table(request, input_dict, output_dict, widget):
from visualization_views import orng_table_to_dict
......
......@@ -159,7 +159,6 @@ def build_filter(val, attr, data):
import Orange
pos = 0
try:
pos = data.domain.meta_id(attr)
except Exception, e:
......@@ -339,47 +338,27 @@ def select_data_post(postdata, input_dict, output_dict):
import Orange, json
data = input_dict['data']
try:
conditions = json.loads(str(postdata['conditions'][0]))
for c in conditions['conditions']:
if c['condition'][0]['operator'] in ["is defined", "sis defined"]:
# if the operator is "is defined"
fil = Orange.data.filter.IsDefined(domain = data.domain)
for v in range(len(data.domain.variables)):
fil.check[int(v)] = 0
if c['negate']:
fil.negate = True
fil.check[str(c['condition'][0]['attr'])] = 1
else:
fil = Orange.data.filter.Values()
fil.domain = data.domain
if c['negate']:
fil.negate = True
if len(c['condition']) > 1:
fil.conjunction = False
for val in c['condition']:
attr = data.domain[str(val['attr'])]
fil.conditions.append(build_filter(val, attr, data))
else:
for val in c['condition']:
attr = data.domain[str(val['attr'])]
fil.conditions.append(build_filter(val, attr, data))
data = fil(data)
except Exception, e:
pass
output_dict = {'data': data}
return output_dict
conditions = json.loads(str(postdata['conditions'][0]))
for cond in conditions['conditions']:
data_filter = None
if cond['condition'][0]['operator'] in ["is defined", "sis defined"]:
data_filter = Orange.data.filter.IsDefined(domain = data.domain)
data_filter.negate = cond['negate']
data_filter.check[str(cond['condition'][0]['attr'])] = 1
for v in range(len(data.domain.variables)):
data_filter.check[int(v)] = 0
else:
data_filter = Orange.data.filter.Values()
data_filter.domain = data.domain
data_filter.negate = cond['negate']
data_filter.conjunction = False
for or_cond in cond['condition']:
attr = data.domain[str(or_cond['attr'])]
data_filter.conditions.append(build_filter(or_cond, attr, data))
data = data_filter(data)
return {'data': data}
def build_classifier(input_dict):
learner = input_dict['learner']
......
......@@ -15,7 +15,7 @@
var count = 0;
for (var i = selObj.options.length - 1; i >= 0; i--) {
if (selObj.options[i].selected) {
if (dest == "ca_list" && (destObj.options.length != 0 || count >= 1) ) {
if (dest == "ca_list{{widget.pk}}" && (destObj.options.length != 0 || count >= 1) ) {
msgDisplay("Class Attribute already assigned!")
break;
};
......@@ -31,14 +31,14 @@
}
function msgDisplay (msg) {
document.getElementById("msg").innerHTML = msg;
document.getElementById("msg{{widget.pk}}").innerHTML = msg;
}
function prepareForm () {
var selObj_ma = document.getElementById('ma_list');
var hideObj_ma = document.getElementById('ma_values');
var selObj_attrs = document.getElementById('attrs_list');
var hideObj_attrs = document.getElementById('attrs_values');
var selObj_ma = document.getElementById('ma_list{{widget.pk}}');
var hideObj_ma = document.getElementById('ma_values{{widget.pk}}');
var selObj_attrs = document.getElementById('attrs_list{{widget.pk}}');
var hideObj_attrs = document.getElementById('attrs_values{{widget.pk}}');
hideObj_ma.value = '';
hideObj_attrs.value = '';
for (var i = selObj_ma.options.length - 1; i >= 0; i--) {
......@@ -58,9 +58,9 @@
};
}
function prepareForm2{{widget.id}} () {
var selObj_ma = document.getElementById('ma_list');
var selObj_attrs = document.getElementById('attrs_list');
function prepareForm2{{widget.pk}} () {
var selObj_ma = document.getElementById('ma_list{{widget.pk}}');
var selObj_attrs = document.getElementById('attrs_list{{widget.pk}}');
for (var i = selObj_ma.options.length - 1; i >= 0; i--) {
selObj_ma.options[i].selected = true;
};
......@@ -71,8 +71,8 @@
</script>
<p>Arrange the attributes. The attributes on the right side are the ones that are included in the dataset.<br><br></p>
<p id="msg" style="color:red;font-weight:bold" ></p>
<form id="interactionform-{{widget.pk}}" name="interactionform-{{widget.pk}}" onsubmit="prepareForm2{{widget.id}}();" >
<p id="msg{{widget.pk}}" style="color:red;font-weight:bold" ></p>
<form id="interactionform-{{widget.pk}}" name="interactionform-{{widget.pk}}" onsubmit="prepareForm2{{widget.pk}}();" >
<table>
<tr>
......@@ -84,30 +84,32 @@
<tr>
<td rowspan="3" >
<h2>Attributes (not in the dataset)</h2>
<select name="att" id="attr_list" style="width: 250px" size="29" multiple="multiple" >
<select name="att" id="attr_list{{widget.pk}}" style="width: 250px" size="29" multiple="multiple" >
</select>
</td>
<td style = "vertical-align:middle; text-align:center" >
<button type="button" onclick="movAttr('ca_list', 'attr_list', 'No Class Attributes available!');" > <-- </button>
<button type="button" onclick="movAttr('ca_list{{widget.pk}}', 'attr_list{{widget.pk}}', 'No Class Attributes available!');" > <-- </button>
</br>
<button type="button" onclick="movAttr('attr_list', 'ca_list', 'No more unsorted Attributes available!');" > --> </button>
<button type="button" onclick="movAttr('attr_list{{widget.pk}}', 'ca_list{{widget.pk}}', 'No more unsorted Attributes available!');" > --> </button>
</td>
<td>
<h2>Class Attribute</h2>
<SELECT name="ca" id="ca_list" style="width: 250px" SIZE="1" >
<SELECT name="ca" id="ca_list{{widget.pk}}" style="width: 250px" SIZE="1" >
{% if input_dict.ca %}
<OPTION value="{{input_dict.ca}}" SELECTED> {{input_dict.ca}}
{% endif %}
</SELECT>
</td>
</tr>
<tr>
<td style = "vertical-align:middle; text-align:center">
<button type="button" onclick="movAttr('ma_list', 'attr_list', 'No more Meta Attributes available!');" > <-- </button>
<button type="button" onclick="movAttr('ma_list{{widget.pk}}', 'attr_list{{widget.pk}}', 'No more Meta Attributes available!');" > <-- </button>
</br>
<button type="button" onclick="movAttr('attr_list', 'ma_list', 'No more unsorted Attributes available!');" > --> </button>
<button type="button" onclick="movAttr('attr_list{{widget.pk}}', 'ma_list{{widget.pk}}', 'No more unsorted Attributes available!');" > --> </button>
</td>
<td>
<h2>Meta Attributes</h2>
<select name="ma" id="ma_list" style="width: 250px" size="10" multiple="multiple" >
<select name="ma" id="ma_list{{widget.pk}}" style="width: 250px" size="10" multiple="multiple" >
{% for attr in input_dict.ma %}
<option value="{{attr}}">
{{attr}}
......@@ -118,13 +120,13 @@
</tr>
<tr>
<td style = "vertical-align:middle; text-align:center" >
<button type="button" onclick="movAttr('attrs_list', 'attr_list', 'No more Attributes available!');" > <-- </button>
<button type="button" onclick="movAttr('attrs_list{{widget.pk}}', 'attr_list{{widget.pk}}', 'No more Attributes available!');" > <-- </button>
</br>
<button type="button" onclick="movAttr('attr_list', 'attrs_list', 'No more unsorted Attributes available!');" > --> </button>
<button type="button" onclick="movAttr('attr_list{{widget.pk}}', 'attrs_list{{widget.pk}}', 'No more unsorted Attributes available!');" > --> </button>
</td>
<td>
<h2>Attributes (in the dataset)</h2>
<select name="attrs" id="attrs_list" style="width: 250px" size="15" multiple="multiple" >
<select name="attrs" id="attrs_list{{widget.pk}}" style="width: 250px" size="15" multiple="multiple" >
{% for k, v in input_dict.sorted_attrs %}
<option value="{{k}}">
{{k}}
......@@ -135,7 +137,7 @@
</tr>
</table>
<input class="runfunction" type="hidden" name="runfunction" value="prepareForm2{{widget.id}}();">
<input class="runfunction" type="hidden" name="runfunction" value="prepareForm2{{widget.pk}}();">
<input type="hidden" name="widget_id" value="{{widget.pk}}">
</center>
......
......@@ -10,309 +10,287 @@ select {width: 250px;}
</style>
<script type="text/javascript">
var SelectData = function()
{
var that = {}
that.init = function(pk)
{
that.pk = pk;
that.add_clicked = false;
that.attr_select = $('#attr_list' + that.pk);
that.operators_select = $('#operator' + that.pk);
that.values_select = $('#values' + that.pk);
that.val1_input = $('#val1' + that.pk);
that.val2_input = $('#val2' + that.pk);
that.values = $('#values' + that.pk);
that.case_sensitive = $('#case' + that.pk);
that.filters = $('#filters' + that.pk);
that.json_conditions = $('#conditions' + that.pk);
// Object containing the filtering rules
that.rules = [];
// Next position to add rule
that.index = 0;
$('#btn_add' + that.pk).click(function() {
that.add_cond('and');
});
$('#btn_or' + that.pk).click(function() {
if (that.add_clicked) {
that.add_cond('or');
} else {
that.add_cond('and');
}
});
$('#btn_del' + that.pk).click(that.del_last);
$('#btn_neg' + that.pk).click(that.neg_last);
};
that.attr_change = function(attr)
{
// Clear the select lists
that.operators_select.empty();
that.values_select.empty();
var is_string = false;
var operators = [];
if (attr['type'] == 'Discrete') {
operators = ['in', 'equals'];
that.val1_input.hide();
that.val2_input.hide();
that.values.show();
that.case_sensitive.show();
$.each(attr['values'], function(idx, value) {
var opt = $('<option></option>')
.text(value)
.val(value);
that.values_select.append(opt);
});
} else if(attr['type'] == 'Continuous') {
operators = ['outside', 'between', '<=', '<', '>=', '>', '='];
that.val1_input.show();
that.values.hide();
that.case_sensitive.hide();
} else {
is_string = true;
operators = ['ends with', 'begins with', 'not contains', 'contains',
'outside', 'between', '<=', '<', '>=', '>', '='];
that.val1_input.show();
that.values.hide();
that.case_sensitive.show();
}
function attrChange (attr) {
//clear operators list
var op_list = document.getElementById('operator');
for (var i = op_list.options.length - 1; i >= 0; i--) {
op_list.remove(i);
};
//clear values list
var vl_list = document.getElementById('values');
for (var i = vl_list.length - 1; i >= 0; i--) {
vl_list.remove(i);
};
var operators = [];
if (attr['type'] == 'Discrete') {
//for discrete attributes
operators = ['in', 'equals'];
//if the attribute is a feature
if (attr['feature']) {
operators.unshift('is defined');
};
//prepare form elements
document.getElementById('val1').className="hidden";
document.getElementById('val2').className="hidden";
document.getElementById('values').className="shown";
document.getElementById('case').className="hidden";
//fill in operators
for (var i = operators.length - 1; i >= 0; i--) {
var opt = document.createElement('option');
opt.text = operators[i];
opt.value = operators[i];
if (operators[i] == 'equals') {
opt.onclick = "document.getElementById('values').multiple = false;";
} else {
opt.onclick = "document.getElementById('values').multiple = true;";
};
op_list.options[op_list.options.length] = opt;
};
//fill in values
for (var i = attr['values'].length - 1; i >= 0; i--) {
var opt = document.createElement('option');
opt.value = attr['values'][i];
opt.text = attr['values'][i];
vl_list.options[vl_list.options.length] = opt;
};
} else if(attr['type'] == 'Continuous') {
// for continuous attributes
operators = ['outside', 'between', '<=', '<', '>=', '>', '='];
//if the attribute is a feature
if (attr['feature']) {
operators.unshift('is defined');
};
//prepare form elements
document.getElementById('val1').className="shown";
document.getElementById('values').className="hidden";
document.getElementById('case').className="hidden";
//fill in operators
for (var i = operators.length - 1; i >= 0; i--) {
var opt = document.createElement('option');
opt.text = operators[i];
opt.value = operators[i];
if (operators[i] == 'outside' || operators[i] == 'between') {
opt.onclick = "document.getElementById('val2').className='shown';";
} else {
opt.onclick = "document.getElementById('val2').className='hidden';";
};
op_list.options[op_list.options.length] = opt;
};
} else {
// for string attributes
operators = ['ends with', 'begins with', 'not contains', 'contains', 'outside', 'between', '<=', '<', '>=', '>', '='];
//if the attribute is a feature
if (attr['feature']) {
operators.unshift('is defined');
};
//prepare form elements
document.getElementById('val1').className="shown";
document.getElementById('values').className="hidden";
document.getElementById('case').className="shown";
//fill in operators
for (var i = operators.length - 1; i >= 0; i--) {
var opt = document.createElement('option');
opt.text = operators[i];
opt.value = 's' + operators[i];
if (operators[i] == 'outside' || operators[i] == 'between') {
opt.onclick = "document.getElementById('val2').className='shown';";
} else {
opt.onclick = "document.getElementById('val2').className='hidden';";
};
op_list.options[op_list.options.length] = opt;
};
};
}
var JSON_txt = '{"conditions":[]}';
var obj = JSON.parse(JSON_txt);
var index = 0;
addclicked{{widget.id}} = false;
function addCond (op) {
if (op=='and') {
addclicked{{widget.id}}=true;
if (attr['feature']) {
operators.push('is defined');
}
var attr_list = document.getElementById('attr_list');
var att_name = attr_list.value;
var op_name = document.getElementById('operator').value;
if (obj['conditions'].length > 0) {
//'is defined' is not supposed to be used in disjunction here
var last_conds = obj['conditions'][obj['conditions'].length-1];
var last_cond = last_conds['condition'][last_conds['condition'].length-1];
if (op=="or" &&
(last_cond['operator'].indexOf('defined') != -1 ||
op_name.indexOf('defined') != -1)
){
alert("Invalid action: operator 'is defined' is not allowed in a disjunction statement!");
return true;
};
};
var vl_list = document.getElementById('values');
var values = new Array ();
//add AND or OR if 'filters' is not empty
if (op != 'or') {
obj.conditions.push({"no":index, "condition":[], 'negate':0})
} else{
index--;
};
//copy values in values array
for (var i = vl_list.options.length - 1; i >= 0; i--) {
if (vl_list.options[i].selected) {
values[values.length] = vl_list.options[i].value;
};
};
var caseSens = document.getElementById('caseSens').checked;
var negate = document.getElementById('neg').checked;
//save selected condition
if (op_name == 'in' || op_name == 'equals')
{
//if attribute is discrete
obj['conditions'][index].condition.push({
'attr':att_name,
'operator':op_name,
'values':values,
'negate':negate
});
} else if (op_name == 'between' || op_name == 'outside' || op_name == 'sbetween' || op_name == 'soutside')
{
//if attribute is non-discrete and selected operator == between or outside
obj['conditions'][index].condition.push({
'attr':att_name,
'operator':op_name,
'values':[document.getElementById('val1').value, document.getElementById('val2').value],
'case':caseSens,
'negate':negate
});
} else {
//if attribute is non-discrete and selected operator is NOT between or outside
obj['conditions'][index].condition.push({
'attr':att_name,
'operator':op_name,
'values':[document.getElementById('val1').value],
'case':caseSens,
'negate':negate
});
};
index ++;
write_conds();
}
function undo () {
if (obj['conditions'].length>0) {
//delete the last statement
obj['conditions'].splice(--index ,1);
write_conds();
if ((obj['conditions'].length==0)) {
addclicked{{widget.id}}=false;
// Fill operators
$.each(operators, function(idx, op) {
var opt = $('<option></option>').text(op);
if (is_string) {
opt.val('s' + op);
} else {
opt.val(op);
}
var multipleSelect = (op != 'equals');
var showVal2 = (op == 'outside' || op == 'between');
opt.click(function() {
that.values.attr('multiple', op != 'equals');
if (op == 'outside' || op == 'between') {
that.val2_input.show();
} else {
that.val2_input.hide();
}
});
that.operators_select.append(opt);
});
};
that.add_cond = function(op)
{
if (op == 'and') {
that.add_clicked = true;
}
}
function negate () {
if (obj['conditions'].length>0) {
//negate the last statement
obj['conditions'][index-1]['negate'] = 1;
write_conds();
var att_name = that.attr_select
.find('option:selected')
.val();
var op_name = that