Data Science 3: Seeing Force

Posted on Jan 15, 2022

Let’s start making some comparisons under the assumption that you’ve read part one and part two. I have that one clean lap in the Falcon GT-F 351 (I finally confirmed the specific model). I also have a lap from the cover car, a Mercedes-AMG One, and a 240Z which is just a complete and utter classic and great car. But they’re all very very different. The Forza games have a concept of a performance class which is subdivisions of the performance index. The elevator pitch is that cars are rated based on specs with regards to their performance for one lap around a computed “index track”. I can assure you that this is a very generalized concept and that highly-rated cars can be nearly undriveable however it is an interesting measure.

Table Of Contents

The usual suspects

Let’s take a look at the dossiers of these vehicles.

The cars as tested–it’s a video game. An arcade-style video game at that.
SpecsFalcon GT-F 351Fairlady 240ZMercedes-AMG One
ManufacturerFordNissanMercedes-AMG
Model Year201519692022?
Car ClassAAX
Performance Index799800999
DrivelineFRFRAWD*
Weight3,344 lb1,927 lb3,133 lb
AspirationSuperchargedTurbochargedTurbocharged/Electric
Horsepower471 hp371 hp1,319 hp
Torque420 lb-ft271 lb-ft770 lb-ft

Ford Falcon GT-F 351

For my American friends this car would seem to be unusual at best and all wrong at worst. We had a Ford Falcon back in the day that was particularly different however the Falcon name survived in Australia as it had a distinguished racing career. The Falcon GT has seen several iterations that, most succinctly, can be paralleled with Ford America’s Special Vehicle Team (SVT) that brought us such performance vehicles as the Mustang SVT Cobra and SVT Lightning. In Australia that was Tickford Vehicle Engineering (TVE) that morphed in the Ford Tickford Experience (FTE) which was eventually bought out by motorsports design firm Prodrive and a change in the collaboration’s branding to Ford Performance Vehicles (FPV).

The Miami V8 is the Australian-sourced, modified, and assembled Ford Coyote V8 and the version of the motor in the GT-F outputs anywhere from 460-540hp based on some variability on boost pressure (it’s my assumption that the ECU opens the bypass valve to avoid boost pressures that could damage the engine during extremely warm Australian weather but I’ve found zero information on this “overboost” functionality of a technical nature–that’s normally not a thing in supercharged engines unless they have some type of variable pulley system on the supercharger belt–and there are clutched superchargers and that’s just kinda weird).

It’s a heavier car coming in at around 4000lbs (in real life) with independent rear suspension. It’s 194" long and 73.5" wide which, for Americans, would be roughly equivalent in overall dimension to a late model Nissan Altima. Driving it in game, the car feels eminently predictable and controllable.

This is the Ford Falcon GT-F 351 as pictured in photo mode. It is actually an almost nuclear orange and the sun the way it was didn't help.

Mercedes-AMG One

The ONE is a car that is still, mostly, in development by Mercedes-AMG and is billed to be the only road-going Formula 1 car as it’s using a significant amount of technology from the Mercedes Formula 1 engine and race team programs. There is still some ambiguity as to how much power and how large it will be so, I would assume, Playground Games just made some reasonable assumptions and Mercedes-AMG didn’t have an issue with that. It’s been reported that the turbocharged V6 will make 748hp without the aid of the electric hybrid system. The electric powertrain will be a multi-component system that will perform various functions as well as outputting power through two electric motors–one at either side of the front of the car. This is the All-Wheel Drive* system referenced above and, with motors at either side, would allow for some extremely clever power manipulation to improve handling. It’s been reported that the electric system will be worth 600hp on its own.

The car will likely be long and wider than any of the others here as it is aerodynamically focused and will be made in limited quantities as opposed to being a mass-produced consumer vehicle. There are various active aerodynamic elements on the car and Forza Horizon 5 allows you to toggle between an “attack mode” high-downforce setting and a “slick mode” (these names are what I’ve called them) low-downforce setting that increases top speed and would, by all accounts, increase fuel economy. Game-wise the car drives fantastically in “attack mode” and drives quite poorly in “slick mode” (at least in comparison). I’m sure my lack of ability does it no favors and this may, in fact, be “too much car” for me.

The AMG One also pictured at Horizon's Apex Outpost on the beach in the southeast part of the map. As you can see it's in attack mode. The vents on the front fenders open up to provide additional downforce and cooling and the wing at the back is up and with a much steeper angle than in slick mode.

Nissan Fairlady 240Z

I saved this one for last because, in the real world, it’s definitely my favorite of the three. The Z cars have a wonderful following and, at least in the US, have carved themselves into a niche as one of the most fun cars to drive. Of the three this is the only one I’ve ever seen in person or driven and I can say that both experiences were great (it was an NA high compression carbureted L28 which isn’t exactly a powerhouse by any recent standards but the car is so light that everything feels immediate and the immediacy makes it a genuinely engaging experience even if you’re not hooning it around [which I was not]). There’s a lot of history to the Z brand, and its ideals, but it was modeled after the gentlemanly sports cars of the time but then produced to be affordable and accessible.

