def remove_slider():
    """
    Remove a slider from the user page.
    :return: Redirects to researcher.config
    """
    check_access_right(forbidden='user', redirect_url='control.index')

    slider_name = request.args.get('slider_name')

    removed = False

    with open(current_app.input_fields, 'r') as f:
        lines = f.readlines()
    with open(current_app.input_fields, 'w') as f:
        for line in lines:
            if (line[-len(slider_name):] != slider_name) and (
                    line[-len(slider_name) - 1:] != slider_name + '\n'):
                f.write(line)
            else:
                removed = True

    if removed:
        flash('Slider "' + slider_name + '" has been removed.')
    else:
        flash('Slider "' + slider_name + '" does not exist. Nothing removed.')

    return redirect(url_for('researcher.config'))
def remove_video():
    """
    Remove a video from the available videos.
    :return: Redirects to researcher.config
    """
    check_access_right(forbidden='user', redirect_url='control.index')

    vid_id = request.args.get('vid_id')
    vid_name = request.args.get('vid_name')

    removed = False

    with open(current_app.vid_file, 'r') as f:
        lines = f.readlines()
    with open(current_app.vid_file, 'w') as f:
        for line in lines:
            if vid_id not in line:
                f.write(line)
            else:
                removed = True

    if removed:
        flash('Video "' + vid_name + '" has been removed.')
    else:
        flash('Video "' + vid_name + '" not found. Nothing removed.')

    return redirect(url_for('researcher.config'))
Beispiel #3
0
def config():
    """
    Display the configuarion page, where the user can add or remove videos or
    change the database this is connected to.
    :return: Renders the website
    """
    check_access_right(forbidden='user', redirect_url='control.index')

    vid_dict, _ = get_videos()

    field_list = get_input_fields()

    oneDsliders = [x for x in field_list if x[0] == 'slider']
    twoDsliders = [x for x in field_list if x[0] == '2dslider']

    with open(current_app.user_instructions_file, 'r') as f:
        instructions = f.read()

    return render_template("researcher/config.html",
                           vid_dict=vid_dict,
                           dbs=current_app.dbs,
                           cur_db=current_app.config['DB'],
                           instructions=instructions,
                           oneDsliders=oneDsliders,
                           twoDsliders=twoDsliders)
def add_video():
    """
    Add a new video to the list of available videos.
    :return: Redirects to researcher.config.
    """
    check_access_right(forbidden='user', redirect_url='control.index')

    vid_id = request.form.get('vid_id')
    vid_name = request.form.get('vid_name')

    if (not vid_id) or (not vid_name):
        flash("You need to provide a video ID (or its URL) and video name in "
              "order to add a video")
    else:
        if not vid_id.isdigit():
            # If the whole video url is given
            vid_id = vid_id.split('/')[-1]
            if not vid_id.isdigit():
                flash('Error, the URL seems to have the wrong format. It '
                      'should end in a number, like for example '
                      '"https://vimeo.com/65107797"')
                return (redirect(url_for('researcher.config')))
        with open(current_app.vid_file, 'a') as f:
            f.write('\n' + vid_id + ':' + vid_name)
        flash('Video "' + vid_name + '" was successfully added.')

    return redirect(url_for('researcher.config'))
def export_all():
    """
    Export all the data stored in MongoDB to a file

    Operation is not allowed for role user.
    :return:
    """
    check_access_right(forbidden='user', redirect_url='control.index')

    b, data = collect_mongodbobjects()
    if b:
        bytes_buffer = BytesIO()
        with StringIO() as str_buffer:
            data.to_csv(str_buffer, index=False)
            str_buffer.seek(0)
            bytes_buffer.write(str_buffer.getvalue().encode('utf-8'))
        bytes_buffer.seek(0)
        filename = 'video_annotations_{date:%Y-%m-%d_%H-%M-%S}.csv'.format(
            date=datetime.datetime.now())
        return send_file(bytes_buffer,
                         as_attachment=True,
                         attachment_filename=filename,
                         mimetype='text/csv')
    else:
        flash('No data to export!')
        return render_template('control/data.html', data='', headers='')
