--- title: "NeuroGeometry: Analysing 3D morphology of neurons" author: "Gregory Jefferis" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{NeuroGeometry} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ## Introduction One of the key distinguishing features of nat is the ability to analyse neuronal morphology and connectivity from a geometric perspective. In other words nat provides functions to analyse the placement of neurons within the context of the brain and the organisation of local circuits. This vignette will give a few examples, but this is only skimming the surface of what is possible. If you see an analysis in a paper associated with the Jefferis lab but cannot figure out how to use nat to achieve this, then feel free to contact the [nat–user Google group](https://groups.google.com/d/forum/nat-user) to ask for help. ## Vertex information ```{r setup} library(nat) ``` One of the key tools for geometric work in nat is the `xyzmatrix` function, which extracts 3-D coordinate information from any object containing vertices. ```{r, message=FALSE, fig.width=6, fig.height=5} n=Cell07PNs[[1]] xyz=xyzmatrix(n) summary(xyz) plot(xyz[,c("X","Y")], type='p') ``` This also works for neuronlists, so we can extract all of the points in a collection of neurons: ```{r} xyz=xyzmatrix(Cell07PNs) ``` We could ask for all the points close to a specific X coordinate ```{r} close_to_x250=abs(xyz[,'X']-250)<10 table(close_to_x250) ``` We can also select points interactively by using the `rgl::select3d` function. ## Worked example - plane cutting a tract As a worked example let's try to find the plane cutting a tract defined by the axons of some example neurons: ```{r, fig.width=6, fig.height=5} plot(Cell07PNs, WithNodes=F) dist=10 abline(v=250, col='red') abline(v=c(250-dist, 250+dist), col='red', lty='dotted') ``` We could ask for all the points close to a specific X coordinate ```{r} close_to_x250=abs(xyz[,'X']-250)<10 table(close_to_x250) ``` Let's find the centroid of those selected points: ```{r, fig.width=6, fig.height=5} centroid=colMeans(xyz[close_to_x250,]) centroid plot(Cell07PNs, WithNodes=F) points(matrix(centroid[1:2],ncol=2), pch=20) ``` ### PCA to find tract vector Now let's do a principal components analysis on those points ```{r, fig.width=6, fig.height=5} pc=prcomp(xyz[close_to_x250,]) pc1=pc$rotation[,'PC1'] plot(Cell07PNs, WithNodes=F) points(matrix(centroid[1:2],ncol=2), pch=20) res=rbind(centroid-pc1*10, centroid, centroid+pc1*10) lines(res[,1:2]) ``` OK, perhaps it would be better if we only used the spine of the neurons ```{r} # There is a problem with one neuron with a loop, hence OmitFailures spines=nlapply(Cell07PNs, spine, UseStartPoint=T, OmitFailures = T) xyz=xyzmatrix(spines) close_to_x250=abs(xyz[,'X']-250)<10 table(close_to_x250) ``` ```{r, fig.width=6, fig.height=5} pc=prcomp(xyz[close_to_x250,]) pc1=pc$rotation[,'PC1'] plot(spines, WithNodes=F) points(matrix(centroid[1:2],ncol=2), pch=20) res=rbind(centroid-pc1*10, centroid, centroid+pc1*10) # nb 1:2 => just the xy coords lines(res[,1:2]) ``` ### Tract vector for each neuron Alternatively, we could find the vector of the first PC for each neuron. Let's write a function to do that and then apply it to the spine of each neuron. ```{r, fig.width=6, fig.height=5} # returns 6 vector # first 3 values are centroid # second three values first principal component tract_vector <- function(n, xval=250, thresh=10) { p=xyzmatrix(n) near=abs(p[,'X']-xval)