This example of the 240Z in the game is highly modified to get it into the A class and is a bit of a handful. With a 90in wheelbase and an overall length of 173 inches the car is quite compact and thusly has a low moment of inertia. This is desirable when the car can be thoroughly and appropriately controlled however, in this particular game with the Xbox One controller, I am not fully able to do that. I did crash it a few times and that tended to come from the rear of the car losing grip when applying throttle during turn exit.

The early Z-cars, however, are not just cult classics. They are true classics and a genuine driving experience.

This is the 240Z as driven. It doesn't look quite as good as a car in real life could--there's a healthy aftermarket that isn't quite reflected in the game.

The plot thickens

There are various ways that you can compare these vehicles. Why don’t we just throw a lap up from each on a line graph and see what we see:

import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.pyplot import figure
import matplotlib.ticker as tick
import numpy as np

WELCOME_TO_EARTH = 9.80665

# read csv file
amg_one = pd.read_csv('/content/drive/MyDrive/ForzaData/amg_one.csv')
z_car = pd.read_csv('/content/drive/MyDrive/ForzaData/240z_3.csv')
ford_falcon = pd.read_csv('/content/drive/MyDrive/ForzaData/ford_falcon.csv')

race_amg_one = amg_one.loc[(amg_one['IsRaceOn'] == 1)]
race_240z = z_car.loc[(z_car['IsRaceOn'] == 1)]
race_falcon = ford_falcon.loc[(ford_falcon['IsRaceOn'] == 1)]

fig, (ax1, ax2, ax3) = plt.subplots(3,1)
fig.set_figheight(16)
fig.set_figwidth(10)

lap_amg = race_amg_one.loc[(race_amg_one['Lap'] == 2)]
lap_240z = race_240z.loc[(race_240z['Lap'] == 2)]
lap_falcon = race_falcon.loc[(race_falcon['Lap'] == 2)]


ax1.plot(lap_amg['CurrentLapTime'],lap_amg['AccelerationX'] / WELCOME_TO_EARTH, color='cyan',label="AMG One")
ax1.plot(lap_240z['CurrentLapTime'],lap_240z['AccelerationX'] / WELCOME_TO_EARTH, color='red',label="240z")
ax1.plot(lap_falcon['CurrentLapTime'],lap_falcon['AccelerationX'] / WELCOME_TO_EARTH, color='green', label="Falcon FPV")  
ax1.set_xlabel("Lap Time")
ax1.set_ylabel("Acceleration X")
ax1.legend()

ax2.plot(lap_amg['CurrentLapTime'],lap_amg['AccelerationY'] / WELCOME_TO_EARTH, color='cyan',label="AMG One")
ax2.plot(lap_240z['CurrentLapTime'],lap_240z['AccelerationY'] / WELCOME_TO_EARTH, color='red',label="240z")
ax2.plot(lap_falcon['CurrentLapTime'],lap_falcon['AccelerationY'] / WELCOME_TO_EARTH, color='green', label="Falcon FPV")
ax2.set_xlabel("Lap Time")
ax2.set_ylabel("Acceleration Y")
ax2.legend()

ax3.plot(lap_amg['CurrentLapTime'],lap_amg['AccelerationZ'] / WELCOME_TO_EARTH, color='cyan',label="AMG One")
ax3.plot(lap_240z['CurrentLapTime'],lap_240z['AccelerationZ'] / WELCOME_TO_EARTH, color='red',label="240z")
ax3.plot(lap_falcon['CurrentLapTime'],lap_falcon['AccelerationZ'] / WELCOME_TO_EARTH, color='green', label="Falcon FPV")
ax3.set_xlabel("Lap Time")
ax3.set_ylabel("Acceleration Z")
ax3.legend()

def racetime_fmt(x, y):
    minutes, seconds = divmod(x, 60)
    return "{:.0f}".format(minutes) + ':' + "{:.0f}".format(seconds)

ax1.xaxis.set_major_formatter(tick.FuncFormatter(racetime_fmt))
ax2.xaxis.set_major_formatter(tick.FuncFormatter(racetime_fmt))
ax3.xaxis.set_major_formatter(tick.FuncFormatter(racetime_fmt))
ax.legend()

Lines, lines, everywhere some lines

This is a busy graph. This is combining multiple lines on one plot and multiple plots in one image.

Throw a bunch of lines at the wall and see what sticks.

This is busy at best and confusing at worst. How is it confusing? While the x-axis is consistent the y-axis changes and it’s auto-formatted based on the values. This does make the graphs look better, yes, however it would be inappropriate to draw any objective comparisons based on how these plots look (which, if I haven’t mentioned, often happens). If you’re thinking “hey, in Data Science 2: Forza Boogaloo we already combined these values into ‘Total Acceleration’” well, you’re right, but I started working off an older plot that I had already done for this one just to prove a point. You can see that the Ford Falcon and Nissan 240Z show some similar acceleration numbers at similar points in time (ignore the part where I crashed in the 240Z).

Histogram? No, thistogram