Beispiel #6
0
def user():
    """
    Display the main user page.
    [The videos that can be accessed have to be defined with name and vimeo
    ID in a dictionary here.]

    This is not accessible for somebody with the role researcher.
    :return: Main webpage
    """
    # videos = {'Omelette':'65107797', 'Happiness':'28374299'}

    check_access_right(forbidden='researcher', redirect_url='control.index')

    currentVideo, vid_dict, _ = get_video_information(
        cur_vid_id=request.args.get('vid'))

    field_list = get_input_fields()

    oneDsliders = [x for x in field_list if x[0]=='slider']
    twoDsliders = [x for x in field_list if x[0]=='2dslider']

    if len(oneDsliders) > 2:
        oneDsliders = oneDsliders[:2]
        flash('Currently, at most two one-dimensional sliders are supported.')
    if len(twoDsliders) > 1:
        twoDsliders = twoDsliders[:1]
        flash('Currently, only one (or zero) two-dimensional sliders are '
              'supported.')

    return render_template('user/user.html', vid_dict=vid_dict,
                           currentVideo=currentVideo, oneDsliders=oneDsliders,
                           twoDsliders=twoDsliders)
Beispiel #7
0
def instructions():
    """
    Display the instruction page for the researcher.
    This is not accessible for somebody with the role user.
    :return: User instructions page.

    """
    check_access_right(forbidden='user', redirect_url='user.userinstructions')

    return render_template('researcher/instructions.html')
def delete_all():
    """
    Delete all data that is stored in the MongoDB database.

    Operation is not allowed for role user.
    :return: User feedback string
    """
    check_access_right(forbidden='user', redirect_url='control.index')
    current_app.d.delete_many({})
    current_app.config['CACHE'] = SimpleCache(default_timeout=1e15)
    flash('All data deleted!')
    return redirect(url_for('researcher.data'))
Beispiel #9
0
def userinstructions():
    """
    Display the instruction page for the user, which looks different
    depending on whether the person accessing has the role user or researcher
    :return: User instructions webpage.
    """
    check_access_right(forbidden='', redirect_url='control.index')

    with open(current_app.user_instructions_file, 'r') as f:
        instructions = f.read()

    return render_template('user/userinstructions.html',
                           instructions=instructions)
Beispiel #10
0
def save_user_instructions():
    """
    Let's the researcher change the user instructions.
    :return:
    """

    check_access_right(forbidden='user', redirect_url='control.index')

    instructions = request.form.get('user_instructions')
    with open(current_app.user_instructions_file, 'w') as f:
        f.write(instructions)
        f.close()

    flash('Instructions saved!')
    return redirect(url_for('researcher.config'))
def change_db():
    """
    Change the internal database in config['DB'] according to the database
    provided by the form.
    :return: Redirects to the configuration page for the researcher.
    """
    check_access_right(forbidden='user', redirect_url='control.index')

    new_db = request.form.get('db')
    current_app.config['DB'] = new_db

    current_app.d = DatabaseClient()

    flash('Database changed to "' + current_app.dbs[new_db] + '".')
    current_app.config['CACHE'] = SimpleCache(default_timeout=1e15)
    return redirect(url_for('researcher.config'))
def add_slider():
    """
    Add a slider to the user page.
    :return: Redirects to researcher.config.
    """
    check_access_right(forbidden='user', redirect_url='control.index')

    slider_type = request.form.get('slider_type')

    min_val = request.form.get('min')
    max_val = request.form.get('max')
    def_val = request.form.get('def')
    name = request.form.get('name')
    if (not min_val) or (not max_val) or (not def_val) or (not name):
        flash("You need to provide values to all fields in order to add a "
              "slider!")
        return redirect(url_for('researcher.config'))

    if slider_type == 'slider':
        with open(current_app.input_fields, 'a') as f:
            f.write('\n' + slider_type + ':' + min_val + ':' + max_val + ':' +
                    def_val + ':' + name)
        flash('Slider "' + name + '" was successfully added.')

    elif slider_type == '2dslider':
        min_val2 = request.form.get('min2')
        max_val2 = request.form.get('max2')
        def_val2 = request.form.get('def2')
        name2 = request.form.get('name2')
        if (not min_val2) or (not max_val2) or (not def_val2) or (not name2):
            flash("You need to provide values to all fields in order to add a "
                  "slider!")
            return redirect(url_for('researcher.config'))
        with open(current_app.input_fields, 'a') as f:
            f.write('\n' + slider_type + ':' + min_val + ':' + min_val2 + ':' +
                    max_val + ':' + max_val2 + ':' + def_val + ':' + def_val2 +
                    ':' + name + ':' + name2)
        flash('Slider "' + name + ':' + name2 + '" was successfully added.')

    else:
        flash(
            'Error, slider could not be added. Try reloading the page and trying again.'
        )

    return (redirect(url_for('researcher.config')))
