From c9c3f710ec9a037ef44bd2cc734f1c1bfc548388 Mon Sep 17 00:00:00 2001
From: Ossi Laine <ossi.laine@utu.fi>
Date: Mon, 10 Jun 2019 14:40:25 +0300
Subject: [PATCH] Export embody results as bitmap image

---
 app/routes.py           | 51 ++++++++++++++++++++++++++---------------
 app/static/js/canvas.js | 25 ++++++++++++--------
 app/task/views.py       | 25 ++++++++++----------
 app/templates/base.html |  3 ---
 embody_plot.py          | 11 +++++----
 5 files changed, 67 insertions(+), 48 deletions(-)

diff --git a/app/routes.py b/app/routes.py
index 9a58a83..0db3d78 100644
--- a/app/routes.py
+++ b/app/routes.py
@@ -388,24 +388,39 @@ def download_csv():
 
     for participant in participants:
 
-        # append user session id
-        answer_row += participant.session + ';'
-
-        # TODO:
-        # 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) + ';'
-
-        # append embody answers (coordinates)
-        embody_answers = embody_answer.query.filter_by(answer_set_idanswer_set=participant.idanswer_set).all()     
-        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)
+        try:
+
+            # 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 = [(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 = ''
diff --git a/app/static/js/canvas.js b/app/static/js/canvas.js
index c7a1e72..9f30042 100644
--- a/app/static/js/canvas.js
+++ b/app/static/js/canvas.js
@@ -21,6 +21,8 @@ $(document).ready(function() {
     var clickRadius = new Array();
     var clickDrag = new Array();
     var paint;
+    var width = 0;
+    var height = 0;
     var drawRadius=13
     var default_embody=false
     var points = []
@@ -49,16 +51,16 @@ $(document).ready(function() {
 
         newImage = new Image();
         newImage.src =  img.src
-        imageId = img.id
 
-        var width = newImage.width;
-        var height = newImage.height;
-
-        context.canvas.height = height
-        context.canvas.width = width
-
-        context.drawImage(newImage, 0, 0);
-        $(img).hide()
+        newImage.onload = function() {
+            imageId = img.id
+            width = newImage.width;
+            height = newImage.height;
+            context.canvas.height = height
+            context.canvas.width = width
+            context.drawImage(newImage, 0, 0);
+            $(img).hide()
+        }
     }
 
     // Click handlers
@@ -140,7 +142,9 @@ $(document).ready(function() {
             id: imageId,
             x: clickX,
             y: clickY,
-            r: clickRadius
+            r: clickRadius,
+            width: width,
+            height: height
         })
 
         clickX = []
@@ -150,6 +154,7 @@ $(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();
diff --git a/app/task/views.py b/app/task/views.py
index c6ae884..9ed7b78 100644
--- a/app/task/views.py
+++ b/app/task/views.py
@@ -171,21 +171,10 @@ def task_embody(page_num):
         # Add answer to DB
         if check_answer is None:
             for coordinate_data in coordinates:
-
-                idembody = int(coordinate_data['id'].split('-')[1])
-                del coordinate_data['id']
-                del coordinate_data['r']
-
-                participant_answer = embody_answer(
-                    answer_set_idanswer_set=session['answer_set'], coordinates=json.dumps(coordinate_data), page_idpage=page_id, embody_question_idembody=idembody)
-                db.session.add(participant_answer)
-                db.session.commit()
-
+                save_coordinates(coordinate_data, page_id)
         else:
             flash("Page has been answered already. Answers discarded")
 
-
-
     # Check if there are unanswered slider questions -> if true redirect to same page
     if slider_on():
         update_answer_set_type('slider')
@@ -195,6 +184,18 @@ def task_embody(page_num):
     return next_page(pages)
 
 
+def save_coordinates(coordinate_data, page_id):
+    """All of the embody results from one page/stimulant is saved in this method"""
+    idembody = int(coordinate_data['id'].split('-')[1])
+    del coordinate_data['id']
+    del coordinate_data['r']
+
+    participant_answer = embody_answer(
+        answer_set_idanswer_set=session['answer_set'], coordinates=json.dumps(coordinate_data), page_idpage=page_id, embody_question_idembody=idembody)
+    db.session.add(participant_answer)
+    db.session.commit()
+
+
 @task_blueprint.route('/question/<int:page_num>', methods=['POST'])
 def task_answer(page_num):
     '''Save slider answers to database'''
diff --git a/app/templates/base.html b/app/templates/base.html
index 8b35de2..f94a356 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -15,11 +15,8 @@
     <script src="{{ url_for('static', filename='lib/js/bootstrap.min.js') }}" ></script>
     <title>Onni</title>
 
-    <!-- Bootstrap core CSS -->
-    <link href="/lib/css/bootstrap.min.css" rel="stylesheet">
     
     <!-- Custom styles for this template -->
-    
     <link href="/static/css/slider.css" rel="stylesheet">
     
   </head>
diff --git a/embody_plot.py b/embody_plot.py
index d8c8634..ea1af5d 100644
--- a/embody_plot.py
+++ b/embody_plot.py
@@ -182,14 +182,10 @@ def plot_coordinates(coordinates, image_path=DEFAULT_IMAGE_PATH):
     # 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")
+    ax2.set_title("gaussian disk around points / raw image")
 
     # set height/width from image
     frame = np.zeros((image_data[0] + 10,image_data[1] + 10))
@@ -215,6 +211,11 @@ def plot_coordinates(coordinates, image_path=DEFAULT_IMAGE_PATH):
         # with pre-created image mask (IMAGE_PATH_MASK)
         ax2.imshow(image)
 
+    # Plot coordinates as points
+    ax1.set_title("raw points")
+    ax1.plot(coordinates["x"],coordinates["y"], 'ro', alpha=0.2)
+    ax1.imshow(image, alpha=0.6)
+
     # return figure for saving/etc...
     return fig
 
-- 
GitLab