A different way of presenting this type of data with a bit more density would be a histogram. Not the bar chart type, but a two-dimensional histogram. For the uninitiated, a histogram has a concept of bins which are categories of values and plots based on frequency of hits in those bins. If you’re into photography or video/cinematography then you’re probably very well of the color histograms which would give you an idea of what luminosity the number of pixels per color would be in. If you do pursue those hobbies but aren’t familiar with histograms then you may possibly benefit from looking into it. Let’s plot a couple of 2D histograms to see what type of representation we can manage.

import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.pyplot import figure
import matplotlib.ticker as tick
import numpy as np


WELCOME_TO_EARTH = 9.80665
# read csv file
ford_falcon = pd.read_csv('/content/drive/MyDrive/ForzaData/ford_falcon_video.csv')
race_falcon = ford_falcon.loc[(ford_falcon['IsRaceOn'] == 1)]
lap = race_falcon.loc[(race_falcon['Lap'] == 2)]

race_amg_one = amg_one.loc[(ford_falcon['IsRaceOn'] == 1)]
lap_amg = race_amg_one.loc[(race_falcon['Lap'] == 2)]

plt.style.use('default')


fig, (ax, ax2) = plt.subplots(1,2,tight_layout=False, sharex=True,sharey=True)
fig.set_size_inches(14,6, forward=True)


hist = ax2.hist2d(lap['AccelerationX'] / WELCOME_TO_EARTH, lap['AccelerationY'] / WELCOME_TO_EARTH, bins=40)
ax2.set_facecolor('#440154') #the histogram would have white borders since we scaled up the axes to match the AMG

hist2 = ax.hist2d(lap_amg['AccelerationX'] / WELCOME_TO_EARTH, lap_amg['AccelerationY'] / WELCOME_TO_EARTH, bins=40)

ax.set_title("Mercedes-AMG One")
ax.set_xlabel("Acceleration X (g)")
ax.set_ylabel("Acceleration Y (g)")
ax2.set_title("Ford Falcon GT-F 351")
ax2.set_xlabel("Acceleration X (g)")
ax2.set_ylabel("Acceleration Y (g)")


def racetime_fmt(x, y):
    minutes, seconds = divmod(x, 60)
    return "{:.0f}".format(minutes) + ':' + "{:.0f}".format(seconds)

fig.suptitle("Acceleration Event Plot")
fig.show()

If you're really into TV procedurals or know anyone with a Jung Number of 2 then this might be a little like a Rorschach test. But for data.

What is the ‘symbology’ of it all?

So we’re seeing a graphical representation of measurements taken from the overhead view of the car. Had I been prepared I would have superimposed a picture of the car over the origin. I was not prepared. I may go back and update this, though, but imaged the car being placed in the origin and facing upwards (I think it’s upwards. I’ll verify the cardinality the next time I get an opportunity to record telemetry.)

You’ll note that I needed to set ax2.set_facecolor('#440154') because I had also set sharex=True,sharey=True when declaring subplots() because I wanted them to have the same axes to be “apples to apples”. So the great part about sharing x and y is that you can easily visually determine groupings and magnitudes and their differences. Also, matplotlib will leave the range that isn’t used as the background color. There might be a way to ensure the entire plot is filled with the background color but I didn’t find it. The colors also display groupings–the brighter the color the more events were recording within those values. That’s the bins=40 values I was talking about–40 bins allows for more resolution in a very practical and layperson’s experience.

It’s obvious (I mean, it was already obvious) that the AMG One has a wider total range but they both roughly have a similar form of many values vertically down the middle which represent acceleration and braking in a straight line. Then there are the two “wings” with the larger magnitude values (the ones further from the origin which is the exact middle of the plot) expanding at the positive y values (I can assume that this is the braking events).

Histograms don’t give you a moment in time but they do give you an idea of overall moments–if that makes sense. A good example: the “wings” on the Falcon’s plot are somewhat even but with more values on the left “wing” (it’s got brighter colors). The AMG One’s left “wing” is much longer than its right “wing” which gives the impression that those left-hand turns are:

  1. More hardcore than their right-hand turn counterparts (with regards to acceleration on the two axes). A more specific assumption here might be that the cars start coming into the long left-handers with a lot of speed and need to start slowing down in the turn–the AMG One just does all of those things more than the Falcon.
  2. The Falcon has basically reached its limits on the right-hand turns as well. It can’t produce any more acceleration than it has on the right-hand turns. The AMG One is a far more capable machine based on this as well as it’s car class and performance index.

Enter the scatter plot

I don’t necessarily know that this is better or worse than the histogram but scatter plots are great for reasons yet to be demonstrated. It’s going to look similar to a histogram but with some fun, albeit not terribly informational, colors.

import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.pyplot import figure
import matplotlib.ticker as tick
import numpy as np
import matplotlib as mpl # new import


WELCOME_TO_EARTH = 9.80665
# read csv file
ford_falcon = pd.read_csv('/content/drive/MyDrive/ForzaData/ford_falcon_video.csv')
race_falcon = ford_falcon.loc[(ford_falcon['IsRaceOn'] == 1)]
lap = race_falcon.loc[(race_falcon['Lap'] == 2)]

