Jerk: A Way to Emphasize Rapid Changes in Acceleration

Usage

For the full theoretical description, refer to the njerk() technical explanation.

MATLAB
J = njerk(A,fs)
R
J <- njerk(A, sampling_rate)
Inputs
  • A: A sensor data structure or an nx3 acceleration matrix with columns [ax ay az]. A can be in any consistent unit, e.g., g or m/s^2. A can be in any frame as the norm-jerk is rotation independent. A must have at least 2 rows (i.e., n>=2) and be regularly sampled.
  • fs: The sampling rate of the sensor data in Hz (samples per second). This is only needed if A is not a sensor structure.
Outputs
  • j: is the norm jerk, a column vector with the same number of rows as in A , or a tag sensor data structure (if the input A was one). The norm-jerk is ||dA/dt||, where ||x|| is the 2-norm of x, i.e., the square-root of the sum of the squares of each axis. If the unit of A is m/s^2, the norm-jerk has unit m/s^3. If the unit of A is g, the norm-jerk has unit g/s. As j is the norm of the jerk, it is always positive or zero (if the acceleration is constant). The final value in j is always 0 because the last finite difference cannot be calculated.
Theoretical Description

Rapid muscle movements which could be associated with strikes at prey, ingestion, predator detection and avoidance, sound production, breathing, heart-beat and many other important activities that we would like to detect reliably could be detected calculating the jerk. For the full theoretical description, refer to the njerk() technical explanation.

Technical Description

The jerk is the differential (i.e., the rate of change) of acceleration and has units m/s3. Taking the differential emphasises the fast-changing parts of a signal and de-emphasises the slow-changing parts. Thus, jerk is a great way to emphasise smaller-but-sharper components in the accelerometer data possibly associated with rapid muscle movements.

Caveats

Jerk is not generally a good measure of activity because it de-emphasises steady powerful movements such as locomotion. For the full caveats description, refer to the njerk() technical explanation.


Load and Visualize the Test Data Set

For this practical we will use data from a suction cup tag attached to the back of a beaked whale [Note]This dataset has already been converted from a source file that was offloaded from the tag into a NetCDF file. In doing so, some metadata was gleaned from the file and added to the data. Other metadata was added by hand.. The same one as in dsf tutorial. This dataset is built into the tagtools package, so you can access it using system.file

MATLAB
bw_file_path = xxx
bw = load_nc(bw_file_path)
R
bw_file_path <- system.file("extdata", "testset1.nc", package = 'tagtools', mustWork = TRUE)
bw <- load_nc(bw_file_path)

Then use plott() to inspect it:

MATLAB
figure
plott(bw.P, bw.A, bw.M)
subplot(311)
ylabel('Depth')
subplot(312)
ylabel('Acc')
subplot(313)
ylabel('Mag')
legend({'x-axis','y-axis','z-axis'})
R
plott(X = list(Depth = bw$P, Acc = bw$A, Mag = bw$M))
MATLAB Output
R Output

This dataset contains a deep dive followed by a shallow dive. We want to infer the function of these by looking for locomotion effort and sudden changes in acceleration that could be indicative of prey capture attempts. We are also going to look for changes in swimming gait

Acceleration transients, jerk and dynamic acceleration

We want to look for indications of foraging during the two dives. Sudden changes (transients) in acceleration are often associated with prey capture attempts. One way to emphasise rapid changes in acceleration is by differentiating it to produce the jerk.

This is effectively high-pass filtering acceleration with a constantly-sloping filter—the higher the frequency, the more it is emphasised. Because we don’t know what kind of movement is involved in a prey capture attempt, we don’t know which axis of acceleration will be most relevant. It is safer then to just compute the magnitude of the jerk in all three axes to get a single vector (also called “norm-jerk”). That way, a peak in any or all axes will show up. njerk() function computes this from acceleration. Try running njerk() on our acceleration data and writing the result to J. Then, once you also grab the sampling rate, you can plot this jerk data.

MATLAB
J = njerk(bw.A)
fs = bw.A.sampling_rate

figure
plott(bw.P.data, fs, J, fs)
subplot(211)
ylabel('Depth')
axis ij
subplot(212)
ylabel('Jerk')
R
J <- njerk(bw$A)
fs <- bw$A$sampling_rate
plott(X = list(Depth = bw$P$data, Jerk = J), fsx = fs)
MATLAB Output
R Output

