Commit 951b39f3 authored by Ossi Laine's avatar Ossi Laine
Browse files

Reordered statistics -page and shows now only values from done experiments

parent 59d2b64f
......@@ -35,18 +35,16 @@
</tr>
<tr>
<td>Number of finished ratings:</td>
<td>{{ finished_ratings }}</td>
</tr>
<tr>
<td><a class="btn btn-primary btn-info" href="{{ url_for('download_csv', exp_id=exp.idexperiment) }}" role="button">Export results (csv)</a></td>
<td></td>
<td>{{ finished_ratings }}
<a class="btn btn-primary btn-info float-right" href="{{ url_for('download_csv', exp_id=exp.idexperiment) }}" role="button">Export results (csv)</a>
</td>
</tr>
</tbody>
</table>
{% endfor %}
<h1 class="container mt-5 display-4 text-left"><br>Rating task question headers:</h1>
<h1 class="container mt-5 display-6 text-left"><br>Slider question headers:</h1>
<br>
<table class="table">
<thead>
......@@ -69,7 +67,40 @@
</tbody>
</table>
<h1 class="container mt-5 display-4 text-left"><br>Rating task stimulus headers:</h1>
<h1 class="container mt-5 display-6 text-left"><br>Slider question answers: (Page ID/Question ID)</h1>
<br>
<table class="table">
<thead>
<tr>
<th scope="col" nowrap>Participant ID:</th>
{% for page in pages_and_questions %}
{% for p in pages_and_questions[page] %}
<th scope="col" nowrap>{{ p[0]}}/{{ p[1]}}</th>
{% endfor %}
{% endfor %}
</tr>
</thead>
<tbody>
{% for participant in participants_and_answers %}
<tr>
<td>{{ participant }}</td>
{% for answer in participants_and_answers[participant] %}
<td>{{ answer }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<h1 class="container mt-5 display-6 text-left"><br>Embody pictures and answers:</h1>
<br>
<table class="table">
<thead>
......@@ -87,8 +118,16 @@
{% if s.type == 'text' %}
<td>{{ s.text }}</td>
{% elif s.type == 'picture' %}
<td><img src="/{{ s.media }}" class="thumbnail" /></td>
{% elif s.type == 'video' %}
<td>
<div class="embed-responsive embed-responsive-16by9 ">
<iframe class="embed-responsive-item thumbnail" src="/{{ s.media }}" allowFullScreen></iframe>
</div>
</td>
{% else %}
<td>{{ s.media }}</td>
<td>{{ s.text }}</td>
{% endif %}
<td><img src="{{ embody_picture.picture }}" class="thumbnail" /></td>
......@@ -116,43 +155,14 @@
<img class="embody-image-container">
<h1 class="container mt-5 display-4 text-left"><br>Rating task values: (Stimulus ID/Question ID)</h1>
<br>
<table class="table">
<thead>
<tr>
<th scope="col" nowrap>Participant ID:</th>
{% for page in pages_and_questions %}
{% for p in pages_and_questions[page] %}
<th scope="col" nowrap>{{ p[0]}}/{{ p[1]}}</th>
{% endfor %}
{% endfor %}
</tr>
</thead>
<tbody>
{% for participant in participants_and_answers %}
<tr>
<td>{{ participant }}</td>
{% for answer in participants_and_answers[participant] %}
<td>{{ answer[3] }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<h1 class="container mt-5 display-4 text-left"><br>Background question answers:</h1>
<h1 class="container mt-5 display-6 text-left"><br>Background question answers:</h1>
<br>
<table class="table">
<thead>
<tr>
<th scope="col" nowrap>Question:</th>
<th scope="col" nowrap>Participant</th>
{% for bg in bg_questions %}
<th scope="col" nowrap>{{ bg.background_question }}</th>
......@@ -168,6 +178,8 @@
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
......
......@@ -893,6 +893,14 @@ def statistics():
experiment_info = experiment.query.filter_by(idexperiment = exp_id).all()
participants = answer_set.query.filter_by(experiment_idexperiment= exp_id).all()
#started and finished ratings counters
started_ratings = answer_set.query.filter_by(
experiment_idexperiment=exp_id).count()
experiment_page_count = page.query.filter_by(
experiment_idexperiment=exp_id).count()
finished_ratings = answer_set.query.filter(and_(
answer_set.answer_counter == experiment_page_count, answer_set.experiment_idexperiment == exp_id)).count()
#Rating task headers
question_headers = question.query.filter_by(experiment_idexperiment=exp_id).all()
......@@ -903,47 +911,56 @@ def statistics():
pages_and_questions = {}
for p in pages:
questions_list = [(p.idpage, a.idquestion) for a in questions]
pages_and_questions[p.idpage] = questions_list
#List of answers per participant in format question Stimulus ID/Question ID
#those are in answer table as page_idpage and question_idquestion respectively
participants_and_answers = {}
slider_answers = {}
for participant in participants:
answers = answer.query.filter_by(answer_set_idanswer_set=participant.idanswer_set).all()
answers_list = [(a.idanswer, a.question_idquestion, a.answer_set_idanswer_set, a.answer, a.page_idpage) for a in answers]
participants_and_answers[participant.session] = answers_list
# list only finished answer sets
if experiment_page_count == participant.answer_counter:
answers = answer.query.filter_by(answer_set_idanswer_set=participant.idanswer_set).all()
slider_answers[participant.session] = [ a.answer for a in answers]
# map slider_answers from str to int and calculate mean
a = [map(int,i) for i in list(slider_answers.values())]
slider_answers['mean'] = [float(sum(l))/len(l) for l in zip(*a)]
#Background question answers
bg_questions = background_question.query.filter_by(
experiment_idexperiment=exp_id).all()
bg_answers_for_participants = {}
for participant in participants:
bg_answers = background_question_answer.query.filter_by(
answer_set_idanswer_set=participant.idanswer_set).all()
bg_answers_list = [(a.answer) for a in bg_answers]
bg_answers_for_participants[participant.session] = bg_answers_list
# list only finished answer sets
if experiment_page_count == participant.answer_counter:
bg_answers = background_question_answer.query.filter_by(
answer_set_idanswer_set=participant.idanswer_set).all()
bg_answers_list = [(a.answer) for a in bg_answers]
bg_answers_for_participants[participant.session] = bg_answers_list
#started and finished ratings counters
started_ratings = answer_set.query.filter_by(
experiment_idexperiment=exp_id).count()
experiment_page_count = page.query.filter_by(
experiment_idexperiment=exp_id).count()
finished_ratings = answer_set.query.filter(and_(
answer_set.answer_counter == experiment_page_count, answer_set.experiment_idexperiment == exp_id)).count()
# embody questions
embody_questions = embody_question.query.filter_by(
experiment_idexperiment=exp_id).all()
return render_template('experiment_statistics.html', experiment_info=experiment_info, participants_and_answers=participants_and_answers, pages_and_questions=pages_and_questions, bg_questions=bg_questions, bg_answers_for_participants=bg_answers_for_participants, started_ratings=started_ratings, finished_ratings=finished_ratings, question_headers=question_headers, stimulus_headers=stimulus_headers, embody_questions=embody_questions)
return render_template('experiment_statistics.html',
experiment_info=experiment_info,
participants_and_answers=slider_answers,
pages_and_questions=pages_and_questions,
bg_questions=bg_questions,
bg_answers_for_participants=bg_answers_for_participants,
started_ratings=started_ratings,
finished_ratings=finished_ratings,
question_headers=question_headers,
stimulus_headers=stimulus_headers,
embody_questions=embody_questions
)
import embody_plot
......
......@@ -81,9 +81,9 @@ class TestForm2(Form):
questions1 = SelectField()
#Forms for editing functions
class CreateExperimentForm(Form):
name = StringField('Name', [validators.DataRequired()])
......@@ -147,6 +147,7 @@ class CreateEmbodyForm(Form):
picture = FileField('Upload picture')
submit = SubmitField('Send')
class EditQuestionForm(Form):
left = StringField('left_scale', [validators.DataRequired()])
......@@ -168,7 +169,6 @@ class UploadResearchBulletinForm(Form):
file = FileField('Upload file')
submit = SubmitField('Send')
class EditPageForm(Form):
......@@ -183,6 +183,7 @@ class RemoveExperimentForm(Form):
remove = TextAreaField('Remove')
submit = SubmitField('Send')
class GenerateIdForm(Form):
number = IntegerField('number', [validators.DataRequired()])
......
......@@ -382,47 +382,50 @@ def download_csv():
header += ';' + ';'.join(['page' + str(idx) + '_' + str(count) +'. embody_question: '+ question.picture for count,question in enumerate(embody_questions, 1)])
csv += header + '\r\n'
answer_row = ''
for participant in participants:
try:
# list only finished answer sets
if experiment_page_count == participant.answer_counter:
# append user session id
answer_row += participant.session + ';'
try:
# append background question answers
bg_answers = background_question_answer.query.filter_by(answer_set_idanswer_set=participant.idanswer_set).all()
bg_answers_list = [(a.answer) for a in bg_answers]
answer_row += ';'.join(bg_answers_list) + ';'
# append slider answers
slider_answers = answer.query.filter_by(answer_set_idanswer_set=participant.idanswer_set).all()
answers_list = [ a.answer for a in slider_answers]
answer_row += ';'.join(answers_list) + ';' if slider_answers else ''
# append embody answers (coordinates)
# save embody answers as bitmap images
embody_answers = embody_answer.query.filter_by(answer_set_idanswer_set=participant.idanswer_set).all()
answers_list = []
for embody_answer_data in embody_answers:
embody_answer_data = json.loads(embody_answer_data.coordinates)
coordinates_to_bitmap = [[0 for x in range(embody_answer_data['height'] + 2)] for y in range(embody_answer_data['width'] + 2)]
for point in list(zip( embody_answer_data['x'], embody_answer_data['y'])):
coordinates_to_bitmap[point[0]][point[1]] += 0.1
answers_list.append(json.dumps(coordinates_to_bitmap))
# old way to save only visited points:
# answers_list = [ json.dumps(list(zip( json.loads(a.coordinates)['x'], json.loads(a.coordinates)['y']))) for a in embody_answers]
answer_row += ';'.join(answers_list) if embody_answers else ''
except TypeError as err:
print(err)
csv += answer_row + '\r\n'
answer_row = ''
# append user session id
answer_row += participant.session + ';'
# append background question answers
bg_answers = background_question_answer.query.filter_by(answer_set_idanswer_set=participant.idanswer_set).all()
bg_answers_list = [ str(a.answer).strip() for a in bg_answers]
answer_row += ';'.join(bg_answers_list) + ';'
# append slider answers
slider_answers = answer.query.filter_by(answer_set_idanswer_set=participant.idanswer_set).all()
answers_list = [ str(a.answer).strip() for a in slider_answers]
answer_row += ';'.join(answers_list) + ';' if slider_answers else len(questions) * len(pages) * ';'
# append embody answers (coordinates)
# save embody answers as bitmap images
embody_answers = embody_answer.query.filter_by(answer_set_idanswer_set=participant.idanswer_set).all()
answers_list = []
for embody_answer_data in embody_answers:
embody_answer_data = json.loads(embody_answer_data.coordinates)
coordinates_to_bitmap = [[0 for x in range(embody_answer_data['height'] + 2)] for y in range(embody_answer_data['width'] + 2)]
for point in list(zip( embody_answer_data['x'], embody_answer_data['y'])):
coordinates_to_bitmap[point[0]][point[1]] += 0.1
answers_list.append('hello')
#answers_list.append(json.dumps(coordinates_to_bitmap))
# old way to save only visited points:
# answers_list = [ json.dumps(list(zip( json.loads(a.coordinates)['x'], json.loads(a.coordinates)['y']))) for a in embody_answers]
answer_row += ';'.join(answers_list) if embody_answers else len(embody_questions) * len(pages) * ';'
except TypeError as err:
print(err)
csv += answer_row + '\r\n'
answer_row = ''
try:
fd, path = tempfile.mkstemp()
......
......@@ -6,16 +6,7 @@ const defaultEmbodySource = '/static/img/dummy_600.png';
$(document).ready(function() {
// Init draw variables
/*
OO-style coordinates:
var paint;
var point = {
x: null,
y: null,
r: 13
}
var points = new Array()
*/
var clickX = new Array();
var clickY = new Array();
var clickRadius = new Array();
......@@ -36,9 +27,9 @@ $(document).ready(function() {
//var oldimg = document.getElementById("baseImage");
var img = $('.embody-image.selected-embody')[0]
$(img).on('load', function() {
img.onload = function() {
drawImage()
})
}
} catch (e) {
console.log(e)
......@@ -63,6 +54,8 @@ $(document).ready(function() {
}
}
drawImage()
// Click handlers
canvas.mousedown(function(e){
var mouseX = e.pageX - this.offsetLeft;
......@@ -85,6 +78,27 @@ $(document).ready(function() {
}
});
canvas.bind('touchmove', function(e){
e.preventDefault()
var mouseX = e.touches[0].pageX - this.offsetLeft;
var mouseY = e.touches[0].pageY - this.offsetTop;
if (paint && pointInsideBaseImage([mouseX, mouseY])){
addClick(mouseX, mouseY, true);
redraw();
}
});
canvas.bind('touchstart', function(e){
e.preventDefault()
var mouseX = e.touches[0].pageX - this.offsetLeft;
var mouseY = e.touches[0].pageY - this.offsetTop;
paint = true;
if (pointInsideBaseImage([mouseX, mouseY])) {
addClick(mouseX, mouseY);
redraw();
}
});
canvas.mouseup(function(e){
paint = false;
});
......@@ -96,7 +110,6 @@ $(document).ready(function() {
$("#embody-canvas").bind('DOMMouseScroll', changeBrushSize)
// DOMMouseScroll is only for firefox
//$(".canvas-container").bind('wheel', changeBrushSize)
function changeBrushSize(event) {
event.preventDefault()
......@@ -149,7 +162,6 @@ $(document).ready(function() {
if ($(img).hasClass('last-embody')) {
// Send data to db
try {
console.log(points)
points = JSON.stringify(points)
$("#canvas-data").val(points);
$("#canvas-form").submit();
......@@ -259,9 +271,5 @@ $(document).ready(function() {
clickY = []
clickDrag = []
}
drawImage()
});
\ No newline at end of file
......@@ -94,10 +94,6 @@
{% if form.__name__ == 'embody' %}
<div class="canvas-container">
<span class="canvas-info"></span>
<canvas id="embody-canvas" class="crosshair" width="20" height="20" style="border: 1px solid blue;" ></canvas>
......
......@@ -187,7 +187,7 @@ CREATE TABLE embody_question (
ALTER TABLE embody_answer ADD COLUMN (embody_question_idembody INTEGER DEFAULT 0);
ALTER TABLE embody_answer ADD CONSTRAINT FOREIGN KEY (embody_question_idembody) REFERENCES embody_question (idembody);
/* Set flag if embody tool is enabled -> this is not the most modulart solution, but works for now */
/* Set flag if embody tool is enabled -> this is not the most modular solution, but works for now */
ALTER TABLE experiment ADD COLUMN (embody_enabled BOOLEAN DEFAULT 0);
/* Set current answer type (embody/slider/etc..) so returning users are routed to correct question */
......
......@@ -38,6 +38,7 @@ from matplotlib.figure import Figure
from flask_socketio import emit
from app import socketio
# Hard coded image size for default embody image
WIDTH = 207
HEIGHT = 600
......@@ -191,15 +192,16 @@ def plot_coordinates(coordinates, image_path=DEFAULT_IMAGE_PATH):
if image_path == DEFAULT_IMAGE_PATH:
for idx, point in enumerate(coordinates["coordinates"]):
frame[point[1], point[0]] = 1
frame[int(point[1]), int(point[0])] = 1
point = ndimage.gaussian_filter(frame, sigma=5)
ax2.imshow(point, cmap='hot', interpolation='none')
# Try to send progress information to socket.io
try:
socketio.sleep(0)
emit('progress', {'done':idx+1/points_count, 'from':points_count})
socketio.sleep(0)
except RuntimeError as err:
print(err)
continue
image_mask = mpimg.imread(IMAGE_PATH_MASK)
......
alembic==0.9.9
autopep8==1.4.4
Babel==2.6.0
click==6.7
cycler==0.10.0
decorator==4.4.0
dnspython==1.16.0
dominate==2.3.1
Flask==1.0.2
Flask-Babel
Flask-Babel==0.12.2
Flask-Bootstrap==3.3.7.1
Flask-Cors==3.0.7
Flask-Login==0.4.1
Flask-Migrate==2.2.1
Flask-Session==0.3.1
Flask-SocketIO==3.3.2
Flask-SQLAlchemy==2.3.2
Flask-Uploads==0.2.1
Flask-WTF==0.14.2
gevent==1.4.0
greenlet==0.4.15
gunicorn==19.9.0
itsdangerous==0.24
Jinja2==2.10
kiwisolver==1.0.1
lml==0.0.4
Mako==1.0.7
MarkupSafe==1.0
matplotlib==3.0.3
monotonic==1.5
mysql-connector==2.2.9
networkx==2.2
numpy==1.16.2
Pillow==6.0.0
pkg-resources==0.0.0
ply==3.11
pycodestyle==2.5.0
pyexcel==0.5.9.1
pyexcel-io==0.5.9.1
PyMySQL==0.9.3
pyparsing==2.3.1
python-dateutil==2.7.3
python-editor==1.0.3
python-engineio==3.5.1
python-socketio==3.1.2
pytz==2018.7
rope==0.12.0
scipy==1.2.1
six==1.11.0
smop==0.41
SQLAlchemy==1.2.8
texttable==1.5.0
uuid==1.30
visitor==0.1.3
Werkzeug==0.14.1
WTForms==2.2.1
WTForms-SQLAlchemy==0.1
pyexcel
gunicorn==19.9.0
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