In [2]:
%matplotlib inline
DEFAULT_FIGSIZE = (16, 12)
import gzip
import os
import pickle
import itertools
import sys
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.lines as mlines
import matplotlib.patches as mpatches
import seaborn as sns
sns.set_style('darkgrid', {'legend.frameon': True})
import pandas as pd
sys.path.append('..')
from antlia import dtc
from antlia import exp2
from antlia.record import Record, load_file
from antlia.dtype import load_converted_record
from antlia import plot_braking as braking
from antlia.plotdf import plotjoint
%load_ext autoreload
%autoreload 2
import matplotlib as mpl
mpl.rcParams['figure.figsize'] = DEFAULT_FIGSIZE
mpl.rcParams['legend.facecolor'] = 'white'
In [2]:
braking_df = pd.read_pickle('trial2_braking_ttc.p.gz')
# remove rows associated with rider 15
braking_df = braking_df.drop(
braking_df[braking_df['rider id'] == 15].index)
# rename rider 16 to 15
braking_df.loc[braking_df['rider id'] == 16, 'rider id'] = 15
braking_df = braking_df.reset_index(drop=True)
In [8]:
steering_df = pd.read_pickle('trial2_steering_ttc.p.gz')
# rider 16 already dropped
In [9]:
with pd.option_context('display.max_rows', None,
'display.max_columns', None,
'float_format', '{:0.3f}'.format):
print('braking dataframe')
display(braking_df)
print('steering dataframe')
display(steering_df)
In [4]:
def df_speed_subset(dataframe, speed):
index = []
for (i, j) in dataframe[['rider id', 'trial id']].values:
if i == 15:
i = 16
index.append(speed == exp2.instructed_speed(i, j))
return dataframe[index]
#df_speed_subset(steering_df, 12/3.6)
for name, df_type in zip(['braking', 'steering'], [braking_df, steering_df]):
for speed in [None, 12, 17, 22]:
if speed is None:
df = df_type
speed_str = ''
else:
df = df_speed_subset(df_type, speed/3.6)
speed_str = str(speed)
for xtc in ['time-to-collision', 'distance-to-collision']:
xtc_short = xtc[0] + 'tc'
print('{} {}{} {:0.2f}±{:0.2f}'.format(
name, xtc_short, speed_str, df[xtc].mean(), df[xtc].std()))
In [11]:
fields = [
('braking duration', 'duration'),
('linregress slope', 'deceleration'),
]
for type_name, df_type in zip(['braking'], [braking_df]):
for speed in [None, 12, 17, 22]:
if speed is None:
df = df_type
speed_str = ''
else:
df = df_speed_subset(df_type, speed/3.6)
speed_str = str(speed)
for label, field_name in fields:
print('{} \'{}\' {} {:0.2f}±{:0.2f}'.format(
type_name, field_name, speed_str, df[label].mean(), df[label].std()))
In [12]:
fields = [
('event duration', 'duration'),
('minimum clearance', 'clearance'),
]
for type_name, df_type in zip(['steering'], [steering_df]):
for speed in [None, 12, 17, 22]:
if speed is None:
df = df_type
speed_str = ''
else:
df = df_speed_subset(df_type, speed/3.6)
speed_str = str(speed)
for label, field_name in fields:
print('{} \'{}\' {} {:0.2f}±{:0.2f}'.format(
type_name, field_name, speed_str, df[label].mean(), df[label].std()))
In [23]:
print(scipy.stats.linregress(steering_df[['starting velocity', 'time-to-collision']]))
X = steering_df[['starting velocity', 'time-to-collision']].as_matrix()
print(scipy.stats.linregress(*X.T))
#lr = scipy.stats.linregress(x, y)
In [46]:
def field_rvalue_stats(df_name, field):
if df_name == 'braking':
dataframe = braking_df
else:
dataframe = steering_df
df = dataframe[['rider id', 'starting velocity', field]]
rvalue = []
for i in range(16):
df_i = df[df['rider id'] == i].drop('rider id', axis=1)
lr = scipy.stats.linregress(df_i)
rvalue.append(lr.rvalue)
rvalue = np.asarray(rvalue)
float_format = '{:0.2f}'
print('{}, {}'.format(df_name, field))
print('rvalue min: {}'.format(float_format).format(rvalue.min()))
print('rvalue max: {}'.format(float_format).format(rvalue.max()))
print('rvalue mean: {}'.format(float_format).format(rvalue.mean()))
print('rvalue median: {}'.format(float_format).format(np.median(rvalue)))
field_rvalue_stats('braking', 'distance-to-collision')
print()
field_rvalue_stats('braking', 'time-to-collision')
print()
field_rvalue_stats('steering', 'distance-to-collision')
print()
field_rvalue_stats('steering', 'time-to-collision')
print()
field_rvalue_stats('steering', 'lateral clearance')
print()
field_rvalue_stats('steering', 'minimum clearance')
In [5]:
# categorical plots use a default saturation of 0.75
CATEGORICAL_PLOT_SATURATION = 0.75
helper = sns.categorical._CategoricalPlotter()
helper.hue_names = list(range(16))
helper.establish_colors(color=None, palette=None,
saturation=CATEGORICAL_PLOT_SATURATION)
sns.palplot(helper.colors)
helper.gray
Out[5]:
In [35]:
#from antlia import trial2
#
#for tr in r.trials:
# if tr.event.type == trial2.EventType.Overtaking:
# print(tr.event)
In [18]:
from antlia import exp2
#with gzip.open('exp2record00.p.gz', 'rb') as f:
# r0 = pickle.load(f)
# Create braking plot for trial 0-6
plt.close('all')
mpl.rcParams.update({'font.size': 12})
fig, ax = braking.plot_trial_braking_event(
r0.trials[6].event,
metrics_kw=exp2.METRICS_KW,
use_kalman=True,
figsize=DEFAULT_FIGSIZE)
# recreate legend
# ignore last line as it is the x-axis
lines = ax.lines[:-1]
# using known order for this example
handles = [
'filtered measured velocity, gaussian moving average',
'filtered measured acceleration, gaussian moving average',
'linear regression of filtered measured velocity during braking event',
'Kalman estimate velocity',
'linear regression of Kalman estimate velocity during braking event',
'raw measured velocity',
'raw measured acceleration',
]
# get handle for vspan (only 1)
lines.extend(ax.patches)
handles.append('detected braking event')
# update legend
ax.legend(lines, handles, loc='upper right')
# update title and label
ax.set_ylabel('velocity [m/s], deceleration [m/s^2]')
ax.set_title('')
plt.show()
In [72]:
from antlia import trial2
#with gzip.open('exp2record11.p.gz', 'rb') as f:
# r11 = pickle.load(f)
j = 7
event = r11.trials[j].event
colors = sns.color_palette('Paired', 10)
plt.close('all')
fig, ax = plt.subplots()
region = trial2.find_steering_region(event, ax=ax, obstacle_origin=True)
ax.lines[0].set_color(colors[9])
p = ax.patches[0]
p.set_label('detected overtaking event')
p.set_hatch('')
p.set_fill(True)
p.set_alpha(0.2)
c0 = ax.collections[0]
c0.set_label('detected trajectory local y-maxima')
c0.set_color(colors[3])
c1 = ax.collections[1]
c1.set_label('detected trajectory local y-minima')
c1.set_color(colors[3])
plot_kw = {
'label': 'gaussian fit of Kalman estimate \ntrajectory during steering event',
'color': colors[9],
'linestyle': '--',
#'linewidth': 3
}
params = trial2.fit_steering_model(event,
region,
ax=ax,
obstacle_origin=True,
**plot_kw)
ax.scatter(event.x - trial2.OBSTACLE_POINT[0],
event.y - trial2.OBSTACLE_POINT[1],
label='lidar point cloud',
marker='.',
color=colors[1],
alpha=0.05,
zorder=-1)
ax.scatter(
0,
0,
s=100,
marker='x',
linewidth=5,
color=colors[5],
label='Obstacle point'
)
ax.legend()
ax.set_xlabel('x-coordinate [m]')
ax.set_ylabel('y-coordinate [m]')
plt.show()
In [43]:
def boxswarmplot(x, y, data, ax):
# Don't plot outliers in boxplot as they will show up in the swarmplot.
sns.boxplot(x=x, y=y, data=data,
ax=ax, showfliers=False)
# Set alpha transparency of the boxes (excluding edges).
for patch in ax.artists:
r, g, b, a = patch.get_facecolor()
patch.set_facecolor((r, g, b, 0.2))
# Plot swarmplot in front of box face but behind median and IQR lines.
# zorder for box is 0.9 while others are 2 or 2.1.
sns.swarmplot(x=x, y=y, data=data,
ax=ax, zorder=1, alpha=1)
In [44]:
# results 1.1 - increase in speed results in larger braking distance
#
# Calculate pearson correlation coefficient for each person for distance-to-collision and starting velocity
# Range, median of PCC.
# How should we show this?
# Maybe we should calculate the linear regression, and then the error from the linear regression for each trial?
import scipy.stats
# Calculate Pearson correlation coefficient for each rider
pcc = []
x = []
y = []
num_riders = 16
for i in range(num_riders):
df = braking_df[braking_df['rider id'] == i]
xi = df['starting velocity'].values
yi = df['distance-to-collision'].values
reg = scipy.stats.linregress(xi, yi)
x.append(xi)
y.append(yi)
pcc.append(reg)
# create PCC dataframe
dtype = list(zip(pcc[0]._fields, len(pcc[0]._fields)*('float',)))
pcc = np.asarray(pcc, dtype=dtype).view(np.recarray)
print(pcc.dtype)
print('pcc median: ', np.median(pcc.rvalue))
print('pcc range: ', np.ptp(pcc.rvalue))
pcc_df = pd.DataFrame(data=pcc).transpose()
print('Pearson correlation coefficient table')
display(pcc_df)
plt.close('all')
fig, ax = plt.subplots()
# Plot velocity vs. dtc for all trials
colors = sns.color_palette('husl', num_riders)
for i in range(num_riders):
ax.plot(x[i], y[i], color=colors[i], linestyle=' ', marker='.')
x_sorted = np.sort(x[i])
ax.plot(x_sorted, pcc[i].slope*x_sorted + pcc[i].intercept,
color=colors[i], label='rider {}'.format(i))
ax.set_xlabel('starting velocity')
ax.set_ylabel('distance-to-collision')
ax.legend()
plt.show()
fig2, ax2 = plt.subplots(1, 2,
gridspec_kw={'width_ratios': [4, 1]},
sharey=True)
sns.swarmplot(x=list(range(num_riders)), y=pcc.rvalue, ax=ax2[0])
sns.boxplot(pcc.rvalue, color=helper.gray, ax=ax2[1],
orient='v',
showfliers=False,
boxprops={'facecolor': (0, 0, 0, 0)})
sns.swarmplot(x=pcc.rvalue, orient='v',
color=helper.gray, ax=ax2[1],
alpha=0.7)
ax2[0].set_ylabel('Pearson r-value')
ax2[0].set_xlabel('rider id')
# Calculate residuals for each rider
Out[44]:
In [45]:
def calculate_linregress_residuals(data, x, y):
x_ = data[x].values
y_ = data[y].values
reg = scipy.stats.linregress(x_, y_)
#print(reg)
sorted_index = np.argsort(x_)
sorted_x = x_[sorted_index]
observed_y = y_[sorted_index]
predicted_y = reg.slope*sorted_x + reg.intercept
residual = observed_y - predicted_y
# print normalized residual error
#print(np.sqrt(np.sum(residual**2))/len(residual))
return sorted_x, residual
d = {
'rider id': [],
'starting velocity': [],
'linregress residual': [],
}
for i in range(num_riders):
sorted_velocity, residual = calculate_linregress_residuals(
braking_df[braking_df['rider id'] == i],
'starting velocity',
'distance-to-collision')
d['rider id'].extend(len(residual)*[i])
d['starting velocity'].extend(sorted_velocity)
d['linregress residual'].extend(residual)
pcc_residual_df = pd.DataFrame(data=d)
print('PCC residual table (per rider)')
display(pcc_residual_df.transpose())
fig, ax = plt.subplots()
boxswarmplot(x='rider id', y='linregress residual',
data=pcc_residual_df,
ax=ax)
ax.set_ylabel('v-dtc linregress residual')
# plot velocity vs. residuals for each rider
grid = sns.FacetGrid(pcc_residual_df, col='rider id', hue='rider id',
col_wrap=4)
grid.map(plt.plot, 'starting velocity', 'linregress residual', marker='o')
# plot boxswarm of all data
velocity_all, residual_all = calculate_linregress_residuals(
braking_df, 'starting velocity', 'distance-to-collision')
fig, ax = plt.subplots()
sns.boxplot(residual_all,
color=helper.gray, ax=ax,
#orient='v',
showfliers=False,
boxprops={'facecolor': (0, 0, 0, 0)})
sns.swarmplot(residual_all,
color=helper.gray, ax=ax,
alpha=0.7)
sns.distplot(residual_all,
color=helper.gray, ax=ax,
fit=scipy.stats.norm)
ax.autoscale(axis='y')
In [48]:
# results 1.2 - increase in speed results in earlier braking
#
# Braking decleration is independent from speed.
# Add deceleration column
f = lambda row: -row['linregress slope']
braking_df['deceleration'] = braking_df.apply(f, axis=1)
num_riders = 16
d = {'median': [], 'std': []}
for i in range(num_riders):
df = braking_df[braking_df['rider id'] == i]
v = df['deceleration'].values
d['median'].append(np.median(v))
d['std'].append(np.std(v))
# print PCC for velocity-deceleration
reg = scipy.stats.linregress(
df['starting velocity'], v)
for k in reg._fields:
dictkey = 'linregress ' + k
dictvalue = getattr(reg, k)
if dictkey in d:
d[dictkey].append(dictvalue)
else:
d[dictkey] = [dictvalue]
deceleration_df = pd.DataFrame(data=d).transpose()
print('braking deceleration table')
display(deceleration_df)
print('overall')
v = braking_df['deceleration'].values
print('median: ', np.median(v))
print('std: ', np.std(v))
fig, ax = plt.subplots(1, 2, sharey=True,
gridspec_kw={'width_ratios': [5, 1]})
plot_swarm_overlay = True
if not plot_swarm_overlay:
# get a ligher gray for the box face color
c = sns.light_palette(helper.gray)[3]
sns.boxplot(x='deceleration', data=braking_df,
color=helper.gray, ax=ax[1],
orient='v',
boxprops={'facecolor': c})
else:
sns.boxplot(x='deceleration', data=braking_df,
color=helper.gray, ax=ax[1],
orient='v',
showfliers=False,
boxprops={'facecolor': (0, 0, 0, 0)})
sns.swarmplot(y='deceleration', data=braking_df,
color=helper.gray, ax=ax[1],
alpha=0.7)
#sns.distplot(braking_df['deceleration'].values,
# color=helper.gray, ax=ax[1],
# fit=scipy.stats.norm,
# vertical=True)
#ax[1].autoscale(axis='x')
if not plot_swarm_overlay:
sns.boxplot(x='rider id', y='deceleration',
data=braking_df,
ax=ax[0])
else:
boxswarmplot(x='rider id', y='deceleration',
data=braking_df,
ax=ax[0])
ax[0].set_ylabel('braking decleration [m/s^2]')
ax[1].get_yaxis().set_visible(False)
ax[0].set_xlabel('rider id')
ax[1].set_xlabel('all riders')
# plot velocity vs. deceleration for each rider
grid = sns.FacetGrid(braking_df, col='rider id', hue='rider id',
col_wrap=4)
# plot deceleration for each trial
grid.map(plt.plot, 'starting velocity', 'deceleration',
marker='o', linestyle=' ', alpha=0.5)
# plot deceleration linear regression
## we need a function that takes the 'starting velocity' dataframe column,
## sorts it, and then accesses the deceleration linear regression in order
## to plot the linefit
def sorted_plot(x, *args, **kwargs):
i = int(kwargs['label'])
sorted_x = np.sort(x.values)
slope = deceleration_df[i]['linregress slope']
intercept = deceleration_df[i]['linregress intercept']
return plt.plot(sorted_x, slope*sorted_x + intercept, *args, **kwargs)
grid.map(sorted_plot, 'starting velocity',
linestyle='--')
# add text with r-value to each facet
for i, axis in enumerate(grid.axes.flat):
r = deceleration_df[i]['linregress rvalue']
axis.set_title(axis.get_title() + '\nr-value = {:0.3f}'.format(r))
grid.fig.tight_layout()
grid.set_xlabels('starting velocity [m/s]')
grid.set_ylabels('braking deceleration [m/s^2]')
plt.show()
print('overall linear regression, onset velocity vs. deceleration constant')
print(scipy.stats.linregress(
df['starting velocity'],
df['deceleration']
))