Tutorials with step-by-step guides and videos will be posted here.

Data handling

Directories, files and paths
Unstitching image of brain section tiles into multiple tiles
Stitching tiles


Image segmentation is the process of partitioning the digital image into subset of pixels which characterize features such as brain sections, cells, or processes.

Segmentation in WholeBrain can be done in two ways.



Make a custom atlas plate using Illustrator

Open up Adobe Illustrator and select File -> New....
In the document settings set up an ArtBoard with dimensions something like:
3440 x 2410 mm
Start drawing your atlas plate but at some point make sure that each unique shape is a unique layer (you can use color coded shapes to ease reference library later).
Also, make sure that the bottom layer is the outer hull of all the anatomical shapes in your atlas plate. To do this quickly simply mark the outer hull and right click and Arrange -> Send to back

Generate a web-based brain atlas

Given an image file path imagepath, a segmentation object seg, a registration object regi, and a dataset created by dataset<-get.cell.ids(regi, seg, forward.warps=TRUE)

#set pixel resolution in microns 
#name of channel imaged
protein <- "EGFP"
#make a web map output of your result
		registration = regi, 
		dataset = dataset, 
		scale = pixel.resolution, 
		fluorophore = protein

Process multiple sections with a pipeline.

This tutorial shows you how to process a set of images from an entire animal in a single folder.
It assumes that you have cut a brain into several coronal sections with a known spacing in micrometer between the sections.
Extending this pipeline to process through a bunch of animals is then trivial by having all animals in separate folders in the same experiment directory and looping across folders.

Here we have 56 single channel (gray scale) 16-bit TIFF images from a single animal that were cut at 50 microns but only every second was used for mounting and imaging and some sections were too damaged to be imaged but spacing is thus 100 micron in theory.

We begin by setting the path to our folder:

#set animal folder path

Get the images from the folder:

#set animal folder path

Make sure that the number of images make sense:

#check number of images in folder
[1] 56

Lets begin by declaring the 100 micron (0.1 mm) spacing between sections into a sampling period variable smp:

#set spacing between periods in millimeters

Next pick four different images far apart from eachother and manually inspect them for what coordinate they are at by comparing to www.openbrainmap.org (if your uncertain on how to navigate openbrainmap.org check out this video).
Here I opened image 13, 20, 32, 45. To get the path of these files just write:

#set images to manually assign position in the atlas.
inspected<-c(13, 20, 32, 45)
[1] "/Users/moskowitz/Documents/experiment/animal001/mouse001_013_FITC.tif"
[2] "/Users/moskowitz/Documents/experiment/animal001/mouse001_020_FITC.tif"
[3] "/Users/moskowitz/Documents/experiment/animal001/mouse001_032_FITC.tif"
[4] "/Users/moskowitz/Documents/experiment/animal001/mouse001_045_FITC.tif"

You can either open up these images by imshow(images[13]) or segment(images[13]) or alternatively just make a web-files in the current working directory (getwd()) for all of these for inspecting in your internet browser:

lapply(x=inspected, function(x){makewebmap(images[x])})

After inspection I decided that these four sections cooresponds to 1.1, 0.1, -1.0, -2.75 millimeter anterior-posterior from bregma:

#assign brain coordinates for inspected sections.
smp.coord<-c(1.1, 0.1, -1.0, -2.75) #brain coordinates based on bregma from openbrainmap.org

Notice that we assume that you have mounted and image all the sections in sequential order. That is either from the most anterior or posterior coordinate of the brain. This is good practice to do so and will minimize work on organizing your data.
Now we can just generate all the intermediate coordiantes automatically with the map.to.atlas() function:

#assign brain coordinates for all sections in this brain.

Verify by writing coord into the console and press enter:

[1]  2.40000000  2.29166667  2.18333333  2.07500000  1.96666667
[6]  1.85833333  1.75000000  1.64166667  1.53333333  1.42500000
[11]  1.31666667  1.20833333  1.10000000  1.00000000  0.85000000
[16]  0.70000000  0.55000000  0.40000000  0.25000000  0.10000000
[21]  0.00000000 -0.09090909 -0.18181818 -0.27272727 -0.36363636
[26] -0.45454545 -0.54545455 -0.63636364 -0.72727273 -0.81818182
[31] -0.90909091 -1.00000000 -1.10000000 -1.23750000 -1.37500000
[36] -1.51250000 -1.65000000 -1.78750000 -1.92500000 -2.06250000
[41] -2.20000000 -2.33750000 -2.47500000 -2.61250000 -2.75000000
[46] -2.65000000 -2.55000000 -2.45000000 -2.35000000 -2.25000000
[51] -2.15000000 -2.05000000 -1.95000000 -1.85000000 -1.75000000
[56] -1.65000000

Next we set a filter we want to use for segmentation of cell bodies and brain section outline:

myfilter<-structure(list(alim = c(22, 118), threshold.range = c(20268, 35020), eccentricity = 500L, Max = 50000, Min = 2000, brain.threshold = 2026,
resize = 0.04, blur = 4, downsample = 0.25), .Names = c("alim",
"threshold.range", "eccentricity", "Max", "Min", "brain.threshold",
"resize", "blur", "downsample"))

Then we will set up all our data output using the first section:

#Do first section
i = 1
seg<-segment(images[i], filter = myfilter, display=FALSE)
regi<-registration(images[i], coordinate=coord[i], filter = myfilter, display=FALSE)
dev.copy(pdf, paste0(tools::file_path_sans_ext(basename(images[i])), '.pdf'))
dataset<-inspect.registration(regi, seg, soma = TRUE, forward.warps = TRUE, batch.mode = TRUE)
save(file=paste0(tools::file_path_sans_ext(basename(images[i])), '.RData'), seg, regi, dataset)
#use datasets to rbind all dataset to.

#loop through the rest and append them
for(i in seq_along(images)[-1]){
  seg<-segment(images[i], display=FALSE, filter = myfilter)
  regi<-registration(images[i], coordinate=coord[i], display=FALSE, filter = myfilter)
  dev.copy(pdf, paste0(tools::file_path_sans_ext(basename(images[i])), '.pdf'))
  dataset<-inspect.registration(regi, seg, soma = TRUE, forward.warps = TRUE, batch.mode = TRUE)
  save(file=paste0(tools::file_path_sans_ext(basename(images[i])), '.RData'), seg, regi, dataset)
  datasets<-rbind(datasets, dataset)

Then at the end lets add the unique animal ID:

#save animal ID.

And save the data frame to a unique .RData file.

save(datasets, file = 'mouse001.RData')

Next, you can try yourself to nest this loop over multiple animals and rbind() together with individual animals to a master.dataset.

Fitting statistical models



Data-driven whole-brain cell count plot

3D glass brain plot

Bar graph of selected regions using ggplot2

Say that you have a data set with 8 animals in each experimental group (e.g. WT and KO). Sometimes you have a very specific hypothesis to test and then a whole-brain graph might dilute your message. In these cases a standard split-plot or ANOVA styled bar graph is common and ggplot2 is a very popular package in R for making all sorts of graphs.

Lets say that we are here interested in comparing the cell count in thalamus (TH) versus motor areas (MO) in cortex.


Begin by extracting a tidy data frame of cell counts for the regions on interests (ROIs):

#get cell counts for region of interests.
data<-roi.cell.count(dataset, rois=c('TH','MO'))

Let us examine the output of this command by printing the first 6 rows into the console by the head() function:

#view the first 6 rows of the ROI data.
> head(data)
  acronym    animal cell.count
1      TH R0057A317        690
2      MO R0057A317        382
3      TH R0057A319        960
4      MO R0057A319        476
5      TH R0057A322       1621
6      MO R0057A322       3391

As you can see we have three variables: "acronym", the acronym of each brain region, "animal", the ID for each animal, "cell.count", the number of cells in that region for that animal.

We are now going to add the information related to what group each animal belongs to:

'R0057A345','R0057A346', 'R0057A347', 

group<-c('KO' , 'KO' , 'WT' , 'KO' , 'KO' , 'WT'  , 'KO'
, 'WT' , 'KO' , 'WT' , 'KO' ,'WT' , 'KO' ,'WT' 
, 'WT' , 'WT' , 'WT' , 'KO')

data <- add.group(data, subjectID=id, group=group)
#replace group name with genotype
data<-rename(data, c("group" = 'genotype'))

Lets calculate the average statistic and standard error for our 2 x 2 design (region x genotype):

df1<-data.summary(data, varname='cell.count', groupnames=c('acronym','genotype'))
#replace acronym name with brain region
df1<-rename(df1, c('acronym' = 'region'))
#view df1
  region genotype cell.count      err
1     MO       KO   320.2963 308.1244
2     MO       WT   613.5926 607.1180
3     TH       KO   225.4815 141.0244
4     TH       WT   317.9259 259.2605

Lets now plot df1 as a bar graph using ggplot2:

p <- ggplot(df1, aes(x=region, y=cell.count, fill=genotype)) + 
   geom_bar(stat="identity", position=position_dodge()) +
  geom_errorbar(aes(ymin=cell.count-err, ymax=cell.count+err), width=.2,
p + scale_fill_brewer(palette="Paired") + theme_minimal()


Code used in this tutorial: (click to expand)

Updating to latest version of wholebrain AND how to stitch multiple sections

Directly navigate this video tutorial (click on link and then press play on the video):

  1. Jump to: update wholebrain R package | 00:36
  2. Jump to: stitch.animal() command | 03:05
Part I:

#Uninstall anything still remaining of old wholebrain R package.
#importantly quit R before reinstalling the wholebrian package.
#check if devtools is installed by trying to load it. 
#if not then install devtools.
#Devtools is needed to install packages from Github.
if (!require(devtools)) { install.packages("devtools") }
#intall wholebrain from Github. 
#devtools:: calls the command install_github directly from devtools.
# "::" calls functions directly without loading entire library. 

Part II:

#load the wholebrain R package
#assign a folder path
#run stitch.animal command

Also tryout:

#set optional flags 
# to turn off or on Flat-Field Correction or web.map
stitch.animal(folder, FFC=FALSE, web.map=TRUE)
#add a rotation vector
# that specifies which image should be rotated.
# negative means counter clockwise.
rotation<-c(0, -90, 45, 10) # four different images
stitch.animal(folder, rotate=rotation)
Code used in this tutorial: (click to expand)