General Introduction

Today we will briefly introduce some geomorph functions for performing the analyses described yesterday. Note: You should be able to read in your data and perform the analyses from yesterday! Thus this tutorial augments the ‘next steps’ of a morphometric analysis (i.e., we are beginning to flesh out the steps of the Procrustes Paradigm for geometric morphometric analyses).

1: Generalized Procrustes Analysis (GPA) with Sliding Semilandmarks

Below is a simple 2D example containing points and curves. For 3D we could add curves and/or surfaces (see help file)

data(hummingbirds)
hummingbirds$curvepts   
##       before slide after
##  [1,]      1    11    12
##  [2,]     11    12    13
##  [3,]     13    14    15
##  [4,]      7    15    14
##  [5,]     12    13    14
##  [6,]      1    16    17
##  [7,]     16    17    18
##  [8,]     17    18    19
##  [9,]     18    19    20
## [10,]     10    20    19
## [11,]      2    21    22
## [12,]     21    22    23
## [13,]     22    23    24
## [14,]     23    24    25
## [15,]      8    25    24
gpa.BE <- gpagen(hummingbirds$land, 
                 curves = hummingbirds$curvepts, 
                 ProcD=FALSE, 
                 print.progress = F)
plot(gpa.BE)

gpa.procD <- gpagen(hummingbirds$land, 
                    curves = hummingbirds$curvepts, 
                    ProcD=TRUE, print.progress = F)
plot(gpa.procD)

NOTE: For StereoMorph users, the notation is slightly different for specifying curves (see help file):
shapes <- StereoMorph::readShapes("Data/example.digitized")
shapesGM <- readland.shapes(shapes, 
  nCurvePts = c(12, 12, 12, 8, 6, 6, 6, 12, 10))

Y.gpa <- gpagen(shapesGM, 
                print.progress = FALSE)
plot(Y.gpa)

2: Partial Least Squares (PLS)

Here is a simple example of partial least squares:

data("plethShapeFood")
Y.gpa <- gpagen(plethShapeFood$land,
                print.progress = FALSE)

food <- plethShapeFood$food

rownames(food) <- names(Y.gpa$Csize) # just to assure match

PLSfood <- two.b.pls(food, Y.gpa$coords, 
                     print.progress = FALSE,
                     iter = 9999)
plot(PLSfood)

3: GLM: Regression

Here is a simple example of regression from a linear model:

fit.null <- procD.lm(coords ~ 1, data = Y.gpa,
                     iter = 9999)
fit.alt <- procD.lm(coords ~ log(Csize), data = Y.gpa,
                    turbo = FALSE, iter = 9999)
anova(fit.alt)
## 
## Analysis of Variance, using Residual Randomization
## Permutation procedure: Randomization of null model residuals 
## Number of permutations: 10000 
## Estimation method: Ordinary Least Squares 
## Sums of Squares and Cross-products: Type I 
## Effect sizes (Z) based on F distributions
## 
##            Df      SS       MS     Rsq      F      Z Pr(>F)    
## log(Csize)  1 0.10758 0.107583 0.23511 20.594 5.3289  1e-04 ***
## Residuals  67 0.35001 0.005224 0.76489                         
## Total      68 0.45759                                          
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Call: procD.lm(f1 = coords ~ log(Csize), iter = 9999, turbo = FALSE,  
##     data = Y.gpa)
plot(fit.alt, type = "regression", 
     reg.type = "RegScore", 
     predictor = Y.gpa$Csize)

4: Allometry

Here is a simple example of examining allometry:

data(pupfish)
plotAllSpecimens(pupfish$coords)  #NOTE: already GPA-aligned

  #Y.gpa <- gpagen(pupfish$coords, print.progress = FALSE)    #GPA-alignment  
pupfish$logSize <- log(pupfish$CS)
pupfish$Group <- interaction(pupfish$Pop, pupfish$Sex)

fit <- procD.lm(coords ~ logSize, 
                data = pupfish, 
                print.progress = FALSE) 
anova(fit)
## 
## Analysis of Variance, using Residual Randomization
## Permutation procedure: Randomization of null model residuals 
## Number of permutations: 1000 
## Estimation method: Ordinary Least Squares 
## Sums of Squares and Cross-products: Type I 
## Effect sizes (Z) based on F distributions
## 
##           Df       SS        MS     Rsq      F      Z Pr(>F)    
## logSize    1 0.014019 0.0140193 0.24886 17.229 4.3462  0.001 ***
## Residuals 52 0.042314 0.0008137 0.75114                         
## Total     53 0.056333                                           
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Call: procD.lm(f1 = coords ~ logSize, data = pupfish, print.progress = FALSE)
plot(fit, type = "regression", 
     reg.type = "RegScore", 
     predictor = pupfish$logSize, 
     pch = 19)

  #NOTE: Try also: reg.type = "PredLine"

Comparing Allometric Trajectories

fit.common <- procD.lm(coords ~ logSize + Group, 
                           data = pupfish, print.progress = FALSE) 
fit.unique <- procD.lm(coords ~ logSize * Group, 
                           data = pupfish, print.progress = FALSE)  
anova(fit.unique)
## 
## Analysis of Variance, using Residual Randomization
## Permutation procedure: Randomization of null model residuals 
## Number of permutations: 1000 
## Estimation method: Ordinary Least Squares 
## Sums of Squares and Cross-products: Type I 
## Effect sizes (Z) based on F distributions
## 
##               Df       SS        MS     Rsq       F      Z Pr(>F)    
## logSize        1 0.014019 0.0140193 0.24886 29.2078 5.0041  0.001 ***
## Group          3 0.018230 0.0060766 0.32361 12.6601 6.4891  0.001 ***
## logSize:Group  3 0.002004 0.0006682 0.03558  1.3921 1.1451  0.136    
## Residuals     46 0.022079 0.0004800 0.39194                          
## Total         53 0.056333                                            
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Call: procD.lm(f1 = coords ~ logSize * Group, data = pupfish, print.progress = FALSE)
par(mfcol = c(1, 2))

plot(fit.common, type = "regression", 
     predictor = pupfish$logSize, 
     reg.type = "PredLine", 
     pch=19, 
     col = pupfish$Group)

legend("topleft", 
       legend = unique(pupfish$Group), 
       pch = 21, 
       pt.bg = unique(pupfish$Group))

mtext("Common Slopes")

plot(fit.unique, 
     type = "regression", 
     predictor = pupfish$logSize, 
     reg.type = "PredLine", 
     pch=19, 
     col = pupfish$Group)

legend("topleft", 
       legend = unique(pupfish$Group), 
       pch = 21, 
       pt.bg = unique(pupfish$Group))

mtext("Unique Slopes")

par(mfcol = c(1, 1))

Conclusion: Not much going on for this example (illustration purposes only).

5: Things to Explore on Your Own

  1. Remember Day 1 (read in your data, GPA, PCA, TPS)
  2. Perform GPA + sliders
  3. 3D data: Perform GPA with points, curves, surfaces, or some combination
  4. Perform PLS: visualize shapes along PLS
  5. Perform regression: visualize shapes along regression
  6. Generate shapes for small and large specimens in an allometry analysis
  7. Explore function options and output (there are many!)