race_amg_one = amg_one.loc[(ford_falcon['IsRaceOn'] == 1)]
lap_amg = race_amg_one.loc[(race_falcon['Lap'] == 2)]

## Add total acceleration to dataframe
lap = lap.assign(TotalAcceleration=lambda x: np.sqrt(pow(x['AccelerationX'],2) + pow(x['AccelerationY'],2))/ WELCOME_TO_EARTH)
lap_amg = lap_amg.assign(TotalAcceleration=lambda x: np.sqrt(pow(x['AccelerationX'],2) + pow(x['AccelerationY'],2))/ WELCOME_TO_EARTH)
plt.style.use('default')


fig, (ax, ax2) = plt.subplots(1,2,tight_layout=False, sharex=True,sharey=True)
fig.set_size_inches(14,6, forward=True)

cmap = plt.cm.jet
norm = plt.Normalize(vmin=np.min(abs(lap['TotalAcceleration'])), vmax=np.max(abs(lap_amg['TotalAcceleration'])))
scatter = ax2.scatter(lap['AccelerationX'] / WELCOME_TO_EARTH, lap['AccelerationY'] / WELCOME_TO_EARTH, color=cmap(norm(abs(lap['TotalAcceleration'])) ))


scatter_amg = ax.scatter(lap_amg['AccelerationX'] / WELCOME_TO_EARTH, lap_amg['AccelerationY'] / WELCOME_TO_EARTH, color=cmap(norm(abs(lap_amg['TotalAcceleration']))))

ax.set_title("Mercedes-AMG One")
ax.set_xlabel("Acceleration X (g)")
ax.set_ylabel("Acceleration Y (g)")
ax2.set_title("Ford Falcon GT-F 351")
ax2.set_xlabel("Acceleration X (g)")
ax2.set_ylabel("Acceleration Y (g)")

sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
plt.colorbar(sm, ax=[ax, ax2],ticks=[np.min(lap['TotalAcceleration']),np.mean(lap['TotalAcceleration']),np.mean(lap_amg['TotalAcceleration']),np.max(lap_amg['TotalAcceleration'])],label="Total Acceleration(G)",orientation="horizontal")


fig.suptitle("Acceleration Event Plot")
fig.show()

Very colorful but not necessarily better than the histogram.

An IT guy, a python, and a matplotlib walk into a colorbar

I think that the colorbar is very cool. There are a few components to it. The ColorMap is actually crucial and can be changed. This page shows a very complicated way to find out what they look like–there could be a simple command like listing the ColorMaps but this didn’t happen for these docs. You can try using dir(plt.cm) (when using plt as imported in the above examples or the linked notebook) and it should provide some insight as to what you may have available to you. The linked documentation gives you visual indicators of what the ColorMaps look like. We’re using plt.cm.jet in this example.

If you’ve worked in audio you’ve heard of “normalization”. This isn’t the database term but more the statistical term and, unfortunately, the audio term seems to have been co-opted somewhat. There is definitely several posts about the audio term and they’re of varying practical and factual utility (and yes, they’re independent values if you can dig that) but the idea, from my experience, is to bring the loudest peak to your normalization target. Or to use a metric like LUFS over a time (that’s the integrated value and a subject for another post) but here, in the statistical concept of normalization, what we’re looking for is to take the range of our data and match the minimum and the maximum of our data to the minimum and the maximum values of our ColorMap.

So cheers to norm which uses plt.Normalize to take vmin and vmax and stretch those values out. Good and easy stuff. Does it follow a biased distribution? No. Is that fully necessary for a human do acquire information from it? Also no. We’re going to use the ticks to provide some context anyway. Or we already did. Time is a flat circle. We drop this normalization into the variable norm and the color parameter (remember that after the main positional parameters in Python you can just be like parameter=blah and it’s all good–very Pythonic) of plotting the .scatter is going to use cmap to take a norm of the specific value of the column TotalAcceleration from the DataFrame. This means that you can actually map scatter plot colors to independent variables. In this case they end up like a very well organized rainbow because they’re governed by magnitude and the further out from the origin they get the more the magnitude is. No big deal but it’s not necessarily the best example. The colorbar gives us context for what those values that map the colors are.

We use the parameter label for the plt.colorbar function to put the title on it and that’s actually super important in providing context. In this case we use sm to set up the spectrum of values (from norm) and applying the same ColorMap cmap to set the spectrum of the color bar. It makes sense when you think about it but not necessarily when you read it. Thanks, Python. We get an array of these values (probably an array to represent some type of data structure–at this point I’m 19 layers in and not asking many questions) as well as the parameter ax which means “which axes are you applying this colorbar to?” and to that query we respond [ax, ax2] because we want it to apply to both plots equally (since we’re comparing them–apples to apples). This is why we defined vmin as the minimum total acceleration of the Ford Falcon and vmax as the maximum acceleration of the Mercedes-AMG One. Really catch all of the spectrum there. Not throwing shade at the Falcon–I really like driving that car it’s just very much Class A.

