Density Plot "Heatmap" Using R

This tutorial describes how users can interact with the track data provided in their Actual report to produce a plot showing the relative amount of time occupied across spatial regions (indicated visually by a scaling of colours).

We follow on from the previous tutorials where we showed how to load experiment data tracking data from individual trial files and to perform basic visualization. Here we look at a more useful way of adding multiple data-sets to produce a more informative display. The crucial difference with this type of visualization is that an image is produced - not just a collection of lines and points. This requires us to convert data points into actual pixel values.

Fundamentally, in this tutorial, the assumption is that each of the trials has exactly the same dimensions of arena and layout - so that they can be aligned correctly (particularly in relationship to any zones). If there are no zones and the arenas are different sizes, then the data is aligned simply by the origin located in the top left corner.

[Footnote: Aligning the data by zones would be possible by calculating the centroids of each zone region and using these to perform Procrustes alignment - in this way scaling, translational and rotational components between trials are minimised. We will tackle this issue in a later tutorial.]

Installing Additional Packages

The ability to install additional packages for R is required, since we generate our plots using the "spatstat" package for the statistical analysis of spatial point patterns. This is most easily achieved by invoking the "Package Installer" using the R GUI - and searching for "spatstat" (version 1.21-2). The packages "deldir" and "mgcv" may also be installed in the same way. Alternatively, typing (on the R console):

> install.packages()

will allow the user to select these packages to install from the command line.

We may then need to tell R to load the package, so that the methods it provides can be used. For this the require command indicates a package to load (and will also pull in any dependancies):

> require(spatstat)
Loading required package: spatstat
Loading required package: mgcv
This is mgcv 1.6-2. For overview type 'help("mgcv-package")'.
Loading required package: deldir
deldir 0.0-13
Please note: The process for determining duplicated points
has changed from that used in version 0.0-9 (and previously).
spatstat 1.21-2
Type 'help(spatstat)' for an overview of spatstat
'latest.news()' for news on latest version
'licence.polygons()' for licence information on polygon calculations

Restructuring Data into an Image

To create a density (heatmap) plot version of this we have to effectively enumerate the occurrence of these points at each discrete location in the image. This is done by setting a up a grid and counting the number of times a point coordinate "falls" into each of the individual pixel "bins" at every location in that grid.

To do this, we first create a "point pattern" dataset object from our body data (), and specifying the maximum and minimum values along each axis:

> points <- ppp(body[,1],body[,2],c(min(body[,1]),max(body[,1])),c(min(body[,2]),max(body[,2])))
Warning message:
In ppp(body[, 1], body[, 2], c(min(body[, 1]), max(body[, 1])), :
data contain duplicated points

Note that this warning message about "duplicated points" is acceptable - since we are intentionally giving the function multiple occurrences of the same point to count.

We then set the sampling size (i.e. number of bins along each axis) for our regularly sampled grid:

> spatstat.options(npixel=c(100,100))

Now, we convert the point pattern object to an image map object with the function:

> map <- pixellate(points)

This does the hard work of actually binning and adding up the cumulative points that occur at each grid location. We now can view the result with:

> image(map)

As shown in Figure 1. This is perhaps not very clear (just yet) where the true density/distributions of points lie (especially for just one trial). We can address this by loading more data and enhancing the distribution of the colorspace, as described below.

Heatmap

Figure 2: Output of conversation of points to pixellated grid image (using default color map).

Adding More Data

If we want to add data from multiple trials to this plot, and so reveal more telling information, this can most easily be done by appending new x and y coordinate values to the existing objects. We load in the new trial with the same command, but different file, as follows:

> trial2 <- read.csv(file="Trial_2_Data.csv",head=TRUE,sep=",")

And then by creating and binding the new data with the old using the rbind function:

> body2 <- matrix(c(trial$BodyCenter_X..cm,-trial2$BodyCenter_Y..cm),length(times),2)
> allbody <- rbind(body,body2)

This adds the new trials points to the existing one (making it almost twice as long) as proven by:

> dim(allbody)
[1] 12000 2

This same operation can be repeated for all the data sets. Indeed, the rbind function can take any number of matrices to combine. e.g:

> allbody <- rbind(body, body2, body3, body4, body5, body6)

Plotting More Clearly

For clarity, we could also define our own colors, and to scale the lower end of the color range to show more detail. This can be done with:

> Lab.palette <- colorRampPalette(c("blue", "magenta", "red", "yellow", "white"), bias=2, space="Lab")

in order to create a new color palette object, in the Lab color space, which goes from "blue" through to the other colors to "white", and which has a lower spectrum bias of 2.

Reducing the resolution of the pixel "bins" can also assist visualisation, for example:

> spatstat.options(npixel=c(50,50))

To finally plot (as seen in Figure 2), we then convert all the points again to an image - and additionally provide a more meaningful title:

> points <- ppp(allbody[,1],allbody[,2],c(min(allbody[,1]),max(allbody[,1])),c(min(allbody[,2]),max(allbody[,2])))
> map <- pixellate(points)
> image(map,col=Lab.palette(256),main="Cumulative Visits to Spatial Location")

Cumulative Visits to a Spatial Location

Figure 2: Example spatial density plot produced with R.