Here we will step through some of the new visualization tools built into RMINC 1.3. So, let’s start with getting a dataset ready - we’ll look at sex differences in the brain.

# load libraries
library(RMINC)
## Warning in rgl.init(initValue, onlyNULL): RGL: unable to open X11 display
## Warning: 'rgl_init' failed, running with rgl.useNULL = TRUE
library(plotrix) # for legends

# some weirdness potentially particular to my mac. Images are flipped, so fix that:
options(RMINC_flip_image=TRUE)

# load an existing dataset
load("~/data/CREB/CREB-analyses/wtonly.RData")
table(gfwt$Sex)
## 
##  F  M 
## 38 42
mask <- "/Users/jason/data/CREB/mask.mnc"

Let’s start by running a linear model testing the effect of sex on local brain volume.

vs <- mincLm(relJac02 ~ Sex, gfwt, mask=mask)
## Method: lm
## Number of volumes: 80
## Volume sizes: 201 439 298
## N: 80 P: 2
## In slice 
##  0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99  100  101  102  103  104  105  106  107  108  109  110  111  112  113  114  115  116  117  118  119  120  121  122  123  124  125  126  127  128  129  130  131  132  133  134  135  136  137  138  139  140  141  142  143  144  145  146  147  148  149  150  151  152  153  154  155  156  157  158  159  160  161  162  163  164  165  166  167  168  169  170  171  172  173  174  175  176  177  178  179  180  181  182  183  184  185  186  187  188  189  190  191  192  193  194  195  196  197  198  199  200 
## Done

And we take a look

# first step - load the background anatomy
anatVol <- mincGetVolume("/Users/jason/data/CREB/21aug15_est_conserv-nlin-3.mnc")
## Start: 0 0 0
## Count: 201 439 298
# and a series of slices through the brain
mincPlotSliceSeries(mincArray(anatVol),           # the anatomical volume
                    mincArray(vs, "tvalue-SexM"), # pull out one column of the stats
                    anatLow=700, anatHigh=1400,   # set anatomy thresholds
                    low=2.5, high=10,             # set stats thresholds
                    symmetric=T)                  # show separate upper and lower

This introduces the first, and one of the most useful, of the visualization functions: mincPlotSliceSeries. It does what the name claims - shows a series of slices through the brain, in this case overlaying the mincLm results on the average anatomy background. Before proceeding, one note: mincArray is called for both the anatomical volume and the stats; for the moment it’s a shortcut to add dimension information to each volume. Future versions of RMINC will likely get rid of that and store the necessary information right after outputs are created by the likes of mincLm.

Anyway, let’s make the plot a bit prettier: there are too many slices at the beginning and end that show no useful info, so let’s get rid of them.

mincPlotSliceSeries(mincArray(anatVol),           # the anatomical volume
                    mincArray(vs, "tvalue-SexM"), # pull out one column of the stats
                    anatLow=700, anatHigh=1400,   # set anatomy thresholds
                    low=2.5, high=10,             # set stats thresholds
                    symmetric=T,                  # show separate upper and lower
                    begin=50, end=-90)            # remove slices from both sides      

Looks prettier already. But it would help to have an indication of where the slices are and what the colours represent. So let’s add that:

mincPlotSliceSeries(mincArray(anatVol),           # the anatomical volume
                    mincArray(vs, "tvalue-SexM"), # pull out one column of the stats
                    anatLow=700, anatHigh=1400,   # set anatomy thresholds
                    low=2.5, high=10,             # set stats thresholds
                    symmetric=T,                  # show separate upper and lower
                    begin=50, end=-90,            # remove slices from both sides  
                    legend="t-statistics")                    

And let’s show the other dimensions:

mincPlotSliceSeries(mincArray(anatVol),           # the anatomical volume
                    mincArray(vs, "tvalue-SexM"), # pull out one column of the stats
                    anatLow=700, anatHigh=1400,   # set anatomy thresholds
                    low=2.5, high=10,             # set stats thresholds
                    symmetric=T,                  # show separate upper and lower
                    begin=35, end=-35  ,          # remove slices from both sides  
                    legend="t-statistics",
                    dimension = 1)  

mincPlotSliceSeries(mincArray(anatVol),           # the anatomical volume
                    mincArray(vs, "tvalue-SexM"), # pull out one column of the stats
                    anatLow=700, anatHigh=1400,   # set anatomy thresholds
                    low=2.5, high=10,             # set stats thresholds
                    symmetric=T,                  # show separate upper and lower
                    begin=25, end=-25  ,          # remove slices from both sides  
                    legend="t-statistics",
                    dimension = 3)  

Let’s do something fancier - or at least requiring more customization. Let’s create a slice showing the estimated effect (i.e. the beta) with the significant regions contoured.

The core function underlying it all is mincImage. So we begin by putting together the plot with a simple rendition of the underlying anatomy.

mincImage(mincArray(anatVol), slice=250)

A good start, but the axes are quite unnecessary, so let’s get rid of them.

mincImage(mincArray(anatVol), slice=250, axes=F)

And let’s return to a cleaner setting of thresholds:

mincImage(mincArray(anatVol), slice=250, axes=F, low=700, high=1400)

Now we add the beta coefficients on top.

mincImage(mincArray(anatVol), slice=250, axes=F, low=700, high=1400)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=0.02, high=0.1, add=T, col=heat.colors(255), underTransparent = T)

Starting to look good, but we’ll want slighty different colours and both the positive and the negative effects shown:

poscolours = colorRampPalette(c("red", "yellow"))(255)
negcolours = colorRampPalette(c("blue", "turquoise1"))(255)

mincImage(mincArray(anatVol), slice=250, axes=F, low=700, high=1400)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=0.02, high=0.1, add=T, col=poscolours, underTransparent = T)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=-0.02, high=-0.1, add=T, col=negcolours, underTransparent = T)

This slice shows any effects above (or below) a log jacobians of 0.02. Is any of that significant? Let’s find out via FDR.

mincFDR(vs, mask=mask)
## 
## Computing FDR threshold for all columns
## Start: 0 0 0
## Count: 201 439 298
##   Computing threshold for  F-statistic 
##   Computing threshold for  tvalue-(Intercept) 
##   Computing threshold for  tvalue-SexM
## Multidimensional MINC volume
## Columns:       F-statistic tvalue-(Intercept) tvalue-SexM 
## NULL
## Degrees of Freedom: c(1, 78) 78 78 
## FDR Thresholds:
##      F-statistic tvalue-(Intercept) tvalue-SexM
## 0.01   12.720632           2.830987    3.569582
## 0.05    7.627336           2.159808    2.763280
## 0.1     5.579595           1.821244    2.363340
## 0.15    4.411686           1.601513    2.101459
## 0.2     3.597821           1.432507    1.897762

Sure enough, there is. So let’s add contours to where we have significance.

poscolours = colorRampPalette(c("red", "yellow"))(255)
negcolours = colorRampPalette(c("blue", "turquoise1"))(255)

mincImage(mincArray(anatVol), slice=250, axes=F, low=700, high=1400)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=0.02, high=0.1, add=T, col=poscolours, underTransparent = T)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=-0.02, high=-0.1, add=T, col=negcolours, underTransparent = T)
mincContour(abs(mincArray(vs, "tvalue-SexM")), slice=250, levels=c(2.36, 3.57), add=T)

We’ve added lines for 10% and 1%; let’s label them and make them easier to distinguish:

poscolours = colorRampPalette(c("red", "yellow"))(255)
negcolours = colorRampPalette(c("blue", "turquoise1"))(255)

mincImage(mincArray(anatVol), slice=250, axes=F, low=700, high=1400)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=0.02, high=0.1, add=T, col=poscolours, underTransparent = T)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=-0.02, high=-0.1, add=T, col=negcolours, underTransparent = T)
mincContour(abs(mincArray(vs, "tvalue-SexM")), slice=250, levels=c(2.36, 3.57), 
            labels=c("10%", "1%"), lty=c(2,1), add=T)

Fairly pretty, but I’d rather have the labels in a legend rather than on the image itself. Doable:

poscolours = colorRampPalette(c("red", "yellow"))(255)
negcolours = colorRampPalette(c("blue", "turquoise1"))(255)

mincImage(mincArray(anatVol), slice=250, axes=F, low=700, high=1400)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=0.02, high=0.1, add=T, col=poscolours, underTransparent = T)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=-0.02, high=-0.1, add=T, col=negcolours, underTransparent = T)
mincContour(abs(mincArray(vs, "tvalue-SexM")), slice=250, levels=c(2.36, 3.57), 
            drawlabels=F, lty=c(2,1), col="white", add=T)
legend(200, 200, c("10% FDR", "1% FDR"), lty=c(2,1), col="white",
       text.col="white", bg="black", bty="n")

Still missing the colour bars - let’s add those to the bottom. This will also need some mucking about with the par plot settings to get the whole background to be black and pretty.

poscolours = colorRampPalette(c("red", "yellow"))(255)
negcolours = colorRampPalette(c("blue", "turquoise1"))(255)
graycolours = gray.colors(255)

opar <- par(bg=graycolours[1]) # set the background to be the same colour as the under colour

mincImage(mincArray(anatVol), slice=250, axes=F, low=700, high=1400, col=graycolours)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=0.02, high=0.1, add=T, col=poscolours, underTransparent = T)
mincImage(mincArray(vs, "beta-SexM"), slice=250, low=-0.02, high=-0.1, add=T, col=negcolours, underTransparent = T)
mincContour(abs(mincArray(vs, "tvalue-SexM")), slice=250, levels=c(2.36, 3.57), 
            drawlabels=F, lty=c(2,1), col="white", add=T)
legend(200, 200, c("10% FDR", "1% FDR"), lty=c(2,1), col="white",
       text.col="white", bg="black", bty="n")
color.legend(20, -20, 130, 0, c("-0.1", "-0.02"), rev(negcolours), col="white", align="rb")
color.legend(170, -20, 280, 0, c("0.02", "0.1"), poscolours, col="white", align="rb")

# restore the old settings
par(opar)