Importantly we also use the color parameter to ax.scatter and ax2.scatter to ensure that they use the Color Map that we (I) have decided on. Just be warned because in all these nested functions here be parenthesis mismatches. Ensure that if you get an error you are meticulous about your brackets, parenthesis, quotes, and commas. I’ve heard people say that Python is easier because it doesn’t require semi-colons but that’s simply not true and the language lends itself to be written with less lines but with more complexity–and maybe it’s more the culture around it than the language itself but here we are–and, aside from spaces issues (yes, spaces. I’ve already lived that so I’m good with it but just use tabs. And ensure your tabs are good. Really. This could be the source of your frustration–something simultaneously less obvious and infinitely more simple than parenthesis and brackets) this is the most common source of “hey what the hell does that error mean?” so keep your wits about you.

SO we’re using a colormap based on the largest range of both plots as well as applying that same colormap to both plots. This makes logical visual sense to me. Logical and visual sense isn’t always the purpose of a plot (check out a pie chart if you’re bored) but it’s what I’m striving for. Using ticks we are able to add the np.mean of both the Falcon and the One (there is no spoon). It’s clever and maybe it’s even cute but I’m not entirely convinced that it’s helpful.

Standard nerds

I don’t think it’d be wise to try to extend Hugo to make a heading a link so here’s the link for the heading. But we aren’t talk about Sonic fan art–we’re talking about Standard Deviation. The standard deviation is the average amount that we expect a point to deviate from the average (and that’s something that no one in a University can tell you) and has a long and storied history of coming from the “variance”. This website has a banging image of what a normal distribution looks like however the function that we’re using, by my research, takes a biased number. I’ll take it as it comes but that’s the vibe that I get based on the distribution of the numbers. Plot’em if you got’em.

If you got it better plot it

Another plot and it’s two of America’s most wanted (stats) (no they aren’t) (I’m reaching).

np.std(lap['TotalAcceleration'])

totalaccel_falcon = lap['TotalAcceleration'].to_numpy()
totalaccel_amg = lap_amg['TotalAcceleration'].to_numpy()


total_totals = np.append(totalaccel_amg, totalaccel_falcon)

std_dev = np.std(total_totals)
std_rounded = round(np.std(total_totals),3)
print (std_rounded) #debugging



mintick = np.min(lap['TotalAcceleration'])
maxtick = np.max(lap_amg['TotalAcceleration'])
ticks = [mintick, maxtick, np.mean(lap['TotalAcceleration']), np.mean(lap_amg['TotalAcceleration'])]
i = mintick
while i < maxtick - std_dev:
  i = i + std_dev
  ticks.append(round(i, 3))

So this gives us our ticks (yes, you’ll need to import and have many other variables set up–check the notebook at the bottom if you haven’t already). It’s both non-obvious and incredibly straightforward. np.std gives you that hot stuff based off of a DataFrame column (in this case ‘TotalAcceleration’) and there are a few false starts before I figure it out. Debugging in the raw. total_totals is the total compilation of TotalAcceleration readings from both the Falcon and the One. std_dev is, roughly and based on the very simple way of thinking about it, the average amount that you’d expect a point to differ from the average. So with the average and the standard deviation you can make some guesses. I’ve read that np.std returns a biased number that assists with the distribution of your particular dataset. Put it into action:

Have some standard deviations. Something feels a little weird about it. Did I do this wrong? let me know in the comments. I don't have comments. Let me know on twitter, I guess.

But that’s actually turbo busy down there. Not super helpful. It’s also difficult to label things on a color bar (from what I’ve seen it’s non-obvious). We can use what we learned about annotations to spice up the plot while keeping specific scalars separate from the colorbar.

Just slap a label on it

import pandas as pd
from matplotlib import pyplot as plt
from matplotlib.pyplot import figure
import matplotlib.ticker as tick
import numpy as np
import matplotlib as mpl # new import


WELCOME_TO_EARTH = 9.80665
# read csv file
ford_falcon = pd.read_csv('/content/drive/MyDrive/ForzaData/ford_falcon_video.csv')
race_falcon = ford_falcon.loc[(ford_falcon['IsRaceOn'] == 1)]
lap = race_falcon.loc[(race_falcon['Lap'] == 2)]

race_amg_one = amg_one.loc[(ford_falcon['IsRaceOn'] == 1)]
lap_amg = race_amg_one.loc[(race_falcon['Lap'] == 2)]

## Add total acceleration to dataframe
lap = lap.assign(TotalAcceleration=lambda x: np.sqrt(pow(x['AccelerationX'],2) + pow(x['AccelerationY'],2))/ WELCOME_TO_EARTH)
lap_amg = lap_amg.assign(TotalAcceleration=lambda x: np.sqrt(pow(x['AccelerationX'],2) + pow(x['AccelerationY'],2))/ WELCOME_TO_EARTH)
plt.style.use('default')