Beispiel #13
0
def data():
    """
    Function to print all data that is stored in the MongoDB database.

    Operation is not allowed for role user.
    :return: Webpage displaying currently stored data
    """
    check_access_right(forbidden='user', redirect_url='control.index')

    b, data = collect_mongodbobjects()
    if b:
        # The names of the data fields:
        headers = list(data)
        # And a list of their contents:
        data_rows = list(data.values)
        return render_template('researcher/data.html',
                               data=data_rows,
                               headers=headers)
    else:
        return render_template('researcher/data.html', data='', headers='')
Beispiel #14
0
def chart():
    """
    Display the web page for the researcher view.

    This webpage is only for the role researcher.
    :return: Researcher view webpage
    """
    check_access_right(forbidden='user', redirect_url='control.index')

    # Get the data:

    currentVideo, vid_dict, _ = get_video_information(
        request.args.get('vid'), request.args.get('cluster'))
    _, data = collect_mongodbobjects(currentVideo[0])

    if _ == False or data.empty:
        return render_template(
            "researcher/chart.html",
            the_div="There are no observations for this video!",
            the_script="",
            vid_dict=vid_dict,
            currentVideo=currentVideo,
            currentVariable='-',
            variable_list=[])

    data, currentVariable, variable_list = extract_variable(
        data, request.args.get('variable'))

    # Group by username and extract timestamps and values for each user
    grouped_data = data.groupby('username')
    data_by_user = [user for _, user in grouped_data]
    ts = [
        np.array(t)
        for t in (data_by_user[i]['timestamp'].apply(lambda x: float(x))
                  for i in range(len(data_by_user)))
    ]
    vals = [
        np.array(val)
        for val in (data_by_user[i][currentVariable].apply(lambda x: float(x))
                    for i in range(len(data_by_user)))
    ]

    vals = [v for v in vals if len(v) > 1]
    ts = [t for t in ts if len(t) > 1]

    # # Make sure all data starts and ends at the same time for each user, if the
    # # data doesn't suggest otherwise start and end value are 50.
    max_ts = [max(t) for t in ts]
    min_ts = [min(t) for t in ts]

    # Create the interpolation
    xs = [
        np.linspace(min_ts[i], max_ts[i], int(max_ts[i] - min_ts[i]))
        for i in range(len(max_ts))
    ]
    interpolators = [PchipInterpolator(t, val) for (t, val) in zip(ts, vals)]
    user_timeseries = [[xs[i], interpolator(xs[i])]
                       for i, interpolator in enumerate(interpolators)]

    # Create the Bokeh plot
    TOOLS = 'save,pan,box_zoom,reset,wheel_zoom,hover'
    p = figure(title="Valence ratings by timestamp",
               y_axis_type="linear",
               plot_height=500,
               tools=TOOLS,
               active_scroll='wheel_zoom',
               plot_width=900)
    p.xaxis.axis_label = 'Timestamp (seconds)'
    p.yaxis.axis_label = 'Valence rating'

    for i, tseries in enumerate(user_timeseries):
        p.line(tseries[0],
               tseries[1],
               line_color=Spectral6[i % 6],
               line_width=1.5,
               name=data_by_user[i]['username'].iloc[0])
    for i in range(len(ts)):
        for j in range(len(ts[i])):
            p.circle(ts[i][j],
                     vals[i][j],
                     fill_color=Spectral6[i % 6],
                     line_color='black',
                     radius=0.5)

    p.select_one(HoverTool).tooltips = [('Time', '@x'), ('Valence', '@y'),
                                        ('User', '$name')]

    script, div = components(p)

    return render_template("researcher/chart.html",
                           the_div=div,
                           the_script=script,
                           vid_dict=vid_dict,
                           currentVideo=currentVideo,
                           variable_list=variable_list,
                           currentVariable=currentVariable)
