Commit ccd10549 authored by Ossi Laine's avatar Ossi Laine
Browse files

Updated embody_plot.py and attached it to /experiment/statistics -page

parent 1482d609
......@@ -78,43 +78,36 @@
<tr>
<th scope="col" nowrap>Stimulus ID:</td>
<th scope="col" nowrap>Stimulus:</th>
<th scope="col" nowrap>Embody:</th>
</tr>
</thead>
<tbody>
{% for s in stimulus_headers %}
<tr>
<td>{{ s.idpage }}</td>
{% if s.type == 'text' %}
<td>{{ s.text }}</td>
{% else %}
<td>{{ s.media }}</td>
{% endif %}
<td>{{ s.idpage }}</td>
{% if s.type == 'text' %}
<td>{{ s.text }}</td>
{% else %}
<td>{{ s.media }}</td>
{% endif %}
{% if experiment_info[0].embody_enabled %}
<td>
<button data-value={{ s.idpage }} class="btn btn-primary embody-get-drawing">
<span class="spinner-border spinner-border-sm hidden"></span>
Draw
</button>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<img class="embody-image-container">
<h1 class="container mt-5 display-4 text-left"><br>Rating task values: (Stimulus ID/Question ID)</h1>
......@@ -147,11 +140,9 @@
</tbody>
</table>
<h1 class="container mt-5 display-4 text-left"><br>Background question answers:</h1>
<br>
<table class="table">
<thead>
<tr>
......@@ -174,9 +165,6 @@
</tbody>
</table>
<script src="{{ url_for('static', filename='js/getDrawing.js') }}" ></script>
{% endblock %}
\ No newline at end of file
......@@ -2,6 +2,7 @@
import os
import secrets
import json
from flask import (
Flask,
......@@ -11,7 +12,8 @@ from flask import (
flash,
redirect,
url_for,
Blueprint
Blueprint,
jsonify
)
from wtforms import Form
......@@ -26,6 +28,7 @@ from app.models import page, question
from app.models import background_question_option
from app.models import answer_set, answer, forced_id
from app.models import user, trial_randomization
from app.models import embody_answer
from app.forms import (
CreateBackgroundQuestionForm,
CreateQuestionForm, UploadStimuliForm, EditBackgroundQuestionForm,
......@@ -683,9 +686,21 @@ def edit_stimuli():
exp_id = request.args.get('exp_id', None)
page_id = request.args.get('idpage', None)
edit_page = page.query.filter_by(idpage=page_id).first()
form = EditPageForm(request.form, obj=edit_page)
form = EditPageForm(request.form)
#form = EditPageForm(request.form, obj=edit_page)
# TODO: replacing image not working!!
print(request.files.getlist("file"))
print("errors:", form.errors)
print("form:", form.__dict__)
print("type:", form.type.data)
print("media:", form.media.data)
print("file:", form.file.data)
print("text:", form.text.data)
if request.method == 'POST' and form.validate():
print("POST IMAGE")
#If the stimulus type is not text, then the old stimulus file is deleted from os and replaced
if edit_page.type != 'text':
#remove old file
......@@ -834,3 +849,16 @@ def statistics():
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)
import embody_plot
from flask_cors import CORS,cross_origin
@experiment_blueprint.route('/create_embody', methods=['POST'])
@cross_origin()
def create_embody():
#page = request.args.get("page")
page = request.form["page"]
img_path = embody_plot.get_coordinates(page)
#return send_file('static/' + img_path, 'test')
return json.dumps({'path':img_path})
......@@ -9,9 +9,6 @@ body {
}
.hidden {
display: none;
}
#embody-canvas {
display: block;
......@@ -24,4 +21,31 @@ body {
margin:10px;
}
.crosshair {cursor: crosshair;}
\ No newline at end of file
.crosshair {cursor: crosshair;}
@keyframes spinner-border {
to {
transform: rotate(360deg);
}
}
.spinner-border{
display: inline-block;
width: 2rem;
height: 2rem;
vertical-align: text-bottom;
border: .25em solid currentColor;
border-right-color: transparent;
border-radius: 50%;
-webkit-animation: spinner-border .75s linear infinite;
animation: spinner-border .75s linear infinite;width: 1rem;
}
.spinner-border-sm{
height: 1rem;
border-width: .2em;
}
.hidden {
display: none;
}
......@@ -22,8 +22,19 @@ $(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();
var clickDrag = new Array();
var paint;
var drawRadius=13;
......@@ -105,6 +116,7 @@ $(document).ready(function() {
function addClick(x, y, dragging=false) {
clickX.push(x);
clickY.push(y);
clickRadius.push(drawRadius);
clickDrag.push(dragging);
}
......@@ -185,9 +197,11 @@ $(document).ready(function() {
}
function saveData() {
var points = {
x: clickX,
y: clickY
y: clickY,
r: clickRadius
}
points = JSON.stringify(points)
......
const baseURI = 'http://127.0.0.1:8000/';
var getDrawingURI = baseURI + 'experiment/create_embody';
$(document).ready(function()  {
var drawButtons = $(".embody-get-drawing");
var imageContainer = $(".embody-image-container")
var source = ''
drawButtons.click(function(event) {
event.preventDefault()
var spinner = $(event.target.firstElementChild)
spinner.removeClass("hidden")
var pageId = this.dataset.value
$.ajax({
url: getDrawingURI,
method: 'POST',
data: {page:pageId}
}).done(function(data) {
var source = JSON.parse(data).path;
console.log(source)
d = new Date()
imageContainer.attr("src", "/static/" + source + "?" +d.getTime())
spinner.addClass("hidden")
})
})
})
\ No newline at end of file
......@@ -236,7 +236,9 @@ def task(page_num):
if session['randomization'] == 'On':
randomized_page_id = get_randomized_page(page_id).randomized_idpage
randomized_stimulus = page.query.filter_by(idpage=randomized_page_id).first()
print(session)
return render_template(
'task.html',
pages=pages,
......
......@@ -10,7 +10,7 @@
<meta name="author" content="">
<link rel="stylesheet" href="{{ url_for('static', filename='lib/css/bootstrap.min.css') }}" ></link>
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}" ></link>
<script src="{{ url_for('static', filename='lib/js/jquery-3.3.1.slim.min.js') }}" ></script>
<script src="{{ url_for('static', filename='lib/js/jquery-3.3.1.js') }}" ></script>
<script src="{{ url_for('static', filename='lib/js/popper.min.js') }}" ></script>
<script src="{{ url_for('static', filename='lib/js/bootstrap.min.js') }}" ></script>
<title>Onni</title>
......
......@@ -146,7 +146,8 @@ CREATE TABLE answer (
FOREIGN KEY(question_idquestion) REFERENCES question (idquestion)
);
/* Embody answer (coordinates). Answer is saved as a json object {x:[1,2,100,..], y:[3,4,101,..]} */
/* Embody answer (coordinates). Answer is saved as a json object:
{x:[1,2,100,..], y:[3,4,101,..], r:[13,13,8,...]} */
CREATE TABLE embody_answer (
idanswer INTEGER NOT NULL AUTO_INCREMENT,
answer_set_idanswer_set INTEGER,
......
......@@ -20,24 +20,67 @@ Run:
python embody_plot.py
"""
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import scipy.ndimage as ndimage
import sys
import time
import datetime
import json
import resource
import mysql.connector as mariadb
import io
import urllib, base64
import argparse
import numpy as np
import scipy.ndimage as ndimage
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
# Hard coded image size
WIDTH = 207
HEIGHT = 600
# image paths
IMAGE_PATH = './app/static/img/dummy_600.png'
IMAGE_PATH_MASK = './app/static/img/dummy_600_mask.png'
STATIC_PATH = './app/static/'
# Interpolation methods
METHODS = ['none','bilinear', 'bicubic', 'gaussian']
# SELECT methods
SELECT_ALL = ("SELECT coordinates from embody_answer")
SELECT_BY_EXP_ID = 'select coordinates from embody_answer as em JOIN (SELECT idanswer_set FROM answer_set as a JOIN experiment as e ON a.experiment_idexperiment=e.idexperiment AND e.idexperiment=%s) as ida ON em.answer_set_idanswer_set=ida.idanswer_set'
SELECT_BY_ANSWER_SET = 'select coordinates from embody_answer WHERE answer_set_idanswer_set=%s'
SELECT_BY_PAGE = 'select coordinates from embody_answer WHERE page_idpage=%s'
'''
mariadb_connection = mariadb.connect(
user='rating',
password='rating_passwd',
database='rating_db'
)
cursor = mariadb_connection.cursor()
)
'''
# Get date
now = datetime.datetime.now()
DATE_STRING = now.strftime("%Y-%m-%d")
class MyDB(object):
def __init__(self):
self._db_connection = mariadb.connect(user='rating', password='rating_passwd', database='rating_db')
self._db_cur = self._db_connection.cursor()
def query(self, query, params):
return self._db_cur.execute(query, params)
def __del__(self):
self._db_connection.close()
start = time.time()
def matlab_style_gauss2D(shape=(1,1),sigma=5):
"""2D gaussian mask - should give the same result as MATLAB's
......@@ -52,80 +95,156 @@ def matlab_style_gauss2D(shape=(1,1),sigma=5):
h /= sumh
return h
# Hard coded image size
WIDTH = 207
HEIGHT = 600
# import image
image_path = './app/static/img/dummy_600.png'
image_path_mask = './app/static/img/dummy_600_mask.png'
def map_coordinates(a,b,c=None):
return [a,b,c]
# Load image to a plot
image = mpimg.imread(image_path)
image_mask = mpimg.imread(image_path_mask)
# Interpolation methods
methods = ['none','bilinear', 'bicubic', 'gaussian']
def timeit(method):
def timed(*args, **kw):
ts = time.time()
result = method(*args, **kw)
te = time.time()
if 'log_time' in kw:
name = kw.get('log_name', method.__name__.upper())
kw['log_time'][name] = int((te - ts) * 1000)
else:
print('%r %2.2f ms' % \
(method.__name__, (te - ts) * 1000))
return result
return timed
@timeit
def get_coordinates(selected_value, select_clause=SELECT_BY_PAGE):
"""Select all drawn points from certain stimulus and plot them onto
the human body"""
db = MyDB()
db.query(select_clause, (selected_value,))
# Get coordinates
coordinates = format_coordinates(db._db_cur)
# Draw image
plt = plot_coordinates(coordinates)
# Save image to ./app/static/
img_filename = 'PAGE-' + str(selected_value) + '-' + DATE_STRING + '.png'
plt.savefig(STATIC_PATH + img_filename)
# Return image path to function caller
return img_filename
def format_coordinates(cursor):
# Init coordinate arrays and radius of point
x=[]
y=[]
r=[]
standard_radius=13
# Loop through all of the saved coordinates and push them to coordinates arrays
for coordinate in cursor:
try:
coordinates = json.loads(coordinate[0])
x.extend(coordinates['x'])
y.extend(coordinates['y'])
r.extend(coordinates['r'])
except KeyError:
standard_radiuses = np.full((1, len(coordinates['x'])), standard_radius).tolist()[0]
r.extend(standard_radiuses)
continue
return {
"x":x,
"y":y,
"coordinates":list(map(map_coordinates, x,y,r))
}
def plot_coordinates(coordinates):
# Load image to a plot
image = mpimg.imread(IMAGE_PATH)
image_mask = mpimg.imread(IMAGE_PATH_MASK)
# Init plots
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2)
# Plot coordinates as points
ax1.set_title("raw points")
ax1.plot(coordinates["x"],coordinates["y"], 'ro', alpha=0.2)
ax1.imshow(image)
# Draw circles from coordinates (imshow don't need interpolation)
# TODO: set sigma according to brush size!
ax2.set_title("gaussian disk around points")
frame = np.zeros((HEIGHT,WIDTH))
for point in coordinates["coordinates"]:
frame[point[1], point[0]] = 1
point = ndimage.gaussian_filter(frame, sigma=5)
ax2.imshow(point, cmap='hot', interpolation='none')
# TODO: send progress information to frontend
ax2.imshow(image_mask)
# Draw a gaussian heatmap on the whole image
# NOT USABLE
'''
x_min = min(x)
x_max = max(x)
y_min = min(y)
y_max = max(y)
extent=[x_min, x_max, y_min, y_max]
extent_all = [0,WIDTH,0,HEIGHT]
plt.subplot2grid((2, 2), (1, 1))
plt.title('gaussian heatmap')
plt.imshow(image)
plt.imshow(coordinates, extent=extent_all, cmap='hot', interpolation='gaussian')
plt.imshow(image_mask)
'''
# return figure for saving/etc...
return fig
'''
# Return image as bytes
fig = plt.gcf()
imgdata = io.BytesIO()
fig.savefig(imgdata, format='png')
imgdata.seek(0) # rewind the data
return imgdata.read()
#Show image
mng = plt.get_current_fig_manager()
mng.resize(*mng.window.maxsize())
plt.show()
'''
if __name__=='__main__':
arg_parser = argparse.ArgumentParser(description='Draw bodily maps of emotions')
arg_parser.add_argument('-s','--stimulus', help='Select drawn points from certain stimulus', required=False, action='store_true')
arg_parser.add_argument('-e','--experiment', help='Select drawn points from certain experiment', required=False, action='store_true')
arg_parser.add_argument('-a','--answer-set', help='Select drawn points from certain answer_set', required=False, action='store_true')
arg_parser.add_argument('integers', metavar='N', type=int, nargs='+', help='an integer for the accumulator')
args = vars(arg_parser.parse_args())
value = args['integers'][0]
if args['stimulus']:
get_coordinates(value, SELECT_BY_PAGE)
elif args['experiment']:
get_coordinates(value, SELECT_BY_EXP_ID)
elif args['answer_set']:
get_coordinates(value, SELECT_BY_ANSWER_SET)
else:
print("No arguments given. Exit.")
sys.exit(0)
SELECT_ALL = ("SELECT coordinates from embody_answer")
SELECT_BY_EXP_ID = 'select coordinates from embody_answer as em JOIN (SELECT idanswer_set FROM answer_set as a JOIN experiment as e ON a.experiment_idexperiment=e.idexperiment AND e.idexperiment=%s) as ida ON em.answer_set_idanswer_set=ida.idanswer_set'
exp_id = 2
cursor.execute(SELECT_BY_EXP_ID, (exp_id,))
# Init coordinate arrays
x=[]
y=[]
# Loop through all of the saved coordinates and push them to coordinates arrays
for coordinate in cursor:
coordinates = json.loads(coordinate[0])
x.extend(coordinates['x'])
y.extend(coordinates['y'])
def map_coordinates(a,b):
return [a,b]
coordinates = list(map(map_coordinates, x,y))
# Plot coordinates as points
plt.subplot2grid((2, 2), (0, 0))
plt.title("raw points")
plt.plot(x,y, 'ro', alpha=0.2)
plt.imshow(image)
plt.grid(True)
# Draw circles from coordinates (imshow don't need interpolation)
plt.subplot2grid((2, 2), (0, 1))
plt.title("gaussian disk around points")
frame = np.zeros((HEIGHT,WIDTH))
for point in coordinates:
frame[point[1], point[0]] = 1
point = ndimage.gaussian_filter(frame, sigma=5)
plt.imshow(point, cmap='hot', interpolation='none')
plt.imshow(image_mask)
plt.grid(True)
# Draw a gaussian heatmap on the whole image
# NOT USABLE
x_min = min(x)
x_max = max(x)
y_min = min(y)
y_max = max(y)
extent=[x_min, x_max, y_min, y_max]
extent_all = [0,WIDTH,0,HEIGHT]
plt.subplot2grid((2, 2), (1, 1))
plt.title('gaussian heatmap')
plt.imshow(image)
plt.imshow(coordinates, extent=extent, cmap='hot', interpolation='gaussian')
plt.imshow(image_mask)
end = time.time()
print("Drawing image took:", end - start)
mng = plt.get_current_fig_manager()
mng.resize(*mng.window.maxsize())
plt.show()
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