diff --git a/app/create/views.py b/app/create/views.py index 7f49fe85d9245cd4b644992c01b9f77dce955b78..a9ab7c382a138d3271e40a6e3f25fa658c557f8f 100644 --- a/app/create/views.py +++ b/app/create/views.py @@ -2,13 +2,13 @@ import os from datetime import datetime from flask import ( - Flask, - render_template, - request, - session, - flash, - redirect, - url_for, + Flask, + render_template, + request, + session, + flash, + redirect, + url_for, Blueprint ) @@ -23,44 +23,33 @@ 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.forms import ( - CreateExperimentForm, CreateBackgroundQuestionForm, + CreateExperimentForm, CreateBackgroundQuestionForm, CreateQuestionForm, UploadStimuliForm ) -create_blueprint = Blueprint("create", __name__, - template_folder='templates', - #static_folder='static', - url_prefix='/create') +create_blueprint = Blueprint("create", __name__, + template_folder='templates', + # static_folder='static', + url_prefix='/create') + @create_blueprint.route('/experiment', methods=['GET', 'POST']) @login_required def create_experiment(): - - form = CreateExperimentForm(request.form) + + form = CreateExperimentForm(request.form) if request.method == 'POST' and form.validate(): - + the_time = datetime.now() the_time = the_time.replace(microsecond=0) - - new_exp = experiment(name=request.form['name'], instruction=request.form['instruction'], language=request.form['language'], status='Hidden', randomization='Off', single_sentence_instruction=request.form['single_sentence_instruction'], short_instruction=request.form['short_instruction'], creator_name=request.form['creator_name'], is_archived='False', creation_time=the_time, stimulus_size='7', consent_text=request.form['consent_text'], use_forced_id='Off') + + new_exp = experiment(name=request.form['name'], instruction=request.form['instruction'], language=request.form['language'], status='Hidden', randomization='Off', single_sentence_instruction=request.form['single_sentence_instruction'], + short_instruction=request.form['short_instruction'], creator_name=request.form['creator_name'], is_archived='False', creation_time=the_time, stimulus_size='7', consent_text=request.form['consent_text'], use_forced_id='Off') db.session.add(new_exp) - db.session.commit() + db.session.commit() exp_id = new_exp.idexperiment - #data = request.form.to_dict() - #for key, value in data.items(): - #tähän db insertit - - #flash(key) - #flash(value) - #flash('{}'.format(form.name.data)) - - #Input registration page answers to database - # participant_background_question_answers = background_question_answer(answer_set_idanswer_set=session['answer_set'], answer=value, background_question_idbackground_question=key) - # db.session.add(participant_background_question_answers) - # db.session.commit() - return redirect(url_for('create.experiment_bgquestions', exp_id=exp_id)) return render_template('create_experiment.html', form=form) @@ -69,36 +58,38 @@ def create_experiment(): @create_blueprint.route('/experiment_bgquestions', methods=['GET', 'POST']) @login_required def experiment_bgquestions(): - + exp_id = request.args.get('exp_id', None) form = CreateBackgroundQuestionForm(request.form) - + if request.method == 'POST' and form.validate(): str = form.bg_questions_and_options.data - #Split the form data into a list that separates questions followed by the corresponding options + # Split the form data into a list that separates questions followed by the corresponding options str_list = str.split('/n') - #Iterate through the questions and options list + # Iterate through the questions and options list for a in range(len(str_list)): - - #Split the list cells further into questions and options + + # Split the list cells further into questions and options list = str_list[a].split(';') - - #Input the first item of the list as a question in db and the items followed by that as options for that question + + # Input the first item of the list as a question in db and the items followed by that as options for that question for x in range(len(list)): - + if x == 0: - add_bgquestion = background_question(background_question=list[x], experiment_idexperiment=exp_id) + add_bgquestion = background_question( + background_question=list[x], experiment_idexperiment=exp_id) db.session.add(add_bgquestion) db.session.commit() else: - add_bgq_option = background_question_option(background_question_idbackground_question=add_bgquestion.idbackground_question, option=list[x]) + add_bgq_option = background_question_option( + background_question_idbackground_question=add_bgquestion.idbackground_question, option=list[x]) db.session.add(add_bgq_option) db.session.commit() - - return redirect(url_for('create.experiment_questions', exp_id=exp_id)) + + return redirect(url_for('create.experiment_questions', exp_id=exp_id)) return render_template('create_experiment_bgquestions.html', form=form, exp_id=exp_id) @@ -107,7 +98,7 @@ def experiment_bgquestions(): @login_required def experiment_questions(): """Add slider questions""" - + exp_id = request.args.get('exp_id', None) form = CreateQuestionForm(request.form) @@ -116,86 +107,87 @@ def experiment_questions(): str = form.questions_and_options.data str_list = str.split('/n') - for a in range(len(str_list)): + for a in range(len(str_list)): list = str_list[a].split(';') - - #If there are the wrong amount of values for any of the the slider input values - #redirect back to the form + + # If there are the wrong amount of values for any of the the slider input values + # redirect back to the form if len(list) != 3: - flash("Error Each slider must have 3 parameters separated by ; Some slider has:") + flash( + "Error Each slider must have 3 parameters separated by ; Some slider has:") flash(len(list)) - + return redirect(url_for('create.experiment_questions', exp_id=exp_id)) - #If all the slider inputs were of length 3 items - #we can input them to db - for a in range(len(str_list)): + # If all the slider inputs were of length 3 items + # we can input them to db + for a in range(len(str_list)): list = str_list[a].split(';') - - add_question = question(experiment_idexperiment=exp_id, question=list[0], left=list[1], right=list[2]) + + add_question = question( + experiment_idexperiment=exp_id, question=list[0], left=list[1], right=list[2]) db.session.add(add_question) db.session.commit() - - return redirect(url_for('create.experiment_upload_stimuli', exp_id=exp_id)) + + return redirect(url_for('create.experiment_upload_stimuli', exp_id=exp_id)) @create_blueprint.route('/experiment_upload_stimuli', methods=['GET', 'POST']) @login_required def experiment_upload_stimuli(): """Upload stimuli""" - + exp_id = request.args.get('exp_id', None) form = UploadStimuliForm(request.form) - + if request.method == 'POST' and form.validate(): - - #If stimulus type is text lets parse the information and insert it to database + + # If stimulus type is text lets parse the information and insert it to database if form.type.data == 'text': string = form.text.data str_list = string.split('/n') for a in range(len(str_list)): - add_text_stimulus = page(experiment_idexperiment=exp_id, type='text', text=str_list[a], media='none') + add_text_stimulus = page( + experiment_idexperiment=exp_id, type='text', text=str_list[a], media='none') db.session.add(add_text_stimulus) db.session.commit() - - return redirect(url_for('experiment.view', exp_id=exp_id)) - + + return redirect(url_for('experiment.view', exp_id=exp_id)) + else: - #Upload stimuli into /static/experiment_stimuli/exp_id folder - #Create the pages for the stimuli by inserting experiment_id, stimulus type, text and names of the stimulus files (as a path to the folder) + # Upload stimuli into /static/experiment_stimuli/exp_id folder + # Create the pages for the stimuli by inserting experiment_id, stimulus type, text and names of the stimulus files (as a path to the folder) path = 'static/experiment_stimuli/' + str(exp_id) target = os.path.join(APP_ROOT, path) - + if not os.path.isdir(target): os.mkdir(target) - - #This returns a list of filenames: request.files.getlist("file") + + # This returns a list of filenames: request.files.getlist("file") for file in request.files.getlist("file"): - - #save files in the correct folder + + # save files in the correct folder filename = file.filename destination = "/".join([target, filename]) file.save(destination) - - #add pages to the db - db_path = path + str('/') + str(filename) - new_page = page(experiment_idexperiment=exp_id, type=form.type.data, media=db_path) - + + # add pages to the db + db_path = path + str('/') + str(filename) + new_page = page(experiment_idexperiment=exp_id, + type=form.type.data, media=db_path) + db.session.add(new_page) db.session.commit() - - #flash("Succes!") - + + # flash("Succes!") + return redirect(url_for('experiment.view', exp_id=exp_id)) - + return redirect(url_for('create.experiment_upload_stimuli', exp_id=exp_id)) return render_template('create_experiment_upload_stimuli.html', form=form) - - -# EOF \ No newline at end of file diff --git a/app/experiment/views.py b/app/experiment/views.py index c7e9cb15a110081e86804ea5cfa7aec542fd5344..cfee8678a35ffe6a0286e52d9abf8b15a01ee29d 100644 --- a/app/experiment/views.py +++ b/app/experiment/views.py @@ -731,7 +731,6 @@ def remove_embody(): # Stimuli: - @experiment_blueprint.route('/add_stimuli', methods=['GET', 'POST']) @login_required def add_stimuli(): @@ -1045,13 +1044,11 @@ def remove_rows(rows): @socketio.on('connect', namespace="/create_embody") def start_create_embody(): - print('io connected') emit('success', {'connection': 'on'}) @socketio.on('draw', namespace="/create_embody") def create_embody(meta): - print("draw initialized") page = meta["page"] embody = meta["embody"] img_path = embody_plot.get_coordinates(page, embody) @@ -1061,7 +1058,6 @@ def create_embody(meta): @socketio.on('connect', namespace="/download_csv") def start_download_csv(): - print('io connected') emit('success', {'connection': 'Start generating CSV file'}) diff --git a/app/forms.py b/app/forms.py index d532931f9aa3db95a8e1f0cf80b65b6d6022be46..265cd9b3817a0d99a568f656b41b7dcc3b578de6 100644 --- a/app/forms.py +++ b/app/forms.py @@ -19,46 +19,47 @@ class LoginForm(FlaskForm): class RegisterForm(Form): - questions1 = FieldList(SelectField([validators.InputRequired()])) submit = SubmitField("Send") class TaskForm(Form): - __name__= 'slider' + __name__ = 'slider' categories1 = FieldList(SelectField([validators.InputRequired()])) submit = SubmitField("Send") class StringForm(Form): - __name__= 'embody' + __name__ = 'embody' text = StringField() submit = SubmitField("Send") class ContinueTaskForm(FlaskForm): - + participant_id = StringField('participant_id', validators=[DataRequired()]) - submit = SubmitField( _l('Continue rating') ) + submit = SubmitField(_l('Continue rating')) + class StartWithIdForm(FlaskForm): - + participant_id = StringField('participant_id', validators=[DataRequired()]) - submit = SubmitField( _l('Start rating') ) - + submit = SubmitField(_l('Start rating')) + class Questions(FlaskForm): - + questions = StringField() class Answers(FlaskForm): - - background_question_idbackground_question = SelectField(coerce=int, validators=[InputRequired]) + + background_question_idbackground_question = SelectField( + coerce=int, validators=[InputRequired]) class BackgroundQuestionForm(Form): - + idbackground_question_option = StringField() background_question_idbackground_question = StringField() option = StringField() @@ -66,13 +67,13 @@ class BackgroundQuestionForm(Form): class TestForm(Form): - + question_name = StringField() options1 = SelectField() class TestForm1(Form): - + questions1 = FieldList(SelectField([validators.InputRequired()])) submit = SubmitField("Send") @@ -82,14 +83,16 @@ class TestForm2(Form): questions1 = SelectField() -#Forms for editing functions - +# Forms for editing functions + class CreateExperimentForm(Form): name = StringField('Name', [validators.DataRequired()]) - creator_name = StringField('Creator_name', [validators.DataRequired()]) - single_sentence_instruction = StringField('Single_sentence_instruction', [validators.DataRequired()]) - short_instruction = TextAreaField('Short_instruction', [validators.DataRequired()]) + creator_name = StringField('Creator_name', [validators.DataRequired()]) + single_sentence_instruction = StringField( + 'Single_sentence_instruction', [validators.DataRequired()]) + short_instruction = TextAreaField( + 'Short_instruction', [validators.DataRequired()]) instruction = TextAreaField('Instruction', [validators.DataRequired()]) consent_text = TextAreaField('Instruction', [validators.DataRequired()]) language = StringField('Language', [validators.DataRequired()]) @@ -102,53 +105,68 @@ class EditExperimentForm(Form): creator_name = StringField('Creator_name', [validators.DataRequired()]) instruction = TextAreaField('Instruction', [validators.DataRequired()]) consent_text = TextAreaField('Instruction', [validators.DataRequired()]) - short_instruction = TextAreaField('Short_instruction', [validators.DataRequired()]) - single_sentence_instruction = StringField('Single_sentece_instruction', [validators.DataRequired()]) + short_instruction = TextAreaField( + 'Short_instruction', [validators.DataRequired()]) + single_sentence_instruction = StringField( + 'Single_sentece_instruction', [validators.DataRequired()]) language = SelectField('Language', choices=[ - ('Afrikanns', 'Afrikanns'), ('Albanian', 'Albanian'), ('Arabic', 'Arabic'), ('Armenian', 'Armenian'), ('Basque', 'Basque'), ('Bengali', 'Bengali'), ('Bulgarian', 'Bulgarian'), - ('Catalan', 'Catalan'), ('Cambodian', 'Cambodian'), ('Chinese', 'Chinese'), ('Croation', 'Croation'), ('Czech', 'Czech'), ('Danish', 'Danish'), - ('Dutch', 'Dutch'), ('English', 'English'), ('Estonian', 'Estonian'), ('Fiji', 'Fiji'), ('Finnish', 'Finnish'), ('French', 'French'), ('Georgian', 'Georgian'), - ('German', 'German'), ('Greek', 'Greek'), ('Gujarati', 'Gujarati'), ('Hebrew', 'Hebrew'), ('Hindi', 'Hindi'), ('Hungarian', 'Hungarian'), ('Icelandic', 'Icelandic'), - ('Indonesian', 'Indonesian'), ('Irish', 'Irish'), ('Italian', 'Italian'), ('Japanese', 'Japanese'), ('Javanese', 'Javanese'), ('Korean', 'Korean'), ('Latin', 'Latin'), - ('Latvian', 'Latvian'), ('Lithuanian', 'Lithuanian'), ('Macedonian', 'Macedonian'), ('Malay', 'Malay'), ('Malayalam', 'Malayalam'), ('Maltese', 'Maltese'), ('Maori', 'Maori'), - ('Marathi', 'Marathi'), ('Mongolian', 'Mongolian'), ('Nepali', 'Nepali'), ('Norwegian', 'Norwegian'), ('Persian', 'Persian'), ('Polish', 'Polish'), ('Portuguese', 'Portuguese'), - ('Punjabi', 'Punjabi'), ('Quechua', 'Quechua'), ('Romanian', 'Romanian'), ('Russian', 'Russian'), ('Samoan', 'Samoan'), ('Serbian', 'Serbian'), ('Slovak', 'Slovak'), - ('Slovenian', 'Slovenian'), ('Spanish', 'Spanish'), ('Swahili', 'Swahili'), ('Swedish ', 'Swedish '), ('Tamil', 'Tamil'), ('Tatar', 'Tatar'), ('Telugu', 'Telugu'), - ('Thai', 'Thai'), ('Tibetan', 'Tibetan'), ('Tonga', 'Tonga'), ('Turkish', 'Turkish'), ('Ukranian', 'Ukranian'), ('Urdu', 'Urdu'), ('Uzbek', 'Uzbek'), ('Vietnamese', 'Vietnamese'), - ('Welsh', 'Welsh'), ('Xhosa', 'Xhosa')]) + ('Afrikanns', 'Afrikanns'), ('Albanian', 'Albanian'), ('Arabic', 'Arabic'), ('Armenian', + 'Armenian'), ('Basque', 'Basque'), ('Bengali', 'Bengali'), ('Bulgarian', 'Bulgarian'), + ('Catalan', 'Catalan'), ('Cambodian', 'Cambodian'), ('Chinese', + 'Chinese'), ('Croation', 'Croation'), ('Czech', 'Czech'), ('Danish', 'Danish'), + ('Dutch', 'Dutch'), ('English', 'English'), ('Estonian', 'Estonian'), ('Fiji', + 'Fiji'), ('Finnish', 'Finnish'), ('French', 'French'), ('Georgian', 'Georgian'), + ('German', 'German'), ('Greek', 'Greek'), ('Gujarati', 'Gujarati'), ('Hebrew', + 'Hebrew'), ('Hindi', 'Hindi'), ('Hungarian', 'Hungarian'), ('Icelandic', 'Icelandic'), + ('Indonesian', 'Indonesian'), ('Irish', 'Irish'), ('Italian', 'Italian'), ('Japanese', + 'Japanese'), ('Javanese', 'Javanese'), ('Korean', 'Korean'), ('Latin', 'Latin'), + ('Latvian', 'Latvian'), ('Lithuanian', 'Lithuanian'), ('Macedonian', 'Macedonian'), ('Malay', + 'Malay'), ('Malayalam', 'Malayalam'), ('Maltese', 'Maltese'), ('Maori', 'Maori'), + ('Marathi', 'Marathi'), ('Mongolian', 'Mongolian'), ('Nepali', 'Nepali'), ('Norwegian', + 'Norwegian'), ('Persian', 'Persian'), ('Polish', 'Polish'), ('Portuguese', 'Portuguese'), + ('Punjabi', 'Punjabi'), ('Quechua', 'Quechua'), ('Romanian', 'Romanian'), ('Russian', + 'Russian'), ('Samoan', 'Samoan'), ('Serbian', 'Serbian'), ('Slovak', 'Slovak'), + ('Slovenian', 'Slovenian'), ('Spanish', 'Spanish'), ('Swahili', 'Swahili'), ('Swedish ', + 'Swedish '), ('Tamil', 'Tamil'), ('Tatar', 'Tatar'), ('Telugu', 'Telugu'), + ('Thai', 'Thai'), ('Tibetan', 'Tibetan'), ('Tonga', 'Tonga'), ('Turkish', 'Turkish'), ('Ukranian', + 'Ukranian'), ('Urdu', 'Urdu'), ('Uzbek', 'Uzbek'), ('Vietnamese', 'Vietnamese'), + ('Welsh', 'Welsh'), ('Xhosa', 'Xhosa')]) stimulus_size = SelectField('Stimulus_size', choices=[ - ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8'), ('9', '9'), ('10', '10'), ('11', '11'), ('12', '12')]) - + ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8'), ('9', '9'), ('10', '10'), ('11', '11'), ('12', '12')]) + submit = SubmitField('Send') class CreateBackgroundQuestionForm(Form): - - bg_questions_and_options = TextAreaField('Background questions and options', [validators.DataRequired()]) + + bg_questions_and_options = TextAreaField( + 'Background questions and options', [validators.DataRequired()]) submit = SubmitField('Send') - + class EditBackgroundQuestionForm(Form): - - bg_questions_and_options = TextAreaField('Background questions and options') + + bg_questions_and_options = TextAreaField( + 'Background questions and options') new_values = TextAreaField('New values', [validators.DataRequired()]) submit = SubmitField('Send') class CreateQuestionForm(Form): - - questions_and_options = TextAreaField('Questions and options', [validators.DataRequired()]) + + questions_and_options = TextAreaField( + 'Questions and options', [validators.DataRequired()]) submit = SubmitField('Send') class CreateEmbodyForm(Form): - + question = TextAreaField('Question') picture = FileField('Upload picture') submit = SubmitField('Send') -class EditQuestionForm(Form): +class EditQuestionForm(Form): left = StringField('left_scale', [validators.DataRequired()]) right = StringField('right_scale', [validators.DataRequired()]) @@ -156,8 +174,9 @@ class EditQuestionForm(Form): class UploadStimuliForm(Form): - - type = RadioField('type', choices=[('text', 'text'), ('picture', 'picture'), ('video', 'video'), ('audio', 'audio')]) + + type = RadioField('type', choices=[ + ('text', 'text'), ('picture', 'picture'), ('video', 'video'), ('audio', 'audio')]) text = TextAreaField('Text stimulus') media = TextAreaField('Media filename') file = FileField('Upload file') @@ -165,28 +184,28 @@ class UploadStimuliForm(Form): class UploadResearchBulletinForm(Form): - + file = FileField('Upload file') submit = SubmitField('Send') class EditPageForm(Form): - - type = RadioField('type', choices=[('text', 'text'), ('picture', 'picture'), ('video', 'video'), ('audio', 'audio')]) + + type = RadioField('type', choices=[ + ('text', 'text'), ('picture', 'picture'), ('video', 'video'), ('audio', 'audio')]) text = TextAreaField('Text stimulus') media = TextAreaField('Media filename') file = FileField('Upload file') submit = SubmitField('Send') - - + + class RemoveExperimentForm(Form): remove = TextAreaField('Remove') submit = SubmitField('Send') -class GenerateIdForm(Form): +class GenerateIdForm(Form): number = IntegerField('number', [validators.DataRequired()]) string = StringField('string', [validators.DataRequired()]) submit = SubmitField('Submit') - diff --git a/app/models.py b/app/models.py index c792add29192ab35999a8898e477eff576fd505b..96af1a0898b8f86321afd2011abd121a873309d4 100644 --- a/app/models.py +++ b/app/models.py @@ -3,16 +3,13 @@ from flask import session from app import db from sqlalchemy import Column, Integer, String, Text, Boolean from flask_wtf import FlaskForm -from wtforms_sqlalchemy.fields import QuerySelectField, QuerySelectMultipleField +from wtforms_sqlalchemy.fields import QuerySelectField from werkzeug.security import generate_password_hash, check_password_hash from flask_login import UserMixin from app import login from datetime import datetime -"""DATABASE CLASSES""" - - class background_question(db.Model): __tablename__ = "background_question" idbackground_question = db.Column(db.Integer, primary_key=True) diff --git a/app/routes.py b/app/routes.py index 9d64ba14306b391f4546579683f54c383f1e1b8f..5e951f9b1a57affc68fb3f64ef923a8ca817e561 100644 --- a/app/routes.py +++ b/app/routes.py @@ -198,14 +198,10 @@ def register(): data = request.form.to_dict() for key, value in data.items(): - - # tähän db insertit - - # flash(key) - # flash(value) # Input registration page answers to database participant_background_question_answers = background_question_answer( - answer_set_idanswer_set=session['answer_set'], answer=value, background_question_idbackground_question=key) + answer_set_idanswer_set=session['answer_set'], + answer=value, background_question_idbackground_question=key) db.session.add(participant_background_question_answers) db.session.commit() @@ -253,7 +249,8 @@ def begin_with_id(): else: # save the participant ID in session list for now, this is deleted after the session has been started in participant_session-view session['begin_with_id'] = form.participant_id.data - return render_template('consent.html', exp_id=exp_id, experiment_info=experiment_info, instruction_paragraphs=instruction_paragraphs, consent_paragraphs=consent_paragraphs) + return render_template('consent.html', exp_id=exp_id, experiment_info=experiment_info, + instruction_paragraphs=instruction_paragraphs, consent_paragraphs=consent_paragraphs) return render_template('begin_with_id.html', exp_id=exp_id, form=form) @@ -294,7 +291,9 @@ def instructions(): instruction_paragraphs = str(instructions.instruction) instruction_paragraphs = instruction_paragraphs.split('<br>') - return render_template('instructions.html', instruction_paragraphs=instruction_paragraphs, participant_id=participant_id) + return render_template('instructions.html', + instruction_paragraphs=instruction_paragraphs, + participant_id=participant_id) @app.route('/researcher_login', methods=['GET', 'POST']) @@ -312,9 +311,6 @@ def login(): login_user(user_details, remember=form.remember_me.data) return redirect(url_for('index')) -# flash('Login requested for user {}, remember_me={}'.format( -# form.username.data, form.remember_me.data)) -# return redirect('/index') return render_template('researcher_login.html', title='Sign In', form=form) @@ -326,12 +322,12 @@ def logout(): @app.route('/view_research_notification') def view_research_notification(): - exp_id = request.args.get('exp_id', None) image = experiment.query.filter_by(idexperiment=exp_id).first() research_notification_filename = image.research_notification_filename - return render_template('view_research_notification.html', research_notification_filename=research_notification_filename) + return render_template('view_research_notification.html', + research_notification_filename=research_notification_filename) @app.route('/researcher_info') diff --git a/app/static/js/getDrawing.js b/app/static/js/getDrawing.js index 8df13c3db64fcae7e0fad064a5e9cb1b82d6eaa6..a57cc53c3f4fc14c9d97536b93581058bfd52b1b 100644 --- a/app/static/js/getDrawing.js +++ b/app/static/js/getDrawing.js @@ -36,8 +36,6 @@ $(document).ready(function () { drawButtons.click(function (event) { event.preventDefault(); - console.log("SADATDS"); - // Init socket var socket = io.connect(getDrawingURI); initConnection(socket); diff --git a/app/task/views.py b/app/task/views.py index 6e3a2085c9913f48963d4b4fa4b5e10eec24e036..879596da2ac509b93a682cc65fa60332ff02abd4 100644 --- a/app/task/views.py +++ b/app/task/views.py @@ -1,23 +1,20 @@ - - - import math import json from datetime import datetime from flask import ( - Flask, - render_template, - request, - session, - flash, - redirect, - url_for, + Flask, + render_template, + request, + session, + flash, + redirect, + url_for, Blueprint ) -from flask_cors import CORS,cross_origin +from flask_cors import CORS, cross_origin -from sqlalchemy import and_ +from sqlalchemy import and_ from sqlalchemy import exc from flask_babel import _, lazy_gettext as _l @@ -28,10 +25,10 @@ from app.models import answer_set, answer, embody_answer, embody_question from app.models import user, trial_randomization from app.forms import Answers, TaskForm, ContinueTaskForm, StringForm -task_blueprint = Blueprint("task", __name__, - template_folder='templates', - static_folder='static', - url_prefix='/task') +task_blueprint = Blueprint("task", __name__, + template_folder='templates', + static_folder='static', + url_prefix='/task') def get_randomized_page(page_id): @@ -45,7 +42,8 @@ def add_slider_answer(key, value, page_id=None): the values are inputted for session['current_idpage']. Otherwise the values are set for the corresponding id found in the trial randomization table""" - participant_answer = answer(question_idquestion=key, answer_set_idanswer_set=session['answer_set'], answer=value, page_idpage=page_id) + participant_answer = answer( + question_idquestion=key, answer_set_idanswer_set=session['answer_set'], answer=value, page_idpage=page_id) db.session.add(participant_answer) db.session.commit() @@ -55,8 +53,10 @@ def update_answer_set_page(): the_time = datetime.now() the_time = the_time.replace(microsecond=0) - update_answer_counter = answer_set.query.filter_by(idanswer_set=session['answer_set']).first() - update_answer_counter.answer_counter = int(update_answer_counter.answer_counter) + 1 + update_answer_counter = answer_set.query.filter_by( + idanswer_set=session['answer_set']).first() + update_answer_counter.answer_counter = int( + update_answer_counter.answer_counter) + 1 update_answer_counter.last_answer_time = the_time db.session.commit() @@ -67,7 +67,8 @@ def update_answer_set_type(answer_type): the_time = datetime.now() the_time = the_time.replace(microsecond=0) - updated_answer_set = answer_set.query.filter_by(idanswer_set=session['answer_set']).first() + updated_answer_set = answer_set.query.filter_by( + idanswer_set=session['answer_set']).first() updated_answer_set.answer_type = answer_type updated_answer_set.last_answer_time = the_time db.session.commit() @@ -77,17 +78,19 @@ def select_form_type(): """Select form type based on the value in answer_set->answer_type""" form = None - answer_set_type = answer_set.query.filter_by(idanswer_set=session['answer_set']).first().answer_type + answer_set_type = answer_set.query.filter_by( + idanswer_set=session['answer_set']).first().answer_type if answer_set_type == 'slider': form = TaskForm() # Get sliders from this experiment - categories = question.query.filter_by(experiment_idexperiment=session['exp_id']).all() + categories = question.query.filter_by( + experiment_idexperiment=session['exp_id']).all() categories_and_scales = {} - for cat in categories: + for cat in categories: scale_list = [(cat.left, cat.right)] - categories_and_scales[cat.idquestion, cat.question] = scale_list + categories_and_scales[cat.idquestion, cat.question] = scale_list form.categories1 = categories_and_scales else: form = StringForm() @@ -100,9 +103,11 @@ def check_if_answer_exists(answer_type, page_id): check_answer = None if answer_type == 'embody': - check_answer = embody_answer.query.filter(and_(embody_answer.answer_set_idanswer_set==session['answer_set'], embody_answer.page_idpage==page_id)).first() + check_answer = embody_answer.query.filter(and_( + embody_answer.answer_set_idanswer_set == session['answer_set'], embody_answer.page_idpage == page_id)).first() elif answer_type == 'slider': - check_answer = answer.query.filter(and_(answer.answer_set_idanswer_set==session['answer_set'], answer.page_idpage==page_id)).first() + check_answer = answer.query.filter(and_( + answer.answer_set_idanswer_set == session['answer_set'], answer.page_idpage == page_id)).first() return check_answer @@ -110,10 +115,10 @@ def check_if_answer_exists(answer_type, page_id): def next_page(pages): # If no more pages left -> complete task if not pages.has_next: - return redirect ( url_for('task.completed')) + return redirect(url_for('task.completed')) # If user has answered to all questions, then move to next page - return redirect( url_for('task.task', page_num=pages.next_num)) + return redirect(url_for('task.task', page_num=pages.next_num)) def get_experiment_info(): @@ -124,6 +129,7 @@ def get_experiment_info(): flash("No valid session found") return redirect('/') + def embody_on(): """Check from session[exp_id] if embody questions are enabled""" experiment_info = get_experiment_info() @@ -136,7 +142,8 @@ def embody_on(): def slider_on(): """Check from session[exp_id] if there are slider questions in this session""" experiment_info = get_experiment_info() - questions = question.query.filter_by(experiment_idexperiment=experiment_info.idexperiment).all() + questions = question.query.filter_by( + experiment_idexperiment=experiment_info.idexperiment).all() if len(questions) == 0: return False @@ -149,7 +156,8 @@ def task_embody(page_num): '''Save embody drawing to database.''' form = StringForm(request.form) - pages = page.query.filter_by(experiment_idexperiment=session['exp_id']).paginate(per_page=1, page=page_num, error_out=True) + pages = page.query.filter_by(experiment_idexperiment=session['exp_id']).paginate( + per_page=1, page=page_num, error_out=True) page_id = pages.items[0].idpage if form.validate(): @@ -160,7 +168,7 @@ def task_embody(page_num): if session['randomization'] == 'On': page_id = get_randomized_page(page_id).randomized_idpage - check_answer = check_if_answer_exists('embody',page_id) + check_answer = check_if_answer_exists('embody', page_id) # Add answer to DB if check_answer is None: @@ -172,7 +180,7 @@ def task_embody(page_num): # Check if there are unanswered slider questions -> if true redirect to same page if slider_on(): update_answer_set_type('slider') - return redirect( url_for('task.task', page_num=page_num)) + return redirect(url_for('task.task', page_num=page_num)) update_answer_set_page() return next_page(pages) @@ -195,16 +203,17 @@ def task_answer(page_num): '''Save slider answers to database''' form = TaskForm(request.form) - pages = page.query.filter_by(experiment_idexperiment=session['exp_id']).paginate(per_page=1, page=page_num, error_out=True) + pages = page.query.filter_by(experiment_idexperiment=session['exp_id']).paginate( + per_page=1, page=page_num, error_out=True) page_id = pages.items[0].idpage if form.validate(): - # Check if randomization ON and if user has already answered to slider question + # Check if randomization ON and if user has already answered to slider question if session['randomization'] == 'On': page_id = get_randomized_page(page_id).randomized_idpage - - check_answer = check_if_answer_exists('slider',page_id) + + check_answer = check_if_answer_exists('slider', page_id) if check_answer is None: data = request.form.to_dict() @@ -212,7 +221,7 @@ def task_answer(page_num): add_slider_answer(key, value, page_id) else: flash("Page has been answered already. Answers discarded") - + if embody_on(): update_answer_set_type('embody') @@ -224,15 +233,16 @@ def task_answer(page_num): @task_blueprint.route('/<int:page_num>', methods=['GET']) def task(page_num): """Get selected task page""" - randomized_stimulus="" + randomized_stimulus = "" experiment_info = get_experiment_info() - - #for text stimuli the size needs to be calculated since the template element utilises h1-h6 tags. - #A value of stimulus size 12 gives h1 and value of 1 gives h6 + + # for text stimuli the size needs to be calculated since the template element utilises h1-h6 tags. + # A value of stimulus size 12 gives h1 and value of 1 gives h6 stimulus_size = experiment_info.stimulus_size stimulus_size_text = 7-math.ceil((int(stimulus_size)/2)) - pages = page.query.filter_by(experiment_idexperiment=session['exp_id']).paginate(per_page=1, page=page_num, error_out=True) + pages = page.query.filter_by(experiment_idexperiment=session['exp_id']).paginate( + per_page=1, page=page_num, error_out=True) page_id = pages.items[0].idpage progress_bar_percentage = round((pages.page/pages.pages)*100) session['current_idpage'] = page_id @@ -241,20 +251,22 @@ def task(page_num): # but we will pass the randomized pair of the page_id from trial randomization table to the task.html 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() + randomized_stimulus = page.query.filter_by( + idpage=randomized_page_id).first() - # get all embody questions - embody_questions = embody_question.query.filter_by(experiment_idexperiment=session['exp_id']).all() + # get all embody questions + embody_questions = embody_question.query.filter_by( + experiment_idexperiment=session['exp_id']).all() return render_template( - 'task.html', - pages=pages, + 'task.html', + pages=pages, page_num=page_num, - progress_bar_percentage=progress_bar_percentage, - form=select_form_type(), - randomized_stimulus=randomized_stimulus, - rating_instruction=experiment_info.single_sentence_instruction, - stimulus_size=stimulus_size, + progress_bar_percentage=progress_bar_percentage, + form=select_form_type(), + randomized_stimulus=randomized_stimulus, + rating_instruction=experiment_info.single_sentence_instruction, + stimulus_size=stimulus_size, stimulus_size_text=stimulus_size_text, experiment_info=experiment_info, embody_questions=embody_questions @@ -264,7 +276,7 @@ def task(page_num): @task_blueprint.route('/completed') def completed(): session.pop('user', None) - session.pop('exp_id', None) + session.pop('exp_id', None) session.pop('agree', None) session.pop('answer_set', None) session.pop('type', None) @@ -282,56 +294,59 @@ def continue_task(): session['exp_id'] = exp_id form = ContinueTaskForm() - + if form.validate_on_submit(): - #check if participant ID is found from db and that the answer set is linked to the correct experiment - participant = answer_set.query.filter(and_(answer_set.session==form.participant_id.data, answer_set.experiment_idexperiment==exp_id)).first() + # check if participant ID is found from db and that the answer set is linked to the correct experiment + participant = answer_set.query.filter(and_( + answer_set.session == form.participant_id.data, answer_set.experiment_idexperiment == exp_id)).first() if participant is None: flash('Invalid ID') - return redirect(url_for('task.continue_task', exp_id=exp_id)) - - #if correct participant_id is found with the correct experiment ID; start session for that user + return redirect(url_for('task.continue_task', exp_id=exp_id)) + + # if correct participant_id is found with the correct experiment ID; start session for that user exp = get_experiment_info() - session['user'] = form.participant_id.data + session['user'] = form.participant_id.data session['answer_set'] = participant.idanswer_set session['randomization'] = exp.randomization update_answer_set_type(participant.answer_type) - - mediatype = page.query.filter_by(experiment_idexperiment=session['exp_id']).first() + + mediatype = page.query.filter_by( + experiment_idexperiment=session['exp_id']).first() if mediatype: session['type'] = mediatype.type else: flash('No pages or mediatype set for experiment') return redirect('/') - #If participant has done just the registration redirect to the first page of the experiment + # If participant has done just the registration redirect to the first page of the experiment if participant.answer_counter == 0: - return redirect( url_for('task.task', page_num=1)) - + return redirect(url_for('task.task', page_num=1)) + redirect_to_page = participant.answer_counter + 1 - experiment_page_count = db.session.query(page).filter_by(experiment_idexperiment=session['exp_id']).count() - - #If participant has ansvered all pages allready redirect to task completed page + experiment_page_count = db.session.query(page).filter_by( + experiment_idexperiment=session['exp_id']).count() + + # If participant has ansvered all pages allready redirect to task completed page if experiment_page_count == participant.answer_counter: - return redirect( url_for('task.completed')) - - return redirect( url_for('task.task', page_num=redirect_to_page)) - + return redirect(url_for('task.completed')) + + return redirect(url_for('task.task', page_num=redirect_to_page)) + return render_template('continue_task.html', exp_id=exp_id, form=form) @task_blueprint.route('/quit') def quit(): - + user_id = session['user'] session.pop('user', None) - session.pop('exp_id', None) + session.pop('exp_id', None) session.pop('agree', None) session.pop('answer_set', None) session.pop('type', None) - + return render_template('quit_task.html', user_id=user_id) -#EOF +# EOF diff --git a/app/utils.py b/app/utils.py index a06c23ceda44af401265805c3b9ac94b0600ba34..a64c872534fec86fd76fe7e9eb037990d3820aa3 100644 --- a/app/utils.py +++ b/app/utils.py @@ -20,7 +20,8 @@ def timeit(method): name = kw.get('log_name', method.__name__.upper()) kw['log_time'][name] = int((te - ts) * 1000) else: - app.logger.info('{} {:2.2f} ms'.format(method.__name__, (te - ts) * 1000)) + app.logger.info('{} {:2.2f} ms'.format( + method.__name__, (te - ts) * 1000)) return result return timed @@ -106,42 +107,6 @@ def map_answers_to_questions(answers, questions): return results - ''' - return list(map( - lambda x: get_values_from_list_of_answers(x, answers), - questions)) - ''' - - -''' -select sub.answer_set_idanswer_set, group_concat(concat( - COALESCE(sub.aa, ''), - COALESCE(sub.ab, ''), - COALESCE(sub.ba, ''), - COALESCE(sub.bb, ''), - COALESCE(sub.ca, ''), - COALESCE(sub.cb, '') -)) -FROM ( - select *, - case when page_idpage = 4 and question_idquestion = 1 then answer end as aa, - case when page_idpage = 4 and question_idquestion = 2 then answer end as ab, - case when page_idpage = 5 and question_idquestion = 1 then answer end as ba, - case when page_idpage = 5 and question_idquestion = 2 then answer end as bb, - case when page_idpage = 6 and question_idquestion = 1 then answer end as ca, - case when page_idpage = 6 and question_idquestion = 2 then answer end as cb - from answer where answer_set_idanswer_set in ( select idanswer_set from answer_set where experiment_idexperiment = 2 and answer_counter != 0 ) -) as sub -group by sub.answer_set_idanswer_set; - - - - -# all possible page/question comobs -select distinct p.idpage, q.idquestion from question q join page p on p.experiment_idexperiment=q.experiment_idexperiment where p.experiment_idexperiment = 2 order by p.idpage,q.idquestion; -''' - - @timeit def generate_csv(exp_id): @@ -289,9 +254,10 @@ def generate_answer_row(participant, pages, questions, embody_questions): for point in coordinates: try: - # for every brush stroke, increment the pixel + # for every brush stroke, increment the pixel # value for every brush stroke - coordinates_to_bitmap[int(point[0])][int(point[1])] += 0.1 + coordinates_to_bitmap[int( + point[0])][int(point[1])] += 0.1 except IndexError: continue diff --git a/config.py b/config.py index 632122a826069dbc4e2203de761d258a5c66a275..5e2e9071ca7bd9ac922d27e9d27f89c06f87a3d2 100644 --- a/config.py +++ b/config.py @@ -1,25 +1,11 @@ from decouple import config -import os -basedir = os.path.abspath(os.path.dirname(__file__)) class Config(object): - # seret key is set in __ini__.py - #SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess' - LANGUAGES = ['en', 'fi', 'fa', 'el', 'it', 'zh'] - """ - #SQLITE3 connection settings: - - SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \ - 'sqlite:///' + os.path.join(basedir, 'app.db') - SQLALCHEMY_TRACK_MODIFICATIONS = False - """ - # MariaDB mysql database settings - MYSQL_USER = config('MYSQL_USER') MYSQL_PASSWORD = config('MYSQL_PASSWORD') MYSQL_SERVER = config('MYSQL_SERVER') diff --git a/dump.sql b/dump.sql index 4daea503fb562eed99c76049742c6a132bf25625..e6179233ac44d21e874f676c191d8beb170a213b 100644 --- a/dump.sql +++ b/dump.sql @@ -29,7 +29,6 @@ CREATE TABLE user ( password_hash VARCHAR(128), PRIMARY KEY (id) ); -INSERT INTO user VALUES(1,'timo',NULL,'pbkdf2:sha256:50000$sctKb5R4$688ff9fd63df4a0883b9eb003b6738c6b7baa2010e1cd503c678b43c881c07bf'); CREATE TABLE answer_set ( idanswer_set INTEGER NOT NULL, experiment_idexperiment INTEGER, diff --git a/embody_plot.py b/embody_plot.py index f540d77fafee5a5fbdf446d50d2732bc08b4be4d..da51ab8c63d5e33c2d511d105a93aa8cada68d87 100644 --- a/embody_plot.py +++ b/embody_plot.py @@ -5,27 +5,17 @@ Visualize emBODY data This python script is based on matlab code found from: https://version.aalto.fi/gitlab/eglerean/embody/tree/master/matlab - - -Requirements: - - python 3+ - - matplotlib - - numpy - - scipy - -Run: -python embody_plot.py - """ -import sys +from config import Config +from app import socketio, app +from flask_socketio import emit +import matplotlib.image as mpimg +import matplotlib.pyplot as plt import time import datetime import json -import resource import mysql.connector as mariadb -import io -import urllib, base64 import argparse import numpy as np @@ -34,15 +24,6 @@ import scipy.ndimage as ndimage import matplotlib matplotlib.use('agg') -import matplotlib.pyplot as plt -import matplotlib.image as mpimg -from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas -from matplotlib.figure import Figure - -from flask_socketio import emit -from app import socketio, app -from config import Config - # Hard coded image size for default embody image WIDTH = 207 @@ -54,7 +35,7 @@ IMAGE_PATH_MASK = './app/static/img/dummy_600_mask.png' STATIC_PATH = './app/static/embody_drawings/' # Interpolation methods -METHODS = ['none','bilinear', 'bicubic', 'gaussian'] +METHODS = ['none', 'bilinear', 'bicubic', 'gaussian'] # SELECT methods SELECT_ALL = ("SELECT coordinates from embody_answer") @@ -72,10 +53,10 @@ class MyDB(object): def __init__(self): self._db_connection = mariadb.connect( - user = Config.MYSQL_USER, - password = Config.MYSQL_PASSWORD, - database = Config.MYSQL_DB - ) + user=Config.MYSQL_USER, + password=Config.MYSQL_PASSWORD, + database=Config.MYSQL_DB + ) self._db_cur = self._db_connection.cursor() def query(self, query, params): @@ -85,22 +66,22 @@ class MyDB(object): self._db_connection.close() -def matlab_style_gauss2D(shape=(1,1),sigma=5): +def matlab_style_gauss2D(shape=(1, 1), sigma=5): """2D gaussian mask - should give the same result as MATLAB's fspecial('gaussian',[shape],[sigma])""" - m,n = [(ss-1.)/2. for ss in shape] - y,x = np.ogrid[-m:m+1,-n:n+1] - h = np.exp( -(x*x + y*y) / (2.*sigma*sigma) ) - h[ h < np.finfo(h.dtype).eps*h.max() ] = 0 + m, n = [(ss-1.)/2. for ss in shape] + y, x = np.ogrid[-m:m+1, -n:n+1] + h = np.exp(-(x*x + y*y) / (2.*sigma*sigma)) + h[h < np.finfo(h.dtype).eps*h.max()] = 0 sumh = h.sum() if sumh != 0: h /= sumh return h -def map_coordinates(a,b,c=None): - return [a,b,c] +def map_coordinates(a, b, c=None): + return [a, b, c] def timeit(method): @@ -113,7 +94,7 @@ def timeit(method): name = kw.get('log_name', method.__name__.upper()) kw['log_time'][name] = int((te - ts) * 1000) else: - print('%r %2.2f ms' % \ + print('%r %2.2f ms' % (method.__name__, (te - ts) * 1000)) return result @@ -127,14 +108,15 @@ def get_coordinates(idpage, idembody=None, select_clause=SELECT_BY_PAGE_AND_PICT # init db db = MyDB() - db.query(select_clause, (idpage,idembody)) + db.query(select_clause, (idpage, idembody)) # Get coordinates coordinates = format_coordinates(db._db_cur) if idembody: # Get image path - image_query = db.query('SELECT picture from embody_question where idembody=%s', (idembody,)) + image_query = db.query( + 'SELECT picture from embody_question where idembody=%s', (idembody,)) image_path = db._db_cur.fetchone()[0] image_path = './app' + image_path @@ -146,7 +128,7 @@ def get_coordinates(idpage, idembody=None, select_clause=SELECT_BY_PAGE_AND_PICT # close db connection db.__del__() - # Save image to ./app/static/ + # Save image to ./app/static/ img_filename = 'PAGE-' + str(idpage) + '-' + DATE_STRING + '.png' plt.savefig(STATIC_PATH + img_filename) @@ -156,10 +138,10 @@ def get_coordinates(idpage, idembody=None, select_clause=SELECT_BY_PAGE_AND_PICT def format_coordinates(cursor): # Init coordinate arrays and radius of point - x=[] - y=[] - r=[] - standard_radius=13 + x = [] + y = [] + r = [] + standard_radius = 13 # Loop through all of the saved coordinates and push them to coordinates arrays for coordinate in cursor: @@ -170,7 +152,8 @@ def format_coordinates(cursor): y.extend(coordinates['y']) r.extend(coordinates['r']) except KeyError: - standard_radiuses = np.full((1, len(coordinates['x'])), standard_radius).tolist()[0] + standard_radiuses = np.full( + (1, len(coordinates['x'])), standard_radius).tolist()[0] r.extend(standard_radiuses) continue except ValueError as err: @@ -178,16 +161,16 @@ def format_coordinates(cursor): continue return { - "x":x, - "y":y, - "coordinates":list(map(map_coordinates, x,y,r)) + "x": x, + "y": y, + "coordinates": list(map(map_coordinates, x, y, r)) } def plot_coordinates(coordinates, image_path=DEFAULT_IMAGE_PATH): # Total amount of points - points_count = len(coordinates['coordinates']) + points_count = len(coordinates['coordinates']) step = 1 # Load image to a plot @@ -197,16 +180,15 @@ def plot_coordinates(coordinates, image_path=DEFAULT_IMAGE_PATH): # Init plots fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2) - # Draw circles from coordinates (imshow don't need interpolation) # TODO: set sigma according to brush size! 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)) + frame = np.zeros((image_data[0] + 10, image_data[1] + 10)) if image_path == DEFAULT_IMAGE_PATH: - #app.logger.info(coordinates) + # app.logger.info(coordinates) for idx, point in enumerate(coordinates["coordinates"]): @@ -242,7 +224,7 @@ def plot_coordinates(coordinates, image_path=DEFAULT_IMAGE_PATH): # Plot coordinates as points ax1.set_title("raw points") - ax1.plot(coordinates["x"],coordinates["y"], 'ro', alpha=0.2) + ax1.plot(coordinates["x"], coordinates["y"], 'ro', alpha=0.2) ax1.imshow(image, alpha=0.6) app.logger.info("image plotted") @@ -250,27 +232,19 @@ def plot_coordinates(coordinates, image_path=DEFAULT_IMAGE_PATH): # 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') + +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] @@ -282,7 +256,3 @@ if __name__=='__main__': get_coordinates(value, None, SELECT_BY_EXP_ID) else: print("No arguments given. Exit.") - sys.exit(0) - - - diff --git a/migrations/README b/migrations/README deleted file mode 100644 index 98e4f9c44effe479ed38c66ba922e7bcc672916f..0000000000000000000000000000000000000000 --- a/migrations/README +++ /dev/null @@ -1 +0,0 @@ -Generic single-database configuration. \ No newline at end of file diff --git a/migrations/alembic.ini b/migrations/alembic.ini deleted file mode 100644 index f8ed4801f78bcb83cc6acb589508c1b24eda297a..0000000000000000000000000000000000000000 --- a/migrations/alembic.ini +++ /dev/null @@ -1,45 +0,0 @@ -# A generic, single database configuration. - -[alembic] -# template used to generate migration files -# file_template = %%(rev)s_%%(slug)s - -# set to 'true' to run the environment during -# the 'revision' command, regardless of autogenerate -# revision_environment = false - - -# Logging configuration -[loggers] -keys = root,sqlalchemy,alembic - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = WARN -handlers = console -qualname = - -[logger_sqlalchemy] -level = WARN -handlers = -qualname = sqlalchemy.engine - -[logger_alembic] -level = INFO -handlers = -qualname = alembic - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(levelname)-5.5s [%(name)s] %(message)s -datefmt = %H:%M:%S diff --git a/migrations/env.py b/migrations/env.py deleted file mode 100644 index 23663ff2f54e6c4425953537976b175246c8a9e6..0000000000000000000000000000000000000000 --- a/migrations/env.py +++ /dev/null @@ -1,87 +0,0 @@ -from __future__ import with_statement -from alembic import context -from sqlalchemy import engine_from_config, pool -from logging.config import fileConfig -import logging - -# this is the Alembic Config object, which provides -# access to the values within the .ini file in use. -config = context.config - -# Interpret the config file for Python logging. -# This line sets up loggers basically. -fileConfig(config.config_file_name) -logger = logging.getLogger('alembic.env') - -# add your model's MetaData object here -# for 'autogenerate' support -# from myapp import mymodel -# target_metadata = mymodel.Base.metadata -from flask import current_app -config.set_main_option('sqlalchemy.url', - current_app.config.get('SQLALCHEMY_DATABASE_URI')) -target_metadata = current_app.extensions['migrate'].db.metadata - -# other values from the config, defined by the needs of env.py, -# can be acquired: -# my_important_option = config.get_main_option("my_important_option") -# ... etc. - - -def run_migrations_offline(): - """Run migrations in 'offline' mode. - - This configures the context with just a URL - and not an Engine, though an Engine is acceptable - here as well. By skipping the Engine creation - we don't even need a DBAPI to be available. - - Calls to context.execute() here emit the given string to the - script output. - - """ - url = config.get_main_option("sqlalchemy.url") - context.configure(url=url) - - with context.begin_transaction(): - context.run_migrations() - - -def run_migrations_online(): - """Run migrations in 'online' mode. - - In this scenario we need to create an Engine - and associate a connection with the context. - - """ - - # this callback is used to prevent an auto-migration from being generated - # when there are no changes to the schema - # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html - def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, 'autogenerate', False): - script = directives[0] - if script.upgrade_ops.is_empty(): - directives[:] = [] - logger.info('No changes in schema detected.') - - engine = engine_from_config(config.get_section(config.config_ini_section), - prefix='sqlalchemy.', - poolclass=pool.NullPool) - - connection = engine.connect() - context.configure(connection=connection, - target_metadata=target_metadata, - process_revision_directives=process_revision_directives, - **current_app.extensions['migrate'].configure_args) - - try: - with context.begin_transaction(): - context.run_migrations() - finally: - connection.close() - -if context.is_offline_mode(): - run_migrations_offline() -else: - run_migrations_online() diff --git a/migrations/script.py.mako b/migrations/script.py.mako deleted file mode 100644 index 2c0156303a8df3ffdc9de87765bf801bf6bea4a5..0000000000000000000000000000000000000000 --- a/migrations/script.py.mako +++ /dev/null @@ -1,24 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -# revision identifiers, used by Alembic. -revision = ${repr(up_revision)} -down_revision = ${repr(down_revision)} -branch_labels = ${repr(branch_labels)} -depends_on = ${repr(depends_on)} - - -def upgrade(): - ${upgrades if upgrades else "pass"} - - -def downgrade(): - ${downgrades if downgrades else "pass"} diff --git a/migrations/versions/aea4a0f982b4_.py b/migrations/versions/aea4a0f982b4_.py deleted file mode 100644 index c42c4389f507d6255537a48a6875fe85f9b3c7e9..0000000000000000000000000000000000000000 --- a/migrations/versions/aea4a0f982b4_.py +++ /dev/null @@ -1,168 +0,0 @@ -"""empty message - -Revision ID: aea4a0f982b4 -Revises: -Create Date: 2018-11-28 17:07:11.577139 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = 'aea4a0f982b4' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('background_question', - sa.Column('idbackground_question', sa.Integer(), nullable=False), - sa.Column('background_question', sa.String(length=120), nullable=True), - sa.Column('experiment_idexperiment', sa.Integer(), nullable=True), - sa.PrimaryKeyConstraint('idbackground_question') - ) - op.create_table('experiment', - sa.Column('idexperiment', sa.Integer(), nullable=False), - sa.Column('name', sa.String(length=120), nullable=True), - sa.Column('instruction', sa.Text(), nullable=True), - sa.Column('directoryname', sa.String(length=120), nullable=True), - sa.Column('language', sa.String(length=120), nullable=True), - sa.Column('status', sa.String(length=120), nullable=True), - sa.Column('randomization', sa.String(length=120), nullable=True), - sa.Column('short_instruction', sa.Text(), nullable=True), - sa.Column('single_sentence_instruction', sa.Text(), nullable=True), - sa.Column('is_archived', sa.String(length=120), nullable=True), - sa.Column('creator_name', sa.String(length=120), nullable=True), - sa.Column('research_notification_filename', sa.String(length=120), nullable=True), - sa.Column('creation_time', sa.DateTime(), nullable=True), - sa.Column('stimulus_size', sa.String(length=120), nullable=True), - sa.Column('consent_text', sa.Text(), nullable=True), - sa.Column('use_forced_id', sa.String(length=120), nullable=True), - sa.PrimaryKeyConstraint('idexperiment') - ) - op.create_index(op.f('ix_experiment_consent_text'), 'experiment', ['consent_text'], unique=False) - op.create_index(op.f('ix_experiment_creation_time'), 'experiment', ['creation_time'], unique=False) - op.create_index(op.f('ix_experiment_directoryname'), 'experiment', ['directoryname'], unique=True) - op.create_index(op.f('ix_experiment_instruction'), 'experiment', ['instruction'], unique=False) - op.create_index(op.f('ix_experiment_name'), 'experiment', ['name'], unique=False) - op.create_index(op.f('ix_experiment_short_instruction'), 'experiment', ['short_instruction'], unique=False) - op.create_index(op.f('ix_experiment_single_sentence_instruction'), 'experiment', ['single_sentence_instruction'], unique=False) - op.create_table('trial_randomization', - sa.Column('idtrial_randomization', sa.Integer(), nullable=False), - sa.Column('page_idpage', sa.Integer(), nullable=True), - sa.Column('randomized_idpage', sa.Integer(), nullable=True), - sa.Column('answer_set_idanswer_set', sa.Integer(), nullable=True), - sa.Column('experiment_idexperiment', sa.Integer(), nullable=True), - sa.PrimaryKeyConstraint('idtrial_randomization') - ) - op.create_table('user', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('username', sa.String(length=64), nullable=True), - sa.Column('email', sa.String(length=120), nullable=True), - sa.Column('password_hash', sa.String(length=128), nullable=True), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_user_email'), 'user', ['email'], unique=True) - op.create_index(op.f('ix_user_username'), 'user', ['username'], unique=True) - op.create_table('answer_set', - sa.Column('idanswer_set', sa.Integer(), nullable=False), - sa.Column('experiment_idexperiment', sa.Integer(), nullable=True), - sa.Column('session', sa.String(length=120), nullable=True), - sa.Column('agreement', sa.String(length=120), nullable=True), - sa.Column('answer_counter', sa.Integer(), nullable=True), - sa.Column('registration_time', sa.DateTime(), nullable=True), - sa.Column('last_answer_time', sa.DateTime(), nullable=True), - sa.ForeignKeyConstraint(['experiment_idexperiment'], ['experiment.idexperiment'], ), - sa.PrimaryKeyConstraint('idanswer_set') - ) - op.create_index(op.f('ix_answer_set_last_answer_time'), 'answer_set', ['last_answer_time'], unique=False) - op.create_index(op.f('ix_answer_set_registration_time'), 'answer_set', ['registration_time'], unique=False) - op.create_table('background_question_option', - sa.Column('idbackground_question_option', sa.Integer(), nullable=False), - sa.Column('background_question_idbackground_question', sa.Integer(), nullable=True), - sa.Column('option', sa.String(length=120), nullable=True), - sa.ForeignKeyConstraint(['background_question_idbackground_question'], ['background_question.idbackground_question'], ), - sa.PrimaryKeyConstraint('idbackground_question_option') - ) - op.create_table('forced_id', - sa.Column('idforced_id', sa.Integer(), nullable=False), - sa.Column('experiment_idexperiment', sa.Integer(), nullable=True), - sa.Column('pregenerated_id', sa.String(length=120), nullable=True), - sa.ForeignKeyConstraint(['experiment_idexperiment'], ['experiment.idexperiment'], ), - sa.PrimaryKeyConstraint('idforced_id') - ) - op.create_table('page', - sa.Column('idpage', sa.Integer(), nullable=False), - sa.Column('experiment_idexperiment', sa.Integer(), nullable=True), - sa.Column('type', sa.String(length=120), nullable=True), - sa.Column('text', sa.String(length=120), nullable=True), - sa.Column('media', sa.String(length=120), nullable=True), - sa.ForeignKeyConstraint(['experiment_idexperiment'], ['experiment.idexperiment'], ), - sa.PrimaryKeyConstraint('idpage') - ) - op.create_index(op.f('ix_page_media'), 'page', ['media'], unique=False) - op.create_index(op.f('ix_page_text'), 'page', ['text'], unique=False) - op.create_index(op.f('ix_page_type'), 'page', ['type'], unique=False) - op.create_table('question', - sa.Column('idquestion', sa.Integer(), nullable=False), - sa.Column('experiment_idexperiment', sa.Integer(), nullable=True), - sa.Column('question', sa.String(length=120), nullable=True), - sa.Column('left', sa.String(length=120), nullable=True), - sa.Column('right', sa.String(length=120), nullable=True), - sa.ForeignKeyConstraint(['experiment_idexperiment'], ['experiment.idexperiment'], ), - sa.PrimaryKeyConstraint('idquestion') - ) - op.create_table('answer', - sa.Column('idanswer', sa.Integer(), nullable=False), - sa.Column('question_idquestion', sa.Integer(), nullable=True), - sa.Column('answer_set_idanswer_set', sa.Integer(), nullable=True), - sa.Column('answer', sa.String(length=120), nullable=True), - sa.Column('page_idpage', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['answer_set_idanswer_set'], ['answer_set.idanswer_set'], ), - sa.ForeignKeyConstraint(['page_idpage'], ['page.idpage'], ), - sa.ForeignKeyConstraint(['question_idquestion'], ['question.idquestion'], ), - sa.PrimaryKeyConstraint('idanswer') - ) - op.create_table('background_question_answer', - sa.Column('idbackground_question_answer', sa.Integer(), nullable=False), - sa.Column('answer_set_idanswer_set', sa.Integer(), nullable=True), - sa.Column('answer', sa.String(length=120), nullable=True), - sa.Column('background_question_idbackground_question', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['answer_set_idanswer_set'], ['answer_set.idanswer_set'], ), - sa.ForeignKeyConstraint(['background_question_idbackground_question'], ['background_question.idbackground_question'], ), - sa.PrimaryKeyConstraint('idbackground_question_answer') - ) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('background_question_answer') - op.drop_table('answer') - op.drop_table('question') - op.drop_index(op.f('ix_page_type'), table_name='page') - op.drop_index(op.f('ix_page_text'), table_name='page') - op.drop_index(op.f('ix_page_media'), table_name='page') - op.drop_table('page') - op.drop_table('forced_id') - op.drop_table('background_question_option') - op.drop_index(op.f('ix_answer_set_registration_time'), table_name='answer_set') - op.drop_index(op.f('ix_answer_set_last_answer_time'), table_name='answer_set') - op.drop_table('answer_set') - op.drop_index(op.f('ix_user_username'), table_name='user') - op.drop_index(op.f('ix_user_email'), table_name='user') - op.drop_table('user') - op.drop_table('trial_randomization') - op.drop_index(op.f('ix_experiment_single_sentence_instruction'), table_name='experiment') - op.drop_index(op.f('ix_experiment_short_instruction'), table_name='experiment') - op.drop_index(op.f('ix_experiment_name'), table_name='experiment') - op.drop_index(op.f('ix_experiment_instruction'), table_name='experiment') - op.drop_index(op.f('ix_experiment_directoryname'), table_name='experiment') - op.drop_index(op.f('ix_experiment_creation_time'), table_name='experiment') - op.drop_index(op.f('ix_experiment_consent_text'), table_name='experiment') - op.drop_table('experiment') - op.drop_table('background_question') - # ### end Alembic commands ### diff --git a/plot_image.py b/plot_image.py index bc723397bcdf5b66a8bd2b2adb96da1cdbd9c2a9..d1f1813828d825dbda39028bdef366a54ae084b0 100644 --- a/plot_image.py +++ b/plot_image.py @@ -22,12 +22,10 @@ in onni.utu.fu) to the same path as the script. ''' import copy - import numpy as np import matplotlib.pyplot as plt import csv import sys -import json csv.field_size_limit(sys.maxsize) @@ -56,8 +54,7 @@ def show_images(images, cols=1, titles=None): # get a copy of the gray color map my_cmap = copy.copy(plt.cm.get_cmap('gray')) # set how the colormap handles 'bad' values - my_cmap.set_bad(alpha=0) - + my_cmap.set_bad(alpha=0) assert((titles is None) or (len(images) == len(titles))) n_images = len(images) diff --git a/run.py b/run.py index 60d5d24ad98b96670253971441f1c8b3433961a5..4989040691fa54f6f71984379ed7bcd25efe6e75 100644 --- a/run.py +++ b/run.py @@ -1,7 +1,5 @@ +import os from app import app - - -# Setup logging import logging from logging.handlers import RotatingFileHandler from logging import Formatter @@ -14,7 +12,7 @@ logging.basicConfig( filename=app.config.get('LOG_FILENAME', 'logs/flask.log'), level=logging.DEBUG, datefmt="%Y-%m-%d %H:%M:%S", - format = format + format=format ) logging.info( @@ -31,7 +29,6 @@ handler.setFormatter( app.logger.addHandler(handler) # Logging for production (nginx + gunicorn) -import os is_gunicorn = "gunicorn" in os.environ.get("SERVER_SOFTWARE", "") if is_gunicorn: app.logger.info("Application run through gunicorn") @@ -44,6 +41,3 @@ else: log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) ''' - -# EOF -