Beispiel #15
0
def clusters():
    """
        Display correlation plot for the researcher.

        This webpage is only for the role researcher.
        :return: Correlation plot
        """
    check_access_right(forbidden='user', redirect_url='control.index')

    currentVideo, vid_dict, n_clusters = get_video_information(
        request.args.get('vid'), request.args.get('cluster'))
    _, data = collect_mongodbobjects(currentVideo[0])

    ### set desired amount of clusters
    clustervals = np.arange(1, 10, 1)

    if _ == False or data.empty:
        return render_template("researcher/clusters.html",
                               the_div="There is no data for this video!",
                               the_script="",
                               vid_dict=vid_dict,
                               currentVideo=currentVideo,
                               currentCluster=n_clusters,
                               clustervals=clustervals,
                               currentVariable='-',
                               variable_list=[])

    data, currentVariable, variable_list = extract_variable(
        data, request.args.get('variable'))

    interpolators, max_t = get_interpolators(data, currentVariable)
    xs = np.arange(0, int(max_t) + 1.5, 1)

    # Generate data
    user_timeseries = [[interpolator(xs)] for interpolator in interpolators]

    seed = np.random.randint(0, int(1e5), 1)[0]
    np.random.seed(seed)

    # Set cluster count
    # n_clusters = 3
    if n_clusters > np.array(user_timeseries).shape[0]:
        n_clusters = np.array(user_timeseries).shape[0]

    # Euclidean k-means
    km = TimeSeriesKMeans(n_clusters=n_clusters,
                          verbose=True,
                          random_state=seed)
    y_pred = km.fit_predict(user_timeseries)

    # Generate plots and calculate statistics
    all_plots = ""
    all_scripts = ""
    plots = []

    ### TODO MAYBE: intra-cluster correlation with rpy2. Might not work with matrices
    """    valmatrix = np.empty([24,151])
    for iii in range(24):
        valmatrix[iii, :] = user_timeseries[iii][0]
    print(type(valmatrix), valmatrix.shape)
    print(type(valmatrix[0]), len(valmatrix[0]))
    print(type(valmatrix[0][0]))
    r_icc = importr("ICC", lib_loc="C:/Users/Lauri Lode/Documents/R/win-library/3.4")
    #m = r.matrix(FloatVector(valmatrix.flatten()), nrow=24)
    df = DataFrame({"groups": IntVector(y_pred),
        "values": FloatVector(valmatrix.flatten())})
    icc_res = r_icc.ICCbare("groups", "values", data=df)
    icc_val = icc_res[0]
    print("ICC" + str(icc_val))"""

    for yi in range(n_clusters):
        p = figure()
        n = 0
        values = km.cluster_centers_[yi].ravel()
        centerMean = np.mean(km.cluster_centers_[yi].ravel())
        varsum = 0
        for xx in range(0, len(y_pred)):
            if y_pred[xx] == yi:
                n = n + 1
                for iii in range(len(user_timeseries[xx][0])):
                    varsum = varsum + eucl(user_timeseries[xx][0][iii],
                                           values[iii]) / len(
                                               user_timeseries[xx][0])

                p.line(range(0, len(user_timeseries[xx][0])),
                       user_timeseries[xx][0],
                       line_width=0.3)
        varsum = np.sqrt(varsum)

        titleString = "C#" + str(yi + 1) + ", n: " + str(n) + ", μ: " + str(
            np.round(centerMean, decimals=3)) + ", σ: " + str(
                np.round(varsum, decimals=3)) + ", σ²: " + str(
                    np.round(varsum**2, decimals=3))
        t = Title()
        t.text = titleString
        p.title = t
        p.line(range(0, len(values)), values, line_width=2)
        plots.append(p)

    # Get plot codes
    script, div = components(
        gridplot(plots, ncols=3, plot_width=350, plot_height=300))

    return render_template("researcher/clusters.html",
                           the_div=div,
                           the_script=script,
                           vid_dict=vid_dict,
                           currentVideo=currentVideo,
                           currentCluster=n_clusters,
                           clustervals=clustervals,
                           variable_list=variable_list,
                           currentVariable=currentVariable)