The coefficient of restitution, $C_\mathrm{R}$, of a ball dropped vertically onto a surface is the ratio of the ball's speed just before it hits the surface to its speed immediately after it bounces back from it. If the ball is dropped from a height $h_0$ above the surface, it is easy to show that it will be travelling with speed $v_0 = \sqrt{2g/h_0}$ when it hits; its speed as it bounces back up will then be $v_1 = C_\mathrm{R}v_0$.

More generally, the upward speed of the ball after the $n$th bounce is: $$ v_{n+1} = v_n C_\mathrm{R}^n. $$

An experiment to measure $C_\mathrm{R}$, assuming it is independent of the ball's speed, may be conducted as follows. Drop the ball from a height $h_0$ at time $t=0$ and record the sound of the ball hitting the surface over a number of bounces. The time between the bounce events is then $$ T_n = T_0 C_\mathrm{R}^n, $$ (show this), where $T_0 = 2v_0/g$. Then $$ \ln T_n = n\ln C_\mathrm{R} + \ln T_0, $$ and so a plot of $\ln T_n$ against $n$ should be a straight line with gradient $\ln C_\mathrm{R}$.

The data file `bounce-data.txt`

is a text-version of the recording of an experiment carried out as described above, with a sampling frequency of $4410\;\mathrm{s^{-1}}$ (*i.e.* data points are separated by $1/4410\;\mathrm{s}$). Analyse these data to find a value for $C_\mathrm{R}$. If $h_0 = 57.5\;\mathrm{cm}$, what is the value of $g$ inferred from the intercept?

The following program gives $CR = 0.86$ and $g = 9.7\;\mathrm{m\,s^{-1}}$.

```
import numpy as np
import pylab
data = np.loadtxt('bounce-data.txt')
fs = 4410 # sample rate (s-1)
n = len(data)
# Set up a time-grid
t = np.linspace(0, float(n)/fs, n)
# When the signal reaches <thresh>, count a bounce...
thresh = 0.05
# then skip the next <width> data points which are the sound of the bounce
width = 700
# make a list of bounce event times
bounce_time = []
i = 0
while i < n:
if data[i] > thresh:
bounce_time.append(t[i])
i += width
i += 1
# create a numpy array of the bounce time intervals
T = np.empty(len(bounce_time)-1)
for i in range(len(T)):
T[i] = bounce_time[i+1] - bounce_time[i]
# we want to plot ln(T) vs n where n is the bounce number
lnT = np.log(T)
n = np.linspace(0, len(lnT)-1, len(lnT))
# set up the linear equations lnT = m.n + c as the matrix
# equation lnT = Ap where p is (m, c)
A = np.vstack([n, np.ones(len(n))]).T
# find the "best" values of m, c by linear least squares fit
m, c = np.linalg.lstsq(A, lnT)[0]
# we're done: calculate CR and g from m and c
CR = np.exp(m)
T0 = np.exp(c)
h0 = 0.575
g = 8.*h0/T0**2
print(CR, g)
# finally, plot the data and best fit line
pylab.plot(n, lnT, 'o', label='obs')
pylab.plot(n, m*n+c, 'r', label='fit')
pylab.legend()
pylab.show()
```