fig, (ax, ax2) = plt.subplots(1,2,tight_layout=False, sharex=True,sharey=True)
fig.set_size_inches(14,6, forward=True)
cmap = plt.cm.jet
norm = plt.Normalize(vmin=np.min(abs(lap['TotalAcceleration'])), vmax=np.max(abs(lap_amg['TotalAcceleration'])))
scatter = ax2.scatter(lap['AccelerationX'] / WELCOME_TO_EARTH, lap['AccelerationY'] / WELCOME_TO_EARTH, color=cmap(norm(abs(lap['TotalAcceleration'])) ))

scatter_amg = ax.scatter(lap_amg['AccelerationX'] / WELCOME_TO_EARTH, lap_amg['AccelerationY'] / WELCOME_TO_EARTH, color=cmap(norm(abs(lap_amg['TotalAcceleration']))))
ax.set_title("Mercedes-AMG One")
ax.set_xlabel("Acceleration X (g)")
ax.set_ylabel("Acceleration Y (g)")
ax2.set_title("Ford Falcon GT-F 351")
ax2.set_xlabel("Acceleration X (g)")
ax2.set_ylabel("Acceleration Y (g)")

# colorbar setup
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])

# colorbar ticks setup
np.std(lap['TotalAcceleration'])

totalaccel_falcon = lap['TotalAcceleration'].to_numpy()
totalaccel_amg = lap_amg['TotalAcceleration'].to_numpy()
total_totals = np.append(totalaccel_amg, totalaccel_falcon)
std_dev = np.std(total_totals)
std_rounded = round(np.std(total_totals),3)
print (std_rounded) #debugging
mintick = np.min(lap['TotalAcceleration'])
maxtick = np.max(lap_amg['TotalAcceleration'])
ticks = [mintick, maxtick, np.mean(total_totals)]
mean_std = np.mean(total_totals)
print (mean_std)
ticks.append(round(mean_std - std_dev, 3))
ticks.append(round(mean_std + std_dev, 3))
#i = mintick
#while i < maxtick - std_dev:
  #i = i + std_dev
  #ticks.append(round(i, 3))

# then the colorbar
plt.colorbar(sm, ax=[ax, ax2],ticks=ticks,label="Total Acceleration(G)",orientation="horizontal")
def racetime_fmt(x, y):
    minutes, seconds = divmod(x, 60)
    return "{:.0f}".format(minutes) + ':' + "{:.0f}".format(seconds)
xlimmleft, xlimright = ax.axes.get_xlim()
ylimbottom, ylimtop = ax.axes.get_ylim()
amg_txt = ax.text( s ="{:.2f} g".format(np.mean(lap_amg['TotalAcceleration'])), x=.09, y=.065, transform=ax.transAxes, 
                  ha="center", va="center", rotation=0, size=15, 
                  bbox=dict(boxstyle="square,pad=0.3", fc=cmap(norm(np.mean(lap_amg['TotalAcceleration']))),
                            ec=cmap(norm(np.mean(lap_amg['TotalAcceleration']))), lw=2))

falcon_txt = ax2.text( s ="{:.2f} g".format(np.mean(lap['TotalAcceleration'])), x=.09, y=.065, transform=ax2.transAxes, 
                  ha="center", va="center", rotation=0, size=15, 
                  bbox=dict(boxstyle="square,pad=0.3", fc=cmap(norm(np.mean(lap['TotalAcceleration']))),
                            ec=cmap(norm(np.mean(lap['TotalAcceleration']))), lw=2))


fig.suptitle("Acceleration Event Plot")
fig.show()

Throw a bunch of lines at the wall and see what sticks. Most of the values fall between the ticks of 0.4 g and 1.99 g and that's moving pretty good. An average road vehicle would likely not see any of those outside of a crash (where it would see more).

It’s easier to read now even if it’s less dense. But you’ll note that the labels on the bottom left are:

  1. Huge. Sorry. There’s a lot of formatting that can be done here and I just took the W and kept going.
  2. Color-mapped to the value. That’s cool, right? Gives it some visual interest.

It’s a bit more involved than I would like to get this box of text on the plot (honestly) and it comes from that transform=ax.transAxes which allows you to place the box in the coordinate plane of the plot. There are other parameters that would normally allow you to do that but those would apply to label and not text because they’re sooo different. boxstyle is where you can apply, you guess it, box styles, to the boundary box (bbox). You can definitely use boundary boxes to put actual boundaries into your plot–that’s actually their purpose this is just hacky. The fc parameter is “face color” and that’s where we use the cmap object to apply norm to the average of the acceleration values over the lap. Bingo bango ha-ta-ta.

In the long run

This is just one of many ways to display this type of data. Is it the best way? That depends on what you’re objective is. My objective was to cheese my way into the next post. That one will be fun, I promise. Maybe. I thought it was particularly cool. I also came across an interesting little post on Gearing and the Force of Acceleration by Marc Haibeck which, aside from being interesting, projects a 485hp car with 4.10 gears on drag radials with no tire slip at 0.67 g of peak acceleration and traction does make all the difference. There was probably a better place for this but call it an Easter egg for reading all the way to the end.

