import os
import collections
import itertools
import concurrent.futures
import numpy as np
import matplotlib.pyplot as plt
from utils import utils, video, movement, data, beacons, clustering
%matplotlib inline
The mean distance each participant did at different blocks (normalized by the length of the block, so actually its the mean participant speed in meters / second).
dists_futures = {}
with concurrent.futures.ProcessPoolExecutor() as executor:
for group, block in itertools.product(['A', 'B'], [1, 2, 3]):
dists_futures[(group, block)] = executor.submit(movement.distance, group, block)
# extracting the values from the futures
dists = {k: v.result() for k, v in dists_futures.items()}
utils.two_groups_three_bars(dists, ylim=[0, 0.5], ylabel='Mean velocity')
data.save_to_graphics('analyze-movement')
A/1 -- mean: 0.258, stderr: 0.0354 A/2 -- mean: 0.278, stderr: 0.0434 A/3 -- mean: 0.37, stderr: 0.0277 B/1 -- mean: 0.269, stderr: 0.0478 B/2 -- mean: 0.176, stderr: 0.0252 B/3 -- mean: 0.206, stderr: 0.051
No difference between groups in the first block:
utils.independent_one_sided_ttest_summary(dists[('A', 1)], dists[('B', 1)])
mean (a vs b): 0.258 0.269 stderr (a vs b): 0.035 0.048 t: -0.1848587720687531 p: 0.42760769582198077 df: 21
data.save_to_cooked(dists, 'movement')
Calculate for each participant the percentage of the time he / she stayed at the bench area (for every block). Apply t-tests.
bench_pos = data.get_bench()
bench_radius = video.BENCH_RADIUS
dist_func = utils.euclidean_distance
def at_the_bench(point):
'''Returns a boolean indicates if the point is in the bench radius or not.'''
return dist_func(point, bench_pos) <= bench_radius
def at_the_bench_percentage(group, block):
'''Returns a list of percentages (value for each participant) of time at the bench.'''
d = data.participants_data(group, block)
return d.apply(utils.divide_apply_unpack, axis=1, args=(at_the_bench, 2)).mean(axis=0)
percentages = {}
with concurrent.futures.ProcessPoolExecutor() as executor:
for group, block in itertools.product(['A', 'B'], [1, 2, 3]):
percentages[(group, block)] = executor.submit(at_the_bench_percentage, group, block)
# extracting the values from the futures
percentages = {k: v.result() for k, v in percentages.items()}
utils.two_groups_three_bars(percentages, ylim=[0, 0.7])
A/1 -- mean: 0.204, stderr: 0.0514 A/2 -- mean: 0.291, stderr: 0.0756 A/3 -- mean: 0.0093, stderr: 0.00509 B/1 -- mean: 0.0806, stderr: 0.0461 B/2 -- mean: 0.21, stderr: 0.0306 B/3 -- mean: 0.383, stderr: 0.112
data.save_to_cooked(percentages, 'sitting_on_the_bench')
Expectancy of the number of participants arround a beacon, excluding beacons with 0 participants around.
close_to = {}
with concurrent.futures.ProcessPoolExecutor() as executor:
for group, block in itertools.product(['A', 'B'], range(1, 4)):
close_to[(group, block)] = executor.submit(beacons.close_to_beacon, group, block)
# extract the futures results
for key, val in close_to.items():
close_to[key] = val.result()
# calculate vectors of column means (excluding beacons with 0 participants around them)
close_to_vecs = {}
for key, mat in close_to.items():
# calculate the mean of all the cells with positive numbers
# (do not include beacons with 0 close participants to the mean)
close_to_vecs[key] = np.array([col[col > 0].mean() for col in mat.transpose()])
/usr/lib/python3/dist-packages/numpy/core/_methods.py:55: RuntimeWarning: Mean of empty slice. warnings.warn("Mean of empty slice.", RuntimeWarning)
utils.two_groups_three_bars(close_to_vecs,
title='Expectancy of participants close to a beacon',
ylabel='Participants')
data.save_to_graphics('analyze-expectancy_of_participants_close_to_a_beacon')
A/1 -- mean: 1.64, stderr: 0.207 A/2 -- mean: 1.63, stderr: 0.151 A/3 -- mean: 1.84, stderr: 0.156 B/1 -- mean: 1.77, stderr: 0.0714 B/2 -- mean: 2.5, stderr: 0.146 B/3 -- mean: 2.15, stderr: 0.187
utils.independent_one_sided_ttest_summary(close_to_vecs[('A', 1)], close_to_vecs[('B', 1)])
mean (a vs b): 1.639 1.775 stderr (a vs b): 0.207 0.071 t: -0.5655034231641781 p: 0.29583467952978815 df: 10
0.29583467952978815 / 2
0.14791733976489407
data.save_to_cooked(close_to_vecs, 'expectancy_of_participants_close_to_a_beacon')
Cluster (with MeanShift) every frame in the video and score by:
Algorithm score: the mean of the distances of each participant from his centroid. Consider normalizing by the distances between the centroids.
Social score: The mean of the social score each participant gave to each other participant in his cluster.
Generate graphs over time of the above data.
part_clusters = {}
with concurrent.futures.ProcessPoolExecutor() as executor:
for group, block in itertools.product(['A', 'B'], [1, 2, 3]):
part_clusters[(group, block)] = executor.submit(clustering.participants_clustering, group, block)
# extract the futures results
for key, val in part_clusters.items():
part_clusters[key] = val.result()
part_scores = collections.defaultdict(dict)
with concurrent.futures.ProcessPoolExecutor() as executor:
for key, (clusters, mapings) in part_clusters.items():
participants_data = data.participants_data(*key)
part_scores['algorithm'][key] = executor.submit(clustering.score, 'algorithm', clusters, mapings, participants_data)
part_scores['social'][key] = executor.submit(clustering.score, 'social', clusters, mapings, participants_data)
# extract the futures results
for kind, inner_dict in part_scores.items():
for key, val in inner_dict.items():
part_scores[kind][key] = val.result()
d = part_scores['algorithm']
utils.two_groups_three_bars(d, title='Participant based clustering - algorithm score', ylim=[0.5, 1.2])
A/1 -- mean: 0.866, stderr: 0.053 A/2 -- mean: 1.01, stderr: 0.0464 A/3 -- mean: 0.899, stderr: 0.0772 B/1 -- mean: 0.94, stderr: 0.044 B/2 -- mean: 0.68, stderr: 0.034 B/3 -- mean: 0.737, stderr: 0.0575
utils.independent_one_sided_ttest_summary(d[('A', 1)], d[('B', 1)])
mean (a vs b): 0.866 0.940 stderr (a vs b): 0.053 0.044 t: -1.0166109370684138 p: 0.16076982324511818 df: 21
0.16076982324511818 / 2
0.08038491162255909
data.save_to_cooked(d, 'participant_based_clustering_algorithm_score')
d = part_scores['social']
utils.two_groups_three_bars(d, title='Participant based clustering - social score', ylim=[0.4, 0.7])
A/1 -- mean: 0.563, stderr: 0.0378 A/2 -- mean: 0.545, stderr: 0.0421 A/3 -- mean: 0.531, stderr: 0.0433 B/1 -- mean: 0.565, stderr: 0.0274 B/2 -- mean: 0.598, stderr: 0.0356 B/3 -- mean: 0.598, stderr: 0.0282
data.save_to_cooked(d, 'participant_based_clustering_social_score')
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
utils.two_groups_three_bars(part_scores['algorithm'], title='Clustering algorithm score', ylim=[0.5, 1.2])
plt.subplot(1, 2, 2)
utils.two_groups_three_bars(part_scores['social'], title='Clustering social score', ylim=[0.4, 0.7])
data.save_to_graphics('analyze-clustering_scores')
A/1 -- mean: 0.866, stderr: 0.053 A/2 -- mean: 1.01, stderr: 0.0464 A/3 -- mean: 0.899, stderr: 0.0772 B/1 -- mean: 0.94, stderr: 0.044 B/2 -- mean: 0.68, stderr: 0.034 B/3 -- mean: 0.737, stderr: 0.0575 A/1 -- mean: 0.563, stderr: 0.0378 A/2 -- mean: 0.545, stderr: 0.0421 A/3 -- mean: 0.531, stderr: 0.0433 B/1 -- mean: 0.565, stderr: 0.0274 B/2 -- mean: 0.598, stderr: 0.0356 B/3 -- mean: 0.598, stderr: 0.0282
Similarly to the participants positioning based clustering, use clustering based on beacons with at least two participants around them. Merge close beacons and ignore timestamps where there is no such cluster.
beacon_clusters = {}
with concurrent.futures.ProcessPoolExecutor() as executor:
for group, block in itertools.product(['A', 'B'], [1, 2, 3]):
beacon_clusters[(group, block)] = executor.submit(clustering.beacons_clustering, group, block)
# extract the futures results
for key, val in beacon_clusters.items():
beacon_clusters[key] = val.result()
beacon_scores = collections.defaultdict(dict)
with concurrent.futures.ProcessPoolExecutor() as executor:
for key, (clusters, mapings) in beacon_clusters.items():
participants_data = data.participants_data(*key)
beacon_scores['algorithm'][key] = executor.submit(clustering.score, 'algorithm', clusters, mapings, participants_data)
beacon_scores['social'][key] = executor.submit(clustering.score, 'social', clusters, mapings, participants_data)
# extract the futures results
for kind, inner_dict in beacon_scores.items():
for key, val in inner_dict.items():
beacon_scores[kind][key] = val.result()
d = beacon_scores['algorithm']
utils.two_groups_three_bars(d, title='Beacon based clustering - algorithm score', ylim=[0.4, 0.7])
A/1 -- mean: 0.614, stderr: 0.0438 A/2 -- mean: 0.601, stderr: 0.0264 A/3 -- mean: 0.604, stderr: 0.021 B/1 -- mean: 0.611, stderr: 0.0317 B/2 -- mean: 0.624, stderr: 0.0189 B/3 -- mean: 0.639, stderr: 0.0386
data.save_to_cooked(d, 'beacon_based_clustering_algorithm_score')
d = beacon_scores['social']
utils.two_groups_three_bars(d, title='Beacon based clustering - social score', ylim=[0.4, 0.7])
A/1 -- mean: 0.557, stderr: 0.0532 A/2 -- mean: 0.591, stderr: 0.0466 A/3 -- mean: 0.591, stderr: 0.0467 B/1 -- mean: 0.562, stderr: 0.0357 B/2 -- mean: 0.611, stderr: 0.0334 B/3 -- mean: 0.562, stderr: 0.0379
data.save_to_cooked(d, 'beacon_based_clustering_social_score')