The largest jerk transients appear mostly at the bottom of the deeper dive.

Check out some of the biggest peaks to see how short they are.

Effects of Sampling Rate on jerk

The size and clarity of the jerk peaks depends on the sampling rate. We are using 25 Hz data. To see what you would get with 5 Hz data, try decimating the acceleration before computing the jerk:

MATLAB
bw.A % look at the data before decimation
Ad = decdc(bw.A, 5) % decimate by 5 times. New sampling rate is 25/5 Hz
bw.Ad % look at the data after decimation
R
str(bw$A, max.level = 1) # look at the data before decimation
Ad <- decdc(bw$A, 5) # decimate by 5 times. New sampling rate is 25/5 Hz
str(Ad, max.level = 1) # and after decimation

Compute the decimated jerk from the decimated acceleration, and plot it with the jerk computed from the full bandwidth acceleration:

MATLAB
Jd = njerk(Ad)
fsd = bw.Ad.sampling_rate 

figure
plott(bw.P.data, fs, J, fs, Jd, fsd)

subplot(311)
ylabel('Depth')
axis ij
subplot(312)
ylabel('Jerk')
subplot(313)
ylabel('Jerk dec')
R
Jd <- njerk(Ad)
plott(X = list(Depth = bw$P$data, `25 Hz Jerk` = J, `5Hz Jerk` = Jd),
      fsx = c(fs, fs, fs/5))
MATLAB Output
R Output

Check out some of the obvious peaks around minute 20 to minute 30 to have a look at the ‘signal-to-noise’ in the jerk transients.

Jerk transients are clearer in the original data rate. This is an indication that the frequency content in the transients is higher than 5Hz.

Detecting Jerk Peaks

To find potential prey capture attempts, we need to run a detector on the norm-jerk signal. Although it is easy to see peaks by eye in the data, detectors require some information to do a good job: they need to know the threshold above which a peak is really a peak and the blanking time, i.e., the minimum time that must elapse after a detection before another detection can happen.

The tagtools toolbox includes interactive peak detectors, detect_peaks() function, that allow you to choose a threshold and see the effect this has on which transients are detected. We will use a blanking time of 5s, i.e., we expect that the shortest time between prey captures is 5s, the rest of the inputs will be set as default, i.e., []:

MATLAB
peaks = detect_peaks(J, fs,[], [], 5, [], [])
xlabel('Time (1/sampling rate)')
ylabel('Signal Power')
R
pks <- detect_peaks(J, fs, bktime = 5)  # 5s blanking time, threshold is interactive
MATLAB Output
R Output

Follow the instructions in the console to change the threshold. You need to pick a threshold that excludes most of the jerk transients during the strong propulsion locomotion in the ascent but that still detects most of the jerk transients during the bottom part of the deep dive. (Balancing false detections and missed detections is often not easy in a detector and is a matter of finding a trade-off that works for your application.) In the figure given, we’ve set the threshold to 100.

This function returns a list of information about the detected peaks. For each detection, the start and end times are reported (in seconds), along with the time at which the peak occurred and the height of the peak. Finally, the selected threshold and blanking time are reported. You can plot the height and time of each detection along with the dive profile as follows:

MATLAB
figure
plott(bw.P)
plot(peaks.peak_time/fs/60,bw.P.data(round(peaks.peak_time)),'go')
ylabel('Depth, m')
R
plott(X = list(Depth = bw$P))
# note: the code below assumes your plott x-axis is in hours.
# if it were in minutes use /60 instead of /3600, etc.
points(pks$peak_time/fs/3600, bw$P$data[round(pks$peak_time)], pch = 8)
MATLAB Output
R Output

Common Questions

Yes during the deep dive, but not during the shallow dive.

We know now that the whale is likely not foraging in the shallow dive, since the sudden movements (jerk peaks) are happening only in the earlier dive. Additionally, though the animal is not accelerating quickly (striking/flinching), it is still moving (locomotion). So it seems more likely to be traveling than resting.

Further Resources

You’ve learned how to accentuate quick movements of an animal using jerk, and used the accentuated picture to gain understanding about the animal’s behaviour.

For a more in-depth explanation of the usage and inner workings of the njerk() tool, refer to the Technical Explanation of jerk.