Hi, this post was checked with vale which is a content-aware linter. It was checked using the Microsoft style as well as some rules that I made. A summary of those results is below. More details as to how this was put together check out this post. This post had: 51 errors, 126 warnings and 0 suggestions For details on the linting of this post
 ./content/posts/data-science-3-seeing-speed.md
 9:1       warning  Try to avoid using              Microsoft.We                 
                    first-person plural like                                     
                    'Let's'.                                                     
 9:218     warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 9:309     warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 9:453     warning  Consider removing 'very'.       Microsoft.Adverbs            
 9:459     warning  Consider removing 'very'.       Microsoft.Adverbs            
 9:799     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 9:813     warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 9:846     warning  Consider removing 'very'.       Microsoft.Adverbs            
 9:879     warning  ' highly-' doesn't need a       Microsoft.Hyphens            
                    hyphen.                                                      
 9:905     warning  Consider removing 'nearly'.     Microsoft.Adverbs            
 9:932     error    Use 'it's' instead of 'it is'.  Microsoft.Contractions       
 13:1      warning  Try to avoid using              Microsoft.We                 
                    first-person plural like                                     
                    'Let's'.                                                     
 16:14     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 18:9      error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 19:9      error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 20:9      error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 25:18     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 26:28     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 27:26     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 31:18     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 32:28     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 33:26     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 37:18     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 38:28     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 39:26     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 43:18     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 44:28     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 45:26     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 49:18     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 50:28     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 51:26     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 55:18     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 56:28     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 56:30     error    More than 3 commas!             marktoso.TresComas           
 57:26     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 61:17     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 62:28     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 63:26     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 67:17     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 68:28     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 69:26     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 73:17     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 74:28     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 75:26     error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 82:17     warning  Avoid using acronyms in a       Microsoft.HeadingAcronyms    
                    title or heading.                                            
 83:5      warning  Use first person (such as       Microsoft.FirstPerson        
                    'my') sparingly.                                             
 83:91     warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'We'.                               
 83:390    warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'us'.                               
 85:203    warning  Use first person (such as       Microsoft.FirstPerson        
                    'my') sparingly.                                             
 85:314    warning  Consider removing 'extremely'.  Microsoft.Adverbs            
 87:158    warning  Consider removing 'roughly'.    Microsoft.Adverbs            
 89:124    error    Use 'it's' instead of 'It is'.  Microsoft.Contractions       
 91:14     warning  Avoid using acronyms in a       Microsoft.HeadingAcronyms    
                    title or heading.                                            
 92:18     error    Use 'that's' instead of 'that   Microsoft.Contractions       
                    is'.                                                         
 92:313    warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 92:842    warning  Consider removing 'extremely'.  Microsoft.Adverbs            
 94:70     error    Use 'it's' instead of 'it is'.  Microsoft.Contractions       
 94:571    warning  Consider removing 'poorly'.     Microsoft.Adverbs            
 94:620    warning  Use first person (such as       Microsoft.FirstPerson        
                    'I'm') sparingly.                                            
 94:629    warning  Use first person (such as       Microsoft.FirstPerson        
                    'my') sparingly.                                             
 94:711    warning  Use first person (such as       Microsoft.FirstPerson        
                    'me') sparingly.                                             
 98:1      warning  Use first person (such as 'I    Microsoft.FirstPerson        
                    ') sparingly.                                                
 98:71     warning  Use first person (such as       Microsoft.FirstPerson        
                    'my') sparingly.                                             
 98:156    warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'US'.                               
 98:306    warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 98:611    warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 98:614    error    Use 'wasn't' instead of 'was    Microsoft.Contractions       
                    not'.                                                        
 100:272   warning  Consider removing               Microsoft.Adverbs            
                    'thoroughly'.                                                
 100:374   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 100:406   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 102:28    error    Use 'aren't' instead of 'are    Microsoft.Contractions       
                    not'.                                                        
 102:56    error    Use 'they're' instead of 'They  Microsoft.Contractions       
                    are'.                                                        
 108:71    warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 108:133   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 171:46    error    Use 'how's' instead of 'How     Microsoft.Contractions       
                    is'.                                                         
 171:126   error    In general, don't hyphenate     Microsoft.Auto               
                    'auto-formatted'.                                            
 171:201   error    More than 3 commas!             marktoso.TresComas           
 171:318   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 171:480   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 171:563   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 171:604   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 171:796   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 173:12    warning  Don't use end punctuation in    Microsoft.HeadingPunctuation 
                    headings.                                                    
 174:366   warning  Consider removing 'very'.       Microsoft.Adverbs            
 174:459   error    Don't spell out the number in   Microsoft.Units              
                    'of pixels'.                                                 
 174:613   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like                                     
                    'Let's'.                                                     
 174:685   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 219:87    warning  Consider removing 'really'.     Microsoft.Adverbs            
 221:5     error    Use 'what's' instead of 'What   Microsoft.Contractions       
                    is'.                                                         
 221:37    warning  Don't use end punctuation in    Microsoft.HeadingPunctuation 
                    headings.                                                    
 222:4     warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 222:104   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 222:120   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 222:187   error    Use 'wasn't' instead of 'was    Microsoft.Contractions       
                    not'.                                                        
 222:373   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 224:17    warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 224:73    warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 224:150   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 224:193   error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 224:269   warning  Consider removing 'easily'.     Microsoft.Adverbs            
 224:508   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 224:664   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 224:726   warning  Consider removing 'very'.       Microsoft.Adverbs            
 226:102   warning  Consider removing 'roughly'.    Microsoft.Adverbs            
 229:287   warning  Consider using 'all' instead    Microsoft.Wordiness          
                    of 'all of'.                                                 
 233:1     warning  Use first person (such as 'I    Microsoft.FirstPerson        
                    ') sparingly.                                                
 233:214   warning  Consider removing 'terribly'.   Microsoft.Adverbs            
 283:66    warning  Consider removing 'Very'.       Microsoft.Adverbs            
 285:8     warning  Avoid using acronyms in a       Microsoft.HeadingAcronyms    
                    title or heading.                                            
 286:1     warning  Use first person (such as 'I    Microsoft.FirstPerson        
                    ') sparingly.                                                
 286:30    warning  Consider removing 'very'.       Microsoft.Adverbs            
 286:364   warning  Consider removing 'very'.       Microsoft.Adverbs            
 286:787   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'We'.                               
 288:43    error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 288:124   warning  Consider removing               Microsoft.Adverbs            
                    'unfortunately'.                                             
 288:377   warning  Use first person (such as       Microsoft.FirstPerson        
                    'my') sparingly.                                             
 288:615   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 288:657   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like                                     
                    'our'.                                                       
 288:707   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like                                     
                    'our'.                                                       
 290:244   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'We'.                               
 290:308   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 290:347   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'We'.                               
 290:544   warning  Consider removing 'very'.       Microsoft.Adverbs            
 290:817   warning  Consider removing 'very'.       Microsoft.Adverbs            
 290:1029  warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'us'.                               
 292:1     warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'We'.                               
 292:156   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 292:384   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'We'.                               
 292:491   warning  Use first person (such as       Microsoft.FirstPerson        
                    'I'm') sparingly.                                            
 292:647   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 292:678   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 292:727   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 292:915   warning  Consider removing 'Really'.     Microsoft.Adverbs            
 292:928   warning  Consider using 'all' instead    Microsoft.Wordiness          
                    of 'all of'.                                                 
 292:991   warning  Consider removing 'really'.     Microsoft.Adverbs            
 292:1030  warning  Consider removing 'very'.       Microsoft.Adverbs            
 294:13    warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 294:124   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 294:612   error    Use 'we're' instead of 'we      Microsoft.Contractions       
                    are'.                                                        
 294:612   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 294:691   warning  Use first person (such as       Microsoft.FirstPerson        
                    'I'm') sparingly.                                            
 294:758   warning  Consider removing 'Really'.     Microsoft.Adverbs            
 296:4     warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 296:157   warning  Use first person (such as       Microsoft.FirstPerson        
                    'me') sparingly.                                             
 296:275   warning  Use first person (such as       Microsoft.FirstPerson        
                    'I'm') sparingly.                                            
 296:307   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 296:307   error    Use 'we're' instead of 'we      Microsoft.Contractions       
                    are'.                                                        
 296:433   warning  Use first person (such as       Microsoft.FirstPerson        
                    'I'm') sparingly.                                            
 299:1     warning  Use first person (such as 'I    Microsoft.FirstPerson        
                    ') sparingly.                                                
 299:162   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 299:198   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 299:340   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 299:504   error    Punctuation should be inside    Microsoft.Quotes             
                    the quotes.                                                  
 299:657   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 299:673   warning  Use first person (such as       Microsoft.FirstPerson        
                    'my') sparingly.                                             
 299:760   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 302:78    warning  Use first person (such as       Microsoft.FirstPerson        
                    'I'm') sparingly.                                            
 326:17    warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'us'.                               
 326:20    warning  Try to avoid using              Microsoft.We                 
                    first-person plural like                                     
                    'our'.                                                       
 326:348   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 326:508   warning  Consider removing 'roughly'.    Microsoft.Adverbs            
 326:533   warning  Consider removing 'very'.       Microsoft.Adverbs            
 328:143   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 328:165   warning  Use first person (such as       Microsoft.FirstPerson        
                    'me') sparingly.                                             
 328:189   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 328:236   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 330:154   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'We'.                               
 330:170   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 419:70    warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 422:30    warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 422:81    warning  Consider removing 'honestly'.   Microsoft.Adverbs            
 422:632   warning  Try to avoid using              Microsoft.We                 
                    first-person plural like 'we'.                               
 425:1     warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 425:123   warning  Use first person (such as       Microsoft.FirstPerson        
                    'My') sparingly.                                             
 425:150   warning  Use first person (such as       Microsoft.FirstPerson        
                    'my') sparingly.                                             
 425:200   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 425:256   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                
 427:210   warning  Use first person (such as ' I   Microsoft.FirstPerson        
                    ') sparingly.                                                

51 errors, 127 warnings and 0 suggestions in 1 file.